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:
@@ -5,9 +5,6 @@
|
||||
* schema-invalid call). The submitted value is captured from the execute
|
||||
* seam, which only fires on a schema-valid call — the ??-fill (the old zod
|
||||
* defaults) applies at the capture.
|
||||
*
|
||||
* Extraction passes its own weak-model argument heal (healStringifiedArrays)
|
||||
* through `prepareArguments`; the default is identity pass-through.
|
||||
*/
|
||||
|
||||
import type { Usage } from "@earendil-works/pi-ai";
|
||||
@@ -18,6 +15,34 @@ import type { ModelRole } from "../../../config.ts";
|
||||
import type { PiEngine } from "../models.ts";
|
||||
import { runSubagent } from "./pi-run.ts";
|
||||
|
||||
// ── the weak-model string-heal (owner, 2026-09-28; moved here from
|
||||
// extraction.ts with the spine stage, 2026-09-30 — the heal is wire-format
|
||||
// medicine shared by every submit agent) ──
|
||||
//
|
||||
// OpenRouter log evidence: weak models under a big submit payload often
|
||||
// emit a whole array as ONE JSON-STRING instead of a native array
|
||||
// ("propositions.0: must be object"). pi-agent-core runs
|
||||
// `prepareArguments` BEFORE TypeBox validation — the sanctioned shim
|
||||
// point (same doctrine as restoreMathEscapes at the display seam: heal
|
||||
// weak-model wire behavior, don't punish it with a retry). Best-effort:
|
||||
// heal only a string that parses to an array; anything else passes
|
||||
// through untouched and fails validation exactly as before.
|
||||
export function healStringifiedArrays(raw: unknown): unknown {
|
||||
if (typeof raw !== "object" || raw === null) return raw;
|
||||
const out: Record<string, unknown> = { ...(raw as Record<string, unknown>) };
|
||||
for (const key of ["propositions", "chains"]) {
|
||||
const v = out[key];
|
||||
if (typeof v !== "string" || v.trim().length === 0) continue;
|
||||
try {
|
||||
const parsed: unknown = JSON.parse(v);
|
||||
if (Array.isArray(parsed)) out[key] = parsed;
|
||||
} catch {
|
||||
// not a clean stringify (e.g. truncated) — leave for validation
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export async function runSubmitAgent<T>(opts: {
|
||||
role: ModelRole;
|
||||
toolName: string;
|
||||
|
||||
Reference in New Issue
Block a user