extraction: the spine stage — cross-stretch assembly between extract and audit

Per-batch pipeline is now extract → spine → audit → merge (owner order,
2026-09-30), the spine inside the serialized audit section so it reads
the graph exactly as the following audit will. Measured motive: 0 of 133
chains in the live corpus crossed a stretch boundary — no stage minted
cross-stretch chains.

- src/agent/subagents/spine.ts: SESSION/NOTES spine preambles + shared
  SPINE_CORE (span doctrine; extraction doctrines carried over), the
  submit_spine TypeBox schema, validateSpine (mechanical span law: every
  chain touches >=1 fresh endpoint AND >=1 existing digest endpoint;
  unknown ids, self-reference, and id collisions are loud), the digest
  prompt builder, and the runner (strong tier, retry-only).
- extraction.ts: 'assembling' phase, spine stage in the per-need gate,
  usage/billing stage, assemble() inside withAuditLock for both front
  doors; first stretch of a source skips the call (empty digest, no
  spend); the audit sees COMBINED propositions (chunk + connectives),
  never chains; merger receives the combined findings.
- core/graph.ts mergeFindings: chain endpoints resolve through the
  job-local map OR pass through verbatim as existing n_ ids (the spine's
  mixed namespace).
- EXTRACTION_CORE: steps-of-reasoning selection bar (examples, notation
  glosses, and restatements that no argument needs are not steps).
- Factory chunk budget 4096 -> 8192 (fewer seams, more local context).
- healStringifiedArrays moved to the shared submit seam (submit-agent.ts).
- Cost panel: Assembly row; usage records carry a spine stage (optional
  on legacy records).
- Tests +5: prompt pins, span-law matrix, digest rendering, seeded
  end-to-end flow (spanning chain + connective, verbatim n_ endpoint,
  spine billed as its own stage), non-spanning refused + retried.
This commit is contained in:
amosblomqvist
2026-09-30 16:38:45 +03:00
parent 5ed724c224
commit 52c02533d1
18 changed files with 787 additions and 87 deletions
+5 -3
View File
@@ -22,8 +22,9 @@ describe("FACTORY_SETTINGS (the compiled factory layer)", () => {
assert.equal(CURRENT_SETTINGS_VERSION, 1);
assert.deepEqual(FACTORY_SETTINGS.general, { autoUpdate: true });
// wave 7 collapse: the master switch ONLY + the extraction-UX
// redesign's chunk budget (2026-09-24) — default = the old config constant
assert.deepEqual(FACTORY_SETTINGS.graph, { enabled: true, extractionChunkTokens: 4096 });
// redesign's chunk budget (2024-09-24); default doubled 8192 with
// the spine stage (owner, 2026-09-30)
assert.deepEqual(FACTORY_SETTINGS.graph, { enabled: true, extractionChunkTokens: 8192 });
const a = FACTORY_SETTINGS.appearance;
assert.equal(a.mode, "dark");
assert.equal(a.background, null); // the mode's own default, not a factory hex
@@ -202,12 +203,13 @@ describe("sanitizeUserSettings", () => {
assert.deepEqual(out.agent?.tools, { quiz: false, demo: true });
});
it("BACKGROUND_MODEL_ROLES matches the eight background roles (practice trio added, owner 2026-09-29)", () => {
it("BACKGROUND_MODEL_ROLES matches the nine background roles (spine added 2026-09-30; practice trio 2026-09-29)", () => {
assert.deepEqual([...BACKGROUND_MODEL_ROLES], [
"researcher",
"demoBuilder",
"visualMaker",
"extractor",
"spine",
"auditor",
"partitioner",
"problemGenerator",