specweave 0.33.3 → 0.33.4

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 (51) hide show
  1. package/CLAUDE.md +77 -19
  2. package/dist/src/cli/cleanup-zombies.js +8 -5
  3. package/dist/src/cli/cleanup-zombies.js.map +1 -1
  4. package/dist/src/config/types.d.ts +203 -1208
  5. package/dist/src/config/types.d.ts.map +1 -1
  6. package/dist/src/importers/jira-importer.d.ts +10 -0
  7. package/dist/src/importers/jira-importer.d.ts.map +1 -1
  8. package/dist/src/importers/jira-importer.js +55 -5
  9. package/dist/src/importers/jira-importer.js.map +1 -1
  10. package/dist/src/init/architecture/types.d.ts +33 -140
  11. package/dist/src/init/architecture/types.d.ts.map +1 -1
  12. package/dist/src/init/compliance/types.d.ts +30 -27
  13. package/dist/src/init/compliance/types.d.ts.map +1 -1
  14. package/dist/src/init/repo/types.d.ts +11 -34
  15. package/dist/src/init/repo/types.d.ts.map +1 -1
  16. package/dist/src/init/research/src/config/types.d.ts +15 -82
  17. package/dist/src/init/research/src/config/types.d.ts.map +1 -1
  18. package/dist/src/init/research/types.d.ts +38 -93
  19. package/dist/src/init/research/types.d.ts.map +1 -1
  20. package/dist/src/init/team/types.d.ts +4 -42
  21. package/dist/src/init/team/types.d.ts.map +1 -1
  22. package/dist/src/sync/closure-metrics.d.ts +102 -0
  23. package/dist/src/sync/closure-metrics.d.ts.map +1 -0
  24. package/dist/src/sync/closure-metrics.js +267 -0
  25. package/dist/src/sync/closure-metrics.js.map +1 -0
  26. package/dist/src/sync/sync-coordinator.d.ts +29 -0
  27. package/dist/src/sync/sync-coordinator.d.ts.map +1 -1
  28. package/dist/src/sync/sync-coordinator.js +153 -16
  29. package/dist/src/sync/sync-coordinator.js.map +1 -1
  30. package/dist/src/utils/notification-constants.d.ts +85 -0
  31. package/dist/src/utils/notification-constants.d.ts.map +1 -0
  32. package/dist/src/utils/notification-constants.js +129 -0
  33. package/dist/src/utils/notification-constants.js.map +1 -0
  34. package/dist/src/utils/platform-utils.d.ts +13 -3
  35. package/dist/src/utils/platform-utils.d.ts.map +1 -1
  36. package/dist/src/utils/platform-utils.js +17 -6
  37. package/dist/src/utils/platform-utils.js.map +1 -1
  38. package/package.json +1 -1
  39. package/plugins/specweave/commands/specweave-increment.md +46 -0
  40. package/plugins/specweave/commands/specweave-jobs.md +153 -8
  41. package/plugins/specweave/hooks/spec-project-validator.sh +24 -2
  42. package/plugins/specweave/hooks/universal/hook-wrapper.cmd +26 -26
  43. package/plugins/specweave/hooks/universal/session-start.cmd +16 -16
  44. package/plugins/specweave/hooks/universal/session-start.ps1 +16 -16
  45. package/plugins/specweave/scripts/session-watchdog.sh +278 -130
  46. package/plugins/specweave/skills/increment-planner/SKILL.md +48 -18
  47. package/plugins/specweave/skills/increment-planner/templates/spec-multi-project.md +27 -14
  48. package/plugins/specweave/skills/increment-planner/templates/spec-single-project.md +16 -5
  49. package/plugins/specweave/skills/spec-generator/SKILL.md +74 -15
  50. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +0 -738
  51. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -1107
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: specweave:jobs
3
3
  description: Show current work status (active increments, progress) and background jobs (imports, cloning). Even with no jobs, shows increment summary and helpful context.
4
- usage: /specweave:jobs [--all] [--id <job-id>] [--resume <job-id>] [--kill <job-id>] [--follow <job-id>] [--logs <job-id>]
4
+ usage: /specweave:jobs [--all] [--id <job-id>] [--resume <job-id>] [--kill <job-id>] [--follow <job-id>] [--logs <job-id>] [--diagnostics]
5
5
  ---
6
6
 
7
7
  # Background Jobs Monitor
@@ -17,6 +17,7 @@ Monitor and manage long-running background operations:
17
17
  - **Issue import** (10K+ items from GitHub/JIRA/ADO)
18
18
  - **External sync** operations
