LearnNewsExamplesServices
Frontmatter
id12990
titleClose-target split rule + Ledger trigger + gitlab-pat healthcheck seam
stateClosed
labels
documentationenhancementaimodel-experience
assigneesneo-gpt
createdAtJun 12, 2026, 1:40 PM
updatedAtJun 13, 2026, 5:25 PM
githubUrlhttps://github.com/neomjs/neo/issues/12990
authorneo-fable
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 13, 2026, 5:25 PM

Close-target split rule + Ledger trigger + gitlab-pat healthcheck seam

Closed v13.1.0/archive-v13-1-0-chunk-1 documentationenhancementaimodel-experience
neo-fable
neo-fable commented on Jun 12, 2026, 1:40 PM

Context

One morning (2026-06-12, the v13 publish-hold window) produced three completeness-gate frictions, each costing real review cycles. This ticket absorbs all three into the substrate that should have prevented them — the friction → gold unit for the day.

(a) Reviewer-prescribed close-target downgrades are mechanically un-greenable. Cycle-1 reviews on PR #12971 and PR #12979 prescribed downgrading Resolves #NRefs #N (close-target hygiene: the PRs didn't deliver every AC). But agent-pr-body-lint enforces the operator rule (#12367): Resolves #N is the mandatory closing keyword — Refs/Related alone can never pass. Both PRs went red; the reviewer parked blocked; diagnosis was non-obvious (a stale event-payload twin run passed, making a rerun look like the fix — actions/github-script lints the frozen context.payload.pull_request.body snapshot, so the failing run was the truthful one). Resolution took 2 extra author cycles: ticket re-scopes/splits + Resolves restoration. The linter's own comment block names the sanctioned shape ("a ticket that needs N PRs… must become an epic + subs or be split") — but the pr-review payload never tells the reviewer side, so reviewers keep prescribing the forbidden shape.

(b) Consumed-surface tickets are born Ledger-less; every one costs a yield round-trip. Four intake yields in one morning — #12951, #12957, #12884, #12931 — all "blocked until the ticket carries a Contract Ledger", plus a REQUEST_CHANGES cycle (PR #12979 cycle-3 → #12969 Ledger backfill, then instant approval). ticket-create-workflow.md §5 lists the Contract Ledger Matrix as "(when applicable)" with no applicability test — the trigger is too weak to fire at authoring time, so the cost lands downstream at intake/review instead.

(c) The gitlab-pat healthcheck seam is charted nowhere canonical. The first deployment ever to run NEO_AUTH_MODE=gitlab-pat (a private remote stack, 2026-06-12) discovered: setupGitlabPat installs app.use(requireBearerAuth(...)) app-wide with no exemption (ai/mcp/server/shared/services/AuthService.mjs:230), and the in-container healthchecks send no bearer unless NEO_MCP_HEALTHCHECK_TOKEN is set (ai/scripts/diagnostics/mcpHealthcheck.mjs:39,50,69-70) → every probe 401s → kb/mc never reach service_healthy → orchestrator depends_on conditions never satisfy → a fresh docker compose up structurally never completes. Found at review time (fix: a 2-line env passthrough), but only because the reviewer traced the full chain — ai/deploy/docker-compose.yml never sets NEO_AUTH_MODE, so the canonical compose silently doesn't chart the seam for the next bearer-mode deployment.

The Architectural Reality

  • .github/workflows/agent-pr-body-lint.yml:71-92 — the Resolves mandate + the split prescription (authoritative, already correct; NOT touched here).
  • .agents/skills/pr-review/references/pr-review-guide.md — the close-target / Contract-Completeness audit sections; read-on-demand payload (not turn-loaded).
  • .agents/skills/ticket-create/references/ticket-create-workflow.md §5 — the Contract Ledger Matrix bullet; same payload tier.
  • ai/deploy/docker-compose.yml:75-80,133-138 — the kb/mc healthcheck blocks (no auth-mode seam note).
  • learn/agentos/process/contract-ledger.md — the Ledger discipline doc the trigger should point at.

The Fix

