-
Cadence 1.4.0 Stable
released this
2026-07-28 16:47:20 +00:00 | 25 commits to main since this releaseCadence parsed four formats it owns with regexes that accreted a case at a
time, and every one of them failed silently in both directions. An over-read
invented a requirement id that came back later as an/cad-auditorphan. An
under-read dropped a real path and handed the parallel-safety gate a false
overlaps: [], so the gate dispatched two plans that both write
src/shared.rsonto the same file. Both of those look exactly like success
from the outside, which is the whole problem.I replaced those four readers with grammars I wrote down. Each one gets a
reference file stating what it accepts, a table of the shapes it deliberately
refuses and what it does with them instead, and a parser-level test per row.
An input outside the grammar now earns a named diagnostic instead of quietly
changing what the reader took.The plan-file frontmatter reader
One normalized classifying pass replaces the accreted arms. The greedy
\[(.*)\]is gone, sofiles: [a.md, b.md] # [see notes]reads two files
instead of swallowing the comment's bracket, andrequirements: # TODOabove
a block list reads the block instead of the comment. That second one was a
regression I shipped in v1.3.1.Everything outside the grammar now reports on the
auditandplan-overlap
envelopes asfrontmatter_issues. The shipped template's own former shape was
one of the broken ones: afiles: [] # commentkey line with indented paths
under it took the inline arm, so every path beneath it vanished with no
diagnostic at all. Four more shapes earn names now: a quoted value with
trailing text, a commented-out key line inside an open block, a missing space
after the colon, a backslash escape, and a backtick-wrapped value.Paths reach
plan-overlapbyte-exact as the plan wrote them, sosrc/x(1)and
lib/a`b.mjssurvive unrewritten.One tokenizer for the git rails
I closed the six rail-3 holes from the v1.3.1 known-gaps list, plus a seventh I
found while gathering context. A quoted-Cpath with a space,&as a
separator,$(...), backticks, a subshell, an escaped\", and the
bash/sh/zsh/dash/evalwrapper set with-call reached the network
with no prompt before this. They ask now.Six more regex arms was the alternative, and regex patching is what produced
the two push-rail regressions this repo already paid for, so I deleted the arms
instead of extending them. One left-to-right pass in
cadence-core/bin/lib/shell-tokens.mjscarries a single quote and escape
state, keeps word boundaries, descends into substitutions and subshells, and
re-tokenizes a wrapper's operands. Both rails read that one output, so they
agree on what a wrapped command is.One deliberate regression comes with it. The guard detects a wrapper at any
position, so it seessudo bash -c "git push", but it only hard-refuses when
both the wrapper and the git word sit at command position. Under
git.on_protected: refusethat meanssudo git commitandtimeout 60 git commitnow ask instead of hard-blocking. I dropped the enumerated prefix and
shell-keyword sets that used to deny them: every prefix carries its own option
grammar, three review rounds kept finding new members, and the enumeration
falsely deniedcommand -v git commit, which runs nothing. A missing deny
costs a prompt on a real commit. A wrong deny blocks read-only work.The roadmap phase list
An empty
## Phasesderives a closed-milestone state now instead of
unparseable-roadmap, so/cad-progressworks in the window between a
milestone close and the next cycle rather than calling the roadmap broken.
statusreturnscycle: "none"as an additive field.A wiped checkbox list whose
### Phase N:detail sections survived is the
signature of an interrupted prune, and it reports as one. A heuristic read that
same tree as a cleanly closed milestone, which is why I reverted the first
attempt at this during the v1.3.1 close.The
## Activerequirement sectionAn
## Activerequirement no phase has picked up now breaks/cad-auditas
unpicked. The gate used to hold only against a zero-row traceability table,
so it went quiet as soon as one phase had a plan, which is the state a
milestone spends most of its life in. That blind spot is how the v1.2.0 and
v1.3.1 closes both got through without their audits firing.Two things to know before you upgrade.
counts.totalnow counts traceability
rows plus unpicked ids rather thanrows.length, so anything you wrote against
total === rows.lengthreads a different number. Andunseededmoves the
verdict now, reversing the additive shape I shipped one milestone earlier: a
diagnostic that never moves the verdict leaves the ship gate exactly as
permeable as it was. A project with no## Activeheading gains no break from
any of this.The spine's own bookkeeping
/cad-planseeds its own traceability rows through a newseed-reqs
subcommand, so a milestone close no longer needs a hand-populated table before
/cad-auditpasses. It needed one at the last two closes, and that is exactly
why neither audit fired.A worktree executor now checks that its own
PLAN-<k>.mdexists before task 1
and halts with ablockedcheckpoint naming the missing path, rather than
planning against a stale merge point. Three executors caught that one only by
noticing. It repairs nothing on its own, and it cannot merge, rebase or fetch
inside the worktree.Known gaps
I wrote these into CHANGELOG.md under
[1.4.0]rather than leaving you to find
them. Markdown decoration inside a frontmatter value that touches neither
boundary still resolves silently, and I cannot flag an interior backtick
without also flagginglib/a`b.mjs, which has to stay clean. Closing that
means stating one rule about markdown in values, not adding a sixth arm.727 tests,
tsc --checkJsclean on Node 22 and 24, self-verify clean.Install
/plugin marketplace add https://github.com/crenshawdev/cadence.git /plugin install cadence@cadenceFull Changelog: https://github.com/crenshawdev/cadence/compare/v1.3.1...v1.4.0
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
Source code (ZIP)