Context
Operator flagged (2026-06-04): learn/agentos/ is public-facing docs (rendered in the portal learn-viewer), but the swarm increasingly pollutes it with exploration/audit/plan artifacts = technical debt. Operator boundary: agentos/ top-level guides + decisions/ + cloud-deployment/ are public; exploration/ledger/audit items are not, and should not be top-level. "Small ticket, but prevent recurrence."
The Problem
learn/tree.json is the publish-gate for the public portal learn-viewer (Portal.view.learn → ContentStore → tree.json). V-B-A of the AgentOS deck found two failure modes:
- Exploration registered as published guides (in
tree.json → rendered in public nav next to real guides): SkillCompressionRolloutPlan, ConfigSubstrateDeadConfigAudit, ConfigSubstrateEnvVarAudit.
- Real guides wrongly unpublished (the inverse bug):
AiConfigModel (ADR 0019 line 128 literally names it "the public configuration-model guide"), MX, rem-state-model are unpublished orphans.
(50% of top-level — 14/28 .md — are unpublished orphans; the broader orphan-dump cleanup is split to a follow-up, see Out of Scope.)
The Architectural Reality
learn/tree.json flat adjacency list drives portal nav + SEO; ai/scripts/lint/lint-tree-json.mjs already enforces tree↔folder mirroring (LEAF_FILE / PARENT_INTEGRITY / GROUP_COHESION / FOLDER_UNIQUENESS). The recurrence guard belongs here as a fifth invariant.
learn/agentos/cloud-deployment/Configuration.md:134 load-bearingly links ../ConfigSubstrateEnvVarAudit.md — so that audit cannot be deleted without de-linking first.
The Fix (this PR)
- De-publish (remove
tree.json leaves): SkillCompressionRolloutPlan, ConfigSubstrateDeadConfigAudit, ConfigSubstrateEnvVarAudit.
- Delete files (no inbound refs; content lives in owning tickets —
SkillCompressionRolloutPlan → #11605/#12496): SkillCompressionRolloutPlan.md, ConfigSubstrateDeadConfigAudit.md. Keep ConfigSubstrateEnvVarAudit.md on disk (referenced by Configuration.md; final disposition deferred) + de-link Configuration.md's portal link to it (convert to plain text so no broken portal nav).
- Publish (add
tree.json leaves under AgentOS): AiConfigModel, MX, rem-state-model.
- Guard — new
lint-tree-json.mjs invariant EXPLORATION_ARTIFACT: a tree.json leaf id whose basename matches exploration-artifact patterns (*Audit, *RolloutPlan/*Plan, *Sweep, *Census, *Forensics, *Benchmark) is rejected — those belong in a non-published subfolder or the owning ticket, never the public nav. + unit test.
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
lint-tree-json.mjs EXPLORATION_ARTIFACT invariant |
this ticket (operator 2026-06-04) |
reject tree.json leaves whose basename matches exploration-artifact naming patterns |
none — fail-build |
yes (lint JSDoc) |
unit test (positive + negative); node ai/scripts/lint/lint-tree-json.mjs green post-cleanup |
learn/tree.json AgentOS nav |
operator boundary |
de-publish exploration artifacts; publish the mis-filed guides |
— |
yes |
lint-tree-json green |
Acceptance Criteria
Out of Scope (follow-up tickets)
- Orphan-dump cleanup: the remaining ~11 top-level orphans (
ModelStats, Tier2RevalidationSweep, v13-path, gemma4-rem-benchmark, sandman-*, IdentitySchema) + a stricter NO_TOP_LEVEL_ORPHAN guard (every depth-1 *.md must be registered).
- Methodology docs → new
agentos/process/ subfolder (contract-ledger, evidence-ladder, reference-hygiene, AGENTS_ATLAS) + skill-pointer + #12497 reference-integrity ref updates.
ConfigSubstrateEnvVarAudit final disposition (keep-as-reference vs absorb into Configuration.md) + add *Audit follow-up if relocated.
measurements/ de-publish decision (internal baselines vs MX-transparency curation).
Related
Authority: operator boundary 2026-06-04; ADR 0019 (AiConfigModel is the public config guide). Consumer: apps/portal/view/learn/MainContainerStateProvider.mjs.
Origin Session ID: c2800781-b204-4883-a52f-2979a560718b
Context
Operator flagged (2026-06-04):
learn/agentos/is public-facing docs (rendered in the portal learn-viewer), but the swarm increasingly pollutes it with exploration/audit/plan artifacts = technical debt. Operator boundary:agentos/top-level guides +decisions/+cloud-deployment/are public; exploration/ledger/audit items are not, and should not be top-level. "Small ticket, but prevent recurrence."The Problem
learn/tree.jsonis the publish-gate for the public portal learn-viewer (Portal.view.learn→ContentStore→tree.json). V-B-A of the AgentOS deck found two failure modes:tree.json→ rendered in public nav next to real guides):SkillCompressionRolloutPlan,ConfigSubstrateDeadConfigAudit,ConfigSubstrateEnvVarAudit.AiConfigModel(ADR 0019 line 128 literally names it "the public configuration-model guide"),MX,rem-state-modelare unpublished orphans.(50% of top-level — 14/28
.md— are unpublished orphans; the broader orphan-dump cleanup is split to a follow-up, see Out of Scope.)The Architectural Reality
learn/tree.jsonflat adjacency list drives portal nav + SEO;ai/scripts/lint/lint-tree-json.mjsalready enforces tree↔folder mirroring (LEAF_FILE / PARENT_INTEGRITY / GROUP_COHESION / FOLDER_UNIQUENESS). The recurrence guard belongs here as a fifth invariant.learn/agentos/cloud-deployment/Configuration.md:134load-bearingly links../ConfigSubstrateEnvVarAudit.md— so that audit cannot be deleted without de-linking first.The Fix (this PR)
tree.jsonleaves):SkillCompressionRolloutPlan,ConfigSubstrateDeadConfigAudit,ConfigSubstrateEnvVarAudit.SkillCompressionRolloutPlan→ #11605/#12496):SkillCompressionRolloutPlan.md,ConfigSubstrateDeadConfigAudit.md. KeepConfigSubstrateEnvVarAudit.mdon disk (referenced byConfiguration.md; final disposition deferred) + de-linkConfiguration.md's portal link to it (convert to plain text so no broken portal nav).tree.jsonleaves under AgentOS):AiConfigModel,MX,rem-state-model.lint-tree-json.mjsinvariantEXPLORATION_ARTIFACT: atree.jsonleafidwhose basename matches exploration-artifact patterns (*Audit,*RolloutPlan/*Plan,*Sweep,*Census,*Forensics,*Benchmark) is rejected — those belong in a non-published subfolder or the owning ticket, never the public nav. + unit test.Contract Ledger
lint-tree-json.mjsEXPLORATION_ARTIFACTinvarianttree.jsonleaves whose basename matches exploration-artifact naming patternsnode ai/scripts/lint/lint-tree-json.mjsgreen post-cleanuplearn/tree.jsonAgentOS navlint-tree-jsongreenAcceptance Criteria
SkillCompressionRolloutPlan+ bothConfigSubstrate*Auditremoved fromtree.jsonnav.SkillCompressionRolloutPlan.md+ConfigSubstrateDeadConfigAudit.mddeleted (V-B-A'd: no inbound refs).Configuration.mdno longer hard-links the unpublishedConfigSubstrateEnvVarAudit.md(no broken portal link).AiConfigModel,MX,rem-state-modelpublished intree.json.lint-tree-json.mjsrejects exploration-artifact basenames intree.json+ unit test (positive + negative) passes.node ai/scripts/lint/lint-tree-json.mjsgreen; existing tree-json unit tests green.Out of Scope (follow-up tickets)
ModelStats,Tier2RevalidationSweep,v13-path,gemma4-rem-benchmark,sandman-*,IdentitySchema) + a stricterNO_TOP_LEVEL_ORPHANguard (every depth-1*.mdmust be registered).agentos/process/subfolder (contract-ledger,evidence-ladder,reference-hygiene,AGENTS_ATLAS) + skill-pointer + #12497 reference-integrity ref updates.ConfigSubstrateEnvVarAuditfinal disposition (keep-as-reference vs absorb intoConfiguration.md) + add*Auditfollow-up if relocated.measurements/de-publish decision (internal baselines vs MX-transparency curation).Related
Authority: operator boundary 2026-06-04; ADR 0019 (
AiConfigModelis the public config guide). Consumer:apps/portal/view/learn/MainContainerStateProvider.mjs.Origin Session ID: c2800781-b204-4883-a52f-2979a560718b