@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/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# ⬡ Specgate
|
|
4
|
+
|
|
5
|
+
**Specs as executable contracts — requirements, scenarios and traceability that CI enforces.**
|
|
6
|
+
|
|
7
|
+
[](https://github.com/rsaglobaltech/specgate/actions/workflows/ci.yml)
|
|
8
|
+
[](https://www.npmjs.com/package/specgate)
|
|
9
|
+
[](https://www.npmjs.com/package/specgate)
|
|
10
|
+
[](https://rsaglobaltech.github.io/specgate/)
|
|
11
|
+
[](#-license)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
> Stop coding before requirements are operationally clear. Every requirement
|
|
16
|
+
> maps to a scenario, a domain artefact, an implementation and a test — and the
|
|
17
|
+
> gate fails when one is missing.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## ⚡ Start
|
|
22
|
+
|
|
23
|
+
> **Just renamed** ([ADR-0024](docs/specs/adr/0024-the-tool-is-renamed-the-format-is-not.md)): until the
|
|
24
|
+
> first release under the new name the registries still hold `create-spec-driven-app` and the `csda` image — both kept as aliases.
|
|
25
|
+
|
|
26
|
+
**Existing codebase** — the common enterprise case:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
cd your-repo
|
|
30
|
+
npx @rsaglobaltech/specgate@latest onboard # reads the repo, proposes its capabilities
|
|
31
|
+
npx @rsaglobaltech/specgate@latest adopt # writes the spec skeleton, touches no code
|
|
32
|
+
npx @rsaglobaltech/specgate@latest validate .
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**New project:**
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx @rsaglobaltech/specgate@latest init # interactive wizard
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Requires **Node.js ≥ 22** — or none at all with the Docker image:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
docker run --rm -v "$PWD:/workspace" ghcr.io/rsaglobaltech/specgate validate . --strict-tdd
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
→ [Getting started](docs/getting-started.md) · [Quickstart for joiners](docs/quickstart.md)
|
|
48
|
+
|
|
49
|
+
## 🪜 Adopt one level at a time
|
|
50
|
+
|
|
51
|
+
Each level is useful on its own and never requires the ones above it.
|
|
52
|
+
|
|
53
|
+
| Level | You get | Commands | Cost |
|
|
54
|
+
| --- | --- | --- | --- |
|
|
55
|
+
| **L1** | Traceable specs in your repo | `onboard`, `adopt` | ~1 hour |
|
|
56
|
+
| **L2** | A PR gate enforcing spec and test coverage | `validate --strict-tdd` | ~1 hour |
|
|
57
|
+
| **L3** | Versioned, reusable domain requirements | `specops add / sync / diff` | ~1 day |
|
|
58
|
+
| **L4** | Agent-driven delivery, one requirement at a time | `agents init`, `harness run` | ~1 week |
|
|
59
|
+
|
|
60
|
+
## 🛠️ What it does
|
|
61
|
+
|
|
62
|
+
**A daily loop, not a one-shot scaffolder.** `specgate status` says where the
|
|
63
|
+
project stands and what to run next; `specgate plan` is the queue; `specgate req` adds
|
|
64
|
+
and links requirements so nobody hand-edits the ten-column matrix; `specgate done`
|
|
65
|
+
closes them.
|
|
66
|
+
→ [Quickstart](docs/quickstart.md) · [Command reference](docs/commands.md)
|
|
67
|
+
|
|
68
|
+
**Specs that are checked.** `specgate validate` fails the build when a requirement
|
|
69
|
+
has no scenario, no test, or no row in the traceability matrix. `--strict-tdd`
|
|
70
|
+
fails it when a requirement moves past Draft without a test.
|
|
71
|
+
→ [Writing specs](docs/writing-specs.md) · [Validating](docs/validating.md)
|
|
72
|
+
|
|
73
|
+
**Changes you review as intent.** Modify a spec that already shipped through a
|
|
74
|
+
reviewable delta — only what moves, never a copy. Archiving merges it into the
|
|
75
|
+
spec tree, writes the matrix rows and materialises the feature files, so a
|
|
76
|
+
merged proposal cannot quietly become undone work.
|
|
77
|
+
→ [Reviewing changes](docs/reviewing-changes.md)
|
|
78
|
+
|
|
79
|
+
**Domain knowledge as a dependency.** A pack is a versioned, schema-validated
|
|
80
|
+
domain model. Install it, pin it, upgrade it deliberately — and review the
|
|
81
|
+
upgrade as intent with `specops diff --as-change`, not as a file diff.
|
|
82
|
+
→ [Domain packs](docs/domain-packs.md)
|
|
83
|
+
|
|
84
|
+
**An agent surface that is a contract.** Twelve commands speak JSON with stable
|
|
85
|
+
diagnostic codes and a `fix` on each — every command of the daily loop, and a
|
|
86
|
+
test asserts it. `specgate agents init` wires the loop into eight agent tools from
|
|
87
|
+
one definition.
|
|
88
|
+
→ [Agents](docs/agents.md) · [The agent contract](docs/specs/agent-contract.md)
|
|
89
|
+
|
|
90
|
+
**Unattended delivery.** `specgate harness run` drives plan → agent → verify → done
|
|
91
|
+
for every pending requirement, each in its own git worktree. It never merges.
|
|
92
|
+
`specgate ci init` generates the gate for GitHub, GitLab, Azure or Jenkins, and
|
|
93
|
+
`specgate alm sync` keeps Jira or Azure Boards in step.
|
|
94
|
+
|
|
95
|
+
**Any agent CLI.** No agent runtime, no SDK dependency: the agent is any shell
|
|
96
|
+
command containing `{prompt_file}` — `claude -p < {prompt_file}`, `aider --yes
|
|
97
|
+
--message-file {prompt_file}`, or `my-wrapper.sh {prompt_file}` for anything
|
|
98
|
+
else. Commit your team's commands in `.harness/profiles.yaml` and pick one by
|
|
99
|
+
name.
|
|
100
|
+
→ [Automation](docs/automation.md) · [The harness](docs/harness.md) · [Jira and Azure Boards](docs/alm.md)
|
|
101
|
+
|
|
102
|
+
**It stays current.** `specgate update` refreshes the generated agent files after an
|
|
103
|
+
upgrade, three-way merging your edits rather than clobbering them. `specgate doctor`
|
|
104
|
+
reports what has drifted, with a fix per finding.
|
|
105
|
+
→ [Command reference](docs/commands.md)
|
|
106
|
+
|
|
107
|
+
## 🆚 How it compares
|
|
108
|
+
|
|
109
|
+
| Capability | **this** | [OpenSpec](https://github.com/Fission-AI/OpenSpec) | [spec-kit](https://github.com/github/spec-kit) | [Cursor rules](https://docs.cursor.com/context/rules-for-ai) | README only |
|
|
110
|
+
| --- | :-: | :-: | :-: | :-: | :-: |
|
|
111
|
+
| Change lifecycle | ✅ | ✅ | ❌ | ❌ | ❌ |
|
|
112
|
+
| Versioned domain packs | ✅ | ❌ | ⚠️ | ❌ | ❌ |
|
|
113
|
+
| Traceability matrix + CI gate | ✅ | ❌ | ⚠️ | ❌ | ❌ |
|
|
114
|
+
| Agent JSON contract | ✅ | ✅ | ❌ | ❌ | ❌ |
|
|
115
|
+
| Vendor-neutral | ✅ | ✅ | ✅ | ❌ | ✅ |
|
|
116
|
+
| Smaller surface to learn | ❌ | ✅ | ✅ | ✅ | ✅ |
|
|
117
|
+
|
|
118
|
+
OpenSpec is the closest tool and the honest comparison: if you want the change
|
|
119
|
+
loop without versioned packs or an enforced matrix, theirs is the better fit.
|
|
120
|
+
→ [Full matrix, trade-offs and migration paths](docs/comparisons.md)
|
|
121
|
+
|
|
122
|
+
## 📚 Documentation
|
|
123
|
+
|
|
124
|
+
- [Command reference](docs/commands.md) — every command, grouped by when you reach for it
|
|
125
|
+
- [How-to guides](docs/how-to.md) — by task and by adoption level
|
|
126
|
+
- [Tutorial](docs/tutorial.md) — long-form, on a real public pack
|
|
127
|
+
- [Supply chain](docs/supply-chain.md) — pack pinning, digests, signing, air-gapped installs, SBOM
|
|
128
|
+
- [Architecture](docs/specs/architecture.md) — three repos, three lifecycles
|
|
129
|
+
- [Bootstrap prompt](docs/bootstrap-prompt.md) — the one freeform-AI step
|
|
130
|
+
- [Case study](docs/case-studies/case-1.md) · [ADRs](docs/specs/adr/README.md) · [Docs site](https://rsaglobaltech.github.io/specgate/) · [Spec coverage report](https://rsaglobaltech.github.io/specgate/report.html)
|
|
131
|
+
|
|
132
|
+
## 🧰 Companion tools
|
|
133
|
+
|
|
134
|
+
**MCP server** ([`mcp-spec-driven`](packages/mcp-spec-driven)) · **Language
|
|
135
|
+
server** ([`lsp-spec-driven`](packages/lsp-spec-driven)) · **VS Code extension**
|
|
136
|
+
([`vscode-spec-driven`](packages/vscode-spec-driven)) · **Maven and Gradle
|
|
137
|
+
plugins** for teams that do not want Node on the build agent.
|
|
138
|
+
|
|
139
|
+
## 🤝 Contributing
|
|
140
|
+
|
|
141
|
+
PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). Good first contributions:
|
|
142
|
+
new module templates, validator rules, additional domain packs.
|
|
143
|
+
[MAINTAINERS.md](MAINTAINERS.md) says who owns what;
|
|
144
|
+
[SECURITY.md](SECURITY.md) is how to report a vulnerability privately.
|
|
145
|
+
|
|
146
|
+
## 📄 License
|
|
147
|
+
|
|
148
|
+
MIT © RSA Global Tech
|
package/bin/specgate.js
ADDED
package/bin/specgate.ts
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
import { spawnSync } from "child_process";
|
|
6
|
+
|
|
7
|
+
const rootDir = path.resolve(__dirname, "..", "..");
|
|
8
|
+
const distScripts = path.join(__dirname, "..", "scripts");
|
|
9
|
+
const packageJson = require(path.join(rootDir, "package.json"));
|
|
10
|
+
const VERSION: string = packageJson.version || "0.0.0";
|
|
11
|
+
import { ICommand } from "../scripts/lib/command";
|
|
12
|
+
import { SURFACE, helpRows, coreHelpRows, hiddenCommandCount } from "../scripts/lib/surface";
|
|
13
|
+
|
|
14
|
+
/** Resolve a registry row's `script` segments to a path under dist/scripts. */
|
|
15
|
+
function resolveScript(segments: string[]): string {
|
|
16
|
+
return path.join(distScripts, ...segments);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// ── Pretty output helpers ─────────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
const COLOR_ENABLED =
|
|
22
|
+
process.stdout.isTTY && process.env.NO_COLOR === undefined && process.env.TERM !== "dumb";
|
|
23
|
+
|
|
24
|
+
const c = {
|
|
25
|
+
reset: COLOR_ENABLED ? "\x1b[0m" : "",
|
|
26
|
+
bold: COLOR_ENABLED ? "\x1b[1m" : "",
|
|
27
|
+
dim: COLOR_ENABLED ? "\x1b[2m" : "",
|
|
28
|
+
red: COLOR_ENABLED ? "\x1b[31m" : "",
|
|
29
|
+
green: COLOR_ENABLED ? "\x1b[32m" : "",
|
|
30
|
+
yellow: COLOR_ENABLED ? "\x1b[33m" : "",
|
|
31
|
+
blue: COLOR_ENABLED ? "\x1b[34m" : "",
|
|
32
|
+
magenta: COLOR_ENABLED ? "\x1b[35m" : "",
|
|
33
|
+
cyan: COLOR_ENABLED ? "\x1b[36m" : "",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function info(msg: string): void {
|
|
37
|
+
process.stdout.write(`${c.cyan}ℹ${c.reset} ${msg}\n`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function error(msg: string): void {
|
|
41
|
+
process.stderr.write(`${c.red}✖${c.reset} ${msg}\n`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function banner(): string {
|
|
45
|
+
return (
|
|
46
|
+
`\n` +
|
|
47
|
+
` ${c.bold}${c.cyan}🧭 specgate${c.reset} ${c.dim}v${VERSION}${c.reset}\n` +
|
|
48
|
+
` ${c.dim}Specs as executable contracts — requirements, scenarios and traceability that CI enforces.${c.reset}\n`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function section(title: string): string {
|
|
53
|
+
return `\n ${c.bold}${title}${c.reset}\n`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function cmd(emoji: string, name: string, summary: string, pad = 16): string {
|
|
57
|
+
// Use Array.from to count code points (emojis with surrogate pairs count as 1)
|
|
58
|
+
const visible = Array.from(name).length;
|
|
59
|
+
const padding = " ".repeat(Math.max(1, pad - visible));
|
|
60
|
+
return ` ${c.green}${emoji}${c.reset} ${c.green}${name}${c.reset}${padding}${c.dim}${summary}${c.reset}\n`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function flag(name: string, summary: string, pad = 18): string {
|
|
64
|
+
const visible = Array.from(name).length;
|
|
65
|
+
const padding = " ".repeat(Math.max(1, pad - visible));
|
|
66
|
+
return ` ${c.green}${name}${c.reset}${padding}${c.dim}${summary}${c.reset}\n`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function example(line: string, comment?: string): string {
|
|
70
|
+
const prefix = comment ? ` ${c.dim}# ${comment}${c.reset}\n` : "";
|
|
71
|
+
return `${prefix} ${c.yellow}$${c.reset} ${line}\n`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The worked examples of `--help --all`. Prose, not surface: they are chosen
|
|
76
|
+
* for what they teach, so they are declared here rather than derived.
|
|
77
|
+
*/
|
|
78
|
+
const EXAMPLES =
|
|
79
|
+
example(`npx @rsaglobaltech/specgate@latest init`, "Generate a new project (wizard)") +
|
|
80
|
+
example(
|
|
81
|
+
`npx @rsaglobaltech/specgate@latest adopt --project-dir ./my-existing-repo`,
|
|
82
|
+
"Adopt SDD on an existing codebase"
|
|
83
|
+
) +
|
|
84
|
+
example(
|
|
85
|
+
`npx @rsaglobaltech/specgate@latest init --config ./project.config --out ./projects`,
|
|
86
|
+
"Generate a new project from a config file"
|
|
87
|
+
) +
|
|
88
|
+
example(
|
|
89
|
+
`npx @rsaglobaltech/specgate@latest validate ./projects/my-app --strict-tdd`,
|
|
90
|
+
"Validate with the TDD gate"
|
|
91
|
+
) +
|
|
92
|
+
example(
|
|
93
|
+
`npx @rsaglobaltech/specgate@latest expand --pack-root ./domain-packs \\\n --pack parking-management/backend --project-dir ./projects/my-app \\\n --var PROJECT_NAME="My App" --var PROJECT_SLUG=my-app --var DOMAIN="parking ops"`,
|
|
94
|
+
"Apply a local pack"
|
|
95
|
+
) +
|
|
96
|
+
example(
|
|
97
|
+
`npx @rsaglobaltech/specgate@latest expand --pack-repo https://github.com/acme/parking-specops.git \\\n --pack-version v0.1.0 --pack backend --project-dir ./projects/smart-parking \\\n --var PROJECT_NAME="Smart Parking"`,
|
|
98
|
+
"Apply a remote pack pinned to a git tag"
|
|
99
|
+
) +
|
|
100
|
+
example(
|
|
101
|
+
`npx @rsaglobaltech/specgate@latest specops sync --project-dir ./projects/smart-parking`,
|
|
102
|
+
"Re-expand everything in .specops.lock / specops.config.yaml"
|
|
103
|
+
) +
|
|
104
|
+
example(
|
|
105
|
+
`npx @rsaglobaltech/specgate@latest specops diff --project-dir ./projects/smart-parking --pack-version v0.2.0`,
|
|
106
|
+
"Preview a version bump"
|
|
107
|
+
) +
|
|
108
|
+
example(
|
|
109
|
+
`npx @rsaglobaltech/specgate@latest plan --project-dir ./projects/smart-parking`,
|
|
110
|
+
"Show what requirements still need work"
|
|
111
|
+
) +
|
|
112
|
+
example(
|
|
113
|
+
`npx @rsaglobaltech/specgate@latest plan --project-dir ./projects/smart-parking --format json`,
|
|
114
|
+
"Same, machine-readable for AI agents"
|
|
115
|
+
) +
|
|
116
|
+
example(
|
|
117
|
+
`npx @rsaglobaltech/specgate@latest done REQ-007 --check`,
|
|
118
|
+
"Mark REQ-007 Implemented (after validate passes)"
|
|
119
|
+
) +
|
|
120
|
+
example(
|
|
121
|
+
`npx @rsaglobaltech/specgate@latest pack init --out ./domain-packs --name "Billing Backend" --type contracts`,
|
|
122
|
+
"Scaffold a contracts-flavoured pack"
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The daily loop, narrowed.
|
|
127
|
+
*
|
|
128
|
+
* The surface grew past twenty, which is more than anyone reads. A new user
|
|
129
|
+
* needs `init` or `adopt` once, then lives in status → plan → req → change →
|
|
130
|
+
* validate → done. Everything else is real but not first — `--help --all`
|
|
131
|
+
* shows it, and `specgate config set profile full` makes that the default.
|
|
132
|
+
*
|
|
133
|
+
* Both help profiles are rendered from the surface registry, so a command
|
|
134
|
+
* cannot exist without appearing in one of them or being deliberately absent
|
|
135
|
+
* from both.
|
|
136
|
+
*/
|
|
137
|
+
function renderGroups(groups: any[]): string {
|
|
138
|
+
return groups
|
|
139
|
+
.map((g) => section(g.title) + g.rows.map((r: any) => cmd(r.icon, r.label, r.summary)).join(""))
|
|
140
|
+
.join("");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function usageCore() {
|
|
144
|
+
process.stdout.write(
|
|
145
|
+
banner() +
|
|
146
|
+
section("USAGE") +
|
|
147
|
+
` ${c.cyan}specgate${c.reset} ${c.bold}<command>${c.reset} [options]\n` +
|
|
148
|
+
` ${c.dim}Run ‘<command> --help’ for per-command details.${c.reset}\n` +
|
|
149
|
+
renderGroups(coreHelpRows()) +
|
|
150
|
+
section("MORE") +
|
|
151
|
+
` ${c.dim}${hiddenCommandCount()} more commands cover packs, automation, agents and reporting.${c.reset}\n` +
|
|
152
|
+
` ${c.green}specgate --help --all${c.reset}${c.dim} show every command${c.reset}\n` +
|
|
153
|
+
` ${c.green}specgate config set profile full${c.reset}${c.dim} make that the default${c.reset}\n` +
|
|
154
|
+
section("EXAMPLES") +
|
|
155
|
+
example(`npx @rsaglobaltech/specgate@latest adopt`, "Existing codebase") +
|
|
156
|
+
example(`npx @rsaglobaltech/specgate@latest init`, "New project (wizard)") +
|
|
157
|
+
example(`specgate status`, "Start of day") +
|
|
158
|
+
"\n"
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* `core` unless the project says otherwise. Read from .csda/config.json so a
|
|
164
|
+
* team that lives in the full surface is not re-narrowed on every invocation.
|
|
165
|
+
*/
|
|
166
|
+
function helpProfile(): string {
|
|
167
|
+
if (process.env.CSDA_PROFILE) return process.env.CSDA_PROFILE;
|
|
168
|
+
try {
|
|
169
|
+
const raw = fs.readFileSync(path.join(process.cwd(), ".csda", "config.json"), "utf8");
|
|
170
|
+
const parsed = JSON.parse(raw);
|
|
171
|
+
if (parsed && typeof parsed.profile === "string") return parsed.profile;
|
|
172
|
+
} catch {
|
|
173
|
+
// No config, unreadable, or malformed — core is the safe default.
|
|
174
|
+
}
|
|
175
|
+
return "core";
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function usage(opts?: { all?: boolean }) {
|
|
179
|
+
if (opts && opts.all) return usageFull();
|
|
180
|
+
if (helpProfile() === "full") return usageFull();
|
|
181
|
+
return usageCore();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function usageFull() {
|
|
185
|
+
process.stdout.write(
|
|
186
|
+
banner() +
|
|
187
|
+
section("USAGE") +
|
|
188
|
+
` ${c.cyan}specgate${c.reset} ${c.bold}<command>${c.reset} [options]\n` +
|
|
189
|
+
` ${c.dim}Run ‘<command> --help’ for per-command details.${c.reset}\n` +
|
|
190
|
+
renderGroups(helpRows()) +
|
|
191
|
+
section("GLOBAL FLAGS") +
|
|
192
|
+
flag("-h, --help", "Show this help.") +
|
|
193
|
+
flag("-v, --version", "Show CLI version.") +
|
|
194
|
+
section("EXAMPLES") +
|
|
195
|
+
EXAMPLES +
|
|
196
|
+
section("LEARN MORE") +
|
|
197
|
+
` ${c.dim}📖 How-to guide ${c.reset}${c.blue}https://github.com/rsaglobaltech/specgate/blob/main/docs/how-to.md${c.reset}\n` +
|
|
198
|
+
` ${c.dim}🌐 Documentation ${c.reset}${c.blue}https://rsaglobaltech.github.io/specgate/${c.reset}\n` +
|
|
199
|
+
` ${c.dim}🪲 Report a bug ${c.reset}${c.blue}https://github.com/rsaglobaltech/specgate/issues${c.reset}\n` +
|
|
200
|
+
`\n`
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function ensureExecutable(scriptPath: string): void {
|
|
205
|
+
if (!fs.existsSync(scriptPath)) {
|
|
206
|
+
error(`Required script not found: ${scriptPath}`);
|
|
207
|
+
process.exit(3);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function runNodeScript(scriptPath: string, args: string[]): void {
|
|
212
|
+
const result = spawnSync(process.execPath, [scriptPath, ...args], {
|
|
213
|
+
stdio: "inherit",
|
|
214
|
+
env: process.env,
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
if (result.error) {
|
|
218
|
+
error(`Failed to execute script: ${result.error.message}`);
|
|
219
|
+
process.exit(1);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (result.signal) {
|
|
223
|
+
error(`Process terminated by signal: ${result.signal}`);
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
process.exit(typeof result.status === "number" ? result.status : 1);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export class CreateSpecDrivenAppCommand implements ICommand {
|
|
231
|
+
public execute(args: string[] = []): void {
|
|
232
|
+
args = args.length ? args : process.argv.slice(2);
|
|
233
|
+
|
|
234
|
+
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
235
|
+
usage({ all: args.includes("--all") });
|
|
236
|
+
process.exit(0);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (args[0] === "--version" || args[0] === "-v") {
|
|
240
|
+
process.stdout.write(`${VERSION}\n`);
|
|
241
|
+
process.exit(0);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const command = args[0];
|
|
245
|
+
|
|
246
|
+
const row = SURFACE.find((c: any) => c.name === command);
|
|
247
|
+
if (!row) {
|
|
248
|
+
info(`Unknown command: ${command}`);
|
|
249
|
+
usage();
|
|
250
|
+
process.exit(2);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Three commands need more than a table row. Each is a genuine parsing
|
|
254
|
+
// decision, not a route, which is why it lives here and not in the registry.
|
|
255
|
+
if (command === "init") return dispatchInit(args.slice(1));
|
|
256
|
+
if (command === "validate") return dispatchValidate(args.slice(1));
|
|
257
|
+
if (command === "harness" && args[1] === "prompt") return dispatchHarnessPrompt(args);
|
|
258
|
+
|
|
259
|
+
// A command with its own script owns its sub-commands: the dispatcher hands
|
|
260
|
+
// the whole tail over and the script reports an unknown one in its own words.
|
|
261
|
+
if (row.script) {
|
|
262
|
+
const target = resolveScript(row.script);
|
|
263
|
+
ensureExecutable(target);
|
|
264
|
+
runNodeScript(target, args.slice(1));
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Otherwise the sub-command is the route, and an unknown one stops here.
|
|
269
|
+
const subName = args[1];
|
|
270
|
+
const sub = (row.subcommands || []).find((s: any) => s.name === subName);
|
|
271
|
+
if (!sub) {
|
|
272
|
+
const expected = (row.subcommands || []).map((s: any) => s.name).join(", ");
|
|
273
|
+
error(`Unknown ${command} sub-command: ${subName || "(none)"}. Expected: ${expected}`);
|
|
274
|
+
usage();
|
|
275
|
+
process.exit(2);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const target = resolveScript(sub.script);
|
|
279
|
+
ensureExecutable(target);
|
|
280
|
+
runNodeScript(target, args.slice(sub.argsFrom === undefined ? 2 : sub.argsFrom));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* `init` is two commands wearing one name: `--from-pack` composes it with
|
|
286
|
+
* `specops add`, which needs its own orchestrator rather than another flag
|
|
287
|
+
* inside init.
|
|
288
|
+
*/
|
|
289
|
+
function dispatchInit(passThrough: string[]): void {
|
|
290
|
+
// Reject --engine=shell — the Bash engine was removed in this release.
|
|
291
|
+
const engineIdx = passThrough.indexOf("--engine");
|
|
292
|
+
if (
|
|
293
|
+
passThrough.includes("--engine=shell") ||
|
|
294
|
+
(engineIdx !== -1 && passThrough[engineIdx + 1] === "shell")
|
|
295
|
+
) {
|
|
296
|
+
error(
|
|
297
|
+
"--engine=shell was removed. The CLI is now Node-only. Drop the flag to use the (sole) Node engine."
|
|
298
|
+
);
|
|
299
|
+
process.exit(2);
|
|
300
|
+
}
|
|
301
|
+
const script = passThrough.includes("--from-pack")
|
|
302
|
+
? resolveScript(["init_from_pack.js"])
|
|
303
|
+
: resolveScript(["init_project.js"]);
|
|
304
|
+
ensureExecutable(script);
|
|
305
|
+
runNodeScript(script, passThrough);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* `validate` is the gate, so a typo in a flag must not read as "nothing to
|
|
310
|
+
* report". It is the one command whose arguments the dispatcher checks.
|
|
311
|
+
*/
|
|
312
|
+
function dispatchValidate(validateArgs: string[]): void {
|
|
313
|
+
const script = resolveScript(["validate_specs.js"]);
|
|
314
|
+
ensureExecutable(script);
|
|
315
|
+
|
|
316
|
+
const positional = validateArgs.filter((a) => !a.startsWith("-"));
|
|
317
|
+
if (positional.length !== 1) {
|
|
318
|
+
error(`'validate' expects exactly one positional argument: <project_dir>`);
|
|
319
|
+
usage();
|
|
320
|
+
process.exit(2);
|
|
321
|
+
}
|
|
322
|
+
const VALIDATE_FLAGS = new Set([
|
|
323
|
+
"--strict-tdd",
|
|
324
|
+
"--strict-scenarios",
|
|
325
|
+
"--strict-requirements",
|
|
326
|
+
"--strict-links",
|
|
327
|
+
"--against-lock",
|
|
328
|
+
"--json",
|
|
329
|
+
]);
|
|
330
|
+
const unknownFlags = validateArgs.filter((a) => a.startsWith("-") && !VALIDATE_FLAGS.has(a));
|
|
331
|
+
if (unknownFlags.length > 0) {
|
|
332
|
+
error(`Unknown flag(s) for validate: ${unknownFlags.join(", ")}`);
|
|
333
|
+
usage();
|
|
334
|
+
process.exit(2);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
runNodeScript(script, validateArgs);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* `harness prompt <REQ-id>` is a friendly alias for `harness run --dry-run
|
|
342
|
+
* --req <REQ>`: it prints the prompt the agent would receive, with no git, no
|
|
343
|
+
* agent and no gate.
|
|
344
|
+
*/
|
|
345
|
+
function dispatchHarnessPrompt(args: string[]): void {
|
|
346
|
+
const reqId = args[2];
|
|
347
|
+
if (!reqId || !/^REQ-\d+$/.test(reqId)) {
|
|
348
|
+
error("`harness prompt` expects a REQ-id, e.g. `specgate harness prompt REQ-001`.");
|
|
349
|
+
usage();
|
|
350
|
+
process.exit(2);
|
|
351
|
+
}
|
|
352
|
+
const script = resolveScript(["harness", "run.js"]);
|
|
353
|
+
ensureExecutable(script);
|
|
354
|
+
runNodeScript(script, ["--dry-run", "--req", reqId, ...args.slice(3)]);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Run when this module *is* the entry point, or when the published `bin/` shim
|
|
359
|
+
* required it.
|
|
360
|
+
*
|
|
361
|
+
* The shim is two lines — `require("../dist/bin/specgate.js")` — so
|
|
362
|
+
* `require.main` is the shim and not this module, and the check has to
|
|
363
|
+
* recognise it by name.
|
|
364
|
+
*
|
|
365
|
+
* Compare on the basename. An earlier form asked
|
|
366
|
+
* `filename.endsWith("bin/specgate.js")`, and on Windows
|
|
367
|
+
* `filename` is `bin\specgate.js`, so it never matched: the CLI
|
|
368
|
+
* loaded, dispatched nothing, and exited 0 with no output on either stream.
|
|
369
|
+
* Every test that spawns the CLI failed — 437 of them — and none of the
|
|
370
|
+
* messages said why, because there was no message.
|
|
371
|
+
*
|
|
372
|
+
* It survived because this branch had never been through CI, and the two
|
|
373
|
+
* platforms it was developed on both use `/`.
|
|
374
|
+
*/
|
|
375
|
+
const isEntryPoint =
|
|
376
|
+
require.main === module ||
|
|
377
|
+
(require.main
|
|
378
|
+
? ["specgate.js", "specgate.js"].includes(path.basename(require.main.filename))
|
|
379
|
+
: false);
|
|
380
|
+
|
|
381
|
+
if (isEntryPoint) {
|
|
382
|
+
new CreateSpecDrivenAppCommand().execute();
|
|
383
|
+
}
|