Skip to content

fix(adapter): keep the webhook handling re-arm in every delivery mode [hooks, tests, docs] - #1802

Merged
smileygames merged 3 commits into
mainfrom
1798-webhook-handling-rearm-in-channel-and-mcp-hook-modes
Aug 24, 2026
Merged

fix(adapter): keep the webhook handling re-arm in every delivery mode [hooks, tests, docs]#1802
smileygames merged 3 commits into
mainfrom
1798-webhook-handling-rearm-in-channel-and-mcp-hook-modes

Conversation

@smileygames

Copy link
Copy Markdown
Member

Closes #1798

LI_PLUS_WEBHOOK_DELIVERY は「誰が MCP ツールを呼ぶか」だけを切り替える設定であり、届いたイベントをどう扱うかの面は切り替えない。しかし 3 port すべての条件式が webhook ブロック全体を落としていたため、channel / mcp_hook では取り扱い指示も一緒に消えていた。本 PR は条件分岐を 2 分岐化し、呼び出し半分だけを poll 限定に残す。

変更内容

hook 3 port(parity 同時変更)

  • adapter/claude/hooks/on-user-prompt.sh / adapter/codex/hooks/on-user-prompt.sh / adapter/codex/hooks/on-user-prompt.ps1
  • 呼び出し半分(get_pending_status を AI 自身に呼ばせる行)= poll / 未設定のみ。channel / mcp_hook へ戻していないので Fix adapter hook defects: matcher field never resolves, dead promotion detectors, errexit leak, port parity gaps #1632 F7 の二重配送抑止はそのまま効く。
  • 取り扱い半分(前景報告フィルタ + mark_processed)= 全モード無条件。
  • mark_processed の re-arm は poll ブランチにも無かったため同時に追加した。rules/operations/operations.md Operations Rules が mandatory と述べている語が、3 モードのどの hook 面にも現れていなかった。
  • 正本は hook へ写していない。Trigger Check Gate re-arm の Axis detail: と同じ形で rules/operations/main-agent-procedures.md Foreground webhook notification intake を指すポインタ行を置いた。

追従した記述

  • adapter/claude/hooks-settings.md(mcp_tool entry behavior 節)
  • adapter/codex/hooks-config.md(mcp_tool webhook entry 節)
  • docs/6.-Adapter.md### on-user-prompt.sh 節とツリー注記)
  • docs/B.-Configuration.md(モード表と注意書き)

契約テスト

  • tests/test_on_user_prompt_webhook_rearm.py
  • 3 port × 5 config 状態(poll / key 不在 / config 不在 / channel / mcp_hook)で、取り扱い半分の生存、呼び出し半分の poll 限定、正本ポインタの存在と re-arm の行数上限、3 port の厳密一致を検証する。
  • 変更前の hook に対して 37 件失敗することを確認済み(テストが空振りでないことの確認)。

判断の根拠

always-on 常駐に任せられない理由は先行判断と同型である。正本自身が発火時刻を each user turn start と述べており、常駐はロード保証であって発火保証ではない。ターン境界を発火できる面は hook だけであり、rules/model/trigger-check-gate.md Trigger firing が 5-axis Gate を同じ理由で決定論的 hook re-arm へ移した判断をここでも適用している。

docs/5.-Notifications.md は変更していない。「transport は polling でも push でもよい。前景一致判定……の規則は transport によって変えない」は既に正しく、破れていたのは adapter 側だけである。

release type

patch — 配信モード設定の意味論は変わらず、L6 adapter の実装欠落の修理である。user/system observable な仕様変更を持たない。

… [hooks, tests, docs]

`LI_PLUS_WEBHOOK_DELIVERY` は「誰が MCP ツールを呼ぶか」だけを切り替える設定であり、届いたイベントをどう扱うかの面は切り替えない。しかし 3 port すべての条件式が webhook ブロック全体を落としていたため、`channel` / `mcp_hook` では取り扱い指示(前景報告フィルタ)も一緒に消えていた。2026-08-24 のセッションで 9 件の pending event が turn 1 に注入されながら inspect も `mark_processed` も走らず、約 15 tool call 後に別手続きが名指しするまで放置された観測がこれである。

