@rsaglobaltech/specgate 0.22.0 → 0.22.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +135 -51
  2. package/README.md +81 -96
  3. package/dist/packages/core/src/domain/CapabilitySpecMerge.js +83 -0
  4. package/dist/packages/core/src/domain/CapabilitySpecMerge.js.map +1 -0
  5. package/dist/packages/core/test/unit/capability-spec-merge.test.js +104 -0
  6. package/dist/packages/core/test/unit/capability-spec-merge.test.js.map +1 -0
  7. package/dist/packages/mcp-spec-driven/src/native-tools.js +1 -1
  8. package/dist/packages/mcp-spec-driven/src/native-tools.js.map +1 -1
  9. package/dist/scripts/agents/commands.js +7 -7
  10. package/dist/scripts/agents/commands.js.map +1 -1
  11. package/dist/scripts/agents/detect.js +1 -0
  12. package/dist/scripts/agents/detect.js.map +1 -1
  13. package/dist/scripts/agents/init.js +13 -0
  14. package/dist/scripts/agents/init.js.map +1 -1
  15. package/dist/scripts/alm/cli.js +3 -2
  16. package/dist/scripts/alm/cli.js.map +1 -1
  17. package/dist/scripts/cli/commands/change/ChangeCommand.js +22 -1
  18. package/dist/scripts/cli/commands/change/ChangeCommand.js.map +1 -1
  19. package/dist/scripts/cli/commands/change/TicketCommand.js +64 -6
  20. package/dist/scripts/cli/commands/change/TicketCommand.js.map +1 -1
  21. package/dist/scripts/cli/commands/quality/CheckCommand.js +15 -5
  22. package/dist/scripts/cli/commands/quality/CheckCommand.js.map +1 -1
  23. package/dist/scripts/cli/commands/quality/DoctorCommand.js +22 -8
  24. package/dist/scripts/cli/commands/quality/DoctorCommand.js.map +1 -1
  25. package/dist/scripts/docs/journey-storyboard.js +34 -17
  26. package/dist/scripts/docs/journey-storyboard.js.map +1 -1
  27. package/dist/scripts/docs/nav.js +155 -143
  28. package/dist/scripts/docs/nav.js.map +1 -1
  29. package/dist/scripts/docs/record-journey.js +46 -19
  30. package/dist/scripts/docs/record-journey.js.map +1 -1
  31. package/dist/scripts/docs/terminal-storyboard.js +15 -11
  32. package/dist/scripts/docs/terminal-storyboard.js.map +1 -1
  33. package/dist/scripts/draft/drafting-guide.js +4 -0
  34. package/dist/scripts/draft/drafting-guide.js.map +1 -1
  35. package/dist/scripts/draft/ticket-guide.js +4 -0
  36. package/dist/scripts/draft/ticket-guide.js.map +1 -1
  37. package/dist/scripts/harness/init.js +85 -25
  38. package/dist/scripts/harness/init.js.map +1 -1
  39. package/dist/scripts/harness/prompt.js +13 -1
  40. package/dist/scripts/harness/prompt.js.map +1 -1
  41. package/dist/scripts/lib/base-ids.js +7 -0
  42. package/dist/scripts/lib/base-ids.js.map +1 -1
  43. package/dist/scripts/lib/change-base.js +230 -0
  44. package/dist/scripts/lib/change-base.js.map +1 -0
  45. package/dist/scripts/lib/change-overlap.js +234 -0
  46. package/dist/scripts/lib/change-overlap.js.map +1 -0
  47. package/dist/scripts/lib/surface.js +8 -0
  48. package/dist/scripts/lib/surface.js.map +1 -1
  49. package/dist/scripts/lib/ticket-keys.js +48 -3
  50. package/dist/scripts/lib/ticket-keys.js.map +1 -1
  51. package/dist/scripts/merge-capability-spec.js +87 -0
  52. package/dist/scripts/merge-capability-spec.js.map +1 -0
  53. package/dist/scripts/vcs/github-pr.js +1 -1
  54. package/dist/scripts/vcs/github-pr.js.map +1 -1
  55. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,4 +1,5 @@
1
1
  <!-- specgate:allow-placeholders — release notes quote the {{VAR}} template syntax. -->
2
+
2
3
  # Changelog
3
4
 
