specweave 0.32.10 → 0.33.2
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 +106 -1
- package/dist/src/cli/add-child-pid.d.ts +11 -0
- package/dist/src/cli/add-child-pid.d.ts.map +1 -0
- package/dist/src/cli/add-child-pid.js +42 -0
- package/dist/src/cli/add-child-pid.js.map +1 -0
- package/dist/src/cli/add-child-process.d.ts +15 -0
- package/dist/src/cli/add-child-process.d.ts.map +1 -0
- package/dist/src/cli/add-child-process.js +40 -0
- package/dist/src/cli/add-child-process.js.map +1 -0
- package/dist/src/cli/check-watchdog.d.ts +15 -0
- package/dist/src/cli/check-watchdog.d.ts.map +1 -0
- package/dist/src/cli/check-watchdog.js +47 -0
- package/dist/src/cli/check-watchdog.js.map +1 -0
- package/dist/src/cli/cleanup-zombies.d.ts +14 -0
- package/dist/src/cli/cleanup-zombies.d.ts.map +1 -0
- package/dist/src/cli/cleanup-zombies.js +268 -0
- package/dist/src/cli/cleanup-zombies.js.map +1 -0
- package/dist/src/cli/find-session-by-pid.d.ts +14 -0
- package/dist/src/cli/find-session-by-pid.d.ts.map +1 -0
- package/dist/src/cli/find-session-by-pid.js +45 -0
- package/dist/src/cli/find-session-by-pid.js.map +1 -0
- package/dist/src/cli/get-stale-sessions.d.ts +17 -0
- package/dist/src/cli/get-stale-sessions.d.ts.map +1 -0
- package/dist/src/cli/get-stale-sessions.js +36 -0
- package/dist/src/cli/get-stale-sessions.js.map +1 -0
- package/dist/src/cli/register-session.d.ts +16 -0
- package/dist/src/cli/register-session.d.ts.map +1 -0
- package/dist/src/cli/register-session.js +48 -0
- package/dist/src/cli/register-session.js.map +1 -0
- package/dist/src/cli/remove-session.d.ts +11 -0
- package/dist/src/cli/remove-session.d.ts.map +1 -0
- package/dist/src/cli/remove-session.js +36 -0
- package/dist/src/cli/remove-session.js.map +1 -0
- package/dist/src/cli/update-heartbeat.d.ts +11 -0
- package/dist/src/cli/update-heartbeat.d.ts.map +1 -0
- package/dist/src/cli/update-heartbeat.js +36 -0
- package/dist/src/cli/update-heartbeat.js.map +1 -0
- package/dist/src/config/types.d.ts +1208 -203
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/core/background/job-manager.d.ts +16 -0
- package/dist/src/core/background/job-manager.d.ts.map +1 -1
- package/dist/src/core/background/job-manager.js +110 -15
- package/dist/src/core/background/job-manager.js.map +1 -1
- package/dist/src/core/increment/increment-utils.d.ts +26 -1
- package/dist/src/core/increment/increment-utils.d.ts.map +1 -1
- package/dist/src/core/increment/increment-utils.js +66 -4
- package/dist/src/core/increment/increment-utils.js.map +1 -1
- package/dist/src/core/increment/status-change-sync-trigger.d.ts +3 -1
- package/dist/src/core/increment/status-change-sync-trigger.d.ts.map +1 -1
- package/dist/src/core/increment/status-change-sync-trigger.js +5 -2
- package/dist/src/core/increment/status-change-sync-trigger.js.map +1 -1
- 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 +48 -12
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/cache-manager.d.ts +70 -0
- package/dist/src/core/living-docs/intelligent-analyzer/cache-manager.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/cache-manager.js +188 -0
- package/dist/src/core/living-docs/intelligent-analyzer/cache-manager.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/dashboard-generator.d.ts +33 -0
- package/dist/src/core/living-docs/intelligent-analyzer/dashboard-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/dashboard-generator.js +290 -0
- package/dist/src/core/living-docs/intelligent-analyzer/dashboard-generator.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.d.ts.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js +114 -11
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/graph-visualizer.d.ts +23 -0
- package/dist/src/core/living-docs/intelligent-analyzer/graph-visualizer.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/graph-visualizer.js +283 -0
- package/dist/src/core/living-docs/intelligent-analyzer/graph-visualizer.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/mermaid-generator.d.ts +44 -0
- package/dist/src/core/living-docs/intelligent-analyzer/mermaid-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/mermaid-generator.js +61 -0
- package/dist/src/core/living-docs/intelligent-analyzer/mermaid-generator.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/orchestrator.d.ts +126 -0
- package/dist/src/core/living-docs/intelligent-analyzer/orchestrator.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/orchestrator.js +378 -0
- package/dist/src/core/living-docs/intelligent-analyzer/orchestrator.js.map +1 -0
- 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 +57 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/pattern-analyzer.d.ts +82 -0
- package/dist/src/core/living-docs/intelligent-analyzer/pattern-analyzer.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/pattern-analyzer.js +430 -0
- package/dist/src/core/living-docs/intelligent-analyzer/pattern-analyzer.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/repo-scanner.d.ts +84 -0
- package/dist/src/core/living-docs/intelligent-analyzer/repo-scanner.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/repo-scanner.js +387 -0
- package/dist/src/core/living-docs/intelligent-analyzer/repo-scanner.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/report-writer.d.ts +61 -0
- package/dist/src/core/living-docs/intelligent-analyzer/report-writer.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/report-writer.js +174 -0
- package/dist/src/core/living-docs/intelligent-analyzer/report-writer.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts.map +1 -1
- package/dist/src/core/living-docs/module-analyzer.d.ts +3 -0
- package/dist/src/core/living-docs/module-analyzer.d.ts.map +1 -1
- package/dist/src/core/living-docs/module-analyzer.js +40 -1
- package/dist/src/core/living-docs/module-analyzer.js.map +1 -1
- package/dist/src/core/qa/qa-runner.js +1 -1
- package/dist/src/core/qa/qa-runner.js.map +1 -1
- package/dist/src/core/scheduler/session-sync-executor.js +1 -1
- package/dist/src/core/scheduler/session-sync-executor.js.map +1 -1
- package/dist/src/core/status-line/status-line-updater.d.ts +1 -1
- package/dist/src/core/status-line/status-line-updater.d.ts.map +1 -1
- package/dist/src/core/status-line/status-line-updater.js +4 -3
- package/dist/src/core/status-line/status-line-updater.js.map +1 -1
- package/dist/src/importers/jira-importer.d.ts.map +1 -1
- package/dist/src/importers/jira-importer.js +18 -9
- package/dist/src/importers/jira-importer.js.map +1 -1
- package/dist/src/init/architecture/types.d.ts +140 -33
- package/dist/src/init/architecture/types.d.ts.map +1 -1
- package/dist/src/init/compliance/types.d.ts +27 -30
- package/dist/src/init/compliance/types.d.ts.map +1 -1
- package/dist/src/init/repo/types.d.ts +34 -11
- package/dist/src/init/repo/types.d.ts.map +1 -1
- package/dist/src/init/research/src/config/types.d.ts +82 -15
- package/dist/src/init/research/src/config/types.d.ts.map +1 -1
- package/dist/src/init/research/types.d.ts +93 -38
- package/dist/src/init/research/types.d.ts.map +1 -1
- package/dist/src/init/team/types.d.ts +42 -4
- package/dist/src/init/team/types.d.ts.map +1 -1
- package/dist/src/sync/ado-reconciler.js +1 -1
- package/dist/src/sync/ado-reconciler.js.map +1 -1
- package/dist/src/sync/github-reconciler.js +1 -1
- package/dist/src/sync/github-reconciler.js.map +1 -1
- package/dist/src/sync/jira-reconciler.js +1 -1
- package/dist/src/sync/jira-reconciler.js.map +1 -1
- package/dist/src/types/session.d.ts +65 -0
- package/dist/src/types/session.d.ts.map +1 -0
- package/dist/src/types/session.js +8 -0
- package/dist/src/types/session.js.map +1 -0
- package/dist/src/utils/lock-manager.d.ts +48 -0
- package/dist/src/utils/lock-manager.d.ts.map +1 -0
- package/dist/src/utils/lock-manager.js +195 -0
- package/dist/src/utils/lock-manager.js.map +1 -0
- package/dist/src/utils/notification-manager.d.ts +45 -0
- package/dist/src/utils/notification-manager.d.ts.map +1 -0
- package/dist/src/utils/notification-manager.js +130 -0
- package/dist/src/utils/notification-manager.js.map +1 -0
- package/dist/src/utils/platform-utils.d.ts +136 -0
- package/dist/src/utils/platform-utils.d.ts.map +1 -0
- package/dist/src/utils/platform-utils.js +366 -0
- package/dist/src/utils/platform-utils.js.map +1 -0
- package/dist/src/utils/session-registry.d.ts +142 -0
- package/dist/src/utils/session-registry.d.ts.map +1 -0
- package/dist/src/utils/session-registry.js +480 -0
- package/dist/src/utils/session-registry.js.map +1 -0
- package/package.json +5 -2
- package/plugins/specweave/commands/specweave-living-docs.md +42 -0
- package/plugins/specweave/hooks/hooks.json +10 -0
- package/plugins/specweave/hooks/lib/update-active-increment.sh +2 -2
- package/plugins/specweave/hooks/lib/update-status-line.sh +1 -1
- package/plugins/specweave/hooks/post-increment-status-change.sh +3 -3
- package/plugins/specweave/hooks/post-metadata-change.sh +1 -1
- package/plugins/specweave/hooks/universal/hook-wrapper.cmd +26 -26
- package/plugins/specweave/hooks/universal/session-start.cmd +16 -16
- package/plugins/specweave/hooks/universal/session-start.ps1 +16 -16
- package/plugins/specweave/hooks/user-prompt-submit.sh +2 -2
- package/plugins/specweave/hooks/v2/guards/increment-root-guard.sh +61 -0
- package/plugins/specweave/hooks/v2/session-end.sh +69 -0
- package/plugins/specweave/hooks/v2/session-start.sh +81 -0
- package/plugins/specweave/lib/vendor/sync/github-reconciler.js +1 -1
- package/plugins/specweave/lib/vendor/sync/github-reconciler.js.map +1 -1
- package/plugins/specweave/scripts/heartbeat.sh +110 -0
- package/plugins/specweave/scripts/progress.js +34 -4
- package/plugins/specweave/scripts/read-jobs.sh +1 -1
- package/plugins/specweave/scripts/read-progress.sh +50 -5
- package/plugins/specweave/scripts/read-workflow.sh +1 -1
- package/plugins/specweave/scripts/session-watchdog.sh +65 -0
- package/plugins/specweave/scripts/status.js +28 -11
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +738 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1107 -0
package/CLAUDE.md
CHANGED
|
@@ -132,7 +132,36 @@ const config = detectStructureLevel(projectRoot);
|
|
|
132
132
|
|
|
133
133
|
**Pre-tool-use hook `features-folder-guard.sh` BLOCKS writes to `_features/` (v0.33.0+).**
|
|
134
134
|
|
|
135
|
-
### 2e. NEVER Create
|
|
135
|
+
### 2e. NEVER Create Files at Increment Root (FOLDER STRUCTURE v0.33.0+)
|
|
136
|
+
|
|
137
|
+
**Files at increment root MUST be limited to required files!**
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
❌ FORBIDDEN (Bug pattern from 2025-12-09):
|
|
141
|
+
.specweave/increments/0134-feature/COMPLETION_REPORT.md
|
|
142
|
+
.specweave/increments/0135-feature/COMPLETION_SUMMARY.md
|
|
143
|
+
|
|
144
|
+
✅ CORRECT - Use reports/ subfolder:
|
|
145
|
+
.specweave/increments/0134-feature/reports/COMPLETION_REPORT.md
|
|
146
|
+
.specweave/increments/0135-feature/reports/COMPLETION_SUMMARY.md
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**ONLY ALLOWED at increment root:**
|
|
150
|
+
- `metadata.json`
|
|
151
|
+
- `spec.md`
|
|
152
|
+
- `plan.md`
|
|
153
|
+
- `tasks.md`
|
|
154
|
+
|
|
155
|
+
**Everything else → subfolders:**
|
|
156
|
+
- `reports/` - completion reports, validation reports, analysis docs
|
|
157
|
+
- `scripts/` - helper scripts, automation
|
|
158
|
+
- `logs/` - execution logs, debug output
|
|
159
|
+
- `backups/` - backup files
|
|
160
|
+
- `docs/` - additional documentation
|
|
161
|
+
|
|
162
|
+
**Pre-tool-use hook `increment-root-guard.sh` BLOCKS non-standard files at root (v0.33.0+).**
|
|
163
|
+
|
|
164
|
+
### 2f. NEVER Create Duplicate Increment IDs (v0.33.0+)
|
|
136
165
|
|
|
137
166
|
**Increment numbers MUST be unique across ALL directories!**
|
|
138
167
|
|
|
@@ -171,6 +200,44 @@ IncrementNumberManager.findDuplicates('0121');
|
|
|
171
200
|
|
|
172
201
|
**Pre-tool-use hook `increment-duplicate-guard.sh` BLOCKS duplicate increment creation (v0.33.0+).**
|
|
173
202
|
|
|
203
|
+
### 2f. Gap-Filling Increment IDs (v0.33.1+)
|
|
204
|
+
|
|
205
|
+
**Increment IDs now FILL GAPS instead of always using highest + 1!**
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
OLD BEHAVIOR (v0.33.0 and earlier):
|
|
209
|
+
0128 (exists) → next is 0136 (highest + 1, even if gaps exist)
|
|
210
|
+
|
|
211
|
+
NEW BEHAVIOR (v0.33.1+):
|
|
212
|
+
0106, 0108, 0128, 0131 (exists) → next is 0107 (fills first gap!)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Gap-filling algorithm:**
|
|
216
|
+
1. Scans ALL directories (main, _archive, _paused, _abandoned)
|
|
217
|
+
2. Finds first available number starting from 0001
|
|
218
|
+
3. Returns gap number if found, otherwise returns highest + 1
|
|
219
|
+
|
|
220
|
+
**Examples:**
|
|
221
|
+
```typescript
|
|
222
|
+
// Existing: [0001, 0002, 0004, 0005]
|
|
223
|
+
IncrementNumberManager.getNextIncrementNumber(); // "0003" ← Fills gap!
|
|
224
|
+
|
|
225
|
+
// Existing: [0001, 0002, 0003, 0004]
|
|
226
|
+
IncrementNumberManager.getNextIncrementNumber(); // "0005" ← Sequential (no gaps)
|
|
227
|
+
|
|
228
|
+
// Existing: [0050, 0051]
|
|
229
|
+
IncrementNumberManager.getNextIncrementNumber(); // "0001" ← Starts from beginning!
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Benefits:**
|
|
233
|
+
- ✅ No wasted ID space (4-digit limit = max 9999 increments)
|
|
234
|
+
- ✅ Clear sequence without confusing gaps
|
|
235
|
+
- ✅ Total increment count = highest number (no need to scan all)
|
|
236
|
+
|
|
237
|
+
**Migration:** Automatic, no action required. Next increment fills first gap!
|
|
238
|
+
|
|
239
|
+
**Details:** See ADR-0142 (`.specweave/docs/internal/architecture/adr/0142-gap-filling-increment-ids.md`)
|
|
240
|
+
|
|
174
241
|
### 3. Protected Directories
|
|
175
242
|
|
|
176
243
|
**NEVER delete**: `.specweave/docs/`, `.specweave/increments/`
|
|
@@ -555,6 +622,44 @@ bash plugins/specweave/scripts/cleanup-state.sh
|
|
|
555
622
|
- Update Claude Code VS Code extension regularly
|
|
556
623
|
- Use terminal mode for long-running sessions
|
|
557
624
|
|
|
625
|
+
### Zombie Processes (v0.33.0+ AUTO-CLEANUP)
|
|
626
|
+
|
|
627
|
+
**Status**: ✅ AUTOMATED - No manual intervention needed!
|
|
628
|
+
|
|
629
|
+
**How it works:**
|
|
630
|
+
- SessionStart hook registers all Claude Code sessions
|
|
631
|
+
- Heartbeat process monitors parent health every 5s
|
|
632
|
+
- Session watchdog cleans up zombies every 60s
|
|
633
|
+
- Automatic cleanup within 60s of session termination
|
|
634
|
+
|
|
635
|
+
**Session Registry**: `.specweave/state/.session-registry.json`
|
|
636
|
+
|
|
637
|
+
**Logs**:
|
|
638
|
+
```bash
|
|
639
|
+
# Session tracking logs
|
|
640
|
+
cat .specweave/logs/sessions/session-*.log
|
|
641
|
+
|
|
642
|
+
# Cleanup logs
|
|
643
|
+
cat .specweave/logs/cleanup.log
|
|
644
|
+
|
|
645
|
+
# Heartbeat logs
|
|
646
|
+
cat .specweave/logs/heartbeat-*.log
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
**Manual Cleanup (if needed)**:
|
|
650
|
+
```bash
|
|
651
|
+
# Kill all zombie processes
|
|
652
|
+
node dist/src/cli/cleanup-zombies.js 60
|
|
653
|
+
|
|
654
|
+
# Or use watchdog
|
|
655
|
+
bash plugins/specweave/scripts/session-watchdog.sh
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
**Troubleshooting**:
|
|
659
|
+
- If zombies persist >5 minutes: Check `.specweave/state/.session-registry.json`
|
|
660
|
+
- If cleanup fails: Run `bash plugins/specweave/scripts/cleanup-state.sh`
|
|
661
|
+
- For details: See `.specweave/docs/internal/troubleshooting/zombie-processes.md`
|
|
662
|
+
|
|
558
663
|
### Crash loop / prompt duplication
|
|
559
664
|
|
|
560
665
|
**Disable hooks FIRST:**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-child-pid.d.ts","sourceRoot":"","sources":["../../../src/cli/add-child-pid.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Add Child PID CLI
|
|
4
|
+
*
|
|
5
|
+
* Adds a child PID to a session
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node dist/src/cli/add-child-pid.js <session-id> <child-pid>
|
|
9
|
+
*/
|
|
10
|
+
import { SessionRegistry } from '../utils/session-registry.js';
|
|
11
|
+
import { consoleLogger } from '../utils/logger.js';
|
|
12
|
+
async function main() {
|
|
13
|
+
const sessionId = process.argv[2];
|
|
14
|
+
const childPidStr = process.argv[3];
|
|
15
|
+
if (!sessionId || !childPidStr) {
|
|
16
|
+
console.error('Usage: node add-child-pid.js <session-id> <child-pid>');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const childPid = parseInt(childPidStr, 10);
|
|
20
|
+
if (isNaN(childPid)) {
|
|
21
|
+
console.error(`Invalid child PID: ${childPidStr}`);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const registry = new SessionRegistry(process.cwd(), { logger: consoleLogger });
|
|
25
|
+
try {
|
|
26
|
+
const success = await registry.addChildProcess(sessionId, childPid);
|
|
27
|
+
if (success) {
|
|
28
|
+
console.log(`Child PID ${childPid} added to session ${sessionId}`);
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
console.error('Failed to add child PID');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
console.error('Error adding child PID:', err);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
main();
|
|
42
|
+
//# sourceMappingURL=add-child-pid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-child-pid.js","sourceRoot":"","sources":["../../../src/cli/add-child-pid.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEpC,IAAI,CAAC,SAAS,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC3C,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,sBAAsB,WAAW,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;IAE/E,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAEpE,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,aAAa,QAAQ,qBAAqB,SAAS,EAAE,CAAC,CAAC;YACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Add Child Process CLI
|
|
4
|
+
*
|
|
5
|
+
* Adds a child process PID to a session's child_pids array
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node dist/src/cli/add-child-process.js <session-id> <child-pid>
|
|
9
|
+
*
|
|
10
|
+
* Arguments:
|
|
11
|
+
* session-id: Session identifier
|
|
12
|
+
* child-pid: Child process ID to add
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=add-child-process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-child-process.d.ts","sourceRoot":"","sources":["../../../src/cli/add-child-process.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Add Child Process CLI
|
|
4
|
+
*
|
|
5
|
+
* Adds a child process PID to a session's child_pids array
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node dist/src/cli/add-child-process.js <session-id> <child-pid>
|
|
9
|
+
*
|
|
10
|
+
* Arguments:
|
|
11
|
+
* session-id: Session identifier
|
|
12
|
+
* child-pid: Child process ID to add
|
|
13
|
+
*/
|
|
14
|
+
import { SessionRegistry } from '../utils/session-registry.js';
|
|
15
|
+
import { consoleLogger } from '../utils/logger.js';
|
|
16
|
+
async function main() {
|
|
17
|
+
const sessionId = process.argv[2];
|
|
18
|
+
const childPidStr = process.argv[3];
|
|
19
|
+
if (!sessionId || !childPidStr) {
|
|
20
|
+
console.error('Usage: node add-child-process.js <session-id> <child-pid>');
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const childPid = parseInt(childPidStr, 10);
|
|
24
|
+
if (isNaN(childPid)) {
|
|
25
|
+
console.error(`Invalid child PID: ${childPidStr}`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
const registry = new SessionRegistry(process.cwd(), { logger: consoleLogger });
|
|
29
|
+
try {
|
|
30
|
+
await registry.addChildProcess(sessionId, childPid);
|
|
31
|
+
console.log(`Child process ${childPid} added to session ${sessionId}`);
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
console.error('Error adding child process:', err);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
main();
|
|
40
|
+
//# sourceMappingURL=add-child-process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-child-process.js","sourceRoot":"","sources":["../../../src/cli/add-child-process.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEpC,IAAI,CAAC,SAAS,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC3C,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,sBAAsB,WAAW,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;IAE/E,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,qBAAqB,SAAS,EAAE,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Check Watchdog CLI
|
|
4
|
+
*
|
|
5
|
+
* Checks if an active watchdog is running
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node dist/src/cli/check-watchdog.js
|
|
9
|
+
*
|
|
10
|
+
* Output:
|
|
11
|
+
* - PID of active watchdog (if exists)
|
|
12
|
+
* - Empty string (if no active watchdog)
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=check-watchdog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-watchdog.d.ts","sourceRoot":"","sources":["../../../src/cli/check-watchdog.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Check Watchdog CLI
|
|
4
|
+
*
|
|
5
|
+
* Checks if an active watchdog is running
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node dist/src/cli/check-watchdog.js
|
|
9
|
+
*
|
|
10
|
+
* Output:
|
|
11
|
+
* - PID of active watchdog (if exists)
|
|
12
|
+
* - Empty string (if no active watchdog)
|
|
13
|
+
*/
|
|
14
|
+
import { SessionRegistry } from '../utils/session-registry.js';
|
|
15
|
+
import { consoleLogger } from '../utils/logger.js';
|
|
16
|
+
async function main() {
|
|
17
|
+
const registry = new SessionRegistry(process.cwd(), { logger: consoleLogger });
|
|
18
|
+
try {
|
|
19
|
+
const sessions = await registry.getAllSessions();
|
|
20
|
+
// Find watchdog sessions
|
|
21
|
+
const watchdogs = sessions.filter((s) => s.type === 'watchdog' && s.status === 'active');
|
|
22
|
+
if (watchdogs.length === 0) {
|
|
23
|
+
// No active watchdog
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
// Check heartbeat freshness (last 30 seconds)
|
|
27
|
+
const now = Date.now();
|
|
28
|
+
const threshold = 30 * 1000; // 30 seconds
|
|
29
|
+
for (const watchdog of watchdogs) {
|
|
30
|
+
const lastHeartbeat = new Date(watchdog.last_heartbeat).getTime();
|
|
31
|
+
const age = now - lastHeartbeat;
|
|
32
|
+
if (age < threshold) {
|
|
33
|
+
// Active watchdog found
|
|
34
|
+
console.log(watchdog.pid);
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// All watchdogs are stale
|
|
39
|
+
process.exit(0);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
console.error('Error checking watchdog:', err);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
main();
|
|
47
|
+
//# sourceMappingURL=check-watchdog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-watchdog.js","sourceRoot":"","sources":["../../../src/cli/check-watchdog.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,KAAK,UAAU,IAAI;IACjB,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;IAE/E,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,cAAc,EAAE,CAAC;QAEjD,yBAAyB;QACzB,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;QAEzF,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,qBAAqB;YACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,8CAA8C;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;QAE1C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,aAAa,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;YAClE,MAAM,GAAG,GAAG,GAAG,GAAG,aAAa,CAAC;YAEhC,IAAI,GAAG,GAAG,SAAS,EAAE,CAAC;gBACpB,wBAAwB;gBACxB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAED,0BAA0B;QAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Cleanup Zombies CLI
|
|
4
|
+
*
|
|
5
|
+
* Detects and cleans up zombie/stale processes
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node dist/src/cli/cleanup-zombies.js [threshold-seconds]
|
|
9
|
+
*
|
|
10
|
+
* Arguments:
|
|
11
|
+
* threshold-seconds: Heartbeat age threshold (default: 60)
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=cleanup-zombies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup-zombies.d.ts","sourceRoot":"","sources":["../../../src/cli/cleanup-zombies.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Cleanup Zombies CLI
|
|
4
|
+
*
|
|
5
|
+
* Detects and cleans up zombie/stale processes
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node dist/src/cli/cleanup-zombies.js [threshold-seconds]
|
|
9
|
+
*
|
|
10
|
+
* Arguments:
|
|
11
|
+
* threshold-seconds: Heartbeat age threshold (default: 60)
|
|
12
|
+
*/
|
|
13
|
+
import { SessionRegistry } from '../utils/session-registry.js';
|
|
14
|
+
import { consoleLogger } from '../utils/logger.js';
|
|
15
|
+
import * as childProcess from 'child_process';
|
|
16
|
+
import * as util from 'util';
|
|
17
|
+
import * as fs from 'fs';
|
|
18
|
+
import * as path from 'path';
|
|
19
|
+
const exec = util.promisify(childProcess.exec);
|
|
20
|
+
// Cleanup logging
|
|
21
|
+
function logCleanupAction(level, action, details) {
|
|
22
|
+
const logDir = path.join(process.cwd(), '.specweave', 'logs');
|
|
23
|
+
const logFile = path.join(logDir, 'cleanup.log');
|
|
24
|
+
// Ensure log directory exists
|
|
25
|
+
if (!fs.existsSync(logDir)) {
|
|
26
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
const timestamp = new Date().toISOString();
|
|
29
|
+
const logEntry = `[${timestamp}] [${level}] [${action}] ${details}\n`;
|
|
30
|
+
try {
|
|
31
|
+
fs.appendFileSync(logFile, logEntry, 'utf-8');
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
// If we can't log, just continue
|
|
35
|
+
console.error('Failed to write cleanup log:', err);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async function killProcess(pid, signal = 'SIGTERM') {
|
|
39
|
+
try {
|
|
40
|
+
process.kill(pid, signal);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
// Process may not exist, ignore
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async function validatePidIsSpecWeave(pid) {
|
|
47
|
+
try {
|
|
48
|
+
const { stdout } = await exec(`ps -p ${pid} -o command= || true`);
|
|
49
|
+
const command = stdout.trim().toLowerCase();
|
|
50
|
+
// Valid SpecWeave/Claude processes
|
|
51
|
+
const validPatterns = [
|
|
52
|
+
'claude',
|
|
53
|
+
'specweave',
|
|
54
|
+
'cat.*eof',
|
|
55
|
+
'esbuild',
|
|
56
|
+
'processor.sh',
|
|
57
|
+
'session-watchdog',
|
|
58
|
+
'heartbeat.sh',
|
|
59
|
+
'node.*specweave',
|
|
60
|
+
'bash.*specweave',
|
|
61
|
+
];
|
|
62
|
+
return validPatterns.some((pattern) => {
|
|
63
|
+
const regex = new RegExp(pattern, 'i');
|
|
64
|
+
return regex.test(command);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// If we can't determine, err on the side of caution
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function killZombieProcesses(registry) {
|
|
73
|
+
let killedCount = 0;
|
|
74
|
+
let skippedCount = 0;
|
|
75
|
+
// Pattern 1: Heredoc zombies
|
|
76
|
+
try {
|
|
77
|
+
const { stdout } = await exec("pgrep -f 'cat.*EOF' || true");
|
|
78
|
+
const pids = stdout
|
|
79
|
+
.trim()
|
|
80
|
+
.split('\n')
|
|
81
|
+
.filter((p) => p);
|
|
82
|
+
for (const pidStr of pids) {
|
|
83
|
+
const pid = parseInt(pidStr, 10);
|
|
84
|
+
if (!isNaN(pid)) {
|
|
85
|
+
await killProcess(pid, 'SIGKILL');
|
|
86
|
+
const msg = `Killed heredoc zombie: PID ${pid}`;
|
|
87
|
+
console.log(msg);
|
|
88
|
+
logCleanupAction('INFO', 'KILL_ZOMBIE', `heredoc cat EOF process - PID ${pid}`);
|
|
89
|
+
killedCount++;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
// Ignore errors
|
|
95
|
+
}
|
|
96
|
+
// Pattern 2: Stale esbuild services (>1 hour old)
|
|
97
|
+
try {
|
|
98
|
+
const { stdout } = await exec("pgrep -f 'esbuild.*--service' || true");
|
|
99
|
+
const pids = stdout
|
|
100
|
+
.trim()
|
|
101
|
+
.split('\n')
|
|
102
|
+
.filter((p) => p);
|
|
103
|
+
for (const pidStr of pids) {
|
|
104
|
+
const pid = parseInt(pidStr, 10);
|
|
105
|
+
if (!isNaN(pid)) {
|
|
106
|
+
// Check age using ps
|
|
107
|
+
try {
|
|
108
|
+
const { stdout: psOut } = await exec(`ps -o etime= -p ${pid}`);
|
|
109
|
+
const etime = psOut.trim();
|
|
110
|
+
// Parse elapsed time (format: [[dd-]hh:]mm:ss)
|
|
111
|
+
const parts = etime.split(/[-:]/);
|
|
112
|
+
let totalSeconds = 0;
|
|
113
|
+
if (parts.length >= 2) {
|
|
114
|
+
const seconds = parseInt(parts[parts.length - 1], 10);
|
|
115
|
+
const minutes = parseInt(parts[parts.length - 2], 10);
|
|
116
|
+
totalSeconds = minutes * 60 + seconds;
|
|
117
|
+
if (parts.length >= 3) {
|
|
118
|
+
const hours = parseInt(parts[parts.length - 3], 10);
|
|
119
|
+
totalSeconds += hours * 3600;
|
|
120
|
+
}
|
|
121
|
+
if (parts.length >= 4) {
|
|
122
|
+
const days = parseInt(parts[parts.length - 4], 10);
|
|
123
|
+
totalSeconds += days * 86400;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Kill if older than 1 hour
|
|
127
|
+
if (totalSeconds > 3600) {
|
|
128
|
+
await killProcess(pid, 'SIGKILL');
|
|
129
|
+
const ageMinutes = Math.floor(totalSeconds / 60);
|
|
130
|
+
console.log(`Killed stale esbuild: PID ${pid} (age: ${ageMinutes}m)`);
|
|
131
|
+
logCleanupAction('INFO', 'KILL_ZOMBIE', `stale esbuild service - PID ${pid} - age ${ageMinutes}m`);
|
|
132
|
+
killedCount++;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
// Ignore errors
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
// Ignore errors
|
|
143
|
+
}
|
|
144
|
+
// Pattern 3: Orphaned processor.sh daemons (not in registry)
|
|
145
|
+
try {
|
|
146
|
+
const { stdout } = await exec("pgrep -f 'processor\\.sh.*--daemon' || true");
|
|
147
|
+
const pids = stdout
|
|
148
|
+
.trim()
|
|
149
|
+
.split('\n')
|
|
150
|
+
.filter((p) => p);
|
|
151
|
+
for (const pidStr of pids) {
|
|
152
|
+
const pid = parseInt(pidStr, 10);
|
|
153
|
+
if (!isNaN(pid)) {
|
|
154
|
+
// Check if this processor is registered in any session
|
|
155
|
+
const sessions = await registry.getAllSessions();
|
|
156
|
+
const isRegistered = sessions.some((s) => s.child_pids?.includes(pid) || s.pid === pid);
|
|
157
|
+
if (!isRegistered) {
|
|
158
|
+
// Orphaned processor daemon - kill it
|
|
159
|
+
await killProcess(pid, 'SIGTERM');
|
|
160
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
161
|
+
await killProcess(pid, 'SIGKILL');
|
|
162
|
+
console.log(`Killed orphaned processor daemon: PID ${pid}`);
|
|
163
|
+
logCleanupAction('INFO', 'KILL_ZOMBIE', `orphaned processor.sh daemon - PID ${pid} - not in registry`);
|
|
164
|
+
killedCount++;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
// Ignore errors
|
|
171
|
+
}
|
|
172
|
+
return { killed: killedCount, skipped: skippedCount };
|
|
173
|
+
}
|
|
174
|
+
async function main() {
|
|
175
|
+
const thresholdArg = process.argv[2];
|
|
176
|
+
const threshold = thresholdArg ? parseInt(thresholdArg, 10) : 60;
|
|
177
|
+
if (isNaN(threshold)) {
|
|
178
|
+
console.error('Invalid threshold:', thresholdArg);
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
const registry = new SessionRegistry(process.cwd(), { logger: consoleLogger });
|
|
182
|
+
try {
|
|
183
|
+
// Get stale sessions
|
|
184
|
+
const staleSessions = await registry.getStaleSessions(threshold);
|
|
185
|
+
let totalKilled = 0;
|
|
186
|
+
// Kill stale session processes
|
|
187
|
+
for (const staleInfo of staleSessions) {
|
|
188
|
+
const { session, pid_exists } = staleInfo;
|
|
189
|
+
const staleAge = Math.floor(staleInfo.stale_duration_seconds);
|
|
190
|
+
console.log(`Found stale session: ${session.session_id} (PID: ${session.pid}, ${staleAge}s old)`);
|
|
191
|
+
logCleanupAction('INFO', 'DETECT_STALE', `session ${session.session_id} - PID ${session.pid} - age ${staleAge}s`);
|
|
192
|
+
// PID validation: ensure process is SpecWeave-related
|
|
193
|
+
if (pid_exists) {
|
|
194
|
+
const isValid = await validatePidIsSpecWeave(session.pid);
|
|
195
|
+
if (!isValid) {
|
|
196
|
+
console.log(` ⚠️ Skipping PID ${session.pid} - not a SpecWeave process`);
|
|
197
|
+
logCleanupAction('WARN', 'SKIP_PID', `PID ${session.pid} not a SpecWeave process - removed from registry only`);
|
|
198
|
+
// Remove from registry but don't kill
|
|
199
|
+
await registry.removeSession(session.session_id);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Kill parent process
|
|
204
|
+
if (pid_exists) {
|
|
205
|
+
await killProcess(session.pid, 'SIGTERM');
|
|
206
|
+
// Wait 2 seconds, then SIGKILL if still exists
|
|
207
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
208
|
+
await killProcess(session.pid, 'SIGKILL');
|
|
209
|
+
console.log(` Killed parent PID: ${session.pid}`);
|
|
210
|
+
logCleanupAction('INFO', 'KILL_PARENT', `session ${session.session_id} - PID ${session.pid} - SIGTERM -> SIGKILL`);
|
|
211
|
+
totalKilled++;
|
|
212
|
+
}
|
|
213
|
+
// Kill child processes
|
|
214
|
+
if (session.child_pids && session.child_pids.length > 0) {
|
|
215
|
+
for (const childPid of session.child_pids) {
|
|
216
|
+
await killProcess(childPid, 'SIGTERM');
|
|
217
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
218
|
+
await killProcess(childPid, 'SIGKILL');
|
|
219
|
+
console.log(` Killed child PID: ${childPid}`);
|
|
220
|
+
logCleanupAction('INFO', 'KILL_CHILD', `session ${session.session_id} - child PID ${childPid}`);
|
|
221
|
+
totalKilled++;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Remove from registry
|
|
225
|
+
await registry.removeSession(session.session_id);
|
|
226
|
+
logCleanupAction('INFO', 'REMOVE_SESSION', `session ${session.session_id} removed from registry`);
|
|
227
|
+
}
|
|
228
|
+
// Kill zombie processes by pattern
|
|
229
|
+
const zombieResults = await killZombieProcesses(registry);
|
|
230
|
+
totalKilled += zombieResults.killed;
|
|
231
|
+
if (totalKilled > 0) {
|
|
232
|
+
console.log(`\nTotal processes cleaned up: ${totalKilled}`);
|
|
233
|
+
logCleanupAction('INFO', 'SUMMARY', `Total processes cleaned: ${totalKilled}`);
|
|
234
|
+
// Send notification if >3 processes cleaned
|
|
235
|
+
if (totalKilled > 3) {
|
|
236
|
+
const title = '🚨 Zombie Cleanup';
|
|
237
|
+
const message = `Cleaned up ${totalKilled} zombie processes`;
|
|
238
|
+
try {
|
|
239
|
+
if (process.platform === 'darwin') {
|
|
240
|
+
// macOS notification
|
|
241
|
+
await exec(`osascript -e 'display notification "${message}" with title "${title}" sound name "Glass"'`);
|
|
242
|
+
}
|
|
243
|
+
else if (process.platform === 'linux') {
|
|
244
|
+
// Linux notification
|
|
245
|
+
await exec(`notify-send "${title}" "${message}" --urgency=normal`);
|
|
246
|
+
}
|
|
247
|
+
else if (process.platform === 'win32') {
|
|
248
|
+
// Windows notification (PowerShell)
|
|
249
|
+
const psScript = `[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null; $null`;
|
|
250
|
+
await exec(`powershell -Command "${psScript}"`);
|
|
251
|
+
}
|
|
252
|
+
logCleanupAction('INFO', 'NOTIFICATION', `Sent notification - ${totalKilled} processes cleaned`);
|
|
253
|
+
}
|
|
254
|
+
catch (err) {
|
|
255
|
+
// Ignore notification errors
|
|
256
|
+
logCleanupAction('WARN', 'NOTIFICATION', `Failed to send notification: ${err}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
process.exit(0);
|
|
261
|
+
}
|
|
262
|
+
catch (err) {
|
|
263
|
+
console.error('Error during cleanup:', err);
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
main();
|
|
268
|
+
//# sourceMappingURL=cleanup-zombies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup-zombies.js","sourceRoot":"","sources":["../../../src/cli/cleanup-zombies.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Find Session By PID CLI
|
|
4
|
+
*
|
|
5
|
+
* Finds a session in the registry by its PID
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node dist/src/cli/find-session-by-pid.js <pid>
|
|
9
|
+
*
|
|
10
|
+
* Output:
|
|
11
|
+
* JSON session info or empty string
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=find-session-by-pid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-session-by-pid.d.ts","sourceRoot":"","sources":["../../../src/cli/find-session-by-pid.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG"}
|