fix(dashboard): expose column roles to browser bundle (#3151)
## Summary - export the browser-safe `@fusion/core/column-roles` subpath - keep Vite/Vitest aliases ahead of broad `@fusion/core` aliases - restore production dashboard builds after task undo classification adopted shared column-role helpers ## Test plan - `node scripts/check-no-node-only-core-imports-in-dashboard.mjs` - `FUSION_DASHBOARD_DEEP=1 pnpm --filter @fusion/dashboard exec vitest run app/utils/__tests__/taskRevert.test.ts --pool=threads --maxWorkers=1` - `pnpm --filter @fusion/core typecheck` - `pnpm --filter @fusion/dashboard typecheck` - `CI=true pnpm check:changesets` - `pnpm build` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed dashboard build compatibility for browser-based environments. * Improved reliability when importing column role functionality across supported application components. * **Refactor** * Made column role utilities available through a dedicated browser-safe entry point. * **Chores** * Updated development and test configurations to consistently resolve the new entry point. * Documented the browser-safe module classification and recorded the release patch. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
7
.changeset/dashboard-column-role-browser-export.md
Normal file
7
.changeset/dashboard-column-role-browser-export.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
summary: Fix the dashboard build after task undo classification began using shared column-role helpers.
|
||||
category: fix
|
||||
dev: Export the browser-safe column-roles core leaf and mirror its alias across Vite and Vitest consumers so broad core aliases cannot swallow the subpath.
|
||||
@@ -29,6 +29,11 @@
|
||||
"source": "./src/task-delete-attribution.ts",
|
||||
"import": "./dist/task-delete-attribution.js"
|
||||
},
|
||||
"./column-roles": {
|
||||
"types": "./src/column-roles.ts",
|
||||
"source": "./src/column-roles.ts",
|
||||
"import": "./dist/column-roles.js"
|
||||
},
|
||||
"./detect-content-language": {
|
||||
"types": "./src/detect-content-language.ts",
|
||||
"source": "./src/detect-content-language.ts",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Task } from "@fusion/core";
|
||||
import { isTerminalColumnRole, type ColumnRoleTraitFlags } from "@fusion/core";
|
||||
import { isTerminalColumnRole, type ColumnRoleTraitFlags } from "@fusion/core/column-roles";
|
||||
|
||||
/**
|
||||
* FNXC:TaskRevert 2026-07-04-00:00:
|
||||
|
||||
@@ -141,6 +141,7 @@ export default defineConfig({
|
||||
Ordered before the `@fusion/core` entry because Vite matches aliases in order and the broader key would otherwise swallow this subpath — the exact failure this line was added to fix (`"FUSION_CLIENT_HEADER" is not exported by ../core/src/types.ts`).
|
||||
*/
|
||||
"@fusion/core/task-delete-attribution": resolve(__dirname, "../core/src/task-delete-attribution.ts"),
|
||||
"@fusion/core/column-roles": resolve(__dirname, "../core/src/column-roles.ts"),
|
||||
"@fusion/core/detect-content-language": resolve(__dirname, "../core/src/detect-content-language.ts"),
|
||||
"@fusion/core": resolve(__dirname, "../core/src/types.ts"),
|
||||
"@fusion/dashboard/app/components/TaskCard": resolve(__dirname, "app/components/TaskCard.tsx"),
|
||||
|
||||
@@ -534,6 +534,7 @@ export default defineConfig({
|
||||
Keep this exact alias before the broader core alias so Vite does not rewrite the subpath.
|
||||
*/
|
||||
"@fusion/core/task-delete-attribution": resolve(__dirname, "../core/src/task-delete-attribution.ts"),
|
||||
"@fusion/core/column-roles": resolve(__dirname, "../core/src/column-roles.ts"),
|
||||
"@fusion/core": resolve(__dirname, "../core/src/index.ts"),
|
||||
"@fusion/engine": resolve(__dirname, "../engine/src/index.ts"),
|
||||
"@fusion/plugin-sdk": resolve(__dirname, "../plugin-sdk/src/index.ts"),
|
||||
|
||||
@@ -11,6 +11,7 @@ const fusionAliases = {
|
||||
transitively — this project aliases `@fusion/dashboard`, and `app/api/client.ts` imports the
|
||||
browser-safe delete-attribution leaf.
|
||||
*/
|
||||
"@fusion/core/column-roles": resolve(__dirname, "../core/src/column-roles.ts"),
|
||||
"@fusion/core/task-delete-attribution": resolve(__dirname, "../core/src/task-delete-attribution.ts"),
|
||||
"@fusion/core": resolve(__dirname, "../core/src/index.ts"),
|
||||
"@fusion/dashboard": resolve(__dirname, "../dashboard/src/index.ts"),
|
||||
|
||||
@@ -168,7 +168,7 @@ pgDescribe("scheduler parked-column resolution against a live store", () => {
|
||||
|
||||
it("REGRESSION — a dependent in a RENAMED hold column IS unblocked when its blocker is deleted", async () => {
|
||||
/*
|
||||
FNXC:WorkflowResolvedColumns 2026-08-01-02:20 (fleet — the flip this test was written to catch):
|
||||
FNXC:WorkflowResolvedColumns 2026-07-31-06:35 (fleet — the flip this test was written to catch):
|
||||
This was a CHARACTERIZATION of the inert sync read: `resolveTaskParkedColumnsSync` answered
|
||||
`{ hold: "todo" }` for a board whose hold column is `backlog`, so the reconciliation queried a
|
||||
column that does not exist, found no dependents, and left `blockedBy` pointing at a deleted task.
|
||||
|
||||
@@ -450,7 +450,7 @@ function mergeParkedColumns(
|
||||
}
|
||||
|
||||
/*
|
||||
FNXC:WorkflowResolvedColumns 2026-08-01-01:40 (fleet):
|
||||
FNXC:WorkflowResolvedColumns 2026-07-31-06:35 (fleet):
|
||||
The ASYNC twin. The sync one below cannot answer for a custom workflow in production, so any guard that
|
||||
can reach this one must.
|
||||
|
||||
@@ -477,7 +477,7 @@ async function resolveTaskParkedColumns(store: TaskStore, taskId: string): Promi
|
||||
archived,
|
||||
terminal: new Set([complete, archived]),
|
||||
/*
|
||||
FNXC:WorkflowResolvedColumns 2026-08-01-02:05 (fleet):
|
||||
FNXC:WorkflowResolvedColumns 2026-07-31-06:35 (fleet):
|
||||
The wake set UNIONS the legacy ids rather than replacing them, and that is load-bearing rather
|
||||
than defensive. Post-U11 the default lineage has no `triage` column, so a RESOLVED answer returns
|
||||
`intake: "todo"` where the old inert path fell back to `"triage"`. Converting without the union
|
||||
@@ -1268,7 +1268,7 @@ export class Scheduler {
|
||||
schedulerLog.warn(`Failed to reset dispatch oscillation state for ${task.id} on unpause: ${error instanceof Error ? error.message : String(error)}`);
|
||||
});
|
||||
}
|
||||
/* FNXC:WorkflowResolvedColumns 2026-08-01-01:40 (fleet): the answer only gates `schedule()`,
|
||||
/* FNXC:WorkflowResolvedColumns 2026-07-31-06:35 (fleet): the answer only gates `schedule()`,
|
||||
which is async and fire-and-forget, so resolving it properly costs nothing observable. */
|
||||
void (async () => {
|
||||
const unpausedParked = await resolveTaskParkedColumns(this.store, task.id);
|
||||
@@ -1299,7 +1299,7 @@ export class Scheduler {
|
||||
this.planningTaskIds.add(task.id);
|
||||
} else if (this.planningTaskIds.has(task.id)) {
|
||||
this.planningTaskIds.delete(task.id);
|
||||
/* FNXC:WorkflowResolvedColumns 2026-08-01-01:40 (fleet): as with the unpause wake above, the
|
||||
/* FNXC:WorkflowResolvedColumns 2026-07-31-06:35 (fleet): as with the unpause wake above, the
|
||||
answer only gates `schedule()`. The `planningTaskIds.delete` stays SYNCHRONOUS — it is the
|
||||
edge-trigger bookkeeping, and deferring it would let a second update re-enter this branch. */
|
||||
void (async () => {
|
||||
|
||||
@@ -14,6 +14,7 @@ export default defineConfig({
|
||||
transitively — this project aliases `@fusion/dashboard`, and `app/api/client.ts` imports the
|
||||
browser-safe delete-attribution leaf.
|
||||
*/
|
||||
"@fusion/core/column-roles": resolve(__dirname, "../core/src/column-roles.ts"),
|
||||
"@fusion/core/task-delete-attribution": resolve(__dirname, "../core/src/task-delete-attribution.ts"),
|
||||
"@fusion/core": resolve(__dirname, "../core/src/index.ts"),
|
||||
"@fusion/test-utils": resolve(__dirname, "../core/src/__test-utils__/workspace.ts"),
|
||||
|
||||
@@ -32,6 +32,7 @@ export default defineConfig({
|
||||
transitively — this project aliases `@fusion/dashboard`, and `app/api/client.ts` imports the
|
||||
browser-safe delete-attribution leaf.
|
||||
*/
|
||||
"@fusion/core/column-roles": fileURLToPath(new URL("../../packages/core/src/column-roles.ts", import.meta.url)),
|
||||
"@fusion/core/task-delete-attribution": fileURLToPath(new URL("../../packages/core/src/task-delete-attribution.ts", import.meta.url)),
|
||||
"@fusion/core": fileURLToPath(new URL("../../packages/core/src/index.ts", import.meta.url)),
|
||||
"@fusion/plugin-sdk": fileURLToPath(new URL("../../packages/plugin-sdk/src/index.ts", import.meta.url)),
|
||||
|
||||
@@ -52,6 +52,7 @@ export default defineConfig({
|
||||
transitively — this project aliases `@fusion/dashboard`, and `app/api/client.ts` imports the
|
||||
browser-safe delete-attribution leaf.
|
||||
*/
|
||||
{ find: "@fusion/core/column-roles", replacement: fileURLToPath(new URL("../../packages/core/src/column-roles.ts", import.meta.url)) },
|
||||
{ find: "@fusion/core/task-delete-attribution", replacement: fileURLToPath(new URL("../../packages/core/src/task-delete-attribution.ts", import.meta.url)) },
|
||||
{ find: "@fusion/core", replacement: fileURLToPath(new URL("../../packages/core/src/index.ts", import.meta.url)) },
|
||||
{
|
||||
|
||||
@@ -33,6 +33,7 @@ export default defineConfig({
|
||||
transitively — this project aliases `@fusion/dashboard`, and `app/api/client.ts` imports the
|
||||
browser-safe delete-attribution leaf.
|
||||
*/
|
||||
{ find: "@fusion/core/column-roles", replacement: fileURLToPath(new URL("../../packages/core/src/column-roles.ts", import.meta.url)) },
|
||||
{ find: "@fusion/core/task-delete-attribution", replacement: fileURLToPath(new URL("../../packages/core/src/task-delete-attribution.ts", import.meta.url)) },
|
||||
{ find: "@fusion/core", replacement: fileURLToPath(new URL("../../packages/core/src/index.ts", import.meta.url)) },
|
||||
{
|
||||
|
||||
@@ -32,6 +32,7 @@ export default defineConfig({
|
||||
transitively — this project aliases `@fusion/dashboard`, and `app/api/client.ts` imports the
|
||||
browser-safe delete-attribution leaf.
|
||||
*/
|
||||
"@fusion/core/column-roles": fileURLToPath(new URL("../../packages/core/src/column-roles.ts", import.meta.url)),
|
||||
"@fusion/core/task-delete-attribution": fileURLToPath(new URL("../../packages/core/src/task-delete-attribution.ts", import.meta.url)),
|
||||
"@fusion/core": fileURLToPath(new URL("../../packages/core/src/index.ts", import.meta.url)),
|
||||
// FNXC:Clipboard 2026-07-12-00:00: The reports plugin imports the dashboard clipboard helper through its package subpath export; keep this exact alias ahead of the package root alias so vitest does not collapse the subpath to src/index.ts.
|
||||
|
||||
@@ -60,6 +60,11 @@
|
||||
"reason": "2026-07-26: Delete caller-attribution constants and the pure header resolver are shared by the browser client that stamps `x-fusion-client` and the route that reads it; the module has no imports at all.",
|
||||
"verifiedAt": "2026-07-26"
|
||||
},
|
||||
{
|
||||
"module": "column-roles",
|
||||
"reason": "2026-07-31: Column role predicates depend only on erased trait types and provide browser-safe flags-first lifecycle classification.",
|
||||
"verifiedAt": "2026-07-31"
|
||||
},
|
||||
{
|
||||
"module": "live-agent-count",
|
||||
"reason": "2026-07-21: FN-8453 shares pure workflow-trait-based Running and Waiting predicates with dashboard capacity indicators; its dependency graph has no Node-only modules.",
|
||||
|
||||
Reference in New Issue
Block a user