4
5
  Notable changes, newest first. Follows [Keep a Changelog](https://keepachangelog.com/)
@@ -8,6 +9,91 @@ The release process is in [`docs/release-process.md`](docs/release-process.md).
8
9
 
9
10
  ## [Unreleased]
10
11
 
12
+ ## [0.22.2] — 2026-10-21
13
+
14
+ Parallel tickets that never overwrite each other, rehearsed end to end on a brownfield Maven project with Jira tickets and OpenCode.
15
+
16
+ ### Fixed
17
+
18
+ - **A merge driver that is gone falls back to git's merge** (REQ-169): in a
19
+ project without `node_modules`, the drivers run this machine's copy of
20
+ specgate. With that copy gone, git stopped the merge with only your side in
21
+ the file, no markers, and `git add` dropped the other side's text. The
22
+ driver now says it is missing and merges by lines; `specgate doctor` warns.
23
+ Re-run `specgate harness init` in clones registered before this release.
24
+ - **`id_taken_on_base` only for ids the branch introduced** (REQ-120): a
25
+ requirement the base changed after the branch started was reported as an id
26
+ taken, with the advice to renumber it.
27
+ - **A local `develop` nobody updated is not the base** (REQ-148): `pr.base`
28
+ resolves to `origin/develop` unless the local branch already contains it,
29
+ and a ticket's branch no longer tracks its base. Behind origin, every
30
+ colleague's commit merged from `origin/develop` was reported as missing the
31
+ ticket key.
32
+ - **`check` compares ids with `pr.base`** (REQ-120): ticket keys were
33
+ measured from `develop` and ids from the remote's default, `main`, so an id
34
+ taken on `develop` and not yet released went unseen.
35
+ - **`harness init` keeps a generated matrix on `merge=union`**: it appended
36
+ the row driver after the union line, and git takes the last matching line,
37
+ so the matrix could stop a merge again (ADR-0036).
38
+ - **A ticket's branch starts from `develop` with gitflow** (REQ-148): from
39
+ `pr.base`, else the branch you are on, else the remote's default. A clone
40
+ whose default is `main` cut the branch from `origin/main`, without the
41
+ team's work on `develop`; `ticket_key_missing` measures from the same base.
42
+ - **Readable ids from German summaries** (REQ-161): `ß` → `ss`, `ä` → `ae`…;
43
+ "Groß-/Kleinschreibung" made `gro-kleinschreibung`.
44
+
45
+ ### Added
46
+
47
+ - **`change_base_moved`** (REQ-168): a change records, in `based_on` in its
48
+ `change.yaml`, the text of each requirement it modifies or removes; `check`
49
+ warns and `archive` refuses when that requirement changed since, and `check`
50
+ warns before the branch has even brought the base in.
51
+ `change validate <change> --rebased` records the new text once the delta is
52
+ rewritten. When two tickets rewrote one requirement, the second used to
53
+ archive over the first with a green gate and no conflict.
54
+ - **Capability specs merge requirement by requirement** (REQ-166):
55
+ `harness init` registers a second git merge driver, `specgate-spec`, for
56
+ `docs/specs/capabilities/*/spec.md`, and `doctor` checks it. Two tickets
57
+ archiving into the same capability used to conflict on the whole file; only
58
+ a requirement both rewrote differently conflicts now.
59
+ - **OpenCode in `agents init`** (REQ-162): `/specgate-*` commands in
60
+ `.opencode/commands/`, detected from `.opencode/` or `opencode.json`.
61
+ - **Opening a ticket's change commits and pushes it** (REQ-165), so the ids it
62
+ reserved are visible to every other clone at once; the branch used to be
63
+ pushed empty, with the reservation left uncommitted on one disk.
64
+ - **`change_id_clash`** (REQ-164), and `propose --from-ticket` fetches
65
+ `origin` before reserving ids (REQ-163): two developers who opened tickets a
66
+ minute apart on two clones both reserved REQ-010.
67
+ - **`change_overlap`** (REQ-160): `check`, and the report on a change opened
68
+ from a ticket, warn when a requirement your open change modifies or removes
69
+ is also rewritten by another open change, on this branch or on any local or
70
+ remote-tracking branch not merged yet. Two tickets rewriting REQ-012 on two
71
+ branches used to surface as a git conflict at the second merge, or not at
72
+ all.
73
+
74
+ ## [0.22.1] — 2026-10-20
75
+
76
+ Documentation a newcomer can follow, and the CLI's words brought in line with it.
77
+
78
+ ### Changed
79
+
80
+ - **The documentation, rewritten** after an audit of every page against the
81
+ CLI and the first real end-to-end run on Jira Cloud and GitHub. Three
82
+ sources of work (a change, a brief, a Jira ticket) into one lifecycle of
83
+ four verbs; the recorded journeys run `propose`, `apply` and `archive`;
84
+ archive comes before the pull request everywhere. New pages: _From a Jira
85
+ ticket_ for a team lead setting it up, and _An existing codebase, with work
86
+ in Jira_ (Maven profiles, a parent POM, Bitbucket and Jenkins).
87
+ - **The `/specgate:draft` agent command runs `propose --from-brief`**, and the
88
+ MCP write guard names `specgate propose <id>`.
89
+
90
+ ### Fixed
91
+
92
+ - `propose --help` lists `--no-push`; `alm --help` no longer says a ticket has
93
+ no acceptance criterion.
94
+ - `alm pr` asks for the least token it needs: Pull requests, read and write.
95
+ - `alm pr` is covered by an E2E journey and is not exposed as an MCP tool.
96
+
11
97
  ## [0.22.0] — 2026-10-20
12
98
 
13
99
  A brief shaped like what it becomes, checked before any agent drafts from it
@@ -43,7 +129,7 @@ ticket to Done, the board moved by its own automation.
43
129
  ### Changed
44
130
 
45
131
  - **A draft is not opened over a broken brief.** `propose --from-brief
46
- <module>` refuses with `brief_not_ready` while the brief has an error: an
132
+ <module>` refuses with `brief_not_ready` while the brief has an error: an
47
133
  empty body, an empty module section, a module without its section once the
48
134
  brief uses sections, or rules without examples. A brief with no module
49
135
  sections — a pasted email — drafts as before.
@@ -165,7 +251,7 @@ while it works (ADR-0037).
165
251
 
166
252
  - The placeholder rule ignores code spans, and the vague-step rule code spans
167
253
  and quoted text: `` `tool verify <module>` `` is a command, not a template.
168
- - TDD-3 asks a matrix row for a requirement a spec *declares* (a heading or a
254
+ - TDD-3 asks a matrix row for a requirement a spec _declares_ (a heading or a
169
255
  requirement table row outside fenced code), not for every id it mentions.
170
256
  - A generated matrix is declared `merge=union` in `.gitattributes`: parallel
171
257
  branches no longer conflict on it, and `check` regenerates it.
@@ -229,7 +315,7 @@ while it works (ADR-0037).
229
315
  runtime dependencies; `SPECGATE_FORJA_CMD` points at another forja.
230
316
  - **`specgate add usecase|entity|port`** in a forja project: the class where the
231
317
  architecture expects it, its test and its wiring, through `forja add`; `add
232
- usecase` also creates the requirement and names it in the test. Outside a forja
318
+ usecase` also creates the requirement and names it in the test. Outside a forja
233
319
  project it says to use `new`. In a forja project, `status` suggests it as the
234
320
  next step for a requirement with no code.
235
321
  - **`arch_cmd`: your architecture check in the gate** ([ADR-0028](docs/specs/adr/0028-architecture-conformance-is-part-of-the-gate.md), points 1–2).
@@ -365,8 +451,8 @@ while it works (ADR-0037).
365
451
  `transfers`, `event-registration`, `clinical-record`, `appointment-booking`,
366
452
  `shop-orders` and `time-attendance`: 65 requirements and 85 scenarios, each
367
453
  implemented and tested by the product it came from (Spring Boot, Quarkus and
368
- TypeScript stacks). Questions a pilot could not answer ship as *Needs
369
- Clarification* — drug interaction alerts, shipping costs — instead of an
454
+ TypeScript stacks). Questions a pilot could not answer ship as _Needs
455
+ Clarification_ — drug interaction alerts, shipping costs — instead of an
370
456
  invented answer. Separate id ranges, so a project can install all seven.
