From ccc3dc772e1e5e336bc00b8a5b9c41033e79210a Mon Sep 17 00:00:00 2001 From: mptyl Date: Thu, 13 Aug 2026 11:38:00 +0200 Subject: [PATCH] fix: generate FK candidates through the full run before schema accept (P5) --- backend/scripts/p5-acceptance.mjs | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/backend/scripts/p5-acceptance.mjs b/backend/scripts/p5-acceptance.mjs index eb601db5..23b0bd2e 100644 --- a/backend/scripts/p5-acceptance.mjs +++ b/backend/scripts/p5-acceptance.mjs @@ -1216,30 +1216,24 @@ async function realChecks(ctx) { { id: "accept_happy_path", async run() { - // 1) introspect the physical schema, then mine FK candidates from SQL. - await runThothctlJson(ctx, "preprocess-dwh-filesystem", ["workspace", "preprocess", "dwh", "--workspace", "p2-filesystem"], 0); - const sqlPath = join(ctx.run.root, "fixtures", "p2-filesystem.sql"); - await atomicWrite(sqlPath, "SELECT v.id FROM dw.visits v JOIN dw.patients p ON v.patient_id = p.patient_id\n"); - const suggest = await runThothctlJson(ctx, "schema-suggest-filesystem", ["workspace", "schema", "suggest-fks", "--workspace", "p2-filesystem", "--from-sql", sqlPath], 3); - assert(suggest.payload.code === "manual_review_required", "suggest did not block"); - assert(typeof suggest.payload.suggestedFksYaml === "string" && suggest.payload.suggestedFksYaml.length > 0, "suggested FK YAML missing"); - const digest = suggest.payload.artifactIdentities?.[0]?.digest; + // 1) a fresh full run introspects the DWH, mines FK candidates, and blocks for review. + const full = await runThothctlJson(ctx, "preprocess-run-fs-blocked", ["workspace", "preprocess", "run", "--workspace", "p2-filesystem"], 3); + assert(full.payload.code === "manual_review_required", `full run did not block: ${full.payload.code}`); + const digest = full.payload.artifactIdentities?.[0]?.digest; assert(/^sha256:[0-9a-f]{64}$/.test(digest ?? ""), "candidate digest missing"); - assert(`sha256:${sha256(suggest.payload.suggestedFksYaml)}` === digest, "candidate digest mismatch"); - state.runId = suggest.payload.runId; - assert(/^[0-9a-f]{32}$/.test(state.runId ?? ""), "suggest run id missing"); + state.runId = full.payload.runId; + assert(/^[0-9a-f]{32}$/.test(state.runId ?? ""), "run id missing"); - // 2) The curator's reviewed blob is already the committed empty set (no approved FKs); the - // operator records the human review with the explicit accept command. + // 2) the operator records the human review with the explicit accept command. const accepted = await runThothctlJson(ctx, "schema-accept-filesystem", ["workspace", "schema", "accept", "--workspace", "p2-filesystem", "--run", state.runId, "--yes"], 0); assert(accepted.payload.status === "succeeded" && accepted.payload.code === "ok", "schema accept failed"); assert(Array.isArray(accepted.payload.artifactIdentities), "accept artifact identities missing"); - // 3) Same-revision resume continues through the FK gate and stops at filesystem Evidence. + // 3) same-revision resume continues through the FK gate and stops at filesystem Evidence. const resumed = await runThothctlJson(ctx, "preprocess-run-fs-resume", ["workspace", "preprocess", "run", "--workspace", "p2-filesystem", "--resume", state.runId], 3); - assert(resumed.payload.code === "evidence_materialization_required", "resume did not pass the FK gate and block on filesystem Evidence"); + assert(resumed.payload.code === "evidence_materialization_required", `resume code mismatch: ${resumed.payload.code}`); state.acceptedCommit = state.initialCommit; - return { commands: ["thothctl"], artifacts: [...suggest.artifacts, ...accepted.artifacts, ...resumed.artifacts, await fileArtifact(ctx.run.root, "fixtures/p2-filesystem.sql")] }; + return { commands: ["thothctl"], artifacts: [...full.artifacts, ...accepted.artifacts, ...resumed.artifacts] }; }, }, {