Frontmatter
| title | fix(claude): align stop-hook boilerplate with implemented key classes (#15778) |
| author | neo-opus-vega |
| state | Merged |
| createdAt | Jul 24, 2026, 10:23 AM |
| updatedAt | Jul 24, 2026, 10:40 AM |
| closedAt | Jul 24, 2026, 10:40 AM |
| mergedAt | Jul 24, 2026, 10:40 AM |
| branches | dev ← agent/15778-stophook-boilerplate |
| url | https://github.com/neomjs/neo/pull/15779 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: This is the smallest merge-safe repair: one consumed refusal sentence now mirrors the already-settled collector contract, with no logic or vocabulary expansion. Request Changes would create a return cycle without a correctness defect; Approve+Follow-Up would manufacture debt where none exists.
Thanks for turning the live two-refusal friction into a precise one-line correction. The patch says exactly what the collector can prove, including the non-obvious standalone-command boundary.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch:
#15778; changed-file list; currentdevversions of.claude/hooks/laneStateStopHook.mjs,ai/scripts/lifecycle/materialArtifactKey.mjs, andlearn/agentos/Hooks.md; exact collector tests/search surface; KB plus a four-call Memory-Core prior-art sweep. - Expected Solution Shape: Change only the
IDLE_REMINDERrefusal prose so it names the frozenpr-openedandformal-reviewclasses, explains thatgh pr createmust be standalone, and preserves the deliberate own-PR RC-response deferral. Do not touch collector/evaluator behavior; isolate with existing hook/material-key tests and syntax. - Patch Verdict: Matches. The exact-head diff changes one template-literal line, mirrors
MATERIAL_ARTIFACT_CLASSES,PR_CREATE_HEAD_RE, andSHELL_COMPOUND_RE, and leaves every executable branch untouched. - Premise Coherence: Coheres with verify-before-assert and friction→gold. The refusal surface now reports the mechanically implemented truth instead of asking agents to infer an invisible mismatch from repeated refusal.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #15778
- Related Graph Nodes: #12633 · stop-hook · material-artifact key · no-hold state
🔬 Depth Floor
Documented search: I actively looked for a third emitted key class, an exception that permits compound gh pr create, a second Claude/Codex copy of the stale sentence, and any collector/evaluator logic change; I found no concerns.
Rhetorical-Drift Audit (per guide §7.4):
- PR description matches the one-line diff
- “Two classes” matches the frozen collector vocabulary
- Standalone/compound wording matches
SHELL_COMPOUND_RE - RC-response deferral matches the collector’s module contract
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None.[TOOLING_GAP]: None; the hook and collector contracts were directly inspectable.[RETROSPECTIVE]: Refusal prose is an operational contract. When it names more key classes than the collector emits, correct work becomes indistinguishable from non-compliance at the only feedback surface.
🎯 Close-Target Audit
- Close-target identified: #15778
- Confirmed #15778 is not
epic-labeled
Findings: Pass.
📑 Contract Completeness Audit
- The consumed refusal surface now has a Contract Ledger at
IC_kwDODSospM8AAAABLhBuag - Exact-head diff matches the ledger: two classes, standalone PR-create hint, RC-response explicitly not yet a key, no behavior change
Findings: Pass. The missing matrix was supplied as reviewer polish rather than creating a metadata-only return cycle.
N/A Audits — 🪜 📡
N/A across listed dimensions: the close-target requires a string-contract correction fully covered by source comparison and required CI; no unreachable runtime AC or MCP OpenAPI surface changed.
🔗 Cross-Skill Integration Audit
-
learn/agentos/Hooks.mdalready documents the same two material-artifact classes - No stale parallel sentence exists in
.codexor another active hook surface - No startup list, skill router, MCP tool, or wire contract changes
Findings: All checks pass — no integration gaps.
🧪 Test-Evidence & Location Audit
- Execution evidence: every required check is green at
338df8b68f5d9cdb8fdec5cbf7a0fcfc505600a3, including unit in 10m45s; author reports 105 focused hook/collector tests plus syntax check - Reviewer falsifier: N/A — the named concern was semantic alignment, falsified directly against the frozen class list and compound-command recognizer
- Test location: N/A — no tests added or moved; no existing test pins the stale prose
Findings: Pass.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 100 - Checked the key vocabulary, compound-command boundary, cross-harness copy surface, and logic-diff boundary; the patch stays at the single owning refusal string.[CONTENT_COMPLETENESS]: 95 - Ticket and PR explain the live failure and exact repair; 5 points reflect the consumed-surface ledger supplied during reviewer polish rather than at intake.[EXECUTION_QUALITY]: 100 - Exact-head required CI is fully green, focused author evidence covers both hook and collector, and the diff changes no executable branch.[PRODUCTIVITY]: 100 - All four close-target ACs are satisfied without broadening scope.[IMPACT]: 48 - A one-line message fix removes an invisible repeated-refusal loop from every affected Claude stop-hook interaction.[COMPLEXITY]: 12 - One template-literal line changes against a frozen two-class contract; cognitive complexity lies only in accurately summarizing the compound-command rule.[EFFORT_PROFILE]: Quick Win - Low mechanical breadth with direct reduction of recurring correction-cycle waste.
Approved at exact head 338df8b68f.
Resolves #15778
One-sentence alignment of the stop-hook's refuse-boilerplate with the material-artifact contract its collector actually implements. The old Stop-key sentence promised three minting classes;
ai/scripts/lifecycle/materialArtifactKey.mjsfreezes two (pr-opened,formal-review) and documents the own-PR RC-response cycle as a deliberate v1 deferral (line 16). The new sentence lists exactly the implemented classes, adds the one-clause standalone-invocation hint forpr-opened(piped/chained/compoundgh pr createnever mints — fail-closed by the collector's documented design), and names the RC-response cycle as real work that is not yet a key class. String-only: no collector, evaluator, or hook-logic change. This closes the invisible-refusal loop where an agent ships a promised artifact class in good faith, emits a valid terminal, and is refused with no visible reason — the live two-refusal specimen is documented on the ticket.Evidence: L2 (string constant in agent-harness hook substrate; full hook + collector unit suites runnable in-sandbox) → L2 required (the AC surface is refusal-prose content and unchanged behavior). Residual: none.
Deltas from ticket
None substantive — the shipped sentence follows the ticket's Fix item 1 with the "(planned, not yet a key)" option folded in as "not yet a key class".
Test Evidence
hooks/laneStateStopHook.spec.mjs+ai/scripts/lifecycle/materialArtifactKey.spec.mjs— 105 passed at338df8b68f(no spec pins the old prose; logic contracts untouched).node --check .claude/hooks/laneStateStopHook.mjs— OK (escaped backticks inside the template literal).None found(agent-harness hook prose only).Post-Merge Validation
gh pr createin an autonomous continuation mintspr-openedand the stop is accepted with aMATERIAL-ALLOWaudit line.Review note
Micro-change exception candidate per
pull-request-workflow.md §6.1: 1 line changed, refusal-prose only, no runtime-behavior delta — stating it here rather than claiming a merge bypass; any peer veto stands.Authored by Vega (Claude Fable 5, Claude Code). Session 2cca0fff-6354-4036-bfdd-fc3320938015.