371
457
  Install them with `specops add` into a project made by `specgate init`;
372
458
  `init --from-pack` does not handle a requirement with two scenarios yet.
@@ -531,9 +617,9 @@ while it works (ADR-0037).
531
617
 
532
618
  ### Documentation
533
619
 
534
- - **Two new guides.** *From a client brief* — the brief, a draft per module,
620
+ - **Two new guides.** _From a client brief_ — the brief, a draft per module,
535
621
  assumptions and open questions, the D1–D10 checklist, writing in Spanish, and
536
- what the checklist cannot see. *Already on OpenSpec* — `verify`, scenario ids,
622
+ what the checklist cannot see. _Already on OpenSpec_ — `verify`, scenario ids,
537
623
  V1–V7, adopting with `--since`, the GitHub Action.
538
624
  - **The harness** documents when it does not retry, the per-attempt time limit,
539
625
  and the build in the gate; **the README** covers drafting from a brief,
@@ -620,7 +706,7 @@ From a second and third cycle on the same product (reservas_app), on 0.17.1.
620
706
  - **`plan` and `status` agree with `validate` about untested scenarios.** A
621
707
  requirement with two scenarios no test named was "Ready to close — its test
622
708
  is in place", and `NEEDS_STATUS_UPDATE` to the harness, while `validate
623
- --strict` said "Nothing proves" them. It is now `NEEDS_TEST`.
709
+ --strict` said "Nothing proves" them. It is now `NEEDS_TEST`.
624
710
  - **`draft --check`:** a requirement can say it lives on one surface
625
711
  (`surfaces=web` in its trace), so a menu is not asked for an API scenario
626
712
  (D3); a value already in the project's specification — reviewed in an
@@ -646,7 +732,7 @@ Found building a second real product from a client brief (reservas_app,
646
732
  written in Spanish).
647
733
 
