Skip to content

fix(g4): judge N1 argv only after the launcher has exec'ed claude - #451

Open
kappaseijin4claude wants to merge 1 commit into
mainfrom
fix/issue-448-n1-exec-observation
Open

fix(g4): judge N1 argv only after the launcher has exec'ed claude#451
kappaseijin4claude wants to merge 1 commit into
mainfrom
fix/issue-448-n1-exec-observation

Conversation

@kappaseijin4claude

Copy link
Copy Markdown
Collaborator

概要

N1 は launcher PID のコマンドラインを 1 回だけ採り、exec する前の launcher 自身を「args 不一致の fail」と判定していた。これを、binding を観測した後に別枠の上限時間まで exec を観測する方式に変える。設計は docs/decisions/2026-09-13T164649_issue-448-n1-exec-observation.md(PR #449)にある。

Refs #448 #434 #407

変更

対象 内容
pilot-gate-isolation.py observe-n1-exec binding を観測してから 10 秒まで、0.2 秒ごとに ps -ww -o command= を採り、launcher / claude / unrecognized / absent に分類する。claude は argv[0] が CLAUDE_BIN と文字列で一致するか、canonical path が CLAUDE_BIN_CANONICAL と一致するときとする
判定 args は claude に分類した後にだけ照合する(既存の規則を process_argv_matches として切り出し、そのまま再利用)。一致すれば pass、不一致だけが fail。exec_not_observed / launcher_exited_before_exec / process_identity_unrecognized は unknown
証跡 exec-observation.json に、経過秒・分類の遷移・binding の mtime・観測回数を残す。claude に到達しなかった場合は、さらに launcher-stat.txtprocess-command.rawlauncher-output-tail.txtpty.raw の末尾 4096 byte、ANSI 除去)を残す。exec_not_observed のときだけ、判定を変えない 5 秒の遅延観測を exec-late-observation.json に残す
runner 定数 N1_EXEC_TIMEOUT_SECONDS=10N1_EXEC_POLL_SECONDS=0.2 を追加した。1 回だけ採る record_process_command と、その前にあった生存確認は削除した(どちらも観測の中で扱う)。「binding は exec の直前に書かれる」というコメントは実態に合わせて直した。case の reason は N1/<mode>/reason と N1 の結果に載せる

設計書から判断した点

  • 終了したが親にまだ回収されていない launcher は、ps<defunct>(stat Z)と表示される。これを absent として扱う(設計書 §3 の「PID が生きていない」にあたる)。macOS で実測し、単体試験を足した
  • claude に分類したのに args を判定できない場合(照合規則が exit 2 を返す場合)は、process_identity_unrecognized の unknown とした。設計書の表にこの場合の定めは無い
  • bindingObservedElapsedFromLauncherStart は、bash の SECONDS の差(整数秒)で記録する

README への影響

なし。gate harness は内部ツールである。

試験

ID stub の振る舞い 結果
N1E-01 3 秒後に args の一致する claude へ exec する(binding の stub が約 1 秒かかる) pass、遷移が launcher → claude、elapsedSecondsToClaude が 0.8〜5 秒
N1E-02 launcher のまま exec しない unknown exec_not_observed、証跡 4 ファイルがあり、fail にならない
N1E-03 --settings が別パスの claude fail claude_args_mismatch
N1E-04 exec の前に終了する unknown launcher_exited_before_exec、出力の末尾に launcher のエラー文、stat は absent
N1E-05 sleep 60 unknown process_identity_unrecognized を即座に返す(観測 3 回以下、遅延観測なし)
N1E-06 13 秒後に exec する unknown exec_not_observed、遅延観測で claude
N1E-07 resume の case で fresh の args を持つ claude fail claude_args_mismatch
N1E-08 CLAUDE_BIN が symlink。argv[0] が symlink のパスの場合と、実体のパスの場合 どちらも pass
単体 回収前の終了プロセス、launcher の 2 つの起動形、分類の境界 isolation に 2 件

stub は実際に exec -a で argv[0] を差し替えるので、PID のコマンドラインは本物と同じように変わる。N1E の 8 件は 3 回続けて全件通過した。

負の対照(原本は変更せず、コピーに当てた。時間差を含むので、変異ごとに 3 回ずつ実行。原本の sha256 は前後で一致)

