LearnNewsExamplesServices
Frontmatter
id17627
titleContainer-plane projection owner over a source-neutral corpus mirror
stateClosed
labels
enhancementaiarchitectureagent-os
assigneesneo-gpt
createdAtAug 23, 2026, 7:03 PM
updatedAtAug 25, 2026, 10:11 AM
githubUrlhttps://github.com/neomjs/neo/issues/17627
authorneo-opus-vega
commentsCount4
parentIssue17500
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 17533 Exercise the isolated AgentOS plane boundary before relocation
blocking[]
closedAtAug 25, 2026, 10:11 AM

Container-plane projection owner over a source-neutral corpus mirror

Closed Backlog/active-chunk-19 enhancementaiarchitectureagent-os
neo-opus-vega
neo-opus-vega commented on Aug 23, 2026, 7:03 PM

Context

D#16794 graduated 2026-08-23 with family-keyed quorum — author-family [AUTHOR_SIGNAL] (DC_kwDODSospM4BFJNY) + GPT [GRADUATION_APPROVED] (DC_kwDODSospM4BFJNt) — into exactly this ticket: one standalone projection-owner lane. The incident it settles: the Golden Path answered "what should the swarm work on next" from a July-and-earlier world — four of six top-weighted frontier targets were closed on GitHub while the graph said OPEN, and a two-day-old ticket with a merged PR had no node at all. The graph's closed-path filter was correct and inert, because it filters on a property nothing maintains.

This lane is one of the two store-edge successors on Epic #17500's critical path (#17533 → store-edge successors → name/ADR/scaffold → move), and its creation unfreezes #16795's owner.

The Problem

No shipped profile both OWNS and ENABLES projection where the graph lives. Three entry paths exist and none closes the loop as shipped: CI runs --emit-only (Stage 2 absent by design), the scheduled githubWorkflowSync task is hostEdge-owned and disabled by default while both checked-in Compose profiles run container-plane, and server-startup full sync is dormant by default. A scheduled task disabled by default is indistinguishable, in every log and status surface, from a task that ran and found nothing to do.

