fix(confidence-engine): supply synthesis output schema
This commit is contained in:
@@ -41,7 +41,8 @@ If YES, the next live experiment is one timed/costed OpenAI UI investigation mea
|
||||
- Current deterministic final-fetch schema remains internally valid, yet the live rejection contradicts it. `CONFIDENCE_ENGINE_EXPERIMENT_TRACE_OPENAI_SCHEMA=1` now emits one safe, server-side structural summary immediately before the OpenAI fetch—no prompt, answer, request body, secret, or model output.
|
||||
- The focused-deconstruction route now emits complementary safe server diagnostics for start, provider success/failure, focused validation, and end status; the OpenAI schema trace remains provider-owned. No user content or secrets are logged.
|
||||
- Canonical focused relationship items are now strict `{ from, to, type }`: all required non-empty strings, free-text `type`, and no `rationale`; `relationships` remains required and may be `[]`. Schema, prompt field names, and validator align; the stale rationale-bearing test fixture was corrected.
|
||||
- Focused and provider deterministic suites pass; the OpenAI projector is unchanged. Zero live calls occurred. Next evidence boundary: live provider compatibility of this same canonical focused contract.
|
||||
- Live Terra focused deconstruction now passes through the real UI, but the following Current Understanding synthesis exposed a separate caller/schema mismatch: its prompt and validator require `{ currentUnderstanding }` while the provider received the default initial-reconstruction schema.
|
||||
- Synthesis now supplies its own output schema as provider argument three; provider implementation is unchanged. Synthesis and provider deterministic suites pass with zero live calls. Next boundary: one isolated live synthesis request using the already captured situationGraph and findings payload.
|
||||
|
||||
## Repository checkpoint
|
||||
|
||||
|
||||
@@ -186,6 +186,15 @@ export const synthesisResponseSchema = z.object({
|
||||
.min(1, "currentUnderstanding must be a non-empty string"),
|
||||
});
|
||||
|
||||
export const synthesisOutputSchema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
currentUnderstanding: { type: "string" },
|
||||
},
|
||||
required: ["currentUnderstanding"],
|
||||
additionalProperties: false,
|
||||
};
|
||||
|
||||
/** Validate raw provider output against synthesis response schema */
|
||||
export function validateSynthesisResponse(raw) {
|
||||
if (raw == null) {
|
||||
@@ -274,7 +283,8 @@ export async function synthesizeCurrentUnderstanding(
|
||||
try {
|
||||
rawResponse = await provider.generateReconstruction(
|
||||
prompt,
|
||||
modelName
|
||||
modelName,
|
||||
synthesisOutputSchema,
|
||||
);
|
||||
} catch (error) {
|
||||
const err = new Error(error.message ?? "Synthesis provider call failed");
|
||||
|
||||
@@ -375,6 +375,12 @@ describe("synthesizeCurrentUnderstanding — full seam", () => {
|
||||
const prompt = fake.generateReconstruction.mock.calls[0][0];
|
||||
expect(prompt).toContain("Complaint count increased by 35%");
|
||||
expect(prompt).toContain("[known]");
|
||||
expect(fake.generateReconstruction.mock.calls[0][2]).toEqual({
|
||||
type: "object",
|
||||
properties: { currentUnderstanding: { type: "string" } },
|
||||
required: ["currentUnderstanding"],
|
||||
additionalProperties: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("supported node content flows to provider via synthesis prompt", async () => {
|
||||
|
||||
Reference in New Issue
Block a user