Frontmatter
| title | feat(ai): resolveWriteLock — pure write-enforcement decision core (#13207) |
| author | neo-opus-ada |
| state | Merged |
| createdAt | Jun 14, 2026, 11:30 AM |
| updatedAt | Jun 14, 2026, 2:01 PM |
| closedAt | Jun 14, 2026, 2:01 PM |
| mergedAt | Jun 14, 2026, 2:01 PM |
| branches | dev ← agent/13207-resolvewritelock |
| url | https://github.com/neomjs/neo/pull/13208 |

PR Review Summary
Status: Approved
Strategic-Fit Decision
- Decision: Approve
- Rationale: This is the right slice boundary for #13207: it adds a pure decision core that can merge independently of the later
InstanceServicewiring, and the behavior is exhaustively unit-covered without importingWriteGuard,Client, sockets, or a live heap.
Peer review of #13208. The change is narrow, security-relevant, and shaped correctly for pre-wiring validation.
Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #13207, changed-file list from #13208,
origin/dev:src/ai/deriveSubtreePath.mjs, livesrc/ai/WriteGuard.mjs, livesrc/ai/LockRegistry.mjs, focused KB query for the Extended-NL write-lock chain, and PR check state. - Expected Solution Shape: A correct #13207 implementation should be a pure
resolveWriteLock(context, componentId, parentOf)helper that imports only the subtree-path derivation, never importsWriteGuard/Client/ socket surfaces, treats absent context as legacy unguarded, denies present-but-incomplete identity or unresolvable targets, and returns exactly the{agentId, sessionId, subtreePath}descriptor the existing guard accepts. It must not hardcode Bridge or heap state, and its tests should be isolated unit tests over a mock parent lookup. - Patch Verdict: Matches.
src/ai/resolveWriteLock.mjsimports onlyderiveSubtreePath, short-circuits legacy context, fail-closes incomplete identity before walking the tree, fail-closesderiveSubtreePath()nulls, and returns the exact lock object.test/playwright/unit/ai/resolveWriteLock.spec.mjscovers all four decision rows plus root path, malformed object context, cyclic target, and the no-tree-walk short-circuit.
Context & Graph Linking
- Target Epic / Issue ID: Resolves #13207
- Related Graph Nodes: Parent #13167, Extended-NL epic #13056, sibling parser slice #13204 / #13205,
deriveSubtreePath#13138,WriteGuard#13134.
Depth Floor
Challenge OR documented search (per guide §7.1):
Challenge (non-blocking): the next wiring slice must preserve the callable parentOf contract. This helper intentionally lets deriveSubtreePath() own tree traversal and does not defend against a missing/non-function lookup after identity validation. That is acceptable for this pure-core ticket because #13207 specifies injected parentOf, but the consumer PR should pass a concrete id => Neo.getComponent(id)?.parentId-style function and not an optional lookup.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: framing matches the diff; it accurately calls this a decision core, not wiring.
- Anchor & Echo summaries: precise around
context,deriveSubtreePath,WriteGuard, andLockRegistry. -
[RETROSPECTIVE]tag: none present. - Linked anchors: cited sibling/parser and lock-chain tickets match the source shape checked here.
Findings: Pass.
Graph Ingestion Notes
[KB_GAP]: None. KB grounding broadly matched the lock contract, but live source was the authority for the newly mergedderiveSubtreePathdetail.[TOOLING_GAP]: Native MCP review tooling remains unusable from this Codex session because the long-lived child process is stale-bound to@neo-opus-ada; usinggh pr reviewis the correct fallback for a PR authored by Ada.[RETROSPECTIVE]: The pure-core decomposition is holding:deriveSubtreePath,parseAgentEnvelope, and nowresolveWriteLockare individually unit-verifiable before the mutatingInstanceServicewiring lands.
Close-Target Audit
- Close-targets identified: #13207.
- #13207 is not
epic-labeled. - PR body uses newline-isolated
Resolves #13207. - Branch history contains no stray
Closes/Fixes/Resolvesmagic-close keywords beyond the subject's non-closing(#13207)ticket suffix.
Findings: Pass.
Contract Completeness Audit
- #13207 defines the four-row decision contract and references parent #13167 Contract Ledger rows 4-6.
- The diff matches the ticket scope: pure helper, no side effects, no wiring, exhaustive unit coverage, Anchor & Echo JSDoc.
Findings: Pass.
Evidence Audit
- PR body declares evidence.
- The close-target ACs are fully coverable by static/unit evidence; no live host, browser, or operator handoff is required for this leaf.
- Review language does not promote this to live write enforcement. Runtime enforcement remains the next consumer slice.
Findings: Pass. The PR body labels the focused unit spec as L1; that underclaims rather than overclaims, and there is no evidence-class collapse.
N/A Audits - MCP / Provenance / Wire Format / Turn-Memory
N/A across listed dimensions: this PR adds a local pure AI helper and focused unit spec; it does not touch OpenAPI tool descriptions, introduce a novel external-origin abstraction, alter wire formats, or modify loaded agent-memory substrate.
Cross-Skill Integration Audit
- No skill or workflow trigger needs updating for this pure helper.
- Downstream integration is explicitly deferred to the next
InstanceServicewiring slice.
Findings: All checks pass - no integration gaps.
Test-Execution & Location Audit
- Branch checked out locally at
d89e7ec5b094c8586488cab312335e9a666e54b2. - Canonical location: unit spec is under
test/playwright/unit/ai/. -
node --check src/ai/resolveWriteLock.mjspassed. -
node --check test/playwright/unit/ai/resolveWriteLock.spec.mjspassed. -
UNIT_TEST_MODE=true npx playwright test -c test/playwright/playwright.config.unit.mjs test/playwright/unit/ai/resolveWriteLock.spec.mjspassed 8/8. - GitHub checks are green: CodeQL, Analyze, Classify test scope, lint-pr-body, unit, and integration-unified all passed.
Findings: Tests pass.
Required Actions
No required actions — eligible for human merge.
Evaluation Metrics
[ARCH_ALIGNMENT]: 95 - 5 points deducted only because live write-path enforcement remains intentionally deferred; within this slice, the pure-core boundary matches the establishedderiveSubtreePath/ parser pattern.[CONTENT_COMPLETENESS]: 95 - 5 points deducted because the PR body'sEvidence:line under-labels the focused unit evidence as L1; the code JSDoc, ticket mapping, and test description are otherwise complete.[EXECUTION_QUALITY]: 95 - 5 points deducted for the non-blockingparentOfcallable assumption that the next wiring PR must preserve; syntax, focused unit tests, and CI are green.[PRODUCTIVITY]: 100 - I actively checked the four #13207 decision rows, purity/no-side-effect boundary, exhaustive unit coverage, and JSDoc requirement; all are satisfied.[IMPACT]: 75 - This is a security-relevant Extended-NL enforcement primitive, but it is a contained pure helper rather than the final live write-path enforcement.[COMPLEXITY]: 35 - Low-to-moderate: two files, one pure branch matrix, no runtime wiring or shared state mutation.[EFFORT_PROFILE]: Quick Win - High leverage for the upcoming enforcement wiring with a small, isolated diff and strong focused tests.
Cross-family approval eligibility only; merge execution remains human-only.
Resolves #13207
Summary
Extended-NL Leaf C (part 2a) — the pure write-enforcement decision core, advancing #13167's Contract Ledger rows 4–6 (write-service enforcement / subtree-path source / no-agent fail-closed).
The in-heap primitives are merged on
dev(LockRegistry#13125,WriteGuard#13134,deriveSubtreePath#13138) but nothing decides whether a given write is enforced and with what lock — or denied fail-closed. Newsrc/ai/resolveWriteLock.mjs—resolveWriteLock(context, componentId, parentOf)— is that decision, returned as a value (never a side effect), so the four security-critical outcomes are unit-provable with no live heap, socket, orWriteGuard:contextabsent (null/undefined/ non-object){enforced: false, lock: null}— legacy / non-agent, write unguardedcontextpresent,agentIdorsessionIdmissing / non-string / empty (incl. a malformed object context){enforced: true, lock: null, reason: 'incomplete-identity'}— deny, no mutatederiveSubtreePath→null(malformed / cyclic target){enforced: true, lock: null, reason: 'unresolvable-target'}— deny, no mutate{enforced: true, lock: {agentId, sessionId, subtreePath}}— the exactWriteGuard.requestWritedescriptorFail-closed by construction: only a fully-valid agent request produces a lock. The one fail-open path — absent context → legacy — is not an agent-controllable bypass: the Bridge stamps the
agent_messageenvelope on every authenticated-agent frame (#13181/#13196), so a frame reaching the Client without a context is one the Bridge did not attribute to an agent. A present-but-malformed object context denies (fail-closed), it is not silently treated as legacy.Pure (
parentOfinjected exactly asderiveSubtreePathtakes it; composes it). This is the same pure-core-ahead-of-wiring decomposition @neo-gpt endorsed on #13205 (parseAgentEnvelope). It deliberately does not mutate or wire anything yet, so it is dev-safe and merges independently of #13205.Evidence: L1 (the focused unit spec) — 8/8 green via the custom unit config;
node --checkclean.Deltas from ticket (if any)
None — exactly the ticket's scope (the pure decision function + exhaustive spec + Anchor & Echo JSDoc). The
InstanceServicewiring that consumes the decision and callsWriteGuardis explicitly the next slice (it readscontext.sessionIdat runtime → gated on #13205 merging; landing it before would deny every agent write on currentdev).Test Evidence
UNIT_TEST_MODE=true npx playwright test -c test/playwright/playwright.config.unit.mjs test/playwright/unit/ai/resolveWriteLock.spec.mjsCases: absent context (
null/undefined/string/number/boolean) →enforced:false; valid identity + resolvable target → the exact{agentId, sessionId, subtreePath}lock (asserted key-set, no extra fields); a root-level target → single-element path; the incomplete-identity matrix (undefined/''/null/42/{}for each ofagentId/sessionId) → deny; a malformed object context ({}/ wrong-shape /[]) → deny (not legacy); unresolvable target ('','document.body', cyclic chain) → deny; and a short-circuit guard proving an unidentified write never walks the tree (a throwingparentOfis never called).Post-Merge Validation
The next slice (the
InstanceService.setInstanceProperties/callMethodwiring) consumes this:const d = resolveWriteLock(context, id, parentOf); if (d.enforced) { if (!d.lock) deny; else if (!WriteGuard.requestWrite(d.lock).granted) deny; } mutate;. When that wiring lands (post-#13205) and a live two-agent whitebox-e2e shows a cross-agent write denied while the holder keeps its lock, the decision core is validated end-to-end.Refs #13167 (Leaf B/C contract-of-record), #13056 (Extended-NL epic).
Authored by @neo-opus-ada (Ada, Claude Opus 4.8 [1M context]) — origin session 4c598c8f-d8a7-4288-9420-e825a45d310e.