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
@@ -0,0 +1,318 @@
1
+ /**
2
+ * PreToolUse hook handler — inlines all guard logic:
3
+ * 1. Status Completion Guard (Edit metadata.json → "completed")
4
+ * 2. Interview Enforcement Guard (Write spec.md with strict interview)
5
+ * 3. Increment Existence Guard (TeamCreate without valid spec)
6
+ *
7
+ * @module core/hooks/handlers/pre-tool-use
8
+ */
9
+ import * as fs from 'fs';
10
+ import * as path from 'path';
11
+ const ALLOW = { decision: 'allow' };
12
+ const TEMPLATE_MARKERS = [
13
+ '[Story Title]',
14
+ '[user type]',
15
+ '[goal]',
16
+ '[benefit]',
17
+ '[Specific, testable criterion]',
18
+ '[Component 1]',
19
+ '[High-level description',
20
+ '{{RESOLVED_PROJECT}}',
21
+ 'TEMPLATE FILE',
22
+ ];
23
+ const DEFAULT_INTERVIEW_CATEGORIES = [
24
+ 'architecture',
25
+ 'integrations',
26
+ 'ui-ux',
27
+ 'performance',
28
+ 'security',
29
+ 'edge-cases',
30
+ ];
31
+ const NON_IMPL_PREFIXES = [
32
+ 'review-',
33
+ 'brainstorm-',
34
+ 'analysis-',
35
+ 'audit-',
36
+ 'explore-',
37
+ 'ideate-',
38
+ 'research-',
39
+ 'plan-',
40
+ ];
41
+ const NON_IMPL_KEYWORDS = [
42
+ 'review',
43
+ 'brainstorm',
44
+ 'analyze',
45
+ 'audit',
46
+ 'explore',
47
+ 'ideate',
48
+ 'pull request',
49
+ 'pr #',
50
+ 'pr review',
51
+ 'code review',
52
+ 'architecture review',
53
+ 'security audit',
54
+ 'performance audit',
55
+ 'code audit',
56
+ 'ideation',
57
+ 'exploration',
58
+ 'research',
59
+ 'planning',
60
+ 'perspectives',
61
+ "devil's advocate",
62
+ 'pros and cons',
63
+ ];
64
+ function getToolName(input) {
65
+ return (input.tool_name ?? input.toolName ?? '');
66
+ }
67
+ function getToolInput(input) {
68
+ return (input.tool_input ?? input.toolInput ?? {});
69
+ }
70
+ function getFilePath(input) {
71
+ const ti = getToolInput(input);
72
+ return (ti.file_path ?? '');
73
+ }
74
+ function isIncrementFile(filePath) {
75
+ return filePath.includes('.specweave/increments/');
76
+ }
77
+ function extractIncrementId(filePath) {
78
+ const match = filePath.match(/(\d{4}[E]?-[^/]+)/);
79
+ return match ? match[1] : 'unknown';
80
+ }
81
+ function readJsonSafe(filePath) {
82
+ try {
83
+ if (!fs.existsSync(filePath))
84
+ return {};
85
+ return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
86
+ }
87
+ catch {
88
+ return {};
89
+ }
90
+ }
91
+ // ---------------------------------------------------------------------------
92
+ // Guard: Status Completion (Edit metadata.json → "completed")
93
+ // ---------------------------------------------------------------------------
94
+ function checkStatusCompletionGuard(input, context) {
95
+ const ti = getToolInput(input);
96
+ const filePath = getFilePath(input);
97
+ const newString = (ti.new_string ?? '');
98
+ // Only care about metadata.json in increments
99
+ if (!filePath.match(/\.specweave\/increments\/.*\/metadata\.json$/)) {
100
+ return ALLOW;
101
+ }
102
+ // Check if setting status to "completed"
103
+ if (!/"status"\s*:\s*"completed"/.test(newString)) {
104
+ return ALLOW;
105
+ }
106
+ // Allow if sw-done marker exists
107
+ const doneMarker = path.join(context.stateDir, '.sw-done-in-progress');
108
+ if (fs.existsSync(doneMarker)) {
109
+ return ALLOW;
110
+ }
111
+ // Allow if auto-mode active with testsVerified
112
+ const autoSession = path.join(context.stateDir, 'auto', 'session.json');
113
+ if (fs.existsSync(autoSession)) {
114
+ const session = readJsonSafe(autoSession);
115
+ if (session.status === 'active' && session.testsVerified === true) {
116
+ return ALLOW;
117
+ }
118
+ }
119
+ const incrementId = extractIncrementId(filePath);
120
+ return {
121
+ decision: 'block',
122
+ reason: `Direct status change to 'completed' is blocked for ${incrementId}. Use /sw:done or /sw:auto instead.`,
123
+ };
124
+ }
125
+ // ---------------------------------------------------------------------------
126
+ // Guard: Interview Enforcement (Write spec.md with strict interview)
127
+ // ---------------------------------------------------------------------------
128
+ function checkInterviewGuard(input, context) {
129
+ const filePath = getFilePath(input);
130
+ const ti = getToolInput(input);
131
+ const content = (ti.content ?? '');
132
+ // Only care about spec.md in increments
133
+ if (!filePath.match(/\.specweave\/increments\/\d{4}-[^/]+\/spec\.md$/)) {
134
+ return ALLOW;
135
+ }
136
+ // Allow template writes through
137
+ for (const marker of TEMPLATE_MARKERS) {
138
+ if (content.includes(marker)) {
139
+ return ALLOW;
140
+ }
141
+ }
142
+ // Read config to check if strict interview enabled
143
+ const config = readJsonSafe(context.configPath);
144
+ const planning = (config.planning ?? {});
145
+ const di = (planning.deepInterview ?? {});
146
+ if (di.enabled !== true || di.enforcement !== 'strict') {
147
+ return ALLOW;
148
+ }
149
+ const incrementId = extractIncrementId(filePath);
150
+ const categories = di.categories ?? DEFAULT_INTERVIEW_CATEGORIES;
151
+ // Check interview state file
152
+ const interviewState = path.join(context.stateDir, `interview-${incrementId}.json`);
153
+ if (!fs.existsSync(interviewState)) {
154
+ return {
155
+ decision: 'block',
156
+ reason: `Strict Interview Enforcement: Interview Required. Deep Interview has not been started for ${incrementId}. Start and cover all categories before writing spec.md.`,
157
+ };
158
+ }
159
+ // Check covered categories
160
+ const state = readJsonSafe(interviewState);
161
+ const covered = state.coveredCategories;
162
+ const coveredKeys = covered ? Object.keys(covered) : [];
163
+ const missing = categories.filter((c) => !coveredKeys.includes(c));
164
+ if (missing.length > 0) {
165
+ return {
166
+ decision: 'block',
167
+ reason: `Strict Interview Enforcement: Incomplete Interview for ${incrementId}. Missing categories: ${missing.join(', ')}`,
168
+ };
169
+ }
170
+ return ALLOW;
171
+ }
172
+ // ---------------------------------------------------------------------------
173
+ // Guard: Increment Existence (TeamCreate without valid spec)
174
+ // ---------------------------------------------------------------------------
175
+ function isNonImplTeam(input) {
176
+ const ti = getToolInput(input);
177
+ const teamName = (ti.team_name ?? '').toLowerCase();
178
+ const description = (ti.description ?? '').toLowerCase();
179
+ // Check team name prefix
180
+ for (const prefix of NON_IMPL_PREFIXES) {
181
+ if (teamName.startsWith(prefix))
182
+ return true;
183
+ }
184
+ // Check description keywords
185
+ for (const keyword of NON_IMPL_KEYWORDS) {
186
+ if (description.includes(keyword))
187
+ return true;
188
+ }
189
+ return false;
190
+ }
191
+ function hasValidSpec(specPath) {
192
+ try {
193
+ if (!fs.existsSync(specPath))
194
+ return false;
195
+ const content = fs.readFileSync(specPath, 'utf-8');
196
+ // Min 500 bytes
197
+ if (Buffer.byteLength(content) <= 500)
198
+ return false;
199
+ // No template markers
200
+ for (const marker of TEMPLATE_MARKERS) {
201
+ if (content.includes(marker))
202
+ return false;
203
+ }
204
+ // No {{UPPERCASE}} mustache placeholders
205
+ if (/\{\{[A-Z_]+\}\}/.test(content))
206
+ return false;
207
+ // Must have at least one acceptance criterion
208
+ if (!/AC-US\d+-\d+|AC-\d+/.test(content))
209
+ return false;
210
+ return true;
211
+ }
212
+ catch {
213
+ return false;
214
+ }
215
+ }
216
+ function checkIncrementExistenceGuard(_input, context) {
217
+ // Env var bypass
218
+ if (process.env.SPECWEAVE_NO_INCREMENT === '1') {
219
+ return ALLOW;
220
+ }
221
+ // Scan increments for valid specs with active/in-progress status
222
+ const incDir = path.join(context.projectRoot, '.specweave', 'increments');
223
+ if (fs.existsSync(incDir)) {
224
+ try {
225
+ const entries = fs.readdirSync(incDir, { withFileTypes: true });
226
+ for (const entry of entries) {
227
+ if (entry.isDirectory()) {
228
+ const specPath = path.join(incDir, entry.name, 'spec.md');
229
+ if (!hasValidSpec(specPath))
230
+ continue;
231
+ // Check metadata.json for qualifying status
232
+ const metaPath = path.join(incDir, entry.name, 'metadata.json');
233
+ if (fs.existsSync(metaPath)) {
234
+ try {
235
+ const meta = JSON.parse(fs.readFileSync(metaPath, 'utf8'));
236
+ const status = meta?.status ?? '';
237
+ const qualifying = ['active', 'in-progress', 'ready_for_review', 'planned'];
238
+ if (qualifying.includes(status))
239
+ return ALLOW;
240
+ }
241
+ catch {
242
+ // Unreadable metadata — skip this increment
243
+ }
244
+ }
245
+ else {
246
+ // No metadata.json but valid spec — allow (legacy increments)
247
+ return ALLOW;
248
+ }
249
+ }
250
+ }
251
+ }
252
+ catch {
253
+ // scan failure — don't block
254
+ }
255
+ }
256
+ // Scan multi-repo increments
257
+ const reposDir = path.join(context.projectRoot, 'repositories');
258
+ if (fs.existsSync(reposDir)) {
259
+ try {
260
+ const orgs = fs.readdirSync(reposDir, { withFileTypes: true });
261
+ for (const org of orgs) {
262
+ if (!org.isDirectory())
263
+ continue;
264
+ const orgPath = path.join(reposDir, org.name);
265
+ const repos = fs.readdirSync(orgPath, { withFileTypes: true });
266
+ for (const repo of repos) {
267
+ if (!repo.isDirectory())
268
+ continue;
269
+ const repoIncDir = path.join(orgPath, repo.name, '.specweave', 'increments');
270
+ if (!fs.existsSync(repoIncDir))
271
+ continue;
272
+ const incs = fs.readdirSync(repoIncDir, { withFileTypes: true });
273
+ for (const inc of incs) {
274
+ if (inc.isDirectory()) {
275
+ const specPath = path.join(repoIncDir, inc.name, 'spec.md');
276
+ if (hasValidSpec(specPath))
277
+ return ALLOW;
278
+ }
279
+ }
280
+ }
281
+ }
282
+ }
283
+ catch {
284
+ // scan failure — don't block
285
+ }
286
+ }
287
+ return {
288
+ decision: 'block',
289
+ reason: 'Increment Required Before Team Creation. No qualifying increment with a valid spec.md found. Run /sw:increment first, or use a mode-prefixed team name (review-*, brainstorm-*, analysis-*, research-*) for non-implementation work.',
290
+ };
291
+ }
292
+ // ---------------------------------------------------------------------------
293
+ // Main handler
294
+ // ---------------------------------------------------------------------------
295
+ export const handle = async (input, context) => {
296
+ const toolName = getToolName(input);
297
+ const filePath = getFilePath(input);
298
+ // Fast path: not targeting increment files AND not TeamCreate
299
+ if (!isIncrementFile(filePath) && toolName !== 'TeamCreate') {
300
+ return ALLOW;
301
+ }
302
+ // Edit guard: status completion
303
+ if (toolName === 'Edit') {
304
+ return checkStatusCompletionGuard(input, context);
305
+ }
306
+ // Write guard: interview enforcement
307
+ if (toolName === 'Write') {
308
+ return checkInterviewGuard(input, context);
309
+ }
310
+ // TeamCreate guard: increment existence
311
+ if (toolName === 'TeamCreate') {
312
+ if (isNonImplTeam(input))
313
+ return ALLOW;
314
+ return checkIncrementExistenceGuard(input, context);
315
+ }
316
+ return ALLOW;
317
+ };
318
+ //# sourceMappingURL=pre-tool-use.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pre-tool-use.js","sourceRoot":"","sources":["../../../../../src/core/hooks/handlers/pre-tool-use.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Session-start hook handler — session initialization.
3
+ *
4
+ * Clears stale auto-mode files, resets context pressure,
5
+ * and performs baseline prompt health check.
6
+ */
7
+ import type { HandlerFn } from './types.js';
8
+ export declare const handle: HandlerFn;
9
+ //# sourceMappingURL=session-start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-start.d.ts","sourceRoot":"","sources":["../../../../../src/core/hooks/handlers/session-start.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAkC5C,eAAO,MAAM,MAAM,EAAE,SA6EpB,CAAC"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Session-start hook handler — session initialization.
3
+ *
4
+ * Clears stale auto-mode files, resets context pressure,
5
+ * and performs baseline prompt health check.
6
+ */
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+ const STALE_THRESHOLD_MS = 24 * 60 * 60 * 1000; // 24 hours
10
+ const WARNING_THRESHOLD = 80000;
11
+ const CRITICAL_THRESHOLD = 120000;
12
+ const SYSTEM_ESTIMATE = 12000;
13
+ const SKILL_BUDGET = 15000;
14
+ const HOOK_PER_TURN = 3000;
15
+ function isStale(filePath) {
16
+ try {
17
+ const stat = fs.statSync(filePath);
18
+ return Date.now() - stat.mtimeMs > STALE_THRESHOLD_MS;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ function safeRemove(filePath) {
25
+ try {
26
+ fs.unlinkSync(filePath);
27
+ }
28
+ catch {
29
+ // Ignore
30
+ }
31
+ }
32
+ function fileSize(filePath) {
33
+ try {
34
+ return fs.statSync(filePath).size;
35
+ }
36
+ catch {
37
+ return 0;
38
+ }
39
+ }
40
+ export const handle = async (_input, context) => {
41
+ const { projectRoot, stateDir, logsDir, timestamp } = context;
42
+ try {
43
+ fs.mkdirSync(stateDir, { recursive: true });
44
+ }
45
+ catch {
46
+ return { continue: true };
47
+ }
48
+ // --- Auto-mode cleanup: remove stale session files (>24h) ---
49
+ const autoFile = path.join(stateDir, 'auto-mode.json');
50
+ if (fs.existsSync(autoFile) && isStale(autoFile)) {
51
+ safeRemove(autoFile);
52
+ safeRemove(path.join(stateDir, '.stop-auto-dedup'));
53
+ safeRemove(path.join(stateDir, '.stop-auto-dedup-prev'));
54
+ safeRemove(path.join(stateDir, '.stop-auto-turns'));
55
+ try {
56
+ fs.mkdirSync(logsDir, { recursive: true });
57
+ fs.appendFileSync(path.join(logsDir, 'session.log'), `[${timestamp}] SessionStart: Cleared stale auto-mode session files (>24h)\n`);
58
+ }
59
+ catch {
60
+ // Never throw from logging
61
+ }
62
+ }
63
+ // --- Context pressure reset ---
64
+ safeRemove(path.join(stateDir, 'context-pressure.json'));
65
+ safeRemove(path.join(stateDir, 'prompt-health-alert.json'));
66
+ // --- Baseline health check ---
67
+ try {
68
+ const claudeMdSize = fileSize(path.join(projectRoot, 'CLAUDE.md'));
69
+ const memoryDir = path.join(projectRoot, '.claude', 'projects');
70
+ let memoryMdSize = 0;
71
+ try {
72
+ // Find MEMORY.md in any project subdirectory
73
+ if (fs.existsSync(memoryDir)) {
74
+ const entries = fs.readdirSync(memoryDir, { withFileTypes: true });
75
+ for (const entry of entries) {
76
+ if (entry.isDirectory()) {
77
+ const memPath = path.join(memoryDir, entry.name, 'memory', 'MEMORY.md');
78
+ memoryMdSize += fileSize(memPath);
79
+ }
80
+ }
81
+ }
82
+ }
83
+ catch {
84
+ // Best-effort
85
+ }
86
+ const baseline = claudeMdSize + memoryMdSize + SYSTEM_ESTIMATE + SKILL_BUDGET + HOOK_PER_TURN;
87
+ let warningLevel = 'normal';
88
+ if (baseline > CRITICAL_THRESHOLD) {
89
+ warningLevel = 'critical';
90
+ }
91
+ else if (baseline > WARNING_THRESHOLD) {
92
+ warningLevel = 'warning';
93
+ }
94
+ const health = {
95
+ baseline,
96
+ claudeMdSize,
97
+ memoryMdSize,
98
+ skillBudget: SKILL_BUDGET,
99
+ systemEstimate: SYSTEM_ESTIMATE,
100
+ hookPerTurn: HOOK_PER_TURN,
101
+ warningLevel,
102
+ checkedAt: timestamp,
103
+ };
104
+ fs.writeFileSync(path.join(stateDir, 'prompt-health.json'), JSON.stringify(health));
105
+ }
106
+ catch {
107
+ // Health check is best-effort
108
+ }
109
+ return { continue: true };
110
+ };
111
+ //# sourceMappingURL=session-start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-start.js","sourceRoot":"","sources":["../../../../../src/core/hooks/handlers/session-start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Stop-auto hook handler.
3
+ *
4
+ * Fires when a session ends. Checks if an auto-mode session is active:
5
+ * 1. Look for auto-mode.json (per-session or global)
6
+ * 2. Check session staleness
7
+ * 3. Scan active increments for pending tasks
8
+ * 4. Include progress context but always approve
9
+ *
10
+ * Stop hooks should NEVER block session exit.
11
+ *
12
+ * @module core/hooks/handlers/stop-auto
13
+ */
14
+ import type { HandlerFn } from './types.js';
15
+ export declare const handle: HandlerFn;
16
+ //# sourceMappingURL=stop-auto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop-auto.d.ts","sourceRoot":"","sources":["../../../../../src/core/hooks/handlers/stop-auto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAwE5C,eAAO,MAAM,MAAM,EAAE,SAyCpB,CAAC"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Stop-auto hook handler.
3
+ *
4
+ * Fires when a session ends. Checks if an auto-mode session is active:
5
+ * 1. Look for auto-mode.json (per-session or global)
6
+ * 2. Check session staleness
7
+ * 3. Scan active increments for pending tasks
8
+ * 4. Include progress context but always approve
9
+ *
10
+ * Stop hooks should NEVER block session exit.
11
+ *
12
+ * @module core/hooks/handlers/stop-auto
13
+ */
14
+ import * as fs from 'fs';
15
+ import * as path from 'path';
16
+ import { logHook } from './utils.js';
17
+ /** Read JSON safely, return null on error */
18
+ function readJsonSafe(filePath) {
19
+ try {
20
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ /** Get auto-mode session file path (per-session or global fallback) */
27
+ function getSessionPath(stateDir) {
28
+ const sessionId = process.env.CLAUDE_SESSION_ID;
29
+ if (sessionId) {
30
+ const perSession = path.join(stateDir, 'sessions', sessionId, 'auto-mode.json');
31
+ if (fs.existsSync(perSession))
32
+ return perSession;
33
+ }
34
+ return path.join(stateDir, 'auto-mode.json');
35
+ }
36
+ /** Check if session file is stale (older than maxSessionAge seconds) */
37
+ function isSessionStale(sessionPath, maxSessionAge) {
38
+ try {
39
+ const stat = fs.statSync(sessionPath);
40
+ const ageMs = Date.now() - stat.mtimeMs;
41
+ return ageMs > maxSessionAge * 1000;
42
+ }
43
+ catch {
44
+ return true;
45
+ }
46
+ }
47
+ /** Count pending tasks across active increments */
48
+ function scanPendingTasks(projectRoot) {
49
+ const incDir = path.join(projectRoot, '.specweave', 'increments');
50
+ let pending = 0;
51
+ let completed = 0;
52
+ const incrementIds = [];
53
+ try {
54
+ if (!fs.existsSync(incDir))
55
+ return { pending, completed, incrementIds };
56
+ const dirs = fs.readdirSync(incDir);
57
+ for (const dir of dirs) {
58
+ const metaPath = path.join(incDir, dir, 'metadata.json');
59
+ if (!fs.existsSync(metaPath))
60
+ continue;
61
+ const meta = readJsonSafe(metaPath);
62
+ if (!meta || (meta.status !== 'active' && meta.status !== 'in-progress'))
63
+ continue;
64
+ const tasksPath = path.join(incDir, dir, 'tasks.md');
65
+ try {
66
+ const tasks = fs.readFileSync(tasksPath, 'utf8');
67
+ const p = (tasks.match(/\[ \]/g) || []).length;
68
+ const c = (tasks.match(/\[x\]/g) || []).length;
69
+ if (p > 0) {
70
+ pending += p;
71
+ completed += c;
72
+ incrementIds.push(dir);
73
+ }
74
+ }
75
+ catch {
76
+ // No tasks file
77
+ }
78
+ }
79
+ }
80
+ catch {
81
+ // fs errors
82
+ }
83
+ return { pending, completed, incrementIds };
84
+ }
85
+ export const handle = async (input, context) => {
86
+ try {
87
+ // 1. Find auto-mode session file
88
+ const sessionPath = getSessionPath(context.stateDir);
89
+ if (!fs.existsSync(sessionPath)) {
90
+ logHook(context, 'stop-auto', 'No auto session');
91
+ return { decision: 'approve' };
92
+ }
93
+ // 2. Read session data
94
+ const session = readJsonSafe(sessionPath);
95
+ if (!session || session.active !== true) {
96
+ logHook(context, 'stop-auto', 'Session not active');
97
+ return { decision: 'approve' };
98
+ }
99
+ // 3. Read config for maxSessionAge
100
+ const config = readJsonSafe(context.configPath);
101
+ const maxSessionAge = config?.auto?.maxSessionAge ?? 7200;
102
+ // 4. Check staleness
103
+ if (isSessionStale(sessionPath, maxSessionAge)) {
104
+ logHook(context, 'stop-auto', 'Stale session — expired');
105
+ return { decision: 'approve' };
106
+ }
107
+ // 5. Scan active increments for pending tasks
108
+ const { pending, completed, incrementIds } = scanPendingTasks(context.projectRoot);
109
+ if (pending === 0) {
110
+ logHook(context, 'stop-auto', 'All tasks complete');
111
+ return { decision: 'approve' };
112
+ }
113
+ // 6. Pending tasks exist — include progress context but still approve
114
+ logHook(context, 'stop-auto', `Pending tasks: ${pending} across ${incrementIds.length} increment(s)`);
115
+ return { decision: 'approve' };
116
+ }
117
+ catch {
118
+ // Never throw — always approve
119
+ return { decision: 'approve' };
120
+ }
121
+ };
122
+ //# sourceMappingURL=stop-auto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop-auto.js","sourceRoot":"","sources":["../../../../../src/core/hooks/handlers/stop-auto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Stop-reflect hook handler.
3
+ *
4
+ * Fires when a session ends. Checks if reflection is enabled in config.
5
+ * If enabled, logs that reflection was requested (actual reflection logic
6
+ * will call `specweave reflect-stop` CLI in a follow-up).
7
+ *
8
+ * NEVER blocks — always returns approve.
9
+ *
10
+ * @module core/hooks/handlers/stop-reflect
11
+ */
12
+ import type { HandlerFn } from './types.js';
13
+ export declare const handle: HandlerFn;
14
+ //# sourceMappingURL=stop-reflect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop-reflect.d.ts","sourceRoot":"","sources":["../../../../../src/core/hooks/handlers/stop-reflect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAe5C,eAAO,MAAM,MAAM,EAAE,SAgBpB,CAAC"}