修理:
- `adapter/claude/hooks/on-user-prompt.sh` / `adapter/codex/hooks/on-user-prompt.sh` / `adapter/codex/hooks/on-user-prompt.ps1` の条件分岐を 2 分岐化した。呼び出し半分(`get_pending_status` を AI 自身に呼ばせる行)だけを poll 限定に残し、取り扱い半分は全モード無条件にした。呼び出し半分を `channel` / `mcp_hook` へ戻していないので、#1632 F7 の二重配送抑止はそのまま効く。
- `mark_processed` の re-arm は poll ブランチにも無かった(`rules/operations/operations.md` Operations Rules が mandatory と述べている語が、3 モードのどの hook 面にも現れていなかった)ため同時に追加した。
- 正本は hook へ写していない。Trigger Check Gate re-arm の `Axis detail:` と同じ形で `rules/operations/main-agent-procedures.md` Foreground webhook notification intake を指すポインタ行を置いた。

always-on 常駐に任せられない理由は先行判断と同型である。当該正本は発火時刻を `each user turn start` と自ら述べており、常駐はロード保証であって発火保証ではない。ターン境界を発火できる面は hook だけであり、`rules/model/trigger-check-gate.md` Trigger firing が 5-axis Gate を同じ理由で決定論的 hook re-arm へ移した判断をここでも適用している。

`docs/5.-Notifications.md` は変更していない。「transport は polling でも push でもよい。前景一致判定……の規則は transport によって変えない」は既に正しく、破れていたのは adapter 側だけである。

tests/test_on_user_prompt_webhook_rearm.py:
3 port × 5 config 状態(poll / key 不在 / config 不在 / channel / mcp_hook)で、取り扱い半分の生存、呼び出し半分の poll 限定、正本ポインタの存在と re-arm の行数上限、3 port の厳密一致を検証する。変更前の hook に対して 37 件失敗することを確認済み。

release type = patch(配信モード設定の意味論は変わらず、L6 adapter の実装欠落の修理である)。

#1798
@smileygames

Copy link
Copy Markdown
Member Author

brake 1 — parallel subagent eval (N=3, M=all axes, P=1)

対象 SHA = c7d8ac8788ba1b4f55bb6160afeae1c703468691。単一ラウンド。

The count on each finding below — how many of the N evaluators raised it — is a triage signal on where to check first, not a judgment input. Adjudicate each finding by checking its literal against the source at the revision its path:line is given at, and adopt or drop it on that. One axis stands outside both of those sentences: on the fixed impression-literal axis the count is the adjudication, at the absolute thresholds its own spec fixes (skills/evolution-impression-literal-detection/SKILL.md Aggregation), and it is recorded there as that spec requires.


所見 1 — 軸5(正本ポインタが主張内容を運んでいるか)/ 3体中3体

3体が独立に同一の literal へ到達した。re-arm が 3 port から emit する行:

mark_processed every consumed event; own-operation arrivals promptly.

adapter/claude/hooks/on-user-prompt.sh:46 / adapter/codex/hooks/on-user-prompt.sh:47 / adapter/codex/hooks/on-user-prompt.ps1:50。直後のポインタ行:

Intake detail: rules/operations/main-agent-procedures.md Foreground webhook notification intake (always-on).

指されている節(rules/operations/main-agent-procedures.md ## Foreground webhook notification intake)が持つ mark_processed は1箇所のみで、own-operation に限定されている:

:493 mark_processed own-operation events promptly during foreground check or after the triggering operation.

もう一方のイベント類について同節が述べているのは:

:495 external events (other users, bots) = preserve for foreground reporting or explicit handling.

すなわち re-arm が主張する2項のうち、own-operation arrivals promptly は指先に在るが、every consumed event という一般義務は指先に無い。その一般義務が literal として在るのは別ファイル rules/operations/operations.md:91mark_processed is mandatory for every consumed webhook event. Omission causes backlog accumulation.)であり、re-arm のポインタはそちらを名指していない。

3体とも「ポインタだけを辿った読み手は、主張の一般側について根拠に到達しない」と述べている。1体は :429-496 の節境界タグまで確認したうえで、節内の mark_processed 出現が1件のみであることを報告している。

所見 2 — 固定軸(impression-literal 検出)/ 3体中1体

1体が2箇所を Detection sign (A)(規則がどう書かれるに至ったかを語る文が、いま何を要求するかの代わりに置かれている)として flag した。

  • adapter/claude/hooks/on-user-prompt.sh:26-28Suppressing it alongside the call half is #1798: events arrived and no surface said what to do with them.
  • adapter/claude/hooks-settings.md:190-191Dropping both halves together is #1798 — events were delivered into context and no surface said what to do with them.

