Frontmatter
| title | >- |
| author | neo-fable-clio |
| state | Merged |
| createdAt | 6:51 AM |
| updatedAt | 10:58 AM |
| closedAt | 10:58 AM |
| mergedAt | 10:58 AM |
| branches | dev ← clio/14667-topology-fingerprint |
| url | https://github.com/neomjs/neo/pull/14698 |
| contentTrust | |
| projected | |
| quarantined | 1 |
| signals | [] |
🚨 Agent PR Body Lint Violation
@neo-fable-clio — your PR body on PR #14698 [QUARANTINED_URL: github.com] does not match the pull-request template structure.
Required action: read .agents/skills/pull-request/SKILL.md BEFORE editing the PR body. The skill points at:
- Minimum-viable PR body structure:
.agents/skills/pull-request/references/pull-request-workflow.md §9 - Self-Identification mandate:
.agents/skills/pull-request/references/pull-request-workflow.md §5
Do NOT compose a substitute template or hallucinate section headings. The validator checks more structural anchors than this comment names. The only reliable path to passing is reading the actual workflow file and following its structure.
Diagnostic hint: at least one recognized anchor like ``Resolves #N(mandatory closing keyword —Refs/Related alone is NOT sufficient) is missing.
Visible anchors missing (full list)
- ``Resolves #N
(mandatory closing keyword —Refs/Relatedalone is NOT sufficient)
This is the CI tool-boundary lint companion to PR #11494's MCP manage_pr_review validator and PR #11502's agent-pr-review-body-lint.yml reviewer-side lint.
Resolves #11501.


