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 <noreply@anthropic.com>
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -271,7 +271,24 @@ const STORE_METHOD_CLASSIFICATION: Record<string, Omit<SurfaceClassification, "m
|
||||
updatePrInfo: { kind: "writer", reason: "persists or mutates TaskStore state" },
|
||||
updatePrInfoByNumber: { kind: "writer", reason: "persists or mutates TaskStore state" },
|
||||
updateSettings: { kind: "writer", reason: "persists or mutates TaskStore state" },
|
||||
/*
|
||||
FNXC:DurableWriteInventory 2026-08-24-00:40:
|
||||
Public TaskStore write surfaces added since this inventory was last regenerated. Each persists or
|
||||
mutates task state, so each is a durable writer:
|
||||
- dismissAiMergeReviewFinding / mutateTaskRepositoryScope / resetTaskPublication /
|
||||
normalizeWorkspaceTaskWorktreeMetadata -> 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<string, string> = 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<string, string> = 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",
|
||||
|
||||
@@ -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" });
|
||||
|
||||
@@ -1291,6 +1291,17 @@ function createPostReviewTask(groupId: string): Record<string, any> {
|
||||
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<string, any>, branchGroup: Record<st
|
||||
listTasksByBranchGroup: vi.fn(async () => (branchGroup ? [task] : [])),
|
||||
getBranchGroup: vi.fn(() => branchGroup),
|
||||
updateTask: vi.fn(async (_id: string, patch: Record<string, unknown>) => 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<string, unknown> | 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),
|
||||
|
||||
@@ -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<string, unknown>) => { 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<string, unknown> | 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); }),
|
||||
|
||||
@@ -92,6 +92,11 @@ function advanceOrigin(originDir: string, fileName: string): void {
|
||||
|
||||
function makeStore(settingsOverrides: Record<string, unknown> = {}) {
|
||||
const task: Record<string, unknown> = {
|
||||
/* 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<string, unknown> = {}) {
|
||||
...settingsOverrides,
|
||||
})),
|
||||
updateTask: vi.fn(async (_id: string, patch: Record<string, unknown>) => { 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<string, unknown> | 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 }); }),
|
||||
|
||||
@@ -38,6 +38,11 @@ function createRepo(change: (dir: string) => void): string {
|
||||
|
||||
function makeStore(scope: string[], overrides: Record<string, unknown> = {}) {
|
||||
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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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: [],
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -78,6 +78,11 @@ const approveReviewAgent = async (): Promise<string> => "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(),
|
||||
|
||||
@@ -168,6 +168,11 @@ const approveReviewAgent = async (): Promise<string> => "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: "",
|
||||
|
||||
@@ -130,6 +130,11 @@ const approveReviewAgent = async (): Promise<string> => "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: "",
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -183,6 +183,11 @@ const approveReviewAgent = async (): Promise<string> => "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: "",
|
||||
|
||||
Reference in New Issue
Block a user