Skip to content

Terminal lane post-merge read: 11 findings repaired (probes end by the signal, spawn guard observed, sweep coverage stated, tmux identity control) - #563

Merged
seathatflowsinourveins merged 1 commit into
mainfrom
claude/terminal-lane-post-merge-read-20260930
Oct 1, 2026
Merged

seathatflowsinourveins merged 1 commit into
mainfrom
claude/terminal-lane-post-merge-read-20260930

Conversation

@seathatflowsinourveins

@seathatflowsinourveins seathatflowsinourveins commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Scope

  • What this PR changes, in one or two sentences: the repairs of a post-merge read of the terminal lane's signal handling and shutdown code (Terminal lane: repairs after the cross-family review (gpt-6.1-sol through the packaged Codex lane on OmniRoute), 46 findings checked, 39 repaired #532, Terminal lane final read: 37 findings repaired (signal latch with per-line sweep, tmux shutdown by identity, complete scan, landscape and colour readers) #552). One read-only Claude Opus agent (effort max, no shell) read the merged code and returned 11 findings (3 medium, 8 low, none high); each was verified by a measurement or by reading before it was repaired: the pty probes now end BY a latched signal instead of exiting 128 plus its number (a shell loop goes on after an exit 130 and stops after a death by SIGINT: measured), the per-line sweep observes the spawn guard and the documents state its real coverage (110 of 160 lines with code for alert_probe.py, 123 of 186 for the push probe), an inherited SIG_IGN stays ignored, typing stops at a latched signal, and a third tmux control only the command-line check of the identity can fail.
  • Base commit: 46365ea8 (origin/main when this head was pushed; the branch was built on 29458b43 and replayed twice on newer mains, the last time under the hot-file protocol of docs/lanes.md because manifests/evidence.json conflicted: main's copy, this branch's two receipt entries and the hashes of its 34 changed files re-registered, the generated reports rebuilt, the validators re-run)
  • Lane: lane:foundation
  • Owned paths touched: evidence/artifacts/{terminal-experience-20260928,notification-types-20260929,terminal-lane-cross-family-review-20260930}/ (the two pty probes, the mutant runner, the two tmux probes, their READMEs, four new scripts, the record of the read, recorded/), evidence/receipts/ (cross-family-review-terminal-lane-20260930 rebuilt, terminal-experience-20260928 corrected), docs/decisions/2026-09-28-terminal-experience.md, docs/harness-defaults.md (three anti-pattern rows, one edited), and manifests/evidence.json with the generated reports (hot-file protocol: main's copy, the two receipt entries and the hashes of the changed files). No Gate A frozen file (settings, hooks, launcher, AGENTS.md, CLAUDE.md) is touched.
  • Outside git: nothing; the practice repository, ~/.claude, ~/.codex and the gateway are unchanged.
  • Authorship: written by a Claude Sonnet 5.5 coordinator session, hence the commit trailer. The reviewer is one Claude Opus evidence-reviewer agent; no GPT read was made (the gateway pool's only usable account read 83 of 100 points and the other five read 100 until 2026-10-03/04, so a read would have taken the pool from the other sessions' running waves).

SOTA sources

  • Martin Cracauer, "Proper handling of SIGINT/SIGQUIT" (cons.org/cracauer/sigint.html, fetched 2026-09-30): a program that catches SIGINT must end by resetting the signal to its default action and sending it to itself; "You cannot fake the proper exit status by an exit(3) with a special numeric value". Measured here with bash 5 in shell_loop_control.py, with a control.
  • Python signal module documentation (docs.python.org/3/library/signal.html, fetched 2026-09-30): SIGINT is translated into KeyboardInterrupt only "if the parent process has not changed it" (the latch now leaves an inherited SIG_IGN alone); the note on signal handlers and exceptions (kept from the earlier round: the handler only latches).
  • CPython's dispatch order of pending signals, measured in signal_order_probe.py (ascending signal number).
  • tmux 3.4 and the Linux /proc interface, as in the earlier rounds (display-message -p '#{pid}', the server's retained command line, the stat start-time field and state).
  • No code was written where a maintained upstream exists: the repaired files are this repository's own probes and checks; the agent, the verifier practice and the merge tool are the existing ones.

Evidence-class table

Claim Evidence class Command / receipt
One read-only Claude Opus agent returned 11 findings (3 medium, 8 low), 236,557 subagent tokens, 27 tool uses, 20 minutes, no gateway pool points native_proven (the client's own subagent record) plus source_review receipt cross-family-review-terminal-lane-20260930 data.post_merge_read; post-merge-read.json
A bash loop went on after a child that exits 130 and stopped after a child that ends BY SIGINT; pending signals run their handlers in ascending number native_proven (bash, CPython, a control per check) recorded/shell_loop_control.txt, recorded/signal_order_probe.txt
The two pty probes pass 8 end-to-end cases and 8 in-process tests each (the probe ends BY the signal: exit -15 and -2; 110 of 160 and 123 of 186 lines swept, 45 and 50 of them up to the spawn guard, no client started there) and 22 mutant runs (11 per probe, each failing exactly its cases: the spawn guard, the exit-status conversion, an ignored signal, typing) plus the 2 unmutated probes pass all 8 cases local_integration (negative controls) recorded/alert_probe_selftest.txt, recorded/push_notification_probe_selftest.txt, recorded/pty_probe_mutants_alert.txt, recorded/pty_probe_mutants_push.txt
The tmux probes' selftests have three shutdown-failure controls; deleting the command-line clause of server_identity used to leave every control green and is now caught (9 checks, 1 problem) local_integration (private tmux server, a mutant) recorded/tmux_bell_probe_selftest.txt, recorded/tmux_sync_probe_selftest.txt, recorded/tmux_identity_mutant_bell.txt, recorded/tmux_identity_mutant_sync.txt
259 unit tests in the five affected modules pass local_integration recorded/unit_tests.txt
An inherited SIG_IGN stays ignored end to end (a probe started with SIGHUP ignored carried on to exit 2; with the default it ended by SIGHUP) ad hoc native run, not recorded (the in-process case and its mutant are) none

Local commands run

$ python3 scripts/validate.py
exit 0: {"components": 69, "hashed_files": 8641, "profiles": 4, "receipts": 177, "status": "passed"} (on the replayed head)
$ python3 scripts/validate_foundation.py ; python3 scripts/component_matrix.py --check ; python3 scripts/new_host_grand_list.py --check
exit 0, 0 and 0
$ python3 -B -m unittest tests.test_adoption_status tests.test_windows_terminal_defaults tests.test_adoption_docs_consistency tests.test_render_config tests.test_apply_claude_settings
Ran 259 tests ... OK (skipped=1)
$ the 35 commands of evidence/artifacts/terminal-lane-cross-family-review-20260930/recorded/exit_codes.txt
exit 0 each (each run alone; the two pty mutant suites, 12 runs and 0 problems each, ran before the rest; Claude Code 2.1.286 was installed meanwhile, so the scans cover 2.1.284, 2.1.285 and 2.1.286 and the 2.1.283 scan is retained from the earlier pass)
$ gitleaks git --pre-commit --staged --redact (the repository's pre-commit hook)
exit 0 on the commit; the first run of this PR failed only `osv-scanner` (an advisory for `litellm 1.93.0` in the OpenHands lane's lock, published 2026-09-30T21:11Z, fixed by #562); the checks were run again on a merge commit that includes #562 and passed, including both macOS jobs

Decision record

docs/decisions/2026-09-28-terminal-experience.md: the new subsection "The post-merge read of the final repairs" (what was found and repaired, what is documented and not repaired), two decision rows (how a probe ends after a latched signal, the one post-merge read), the evidence row, the updated limits. docs/harness-defaults.md has three new anti-pattern rows (reporting a caught signal with an exit status, describing a sweep's coverage by intent instead of by a count, a control that only the first clause of a check can fail) and the row of the signal-handling lesson now says the probe ends by the signal.

Host evidence

This PR adds no file under evidence/hosts/.

  • python3 scripts/host_receipts.py validate is part of scripts/validate.py, which passes.
  • Independent review is recorded in this description (Review).
  • No platform_status change is made from a host receipt alone.

Review

  • The read: 11 findings, none high. The three medium ones: the probes exited 128 plus the signal instead of ending by it; no case observed the spawn guard (with if True: the sweep still passed); "every line of the resource lifecycle" overclaimed (the dry run reached 107 of 161 lines with code). The eight low ones: signals pending together are ordered by number, an inherited SIG_IGN was replaced by the latch, typing ignored the latch, a tmux control exercised only the process-name clause, a zombie counted as alive, a timeout left a stand-in, a failed exec fell into the parent's code, a stale case count.
  • Verified before repaired: shell_loop_control.py, a mutated copy the sweep still passed, the unswept-line count, signal_order_probe.py, and tmux_identity_mutant.py reproduced five findings; the rest were confirmed by reading and are covered by new cases and mutants. post-merge-read.json has the row of each.
  • Not read again: the repairs of this round are checked by the sweep, 22 mutant runs and native reruns and were not read by a reviewer, and no further read is made inside this PR (the bounded-review rule is used up; a read of the merged result is the user's call).
  • Residuals (recorded in the decision record): the lines after the prompt is typed remain unswept; signals pending together are ordered by number, so the first signal wins one dispatch apart; a kill by pid after the identity check has a gap that pidfd_open would close; SIGHUP is covered in process only; the tmux probes install no signal handler; the selftests exit 0 when end-to-end cases are skipped; a run killed from outside can leave sleep 3137<digits> stand-ins; no Windows Terminal or interactive Claude Code session was run (the bell and focus reports remain unobserved).

Checklist

  • New/changed GitHub Actions are pinned to a full commit SHA with a version comment (no workflow is changed).
  • New/changed workflows declare top-level permissions: contents: read (no workflow is changed).
  • No secrets are printed, logged or committed; no new required secret was added. The added lines were scanned for user names, home paths, GUIDs, credential shapes and e-mail addresses: 0 hits (the scanner was shown to flag a planted home path and user name in a throwaway worktree).
  • No new paid hosting, subscription or billing surface was introduced.
  • Peer-owned untracked files and worktrees were preserved (not deleted, moved or overwritten).

🤖 Generated with Claude Code

@seathatflowsinourveins seathatflowsinourveins added the lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers label Oct 1, 2026
…signal, spawn guard observed, sweep coverage stated, tmux identity control)

One read-only Claude Opus agent read the merged signal handling and shutdown code of the terminal lane (#532, #552) and returned 11 findings (3 medium, 8 low, none high). Each was verified by a measurement or by reading before it was repaired:

- the pty probes now end BY a latched signal (default action restored, then the signal sent to themselves) instead of exiting 128+N: a bash loop goes on after an exit 130 and stops after a death by SIGINT (shell_loop_control.py), as Cracauer's note says
- the per-line sweep records whether a client was started before the spawn guard and fails when one was; it states the lines swept of the lines with code, and the documents say what it does not reach
- an inherited SIG_IGN stays ignored; typing stops at a latched signal
- the tmux probes get a third shutdown-failure control that only the command-line check of the identity can fail (tmux_identity_mutant.py), a zombie no longer counts as alive, the pty.fork child ends with os._exit(127)
- timeouts count as failed results and still kill the stand-in; the mutant runner has eleven mutants and eight cases per probe (12 runs each, 0 problems)
- record of the read, rebuilt receipt, recorded outputs of 35 commands (Claude Code 2.1.286 scanned: the same 17 notification types), decision record, anti-pattern rows

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/terminal-lane-post-merge-read-20260930 branch from d5c318d to b06bdf3 Compare October 1, 2026 01:38
@seathatflowsinourveins
seathatflowsinourveins merged commit c99a482 into main Oct 1, 2026
25 checks passed
@seathatflowsinourveins
seathatflowsinourveins deleted the claude/terminal-lane-post-merge-read-20260930 branch October 1, 2026 02:35
seathatflowsinourveins pushed a commit that referenced this pull request Oct 1, 2026
…s, 16 distinct, all repaired)

Six read-only jobs of the packaged GPT-6 lane (three lenses, each on gpt-6.1-sol and gpt-6-astra-ultra, effort max, Codex 0.159.3) read the merged
repairs of #563 and returned 38 findings (5 high, 31 medium, 2 low): 16 distinct issues and 22 duplicates. The coordinator reproduced each distinct
issue (13 by execution on the merged code, 3 by reading; no verifier agent) and all 38 are repaired in this one round:

- the pty probes' latch stays installed to the end of the process, nothing is flushed before the final kill, the signal is unblocked, and the Enter is
  written with the handled signals blocked; new cases for a closed stdout, a blocked signal, a second signal after the cleanups and five typing situations
- the sweep counts the client's creation (a marked guard and a mutant that must fail through that count), reports a truncated record and kills the
  stand-in; the mutant runner ends the run on a skipped case and has 18 mutants per probe with exact failing sets
- the tmux identity is an exact comparison (command name and socket argument) with a fourth shutdown-failure control and a cleanup control, and a
  mutant script with three mutants
- the shell statements name bash and dash and the condition measured; shell_loop_control.py and signal_order_probe.py are repaired (private temp dir,
  readiness handshake, asserted exit status, exact expected order, a selftest with two broken recorders)
- receipt cross-family-review-terminal-lane-20260930 rebuilt (data.post_gpt_read), decision record subsection and rows, six anti-pattern rows

Not read again by a reviewer; residuals are in the decision record.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
seathatflowsinourveins pushed a commit that referenced this pull request Oct 1, 2026
…Codex review bot's three findings

Six read-only jobs of the packaged GPT-6 lane (three lenses, each on gpt-6.1-sol and gpt-6-astra-ultra, effort max, Codex 0.159.3) read the merged
repairs of #563 and returned 38 findings (5 high, 31 medium, 2 low): 16 distinct issues and 22 duplicates. The coordinator reproduced each distinct
issue (13 by execution on the merged code, 3 by reading; no verifier agent) and all 38 are repaired:

- the pty probes' latch, the Enter under a signal block, the sweep's client-start observation (a marked guard and a mutant that must fail through
  it), a truncated sweep record, the mutant runner (exact failing sets), the tmux identity as an exact comparison with a fourth control and a cleanup
  control, shell statements scoped to bash and dash, and the scripts that measured them

GitHub's Codex review bot then read the first push on its own and left three P2 threads (the ruleset makes an unresolved thread a merge gate); all
three were reproduced by execution and are repaired here:

- a signal that landed after the final snapshot of the latch was lost: the handoff (end_by_latched_signal) is the last safe point and ends the latch's
  life (block the handled signals, read the latch, die BY the first signal or give every handler back to the default action), run once, in main's
  finally; the sweep covers it and requires death BY SIGTERM
- a stuck stdout held the probe for good: nothing is written while the latch is installed (measure collects its result lines, emit_report prints them
  after the handoff; a failed write goes to devnull)
- the tmux selftests left socket directories behind: the controls remove the directories of their recorded sockets once the servers are gone (only
  directories of the probe's own mkdtemp shape), count them before and after, have a scope control, and count only their own servers

One read-only Claude Opus reader read those repairs before this head was pushed and returned nine findings (four high, one medium, four low); each is
verified (five by execution) and repaired: the sweep driver repeated the handoff call and hid its window, two expected sets of new mutants were wrong,
the flush case failed under PYTHONUNBUFFERED=1, a closed stdout made a normal run exit 120, and more.

Receipt cross-family-review-terminal-lane-20260930 rebuilt (data.post_gpt_read, data.codex_bot_read, data.second_head_read), decision record
subsections and rows, eleven anti-pattern rows, records codex-bot-read.json and second-head-read.json. The repairs of the reader's findings were not
read again by a reviewer; residuals are in the decision record.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
seathatflowsinourveins pushed a commit that referenced this pull request Oct 1, 2026
…Codex review bot's three findings

Six read-only jobs of the packaged GPT-6 lane (three lenses, each on gpt-6.1-sol and gpt-6-astra-ultra, effort max, Codex 0.159.3) read the merged
repairs of #563 and returned 38 findings (5 high, 31 medium, 2 low): 16 distinct issues and 22 duplicates. The coordinator reproduced each distinct
issue (13 by execution on the merged code, 3 by reading; no verifier agent) and all 38 are repaired:

- the pty probes' latch, the Enter under a signal block, the sweep's client-start observation (a marked guard and a mutant that must fail through
  it), a truncated sweep record, the mutant runner (exact failing sets), the tmux identity as an exact comparison with a fourth control and a cleanup
  control, shell statements scoped to bash and dash, and the scripts that measured them

GitHub's Codex review bot then read the first push on its own and left three P2 threads (the ruleset makes an unresolved thread a merge gate); all
three were reproduced by execution and are repaired here:

- a signal that landed after the final snapshot of the latch was lost: the handoff (end_by_latched_signal) is the last safe point and ends the latch's
  life (block the handled signals, read the latch, die BY the first signal or give every handler back to the default action), run once, in main's
  finally; the sweep covers it and requires death BY SIGTERM
- a stuck stdout held the probe for good: nothing is written while the latch is installed (measure collects its result lines, emit_report prints them
  after the handoff; a failed write goes to devnull)
- the tmux selftests left socket directories behind: the controls remove the directories of their recorded sockets once the servers are gone (only
  directories of the probe's own mkdtemp shape), count them before and after, have a scope control, and count only their own servers

One read-only Claude Opus reader read those repairs before this head was pushed and returned nine findings (four high, one medium, four low); each is
verified (five by execution) and repaired: the sweep driver repeated the handoff call and hid its window, two expected sets of new mutants were wrong,
the flush case failed under PYTHONUNBUFFERED=1, a closed stdout made a normal run exit 120, and more.

Receipt cross-family-review-terminal-lane-20260930 rebuilt (data.post_gpt_read, data.codex_bot_read, data.second_head_read), decision record
subsections and rows, eleven anti-pattern rows, records codex-bot-read.json and second-head-read.json. The repairs of the reader's findings were not
read again by a reviewer; residuals are in the decision record.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
seathatflowsinourveins added a commit that referenced this pull request Oct 1, 2026
…Codex review bot's three findings (#572)

Six read-only jobs of the packaged GPT-6 lane (three lenses, each on gpt-6.1-sol and gpt-6-astra-ultra, effort max, Codex 0.159.3) read the merged
repairs of #563 and returned 38 findings (5 high, 31 medium, 2 low): 16 distinct issues and 22 duplicates. The coordinator reproduced each distinct
issue (13 by execution on the merged code, 3 by reading; no verifier agent) and all 38 are repaired:

- the pty probes' latch, the Enter under a signal block, the sweep's client-start observation (a marked guard and a mutant that must fail through
  it), a truncated sweep record, the mutant runner (exact failing sets), the tmux identity as an exact comparison with a fourth control and a cleanup
  control, shell statements scoped to bash and dash, and the scripts that measured them

GitHub's Codex review bot then read the first push on its own and left three P2 threads (the ruleset makes an unresolved thread a merge gate); all
three were reproduced by execution and are repaired here:

- a signal that landed after the final snapshot of the latch was lost: the handoff (end_by_latched_signal) is the last safe point and ends the latch's
  life (block the handled signals, read the latch, die BY the first signal or give every handler back to the default action), run once, in main's
  finally; the sweep covers it and requires death BY SIGTERM
- a stuck stdout held the probe for good: nothing is written while the latch is installed (measure collects its result lines, emit_report prints them
  after the handoff; a failed write goes to devnull)
- the tmux selftests left socket directories behind: the controls remove the directories of their recorded sockets once the servers are gone (only
  directories of the probe's own mkdtemp shape), count them before and after, have a scope control, and count only their own servers

One read-only Claude Opus reader read those repairs before this head was pushed and returned nine findings (four high, one medium, four low); each is
verified (five by execution) and repaired: the sweep driver repeated the handoff call and hid its window, two expected sets of new mutants were wrong,
the flush case failed under PYTHONUNBUFFERED=1, a closed stdout made a normal run exit 120, and more.

Receipt cross-family-review-terminal-lane-20260930 rebuilt (data.post_gpt_read, data.codex_bot_read, data.second_head_read), decision record
subsections and rows, eleven anti-pattern rows, records codex-bot-read.json and second-head-read.json. The repairs of the reader's findings were not
read again by a reviewer; residuals are in the decision record.

Co-authored-by: Scout <scout@local>
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant