Files
fusion/packages/dashboard/src/test/mockCoreEngine.ts
gsxdsm af06170a51 FN-6778: add agent artifact registry tools
Adds engine and chat tools for registering, discovering, and viewing artifacts with inbox notifications.

- Add fn_artifact_register, fn_artifact_list, and fn_artifact_view tools for heartbeat, executor, and chat sessions.
- Send best-effort dashboard system inbox notifications when artifacts are registered.
- Classify artifact tools for action gating and coordination exemptions, with coverage for executor, heartbeat, permanent agent, and chat flows.
- Document the artifact registry behavior and update package metadata, quarantine ledger, and line-count baseline.

Files changed:
 .changeset/fn-6778-artifact-agent-tools.md         |   5 +
 CONCEPTS.md                                        |   3 +
 docs/agents.md                                     |   1 +
 packages/core/src/db.ts                            |   1 +
 .../src/__tests__/session-error-recovery.test.ts   |   1 +
 .../session-persistence-roundtrip.test.ts          |   1 +
 .../src/__tests__/session-reconnect.test.ts        |   1 +
 .../src/__tests__/session-resume-history.test.ts   |   1 +
 packages/dashboard/src/chat.ts                     |   6 +-
 packages/dashboard/src/planning.ts                 |   4 +
 packages/dashboard/src/test/mockCoreEngine.ts      |   1 +
 .../engine/src/__tests__/agent-action-gate.test.ts |   3 +
 .../src/__tests__/agent-artifact-tools.test.ts     | 458 +++++++++++++++++++++
 .../src/__tests__/executor-step-session.test.ts    |  48 +++
 .../src/__tests__/gating-classifications.test.ts   |   3 +
 .../src/__tests__/heartbeat-executor.test.ts       |  40 +-
 .../src/__tests__/heartbeat-session-prompt.test.ts |  25 +-
 .../src/__tests__/permanent-agent-gating.test.ts   |   6 +
 packages/engine/src/agent-heartbeat.ts             |   6 +-
 packages/engine/src/agent-tools.ts                 | 288 ++++++++++++-
 packages/engine/src/executor.ts                    |  25 ++
 packages/engine/src/gating-classifications.ts      |   7 +
 packages/engine/src/index.ts                       |   9 +
 scripts/lib/test-quarantine.json                   |   8 +-
 scripts/line-count-baseline.json                   |  54 +--
 25 files changed, 945 insertions(+), 60 deletions(-)

Fusion-Task-Id: FN-6778
Fusion-Task-Lineage: 7eb4afcb-8140-4f86-9540-eb3b83e64148
2026-06-22 03:34:14 -07:00

76 lines
2.8 KiB
TypeScript

/**
* Canonical @fusion/core and @fusion/engine mock helpers for dashboard server tests.
*
* If a route test starts failing with "No \"X\" export is defined", update this
* helper first instead of adding another full inline export map in the test file.
*/
import { vi, type Mock } from "vitest";
type AnyModule = Record<string, unknown>;
type AnyMock = Mock;
const fallbackFns = new Map<string, AnyMock>();
function getFallback(name: string): AnyMock {
if (!fallbackFns.has(name)) fallbackFns.set(name, vi.fn());
return fallbackFns.get(name)!;
}
function withFallbackFunctions(actual: AnyModule, moduleValue: AnyModule): AnyModule {
return new Proxy(moduleValue, {
get(target, prop, receiver) {
if (typeof prop !== "string") return Reflect.get(target, prop, receiver);
if (Reflect.has(target, prop)) return Reflect.get(target, prop, receiver);
if (["then", "catch", "finally"].includes(prop)) return undefined;
const actualValue = actual[prop];
if (typeof actualValue === "function" || actualValue === undefined) {
const fn = getFallback(prop);
target[prop] = fn;
return fn;
}
return actualValue;
},
});
}
export async function createCoreMock(
importActual: () => Promise<AnyModule>,
overrides: AnyModule = {},
): Promise<AnyModule> {
const actual = await importActual();
return withFallbackFunctions(actual, { ...actual, ...overrides });
}
export function createEngineMock(overrides: AnyModule = {}): AnyModule {
const actual: AnyModule = {};
return withFallbackFunctions(actual, {
createFnAgent: vi.fn(),
promptWithFallback: vi.fn(),
/*
FNXC:TestSkills 2026-06-17-19:33:
Dashboard route tests mock @fusion/engine wholesale, so skill-aware planning lanes need a shaped session-skill helper result instead of the fallback vi.fn() returning undefined.
*/
buildSessionSkillContextSync: vi.fn(() => ({
skillSelectionContext: undefined,
resolvedSkillNames: [],
skillSource: "none" as const,
})),
// Returns an iterable tool list; dashboard code spreads its result
// (`...createWorkflowAuthoringTools(...)`), so it must not be undefined.
createWorkflowAuthoringTools: vi.fn(() => []),
/*
FNXC:DashboardRouteTests 2026-06-18-09:07:
Planning and chat route files can share worker-level @fusion/engine mocks during broad dashboard API quality runs.
Keep chat task document tools iterable by default so rescuing chat-routes from quarantine does not poison planning route imports with a fallback vi.fn() result.
*/
createChatTaskDocumentTools: vi.fn(() => []),
createChatArtifactTools: vi.fn(() => []),
...overrides,
});
}
export function resetDashboardServerMockState(): void {
for (const fn of fallbackFns.values()) fn.mockReset();
}