@rsaglobaltech/specgate 0.8.1

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 (494) hide show
  1. package/CHANGELOG.md +1016 -0
  2. package/README.md +148 -0
  3. package/bin/specgate.js +2 -0
  4. package/bin/specgate.ts +383 -0
  5. package/dist/bin/specgate.js +342 -0
  6. package/dist/bin/specgate.js.map +1 -0
  7. package/dist/packages/core/src/application/AddRequirementUseCase.js +24 -0
  8. package/dist/packages/core/src/application/AddRequirementUseCase.js.map +1 -0
  9. package/dist/packages/core/src/application/ArchiveChangeUseCase.js +185 -0
  10. package/dist/packages/core/src/application/ArchiveChangeUseCase.js.map +1 -0
  11. package/dist/packages/core/src/application/CheckAgainstLockUseCase.js +134 -0
  12. package/dist/packages/core/src/application/CheckAgainstLockUseCase.js.map +1 -0
  13. package/dist/packages/core/src/application/GenerateAgentPromptUseCase.js +25 -0
  14. package/dist/packages/core/src/application/GenerateAgentPromptUseCase.js.map +1 -0
  15. package/dist/packages/core/src/application/GeneratePlanUseCase.js +135 -0
  16. package/dist/packages/core/src/application/GeneratePlanUseCase.js.map +1 -0
  17. package/dist/packages/core/src/application/LinkRequirementUseCase.js +25 -0
  18. package/dist/packages/core/src/application/LinkRequirementUseCase.js.map +1 -0
  19. package/dist/packages/core/src/application/RemovePackUseCase.js +28 -0
  20. package/dist/packages/core/src/application/RemovePackUseCase.js.map +1 -0
  21. package/dist/packages/core/src/application/UpdateRequirementStatusUseCase.js +37 -0
  22. package/dist/packages/core/src/application/UpdateRequirementStatusUseCase.js.map +1 -0
  23. package/dist/packages/core/src/application/ValidateChangeUseCase.js +86 -0
  24. package/dist/packages/core/src/application/ValidateChangeUseCase.js.map +1 -0
  25. package/dist/packages/core/src/application/ValidateProjectUseCase.js +101 -0
  26. package/dist/packages/core/src/application/ValidateProjectUseCase.js.map +1 -0
  27. package/dist/packages/core/src/application/ports/IDomainPackRepository.js +3 -0
  28. package/dist/packages/core/src/application/ports/IDomainPackRepository.js.map +1 -0
  29. package/dist/packages/core/src/application/ports/IHarnessConfigRepository.js +3 -0
  30. package/dist/packages/core/src/application/ports/IHarnessConfigRepository.js.map +1 -0
  31. package/dist/packages/core/src/application/ports/ILockfileRepository.js +3 -0
  32. package/dist/packages/core/src/application/ports/ILockfileRepository.js.map +1 -0
  33. package/dist/packages/core/src/application/ports/IManifestRepository.js +3 -0
  34. package/dist/packages/core/src/application/ports/IManifestRepository.js.map +1 -0
  35. package/dist/packages/core/src/application/ports/IProjectRepository.js +3 -0
  36. package/dist/packages/core/src/application/ports/IProjectRepository.js.map +1 -0
  37. package/dist/packages/core/src/application/ports/IRequirementGraphRepository.js +3 -0
  38. package/dist/packages/core/src/application/ports/IRequirementGraphRepository.js.map +1 -0
  39. package/dist/packages/core/src/application/ports/ITraceabilityRepository.js +3 -0
  40. package/dist/packages/core/src/application/ports/ITraceabilityRepository.js.map +1 -0
  41. package/dist/packages/core/src/domain/AgentPrompt.js +79 -0
  42. package/dist/packages/core/src/domain/AgentPrompt.js.map +1 -0
  43. package/dist/packages/core/src/domain/ArchivePlan.js +26 -0
  44. package/dist/packages/core/src/domain/ArchivePlan.js.map +1 -0
  45. package/dist/packages/core/src/domain/AuthoringScope.js +48 -0
  46. package/dist/packages/core/src/domain/AuthoringScope.js.map +1 -0
  47. package/dist/packages/core/src/domain/ChangeTemplates.js +133 -0
  48. package/dist/packages/core/src/domain/ChangeTemplates.js.map +1 -0
  49. package/dist/packages/core/src/domain/CucumberMessages.js +256 -0
  50. package/dist/packages/core/src/domain/CucumberMessages.js.map +1 -0
  51. package/dist/packages/core/src/domain/DeclaredArtifacts.js +117 -0
  52. package/dist/packages/core/src/domain/DeclaredArtifacts.js.map +1 -0
  53. package/dist/packages/core/src/domain/DeltaSpec.js +219 -0
  54. package/dist/packages/core/src/domain/DeltaSpec.js.map +1 -0
  55. package/dist/packages/core/src/domain/Diagnostic.js +75 -0
  56. package/dist/packages/core/src/domain/Diagnostic.js.map +1 -0
  57. package/dist/packages/core/src/domain/DomainPack.js +62 -0
  58. package/dist/packages/core/src/domain/DomainPack.js.map +1 -0
  59. package/dist/packages/core/src/domain/EmptyAttempt.js +60 -0
  60. package/dist/packages/core/src/domain/EmptyAttempt.js.map +1 -0
  61. package/dist/packages/core/src/domain/FileChangeSet.js +37 -0
  62. package/dist/packages/core/src/domain/FileChangeSet.js.map +1 -0
  63. package/dist/packages/core/src/domain/Gherkin.js +272 -0
  64. package/dist/packages/core/src/domain/Gherkin.js.map +1 -0
  65. package/dist/packages/core/src/domain/GherkinDialects.js +97 -0
  66. package/dist/packages/core/src/domain/GherkinDialects.js.map +1 -0
  67. package/dist/packages/core/src/domain/GherkinQuality.js +160 -0
  68. package/dist/packages/core/src/domain/GherkinQuality.js.map +1 -0
  69. package/dist/packages/core/src/domain/GherkinTags.js +119 -0
  70. package/dist/packages/core/src/domain/GherkinTags.js.map +1 -0
  71. package/dist/packages/core/src/domain/GitSafety.js +77 -0
  72. package/dist/packages/core/src/domain/GitSafety.js.map +1 -0
  73. package/dist/packages/core/src/domain/HarnessConfig.js +58 -0
  74. package/dist/packages/core/src/domain/HarnessConfig.js.map +1 -0
  75. package/dist/packages/core/src/domain/HarnessReport.js +162 -0
  76. package/dist/packages/core/src/domain/HarnessReport.js.map +1 -0
  77. package/dist/packages/core/src/domain/HarnessRun.js +154 -0
  78. package/dist/packages/core/src/domain/HarnessRun.js.map +1 -0
  79. package/dist/packages/core/src/domain/InboundChange.js +127 -0
  80. package/dist/packages/core/src/domain/InboundChange.js.map +1 -0
  81. package/dist/packages/core/src/domain/Language.js +112 -0
  82. package/dist/packages/core/src/domain/Language.js.map +1 -0
  83. package/dist/packages/core/src/domain/Lockfile.js +64 -0
  84. package/dist/packages/core/src/domain/Lockfile.js.map +1 -0
  85. package/dist/packages/core/src/domain/PackContribution.js +106 -0
  86. package/dist/packages/core/src/domain/PackContribution.js.map +1 -0
  87. package/dist/packages/core/src/domain/PackDelta.js +298 -0
  88. package/dist/packages/core/src/domain/PackDelta.js.map +1 -0
  89. package/dist/packages/core/src/domain/PackSpec.js +481 -0
  90. package/dist/packages/core/src/domain/PackSpec.js.map +1 -0
  91. package/dist/packages/core/src/domain/ProfileMatch.js +87 -0
  92. package/dist/packages/core/src/domain/ProfileMatch.js.map +1 -0
  93. package/dist/packages/core/src/domain/Reconciliation.js +72 -0
  94. package/dist/packages/core/src/domain/Reconciliation.js.map +1 -0
  95. package/dist/packages/core/src/domain/RequirementGraph.js +197 -0
  96. package/dist/packages/core/src/domain/RequirementGraph.js.map +1 -0
  97. package/dist/packages/core/src/domain/RequirementPlan.js +85 -0
  98. package/dist/packages/core/src/domain/RequirementPlan.js.map +1 -0
  99. package/dist/packages/core/src/domain/RequirementReadiness.js +115 -0
  100. package/dist/packages/core/src/domain/RequirementReadiness.js.map +1 -0
  101. package/dist/packages/core/src/domain/RequirementSyntax.js +91 -0
  102. package/dist/packages/core/src/domain/RequirementSyntax.js.map +1 -0
  103. package/dist/packages/core/src/domain/ResumeState.js +115 -0
  104. package/dist/packages/core/src/domain/ResumeState.js.map +1 -0
  105. package/dist/packages/core/src/domain/RunBudget.js +103 -0
  106. package/dist/packages/core/src/domain/RunBudget.js.map +1 -0
  107. package/dist/packages/core/src/domain/SpecDiff.js +48 -0
  108. package/dist/packages/core/src/domain/SpecDiff.js.map +1 -0
  109. package/dist/packages/core/src/domain/SpecParser.js +406 -0
  110. package/dist/packages/core/src/domain/SpecParser.js.map +1 -0
  111. package/dist/packages/core/src/domain/SpecopsManifest.js +90 -0
  112. package/dist/packages/core/src/domain/SpecopsManifest.js.map +1 -0
  113. package/dist/packages/core/src/domain/TraceabilityFormat.js +317 -0
  114. package/dist/packages/core/src/domain/TraceabilityFormat.js.map +1 -0
  115. package/dist/packages/core/src/domain/TraceabilityMatrix.js +200 -0
  116. package/dist/packages/core/src/domain/TraceabilityMatrix.js.map +1 -0
  117. package/dist/packages/core/src/domain/TraceabilityMerge.js +180 -0
  118. package/dist/packages/core/src/domain/TraceabilityMerge.js.map +1 -0
  119. package/dist/packages/core/src/domain/ValidationReport.js +53 -0
  120. package/dist/packages/core/src/domain/ValidationReport.js.map +1 -0
  121. package/dist/packages/core/src/domain/ValueAnnotations.js +138 -0
  122. package/dist/packages/core/src/domain/ValueAnnotations.js.map +1 -0
  123. package/dist/packages/core/src/domain/WriteScope.js +155 -0
  124. package/dist/packages/core/src/domain/WriteScope.js.map +1 -0
  125. package/dist/packages/core/src/domain/YamlLite.js +226 -0
  126. package/dist/packages/core/src/domain/YamlLite.js.map +1 -0
  127. package/dist/packages/core/src/index.js +120 -0
  128. package/dist/packages/core/src/index.js.map +1 -0
  129. package/dist/packages/core/src/infrastructure/ChangeWorkspace.js +276 -0
  130. package/dist/packages/core/src/infrastructure/ChangeWorkspace.js.map +1 -0
  131. package/dist/packages/core/src/infrastructure/ConsoleReporter.js +19 -0
  132. package/dist/packages/core/src/infrastructure/ConsoleReporter.js.map +1 -0
  133. package/dist/packages/core/src/infrastructure/DirectorySnapshot.js +106 -0
  134. package/dist/packages/core/src/infrastructure/DirectorySnapshot.js.map +1 -0
  135. package/dist/packages/core/src/infrastructure/DiskDomainPackRepository.js +57 -0
  136. package/dist/packages/core/src/infrastructure/DiskDomainPackRepository.js.map +1 -0
  137. package/dist/packages/core/src/infrastructure/DiskHarnessConfigRepository.js +58 -0
  138. package/dist/packages/core/src/infrastructure/DiskHarnessConfigRepository.js.map +1 -0
  139. package/dist/packages/core/src/infrastructure/DiskLanguageRepository.js +69 -0
  140. package/dist/packages/core/src/infrastructure/DiskLanguageRepository.js.map +1 -0
  141. package/dist/packages/core/src/infrastructure/DiskLockfileRepository.js +64 -0
  142. package/dist/packages/core/src/infrastructure/DiskLockfileRepository.js.map +1 -0
  143. package/dist/packages/core/src/infrastructure/DiskManifestRepository.js +88 -0
  144. package/dist/packages/core/src/infrastructure/DiskManifestRepository.js.map +1 -0
  145. package/dist/packages/core/src/infrastructure/DiskPackDeltaRepository.js +138 -0
  146. package/dist/packages/core/src/infrastructure/DiskPackDeltaRepository.js.map +1 -0
  147. package/dist/packages/core/src/infrastructure/DiskPackRepository.js +130 -0
  148. package/dist/packages/core/src/infrastructure/DiskPackRepository.js.map +1 -0
  149. package/dist/packages/core/src/infrastructure/DiskProjectRepository.js +127 -0
  150. package/dist/packages/core/src/infrastructure/DiskProjectRepository.js.map +1 -0
  151. package/dist/packages/core/src/infrastructure/DiskRequirementGraphRepository.js +124 -0
  152. package/dist/packages/core/src/infrastructure/DiskRequirementGraphRepository.js.map +1 -0
  153. package/dist/packages/core/src/infrastructure/DiskTraceabilityRepository.js +53 -0
  154. package/dist/packages/core/src/infrastructure/DiskTraceabilityRepository.js.map +1 -0
  155. package/dist/packages/core/src/infrastructure/GitContributionStager.js +99 -0
  156. package/dist/packages/core/src/infrastructure/GitContributionStager.js.map +1 -0
  157. package/dist/packages/core/src/infrastructure/GitMergeDriver.js +103 -0
  158. package/dist/packages/core/src/infrastructure/GitMergeDriver.js.map +1 -0
  159. package/dist/packages/core/src/infrastructure/HarnessConfigFile.js +348 -0
  160. package/dist/packages/core/src/infrastructure/HarnessConfigFile.js.map +1 -0
  161. package/dist/packages/core/src/infrastructure/PackChangeDeposit.js +106 -0
  162. package/dist/packages/core/src/infrastructure/PackChangeDeposit.js.map +1 -0
  163. package/dist/packages/core/src/infrastructure/RemotePackResolver.js +181 -0
  164. package/dist/packages/core/src/infrastructure/RemotePackResolver.js.map +1 -0
  165. package/dist/packages/core/src/infrastructure/SpecopsConfigFile.js +94 -0
  166. package/dist/packages/core/src/infrastructure/SpecopsConfigFile.js.map +1 -0
  167. package/dist/packages/core/test/unit/authoring-scope.test.js +102 -0
  168. package/dist/packages/core/test/unit/authoring-scope.test.js.map +1 -0
  169. package/dist/packages/core/test/unit/change-templates.test.js +96 -0
  170. package/dist/packages/core/test/unit/change-templates.test.js.map +1 -0
  171. package/dist/packages/core/test/unit/cucumber-messages.test.js +232 -0
  172. package/dist/packages/core/test/unit/cucumber-messages.test.js.map +1 -0
  173. package/dist/packages/core/test/unit/declared-artifacts.test.js +124 -0
  174. package/dist/packages/core/test/unit/declared-artifacts.test.js.map +1 -0
  175. package/dist/packages/core/test/unit/empty-attempt.test.js +79 -0
  176. package/dist/packages/core/test/unit/empty-attempt.test.js.map +1 -0
  177. package/dist/packages/core/test/unit/gherkin-dialects.test.js +115 -0
  178. package/dist/packages/core/test/unit/gherkin-dialects.test.js.map +1 -0
  179. package/dist/packages/core/test/unit/gherkin-keyword-case.test.js +110 -0
  180. package/dist/packages/core/test/unit/gherkin-keyword-case.test.js.map +1 -0
  181. package/dist/packages/core/test/unit/gherkin-quality.test.js +151 -0
  182. package/dist/packages/core/test/unit/gherkin-quality.test.js.map +1 -0
  183. package/dist/packages/core/test/unit/gherkin-tags.test.js +127 -0
  184. package/dist/packages/core/test/unit/gherkin-tags.test.js.map +1 -0
  185. package/dist/packages/core/test/unit/git-safety.test.js +104 -0
  186. package/dist/packages/core/test/unit/git-safety.test.js.map +1 -0
  187. package/dist/packages/core/test/unit/harness-report.test.js +192 -0
  188. package/dist/packages/core/test/unit/harness-report.test.js.map +1 -0
  189. package/dist/packages/core/test/unit/harness-roles.test.js +86 -0
  190. package/dist/packages/core/test/unit/harness-roles.test.js.map +1 -0
  191. package/dist/packages/core/test/unit/inbound-change.test.js +145 -0
  192. package/dist/packages/core/test/unit/inbound-change.test.js.map +1 -0
  193. package/dist/packages/core/test/unit/matrix-dependencies.test.js +100 -0
  194. package/dist/packages/core/test/unit/matrix-dependencies.test.js.map +1 -0
  195. package/dist/packages/core/test/unit/profile-match.test.js +115 -0
  196. package/dist/packages/core/test/unit/profile-match.test.js.map +1 -0
  197. package/dist/packages/core/test/unit/reconciliation.test.js +112 -0
  198. package/dist/packages/core/test/unit/reconciliation.test.js.map +1 -0
  199. package/dist/packages/core/test/unit/requirement-readiness.test.js +161 -0
  200. package/dist/packages/core/test/unit/requirement-readiness.test.js.map +1 -0
  201. package/dist/packages/core/test/unit/resume-state.test.js +124 -0
  202. package/dist/packages/core/test/unit/resume-state.test.js.map +1 -0
  203. package/dist/packages/core/test/unit/run-budget.test.js +113 -0
  204. package/dist/packages/core/test/unit/run-budget.test.js.map +1 -0
  205. package/dist/packages/core/test/unit/traceability-merge.test.js +159 -0
  206. package/dist/packages/core/test/unit/traceability-merge.test.js.map +1 -0
  207. package/dist/packages/core/test/unit/validate-project.test.js +156 -0
  208. package/dist/packages/core/test/unit/validate-project.test.js.map +1 -0
  209. package/dist/packages/core/test/unit/value-annotations.test.js +149 -0
  210. package/dist/packages/core/test/unit/value-annotations.test.js.map +1 -0
  211. package/dist/packages/core/test/unit/write-scope.test.js +165 -0
  212. package/dist/packages/core/test/unit/write-scope.test.js.map +1 -0
  213. package/dist/packages/core/test/unit/yaml-lite.test.js +78 -0
  214. package/dist/packages/core/test/unit/yaml-lite.test.js.map +1 -0
  215. package/dist/scripts/adopt_project.js +11 -0
  216. package/dist/scripts/adopt_project.js.map +1 -0
  217. package/dist/scripts/agents/commands.js +100 -0
  218. package/dist/scripts/agents/commands.js.map +1 -0
  219. package/dist/scripts/agents/init.js +482 -0
  220. package/dist/scripts/agents/init.js.map +1 -0
  221. package/dist/scripts/alm/cli.js +154 -0
  222. package/dist/scripts/alm/cli.js.map +1 -0
  223. package/dist/scripts/alm/clients.js +30 -0
  224. package/dist/scripts/alm/clients.js.map +1 -0
  225. package/dist/scripts/alm/core.js +258 -0
  226. package/dist/scripts/alm/core.js.map +1 -0
  227. package/dist/scripts/alm/port.js +116 -0
  228. package/dist/scripts/alm/port.js.map +1 -0
  229. package/dist/scripts/alm/providers/azure.js +79 -0
  230. package/dist/scripts/alm/providers/azure.js.map +1 -0
  231. package/dist/scripts/alm/providers/github.js +124 -0
  232. package/dist/scripts/alm/providers/github.js.map +1 -0
  233. package/dist/scripts/alm/providers/http-client.js +47 -0
  234. package/dist/scripts/alm/providers/http-client.js.map +1 -0
  235. package/dist/scripts/alm/providers/index.js +107 -0
  236. package/dist/scripts/alm/providers/index.js.map +1 -0
  237. package/dist/scripts/alm/providers/jira.js +129 -0
  238. package/dist/scripts/alm/providers/jira.js.map +1 -0
  239. package/dist/scripts/bundle_pack.js +10 -0
  240. package/dist/scripts/bundle_pack.js.map +1 -0
  241. package/dist/scripts/change/archive.js +68 -0
  242. package/dist/scripts/change/archive.js.map +1 -0
  243. package/dist/scripts/change/artifacts.js +143 -0
  244. package/dist/scripts/change/artifacts.js.map +1 -0
  245. package/dist/scripts/change/cli.js +39 -0
  246. package/dist/scripts/change/cli.js.map +1 -0
  247. package/dist/scripts/change/delta.js +20 -0
  248. package/dist/scripts/change/delta.js.map +1 -0
  249. package/dist/scripts/change/instructions.js +339 -0
  250. package/dist/scripts/change/instructions.js.map +1 -0
  251. package/dist/scripts/ci_init.js +12 -0
  252. package/dist/scripts/ci_init.js.map +1 -0
  253. package/dist/scripts/cli/commands/alm/PullCommand.js +238 -0
  254. package/dist/scripts/cli/commands/alm/PullCommand.js.map +1 -0
  255. package/dist/scripts/cli/commands/change/ChangeCommand.js +867 -0
  256. package/dist/scripts/cli/commands/change/ChangeCommand.js.map +1 -0
  257. package/dist/scripts/cli/commands/config/CiInitCommand.js +144 -0
  258. package/dist/scripts/cli/commands/config/CiInitCommand.js.map +1 -0
  259. package/dist/scripts/cli/commands/config/CompletionCommand.js +160 -0
  260. package/dist/scripts/cli/commands/config/CompletionCommand.js.map +1 -0
  261. package/dist/scripts/cli/commands/config/ConfigInitCommand.js +108 -0
  262. package/dist/scripts/cli/commands/config/ConfigInitCommand.js.map +1 -0
  263. package/dist/scripts/cli/commands/config/ConfigSetCommand.js +166 -0
  264. package/dist/scripts/cli/commands/config/ConfigSetCommand.js.map +1 -0
  265. package/dist/scripts/cli/commands/config/GenAgentContractCommand.js +212 -0
  266. package/dist/scripts/cli/commands/config/GenAgentContractCommand.js.map +1 -0
  267. package/dist/scripts/cli/commands/harness/RunCommand.js +1922 -0
  268. package/dist/scripts/cli/commands/harness/RunCommand.js.map +1 -0
  269. package/dist/scripts/cli/commands/mcp/McpInstallCommand.js +114 -0
  270. package/dist/scripts/cli/commands/mcp/McpInstallCommand.js.map +1 -0
  271. package/dist/scripts/cli/commands/mcp/index.js +29 -0
  272. package/dist/scripts/cli/commands/mcp/index.js.map +1 -0
  273. package/dist/scripts/cli/commands/pack/BundlePackCommand.js +59 -0
  274. package/dist/scripts/cli/commands/pack/BundlePackCommand.js.map +1 -0
  275. package/dist/scripts/cli/commands/pack/ExpandDomainPackCommand.js +559 -0
  276. package/dist/scripts/cli/commands/pack/ExpandDomainPackCommand.js.map +1 -0
  277. package/dist/scripts/cli/commands/pack/InferPackCommand.js +304 -0
  278. package/dist/scripts/cli/commands/pack/InferPackCommand.js.map +1 -0
  279. package/dist/scripts/cli/commands/pack/InitPackCommand.js +368 -0
  280. package/dist/scripts/cli/commands/pack/InitPackCommand.js.map +1 -0
  281. package/dist/scripts/cli/commands/pack/LintPackCommand.js +631 -0
  282. package/dist/scripts/cli/commands/pack/LintPackCommand.js.map +1 -0
  283. package/dist/scripts/cli/commands/pack/pack-args.js +83 -0
  284. package/dist/scripts/cli/commands/pack/pack-args.js.map +1 -0
  285. package/dist/scripts/cli/commands/project/AdoptCommand.js +414 -0
  286. package/dist/scripts/cli/commands/project/AdoptCommand.js.map +1 -0
  287. package/dist/scripts/cli/commands/project/InitFromPackCommand.js +188 -0
  288. package/dist/scripts/cli/commands/project/InitFromPackCommand.js.map +1 -0
  289. package/dist/scripts/cli/commands/project/InitProjectCommand.js +791 -0
  290. package/dist/scripts/cli/commands/project/InitProjectCommand.js.map +1 -0
  291. package/dist/scripts/cli/commands/project/OnboardCommand.js +655 -0
  292. package/dist/scripts/cli/commands/project/OnboardCommand.js.map +1 -0
  293. package/dist/scripts/cli/commands/project/UpdateCommand.js +206 -0
  294. package/dist/scripts/cli/commands/project/UpdateCommand.js.map +1 -0
  295. package/dist/scripts/cli/commands/project/WizardCommand.js +166 -0
  296. package/dist/scripts/cli/commands/project/WizardCommand.js.map +1 -0
  297. package/dist/scripts/cli/commands/quality/DoctorCommand.js +553 -0
  298. package/dist/scripts/cli/commands/quality/DoctorCommand.js.map +1 -0
  299. package/dist/scripts/cli/commands/quality/FixCommand.js +201 -0
  300. package/dist/scripts/cli/commands/quality/FixCommand.js.map +1 -0
  301. package/dist/scripts/cli/commands/quality/LicenseCheckCommand.js +187 -0
  302. package/dist/scripts/cli/commands/quality/LicenseCheckCommand.js.map +1 -0
  303. package/dist/scripts/cli/commands/quality/ReportCommand.js +557 -0
  304. package/dist/scripts/cli/commands/quality/ReportCommand.js.map +1 -0
  305. package/dist/scripts/cli/commands/quality/ValidateSpecsCommand.js +764 -0
  306. package/dist/scripts/cli/commands/quality/ValidateSpecsCommand.js.map +1 -0
  307. package/dist/scripts/cli/commands/spec/DoneCommand.js +116 -0
  308. package/dist/scripts/cli/commands/spec/DoneCommand.js.map +1 -0
  309. package/dist/scripts/cli/commands/spec/PlanCommand.js +397 -0
  310. package/dist/scripts/cli/commands/spec/PlanCommand.js.map +1 -0
  311. package/dist/scripts/cli/commands/spec/ReqCommand.js +303 -0
  312. package/dist/scripts/cli/commands/spec/ReqCommand.js.map +1 -0
  313. package/dist/scripts/cli/commands/spec/StatusCommand.js +206 -0
  314. package/dist/scripts/cli/commands/spec/StatusCommand.js.map +1 -0
  315. package/dist/scripts/cli/commands/spec/StudioCommand.js +241 -0
  316. package/dist/scripts/cli/commands/spec/StudioCommand.js.map +1 -0
  317. package/dist/scripts/cli/commands/specops/ContributeCommand.js +313 -0
  318. package/dist/scripts/cli/commands/specops/ContributeCommand.js.map +1 -0
  319. package/dist/scripts/cli/commands/specops/DiffCommand.js +394 -0
  320. package/dist/scripts/cli/commands/specops/DiffCommand.js.map +1 -0
  321. package/dist/scripts/cli/commands/specops/SyncCommand.js +380 -0
  322. package/dist/scripts/cli/commands/specops/SyncCommand.js.map +1 -0
  323. package/dist/scripts/completion.js +24 -0
  324. package/dist/scripts/completion.js.map +1 -0
  325. package/dist/scripts/config_init.js +12 -0
  326. package/dist/scripts/config_init.js.map +1 -0
  327. package/dist/scripts/config_set.js +20 -0
  328. package/dist/scripts/config_set.js.map +1 -0
  329. package/dist/scripts/docs/blocks.js +137 -0
  330. package/dist/scripts/docs/blocks.js.map +1 -0
  331. package/dist/scripts/docs/build-site.js +425 -0
  332. package/dist/scripts/docs/build-site.js.map +1 -0
  333. package/dist/scripts/docs/nav.js +198 -0
  334. package/dist/scripts/docs/nav.js.map +1 -0
  335. package/dist/scripts/docs/record-terminal.js +477 -0
  336. package/dist/scripts/docs/record-terminal.js.map +1 -0
  337. package/dist/scripts/docs/terminal-storyboard.js +121 -0
  338. package/dist/scripts/docs/terminal-storyboard.js.map +1 -0
  339. package/dist/scripts/doctor.js +14 -0
  340. package/dist/scripts/doctor.js.map +1 -0
  341. package/dist/scripts/done.js +17 -0
  342. package/dist/scripts/done.js.map +1 -0
  343. package/dist/scripts/expand_domain_pack.js +18 -0
  344. package/dist/scripts/expand_domain_pack.js.map +1 -0
  345. package/dist/scripts/fix.js +12 -0
  346. package/dist/scripts/fix.js.map +1 -0
  347. package/dist/scripts/gen_agent_contract.js +14 -0
  348. package/dist/scripts/gen_agent_contract.js.map +1 -0
  349. package/dist/scripts/gen_mcp_tools.js +264 -0
  350. package/dist/scripts/gen_mcp_tools.js.map +1 -0
  351. package/dist/scripts/harness/init.js +358 -0
  352. package/dist/scripts/harness/init.js.map +1 -0
  353. package/dist/scripts/harness/prompt.js +18 -0
  354. package/dist/scripts/harness/prompt.js.map +1 -0
  355. package/dist/scripts/harness/report.js +323 -0
  356. package/dist/scripts/harness/report.js.map +1 -0
  357. package/dist/scripts/harness/run.js +33 -0
  358. package/dist/scripts/harness/run.js.map +1 -0
  359. package/dist/scripts/infer_pack.js +17 -0
  360. package/dist/scripts/infer_pack.js.map +1 -0
  361. package/dist/scripts/init_from_pack.js +16 -0
  362. package/dist/scripts/init_from_pack.js.map +1 -0
  363. package/dist/scripts/init_pack.js +16 -0
  364. package/dist/scripts/init_pack.js.map +1 -0
  365. package/dist/scripts/init_project.js +17 -0
  366. package/dist/scripts/init_project.js.map +1 -0
  367. package/dist/scripts/lib/agent.js +99 -0
  368. package/dist/scripts/lib/agent.js.map +1 -0
  369. package/dist/scripts/lib/capability-specs.js +80 -0
  370. package/dist/scripts/lib/capability-specs.js.map +1 -0
  371. package/dist/scripts/lib/command.js +17 -0
  372. package/dist/scripts/lib/command.js.map +1 -0
  373. package/dist/scripts/lib/diagnostics.js +62 -0
  374. package/dist/scripts/lib/diagnostics.js.map +1 -0
  375. package/dist/scripts/lib/monorepo-fanout.js +118 -0
  376. package/dist/scripts/lib/monorepo-fanout.js.map +1 -0
  377. package/dist/scripts/lib/placeholders.js +190 -0
  378. package/dist/scripts/lib/placeholders.js.map +1 -0
  379. package/dist/scripts/lib/project-root.js +124 -0
  380. package/dist/scripts/lib/project-root.js.map +1 -0
  381. package/dist/scripts/lib/requirement-graph.js +31 -0
  382. package/dist/scripts/lib/requirement-graph.js.map +1 -0
  383. package/dist/scripts/lib/surface.js +609 -0
  384. package/dist/scripts/lib/surface.js.map +1 -0
  385. package/dist/scripts/license_check.js +15 -0
  386. package/dist/scripts/license_check.js.map +1 -0
  387. package/dist/scripts/lint_pack.js +18 -0
  388. package/dist/scripts/lint_pack.js.map +1 -0
  389. package/dist/scripts/merge-traceability.js +106 -0
  390. package/dist/scripts/merge-traceability.js.map +1 -0
  391. package/dist/scripts/onboard.js +22 -0
  392. package/dist/scripts/onboard.js.map +1 -0
  393. package/dist/scripts/plan.js +17 -0
  394. package/dist/scripts/plan.js.map +1 -0
  395. package/dist/scripts/plugin/gate-hook.js +171 -0
  396. package/dist/scripts/plugin/gate-hook.js.map +1 -0
  397. package/dist/scripts/report.js +17 -0
  398. package/dist/scripts/report.js.map +1 -0
  399. package/dist/scripts/req.js +22 -0
  400. package/dist/scripts/req.js.map +1 -0
  401. package/dist/scripts/schema/cli.js +215 -0
  402. package/dist/scripts/schema/cli.js.map +1 -0
  403. package/dist/scripts/schema/registry.js +264 -0
  404. package/dist/scripts/schema/registry.js.map +1 -0
  405. package/dist/scripts/specops/add.js +180 -0
  406. package/dist/scripts/specops/add.js.map +1 -0
  407. package/dist/scripts/specops/against_lock.js +100 -0
  408. package/dist/scripts/specops/against_lock.js.map +1 -0
  409. package/dist/scripts/specops/as_change.js +49 -0
  410. package/dist/scripts/specops/as_change.js.map +1 -0
  411. package/dist/scripts/specops/contribute.js +24 -0
  412. package/dist/scripts/specops/contribute.js.map +1 -0
  413. package/dist/scripts/specops/diff.js +32 -0
  414. package/dist/scripts/specops/diff.js.map +1 -0
  415. package/dist/scripts/specops/lock.js +39 -0
  416. package/dist/scripts/specops/lock.js.map +1 -0
  417. package/dist/scripts/specops/manifest.js +90 -0
  418. package/dist/scripts/specops/manifest.js.map +1 -0
  419. package/dist/scripts/specops/remove.js +102 -0
  420. package/dist/scripts/specops/remove.js.map +1 -0
  421. package/dist/scripts/specops/sync.js +27 -0
  422. package/dist/scripts/specops/sync.js.map +1 -0
  423. package/dist/scripts/specops/verify.js +149 -0
  424. package/dist/scripts/specops/verify.js.map +1 -0
  425. package/dist/scripts/status.js +17 -0
  426. package/dist/scripts/status.js.map +1 -0
  427. package/dist/scripts/studio.js +14 -0
  428. package/dist/scripts/studio.js.map +1 -0
  429. package/dist/scripts/update.js +17 -0
  430. package/dist/scripts/update.js.map +1 -0
  431. package/dist/scripts/validate_specs.js +10 -0
  432. package/dist/scripts/validate_specs.js.map +1 -0
  433. package/examples/project.config.example +19 -0
  434. package/examples/project.yaml.example +17 -0
  435. package/package.json +105 -0
  436. package/templates/adopt/AI_RULES.md.tpl +27 -0
  437. package/templates/adopt/adr-readme.md.tpl +5 -0
  438. package/templates/adopt/baseline.feature.tpl +9 -0
  439. package/templates/adopt/spec.md.tpl +25 -0
  440. package/templates/adopt/traceability.md.tpl +11 -0
  441. package/templates/backend/AI_RULES.md.tpl +35 -0
  442. package/templates/backend/features/core/health.feature.tpl +7 -0
  443. package/templates/base/.devcontainer/devcontainer.json.tpl +18 -0
  444. package/templates/base/.dockerignore.tpl +11 -0
  445. package/templates/base/.env.dev.app.tpl +13 -0
  446. package/templates/base/.env.dev.infra.tpl +6 -0
  447. package/templates/base/.env.dev.tpl +16 -0
  448. package/templates/base/.env.example.tpl +17 -0
  449. package/templates/base/.env.feature.app.tpl +11 -0
  450. package/templates/base/.env.feature.infra.tpl +4 -0
  451. package/templates/base/.env.feature.tpl +16 -0
  452. package/templates/base/.env.prod.app.tpl +13 -0
  453. package/templates/base/.env.prod.infra.tpl +6 -0
  454. package/templates/base/.env.prod.tpl +16 -0
  455. package/templates/base/.github/workflows/specs.yml.tpl +26 -0
  456. package/templates/base/.gitignore.tpl +9 -0
  457. package/templates/base/.pre-commit-config.yaml.tpl +10 -0
  458. package/templates/base/AGENTS.md.tpl +32 -0
  459. package/templates/base/README.md.tpl +32 -0
  460. package/templates/base/docker-compose.yml.tpl +13 -0
  461. package/templates/base/docs/specs/adr/README.md.tpl +10 -0
  462. package/templates/base/docs/specs/aggregates.md.tpl +5 -0
  463. package/templates/base/docs/specs/commands.md.tpl +13 -0
  464. package/templates/base/docs/specs/domain-model.md.tpl +30 -0
  465. package/templates/base/docs/specs/events.md.tpl +5 -0
  466. package/templates/base/docs/specs/review-checklist.md.tpl +18 -0
  467. package/templates/base/docs/specs/runtime-environments.md.tpl +26 -0
  468. package/templates/base/docs/specs/status-model.md.tpl +16 -0
  469. package/templates/base/docs/specs/traceability.md.tpl +7 -0
  470. package/templates/base/docs/specs/use-cases.md.tpl +5 -0
  471. package/templates/base/spec.md.tpl +63 -0
  472. package/templates/ci/azure.yml.tpl +40 -0
  473. package/templates/ci/github.yml.tpl +40 -0
  474. package/templates/ci/gitlab.yml.tpl +21 -0
  475. package/templates/ci/jenkins.tpl +35 -0
  476. package/templates/contracts/AI_RULES.md.tpl +55 -0
  477. package/templates/contracts/asyncapi-stub.yaml.tpl +24 -0
  478. package/templates/contracts/contract-traceability.md.tpl +10 -0
  479. package/templates/contracts/openapi-stub.yaml.tpl +29 -0
  480. package/templates/contracts/pacts-gitkeep.tpl +0 -0
  481. package/templates/contracts/test-strategy.md.tpl +94 -0
  482. package/templates/frontend/AI_RULES.md.tpl +34 -0
  483. package/templates/frontend/features/core/health.feature.tpl +6 -0
  484. package/templates/harness/harness.config.yaml.tpl +74 -0
  485. package/templates/harness/prompt-prefix.md.tpl +60 -0
  486. package/templates/mobile/AI_RULES.md.tpl +56 -0
  487. package/templates/mobile/features/core/health.feature.tpl +7 -0
  488. package/templates/modules/auth/backend/registration_and_login.feature.tpl +10 -0
  489. package/templates/modules/auth/frontend/login.feature.tpl +5 -0
  490. package/templates/modules/billing/backend/billing_settlement.feature.tpl +5 -0
  491. package/templates/modules/billing/frontend/billing_summary.feature.tpl +5 -0
  492. package/templates/modules/dashboard/backend/dashboard_kpi.feature.tpl +5 -0
  493. package/templates/modules/dashboard/frontend/dashboard.feature.tpl +5 -0
  494. package/vendor/mermaid.min.js +3636 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,1016 @@