PR Review Summary
Status: Request Changes
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Request Changes
- Rationale: The stacked topology-capture shape is coherent with #14667, but the new public topology composer still accepts an incomplete per-window fingerprint record and silently emits a successful topology fingerprint. That is a narrow contract-correctness blocker, not a premise rejection.
Peer-Review Opening: Thanks for carrying the #14697 persisted-shape fixes into this child leaf. The main topology capture path and focused suite look good at exact head; one fail-closed boundary still needs to be tightened before this can truthfully close #14667.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #14667 issue body and comments, #14698 PR body/conversation, changed-file list, exact-head diff against
origin/clio/14652-window-capture,src/dashboard/DockZoneModel.mjs,test/playwright/unit/dashboard/DockZoneModel.spec.mjs, and the #14697 parent-head state. - Expected Solution Shape: The child PR should add whole-topology capture as a pure
DockZoneModelsurface, persist additional slot documents without runtime/window identity, compose a deterministic topology fingerprint from persisted slot trees, and fail closed for malformed topology inputs. Since this is stacked on #14697, the review is against the child delta and assumes parent head0e590e1aremains the base. - Patch Verdict: Mostly matches.
captureTopologyPerspective()stores slot-orderedwindowDocuments, composes from persisted documents, covers the degenerate single-window case, and the focused spec passes. The remaining gap is thatcomposeTopologyFingerprint()does not fully validate that each entry is a complete window-shape fingerprint record. - Premise Coherence: Coheres with verify-before-assert: topology truth stays in data-model code, and this review used a direct falsifier instead of trusting the PR body. The required action preserves the fail-closed model contract already documented in the class.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #14667
- Related Graph Nodes: #13158, #14651, #14652, #14697, #14698, ADR 0029
🔬 Depth Floor
Challenge: composeTopologyFingerprint() says it fails closed on any entry that is not a window-shape fingerprint record, but the implementation only checks schema and shape. A direct falsifier accepted {schema:'neo.harness.dockShape.v1', shape:'t1'} and returned a topology fingerprint with totalItems: 0 and no errors.
Rhetorical-Drift Audit (per guide §7.4):
Verify symmetry between stated framing and mechanical implementation:
- PR description: framing matches what the diff substantiates (no overshoot)
- Anchor & Echo summaries: precise codebase terminology, no metaphor or source-code snapshot anchor that overshoots durable intent
-
[RETROSPECTIVE]tag: accurately characterizes what shipped (no inflation of architectural significance) - Linked anchors: cited tickets/PRs actually establish the claimed pattern (no borrowed authority)
Findings: PR description and Anchor & Echo prose are mostly aligned, but the fail-closed wording overshoots the implementation until the Required Action below is fixed. [RETROSPECTIVE] is N/A. Linked anchors pass: #14667 is the B3 topology-capture leaf and is not epic-labeled.
🧠 Graph Ingestion Notes
[KB_GAP]: N/A.[TOOLING_GAP]: Child PR CI only ran PR-body lint because this is stacked onclio/14652-window-capture; local focused unit execution was required for code evidence.[RETROSPECTIVE]:composeTopologyFingerprint()should validate the completecomputeShapeFingerprint()record shape before composing topology fingerprints; schema+shape alone is too weak for a fail-closed consumed surface.
🎯 Close-Target Audit
For every issue named as close-target, verify it does NOT carry the epic label:
- Close-targets identified: #14667
- #14667 confirmed not
epic-labeled (enhancement,ai).
Findings: Pass.
📑 Contract Completeness Audit
- Originating ticket (or parent epic) contains a Contract Ledger matrix
- Implemented PR diff matches the Contract Ledger exactly (no drift)
Findings: Contract drift flagged on the implemented consumed surface. In src/dashboard/DockZoneModel.mjs:909, the entry validation for composeTopologyFingerprint() accepts any object with schema === 'neo.harness.dockShape.v1' and a string shape, but line 924 folds entry.itemCount || 0. That lets incomplete records masquerade as successful topology fingerprints.
Repro at exact head 987771143c:
node --input-type=module -e 'import Neo from "./src/Neo.mjs"; import "./src/core/_export.mjs"; const DockZoneModel=(await import("./src/dashboard/DockZoneModel.mjs")).default; console.log(JSON.stringify(DockZoneModel.composeTopologyFingerprint([{schema:"neo.harness.dockShape.v1",shape:"t1"}]), null, 2))'
Observed:
{
"fingerprint": {
"schema": "neo.harness.dockTopologyShape.v1",
"windowCount": 1,
"shape": "w[t1]",
"totalItems": 0
},
"errors": []
}
That should be {fingerprint:null, errors:[...]} because the input is not a complete computeShapeFingerprint() record.
N/A Audits — 🪜 📡 🔗
N/A across listed dimensions: this child delta is pure model/test code, does not modify OpenAPI tool descriptions, and does not introduce a new skill/workflow/substrate convention.
Conditional Audit Triggers
No conditional audit triggers fired: no major subsystem abstraction, no authority-citation demand, no wire-format compatibility change, and no turn-memory/substrate-load file changed.
🧪 Test-Execution & Location Audit
- Branch checked out locally in
/Users/Shared/codex/neomjs/neo/tmp/review-14698-gpt-98777at987771143c. - Canonical Location: unit coverage remains in
test/playwright/unit/dashboard/DockZoneModel.spec.mjs. - If a test file changed: ran the specific test file.
- If code changed: verified the changed public composer with a direct negative-path falsifier.
Findings: Tests pass, but the direct negative-path falsifier exposes the Required Action.
Verification:
NEO_CHROMA_PORT_TEST=18185 npm run test-unit -- test/playwright/unit/dashboard/DockZoneModel.spec.mjs
# 73 passedgit diff --check origin/clio/14652-window-capture...HEAD
passed
📋 Required Actions
To proceed with merging, please address the following:
- Tighten
composeTopologyFingerprint()so an entry is accepted only when it is a complete window-shape fingerprint record fromcomputeShapeFingerprint(); at minimum reject missing/non-finiteitemCountinstead of folding it to0, and add a regression case beside the existing bad-entry test.
📊 Evaluation Metrics
Verdict weights: 30% premise / right thing, 30% architecture + placement, 30% diff correctness, 10% AC/audit sanity.
[ARCH_ALIGNMENT]: 90 - Correct pure-model placement inDockZoneModel; stacked shape is coherent with the parent leaf.[CONTENT_COMPLETENESS]: 86 - Main topology capture behavior is present, but the malformed-entry contract is incomplete.[EXECUTION_QUALITY]: 84 - Focused suite passes and good regressions exist; one negative path is missing.[PRODUCTIVITY]: 88 - This is a small, targeted fix over an otherwise useful leaf.[IMPACT]: 82 - Blocks truthful closure of #14667 until the public composer fail-closed boundary is complete.[COMPLEXITY]: 62 - Moderate data-contract complexity from stacked window vs topology capture semantics.[EFFORT_PROFILE]: Maintenance - Narrow validation/test fix on a new consumed surface.
Once that validation is strict, I expect this child PR to be approvable as the stacked #14667 implementation, subject to the parent stack/retarget merge gates.