19
19
  - **Brownfield analysis** (codebase documentation gap detection)
20
+ - **Session health monitoring** (watchdog diagnostics)
20
21
 
21
22
  **ASYNC ARCHITECTURE (2025-12-01)**:
22
23
  - Jobs run as **detached processes** that survive terminal close
@@ -29,13 +30,14 @@ Monitor and manage long-running background operations:
29
30
 
30
31
  | Option | Description |
31
32
  |--------|-------------|
32
- | (none) | Show active jobs |
33
+ | (none) | Show active jobs + session health |
33
34
  | `--all` | Show all jobs (including completed) |
34
35
  | `--id <jobId>` | Show details for specific job |
35
36
  | `--follow <jobId>` | Follow job progress in real-time |
36
37
  | `--logs <jobId>` | Show worker log output |
37
38
  | `--resume <jobId>` | Resume paused job |
38
39
  | `--kill <jobId>` | Kill running background job |
40
+ | `--diagnostics` | Show detailed watchdog diagnostics |
39
41
 
40
42
  ---
41
43
 
@@ -57,7 +59,9 @@ STATE_FILE=".specweave/state/background-jobs.json"
57
59
  ### Display Format
58
60
 
59
61
  ```
60
- šŸ“‹ Background Jobs
62
+ šŸ“‹ Background Jobs & Session Health
63
+
64
+ 🩺 Session Health: āœ… healthy (last check: 30s ago)
61
65
 
62
66
  šŸ”„ Running (2):
63
67
  [abc12345] import-issues (ADO)
@@ -87,6 +91,7 @@ STATE_FILE=".specweave/state/background-jobs.json"
87
91
  /specweave:jobs --logs abc12345 → View worker logs
88
92
  /specweave:jobs --resume def67890 → Resume paused job
89
93
  /specweave:jobs --kill abc12345 → Kill running job
94
+ /specweave:jobs --diagnostics → Show watchdog diagnostics
90
95
  /specweave:jobs --all → Show all jobs (including old)
91
96
  ```
92
97
 
