Skip to content

refactor(workflow): add workflow-owned merge migration slice#1571

Merged
gsxdsm merged 5 commits into
mainfrom
feature/workflow-owned-merge-retry-scheduling-plan
Jun 11, 2026
Merged

refactor(workflow): add workflow-owned merge migration slice#1571
gsxdsm merged 5 commits into
mainfrom
feature/workflow-owned-merge-retry-scheduling-plan

Conversation

@gsxdsm

@gsxdsm gsxdsm commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Documents the full workflow-owned merge/retry/scheduling migration slices in docs/plans/2026-06-09-003-refactor-workflow-owned-merge-full-migration-slices-plan.md.
  • Adds the S1 workflow work-item schema, migration, exported types, and TaskStore APIs for durable due-work selection, leasing, transitions, and terminal-state protection.
  • Adds focused core coverage for fresh schema creation, idempotent upserts, due selection, lease reclaiming, and terminal work.
  • Creates the draft PR stack for S2-S18 so every remaining migration slice has a durable branch, PR, and handoff artifact.

Migration Milestones

  • Gate A after S4: built-in workflow IR expresses all planned merge, retry, recovery, manual-hold, and branch-group policy regions.
  • Gate B after S8: workflow runtime can process merge work without hidden merge queue ownership.
  • Gate C after S10: self-healing emits typed recovery events for merge/retry surfaces instead of mutating lifecycle directly.
  • Gate D after S12: dashboard, API, and CLI projections read workflow state first.
  • Gate E after S17: deletion tests and the end-to-end matrix prove no production legacy merge/retry/scheduling control plane remains.

Migration Slices

Slice Milestone Goal Status
S0 Foundation Ownership map and guard for current policy surfaces. Done in this PR stack
S1 Foundation Workflow work-item schema and store API. Implemented in this PR
S2 Foundation Merge request projection onto work items. Draft PR #1575
S3 Foundation Generic scheduler claim path for due workflow work. Draft PR #1576
S4 Gate A Built-in merge/retry/recovery IR regions. Draft PR #1577
S5 Runtime Runtime work-item driver. Draft PR #1578
S6 Runtime Git and merge capability extraction. Draft PR #1579
S7 Runtime Completion handoff creates merge work. Draft PR #1580
S8 Gate B Workflow-owned merge queue processing. Draft PR #1581
S9 Retry Workflow-owned retry state. Draft PR #1582
S10 Gate C Self-healing recovery events. Draft PR #1583
S11 Branch Groups Branch-group workflow subgraphs. Draft PR #1584
S12 Gate D Dashboard/API/CLI workflow projection. Draft PR #1585
S13 Deletion Scheduler policy deletion. Draft PR #1586
S14 Deletion ProjectEngine merge queue deletion. Draft PR #1587
S15 Deletion Self-healing policy deletion. Draft PR #1588
S16 Deletion Legacy retry field demotion. Draft PR #1589
S17 Gate E End-to-end cutover matrix. Draft PR #1590
S18 Release Documentation, settings, and release notes. Draft PR #1591

Stack PRs

Verification

  • pnpm --filter @fusion/core exec vitest run src/__tests__/store-workflow-runtime.test.ts src/__tests__/merge-request-record.test.ts --silent=passed-only --reporter=dot
  • pnpm --filter @fusion/core typecheck
  • pnpm test:gate
  • pnpm lint
  • pnpm build

Browser

  • Not applicable: this slice changes core storage/schema/tests and stack handoff docs; no browser surface.

Summary by CodeRabbit

  • Documentation

    • Added plans and an ownership map describing the workflow-owned merge/retry/scheduling control plane, migration slices, rollout, risks, and verification criteria.
  • New Features

    • Introduced workflow work-item scheduling primitives for workflow-owned retry, leasing, timing, and state projection.
  • Tests

    • Added and updated tests to validate the ownership map, migrations, and work-item behavior.
  • Chores

    • Bumped database schema to support the new workflow work-item store.

Implementation Added

  • Added workflow work-item schema/store API, schema migration, indexes, exports, focused core tests, ownership map, and migration plan.\n- Verification: core workflow runtime tests, schema tests, engine ownership-map tests, and gate/CI checks.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds foundational documentation and validation for shifting merge, retry, and scheduling control to workflow-owned policy, and implements durable workflow_work_items support: schema migration (v115), types, TaskStore scheduling/lease APIs, and tests exercising upsert, due listing, leases, retries, and terminal-state guards.

