@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,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeTraceability = mergeTraceability;
|
|
4
|
+
const Reconciliation_1 = require("./Reconciliation");
|
|
5
|
+
const TraceabilityFormat_1 = require("./TraceabilityFormat");
|
|
6
|
+
/**
|
|
7
|
+
* Merging two versions of `docs/specs/traceability.md`, row by row.
|
|
8
|
+
*
|
|
9
|
+
* ## Why this exists
|
|
10
|
+
*
|
|
11
|
+
* Run the harness with `--concurrency 3` and you get three green branches, each
|
|
12
|
+
* having flipped **its own** requirement to `Implemented`. Merge the second one
|
|
13
|
+
* and git reports a conflict in the matrix — even though no two branches touched
|
|
14
|
+
* the same row.
|
|
15
|
+
*
|
|
16
|
+
* The reason is not concurrency. Git's three-way merge works on lines, and it
|
|
17
|
+
* needs at least one *unchanged* line between two changed regions to treat them
|
|
18
|
+
* as independent. Matrix rows are consecutive lines, so two edits one row apart
|
|
19
|
+
* land in the same hunk. Measured: rows 1 and 2 conflict, rows 1 and 5 merge
|
|
20
|
+
* clean. Same writers, same file, same concurrency — only the distance differs.
|
|
21
|
+
*
|
|
22
|
+
* So the fix is not a lock (there is no race: every worker writes its own
|
|
23
|
+
* worktree) and not a different diff algorithm (myers, patience, histogram and
|
|
24
|
+
* minimal all conflict). The fix is to merge the file in the unit it is actually
|
|
25
|
+
* made of: rows.
|
|
26
|
+
*
|
|
27
|
+
* ## How a row is identified
|
|
28
|
+
*
|
|
29
|
+
* By `Requirement` + `Scenario ID`, and **never** by anything that changes.
|
|
30
|
+
*
|
|
31
|
+
* That is not a stylistic preference, it is the bug that nearly shipped: a first
|
|
32
|
+
* prototype keyed rows on the first two cells of a two-column test table, where
|
|
33
|
+
* the second cell *was* the status. A row whose status had changed then looked
|
|
34
|
+
* like a *different* row, the merge came out "clean", and the other branch's
|
|
35
|
+
* edit was lost in silence. A merge that loses an edit is worse than one that
|
|
36
|
+
* refuses, so the key is the pair of columns that a status flip never touches.
|
|
37
|
+
*
|
|
38
|
+
* ## What it will and will not do
|
|
39
|
+
*
|
|
40
|
+
* It resolves the case it was built for — two branches, two different rows — and
|
|
41
|
+
* it still **conflicts** when two branches change the same row to different
|
|
42
|
+
* values. Losing an edit quietly is the one outcome worse than a conflict, so
|
|
43
|
+
* anything genuinely ambiguous comes back with markers for a human.
|
|
44
|
+
*
|
|
45
|
+
* The per-row decision is not reimplemented here: it is `reconcile`, the same
|
|
46
|
+
* function `specops sync` uses to decide what to do when a pack and a project
|
|
47
|
+
* have both changed a file. Identical question, one granularity down.
|
|
48
|
+
*/
|
|
49
|
+
/** Conflict markers, in git's own shape so existing tooling recognises them. */
|
|
50
|
+
const OURS_MARK = "<<<<<<<";
|
|
51
|
+
const SPLIT_MARK = "=======";
|
|
52
|
+
const THEIRS_MARK = ">>>>>>>";
|
|
53
|
+
/**
|
|
54
|
+
* A row key that a status flip cannot change.
|
|
55
|
+
*
|
|
56
|
+
* `parseMatrixRows` splits on `|`, which leaves an empty cell at each end, so
|
|
57
|
+
* `cells[1]` is the first column. `readRowFields` owns that offset for both
|
|
58
|
+
* matrix shapes; going through it means this module never learns the layout.
|
|
59
|
+
*/
|
|
60
|
+
function rowKey(line, mode) {
|
|
61
|
+
const cells = line.split("|").map((c) => c.trim());
|
|
62
|
+
const { requirementId, scenarioId } = (0, TraceabilityFormat_1.readRowFields)(cells, mode);
|
|
63
|
+
const key = `${requirementId}::${scenarioId}`;
|
|
64
|
+
return key === "::" ? null : key;
|
|
65
|
+
}
|
|
66
|
+
/** Every data row of a matrix, keyed and in file order. */
|
|
67
|
+
function indexRows(content, mode) {
|
|
68
|
+
const rows = new Map();
|
|
69
|
+
for (const line of content.split("\n")) {
|
|
70
|
+
if (!line.trim().startsWith("|"))
|
|
71
|
+
continue;
|
|
72
|
+
if (line.includes("---"))
|
|
73
|
+
continue;
|
|
74
|
+
const key = rowKey(line, mode);
|
|
75
|
+
if (key)
|
|
76
|
+
rows.set(key, line);
|
|
77
|
+
}
|
|
78
|
+
return rows;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* A row both sides changed differently is a conflict, full stop.
|
|
82
|
+
*
|
|
83
|
+
* `reconcile` takes a merge function for the case where base, ours and theirs
|
|
84
|
+
* all differ. One row is a single fact — a status is `Implemented` or it is
|
|
85
|
+
* `Verified`, there is no blend — so this always reports a conflict and lets
|
|
86
|
+
* `reconcile` produce the outcome.
|
|
87
|
+
*/
|
|
88
|
+
const rowsDoNotBlend = () => ({ merged: "", conflict: true });
|
|
89
|
+
/**
|
|
90
|
+
* Three-way merge of a traceability matrix.
|
|
91
|
+
*
|
|
92
|
+
* @param base the common ancestor's content, or "" when git has none
|
|
93
|
+
* @param ours the version being merged into
|
|
94
|
+
* @param theirs the version being merged in
|
|
95
|
+
*/
|
|
96
|
+
function mergeTraceability(base, ours, theirs) {
|
|
97
|
+
// The mode comes from `ours`: git is merging *into* that file, and a merge is
|
|
98
|
+
// not the place to convert a project between matrix shapes. A file with
|
|
99
|
+
// neither header has no rows to key, so the whole merge is handed back
|
|
100
|
+
// unresolved rather than guessed at.
|
|
101
|
+
const mode = (0, TraceabilityFormat_1.detectTraceabilityMode)(ours);
|
|
102
|
+
if (mode === null) {
|
|
103
|
+
return { content: ours, conflicts: ["(traceability.md has no recognisable matrix header)"] };
|
|
104
|
+
}
|
|
105
|
+
const baseRows = indexRows(base, mode);
|
|
106
|
+
const ourRows = indexRows(ours, mode);
|
|
107
|
+
const theirRows = indexRows(theirs, mode);
|
|
108
|
+
const conflicts = [];
|
|
109
|
+
const emitted = new Set();
|
|
110
|
+
const out = [];
|
|
111
|
+
for (const line of ours.split("\n")) {
|
|
112
|
+
const key = line.trim().startsWith("|") && !line.includes("---") ? rowKey(line, mode) : null;
|
|
113
|
+
if (!key) {
|
|
114
|
+
out.push(line); // header, separator, prose — carried through untouched
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
emitted.add(key);
|
|
118
|
+
const ourRow = ourRows.get(key) ?? line;
|
|
119
|
+
const baseRow = baseRows.get(key) ?? null;
|
|
120
|
+
const theirRow = theirRows.get(key);
|
|
121
|
+
if (theirRow === undefined) {
|
|
122
|
+
// They do not have this row. Either we added it, or they deleted it.
|
|
123
|
+
if (baseRow === null || baseRow === ourRow) {
|
|
124
|
+
// We added it (no base), or they deleted a row we left alone. Keeping
|
|
125
|
+
// ours in the first case is right; in the second, honouring a deletion
|
|
126
|
+
// would drop a requirement during a merge, which is a decision no
|
|
127
|
+
// driver should make silently — so the row stays and `validate` on the
|
|
128
|
+
// result is what tells the truth.
|
|
129
|
+
out.push(ourRow);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// We changed it, they deleted it. Nothing here can be right by itself.
|
|
133
|
+
conflicts.push(key);
|
|
134
|
+
out.push(conflictBlock(ourRow, "(row deleted on the other side)"));
|
|
135
|
+
}
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const decision = (0, Reconciliation_1.reconcile)(baseRow, ourRow, theirRow, {}, rowsDoNotBlend);
|
|
139
|
+
if (decision.outcome === "conflict" || decision.outcome === "conflict-no-base") {
|
|
140
|
+
conflicts.push(key);
|
|
141
|
+
out.push(conflictBlock(ourRow, theirRow));
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
// `write === null` means "leave ours alone" — unchanged, or their side did
|
|
145
|
+
// not move. Anything else is the row to take.
|
|
146
|
+
out.push(decision.write ?? ourRow);
|
|
147
|
+
}
|
|
148
|
+
// Rows only they have. Appended after the last row rather than interleaved:
|
|
149
|
+
// the matrix has no total order the driver could honour, and inventing one
|
|
150
|
+
// would reshuffle a file nobody asked to reshuffle. `specgate req` owns ordering.
|
|
151
|
+
const added = [...theirRows].filter(([key]) => !emitted.has(key)).map(([, line]) => line);
|
|
152
|
+
if (added.length > 0) {
|
|
153
|
+
const lastRow = lastRowIndex(out, mode);
|
|
154
|
+
out.splice(lastRow + 1, 0, ...added);
|
|
155
|
+
}
|
|
156
|
+
return { content: out.join("\n"), conflicts };
|
|
157
|
+
}
|
|
158
|
+
/** Where the final data row sits, so appended rows land inside the table. */
|
|
159
|
+
function lastRowIndex(lines, mode) {
|
|
160
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
161
|
+
const line = lines[i];
|
|
162
|
+
if (line.trim().startsWith("|") && !line.includes("---") && rowKey(line, mode))
|
|
163
|
+
return i;
|
|
164
|
+
}
|
|
165
|
+
return lines.length - 1;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* One row, both versions, in git's marker shape.
|
|
169
|
+
*
|
|
170
|
+
* **How to resolve one of these by hand:** the two lines are the same row as the
|
|
171
|
+
* two branches left it. Delete the three marker lines and the version you do not
|
|
172
|
+
* want, keeping exactly one row. Then run `specgate validate <project>` — it checks
|
|
173
|
+
* the statuses are legal and that no scenario id is duplicated, which is what
|
|
174
|
+
* catches a half-finished resolution. Do not keep both lines: a duplicated
|
|
175
|
+
* requirement is the one shape of corruption this file must never have.
|
|
176
|
+
*/
|
|
177
|
+
function conflictBlock(ourRow, theirRow) {
|
|
178
|
+
return [`${OURS_MARK} ours`, ourRow, SPLIT_MARK, theirRow, `${THEIRS_MARK} theirs`].join("\n");
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=TraceabilityMerge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TraceabilityMerge.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/TraceabilityMerge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ValidationReport = void 0;
|
|
4
|
+
class ValidationReport {
|
|
5
|
+
findings = [];
|
|
6
|
+
get valid() {
|
|
7
|
+
return !this.findings.some((f) => f.severity === "error");
|
|
8
|
+
}
|
|
9
|
+
get errors() {
|
|
10
|
+
return this.findings.filter((f) => f.severity === "error");
|
|
11
|
+
}
|
|
12
|
+
get warnings() {
|
|
13
|
+
return this.findings.filter((f) => f.severity === "warning");
|
|
14
|
+
}
|
|
15
|
+
addError(code, message, opts = {}) {
|
|
16
|
+
this.findings.push({
|
|
17
|
+
severity: "error",
|
|
18
|
+
code,
|
|
19
|
+
message,
|
|
20
|
+
file: opts.file,
|
|
21
|
+
line: opts.line,
|
|
22
|
+
target: opts.target,
|
|
23
|
+
fix: opts.fix,
|
|
24
|
+
fixLines: opts.fixLines,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
addWarning(code, message, opts = {}) {
|
|
28
|
+
this.findings.push({
|
|
29
|
+
severity: "warning",
|
|
30
|
+
code,
|
|
31
|
+
message,
|
|
32
|
+
file: opts.file,
|
|
33
|
+
line: opts.line,
|
|
34
|
+
target: opts.target,
|
|
35
|
+
fix: opts.fix,
|
|
36
|
+
fixLines: opts.fixLines,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
addInfo(code, message, opts = {}) {
|
|
40
|
+
this.findings.push({
|
|
41
|
+
severity: "info",
|
|
42
|
+
code,
|
|
43
|
+
message,
|
|
44
|
+
file: opts.file,
|
|
45
|
+
line: opts.line,
|
|
46
|
+
target: opts.target,
|
|
47
|
+
fix: opts.fix,
|
|
48
|
+
fixLines: opts.fixLines,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.ValidationReport = ValidationReport;
|
|
53
|
+
//# sourceMappingURL=ValidationReport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValidationReport.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/ValidationReport.ts"],"names":[],"mappings":";;;AAoBA,MAAa,gBAAgB;IACpB,QAAQ,GAAwB,EAAE,CAAC;IAE1C,IAAW,KAAK;QACd,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;IAC5D,CAAC;IAED,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;IAC7D,CAAC;IAED,IAAW,QAAQ;QACjB,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;IAC/D,CAAC;IAEM,QAAQ,CAAC,IAAY,EAAE,OAAe,EAAE,OAAuB,EAAE;QACtE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YACjB,QAAQ,EAAE,OAAO;YACjB,IAAI;YACJ,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;IACL,CAAC;IAEM,UAAU,CAAC,IAAY,EAAE,OAAe,EAAE,OAAuB,EAAE;QACxE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YACjB,QAAQ,EAAE,SAAS;YACnB,IAAI;YACJ,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;IACL,CAAC;IAEM,OAAO,CAAC,IAAY,EAAE,OAAe,EAAE,OAAuB,EAAE;QACrE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YACjB,QAAQ,EAAE,MAAM;YAChB,IAAI;YACJ,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;IACL,CAAC;CACF;AArDD,4CAqDC"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Does the value a spec declares match the value the code declares?
|
|
4
|
+
* (`PLAN_PREDICTABLE_CODE_EVOLUTION.md` §8.6.)
|
|
5
|
+
*
|
|
6
|
+
* ## The gap this closes
|
|
7
|
+
*
|
|
8
|
+
* `--strict-requirements` (F6) checks that a requirement's prose states an
|
|
9
|
+
* obligation. `--strict-links` checks that a declared file still exists.
|
|
10
|
+
* Neither checks what Predictable Code's own page uses as its example:
|
|
11
|
+
* *"session timeout is 30m but spec requires 15m"*. This module compares an
|
|
12
|
+
* explicit value on each side — no AST, no unit inference, no guessing a
|
|
13
|
+
* variable's name from a requirement's prose.
|
|
14
|
+
*
|
|
15
|
+
* ## Why explicit annotation, and not something smarter
|
|
16
|
+
*
|
|
17
|
+
* The comparison is exact string equality between two things a human (or an
|
|
18
|
+
* agent) wrote on purpose:
|
|
19
|
+
*
|
|
20
|
+
* spec: `<!-- csda:trace uc=Login value_session_timeout=15m -->`
|
|
21
|
+
* code: `// csda:value session_timeout=15m`
|
|
22
|
+
*
|
|
23
|
+
* `csda:value` is a plain literal string, not a language-specific comment
|
|
24
|
+
* form — the same reason `csda:trace` works identically in every markdown
|
|
25
|
+
* file without knowing anything about markdown grammar. It is found by
|
|
26
|
+
* scanning line by line, so it reads the same inside `//`, `#`, `--`, or no
|
|
27
|
+
* comment marker at all. Interpreting units (`15m` vs `900000`) is exactly
|
|
28
|
+
* the claim `PLAN_PREDICTABLE_CODE_EVOLUTION.md` §5 refuses to make — that is
|
|
29
|
+
* the H13 trap, a check asserting authority over a grammar it does not parse.
|
|
30
|
+
*
|
|
31
|
+
* ## Why this is a report, not a gate
|
|
32
|
+
*
|
|
33
|
+
* See §8.6: annotating every checkable fact by hand does not scale with
|
|
34
|
+
* project size, and the fraction of requirements that reduce to a scalar
|
|
35
|
+
* value shrinks as a system gets more complex. `compareDeclaredValues` never
|
|
36
|
+
* decides pass/fail — it classifies. The caller (`ReportCommand.ts`) turns
|
|
37
|
+
* that into a coverage-style report section, the same shape as `needsTest`
|
|
38
|
+
* or `orphanFeatures`.
|
|
39
|
+
*/
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.declaredSpecValues = declaredSpecValues;
|
|
42
|
+
exports.declaredCodeValues = declaredCodeValues;
|
|
43
|
+
exports.compareDeclaredValues = compareDeclaredValues;
|
|
44
|
+
const VALUE_PREFIX = "value_";
|
|
45
|
+
/**
|
|
46
|
+
* Every `value_<id>=<literal>` key in an already-parsed `csda:trace` comment.
|
|
47
|
+
*
|
|
48
|
+
* `SpecParser.parseTraceComment` already accepts any `[a-z_]+` key — this
|
|
49
|
+
* reads the convention out of the flat object it returns. No parser change,
|
|
50
|
+
* no new field.
|
|
51
|
+
*/
|
|
52
|
+
function declaredSpecValues(trace) {
|
|
53
|
+
const out = [];
|
|
54
|
+
if (!trace)
|
|
55
|
+
return out;
|
|
56
|
+
for (const key of Object.keys(trace)) {
|
|
57
|
+
if (key.length > VALUE_PREFIX.length && key.startsWith(VALUE_PREFIX)) {
|
|
58
|
+
out.push({ id: key.slice(VALUE_PREFIX.length), value: trace[key] });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Every `csda:value <id>=<literal>` marker in a source file's text.
|
|
65
|
+
*
|
|
66
|
+
* Line-oriented, not language-aware — the marker is found by scanning text,
|
|
67
|
+
* not by parsing whatever comment syntax the file uses. `id` is restricted to
|
|
68
|
+
* `[a-z_]+`, the same identifier space `csda:trace` keys use, so a name is
|
|
69
|
+
* either checkable on both sides or on neither.
|
|
70
|
+
*/
|
|
71
|
+
function declaredCodeValues(source) {
|
|
72
|
+
const out = [];
|
|
73
|
+
const re = /csda:value\s+([a-z_]+)\s*=\s*(\S+)/i;
|
|
74
|
+
const lines = String(source || "").split(/\r?\n/);
|
|
75
|
+
for (let i = 0; i < lines.length; i++) {
|
|
76
|
+
const m = re.exec(lines[i]);
|
|
77
|
+
if (m)
|
|
78
|
+
out.push({ id: m[1].toLowerCase(), value: m[2], line: i + 1 });
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Compares one requirement's spec-declared values against the code values
|
|
84
|
+
* found in the file(s) that requirement's matrix row points at.
|
|
85
|
+
*
|
|
86
|
+
* Scoped per requirement, not global: two unrelated requirements reusing the
|
|
87
|
+
* same id (`session_timeout`) are never compared against each other, because
|
|
88
|
+
* the caller only ever passes one requirement's code entries at a time.
|
|
89
|
+
*
|
|
90
|
+
* A repeated code id (the same marker in two files) keeps its first
|
|
91
|
+
* occurrence, in the order the caller supplied — deterministic, not
|
|
92
|
+
* "whichever file happened to be read last".
|
|
93
|
+
*/
|
|
94
|
+
function compareDeclaredValues(specEntries, codeEntries) {
|
|
95
|
+
const codeById = new Map();
|
|
96
|
+
for (const entry of codeEntries) {
|
|
97
|
+
if (!codeById.has(entry.id))
|
|
98
|
+
codeById.set(entry.id, entry);
|
|
99
|
+
}
|
|
100
|
+
const out = [];
|
|
101
|
+
const specIds = new Set(specEntries.map((e) => e.id));
|
|
102
|
+
for (const spec of specEntries) {
|
|
103
|
+
const code = codeById.get(spec.id);
|
|
104
|
+
if (!code) {
|
|
105
|
+
out.push({
|
|
106
|
+
id: spec.id,
|
|
107
|
+
specValue: spec.value,
|
|
108
|
+
codeValue: null,
|
|
109
|
+
codeFile: null,
|
|
110
|
+
codeLine: null,
|
|
111
|
+
status: "spec_only",
|
|
112
|
+
});
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
out.push({
|
|
116
|
+
id: spec.id,
|
|
117
|
+
specValue: spec.value,
|
|
118
|
+
codeValue: code.value,
|
|
119
|
+
codeFile: code.file,
|
|
120
|
+
codeLine: code.line,
|
|
121
|
+
status: code.value === spec.value ? "matched" : "diverging",
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
for (const code of codeById.values()) {
|
|
125
|
+
if (!specIds.has(code.id)) {
|
|
126
|
+
out.push({
|
|
127
|
+
id: code.id,
|
|
128
|
+
specValue: null,
|
|
129
|
+
codeValue: code.value,
|
|
130
|
+
codeFile: code.file,
|
|
131
|
+
codeLine: code.line,
|
|
132
|
+
status: "code_only",
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=ValueAnnotations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValueAnnotations.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/ValueAnnotations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* What the agent was allowed to write — checked, not merely asked for (A1, H16).
|
|
4
|
+
*
|
|
5
|
+
* ## The hole this closes
|
|
6
|
+
*
|
|
7
|
+
* The prompt tells the agent not to touch the spec. Nothing verified it. An
|
|
8
|
+
* agent that cannot make a scenario pass can instead relax the scenario, or add
|
|
9
|
+
* a permissive line to `AI_RULES.md`, and the gate approves: `validate
|
|
10
|
+
* --strict-tdd` checks that the feature **exists** and is in the matrix, never
|
|
11
|
+
* that it still **says what it said before**.
|
|
12
|
+
*
|
|
13
|
+
* That is not a hypothetical. It is precisely the failure this product claims
|
|
14
|
+
* to prevent — "specs as executable contracts" stops being true the moment the
|
|
15
|
+
* executor can edit the contract. Same family as H1, H14 and H15: the gate
|
|
16
|
+
* approving without having verified.
|
|
17
|
+
*
|
|
18
|
+
* ## Why a new file is not a violation
|
|
19
|
+
*
|
|
20
|
+
* A requirement in category `NEEDS_FEATURE` is *supposed* to create its feature
|
|
21
|
+
* file, so a blanket ban on `features/**` would fail the legitimate case. The
|
|
22
|
+
* distinction A1 asks for — creating a file that did not exist is fine,
|
|
23
|
+
* modifying one that did is not — is one git already draws for us: an untracked
|
|
24
|
+
* path is new, a tracked change is an edit. No heuristics required.
|
|
25
|
+
*
|
|
26
|
+
* The exception is safe in the direction that matters. A matrix row points the
|
|
27
|
+
* gate at one specific feature file, so a *new* file cannot loosen the contract
|
|
28
|
+
* the gate is running; deleting the declared feature and writing a fresh one in
|
|
29
|
+
* its place shows up as a tracked deletion, and is refused.
|
|
30
|
+
*
|
|
31
|
+
* ## Why this module holds no git
|
|
32
|
+
*
|
|
33
|
+
* Deciding whether `features/core/health.feature` is protected is a rule.
|
|
34
|
+
* Finding out which paths changed is I/O. Keeping them apart is what lets every
|
|
35
|
+
* case below be tested without a repository, an agent, or twenty minutes.
|
|
36
|
+
*/
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.DEFAULT_PROTECTED_PATHS = void 0;
|
|
39
|
+
exports.matchesGlob = matchesGlob;
|
|
40
|
+
exports.protectingPattern = protectingPattern;
|
|
41
|
+
exports.checkWriteScope = checkWriteScope;
|
|
42
|
+
exports.parseGitStatus = parseGitStatus;
|
|
43
|
+
/**
|
|
44
|
+
* Protected unless the project says otherwise.
|
|
45
|
+
*
|
|
46
|
+
* Everything here is a term of the contract the agent is working *against*:
|
|
47
|
+
* the business manifesto, the execution rules, the scenarios that decide pass
|
|
48
|
+
* or fail, the specification documents, the pack lockfile, and the harness
|
|
49
|
+
* configuration itself — an agent that may edit `harness.config.yaml` may
|
|
50
|
+
* disable its own gate.
|
|
51
|
+
*/
|
|
52
|
+
exports.DEFAULT_PROTECTED_PATHS = Object.freeze([
|
|
53
|
+
"spec.md",
|
|
54
|
+
"AI_RULES.md",
|
|
55
|
+
"features/**/*.feature",
|
|
56
|
+
"docs/specs/**",
|
|
57
|
+
".specops.lock",
|
|
58
|
+
"harness.config.yaml",
|
|
59
|
+
]);
|
|
60
|
+
/**
|
|
61
|
+
* Glob matching, in the small dialect these patterns actually use.
|
|
62
|
+
*
|
|
63
|
+
* `**` crosses directory separators, `*` does not, `?` is one character. Enough
|
|
64
|
+
* for `features/**\/*.feature` and `docs/specs/**`, and no more: this package
|
|
65
|
+
* has no runtime dependencies (the CLI runs through `npx` on other people's
|
|
66
|
+
* machines), so a matcher is written rather than installed.
|
|
67
|
+
*
|
|
68
|
+
* A pattern naming a directory — `docs/specs/**` — also matches the directory
|
|
69
|
+
* itself, because a person writing that means "this subtree".
|
|
70
|
+
*/
|
|
71
|
+
function matchesGlob(filePath, pattern) {
|
|
72
|
+
const normalise = (p) => p.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
73
|
+
const target = normalise(filePath);
|
|
74
|
+
const glob = normalise(pattern);
|
|
75
|
+
const source = glob.split("").reduce((acc, _ch, i, chars) => {
|
|
76
|
+
if (i < acc.i)
|
|
77
|
+
return acc;
|
|
78
|
+
const rest = chars.slice(i).join("");
|
|
79
|
+
if (rest.startsWith("**/"))
|
|
80
|
+
return { out: acc.out + "(?:.*/)?", i: i + 3 };
|
|
81
|
+
if (rest.startsWith("**"))
|
|
82
|
+
return { out: acc.out + ".*", i: i + 2 };
|
|
83
|
+
const ch = chars[i];
|
|
84
|
+
if (ch === "*")
|
|
85
|
+
return { out: acc.out + "[^/]*", i: i + 1 };
|
|
86
|
+
if (ch === "?")
|
|
87
|
+
return { out: acc.out + "[^/]", i: i + 1 };
|
|
88
|
+
return { out: acc.out + ch.replace(/[.+^${}()|[\]\\]/g, "\\$&"), i: i + 1 };
|
|
89
|
+
}, { out: "", i: 0 }).out;
|
|
90
|
+
if (new RegExp(`^${source}$`).test(target))
|
|
91
|
+
return true;
|
|
92
|
+
// `docs/specs/**` means the subtree, and a person writing it means the
|
|
93
|
+
// directory too. Without this, `docs/specs` itself slips through.
|
|
94
|
+
if (glob.endsWith("/**")) {
|
|
95
|
+
const dir = glob.slice(0, -3);
|
|
96
|
+
return target === dir || target.startsWith(`${dir}/`);
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
/** The first protecting pattern, or `null` when the path is not protected. */
|
|
101
|
+
function protectingPattern(filePath, rules = {}) {
|
|
102
|
+
const allow = rules.allowPaths || [];
|
|
103
|
+
if (allow.some((pattern) => matchesGlob(filePath, pattern)))
|
|
104
|
+
return null;
|
|
105
|
+
const guarded = rules.protectedPaths || exports.DEFAULT_PROTECTED_PATHS;
|
|
106
|
+
return guarded.find((pattern) => matchesGlob(filePath, pattern)) || null;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Which of the agent's writes were out of scope.
|
|
110
|
+
*
|
|
111
|
+
* `added` paths are never violations — see the module note on `NEEDS_FEATURE`.
|
|
112
|
+
* Ordered by path so a report reads the same twice.
|
|
113
|
+
*/
|
|
114
|
+
function checkWriteScope(changes, rules = {}) {
|
|
115
|
+
const violations = [];
|
|
116
|
+
for (const filePath of [...changes.modified].sort()) {
|
|
117
|
+
const pattern = protectingPattern(filePath, rules);
|
|
118
|
+
if (pattern)
|
|
119
|
+
violations.push({ path: filePath, pattern });
|
|
120
|
+
}
|
|
121
|
+
return violations;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* `git status --porcelain`, split into what was edited and what is new.
|
|
125
|
+
*
|
|
126
|
+
* Parsing the status codes rather than guessing from the path is the lesson
|
|
127
|
+
* `change author` taught the hard way: it ran `git checkout` on everything and
|
|
128
|
+
* deleted the files that had never been tracked. `??` means new; every other
|
|
129
|
+
* code means the file existed and the agent changed it — including `D`
|
|
130
|
+
* (deleted) and both halves of a rename, which are edits to the contract by any
|
|
131
|
+
* reading.
|
|
132
|
+
*/
|
|
133
|
+
function parseGitStatus(porcelain) {
|
|
134
|
+
const modified = [];
|
|
135
|
+
const added = [];
|
|
136
|
+
for (const raw of porcelain.split("\n")) {
|
|
137
|
+
if (!raw.trim())
|
|
138
|
+
continue;
|
|
139
|
+
const code = raw.slice(0, 2);
|
|
140
|
+
const rest = raw.slice(3);
|
|
141
|
+
if (code === "??") {
|
|
142
|
+
added.push(rest.trim());
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
// `R old -> new`: both sides are edits to something that existed.
|
|
146
|
+
if (rest.includes(" -> ")) {
|
|
147
|
+
const [from, to] = rest.split(" -> ");
|
|
148
|
+
modified.push(from.trim(), to.trim());
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
modified.push(rest.trim());
|
|
152
|
+
}
|
|
153
|
+
return { modified, added };
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=WriteScope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WriteScope.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/WriteScope.ts"],"names":[],"mappings":"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"}
|