@@ -221,14 +226,57 @@ const result = await launchImportJob({
221
226
  ## Implementation
222
227
 
223
228
  1. Read `.specweave/state/background-jobs.json`
224
- 2. Parse job entries
225
- 3. Display formatted status
226
- 4. For --resume, update job status and continue operation
229
+ 2. Read `.specweave/state/.watchdog-diagnostics.json` for session health
230
+ 3. Parse job entries
231
+ 4. Display formatted status with health indicator
232
+ 5. For --resume, update job status and continue operation
233
+ 6. For --diagnostics, show detailed watchdog checks
227
234
 
228
- ### State File Location
235
+ ### State File Locations
229
236
 
230
237
  ```
231
- .specweave/state/background-jobs.json
238
+ .specweave/state/background-jobs.json - Job status and progress
239
+ .specweave/state/.watchdog-diagnostics.json - Session health checks
240
+ .specweave/state/jobs/<jobId>/config.json - Job configuration
241
+ .specweave/state/jobs/<jobId>/worker.pid - Worker process ID
242
+ .specweave/state/jobs/<jobId>/worker.log - Worker output log
243
+ .specweave/logs/watchdog.log - Watchdog history
244
+ ```
245
+
246
+ ### Reading Session Health
247
+
248
+ ```typescript
249
+ import * as fs from 'fs';
250
+ import * as path from 'path';
251
+
252
+ function getSessionHealth(projectPath: string): SessionHealth | null {
253
+ const diagnosticsPath = path.join(projectPath, '.specweave/state/.watchdog-diagnostics.json');
254
+ if (!fs.existsSync(diagnosticsPath)) {
255
+ return null; // Watchdog not running
256
+ }
257
+
258
+ try {
259
+ const content = fs.readFileSync(diagnosticsPath, 'utf-8');
260
+ return JSON.parse(content);
261
+ } catch {
262
+ return null;
263
+ }
264
+ }
265
+
266
+ interface SessionHealth {
267
+ timestamp: string;
268
+ severity: 0 | 1 | 2; // INFO | WARNING | CRITICAL
269
+ status: 'healthy' | 'warning' | 'critical';
270
+ checks: {
271
+ lock: { severity: number; message: string };
272
+ zombies: { count: number; message: string };
273
+ mcp: { drops: number; message: string };
274
+ orphanedJobs: { count: number; message: string };
275
+ };
276
+ consecutiveWarnings: number;
277
+ thresholdSeconds: number;
278
+ checkIntervalSeconds: number;
279
+ }
232
280
  ```
233
281
 
234
282
  ### Job Types
@@ -299,9 +347,106 @@ If job failed:
299
347
 
300
348
  ---
301
349
 
350
+ ## Session Health & Watchdog Diagnostics (v2.0)
351
+
352
+ The `/specweave:jobs` command now includes session health monitoring. The watchdog runs in the background and writes diagnostics that help explain any alerts you may have received.
353
+
354
+ ### Display Format (with health status)
355
+
356
+ ```
357
+ šŸ“‹ Background Jobs & Session Health
358
+
359
+ 🩺 Session Health: āœ… healthy
360
+ Last check: 30 seconds ago
361
+ Consecutive warnings: 0/3
362
+
363
+ šŸ”„ Running (1):
364
+ [abc12345] import-issues (ADO)
365
+ Progress: 2,500/10,000 (25%)
366
+ ...
367
+ ```
368
+
369
+ ### Diagnostics File
370
+
371
+ The watchdog writes diagnostics to `.specweave/state/.watchdog-diagnostics.json`:
372
+
373
+ ```json
374
+ {
375
+ "timestamp": "2025-12-10T10:30:00Z",
376
+ "severity": 0,
377
+ "status": "healthy",
378
+ "checks": {
379
+ "lock": { "severity": 0, "message": "ok" },
380
+ "zombies": { "count": 0, "message": "none" },
381
+ "mcp": { "drops": 2, "message": "minor instability" },
382
+ "orphanedJobs": { "count": 0, "message": "none" }
383
+ },
384
+ "consecutiveWarnings": 0,
385
+ "thresholdSeconds": 300,
386
+ "checkIntervalSeconds": 60
387
+ }
388
+ ```
389
+
390
+ ### View Detailed Diagnostics
391
+
392
+ ```
393
+ /specweave:jobs --diagnostics
394
+
395
+ 🩺 Watchdog Diagnostics
396
+
397
+ Overall Status: āœ… healthy
398
+ Last Check: 2025-12-10 10:30:00
399
+ Severity Level: INFO (0)
400
+
401
+ Checks:
402
+ šŸ“ Lock File: āœ… ok
403
+ šŸ’€ Zombie Procs: āœ… none (0)
404
+ šŸ”Œ MCP Connection: āš ļø 2 drops detected (minor instability)
405
+ šŸ“¦ Orphaned Jobs: āœ… none (0)
406
+
407
+ Alert Threshold: 3 consecutive warnings
408
+ Current Warnings: 0/3
409
+
410
+ Severity Levels:
411
+ INFO (0) - Everything healthy, no action needed
412
+ WARNING (1) - Minor issue detected, monitoring (NO notification)
413
+ CRITICAL (2) - Real stuck condition detected → NOTIFICATION SENT
414
+
415
+ šŸ’” The watchdog only sends notifications for CRITICAL issues
416
+ that persist across 3+ consecutive checks (prevents false positives).
417
+ ```
418
+
419
+ ### Why You Got a Notification
420
+
421
+ If you received a notification but your job completed successfully, here's what happened:
422
+
423
+ 1. **Old behavior (v1)**: Watchdog triggered on stale lock files even if no process was stuck
424
+ 2. **New behavior (v2)**: Watchdog verifies actual process state before alerting
425
+
426
+ Common false positive causes (now fixed):
427
+ - Stale `.processor.lock` file from completed job
428
+ - Missing heartbeat file (never written in normal operation)
429
+ - MCP connection drops (warning only, not critical)
430
+
431
+ **The v2 watchdog now requires**:
432
+ 1. **Actual stuck process** (zombie heredoc, hung worker)
433
+ 2. **3 consecutive checks** showing the same issue
434
+ 3. **CRITICAL severity** (not just warnings)
435
+
436
+ ### Watchdog Log
437
+
438
+ View historical watchdog checks:
439
+
440
+ ```bash
441
+ cat .specweave/logs/watchdog.log
442
+ ```
443
+
444
+ ---
445
+
302
446
  ## Notes
303
447
 
304
448
  - Jobs persist across Claude sessions
305
449
  - Paused jobs can be resumed later
306
450
  - Completed jobs cleaned up after 10 entries
307
451
  - Rate limiting auto-pauses and notifies
452
+ - Watchdog diagnostics available via `--diagnostics` flag
@@ -61,18 +61,40 @@ fi
61
61
  # Extract YAML frontmatter
62
62
  FRONTMATTER=$(echo "$CONTENT" | sed -n '/^---$/,/^---$/p' | tail -n +2 | head -n -1)
63
63
 
64
- # Check for unresolved project placeholder
64
+ # Check for unresolved project placeholder (legacy {{PROJECT_ID}})
65
65
  if echo "$FRONTMATTER" | grep -q 'project:\s*{{PROJECT_ID}}'; then
66
66
  echo '{"decision": "block", "reason": "spec.md has unresolved placeholder {{PROJECT_ID}}. Run '\''specweave context projects'\'' to get available projects, then select one."}'
67
67
  exit 0
68
68
  fi
69
69
 
70
- # Check for unresolved board placeholder
70
+ # Check for unresolved board placeholder (legacy {{BOARD_ID}})
71
71
  if echo "$FRONTMATTER" | grep -q 'board:\s*{{BOARD_ID}}'; then
72
72
  echo '{"decision": "block", "reason": "spec.md has unresolved placeholder {{BOARD_ID}}. Run '\''specweave context boards --project=<id>'\'' to get available boards, then select one."}'
73
73
  exit 0
74
74
  fi
75
75
 
76
+ # Check for ANY unresolved {{...}} placeholder in frontmatter (v0.34.0+)
77
+ # This catches {{RESOLVED_PROJECT}}, {{RESOLVED_BOARD}}, and any other placeholders
78
+ if echo "$FRONTMATTER" | grep -qE '\{\{[A-Z_]+\}\}'; then
79
+ FOUND_PLACEHOLDERS=$(echo "$FRONTMATTER" | grep -oE '\{\{[A-Z_]+\}\}' | tr '\n' ', ' | sed 's/,$//')
80
+ echo "{\"decision\": \"block\", \"reason\": \"spec.md has unresolved placeholders: ${FOUND_PLACEHOLDERS}\\n\\nYOU MUST RESOLVE these BEFORE creating spec.md:\\n1. Run: specweave context projects\\n2. Parse the JSON output to get valid project/board IDs\\n3. Replace placeholders with actual values from step 2\\n\\nāŒ FORBIDDEN: Using placeholder templates directly\\nāœ… REQUIRED: Resolve ALL placeholders to actual values\"}"
81
+ exit 0
82
+ fi
83
+
84
+ # Check for ANY unresolved {{...}} placeholder in full content (catches per-US **Project**: {{...}})
85
+ if echo "$CONTENT" | grep -qE '\*\*Project\*\*:\s*\{\{[A-Z_]+\}\}'; then
86
+ FOUND_PLACEHOLDERS=$(echo "$CONTENT" | grep -oE '\*\*Project\*\*:\s*\{\{[A-Z_]+\}\}' | head -1)
87
+ echo "{\"decision\": \"block\", \"reason\": \"spec.md has unresolved **Project**: placeholder\\n\\nFound: ${FOUND_PLACEHOLDERS}\\n\\nEach user story MUST have a resolved **Project**: field.\\n\\n1. Run: specweave context projects\\n2. Get valid project IDs from the JSON output\\n3. Replace the placeholder with an actual project ID\"}"
88
+ exit 0
89
+ fi
90
+
91
+ # Check for unresolved **Board**: placeholders in full content (2-level structures)
92
+ if echo "$CONTENT" | grep -qE '\*\*Board\*\*:\s*\{\{[A-Z_]+\}\}'; then
93
+ FOUND_PLACEHOLDERS=$(echo "$CONTENT" | grep -oE '\*\*Board\*\*:\s*\{\{[A-Z_]+\}\}' | head -1)
94
+ echo "{\"decision\": \"block\", \"reason\": \"spec.md has unresolved **Board**: placeholder\\n\\nFound: ${FOUND_PLACEHOLDERS}\\n\\nEach user story MUST have a resolved **Board**: field (for 2-level structures).\\n\\n1. Run: specweave context projects\\n2. Get valid board IDs from boardsByProject in the JSON output\\n3. Replace the placeholder with an actual board ID\"}"
95
+ exit 0
96
+ fi
97
+
76
98
  # Extract project and board from frontmatter
77
99
  PROJECT=$(echo "$FRONTMATTER" | grep -E '^project:\s*' | sed 's/^project:\s*//' | tr -d '"'"'" | tr -d '[:space:]')
78
100
  BOARD=$(echo "$FRONTMATTER" | grep -E '^board:\s*' | sed 's/^board:\s*//' | tr -d '"'"'" | tr -d '[:space:]')
@@ -1,26 +1,26 @@
1
- @echo off
2
- REM hook-wrapper.cmd - Windows resilient hook launcher
3
- REM Prevents crashes when dispatcher.mjs is temporarily unavailable
4
-
5
- setlocal enabledelayedexpansion
6
-
7
- set "HOOK_TYPE=%~1"
8
- if "%HOOK_TYPE%"=="" set "HOOK_TYPE=unknown"
9
-
10
- set "SCRIPT_DIR=%~dp0"
11
- set "DISPATCHER=%SCRIPT_DIR%dispatcher.mjs"
12
-
13
- REM Check if dispatcher exists
14
- if not exist "%DISPATCHER%" (
15
- echo {"continue":true,"systemMessage":"Hook skipped: dispatcher.mjs not found"}
16
- exit /b 0
17
- )
18
-
19
- REM Run dispatcher with error suppression
20
- node "%DISPATCHER%" "%HOOK_TYPE%" 2>nul
21
- if errorlevel 1 (
22
- echo {"continue":true,"systemMessage":"Hook error, continuing"}
23
- exit /b 0
24
- )
25
-
26
- exit /b 0
1
+ @echo off
2
+ REM hook-wrapper.cmd - Windows resilient hook launcher
3
+ REM Prevents crashes when dispatcher.mjs is temporarily unavailable
4
+
5
+ setlocal enabledelayedexpansion
6
+
7
+ set "HOOK_TYPE=%~1"
8
+ if "%HOOK_TYPE%"=="" set "HOOK_TYPE=unknown"
9
+
10
+ set "SCRIPT_DIR=%~dp0"
11
+ set "DISPATCHER=%SCRIPT_DIR%dispatcher.mjs"
12
+
13
+ REM Check if dispatcher exists
14
+ if not exist "%DISPATCHER%" (
15
+ echo {"continue":true,"systemMessage":"Hook skipped: dispatcher.mjs not found"}
16
+ exit /b 0
17
+ )
18
+
19
+ REM Run dispatcher with error suppression
20
+ node "%DISPATCHER%" "%HOOK_TYPE%" 2>nul
21
+ if errorlevel 1 (
22
+ echo {"continue":true,"systemMessage":"Hook error, continuing"}
23
+ exit /b 0
24
+ )
25
+
26
+ exit /b 0
@@ -1,16 +1,16 @@
1
- @echo off
2
- :: Universal Session Start Hook for Windows
3
- :: Calls the Node.js dispatcher
4
-
5
- :: Find node.exe
6
- where node >nul 2>&1
7
- if %ERRORLEVEL% neq 0 (
8
- echo {"continue": true, "error": "Node.js not found"}
9
- exit /b 0
10
- )
11
-
12
- :: Get the directory of this script
13
- set "SCRIPT_DIR=%~dp0"
14
-
15
- :: Run the dispatcher
16
- node "%SCRIPT_DIR%dispatcher.mjs" session-start
1
+ @echo off
2
+ :: Universal Session Start Hook for Windows
3
+ :: Calls the Node.js dispatcher
4
+
5
+ :: Find node.exe
6
+ where node >nul 2>&1
7
+ if %ERRORLEVEL% neq 0 (
8
+ echo {"continue": true, "error": "Node.js not found"}
9
+ exit /b 0
10
+ )
11
+
12
+ :: Get the directory of this script
13
+ set "SCRIPT_DIR=%~dp0"
14
+
15
+ :: Run the dispatcher
16
+ node "%SCRIPT_DIR%dispatcher.mjs" session-start
@@ -1,16 +1,16 @@
1
- # Universal Session Start Hook for Windows PowerShell
2
- # Calls the Node.js dispatcher for cross-platform compatibility
3
-
4
- # Find node.exe
5
- $nodePath = Get-Command node -ErrorAction SilentlyContinue
6
-
7
- if (-not $nodePath) {
8
- Write-Host '{"continue": true, "error": "Node.js not found"}'
9
- exit 0
10
- }
11
-
12
- # Get script directory
13
- $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
14
-
15
- # Run the dispatcher
16
- & node "$scriptDir\dispatcher.mjs" session-start
1
+ # Universal Session Start Hook for Windows PowerShell
2
+ # Calls the Node.js dispatcher for cross-platform compatibility
3
+
4
+ # Find node.exe
5
+ $nodePath = Get-Command node -ErrorAction SilentlyContinue
6
+
7
+ if (-not $nodePath) {
8
+ Write-Host '{"continue": true, "error": "Node.js not found"}'
9
+ exit 0
10
+ }
11
+
12
+ # Get script directory
13
+ $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
14
+
15
+ # Run the dispatcher
16
+ & node "$scriptDir\dispatcher.mjs" session-start