Changes

Workflow Policy Ownership and Merge-Retry-Scheduling Refactor

Layer / File(s) Summary
Workflow-owned merge/retry/scheduling refactor plan
docs/plans/2026-06-09-002-refactor-workflow-owned-merge-retry-scheduling-plan.md
Comprehensive plan defining requirements, scope, target architecture, 11 implementation units (work-item model, scheduler substrate, git/merge node capabilities, retry policies, self-healing recovery, workflow migration, branch-group modeling, state projection), rollout sequence, risks, verification plan, and done criteria.
Workflow policy ownership characterization artifact
docs/workflow-policy-ownership-map.md
Catalog mapping production surfaces to ownership categories, enumerating non-bypassable guard services and deletion gates that constrain legacy Scheduler/SelfHealingManager responsibilities and declare workflow state as policy authority.
Ownership map validation tests and test registration
packages/engine/src/__tests__/workflow-policy-ownership-map.test.ts, packages/engine/vitest.config.ts
Vitest suite validates the ownership map contains required policy-surface strings, production source paths, migration/disposition markers, and deletion-gate phrasing; test is added to the engine-core include list.
Changeset and migration slices plan
.changeset/workflow-work-items.md, docs/plans/2026-06-09-003-refactor-workflow-owned-merge-full-migration-slices-plan.md
Adds a patch changeset and a detailed slice-by-slice migration plan (S0–S18) describing goals, dependencies, dependency graph, cutover/rollback strategy, and verification commands.
Database schema and migration
packages/core/src/db.ts
Bumps SCHEMA_VERSION 114→115, adds workflow_work_items table and indexes to canonical schema, and adds migration 115 to create the table/indexes on existing DBs.
Types and barrel exports
packages/core/src/types.ts, packages/core/src/index.ts
Adds WORKFLOW_WORK_ITEM_KINDS/WORKFLOW_WORK_ITEM_STATES and exported union/interface types for work items; re-exports work-item constants from the core barrel.
TaskStore workflow work-item APIs
packages/core/src/store.ts
Introduces internal row mapping and normalization helpers and public TaskStore methods: upsertWorkflowWorkItem, transitionWorkflowWorkItem, getWorkflowWorkItem, listDueWorkflowWorkItems, and acquireWorkflowWorkItemLease implementing idempotent upsert, terminal-state immutability, due-listing, and atomic lease acquisition with audit events.
Tests: schema version updates & workflow runtime tests
packages/core/src/__tests__/*, packages/core/src/__tests__/store-workflow-runtime.test.ts
Updates multiple migration/unit tests to expect schema version 115 and adds a new TaskStore workflow work items test suite verifying table/index creation, upsert idempotency, due listing timing, lease semantics, idempotent retry upserts, and terminal-state requeue prevention.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

I nibble on the migration map, 🐇
A carrot plan across the app,
Work items hop in rows anew,
Leases held until they’re due—
Docs, tests, and schema stamped in glue.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.58% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately describes the primary change: adding a workflow-owned merge migration slice (S1) with work-item schema, storage, and APIs.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/workflow-owned-merge-retry-scheduling-plan

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gsxdsm gsxdsm force-pushed the feature/workflow-owned-merge-retry-scheduling-plan branch from 8911676 to 0cb54dd Compare June 9, 2026 18:52
@greptile-apps

greptile-apps Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR implements the S1 foundation slice of a workflow-owned merge/retry/scheduling migration: it introduces the workflow_work_items durable table (schema v115), a complete TaskStore API for upsert, transition, lease acquisition, and due-work selection, and the corresponding TypeScript types. It also installs a gate test that enforces the new workflow-policy-ownership-map.md doc.

  • Schema & migration: workflow_work_items is added in both the base schema and the migration 115 block with three covering indexes for due-selection, lease expiry, and task-run lookup.
  • Store API: five new methods (upsertWorkflowWorkItem, transitionWorkflowWorkItem, getWorkflowWorkItem, listDueWorkflowWorkItems, acquireWorkflowWorkItemLease) each run inside transactionImmediate and emit typed audit events.
  • Tests & documentation: focused unit tests cover fresh schema, idempotent upserts, due-list filtering, lease reclaim, and terminal-state protection; the ownership map gate test uses import.meta.url for deterministic path resolution.

Confidence Score: 5/5

Safe to merge; all changes are additive (new table, new store methods, new tests) with no modifications to existing data paths.

The schema migration is idempotent, the new store methods are fully transactional with audit logging, and the tests cover the core invariants. No existing behavior is altered.

No files require special attention for merge safety.

Important Files Changed

Filename Overview
packages/core/src/db.ts Schema bumped to v115; adds workflow_work_items table in both the base schema and the migration 115 block with correct CREATE TABLE IF NOT EXISTS idempotency and three appropriate indexes.
packages/core/src/store.ts Adds five new TaskStore methods with correct transactional semantics and audit logging; normalizer fallback silently masks unknown state/kind values which can bypass terminal-state protection.
packages/core/src/types.ts Adds well-typed WorkflowWorkItem* interfaces and const-array state/kind enumerations; all types are correctly re-exported from index.ts.
packages/core/src/tests/store-workflow-runtime.test.ts New test file covering fresh schema creation, idempotent upserts, due-list selection, lease acquisition/reclaim, state filters, and terminal-state protection; no migration-path coverage.
packages/core/src/tests/db-migrate.test.ts Version-number bumps across all existing migration tests; no new forward-migration test for migration 115 itself.
packages/engine/src/tests/workflow-policy-ownership-map.test.ts New gate test verifying the ownership map doc contains required policy surfaces, source files, and disposition strings; uses import.meta.url for deterministic path resolution.
docs/workflow-policy-ownership-map.md New ownership map documenting all policy surfaces, source files, migration dispositions, and deletion gates; referenced by the engine gate test.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    NEW([new work item]) -->|upsertWorkflowWorkItem| RUNNABLE[runnable]
    RETRYING[retrying] -->|acquireWorkflowWorkItemLease| RUNNING[running]
    RUNNABLE -->|acquireWorkflowWorkItemLease| RUNNING
    RUNNING -->|lease expired + acquireWorkflowWorkItemLease| RUNNING
    RUNNING -->|transitionWorkflowWorkItem| RETRYING
    RUNNING -->|transitionWorkflowWorkItem| HELD[held]
    RUNNING -->|transitionWorkflowWorkItem| MANUAL[manual-required]
    HELD -->|transitionWorkflowWorkItem| RUNNABLE
    MANUAL -->|transitionWorkflowWorkItem| RUNNABLE
    RUNNING -->|transitionWorkflowWorkItem| SUCCEEDED([succeeded])
    RUNNING -->|transitionWorkflowWorkItem| FAILED([failed])
    RUNNING -->|transitionWorkflowWorkItem| CANCELLED([cancelled])
    RUNNING -->|transitionWorkflowWorkItem| EXHAUSTED([exhausted])
    SUCCEEDED -->|upsert same state: allowed| SUCCEEDED
    FAILED -->|any state change: throws| ERR{{Error: terminal}}
    SUCCEEDED -->|any state change: throws| ERR
Loading

Reviews (5): Last reviewed commit: "fix(review): stabilize ownership map tes..." | Re-trigger Greptile

Comment thread packages/engine/src/__tests__/workflow-policy-ownership-map.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (5)
packages/engine/src/__tests__/agent-tools.test.ts (1)

204-206: ⚡ Quick win

Strengthen the “workflowId omitted” assertions.

Line 204 and Line 376 use a matcher that can still pass when workflowId: undefined is present. Assert property absence directly on the create input object.

✅ Suggested assertion pattern
-    expect(store.createTask).toHaveBeenCalledWith(expect.not.objectContaining({
-      workflowId: expect.anything(),
-    }), expect.anything());
+    const createInput = vi.mocked(store.createTask).mock.calls[0]?.[0] as Record<string, unknown>;
+    expect(createInput).not.toHaveProperty("workflowId");
...
-    expect(taskStore.createTask).toHaveBeenCalledWith(expect.not.objectContaining({
-      workflowId: expect.anything(),
-    }), expect.anything());
+    const delegatedInput = vi.mocked(taskStore.createTask).mock.calls[0]?.[0] as Record<string, unknown>;
+    expect(delegatedInput).not.toHaveProperty("workflowId");

Also applies to: 376-378

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/engine/src/__tests__/agent-tools.test.ts` around lines 204 - 206,
The current matcher can still pass when workflowId is present but undefined;
instead extract the actual create input from store.createTask's mock calls and
assert the property is absent using Jest's not.toHaveProperty; e.g., grab the
first call arg via (store.createTask as jest.Mock).mock.calls[0][0] and run
expect(createArg).not.toHaveProperty('workflowId'), then keep the other call
assertions (or assert the full call args if needed); apply the same change for
the second occurrence that checks workflowId absence.
packages/engine/src/__tests__/agent-tools-github-tracking-end-to-end.test.ts (1)

45-45: 💤 Low value

Mock cleanup strategy changed from restoreAllMocks to clearAllMocks.

The change from vi.restoreAllMocks() to vi.clearAllMocks() means mocks retain their implementation between tests (only call history is cleared). This works for the current test cases, but could cause issues if additional tests with different mocking needs are added later. Consider documenting this choice or keeping restoreAllMocks for more robust test isolation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/engine/src/__tests__/agent-tools-github-tracking-end-to-end.test.ts`
at line 45, The test teardown was changed to vi.clearAllMocks(), which only
resets call history and leaves mock implementations in place; decide and
implement the intended isolation strategy by either switching back to
vi.restoreAllMocks() in the test file to fully restore mocked implementations
after each test, or add a comment near the vi.clearAllMocks() call documenting
why persistent implementations are required and that test authors must manually
reset/restore implementations when needed; update references to
vi.clearAllMocks() and vi.restoreAllMocks() accordingly.
packages/engine/src/__tests__/agent-task-creation-github-tracking-flag.test.ts (1)

46-46: 💤 Low value

Mock cleanup strategy changed from restoreAllMocks to clearAllMocks.

The change from vi.restoreAllMocks() to vi.clearAllMocks() means mocks retain their implementation between tests (only call history is cleared). This works for the current single test case, but could cause issues if additional tests with different mocking needs are added later. Consider documenting this choice or keeping restoreAllMocks for more robust test isolation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/engine/src/__tests__/agent-task-creation-github-tracking-flag.test.ts`
at line 46, The test switched from vi.restoreAllMocks() to vi.clearAllMocks(),
which leaves mock implementations intact and can cause cross-test leakage;
either revert to vi.restoreAllMocks() in the test teardown to fully restore
original implementations (replace the vi.clearAllMocks() call), or explicitly
document and justify the choice by adding a comment and ensure test isolation by
resetting implementations where needed (e.g., re-stubbing before each test) so
functions referenced like vi.clearAllMocks() and vi.restoreAllMocks() do not
introduce hidden state between tests.
packages/dashboard/app/components/__tests__/TaskCard.test.tsx (1)

4342-4366: ⚡ Quick win

Use existing mountCssForBadgeTests() helper for consistent CSS injection.

The test manually injects CSS and handles cleanup, but the file already provides mountCssForBadgeTests() (line 123) that does the same with proper variable setup. Other tests use this helper (e.g., line 2782, line 3251).

♻️ Refactor to use existing helper
 it("renders a promote action when onPromote is provided", () => {
   const onPromote = vi.fn().mockResolvedValue(undefined);
-  const style = document.createElement("style");
-  style.textContent = loadAllAppCss();
-  document.head.appendChild(style);
+  const cleanupCss = mountCssForBadgeTests();

   try {
     render(
       <TaskCard
         task={makeTask({ id: "FN-777", column: "todo" })}
         onOpenDetail={noop}
         addToast={noop}
         onPromote={onPromote}
       />,
     );

     const promoteButton = screen.getByTestId("card-promote-FN-777");
     expect(promoteButton).toBeDefined();
     expect(promoteButton).toHaveClass("card-promote-action");
     expect(promoteButton.textContent).toContain("Promote");

-    const styles = getComputedStyle(promoteButton);
-    expect(styles.gap).toBe("var(--space-xs)");
-    expect(styles.padding).toBe("var(--space-xs) var(--space-sm)");
+    // Verify styles are applied (after fixing assertions per other comment)
   } finally {
-    style.remove();
+    cleanupCss();
   }
 });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/dashboard/app/components/__tests__/TaskCard.test.tsx` around lines
4342 - 4366, Replace the manual CSS injection block (creating a <style>, setting
textContent = loadAllAppCss(), appending to document.head, and removing it in
finally) with the existing test helper mountCssForBadgeTests(); call
mountCssForBadgeTests() before rendering the <TaskCard> (and rely on its
internal cleanup) so the test uses the consistent CSS setup used by other tests
(see mountCssForBadgeTests).
packages/engine/src/merger-ai.ts (1)

1008-1022: 💤 Low value

Consider consolidating merge details persistence.

finalizeTask rebuilds and persists mergeDetails even though finalizeMerged (line 959) already wrote a complete mergeDetails object for non-empty merges. The defensive merge pattern here is safe and handles both empty and non-empty cases uniformly, but it results in two store writes for the AI merge path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/engine/src/merger-ai.ts` around lines 1008 - 1022, finalizeTask is
rebuilding and persisting mergeDetails even though finalizeMerged already wrote
a complete mergeDetails for non-empty AI merges, causing duplicate store writes;
modify finalizeTask to avoid the second write by checking for an existing
complete mergeDetails (e.g., inspect result.task.mergeDetails and a reliable
marker such as mergedAt or mergeConfirmed) and only construct+call
store.updateTask when mergeDetails is absent/incomplete (otherwise skip the
update), leaving finalizeMerged, mergeDetails, result.task.mergeDetails, and
store.updateTask as the referenced symbols to locate the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@eslint.config.mjs`:
- Around line 72-100: The noPluginViewReexport rule currently only inspects
ExportNamedDeclaration nodes; add an ExportAllDeclaration handler alongside
ExportNamedDeclaration that uses the existing
isViewEntrypointReexportSource(node.source?.value) check and calls
context.report with the same node.source and message so `export * from
"./dashboard-view"` is caught; reuse the same message text and reporting logic
as in the ExportNamedDeclaration branch to ensure consistent behavior.

In `@packages/dashboard/app/components/__tests__/TaskCard.test.tsx`:
- Around line 4362-4363: The test asserts CSS variables directly but
getComputedStyle returns resolved values, so update the assertions in
TaskCard.test.tsx (the expectations using styles.gap and styles.padding) to
either compare the resolved pixel strings (e.g., "4px" / "8px 12px") or simply
assert that the computed style properties are truthy/present; locate the lines
referencing styles.gap and styles.padding and replace them with assertions that
match the computed values or non-exact presence checks (e.g.,
expect(styles.gap).toBeDefined() or expect(styles.gap).toBe("4px") depending on
whether you want a loose or exact check).

In `@packages/dashboard/src/file-service.ts`:
- Around line 495-501: The catch blocks around the stat/existence/parent checks
in file-service.ts currently rethrow raw errors (see the catch that casts to
Error & { code?: string }) which lets EACCES/EPERM bubble up as 500s; instead,
detect permission-related error.code values ("EACCES", "EPERM") and wrap/throw
them as a FileServiceError (preserving the original error message) so they
normalize to a 403 response. Update both catch sites (the block handling
existence/parent checks and the similar block at the second occurrence) to:
check error.code, if it's "ENOENT" keep current behavior, if it's "EACCES" or
"EPERM" throw new FileServiceError(...) (or rethrow a FileServiceError instance)
otherwise rethrow the original error; reference FileServiceError and the
stat/existence/parent check locations when making the change.

---

Nitpick comments:
In `@packages/dashboard/app/components/__tests__/TaskCard.test.tsx`:
- Around line 4342-4366: Replace the manual CSS injection block (creating a
<style>, setting textContent = loadAllAppCss(), appending to document.head, and
removing it in finally) with the existing test helper mountCssForBadgeTests();
call mountCssForBadgeTests() before rendering the <TaskCard> (and rely on its
internal cleanup) so the test uses the consistent CSS setup used by other tests
(see mountCssForBadgeTests).

In
`@packages/engine/src/__tests__/agent-task-creation-github-tracking-flag.test.ts`:
- Line 46: The test switched from vi.restoreAllMocks() to vi.clearAllMocks(),
which leaves mock implementations intact and can cause cross-test leakage;
either revert to vi.restoreAllMocks() in the test teardown to fully restore
original implementations (replace the vi.clearAllMocks() call), or explicitly
document and justify the choice by adding a comment and ensure test isolation by
resetting implementations where needed (e.g., re-stubbing before each test) so
functions referenced like vi.clearAllMocks() and vi.restoreAllMocks() do not
introduce hidden state between tests.

In
`@packages/engine/src/__tests__/agent-tools-github-tracking-end-to-end.test.ts`:
- Line 45: The test teardown was changed to vi.clearAllMocks(), which only
resets call history and leaves mock implementations in place; decide and
implement the intended isolation strategy by either switching back to
vi.restoreAllMocks() in the test file to fully restore mocked implementations
after each test, or add a comment near the vi.clearAllMocks() call documenting
why persistent implementations are required and that test authors must manually
reset/restore implementations when needed; update references to
vi.clearAllMocks() and vi.restoreAllMocks() accordingly.

In `@packages/engine/src/__tests__/agent-tools.test.ts`:
- Around line 204-206: The current matcher can still pass when workflowId is
present but undefined; instead extract the actual create input from
store.createTask's mock calls and assert the property is absent using Jest's
not.toHaveProperty; e.g., grab the first call arg via (store.createTask as
jest.Mock).mock.calls[0][0] and run
expect(createArg).not.toHaveProperty('workflowId'), then keep the other call
assertions (or assert the full call args if needed); apply the same change for
the second occurrence that checks workflowId absence.

In `@packages/engine/src/merger-ai.ts`:
- Around line 1008-1022: finalizeTask is rebuilding and persisting mergeDetails
even though finalizeMerged already wrote a complete mergeDetails for non-empty
AI merges, causing duplicate store writes; modify finalizeTask to avoid the
second write by checking for an existing complete mergeDetails (e.g., inspect
result.task.mergeDetails and a reliable marker such as mergedAt or
mergeConfirmed) and only construct+call store.updateTask when mergeDetails is
absent/incomplete (otherwise skip the update), leaving finalizeMerged,
mergeDetails, result.task.mergeDetails, and store.updateTask as the referenced
symbols to locate the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3410eb8c-ba24-484f-82a2-ea61e44d63b3

📥 Commits

Reviewing files that changed from the base of the PR and between 8d7fc1a and 8911676.

📒 Files selected for processing (63)
  • .changeset/fn-6088-workflow-editor-selected-workflow.md
  • .changeset/fn-6091-workflow-id-agent-tools.md
  • .changeset/fn-6092-promote-button.md
  • .changeset/fn-6093-notification-workflow-fix.md
  • .changeset/merge-queued-stalled-review.md
  • docs/PLUGIN_AUTHORING.md
  • docs/dashboard-guide.md
  • docs/plans/2026-06-09-002-refactor-workflow-owned-merge-retry-scheduling-plan.md
  • docs/solutions/integration-issues/bundled-plugin-registration-drift.md
  • docs/solutions/integration-issues/bundled-plugin-vite-alias-missing.md
  • docs/workflow-policy-ownership-map.md
  • eslint.config.mjs
  • packages/cli/skill/fusion/references/engine-tools.md
  • packages/cli/skill/fusion/references/extension-tools.md
  • packages/cli/skill/fusion/references/fusion-capabilities.md
  • packages/cli/src/__tests__/extension.test.ts
  • packages/cli/src/extension.ts
  • packages/core/src/__tests__/store-stalled-review.test.ts
  • packages/core/src/store.ts
  • packages/dashboard/app/api/legacy.ts
  • packages/dashboard/app/components/AppModals.tsx
  • packages/dashboard/app/components/ChatView.css
  • packages/dashboard/app/components/FileBrowser.css
  • packages/dashboard/app/components/FileBrowser.tsx
  • packages/dashboard/app/components/InlineCreateCard.tsx
  • packages/dashboard/app/components/ModelSelectionModal.tsx
  • packages/dashboard/app/components/QuickEntryBox.tsx
  • packages/dashboard/app/components/ReliabilityView.css
  • packages/dashboard/app/components/ReliabilityView.tsx
  • packages/dashboard/app/components/TaskCard.css
  • packages/dashboard/app/components/WorkflowNodeEditor.tsx
  • packages/dashboard/app/components/__tests__/ChatView.chat-input-autosize.test.tsx
  • packages/dashboard/app/components/__tests__/FileBrowser.test.tsx
  • packages/dashboard/app/components/__tests__/InlineCreateCard.test.tsx
  • packages/dashboard/app/components/__tests__/QuickEntryBox.test.tsx
  • packages/dashboard/app/components/__tests__/ReliabilityView.test.tsx
  • packages/dashboard/app/components/__tests__/TaskCard.test.tsx
  • packages/dashboard/app/components/__tests__/WorkflowNodeEditor.css.test.ts
  • packages/dashboard/app/components/__tests__/WorkflowNodeEditor.test.tsx
  • packages/dashboard/src/__tests__/routes-git.test.ts
  • packages/dashboard/src/file-service.ts
  • packages/dashboard/src/routes/README.md
  • packages/dashboard/src/routes/register-file-workspace-routes.ts
  • packages/dashboard/vitest.config.ts
  • packages/engine/src/__tests__/agent-task-creation-github-tracking-flag.test.ts
  • packages/engine/src/__tests__/agent-tools-github-tracking-end-to-end.test.ts
  • packages/engine/src/__tests__/agent-tools.test.ts
  • packages/engine/src/__tests__/merger-ai.test.ts
  • packages/engine/src/__tests__/merger-post-merge.test.ts
  • packages/engine/src/__tests__/notification-service.test.ts
  • packages/engine/src/__tests__/self-healing.test.ts
  • packages/engine/src/__tests__/workflow-policy-ownership-map.test.ts
  • packages/engine/src/agent-tools.ts
  • packages/engine/src/merger-ai.ts
  • packages/engine/src/merger.ts
  • packages/engine/src/notification/notification-service.ts
  • packages/engine/src/notifier.ts
  • packages/engine/src/self-healing.ts
  • packages/engine/vitest.config.ts
  • plugins/fusion-plugin-cli-printing-press/src/index.ts
  • plugins/fusion-plugin-compound-engineering/src/index.ts
  • plugins/fusion-plugin-reports/src/index.ts
  • scripts/lib/test-quarantine.json
💤 Files with no reviewable changes (4)
  • plugins/fusion-plugin-cli-printing-press/src/index.ts
  • plugins/fusion-plugin-reports/src/index.ts
  • packages/dashboard/app/components/QuickEntryBox.tsx
  • plugins/fusion-plugin-compound-engineering/src/index.ts

Comment thread eslint.config.mjs Outdated
Comment thread packages/dashboard/app/components/__tests__/TaskCard.test.tsx Outdated
Comment thread packages/dashboard/src/file-service.ts Outdated
Comment thread packages/engine/src/agent-tools.ts Outdated
@gsxdsm gsxdsm changed the title refactor(workflow): map merge policy ownership refactor(workflow): add workflow-owned merge migration slice Jun 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
packages/core/src/__tests__/db-migrate.test.ts (1)

718-719: ⚡ Quick win

Remove duplicate schema-version assertions in the same test block.

The second assertion is redundant and this pattern repeats in multiple updated tests in this file.

♻️ Proposed cleanup
-    expect(db.getSchemaVersion()).toBe(115);
     expect(db.getSchemaVersion()).toBe(115);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/__tests__/db-migrate.test.ts` around lines 718 - 719,
Remove the duplicate schema-version assertion in the test by deleting the
redundant expect(db.getSchemaVersion()).toBe(115); so each test block only
asserts getSchemaVersion() once; locate the duplicate calls to
getSchemaVersion() in the failing test(s) (search for
expect(db.getSchemaVersion()).toBe(...)) and keep a single assertion per block
to avoid redundant checks.
packages/core/src/__tests__/db.test.ts (1)

337-338: ⚡ Quick win

Collapse duplicated schema-version expectations.

These two assertions are identical with no intervening mutation; this same duplicate pattern appears in multiple changed spots in this file.

♻️ Proposed cleanup
-      expect(db.getSchemaVersion()).toBe(115);
       expect(db.getSchemaVersion()).toBe(115);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/__tests__/db.test.ts` around lines 337 - 338, Remove the
duplicated identical assertion calls that check the schema version; replace
consecutive duplicate expect(db.getSchemaVersion()).toBe(115) lines with a
single assertion. Search for repeated patterns of expect(db.getSchemaVersion())
in the test file (and other duplicated expect calls) and collapse each pair into
one to avoid redundant checks while preserving test semantics.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/__tests__/run-audit.test.ts`:
- Around line 586-588: Rename the test description to match the asserted schema
version: update the `it("schema version is bumped to 40", ...)` test title to
reflect version 115 (for example `it("schema version is bumped to 115", ...)`)
so the human-readable test name aligns with the
`expect(db.getSchemaVersion()).toBe(115);` assertion referencing
`db.getSchemaVersion()`.

In `@packages/core/src/store.ts`:
- Around line 9102-9123: acquireWorkflowWorkItemLease currently allows zero or
negative leaseDurationMs, producing already-expired leases; add the same guard
used by acquireMergeQueueLease by validating opts.leaseDurationMs > 0 at the
start of acquireWorkflowWorkItemLease (before calling
this.db.transactionImmediate) and throw a clear Error (e.g., "leaseDurationMs
must be > 0") when the value is non-positive so the method enforces the same
contract as acquireMergeQueueLease.
- Around line 9076-9099: In listDueWorkflowWorkItems ensure the special "(state
= 'running' AND leaseExpiresAt ...)" branch is only added when the caller's
filter.states either is not provided (current default behavior) or explicitly
includes "running"; when filter.states is provided and does not include
"running" remove that OR branch and do not append the extra now param for it,
and update the conditions/params build (symbols: listDueWorkflowWorkItems,
filter.states, conditions, params) so the prepared SQL and parameter ordering
match the chosen branches (preserve existing handling for kinds and limit).

---

Nitpick comments:
In `@packages/core/src/__tests__/db-migrate.test.ts`:
- Around line 718-719: Remove the duplicate schema-version assertion in the test
by deleting the redundant expect(db.getSchemaVersion()).toBe(115); so each test
block only asserts getSchemaVersion() once; locate the duplicate calls to
getSchemaVersion() in the failing test(s) (search for
expect(db.getSchemaVersion()).toBe(...)) and keep a single assertion per block
to avoid redundant checks.

In `@packages/core/src/__tests__/db.test.ts`:
- Around line 337-338: Remove the duplicated identical assertion calls that
check the schema version; replace consecutive duplicate
expect(db.getSchemaVersion()).toBe(115) lines with a single assertion. Search
for repeated patterns of expect(db.getSchemaVersion()) in the test file (and
other duplicated expect calls) and collapse each pair into one to avoid
redundant checks while preserving test semantics.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 06276cfb-ef03-4b18-bc4d-5ef2e35f4d1f

📥 Commits

Reviewing files that changed from the base of the PR and between 0cb54dd and f16b038.

📒 Files selected for processing (16)
  • .changeset/workflow-work-items.md
  • docs/plans/2026-06-09-003-refactor-workflow-owned-merge-full-migration-slices-plan.md
  • packages/core/src/__tests__/db-migrate.test.ts
  • packages/core/src/__tests__/db.test.ts
  • packages/core/src/__tests__/goals-schema.test.ts
  • packages/core/src/__tests__/insight-store.test.ts
  • packages/core/src/__tests__/merge-request-record.test.ts
  • packages/core/src/__tests__/mission-store.test.ts
  • packages/core/src/__tests__/run-audit.test.ts
  • packages/core/src/__tests__/store-merge-queue.test.ts
  • packages/core/src/__tests__/store-workflow-runtime.test.ts
  • packages/core/src/__tests__/task-documents.test.ts
  • packages/core/src/db.ts
  • packages/core/src/index.ts
  • packages/core/src/store.ts
  • packages/core/src/types.ts
✅ Files skipped from review due to trivial changes (7)
  • packages/core/src/tests/goals-schema.test.ts
  • packages/core/src/tests/task-documents.test.ts
  • packages/core/src/tests/merge-request-record.test.ts
  • packages/core/src/tests/mission-store.test.ts
  • packages/core/src/tests/store-merge-queue.test.ts
  • .changeset/workflow-work-items.md
  • packages/core/src/tests/insight-store.test.ts

Comment thread packages/core/src/__tests__/run-audit.test.ts Outdated
Comment thread packages/core/src/store.ts
Comment thread packages/core/src/store.ts
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@gsxdsm

gsxdsm commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator Author

Resolved Greptile ownership-map path feedback in efe7db64f: workflow-policy-ownership-map.test.ts now resolves the doc path from import.meta.url instead of process.cwd(). Verified with pnpm --filter @fusion/engine exec vitest run src/__tests__/workflow-policy-ownership-map.test.ts --silent=passed-only --reporter=dot, pnpm --filter @fusion/engine typecheck, and pnpm test:gate.

@gsxdsm gsxdsm merged commit 46db9a7 into main Jun 11, 2026
6 checks passed
@gsxdsm gsxdsm deleted the feature/workflow-owned-merge-retry-scheduling-plan branch June 11, 2026 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant