Skip to content

feat(g4): tie the N1 transcript to its session with a one-time marker - #440

Merged
kappaseijin4claude merged 2 commits into
mainfrom
fix/issue-434-native-transcript-marker
Sep 13, 2026
Merged

kappaseijin4claude merged 2 commits into
mainfrom
fix/issue-434-native-transcript-marker

Conversation

@kappaseijin4claude

Copy link
Copy Markdown
Collaborator

概要

Issue #434(N1のtranscript観測が無送信では成立しない問題)の実装。設計はPR #435でmerge済み。

Refs #434(マージでは自動クローズしない。verifierによるsmoke/受入確認後、PMが手動でクローズする)

実装内容

binding完全照合後、runnerが各native PTYへpilot-pty.py経由のcontrol socketを通じて識別用prompt(case固有marker付き)を一回だけ送信し、同一transcriptファイル内のsessionId一致とmarkerの両方が揃うのを待つ。

codexから引き継いだ経緯

programmer_codexの週次枠枯渇に伴い、agmsg_programmer_claudeが引き継いで完了した。引き継ぎ時点でsocketパスは既に/tmp/agmsg-n1-$$-${RANDOM}.sockへ変更されており(元のバグ: AF_UNIX path too長すぎは解消)、runner bats 43/43 PASSだったが、fail-closedの観点から追加で3点修正した。

  1. pilot-pty.pyがpilot起動にsocketをbindしていた(bind失敗時、起動済みpilotを止める者がいなくなる)→ bindをspawnの前に移動、失敗時はexit 70で何も起動しない
  2. /tmp直下の推測可能パスをbind直前にunlinkしていた(別プロセスのファイルを消しうる)→ mktemp -d /tmp/agmsg-n1.XXXXXX(0700)の専用ディレクトリへ変更、case停止時に削除
  3. marker生成(openssl)失敗時、launcherとhelperを止めずにreturnしていた→停止処理を追加

検証

  • runner bats 43/43、launcher bats 33/33、fd guard・kill -0規約・close_fds・compat_posix すべて通過
  • pilot-gate Python全12モジュール通過(isolation 115件)、test_pilot_pty.py 13/13
  • enforced assertions 718(baselineのまま)
  • 試験後に/tmp/agmsg-n1.*が残っていないことを確認(0件)

変異試験・負の対照

変異 判定 落ちた箇所
専用ディレクトリを削除しない KILLED runner bats「control directory left behind」
socketをcaseディレクトリ(深いパス)へ戻す KILLED AF_UNIX path too long(今回の不具合の再現)
bindをspawnの後へ戻す KILLED test_an_unbindable_control_socket_starts_nothing

この実装で扱わない範囲

  • 全gate再実行、live起動・物理移行(pilot_ready=falseのまま)
  • 設計書記載の実native smokeとN1M-01〜07個別fixture試験のうち、本差分で未実施のものがあるかは未突き合わせ(verifierへ依頼予定)

README への影響

無。G4 gateの内部harnessの変更で、ユーザーが設定・利用する手順は変わらない。

🤖 Generated with Claude Code

https://claude.ai/code/session_01QCtgi8wVJDRaMwXHZmkHqT

kappaseijin4codex and others added 2 commits September 13, 2026 12:16
…#434)

After the binding is fully matched, the runner sends each native PTY one
harmless prompt carrying a case-specific marker, through a control
socket held by pilot-pty.py, and waits for exactly one transcript that
has both the bound sessionId and that marker. Anything else (no file,
several files, marker and sessionId in different files, a failed or
partial write) is unknown.

- pilot-pty.py: "run --control-socket" writes datagrams to the retained
  PTY master; "send" delivers one input and reports ok/error. The socket
  is bound before the pilot starts, so an unbindable path starts nothing.
- runner: the socket lives in a private mktemp -d directory under /tmp
  (AF_UNIX paths are too short for the artifact tree) and is removed
  when the case stops; a marker that cannot be generated stops the case.
- isolation helper: match transcript candidates on sessionId and marker.

Implementation started by agmsg_programmer_codex and completed by
agmsg_programmer_claude after the handover.

Refs #434 #395

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gd6MbRAYGpkDzHAk1XZroZ
- runner: input-count is written before the single send attempt, and
  input-result records ok/error, so a failed or partial write is still
  one recorded input and is never retried (design 3.2, N1M-07).
- runner bats: N1M-01 (the prompt reaches the PTY once and the transcript
  wait uses that marker) and N1M-07 (a failed send is unknown, counted
  once, not retried, and no transcript wait starts).
- isolation: N1M-03/04/05/06/08 finder controls (marker in another
  session, sessionId and marker split across files, two candidates,
  a match outside the root, a session file without the marker).
- pilot-pty: write_master only accepts a complete write (partial, EIO,
  closed descriptor are errors).

Refs #434

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gd6MbRAYGpkDzHAk1XZroZ
@kappaseijin4claude
kappaseijin4claude merged commit e613163 into main Sep 13, 2026
49 of 50 checks passed
@kappaseijin4claude
kappaseijin4claude deleted the fix/issue-434-native-transcript-marker branch September 13, 2026 04:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants