- Add task `source` provenance field tracking how tasks enter the system (e.g. `"manual"`, `"heartbeat"`, `"executor"`, `"triage"`, `"cron"`, `"routine"`) - Wire `source` into shared create-task tools, executor agent, triage agent, cron runner, and routine runner - Add `source` to heartbeat task creation in `agent-heartbeat.ts` and mission execution loop in `mission-execution-loop.ts` - Wire `source` field into dashboard routes (`register-planning-subtask-routes.ts`, `register-task-workflow-routes.ts`) and GitHub integration (`register-git-github.ts`) - Add `source` to the API layer and task store handlers in the dashboard - Expose `source` in the `fn` CLI task command and `task-plan` extension tool - Add integration tests for provenance across engine (agent-tools, agent-heartbeat, cron-runner, triage, pr-comment-handler) and dashboard routes - Update existing tests to assert the correct source values - Bulk-revert stale changeset files that were superseded by the v0.9.1 release commit Commits merged: - test(FN-2923): complete Step 14 — align tests with task source provenance - test(FN-2923): complete Steps 12-13 — update and add provenance tests - feat(FN-2923): complete Step 10 — wire CLI task provenance - feat(FN-2923): complete Step 9 — wire dashboard UI and API source fields - feat(FN-2923): complete Step 8 — wire dashboard route provenance - feat(FN-2923): complete Step 7 — wire remaining engine provenance - feat(FN-2923): complete Step 6 — add routine create-task provenance - feat(FN-2923): complete Step 5 — add cron create-task provenance - feat(FN-2923): complete Step 4 — add triage subtask source - feat(FN-2923): complete Step 3 — add executor create-task source - feat(FN-2923): complete Step 2 — add heartbeat task provenance - feat(FN-2923): complete Step 1 — add provenance to shared create-task tools - feat(FN-2945): merge fusion/fn-2945 - chore(release): v0.9.1 Files changed: .changeset/active-agents-no-stuck-connecting.md | 13 --- .changeset/active-agents-panel-hoist-heartbeat.md | 13 --- .changeset/fix-agent-heartbeat-terminal-links.md | 5 -- .changeset/fix-experimental-defaults.md | 5 -- .changeset/improve-git-manager-diff-pane.md | 5 -- .changeset/insights-two-pane-layout.md | 5 -- .changeset/show-planning-tasks-immediately.md | 5 -- CHANGELOG.md | 92 ++++++++++++++++++++++ package.json | 2 +- packages/cli-alias/CHANGELOG.md | 15 ++++ packages/cli-alias/package.json | 2 +- packages/cli/CHANGELOG.md | 12 +++ packages/cli/package.json | 2 +- packages/cli/src/__tests__/task-plan.test.ts | 1 + packages/cli/src/commands/__tests__/task.test.ts | 15 +++- packages/cli/src/commands/task.ts | 15 +++- packages/cli/src/extension.ts | 9 +++ packages/core/CHANGELOG.md | 7 ++ packages/core/package.json | 2 +- packages/dashboard/CHANGELOG.md | 14 ++++ .../app/__tests__/agent-css-classes.test.ts | 3 +- packages/dashboard/app/__tests__/api.test.ts | 13 +++ packages/dashboard/app/api/legacy.ts | 2 + packages/dashboard/app/components/AgentsView.css | 22 +++--- .../app/components/ModelOnboardingModal.tsx | 5 +- packages/dashboard/app/components/TodoView.tsx | 2 + .../__tests__/ModelOnboardingModal.test.tsx | 4 +- .../app/components/__tests__/QuickChatFAB.test.tsx | 14 +--- .../app/components/__tests__/TodoView.test.tsx | 4 +- .../__tests__/agents-view-mobile.test.tsx | 5 +- .../components/__tests__/onboarding-flow.test.tsx | 2 +- .../app/hooks/__tests__/useTaskHandlers.test.ts | 4 +- packages/dashboard/app/hooks/useTaskHandlers.ts | 4 +- packages/dashboard/package.json | 2 +- packages/dashboard/src/__tests__/routes.test.ts | 14 ++++ packages/dashboard/src/routes.ts | 4 + .../dashboard/src/routes/register-git-github.ts | 12 +++ .../src/routes/register-planning-subtask-routes.ts | 3 + .../src/routes/register-task-workflow-routes.ts | 7 ++ packages/desktop/CHANGELOG.md | 7 ++ packages/desktop/package.json | 2 +- packages/engine/CHANGELOG.md | 11 +++ packages/engine/package.json | 2 +- .../engine/src/__tests__/agent-heartbeat.test.ts | 10 +++ .../src/__tests__/agent-tools-delegation.test.ts | 2 + packages/engine/src/__tests__/agent-tools.test.ts | 37 +++++++++ packages/engine/src/__tests__/cron-runner.test.ts | 4 + .../src/__tests__/pr-comment-handler.test.ts | 8 ++ packages/engine/src/__tests__/triage.test.ts | 2 + packages/engine/src/agent-heartbeat.ts | 13 ++- packages/engine/src/agent-tools.ts | 13 ++- packages/engine/src/cron-runner.ts | 7 +- packages/engine/src/executor.ts | 2 +- packages/engine/src/mission-execution-loop.ts | 8 ++ packages/engine/src/pr-comment-handler.ts | 5 ++ packages/engine/src/project-engine.ts | 8 ++ packages/engine/src/routine-runner.ts | 4 + packages/engine/src/triage.ts | 4 + packages/mobile/CHANGELOG.md | 7 ++ packages/mobile/package.json | 2 +- packages/pi-claude-cli/CHANGELOG.md | 7 ++ packages/pi-claude-cli/package.json | 2 +- packages/plugin-sdk/CHANGELOG.md | 10 +++ packages/plugin-sdk/package.json | 2 +- .../examples/fusion-plugin-auto-label/CHANGELOG.md | 8 ++ .../examples/fusion-plugin-auto-label/package.json | 2 +- .../examples/fusion-plugin-ci-status/CHANGELOG.md | 8 ++ .../examples/fusion-plugin-ci-status/package.json | 2 +- .../fusion-plugin-notification/CHANGELOG.md | 8 ++ .../fusion-plugin-notification/package.json | 2 +- .../fusion-plugin-settings-demo/CHANGELOG.md | 8 ++ .../fusion-plugin-settings-demo/package.json | 2 +- plugins/fusion-plugin-hermes-runtime/CHANGELOG.md | 8 ++ plugins/fusion-plugin-hermes-runtime/package.json | 2 +- .../fusion-plugin-openclaw-runtime/CHANGELOG.md | 8 ++ .../fusion-plugin-openclaw-runtime/package.json | 2 +- .../fusion-plugin-paperclip-runtime/CHANGELOG.md | 8 ++ .../fusion-plugin-paperclip-runtime/package.json | 2 +- 78 files changed, 499 insertions(+), 115 deletions(-) Fusion-Task-Id: FN-2923
114 lines
3.7 KiB
TypeScript
114 lines
3.7 KiB
TypeScript
import { act, renderHook } from "@testing-library/react";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { useTaskHandlers } from "../useTaskHandlers";
|
|
import type { Task, TaskCreateInput } from "@fusion/core";
|
|
|
|
const CREATED_TASK: Task = {
|
|
id: "FN-123",
|
|
title: "Test",
|
|
description: "Created task",
|
|
status: "pending",
|
|
column: "triage",
|
|
steps: [],
|
|
currentStep: 0,
|
|
dependencies: [],
|
|
log: [],
|
|
attachments: [],
|
|
createdAt: "",
|
|
updatedAt: "",
|
|
size: "M",
|
|
reviewLevel: 0,
|
|
};
|
|
|
|
function createOptions(overrides: Partial<Parameters<typeof useTaskHandlers>[0]> = {}): Parameters<typeof useTaskHandlers>[0] {
|
|
return {
|
|
createTask: vi.fn().mockResolvedValue(CREATED_TASK),
|
|
ingestCreatedTasks: vi.fn(),
|
|
onPlanningTaskCreated: vi.fn(),
|
|
onPlanningTasksCreated: vi.fn(),
|
|
onSubtaskTasksCreated: vi.fn(),
|
|
addToast: vi.fn(),
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("useTaskHandlers", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it("handleBoardQuickCreate calls createTask with triage column and returns task", async () => {
|
|
const options = createOptions();
|
|
const { result } = renderHook(() => useTaskHandlers(options));
|
|
const input: TaskCreateInput = { description: "Do work" };
|
|
|
|
let created: Task | null = null;
|
|
await act(async () => {
|
|
created = await result.current.handleBoardQuickCreate(input);
|
|
});
|
|
|
|
expect(options.createTask).toHaveBeenCalledWith({ description: "Do work", column: "triage", source: { sourceType: "dashboard_ui" } });
|
|
expect(created).toEqual(CREATED_TASK);
|
|
});
|
|
|
|
it("handleModalCreate calls createTask with triage column and returns task", async () => {
|
|
const options = createOptions();
|
|
const { result } = renderHook(() => useTaskHandlers(options));
|
|
|
|
let created: Task | null = null;
|
|
await act(async () => {
|
|
created = await result.current.handleModalCreate({ description: "From modal" });
|
|
});
|
|
|
|
expect(options.createTask).toHaveBeenCalledWith({ description: "From modal", column: "triage", source: { sourceType: "dashboard_ui" } });
|
|
expect(created).toEqual(CREATED_TASK);
|
|
});
|
|
|
|
it("handlePlanningTaskCreated delegates with addToast", () => {
|
|
const options = createOptions();
|
|
const { result } = renderHook(() => useTaskHandlers(options));
|
|
|
|
act(() => {
|
|
result.current.handlePlanningTaskCreated(CREATED_TASK);
|
|
});
|
|
|
|
expect(options.ingestCreatedTasks).toHaveBeenCalledWith([CREATED_TASK]);
|
|
expect(options.onPlanningTaskCreated).toHaveBeenCalledWith(CREATED_TASK, options.addToast);
|
|
});
|
|
|
|
it("handlePlanningTasksCreated delegates with addToast", () => {
|
|
const options = createOptions();
|
|
const { result } = renderHook(() => useTaskHandlers(options));
|
|
|
|
act(() => {
|
|
result.current.handlePlanningTasksCreated([CREATED_TASK]);
|
|
});
|
|
|
|
expect(options.ingestCreatedTasks).toHaveBeenCalledWith([CREATED_TASK]);
|
|
expect(options.onPlanningTasksCreated).toHaveBeenCalledWith([CREATED_TASK], options.addToast);
|
|
});
|
|
|
|
it("handleSubtaskTasksCreated delegates with addToast", () => {
|
|
const options = createOptions();
|
|
const { result } = renderHook(() => useTaskHandlers(options));
|
|
|
|
act(() => {
|
|
result.current.handleSubtaskTasksCreated([CREATED_TASK]);
|
|
});
|
|
|
|
expect(options.ingestCreatedTasks).toHaveBeenCalledWith([CREATED_TASK]);
|
|
expect(options.onSubtaskTasksCreated).toHaveBeenCalledWith([CREATED_TASK], options.addToast);
|
|
});
|
|
|
|
it("handleGitHubImport shows success toast with task ID", () => {
|
|
const options = createOptions();
|
|
const { result } = renderHook(() => useTaskHandlers(options));
|
|
|
|
act(() => {
|
|
result.current.handleGitHubImport(CREATED_TASK);
|
|
});
|
|
|
|
expect(options.addToast).toHaveBeenCalledWith("Imported FN-123 from GitHub", "success");
|
|
});
|
|
});
|