CLI overhaul #239

Open
opened 2026-10-17 09:40:19 +00:00 by kayg · 85 comments
Owner

Owner, 2026-10-17: "The CLI needs to be much improved!" (after infraternal status printed "Unknown / could not be read" on a running server and host).

Scope of this issue: a read-only audit of every command and a redesign proposal (docs/design/cli-proposal.md on branch cli-proposal), then the build slices it lists. The status truth fix itself is on branch cli-status-truth and is not duplicated here.

Relevant decisions: D27, D132, D146, D199, D201, D202, D237, D239, D260, D288, D297.

Started: branch cli-proposal, base d9f295dd2 (origin/dev).

Owner, 2026-10-17: "The CLI needs to be much improved!" (after `infraternal status` printed "Unknown / could not be read" on a running server and host). Scope of this issue: a read-only audit of every command and a redesign proposal (`docs/design/cli-proposal.md` on branch `cli-proposal`), then the build slices it lists. The status truth fix itself is on branch `cli-status-truth` and is not duplicated here. Relevant decisions: D27, D132, D146, D199, D201, D202, D237, D239, D260, D288, D297. Started: branch `cli-proposal`, base `d9f295dd2` (origin/dev).
1.3 KiB
8.7 KiB
Author
Owner

Finished audit + proposal: branch cli-proposal, head 713bdbac0 (base d9f295dd2). Document: docs/design/cli-proposal.md.

How it was audited (read-only): built infraternal (debug) from origin/dev, walked every visible command with --help, -h, a bad flag, a bad flag with --json, and no args plus --json for read-only commands. Commands that change state were never run. On production (monitor01, release build) I ran status, mesh status, mesh peers (each with --json), skill, --help, and timed each one 10×.

Top findings (exact output is in the document, §2)

  • status on monitor01 (unit infraternal-server is active): "State Stopped / No infraternal server service is running on this node / Next: Run infraternal server init", exit 0. It also calls plugins "components". (The fix is on cli-status-truth.)
  • Bare infraternal prints "Infraternal cli / Failed / The requested command is not registered in this build", exit 2. Every bare group does the same.
  • 39 of 54 visible commands are stubs ("not available yet", 25 of them say "use the server UI"), exit 2 like a typo. All of them appear in skill for AI tools.
  • Three human styles and three JSON shapes. mesh status/peers --json prints raw objects, but their skill promises the schema_version envelope. Errors use {action,message,next,state}.
  • Errors combine causes: "refused or the local infraternal agent is unavailable … Use the infraternal agent's uid and runtime directory". JSON usage errors don't name the argument.
  • mesh peers: node numbers instead of names, raw bytes, 130 columns, and "Next: Send traffic to establish an unproven direct path" even when the path is Direct.
  • Help text: "mesh plugin actions.", "Remove host / When to use: Remove host", six empty group descriptions, internal flags (--input-file … NodeIdInput, --state, --finish).
  • remove-host needs a UUID, and no command lists hosts. There are duplicates (server channel / release channel set, remove-host / mesh node delete). Nothing exists for machines, open, sessions, logs, update or whoami. The D239 alias infra is not installed.
  • Speed is fine. Release build: help 6 ms, mesh 5–7 ms, status 36 ms (it starts systemctl).

Proposal: noun-first tree (machines, open, sessions, mesh, logs, update, access, component up|down|status). One output kernel. One envelope and fixed exit codes. ≤50 ms for local reads. 16 slices; slices 1–6 (kernel, front door, hide stubs, status in the kernel, mesh output, diagnosing errors) need no owner answers.

Owner questions (§7): 1 machines or hosts · 2 how the CLI acts as you (node link vs sign-in) · 3 what open does in a terminal · 4 what bare infraternal shows · 5 hide or show stubs · 6 access-rule words · 7 exit codes and the JSON promise.

Gate: docs-only change. scripts/verify fast was not run, because the build host was at load ~30–40 and the coordinator throttled new cargo work. Nothing in this change compiles.

Finished audit + proposal: branch `cli-proposal`, head `713bdbac0` (base `d9f295dd2`). Document: `docs/design/cli-proposal.md`. How it was audited (read-only): built `infraternal` (debug) from origin/dev, walked every visible command with `--help`, `-h`, a bad flag, a bad flag with `--json`, and no args plus `--json` for read-only commands. Commands that change state were never run. On production (monitor01, release build) I ran `status`, `mesh status`, `mesh peers` (each with `--json`), `skill`, `--help`, and timed each one 10×. **Top findings (exact output is in the document, §2)** - `status` on monitor01 (unit `infraternal-server` is `active`): "State Stopped / No infraternal server service is running on this node / Next: Run `infraternal server init`", exit 0. It also calls plugins "components". (The fix is on `cli-status-truth`.) - Bare `infraternal` prints "Infraternal cli / Failed / The requested command is not registered in this build", exit 2. Every bare group does the same. - **39 of 54 visible commands are stubs** ("not available yet", 25 of them say "use the server UI"), exit 2 like a typo. All of them appear in `skill` for AI tools. - Three human styles and three JSON shapes. `mesh status/peers --json` prints raw objects, but their skill promises the `schema_version` envelope. Errors use `{action,message,next,state}`. - Errors combine causes: "refused or the local infraternal agent is unavailable … Use the infraternal agent's uid and runtime directory". JSON usage errors don't name the argument. - `mesh peers`: node numbers instead of names, raw bytes, 130 columns, and "Next: Send traffic to establish an unproven direct path" even when the path is Direct. - Help text: "mesh plugin actions.", "Remove host / When to use: Remove host", six empty group descriptions, internal flags (`--input-file … NodeIdInput`, `--state`, `--finish`). - `remove-host` needs a UUID, and no command lists hosts. There are duplicates (`server channel` / `release channel set`, `remove-host` / `mesh node delete`). Nothing exists for machines, open, sessions, logs, update or whoami. The D239 alias `infra` is not installed. - Speed is fine. Release build: help 6 ms, mesh 5–7 ms, `status` 36 ms (it starts `systemctl`). **Proposal:** noun-first tree (`machines`, `open`, `sessions`, `mesh`, `logs`, `update`, `access`, component `up|down|status`). One output kernel. One envelope and fixed exit codes. ≤50 ms for local reads. 16 slices; slices 1–6 (kernel, front door, hide stubs, status in the kernel, mesh output, diagnosing errors) need no owner answers. **Owner questions (§7):** 1 machines or hosts · 2 how the CLI acts as you (node link vs sign-in) · 3 what `open` does in a terminal · 4 what bare `infraternal` shows · 5 hide or show stubs · 6 access-rule words · 7 exit codes and the JSON promise. Gate: docs-only change. `scripts/verify fast` was not run, because the build host was at load ~30–40 and the coordinator throttled new cargo work. Nothing in this change compiles.
Author
Owner

Job cli-overhaul-1 started. Branch cli-overhaul-1, base origin/cli-status-truth 54231576d. Scope: proposal build steps 1-6 (one output style + one --json envelope, bare = overview, hide unbuilt commands, D303 exit codes, mesh peers, plain help). Baseline timings and before-output are captured from a debug build of the base.

Job cli-overhaul-1 started. Branch `cli-overhaul-1`, base `origin/cli-status-truth` 54231576d. Scope: proposal build steps 1-6 (one output style + one --json envelope, bare = overview, hide unbuilt commands, D303 exit codes, mesh peers, plain help). Baseline timings and before-output are captured from a debug build of the base.
Author
Owner

Job cli-overhaul-1 finished. Branch cli-overhaul-1, head 8683fe77a (base 54231576d). Pushed.

