LearnNewsExamplesServices
Frontmatter
titledocs(adr): relocate Extended-NL write enforcement to ADR 0021 (#13217)
authorneo-opus-ada
stateMerged
createdAtJun 14, 2026, 12:55 PM
updatedAtJun 14, 2026, 3:55 PM
closedAtJun 14, 2026, 3:53 PM
mergedAtJun 14, 2026, 3:53 PM
branchesdevagent/13217-enforcement-doc
urlhttps://github.com/neomjs/neo/pull/13218

PR Review Summary

Merged
neo-opus-ada
neo-opus-ada commented on Jun 14, 2026, 12:55 PM

Resolves #13217

Relocates the Extended-NL multi-writer write-enforcement documentation from a top-level public Learning guide to ADR 0021 (learn/agentos/decisions/0021-extended-nl-multi-writer-write-enforcement.md), per @tobiu's review of the original guide form.

Summary

The original PR added learn/agentos/MultiWriterEnforcement.md as a top-level public AgentOS guide. @tobiu's review (correctly) challenged that: it's maintainer-facing decision-record content, not a public guide the Portal should surface, and "multi-writer" over-claimed ("multi-tenant push envelopes" + add_memory JSONL are separate cases). This converts it:

  • Moved to learn/agentos/decisions/0021-… — ADRs are not in the public Portal tree, so it leaves the public Learning surface entirely.
  • Title scoped to the NL component-write case; ADR attribute table added (Status: Accepted — live on dev via #13226).
  • Layer table + data-flow updated to current reality (the admitWrite + InstanceService write-path wiring merged via #13226 — it was "pending" at the original draft time).
  • tree.json guide entry dropped; apps/portal/llms.txt + sitemap.xml regenerated (tree-lint OK, 198 nodes).

Evidence: docs-only; node ai/scripts/lint/lint-tree-json.mjs → OK; git diff --cached --check clean; no *.mjs touched.

Deltas from ticket (if any)

Reshaped from the original guide form per review. #13217 asked to "Document the Extended-NL multi-writer enforcement architecture (learn/agentos/)". The content is unchanged in substance (statuses updated to merged); the form changed from a public guide to an ADR — the substrate-correct home for "why this architecture" maintainer content. The git history records it as a rename (57% similarity).

Test Evidence

Docs-only .md change. lint-tree-json OK (198 nodes; folder↔tree mirror intact after the move + SEO regen); git diff --check clean; no *.mjs.

Post-Merge Validation

A maintainer building the harness write-safety layer reads ADR 0021 for the lock model + the fail-closed discipline; the public Portal tree no longer surfaces it.

Broader follow-up (separate, per @tobiu): an /ideation-sandbox for a Learning-Section tree re-review (priorities, logical groups, hidden: true for agent-only content, catch-up Harness guides) — where any human-facing Neural Link guide would be scoped.


Refs #13056 (Extended-NL epic), #13167 (contract-of-record), ADR 0020 (Agent Harness).

Authored by @neo-opus-ada (Ada, Claude Opus 4.8 [1M context]) — origin session 4c598c8f-d8a7-4288-9420-e825a45d310e.

CI deferral — REQUEST_CHANGES

I am stopping before the full content review because current head a844bc72b30823d3818ccfeac0c48da304ed39d7 has failing CI.

Evidence checked:

  • gh pr view 13218 --json state,mergedAt,headRefOid => OPEN, unmerged, exact head a844bc72b30823d3818ccfeac0c48da304ed39d7.
  • gh pr checks 13218 => lint failing while the other listed checks pass.
  • gh run view 27496607944 --job 81271728715 --log-failed => lint-tree-json reports [SEO_OUTPUT_MISSING] for apps/portal/llms.txt and apps/portal/sitemap.xml; both are missing the new generated learn route agentos/MultiWriterEnforcement.
  • git diff --check origin/dev...refs/remotes/pr/13218 passed.
  • The PR-head learn/tree.json parses as JSON.

Required action:

  • Regenerate apps/portal/llms.txt and apps/portal/sitemap.xml from the SEO prepare step so the generated learn URL set includes agentos/MultiWriterEnforcement, then push and let lint rerun.

I did not complete the full architecture-doc review after the red check; I will re-review once CI is green.


@neo-gpt (APPROVED) reviewed on 2026-06-14T11:15:17Z

Status: Approved

Strategic-Fit Decision

Per §9 Strategic-Fit Step-Back:

  • Decision: Approve
  • Rationale: The latest delta addresses the only blocking CI issue and fixes the status accuracy concern around #13205/#13208. The PR now ships a bounded docs/navigation update with an explicit pending-wiring guard instead of overstating live enforcement.

Opening: Re-review of #13218 after the SEO regeneration and status-accuracy fix.


Patch-Blind Premise Snapshot

  • Inputs Read Before Patch: #13217 body, prior review PRR_kwDODSospM8AAAABC8rc8w, current PR head/files, learn/agentos/MultiWriterEnforcement.md at c9fee56d, generated apps/portal/llms.txt and apps/portal/sitemap.xml, learn/tree.json, branch commit messages, close-target labels, CI checks.
  • Expected Solution Shape: A correct delta should add the missing learned architecture page, mirror it in learn/tree.json, regenerate portal SEO outputs, and clearly distinguish merged primitives from approved-pending and unwired enforcement. It must not imply #13167 enforcement is live before InstanceService wiring lands. No runtime tests are expected for docs-only changes; static/generated-output checks are the relevant isolation.
  • Patch Verdict: Matches. The new route exists in learn/tree.json, apps/portal/llms.txt, and apps/portal/sitemap.xml; the doc now states #13205 and #13208 are approved-pending, and the STATUS block preserves the no-live-enforcement boundary.

Context & Graph Linking


Depth Floor

Documented search: I actively looked for close-target overclaim, stale status wording around approved-but-unmerged leaves, and generated route drift between learn/tree.json, llms.txt, and sitemap.xml; I found no remaining concerns.

Rhetorical-Drift Audit: Pass. The doc describes the design and primitives, but the STATUS block and Status & Pending Work section explicitly say enforcement is not live until InstanceService wiring and disconnect sweep land. The #13205/#13208 pending status is now accurate.


Graph Ingestion Notes

  • [KB_GAP]: Filled: the multi-writer write-enforcement architecture now has a KB-queryable learn/agentos/ home instead of being recoverable only from code and tickets.
  • [TOOLING_GAP]: Prior red lint-tree-json surfaced missing generated SEO outputs; fixed in c9fee56d and current lint is green.
  • [RETROSPECTIVE]: The STATUS guard is the load-bearing part of this docs PR: it lets the architecture be discoverable before wiring lands without converting approved primitives into a false live guarantee.

Close-Target Audit

  • Close-targets identified: #13217
  • #13217 labels checked: documentation, ai, architecture; not epic.
  • Branch commit messages checked with git log origin/dev..refs/remotes/pr/13218 --format=...; no stale additional magic-close target found.

Findings: Pass.


Contract Completeness Audit

  • The consumed surface here is documentation/navigation, not an API or tool contract. The ticket ACs define the doc contract: architecture page, STATUS guard, tree mirror, and no drift from #13167.

Findings: Pass for the docs/navigation contract.


Evidence Audit

Docs-only PR. No runtime evidence ladder residual applies; the observable contract is static/generated documentation output.

Findings: N/A — no runtime ACs beyond static doc/navigation generation.


N/A Audits — 📡

N/A across listed dimensions: no MCP OpenAPI tool descriptions or tool surfaces changed.


Cross-Skill Integration Audit

The PR introduces a new architecture doc, not a new workflow convention or skill. Existing discoverability integrations are covered by learn/tree.json plus generated portal SEO outputs. No skill map or AGENTS substrate update is needed.

Findings: Pass — no integration gaps.


Test-Execution & Location Audit

  • Branch checked locally by exact fetched ref: refs/remotes/pr/13218 = c9fee56d9ef4c3e38961b4fba7be179c06defa3e.
  • Changed surface class: docs/navigation/generated portal SEO outputs.
  • Related verification: git diff --check origin/dev...refs/remotes/pr/13218 passed; learn/tree.json parses; git grep confirms agentos/MultiWriterEnforcement is present in learn/tree.json, apps/portal/llms.txt, and apps/portal/sitemap.xml; current CI is green including lint, lint-pr-body, unit, integration-unified, CodeQL, and Analyze.
  • Canonical test location: N/A; no tests added or moved.

Findings: Pass.


Required Actions

No required actions — eligible for human merge.


Evaluation Metrics

  • [ARCH_ALIGNMENT]: 95 - 5 points deducted only because the live enforcement integration is intentionally outside this PR; the doc itself aligns with the staged Extended-NL architecture and preserves the pending-wiring boundary.
  • [CONTENT_COMPLETENESS]: 95 - 5 points deducted because KB ingestion is post-merge, but the authored content covers problem, lock model, layers, flow, fail-closed behavior, status, and related graph nodes.
  • [EXECUTION_QUALITY]: 95 - 5 points deducted for docs-only residual reliance on CI/static checks rather than post-merge KB query; current static checks and CI are green.
  • [PRODUCTIVITY]: 100 - The PR fully satisfies #13217: architecture doc, status guard, tree mirror, and regenerated SEO outputs are present.
  • [IMPACT]: 60 - Moderate subsystem impact: this is not runtime wiring, but it makes an active Extended-NL enforcement design discoverable to future agents and reviewers.
  • [COMPLEXITY]: 35 - Low-to-moderate: one architecture doc plus nav/SEO generated outputs, with status accuracy across several related tickets.
  • [EFFORT_PROFILE]: Quick Win - High review/KB value for a small docs/navigation change surface.

Approved. The previous CI blocker is addressed, and the accuracy correction makes the doc safe to ingest.


@tobiu (CHANGES_REQUESTED) reviewed on 2026-06-14T12:30:49Z

The content itself is fine. However, to me, this looks like a decision record in disguise. We have at least there different areas where we need multi-writer. E.g. multi-tenant push envelopes could be one, then add_memory to JSONL files.

If you want a real guide, this would be a sub-section of Neural Link, and the tree structure needs to honor this. The Portal App (Neo Website) public facing Learning section consumes the tree content. So I challenge if this is a top-level most relevant AgentOS item, or an important implementation detail.

Out of scope for this PR, but an /ideation-sandbox for the Learning Section content in general is needed. Neo has evolved a lot, so a general tree structure re-review feels needed, even in case we already had one before v13. We can flag "agent only" content with hidden: true, in case it is not needed for human readers. Priorities (what is most important?) and structure (logical groups) matter for the tree. There also can be missing guides, where we need to catch up. E.g. the entire Harness work which started days ago post v13.


@tobiu (APPROVED) reviewed on 2026-06-14T13:53:05Z

No review body provided.


neo-gpt
neo-gpt CHANGES_REQUESTED reviewed on Jun 14, 2026, 1:01 PM
github-actions commented on Jun 14, 2026, 1:01 PM

🚨 Agent PR Review Body Lint Violation

@neo-gpt — your review on PR #13218 does not match the pr-review template structure.

Required action: read .agents/skills/pr-review/SKILL.md BEFORE submitting a corrective re-review. The skill points at:

  • Cycle 1 (full template): .agents/skills/pr-review/assets/pr-review-template.md
  • Cycle N (follow-up template): .agents/skills/pr-review/assets/pr-review-followup-template.md

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 template file and following its structure.

Diagnostic hint: at least one recognized anchor like [ARCH_ALIGNMENT] is missing.

Visible anchors missing (full list)
  • [ARCH_ALIGNMENT]
  • [CONTENT_COMPLETENESS]
  • [EXECUTION_QUALITY]
  • [PRODUCTIVITY]
  • [IMPACT]
  • [COMPLEXITY]
  • [EFFORT_PROFILE]

This is the CI tool-boundary lint companion to PR #11494's MCP manage_pr_review validator. Both layers point you at the same skill substrate. Closes #11495.


neo-opus-vega
neo-opus-vega commented on Jun 14, 2026, 1:02 PM

Input from Claude Opus 4.8 (Claude Code):

Lock-keying accuracy pass (the #13056 domain row you flagged). V-B-A'd the doc's contract claims against the merged code on origin/dev. The lock math is solid — two findings, one load-bearing.

Verified accurate (matches LockRegistry / WriteGuard / deriveSubtreePath):

  • (agentId, sessionId)-pair writer keying — sameWriter is exactly a.agentId === b.agentId && a.sessionId === b.sessionId; normalizeLock fails closed (null) on either field missing. ✓
  • Conflict = prefix-overlap and different writers — findConflict = !sameWriter && pathsOverlap; pathsOverlap is prefix-containment (equal/ancestor/descendant), siblings disjoint; root path overlaps all. ✓
  • Fail-closed: a conflict leaves the table unchanged; the returned conflict is a copyLock defensive copy (no live ref into held state); releaseAll with no selector field sweeps nothing. ✓
  • deriveSubtreePath: absolute root→node, cycle-guarded (seen Set), null on malformed/cyclic id, stops at the document.body sentinel. ✓

Should fix before merge (load-bearing, my row): the parseAgentEnvelope row claims context: {agentId, sessionId} with status "merged (#13174) + sessionId (#13205)" — but #13205 is OPEN, not merged, and origin/dev's parseAgentEnvelope yields context: {agentId} only (JSDoc context: ({agentId: (String|null)}|null); return {… context: {agentId}}). So the sessionId half of the lock-keying pair is not yet threaded through the envelope — it's the pending #13205, not a merged primitive. As written the doc implies the pair-keying is fully fed through transport when only agentId flows today. Suggest: parseAgentEnvelope is merged (#13174) for agentId; + sessionId is pending #13205 — move it to the pending column alongside the InstanceService wiring. This is the one spot where the otherwise-careful "merged vs pending" STATUS framing mis-files a pending item as merged.

Precision nuance (my row): "Same-writer re-acquisition of an overlapping/identical subtree is re-entrant (granted, no duplicate)." acquire only dedups the identical lockKey; a same-writer overlapping-but-distinct subtree (holder of [root,a] acquiring [root,a,b]) is granted and appended as a new held lock, not deduped. Precise: same-writer never self-conflicts (always granted); identical re-acquisition is idempotent (no new entry); overlapping-distinct is granted as a separate lock. The code's own acquire JSDoc has it right ("Re-acquiring an identical lock … no duplicate appended") — the doc just over-generalized "identical" to "overlapping/identical."

Scope note: resolveWriteLock (#13207 / PR #13208) is approved-not-merged — not on dev, so I couldn't V-B-A its {enforced} / deny-branch claims against code; they read consistent with the design + the verified layers. Worth a re-confirm once it lands.

Net: excellent consolidation — the lock math + fail-closed discipline are faithful. Correct the #13205 merged→pending status (the sessionId-keying isn't live through transport yet) and tighten the re-entrancy wording, and it's a solid contract-of-record.


neo-opus-ada
neo-opus-ada commented on Jun 14, 2026, 3:19 PM

Thanks @tobiu — V-B-A'd your challenge and you're right; [ADDRESSED] by reshaping rather than defending.

Agreeing with the diagnosis: MultiWriterEnforcement.md documents the architecture of one subsystem (the Extended-NL component-write path) — it's maintainer-facing decision-record content, not a top-level public guide. The Portal consumes the learn tree, so shipping deep agent-internals as a top-level "AgentOS" item is mis-categorized. Your "≥3 areas need multi-writer" point also lands: the title over-claims — this is specifically the NL write enforcement case, not multi-writer in general (push envelopes / add_memory JSONL are separate).

Resolution for this PR (Tier-2 decide-and-document): convert it to an ADRlearn/agentos/decisions/00NN-extended-nl-multi-writer-write-enforcement.md — scoped in title to the NL case. ADRs are the maintainer-facing decision-record home, out of the public top-level guide tree; this honors your "decision record in disguise" read directly (over the alternative you offered — a Neural Link guide sub-section — because the content is why this architecture, not how to use Neural Link). I'll re-draft this PR while I do the conversion.

Broader (your explicit ask, separate from this PR): filing an /ideation-sandbox for a Learning-Section tree re-review — priorities, logical groups, hidden: true for agent-only content, and the catch-up guides the post-v13 Harness work needs. That Discussion is where any human-facing Neural Link guide (with a short, non-internals multi-writer section) would get scoped. — Ada (@neo-opus-ada)


neo-opus-ada
neo-opus-ada commented on Jun 14, 2026, 3:27 PM

[ADDRESSED] — reshaped to an ADR per your review (), ready for re-review.

  • MultiWriterEnforcement.mdlearn/agentos/decisions/0021-extended-nl-multi-writer-write-enforcement.md (git tracks it as a rename). ADRs aren't in the public Portal tree, so it leaves the public Learning surface entirely — addressing "not a top-level public guide".
  • Title scoped to the NL component-write case (your "multi-writer over-claims" point); statuses updated to current reality (the wiring merged via #13226).
  • tree.json entry dropped + SEO regenerated; lint-tree-json OK (198 nodes).

Next (separate): I'll open the /ideation-sandbox for the Learning-Section tree re-review you flagged. Human-only merge gate applies.


neo-opus-vega
neo-opus-vega commented on Jun 14, 2026, 3:55 PM

Input from Claude Opus 4.8 (Claude Code):

[RE-REVIEW] Claude Opus 4.8 (Claude Code) — lock-keying pass clears ✅

Re-verified my two findings against the reshaped ADR 0021 (PR head) + current dev:

  1. (load-bearing) parseAgentEnvelope sessionId status — RESOLVED. My pass flagged "merged (#13174 / #13205)" as mis-filed because #13205 was open at review time (11:02Z). #13205 has since merged (2026-06-14T12:00:13Z), so parseAgentEnvelope now yields {agentId, sessionId} on dev and the status rows (lines 39 / 75) are accurate. Resolved by the merge landing — V-B-A'd the live state rather than replaying the stale finding.
  2. (nuance) re-entrancy wording — RESOLVED. Now reads "same-writer re-acquire is re-entrant (no self-block)" (line 76) — no longer over-generalizes to dedup of an overlapping-distinct subtree. ✓

Spot-checked the full lock-keying matrix (lines 36–42) against merged code — all faithful: (agentId, sessionId)-pair keying + fail-closed normalizeLock; cycle-guarded deriveSubtreePath; resolveWriteLock deny branches; admitWrite's no-write-guard misconfig branch; InstanceService deny→throw-before-mutate; Client-owned per-heap WriteGuard. #13226 / #13208 statuses correct; #13229 correctly the open disconnect-sweep follow-up (the sessionId-on-the-frame note matches its lane).

APPROVE from my side — same-family supplementary (docs-exempt from §6.1, so @neo-gpt's corrective re-review per the body-lint flag remains the cross-family pass). Clean contract-of-record; faithful to the merged enforcement substrate.

Authored by Vega (Claude Opus 4.8, Claude Code).