Highest-severity finding of the post-merge audit, and it is the
**out-of-the-box** shape rather than an edge case.
## The defect
`createTask` resolves the intake column only as a by-product of
materializing the project's default workflow. A project that has never
**explicitly** set a default workflow has no persisted default row — so
that materialization returns nothing, `resolvedEntryColumn` stays
`undefined`, and the row falls through to the hard-coded `|| "triage"`.
Post-merge, that column does not exist in the default workflow.
Measured, three creates on one store:
| create | column |
|---|---|
| no default row persisted | **`triage`** ← broken |
| default explicitly `builtin:coding` | `todo` |
| explicit `workflowId` | `todo` |
`builtin:coding` is the **implicit** default via `DEFAULT_WORKFLOW_ID`,
and nothing writes a default-workflow row until an operator picks one.
So this was **every new task on a fresh project.**
## What it costs
Triage discovery resolves intake **by trait**, so `isAtIntakeColumn` is
false for a card sitting in `triage` while its workflow says `todo` —
**the card is never admitted for planning.** It isn't in the hold column
either, so hold-release ignores it. Only
`reconcileUndeclaredTaskColumns` eventually re-homes it.
A newly created task is invisible to planning until that sweep runs. Not
a permanent stall, but the first thing an operator does on a new project
is create a task.
## The fix — three parts, and missing any one leaves it half-fixed
1. `resolveDefaultWorkflowIntakeColumn` falls back to
`DEFAULT_WORKFLOW_ID` when no default row is persisted — the implicit
default every other resolver already assumes.
2. Both create paths consult it as a **last** resort before the literal,
so any path that already has an explicit column or a resolved entry
column is untouched.
3. **`isIntakeColumn` honours the same fallback.** Without this the card
lands in the right column but is classified *not*-intake and receives
`generateSpecifiedPrompt` instead of the bootstrap seed — and triage
admits a card only when its `PROMPT.md` reads as a seed, so it would sit
in Planning already looking "planned". FN-8587's failure mode by another
route.
`workflowId: null` ("No workflow") is excluded and asserted — there is
no workflow whose intake could be resolved, so that path keeps the
literal.
## Fixture drift, fixed with intent preserved
Seven tests asserted a created card lands in `triage`. None had their
assertion merely retargeted:
- **`move-task-if-planning`, `delete-task-if-planning`** — the mechanism
under test is the **live predicate**, not the column. Predicates and the
"advanced" column now name where the card actually rests.
- **`task-lifecycle-e2e`, `activity-log-parity`, `mission-store`** —
first-column and first-transition expectations.
- **`workflow-reconciliation-production-shape`** — the subtle one. Its
filler must occupy the **target** workflow's capped `triage` entry
column, but was created *before* the switch and so landed in the
**project default's** intake. It now names its column explicitly, which
makes the fixture independent of the project default — exactly the
coupling that let it drift.
- **`store-create-intake-column`** — the "lands in triage" guard now
names the invariant (the default workflow's *own* intake column) and
keeps a `not.toBe("triage")` so a regression back to the literal still
fails.
## Measured
Core package, against the 47-failure post-merge main baseline: **47
failed / 4413 passed — zero new failures.**
Three engine triage tests are red and are **not from this change**:
verified by stashing these edits and re-running against clean main,
where they fail identically. They arrived with #2515 and belong to the
triage-fixture owner.
Gate 414 + 10 + 71 green. Lint clean.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* New tasks now consistently start in the default workflow’s `todo`
intake column, including fresh projects without persisted workflow
settings.
* Bootstrap `PROMPT.md` content is now created consistently for all
supported task-creation paths.
* Task movement and deletion behavior now correctly respects current
columns and avoids acting on stale task data.
* Workflow reconciliation and activity tracking now reflect the updated
default task lifecycle.
* **Tests**
* Expanded coverage for intake-column resolution, task lifecycle
transitions, stale candidates, and workflow edge cases.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>