test(FN-889): add regression tests for merger import chain and runtime export contract

- Add integration tests verifying export/import contract for merger restart scenarios
- Enhance regression coverage for the full merger import chain
- Add developer note in README on keeping runtime exports in sync with dist artifacts
- All tests passing, build verified
This commit is contained in:
gsxdsm
2026-04-04 20:19:13 -07:00
parent 6ce2b7eaff
commit 44447af7a9
2 changed files with 45 additions and 0 deletions

View File

@@ -388,6 +388,17 @@ pnpm typecheck # Type-check all packages
This command validates TypeScript across all packages using source file resolution, without requiring `dist/` output from prior builds. Run it after cloning or before committing to catch type errors early.
### Keeping Runtime Exports in Sync
When `@fusion/core` (or any workspace package) adds, renames, or removes an exported function, the `dist/` artifacts must be regenerated before downstream consumers (like `@fusion/engine`) can import the change at runtime. The workspace is configured so that TypeScript resolves types from source (`src/index.ts`), but the Node.js runtime resolves from compiled output (`dist/index.js`). If these fall out of sync, engine tests may fail with `TypeError: ... is not a function` or module import errors.
**After modifying exports in `@fusion/core`:**
```bash
pnpm --filter @fusion/core build # Regenerate dist/
pnpm test # Verify downstream consumers
```
## Dashboard Features
### Interactive Terminal

View File

@@ -1102,3 +1102,37 @@ describe("Engine pause/unpause cycle", () => {
expect(secondSlotAcquired).toBe(true);
});
});
// ── Regression: getTaskMergeBlocker import contract ──────────────────────
describe("getTaskMergeBlocker import regression", () => {
it("getTaskMergeBlocker is importable from @fusion/core at runtime", async () => {
// Dynamic import to verify the runtime export contract — if this fails,
// packages/core/dist/index.js is stale or the export was removed.
const core = await import("@fusion/core");
expect(typeof core.getTaskMergeBlocker).toBe("function");
expect(typeof core.isTaskReadyForMerge).toBe("function");
});
it("getTaskMergeBlocker rejects non-in-review tasks", async () => {
const { getTaskMergeBlocker } = await import("@fusion/core");
const blocker = getTaskMergeBlocker({
column: "in-progress",
paused: false,
status: undefined,
error: undefined,
steps: [],
workflowStepResults: [],
});
expect(blocker).toContain("must be in 'in-review'");
});
it("aiMergeTask can be loaded from merger module (getTaskMergeBlocker reachable)", async () => {
// Verify the merger module itself loads without import errors.
// aiMergeTask internally uses getTaskMergeBlocker from @fusion/core —
// if the core export is broken, this dynamic import will fail.
const merger = await import("./merger.js");
expect(typeof merger.aiMergeTask).toBe("function");
expect(typeof merger.findWorktreeUser).toBe("function");
});
});