LearnNewsExamplesServices
Frontmatter
id13711
titleRepair post-review-pickup fenced lane-state docs
stateClosed
labels
bugdocumentationaiarchitecturemodel-experience
assigneesneo-gpt
createdAtJun 21, 2026, 6:40 AM
updatedAtJun 21, 2026, 11:23 AM
githubUrlhttps://github.com/neomjs/neo/issues/13711
authorneo-gpt
commentsCount0
parentIssue13623
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJun 21, 2026, 11:23 AM

Repair post-review-pickup fenced lane-state docs

Closed v13.1.0/archive-v13-1-0-chunk-5 bugdocumentationaiarchitecturemodel-experience
neo-gpt
neo-gpt commented on Jun 21, 2026, 6:40 AM

Context

After the Codex harness restart on 2026-06-21, the repo-local Codex Stop hook live-fired and reported no lane-state block emitted at turn-terminal on a terminal that followed the older human-readable lane-state: convention. A later live-fire also showed the current no-hold policy can still block autonomous terminals even when the descriptor is valid; this ticket does not change that policy. It repairs the documentation/input-contract drift so lifecycle guidance tells agents to emit the fenced machine-readable block that parseLaneState() actually reads.

Live latest-open sweep: checked latest 20 open issues at 2026-06-21T04:39:52Z; no equivalent open ticket found. A2A in-flight claim sweep: latest 30 messages showed Ada's non-conflicting #13710 branch-freshness lane and older closed #13643 claim; no active claim on this narrow post-review-pickup §2.5 repair. Related duplicate-risk audit: closed NOT_PLANNED #13643 was broader (full emission contract, always-loaded pointer, hook directive example, dry-run readiness). This ticket is intentionally narrower and bounded to the existing lifecycle-boundary wording.

Release classification: boardless (MX substrate repair; not release-blocking).

The Problem

post-review-pickup is the lifecycle skill that tells agents what to emit at turn boundaries, but §2.5 still described only prose lane-state: examples. The live parser seam is stricter: ai/scripts/lifecycle/parseLaneState.mjs extracts only a fenced ```lane-state block and returns null when that block is absent. Agents following the old §2.5 wording therefore satisfy the human-readable convention while failing the machine seam, producing noisy Stop-hook diagnostics and weakening hook parity testing.

The Architectural Reality

  • ai/scripts/lifecycle/parseLaneState.mjs documents that the human-readable lane-state: prose line remains, while the machine seam is the fenced lane-state block.
  • .codex/hooks/codex-lane-state-stop.mjs and .claude/hooks/laneStateStopHook.mjs both route final assistant text through the shared parser/validator seam.
  • .agents/skills/post-review-pickup/references/post-review-pickup-workflow.md §2.5 is already the lifecycle-boundary place where agents are told to emit lane-state:.

The Fix

Update only post-review-pickup §2.5 so each lifecycle boundary emits both surfaces: prose for humans and a fenced JSON lane-state block for Stop hooks. Include the minimal descriptor example plus edge notes for no-gate (namedGates: []) and merge-claim evidence (mergeClaim plus field:"mergedAt").

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
.agents/skills/post-review-pickup/references/post-review-pickup-workflow.md §2.5 #13623 no-hold operationalization; parseLaneState.mjs; Codex/Claude Stop hooks Lifecycle boundaries document both human prose and fenced JSON machine emission Prose alone is explicitly not machine emission; no gate uses namedGates: []; merge claims name field:"mergedAt" Same skill payload only; no AGENTS.md or SKILL.md router expansion lint-skill-manifest, lint-agents, substrate size check, focused parser/hook unit tests

Decision Record impact

aligned-with #13623. No ADR change. This keeps the full detail in the skill payload per Progressive Disclosure and does not add always-loaded substrate.

Acceptance Criteria

  • post-review-pickup §2.5 names both emission surfaces: human prose lane-state: and fenced JSON lane-state block.
  • The example includes laneContinuation, namedGates[].ref, and namedGates[].checkedAt, plus notes for empty gates and merge-claim evidence.
  • No AGENTS.md, SKILL.md, hook policy, or parser behavior changes are required for this leaf.
  • Verification includes lint-skill-manifest, lint-agents, substrate size, and focused parser/hook unit coverage.

Out of Scope

  • Reopening the full #13643 emission-contract substrate.
  • Changing Codex or Claude Stop-hook allow/block policy.
  • Adding an always-loaded AGENTS.md pointer.
  • Updating hook reminder prose to show a full descriptor template.
  • #13710 branch-freshness guard work.

Avoided Traps

  • Make parseLaneState() accept prose: rejected because prose cannot carry structured gate evidence like checkedAt and merge-field claims.
  • Resurrect #13643 wholesale: rejected because the operator already closed that broader substrate as too much context. This repair stays at the existing §2.5 lifecycle-boundary instruction.
  • Claim this resolves all hook live-fire friction: rejected because the current no-hold policy can still block autonomous valid terminals by design; this ticket only removes the stale prose-only instruction.

Related

Related: #13623, #13643, #13710

Origin Session ID: 747ae298-5a6e-4416-b90d-7786e184aa54 Handoff Retrieval Hints: post-review-pickup fenced lane-state docs, parseLaneState prose alone not machine emission, Codex Stop hook no lane-state block emitted

tobiu closed this issue on Jun 21, 2026, 11:23 AM
tobiu referenced in commit 9272f11 - "docs(ai): require fenced lane-state machine emission (#13711) (#13712)" on Jun 21, 2026, 11:23 AM