fix: what an audit of the documented behaviour found
An independent check of every behaviour AGENTS.md was to describe: - `--units ,` and `--only ,` skipped their empty items and so had no filter left: a typo started a run of every unit. They are usage errors now (exit 3). - Two fixes the plan lists were missing: a dry run now clears the prompts a dry run before it left in the dir they share (the report counted them), and `config` reports an absolute functional.mcp.command that is no program here - /usr/bin/npx inside the Flatpak, whose /usr is the Sdk's. - A patch that is not UTF-8 stops `run` at preflight (exit 3), as the plan has it; it exited 1. - An exception no command caught aborted the process (134), e.g. a home that holds no lenses: it ends with its message and exit 1. An error escaping `run` or `freeze` now also clears the signal handler's run and sweeps what is left below the subreaper. - `config -h` printed "unrecognized arguments" (exit 3): it prints the usage, exit 0. - An API seat's .claude.json is linked into place, so a second writer never replaces the first's file and what claude wrote to it since. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
53b7d6de31
commit
32a0de1a07
7 changed files with 114 additions and 11 deletions
|
|
@ -347,6 +347,13 @@ inventory unit, against a frozen commit range.)";
|
|||
if (std::string id = Dyn::Strip(part); !id.empty()) a.units->insert(std::move(id));
|
||||
}
|
||||
}
|
||||
// Empty items are skipped, so a typo such as `--units ,` must not
|
||||
// leave no filter at all: that is a full run.
|
||||
auto namesNothing = [](const std::optional<std::string>& list) {
|
||||
return list && !list->empty() && std::ranges::all_of(Dyn::Split(*list, ","), [](const std::string& part) { return Dyn::Strip(part).empty(); });
|
||||
};
|
||||
if (namesNothing(a.only)) return UsageError(UsageLine(Prog, specs), Prog, std::format("argument --only: names no lens file ({})", Dyn::Repr(*a.only)));
|
||||
if (namesNothing(parsed.Value("units"))) return UsageError(UsageLine(Prog, specs), Prog, std::format("argument --units: names no unit id ({})", Dyn::Repr(*parsed.Value("units"))));
|
||||
a.warm = parsed.Flag("warm");
|
||||
if (const std::optional<std::string> n = parsed.Value("concurrency")) a.concurrency = *Dyn::ParseInt(*n);
|
||||
a.effort = parsed.Value("effort").value_or("");
|
||||
|
|
@ -436,9 +443,12 @@ inventory unit, against a frozen commit range.)";
|
|||
// `%G?` starts gpg, which can leave a daemon behind: as a subreaper
|
||||
// this process inherits it, and takes it down on the way out.
|
||||
Process::BecomeSubreaper();
|
||||
const std::int32_t code = Freeze::Main(arguments, *config);
|
||||
Process::KillDescendants();
|
||||
return code;
|
||||
struct Sweep {
|
||||
~Sweep() {
|
||||
Process::KillDescendants();
|
||||
}
|
||||
} const sweep;
|
||||
return Freeze::Main(arguments, *config);
|
||||
}
|
||||
|
||||
// ---- seats: the report, the ledger and the board beside it ------------------
|
||||
|
|
@ -929,7 +939,12 @@ inventory unit, against a frozen commit range.)";
|
|||
if (command == "totp") return Totp::Main(after);
|
||||
if (command == "inventory" && !configPath) return Inventory::Main(after);
|
||||
if (command == "config") {
|
||||
if (!after.empty()) return UsageError(Usage, "crafter-review", std::format("unrecognized arguments: {}", after.front()));
|
||||
const Parsed parsed = ParseOptions(after, {});
|
||||
if (parsed.help) {
|
||||
std::print("{}", Help("crafter-review config", "print the merged consumer config and its problems", {}));
|
||||
return 0;
|
||||
}
|
||||
if (!parsed.error.empty()) return UsageError(Usage, "crafter-review", parsed.error);
|
||||
return Config::Main(fs::current_path(), configPath ? fs::path(*configPath) : fs::path());
|
||||
}
|
||||
if (command == "freeze") return FreezeCommand(after, configPath);
|
||||
|
|
@ -944,6 +959,10 @@ inventory unit, against a frozen commit range.)";
|
|||
// An error no command catches: its message, exit 1.
|
||||
std::println(std::cerr, "crafter-review: {}: {}", error.Kind(), error.what());
|
||||
return 1;
|
||||
} catch (const std::exception& error) {
|
||||
// Anything else that escapes a command, as a traceback would.
|
||||
std::println(std::cerr, "crafter-review: {}", error.what());
|
||||
return 1;
|
||||
}
|
||||
return UsageError(Usage, "crafter-review", std::format("argument cmd: invalid choice: '{}'", command));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue