Feature/product platform foundation v0.62 #1
@@ -33,10 +33,13 @@ export async function POST(request) {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Invoke domain seam with provider resolution ───────────
|
||||
// ── Invoke domain seam with configured model ──────────────
|
||||
const result = await synthesizeCurrentUnderstanding(
|
||||
{ situationGraph, findings },
|
||||
{ provider: getProvider() }
|
||||
{
|
||||
provider: getProvider(),
|
||||
modelName: process.env.OLLAMA_MODEL ?? null,
|
||||
}
|
||||
);
|
||||
|
||||
return Response.json({ success: true, currentUnderstanding: result.currentUnderstanding }, { status: 200 });
|
||||
|
||||
@@ -2845,3 +2845,58 @@ Fix synthesis route to pass `modelName: process.env.OLLAMA_MODEL`; then integrat
|
||||
#### Exact first trace question
|
||||
|
||||
What is the minimal server-side fix to the synthesis route so it passes `modelName` to `synthesizeCurrentUnderstanding`, enabling live CU reconstruction verification?
|
||||
|
||||
---
|
||||
|
||||
## v0.50 — FOCUSED-FINDING SYNTHESIS TRIGGER (2026-08-31)
|
||||
|
||||
### Model-resolution repair — CLOSED
|
||||
|
||||
The synthesis route now supplies the configured `OLLAMA_MODEL` and the domain resolves explicit dependency / config / environment model with correct priority.
|
||||
|
||||
**Changes:**
|
||||
- `app/api/cases/synthesis/route.js` — passes `modelName: process.env.OLLAMA_MODEL ?? null` to `synthesizeCurrentUnderstanding`
|
||||
- `lib/graph/current-understanding-synthesis.js` — resolves modelName by priority: explicit dep > config dep (assertConfig) > process.env > null
|
||||
- `tests/graph/current-understanding-synthesis.test.js` — two new tests confirming configured model resolution and explicit override
|
||||
|
||||
**Deterministic gate:**
|
||||
- synthesis + route tests: 54/54 PASS
|
||||
- focused integration tests: 19/19 PASS
|
||||
- build: PASS (pre-existing reasoning-workspace warning unchanged)
|
||||
|
||||
**Direct API evidence:**
|
||||
- small canonical fixture → HTTP 200
|
||||
- exact persisted onboarding investigation:
|
||||
- 13 nodes, 10 edges, 21 canonical Findings
|
||||
- 21,301-byte request
|
||||
- → HTTP 200 in 46.181s
|
||||
- → coherent reconstructed CU
|
||||
- → no Evidence append/repetition observed
|
||||
|
||||
**Static ownership:**
|
||||
- one successful focused deconstruction owns one synthesis call
|
||||
- no automatic duplicate synthesis
|
||||
- newly derived Findings are included explicitly
|
||||
- HTTP synthesis failure does not propagate into focused-deconstruction error handling
|
||||
- no static lifecycle defect was proved
|
||||
|
||||
**Final live runtime (classification RUN-A):**
|
||||
- one focused deconstruction → HTTP 200
|
||||
- exactly one `/api/cases/synthesis` request → HTTP 200
|
||||
- Current Understanding visibly replaced
|
||||
- newly submitted evidence incorporated
|
||||
- generic workspace error absent
|
||||
|
||||
### NEXT BOUNDED ISSUE (for future reference)
|
||||
|
||||
#### Name
|
||||
|
||||
Focused → global integration — carry synthesized understanding back through case/update path and persist across cold return.
|
||||
|
||||
#### Next branch
|
||||
|
||||
to be determined
|
||||
|
||||
#### Exact first trace question
|
||||
|
||||
How does the reconstructed Current Understanding from synthesis reach the ScenarioForm state on cold return without re-fetching or losing narrative continuity?
|
||||
|
||||
@@ -213,11 +213,20 @@ export async function synthesizeCurrentUnderstanding(
|
||||
throw new Error("Invalid dependency: provider must have generateReconstruction");
|
||||
}
|
||||
|
||||
// Resolve configured model: explicit dep > config dep (assertConfig) > process.env > null
|
||||
let modelName = dependencies.modelName;
|
||||
if (modelName == null && dependencies.config?.OLLAMA_MODEL != null) {
|
||||
modelName = dependencies.config.OLLAMA_MODEL;
|
||||
}
|
||||
if (modelName == null) {
|
||||
modelName = process.env.OLLAMA_MODEL ?? null;
|
||||
}
|
||||
|
||||
let rawResponse;
|
||||
try {
|
||||
rawResponse = await provider.generateReconstruction(
|
||||
prompt,
|
||||
dependencies.modelName ?? null
|
||||
modelName
|
||||
);
|
||||
} catch (error) {
|
||||
const err = new Error(error.message ?? "Synthesis provider call failed");
|
||||
|
||||
@@ -384,6 +384,50 @@ describe("synthesizeCurrentUnderstanding — full seam", () => {
|
||||
).rejects.toThrow(/OLLAMA_BASE_URL/);
|
||||
});
|
||||
|
||||
|
||||
// ── Configured model resolution ──────────────────────────
|
||||
|
||||
it("default synthesis path resolves configured modelName — provider receives non-null", async () => {
|
||||
const fake = makeFakeProvider();
|
||||
|
||||
// Stub the configured model so test does not depend on dev-machine .env.local
|
||||
const savedModel = process.env.OLLAMA_MODEL;
|
||||
process.env.OLLAMA_MODEL = "configured-model-v0.50";
|
||||
|
||||
try {
|
||||
const result = await synthesizeCurrentUnderstanding(
|
||||
{ situationGraph: canonicalGraph, findings: [] },
|
||||
{ provider: fake }
|
||||
);
|
||||
|
||||
expect(result.currentUnderstanding).toBe("Synthesized output");
|
||||
|
||||
// KEY ASSERTION: configured model must flow to provider
|
||||
const receivedModel = fake.generateReconstruction.mock.calls[0][1];
|
||||
expect(receivedModel).toBeDefined();
|
||||
expect(receivedModel).not.toBeNull();
|
||||
expect(typeof receivedModel).toBe("string");
|
||||
expect(receivedModel.length).toBeGreaterThan(0);
|
||||
} finally {
|
||||
// Restore original env value (may be undefined)
|
||||
if (savedModel == null) {
|
||||
delete process.env.OLLAMA_MODEL;
|
||||
} else {
|
||||
process.env.OLLAMA_MODEL = savedModel;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("explicit modelName dependency overrides default — provider receives injected model", async () => {
|
||||
const fake = makeFakeProvider();
|
||||
await synthesizeCurrentUnderstanding(
|
||||
{ situationGraph: canonicalGraph, findings: [] },
|
||||
{ provider: fake, modelName: "test-model-v0.50" }
|
||||
);
|
||||
|
||||
expect(fake.generateReconstruction.mock.calls[0][1]).toBe("test-model-v0.50");
|
||||
});
|
||||
|
||||
// ── Provider sees full graph, not just centralStatement ───
|
||||
|
||||
it("provider receives full canonical graph content (nodes + edges + centralStatement)", async () => {
|
||||
|
||||
Reference in New Issue
Block a user