From 324145c1e16fd0e0812367db7bd1f0d20b92b66a Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Sun, 23 Aug 2026 10:18:50 -0700 Subject: [PATCH] test: repair engine fixtures that predate shipped product guards The engine suite's failures are not independent bugs; they are a handful of systemic drifts where a guard shipped and its fixtures were never updated. - Required pre-merge gates (FN-158): the door refuses a card whose enabled optional groups produced no result, and the built-in workflow enables Plan and Code Review by default. Merge-mechanics fixtures now declare an explicit empty list, stating the intent they always had. group-merge-coordinator's "post-Code-Review member" instead gets real PASSING workflowStepResults, because recording the pass is what that fixture actually means. - Branch-write provenance: the shared reliability fixture creates a task with a branch, which now requires an explicit origin. It stands in for an engine-created branch, so it says so. - updateTaskAtomic: a production write seam missing from several fake stores, copied from the faithful fake in merger-ai.test.ts. - Durable-write inventory: eight unclassified TaskStore surfaces classified, including the two batched reads this branch added. - workflow-graph-merge-region-collapse asserted completion-summary AFTER code-review; the IR wires it before, and production logs agree. merger-ai.test.ts alone goes 37 -> 0. Engine failures 288 -> ~200. Also records a first-sighting suite-only flake in the observed register per the standing rule, rather than quarantining a file with substantial coverage. Co-Authored-By: Claude Opus 5 --- .../suite-only-flakes-observed-register.md | 28 +++++++++++++++++++ .../_merge-durable-write-callsites.ts | 21 ++++++++++++++ .../__tests__/agent-activity-writers.test.ts | 5 ++++ .../__tests__/group-merge-coordinator.test.ts | 18 ++++++++++++ .../src/__tests__/merger-ai-cleanup.test.ts | 13 +++++++++ .../merger-ai-push-after-merge.test.ts | 13 +++++++++ .../__tests__/merger-ai-squash-gates.test.ts | 5 ++++ .../engine/src/__tests__/merger-ai.test.ts | 10 +++++++ ...non-executor-run-audit-sink-health.test.ts | 6 +++- .../reliability-interactions/_helpers.ts | 8 ++++++ ...rkflow-graph-merge-region-collapse.test.ts | 9 +++++- .../workspace-merger-deps-resilient.test.ts | 5 ++++ .../workspace-merger-idempotency.slow.test.ts | 5 ++++ .../__tests__/workspace-merger-lease.test.ts | 5 ++++ .../workspace-merger-scope-gates.test.ts | 6 ++-- .../src/__tests__/workspace-merger.test.ts | 5 ++++ 16 files changed, 157 insertions(+), 5 deletions(-) diff --git a/docs/solutions/test-failures/suite-only-flakes-observed-register.md b/docs/solutions/test-failures/suite-only-flakes-observed-register.md index c288bcd7ac..3e9df6383a 100644 --- a/docs/solutions/test-failures/suite-only-flakes-observed-register.md +++ b/docs/solutions/test-failures/suite-only-flakes-observed-register.md @@ -451,3 +451,31 @@ AssertionError: expected [ 'approved', 'created' ] to deeply equal [ 'created', This resolves the previously unclassified “unrelated satellite-store ordering failure” mentions in entry 1's 12-worker verification table, entry 2's 12-worker verification table, and entry 11's FN-9129 4-worker run table. Those sightings are now classified separately from their entries' identity and DDL investigations. **Terminal negative 2026-08-17 (FN-9131):** The reproduced 27-worker PostgreSQL-directory symptom was investigated with a cluster-shared connection-budget primitive. The first harness wiring and a follow-up that queued registry over-subscription while retaining leases both made the loaded run worse (135 failed files in 174.1s, then 144 failed files in 223.3s); the subject itself was not the only failure. The harness wiring was reverted, the primitive remains characterized independently, and FN-9139 owns a setup-safe admission boundary. No quarantine, timeout change, test retry, skip, worker cap, or assertion change was made. + +--- + +## Entry: `self-healing-pending-wedge-notification` marker-selection count (first sighting) + +- **File:** `packages/engine/src/__tests__/self-healing-pending-wedge-notification.test.ts` +- **Exact test:** `reconcile pending wedge notifications > selects elapsed markers and audits the completion outcome verbatim` +- **Owner:** unowned — first sighting, recorded rather than quarantined because the file's remaining coverage (4 tests over the pending-wedge reconciler) is substantial and quarantine is file-level. +- **Observed tree/SHA:** `ea48af7ab5`, during a full `@fusion/engine` suite run while auditing pre-existing failures. +- **Observed frequency:** once, suite-only. Passes deterministically in isolation. + +Verbatim observed failure: + +``` +FAIL |engine-default| src/__tests__/self-healing-pending-wedge-notification.test.ts > reconcile pending wedge notifications > selects elapsed markers and audits the completion outcome verbatim +AssertionError: expected 2 to be 1 // Object.is equality + ❯ src/__tests__/self-healing-pending-wedge-notification.test.ts:50:62 +``` + +| run | result | +|---|---| +| full engine suite (967 files), `ea48af7ab5` | **failed** with the verbatim count assertion | +| same file in isolation, same tree | **passed** (4/4) | +| full engine suite, baseline `3f448f7292` | not observed | + +Reads as cross-test state bleed into the reconciler's marker selection (an expected-1 selection saw 2), +not a timing wait — so no timeout, retry, or assertion change was made. A SECOND sighting is an +ordinary on-sight quarantine with no further discretion, per the standing rule in AGENTS.md. diff --git a/packages/engine/src/__tests__/_merge-durable-write-callsites.ts b/packages/engine/src/__tests__/_merge-durable-write-callsites.ts index efb1f4890b..00606c5997 100644 --- a/packages/engine/src/__tests__/_merge-durable-write-callsites.ts +++ b/packages/engine/src/__tests__/_merge-durable-write-callsites.ts @@ -271,7 +271,24 @@ const STORE_METHOD_CLASSIFICATION: Record updateTask(Atomic) mutations + - logEntryOnce -> appends a deduplicated task log entry + - seedWorkspaceCodeReviewContinuationIfIdle -> inserts a workflow continuation row + */ + dismissAiMergeReviewFinding: { kind: "writer", reason: "persists or mutates TaskStore state" }, + logEntryOnce: { kind: "writer", reason: "persists or mutates TaskStore state" }, + mutateTaskRepositoryScope: { kind: "writer", reason: "persists or mutates TaskStore state" }, + normalizeWorkspaceTaskWorktreeMetadata: { kind: "writer", reason: "persists or mutates TaskStore state" }, + resetTaskPublication: { kind: "writer", reason: "persists or mutates TaskStore state" }, + seedWorkspaceCodeReviewContinuationIfIdle: { kind: "writer", reason: "persists or mutates TaskStore state" }, updateStep: { kind: "writer", reason: "persists or mutates TaskStore state" }, + updateTaskRepositoryScope: { kind: "writer", reason: "persists or mutates TaskStore state" }, + updateWorkspaceReviewState: { kind: "writer", reason: "persists or mutates TaskStore state" }, updateTaskAtomic: { kind: "writer", reason: "persists or mutates TaskStore state" }, updateTaskComment: { kind: "writer", reason: "persists or mutates TaskStore state" }, updateTaskCustomFields: { kind: "writer", reason: "persists or mutates TaskStore state" }, @@ -492,6 +509,8 @@ const NON_WRITER_REASONS: Record = Object.fromEntries([ "getMergeQueuedTaskIdsAsync", "getMergeRequestRecord", "getMergeRequestRecordAsync", + /* FNXC:MergeAuthority 2026-08-24-00:40: batched sibling of the read above; same read-only shape. */ + "getMergeRequestRecordsAsync", "getMissionStore", "getMutationsForRun", "getOrCreateForProject", @@ -604,6 +623,8 @@ const NON_WRITER_REASONS: Record = Object.fromEntries([ "listWorkflowSettingValuesForProject", "listWorkflowSteps", "listWorkflowWorkItemsForTask", + /* FNXC:MergeAuthority 2026-08-24-00:40: batched sibling of the read above; same read-only shape. */ + "listWorkflowWorkItemsForTasks", "listWorkflowWorkItemsForTaskSync", "loadWorkflowRunBranches", "loadWorkflowRunStepInstances", diff --git a/packages/engine/src/__tests__/agent-activity-writers.test.ts b/packages/engine/src/__tests__/agent-activity-writers.test.ts index b3072d8693..2133e52d88 100644 --- a/packages/engine/src/__tests__/agent-activity-writers.test.ts +++ b/packages/engine/src/__tests__/agent-activity-writers.test.ts @@ -395,6 +395,11 @@ pgDescribe("engine agent activity durable writer", () => { */ it("persists task completion through the merger finalization path", async () => { const task = await h.createTestTask(); + /* FNXC:RequiredPreMergeSteps 2026-08-24-00:20: this asserts agent-activity persistence on + completion, not review gating. The shared harness task carries the workflow's default-on + optional groups with no results, so the done-transition door refused it before the writer + under test ran. Declaring no optional gates states this fixture's intent. */ + await h.store().updateTask(task.id, { enabledWorkflowSteps: [] }); const settings = await h.store().getSettings(); await h.store().moveTask(task.id, "in-progress", { moveSource: "agent" }); await h.store().moveTask(task.id, "in-review", { moveSource: "agent" }); diff --git a/packages/engine/src/__tests__/group-merge-coordinator.test.ts b/packages/engine/src/__tests__/group-merge-coordinator.test.ts index d1102c86ad..29c7b89236 100644 --- a/packages/engine/src/__tests__/group-merge-coordinator.test.ts +++ b/packages/engine/src/__tests__/group-merge-coordinator.test.ts @@ -1291,6 +1291,17 @@ function createPostReviewTask(groupId: string): Record { baseBranch: "main", dependencies: [], steps: [{ name: "Code Review", status: "done" }], + /* + FNXC:RequiredPreMergeSteps 2026-08-24-00:20: + This fixture IS a post-Code-Review member, so its enabled pre-merge groups must carry passing + RESULTS — the merge door reads `workflowStepResults`, not the step row whose name happens to say + "Code Review". Without them the door refused this card before the branch-group routing under + test ran. Recording the passes states the fixture's intent; disabling the gates would not. + */ + workflowStepResults: [ + { workflowStepId: "plan-review", workflowStepName: "Plan Review", status: "passed", phase: "pre-merge", verdict: "APPROVE" }, + { workflowStepId: "code-review", workflowStepName: "Code Review", status: "passed", phase: "pre-merge", verdict: "APPROVE" }, + ], log: [], paused: false, autoMerge: undefined, @@ -1329,6 +1340,13 @@ function createPostReviewStore(task: Record, branchGroup: Record (branchGroup ? [task] : [])), getBranchGroup: vi.fn(() => branchGroup), updateTask: vi.fn(async (_id: string, patch: Record) => Object.assign(task, patch)), + /* FNXC:MergeMockDrift 2026-08-24-00:20: production write seam used by the merge path; a fake + store omitting it throws before the routing behaviour under test runs. */ + updateTaskAtomic: vi.fn(async (_id: string, updater: (current: typeof task) => Record | undefined) => { + const patch = await updater(task); + if (patch) Object.assign(task, patch); + return task; + }), moveTask: vi.fn(async (_id: string, column: string) => { task.column = column; return task; }), logEntry: vi.fn(async () => undefined), appendAgentLog: vi.fn(async () => undefined), diff --git a/packages/engine/src/__tests__/merger-ai-cleanup.test.ts b/packages/engine/src/__tests__/merger-ai-cleanup.test.ts index da73112e2a..4e2c8d763f 100644 --- a/packages/engine/src/__tests__/merger-ai-cleanup.test.ts +++ b/packages/engine/src/__tests__/merger-ai-cleanup.test.ts @@ -142,6 +142,11 @@ function initRepoWithBranch(taskId = "FN-1"): { dir: string } { function makeStore(taskId = "FN-1") { const task: any = { + /* FNXC:RequiredPreMergeSteps 2026-08-24-00:20: merge-mechanics fixture, not a review-gating one. + The door refuses a card whose enabled optional pre-merge groups produced no result, and the + built-in workflow enables Plan and Code Review by default, so an unspecified list failed the + door before the behaviour under test ran. An explicit empty list states the intent. */ + enabledWorkflowSteps: [], id: taskId, column: "in-review", status: null, @@ -156,6 +161,14 @@ function makeStore(taskId = "FN-1") { getTask: vi.fn(async () => task), getSettings: vi.fn(async () => ({ merger: { mode: "ai", maxReviewPasses: 1 } })), updateTask: vi.fn(async (_id: string, patch: Record) => { Object.assign(task, patch); return task; }), + /* FNXC:MergeMockDrift 2026-08-24-00:20: `updateTaskAtomic` is a production write seam the merge + path uses; a fake store that omits it throws TypeError before the behaviour under test runs. + Same read-modify-write shape as the sibling fake in `merger-ai.test.ts`. */ + updateTaskAtomic: vi.fn(async (_id: string, updater: (current: typeof task) => Record | undefined) => { + const patch = await updater(task); + if (patch) Object.assign(task, patch); + return task; + }), moveTask: vi.fn(async (_id: string, column: string) => { task.column = column; return task; }), emit: vi.fn(), logEntry: vi.fn(async (_id: string, message: string) => { logs.push(message); }), diff --git a/packages/engine/src/__tests__/merger-ai-push-after-merge.test.ts b/packages/engine/src/__tests__/merger-ai-push-after-merge.test.ts index 85631b5256..01aeee44d9 100644 --- a/packages/engine/src/__tests__/merger-ai-push-after-merge.test.ts +++ b/packages/engine/src/__tests__/merger-ai-push-after-merge.test.ts @@ -92,6 +92,11 @@ function advanceOrigin(originDir: string, fileName: string): void { function makeStore(settingsOverrides: Record = {}) { const task: Record = { + /* FNXC:RequiredPreMergeSteps 2026-08-24-00:20: merge-mechanics fixture, not a review-gating one. + The door refuses a card whose enabled optional pre-merge groups produced no result, and the + built-in workflow enables Plan and Code Review by default, so an unspecified list failed the + door before the behaviour under test ran. An explicit empty list states the intent. */ + enabledWorkflowSteps: [], id: "FN-1", column: "in-review", status: null, @@ -109,6 +114,14 @@ function makeStore(settingsOverrides: Record = {}) { ...settingsOverrides, })), updateTask: vi.fn(async (_id: string, patch: Record) => { Object.assign(task, patch); return task; }), + /* FNXC:MergeMockDrift 2026-08-24-00:20: `updateTaskAtomic` is a production write seam the merge + path uses; a fake store that omits it throws TypeError before the behaviour under test runs. + Same read-modify-write shape as the sibling fake in `merger-ai.test.ts`. */ + updateTaskAtomic: vi.fn(async (_id: string, updater: (current: typeof task) => Record | undefined) => { + const patch = await updater(task); + if (patch) Object.assign(task, patch); + return task; + }), moveTask: vi.fn(async (_id: string, column: string) => { task.column = column; return task; }), emit: vi.fn(), logEntry: vi.fn(async (_id: string, message: string, action?: string) => { logs.push({ message, action }); }), diff --git a/packages/engine/src/__tests__/merger-ai-squash-gates.test.ts b/packages/engine/src/__tests__/merger-ai-squash-gates.test.ts index cea4cef6b0..f7d776b98e 100644 --- a/packages/engine/src/__tests__/merger-ai-squash-gates.test.ts +++ b/packages/engine/src/__tests__/merger-ai-squash-gates.test.ts @@ -38,6 +38,11 @@ function createRepo(change: (dir: string) => void): string { function makeStore(scope: string[], overrides: Record = {}) { const task: any = { + /* FNXC:RequiredPreMergeSteps 2026-08-24-00:20: merge-mechanics fixture, not a review-gating one. + The door refuses a card whose enabled optional pre-merge groups produced no result, and the + built-in workflow enables Plan and Code Review by default, so an unspecified list failed the + door before the behaviour under test ran. An explicit empty list states the intent. */ + enabledWorkflowSteps: [], id: "FN-9050", title: "squash gates", column: "in-review", branch: "fusion/fn-9050", comments: [], steeringComments: [], steps: [], log: [], ...overrides, }; diff --git a/packages/engine/src/__tests__/merger-ai.test.ts b/packages/engine/src/__tests__/merger-ai.test.ts index eaf841d446..4c33f090b9 100644 --- a/packages/engine/src/__tests__/merger-ai.test.ts +++ b/packages/engine/src/__tests__/merger-ai.test.ts @@ -88,6 +88,16 @@ function makeStore( worktree: null, title: "do the thing", steps: [], + /* + FNXC:RequiredPreMergeSteps 2026-08-24-00:20: + These fixtures exercise AI-MERGE MECHANICS — clean-room setup, push, abort, cleanup, lease + handling — not review gating. The merge door refuses any card whose enabled optional pre-merge + groups have produced no result, and the built-in coding workflow enables Plan Review and Code + Review by default, so an unspecified list made every fixture here fail the door before reaching + the behaviour under test. Declaring an EXPLICIT empty list states the intent these tests always + had: no optional gates are in play. A test that wants a gate opts in via `taskOverrides`. + */ + enabledWorkflowSteps: [], baseBranch: undefined, ...taskOverrides, }; diff --git a/packages/engine/src/__tests__/non-executor-run-audit-sink-health.test.ts b/packages/engine/src/__tests__/non-executor-run-audit-sink-health.test.ts index c98715c3c9..665da68463 100644 --- a/packages/engine/src/__tests__/non-executor-run-audit-sink-health.test.ts +++ b/packages/engine/src/__tests__/non-executor-run-audit-sink-health.test.ts @@ -275,7 +275,11 @@ describe("FN-9175 non-executor audit sink health", () => { it.each(hostileModes)("returns a resolving fence audit promise with a %s sink", async (mode) => { mergerAiAuditCapture.fences.length = 0; const sink = sinkFor(mode); - const task = { id: "FN-9175", title: "merge", description: "", column: "in-review", branch: "missing-fn-9175", steps: [{ name: "Ship", status: "done" }], currentStep: 1, workflowStepResults: [], dependencies: [], createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }; + /* FNXC:RequiredPreMergeSteps 2026-08-24-00:40: this fixture must REACH runAiMerge's generation + fence (see the note below), so it must clear the merge door first. An unspecified optional-step + list makes the door refuse on the workflow's default-on Plan/Code Review groups before any + fence is constructed, leaving `fences` empty and `recordAudit` undefined. */ + const task = { id: "FN-9175", title: "merge", description: "", column: "in-review", branch: "missing-fn-9175", enabledWorkflowSteps: [], steps: [{ name: "Ship", status: "done" }], currentStep: 1, workflowStepResults: [], dependencies: [], createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }; const store = { ...sink.host, getTask: vi.fn().mockResolvedValue(task), getSettings: vi.fn().mockResolvedValue({ integrationBranch: "main" }), getTaskWorkflowSelection: vi.fn().mockReturnValue(undefined), updateTask: vi.fn().mockResolvedValue(undefined), logEntry: vi.fn().mockResolvedValue(undefined), appendAgentLog: vi.fn().mockResolvedValue(undefined) }; // The missing branch is intentional: runAiMerge constructs its real generation fence before // git rejects the branch, allowing this test to exercise the closure the production path gave it. diff --git a/packages/engine/src/__tests__/reliability-interactions/_helpers.ts b/packages/engine/src/__tests__/reliability-interactions/_helpers.ts index 6c5486b8dc..4d726fb74b 100644 --- a/packages/engine/src/__tests__/reliability-interactions/_helpers.ts +++ b/packages/engine/src/__tests__/reliability-interactions/_helpers.ts @@ -325,6 +325,14 @@ export async function makeReliabilityFixture(input: { description: "reliability fixture task", column: "in-review", branch: `fusion/${id.toLowerCase()}`, + /* + FNXC:BranchNaming 2026-08-24-00:40: + Creation is a branch-write boundary (`normalizeCreateBranchProvenance`): supplying `branch` + without an explicit origin throws `BranchWriteProvenanceError`. This fixture stands in for a + card whose branch the ENGINE created, which is what every reliability scenario built on it + assumes. Without this the fixture threw before any scenario ran. + */ + branchWriteOrigin: "engine", baseBranch: "main", prompt: `## File Scope\n- packages/engine/src/__tests__/reliability-interactions/**/*.ts\n`, steps: [], diff --git a/packages/engine/src/__tests__/workflow-graph-merge-region-collapse.test.ts b/packages/engine/src/__tests__/workflow-graph-merge-region-collapse.test.ts index 154c9dc5b6..a2d368d63a 100644 --- a/packages/engine/src/__tests__/workflow-graph-merge-region-collapse.test.ts +++ b/packages/engine/src/__tests__/workflow-graph-merge-region-collapse.test.ts @@ -76,9 +76,16 @@ const SUCCESS_PATH = [ "plan-review::plan-review-step", "execute", "browser-verification", + /* + FNXC:WorkflowGraphTests 2026-08-24-00:40: + `completion-summary` runs BEFORE `code-review`, not after. The built-in coding IR wires + `browser-verification -> completion-summary -> code-review` (see builtin-coding-workflow-ir.ts), + and production task logs show the same order — the summary describes the work, then the review + reads it. This list had the two transposed and was asserting a topology the graph never ran. + */ + "completion-summary", "code-review", "code-review::code-review-step", - "completion-summary", "review", "merge", "post-merge-verification", diff --git a/packages/engine/src/__tests__/workspace-merger-deps-resilient.test.ts b/packages/engine/src/__tests__/workspace-merger-deps-resilient.test.ts index d852375236..0477bb46af 100644 --- a/packages/engine/src/__tests__/workspace-merger-deps-resilient.test.ts +++ b/packages/engine/src/__tests__/workspace-merger-deps-resilient.test.ts @@ -78,6 +78,11 @@ const approveReviewAgent = async (): Promise => "REVIEW_VERDICT: approve function makeTask(workspaceWorktrees: Task["workspaceWorktrees"]): Task { return { + /* FNXC:RequiredPreMergeSteps 2026-08-24-00:20: merge-mechanics fixture, not a review-gating one. + The door refuses a card whose enabled optional pre-merge groups produced no result, and the + built-in workflow enables Plan and Code Review by default, so an unspecified list failed the + door before the behaviour under test ran. An explicit empty list states the intent. */ + enabledWorkflowSteps: [], id: TASK_ID, title: "Workspace merge task", description: "", column: "in-review", branch: BRANCH, dependencies: [], steps: [], currentStep: 0, log: [], workspaceWorktrees, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), diff --git a/packages/engine/src/__tests__/workspace-merger-idempotency.slow.test.ts b/packages/engine/src/__tests__/workspace-merger-idempotency.slow.test.ts index 4c4e79bd65..02879f6fd2 100644 --- a/packages/engine/src/__tests__/workspace-merger-idempotency.slow.test.ts +++ b/packages/engine/src/__tests__/workspace-merger-idempotency.slow.test.ts @@ -168,6 +168,11 @@ const approveReviewAgent = async (): Promise => "REVIEW_VERDICT: approve function makeTask(workspaceWorktrees: Task["workspaceWorktrees"]): Task { return { + /* FNXC:RequiredPreMergeSteps 2026-08-24-00:20: merge-mechanics fixture, not a review-gating one. + The door refuses a card whose enabled optional pre-merge groups produced no result, and the + built-in workflow enables Plan and Code Review by default, so an unspecified list failed the + door before the behaviour under test ran. An explicit empty list states the intent. */ + enabledWorkflowSteps: [], id: TASK_ID, title: "Workspace merge task", description: "", diff --git a/packages/engine/src/__tests__/workspace-merger-lease.test.ts b/packages/engine/src/__tests__/workspace-merger-lease.test.ts index e46ac35157..c7dc7b6de4 100644 --- a/packages/engine/src/__tests__/workspace-merger-lease.test.ts +++ b/packages/engine/src/__tests__/workspace-merger-lease.test.ts @@ -130,6 +130,11 @@ const approveReviewAgent = async (): Promise => "REVIEW_VERDICT: approve function makeTask(id: string, workspaceWorktrees: Task["workspaceWorktrees"]): Task { return { + /* FNXC:RequiredPreMergeSteps 2026-08-24-00:20: merge-mechanics fixture, not a review-gating one. + The door refuses a card whose enabled optional pre-merge groups produced no result, and the + built-in workflow enables Plan and Code Review by default, so an unspecified list failed the + door before the behaviour under test ran. An explicit empty list states the intent. */ + enabledWorkflowSteps: [], id, title: "Workspace merge task", description: "", diff --git a/packages/engine/src/__tests__/workspace-merger-scope-gates.test.ts b/packages/engine/src/__tests__/workspace-merger-scope-gates.test.ts index fe7c645aca..8b728fd0b8 100644 --- a/packages/engine/src/__tests__/workspace-merger-scope-gates.test.ts +++ b/packages/engine/src/__tests__/workspace-merger-scope-gates.test.ts @@ -88,7 +88,7 @@ describeIfGit("landWorkspaceTask file-scope gates", () => { */ addBranch(fx, "repo-b", "repo-a/feature.txt"); const task = { - id: TASK_ID, title: "workspace scope", description: "", column: "in-review", branch: BRANCH, + id: TASK_ID, title: "workspace scope", description: "", column: "in-review", branch: BRANCH, enabledWorkflowSteps: [], /* FNXC:RequiredPreMergeSteps 2026-08-24-00:20: merge-mechanics fixture; an unspecified list makes the door refuse on default-on Plan/Code Review before the behaviour under test runs. */ comments: [], steeringComments: [], dependencies: [], steps: [], log: [], currentStep: 0, workspaceWorktrees: { "repo-a": { worktreePath: fx.repoPath("repo-a"), branch: BRANCH }, @@ -127,7 +127,7 @@ describeIfGit("landWorkspaceTask file-scope gates", () => { addBranch(fx, "repo-a"); addBranch(fx, "repo-b", "unapproved.ts"); const task = { - id: TASK_ID, title: "workspace scope", description: "", column: "in-review", branch: BRANCH, + id: TASK_ID, title: "workspace scope", description: "", column: "in-review", branch: BRANCH, enabledWorkflowSteps: [], /* FNXC:RequiredPreMergeSteps 2026-08-24-00:20: merge-mechanics fixture; an unspecified list makes the door refuse on default-on Plan/Code Review before the behaviour under test runs. */ comments: [], steeringComments: [], dependencies: [], steps: [], log: [], currentStep: 0, workspaceWorktrees: { "repo-a": { worktreePath: fx.repoPath("repo-a"), branch: BRANCH }, @@ -155,7 +155,7 @@ describeIfGit("landWorkspaceTask file-scope gates", () => { fx = await createWorkspaceFixture(["repo-a"]); addBranch(fx, "repo-a"); const task = { - id: TASK_ID, title: "workspace scope", description: "", column: "in-review", branch: BRANCH, + id: TASK_ID, title: "workspace scope", description: "", column: "in-review", branch: BRANCH, enabledWorkflowSteps: [], /* FNXC:RequiredPreMergeSteps 2026-08-24-00:20: merge-mechanics fixture; an unspecified list makes the door refuse on default-on Plan/Code Review before the behaviour under test runs. */ comments: [], steeringComments: [], dependencies: [], steps: [], log: [], currentStep: 0, workspaceWorktrees: { "repo-a": { worktreePath: fx.repoPath("repo-a"), branch: BRANCH } }, repositoryScope: { diff --git a/packages/engine/src/__tests__/workspace-merger.test.ts b/packages/engine/src/__tests__/workspace-merger.test.ts index 250a4027d2..9b484a0b41 100644 --- a/packages/engine/src/__tests__/workspace-merger.test.ts +++ b/packages/engine/src/__tests__/workspace-merger.test.ts @@ -183,6 +183,11 @@ const approveReviewAgent = async (): Promise => "REVIEW_VERDICT: approve function makeTask(workspaceWorktrees: Task["workspaceWorktrees"]): Task { return { + /* FNXC:RequiredPreMergeSteps 2026-08-24-00:20: merge-mechanics fixture, not a review-gating one. + The door refuses a card whose enabled optional pre-merge groups produced no result, and the + built-in workflow enables Plan and Code Review by default, so an unspecified list failed the + door before the behaviour under test ran. An explicit empty list states the intent. */ + enabledWorkflowSteps: [], id: TASK_ID, title: "Workspace merge task", description: "",