変異 判定
launcher の分類も args 照合にかける(本 Issue の欠陥の再現) N1E-02 3/3 KILLED
args 照合を外す N1E-03 3/3 KILLED
上限を 0 秒にする(1 回だけ採る方式への退行) N1E-01 3/3 KILLED
absent を待ち続ける N1E-04 3/3 KILLED
unrecognized を待ち続ける N1E-05 3/3 KILLED
遅延観測で claude を見たら pass にする N1E-06 3/3 KILLED
mode を無視して fresh の規則で照合する N1E-07 3/3 KILLED
canonical path の比較を外す N1E-08 3/3 KILLED
<defunct>absent にしない runner bats では 0/3(fixture では launcher が観測の前に回収されるため)。単体試験を足し、3/3 KILLED

検証(clean worktree)

試験 結果
tests/test_pilot_gate_runner.bats 60/60
tests/test_pilot_launcher.bats 33/33
fd guard / compat_posix / kill -0 規約(instance_id)/ close_fds 4 / 5 / 61 / 4
tests/test_pilot_gate_*.py 全 12 モジュール 全件通過(isolation 135)
tests/test_pilot_pty.py 18/18
check-enforced-assertions.sh 718(baseline のまま)

扱わない範囲

🤖 Generated with Claude Code

https://claude.ai/code/session_01QCtgi8wVJDRaMwXHZmkHqT

N1 sampled the launcher PID's command line once, right after the binding.
The launcher still runs its claim, roster and digest checks after
publishing the binding, so that sample could be the launcher itself,
which never carries --session-id and was judged a fail.

Implements docs/decisions/2026-09-13T164649_issue-448-n1-exec-observation.md:

- isolation observe-n1-exec polls ps every 0.2 s for up to 10 s from the
  binding observation and classifies launcher / claude / unrecognized /
  absent (an unreaped <defunct> launcher is absent). The existing argv
  rule, now process_argv_matches, runs only on claude: match is pass,
  mismatch is the only fail; exec_not_observed,
  launcher_exited_before_exec and process_identity_unrecognized are
  unknown.
- exec-observation.json records elapsed seconds, class transitions and the
  binding mtime. When claude is not reached, launcher-stat.txt,
  process-command.raw and launcher-output-tail.txt (pty.raw tail) are
  kept, and exec_not_observed adds a 5 s late observation that never
  changes the verdict.
- runner: N1_EXEC_TIMEOUT_SECONDS=10, N1_EXEC_POLL_SECONDS=0.2; the
  one-shot record_process_command is removed; the case reason is carried
  into the N1 result.

Tests N1E-01..08 (bats) and classification unit tests.

Refs #448 #434 #407

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gd6MbRAYGpkDzHAk1XZroZ
@kappaseijin4claude

Copy link
Copy Markdown
Collaborator Author

凍結(2026-09-13、ユーザー決定)

Issue #373の方針転換(breaker断定・ユーザー承認)により、G4連鎖(本issueを含む
Issue #236/#385/#395/#407/#434/#444/#448/#450、PR #451/#437)を凍結する。

closeしない。成果は残す。着手を停止する。

詳細: Issue #373のコメント(breaker断定、2026-09-13T08:36:53Z / ユーザー決定、
同日直後)を参照。

再開条件: agguild/agguild_pool構築(新方針)の状況次第でユーザーが判断する。

@kappaseijin4claude kappaseijin4claude added the close-scheduled-2026-09-20 移行後1週間、問題なければクローズ予定(ユーザー決定2026-09-13) label Sep 13, 2026
@kappaseijin4claude

Copy link
Copy Markdown
Collaborator Author

凍結解除の判断スケジュール(ユーザー決定 2026-09-13)

fork→公式agmsg切替・agguild_pool移行が完了(2026-09-13)したことを受け、
ユーザーより以下の決定がありました。

凍結したissueは移行後1週間後に問題がなければクローズしてください。

2026-09-20頃、新環境(agguild経由)の運用実績に問題がなければ、このissue/PRを
クローズします。
問題があれば継続し、その内容をIssue #373へ記録します。

親issue: #373

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

close-scheduled-2026-09-20 移行後1週間、問題なければクローズ予定(ユーザー決定2026-09-13)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants