Skip to content

v0.1.9

Choose a tag to compare

@github-actions github-actions released this 25 Aug 08:43
· 20 commits to dev since this release

Action required

Run specflow upgrade in every repo that has specflow installed, and update the binary. This
release changes the CLI, every managed procedure file, and every agent adapter.

curl -fsSL https://raw.githubusercontent.com/MatanKoby/specflow/main/install.sh | sh
specflow upgrade
specflow status     # `stale` should read `none` afterwards

If a managed file shows as drifted and you have edited it on purpose, specflow waive <file>
is new in this release: see Drift is a state you can leave, below.

Five batches

v0.1.9 is the largest line so far. Two of the five fix things a downstream install reported, one
adds a verb for repos arriving from 0.1.8, and two are a punctuation sweep with an enforcement rule
behind it.

Batch What
RC drift is a state you can leave: a reconcilable sidecar, adoption on identical bytes, and specflow waive
MC specflow migrate-claims, retrofitting 0.1.8's stub shape onto entries written before it
FS the stub contract now says what the code already does, and finish supplies and checks the pointer
ED no em dash in anything specflow ships as files
EM no em dash in anything specflow writes at runtime

Drift is a state you can leave

Two defects, both reported from an install running 0.1.8, and both about the same thing: editing a
managed file used to be a one-way door.

The sidecar held the wrong bytes. When upgrade declined to overwrite a file you had edited, it
wrote the fresh template whole to <file>.specflow-new. For an adapter that is right, because
every byte is specflow's. For a marker-delimited file such as CLAUDE.md it was a footgun: the
warning invites you to reconcile, the obvious reconciliation is mv, and mv threw away everything
outside the region. One install carried 27 managed lines and 73 lines of its own project guidance
below them. The sidecar now holds before + markers + fresh region + after, so mv is correct
everywhere, and the CLI says mv outright.

Drift was terminal. Upgrade carried the old baseline forward for a drifted file, so a user who
followed the printed advice ended up with a region matching the new template and a baseline still
holding the old hash: re-drifted on every upgrade, warned on in every verify, with no exit but
discarding the edit. Upgrade now adopts on identical bytes, which self-heals every already
reconciled install on its next run, with no verb involved.

specflow waive <file> keeps a deliberate edit.

specflow waive AGENTS.md          # this edit is on purpose; stop reporting it
specflow waive --all              # every currently drifted file
specflow waive --clear AGENTS.md  # go back to reporting it as drift

A waiver changes no file bytes. It records the exact bytes waived (so a later edit resurfaces as
drift) and the template version it was taken against (so upgrade can tell you when specflow has
moved past your waiver rather than sitting silent forever) in a new waived map in
specflow/config.json. upgrade leaves a waived file alone and writes no sidecar, verify reports
it as a choice rather than a warning, and status counts it on its own row. Only a drifted file
can be waived: waiving a clean one would silently opt it out of every future refresh for nothing.

This is deliberately a waiver and not the specflow adopt the queue entry originally proposed.
Re-recording your edited bytes as the baseline would make the region read as clean, so the very next
upgrade would refresh it and destroy the edit being blessed.

specflow migrate-claims

Retention bounds how many entries a ledger holds. The stub cap that shipped in 0.1.8 bounds how big
one entry gets, but it only reached entries written after the upgrade, so a repo arriving at 0.1.8
still carried every legacy essay in the file that is re-read on every claim, finish, and prune.

specflow migrate-claims --dry-run   # report only
specflow migrate-claims

Each over-cap entry in CLAIMS.md ## Completed and in specflow/history/CLAIMS_DONE.md is
rewritten to its metadata, a stub within the cap, and the Full narrative pointer; the narrative
relocates to specflow/history/BUILD_QUEUE_DONE.md under that batch's heading.

Three things it deliberately does not do. The body relocates whole, not just the part that did
not fit, so the archive section reads from its first sentence and the stub is a copy of its head.
An entry already within the cap is left exactly as it is, including one with no pointer, because
emitting a pointer at a section that may not exist would fabricate a reference. And ## In progress
is never touched: a live claim has no archived narrative to point at yet. If any ledger fails to
parse, nothing is written.

Run against this repo's own ledgers it took CLAIMS.md from 201 to 137 lines and CLAIMS_DONE.md
from 696 to 328, losing no prose.

The stub contract

finish has always skipped blank lines and the pointer when counting a stub against the 8-line cap,
which is why a 10-line stub file is accepted. Nothing said so, so an agent budgeting against the
bound budgeted against the wrong number and the natural response to a rejection was to delete prose
that was never costing anything. finish-batch.md step 3, templates/base/CLAIMS.md, and
specflow finish --help now all say the cap counts prose lines.

The Full narrative pointer is now checked rather than merely skipped. finish supplies it
when your stub omits one (gated on --done-file, since a pointer at a section that was never filed
is worse than no pointer) and refuses one that names a different batch, which is what a stub
copy-pasted from the entry above it looks like. That failure is silent otherwise: it sends the next
reader to someone else's narrative with nothing visibly wrong.

No em dashes

specflow's shipped text no longer contains an em dash (or an en dash, or a double hyphen in prose).
This matters because a downstream sweep is drift: upgrade would stop refreshing the swept files,
and the next clean upgrade would put the dashes back. Fixing it upstream is the only version that
holds.

Batch ED swept the files: 214 em dashes and 2 en dashes across templates/** and
specflow/procedures/*.md. Punctuation only, nothing reworded. A fresh specflow init now writes
an install with no em dash in it.

Batch EM swept what the CLI writes. specflow claim used to put ### Batch N — title into
your CLAIMS.md and finish put ## Batch N — title into your BUILD_QUEUE_DONE.md, so a repo
that had just been swept clean got a fresh em dash back on its next verb. Both now write a plain
hyphen, matching the entry format AGENTS.md and the CLAIMS.md template have always documented.
Console output, --help text, and every error and warning message went the same way.

Your existing ledgers keep working. The parsers still accept the em dash, and always will:
finish, next, and migrate-claims locate entries by heading, and every install that ran 0.1.9
or earlier has ledgers full of em-dash headings. Nothing needs rewriting, and mixed ledgers are
fine. Three tests pin this from both sides.

Behavior changes

  • New: specflow waive <file>... [--all] [--clear].
  • New: specflow migrate-claims [--dry-run].
  • upgrade writes a reconcilable sidecar for marker-managed files, and adopts a region whose bytes
    already match the template instead of reporting it as drift forever.
  • upgrade, verify, and status all report waived files distinctly from drifted ones.
  • finish supplies a missing Full narrative pointer and refuses one naming another batch.
  • claim and finish write hyphen headings into downstream ledgers; the parsers still accept the
    em dash.

Install

curl -fsSL https://raw.githubusercontent.com/MatanKoby/specflow/main/install.sh | sh
# or
go install github.com/MatanKoby/specflow/cmd/specflow@v0.1.9

Full diff: v0.1.8...v0.1.9