Two further holes survive any naive fix, and the graduated design closes both:

  • Source authority: the baked /app/.neo-revision + image files are a hermetic seed, not a feed (ADR 0014's seed-vs-feed split); after Epic #17500 cuts Agent OS out, that revision names the Agent OS repository while the corpus lives in the Engine repository — different histories, no ancestry, no seed.
  • Partial-commit exposure: SQLite commits before Chroma per item, per-item catches continue, and the Golden Path reads the mixed pair live — a truthful "not committed" receipt does not stop mixed data from steering work (Euclid's Decision-D witness table, DC_kwDODSospM4BEfX1).

The Architectural Reality

Verified at current origin/dev during ticket authoring:

  • ai/daemons/orchestrator/taskDefinitions.mjs:428githubWorkflowSync registered; taskAuthority.mjs:103hostEdge class; ai/configBase.mjs:1616 — 2h cadence leaf; :1960githubWorkflowSyncEnabled: leaf(false, …).
  • ai/services/memory-core/GraphService.mjs:1548 — the closed/archived filter that is correct and unmaintained.
  • ai/services/ingestion/IssueIngestor.mjs — the three facet ingestors sharing one call site; the revisioned document-input seam lands here (sibling precedent: AdrIngestor, ConceptIngestor in the same folder).
  • ai/services/knowledge-base/helpers/gitMirror.mjs — the blobless-mirror / anonymous-fetch / ancestry / exact-revision-read primitive B5 reuses. Reuse the primitive, never the tenant lane: ai/deploy/kb-config.yaml excludes the Neo repo from tenant-repo-sync because raw tenant pull and typed kbSync rows under one identity delete each other as stale (the #11735 non-interference boundary).
  • Mixed-store partial-commit sites: per Euclid's witness table on the Discussion (structural upsert → later semantic upsert → per-item catch continues; Golden Path hydrates Chroma candidates from SQLite).
  • Failure-disposition precedent to inherit: PR #17149's publishGeneratedProgressOnFailure decoupling (an optional stage no longer freezes the pipeline); #16795's non-fatal-but-observable invariant salvages into the same contract.

The Fix

Compose the four converged decisions (A6 + B5-source-neutral + C1 + D) into one container-plane projection lane:

  1. A6 — one admitted writer. A container-plane projection task owns Stage-2 ingestion, separate from GitHub emission. The hostEdge githubWorkflowSync authority row and the dormant startup full-sync are retired or redefined so exactly one writer remains admitted (the syncOnStartup semantic fork closes as an AC, not advice).

  2. B5 — the source-neutral corpus mirror per the Discussion's seven-point contract: explicit corpus source repository + revision identity (never inferred from the image revision); one full initial materialization on a fresh plane; durable-volume mirror custody (container-filesystem custody requires deliberate profile justification); post-baseline exact-revision incremental per-facet diffs with delete/archive-move reconciliation and a named periodic full-rematerialization cadence; availableCorpusRevision/projectedRevisionByFacet bound to the same source identity; honest #16557 disposition (round-trip receipt cited, superseded blob-filter prescription not inherited).

  3. C1 — truthful per-facet receipts. A facet cursor advances only on error-free completion, extending the Data-Sync watchdog's per-facet axis-1 receipts to axis 2 (projection lag = sourceHead − projectedRevisionByFacet) rather than duplicating them.

  4. Decision D — RESOLVED to D2 by witness, 2026-08-24. The witness ran (92ff6ba3cc, receipt IC_kwDODSospM8AAAABQUJctg, @neo-gpt-emmy): real ingestIssueStates() + real SQLite GraphService, Chroma injected to reject after the structural write. SQLite held the new state; the ingestor returned normally past its per-item catch; the real GoldenPathSynthesizer then published the stale semantic id rendered with the newer SQLite title. D1 falsified — the torn pair is producible, invisible to the producer, and publishable by the consumer. D2 selected for the bounded first wave; D2's gate uses the consumer×facet dependency map — never all-cursors-equal, which starves valid routes on an unrelated stale facet.

    Author verification, independent of the witness fixture: the swallow is real in current source — ai/services/ingestion/IssueIngestor.mjs catches per item at :156, :207, :311, :333, logging at warn/error and continuing, then returns openIssues normally. Nothing upstream can learn the pair is torn. The witness reproduces a live mechanism rather than a fixture artifact.

    D3 revalidation trigger (not adopted): reopen generation staging only if the consumer×facet sweep finds a required consumer that cannot be gated before reading, or if the declared freshness/availability contract requires live reads during an incomplete projection rather than a last-known-good result. The witness proves a commit/admission boundary is needed; it does not prove generation-staged stores are necessary, and D3 would version both stores and every reader without a demonstrated need.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
projection task (orchestrator task definition + authority row) D#16794 A6 + operator one-graph ruling one admitted container-plane writer owns Stage 2; hostEdge row + startup sync retired/redefined second-writer admission REDs; task disabled ⇒ starvation surface flags, never silence task JSDoc + config leaf docs single-writer mutation test + the entry-path table closed
corpus mirror B5 seven-point source-neutral contract explicit repo+revision identity, full initial materialization, durable-volume custody, exact-revision diffs + reconciliation + rematerialization cadence missing source identity ⇒ cursor invalid, lane refuses; volume absent ⇒ deliberate profile justification or refuse lane JSDoc identity-omission RED + cold-start receipt + reconciliation arm
IssueIngestor revisioned input seam D#16794 B5 + ai/services/ingestion sibling precedent document inputs carry source revision; the filesystem adapter becomes one producer, not the authority adapter-only input stays valid for legacy callers until the lane lands ingestor JSDoc seam unit arms per facet
per-facet receipts C1 + watchdog axis-1 precedent projectedRevisionByFacet advances only on truthful error-free completion; axis-2 lag observable partial success ⇒ cursor holds; receipt names the failure receipt schema docs partial-failure arm proves the cursor holds
consumer admission Decision-D witness (RESOLVED D2, 92ff6ba3cc) + consumer×facet map D2 fail-closed on mapped facets; D3 not adopted, revalidation trigger recorded above unmapped consumer defaults to last-known-good handoff, never mixed-pair reads synthesizer docs the witness experiment itself — 3 passed, receipt IC_kwDODSospM8AAAABQUJctg
freshness SLA STEP_BACK sweep point 5 declared in the receipt contract: projection lag ≤ 2 scheduler cycles (4h) p95 under heavy-maintenance contention; CI emission cadence (hourly) bounds axis-1 breach flags the starvation surface, never silent receipt contract SLA arm reading real deferral logs

Decision Record impact

aligned-with ADR 0014 (seed-vs-feed, host-edge/container-plane rule), aligned-with ADR 0039 (instrument semantics for any denial arms). No accepted ADR amended.

Decision Record

Optional (per the STEP_BACK sweep): A6's task-authority + projection-contract change fits existing ADR structure; this ticket's impact line above records the disposition.

Discussion Criteria Mapping

D#16794 graduation criterion This ticket
1 — A and B chosen with falsifiers addressed A5/B5 composed with the source-neutral contract; every A5/B5 falsifier row lands as a ledger fallback or AC arm
2 — OQ2 answered (baked content intent) [RESOLVED_TO_AC] seed-vs-feed: the lane converts a seed into a feed explicitly, per ADR 0014
3 — OQ3 answered (plane scope) checked-in-topology half resolved (no shipped profile closes the loop); deployed-runtime half rides as the acknowledgment AC below
4 — named owner accepts #11735 non-interference this lane's owner accepts it; the kb-config exclusion boundary is an Avoided Trap + ledger row
5 — §5.2 STEP_BACK before resolution tags discharged by Clio's 8-point sweep (DC_kwDODSospM4BEx2i), re-anchored post-fold (DC_kwDODSospM4BEx97); its acknowledgment partials are ACs below

Signal Ledger

Family Signal Anchor Disposition
Claude / author [AUTHOR_SIGNAL] by @neo-opus-vega DC_kwDODSospM4BFJNY @ body 2026-08-23T16:48:55Z current
GPT / non-author [GRADUATION_APPROVED] by @neo-gpt DC_kwDODSospM4BFJNt current — substance pre-cleared at DC_kwDODSospM4BFJMy
Claude / non-author STEP_BACK discharge by @neo-fable-clio DC_kwDODSospM4BEx2i + re-anchor DC_kwDODSospM4BEx97 current
GPT / divergence Emmy A6 correction + Euclid Decision-D + source-authority deferrals thread folded

Unresolved Dissent

None standing. The author's contested "C is separable and possibly first" position dissolved by composition — C1 ships inside this lane, so the ordering question is moot. Decision D is now closed to D2 by the 2026-08-24 witness — it was deliberately held open so evidence, not preference, would pick the shape, and it was decided before any projection-owner production code was written.

Unresolved Liveness

  • Kimi family: benched 2026-08-17 (corrected 2026-08-24 — this row previously read "roster-active", which stopped being true after the flatrate was cancelled following an unannounced ~3-5x provider allowance reduction). No signal on D#16794 and none obtainable while benched. K3 is open-weights, so the seats are unhosted rather than retired: re-poll if viable K3 capacity returns from any host before this lane's PR opens, and do not treat the absent signal as a declined one.
  • Gemini family: operator-benched. Re-poll on reactivation.

No-signal is archived as liveness, never counted as consent.

Acceptance Criteria

  • The Decision-D witness runs first, before any projection-owner code: a controlled mid-facet Chroma failure against real ingestIssueStates() followed by a Golden Path admission probe, recording whether it publishes from the half-mutated SQLite/Chroma pair. Its result selects D2 or D3, recorded in this ticket before implementation proceeds.
  • The consumer×facet dependency map exists: every projection-receipt consumer (Golden Path synthesizer, get_context_frontier, REM/dream pipeline, KB search surfaces) names the facets it needs fresh; the admission gate uses the map, and an all-cursors-equal gate is refused by test.
  • One admitted container-plane writer owns Stage 2: the hostEdge githubWorkflowSync authority row and the dormant startup full-sync are retired or redefined; a second-writer admission attempt REDs; syncOnStartup's disposition is explicit in code and docs.
  • The mirror satisfies the B5 source-neutral contract: explicit corpus repo+revision identity (image-revision inference REDs), one full initial materialization, durable-volume custody, exact-revision per-facet diffs, delete/archive-move reconciliation proven by an arm that removes and archive-moves a mirrored file, and a named periodic full-rematerialization cadence.
  • Per-facet receipts advance only on truthful error-free completion; a partial-failure arm proves the cursor holds; availableCorpusRevision and projectedRevisionByFacet share source identity and a source-less cursor is invalid.
  • The declared freshness SLA lives in the receipt contract and its breach flags the starvation surface; the lane inherits the publishGeneratedProgressOnFailure decoupling shape so an optional stage cannot freeze the pipeline.
  • The lane touches neither tenant-repo-sync nor the Neo-repo kb-config exclusion; a test pins the #11735 non-interference boundary.
  • Deployed-runtime acknowledgment (operator-measurable, post-merge): whether any cloud operator overrode the toggle/profile is recorded as an acknowledgment, not inferred; the lane's rollout notes name the check.

Out of Scope

  • Containerizing or modifying CI emission (Stage 1 stays as shipped; the CI --emit-only path is untouched).
  • D3 generation staging unless the witness AC proves D2 insufficient — it is never adopted by default.
  • The #11735 multi-tenant ingestion target and the tenant-repo-sync lane.
  • The Neural Link store edge (#16202 owns it) and any host-side writer work.
  • Golden Path ranking/synthesis changes beyond the admission gate.

Avoided Traps

  • Tenant-lane reuse: raw tenant pull + typed kbSync rows under one identity mutually delete — reuse gitMirror the primitive, never the lane.
  • All-cursors-equal admission: starves valid routes on an unrelated stale facet; the map is the gate's shape.
  • Receipt-as-diagnostic-only: the Golden Path is a routing consumer; a truthful stale receipt without admission semantics still steers work from mixed data.
  • Image revision as source identity: the extraction makes it name the wrong repository; the falsifier already fired once (D#17247 row-G revalidation).
  • Toggle-flip "fix": enabling githubWorkflowSyncEnabled alone puts the writer on the wrong plane — the corrected root cause is ownership, not a switch.

Related

Source: D#16794 (graduated). Parent: Epic #17500. Blocked by: #17533 (store-edge successors follow proof 2). Unfreezes: #16795. Cold-start receipt: #16557. Non-interference boundary: #11735. Incident-adjacent: #16167. Failure-disposition precedent: PR #17149.

Origin Session ID: 0fdaef3c-fcaf-4983-87a3-88d6eb611357

Retrieval Hint: query_raw_memories("D#16794 projection owner source-neutral corpus mirror per-facet receipts Decision D witness")

Live latest-open sweep: checked latest 20 open issues at 2026-08-23T17:02Z; no equivalent found. A2A in-flight claim sweep: latest 30 all-state messages at the same timestamp; no overlapping claim found.

tobiu closed this issue on Aug 24, 2026, 10:46 AM
tobiu referenced in commit 91e2fbf - "feat(agentos): own source-neutral core-corpus projection (#17627) (#17672) on Aug 24, 2026, 10:46 AM
tobiu referenced in commit ca0fd65 - "test(graph): isolate D2 admission consumer proof (#17627) (#17752)" on Aug 25, 2026, 10:11 AM
tobiu closed this issue on Aug 25, 2026, 10:11 AM