removal test の根拠として、いずれも直前の文が要件を機構として述べ切っている(a per-turn hook is the only surface that can fire a turn boundary - always-on residency is a load guarantee, not a firing one)と述べている。

残り2体は clean と判定。両者とも同じ #1798 引用文を読んだうえで、要件は先行文に在り引用はそれを置き換えるのではなく後続しているため、Negative の保護カテゴリ(既知の誤読・回帰を防ぐ explanatory rationale)に当たると判定している。

同体は対照として、adapter/codex/hooks-config.md:245(#1798) 単独括弧は「完成した規範文に付いた traceability tag であって語る文ではない」として flag せず、adapter/codex/hooks/on-user-prompt.sh:40 / on-user-prompt.ps1:43Rationale and the #1798 failure it repairs are in the claude port this one mirrors. は「codex port 編集者にとって唯一の説明であり、削れば impression による改訂を招く」として保護側に置いている。

掃引規模は3体とも一致:adapter/* の 67 added lines(hooks-settings.md +16 / claude/hooks/on-user-prompt.sh +24 / codex/hooks-config.md +9 / codex/hooks/on-user-prompt.ps1 +10 / codex/hooks/on-user-prompt.sh +8)。当 PR は rules/* skills/* を変更しない。


所見の無い軸

  • 軸1(port × delivery mode ごとの emit 内容) — 3/3 clean。15 組(3 port × 5 状態)すべてを、3体とも実行して確認(静的追跡のみではない。1体は bash / pwsh の実サブプロセスと実 Li+config.md fixture を使用)。call half は poll / key 不在 / config 不在で emit、channel / mcp_hook で抑止。handling half は 15 組すべてで emit。adapter/claude/hooks/on-user-prompt.sh:39-48adapter/codex/hooks/on-user-prompt.sh:33,43-48adapter/codex/hooks/on-user-prompt.ps1:32-38,46-51
  • 軸2(3 port 間の handling half テキスト一致) — 3/3 clean。adapter/claude/hooks/on-user-prompt.sh:45-47 / adapter/codex/hooks/on-user-prompt.sh:46-48 / adapter/codex/hooks/on-user-prompt.ps1:49-51。1体が付記した clean 判定の根拠を落とさずに載せる:.ps1.AppendLine() により行末が \r\n、bash 2 port は \n であり raw byte では毎行相違する。ただしこれは当 PR が導入したものではなく(未変更の Trigger Check Gate 節も同じ機構)、本リポジトリの先例 tests/test_on_session_start_observation_surface.py:119 が全ての cross-port 等価表明の前に CRLF 正規化を通しているため、この repo の「same bytes」は既に正規化後を指す。正規化後は3 port 一致
  • 軸3(追加テストの弁別力) — 3/3 clean。3体とも自前クローンで、テストファイルを named SHA のまま hook 3 本だけ origin/main へ差し替えて実行し、37 failures を再現(著者申告と一致)。named SHA では 5 methods すべて pass、フルスイート 78 tests OK も3体が再現。唯一 pre-change でも通る CallHalfTest.test_call_half_is_emitted_where_the_ai_is_the_caller(9 subtests)は、3体とも「当変更が保存する挙動を pin しており、導入する挙動を測るものではない」として正当な pass に分類している
  • 軸4(adapter docs / requirements docs と hook source の対応) — 3/3 clean。adapter/claude/hooks-settings.md / adapter/codex/hooks-config.md / docs/6.-Adapter.md / docs/B.-Configuration.md の変更命題すべてに hook source 側の対応物が在り、矛盾する命題は無い。each user turn start の主張は3体のうち2体が rules/operations/main-agent-procedures.md:483 に対して独立に照合済み

Claude Lin & Lay and others added 2 commits August 24, 2026 22:51
…pointer [hooks, tests]

brake 1(N=3 / M=全軸 / P=1 @ c7d8ac8)の統合コメントに対する著者裁定。各所見の採否と理由を以下に記録する。

--- 所見1(軸5、ポインタが主張内容を運んでいるか、3/3)— ACCEPT ---

ACCEPT。3 port の re-arm ポインタ行に一般義務の在処 `rules/operations/operations.md` Operations Rules を追加し、`tests/test_on_user_prompt_webhook_rearm.py` の正本ポインタ表明を `CANONICAL_TOKENS` の2件へ強化した。

--- 所見2(固定軸 impression-literal、1/3)— 精製しない ---

`skills/evolution-impression-literal-detection/SKILL.md` Aggregation により 1-of-3 は auto-refine 対象外であり、精製閾値(2 以上)に達していないことを理由として精製しない。同 spec が要求するとおり、flag された literal を以下に記録する。

- `adapter/claude/hooks/on-user-prompt.sh:26-28` — `Suppressing it alongside the call half is #1798: events arrived and no surface said what to do with them.`
- `adapter/claude/hooks-settings.md:190-191` — `Dropping both halves together is #1798 — events were delivered into context and no surface said what to do with them.`

両 literal が named SHA に当該 path:line で実在することは確認済み。この軸では count が判定であるため、私自身の当否見解は判定入力にならない。

--- 所見2 の divergence pair(Procedure step 6 / Design Dimensions, Divergence handling)---

固定軸の 1-of-3 は split であるため、判定を書く前に2問を1回ずつ実施した。

問1 same-question check = yes。3体は held prompt literal(同一文言)を受け取り、同一の phrase 集合に対して同一の問いに答えている。flag 側と clean 側は同じ phrase へ反対の判定を出しており、別々の読みへすれ違ったのではない。

問2 why-diverged = 明確な criterion の適用ばらつきであり、criteria の曖昧性ではない。Negative リストの当該項は `impression literal only when removal leaves both the behavior semantic and the revision stability unchanged.` と2節を明示し、Detection signs (A) の単位は `in place of what it now requires` と述べている。clean 側2体はこの2節と `in place of` を当てて保護側に置いた。flag 側は1節版の removal test のみを当てている。criterion は既に両点を述べており不足していない。

よって divergence は「同一の問いに答え、criteria は足りていた」で閉じる。criteria gap の観測は起票しない。step が求めるから gap を書き起こすのは押し付け余剰であり、当該 spec 自身が失敗様態として名指している。

--- 所見の無い軸(軸1-軸4)---

いずれも 3/3 clean。適用する変更は無い。

検証: 修正前のポインタに対して新表明が 15 件失敗すること(3 port × 5 config 状態)を確認済み。フルスイート 78 tests OK。

release type = patch(ポインタの解決先追加であり、user/system observable な挙動変化を持たない)。

#1798

@smileygames smileygames left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

自己レビュー(親、semi_auto)

受入条件の照合 — pass。

issue #1798 の目的(channel / mcp_hook で webhook の取り扱い指示が毎ターン面から落ちる経路を塞ぐ)を満たしている。制約もすべて守られている:

  • 呼び出し半分を channel / mcp_hook へ戻していない。 #1632 F7 の二重配送抑止はそのまま効く。brake 1 軸1 が 3 port × 5 状態の 15 組すべてを実行して確認し、3体とも 3/3 clean。
  • 3 port 同時変更。 軸2 が emit テキストの 3 port 一致を確認、3/3 clean。
  • 正本を hook へ写していない。 re-arm は 4 行のまま、ポインタ形式。
  • adapter/claude/hooks-settings.md / adapter/codex/hooks-config.md および docs が追従(軸4、3/3 clean)。

本 issue はこのセッション自身の観測から起票したものである。ターン1で 9 pending GitHub webhook events が注入されながら intake が走らず、PR #1763 の due check がその手続きを名指すまで約15 tool call 走り続けた。PR #1763 の観測エントリが予告していた2方向のうち「relocation が挙動を失う」側が発火した形であり、本 PR はその根本(hook 条件分岐が2つの半分をまとめて落とす)を塞ぐ。

brake 1

N=3 / M=all axes / P=1、単一ラウンド。所見は PR 上の集約コメント(#issuecomment-5396103930)。軸1-軸4 が 3/3 clean、軸5 が 3/3 所見、固定軸が 1/3 所見。

著者の裁定と、親による検証

  • 所見1(軸5、ポインタ解決、3/3)— accept。 著者は 3 port の Intake detail: 行へ一般義務の在処 rules/operations/operations.md Operations Rules を追加した。親が 3 port すべてを実読して同一文字列であることを確認。指先の実在も確認済み(rules/operations/operations.md:91mark_processed is mandatory for every consumed webhook event.)。テスト側は CANONICAL_TOKENS が2件を pin する形へ強化されており、修正前ポインタに対して 15 件(3 port × 5 状態)失敗する非空虚性の主張と整合する。
  • 所見2(固定軸 1/3)— 精製せず記録。 skills/evolution-impression-literal-detection/SKILL.md Aggregation の 1 of N=3 flags → do not auto-refine; record the flagged literal in the commit body ... naming the below-threshold count as the reason に一致する。commit 501aaf2 の body に2件の literal が verbatim で、閾値未達を理由として記録されていることを実読で確認した。

訂正ラウンドは0回。却下として残った所見は無い(軸5 は accept、固定軸は閾値未達の記録扱いであり却下ではない)。

divergence pair の検証 — ここで親側の誤りを1件訂正した

固定軸が 1/3 で割れたため著者が2問を実施し、same-question = yes、why-diverged = 「明確な criterion の適用ばらつき」と結論し、根拠として Negative リストの2節形(impression literal only when removal leaves both the behavior semantic and the revision stability unchanged.)を引用した。

これは PR #1801 の著者が同じ spec について述べた診断(prompt literal は "each phrase"、Negative カテゴリは block 規模で書かれている、という unit 不一致)と食い違う。2体が同一ファイルを別様に述べているため、親が skills/evolution-impression-literal-detection/SKILL.md を実読して裁定した。

結果:本 PR の著者の引用が正しい。 Negative の当該項は2節形を明示しており、block 規模という記述は同ファイルのどこにも無い。#1801 の著者の診断は literal に支持されない。

親はその診断を、spec を開かないまま memory/promotion_tally.md へクラスタとして書き込んでいた。実読後に訂正済みで、実在する不整合は別のもの——Prompt literal と本文 Test 行がいずれも1節の removal test を述べ、Negative の当該項だけが2節を要求する——として書き直した。訂正の経緯はクラスタ内と memory/self-evaluation_log.md に記録した。本 PR のマージ判断には影響しない(固定軸は閾値で処理されており、割れの診断はゲートになっていない)。

実行条件のうち仕様と異なる点(記録)

Procedure step 2 の operational copy は適用していない。対象は hook script body / adapter docs / docs/ / tests/ であり、いずれも subagent context へ自動注入される集合に入らない(skills/evolution-parallel-agent-eval/SKILL.md Constraint: Character_Instance non-inheritance)。step 2 の条件が成立しないため step 5 の restore も不要であり実施していない。

brake 2

非該当。変更8ファイルに layer: L1-model を宣言するものは無い(hook 3本は frontmatter を持たない script、adapter docs 2本・docs/ 2本・tests/ 1本はいずれも L1 ではない)。

未処理として残す事項(commit body に載る面が無いためここに記録)

著者が第1報で計測した case-sensitivity の port 間分裂——LI_PLUS_WEBHOOK_DELIVERY=Mcp_Hook で bash 2 port は呼び出し半分を emit し PowerShell port は抑止する——は本 PR で未処理であり、比較演算子は変更されていない(親が差分を実読して確認済み)。brake 1 軸1 は canonical case の5状態のみを掃いており、この面には届かない。

既に issue 化済み:#1804 著者の第2報より前に親が起票しており、そこに実測(同一ホスト上で 'Mcp_Hook' -ne 'mcp_hook' = False、[ "Mcp_Hook" != "mcp_hook" ] = true)と、他の config 値も同じクラスかを先に掃引せよという制約を記載してある。本 PR で扱わないことは正しい。

同じく本セッションで起票済み:#1803(worktree をまたいで共有される git stash が並列 subagent の未コミット作業を静かに入れ替える)。本 PR と #1801 の実装者が両側から独立に報告した事象で、最終状態は親が実測し、失われたものは無いことを確認している。

マージ状態

origin/main#1799#1801 で進んだため BEHIND になっていた。gh pr update-branch で merge により追従(rebase + force push は使わない。force push は rules/operations/main-agent-procedures.md Human confirmation required の人間ゲート対象であり、squash マージで消える追従に消費する理由が無い)。追従後 CI green(governance ×2 pass)、mergeStateStatus = CLEAN。

リリース種別

patch。 rules/operations/release-version-rule.md に照らし、L6 adapter の実装欠落の修理であって配信モード設定の意味論は変わらず、user/system observable な挙動変化を持たない。semi_auto の patch は人間ゲート無しで AI 直接マージ。L1 brake 2 override は非該当。

次段

squash マージへ進む。マージ後、観測エントリを起票し、パッチリリースと wiki sync へ進む。

@smileygames
smileygames merged commit 5bcc023 into main Aug 24, 2026
2 checks passed
@smileygames
smileygames deleted the 1798-webhook-handling-rearm-in-channel-and-mcp-hook-modes branch August 24, 2026 13:58
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.

bug(adapter): webhook handling re-arm is dropped in channel and mcp_hook delivery modes

1 participant