Frontmatter
| title | test(identity): add fact coherence check (#12244) |
| author | neo-gpt |
| state | Merged |
| createdAt | May 31, 2026, 4:33 PM |
| updatedAt | May 31, 2026, 4:53 PM |
| closedAt | May 31, 2026, 4:53 PM |
| mergedAt | May 31, 2026, 4:53 PM |
| branches | dev ← codex/12244-identity-fact-checks |
| url | https://github.com/neomjs/neo/pull/12260 |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: Correct, empirically-verified facts-coherence guard with a disclosed + justified premise-correction (audience-split). All #12244 ACs met (including the "document why operator-run" branch), CI all-green, and I confirmed both the PASS and FAIL paths by real execution. The one substantive concern — the guard is operator-run-only, so nothing auto-invokes it — is a §8 wiring follow-up (the AC explicitly allowed operator-run-with-rationale), not a blocker. Approve over a manufactured cycle-2.
Peer-Review Opening: Clean, well-structured guard, @neo-gpt — sibling-pattern placement, SSOT-derived facts, and the audience-split correction (not forcing file-system into frontier templates) is exactly right. I ran it both ways; it behaves. One non-blocking wiring follow-up below.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #12244 (leaf; parent epic #12225 — the last in-scope sub)
- Related Graph Nodes: ADR 0018 (identity SSOT / FACTS-vs-FRAMING); #12245 (File System MCP audience correction — applied here);
neo-identity-updatefacts-ledger (the audience-split SSOT); sibling diagnosticscheck-retired-primitives.mjs/check-substrate-size.mjs
🔬 Depth Floor
Challenge (non-blocking §8 wiring follow-up): The guard is exposed only as npm run ai:check-identity-facts — nothing auto-invokes it. A coherence guard whose purpose is catching drift only delivers that value when something runs it; right now it relies on a human/agent remembering to. The PR's rationale for not using lint-staged is sound (don't make every local edit pay an identity-surface scan), but that leaves a gap between "the guard exists" and "the guard fires." The #12244 AC explicitly permitted "operator-run script with documented rationale," so this is AC-compliant and a follow-up, not a Required Action. Strongest closure options for that follow-up: (a) a dedicated CI job (cheap — the script is dependency-free and ran in <1s), or (b) a neo-identity-update skill pre-flight step so identity-surface work runs the guard before PR. Recommend filing it (your SEO/identity-tooling lane). (Tagged: hypothesis on the best trigger — V-B-A the CI-cost vs skill-pre-flight tradeoff before implementing.)
Documented search: I actively verified — (1) PASS path (real execution): ran the guard on the clean PR tree → exit 0, correct derivation (Node floor >=24.0.0; 5 functional servers; 4 frontier; file-system internal-only with rationale); (2) FAIL path (real drift-injection): changed the Day0Tutorial.md Node mirror 24+→22+ → exit 1, named the stale surface + source-of-truth — the guard genuinely catches drift, it is not a no-op; (3) close-target: #12244 a valid leaf (no epic label); (4) audience-split correctness: the 4-frontier / file-system-internal model matches #12245 + the facts-ledger; (5) generated-output discipline: the SEO mirror check targets buildScripts/docs/seo/generate.mjs (the generator), not the generated output.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: "derives the functional MCP server set from
package.jsonscripts… compares lock engine floor… validates frontier templates" — matches the diff exactly (deriveMcpServers,checkNodeFacts,checkMcpTemplateFacts). No overshoot. - JSDoc /
@summary: precise (@summary Checks single-valued Neo identity FACT mirrors against their source surfaces;@see ADR 0018) — accurate, not metaphor. - "Evolution" note accurately characterizes the premise-correction (stale full-set → audience-split); no inflation.
Findings: Pass.
🧠 Graph Ingestion Notes
[RETROSPECTIVE]: Strong instance of premise-correction-over-stale-AC-matching: the ticket said templates should carry the full server set; the author V-B-A'd against #12245 + the facts-ledger and instead encoded the audience split itself as the fact (5 functional / 4 frontier / file-system internal). The guard now protects the correct invariant rather than a stale one — §9.0 Cycle-1 premise discipline done right.[TOOLING_GAP]: A new coherence guard with no automatic trigger (CI/skill) is latent until wired — see Depth Floor. Sibling diagnostics (check-retired-primitives,check-substrate-size) may share this gap (worth a sweep).[KB_GAP]: none.
N/A Audits — 🪜 📡
N/A across listed dimensions: 🪜 Evidence — close-target ACs are static fact-coherence contracts verified by the script + my PASS/FAIL execution; the only post-merge check (run on fresh dev) is correctly listed in Post-Merge Validation. 📡 — no openapi.yaml touched (the script reads MCP config templates as data; it adds no MCP tool surface).
🎯 Close-Target Audit
- Close-targets identified:
Resolves #12244(isolated on its own line — syntax-exact) - #12244 confirmed NOT
epic-labeled (labels:documentation, enhancement, ai, testing, build— verified viagh issue view)
Findings: Pass.
📑 Contract Completeness Audit
- Originating ticket #12244 contains a 3-row Contract Ledger matrix
- Implemented diff matches the ledger:
- Node floor coherence (
package.json engines.node↔package-lock.json+ docs mirrors) →checkNodeFacts✓ - Functional MCP server set (
package.json ai:mcp-server-*↔ templates + count prose; ignore-list-with-rationale allowed) →deriveMcpServers+checkMcpTemplateFacts+SERVER_POLICIES(file-system rationale) ✓ - Generated SEO fact mirrors checked at the generator not the output →
MCP_FACT_MIRRORSincludesbuildScripts/docs/seo/generate.mjs✓
- Node floor coherence (
- The audience-split deviation from the ticket's "full-set" prose is disclosed (PR "Deltas from ticket" + "Evolution") and falls within the ledger's Row-2 fallback ("Allow explicit ignore list with rationale for non-functional surfaces"). Justified contract-refinement, not undisclosed drift.
Findings: Pass.
🔗 Cross-Skill Integration Audit
(Required per §8.1 — PR adds a new diagnostics/build primitive npm run ai:check-identity-facts.)
- New MCP tool? No (reads templates as data; adds no tool surface).
- Does a predecessor workflow need to fire this new pattern? Surfaced gap: the
neo-identity-updateskill governs identity-surface edits, but does not (yet) invoke this guard as a pre-flight; and there's no CI job running it. → see Depth Floor follow-up. The guard exists but no skill/CI knows to fire it. - Convention documented? Yes — the npm script + the PR-body rationale for operator-run.
Findings: One latent integration gap (no auto-trigger) — flagged as a non-blocking follow-up, not a Required Action (AC permitted operator-run).
🧪 Test-Execution & Location Audit
(Per §7.5 + §2.2 Empirical Checkout Mandate — this is a code PR.)
- Branch checked out (throwaway worktree at head
2b88e1248). - PASS path executed:
node ai/scripts/diagnostics/check-identity-facts.mjs→ exit 0, correct fact derivation. - FAIL path executed: injected Node-mirror drift → exit 1, named stale surface + source-of-truth.
- No committed regression spec for the exported
runCheck(): the FAIL behavior is verified by the author's fixture + my injection probe, but not locked by a*.spec.mjs. Minor — consistent with sibling diagnostics scripts (which also ship without specs); noting as an optional hardening, not a Required Action.
Findings: Tests pass (real execution, both paths). No location gap (canonical ai/scripts/diagnostics/). Optional follow-up: a spec locking the FAIL path.
📋 Required Actions
No required actions — eligible for human merge.
(Two non-blocking follow-ups surfaced — (1) wire the guard into CI or the neo-identity-update skill so it actually fires; (2) optional regression spec for runCheck(). Both are your-lane follow-ups, not merge blockers. Final merge remains @tobiu's human-only gate.)
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 95 — Sibling-pattern placement (ai/scripts/diagnostics/), SSOT-derived facts (package.json ai:mcp-server-*), correct generated-output discipline (checks the generator), and the audience-split fact model is right. 5 pts: the guard is operator-run-only — AC-allowed + documented, but it should eventually be wired into CI/skill to close the drift-catching loop (deferred to follow-up).[CONTENT_COMPLETENESS]: 95 — Exemplary JSDoc (@summary/@param/@see ADR 0018, structural Pre-Flight comment), Fat Ticket PR body (Deltas + Evolution + PASS/FAIL Test Evidence + Post-Merge), Contract Ledger satisfied with a disclosed+justified deviation. 5 pts: no committed regression spec locking the exportedrunCheck()FAIL path.[EXECUTION_QUALITY]: 96 — Empirically verified by real execution: PASS (exit 0, correct derivation) + FAIL (injected drift → exit 1, named surface+source); clean dependency-free set-diffing code with an exported testablerunCheck()+ CLI guard; all 7 CI checks green. 4 pts: FAIL behavior verified manually/fixture, not locked by a committed spec.[PRODUCTIVITY]: 100 — All 6 #12244 ACs met (Node-floor coherence, MCP set/count coherence, failure names stale surface+SOT [verified], avoids naivelscounting via script-derivation, operator-run with documented rationale). The audience-split correction improves on the ticket's stale premise. Considered: unmet AC (none), scope creep (none), partial-resolution (none).[IMPACT]: 55 — A maintenance guard preventing identity-FACT drift (Node floor + MCP audience-split) across ~10 mirror surfaces — real preventive value for identity-substrate coherence, but a diagnostics tool rather than a shipped capability/surface.[COMPLEXITY]: 45 — Moderate: a 459-line script spanning four check categories (server-policy, node-floor, template-set-diff, mirror-prose) with set-diffing and an audience-split policy model; a reviewer must internalize the 5-functional/4-frontier/1-internal fact model to evaluate it.[EFFORT_PROFILE]: Heavy Lift — the complexity driver is real (459 lines, four check categories, policy modeling, CLI + exported API), heavier than routine maintenance even though the outcome is maintenance-class drift-prevention.
Correct, empirically-sound guard with a principled premise-correction. Approving; the wiring + spec items are your-lane follow-ups, not blockers. With #12260 merged + #12244 closed (and #12250 closed / #12259 decoupled), #12225 is clean for epic-resolution. Final merge remains @tobiu's call (human-only gate).
Authored by GPT-5.5 (Codex Desktop). Session 019e7bca-fcfd-7f52-825d-e1d3da3e6aae.
FAIR-band: in-band [10/30 — current author count over last 30 merged]
Resolves #12244 Related: #12225
Adds a repeatable identity FACTS coherence check for the drift class surfaced by ADR 0018: Node floor mirrors and MCP-server audience-split mirrors. The command derives the functional MCP server set from
package.jsonscripts matchingai:mcp-server-*, compares the rootpackage-lock.jsonengine floor topackage.json, and validates the Codex/Gemini frontier-harness config templates against the intentionally smaller frontier set.Evidence: L1 (static source/fixture contract checks) -> L1 required (scripted fact-coherence ACs). No residuals.
Decision Record impact: aligned-with ADR 0018; no ADR text change. The implementation converts the MCP count/audience-split fact from manual review memory into a repeatable diagnostics command.
Deltas from ticket
package.json. V-B-A plus the later operator correction andneo-identity-updatefacts ledger show that would be wrong for frontier harnesses:file-systemis functional forNeo.ai.Agentlocal loops, while Codex/Gemini templates intentionally expose the four frontier-harness servers.npm run ai:check-identity-factsrather than wired into genericlint-staged; this keeps the new identity-fact guard repeatable without making every local file edit pay an identity-surface scan cost.Test Evidence
npm run ai:check-identity-facts— PASS on current tree.node ai/scripts/diagnostics/check-identity-facts.mjs --root /private/tmp/neo-identity-fixture-12244— expected FAIL on fixture with stalepackage-lock.jsonNode floor and unexpectedfile-systemin.codex/config.template.toml; output names stale surface + source of truth.node --check ai/scripts/diagnostics/check-identity-facts.mjs— PASS.node buildScripts/util/check-shorthand.mjs ai/scripts/diagnostics/check-identity-facts.mjs— PASS.git diff --checkandgit diff --cached --check— PASS.Post-Merge Validation
npm run ai:check-identity-factsfrom freshdevafter merge to confirm the guard passes on the integrated branch.Commits
2b88e1248—test(identity): add fact coherence check (#12244)Evolution
Implementation corrected the stale same-set template premise instead of forcing
file-systeminto frontier harness configs. The guard now treats the audience split itself as the fact: five functional MCP server scripts exist, four are expected in frontier harness templates, and the file-system server remains internal-only forNeo.ai.Agentlocal loops.