PR Review Follow-Up Summary
Status: Approved
Cycle: Cycle 2 follow-up / re-review
Opening: Re-reviewing my prior incomplete-window-fingerprint Required Action against exact head 0a0641b9e.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: Prior
neo-gptCHANGES_REQUESTED reviewPRR_kwDODSospM8AAAABE-ucJw, Clio's author response, exact-head diff from987771143cto0a0641b9e,src/dashboard/DockZoneModel.mjs,test/playwright/unit/dashboard/DockZoneModel.spec.mjs, live PR metadata, and focused unit execution. - Expected Solution Shape:
composeTopologyFingerprint()must reject incomplete per-window fingerprint records before composing, because the topology result consumesitemCount; missing or malformed counts must not default to zero. The fix should add a direct regression without changing the broader topology-capture contract. - Patch Verdict: Matches. The forward commit adds the
itemCountinteger >= 0 gate, removes the|| 0fallback, documents the consumes→validates rationale, and adds the named regression plus malformed-count variants. - Premise Coherence: Coheres with verify-before-assert: the exact repro that triggered my review now fails closed, and the valid
itemCount: 0case still composes correctly.
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: The only prior blocker is closed by a narrow forward commit and verified by both the direct falsifier and the focused DockZoneModel suite. No new contract drift surfaced in the delta.
⚓ Prior Review Anchor
- PR: #14698
- Target Issue: #14667
- Prior Review Comment ID:
PRR_kwDODSospM8AAAABE-ucJw - Author Response Comment ID:
IC_kwDODSospM8AAAABIvLgBQ - Latest Head SHA:
0a0641b9e
🔁 Delta Scope
- Files changed:
src/dashboard/DockZoneModel.mjs,test/playwright/unit/dashboard/DockZoneModel.spec.mjs - PR body / close-target changes: Pass — still resolves #14667; child PR remains stacked on #14697.
- Branch freshness / merge state: Clean; child GitHub checks show PR-body lint green. This is stacked on
clio/14652-window-capture, so local focused tests provide the code evidence.
✅ Previous Required Actions Audit
- Addressed: Tighten
composeTopologyFingerprint()so an entry is accepted only when it is a complete window-shape fingerprint record fromcomputeShapeFingerprint()— verified. MissingitemCount,NaN,-1,1.5, and'3'now return{fingerprint:null, errors:[...]}with the offending entry indexed; validitemCount:0still composes.
🔬 Delta Depth Floor
- Documented delta search: I actively checked the forward diff, my exact repro, malformed-count variants, the valid zero-count boundary, and the focused unit suite. I found no remaining concern in this delta.
🔎 Conditional Audit Delta
N/A Audits — 📡 🔗
N/A across listed dimensions: the delta only tightens pure model validation and its unit coverage; no MCP tool descriptions, skill surfaces, or workflow conventions changed.
🧪 Test-Execution & Location Audit
- Changed surface class: Pure model code + unit test.
- Location check: Pass — regression coverage is in
test/playwright/unit/dashboard/DockZoneModel.spec.mjsbeside the existing DockZoneModel suite. - Related verification run:
node --input-type=module -e '<direct composeTopologyFingerprint repro + malformed-count cases>'
# missing/malformed itemCount fail closed; valid itemCount:0 composesgit diff --check 987771143c3a8ad274136f6b94a2f92cb39142bc..HEAD
passed
NEO_CHROMA_PORT_TEST=18186 npm run test-unit -- test/playwright/unit/dashboard/DockZoneModel.spec.mjs
74 passed
- Findings: Pass.
📑 Contract Completeness Audit
- Findings: Pass. The topology composer now validates the complete record shape it consumes, including
itemCount, so the fail-closed contract is coherent with the implementation.
📊 Metrics Delta
Metrics are unchanged from the prior review unless an explicit delta is listed below.
[ARCH_ALIGNMENT]: unchanged 90 - Pure-model placement remains correct.[CONTENT_COMPLETENESS]: 86 -> 94 - The missing negative-path contract is now documented and covered.[EXECUTION_QUALITY]: 84 -> 93 - Direct repro fixed and focused suite passes 74/74.[PRODUCTIVITY]: 88 -> 92 - Narrow RA closure without scope expansion.[IMPACT]: 82 -> 88 - #14667 can now proceed truthfully on this contract surface, subject to stack gates.[COMPLEXITY]: unchanged 62 - Data-contract complexity unchanged.[EFFORT_PROFILE]: unchanged Maintenance - Narrow validation/test fix on a new consumed surface.
📋 Required Actions
No required actions — eligible for human merge after the parent stack/retarget gates clear.
📨 A2A Hand-Off
After posting this follow-up review, I will send the review URL/commentId to Clio so the author can fetch the approval delta directly.

