specweave 0.32.10 → 0.33.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +162 -1
- package/dist/plugins/specweave-ado/lib/per-us-sync.d.ts +120 -0
- package/dist/plugins/specweave-ado/lib/per-us-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-ado/lib/per-us-sync.js +276 -0
- package/dist/plugins/specweave-ado/lib/per-us-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +4 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js +13 -3
- package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
- package/dist/plugins/specweave-github/lib/per-us-sync.d.ts +97 -0
- package/dist/plugins/specweave-github/lib/per-us-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/per-us-sync.js +274 -0
- package/dist/plugins/specweave-github/lib/per-us-sync.js.map +1 -0
- package/dist/plugins/specweave-jira/lib/per-us-sync.d.ts +113 -0
- package/dist/plugins/specweave-jira/lib/per-us-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-jira/lib/per-us-sync.js +254 -0
- package/dist/plugins/specweave-jira/lib/per-us-sync.js.map +1 -0
- 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/config/config-manager.d.ts.map +1 -1
- package/dist/src/core/config/config-manager.js +58 -0
- package/dist/src/core/config/config-manager.js.map +1 -1
- package/dist/src/core/config/types.d.ts +80 -0
- package/dist/src/core/config/types.d.ts.map +1 -1
- package/dist/src/core/config/types.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/cross-project-sync.d.ts +87 -15
- package/dist/src/core/living-docs/cross-project-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/cross-project-sync.js +147 -28
- package/dist/src/core/living-docs/cross-project-sync.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/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +26 -22
- package/dist/src/core/living-docs/living-docs-sync.js.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/living-docs/types.d.ts +24 -3
- package/dist/src/core/living-docs/types.d.ts.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/core/types/config.d.ts +79 -0
- package/dist/src/core/types/config.d.ts.map +1 -1
- package/dist/src/core/types/config.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/sync/sync-coordinator.d.ts +20 -0
- package/dist/src/sync/sync-coordinator.d.ts.map +1 -1
- package/dist/src/sync/sync-coordinator.js +258 -33
- package/dist/src/sync/sync-coordinator.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/project-resolver.d.ts +156 -0
- package/dist/src/utils/project-resolver.d.ts.map +1 -0
- package/dist/src/utils/project-resolver.js +587 -0
- package/dist/src/utils/project-resolver.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 +20 -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 +107 -5
- package/plugins/specweave/hooks/v2/guards/increment-root-guard.sh +61 -0
- package/plugins/specweave/hooks/v2/guards/per-us-project-validator.sh +281 -0
- package/plugins/specweave/hooks/v2/handlers/living-specs-handler.sh +29 -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-ado/lib/per-us-sync.js +247 -0
- package/plugins/specweave-ado/lib/per-us-sync.ts +410 -0
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +738 -0
- package/plugins/specweave-github/lib/github-client-v2.js +10 -3
- package/plugins/specweave-github/lib/github-client-v2.ts +15 -3
- package/plugins/specweave-github/lib/per-us-sync.js +241 -0
- package/plugins/specweave-github/lib/per-us-sync.ts +375 -0
- package/plugins/specweave-jira/lib/per-us-sync.js +224 -0
- package/plugins/specweave-jira/lib/per-us-sync.ts +366 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1107 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Registry - Central tracking for all Claude Code sessions and child processes
|
|
3
|
+
*
|
|
4
|
+
* Provides atomic file-based operations for tracking active sessions, detecting
|
|
5
|
+
* stale/zombie processes, and coordinating cleanup across multiple sessions.
|
|
6
|
+
*
|
|
7
|
+
* Key Features:
|
|
8
|
+
* - Atomic operations using temp file + rename pattern
|
|
9
|
+
* - File locking via mkdir (cross-platform atomic operation)
|
|
10
|
+
* - Automatic corruption recovery with JSON validation
|
|
11
|
+
* - Concurrent-safe updates from multiple processes
|
|
12
|
+
*
|
|
13
|
+
* Registry Location: `.specweave/state/.session-registry.json`
|
|
14
|
+
*/
|
|
15
|
+
import { SessionInfo, RegisterSessionOptions, StaleSessionInfo, SessionStatus } from '../types/session.js';
|
|
16
|
+
import { Logger } from './logger.js';
|
|
17
|
+
export declare class SessionRegistry {
|
|
18
|
+
private registryPath;
|
|
19
|
+
private lockPath;
|
|
20
|
+
private logger;
|
|
21
|
+
constructor(projectRoot: string, options?: {
|
|
22
|
+
logger?: Logger;
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* Acquires an exclusive lock on the registry file
|
|
26
|
+
*
|
|
27
|
+
* Uses mkdir as an atomic operation (works cross-platform)
|
|
28
|
+
* Waits up to LOCK_TIMEOUT_MS before failing
|
|
29
|
+
*
|
|
30
|
+
* @returns true if lock acquired, false if timeout
|
|
31
|
+
*/
|
|
32
|
+
private acquireLock;
|
|
33
|
+
/**
|
|
34
|
+
* Releases the lock on the registry file
|
|
35
|
+
*/
|
|
36
|
+
private releaseLock;
|
|
37
|
+
/**
|
|
38
|
+
* Reads the registry file with corruption recovery
|
|
39
|
+
*
|
|
40
|
+
* If registry doesn't exist, creates a new empty one
|
|
41
|
+
* If registry is corrupted (invalid JSON), creates backup and reinitializes
|
|
42
|
+
*
|
|
43
|
+
* @returns The current registry state
|
|
44
|
+
*/
|
|
45
|
+
private readRegistry;
|
|
46
|
+
/**
|
|
47
|
+
* Writes registry to disk atomically
|
|
48
|
+
*
|
|
49
|
+
* Uses temp file + rename pattern for atomic write
|
|
50
|
+
* This ensures registry is never left in a corrupted state
|
|
51
|
+
*
|
|
52
|
+
* @param registry - The registry state to write
|
|
53
|
+
*/
|
|
54
|
+
private writeRegistry;
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new empty registry
|
|
57
|
+
*/
|
|
58
|
+
private createEmptyRegistry;
|
|
59
|
+
/**
|
|
60
|
+
* Registers a new session in the registry
|
|
61
|
+
*
|
|
62
|
+
* @param sessionId - Unique session identifier
|
|
63
|
+
* @param pid - Process ID of the session
|
|
64
|
+
* @param options - Optional configuration
|
|
65
|
+
* @returns true if registration successful
|
|
66
|
+
*/
|
|
67
|
+
registerSession(sessionId: string, pid: number, options?: RegisterSessionOptions): Promise<boolean>;
|
|
68
|
+
/**
|
|
69
|
+
* Updates the heartbeat timestamp for a session
|
|
70
|
+
*
|
|
71
|
+
* @param sessionId - Session to update
|
|
72
|
+
* @returns true if update successful
|
|
73
|
+
*/
|
|
74
|
+
updateHeartbeat(sessionId: string): Promise<boolean>;
|
|
75
|
+
/**
|
|
76
|
+
* Adds a child process PID to a session
|
|
77
|
+
*
|
|
78
|
+
* @param sessionId - Parent session ID
|
|
79
|
+
* @param childPid - Child process PID to add
|
|
80
|
+
* @returns true if successful
|
|
81
|
+
*/
|
|
82
|
+
addChildProcess(sessionId: string, childPid: number): Promise<boolean>;
|
|
83
|
+
/**
|
|
84
|
+
* Removes a session from the registry
|
|
85
|
+
*
|
|
86
|
+
* @param sessionId - Session to remove
|
|
87
|
+
* @returns true if successful
|
|
88
|
+
*/
|
|
89
|
+
removeSession(sessionId: string): Promise<boolean>;
|
|
90
|
+
/**
|
|
91
|
+
* Gets a session by ID
|
|
92
|
+
*
|
|
93
|
+
* @param sessionId - Session to retrieve
|
|
94
|
+
* @returns Session info or undefined
|
|
95
|
+
*/
|
|
96
|
+
getSession(sessionId: string): Promise<SessionInfo | undefined>;
|
|
97
|
+
/**
|
|
98
|
+
* Gets all sessions
|
|
99
|
+
*
|
|
100
|
+
* @returns Array of all session info
|
|
101
|
+
*/
|
|
102
|
+
getAllSessions(): Promise<SessionInfo[]>;
|
|
103
|
+
/**
|
|
104
|
+
* Updates the status of a session
|
|
105
|
+
*
|
|
106
|
+
* @param sessionId - Session to update
|
|
107
|
+
* @param status - New status
|
|
108
|
+
* @returns true if successful
|
|
109
|
+
*/
|
|
110
|
+
updateStatus(sessionId: string, status: SessionStatus): Promise<boolean>;
|
|
111
|
+
/**
|
|
112
|
+
* Gets all stale sessions based on heartbeat threshold
|
|
113
|
+
*
|
|
114
|
+
* A session is considered stale if its last_heartbeat is older than
|
|
115
|
+
* the specified threshold.
|
|
116
|
+
*
|
|
117
|
+
* @param thresholdSeconds - Max age of last heartbeat before considered stale
|
|
118
|
+
* @returns Array of stale session info with staleness details
|
|
119
|
+
*/
|
|
120
|
+
getStaleSessions(thresholdSeconds: number): Promise<StaleSessionInfo[]>;
|
|
121
|
+
/**
|
|
122
|
+
* Cleans up old sessions based on retention period
|
|
123
|
+
*
|
|
124
|
+
* Removes sessions that have been completed or stale for longer
|
|
125
|
+
* than the retention period.
|
|
126
|
+
*
|
|
127
|
+
* @param retentionHours - How long to keep old sessions (in hours)
|
|
128
|
+
* @returns Number of sessions removed
|
|
129
|
+
*/
|
|
130
|
+
cleanupOldSessions(retentionHours: number): Promise<number>;
|
|
131
|
+
/**
|
|
132
|
+
* Checks if a PID exists (cross-platform)
|
|
133
|
+
*
|
|
134
|
+
* Uses kill -0 on Unix-like systems, which doesn't actually send a signal
|
|
135
|
+
* but checks if the process exists.
|
|
136
|
+
*
|
|
137
|
+
* @param pid - Process ID to check
|
|
138
|
+
* @returns true if process exists
|
|
139
|
+
*/
|
|
140
|
+
private checkPidExists;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=session-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-registry.d.ts","sourceRoot":"","sources":["../../../src/utils/session-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EACL,WAAW,EAEX,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAiB,MAAM,aAAa,CAAC;AAOpD,qBAAa,eAAe;IAC1B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEX,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;IAclE;;;;;;;OAOG;YACW,WAAW;IA4BzB;;OAEG;IACH,OAAO,CAAC,WAAW;IAenB;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY;IAsCpB;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;IAyBrB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAQ3B;;;;;;;OAOG;IACG,eAAe,CACnB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,OAAO,CAAC;IAuCnB;;;;;OAKG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAyB1D;;;;;;OAMG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgC5E;;;;;OAKG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAwBxD;;;;;OAKG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAcrE;;;;OAIG;IACG,cAAc,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAc9C;;;;;;OAMG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IAwB9E;;;;;;;;OAQG;IACG,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAyC7E;;;;;;;;OAQG;IACG,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgDjE;;;;;;;;OAQG;YACW,cAAc;CAuB7B"}
|
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Registry - Central tracking for all Claude Code sessions and child processes
|
|
3
|
+
*
|
|
4
|
+
* Provides atomic file-based operations for tracking active sessions, detecting
|
|
5
|
+
* stale/zombie processes, and coordinating cleanup across multiple sessions.
|
|
6
|
+
*
|
|
7
|
+
* Key Features:
|
|
8
|
+
* - Atomic operations using temp file + rename pattern
|
|
9
|
+
* - File locking via mkdir (cross-platform atomic operation)
|
|
10
|
+
* - Automatic corruption recovery with JSON validation
|
|
11
|
+
* - Concurrent-safe updates from multiple processes
|
|
12
|
+
*
|
|
13
|
+
* Registry Location: `.specweave/state/.session-registry.json`
|
|
14
|
+
*/
|
|
15
|
+
import * as fs from 'fs';
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
import { consoleLogger } from './logger.js';
|
|
18
|
+
const REGISTRY_FILENAME = '.session-registry.json';
|
|
19
|
+
const LOCK_TIMEOUT_MS = 5000; // 5 seconds max wait for lock
|
|
20
|
+
const LOCK_CHECK_INTERVAL_MS = 50; // Check lock every 50ms
|
|
21
|
+
const REGISTRY_VERSION = '1.0.0';
|
|
22
|
+
export class SessionRegistry {
|
|
23
|
+
constructor(projectRoot, options = {}) {
|
|
24
|
+
this.logger = options.logger ?? consoleLogger;
|
|
25
|
+
const stateDir = path.join(projectRoot, '.specweave', 'state');
|
|
26
|
+
// Ensure state directory exists
|
|
27
|
+
if (!fs.existsSync(stateDir)) {
|
|
28
|
+
fs.mkdirSync(stateDir, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
this.registryPath = path.join(stateDir, REGISTRY_FILENAME);
|
|
31
|
+
this.lockPath = path.join(stateDir, `${REGISTRY_FILENAME}.lock`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Acquires an exclusive lock on the registry file
|
|
35
|
+
*
|
|
36
|
+
* Uses mkdir as an atomic operation (works cross-platform)
|
|
37
|
+
* Waits up to LOCK_TIMEOUT_MS before failing
|
|
38
|
+
*
|
|
39
|
+
* @returns true if lock acquired, false if timeout
|
|
40
|
+
*/
|
|
41
|
+
async acquireLock() {
|
|
42
|
+
const startTime = Date.now();
|
|
43
|
+
while (Date.now() - startTime < LOCK_TIMEOUT_MS) {
|
|
44
|
+
try {
|
|
45
|
+
// mkdir is atomic on all platforms
|
|
46
|
+
fs.mkdirSync(this.lockPath, { recursive: false });
|
|
47
|
+
// Write our PID to lock directory for debugging
|
|
48
|
+
const lockPidFile = path.join(this.lockPath, 'pid');
|
|
49
|
+
fs.writeFileSync(lockPidFile, String(process.pid));
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
if (err.code !== 'EEXIST') {
|
|
54
|
+
this.logger.error('Failed to acquire lock:', err);
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
// Lock exists, wait and retry
|
|
58
|
+
await new Promise((resolve) => setTimeout(resolve, LOCK_CHECK_INTERVAL_MS));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
this.logger.error(`Lock acquisition timeout after ${LOCK_TIMEOUT_MS}ms`);
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Releases the lock on the registry file
|
|
66
|
+
*/
|
|
67
|
+
releaseLock() {
|
|
68
|
+
try {
|
|
69
|
+
// Remove PID file first
|
|
70
|
+
const lockPidFile = path.join(this.lockPath, 'pid');
|
|
71
|
+
if (fs.existsSync(lockPidFile)) {
|
|
72
|
+
fs.unlinkSync(lockPidFile);
|
|
73
|
+
}
|
|
74
|
+
// Remove lock directory
|
|
75
|
+
fs.rmdirSync(this.lockPath);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
this.logger.error('Failed to release lock:', err);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Reads the registry file with corruption recovery
|
|
83
|
+
*
|
|
84
|
+
* If registry doesn't exist, creates a new empty one
|
|
85
|
+
* If registry is corrupted (invalid JSON), creates backup and reinitializes
|
|
86
|
+
*
|
|
87
|
+
* @returns The current registry state
|
|
88
|
+
*/
|
|
89
|
+
readRegistry() {
|
|
90
|
+
// If registry doesn't exist, create empty one
|
|
91
|
+
if (!fs.existsSync(this.registryPath)) {
|
|
92
|
+
return this.createEmptyRegistry();
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const content = fs.readFileSync(this.registryPath, 'utf-8');
|
|
96
|
+
const registry = JSON.parse(content);
|
|
97
|
+
// Validate basic structure
|
|
98
|
+
if (!registry.sessions || typeof registry.sessions !== 'object') {
|
|
99
|
+
throw new Error('Invalid registry structure: missing sessions object');
|
|
100
|
+
}
|
|
101
|
+
if (!registry.version) {
|
|
102
|
+
// Migrate old registry without version
|
|
103
|
+
registry.version = REGISTRY_VERSION;
|
|
104
|
+
}
|
|
105
|
+
return registry;
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
this.logger.error('Registry corrupted, creating backup and reinitializing:', err);
|
|
109
|
+
// Backup corrupted registry
|
|
110
|
+
const backupPath = `${this.registryPath}.corrupted.${Date.now()}`;
|
|
111
|
+
try {
|
|
112
|
+
fs.copyFileSync(this.registryPath, backupPath);
|
|
113
|
+
this.logger.info(`Corrupted registry backed up to: ${backupPath}`);
|
|
114
|
+
}
|
|
115
|
+
catch (backupErr) {
|
|
116
|
+
this.logger.error('Failed to backup corrupted registry:', backupErr);
|
|
117
|
+
}
|
|
118
|
+
// Create new empty registry
|
|
119
|
+
return this.createEmptyRegistry();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Writes registry to disk atomically
|
|
124
|
+
*
|
|
125
|
+
* Uses temp file + rename pattern for atomic write
|
|
126
|
+
* This ensures registry is never left in a corrupted state
|
|
127
|
+
*
|
|
128
|
+
* @param registry - The registry state to write
|
|
129
|
+
*/
|
|
130
|
+
writeRegistry(registry) {
|
|
131
|
+
const tempPath = `${this.registryPath}.tmp.${process.pid}`;
|
|
132
|
+
try {
|
|
133
|
+
// Write to temp file with pretty formatting
|
|
134
|
+
fs.writeFileSync(tempPath, JSON.stringify(registry, null, 2), 'utf-8');
|
|
135
|
+
// Atomic rename (overwrites existing file)
|
|
136
|
+
fs.renameSync(tempPath, this.registryPath);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
this.logger.error('Failed to write registry:', err);
|
|
140
|
+
// Clean up temp file if it exists
|
|
141
|
+
if (fs.existsSync(tempPath)) {
|
|
142
|
+
try {
|
|
143
|
+
fs.unlinkSync(tempPath);
|
|
144
|
+
}
|
|
145
|
+
catch (cleanupErr) {
|
|
146
|
+
// Ignore cleanup errors
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
throw err;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Creates a new empty registry
|
|
154
|
+
*/
|
|
155
|
+
createEmptyRegistry() {
|
|
156
|
+
return {
|
|
157
|
+
sessions: {},
|
|
158
|
+
last_cleanup: new Date().toISOString(),
|
|
159
|
+
version: REGISTRY_VERSION,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Registers a new session in the registry
|
|
164
|
+
*
|
|
165
|
+
* @param sessionId - Unique session identifier
|
|
166
|
+
* @param pid - Process ID of the session
|
|
167
|
+
* @param options - Optional configuration
|
|
168
|
+
* @returns true if registration successful
|
|
169
|
+
*/
|
|
170
|
+
async registerSession(sessionId, pid, options = {}) {
|
|
171
|
+
const lockAcquired = await this.acquireLock();
|
|
172
|
+
if (!lockAcquired) {
|
|
173
|
+
this.logger.error('Failed to acquire lock for session registration');
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
const registry = this.readRegistry();
|
|
178
|
+
const now = new Date().toISOString();
|
|
179
|
+
// Check if session already exists
|
|
180
|
+
if (registry.sessions[sessionId]) {
|
|
181
|
+
this.logger.warn(`Session ${sessionId} already registered, updating...`);
|
|
182
|
+
}
|
|
183
|
+
// Create session entry
|
|
184
|
+
const sessionInfo = {
|
|
185
|
+
session_id: sessionId,
|
|
186
|
+
pid,
|
|
187
|
+
type: options.type ?? 'claude-code',
|
|
188
|
+
start_time: now,
|
|
189
|
+
last_heartbeat: now,
|
|
190
|
+
status: 'active',
|
|
191
|
+
child_pids: [],
|
|
192
|
+
parent_session: options.parent_session,
|
|
193
|
+
metadata: options.metadata,
|
|
194
|
+
};
|
|
195
|
+
registry.sessions[sessionId] = sessionInfo;
|
|
196
|
+
this.writeRegistry(registry);
|
|
197
|
+
this.logger.info(`Registered session: ${sessionId} (PID: ${pid})`);
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
this.releaseLock();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Updates the heartbeat timestamp for a session
|
|
206
|
+
*
|
|
207
|
+
* @param sessionId - Session to update
|
|
208
|
+
* @returns true if update successful
|
|
209
|
+
*/
|
|
210
|
+
async updateHeartbeat(sessionId) {
|
|
211
|
+
const lockAcquired = await this.acquireLock();
|
|
212
|
+
if (!lockAcquired) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
const registry = this.readRegistry();
|
|
217
|
+
const session = registry.sessions[sessionId];
|
|
218
|
+
if (!session) {
|
|
219
|
+
this.logger.error(`Session not found: ${sessionId}`);
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
session.last_heartbeat = new Date().toISOString();
|
|
223
|
+
session.status = 'active'; // Reset to active on heartbeat
|
|
224
|
+
this.writeRegistry(registry);
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
finally {
|
|
228
|
+
this.releaseLock();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Adds a child process PID to a session
|
|
233
|
+
*
|
|
234
|
+
* @param sessionId - Parent session ID
|
|
235
|
+
* @param childPid - Child process PID to add
|
|
236
|
+
* @returns true if successful
|
|
237
|
+
*/
|
|
238
|
+
async addChildProcess(sessionId, childPid) {
|
|
239
|
+
const lockAcquired = await this.acquireLock();
|
|
240
|
+
if (!lockAcquired) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
const registry = this.readRegistry();
|
|
245
|
+
const session = registry.sessions[sessionId];
|
|
246
|
+
if (!session) {
|
|
247
|
+
this.logger.error(`Session not found: ${sessionId}`);
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
if (!session.child_pids) {
|
|
251
|
+
session.child_pids = [];
|
|
252
|
+
}
|
|
253
|
+
// Avoid duplicates
|
|
254
|
+
if (!session.child_pids.includes(childPid)) {
|
|
255
|
+
session.child_pids.push(childPid);
|
|
256
|
+
this.writeRegistry(registry);
|
|
257
|
+
this.logger.info(`Added child PID ${childPid} to session ${sessionId}`);
|
|
258
|
+
}
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
finally {
|
|
262
|
+
this.releaseLock();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Removes a session from the registry
|
|
267
|
+
*
|
|
268
|
+
* @param sessionId - Session to remove
|
|
269
|
+
* @returns true if successful
|
|
270
|
+
*/
|
|
271
|
+
async removeSession(sessionId) {
|
|
272
|
+
const lockAcquired = await this.acquireLock();
|
|
273
|
+
if (!lockAcquired) {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
try {
|
|
277
|
+
const registry = this.readRegistry();
|
|
278
|
+
if (!registry.sessions[sessionId]) {
|
|
279
|
+
this.logger.warn(`Session not found for removal: ${sessionId}`);
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
delete registry.sessions[sessionId];
|
|
283
|
+
this.writeRegistry(registry);
|
|
284
|
+
this.logger.info(`Removed session: ${sessionId}`);
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
finally {
|
|
288
|
+
this.releaseLock();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Gets a session by ID
|
|
293
|
+
*
|
|
294
|
+
* @param sessionId - Session to retrieve
|
|
295
|
+
* @returns Session info or undefined
|
|
296
|
+
*/
|
|
297
|
+
async getSession(sessionId) {
|
|
298
|
+
const lockAcquired = await this.acquireLock();
|
|
299
|
+
if (!lockAcquired) {
|
|
300
|
+
return undefined;
|
|
301
|
+
}
|
|
302
|
+
try {
|
|
303
|
+
const registry = this.readRegistry();
|
|
304
|
+
return registry.sessions[sessionId];
|
|
305
|
+
}
|
|
306
|
+
finally {
|
|
307
|
+
this.releaseLock();
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Gets all sessions
|
|
312
|
+
*
|
|
313
|
+
* @returns Array of all session info
|
|
314
|
+
*/
|
|
315
|
+
async getAllSessions() {
|
|
316
|
+
const lockAcquired = await this.acquireLock();
|
|
317
|
+
if (!lockAcquired) {
|
|
318
|
+
return [];
|
|
319
|
+
}
|
|
320
|
+
try {
|
|
321
|
+
const registry = this.readRegistry();
|
|
322
|
+
return Object.values(registry.sessions);
|
|
323
|
+
}
|
|
324
|
+
finally {
|
|
325
|
+
this.releaseLock();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Updates the status of a session
|
|
330
|
+
*
|
|
331
|
+
* @param sessionId - Session to update
|
|
332
|
+
* @param status - New status
|
|
333
|
+
* @returns true if successful
|
|
334
|
+
*/
|
|
335
|
+
async updateStatus(sessionId, status) {
|
|
336
|
+
const lockAcquired = await this.acquireLock();
|
|
337
|
+
if (!lockAcquired) {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
try {
|
|
341
|
+
const registry = this.readRegistry();
|
|
342
|
+
const session = registry.sessions[sessionId];
|
|
343
|
+
if (!session) {
|
|
344
|
+
this.logger.error(`Session not found: ${sessionId}`);
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
session.status = status;
|
|
348
|
+
this.writeRegistry(registry);
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
finally {
|
|
352
|
+
this.releaseLock();
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Gets all stale sessions based on heartbeat threshold
|
|
357
|
+
*
|
|
358
|
+
* A session is considered stale if its last_heartbeat is older than
|
|
359
|
+
* the specified threshold.
|
|
360
|
+
*
|
|
361
|
+
* @param thresholdSeconds - Max age of last heartbeat before considered stale
|
|
362
|
+
* @returns Array of stale session info with staleness details
|
|
363
|
+
*/
|
|
364
|
+
async getStaleSessions(thresholdSeconds) {
|
|
365
|
+
const lockAcquired = await this.acquireLock();
|
|
366
|
+
if (!lockAcquired) {
|
|
367
|
+
return [];
|
|
368
|
+
}
|
|
369
|
+
try {
|
|
370
|
+
const registry = this.readRegistry();
|
|
371
|
+
const now = Date.now();
|
|
372
|
+
const staleSessions = [];
|
|
373
|
+
for (const session of Object.values(registry.sessions)) {
|
|
374
|
+
const lastHeartbeat = new Date(session.last_heartbeat).getTime();
|
|
375
|
+
const ageSec = (now - lastHeartbeat) / 1000;
|
|
376
|
+
if (ageSec > thresholdSeconds) {
|
|
377
|
+
// Check if PID still exists (cross-platform)
|
|
378
|
+
const pidExists = await this.checkPidExists(session.pid);
|
|
379
|
+
staleSessions.push({
|
|
380
|
+
session,
|
|
381
|
+
stale_duration_seconds: ageSec,
|
|
382
|
+
pid_exists: pidExists,
|
|
383
|
+
});
|
|
384
|
+
// Mark session as stale
|
|
385
|
+
session.status = 'stale';
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// Update registry with stale statuses
|
|
389
|
+
if (staleSessions.length > 0) {
|
|
390
|
+
this.writeRegistry(registry);
|
|
391
|
+
}
|
|
392
|
+
return staleSessions;
|
|
393
|
+
}
|
|
394
|
+
finally {
|
|
395
|
+
this.releaseLock();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Cleans up old sessions based on retention period
|
|
400
|
+
*
|
|
401
|
+
* Removes sessions that have been completed or stale for longer
|
|
402
|
+
* than the retention period.
|
|
403
|
+
*
|
|
404
|
+
* @param retentionHours - How long to keep old sessions (in hours)
|
|
405
|
+
* @returns Number of sessions removed
|
|
406
|
+
*/
|
|
407
|
+
async cleanupOldSessions(retentionHours) {
|
|
408
|
+
const lockAcquired = await this.acquireLock();
|
|
409
|
+
if (!lockAcquired) {
|
|
410
|
+
return 0;
|
|
411
|
+
}
|
|
412
|
+
try {
|
|
413
|
+
const registry = this.readRegistry();
|
|
414
|
+
const now = Date.now();
|
|
415
|
+
const retentionMs = retentionHours * 60 * 60 * 1000;
|
|
416
|
+
const sessionsToRemove = [];
|
|
417
|
+
for (const [sessionId, session] of Object.entries(registry.sessions)) {
|
|
418
|
+
// Only clean up completed or stale sessions
|
|
419
|
+
if (session.status !== 'completed' && session.status !== 'stale') {
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
// Check age based on last_heartbeat
|
|
423
|
+
const lastActivity = new Date(session.last_heartbeat).getTime();
|
|
424
|
+
const ageMs = now - lastActivity;
|
|
425
|
+
if (ageMs > retentionMs) {
|
|
426
|
+
sessionsToRemove.push(sessionId);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
// Remove old sessions
|
|
430
|
+
for (const sessionId of sessionsToRemove) {
|
|
431
|
+
delete registry.sessions[sessionId];
|
|
432
|
+
this.logger.info(`Cleaned up old session: ${sessionId} (age: ${Math.floor((now - new Date(registry.sessions[sessionId]?.last_heartbeat || now).getTime()) / 3600000)}h)`);
|
|
433
|
+
}
|
|
434
|
+
// Update last_cleanup timestamp
|
|
435
|
+
registry.last_cleanup = new Date().toISOString();
|
|
436
|
+
if (sessionsToRemove.length > 0) {
|
|
437
|
+
this.writeRegistry(registry);
|
|
438
|
+
}
|
|
439
|
+
return sessionsToRemove.length;
|
|
440
|
+
}
|
|
441
|
+
finally {
|
|
442
|
+
this.releaseLock();
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Checks if a PID exists (cross-platform)
|
|
447
|
+
*
|
|
448
|
+
* Uses kill -0 on Unix-like systems, which doesn't actually send a signal
|
|
449
|
+
* but checks if the process exists.
|
|
450
|
+
*
|
|
451
|
+
* @param pid - Process ID to check
|
|
452
|
+
* @returns true if process exists
|
|
453
|
+
*/
|
|
454
|
+
async checkPidExists(pid) {
|
|
455
|
+
try {
|
|
456
|
+
// On Unix-like systems (macOS, Linux), kill -0 checks process existence
|
|
457
|
+
// without actually sending a signal
|
|
458
|
+
if (process.platform === 'win32') {
|
|
459
|
+
// Windows: use tasklist
|
|
460
|
+
const { execSync } = await import('child_process');
|
|
461
|
+
const output = execSync(`tasklist /FI "PID eq ${pid}" /NH`, {
|
|
462
|
+
encoding: 'utf-8',
|
|
463
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
464
|
+
});
|
|
465
|
+
return output.includes(String(pid));
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
// Unix-like (macOS, Linux)
|
|
469
|
+
const { execSync } = await import('child_process');
|
|
470
|
+
execSync(`kill -0 ${pid}`, { stdio: 'ignore' });
|
|
471
|
+
return true;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
catch {
|
|
475
|
+
// Process doesn't exist or we don't have permission
|
|
476
|
+
return false;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
//# sourceMappingURL=session-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-registry.js","sourceRoot":"","sources":["../../../src/utils/session-registry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specweave",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.3",
|
|
4
4
|
"description": "Spec-driven development framework for Claude Code. AI-native workflow with living documentation, intelligent agents, and multilingual support (9 languages). Enterprise-grade traceability with permanent specs and temporary increments.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -19,9 +19,12 @@
|
|
|
19
19
|
"prepublishOnly": "npm run rebuild",
|
|
20
20
|
"test:unit": "vitest run tests/unit --coverage",
|
|
21
21
|
"test:integration": "vitest run tests/integration --coverage",
|
|
22
|
+
"test:lifecycle": "npm run test:unit && npm run test:integration",
|
|
23
|
+
"test:e2e:lifecycle": "vitest run tests/e2e/normal-session-lifecycle.e2e.ts tests/e2e/crash-recovery.e2e.ts tests/e2e/multiple-sessions.e2e.ts",
|
|
24
|
+
"test:performance": "ts-node tests/performance/session-registry-bench.ts && bash tests/performance/heartbeat-overhead-bench.sh && ts-node tests/performance/compare-to-baseline.ts",
|
|
22
25
|
"test:smoke": "bash tests/smoke/smoke-test.sh",
|
|
23
26
|
"test:e2e": "playwright test tests/e2e/ --grep-invert=\"(should default to claude adapter|should use claude adapter when explicitly requested|should use generic adapter|should create .claude|should initialize project with specweave init|should create correct directory structure|should handle non-interactive mode correctly|should validate config.json structure|should create .specweave directory structure|should create CLAUDE.md and AGENTS.md|should initialize git repository|should install SpecWeave|should scaffold SaaS|should create proper directory|should create required configuration|should install core skills|should install core agents|should have deployment|should have Stripe|ADO Sync|Increment Discipline Blocking|Self-Reflection|Increment Discipline Enforcement)\"",
|
|
24
|
-
"test:all": "npm run test:unit && npm run test:integration && npm run test:e2e",
|
|
27
|
+
"test:all": "npm run test:unit && npm run test:integration && npm run test:e2e && npm run test:e2e:lifecycle",
|
|
25
28
|
"test:coverage": "vitest run --coverage",
|
|
26
29
|
"test": "npm run test:smoke",
|
|
27
30
|
"benchmark": "ts-node tests/performance/run-all-benchmarks.ts",
|