agileflow 2.95.2 → 2.96.0

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 (81) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +6 -6
  3. package/lib/api-routes.js +605 -0
  4. package/lib/api-server.js +260 -0
  5. package/lib/claude-cli-bridge.js +221 -0
  6. package/lib/dashboard-protocol.js +541 -0
  7. package/lib/dashboard-server.js +1601 -0
  8. package/lib/drivers/claude-driver.ts +310 -0
  9. package/lib/drivers/codex-driver.ts +454 -0
  10. package/lib/drivers/driver-manager.ts +158 -0
  11. package/lib/drivers/gemini-driver.ts +485 -0
  12. package/lib/drivers/index.ts +17 -0
  13. package/lib/flag-detection.js +350 -0
  14. package/lib/git-operations.js +267 -0
  15. package/lib/lock-file.js +144 -0
  16. package/lib/merge-operations.js +959 -0
  17. package/lib/protocol/driver.ts +360 -0
  18. package/lib/protocol/index.ts +12 -0
  19. package/lib/protocol/ir.ts +271 -0
  20. package/lib/session-display.js +330 -0
  21. package/lib/worktree-operations.js +221 -0
  22. package/package.json +2 -2
  23. package/scripts/agileflow-welcome.js +272 -24
  24. package/scripts/api-server-runner.js +177 -0
  25. package/scripts/archive-completed-stories.sh +22 -0
  26. package/scripts/automation-run-due.js +126 -0
  27. package/scripts/backfill-ideation-status.js +124 -0
  28. package/scripts/claude-tmux.sh +62 -1
  29. package/scripts/context-loader.js +292 -0
  30. package/scripts/dashboard-serve.js +323 -0
  31. package/scripts/lib/automation-registry.js +544 -0
  32. package/scripts/lib/automation-runner.js +476 -0
  33. package/scripts/lib/concurrency-limiter.js +513 -0
  34. package/scripts/lib/configure-features.js +46 -0
  35. package/scripts/lib/context-formatter.js +61 -0
  36. package/scripts/lib/damage-control-utils.js +29 -4
  37. package/scripts/lib/hook-metrics.js +324 -0
  38. package/scripts/lib/ideation-index.js +1196 -0
  39. package/scripts/lib/process-cleanup.js +359 -0
  40. package/scripts/lib/quality-gates.js +574 -0
  41. package/scripts/lib/status-task-bridge.js +522 -0
  42. package/scripts/lib/sync-ideation-status.js +292 -0
  43. package/scripts/lib/task-registry-cache.js +490 -0
  44. package/scripts/lib/task-registry.js +1181 -0
  45. package/scripts/migrate-ideation-index.js +515 -0
  46. package/scripts/precompact-context.sh +104 -0
  47. package/scripts/ralph-loop.js +2 -2
  48. package/scripts/session-manager.js +363 -2770
  49. package/scripts/spawn-parallel.js +45 -9
  50. package/src/core/agents/api-validator.md +180 -0
  51. package/src/core/agents/api.md +2 -0
  52. package/src/core/agents/code-reviewer.md +289 -0
  53. package/src/core/agents/configuration/damage-control.md +17 -0
  54. package/src/core/agents/database.md +2 -0
  55. package/src/core/agents/error-analyzer.md +203 -0
  56. package/src/core/agents/logic-analyzer-edge.md +171 -0
  57. package/src/core/agents/logic-analyzer-flow.md +254 -0
  58. package/src/core/agents/logic-analyzer-invariant.md +207 -0
  59. package/src/core/agents/logic-analyzer-race.md +267 -0
  60. package/src/core/agents/logic-analyzer-type.md +218 -0
  61. package/src/core/agents/logic-consensus.md +256 -0
  62. package/src/core/agents/orchestrator.md +89 -1
  63. package/src/core/agents/schema-validator.md +451 -0
  64. package/src/core/agents/team-coordinator.md +328 -0
  65. package/src/core/agents/ui-validator.md +328 -0
  66. package/src/core/agents/ui.md +2 -0
  67. package/src/core/commands/api.md +267 -0
  68. package/src/core/commands/automate.md +415 -0
  69. package/src/core/commands/babysit.md +290 -9
  70. package/src/core/commands/ideate/history.md +403 -0
  71. package/src/core/commands/{ideate.md → ideate/new.md} +244 -34
  72. package/src/core/commands/logic/audit.md +368 -0
  73. package/src/core/commands/roadmap/analyze.md +1 -1
  74. package/src/core/experts/documentation/expertise.yaml +29 -2
  75. package/src/core/templates/CONTEXT.md.example +49 -0
  76. package/src/core/templates/claude-settings.advanced.example.json +4 -0
  77. package/tools/cli/commands/serve.js +456 -0
  78. package/tools/cli/installers/core/installer.js +7 -2
  79. package/tools/cli/installers/ide/claude-code.js +85 -0
  80. package/tools/cli/lib/content-injector.js +27 -1
  81. package/tools/cli/lib/ui.js +26 -57
