@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
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* What `specops sync` does with one file when the pack has moved on.
|
|
4
|
+
*
|
|
5
|
+
* The hard case is the ordinary one: the pack changed a file and so did the
|
|
6
|
+
* project. Sync therefore keeps a baseline — the content the pack last wrote —
|
|
7
|
+
* and treats the three-way comparison as the primary decision rather than a
|
|
8
|
+
* fallback. Without a baseline it refuses to guess, because silently choosing
|
|
9
|
+
* a side is how a local edit disappears without anyone noticing.
|
|
10
|
+
*
|
|
11
|
+
* Pure: the contents arrive as strings and the outcome says what to write.
|
|
12
|
+
* Reading them, running `git merge-file`, and writing the result are the
|
|
13
|
+
* caller's, so every branch below is testable without a filesystem.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.OUTCOME_LABEL = exports.CONFLICT_OUTCOMES = void 0;
|
|
17
|
+
exports.reconcile = reconcile;
|
|
18
|
+
/** The outcomes a human has to resolve by hand. */
|
|
19
|
+
exports.CONFLICT_OUTCOMES = new Set([
|
|
20
|
+
"conflict",
|
|
21
|
+
"conflict-skipped",
|
|
22
|
+
"conflict-no-base",
|
|
23
|
+
]);
|
|
24
|
+
/** How each outcome is named in the per-pack summary. */
|
|
25
|
+
exports.OUTCOME_LABEL = {
|
|
26
|
+
added: "added",
|
|
27
|
+
unchanged: "unchanged",
|
|
28
|
+
updated: "updated",
|
|
29
|
+
overwritten: "overwritten",
|
|
30
|
+
kept: "kept (local edits preserved)",
|
|
31
|
+
merged: "merged",
|
|
32
|
+
conflict: "CONFLICT (markers written)",
|
|
33
|
+
"conflict-skipped": "CONFLICT (skipped)",
|
|
34
|
+
"conflict-no-base": "CONFLICT (no merge base)",
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* @param base what the pack wrote last time, or null if never recorded
|
|
38
|
+
* @param local what the project has now, or null if the file does not exist
|
|
39
|
+
* @param incoming what the pack writes this time
|
|
40
|
+
*/
|
|
41
|
+
function reconcile(base, local, incoming, opts, merge) {
|
|
42
|
+
if (local === null) {
|
|
43
|
+
return { outcome: "added", write: incoming, baselineContent: incoming };
|
|
44
|
+
}
|
|
45
|
+
if (local === incoming) {
|
|
46
|
+
return { outcome: "unchanged", write: null, baselineContent: incoming };
|
|
47
|
+
}
|
|
48
|
+
if (opts.force) {
|
|
49
|
+
return { outcome: "overwritten", write: incoming, baselineContent: incoming };
|
|
50
|
+
}
|
|
51
|
+
if (base === null) {
|
|
52
|
+
// No merge base recorded — refuse to guess. Leave local untouched.
|
|
53
|
+
return { outcome: "conflict-no-base", write: null, baselineContent: null };
|
|
54
|
+
}
|
|
55
|
+
if (local === base) {
|
|
56
|
+
return { outcome: "updated", write: incoming, baselineContent: incoming };
|
|
57
|
+
}
|
|
58
|
+
if (incoming === base) {
|
|
59
|
+
// Pack unchanged for this file; local edits stand.
|
|
60
|
+
return { outcome: "kept", write: null, baselineContent: base };
|
|
61
|
+
}
|
|
62
|
+
// Both sides diverged from base — real three-way merge.
|
|
63
|
+
const result = merge(base, local, incoming);
|
|
64
|
+
if (!result.conflict) {
|
|
65
|
+
return { outcome: "merged", write: result.merged, baselineContent: incoming };
|
|
66
|
+
}
|
|
67
|
+
if (opts.abortOnConflict) {
|
|
68
|
+
return { outcome: "conflict-skipped", write: null, baselineContent: base };
|
|
69
|
+
}
|
|
70
|
+
return { outcome: "conflict", write: result.merged, baselineContent: base };
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=Reconciliation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Reconciliation.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/Reconciliation.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;AA4DH,8BAqCC;AApFD,mDAAmD;AACtC,QAAA,iBAAiB,GAAkC,IAAI,GAAG,CAAmB;IACxF,UAAU;IACV,kBAAkB;IAClB,kBAAkB;CACnB,CAAC,CAAC;AAEH,yDAAyD;AAC5C,QAAA,aAAa,GAA+C;IACvE,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,WAAW;IACtB,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,aAAa;IAC1B,IAAI,EAAE,8BAA8B;IACpC,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,4BAA4B;IACtC,kBAAkB,EAAE,oBAAoB;IACxC,kBAAkB,EAAE,0BAA0B;CAC/C,CAAC;AAwBF;;;;GAIG;AACH,SAAgB,SAAS,CACvB,IAAmB,EACnB,KAAoB,EACpB,QAAgB,EAChB,IAAsB,EACtB,KAAc;IAEd,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC;IAC1E,CAAC;IACD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC;IAC1E,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC;IAChF,CAAC;IACD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,mEAAmE;QACnE,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;IAC7E,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC;IAC5E,CAAC;IACD,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,mDAAmD;QACnD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;IACjE,CAAC;IAED,wDAAwD;IACxD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC;IAChF,CAAC;IACD,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;IAC7E,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;AAC9E,CAAC"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The dependency graph between requirements.
|
|
4
|
+
*
|
|
5
|
+
* `harness run` processed requirements in matrix order and cut every worktree
|
|
6
|
+
* from the same base, which is wrong whenever one requirement builds on
|
|
7
|
+
* another: REQ-002 needed REQ-001's code to exist and there was no way to say
|
|
8
|
+
* so, so somebody had to know it and pass `--base-branch` by hand. That is
|
|
9
|
+
* defect H12 of the closure plan, and the false failure recorded as H9 was the
|
|
10
|
+
* same gap seen from the other side.
|
|
11
|
+
*
|
|
12
|
+
* A requirement declares what it builds on inside the `csda:trace` comment it
|
|
13
|
+
* already carries:
|
|
14
|
+
*
|
|
15
|
+
* <!-- csda:trace uc=UC-002 feature=features/auth/scopes.feature
|
|
16
|
+
* depends=REQ-001 -->
|
|
17
|
+
*
|
|
18
|
+
* That comment is the repository's existing way of attaching machine-readable
|
|
19
|
+
* facts to a requirement, and `change archive` already reads it to write the
|
|
20
|
+
* traceability row. So the model is the one this repository uses everywhere
|
|
21
|
+
* else: **the requirement declares, the matrix reflects.** Nothing about the
|
|
22
|
+
* ten-column format changes, which matters — `done` and `alm sync` both read
|
|
23
|
+
* Status as the penultimate cell, so an extra column would have silently sent
|
|
24
|
+
* status writes to the wrong place.
|
|
25
|
+
*
|
|
26
|
+
* A missing declaration means no dependencies, so every project that never
|
|
27
|
+
* writes one behaves exactly as it does today.
|
|
28
|
+
*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.RequirementGraph = void 0;
|
|
31
|
+
exports.splitDependencies = splitDependencies;
|
|
32
|
+
/** `"REQ-001, REQ-003"` → `["REQ-001", "REQ-003"]`, de-duplicated and upper-cased. */
|
|
33
|
+
function splitDependencies(raw) {
|
|
34
|
+
const seen = new Set();
|
|
35
|
+
for (const token of String(raw).split(/[,;\s]+/)) {
|
|
36
|
+
const id = token.trim().toUpperCase();
|
|
37
|
+
if (id)
|
|
38
|
+
seen.add(id);
|
|
39
|
+
}
|
|
40
|
+
return [...seen];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The graph over a known set of requirements, and every question the CLI asks
|
|
44
|
+
* of it.
|
|
45
|
+
*
|
|
46
|
+
* Built once and then queried: ordering, levels and cycles are all derived
|
|
47
|
+
* from the same two adjacency maps, so they cannot disagree with each other.
|
|
48
|
+
*/
|
|
49
|
+
class RequirementGraph {
|
|
50
|
+
dependsOn;
|
|
51
|
+
dependents;
|
|
52
|
+
unknown;
|
|
53
|
+
selfReferential;
|
|
54
|
+
ids;
|
|
55
|
+
constructor(requirementIds, declared) {
|
|
56
|
+
this.ids = requirementIds.map((id) => String(id).toUpperCase());
|
|
57
|
+
const known = new Set(this.ids);
|
|
58
|
+
const dependsOn = {};
|
|
59
|
+
const dependents = {};
|
|
60
|
+
for (const id of known) {
|
|
61
|
+
dependsOn[id] = [];
|
|
62
|
+
dependents[id] = [];
|
|
63
|
+
}
|
|
64
|
+
const unknown = [];
|
|
65
|
+
const selfReferential = [];
|
|
66
|
+
for (const [requirement, deps] of Object.entries(declared)) {
|
|
67
|
+
if (!known.has(requirement))
|
|
68
|
+
continue; // declared for a REQ not in this project
|
|
69
|
+
for (const dependency of deps) {
|
|
70
|
+
if (dependency === requirement) {
|
|
71
|
+
selfReferential.push(requirement);
|
|
72
|
+
}
|
|
73
|
+
else if (!known.has(dependency)) {
|
|
74
|
+
unknown.push({ requirement, dependency });
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
dependsOn[requirement].push(dependency);
|
|
78
|
+
dependents[dependency].push(requirement);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
this.dependsOn = dependsOn;
|
|
83
|
+
this.dependents = dependents;
|
|
84
|
+
this.unknown = unknown;
|
|
85
|
+
this.selfReferential = selfReferential;
|
|
86
|
+
}
|
|
87
|
+
/** Build from an adjacency map the caller already has — the harness has one. */
|
|
88
|
+
static fromDependencies(requirementIds, declared) {
|
|
89
|
+
return new RequirementGraph(requirementIds, declared);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Requirements in an order where every dependency comes before what needs
|
|
93
|
+
* it, and the sets that could run at the same time.
|
|
94
|
+
*
|
|
95
|
+
* Kahn's algorithm with the queue kept in the caller's original order, so
|
|
96
|
+
* the result is stable: two requirements that do not constrain each other
|
|
97
|
+
* stay in matrix order, and a project with no declarations gets its input
|
|
98
|
+
* back untouched.
|
|
99
|
+
*/
|
|
100
|
+
get schedule() {
|
|
101
|
+
const remaining = new Map(this.ids.map((id) => [id, new Set(this.dependsOn[id] ?? [])]));
|
|
102
|
+
const order = [];
|
|
103
|
+
const levels = [];
|
|
104
|
+
while (remaining.size > 0) {
|
|
105
|
+
const ready = this.ids.filter((id) => remaining.get(id)?.size === 0);
|
|
106
|
+
if (ready.length === 0)
|
|
107
|
+
break; // everything left is in, or behind, a cycle
|
|
108
|
+
levels.push(ready);
|
|
109
|
+
for (const id of ready) {
|
|
110
|
+
order.push(id);
|
|
111
|
+
remaining.delete(id);
|
|
112
|
+
}
|
|
113
|
+
for (const deps of remaining.values()) {
|
|
114
|
+
for (const id of ready)
|
|
115
|
+
deps.delete(id);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return { order, levels };
|
|
119
|
+
}
|
|
120
|
+
get order() {
|
|
121
|
+
return this.schedule.order;
|
|
122
|
+
}
|
|
123
|
+
get levels() {
|
|
124
|
+
return this.schedule.levels;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The cycles among the requirements that could not be ordered.
|
|
128
|
+
*
|
|
129
|
+
* Reporting "there is a cycle" is not actionable; reporting
|
|
130
|
+
* `REQ-002 → REQ-003 → REQ-002` is.
|
|
131
|
+
*/
|
|
132
|
+
get cycles() {
|
|
133
|
+
const ordered = new Set(this.order);
|
|
134
|
+
const stuck = this.ids.filter((id) => !ordered.has(id));
|
|
135
|
+
return this.findCycles(stuck);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Everything that transitively waits on `requirement`, so a cascade is
|
|
139
|
+
* reported once as blocked rather than N times as failed.
|
|
140
|
+
*/
|
|
141
|
+
transitiveDependents(requirement) {
|
|
142
|
+
const blocked = new Set();
|
|
143
|
+
let grew = true;
|
|
144
|
+
while (grew) {
|
|
145
|
+
grew = false;
|
|
146
|
+
for (const [id, deps] of Object.entries(this.dependsOn)) {
|
|
147
|
+
if (blocked.has(id))
|
|
148
|
+
continue;
|
|
149
|
+
if (deps.some((d) => d === requirement || blocked.has(d))) {
|
|
150
|
+
blocked.add(id);
|
|
151
|
+
grew = true;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return blocked;
|
|
156
|
+
}
|
|
157
|
+
/** Depth-first, returning each cycle once, as the path that closes it. */
|
|
158
|
+
findCycles(stuck) {
|
|
159
|
+
const inStuck = new Set(stuck);
|
|
160
|
+
const cycles = [];
|
|
161
|
+
const seenSignature = new Set();
|
|
162
|
+
const done = new Set();
|
|
163
|
+
const path = [];
|
|
164
|
+
const visit = (id) => {
|
|
165
|
+
if (done.has(id))
|
|
166
|
+
return;
|
|
167
|
+
const at = path.indexOf(id);
|
|
168
|
+
if (at !== -1) {
|
|
169
|
+
this.recordCycle(path.slice(at), cycles, seenSignature);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
path.push(id);
|
|
173
|
+
for (const dep of this.dependsOn[id] ?? []) {
|
|
174
|
+
if (inStuck.has(dep))
|
|
175
|
+
visit(dep);
|
|
176
|
+
}
|
|
177
|
+
path.pop();
|
|
178
|
+
done.add(id);
|
|
179
|
+
};
|
|
180
|
+
for (const id of stuck)
|
|
181
|
+
visit(id);
|
|
182
|
+
return cycles;
|
|
183
|
+
}
|
|
184
|
+
/** Rotate to the smallest id so one loop found from two entry points is one cycle. */
|
|
185
|
+
recordCycle(cycle, cycles, seen) {
|
|
186
|
+
const smallest = [...cycle].sort()[0];
|
|
187
|
+
const pivot = cycle.indexOf(smallest);
|
|
188
|
+
const normalised = [...cycle.slice(pivot), ...cycle.slice(0, pivot)];
|
|
189
|
+
const signature = normalised.join(">");
|
|
190
|
+
if (seen.has(signature))
|
|
191
|
+
return;
|
|
192
|
+
seen.add(signature);
|
|
193
|
+
cycles.push(normalised);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
exports.RequirementGraph = RequirementGraph;
|
|
197
|
+
//# sourceMappingURL=RequirementGraph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequirementGraph.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/RequirementGraph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RequirementPlan = void 0;
|
|
4
|
+
class RequirementPlan {
|
|
5
|
+
static DONE_STATUSES = new Set(["Implemented", "Verified", "Released"]);
|
|
6
|
+
static PLACEHOLDER_RE = /^(TBD|TODO|\?+|-)?$|\{\{/;
|
|
7
|
+
static isMeaningful(value) {
|
|
8
|
+
if (typeof value !== "string")
|
|
9
|
+
return false;
|
|
10
|
+
const stripped = value.replace(/^`|`$/g, "").trim();
|
|
11
|
+
if (!stripped)
|
|
12
|
+
return false;
|
|
13
|
+
return !RequirementPlan.PLACEHOLDER_RE.test(stripped);
|
|
14
|
+
}
|
|
15
|
+
static classifyRow(row, fileChecker) {
|
|
16
|
+
const reqId = row.requirement || "";
|
|
17
|
+
if (!/^REQ-\d+/.test(reqId))
|
|
18
|
+
return null;
|
|
19
|
+
const featureExists = fileChecker(row.featureFile || "");
|
|
20
|
+
const techDeclared = RequirementPlan.isMeaningful(row.technicalArtifact);
|
|
21
|
+
const testDeclared = RequirementPlan.isMeaningful(row.testArtifact);
|
|
22
|
+
const techExists = techDeclared && fileChecker(row.technicalArtifact || "");
|
|
23
|
+
const testExists = testDeclared && fileChecker(row.testArtifact || "");
|
|
24
|
+
const isDone = RequirementPlan.DONE_STATUSES.has(row.status || "");
|
|
25
|
+
let category;
|
|
26
|
+
if (!featureExists)
|
|
27
|
+
category = "NEEDS_FEATURE";
|
|
28
|
+
else if (!techDeclared && !testDeclared)
|
|
29
|
+
category = "NEEDS_EVERYTHING";
|
|
30
|
+
else if (testDeclared && !testExists && techDeclared && !techExists)
|
|
31
|
+
category = "NEEDS_EVERYTHING";
|
|
32
|
+
else if (testDeclared && !testExists)
|
|
33
|
+
category = "NEEDS_TEST";
|
|
34
|
+
else if (techDeclared && !techExists)
|
|
35
|
+
category = "NEEDS_IMPLEMENTATION";
|
|
36
|
+
else if (!isDone)
|
|
37
|
+
category = "NEEDS_STATUS_UPDATE";
|
|
38
|
+
else
|
|
39
|
+
category = "DONE";
|
|
40
|
+
return {
|
|
41
|
+
requirement: reqId,
|
|
42
|
+
scenario_id: row.scenarioId || "",
|
|
43
|
+
feature_file: row.featureFile || "",
|
|
44
|
+
technical_artifact: row.technicalArtifact || "",
|
|
45
|
+
test_artifact: row.testArtifact || "",
|
|
46
|
+
status: row.status || "",
|
|
47
|
+
feature_exists: featureExists,
|
|
48
|
+
technical_exists: techExists,
|
|
49
|
+
test_exists: testExists,
|
|
50
|
+
category,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
static buildSummary(items) {
|
|
54
|
+
const summary = {
|
|
55
|
+
total: items.length,
|
|
56
|
+
done: 0,
|
|
57
|
+
needs_feature: 0,
|
|
58
|
+
needs_test: 0,
|
|
59
|
+
needs_implementation: 0,
|
|
60
|
+
needs_status_update: 0,
|
|
61
|
+
needs_everything: 0,
|
|
62
|
+
blocked: 0,
|
|
63
|
+
};
|
|
64
|
+
for (const item of items) {
|
|
65
|
+
if (item.category === "DONE")
|
|
66
|
+
summary.done++;
|
|
67
|
+
else if (item.category === "NEEDS_FEATURE")
|
|
68
|
+
summary.needs_feature++;
|
|
69
|
+
else if (item.category === "NEEDS_TEST")
|
|
70
|
+
summary.needs_test++;
|
|
71
|
+
else if (item.category === "NEEDS_IMPLEMENTATION")
|
|
72
|
+
summary.needs_implementation++;
|
|
73
|
+
else if (item.category === "NEEDS_STATUS_UPDATE")
|
|
74
|
+
summary.needs_status_update++;
|
|
75
|
+
else if (item.category === "NEEDS_EVERYTHING")
|
|
76
|
+
summary.needs_everything++;
|
|
77
|
+
if (item.blocked_by && item.blocked_by.length > 0) {
|
|
78
|
+
summary.blocked++;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return summary;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.RequirementPlan = RequirementPlan;
|
|
85
|
+
//# sourceMappingURL=RequirementPlan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequirementPlan.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/RequirementPlan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Is this requirement fit to hand to an agent? (B2)
|
|
4
|
+
*
|
|
5
|
+
* ## The attempt with the worst cost/result ratio in the loop
|
|
6
|
+
*
|
|
7
|
+
* `plan` already classifies `NEEDS_FEATURE` and `NEEDS_EVERYTHING`, and
|
|
8
|
+
* `harness run` never used it as a filter. A requirement whose feature does not
|
|
9
|
+
* exist and whose row declares no artifacts is handed over exactly like any
|
|
10
|
+
* other, and the agent discovers halfway through that it has to invent the
|
|
11
|
+
* acceptance criterion — then spends up to `max_attempts` × the timeout on it.
|
|
12
|
+
*
|
|
13
|
+
* What this buys is not a new rule. It is that "is this ready for an agent?"
|
|
14
|
+
* stops being the intuition of whoever typed the command and becomes something
|
|
15
|
+
* calculated, with a fix attached to each answer.
|
|
16
|
+
*
|
|
17
|
+
* ## Blocking versus warning
|
|
18
|
+
*
|
|
19
|
+
* A blocker means the agent cannot succeed, not that the requirement is untidy:
|
|
20
|
+
*
|
|
21
|
+
* - **no feature file** — there is no acceptance criterion to satisfy;
|
|
22
|
+
* - **a scenario the gate cannot fail** — the reward signal is counterfeit
|
|
23
|
+
* (H14), so a green run would prove nothing;
|
|
24
|
+
* - **dependencies not green** — the work it builds on is not there;
|
|
25
|
+
* - **`Deprecated`** — nobody wants it built;
|
|
26
|
+
* - **`Needs Clarification`** — its meaning is disputed, and an agent asked to
|
|
27
|
+
* settle a disagreement will settle it by guessing.
|
|
28
|
+
*
|
|
29
|
+
* Undeclared artifacts only warn. The row being vague about *where* the work
|
|
30
|
+
* goes does not stop the work, and `A2` already reports it against the diff
|
|
31
|
+
* afterwards, which is the moment there is evidence to report.
|
|
32
|
+
*
|
|
33
|
+
* ## Why no I/O here
|
|
34
|
+
*
|
|
35
|
+
* Whether a file exists and what its scenarios say are facts the caller
|
|
36
|
+
* gathers; whether those facts add up to "ready" is a rule. Keeping them apart
|
|
37
|
+
* is what lets every case below be tested without a project on disk.
|
|
38
|
+
*/
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.UNBUILDABLE_STATUS = exports.READINESS_CODES = void 0;
|
|
41
|
+
exports.requirementReadiness = requirementReadiness;
|
|
42
|
+
const Diagnostic_1 = require("./Diagnostic");
|
|
43
|
+
exports.READINESS_CODES = Object.freeze({
|
|
44
|
+
NO_FEATURE: "requirement_has_no_feature",
|
|
45
|
+
UNRUNNABLE_SCENARIO: "requirement_scenario_unrunnable",
|
|
46
|
+
BLOCKED_BY: "requirement_blocked_by_dependency",
|
|
47
|
+
NOT_WANTED: "requirement_not_wanted",
|
|
48
|
+
NEEDS_CLARIFICATION: "requirement_needs_clarification",
|
|
49
|
+
NO_TEST_ARTIFACT: "requirement_declares_no_test_artifact",
|
|
50
|
+
NO_TECHNICAL_ARTIFACT: "requirement_declares_no_technical_artifact",
|
|
51
|
+
});
|
|
52
|
+
/** Statuses that mean an agent should not be pointed at this row. */
|
|
53
|
+
exports.UNBUILDABLE_STATUS = Object.freeze({
|
|
54
|
+
Deprecated: exports.READINESS_CODES.NOT_WANTED,
|
|
55
|
+
"Needs Clarification": exports.READINESS_CODES.NEEDS_CLARIFICATION,
|
|
56
|
+
});
|
|
57
|
+
function requirementReadiness(input) {
|
|
58
|
+
const target = input.requirement;
|
|
59
|
+
const blockers = [];
|
|
60
|
+
const unbuildable = exports.UNBUILDABLE_STATUS[String(input.status || "")];
|
|
61
|
+
if (unbuildable) {
|
|
62
|
+
blockers.push((0, Diagnostic_1.error)(unbuildable, unbuildable === exports.READINESS_CODES.NOT_WANTED
|
|
63
|
+
? `status is ${input.status} — nobody wants this built.`
|
|
64
|
+
: `status is ${input.status} — its meaning is still disputed, and an agent ` +
|
|
65
|
+
`asked to settle a disagreement will settle it by guessing.`, {
|
|
66
|
+
target,
|
|
67
|
+
fix: unbuildable === exports.READINESS_CODES.NOT_WANTED
|
|
68
|
+
? "Drop it from the run, or move the row out of Deprecated."
|
|
69
|
+
: "Settle the question with the people who raised it, then set the status.",
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
if (!input.featureExists) {
|
|
73
|
+
blockers.push((0, Diagnostic_1.error)(exports.READINESS_CODES.NO_FEATURE, input.featureFile
|
|
74
|
+
? `its feature file ${input.featureFile} does not exist, so there is no ` +
|
|
75
|
+
`acceptance criterion to satisfy.`
|
|
76
|
+
: "the row declares no feature file, so there is no acceptance criterion to satisfy.", {
|
|
77
|
+
target,
|
|
78
|
+
fix: `Write the scenario first: \`specgate req link ${target} --feature <path>\`.`,
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
// Only errors. A scenario Cucumber sees as empty passes without running
|
|
82
|
+
// anything, so a green gate on it would mean nothing (H14).
|
|
83
|
+
const unrunnable = (input.scenarioFindings || []).filter((f) => f.severity === "error");
|
|
84
|
+
if (unrunnable.length > 0) {
|
|
85
|
+
blockers.push((0, Diagnostic_1.error)(exports.READINESS_CODES.UNRUNNABLE_SCENARIO, `its scenario would pass without testing anything (${unrunnable.length} error(s)), ` +
|
|
86
|
+
`so the gate could not tell success from failure.`, {
|
|
87
|
+
target,
|
|
88
|
+
fix: "Run `specgate validate <dir> --strict-scenarios` to see them, and fix them first.",
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
const blocked = input.blockedBy || [];
|
|
92
|
+
if (blocked.length > 0) {
|
|
93
|
+
blockers.push((0, Diagnostic_1.error)(exports.READINESS_CODES.BLOCKED_BY, `it depends on ${blocked.join(", ")}, which ${blocked.length === 1 ? "is" : "are"} not done.`, {
|
|
94
|
+
target,
|
|
95
|
+
fix: `Run ${blocked.join(", ")} first — \`specgate harness run\` orders them for you.`,
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
// Warnings, not blockers: a vague row does not stop the work, and A2 reports
|
|
99
|
+
// the same gap against the actual diff afterwards — the moment there is
|
|
100
|
+
// evidence rather than an expectation.
|
|
101
|
+
//
|
|
102
|
+
// These are not the noise trap A2 had to avoid. `TBD` in the test column is
|
|
103
|
+
// not a false positive; it is an accurate statement about an incomplete row,
|
|
104
|
+
// and TDD says that column is what should be filled in first.
|
|
105
|
+
if (!input.testDeclared) {
|
|
106
|
+
blockers.push((0, Diagnostic_1.warning)(exports.READINESS_CODES.NO_TEST_ARTIFACT, "the row declares no test artifact, so the agent chooses where the test " +
|
|
107
|
+
"goes and the matrix will point somewhere else.", { target, fix: `specgate req link ${target} --test <path>` }));
|
|
108
|
+
}
|
|
109
|
+
if (!input.technicalDeclared) {
|
|
110
|
+
blockers.push((0, Diagnostic_1.warning)(exports.READINESS_CODES.NO_TECHNICAL_ARTIFACT, "the row declares no production artifact, so the agent chooses where the " +
|
|
111
|
+
"implementation goes and the matrix will point somewhere else.", { target, fix: `specgate req link ${target} --code <path>` }));
|
|
112
|
+
}
|
|
113
|
+
return { ready: !blockers.some((b) => b.severity === "error"), blockers };
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=RequirementReadiness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequirementReadiness.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/RequirementReadiness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Whether a requirement's prose is checkable by a machine — EARS, opt-in (F6).
|
|
4
|
+
*
|
|
5
|
+
* ## Why this exists
|
|
6
|
+
*
|
|
7
|
+
* `PLAN_PREDICTABLE_CODE_EVOLUTION.md` §4 names the real gap against
|
|
8
|
+
* Predictable Code: `specgate validate` checks that the paperwork is internally
|
|
9
|
+
* consistent, not that the code does what the spec says. §8.1 draws the
|
|
10
|
+
* consequence — a code verifier is useless while the spec it checks against is
|
|
11
|
+
* prose. `- Max 5 failed attempts per hour per user` is not checkable by
|
|
12
|
+
* anything. So the first step is not a verifier; it is making the requirement
|
|
13
|
+
* itself say something a machine can hold code to.
|
|
14
|
+
*
|
|
15
|
+
* EARS (Easy Approach to Requirements Syntax) is the narrowest tool for that:
|
|
16
|
+
* five sentence shapes, each pairing a trigger keyword with an obligation.
|
|
17
|
+
* This module does not attempt to parse full EARS grammar — no regex can
|
|
18
|
+
* reliably tell "the system" from a response clause. It checks the one thing a
|
|
19
|
+
* regex can tell honestly: whether an obligation keyword (RFC 2119) is present
|
|
20
|
+
* at all, and whether a requirement that opens as an unwanted-behaviour clause
|
|
21
|
+
* (`IF …`) actually resolves with `THEN …`. Anything wider would be the H13
|
|
22
|
+
* mistake again — a check that claims to enforce a grammar it does not parse.
|
|
23
|
+
*
|
|
24
|
+
* ## Why RFC 2119 lives here now
|
|
25
|
+
*
|
|
26
|
+
* `DeltaSpec.ts` already enforces `no_rfc2119_keyword`, but only for
|
|
27
|
+
* requirements inside a delta (`change validate` / `change archive`) — a
|
|
28
|
+
* capability spec at rest has never been checked. Moving the constant here and
|
|
29
|
+
* having `DeltaSpec` import it keeps one definition instead of two that can
|
|
30
|
+
* drift, which is the F1/A3 lesson: a rule enforced in one place and silent in
|
|
31
|
+
* another is not a rule, it is luck.
|
|
32
|
+
*/
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.REQUIREMENT_SYNTAX_CODES = exports.RFC2119 = void 0;
|
|
35
|
+
exports.analyseRequirementText = analyseRequirementText;
|
|
36
|
+
const Diagnostic_1 = require("./Diagnostic");
|
|
37
|
+
/** An obligation keyword, English or Spanish. Unchanged from `DeltaSpec`. */
|
|
38
|
+
exports.RFC2119 = /\b(SHALL|MUST|SHOULD|MAY|DEBE|DEBERÁ|DEBERA)\b/;
|
|
39
|
+
/** Every code this module can emit. Callers branch on these, never on prose. */
|
|
40
|
+
exports.REQUIREMENT_SYNTAX_CODES = Object.freeze({
|
|
41
|
+
NO_RFC2119: "no_rfc2119_keyword",
|
|
42
|
+
MISSING_THEN: "requirement_missing_then_clause",
|
|
43
|
+
});
|
|
44
|
+
/**
|
|
45
|
+
* The one paired-keyword EARS shape a regex can check honestly: a requirement
|
|
46
|
+
* that opens as "IF <trigger>" (unwanted behaviour) has to resolve with
|
|
47
|
+
* "THEN <response>" in the same sentence, or it names a trigger and never says
|
|
48
|
+
* what happens.
|
|
49
|
+
*
|
|
50
|
+
* The other four EARS shapes — ubiquitous, event-driven (`WHEN`), state-driven
|
|
51
|
+
* (`WHILE`), optional-feature (`WHERE`) — have no second keyword to be missing;
|
|
52
|
+
* their only checkable requirement is the obligation keyword, which
|
|
53
|
+
* `NO_RFC2119` already covers. Claiming to validate their internal structure
|
|
54
|
+
* beyond that would be checking a shape this module cannot actually parse.
|
|
55
|
+
*/
|
|
56
|
+
const IF_TRIGGER = /^\s*(?:IF|SI)\b/i;
|
|
57
|
+
const THEN_KEYWORD = /\b(?:THEN|ENTONCES)\b/i;
|
|
58
|
+
/**
|
|
59
|
+
* Checks one requirement's prose. `text` is the requirement body as
|
|
60
|
+
* `SpecParser` / `DeltaSpec` hand it over — free-text only, scenario steps
|
|
61
|
+
* live separately and are not part of this check.
|
|
62
|
+
*
|
|
63
|
+
* Two independent findings, never conflated: a requirement can state no
|
|
64
|
+
* obligation at all (`NO_RFC2119`), or state one but leave an `IF` trigger
|
|
65
|
+
* unresolved (`MISSING_THEN`). A requirement missing both reports both — they
|
|
66
|
+
* are different defects with different fixes.
|
|
67
|
+
*/
|
|
68
|
+
function analyseRequirementText(text, opts) {
|
|
69
|
+
const trimmed = String(text || "").trim();
|
|
70
|
+
const found = [];
|
|
71
|
+
const at = (extra = {}) => ({
|
|
72
|
+
target: opts.target,
|
|
73
|
+
...(opts.file ? { file: opts.file } : {}),
|
|
74
|
+
...(opts.line ? { line: opts.line } : {}),
|
|
75
|
+
...extra,
|
|
76
|
+
});
|
|
77
|
+
if (!trimmed)
|
|
78
|
+
return found;
|
|
79
|
+
const hasObligation = exports.RFC2119.test(trimmed);
|
|
80
|
+
if (!hasObligation) {
|
|
81
|
+
found.push((0, Diagnostic_1.warning)(exports.REQUIREMENT_SYNTAX_CODES.NO_RFC2119, `${opts.target} states no obligation (SHALL / MUST / SHOULD / MAY / DEBE / DEBERÁ).`, at({ fix: 'Rewrite the body as "The system SHALL …" or one of its EARS forms.' })));
|
|
82
|
+
}
|
|
83
|
+
if (IF_TRIGGER.test(trimmed) && !THEN_KEYWORD.test(trimmed)) {
|
|
84
|
+
found.push((0, Diagnostic_1.warning)(exports.REQUIREMENT_SYNTAX_CODES.MISSING_THEN, `${opts.target} opens with "IF" but never resolves with "THEN" — the trigger names a ` +
|
|
85
|
+
"condition and never says what the system does about it.", at({
|
|
86
|
+
fix: 'Complete the EARS unwanted-behaviour form: "IF <trigger>, THEN the system SHALL …".',
|
|
87
|
+
})));
|
|
88
|
+
}
|
|
89
|
+
return found;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=RequirementSyntax.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequirementSyntax.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/RequirementSyntax.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;;;AAuCH,wDAwCC;AA5ED,6CAAuC;AAEvC,6EAA6E;AAChE,QAAA,OAAO,GAAG,gDAAgD,CAAC;AAExE,gFAAgF;AACnE,QAAA,wBAAwB,GAAG,MAAM,CAAC,MAAM,CAAC;IACpD,UAAU,EAAE,oBAAoB;IAChC,YAAY,EAAE,iCAAiC;CAChD,CAAC,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,GAAG,kBAAkB,CAAC;AACtC,MAAM,YAAY,GAAG,wBAAwB,CAAC;AAE9C;;;;;;;;;GASG;AACH,SAAgB,sBAAsB,CACpC,IAAY,EACZ,IAAsD;IAEtD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,EAAE,GAAG,CAAC,QAAiC,EAAE,EAAE,EAAE,CAAC,CAAC;QACnD,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzC,GAAG,KAAK;KACT,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAE3B,MAAM,aAAa,GAAG,eAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CACR,IAAA,oBAAO,EACL,gCAAwB,CAAC,UAAU,EACnC,GAAG,IAAI,CAAC,MAAM,sEAAsE,EACpF,EAAE,CAAC,EAAE,GAAG,EAAE,oEAAoE,EAAE,CAAC,CAClF,CACF,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5D,KAAK,CAAC,IAAI,CACR,IAAA,oBAAO,EACL,gCAAwB,CAAC,YAAY,EACrC,GAAG,IAAI,CAAC,MAAM,wEAAwE;YACpF,yDAAyD,EAC3D,EAAE,CAAC;YACD,GAAG,EAAE,qFAAqF;SAC3F,CAAC,CACH,CACF,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|