## Why
Diagnosing "tasks take too long" showed the dominant end-to-end
wall-clock is **waiting**, not work: tasks sit in `todo` (queue) and
`in-review` (merge wait) far longer than the agent actually runs. Today
only `cumulativeActiveMs` exists, which measures **in-progress time
only** — every other stage's dwell had to be reconstructed by hand from
agent logs.
## What
Adds `columnDwellMs?: Record<string, number>` to `Task` — a per-column
accumulator (column name → cumulative ms), recorded at the **same store
column-transition seam** as `cumulativeActiveMs` (`moveTaskInternal`).
On each move it adds `columnMovedAt(new) − columnMovedAt(prev)` to the
bucket for the column being left:
- clamped `>= 0` (clock skew safe);
- unparseable/missing prior timestamp and zero-dwell moves are skipped
(no spurious buckets);
- second visits **add** to the existing bucket (multi-visit churn is
captured);
- flag-independent — keys off the generic `columnMovedAt` delta, so it
runs for both the workflow-hook and legacy-inline move paths.
This makes per-stage dwell directly queryable, the same way
`productivity-analytics.ts` already consumes `cumulativeActiveMs`.
## Persistence
JSON-text task column, following the v129 `workspaceWorktrees` precedent
exactly: `SCHEMA_SQL` column + `SCHEMA_VERSION` 129→130 + a versioned
`addColumnIfMissing` migration. Additive and behavior-preserving —
pre-existing rows start NULL and accumulate from their next transition.
Survives archive/restore (added to the archive-entry mapping).
## Tests
`src/__tests__/store-execution-timing.test.ts` — new regression asserts
dwell across
`todo→in-progress→in-review→done→todo→in-progress→in-review` accumulates
the right per-column ms (second visits add) and survives a `getTask` DB
round-trip.
```
pnpm --filter @fusion/core exec vitest run src/__tests__/store-execution-timing.test.ts ... --reporter=dot
→ store-execution-timing 5/5, schema suites (goals/secrets) green, 17/17 total
```
Migration chain verified end-to-end (secrets-schema test climbs v11/v82
→ v130). No hardcoded literal version assertions in the suite; schema
tests assert against the `SCHEMA_VERSION` constant.
`@fusion/core` is private — no changeset.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1781">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added per-column dwell timing to tasks, showing how long work spent in
each column across multiple visits.
* Preserved this timing data when tasks are archived and restored.
* **Bug Fixes**
* Task timing now updates correctly during column moves, including
repeated returns to the same column.
* Existing data can be upgraded to the new timing format without
breaking stored tasks.
* **Tests**
* Added coverage for multi-step task movement and data reloading to
verify timing totals stay accurate.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->