forge-cc 1.0.0 → 1.0.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.
Files changed (144) hide show
  1. package/dist/cli.js +7 -1
  2. package/dist/cli.js.map +1 -1
  3. package/package.json +3 -2
  4. package/dist/gates/codex-gate.d.ts +0 -51
  5. package/dist/gates/codex-gate.js +0 -121
  6. package/dist/gates/codex-gate.js.map +0 -1
  7. package/dist/gates/prd-gate.d.ts +0 -7
  8. package/dist/gates/prd-gate.js +0 -193
  9. package/dist/gates/prd-gate.js.map +0 -1
  10. package/dist/gates/remediation.d.ts +0 -46
  11. package/dist/gates/remediation.js +0 -423
  12. package/dist/gates/remediation.js.map +0 -1
  13. package/dist/gates/review-gate.d.ts +0 -16
  14. package/dist/gates/review-gate.js +0 -479
  15. package/dist/gates/review-gate.js.map +0 -1
  16. package/dist/gates/runtime-gate.d.ts +0 -5
  17. package/dist/gates/runtime-gate.js +0 -99
  18. package/dist/gates/runtime-gate.js.map +0 -1
  19. package/dist/gates/test-analysis.d.ts +0 -21
  20. package/dist/gates/test-analysis.js +0 -394
  21. package/dist/gates/test-analysis.js.map +0 -1
  22. package/dist/gates/visual-capture.d.ts +0 -24
  23. package/dist/gates/visual-capture.js +0 -144
  24. package/dist/gates/visual-capture.js.map +0 -1
  25. package/dist/gates/visual-gate.d.ts +0 -18
  26. package/dist/gates/visual-gate.js +0 -234
  27. package/dist/gates/visual-gate.js.map +0 -1
  28. package/dist/gates/visual-reviewer.d.ts +0 -11
  29. package/dist/gates/visual-reviewer.js +0 -211
  30. package/dist/gates/visual-reviewer.js.map +0 -1
  31. package/dist/go/auto-chain.d.ts +0 -136
  32. package/dist/go/auto-chain.js +0 -389
  33. package/dist/go/auto-chain.js.map +0 -1
  34. package/dist/go/executor.d.ts +0 -137
  35. package/dist/go/executor.js +0 -447
  36. package/dist/go/executor.js.map +0 -1
  37. package/dist/go/finalize.d.ts +0 -108
  38. package/dist/go/finalize.js +0 -331
  39. package/dist/go/finalize.js.map +0 -1
  40. package/dist/go/linear-sync-cli.d.ts +0 -55
  41. package/dist/go/linear-sync-cli.js +0 -192
  42. package/dist/go/linear-sync-cli.js.map +0 -1
  43. package/dist/go/linear-sync.d.ts +0 -112
  44. package/dist/go/linear-sync.js +0 -375
  45. package/dist/go/linear-sync.js.map +0 -1
  46. package/dist/go/prd-queue.d.ts +0 -43
  47. package/dist/go/prd-queue.js +0 -67
  48. package/dist/go/prd-queue.js.map +0 -1
  49. package/dist/go/prd-selector.d.ts +0 -57
  50. package/dist/go/prd-selector.js +0 -101
  51. package/dist/go/prd-selector.js.map +0 -1
  52. package/dist/go/verify-loop.d.ts +0 -64
  53. package/dist/go/verify-loop.js +0 -327
  54. package/dist/go/verify-loop.js.map +0 -1
  55. package/dist/hooks/pre-commit.d.ts +0 -5
  56. package/dist/hooks/pre-commit.js +0 -75
  57. package/dist/hooks/pre-commit.js.map +0 -1
  58. package/dist/linear/issues.d.ts +0 -22
  59. package/dist/linear/issues.js +0 -51
  60. package/dist/linear/issues.js.map +0 -1
  61. package/dist/linear/milestones.d.ts +0 -11
  62. package/dist/linear/milestones.js +0 -32
  63. package/dist/linear/milestones.js.map +0 -1
  64. package/dist/linear/projects.d.ts +0 -16
  65. package/dist/linear/projects.js +0 -51
  66. package/dist/linear/projects.js.map +0 -1
  67. package/dist/reporter/human.d.ts +0 -7
  68. package/dist/reporter/human.js +0 -93
  69. package/dist/reporter/human.js.map +0 -1
  70. package/dist/reporter/json.d.ts +0 -2
  71. package/dist/reporter/json.js +0 -4
  72. package/dist/reporter/json.js.map +0 -1
  73. package/dist/setup/structural-templates.d.ts +0 -12
  74. package/dist/setup/structural-templates.js +0 -288
  75. package/dist/setup/structural-templates.js.map +0 -1
  76. package/dist/setup/templates.d.ts +0 -17
  77. package/dist/setup/templates.js +0 -109
  78. package/dist/setup/templates.js.map +0 -1
  79. package/dist/setup/test-planner.d.ts +0 -38
  80. package/dist/setup/test-planner.js +0 -91
  81. package/dist/setup/test-planner.js.map +0 -1
  82. package/dist/setup/test-scaffold.d.ts +0 -31
  83. package/dist/setup/test-scaffold.js +0 -209
  84. package/dist/setup/test-scaffold.js.map +0 -1
  85. package/dist/setup/test-templates.d.ts +0 -37
  86. package/dist/setup/test-templates.js +0 -313
  87. package/dist/setup/test-templates.js.map +0 -1
  88. package/dist/spec/generator.d.ts +0 -34
  89. package/dist/spec/generator.js +0 -227
  90. package/dist/spec/generator.js.map +0 -1
  91. package/dist/spec/interview.d.ts +0 -142
  92. package/dist/spec/interview.js +0 -287
  93. package/dist/spec/interview.js.map +0 -1
  94. package/dist/spec/linear-sync.d.ts +0 -48
  95. package/dist/spec/linear-sync.js +0 -125
  96. package/dist/spec/linear-sync.js.map +0 -1
  97. package/dist/spec/scanner.d.ts +0 -79
  98. package/dist/spec/scanner.js +0 -566
  99. package/dist/spec/scanner.js.map +0 -1
  100. package/dist/spec/templates.d.ts +0 -375
  101. package/dist/spec/templates.js +0 -95
  102. package/dist/spec/templates.js.map +0 -1
  103. package/dist/state/prd-status.d.ts +0 -62
  104. package/dist/state/prd-status.js +0 -122
  105. package/dist/state/prd-status.js.map +0 -1
  106. package/dist/state/reader.d.ts +0 -7
  107. package/dist/state/reader.js +0 -43
  108. package/dist/state/reader.js.map +0 -1
  109. package/dist/state/writer.d.ts +0 -21
  110. package/dist/state/writer.js +0 -106
  111. package/dist/state/writer.js.map +0 -1
  112. package/dist/team/consensus.d.ts +0 -28
  113. package/dist/team/consensus.js +0 -130
  114. package/dist/team/consensus.js.map +0 -1
  115. package/dist/team/index.d.ts +0 -4
  116. package/dist/team/index.js +0 -5
  117. package/dist/team/index.js.map +0 -1
  118. package/dist/team/lifecycle.d.ts +0 -37
  119. package/dist/team/lifecycle.js +0 -92
  120. package/dist/team/lifecycle.js.map +0 -1
  121. package/dist/team/reviewer.d.ts +0 -10
  122. package/dist/team/reviewer.js +0 -345
  123. package/dist/team/reviewer.js.map +0 -1
  124. package/dist/team/types.d.ts +0 -269
  125. package/dist/team/types.js +0 -70
  126. package/dist/team/types.js.map +0 -1
  127. package/dist/utils/browser.d.ts +0 -10
  128. package/dist/utils/browser.js +0 -96
  129. package/dist/utils/browser.js.map +0 -1
  130. package/dist/utils/platform.d.ts +0 -29
  131. package/dist/utils/platform.js +0 -90
  132. package/dist/utils/platform.js.map +0 -1
  133. package/dist/worktree/identity.d.ts +0 -9
  134. package/dist/worktree/identity.js +0 -32
  135. package/dist/worktree/identity.js.map +0 -1
  136. package/dist/worktree/parallel.d.ts +0 -87
  137. package/dist/worktree/parallel.js +0 -328
  138. package/dist/worktree/parallel.js.map +0 -1
  139. package/dist/worktree/session.d.ts +0 -67
  140. package/dist/worktree/session.js +0 -194
  141. package/dist/worktree/session.js.map +0 -1
  142. package/dist/worktree/state-merge.d.ts +0 -43
  143. package/dist/worktree/state-merge.js +0 -162
  144. package/dist/worktree/state-merge.js.map +0 -1