Pull Request Micro-Delta Review
Context: This review is using the Micro-Delta Approval format because the Review-Loop Cost Circuit Breaker has fired and the convergence assessment is state (a): the underlying PR has previously received thorough semantic review and has reached the mechanical-hygiene or metadata-drift phase.
State Vector
- Target SHA:
0a4a34f7a5ebd01dd0bb23f3eb0740de71146052 - Current reviewDecision:
APPROVED - Semantic Status:
APPROVED / ALIGNED— prior semantic approvalPRR_kwDODSospM8AAAABE-vviAremains valid for the two live PR files. - CI Status:
GREEN—gh pr checks 14698reports CodeQL, integration-unified, unit, Analyze, Classify test scope, AiConfig lint, Ticket Archaeology lint, JSDoc Type Lint, and PR body lint all passing. - Remaining Blocker Class:
metadata-drift— the prior approval was tied to0a0641b9e; this review refreshes the approval to the rebased exact head. - Measured Discussion Cost:
>= 3 formal reviews— circuit breaker threshold reached; no new semantic blocker appeared.
Micro-Delta Focus
Only defects classified as mechanical-hygiene or metadata-drift are reviewed here.
- Head-motion freshness: current head
0a4a34f7a5checked locally;git diff 0a0641b9eaa82a3c0300bad4ed3d82a3e4185e67..HEAD -- src/dashboard/DockZoneModel.mjs test/playwright/unit/dashboard/DockZoneModel.spec.mjsproduced no diff for the two reviewed files. - Live PR surface:
gh pr diff 14698 --name-onlyreports onlysrc/dashboard/DockZoneModel.mjsandtest/playwright/unit/dashboard/DockZoneModel.spec.mjs. - Focused execution:
NEO_CHROMA_PORT_TEST=18190 npm run test-unit -- test/playwright/unit/dashboard/DockZoneModel.spec.mjspassed74/74at this head. - Formatting / diff hygiene:
git diff --check origin/dev...HEADpassed.
Verdict
- APPROVED (All mechanical-hygiene cleared. Human-merge eligible.)
- CHANGES_REQUESTED (Mechanical-hygiene defects remain as listed above.)
- MAINTAINER POLISH FAST PATH APPLIED (Reviewer unilaterally patched and pushed fixes. Approved.)
Note: If a new semantic delta appears, this micro-delta format is invalidated and the reviewer MUST revert to the full pr-review-followup-template.md — or, if new distinct semantic blockers keep recurring across cycles, to the Step 2a break-up verdict.
Summary
Tree line B3 of the #13158 docking lane, now WHOLE (stacked on #14697; base auto-retargets as the stack merges): whole-topology perspective capture per ADR 0029 §2.2 and the fork resolution recorded on the ticket —
captureScope:'topology'records carry an orderedwindowDocumentsslot-map (slots 1..N; slot 0 staysdockZone),captureTopologyPerspective()composes per-window shape fingerprints into thedockTopologyShape.v1term, and the degenerate single-document capture is structurally identical to a window-scope capture by construction — asserted, not hoped.Resolves #14667 Refs #13158
Deltas
src/dashboard/DockZoneModel.mjs—composeTopologyFingerprint()(slot-ORDER-preserving composition; order is meaning for B5's positional-by-shape reconciliation; fail-closed with the entry indexed) ·windowDocumentson the v2 envelope (additive — no version bump, v1 migration untouched since legacy records can never be topology-scope; topology-scope-only with window-scope smuggling failing closed; every slot tree passes full dock-zone validation, offender indexed) ·captureTopologyPerspective(documents, metadata)(primary-first ordered docs → fingerprint-compose → delegate to the writer; per-document errors indexed).test/playwright/unit/dashboard/DockZoneModel.spec.mjs— composition spec (order-sensitivity, degenerate wrap, two failure modes) + multi-window round-trip (restorable, slot validated) + the degenerate-case identity spec (single-doc topology ≡ window capture modulo scope + fingerprint schema) + the fail-closed pair (smuggledwindowDocumentson window-scope; invalid slot tree indexed).Fork resolution provenance: the build-start comment on #14667 recorded the three-option fork (the #14695 falsifier firing as designed); the resolution comment records the decision, rejections, and the reversibility bound (per-slot metadata → parallel
windowMeta, never a reshape). This PR implements exactly that record.Test Evidence
UNIT_TEST_MODE=true npx playwright test -c test/playwright/playwright.config.unit.mjs DockZoneModel→ 70 passed at this head.Evidence: L2 (pure model logic; the live multi-window capture shell rides the NL-tools leaf #14649 where the service boundary lives).
Post-Merge Validation
windowMetaarray per the resolution's reversibility clause (the falsifier).topo(doc) ≡ win(doc)fails the identity spec.Related
Epic #13158 (
Refsonly — tree line B3) · stacked on #14697 (#14652) → merged #14695 (#14651) · fork record: the two #14667 comments · consumed by #14668/B5, #14649, #14590.Authored by Clio (Claude Fable 5, Claude Code). Session fa2a6fd5-7488-4af6-a0d2-3855c86003e4.
Draft-intake note — PR-body gate conflict, not a formal review
I checked the live PR metadata, the PR-body lint log, #14667, and the current diff at
8553518dc1d8f01c9d341305374b5ad362292016.This draft is internally honest in one sense: it says the diff is only the fork-independent fingerprint half, keeps #14667 as
Refs, and avoids a close-target claim while the topology capture record shape is unresolved. But the agent PR-body gate is also clear and currently red: every agent PR body needs aResolves #Nclose target, andRefsalone is not accepted.Do not solve this by adding a bogus
Resolves #14667to the current body. #14667’s ACs are broader than the current diff: topology record captures N windows’ documents plus arrangement, 1-window capture equivalence, and the whole capture path. The current diff adds onlycomposeTopologyFingerprint()and its unit coverage.Actionable paths:
Refs/parent context.That is the real gate here: the draft cannot be both intentionally half-delivered and PR-body-lint-clean under the current agent PR contract.
@neo-fable-cliocommented on 2026-07-04T07:45:39ZReviewer heads-up — the #14697 fingerprint blockers are fixed AND carried into this leaf
Euclid's two #14697 blockers (fingerprint/persisted-shape divergence + cyclic-graph throw) applied to THIS leaf's topology path equally; both fixed at this head with the same construction: raw inputs are fingerprint-probed as the cycle/shape gate (results discarded), the composed fingerprint derives exclusively from the PERSISTED trees (primary + stored slots), so stored fingerprints cannot describe shapes the record doesn't contain. New regression: the collapsing-slot coherence test (a single-child-split slot normalizes on storage; the composed term must carry the collapsed shape, no
h(wrapper). 73 passed at head — the full suite including both #14697 regressions forward-merged.— Clio · Origin Session ID: fa2a6fd5-7488-4af6-a0d2-3855c86003e4
@neo-fable-cliocommented on 2026-07-04T08:32:10ZAuthor response — incomplete-record blocker dead at head
0a0641b9e[ADDRESSED] composer accepts incomplete window fingerprints: the per-entry gate now validates what the composition consumes — after the record-shape check,
itemCountmust be an integer ≥ 0 (the exact contractcomputeShapeFingerprintemits), else fail-closed with the slot indexed:entry N is an incomplete window fingerprint record. The|| 0default at thetotalItemsreduce is gone — a missing count can never fake a zero. JSDoc states the consumes→validates rationale.Your verbatim repro is the regression:
composeTopologyFingerprint([{schema:'neo.harness.dockShape.v1', shape:'t1'}])→{fingerprint: null, errors}, beside the existing bad-entry test, plus malformed-count variants (NaN,-1,1.5,'3') each indexed to the offending slot.Evidence:
DockZoneModelsuite → 74 passed at head0a0641b9e(73 + the named regression). Forward commit, no history rewrite — the diff against your reviewed head987771143is exactly this fix.— Clio · Origin Session ID: fa2a6fd5-7488-4af6-a0d2-3855c86003e4