@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.
- package/CHANGELOG.md +1016 -0
- package/README.md +148 -0
- package/bin/specgate.js +2 -0
- package/bin/specgate.ts +383 -0
- package/dist/bin/specgate.js +342 -0
- package/dist/bin/specgate.js.map +1 -0
- package/dist/packages/core/src/application/AddRequirementUseCase.js +24 -0
- package/dist/packages/core/src/application/AddRequirementUseCase.js.map +1 -0
- package/dist/packages/core/src/application/ArchiveChangeUseCase.js +185 -0
- package/dist/packages/core/src/application/ArchiveChangeUseCase.js.map +1 -0
- package/dist/packages/core/src/application/CheckAgainstLockUseCase.js +134 -0
- package/dist/packages/core/src/application/CheckAgainstLockUseCase.js.map +1 -0
- package/dist/packages/core/src/application/GenerateAgentPromptUseCase.js +25 -0
- package/dist/packages/core/src/application/GenerateAgentPromptUseCase.js.map +1 -0
- package/dist/packages/core/src/application/GeneratePlanUseCase.js +135 -0
- package/dist/packages/core/src/application/GeneratePlanUseCase.js.map +1 -0
- package/dist/packages/core/src/application/LinkRequirementUseCase.js +25 -0
- package/dist/packages/core/src/application/LinkRequirementUseCase.js.map +1 -0
- package/dist/packages/core/src/application/RemovePackUseCase.js +28 -0
- package/dist/packages/core/src/application/RemovePackUseCase.js.map +1 -0
- package/dist/packages/core/src/application/UpdateRequirementStatusUseCase.js +37 -0
- package/dist/packages/core/src/application/UpdateRequirementStatusUseCase.js.map +1 -0
- package/dist/packages/core/src/application/ValidateChangeUseCase.js +86 -0
- package/dist/packages/core/src/application/ValidateChangeUseCase.js.map +1 -0
- package/dist/packages/core/src/application/ValidateProjectUseCase.js +101 -0
- package/dist/packages/core/src/application/ValidateProjectUseCase.js.map +1 -0
- package/dist/packages/core/src/application/ports/IDomainPackRepository.js +3 -0
- package/dist/packages/core/src/application/ports/IDomainPackRepository.js.map +1 -0
- package/dist/packages/core/src/application/ports/IHarnessConfigRepository.js +3 -0
- package/dist/packages/core/src/application/ports/IHarnessConfigRepository.js.map +1 -0
- package/dist/packages/core/src/application/ports/ILockfileRepository.js +3 -0
- package/dist/packages/core/src/application/ports/ILockfileRepository.js.map +1 -0
- package/dist/packages/core/src/application/ports/IManifestRepository.js +3 -0
- package/dist/packages/core/src/application/ports/IManifestRepository.js.map +1 -0
- package/dist/packages/core/src/application/ports/IProjectRepository.js +3 -0
- package/dist/packages/core/src/application/ports/IProjectRepository.js.map +1 -0
- package/dist/packages/core/src/application/ports/IRequirementGraphRepository.js +3 -0
- package/dist/packages/core/src/application/ports/IRequirementGraphRepository.js.map +1 -0
- package/dist/packages/core/src/application/ports/ITraceabilityRepository.js +3 -0
- package/dist/packages/core/src/application/ports/ITraceabilityRepository.js.map +1 -0
- package/dist/packages/core/src/domain/AgentPrompt.js +79 -0
- package/dist/packages/core/src/domain/AgentPrompt.js.map +1 -0
- package/dist/packages/core/src/domain/ArchivePlan.js +26 -0
- package/dist/packages/core/src/domain/ArchivePlan.js.map +1 -0
- package/dist/packages/core/src/domain/AuthoringScope.js +48 -0
- package/dist/packages/core/src/domain/AuthoringScope.js.map +1 -0
- package/dist/packages/core/src/domain/ChangeTemplates.js +133 -0
- package/dist/packages/core/src/domain/ChangeTemplates.js.map +1 -0
- package/dist/packages/core/src/domain/CucumberMessages.js +256 -0
- package/dist/packages/core/src/domain/CucumberMessages.js.map +1 -0
- package/dist/packages/core/src/domain/DeclaredArtifacts.js +117 -0
- package/dist/packages/core/src/domain/DeclaredArtifacts.js.map +1 -0
- package/dist/packages/core/src/domain/DeltaSpec.js +219 -0
- package/dist/packages/core/src/domain/DeltaSpec.js.map +1 -0
- package/dist/packages/core/src/domain/Diagnostic.js +75 -0
- package/dist/packages/core/src/domain/Diagnostic.js.map +1 -0
- package/dist/packages/core/src/domain/DomainPack.js +62 -0
- package/dist/packages/core/src/domain/DomainPack.js.map +1 -0
- package/dist/packages/core/src/domain/EmptyAttempt.js +60 -0
- package/dist/packages/core/src/domain/EmptyAttempt.js.map +1 -0
- package/dist/packages/core/src/domain/FileChangeSet.js +37 -0
- package/dist/packages/core/src/domain/FileChangeSet.js.map +1 -0
- package/dist/packages/core/src/domain/Gherkin.js +272 -0
- package/dist/packages/core/src/domain/Gherkin.js.map +1 -0
- package/dist/packages/core/src/domain/GherkinDialects.js +97 -0
- package/dist/packages/core/src/domain/GherkinDialects.js.map +1 -0
- package/dist/packages/core/src/domain/GherkinQuality.js +160 -0
- package/dist/packages/core/src/domain/GherkinQuality.js.map +1 -0
- package/dist/packages/core/src/domain/GherkinTags.js +119 -0
- package/dist/packages/core/src/domain/GherkinTags.js.map +1 -0
- package/dist/packages/core/src/domain/GitSafety.js +77 -0
- package/dist/packages/core/src/domain/GitSafety.js.map +1 -0
- package/dist/packages/core/src/domain/HarnessConfig.js +58 -0
- package/dist/packages/core/src/domain/HarnessConfig.js.map +1 -0
- package/dist/packages/core/src/domain/HarnessReport.js +162 -0
- package/dist/packages/core/src/domain/HarnessReport.js.map +1 -0
- package/dist/packages/core/src/domain/HarnessRun.js +154 -0
- package/dist/packages/core/src/domain/HarnessRun.js.map +1 -0
- package/dist/packages/core/src/domain/InboundChange.js +127 -0
- package/dist/packages/core/src/domain/InboundChange.js.map +1 -0
- package/dist/packages/core/src/domain/Language.js +112 -0
- package/dist/packages/core/src/domain/Language.js.map +1 -0
- package/dist/packages/core/src/domain/Lockfile.js +64 -0
- package/dist/packages/core/src/domain/Lockfile.js.map +1 -0
- package/dist/packages/core/src/domain/PackContribution.js +106 -0
- package/dist/packages/core/src/domain/PackContribution.js.map +1 -0
- package/dist/packages/core/src/domain/PackDelta.js +298 -0
- package/dist/packages/core/src/domain/PackDelta.js.map +1 -0
- package/dist/packages/core/src/domain/PackSpec.js +481 -0
- package/dist/packages/core/src/domain/PackSpec.js.map +1 -0
- package/dist/packages/core/src/domain/ProfileMatch.js +87 -0
- package/dist/packages/core/src/domain/ProfileMatch.js.map +1 -0
- package/dist/packages/core/src/domain/Reconciliation.js +72 -0
- package/dist/packages/core/src/domain/Reconciliation.js.map +1 -0
- package/dist/packages/core/src/domain/RequirementGraph.js +197 -0
- package/dist/packages/core/src/domain/RequirementGraph.js.map +1 -0
- package/dist/packages/core/src/domain/RequirementPlan.js +85 -0
- package/dist/packages/core/src/domain/RequirementPlan.js.map +1 -0
- package/dist/packages/core/src/domain/RequirementReadiness.js +115 -0
- package/dist/packages/core/src/domain/RequirementReadiness.js.map +1 -0
- package/dist/packages/core/src/domain/RequirementSyntax.js +91 -0
- package/dist/packages/core/src/domain/RequirementSyntax.js.map +1 -0
- package/dist/packages/core/src/domain/ResumeState.js +115 -0
- package/dist/packages/core/src/domain/ResumeState.js.map +1 -0
- package/dist/packages/core/src/domain/RunBudget.js +103 -0
- package/dist/packages/core/src/domain/RunBudget.js.map +1 -0
- package/dist/packages/core/src/domain/SpecDiff.js +48 -0
- package/dist/packages/core/src/domain/SpecDiff.js.map +1 -0
- package/dist/packages/core/src/domain/SpecParser.js +406 -0
- package/dist/packages/core/src/domain/SpecParser.js.map +1 -0
- package/dist/packages/core/src/domain/SpecopsManifest.js +90 -0
- package/dist/packages/core/src/domain/SpecopsManifest.js.map +1 -0
- package/dist/packages/core/src/domain/TraceabilityFormat.js +317 -0
- package/dist/packages/core/src/domain/TraceabilityFormat.js.map +1 -0
- package/dist/packages/core/src/domain/TraceabilityMatrix.js +200 -0
- package/dist/packages/core/src/domain/TraceabilityMatrix.js.map +1 -0
- package/dist/packages/core/src/domain/TraceabilityMerge.js +180 -0
- package/dist/packages/core/src/domain/TraceabilityMerge.js.map +1 -0
- package/dist/packages/core/src/domain/ValidationReport.js +53 -0
- package/dist/packages/core/src/domain/ValidationReport.js.map +1 -0
- package/dist/packages/core/src/domain/ValueAnnotations.js +138 -0
- package/dist/packages/core/src/domain/ValueAnnotations.js.map +1 -0
- package/dist/packages/core/src/domain/WriteScope.js +155 -0
- package/dist/packages/core/src/domain/WriteScope.js.map +1 -0
- package/dist/packages/core/src/domain/YamlLite.js +226 -0
- package/dist/packages/core/src/domain/YamlLite.js.map +1 -0
- package/dist/packages/core/src/index.js +120 -0
- package/dist/packages/core/src/index.js.map +1 -0
- package/dist/packages/core/src/infrastructure/ChangeWorkspace.js +276 -0
- package/dist/packages/core/src/infrastructure/ChangeWorkspace.js.map +1 -0
- package/dist/packages/core/src/infrastructure/ConsoleReporter.js +19 -0
- package/dist/packages/core/src/infrastructure/ConsoleReporter.js.map +1 -0
- package/dist/packages/core/src/infrastructure/DirectorySnapshot.js +106 -0
- package/dist/packages/core/src/infrastructure/DirectorySnapshot.js.map +1 -0
- package/dist/packages/core/src/infrastructure/DiskDomainPackRepository.js +57 -0
- package/dist/packages/core/src/infrastructure/DiskDomainPackRepository.js.map +1 -0
- package/dist/packages/core/src/infrastructure/DiskHarnessConfigRepository.js +58 -0
- package/dist/packages/core/src/infrastructure/DiskHarnessConfigRepository.js.map +1 -0
- package/dist/packages/core/src/infrastructure/DiskLanguageRepository.js +69 -0
- package/dist/packages/core/src/infrastructure/DiskLanguageRepository.js.map +1 -0
- package/dist/packages/core/src/infrastructure/DiskLockfileRepository.js +64 -0
- package/dist/packages/core/src/infrastructure/DiskLockfileRepository.js.map +1 -0
- package/dist/packages/core/src/infrastructure/DiskManifestRepository.js +88 -0
- package/dist/packages/core/src/infrastructure/DiskManifestRepository.js.map +1 -0
- package/dist/packages/core/src/infrastructure/DiskPackDeltaRepository.js +138 -0
- package/dist/packages/core/src/infrastructure/DiskPackDeltaRepository.js.map +1 -0
- package/dist/packages/core/src/infrastructure/DiskPackRepository.js +130 -0
- package/dist/packages/core/src/infrastructure/DiskPackRepository.js.map +1 -0
- package/dist/packages/core/src/infrastructure/DiskProjectRepository.js +127 -0
- package/dist/packages/core/src/infrastructure/DiskProjectRepository.js.map +1 -0
- package/dist/packages/core/src/infrastructure/DiskRequirementGraphRepository.js +124 -0
- package/dist/packages/core/src/infrastructure/DiskRequirementGraphRepository.js.map +1 -0
- package/dist/packages/core/src/infrastructure/DiskTraceabilityRepository.js +53 -0
- package/dist/packages/core/src/infrastructure/DiskTraceabilityRepository.js.map +1 -0
- package/dist/packages/core/src/infrastructure/GitContributionStager.js +99 -0
- package/dist/packages/core/src/infrastructure/GitContributionStager.js.map +1 -0
- package/dist/packages/core/src/infrastructure/GitMergeDriver.js +103 -0
- package/dist/packages/core/src/infrastructure/GitMergeDriver.js.map +1 -0
- package/dist/packages/core/src/infrastructure/HarnessConfigFile.js +348 -0
- package/dist/packages/core/src/infrastructure/HarnessConfigFile.js.map +1 -0
- package/dist/packages/core/src/infrastructure/PackChangeDeposit.js +106 -0
- package/dist/packages/core/src/infrastructure/PackChangeDeposit.js.map +1 -0
- package/dist/packages/core/src/infrastructure/RemotePackResolver.js +181 -0
- package/dist/packages/core/src/infrastructure/RemotePackResolver.js.map +1 -0
- package/dist/packages/core/src/infrastructure/SpecopsConfigFile.js +94 -0
- package/dist/packages/core/src/infrastructure/SpecopsConfigFile.js.map +1 -0
- package/dist/packages/core/test/unit/authoring-scope.test.js +102 -0
- package/dist/packages/core/test/unit/authoring-scope.test.js.map +1 -0
- package/dist/packages/core/test/unit/change-templates.test.js +96 -0
- package/dist/packages/core/test/unit/change-templates.test.js.map +1 -0
- package/dist/packages/core/test/unit/cucumber-messages.test.js +232 -0
- package/dist/packages/core/test/unit/cucumber-messages.test.js.map +1 -0
- package/dist/packages/core/test/unit/declared-artifacts.test.js +124 -0
- package/dist/packages/core/test/unit/declared-artifacts.test.js.map +1 -0
- package/dist/packages/core/test/unit/empty-attempt.test.js +79 -0
- package/dist/packages/core/test/unit/empty-attempt.test.js.map +1 -0
- package/dist/packages/core/test/unit/gherkin-dialects.test.js +115 -0
- package/dist/packages/core/test/unit/gherkin-dialects.test.js.map +1 -0
- package/dist/packages/core/test/unit/gherkin-keyword-case.test.js +110 -0
- package/dist/packages/core/test/unit/gherkin-keyword-case.test.js.map +1 -0
- package/dist/packages/core/test/unit/gherkin-quality.test.js +151 -0
- package/dist/packages/core/test/unit/gherkin-quality.test.js.map +1 -0
- package/dist/packages/core/test/unit/gherkin-tags.test.js +127 -0
- package/dist/packages/core/test/unit/gherkin-tags.test.js.map +1 -0
- package/dist/packages/core/test/unit/git-safety.test.js +104 -0
- package/dist/packages/core/test/unit/git-safety.test.js.map +1 -0
- package/dist/packages/core/test/unit/harness-report.test.js +192 -0
- package/dist/packages/core/test/unit/harness-report.test.js.map +1 -0
- package/dist/packages/core/test/unit/harness-roles.test.js +86 -0
- package/dist/packages/core/test/unit/harness-roles.test.js.map +1 -0
- package/dist/packages/core/test/unit/inbound-change.test.js +145 -0
- package/dist/packages/core/test/unit/inbound-change.test.js.map +1 -0
- package/dist/packages/core/test/unit/matrix-dependencies.test.js +100 -0
- package/dist/packages/core/test/unit/matrix-dependencies.test.js.map +1 -0
- package/dist/packages/core/test/unit/profile-match.test.js +115 -0
- package/dist/packages/core/test/unit/profile-match.test.js.map +1 -0
- package/dist/packages/core/test/unit/reconciliation.test.js +112 -0
- package/dist/packages/core/test/unit/reconciliation.test.js.map +1 -0
- package/dist/packages/core/test/unit/requirement-readiness.test.js +161 -0
- package/dist/packages/core/test/unit/requirement-readiness.test.js.map +1 -0
- package/dist/packages/core/test/unit/resume-state.test.js +124 -0
- package/dist/packages/core/test/unit/resume-state.test.js.map +1 -0
- package/dist/packages/core/test/unit/run-budget.test.js +113 -0
- package/dist/packages/core/test/unit/run-budget.test.js.map +1 -0
- package/dist/packages/core/test/unit/traceability-merge.test.js +159 -0
- package/dist/packages/core/test/unit/traceability-merge.test.js.map +1 -0
- package/dist/packages/core/test/unit/validate-project.test.js +156 -0
- package/dist/packages/core/test/unit/validate-project.test.js.map +1 -0
- package/dist/packages/core/test/unit/value-annotations.test.js +149 -0
- package/dist/packages/core/test/unit/value-annotations.test.js.map +1 -0
- package/dist/packages/core/test/unit/write-scope.test.js +165 -0
- package/dist/packages/core/test/unit/write-scope.test.js.map +1 -0
- package/dist/packages/core/test/unit/yaml-lite.test.js +78 -0
- package/dist/packages/core/test/unit/yaml-lite.test.js.map +1 -0
- package/dist/scripts/adopt_project.js +11 -0
- package/dist/scripts/adopt_project.js.map +1 -0
- package/dist/scripts/agents/commands.js +100 -0
- package/dist/scripts/agents/commands.js.map +1 -0
- package/dist/scripts/agents/init.js +482 -0
- package/dist/scripts/agents/init.js.map +1 -0
- package/dist/scripts/alm/cli.js +154 -0
- package/dist/scripts/alm/cli.js.map +1 -0
- package/dist/scripts/alm/clients.js +30 -0
- package/dist/scripts/alm/clients.js.map +1 -0
- package/dist/scripts/alm/core.js +258 -0
- package/dist/scripts/alm/core.js.map +1 -0
- package/dist/scripts/alm/port.js +116 -0
- package/dist/scripts/alm/port.js.map +1 -0
- package/dist/scripts/alm/providers/azure.js +79 -0
- package/dist/scripts/alm/providers/azure.js.map +1 -0
- package/dist/scripts/alm/providers/github.js +124 -0
- package/dist/scripts/alm/providers/github.js.map +1 -0
- package/dist/scripts/alm/providers/http-client.js +47 -0
- package/dist/scripts/alm/providers/http-client.js.map +1 -0
- package/dist/scripts/alm/providers/index.js +107 -0
- package/dist/scripts/alm/providers/index.js.map +1 -0
- package/dist/scripts/alm/providers/jira.js +129 -0
- package/dist/scripts/alm/providers/jira.js.map +1 -0
- package/dist/scripts/bundle_pack.js +10 -0
- package/dist/scripts/bundle_pack.js.map +1 -0
- package/dist/scripts/change/archive.js +68 -0
- package/dist/scripts/change/archive.js.map +1 -0
- package/dist/scripts/change/artifacts.js +143 -0
- package/dist/scripts/change/artifacts.js.map +1 -0
- package/dist/scripts/change/cli.js +39 -0
- package/dist/scripts/change/cli.js.map +1 -0
- package/dist/scripts/change/delta.js +20 -0
- package/dist/scripts/change/delta.js.map +1 -0
- package/dist/scripts/change/instructions.js +339 -0
- package/dist/scripts/change/instructions.js.map +1 -0
- package/dist/scripts/ci_init.js +12 -0
- package/dist/scripts/ci_init.js.map +1 -0
- package/dist/scripts/cli/commands/alm/PullCommand.js +238 -0
- package/dist/scripts/cli/commands/alm/PullCommand.js.map +1 -0
- package/dist/scripts/cli/commands/change/ChangeCommand.js +867 -0
- package/dist/scripts/cli/commands/change/ChangeCommand.js.map +1 -0
- package/dist/scripts/cli/commands/config/CiInitCommand.js +144 -0
- package/dist/scripts/cli/commands/config/CiInitCommand.js.map +1 -0
- package/dist/scripts/cli/commands/config/CompletionCommand.js +160 -0
- package/dist/scripts/cli/commands/config/CompletionCommand.js.map +1 -0
- package/dist/scripts/cli/commands/config/ConfigInitCommand.js +108 -0
- package/dist/scripts/cli/commands/config/ConfigInitCommand.js.map +1 -0
- package/dist/scripts/cli/commands/config/ConfigSetCommand.js +166 -0
- package/dist/scripts/cli/commands/config/ConfigSetCommand.js.map +1 -0
- package/dist/scripts/cli/commands/config/GenAgentContractCommand.js +212 -0
- package/dist/scripts/cli/commands/config/GenAgentContractCommand.js.map +1 -0
- package/dist/scripts/cli/commands/harness/RunCommand.js +1922 -0
- package/dist/scripts/cli/commands/harness/RunCommand.js.map +1 -0
- package/dist/scripts/cli/commands/mcp/McpInstallCommand.js +114 -0
- package/dist/scripts/cli/commands/mcp/McpInstallCommand.js.map +1 -0
- package/dist/scripts/cli/commands/mcp/index.js +29 -0
- package/dist/scripts/cli/commands/mcp/index.js.map +1 -0
- package/dist/scripts/cli/commands/pack/BundlePackCommand.js +59 -0
- package/dist/scripts/cli/commands/pack/BundlePackCommand.js.map +1 -0
- package/dist/scripts/cli/commands/pack/ExpandDomainPackCommand.js +559 -0
- package/dist/scripts/cli/commands/pack/ExpandDomainPackCommand.js.map +1 -0
- package/dist/scripts/cli/commands/pack/InferPackCommand.js +304 -0
- package/dist/scripts/cli/commands/pack/InferPackCommand.js.map +1 -0
- package/dist/scripts/cli/commands/pack/InitPackCommand.js +368 -0
- package/dist/scripts/cli/commands/pack/InitPackCommand.js.map +1 -0
- package/dist/scripts/cli/commands/pack/LintPackCommand.js +631 -0
- package/dist/scripts/cli/commands/pack/LintPackCommand.js.map +1 -0
- package/dist/scripts/cli/commands/pack/pack-args.js +83 -0
- package/dist/scripts/cli/commands/pack/pack-args.js.map +1 -0
- package/dist/scripts/cli/commands/project/AdoptCommand.js +414 -0
- package/dist/scripts/cli/commands/project/AdoptCommand.js.map +1 -0
- package/dist/scripts/cli/commands/project/InitFromPackCommand.js +188 -0
- package/dist/scripts/cli/commands/project/InitFromPackCommand.js.map +1 -0
- package/dist/scripts/cli/commands/project/InitProjectCommand.js +791 -0
- package/dist/scripts/cli/commands/project/InitProjectCommand.js.map +1 -0
- package/dist/scripts/cli/commands/project/OnboardCommand.js +655 -0
- package/dist/scripts/cli/commands/project/OnboardCommand.js.map +1 -0
- package/dist/scripts/cli/commands/project/UpdateCommand.js +206 -0
- package/dist/scripts/cli/commands/project/UpdateCommand.js.map +1 -0
- package/dist/scripts/cli/commands/project/WizardCommand.js +166 -0
- package/dist/scripts/cli/commands/project/WizardCommand.js.map +1 -0
- package/dist/scripts/cli/commands/quality/DoctorCommand.js +553 -0
- package/dist/scripts/cli/commands/quality/DoctorCommand.js.map +1 -0
- package/dist/scripts/cli/commands/quality/FixCommand.js +201 -0
- package/dist/scripts/cli/commands/quality/FixCommand.js.map +1 -0
- package/dist/scripts/cli/commands/quality/LicenseCheckCommand.js +187 -0
- package/dist/scripts/cli/commands/quality/LicenseCheckCommand.js.map +1 -0
- package/dist/scripts/cli/commands/quality/ReportCommand.js +557 -0
- package/dist/scripts/cli/commands/quality/ReportCommand.js.map +1 -0
- package/dist/scripts/cli/commands/quality/ValidateSpecsCommand.js +764 -0
- package/dist/scripts/cli/commands/quality/ValidateSpecsCommand.js.map +1 -0
- package/dist/scripts/cli/commands/spec/DoneCommand.js +116 -0
- package/dist/scripts/cli/commands/spec/DoneCommand.js.map +1 -0
- package/dist/scripts/cli/commands/spec/PlanCommand.js +397 -0
- package/dist/scripts/cli/commands/spec/PlanCommand.js.map +1 -0
- package/dist/scripts/cli/commands/spec/ReqCommand.js +303 -0
- package/dist/scripts/cli/commands/spec/ReqCommand.js.map +1 -0
- package/dist/scripts/cli/commands/spec/StatusCommand.js +206 -0
- package/dist/scripts/cli/commands/spec/StatusCommand.js.map +1 -0
- package/dist/scripts/cli/commands/spec/StudioCommand.js +241 -0
- package/dist/scripts/cli/commands/spec/StudioCommand.js.map +1 -0
- package/dist/scripts/cli/commands/specops/ContributeCommand.js +313 -0
- package/dist/scripts/cli/commands/specops/ContributeCommand.js.map +1 -0
- package/dist/scripts/cli/commands/specops/DiffCommand.js +394 -0
- package/dist/scripts/cli/commands/specops/DiffCommand.js.map +1 -0
- package/dist/scripts/cli/commands/specops/SyncCommand.js +380 -0
- package/dist/scripts/cli/commands/specops/SyncCommand.js.map +1 -0
- package/dist/scripts/completion.js +24 -0
- package/dist/scripts/completion.js.map +1 -0
- package/dist/scripts/config_init.js +12 -0
- package/dist/scripts/config_init.js.map +1 -0
- package/dist/scripts/config_set.js +20 -0
- package/dist/scripts/config_set.js.map +1 -0
- package/dist/scripts/docs/blocks.js +137 -0
- package/dist/scripts/docs/blocks.js.map +1 -0
- package/dist/scripts/docs/build-site.js +425 -0
- package/dist/scripts/docs/build-site.js.map +1 -0
- package/dist/scripts/docs/nav.js +198 -0
- package/dist/scripts/docs/nav.js.map +1 -0
- package/dist/scripts/docs/record-terminal.js +477 -0
- package/dist/scripts/docs/record-terminal.js.map +1 -0
- package/dist/scripts/docs/terminal-storyboard.js +121 -0
- package/dist/scripts/docs/terminal-storyboard.js.map +1 -0
- package/dist/scripts/doctor.js +14 -0
- package/dist/scripts/doctor.js.map +1 -0
- package/dist/scripts/done.js +17 -0
- package/dist/scripts/done.js.map +1 -0
- package/dist/scripts/expand_domain_pack.js +18 -0
- package/dist/scripts/expand_domain_pack.js.map +1 -0
- package/dist/scripts/fix.js +12 -0
- package/dist/scripts/fix.js.map +1 -0
- package/dist/scripts/gen_agent_contract.js +14 -0
- package/dist/scripts/gen_agent_contract.js.map +1 -0
- package/dist/scripts/gen_mcp_tools.js +264 -0
- package/dist/scripts/gen_mcp_tools.js.map +1 -0
- package/dist/scripts/harness/init.js +358 -0
- package/dist/scripts/harness/init.js.map +1 -0
- package/dist/scripts/harness/prompt.js +18 -0
- package/dist/scripts/harness/prompt.js.map +1 -0
- package/dist/scripts/harness/report.js +323 -0
- package/dist/scripts/harness/report.js.map +1 -0
- package/dist/scripts/harness/run.js +33 -0
- package/dist/scripts/harness/run.js.map +1 -0
- package/dist/scripts/infer_pack.js +17 -0
- package/dist/scripts/infer_pack.js.map +1 -0
- package/dist/scripts/init_from_pack.js +16 -0
- package/dist/scripts/init_from_pack.js.map +1 -0
- package/dist/scripts/init_pack.js +16 -0
- package/dist/scripts/init_pack.js.map +1 -0
- package/dist/scripts/init_project.js +17 -0
- package/dist/scripts/init_project.js.map +1 -0
- package/dist/scripts/lib/agent.js +99 -0
- package/dist/scripts/lib/agent.js.map +1 -0
- package/dist/scripts/lib/capability-specs.js +80 -0
- package/dist/scripts/lib/capability-specs.js.map +1 -0
- package/dist/scripts/lib/command.js +17 -0
- package/dist/scripts/lib/command.js.map +1 -0
- package/dist/scripts/lib/diagnostics.js +62 -0
- package/dist/scripts/lib/diagnostics.js.map +1 -0
- package/dist/scripts/lib/monorepo-fanout.js +118 -0
- package/dist/scripts/lib/monorepo-fanout.js.map +1 -0
- package/dist/scripts/lib/placeholders.js +190 -0
- package/dist/scripts/lib/placeholders.js.map +1 -0
- package/dist/scripts/lib/project-root.js +124 -0
- package/dist/scripts/lib/project-root.js.map +1 -0
- package/dist/scripts/lib/requirement-graph.js +31 -0
- package/dist/scripts/lib/requirement-graph.js.map +1 -0
- package/dist/scripts/lib/surface.js +609 -0
- package/dist/scripts/lib/surface.js.map +1 -0
- package/dist/scripts/license_check.js +15 -0
- package/dist/scripts/license_check.js.map +1 -0
- package/dist/scripts/lint_pack.js +18 -0
- package/dist/scripts/lint_pack.js.map +1 -0
- package/dist/scripts/merge-traceability.js +106 -0
- package/dist/scripts/merge-traceability.js.map +1 -0
- package/dist/scripts/onboard.js +22 -0
- package/dist/scripts/onboard.js.map +1 -0
- package/dist/scripts/plan.js +17 -0
- package/dist/scripts/plan.js.map +1 -0
- package/dist/scripts/plugin/gate-hook.js +171 -0
- package/dist/scripts/plugin/gate-hook.js.map +1 -0
- package/dist/scripts/report.js +17 -0
- package/dist/scripts/report.js.map +1 -0
- package/dist/scripts/req.js +22 -0
- package/dist/scripts/req.js.map +1 -0
- package/dist/scripts/schema/cli.js +215 -0
- package/dist/scripts/schema/cli.js.map +1 -0
- package/dist/scripts/schema/registry.js +264 -0
- package/dist/scripts/schema/registry.js.map +1 -0
- package/dist/scripts/specops/add.js +180 -0
- package/dist/scripts/specops/add.js.map +1 -0
- package/dist/scripts/specops/against_lock.js +100 -0
- package/dist/scripts/specops/against_lock.js.map +1 -0
- package/dist/scripts/specops/as_change.js +49 -0
- package/dist/scripts/specops/as_change.js.map +1 -0
- package/dist/scripts/specops/contribute.js +24 -0
- package/dist/scripts/specops/contribute.js.map +1 -0
- package/dist/scripts/specops/diff.js +32 -0
- package/dist/scripts/specops/diff.js.map +1 -0
- package/dist/scripts/specops/lock.js +39 -0
- package/dist/scripts/specops/lock.js.map +1 -0
- package/dist/scripts/specops/manifest.js +90 -0
- package/dist/scripts/specops/manifest.js.map +1 -0
- package/dist/scripts/specops/remove.js +102 -0
- package/dist/scripts/specops/remove.js.map +1 -0
- package/dist/scripts/specops/sync.js +27 -0
- package/dist/scripts/specops/sync.js.map +1 -0
- package/dist/scripts/specops/verify.js +149 -0
- package/dist/scripts/specops/verify.js.map +1 -0
- package/dist/scripts/status.js +17 -0
- package/dist/scripts/status.js.map +1 -0
- package/dist/scripts/studio.js +14 -0
- package/dist/scripts/studio.js.map +1 -0
- package/dist/scripts/update.js +17 -0
- package/dist/scripts/update.js.map +1 -0
- package/dist/scripts/validate_specs.js +10 -0
- package/dist/scripts/validate_specs.js.map +1 -0
- package/examples/project.config.example +19 -0
- package/examples/project.yaml.example +17 -0
- package/package.json +105 -0
- package/templates/adopt/AI_RULES.md.tpl +27 -0
- package/templates/adopt/adr-readme.md.tpl +5 -0
- package/templates/adopt/baseline.feature.tpl +9 -0
- package/templates/adopt/spec.md.tpl +25 -0
- package/templates/adopt/traceability.md.tpl +11 -0
- package/templates/backend/AI_RULES.md.tpl +35 -0
- package/templates/backend/features/core/health.feature.tpl +7 -0
- package/templates/base/.devcontainer/devcontainer.json.tpl +18 -0
- package/templates/base/.dockerignore.tpl +11 -0
- package/templates/base/.env.dev.app.tpl +13 -0
- package/templates/base/.env.dev.infra.tpl +6 -0
- package/templates/base/.env.dev.tpl +16 -0
- package/templates/base/.env.example.tpl +17 -0
- package/templates/base/.env.feature.app.tpl +11 -0
- package/templates/base/.env.feature.infra.tpl +4 -0
- package/templates/base/.env.feature.tpl +16 -0
- package/templates/base/.env.prod.app.tpl +13 -0
- package/templates/base/.env.prod.infra.tpl +6 -0
- package/templates/base/.env.prod.tpl +16 -0
- package/templates/base/.github/workflows/specs.yml.tpl +26 -0
- package/templates/base/.gitignore.tpl +9 -0
- package/templates/base/.pre-commit-config.yaml.tpl +10 -0
- package/templates/base/AGENTS.md.tpl +32 -0
- package/templates/base/README.md.tpl +32 -0
- package/templates/base/docker-compose.yml.tpl +13 -0
- package/templates/base/docs/specs/adr/README.md.tpl +10 -0
- package/templates/base/docs/specs/aggregates.md.tpl +5 -0
- package/templates/base/docs/specs/commands.md.tpl +13 -0
- package/templates/base/docs/specs/domain-model.md.tpl +30 -0
- package/templates/base/docs/specs/events.md.tpl +5 -0
- package/templates/base/docs/specs/review-checklist.md.tpl +18 -0
- package/templates/base/docs/specs/runtime-environments.md.tpl +26 -0
- package/templates/base/docs/specs/status-model.md.tpl +16 -0
- package/templates/base/docs/specs/traceability.md.tpl +7 -0
- package/templates/base/docs/specs/use-cases.md.tpl +5 -0
- package/templates/base/spec.md.tpl +63 -0
- package/templates/ci/azure.yml.tpl +40 -0
- package/templates/ci/github.yml.tpl +40 -0
- package/templates/ci/gitlab.yml.tpl +21 -0
- package/templates/ci/jenkins.tpl +35 -0
- package/templates/contracts/AI_RULES.md.tpl +55 -0
- package/templates/contracts/asyncapi-stub.yaml.tpl +24 -0
- package/templates/contracts/contract-traceability.md.tpl +10 -0
- package/templates/contracts/openapi-stub.yaml.tpl +29 -0
- package/templates/contracts/pacts-gitkeep.tpl +0 -0
- package/templates/contracts/test-strategy.md.tpl +94 -0
- package/templates/frontend/AI_RULES.md.tpl +34 -0
- package/templates/frontend/features/core/health.feature.tpl +6 -0
- package/templates/harness/harness.config.yaml.tpl +74 -0
- package/templates/harness/prompt-prefix.md.tpl +60 -0
- package/templates/mobile/AI_RULES.md.tpl +56 -0
- package/templates/mobile/features/core/health.feature.tpl +7 -0
- package/templates/modules/auth/backend/registration_and_login.feature.tpl +10 -0
- package/templates/modules/auth/frontend/login.feature.tpl +5 -0
- package/templates/modules/billing/backend/billing_settlement.feature.tpl +5 -0
- package/templates/modules/billing/frontend/billing_summary.feature.tpl +5 -0
- package/templates/modules/dashboard/backend/dashboard_kpi.feature.tpl +5 -0
- package/templates/modules/dashboard/frontend/dashboard.feature.tpl +5 -0
- 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.
|