Graduated from D#17756 at §6.2 quorum. [GRADUATED_FROM: D#17756 @ body updatedAt 2026-08-25T21:13:40Z]
Context
neomjs/devindex carries a hand-copied AGENTS.md differing from canonical in 8 hunks, two of them semantic — an older §identity_prompt_firewall duty scope and a missing #16528 rule. An agent working there runs an older constitution and nothing compares the two. Where substrate was copied it drifted invisibly; where it was not copied it is simply absent (neo-agent-brain has no .agents/skills at all).
The canonical store now exists — neomjs/neo-agent-skills, created 2026-08-25, public, empty, default branch main. This ticket defines what its first commit must be. That is the cheapest moment this contract will ever have.
Live latest-open sweep: checked the latest 20 open issues at 2026-08-25T21:22:18Z; no equivalent found. A2A in-flight claim sweep over 30 messages (all read-states): no overlapping [lane-claim].
The Problem
Skill substrate takes 181 commits per 90 days across 62 distinct days. No mechanism keeps consuming repos current, and the failure mode is not staleness — it is invisible staleness. devindex is not behind, it is forked, and nothing reports that.
The target population was itself wrong for most of the Discussion: the body priced this over "21 repositories" until a live census returned 52 (44 public / 8 private, 4 forks, 48 owned-non-fork, 0 archived). Every cadence and blast estimate computed over 21 was computed over the wrong set — which is why this ticket forbids hardcoded populations outright.
Two axes were also conflated, and separating them is load-bearing:
axis
rule
Repo distribution
every enrolled repo carries the same canonical tree — no per-repo subsets (operator SSOT ruling)
Harness exposure
each harness receives the manifest-declared projection — per-harness subsets are legitimate
.agents/skills/skills.manifest.json — budget + projection SSOT. defaults.claudeSymlinkRequired: true, per-skill override observed on debugging-antigravity. Lint-enforced at ai/scripts/lint/lint-skill-manifest.mjs:890.
.claude/skills/ — 37 committed per-skill symlinks into ../../.agents/skills/*: the current manifest-derived façade.
buildScripts/util/check-chore-sync.mjs (via .husky/pre-commit:1) — the existing sync-guard precedent, gating resources/content/** commits to sync branches.
.husky/pre-push:16 runs node ./ai/scripts/lint/check-commit-authorship.mjs as guard 2 of 3, under set -e at line 7.
The enforcing seat cannot be husky.check-chore-sync.mjs and mergeInheritance.mjs honour --no-verify, so hook-based guards are feedback, not authority. Authority is reusable CI plus required branch protection — owned by #17783.
Install-time materialization of the tree is falsified.npm ci --ignore-scripts is already deliberate practice in three of our workflows — openapi-service-parity-lint.yml:72, ticket-archaeology-lint.yml:45, jsdoc-type-lint.yml:46 — two carrying comments that it exists to skip the heavy postinstall. We have prepare, not postinstall, and --ignore-scripts skips both. An install-time tree yields zero skills, silently, with no error.
The Fix
Seed neomjs/neo-agent-skills and stand up B6 + B3:
Canonical tree committed in the canonical repo and bot-synced as committed bytes into each enrolled repo.
AGENT_SUBSTRATE_REVISION receipt — one immutable canonical commit/tree covering the skill tree, the manifest, and the public facts schema/renderer/public-common clauses. It excludes the internal maintainer constitution, which keeps its own revision authority in the D#17644 / Brain substrate.
Promotion epochs — canonical changes coalesce behind a tested promotion revision; one campaign opens at most one PR per enrolled repo. Early promotion reserved for urgent safety changes.
Per-harness façade generated from the manifest. Wave one preserves the current committed per-skill links unchanged.
Two-leg consumer CI (callers of a reusable workflow): synced bytes equal canonical@receipt, and non-sync mutation of synced paths is rejected — while permitting manifest-declared per-harness projection differences.
Registry predicate, never a hardcoded population. Enrollment is rows in the canonical org registry; exclusions are explicit rows with reasons; absence never means exempt. Skill-distribution enrollment is distinct from enforcement enrollment.
Required: ADR — amend ADR 0040 §2.7 + new ADR for the distribution contract (preserved from D#17756's graduation classification).
Decision Record impact
amends ADR 0040 — §2.7's separation principle is confirmed; its boundary description needs the rendered-contributor-file / projected-constitution split. A new ADR records the distribution contract itself. The amendment lands with this work, not after it.
Discussion Criteria Mapping
D#17756 criterion
AC
OQ1 — manifest-derived façade is the required property
AC-4
OQ2 — wave one preserves current façade; replacement deferred
AC-4 + Out of Scope
OQ4 — receipt + two verification legs, constitution excluded
AC-1 — neomjs/neo-agent-skills carries the canonical tree (38 skills + manifest + schema) and the public facts schema/renderer, on a first commit that matches this contract.
AC-2 — an AGENT_SUBSTRATE_REVISION receipt exists in each enrolled repo, pinning one immutable canonical tree; the internal maintainer constitution is provably absent from what the receipt covers. Merge-order constraint (2026-08-26): enrolled repos are the registry's rows, so this AC completes only when neomjs/devindex#6 and neomjs/neo-agent-brain#5 land. Both are green. They must merge before the neomjs/neo PR that closes this ticket, or the close fires against an unmet AC.
AC-3 — consumer CI fails red when synced bytes differ from canonical@receipt. Red control: devindex's current divergence must go red, demonstrated, not asserted.
AC-4 — the per-harness façade is generated from skills.manifest.json; a manifest-declared opt-out is absent from the generated façade, proven by a test, while an included skill is present. The current committed links are preserved unchanged in wave one.
AC-5 — non-sync mutation of a synced path is rejected by CI, and a manifest-declared per-harness projection difference is permitted by the same guard. Both arms proven.
AC-6 — enrollment is a registry predicate; no population integer is hardcoded anywhere in the mechanism. An excluded repo is an explicit row with a reason.
AC-7 — enforcement binds via reusable CI + required branch protection, citing #17783's binding receipt.MOVED TO #17783 (2026-08-26). Honest amendment rather than a residual carried by PR prose: the branch-protection half requires repository admin, and every maintainer seat holds maintain — GET /branches/dev/protection returns 404 for us. An AC no assignee can execute does not belong on an implementation ticket. The reusable-CI half is delivered here (always-emitted, least-privileged, workflow_call); the binding is #17783's enforcement-custody scope, where the receipt it cites already lives.
AC-8(Tier-2 revalidationTrigger) — on reactivation of gemini or kimi (participationStatus → active in ai/graph/identityRoots.mjs), this contract is re-presented for retroactive signal before being treated as settled.
Out of Scope
The Windows / core.symlinks=false façade replacement — its own ticket, behind an explicit cross-platform AC. Wave one preserves today's proven façade.
The one-directory harness-view optimization — its own ticket, and it owes a restart proof of both arms.
CI/husky custody and branch-protection mechanics — #17783.
The contributor-surface extraction — its own graduated ticket.
Avoided Traps
npm + postinstall as the tree transport. Sketched during the Discussion and falsified: --ignore-scripts is our own practice and silently yields zero skills.
One directory symlink replacing 37. Rejected by source authority — it would expose a manifest opt-out and forecloses per-harness projection permanently, since you cannot opt a skill out of a directory symlink.
Husky as the enforcing seat.--no-verify makes it feedback, not authority.
A hardcoded repo count. Produced a wrong-by-half population that survived multiple revisions unexamined.
tobiu referenced in commit 302375c - "feat: two-leg consumer guard, reusable CI seat, enrollment predicate (neomjs/neo#17784) on Aug 26, 2026, 12:47 AM
tobiu referenced in commit 1b7cecd - "feat: generate the harness facade from the manifest (neomjs/neo#17784) on Aug 26, 2026, 12:49 AM
tobiu cross-referenced by PR #5 on Aug 26, 2026, 12:57 AM
tobiu cross-referenced by PR #4 on Aug 26, 2026, 12:57 AM
tobiu referenced in commit a3282a7 - "feat: bounded facts schema, renderer, and the Tier-2 revalidation gate (neomjs/neo#17784) on Aug 26, 2026, 1:03 AM
tobiu referenced in commit bf88227 - "chore: pin canonical@a3282a71e3 (neomjs/neo#17784) on Aug 26, 2026, 1:03 AM
tobiu referenced in commit 9d5e3ef - "chore: pin canonical@a3282a71e3 (neomjs/neo#17784) on Aug 26, 2026, 1:03 AM
tobiu referenced in commit a85dff3 - "fix: Leg A anchors to canonical history, not the consumer's own receipt (neomjs/neo#17784) on Aug 26, 2026, 2:05 AM
tobiu referenced in commit 63f838e - "chore: pin the repaired canonical guard (neomjs/neo#17784) on Aug 26, 2026, 2:05 AM
tobiu referenced in commit cddcbd9 - "chore: pin the repaired canonical guard (neomjs/neo#17784) on Aug 26, 2026, 2:05 AM
tobiu referenced in commit 8da0605 - "chore: promotion epoch — adopt the pr-review-guide change from #17794 (neomjs/neo#17784) on Aug 26, 2026, 2:11 AM
tobiu referenced in commit 3e53643 - "chore: adopt promotion epoch canonical@8da0605cd0 (neomjs/neo#17784)" on Aug 26, 2026, 2:11 AM
tobiu referenced in commit 9b24b05 - "chore: adopt promotion epoch canonical@8da0605cd0 (neomjs/neo#17784)" on Aug 26, 2026, 2:11 AM
tobiu referenced in commit c04b1ac - "fix: inert roster boundary, exact projection, least-privilege CI (neomjs/neo#17784) on Aug 26, 2026, 2:34 AM
tobiu referenced in commit 469f5f6 - "fix: exclude neo-agent-brain — extraction destination, not a stale consumer (neomjs/neo#17784) on Aug 26, 2026, 10:19 AM
tobiu referenced in commit 02cb8a2 - "fix(ci): canonical-ref defaults to dev, not the deleted main (neomjs/neo#17784) on Aug 26, 2026, 10:48 AM
tobiu referenced in commit ecb4e69 - "feat: npm package contract + consumer materializer (neomjs/neo#17784) on Aug 26, 2026, 11:01 AM
Graduated from D#17756 at §6.2 quorum.
[GRADUATED_FROM: D#17756 @ body updatedAt 2026-08-25T21:13:40Z]Context
neomjs/devindexcarries a hand-copiedAGENTS.mddiffering from canonical in 8 hunks, two of them semantic — an older§identity_prompt_firewallduty scope and a missing#16528rule. An agent working there runs an older constitution and nothing compares the two. Where substrate was copied it drifted invisibly; where it was not copied it is simply absent (neo-agent-brainhas no.agents/skillsat all).The canonical store now exists —
neomjs/neo-agent-skills, created 2026-08-25, public, empty, default branchmain. This ticket defines what its first commit must be. That is the cheapest moment this contract will ever have.Live latest-open sweep: checked the latest 20 open issues at 2026-08-25T21:22:18Z; no equivalent found. A2A in-flight claim sweep over 30 messages (all read-states): no overlapping
[lane-claim].The Problem
Skill substrate takes 181 commits per 90 days across 62 distinct days. No mechanism keeps consuming repos current, and the failure mode is not staleness — it is invisible staleness.
devindexis not behind, it is forked, and nothing reports that.The target population was itself wrong for most of the Discussion: the body priced this over "21 repositories" until a live census returned 52 (44 public / 8 private, 4 forks, 48 owned-non-fork, 0 archived). Every cadence and blast estimate computed over 21 was computed over the wrong set — which is why this ticket forbids hardcoded populations outright.
Two axes were also conflated, and separating them is load-bearing:
The Architectural Reality
.agents/skills/— subject: 38 skills + 2 manifest files (skills.manifest.json,skills.manifest.schema.json)..agents/skills/skills.manifest.json— budget + projection SSOT.defaults.claudeSymlinkRequired: true, per-skill override observed ondebugging-antigravity. Lint-enforced atai/scripts/lint/lint-skill-manifest.mjs:890..claude/skills/— 37 committed per-skill symlinks into../../.agents/skills/*: the current manifest-derived façade.buildScripts/util/check-chore-sync.mjs(via.husky/pre-commit:1) — the existing sync-guard precedent, gatingresources/content/**commits to sync branches..husky/pre-push:16runsnode ./ai/scripts/lint/check-commit-authorship.mjsas guard 2 of 3, underset -eat line 7.The enforcing seat cannot be husky.
check-chore-sync.mjsandmergeInheritance.mjshonour--no-verify, so hook-based guards are feedback, not authority. Authority is reusable CI plus required branch protection — owned by #17783.Install-time materialization of the tree is falsified.
npm ci --ignore-scriptsis already deliberate practice in three of our workflows —openapi-service-parity-lint.yml:72,ticket-archaeology-lint.yml:45,jsdoc-type-lint.yml:46— two carrying comments that it exists to skip the heavy postinstall. We haveprepare, notpostinstall, and--ignore-scriptsskips both. An install-time tree yields zero skills, silently, with no error.The Fix
Seed
neomjs/neo-agent-skillsand stand up B6 + B3:AGENT_SUBSTRATE_REVISIONreceipt — one immutable canonical commit/tree covering the skill tree, the manifest, and the public facts schema/renderer/public-common clauses. It excludes the internal maintainer constitution, which keeps its own revision authority in the D#17644 / Brain substrate.Contract Ledger Matrix
AGENT_SUBSTRATE_REVISIONreceipt filelearn/agentos/ADR.agents/skills/**in enrolled reposdevindex8-hunk divergence is the red control.claude/skills/)skills.manifest.jsonclaudeSymlinkRequiredobserved, lint-enforcedRepoContextDecision Record
Required: ADR — amend ADR 0040 §2.7 + new ADR for the distribution contract(preserved from D#17756's graduation classification).Decision Record impact
amends ADR 0040— §2.7's separation principle is confirmed; its boundary description needs the rendered-contributor-file / projected-constitution split. A new ADR records the distribution contract itself. The amendment lands with this work, not after it.Discussion Criteria Mapping
Acceptance Criteria
neomjs/neo-agent-skillscarries the canonical tree (38 skills + manifest + schema) and the public facts schema/renderer, on a first commit that matches this contract.AGENT_SUBSTRATE_REVISIONreceipt exists in each enrolled repo, pinning one immutable canonical tree; the internal maintainer constitution is provably absent from what the receipt covers. Merge-order constraint (2026-08-26): enrolled repos are the registry's rows, so this AC completes only when neomjs/devindex#6 and neomjs/neo-agent-brain#5 land. Both are green. They must merge before the neomjs/neo PR that closes this ticket, or the close fires against an unmet AC.devindex's current divergence must go red, demonstrated, not asserted.skills.manifest.json; a manifest-declared opt-out is absent from the generated façade, proven by a test, while an included skill is present. The current committed links are preserved unchanged in wave one.AC-7 — enforcement binds via reusable CI + required branch protection, citing #17783's binding receipt.MOVED TO #17783 (2026-08-26). Honest amendment rather than a residual carried by PR prose: the branch-protection half requires repository admin, and every maintainer seat holdsmaintain—GET /branches/dev/protectionreturns 404 for us. An AC no assignee can execute does not belong on an implementation ticket. The reusable-CI half is delivered here (always-emitted, least-privileged,workflow_call); the binding is #17783's enforcement-custody scope, where the receipt it cites already lives.revalidationTrigger) — on reactivation ofgeminiorkimi(participationStatus→activeinai/graph/identityRoots.mjs), this contract is re-presented for retroactive signal before being treated as settled.Out of Scope
core.symlinks=falsefaçade replacement — its own ticket, behind an explicit cross-platform AC. Wave one preserves today's proven façade.Avoided Traps
--ignore-scriptsis our own practice and silently yields zero skills.--no-verifymakes it feedback, not authority.Related
#17500 (parent epic) · #17783 (enforcement custody) · D#17756 (origin) · D#17644 (seat/session layer) · D#17782 (split runway) · ADR 0040
Origin Session ID: 10411e26-a3db-4f3d-b6bd-69e09045b804
Retrieval Hint:
query_raw_memories("AGENT_SUBSTRATE_REVISION receipt promotion epochs ignore-scripts falsified")·query_summaries("D#17756 skills distribution graduation")