@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,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Linking the matrix to the file, in the way Cucumber already understands (F4).
|
|
4
|
+
*
|
|
5
|
+
* ## The gap
|
|
6
|
+
*
|
|
7
|
+
* A matrix row says `SCN-001` and names a feature file, and **nothing checks
|
|
8
|
+
* that the scenario is in it**. Measured: rename the scenario and both
|
|
9
|
+
* `validate --strict-tdd` and `validate --strict-scenarios` still pass. The
|
|
10
|
+
* help text has been asking for a Scenario ID "that matches a scenario in its
|
|
11
|
+
* feature file" without ever comparing the two.
|
|
12
|
+
*
|
|
13
|
+
* Cucumber has an idiomatic way to express that link, and it is tags:
|
|
14
|
+
*
|
|
15
|
+
* ```gherkin
|
|
16
|
+
* @REQ-001 @SCN-001
|
|
17
|
+
* Scenario: Evaluation respects the rollout percentage
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* A tag survives renaming the scenario, which is what makes the harness gate
|
|
21
|
+
* robust to the one thing an agent does that turns the gate green and empty
|
|
22
|
+
* (§2.2): filtering by `--tags "@REQ-001"` cannot be defeated by rewording a
|
|
23
|
+
* title.
|
|
24
|
+
*
|
|
25
|
+
* ## Idempotent on purpose
|
|
26
|
+
*
|
|
27
|
+
* `expand` runs more than once against the same project, and `change archive`
|
|
28
|
+
* rewrites features in place. Adding a tag has to be safe to repeat: a tag
|
|
29
|
+
* already present is left alone rather than duplicated, and existing tags a
|
|
30
|
+
* person wrote are preserved.
|
|
31
|
+
*/
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
exports.isCsdaTag = isCsdaTag;
|
|
34
|
+
exports.parseTagLine = parseTagLine;
|
|
35
|
+
exports.tagScenario = tagScenario;
|
|
36
|
+
exports.csdaTagsByScenario = csdaTagsByScenario;
|
|
37
|
+
exports.csdaTagsIn = csdaTagsIn;
|
|
38
|
+
/** `@REQ-001`, `@SCN-014a` — ours. Anything else on the line belongs to the project. */
|
|
39
|
+
const CSDA_TAG = /^@(REQ|SCN)-[A-Za-z0-9.]+$/;
|
|
40
|
+
/** A scenario heading in any dialect, captured with its indentation. */
|
|
41
|
+
const SCENARIO_LINE = /^(\s*)([^\s:][^:]*):\s*(.*)$/;
|
|
42
|
+
function isCsdaTag(tag) {
|
|
43
|
+
return CSDA_TAG.test(tag.trim());
|
|
44
|
+
}
|
|
45
|
+
/** The tags on a line, or `null` when the line is not a tag line. */
|
|
46
|
+
function parseTagLine(line) {
|
|
47
|
+
const trimmed = line.trim();
|
|
48
|
+
if (!trimmed.startsWith("@"))
|
|
49
|
+
return null;
|
|
50
|
+
const tags = trimmed.split(/\s+/).filter(Boolean);
|
|
51
|
+
return tags.every((t) => t.startsWith("@")) ? tags : null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Add `tags` above the scenario named `scenarioName`.
|
|
55
|
+
*
|
|
56
|
+
* Returns the source unchanged when the scenario is not there — a caller that
|
|
57
|
+
* wants that reported should compare, because silently doing nothing is how a
|
|
58
|
+
* tagging step becomes a no-op nobody notices.
|
|
59
|
+
*/
|
|
60
|
+
function tagScenario(source, scenarioName, tags) {
|
|
61
|
+
const wanted = tags.map((t) => t.trim()).filter(Boolean);
|
|
62
|
+
if (wanted.length === 0 || !scenarioName)
|
|
63
|
+
return source;
|
|
64
|
+
const lines = source.replace(/\r\n/g, "\n").split("\n");
|
|
65
|
+
const target = scenarioName.trim();
|
|
66
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
67
|
+
const match = SCENARIO_LINE.exec(lines[i]);
|
|
68
|
+
if (!match || match[3].trim() !== target)
|
|
69
|
+
continue;
|
|
70
|
+
// Only a heading that introduces a scenario; `Feature:` and `Background:`
|
|
71
|
+
// take tags in Gherkin too, but this is asked for one scenario by name.
|
|
72
|
+
if (!/^(Scenario|Scenario Outline|Example|Escenario|Esquema del escenario|Cenário|Esquema do Cenário)$/i.test(match[2].trim())) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const indent = match[1];
|
|
76
|
+
const existing = i > 0 ? parseTagLine(lines[i - 1]) : null;
|
|
77
|
+
const already = new Set(existing || []);
|
|
78
|
+
const missing = wanted.filter((t) => !already.has(t));
|
|
79
|
+
if (missing.length === 0)
|
|
80
|
+
return lines.join("\n");
|
|
81
|
+
if (existing) {
|
|
82
|
+
lines[i - 1] = `${indent}${[...existing, ...missing].join(" ")}`;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
lines.splice(i, 0, `${indent}${missing.join(" ")}`);
|
|
86
|
+
}
|
|
87
|
+
return lines.join("\n");
|
|
88
|
+
}
|
|
89
|
+
return lines.join("\n");
|
|
90
|
+
}
|
|
91
|
+
/** The csda tags a scenario carries, by scenario name. */
|
|
92
|
+
function csdaTagsByScenario(source) {
|
|
93
|
+
const lines = source.replace(/\r\n/g, "\n").split("\n");
|
|
94
|
+
const found = {};
|
|
95
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
96
|
+
const match = SCENARIO_LINE.exec(lines[i]);
|
|
97
|
+
if (!match)
|
|
98
|
+
continue;
|
|
99
|
+
const tags = i > 0 ? parseTagLine(lines[i - 1]) : null;
|
|
100
|
+
if (!tags)
|
|
101
|
+
continue;
|
|
102
|
+
const ours = tags.filter(isCsdaTag);
|
|
103
|
+
if (ours.length > 0)
|
|
104
|
+
found[match[3].trim()] = ours;
|
|
105
|
+
}
|
|
106
|
+
return found;
|
|
107
|
+
}
|
|
108
|
+
/** Every csda tag in a file, whatever it is attached to. */
|
|
109
|
+
function csdaTagsIn(source) {
|
|
110
|
+
const found = new Set();
|
|
111
|
+
for (const line of source.replace(/\r\n/g, "\n").split("\n")) {
|
|
112
|
+
for (const tag of parseTagLine(line) || []) {
|
|
113
|
+
if (isCsdaTag(tag))
|
|
114
|
+
found.add(tag);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return [...found].sort();
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=GherkinTags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GherkinTags.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/GherkinTags.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Values this tool hands to `git`, checked before they get there.
|
|
4
|
+
*
|
|
5
|
+
* ## Why this exists
|
|
6
|
+
*
|
|
7
|
+
* `specgate expand --pack-repo <url>` and `specgate specops contribute` pass a
|
|
8
|
+
* repository the caller named straight to `git clone`. Two things make that
|
|
9
|
+
* more than a style concern, and CodeQL flags both as
|
|
10
|
+
* `js/second-order-command-line-injection`:
|
|
11
|
+
*
|
|
12
|
+
* - **A value beginning with `-` is read as an option.** `--upload-pack=<cmd>`
|
|
13
|
+
* makes git run `<cmd>` on what it thinks is the far end. Passing the value
|
|
14
|
+
* as its own argv element does not help: git parses argv, not the shell.
|
|
15
|
+
* - **`ext::` is a git transport that executes a command by design.**
|
|
16
|
+
* `ext::sh -c '…'` is not an exploit of git; it is git doing what it says.
|
|
17
|
+
*
|
|
18
|
+
* The defence is two-sided and both halves are needed. The `--` separator tells
|
|
19
|
+
* git where options stop, and that is what these functions expect their callers
|
|
20
|
+
* to add; this module refuses the values a separator cannot save — `ext::`
|
|
21
|
+
* still executes after a `--`, because by then it is a URL and the URL is the
|
|
22
|
+
* payload.
|
|
23
|
+
*
|
|
24
|
+
* ## What is deliberately still allowed
|
|
25
|
+
*
|
|
26
|
+
* Local paths, `file://`, `https://`, `ssh://`, `git://`, `git@host:path` and
|
|
27
|
+
* `.bundle` files. A pack repository is often a directory or a bundle carried
|
|
28
|
+
* into an air-gapped network, and refusing those would be refusing the feature.
|
|
29
|
+
*/
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.UnsafeGitValueError = void 0;
|
|
32
|
+
exports.assertSafeGitRepo = assertSafeGitRepo;
|
|
33
|
+
exports.assertSafeGitRef = assertSafeGitRef;
|
|
34
|
+
/** Transports that run a command as their normal operation. */
|
|
35
|
+
const EXECUTING_TRANSPORT = /^\s*ext::/i;
|
|
36
|
+
class UnsafeGitValueError extends Error {
|
|
37
|
+
}
|
|
38
|
+
exports.UnsafeGitValueError = UnsafeGitValueError;
|
|
39
|
+
/**
|
|
40
|
+
* A repository the caller named, checked before `git` sees it.
|
|
41
|
+
*
|
|
42
|
+
* Returns the value so it can be used inline. Throws `UnsafeGitValueError`,
|
|
43
|
+
* which callers turn into their own message.
|
|
44
|
+
*/
|
|
45
|
+
function assertSafeGitRepo(value, what = "repository") {
|
|
46
|
+
const repo = String(value ?? "").trim();
|
|
47
|
+
if (!repo) {
|
|
48
|
+
throw new UnsafeGitValueError(`No ${what} given.`);
|
|
49
|
+
}
|
|
50
|
+
if (repo.startsWith("-")) {
|
|
51
|
+
throw new UnsafeGitValueError(`The ${what} "${repo}" starts with "-", so git would read it as an option ` +
|
|
52
|
+
`rather than a location. Options like --upload-pack run a command.`);
|
|
53
|
+
}
|
|
54
|
+
if (EXECUTING_TRANSPORT.test(repo)) {
|
|
55
|
+
throw new UnsafeGitValueError(`The ${what} "${repo}" uses git's ext:: transport, which runs a command by ` +
|
|
56
|
+
`design. Use a path, a bundle, or an http(s)/ssh URL.`);
|
|
57
|
+
}
|
|
58
|
+
return repo;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A ref — branch, tag or commit — the caller named.
|
|
62
|
+
*
|
|
63
|
+
* Narrower than a repository: a ref has no transport, so the only question is
|
|
64
|
+
* whether git would read it as an option.
|
|
65
|
+
*/
|
|
66
|
+
function assertSafeGitRef(value, what = "version") {
|
|
67
|
+
const ref = String(value ?? "").trim();
|
|
68
|
+
if (!ref) {
|
|
69
|
+
throw new UnsafeGitValueError(`No ${what} given.`);
|
|
70
|
+
}
|
|
71
|
+
if (ref.startsWith("-")) {
|
|
72
|
+
throw new UnsafeGitValueError(`The ${what} "${ref}" starts with "-", so git would read it as an option ` +
|
|
73
|
+
`rather than a ref.`);
|
|
74
|
+
}
|
|
75
|
+
return ref;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=GitSafety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitSafety.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/GitSafety.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;;;AAaH,8CAkBC;AAQD,4CAYC;AAjDD,+DAA+D;AAC/D,MAAM,mBAAmB,GAAG,YAAY,CAAC;AAEzC,MAAa,mBAAoB,SAAQ,KAAK;CAAG;AAAjD,kDAAiD;AAEjD;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAC,KAAc,EAAE,IAAI,GAAG,YAAY;IACnE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,mBAAmB,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,mBAAmB,CAC3B,OAAO,IAAI,KAAK,IAAI,uDAAuD;YACzE,mEAAmE,CACtE,CAAC;IACJ,CAAC;IACD,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,mBAAmB,CAC3B,OAAO,IAAI,KAAK,IAAI,wDAAwD;YAC1E,sDAAsD,CACzD,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAgB,gBAAgB,CAAC,KAAc,EAAE,IAAI,GAAG,SAAS;IAC/D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,mBAAmB,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,mBAAmB,CAC3B,OAAO,IAAI,KAAK,GAAG,uDAAuD;YACxE,oBAAoB,CACvB,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HarnessConfig = void 0;
|
|
4
|
+
class HarnessConfig {
|
|
5
|
+
settings;
|
|
6
|
+
static FILENAME = "harness.config.yaml";
|
|
7
|
+
static DEFAULT_SETTINGS = {
|
|
8
|
+
agent: "",
|
|
9
|
+
testCmd: "",
|
|
10
|
+
maxAttempts: 3,
|
|
11
|
+
concurrency: 1,
|
|
12
|
+
promptPrefix: "",
|
|
13
|
+
push: false,
|
|
14
|
+
remote: "origin",
|
|
15
|
+
prCmd: "",
|
|
16
|
+
attemptProfiles: [],
|
|
17
|
+
reviewProfile: "",
|
|
18
|
+
profileAgents: {},
|
|
19
|
+
protectedPaths: [],
|
|
20
|
+
allowPaths: [],
|
|
21
|
+
messageReport: "",
|
|
22
|
+
costPerRunHint: {},
|
|
23
|
+
profileRules: [],
|
|
24
|
+
};
|
|
25
|
+
constructor(settings) {
|
|
26
|
+
this.settings = settings;
|
|
27
|
+
}
|
|
28
|
+
static merge(fileConfig, cliArgs) {
|
|
29
|
+
const file = fileConfig || {};
|
|
30
|
+
return new HarnessConfig({
|
|
31
|
+
agent: cliArgs.agent || file.agent || HarnessConfig.DEFAULT_SETTINGS.agent,
|
|
32
|
+
testCmd: cliArgs.testCmd || file.testCmd || HarnessConfig.DEFAULT_SETTINGS.testCmd,
|
|
33
|
+
maxAttempts: cliArgs.maxAttempts || file.maxAttempts || HarnessConfig.DEFAULT_SETTINGS.maxAttempts,
|
|
34
|
+
concurrency: cliArgs.concurrency || file.concurrency || HarnessConfig.DEFAULT_SETTINGS.concurrency,
|
|
35
|
+
promptPrefix: cliArgs.promptPrefix || file.promptPrefix || HarnessConfig.DEFAULT_SETTINGS.promptPrefix,
|
|
36
|
+
push: cliArgs.push !== undefined
|
|
37
|
+
? cliArgs.push
|
|
38
|
+
: file.push !== undefined
|
|
39
|
+
? file.push
|
|
40
|
+
: HarnessConfig.DEFAULT_SETTINGS.push,
|
|
41
|
+
remote: cliArgs.remote || file.remote || HarnessConfig.DEFAULT_SETTINGS.remote,
|
|
42
|
+
prCmd: cliArgs.prCmd || file.prCmd || HarnessConfig.DEFAULT_SETTINGS.prCmd,
|
|
43
|
+
attemptProfiles: file.attemptProfiles || HarnessConfig.DEFAULT_SETTINGS.attemptProfiles,
|
|
44
|
+
reviewProfile: file.reviewProfile || HarnessConfig.DEFAULT_SETTINGS.reviewProfile,
|
|
45
|
+
profileAgents: file.profileAgents || HarnessConfig.DEFAULT_SETTINGS.profileAgents,
|
|
46
|
+
// Write scope is a repository decision, like the role ladder: it comes
|
|
47
|
+
// from the file only. A flag that relaxes what the agent may edit is a
|
|
48
|
+
// flag somebody eventually types to make a red run go green.
|
|
49
|
+
protectedPaths: file.protectedPaths || HarnessConfig.DEFAULT_SETTINGS.protectedPaths,
|
|
50
|
+
allowPaths: file.allowPaths || HarnessConfig.DEFAULT_SETTINGS.allowPaths,
|
|
51
|
+
messageReport: file.messageReport || HarnessConfig.DEFAULT_SETTINGS.messageReport,
|
|
52
|
+
costPerRunHint: file.costPerRunHint || HarnessConfig.DEFAULT_SETTINGS.costPerRunHint,
|
|
53
|
+
profileRules: file.profileRules || HarnessConfig.DEFAULT_SETTINGS.profileRules,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.HarnessConfig = HarnessConfig;
|
|
58
|
+
//# sourceMappingURL=HarnessConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HarnessConfig.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/HarnessConfig.ts"],"names":[],"mappings":";;;AA2CA,MAAa,aAAa;IAqBW;IApB5B,MAAM,CAAU,QAAQ,GAAG,qBAAqB,CAAC;IACjD,MAAM,CAAU,gBAAgB,GAAoB;QACzD,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,EAAE;QACX,WAAW,EAAE,CAAC;QACd,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,EAAE;QAChB,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,EAAE;QACT,eAAe,EAAE,EAAE;QACnB,aAAa,EAAE,EAAE;QACjB,aAAa,EAAE,EAAE;QACjB,cAAc,EAAE,EAAE;QAClB,UAAU,EAAE,EAAE;QACd,aAAa,EAAE,EAAE;QACjB,cAAc,EAAE,EAAE;QAClB,YAAY,EAAE,EAAE;KACjB,CAAC;IAEF,YAAmC,QAAyB;QAAzB,aAAQ,GAAR,QAAQ,CAAiB;IAAG,CAAC;IAEzD,MAAM,CAAC,KAAK,CACjB,UAA2C,EAC3C,OAAiC;QAEjC,MAAM,IAAI,GAAG,UAAU,IAAI,EAAE,CAAC;QAC9B,OAAO,IAAI,aAAa,CAAC;YACvB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,aAAa,CAAC,gBAAgB,CAAC,KAAK;YAC1E,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,IAAI,aAAa,CAAC,gBAAgB,CAAC,OAAO;YAClF,WAAW,EACT,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,IAAI,aAAa,CAAC,gBAAgB,CAAC,WAAW;YACvF,WAAW,EACT,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,IAAI,aAAa,CAAC,gBAAgB,CAAC,WAAW;YACvF,YAAY,EACV,OAAO,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,IAAI,aAAa,CAAC,gBAAgB,CAAC,YAAY;YAC1F,IAAI,EACF,OAAO,CAAC,IAAI,KAAK,SAAS;gBACxB,CAAC,CAAC,OAAO,CAAC,IAAI;gBACd,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS;oBACvB,CAAC,CAAC,IAAI,CAAC,IAAI;oBACX,CAAC,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI;YAC3C,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI,aAAa,CAAC,gBAAgB,CAAC,MAAM;YAC9E,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,aAAa,CAAC,gBAAgB,CAAC,KAAK;YAC1E,eAAe,EAAE,IAAI,CAAC,eAAe,IAAI,aAAa,CAAC,gBAAgB,CAAC,eAAe;YACvF,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,gBAAgB,CAAC,aAAa;YACjF,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,gBAAgB,CAAC,aAAa;YACjF,uEAAuE;YACvE,uEAAuE;YACvE,6DAA6D;YAC7D,cAAc,EAAE,IAAI,CAAC,cAAc,IAAI,aAAa,CAAC,gBAAgB,CAAC,cAAc;YACpF,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,aAAa,CAAC,gBAAgB,CAAC,UAAU;YACxE,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,gBAAgB,CAAC,aAAa;YACjF,cAAc,EAAE,IAAI,CAAC,cAAc,IAAI,aAAa,CAAC,gBAAgB,CAAC,cAAc;YACpF,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,aAAa,CAAC,gBAAgB,CAAC,YAAY;SAC/E,CAAC,CAAC;IACL,CAAC;;AAzDH,sCA0DC"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* What the harness has actually done, aggregated (C2).
|
|
4
|
+
*
|
|
5
|
+
* ## What was already there, and what C2 adds
|
|
6
|
+
*
|
|
7
|
+
* The proposal opens with "every `harness run` forgets itself". That stopped
|
|
8
|
+
* being true when `E1-04` added the run ledger and the two cost numbers. What
|
|
9
|
+
* was still missing is the part the InfoQ analysis calls *our* metric — the
|
|
10
|
+
* effectiveness of the validation mechanism:
|
|
11
|
+
*
|
|
12
|
+
* - **where the gate rejects.** The ledger records the stage each attempt ended
|
|
13
|
+
* at; nothing added them up. It matters more now than when C2 was written,
|
|
14
|
+
* because `A1` and `A2` introduced two new stages — an attempt rejected for
|
|
15
|
+
* editing the spec is a different problem from one that failed its tests.
|
|
16
|
+
* - **which requirements burn every attempt.** Those are the ones costing
|
|
17
|
+
* `max_attempts` × the timeout and delivering nothing.
|
|
18
|
+
* - **a series over time**, so a rate can be seen moving rather than guessed at.
|
|
19
|
+
* - **real failures versus false ones.** A gate that rejects good work is a
|
|
20
|
+
* different failure from a gate catching a genuine defect, and no amount of
|
|
21
|
+
* recorded data distinguishes them: only a person can say which a given
|
|
22
|
+
* rejection was. Hence the mark, and hence the ratio being *un*computable
|
|
23
|
+
* until someone makes one.
|
|
24
|
+
*
|
|
25
|
+
* ## Why the aggregation lives in the domain
|
|
26
|
+
*
|
|
27
|
+
* It is arithmetic over records — no files, no terminal, no colours. Keeping it
|
|
28
|
+
* here is what lets every case below be tested without writing a ledger to
|
|
29
|
+
* disk, and it is the rule `tests/unit/architecture.test.ts` enforces.
|
|
30
|
+
*/
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.STAGE_LABELS = void 0;
|
|
33
|
+
exports.summariseRuns = summariseRuns;
|
|
34
|
+
exports.parseFalseFailures = parseFalseFailures;
|
|
35
|
+
exports.sparkline = sparkline;
|
|
36
|
+
const RunBudget_1 = require("./RunBudget");
|
|
37
|
+
/** How an attempt ending is worth describing to a person. */
|
|
38
|
+
exports.STAGE_LABELS = Object.freeze({
|
|
39
|
+
pass: "passed",
|
|
40
|
+
"agent-timeout": "agent timed out",
|
|
41
|
+
"agent-error": "agent exited non-zero",
|
|
42
|
+
"write-scope": "agent edited protected files",
|
|
43
|
+
gate: "gate rejected the work",
|
|
44
|
+
artifacts: "diff missed the declared artifacts",
|
|
45
|
+
done: "`specgate done` failed",
|
|
46
|
+
commit: "commit failed",
|
|
47
|
+
});
|
|
48
|
+
function summariseRuns(runs, falseFailures = [], costPerRunHint = {}) {
|
|
49
|
+
const rows = runs.flatMap((r) => r.results ?? []);
|
|
50
|
+
const passed = rows.filter((r) => r.result === "pass");
|
|
51
|
+
const failed = rows.filter((r) => r.result === "fail");
|
|
52
|
+
const totalMs = rows.reduce((n, r) => n + (r.durationMs ?? 0), 0);
|
|
53
|
+
const firstAttemptPasses = passed.filter((r) => r.attempts === 1).length;
|
|
54
|
+
const worst = [...rows]
|
|
55
|
+
.filter((r) => (r.durationMs ?? 0) > 0)
|
|
56
|
+
.sort((a, b) => (b.durationMs ?? 0) - (a.durationMs ?? 0))
|
|
57
|
+
.slice(0, 5)
|
|
58
|
+
.map((r) => ({
|
|
59
|
+
requirement: r.requirement,
|
|
60
|
+
durationMs: r.durationMs ?? 0,
|
|
61
|
+
attempts: r.attempts,
|
|
62
|
+
result: r.result,
|
|
63
|
+
}));
|
|
64
|
+
// Where attempts ended. Read from attemptLog rather than the row's result,
|
|
65
|
+
// because a requirement that passed on attempt 3 still failed twice, and
|
|
66
|
+
// those two failures are the interesting ones.
|
|
67
|
+
const stageCounts = new Map();
|
|
68
|
+
for (const row of rows) {
|
|
69
|
+
for (const attempt of row.attemptLog ?? []) {
|
|
70
|
+
if (!attempt || !attempt.endedAt)
|
|
71
|
+
continue;
|
|
72
|
+
stageCounts.set(attempt.endedAt, (stageCounts.get(attempt.endedAt) ?? 0) + 1);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const stages = [...stageCounts.entries()]
|
|
76
|
+
.map(([stage, count]) => ({ stage, count }))
|
|
77
|
+
.sort((a, b) => b.count - a.count || a.stage.localeCompare(b.stage));
|
|
78
|
+
// Requirements that spent every attempt the run allowed and delivered
|
|
79
|
+
// nothing. `maxAttempts` is per run, so it is read from the run it belongs to.
|
|
80
|
+
const exhausted = [];
|
|
81
|
+
for (const run of runs) {
|
|
82
|
+
const ceiling = run.maxAttempts ?? 0;
|
|
83
|
+
for (const row of run.results ?? []) {
|
|
84
|
+
if (row.result === "fail" && ceiling > 0 && row.attempts >= ceiling) {
|
|
85
|
+
exhausted.push({
|
|
86
|
+
requirement: row.requirement,
|
|
87
|
+
attempts: row.attempts,
|
|
88
|
+
durationMs: row.durationMs ?? 0,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const attemptProfiles = rows.flatMap((row) => (row.attemptLog ?? []).map((a) => a?.profiles ?? []));
|
|
94
|
+
const timeline = [...runs]
|
|
95
|
+
.sort((a, b) => String(a.startedAt).localeCompare(String(b.startedAt)))
|
|
96
|
+
.map((run) => ({
|
|
97
|
+
startedAt: run.startedAt,
|
|
98
|
+
passed: (run.results ?? []).filter((r) => r.result === "pass").length,
|
|
99
|
+
failed: (run.results ?? []).filter((r) => r.result === "fail").length,
|
|
100
|
+
}));
|
|
101
|
+
// Only marks naming a requirement that actually failed count. A mark for
|
|
102
|
+
// something that passed is a typo, and letting it improve the number would
|
|
103
|
+
// make the metric worse than not having it.
|
|
104
|
+
const failedIds = new Set(failed.map((r) => r.requirement));
|
|
105
|
+
const marked = new Set(falseFailures.filter((m) => failedIds.has(m.requirement)).map((m) => m.requirement));
|
|
106
|
+
const falseCount = failed.filter((r) => marked.has(r.requirement)).length;
|
|
107
|
+
return {
|
|
108
|
+
runs: runs.length,
|
|
109
|
+
requirementsAttempted: rows.length,
|
|
110
|
+
passed: passed.length,
|
|
111
|
+
failed: failed.length,
|
|
112
|
+
blocked: rows.filter((r) => r.result === "blocked").length,
|
|
113
|
+
firstAttemptPasses,
|
|
114
|
+
firstAttemptRate: passed.length > 0 ? firstAttemptPasses / passed.length : null,
|
|
115
|
+
totalMs,
|
|
116
|
+
msPerDelivered: passed.length > 0 ? Math.round(totalMs / passed.length) : null,
|
|
117
|
+
worst,
|
|
118
|
+
stages,
|
|
119
|
+
exhausted,
|
|
120
|
+
timeline,
|
|
121
|
+
estimatedCost: (0, RunBudget_1.estimateRunCost)(attemptProfiles, costPerRunHint),
|
|
122
|
+
falseFailures: falseCount,
|
|
123
|
+
realFailureRate: failed.length > 0 && marked.size > 0 ? (failed.length - falseCount) / failed.length : null,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/** The ledger of human marks, one JSON object per line. */
|
|
127
|
+
function parseFalseFailures(jsonl) {
|
|
128
|
+
const marks = [];
|
|
129
|
+
for (const line of (jsonl || "").split("\n")) {
|
|
130
|
+
if (!line.trim())
|
|
131
|
+
continue;
|
|
132
|
+
try {
|
|
133
|
+
const parsed = JSON.parse(line);
|
|
134
|
+
if (parsed && typeof parsed.requirement === "string") {
|
|
135
|
+
marks.push({
|
|
136
|
+
requirement: parsed.requirement,
|
|
137
|
+
reason: String(parsed.reason ?? ""),
|
|
138
|
+
markedAt: String(parsed.markedAt ?? ""),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// One malformed line must not hide the rest — the file is append-only and
|
|
144
|
+
// a half-written line is exactly what a killed process leaves.
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return marks;
|
|
148
|
+
}
|
|
149
|
+
/** A run-by-run bar, oldest on the left. Empty when there is nothing to show. */
|
|
150
|
+
function sparkline(points) {
|
|
151
|
+
if (points.length === 0)
|
|
152
|
+
return "";
|
|
153
|
+
const blocks = "▁▂▃▄▅▆▇█";
|
|
154
|
+
const totals = points.map((p) => p.passed + p.failed);
|
|
155
|
+
const max = Math.max(...totals, 1);
|
|
156
|
+
return totals
|
|
157
|
+
.map((n) => n === 0
|
|
158
|
+
? blocks[0]
|
|
159
|
+
: blocks[Math.min(blocks.length - 1, Math.ceil((n / max) * (blocks.length - 1)))])
|
|
160
|
+
.join("");
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=HarnessReport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HarnessReport.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/HarnessReport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The decisions `specgate harness run` makes before it spawns anything.
|
|
4
|
+
*
|
|
5
|
+
* Substituting a command template, reading a hint out of a gate's output, and
|
|
6
|
+
* working out which requirements can run at the same time are all judgements
|
|
7
|
+
* over data. Spawning the agent, running the gate, cutting branches and
|
|
8
|
+
* writing the ledger are not, and stay in the command.
|
|
9
|
+
*
|
|
10
|
+
* Keeping them apart is what makes the scheduler testable: a dependency cycle
|
|
11
|
+
* or a mis-substituted `{feature_file}` is a bug you want to find without a
|
|
12
|
+
* git repository and an agent.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.substituteAgentCommand = substituteAgentCommand;
|
|
16
|
+
exports.featureFilePath = featureFilePath;
|
|
17
|
+
exports.substituteGateCommand = substituteGateCommand;
|
|
18
|
+
exports.filterHint = filterHint;
|
|
19
|
+
exports.scheduleLevels = scheduleLevels;
|
|
20
|
+
exports.planAttempt = planAttempt;
|
|
21
|
+
const RequirementGraph_1 = require("./RequirementGraph");
|
|
22
|
+
/**
|
|
23
|
+
* Substitute the {prompt_file} placeholder in an agent command template.
|
|
24
|
+
* Throws when the template is missing the placeholder — without it the agent
|
|
25
|
+
* would never receive the prompt.
|
|
26
|
+
*/
|
|
27
|
+
function substituteAgentCommand(template, promptFile) {
|
|
28
|
+
if (!template.includes("{prompt_file}")) {
|
|
29
|
+
throw new Error("The agent command must contain the {prompt_file} placeholder, e.g. " +
|
|
30
|
+
'--agent "claude -p < {prompt_file}"');
|
|
31
|
+
}
|
|
32
|
+
return template.split("{prompt_file}").join(promptFile);
|
|
33
|
+
}
|
|
34
|
+
/** Run the gate (validate --strict-tdd, then the optional test command). */
|
|
35
|
+
/**
|
|
36
|
+
* Fill the placeholders a gate command may use.
|
|
37
|
+
*
|
|
38
|
+
* Without this, `test_cmd` was a fixed string, so a project could not run the
|
|
39
|
+
* scenario belonging to the requirement under test — and the gate runs *before*
|
|
40
|
+
* `done`, so the requirement is still Draft and `validate --strict-tdd` does not
|
|
41
|
+
* demand its test either. The loop could therefore mark a requirement
|
|
42
|
+
* Implemented without ever executing its scenario, which is the one thing this
|
|
43
|
+
* whole tool exists to prevent.
|
|
44
|
+
*
|
|
45
|
+
* `{feature_file}` is the useful one in practice: most runners accept a path and
|
|
46
|
+
* will run exactly that feature's scenarios.
|
|
47
|
+
*/
|
|
48
|
+
/**
|
|
49
|
+
* The feature file a requirement points at, as a plain relative path.
|
|
50
|
+
*
|
|
51
|
+
* The matrix stores it as markdown, so `plan --format json` hands it over
|
|
52
|
+
* still wearing its back-ticks — `` `features/core/health.feature` `` — and it
|
|
53
|
+
* may carry a `#SCN-001` fragment. Three callers needed the bare path and two
|
|
54
|
+
* of them had grown their own copy of this normalisation; a third would have
|
|
55
|
+
* been the H14 shape again, several readers disagreeing about the same text.
|
|
56
|
+
* Worse, the failure is silent: an un-stripped path simply does not exist, so a
|
|
57
|
+
* check that reads it finds nothing wrong and says so.
|
|
58
|
+
*
|
|
59
|
+
* Returns `""` when the requirement declares no feature.
|
|
60
|
+
*/
|
|
61
|
+
function featureFilePath(req) {
|
|
62
|
+
return String(req.featureFile || req.feature_file || "")
|
|
63
|
+
.replace(/^`|`$/g, "")
|
|
64
|
+
.split("#")[0]
|
|
65
|
+
.trim();
|
|
66
|
+
}
|
|
67
|
+
function substituteGateCommand(template, req) {
|
|
68
|
+
const featureFile = featureFilePath(req);
|
|
69
|
+
return template
|
|
70
|
+
.split("{req}")
|
|
71
|
+
.join(req.requirement || "")
|
|
72
|
+
.split("{scenario}")
|
|
73
|
+
.join(req.scenarioId || req.scenario_id || "")
|
|
74
|
+
.split("{feature_file}")
|
|
75
|
+
.join(featureFile);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Warn when a gate that asked to be filtered plainly was not.
|
|
79
|
+
*
|
|
80
|
+
* REQ-002 cost two agent runs to explain: the requirement's scenario passed, the
|
|
81
|
+
* gate ran the whole suite anyway — a `paths` key in the base branch's cucumber
|
|
82
|
+
* config silently overrode the CLI argument — and the failure was
|
|
83
|
+
* indistinguishable from the agent having written broken code.
|
|
84
|
+
*
|
|
85
|
+
* The harness cannot know how many tests *should* run. What it can notice is a
|
|
86
|
+
* command that substituted one feature file against output that talks about
|
|
87
|
+
* many, which is the shape of that mistake. A hint, not a verdict: a legitimate
|
|
88
|
+
* failure must not be second-guessed into passing.
|
|
89
|
+
*/
|
|
90
|
+
function filterHint(template, req, output) {
|
|
91
|
+
if (!String(template).includes("{feature_file}"))
|
|
92
|
+
return "";
|
|
93
|
+
const featureFile = substituteGateCommand("{feature_file}", req);
|
|
94
|
+
if (!featureFile)
|
|
95
|
+
return "";
|
|
96
|
+
// "16 scenarios", "42 tests", "7 examples" — the common shapes.
|
|
97
|
+
// `\b` before the digits: without it the engine restarts inside a long run of
|
|
98
|
+
// them, which is the polynomial case CodeQL reports. One separator, because
|
|
99
|
+
// `[ \t]+` before a word is another way to say the same scan twice.
|
|
100
|
+
const counted = /\b(\d+)[ \t](scenarios|tests|examples|specs)\b/i.exec(output);
|
|
101
|
+
if (!counted || Number(counted[1]) <= 1)
|
|
102
|
+
return "";
|
|
103
|
+
return (`The gate asked for one feature (${featureFile}) and the run reported ` +
|
|
104
|
+
`${counted[1]} ${counted[2].toLowerCase()}. The filter may not be applying — ` +
|
|
105
|
+
"a runner config that pins its own paths can override the argument. Check " +
|
|
106
|
+
"that config on the base branch, not only on main.");
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Split the pending queue into levels, and say what each requirement waits for.
|
|
110
|
+
*
|
|
111
|
+
* `plan` already ordered the queue and told us what every requirement builds
|
|
112
|
+
* on (E1-01). What the harness needs on top of that is the *grouping*: a level
|
|
113
|
+
* is a set of requirements that do not depend on one another, so they are the
|
|
114
|
+
* ones that could run at the same time.
|
|
115
|
+
*
|
|
116
|
+
* Dependencies on requirements that are already DONE do not appear here —
|
|
117
|
+
* `plan` reports them under `dependsOn` but not `blockedBy`, because a
|
|
118
|
+
* finished dependency constrains nothing.
|
|
119
|
+
*/
|
|
120
|
+
function scheduleLevels(pending) {
|
|
121
|
+
const pendingIds = pending.map((r) => r.requirement);
|
|
122
|
+
const inQueue = new Set(pendingIds);
|
|
123
|
+
const dependsOn = {};
|
|
124
|
+
for (const req of pending) {
|
|
125
|
+
// Only dependencies that are themselves in this run constrain the order.
|
|
126
|
+
// A dependency outside the queue is either done or was filtered out by
|
|
127
|
+
// `--req`, and in both cases waiting for it here would deadlock the level.
|
|
128
|
+
dependsOn[req.requirement] = (req.dependsOn || req.depends_on || []).filter((d) => inQueue.has(d));
|
|
129
|
+
}
|
|
130
|
+
const graph = RequirementGraph_1.RequirementGraph.fromDependencies(pendingIds, dependsOn);
|
|
131
|
+
return { levels: graph.levels, cycles: graph.cycles, dependsOn, graph };
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Which agents run, in order, for a given attempt.
|
|
135
|
+
*
|
|
136
|
+
* Attempt 1 is always a single implementing step: there is nothing to review
|
|
137
|
+
* yet. From attempt 2 the review profile, when configured, runs first and its
|
|
138
|
+
* findings feed the step that follows.
|
|
139
|
+
*
|
|
140
|
+
* With no configuration this returns exactly one non-advisory step with no
|
|
141
|
+
* profile for every attempt — today's behaviour, so an existing project sees
|
|
142
|
+
* no change until it asks for one.
|
|
143
|
+
*/
|
|
144
|
+
function planAttempt(attempt, opts = {}) {
|
|
145
|
+
const ladder = opts.attemptProfiles ?? [];
|
|
146
|
+
const profile = ladder.length > 0 ? ladder[Math.min(attempt, ladder.length) - 1] : null;
|
|
147
|
+
const steps = [];
|
|
148
|
+
if (attempt > 1 && opts.reviewProfile) {
|
|
149
|
+
steps.push({ profile: opts.reviewProfile, advisory: true });
|
|
150
|
+
}
|
|
151
|
+
steps.push({ profile: profile ?? null, advisory: false });
|
|
152
|
+
return steps;
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=HarnessRun.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HarnessRun.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/HarnessRun.ts"],"names":[],"mappings":"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"}
|