648
734
  - **A draft archives into feature files, in its own language.** `change
649
- archive` wrote no `.feature` for a requirement whose trace named none — a
735
+ archive` wrote no `.feature` for a requirement whose trace named none — a
650
736
  draft that passed `draft --check` archived with "0 materialised". Each
651
737
  requirement with scenarios now gets `features/<capability>/<REQ>.feature`.
652
738
  Scenarios written with `DADO / CUANDO / ENTONCES` become Spanish Gherkin
@@ -670,7 +756,7 @@ written in Spanish).
670
756
  the one line that turns it on (`specgate harness init`). The first gate after
671
757
  adoption still checks the specification only, as documented.
672
758
  - **`draft --check`:** an answered question (an `Answer` column, or `Answer
673
- (Q1): …` below the table) no longer keeps its requirement waiting; a value
759
+ (Q1): …` below the table) no longer keeps its requirement waiting; a value
674
760
  repeated in a scenario is one finding, not one per mention; "responsive" is
675
761
  not read as a promised response time, and `px` is a unit.
676
762
  - **`status` shows the title of a requirement archived from a change** instead
@@ -686,6 +772,7 @@ written in Spanish).
686
772
  version, commit or variables do.
687
773
 
688
774
  ## [0.16.0] — 2026-10-09
775
+
689
776
  ### Changed
690
777
 
691
778
  - **`AGENTS.md` is the agent contract; `AI_RULES.md` folds into it**
@@ -761,7 +848,7 @@ written in Spanish).
761
848
  (`--run`), or after a scenario's text changed since `--record` pinned it.
762
849
  `--since <ref>` gates only claims made after the ref, so adopting it never
763
850
  fails a project for its past. `--ids` prints the ids to name; `--format
764
- github` annotates the spec lines; `actions/verify` runs it on pull requests.
851
+ github` annotates the spec lines; `actions/verify` runs it on pull requests.
765
852
  Read against OpenSpec's own repository: 747 scenarios, 108 claims, including
766
853
  its archived history from before the structured format.
767
854
 
@@ -851,7 +938,7 @@ published 0.14.1:
851
938
 
852
939
  - **A pack keeps a generated matrix generated.** Installing a pack wrote
853
940
  matrix rows and turned the project back into a hand-kept matrix; `matrix
854
- --migrate` then wrote 47 placeholder sections into `spec.md` titled after
941
+ --migrate` then wrote 47 placeholder sections into `spec.md` titled after
855
942
  use cases. Now each requirement's use case, command, aggregate, event and
856
943
  context go into the `csda:trace` of its section — the pack's capability
857
944
  spec, or a new `spec.md` section carrying the pack's own description — and
@@ -866,7 +953,7 @@ published 0.14.1:
866
953
  scenario: a requirement with two scenarios ran two paid agent sessions on
867
954
  the same branch.