@@ -1,328 +0,0 @@
1
- /**
2
- * Parallel Scheduler — Milestone Dependency Analyzer & Execution Planner
3
- *
4
- * Parses `dependsOn` from PRD milestones, builds a DAG, determines which
5
- * milestones can run simultaneously in parallel waves, and provides
6
- * functions to query ready milestones given completed set.
7
- *
8
- * Backward compatible: milestones without `dependsOn` are treated as
9
- * having no dependencies (roots).
10
- */
11
- import { readFile } from "node:fs/promises";
12
- // ---------------------------------------------------------------------------
13
- // buildDAG
14
- // ---------------------------------------------------------------------------
15
- /**
16
- * Build a directed acyclic graph from milestone dependencies.
17
- *
18
- * Validates:
19
- * - All referenced dependencies exist in the milestone set
20
- * - No cycles exist in the dependency graph
21
- *
22
- * Throws descriptive errors on validation failure.
23
- */
24
- export function buildDAG(milestones) {
25
- const dag = new Map();
26
- const milestoneNumbers = new Set(milestones.map((m) => m.number));
27
- // Initialize all nodes
28
- for (const milestone of milestones) {
29
- dag.set(milestone.number, {
30
- milestone,
31
- children: [],
32
- parents: [...milestone.dependsOn],
33
- depth: -1, // computed later
34
- });
35
- }
36
- // Validate dependencies exist and build children links
37
- for (const milestone of milestones) {
38
- for (const dep of milestone.dependsOn) {
39
- if (!milestoneNumbers.has(dep)) {
40
- throw new Error(`Milestone ${milestone.number} ("${milestone.name}") depends on milestone ${dep}, which does not exist`);
41
- }
42
- const parentNode = dag.get(dep);
43
- parentNode.children.push(milestone.number);
44
- }
45
- }
46
- // Detect cycles using DFS with coloring (white/gray/black)
47
- detectCycles(dag);
48
- // Compute depths via BFS from roots
49
- computeDepths(dag);
50
- return dag;
51
- }
52
- /**
53
- * Detect cycles in the DAG using DFS with three-color marking.
54
- * Throws an error with a descriptive message if a cycle is found.
55
- */
56
- function detectCycles(dag) {
57
- const WHITE = 0; // unvisited
58
- const GRAY = 1; // in current DFS path
59
- const BLACK = 2; // fully processed
60
- const color = new Map();
61
- for (const num of dag.keys()) {
62
- color.set(num, WHITE);
63
- }
64
- const path = [];
65
- function dfs(nodeNum) {
66
- color.set(nodeNum, GRAY);
67
- path.push(nodeNum);
68
- const node = dag.get(nodeNum);
69
- for (const childNum of node.children) {
70
- const childColor = color.get(childNum);
71
- if (childColor === GRAY) {
72
- // Found a cycle — extract the cycle path for the error message
73
- const cycleStart = path.indexOf(childNum);
74
- const cyclePath = path.slice(cycleStart);
75
- cyclePath.push(childNum); // close the cycle
76
- const cycleStr = cyclePath
77
- .map((n) => {
78
- const m = dag.get(n).milestone;
79
- return `M${m.number}("${m.name}")`;
80
- })
81
- .join(" -> ");
82
- throw new Error(`Dependency cycle detected: ${cycleStr}`);
83
- }
84
- if (childColor === WHITE) {
85
- dfs(childNum);
86
- }
87
- }
88
- color.set(nodeNum, BLACK);
89
- path.pop();
90
- }
91
- for (const num of dag.keys()) {
92
- if (color.get(num) === WHITE) {
93
- dfs(num);
94
- }
95
- }
96
- }
97
- /**
98
- * Compute depth for each node via BFS from roots (nodes with no parents).
99
- * Depth = longest path from any root to this node.
100
- */
101
- function computeDepths(dag) {
102
- // Find roots (no parents)
103
- const roots = [];
104
- for (const [num, node] of dag) {
105
- if (node.parents.length === 0) {
106
- roots.push(num);
107
- }
108
- }
109
- // BFS-like traversal computing max depth
110
- // Use Kahn's algorithm approach: process nodes whose all parents are resolved
111
- const depth = new Map();
112
- const inDegree = new Map();
113
- for (const [num, node] of dag) {
114
- inDegree.set(num, node.parents.length);
115
- }
116
- const queue = [];
117
- for (const root of roots) {
118
- depth.set(root, 0);
119
- queue.push(root);
120
- }
121
- while (queue.length > 0) {
122
- const current = queue.shift();
123
- const currentDepth = depth.get(current);
124
- const node = dag.get(current);
125
- node.depth = currentDepth;
126
- for (const childNum of node.children) {
127
- const childDepth = depth.get(childNum);
128
- // Set child depth to max of current paths
129
- if (childDepth === undefined || currentDepth + 1 > childDepth) {
130
- depth.set(childNum, currentDepth + 1);
131
- }
132
- // Decrement in-degree; enqueue when all parents processed
133
- const remaining = inDegree.get(childNum) - 1;
134
- inDegree.set(childNum, remaining);
135
- if (remaining === 0) {
136
- queue.push(childNum);
137
- }
138
- }
139
- }
140
- }
141
- // ---------------------------------------------------------------------------
142
- // computeExecutionWaves
143
- // ---------------------------------------------------------------------------
144
- /**
145
- * Topological sort milestones into parallel execution waves.
146
- *
147
- * - Wave 1: all milestones with no dependencies (roots)
148
- * - Wave 2: milestones whose dependencies are all in Wave 1
149
- * - Wave N: milestones whose dependencies are all in waves < N
150
- */
151
- export function computeExecutionWaves(dag) {
152
- if (dag.size === 0) {
153
- return {
154
- waves: [],
155
- totalMilestones: 0,
156
- maxParallelism: 0,
157
- isSequential: true,
158
- };
159
- }
160
- // Group milestones by depth — depth corresponds to wave number
161
- const waveMap = new Map();
162
- for (const [num, node] of dag) {
163
- const d = node.depth;
164
- if (!waveMap.has(d)) {
165
- waveMap.set(d, []);
166
- }
167
- waveMap.get(d).push(num);
168
- }
169
- // Sort wave keys and build ExecutionWave array
170
- const sortedDepths = [...waveMap.keys()].sort((a, b) => a - b);
171
- const waves = sortedDepths.map((depth, index) => ({
172
- waveNumber: index + 1,
173
- milestones: waveMap.get(depth).sort((a, b) => a - b),
174
- }));
175
- const maxParallelism = Math.max(...waves.map((w) => w.milestones.length));
176
- const isSequential = maxParallelism <= 1;
177
- return {
178
- waves,
179
- totalMilestones: dag.size,
180
- maxParallelism,
181
- isSequential,
182
- };
183
- }
184
- // ---------------------------------------------------------------------------
185
- // parseMilestoneDependencies
186
- // ---------------------------------------------------------------------------
187
- /**
188
- * Parse a PRD markdown document to extract milestone definitions and
189
- * their `dependsOn` fields.
190
- *
191
- * Looks for milestone headers like:
192
- * ### Milestone 1: Name Here
193
- * ### Milestone 2 — Name Here
194
- *
195
- * And within each milestone section, looks for:
196
- * **dependsOn:** 1, 3
197
- * dependsOn: [1, 3]
198
- * **dependsOn:** [1]
199
- *
200
- * If no `dependsOn` field is found, treats the milestone as having no
201
- * dependencies (backward compatible).
202
- */
203
- export function parseMilestoneDependencies(prdContent) {
204
- const milestones = [];
205
- // Split PRD into milestone sections
206
- // Match headers like: ### Milestone 1: Name or ### Milestone 1 — Name
207
- const milestoneHeaderRe = /###\s*Milestone\s+(\d+)\s*[:\—–-]\s*(.+)/g;
208
- const headers = [];
209
- let headerMatch;
210
- while ((headerMatch = milestoneHeaderRe.exec(prdContent)) !== null) {
211
- headers.push({
212
- number: parseInt(headerMatch[1], 10),
213
- name: headerMatch[2].trim(),
214
- index: headerMatch.index,
215
- });
216
- }
217
- // Extract section content for each milestone
218
- for (let i = 0; i < headers.length; i++) {
219
- const header = headers[i];
220
- const sectionStart = header.index;
221
- const sectionEnd = i + 1 < headers.length ? headers[i + 1].index : prdContent.length;
222
- const sectionContent = prdContent.slice(sectionStart, sectionEnd);
223
- // Look for dependsOn field in the section
224
- const dependsOn = parseDependsOnField(sectionContent);
225
- milestones.push({
226
- number: header.number,
227
- name: header.name,
228
- dependsOn,
229
- });
230
- }
231
- return milestones;
232
- }
233
- /**
234
- * Parse the dependsOn field from a milestone section.
235
- * Supports formats:
236
- * **dependsOn:** 1, 3
237
- * dependsOn: [1, 3]
238
- * **dependsOn:** [1]
239
- * **dependsOn:** none
240
- *
241
- * Returns empty array if not found or explicitly "none".
242
- */
243
- function parseDependsOnField(sectionContent) {
244
- // Match patterns like:
245
- // **dependsOn:** 1, 3 (bold markdown: ** before key, :** after)
246
- // dependsOn: [1, 3] (plain text)
247
- // **dependsOn:** [1] (bold with brackets)
248
- const dependsOnRe = /\*{0,2}dependsOn:\*{0,2}\s*(.+)/i;
249
- const match = sectionContent.match(dependsOnRe);
250
- if (!match) {
251
- return [];
252
- }
253
- const value = match[1].trim();
254
- // Handle "none" or empty
255
- if (value.toLowerCase() === "none" ||
256
- value === "[]" ||
257
- value === "" ||
258
- value === "-") {
259
- return [];
260
- }
261
- // Strip brackets if present: [1, 3] -> 1, 3
262
- const stripped = value.replace(/^\[/, "").replace(/\].*$/, "");
263
- // Parse comma-separated numbers
264
- const numbers = [];
265
- for (const part of stripped.split(",")) {
266
- const trimmed = part.trim();
267
- const num = parseInt(trimmed, 10);
268
- if (!isNaN(num)) {
269
- numbers.push(num);
270
- }
271
- }
272
- return numbers;
273
- }
274
- // ---------------------------------------------------------------------------
275
- // getReadyMilestones
276
- // ---------------------------------------------------------------------------
277
- /**
278
- * Given execution waves and a set of completed milestone numbers,
279
- * return which milestones are ready to start.
280
- *
281
- * A milestone is ready if:
282
- * 1. It has not been completed yet
283
- * 2. All of its dependencies (from the wave schedule) are in the completed set
284
- *
285
- * This requires the original DAG to check dependencies, so we accept
286
- * the waves plus the DAG.
287
- */
288
- export function getReadyMilestones(dag, completed) {
289
- const ready = [];
290
- for (const [num, node] of dag) {
291
- // Skip already completed
292
- if (completed.has(num)) {
293
- continue;
294
- }
295
- // Check if all parents are completed
296
- const allParentsCompleted = node.parents.every((p) => completed.has(p));
297
- if (allParentsCompleted) {
298
- ready.push(num);
299
- }
300
- }
301
- return ready.sort((a, b) => a - b);
302
- }
303
- // ---------------------------------------------------------------------------
304
- // buildScheduleFromPRD — convenience function
305
- // ---------------------------------------------------------------------------
306
- /**
307
- * Parse a PRD file and build the full execution schedule.
308
- * Combines parseMilestoneDependencies + buildDAG + computeExecutionWaves.
309
- *
310
- * If the PRD has no `dependsOn` fields, all milestones will be in wave 1
311
- * (all roots), which is backward compatible with sequential execution
312
- * when the caller processes them in milestone-number order.
313
- */
314
- export async function buildScheduleFromPRD(prdPath) {
315
- const prdContent = await readFile(prdPath, "utf-8");
316
- const milestones = parseMilestoneDependencies(prdContent);
317
- if (milestones.length === 0) {
318
- return {
319
- waves: [],
320
- totalMilestones: 0,
321
- maxParallelism: 0,
322
- isSequential: true,
323
- };
324
- }
325
- const dag = buildDAG(milestones);
326
- return computeExecutionWaves(dag);
327
- }
328
- //# sourceMappingURL=parallel.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"parallel.js","sourceRoot":"","sources":["../../src/worktree/parallel.ts"],"names":[],"mappings":"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"}
@@ -1,67 +0,0 @@
1
- import type { UserIdentity } from "./identity.js";
2
- export interface Session {
3
- id: string;
4
- user: string;
5
- email: string;
6
- skill: "go" | "spec";
7
- milestone?: string;
8
- /** PRD slug this session is executing (for multi-PRD queue tracking) */
9
- prdSlug?: string;
10
- branch: string;
11
- worktreePath: string;
12
- startedAt: string;
13
- pid: number;
14
- status: "active" | "stale" | "completing";
15
- }
16
- export interface SessionRegistry {
17
- sessions: Session[];
18
- }
19
- /**
20
- * Get the path to the session registry file.
21
- * Located at <repoRoot>/.forge/sessions.json
22
- */
23
- export declare function getRegistryPath(repoRoot: string): string;
24
- /**
25
- * Load the session registry. Returns empty registry if file doesn't exist.
26
- */
27
- export declare function loadRegistry(repoRoot: string): SessionRegistry;
28
- /**
29
- * Save the session registry atomically.
30
- */
31
- export declare function saveRegistry(repoRoot: string, registry: SessionRegistry): void;
32
- /**
33
- * Register a new session. Returns the created session.
34
- * Uses file-based locking to prevent lost updates from concurrent writes.
35
- */
36
- export declare function registerSession(repoRoot: string, params: {
37
- user: UserIdentity;
38
- skill: "go" | "spec";
39
- milestone?: string;
40
- prdSlug?: string;
41
- branch: string;
42
- worktreePath: string;
43
- }): Session;
44
- /**
45
- * Deregister (remove) a session by ID.
46
- * Uses file-based locking to prevent lost updates.
47
- */
48
- export declare function deregisterSession(repoRoot: string, sessionId: string): void;
49
- /**
50
- * Update a session's status.
51
- * Uses file-based locking to prevent lost updates.
52
- */
53
- export declare function updateSessionStatus(repoRoot: string, sessionId: string, status: Session["status"]): void;
54
- /**
55
- * Find and mark stale sessions.
56
- * A session is stale if its PID is no longer running.
57
- * Uses file-based locking to prevent lost updates.
58
- */
59
- export declare function detectStaleSessions(repoRoot: string): Session[];
60
- /**
61
- * Get all active sessions.
62
- */
63
- export declare function getActiveSessions(repoRoot: string): Session[];
64
- /**
65
- * Get a session by ID.
66
- */
67
- export declare function getSession(repoRoot: string, sessionId: string): Session | null;
@@ -1,194 +0,0 @@
1
- import { join } from "node:path";
2
- import { openSync, closeSync, unlinkSync, mkdirSync, existsSync, } from "node:fs";
3
- import { readJsonFileSync, writeJsonFileSync, generateSessionId, } from "../utils/platform.js";
4
- /**
5
- * Get the path to the session registry file.
6
- * Located at <repoRoot>/.forge/sessions.json
7
- */
8
- export function getRegistryPath(repoRoot) {
9
- return join(repoRoot, ".forge", "sessions.json");
10
- }
11
- // ---------------------------------------------------------------------------
12
- // File-based lock for registry writes
13
- // ---------------------------------------------------------------------------
14
- const LOCK_RETRIES = 10;
15
- const LOCK_RETRY_MS = 100;
16
- function getLockPath(repoRoot) {
17
- return join(repoRoot, ".forge", "sessions.lock");
18
- }
19
- /**
20
- * Acquire an exclusive lock file. Retries with backoff on contention.
21
- * Uses O_CREAT|O_EXCL which atomically fails if the file exists.
22
- */
23
- function acquireLock(repoRoot) {
24
- const lockPath = getLockPath(repoRoot);
25
- const dir = join(repoRoot, ".forge");
26
- if (!existsSync(dir)) {
27
- mkdirSync(dir, { recursive: true });
28
- }
29
- for (let attempt = 0; attempt < LOCK_RETRIES; attempt++) {
30
- try {
31
- // O_CREAT | O_EXCL | O_WRONLY — fails if file already exists
32
- const fd = openSync(lockPath, "wx");
33
- closeSync(fd);
34
- return;
35
- }
36
- catch {
37
- if (attempt === LOCK_RETRIES - 1) {
38
- // Last attempt — force-remove stale lock and try once more
39
- try {
40
- unlinkSync(lockPath);
41
- const fd = openSync(lockPath, "wx");
42
- closeSync(fd);
43
- return;
44
- }
45
- catch {
46
- throw new Error(`Failed to acquire session registry lock at ${lockPath} after ${LOCK_RETRIES} attempts`);
47
- }
48
- }
49
- // Busy-wait (sync context)
50
- const waitUntil = Date.now() + LOCK_RETRY_MS;
51
- while (Date.now() < waitUntil) {
52
- // spin
53
- }
54
- }
55
- }
56
- }
57
- /**
58
- * Release the lock file.
59
- */
60
- function releaseLock(repoRoot) {
61
- try {
62
- unlinkSync(getLockPath(repoRoot));
63
- }
64
- catch {
65
- // Lock already removed — non-fatal
66
- }
67
- }
68
- /**
69
- * Execute a callback while holding the registry lock.
70
- * Ensures read-modify-write operations are serialized.
71
- */
72
- function withRegistryLock(repoRoot, fn) {
73
- acquireLock(repoRoot);
74
- try {
75
- return fn();
76
- }
77
- finally {
78
- releaseLock(repoRoot);
79
- }
80
- }
81
- /**
82
- * Load the session registry. Returns empty registry if file doesn't exist.
83
- */
84
- export function loadRegistry(repoRoot) {
85
- const data = readJsonFileSync(getRegistryPath(repoRoot));
86
- if (data === null) {
87
- return { sessions: [] };
88
- }
89
- return data;
90
- }
91
- /**
92
- * Save the session registry atomically.
93
- */
94
- export function saveRegistry(repoRoot, registry) {
95
- writeJsonFileSync(getRegistryPath(repoRoot), registry);
96
- }
97
- /**
98
- * Register a new session. Returns the created session.
99
- * Uses file-based locking to prevent lost updates from concurrent writes.
100
- */
101
- export function registerSession(repoRoot, params) {
102
- return withRegistryLock(repoRoot, () => {
103
- const registry = loadRegistry(repoRoot);
104
- const session = {
105
- id: generateSessionId(),
106
- user: params.user.name,
107
- email: params.user.email,
108
- skill: params.skill,
109
- milestone: params.milestone,
110
- prdSlug: params.prdSlug,
111
- branch: params.branch,
112
- worktreePath: params.worktreePath,
113
- startedAt: new Date().toISOString(),
114
- pid: process.pid,
115
- status: "active",
116
- };
117
- registry.sessions.push(session);
118
- saveRegistry(repoRoot, registry);
119
- return session;
120
- });
121
- }
122
- /**
123
- * Deregister (remove) a session by ID.
124
- * Uses file-based locking to prevent lost updates.
125
- */
126
- export function deregisterSession(repoRoot, sessionId) {
127
- withRegistryLock(repoRoot, () => {
128
- const registry = loadRegistry(repoRoot);
129
- registry.sessions = registry.sessions.filter((s) => s.id !== sessionId);
130
- saveRegistry(repoRoot, registry);
131
- });
132
- }
133
- /**
134
- * Update a session's status.
135
- * Uses file-based locking to prevent lost updates.
136
- */
137
- export function updateSessionStatus(repoRoot, sessionId, status) {
138
- withRegistryLock(repoRoot, () => {
139
- const registry = loadRegistry(repoRoot);
140
- const session = registry.sessions.find((s) => s.id === sessionId);
141
- if (session) {
142
- session.status = status;
143
- saveRegistry(repoRoot, registry);
144
- }
145
- });
146
- }
147
- /**
148
- * Check if a process with the given PID is still running.
149
- */
150
- function isPidAlive(pid) {
151
- try {
152
- process.kill(pid, 0);
153
- return true;
154
- }
155
- catch {
156
- return false;
157
- }
158
- }
159
- /**
160
- * Find and mark stale sessions.
161
- * A session is stale if its PID is no longer running.
162
- * Uses file-based locking to prevent lost updates.
163
- */
164
- export function detectStaleSessions(repoRoot) {
165
- return withRegistryLock(repoRoot, () => {
166
- const registry = loadRegistry(repoRoot);
167
- const newlyStale = [];
168
- for (const session of registry.sessions) {
169
- if (session.status === "active" && !isPidAlive(session.pid)) {
170
- session.status = "stale";
171
- newlyStale.push(session);
172
- }
173
- }
174
- if (newlyStale.length > 0) {
175
- saveRegistry(repoRoot, registry);
176
- }
177
- return newlyStale;
178
- });
179
- }
180
- /**
181
- * Get all active sessions.
182
- */
183
- export function getActiveSessions(repoRoot) {
184
- const registry = loadRegistry(repoRoot);
185
- return registry.sessions.filter((s) => s.status === "active");
186
- }
187
- /**
188
- * Get a session by ID.
189
- */
190
- export function getSession(repoRoot, sessionId) {
191
- const registry = loadRegistry(repoRoot);
192
- return registry.sessions.find((s) => s.id === sessionId) ?? null;
193
- }
194
- //# sourceMappingURL=session.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/worktree/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,UAAU,GACX,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAsB9B;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,OAAO,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;AACnD,CAAC;AAED,8EAA8E;AAC9E,sCAAsC;AACtC,8EAA8E;AAE9E,MAAM,YAAY,GAAG,EAAE,CAAC;AACxB,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,SAAS,WAAW,CAAC,QAAgB;IACnC,OAAO,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;AACnD,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW,CAAC,QAAgB;IACnC,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACrC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,YAAY,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,IAAI,CAAC;YACH,6DAA6D;YAC7D,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACpC,SAAS,CAAC,EAAE,CAAC,CAAC;YACd,OAAO;QACT,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,OAAO,KAAK,YAAY,GAAG,CAAC,EAAE,CAAC;gBACjC,2DAA2D;gBAC3D,IAAI,CAAC;oBACH,UAAU,CAAC,QAAQ,CAAC,CAAC;oBACrB,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;oBACpC,SAAS,CAAC,EAAE,CAAC,CAAC;oBACd,OAAO;gBACT,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,IAAI,KAAK,CACb,8CAA8C,QAAQ,UAAU,YAAY,WAAW,CACxF,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,2BAA2B;YAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC;YAC7C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;gBAC9B,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,QAAgB;IACnC,IAAI,CAAC;QACH,UAAU,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;IACrC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAI,QAAgB,EAAE,EAAW;IACxD,WAAW,CAAC,QAAQ,CAAC,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,WAAW,CAAC,QAAQ,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,IAAI,GAAG,gBAAgB,CAAkB,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1E,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC1B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAgB,EAChB,QAAyB;IAEzB,iBAAiB,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,MAOC;IAED,OAAO,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;QACrC,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QAExC,MAAM,OAAO,GAAY;YACvB,EAAE,EAAE,iBAAiB,EAAE;YACvB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI;YACtB,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK;YACxB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,MAAM,EAAE,QAAQ;SACjB,CAAC;QAEF,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAEjC,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,SAAiB;IAEjB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;QAC9B,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACxC,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QACxE,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,SAAiB,EACjB,MAAyB;IAEzB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;QAC9B,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QAElE,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;YACxB,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,OAAO,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;QACrC,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,UAAU,GAAc,EAAE,CAAC;QAEjC,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACxC,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5D,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC;gBACzB,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACxC,OAAO,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;AAChE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CACxB,QAAgB,EAChB,SAAiB;IAEjB,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACxC,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,IAAI,IAAI,CAAC;AACnE,CAAC"}
@@ -1,43 +0,0 @@
1
- export interface MergeResult {
2
- stateUpdated: boolean;
3
- roadmapUpdated: boolean;
4
- warnings: string[];
5
- }
6
- /**
7
- * Merge state from a completed worktree session back to the main repo.
8
- *
9
- * - STATE.md: updates the milestone row with completion status and the
10
- * Last Session date.
11
- * - ROADMAP.md: marks the milestone row as complete with the given date.
12
- *
13
- * Uses synchronous I/O throughout — consistent with all other worktree modules.
14
- *
15
- * @param mainRepoDir - Absolute path to the main repository
16
- * @param worktreeDir - Absolute path to the completed worktree
17
- * @param milestoneNumber - The milestone that was completed
18
- * @param completionDate - Date string (YYYY-MM-DD) for the completion
19
- */
20
- export declare function mergeSessionState(mainRepoDir: string, worktreeDir: string, milestoneNumber: number, completionDate: string): MergeResult;
21
- /**
22
- * Update a specific milestone row in a ROADMAP.md file.
23
- * Uses structured line-by-line parsing (not regex replace) to safely
24
- * update the status column of the milestone's table row.
25
- *
26
- * @param roadmapPath - Absolute path to ROADMAP.md
27
- * @param milestoneNumber - Which milestone to update
28
- * @param newStatus - New status string (e.g., "Complete (2026-02-15)")
29
- * @returns true if the milestone was found and updated
30
- */
31
- export declare function updateRoadmapMilestoneStatus(roadmapPath: string, milestoneNumber: number, newStatus: string): boolean;
32
- /**
33
- * Update the milestone progress table in STATE.md.
34
- * Reads the current STATE.md, finds the milestone row, updates its status.
35
- * Also updates the `**Last Session:**` date if present.
36
- * Preserves all other content.
37
- *
38
- * @param statePath - Absolute path to STATE.md
39
- * @param milestoneNumber - Which milestone to update
40
- * @param newStatus - New status string
41
- * @returns true if the milestone was found and updated
42
- */
43
- export declare function updateStateMilestoneRow(statePath: string, milestoneNumber: number, newStatus: string): boolean;