feat(KB-330): rename internal packages from @kb/* to @fusion/*

- Rename @kb/core, @kb/dashboard, @kb/engine to @fusion/* namespace
- Update all import statements across 143+ files to use new package names
- Update workspace dependencies and root package.json references
- Fix bundler configurations (tsup, vite) for new package names
- Update test files and fix typecheck issues
- Add changeset file documenting the package rename
This commit is contained in:
gsxdsm
2026-03-31 13:33:44 -07:00
parent c6fe660dd9
commit fc0411713c
142 changed files with 340 additions and 328 deletions

View File

@@ -15,18 +15,18 @@ describe("CLI bundle output", () => {
expect(content.startsWith("#!/usr/bin/env node")).toBe(true);
});
it("does not contain bare @kb/* import specifiers", () => {
it("does not contain bare @fusion/* import specifiers", () => {
const content = readFileSync(bundlePath, "utf-8");
expect(content).not.toMatch(/from\s+["']@kb\/core["']/);
expect(content).not.toMatch(/from\s+["']@kb\/dashboard["']/);
expect(content).not.toMatch(/from\s+["']@kb\/engine["']/);
expect(content).not.toMatch(/from\s+["']@fusion\/core["']/);
expect(content).not.toMatch(/from\s+["']@fusion\/dashboard["']/);
expect(content).not.toMatch(/from\s+["']@fusion\/engine["']/);
});
it("contains inlined workspace code", () => {
const content = readFileSync(bundlePath, "utf-8");
// TaskStore from @kb/core
// TaskStore from @fusion/core
expect(content).toContain("TaskStore");
// createServer from @kb/dashboard
// createServer from @fusion/dashboard
expect(content).toContain("createServer");
});

View File

@@ -4,7 +4,7 @@ import { join } from "node:path";
import { tmpdir } from "node:os";
import kbExtension from "../extension.js";
import { TaskStore } from "@kb/core";
import { TaskStore } from "@fusion/core";
// ── Mock ExtensionAPI that captures registrations ──────────────────

View File

@@ -75,11 +75,11 @@ describe("CLI package.json publishing config", () => {
});
});
describe("Scoped @kb/* packages publishing config", () => {
describe("Scoped @fusion/* packages publishing config", () => {
const scopedPackages = ["core", "engine", "dashboard"];
for (const name of scopedPackages) {
describe(`@kb/${name}`, () => {
describe(`@fusion/${name}`, () => {
const pkg = loadPackageJson(name);
it('has publishConfig with access "public"', () => {

View File

@@ -5,8 +5,8 @@ vi.mock("node:readline/promises", () => ({
createInterface: vi.fn(),
}));
// Mock @kb/core before importing
vi.mock("@kb/core", () => ({
// Mock @fusion/core before importing
vi.mock("@fusion/core", () => ({
TaskStore: vi.fn(),
COLUMNS: ["triage", "todo", "in-progress", "in-review", "done", "archived"],
COLUMN_LABELS: {
@@ -19,8 +19,8 @@ vi.mock("@kb/core", () => ({
},
}));
// Mock @kb/dashboard/planning
vi.mock("@kb/dashboard/planning", () => ({
// Mock @fusion/dashboard/planning
vi.mock("@fusion/dashboard/planning", () => ({
createSession: vi.fn(),
submitResponse: vi.fn(),
RateLimitError: class RateLimitError extends Error {
@@ -45,8 +45,8 @@ vi.mock("@kb/dashboard/planning", () => ({
// Import after mocking
import { createInterface } from "node:readline/promises";
import { TaskStore } from "@kb/core";
import { createSession, submitResponse, RateLimitError, SessionNotFoundError } from "@kb/dashboard/planning";
import { TaskStore } from "@fusion/core";
import { createSession, submitResponse, RateLimitError, SessionNotFoundError } from "@fusion/dashboard/planning";
import { runTaskPlan } from "../commands/task.js";
describe("runTaskPlan", () => {

View File

@@ -5,8 +5,8 @@ vi.mock("node:readline/promises", () => ({
createInterface: vi.fn(),
}));
// Mock @kb/core before importing
vi.mock("@kb/core", () => ({
// Mock @fusion/core before importing
vi.mock("@fusion/core", () => ({
TaskStore: vi.fn(),
COLUMNS: ["triage", "todo", "in-progress", "in-review", "done", "archived"],
COLUMN_LABELS: {
@@ -21,7 +21,7 @@ vi.mock("@kb/core", () => ({
// Import after mocking
import { createInterface } from "node:readline/promises";
import { TaskStore } from "@kb/core";
import { TaskStore } from "@fusion/core";
import { runTaskSteer } from "../commands/task.js";
describe("runTaskSteer", () => {

View File

@@ -24,9 +24,9 @@ function makeMockStore() {
};
}
// ── Mock @kb/core ──────────────────────────────────────────────────
// ── Mock @fusion/core ──────────────────────────────────────────────────
vi.mock("@kb/core", () => ({
vi.mock("@fusion/core", () => ({
TaskStore: vi.fn().mockImplementation(() => makeMockStore()),
AutomationStore: vi.fn().mockImplementation(() => ({
init: vi.fn().mockResolvedValue(undefined),
@@ -35,7 +35,7 @@ vi.mock("@kb/core", () => ({
})),
}));
// ── Mock @kb/dashboard ─────────────────────────────────────────────
// ── Mock @fusion/dashboard ─────────────────────────────────────────────
/** Create a mock server (EventEmitter) that simulates net.Server behavior. */
function createMockServer(portToReturn: number = 0) {
@@ -64,15 +64,15 @@ const MockGitHubClient = vi.fn().mockImplementation(() => ({
mergePr: vi.fn(),
}));
vi.mock("@kb/dashboard", () => ({
vi.mock("@fusion/dashboard", () => ({
createServer: vi.fn(() => ({ listen: mockListen })),
GitHubClient: MockGitHubClient,
}));
// ── Mock @kb/engine ────────────────────────────────────────────────
// ── Mock @fusion/engine ────────────────────────────────────────────────
vi.mock("@kb/engine", async (importOriginal) => {
const original = await importOriginal<typeof import("@kb/engine")>();
vi.mock("@fusion/engine", async (importOriginal) => {
const original = await importOriginal<typeof import("@fusion/engine")>();
return {
...original,
WorktreePool: original.WorktreePool,
@@ -134,12 +134,12 @@ describe("runDashboard — AuthStorage & ModelRegistry wiring", () => {
runtime: { pendingProviderRegistrations: [] },
errors: [],
});
const { TaskStore } = await import("@kb/core");
const { TaskStore } = await import("@fusion/core");
(TaskStore as ReturnType<typeof vi.fn>).mockImplementation(() => makeMockStore());
});
it("passes authStorage and modelRegistry to createServer", async () => {
const { createServer } = await import("@kb/dashboard");
const { createServer } = await import("@fusion/dashboard");
await runDashboard(0, {});

View File

@@ -33,9 +33,9 @@ function makeMockStore() {
};
}
// ── Mock @kb/core ──────────────────────────────────────────────────
// ── Mock @fusion/core ──────────────────────────────────────────────────
vi.mock("@kb/core", () => ({
vi.mock("@fusion/core", () => ({
TaskStore: vi.fn().mockImplementation(() => makeMockStore()),
AutomationStore: vi.fn().mockImplementation(() => ({
init: vi.fn().mockResolvedValue(undefined),
@@ -78,7 +78,7 @@ vi.mock("node:child_process", async (importOriginal) => {
};
});
// ── Mock @kb/dashboard ─────────────────────────────────────────────
// ── Mock @fusion/dashboard ─────────────────────────────────────────────
/** Create a mock server (EventEmitter) that simulates net.Server behavior. */
function createMockServer(portToReturn: number = 0) {
@@ -100,7 +100,7 @@ const mockListen = vi.fn((port: number) => {
return server;
});
vi.mock("@kb/dashboard", () => ({
vi.mock("@fusion/dashboard", () => ({
createServer: vi.fn(() => ({ listen: mockListen })),
GitHubClient: vi.fn().mockImplementation(() => ({
findPrForBranch: mockFindPrForBranch,
@@ -116,13 +116,13 @@ vi.mock("node:readline", () => ({
createInterface: vi.fn(),
}));
// ── Mock @kb/engine ────────────────────────────────────────────────
// ── Mock @fusion/engine ────────────────────────────────────────────────
// We need the real WorktreePool class so we can assert `instanceof`.
const { WorktreePool } = await import("@kb/engine");
const { WorktreePool } = await import("@fusion/engine");
vi.mock("@kb/engine", async (importOriginal) => {
const original = await importOriginal<typeof import("@kb/engine")>();
vi.mock("@fusion/engine", async (importOriginal) => {
const original = await importOriginal<typeof import("@fusion/engine")>();
return {
...original,
// Keep real WorktreePool & AgentSemaphore
@@ -452,12 +452,12 @@ describe("runDashboard — PR-first auto-merge queue", () => {
log: [],
});
const { TaskStore } = await import("@kb/core");
const { TaskStore } = await import("@fusion/core");
(TaskStore as ReturnType<typeof vi.fn>).mockImplementation(() => mockStore);
});
it("uses PR lifecycle instead of aiMergeTask when mergeStrategy is pull-request", async () => {
const { aiMergeTask } = await import("@kb/engine");
const { aiMergeTask } = await import("@fusion/engine");
await runDashboard(0, { open: false });
await new Promise((r) => setTimeout(r, 100));
@@ -477,10 +477,10 @@ describe("runDashboard — WorktreePool wiring", () => {
vi.clearAllMocks();
resetGitHubMocks();
// Re-set TaskStore mock (clearAllMocks wipes implementations)
const { TaskStore } = await import("@kb/core");
const { TaskStore } = await import("@fusion/core");
(TaskStore as ReturnType<typeof vi.fn>).mockImplementation(() => makeMockStore());
// Re-set engine mocks
const engine = await import("@kb/engine");
const engine = await import("@fusion/engine");
(engine.aiMergeTask as ReturnType<typeof vi.fn>).mockImplementation(() =>
Promise.resolve({ merged: true }),
);
@@ -500,8 +500,8 @@ describe("runDashboard — WorktreePool wiring", () => {
});
it("passes a WorktreePool instance to aiMergeTask via rawMerge", async () => {
const { aiMergeTask } = await import("@kb/engine");
const { createServer } = await import("@kb/dashboard");
const { aiMergeTask } = await import("@fusion/engine");
const { createServer } = await import("@fusion/dashboard");
await runDashboard(0, { open: false });
@@ -518,8 +518,8 @@ describe("runDashboard — WorktreePool wiring", () => {
});
it("shares the same WorktreePool instance between executor and merger", async () => {
const { aiMergeTask } = await import("@kb/engine");
const { createServer } = await import("@kb/dashboard");
const { aiMergeTask } = await import("@fusion/engine");
const { createServer } = await import("@fusion/dashboard");
await runDashboard(0, { open: false });
@@ -545,9 +545,9 @@ describe("runDashboard — auto-merge pause exclusion", () => {
vi.clearAllMocks();
resetGitHubMocks();
mockStore = makeMockStore();
const { TaskStore } = await import("@kb/core");
const { TaskStore } = await import("@fusion/core");
(TaskStore as ReturnType<typeof vi.fn>).mockImplementation(() => mockStore);
const engine = await import("@kb/engine");
const engine = await import("@fusion/engine");
(engine.aiMergeTask as ReturnType<typeof vi.fn>).mockImplementation(() =>
Promise.resolve({ merged: true }),
);
@@ -569,7 +569,7 @@ describe("runDashboard — auto-merge pause exclusion", () => {
await runDashboard(0, { open: false });
const { aiMergeTask } = await import("@kb/engine");
const { aiMergeTask } = await import("@fusion/engine");
// Emit task:moved with a paused task
mockStore.emit("task:moved", {
@@ -596,7 +596,7 @@ describe("runDashboard — auto-merge pause exclusion", () => {
{ id: "KB-ACTIVE", column: "in-review", paused: false },
]);
const { aiMergeTask } = await import("@kb/engine");
const { aiMergeTask } = await import("@fusion/engine");
// Reset after import
(aiMergeTask as ReturnType<typeof vi.fn>).mockImplementation(() =>
Promise.resolve({ merged: true }),
@@ -623,9 +623,9 @@ describe("runDashboard — immediate resume on unpause", () => {
vi.clearAllMocks();
resetGitHubMocks();
mockStore = makeMockStore();
const { TaskStore } = await import("@kb/core");
const { TaskStore } = await import("@fusion/core");
(TaskStore as ReturnType<typeof vi.fn>).mockImplementation(() => mockStore);
const engine = await import("@kb/engine");
const engine = await import("@fusion/engine");
(engine.aiMergeTask as ReturnType<typeof vi.fn>).mockImplementation(() =>
Promise.resolve({ merged: true }),
);
@@ -649,7 +649,7 @@ describe("runDashboard — immediate resume on unpause", () => {
});
it("calls executor.resumeOrphaned() when globalPause transitions true → false", async () => {
const { TaskExecutor } = await import("@kb/engine");
const { TaskExecutor } = await import("@fusion/engine");
const resumeOrphaned = vi.fn().mockResolvedValue(undefined);
(TaskExecutor as unknown as ReturnType<typeof vi.fn>).mockImplementation(
(_store: unknown, _cwd: unknown, opts: unknown) => {
@@ -694,7 +694,7 @@ describe("runDashboard — immediate resume on unpause", () => {
paused: false,
}));
const { aiMergeTask } = await import("@kb/engine");
const { aiMergeTask } = await import("@fusion/engine");
(aiMergeTask as ReturnType<typeof vi.fn>).mockImplementation(() =>
Promise.resolve({ merged: true }),
);
@@ -729,16 +729,16 @@ describe("runDashboard — engine pause/unpause cycle", () => {
vi.clearAllMocks();
resetGitHubMocks();
mockStore = makeMockStore();
const { TaskStore } = await import("@kb/core");
const { TaskStore } = await import("@fusion/core");
(TaskStore as ReturnType<typeof vi.fn>).mockImplementation(() => mockStore);
const engine = await import("@kb/engine");
const engine = await import("@fusion/engine");
(engine.aiMergeTask as ReturnType<typeof vi.fn>).mockImplementation(() =>
Promise.resolve({ merged: true }),
);
});
it("calls executor.resumeOrphaned() when enginePaused transitions true → false", async () => {
const { TaskExecutor } = await import("@kb/engine");
const { TaskExecutor } = await import("@fusion/engine");
const resumeOrphaned = vi.fn().mockResolvedValue(undefined);
(TaskExecutor as unknown as ReturnType<typeof vi.fn>).mockImplementation(
(_store: unknown, _cwd: unknown, opts: unknown) => {
@@ -770,9 +770,9 @@ describe("runDashboard — port fallback on EADDRINUSE", () => {
beforeEach(async () => {
vi.clearAllMocks();
resetGitHubMocks();
const { TaskStore } = await import("@kb/core");
const { TaskStore } = await import("@fusion/core");
(TaskStore as ReturnType<typeof vi.fn>).mockImplementation(() => makeMockStore());
const engine = await import("@kb/engine");
const engine = await import("@fusion/engine");
(engine.TaskExecutor as unknown as ReturnType<typeof vi.fn>).mockImplementation(
() => ({ resumeOrphaned: vi.fn().mockResolvedValue(undefined) }),
);
@@ -888,9 +888,9 @@ describe("runDashboard — enginePaused (soft pause)", () => {
vi.clearAllMocks();
resetGitHubMocks();
mockStore = makeMockStore();
const { TaskStore } = await import("@kb/core");
const { TaskStore } = await import("@fusion/core");
(TaskStore as ReturnType<typeof vi.fn>).mockImplementation(() => mockStore);
const engine = await import("@kb/engine");
const engine = await import("@fusion/engine");
(engine.aiMergeTask as ReturnType<typeof vi.fn>).mockImplementation(() =>
Promise.resolve({ merged: true }),
);
@@ -913,7 +913,7 @@ describe("runDashboard — enginePaused (soft pause)", () => {
await runDashboard(0, { open: false });
const { aiMergeTask } = await import("@kb/engine");
const { aiMergeTask } = await import("@fusion/engine");
// Emit task:moved
mockStore.emit("task:moved", {
@@ -928,7 +928,7 @@ describe("runDashboard — enginePaused (soft pause)", () => {
});
it("calls executor.resumeOrphaned() when enginePaused transitions true → false", async () => {
const { TaskExecutor } = await import("@kb/engine");
const { TaskExecutor } = await import("@fusion/engine");
const resumeOrphaned = vi.fn().mockResolvedValue(undefined);
(TaskExecutor as unknown as ReturnType<typeof vi.fn>).mockImplementation(
(_store: unknown, _cwd: unknown, opts: unknown) => {
@@ -971,7 +971,7 @@ describe("runDashboard — enginePaused (soft pause)", () => {
paused: false,
}));
const { aiMergeTask } = await import("@kb/engine");
const { aiMergeTask } = await import("@fusion/engine");
(aiMergeTask as ReturnType<typeof vi.fn>).mockImplementation(() =>
Promise.resolve({ merged: true }),
);
@@ -1003,9 +1003,9 @@ describe("runDashboard — --paused flag", () => {
vi.clearAllMocks();
resetGitHubMocks();
mockStore = makeMockStore();
const { TaskStore } = await import("@kb/core");
const { TaskStore } = await import("@fusion/core");
(TaskStore as ReturnType<typeof vi.fn>).mockImplementation(() => mockStore);
const engine = await import("@kb/engine");
const engine = await import("@fusion/engine");
(engine.aiMergeTask as ReturnType<typeof vi.fn>).mockImplementation(() =>
Promise.resolve({ merged: true }),
);
@@ -1064,9 +1064,9 @@ describe("runDashboard — --paused flag", () => {
vi.clearAllMocks();
resetGitHubMocks();
mockStore = makeMockStore();
const { TaskStore } = await import("@kb/core");
const { TaskStore } = await import("@fusion/core");
(TaskStore as ReturnType<typeof vi.fn>).mockImplementation(() => mockStore);
const engine = await import("@kb/engine");
const engine = await import("@fusion/engine");
(engine.TaskExecutor as unknown as ReturnType<typeof vi.fn>).mockImplementation(
() => ({ resumeOrphaned: vi.fn().mockResolvedValue(undefined) }),
);
@@ -1117,9 +1117,9 @@ describe("runDashboard — --dev mode", () => {
vi.clearAllMocks();
resetGitHubMocks();
mockStore = makeMockStore();
const { TaskStore } = await import("@kb/core");
const { TaskStore } = await import("@fusion/core");
(TaskStore as ReturnType<typeof vi.fn>).mockImplementation(() => mockStore);
const engine = await import("@kb/engine");
const engine = await import("@fusion/engine");
(engine.aiMergeTask as ReturnType<typeof vi.fn>).mockImplementation(() =>
Promise.resolve({ merged: true }),
);
@@ -1137,25 +1137,25 @@ describe("runDashboard — --dev mode", () => {
});
it("does NOT start TriageProcessor in dev mode", async () => {
const { TriageProcessor } = await import("@kb/engine");
const { TriageProcessor } = await import("@fusion/engine");
await runDashboard(0, { open: false, dev: true });
expect(TriageProcessor).not.toHaveBeenCalled();
});
it("does NOT start TaskExecutor in dev mode", async () => {
const { TaskExecutor } = await import("@kb/engine");
const { TaskExecutor } = await import("@fusion/engine");
await runDashboard(0, { open: false, dev: true });
expect(TaskExecutor).not.toHaveBeenCalled();
});
it("does NOT start Scheduler in dev mode", async () => {
const { Scheduler } = await import("@kb/engine");
const { Scheduler } = await import("@fusion/engine");
await runDashboard(0, { open: false, dev: true });
expect(Scheduler).not.toHaveBeenCalled();
});
it("starts the server correctly in dev mode", async () => {
const { createServer } = await import("@kb/dashboard");
const { createServer } = await import("@fusion/dashboard");
await runDashboard(4040, { open: false, dev: true });
// Wait for async 'listening' event
@@ -1201,7 +1201,7 @@ describe("runDashboard — --dev mode", () => {
});
it("starts all engine components when dev is false (default)", async () => {
const { TriageProcessor, TaskExecutor, Scheduler } = await import("@kb/engine");
const { TriageProcessor, TaskExecutor, Scheduler } = await import("@fusion/engine");
await runDashboard(0, { open: false });
expect(TriageProcessor).toHaveBeenCalled();
@@ -1231,7 +1231,7 @@ describe("runDashboard — merge conflict retry logic", () => {
vi.clearAllMocks();
resetGitHubMocks();
mockStore = makeMockStore();
const { TaskStore } = await import("@kb/core");
const { TaskStore } = await import("@fusion/core");
(TaskStore as ReturnType<typeof vi.fn>).mockImplementation(() => mockStore);
// Default mock store.getTask implementation
@@ -1242,7 +1242,7 @@ describe("runDashboard — merge conflict retry logic", () => {
mergeRetries: 0,
}));
const engine = await import("@kb/engine");
const engine = await import("@fusion/engine");
(engine.aiMergeTask as ReturnType<typeof vi.fn>).mockImplementation(() =>
Promise.resolve({ merged: true }),
);
@@ -1260,7 +1260,7 @@ describe("runDashboard — merge conflict retry logic", () => {
});
it("increments mergeRetries and re-enqueues on conflict error", async () => {
const { aiMergeTask } = await import("@kb/engine");
const { aiMergeTask } = await import("@fusion/engine");
// Simulate merge failure with conflict
(aiMergeTask as ReturnType<typeof vi.fn>).mockRejectedValue(
@@ -1300,7 +1300,7 @@ describe("runDashboard — merge conflict retry logic", () => {
});
it("gives up after max retries (3) exceeded", async () => {
const { aiMergeTask } = await import("@kb/engine");
const { aiMergeTask } = await import("@fusion/engine");
(aiMergeTask as ReturnType<typeof vi.fn>).mockRejectedValue(
new Error("Merge conflict detected"),
@@ -1347,7 +1347,7 @@ describe("runDashboard — merge conflict retry logic", () => {
});
it("skips retry when autoResolveConflicts is disabled", async () => {
const { aiMergeTask } = await import("@kb/engine");
const { aiMergeTask } = await import("@fusion/engine");
(aiMergeTask as ReturnType<typeof vi.fn>).mockRejectedValue(
new Error("Merge conflict detected"),
@@ -1381,7 +1381,7 @@ describe("runDashboard — merge conflict retry logic", () => {
});
it("clears mergeRetries on successful merge after retries", async () => {
const { aiMergeTask } = await import("@kb/engine");
const { aiMergeTask } = await import("@fusion/engine");
(aiMergeTask as ReturnType<typeof vi.fn>).mockResolvedValue({ merged: true });

View File

@@ -1,10 +1,10 @@
import { execSync } from "node:child_process";
import type { AddressInfo } from "node:net";
import { createInterface } from "node:readline";
import { TaskStore, AutomationStore } from "@kb/core";
import type { Settings, TaskDetail, PrInfo } from "@kb/core";
import { createServer, GitHubClient } from "@kb/dashboard";
import { TriageProcessor, TaskExecutor, Scheduler, AgentSemaphore, WorktreePool, aiMergeTask, UsageLimitPauser, PRIORITY_MERGE, scanIdleWorktrees, cleanupOrphanedWorktrees, NtfyNotifier, PrMonitor, PrCommentHandler, CronRunner, StuckTaskDetector } from "@kb/engine";
import { TaskStore, AutomationStore } from "@fusion/core";
import type { Settings, TaskDetail, PrInfo } from "@fusion/core";
import { createServer, GitHubClient } from "@fusion/dashboard";
import { TriageProcessor, TaskExecutor, Scheduler, AgentSemaphore, WorktreePool, aiMergeTask, UsageLimitPauser, PRIORITY_MERGE, scanIdleWorktrees, cleanupOrphanedWorktrees, NtfyNotifier, PrMonitor, PrCommentHandler, CronRunner, StuckTaskDetector } from "@fusion/engine";
import { AuthStorage, ModelRegistry, discoverAndLoadExtensions, createExtensionRuntime } from "@mariozechner/pi-coding-agent";
/**

View File

@@ -1,7 +1,7 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
// Mock @kb/core before importing the module under test
vi.mock("@kb/core", () => {
// Mock @fusion/core before importing the module under test
vi.mock("@fusion/core", () => {
const DEFAULT_SETTINGS = {
maxConcurrent: 2,
maxWorktrees: 4,
@@ -21,7 +21,7 @@ vi.mock("@kb/core", () => {
};
});
import { TaskStore, DEFAULT_SETTINGS } from "@kb/core";
import { TaskStore, DEFAULT_SETTINGS } from "@fusion/core";
import {
runSettingsShow,
runSettingsSet,

View File

@@ -1,4 +1,4 @@
import { TaskStore, type Settings, DEFAULT_SETTINGS } from "@kb/core";
import { TaskStore, type Settings, DEFAULT_SETTINGS } from "@fusion/core";
// Settings that can be updated via CLI
export const VALID_SETTINGS = [

View File

@@ -14,8 +14,8 @@ vi.mock("node:fs", () => ({
readFileSync: vi.fn(),
}));
// Mock @kb/core before importing the module under test
vi.mock("@kb/core", () => {
// Mock @fusion/core before importing the module under test
vi.mock("@fusion/core", () => {
const COLUMNS = ["triage", "specified", "in-progress", "review", "done"];
const COLUMN_LABELS: Record<string, string> = {
triage: "Triage",
@@ -32,29 +32,29 @@ vi.mock("@kb/core", () => {
};
});
// Mock @kb/engine
vi.mock("@kb/engine", () => ({ aiMergeTask: vi.fn() }));
// Mock @fusion/engine
vi.mock("@fusion/engine", () => ({ aiMergeTask: vi.fn() }));
// Mock @kb/dashboard
vi.mock("@kb/dashboard", () => ({
// Mock @fusion/dashboard
vi.mock("@fusion/dashboard", () => ({
GitHubClient: vi.fn().mockImplementation(() => ({
createPr: vi.fn(),
})),
}));
// Mock @kb/core/gh-cli
vi.mock("@kb/core/gh-cli", () => ({
// Mock @fusion/core/gh-cli
vi.mock("@fusion/core/gh-cli", () => ({
isGhAvailable: vi.fn(),
isGhAuthenticated: vi.fn(),
getCurrentRepo: vi.fn(),
}));
import { createInterface } from "node:readline/promises";
import { TaskStore } from "@kb/core";
import { TaskStore } from "@fusion/core";
import { watchFile, unwatchFile, statSync, existsSync, readFileSync } from "node:fs";
import { runTaskShow, runTaskCreate, runTaskDuplicate, runTaskRefine, runTaskDelete, runTaskRetry, runTaskLogs, runTaskPrCreate, type LogsOptions } from "./task.js";
import { isGhAvailable, isGhAuthenticated, getCurrentRepo } from "@kb/core/gh-cli";
import { GitHubClient } from "@kb/dashboard";
import { isGhAvailable, isGhAuthenticated, getCurrentRepo } from "@fusion/core/gh-cli";
import { GitHubClient } from "@fusion/dashboard";
function makeTask(overrides: Record<string, unknown> = {}) {
return {
@@ -1299,7 +1299,7 @@ describe("runTaskLogs", () => {
let mockReadFileSync: ReturnType<typeof vi.fn>;
let sigintHandlers: Array<() => void> = [];
function makeAgentLogEntry(overrides: Record<string, unknown> = {}): import("@kb/core").AgentLogEntry {
function makeAgentLogEntry(overrides: Record<string, unknown> = {}): import("@fusion/core").AgentLogEntry {
return {
timestamp: new Date().toISOString(),
taskId: "KB-001",
@@ -1461,7 +1461,7 @@ describe("runTaskLogs", () => {
it("filters by type with --limit combined", async () => {
mockGetTask.mockResolvedValueOnce(makeTask({ id: "KB-001" }));
// Create 50 tool entries interspersed with text entries
const entries: import("@kb/core").AgentLogEntry[] = [];
const entries: import("@fusion/core").AgentLogEntry[] = [];
for (let i = 0; i < 100; i++) {
entries.push(makeAgentLogEntry({
type: i % 2 === 0 ? "tool" : "text",
@@ -1599,7 +1599,7 @@ describe("runTaskLogs", () => {
// ── PR Create Tests ───────────────────────────────────────────────────────────
import type { PrInfo } from "@kb/core";
import type { PrInfo } from "@fusion/core";
describe("runTaskPrCreate", () => {
let logSpy: ReturnType<typeof vi.spyOn>;

View File

@@ -1,12 +1,12 @@
import { TaskStore, COLUMNS, COLUMN_LABELS, type Column, type MergeResult, type StepStatus, type AgentLogType, type AgentLogEntry } from "@kb/core";
import { aiMergeTask } from "@kb/engine";
import { TaskStore, COLUMNS, COLUMN_LABELS, type Column, type MergeResult, type StepStatus, type AgentLogType, type AgentLogEntry } from "@fusion/core";
import { aiMergeTask } from "@fusion/engine";
import { createInterface } from "node:readline/promises";
import type { PlanningQuestion, PlanningSummary } from "@kb/core";
import { createSession, submitResponse, RateLimitError, SessionNotFoundError, InvalidSessionStateError } from "@kb/dashboard/planning";
import type { PlanningQuestion, PlanningSummary } from "@fusion/core";
import { createSession, submitResponse, RateLimitError, SessionNotFoundError, InvalidSessionStateError } from "@fusion/dashboard/planning";
import { watchFile, unwatchFile, statSync, existsSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { GitHubClient } from "@kb/dashboard";
import { isGhAvailable, isGhAuthenticated, getCurrentRepo } from "@kb/core/gh-cli";
import { GitHubClient } from "@fusion/dashboard";
import { isGhAvailable, isGhAuthenticated, getCurrentRepo } from "@fusion/core/gh-cli";
const STEP_STATUSES: StepStatus[] = ["pending", "in-progress", "done", "skipped"];

View File

@@ -7,7 +7,7 @@ import {
COLUMN_LABELS,
type Column,
type Task,
} from "@kb/core";
} from "@fusion/core";
import { resolve, basename, extname } from "node:path";
import { readFile } from "node:fs/promises";
import { spawn, type ChildProcess } from "node:child_process";