# Orchestrator Contract — Confidence Engine v0.4 ## 1. Exported Function Signatures & Shape (JavaScript) ### lib/analysis.js ```js export async function analyseScenario(scenario, opts = {}) // @param {string} scenario // @param {{ promptVersion?: "v0.2" | "v0.3" }} [opts] // @returns {Promise<{ success: boolean, validationStatus: "valid"|"invalid", // modelName: string|null, responseDurationMs: number, rawResponse: string|null, // promptVersion: string|null, inputClassification: object|null, reconstruction: object|null, // evidence: object[]|undefined, nextQuestion: string|undefined, errors: string[]|undefined, // error: string|undefined, statusCode: number|undefined }>} export const PROMPT_VERSIONS // { [key: string]: string } export const DEFAULT_PROMPT_VERSION // "v0.2" ``` ### lib/graph/schema.js ```js export const SituationKind // { observation, reported_claim, metric, state, transition, relationship, assumption, unknown, conclusion } export const SituationStatus // { known, unknown, provisional, supported, weakened, contradicted, resolved } export const ConfidenceLevel // { low, medium, high } export const SituationRelationship // { supports, weakens, contradicts, depends_on, causes, may_cause, measures, compares_with, updates, other } export const situationNodeSchema // Zod → {@typedef SituationNode} export const situationEdgeSchema // Zod → {@typedef SituationEdge} export const situationGraphSchema // Zod → {@typedef SituationGraph} export const graphUpdateSchema // Zod → {@typedef GraphUpdate} export const startCaseRequestSchema // { scenario: string (1-10000), promptVersion?: string } export const updateCaseRequestSchema// { situationGraph: SituationGraph, previousQuestion: string, answer: string (1-5000), promptVersion?: string } /** @param {string} label */ /** @returns {string} */ export function makeNodeId(label) /** @param {{ id?, label, description, kind?, status?, confidence?, value?, unit?, ... }} opts */ /** @returns {SituationNode} */ export function makeNode(opts) /** @param {{ id?, fromNodeId, toNodeId, relationship?, confidence?, description? }} opts */ /** @returns {SituationEdge} */ export function makeEdge(opts) /** @param {{ centralStatement?, nodes?, edges?, activeUnknownNodeId?, resolvedNodeIds?, currentSummary? }} opts */ /** @returns {SituationGraph} */ export function makeGraph(opts) ``` ### lib/graph/utils.js ```js export function validateGraphReferences(graph) // → { valid: boolean, errors: string[] } export function detectDuplicateNodeIds(nodes) // → { nodeId, count }[] export function detectDuplicateEdges(edges) // { edgeId, fromNodeId, toNodeId, relationship }[] export function findDependentNodes(graph, nodeId) // → string[] (transitive) export function findAffectedNodes(graph, nodeId) // → string[] (direct + indirect via affects/dependsOn) /** @param {SituationGraph} graph */ /** @param {string} nodeId */ /** @param {string} newStatus */ /** @param {*} newValue */ /** @param {string} reason */ export function resolveUnknownNode(graph, nodeId, newStatus, newValue, reason) // → { success, error?, previousStatus?, newStatus?, previousValue?, newValue?, reason?, affectedNodes? } export function selectActiveUnknownCandidate(graph, resolvedNodeIds) // → { nodeId, label, score } | null /** @param {SituationGraph} graph */ /** @param {GraphUpdate} update */ export function applyGraphUpdate(graph, update) // → { success: boolean, errors?, nodes?, edges?, resolvedNodeIds? } /** @param {SituationGraph} graph */ /** @param {GraphUpdate} update */ export function validateGraphUpdate(graph, update) // → { valid: boolean, errors: string[] } ``` ### lib/graph/builder.js ```js export function buildInitialGraph(analysisData) // @param {{ reconstruction, evidence? }} → { nodes: SituationNode[], edges: SituationEdge[] } export function buildMinimalGraph(scenario) // @param {string} → { nodes, edges } export function describeGraph(graph) // @param {{ nodes, edges }} → string (summary text) ``` ## 2. Dependencies Between Files ``` lib/analysis.js ├── getConfig() from lib/config.js ├── getProvider() from lib/llm/provider.js [EXTERNAL] ├── buildPrompt() from lib/reconstruction/prompt.js └── reconstructionV2/V1Schema from lib/reconstruction/schema.js lib/graph/utils.js ← imports situationNodeSchema, situationEdgeSchema, situationGraphSchema from schema.js lib/graph/builder.js ← imports situationNodeSchema, situationEdgeSchema, makeNodeId from schema.js docs/v0.4-handoff.md → references CaseOrchestrator.startCase()/updateCase() (not in any inspected file) ``` ## 3. Side Effects (LLM Calls) | Function | LLM Call? | Details | |---|---|---| | `analyseScenario()` | **Yes** | `provider.generateReconstruction(prompt, model)` — POST to configured LLM. Prompt from `buildPrompt(scenario, version)`. | | All graph functions (`schema.js`, `utils.js`, `builder.js`) | No | Pure/deterministic only. | | `startCase()` / `updateCase()` (per handoff) | **Yes** | startCase: calls analyseScenario. updateCase: calls LLM via buildUpdatePrompt context + provider for GraphUpdate, then applyGraphUpdate(). | ## 4. Minimal Proposed Contract for API Functions ### startCase(body) - **Input:** `{ scenario: string (1-10000), promptVersion?: string }` — validated by `startCaseRequestSchema`. - **Flow:** validate → `analyseScenario()` → if ok, `buildInitialGraph(result)`; on failure return minimal graph via `buildMinimalGraph()`. - **Output (success):** `{ success: true, graphSummary: string, nodeCount: number, edgeCount: number, activeUnknownNodeId: string|undefined, nextQuestion: string }` - **Output (failure):** `{ success: false, error: string, graphSummary: string, nodeCount: number, edgeCount: number }` ### updateCase(body) - **Input:** `{ situationGraph: SituationGraph, previousQuestion: string (1+), answer: string (1-5000), promptVersion?: string }` — validated by `updateCaseRequestSchema`. - **Flow:** validate → `buildUpdatePrompt(ctx)` → LLM call for GraphUpdate proposal → `validateGraphUpdate()` → `applyGraphUpdate()` → resolve unknowns via `resolveUnknownNode()` → pick next candidate via `selectActiveUnknownCandidate()`. - **Output (success):** `{ success: true, graphSummary: string, nodeChanges: { added, updated, removed }, edgeChanges: { added, removed }, resolvedNodes: string[], nextQuestion: string|null }` - **Output (failure):** `{ success: false, error: string, graphSummary: string, nodeChanges: {}, edgeChanges: {}, resolvedNodes: [], nextQuestion: null }` ## 5. Missing Interfaces — TODO 1. **[TODO]** `CaseOrchestrator` class described in handoff but absent from all five inspected files. startCase()/updateCase() wrappers need implementation per above contract. 2. **[TODO]** `buildUpdatePrompt(ctx)` (per handoff lives in prompt-builder.js) — not reviewed; input/output needs a separate doc once the file is available. 3. **[TODO]** LLM provider interface (`getProvider()`, `generateReconstruction(prompt, model)`) — external dependency. Assumes rawResponse is parseable JSON matching v0.2/v0.1 schema; needs explicit contract. 4. **[TODO]** Error handling for updateCase() on malformed LLM JSON — handoff notes "generic 500"; needs structured retry/error contract. 5. **[TODO]** Completion heuristic `getCompletionStatus()` referenced in handoff but absent; needs contract (e.g., "complete" when no unresolved unknown nodes). --- *End of contract.*