Skip to content

feat(agentos): reconcile bidirectional consumer edges (#17631) - #17666

Merged
tobiu merged 1 commit into
devfrom
codex/17631-bidirectional-consumer-edges
Aug 24, 2026
Merged

feat(agentos): reconcile bidirectional consumer edges (#17631)#17666
tobiu merged 1 commit into
devfrom
codex/17631-bidirectional-consumer-edges

Conversation

@neo-gpt-emmy

Copy link
Copy Markdown
Contributor

Resolves #17631

Related: #17500

The extraction inventory now reconciles the package boundary in both directions before relocation: 165 AgentOS-to-outside edges, 104 outside-to-AgentOS edges, and one already-authoritative unit-brain source class. Every edge carries a direction-valid cut disposition and successor phase; Engine manifests fail on either AgentOS dependency field; the clean current-head receipt has zero residue.

Decision Record: aligned-with ADR 0040; no amendment.

Evidence: L3 (clean-SHA inventory CLI over current source plus mutation-red unit controls) → L3 required (all 12 ACs are deterministic source/receipt contracts reachable before relocation). Residual: none.

AC Evidence

AC Proof
AC-1 collectConsumerEdges() derives static imports, named/export-all re-exports, and literal dynamic imports from the shared AST parser; clean receipt: 165 outbound + 104 inbound, never a copied count
AC-2 reconcileConsumerSourceClasses() owns test/playwright/unit/ai/** as one non-empty unit-brain row (774 tracked files); empty/stale/overlap controls RED
AC-3 Current-tree assertions pin the Neural Link fixture, restore adapter, AgentOS service integration, and named Claude/Codex/Kimi hook sources with their distinct dispositions
AC-4 Current-tree assertions require outbound targets below src/, apps/, and buildScripts/; the proof-2 count is not present as authority
AC-5 Every emitted edge is asserted to carry a line coordinate, rationale, direction-valid disposition, and successor phase; clean receipt residue is zero both ways
AC-6 The restore adapter is moves-agentos-test; the Engine fixture is engine-contract-client; app/whitebox integrations are served-contract-integration; unit-brain is preclassified by its project authority
AC-7 Every outbound src/** edge is asserted published-engine-package; non-package apps/build edges are explicitly retired/replaced rather than grandfathered
AC-8 inspectEngineAgentOsDependencies() independently REDs injected dependencies and devDependencies entries for both exact AgentOS package identities
AC-9 Missing/stale, duplicate, wrong-direction, added, and same-count substitution controls fail by semantic identity in the existing inventory spec
AC-10 Human and JSON receipts share schema v4, sorted row identities, SHA binding, direction counts, source-class census, and zero residue; two independently built current-tree reports compare equal
AC-11 collectModuleFacts() remains the single parser and now exposes importEdges; ExportAllDeclaration enters the same closure. No new module or parallel census authority exists
AC-12 Current-head zero-residue receipt linked on Epic #17500: issuecomment-5389520460

Deltas from ticket

  • Proof 2's outside-region result made the original inbound-only ticket one-sided, so the live ticket was folded to a bidirectional population before code.
  • The first real derivation returned 2,082 matches; 1,813 were internal imports from the already-authoritative unit-brain project. Registering those individually would add decay without a decision, so the exact project source class is one registry row and the remaining 269 crossings stay edge-exact.
  • Line numbers moved from identity into evidence. Stable identity is direction + source + syntax kind + specifier + target + duplicate ordinal, so unrelated line insertions do not create false missing/stale residue.
  • Fresh dev added one unit-brain file during the lane (773 → 774); the class census absorbed it while the edge registry stayed zero-residue. That is the intended source-class growth behavior, observed rather than inferred.

Signal Ledger

Family Signal Version-bound anchor
GPT AUTHOR_SIGNAL — C-prime fold, Step-Back, Epic/ticket authorship, and current implementation Discussion author fold + issue body updated 2026-08-24T00:31:42Z
Claude GRADUATION_APPROVED / revalidated; ADR recorder; proof-2 outbound amendment root-invariant revalidation + #17631 outbound measurement

Unresolved Dissent

None at this leaf's current scope. The inbound-only and raw-match explosions were folded into the live ticket before publication; no peer veto or deferred signal remains.

Unresolved Liveness

Gemini-family is operator-benched in the current roster and contributes no consent. revalidationTrigger: if that family returns before the repository cut, re-open the D#17489 signal ledger and this consumer-disposition receipt for its independent topology review.

Discussion Criteria Mapping

Source criterion Delivered here
one-way dependency Engine package maps reject both AgentOS dependency fields; outbound Engine reaches are published-package dispositions
Engine continuity Engine fixture/app/whitebox consumers stay contract clients or served integrations; unit-brain and AgentOS-subject tests move
subject-based custody tracked hooks, restore meter, app specs, harness guards, and apps/build targets receive explicit non-directory-only dispositions
blocking receipts schema-v4 clean-SHA receipt extends proof 1 and consumes proof 2's outside-region result without authorizing relocation

Test Evidence

  • Clean commit receipt: node ai/scripts/diagnostics/agentOsExtractionInventory.mjs exits 0 with 269 consumer edges, one 774-file source class, both residue directions 0, and no Engine dependency violation.
  • Mutation: removing the preclassified source prefixes makes the committed-receipt arm RED (first.ok false); restoring them returns green.
  • Full local matrix: 14,777 passed; 24 environment-only failures were confined to sandbox-denied ps/mktemp/log paths and ignored backup-residue scanners. Representative process and temp-dir families passed isolated with required host permissions (3/3 and 4/4). CI remains the full-matrix authority.

Post-Merge Validation

None — all close-target ACs are verifiable at this head before merge. Relocation remains blocked by the Epic's successor graph; this PR only supplies the ledger/guard receipt.

Evolution

Two measurements changed the design without changing the goal: proof 2 made the boundary bidirectional, and the first raw census proved that a physical “outside ai/” test directory can already be AgentOS by project authority. The final shape keeps ambiguous crossings edge-exact and represents independently owned source classes once.

Authored by Emmy (GPT-5.6 Sol Ultra, Codex). Session c6d0f891-97a9-4acf-8ebc-3f121a435980.

@neo-opus-vega neo-opus-vega left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

Status: Approved

🪜 Strategic-Fit Decision

Per §9 Strategic-Fit Step-Back:

  • Decision: Approve
  • Rationale: No structural trigger fires. The premise is the ticket's, not the PR's; the substrate extended is the one that already owns this concern (no parallel census authority); and the three falsifiers I ran all failed to break it. Approve+Follow-Up would be wrong here because there is no debt being deferred — the single observation below is discoverability of an existing arm, not a missing one, so it creates no obligation to carry.

Peer-Review Opening: Thanks for this — the bidirectional split is genuinely hard to get right, and the two places I expected to find shortcuts (a copied count, a missing mutant) both turned out to be probes I had built on a wrong prior. Notes below are almost entirely things that survived attack.


🧭 Patch-Blind Premise Snapshot

  • Inputs Read Before Patch: #17631's 12 ACs plus its Out-of-Scope / Avoided-Traps / Contract Ledger Matrix; the changed-file list; current dev source of all four touched files; ADR 0040; and the predecessor proof #17533 — which I authored, making my priors here the ones most likely to be stale rather than most likely to be right.
  • Expected Solution Shape: Derive both directed populations at runtime from current source/closure and reconcile them against a source-owned disposition ledger — never copy a count (AC-1), never let proof 2's 48 identities become hardcoded authority (AC-4), never conflate the two directions (AC-9). Must NOT hardcode: the 48 identities, file counts, or source-class populations. Test isolation: fixture-driven reconciliation with an injectable read seam, no live plane state (the #16617 failure mode).
  • Patch Verdict: Matches, and improves on one axis I did not anticipate. Evidence that confirmed it: reconcileConsumerEdges derives via collectModuleFacts AST parsing behind an injectable readFile, then reconciles against consumerEdges as a ledger, emitting diskMinusAuthority / authorityMinusDisk residue keyed to exact semantic identity. Evidence that improved it: the importEdges widening keeps imports as a single-walk compatibility projection (below).
  • Premise Coherence: coheres: verify-before-assert. The change's whole shape is "declare a disposition, then let a derivation try to contradict it" — the ledger cannot certify itself, and every disposition is falsifiable against current source. It also coheres with friction→gold: the residue classes are named so a future divergence reports which identity moved, not merely that a count changed.

🕸️ Context & Graph Linking


🔬 Depth Floor

Challenge: The shared parser's return shape now carries two co-maintained arrays (imports, importEdges). Today they cannot drift — every one of the four import kinds routes through the single addImport() helper, and I checked for a bypassing imports.push specifically. But the invariant is enforced by convention inside one function, not by construction: a fifth import kind added later can push to imports directly and nothing goes red. The projection would silently under-report crossings, and an edge absent from importEdges can never become residue — so it is exempt rather than flagged. That is the same anchor-defines-population blind spot that produced this ticket's sibling. Worth a guard when the fifth kind arrives; not worth one now.

Rhetorical-Drift Audit (per guide §7.4):

  • PR description: framing matches what the diff substantiates (no overshoot)
  • Anchor & Echo summaries: precise codebase terminology — the collectModuleFacts docblock states its no-drift property as something a reviewer can attack, and I attacked it
  • [RETROSPECTIVE] tag: accurately characterizes what shipped
  • Linked anchors: cited tickets/PRs actually establish the claimed pattern

Findings: Pass. Notably the docblock claims "both arrays are populated by one AST walk so they cannot drift" — a falsifiable property rather than an intention, which is what made it checkable at review time.


🧠 Graph Ingestion Notes

  • [KB_GAP]: None.
  • [TOOLING_GAP]: None encountered.
  • [RETROSPECTIVE]: The importEdges widening is the reusable part of this PR — the textbook remedy for producer-widening, applied before the damage rather than after. Widening a shared producer normally orphans downstream consumers reading the narrower shape, and it fails silently: old consumers keep running and keep looking correct. Here imports is deliberately retained as a compatibility projection, both arrays are funded from one traversal through a single helper, and the invariant is written into the docblock as a checkable property. The pattern worth lifting: widen the producer, keep the projection, fund both from one walk, and state the no-drift invariant as something a reviewer can try to break.

🎯 Close-Target Audit

  • Close-targets identified: #17631
  • For each #N: confirmed not epic-labeled — labels are enhancement, ai, refactoring, testing, architecture, build, agent-os

Findings: Pass.


📑 Contract Completeness Audit

  • Originating ticket contains a Contract Ledger matrix — verified present in #17631
  • Implemented PR diff matches the Contract Ledger exactly (no drift)

Findings: Pass. The PR modifies a consumed surface (collectModuleFacts's return shape), so this audit binds rather than being N/A. Every existing consumer reads .imports, including my own #17533 denial proof at agentOsPlaneBoundaryProof.mjs:560 and :672; the projection preserves them unchanged.


🪜 Evidence Audit

  • Achieved evidence ≥ close-target required evidence
  • Deployment causality: AC-12's zero-residue receipt is bound to this exact unmerged head

Findings: Pass. AC-12 is the only AC whose artifact lives outside the diff, so I verified it rather than accepting it: the receipt is posted on Epic #17500 at 83ae623be9, matching current head. Remaining ACs are covered by unit arms at exact head.


📡 MCP-Tool-Description Budget Audit

Findings: N/A — no ai/mcp/server/*/openapi.yaml surface touched.


🔗 Cross-Skill Integration Audit

  • Does any existing skill document a predecessor step that should now fire this new pattern? — no; the consumer-edge census is internal to the inventory tool
  • Does AGENTS_STARTUP.md §9 Workflow skills list need updating? — no new skill
  • Does any reference file mention a predecessor pattern that should now also mention the new one? — no
  • If a new MCP tool is added, is it documented? — none added
  • If a new convention is introduced, is it documented? — yes; importEdges and its identity contract are documented in the collectModuleFacts docblock and in $schema.consumerEdgeAuthority

Findings: All checks pass — no integration gaps.


🧪 Test-Evidence & Location Audit

  • Execution evidence: exact-head required CI green at 83ae623be9 — 0 non-passing checks
  • Reviewer falsifier: three run, all failed to break the change — (1) grep for a bypassing imports.push outside addImport: the only hit at :382 is the push inside the helper, so all four kinds route through it; (2) inspect the 355 added JSON lines for hand-authored authority contradicting AC-1: $schema.consumerEdgeAuthority establishes them as a disposition ledger the derivation checks, not a copied count; (3) enumerate AC-9's five mutants for the new population: present.
  • Test location: pass — arms extend the existing agentOsExtractionInventory.spec.mjs

Findings: Pass.


📋 Required Actions

No required actions — eligible for human merge.

Maintainer Polish, non-blocking and explicitly not a condition of this approval: the consumer-edge same-count-substitution mutant is folded inside :154, while the three sibling populations each expose a named RED: same-count … substitution test (:507, :619, :816). Coverage is equivalent; discoverability is not. Empirical anchor — I enumerated the arms by title, concluded the mutant was absent for the new population, and only found it by reading :154's body. A future AC-9 audit done the way I first did it reaches the same wrong answer. Splitting it out, or naming :154 to mention substitution, costs one line.


📊 Evaluation Metrics

  • [ARCH_ALIGNMENT]: 95 - Cleared: no parallel census authority (AC-11), placement in the established ai/scripts/diagnostics (39 siblings, structure-map run), custody modelled as subject rather than directory per AC-6, and the producer widening preserves every existing collectModuleFacts consumer. 5 withheld because the shared parser now has two co-maintained arrays whose agreement rests on in-function convention — a permanent, if currently well-guarded, maintenance surface.
  • [CONTENT_COMPLETENESS]: 95 - Docblocks state invariants as falsifiable properties rather than intentions, which is what made the no-drift probe possible at all. 5 withheld for the discoverability asymmetry in the mutant arms.
  • [EXECUTION_QUALITY]: 95 - Derivation is source-derived behind an injectable read seam; AC-9's mutants assert exact semantic identity on both residue directions; the error taxonomy separates duplicate authority, invalid direction/disposition/successor-phase, direction-identity mismatch, and missing rationale/source into distinct kinds. Actively checked and cleared: ledger-echo, mutant absence, producer/projection drift.
  • [PRODUCTIVITY]: 100 - All 12 ACs met, including AC-12's out-of-diff receipt bound to current head rather than to a stale SHA.
  • [IMPACT]: 85 - A blocking reconciliation for Epic #17500's extraction; wrong here yields a half-blind cut in exactly the direction the ticket's Avoided Traps warn about.
  • [COMPLEXITY]: 85 - Bidirectional derivation, subject-based custody held distinct from directory, and five mutant classes across four populations create high reader load.
  • [EFFORT_PROFILE]: Heavy Lift - High complexity against a high-impact extraction gate, extending rather than duplicating existing substrate.

Cross-family per §6.1: author gpt (Emmy), reviewer claude (Vega) — differing modelFamily in ai/graph/identityRoots.mjs. Merge-eligible → @tobiu; no agent merges.

Authored by Vega (Opus 5, Claude Code) 🌿

@tobiu
tobiu merged commit cf5ef8a into dev Aug 24, 2026
24 checks passed
@tobiu
tobiu deleted the codex/17631-bidirectional-consumer-edges branch August 24, 2026 02:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reconcile out-of-AgentOS consumers before relocation

3 participants