868
955
  - **`setup_cmd`** prepares each fresh worktree before the agent (`harness
869
- init` proposes `npm ci` / `pnpm install` / `yarn install` from the
956
+ init` proposes `npm ci` / `pnpm install` / `yarn install` from the
870
957
  lockfile), so the agent can run the tests it writes and `check` no longer
871
958
  needs `npm ci` in `test_cmd`. The generated prompt prefix teaches linking by
872
959
  mention instead of "the test named in the matrix".
@@ -889,7 +976,7 @@ domain packs in a specops repository:
889
976
  lines, and the `''` / `\"` escapes inside quotes. A pack generated with
890
977
  PyYAML's defaults failed with "Unexpected YAML token".
891
978
  - **"tag work" is not a vague step.** The vague-step check matched the bare
892
- word *work*; it now flags verdicts ("it works", "should work"), not trade
979
+ word _work_; it now flags verdicts ("it works", "should work"), not trade
893
980
  terms.
894
981
  - **A requirement can have several scenarios.** On a generated matrix a
895
982
  requirement with two scenarios has two rows, and the gate called it a
@@ -970,7 +1057,7 @@ Found by following the documentation step by step on the published 0.13.0:
970
1057
  published.
971
1058
  - **Diagrams render on every docs page.** A blank line inside an inlined SVG
972
1059
  ended Markdown's HTML block, so the rest of the diagram showed as a block of
973
- escaped markup on *Domain packs* and in *Specs that cannot lie*. Blank lines
1060
+ escaped markup on _Domain packs_ and in _Specs that cannot lie_. Blank lines
974
1061
  are dropped when a diagram is inlined, and a test fails on any page showing
975
1062
  diagram markup as text.
976
1063
  - **`mcp install --help` names the clients it supports.** It offered
@@ -1064,7 +1151,7 @@ Found by following the documentation step by step on the published 0.13.0:
1064
1151
  `completion`, `studio`, `onboard` — take it from 14 to 34 of 60 commands, and
1065
1152
  offline journeys for packs — `specops add/diff/sync/remove` against a local
1066
1153
  git remote with tags, `pack bundle` for an air-gapped install, `pack
1067
- init/lint/infer`, `expand` — to 43, and the change cycle (`new` → `archive`
1154
+ init/lint/infer`, `expand` — to 43, and the change cycle (`new` → `archive`
1068
1155
  → delivered with `done`), `change author` reverting an agent's write outside
1069
1156
  the change, `harness init/prompt/run/report` and `specops contribute` to 55.
1070
1157
 
@@ -1252,13 +1339,13 @@ Agent files generated by earlier versions are named `csda`; run
1252
1339
  short help and keep working. `adopt`'s next steps now teach `check`, `new`,
1253
1340
  `status` and `ci init`.
1254
1341
  - **`status` lists the queue itself.** One line per requirement — its title and
1255
- what it still needs — split into *Ready to close* and *To do*, capped at 12
1342
+ what it still needs — split into _Ready to close_ and _To do_, capped at 12
1256
1343
  per group. `Next` names a requirement (`specgate done REQ-003 --strict`)
1257
1344
  instead of answering `specgate plan`. `--json` gains a `requirements` array.
1258
1345
  `plan` leaves the daily help and keeps the full detail.
1259
1346
  - **`plan` no longer says "code & test exist" over a row with no code.** A
1260
- declared code path is optional; the heading now says *its declared test and
1261
- code exist*.
1347
+ declared code path is optional; the heading now says _its declared test and
1348
+ code exist_.
1262
1349
  - **The scenario rules are owed on delivery, like the files.** A Draft row's
1263
1350
  feature file is not held to `--strict-scenarios`, so a fresh `specgate new`
1264
1351
  does not turn CI red. The three rules that make a suite report a pass it
@@ -1323,7 +1410,7 @@ Agent files generated by earlier versions are named `csda`; run
1323
1410
  and `--from` repeats and accepts a directory, so a command shared by three
1324
1411
  files is proposed once.
1325
1412
 
1326
- `--llm` is *not* here: ADR-0014 defers it, and reopening that needs an ADR
1413
+ `--llm` is _not_ here: ADR-0014 defers it, and reopening that needs an ADR
1327
1414
  rather than a flag. Everything above stays a skeleton to review with every
1328
1415
  guess carrying its `TODO` — an inference that stops looking like a guess is
1329
1416
  the failure mode the ADR names. Closes #32.
@@ -1367,7 +1454,7 @@ Agent files generated by earlier versions are named `csda`; run
1367
1454
  runs in its own process and every one creates a worktree in the same
1368
1455
  repository; git writes `.git/worktrees/<name>/` incrementally, so a sibling
1369
1456
  read an entry that was half there and failed with `failed to read …
1370
- /commondir`. Worse, the failure was *attributed*: the run reported the
1457
+ /commondir`. Worse, the failure was _attributed_: the run reported the
1371
1458
  requirement as failed with "the agent produced no files", so a race in the
1372
1459
  harness read as the agent's fault.
1373
1460
 
@@ -1405,7 +1492,7 @@ Agent files generated by earlier versions are named `csda`; run
1405
1492
  [`spec-gate`](https://www.npmjs.com/package/spec-gate) normalises to exactly
1406
1493
  `specgate`, so the registry refuses the name to everyone and reports it as a
1407
1494
  credentials error. ADR-0024 had checked availability with `npm view specgate`
1408
- → 404, which says *not published* and never *creatable*; the
1495
+ → 404, which says _not published_ and never _creatable_; the
1409
1496
  [2026-09-01 addendum](docs/specs/adr/0024-the-tool-is-renamed-the-format-is-not.md)
1410
1497
  records both the decision and the bad check that led to it.
1411
1498
 
@@ -1447,7 +1534,7 @@ the one that finishes the rename past the layer where it had stopped.
1447
1534
  **The on-disk format is deliberately unchanged.** `csda:trace`, `csda:value`,
1448
1535
  `csda:allow-placeholders` and the `.csda/` directory keep their names. Those
1449
1536
  are not branding: they are a parsed format and a config directory that live
1450
- inside *user* repositories, and renaming them would be a silent breaking
1537
+ inside _user_ repositories, and renaming them would be a silent breaking
1451
1538
  change to every adopted project — surfacing as "requirement not found" rather
1452
1539
  than as "your marker prefix changed". Reading both prefixes is a real
1453
1540
  migration feature, not a find-and-replace, and it is not built here.
@@ -1462,7 +1549,7 @@ the one that finishes the rename past the layer where it had stopped.
1462
1549
  rebuilt in place and keep working.
1463
1550
 
1464
1551
  `docs/release-process.md` gains the one-time cutover: the exact `npm
1465
- deprecate` invocation for `create-spec-driven-app`, why the old package is
1552
+ deprecate` invocation for `create-spec-driven-app`, why the old package is
1466
1553
  deprecated and never unpublished (npm blocks reusing an unpublished name, and
1467
1554
  a pinned dependency would break for no gain), and the sequencing constraint —
1468
1555
  the rename and the release that publishes `specgate` are one event, because
@@ -1498,7 +1585,7 @@ The release that starts checking content instead of only paperwork. Every check
1498
1585
  until now answered "are these documents internally consistent?"; none answered
1499
1586
  "does the code say what the spec says?". These do — for the narrow slice where
1500
1587
  that question has an honest answer. The reasoning, including what was
1501
- deliberately *not* built, is [ADR-0023](docs/specs/adr/0023-checking-content-gate-or-report.md).
1588
+ deliberately _not_ built, is [ADR-0023](docs/specs/adr/0023-checking-content-gate-or-report.md).
1502
1589
 
1503
1590
  ### Added
1504
1591
 
@@ -1510,7 +1597,7 @@ deliberately *not* built, is [ADR-0023](docs/specs/adr/0023-checking-content-gat
1510
1597
  the H13 mistake. These two rules are what a regex can assert honestly.
1511
1598
 
1512
1599
  The point is upstream of any code checking: `- Max 5 failed attempts per hour
1513
- per user` is not something a machine can hold code to. RFC 2119 detection also
1600
+ per user` is not something a machine can hold code to. RFC 2119 detection also
1514
1601
  stops being duplicated — `DeltaSpec` enforced it for requirements inside a
1515
1602
  change while a capability spec at rest was never checked; both now read one
1516
1603
  definition.
@@ -1523,7 +1610,7 @@ deliberately *not* built, is [ADR-0023](docs/specs/adr/0023-checking-content-gat
1523
1610
  Opt-in, and that was measured rather than assumed: the first version ran
1524
1611
  unconditionally on the theory that a missing path has no legitimate reading,
1525
1612
  and the test suite disproved it at once — a `Draft` or `In Dev` row routinely
1526
- names the file a requirement is *going to* land in. Planning ahead is not
1613
+ names the file a requirement is _going to_ land in. Planning ahead is not
1527
1614
  documentary drift.
1528
1615
 
1529
1616
  - **Declared-value drift in `csda report`.** Annotate a value on both sides —
@@ -1547,7 +1634,7 @@ deliberately *not* built, is [ADR-0023](docs/specs/adr/0023-checking-content-gat
1547
1634
 
1548
1635
  - **`csda change new <id> --from-value-drift <REQ-ID>:<value_id>`** turns a
1549
1636
  diverging value into a reviewable change. It writes a `## MODIFIED
1550
- Requirements` delta carrying the full requirement, with the structured
1637
+ Requirements` delta carrying the full requirement, with the structured
1551
1638
  `value_<id>` rewritten to the value the code declares.
1552
1639
 
1553
1640
  **The prose is left alone.** Turning "expires after 15 minutes" into "after
@@ -1563,7 +1650,7 @@ deliberately *not* built, is [ADR-0023](docs/specs/adr/0023-checking-content-gat
1563
1650
 
1564
1651
  ### Fixed
1565
1652
 
1566
- - **The gate approved an agent that wrote nothing (H19).** The gate runs *before*
1653
+ - **The gate approved an agent that wrote nothing (H19).** The gate runs _before_
1567
1654
  `csda done`, so at gate time the requirement is still `Draft` — and
1568
1655
  `--strict-tdd`'s "no `Test Artifact = TBD` past Draft" rule does not apply to a
1569
1656
  Draft row. `done` then moved the status to `Implemented` and nothing validated
@@ -1595,8 +1682,8 @@ deliberately *not* built, is [ADR-0023](docs/specs/adr/0023-checking-content-gat
1595
1682
 
1596
1683
  Worse than a red gate on day one: `csda harness run` on a new project **burned
1597
1684
  all three agent attempts** failing on something the agent neither caused nor
1598
- could fix. And it contradicted the README's L2 — *"a PR gate enforcing spec and
1599
- test coverage, ~1 hour"* — since the gate was red before the hour started.
1685
+ could fix. And it contradicted the README's L2 — _"a PR gate enforcing spec and
1686
+ test coverage, ~1 hour"_ — since the gate was red before the hour started.
1600
1687
 
1601
1688
  The placeholder row is gone, replaced by a comment pointing at
1602
1689
  `csda req add "<what the requirement does>"`, which writes the row in `spec.md`
@@ -1652,7 +1739,7 @@ deliberately *not* built, is [ADR-0023](docs/specs/adr/0023-checking-content-gat
1652
1739
  - **`specgate adopt` did not run at all.** `templates/adopt/spec.md.tpl` asks
1653
1740
  for `{{PROPOSED_REQUIREMENTS}}` and nothing supplied it, so the brownfield
1654
1741
  entry point died on `Missing variable 'PROPOSED_REQUIREMENTS' required by
1655
- template` for every repository.
1742
+ template` for every repository.
1656
1743
 
1657
1744
  Two parallel branches caused it. P6 taught `adopt` to seed one requirement per
1658
1745
  capability `onboard` reads off the layout, and added `--monorepo` and
@@ -1719,7 +1806,7 @@ deliberately *not* built, is [ADR-0023](docs/specs/adr/0023-checking-content-gat
1719
1806
  - **The landing page claimed 24 commands against a surface of 25.**
1720
1807
 
1721
1808
  - **CI had not run this repository's own gate since the rename.** The rename
1722
- commit changed the *references* to `bin/specgate.{ts,js}` in `ci.yml`,
1809
+ commit changed the _references_ to `bin/specgate.{ts,js}` in `ci.yml`,
1723
1810
  `CONTRIBUTING.md` and `AI_RULES.md` without renaming the file, so the step
1724
1811
  named "Validate this repository against its own spec gate" ran
1725
1812
  `node bin/specgate.js validate .` against a path that did not exist and every
@@ -1737,7 +1824,6 @@ deliberately *not* built, is [ADR-0023](docs/specs/adr/0023-checking-content-gat
1737
1824
  masked: the `adopt` regression above failed those files on every platform, so
1738
1825
  nothing distinguished "broken everywhere" from "broken on Windows".
1739
1826
 
1740
-
1741
1827
  ## [0.7.0] — 2026-08-23
1742
1828
 
1743
1829
  The release that closes the gate on itself. Every item below came from running
@@ -1754,7 +1840,7 @@ H16, all four measured before anything was written and reproduced after.
1754
1840
 
1755
1841
  - **`csda harness run --skip-not-ready`** skips a requirement an agent could not
1756
1842
  succeed at — no feature file, unmet dependencies, `Deprecated`, or `Needs
1757
- Clarification`. `csda plan --format json` now carries `ready` and `blockers[]`
1843
+ Clarification`. `csda plan --format json` now carries `ready` and `blockers[]`
1758
1844
  per requirement, each blocker with a fix. Default is to warn and run it
1759
1845
  anyway; an unrunnable scenario skips regardless, because an empty scenario
1760
1846
  passes and a green run over one proves nothing.
@@ -1762,7 +1848,7 @@ H16, all four measured before anything was written and reproduced after.
1762
1848
  - **`csda harness run --resume`** continues an interrupted run: it re-attaches to
1763
1849
  the branch and, when git still knows of one, to the worktree holding the
1764
1850
  agent's uncommitted work. Where it picks up is read from the prompt archive,
1765
- not the run ledger — the ledger is written when a run *finishes*, so an
1851
+ not the run ledger — the ledger is written when a run _finishes_, so an
1766
1852
  interrupted run leaves none.
1767
1853
 
1768
1854
  - **`csda harness run --budget-seconds` and `--max-requirements`** put a ceiling
@@ -1787,7 +1873,7 @@ H16, all four measured before anything was written and reproduced after.
1787
1873
 
1788
1874
  - **`csda harness report`** gains where attempts end, which requirements spend
1789
1875
  every attempt, a series over time, and `--mark-false-failure REQ-NNN --reason
1790
- "…"`. The real-failure rate reads `—` until somebody marks one: nothing
1876
+ "…"`. The real-failure rate reads `—` until somebody marks one: nothing
1791
1877
  recorded can tell a gate that was wrong from work that was.
1792
1878
 
1793
1879
  - **`depends_on`** on a pack's requirements. The harness cuts a dependent's
@@ -1837,7 +1923,7 @@ H16, all four measured before anything was written and reproduced after.
1837
1923
 
1838
1924
  - **`parseYamlLite` split inline sequences on every comma**, including the ones
1839
1925
  inside quotes, so `responsibilities: ["Invoice line items, totals, status,
1840
- aging"]` parsed as four items carrying stray quote characters.
1926
+ aging"]` parsed as four items carrying stray quote characters.
1841
1927
 
1842
1928
  ### Security
1843
1929
 
@@ -1892,9 +1978,9 @@ date.
1892
1978
  - **The scenarios shipped in the curated packs were never executed.** 27 of the
1893
1979
  28 scenarios under `packs/**` wrote their keywords in upper case —
1894
1980
  `GIVEN` / `WHEN` / `THEN` — and Gherkin keywords are case-sensitive. Cucumber
1895
- read those lines as the scenario's *description*, so the scenario existed with
1981
+ read those lines as the scenario's _description_, so the scenario existed with
1896
1982
  **zero steps**, and an empty scenario passes: `1 scenario (1 passed) · 0 steps
1897
- · exit 0`.
1983
+ · exit 0`.
1898
1984
 
1899
1985
  Every project seeded with `csda specops add` therefore inherited an acceptance
1900
1986
  criterion that approves anything, and a harness run over those requirements
@@ -1924,7 +2010,7 @@ date.
1924
2010
  first run already had.
1925
2011
 
1926
2012
  The attempt is now committed on the branch with a `wip(REQ-NNN): FAILED the
1927
- gate — do not merge as is` subject. The requirement stays `Draft`, because
2013
+ gate — do not merge as is` subject. The requirement stays `Draft`, because
1928
2014
  `csda done` never ran, so nothing about the matrix claims the work is good. A
1929
2015
  human reads it and decides; git just stops throwing it away. The report says
1930
2016
  whether the work was preserved, and distinguishes that from an agent that
@@ -1935,7 +2021,7 @@ date.
1935
2021
  a filter silently fails to apply — a runner config pinning its own paths will
1936
2022
  override the CLI argument — the gate rejects correct work and the failure is
1937
2023
  indistinguishable from broken code. It cost two agent runs to explain the
1938
- first time. The harness cannot know how many tests *should* run, but it can
2024
+ first time. The harness cannot know how many tests _should_ run, but it can
1939
2025
  notice a command that asked for one feature against output reporting many, and
1940
2026
  warn. A hint, not a verdict: a genuine failure must not be explained away.
1941
2027
 
@@ -1976,7 +2062,7 @@ date.
1976
2062
  version and path.
1977
2063
 
1978
2064
  Reported by a user whose `csda -v` kept printing 0.1.2 after installing "the
1979
- latest". The tool was right — it *was* 0.1.2, from a global install made
2065
+ latest". The tool was right — it _was_ 0.1.2, from a global install made
1980
2066
  months earlier. `npx create-spec-driven-app@latest` runs a temporary copy and
1981
2067
  never touches a global one, so the two answer different questions and nothing
1982
2068
  said so. Three minor versions behind, with no way to notice.
@@ -1986,8 +2072,7 @@ date.
1986
2072
  newest is not doctor's business, and a lookup would break the offline and
1987
2073
  air-gapped modes the tool promises.
1988
2074
 
1989
- - **Doctor's Node check read `>= 20`** for a release after the floor moved to
1990
- 22. It now reads the floor from `package.json` rather than repeating it — the
2075
+ - **Doctor's Node check read `>= 20`** for a release after the floor moved to 22. It now reads the floor from `package.json` rather than repeating it — the
1991
2076
  same drift the floor guard exists to prevent, in the one file the guard did
1992
2077
  not cover.
1993
2078
 
@@ -1996,7 +2081,7 @@ date.
1996
2081
  ### Fixed
1997
2082
 
1998
2083
  - **The gate could not run the scenario it was gating.** `test_cmd` was a fixed
1999
- string with no substitution, and the gate runs *before* `csda done` — so the
2084
+ string with no substitution, and the gate runs _before_ `csda done` — so the
2000
2085
  requirement is still Draft and `validate --strict-tdd` does not demand its
2001
2086
  test either. Between them, `harness run` could mark a requirement Implemented
2002
2087
  with its scenario never executed.
@@ -2011,7 +2096,7 @@ date.
2011
2096
  With that, the same no-op agent fails at the requirement's own scenario.
2012
2097
 
2013
2098
  - **The harness blocked its own second run.** It archived each prompt into the
2014
- *project* directory, which left untracked files behind — and the harness
2099
+ _project_ directory, which left untracked files behind — and the harness
2015
2100
  refuses to start on a dirty tree. The archive now goes in the worktree, where
2016
2101
  `git add -A` commits it with the work, so the prompt arrives in the branch
2017
2102
  under review. That is what an audit copy was for.
@@ -2107,7 +2192,6 @@ date.
2107
2192
  migrating is the shape that never worked, and `pack lint` now names exactly
2108
2193
  what is wrong with it.
2109
2194
 
2110
-
2111
2195
  - **The CLI is called `csda` in every place it is a command.** The package
2112
2196
  ships two binaries — `create-spec-driven-app` and the `csda` alias — and the
2113
2197
  two were used interchangeably, so the same command appeared under different
@@ -2183,7 +2267,7 @@ date.
2183
2267
  `schema_version` and `.specops.lock`'s `specops_version` were both written by
2184
2268
  the CLI and read by nothing, so a file from a newer version was accepted and
2185
2269
  then misread field by field. Both now fail up front, naming the versions and
2186
- the upgrade command. Older files still load — only *newer than this CLI* is
2270
+ the upgrade command. Older files still load — only _newer than this CLI_ is
2187
2271
  refused.
2188
2272
 
2189
2273
  - **`SECURITY.md`, `MAINTAINERS.md` and `CODEOWNERS`**, with private
@@ -2287,7 +2371,7 @@ date.
2287
2371
  runner. The workflow needed QEMU alongside buildx to cross-build.
2288
2372
 
2289
2373
  The 0.2.0 image tag could not be rebuilt in place: re-running a workflow
2290
- against an old tag checks out the workflow *as it was at that tag*, which did
2374
+ against an old tag checks out the workflow _as it was at that tag_, which did
2291
2375
  not yet have the fix. Hence a patch release rather than moving a published
2292
2376
  tag.
2293
2377
 
@@ -2323,7 +2407,7 @@ and brownfield onboarding have all landed since.
2323
2407
  ### Added
2324
2408
 
2325
2409
  - **Change lifecycle** — `csda change new | list | show | status | validate |
2326
- archive`. Modify a spec that already shipped through a reviewable delta.
2410
+ archive`. Modify a spec that already shipped through a reviewable delta.
2327
2411
  Archiving merges it into the spec tree, writes the traceability rows and
2328
2412
  materialises the feature files.
2329
2413
  - **`csda change instructions <artifact>`** — the single context engine.