v0.28.0
Released July 17, 2026 · All releases
Plan model hardening. Tighten the plan runes' data model along three axes: status vocabulary, spec/PR traceability, and the dependency graph — then sweep the existing content to match.
Changes
- Add the
datarune (SPEC-103) — ingest an external tabular source and render it as a table, chart, or datatable. - A preprocess-time
{% data %}rune reads an external file through the SPEC-113ProjectFilessandbox and emits a Markdoctablenode thatchartanddatatableconsume with no structural changes — the emitted table is also the honest no-JS fallback. - Formats — CSV/TSV (RFC-4180 quoting,
delimiter/headerknobs) and JSON/NDJSON (rootlocator,orientrecords/values/index,key-column, nested objects flattened to dotted headers).formatis extension-inferred and overridable. - Shaping — build-time
where(the SPEC-070field:valuegrammar),sort,columns(select/order/rename),limit/offset, all format-agnostic. - Typing —
numeric/textwith auto-inference; typed-numeric cells emit a normalizeddata-value("$1,200"→1200) thatchartreads anddatatablenow sorts on. - datatable — its sort comparator now prefers a cell's
data-valueover its text, so human-formatted numbers sort correctly. Purely additive: tables withoutdata-valueare unchanged, and hand-authored tables can opt in. - Failures (sandbox escape, missing file, parse error, empty result) render a visible error callout and warn — the build continues.
- Give plan dependencies a direction so cycle detection means what it says (SPEC-114).
- Directed sections —
workandbuggain canonical## Blocked by(this item waits for the ref) and## Blocks(the ref waits for this item) sections, each with aliases.## Dependenciesis retained as a deprecated alias ofBlocked by, so legacy content keeps parsing. - Typed edges —
PlanEntitycarries a directeddependenciesarray derived only from those sections. Prose{% ref %}mentions,## References, and the source line are no longer dependency edges. - Meaningful cycle detection —
checkCircularDepsbuilds its graph from the typed edges (normalised to "A is blocked by B"), not the raw ref set. This clears the 88 false-positivecircular-dependencyerrors that any two items mentioning each other used to produce, while a genuine directed deadlock is still caught.plan nextand the pipeline dependency rollups consume the same typed edges — one source of truth. refrakt plan migrate dependencies— renames legacy## Dependenciesheadings to## Blocked by(dry-run by default;--apply/--git) and flags — without auto-flipping — entries whose prose reads like the reverse direction, for manual review.- Docs — CLAUDE.md and the plan workflow docs describe the directed model, the section aliases, and the migration.
- The scan cache is versioned so upgrading discards a stale cache whose entities predate the typed
dependenciesfield. - Close the spec → work → PR traceability loop (SPEC-049).
- Spec lifecycle — specs gain
implemented(code inmain) andshipped(released to npm) statuses beyondaccepted, plus areleased-in="vX.Y.Z"attribute.plan validateerrors on ashippedspec that lacksreleased-in. - ADR
rejected— decisions gain a terminalrejectedstatus for "considered and explicitly declined", distinct fromsuperseded/deprecated. - First-class
prattribute —workandbugaccept a multi-valuedpr(<org>/<repo>#<number>).plan validateerrors on malformed values but does not warn on a missingpr(carrot before stick). The legacyPR:resolution line is still parsed as a fallback; the attribute wins. plan statustraceability rollups — a per-spec PR rollup (deduped acrossimplemented-bywork) and animplemented-flip suggestion when every linked work item of anacceptedspec isdone. Exposed in--format json.refrakt plan migrate pr-attrs— backfills theprattribute on legacydonework /fixedbug items by mining git merge-commit history (dry-run by default;--apply/--git). It attributes a commit to the PR whose topic branch actually introduced it, skips items whose history is ambiguous, and reports unresolved items without touching them.- Docs — CLAUDE.md's completion checklist gains a standalone
prstep; theplan inittemplate, SPEC-021, and the site plan docs describe the new statuses, theprattribute, and theaccepted → implemented → shippedlifecycle. - Consolidate the plan status vocabulary and add terminal work states (SPEC-117).
plugins/plan/src/commands/enums.tsis now the single source of truth for status/severity/priority/complexity vocabularies. Consumers (rune schemas, MCP input schemas,next/status/validate, the renderer, andtheme.orderings) import from it instead of re-declaring value lists, and an exhaustiveness test fails CI if a canonical status ever lacks a sentiment-map or ordering entry.- New terminal work states —
cancelled(deliberately dropped) andsuperseded(replaced, paired with a newsupersedes="WORK-xxx"attribute). Both are terminal but non-achieving: excluded fromplan next, milestone progress numerators, andplan-progressachieved counts.supersededproduces asupersedes/superseded-byrelationship edge. - Derived lifecycle helpers —
TERMINAL_STATUSES,ACHIEVING_STATUSES,ACTIONABLE_STATUSESandisTerminal/isAchieving/isActionable, so every consumer asks the same lifecycle question the same way. - Validation —
plan validatewarns on asupersededwork item withoutsupersedes(or with an unresolvable one), and no longer warns about a## Resolutionon acancelled/supersededitem (terminal items may record why they were retired). - Drift fixes — the MCP
plan.updatetool now acceptspending(work) andcosmetic(bug severity) and rejectstrivial, because its enums derive fromenums.tsrather than a hand-maintained copy that had drifted (a regression of the WORK-127 / SPEC-037 fix).