Unify live-agent capacity accounting across engine and dashboard. - Derive Running and Waiting from workflow traits and durable agent liveness. - Apply unified limits to planner, executor, and merge admission while updating dashboard indicators. - Remove duplicate concurrency controls and document the unified operator model. Files changed: .changeset/fn-8453-unified-concurrency.md | 7 + docs/agent-tool-surface-full-loop.md | 4 +- docs/architecture.md | 2 +- docs/dashboard-guide.md | 4 +- docs/settings-reference.md | 4 +- .../skill/fusion/references/fusion-capabilities.md | 4 +- .../core/src/__tests__/live-agent-count.test.ts | 91 ++++---- packages/core/src/index.gate.ts | 6 + packages/core/src/index.ts | 6 + packages/core/src/live-agent-count.ts | 107 ++++++--- packages/dashboard/app/App.tsx | 28 ++- packages/dashboard/app/api/board-workflows.ts | 2 + packages/dashboard/app/components/Column.tsx | 6 +- .../dashboard/app/components/EngineControlMenu.tsx | 26 --- .../dashboard/app/components/ExecutorStatusBar.tsx | 38 ++- .../dashboard/app/components/SettingsModal.tsx | 1 - .../app/components/__tests__/Column.test.tsx | 6 +- .../__tests__/EngineControlMenu.test.tsx | 10 +- .../__tests__/ExecutorStatusBar.test.tsx | 32 ++- .../command-center/CommandCenterControls.tsx | 26 --- .../settings/sections/SchedulingSection.search.ts | 9 - .../settings/sections/SchedulingSection.tsx | 13 -- .../app/hooks/__tests__/useExecutorStats.test.ts | 12 +- packages/dashboard/app/hooks/useExecutorStats.ts | 50 ++-- .../src/__tests__/project-store-resolver.test.ts | 11 +- packages/dashboard/src/project-store-resolver.ts | 14 +- .../register-config-mcp-pi-settings-routes.ts | 3 +- packages/engine/src/__tests__/concurrency.test.ts | 123 +++++++++- .../engine/src/__tests__/project-engine.test.ts | 34 +++ packages/engine/src/__tests__/triage.test.ts | 7 +- packages/engine/src/concurrency.ts | 207 ++++++++++++++++- packages/engine/src/project-engine.ts | 151 ++++++++++-- packages/engine/src/scheduler.ts | 82 ++++++- packages/engine/src/triage.ts | 254 +++++++++++++-------- .../lib/dashboard-browser-safe-core-modules.json | 5 + 35 files changed, 991 insertions(+), 394 deletions(-) Fusion-Task-Id: FN-8453 Fusion-Task-Lineage: 12cfa5df-675d-4fce-b17e-932376544239 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
108 lines
3.3 KiB
TypeScript
108 lines
3.3 KiB
TypeScript
/**
|
|
* FNXC:CodeOrganization 2026-07-16-20:00:
|
|
* Board workflow client types/API peeled from legacy.ts.
|
|
*/
|
|
import type {
|
|
Task,
|
|
WorkflowFieldDefinition,
|
|
WorkflowFieldType,
|
|
WorkflowFieldOption,
|
|
WorkflowFieldRender,
|
|
WorkflowSettingDefinition,
|
|
WorkflowSettingType,
|
|
WorkflowSettingOption,
|
|
WorkflowSettingRender,
|
|
WorkflowSettingRejection,
|
|
} from "@fusion/core";
|
|
import { api } from "./client.js";
|
|
import type { FetchOptions } from "./client.js";
|
|
import { withProjectId } from "./health.js";
|
|
import { dedupe } from "./dedupe.js";
|
|
|
|
// Workflow field/setting declaration types re-exported from @fusion/core so
|
|
// WorkflowSettingsPanel can import them from `../api` (KTD-13/14, U6/KTD-1).
|
|
export type {
|
|
WorkflowFieldDefinition,
|
|
WorkflowFieldType,
|
|
WorkflowFieldOption,
|
|
WorkflowFieldRender,
|
|
WorkflowSettingDefinition,
|
|
WorkflowSettingType,
|
|
WorkflowSettingOption,
|
|
WorkflowSettingRender,
|
|
WorkflowSettingRejection,
|
|
};
|
|
|
|
/** Resolved trait flags for a board column (subset the client cares about). */
|
|
export interface BoardWorkflowColumnFlags {
|
|
countsTowardWip?: boolean;
|
|
complete?: boolean;
|
|
archived?: boolean;
|
|
hiddenFromBoard?: boolean;
|
|
hold?: boolean;
|
|
intake?: boolean;
|
|
mergeBlocker?: boolean;
|
|
/** Merge/review lane membership used by the shared live-agent predicate. */
|
|
mergeOrchestration?: boolean;
|
|
humanReview?: boolean;
|
|
[key: string]: boolean | undefined;
|
|
}
|
|
|
|
export interface BoardWorkflowColumn {
|
|
id: string;
|
|
name: string;
|
|
flags: BoardWorkflowColumnFlags;
|
|
}
|
|
|
|
export interface BoardWorkflowDefinition {
|
|
id: string;
|
|
name: string;
|
|
/** Optional compact custom workflow icon; built-ins render the Fusion mark by id. */
|
|
icon?: string;
|
|
columns: BoardWorkflowColumn[];
|
|
/** Custom field definitions declared by this workflow (U13/KTD-14). Absent on
|
|
* workflows with no fields, or from older servers. */
|
|
fields?: WorkflowFieldDefinition[];
|
|
}
|
|
|
|
export interface BoardWorkflowsPayload {
|
|
flagEnabled: boolean;
|
|
defaultWorkflowId: string;
|
|
workflows: BoardWorkflowDefinition[];
|
|
taskWorkflowIds: Record<string, string>;
|
|
}
|
|
|
|
/** A typed custom-field rejection surfaced by the PATCH endpoint (KTD-13). */
|
|
export interface CustomFieldRejection {
|
|
code: "no-fields-defined" | "unknown-field" | "type-mismatch" | "enum-violation";
|
|
fieldId: string;
|
|
detail: string;
|
|
}
|
|
|
|
/**
|
|
* Patch a task's custom field values (U13/KTD-14). The server validates the
|
|
* patch against the task's workflow field schema and returns the updated task;
|
|
* a validation failure surfaces as a 400 carrying `{ fieldId, code, detail }`.
|
|
* A `null` value for a field deletes it.
|
|
*/
|
|
export function updateTaskCustomFields(
|
|
id: string,
|
|
customFields: Record<string, unknown>,
|
|
projectId?: string,
|
|
): Promise<Task> {
|
|
return api<Task>(withProjectId(`/tasks/${id}/custom-fields`, projectId), {
|
|
method: "PATCH",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ customFields }),
|
|
});
|
|
}
|
|
|
|
/** Fetch the multi-lane board metadata (U9). When the flag is OFF the server
|
|
* returns `{ flagEnabled: false }` and the board renders its legacy form. */
|
|
export function fetchBoardWorkflows(projectId?: string, options?: FetchOptions): Promise<BoardWorkflowsPayload> {
|
|
const path = withProjectId("/tasks/board-workflows", projectId);
|
|
return dedupe(path, () => api<BoardWorkflowsPayload>(path), options);
|
|
}
|
|
|
|
|