specky-sdd 3.11.0 → 3.12.0
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/.apm/agents/specky-design-architect.agent.md +7 -27
- package/.apm/agents/specky-implementer.agent.md +14 -26
- package/.apm/agents/specky-onboarding.agent.md +8 -49
- package/.apm/agents/specky-orchestrator.agent.md +11 -36
- package/.apm/agents/specky-quality-reviewer.agent.md +8 -29
- package/.apm/agents/specky-release-engineer.agent.md +7 -30
- package/.apm/agents/specky-sdd-init.agent.md +7 -18
- package/.apm/agents/specky-spec-engineer.agent.md +8 -30
- package/.apm/agents/specky-task-planner.agent.md +6 -25
- package/.apm/agents/specky-test-verifier.agent.md +6 -17
- package/.apm/hooks/scripts/specky-artifact-validator.sh +14 -10
- package/.apm/hooks/scripts/specky-auto-checkpoint.sh +9 -4
- package/.apm/hooks/scripts/specky-branch-validator.sh +29 -116
- package/.apm/hooks/scripts/specky-cognitive-debt-alert.sh +6 -3
- package/.apm/hooks/scripts/specky-contract-context.bash +24 -0
- package/.apm/hooks/scripts/specky-contract-context.mjs +235 -0
- package/.apm/hooks/scripts/specky-drift-monitor.sh +6 -3
- package/.apm/hooks/scripts/specky-ears-validator.sh +5 -2
- package/.apm/hooks/scripts/specky-lgtm-gate.sh +12 -10
- package/.apm/hooks/scripts/specky-metrics-dashboard.sh +5 -2
- package/.apm/hooks/scripts/specky-phase-gate.sh +18 -9
- package/.apm/hooks/scripts/specky-pipeline-guard.sh +19 -26
- package/.apm/hooks/scripts/specky-release-gate.sh +38 -46
- package/.apm/hooks/scripts/specky-security-scan.sh +53 -36
- package/.apm/hooks/scripts/specky-session-banner.sh +22 -74
- package/.apm/hooks/scripts/specky-spec-quality.sh +7 -4
- package/.apm/hooks/scripts/specky-spec-sync.sh +12 -11
- package/.apm/hooks/scripts/specky-task-tracer.sh +5 -2
- package/.apm/hooks/specky-run.sh +3 -0
- package/.apm/instructions/claude-instructions.instructions.md +3 -3
- package/.apm/instructions/copilot-instructions.instructions.md +3 -3
- package/.apm/instructions/cursor-instructions.instructions.md +3 -3
- package/.apm/instructions/opencode-instructions.instructions.md +2 -2
- package/.apm/prompts/specky-brownfield.prompt.md +8 -5
- package/.apm/prompts/specky-greenfield.prompt.md +7 -5
- package/.apm/prompts/specky-implement.prompt.md +1 -1
- package/.apm/prompts/specky-orchestrate.prompt.md +1 -1
- package/.apm/skills/specky-design-architect/SKILL.md +39 -16
- package/.apm/skills/specky-implementer/SKILL.md +46 -158
- package/.apm/skills/specky-onboarding/SKILL.md +50 -156
- package/.apm/skills/specky-orchestrator/SKILL.md +28 -26
- package/.apm/skills/specky-quality-reviewer/SKILL.md +38 -23
- package/.apm/skills/specky-release-engineer/SKILL.md +38 -270
- package/.apm/skills/specky-research-analyst/SKILL.md +1 -1
- package/.apm/skills/specky-sdd-init/SKILL.md +61 -23
- package/.apm/skills/specky-sdd-pipeline/SKILL.md +36 -216
- package/.apm/skills/specky-spec-engineer/SKILL.md +40 -17
- package/.apm/skills/specky-task-planner/SKILL.md +31 -12
- package/.apm/skills/specky-test-verifier/SKILL.md +23 -202
- package/CHANGELOG.md +54 -0
- package/README.md +55 -46
- package/apm.lock.yaml +51 -49
- package/apm.yml +3 -3
- package/config.yml +32 -56
- package/dist/cli/commands/apm.d.ts +11 -0
- package/dist/cli/commands/apm.d.ts.map +1 -1
- package/dist/cli/commands/apm.js +4 -4
- package/dist/cli/commands/apm.js.map +1 -1
- package/dist/cli/commands/compile.d.ts.map +1 -1
- package/dist/cli/commands/compile.js +33 -10
- package/dist/cli/commands/compile.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +74 -9
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/hooks.d.ts.map +1 -1
- package/dist/cli/commands/hooks.js +3 -1
- package/dist/cli/commands/hooks.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +28 -17
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/migrate-contracts.d.ts +15 -0
- package/dist/cli/commands/migrate-contracts.d.ts.map +1 -0
- package/dist/cli/commands/migrate-contracts.js +317 -0
- package/dist/cli/commands/migrate-contracts.js.map +1 -0
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +68 -52
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/index.js +98 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/lib/apm/lock.d.ts.map +1 -1
- package/dist/cli/lib/apm/lock.js +1 -1
- package/dist/cli/lib/apm/lock.js.map +1 -1
- package/dist/cli/lib/apm/manifest.d.ts.map +1 -1
- package/dist/cli/lib/apm/manifest.js +1 -1
- package/dist/cli/lib/apm/manifest.js.map +1 -1
- package/dist/cli/lib/apm/policy.d.ts.map +1 -1
- package/dist/cli/lib/apm/policy.js +2 -2
- package/dist/cli/lib/apm/policy.js.map +1 -1
- package/dist/cli/lib/asset-copier.d.ts.map +1 -1
- package/dist/cli/lib/asset-copier.js +25 -10
- package/dist/cli/lib/asset-copier.js.map +1 -1
- package/dist/cli/lib/cursor-plugin-writer.d.ts.map +1 -1
- package/dist/cli/lib/cursor-plugin-writer.js +36 -9
- package/dist/cli/lib/cursor-plugin-writer.js.map +1 -1
- package/dist/cli/lib/gitignore-writer.d.ts.map +1 -1
- package/dist/cli/lib/gitignore-writer.js.map +1 -1
- package/dist/cli/lib/harness/compilers/agent-skills.js.map +1 -1
- package/dist/cli/lib/harness/compilers/claude.d.ts.map +1 -1
- package/dist/cli/lib/harness/compilers/claude.js +2 -4
- package/dist/cli/lib/harness/compilers/claude.js.map +1 -1
- package/dist/cli/lib/harness/compilers/common.d.ts.map +1 -1
- package/dist/cli/lib/harness/compilers/common.js +2 -6
- package/dist/cli/lib/harness/compilers/common.js.map +1 -1
- package/dist/cli/lib/harness/compilers/copilot.js.map +1 -1
- package/dist/cli/lib/harness/compilers/cursor.d.ts.map +1 -1
- package/dist/cli/lib/harness/compilers/cursor.js +2 -4
- package/dist/cli/lib/harness/compilers/cursor.js.map +1 -1
- package/dist/cli/lib/harness/compilers/opencode.d.ts.map +1 -1
- package/dist/cli/lib/harness/compilers/opencode.js +1 -3
- package/dist/cli/lib/harness/compilers/opencode.js.map +1 -1
- package/dist/cli/lib/harness/index.d.ts +1 -1
- package/dist/cli/lib/harness/index.d.ts.map +1 -1
- package/dist/cli/lib/harness/index.js +3 -3
- package/dist/cli/lib/harness/index.js.map +1 -1
- package/dist/cli/lib/harness/tool-map.d.ts.map +1 -1
- package/dist/cli/lib/harness/tool-map.js +1 -2
- package/dist/cli/lib/harness/tool-map.js.map +1 -1
- package/dist/cli/lib/harness/types.d.ts.map +1 -1
- package/dist/cli/lib/ide-detect.d.ts.map +1 -1
- package/dist/cli/lib/ide-detect.js +1 -5
- package/dist/cli/lib/ide-detect.js.map +1 -1
- package/dist/cli/lib/paths.d.ts +10 -0
- package/dist/cli/lib/paths.d.ts.map +1 -1
- package/dist/cli/lib/paths.js +1 -1
- package/dist/cli/lib/paths.js.map +1 -1
- package/dist/cli/lib/settings-merger.d.ts.map +1 -1
- package/dist/cli/lib/settings-merger.js +2 -3
- package/dist/cli/lib/settings-merger.js.map +1 -1
- package/dist/cli/lib/update-check.js +5 -2
- package/dist/cli/lib/update-check.js.map +1 -1
- package/dist/cli/lib/vscode-settings-writer.d.ts.map +1 -1
- package/dist/cli/lib/vscode-settings-writer.js +1 -1
- package/dist/cli/lib/vscode-settings-writer.js.map +1 -1
- package/dist/config.d.ts +119 -47
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +164 -130
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +6 -1
- package/dist/constants.js.map +1 -1
- package/dist/contracts/pipeline-profiles.d.ts +61 -0
- package/dist/contracts/pipeline-profiles.d.ts.map +1 -0
- package/dist/contracts/pipeline-profiles.js +315 -0
- package/dist/contracts/pipeline-profiles.js.map +1 -0
- package/dist/contracts/tool-contracts.d.ts +449 -0
- package/dist/contracts/tool-contracts.d.ts.map +1 -0
- package/dist/contracts/tool-contracts.js +456 -0
- package/dist/contracts/tool-contracts.js.map +1 -0
- package/dist/contracts/use-case.d.ts +736 -0
- package/dist/contracts/use-case.d.ts.map +1 -0
- package/dist/contracts/use-case.js +533 -0
- package/dist/contracts/use-case.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -50
- package/dist/index.js.map +1 -1
- package/dist/schemas/common.d.ts +3 -3
- package/dist/schemas/common.d.ts.map +1 -1
- package/dist/schemas/common.js +1 -6
- package/dist/schemas/common.js.map +1 -1
- package/dist/schemas/context.d.ts +2 -2
- package/dist/schemas/context.d.ts.map +1 -1
- package/dist/schemas/context.js +6 -3
- package/dist/schemas/context.js.map +1 -1
- package/dist/schemas/environment.d.ts +6 -17
- package/dist/schemas/environment.d.ts.map +1 -1
- package/dist/schemas/environment.js +16 -34
- package/dist/schemas/environment.js.map +1 -1
- package/dist/schemas/feature-content.d.ts +116 -0
- package/dist/schemas/feature-content.d.ts.map +1 -0
- package/dist/schemas/feature-content.js +92 -0
- package/dist/schemas/feature-content.js.map +1 -0
- package/dist/schemas/infrastructure.d.ts +6 -28
- package/dist/schemas/infrastructure.d.ts.map +1 -1
- package/dist/schemas/infrastructure.js +16 -36
- package/dist/schemas/infrastructure.js.map +1 -1
- package/dist/schemas/input.d.ts +412 -8
- package/dist/schemas/input.d.ts.map +1 -1
- package/dist/schemas/input.js +22 -17
- package/dist/schemas/input.js.map +1 -1
- package/dist/schemas/integration.d.ts +22 -28
- package/dist/schemas/integration.d.ts.map +1 -1
- package/dist/schemas/integration.js +37 -67
- package/dist/schemas/integration.js.map +1 -1
- package/dist/schemas/metrics.d.ts +3 -2
- package/dist/schemas/metrics.d.ts.map +1 -1
- package/dist/schemas/metrics.js +7 -3
- package/dist/schemas/metrics.js.map +1 -1
- package/dist/schemas/pbt.d.ts +2 -7
- package/dist/schemas/pbt.d.ts.map +1 -1
- package/dist/schemas/pbt.js +6 -11
- package/dist/schemas/pbt.js.map +1 -1
- package/dist/schemas/pipeline.d.ts +282 -35
- package/dist/schemas/pipeline.d.ts.map +1 -1
- package/dist/schemas/pipeline.js +95 -68
- package/dist/schemas/pipeline.js.map +1 -1
- package/dist/schemas/quality.d.ts +15 -19
- package/dist/schemas/quality.d.ts.map +1 -1
- package/dist/schemas/quality.js +41 -15
- package/dist/schemas/quality.js.map +1 -1
- package/dist/schemas/routing.d.ts +2 -2
- package/dist/schemas/routing.d.ts.map +1 -1
- package/dist/schemas/routing.js +7 -6
- package/dist/schemas/routing.js.map +1 -1
- package/dist/schemas/testing.d.ts +4 -13
- package/dist/schemas/testing.d.ts.map +1 -1
- package/dist/schemas/testing.js +11 -13
- package/dist/schemas/testing.js.map +1 -1
- package/dist/schemas/transcript.d.ts +648 -10
- package/dist/schemas/transcript.d.ts.map +1 -1
- package/dist/schemas/transcript.js +42 -25
- package/dist/schemas/transcript.js.map +1 -1
- package/dist/schemas/utility.d.ts +28 -15
- package/dist/schemas/utility.d.ts.map +1 -1
- package/dist/schemas/utility.js +52 -60
- package/dist/schemas/utility.js.map +1 -1
- package/dist/schemas/visualization.d.ts +74 -15
- package/dist/schemas/visualization.d.ts.map +1 -1
- package/dist/schemas/visualization.js +155 -27
- package/dist/schemas/visualization.js.map +1 -1
- package/dist/services/analysis-engine.d.ts.map +1 -1
- package/dist/services/analysis-engine.js +7 -3
- package/dist/services/analysis-engine.js.map +1 -1
- package/dist/services/audit-logger.d.ts +18 -0
- package/dist/services/audit-logger.d.ts.map +1 -1
- package/dist/services/audit-logger.js +75 -37
- package/dist/services/audit-logger.js.map +1 -1
- package/dist/services/codebase-scanner.d.ts +1 -1
- package/dist/services/codebase-scanner.d.ts.map +1 -1
- package/dist/services/codebase-scanner.js +3 -6
- package/dist/services/codebase-scanner.js.map +1 -1
- package/dist/services/cognitive-debt-engine.d.ts.map +1 -1
- package/dist/services/cognitive-debt-engine.js +1 -1
- package/dist/services/cognitive-debt-engine.js.map +1 -1
- package/dist/services/compliance-engine.d.ts +4 -3
- package/dist/services/compliance-engine.d.ts.map +1 -1
- package/dist/services/compliance-engine.js +244 -51
- package/dist/services/compliance-engine.js.map +1 -1
- package/dist/services/content-diagram-generator.d.ts +96 -0
- package/dist/services/content-diagram-generator.d.ts.map +1 -0
- package/dist/services/content-diagram-generator.js +372 -0
- package/dist/services/content-diagram-generator.js.map +1 -0
- package/dist/services/context-tiering-engine.d.ts +1 -1
- package/dist/services/context-tiering-engine.d.ts.map +1 -1
- package/dist/services/context-tiering-engine.js +2 -4
- package/dist/services/context-tiering-engine.js.map +1 -1
- package/dist/services/cross-analyzer.d.ts +1 -3
- package/dist/services/cross-analyzer.d.ts.map +1 -1
- package/dist/services/cross-analyzer.js +28 -28
- package/dist/services/cross-analyzer.js.map +1 -1
- package/dist/services/dependency-graph.d.ts.map +1 -1
- package/dist/services/dependency-graph.js +148 -28
- package/dist/services/dependency-graph.js.map +1 -1
- package/dist/services/design-completeness.d.ts +19 -0
- package/dist/services/design-completeness.d.ts.map +1 -0
- package/dist/services/design-completeness.js +58 -0
- package/dist/services/design-completeness.js.map +1 -0
- package/dist/services/diagram-generator.d.ts +4 -96
- package/dist/services/diagram-generator.d.ts.map +1 -1
- package/dist/services/diagram-generator.js +18 -1051
- package/dist/services/diagram-generator.js.map +1 -1
- package/dist/services/doc-generator.d.ts +19 -52
- package/dist/services/doc-generator.d.ts.map +1 -1
- package/dist/services/doc-generator.js +420 -524
- package/dist/services/doc-generator.js.map +1 -1
- package/dist/services/document-converter.d.ts +1 -1
- package/dist/services/document-converter.d.ts.map +1 -1
- package/dist/services/document-converter.js +35 -21
- package/dist/services/document-converter.js.map +1 -1
- package/dist/services/ears-validator.d.ts +1 -1
- package/dist/services/ears-validator.d.ts.map +1 -1
- package/dist/services/ears-validator.js +36 -11
- package/dist/services/ears-validator.js.map +1 -1
- package/dist/services/execution-context.d.ts +45 -0
- package/dist/services/execution-context.d.ts.map +1 -0
- package/dist/services/execution-context.js +160 -0
- package/dist/services/execution-context.js.map +1 -0
- package/dist/services/feature-package-generator.d.ts.map +1 -1
- package/dist/services/feature-package-generator.js +43 -15
- package/dist/services/feature-package-generator.js.map +1 -1
- package/dist/services/file-manager.d.ts +16 -4
- package/dist/services/file-manager.d.ts.map +1 -1
- package/dist/services/file-manager.js +98 -8
- package/dist/services/file-manager.js.map +1 -1
- package/dist/services/git-manager.d.ts +1 -1
- package/dist/services/git-manager.d.ts.map +1 -1
- package/dist/services/git-manager.js +18 -7
- package/dist/services/git-manager.js.map +1 -1
- package/dist/services/iac-generator.d.ts +57 -11
- package/dist/services/iac-generator.d.ts.map +1 -1
- package/dist/services/iac-generator.js +690 -175
- package/dist/services/iac-generator.js.map +1 -1
- package/dist/services/intent-drift-engine.d.ts.map +1 -1
- package/dist/services/intent-drift-engine.js +19 -2
- package/dist/services/intent-drift-engine.js.map +1 -1
- package/dist/services/methodology.d.ts.map +1 -1
- package/dist/services/methodology.js +86 -22
- package/dist/services/methodology.js.map +1 -1
- package/dist/services/metrics-generator.d.ts +1 -2
- package/dist/services/metrics-generator.d.ts.map +1 -1
- package/dist/services/metrics-generator.js +30 -21
- package/dist/services/metrics-generator.js.map +1 -1
- package/dist/services/model-routing-engine.d.ts +4 -4
- package/dist/services/model-routing-engine.d.ts.map +1 -1
- package/dist/services/model-routing-engine.js +73 -72
- package/dist/services/model-routing-engine.js.map +1 -1
- package/dist/services/pbt-generator.d.ts +10 -31
- package/dist/services/pbt-generator.d.ts.map +1 -1
- package/dist/services/pbt-generator.js +44 -515
- package/dist/services/pbt-generator.js.map +1 -1
- package/dist/services/rate-limiter.d.ts +8 -0
- package/dist/services/rate-limiter.d.ts.map +1 -1
- package/dist/services/rate-limiter.js +18 -0
- package/dist/services/rate-limiter.js.map +1 -1
- package/dist/services/rbac-engine.d.ts.map +1 -1
- package/dist/services/rbac-engine.js +1 -3
- package/dist/services/rbac-engine.js.map +1 -1
- package/dist/services/state-machine.d.ts +37 -16
- package/dist/services/state-machine.d.ts.map +1 -1
- package/dist/services/state-machine.js +265 -233
- package/dist/services/state-machine.js.map +1 -1
- package/dist/services/template-engine.d.ts +11 -5
- package/dist/services/template-engine.d.ts.map +1 -1
- package/dist/services/template-engine.js +51 -23
- package/dist/services/template-engine.js.map +1 -1
- package/dist/services/test-generator.d.ts +11 -9
- package/dist/services/test-generator.d.ts.map +1 -1
- package/dist/services/test-generator.js +104 -94
- package/dist/services/test-generator.js.map +1 -1
- package/dist/services/test-result-parser.d.ts.map +1 -1
- package/dist/services/test-result-parser.js +5 -4
- package/dist/services/test-result-parser.js.map +1 -1
- package/dist/services/test-traceability-mapper.d.ts.map +1 -1
- package/dist/services/test-traceability-mapper.js +16 -4
- package/dist/services/test-traceability-mapper.js.map +1 -1
- package/dist/services/transcript-parser.d.ts +1 -1
- package/dist/services/transcript-parser.d.ts.map +1 -1
- package/dist/services/transcript-parser.js +61 -27
- package/dist/services/transcript-parser.js.map +1 -1
- package/dist/services/work-item-exporter.d.ts +1 -1
- package/dist/services/work-item-exporter.d.ts.map +1 -1
- package/dist/services/work-item-exporter.js +14 -2
- package/dist/services/work-item-exporter.js.map +1 -1
- package/dist/templates/design.md +6 -0
- package/dist/tools/analysis.d.ts +1 -1
- package/dist/tools/analysis.d.ts.map +1 -1
- package/dist/tools/analysis.js +29 -25
- package/dist/tools/analysis.js.map +1 -1
- package/dist/tools/audit.d.ts.map +1 -1
- package/dist/tools/audit.js +4 -2
- package/dist/tools/audit.js.map +1 -1
- package/dist/tools/checkpoint.d.ts.map +1 -1
- package/dist/tools/checkpoint.js +88 -77
- package/dist/tools/checkpoint.js.map +1 -1
- package/dist/tools/context.d.ts +1 -1
- package/dist/tools/context.d.ts.map +1 -1
- package/dist/tools/context.js +8 -15
- package/dist/tools/context.js.map +1 -1
- package/dist/tools/documentation.d.ts +1 -4
- package/dist/tools/documentation.d.ts.map +1 -1
- package/dist/tools/documentation.js +115 -159
- package/dist/tools/documentation.js.map +1 -1
- package/dist/tools/environment.d.ts +3 -3
- package/dist/tools/environment.d.ts.map +1 -1
- package/dist/tools/environment.js +76 -116
- package/dist/tools/environment.js.map +1 -1
- package/dist/tools/infrastructure.d.ts +1 -1
- package/dist/tools/infrastructure.d.ts.map +1 -1
- package/dist/tools/infrastructure.js +50 -53
- package/dist/tools/infrastructure.js.map +1 -1
- package/dist/tools/input.d.ts +1 -1
- package/dist/tools/input.d.ts.map +1 -1
- package/dist/tools/input.js +46 -37
- package/dist/tools/input.js.map +1 -1
- package/dist/tools/integration.d.ts +1 -1
- package/dist/tools/integration.d.ts.map +1 -1
- package/dist/tools/integration.js +86 -98
- package/dist/tools/integration.js.map +1 -1
- package/dist/tools/metrics.d.ts +4 -4
- package/dist/tools/metrics.d.ts.map +1 -1
- package/dist/tools/metrics.js +22 -44
- package/dist/tools/metrics.js.map +1 -1
- package/dist/tools/pbt.d.ts +1 -1
- package/dist/tools/pbt.d.ts.map +1 -1
- package/dist/tools/pbt.js +13 -25
- package/dist/tools/pbt.js.map +1 -1
- package/dist/tools/pipeline-writers.d.ts +193 -0
- package/dist/tools/pipeline-writers.d.ts.map +1 -0
- package/dist/tools/pipeline-writers.js +203 -0
- package/dist/tools/pipeline-writers.js.map +1 -0
- package/dist/tools/pipeline.d.ts +1 -1
- package/dist/tools/pipeline.d.ts.map +1 -1
- package/dist/tools/pipeline.js +261 -431
- package/dist/tools/pipeline.js.map +1 -1
- package/dist/tools/quality.d.ts +3 -3
- package/dist/tools/quality.d.ts.map +1 -1
- package/dist/tools/quality.js +401 -129
- package/dist/tools/quality.js.map +1 -1
- package/dist/tools/rbac.d.ts.map +1 -1
- package/dist/tools/rbac.js +7 -4
- package/dist/tools/rbac.js.map +1 -1
- package/dist/tools/response-builder.d.ts +1 -1
- package/dist/tools/response-builder.d.ts.map +1 -1
- package/dist/tools/response-builder.js +12 -13
- package/dist/tools/response-builder.js.map +1 -1
- package/dist/tools/routing.d.ts.map +1 -1
- package/dist/tools/routing.js +3 -9
- package/dist/tools/routing.js.map +1 -1
- package/dist/tools/testing.d.ts.map +1 -1
- package/dist/tools/testing.js +59 -56
- package/dist/tools/testing.js.map +1 -1
- package/dist/tools/tool-enforcement.d.ts +3 -1
- package/dist/tools/tool-enforcement.d.ts.map +1 -1
- package/dist/tools/tool-enforcement.js +85 -59
- package/dist/tools/tool-enforcement.js.map +1 -1
- package/dist/tools/tool-result.d.ts +1 -0
- package/dist/tools/tool-result.d.ts.map +1 -1
- package/dist/tools/tool-result.js.map +1 -1
- package/dist/tools/transcript.d.ts +1 -1
- package/dist/tools/transcript.d.ts.map +1 -1
- package/dist/tools/transcript.js +357 -506
- package/dist/tools/transcript.js.map +1 -1
- package/dist/tools/turnkey.d.ts +1 -31
- package/dist/tools/turnkey.d.ts.map +1 -1
- package/dist/tools/turnkey.js +124 -484
- package/dist/tools/turnkey.js.map +1 -1
- package/dist/tools/utility.d.ts +2 -2
- package/dist/tools/utility.d.ts.map +1 -1
- package/dist/tools/utility.js +156 -164
- package/dist/tools/utility.js.map +1 -1
- package/dist/tools/visualization.d.ts +1 -25
- package/dist/tools/visualization.d.ts.map +1 -1
- package/dist/tools/visualization.js +250 -527
- package/dist/tools/visualization.js.map +1 -1
- package/dist/types.d.ts +39 -13
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/artifact-metadata.d.ts +8 -0
- package/dist/utils/artifact-metadata.d.ts.map +1 -0
- package/dist/utils/artifact-metadata.js +10 -0
- package/dist/utils/artifact-metadata.js.map +1 -0
- package/dist/utils/context-helper.d.ts +1 -1
- package/dist/utils/context-helper.d.ts.map +1 -1
- package/dist/utils/context-helper.js.map +1 -1
- package/dist/utils/http-auth.d.ts.map +1 -1
- package/dist/utils/http-auth.js +1 -1
- package/dist/utils/http-auth.js.map +1 -1
- package/dist/utils/id-contracts.d.ts +21 -0
- package/dist/utils/id-contracts.d.ts.map +1 -1
- package/dist/utils/id-contracts.js +60 -1
- package/dist/utils/id-contracts.js.map +1 -1
- package/dist/utils/requirement-partition.d.ts +8 -0
- package/dist/utils/requirement-partition.d.ts.map +1 -0
- package/dist/utils/requirement-partition.js +15 -0
- package/dist/utils/requirement-partition.js.map +1 -0
- package/dist/utils/routing-helper.d.ts +1 -1
- package/dist/utils/routing-helper.d.ts.map +1 -1
- package/dist/utils/routing-helper.js.map +1 -1
- package/dist/utils/safe-read.d.ts +10 -0
- package/dist/utils/safe-read.d.ts.map +1 -0
- package/dist/utils/safe-read.js +10 -0
- package/dist/utils/safe-read.js.map +1 -0
- package/dist/utils/task-parser.d.ts.map +1 -1
- package/dist/utils/task-parser.js +1 -1
- package/dist/utils/task-parser.js.map +1 -1
- package/dist/utils/test-quality.d.ts +10 -0
- package/dist/utils/test-quality.d.ts.map +1 -0
- package/dist/utils/test-quality.js +10 -0
- package/dist/utils/test-quality.js.map +1 -0
- package/dist/utils/token-table.d.ts +20 -0
- package/dist/utils/token-table.d.ts.map +1 -1
- package/dist/utils/token-table.js +2 -2
- package/dist/utils/token-table.js.map +1 -1
- package/package.json +7 -3
- package/templates/design.md +6 -0
- package/dist/utils/design-stubs.d.ts +0 -32
- package/dist/utils/design-stubs.d.ts.map +0 -1
- package/dist/utils/design-stubs.js +0 -103
- package/dist/utils/design-stubs.js.map +0 -1
|
@@ -1,131 +1,44 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# specky-branch-validator.sh — Validate
|
|
3
|
-
#
|
|
4
|
-
# Type: Mixed (see below) | Trigger: PreToolUse | All phases
|
|
5
|
-
# • Advisory (exit 0, warn) for sdd_* pipeline tools (always).
|
|
6
|
-
# • For native edit tools (Write|Edit|MultiEdit) on a wrong branch during
|
|
7
|
-
# an active pipeline:
|
|
8
|
-
# - default (SPECKY_GUARD unset OR "off"/"advisory") → warn, exit 0
|
|
9
|
-
# - SPECKY_GUARD=strict → exit 2 (BLOCK)
|
|
10
|
-
#
|
|
11
|
-
# Rationale (rc.13): rc.10-rc.12 defaulted Write|Edit|MultiEdit to BLOCKING,
|
|
12
|
-
# which burned pilots who run `specky init` and then edit anything from
|
|
13
|
-
# develop/main. Enforcement is now explicit opt-in.
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# specky-branch-validator.sh — Validate persisted release branch policy.
|
|
3
|
+
# Type: advisory by default; strict for native edits when SPECKY_GUARD=strict.
|
|
14
4
|
|
|
15
5
|
set -euo pipefail
|
|
6
|
+
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
7
|
+
source "$SCRIPT_DIR/specky-contract-context.bash"
|
|
16
8
|
|
|
17
9
|
TOOL="${SDD_TOOL_NAME:-unknown}"
|
|
18
10
|
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr -d '\n' || true)
|
|
19
11
|
[ -z "$CURRENT_BRANCH" ] && CURRENT_BRANCH="unknown"
|
|
20
12
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
13
|
+
specky_load_contract_context || exit $?
|
|
14
|
+
if [ "${SPECKY_CONTEXT_ACTIVE:-0}" != "1" ]; then
|
|
15
|
+
echo "ℹ️ Branch Validator — no explicit feature context; no branch inferred."
|
|
16
|
+
exit 0
|
|
25
17
|
fi
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if [[ "$TOOL" == "Write" || "$TOOL" == "Edit" || "$TOOL" == "MultiEdit" ]]; then
|
|
29
|
-
LATEST=$(ls -td .specs/*/ 2>/dev/null | head -1 || true)
|
|
30
|
-
if [ -z "$LATEST" ]; then exit 0; fi
|
|
31
|
-
STATE="$LATEST/.sdd-state.json"
|
|
32
|
-
if [ ! -f "$STATE" ]; then exit 0; fi
|
|
33
|
-
|
|
34
|
-
PHASE="?"
|
|
35
|
-
if command -v jq >/dev/null 2>&1; then
|
|
36
|
-
PHASE=$(jq -r '.current_phase // "?"' "$STATE" 2>/dev/null || echo "?")
|
|
37
|
-
fi
|
|
38
|
-
|
|
39
|
-
FEATURE=$(basename "$LATEST")
|
|
40
|
-
|
|
41
|
-
emit_violation() {
|
|
42
|
-
local expected="$1"
|
|
43
|
-
if [ "$SPECKY_GUARD_MODE" = "strict" ]; then
|
|
44
|
-
echo "" >&2
|
|
45
|
-
echo "🚫 [specky-branch-validator] BLOCKED — $TOOL on '$CURRENT_BRANCH' (phase $PHASE expects $expected) [SPECKY_GUARD=strict]" >&2
|
|
46
|
-
echo " Feature: $FEATURE" >&2
|
|
47
|
-
echo " Fix: git checkout $expected (or: git checkout -b spec/$FEATURE)" >&2
|
|
48
|
-
echo " Disable: unset SPECKY_GUARD" >&2
|
|
49
|
-
exit 2
|
|
50
|
-
fi
|
|
51
|
-
echo "⚠️ [specky-branch-validator] $TOOL on '$CURRENT_BRANCH' during phase $PHASE (expected $expected). Enforce with: export SPECKY_GUARD=strict" >&2
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
case "$PHASE" in
|
|
55
|
-
init|discover|specify|clarify|design|tasks|analyze|implement)
|
|
56
|
-
if [[ "$CURRENT_BRANCH" != spec/* ]]; then
|
|
57
|
-
emit_violation "spec/$FEATURE"
|
|
58
|
-
fi
|
|
59
|
-
;;
|
|
60
|
-
verify)
|
|
61
|
-
if [[ "$CURRENT_BRANCH" != "develop" ]]; then
|
|
62
|
-
emit_violation "develop"
|
|
63
|
-
fi
|
|
64
|
-
;;
|
|
65
|
-
release)
|
|
66
|
-
if [[ "$CURRENT_BRANCH" != "stage" ]]; then
|
|
67
|
-
emit_violation "stage"
|
|
68
|
-
fi
|
|
69
|
-
;;
|
|
70
|
-
esac
|
|
18
|
+
if [ "${SPECKY_RELEASE_ENABLED:-0}" != "1" ]; then
|
|
19
|
+
echo "ℹ️ Branch Validator — release capability disabled by $SPECKY_CONTRACT_ID."
|
|
71
20
|
exit 0
|
|
72
21
|
fi
|
|
73
22
|
|
|
74
|
-
|
|
23
|
+
EXPECTED_FEATURE_BRANCH="${SPECKY_BRANCH_PREFIX}${SPECKY_FEATURE_NUMBER}-${SPECKY_FEATURE_NAME}"
|
|
24
|
+
EXPECTED="$EXPECTED_FEATURE_BRANCH"
|
|
25
|
+
if [ "$TOOL" = "sdd_create_branch" ]; then
|
|
26
|
+
EXPECTED="$SPECKY_BASE_BRANCH"
|
|
27
|
+
fi
|
|
75
28
|
|
|
76
|
-
|
|
77
|
-
echo "
|
|
78
|
-
|
|
79
|
-
|
|
29
|
+
if [ "$CURRENT_BRANCH" = "$EXPECTED" ]; then
|
|
30
|
+
echo "✅ Branch Validator — $CURRENT_BRANCH matches persisted release policy."
|
|
31
|
+
exit 0
|
|
32
|
+
fi
|
|
80
33
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
fi
|
|
87
|
-
;;
|
|
88
|
-
sdd_write_spec|sdd_turnkey_spec|sdd_figma_to_spec|sdd_write_design|sdd_write_tasks|sdd_implement|sdd_generate_tests|sdd_generate_pbt|sdd_generate_iac|sdd_generate_dockerfile)
|
|
89
|
-
# Spec work must be on spec/* branch
|
|
90
|
-
if [[ "$CURRENT_BRANCH" != spec/* ]]; then
|
|
91
|
-
warn "Spec work should be on a spec/NNN-* branch, not '$CURRENT_BRANCH'" "spec/NNN-feature-name"
|
|
92
|
-
echo " Flow: spec/NNN-* → develop → stage → main"
|
|
93
|
-
fi
|
|
94
|
-
;;
|
|
95
|
-
sdd_discover|sdd_research|sdd_import_document|sdd_import_transcript|sdd_clarify|sdd_validate_ears)
|
|
96
|
-
# Research/clarify on spec branch
|
|
97
|
-
if [[ "$CURRENT_BRANCH" != spec/* ]]; then
|
|
98
|
-
warn "Research and clarification should be on a spec/NNN-* branch" "spec/NNN-feature-name"
|
|
99
|
-
fi
|
|
100
|
-
;;
|
|
101
|
-
sdd_verify_tests|sdd_verify_tasks|sdd_check_sync)
|
|
102
|
-
# Verification on spec branch
|
|
103
|
-
if [[ "$CURRENT_BRANCH" != spec/* ]]; then
|
|
104
|
-
warn "Verification should be on a spec/NNN-* branch" "spec/NNN-feature-name"
|
|
105
|
-
fi
|
|
106
|
-
;;
|
|
107
|
-
sdd_run_analysis|sdd_cross_analyze|sdd_compliance_check)
|
|
108
|
-
# Review on develop (after merge from spec)
|
|
109
|
-
if [[ "$CURRENT_BRANCH" != "develop" ]] && [[ "$CURRENT_BRANCH" != spec/* ]]; then
|
|
110
|
-
warn "Review tools typically run on 'develop' after merge from spec" "develop"
|
|
111
|
-
fi
|
|
112
|
-
;;
|
|
113
|
-
sdd_create_pr)
|
|
114
|
-
# PR: branch determines target
|
|
115
|
-
if [[ "$CURRENT_BRANCH" == spec/* ]]; then
|
|
116
|
-
echo " ℹ️ spec branch → PR will target develop"
|
|
117
|
-
elif [[ "$CURRENT_BRANCH" == "develop" ]]; then
|
|
118
|
-
echo " ℹ️ develop → PR will target stage"
|
|
119
|
-
elif [[ "$CURRENT_BRANCH" == "stage" ]]; then
|
|
120
|
-
echo " ℹ️ stage → PR will target main"
|
|
121
|
-
elif [[ "$CURRENT_BRANCH" == "main" ]]; then
|
|
122
|
-
warn "Cannot create PR from main — nothing to merge" "spec/*, develop, or stage"
|
|
123
|
-
fi
|
|
124
|
-
;;
|
|
125
|
-
*)
|
|
126
|
-
echo " ✅ No branch requirement for $TOOL"
|
|
127
|
-
;;
|
|
128
|
-
esac
|
|
34
|
+
MESSAGE="branch '$CURRENT_BRANCH' does not match persisted release policy '$EXPECTED' for $TOOL"
|
|
35
|
+
if [[ "$TOOL" == "Write" || "$TOOL" == "Edit" || "$TOOL" == "MultiEdit" ]] && [ "${SPECKY_GUARD:-advisory}" = "strict" ]; then
|
|
36
|
+
echo "🚫 [specky-branch-validator] BLOCKED — $MESSAGE" >&2
|
|
37
|
+
exit 2
|
|
38
|
+
fi
|
|
129
39
|
|
|
130
|
-
|
|
40
|
+
echo "⚠️ [specky-branch-validator] $MESSAGE" >&2
|
|
41
|
+
echo " Contract: $SPECKY_CONTRACT_ID" >&2
|
|
42
|
+
echo " Base: $SPECKY_BASE_BRANCH | Prefix: $SPECKY_BRANCH_PREFIX" >&2
|
|
43
|
+
echo " Enforce native edits with: export SPECKY_GUARD=strict" >&2
|
|
131
44
|
exit 0
|
|
@@ -5,14 +5,17 @@
|
|
|
5
5
|
# Paper: arXiv:2603.22106 — cognitive surrender measurement
|
|
6
6
|
|
|
7
7
|
set -euo pipefail
|
|
8
|
+
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
|
9
|
+
. "$SCRIPT_DIR/specky-contract-context.bash"
|
|
10
|
+
specky_load_contract_context || exit $?
|
|
11
|
+
[ "${SPECKY_CONTEXT_ACTIVE:-0}" = "1" ] || exit 0
|
|
8
12
|
|
|
9
|
-
STATE
|
|
10
|
-
[ -z "$STATE" ] || [ ! -f "$STATE" ] && exit 0
|
|
13
|
+
STATE="$SPECKY_STATE_FILE"
|
|
11
14
|
|
|
12
15
|
# Check if gate history exists in state
|
|
13
16
|
if command -v jq &>/dev/null && [ -f "$STATE" ]; then
|
|
14
17
|
GATES=$(jq -r '.gate_history // [] | length' "$STATE" 2>/dev/null || echo "0")
|
|
15
|
-
LGTM_NO_MOD=$(jq -r '[.gate_history // [] | .[] | select(.
|
|
18
|
+
LGTM_NO_MOD=$(jq -r '[.gate_history // [] | .[] | select(.was_modified == false)] | length' "$STATE" 2>/dev/null || echo "0")
|
|
16
19
|
|
|
17
20
|
if [ "$GATES" -gt 0 ]; then
|
|
18
21
|
RATE=$((LGTM_NO_MOD * 100 / GATES))
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Shared explicit feature-contract context for Specky hooks.
|
|
2
|
+
|
|
3
|
+
specky_load_contract_context() {
|
|
4
|
+
local context_dir context_exports
|
|
5
|
+
context_dir=$(cd "$(dirname "$0")" && pwd)
|
|
6
|
+
context_exports=$(node "$context_dir/specky-contract-context.mjs" shell) || return $?
|
|
7
|
+
eval "$context_exports"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
specky_has_capability() {
|
|
11
|
+
local capability=",${SPECKY_CAPABILITIES:-},"
|
|
12
|
+
case "$capability" in
|
|
13
|
+
*",$1,"*) return 0 ;;
|
|
14
|
+
*) return 1 ;;
|
|
15
|
+
esac
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
specky_require_feature_context() {
|
|
19
|
+
specky_load_contract_context || return $?
|
|
20
|
+
if [ "${SPECKY_CONTEXT_ACTIVE:-0}" != "1" ]; then
|
|
21
|
+
echo "[specky] Explicit feature context required: ${SPECKY_CONTEXT_REASON:-missing context}." >&2
|
|
22
|
+
return 2
|
|
23
|
+
fi
|
|
24
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
|
|
3
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
4
|
+
import { relative, resolve, sep } from "node:path";
|
|
5
|
+
|
|
6
|
+
function fail(message) {
|
|
7
|
+
console.error(`[specky-contract-context] ${message}`);
|
|
8
|
+
process.exit(2);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function readHookInput() {
|
|
12
|
+
const fromEnvironment = process.env.SDD_HOOK_INPUT;
|
|
13
|
+
if (fromEnvironment?.trim()) return fromEnvironment;
|
|
14
|
+
if (process.stdin.isTTY) return "";
|
|
15
|
+
try {
|
|
16
|
+
return readFileSync(0, "utf8");
|
|
17
|
+
} catch {
|
|
18
|
+
return "";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function parseInput(raw) {
|
|
23
|
+
if (!raw.trim()) return {};
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(raw);
|
|
26
|
+
} catch {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function objects(value) {
|
|
32
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return [];
|
|
33
|
+
const record = value;
|
|
34
|
+
return [
|
|
35
|
+
record,
|
|
36
|
+
record.tool_input,
|
|
37
|
+
record.toolInput,
|
|
38
|
+
record.arguments,
|
|
39
|
+
record.input,
|
|
40
|
+
record.params,
|
|
41
|
+
record.params?.arguments,
|
|
42
|
+
record.request?.params?.arguments,
|
|
43
|
+
].filter(
|
|
44
|
+
(candidate) => typeof candidate === "object" && candidate !== null && !Array.isArray(candidate),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function findString(input, keys) {
|
|
49
|
+
for (const candidate of objects(input)) {
|
|
50
|
+
for (const key of keys) {
|
|
51
|
+
const value = candidate[key];
|
|
52
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function safeRelativePath(value, label) {
|
|
59
|
+
if (!value || value.startsWith("/") || value.startsWith("\\") || /^[A-Za-z]:/.test(value)) {
|
|
60
|
+
fail(`${label} must be a workspace-relative path.`);
|
|
61
|
+
}
|
|
62
|
+
const segments = value.split(/[\\/]/);
|
|
63
|
+
if (segments.includes("..") || value.includes("\0")) fail(`${label} contains unsafe traversal.`);
|
|
64
|
+
return segments.filter((segment) => segment && segment !== ".").join("/");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function canonicalize(value) {
|
|
68
|
+
if (Array.isArray(value)) return value.map(canonicalize);
|
|
69
|
+
if (typeof value !== "object" || value === null) return value;
|
|
70
|
+
return Object.keys(value)
|
|
71
|
+
.sort((left, right) => left.localeCompare(right))
|
|
72
|
+
.reduce((result, key) => {
|
|
73
|
+
result[key] = canonicalize(value[key]);
|
|
74
|
+
return result;
|
|
75
|
+
}, {});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function fingerprintContract(contract) {
|
|
79
|
+
const { fingerprint: _fingerprint, ...snapshot } = contract;
|
|
80
|
+
return createHash("sha256")
|
|
81
|
+
.update(JSON.stringify(canonicalize(snapshot)))
|
|
82
|
+
.digest("hex");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function safeEqualHex(left, right) {
|
|
86
|
+
if (!/^[a-f0-9]{64}$/.test(left) || !/^[a-f0-9]{64}$/.test(right)) return false;
|
|
87
|
+
return timingSafeEqual(Buffer.from(left, "hex"), Buffer.from(right, "hex"));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function shellQuote(value) {
|
|
91
|
+
return `'${String(value).replaceAll("'", `'"'"'`)}'`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function resolveContext() {
|
|
95
|
+
const workspace = resolve(process.env.SPECKY_HOOK_WORKSPACE ?? process.cwd());
|
|
96
|
+
const input = parseInput(readHookInput());
|
|
97
|
+
const requestedSpecDir = process.env.SDD_SPEC_DIR ?? findString(input, ["spec_dir", "specDir"]);
|
|
98
|
+
const requestedFeatureNumber =
|
|
99
|
+
process.env.SDD_FEATURE_NUMBER ?? findString(input, ["feature_number", "featureNumber"]);
|
|
100
|
+
|
|
101
|
+
if (!requestedSpecDir || !requestedFeatureNumber) {
|
|
102
|
+
return { active: false, reason: "missing explicit SDD_SPEC_DIR/SDD_FEATURE_NUMBER context" };
|
|
103
|
+
}
|
|
104
|
+
const specDir = safeRelativePath(requestedSpecDir, "spec_dir");
|
|
105
|
+
if (!/^\d{3}$/.test(requestedFeatureNumber)) fail("feature_number must be exactly three digits.");
|
|
106
|
+
|
|
107
|
+
const specRoot = resolve(workspace, specDir);
|
|
108
|
+
if (!existsSync(specRoot)) fail(`spec root does not exist: ${specDir}`);
|
|
109
|
+
const matches = readdirSync(specRoot, { withFileTypes: true }).filter(
|
|
110
|
+
(entry) => entry.isDirectory() && entry.name.startsWith(`${requestedFeatureNumber}-`),
|
|
111
|
+
);
|
|
112
|
+
if (matches.length !== 1) {
|
|
113
|
+
fail(
|
|
114
|
+
`feature ${requestedFeatureNumber} must resolve to exactly one directory in ${specDir}; found ${matches.length}.`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const featureName = matches[0].name.slice(4);
|
|
119
|
+
const featureDirectory = `${specDir}/${matches[0].name}`;
|
|
120
|
+
const statePath = resolve(workspace, featureDirectory, ".sdd-state.json");
|
|
121
|
+
const signaturePath = `${statePath}.sig`;
|
|
122
|
+
if (!existsSync(statePath) || !existsSync(signaturePath)) {
|
|
123
|
+
fail(
|
|
124
|
+
`feature ${requestedFeatureNumber} requires signed v5 state at ${featureDirectory}/.sdd-state.json.`,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const raw = readFileSync(statePath, "utf8");
|
|
129
|
+
let state;
|
|
130
|
+
try {
|
|
131
|
+
state = JSON.parse(raw);
|
|
132
|
+
} catch {
|
|
133
|
+
fail(`state is not valid JSON: ${relative(workspace, statePath)}`);
|
|
134
|
+
}
|
|
135
|
+
if (state.version !== "5.0.0") fail(`state version ${String(state.version)} requires migration.`);
|
|
136
|
+
|
|
137
|
+
const key =
|
|
138
|
+
process.env.SDD_STATE_KEY ??
|
|
139
|
+
createHash("sha256").update(`specky-state-v1:${workspace}`).digest("hex");
|
|
140
|
+
const expectedSignature = createHmac("sha256", key).update(raw).digest("hex");
|
|
141
|
+
const storedSignature = readFileSync(signaturePath, "utf8").trim();
|
|
142
|
+
if (!safeEqualHex(storedSignature, expectedSignature))
|
|
143
|
+
fail("feature state signature verification failed.");
|
|
144
|
+
|
|
145
|
+
if (
|
|
146
|
+
state.feature?.number !== requestedFeatureNumber ||
|
|
147
|
+
state.feature?.name !== featureName ||
|
|
148
|
+
state.feature?.directory !== featureDirectory
|
|
149
|
+
) {
|
|
150
|
+
fail(`feature state identity does not match ${featureDirectory}.`);
|
|
151
|
+
}
|
|
152
|
+
if (!state.contract || fingerprintContract(state.contract) !== state.contract.fingerprint) {
|
|
153
|
+
fail("feature contract fingerprint verification failed.");
|
|
154
|
+
}
|
|
155
|
+
if (
|
|
156
|
+
!Array.isArray(state.contract.phases) ||
|
|
157
|
+
!state.contract.phases.includes(state.current_phase)
|
|
158
|
+
) {
|
|
159
|
+
fail(`current phase ${String(state.current_phase)} is not enabled by the feature contract.`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const capabilities = Array.isArray(state.contract.capabilities)
|
|
163
|
+
? state.contract.capabilities
|
|
164
|
+
: [];
|
|
165
|
+
const capabilityConfig = state.contract.capability_config ?? {};
|
|
166
|
+
const configuredCapabilities = Object.keys(capabilityConfig).sort();
|
|
167
|
+
const declaredCapabilities = [...new Set(capabilities)].sort();
|
|
168
|
+
if (JSON.stringify(configuredCapabilities) !== JSON.stringify(declaredCapabilities)) {
|
|
169
|
+
fail("capabilities and capability_config keys do not match.");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
active: true,
|
|
174
|
+
workspace,
|
|
175
|
+
specDir,
|
|
176
|
+
featureNumber: requestedFeatureNumber,
|
|
177
|
+
featureName,
|
|
178
|
+
featureDirectory,
|
|
179
|
+
statePath: relative(workspace, statePath).split(sep).join("/"),
|
|
180
|
+
phase: state.current_phase,
|
|
181
|
+
contract: state.contract,
|
|
182
|
+
gateDecision: state.gate_decision?.decision ?? "",
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function printShell(context) {
|
|
187
|
+
const contract = context.contract ?? {};
|
|
188
|
+
const capabilities = Array.isArray(contract.capabilities) ? contract.capabilities : [];
|
|
189
|
+
const release = contract.capability_config?.release;
|
|
190
|
+
const tdd = contract.capability_config?.tdd;
|
|
191
|
+
const compliance = contract.capability_config?.compliance;
|
|
192
|
+
const development = contract.capability_config?.["dev-environment"];
|
|
193
|
+
const iac = contract.capability_config?.iac;
|
|
194
|
+
const values = {
|
|
195
|
+
SPECKY_CONTEXT_ACTIVE: context.active ? "1" : "0",
|
|
196
|
+
SPECKY_CONTEXT_REASON: context.reason ?? "",
|
|
197
|
+
SPECKY_SPEC_DIR: context.specDir ?? "",
|
|
198
|
+
SPECKY_FEATURE_NUMBER: context.featureNumber ?? "",
|
|
199
|
+
SPECKY_FEATURE_NAME: context.featureName ?? "",
|
|
200
|
+
SPECKY_FEATURE_DIR: context.featureDirectory ?? "",
|
|
201
|
+
SPECKY_STATE_FILE: context.statePath ?? "",
|
|
202
|
+
SPECKY_PHASE: context.phase ?? "",
|
|
203
|
+
SPECKY_CONTRACT_ID: contract.id ?? "",
|
|
204
|
+
SPECKY_CONTRACT_FINGERPRINT: contract.fingerprint ?? "",
|
|
205
|
+
SPECKY_LIFECYCLE: contract.lifecycle ?? "",
|
|
206
|
+
SPECKY_WORKLOAD: contract.workload ?? "",
|
|
207
|
+
SPECKY_EXECUTION_MODE: contract.execution_mode ?? "",
|
|
208
|
+
SPECKY_CAPABILITIES: capabilities.join(","),
|
|
209
|
+
SPECKY_GATE_DECISION: context.gateDecision ?? "",
|
|
210
|
+
SPECKY_RELEASE_ENABLED: release ? "1" : "0",
|
|
211
|
+
SPECKY_BRANCH_PREFIX: release?.branch_prefix ?? "",
|
|
212
|
+
SPECKY_BASE_BRANCH: release?.base_branch ?? "",
|
|
213
|
+
SPECKY_CHECKPOINTS_REQUIRED: release?.checkpoints ? "1" : "0",
|
|
214
|
+
SPECKY_TDD_ENABLED: tdd ? "1" : "0",
|
|
215
|
+
SPECKY_TDD_THRESHOLD: tdd ? String(tdd.coverage_threshold) : "",
|
|
216
|
+
SPECKY_COMPLIANCE_ENABLED: compliance ? "1" : "0",
|
|
217
|
+
SPECKY_COMPLIANCE_FRAMEWORKS: compliance?.frameworks?.join(",") ?? "",
|
|
218
|
+
SPECKY_DEV_ENV_ENABLED: development ? "1" : "0",
|
|
219
|
+
SPECKY_DEV_LANGUAGE: development?.language ?? "",
|
|
220
|
+
SPECKY_IAC_ENABLED: iac ? "1" : "0",
|
|
221
|
+
SPECKY_IAC_PROVIDER: iac?.provider ?? "",
|
|
222
|
+
SPECKY_IAC_CLOUD: iac?.cloud ?? "",
|
|
223
|
+
};
|
|
224
|
+
for (const [key, value] of Object.entries(values)) console.log(`${key}=${shellQuote(value)}`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const command = process.argv[2] ?? "shell";
|
|
228
|
+
const context = resolveContext();
|
|
229
|
+
if (command === "json") {
|
|
230
|
+
console.log(JSON.stringify(context));
|
|
231
|
+
} else if (command === "shell") {
|
|
232
|
+
printShell(context);
|
|
233
|
+
} else {
|
|
234
|
+
fail(`unknown command ${command}`);
|
|
235
|
+
}
|
|
@@ -5,14 +5,17 @@
|
|
|
5
5
|
# Paper: arXiv:2602.20478, arXiv:2603.22106
|
|
6
6
|
|
|
7
7
|
set -euo pipefail
|
|
8
|
+
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
|
9
|
+
. "$SCRIPT_DIR/specky-contract-context.bash"
|
|
10
|
+
specky_load_contract_context || exit $?
|
|
11
|
+
[ "${SPECKY_CONTEXT_ACTIVE:-0}" = "1" ] || exit 0
|
|
8
12
|
|
|
9
|
-
LATEST
|
|
10
|
-
[ -z "$LATEST" ] && exit 0
|
|
13
|
+
LATEST="$SPECKY_FEATURE_DIR"
|
|
11
14
|
CONST="$LATEST/CONSTITUTION.md"
|
|
12
15
|
SPEC="$LATEST/SPECIFICATION.md"
|
|
13
16
|
[ -f "$CONST" ] && [ -f "$SPEC" ] || exit 0
|
|
14
17
|
|
|
15
|
-
echo "🧭 Drift Monitor: $(
|
|
18
|
+
echo "🧭 Drift Monitor: ${SPECKY_FEATURE_NUMBER}-${SPECKY_FEATURE_NAME} ($SPECKY_CONTRACT_ID)"
|
|
16
19
|
|
|
17
20
|
# Simple drift: compare key terms in constitution vs spec (POSIX ERE for portability)
|
|
18
21
|
CONST_TERMS=$(grep -oE '[A-Z][a-z]+([[:space:]][A-Z][a-z]+)+' "$CONST" 2>/dev/null | sort -u | wc -l)
|
|
@@ -10,9 +10,12 @@
|
|
|
10
10
|
# plain `set -eu` instead of bash-only `set -o pipefail`.
|
|
11
11
|
|
|
12
12
|
set -eu
|
|
13
|
+
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
|
14
|
+
. "$SCRIPT_DIR/specky-contract-context.bash"
|
|
15
|
+
specky_load_contract_context || exit $?
|
|
16
|
+
[ "${SPECKY_CONTEXT_ACTIVE:-0}" = "1" ] || exit 0
|
|
13
17
|
|
|
14
|
-
LATEST
|
|
15
|
-
[ -z "$LATEST" ] && exit 0
|
|
18
|
+
LATEST="$SPECKY_FEATURE_DIR"
|
|
16
19
|
SPEC="$LATEST/SPECIFICATION.md"
|
|
17
20
|
|
|
18
21
|
if [ ! -f "$SPEC" ] || [ ! -r "$SPEC" ]; then
|
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
# Summarizes artifact and prompts for LGTM before phase advancement
|
|
5
5
|
|
|
6
6
|
set -euo pipefail
|
|
7
|
+
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
|
8
|
+
. "$SCRIPT_DIR/specky-contract-context.bash"
|
|
9
|
+
specky_load_contract_context || exit $?
|
|
10
|
+
[ "${SPECKY_CONTEXT_ACTIVE:-0}" = "1" ] || exit 0
|
|
7
11
|
|
|
8
12
|
TOOL="${SDD_TOOL_NAME:-unknown}"
|
|
9
|
-
LATEST
|
|
13
|
+
LATEST="$SPECKY_FEATURE_DIR"
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
FEATURE=$(basename "$LATEST")
|
|
15
|
+
FEATURE="${SPECKY_FEATURE_NUMBER}-${SPECKY_FEATURE_NAME}"
|
|
14
16
|
|
|
15
17
|
print_summary() {
|
|
16
18
|
local file="$1" label="$2"
|
|
@@ -29,25 +31,25 @@ case "$TOOL" in
|
|
|
29
31
|
sdd_write_spec|sdd_turnkey_spec|sdd_figma_to_spec)
|
|
30
32
|
print_summary "SPECIFICATION.md" "SPECIFICATION.md"
|
|
31
33
|
echo ""
|
|
32
|
-
echo "⏸ LGTM
|
|
34
|
+
echo "⏸ LGTM REVIEW — Specify ($SPECKY_CONTRACT_ID)"
|
|
33
35
|
echo " Review SPECIFICATION.md above. Are the requirements correct?"
|
|
34
|
-
echo "
|
|
36
|
+
echo " If workspace policy requires LGTM, pass lgtm:true to sdd_advance_phase."
|
|
35
37
|
echo " Reply with feedback to revise."
|
|
36
38
|
;;
|
|
37
39
|
sdd_write_design)
|
|
38
40
|
print_summary "DESIGN.md" "DESIGN.md"
|
|
39
41
|
echo ""
|
|
40
|
-
echo "⏸ LGTM
|
|
42
|
+
echo "⏸ LGTM REVIEW — Design ($SPECKY_CONTRACT_ID)"
|
|
41
43
|
echo " Review DESIGN.md above. Is the architecture sound?"
|
|
42
|
-
echo "
|
|
44
|
+
echo " If workspace policy requires LGTM, pass lgtm:true to sdd_advance_phase."
|
|
43
45
|
echo " Reply with feedback to revise."
|
|
44
46
|
;;
|
|
45
47
|
sdd_write_tasks)
|
|
46
48
|
print_summary "TASKS.md" "TASKS.md"
|
|
47
49
|
echo ""
|
|
48
|
-
echo "⏸ LGTM
|
|
50
|
+
echo "⏸ LGTM REVIEW — Tasks ($SPECKY_CONTRACT_ID)"
|
|
49
51
|
echo " Review TASKS.md above. Is the task breakdown complete?"
|
|
50
|
-
echo "
|
|
52
|
+
echo " If workspace policy requires LGTM, pass lgtm:true to sdd_advance_phase."
|
|
51
53
|
echo " Reply with feedback to revise."
|
|
52
54
|
;;
|
|
53
55
|
*)
|
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
# Paper: arXiv:2507.09089 — AI productivity paradox
|
|
6
6
|
|
|
7
7
|
set -euo pipefail
|
|
8
|
+
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
|
9
|
+
. "$SCRIPT_DIR/specky-contract-context.bash"
|
|
10
|
+
specky_load_contract_context || exit $?
|
|
11
|
+
[ "${SPECKY_CONTEXT_ACTIVE:-0}" = "1" ] || exit 0
|
|
8
12
|
|
|
9
|
-
LATEST
|
|
10
|
-
[ -z "$LATEST" ] && exit 0
|
|
13
|
+
LATEST="$SPECKY_FEATURE_DIR"
|
|
11
14
|
|
|
12
15
|
# Check if analysis is done but metrics not generated
|
|
13
16
|
if [ -f "$LATEST/ANALYSIS.md" ] && [ ! -f "$LATEST/specky-metrics-dashboard.html" ]; then
|
|
@@ -4,14 +4,16 @@
|
|
|
4
4
|
# Ensures phase artifacts exist and meet minimum quality after creation
|
|
5
5
|
|
|
6
6
|
set -euo pipefail
|
|
7
|
+
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
8
|
+
source "$SCRIPT_DIR/specky-contract-context.bash"
|
|
7
9
|
|
|
8
10
|
TOOL="${SDD_TOOL_NAME:-unknown}"
|
|
9
|
-
LATEST=$(ls -td .specs/*/ 2>/dev/null | head -1 || true)
|
|
10
11
|
FAILS=0
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
specky_require_feature_context || exit $?
|
|
14
|
+
LATEST="$SPECKY_FEATURE_DIR"
|
|
13
15
|
|
|
14
|
-
FEATURE
|
|
16
|
+
FEATURE="${SPECKY_FEATURE_NUMBER}-${SPECKY_FEATURE_NAME}"
|
|
15
17
|
echo "🚦 Phase Gate — $FEATURE — after $TOOL"
|
|
16
18
|
|
|
17
19
|
check_created() {
|
|
@@ -43,28 +45,35 @@ case "$TOOL" in
|
|
|
43
45
|
sdd_init)
|
|
44
46
|
check_created "CONSTITUTION.md" "CONSTITUTION.md"
|
|
45
47
|
check_created ".sdd-state.json" ".sdd-state.json"
|
|
48
|
+
check_created ".sdd-state.json.sig" ".sdd-state.json.sig"
|
|
46
49
|
;;
|
|
47
50
|
sdd_write_spec|sdd_turnkey_spec|sdd_figma_to_spec)
|
|
48
51
|
check_created "SPECIFICATION.md" "SPECIFICATION.md"
|
|
49
|
-
check_has_content "SPECIFICATION.md" "REQ-[A-Z]+-[0-9]+" "REQ-IDs"
|
|
50
|
-
check_has_content "SPECIFICATION.md" "(shall|When .* shall|While .* shall|Where .* shall|If .* then)" "EARS patterns"
|
|
52
|
+
check_has_content "SPECIFICATION.md" "REQ-[A-Z]+-[0-9]+" "REQ-IDs" 1
|
|
53
|
+
check_has_content "SPECIFICATION.md" "(shall|When .* shall|While .* shall|Where .* shall|If .* then)" "EARS patterns" 1
|
|
51
54
|
;;
|
|
52
55
|
sdd_write_design)
|
|
53
56
|
check_created "DESIGN.md" "DESIGN.md"
|
|
54
|
-
check_has_content "DESIGN.md" "##" "
|
|
57
|
+
check_has_content "DESIGN.md" "## 13\. Workload-Specific Design Contract" "Workload design contract" 1
|
|
58
|
+
check_has_content "DESIGN.md" "REQ-[A-Z]+-[0-9]+" "REQ-ID traceability" 1
|
|
59
|
+
;;
|
|
60
|
+
sdd_generate_all_diagrams)
|
|
61
|
+
check_created "DIAGRAMS.md" "DIAGRAMS.md"
|
|
62
|
+
REQUIRED_DIAGRAMS=$(node -e 'const s=JSON.parse(require("fs").readFileSync(process.argv[1],"utf8")); console.log(s.contract.required_diagrams.length)' "$SPECKY_STATE_FILE")
|
|
63
|
+
check_has_content "DIAGRAMS.md" '^```mermaid' "Contracted Mermaid diagrams" "$REQUIRED_DIAGRAMS"
|
|
55
64
|
;;
|
|
56
65
|
sdd_write_tasks)
|
|
57
66
|
check_created "TASKS.md" "TASKS.md"
|
|
58
67
|
check_has_content "TASKS.md" "REQ-[A-Z]+-[0-9]+" "REQ-ID traceability" 1
|
|
59
|
-
check_has_content "TASKS.md" "T
|
|
68
|
+
check_has_content "TASKS.md" "T-[0-9]{3}" "Task IDs" 1
|
|
60
69
|
;;
|
|
61
70
|
sdd_verify_tests|sdd_verify_tasks)
|
|
62
71
|
check_created "VERIFICATION.md" "VERIFICATION.md"
|
|
63
|
-
check_has_content "VERIFICATION.md" "pass_rate" "Pass rate metric" 1
|
|
72
|
+
check_has_content "VERIFICATION.md" "Pass Rate|pass_rate" "Pass rate metric" 1
|
|
64
73
|
;;
|
|
65
74
|
sdd_run_analysis)
|
|
66
75
|
check_created "ANALYSIS.md" "ANALYSIS.md"
|
|
67
|
-
check_has_content "ANALYSIS.md" "
|
|
76
|
+
check_has_content "ANALYSIS.md" "APPROVE|CHANGES_NEEDED|BLOCK" "Gate decision" 1
|
|
68
77
|
;;
|
|
69
78
|
sdd_cross_analyze)
|
|
70
79
|
check_created "CROSS_ANALYSIS.md" "CROSS_ANALYSIS.md"
|