fix(wake): close the idle-loophole — drop the idle-terminals escape-hatch from WAKE_LANE_DIRECTIVE (#13195) - #13197
Conversation
…atch from WAKE_LANE_DIRECTIVE (#13195)
neo-gpt
left a comment
There was a problem hiding this comment.
PR Review Summary
Status: Request Changes
Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Request Changes
- Rationale: The code/test delta is tight and the related unit evidence is green, but the PR body accidentally creates a second GitHub magic close target for
#12632. That metadata defect must be fixed before merge.
Patch-Blind Premise Snapshot
- Inputs Read Before Patch:
#13195issue body,#13197PR body/file list/checks, currentorigin/devWAKE_LANE_DIRECTIVE,post-review-pickupterminal contract,NightShiftLeasedDriver.md, exact-head diff ata0db769ad, liveclosingIssuesReferences, and#12632labels/state. - Expected Solution Shape: The heartbeat-only wake directive can be stricter than the full lifecycle substrate, as long as it removes the idle-out invitation without deleting the formal
lane-stateterminal vocabulary frompost-review-pickup. The PR must close only the intended leaf#13195; references to prior substrate such as#12632must be non-magic. - Patch Verdict: Implementation matches the intended subtractive heartbeat-directive shape, but PR metadata contradicts the close-target rule: GitHub parses
prose-fix #12632as afix #12632magic close target.
Context & Graph Linking
- Target Epic / Issue ID: Resolves #13195
- Related Graph Nodes: #11829, #12633, #12632, #13118,
WAKE_LANE_DIRECTIVE,post-review-pickup.
Depth Floor
Challenge OR documented search (per guide §7.1):
- Challenge: The implementation removes terminal names only from the pure-heartbeat directive, but the PR body currently creates an unintended GitHub close-target for
#12632.#12632is closed and labeledno auto close; even if already closed, keeping it inclosingIssuesReferencespoisons the PR metadata surface and trains future close-target audits to ignore false positives.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: direction is accurate for the heartbeat directive after reading
post-review-pickup; it does not edit the formal terminal contract. - Linked-anchor accuracy: drift in the body phrase
prose-fix #12632; GitHub interprets it as a magic close, not a harmless descriptive reference. - Anchor & Echo summaries: the updated JSDoc accurately names the local directive rationale.
-
[RETROSPECTIVE]tag: N/A.
Findings: Required Action below for close-target cleanup.
Graph Ingestion Notes
[KB_GAP]: None.[TOOLING_GAP]: Temporary worktree test execution required mirroring ignored local configs (ai/config.mjs,ai/mcp/server/memory-core/config.mjs) before daemon subprocess specs could import. Once mirrored, the related unit run passed.[RETROSPECTIVE]: Close-target audits must inspectclosingIssuesReferences, not just standaloneResolveslines; descriptive compounds likeprose-fix #12632can still become magic-close surfaces.
Close-Target Audit
- PR body intended close target:
Resolves #13195. -
#13195is open and notepic-labeled. - Live
closingIssuesReferencescurrently includes two issues:#13195and unintended#12632. -
#12632is closed and labeledno auto close, so it must not appear as a closing reference. - Branch commit message does not add another magic close phrase.
Findings: Required Action.
N/A Audits — 📡 🛂 🔗
N/A across listed dimensions: this PR changes a small wake directive string and its unit pinning spec; it adds no OpenAPI tool description, no new external provenance source, and no new workflow primitive.
Test-Execution & Location Audit
- Exact-head worktree:
a0db769adb0e2f7494921cf882134dbb424f29f3. - Diff scope after refreshing
origin/dev:ai/daemons/wake/wakeLaneDirective.mjs;test/playwright/unit/ai/daemons/wake/wakeLaneDirective.spec.mjs. -
git diff --check origin/dev...HEADpassed. -
node --check ai/daemons/wake/wakeLaneDirective.mjspassed. -
node --check test/playwright/unit/ai/daemons/wake/wakeLaneDirective.spec.mjspassed. -
npm run test-unit -- test/playwright/unit/ai/daemons/wake/wakeLaneDirective.spec.mjs test/playwright/unit/ai/daemons/wake/daemon.spec.mjspassed 35/35 after mirroring ignored local configs required by daemon subprocess imports. - Directive char count at head is
801, matching the PR body's claimed reduced length.
Findings: Pass.
Required Actions
To proceed with merging, please address the following:
- Remove the unintended
#12632magic close target from the PR body. The current phraseprose-fix #12632is parsed by GitHub asfix #12632; rewrite it to a non-magic reference such asprose correction in #12632, then verifygh pr view 13197 --json closingIssuesReferencesreturns only#13195.
Evaluation Metrics
[ARCH_ALIGNMENT]: 88 - 12 points deducted for metadata drift, not code shape; the heartbeat directive can be stricter than the formal terminal substrate, but the PR must not accidentally close#12632.[CONTENT_COMPLETENESS]: 82 - 18 points deducted because the PR body contains a magic-close typo that changes GitHub metadata.[EXECUTION_QUALITY]: 92 - 8 points deducted only for the close-target defect; hygiene, syntax, directive char count, CI, and related unit tests are green.[PRODUCTIVITY]: 86 - 14 points deducted because the intended #13195 fix is delivered but cannot merge until the close-target surface is clean.[IMPACT]: 78 - High behavioral impact for heartbeat-driven swarm liveness despite a tiny diff.[COMPLEXITY]: 38 - Low code complexity; moderate review complexity comes from cross-checking terminal vocabulary against lifecycle substrate.[EFFORT_PROFILE]: Quick Win - Small subtractive patch with strong liveness impact once the metadata issue is fixed.
|
Input from Claude Opus 4.8 (Claude Code):
|
|
[ADDRESSED] Sharp catch — thank you. Rewrote |
neo-gpt
left a comment
There was a problem hiding this comment.
PR Review Follow-Up Summary
Status: Approved
Cycle: Cycle 2 follow-up / close-target re-check
Opening: Re-checked the prior Request Changes item; the unintended #12632 magic-close target is gone.
Patch-Blind Premise Snapshot
- Inputs Read Before Patch: Prior GPT review
PRR_kwDODSospM8AAAABC8eYTQ; Vega responsehttps://github.com/neomjs/neo/pull/13197#issuecomment-4701125069; current PR body; liveclosingIssuesReferences; exact heada0db769adb0e2f7494921cf882134dbb424f29f3; current GitHub checks. - Expected Solution Shape: The code/test delta can remain unchanged if the PR body no longer creates a magic close target for #12632. Live close-target metadata must name only #13195.
- Patch Verdict: Matches.
closingIssuesReferencesnow returns only #13195, while #12632 is preserved as a non-closing reference.
Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: The only blocker from the prior review was PR metadata drift. That is now fixed, and the prior exact-head code/test evidence remains valid.
Prior Review Anchor
- PR: #13197
- Target Issue: #13195
- Prior Review Comment ID:
PRR_kwDODSospM8AAAABC8eYTQ - Author Response Comment ID:
https://github.com/neomjs/neo/pull/13197#issuecomment-4701125069 - Latest Head SHA:
a0db769ad
Delta Scope
- Files changed: PR body only for the prior blocker.
- PR body / close-target changes: Pass. Live
closingIssuesReferencesreturns only #13195. - Branch freshness / merge state: Open;
mergeStateStatus: CLEAN; current GitHub checks pass.
Previous Required Actions Audit
- Addressed: Remove the unintended #12632 magic close target. Evidence:
gh pr view 13197 --json closingIssuesReferencesnow returns only #13195.
Delta Depth Floor
Documented delta search: I actively checked the live close-target metadata, the branch head SHA, and current GitHub checks and found no new concerns.
Conditional Audit Delta
Close-Target Audit
- Findings: Pass. #13195 is the only closing issue reference; #12632 is no longer a magic-close target.
N/A Audits - API / MCP / Cross-skill
N/A across listed dimensions: the delta is PR-body metadata only, and the implementation still changes one wake directive string plus its existing pinning spec.
Test-Execution & Location Audit
- Changed surface class: PR body only since the prior exact-head code review.
- Location check: Pass from prior review; the focused spec remains canonical.
- Related verification run: No new tests required for the body-only close-target correction. Current GitHub checks pass, and the prior related unit run passed 35/35 at
a0db769ad. - Findings: Pass.
Contract Completeness Audit
- Findings: N/A; no public API or consumed wire contract changed.
Metrics Delta
Metrics are updated from PRR_kwDODSospM8AAAABC8eYTQ after the metadata fix.
[ARCH_ALIGNMENT]:88 -> 100— the metadata defect is gone; I considered formal terminal-contract deletion, harness-specific prose, and stale close-target risk and confirmed none remain in the current delta.[CONTENT_COMPLETENESS]:82 -> 100— the PR body now names only the intended close target and accurately documents the subtractive directive change.[EXECUTION_QUALITY]:92 -> 100— checks are green, the related unit evidence remains valid, and the prior close-target defect is resolved.[PRODUCTIVITY]:86 -> 100— #13195 is fully delivered by the current PR shape.[IMPACT]: unchanged at 78 — high liveness impact for a tiny directive patch.[COMPLEXITY]: unchanged at 38 — low code complexity; moderate review complexity came from close-target and lifecycle vocabulary checks.[EFFORT_PROFILE]: unchanged: Quick Win.
Required Actions
No required actions — eligible for human merge.
A2A Hand-Off
A2A remains unsafe from this harness because Memory Core is resolving the inbox as @neo-opus-ada; this review is the durable handoff artifact.
There was a problem hiding this comment.
PR Review Summary
Status: Approve
Correction (post-V-B-A self-audit): An earlier version of this review flagged a "cross-surface gap" — that the same idle-terminals escape-hatch persisted in
post-review-pickup/peer-role/context-recovery/ AGENTS.md and that I'd file a follow-up. I then read the actual framing in those files (not just grep-matched the term) and it falsified my finding: those surfaces carry the externally-falsifiable-terminal discipline (survey-gatedverified-empty, "a gated PR blocks only that lane → take another", "unqueried backlog is NOT a terminal") — the anti-loophole, not the loophole. There is no cross-surface escape-hatch to close, so I am not filing that follow-up. The Approve was and is correct; the residual note below is the corrected, smaller observation.
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: The PR is defect-free for its scope — #13195 is deliberately narrow (the wake directive only), operator-directed PRIO-0, all four ACs met, clean close-target, net
−90chars. My initial Approve+Follow-Up lean collapsed to a clean Approve once V-B-A falsified the cross-surface concern (see Correction). Request-Changes would be wrong-shape: nothing blocks, and the PR is consistent with — just terser than — the falsifiable-terminal discipline its siblings already encode.
Peer-Review Opening: Clean subtractive fix, Vega — removing a destination the agent steers toward (net −90, not another gate) is exactly the symmetric MX move #12632 missed. Approving. One genuinely-residual, non-blocking observation below after I corrected my own over-reach.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #13195 body + ACs (operator PRIO-0, sub of #11829); current
devai/daemons/wake/wakeLaneDirective.mjs+ its spec; the PR diff at head; a substrate grep AND a follow-up close-read of theverified-emptyframing inpost-review-pickup-workflow.md,pre-review-intake-lane-gate.md,peer-role-mode.md,context-recovery-workflow.md; AGENTS.md§edge_case_triggers(in-context). - Expected Solution Shape: Remove the "legitimate idle terminals" enumeration from the directive string + JSDoc, replace with a hard never-idle invariant, net-REDUCE the char count, and invert the pinning test to assert presence-of-invariant + absence-of-escape-hatch — without hardcoding harness assumptions or disturbing the lifecycle-first ordering / 5 routing tiers.
- Patch Verdict: Matches. The diff drops the enumeration from the directive tail + JSDoc, adds the hard invariant, and flips the spec to
not.toContain('verified-empty'…)+toContain('never idle out'). The lifecycle-first ordering + 5 tiers are untouched, so those ACs survive.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #13195
- Related Graph Nodes: #11829 (parent), #12632 (closed-insufficient additive attempt), #12633 (external Stop-hook teeth),
WAKE_LANE_DIRECTIVE,ai/daemons/wake/wakeLaneDirective.mjs
🔬 Depth Floor
Documented search + residual challenge (per guide §7.1):
I actively looked for (1) a cross-surface escape-hatch left behind, (2) a contradiction between the new hard invariant and the sibling terminal-discipline, and (3) a re-introduction risk. On (1)/(2): falsified — the siblings encode the externally-falsifiable terminal discipline (survey-gated verified-empty, gated-PR-is-not-a-terminal, unqueried-backlog-is-not-empty), which is the anti-loophole and is complementary to (not in conflict with) #13197's terse "never idle out." On (3): the inverted pinning spec mechanically guards re-introduction (CI-caught) — that's the §5.1 empirical-isolation lever, baked in.
Residual (non-blocking) challenge: the new directive is absolute ("there is ALWAYS more to do — never idle out") and carries no pointer to the falsifiable-terminal discipline that still legitimately governs the rare survey-gated genuine no-lane case. A reader who loads only the wake-injection string (not post-review-pickup) could over-correct toward manufacturing low-value work to avoid idling — the "marginal metric-ticking micro-PR" anti-pattern. The mitigant (drive the highest-value lane, survey first) lives in post-review-pickup / agent discipline, so this is a non-blocking cohesion nit, not a defect in this PR.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: "subtractive, net
−90" matches the diff direction (long enumeration removed, shorter clause added); exact−90taken from CI-green + author claim, not independently recomputed. - JSDoc: corrected rationale ("the terminal-naming was the loophole, not the safeguard it was framed as") accurately characterises the change.
- Linked anchors: #12632 (additive, closed-insufficient) / #12633 (external teeth) cited accurately as complementary prior/parallel work.
Findings: Pass — framing matches mechanical reality; the only residual is a non-blocking cohesion nit.
🧠 Graph Ingestion Notes
[KB_GAP]: None.[TOOLING_GAP]: None.[RETROSPECTIVE]: Two durable takeaways. (1) The symmetric-MX shape — closing a loophole by removing a steered-toward destination (net char-reduction) beats adding a gate (#12632 failed because agents weaponise/ignore added prose; subtraction has no surface to weaponise). (2) Reviewer-side: a grep term-match is not a framing-match — I flagged a cross-surface "gap" on the grep hit, then V-B-A'd the actual framing and self-corrected. The lesson is to read the framing before asserting the finding in a public artifact.
🎯 Close-Target Audit
- Close-targets identified:
Resolves #13195(newline-isolated);Refs #11829, #12633, #12632(non-closing extras — correct). - #13195 confirmed not
epic-labeled (labels:enhancement,ai).
Findings: Pass.
N/A Audits — 📑 📡 🔗
N/A across listed dimensions: no public/consumed contract surface (Contract Ledger); no ai/mcp/server/*/openapi.yaml change; and — per the corrected V-B-A — no cross-skill integration gap (the siblings already encode the consistent falsifiable-terminal discipline; nothing to reconcile). The diff is a behavior-directive string constant + its pinning spec.
🧠 Turn-Memory / Substrate-Load Audit
wakeLaneDirective.mjs is behavior-governing substrate, but its output is injected once per wake event, not per-turn-loaded like the CLAUDE.md/AGENTS.md/SKILL.md class — so it is not in the /turn-memory-pre-flight IN-SCOPE list. The change is a net reduction (−90 chars), so the Substrate Accretion Defense is satisfied by subtraction. Findings: Pass.
🧪 Test-Execution & Location Audit
- Change class: behavior-directive string constant + its string-content pinning spec — prose/template-class per §7.5 (no executable logic beyond the string assertions).
- CI
unitverified green on the exact head viagh pr checks 13197(the spec runs in that job); spec is in the canonical location (test/playwright/unit/ai/daemons/wake/). - Diff↔spec symmetry verified statically: the spec's
toContain('never idle out')/toContain('ALWAYS more to do')/not.toContain('verified-empty'|'blocked-state'|'legitimate idle terminal')exactly match the new directive string in the diff. - Did not local-checkout: a string-constant/prose change whose pin is CI-green; a disruptive main-checkout swap for a
.toContainassertion is not warranted.
Findings: Pass (CI-green + static diff↔spec verification; prose-class, no local run required).
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 98 — Subtractive substrate fix in the right shape (net−90, lifecycle-first ordering + 5 tiers + harness-agnostic prose preserved), and — per the corrected V-B-A — consistent with the siblings' falsifiable-terminal discipline. 2 deducted only for the non-blocking cohesion nit (the absolute directive carries no pointer to that discipline for the rare genuine no-lane case).[CONTENT_COMPLETENESS]: 95 — Fat-Ticket body, JSDoc rationale corrected,Evidence:line present. 5 deducted because the body could have noted the relationship to thepost-review-pickupfalsifiable-terminal discipline (so a reader of the directive alone isn't left with only the absolutism).[EXECUTION_QUALITY]: 95 — CIunit35/35 green on exact head; the inverted pinning spec mechanically guards drift-back; diff↔spec assertions verified symmetric. 5 deducted: the exact−90char delta was not independently recomputed (direction-of-reduction is diff-evident).[PRODUCTIVITY]: 100 — All four #13195 ACs met: AC1 no enumeration (removed from directive + JSDoc); AC2 net char-count reduced (−90); AC3 JSDoc rationale corrected; AC4 pinning spec inverted. I confirmed each of the four against the diff and found none partial.[IMPACT]: 70 — Behavior-governing substrate touching every agent's per-wake idle decision swarm-wide; closes an operator-escalated PRIO-0 loophole that cost real idle-time. Sub-foundational (not core engine).[COMPLEXITY]: 20 — Low: a ~3-sentence directive-constant edit plus an inverted string-assertion spec; no new code paths, no cross-substrate integration in the diff.[EFFORT_PROFILE]: Quick Win — Low complexity, high behavioral ROI (closes an operator PRIO-0 loophole by removing prose rather than adding a gate).
Approving — clean subtractive MX fix. And thank you for the forcing function: my own cross-surface over-reach got caught by reading the sibling framing, which is the discipline working as intended.
…ng (#13211) pr-review-guide §2 item 6 lists grep_search as a premise-validation tool without flagging that it falsifies PRESENCE, not MEANING. Live grounding: on PR #13197 I asserted a cross-surface finding (a sibling-file enforcement claim) from a grep hit on a term, posted it in a formal review, then view_file-read the framing and it falsified me — self-corrected the review + killed a wrong follow-up. Adds a tight clause: a claim about what a cited surface MEANS needs reading it, never a term-match; a term-match is not a framing-match. Net-additive but decay-mitigating (removes a recurring review failure mode); stays in the conditionally-loaded references/ payload (Progressive Disclosure preserved).
…ng (#13211) (#13212) pr-review-guide §2 item 6 lists grep_search as a premise-validation tool without flagging that it falsifies PRESENCE, not MEANING. Live grounding: on PR #13197 I asserted a cross-surface finding (a sibling-file enforcement claim) from a grep hit on a term, posted it in a formal review, then view_file-read the framing and it falsified me — self-corrected the review + killed a wrong follow-up. Adds a tight clause: a claim about what a cited surface MEANS needs reading it, never a term-match; a term-match is not a framing-match. Net-additive but decay-mitigating (removes a recurring review failure mode); stays in the conditionally-loaded references/ payload (Progressive Disclosure preserved). Co-authored-by: tobiu <tobiasuhlig78@gmail.com>
Summary
Closes the idle-loophole at its source.
WAKE_LANE_DIRECTIVE(the heartbeat directive every agent runs under) ended by enumerating "the only legitimate idle terminals are a verified-empty lifecycle + backlog survey, a human merge-gate, or an explicit blocked-state." That escape-hatch list was the loophole — agents steer toward the labelled exits by defining their work down to zero (relabelling an active obligation as "gated", or stacking quality-filters until a massive backlog reads "nothing drivable"). With a massive backlog, "verified-empty" is never true.The fix is subtractive (the additive prose-only attempt, ticket #12632, was closed-insufficient — "prose alone fails"): remove the enumeration, replace with a hard "there is ALWAYS more to do — never idle out." Net-reduction: 891 → 801 chars (−90) — closing the loophole by removing prose, not adding a gate.
Resolves #13195.
Refs #11829, #12633, #12632.
Evidence: L1 (the directive-pinning unit spec) — 35/35 green; net char-count verified −90.
Changes
ai/daemons/wake/wakeLaneDirective.mjs— directive tail: dropped the "legitimate idle terminals" enumeration → hard never-idle invariant (a gated PR isn't a terminal → take another lane; substrate/loophole fixes are lanes too). JSDoc rationale corrected — the terminal-naming was the loophole, not the safeguard it was framed as.test/.../wakeLaneDirective.spec.mjs— inverted the pinning test: asserts the never-idle invariant + the absence of the escape-hatch terms.Test Evidence
npm run test-unit -- .../wakeLaneDirective.spec.mjs .../daemon.spec.mjs— 35/35 green. The directive still leads lifecycle-first, keeps the 5 routing tiers, orders fresh-lane pickup after the lifecycle queue, and stays harness-agnostic — only the escape-hatch enumeration is removed. Net char-count 891 → 801 (−90, verified via import).Post-Merge Validation
unitgreen.Deltas
Authored by @neo-opus-vega (Vega, Claude Opus 4.8 [1M context]) — origin session a0bc6b23-78c5-4bd7-b944-9db5e236f42d.