fix(confidence-engine): enforce openai strict object invariants
This commit is contained in:
@@ -37,7 +37,8 @@ If YES, the next live experiment is one timed/costed OpenAI UI investigation mea
|
||||
|
||||
- The OpenAI provider now honors a caller-supplied structured-output schema, applying its existing strict-schema transport projection; absent an alternate schema, initial reconstruction retains its existing strict schema and transport normalization.
|
||||
- The next live run exposed incomplete recursive strict projection: OpenAI rejected `relationships.items` because it lacked `additionalProperties: false`. The projector now recognizes every `type: "object"` node, including property-less objects in array items, and recursively enforces strict object schemas while preserving initial-reconstruction optionality/nullability behavior.
|
||||
- This deterministically fixes the focused-deconstruction transport failures. Provider and focused-route suites pass with zero live calls.
|
||||
- The latest Terra request then exposed an inconsistent root `properties`/`required` contract. The projector now derives `required` after projection from the surviving property keys, and recursive tests verify `properties`, `required`, and `additionalProperties` consistency. Property-less object strictness and initial-reconstruction transport behavior remain preserved.
|
||||
- Provider and focused-route suites pass with zero live calls.
|
||||
- Next boundary: retry one fresh real Playwright-driven OpenAI/Terra investigation; do not reuse the failed focused-deconstruction attempt.
|
||||
|
||||
## Repository checkpoint
|
||||
|
||||
+1
-1
@@ -171,7 +171,6 @@ function projectOpenAIStrictSchema(schema, zodSchema, rootSchema, visited) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (resolved.properties) resolved.required = Object.keys(resolved.properties);
|
||||
resolved.additionalProperties = false;
|
||||
}
|
||||
|
||||
@@ -182,6 +181,7 @@ function projectOpenAIStrictSchema(schema, zodSchema, rootSchema, visited) {
|
||||
for (const [key, property] of Object.entries(resolved.properties)) {
|
||||
projectOpenAIStrictSchema(property, shape?.[key], rootSchema, visited);
|
||||
}
|
||||
resolved.required = Object.keys(resolved.properties);
|
||||
}
|
||||
for (const branch of [
|
||||
...(resolved.anyOf ?? []),
|
||||
|
||||
@@ -190,6 +190,30 @@ describe("OllamaLlmProvider chat capability detection", () => {
|
||||
});
|
||||
|
||||
describe("OpenAI reconstruction provider experiment seam", () => {
|
||||
function assertStrictObjectInvariant(schema, root = schema, visited = new Set()) {
|
||||
if (!schema || typeof schema !== "object" || visited.has(schema)) return;
|
||||
visited.add(schema);
|
||||
|
||||
if (schema.properties) {
|
||||
expect(schema.additionalProperties).toBe(false);
|
||||
expect(new Set(schema.required)).toEqual(new Set(Object.keys(schema.properties)));
|
||||
Object.values(schema.properties).forEach((property) =>
|
||||
assertStrictObjectInvariant(property, root, visited),
|
||||
);
|
||||
}
|
||||
if (schema.items) assertStrictObjectInvariant(schema.items, root, visited);
|
||||
for (const branch of [
|
||||
...(schema.anyOf ?? []),
|
||||
...(schema.oneOf ?? []),
|
||||
...(schema.allOf ?? []),
|
||||
]) {
|
||||
assertStrictObjectInvariant(branch, root, visited);
|
||||
}
|
||||
for (const definition of Object.values(schema.$defs ?? schema.definitions ?? {})) {
|
||||
assertStrictObjectInvariant(definition, root, visited);
|
||||
}
|
||||
}
|
||||
|
||||
it("projects canonical optional fields as required but nullable", () => {
|
||||
const nativeSchema = z.toJSONSchema(reconstructionV2Schema);
|
||||
const projectedSchema = createOpenAIStrictSchema(
|
||||
@@ -351,6 +375,10 @@ describe("OpenAI reconstruction provider experiment seam", () => {
|
||||
relationships: [],
|
||||
possibleFollowUpQuestions: [],
|
||||
});
|
||||
expect(new Set(schema.required)).toEqual(new Set(Object.keys(schema.properties)));
|
||||
expect(schema.properties).toHaveProperty("relationships");
|
||||
expect(schema.required).toContain("relationships");
|
||||
assertStrictObjectInvariant(schema);
|
||||
});
|
||||
|
||||
it("recursively projects arbitrary nested object schemas as strict", () => {
|
||||
|
||||
Reference in New Issue
Block a user