• v1.4.0 fba5879871

    Cadence 1.4.0 Stable

    crenshawdev released this 2026-07-28 16:47:20 +00:00 | 25 commits to main since this release

    Cadence 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-audit orphan. 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.rs onto 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, so files: [a.md, b.md] # [see notes] reads two files
    instead of swallowing the comment's bracket, and requirements: # TODO above
    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 audit and plan-overlap
    envelopes as frontmatter_issues. The shipped template's own former shape was
    one of the broken ones: a files: [] # comment key 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-overlap byte-exact as the plan wrote them, so src/x(1) and
    lib/a`b.mjs survive 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 -C path with a space, & as a
    separator, $(...), backticks, a subshell, an escaped \", and the
    bash/sh/zsh/dash/eval wrapper set with -c all 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.mjs carries 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 sees sudo 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: refuse that means sudo git commit and timeout 60 git commit now 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 denied command -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 ## Phases derives a closed-milestone state now instead of
    unparseable-roadmap, so /cad-progress works in the window between a
    milestone close and the next cycle rather than calling the roadmap broken.
    status returns cycle: "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 ## Active requirement section

    An ## Active requirement no phase has picked up now breaks /cad-audit as
    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.total now counts traceability
    rows plus unpicked ids rather than rows.length, so anything you wrote against
    total === rows.length reads a different number. And unseeded moves 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 ## Active heading gains no break from
    any of this.

    The spine's own bookkeeping

    /cad-plan seeds its own traceability rows through a new seed-reqs
    subcommand, so a milestone close no longer needs a hand-populated table before
    /cad-audit passes. 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>.md exists before task 1
    and halts with a blocked checkpoint 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 flagging lib/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 --checkJs clean on Node 22 and 24, self-verify clean.

    Install

    /plugin marketplace add https://github.com/crenshawdev/cadence.git
    /plugin install cadence@cadence
    

    Full Changelog: https://github.com/crenshawdev/cadence/compare/v1.3.1...v1.4.0

    Downloads