specweave 0.32.2 → 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 +39 -0
- package/bin/specweave.js +34 -0
- 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/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 +111 -69
- package/dist/src/cli/commands/init.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/core/increment/increment-archiver.d.ts +25 -4
- package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
- package/dist/src/core/increment/increment-archiver.js +64 -20
- package/dist/src/core/increment/increment-archiver.js.map +1 -1
- package/dist/src/core/increment/increment-utils.d.ts +65 -0
- package/dist/src/core/increment/increment-utils.d.ts.map +1 -1
- package/dist/src/core/increment/increment-utils.js +114 -0
- package/dist/src/core/increment/increment-utils.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 +7 -3
- 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/intelligent-analyzer/architecture-generator.d.ts.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js +54 -2
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts +5 -1
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js +358 -30
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts +44 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.d.ts +6 -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 +17 -8
- 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/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/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/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/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-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/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/commands/specweave-costs.md +4 -4
- package/plugins/specweave/commands/specweave-do.md +9 -9
- package/plugins/specweave/commands/specweave-done.md +13 -0
- package/plugins/specweave/commands/specweave-validate.md +27 -1
- package/plugins/specweave/hooks/hooks.json +10 -0
- package/plugins/specweave/hooks/spec-project-validator.sh +80 -25
- package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +135 -0
- package/plugins/specweave/scripts/read-costs.sh +3 -3
- package/plugins/specweave/skills/code-standards-analyzer/SKILL.md +58 -6
- package/plugins/specweave/skills/increment-planner/SKILL.md +56 -25
- package/plugins/specweave/skills/increment-planner/templates/spec-multi-project.md +4 -2
- package/plugins/specweave/skills/increment-planner/templates/spec-single-project.md +2 -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-ado/commands/cleanup-duplicates.md +212 -0
- package/plugins/specweave-ado/commands/reconcile.md +120 -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-github/agents/github-manager/AGENT.md +2 -2
- 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/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
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
* Intelligent model selection for SpecWeave tasks based on complexity,
|
|
5
5
|
* instruction detail, and task characteristics.
|
|
6
6
|
*
|
|
7
|
-
* Strategy:
|
|
8
|
-
* - Haiku:
|
|
9
|
-
* -
|
|
10
|
-
* - Opus: Critical architecture, high-stakes decisions (rare)
|
|
7
|
+
* Strategy (Opus 4.5 Default):
|
|
8
|
+
* - Haiku: Simple/cheap operations, translations, mechanical work
|
|
9
|
+
* - Opus: Default for all complex work, architecture, creative problem-solving
|
|
11
10
|
*/
|
|
12
11
|
export type ModelTier = 'haiku' | 'sonnet' | 'opus';
|
|
13
12
|
export interface Task {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-selection.d.ts","sourceRoot":"","sources":["../../../src/utils/model-selection.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"model-selection.d.ts","sourceRoot":"","sources":["../../../src/utils/model-selection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AA4BD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,OAAO,GAAE;IACP,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CACtB,GACL,eAAe,CAkGjB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,GAAE;IACP,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;CACtB,GACL,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAS9B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAQxD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAU7D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,EAChB,eAAe,GAAE,MAAa,GAC7B,MAAM,CASR;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,EACvC,oBAAoB,GAAE,MAAa,GAClC;IACD,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB,CAkBA"}
|
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
* Intelligent model selection for SpecWeave tasks based on complexity,
|
|
5
5
|
* instruction detail, and task characteristics.
|
|
6
6
|
*
|
|
7
|
-
* Strategy:
|
|
8
|
-
* - Haiku:
|
|
9
|
-
* -
|
|
10
|
-
* - Opus: Critical architecture, high-stakes decisions (rare)
|
|
7
|
+
* Strategy (Opus 4.5 Default):
|
|
8
|
+
* - Haiku: Simple/cheap operations, translations, mechanical work
|
|
9
|
+
* - Opus: Default for all complex work, architecture, creative problem-solving
|
|
11
10
|
*/
|
|
12
11
|
/**
|
|
13
12
|
* Keywords that suggest complex thinking is required (Sonnet territory)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-selection.js","sourceRoot":"","sources":["../../../src/utils/model-selection.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"model-selection.js","sourceRoot":"","sources":["../../../src/utils/model-selection.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specweave",
|
|
3
|
-
"version": "0.32.
|
|
3
|
+
"version": "0.32.3",
|
|
4
4
|
"description": "Spec-driven development framework for Claude Code. AI-native workflow with living documentation, intelligent agents, and multilingual support (9 languages). Enterprise-grade traceability with permanent specs and temporary increments.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -889,3 +889,51 @@ If analysis fails at any phase:
|
|
|
889
889
|
- **PM Agent**: Uses standards during increment planning
|
|
890
890
|
- **Architect Agent**: References standards in HLD
|
|
891
891
|
- **Code Reviewer Agent**: Enforces standards during review
|
|
892
|
+
|
|
893
|
+
---
|
|
894
|
+
|
|
895
|
+
## Multi-Technology Support
|
|
896
|
+
|
|
897
|
+
**Status**: ✅ Implemented (increment 0122-multi-technology-governance)
|
|
898
|
+
|
|
899
|
+
| Technology | Config Files | Status |
|
|
900
|
+
|------------|--------------|--------|
|
|
901
|
+
| TypeScript/JS | `.eslintrc.*`, `.prettierrc`, `tsconfig.json` | ✅ Implemented |
|
|
902
|
+
| Python | `pyproject.toml`, `.pylintrc`, `ruff.toml`, `.flake8`, `mypy.ini` | ✅ Implemented |
|
|
903
|
+
| Go | `go.mod`, `.golangci.yml`, `staticcheck.conf` | ✅ Implemented |
|
|
904
|
+
| Java/Kotlin | `checkstyle.xml`, `pmd.xml`, `spotbugs.xml`, `detekt.yml` | ✅ Implemented |
|
|
905
|
+
| C#/.NET | `.editorconfig`, `StyleCop.json`, `Directory.Build.props` | ✅ Implemented |
|
|
906
|
+
| Rust | `rustfmt.toml`, `clippy.toml`, `Cargo.toml` | ✅ Implemented |
|
|
907
|
+
| React | ESLint + `plugin:react/*`, `package.json` | ✅ Implemented |
|
|
908
|
+
| Angular | `angular.json`, `.eslintrc` | ✅ Implemented |
|
|
909
|
+
| Vue | ESLint + `plugin:vue/*`, `vite.config.*` | ✅ Implemented |
|
|
910
|
+
| Svelte | `svelte.config.js`, `package.json` | ✅ Implemented |
|
|
911
|
+
|
|
912
|
+
**Output Structure:**
|
|
913
|
+
```
|
|
914
|
+
.specweave/docs/internal/governance/
|
|
915
|
+
├── coding-standards.md # Unified summary of ALL technologies
|
|
916
|
+
├── shared-conventions.md # EditorConfig, Git conventions
|
|
917
|
+
└── standards/
|
|
918
|
+
├── typescript.md
|
|
919
|
+
├── python.md
|
|
920
|
+
├── golang.md
|
|
921
|
+
├── java.md
|
|
922
|
+
├── react.md
|
|
923
|
+
├── angular.md
|
|
924
|
+
├── vue.md
|
|
925
|
+
└── svelte.md
|
|
926
|
+
```
|
|
927
|
+
|
|
928
|
+
**Usage**:
|
|
929
|
+
```typescript
|
|
930
|
+
import {
|
|
931
|
+
detectEcosystems,
|
|
932
|
+
parsePythonStandards,
|
|
933
|
+
parseGoStandards,
|
|
934
|
+
parseJavaStandards,
|
|
935
|
+
parseFrontendStandards,
|
|
936
|
+
generateStandardsMarkdown,
|
|
937
|
+
generateUnifiedSummary
|
|
938
|
+
} from 'src/core/living-docs/governance/index.js';
|
|
939
|
+
```
|
|
@@ -11,9 +11,9 @@ You are being invoked via the `/specweave:costs [incrementId]` command.
|
|
|
11
11
|
|
|
12
12
|
Display a comprehensive cost dashboard showing:
|
|
13
13
|
1. Token usage breakdown
|
|
14
|
-
2. Cost by model (
|
|
14
|
+
2. Cost by model (Opus vs Haiku)
|
|
15
15
|
3. Cost by agent
|
|
16
|
-
4. Savings vs baseline (all-
|
|
16
|
+
4. Savings vs baseline (all-Opus)
|
|
17
17
|
5. Recent sessions
|
|
18
18
|
|
|
19
19
|
**Optional**: Export data to JSON/CSV format
|
|
@@ -155,7 +155,7 @@ SUMMARY
|
|
|
155
155
|
|
|
156
156
|
COST BY MODEL
|
|
157
157
|
───────────────────────────────────────────────────────────────
|
|
158
|
-
|
|
158
|
+
opus $ 0.0734 ( 59.4%)
|
|
159
159
|
haiku $ 0.0500 ( 40.6%)
|
|
160
160
|
|
|
161
161
|
COST BY AGENT
|
|
@@ -240,7 +240,7 @@ Use /specweave:costs without arguments to see all increments.
|
|
|
240
240
|
## Important Notes
|
|
241
241
|
|
|
242
242
|
1. **Cost Data Persistence**: Costs are persisted to `.specweave/logs/costs.json`
|
|
243
|
-
2. **Baseline Calculation**: Savings are calculated vs an all-
|
|
243
|
+
2. **Baseline Calculation**: Savings are calculated vs an all-Opus baseline
|
|
244
244
|
3. **Real-Time Updates**: Costs update after each agent invocation
|
|
245
245
|
4. **Export Formats**: JSON for machine parsing, CSV for spreadsheet import
|
|
246
246
|
5. **Privacy**: Cost data is local only, never sent to external services
|
|
@@ -31,9 +31,9 @@ You are helping the user implement a SpecWeave increment by executing tasks from
|
|
|
31
31
|
- **Smart resume**: Automatically starts from next incomplete task
|
|
32
32
|
|
|
33
33
|
- `--model <tier>`: Optional. Override model selection for all tasks
|
|
34
|
-
- `haiku`: Fast, cheap execution (
|
|
35
|
-
- `sonnet`:
|
|
36
|
-
- `opus`: Maximum quality (default for all tasks)
|
|
34
|
+
- `haiku`: Fast, cheap execution (simple mechanical tasks)
|
|
35
|
+
- `sonnet`: Legacy option (rarely needed)
|
|
36
|
+
- `opus`: Maximum quality (default for all complex tasks)
|
|
37
37
|
- If omitted, uses model hints from tasks.md (recommended)
|
|
38
38
|
|
|
39
39
|
---
|
|
@@ -162,13 +162,13 @@ You are helping the user implement a SpecWeave increment by executing tasks from
|
|
|
162
162
|
📊 Resume Context:
|
|
163
163
|
|
|
164
164
|
Completed: 3/12 tasks (25%)
|
|
165
|
-
├─ [✅] T001: ⚡ haiku - Setup auth module (P1) [saved $0.
|
|
166
|
-
├─ [✅] T002: ⚡ haiku - Create user model (P1) [saved $0.
|
|
167
|
-
├─ [✅] T003:
|
|
165
|
+
├─ [✅] T001: ⚡ haiku - Setup auth module (P1) [saved $0.14]
|
|
166
|
+
├─ [✅] T002: ⚡ haiku - Create user model (P1) [saved $0.14]
|
|
167
|
+
├─ [✅] T003: 💎 opus - Implement JWT tokens (P1)
|
|
168
168
|
└─ [⏳] T004: ⚡ haiku - Add password hashing (P1) ← RESUMING HERE
|
|
169
169
|
|
|
170
170
|
Remaining: 9 tasks (estimated 2 weeks)
|
|
171
|
-
Cost savings so far: $0.
|
|
171
|
+
Cost savings so far: $0.28 (67% cheaper than all-Opus)
|
|
172
172
|
```
|
|
173
173
|
|
|
174
174
|
**Why smart resume?**
|
|
@@ -281,14 +281,14 @@ TASK T001: Create User model (PostgreSQL)
|
|
|
281
281
|
• Description: Create User model with Prisma
|
|
282
282
|
• Acceptance: Model has id, email, passwordHash, createdAt fields
|
|
283
283
|
|
|
284
|
-
⚡ Executing with Haiku (3x faster, ~$0.0025 vs $0.
|
|
284
|
+
⚡ Executing with Haiku (3x faster, ~$0.0025 vs $0.15 Opus)...
|
|
285
285
|
✓ Created src/models/User.ts
|
|
286
286
|
✓ Added Prisma schema definition
|
|
287
287
|
✓ Generated migration file
|
|
288
288
|
✓ Added inline documentation
|
|
289
289
|
|
|
290
290
|
✅ Task T001 completed
|
|
291
|
-
💰 Cost savings: $0.
|
|
291
|
+
💰 Cost savings: $0.1475 (98% cheaper than Opus)
|
|
292
292
|
|
|
293
293
|
🔊 [Glass.aiff plays automatically via hook]
|
|
294
294
|
🔔 Task completed! Remember to update documentation...
|
|
@@ -89,6 +89,19 @@ status was set to "completed" without ACs being checked or user approval.
|
|
|
89
89
|
```typescript
|
|
90
90
|
import { IncrementCompletionValidator } from '../../../src/core/increment/completion-validator.js';
|
|
91
91
|
import { DesyncDetector } from '../../../src/core/increment/desync-detector.js';
|
|
92
|
+
import { ACStatusManager } from '../../../src/core/increment/ac-status-manager.js';
|
|
93
|
+
|
|
94
|
+
// **NEW (2025-12-08)**: Sync ACs BEFORE validation to prevent race conditions
|
|
95
|
+
// The background hook (post-task-completion.sh) may not have completed yet
|
|
96
|
+
// This ensures spec.md ACs are up-to-date with tasks.md completion status
|
|
97
|
+
console.log('🔄 Syncing AC status before validation...');
|
|
98
|
+
const acManager = new ACStatusManager(projectRoot);
|
|
99
|
+
const acSyncResult = await acManager.syncACStatus(incrementId);
|
|
100
|
+
if (acSyncResult.synced && acSyncResult.updated.length > 0) {
|
|
101
|
+
console.log(`✅ Updated ${acSyncResult.updated.length} ACs: ${acSyncResult.updated.join(', ')}`);
|
|
102
|
+
} else {
|
|
103
|
+
console.log('✅ AC status already in sync');
|
|
104
|
+
}
|
|
92
105
|
|
|
93
106
|
// **NEW (2025-11-20)**: Validate no status desync exists
|
|
94
107
|
// This prevents closing increments with inconsistent metadata.json and spec.md
|
|
@@ -95,6 +95,32 @@ Available increments:
|
|
|
95
95
|
Usage: /specweave:validate-increment <id> [--quality] [--export] [--fix] [--always]
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
+
### Step 1.5: Sync AC Status (NEW - v0.33.0)
|
|
99
|
+
|
|
100
|
+
**Before running validation, synchronize spec.md ACs with tasks.md completion status**:
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { ACStatusManager } from '../../../src/core/increment/ac-status-manager.js';
|
|
104
|
+
|
|
105
|
+
// Sync ACs BEFORE validation to prevent false positives
|
|
106
|
+
// This ensures spec.md ACs reflect actual task completion from tasks.md
|
|
107
|
+
console.log('🔄 Syncing AC status before validation...');
|
|
108
|
+
const acManager = new ACStatusManager(projectRoot);
|
|
109
|
+
const acSyncResult = await acManager.syncACStatus(incrementId);
|
|
110
|
+
|
|
111
|
+
if (acSyncResult.synced && acSyncResult.updated.length > 0) {
|
|
112
|
+
console.log(`✅ Pre-validation sync: Updated ${acSyncResult.updated.length} ACs`);
|
|
113
|
+
acSyncResult.updated.forEach(acId => console.log(` ${acId} → [x]`));
|
|
114
|
+
} else {
|
|
115
|
+
console.log('✅ AC status already in sync');
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Why this matters**:
|
|
120
|
+
- Background hooks (`post-task-completion.sh`) run async and may not complete before validation
|
|
121
|
+
- This explicit sync prevents "0 ACs checked" false positives
|
|
122
|
+
- Idempotent: safe to call multiple times (no-op if already synced)
|
|
123
|
+
|
|
98
124
|
### Step 2: Run Rule-Based Validation (Always)
|
|
99
125
|
|
|
100
126
|
Run 130+ validation rules across 7 categories:
|
|
@@ -260,7 +286,7 @@ This will:
|
|
|
260
286
|
• Evaluate spec clarity, testability, edge cases
|
|
261
287
|
• Provide detailed improvement suggestions
|
|
262
288
|
• Use ~2,000 tokens (1-2 minutes)
|
|
263
|
-
• Cost: ~$0.
|
|
289
|
+
• Cost: ~$0.05 (Claude Opus 4.5)
|
|
264
290
|
|
|
265
291
|
Your choice:
|
|
266
292
|
[Y] Yes, assess quality
|
|
@@ -59,6 +59,16 @@
|
|
|
59
59
|
"command": "bash -c 'W=\"${CLAUDE_PLUGIN_ROOT}/hooks/universal/fail-fast-wrapper.sh\"; S=\"${CLAUDE_PLUGIN_ROOT}/hooks/v2/guards/features-folder-guard.sh\"; [[ -x \"$W\" ]] && exec \"$W\" \"$S\" || (cat >/dev/null && printf \"{\\\"decision\\\":\\\"allow\\\"}\")'"
|
|
60
60
|
}
|
|
61
61
|
]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"matcher": "Write",
|
|
65
|
+
"matcher_content": "\\.specweave/increments/\\d{3,4}E?-[^/]+/",
|
|
66
|
+
"hooks": [
|
|
67
|
+
{
|
|
68
|
+
"type": "command",
|
|
69
|
+
"command": "bash -c 'W=\"${CLAUDE_PLUGIN_ROOT}/hooks/universal/fail-fast-wrapper.sh\"; S=\"${CLAUDE_PLUGIN_ROOT}/hooks/v2/guards/increment-duplicate-guard.sh\"; [[ -x \"$W\" ]] && exec \"$W\" \"$S\" || (cat >/dev/null && printf \"{\\\"decision\\\":\\\"allow\\\"}\")'"
|
|
70
|
+
}
|
|
71
|
+
]
|
|
62
72
|
}
|
|
63
73
|
],
|
|
64
74
|
"PostToolUse": [
|
|
@@ -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
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# increment-duplicate-guard.sh - Block creation of duplicate increment IDs
|
|
3
|
+
#
|
|
4
|
+
# v0.33.0+: Prevents duplicate increment numbers (0121 and 0121 both existing)
|
|
5
|
+
# Also prevents 0001 and 0001E collisions (they share the same base number)
|
|
6
|
+
#
|
|
7
|
+
# PreToolUse hook for Write tool - BLOCKS the tool call if duplicate detected
|
|
8
|
+
#
|
|
9
|
+
# CRITICAL: This guards against the BUG where two increments get the same ID:
|
|
10
|
+
# - 0121-ado-jira-feature-parity-p2-p3
|
|
11
|
+
# - 0121-intelligent-living-docs-content
|
|
12
|
+
#
|
|
13
|
+
# Exit 0 = allow, Exit 2 = block
|
|
14
|
+
set +e
|
|
15
|
+
|
|
16
|
+
[[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
|
|
17
|
+
|
|
18
|
+
# Read stdin for tool input
|
|
19
|
+
INPUT=$(cat)
|
|
20
|
+
|
|
21
|
+
# Extract file_path from the tool call
|
|
22
|
+
FILE_PATH=$(echo "$INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/')
|
|
23
|
+
|
|
24
|
+
# Only care about .specweave/increments/ paths
|
|
25
|
+
if [[ "$FILE_PATH" != *.specweave/increments/* ]]; then
|
|
26
|
+
exit 0 # Not an increment file - allow
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# Extract the increment folder name from the path
|
|
30
|
+
# Pattern: .specweave/increments/XXXX-name/file.md or .specweave/increments/XXXX-name/subfolder/file
|
|
31
|
+
# We need to extract "XXXX-name" part
|
|
32
|
+
|
|
33
|
+
# Remove the .specweave/increments/ prefix
|
|
34
|
+
AFTER_INCREMENTS=${FILE_PATH#*.specweave/increments/}
|
|
35
|
+
|
|
36
|
+
# Get the first path component (the increment folder)
|
|
37
|
+
INCREMENT_FOLDER=$(echo "$AFTER_INCREMENTS" | cut -d'/' -f1)
|
|
38
|
+
|
|
39
|
+
# Skip special folders
|
|
40
|
+
if [[ "$INCREMENT_FOLDER" == "_archive" ]] || [[ "$INCREMENT_FOLDER" == "_abandoned" ]] || [[ "$INCREMENT_FOLDER" == "_paused" ]] || [[ "$INCREMENT_FOLDER" == "README.md" ]]; then
|
|
41
|
+
exit 0
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Extract the increment number from folder name (handles both 0121-name and 0121E-name)
|
|
45
|
+
INCREMENT_NUM=$(echo "$INCREMENT_FOLDER" | grep -oE '^[0-9]{3,4}' | head -1)
|
|
46
|
+
|
|
47
|
+
if [[ -z "$INCREMENT_NUM" ]]; then
|
|
48
|
+
exit 0 # Not a standard increment folder pattern - allow
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# Normalize to 4 digits (strip leading zeros to avoid octal interpretation)
|
|
52
|
+
INCREMENT_NUM=$(printf "%04d" "$((10#$INCREMENT_NUM))")
|
|
53
|
+
|
|
54
|
+
# Find the increments root directory
|
|
55
|
+
INCREMENTS_DIR=$(echo "$FILE_PATH" | grep -o '.*/\.specweave/increments' | head -1)
|
|
56
|
+
|
|
57
|
+
if [[ ! -d "$INCREMENTS_DIR" ]]; then
|
|
58
|
+
exit 0 # Increments directory doesn't exist yet - allow (first increment)
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# Scan ALL directories for existing increment with the same number
|
|
62
|
+
DIRS_TO_CHECK=(
|
|
63
|
+
"$INCREMENTS_DIR"
|
|
64
|
+
"$INCREMENTS_DIR/_archive"
|
|
65
|
+
"$INCREMENTS_DIR/_abandoned"
|
|
66
|
+
"$INCREMENTS_DIR/_paused"
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
FOUND_DUPLICATES=()
|
|
70
|
+
|
|
71
|
+
for DIR in "${DIRS_TO_CHECK[@]}"; do
|
|
72
|
+
if [[ ! -d "$DIR" ]]; then
|
|
73
|
+
continue
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# Find all folders matching this increment number (including E suffix variants)
|
|
77
|
+
while IFS= read -r -d '' EXISTING_FOLDER; do
|
|
78
|
+
EXISTING_NAME=$(basename "$EXISTING_FOLDER")
|
|
79
|
+
|
|
80
|
+
# Extract number from existing folder
|
|
81
|
+
EXISTING_NUM=$(echo "$EXISTING_NAME" | grep -oE '^[0-9]{3,4}' | head -1)
|
|
82
|
+
|
|
83
|
+
if [[ -z "$EXISTING_NUM" ]]; then
|
|
84
|
+
continue
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
EXISTING_NUM=$(printf "%04d" "$((10#$EXISTING_NUM))")
|
|
88
|
+
|
|
89
|
+
# Check if same base number (0121 matches 0121, 0121E, etc.)
|
|
90
|
+
if [[ "$EXISTING_NUM" == "$INCREMENT_NUM" ]]; then
|
|
91
|
+
# Skip if it's the exact same folder we're creating
|
|
92
|
+
if [[ "$EXISTING_NAME" == "$INCREMENT_FOLDER" ]]; then
|
|
93
|
+
continue
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
# Found a duplicate!
|
|
97
|
+
FOUND_DUPLICATES+=("$EXISTING_NAME (in $(basename "$DIR"))")
|
|
98
|
+
fi
|
|
99
|
+
done < <(find "$DIR" -maxdepth 1 -type d -name "${INCREMENT_NUM}*" -print0 2>/dev/null)
|
|
100
|
+
done
|
|
101
|
+
|
|
102
|
+
# If duplicates found, BLOCK the operation
|
|
103
|
+
if [[ ${#FOUND_DUPLICATES[@]} -gt 0 ]]; then
|
|
104
|
+
echo ""
|
|
105
|
+
echo "=============================================================================="
|
|
106
|
+
echo " BLOCKED: Duplicate increment ID detected (v0.33.0+)"
|
|
107
|
+
echo "=============================================================================="
|
|
108
|
+
echo ""
|
|
109
|
+
echo "You are trying to create increment: $INCREMENT_FOLDER"
|
|
110
|
+
echo "But increment number $INCREMENT_NUM already exists:"
|
|
111
|
+
echo ""
|
|
112
|
+
for DUP in "${FOUND_DUPLICATES[@]}"; do
|
|
113
|
+
echo " - $DUP"
|
|
114
|
+
done
|
|
115
|
+
echo ""
|
|
116
|
+
echo "IMPORTANT: Increment IDs MUST be unique across all directories:"
|
|
117
|
+
echo " - Active increments"
|
|
118
|
+
echo " - Archived increments (_archive/)"
|
|
119
|
+
echo " - Abandoned increments (_abandoned/)"
|
|
120
|
+
echo " - Paused increments (_paused/)"
|
|
121
|
+
echo ""
|
|
122
|
+
echo "NOTE: 0001 and 0001E share the SAME base number and cannot coexist!"
|
|
123
|
+
echo ""
|
|
124
|
+
echo "TO FIX:"
|
|
125
|
+
echo "1. Use a different increment number"
|
|
126
|
+
echo "2. Get the next available number:"
|
|
127
|
+
echo " node -e \"import('./dist/core/increment/increment-utils.js').then(m => console.log(m.IncrementNumberManager.getNextIncrementNumber()))\""
|
|
128
|
+
echo ""
|
|
129
|
+
echo "=============================================================================="
|
|
130
|
+
|
|
131
|
+
exit 2 # Block the tool call
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
# No duplicates - allow
|
|
135
|
+
exit 0
|
|
@@ -66,12 +66,12 @@ if [[ "$TOTAL_TOKENS" -eq 0 ]] && [[ "$TOTAL_COST" == "0" ]]; then
|
|
|
66
66
|
echo ""
|
|
67
67
|
echo "💡 Tips:"
|
|
68
68
|
echo " • Use ⚡ haiku for simple tasks (3x faster, 20x cheaper)"
|
|
69
|
-
echo " • Use
|
|
70
|
-
echo " • Use
|
|
69
|
+
echo " • Use 💎 opus for complex reasoning (default, best quality)"
|
|
70
|
+
echo " • Use 🧠 sonnet only for legacy compatibility (rarely needed)"
|
|
71
71
|
echo ""
|
|
72
72
|
echo "Model hints in tasks.md:"
|
|
73
73
|
echo " ### T-001: Setup project structure ⚡"
|
|
74
|
-
echo " ### T-002: Design architecture
|
|
74
|
+
echo " ### T-002: Design architecture 💎"
|
|
75
75
|
exit 0
|
|
76
76
|
fi
|
|
77
77
|
|