1
+ <!-- csda:allow-placeholders — release notes quote the {{VAR}} template syntax. -->
2
+ # Changelog
3
+
4
+ Notable changes, newest first. Follows [Keep a Changelog](https://keepachangelog.com/)
5
+ and [Semantic Versioning](https://semver.org/).
6
+
7
+ The release process is in [`docs/release-process.md`](docs/release-process.md).
8
+
9
+ ## [0.8.1] — 2026-09-01
10
+
11
+ ### Changed
12
+
13
+ - **The npm package is `@rsaglobaltech/specgate`.** 0.8.0 could not be published
14
+ under the unscoped name:
15
+
16
+ ```
17
+ npm error 403 Forbidden - PUT https://registry.npmjs.org/specgate
18
+ - You may not perform that action with these credentials.
19
+ ```
20
+
21
+ Not a permissions problem. npm compares a new package name against existing
22
+ ones with punctuation removed, and
23
+ [`spec-gate`](https://www.npmjs.com/package/spec-gate) normalises to exactly
24
+ `specgate`, so the registry refuses the name to everyone and reports it as a
25
+ credentials error. ADR-0024 had checked availability with `npm view specgate`
26
+ → 404, which says *not published* and never *creatable*; the
27
+ [2026-09-01 addendum](docs/specs/adr/0024-the-tool-is-renamed-the-format-is-not.md)
28
+ records both the decision and the bad check that led to it.
29
+
30
+ The scope is what makes the name reachable at all, and it is the one the
31
+ package already carries on GitHub Packages — so the tool now answers to a
32
+ single spelling in both registries rather than two.
33
+
34
+ **Only the install line changes.** The tool is still Specgate, the binary is
35
+ still `specgate`, and `csda` and `create-spec-driven-app` remain alias
36
+ binaries. The repository and the Docker image `ghcr.io/rsaglobaltech/specgate`
37
+ are untouched — 0.8.0 published the image and the GitHub Packages copy
38
+ successfully, which is why this ships as 0.8.1 rather than re-cutting a tag
39
+ that is already live.
40
+
41
+ Every scaffolded CI config, the pre-commit hook, the GitHub Action, the VS
42
+ Code extension's `cliPath` default and the MCP server's fallback command all
43
+ name the scoped package, so a project generated today installs something that
44
+ resolves.
45
+
46
+ ## [0.8.0] — 2026-09-01
47
+
48
+ The release that makes the new name real. Everything since 0.7.0 shipped under
49
+ `create-spec-driven-app`; this is the first version published as `specgate`, and
50
+ the one that finishes the rename past the layer where it had stopped.
51
+
52
+ ### Changed
53
+
54
+ - **The tool is now called Specgate.** npm package `specgate`, binary
55
+ `specgate`. `create-spec-driven-app` described a scaffolder in the
56
+ `create-react-app` mould, and the product stopped being one several minors
57
+ ago — it has a change lifecycle, an enforcing gate, an agent harness,
58
+ versioned domain packs and ALM sync. The new name states the differentiator:
59
+ the gate enforces the specs.
60
+
61
+ **Nothing breaks.** `csda` and `create-spec-driven-app` both remain as alias
62
+ binaries, and neither is removed in the 0.x line — an `npx` invocation that
63
+ worked before still works.
64
+
65
+ **The on-disk format is deliberately unchanged.** `csda:trace`, `csda:value`,
66
+ `csda:allow-placeholders` and the `.csda/` directory keep their names. Those
67
+ are not branding: they are a parsed format and a config directory that live
68
+ inside *user* repositories, and renaming them would be a silent breaking
69
+ change to every adopted project — surfacing as "requirement not found" rather
70
+ than as "your marker prefix changed". Reading both prefixes is a real
71
+ migration feature, not a find-and-replace, and it is not built here.
72
+ [ADR-0024](docs/specs/adr/0024-the-tool-is-renamed-the-format-is-not.md)
73
+ records the decision so the mismatch is not mistaken for an oversight.
74
+
75
+ **Distribution identity moves with it.** Sibling packages become
76
+ `@specgate/*` (never published under the old scope — verified 404, so nothing
77
+ to deprecate), the VS Code extension becomes `specgate-vscode` (unpublished,
78
+ so no installs to orphan), and new Docker tags land under
79
+ `ghcr.io/<owner>/specgate`. Images already published as `csda` are never
80
+ rebuilt in place and keep working.
81
+
82
+ `docs/release-process.md` gains the one-time cutover: the exact `npm
83
+ deprecate` invocation for `create-spec-driven-app`, why the old package is
84
+ deprecated and never unpublished (npm blocks reusing an unpublished name, and
85
+ a pinned dependency would break for no gain), and the sequencing constraint —
86
+ the rename and the release that publishes `specgate` are one event, because
87
+ the README describes the tool by its new name.
88
+
89
+ Two things caught by tests rather than by reading: the Docker workflow's smoke
90
+ test still pulled the old image name after pushing the new one, and the MCP
91
+ server resolved its own version by matching the package name literally, so it
92
+ would have announced `0.0.0` over the wire. Both now match either spelling.
93
+
94
+ Historical records keep the old name where it was accurate when written:
95
+ earlier CHANGELOG entries, ADRs 0008–0010, the published article and the case
96
+ study are left alone.
97
+
98
+ **The cutover reaches the scaffolding this time.** Every template CI config
99
+ installed `create-spec-driven-app`, pinned or floating at `@latest` — so a
100
+ project generated after the deprecation would have installed a deprecated name
101
+ frozen at 0.7.0 forever. They install `specgate`, and the template placeholder
102
+ is `{{SPECGATE_VERSION}}`, renamed in lockstep with its writer.
103
+
104
+ **`csda <sub>` became `specgate <sub>` across every surface a user reads**:
105
+ the landing page (regenerated from its storyboard, not hand-edited), the
106
+ guides, CLI help and error text, agent prompts and the scaffolding templates.
107
+ `tests/unit/docs-truth.test.ts` enforced the opposite rule and is inverted
108
+ rather than deleted — it rejects either alias followed by a real sub-command,
109
+ and never matches the frozen `csda:`, `.csda` or `csda_` spellings.
110
+
111
+ **The pack schema `$id` keeps `spec-driven.dev`.** An `$id` is the identity of
112
+ v1, not a URL anything fetches; changing it is a schema-version event, not a
113
+ rename.
114
+
115
+ The release that starts checking content instead of only paperwork. Every check
116
+ until now answered "are these documents internally consistent?"; none answered
117
+ "does the code say what the spec says?". These do — for the narrow slice where
118
+ that question has an honest answer. The reasoning, including what was
119
+ deliberately *not* built, is [ADR-0023](docs/specs/adr/0023-checking-content-gate-or-report.md).
120
+
121
+ ### Added
122
+
123
+ - **`csda validate --strict-requirements`** fails when a requirement in
124
+ `docs/specs/capabilities/**/spec.md` states no obligation (`SHALL`, `MUST`,
125
+ `SHOULD`, `MAY`, `DEBE`, `DEBERÁ`), or opens with `IF` and never resolves with
126
+ `THEN`. It does **not** parse EARS grammar — no regex tells "the system" from
127
+ a response clause reliably, and a check claiming a grammar it cannot parse is
128
+ the H13 mistake. These two rules are what a regex can assert honestly.
129
+
130
+ The point is upstream of any code checking: `- Max 5 failed attempts per hour
131
+ per user` is not something a machine can hold code to. RFC 2119 detection also
132
+ stops being duplicated — `DeltaSpec` enforced it for requirements inside a
133
+ change while a capability spec at rest was never checked; both now read one
134
+ definition.
135
+
136
+ - **`csda validate --strict-links`** fails when a Feature file, Technical
137
+ artifact or Test artifact the matrix declares as a path no longer exists on
138
+ disk. A cell may anchor a line range (`src/auth/login.ts#L15-L89`); the anchor
139
+ is not part of the path.
140
+
141
+ Opt-in, and that was measured rather than assumed: the first version ran
142
+ unconditionally on the theory that a missing path has no legitimate reading,
143
+ and the test suite disproved it at once — a `Draft` or `In Dev` row routinely
144
+ names the file a requirement is *going to* land in. Planning ahead is not
145
+ documentary drift.
146
+
147
+ - **Declared-value drift in `csda report`.** Annotate a value on both sides —
148
+ `value_<id>=<literal>` in a `csda:trace` comment, `csda:value <id>=<literal>`
149
+ in the source — and the report classifies each identifier as `matched`,
150
+ `diverging`, `spec_only` or `code_only`, with `file:line` for the code side.
151
+ `--record` gains `valuesTotal`, `valuesMatched` and `valuesDiverging`, and the
152
+ sparkline gains a second dotted series once the whole history carries them.
153
+ All additive: an older history line simply lacks the fields.
154
+
155
+ This is the case the other gates structurally cannot catch — spec and code
156
+ both present, both internally consistent, and disagreeing. **It is a report,
157
+ not a gate**, and that is a deliberate rejection of `--strict-values`: the
158
+ cost of annotating grows with the number of checkable facts while coverage
159
+ does not, and the fraction of requirements that reduce to a scalar shrinks as
160
+ a system gets more complex. A hard gate over a partial, hand-maintained
161
+ annotation set would mostly measure who remembered to annotate.
162
+
163
+ It compares strings and does not interpret units. `15m` and `900000` are
164
+ different values here, on purpose.
165
+
166
+ - **`csda change new <id> --from-value-drift <REQ-ID>:<value_id>`** turns a
167
+ diverging value into a reviewable change. It writes a `## MODIFIED
168
+ Requirements` delta carrying the full requirement, with the structured
169
+ `value_<id>` rewritten to the value the code declares.
170
+
171
+ **The prose is left alone.** Turning "expires after 15 minutes" into "after
172
+ 30" would be guessing how a sentence should read on someone's behalf, so it
173
+ leaves an explicit `TODO:` instead — the same restraint `pack infer` already
174
+ applies to what it cannot infer (ADR-0014). Four named exits rather than a
175
+ half-written change directory, including `value_drift_already_matches`:
176
+ proposing a change when there is nothing to change is worse than refusing.
177
+
178
+ The other two routes out of a divergence needed no new command and got none —
179
+ fixing the code (the report already gives `file:line`) and retiring the
180
+ requirement (`--capability` with a `## REMOVED Requirements` section).
181
+
182
+ ### Fixed
183
+
184
+ - **The gate approved an agent that wrote nothing (H19).** The gate runs *before*
185
+ `csda done`, so at gate time the requirement is still `Draft` — and
186
+ `--strict-tdd`'s "no `Test Artifact = TBD` past Draft" rule does not apply to a
187
+ Draft row. `done` then moved the status to `Implemented` and nothing validated
188
+ again.
189
+
190
+ Reproduced against a freshly generated project with
191
+ `--agent "cat {prompt_file} > /dev/null"`: **`✅ REQ-000 pass (1 attempt)`**.
192
+ The branch carried the archived prompt and one changed line — the matrix row
193
+ moved to `Implemented`, its Test artifact still `TBD`. No code, no test. It is
194
+ H1's root cause exactly: the gate approving what it did not check.
195
+
196
+ The harness now refuses an attempt whose diff is empty, before the gate rather
197
+ than after — a green gate over an empty diff proves nothing, and stopping
198
+ early also spares the project's test command. The archived prompt does not
199
+ count as work, because the harness writes it itself. This is a hard failure
200
+ rather than another opt-in flag: `--strict-artifacts` cannot catch it (it
201
+ compares against the paths the row declares, and a row declaring none has
202
+ nothing to compare), and an agent that produced no files has no legitimate
203
+ reading — the condition ADR-0023 sets for a gate. The attempt ends at a new
204
+ `no-op` stage, kept separate from `gate` in the run record because the fix is
205
+ never in the code: it is the agent's write permissions or its prompt.
206
+
207
+ - **A generated project did not pass its own gates (H20).**
208
+ `templates/base/spec.md.tpl` §8 shipped a pre-filled `REQ-001` example, and
209
+ `traceability.md.tpl` carries only `REQ-000` — so every project born from
210
+ `csda init` failed `validate --strict-tdd` with `[TDD-3]` before anyone wrote
211
+ a line. `ensureTraceabilityCoverage` could not save it: it reconciles feature
212
+ files that have no row, not requirements.
213
+
214
+ Worse than a red gate on day one: `csda harness run` on a new project **burned
215
+ all three agent attempts** failing on something the agent neither caused nor
216
+ could fix. And it contradicted the README's L2 — *"a PR gate enforcing spec and
217
+ test coverage, ~1 hour"* — since the gate was red before the hour started.
218
+
219
+ The placeholder row is gone, replaced by a comment pointing at
220
+ `csda req add "<what the requirement does>"`, which writes the row in `spec.md`
221
+ **and** in the matrix at once. The example use case no longer references a
222
+ requirement id that does not exist. A generated project now passes all four of
223
+ its gates, pinned by a test that runs them — the defect was invisible from
224
+ inside, because plain `validate` was green throughout.
225
+
226
+ Found while building the fixture to reproduce H19.
227
+
228
+ - **The test suite was asserting the defect.** Sixteen harness tests handed the
229
+ runner `true {prompt_file}` — a command that reads nothing, writes nothing and
230
+ exits 0 — as the stand-in for "an agent whose work passes the gate", and one
231
+ more used a scripted agent with an empty write list. Every assertion built on
232
+ them was pinning H19 as correct behaviour. They now use an agent that writes
233
+ one file, which is the cheapest thing a real agent does. Same shape as H3,
234
+ where a test weakened its own clean-tree check in order to pass.
235
+
236
+ ### Changed
237
+
238
+ - **The support policy is a commitment now, not an intention (`GATE-G5`).**
239
+ `docs/release-process.md` carried an escape clause saying the post-1.0 policy
240
+ held only until the clause itself was deleted. It is deleted, and its absence
241
+ is the commitment: from 1.0 on, one supported line plus the previous minor for
242
+ **six months** from the day its successor ships — security and correctness
243
+ fixes both, features not backported.
244
+
245
+ What that costs is written down beside it, because a promise nobody costed is
246
+ how the paragraph came to need an escape hatch in the first place: two lines
247
+ need a release path for six months after every minor, and a fix landing on
248
+ `main` has to be evaluated against the previous minor rather than only forward.
249
+
250
+ - **`SECURITY.md` listed `0.2.x` as the supported version — five minors late.**
251
+ Nobody had revisited the table since it was written, so the security policy
252
+ was making a support claim that had been false since 0.3.0. Corrected to
253
+ `0.7.x`, with a note that the table moves with the release or it becomes the
254
+ same kind of unchecked statement it exists to prevent.
255
+
256
+ ### Documentation
257
+
258
+ - **The four opt-in gates are documented together** in
259
+ [validating.md](docs/validating.md), with what each one deliberately does not
260
+ check. **`--strict-scenarios` shipped in 0.7.0 and appeared in no user-facing
261
+ document** — only in `docs/specs/harness.md`. A gate users cannot find is a
262
+ gate that does not exist for them.
263
+
264
+ - **`ADR-0023`** records the rule the three additions follow: a content check is
265
+ a gate only when failing it is always a defect; otherwise opt-in, or a report;
266
+ and no check asserts a grammar it does not parse.
267
+
268
+ ### Fixed
269
+
270
+ - **`specgate adopt` did not run at all.** `templates/adopt/spec.md.tpl` asks
271
+ for `{{PROPOSED_REQUIREMENTS}}` and nothing supplied it, so the brownfield
272
+ entry point died on `Missing variable 'PROPOSED_REQUIREMENTS' required by
273
+ template` for every repository.
274
+
275
+ Two parallel branches caused it. P6 taught `adopt` to seed one requirement per
276
+ capability `onboard` reads off the layout, and added `--monorepo` and
277
+ `--no-capabilities`; the clean-architecture refactor branched before that and
278
+ rewrote `adopt` from the pre-P6 source. Merging both kept P6's template and
279
+ the refactor's code, so the placeholder outlived the function that filled it.
280
+
281
+ The same merge reverted `onboard` from 722 lines to 295, losing declared-module
282
+ discovery, the layered-project descent, the Python package roots and the
283
+ H14/H16/H17 fixes — which is why `proposeCapabilities` answered `[]` for every
284
+ repository in the corpus. All of it is back, in its clean-architecture home,
285
+ including `findAdoptedAncestor`: onboard runs on repositories that are not
286
+ spec-driven yet, so resolving upwards to an adopted ancestor reports a
287
+ different codebase than the one asked about (H16). The ancestor is named,
288
+ never substituted.
289
+
290
+ - **`validate` stopped saying when an adoption was never retro-filled (H15).**
291
+ Lost to the same merge. A project whose only scenario is the adoption baseline
292
+ says so again — still a pass, never an error, because a gate that rejects a
293
+ fresh adoption is a gate nobody installs.
294
+
295
+ - **Three MCP tools had been deleted and four renamed.** #138 generated the tool
296
+ registry from the command surface and, in doing so, removed `read_spec`,
297
+ `list_requirements` and `update_traceability` and renamed the rest to
298
+ `csda_*`. A tool id lives in someone else's agent config. The three that are
299
+ not a CLI command behind a shell now live outside the generated file, so
300
+ regeneration cannot eat them again, and all seven published names resolve.
301
+
302
+ - **The MCP tool generator never wrote the file it generates.** `OUT_FILE`
303
+ resolved from `__dirname`, which is `dist/scripts/` once compiled, so every
304
+ run reported success into build output while the committed registry drifted
305
+ from the surface it is derived from.
306
+
307
+ - **`validate_project` could not work over MCP.** The generated shell always
308
+ passed `--project-dir`, and `validate` takes a positional `<dir>` and rejects
309
+ the flag — so the most used tool of the seven failed with "Unknown flag(s)"
310
+ and an empty payload. The surface already records which form a command takes
311
+ in `json.args`; the generator reads it instead of assuming. Alongside it,
312
+ `ensureProjectDir` had been reduced to a type check (a directory that is not
313
+ spec-driven now gets a reason, not an empty failure) and the CLI command line
314
+ was parsed with `split(" ")` (an interpreter path with a space in it now
315
+ survives).
316
+
317
+ `validate_project` returns the CLI's JSON document verbatim rather than the
318
+ bespoke `{ passed, errors, warnings }` summary it used to flatten it into —
319
+ one envelope, branch on the contract, per ADR-0017.
320
+
321
+ - **The IntelliJ plugin, `mcp install` and `agents init` invoked a package that
322
+ does not exist.** All three named `@spec-driven/lsp-server` or
323
+ `@spec-driven/mcp-server`; that scope was never published. They name
324
+ `@specgate/*` now, which is what the packages actually publish.
325
+
326
+ - **The documented Docker pipeline could not have worked.** `docs/automation.md`
327
+ told readers to pull `ghcr.io/rsaglobaltech/csda:0.2.1` and then run
328
+ `specgate validate` inside it, and an image tagged before the rename has no
329
+ `specgate` binary. The examples move to `ghcr.io/rsaglobaltech/specgate` and
330
+ the note says why the image and the command name travel together. The
331
+ Dockerfile's entrypoint is `specgate` rather than the alias.
332
+
333
+ - **The shell completions did not register `specgate`** — the primary binary was
334
+ the one name that did not complete. All three shells now register all three
335
+ names.
336
+
337
+ - **The landing page claimed 24 commands against a surface of 25.**
338
+
339
+ - **CI had not run this repository's own gate since the rename.** The rename
340
+ commit changed the *references* to `bin/specgate.{ts,js}` in `ci.yml`,
341
+ `CONTRIBUTING.md` and `AI_RULES.md` without renaming the file, so the step
342
+ named "Validate this repository against its own spec gate" ran
343
+ `node bin/specgate.js validate .` against a path that did not exist and every
344
+ test job failed. The entry point is `bin/specgate.ts` now, as those three
345
+ documents already said. All three binaries — `specgate`, `csda` and
346
+ `create-spec-driven-app` — point at it, and the shim's entry-point check
347
+ accepts either basename so an installation carrying the old shim keeps
348
+ dispatching.
349
+
350
+ - **The test suite could not locate the repository root on Windows.** Thirty-nine
351
+ test files resolved it with `__dirname.split("/tests")[0]`, and `__dirname` on
352
+ Windows is `…\dist\tests\unit` — the separator never matched, so the split
353
+ returned the whole path and every spawned CLI was looked for under
354
+ `dist\tests\unit\bin\`. The split is separator-agnostic now. It had been
355
+ masked: the `adopt` regression above failed those files on every platform, so
356
+ nothing distinguished "broken everywhere" from "broken on Windows".
357
+
358
+
359
+ ## [0.7.0] — 2026-08-23
360
+
361
+ The release that closes the gate on itself. Every item below came from running
362
+ the loop and finding it approving work it had not checked — H13, H14, H15 and
363
+ H16, all four measured before anything was written and reproduced after.
364
+
365
+ ### Added
366
+
367
+ - **`csda validate --strict-scenarios`** applies the pack's eight scenario
368
+ quality rules to `features/**/*.feature`. The rules moved into the domain, so
369
+ `pack lint`, `validate`, `doctor` and `harness run` reach the same verdict
370
+ instead of three drifting copies. `doctor` reports them as advisories, which
371
+ is the gradual path for a repository brought in with `csda adopt`.
372
+
373
+ - **`csda harness run --skip-not-ready`** skips a requirement an agent could not
374
+ succeed at — no feature file, unmet dependencies, `Deprecated`, or `Needs
375
+ Clarification`. `csda plan --format json` now carries `ready` and `blockers[]`
376
+ per requirement, each blocker with a fix. Default is to warn and run it
377
+ anyway; an unrunnable scenario skips regardless, because an empty scenario
378
+ passes and a green run over one proves nothing.
379
+
380
+ - **`csda harness run --resume`** continues an interrupted run: it re-attaches to
381
+ the branch and, when git still knows of one, to the worktree holding the
382
+ agent's uncommitted work. Where it picks up is read from the prompt archive,
383
+ not the run ledger — the ledger is written when a run *finishes*, so an
384
+ interrupted run leaves none.
385
+
386
+ - **`csda harness run --budget-seconds` and `--max-requirements`** put a ceiling
387
+ on a run. Asked before starting each requirement, never mid-attempt.
388
+ Exhausting one is not an error: the run ends normally, names what it never
389
+ started, and still writes its ledger.
390
+
391
+ - **`csda harness run --strict-artifacts`** fails an attempt whose green diff
392
+ never touches the paths the matrix declares for the requirement. A warning by
393
+ default — work can legitimately land in a shared module.
394
+
395
+ - **A write-scope guard.** Before the gate, the harness checks the agent has not
396
+ edited the contract it is judged against: `spec.md`, `AI_RULES.md`,
397
+ `features/**`, `docs/specs/**`, `.specops.lock`, `harness.config.yaml`.
398
+ Configurable through `protected_paths` and `allow_paths`. Creating a file that
399
+ did not exist is allowed; modifying one that did is not.
400
+
401
+ - **The gate reads Cucumber's message protocol** when it can. `--format message`
402
+ answers whether a scenario for the requirement exists, ran, had steps and
403
+ passed — where the exit code only said "zero". Opt in with `message_report:`,
404
+ or let the harness add the flag to a direct `cucumber-js` invocation.
405
+
406
+ - **`csda harness report`** gains where attempts end, which requirements spend
407
+ every attempt, a series over time, and `--mark-false-failure REQ-NNN --reason
408
+ "…"`. The real-failure rate reads `—` until somebody marks one: nothing
409
+ recorded can tell a gate that was wrong from work that was.
410
+
411
+ - **`depends_on`** on a pack's requirements. The harness cuts a dependent's
412
+ branch from its predecessor's rather than from the run's base. Cycles and
413
+ broken references are refused when the pack is validated, not at run time.
414
+
415
+ - **An agent profile per requirement.** A profile that declares `match:` selects
416
+ itself, so one run can give different requirements different agents and
417
+ different tool allowances. `cost_per_run_hint` lets a profile declare roughly
418
+ what a run of it costs; the report multiplies it out, labelled as declared
419
+ rather than measured.
420
+
421
+ - **`@REQ-NNN @SCN-NNN` tags** on every scenario `csda expand` and `csda init`
422
+ write. `validate` uses them to check the matrix points at a scenario that
423
+ exists — which nothing did before. A file carrying no tags is left alone.
424
+
425
+ ### Changed
426
+
427
+ - **`scenario_has_no_steps` and `keyword_case_invalid` are errors on their own**,
428
+ without `--strict`. They used to be style opinions that `--strict` promoted,
429
+ CI ran `--strict`, and the packs still went out with 27 scenarios that
430
+ executed nothing. Both messages name the file, the line and the spelling that
431
+ works.
432
+
433
+ - **`schemas/pack.schema.json` describes the format that exists** (1.3.0 →
434
+ 1.4.0). It required full CQRS on every use case and command, so ten of the
435
+ eleven curated packs failed the schema ADR-0020 calls the authority — while
436
+ all eleven passed `pack lint`. Required is now what the installer needs;
437
+ everything else is optional and validated when present. The shipped packs are
438
+ validated against it in the suite, which nothing did before. **No pack changed
439
+ and none had to**: this relaxes and corrects.
440
+
441
+ ### Fixed
442
+
443
+ - **The eleven curated packs rendered empty domain documents.** The schema said
444
+ `context` and `invariants`, the packs write `bounded_context` and
445
+ `responsibilities`, and the renderer read the schema's names — so installing
446
+ any pack produced `| AGG-001 | Invoice | - | - |` with the values right there
447
+ in the pack under other names. Aggregates now render their context and
448
+ responsibilities, and events their producer.
449
+
450
+ - **`validatePackModel` never checked an aggregate's bounded context.** It read
451
+ `aggregate.context`; every pack writes `bounded_context`, and an empty
452
+ reference is skipped — so the cross-reference was inert on all eleven.
453
+ `pack lint` had its own check and caught it, which is why nobody noticed the
454
+ installer's did not.
455
+
456
+ - **`parseYamlLite` split inline sequences on every comma**, including the ones
457
+ inside quotes, so `responsibilities: ["Invoice line items, totals, status,
458
+ aging"]` parsed as four items carrying stray quote characters.
459
+
460
+ ### Security
461
+
462
+ - **A pack repository could make git run a command.** `csda expand --pack-repo`
463
+ and `csda specops contribute` passed a caller-named repository straight to
464
+ `git clone`. Two shapes turn that into execution, both of them git behaving as
465
+ documented: a value beginning with `-` is read as an option, so
466
+ `--upload-pack=<cmd>` runs `<cmd>`; and `ext::` is a transport whose job is to
467
+ run a command.
468
+
469
+ Both are refused now, with a message that says what to use instead, and the
470
+ positional arguments are separated with `--`. Passing the value as its own
471
+ argv element was never the defence — git parses argv, not the shell.
472
+
473
+ - **Fifteen regular expressions could backtrack quadratically.** All the same
474
+ shape: `\s` matching a newline in a line-oriented pattern, or a lazy group
475
+ followed by `\s*$`. Line patterns use `[ \t]` now and capture to the end of
476
+ the line, trimming in code.
477
+
478
+ - **Two YAML writers escaped the quote but not the backslash**, so a value
479
+ ending in `\` escaped its own escape and broke out of its string.
480
+
481
+ - **Matrix trace lines are parsed onto a prototype-less object**, since the keys
482
+ come out of a file.
483
+
484
+ Found by putting the branch through CodeQL for the first time. Twenty-one alerts
485
+ were fixed rather than dismissed; nothing was waved through to make a release
486
+ date.
487
+
488
+ - **The published CLI did nothing on Windows.** `bin/create-spec-driven-app.js`
489
+ is a two-line shim that `require`s the built entry point, so `require.main` is
490
+ the shim and the guard recognised it by name — with
491
+ `filename.endsWith("bin/create-spec-driven-app.js")`, which never matches on
492
+ Windows, where `filename` carries backslashes. The CLI loaded, dispatched
493
+ nothing, and exited 0 **with no output on either stream**.
494
+
495
+ Found by putting this branch through CI for the first time: 437 tests failed
496
+ on Windows and not one message said why, because there was no message. It
497
+ survived because both machines it was developed on use `/`.
498
+
499
+ - **`csda validate .` on this repository had been failing since the clean
500
+ architecture refactor.** Splitting `scripts/init_pack.ts` dropped its
501
+ `csda:allow-placeholders` marker, so the command's own `{{VAR}}` output read
502
+ as an unrendered project. It went unnoticed for six days because the gate
503
+ being run was `test:all` plus the linters, and the selfcheck lives in
504
+ `npm run verify`. Found by running the release gate, which is what it is for.
505
+
506
+ - **`csda pack init` still scaffolded `GIVEN / WHEN / THEN`.** The 27 shipped
507
+ files were fixed; the file that writes new ones was not, so every pack created
508
+ since started with an example scenario Cucumber saw as empty.
509
+
510
+ - **The scenarios shipped in the curated packs were never executed.** 27 of the
511
+ 28 scenarios under `packs/**` wrote their keywords in upper case —
512
+ `GIVEN` / `WHEN` / `THEN` — and Gherkin keywords are case-sensitive. Cucumber
513
+ read those lines as the scenario's *description*, so the scenario existed with
514
+ **zero steps**, and an empty scenario passes: `1 scenario (1 passed) · 0 steps
515
+ · exit 0`.
516
+
517
+ Every project seeded with `csda specops add` therefore inherited an acceptance
518
+ criterion that approves anything, and a harness run over those requirements
519
+ was not verifying them. Measured on one file before and after: 0 steps and
520
+ exit 0 became 3 steps and exit 1.
521
+
522
+ `csda pack lint --strict` had approved them, because its own matcher is
523
+ case-insensitive and saw three steps where the runner saw none. A new test
524
+ parses every `.feature` and `.feature.tpl` this repository ships with
525
+ `@cucumber/gherkin` — the parser that will actually run them — and fails on
526
+ any scenario with no steps, so this cannot come back. Bringing the linter
527
+ itself to parity with Cucumber is separate work.
528
+
529
+ **If you already installed a pack**, `csda specops diff` will report drift in
530
+ the rendered feature files. That is this correction arriving. Reviewing it as
531
+ intent rather than as a file diff is what `csda specops diff --as-change` is
532
+ for.
533
+
534
+ ## [0.6.0] — 2026-08-18
535
+
536
+ ### Fixed
537
+
538
+ - **A failed run destroyed the agent's work.** The gate failing meant `continue`,
539
+ and the worktree was deleted at the end — so the branch came back identical to
540
+ its base and there was nothing to review. Diagnosing a failure cost a second
541
+ full agent run with `--keep-worktrees`, fifteen minutes to recover what the
542
+ first run already had.
543
+
544
+ The attempt is now committed on the branch with a `wip(REQ-NNN): FAILED the
545
+ gate — do not merge as is` subject. The requirement stays `Draft`, because
546
+ `csda done` never ran, so nothing about the matrix claims the work is good. A
547
+ human reads it and decides; git just stops throwing it away. The report says
548
+ whether the work was preserved, and distinguishes that from an agent that
549
+ produced no files at all — one is a code problem, the other a prompt or
550
+ permissions problem.
551
+
552
+ - **A gate that ran the whole suite instead of one scenario now says so.** If
553
+ a filter silently fails to apply — a runner config pinning its own paths will
554
+ override the CLI argument — the gate rejects correct work and the failure is
555
+ indistinguishable from broken code. It cost two agent runs to explain the
556
+ first time. The harness cannot know how many tests *should* run, but it can
557
+ notice a command that asked for one feature against output reporting many, and
558
+ warn. A hint, not a verdict: a genuine failure must not be explained away.
559
+
560
+ - **A failing gate did not say which command it ran.** A gate that silently does
561
+ the wrong thing — running a whole suite because a filter did not apply — fails
562
+ identically to a real failure. That cost two agent runs to explain on REQ-002,
563
+ where the work was correct and the gate rejected it.
564
+
565
+ - **The default `--timeout` is 1200s, up from 600.** Both real runs disproved the
566
+ old value: the first REQ-001 attempt hit 900s while the agent installed
567
+ dependencies and worked. A default that times out on ordinary work makes every
568
+ first attempt a wasted one.
569
+
570
+ - **A failing `harness run` told you nothing you could act on.** The gate's full
571
+ output — the assertion, the file, the line — was captured and then reduced to
572
+ its first line by the report, so a failure read `Gate failed at: test command`
573
+ and stopped there. With the worktree removed by default, there was nothing
574
+ left to inspect either.
575
+
576
+ The report now prints the tail of the gate output, where runners put the
577
+ actual failure, and names the two flags that give more: `--format json` for
578
+ everything, `--keep-worktrees` to reproduce it. Found by running REQ-002 and
579
+ being unable to tell why it had failed.
580
+
581
+ - **`validate` scanned gitignored files.** The skip list is fixed and cannot
582
+ know what a given project ignores, so a gitignored build directory containing
583
+ `{{VAR}}` — documentation of the placeholder syntax, in this case — failed the
584
+ gate with findings the project had already declared were not source.
585
+
586
+ The scan now asks git what it ignores, and skips that as well as the fixed
587
+ list. Best-effort: no git, no repository, or a git that errors falls back to
588
+ the fixed list rather than refusing to scan, because a check that needs git
589
+ to run is a worse failure than the one it prevents. A tracked file with the
590
+ same placeholder is still reported — the fix narrows the scan, it does not
591
+ weaken it.
592
+
593
+ - **`csda doctor` now names the installation it is running from**, and its
594
+ version and path.
595
+
596
+ Reported by a user whose `csda -v` kept printing 0.1.2 after installing "the
597
+ latest". The tool was right — it *was* 0.1.2, from a global install made
598
+ months earlier. `npx create-spec-driven-app@latest` runs a temporary copy and
599
+ never touches a global one, so the two answer different questions and nothing
600
+ said so. Three minor versions behind, with no way to notice.
601
+
602
+ Doctor distinguishes a global install, a project dependency, an npx cache copy
603
+ and a local checkout, and prints the path. No network call: which version is
604
+ newest is not doctor's business, and a lookup would break the offline and
605
+ air-gapped modes the tool promises.
606
+
607
+ - **Doctor's Node check read `>= 20`** for a release after the floor moved to
608
+ 22. It now reads the floor from `package.json` rather than repeating it — the
609
+ same drift the floor guard exists to prevent, in the one file the guard did
610
+ not cover.
611
+
612
+ ## [0.5.0] — 2026-08-17
613
+
614
+ ### Fixed
615
+
616
+ - **The gate could not run the scenario it was gating.** `test_cmd` was a fixed
617
+ string with no substitution, and the gate runs *before* `csda done` — so the
618
+ requirement is still Draft and `validate --strict-tdd` does not demand its
619
+ test either. Between them, `harness run` could mark a requirement Implemented
620
+ with its scenario never executed.
621
+
622
+ Verified rather than argued, with a requirement left unimplemented:
623
+ `validate --strict-tdd` passed, the project's `verify` passed, and the
624
+ scenario was undefined. Both gate steps green on work nobody did.
625
+
626
+ The gate command now substitutes `{req}`, `{scenario}` and `{feature_file}`,
627
+ so a project can write
628
+ `test_cmd: "npm ci && npm run verify && npm run test:e2e -- {feature_file}"`.
629
+ With that, the same no-op agent fails at the requirement's own scenario.
630
+
631
+ - **The harness blocked its own second run.** It archived each prompt into the
632
+ *project* directory, which left untracked files behind — and the harness
633
+ refuses to start on a dirty tree. The archive now goes in the worktree, where
634
+ `git add -A` commits it with the work, so the prompt arrives in the branch
635
+ under review. That is what an audit copy was for.
636
+
637
+ - **A fresh worktree has no `node_modules`**, because it carries only what git
638
+ tracks. Not a code change but the generated `harness.config.yaml` now says so
639
+ and shows `npm ci &&` in front of the gate: the first real run lost an attempt
640
+ to a 900-second timeout while the agent installed dependencies.
641
+
642
+ ## [0.4.0] — 2026-08-17
643
+
644
+ ### ⚠️ Breaking
645
+
646
+ - **The Node floor is 22.** `package.json` declares `>=22`, and CI tests 22 and
647
+ 24 across Linux, macOS and Windows — the floor and the current LTS, so a break
648
+ at either end shows up.
649
+
650
+ Node 20 left LTS maintenance in April 2026, so the matrix was testing against
651
+ an unsupported runtime and proving nothing. An `npx` invocation that used to
652
+ work and now refuses to run is breaking, whatever else this were called.
653
+
654
+ Raised everywhere at once rather than only where it was noticed: the root
655
+ `engines`, the three publishable packages (which still said `>=18`), every
656
+ workflow's `setup-node`, the Docker image, the CI templates handed to users,
657
+ and the prose in the README and the guides.
658
+
659
+ **The policy is now written down**: the floor is a maintained LTS, and when
660
+ one leaves maintenance the floor moves in the next release. See
661
+ `docs/release-process.md`.
662
+
663
+ ### Changed
664
+
665
+ - **`@cucumber/cucumber` 13.** It had been parked for a release because its
666
+ `engines` wanted Node 22 while ours said 20 — the concrete cost of a stale
667
+ floor. The BDD suite passes unchanged.
668
+
669
+ ### Added
670
+
671
+ - **A test holds the floor in one piece.** It checks the root `engines`, every
672
+ publishable package, each workflow, the CI matrix covering the floor itself,
673
+ the Dockerfile, the templates generated for users, the prose in four guides,
674
+ and that cucumber's own requirement is satisfied. Those had drifted before —
675
+ the packages said 18 while the CLI needed 20 — and a floor only some places
676
+ agree on is not a floor.
677
+
678
+ ## [0.3.0] — 2026-08-17
679
+
680
+ ### ⚠️ Breaking
681
+
682
+ - **`plan --json` and `report --json` now use camelCase inside `requirements`.**
683
+ `0.2.0` announced the camelCase rename as a breaking change and applied it to
684
+ the top-level keys only. The nested `requirements` array — the one array an
685
+ agent actually iterates — kept `scenario_id`, `feature_file`,
686
+ `technical_artifact`, `test_artifact`, `feature_exists`, `technical_exists`
687
+ and `test_exists`. They are now `scenarioId`, `featureFile`,
688
+ `technicalArtifact`, `testArtifact`, `featureExists`, `technicalExists` and
689
+ `testExists`.
690
+
691
+ Half-applied was the worst of the three options: the contract document said
692
+ camelCase, the output disagreed, and nothing failed. The row objects keep
693
+ snake_case internally — that is the matrix's own column vocabulary — so the
694
+ rename happens at the emit boundary only.
695
+
696
+ `summary` and `byCategory` are still keyed by the category enum
697
+ (`NEEDS_IMPLEMENTATION` and friends). Those are values, not field names.
698
+
699
+ ### Changed
700
+
701
+ - **One pack format, with `schemas/pack.schema.json` as its authority**
702
+ ([ADR-0020](docs/specs/adr/0020-pack-format-standard.md)). The schema, the
703
+ validator, the installer, `pack init` and every shipped pack had drifted into
704
+ three descriptions that disagreed, and nothing compared them. The result:
705
+ **all eleven curated packs failed to install**, `pack init` generated packs
706
+ the installer refused, and `pack lint` called every one of them clean.
707
+
708
+ - `outputs.features` is gone; `outputs.files` is the only output shape.
709
+ - Domain invariants move from `rules` to a new **`business_rules`**. `rules`
710
+ keeps its narrow meaning — how the pack renders. Two different ideas were
711
+ sharing one key, and that collision is what broke installation.
712
+ - A scenario now requires only what the installer needs: `id`,
713
+ `requirement_id`, `target`, `template`, `feature`, `scenario`, `status`.
714
+ `use_case`, `command`, `aggregate`, `events`, `technical_artifacts` and
715
+ `test_artifact` are optional and validated when present, so a front-end
716
+ pack no longer has to invent a command to satisfy a validator.
717
+ - **`contracts` is a supported project type.** It was in the schema and in
718
+ `pack init` while the installer rejected it outright.
719
+
720
+ **No pack that ever installed stops installing.** Every change is a
721
+ relaxation or an addition: the scenario rules got looser, `business_rules`
722
+ and `contracts` are new, and `outputs.features` was never implemented by
723
+ anything. Verified against eight packs authored outside this repository, all
724
+ on `schema_version` 1.1.0 — every one still installs untouched. What needs
725
+ migrating is the shape that never worked, and `pack lint` now names exactly
726
+ what is wrong with it.
727
+
728
+
729
+ - **The CLI is called `csda` in every place it is a command.** The package
730
+ ships two binaries — `create-spec-driven-app` and the `csda` alias — and the
731
+ two were used interchangeably, so the same command appeared under different
732
+ names depending on which guide or which `--help` you landed on. 92
733
+ occurrences across 38 files now use the alias: usage strings, docblocks,
734
+ guides, templates and the landing page.
735
+
736
+ **Nothing about invocation changed.** Both binaries still work, and the
737
+ bootstrap line is deliberately untouched: `npx create-spec-driven-app@latest`
738
+ runs before anything is installed, at which point `csda` does not yet exist.
739
+ npm links, the package name and file paths keep the long name too, as does
740
+ `completion`, which registers both binaries on purpose.
741
+
742
+ A guard scans the docs and sources so it cannot drift back.
743
+
744
+ ### Added
745
+
746
+ - **`mobile` is a first-class `PROJECT_TYPE`**, and a pack flavour. Building a
747
+ mobile app previously meant declaring `frontend` and setting the stack, so the
748
+ type recorded in the generated project was untrue and the AI rules it
749
+ inherited talked about responsive behaviour and route navigation.
750
+
751
+ `templates/mobile/AI_RULES.md.tpl` is not a copy of the front-end one. It
752
+ states as acceptance criteria the things a mobile app actually gets wrong:
753
+ offline is a state rather than an error, the OS can kill the process at any
754
+ moment, iOS/Android divergence is declared rather than assumed, a permission
755
+ is a flow with a denial branch, deep links are cold entry points, and passing
756
+ store review is part of done. The baseline scenario is a cold start that needs
757
+ no network, not a request to `/`.
758
+
759
+ A test pins all four places that list project types — `init`, the wizard,
760
+ `pack init` and the JSON Schema enum — because a type accepted by one and
761
+ refused by another is how `contracts` became scaffoldable and impossible to
762
+ install.
763
+
764
+ - **`agent_profile` in `harness.config.yaml`**, resolved from
765
+ `.harness/profiles.yaml`. A team commits the agent commands it uses — local,
766
+ CI, a different vendor — and each environment picks one by name, instead of
767
+ committing a single default somebody pays for by accident. An explicit
768
+ `agent:` wins over a profile.
769
+
770
+ It comes from a real pilot that was already configured this way: the file
771
+ declared `agent_profile: local-claude` with a matching `profiles.yaml`, the
772
+ CLI read neither, and `harness run` reported "No agent configured" while the
773
+ config plainly declared one.
774
+
775
+ - **An unknown key in `harness.config.yaml` is now an error.** That silent
776
+ shrug is what let the above go unnoticed. A key nobody reads is worse than a
777
+ missing one, because the file looks configured.
778
+
779
+ - **Supply-chain documentation and a licence gate.** `docs/supply-chain.md`
780
+ covers pack pinning, the content digest that catches a moved tag, GPG
781
+ signing, and both air-gapped paths — `CSDA_OFFLINE=1` against the cache and
782
+ `pack bundle` for a network that has never seen the pack. `CSDA_OFFLINE`
783
+ appeared in no guide before, so a feature built for closed networks was
784
+ invisible to anyone on one.
785
+
786
+ A CycloneDX SBOM is generated on every push and retained 90 days, and
787
+ `scripts/license_check.ts` fails the build on a licence outside an allow-list
788
+ of permissive terms. Both come from `npm sbom` rather than a third-party
789
+ generator — adding a dependency to document having none would be a poor trade.
790
+ Available locally as `npm run sbom` and `npm run licenses`.
791
+
792
+ - **Pack drift is checked by default in generated CI.** `csda ci init` emits
793
+ `validate --against-lock` for GitHub, GitLab, Azure and Jenkins, guarded on
794
+ `.specops.lock` existing so a project without packs is unaffected.
795
+
796
+ Signature verification stays opt-in. `require_signed_packs: true` as a default
797
+ would fail every project installing a pack whose tags are unsigned, and a
798
+ default that fails on correct usage teaches people to switch the check off.
799
+
800
+ - **Compatibility windows are enforced, not just described.** `pack.yaml`'s
801
+ `schema_version` and `.specops.lock`'s `specops_version` were both written by
802
+ the CLI and read by nothing, so a file from a newer version was accepted and
803
+ then misread field by field. Both now fail up front, naming the versions and
804
+ the upgrade command. Older files still load — only *newer than this CLI* is
805
+ refused.
806
+
807
+ - **`SECURITY.md`, `MAINTAINERS.md` and `CODEOWNERS`**, with private
808
+ vulnerability reporting enabled so the policy points at a channel that
809
+ exists. `main` is protected with required checks. Approving reviews are
810
+ deliberately off while there is one maintainer — requiring one would make
811
+ `main` unmergeable — and that exception is written down rather than left to
812
+ look like an oversight.
813
+
814
+ - **Running the gate with no Node on the build agent** is documented in
815
+ `docs/automation.md`: a pinned `ghcr.io/rsaglobaltech/csda` image as a GitLab
816
+ job image or Jenkins docker agent, and the Maven plugin bound to the `verify`
817
+ phase. The generated configs all call `npx`, which a Java shop's agent does
818
+ not have — the reason the image and the plugins exist in the first place.
819
+
820
+ - **`csda harness init`** — scaffolds `harness.config.yaml` and
821
+ `.harness/prompt-prefix.md`. The config was documented in the tutorial and
822
+ named in `harness run`'s own error message long before anything created it,
823
+ so every project hand-copied it out of a guide.
824
+
825
+ It detects the gate from whichever build file is present (`package.json`,
826
+ `pom.xml`, Gradle, Cargo, Go, Python) and **leaves `test_cmd` commented out
827
+ when it cannot tell**. That absence is the point: `test_cmd` is an extra gate
828
+ on top of the `validate --strict-tdd` the harness always runs, so an unset
829
+ key is safe, while a placeholder like `echo "set this"` exits 0 and would let
830
+ the harness mark requirements done without running a single test.
831
+
832
+ `agent:` is left unset too. Which agent runs the loop is the operator's
833
+ choice and their credentials, and a default in a committed file is a default
834
+ somebody pays for by accident.
835
+
836
+ - **`pack lint` runs the installer's own validation.** "Lint passes" now means
837
+ "this pack can be installed". It previously checked cross-references only, so
838
+ a pack that could never be applied reported clean.
839
+ - **`pack init` produces an installable pack**, including the template files
840
+ its `pack.yaml` declares. It used to write `pack.yaml` alone, so the pack it
841
+ generated failed at the very next step it told you to run.
842
+ - **`--json` on `pack lint` and `specops diff`**, completing the agent
843
+ contract. `specops diff` already had `--format json`; it now accepts `--json`
844
+ and emits camelCase like everything else.
845
+ - **`parseYamlLite` understands inline flow sequences** (`[Invoice, Payment]`).
846
+ The curated packs used them 54 times, and each one parsed as a literal string
847
+ and then failed a cross-reference check against an aggregate nobody declared.
848
+ - **A test installs every pack in `packs/` into a scaffolded project.** Nothing
849
+ exercised those packs before — not CI, not a test — which is why the drift
850
+ went unnoticed for as long as it did.
851
+
852
+ - **`csda init --no-sample-req`**, implied by `--from-pack`. `init` seeds
853
+ REQ-000 with a health scenario so a new project has one worked example; a
854
+ domain pack installed afterwards brings its own requirements, often including
855
+ its own health one, and `include_existing_rows` carries the starter forward
856
+ beside them. The result was two requirements describing the same thing —
857
+ found by dogfooding, where the studio app ended up with REQ-000 and the
858
+ pack's REQ-015 both about deployment health.
859
+
860
+ `--from-pack` knows a pack is coming and skips the starter. A plain `init`
861
+ cannot know, so **`doctor` now reports the leftover** with the row to delete.
862
+ It stays quiet when no pack is installed, and when the row has been filled in
863
+ — an adapted REQ-000 belongs to the project, not to the scaffold.
864
+
865
+ - **`--json` on `report`, `fix` and `req list`.** Twelve commands now honour
866
+ the agent contract, which is the figure `docs/agents.md` had been claiming.
867
+ `report --json` is shorthand for `--format json --stdout`; `fix --json`
868
+ requires `--yes` or `--dry-run`, because prompting an agent that never writes
869
+ to stdin is a hang rather than a question.
870
+ - **`tests/unit/json-contract.test.ts`** — runs all twelve against a real
871
+ scaffolded project and asserts one parseable document on stdout, a `status`
872
+ array, and no snake_case field names at any depth.
873
+
874
+ ### Fixed
875
+
876
+ - **Every harness prompt read "(none declared)".** `harness run` feeds the
877
+ prompt builder by shelling out to `plan --format json`, so the camelCase
878
+ rename above landed on one side of that seam only: the scenario, feature
879
+ file and both artefacts came out blank, and no Gherkin was inlined. The
880
+ builder now accepts both spellings, and a test scaffolds a project, asks the
881
+ real CLI for its plan and feeds the first requirement to the real builder.
882
+
883
+ It went unnoticed because the builder's unit fixture was written in the old
884
+ vocabulary and pinned a shape `plan` no longer produces.
885
+
886
+ - **`init` plus a domain pack produced two requirements for the same thing.**
887
+ The scaffold seeds REQ-000 with a health scenario; a pack installed afterwards
888
+ brings its own, and `include_existing_rows` carried the starter forward beside
889
+ it. `--from-pack` now skips the starter, and `doctor` reports the leftover for
890
+ the plain `init` path — staying quiet when no pack is installed, and when the
891
+ row has been filled in.
892
+
893
+ - **`req list --json` printed the human table and ignored the flag.** Worse
894
+ than rejecting it: the caller believes it received a document. Empty matrix
895
+ cells (`-`, `TBD`) now emit as `null` rather than as strings an agent would
896
+ mistake for paths.
897
+
898
+ ## [0.2.1] — 2026-08-16
899
+
900
+ ### Fixed
901
+
902
+ - **The Docker image is built for arm64 as well as amd64.** `0.2.0` shipped
903
+ amd64 only, so `docker run ghcr.io/rsaglobaltech/csda` — which the README
904
+ tells people to use — failed on every Apple Silicon laptop and every ARM CI
905
+ runner. The workflow needed QEMU alongside buildx to cross-build.
906
+
907
+ The 0.2.0 image tag could not be rebuilt in place: re-running a workflow
908
+ against an old tag checks out the workflow *as it was at that tag*, which did
909
+ not yet have the fix. Hence a patch release rather than moving a published
910
+ tag.
911
+
912
+ ## [0.2.0] — 2026-08-16
913
+
914
+ Three months of work that never shipped. `0.1.4` went to npm in May and the
915
+ change lifecycle, SpecOps contribution loop, agent contract, artefact schemas
916
+ and brownfield onboarding have all landed since.
917
+
918
+ ### ⚠️ Breaking
919
+
920
+ - **Command JSON output is camelCase throughout.** `plan`, `status`, `report`,
921
+ `studio`, `pack infer` and `harness run` emitted `schema_version` and
922
+ `project_dir` alongside nested camelCase keys — `studio` managed both in one
923
+ document. ADR-0017 fixes camelCase, so they are normalised: `schemaVersion`,
924
+ `projectDir`, `nextSteps`, `orphanFeatures`, `nextCommand`, `implementedPct`,
925
+ `byCategory`, `needsTest`, `baselinePresent`.
926
+
927
+ **On-disk formats are unaffected.** `pack.yaml` keeps `schema_version` and
928
+ `.specops.lock` keeps `pack_id` and `specops_version` — those are file
929
+ schemas, not command output, and renaming them would break every existing
930
+ pack and lockfile.
931
+
932
+ If you parse `plan --format json`, update those key names. The flag itself
933
+ still works; `--json` is now accepted everywhere as the shorter spelling.
934
+
935
+ - **`csda --help` shows nine commands, not twenty-four.** (This entry said
936
+ "eight, not twenty-one" until the numbers were counted in August 2026.) The
937
+ full surface is
938
+ behind `--help --all`, or set it as the default with
939
+ `csda config set profile full`.
940
+
941
+ ### Added
942
+
943
+ - **Change lifecycle** — `csda change new | list | show | status | validate |
944
+ archive`. Modify a spec that already shipped through a reviewable delta.
945
+ Archiving merges it into the spec tree, writes the traceability rows and
946
+ materialises the feature files.
947
+ - **`csda change instructions <artifact>`** — the single context engine.
948
+ Returns the template, the rules the validator enforces, the project's stack
949
+ and what writing the artefact unblocks. `harness run` and the generated slash
950
+ commands both consume it.
951
+ - **`csda agents init`** — slash commands and instruction files for Claude
952
+ Code, Cursor, Copilot, Windsurf, Aider, Gemini, Cline and Codex, from one
953
+ definition.
954
+ - **`csda onboard`** — reads an existing repository and proposes the
955
+ capabilities its layout already implies, with the evidence for each.
956
+ - **`csda schema which | init | fork | validate`** — the artefact graph a
957
+ change follows is now configurable. Ships `spec-driven` and `bdd-first`.
958
+ - **`csda update`** — three-way merges generated files after a CLI upgrade,
959
+ preserving local edits and reporting conflicts rather than resolving them.
960
+ - **`csda init --from-pack <repo>@<tag>`** — scaffold and install a pinned pack
961
+ in one step. An unpinned reference is refused.
962
+ - **`csda req`, `csda status`, `csda fix`, `csda studio`, `csda config`,
963
+ `csda completion`** — the daily loop, recovered from an unmerged branch.
964
+ - **`specops diff --as-change`** — review a pack version bump as intent rather
965
+ than as a file diff. **`specops contribute`** sends a local change back
966
+ upstream. **`validate --against-lock`** fails CI on drift from the locked
967
+ version.
968
+ - **`csda adopt`, `csda doctor`, `csda report`, `csda ci init`,
969
+ `csda alm sync`** — brownfield adoption, diagnostics, an HTML coverage
970
+ dashboard, CI gate generation for four providers, and Jira / Azure Boards
971
+ synchronisation.
972
+ - **Maven and Gradle plugins**, an official Docker image, air-gapped pack
973
+ bundles, pack integrity digests, and monorepo validation.
974
+ - **Language context** — `csda config set language es|pt`. Generated prose
975
+ follows it; `SHALL`, `GIVEN`/`WHEN`/`THEN` and the section headings never do.
976
+ - **Language server** (`packages/lsp-spec-driven`) and an IntelliJ scaffold.
977
+ - **`docs/specs/agent-contract.md`** — generated from the source, with CI
978
+ failing when it drifts.
979
+
980
+ ### Fixed
981
+
982
+ - **`csda change archive` deleted user content.** It rebuilt `traceability.md`
983
+ from its rows alone, discarding every other section of the file — the
984
+ non-functional requirements, test inventories and notes — and reported
985
+ success. It now replaces only the matrix table.
986
+ - **`validate` scanned `node_modules/`**, so any project with dependencies
987
+ installed hit false placeholder findings from template libraries. It also
988
+ flagged `.tpl` files, which are unrendered by definition. Both fixed, and the
989
+ scan is now shared with `doctor`, which had drifted into reporting 64 false
990
+ positives.
991
+ - **`DOCKER_SUPPORT=false` left an orphaned devcontainer** pointing at the
992
+ `docker-compose.yml` that `init` had just deleted.
993
+ - **The coverage gate never enforced anything** — `c8` was missing
994
+ `--check-coverage`, so the declared thresholds were decorative.
995
+ - **`doctor` reported every archived requirement as a stale matrix row**,
996
+ because it compared against root `spec.md` alone and did not know about
997
+ `docs/specs/capabilities/`.
998
+ - Windows CI ran unit tests only; it now runs the full suite. The Gradle plugin
999
+ failed `validatePlugins` on Gradle 9. The Pages deploy had been broken since
1000
+ the TypeScript migration.
1001
+
1002
+ ### Changed
1003
+
1004
+ - `docs/` is reorganised into task guides, none over 300 lines. The README is
1005
+ 121 lines, down from 397. `docs/tutorial.md` deliberately stays long: it is
1006
+ one narrative, and splitting it would make it worse.
1007
+ - `validate` diagnostics carry stable snake_case codes and a `fix`, and
1008
+ `--strict-tdd` emits one diagnostic per violation instead of a prose block.
1009
+
1010
+ ## [0.1.4] — 2026-05-15
1011
+
1012
+ Harness prompt prefix, `harness prompt`, audit log, and the bootstrap document.
1013
+
1014
+ ## [0.1.0-beta.1] — 2026-05-06
1015
+
1016
+ First tagged pre-release.