Commit Graph

11 Commits

Author SHA1 Message Date
gsxdsm
dc50425e98 docs: correct 104 future-dated FNXC timestamps across 61 files (#2680)
## What

The FNXC convention exists so a reader can place a note against the
change that motivated it. A stamp dated *after* the edit landed defeats
exactly that.

This is program-wide drift, not one author's slip — I contributed to it
in my own commits this week, which is how I noticed it.

## Measured, on this tree

**104 stamps across 61 files** dated later than the day they were
written, from one day ahead to **2026-10-19 (81 days)**:

| count | date | count | date | count | date |
|---|---|---|---|---|---|
| 50 | 2026-07-31 | 6 | 2026-08-05 | 3 | 2026-08-13 |
| 17 | 2026-08-01 | 1 | 2026-08-07 | 1 | 2026-08-19 |
| 7 | 2026-08-02 | 1 | 2026-08-12 | 2 | 2026-08-26 |
| 11 | 2026-08-03 | | | 3 | 2026-10-19 |

An earlier number I circulated was ~70. That came from a narrower
pathspec and was wrong; **104** is the measurement.

## How

Each stamp is rewritten to the date of the commit that introduced **that
line**, via per-line `git blame` — deliberately *not* stamped uniformly
with today's date. A uniform stamp swaps a wrong date for a different
wrong date and flattens the ordering that makes these comments
navigable; blame preserves it. Times of day are untouched, and a blame
date in the future is clamped rather than trusted.

## Why the verification is listed

A docs sweep across 61 files is precisely where a stray edit hides, so
the safety claims are mechanical rather than asserted:

- every changed line begins with a comment marker — **no code touched**;
- **no test asserts an FNXC date later than today**, so no `toContain`
assertion on embedded source text can be silently invalidated (several
such assertions do exist);
- CSS files, which carry several of those assertions, are outside the
pathspec.

## Verified

lint clean · merge gate green (487 + 158 + 10 + 71) · `census --strict`
exit 0 · tsc clean for core, engine, and dashboard
(`tsconfig.app.json`).

**No behavior change.** Comment text only.

## Not done here

A guard preventing recurrence. A check that rejects an FNXC stamp dated
after the commit would stop this returning, but it needs a decision
about where it runs (lint rule vs. gate) and it is a behavior change to
CI — it does not belong riding inside the sweep it would police.
2026-07-30 02:38:58 -07:00
gsxdsm
efbbc45eb0 U12: the LAST triage guard — Plan was offered on executing cards named triage (#2664)
The final `column === "triage"` in production source, and it was a live
defect rather than dead vocabulary.

## The defect

`isPreExecutionHoldColumn` ORed the legacy id with the traits
**unconditionally**:

```ts
return column === "triage" || flags?.intake === true || flags?.hold === true;
```

That is not a fallback. A resolved column merely *named* `triage`
answered true even when its own traits said work was underway — so the
context menu offered **Plan**, which re-plans, on a card that is already
executing.

Now flags-first, with the id as the documented no-metadata answer.

## Why the file's earlier conversion missed it

Every existing case in `TaskContextMenu.test.tsx` passes a column with
**no flags**, or with `hold`/`intake` set. All of them agree under both
forms, so the suite could not distinguish them. Nothing exercised a
column whose **name and traits disagree**, which is the only shape that
separates an OR from a fallback.

Three new cases cover it. Revert check: restoring the OR form fails the
first one — Plan reappears on a mid-flight card.

## The asymmetry is preserved, and now tested

The degraded set stays `{triage}` **alone**, deliberately not the
`{todo, triage}` used by `isPreImplementationColumnRole`. That helper
drives the preserve-progress prompt, where a flagless `todo` *should*
prompt because losing steps is unrecoverable. This drives Plan, where a
flagless `todo` must **not** offer to re-plan a card that may already be
planned. The file documented that difference; nothing asserted it. Now a
test does.

## On reaching zero honestly

The surviving literal is marked `DELIBERATE-LITERAL`. It is the degraded
answer, not an unconverted guard — there is no trait to read when
`flags` is `undefined`, which happens during first paint and for a card
in a column its workflow no longer declares. Deleting it would silently
withdraw Plan from exactly the stranded cards that most need
re-planning.

So **`triage → 0` means "no unconverted guards remain", not "the string
is gone"**, and I would rather say that than move a number by deleting a
fallback.

| branch | triage |
|---|---:|
| `origin/main` | 5 |
| this PR | **4** |
| #2655 (flag resolution, removes 4 in `moves.ts`) | 1 → **0** combined
|

I found it with the census's own AST classifier rather than grep — my
grep of the same tree returned only comment prose and would have had me
report the bar as met while a real defect sat in
`TaskContextMenu.tsx:179`.

## Verification

`pnpm lint` clean. `pnpm test:gate` green (10 / 158 / 487 / 71). `pnpm
check:lifecycle-columns` exits 0 with the baseline re-recorded in this
PR (column 769 → 768, deliberate 12 → 13). `tsc -p tsconfig.app.json`
clean. `TaskContextMenu.test.tsx` 18/18.

Depends on nothing; stacks cleanly with #2655 and #2661.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 00:37:08 -07:00
gsxdsm
347107d8e4 Phase B — TaskContextMenu.tsx: intake by ROLE (2 → 1), and two conversions I dropped rather than force (#2626)
**Claimed:** `packages/dashboard/app/components/TaskContextMenu.tsx`

| file | before | after |
|---|---:|---:|
| `TaskContextMenu.tsx` | **2** | **1** |

## The real bug

`shouldShowActionsMenu: task.column !== "triage"` meant *"a bare card in
a pure intake lane has no actions worth showing yet."*

Post-U11 the literal does not go dead — it **inverts**. A default
Planning card is `todo`, so the condition is true and the menu shows
unconditionally. That is right for the hold half (cards waiting for
capacity do have actions), but the guard has stopped distinguishing
anything — and it would show a full action menu on a bare Coding (Ideas)
capture, which is the case it existed to suppress.

Resolved to `intake AND NOT hold` — a *pure* intake lane — which
reproduces all four shapes rather than picking a winner:

| workflow | column traits | menu |
|---|---|---|
| legacy `triage` | intake only | suppressed *(as before)* |
| legacy `todo` | hold only | shown *(as before)* |
| merged Planning | intake + hold | shown *(matches the Todo half, where
cards wait)* |
| Ideas `ideas` | intake only | suppressed *(a bare captured idea)* |

Its degraded arm now defers to `isIntakeColumnRole`, so the legacy
intake id lives in `utils/columnRoles.ts` only.

## The remaining site is audited, not overlooked

I routed `isPreExecutionHoldColumn` through
`isPreImplementationColumnRole` — same question, one definition — **and
then reverted it.** Its degraded-mode answer is wider: its legacy set is
`{todo, triage}`, this predicate's was `{triage}` alone.

They differ **for a reason.** That helper drives the preserve-progress
prompt, where a flagless `todo` *should* prompt because losing steps is
unrecoverable. This one drives the Plan affordance, where a flagless
`todo` must **not** offer to re-plan a card that may already be planned.

Consolidating added `plan` to flagless `todo` cards — caught by
*"exposes Plan only for pre-execution hold columns"*. Identical trait
path, non-interchangeable fallbacks. Kept separate with the difference
recorded rather than made to look shared.

## Two conversions I dropped rather than force

**1. A `ListView.tsx` 5 → 0 conversion.** Main changed underneath it:
the U12 worker centralized the same fallbacks into
`utils/columnRoles.ts`. Their approach is on main and other files
already call it, so I took theirs and dropped mine rather than fight for
my version through a rebase conflict.

**2. A `strandedColumnFlags.ts` seam** that resolved an undeclared
column's role from the workflow's **rebound target**, so the degraded
arms could be *deleted* rather than documented.

I built it, tested it, wired it into ListView — and then their
`columnRoles.ts` identified a state my seam cannot serve: the **pre-load
window**, where the board renders before the workflows fetch resolves
and there are no columns at all, hence no rebound target to borrow from.
Their analysis is more complete than mine, the fallback is genuinely
undeletable, and shipping an unused module is worse than shipping
nothing.

Worth recording because I twice reported these arms as permanently
unconvertible, then thought I had a way to convert them, and was wrong
for a reason worth knowing: **there are two degraded states, not one.**
The stranded-card half is resolvable; the pre-load half is not.

## Verification

10 of 11 green in this suite. The one failure — `"Back to in-progress"`
vs `"Back to In Progress"` — is **pre-existing**, verified by stashing
this change and re-running against clean `main`.

Dashboard app typecheck and lint clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 23:03:26 -07:00
gsxdsm
50ebf3c543 TAKING cli/project.ts (fn project reported 0 running agents) + two test fixes — dashboard conversions WITHDRAWN in favour of #2626 and #2636 (#2631)
Three app-cluster conversions plus the evidence that they behave on a
renamed AND a merged board.

## Per-file guard counts

| file | before | after | note |
|---|---|---|---|
| `packages/cli/src/commands/project.ts` | 0 | 0 | not a comparison site
— see below |
| `packages/dashboard/app/components/TaskContextMenu.tsx` | 2 | 2 |
**count does not move — deliberate, see below** |
| `packages/dashboard/app/components/Column.tsx` | 2 | 2 | **count does
not move — deliberate, see below** |

**Read this before scoring the PR against the bar.** You said a claim
that does not move your number is not done, so I am telling you up front
that *this PR does not move it*, and why.

Both dashboard conversions are **fallback-preserving**:

```ts
const isIntakeColumn = columnFlags ? columnFlags.intake === true : column === "triage";
```

The literal survives as the no-flags branch, so the grep still counts
it. That is the shape the sibling code already uses
(`isPreExecutionHoldColumn`, same file, converted earlier in the
program), and dropping the fallback would make an unresolved-column
render *lose* the affordance a second way. What changes is the
**behaviour when flags exist** — which is what the mutation results
below measure.

If you want these to zero out the count, the fallback has to go, and
that is a separate decision about whether an unresolved column should
fail open or closed. Say the word and I will do it as a follow-up; I did
not make that call unilaterally because it is not reversible from a
rendering standpoint.

`cli/project.ts` was never a comparison site at all — it fed **raw
rows** to `isRunningAgentTaskShape`, so the helper's own internal legacy
fallback kicked in and `fn project` reported **0 running agents** on any
renamed board. Fixed by resolving the IR per task before counting.
Nothing to subtract.

## Two of the three had a test that looked like coverage and was not

- **`Column.tsx`** — the quick-create gate is `workflowMode ||
isIntakeColumn`. Every pre-existing intake case in `Column.test.tsx`
*also* passes `workflowMode`, so the `||` short-circuited and **none of
them ever reached the trait lookup**. Added cases that omit
`workflowMode`, the only path where the conversion changes the answer.
- **`TaskContextMenu.tsx`** — the intake suppression was asserted only
for the legacy `triage` id, the one board shape where a broken
conversion still returns the right answer.

Mutation-verified rather than asserted:

| mutation | result |
|---|---|
| `isIntakeColumn` → `column === "triage"` | **2 of 88 fail** (exactly
the renamed and merged cases) |
| menu suppression → `task.column !== "triage"` | **1 of 12 fail** |

## A pre-existing red I fixed on the way past

`uses VALID_TRANSITIONS and in-review back-to-progress labels` was
**already failing on origin/main**. #2521 correctly moved the "Back to
X" label onto the host's `columnLabel` function; this file's stub is
`(column) => column`, so the hardcoded `"Back to In Progress"`
expectation was left over from the pre-#2521 hardcode and nothing had
updated it.

Matching the raw id would have made it pass while proving nothing, so
instead that one case gets a display-like label function — the assertion
now fails both if the "Back to" prefix regresses **and** if the label
stops routing through `columnLabel`. Strengthened, not relaxed. Counts
against completion criterion #2.

## Verification

- `Column.test.tsx` + `TaskContextMenu.test.tsx`: **100 passed**
- `tsc -p tsconfig.app.json` (the root config does not cover `app/`) and
the CLI typecheck: clean
- `pnpm test:gate`: green

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 22:52:30 -07:00
gsxdsm
aaa95305cb FN-8148: fix Respecify workflow replanning
Make Respecify reliably return tasks to their workflow's planning lane.

- Resolve task-specific planner lanes with recovery rehoming for custom workflows
- Return the persisted needs-replan task for in-place replans and cover legacy triage
- Hide unsupported Respecify actions for archived tasks

Files changed:
 .changeset/fn-8148-respecify-fix.md                |   7 ++
 .../dashboard/app/components/TaskContextMenu.tsx   |  10 +-
 .../components/__tests__/TaskContextMenu.test.tsx  |   6 +-
 .../dashboard/src/__tests__/routes-github.test.ts  | 103 ++++++++++++++++++++-
 .../src/routes/register-task-workflow-routes.ts    |  66 ++++++-------
 5 files changed, 152 insertions(+), 40 deletions(-)

Fusion-Task-Id: FN-8148

Fusion-Task-Lineage: 7184bd58-e841-4bb1-a7fa-c1c336d6270a

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-16 19:57:17 -07:00
gsxdsm
4e7e013d6f FN-7947: add Plan action to context menu for pre-execution task cards
Adds a Plan action to Board/List task context menus so triage/hold/intake cards can jump straight into Planning Mode without duplicating a task.

- Add `onPlan` handler and `isPreExecutionHoldColumn` gate to `TaskContextMenu` so Plan only appears for pre-execution (triage/intake/hold) columns, and only when a host wires the handler
- Wire the Plan action through `Board.tsx`, `Column.tsx`, `ListView.tsx`, and `WorktreeGroup.tsx` so both board and list views expose the new menu item
- Surface the Plan entry point on `TaskCard.tsx`
- Add test coverage in `TaskContextMenu.test.tsx`, `TaskCard.test.tsx`, and `ListView.test.tsx` for the new gating/wiring behavior
- Document the new action in `docs/dashboard-guide.md`
- Add a minor changeset for `@runfusion/fusion`

Files changed:
 .changeset/fn-7947-plan-context-menu-action.md     |  7 ++
 docs/dashboard-guide.md                            | 10 ++-
 packages/dashboard/app/components/Board.tsx        | 10 ++-
 packages/dashboard/app/components/Column.tsx       |  4 +
 packages/dashboard/app/components/ListView.tsx     | 15 +++-
 packages/dashboard/app/components/TaskCard.tsx     | 24 +++++-
 packages/dashboard/app/components/TaskContextMenu.tsx   | 18 ++++
 packages/dashboard/app/components/WorktreeGroup.tsx     |  9 ++
 packages/dashboard/app/components/__tests__/ListView.test.tsx     | 21 +++++
 packages/dashboard/app/components/__tests__/TaskCard.test.tsx     | 96 ++++++++++++++++++++++
 packages/dashboard/app/components/__tests__/TaskContextMenu.test.tsx  | 32 ++++++++
 11 files changed, 236 insertions(+), 10 deletions(-)

Fusion-Task-Id: FN-7947

Fusion-Task-Lineage: 41c759a2-e76b-4771-9421-c9805c4596e5

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-13 10:14:22 -07:00
gsxdsm
377eee64af FN-7410: allow archived task deletion
Allow archived task snapshots to be deleted while preserving soft-delete tombstones.

- Restore cold archived snapshots into the tasks table before applying delete tombstones.
- Remove archive snapshots after deletion and preserve allowResurrection semantics.
- Cover archived deletion through store, API, UI menu, docs, and changeset updates.

Files changed:
 .changeset/fn-7410-delete-archived-tasks.md        |   7 ++
 docs/task-management.md                            |   3 +-
 .../core/src/__tests__/soft-delete-tasks.test.ts   | 129 +++++++++++++++++++++
 packages/core/src/store.ts                         |  25 +++-
 .../components/__tests__/TaskContextMenu.test.tsx  |  19 +++
 .../src/__tests__/routes-tasks-ops.test.ts         |  24 ++++
 6 files changed, 204 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-7410
Fusion-Task-Lineage: fa7d9983-e62c-4849-89d8-1ae5f6134815
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-02 11:38:30 -07:00
gsxdsm
4694b4a8c9 FN-7387: move destructive task actions to menu bottom
Task context menus now place destructive actions after safer task operations.

- Reorder shared task action descriptors so Reset and Delete render at the bottom, with Delete last.
- Update context-menu model coverage for lifecycle, GitHub tracking, pause, and workflow column states.
- Add a patch changeset for the published Fusion CLI package.

Files changed:
 .changeset/fn-7387-context-menu-action-order.md    |  7 ++++++
 .../dashboard/app/components/TaskContextMenu.tsx   | 24 +++++++++++--------
 .../components/__tests__/TaskContextMenu.test.tsx  | 27 +++++++++++++---------
 3 files changed, 38 insertions(+), 20 deletions(-)

Fusion-Task-Id: FN-7387

Fusion-Task-Lineage: f320ed96-d5e7-48f4-9151-59357ae12de7

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-01 11:18:57 -07:00
gsxdsm
17505231d6 FN-7372: add GitHub tracking context menu action
Expose GitHub tracking enablement from task context menus while reusing existing task update paths.

- Add an Enable GitHub tracking action to the shared task context menu model for untracked tasks with update-capable hosts.
- Wire board cards and list rows to PATCH githubTracking, refresh local snapshots, close stale menus, and show task-detail toasts.
- Extend context-menu/card/list tests and add a changeset for the published CLI package.

Files changed:
 .../fn-7372-enable-github-tracking-context-menu.md |  7 +++
 packages/dashboard/app/components/Column.tsx       |  2 +-
 packages/dashboard/app/components/ListView.tsx     | 20 ++++++++-
 packages/dashboard/app/components/TaskCard.tsx     | 27 +++++++++---
 .../dashboard/app/components/TaskContextMenu.tsx   | 16 ++++++-
 .../app/components/__tests__/ListView.test.tsx     | 51 +++++++++++++++++++++-
 .../app/components/__tests__/TaskCard.test.tsx     | 41 +++++++++++++++++
 .../components/__tests__/TaskContextMenu.test.tsx  | 38 ++++++++++++++++
 packages/dashboard/app/hooks/useTasks.ts           |  2 +-
 9 files changed, 193 insertions(+), 11 deletions(-)

Fusion-Task-Id: FN-7372

Fusion-Task-Lineage: 0d2a05fb-6152-4e29-ac2c-88dd055132ee

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-01 10:13:33 -07:00
gsxdsm
98ca9ac090 FN-7353: fix mobile task menu action taps
Fix task context menu touch activation so mobile popup actions complete reliably.

- Commit touch and pen menu actions on pointer release while preserving mouse click activation.
- Guard synthesized mobile clicks so each selected task action runs exactly once and closes the menu.
- Cover Board, List, shared context menu, and Task Detail mobile popup action selection in tests and docs.
- Add a patch changeset for the published CLI bundle.

Files changed:
 .changeset/fn-7353-mobile-popup-context-menu.md    |  7 ++++
 docs/dashboard-guide.md                            | 12 ++++---
 .../dashboard/app/components/TaskContextMenu.tsx   | 41 ++++++++++++++++++----
 .../app/components/__tests__/ListView.test.tsx     | 12 +++++--
 .../app/components/__tests__/TaskCard.test.tsx     | 26 +++++++++++---
 .../components/__tests__/TaskContextMenu.test.tsx  | 23 ++++++++++++
 .../TaskDetailModal.definition-actions.test.tsx    | 31 ++++++++++++++++
 7 files changed, 133 insertions(+), 19 deletions(-)

Fusion-Task-Id: FN-7353

Fusion-Task-Lineage: 4de96306-1bcc-403d-88fa-be4ec0d9149d

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-01 07:33:56 -07:00
gsxdsm
924bcb97d5 FN-7255: add task card context menus
Add shared task action menus across board and list task surfaces.

- Add reusable task context menu UI with open, copy, archive, delete, pause, duplicate, retry, refine, and dependency actions.
- Wire board cards, swimlanes, worktree groups, and list rows to expose consistent menu behavior.
- Reuse task-detail action handlers and cover menu interactions with dashboard tests.
- Document the new task context menu behavior and add a patch changeset.

Files changed:
 .changeset/fn-7255-card-context-menu.md            |   7 +
 docs/dashboard-guide.md                            |   6 +
 packages/dashboard/app/App.tsx                     |   2 +
 packages/dashboard/app/components/Board.tsx        |  61 ++-
 packages/dashboard/app/components/Column.tsx       |  43 +-
 packages/dashboard/app/components/Lane.tsx         |  11 +-
 packages/dashboard/app/components/ListView.css     |  25 ++
 packages/dashboard/app/components/ListView.tsx     | 438 ++++++++++++++++++-
 packages/dashboard/app/components/TaskCard.css     |  12 +
 packages/dashboard/app/components/TaskCard.tsx     | 472 ++++++++++++++++++++-
 .../dashboard/app/components/TaskContextMenu.css   |  57 +++
 .../dashboard/app/components/TaskContextMenu.tsx   | 346 +++++++++++++++
 .../dashboard/app/components/TaskDetailModal.tsx   | 235 ++++------
 .../dashboard/app/components/WorktreeGroup.tsx     |  60 ++-
 .../app/components/__tests__/ListView.test.tsx     | 159 ++++++-
 .../__tests__/TaskCard.cli-states.test.tsx         |   1 +
 .../app/components/__tests__/TaskCard.test.tsx     | 180 +++++++-
 .../components/__tests__/TaskContextMenu.test.tsx  | 205 +++++++++
 .../app/components/__tests__/board-mobile.test.tsx |   1 +
 .../app/components/dashboard/MainContent.tsx       |  12 +
 .../__tests__/MainContent.graph-popout.test.tsx    |   1 +
 .../dashboard/app/components/dashboard/types.ts    |   1 +
 packages/dashboard/app/hooks/useAppSettings.ts     |   8 +
 23 files changed, 2178 insertions(+), 165 deletions(-)

Fusion-Task-Id: FN-7255
Fusion-Task-Lineage: 5b5714a9-3eb5-4df1-a466-0d2f839b6bd9
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-30 01:57:09 -07:00