specweave 0.32.0 → 0.32.3
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/CLAUDE.md +215 -2
- package/README.md +22 -0
- package/bin/specweave.js +52 -1
- package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.d.ts +100 -0
- package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.d.ts.map +1 -0
- package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.js +291 -0
- package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.js.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.d.ts +103 -0
- package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.d.ts.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.js +310 -0
- package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.js.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-permission-gate.d.ts +126 -0
- package/dist/plugins/specweave-jira/lib/jira-permission-gate.d.ts.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-permission-gate.js +207 -0
- package/dist/plugins/specweave-jira/lib/jira-permission-gate.js.map +1 -0
- package/dist/src/adapters/codex/README.md +1 -1
- package/dist/src/adapters/codex/adapter.js +1 -1
- package/dist/src/cli/commands/archive.d.ts +2 -0
- package/dist/src/cli/commands/archive.d.ts.map +1 -1
- package/dist/src/cli/commands/archive.js +33 -0
- package/dist/src/cli/commands/archive.js.map +1 -1
- package/dist/src/cli/commands/cache.d.ts +17 -0
- package/dist/src/cli/commands/cache.d.ts.map +1 -0
- package/dist/src/cli/commands/cache.js +126 -0
- package/dist/src/cli/commands/cache.js.map +1 -0
- package/dist/src/cli/commands/context.d.ts +92 -0
- package/dist/src/cli/commands/context.d.ts.map +1 -0
- package/dist/src/cli/commands/context.js +205 -0
- package/dist/src/cli/commands/context.js.map +1 -0
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +112 -70
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/plan/increment-detector.js +2 -2
- package/dist/src/cli/commands/plan/increment-detector.js.map +1 -1
- package/dist/src/cli/commands/sync-spec-commits.js +1 -1
- package/dist/src/cli/commands/sync-spec-commits.js.map +1 -1
- package/dist/src/cli/commands/sync-specs.js +2 -2
- package/dist/src/cli/commands/sync-specs.js.map +1 -1
- package/dist/src/cli/helpers/github/increment-profile-selector.js +1 -1
- package/dist/src/cli/helpers/github/increment-profile-selector.js.map +1 -1
- package/dist/src/cli/helpers/init/external-import.d.ts +3 -0
- package/dist/src/cli/helpers/init/external-import.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/external-import.js +17 -4
- package/dist/src/cli/helpers/init/external-import.js.map +1 -1
- package/dist/src/cli/helpers/init/index.d.ts +1 -0
- package/dist/src/cli/helpers/init/index.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/index.js +2 -0
- package/dist/src/cli/helpers/init/index.js.map +1 -1
- package/dist/src/cli/helpers/init/jira-ado-auto-detect.d.ts +70 -0
- package/dist/src/cli/helpers/init/jira-ado-auto-detect.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/jira-ado-auto-detect.js +214 -4
- package/dist/src/cli/helpers/init/jira-ado-auto-detect.js.map +1 -1
- package/dist/src/cli/helpers/init/living-docs-preflight.d.ts +4 -0
- package/dist/src/cli/helpers/init/living-docs-preflight.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/living-docs-preflight.js +34 -3
- package/dist/src/cli/helpers/init/living-docs-preflight.js.map +1 -1
- package/dist/src/cli/helpers/init/testing-config.d.ts +3 -0
- package/dist/src/cli/helpers/init/testing-config.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/testing-config.js +9 -2
- package/dist/src/cli/helpers/init/testing-config.js.map +1 -1
- package/dist/src/cli/helpers/init/translation-config.d.ts +3 -0
- package/dist/src/cli/helpers/init/translation-config.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/translation-config.js +21 -4
- package/dist/src/cli/helpers/init/translation-config.js.map +1 -1
- package/dist/src/cli/helpers/init/wizard-navigation.d.ts +45 -0
- package/dist/src/cli/helpers/init/wizard-navigation.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/wizard-navigation.js +97 -0
- package/dist/src/cli/helpers/init/wizard-navigation.js.map +1 -0
- package/dist/src/cli/workers/living-docs-worker.js +66 -1
- package/dist/src/cli/workers/living-docs-worker.js.map +1 -1
- package/dist/src/config/types.d.ts +203 -1208
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/core/discrepancy/increment-generator.d.ts.map +1 -1
- package/dist/src/core/discrepancy/increment-generator.js +5 -2
- package/dist/src/core/discrepancy/increment-generator.js.map +1 -1
- package/dist/src/core/increment/duplicate-detector.js +2 -2
- package/dist/src/core/increment/duplicate-detector.js.map +1 -1
- package/dist/src/core/increment/increment-archiver.d.ts +49 -4
- package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
- package/dist/src/core/increment/increment-archiver.js +123 -22
- package/dist/src/core/increment/increment-archiver.js.map +1 -1
- package/dist/src/core/increment/increment-status.js +2 -2
- package/dist/src/core/increment/increment-status.js.map +1 -1
- package/dist/src/core/increment/increment-utils.d.ts +150 -0
- package/dist/src/core/increment/increment-utils.d.ts.map +1 -1
- package/dist/src/core/increment/increment-utils.js +216 -4
- package/dist/src/core/increment/increment-utils.js.map +1 -1
- package/dist/src/core/increment/metadata-validator.js +1 -1
- package/dist/src/core/increment/metadata-validator.js.map +1 -1
- package/dist/src/core/living-docs/feature-archiver.d.ts +4 -0
- package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -1
- package/dist/src/core/living-docs/feature-archiver.js +32 -10
- package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
- package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -1
- package/dist/src/core/living-docs/feature-id-manager.js +8 -4
- package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
- package/dist/src/core/living-docs/governance/ecosystem-detector.d.ts +38 -0
- package/dist/src/core/living-docs/governance/ecosystem-detector.d.ts.map +1 -0
- package/dist/src/core/living-docs/governance/ecosystem-detector.js +325 -0
- package/dist/src/core/living-docs/governance/ecosystem-detector.js.map +1 -0
- package/dist/src/core/living-docs/governance/frontend-standards-parser.d.ts +74 -0
- package/dist/src/core/living-docs/governance/frontend-standards-parser.d.ts.map +1 -0
- package/dist/src/core/living-docs/governance/frontend-standards-parser.js +366 -0
- package/dist/src/core/living-docs/governance/frontend-standards-parser.js.map +1 -0
- package/dist/src/core/living-docs/governance/go-standards-parser.d.ts +64 -0
- package/dist/src/core/living-docs/governance/go-standards-parser.d.ts.map +1 -0
- package/dist/src/core/living-docs/governance/go-standards-parser.js +229 -0
- package/dist/src/core/living-docs/governance/go-standards-parser.js.map +1 -0
- package/dist/src/core/living-docs/governance/index.d.ts +50 -0
- package/dist/src/core/living-docs/governance/index.d.ts.map +1 -0
- package/dist/src/core/living-docs/governance/index.js +56 -0
- package/dist/src/core/living-docs/governance/index.js.map +1 -0
- package/dist/src/core/living-docs/governance/java-standards-parser.d.ts +89 -0
- package/dist/src/core/living-docs/governance/java-standards-parser.d.ts.map +1 -0
- package/dist/src/core/living-docs/governance/java-standards-parser.js +356 -0
- package/dist/src/core/living-docs/governance/java-standards-parser.js.map +1 -0
- package/dist/src/core/living-docs/governance/python-standards-parser.d.ts +83 -0
- package/dist/src/core/living-docs/governance/python-standards-parser.d.ts.map +1 -0
- package/dist/src/core/living-docs/governance/python-standards-parser.js +347 -0
- package/dist/src/core/living-docs/governance/python-standards-parser.js.map +1 -0
- package/dist/src/core/living-docs/governance/standards-generator.d.ts +38 -0
- package/dist/src/core/living-docs/governance/standards-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/governance/standards-generator.js +476 -0
- package/dist/src/core/living-docs/governance/standards-generator.js.map +1 -0
- package/dist/src/core/living-docs/hierarchy-mapper.js +3 -3
- package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.d.ts +18 -0
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js +299 -0
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.d.ts +15 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js +138 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.d.ts +24 -0
- package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.js +198 -0
- package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.d.ts +17 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.js +241 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.d.ts +28 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.js +197 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts +22 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js +482 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.d.ts +42 -0
- package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.js +343 -0
- package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts +190 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.js +7 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.js.map +1 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts +11 -3
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +53 -10
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/living-docs/module-analyzer.d.ts +22 -0
- package/dist/src/core/living-docs/module-analyzer.d.ts.map +1 -1
- package/dist/src/core/living-docs/module-analyzer.js +123 -19
- package/dist/src/core/living-docs/module-analyzer.js.map +1 -1
- package/dist/src/core/llm/provider-factory.js +2 -2
- package/dist/src/core/llm/provider-factory.js.map +1 -1
- package/dist/src/core/llm/providers/anthropic-provider.js +1 -1
- package/dist/src/core/llm/providers/bedrock-provider.d.ts.map +1 -1
- package/dist/src/core/llm/providers/bedrock-provider.js +8 -4
- package/dist/src/core/llm/providers/bedrock-provider.js.map +1 -1
- package/dist/src/core/sync/spec-increment-mapper.js +3 -3
- package/dist/src/core/sync/spec-increment-mapper.js.map +1 -1
- package/dist/src/importers/item-converter.d.ts +25 -0
- package/dist/src/importers/item-converter.d.ts.map +1 -1
- package/dist/src/importers/item-converter.js +135 -5
- package/dist/src/importers/item-converter.js.map +1 -1
- package/dist/src/importers/jira-importer.d.ts +14 -0
- package/dist/src/importers/jira-importer.d.ts.map +1 -1
- package/dist/src/importers/jira-importer.js +75 -0
- package/dist/src/importers/jira-importer.js.map +1 -1
- package/dist/src/init/architecture/types.d.ts +33 -140
- package/dist/src/init/architecture/types.d.ts.map +1 -1
- package/dist/src/init/compliance/types.d.ts +30 -27
- package/dist/src/init/compliance/types.d.ts.map +1 -1
- package/dist/src/init/repo/types.d.ts +11 -34
- package/dist/src/init/repo/types.d.ts.map +1 -1
- package/dist/src/init/research/src/config/types.d.ts +15 -82
- package/dist/src/init/research/src/config/types.d.ts.map +1 -1
- package/dist/src/init/research/types.d.ts +38 -93
- package/dist/src/init/research/types.d.ts.map +1 -1
- package/dist/src/init/team/types.d.ts +4 -42
- package/dist/src/init/team/types.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-token-provider.d.ts +93 -0
- package/dist/src/integrations/jira/jira-token-provider.d.ts.map +1 -0
- package/dist/src/integrations/jira/jira-token-provider.js +160 -0
- package/dist/src/integrations/jira/jira-token-provider.js.map +1 -0
- package/dist/src/sync/ado-reconciler.d.ts +92 -0
- package/dist/src/sync/ado-reconciler.d.ts.map +1 -0
- package/dist/src/sync/ado-reconciler.js +335 -0
- package/dist/src/sync/ado-reconciler.js.map +1 -0
- package/dist/src/sync/jira-reconciler.d.ts +106 -0
- package/dist/src/sync/jira-reconciler.d.ts.map +1 -0
- package/dist/src/sync/jira-reconciler.js +405 -0
- package/dist/src/sync/jira-reconciler.js.map +1 -0
- package/dist/src/types/dashboard-cache.d.ts +181 -0
- package/dist/src/types/dashboard-cache.d.ts.map +1 -0
- package/dist/src/types/dashboard-cache.js +65 -0
- package/dist/src/types/dashboard-cache.js.map +1 -0
- package/dist/src/types/model-selection.d.ts +6 -4
- package/dist/src/types/model-selection.d.ts.map +1 -1
- package/dist/src/types/model-selection.js +3 -1
- package/dist/src/types/model-selection.js.map +1 -1
- package/dist/src/utils/docs-validator.d.ts +131 -0
- package/dist/src/utils/docs-validator.d.ts.map +1 -0
- package/dist/src/utils/docs-validator.js +529 -0
- package/dist/src/utils/docs-validator.js.map +1 -0
- package/dist/src/utils/external-tool-drift-detector.d.ts +1 -1
- package/dist/src/utils/external-tool-drift-detector.d.ts.map +1 -1
- package/dist/src/utils/external-tool-drift-detector.js +5 -4
- package/dist/src/utils/external-tool-drift-detector.js.map +1 -1
- package/dist/src/utils/feature-id-collision.js +1 -1
- package/dist/src/utils/feature-id-collision.js.map +1 -1
- package/dist/src/utils/feature-id-derivation.d.ts +8 -3
- package/dist/src/utils/feature-id-derivation.d.ts.map +1 -1
- package/dist/src/utils/feature-id-derivation.js +14 -6
- package/dist/src/utils/feature-id-derivation.js.map +1 -1
- package/dist/src/utils/html-to-mdx.d.ts +1 -0
- package/dist/src/utils/html-to-mdx.d.ts.map +1 -1
- package/dist/src/utils/html-to-mdx.js +43 -5
- package/dist/src/utils/html-to-mdx.js.map +1 -1
- package/dist/src/utils/model-selection.d.ts +3 -4
- package/dist/src/utils/model-selection.d.ts.map +1 -1
- package/dist/src/utils/model-selection.js +3 -4
- package/dist/src/utils/model-selection.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/agents/code-standards-detective/AGENT.md +48 -0
- package/plugins/specweave/agents/pm/AGENT.md +10 -7
- package/plugins/specweave/commands/specweave-archive-features.md +5 -7
- package/plugins/specweave/commands/specweave-archive.md +2 -1
- package/plugins/specweave/commands/specweave-costs.md +4 -4
- package/plugins/specweave/commands/specweave-do.md +44 -10
- package/plugins/specweave/commands/specweave-done.md +109 -0
- package/plugins/specweave/commands/specweave-import-external.md +45 -18
- package/plugins/specweave/commands/specweave-increment.md +331 -33
- package/plugins/specweave/commands/specweave-jobs.md +2 -2
- package/plugins/specweave/commands/specweave-progress.md +4 -4
- package/plugins/specweave/commands/specweave-restore-feature.md +5 -4
- package/plugins/specweave/commands/specweave-sync-docs.md +1 -1
- package/plugins/specweave/commands/specweave-sync-specs.md +216 -322
- package/plugins/specweave/commands/specweave-validate-features.md +13 -8
- package/plugins/specweave/commands/specweave-validate.md +27 -1
- package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
- package/plugins/specweave/hooks/hooks.json +43 -4
- package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
- package/plugins/specweave/hooks/lib/common-setup.sh +375 -0
- package/plugins/specweave/hooks/lib/crash-prevention.sh +336 -0
- package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
- package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
- package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
- package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
- package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
- package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
- package/plugins/specweave/hooks/post-task-completion.sh +4 -23
- package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
- package/plugins/specweave/hooks/pre-command-deduplication.sh +1 -6
- package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
- package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
- package/plugins/specweave/hooks/pre-task-completion.sh +8 -37
- package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
- package/plugins/specweave/hooks/pre-tool-use.sh +2 -11
- package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
- package/plugins/specweave/hooks/spec-project-validator.sh +80 -25
- package/plugins/specweave/hooks/universal/dispatcher.mjs +135 -42
- package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +183 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh +140 -38
- package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +12 -0
- package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +89 -0
- package/plugins/specweave/hooks/v2/guards/bash-file-guard.sh +211 -0
- package/plugins/specweave/hooks/v2/guards/bash-file-guard.test.sh +163 -0
- package/plugins/specweave/hooks/v2/guards/completion-guard.sh +26 -28
- package/plugins/specweave/hooks/v2/guards/features-folder-guard.sh +50 -0
- package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +135 -0
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +2 -2
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -1
- package/plugins/specweave/scripts/README.md +166 -0
- package/plugins/specweave/scripts/cleanup-state.sh +142 -0
- package/plugins/specweave/scripts/force-kill.sh +142 -0
- package/plugins/specweave/scripts/jobs.js +171 -0
- package/plugins/specweave/scripts/progress.js +170 -0
- package/plugins/specweave/scripts/read-costs.sh +132 -0
- package/plugins/specweave/scripts/read-jobs.sh +324 -0
- package/plugins/specweave/scripts/read-progress.sh +185 -0
- package/plugins/specweave/scripts/read-status.sh +146 -0
- package/plugins/specweave/scripts/read-workflow.sh +173 -0
- package/plugins/specweave/scripts/rebuild-dashboard-cache.sh +327 -0
- package/plugins/specweave/scripts/session-watchdog.sh +192 -0
- package/plugins/specweave/scripts/status.js +154 -0
- package/plugins/specweave/scripts/update-dashboard-cache.sh +281 -0
- package/plugins/specweave/skills/code-standards-analyzer/SKILL.md +58 -6
- package/plugins/specweave/skills/increment-planner/SKILL.md +388 -48
- package/plugins/specweave/skills/increment-planner/templates/spec-multi-project.md +17 -7
- package/plugins/specweave/skills/increment-planner/templates/spec-single-project.md +6 -1
- package/plugins/specweave/skills/increment-planner/templates/tasks-multi-project.md +1 -1
- package/plugins/specweave/skills/increment-planner/templates/tasks-single-project.md +1 -1
- package/plugins/specweave/skills/instant-status/SKILL.md +70 -0
- package/plugins/specweave-ado/commands/cleanup-duplicates.md +212 -0
- package/plugins/specweave-ado/commands/reconcile.md +120 -0
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
- package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-ado/lib/ado-duplicate-detector.js +279 -0
- package/plugins/specweave-ado/lib/ado-duplicate-detector.ts +407 -0
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
- package/plugins/specweave-docs/commands/build.md +32 -4
- package/plugins/specweave-docs/commands/preview.md +43 -1
- package/plugins/specweave-docs/commands/validate.md +250 -0
- package/plugins/specweave-github/agents/github-manager/AGENT.md +2 -2
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +1262 -0
- package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
- package/plugins/specweave-github/lib/enhanced-github-sync.js +220 -0
- package/plugins/specweave-infrastructure/skills/hetzner-provisioner/README.md +1 -1
- package/plugins/specweave-jira/agents/jira-manager/AGENT.md +1 -1
- package/plugins/specweave-jira/agents/jira-multi-project-mapper/AGENT.md +530 -0
- package/plugins/specweave-jira/agents/jira-sync-judge/AGENT.md +438 -0
- package/plugins/specweave-jira/commands/cleanup-duplicates.md +219 -0
- package/plugins/specweave-jira/commands/close.md +297 -0
- package/plugins/specweave-jira/commands/create.md +198 -0
- package/plugins/specweave-jira/commands/reconcile.md +123 -0
- package/plugins/specweave-jira/commands/status.md +215 -0
- package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +134 -0
- package/plugins/specweave-jira/lib/jira-duplicate-detector.js +296 -0
- package/plugins/specweave-jira/lib/jira-duplicate-detector.ts +434 -0
- package/plugins/specweave-jira/lib/jira-permission-gate.js +160 -0
- package/plugins/specweave-jira/lib/jira-permission-gate.ts +276 -0
- package/plugins/specweave-jira/lib/jira-profile-resolver.js +222 -0
- package/plugins/specweave-jira/lib/jira-profile-resolver.ts +427 -0
- package/plugins/specweave-jira/reference/jira-specweave-mapping.md +16 -11
- package/plugins/specweave-release/commands/specweave-release-npm.md +140 -14
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1254 -0
- package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
- package/plugins/specweave/hooks/post-edit-spec.sh +0 -265
- package/plugins/specweave/hooks/post-write-spec.sh +0 -267
- package/plugins/specweave/hooks/pre-edit-spec.sh +0 -151
- package/plugins/specweave/hooks/pre-write-spec.sh +0 -151
|
@@ -167,11 +167,7 @@ fi
|
|
|
167
167
|
if [ "$COMPLETING_TASK" = "false" ]; then
|
|
168
168
|
echo "[$(date)] ⏭️ No tasks being completed, skipping validation" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
169
169
|
rm -f "$STDIN_DATA"
|
|
170
|
-
|
|
171
|
-
{
|
|
172
|
-
"continue": true
|
|
173
|
-
}
|
|
174
|
-
EOF
|
|
170
|
+
echo '{"continue":true}'
|
|
175
171
|
exit 0
|
|
176
172
|
fi
|
|
177
173
|
|
|
@@ -184,11 +180,7 @@ CURRENT_INCREMENT=$(ls -td .specweave/increments/*/ 2>/dev/null | xargs -n1 base
|
|
|
184
180
|
if [ -z "$CURRENT_INCREMENT" ]; then
|
|
185
181
|
echo "[$(date)] ℹ️ No active increment found, skipping validation" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
186
182
|
rm -f "$STDIN_DATA"
|
|
187
|
-
|
|
188
|
-
{
|
|
189
|
-
"continue": true
|
|
190
|
-
}
|
|
191
|
-
EOF
|
|
183
|
+
echo '{"continue":true}'
|
|
192
184
|
exit 0
|
|
193
185
|
fi
|
|
194
186
|
|
|
@@ -197,11 +189,7 @@ TASKS_MD=".specweave/increments/$CURRENT_INCREMENT/tasks.md"
|
|
|
197
189
|
if [ ! -f "$TASKS_MD" ]; then
|
|
198
190
|
echo "[$(date)] ℹ️ tasks.md not found for $CURRENT_INCREMENT (increment may be in planning stage)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
199
191
|
rm -f "$STDIN_DATA"
|
|
200
|
-
|
|
201
|
-
{
|
|
202
|
-
"continue": true
|
|
203
|
-
}
|
|
204
|
-
EOF
|
|
192
|
+
echo '{"continue":true}'
|
|
205
193
|
exit 0
|
|
206
194
|
fi
|
|
207
195
|
|
|
@@ -231,12 +219,7 @@ fi
|
|
|
231
219
|
if [ -z "$VALIDATOR_SCRIPT" ] || ! command -v node &> /dev/null; then
|
|
232
220
|
echo "[$(date)] ⚠️ AC test validator not found or Node.js missing" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
233
221
|
rm -f "$STDIN_DATA"
|
|
234
|
-
|
|
235
|
-
{
|
|
236
|
-
"continue": true,
|
|
237
|
-
"systemMessage": "⚠️ Warning: AC test validator not available. Task completion validation skipped. Install Node.js and rebuild SpecWeave to enable validation."
|
|
238
|
-
}
|
|
239
|
-
EOF
|
|
222
|
+
echo '{"continue":true,"systemMessage":"⚠️ Warning: AC test validator not available. Task completion validation skipped. Install Node.js and rebuild SpecWeave to enable validation."}'
|
|
240
223
|
exit 0
|
|
241
224
|
fi
|
|
242
225
|
|
|
@@ -262,16 +245,11 @@ if [ "$VALIDATION_EXIT_CODE" = "0" ]; then
|
|
|
262
245
|
# Reset circuit breaker on success
|
|
263
246
|
echo "0" > "$CIRCUIT_BREAKER_FILE" 2>/dev/null || true
|
|
264
247
|
|
|
265
|
-
VALIDATION_SUMMARY=$(cat "$VALIDATION_OUTPUT" | tail -5 | tr '\n' ' ')
|
|
248
|
+
VALIDATION_SUMMARY=$(cat "$VALIDATION_OUTPUT" | tail -5 | tr '\n' ' ' | sed 's/"/\\"/g')
|
|
266
249
|
|
|
267
250
|
rm -f "$VALIDATION_OUTPUT"
|
|
268
251
|
|
|
269
|
-
|
|
270
|
-
{
|
|
271
|
-
"continue": true,
|
|
272
|
-
"systemMessage": "✅ AC Test Validation Passed: All acceptance criteria have passing tests. Task completion allowed. ${VALIDATION_SUMMARY}"
|
|
273
|
-
}
|
|
274
|
-
EOF
|
|
252
|
+
printf '{"continue":true,"systemMessage":"✅ AC Test Validation Passed: All acceptance criteria have passing tests. Task completion allowed. %s"}\n' "$VALIDATION_SUMMARY"
|
|
275
253
|
else
|
|
276
254
|
# Validation failed - block completion
|
|
277
255
|
echo "[$(date)] ❌ AC test validation failed" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
@@ -280,18 +258,11 @@ else
|
|
|
280
258
|
CURRENT_FAILURES=$(cat "$CIRCUIT_BREAKER_FILE" 2>/dev/null || echo 0)
|
|
281
259
|
echo "$((CURRENT_FAILURES + 1))" > "$CIRCUIT_BREAKER_FILE" 2>/dev/null || true
|
|
282
260
|
|
|
283
|
-
VALIDATION_ERROR=$(cat "$VALIDATION_OUTPUT" | grep -A 10 "VALIDATION FAILED" | tr '\n' ' ' | cut -c 1-300)
|
|
261
|
+
VALIDATION_ERROR=$(cat "$VALIDATION_OUTPUT" | grep -A 10 "VALIDATION FAILED" | tr '\n' ' ' | cut -c 1-300 | sed 's/"/\\"/g')
|
|
284
262
|
|
|
285
263
|
rm -f "$VALIDATION_OUTPUT"
|
|
286
264
|
|
|
287
|
-
|
|
288
|
-
{
|
|
289
|
-
"continue": false,
|
|
290
|
-
"systemMessage": "❌ AC TEST VALIDATION FAILED: Cannot mark task as complete until all acceptance criteria have passing tests. ${VALIDATION_ERROR}
|
|
291
|
-
|
|
292
|
-
Fix the failing tests and try again. Run tests manually: npm test"
|
|
293
|
-
}
|
|
294
|
-
EOF
|
|
265
|
+
printf '{"continue":false,"systemMessage":"❌ AC TEST VALIDATION FAILED: Cannot mark task as complete until all acceptance criteria have passing tests. %s\\n\\nFix the failing tests and try again. Run tests manually: npm test"}\n' "$VALIDATION_ERROR"
|
|
295
266
|
fi
|
|
296
267
|
|
|
297
268
|
# ALWAYS exit 0 - NEVER let hook errors crash Claude Code
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# SpecWeave Pre-Task-Completion Hook
|
|
4
|
+
# CRITICAL QUALITY GATE: Validates AC tests before allowing task completion
|
|
5
|
+
#
|
|
6
|
+
# Runs automatically BEFORE any task is marked complete via TodoWrite
|
|
7
|
+
#
|
|
8
|
+
# WORKFLOW:
|
|
9
|
+
# =========
|
|
10
|
+
# 1. TodoWrite called with status="completed"
|
|
11
|
+
# 2. This hook fires (pre-completion validation)
|
|
12
|
+
# 3. Extract task ID from TodoWrite input
|
|
13
|
+
# 4. Find task in tasks.md
|
|
14
|
+
# 5. Run AC test validator
|
|
15
|
+
# 6. If tests PASS → Allow completion (continue: true)
|
|
16
|
+
# 7. If tests FAIL → Block completion (continue: false, show error)
|
|
17
|
+
#
|
|
18
|
+
# ENFORCEMENT:
|
|
19
|
+
# ============
|
|
20
|
+
# This is the ONLY way to mark tasks complete in SpecWeave.
|
|
21
|
+
# Manual edits to tasks.md are detected and flagged by pre-commit hooks.
|
|
22
|
+
|
|
23
|
+
set -e
|
|
24
|
+
|
|
25
|
+
# Find project root
|
|
26
|
+
find_project_root() {
|
|
27
|
+
local dir="$1"
|
|
28
|
+
while [ "$dir" != "/" ]; do
|
|
29
|
+
if [ -d "$dir/.specweave" ]; then
|
|
30
|
+
echo "$dir"
|
|
31
|
+
return 0
|
|
32
|
+
fi
|
|
33
|
+
dir="$(dirname "$dir")"
|
|
34
|
+
done
|
|
35
|
+
pwd
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
|
|
39
|
+
cd "$PROJECT_ROOT" 2>/dev/null || true
|
|
40
|
+
|
|
41
|
+
# ============================================================================
|
|
42
|
+
# CONFIGURATION
|
|
43
|
+
# ============================================================================
|
|
44
|
+
|
|
45
|
+
LOGS_DIR=".specweave/logs"
|
|
46
|
+
DEBUG_LOG="$LOGS_DIR/hooks-debug.log"
|
|
47
|
+
|
|
48
|
+
mkdir -p "$LOGS_DIR" 2>/dev/null || true
|
|
49
|
+
|
|
50
|
+
echo "[$(date)] 🔒 Pre-task-completion hook fired" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
51
|
+
|
|
52
|
+
# ============================================================================
|
|
53
|
+
# CAPTURE INPUT
|
|
54
|
+
# ============================================================================
|
|
55
|
+
|
|
56
|
+
STDIN_DATA=$(mktemp)
|
|
57
|
+
cat > "$STDIN_DATA"
|
|
58
|
+
|
|
59
|
+
echo "[$(date)] Input JSON:" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
60
|
+
cat "$STDIN_DATA" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
61
|
+
|
|
62
|
+
# ============================================================================
|
|
63
|
+
# CHECK FOR TASK COMPLETION
|
|
64
|
+
# ============================================================================
|
|
65
|
+
|
|
66
|
+
# Only validate if a task is being marked complete
|
|
67
|
+
COMPLETING_TASK=false
|
|
68
|
+
|
|
69
|
+
if command -v jq >/dev/null 2>&1; then
|
|
70
|
+
# Check if any task is transitioning to "completed" status
|
|
71
|
+
COMPLETED_COUNT=$(jq -r '.tool_input.todos // [] | map(select(.status == "completed")) | length' "$STDIN_DATA" 2>/dev/null || echo "0")
|
|
72
|
+
|
|
73
|
+
if [ "$COMPLETED_COUNT" != "0" ]; then
|
|
74
|
+
COMPLETING_TASK=true
|
|
75
|
+
echo "[$(date)] ✓ Detected task completion (${COMPLETED_COUNT} tasks)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
76
|
+
fi
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# If no tasks being completed, allow without validation
|
|
80
|
+
if [ "$COMPLETING_TASK" = "false" ]; then
|
|
81
|
+
echo "[$(date)] ⏭️ No tasks being completed, skipping validation" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
82
|
+
rm -f "$STDIN_DATA"
|
|
83
|
+
cat <<EOF
|
|
84
|
+
{
|
|
85
|
+
"continue": true
|
|
86
|
+
}
|
|
87
|
+
EOF
|
|
88
|
+
exit 0
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# ============================================================================
|
|
92
|
+
# DETECT CURRENT INCREMENT
|
|
93
|
+
# ============================================================================
|
|
94
|
+
|
|
95
|
+
CURRENT_INCREMENT=$(ls -td .specweave/increments/*/ 2>/dev/null | xargs -n1 basename | grep -v "_backlog" | grep -v "_archive" | grep -v "_working" | head -1)
|
|
96
|
+
|
|
97
|
+
if [ -z "$CURRENT_INCREMENT" ]; then
|
|
98
|
+
echo "[$(date)] ℹ️ No active increment found, skipping validation" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
99
|
+
rm -f "$STDIN_DATA"
|
|
100
|
+
cat <<EOF
|
|
101
|
+
{
|
|
102
|
+
"continue": true
|
|
103
|
+
}
|
|
104
|
+
EOF
|
|
105
|
+
exit 0
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
TASKS_MD=".specweave/increments/$CURRENT_INCREMENT/tasks.md"
|
|
109
|
+
|
|
110
|
+
if [ ! -f "$TASKS_MD" ]; then
|
|
111
|
+
echo "[$(date)] ℹ️ tasks.md not found for $CURRENT_INCREMENT (increment may be in planning stage)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
112
|
+
rm -f "$STDIN_DATA"
|
|
113
|
+
cat <<EOF
|
|
114
|
+
{
|
|
115
|
+
"continue": true
|
|
116
|
+
}
|
|
117
|
+
EOF
|
|
118
|
+
exit 0
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
# ============================================================================
|
|
122
|
+
# RUN AC TEST VALIDATION
|
|
123
|
+
# ============================================================================
|
|
124
|
+
|
|
125
|
+
echo "[$(date)] 🧪 Running AC test validation for $CURRENT_INCREMENT" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
126
|
+
|
|
127
|
+
# Determine which validation script to use
|
|
128
|
+
VALIDATOR_SCRIPT=""
|
|
129
|
+
if [ -f "$PROJECT_ROOT/dist/src/core/ac-test-validator-cli.js" ]; then
|
|
130
|
+
VALIDATOR_SCRIPT="$PROJECT_ROOT/dist/src/core/ac-test-validator-cli.js"
|
|
131
|
+
elif [ -f "$PROJECT_ROOT/node_modules/specweave/dist/src/core/ac-test-validator-cli.js" ]; then
|
|
132
|
+
VALIDATOR_SCRIPT="$PROJECT_ROOT/node_modules/specweave/dist/src/core/ac-test-validator-cli.js"
|
|
133
|
+
elif [ -n "${CLAUDE_PLUGIN_ROOT}" ] && [ -f "${CLAUDE_PLUGIN_ROOT}/dist/src/core/ac-test-validator-cli.js" ]; then
|
|
134
|
+
VALIDATOR_SCRIPT="${CLAUDE_PLUGIN_ROOT}/dist/src/core/ac-test-validator-cli.js"
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
if [ -z "$VALIDATOR_SCRIPT" ] || ! command -v node &> /dev/null; then
|
|
138
|
+
echo "[$(date)] ⚠️ AC test validator not found or Node.js missing" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
139
|
+
rm -f "$STDIN_DATA"
|
|
140
|
+
cat <<EOF
|
|
141
|
+
{
|
|
142
|
+
"continue": true,
|
|
143
|
+
"systemMessage": "⚠️ Warning: AC test validator not available. Task completion validation skipped. Install Node.js and rebuild SpecWeave to enable validation."
|
|
144
|
+
}
|
|
145
|
+
EOF
|
|
146
|
+
exit 0
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
# Run validator (captures exit code)
|
|
150
|
+
VALIDATION_OUTPUT=$(mktemp)
|
|
151
|
+
VALIDATION_EXIT_CODE=0
|
|
152
|
+
|
|
153
|
+
(cd "$PROJECT_ROOT" && node "$VALIDATOR_SCRIPT" "$CURRENT_INCREMENT") > "$VALIDATION_OUTPUT" 2>&1 || VALIDATION_EXIT_CODE=$?
|
|
154
|
+
|
|
155
|
+
echo "[$(date)] Validator exit code: $VALIDATION_EXIT_CODE" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
156
|
+
cat "$VALIDATION_OUTPUT" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
157
|
+
|
|
158
|
+
rm -f "$STDIN_DATA"
|
|
159
|
+
|
|
160
|
+
# ============================================================================
|
|
161
|
+
# DECISION LOGIC
|
|
162
|
+
# ============================================================================
|
|
163
|
+
|
|
164
|
+
if [ "$VALIDATION_EXIT_CODE" = "0" ]; then
|
|
165
|
+
# Validation passed - allow completion
|
|
166
|
+
echo "[$(date)] ✅ AC test validation passed" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
167
|
+
|
|
168
|
+
VALIDATION_SUMMARY=$(cat "$VALIDATION_OUTPUT" | tail -5 | tr '\n' ' ')
|
|
169
|
+
|
|
170
|
+
rm -f "$VALIDATION_OUTPUT"
|
|
171
|
+
|
|
172
|
+
cat <<EOF
|
|
173
|
+
{
|
|
174
|
+
"continue": true,
|
|
175
|
+
"systemMessage": "✅ AC Test Validation Passed: All acceptance criteria have passing tests. Task completion allowed. ${VALIDATION_SUMMARY}"
|
|
176
|
+
}
|
|
177
|
+
EOF
|
|
178
|
+
else
|
|
179
|
+
# Validation failed - block completion
|
|
180
|
+
echo "[$(date)] ❌ AC test validation failed" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
181
|
+
|
|
182
|
+
VALIDATION_ERROR=$(cat "$VALIDATION_OUTPUT" | grep -A 10 "VALIDATION FAILED" | tr '\n' ' ' | cut -c 1-300)
|
|
183
|
+
|
|
184
|
+
rm -f "$VALIDATION_OUTPUT"
|
|
185
|
+
|
|
186
|
+
cat <<EOF
|
|
187
|
+
{
|
|
188
|
+
"continue": false,
|
|
189
|
+
"systemMessage": "❌ AC TEST VALIDATION FAILED: Cannot mark task as complete until all acceptance criteria have passing tests. ${VALIDATION_ERROR}
|
|
190
|
+
|
|
191
|
+
Fix the failing tests and try again. Run tests manually: npm test"
|
|
192
|
+
}
|
|
193
|
+
EOF
|
|
194
|
+
fi
|
|
@@ -128,18 +128,9 @@ rm -f "$STDIN_DATA"
|
|
|
128
128
|
# ============================================================================
|
|
129
129
|
|
|
130
130
|
if [ "$TOOL_NAME" = "AskUserQuestion" ]; then
|
|
131
|
-
|
|
132
|
-
{
|
|
133
|
-
"continue": true,
|
|
134
|
-
"systemMessage": "🔔 Sound played - user notified of question request"
|
|
135
|
-
}
|
|
136
|
-
EOF
|
|
131
|
+
echo '{"continue":true,"systemMessage":"🔔 Sound played - user notified of question request"}'
|
|
137
132
|
else
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
"continue": true
|
|
141
|
-
}
|
|
142
|
-
EOF
|
|
133
|
+
echo '{"continue":true}'
|
|
143
134
|
fi
|
|
144
135
|
|
|
145
136
|
# ALWAYS exit 0 - NEVER let hook errors crash Claude Code
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# SpecWeave Pre-Tool-Use Hook
|
|
4
|
+
# Runs BEFORE Claude calls any tool (PreToolUse event)
|
|
5
|
+
#
|
|
6
|
+
# PURPOSE: Detect when Claude asks questions via AskUserQuestion
|
|
7
|
+
# - Plays sound IMMEDIATELY when question is about to be asked
|
|
8
|
+
# - Complements post-task-completion hook (which only fires after TodoWrite)
|
|
9
|
+
# - Ensures user is always notified when Claude needs input
|
|
10
|
+
#
|
|
11
|
+
# SCOPE:
|
|
12
|
+
# - This hook fires for ALL tool calls (Read, Edit, Write, AskUserQuestion, etc.)
|
|
13
|
+
# - We filter for AskUserQuestion specifically to play sound
|
|
14
|
+
# - Non-blocking and fast (<10ms overhead)
|
|
15
|
+
|
|
16
|
+
set -e
|
|
17
|
+
|
|
18
|
+
# ============================================================================
|
|
19
|
+
# CONFIGURATION
|
|
20
|
+
# ============================================================================
|
|
21
|
+
|
|
22
|
+
# Find project root
|
|
23
|
+
find_project_root() {
|
|
24
|
+
local dir="$1"
|
|
25
|
+
while [ "$dir" != "/" ]; do
|
|
26
|
+
if [ -d "$dir/.specweave" ]; then
|
|
27
|
+
echo "$dir"
|
|
28
|
+
return 0
|
|
29
|
+
fi
|
|
30
|
+
dir="$(dirname "$dir")"
|
|
31
|
+
done
|
|
32
|
+
# Fallback
|
|
33
|
+
if [ -d "$(pwd)/.specweave" ]; then
|
|
34
|
+
pwd
|
|
35
|
+
else
|
|
36
|
+
echo "$(pwd)"
|
|
37
|
+
fi
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
|
|
41
|
+
cd "$PROJECT_ROOT" 2>/dev/null || true
|
|
42
|
+
|
|
43
|
+
LOGS_DIR=".specweave/logs"
|
|
44
|
+
DEBUG_LOG="$LOGS_DIR/hooks-debug.log"
|
|
45
|
+
|
|
46
|
+
mkdir -p "$LOGS_DIR" 2>/dev/null || true
|
|
47
|
+
|
|
48
|
+
# ============================================================================
|
|
49
|
+
# CAPTURE INPUT (Tool Call Details)
|
|
50
|
+
# ============================================================================
|
|
51
|
+
|
|
52
|
+
STDIN_DATA=$(mktemp)
|
|
53
|
+
cat > "$STDIN_DATA"
|
|
54
|
+
|
|
55
|
+
# Log the tool call for debugging
|
|
56
|
+
echo "[$(date)] 🔧 PreToolUse hook fired" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
57
|
+
echo "[$(date)] Tool call JSON:" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
58
|
+
cat "$STDIN_DATA" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
59
|
+
echo "" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
60
|
+
|
|
61
|
+
# ============================================================================
|
|
62
|
+
# DETECT AskUserQuestion TOOL
|
|
63
|
+
# ============================================================================
|
|
64
|
+
|
|
65
|
+
TOOL_NAME=""
|
|
66
|
+
|
|
67
|
+
if command -v jq >/dev/null 2>&1; then
|
|
68
|
+
# Use jq if available (most reliable)
|
|
69
|
+
TOOL_NAME=$(jq -r '.tool_name // empty' "$STDIN_DATA" 2>/dev/null)
|
|
70
|
+
else
|
|
71
|
+
# Fallback: grep-based detection
|
|
72
|
+
if grep -q '"tool_name"' "$STDIN_DATA" 2>/dev/null; then
|
|
73
|
+
TOOL_NAME=$(grep -o '"tool_name":"[^"]*"' "$STDIN_DATA" | cut -d'"' -f4)
|
|
74
|
+
fi
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
echo "[$(date)] Tool name: $TOOL_NAME" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
78
|
+
|
|
79
|
+
# ============================================================================
|
|
80
|
+
# PLAY SOUND IF AskUserQuestion
|
|
81
|
+
# ============================================================================
|
|
82
|
+
|
|
83
|
+
play_sound() {
|
|
84
|
+
case "$(uname -s)" in
|
|
85
|
+
Darwin)
|
|
86
|
+
# macOS: Use afplay with a distinctive sound for questions
|
|
87
|
+
afplay /System/Library/Sounds/Tink.aiff 2>/dev/null || true
|
|
88
|
+
;;
|
|
89
|
+
Linux)
|
|
90
|
+
# Linux: Use paplay or aplay
|
|
91
|
+
paplay /usr/share/sounds/freedesktop/stereo/dialog-question.oga 2>/dev/null || \
|
|
92
|
+
paplay /usr/share/sounds/freedesktop/stereo/message-new-instant.oga 2>/dev/null || \
|
|
93
|
+
aplay /usr/share/sounds/alsa/Front_Center.wav 2>/dev/null || true
|
|
94
|
+
;;
|
|
95
|
+
MINGW*|MSYS*|CYGWIN*)
|
|
96
|
+
# Windows: Use PowerShell
|
|
97
|
+
powershell -c "(New-Object Media.SoundPlayer 'C:\Windows\Media\Windows Notify.wav').PlaySync();" 2>/dev/null || true
|
|
98
|
+
;;
|
|
99
|
+
esac
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if [ "$TOOL_NAME" = "AskUserQuestion" ]; then
|
|
103
|
+
echo "[$(date)] 🔔 QUESTION DETECTED! Playing notification sound" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
104
|
+
play_sound
|
|
105
|
+
|
|
106
|
+
# Log this event
|
|
107
|
+
echo "[$(date)] Claude is asking for user input via AskUserQuestion" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# ============================================================================
|
|
111
|
+
# CLEANUP
|
|
112
|
+
# ============================================================================
|
|
113
|
+
|
|
114
|
+
rm -f "$STDIN_DATA"
|
|
115
|
+
|
|
116
|
+
# ============================================================================
|
|
117
|
+
# OUTPUT TO CLAUDE (Always continue)
|
|
118
|
+
# ============================================================================
|
|
119
|
+
|
|
120
|
+
if [ "$TOOL_NAME" = "AskUserQuestion" ]; then
|
|
121
|
+
cat <<EOF
|
|
122
|
+
{
|
|
123
|
+
"continue": true,
|
|
124
|
+
"systemMessage": "🔔 Sound played - user notified of question request"
|
|
125
|
+
}
|
|
126
|
+
EOF
|
|
127
|
+
else
|
|
128
|
+
cat <<EOF
|
|
129
|
+
{
|
|
130
|
+
"continue": true
|
|
131
|
+
}
|
|
132
|
+
EOF
|
|
133
|
+
fi
|
|
@@ -12,11 +12,21 @@
|
|
|
12
12
|
# Rules:
|
|
13
13
|
# - 1-level structure: spec.md MUST have `project:` in YAML frontmatter
|
|
14
14
|
# - 2-level structure: spec.md MUST have BOTH `project:` AND `board:` in frontmatter
|
|
15
|
+
# - Project MUST exist in configuration (validated via specweave context projects)
|
|
16
|
+
# - Board MUST exist under project for 2-level (validated via specweave context boards)
|
|
15
17
|
#
|
|
16
18
|
# Returns exit code 1 (block) if validation fails, 0 (allow) otherwise.
|
|
19
|
+
#
|
|
20
|
+
# Bypass: Set SPECWEAVE_FORCE_PROJECT=1 to skip validation
|
|
17
21
|
|
|
18
22
|
set -e
|
|
19
23
|
|
|
24
|
+
# Check for force bypass
|
|
25
|
+
if [ "$SPECWEAVE_FORCE_PROJECT" = "1" ]; then
|
|
26
|
+
echo '{"decision": "allow", "message": "⚠️ Project validation bypassed (SPECWEAVE_FORCE_PROJECT=1)"}'
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
20
30
|
# Read tool input from stdin
|
|
21
31
|
INPUT=$(cat)
|
|
22
32
|
|
|
@@ -33,7 +43,7 @@ fi
|
|
|
33
43
|
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
|
|
34
44
|
|
|
35
45
|
# Only validate spec.md files in increments folder
|
|
36
|
-
if [[ ! "$FILE_PATH" =~ \.specweave/increments/[0-9]{4}
|
|
46
|
+
if [[ ! "$FILE_PATH" =~ \.specweave/increments/[0-9]{4}E?-[^/]+/spec\.md$ ]]; then
|
|
37
47
|
echo '{"decision": "allow"}'
|
|
38
48
|
exit 0
|
|
39
49
|
fi
|
|
@@ -52,58 +62,103 @@ FRONTMATTER=$(echo "$CONTENT" | sed -n '/^---$/,/^---$/p' | tail -n +2 | head -n
|
|
|
52
62
|
|
|
53
63
|
# Check for unresolved project placeholder
|
|
54
64
|
if echo "$FRONTMATTER" | grep -q 'project:\s*{{PROJECT_ID}}'; then
|
|
55
|
-
echo '{"decision": "block", "reason": "spec.md has unresolved placeholder {{PROJECT_ID}}. Run
|
|
65
|
+
echo '{"decision": "block", "reason": "spec.md has unresolved placeholder {{PROJECT_ID}}. Run '\''specweave context projects'\'' to get available projects, then select one."}'
|
|
56
66
|
exit 0
|
|
57
67
|
fi
|
|
58
68
|
|
|
59
69
|
# Check for unresolved board placeholder
|
|
60
70
|
if echo "$FRONTMATTER" | grep -q 'board:\s*{{BOARD_ID}}'; then
|
|
61
|
-
echo '{"decision": "block", "reason": "spec.md has unresolved placeholder {{BOARD_ID}}. Run
|
|
71
|
+
echo '{"decision": "block", "reason": "spec.md has unresolved placeholder {{BOARD_ID}}. Run '\''specweave context boards --project=<id>'\'' to get available boards, then select one."}'
|
|
62
72
|
exit 0
|
|
63
73
|
fi
|
|
64
74
|
|
|
65
|
-
#
|
|
75
|
+
# Extract project and board from frontmatter
|
|
66
76
|
PROJECT=$(echo "$FRONTMATTER" | grep -E '^project:\s*' | sed 's/^project:\s*//' | tr -d '"'"'" | tr -d '[:space:]')
|
|
77
|
+
BOARD=$(echo "$FRONTMATTER" | grep -E '^board:\s*' | sed 's/^board:\s*//' | tr -d '"'"'" | tr -d '[:space:]')
|
|
67
78
|
|
|
68
|
-
#
|
|
79
|
+
# Get project root from file path
|
|
69
80
|
PROJECT_ROOT="${FILE_PATH%%/.specweave/*}"
|
|
70
|
-
CONFIG_PATH="$PROJECT_ROOT/.specweave/config.json"
|
|
71
81
|
|
|
72
|
-
|
|
82
|
+
# Change to project root for specweave command
|
|
83
|
+
cd "$PROJECT_ROOT" 2>/dev/null || true
|
|
73
84
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if jq -e '.sync.profiles | to_entries[] | select(.value.provider == "ado") | .value.config.areaPathMapping.mappings | length > 0' "$CONFIG_PATH" >/dev/null 2>&1; then
|
|
77
|
-
IS_2_LEVEL=true
|
|
78
|
-
fi
|
|
85
|
+
# Get project context via CLI command
|
|
86
|
+
CONTEXT_OUTPUT=$(specweave context projects 2>/dev/null || echo '{"level": 1, "projects": []}')
|
|
79
87
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
# Parse structure level
|
|
89
|
+
STRUCTURE_LEVEL=$(echo "$CONTEXT_OUTPUT" | jq -r '.level // 1')
|
|
90
|
+
|
|
91
|
+
# Parse available projects
|
|
92
|
+
AVAILABLE_PROJECTS=$(echo "$CONTEXT_OUTPUT" | jq -r '.projects[].id // empty' | tr '\n' ', ' | sed 's/,$//')
|
|
85
93
|
|
|
86
94
|
# Validation based on structure level
|
|
87
|
-
if [ "$
|
|
95
|
+
if [ "$STRUCTURE_LEVEL" = "2" ]; then
|
|
88
96
|
# 2-level: BOTH project AND board required
|
|
97
|
+
|
|
98
|
+
# Check project field exists
|
|
89
99
|
if [ -z "$PROJECT" ] || [ "$PROJECT" = "null" ]; then
|
|
90
|
-
echo
|
|
100
|
+
echo "{\"decision\": \"block\", \"reason\": \"spec.md missing required 'project:' field in YAML frontmatter.\\n\\n2-level structure detected.\\n\\nAvailable projects: ${AVAILABLE_PROJECTS:-none detected}\\n\\nAdd 'project: <project_name>' to frontmatter.\\n\\nRun 'specweave context projects' to see all options.\"}"
|
|
91
101
|
exit 0
|
|
92
102
|
fi
|
|
93
103
|
|
|
94
|
-
|
|
95
|
-
|
|
104
|
+
# Check board field exists
|
|
96
105
|
if [ -z "$BOARD" ] || [ "$BOARD" = "null" ]; then
|
|
97
|
-
|
|
106
|
+
# Get available boards for the project
|
|
107
|
+
AVAILABLE_BOARDS=$(specweave context boards --project="$PROJECT" 2>/dev/null | jq -r '.boards[].id // empty' | tr '\n' ', ' | sed 's/,$//')
|
|
108
|
+
|
|
109
|
+
echo "{\"decision\": \"block\", \"reason\": \"spec.md missing required 'board:' field in YAML frontmatter.\\n\\n2-level structure detected (project: ${PROJECT}).\\n\\nAvailable boards: ${AVAILABLE_BOARDS:-none detected}\\n\\nAdd 'board: <board_name>' to frontmatter.\\n\\nRun 'specweave context boards --project=${PROJECT}' to see all options.\"}"
|
|
98
110
|
exit 0
|
|
99
111
|
fi
|
|
112
|
+
|
|
113
|
+
# Validate project exists in configuration
|
|
114
|
+
PROJECT_EXISTS=$(echo "$CONTEXT_OUTPUT" | jq --arg proj "$PROJECT" '.projects[] | select(.id == $proj)' 2>/dev/null)
|
|
115
|
+
if [ -z "$PROJECT_EXISTS" ]; then
|
|
116
|
+
# Try case-insensitive match
|
|
117
|
+
PROJECT_EXISTS=$(echo "$CONTEXT_OUTPUT" | jq --arg proj "$PROJECT" '.projects[] | select(.id | ascii_downcase == ($proj | ascii_downcase))' 2>/dev/null)
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
if [ -z "$PROJECT_EXISTS" ] && [ -n "$AVAILABLE_PROJECTS" ]; then
|
|
121
|
+
echo "{\"decision\": \"block\", \"reason\": \"Project '${PROJECT}' not found in configuration.\\n\\nAvailable projects: ${AVAILABLE_PROJECTS}\\n\\nEither:\\n1. Update project: field to a valid project\\n2. Set SPECWEAVE_FORCE_PROJECT=1 to bypass validation\"}"
|
|
122
|
+
exit 0
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
# Validate board exists under project
|
|
126
|
+
BOARDS_OUTPUT=$(specweave context boards --project="$PROJECT" 2>/dev/null || echo '{"boards": []}')
|
|
127
|
+
BOARD_EXISTS=$(echo "$BOARDS_OUTPUT" | jq --arg board "$BOARD" '.boards[] | select(.id == $board)' 2>/dev/null)
|
|
128
|
+
|
|
129
|
+
if [ -z "$BOARD_EXISTS" ]; then
|
|
130
|
+
# Try case-insensitive match
|
|
131
|
+
BOARD_EXISTS=$(echo "$BOARDS_OUTPUT" | jq --arg board "$BOARD" '.boards[] | select(.id | ascii_downcase == ($board | ascii_downcase))' 2>/dev/null)
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
AVAILABLE_BOARDS=$(echo "$BOARDS_OUTPUT" | jq -r '.boards[].id // empty' | tr '\n' ', ' | sed 's/,$//')
|
|
135
|
+
|
|
136
|
+
if [ -z "$BOARD_EXISTS" ] && [ -n "$AVAILABLE_BOARDS" ]; then
|
|
137
|
+
echo "{\"decision\": \"block\", \"reason\": \"Board '${BOARD}' not found under project '${PROJECT}'.\\n\\nAvailable boards: ${AVAILABLE_BOARDS}\\n\\nEither:\\n1. Update board: field to a valid board\\n2. Set SPECWEAVE_FORCE_PROJECT=1 to bypass validation\"}"
|
|
138
|
+
exit 0
|
|
139
|
+
fi
|
|
140
|
+
|
|
100
141
|
else
|
|
101
|
-
# 1-level: project is
|
|
142
|
+
# 1-level: project is REQUIRED (not just recommended)
|
|
143
|
+
|
|
102
144
|
if [ -z "$PROJECT" ] || [ "$PROJECT" = "null" ]; then
|
|
103
|
-
|
|
104
|
-
echo '{"decision": "allow", "message": "⚠️ spec.md should have '\''project:'\'' field in YAML frontmatter for explicit sync target."}'
|
|
145
|
+
echo "{\"decision\": \"block\", \"reason\": \"spec.md missing required 'project:' field in YAML frontmatter.\\n\\nAvailable projects: ${AVAILABLE_PROJECTS:-none detected}\\n\\nAdd 'project: <project_name>' to frontmatter.\\n\\nRun 'specweave context projects' to see all options.\"}"
|
|
105
146
|
exit 0
|
|
106
147
|
fi
|
|
148
|
+
|
|
149
|
+
# Validate project exists in configuration (if we have projects configured)
|
|
150
|
+
if [ -n "$AVAILABLE_PROJECTS" ]; then
|
|
151
|
+
PROJECT_EXISTS=$(echo "$CONTEXT_OUTPUT" | jq --arg proj "$PROJECT" '.projects[] | select(.id == $proj)' 2>/dev/null)
|
|
152
|
+
if [ -z "$PROJECT_EXISTS" ]; then
|
|
153
|
+
# Try case-insensitive match
|
|
154
|
+
PROJECT_EXISTS=$(echo "$CONTEXT_OUTPUT" | jq --arg proj "$PROJECT" '.projects[] | select(.id | ascii_downcase == ($proj | ascii_downcase))' 2>/dev/null)
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
if [ -z "$PROJECT_EXISTS" ]; then
|
|
158
|
+
echo "{\"decision\": \"block\", \"reason\": \"Project '${PROJECT}' not found in configuration.\\n\\nAvailable projects: ${AVAILABLE_PROJECTS}\\n\\nEither:\\n1. Update project: field to a valid project\\n2. Set SPECWEAVE_FORCE_PROJECT=1 to bypass validation\"}"
|
|
159
|
+
exit 0
|
|
160
|
+
fi
|
|
161
|
+
fi
|
|
107
162
|
fi
|
|
108
163
|
|
|
109
164
|
# All validations passed
|