Files
confidence-engine/docs/orchestrator-contract.md
T

7.5 KiB

Orchestrator Contract — Confidence Engine v0.4

1. Exported Function Signatures & Shape (JavaScript)

lib/analysis.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

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

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

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/archive/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 docs/archive/v0.4-handoff.md) 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.