## U12 part 3 — every remaining raw-flag read is now on the move path
**Stacks on #2512** (shares a line in `workflow-ops.ts`). Merge that
first.
**Behaviour-preserving. Not a single persisted byte changes.**
### What changed
The three v1-IR rollback-compat persist sites (#1405) all read `flagOn ?
ir : downgradeIrToV1IfPure(ir)`, where `flagOn` came from the retired
raw `experimentalFeatures.workflowColumns` key. No production writer
sets it, so **every real project has always taken the downgrade arm**.
Removing the branch is a runtime no-op; it deletes three flag reads.
Sites: `createWorkflowDefinitionImpl`, `updateWorkflowDefinitionImpl`,
and `insertWorkflowDefinitionSyncImpl` — whose `flagOn` *parameter* is
gone too, along with the plumbing that resolved it in
`migrateLegacyWorkflowStepsImpl`.
With those gone, **`TaskStore.workflowColumnsFlagOn()` has no callers
and is deleted.** Its six readers were the three U5 guards (part 2) and
these three persist sites.
### The decision I made, and why I went the other way
I had this slice scoped as "retire the v1 downgrade." **I rejected
that.** It is a compatibility affordance, not cutover machinery: it
fires only for a graph exactly equivalent to pure v1 (default columns,
default placements, no v2-only features), and `upgradeV1ToV2` re-reads
it into an identical v2 graph, so the runtime never sees a difference.
Retiring it would break a binary downgrade for zero benefit — and stale
binaries opening these databases is an **observed event** in this
project, not a hypothetical.
So the slice became the strictly better version of itself: same three
flag reads removed, no compat surface touched.
### Why this matters for sequencing
`isWorkflowColumnsCompatibilityFlagEnabled` survives. It is still read
by `moves.ts:363` and by `workflow-task-create-ops.ts:351`'s move-policy
preflight that feeds it. Removing those reads **is** the U2b move-path
convergence with its equivalence-proof obligation.
The point of deleting the wrapper is that it makes the remainder
enumerable:
```
$ grep -rn isWorkflowColumnsCompatibilityFlagEnabled --include=*.ts packages/ | grep -v __tests__
packages/core/src/store.ts:38 <- the definition
packages/core/src/task-store/moves.ts:9,363 <- U2b
packages/core/src/task-store/workflow-task-create-ops.ts:11,351 <- U2b (feeds moves.ts)
```
**Every surviving read is on the move path.** U2b deletes the definition
and the unit closes.
### On coverage — stated honestly
This change is behaviour-preserving, so it has **no revert-proof test**,
and I am not going to claim one. `flagOn ? ir : downgrade(ir)` with an
always-false flag *is* `downgrade(ir)`.
What needed a guard is the next edit someone is tempted to make —
deleting `downgradeIrToV1IfPure` as dead cutover machinery. New
`workflow-ir-v1-rollback-persistence.test.ts` fails if it is removed,
and pins the exact boundary: the built-in coding workflow (named columns
+ traits) stays v2; a pure-v1-equivalent graph stores as v1 without the
synthesized `columns`; a downgraded graph re-parses to an **identical**
runtime graph (the property that makes unconditional application safe);
a graph with a custom column stays v2.
### Verification
`pnpm test:gate` (307 + 10 + 71), `pnpm lint`, `pnpm verify:fast` (17
steps), typecheck green. Core workflow-named suites: 383 passed, 1
failed — `workflow-ir-settings.test.ts > moved-key catalog ...`
(`expected 10 to strictly equal 3`), which I confirmed fails identically
on a stashed clean tree. Pre-existing, unrelated. No Fusion instance
booted.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved workflow persistence compatibility by consistently storing
pure v1-equivalent workflows in the compatible format.
* Preserved v2 workflows and custom column information when they are not
v1-equivalent.
* Retired obsolete feature-flag checks without changing stored workflow
or board behavior.
* **Tests**
* Added coverage for workflow version preservation, rollback-compatible
serialization, and custom columns.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>