@@ -0,0 +1,144 @@
1
+ /**
2
+ * lock-file.js - Lock file operations for session management
3
+ *
4
+ * Manages session lock files for PID-based liveness detection.
5
+ * Lock files use a simple key-value format: pid=12345\nstarted=1706825600
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ /**
12
+ * Parse lock file content into an object
13
+ * @param {string} content - Raw lock file content
14
+ * @returns {Object} Parsed key-value pairs
15
+ */
16
+ function parseLockContent(content) {
17
+ const lock = {};
18
+ content.split('\n').forEach(line => {
19
+ const [key, value] = line.split('=');
20
+ if (key && value) {
21
+ lock[key.trim()] = value.trim();
22
+ }
23
+ });
24
+ return lock;
25
+ }
26
+
27
+ /**
28
+ * Get lock file path for a session
29
+ * @param {string} sessionsDir - Sessions directory path
30
+ * @param {string} sessionId - Session identifier
31
+ * @returns {string} Full path to lock file
32
+ */
33
+ function getLockPath(sessionsDir, sessionId) {
34
+ return path.join(sessionsDir, `${sessionId}.lock`);
35
+ }
36
+
37
+ /**
38
+ * Read lock file synchronously
39
+ * @param {string} sessionsDir - Sessions directory path
40
+ * @param {string} sessionId - Session identifier
41
+ * @returns {Object|null} Parsed lock data or null if not found
42
+ */
43
+ function readLock(sessionsDir, sessionId) {
44
+ const lockPath = getLockPath(sessionsDir, sessionId);
45
+ if (!fs.existsSync(lockPath)) return null;
46
+
47
+ try {
48
+ const content = fs.readFileSync(lockPath, 'utf8');
49
+ return parseLockContent(content);
50
+ } catch (e) {
51
+ return null;
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Read lock file asynchronously
57
+ * @param {string} sessionsDir - Sessions directory path
58
+ * @param {string} sessionId - Session identifier
59
+ * @returns {Promise<Object|null>} Parsed lock data or null if not found
60
+ */
61
+ async function readLockAsync(sessionsDir, sessionId) {
62
+ const lockPath = getLockPath(sessionsDir, sessionId);
63
+ try {
64
+ const content = await fs.promises.readFile(lockPath, 'utf8');
65
+ return parseLockContent(content);
66
+ } catch (e) {
67
+ return null;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Write lock file for a session
73
+ * @param {string} sessionsDir - Sessions directory path
74
+ * @param {string} sessionId - Session identifier
75
+ * @param {number} pid - Process ID to record
76
+ */
77
+ function writeLock(sessionsDir, sessionId, pid) {
78
+ const lockPath = getLockPath(sessionsDir, sessionId);
79
+ const content = `pid=${pid}\nstarted=${Math.floor(Date.now() / 1000)}\n`;
80
+ fs.writeFileSync(lockPath, content);
81
+ }
82
+
83
+ /**
84
+ * Remove lock file for a session
85
+ * @param {string} sessionsDir - Sessions directory path
86
+ * @param {string} sessionId - Session identifier
87
+ */
88
+ function removeLock(sessionsDir, sessionId) {
89
+ const lockPath = getLockPath(sessionsDir, sessionId);
90
+ if (fs.existsSync(lockPath)) {
91
+ fs.unlinkSync(lockPath);
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Check if a PID is alive
97
+ * @param {number} pid - Process ID to check
98
+ * @returns {boolean} True if process is alive
99
+ */
100
+ function isPidAlive(pid) {
101
+ if (!pid) return false;
102
+ try {
103
+ process.kill(pid, 0);
104
+ return true;
105
+ } catch (e) {
106
+ return false;
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Check if session is active (has lock with alive PID)
112
+ * @param {string} sessionsDir - Sessions directory path
113
+ * @param {string} sessionId - Session identifier
114
+ * @returns {boolean} True if session is active
115
+ */
116
+ function isSessionActive(sessionsDir, sessionId) {
117
+ const lock = readLock(sessionsDir, sessionId);
118
+ if (!lock || !lock.pid) return false;
119
+ return isPidAlive(parseInt(lock.pid, 10));
120
+ }
121
+
122
+ /**
123
+ * Check if session is active asynchronously
124
+ * @param {string} sessionsDir - Sessions directory path
125
+ * @param {string} sessionId - Session identifier
126
+ * @returns {Promise<boolean>} True if session is active
127
+ */
128
+ async function isSessionActiveAsync(sessionsDir, sessionId) {
129
+ const lock = await readLockAsync(sessionsDir, sessionId);
130
+ if (!lock || !lock.pid) return false;
131
+ return isPidAlive(parseInt(lock.pid, 10));
132
+ }
133
+
134
+ module.exports = {
135
+ parseLockContent,
136
+ getLockPath,
137
+ readLock,
138
+ readLockAsync,
139
+ writeLock,
140
+ removeLock,
141
+ isPidAlive,
142
+ isSessionActive,
143
+ isSessionActiveAsync,
144
+ };