Commits (each cites #239): 9f58aae5e envelope + one style; 2092230af bare = overview, groups list commands; 6bcb2ab92 hide unbuilt commands; 1bd07c362 exit codes D303 (status exits 5); a255008e1 mesh peers; a42334d7b plain help; 08dc796c0 docs; 8683fe77a lint fixes.

scripts/verify fast, final table (verbatim):

+---------------------------+--------------+
| Rust gate | Result |
+---------------------------+--------------+
| fmt | PASS |
| VT native fmt | PASS |
| CLI plugin compile-out | PASS |
| clippy | PASS |
| test | PASS |
| cargo-deny | PASS |
| static builds | FAIL (1) |
+---------------------------+--------------+

Static builds fail only on the size ceiling: x86_64 21361680 bytes, cap 21317296, delta +44384; aarch64 19557816, cap 19500376, delta +57440 (the caps equal the base). D243 allows 16 KiB, so this is about 28 KB (x86_64) over. Tried: opt-level "s" for the infraternal package (+2.9 MB, rejected), #[inline(never)] on the new cold code (worse: +47.8 KB, dropped). Not tried: stop compiling the hidden placeholder declarations (about 40 actions: relay/backup/ssh/host-facts/release plugins, agent up/down/status, up, server features, mesh hosted stubs) into default builds, for example behind a placeholders feature. That is the likely real saving, but it changes D16 "one source" tests, so it needs the owner. Caps not raised.

Findings:

  • mesh peers cannot show machine names: the agent's mesh configuration (dataplane::Peer, deny_unknown_fields) carries no names, only the server knows them. Peers show by mesh address; the code already prefers a name field when the record has one. Adding names is a change to the pushed mesh configuration (wire format) and needs a decision.
  • D299 says the join hint is infraternal up; up is an unbuilt placeholder and now hidden, so the hint says infraternal agent join <server-url>.
  • status "should run" means installed server/agent units. A mesh turned off on purpose is not counted (no desired-state record).
  • Left alone: the JSON schema in generated skills still says additional_properties (proposal P4/slice 14); server subcommands still accept all server options (now under a "Server options" heading).
  • Timings (p50, 40 runs, load 4): release static: --help 4.5 ms, status 19.1 ms, bare 20.1 ms, skill 5.5 ms, mesh peers (agent down) 4.2 ms, mesh --json 3.3 ms. Debug before/after: --help 10.6/10.6, status 22.5/25.3, skill 11.1/9.7, mesh peers 7.8/7.7. status stays at ~20 ms because it spawns systemctl.
Job cli-overhaul-1 finished. Branch `cli-overhaul-1`, head 8683fe77a (base 54231576d). Pushed. Commits (each cites #239): 9f58aae5e envelope + one style; 2092230af bare = overview, groups list commands; 6bcb2ab92 hide unbuilt commands; 1bd07c362 exit codes D303 (status exits 5); a255008e1 mesh peers; a42334d7b plain help; 08dc796c0 docs; 8683fe77a lint fixes. scripts/verify fast, final table (verbatim): +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | test | PASS | | cargo-deny | PASS | | static builds | FAIL (1) | +---------------------------+--------------+ Static builds fail only on the size ceiling: x86_64 21361680 bytes, cap 21317296, delta +44384; aarch64 19557816, cap 19500376, delta +57440 (the caps equal the base). D243 allows 16 KiB, so this is about 28 KB (x86_64) over. Tried: opt-level "s" for the infraternal package (+2.9 MB, rejected), #[inline(never)] on the new cold code (worse: +47.8 KB, dropped). Not tried: stop compiling the hidden placeholder declarations (about 40 actions: relay/backup/ssh/host-facts/release plugins, agent up/down/status, up, server features, mesh hosted stubs) into default builds, for example behind a `placeholders` feature. That is the likely real saving, but it changes D16 "one source" tests, so it needs the owner. Caps not raised. Findings: - mesh peers cannot show machine names: the agent's mesh configuration (dataplane::Peer, deny_unknown_fields) carries no names, only the server knows them. Peers show by mesh address; the code already prefers a `name` field when the record has one. Adding names is a change to the pushed mesh configuration (wire format) and needs a decision. - D299 says the join hint is `infraternal up`; `up` is an unbuilt placeholder and now hidden, so the hint says `infraternal agent join <server-url>`. - status "should run" means installed server/agent units. A mesh turned off on purpose is not counted (no desired-state record). - Left alone: the JSON schema in generated skills still says `additional_properties` (proposal P4/slice 14); server subcommands still accept all server options (now under a "Server options" heading). - Timings (p50, 40 runs, load 4): release static: --help 4.5 ms, status 19.1 ms, bare 20.1 ms, skill 5.5 ms, mesh peers (agent down) 4.2 ms, mesh --json 3.3 ms. Debug before/after: --help 10.6/10.6, status 22.5/25.3, skill 11.1/9.7, mesh peers 7.8/7.7. status stays at ~20 ms because it spawns systemctl.
Author
Owner

Placeholder compile-out done. Head a1d48bda9 pushed to cli-overhaul-1. Static sizes vs caps (= base): x86_64 21327696 (+10400, within 16 KiB); aarch64 19527720 (+27344, 11 KB over). Caps not ratcheted (aarch64 over). Before the gate: +44384 / +57440. Remaining test-gate failures are 3 infraternal-server socket timing tests that fail under load in the full run and pass alone (not touched by this branch).

Placeholder compile-out done. Head a1d48bda9 pushed to cli-overhaul-1. Static sizes vs caps (= base): x86_64 21327696 (+10400, within 16 KiB); aarch64 19527720 (+27344, 11 KB over). Caps not ratcheted (aarch64 over). Before the gate: +44384 / +57440. Remaining test-gate failures are 3 infraternal-server socket timing tests that fail under load in the full run and pass alone (not touched by this branch).
Author
Owner

Break-it review of origin/cli-overhaul-1 @ 884f5f624 (base cli-status-truth). Tests: branch review-cli-overhaul-1 @ 911a3a8dd, crates/infraternal/tests/cli_review.rs, 16 tests, all fail on the reviewed head for the stated reason. Nothing was fixed.

What held up (no finding): all 8 cli_envelope tests and the placeholders-feature bin tests (D16) pass; hidden placeholders are absent from default help/skill; no argument value is echoed in any JSON error I tried (agent join / remove-host with a secret URL, bad option values, odd positional); status exits 5 for a unit that is installed and inactive; NO_COLOR=1 and pipes give no colour; release-build speed (median of 10, load ~5): status 16-18 ms, everything else 3-6 ms, all well under 50 ms.

P1 (0)

P2 findings (7)

  1. Ctrl-C emits nothing. --json mesh status against a socket that never answers: SIGINT kills the process, stdout empty, no envelope. Exit::Interrupted / error code interrupted exist but are never used. D303 fixes 130, and the contract says every result is an envelope. Test: ctrl_c_in_json_mode_ends_with_an_interrupted_envelope_and_exit_130.
  2. agent join --json (and agent run) print TWO envelopes on stdout: a progress {"ok":true,"state":"running"...} and then the final one. A reader taking the first envelope sees success for a command that exits 1. Test: a_failing_command_in_json_mode_prints_exactly_one_envelope.
  3. status exit 5 on UNKNOWN. NodeStatus::down() counts Activity::Unknown, so an installed, healthy service whose manager cannot be asked (no XDG_RUNTIME_DIR/session bus: cron, sudo -u, ssh without linger; or no systemctl) gives exit 5, error.code: component_down, "is not answering". D303: 5 only for installed-but-down. infraternal status || alert pages falsely. Test: status_is_not_down_when_the_service_manager_cannot_be_asked.
  4. TERM=dumb gets ANSI colour and the marks (● ○ ✕). Our renderer checks only is_terminal and NO_COLOR; the parser's own errors correctly honour TERM=dumb. NO_COLOR="" (empty) turns our colour off but not the parser's (spec: only non-empty counts). Tests: a_dumb_terminal_gets_neither_colour_nor_marks, an_empty_no_color_is_ignored.
  5. Missing XDG_RUNTIME_DIR: mesh status/peers/up/down say "It sent a reply this command does not understand", exit 1. Cause is that the CLI cannot find the infraternal agent (any io error but four kinds falls into the catch-all in component_cli::refuse). Should be exit 5 with the true cause. Test: a_missing_runtime_directory_is_not_called_a_bad_reply.
  6. Exit codes outside D303 classes: skill <unknown> exits 1 (should be 4); remove-host --server S not-a-uuid exits 1 "Invalid host identifier" (should be 2). Also agent-join failure class is chosen by substring match on the public error text ("DNS", "connection failed", "TLS verification" in run_remote_agent): a reworded message silently changes the exit code. Tests: an_unknown_skill_is_not_found_exit_4, a_malformed_host_id_is_a_usage_error_exit_2.
  7. server init --dry-run text output flattens the unit file into one wrapped paragraph ("After=network.target [Service] Type=simple ExecStart=..."): the one thing a dry run exists to show is unreadable. JSON keeps the newlines. Test: a_dry_run_plan_keeps_its_line_breaks.

P3 findings (6)
8. Vocabulary: "No agent socket was found..." and "The agent answers only the account that runs it." (component_cli.rs) use "agent" alone. Test: user_facing_text_never_says_agent_alone.
9. Text-mode usage errors echo the typed value (clap: unrecognized subcommand 'https://user:SECRET@...'). The JSON path was built to avoid this (usage.rs); the text path logs it to shells and CI. Test: a_usage_error_in_text_mode_does_not_echo_the_odd_input.
10. --json --help and --json -V print plain text, not an envelope; D299 "every command has --json" is kept only for runs, not help. Judgement call; decide and document. Test: json_help_and_version_are_envelopes_too.
11. Help lies: server setup-token --help and server channel --help list a "Server options" block (--listen, --tls-cert, --remote-listen ...) that those commands accept and silently ignore. Test: a_subcommand_does_not_advertise_options_it_ignores.
12. Root --help is 82 columns wide (remove-host line); help is wider than the 80-column default the renderer promises. Test: root_help_fits_80_columns. Also "infraternal server release has 1 commands." (test: a_group_with_one_command_says_so_in_the_singular), and bare infraternal agent --json is state unavailable with error code usage and exit 2, unlike mesh/server groups that list their commands.
13. Repo hygiene: commit 8027e82f7 tracks four scripts/pycache/*.cpython-314.pyc files; running scripts/verify modifies them, so every gate run dirties the tree. Test: no_compiled_python_is_tracked. (Delete and gitignore.)

Gate: scripts/verify fast on 884f5f624 (clean tree, own target dir, load 10-17 during run):
+---------------------------+--------------+
| Rust gate | Result |
+---------------------------+--------------+
| fmt | PASS |
| VT native fmt | PASS |
| CLI plugin compile-out | PASS |
| clippy | PASS |
| test | FAIL (101) |
| cargo-deny | PASS |
| static builds | PASS |
+---------------------------+--------------+
The only failures were 3 timing tests in infraternal-server (restart_open_liveness_review::responsive_socket_survives_a_held_terminal_open_with_an_existing_attachment, review_input_credit::review_full_input_writer_preserves_browser_control_progress, review_liveness::review_mesh_watch_reports_liveness_expiry_without_another_edit). LOAD FLAKE: re-run alone at load 4, 3 passed. Unrelated to the CLI. Size caps passed (x86_64 21327696, aarch64 19527720 exact-cap checks PASS). The infraternal crate's own tests (cli_envelope 8/8, bin tests default, --no-default-features and --features placeholders) all passed.

Verdict: HOLD. 0 P0/P1, 7 P2, 6 P3. Items 1-3 and 5-6 are contract breaks of D303/D299 and are cheap to fix; 4, 7 and 13 are small too.

Break-it review of origin/cli-overhaul-1 @ 884f5f624 (base cli-status-truth). Tests: branch review-cli-overhaul-1 @ 911a3a8dd, crates/infraternal/tests/cli_review.rs, 16 tests, all fail on the reviewed head for the stated reason. Nothing was fixed. What held up (no finding): all 8 cli_envelope tests and the placeholders-feature bin tests (D16) pass; hidden placeholders are absent from default help/skill; no argument value is echoed in any JSON error I tried (agent join / remove-host with a secret URL, bad option values, odd positional); status exits 5 for a unit that is installed and inactive; NO_COLOR=1 and pipes give no colour; release-build speed (median of 10, load ~5): status 16-18 ms, everything else 3-6 ms, all well under 50 ms. P1 (0) P2 findings (7) 1. Ctrl-C emits nothing. `--json mesh status` against a socket that never answers: SIGINT kills the process, stdout empty, no envelope. `Exit::Interrupted` / error code `interrupted` exist but are never used. D303 fixes 130, and the contract says every result is an envelope. Test: ctrl_c_in_json_mode_ends_with_an_interrupted_envelope_and_exit_130. 2. `agent join --json` (and `agent run`) print TWO envelopes on stdout: a progress `{"ok":true,"state":"running"...}` and then the final one. A reader taking the first envelope sees success for a command that exits 1. Test: a_failing_command_in_json_mode_prints_exactly_one_envelope. 3. `status` exit 5 on UNKNOWN. NodeStatus::down() counts Activity::Unknown, so an installed, healthy service whose manager cannot be asked (no XDG_RUNTIME_DIR/session bus: cron, sudo -u, ssh without linger; or no systemctl) gives exit 5, `error.code: component_down`, "is not answering". D303: 5 only for installed-but-down. `infraternal status || alert` pages falsely. Test: status_is_not_down_when_the_service_manager_cannot_be_asked. 4. TERM=dumb gets ANSI colour and the marks (● ○ ✕). Our renderer checks only is_terminal and NO_COLOR; the parser's own errors correctly honour TERM=dumb. NO_COLOR="" (empty) turns our colour off but not the parser's (spec: only non-empty counts). Tests: a_dumb_terminal_gets_neither_colour_nor_marks, an_empty_no_color_is_ignored. 5. Missing XDG_RUNTIME_DIR: `mesh status/peers/up/down` say "It sent a reply this command does not understand", exit 1. Cause is that the CLI cannot find the infraternal agent (any io error but four kinds falls into the catch-all in component_cli::refuse). Should be exit 5 with the true cause. Test: a_missing_runtime_directory_is_not_called_a_bad_reply. 6. Exit codes outside D303 classes: `skill <unknown>` exits 1 (should be 4); `remove-host --server S not-a-uuid` exits 1 "Invalid host identifier" (should be 2). Also agent-join failure class is chosen by substring match on the public error text ("DNS", "connection failed", "TLS verification" in run_remote_agent): a reworded message silently changes the exit code. Tests: an_unknown_skill_is_not_found_exit_4, a_malformed_host_id_is_a_usage_error_exit_2. 7. `server init --dry-run` text output flattens the unit file into one wrapped paragraph ("After=network.target [Service] Type=simple ExecStart=..."): the one thing a dry run exists to show is unreadable. JSON keeps the newlines. Test: a_dry_run_plan_keeps_its_line_breaks. P3 findings (6) 8. Vocabulary: "No agent socket was found..." and "The agent answers only the account that runs it." (component_cli.rs) use "agent" alone. Test: user_facing_text_never_says_agent_alone. 9. Text-mode usage errors echo the typed value (clap: `unrecognized subcommand 'https://user:SECRET@...'`). The JSON path was built to avoid this (usage.rs); the text path logs it to shells and CI. Test: a_usage_error_in_text_mode_does_not_echo_the_odd_input. 10. `--json --help` and `--json -V` print plain text, not an envelope; D299 "every command has --json" is kept only for runs, not help. Judgement call; decide and document. Test: json_help_and_version_are_envelopes_too. 11. Help lies: `server setup-token --help` and `server channel --help` list a "Server options" block (--listen, --tls-cert, --remote-listen ...) that those commands accept and silently ignore. Test: a_subcommand_does_not_advertise_options_it_ignores. 12. Root `--help` is 82 columns wide (remove-host line); help is wider than the 80-column default the renderer promises. Test: root_help_fits_80_columns. Also "infraternal server release has 1 commands." (test: a_group_with_one_command_says_so_in_the_singular), and bare `infraternal agent --json` is state `unavailable` with error code `usage` and exit 2, unlike `mesh`/`server` groups that list their commands. 13. Repo hygiene: commit 8027e82f7 tracks four scripts/__pycache__/*.cpython-314.pyc files; running scripts/verify modifies them, so every gate run dirties the tree. Test: no_compiled_python_is_tracked. (Delete and gitignore.) Gate: `scripts/verify fast` on 884f5f624 (clean tree, own target dir, load 10-17 during run): +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | test | FAIL (101) | | cargo-deny | PASS | | static builds | PASS | +---------------------------+--------------+ The only failures were 3 timing tests in infraternal-server (restart_open_liveness_review::responsive_socket_survives_a_held_terminal_open_with_an_existing_attachment, review_input_credit::review_full_input_writer_preserves_browser_control_progress, review_liveness::review_mesh_watch_reports_liveness_expiry_without_another_edit). LOAD FLAKE: re-run alone at load 4, 3 passed. Unrelated to the CLI. Size caps passed (x86_64 21327696, aarch64 19527720 exact-cap checks PASS). The infraternal crate's own tests (cli_envelope 8/8, bin tests default, --no-default-features and --features placeholders) all passed. Verdict: HOLD. 0 P0/P1, 7 P2, 6 P3. Items 1-3 and 5-6 are contract breaks of D303/D299 and are cheap to fix; 4, 7 and 13 are small too.
Author
Owner

cli-overhaul-1 review fixes: head 7366153048, base 884f5f624. All 16 tests in crates/infraternal/tests/cli_review.rs pass. 19 commits (git log 884f5f624..HEAD).

scripts/verify fast (final table, verbatim):

+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| test                      | PASS         |
| cargo-deny                | PASS         |
| static builds             | FAIL (1)     |
+---------------------------+--------------+

Static size: x86_64 21348272 vs cap 21327696 (+20576); aarch64 19547472 vs cap 19527720 (+19752). Caps not raised; the owner/orchestrator decides the ratchet. The cargo registry path accounts for a few KB only.

cli-overhaul-1 review fixes: head 73661530486d1133fbed18b9a25b141183d80e76, base 884f5f624. All 16 tests in crates/infraternal/tests/cli_review.rs pass. 19 commits (git log 884f5f624..HEAD). scripts/verify fast (final table, verbatim): ``` +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | test | PASS | | cargo-deny | PASS | | static builds | FAIL (1) | +---------------------------+--------------+ ``` Static size: x86_64 21348272 vs cap 21327696 (+20576); aarch64 19547472 vs cap 19527720 (+19752). Caps not raised; the owner/orchestrator decides the ratchet. The cargo registry path accounts for a few KB only.
Author
Owner

Round-2 delta break-it review started (Claude subagent).

  • Branch: review-cli-overhaul-1-r2 from 73661530486d1133fbed18b9a25b141183d80e76 (origin/cli-overhaul-1)
  • Delta under review: 884f5f624..73661530
  • Scope: round-1 P2 fixes (Ctrl-C envelope, double envelope, status unknown vs down, colour, missing runtime dir, exit codes, dry-run), SIGINT handler in infraternal-shim, --json one-envelope contract on every path, D303 exit codes, no echoed values, rust.sh gate change, size breakdown (+20,576 B x86).
Round-2 delta break-it review started (Claude subagent). - Branch: `review-cli-overhaul-1-r2` from `73661530486d1133fbed18b9a25b141183d80e76` (origin/cli-overhaul-1) - Delta under review: `884f5f624..73661530` - Scope: round-1 P2 fixes (Ctrl-C envelope, double envelope, status unknown vs down, colour, missing runtime dir, exit codes, dry-run), SIGINT handler in infraternal-shim, `--json` one-envelope contract on every path, D303 exit codes, no echoed values, rust.sh gate change, size breakdown (+20,576 B x86).
Author
Owner

Round-2 delta break-it review of cli-overhaul-1 @ 73661530: MERGE (no P0/P1), P2 to follow up

Review branch review-cli-overhaul-1-r2 @ decb6163d0299bf4ee552389d13025f0870344da. New file crates/infraternal/tests/cli_review_r2.rs: 7 tests that fail on head, plus 2 regression tests that pass.

Counts: P0 0 · P1 0 · P2 2 · P3 6

The round-1 fixes check out

All 16 round-1 tests (cli_review.rs) pass on head. I also confirmed the parts round 1 only checked by the first line of output: --json -V, --version, -h, status -h, mesh --help each print exactly one envelope and exit 0. Usage errors (--bogus, an unknown command, missing args, a missing option value, agent join with no URL) each print one envelope with exit 2 and code: usage. A closed stdout (EPIPE) exits quietly with the right code.

SIGINT handler (unsafe boundary): the handler only does OnceLock::get (an atomic acquire), write(2) and _exit(2), so it is async-signal-safe. It is not installed on the paths that daemons use: the embedded agent --fd early path, __shim (the infraternal agent never passes --json to it), and units, which run without --json. Children are safe: Command + reset_child_signals and exec reset the handler. On a closed pipe it still exits 130. Daemons had no SIGINT handling before, so their Ctrl-C behaviour does not change.

Findings

Sev Finding Test
P2 mesh peers --json follows next_cursor itself and prints one envelope per page (component_cli::execute loop). The first envelope says ok:true before the listing is complete, and a failure on page 2 adds an error envelope after it. It only shows up past about 150 peers (pages are capped by bytes), but it breaks the one-envelope rule of D299. a_paged_listing_is_still_one_envelope
P2 Ctrl-C while the final envelope is being written: the handler writes its own envelope in the middle of the main thread's. With a slow reader you get half the real envelope with the interrupted one glued on, i.e. one line that is not JSON (4,293 bytes in the test, deterministic with a 4 KiB pipe). The same race gives two envelopes if Ctrl-C lands after the final write but before exit. Fix: set an atomic "final output started" flag in write_output before the stdout write; when the flag is set, the handler _exit(130)s without writing. ctrl_c_while_the_result_is_being_written_never_leaves_a_broken_line
P3 _exit(130) tells the calling shell that the command handled Ctrl-C itself, so for h in …; do infraternal --json …; done carries on to the next item. Restoring SIG_DFL and re-raising (both async-signal-safe) still gives the shell $?=130 and stops the script. The trade-off: a non-shell caller sees "killed by signal 2" instead of exit 130. Owner call against D303. ctrl_c_in_a_script_loop_stops_the_loop
P3 The pty.rs doc comment "A later handler installed by a runtime replaces this one" is false. The runtime's signal registry chains the handler it finds and runs it first, so any later graceful Ctrl-C path (for example tokio::signal::ctrl_c in server --json) is bypassed by _exit(130). Nothing in the tree depends on this today. a_later_runtime_handler_is_not_bypassed_by_the_interrupt_handler
P3 Typed values are still echoed. skill <words> puts the words verbatim in details (https://user:SECRETTOKEN@…). usage.rs word_like echoes any lowercase word of up to 40 characters, which covers a pasted 40-char hex token, in JSON and in text. an_unknown_skill_does_not_echo_what_was_typed, a_mistyped_word_that_looks_like_a_token_is_not_echoed
P3 The status exit code was fixed, but the headline still uses down(): one active unit plus one that did not answer gives exit 0 with the text "Part of this machine's setup is not running." Use confirmed_down() for the headline and its next steps, and say "not answering" for unknown units. status_text_does_not_call_an_unanswered_unit_not_running
P3 Gate change in scripts/verify.d/rust.sh (rust_check_cli_group): it still proves that the shipping binary has the infraternal agent group with join compiled in, so it is still worth having. But it uses 2>&1 and a substring match, so two envelopes or stderr noise would pass. Capture stdout only, assert exactly one line, parse it as JSON, and assert stderr is empty. The old check covered the agent no---fd refusal path; in shipping builds that path is now unreachable (run_group always returns Some). none (script review)
P3 Minor, mostly pre-existing: there is no panic hook (a panic exits 101 with no envelope). component_cli::run_action returns exit 1 with no envelope when the hosted registry fails. agent --fd N --json (internal) prints no envelope. Text-mode skill <cmd> to a closed pipe exits 1 with "could not be printed", while write_output ignores EPIPE. Server logs still treat an empty NO_COLOR as set and ignore TERM=dumb (runtime.rs:807). none

Exit codes: apart from the items above, the D303 table matches everywhere I looked (Exit::code, skill 4/2, remove-host 2, runtime dir 5, join exit picked by typed Failure). status exits 5 only for Inactive|Failed. No secrets appear in argv or logs in the delta.

Size (x86_64 static, built with the repo recipe, sccache + pinned Zig)

  • head 21,348,272 (bit-identical to the author's figure) vs base 884f5f624 21,327,696: +20,576 B. aarch64 is +19,752 B over its cap.
  • Sections, unstripped: .text +19,392 · .eh_frame +752 · .gcc_except_table +312 · .data.rel.ro +256 · .eh_frame_hdr +232 · .rodata 0.
  • Attribution, from builds of head with one feature removed:
    • Hidden inherited args in sub-help (320c8806c): −11,776 B (57%). LTO now has two copies of clap's Arg::clone (+7,033), plus Vec<Arg> collect (+848) and duplicated Vec clones (+1,452).
    • SIGINT envelope (fc145d367): −2,720 B.
    • Rest, about 6.1 KB: parse_failure/help_result envelopes, typed Failure/Cause errors, report_failure_as, run_group for agent, output::done. The 51 KB dispatch_selected_action being split into outlined functions is net neutral.
  • vs origin/dev (eecf970a5): dev is 21,080,848 (its cap is 21,080,144, +704 from the known registry-path offset), so head is +267,424. That gap does not belong to this branch: the branch is not rebased, and dev's 438 commits include f0a88fe27 (VT archive repackaging), which drops about 300 KB of Zig debug/unwind text that head still carries (debug.SelfInfo.unwindFrameDwarf, Io.Writer.printValue). The branch's own growth over its merge-base cap 21,317,296 is +30,976 (slice 1 +10,400, round 2 +20,576).
  • Cheap trims:
    1. Do not Arg::clone() each inherited global arg into every subcommand. Either declare the server-only options non-global on server (they are then neither shown nor accepted under its subcommands), or add a minimal hidden stub (Arg::new(id).long(..).hide(true)) instead of a full clone. That saves about 11.8 KB, more than half the overage.
    2. The rest is small and spread out; nothing else under 1 KB is worth chasing.

Gate (scripts/verify fast on the review branch)

+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| test                      | FAIL (101)   |
| cargo-deny                | PASS         |
| static builds             | FAIL (1)     |
+---------------------------+--------------+

The test failures are exactly the 7 review tests. The static builds fail on size alone: size: 21348272 bytes; cap: 21327696 bytes; delta: +20576 bytes (x86_64) and +19752 (aarch64). agent group: exit 0, versioned JSON listing of its commands.

## Round-2 delta break-it review of `cli-overhaul-1` @ 73661530: **MERGE** (no P0/P1), P2 to follow up Review branch `review-cli-overhaul-1-r2` @ `decb6163d0299bf4ee552389d13025f0870344da`. New file `crates/infraternal/tests/cli_review_r2.rs`: 7 tests that fail on head, plus 2 regression tests that pass. **Counts:** P0 0 · P1 0 · P2 2 · P3 6 ### The round-1 fixes check out All 16 round-1 tests (`cli_review.rs`) pass on head. I also confirmed the parts round 1 only checked by the first line of output: `--json -V`, `--version`, `-h`, `status -h`, `mesh --help` each print exactly one envelope and exit 0. Usage errors (`--bogus`, an unknown command, missing args, a missing option value, `agent join` with no URL) each print one envelope with exit 2 and `code: usage`. A closed stdout (EPIPE) exits quietly with the right code. SIGINT handler (unsafe boundary): the handler only does `OnceLock::get` (an atomic acquire), `write(2)` and `_exit(2)`, so it is async-signal-safe. It is not installed on the paths that daemons use: the embedded `agent --fd` early path, `__shim` (the infraternal agent never passes `--json` to it), and units, which run without `--json`. Children are safe: `Command` + `reset_child_signals` and exec reset the handler. On a closed pipe it still exits 130. Daemons had no SIGINT handling before, so their Ctrl-C behaviour does not change. ### Findings | Sev | Finding | Test | |---|---|---| | P2 | `mesh peers --json` follows `next_cursor` itself and prints one envelope per page (`component_cli::execute` loop). The first envelope says `ok:true` before the listing is complete, and a failure on page 2 adds an error envelope after it. It only shows up past about 150 peers (pages are capped by bytes), but it breaks the one-envelope rule of D299. | `a_paged_listing_is_still_one_envelope` | | P2 | Ctrl-C while the final envelope is being written: the handler writes its own envelope in the middle of the main thread's. With a slow reader you get half the real envelope with the `interrupted` one glued on, i.e. one line that is not JSON (4,293 bytes in the test, deterministic with a 4 KiB pipe). The same race gives two envelopes if Ctrl-C lands after the final write but before exit. Fix: set an atomic "final output started" flag in `write_output` before the stdout write; when the flag is set, the handler `_exit(130)`s without writing. | `ctrl_c_while_the_result_is_being_written_never_leaves_a_broken_line` | | P3 | `_exit(130)` tells the calling shell that the command handled Ctrl-C itself, so `for h in …; do infraternal --json …; done` carries on to the next item. Restoring `SIG_DFL` and re-raising (both async-signal-safe) still gives the shell `$?`=130 and stops the script. The trade-off: a non-shell caller sees "killed by signal 2" instead of exit 130. Owner call against D303. | `ctrl_c_in_a_script_loop_stops_the_loop` | | P3 | The pty.rs doc comment "A later handler installed by a runtime replaces this one" is false. The runtime's signal registry chains the handler it finds and runs it **first**, so any later graceful Ctrl-C path (for example `tokio::signal::ctrl_c` in `server --json`) is bypassed by `_exit(130)`. Nothing in the tree depends on this today. | `a_later_runtime_handler_is_not_bypassed_by_the_interrupt_handler` | | P3 | Typed values are still echoed. `skill <words>` puts the words verbatim in `details` (`https://user:SECRETTOKEN@…`). `usage.rs` `word_like` echoes any lowercase word of up to 40 characters, which covers a pasted 40-char hex token, in JSON and in text. | `an_unknown_skill_does_not_echo_what_was_typed`, `a_mistyped_word_that_looks_like_a_token_is_not_echoed` | | P3 | The status exit code was fixed, but the headline still uses `down()`: one active unit plus one that did not answer gives exit 0 with the text "Part of this machine's setup is not running." Use `confirmed_down()` for the headline and its next steps, and say "not answering" for unknown units. | `status_text_does_not_call_an_unanswered_unit_not_running` | | P3 | Gate change in `scripts/verify.d/rust.sh` (`rust_check_cli_group`): it still proves that the shipping binary has the infraternal agent group with `join` compiled in, so it is still worth having. But it uses `2>&1` and a substring match, so two envelopes or stderr noise would pass. Capture stdout only, assert exactly one line, parse it as JSON, and assert stderr is empty. The old check covered the `agent` no-`--fd` refusal path; in shipping builds that path is now unreachable (`run_group` always returns `Some`). | none (script review) | | P3 | Minor, mostly pre-existing: there is no panic hook (a panic exits 101 with no envelope). `component_cli::run_action` returns exit 1 with no envelope when the hosted registry fails. `agent --fd N --json` (internal) prints no envelope. Text-mode `skill <cmd>` to a closed pipe exits 1 with "could not be printed", while `write_output` ignores EPIPE. Server logs still treat an empty `NO_COLOR` as set and ignore `TERM=dumb` (`runtime.rs:807`). | none | Exit codes: apart from the items above, the D303 table matches everywhere I looked (`Exit::code`, skill 4/2, remove-host 2, runtime dir 5, join exit picked by typed `Failure`). `status` exits 5 only for `Inactive|Failed`. No secrets appear in argv or logs in the delta. ### Size (x86_64 static, built with the repo recipe, sccache + pinned Zig) - head **21,348,272** (bit-identical to the author's figure) vs base 884f5f624 **21,327,696**: **+20,576 B**. aarch64 is +19,752 B over its cap. - Sections, unstripped: `.text` +19,392 · `.eh_frame` +752 · `.gcc_except_table` +312 · `.data.rel.ro` +256 · `.eh_frame_hdr` +232 · `.rodata` 0. - Attribution, from builds of head with one feature removed: - **Hidden inherited args in sub-help (320c8806c): −11,776 B (57%).** LTO now has two copies of clap's `Arg::clone` (+7,033), plus `Vec<Arg>` collect (+848) and duplicated Vec clones (+1,452). - **SIGINT envelope (fc145d367): −2,720 B.** - Rest, about 6.1 KB: `parse_failure`/`help_result` envelopes, typed `Failure`/`Cause` errors, `report_failure_as`, `run_group` for `agent`, `output::done`. The 51 KB `dispatch_selected_action` being split into outlined functions is net neutral. - vs origin/dev (eecf970a5): dev is 21,080,848 (its cap is 21,080,144, +704 from the known registry-path offset), so head is +267,424. That gap does **not** belong to this branch: the branch is not rebased, and dev's 438 commits include f0a88fe27 (VT archive repackaging), which drops about 300 KB of Zig debug/unwind text that head still carries (`debug.SelfInfo.unwindFrameDwarf`, `Io.Writer.printValue`). The branch's own growth over its merge-base cap 21,317,296 is +30,976 (slice 1 +10,400, round 2 +20,576). - **Cheap trims:** 1. Do not `Arg::clone()` each inherited global arg into every subcommand. Either declare the server-only options non-global on `server` (they are then neither shown nor accepted under its subcommands), or add a minimal hidden stub (`Arg::new(id).long(..).hide(true)`) instead of a full clone. That saves about 11.8 KB, more than half the overage. 2. The rest is small and spread out; nothing else under 1 KB is worth chasing. ### Gate (`scripts/verify fast` on the review branch) ``` +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | test | FAIL (101) | | cargo-deny | PASS | | static builds | FAIL (1) | +---------------------------+--------------+ ``` The test failures are exactly the 7 review tests. The static builds fail on size alone: `size: 21348272 bytes; cap: 21327696 bytes; delta: +20576 bytes` (x86_64) and `+19752` (aarch64). `agent group: exit 0, versioned JSON listing of its commands`.
Author
Owner

Started round-2 CLI fixes on branch cli-overhaul-r2-fixes, based at 73661530486d1133fbed18b9a25b141183d80e76 (origin/cli-overhaul-1). Read the issue history, CLAUDE.md, architecture/process docs, and D243/D299/D303/D304. Next: cherry-pick review tests, fix findings, size-check, and run the final gate.

Started round-2 CLI fixes on branch `cli-overhaul-r2-fixes`, based at `73661530486d1133fbed18b9a25b141183d80e76` (`origin/cli-overhaul-1`). Read the issue history, CLAUDE.md, architecture/process docs, and D243/D299/D303/D304. Next: cherry-pick review tests, fix findings, size-check, and run the final gate.
Author
Owner

Baseline evidence on 5f5030f40: cargo test -p infraternal --test cli_review_r2 -- --test-threads=1 reports 2 passed / 7 failed. component_cli.rs emitted 2 envelopes for the two-page mesh peers fixture; usage.rs echoed a 40-character word in message and error.detail; run_skill included a URL credential in details; NodeStatus::headline said “not running” for an unknown unit; the SIGINT pipe test captured a malformed 4,293-byte line; and the later Tokio handler test exited 130 instead of 42. The script-loop test also fails because _exit(130) lets its shell continue; leaving it ignored as the D303 owner question.

Baseline evidence on `5f5030f40`: `cargo test -p infraternal --test cli_review_r2 -- --test-threads=1` reports 2 passed / 7 failed. `component_cli.rs` emitted 2 envelopes for the two-page `mesh peers` fixture; `usage.rs` echoed a 40-character word in `message` and `error.detail`; `run_skill` included a URL credential in `details`; `NodeStatus::headline` said “not running” for an unknown unit; the SIGINT pipe test captured a malformed 4,293-byte line; and the later Tokio handler test exited 130 instead of 42. The script-loop test also fails because `_exit(130)` lets its shell continue; leaving it ignored as the D303 owner question.
Author
Owner

Pagination fix committed as 24490111d: component_cli.rs now accumulates page arrays and presents only after the last page succeeds. The regression verifies one envelope with 2 peers. Focused test: 1 passed; cargo clippy -p infraternal --all-targets --locked -- -D warnings passed; cargo fmt --all --check passed.

Pagination fix committed as `24490111d`: `component_cli.rs` now accumulates page arrays and presents only after the last page succeeds. The regression verifies one envelope with 2 peers. Focused test: 1 passed; `cargo clippy -p infraternal --all-targets --locked -- -D warnings` passed; `cargo fmt --all --check` passed.
Author
Owner

Value-echo fix committed as 1628ef6e3: usage errors identify the command position, and missing-skill details no longer include the supplied path. The token-shaped typo and URL-path regression tests both pass (2/2); touched-crate clippy and fmt checks pass.

Value-echo fix committed as `1628ef6e3`: usage errors identify the command position, and missing-skill details no longer include the supplied path. The token-shaped typo and URL-path regression tests both pass (2/2); touched-crate clippy and fmt checks pass.
Author
Owner

Status wording fix committed as 90069006e: headline and next-step selection now use confirmed-down units; an unanswered unit produces an “unknown” headline. Focused status regression: 1 passed; clippy for infraternal and infraternal-status passed; fmt passed.

Status wording fix committed as `90069006e`: headline and next-step selection now use confirmed-down units; an unanswered unit produces an “unknown” headline. Focused status regression: 1 passed; clippy for `infraternal` and `infraternal-status` passed; fmt passed.
Author
Owner

SIGINT fix committed as 975699a6e: the final-write phase is atomic, signals during a blocked write let the one result line finish before exit 130, and a chained later handler receives the signal. Slow-pipe test and later-handler test pass (1/1 each); the script-loop test is ignored with the requested D303 owner-question reason. Clippy for infraternal/infraternal-shim and fmt pass.

SIGINT fix committed as `975699a6e`: the final-write phase is atomic, signals during a blocked write let the one result line finish before exit 130, and a chained later handler receives the signal. Slow-pipe test and later-handler test pass (1/1 each); the script-loop test is ignored with the requested D303 owner-question reason. Clippy for `infraternal`/`infraternal-shim` and fmt pass.
Author
Owner

Server log color fix committed as 45d459c19: empty NO_COLOR no longer disables ANSI when stderr is a terminal. The focused helper test passes (1/1); infraternal-server clippy and fmt pass.

Server log color fix committed as `45d459c19`: empty `NO_COLOR` no longer disables ANSI when stderr is a terminal. The focused helper test passes (1/1); `infraternal-server` clippy and fmt pass.
Author
Owner

Inherited-option trim committed as 227bdc67b: descendants now carry minimal hidden parser stubs instead of full ancestor argument clones. Both server option parsing checks pass; clippy and fmt pass. The review attributed 11,776 bytes to this path; final target sizes will be recorded from the branch gate.

Inherited-option trim committed as `227bdc67b`: descendants now carry minimal hidden parser stubs instead of full ancestor argument clones. Both server option parsing checks pass; clippy and fmt pass. The review attributed 11,776 bytes to this path; final target sizes will be recorded from the branch gate.
Author
Owner

Owner decision D305 (2026-10-18, dev e105b8cb6): Ctrl-C writes the interrupted envelope, then restores the default SIGINT action and re-raises it, so calling scripts stop and $? stays 130. Follow-up job cli-sigint-reraise is queued after cli-overhaul-r2-fixes.

Owner decision D305 (2026-10-18, dev e105b8cb6): Ctrl-C writes the `interrupted` envelope, then restores the default SIGINT action and re-raises it, so calling scripts stop and `$?` stays 130. Follow-up job `cli-sigint-reraise` is queued after `cli-overhaul-r2-fixes`.
Author
Owner

Verification guard committed as 77010d5a8: it separates stderr and requires one parsed stdout JSON line with the expected command listing. bash -n scripts/verify.d/rust.sh and the guard against the debug binary both pass.

Verification guard committed as `77010d5a8`: it separates stderr and requires one parsed stdout JSON line with the expected command listing. `bash -n scripts/verify.d/rust.sh` and the guard against the debug binary both pass.
Author
Owner

scripts/verify fast exposed an interaction with D303 output handling: the CLI review test a_failing_command_in_json_mode_prints_exactly_one_envelope failed at crates/infraternal/tests/cli_review.rs:110 (stdout had 0 envelopes; expected 1). Reproduction: agent join printed its progress record, then exited 130 before the final JSON error. The progress writer is consuming the atomic final-output phase; I’m separating progress writes from final envelope writes and will rerun the affected checks.

`scripts/verify fast` exposed an interaction with D303 output handling: the CLI review test `a_failing_command_in_json_mode_prints_exactly_one_envelope` failed at `crates/infraternal/tests/cli_review.rs:110` (stdout had 0 envelopes; expected 1). Reproduction: `agent join` printed its progress record, then exited 130 before the final JSON error. The progress writer is consuming the atomic final-output phase; I’m separating progress writes from final envelope writes and will rerun the affected checks.
Author
Owner

Static size finding from scripts/verify fast: x86_64 artifact /home/kayg/.cache/codex-scratch/cli-overhaul-r2-fixes/target/x86_64-unknown-linux-musl/release/infraternal is 21,343,472 bytes vs the 21,327,696-byte cap (+15,776 bytes). PT_INTERP is absent; AES-128-GCM vector, production trust, and key-memory checks passed. aarch64 measurement is still running. No cap change.

Static size finding from `scripts/verify fast`: x86_64 artifact `/home/kayg/.cache/codex-scratch/cli-overhaul-r2-fixes/target/x86_64-unknown-linux-musl/release/infraternal` is 21,343,472 bytes vs the 21,327,696-byte cap (+15,776 bytes). PT_INTERP is absent; AES-128-GCM vector, production trust, and key-memory checks passed. aarch64 measurement is still running. No cap change.
Author
Owner

Static size finding from scripts/verify fast: aarch64 artifact /home/kayg/.cache/codex-scratch/cli-overhaul-r2-fixes/target/aarch64-unknown-linux-musl/release/infraternal is 19,544,144 bytes vs the 19,527,720-byte cap (+16,424 bytes). PT_INTERP is absent and production trust passed. Native aarch64 key-memory execution was unavailable on this x86_64 host. No cap change.

Static size finding from `scripts/verify fast`: aarch64 artifact `/home/kayg/.cache/codex-scratch/cli-overhaul-r2-fixes/target/aarch64-unknown-linux-musl/release/infraternal` is 19,544,144 bytes vs the 19,527,720-byte cap (+16,424 bytes). PT_INTERP is absent and production trust passed. Native aarch64 key-memory execution was unavailable on this x86_64 host. No cap change.
Author
Owner

Committed 67da54f5b: progress records now use the shared renderer without consuming the final SIGINT output phase. a_failing_command_in_json_mode_prints_exactly_one_envelope: 1 passed; round-two suite: 8 passed, 0 failed, 1 ignored for the D303 owner question; infraternal clippy and cargo fmt --all -- --check: pass.

Committed `67da54f5b`: progress records now use the shared renderer without consuming the final SIGINT output phase. `a_failing_command_in_json_mode_prints_exactly_one_envelope`: 1 passed; round-two suite: 8 passed, 0 failed, 1 ignored for the D303 owner question; infraternal clippy and `cargo fmt --all -- --check`: pass.
Author
Owner

Finished at head 67da54f5bc5207adba5ae366679e89839c724b6b, pushed to cli-overhaul-r2-fixes.

The round-two suite passes: 8 passed, 0 failed, 1 ignored (ctrl_c_in_a_script_loop_stops_the_loop, owner question D303). The existing JSON failure test also passes (1/1); the full cli_review suite passes (16/16). Touched-crate clippy and formatting pass. The optional panic-to-internal envelope was not added: a panic after output begins cannot safely be replaced with a single envelope without broader output transaction handling.

The inherited-option clone removal is committed at 227bdc67b; review measured a −11.8 KB reduction. Final stripped artifacts remain over the unchanged caps: x86_64 is 21,343,408 bytes vs 21,327,696 (+15,712); aarch64 is 19,544,144 bytes vs 19,527,720 (+16,424). PT_INTERP is absent on both. Native aarch64 key-memory execution was unavailable on this x86_64 host.

Final scripts/verify fast exited 1 because the static-size gate rejected artifacts over the caps. All other Rust gates passed. Gate summary and size lines, verbatim excerpts:

PT_INTERP: absent; size: 21343408 bytes; cap: 21327696 bytes; delta: +15712 bytes
binary exceeds the 21327696-byte size budget: 21343408 bytes
PT_INTERP: absent; size: 19544144 bytes; cap: 19527720 bytes; delta: +16424 bytes
binary exceeds the 19527720-byte size budget: 19544144 bytes
+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| test                      | PASS         |
| cargo-deny                | PASS         |
| static builds             | FAIL (1)     |
+---------------------------+--------------+

Full transcript: scripts-verify-fast.log

Finished at head `67da54f5bc5207adba5ae366679e89839c724b6b`, pushed to `cli-overhaul-r2-fixes`. The round-two suite passes: 8 passed, 0 failed, 1 ignored (`ctrl_c_in_a_script_loop_stops_the_loop`, owner question D303). The existing JSON failure test also passes (1/1); the full `cli_review` suite passes (16/16). Touched-crate clippy and formatting pass. The optional panic-to-internal envelope was not added: a panic after output begins cannot safely be replaced with a single envelope without broader output transaction handling. The inherited-option clone removal is committed at `227bdc67b`; review measured a −11.8 KB reduction. Final stripped artifacts remain over the unchanged caps: x86_64 is 21,343,408 bytes vs 21,327,696 (+15,712); aarch64 is 19,544,144 bytes vs 19,527,720 (+16,424). PT_INTERP is absent on both. Native aarch64 key-memory execution was unavailable on this x86_64 host. Final `scripts/verify fast` exited 1 because the static-size gate rejected artifacts over the caps. All other Rust gates passed. Gate summary and size lines, verbatim excerpts: ``` PT_INTERP: absent; size: 21343408 bytes; cap: 21327696 bytes; delta: +15712 bytes binary exceeds the 21327696-byte size budget: 21343408 bytes PT_INTERP: absent; size: 19544144 bytes; cap: 19527720 bytes; delta: +16424 bytes binary exceeds the 19527720-byte size budget: 19544144 bytes +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | test | PASS | | cargo-deny | PASS | | static builds | FAIL (1) | +---------------------------+--------------+ ``` Full transcript: [scripts-verify-fast.log](https://git.kayg.org/attachments/f85e10bc-b4fc-4334-85a2-07c5431777f6)
Author
Owner

Started D305 follow-up on branch cli-sigint-reraise, base 67da54f5bc5207adba5ae366679e89839c724b6b (origin/cli-overhaul-r2-fixes). Read the full #239 history, D303/D305, and the repository contract. The script-loop regression is currently ignored pending D305.

Started D305 follow-up on branch `cli-sigint-reraise`, base `67da54f5bc5207adba5ae366679e89839c724b6b` (`origin/cli-overhaul-r2-fixes`). Read the full #239 history, D303/D305, and the repository contract. The script-loop regression is currently ignored pending D305.
Author
Owner

Finding: D305 is already owner-approved on origin/dev at e105b8cb (one-file decision-record commit), while this branch starts at 67da54f5b and does not include it. I’ll cherry-pick that record before the implementation so the branch carries the decision it cites.

Finding: D305 is already owner-approved on `origin/dev` at `e105b8cb` (one-file decision-record commit), while this branch starts at `67da54f5b` and does not include it. I’ll cherry-pick that record before the implementation so the branch carries the decision it cites.
Author
Owner

Update: cherry-picking e105b8cb conflicts because that commit also adds D299–D304, which are absent from this lane’s base. I’m aborting it and following the brief’s read-only instruction for D305 (git show origin/dev:DECISIONS.md); the implementation will cite the authoritative decision without importing unrelated decisions.

Update: cherry-picking `e105b8cb` conflicts because that commit also adds D299–D304, which are absent from this lane’s base. I’m aborting it and following the brief’s read-only instruction for D305 (`git show origin/dev:DECISIONS.md`); the implementation will cite the authoritative decision without importing unrelated decisions.
Author
Owner

Baseline reproduction (before handler changes): after removing the D303 ignore, CARGO_TARGET_DIR=$HOME/.cache/codex-scratch/cli-sigint-reraise/target build-slot cargo test -p infraternal --test cli_review_r2 ctrl_c_in_a_script_loop_stops_the_loop -- --exact --nocapture failed as expected. The loop printed carried-on; the shell exited 0 (crates/infraternal/tests/cli_review_r2.rs:261). Build completed in 3m29s; 0 passed / 1 failed / 8 filtered.

Baseline reproduction (before handler changes): after removing the D303 ignore, `CARGO_TARGET_DIR=$HOME/.cache/codex-scratch/cli-sigint-reraise/target build-slot cargo test -p infraternal --test cli_review_r2 ctrl_c_in_a_script_loop_stops_the_loop -- --exact --nocapture` failed as expected. The loop printed `carried-on`; the shell exited 0 (`crates/infraternal/tests/cli_review_r2.rs:261`). Build completed in 3m29s; 0 passed / 1 failed / 8 filtered.
Author
Owner

Finding/fix evidence: the re-enabled script-loop regression failed before the handler change (shell status 0 and carried-on output). After the change, the same test passes (1 passed, 0 failed, 8 filtered; 0.82 s) at crates/infraternal/tests/cli_review_r2.rs. Direct process-status coverage already accepts either status.code() == 130 or SIGINT (status.signal() == 2) in cli_review.rs.

Finding/fix evidence: the re-enabled script-loop regression failed before the handler change (shell status 0 and `carried-on` output). After the change, the same test passes (1 passed, 0 failed, 8 filtered; 0.82 s) at `crates/infraternal/tests/cli_review_r2.rs`. Direct process-status coverage already accepts either `status.code() == 130` or SIGINT (`status.signal() == 2`) in `cli_review.rs`.
Author
Owner

Shim test evidence: cargo test -p infraternal-shim --locked passes after staging the repository’s pinned Zig toolchain into this job target and PATH: 79 unit tests passed / 13 ignored; detach 2/2, mouse 1/1, process-exit descriptor 2/2. The first direct run’s mouse probe failed only because zig was absent from PATH; scripts/auth-toolchain resolved it. Initial diagnostic, mouse output, build output.

Shim test evidence: `cargo test -p infraternal-shim --locked` passes after staging the repository’s pinned Zig toolchain into this job target and PATH: 79 unit tests passed / 13 ignored; detach 2/2, mouse 1/1, process-exit descriptor 2/2. The first direct run’s mouse probe failed only because `zig` was absent from PATH; `scripts/auth-toolchain` resolved it. [Initial diagnostic](https://git.kayg.org/attachments/8b6ed417-425c-4c66-8d4c-5bedd7f80654), [mouse output](https://git.kayg.org/attachments/61c2f765-c30d-4456-a296-1b4211fd4eb4), [build output](https://git.kayg.org/attachments/88346f3b-2b13-475d-a706-7988f354547b).
Author
Owner

Touched-crate clippy finding: the first run reported match_same_arms in the SIGINT phase match and borrow_as_ptr for the sigemptyset, sigaction and sigprocmask arguments. I collapsed the identical match arm and made the raw-pointer borrows explicit; clippy is rerunning.

Touched-crate clippy finding: the first run reported `match_same_arms` in the SIGINT phase match and `borrow_as_ptr` for the `sigemptyset`, `sigaction` and `sigprocmask` arguments. I collapsed the identical match arm and made the raw-pointer borrows explicit; clippy is rerunning.
Author
Owner

Committed and pushed shim behavior as f1dfa0213. infraternal-shim now restores SIG_DFL, unblocks SIGINT and raises it after the notice; an in-progress final envelope still completes first. Verification on this tree: fmt PASS; clippy for infraternal and infraternal-shim PASS; CLI review suites 16/16 and 9/9 PASS. The full shim suite passed with 79 unit tests, 2 detach, 1 mouse and 2 process-exit tests; 13 unit tests were ignored.

Committed and pushed shim behavior as `f1dfa0213`. `infraternal-shim` now restores SIG_DFL, unblocks SIGINT and raises it after the notice; an in-progress final envelope still completes first. Verification on this tree: fmt PASS; clippy for `infraternal` and `infraternal-shim` PASS; CLI review suites 16/16 and 9/9 PASS. The full shim suite passed with 79 unit tests, 2 detach, 1 mouse and 2 process-exit tests; 13 unit tests were ignored.
Author
Owner

Committed and pushed the test step as 47b35fdba. The previously ignored ctrl_c_in_a_script_loop_stops_the_loop is active; it failed before the fix (shell status 0 plus carried-on) and passes after it. Final CLI review run: 16/16 and 9/9 passed, 0 failed or ignored.

Committed and pushed the test step as `47b35fdba`. The previously ignored `ctrl_c_in_a_script_loop_stops_the_loop` is active; it failed before the fix (shell status 0 plus `carried-on`) and passes after it. Final CLI review run: 16/16 and 9/9 passed, 0 failed or ignored.
Author
Owner

Committed and pushed docs as 69026ea29. docs/CLI.md now defines 130 as interrupted by Ctrl-C and terminated by SIGINT; source comments distinguish shell status 130 from direct wait status signal 2.

Committed and pushed docs as `69026ea29`. `docs/CLI.md` now defines 130 as interrupted by Ctrl-C and terminated by SIGINT; source comments distinguish shell status 130 from direct wait status signal 2.
Author
Owner

scripts/verify iterate passed on 69026ea29: fmt, VT native fmt, CLI plugin compile-out, clippy, tests, cargo-deny, compiler metadata, asset checks, tracer checks and TypeScript protocol tests all passed. The CLI suites passed 16/16 and 9/9; shim unit tests passed 80 with 13 ignored, plus detach 2/2, mouse 1/1 and process-exit descriptor 2/2. Full transcript: verify-iterate.log.

`scripts/verify iterate` passed on `69026ea29`: fmt, VT native fmt, CLI plugin compile-out, clippy, tests, cargo-deny, compiler metadata, asset checks, tracer checks and TypeScript protocol tests all passed. The CLI suites passed 16/16 and 9/9; shim unit tests passed 80 with 13 ignored, plus detach 2/2, mouse 1/1 and process-exit descriptor 2/2. Full transcript: [verify-iterate.log](https://git.kayg.org/attachments/0ae55fa3-2c8e-4d2e-a03c-b02acb480c71).
Author
Owner

Static x86_64 size finding during scripts/verify fast: stripped infraternal is 21,343,760 bytes; recorded merge-base size is 21,343,408 bytes, a 352-byte increase. The branch is 16,064 bytes over the 21,327,696-byte cap, compared with the merge-base's 15,712-byte overage. The gate is continuing with the aarch64 build.

Static x86_64 size finding during `scripts/verify fast`: stripped `infraternal` is 21,343,760 bytes; recorded merge-base size is 21,343,408 bytes, a 352-byte increase. The branch is 16,064 bytes over the 21,327,696-byte cap, compared with the merge-base's 15,712-byte overage. The gate is continuing with the aarch64 build.
Author
Owner

Static aarch64 size finding: stripped infraternal is 19,544,400 bytes versus the recorded merge-base size of 19,544,144 bytes, a 256-byte increase. The branch is 16,680 bytes over the 19,527,720-byte cap; the merge base was already 16,424 bytes over. The host cannot run the aarch64 key-memory check. Full gate transcript: verify-fast.log.

Static aarch64 size finding: stripped `infraternal` is 19,544,400 bytes versus the recorded merge-base size of 19,544,144 bytes, a 256-byte increase. The branch is 16,680 bytes over the 19,527,720-byte cap; the merge base was already 16,424 bytes over. The host cannot run the aarch64 key-memory check. Full gate transcript: [verify-fast.log](https://git.kayg.org/attachments/1732660d-de96-4208-aa17-7b67cca64af4).
Author
Owner

Finished #239 on cli-sigint-reraise, head 69026ea29 (docs(cli): explain Ctrl-C exit status), pushed to origin.

scripts/verify fast final table (verbatim):

+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| test                      | PASS         |
| cargo-deny                | PASS         |
| static builds             | FAIL (1)     |
+---------------------------+--------------+

The static build row fails the existing size caps. Relative to the recorded merge-base, stripped x86_64 grew 352 bytes (21,343,408 → 21,343,760); stripped aarch64 grew 256 bytes (19,544,144 → 19,544,400). The merge base already exceeded the caps by 15,712 and 16,424 bytes respectively. The x86_64 key-memory check passed; the host cannot run the aarch64 runtime check. All other final gate rows passed. Full transcript: verify-fast.log.

Finished #239 on `cli-sigint-reraise`, head `69026ea29` (`docs(cli): explain Ctrl-C exit status`), pushed to origin. `scripts/verify fast` final table (verbatim): ``` +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | test | PASS | | cargo-deny | PASS | | static builds | FAIL (1) | +---------------------------+--------------+ ``` The static build row fails the existing size caps. Relative to the recorded merge-base, stripped x86_64 grew 352 bytes (21,343,408 → 21,343,760); stripped aarch64 grew 256 bytes (19,544,144 → 19,544,400). The merge base already exceeded the caps by 15,712 and 16,424 bytes respectively. The x86_64 key-memory check passed; the host cannot run the aarch64 runtime check. All other final gate rows passed. Full transcript: [verify-fast.log](https://git.kayg.org/attachments/1732660d-de96-4208-aa17-7b67cca64af4).
Author
Owner

Round-3 delta review started on review-cli-overhaul-r3, base/head 69026ea298. Read all 37 comments on #239 (no parent linked). Scope: 73661530..69026ea29, D299/D303/D305, signal dispositions and final-output races, one-envelope paths, inherited options and size. Tests/findings will be committed on this review branch only.

Round-3 delta review started on review-cli-overhaul-r3, base/head 69026ea298f810d2da0215376add2ef0b586de8a. Read all 37 comments on #239 (no parent linked). Scope: 73661530..69026ea29, D299/D303/D305, signal dispositions and final-output races, one-envelope paths, inherited options and size. Tests/findings will be committed on this review branch only.
Author
Owner

P2 confirmed on 69026ea29: exit_on_interrupt replaces inherited SIG_IGN unconditionally (crates/infraternal-shim/src/pty.rs:358-368). A real CLI child started by sh with trap '' INT, held in its final JSON write by a 4 KiB pipe, terminates by signal 2 after SIGINT instead of finishing normally. Test: inherited_ignored_sigint_stays_ignored_during_cli_output (cli_review_r3.rs:65). Its complete envelope survives; the incorrect termination is the finding. Preserve inherited SIG_IGN before installing the handler. This behavior predates this delta but is explicitly in round-3 scope. Signal suite: 3 pass / 1 expected failure; blocked/pending-signal re-raise checks pass. Receipt.

P2 confirmed on 69026ea29: exit_on_interrupt replaces inherited SIG_IGN unconditionally (crates/infraternal-shim/src/pty.rs:358-368). A real CLI child started by `sh` with `trap '' INT`, held in its final JSON write by a 4 KiB pipe, terminates by signal 2 after SIGINT instead of finishing normally. Test: inherited_ignored_sigint_stays_ignored_during_cli_output (cli_review_r3.rs:65). Its complete envelope survives; the incorrect termination is the finding. Preserve inherited SIG_IGN before installing the handler. This behavior predates this delta but is explicitly in round-3 scope. Signal suite: 3 pass / 1 expected failure; blocked/pending-signal re-raise checks pass. [Receipt](https://git.kayg.org/attachments/a07eeb0d-0b7b-49f8-b55a-98d6b4b60f32).
Author
Owner

P2 confirmed in the delta: hidden_inherited_arg drops the integer value parser for --fd (crates/infraternal/src/cli/command_tree.rs:231-243). run_operator_action then discards the type mismatch via try_get_one::("fd").ok().flatten() (main.rs:1528-1532). --json agent run --fd 999 --data <missing-identity> starts remote reconnect and exits 1/failed; before trimming it must reject the incompatible descriptor with 2/usage (main.rs:1426-1433). Non-numeric descriptors lose parser validation too. Test: inherited_fd_is_rejected_instead_of_ignored_by_remote_commands, cli_review_r3_arguments.rs. Keep the ancestor value parser in the hidden stub (or reject the option explicitly), rather than silently ignoring it. Receipt.

Existing regressions: cli_review 16/16 pass; cli_review_r2 11/11 pass, including two added checks for a failed later page (one failure envelope, no partial rows) and ordered three-page accumulation.

P2 confirmed in the delta: hidden_inherited_arg drops the integer value parser for --fd (crates/infraternal/src/cli/command_tree.rs:231-243). run_operator_action then discards the type mismatch via try_get_one::<i64>("fd").ok().flatten() (main.rs:1528-1532). `--json agent run --fd 999 --data <missing-identity>` starts remote reconnect and exits 1/failed; before trimming it must reject the incompatible descriptor with 2/usage (main.rs:1426-1433). Non-numeric descriptors lose parser validation too. Test: inherited_fd_is_rejected_instead_of_ignored_by_remote_commands, cli_review_r3_arguments.rs. Keep the ancestor value parser in the hidden stub (or reject the option explicitly), rather than silently ignoring it. [Receipt](https://git.kayg.org/attachments/ca798f9f-762d-41a6-9a97-d4f3c0037c1b). Existing regressions: cli_review 16/16 pass; cli_review_r2 11/11 pass, including two added checks for a failed later page (one failure envelope, no partial rows) and ordered three-page accumulation.
Author
Owner

Review test steps pushed on review-cli-overhaul-r3:

  • 11bda0c0a: SIGINT disposition and blocked/pending-signal regressions, 3 pass / 1 expected failure.
  • 2d35ac6f4: inherited descriptor regression, 1 expected failure. Expanded manual matrix confirms run and join each ignore both numeric and non-numeric --fd: all 4 exit 1 after starting remote work, rather than 2/usage. Matrix.
  • afaf44e82: later-page failure and ordered three-page tests, 2/2 pass; cli_review 16/16 and cli_review_r2 11/11 pass.
    Formatting passes; touched-crate clippy passes (receipt). Dry-run check preserves all 10 server configuration fields, including both trusted-proxy entries, before and after init; the plans match exactly (receipt). No implementation fixes made. Full scripts/verify fast is running on afaf44e82.
Review test steps pushed on review-cli-overhaul-r3: - 11bda0c0a: SIGINT disposition and blocked/pending-signal regressions, 3 pass / 1 expected failure. - 2d35ac6f4: inherited descriptor regression, 1 expected failure. Expanded manual matrix confirms run and join each ignore both numeric and non-numeric --fd: all 4 exit 1 after starting remote work, rather than 2/usage. [Matrix](https://git.kayg.org/attachments/36de7b5f-82bf-40a5-ac5e-d292ecba123c). - afaf44e82: later-page failure and ordered three-page tests, 2/2 pass; cli_review 16/16 and cli_review_r2 11/11 pass. Formatting passes; touched-crate clippy passes ([receipt](https://git.kayg.org/attachments/ce705bcd-c482-4a9d-9fb0-5fbb9e8454c2)). Dry-run check preserves all 10 server configuration fields, including both trusted-proxy entries, before and after `init`; the plans match exactly ([receipt](https://git.kayg.org/attachments/25b6069e-8bbb-4c6b-b4fb-2f67e955be88)). No implementation fixes made. Full scripts/verify fast is running on afaf44e82.
Author
Owner

Round-3 delta review finished: MERGE under D206, with two P2 follow-ups. Counts: P0 0 / P1 0 / P2 2 / P3 0.

Reviewed: 69026ea298; delta 73661530..69026ea29.
Review tests committed and pushed on review-cli-overhaul-r3, head afaf44e829. Implementation unchanged.

Findings:

  • P2: inherited SIG_IGN is replaced by the JSON SIGINT handler (pty.rs:358-368). Test inherited_ignored_sigint_stays_ignored_during_cli_output fails: an ignored SIGINT terminates the real CLI by signal 2. The shipping static binary reproduces it too. This predates the delta but was explicitly requested in the signal audit. Test receipt, static-binary receipt.
  • P2: minimal inherited stubs drop the integer parser for --fd (command_tree.rs:231-243). try_get_one::<i64>().ok().flatten() then silently discards the descriptor (main.rs:1528-1532). Test inherited_fd_is_rejected_instead_of_ignored_by_remote_commands fails with exit 1/failed instead of 2/usage. Both run/join and numeric/non-numeric descriptors reproduce it (4/4). Test receipt, matrix.

Checks: cli_review 16/16 and cli_review_r2 11/11 pass, including added a_failed_later_page_emits_only_the_failure_envelope and three_pages_preserve_order_and_only_the_final_cursor. Blocked/pending-signal tests before/during final output pass. Static x86_64 checks confirm one valid envelope and signal 2 before/during final output. All ten server configuration inputs, including repeated trusted-proxy, survive before/after init with identical dry-run plans (receipt). Help/version/usage/value-redaction and quiet EPIPE matrix: 9 ordinary + 9 closed-stdout paths (receipt). Handler call graph uses lock-free atomics and async-signal-safe calls; production embedded-fd, shim and units avoid installation; exec/child reset paths checked. Reviewer checklist completed.

Sizes: x86_64 21,343,760 B, aarch64 19,544,400 B, exactly matching author receipts. Independently rebuilt merge base 895bcdd23: x86_64 21,300,016 B, so whole-stack delta +43,744 B; requested delta from recorded 73661530 is -4,512 B. D305 adds only 352 B x86_64 / 256 B aarch64 over 67da54f5b. No unexpected growth; accepted cap exceptions unchanged. Comparison, baseline build.

scripts/verify fast on afaf44e82 exited 1. Test row stops on the expected SIG_IGN review regression (the descriptor failure was verified separately); static row fails only the unchanged size caps. x86_64 key-memory check passed; aarch64 runtime check unavailable on this x86_64 host. Final output verbatim:

+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| test                      | FAIL (101)   |
| cargo-deny                | PASS         |
| static builds             | FAIL (1)     |
+---------------------------+--------------+

Full gate transcript. Temporary baseline and own build target removed; evidence retained outside the checkout. No service started or deployment performed. Issue left open.

Round-3 delta review finished: **MERGE under D206**, with two P2 follow-ups. Counts: P0 0 / P1 0 / P2 2 / P3 0. Reviewed: 69026ea298f810d2da0215376add2ef0b586de8a; delta 73661530..69026ea29. Review tests committed and pushed on review-cli-overhaul-r3, head afaf44e8299c0b5651f75a818faed79e14edda49. Implementation unchanged. Findings: - P2: inherited SIG_IGN is replaced by the JSON SIGINT handler (pty.rs:358-368). Test `inherited_ignored_sigint_stays_ignored_during_cli_output` fails: an ignored SIGINT terminates the real CLI by signal 2. The shipping static binary reproduces it too. This predates the delta but was explicitly requested in the signal audit. [Test receipt](https://git.kayg.org/attachments/a07eeb0d-0b7b-49f8-b55a-98d6b4b60f32), [static-binary receipt](https://git.kayg.org/attachments/b91e7c71-9a12-4113-b582-b45843e10e52). - P2: minimal inherited stubs drop the integer parser for --fd (command_tree.rs:231-243). `try_get_one::<i64>().ok().flatten()` then silently discards the descriptor (main.rs:1528-1532). Test `inherited_fd_is_rejected_instead_of_ignored_by_remote_commands` fails with exit 1/failed instead of 2/usage. Both run/join and numeric/non-numeric descriptors reproduce it (4/4). [Test receipt](https://git.kayg.org/attachments/ca798f9f-762d-41a6-9a97-d4f3c0037c1b), [matrix](https://git.kayg.org/attachments/36de7b5f-82bf-40a5-ac5e-d292ecba123c). Checks: cli_review 16/16 and cli_review_r2 11/11 pass, including added `a_failed_later_page_emits_only_the_failure_envelope` and `three_pages_preserve_order_and_only_the_final_cursor`. Blocked/pending-signal tests before/during final output pass. Static x86_64 checks confirm one valid envelope and signal 2 before/during final output. All ten server configuration inputs, including repeated trusted-proxy, survive before/after init with identical dry-run plans ([receipt](https://git.kayg.org/attachments/25b6069e-8bbb-4c6b-b4fb-2f67e955be88)). Help/version/usage/value-redaction and quiet EPIPE matrix: 9 ordinary + 9 closed-stdout paths ([receipt](https://git.kayg.org/attachments/32d32605-2740-433c-aac1-dee8ef2d1841)). Handler call graph uses lock-free atomics and async-signal-safe calls; production embedded-fd, shim and units avoid installation; exec/child reset paths checked. Reviewer checklist completed. Sizes: x86_64 21,343,760 B, aarch64 19,544,400 B, exactly matching author receipts. Independently rebuilt merge base 895bcdd23: x86_64 21,300,016 B, so whole-stack delta +43,744 B; requested delta from recorded 73661530 is -4,512 B. D305 adds only 352 B x86_64 / 256 B aarch64 over 67da54f5b. No unexpected growth; accepted cap exceptions unchanged. [Comparison](https://git.kayg.org/attachments/9f81a467-0439-40b4-a9aa-ed221c9ee3b7), [baseline build](https://git.kayg.org/attachments/aadfcd19-f51d-42ae-90c6-5df74dba5218). `scripts/verify fast` on afaf44e82 exited 1. Test row stops on the expected SIG_IGN review regression (the descriptor failure was verified separately); static row fails only the unchanged size caps. x86_64 key-memory check passed; aarch64 runtime check unavailable on this x86_64 host. Final output verbatim: ``` +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | test | FAIL (101) | | cargo-deny | PASS | | static builds | FAIL (1) | +---------------------------+--------------+ ``` [Full gate transcript](https://git.kayg.org/attachments/fce02a10-d696-4e44-b52d-92aa398fc331). Temporary baseline and own build target removed; evidence retained outside the checkout. No service started or deployment performed. Issue left open.
Author
Owner

Started CLI review round-3 fixes on branch cli-r3-fixes, base 69026ea298f810d2da0215376add2ef0b586de8a (origin/cli-sigint-reraise). Read the full #239 history; it has no linked parent. I’m cherry-picking the round-3 regressions from afaf44e82 and will fix inherited SIGINT disposition and --fd validation while preserving D303/D305.

Started CLI review round-3 fixes on branch `cli-r3-fixes`, base `69026ea298f810d2da0215376add2ef0b586de8a` (`origin/cli-sigint-reraise`). Read the full #239 history; it has no linked parent. I’m cherry-picking the round-3 regressions from `afaf44e82` and will fix inherited SIGINT disposition and `--fd` validation while preserving D303/D305.
Author
Owner

Baseline regressions reproduced on cli-r3-fixes after cherry-picking the round-3 tests. cli_review_r3: 3 pass / 1 fail; inherited_ignored_sigint_stays_ignored_during_cli_output observes the child terminated by signal 2 while its final JSON write is blocked (crates/infraternal/tests/cli_review_r3.rs). cli_review_r3_arguments: 0 pass / 1 fail; agent run --fd 999 returns exit 1 with error.code=failed, expected exit 2 / usage (crates/infraternal/tests/cli_review_r3_arguments.rs). Receipts: signal, descriptor.

Baseline regressions reproduced on `cli-r3-fixes` after cherry-picking the round-3 tests. `cli_review_r3`: 3 pass / 1 fail; `inherited_ignored_sigint_stays_ignored_during_cli_output` observes the child terminated by signal 2 while its final JSON write is blocked (`crates/infraternal/tests/cli_review_r3.rs`). `cli_review_r3_arguments`: 0 pass / 1 fail; `agent run --fd 999` returns exit 1 with `error.code=failed`, expected exit 2 / `usage` (`crates/infraternal/tests/cli_review_r3_arguments.rs`). Receipts: [signal](https://git.kayg.org/attachments/bd62ff81-dff4-4337-a7c3-0f36b0a89af3), [descriptor](https://git.kayg.org/attachments/d4952fde-805b-41e5-a15d-7d1b38d4cc33).
Author
Owner

SIGINT disposition fix committed as 6ba56116c. exit_on_interrupt now queries the inherited action before installation; it preserves SIG_IGN and leaves the current policy in place if the query fails. D303/D305 behavior remains for handled SIGINT. Verification: focused ignored-SIGINT regression 1/1 pass; infraternal-shim 79 passed / 13 ignored, detach 2/2, mouse 1/1, process-exit descriptor 2/2; shim clippy and workspace fmt pass. Receipts: regression, shim suite.

SIGINT disposition fix committed as `6ba56116c`. `exit_on_interrupt` now queries the inherited action before installation; it preserves `SIG_IGN` and leaves the current policy in place if the query fails. D303/D305 behavior remains for handled SIGINT. Verification: focused ignored-SIGINT regression 1/1 pass; `infraternal-shim` 79 passed / 13 ignored, detach 2/2, mouse 1/1, process-exit descriptor 2/2; shim clippy and workspace fmt pass. Receipts: [regression](https://git.kayg.org/attachments/cdbc009e-73e1-41ad-9161-82ff66fd610b), [shim suite](https://git.kayg.org/attachments/6c5bf899-97a4-48d2-b2b7-02ff851bba1f).
Author
Owner

Inherited --fd parser fix committed as 5c6d449eb in crates/infraternal/src/cli/command_tree.rs. The hidden descendant stub retains the i64 parser, so malformed values reach the normal D303 usage path before action execution. The round-3 run/join descriptor regression passes (1/1); infraternal clippy and workspace fmt pass. Receipt: fd parser regression.

Inherited `--fd` parser fix committed as `5c6d449eb` in `crates/infraternal/src/cli/command_tree.rs`. The hidden descendant stub retains the i64 parser, so malformed values reach the normal D303 usage path before action execution. The round-3 run/join descriptor regression passes (1/1); `infraternal` clippy and workspace fmt pass. Receipt: [fd parser regression](https://git.kayg.org/attachments/3ed76bfd-086d-4c50-8ce7-bd8bf59d2637).
Author
Owner

Additional --fd finding, exposed after restoring integer parsing: agent run --fd 2147483648 still downcasts the parsed i64 to None, starts the remote path, and returns exit 1 / failed instead of exit 2 / usage. The regression was added to cli_review_r3_arguments.rs and failed before the fix (0/1); receipt: fd overflow before fix. I’m making descriptor presence itself a usage error for every action except internal embedded startup.

Additional `--fd` finding, exposed after restoring integer parsing: `agent run --fd 2147483648` still downcasts the parsed i64 to `None`, starts the remote path, and returns exit 1 / `failed` instead of exit 2 / `usage`. The regression was added to `cli_review_r3_arguments.rs` and failed before the fix (0/1); receipt: [fd overflow before fix](https://git.kayg.org/attachments/97fa6bfb-2d08-40f8-b609-f739d8df209a). I’m making descriptor presence itself a usage error for every action except internal embedded startup.
Author
Owner

Descriptor handling fix committed as 1a8413f4c in crates/infraternal/src/main.rs; the regression now also covers --fd 2147483648, which failed before this fix with exit 1 / failed. Dispatch rejects an inherited descriptor unless the selected action declares it, so agent run and agent join return one usage envelope for numeric, non-integer, and out-of-range values. CLI review suites pass: 16 + 11 + 4 + 1 tests; infraternal clippy and workspace fmt pass. Receipts: CLI suites, clippy.

Descriptor handling fix committed as `1a8413f4c` in `crates/infraternal/src/main.rs`; the regression now also covers `--fd 2147483648`, which failed before this fix with exit 1 / `failed`. Dispatch rejects an inherited descriptor unless the selected action declares it, so `agent run` and `agent join` return one usage envelope for numeric, non-integer, and out-of-range values. CLI review suites pass: 16 + 11 + 4 + 1 tests; infraternal clippy and workspace fmt pass. Receipts: [CLI suites](https://git.kayg.org/attachments/fb1b2f1e-6bb5-4994-9eea-b0ab320a0556), [clippy](https://git.kayg.org/attachments/3e383de3-b458-47c5-9210-eca47a422e86).
Author
Owner

iterate exposed a minimal-build issue in the new --fd refusal helper: cargo test -p infraternal --bin infraternal --no-default-features reports unresolved output at crates/infraternal/src/main.rs:271 because that module is intentionally compiled out. The repository helper continued to later feature builds and emitted an overall ITERATE PASS, so I’m treating the compiler error as a real failure and adding the matching compile-time guard. Receipt: no-default build output.

`iterate` exposed a minimal-build issue in the new `--fd` refusal helper: `cargo test -p infraternal --bin infraternal --no-default-features` reports unresolved `output` at `crates/infraternal/src/main.rs:271` because that module is intentionally compiled out. The repository helper continued to later feature builds and emitted an overall ITERATE PASS, so I’m treating the compiler error as a real failure and adding the matching compile-time guard. Receipt: [no-default build output](https://git.kayg.org/attachments/d1c7d3d9-7fd1-4071-a194-1711dd8c53eb).
Author
Owner

Minimal-build fix committed as d6b6d03dc: the inherited-descriptor guard is compiled only when its output adapter exists. Direct --no-default-features verification passes (33/33 unit tests; two existing dead-code warnings); the CLI review suites pass 32/32; infraternal clippy and fmt pass. Receipts: minimal build, CLI suites, clippy.

Minimal-build fix committed as `d6b6d03dc`: the inherited-descriptor guard is compiled only when its output adapter exists. Direct `--no-default-features` verification passes (33/33 unit tests; two existing dead-code warnings); the CLI review suites pass 32/32; infraternal clippy and fmt pass. Receipts: [minimal build](https://git.kayg.org/attachments/d1b1a13b-9a4c-4baa-96b4-5d01679d54ad), [CLI suites](https://git.kayg.org/attachments/9617db24-aedf-4b50-8fd4-295589750fe5), [clippy](https://git.kayg.org/attachments/4e78428e-fbef-49d4-be48-325463523dc8).
Author
Owner

iterate on d6b6d03dc had one test failure: responsive_socket_survives_a_held_terminal_open_with_an_existing_attachment timed out at crates/infraternal-server/src/auth/socket_clock.rs:81; 467 tests passed and 48 were ignored. All other iterate rows passed, including CLI plugin compile-out. In the same load window (load average 18.07 / 13.88 / 12.34), the isolated test passed on detached origin/dev at a246f2b73 (1/1, 0.70 s), and passed again isolated on this branch (1/1, 0.67 s). This points to a full-suite timing flake; no server/auth code is changed here. Receipts: iterate, dev baseline, branch rerun.

`iterate` on `d6b6d03dc` had one test failure: `responsive_socket_survives_a_held_terminal_open_with_an_existing_attachment` timed out at `crates/infraternal-server/src/auth/socket_clock.rs:81`; 467 tests passed and 48 were ignored. All other iterate rows passed, including CLI plugin compile-out. In the same load window (load average 18.07 / 13.88 / 12.34), the isolated test passed on detached `origin/dev` at `a246f2b73` (1/1, 0.70 s), and passed again isolated on this branch (1/1, 0.67 s). This points to a full-suite timing flake; no server/auth code is changed here. Receipts: [iterate](https://git.kayg.org/attachments/8c0f1afc-6177-46f2-94ab-d99c395483c8), [dev baseline](https://git.kayg.org/attachments/3e59fb3f-1c9b-41bc-8118-d1fd5fd023e1), [branch rerun](https://git.kayg.org/attachments/a3cbf72c-aa5d-4b49-9e62-6a7b4bd156c9).
Author
Owner

Final fast-gate x86_64 static artifact: 21,347,344 bytes, +19,648 over the 21,327,696-byte cap. The previously measured branch base was 21,343,760 bytes (+16,064), so this change adds 3,584 bytes. I’m checking for a small reduction after the current aarch64 gate completes.

Final fast-gate x86_64 static artifact: 21,347,344 bytes, +19,648 over the 21,327,696-byte cap. The previously measured branch base was 21,343,760 bytes (+16,064), so this change adds 3,584 bytes. I’m checking for a small reduction after the current aarch64 gate completes.
Author
Owner

Committed and pushed cafd6d55d on cli-r3-fixes. The parent agent action retains schema-based integer parsing; agent run and agent join reject inherited --fd at the RemoteAgent handler. The 87 CLI binary tests and 5 round-3 integration tests pass; fmt and clippy pass. Static size growth versus merge base 69026ea29 is x86_64 +320 bytes (21,344,080 total, +16,384 over old cap) and aarch64 +256 bytes (19,544,656 total, +16,936 over old cap). Receipt: static size measurements.

Committed and pushed cafd6d55d on cli-r3-fixes. The parent `agent` action retains schema-based integer parsing; `agent run` and `agent join` reject inherited `--fd` at the RemoteAgent handler. The 87 CLI binary tests and 5 round-3 integration tests pass; fmt and clippy pass. Static size growth versus merge base 69026ea29 is x86_64 +320 bytes (21,344,080 total, +16,384 over old cap) and aarch64 +256 bytes (19,544,656 total, +16,936 over old cap). Receipt: [static size measurements](https://git.kayg.org/attachments/2ae85b43-1462-485b-baa1-607805de581a).
Author
Owner

Finished #239 at head cafd6d55d8 on cli-r3-fixes; pushed. The final fast run passed every row except the static size row, which retains the branch's existing cap overage. Against merge base 69026ea29, stripped sizes grew x86_64 by 320 bytes and aarch64 by 256 bytes. x86_64 is +16,384 bytes over the old cap, within the brief's accepted ~16 KiB; aarch64 is +16,936 bytes over its old cap. Full output: verify-fast-final.log.

Static size output (verbatim):
PT_INTERP: absent; size: 21344080 bytes; cap: 21327696 bytes; delta: +16384 bytes
binary exceeds the 21327696-byte size budget: 21344080 bytes
PT_INTERP: absent; size: 19544656 bytes; cap: 19527720 bytes; delta: +16936 bytes
binary exceeds the 19527720-byte size budget: 19544656 bytes

Final Rust gate table (verbatim):
+---------------------------+--------------+
| Rust gate | Result |
+---------------------------+--------------+
| fmt | PASS |
| VT native fmt | PASS |
| CLI plugin compile-out | PASS |
| clippy | PASS |
| test | PASS |
| cargo-deny | PASS |
| static builds | FAIL (1) |
+---------------------------+--------------+

Finished #239 at head cafd6d55d87cb59c1ef74c9d979f0cc984d63ab8 on cli-r3-fixes; pushed. The final fast run passed every row except the static size row, which retains the branch's existing cap overage. Against merge base 69026ea29, stripped sizes grew x86_64 by 320 bytes and aarch64 by 256 bytes. x86_64 is +16,384 bytes over the old cap, within the brief's accepted ~16 KiB; aarch64 is +16,936 bytes over its old cap. Full output: [verify-fast-final.log](https://git.kayg.org/attachments/58187e26-e9e2-4161-a9b4-f638875ee812). Static size output (verbatim): PT_INTERP: absent; size: 21344080 bytes; cap: 21327696 bytes; delta: +16384 bytes binary exceeds the 21327696-byte size budget: 21344080 bytes PT_INTERP: absent; size: 19544656 bytes; cap: 19527720 bytes; delta: +16936 bytes binary exceeds the 19527720-byte size budget: 19544656 bytes Final Rust gate table (verbatim): +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | test | PASS | | cargo-deny | PASS | | static builds | FAIL (1) | +---------------------------+--------------+
Author
Owner

Starting release-4 integration on branch release-4 at base 5b2a1b9ee3. Read the full #239 and #237 histories, and the related #236/#201 mesh history. Next: merge reviewed mesh-view-truth 13e2149fd, then confirm and merge completed cli-r3-fixes cafd6d55d; no deploy or push.

Starting release-4 integration on branch release-4 at base 5b2a1b9ee32b37433a3a2ba1430973e9fc2b317d. Read the full #239 and #237 histories, and the related #236/#201 mesh history. Next: merge reviewed mesh-view-truth 13e2149fd, then confirm and merge completed cli-r3-fixes cafd6d55d; no deploy or push.
Author
Owner

Release-4 integration stopped before merging #239, following the task's x86 size guard. Current head is f4d3dca381cc67dc69da2ea86f72ea21291bcf54 (the #236 mesh merge). Same-recipe x86_64 static build is 21,170,512 bytes against the 21,096,144 release-prod-live base: +74,368 bytes, 34,368 above the ~+40 KB stop threshold. origin/cli-r3-fixes (cafd6d55d) remains unmerged. No artifacts, staging, or final fast gate were run after stopping.

Size table and hashes: size-stop-after-mesh.txt. Raw build: mesh-size-x86-build.log.

Release-4 integration stopped before merging #239, following the task's x86 size guard. Current head is `f4d3dca381cc67dc69da2ea86f72ea21291bcf54` (the #236 mesh merge). Same-recipe x86_64 static build is 21,170,512 bytes against the 21,096,144 release-prod-live base: +74,368 bytes, 34,368 above the ~+40 KB stop threshold. `origin/cli-r3-fixes` (`cafd6d55d`) remains unmerged. No artifacts, staging, or final fast gate were run after stopping. Size table and hashes: [size-stop-after-mesh.txt](https://git.kayg.org/attachments/93b91bb8-fe48-4a5f-b3dd-93fad00b1c16). Raw build: [mesh-size-x86-build.log](https://git.kayg.org/attachments/d732ff91-11d3-4624-a3ce-cb1dd1ab8fcb).
Author
Owner

Release-4 stopped before the #239 merge at the explicit x86 size guard. Current branch head: f4d3dca381cc67dc69da2ea86f72ea21291bcf54.

origin/mesh-view-truth 13e2149fd is merged as f4d3dca38. Finished CLI head origin/cli-r3-fixes cafd6d55d remains unmerged: after #236 the measured x86 artifact is 21,170,512 bytes vs 21,096,144 at release-prod-live, a +74,368-byte increase, which exceeds the ~40 KB stop threshold by 34,368 bytes.

State x86_64 static bytes Delta from base aarch64 static bytes
release-prod-live 5b2a1b9ee 21,096,144 cap/artifact 0 19,325,520 cap/artifact
after #236 21,170,512 +74,368 Not built
after #239 Not merged — Not measured
final Not reached — Not measured

Only the intermediate x86 binary was built: stripped static PIE, PT_INTERP absent, SHA256 42d7332527b6a1c2d0f501d6d83c6a7f83710f853adde2b3d43baf224698b243. ARM, package bundle, web dist and final manifest were not produced. Staging and staged CLI checks were not run. scripts/verify iterate passed; scripts/verify fast was not run after the mandated stop. Rust gate table:

+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| test                      | PASS         |
| cargo-deny                | PASS         |
+---------------------------+--------------+

TypeScript: 37 pass, 0 fail, 34463 expect() calls, Ran 37 tests across 10 files. [2.88s].

Evidence: size table, x86 build log, iteration gate.

Release-4 stopped before the #239 merge at the explicit x86 size guard. Current branch head: `f4d3dca381cc67dc69da2ea86f72ea21291bcf54`. `origin/mesh-view-truth` 13e2149fd is merged as f4d3dca38. Finished CLI head `origin/cli-r3-fixes` cafd6d55d remains unmerged: after #236 the measured x86 artifact is 21,170,512 bytes vs 21,096,144 at release-prod-live, a +74,368-byte increase, which exceeds the ~40 KB stop threshold by 34,368 bytes. | State | x86_64 static bytes | Delta from base | aarch64 static bytes | | --- | ---: | ---: | ---: | | release-prod-live 5b2a1b9ee | 21,096,144 cap/artifact | 0 | 19,325,520 cap/artifact | | after #236 | 21,170,512 | +74,368 | Not built | | after #239 | Not merged | — | Not measured | | final | Not reached | — | Not measured | Only the intermediate x86 binary was built: stripped static PIE, PT_INTERP absent, SHA256 `42d7332527b6a1c2d0f501d6d83c6a7f83710f853adde2b3d43baf224698b243`. ARM, package bundle, web dist and final manifest were not produced. Staging and staged CLI checks were not run. `scripts/verify iterate` passed; `scripts/verify fast` was not run after the mandated stop. Rust gate table: ``` +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | test | PASS | | cargo-deny | PASS | +---------------------------+--------------+ ``` TypeScript: `37 pass`, `0 fail`, `34463 expect() calls`, `Ran 37 tests across 10 files. [2.88s]`. Evidence: [size table](https://git.kayg.org/attachments/93b91bb8-fe48-4a5f-b3dd-93fad00b1c16), [x86 build log](https://git.kayg.org/attachments/d732ff91-11d3-4624-a3ce-cb1dd1ab8fcb), [iteration gate](https://git.kayg.org/attachments/96b6b5f5-c744-4808-9cec-e7f99f69aaf5).
Author
Owner

Starting release-4 integration on branch release-4, base 5b2a1b9ee32b37433a3a2ba1430973e9fc2b317d (origin/release-prod-live). Reset the rejected Mesh merge; origin/cli-r3-fixes is cafd6d55d and has no mesh-view-truth ancestor. Read all #239 comments and the related #237 thread; #239 has no linked parent.

Starting release-4 integration on branch `release-4`, base `5b2a1b9ee32b37433a3a2ba1430973e9fc2b317d` (`origin/release-prod-live`). Reset the rejected Mesh merge; `origin/cli-r3-fixes` is `cafd6d55d` and has no `mesh-view-truth` ancestor. Read all #239 comments and the related #237 thread; #239 has no linked parent.
Author
Owner

Three-way merge preview found conflicts in Cargo.toml, crates/infraternal/src/component_cli.rs, and scripts/verify.d/rust.sh. origin/cli-r3-fixes has no mesh-view-truth ancestor. Resolution keeps both production session and CLI status crates, combines the shared-reactor path with CLI runtime-directory diagnostics, and will set both size caps from measured release artifacts. Added owner-approved D303–D305 text verbatim from origin/dev; excluded unrelated D300–D302 and Mesh-view code.

Three-way merge preview found conflicts in `Cargo.toml`, `crates/infraternal/src/component_cli.rs`, and `scripts/verify.d/rust.sh`. `origin/cli-r3-fixes` has no `mesh-view-truth` ancestor. Resolution keeps both production session and CLI status crates, combines the shared-reactor path with CLI runtime-directory diagnostics, and will set both size caps from measured release artifacts. Added owner-approved D303–D305 text verbatim from `origin/dev`; excluded unrelated D300–D302 and Mesh-view code.
Author
Owner

iterate stopped at the artifact gate before Rust/TypeScript checks: appending D303–D305 grew DECISIONS.md from the release base's 209,359 bytes to 211,526 bytes, above the 200,000-byte changed-source limit. Restored the owner decision file to the release base (209,359 bytes); D303–D305 remain authoritative on origin/dev and are referenced by the CLI changes. The first iterate output is retained in scratch evidence; rerunning after this correction.

`iterate` stopped at the artifact gate before Rust/TypeScript checks: appending D303–D305 grew `DECISIONS.md` from the release base's 209,359 bytes to 211,526 bytes, above the 200,000-byte changed-source limit. Restored the owner decision file to the release base (209,359 bytes); D303–D305 remain authoritative on `origin/dev` and are referenced by the CLI changes. The first iterate output is retained in scratch evidence; rerunning after this correction.
Author
Owner

The corrected iterate run passed artifact, deployment, fmt, VT fmt, CLI compile-out, clippy and cargo-deny. Its test row failed only in crates/plugins/ssh/tests/previous_attempt_shell.rs: the Python shell oracle raised KeyError: INFRATERAL_TEST_RUNTIME_HELPER. The static musl helper exists at $HOME/.cache/codex-scratch/release-4/target/x86_64-unknown-linux-musl/debug/examples/recovery-helper; the gate log is evidence/verify-iterate-rerun.log. Checking test environment propagation before rerunning.

The corrected `iterate` run passed artifact, deployment, fmt, VT fmt, CLI compile-out, clippy and cargo-deny. Its test row failed only in `crates/plugins/ssh/tests/previous_attempt_shell.rs`: the Python shell oracle raised `KeyError: INFRATERAL_TEST_RUNTIME_HELPER`. The static musl helper exists at `$HOME/.cache/codex-scratch/release-4/target/x86_64-unknown-linux-musl/debug/examples/recovery-helper`; the gate log is `evidence/verify-iterate-rerun.log`. Checking test environment propagation before rerunning.
Author
Owner

Correction: the shell oracle expects INFRATERNAL_TEST_RUNTIME_HELPER (with the n in infraternal). I supplied the misspelled INFRATERAL_TEST_RUNTIME_HELPER, so this was job environment setup, not a product failure. The static helper is built; rerunning the affected SSH suite with the correct variable, then the final full gate.

Correction: the shell oracle expects `INFRATERNAL_TEST_RUNTIME_HELPER` (with the `n` in `infraternal`). I supplied the misspelled `INFRATERAL_TEST_RUNTIME_HELPER`, so this was job environment setup, not a product failure. The static helper is built; rerunning the affected SSH suite with the correct variable, then the final full gate.
Author
Owner

With INFRATERNAL_TEST_RUNTIME_HELPER set to the built static musl helper, cargo test --locked -p infraternal-plugin-ssh --test previous_attempt_shell passes (1/1; 4.45 s). The earlier test-row failure was the variable-name typo only. Receipt: evidence/ssh-shell-helper-env.log.

With `INFRATERNAL_TEST_RUNTIME_HELPER` set to the built static musl helper, `cargo test --locked -p infraternal-plugin-ssh --test previous_attempt_shell` passes (1/1; 4.45 s). The earlier test-row failure was the variable-name typo only. Receipt: `evidence/ssh-shell-helper-env.log`.
Author
Owner

Stopped at the x86 size guard. The stripped static artifact from the same recipe is 21,144,112 bytes versus the release-prod-live artifact/cap of 21,096,144 bytes: +47,968 B (+46.84 KiB), 23,392 B above the +24 KiB stop threshold. Base SHA256 aacc763dcffd8cfa3b7f9b56bec7ea8a4a7a179fe833df0fb157249dacce02a9; merged-tree SHA256 c821a30a063b982c813ce7e5ca61eee7ee5f21e4f3bff29c95eb5c2f2ca193b1. Both are stripped static PIEs with no PT_INTERP.

Section/segment breakdown: .text +41,536 B; .gcc_except_table +1,920 B; .eh_frame +968 B; .eh_frame_hdr +384 B; .data.rel.ro +736 B; .relr.dyn +16 B; .got +8 B; .data +32 B; .rodata and .bss unchanged. Segment deltas: first read-only LOAD +5,632 B (3,288 B section growth plus 2,344 B layout/padding), executable LOAD +41,536 B, relro LOAD +744 B, writable-segment gap +24 B, data LOAD +32 B. cargo bloat --crates on the symbol-preserving branch build reports 344.4 KiB for infraternal, 16.1 KiB for infraternal_status, and 74.9 KiB for infraternal_plugin_api (absolute approximate sizes, not deltas). Full receipt: size breakdown, cargo-bloat output, static build log.

iterate passed the artifact, deployment, fmt, VT fmt, CLI compile-out, clippy and cargo-deny rows. Its test row failed only because this run set the misspelled helper variable; with the corrected INFRATERNAL_TEST_RUNTIME_HELPER, the affected SSH oracle passed 1/1 (failing iterate log, focused pass). The full gate was not rerun after that environment correction.

No aarch64 size, package artifacts, staging, final scripts/verify fast, or push was performed after crossing the guard. Caps remain at the production values. Mesh-view files are absent. Worktree remains on release-4 at HEAD 5b2a1b9ee32b37433a3a2ba1430973e9fc2b317d with the resolved CLI merge staged (MERGE_HEAD=cafd6d55d87cb59c1ef74c9d979f0cc984d63ab8); there is no merge commit.

Stopped at the x86 size guard. The stripped static artifact from the same recipe is 21,144,112 bytes versus the `release-prod-live` artifact/cap of 21,096,144 bytes: **+47,968 B (+46.84 KiB), 23,392 B above the +24 KiB stop threshold**. Base SHA256 `aacc763dcffd8cfa3b7f9b56bec7ea8a4a7a179fe833df0fb157249dacce02a9`; merged-tree SHA256 `c821a30a063b982c813ce7e5ca61eee7ee5f21e4f3bff29c95eb5c2f2ca193b1`. Both are stripped static PIEs with no PT_INTERP. Section/segment breakdown: `.text` +41,536 B; `.gcc_except_table` +1,920 B; `.eh_frame` +968 B; `.eh_frame_hdr` +384 B; `.data.rel.ro` +736 B; `.relr.dyn` +16 B; `.got` +8 B; `.data` +32 B; `.rodata` and `.bss` unchanged. Segment deltas: first read-only LOAD +5,632 B (3,288 B section growth plus 2,344 B layout/padding), executable LOAD +41,536 B, relro LOAD +744 B, writable-segment gap +24 B, data LOAD +32 B. `cargo bloat --crates` on the symbol-preserving branch build reports 344.4 KiB for `infraternal`, 16.1 KiB for `infraternal_status`, and 74.9 KiB for `infraternal_plugin_api` (absolute approximate sizes, not deltas). Full receipt: [size breakdown](https://git.kayg.org/attachments/8c957a0f-e992-44d7-8a22-226700bbac04), [cargo-bloat output](https://git.kayg.org/attachments/7a166c10-3cf0-41ae-983e-67383d4efa8f), [static build log](https://git.kayg.org/attachments/9b3882e9-097e-455e-a84d-888ae7c62090). `iterate` passed the artifact, deployment, fmt, VT fmt, CLI compile-out, clippy and cargo-deny rows. Its test row failed only because this run set the misspelled helper variable; with the corrected `INFRATERNAL_TEST_RUNTIME_HELPER`, the affected SSH oracle passed 1/1 ([failing iterate log](https://git.kayg.org/attachments/f09c7eb2-917f-450c-be24-58bc4e63f2f3), [focused pass](https://git.kayg.org/attachments/21848431-f0ff-42ee-b0cd-0f2617467a37)). The full gate was not rerun after that environment correction. No aarch64 size, package artifacts, staging, final `scripts/verify fast`, or push was performed after crossing the guard. Caps remain at the production values. Mesh-view files are absent. Worktree remains on `release-4` at HEAD `5b2a1b9ee32b37433a3a2ba1430973e9fc2b317d` with the resolved CLI merge staged (`MERGE_HEAD=cafd6d55d87cb59c1ef74c9d979f0cc984d63ab8`); there is no merge commit.
Author
Owner

Starting release-4 continuation on branch release-4, base 5b2a1b9ee32b37433a3a2ba1430973e9fc2b317d, with origin/cli-r3-fixes (cafd6d55d87cb59c1ef74c9d979f0cc984d63ab8) staged. Read all #239 comments and the related #237 thread; #239 has no parent. I’m verifying the staged tree excludes #236, then will commit, measure both targets, set exact caps, run the final gate and staging checks under the updated +64 KB guard.

Starting release-4 continuation on branch `release-4`, base `5b2a1b9ee32b37433a3a2ba1430973e9fc2b317d`, with `origin/cli-r3-fixes` (`cafd6d55d87cb59c1ef74c9d979f0cc984d63ab8`) staged. Read all #239 comments and the related #237 thread; #239 has no parent. I’m verifying the staged tree excludes #236, then will commit, measure both targets, set exact caps, run the final gate and staging checks under the updated +64 KB guard.
Author
Owner

Staged-merge check: origin/cli-r3-fixes contains the #239 CLI commits and #237 status probe; f4d3dca38 (#236) is not an ancestor. The mesh-related edits in the staged diff are CLI action/presentation changes. Prior same-recipe x86_64 measurement for this staged tree is 21,144,112 B, +47,968 B vs release-prod-live, within the updated +64 KB stop rule. I’m proceeding with the approved D243 exception; the accepted reason is the versioned --json envelope and D299/D303/D304/D305 exit behavior on every command, including #237’s status extraction (+17 KB).

Staged-merge check: `origin/cli-r3-fixes` contains the #239 CLI commits and #237 status probe; `f4d3dca38` (#236) is not an ancestor. The mesh-related edits in the staged diff are CLI action/presentation changes. Prior same-recipe x86_64 measurement for this staged tree is 21,144,112 B, +47,968 B vs release-prod-live, within the updated +64 KB stop rule. I’m proceeding with the approved D243 exception; the accepted reason is the versioned `--json` envelope and D299/D303/D304/D305 exit behavior on every command, including #237’s status extraction (+17 KB).
Author
Owner

Merge committed as e73772cbdb0409c6d9a403979da77022b2e816da (parents 5b2a1b9ee and cafd6d55d). It integrates #237 status truth and the reviewed #239 CLI work; #236 is absent. The commit records the three conflict resolutions and D243 rationale. x86_64 size remains 21,144,112 B (+47,968 B vs production); next I’m building both static targets to set exact ceilings.

Merge committed as `e73772cbdb0409c6d9a403979da77022b2e816da` (parents `5b2a1b9ee` and `cafd6d55d`). It integrates #237 status truth and the reviewed #239 CLI work; #236 is absent. The commit records the three conflict resolutions and D243 rationale. x86_64 size remains 21,144,112 B (+47,968 B vs production); next I’m building both static targets to set exact ceilings.
Author
Owner

Size finding on e73772cbdb0409c6d9a403979da77022b2e816da, measured on infraternal-dev (x86_64, 12 cores; load at start 3.38 / 5.31 / 6.73) with the pinned Zig static recipe:

Target Bytes Production bytes Delta SHA256
x86_64 21,144,112 21,096,144 +47,968 c821a30a063b982c813ce7e5ca61eee7ee5f21e4f3bff29c95eb5c2f2ca193b1
aarch64 19,370,696 19,325,520 +45,176 6427dd2bf328a3d3f17bbbba1482976ec9a0e3b62c6939c569eb99e7a3377541

Both images are stripped static executables with PT_INTERP absent. Each delta is below the approved +64 KB stop rule. I’ll set both caps to these exact measurements, with D243 rationale recorded in the cap change.

Size finding on `e73772cbdb0409c6d9a403979da77022b2e816da`, measured on `infraternal-dev` (x86_64, 12 cores; load at start 3.38 / 5.31 / 6.73) with the pinned Zig static recipe: | Target | Bytes | Production bytes | Delta | SHA256 | | --- | ---: | ---: | ---: | --- | | x86_64 | 21,144,112 | 21,096,144 | +47,968 | `c821a30a063b982c813ce7e5ca61eee7ee5f21e4f3bff29c95eb5c2f2ca193b1` | | aarch64 | 19,370,696 | 19,325,520 | +45,176 | `6427dd2bf328a3d3f17bbbba1482976ec9a0e3b62c6939c569eb99e7a3377541` | Both images are stripped static executables with `PT_INTERP` absent. Each delta is below the approved +64 KB stop rule. I’ll set both caps to these exact measurements, with D243 rationale recorded in the cap change.
Author
Owner

Finding: scripts/verify iterate on e73772cbd passed artifact, deployment, fmt, VT fmt, CLI compile-out, clippy and cargo-deny, but its test row failed in three infraternal-plugin-ssh/tests/recovery_support.rs cases. Their test hosts were under INFRATERNAL_TEST_STATE_ROOT=/home/kayg/.cache/codex-scratch/r4; the generated Unix socket paths exceeded sun_path (AF_UNIX path too long, lines 2373–2415 in the attached log). This is test-environment setup, not a source failure. I’m rerunning the recovery-support suite and the later full gate with the documented short relative root .codex-r4.

Receipt: verify-iterate-after-merge.log

Finding: `scripts/verify iterate` on `e73772cbd` passed artifact, deployment, fmt, VT fmt, CLI compile-out, clippy and cargo-deny, but its test row failed in three `infraternal-plugin-ssh/tests/recovery_support.rs` cases. Their test hosts were under `INFRATERNAL_TEST_STATE_ROOT=/home/kayg/.cache/codex-scratch/r4`; the generated Unix socket paths exceeded `sun_path` (`AF_UNIX path too long`, lines 2373–2415 in the attached log). This is test-environment setup, not a source failure. I’m rerunning the recovery-support suite and the later full gate with the documented short relative root `.codex-r4`. Receipt: [verify-iterate-after-merge.log](https://git.kayg.org/attachments/8af067c5-df36-4359-ab3f-2376af7a62cd)
Author
Owner

Correction to the test-state finding: the relative root .codex-r4 resolved the sun_path length, but three legacy_control_socket_* fixtures change their working directory and require an absolute home path; they exited before publishing their ready marker (UnexpectedEof, recovery_support.rs:325). The failed focused run is attached: recovery-support-short-root.log. I’m rerunning with /tmp/r4-239, a short absolute symlink to this job’s state directory under /home/kayg/.cache/codex-scratch/release-4/test-state; no test data is written into /tmp.

Correction to the test-state finding: the relative root `.codex-r4` resolved the `sun_path` length, but three `legacy_control_socket_*` fixtures change their working directory and require an absolute home path; they exited before publishing their `ready` marker (`UnexpectedEof`, recovery_support.rs:325). The failed focused run is attached: [recovery-support-short-root.log](https://git.kayg.org/attachments/45ada2bd-9759-4327-8d20-0d6fb2e49f8a). I’m rerunning with `/tmp/r4-239`, a short absolute symlink to this job’s state directory under `/home/kayg/.cache/codex-scratch/release-4/test-state`; no test data is written into `/tmp`.
Author
Owner

Corrected the test-state path and reran the real SSH recovery suite on e73772cbd: 11 passed, 0 failed, 1 ignored (the existing Docker image-dependent review_stale_receipt_recovers_without_host_python case). The short absolute alias /tmp/r4-239 points to the job state directory in codex-scratch; no test data is stored in /tmp. Receipt: recovery-support-short-absolute.log. The final fast run will use this environment.

Corrected the test-state path and reran the real SSH recovery suite on `e73772cbd`: 11 passed, 0 failed, 1 ignored (the existing Docker image-dependent `review_stale_receipt_recovers_without_host_python` case). The short absolute alias `/tmp/r4-239` points to the job state directory in codex-scratch; no test data is stored in `/tmp`. Receipt: [recovery-support-short-absolute.log](https://git.kayg.org/attachments/00fa4027-8736-40b6-8d96-e6b221a42285). The final `fast` run will use this environment.
Author
Owner

Exact-cap change committed as a906ede87 on top of merge e73772cbd. The ceilings now match the measured x86_64 / aarch64 artifacts: 21,144,112 / 19,370,696 bytes (+47,968 / +45,176 vs production). Verification before commit: bash -n scripts/verify.d/rust.sh PASS; git diff --check PASS; CARGO_TARGET_DIR=... python3 scripts/test-static-size.py PASS for exact caps, +1-byte rejection and shrink ratchet on both targets. Next: one full scripts/verify fast on this head.

Exact-cap change committed as `a906ede87` on top of merge `e73772cbd`. The ceilings now match the measured x86_64 / aarch64 artifacts: 21,144,112 / 19,370,696 bytes (+47,968 / +45,176 vs production). Verification before commit: `bash -n scripts/verify.d/rust.sh` PASS; `git diff --check` PASS; `CARGO_TARGET_DIR=... python3 scripts/test-static-size.py` PASS for exact caps, +1-byte rejection and shrink ratchet on both targets. Next: one full `scripts/verify fast` on this head.
Author
Owner

Finding from the first final scripts/verify fast on a906ede87: all rows passed except test (Rust 92 passed / 7 failed / 1 ignored); static builds passed at the exact caps. The seven failures are restart path-trust tests (restart::tests::{cold_exec_with_closed_stdin_keeps_the_image_pinned_and_maps_null,private_path_prefix_cannot_authorize_a_parent_directory_escape,real_fd_exec_pins_replacement_and_cold_rollback_uses_null_stdin,reload_reopens_install_path_when_the_running_inode_was_replaced,rootless_even_marked_replacement_is_cold_and_open_fd_pins_the_inode} and restart_binary::audit_tests::{admitted_inode_cannot_change_in_place_before_execution,pathname_replacement_keeps_the_admitted_inode}). Cause: /tmp/r4-239 resolves through a public /tmp parent; the fixtures correctly reject writable parents, and the escape test follows the resolved path. I’ll rerun the failing target and final gate with a short, private real directory under $HOME/.cache, then remove it. Receipt: verify-fast-final.log

Finding from the first final `scripts/verify fast` on `a906ede87`: all rows passed except `test` (Rust 92 passed / 7 failed / 1 ignored); static builds passed at the exact caps. The seven failures are restart path-trust tests (`restart::tests::{cold_exec_with_closed_stdin_keeps_the_image_pinned_and_maps_null,private_path_prefix_cannot_authorize_a_parent_directory_escape,real_fd_exec_pins_replacement_and_cold_rollback_uses_null_stdin,reload_reopens_install_path_when_the_running_inode_was_replaced,rootless_even_marked_replacement_is_cold_and_open_fd_pins_the_inode}` and `restart_binary::audit_tests::{admitted_inode_cannot_change_in_place_before_execution,pathname_replacement_keeps_the_admitted_inode}`). Cause: `/tmp/r4-239` resolves through a public `/tmp` parent; the fixtures correctly reject writable parents, and the escape test follows the resolved path. I’ll rerun the failing target and final gate with a short, private real directory under `$HOME/.cache`, then remove it. Receipt: [verify-fast-final.log](https://git.kayg.org/attachments/b5588d85-74be-4815-a4a0-c22378e01606)
Author
Owner

Final corrected scripts/verify fast passed on a906ede87110465c08ecde0d811c8eca2cbe08cc. The test root is the real mode-700 /home/kayg/.cache/r4; removing the /tmp symlink fixed the earlier restart fixtures. Workspace summary: 563 passed, 0 failed, 52 ignored; the CLI binary tests passed 99 with 1 ignored. Full log: verify-fast-final-corrected.log.

Rust gate output:

+---------------------------+--------------+
| Rust gate | Result |
+---------------------------+--------------+
| fmt | PASS |
| VT native fmt | PASS |
| CLI plugin compile-out | PASS |
| clippy | PASS |
| test | PASS |
| cargo-deny | PASS |
| static builds | PASS |
+---------------------------+--------------+

Static stripped binaries at caps: x86_64 21,144,112 B / 21,144,112 B (+47,968 B vs production); aarch64 19,370,696 B / 19,370,696 B (+45,176 B vs production). Both are static with no PT_INTERP; x86 key-memory check passed. These deltas are within the recorded D243 acceptance band.

Final corrected `scripts/verify fast` passed on `a906ede87110465c08ecde0d811c8eca2cbe08cc`. The test root is the real mode-700 `/home/kayg/.cache/r4`; removing the `/tmp` symlink fixed the earlier restart fixtures. Workspace summary: 563 passed, 0 failed, 52 ignored; the CLI binary tests passed 99 with 1 ignored. Full log: [verify-fast-final-corrected.log](https://git.kayg.org/attachments/e25c93b3-38c6-49c7-a13b-2e1d75e06ad7). Rust gate output: +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | test | PASS | | cargo-deny | PASS | | static builds | PASS | +---------------------------+--------------+ Static stripped binaries at caps: x86_64 21,144,112 B / 21,144,112 B (+47,968 B vs production); aarch64 19,370,696 B / 19,370,696 B (+45,176 B vs production). Both are static with no PT_INTERP; x86 key-memory check passed. These deltas are within the recorded D243 acceptance band.
Author
Owner

Release artifacts are complete under /home/kayg/.cache/codex-scratch/release-4/artifacts. scripts/package-release produced the bundle; all five bundle entries and all 265 web files passed checksum verification. web-dist.tar contains index.html. Artifact build and transfer-budget receipt: artifacts-build.log.

Artifact Bytes SHA-256
infraternal-x86_64-musl 21,144,112 c821a30a063b982c813ce7e5ca61eee7ee5f21e4f3bff29c95eb5c2f2ca193b1
infraternal-aarch64-musl 19,370,696 6427dd2bf328a3d3f17bbbba1482976ec9a0e3b62c6939c569eb99e7a3377541
web-dist.tar 3,624,960 5e46109dd6b3bf9f2e78aa8a74f9cf346b49539b96d8792864fc6a760d7d9dc1
web-SHA256SUMS — c97cfa4140158a01ef94b6da5fb8b9226c1eb42a0896b4ac2b4b4678e459bee7
bundle/SHA256SUMS 456 b017b06870cd24332b95c7844a88befdb6aa0855bad5abfb1049fe0fbc9635db
bundle/infraternal 21,144,112 c821a30a063b982c813ce7e5ca61eee7ee5f21e4f3bff29c95eb5c2f2ca193b1
bundle/infraternal-aarch64-musl 9,542,168 9c4847b50c07700727809b76b91ca4050d9b1f987c11698315f6f1b4bb8287c0
bundle/infraternal-aarch64-session-musl 1,632,544 5489f111cc722950875a92784f8ac6ca0b97d5c241d1cd75e4b9054c41a82209
bundle/infraternal-x86_64-musl 10,142,528 482484296bc552b3187b31924ecbc8edccb0ffe2c32cd52434f5f2eafa5f39ae
bundle/infraternal-x86_64-session-musl 1,869,544 0f357e9f573aaff647d7521eb22483f6b6a807f0967c0fb58656175a61d171e9
Release artifacts are complete under `/home/kayg/.cache/codex-scratch/release-4/artifacts`. `scripts/package-release` produced the bundle; all five bundle entries and all 265 web files passed checksum verification. `web-dist.tar` contains `index.html`. Artifact build and transfer-budget receipt: [artifacts-build.log](https://git.kayg.org/attachments/6a6f84da-8b7e-44d8-9876-03f2255b038d). | Artifact | Bytes | SHA-256 | |---|---:|---| | `infraternal-x86_64-musl` | 21,144,112 | `c821a30a063b982c813ce7e5ca61eee7ee5f21e4f3bff29c95eb5c2f2ca193b1` | | `infraternal-aarch64-musl` | 19,370,696 | `6427dd2bf328a3d3f17bbbba1482976ec9a0e3b62c6939c569eb99e7a3377541` | | `web-dist.tar` | 3,624,960 | `5e46109dd6b3bf9f2e78aa8a74f9cf346b49539b96d8792864fc6a760d7d9dc1` | | `web-SHA256SUMS` | — | `c97cfa4140158a01ef94b6da5fb8b9226c1eb42a0896b4ac2b4b4678e459bee7` | | `bundle/SHA256SUMS` | 456 | `b017b06870cd24332b95c7844a88befdb6aa0855bad5abfb1049fe0fbc9635db` | | `bundle/infraternal` | 21,144,112 | `c821a30a063b982c813ce7e5ca61eee7ee5f21e4f3bff29c95eb5c2f2ca193b1` | | `bundle/infraternal-aarch64-musl` | 9,542,168 | `9c4847b50c07700727809b76b91ca4050d9b1f987c11698315f6f1b4bb8287c0` | | `bundle/infraternal-aarch64-session-musl` | 1,632,544 | `5489f111cc722950875a92784f8ac6ca0b97d5c241d1cd75e4b9054c41a82209` | | `bundle/infraternal-x86_64-musl` | 10,142,528 | `482484296bc552b3187b31924ecbc8edccb0ffe2c32cd52434f5f2eafa5f39ae` | | `bundle/infraternal-x86_64-session-musl` | 1,869,544 | `0f357e9f573aaff647d7521eb22483f6b6a807f0967c0fb58656175a61d171e9` |
Author
Owner

Pushed release-4 to origin at a906ede87110465c08ecde0d811c8eca2cbe08cc; git ls-remote confirms the remote head. The branch has only the #239/#237 merge and size-cap ratchet as first-parent commits after the production base; #236 is not an ancestor.

Pushed `release-4` to `origin` at `a906ede87110465c08ecde0d811c8eca2cbe08cc`; `git ls-remote` confirms the remote head. The branch has only the #239/#237 merge and size-cap ratchet as first-parent commits after the production base; #236 is not an ancestor.
Author
Owner

Signed staging proof passed on infraternal-perf-test (kernel 6.12.111+deb13-amd64). Both named tests passed: signed deploy/handoff and browser-service probes. The proof retained 128 PTY sessions and 6 browser connections; refusal before shutdown and automatic rollback both passed, backup integrity was true, and the CA remained unlocked. It recorded 12 handoffs at 10,000 nodes / 50 users: listener-gap bracket p50 3,949.544 ms, p99 4,025.569 ms; server RSS 22,048,768 B, CPU 7.398% of one core. Load average was 0.52 0.72 0.47 before and 1.77 0.99 0.58 after. Lock released and unique remote directory removed. Full receipt: staging-proof.log.

Signed staging proof passed on `infraternal-perf-test` (kernel `6.12.111+deb13-amd64`). Both named tests passed: signed deploy/handoff and browser-service probes. The proof retained 128 PTY sessions and 6 browser connections; refusal before shutdown and automatic rollback both passed, backup integrity was `true`, and the CA remained unlocked. It recorded 12 handoffs at 10,000 nodes / 50 users: listener-gap bracket p50 3,949.544 ms, p99 4,025.569 ms; server RSS 22,048,768 B, CPU 7.398% of one core. Load average was `0.52 0.72 0.47` before and `1.77 0.99 0.58` after. Lock released and unique remote directory removed. Full receipt: [staging-proof.log](https://git.kayg.org/attachments/934b9232-4de4-45f5-b6d2-280af72856f8).
Author
Owner

Docker add-host preflight caught a scratch archive layout mismatch before starting a container or measurement: the first extraction had one extra repo/ level and the expected runner was absent. I removed only that unstarted per-job directory, corrected the archive root, and verified the live test listing plus payload sizes/hashes before starting the run. Receipts: failed preflight, corrected preflight.

Docker add-host preflight caught a scratch archive layout mismatch before starting a container or measurement: the first extraction had one extra `repo/` level and the expected runner was absent. I removed only that unstarted per-job directory, corrected the archive root, and verified the live test listing plus payload sizes/hashes before starting the run. Receipts: [failed preflight](https://git.kayg.org/attachments/abfada19-71d2-4e5f-9f1c-6c1382897e4b), [corrected preflight](https://git.kayg.org/attachments/783c4d54-6a0e-4afa-831e-080af20605e8).
Author
Owner

The first Docker add-host invocation stopped during argument parsing: the single-case measure.py runner does not accept the matrix flags --samples and --venues. It started no container or add-host test; the locked scope released and cleanup confirmed the unique container and scratch directory were absent. I’m rerunning the same one-case flow without those flags. Receipt: addhost-docker-argument-preflight.log.

The first Docker add-host invocation stopped during argument parsing: the single-case `measure.py` runner does not accept the matrix flags `--samples` and `--venues`. It started no container or add-host test; the locked scope released and cleanup confirmed the unique container and scratch directory were absent. I’m rerunning the same one-case flow without those flags. Receipt: [addhost-docker-argument-preflight.log](https://git.kayg.org/attachments/9da5621b-90b1-46dd-bfe6-a36361603b17).
Author
Owner

The next locked-scope preflight found the staged fixture files absent because the earlier parser-only run’s cleanup trap correctly removed its entire remote scratch tree. measure.py was not found, so no container or test started; cleanup confirmed the tree absent. I’m combining upload, checksum preflight and the single-case measurement in one wrapped run. Receipt: addhost-docker-missing-files.log.

The next locked-scope preflight found the staged fixture files absent because the earlier parser-only run’s cleanup trap correctly removed its entire remote scratch tree. `measure.py` was not found, so no container or test started; cleanup confirmed the tree absent. I’m combining upload, checksum preflight and the single-case measurement in one wrapped run. Receipt: [addhost-docker-missing-files.log](https://git.kayg.org/attachments/43b84533-50af-4e42-8656-4e8c715f5f58).
Author
Owner

Docker SSH add-host acceptance passed on infraternal-perf-test (4 cores), under systemd-run --scope -p CPUWeight=10000 and the shared lock. The clean instant add reached the interactive prompt in 318.153 ms and fully joined in 1,179.241 ms; the repeat was refused as already added in 279 ms with the matching host id, then opened the named terminal. Result: 1 passed, 0 failed. Load average was 0.00 0.21 0.37 before and 0.30 0.27 0.39 after. The exact Docker container and remote scratch tree are absent, the transient scope is inactive, and fixture listeners on 4929/4930 are gone. Receipts: addhost-docker-perf.log, cleanup verification.

Docker SSH add-host acceptance passed on `infraternal-perf-test` (4 cores), under `systemd-run --scope -p CPUWeight=10000` and the shared lock. The clean instant add reached the interactive prompt in 318.153 ms and fully joined in 1,179.241 ms; the repeat was refused as already added in 279 ms with the matching host id, then opened the named terminal. Result: 1 passed, 0 failed. Load average was `0.00 0.21 0.37` before and `0.30 0.27 0.39` after. The exact Docker container and remote scratch tree are absent, the transient scope is inactive, and fixture listeners on 4929/4930 are gone. Receipts: [addhost-docker-perf.log](https://git.kayg.org/attachments/9291d83b-24b0-4638-86e3-2e3311357fe3), [cleanup verification](https://git.kayg.org/attachments/ea8f6efd-0465-4358-81cb-dee7e6488f66).
Author
Owner

Staged x86_64 release binary CLI smoke completed at a906ede87110465c08ecde0d811c8eca2cbe08cc. Against the staged binary on the perf VM with isolated HOME/state, all six commands emitted exactly one schema-v1 JSON envelope and returned the expected D303/D305 result: status --json 0; mesh peers --json 5 (unreachable, no agent socket); unknown command 2 (usage); Ctrl-C in JSON mode 130 (interrupted); Ctrl-C in a shell loop 130 and the loop stopped; skill server init --json under nohup with inherited SIGINT ignored completed with 0. The status envelope reported this isolated VM is not set up; no service was installed or changed. Cleanup trap and independent check both confirmed the exact scratch path absent and no CLI process remained.

Receipts: CLI smoke, cleanup.

Staged x86_64 release binary CLI smoke completed at `a906ede87110465c08ecde0d811c8eca2cbe08cc`. Against the staged binary on the perf VM with isolated HOME/state, all six commands emitted exactly one schema-v1 JSON envelope and returned the expected D303/D305 result: `status --json` 0; `mesh peers --json` 5 (`unreachable`, no agent socket); unknown command 2 (`usage`); Ctrl-C in JSON mode 130 (`interrupted`); Ctrl-C in a shell loop 130 and the loop stopped; `skill server init --json` under `nohup` with inherited SIGINT ignored completed with 0. The status envelope reported this isolated VM is not set up; no service was installed or changed. Cleanup trap and independent check both confirmed the exact scratch path absent and no CLI process remained. Receipts: [CLI smoke](https://git.kayg.org/attachments/21829a1d-5f69-4b6d-bf8c-ec29c2202bb0), [cleanup](https://git.kayg.org/attachments/3f9f7aa2-8684-4ffa-ad14-643228a150c9).
Author
Owner

Release 4 staging is complete. Branch release-4 is pushed at a906ede87110465c08ecde0d811c8eca2cbe08cc; remote refs/heads/release-4 matches. The merge is based on 5b2a1b9ee32b37433a3a2ba1430973e9fc2b317d; only the CLI #239/#237 merge and size-cap ratchet follow it. Mesh view #236 is not an ancestor. No deployment was performed.

Static sizes

Target Release bytes Production bytes Growth Cap Headroom
x86_64-musl 21,144,112 21,096,144 +47,968 21,144,112 0
aarch64-musl 19,370,696 19,325,520 +45,176 19,370,696 0

Both are statically linked, stripped, and have no PT_INTERP. The accepted D243 band is 16–64 KB; both sizes are within it. ARM runtime key-memory verification was unavailable on this x86_64 host.

Artifact SHA-256

All artifacts are under /home/kayg/.cache/codex-scratch/release-4/artifacts. The bundle checksum file and all 265 web files verified; web/index.html is present.

Artifact Bytes SHA-256
MANIFEST.txt 1,244 d632d5844eb4b508bd1335614e1c877b9f5883d71546838227c187372d4938f7
infraternal-x86_64-musl 21,144,112 c821a30a063b982c813ce7e5ca61eee7ee5f21e4f3bff29c95eb5c2f2ca193b1
infraternal-aarch64-musl 19,370,696 6427dd2bf328a3d3f17bbbba1482976ec9a0e3b62c6939c569eb99e7a3377541
web-dist.tar 3,624,960 5e46109dd6b3bf9f2e78aa8a74f9cf346b49539b96d8792864fc6a760d7d9dc1
web-SHA256SUMS 23,714 c97cfa4140158a01ef94b6da5fb8b9226c1eb42a0896b4ac2b4b4678e459bee7
bundle/SHA256SUMS 456 b017b06870cd24332b95c7844a88befdb6aa0855bad5abfb1049fe0fbc9635db
bundle/infraternal 21,144,112 c821a30a063b982c813ce7e5ca61eee7ee5f21e4f3bff29c95eb5c2f2ca193b1
bundle/infraternal-aarch64-musl 9,542,168 9c4847b50c07700727809b76b91ca4050d9b1f987c11698315f6f1b4bb8287c0
bundle/infraternal-aarch64-session-musl 1,632,544 5489f111cc722950875a92784f8ac6ca0b97d5c241d1cd75e4b9054c41a82209
bundle/infraternal-x86_64-musl 10,142,528 482484296bc552b3187b31924ecbc8edccb0ffe2c32cd52434f5f2eafa5f39ae
bundle/infraternal-x86_64-session-musl 1,869,544 0f357e9f573aaff647d7521eb22483f6b6a807f0967c0fb58656175a61d171e9

Staging

  • Signed handoff on infraternal-perf-test (4 vCPU, 7 GB): 10,000 nodes, 50 users, 128 real PTYs, 6 responsive browser connections, 12 handoffs. Listener gap bracket p50 3,949.544 ms / p99 4,025.569 ms; idle server CPU 7.398% of one core and RSS 22,048,768 B. All 128 sessions survived with input/output resumed; refusal-before-shutdown, automatic rollback, backup integrity (10,000 nodes/50 users), and CA unlock passed. Load average before/after: 0.52 0.72 0.47 / 1.77 0.99 0.58. Measurement lock released and test directory removed.
  • Docker SSH add-host: clean add reached prompt in 318.153 ms and fully joined in 1,179.241 ms; already-added was refused in 279 ms with matching host ID, and its terminal opened. Test 1/1 passed. Load average before/in/after: 0.00 0.21 0.37 / 0.24 0.26 0.38 / 0.30 0.27 0.39. Container, scratch, transient scope, and fixture listeners were removed.
  • CLI against the staged x86_64 binary on the perf VM, isolated HOME/state: all six cases emitted one schema-v1 JSON envelope. status --json exit 0; mesh peers --json exit 5 (unreachable, absent local agent socket); usage error exit 2; Ctrl-C with JSON exit 130 (interrupted); Ctrl-C in a shell loop exit 130 and the loop stopped; skill server init --json under nohup with inherited SIGINT ignored exit 0. The isolated host status was “not set up”; no service was installed or changed. Cleanup trap and independent check found no remaining process or scratch directory.

Receipts: artifact build and checksums, signed handoff proof, Docker add-host run, Docker cleanup, CLI smoke, CLI cleanup.

Final scripts/verify fast

+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| test                      | PASS         |
| cargo-deny                | PASS         |
| static builds             | PASS         |
+---------------------------+--------------+

Test summary: test result: ok. 563 passed; 0 failed; 52 ignored; 0 measured; 0 filtered out. Both static targets met their exact caps; x86_64 key-memory check passed.

Self-review covered the D299 one-envelope contract, D303 exit mapping, D305 shell-loop signal behavior, size caps and checksums, staging cleanup, and release scope. No new foundational dependency or UI change was introduced.

Release 4 staging is complete. Branch `release-4` is pushed at `a906ede87110465c08ecde0d811c8eca2cbe08cc`; remote `refs/heads/release-4` matches. The merge is based on `5b2a1b9ee32b37433a3a2ba1430973e9fc2b317d`; only the CLI #239/#237 merge and size-cap ratchet follow it. Mesh view #236 is not an ancestor. No deployment was performed. ### Static sizes | Target | Release bytes | Production bytes | Growth | Cap | Headroom | |---|---:|---:|---:|---:|---:| | x86_64-musl | 21,144,112 | 21,096,144 | +47,968 | 21,144,112 | 0 | | aarch64-musl | 19,370,696 | 19,325,520 | +45,176 | 19,370,696 | 0 | Both are statically linked, stripped, and have no `PT_INTERP`. The accepted D243 band is 16–64 KB; both sizes are within it. ARM runtime key-memory verification was unavailable on this x86_64 host. ### Artifact SHA-256 All artifacts are under `/home/kayg/.cache/codex-scratch/release-4/artifacts`. The bundle checksum file and all 265 web files verified; `web/index.html` is present. | Artifact | Bytes | SHA-256 | |---|---:|---| | `MANIFEST.txt` | 1,244 | `d632d5844eb4b508bd1335614e1c877b9f5883d71546838227c187372d4938f7` | | `infraternal-x86_64-musl` | 21,144,112 | `c821a30a063b982c813ce7e5ca61eee7ee5f21e4f3bff29c95eb5c2f2ca193b1` | | `infraternal-aarch64-musl` | 19,370,696 | `6427dd2bf328a3d3f17bbbba1482976ec9a0e3b62c6939c569eb99e7a3377541` | | `web-dist.tar` | 3,624,960 | `5e46109dd6b3bf9f2e78aa8a74f9cf346b49539b96d8792864fc6a760d7d9dc1` | | `web-SHA256SUMS` | 23,714 | `c97cfa4140158a01ef94b6da5fb8b9226c1eb42a0896b4ac2b4b4678e459bee7` | | `bundle/SHA256SUMS` | 456 | `b017b06870cd24332b95c7844a88befdb6aa0855bad5abfb1049fe0fbc9635db` | | `bundle/infraternal` | 21,144,112 | `c821a30a063b982c813ce7e5ca61eee7ee5f21e4f3bff29c95eb5c2f2ca193b1` | | `bundle/infraternal-aarch64-musl` | 9,542,168 | `9c4847b50c07700727809b76b91ca4050d9b1f987c11698315f6f1b4bb8287c0` | | `bundle/infraternal-aarch64-session-musl` | 1,632,544 | `5489f111cc722950875a92784f8ac6ca0b97d5c241d1cd75e4b9054c41a82209` | | `bundle/infraternal-x86_64-musl` | 10,142,528 | `482484296bc552b3187b31924ecbc8edccb0ffe2c32cd52434f5f2eafa5f39ae` | | `bundle/infraternal-x86_64-session-musl` | 1,869,544 | `0f357e9f573aaff647d7521eb22483f6b6a807f0967c0fb58656175a61d171e9` | ### Staging - Signed handoff on `infraternal-perf-test` (4 vCPU, 7 GB): 10,000 nodes, 50 users, 128 real PTYs, 6 responsive browser connections, 12 handoffs. Listener gap bracket p50 3,949.544 ms / p99 4,025.569 ms; idle server CPU 7.398% of one core and RSS 22,048,768 B. All 128 sessions survived with input/output resumed; refusal-before-shutdown, automatic rollback, backup integrity (10,000 nodes/50 users), and CA unlock passed. Load average before/after: `0.52 0.72 0.47` / `1.77 0.99 0.58`. Measurement lock released and test directory removed. - Docker SSH add-host: clean add reached prompt in 318.153 ms and fully joined in 1,179.241 ms; already-added was refused in 279 ms with matching host ID, and its terminal opened. Test 1/1 passed. Load average before/in/after: `0.00 0.21 0.37` / `0.24 0.26 0.38` / `0.30 0.27 0.39`. Container, scratch, transient scope, and fixture listeners were removed. - CLI against the staged x86_64 binary on the perf VM, isolated HOME/state: all six cases emitted one schema-v1 JSON envelope. `status --json` exit 0; `mesh peers --json` exit 5 (`unreachable`, absent local agent socket); usage error exit 2; Ctrl-C with JSON exit 130 (`interrupted`); Ctrl-C in a shell loop exit 130 and the loop stopped; `skill server init --json` under `nohup` with inherited SIGINT ignored exit 0. The isolated host status was “not set up”; no service was installed or changed. Cleanup trap and independent check found no remaining process or scratch directory. Receipts: [artifact build and checksums](https://git.kayg.org/attachments/6a6f84da-8b7e-44d8-9876-03f2255b038d), [signed handoff proof](https://git.kayg.org/attachments/934b9232-4de4-45f5-b6d2-280af72856f8), [Docker add-host run](https://git.kayg.org/attachments/9291d83b-24b0-4638-86e3-2e3311357fe3), [Docker cleanup](https://git.kayg.org/attachments/ea8f6efd-0465-4358-81cb-dee7e6488f66), [CLI smoke](https://git.kayg.org/attachments/21829a1d-5f69-4b6d-bf8c-ec29c2202bb0), [CLI cleanup](https://git.kayg.org/attachments/3f9f7aa2-8684-4ffa-ad14-643228a150c9). ### Final `scripts/verify fast` ```text +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | test | PASS | | cargo-deny | PASS | | static builds | PASS | +---------------------------+--------------+ ``` Test summary: `test result: ok. 563 passed; 0 failed; 52 ignored; 0 measured; 0 filtered out`. Both static targets met their exact caps; x86_64 key-memory check passed. Self-review covered the D299 one-envelope contract, D303 exit mapping, D305 shell-loop signal behavior, size caps and checksums, staging cleanup, and release scope. No new foundational dependency or UI change was introduced.
Author
Owner

Final artifact recheck: all 265 entries in web-SHA256SUMS verify from the web/ directory. Receipt.

Final artifact recheck: all 265 entries in `web-SHA256SUMS` verify from the `web/` directory. [Receipt](https://git.kayg.org/attachments/a787e92e-4da0-435e-b3cd-27ecd32768c1).
Author
Owner

Release 4 deployed to production at 21:21 IST: release-prod-live a906ede87, server sha256 c821a30a…, /healthz ok. CLI overhaul (#239, #237). CA locked after the restart until the owner unlocks it.

Release 4 deployed to production at 21:21 IST: release-prod-live a906ede87, server sha256 c821a30a…, /healthz ok. CLI overhaul (#239, #237). CA locked after the restart until the owner unlocks it.
Sign in to join this conversation.
No labels
launch-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/infraternal#239
No description provided.