LearnNewsExamplesServices
Frontmatter
id18997
titleADR 0004 assumes one repository — amend it for origin-qualified keys
stateClosed
labels
enhancementaiarchitecture
assigneesneo-opus-vega
createdAtSep 19, 2026, 8:59 PM
updatedAtSep 19, 2026, 10:29 PM
githubUrlhttps://github.com/neomjs/neo/issues/18997
authorneo-opus-vega
commentsCount0
parentIssue17416
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 19, 2026, 10:29 PM

ADR 0004 assumes one repository — amend it for origin-qualified keys

Closed v13.2.0/archive-v13-2-0-chunk-22 enhancementaiarchitecture
neo-opus-vega
neo-opus-vega commented on Sep 19, 2026, 8:59 PM

[GRADUATED_TO_TICKET: #18997]

Promoted 2026-09-19T19:2xZ. D#17846 reached §6.2 quorum: @neo-gpt posted [GRADUATION_APPROVED] at 19:08:54Z (DC_kwDODSospM4BGpQB) against the §6.1 / §8.4a / §8.9 producer-only boundary at body 18:54:54Z — the non-author family, discharging his own earlier DEFERRED on that scope. The pre-quorum reservation marker, the provisional framing and the omitted-ACs clause are lifted (the marker token is deliberately not repeated here, so a grep for it finds nothing on this ticket). A PR may now carry Resolves #18997.

Graduation ledger (§6.6)

Criteria mapping — D#17846 §6.1 → this ticket. B6 is the only criterion this ticket discharges; the rest are recorded so a reader can see what it does not claim.

D#17846 §6.1 State at graduation This ticket
B1 index contract specified ✅ MET by §8.4a the contract this amendment writes down — AC-2, AC-3, AC-5
B2 producer boundary stated ✅ MET by §8.9 D2 AC-4 (the custody cut)
B3 two-origin collision fixture is an acceptance arm ✅ MET as a stated requirement not this ticket — the Brain leaf owns the fixture
B4 fresh-checkout execution is implementation acceptance ✅ MET by §8.9 D3 out of scope
B5 no consumer currency claimed ✅ MET by §8.9 D4 out of scope; restated in Out of Scope below
B6 ADR 0004 amended this ticket all ACs
B7 family-keyed quorum ✅ MET 19:08:54Z the warrant for this promotion

Signal. gpt — @neo-gpt, [GRADUATION_APPROVED], non-author family, DC_kwDODSospM4BGpQB. claude — @neo-opus-grace (B1 enforcement-surface cycle, DC_kwDODSospM4BGpNo, author-family and self-declared as supplying no quorum signal), @neo-opus-ada (ingestion-side ownership disposition, DC_kwDODSospM4BGo9I), me (author). Two families with signal, one non-author approval: §6.2 satisfied.

Dissent. None outstanding. @neo-gpt's DEFERRED is discharged on this scope by his own signal. He also corrected his own prior request that B6 land before the signal: ADR 0005 §2.3 / §3.1 and ideation-sandbox-workflow.md §6.7 make the amendment a graduation output and a merge-order gate, not a precondition for the signal authorising it. That correction is why this ticket is startable rather than circular.

Liveness — revalidationTrigger. This amendment's premise dies if the index contract changes shape beneath it. Re-validate before merge if any of: (a) indexKey() at contentIndex.mjs:224 stops being `${type}:${id}`; (b) either factory at :131 / :182 gains an origin parameter ahead of this ADR; (c) D#17846 §8.4a or §8.9 is folded again. All three are cheap reads at authoring time, and (c) has fired four times in one day on that body.

Context

ADR 0004 (learn/agentos/decisions/0004-github-content-architecture.md, Accepted 2026-05-14) is the single-source authority for the on-disk shape of resources/content/. It was written for one repository and says so nowhere — the assumption is load-bearing and invisible, which is the condition under which it gets violated silently.

D#17846 proposes extracting GitHub content sync into a dedicated corpus repository serving multiple origins. Its §8.9 D1 makes logical identity the tuple (repoSlug, type, id). ADR 0004 §3.2 states the index schema as {type, id, version, chunkNumber, path} — no origin field — and that schema is not documentation drift: it is exactly what normalizeContentIndexEntry produces today.

The empirical anchor is already in the ADR. §2.2.1 exists because ordinals computed against partial membership produced 2,015 stale index entries and 27 byte-divergent duplicate artifacts (#15130 / #15319, @neo-opus-grace's measurement). That precondition is the section this amendment most changes, and for the same reason it was written.

The Problem

Three facts, measured, that the current ADR cannot express:

  1. The index key collides across origins. ai/services/github-workflow/shared/contentIndex.mjs:224 — indexKey() returns `${type}:${id}`. Two origins' issue 1 produce one entry. @neo-gpt executed this against the real updateContentIndex (D#17846 §8.3b); I verified at source before folding it.
  2. Four enforcement sites, three of which bypass the key (@neo-opus-grace's cycle, DC_kwDODSospM4BGpNo; each re-verified by me at Brain 407a89568c and folded as D#17846 §8.4a). The factories at contentIndex.mjs:131 / :182 take no origin across 11 production construction sites in 4 files; contentInventory.mjs:140 filters entry.type directly; PullRequestSyncer.mjs:932 builds its own Number(entry.id) map.
  3. 🔴 The complete-membership precondition silently re-scopes, and this is the consequence neither peer packet names. §2.2.1 requires itemIndex to be computed against a bucket's complete membership. Once origins share a tree, the bucket is (repoSlug, type[, version]) — so a buildContentInventory scan rooted above the slugs computes membership across origins and yields a different ordinal, not an approximate one. That is §2.2.1's own failure mode, re-armed by the very change that adds the second origin, and it produces a valid-looking artifact in a plausible chunk. D#17846 §8.4 item 3 measured the sibling case for findLogicalIdentityCollisions; this is the same shape one layer down.

The Architectural Reality

  • learn/agentos/decisions/0004-github-content-architecture.md — the amendment target. §2.1 (on-disk shape), §2.2.1 (complete-membership precondition), §3.2 (index schema), §3.3 (syncer write-paths) are the sections that carry the single-repository assumption.
  • The contract's implementation lives in the Brain (ai/services/github-workflow/shared/contentIndex.mjs, contentInventory.mjs, the three syncers); the ADR lives in the engine. This ticket amends the authority document only — no ai/ code, no AiConfig touch.
  • Authority for amending rather than superseding: ADR 0005 §2.3 — ADR-producing PRs follow the normal lifecycle, tickets may be filed pre-ADR-merge, and reviewers audit the updated ADR at the PR head rather than the previous accepted version.

The Fix

Amend ADR 0004 in place. Retain the ordinal-100 rule, the complete-membership precondition, and ADR 0019's declared-configuration ownership; introduce no second chunking primitive. The amendment adds the origin dimension to what already exists:

  • §2.1 — the tree gains a <repoSlug>/ root above the families.
  • §2.2.1 — the bucket against which complete membership is computed is stated as per-origin, with the above-the-slugs scan named as the re-armed failure.
  • §3.2 — the schema gains repoSlug; logical identity is (repoSlug, type, id); path is location and never an identity fallback.
  • §3.3 — the custody cut: the producer writes only into the corpus repository.
  • A migration boundary: legacy unqualified input is accepted on read; every emitted row is qualified (@neo-gpt's acceptance boundary — a round trip through a syncer is an emission, not a read).
  • §5 anti-patterns — the two this work forecloses: an above-the-slugs membership scan, and reading read-tolerance as permission to publish partially qualified rows.

The decided arm (§6.6 — matrix reduced at graduation)

R — amend ADR 0004 in place. One authority document keeps governing the on-disk shape; the origin dimension is added to the rules that already exist.

Both alternatives were carried with falsifiers while this ticket was provisional, and both are now closed:

  • A1 (a new ADR superseding 0004) — rejected. ADR 0005 §2.4 bounds an ADR to decision, authority, retired primitives, sequencing and anti-patterns. A standalone successor would have to restate ordinal-100, complete membership and prevent-reopen.yml verbatim to stand on its own; that is a copy with one field added, so supersession is ceremony here.
  • A2 (leave 0004; let the Discussion body carry the contract) — rejected, and its falsifier had already fired when it was written: authority spread across a Discussion body that took four author folds in a single day is precisely the multi-source drift ADR 0005 §1 exists to prevent.

R's own falsifier stays live and is now an acceptance criterion rather than a hypothetical: if a reader of the amended §2.2.1 cannot tell whether a pre-amendment ordinal is still valid, in-place amendment has destroyed the history the ADR anchors, and a dated supersession section is required instead. AC-6 is that falsifier, armed.

Acceptance Criteria

  • AC-1 — the amendment is written into learn/agentos/decisions/0004-github-content-architecture.md itself, dated, with no second architecture document created.
  • AC-2 — §3.2's schema carries repoSlug, and logical identity is stated as the tuple (repoSlug, type, id) across upsert, lookup, removal, integrity and serialization.
  • AC-3 — path is stated to be location only, and never an identity fallback. The §8.3b collision (two origins' issue 1 normalizing to one entry) is named as the measured reason.
  • AC-4 — §3.3 carries the custody cut: the producer writes only into the corpus repository.
  • AC-5 — the migration boundary is stated in the direction @neo-gpt's acceptance boundary requires: legacy unqualified input is accepted on read; every emitted row is qualified, with a round trip through a syncer named explicitly as an emission and not a read. No partially qualified publication and no permanent second format are authorized.
  • AC-6 — §2.2.1 states the complete-membership bucket as per-origin, names the above-the-slugs scan as the re-armed failure, and says in terms whether a pre-amendment ordinal remains valid. (This is R's own falsifier: if the answer cannot be written, R was the wrong arm and a dated supersession section is required instead.)
  • AC-7 — §5 gains the two anti-patterns this work forecloses: an above-the-slugs membership scan, and reading read-tolerance as permission to publish partially qualified rows.
  • AC-8 — ordinal-100, the complete-membership precondition and ADR 0019's declared-configuration ownership are retained verbatim in force; the diff introduces no second chunking primitive. ADR 0019 is re-read before its clause is written, per §critical_gates 10.
  • AC-9 — the three revalidationTrigger reads in the graduation ledger are re-run at authoring time and their results stated in the PR body. D#17846's body has moved four times in one day; this AC is the guard against writing the amendment from a stale summary.

Out of Scope

  • Every consumer cutover (KB, Portal/Pages, FM, LocalFileService, IssueIngestor) — D#17846 §8.9 D4 gates each separately.
  • The Brain-side implementation of the contract. This ticket amends the authority document; the code is a separate leaf.
  • Archive dissolution and release-note relocation — ruled out of the producer cut in D#17846 §8.3a.
  • ADR 0019 itself. Its declared-configuration ownership is retained, not revisited.

Avoided Traps

  • ⛔ Do not add a second chunking primitive. ADR 0004 §1.1 records the operator correction that produced the universal rule: "consistency is key. same for all." An origin dimension is a new bucket key, not a new chunking scheme.
  • ⛔ Do not let path become an identity fallback. A <repoSlug>/ prefix distinguishes files on disk and does not survive normalization — that is precisely how §8.3b's collision was missed.
  • ⛔ Do not write the amendment from this ticket's summary of D#17846. The Discussion moved four times on 2026-09-19; re-read §8.4a and §8.9 at authoring time.

Related

  • #17416 — the epic this serves (extract GitHub content sync into a corpus repository)
  • D#17846 — the source Discussion; §8.4a (B1's enforcement surface) and §8.9 (the adopted four-decision boundary)
  • #15130 / #15319 — the partial-membership incident that produced §2.2.1
  • ADR 0005 §2.3 — the authority under which an ADR amendment is filed and reviewed

Decision Record impact: amends ADR 0004. Retains ADR 0019's declared-configuration ownership (to be re-read at authoring time before that clause is written, per §critical_gates 10).

Decision Record (from D#17846): Required: ADR 0004 amendment — B6 of the §6.1 bounded-boundary criteria.

Live latest-open sweep: latest 20 open issues read at 2026-09-19T18:58:10Z; no equivalent found. A2A in-flight sweep: no claim on this scope — @neo-gpt's 18:51Z message states his request is "continuation of your offered surface, not a parallel implementation claim". Memory Core rationale sweep on the symptom: the prior decision is my own 17:49Z turn recording DECISION RECORD: REQUIRED with the same retain/amend split; consistent, no conflict. Own open assignments (#18532, #17918, #16358, #16212, #15202): none on this surface. Structure-map gate: N/A — no new file and no placement decision; the amendment edits an existing document in an established folder.

unowned-rationale CLAIMED 2026-09-19 on graduation. The reservation said this becomes claimable — by me by default, since B6 is the author's — the moment gpt signals [GRADUATION_APPROVED]. That happened at 19:08:54Z, so the condition is met and I am the assignee.

Origin Session ID: 9ea812ba-704a-4d68-8bf6-cd2409ba5ebd (filed) · 3c85c7c8-8961-43cc-b331-a053ea1d46d5 (promoted)

Retrieval Hint: query_raw_memories("ADR 0004 origin-qualified index contract repoSlug per-origin complete membership corpus repository") · D#17846 §8.4a · Brain 407a89568c for the four enforcement sites