/** * Formation Context — bounded projection of ALREADY-PERSISTED formation * evidence into a peer runner's prompt payload (PRI-838 / PRI-839). * * PRI-835 (Formation Context Connectivity Audit) established the gap this * module closes: the identifiers that link a formation back to its evidence — * `scribe.sourceTrace.dreamerArtifactId`, the dreamer artifact's * `lineageArtifactIds` — are ALREADY persisted and ALREADY reach the runner. * They were simply never resolved into prompt *content*. * * ⇒ This is a CONNECTION fix, not a capability addition: * no new artifact kind, no new storage, no new authority, no feature flag, * no change to any output schema or validator. * * `ArtifactSummary / deriveArtifactSummary` (artifact-summary.ts) is the only * bounded-projection implementation that survived PRI-819 R-06 in this layer, * and this module deliberately mirrors its contracts rather than inventing a * second idiom: * - pure projection over structured output that is already persisted; * - untrusted JSON is read with `Object.hasOwn` + `typeof` / `Array.isArray` * guards — never an `as` cast (rc-1 / rc-2 / rc-5 / ERR-013); * - every emitted value is clamped, and every value dropped by the bound is * accounted for in `truncationNotes` or `omittedFields` (rc-9 — degradation * must be observable, never silent); * - deterministic: identical input yields byte-identical output. * * Deliberately NOT restored: the retired PRI-634 Layer 0/1/2 plane * (`ContextManifest` / `PromptBudgetManager` / `CandidateLineage`). PRI-819 R-06 * removed it for never graduating, and PRI-835 explicitly rules out reviving * it. The budget below is a small, local, explicit cap — not a budget manager. * * Consumers (2, materially different → not a speculative seam): * - Scribe (PRI-838): dreamer proposals + source diagnosis + provenance; * - Artificer(PRI-839): bounded, priority-ranked candidate set + differences. * * @see docs/audit/PRI-835-formation-context-connectivity-audit.md (§DC-1, §DC-3, §6.1 C1/C2) */ import type { PIArtifactStore } from './pi-artifact.js'; export declare const FORMATION_CONTEXT_VERSION = "formation-context.v1"; /** `DreamerOutputV1Schema` allows 1..5 candidates — the bound matches the schema. */ export declare const FORMATION_CANDIDATE_LIMIT = 5; /** Per-field clamp. Mirrors `SUMMARY_FIELD_MAX_CHARS` (artifact-summary.ts). */ export declare const FORMATION_FIELD_MAX_CHARS = 400; export declare const FORMATION_DIAGNOSIS_EVIDENCE_LIMIT = 8; export declare const FORMATION_DIAGNOSIS_VIOLATED_LIMIT = 8; export declare const FORMATION_DIAGNOSIS_RECOMMENDATION_LIMIT = 5; export declare const FORMATION_DREAMER_CONTEXT_REF_LIMIT = 8; /** * Hard cap on the SERIALIZED formation block. The projection is trimmed to fit * it — never truncated mid-JSON — and every dropped item is recorded in * `truncationNotes`. * * PRI-815 Phase A measured the cost of this information channel at +24.9% * tokens for the frozen three-block payload; 8000 chars ≈ 2000 tokens keeps * that proportion for a smaller real-world field mix. */ export declare const FORMATION_TOTAL_MAX_CHARS = 8000; /** * Per-section caps. They exist so the degradation ORDER is sensible: without * them a single oversized diagnosis could only be satisfied by dropping every * candidate, which is the wrong trade (the proposals are the unique content). */ export declare const FORMATION_PROPOSALS_MAX_CHARS = 4000; export declare const FORMATION_DIAGNOSIS_MAX_CHARS = 3500; /** Lineage ids are identity, not content — capped last, and only as a last resort. */ export declare const FORMATION_LINEAGE_ID_LIMIT = 16; /** * Diagnostic stage task kinds that can carry the source diagnosis, in * descending authority. `diag_router` emits the canonical * `DiagnosticianOutputV1`; the earlier stages emit narrower schemas handled by * the tolerant readers below. */ export declare const FORMATION_DIAGNOSIS_TASK_KINDS: readonly ['diag_router', 'diag_distiller', 'diag_rootcause']; /** * One Dreamer proposal, projected and clamped. * * Both orderings are exposed so a consumer never has to guess which one it is * reading: * - `candidateIndex` — the order the Dreamer authored; * - `priorityRank` — a DERIVED 1-based reading aid (see `rankCandidates`). */ export interface FormationCandidateProjection { readonly candidateIndex: number; readonly priorityRank: number; readonly badDecision: string; readonly betterDecision: string; readonly rationale: string; readonly confidence: number | null; readonly riskLevel: string | null; readonly strategicPerspective: string | null; } export interface FormationDiagnosisViolatedPrinciple { readonly principleId: string | null; readonly title: string | null; readonly rationale: string; } export interface FormationDiagnosisEvidence { readonly sourceRef: string; readonly note: string; } export interface FormationDiagnosisProjection { readonly artifactId: string; readonly taskId: string; /** The diagnostic stage this projection came from (`diag_router`, …). */ readonly stage: string; readonly rootCause: string | null; readonly summary: string | null; readonly violatedPrinciples: readonly FormationDiagnosisViolatedPrinciple[]; readonly evidence: readonly FormationDiagnosisEvidence[]; /** `description` of each recommendation, bounded; kind is prefixed inline. */ readonly recommendations: readonly string[]; readonly confidence: number | null; /** Field names the tolerant readers could not resolve (rc-9). */ readonly omittedFields: readonly string[]; } export interface FormationProvenance { readonly sourceDreamerArtifactId: string; readonly sourceDreamerTaskId: string; readonly sourceDiagnosisArtifactId: string | null; readonly sourceDiagnosisTaskId: string | null; readonly sourcePainId: string | null; readonly lineageArtifactIds: readonly string[]; } export interface FormationContext { readonly version: string; /** ALL candidates the Dreamer proposed — never only the selected one. */ readonly dreamerProposals: readonly FormationCandidateProjection[]; /** `DreamerOutput.contextRefs` — the evidence references the Dreamer consumed. */ readonly dreamerContextRefs: readonly string[]; readonly sourceDiagnosis?: FormationDiagnosisProjection; readonly provenance: FormationProvenance; readonly truncationNotes: readonly string[]; } /** * Deterministic, factual summary of how the proposals differ — a bounded * alternative to dumping every candidate verbatim. States only what the * evidence actually shows (count, risk spread, distinct better-decisions); * it never editorialises about which proposal is "best". */ export declare function summarizeCandidateDifferences(candidates: readonly FormationCandidateProjection[]): string; export interface DreamerProjection { readonly candidates: readonly FormationCandidateProjection[]; readonly contextRefs: readonly string[]; readonly sourcePainId: string | null; /** VALID proposals dropped by the candidate bound (malformed entries excluded). */ readonly omittedCandidateCount: number; /** Candidates dropped by the bound and malformed entries skipped (rc-9). */ readonly truncationNotes: readonly string[]; } /** * Project a Dreamer artifact's contentJson into a bounded candidate set. * * Never throws. A malformed candidate is SKIPPED and recorded, so one bad * element cannot discard the whole formation's alternatives. */ export declare function projectDreamerProposals(dreamerContent: Record): DreamerProjection; /** * Tolerant projection over a diagnostic stage artifact. `diag_router` emits the * canonical `DiagnosticianOutputV1`; earlier stages expose a narrower schema, * so unresolvable fields are recorded in `omittedFields` instead of failing. */ export declare function projectDiagnosisOutput(diagnosisContent: Record, identity: { readonly artifactId: string; readonly taskId: string; readonly stage: string; }): FormationDiagnosisProjection; /** Narrow task view — phase identity lives on the task row, never on the artifact. */ export interface FormationTaskView { readonly taskKind: string; readonly status: string; readonly dependencyTaskIds: readonly string[]; } export interface FormationContextResolverParams { /** * Untrusted. The dreamer artifact id the upstream stage copied out of the * philosopher artifact (`philosopher.sourceDreamerArtifactId`). */ readonly sourceDreamerArtifactId: string | undefined; readonly artifactStore: Pick; /** * Resolves a task row (with hydrated PI dependency ids). * * Required because every PI artifact is written with `artifact_kind = * 'principle'` — the stage identity of a lineage artifact exists ONLY on its * task row, so the diagnosis cannot be identified from the artifact alone. */ readonly lookupTask: (taskId: string) => Promise; readonly emitEvent: (eventName: string, taskId: string, payload: Record) => void; /** The consuming task, for event attribution only. */ readonly taskId: string; } /** * Resolve the bounded formation context reachable from a dreamer artifact id. * * Degradation policy (PRI-838 Phase 4 Case 2 — degrade, never fail): * - no dreamer id, or the dreamer artifact cannot be read/parsed * ⇒ returns `undefined` (the caller keeps its previous prompt shape) and * emits an observable event; * - dreamer resolvable but the diagnosis is absent/unreadable * ⇒ returns a context WITHOUT `sourceDiagnosis`, plus a truncation note. * * NEVER throws — including when the artifact store or the task lookup itself * fails. Formation evidence is an enrichment: a store error must not fail a * formation run, so every escaping failure is converted into an observable * event plus `undefined` (rc-9: degradation is never silent). */ export declare function resolveFormationContext(params: FormationContextResolverParams): Promise; //# sourceMappingURL=formation-context.d.ts.map