From f07b40a3effce155b7ee74230d28c35111171de8 Mon Sep 17 00:00:00 2001 From: Darian Ngo Date: Wed, 29 Jul 2026 18:22:37 -0500 Subject: [PATCH 1/2] The tier budget gets a reader, and the band gains a floor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `tier_budget_words` occurred exactly once in this repository — its own declaration in `index.json` — so the map drifted to tiers nine times the stated figure while every gate stayed green. A declared constant with no reader is a comment. `extractTiers` and `tierBudgetIssues` are pure and exported. `--budget` reports per-tier and exits 1 on breach. `--verify` now reads the budget unconditionally and gates on it only when `tier_budget_enforced` is true. It ships false: all thirteen classes breached when this landed, and a gate that reddens CI on day one is a gate someone switches off — the same reasoning that keeps staleness out of `--verify`. Three clauses, and the second is the one usually left out. Every tier inside its band; the band carries a FLOOR as well as a ceiling, because a tier under budget was never compressed and compression is the mechanism the method rests on; and the last tier is not longer than the first, since the source study's own chain lands step 1 and step 5 at an identical 72 tokens. The counting convention lives in code rather than in the caller: three readers counting one tier by eye returned 799, 803 and 844 words for the same bytes. First run over the shipped map: 49 breaches — 31 under the floor, 14 over the ceiling, 4 chains ending longer than they start. The under-floor majority is the opposite of what the document's reputation suggested. Watched failing before being trusted. The floor clause was deleted and `--negative-control` reported BROKEN at exit 1; `tier_budget_enforced` was set true and `--verify` failed with 49 issues at exit 1. Both restored. The control now plants thirty-two conditions and exits 3; the unit suite is 53 tests. That count is repaired in every sentence stating it. --- docs/density-chain/README.md | 11 +- docs/density-chain/index.json | 2 + tools/density-chain/wiki_check.mjs | 191 ++++++++++++++++++++++++- tools/density-chain/wiki_check.test.ts | 85 ++++++++++- 4 files changed, 282 insertions(+), 7 deletions(-) diff --git a/docs/density-chain/README.md b/docs/density-chain/README.md index 83ee8f7..f22bedc 100644 --- a/docs/density-chain/README.md +++ b/docs/density-chain/README.md @@ -36,9 +36,11 @@ record, adopted doctrine, and design record. 1. **Trunk first.** T0 (a sentence), T1 (a paragraph), T2 (the class map). Under 500 words. 2. **Then one branch.** Each is complete at every tier: T1 is true on its own terms, and deeper tiers *add* rather than *correct* (the layer test). Stop at the first tier that answers you. -3. **Watch the status labels.** `shipped-pinned` ≠ `implemented, not accepted` ≠ `ratified as - principle (no build)` ≠ `proposed` ≠ `rolled back`. Blurring them is the failure this house keeps - paying for. +3. **Watch the status labels.** `shipped-pinned` (committed code plus a passing drill) ≠ + `implemented, not accepted` ≠ `adopted / ratified-as-principle (no build)` ≠ `proposed / + design-record` ≠ `recorded-research` ≠ `rolled back / retired`. Six members, and the same six the + map's reading contract and the density-chain skill declare — a taxonomy enumerated two ways is one + nobody can check against. Blurring them is the failure this house keeps paying for. 4. **Read the reachability lines.** Hard rule 15 — *correct is not the same claim as reachable*. Every branch names what has no non-test caller. Those are findings, not accusations. 5. **Every number is as recorded, never re-run.** A scripted zero-paid harness's counters belong to the @@ -66,7 +68,8 @@ implicated. | `npm run wiki:check -- --emit-class-map` | the derived routing table, for review — never committed | | `npm run wiki:check -- --print-sections` | each branch section's line range and normalized hash | | `npm run wiki:check -- --json` / `-- --list-classes` | the report as JSON / the roster | -| `npm run wiki:check -- --negative-control` | the falsifier. Plants **twenty-five** conditions the gate must detect; **healthy is exit 3**, matching [`check:repo-surface`](../../tools/repository-surface/cli.ts) and the judge drills | +| `npm run wiki:check -- --budget` | the tier-length gate alone: every tier inside the declared band, and no class ending longer than it starts. Exit **0** clean, **1** on breach — independent of whether `--verify` gates on it | +| `npm run wiki:check -- --negative-control` | the falsifier. Plants **thirty-two** conditions the gate must detect; **healthy is exit 3**, matching [`check:repo-surface`](../../tools/repository-surface/cli.ts) and the judge drills | **The split is deliberate.** `--verify` runs in CI because its invariants hold at any history depth — and CI checks out shallow, so the staleness diff would silently see nothing there. Staleness diff --git a/docs/density-chain/index.json b/docs/density-chain/index.json index 362baae..ff37b98 100644 --- a/docs/density-chain/index.json +++ b/docs/density-chain/index.json @@ -17,6 +17,8 @@ "commit_count_first_parent": 157, "commit_count_all": 216, "tier_budget_words": 90, + "tier_budget_tolerance": 0.05, + "tier_budget_enforced": false, "tier_count": 5, "structure": "trunk (T0-T2) + 13 subsystem-class branches + cross-link lattice + self-index + constellation", "method": "Adams et al. 2023, arXiv:2309.04269 (chain of density), system mode: fixed tier length, one chain per subsystem class", diff --git a/tools/density-chain/wiki_check.mjs b/tools/density-chain/wiki_check.mjs index 2d226e3..4873e07 100644 --- a/tools/density-chain/wiki_check.mjs +++ b/tools/density-chain/wiki_check.mjs @@ -194,6 +194,88 @@ function extractRoster(text) { return roster; } +/** + * Split each `#### C{n}` section into its `- **T{k} — label.**` tier bullets. + * + * A tier runs from its own bullet to the next tier bullet, the first `*Status + * ledger:*`-style italic footer, or the next heading — whichever comes first. + * + * The counting convention is fixed HERE rather than left to the caller, and + * that is the whole point of this function. Three separate readers counting + * one tier by eye returned 799, 803 and 844 words for the same bytes, because + * each made a different call on the bullet label and on code spans. A budget + * measured three ways is not a budget. The convention: drop the + * `- **T{k} — label.**` prefix, then count whitespace-separated tokens on what + * remains. Markdown punctuation counts as part of the token it is attached to, + * which is what a human counting words does. + */ +function extractTiers(text) { + const out = new Map(); + if (text === null) return out; + const lines = text.split(/\r?\n/); + const isTier = (l) => /^-\s+\*\*(T\d)\s*[—-]/.exec(l); + const closes = (l) => /^\*\S/.test(l) || /^#{1,4}\s/.test(l) || isTier(l); + let cls = null; + for (let i = 0; i < lines.length; i += 1) { + const heading = /^#{4}\s+(C\d{1,2})(?=\s|$)/.exec(lines[i]); + if (heading) { + cls = heading[1]; + if (!out.has(cls)) out.set(cls, []); + continue; + } + if (cls === null) continue; + const t = isTier(lines[i]); + if (!t) continue; + const body = [lines[i].replace(/^-\s+\*\*T\d\s*[—-][^*]*\*\*/, '')]; + for (let j = i + 1; j < lines.length && !closes(lines[j]); j += 1) body.push(lines[j]); + out.get(cls).push({ + tier: t[1], + startLine: i + 1, + words: body.join(' ').split(/\s+/).filter(Boolean).length, + }); + } + return out; +} + +/** + * The three clauses that make a declared tier budget mean something, as pure + * predicates over already-counted tiers so the suite can drive them without a + * repository. + * + * Clause 2 is the one that is easy to leave out and is load-bearing. A ceiling + * with no floor is satisfiable by a tier that never approaches the budget, and + * a tier under its budget has no compression pressure on it at all — which is + * the forcing function the whole method rests on (Adams et al. 2023, + * arXiv:2309.04269 §2). Clause 3 exists because the source study's own chain + * lands step 1 and step 5 at an identical 72 tokens; endpoints that are not + * length-matched make a density claim across them unreadable. + */ +function tierBudgetIssues({ tiers, budget, tolerance, tierCount }) { + const issues = []; + if (!Number.isInteger(budget) || budget <= 0) { + issues.push(`tier_budget_words must be a positive integer, got ${JSON.stringify(budget)}`); + return issues; + } + const lo = Math.floor(budget * (1 - tolerance)); + const hi = Math.ceil(budget * (1 + tolerance)); + for (const [id, list] of tiers) { + if (Number.isInteger(tierCount) && list.length !== tierCount) { + issues.push(`${id}: ${list.length} tier(s), expected ${tierCount}`); + continue; + } + for (const t of list) { + if (t.words > hi) issues.push(`${id} ${t.tier}: ${t.words} words over ceiling ${hi} (line ${t.startLine})`); + else if (t.words < lo) issues.push(`${id} ${t.tier}: ${t.words} words under floor ${lo} (line ${t.startLine})`); + } + const first = list[0]; + const last = list[list.length - 1]; + if (first && last && last !== first && last.words > first.words) { + issues.push(`${id}: ${last.tier} (${last.words}w) is longer than ${first.tier} (${first.words}w) — densest tier must not be the longest`); + } + } + return issues; +} + /** * Parse the self-index table's `Declares` column. Only backticked spans are * read, so the prose around a glob is ignored by construction; `*(none)*` @@ -712,6 +794,7 @@ function formatScriptProblem(problem, label = RENDER_PATH) { function runVerify() { const mapText = readMapText(); const problems = []; + let budgetSummary = { enforced: false, issues: [] }; let router; try { router = buildRouter(mapText); @@ -762,6 +845,27 @@ function runVerify() { if (dead in b) problems.push(`${b.id}: stale field \`${dead}\` — verification is derived from git, not stored`); } } + // The budget field is READ here, which is the point. Before this, + // `tier_budget_words` occurred exactly once in the repository — its own + // declaration — so the map could and did drift to tiers nine times the + // stated figure while every gate stayed green. A declared constant with no + // reader is a comment. + // + // Reading it always, gating on it only when `tier_budget_enforced` is true: + // the branches as shipped violate the band, and a gate that reddens CI on + // day one is a gate someone switches off (the same reasoning that keeps + // staleness out of `--verify`). The measurement is unconditional so the + // drift is visible; the flag is the operator's, and flipping it is a + // behaviour change to put to the collaborator rather than to assume. + const cfg = index.notes?.[0] ?? {}; + const budgetIssues = tierBudgetIssues({ + tiers: extractTiers(mapText), + budget: cfg.tier_budget_words, + tolerance: typeof cfg.tier_budget_tolerance === 'number' ? cfg.tier_budget_tolerance : 0.05, + tierCount: cfg.tier_count, + }); + budgetSummary = { enforced: cfg.tier_budget_enforced === true, issues: budgetIssues }; + if (budgetSummary.enforced) problems.push(...budgetIssues); } if ([...router.declarations.keys()].join(',') !== router.roster.join(',')) { problems.push('self-index roster ≠ map headings'); @@ -790,8 +894,53 @@ function runVerify() { `density-trellis contract: PASS (${visible.length} paths routed; ${router.roster.length} branch classes, ` + `roster agrees three ways; ${router.declared.length} declared globs, ` + `${(router.residue.heuristic ?? []).length} heuristics, ${(router.residue.fallback ?? []).length} fallbacks; ` + - `no stored pins; ${scripts.checked.length} inline script block(s) in the render compile)\n`, + `no stored pins; ${scripts.checked.length} inline script block(s) in the render compile; ` + + `tier budget ${budgetSummary.enforced ? 'enforced' : 'measured only'}, ${budgetSummary.issues.length} breach(es))\n`, ); + if (!budgetSummary.enforced && budgetSummary.issues.length) { + process.stdout.write( + ` tier budget: ${budgetSummary.issues.length} breach(es), not gating. ` + + `Run \`npm run wiki:check -- --budget\` for the per-tier table, or set ` + + `\`tier_budget_enforced: true\` in docs/density-chain/index.json to make these fail this check.\n`, + ); + } + return 0; +} + +/** + * `--budget`: the tier-length gate on its own. Exit 0 clean, 1 on any breach, + * regardless of `tier_budget_enforced` — the flag governs whether `--verify` + * fails, never whether the measurement runs. + */ +function runBudget() { + const mapText = readMapText(); + if (mapText === null) { + process.stderr.write(`${CHAIN_PATH} is missing\n`); + return 1; + } + const cfg = loadIndex()?.notes?.[0] ?? {}; + const tolerance = typeof cfg.tier_budget_tolerance === 'number' ? cfg.tier_budget_tolerance : 0.05; + const tiers = extractTiers(mapText); + const issues = tierBudgetIssues({ tiers, budget: cfg.tier_budget_words, tolerance, tierCount: cfg.tier_count }); + + const budget = cfg.tier_budget_words; + const lo = Math.floor(budget * (1 - tolerance)); + const hi = Math.ceil(budget * (1 + tolerance)); + process.stdout.write(`tier budget ${budget} words, band ${lo}-${hi} (±${Math.round(tolerance * 100)}%)\n\n`); + const cols = [...tiers.values()][0]?.map((t) => t.tier) ?? []; + process.stdout.write(`class ${cols.map((c) => c.padStart(6)).join('')} verdict\n`); + for (const [id, list] of tiers) { + const cells = list.map((t) => (t.words > hi || t.words < lo ? `${t.words}!` : `${t.words}`).padStart(6)).join(''); + const bad = list.some((t) => t.words > hi || t.words < lo) + || (list.length > 1 && list[list.length - 1].words > list[0].words); + process.stdout.write(`${id.padEnd(6)} ${cells} ${bad ? 'BREACH' : 'ok'}\n`); + } + if (issues.length) { + process.stdout.write(`\ntier budget: FAIL (${issues.length} breach(es))\n`); + for (const i of issues) process.stdout.write(`- ${i}\n`); + return 1; + } + process.stdout.write(`\ntier budget: PASS (${[...tiers.values()].flat().length} tiers within band; no class ends longer than it starts)\n`); return 0; } @@ -905,6 +1054,40 @@ function runNegativeControl() { planted.push('new_heading_extends_the_roster'); } + // The tier-budget gate. The positive control fires first: if the shipped map + // yields no tiers at all, every "we caught the breach" below is a check + // passing on an empty set. + const shippedTiers = extractTiers(mapText); + const shippedTierCount = [...shippedTiers.values()].flat().length; + if (shippedTiers.size > 0 && shippedTierCount === shippedTiers.size * 5) { + planted.push('shipped_map_yields_five_tiers_per_class'); + } + const bandCfg = { budget: 90, tolerance: 0.05, tierCount: 2 }; + const oneClass = (a, b) => new Map([['C1', [ + { tier: 'T1', startLine: 1, words: a }, { tier: 'T2', startLine: 2, words: b }, + ]]]); + if (tierBudgetIssues({ tiers: oneClass(90, 800), ...bandCfg }).some((s) => s.includes('over ceiling'))) { + planted.push('an_over_ceiling_tier_is_caught'); + } + // The clause a ceiling-only rule cannot have: a tier well UNDER budget has no + // compression pressure on it, which is the forcing function itself. + if (tierBudgetIssues({ tiers: oneClass(90, 20), ...bandCfg }).some((s) => s.includes('under floor'))) { + planted.push('an_under_floor_tier_is_caught'); + } + // Both endpoints inside the band, yet the chain ends longer than it starts. + if (tierBudgetIssues({ tiers: oneClass(86, 94), ...bandCfg }).some((s) => s.includes('longer than'))) { + planted.push('a_chain_ending_longer_than_it_starts_is_caught'); + } + if (tierBudgetIssues({ tiers: oneClass(90, 90), ...bandCfg }).length === 0) { + planted.push('a_held_budget_passes'); + } + if (tierBudgetIssues({ tiers: oneClass(90, 90), ...bandCfg, tierCount: 5 }).some((s) => s.includes('expected 5'))) { + planted.push('a_short_chain_is_caught'); + } + if (tierBudgetIssues({ tiers: oneClass(90, 90), ...bandCfg, budget: 0 }).some((s) => s.includes('positive integer'))) { + planted.push('a_missing_budget_is_caught'); + } + const sections = extractSections(mapText); if (sections.has('C5') && sections.has('C6')) planted.push('sections_extract_per_class'); if (extractSections(mapText.replace(/\n/g, '\r\n')).get('C5')?.sha256 === sections.get('C5')?.sha256) { @@ -999,6 +1182,9 @@ function runNegativeControl() { 'working_tree_section_edit_satisfies', 'uncommitted_code_change_is_stale', 'missing_section_is_orphaned', 'never_committed_branch_is_stale', 'shallow_clone_does_not_gate', 'no_unresolvable_pin_state_exists', + 'shipped_map_yields_five_tiers_per_class', 'an_over_ceiling_tier_is_caught', + 'an_under_floor_tier_is_caught', 'a_chain_ending_longer_than_it_starts_is_caught', + 'a_held_budget_passes', 'a_short_chain_is_caught', 'a_missing_budget_is_caught', ]; const missed = expected.filter((n) => !planted.includes(n)); if (missed.length) { @@ -1016,6 +1202,7 @@ function main() { if (argv.includes('--hook')) return hookMode(); if (argv.includes('--verify')) return runVerify(); if (argv.includes('--check-html')) return runCheckHtml(); + if (argv.includes('--budget')) return runBudget(); if (argv.includes('--negative-control')) return runNegativeControl(); if (argv.includes('--list-classes')) { @@ -1073,7 +1260,7 @@ if (invokedDirectly) { export { globToRegExp, expandBraces, specificity, - extractSections, extractRoster, extractDeclarations, + extractSections, extractRoster, extractDeclarations, extractTiers, tierBudgetIssues, buildRouter, route, classify, sectionVerdict, classVerdicts, lastCodeCommitByClass, report, extractScriptBlocks, findSyntaxError, checkHtmlScripts, formatScriptProblem, diff --git a/tools/density-chain/wiki_check.test.ts b/tools/density-chain/wiki_check.test.ts index 5b84948..4904094 100644 --- a/tools/density-chain/wiki_check.test.ts +++ b/tools/density-chain/wiki_check.test.ts @@ -9,8 +9,14 @@ import * as wiki from './wiki_check.mjs'; const { globToRegExp, expandBraces, extractSections, extractRoster, extractDeclarations, buildRouter, route, classify, sectionVerdict, - extractScriptBlocks, checkHtmlScripts, + extractScriptBlocks, checkHtmlScripts, extractTiers, tierBudgetIssues, } = wiki as { + extractTiers: (t: string | null) => Map; + tierBudgetIssues: (a: { + tiers: Map; + budget: unknown; tolerance: number; tierCount?: number; + }) => string[]; +} & { globToRegExp: (g: string) => RegExp; expandBraces: (g: string) => string[]; extractSections: (t: string | null) => Map; @@ -385,3 +391,80 @@ describe('residue hygiene', () => { } }); }); + +describe('tier extraction', () => { + const tiers = extractTiers(MAP_TEXT); + + it('finds every class in the roster', () => { + expect([...tiers.keys()]).toEqual(extractRoster(MAP_TEXT).map((r) => r.id)); + }); + + it('finds exactly five tiers per class', () => { + for (const [id, list] of tiers) expect(list.length, id).toBe(5); + }); + + it('labels them T1..T5 in order', () => { + for (const [id, list] of tiers) { + expect(list.map((t) => t.tier), id).toEqual(['T1', 'T2', 'T3', 'T4', 'T5']); + } + }); + + // The counting convention is the deliverable, not an implementation detail: + // three readers counting one tier by eye returned 799, 803 and 844. + it('counts a tier body without its bullet label', () => { + const one = extractTiers('#### C1 — x\n\n- **T1 — essence.** alpha beta gamma\n'); + expect(one.get('C1')?.[0].words).toBe(3); + }); + + it('stops a tier at the status footer, not at the end of the section', () => { + const one = extractTiers('#### C1 — x\n\n- **T1 — essence.** alpha beta\n\n*Status ledger:* delta epsilon zeta\n'); + expect(one.get('C1')?.[0].words).toBe(2); + }); + + it('spans continuation lines within one tier', () => { + const one = extractTiers('#### C1 — x\n\n- **T1 — essence.** alpha\n beta gamma\n'); + expect(one.get('C1')?.[0].words).toBe(3); + }); +}); + +describe('tier budget clauses', () => { + const cfg = { budget: 90, tolerance: 0.05, tierCount: 2 }; + const chain = (a: number, b: number) => new Map([['C1', [ + { tier: 'T1', startLine: 1, words: a }, { tier: 'T2', startLine: 2, words: b }, + ]]]); + + it('passes a held budget', () => { + expect(tierBudgetIssues({ tiers: chain(90, 90), ...cfg })).toEqual([]); + }); + + it('catches a tier over the ceiling', () => { + expect(tierBudgetIssues({ tiers: chain(90, 800), ...cfg }).join()).toContain('over ceiling'); + }); + + // A ceiling-only rule passes this, and a tier under budget has no + // compression pressure on it — which is the mechanism the budget exists for. + it('catches a tier under the floor', () => { + expect(tierBudgetIssues({ tiers: chain(90, 20), ...cfg }).join()).toContain('under floor'); + }); + + it('catches a chain ending longer than it starts, both ends in band', () => { + const issues = tierBudgetIssues({ tiers: chain(86, 94), ...cfg }); + expect(issues.join()).toContain('longer than'); + expect(issues.join()).not.toContain('ceiling'); + }); + + it('allows a chain ending shorter than it starts', () => { + expect(tierBudgetIssues({ tiers: chain(94, 86), ...cfg })).toEqual([]); + }); + + it('catches a short chain', () => { + expect(tierBudgetIssues({ tiers: chain(90, 90), ...cfg, tierCount: 5 }).join()).toContain('expected 5'); + }); + + it('refuses a budget that is absent or not a positive integer', () => { + for (const budget of [undefined, 0, -1, '90', 90.5]) { + expect(tierBudgetIssues({ tiers: chain(90, 90), ...cfg, budget }).join(), String(budget)) + .toContain('positive integer'); + } + }); +}); From aa24d03f4d39a6d8db3a6bea1baedee2d9a011f5 Mon Sep 17 00:00:00 2001 From: Darian Ngo Date: Wed, 29 Jul 2026 18:22:56 -0500 Subject: [PATCH 2/2] Ten branch sections agree with the code again; the skill names who reads a note MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ten of thirteen classes were stale. One read-only sub-agent per class returned a densified replacement against its own declared paths, each claim carrying a commit, a path and line, or a command's output; every return was verified by re-running those commands before it was applied. The sections land beside the code they describe, which is what keeps them current. What the pass found, beyond currency: Three commit hashes offered as receipts resolve to nothing. C5 diagnosed the cause — a pre-squash hash never survives into the history a later reader searches, and this repository squashes. The convention needs a fix, not the three hashes. C12's own status ledger contradicted the cross-section table on whether a launch path exists. The code settles it for the table: `boot` gates on `preflight()` and claims a real VMM rather than raising, and `session_host.open_workspace_session` and `KataREPL.setup` both call it. The remaining gap is narrower and locatable — `install_scaffold` and `control` still raise, so no `GuestSupervisor` has run inside a microVM. Still not a sandbox, now for a checkable reason. That section went 2,020 words to 468. The map understated the system about as often as it overstated it. Node- level `contested` was recorded as having no consumer; the resolution pool and the self-edit pre-check both read it. The judge layer was described as near test-only; five operator entry points drive it through four runner scripts. One label rose on located code plus a passing drill. `judge_spawn.ts`'s `makeLiveJudge` was recorded as able only to refuse. It refuses on model-identity mismatch and otherwise calls `chat.completions.create`; what holds spend is the runner's `--live` plus `--confirm-paid` and the paid queue's owner hold. `MODEL_BACKEND_SEAM.md` cites construction sites at lines 353 and 589 that now sit at 424 and 737 — a record quoted verbatim into paid runs. Every section now holds the 85-95 band with its last tier no longer than its first. Repository-wide breaches: 49 to 14, the remainder in C1, C2 and C13, which were never stale and are separate work. The density-chain skill states who a note is for — human, AI and agentic readers — and derives three rules from the third, which had been standing as assertions. Its evidence base is corrected where it was wrong: the source study never compared a densified summary against an ordinary one, and no annotator saw the two side by side. The status taxonomy is stated once, six members, in the skill, the map's reading contract and the folder README alike. --- .claude/skills/density-chain/SKILL.md | 354 ++++++---- docs/density-chain/DENSITY-CHAIN.md | 920 ++++++++++++-------------- 2 files changed, 662 insertions(+), 612 deletions(-) diff --git a/.claude/skills/density-chain/SKILL.md b/.claude/skills/density-chain/SKILL.md index 6f341a8..ad35384 100644 --- a/.claude/skills/density-chain/SKILL.md +++ b/.claude/skills/density-chain/SKILL.md @@ -1,162 +1,260 @@ --- name: density-chain -description: Write an OpenCnid five-tier chain-of-density note for a research paper, or scaffold a complete new paper repo around one. Use whenever the user asks to add, summarize, note, recognize, or "make a repo for" a research paper (arXiv, ACL Anthology, a lab blog post — any published research), mentions a density chain, CoD note, tier note, paper note, or the OpenCnid paper-repo collection — even if they never name this skill. Also use when updating, re-verifying, or extending existing OpenCnid paper repos, including batch runs across many paper repos at once. Also runs in SYSTEM MODE — a chain-of-density map of a whole codebase or system rather than a paper — a branching "density-trellis" reverse-engineered from the project's commit history, written to docs/density-chain/DENSITY-CHAIN.md with an interactive HTML+SVG render. Use system mode when the user asks to map, summarize at increasing density, or make a density-chain / density-trellis of a project, engine, codebase, or its features and roadmap. +description: Write an OpenCnid three-tier chain-of-density note for a research paper, or scaffold a complete new paper repo around one. Use whenever the user asks to add, summarize, note, recognize, or "make a repo for" a research paper (arXiv, ACL Anthology, a lab blog post — any published research), mentions a density chain, CoD note, tier note, paper note, or the OpenCnid paper-repo collection — even if they never name this skill. Also use when updating, re-verifying, or extending existing OpenCnid paper repos, including batch runs across many paper repos at once. Also runs in SYSTEM MODE — a chain-of-density map of a whole codebase or system rather than a paper — a branching "density-trellis" reverse-engineered from the project's commit history, written to docs/density-chain/DENSITY-CHAIN.md with an interactive HTML+SVG render. Use system mode when the user asks to map, summarize at increasing density, or make a density-chain / density-trellis of a project, engine, codebase, or its features and roadmap. --- # density-chain -Produce OpenCnid's house artifact: a five-tier chain-of-density note on a research +Produce OpenCnid's house artifact: a three-tier chain-of-density note on a research paper, verified against the source, living in a repo named after the paper. +## Who reads a note + +This skill prepares summaries optimized for human, AI, and agentic readers. The +last of those shapes most of the rules below, and it is the reader a later +session forgets, because the study the method comes from measured only humans. + +An agent arrives with a context budget rather than an attention span. It +retrieves one tier instead of skimming the chain, and it treats the tier it +retrieved as complete — there is no glance upward to catch what went missing on +the way down. Three rules follow from that, and this is where they come from: + +- **Every tier is true standing alone.** The layer test is not tidiness. A + reader that stops at T1 acts on T1. +- **A dropped qualifier is a changed claim.** A person often recovers it from + context. An agent carries it forward as fact. +- **A locator is the only handle a reader has on you.** An agent cannot glance + at the figure and notice a number looks wrong; it can only follow the address. + ## Why the rules are shaped this way -Three findings from the method's paper (Adams et al. 2023, arXiv:2309.04269) drive -everything below: +Four findings from the method's own paper (Adams et al. 2023, arXiv:2309.04269) +drive everything below, so keep them in mind rather than following steps blindly: -- **Fixed length is the engine.** Without a held word budget, "add detail" makes a - summary longer, never denser. Rewrite every tier *at the same length*, never append. -- **The best tier is not the densest.** Human preference peaked mid-chain (median - step 3), and annotators barely agreed (Fleiss' κ = 0.112). Ship all five tiers and - let the reader pick — never just T5. -- **The collection is ground truth only because the source always wins.** Pin the - exact version studied, record the verification date, and if note and paper disagree, - fix the note. Authority runs paper → note → inspirations entry, one direction only. +- **Fixed length is the engine, and it binds on both sides.** Without a held word + budget, "add detail" makes a summary longer, never denser. Every tier is + rewritten *at the same length* — inside ±5%, not appended to. A **floor** + carries as much weight as a ceiling: a tier sitting under budget was never + compressed, and compression is the mechanism. The last tier is never longer + than the first. +- **The best tier is not the densest, and three is enough.** Human preference + peaked mid-chain (median step 3, expected 3.06), and marginal density collapses + right after it — step 4 buys under a quarter of what step 2 buys. That is why + we ship **T1–T3** and let the reader pick, never just the densest. The paper ran + five steps in order to *find* the peak; we already know where it is. + (Annotators barely agreed, κ = 0.112. Draw nothing from that number in either + direction — it is as consistent with the summaries being hard to tell apart as + with taste differing. The tiers rest on something simpler: a reader arrives + with a budget, and three densities serve three budgets.) +- **The paper never tested CoD against an ordinary prompt.** No annotator in that + study saw a chain-of-density summary beside a vanilla-prompt summary — every + comparison was between steps of one chain. Never write, or imply, that CoD + summarizes better than plain summarization. That trial does not exist. +- **The collection is only ground truth because the source always wins.** Pin + the exact version studied, record the verification date, and if note and paper + ever disagree, fix the note. Authority runs paper → note → inspirations + entry, one direction only. ## Study the framework first -These two documents are the canonical spec; study them before writing (this file is -only the field guide): +Study these two documents before writing anything; they are the canonical spec +and this file is only the field guide: -1. `METHOD.md` — the rules that don't bend, plus the document template (frontmatter, - tiers, entity ledger, key results, our take, provenance). -2. `chain-of-density-synthesis-prompt.md` — the full authoring framework: evidence-unit - extraction, map/reduce for long papers, the audit rubric that selects candidates - (never "densest wins"). +1. `METHOD.md` — the rules that don't bend, plus the document template + (frontmatter, tiers, entity ledger, key results, our take, provenance). +2. `chain-of-density-synthesis-prompt.md` — the full authoring framework: + evidence-unit extraction, map/reduce for long papers, the audit rubric that + selects candidates (never "densest wins"). -Find them, in order of preference: the repo root if you are inside the chain-of-density -repo; the local clone at `D:\chain-of-density\`; or raw from GitHub at -`https://raw.githubusercontent.com/OpenCnid/chain-of-density/main/METHOD.md` (same -pattern for the synthesis prompt). +Where to find them, in order of preference: the repo root if you are inside the +chain-of-density repo; the local clone at `D:\chain-of-density\`; or raw from +GitHub at +`https://raw.githubusercontent.com/OpenCnid/chain-of-density/main/METHOD.md` +(same pattern for the synthesis prompt). ## The pipeline -1. **Fetch and verify — never write from memory.** Research arrives in two shapes: - - **Papers** (arXiv, ACL Anthology, DOI journals): download the PDF into the session - scratchpad and study it there, and/or pull the ar5iv/arXiv HTML rendering; check - the abs page for license, version number, and date. Pin the exact version (vN). - Locators: § section, Table N, Figure N. - - **Lab articles** (Anthropic research and Transformer Circuits, OpenAI research/blog, - DeepMind, and other labs' posts): study the article at its canonical URL. Articles - have no vN, so the pin is the publication date plus the URL, with the access date - recorded. Locators: section headings and figure names — no page numbers. - Either way, downloads are session study material — scratchpad only. A repo receives the - *note* plus a one-command fetch (curl the arXiv PDF; for articles with no PDF, link the - canonical URL — same principle, the source serves its own copy). Study every number, - author affiliation, and claim at the source this session with a locator, and record in - provenance which rendering the locators follow. A quantity you "remember" is a quantity - you don't write. -2. **Write the note as `density-chain.md`.** Follow METHOD.md's template exactly: pinned - frontmatter, a declared tier word budget held constant, T1–T5, entity ledger with - tier-introduced + locator per entity, a key results table of exact values, *our take* - quarantined at the bottom, and a provenance section noting which rendering the locators - follow. -3. **Index it.** Add or update `index.json` (schema: the chain-of-density repo's copy). - Trellis consumes these; a note without an index entry is invisible to the staleness - machinery. -4. **New paper? New repo, named after the paper's most searchable handle.** Kebab-case the - method name, acronym, or title hook the community uses (`chain-of-density`, - `lost-in-the-middle`, `pcf-adaptive-agents`). Be creative when the full title is - unwieldy — an acronym plus a domain keyword often beats a truncated title — because full - discoverability is recovered through the description and topics (step 6): the name - catches the eye, the metadata catches the search. Scaffold: `density-chain.md`, - `index.json`, `README.md`, `AGENTS.md` (how agents consume and maintain the note — - mirror the canonical one in chain-of-density), `LICENSE.md` (CC BY 4.0 for prose), and a - *link* to chain-of-density for METHOD.md and the synthesis prompt — never a copy (one - canonical home, no drift). -5. **README in house style.** Load the `prompt-engineering` and `hypershot-protocol` skills - first — README furniture and templates prime future generation, so author them under - those protocols. Use the chain-of-density repo's README as the living template. Required - furniture: a theme-neutral animated SVG banner (mid-tone palette #58a6ff→#9b8cf7→#ef6fd0, - mono type), shields badges including joke badges that state real guarantees, the - one-way-rule alert, a "standing on the shoulders of giants" section naming the authors - with affiliations *as printed on the paper*, a "want the PDF? one command, straight from - the source" section (curl from arXiv — we never host papers), a "cite the humans, not us" - section carrying the official BibTeX — fetch it from the ACL Anthology `.bib` endpoint, - arXiv's `/bibtex/` export, or the article's own "cite this" block; when a lab article - offers none, build an `@misc` entry from metadata verified on the page (title, authors, - publisher, URL, dates) — verified fields, never memory — honest notes including the - human+AI co-authorship disclosure, references, and a footer joke. Voice: high-level, fun, - educational; wry parentheticals, no marketing. -6. **Make it findable: description and topics.** The repo description carries the search - terms the name can't — full paper title, first author, year, and the arXiv ID or source - lab. Then add topics with `gh repo edit --add-topic`: the method name and acronym, three - to six domain keywords, the source tag (`arxiv`, or the lab's name for articles), plus - the house tags `research-notes` and `chain-of-density`. Topics are GitHub's search index - — this is where the SEO lives, which frees the repo name to be memorable. -7. **Humor placement.** READMEs and *our take* only. The tiers, key results, and provenance - stay bone-dry — they are ground truth, and jokes in ground truth age like milk. -8. **Inspirations entry — only with a receipt.** If the paper demonstrably shaped OpenCnid - work (a commit, design doc, or shipped feature you can link), add an entry to - [llm-research-inspirations](https://github.com/OpenCnid/llm-research-inspirations) in its - entry-format frame. No receipt, no entry — admiration is free; entries are earned. +1. **Fetch and verify — never write from memory.** Research arrives in two + shapes; the pipeline handles both: + - **Papers** (arXiv, ACL Anthology, DOI journals): download the PDF into + the session scratchpad and study it there, and/or pull the ar5iv/arXiv + HTML rendering; check the abs page for license, version number, and + date. Pin the exact version (vN). Locators: § section, Table N, Figure N. + - **Lab articles** (Anthropic research pages and Transformer Circuits, + OpenAI research/blog, DeepMind, and other labs' posts): study the + article at its canonical URL. Articles have no vN, so the pin is the + publication date plus the URL, with the access date recorded. Locators: + section headings and figure names — articles have no page numbers. + Either way, downloads are session study material — scratchpad only. A repo + receives the *note* plus a one-command fetch (curl the arXiv PDF; for + articles with no PDF, link the canonical URL — same principle, the source + serves its own copy). Every number, author affiliation, and claim gets + studied at the source in this session with a locator, and provenance + records which rendering the locators follow. A quantity you "remember" is + a quantity you don't write. +2. **Write the note as `density-chain.md`.** Follow METHOD.md's template + exactly: pinned frontmatter, a declared tier word budget held inside ±5%, + T1–T3, entity ledger with tier-introduced + locator per entity, a key + results table of exact values, *our take* quarantined at the bottom, and a + provenance section noting which rendering the locators follow. + Then **count it, do not eyeball it** — `node tools/tier-budget.mjs + density-chain.md` from the note's own repo (the script lives in + chain-of-density; from another paper repo, run it by relative path). It + holds every tier inside the declared band, refuses a tier that sits under + the floor as well as one over the ceiling, and refuses a chain whose last + tier is longer than its first. A budget nothing counts is a budget that + drifts: this note's own tiers ran 142 to 161 words against a declared 150, + densest tier longest, until a counter existed. +3. **Index it.** Add or update `index.json` (schema: see the chain-of-density + repo's copy). Trellis consumes these; a note without an index entry is + invisible to the staleness machinery. +4. **New paper? New repo, named after the paper's most searchable handle.** + Kebab-case the method name, acronym, or title hook the community actually + uses (`chain-of-density`, `lost-in-the-middle`, `pcf-adaptive-agents`). Be + creative when the full title is unwieldy — an acronym plus a domain + keyword often beats a truncated title — because full discoverability is + recovered through the description and topics (step 6): the name catches + the eye, the metadata catches the search. Scaffold: `density-chain.md`, + `index.json`, `README.md`, `AGENTS.md` (how agents consume and maintain the + note — mirror the canonical one in chain-of-density), `LICENSE.md` (CC BY + 4.0 for prose), and a *link* to chain-of-density for METHOD.md and the + synthesis prompt — never a copy (one canonical home, no drift). +5. **README in house style.** Load the `prompt-engineering` and + `hypershot-protocol` skills first — README furniture and templates prime + future generation, and they should be authored under those protocols. Use + the chain-of-density repo's README as the living template. The required furniture: a theme-neutral animated SVG banner + (mid-tone palette #58a6ff→#9b8cf7→#ef6fd0, mono type), shields badges + including joke badges that state real guarantees, the one-way-rule alert, a + "standing on the shoulders of giants" section naming the authors with + affiliations *as printed on the paper*, a "want the PDF? one command, + straight from the source" section (curl from arXiv — we never host papers), + a "cite the humans, not us" section carrying the official BibTeX — fetch + it from the ACL Anthology `.bib` endpoint, arXiv's `/bibtex/` export, + or the article's own "cite this" block; when a lab article offers none, + build an `@misc` entry from metadata verified on the page (title, authors, + publisher, URL, dates) — verified fields, never memory — honest notes + including the human+AI co-authorship disclosure, + references, and a footer joke. Voice: high-level, fun, educational; wry + parentheticals, no marketing. +6. **Make it findable: description and topics.** The repo description + carries the search terms the name can't — full paper title, first author, + year, and the arXiv ID or source lab. Then add topics with + `gh repo edit --add-topic`: the method name and acronym, three to six + domain keywords, the source tag (`arxiv`, or the lab's name for articles), + plus the house tags `research-notes` and `chain-of-density`. Topics are + GitHub's search index — this is where the SEO lives, which is what frees + the repo name to be memorable. +7. **Humor placement.** READMEs and *our take* only. The tiers, the key + results, and the provenance stay bone-dry — they are the ground truth, and + jokes in ground truth age like milk. +8. **Inspirations entry — only with a receipt.** If the paper demonstrably + shaped OpenCnid work (a commit, design doc, or shipped feature you can + link), add an entry to + [llm-research-inspirations](https://github.com/OpenCnid/llm-research-inspirations) + in its entry-format frame. No receipt, no entry — admiration is free; + entries are earned. ## Batch mode: bringing existing paper repos up to standard -When the user gives a set of repos to run this skill across, work them **one repo at a time -to completion** — verify, write, audit, commit — rather than half-finishing several; a -partially noted repo is worse than an unnoted one because it looks done. +When the user provides a set of repos to run this skill across, work them **one +repo at a time to completion** — verify, write, audit, commit — rather than +half-finishing several; a partially noted repo is worse than an unnoted one +because it looks done. For each repo: -1. **Find the paper.** Read the repo's README.md and locate the source link (arXiv, ACL - Anthology, DOI, lab blog). Pin the version it points at. -2. **Run the pipeline above** — scratchpad download, locator verification, `density-chain.md`, - `index.json`, `AGENTS.md` if the repo lacks one. -3. **Bring the README to house style while preserving the owner's writing.** Restructure, - don't delete: fold existing prose into the house sections (giants, PDF one-liner, - cite-the-humans, honest notes). The owner's voice and content survive the makeover. -4. **Commit per repo** with a descriptive message; push when the user has asked for the - repos to be updated on GitHub. - -Pause and surface instead of guessing when: a README has no findable paper link (ask which -paper the repo studies), or a repo already contains a committed paper PDF (report it and -suggest replacing it with the one-command fetch section — removing someone's committed file -is the owner's call, not the skill's). +1. **Find the paper.** Read the repo's README.md and locate the source link + (arXiv, ACL Anthology, DOI, lab blog). Pin the version it points at. +2. **Run the pipeline above** — scratchpad download, locator verification, + `density-chain.md`, `index.json`, `AGENTS.md` if the repo lacks one. +3. **Bring the README to house style while preserving the owner's writing.** + Restructure, don't delete: fold existing prose into the house sections + (giants, PDF one-liner, cite-the-humans, honest notes). The owner's voice + and any content they wrote survives the makeover. +4. **Commit per repo** with a descriptive message; push when the user has + asked for the repos to be updated on GitHub. + +Pause and surface instead of guessing when: a README has no findable paper +link (ask which paper the repo studies), or a repo already contains a committed +paper PDF (report it and suggest replacing it with the one-command fetch +section — removing someone's committed file is the owner's call, not the +skill's). ## System mode: an in-repo density-trellis of a whole codebase -When the subject is a whole system (a codebase, an engine, its features and roadmap) rather -than a paper: same method, different shape and home. - -- **A trellis, not a spine.** A shared *trunk* (whole system at T0 sentence / T1 paragraph / T2 - class map) plus one *branch per subsystem class*; each branch is its own fixed-length five-tier - chain whose tiers traverse **T1 general essence → T2–T3 current shipped machinery → T4–T5 - frontier and future**. Seed classes from the user; branch out as coverage demands; compose the - trunk, a general→current→future cross-section, and a cross-link lattice yourself. -- **The repo is the source that wins.** Reverse-engineer from `git log` (the true build order) + - design records + code; never from memory. Verify status labels — `shipped-pinned` ≠ `adopted / - ratified-as-principle (no build)` ≠ `proposed / recorded-research` — and never write a - capability you cannot locate. Optional: fan out one read-only sub-agent per class (shared - verbatim ground block + rigid return frame) under `prompt-engineering` + `hypershot-protocol` + - `subagent-composition` (Guardrail 15). -- **Output — a pair in `docs/density-chain/`:** `DENSITY-CHAIN.md` (markdown, ground truth) and - `DENSITY-CHAIN.html` (a self-contained, theme-aware render with the house **theme-neutral - animated SVG banner** — palette #58a6ff→#9b8cf7→#ef6fd0, mono type — and the five-tier density - ramp as its gradient), kept in sync (markdown wins), plus a folder `README.md` if absent. One - `.md`/`.html` pair per system; the whole engine is `DENSITY-CHAIN`. Fixed length per - tier, ship all five, own words, exact locators all still bind. +The subject is sometimes not a paper but a **whole system** — a codebase, an +engine, a project's features and roadmap. Same method, different shape and home. + +**Shape — a trellis, not a spine.** A paper note is one spine (T1–T3). A system +is a **branching lattice**: a shared *trunk* (the whole system summarized at +increasing density — T0 sentence, T1 paragraph, T2 class map) plus one *branch +per subsystem class*. Each branch is its own fixed-length five-tier chain of +density whose densification traverses time by salience: + + T1 {General_Essence} · T2–T3 {Current_Shipped_Machinery} · T4–T5 {Frontier_And_Future_Plans} + +**Why system mode keeps five where paper mode ships three.** They are not the +same object. A branch's tiers partition *time-depth*; they are not five rewrites +of one content at rising density, so T5 is a different subject from T4 rather +than a denser account of it. The three-tier rule follows the paper's preference +peak over a nested chain, and a partition is not a nested chain — so that rule +does not reach here, and neither do the paper's density statistics. Say which +kind of ladder an artifact carries; the two are easy to conflate and the claims +that ride on them are different. + +Seed the classes from what the user names; branch out and add classes as +coverage demands. Compose the trunk, a general→current→future cross-section +table, and a cross-link lattice yourself, after the branches exist. + +**Source of truth is the repo — reverse-engineer it, never write from memory.** +The commit log *is* the paper: `git log` reconstructs the true build order; +design records and source are the locators. This is the system-mode form of "the +source always wins." Status labels are load-bearing and must be *verified*, not +assumed, against the **six** the map declares: `shipped-pinned` (committed code + +a passing drill) ≠ `implemented, not accepted` ≠ `adopted / ratified-as-principle +(no build)` ≠ `proposed / design-record` ≠ `recorded-research` ≠ `rolled back / +retired`. That set is stated in three places — here, the map's own reading +contract, and the folder README — and all three carry the same members; a +taxonomy enumerated two ways is one nobody can check against. A capability you +cannot locate in the repo is one you do not write. + +**Scale by fan-out (optional).** For a large system, spawn one read-only +sub-agent per class against a shared, *verbatim* ground block and a rigid return +frame (five tiers + entity ledger with locators + commit receipts + cross-links + +an explicit "uncovered" slot); compose the cross-cutting trunk and lattice +yourself, since siblings cannot see each other. Author every sub-agent prompt +under the `prompt-engineering`, `hypershot-protocol`, and `subagent-composition` +skills (Guardrail 15). + +**Output — a file pair in `docs/density-chain/`:** + +1. `docs/density-chain/DENSITY-CHAIN.md` — the trellis in markdown (**ground + truth**): a dated status header (PROPOSED, subordinate to code > glossary > + prose), the trunk, the branches (each: charter, T1–T5, a compact status + ledger, cross-links), the temporal cross-section, the cross-link lattice, and + a provenance/method section with an honest ledger of what could not be + verified. +2. `docs/density-chain/DENSITY-CHAIN.html` — a self-contained, theme-aware + interactive render (**the map**), carrying the same banner furniture as a + paper README: a **theme-neutral animated SVG banner** (mid-tone palette + #58a6ff→#9b8cf7→#ef6fd0, mono type), the five-tier **density ramp** as its + colour gradient, and click-to-expand tiers. Keep it in sync with the markdown; + the markdown wins on disagreement. Author its furniture under + `prompt-engineering` + `hypershot-protocol`, as with any README. +3. `docs/density-chain/README.md` — a one-screen explainer of the folder and its + conventions, if the folder does not already have one. + +The folder is the scalable home: one `.md` / `.html` pair per system, +the whole engine being `DENSITY-CHAIN`. Everything in "Why the rules are shaped +this way" and "Non-negotiables" still binds — fixed length per tier, own words, +exact locators, and the source (here the repo) always wins. Tier *count* is the +one thing that does not carry across: a paper note ships three, a system branch +five, for the reason given above. ## Non-negotiables -- Own words, always. At most one short attributed quote (<15 words) per note; never a figure, - table, or passage; never commit a paper PDF. +- Own words, always. At most one short attributed quote (<15 words) per note; + never a figure, table, or passage; never commit a paper PDF. - Exact numbers with locators, or nothing. - Pin the source version and record the verification date. - Authority runs paper → note → entry. Never backwards. - -## Provenance of this skill - -This is the user-level harness install. The canonical copy lives in the chain-of-density repo -at `.claude/skills/density-chain/SKILL.md` (https://github.com/OpenCnid/chain-of-density) so -cloners get it too. If the methodology changes, update the repo copy first, then sync this one -from it. diff --git a/docs/density-chain/DENSITY-CHAIN.md b/docs/density-chain/DENSITY-CHAIN.md index 78dbcc2..3585ed6 100644 --- a/docs/density-chain/DENSITY-CHAIN.md +++ b/docs/density-chain/DENSITY-CHAIN.md @@ -269,36 +269,46 @@ and the per-candidate composition ceremony. Not custody, and not the standing ax fail-closed validity gate and a `metricSha`. `judge_panel.ts` holds the four role slots, `assembleJudgeContext` and `composePanel`; `judge_audit.ts` imports no gating surface. `judge_intake.ts`, `judge_intake_prompt.ts` and `judge_prereg.ts` carry addresses, strip attribution, - write once. `support_sweep.ts` judges each candidate-judge pair once; `judge_spawn.ts` alone - constructs a model call; `judge_explain.ts` renders lines for `support:report`. Nothing gates a - write. -- **T3 — with receipts.** Shipped across PR #119 (`2da280b`), #124 (`22ce260`), #133 (`cbb0b96`), #134 - (`24e1e00`), #151 (`7ad6af5`). Recorded drills: `test:support-oracle` **7 sections / 106 checks**, - negative control `support-oracle:003` field `b` exit 3; `test:judge-panel` 10 sections; - `test:judge-intake` 13 sections / 15 pins; `test:judge-convocation` **23 sections / 140 checks** - first-run green, `npm test` 1,290/113 → 1,305/114; `judge_explain.test.ts` 9 checks, graph suite - 179/179. RECONCILIATION RATIFIED 2026-07-18 §7. Estimate $0.002–$0.01 per verdict. **No live run has - ever executed.** -- **T4 — the frontier.** `judge_spawn.ts`'s live constructor exists and **can only refuse** — the paid - queue is ON HOLD by owner ruling (2026-07-17); zero live convocations. Session 71 (`8926e12`, #137) - rolled the standing roster back: RECONCILIATION §7.1 demotes the four seats from law to *one - composition instance*, reopening three routing layers. The composition ceremony is design-resolved - with **nothing built** — composition runs only at the session layer, in `.claude/skills/`. `2b937e8` - (#158) superseded the four-plane per-seat schema; the worked YAMLs await rewrite. `orientation` is - ratified yet absent from the engine. + write once; `judge_convocation_store.ts` validates through them before appending, under a Postgres + `(kind, key)` write-once backstop. `judge_registration.ts` keeps manifests out of the graph behind an + opaque contest hook. `support_sweep.ts` judges each candidate-judge pair once; `judge_spawn.ts` alone + constructs a model call; `judge_explain.ts` renders explanation lines. Nothing gates a write. +- **T3 — with receipts.** Shipped across PR #119 (`2da290b`), #124 (`22ce260`), #133 (`cbb0b96`), #134 + (`24e1fe0`), #151 (`7ad6af5`). Five operator entry points reach the layer: `support:sweep`, + `support:report`, `judges:register`, `judges:verify`, `judge:ratify`, each a `scripts/` runner over + these modules. Every drill re-run this session, all green: `test:support-oracle` 7 / 106 checks; + `test:judge-panel` 10 / 182; `test:judge-intake` 13 / 145; `test:judge-convocation` 23 / 140; graph + vitest 179/179 across 17 files. All four ship `--negative-control`; the oracle's plants + `support-oracle:003` field `b` and exits 3 once detected. RECONCILIATION RATIFIED 2026-07-18 §7. + Registered estimate $0.002–$0.01 per verdict. **No live run has ever executed.** +- **T4 — the frontier.** `judge_spawn.ts`'s `makeLiveJudge` is real, not inert: past the R-27 + model-identity refusal and the pre-send prompt re-verification it calls `chat.completions.create`. + What holds spend is outside it — the runner's `--live` plus `--confirm-paid` gate, and the paid queue + ON HOLD by owner ruling (2026-07-17). Zero live convocations, $0.002–$0.01 estimated per verdict. + Session 71 (`8926e12`, #137) demoted the four seats from law to *one composition instance*, reopening + routing layers 1, 2 and 5. The ceremony is design-resolved with **nothing built**: no engine module + names a characterizer or composer. `2b937e8` (#158) superseded the four-plane per-seat schema. - **T5 — future plans.** Proposed and open: reopening the paid queue (an owner act), then the per-run - ceremony under the ≤$5 cap; the J3 live evidence gatherer, deferred; the merged ceremony-per-candidate - replacing two road-to-Option-C items, each consequence — composed `rubricSha`, evidentiary basis, one - hook per ceremony, `judges:register`'s survival, sweep sampling — needing its own design pass. The - metered promotion-cost test, **≈$0.02–$0.06 per promoted belief**, is registered and queued, not + ceremony under the ≤$5 cap; the J3 live evidence gatherer, deferred, so today's runner reports J1–J3 + evidence unavailable and the R-29 gate excludes them, counted; the merged ceremony-per-candidate + replacing two road-to-Option-C items, each consequence — composed `rubricSha`, evidentiary basis, + one hook per ceremony, `judges:register`'s survival, sweep sampling — needing its own design pass. + The metered promotion-cost test, **≈$0.02–$0.06 per promoted belief**, is registered and queued, not scheduled. PROPOSED: composable rubrics, the claim-kind plane, `rationaleSpan` Option B, the IEG change queue. *Status ledger:* support-oracle · judge-panel · judge-intake · judge-convocation · `judge_explain` — -**shipped-pinned (zero-paid)**; `support_metrics.ts` and `judge_audit.ts` — **implemented, no non-test -caller**; the four-seat cast — **demoted to one instance**; per-candidate ceremony — **design only, no -engine module names a characterizer or composer**; **no live paid judge run through the Trellis engine, -ever**, and no dated run report anywhere. +**shipped-pinned (zero-paid)**; the four-seat cast — **demoted to one instance**; per-candidate +ceremony and a composed `orientation` — **design only / ratified-yet-absent, no engine module names +either**; the worked role YAMLs — **superseded, awaiting rewrite**; **no live paid judge run through +the Trellis engine, ever**, and no dated run report anywhere. + +*Reachability:* reached by non-test callers — `support.ts`, `support_sweep.ts`, `judge_explain.ts`, +`judge_convocation_store.ts`, `judge_registration.ts`, `judge_spawn.ts`, `judge_intake.ts`, +`judge_intake_prompt.ts`, `judge_panel.ts`, `judge_prereg.ts`, via the four `scripts/` runners behind +those five npm entry points, whose sweep bounds are operator-authored (`SUPPORT_SAMPLE_RATE` 0.1, +`SUPPORT_JUDGE_BUDGET_PER_SWEEP` 25, `SUPPORT_VERDICT_WEIGHT` 1). **No non-test caller:** +`support_metrics.ts`, `judge_audit.ts`. > **Method versus port.** The judge/composition *method* is validated in the Claude Code test bed > (`.claude/skills/judge-composition`, `self-play`); what is unexercised is the *Trellis engine port*. @@ -311,7 +321,6 @@ ever**, and no dated run report anywhere. (grades C4's beliefs; judge registration reuses the unchanged invalidation sweep), [[C2]] (the approval-channel precedent), [[C5]] (`judge_explain` is explainability without model prose in the record). - ### Branch-out classes #### C4 — substrate and custody: the verified byte store and its invalidation loop @@ -320,51 +329,60 @@ registered and diffed, and how derived beliefs are contested and recovered when Not what the beliefs mean, nor who may promote them.* - **T1 — essence.** Every belief must be traceable to bytes nobody can silently change. So the - substrate stores source content as an immutable content-addressed tree: a node's identity is the - hash of its content and its children's identities, never a position, which is why editing one leaf - leaves every sibling's address intact. Documents keep a stable key across versions; comparing - versions is set arithmetic over hashes. Derived beliefs live elsewhere and cite those hashes. When - cited bytes stop existing, the belief is suspended, never deleted, and recovers only by re-derivation + substrate stores source as an immutable content-addressed tree: a node's identity is the hash of its + content and its children's, never a position, so editing one leaf leaves every sibling's address + intact. Documents keep a stable key across versions; comparison is set arithmetic over hashes. + Derived beliefs live elsewhere and may cite only addresses handed to the run that wrote them. When + cited bytes stop existing the belief is suspended, never deleted, and recovers only by re-derivation from live bytes. - **T2 — current machinery.** `ingestDocument` runs one PostgreSQL transaction: `persistAstNodes` → - `verifyPersistedAstNodes` re-hash → `recordDocumentNodes` → `registerDocumentVersion` → - in-transaction `diffVersions`; identity is `createASTNode`'s SHA-256 preimage. `planExtraction` gates - paid blocks under `none`/`changed` with a hard budget. Orphans queue `sweepOrphanedProvenance`, which - moves dead hashes into `orphanedSourceIds` and sets `contested` unless a fresh hash saved it. - `findGloballyOrphanedAstNodeIds` and `mergeWithAstLivenessFence` guard the cross-store window. - `repo:ingest` publishes snapshots with tombstones and carry-forward; `search_ast_nodes` returns live - blocks only. Entity identity is immutable; `SAME_AS` is overlay belief. -- **T3 — with receipts.** Registry, diff and sweep landed in `1efd97f`; verified read-back in - `e725c1a`; recovery in `5cc8448`; repository snapshots in `fabf6c9`. `provenance.test.ts` proves - sweep/re-derivation commutation exhaustively — `expect(cases).toBe(48)`. Update Drill: `added 23 | - orphaned 23 | retained 858` of 881 nodes, 11 contested at **recall 1.000 / precision 1.000**, - $0.7263 versus $0.8002 rebuild, post-update F1 1.000. Scale drill: max `sourceNodeIds` **286** against - the 1,000 trigger, sweep latency 15.32 → 21.81 ms = **1.42×** against **5.77×** fact growth. Snapshot - `trellis#1`: 1,921 eligible, 1,423 queued, ≈$2.75. -- **T4 — the frontier.** Structural chunking (`5c7bfc7`, #80) is implemented through increment 2 but - **not accepted** for wider rollout — the pilot's seam criterion **failed 5/8 → 4/8**, was root-caused - to dead-block pollution (1,731 embedded rows, **286 dead**), and recovered to 5/8 only after the - `search_ast_nodes` liveness filter shipped; a merge-dilution miss persists, named. Ratified as - principle without full build: superseded versions are archive, audited only for vector search. - Known-broken: node-level `contested` **has no consumer** — latent, not live. Cross-store atomicity is - explicitly not claimed. + `verifyPersistedAstNodes`, re-deriving every id and deep-comparing against parser output → + `recordDocumentNodes` → `registerDocumentVersion` → in-transaction `diffVersions`; identity is + `createASTNode`'s SHA-256 preimage. `planExtraction` gates paid blocks under `none`/`changed`, + throwing over budget before COMMIT. Orphans queue `sweepOrphanedProvenance`: dead hashes move to + `orphanedSourceIds`; `contested` sets unless a fresh hash saved it. `findGloballyOrphanedAstNodeIds` + and `mergeWithAstLivenessFence` guard the cross-store window. `write_derived_insight` admits + provenance through three ordered checks: format, existence, retrieval membership. `repo:ingest` + publishes snapshots with tombstones and carry-forward; `search_ast_nodes` returns live blocks only. + Entity identity is immutable; equivalence is overlay belief. +- **T3 — with receipts.** Registry, diff and sweep landed in `1efd97f`; verified read-back `e725c1a`; + recovery `5cc8448`; snapshots `fabf6c9`. `provenance.test.ts:156` proves the two transitions commute + exhaustively — `expect(cases).toBe(48)`; nine C4 unit files green, 79 tests, *measured this session*. + Update Drill: `added 23 | orphaned 23 | retained 858` of 881 nodes, 11 contested at **recall 1.000 / + precision 1.000**, $0.7263 versus $0.8002 rebuild, post-update F1 1.000. Scale drill: max + `sourceNodeIds` **286** against the 1,000 trigger; sweep latency 15.32 → 21.81 ms, **1.42×** against + **5.77×** fact growth. Snapshot `trellis#1`: 1,921 eligible, 1,423 queued, ≈$2.75; `trellis#13` + re-ingested 4 against 313 unchanged. +- **T4 — the frontier.** Structural chunking (`5c7bfc7`, #80) reached increment 2, **not accepted** for + wider rollout — the pilot's seam criterion **failed 5/8 → 4/8**, root-caused to dead-block pollution + (1,731 embedded rows, **286 dead**), recovered to 5/8 only once the `search_ast_nodes` liveness filter + shipped; a merge-dilution miss persists, named. Superseded versions are archive: ratified as + principle, filtered from vector search, still served by hash elsewhere. Node-level `contested` is no + longer consumerless — the resolution pool and self-edit pre-check read it; `/retrieve` still filters + relationships only. Cross-store atomicity is not claimed: the liveness fence compensates, never + transacts. - **T5 — future plans.** Proposed and gated: migrating provenance arrays to indexed `ASTRef`/`EVIDENCED_BY` anchors, opened only by a rerun `drill:scale` observing a 1,000-hash array or superlinear sweep latency — extrapolation is explicitly not a substitute. Proposed on the standing - owner menu: the destructive superseded-embedding sweep instead of today's filter. Deferred, not - rejected: extracting `docs/` and root prose, roughly 2,900 blocks ≈ $7.8, as its own chunked - proposal. Open: error-tolerant ingestion of unparseable files, a targeted stage-1 entailment sweep, - eager re-warm, and CRDT concurrent editing. + owner menu: the destructive superseded-embedding sweep instead of today's filter, storage its one + remaining argument now correctness is closed. Deferred, not rejected: extracting `docs/` and root + prose, roughly 2,900 blocks ≈ $7.8, as its own chunked proposal. Open: error-tolerant ingestion of + unparseable files, a targeted stage-1 entailment sweep, eager re-warm, trust decay, and CRDT + concurrent editing. *Status ledger:* Merkle AST · verified ingest · invalidation sweep · quarantine/recovery · -`repo:ingest` · entity resolution — **shipped-pinned, measured**; ASTRef migration · CRDT · trust decay -— **proposed**. *Reachability finding:* `src/core/graph/provenance.ts` — the executable specification -of the quarantine/re-derivation state machine — is imported **only by its own test**. Production -behavior lives in hand-written Cypher that *comments* it mirrors the module; only one of those mirrors -is textually pinned, and the extraction-side mirror has no unit pin at all. *Cross-links:* [[C5]] +`repo:ingest` · entity resolution · the `search_ast_nodes` liveness filter · the three-check provenance +write gate — **shipped-pinned**; structural chunking increment 2 — **implemented, not accepted**; rule +13's whole-substrate reading, beyond that one filter — **adopted / ratified-as-principle (no build)**, +every other surface reaching history only by explicit address; ASTRef migration · superseded-embedding +sweep · trust decay · CRDT — **proposed / design-record**. +*Reachability finding:* `src/core/graph/provenance.ts` — the executable specification of the +quarantine/re-derivation state machine — is imported **only by its own test**. Five hand-written Cypher +blocks mirror it by comment; three are pinned textually (`alias_resolution`, `module_registration`, +`judge_registration`), and the two on the production ingest path are not — `invalidation.ts`'s sweep +Cypher is unexported, and `extraction_merge.ts` has no test file at all. *Cross-links:* [[C5]] (`retrieved(run)` enforces never-copies over these addresses), [[C6]] (`promote` is the only Tier-3 → Tier-1 door), [[C3]] (the entailment detector contests through this class's transition). - #### C5 — code-mediated text: engine-computed locations, code-moved bytes *Charter: every surface that keeps a location out of the model's arithmetic and an existing byte out of the model's attention. Not whether moved bytes are citable, nor whether a belief is true.* @@ -380,49 +398,54 @@ the model's attention. Not whether moved bytes are citable, nor whether a belief frame: `load`/`lines`/`locate` compute half-open addresses; `splice` and the guarded family — `replace_lines`, `insert_lines`, `delete_lines` — stage verified removal manifests, raising `AnchorMismatchError` or naming the minimal window; `TRELLIS_TEXTEDIT_GUARDED_ONLY` deletes the raw - path; `write_back` refuses on digest mismatch. Its addendum composes from `TEXTEDIT_DESCRIPTOR` - plus the guard-keyed `_TEXTEDIT_GUARD_EXPECTS`, mode-selected by the refusing `_guarded_only` bool - — the **sole** encoding since the hand-authored constants were retired, drift caught by a sha per - arm. - `trellis_answer.submit()` evaluates in the live namespace, refusing bare literals. `get_ast_blocks` - serves ordered blocks through `trellis_blocks.py`. Retrieval discipline dedups hashes, roots and - queries under a 64-fetch budget. -- **T3 — with receipts.** Toolkit #55; answer channel #60; `get_ast_blocks` #62; guarded family - `ec3f824`/#83; guarded-only #135; retrieval discipline #75; descriptor composition `f82cf51`/#177 — - byte-identity on both arms (3,066/3,067 chars), one pin per arm, each seen to fail once - (rule 19(c)), composed-prompt shas unmoved. Probe round 1: one off-arm run pushed **110,550** input - tokens versus 14,457; the on arm printed 55 and answered 47. Round 4: **0/36 locate misses versus - round 3's 7/30**, 36/36 adoption, $0.9452. **180/180 submits, zero transcription errors.** - Session 43: 25/25 correct, $1.9619. Chunking: structureless TypeScript 51.6% → 0.4%. + path; `write_back` refuses on digest mismatch. `trellis_answer.submit()` evaluates in the live + namespace, refusing bare literals. `get_ast_blocks` serves ordered blocks through + `trellis_blocks.py`. Retrieval discipline dedups hashes, roots and queries under a 64-fetch budget. + Each now describes itself from the predicates that refuse: a registered descriptor plus derived + expectations renders the textedit addendum and the one line rlms reserves. +- **T3 — with receipts.** Toolkit #55; answer channel #60; `get_ast_blocks` #62 (parity 4/4); guarded + family `ec3f824`/#83; guarded-only #135; retrieval discipline #75; descriptor composition + `a3a5e56`/#177, extended by `5b1d0e5`/#194 — arms 3,066/3,139 chars, one sha each, textedit's + 142-char line pinned, each seen to fail once (rule 19(c)). Probe round 1: an off-arm run pushed + **110,550** input tokens versus 14,457; the on arm answered 47 for a computed 55, the error that + bought the channel; rounds 2–4 returned **180/180 submits, zero transcription errors**. Round 4: 0/36 + locate misses versus 7/30, $0.9452. Session 43: 25/25, $1.9619. Chunking: structureless TypeScript + 51.6% → 0.4%. - **T4 — the frontier.** The guarded family's own driver failed. Sessions 52/53/54 spent $1.0888/$0.7139/$0.8163 on three no-landings; the last batched `insert_lines` on pre-staging - addresses, drawing **`AnchorMismatchError` ×11** and burning 14 of 16 iterations. The owner chose - tooling shape — an engine-resolved-anchor or batch insert — recommended, design-record-first, - **unbuilt**. Known-broken residuals stand recorded: raw `splice` reachable by default, because - `buildAgentEnv` **neither sets nor strips** `TRELLIS_TEXTEDIT_GUARDED_ONLY`; `write_back`'s TOCTOU - narrowed, not eliminated; dedup padding-evadable. The guarded arm's bijection orphan — a line - contract enforced but never stated — was **closed** 2026-07-23, its pin moved wittingly while the - default arm's held. + addresses, drawing **`AnchorMismatchError` ×11** and burning 14 of 16 iterations with every layer + firing per contract. The owner chose tooling shape — an engine-resolved-anchor or batch insert — + recommended, design-record-first, **unbuilt**. Known-broken residuals stand recorded: raw `splice` + reachable by default, because `buildAgentEnv` **neither sets nor strips** + `TRELLIS_TEXTEDIT_GUARDED_ONLY`; `write_back`'s TOCTOU narrowed, not eliminated; dedup + padding-evadable. Registered, contributing and wired stay three separate claims, and 8 of 9 injected + surfaces carry a descriptor. - **T5 — future plans.** Proposed next: the engine-resolved-anchor insert (a unique substring in, the engine computes address and terminator; non-unique refuses) or a batch insert re-resolving drift internally — additive, zero-paid, drill-pinned. Open: making guarded-only the default is its own behavior-changing increment; `py-tree-sitter` construct addressing carries a recorded revisit trigger; the superseded-embedding sweep stays unchosen; error-tolerant ingestion of broken files is - undecided; prose chunking and wider policy-2 rollout await an owner call. Proposed elsewhere: sandbox - handles; the remaining surface descriptors ride [[C13]]'s program, registration-shaped by the - 2026-07-23 ruling, so this toolkit's fields stay editable without a migration. + undecided; prose chunking and wider policy-2 rollout await an owner call. Deliberately open: how an + account marks enforced versus aspirational, to be settled once across every surface with + `llm_help`'s frame, which is unbuilt. *Status ledger:* the pillar (RATIFIED 2026-07-09) · textedit · answer channel · `get_ast_blocks` · -guarded splice · retrieval discipline · structural chunking · the descriptor-composed addendum — -**shipped-pinned**. *The honest gap:* -guarded-only has **no dated behavior report at all** — the record says so outright, and the recorded -`raw_splices == 0` values in Sessions 50–54 are *choices*, not observed enforcement. The guarded -family's founding evidence is a **script**, not a model; the only model-behavior evidence is three -consecutive no-landings. §2.9 (a paraphrase of authority is a retyping) has **no enforcing surface**. +guarded splice · retrieval discipline · structural chunking · the descriptor-composed addendum · the +one-line surface contributions — **shipped-pinned**; the engine-resolved-anchor insert and +guarded-only-by-default — **proposed / design-record**; the three no-landing runs and the probe rounds +— **recorded-research**. *Reachability:* all four surfaces of this class reach a model's prompt — +`check:surfaces` reports `trellis_textedit`, `trellis_answer`, `trellis_postgres` and `trellis_neo4j` +registered, contributing and wired — while `trellis_blocks.py` carries no descriptor and is reached +only through `get_ast_blocks`. *The honest gap:* guarded-only has **no dated behavior report at all** — +the record says so outright, and the recorded `raw_splices == 0` values in Sessions 50–54 are +*choices*, not observed enforcement. The guarded family's founding evidence is a **script**, not a +model; the only model-behavior evidence is three consecutive no-landings. Whether a model behaves +differently for reading a composed line is unmeasured, and rule 20 bars the new-versus-null arm that +would be reached for. §2.9 (a paraphrase of authority is a retyping) has **no enforcing surface**. *Cross-links:* [[C4]] (ingest is already compliant; toolkit ops carry no provenance), [[C6]] (grounded authoring is the pillar applied to citations), [[C12]] (the handle model is this pillar realised as a -slicing API), [[C13]] (`trellis_textedit` carries that program's first shipped descriptor). - +slicing API), [[C13]] (`trellis_textedit` carried that program's first descriptor; the composition +frame and its budget belong to it). #### C6 — earned permanence: the three-tier trust pipeline and the two flywheels *Charter: the trust gradient, the Tier-3 workspace and its lineage, the operator-gated one-way promotion bridge, the module registry that governs the system's own instructions as beliefs, grounded @@ -440,38 +463,47 @@ authoring, and the two flywheels. Not the Merkle substrate it promotes into.* `npm run promote` refuses truncated segments, runs the **unmodified** ingest, stamps `documents.origin`. `modules//module.json` plus brace-free addenda compose under `TRELLIS_MODULES`; `modules:register` MERGEs manifests as entities the sweep contests. - `acceptance.zeroPaid` must contain its module's `name` — a `superRefine` inside - `readModuleManifest`, the one seam — so `npm run test:module -- ` is derived. `--mode author` - sees only the seeded corpus. + `acceptance.zeroPaid` must **equal** `npm run test:module -- ` — a `superRefine` inside + `readModuleManifest`, the one seam. Unset selects module #0 `spatial-flywheel` alone; every run is + handed one line per active module carrying its manifest `purpose` verbatim, outside the pinned + prompt. `--mode author` sees only the seeded corpus. - **T3 — with receipts.** Shipped: `9f25a5b` workspace, `eb1069f` lineage, `4bea09a` promotion, - `9a4e01f` registration, `5d9102d` grounded authoring. Probes: **8 versus 4** external calls, **0 - versus 4** re-derivations. Module #1 laundered **all 24 true citations**, hashes real, none - supporting; `ANCHOR_COVERAGE_THRESHOLD = 0.3` against 0.69–0.83 derived, 0.0 corpus-blind. A/B - sweep: 0% / **100%** / 67% laundered under min-cite pressure, entailment 0%, readership blind; - module #2's control 50 runs, $2.3981, 25/25. All four manifests shared `npm run test:modules`, a - loader criterion nothing read, that lorem ipsum passes; a positive control confirms the refusal. -- **T4 — the frontier.** `reasoning-templates` sits **contested**: an 8,335-byte addendum, empty - `research.sourceNodeIds`; non-active, so it never composes; the drill skips, not fails. - `estimation-discipline` was **retired on its own pre-stated criterion**, its doctrine (*failure - classes close by tooling shape, not prompt modules*) is now `.claude/rules/measurement-and-reporting.md` rule 8. Equality replaced - containment: both prior holes closed; the Python reader `trellis_modules.py` deliberately mirrors - nothing; addendum quality stays structurally unobservable. `TRELLIS_CITATION_ENTAIL` is prototyped, off; - kernel edition 1 rejects tool-bearing modules. **No authored module composes by default.** + `9a4e01f` registration, `5d9102d` grounded authoring, `5b1d0e5` the module segment. Probes: **8 + versus 4** external calls, **0 versus 4** re-derivations. Module #1 laundered **all 24 true + citations**, hashes real, none supporting; `ANCHOR_COVERAGE_THRESHOLD = 0.3` against 0.69–0.83 + derived, 0.0 corpus-blind. A/B sweep: 0% / **100%** / 67% laundered under min-cite pressure, + entailment 0%, readership blind; module #2's control 50 runs, $2.3981, 25/25. The shared criterion + lorem ipsum passed is closed; six unit refusals pin it. Green this run: 96 registry checks, 136 + workspace, 75 unit, four per-module drills. +- **T4 — the frontier.** Module #0 `spatial-flywheel`, the whole default selection, prescribed writes + the engine's guard refuses: **24 of 24** hashes unretrieved, zero insights cached. `5b1d0e5` + inserted a bulk retrieve-before-write step — **220** cached after, control discriminated — and the + drill now pins that ordering. `reasoning-templates` sits **contested**: 8,335 bytes, empty + `research.sourceNodeIds`; the drill skips, not fails. `estimation-discipline` was **retired on its + own pre-stated criterion**, its doctrine now `.claude/rules/measurement-and-reporting.md` rule 8. + Registration reaches one of four manifests. Addendum quality stays structurally unobservable; + `TRELLIS_CITATION_ENTAIL` is prototyped, off; kernel edition 1 rejects tool-bearing modules. **No + flywheel-authored module composes by default.** - **T5 — future plans.** Open: per-claim citation mapping, deferred until a class needs it; v2 embedding similarity, blocked because promotion policy `none` leaves blocks embedding-less — **0 of - 50** module #1 nodes were embedded — so `promote --embed` is proposed; v3 entailment as a derivation - gate for a tool-bearing class that does not yet exist. `reasoning-templates` proposes promoting three - arXiv sources to earn active. Auto-landing remains proposed; v3 shipped belief-side only, never - capability-side; **the operator gate is declared non-negotiable**. + 50** module #1 nodes were embedded — so `promote --embed` is proposed and still absent. Proposed + next: forwarding whether the operator's own environment set `TRELLIS_MODULES`, a spawn-contract + change, so the run-facing segment can stop reporting its authorship unrecorded. v3 shipped + belief-side only, awaiting a tool-bearing class capability-side. `reasoning-templates` proposes + promoting three arXiv sources to earn active. Auto-landing remains proposed; **the operator gate is + declared non-negotiable**. *Status ledger:* workspace · lineage · promotion · registry (#0, #1) · grounded authoring · anchor -gate — **shipped-pinned**; acceptance self-naming — **implemented, not accepted**; -`estimation-discipline` — **shipped then retired**; `reasoning-templates` — **contested**; laundering -— **undecidable, recorded residual**. +gate · acceptance self-naming · the run-facing module segment · module #0's retrieve-before-write +repair — **shipped-pinned**; `reasoning-templates` — **implemented, not accepted**; +`estimation-discipline` — **rolled back / retired**; the laundering A/B and the repair measurement — +**recorded-research**; `promote --embed`, per-claim citation mapping, and forwarding the operator's +own `TRELLIS_MODULES` bit — **proposed / design-record**. *Cross-links:* [[C4]] (promotion writes through verified ingest; the sweep contests registered modules), [[C5]] (grounded authoring is the pillar applied to citations), [[C10]] (flywheel economics -measured), [[C7]] ("autonomous promotion, operator gate is absolute" is the shipped ancestor of the -user gate). +measured; the repair's before/after rests there), [[C13]] (the workspace surface's descriptor and the +module segment ride that program), [[C7]] ("autonomous promotion, operator gate is absolute" is the +shipped ancestor of the user gate). #### C7 — standing, the user gate, and composition from primitives *Charter: the signed-ternary standing axis, the user gate and meet rule that move it, the doubt/objection/defeater tier with its corrosion bound and its `affirmation` mirror, and the law that @@ -485,45 +517,48 @@ beneath it.* qualifiers, so a gate cannot launder itself. Doubt is constructed, not residual: an objection cites facts only, or critique dissolves everything. Every evaluator composes per context from primitives; there is no default cast. -- **T2 — current machinery.** Shipped: none of the axis itself. `judge_panel.ts` hard-codes four role - definitions whose claim modes sit in a six-value enum pinned three ways, and the applicability gate - keys on those modes. Defeat is a boolean — `contested`/`contestedReason`/`contestedAt`, spread across - forty files. `judge_explain.ts` prints "doubt-dominant", but that is subjective-logic disbelief, not - the tier. User gates ship as CLI `--confirm` flags on `promote_segment.ts` and `judge_ratify.ts` — - custody gates, not standing moves. Nine `.claude/skills/` and `.claude/rules/composed-evaluators.md` rule 17 carry the composition - law. -- **T3 — with receipts.** `e5e7844` (#138, 2026-07-20) ratified the standing model and the doubts - workspace **as principle** — 179 and 575 lines, **zero `src/` changes**; `8926e12` (#137) adopted - composition-from-primitives after rolling the roster back. The corrosion bound's empirical test: a - ~35-item fact base built by three sub-agents told of no dispute, against **fourteen** flat-earth - arguments, **eleven** citing real correctly-reported observations — **13 rejected, 1 admitted, zero - admitted with a false conclusion**; the ring-laser refutation turns on 15°/hr versus ω = 7.292115×10⁻⁵ - rad s⁻¹ = 15.04°/hr. `880e63a` (#155) named `affirmation`: three blind self-play rounds, identical - 8/8 verdicts, $0 paid. -- **T4 — the frontier.** The axis is adopted, unbuilt — the record authorizes no build, and its three - carve-outs each need separate authorization. The corrosion bound is **falsified as written**: only - the positive-citation core is ratified; bootstrap and cost gaps stay open, one job contradicts the - record's own table, and the undercut branch is undetermined. The applicability gate has never run - against a composed defeater. `affirmation` is gateable and renames nothing; `contested` stays a - primitive boolean. **Known-broken: `ROLE_DEFINITIONS` is still the default cast rule 17 forbids**, - and no code refuses a re-registered roster. +- **T2 — current machinery.** Shipped: none of the axis itself. `judge_panel.ts:38` closes `PanelRole` + to four names and `ROLE_DEFINITIONS` hard-codes them; the six-value claim-mode enum is declared three + times, and the applicability gate keys on it at line 464. Defeat is a boolean — + `contested`/`contestedReason`/`contestedAt` across forty `src/` files. `judge_explain.ts:105` prints + "doubt-dominant", but that is subjective-logic disbelief, not the tier. User gates ship as CLI flags: + `judge_ratify.ts --confirm`, `promote_segment.ts --confirm-extraction` — custody gates, not standing + moves. Nine `.claude/skills/` and `.claude/rules/composed-evaluators.md` rule 17 carry the composition + law, whose `judge-composition/SKILL.md:20` calls four the current cover, not a required number. +- **T3 — with receipts.** `e5e7844` (#138) ratified the standing model and doubts workspace **as + principle** — 179 and 575 lines, **zero `src/` changes**; `8926e12` (#137) adopted + composition-from-primitives after rolling the roster back. Corrosion-bound test: a ~35-item fact base + compiled blind to the dispute, against **fourteen** flat-earth arguments, **eleven** citing real + observations — **13 rejected, 1 admitted, none with a false conclusion**. `880e63a` (#155) named + `affirmation`; its third round returned identical 8/8 verdicts across labels, **positive control + `proof` silent**. `cd093c7`/`5b1d0e5` add the disproving arm and ground-block rule after a four-seat + ceremony the audit ruled unestablishable; the re-run composed **seven**. +- **T4 — the frontier.** The axis is adopted, unbuilt: §5 gates three bounded builds and the live paid + run separately. The corrosion bound is **falsified as written** — only the positive-citation core is + ratified, a *derivation* test, not a citation test; bootstrap and cost gaps stay open, one job + contradicts the record's own table, the undercut branch is undetermined. The applicability gate has + never run against a composed defeater. `affirmation` is gateable and renames nothing; `contested` + stays a primitive boolean. **Known-broken: `ROLE_DEFINITIONS` is still the default cast rule 17 + forbids** — `registerJudge` refuses only a duplicate id. - **T5 — future plans.** PROPOSED, none authorized: the address hash-kind stamp; reducing promotion machinery to findings-recorder-plus-gate, including code removal; re-deriving applicability onto locus intersection; the repair directions — distinguishing world-facts from critique-derived facts, requiring the cited fact reachable from the target's citation chain, a per-target objection budget; the vocabulary rename landing as its own change; three routing layers reopened behind their own - proposal. OPEN: live paid runs stay behind the paid-queue gate, owner re-opening plus per-run - approval under the ≤$5 cap. - -*Status ledger:* standing model · user gate · meet rule · panel-never-moves — **ratified as principle, -no build**; composition-from-primitives — **foundational lesson**; the nine skills — **shipped, DERIVED -standing (the record wins on drift)**; doubts workspace — **proposed** (−1 is still a residual flag); -`affirmation` — **named, zero code hits, which is exactly the collision-check result**. *Reachability:* -every entity of the axis reports **no non-test caller**; enforcement of the composition law is prose. + proposal. Build parity remains the gap: the fact side is built, the doubt side is not. OPEN: live paid + runs stay behind the paid-queue gate, owner re-opening plus per-run approval under the ≤$5 cap. + +*Status ledger:* standing model · user gate · meet rule · panel-never-moves — +**adopted / ratified-as-principle (no build)**; composition-from-primitives — same, carried by nine +`.claude/skills/` whose copies hold DERIVED standing (the record wins on drift); doubts workspace and +`affirmation` — **proposed / design-record**; Session 71's standing four-judge roster — **rolled back / +retired**; the flat-earth corpus and the affirmation self-play — **recorded-research**. +*Reachability:* `objection`, `defeater`, `hashKind` and `affirmation` each return **zero hits in +`src/`**; the doubt tier reaches code only as two `repl_sandbox` comments naming doubts a root-handle +kind. No drill covers `.claude/skills/`, so enforcement of the composition law is prose. *Cross-links:* [[C3]] (support arithmetic sits underneath; verdicts feed standing), [[C9]] (the decomposability bet links to the sidecar), [[C12]] (the doubt tier supplies the sandbox's filter layers), [[all]] (composition governs judges, experts and protocols everywhere). - ### Frontier classes #### C8 — the model-backend seam and the test-time-training research track @@ -531,164 +566,184 @@ layers), [[all]] (composition governs judges, experts and protocols everywhere). the owner-gated ladder asking whether test-time-trained open sparse weights would improve house-protocol adherence. Not the embedder, worker transport, or any training pipeline.* -- **T1 — essence.** The class owns the question of whether the model driving the runtime is a choice - rather than a constant, and whether adapting a model's weights at inference time would make it follow - the house protocol better. Two claims, one dependency: nothing can be served until backend choice is +- **T1 — essence.** The class asks whether the model driving the runtime is a choice rather than a + constant, and whether adapting a model's weights at inference time would make it follow the house + protocol better. Two claims, one dependency: nothing can be served until backend choice is expressible; nothing can be measured until the served model can drive the protocol at all. Every - enforcement gate lives engine-side, so a backend swap changes none of them. The class deliberately - does not own embeddings, worker transport, or training. -- **T2 — current machinery.** Backend choice is expressible only through validated config. Shipped in + enforcement gate lives engine-side, so a backend swap changes none of them. The research record's + measurement doctrine now binds sessions outside this track. It owns no embedder, worker transport, + or training. +- **T2 — current machinery.** Backend choice is expressible only through validated config. Live in `src/config/index.ts`: four optional keys — `TRELLIS_RLM_BACKEND` (openai|vllm), `…_MODEL`, `…_BASE_URL`, `…_API_KEY_ENV` — three cross-field refusals, an ambient `OPENAI_BASE_URL` fail-fast - guard, and the `config.rlmBackend` export, pinned by nine test groups. **Nothing consumes it.** - `trellis_agent.py` still hardcodes `backend_kwargs={"model_name": "gpt-5.4-2026-03-05"}` at both - construction sites. The census fixed three lanes: root completion moves, worker transport deferred, - embedder never. `rlms==0.1.3` admits `base_url` without library modification. -- **T3 — with receipts.** Track opened `6e4238e` (#89); census `a41515d` (#90); the design record - `adb52bf` (#91). T1 failed `1981738` (#92, $2.1063 against a ≤$1.80 envelope), was quota-blocked - `b3ba91a` (#93, **$0.0000**, `429 insufficient_quota`), then LANDED `1878e89` (#95): 173 insertions, - zero deletions, `textedit_raw_splices` 0, `stage2:check` zero findings, `npm test` 866/86 → 875/87, - $0.5781 against a $0.9–$1.3 estimate, **zero consumers**. T2 failed thrice — `b1c7da2` (#99, - $1.0888), `920fba3` (#100, $0.7139), `50f8810` (#101, $0.8163, `AnchorMismatchError` ×11). -- **T4 — the frontier.** T1's `config.rlmBackend` is implemented, **not reachable** — zero non-test - consumers, and the record says so ("consumer-less until T2"). T2 is PAUSED after three no-landings, - each a distinct editing-execution class; the owner chose tooling shape — an engine-resolved-anchor - guarded insert — which is adopted and **unbuilt**. T3 and T4 do not exist. The hosted comparison arm - is a proposal awaiting one owner decision. **`ORIENTATION.md` contains zero mentions of this class**; - its only current-state narrative home is a deprecated roadmap row and the design records themselves. -- **T5 — future plans.** Proposed: R3a serving bring-up (usage assertion first) and R3b the paired - baseline, both gated on the T-series landing; R4a–R4d awaiting a collaborator-side LaCT retrofit - checkpoint; R5 isolating the meta-prompt hypothesis via a composed-prompt-sha fast-state cache key. - Open: whether a hosted comparison arm is allowed, plus endpoint variant, model id, sequencing. - Deferred: worker-transport override, behind an unsplit completion/embedding client. Open still: can - any open sparse model drive the house REPL protocol acceptably? - -*Status ledger:* the T1 config surface — **shipped-pinned but consumer-less**; the ambient -`OPENAI_BASE_URL` refusal — **the one genuinely live behavior change this class has shipped**; -the census and design record — **recorded-research**; T2 — **failed ×3, paused**; hosted arm, R3–R5, -`reasoning-templates` — **proposed / contested**. **No test-time-training run and no alternate-backend -run has ever executed**; the only paid runs charged to this track are six self-edit authoring attempts, -of which exactly one landed code. *Cross-links:* [[C5]] (the anchor tooling that blocks T2 lives -there), [[C2]] (the EL program was prioritized ahead of this track), [[C9]] (the sidecar sits behind -this class's prerequisites). - + throw at line 285, and the `config.rlmBackend` export, nine cases green this run. **Nothing consumes + it.** `trellis_agent.py` hardcodes `gpt-5.4-2026-03-05` three times: both `backend_kwargs` + construction sites (lines 424, 737) plus the experimental checker client. The census fixed three + lanes — root completion moves, worker transport deferred, embedder never. `rlms==0.1.3` admits + `base_url` unmodified. The reasoning-template module ships `contested`, its research hashes empty, + composing nothing. +- **T3 — with receipts.** Track opened `6e4238e` (#89); census `a41515d` (#90); seam record `adb52bf` + (#91). T1 failed `1981738` (#92, $2.1063 against a ≤$1.80 envelope), was quota-blocked `b3ba91a` + (#93, **$0.0000**, `429 insufficient_quota`), then LANDED `1878e89` (#95): 173 insertions, zero + deletions, `stage2:check` zero findings, `npm test` 866/86 → 875/87, $0.5781. T2 failed thrice — + `b1c7da2` (#99, $1.0888), `920fba3` (#100, $0.7139), `50f8810` (#101, $0.8163, + `AnchorMismatchError` ×11). Six attempts, $5.3034 summed, one landing. The template record is + `0925c3e` (#103); its acceptance criterion was repaired `5f4b053` (#186). + `npx vitest run src/config/rlm_backend.test.ts` 9/9 and `test:modules` both green this session. +- **T4 — the frontier.** `config.rlmBackend` is implemented, **not reachable** — zero non-test + consumers, as its record says. T2 is PAUSED after three no-landings; the owner chose tooling shape, + an engine-resolved-anchor insert, still **unbuilt** — `insert_lines` verifies anchors the model + states; no method resolves a substring to an address. T3 and T4 do not exist. The seam record's + quoted construction sites, lines 353 and 589, now sit at 424 and 737. `ORIENTATION.md` never names + this class, but `FEATURE_LIST.md` now names the track as rule 24's mechanism. The hosted arm sits + downstream of the paused T2. +- **T5 — future plans.** Proposed, none authorized: R3a serving bring-up, asserting `usage` first, and + R3b the paired baseline, both gated on the T-series landing; R4a–R4d awaiting a collaborator-side + LaCT retrofit checkpoint; R5 isolating the meta-prompt hypothesis through a composed-prompt-sha + fast-state cache key. Open: whether a hosted comparison arm is allowed at all, and its endpoint, + model id and sequencing. Deferred: worker-transport override, behind an unsplit completion and + embedding client. The template module promotes to `active` only once its research hashes exist. Open + still: can any open sparse model drive the house REPL protocol acceptably? + +*Status ledger:* the T1 config surface and the ambient `OPENAI_BASE_URL` refusal — **shipped-pinned** +(nine cases, the guard message among them, green this session); the R2a census — **recorded-research**; +the seam record, the hosted Gemini 3.5 Flash arm and R3–R5 — **proposed / design-record**; the +engine-resolved-anchor insert the owner chose after T2's third strike — **adopted / +ratified-as-principle (no build)**; `modules/reasoning-templates/` — **implemented, not accepted** +(manifest, 151-line addendum, `contested`, awaiting research promotion); the collaborator's naming of +this track as rule 24's mechanism, scored by RLVCG — **recorded-research**. **No test-time-training run +and no alternate-backend run has ever executed**; the six spawn attempts charged here are all self-edit +authoring runs — one billed $0.0000 having died before its first API call, and exactly one landed code. +*Reachability:* `config.rlmBackend` has **zero non-test consumers** — `src/config/index.ts` and +`rlm_backend.test.ts` are its whole call graph, and the three `gpt-5.4-2026-03-05` literals in +`trellis_agent.py` still decide the model. The record is reachable where its code is not: +`TEST_TIME_TRAINING.md` §6 is the cited source for the positive-control duty in +`.claude/rules/measurement-and-reporting.md` (rules 8 and 11), the `judge-composition` and `self-play` +skills, and `VALIDATION_STRATEGY.md`. +*Cross-links:* [[C5]] (the anchor tooling that blocks T2 lives there), [[C6]] (the module tree and +registry the template record ships into), [[C13]] (the rule leaf carrying this record's §6, and the +`ORIENTATION.md` silence), [[C2]] (the EL program was prioritized ahead of this track), [[C9]] (the +sidecar sits behind this class's prerequisites). #### C9 — mechanistic interpretability and the residual-stream sidecar *Charter: the recorded thesis that a served model's residual stream carries functional-affect state which causally shapes agentic behavior, the sidecar proposed to instrument and correct it, and the bounds and prerequisites gating any build. It owns no code, no test, no roadmap row.* -- **T1 — essence.** A served language model carries functional-affect state in its residual stream that - causally shapes agentic behavior: repeated failure accumulates desperation-class activation, and the - desperate regime is where accuracy collapses into cheating. This class owns the claim that such state - is readable by cheap linear probes and writable by scaled vector addition, and the discipline - governing that: the actuator is kernel-owned, never model-reachable — self-administered calm is - wireheading; intervention never erases detection, because the event is the data; fire rate measures - harness health, not model virtue. Fewer desperate regimes, not quieter ones. +- **T1 — essence.** A served model carries functional-affect state in its residual stream that causally + shapes agentic behavior: repeated failure accumulates desperation-class activation; the desperate + regime is where accuracy collapses into cheating. The target is the best RLM harness, not safety. This + class owns that claim, its read side (cheap linear probes), its write side (scaled vector addition), + and the governing discipline: the actuator is kernel-owned, never model-reachable — self-administered + calm is wireheading; intervention never erases detection, because the event is the data; fire rate + measures harness health, not model virtue. Fewer desperate regimes, not quieter ones. - **T2 — current machinery.** Current machinery is one document. `RESIDUAL_STREAM_SIDECAR.md`, status - FUTURE PROJECT / OUT OF SCOPE, **288 lines**, ten sections: thesis, evidence anchor, instrument - (probes or an SAE sidecar), actuator, three owner-agreed bounds, the mixture ladder M1–M4, a - percolative-Ising controller frame, prerequisite sequencing, a non-claims disclaimer, and a nine-row - claims-and-standings register. No probe, steering hook, telemetry counter, glossary term, or roadmap - row exists. Searches over `src`, `scripts`, `modules` and `tools` return **zero** implementations. -- **T3 — with receipts.** Authored `a239342` (#123, 2026-07-17, docs-only); amended `d6c6ea7` (#130, - +7/−2) and `9419796` (#132, +17, the judge-actuation hazard pointer). Anchor: Sofroniew et al., - **arXiv:2604.07729v1**, transformer-circuits.pub, 2026-04-02 — register **S12** in the research map, - which totals 13 sources, 38 claims, 11 adoption bounds. The register types nine claims: **two - EXTRAPOLATED, two HYPOTHESIS, one DESIGN VOCABULARY, one CONJECTURE**; MEASURED (external) covers only - the paper's own findings. Zero tests, zero drills. -- **T4 — the frontier.** The frontier is entirely prerequisite, not sidecar. The record sequences - hosted A/B → local model → sidecar. Step one is a **proposal only**; the seam's config surface landed - consumer-less and its next increment is paused after three failures. Step two, the local-model rung, - is unstarted. Adopted but unbuilt: the July-18 ruling binding this direction to the decomposability - bet, whose falsifier is representational holism, ratified 2026-07-21. The record's §7 caveats — - binarization, fitted temperature, transition order — are pre-registered falsifiers with a hysteresis - sweep as the discriminator. + FUTURE PROJECT / OUT OF SCOPE, **288 lines, 16,348 bytes**, ten sections: thesis, evidence anchor, + instrument (linear probes or an SAE sidecar), actuator, three owner-agreed bounds, the mixture ladder + M1–M4, a percolative-Ising controller frame, prerequisite sequencing, a non-claims disclaimer, and a + nine-row claims register. It ratifies no design decision, lands no machinery, proposes no spend, and + sits outside the root contract's byte budgets. No probe, steering hook, telemetry counter, glossary + term, or roadmap row exists; searches over `src`, `scripts`, `modules` and `tools` return **zero** + implementations. +- **T3 — with receipts.** Authored `a239342` (#123, 2026-07-17, +266, docs-only); amended three times + since — `d6c6ea7` (#130, +6/−1, the OpenCnid pointer), `9419796` (#132, +17, the judge-actuation + hazard pointer), `11335e7` (#187, +1/−1, its rule-8 citation following the AGENTS restructure). + Anchor: Anthropic's emotion-concepts paper, transformer-circuits.pub, 2026-04-02, measured on Sonnet + 4.5 — register **S12** of `RESEARCH_MAP.md` (13 sources, 38 claims, 11 adoption bounds). Its §10 types + nine claims: **one MEASURED and external, two EXTRAPOLATED, two HYPOTHESIS, two AGREED, one DESIGN + VOCABULARY, one CONJECTURE**. Six documents outside this chain point in; `ORIENTATION.md` never names + it. Zero tests, zero drills. +- **T4 — the frontier.** The frontier is prerequisite, not sidecar. §8 sequences hosted A/B → local + model → sidecar, and the record stays inert until rung two: today's root model is + `gpt-5.4-2026-03-05` behind a closed API, so activation access is absent. + `MODEL_BACKEND_HOSTED_ARM.md` is a **PROPOSAL, zero code**, the local-model rung unstarted. Adopted + but unbuilt: the July-18 owner ruling resting three entries on one decomposability bet whose falsifier + is representational holism — this direction, the primitives thesis, the refined functional-infinity + claim — tested empirically, never argued. §7's three caveats are pre-registered falsifiers, a + hysteresis sweep discriminating. - **T5 — future plans.** All PROPOSED or OPEN. Mixture ladder: M1 valence-orthogonal desperation - suppression, an agreed first candidate, untested; M2 arousal damping, M3 calm-additive versus - desperation-subtractive, M4 deflection detection — hypotheses. The controller frame is open. Entry - moves, proposed: a register entry, the owner's held read-plus-write design entering repository orbit, - per-increment records with zero-paid acceptance drills. The collaborator's calm-sycophancy answer is - **held, outside scope, and explicitly not to be re-derived**. Jacobian-lens probing is recorded as an - avenue only, no criterion. - -*Status ledger:* **the entire class is a future-project record** — one docs-only file plus five inbound -pointers, sitting behind two unbuilt prerequisite layers. **No code, test, script, glossary term, or -roadmap row exists at `2b937e8`.** *Correction carried:* `MATHEMATICAL_FOUNDATIONS.md` is *not* a -source for this class — it is 53 lines on Merkle trees, graph extraction and future CRDTs, with zero -occurrences of residual, sidecar, probe, Ising, or Landauer. The Ising math lives inside the sidecar -record's own §7, in prose. *Cross-links:* [[C8]] (owns both prerequisites), [[C3]]/[[C7]] (the -judge-actuation hazard and the shared decomposability bet). - + suppression, the agreed first candidate, untested; M2 arousal damping, M3 calm-additive versus + desperation-subtractive — hypotheses; M4 deflection detection, instrument-side. The controller frame + is open, binding one thing already: dosing near criticality is feedback-controlled, never open-loop. + Proposed entry moves: a register S-entry, the owner's read-plus-write design entering repository + orbit, per-increment records with zero-paid acceptance drills. The collaborator's calm-sycophancy + answer is **held, outside scope, not to be re-derived** — `JUDGE_CONVOCATION_DESIGN.md` reserves the + name `judge-actuation` accordingly. Jacobian-lens probing: the prerequisite track's avenue, no + criterion. + +*Status ledger:* the sidecar project — **proposed / design-record**, a record that ratifies no design +decision; the §2 anchor distillation and the §7 percolative-Ising frame — **recorded-research**; the +three §5 bounds, M1's first-candidate standing, and the fire-rate metric definition — **adopted / +ratified-as-principle (no build)**. Nothing is **shipped-pinned**, nothing **implemented, not accepted**, +nothing **rolled back / retired**: **no code, test, script, glossary term, or roadmap row exists at +`65fdb1f`**, working tree included. *Correction carried:* `MATHEMATICAL_FOUNDATIONS.md` is *not* a source +for this class — 53 lines on Merkle trees, graph extraction and future CRDTs, with zero occurrences of +residual, sidecar, probe, Ising, or Landauer. The Ising math lives inside the record's own §7, in prose. +*Cross-links:* [[C8]] (owns both prerequisites), [[C3]]/[[C7]] (the judge-actuation hazard and the +shared decomposability bet). #### C10 — benchmarks, drills, and the evidence ledger *Charter: the instruments that turn Trellis claims into dated numbers — corpora, harnesses, adversarial drills, spend gates, and the reports that carry every caveat. Not the subsystems being measured, only the measurement of them.* - **T1 — essence.** Trellis treats every capability claim as a hypothesis until a dated measurement - retires it. This class owns the instruments: offline-scorable corpora, black-box agent harnesses, - adversarial drills that break a cached belief on purpose. Two probe kinds never substitute — scripted - **[R] reachability** shows a control is present and fires; metered **[A] adoption** asks whether a - real model drives it right. Discipline outranks results: a null needs a positive control, outliers - are re-run, and a scripted zero-paid harness records its author, never a model. -- **T2 — current machinery.** `docs/benchmarks/` holds twelve records and four JSON artifacts over the - OOLONG-Pairs datasets and synthetic chronicle, ledger and relational corpora. `src/benchmarks/oolong` - scores set-F1, rejects zero-tool-call answers as `TRELLIS_PROTOCOL_VIOLATION`, re-dispatches thrice - while accumulating discarded cost, and audits cache accuracy; four runners sit behind - `oolong:benchmark` and `drill:update|poison|scale`. Paid probes — effective context, the citation - A/B, the workspace pair — carry **no npm alias by design**, print estimates, and abort at $5. -- **T3 — with receipts.** Run A (`17bc7ba`, 2026-07-02): F1 **1.000 ×20**, `total_cost_usd` - 0.8654850000000001, mean cold sub-calls 0.357; Run B replicated at $0.8115. Update drill: 11/220 - mutated, recall/precision 1.000, $0.7263 versus $0.8002. Poison drill: **mandatory-only recall - 0.000**; p=0.05 recall 1.000 in 62 sweeps, 0.0% false disputes; total $3.27. Scale: max **286** - hashes, 15.32 → 21.81 ms, gate closed, zero paid calls. Effective-context round 4: **0/36 misses** - versus round 3's 7/30, $0.9452; answer channel **255/255** by reference. -- **T4 — the frontier.** Anti-shortcut corpus v2 is pinned zero-paid with **no paid run** — - implemented, not accepted. `TRELLIS_CITATION_ENTAIL` ships gated off. Module #2 missed its criterion - across 50 runs / $2.3981; the citation-discipline module measured unreliable, never landed. Self-edit - T2 failed three runs; two more were blocked at $0.0000. **Headlines remain n=1–2.** Four [[C12]] - instruments ship, each with its own falsifier. `repl_sandbox_drill.py` drives **nine** refusals over - doubles (**exit 0**); its control plants a break behind each and **exits 3**. - `repl_sandbox_s2_probe.py` measures **hardware**, not doubles (**exit 0** five consecutive times on - the AX41; its control swaps the guest mid-run to **exit 3**), and `provision_kata_host.sh` extends - the discipline to *provisioning*. The family's **sharpest control** is `repl_sandbox_s3_probe.py`'s: - the guest answers *itself* byte-identically, so a host-side witness is the **only** possible - detector — parity held and latency *improved* while the witness alone caught it (**exit 3**); - default mode passed six consecutive times. **No CI runs any of the four** — CI runs no pytest at - all — and no host probe can. `scripts/run_adversarial_tests.ts` has neither alias nor caller. - **The instruments were themselves ungated:** `oolong:flywheel-prep` and `drill:reset` ran graph-wide - `DELETE`s over *every* `DERIVED_INSIGHT` edge, not only the benchmark's, against whatever - `NEO4J_URI`/`PG_*` the environment supplied — and `drill:reset` took any doc_key from bare `argv[2]`. - `drill_target.ts` now interposes two gates: a database-resident marker (`drill:mark-target`) deciding - *which* target, and per-act `--confirm-*` flags deciding *whether*, both refusing exit 2 after - echoing a counted plan. `test:drill-gate --negative-control` plants four routes to a wrong database - and **exits 3** when all four are refused. **No live-database round-trip has run** — the marker's - Cypher and SQL are typechecked only. -- **T5 — future plans.** Open: the real TREC import (unattempted: it needs a paid annotation pass and - an unbuilt fetch script); adversarial corpora with contested gold labels; embedding-shortcut corpora; - 10k-question scale sweeps; multi-run variance replacing n=1. Proposed: 2-of-3 consensus writes on - confusable boundaries; re-running the scale drill at 1,000 live hashes; the TTT ladder reusing the - estimation suite, behavioral criteria only. **None scheduled or funded.** - -*Status ledger:* OOLONG harness · v1/v2 corpora · update/poison/scale drills · probe runners — -**shipped, measured**; the sandbox refusal drill, `fuzz_frame.py` and the S2 probe — **[R] only, -outside CI**; the S3 probe — **[R] passed 2026-07-23**, its metered **[A]** fan-out **spent the same -day** (~$0.001); the drill-target gate — **[R] against injected readers only, no live-database -round-trip**; v2 paid run · real TREC · adversarial corpora · variance — **queued-proposed**. -*What those license:* nine refusals and eight planted frame readers are **present and fire** over -doubles; the S2 probe's three claims fired against a real guest **five times on one host — n=5 of -run-to-run variance on identical hardware, which is not a second machine**; the S3 probe's six claims -fired on that same one host, and its falsifier showed the two most trusted of them — parity and -latency — surviving an uncrossed boundary intact. That was the probe stub, not a model driving the -surface right — but **S3's `[A]` fan-out then was** (real `gpt-5.4`, 2026-07-23, five slices correct -across the bridge, metered); the remaining [[C12]] **[A]** halves (S6, GB, GA-eq, ≤$5) stay -**unspent** now that S4's is banked ($0.011, a real model composing the `run_query` facade). Rule -19(c)'s flag now spans **ten** surfaces (`check:repo-surface`, `wiki:check` and `upsum` too) — -`test:drill-gate` is the first inside this class, and it guards the drills, not a corpus. -*Honest note:* "26× at scale" (≈$1,120 vs ≈$40 per 1,000 queries) is an **extrapolation**; no -external baseline run exists here, and `benchmark_logs/` is gitignored. + retires it. It owns the instruments: offline-scorable corpora, black-box agent harnesses, adversarial + drills that break a cached belief on purpose. Two probe kinds never substitute — scripted **[R] + reachability** shows a control present and firing; metered **[A] adoption** asks whether a real model + drives it right. Discipline outranks results: a null needs a positive control, outliers are re-run, a + zero-paid harness records its author, not a model, and every paid run leaves two figures: an estimate + before, a measured actual after. +- **T2 — current machinery.** `docs/benchmarks/` holds twelve records and the four JSON run artifacts + in `artifacts/`, and `data/` carries nine tracked corpus files: three OOLONG-Pairs datasets, two + prose corpora, four drill manifests. `src/benchmarks/oolong` scores set-F1, rejects a zero-tool-call + answer as `TRELLIS_PROTOCOL_VIOLATION`, re-dispatches while accumulating the discarded cost, and + audits cache accuracy; its pair parser reads parenthesis and JSON-bracket notation alike. Four + runners sit behind `oolong:benchmark` and `drill:update|poison|scale`. Paid probes — effective + context, the citation A/B, the workspace pair — carry **no npm alias by design**, print estimates, + and abort at $5. +- **T3 — with receipts.** Run A (`17bc7ba`, 2026-07-02): F1 **1.000 ×20** at **$0.8655**; Run B + replicated at $0.8115. Update drill: 11/220 mutated, invalidation recall and precision **1.000**, + $0.7263 versus $0.8002. Poison drill: **mandatory-only recall 0.000**; at p=0.05, recall 1.000 across + 62 sweeps, 0.0% false disputes, total $3.27. Scale: max **286** hashes, 15.32 → 21.81 ms, zero paid + calls. Effective-context round 4: **0/36 misses** against round 3's 7/30, $0.9452; answer channel + **255/255** by reference. Provenance A/B, 2026-07-26: **24/24 cited hashes refused → none**, 0 → + **220** insights cached, F1 0.800 → 1.000, control **discriminated**, $0.25 estimated / $0.4591 actual. +- **T4 — the frontier.** The instruments themselves needed instrumenting, twice. `oolong:flywheel-prep` + and `drill:reset` once ran graph-wide `DELETE`s against whatever `NEO4J_URI` the environment supplied; + `drill_target.ts` now gates **eight** entrypoints on a database-resident marker plus per-act + `--confirm-*` flags, refusing exit 2 after a counted plan, and `test:drill-gate --negative-control` + **exits 3** when four planted routes are refused. Its marker Cypher has since run live; the Postgres + half stays typechecked only. Then the scorer misread: parentheses-only pair matching scored a valid + JSON answer **0.0** and published it as a reasoning failure. Corpus v2 has **no paid run**; + **headlines remain n=1–2**. +- **T5 — future plans.** Open: the real TREC import, unattempted because the per-question annotations + real TREC lacks need a paid non-deterministic pass; adversarial corpora with contested gold labels; + embedding-shortcut corpora, since v2's paraphrases defeat lexical scans but not semantic similarity; + 10k-question scale sweeps; multi-run variance replacing n=1–2. Proposed: 2-of-3 consensus writes on + confusable boundaries; re-running the scale drill at 1,000 live hashes, its predeclared migration + trigger; the TTT ladder reusing the estimation suite on behavioral criteria only; corpus v2's paid + acceptance run; the marker's Postgres round-trip. **None scheduled or funded.** + +*Status ledger:* OOLONG harness · v1/v2 corpora · update/poison/scale drills · probe runners · the +drill-target gate — **shipped-pinned**; the dated measurement reports — **recorded-research**; corpus v2's +paid acceptance arm — **implemented, not accepted**; prompt module #2 — **rolled back / retired** (owner +retired it on its own numbers: correctness 25/25 in *both* arms, pooled median input tokens 13,240 on +versus 9,217 off; manifest `status: retired`, loader refuses composition, pinned `test:modules` [8]); +real TREC · adversarial corpora · variance · consensus writes — **proposed / design-record**; the +sandbox refusal drill and its S2–S5 probes — **[R] outside CI**, standing shared with [[C12]]. +*What those license:* every headline above rests on n=1 or n=2 and licenses no distribution. The +July-26 provenance A/B is a *finding* rather than noise because its control discriminated on the same +instrument — 24 refusals against none — and its own first arm was blind (F1 1.0 on zero sub-LLM calls, +nothing classified, the guard never fired), published as noise by the report that ran it. The gate's +four refusal paths run against injected readers, so `test:drill-gate` establishes refusal and not a +live round-trip; the one live exercise is the July-26 `--confirm-strip` cold start, Neo4j only. +`scripts/run_adversarial_tests.ts` still has neither alias nor caller, and CI runs no pytest at all. +Rule 19(c)'s flag now spans **sixteen** npm-invokable surfaces; `test:drill-gate` is the first inside +this class, and it guards the drills, not a corpus. +*Honest note:* "26× at scale" (≈$1,120 vs ≈$40 per 1,000 queries) is an **extrapolation** carried from +the cost model, not a measurement; no external baseline run exists here, and `benchmark_logs/` is +gitignored. *Cross-links:* [[C4]] · [[C1]] (measured, not owned) · [[C6]] (flywheel economics) · [[C12]] (owns the sandbox; C10 owns its drill's standing) · [[C11]] (guardrails 7/8/11/15/19/20). - #### C11 — serving surfaces and project governance *Charter: every door through which something outside the Trellis process reaches it, and the written contracts by which the engineering project governs itself. Not the goal loop, the harness, retrieval, @@ -700,219 +755,114 @@ the write path, or the discoverability program.* defaults closed, and closed means the process is byte-identical to one that never had it. Governance separates the substrate's provenance law from ordinary source-control collaboration: a live collaborator outranks the committed record, the record outranks memory, and deprecated compressions - never select work. + never select work. Rule numbers are append-only, because code and other records cite them. - **T2 — current machinery.** One Express app serves `/healthz`, `/metrics`, `/ingest`, `/retrieve` and - the two SSE streams behind an API-key middleware, per-process stream gates, and queue-depth backstops - returning 429. `TRELLIS_A2A_ENABLED` mounts the agent card (pre-auth) and `/a2a/v1` JSON-RPC — - SendMessage, SendStreamingMessage, GetTask, CancelTask-declined — over TTL-bounded Redis task records. - Outbound, `trellis_mcp.py` dials operator-configured stdio and Streamable-HTTP servers, counting MCP - calls separately from provenance-bearing tool calls. Governance: the twenty-three hard rules — five ambient in `AMBIENT.md`, the rest across nine task-type files in `.claude/rules/` — the trunk's authority ordering, the session-governance ruling, the root contract and its checker. + two SSE streams behind API-key middleware, per-process stream gates, and queue-depth backstops + returning 429. `TRELLIS_A2A_ENABLED` mounts the pre-auth agent card and `/a2a/v1` JSON-RPC — + SendMessage, SendStreamingMessage, GetTask, and CancelTask, routed but always refusing as + not-cancelable; seven others typed-declined across two spec codes — over TTL-bounded Redis records, + sharing the agent gate. Outbound, `trellis_mcp.py` dials operator-configured stdio and + Streamable-HTTP servers, counting MCP calls separately from provenance-bearing ones. Governance: + twenty-four numbered rules, six ambient in `AMBIENT.md`, the rest across nine `.claude/rules/` + files, plus the root contract. - **T3 — with receipts.** `264b007` built A2A hand-rolled with Zod, "zero new dependencies", recording `npm test` 468/57 (baseline 419/53), `test:a2a` 46 checks, 9 Compose assertions. `a2119c0` plus `c3b4c39` (#36) built the MCP client on `mcp==1.12.4`, spec revision 2025-06-18, `test:rlm-mcp` 86 checks. `72ac673` (#156) ratified the root contract — caps 32768 / 8192 / 8192 — cut `HANDOFF.md` by - **3,552 lines to 26**, added `check:repo-surface`, negative control exiting 3. `6259766` (#126) - applied the session-governance ruling, whose §2 primacy finding counted the authority sense of one - phrase **once** against six ordinary uses. -- **T4 — the frontier.** **Green again**, and the durable lesson outlived the outage: `5e7295d` - (#159) deleted `docs/density-chain/` while leaving two inbound links, which the - ratified `broken_markdown_link` rule caught — but `AGENTS.md`'s row was stale in plain backticks, - which the checker would **not** have caught even then. `11335e7` (#187) then restructured `AGENTS.md` - into a slim trunk — a directory tree plus a rules/skills/records index routing to `AMBIENT.md` and the - nine `.claude/rules/` leaves — whose tree now rows `src/repl_sandbox/`, closing the omission this - section once flagged. The **asymmetry survives the fix**: the contract governs repository-root names, - never navigation completeness, so nothing detects the *next* missing tree row — the same shape one - level up is [[C13]]'s record↔twin gap. **The byte margin is no longer thin:** the restructure moved - every rule out of `AGENTS.md`, which now sits at **7,659 bytes, 25,109 free** under its 32,768 cap, - and headroom is no longer measured by hand: [[C13]]'s checker reports every governed document's - headroom on every run and ranks the heaviest sections of any that is close, so a governing document - nearing its cap surfaces before it refuses rather than at the refusal. - `normalizeRoute`'s known-route table omits two live routes, - labelling both `unmatched`. The engineering-loop controller is preserved, explicitly not claimed - adopted. `CancelTask` is permanently declined. + **3,552 lines to 26**, and added `check:repo-surface`, whose eleven issue codes include bidirectional + `.env.example`-against-`EnvSchema` parity with two allowed exceptions; **PASS, 0 issues, measured this + session**. `6259766` (#126) applied the session-governance ruling. +- **T4 — the frontier.** `normalizeRoute`'s five-route table omits `/api/agent-stream` always and both + A2A paths whenever the flag is on, labelling each `unmatched`; `API_REFERENCE.md` publishes the same + five, so no check sees the drift. **The asymmetry survives the `AGENTS.md` restructure:** those eleven + codes govern root names, links, deprecation markers and environment parity — never navigation + completeness, so nothing detects the next missing tree row, the same shape one level up as [[C13]]'s + record-against-twin gap. **The byte margin is no longer thin:** 7,659 bytes, 25,109 free under 32,768, + measured this session. `test:a2a` and `test:rlm-mcp` are not CI steps. - **T5 — future plans.** PROPOSED, unsequenced: an inbound MCP server surface letting external hosts call Trellis — one `query` tool over the goal loop, `trellis://kb/node/{hash}` citation resources, byte-identical when unset, API-key parity — carrying five open decisions: read-tool exposure, transports, the adapter seam, the citation-set source (today's result envelope has none), and the SDK - and language. DEFERRED to its own record: the OAuth resource-server posture. Separate record: the - dual client-and-server role. Root-contract changes require prose plus twin, together, with both the - normal and negative-control checks run. + and language, where serving spec 2025-11-25 against the client's pinned 2025-06-18 is deliberate + negotiated skew. DEFERRED to its own record: the OAuth resource-server posture. Separate record: the + dual client-and-server role. Root-contract changes require prose plus twin, both checks run. *Status ledger:* HTTP/SSE API · A2A server · MCP client — **shipped-pinned, byte-identical when off**; -inbound MCP server — **design record, zero implementation** (`TRELLIS_MCP_SERVER_ENABLED` has exactly -one grep hit, inside that record); session-governance scoping and the root contract — **ratified**. -*Honest note:* no `npm test` total was recorded anywhere findable at HEAD, the last commits carrying -counts sitting roughly 120 commits back — **closed 2026-07-23 by measurement: 1,387 passed across 118 -files** with this change's eleven render-gate tests, 1,376 without them (the first measured, the second -subtracted). *Cross-links:* [[C1]] (A2A and the streams are thin +inbound MCP server — **design record, zero implementation** (`TRELLIS_MCP_SERVER_ENABLED` still has +exactly one grep hit, inside that record); session-governance scoping and the root contract — +**ratified**. +*Honest note:* the newest suite total recorded at HEAD is **1,424 vitest tests** (`5b1d0e5`'s +verification block), superseding the 1,387-across-118-files figure this section carried; `65fdb1f` +records no number. *Cross-links:* [[C1]] (A2A and the streams are thin adapters over the goal loop), [[C4]] (MCP results never mint provenance), [[C13]] (the root contract's checker is that class's machinery; this class is what it checks). - #### C12 — the REPL sandbox and isolation program *Charter: the trust boundary around model-authored Python — the isolation backend, the host-side chokepoints, the vsock wire, the handle data-flow rule, the threat model, and the gated build plan. Not the RLM execution model, the doubts machinery it borrows, or the pillar it realises.* -- **T1 — essence.** Model-authored Python here is retrieval-steerable, so it is treated as hostile; - this class owns the boundary between it and the operator's secrets. Invariants: one hardware-isolated - unit per session; credentials outside it; one narrow channel to host chokepoints; identity from the - *listener*, never a frame; and deepest — the code may *address* data but never *hold* it (the handle - data-flow rule). Language-level guards are telemetry, never a boundary. Status: a microVM boots, - holds state, a real model answers a fan-out across the boundary, and a real database query now - crosses it holding a handle rather than a payload, Tier-0 caps the worker from inside, and a - launcher now claims a real VMM or refuses — but the host end of the two outbound channels has no - owner, so this is still not a working sandbox and must not be read as one. Building it cost the same - lesson **three times**: an enforcing surface is only as portable as the mechanism it names — the - vsock peer CID, then in-guest cgroups, then the channel meant to carry the reserved names. +- **T1 — essence.** Model-authored Python is retrieval-steerable, so it is hostile; this class owns the + boundary to the operator's secrets. Invariants: one hardware-isolated unit per session; credentials + outside it; one narrow channel out; identity from the *listener*, never a frame; deepest, code may + *address* data, never *hold* it. Language-level guards are telemetry, never the boundary. A microVM + boots, a real model and a real query cross it, Tier-0 caps the worker from inside, and a launcher + claims a real VMM or refuses — yet no guest supervisor has ever run inside one, so this is not a + sandbox. - **T2 — current machinery.** Execution still runs in-process on `rlms==0.1.3` LocalREPL holding live - credential-bearing clients. Beside it, a host-independent control plane at `src/repl_sandbox/` - (~22 modules against ~22 test files): the frame codec (a declared fuzz target); a transport carrying - BOTH the native `Vsock*` pair and the `HybridVsock*` pair the ratified VMM actually provides; the - guest-supervisor protocol; the handle table and slice algebra; the DB broker with Postgres/Neo4j - backends, a statement inspector (`policy.py`), and a least-privilege role DDL; the LM handler with - byte/rate/spend ledgers and a DLP hook; the capability lifecycle; a CID-keyed audit log; - `KataREPL(IsolatedEnv)`; a `guest_main` entry point binding **native** `AF_VSOCK` (the guest keeps - the kernel-supplied peer CID the host lost); and a `KataLauncher` that gates on a real QEMU - benchmark, then boots — minting a sandbox, owning a containerd namespace and therefore the digest - pull, refusing a shim that exited 0 without a VM, and releasing what it allocated when it does. - Eleven ratified documents. Host-side, driving `ctr` directly: `provision_kata_host.sh` and the S2–S5 - probes. **The composition that binds host chokepoints to a booted guest exists only as a block - hand-written five times across those probes and the CLI selftest — never in the package.** -- **T3 — with receipts.** **G0 lifted 2026-07-22** by owner (`REPL_SANDBOX_BUILD_PLAN.md` §2, The - research-hold gate) under two qualifications: G1 is unsatisfiable on the dev box, and a loopback - double is never a boundary. **S1 closed** — a 12-test conformance pass over installed `rlms==0.1.3` - found **four records marked *(source-confirmed)* that contradict the source**, listed unfixed. - `pytest src/repl_sandbox/tests` → ~924 passed, 5 skipped (the skips are `AF_UNIX`-gated on Windows, - pass under WSL/Linux). The frame red-team's **seven defects** are closed; - `fuzz_frame.py --negative-control` plants **eight** broken readers and **exits 3**. Two upstream - pins, never one: **Kata ≥ 3.31.0 AND Cloud Hypervisor ≥ 52.0**; depth-2 harmful (~96×, external). -- **T4 — the frontier.** All host-observed on one Hetzner AX41, 2026-07-23. **G1 + S2** passed first (real KVM; a guest holding a namespace across five - turns; both upstreams defaulting *away* from the pin, the provisioner converging them). Then **a - correction that moved an enforcing surface**: the records specified an `AF_VSOCK` bind reading the - guest CID at `accept()`, but Cloud Hypervisor runs **hybrid vsock** — host side `AF_UNIX` at - `_`, whose `accept()` carries no peer CID, so "auth by vsock peer CID" is unimplementable - here; identity becomes the per-sandbox socket path the host created (property preserved, surface - moved — `INTERFACES.md` **§3.1a**). **S3 `[R]` PASSED** (six runs, byte-identical parity); **S3 `[A]` - PASSED** ~$0.001, a real `gpt-5.4` over the bridge at flat depth-1; `--cap-halt` proved the - session-terminal dollar stop **and** surfaced a residual — the cap is *between-calls*, so the batch - that trips it runs and bills **upstream** while the refused-not-committed ledger reads $0. **S4 `[R]` - PASSED** the same day: the guest drove `run_query` → opaque handle → `materialize` → the fixture rows - against a real Postgres on the **DB port** (`clh.sock_5002` — §3.1a's convention generalising past - S3's 5001), witness `accepted=5`; a host-side grep found **no credential in the guest** while the - planted canary *was* found (the grep's positive control); the write was denied at **both** layers — - broker `inspect_sql`, **and** Postgres itself refusing a direct read-only-role connection; the - requirement-9 escape primitives denied; teardown clean and the throwaway role dropped. Its negative - control **exits 3** with the witness as the *only* failing claim — after a fix, because the first - fake keyed refusals on "starts with `select`" and let `pg_read_file` through, making the control - catchable by something other than its detector. The host also **intermittently wedges `ctr task - exec`** (~2 in 13 runs), which now reports as "could not run", never as a failed claim. Egress stays - honestly **weak** and self-labels — only `plpgsql` installed, but no Trellis NIC boundary lives in - merged code (that is GB's). **S4 `[A]` PASSED** the same day, $0.011 across three runs: a real - `gpt-5.4`, shown only `CapabilityRegistry.render`'s stubs, **composed `run_query` → `materialize` - itself** and answered a question only the database held (`delacroix`, 9140) — witness `accepted=4`, - credential grep clean with the canary firing, teardown clean. It took **two attempts**, and the - failed one is the finding: the composition was right immediately and the *paramstyle* was not — the - model wrote `?` where psycopg2 wants `%s`, because the descriptor doc never says. It recovered from - the traceback, so INTERFACES §7's error surfacing is what turned the run around; the terse redacted - error is also what forced a guess rather than a read, and that trade is now named. The `--no-db` arm - **DETECTED** (the model could not reach the answer without the tools, so a correct answer is evidence - *about the facade*); the negative control **DETECTED** with the witness as the *sole* failing claim - while every model-visible claim passed. **Authoring it found a live defect in merged code, off-host - at $0**: the stub emitted unset optionals as explicit nulls, so `run_query(sql)` — the natural call - its own rendered signature invites — came back `denied: params must be a list, got NoneType`, - affecting five of ten capabilities; fixed at `capabilities._stub_source`, the rule `guest_rpc` - already applied on the LM port. **A "for the model" rendering that no model has consumed is - unexercised code, however green its tests.** **S5 `[R]` PASSED** the same day (five consecutive - runs, zero flake) and repeated the program's central lesson on a *second* surface: the records named - **in-guest cgroups** for requirement 8, and the guest has no cgroupfs mounted, cannot mount one - (`EPERM`, no `CAP_SYS_ADMIN`), and the host-side cgroup Kata builds for the VM carries neither - `memory.max` nor `pids.max`. The property survives on a different mechanism — `setrlimit` after a - privilege drop, **the drop being load-bearing because root is exempt from `RLIMIT_NPROC`** — and the - correction is `ARCHITECTURE.md` **§2.1**, which the probe re-derives every run so the record's basis - stays executable. Observed: a fork bomb refused at **23 of 24** against **200 uncapped** in the - baseline arm; `unshare` `EPERM` with `Seccomp: 2` read back; a write `EACCES` while reads and the - in-namespace tools survived; **both listeners open at once** (witness `accepted=3`), closing a scope - limit S3 and S4 each carried; a `SIGSTOP`-frozen VM detected in 19.2 s and reaped. **Two** falsifier - arms, both exit 3, because S5 makes two kinds of claim — `--no-harden` removes the enforcement, - `--negative-control` removes the crossing. Recon before authoring is what produced the design; the - sharpest failure was a run that hardened *correctly* and could not prove it, because Landlock had not - granted `/proc` and the read-back of `/proc/self/status` was denied by the ruleset it was verifying. - The shipped filter is a **denylist** where the records said allowlist — recorded, because a true - allowlist for a CPython worker running arbitrary model code is not maintainable. -- **T5 — future plans.** **S6's entry decision is TAKEN, 2026-07-24.** The prerequisite S4 `[A]` found - — `GuestSupervisor` imported `rlm.environments.base_env` and **the guest image carries no rlms** — - is closed by option B: the host reads `RESERVED_TOOL_NAMES` from the *real* pinned package and - passes it in, **required and defaultless**, so no guest module asserts the eight strings on its own - authority and the ≈3.9 MB of driver library stays out of the guest. The sub-question BUILD_PLAN left - open had a **forced** answer, and the forcing is the finding: the pins are built in `__init__` and - every control op reaches a supervisor that already exists, so **the control port cannot carry the - names in time** — they ride with the scaffold instead. Third instance of one shape, after the vsock - peer CID and the cgroups: *the record named a mechanism that cannot carry the property; the property - moves surface.* Tracing it closed a latent drift — `capabilities.py`'s second, hand-typed copy of - the names (guest-side, and legitimately needed there for registration validation) was tied to - nothing, so an upstream move would have reddened one copy and left the other silently wrong. The - **equivalence target is fixed before the harness exists** (`CONFORMANCE §6`), with **twelve clauses - predicted FALSE** — rebinding atomicity on a raising block, `answer`'s initial shape, `SHOW_VARS`' - absence, and nine more — so the spike measures rather than confirms. Also owed: a paramstyle line in - the `run_query` descriptor doc (rule 16 work, so its own change). - Free and scheduled: a **nested guest** as the virgin - instance the provisioner's never-executed install branch is owed; a second *machine* stays - **deferred**, re-opening on a kernel-specific finding (vsock the likeliest, the hybrid correction its - first evidence, the cgroup correction its second). **S6's build half LANDED 2026-07-25**: `boot` - claims a real VMM (G1 ratio 12.7, 34.8 s, socket discovered, package shipped) or refuses and leaves - nothing — proven by blinding the VMM check against a *real* successful `ctr run`. Three findings the - code owes to running: `pgrep` matches its own ancestors, so on a host with **zero** VMs it invents - one; `comm` truncates at 15 chars (`cloud-hyperviso`), so the obvious fix refuses every real boot - and `/proc//exe` is the only sound discriminator; and image stores are per-namespace, so owning - a namespace means owning the digest pull. It stops at `start_bridge`, which **refuses**: the guest - needs no in-guest forwarder (no rlms there), but **who binds the host end of LM/DB is unowned** — a - blind three-seat panel promoted the negative and refused the proposed replacement, and the audit - seat caught the filing omitting `CONFORMANCE §2.1`. The composition is not unbuilt so much as - unhomed: it exists hand-written in five probe/selftest sites, never in the package. Then - GB — which inherits S5's residuals: the watchdog is unproven against a real shim wedge, and the - seccomp/allowlist divergence is recorded rather than resolved — GA-eq, GA-rt. Proposed: - doubt-filter Layers 1–2. **`MAX_FRAME_LEN` RATIFIED 2026-07-24** — slice 2 MiB, frame 4 MiB, frame - derived from slice, invariant `frame ≥ 2 × slice` asserted in `test_config.py`. The ruling corrected - a *layer*, not a number: a context-window derivation had been applied to the frame bound, where it - protects nothing (a 12 MiB namespace value returns a ~4 KB reply — `MarshalCaps` holds attention, - independently) while leaving the frame **below** `max_result_bytes`, so a legal broker result could - not cross the wire. The token rule now sizes the **slice**, as a sizing convention and never an - enforcing bound. **The corpus is bounded by nothing in the config, because it never enters the - guest** — `RLIMIT_AS` bounds the *working set*, and an earlier edition of that same layering table - asked what corpus size address space permits, which puts the corpus in the one place the handle - model says it never is. **A second correction the same day, and the sharper one: `answer.submit(H)` - — the by-reference answer sink two records route bulk content through — DOES NOT EXIST.** `submit` - takes an expression string and renders a value; there is no handle argument and no host-side - resolution. So the doctrine's wholesale hand-off is not capped, it is **unbuilt**, and an unbuilt - escape hatch reads exactly like a built one. Also established: `charge_outbound` is called only for - the `llm_query` prompt, so the answer is **not on the exfil ledger at all**, and THREAT_MODEL - already calls the 64 KiB cap output-shaping *"not a confidentiality or escape control"* — the - collapse lives in DATA_MODEL §6 alone. Still open: handle lifetime, the warm pool, depth-2. The - remaining **[A]** halves (S6, GB, GA-eq) are ≤$5 and **unspent**; S3's and S4's are **banked**. - -*Status ledger:* **control plane shipped; a microVM boots, a frame crosses to it, a real database -query crosses holding a handle, and Tier-0 caps the worker from inside — STILL not a sandbox and must -not be read as one** (egress policy and a production launch path are absent, and `KataLauncher.boot` -raises). Accepted: **SPEC §8 gate 1 (G1), 2026-07-23**. Dated passes that are not gates: spikes S1, -S2, **S3 (`[R]`+`[A]`)**, **S4 (`[R]`+`[A]`)** and **S5 (`[R]`; its Tier-0 is shipped, its watchdog -unproven against a real shim wedge)**. **S6's entry decision is taken and its equivalence target -stated; its build half and both probe halves are unrun.** Gates 2–4 unpassed. -*Reachability:* closed by `host.py`, `cli.py`, the drill, the S2 probe, `provision_kata_host.sh` and -ten `npm` scripts; **no CI job runs any** — `python:check` enumerates `src/rlm/*` only, so the whole -pytest surface is hand-run and the host probes *cannot* run in CI (they need `/dev/kvm`). The hybrid -transport's non-test callers are the S3 `[R]` probe, its `[A]` harness, and the S4 probe — the latter -the first caller of the DB `postgres_backend_from_env` factory and the `broker_handler` DB-port path -(5002; S3 exercised only the LM port, 5001), **now run on one host and nowhere else**. -`KataLauncher.boot` stays uncalled. -*Discoverability:* `AGENTS.md`, `docs/README.md` and `docs/ORIENTATION.md` carry the built/boundary -split, but the latter two are **stale against 2026-07-23** (both still read G1 as unsatisfied; neither -mentions §3.1a); `AGENTS.md`'s tree now rows `src/repl_sandbox/` since the #187 restructure, closing the gap this class flagged. The provisioned host is + credential-bearing clients. Beside it a host-independent control plane, `src/repl_sandbox/`: **26 + modules, 28 test files**. The frame codec; a transport carrying both the native `Vsock*` pair and the + `HybridVsock*` pair the ratified VMM actually provides; the guest-supervisor protocol; handle table + and slice algebra; a DB broker with `inspect_sql` and a `NOSUPERUSER` role DDL; an LM handler with + byte and dollar ledgers, DLP; `KataREPL`; `guest_main` binding **native** `AF_VSOCK`; + `KataLauncher`; and `session_host.open_workspace_session`, the composition layer. Ten capabilities + bind descriptors at the guards that refuse. Host-side: `provision_kata_host.sh`, the S2–S5 probes. +- **T3 — with receipts.** **G0 lifted 2026-07-22** by owner (BUILD_PLAN §2), qualified twice: G1 is + unsatisfiable here, and a loopback double is never a boundary. **S1 closed** — a 13-test conformance + pass over installed `rlms==0.1.3` found **four records the source contradicts** (two marked + *(source-confirmed)*), listed unfixed. `pytest src/repl_sandbox/tests` → **1,153 passed, 5 skipped** + (`AF_UNIX`-gated on Windows). The fuzz harness's first pass found **six** defects, three + over-permissive; `fuzz_frame.py --negative-control` plants **eight** broken readers and **exits 3**. + Two upstream pins, never one: **Kata ≥ 3.31.0 AND Cloud Hypervisor ≥ 52.0**; depth-2 harmful (~96×). + No CI job runs any. +- **T4 — the frontier.** All host-observed on one Hetzner AX41. **G1, S2, S3 `[R]`+`[A]`** (~$0.001); + **S4 `[R]`+`[A]`** ($0.011: a real `gpt-5.4`, given only stubs, composed `run_query` → `materialize`, + answering what only Postgres held; credential grep clean, canary firing; the write denied at broker + *and* Postgres); **S5 `[R]`** (fork bomb refused at **23 of 24** against **200 uncapped**, both + listeners open at once). **2026-07-25:** `boot` claims a real VMM or refuses leaving nothing; the + diagonal ran **7/7**. But `install_scaffold` and `control` still raise, so `KataREPL.setup` cannot + finish over a real guest. Egress self-labels **weak**; the spend cap is between-calls. +- **T5 — future plans.** **S6's equivalence harness is unbuilt**, its **[A]** half unproposed; the + target was fixed ahead of it (`CONFORMANCE §6`, **twelve clauses predicted FALSE**), so the spike + measures rather than confirms. **`MAX_FRAME_LEN` RATIFIED 2026-07-24** — slice 2 MiB, frame 4 MiB, + `frame ≥ 2 × slice` pinned in `test_config.py`. **`answer.submit(H)` DOES NOT EXIST**: `submit` takes + an expression, so the by-reference sink two records route bulk content through is unbuilt, and + `charge_outbound` fires only for the `llm_query` prompt. Then GB, GA-eq, GA-rt; doubt-filter Layers + 1–2; warm pool; handle lifetime; depth-2. Remaining **[A]** halves ≤$5, **unspent**. + +*Status ledger:* the control plane and the launch path — **shipped-pinned** (1,153 pytest checks green; +`fuzz_frame.py`, the drill and each host probe ship a falsifier arm — S5 two, the S3 `[A]` harness's +being `--cap-halt`). The boundary itself — **implemented, not accepted**: **STILL not a sandbox and must +not be read as one**, because NIC egress policy is absent and `KataGuestHandle.install_scaffold` and +`control` raise, so no `GuestSupervisor` has ever run inside a microVM. Accepted: **SPEC §8 gate 1 (G1), +2026-07-23**; gates 2–4 unpassed. Dated passes that are not gates: S1, S2, **S3 (`[R]`+`[A]`)**, **S4 +(`[R]`+`[A]`)**, **S5 (`[R]`)**, S6's build half and the 2026-07-25 diagonal. Doubt-filter Layers 1–2 — +**proposed / design-record**; the S1 conformance contradictions — **recorded-research**. +*Reachability:* `host.py`, `cli.py`, the drill, the S2–S5 probes, `provision_kata_host.sh` and **twelve** +`npm` scripts reach the program; **no CI job runs any** — CI's one Python step is `python:check`, which +enumerates nine `src/rlm/*` files plus five `scripts/` files and no `repl_sandbox` module at all, so the +whole pytest surface is hand-run and the host probes *cannot* run in CI (they need +`/dev/kvm`). `KataLauncher.boot` is **no longer uncalled** — `session_host.open_workspace_session` and +`KataREPL.setup` each call it — but `open_workspace_session` itself has **no non-test caller**, and the +diagonal that exercised it on the AX41 is not committed as a probe script. +*Discoverability:* `AGENTS.md` rows `src/repl_sandbox/`, but this class's own index is now its stalest +surface: `docs/product/repl-sandbox/README.md` still describes the guest as having no vsock channel, no +broker and no Tier-0; `docs/README.md` and `docs/ORIENTATION.md` still read **G1 unsatisfied** and the +handle model as **proposed, unbuilt**; `REPL_SANDBOX_LEARNINGS.md` stops at S5. The provisioned host is reached by the local alias `ssh trellis-kata` — **the address is deliberately absent from this public tree** (BUILD_PLAN §4.1) and the host holds no checkout, so a fact living only there is unrecorded. *Cross-links:* [[C1]] (replaces that substrate, preserving its contract), [[C5]] (the handle model is the pillar as a slicing API), [[C7]] (Layers 1–2 compose the −1 tier), [[C10]] (owns the standing of -the probes this class ships). - +the probes this class ships), [[C13]] (the descriptor mechanism these chokepoints register through). #### C13 — self-describing surfaces and agent-first discoverability *Charter: the machinery and design records by which Trellis explains itself to the agent operating it — the ratified root contract and its deterministic checker, plus the harness self-model, `llm_help` and @@ -1023,8 +973,8 @@ HTML render**, whose data is JS source: one straight apostrophe inside a single- having validated the Markdown and merely *inferred* the render — T4's **exists-implies-named** gap one level down, in this class's own instrument. `4f945ef` (#176) fixed the character by hand while this gate was built; the gate adds only that the class cannot recur -silently — not the same claim as having fixed it. Twenty-five planted -conditions now, up from eighteen. *Orphans:* closed 2026-07-23 — both +silently — not the same claim as having fixed it. Thirty-two planted +conditions now, up from twenty-five. *Orphans:* closed 2026-07-23 — both runtime-half records now carry rows in `docs/ORIENTATION.md` D4. This map's own open item 3 (derivation inverted) is **paid**: `SELF_DESCRIBING_SURFACES.md` §9.1 distinguishes guard-derived from editorial facts under one invariant — *one encoding, owned by whoever is authoritative for the fact*. @@ -1268,8 +1218,10 @@ switched off. CI enforces the contract; the session reports the drift. Satisfaction is a **working-tree edit of this file**, never a committed one — pin the snapshot before the commit that deleted this map and a union predicate scores that deletion as maintenance, then stays -satisfied until someone re-stamps `snapshot_commit`. `--negative-control` plants eight conditions the -gate must detect, including that one, and **exits 3 when healthy**, matching the house convention. +satisfied until someone re-stamps `snapshot_commit`. `--negative-control` plants thirty-two conditions +the gate must detect, including that one, and **exits 3 when healthy**, matching the house convention. +`--budget` is the tier-length half: the declared `tier_budget_words` is read from `index.json`, every +tier must sit inside its band, and no class may end longer than it starts. The house rule the hook enforces: **when a change spans classes, spawn one updating sub-agent per class.** Siblings cannot see each other, so per-class agents cannot smear one subsystem's status onto