Three line-level additions, one PR:

  1. pr-review-guide.md (close-target section, ≤4 lines): when a PR over-claims its close target, the reviewer prescription is "split/re-scope the ticket so Resolves stays honest" — never "downgrade to bare Refs", which agent-pr-body-lint mechanically rejects (rule #12367). Include the stale-snapshot note: a passing duplicate lint run on an edited body may be linting the pre-edit event payload; the fix is a body/ticket fix, not a rerun.
  2. ticket-create-workflow.md §5 (≤3 lines): replace the bare "(when applicable)" with the applicability test — "if the ticket introduces, modifies, or removes ANY surface another human, agent, or system consumes (tool answer shapes, configs/env, lifecycle scripts, public methods, docs flows), the Ledger is REQUIRED at creation; a consumed-surface ticket filed without one will be intake-yielded back" — citing the 2026-06-12 four-yield day as the empirical anchor.
  3. ai/deploy/docker-compose.yml (≤4-line comment on each of the two healthcheck blocks): if this deployment enables NEO_AUTH_MODE=gitlab-pat, the self-probes must authenticate — set NEO_MCP_HEALTHCHECK_TOKEN (consumed by mcpHealthcheck.mjs) or the container never reaches service_healthy and dependent services never start.

Contract Ledger

# Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
1 pr-review-guide.md close-target audit (agent-consumed review payload) agent-pr-body-lint.yml:71-92 (rule #12367) reviewers prescribe split/re-scope, never bare-Refs none needed — additive guidance the payload IS the doc PR #12971 + PR #12979 cycle history, 2026-06-12
2 ticket-create-workflow.md §5 Ledger bullet (agent-consumed creation payload) learn/agentos/process/contract-ledger.md + intake-gate practice "(when applicable)" → explicit consumed-surface applicability test none — additive same yields on #12951/#12957/#12884/#12931 + #12969 backfill cycle
3 ai/deploy/docker-compose.yml healthcheck blocks (operator-consumed deploy reference) AuthService.mjs:230 + mcpHealthcheck.mjs:39,50 comment charts the bearer-gate/self-probe seam + the token env none — comment only compose comment the 2026-06-12 remote-deployment review finding (fix verified: token passthrough + docker compose config exit 0)

Decision Record impact

none (read-on-demand payload prose + compose comments; no gates, no loaded-byte growth, no behavior change).

Substrate Accretion Defense

All three additions live in read-on-demand surfaces (no turn-loaded growth; lint-skill-manifest byte budgets unaffected — no SKILL.md router edits). Decay dispositions: row 1 retires if the linter ever grows an explicit no-close exemption anchor; row 2 retires if Ledger validation becomes a mechanical create-time lint; row 3 retires if requireBearerAuth gains a loopback/health exemption upstream. Implementer note: per the compaction taxonomy gate, read learn/agentos/decisions/0007-agents-md-compaction-taxonomy.md before editing the skill payloads.

Acceptance Criteria

  • pr-review-guide.md carries the split-not-Refs reviewer prescription + the stale-snapshot rerun note (≤4 lines, close-target section).
  • ticket-create-workflow.md §5 carries the consumed-surface applicability test (≤3 lines).
  • ai/deploy/docker-compose.yml healthcheck blocks carry the gitlab-pat/NEO_MCP_HEALTHCHECK_TOKEN seam comment (both kb + mc).
  • lint-skill-manifest + lint-pr-body green on the PR.

Out of Scope

  • Changing agent-pr-body-lint.yml itself (it is correct; this charts it for reviewers).
  • New mechanical gates (create-time Ledger linting is a possible successor, deliberately not this ticket).
  • An AuthService loopback/health exemption (weakens the gate; the token route is the supported shape).
  • The private deployment's own repo (fixed there already at review time).

Related

#12367 (the Resolves operator rule), #12969/PR #12979 + #12970/PR #12971 (the collision pair), #12951/#12957/#12884/#12931 (the yield quartet), #12983 (sibling ai/deploy compose wiring lane), PR #12960 (the freshness-gate substrate precedent for payload-tier additions).

Release classification: post-release (process/doc substrate; nothing release-blocking).

Live latest-open sweep: checked latest 20 open issues at 2026-06-12T11:35Z + re-checked latest 10 at 11:39Z; no equivalent found. A2A in-flight sweep (last 60 min, all read-states): no competing claim on this scope.

Origin Session ID: e605ce21-3668-445c-bc00-45896aa9a092

Retrieval Hint: "close-target split Refs downgrade lint collision Contract Ledger trigger healthcheck bearer gate seam"