specweave 1.0.550 → 1.0.552

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.
Files changed (166) hide show
  1. package/CLAUDE.md +1 -1
  2. package/bin/specweave.js +23 -1
  3. package/dist/src/cli/commands/hook.d.ts +15 -0
  4. package/dist/src/cli/commands/hook.d.ts.map +1 -0
  5. package/dist/src/cli/commands/hook.js +61 -0
  6. package/dist/src/cli/commands/hook.js.map +1 -0
  7. package/dist/src/cli/commands/init.d.ts.map +1 -1
  8. package/dist/src/cli/commands/init.js +5 -0
  9. package/dist/src/cli/commands/init.js.map +1 -1
  10. package/dist/src/cli/commands/refresh-plugins.d.ts.map +1 -1
  11. package/dist/src/cli/commands/refresh-plugins.js +11 -1
  12. package/dist/src/cli/commands/refresh-plugins.js.map +1 -1
  13. package/dist/src/cli/commands/sync-setup.d.ts.map +1 -1
  14. package/dist/src/cli/commands/sync-setup.js +7 -3
  15. package/dist/src/cli/commands/sync-setup.js.map +1 -1
  16. package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.d.ts +9 -0
  17. package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.d.ts.map +1 -1
  18. package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.js +9 -3
  19. package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.js.map +1 -1
  20. package/dist/src/config/types.d.ts +2 -2
  21. package/dist/src/core/config/types.d.ts +18 -2
  22. package/dist/src/core/config/types.d.ts.map +1 -1
  23. package/dist/src/core/config/types.js.map +1 -1
  24. package/dist/src/core/hooks/handlers/hook-router.d.ts +19 -0
  25. package/dist/src/core/hooks/handlers/hook-router.d.ts.map +1 -0
  26. package/dist/src/core/hooks/handlers/hook-router.js +75 -0
  27. package/dist/src/core/hooks/handlers/hook-router.js.map +1 -0
  28. package/dist/src/core/hooks/handlers/index.d.ts +10 -0
  29. package/dist/src/core/hooks/handlers/index.d.ts.map +1 -0
  30. package/dist/src/core/hooks/handlers/index.js +9 -0
  31. package/dist/src/core/hooks/handlers/index.js.map +1 -0
  32. package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts +11 -0
  33. package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts.map +1 -0
  34. package/dist/src/core/hooks/handlers/post-tool-use-analytics.js +73 -0
  35. package/dist/src/core/hooks/handlers/post-tool-use-analytics.js.map +1 -0
  36. package/dist/src/core/hooks/handlers/post-tool-use.d.ts +11 -0
  37. package/dist/src/core/hooks/handlers/post-tool-use.d.ts.map +1 -0
  38. package/dist/src/core/hooks/handlers/post-tool-use.js +76 -0
  39. package/dist/src/core/hooks/handlers/post-tool-use.js.map +1 -0
  40. package/dist/src/core/hooks/handlers/pre-compact.d.ts +11 -0
  41. package/dist/src/core/hooks/handlers/pre-compact.d.ts.map +1 -0
  42. package/dist/src/core/hooks/handlers/pre-compact.js +77 -0
  43. package/dist/src/core/hooks/handlers/pre-compact.js.map +1 -0
  44. package/dist/src/core/hooks/handlers/pre-tool-use.d.ts +11 -0
  45. package/dist/src/core/hooks/handlers/pre-tool-use.d.ts.map +1 -0
  46. package/dist/src/core/hooks/handlers/pre-tool-use.js +318 -0
  47. package/dist/src/core/hooks/handlers/pre-tool-use.js.map +1 -0
  48. package/dist/src/core/hooks/handlers/session-start.d.ts +9 -0
  49. package/dist/src/core/hooks/handlers/session-start.d.ts.map +1 -0
  50. package/dist/src/core/hooks/handlers/session-start.js +111 -0
  51. package/dist/src/core/hooks/handlers/session-start.js.map +1 -0
  52. package/dist/src/core/hooks/handlers/stop-auto.d.ts +16 -0
  53. package/dist/src/core/hooks/handlers/stop-auto.d.ts.map +1 -0
  54. package/dist/src/core/hooks/handlers/stop-auto.js +122 -0
  55. package/dist/src/core/hooks/handlers/stop-auto.js.map +1 -0
  56. package/dist/src/core/hooks/handlers/stop-reflect.d.ts +14 -0
  57. package/dist/src/core/hooks/handlers/stop-reflect.d.ts.map +1 -0
  58. package/dist/src/core/hooks/handlers/stop-reflect.js +43 -0
  59. package/dist/src/core/hooks/handlers/stop-reflect.js.map +1 -0
  60. package/dist/src/core/hooks/handlers/stop-sync.d.ts +15 -0
  61. package/dist/src/core/hooks/handlers/stop-sync.d.ts.map +1 -0
  62. package/dist/src/core/hooks/handlers/stop-sync.js +68 -0
  63. package/dist/src/core/hooks/handlers/stop-sync.js.map +1 -0
  64. package/dist/src/core/hooks/handlers/types.d.ts +63 -0
  65. package/dist/src/core/hooks/handlers/types.d.ts.map +1 -0
  66. package/dist/src/core/hooks/handlers/types.js +27 -0
  67. package/dist/src/core/hooks/handlers/types.js.map +1 -0
  68. package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts +14 -0
  69. package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts.map +1 -0
  70. package/dist/src/core/hooks/handlers/user-prompt-submit.js +173 -0
  71. package/dist/src/core/hooks/handlers/user-prompt-submit.js.map +1 -0
  72. package/dist/src/core/hooks/handlers/utils.d.ts +25 -0
  73. package/dist/src/core/hooks/handlers/utils.d.ts.map +1 -0
  74. package/dist/src/core/hooks/handlers/utils.js +64 -0
  75. package/dist/src/core/hooks/handlers/utils.js.map +1 -0
  76. package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
  77. package/dist/src/core/increment/completion-validator.js +32 -0
  78. package/dist/src/core/increment/completion-validator.js.map +1 -1
  79. package/dist/src/init/research/types.d.ts +1 -1
  80. package/dist/src/sync/sync-target-resolver.js.map +1 -1
  81. package/dist/src/utils/lock-manager.d.ts.map +1 -1
  82. package/dist/src/utils/lock-manager.js +5 -0
  83. package/dist/src/utils/lock-manager.js.map +1 -1
  84. package/dist/src/utils/plugin-copier.d.ts +10 -0
  85. package/dist/src/utils/plugin-copier.d.ts.map +1 -1
  86. package/dist/src/utils/plugin-copier.js +63 -35
  87. package/dist/src/utils/plugin-copier.js.map +1 -1
  88. package/package.json +1 -1
  89. package/plugins/specweave/agents/sw-closer.md +3 -2
  90. package/plugins/specweave/hooks/hooks.json +10 -10
  91. package/plugins/specweave/skills/code-reviewer/SKILL.md +180 -16
  92. package/plugins/specweave/skills/code-reviewer/agents/reviewer-comments.md +83 -0
  93. package/plugins/specweave/skills/code-reviewer/agents/reviewer-silent-failures.md +19 -0
  94. package/plugins/specweave/skills/code-reviewer/agents/reviewer-spec-compliance.md +19 -0
  95. package/plugins/specweave/skills/code-reviewer/agents/reviewer-tests.md +101 -0
  96. package/plugins/specweave/skills/code-reviewer/agents/reviewer-types.md +20 -0
  97. package/plugins/specweave/skills/done/SKILL.md +56 -21
  98. package/plugins/specweave/skills/grill/SKILL.md +1 -1
  99. package/plugins/specweave/skills/team-lead/agents/reviewer-logic.md +19 -0
  100. package/plugins/specweave/skills/team-lead/agents/reviewer-performance.md +20 -0
  101. package/plugins/specweave/skills/team-lead/agents/reviewer-security.md +20 -0
  102. package/src/templates/CLAUDE.md.template +7 -4
  103. package/plugins/specweave/hooks/README.md +0 -493
  104. package/plugins/specweave/hooks/_archive/stop-auto-v4-legacy.sh +0 -1319
  105. package/plugins/specweave/hooks/lib/common-setup.sh +0 -144
  106. package/plugins/specweave/hooks/lib/hook-errors.sh +0 -414
  107. package/plugins/specweave/hooks/lib/migrate-increment-work.sh +0 -245
  108. package/plugins/specweave/hooks/lib/resolve-package.sh +0 -146
  109. package/plugins/specweave/hooks/lib/scheduler-startup.sh +0 -135
  110. package/plugins/specweave/hooks/lib/score-increment.sh +0 -87
  111. package/plugins/specweave/hooks/lib/sync-spec-content.sh +0 -193
  112. package/plugins/specweave/hooks/lib/update-active-increment.sh +0 -95
  113. package/plugins/specweave/hooks/lib/update-status-line.sh +0 -233
  114. package/plugins/specweave/hooks/lib/validate-spec-status.sh +0 -171
  115. package/plugins/specweave/hooks/llm-judge-validator.sh +0 -219
  116. package/plugins/specweave/hooks/log-decision.sh +0 -168
  117. package/plugins/specweave/hooks/pre-compact.sh +0 -64
  118. package/plugins/specweave/hooks/startup-health-check.sh +0 -64
  119. package/plugins/specweave/hooks/stop-auto-v5.sh +0 -276
  120. package/plugins/specweave/hooks/stop-reflect.sh +0 -336
  121. package/plugins/specweave/hooks/stop-sync.sh +0 -283
  122. package/plugins/specweave/hooks/tests/test-auto-context-integration.sh +0 -126
  123. package/plugins/specweave/hooks/tests/test-stop-auto-enriched.sh +0 -128
  124. package/plugins/specweave/hooks/universal/dispatcher.mjs +0 -336
  125. package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +0 -325
  126. package/plugins/specweave/hooks/universal/hook-wrapper.cmd +0 -26
  127. package/plugins/specweave/hooks/universal/hook-wrapper.sh +0 -69
  128. package/plugins/specweave/hooks/universal/run-hook.sh +0 -20
  129. package/plugins/specweave/hooks/universal/session-start.cmd +0 -16
  130. package/plugins/specweave/hooks/universal/session-start.ps1 +0 -16
  131. package/plugins/specweave/hooks/user-prompt-submit.sh +0 -2550
  132. package/plugins/specweave/hooks/v2/detectors/lifecycle-detector.sh +0 -87
  133. package/plugins/specweave/hooks/v2/detectors/us-completion-detector.sh +0 -186
  134. package/plugins/specweave/hooks/v2/dispatchers/post-tool-use-analytics.sh +0 -83
  135. package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +0 -447
  136. package/plugins/specweave/hooks/v2/dispatchers/pre-tool-use.sh +0 -104
  137. package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +0 -270
  138. package/plugins/specweave/hooks/v2/guards/completion-guard.sh +0 -14
  139. package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +0 -14
  140. package/plugins/specweave/hooks/v2/guards/increment-existence-guard.sh +0 -240
  141. package/plugins/specweave/hooks/v2/guards/interview-enforcement-guard.sh +0 -171
  142. package/plugins/specweave/hooks/v2/guards/metadata-json-guard.sh +0 -14
  143. package/plugins/specweave/hooks/v2/guards/skill-chain-enforcement-guard.sh +0 -222
  144. package/plugins/specweave/hooks/v2/guards/spec-template-enforcement-guard.sh +0 -21
  145. package/plugins/specweave/hooks/v2/guards/spec-validation-guard.sh +0 -14
  146. package/plugins/specweave/hooks/v2/guards/status-completion-guard.sh +0 -84
  147. package/plugins/specweave/hooks/v2/guards/task-ac-sync-guard.sh +0 -475
  148. package/plugins/specweave/hooks/v2/guards/tdd-enforcement-guard.sh +0 -268
  149. package/plugins/specweave/hooks/v2/handlers/ac-sync-dispatcher.sh +0 -332
  150. package/plugins/specweave/hooks/v2/handlers/ac-validation-handler.sh +0 -50
  151. package/plugins/specweave/hooks/v2/handlers/github-sync-handler.sh +0 -347
  152. package/plugins/specweave/hooks/v2/handlers/living-docs-handler.sh +0 -83
  153. package/plugins/specweave/hooks/v2/handlers/living-specs-handler.sh +0 -268
  154. package/plugins/specweave/hooks/v2/handlers/project-bridge-handler.sh +0 -104
  155. package/plugins/specweave/hooks/v2/handlers/status-line-handler.sh +0 -165
  156. package/plugins/specweave/hooks/v2/handlers/status-update.sh +0 -61
  157. package/plugins/specweave/hooks/v2/handlers/universal-auto-create-dispatcher.sh +0 -270
  158. package/plugins/specweave/hooks/v2/integrations/ado-post-living-docs-update.sh +0 -367
  159. package/plugins/specweave/hooks/v2/integrations/ado-post-task.sh +0 -179
  160. package/plugins/specweave/hooks/v2/integrations/github-auto-create-handler.sh +0 -553
  161. package/plugins/specweave/hooks/v2/integrations/github-post-task.sh +0 -345
  162. package/plugins/specweave/hooks/v2/integrations/jira-post-task.sh +0 -180
  163. package/plugins/specweave/hooks/v2/lib/check-provider-enabled.sh +0 -52
  164. package/plugins/specweave/hooks/v2/queue/enqueue.sh +0 -81
  165. package/plugins/specweave/hooks/v2/session-end.sh +0 -139
  166. package/plugins/specweave/hooks/validate-skill-activations.sh +0 -227
