From 117cea7a4024cfa718acc520f217be8ee70a43b0 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 21 Sep 2026 00:28:27 +0200 Subject: [PATCH 1/2] test(pre-open): expose unknown decision cause --- tests/unit/pre-open-gate-compact.test.mjs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/unit/pre-open-gate-compact.test.mjs b/tests/unit/pre-open-gate-compact.test.mjs index 422914e9..a721f87d 100644 --- a/tests/unit/pre-open-gate-compact.test.mjs +++ b/tests/unit/pre-open-gate-compact.test.mjs @@ -81,6 +81,19 @@ test("compact pre-open report exposes only authoritative remaining obligations", assert.equal(Object.hasOwn(compact.evidenceRequirements.lenses.silent_failures, "status"), false); }); +test("unknown compact report names the incomplete review-scope cause", () => { + const report = blockedReport(); + report.decision = "unknown"; + report.complete = false; + report.blockers = []; + report.incompleteReasons = ["review_scope:patch_missing"]; + + const compact = compactPreOpenGateReport(report); + assert.equal(compact.decision, "unknown"); + assert.deepEqual(compact.incompleteReasons, ["review_scope:patch_missing"]); + assert.equal(compact.nextAction, "inspect_missing_patch_evidence"); +}); + test("ready compact report has one unambiguous publication disposition", () => { const report = blockedReport(); report.decision = "ready"; From ebe076af7fa905757cea3e9122e36fd20da19c21 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 21 Sep 2026 00:28:30 +0200 Subject: [PATCH 2/2] fix(pre-open): explain incomplete review scope --- scripts/pre-open-gate.mjs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/scripts/pre-open-gate.mjs b/scripts/pre-open-gate.mjs index ea9f347b..70348ef4 100644 --- a/scripts/pre-open-gate.mjs +++ b/scripts/pre-open-gate.mjs @@ -79,6 +79,9 @@ export function evaluate(plan, evidence = null) { } } + const incompleteReasons = (plan?.uncertainty || []) + .filter((item) => item?.blocksCompletion !== false) + .map((item) => `review_scope:${String(item?.code || "unknown")}`); const complete = implementationDiffPresent && plan.complete && bugScope.complete && securityScope.complete; const finalBlockers = implementationDiffPresent ? blockers @@ -97,6 +100,7 @@ export function evaluate(plan, evidence = null) { probeEvidenceErrors: probes.errors, blockers: finalBlockers, clearedByEvidence, + incompleteReasons, decision, complete, implementationDiffPresent, @@ -104,7 +108,7 @@ export function evaluate(plan, evidence = null) { }; } -function report({ repo, baseRef, headRef, baseRefOid, headRefOid, diffIdentity, fileCount, bugScope, securityScope, requiredProbes, probeEvidenceErrors, blockers, clearedByEvidence, decision, complete, implementationDiffPresent, evidenceApplied }) { +function report({ repo, baseRef, headRef, baseRefOid, headRefOid, diffIdentity, fileCount, bugScope, securityScope, requiredProbes, probeEvidenceErrors, blockers, clearedByEvidence, incompleteReasons, decision, complete, implementationDiffPresent, evidenceApplied }) { return { schemaVersion: 1, kind: "github-delivery/pre-open-gate", @@ -125,6 +129,7 @@ function report({ repo, baseRef, headRef, baseRefOid, headRefOid, diffIdentity, probeEvidenceErrors, blockers, clearedByEvidence, + incompleteReasons: Array.isArray(incompleteReasons) ? incompleteReasons : [], instructions: [ "workflow:implementation_missing: this pre-open gate requires a non-empty candidate implementation diff; implement first, then rerun the gate before publication.", "decision=blocked: complete every remaining required bug lens, security surface, and deterministic probe on this branch diff (with --evidence-file), fix Confirmed High/Critical findings, then rerun before opening the PR.", @@ -202,12 +207,17 @@ export function compactPreOpenGateReport(result) { }; } + const incompleteReasons = sortedUnique(result?.incompleteReasons || []); const nextAction = result?.decision === "ready" ? "proceed_to_publication" : result?.decision === "blocked" ? "complete_evidence" - : "restore_branch_evidence"; + : incompleteReasons.includes("review_scope:patch_missing") + ? "inspect_missing_patch_evidence" + : incompleteReasons.some((reason) => reason.startsWith("review_scope:probe_registry_invalid")) + ? "repair_probe_registry" + : "resolve_incomplete_review_scope"; return { schemaVersion: 1, @@ -224,6 +234,7 @@ export function compactPreOpenGateReport(result) { implementationDiffPresent: result?.implementationDiffPresent, evidenceApplied: result?.evidenceApplied, blockerCount: blockers.length, + incompleteReasons, remaining, evidenceRequirements: { schemaVersion: PRE_OPEN_EVIDENCE_SCHEMA_VERSION,