@@ -1,171 +0,0 @@
1
- #!/bin/bash
2
- # interview-enforcement-guard.sh - Enforces Deep Interview completion before spec creation
3
- #
4
- # PURPOSE:
5
- # When Deep Interview Mode is enabled with "enforcement": "strict", this guard
6
- # BLOCKS spec.md completion until all interview categories have been covered.
7
- #
8
- # WORKFLOW ENFORCED:
9
- # 1. User starts /sw:increment
10
- # 2. Interview state file created: .specweave/state/interview-{increment-id}.json
11
- # 3. PM skill marks categories as covered during interview
12
- # 4. Spec.md writing BLOCKED until all categories are marked complete
13
- #
14
- # DETECTION LOGIC:
15
- # - CHECK: deepInterview.enabled && deepInterview.enforcement == "strict"
16
- # - CHECK: Interview state file exists and has all categories covered
17
- # - BLOCK: If categories are missing, show which ones
18
- # - ALLOW: All categories covered OR enforcement != "strict"
19
- #
20
- # @since 1.0.198
21
-
22
- set -e
23
-
24
- # Read hook input
25
- INPUT=$(cat)
26
-
27
- # Extract file path and tool from input
28
- TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // .toolName // ""')
29
- FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .toolInput.file_path // ""')
30
- CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // .toolInput.content // ""')
31
-
32
- # Only check Write operations to spec.md in increment folders
33
- if [[ "$TOOL_NAME" != "Write" ]]; then
34
- echo '{"decision":"allow"}'
35
- exit 0
36
- fi
37
-
38
- # Check if this is a spec.md in an increment folder
39
- if [[ ! "$FILE_PATH" =~ \.specweave/increments/[0-9]{4}-[^/]+/spec\.md$ ]]; then
40
- echo '{"decision":"allow"}'
41
- exit 0
42
- fi
43
-
44
- # Extract increment ID from path
45
- INCREMENT_ID=$(echo "$FILE_PATH" | grep -oE '[0-9]{4}-[^/]+' | head -1)
46
-
47
- # Find project root (where .specweave/ is)
48
- PROJECT_ROOT=$(echo "$FILE_PATH" | sed 's|/.specweave/.*|/|')
49
- CONFIG_PATH="${PROJECT_ROOT}.specweave/config.json"
50
-
51
- # Check if Deep Interview Mode is enabled with strict enforcement
52
- if [[ ! -f "$CONFIG_PATH" ]]; then
53
- echo '{"decision":"allow"}'
54
- exit 0
55
- fi
56
-
57
- DEEP_INTERVIEW_ENABLED=$(jq -r '.planning.deepInterview.enabled // false' "$CONFIG_PATH" 2>/dev/null)
58
- ENFORCEMENT=$(jq -r '.planning.deepInterview.enforcement // "advisory"' "$CONFIG_PATH" 2>/dev/null)
59
-
60
- # If not enabled or not strict, allow
61
- if [[ "$DEEP_INTERVIEW_ENABLED" != "true" ]] || [[ "$ENFORCEMENT" != "strict" ]]; then
62
- echo '{"decision":"allow"}'
63
- exit 0
64
- fi
65
-
66
- # Get required categories from config
67
- REQUIRED_CATEGORIES=$(jq -r '.planning.deepInterview.categories // ["architecture","integrations","ui-ux","performance","security","edge-cases"] | .[]' "$CONFIG_PATH" 2>/dev/null)
68
-
69
- # Check if this is a template being created (allow templates through)
70
- TEMPLATE_MARKERS=(
71
- "[Story Title]"
72
- "[user type]"
73
- "[goal]"
74
- "[benefit]"
75
- "TEMPLATE FILE"
76
- "{{RESOLVED_PROJECT}}"
77
- )
78
-
79
- for marker in "${TEMPLATE_MARKERS[@]}"; do
80
- if [[ "$CONTENT" == *"$marker"* ]]; then
81
- # Template creation - allow
82
- echo '{"decision":"allow"}'
83
- exit 0
84
- fi
85
- done
86
-
87
- # Check interview state file
88
- STATE_DIR="${PROJECT_ROOT}.specweave/state"
89
- INTERVIEW_STATE="${STATE_DIR}/interview-${INCREMENT_ID}.json"
90
-
91
- if [[ ! -f "$INTERVIEW_STATE" ]]; then
92
- # No interview state - BLOCK
93
- REASON="⛔ **STRICT INTERVIEW ENFORCEMENT: Interview Required**
94
-
95
- You're attempting to write to spec.md but **Deep Interview has not been conducted**.
96
-
97
- **Strict Interview Mode is enabled** for this project.
98
-
99
- Before creating spec.md, you MUST:
100
-
101
- 1. **Start the interview**:
102
- \`\`\`
103
- Mark interview started for increment ${INCREMENT_ID}
104
- \`\`\`
105
-
106
- 2. **Cover all 6 categories** (ask thorough questions):
107
- - [ ] Architecture - system design, components, data flow
108
- - [ ] Integrations - external APIs, databases, auth providers
109
- - [ ] UI/UX - user flows, error handling, accessibility
110
- - [ ] Performance - load expectations, caching, response times
111
- - [ ] Security - auth, authorization, data protection
112
- - [ ] Edge Cases - failures, concurrency, rollback
113
-
114
- 3. **Mark each category as covered**:
115
- \`\`\`
116
- Mark architecture covered for ${INCREMENT_ID}: [summary of decisions]
117
- \`\`\`
118
-
119
- 4. **Then complete the spec** - this guard will allow it.
120
-
121
- **Why This Matters:**
122
- Thorough requirements gathering prevents rework. Strict mode ensures all bases are covered before implementation begins.
123
-
124
- **To disable strict mode** (not recommended):
125
- Set \`planning.deepInterview.enforcement: \"advisory\"\` in config.json"
126
-
127
- REASON_ESCAPED=$(echo "$REASON" | jq -Rs .)
128
- echo "{\"decision\":\"block\",\"reason\":${REASON_ESCAPED}}"
129
- exit 0
130
- fi
131
-
132
- # Interview state exists - check if all categories are covered
133
- COVERED_CATEGORIES=$(jq -r '.coveredCategories // {} | keys[]' "$INTERVIEW_STATE" 2>/dev/null || echo "")
134
-
135
- # Find missing categories
136
- MISSING=""
137
- for cat in $REQUIRED_CATEGORIES; do
138
- if ! echo "$COVERED_CATEGORIES" | grep -qx "$cat"; then
139
- MISSING="$MISSING\n - [ ] $cat"
140
- fi
141
- done
142
-
143
- if [[ -n "$MISSING" ]]; then
144
- # Some categories not covered - BLOCK
145
- REASON="⛔ **STRICT INTERVIEW ENFORCEMENT: Incomplete Interview**
146
-
147
- Interview started but **not all categories have been covered**.
148
-
149
- **Missing Categories:**
150
- $MISSING
151
-
152
- **Covered Categories:**
153
- $(jq -r '.coveredCategories // {} | to_entries[] | \" - [x] \\(.key): \\(.value.summary // \"covered\")\"' "$INTERVIEW_STATE" 2>/dev/null || echo " (none)")
154
-
155
- **To Continue:**
156
- Ask questions about the missing categories, then mark each as covered:
157
- \`\`\`
158
- Mark [category] covered for ${INCREMENT_ID}: [summary of what was decided]
159
- \`\`\`
160
-
161
- **Why This Matters:**
162
- Strict Interview Mode ensures comprehensive requirements gathering. Skipping categories leads to rework and missed requirements."
163
-
164
- REASON_ESCAPED=$(echo "$REASON" | jq -Rs .)
165
- echo "{\"decision\":\"block\",\"reason\":${REASON_ESCAPED}}"
166
- exit 0
167
- fi
168
-
169
- # All categories covered - ALLOW
170
- echo '{"decision":"allow"}'
171
- exit 0
@@ -1,14 +0,0 @@
1
- #!/bin/bash
2
- # metadata-json-guard.sh - DISABLED (v1.0.38)
3
- #
4
- # This guard was converted to WARNING-only in v1.0.37, and now completely
5
- # disabled in v1.0.38 per user feedback: "you MUST NEVER block such operations"
6
- #
7
- # Metadata validation should be handled by agents/scripts with proper business logic,
8
- # not by hooks that can interfere with file operations.
9
- #
10
- # This guard now does NOTHING - just allows all operations.
11
-
12
- set +e
13
- echo '{"decision":"allow"}'
14
- exit 0
@@ -1,222 +0,0 @@
1
- #!/bin/bash
2
- # DEPRECATED: v1.0.352 — No longer referenced by /sw:increment SKILL.md
3
- # The increment skill now uses Agent() delegation (sw-pm, sw-architect, sw-planner agents)
4
- # instead of Skill() chains with marker-based enforcement.
5
- # This guard remains on disk for backward compatibility with older cached plugin versions.
6
- # It can be safely removed in a future version.
7
- #
8
- # --- Original documentation below ---
9
- #
10
- # skill-chain-enforcement-guard.sh - Enforces skill delegation in /sw:increment
11
- #
12
- # PURPOSE:
13
- # The /sw:increment skill MUST delegate to sub-skills (PM, Architect, Test-Aware-Planner)
14
- # for creating spec.md, plan.md, and tasks.md. Analytics show the LLM writes these files
15
- # inline 97% of the time instead of invoking the specialized skills via Skill() calls.
16
- #
17
- # This guard BLOCKS direct writes to spec.md, plan.md, and tasks.md from the increment
18
- # skill unless the corresponding sub-skill has registered its invocation marker.
19
- #
20
- # WORKFLOW ENFORCED:
21
- # 1. /sw:increment creates folder + metadata.json (ALLOWED)
22
- # 2. /sw:increment MUST invoke Skill("sw:pm") for spec.md
23
- # 3. /sw:increment MUST invoke Skill("sw:architect") for plan.md
24
- # 4. /sw:increment MUST delegate to sw-planner agent for tasks.md
25
- # 5. Each sub-skill writes a marker to .specweave/state/skill-chain-{increment-id}.json
26
- # 6. This guard checks for that marker before allowing the write
27
- #
28
- # DETECTION LOGIC:
29
- # - ALLOW: metadata.json writes (always)
30
- # - ALLOW: File has skill invocation marker in state file
31
- # - ALLOW: File is a template (has template markers)
32
- # - ALLOW: Config has skillChainEnforcement disabled
33
- # - BLOCK: Direct spec.md/plan.md/tasks.md writes without skill marker
34
- #
35
- # @since 1.0.314
36
-
37
- set -e
38
-
39
- # Read hook input
40
- INPUT=$(cat)
41
-
42
- # Extract file path and tool from input
43
- TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // .toolName // ""')
44
- FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .toolInput.file_path // ""')
45
- CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // .toolInput.content // ""')
46
-
47
- # Only check Write and Edit operations
48
- if [[ "$TOOL_NAME" != "Write" ]] && [[ "$TOOL_NAME" != "Edit" ]]; then
49
- echo '{"decision":"allow"}'
50
- exit 0
51
- fi
52
-
53
- # Check if this targets an increment folder
54
- if [[ ! "$FILE_PATH" =~ \.specweave/increments/[0-9]{4}-[^/]+/ ]]; then
55
- echo '{"decision":"allow"}'
56
- exit 0
57
- fi
58
-
59
- # Extract the filename
60
- FILENAME=$(basename "$FILE_PATH")
61
-
62
- # Only guard spec.md, plan.md, and tasks.md
63
- case "$FILENAME" in
64
- spec.md|plan.md|tasks.md) ;;
65
- *)
66
- echo '{"decision":"allow"}'
67
- exit 0
68
- ;;
69
- esac
70
-
71
- # Extract increment ID from path
72
- INCREMENT_ID=$(echo "$FILE_PATH" | grep -oE '[0-9]{4}-[^/]+' | head -1)
73
-
74
- # Find project root (where .specweave/ is)
75
- PROJECT_ROOT=$(echo "$FILE_PATH" | sed 's|/.specweave/.*|/|')
76
- CONFIG_PATH="${PROJECT_ROOT}.specweave/config.json"
77
-
78
- # Check if skill chain enforcement is enabled (default: strict)
79
- ENFORCEMENT="strict"
80
- if [[ -f "$CONFIG_PATH" ]]; then
81
- ENFORCEMENT=$(jq -r '.planning.skillChainEnforcement // "strict"' "$CONFIG_PATH" 2>/dev/null)
82
- if [[ "$ENFORCEMENT" == "off" ]] || [[ "$ENFORCEMENT" == "disabled" ]]; then
83
- echo '{"decision":"allow"}'
84
- exit 0
85
- fi
86
- fi
87
-
88
- # Template markers — allow template creation through
89
- TEMPLATE_MARKERS=(
90
- "[Story Title]"
91
- "[user type]"
92
- "[goal]"
93
- "[benefit]"
94
- "[Specific, testable criterion]"
95
- "{{RESOLVED_PROJECT}}"
96
- "TEMPLATE FILE"
97
- )
98
-
99
- # Check if content has template markers (template creation is ALLOWED)
100
- for marker in "${TEMPLATE_MARKERS[@]}"; do
101
- if [[ "$CONTENT" == *"$marker"* ]]; then
102
- echo '{"decision":"allow"}'
103
- exit 0
104
- fi
105
- done
106
-
107
- # For Edit operations, allow small edits (status updates, checkbox toggles)
108
- # These are operational updates, not full file creation
109
- if [[ "$TOOL_NAME" == "Edit" ]]; then
110
- OLD_STRING=$(echo "$INPUT" | jq -r '.tool_input.old_string // .toolInput.old_string // ""')
111
- NEW_STRING=$(echo "$INPUT" | jq -r '.tool_input.new_string // .toolInput.new_string // ""')
112
- OLD_LEN=${#OLD_STRING}
113
- NEW_LEN=${#NEW_STRING}
114
-
115
- # Allow small edits (status toggles, checkbox changes, minor corrections)
116
- # Threshold: edits where both old and new are under 500 chars are likely operational
117
- if [[ $OLD_LEN -lt 500 ]] && [[ $NEW_LEN -lt 500 ]]; then
118
- echo '{"decision":"allow"}'
119
- exit 0
120
- fi
121
- fi
122
-
123
- # Determine which skill should have been invoked
124
- case "$FILENAME" in
125
- spec.md)
126
- REQUIRED_SKILL="sw:pm"
127
- SKILL_LABEL="PM (Product Manager)"
128
- STATE_KEY="pm_invoked"
129
- ;;
130
- plan.md)
131
- REQUIRED_SKILL="sw:architect"
132
- SKILL_LABEL="Architect"
133
- STATE_KEY="architect_invoked"
134
- ;;
135
- tasks.md)
136
- REQUIRED_SKILL="sw-planner"
137
- SKILL_LABEL="Planner"
138
- STATE_KEY="planner_invoked"
139
- ;;
140
- esac
141
-
142
- # Check for skill invocation marker
143
- STATE_DIR="${PROJECT_ROOT}.specweave/state"
144
- STATE_FILE="${STATE_DIR}/skill-chain-${INCREMENT_ID}.json"
145
-
146
- if [[ -f "$STATE_FILE" ]]; then
147
- INVOKED=$(jq -r ".${STATE_KEY} // false" "$STATE_FILE" 2>/dev/null)
148
- if [[ "$INVOKED" == "true" ]]; then
149
- echo '{"decision":"allow"}'
150
- exit 0
151
- fi
152
- fi
153
-
154
- # Check if the file already exists with content (this is an update, not creation)
155
- # Allow updates to existing files that already have substantive content
156
- if [[ -f "$FILE_PATH" ]]; then
157
- EXISTING_SIZE=$(wc -c < "$FILE_PATH" 2>/dev/null || echo "0")
158
- # If existing file has real content (>200 bytes, not just a template), allow edits
159
- if [[ "$EXISTING_SIZE" -gt 200 ]]; then
160
- # But check if this is the first substantive write to a template file
161
- EXISTING_CONTENT=$(head -5 "$FILE_PATH" 2>/dev/null || echo "")
162
- HAS_TEMPLATE=false
163
- for marker in "${TEMPLATE_MARKERS[@]}"; do
164
- if [[ "$EXISTING_CONTENT" == *"$marker"* ]]; then
165
- HAS_TEMPLATE=true
166
- break
167
- fi
168
- done
169
- # If existing file is NOT a template, allow updates (sub-skill already wrote it)
170
- if [[ "$HAS_TEMPLATE" == "false" ]]; then
171
- echo '{"decision":"allow"}'
172
- exit 0
173
- fi
174
- fi
175
- fi
176
-
177
- # BLOCK: No skill invocation marker found
178
- if [[ "$ENFORCEMENT" == "warn" ]]; then
179
- # Warn mode: allow but show warning
180
- REASON="**SKILL CHAIN WARNING**: You are writing ${FILENAME} directly without invoking the ${SKILL_LABEL} skill.
181
-
182
- Best practice: Use \`Skill({ skill: \"${REQUIRED_SKILL}\", args: \"... for increment ${INCREMENT_ID}\" })\`
183
-
184
- To suppress: Set \`planning.skillChainEnforcement: \"off\"\` in config.json"
185
-
186
- REASON_ESCAPED=$(echo "$REASON" | jq -Rs .)
187
- echo "{\"decision\":\"allow\",\"reason\":${REASON_ESCAPED}}"
188
- exit 0
189
- fi
190
-
191
- # Strict mode: BLOCK
192
- REASON="SKILL CHAIN ENFORCEMENT: Delegation Required
193
-
194
- You are attempting to write ${FILENAME} directly. The /sw:increment skill MUST delegate
195
- to specialized sub-skills instead of writing increment files inline.
196
-
197
- REQUIRED ACTION for ${FILENAME}:
198
- Invoke: Skill({ skill: \"${REQUIRED_SKILL}\", args: \"... for increment ${INCREMENT_ID}\" })
199
-
200
- The ${SKILL_LABEL} skill will:
201
- 1. Register its invocation marker (this unblocks the guard)
202
- 2. Apply specialized expertise (research, architecture, test planning)
203
- 3. Write ${FILENAME} with proper structure and coverage
204
-
205
- SKILL CHAIN (all 3 MUST be invoked):
206
- spec.md --> Skill({ skill: \"sw:pm\", args: \"...\" })
207
- plan.md --> Skill({ skill: \"sw:architect\", args: \"...\" })
208
- tasks.md --> Agent({ subagent_type: \"sw:sw-planner\", ... })
209
-
210
- Each skill writes its marker to:
211
- ${STATE_DIR}/skill-chain-${INCREMENT_ID}.json
212
-
213
- WHY THIS MATTERS:
214
- Analytics show 82 increment invocations but only 6 PM, 1 Architect, 1 TAP calls.
215
- Inlining bypasses specialized expertise and produces lower-quality specs.
216
-
217
- TO DISABLE (not recommended):
218
- Set planning.skillChainEnforcement: \"off\" in .specweave/config.json"
219
-
220
- REASON_ESCAPED=$(echo "$REASON" | jq -Rs .)
221
- echo "{\"decision\":\"block\",\"reason\":${REASON_ESCAPED}}"
222
- exit 0
@@ -1,21 +0,0 @@
1
- #!/bin/bash
2
- # spec-template-enforcement-guard.sh - DISABLED (v1.0.38)
3
- #
4
- # This guard was disabled in v1.0.38 per user feedback and error dashboard
5
- # analysis showing 322+ false positive tool_failure errors across 92 sessions.
6
- #
7
- # The guard blocked legitimate spec.md writes when /sw:increment creates
8
- # spec.md in a single pass (no template intermediate step).
9
- #
10
- # Sibling guards (spec-validation-guard.sh, increment-duplicate-guard.sh)
11
- # were already disabled for the same reason.
12
- #
13
- # Spec template workflow should be encouraged via documentation and skill
14
- # defaults, not enforced by hooks that block file operations.
15
- #
16
- # @since 1.0.167
17
- # @disabled 1.0.38
18
-
19
- set +e
20
- echo '{"decision":"allow"}'
21
- exit 0
@@ -1,14 +0,0 @@
1
- #!/bin/bash
2
- # spec-validation-guard.sh - DISABLED (v1.0.38)
3
- #
4
- # This guard was converted to WARNING-only in v1.0.37, and now completely
5
- # disabled in v1.0.38 per user feedback: "you MUST NEVER block such operations"
6
- #
7
- # Spec validation should be handled by agents/scripts with proper business logic,
8
- # not by hooks that can interfere with file operations.
9
- #
10
- # This guard now does NOTHING - just allows all operations.
11
-
12
- set +e
13
- echo '{"decision":"allow"}'
14
- exit 0
@@ -1,84 +0,0 @@
1
- #!/bin/bash
2
- # status-completion-guard.sh - Prevents direct status changes to "completed"
3
- #
4
- # RULE: Increment status should NEVER be changed to "completed" directly!
5
- #
6
- # ALLOWED paths to completion:
7
- # 1. /sw:done command (validates ACs, tests, docs)
8
- # 2. /sw:auto mode when all tests pass (auto-verified closure)
9
- #
10
- # @since 1.0.196
11
- # @see CLAUDE.md "Status Workflow" section
12
-
13
- set +e # CRITICAL: Never exit on error - consistent with non-blocking hook principle
14
-
15
- INPUT=$(cat)
16
-
17
- # Extract tool parameters
18
- TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // .toolName // ""')
19
- FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
20
- OLD_STRING=$(echo "$INPUT" | jq -r '.tool_input.old_string // ""')
21
- NEW_STRING=$(echo "$INPUT" | jq -r '.tool_input.new_string // ""')
22
-
23
- # Only check Edit operations on metadata.json files
24
- if [[ "$TOOL_NAME" != "Edit" ]]; then
25
- echo '{"decision":"allow"}'
26
- exit 0
27
- fi
28
-
29
- # Only check metadata.json files in increments
30
- if [[ ! "$FILE_PATH" =~ \.specweave/increments/.*/metadata\.json$ ]]; then
31
- echo '{"decision":"allow"}'
32
- exit 0
33
- fi
34
-
35
- # Check if this is a status change to "completed"
36
- # Pattern: "status": "active" -> "status": "completed"
37
- # Or: "status": "paused" -> "status": "completed"
38
- # Or: "status": "ready_for_review" -> "status": "completed"
39
- if echo "$NEW_STRING" | grep -qE '"status":\s*"completed"'; then
40
- # Detect project root via walk-up
41
- _DIR="$PWD"
42
- _LIMIT=0
43
- while [[ "$_DIR" != "/" ]] && [[ ! -f "$_DIR/.specweave/config.json" ]] && [[ $_LIMIT -lt 50 ]]; do
44
- _DIR=$(dirname "$_DIR")
45
- _LIMIT=$((_LIMIT + 1))
46
- done
47
- _ROOT="$_DIR"
48
-
49
- # Check if auto-mode is active with verified completion
50
- AUTO_STATE_FILE="$_ROOT/.specweave/state/auto/session.json"
51
- if [[ -f "$AUTO_STATE_FILE" ]]; then
52
- AUTO_STATUS=$(jq -r '.status // "unknown"' "$AUTO_STATE_FILE" 2>/dev/null || echo "unknown")
53
- AUTO_VERIFIED=$(jq -r '.testsVerified // false' "$AUTO_STATE_FILE" 2>/dev/null || echo "false")
54
-
55
- # Allow if auto-mode is active AND tests are verified
56
- if [[ "$AUTO_STATUS" == "active" && "$AUTO_VERIFIED" == "true" ]]; then
57
- echo '{"decision":"allow"}'
58
- exit 0
59
- fi
60
- fi
61
-
62
- # Check if called from /sw:done command (look for marker file)
63
- DONE_MARKER="$_ROOT/.specweave/state/.sw-done-in-progress"
64
- if [[ -f "$DONE_MARKER" ]]; then
65
- echo '{"decision":"allow"}'
66
- exit 0
67
- fi
68
-
69
- # Extract increment ID for the message
70
- INCREMENT_ID=$(echo "$FILE_PATH" | grep -oE '[0-9]{4}[E]?-[^/]+' || echo "unknown")
71
-
72
- # Block the direct status change
73
- cat << EOF
74
- {
75
- "decision": "block",
76
- "reason": "Direct status change to 'completed' is blocked",
77
- "systemMessage": "⛔ **STATUS PROTECTION ACTIVE**\\n\\n❌ Cannot directly edit metadata.json to set status='completed'\\n\\n**Why?** Completion requires validation:\\n- All tasks marked complete\\n- Acceptance criteria satisfied\\n- Tests passing\\n- Documentation updated\\n\\n**Correct approach:**\\n\`\`\`\\n/sw:done ${INCREMENT_ID}\\n\`\`\`\\n\\nOr in auto-mode:\\n\`\`\`\\n/sw:auto ${INCREMENT_ID}\\n\`\`\`\\n(auto-closes when all tests pass)"
78
- }
79
- EOF
80
- exit 0
81
- fi
82
-
83
- echo '{"decision":"allow"}'
84
- exit 0