forge-dev-framework 1.0.1 → 1.2.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 (109) hide show
  1. package/.claude/commands/forge/README.md +281 -0
  2. package/.claude/commands/forge/add-phase.md +90 -0
  3. package/.claude/commands/forge/complete-milestone.md +130 -0
  4. package/.claude/commands/forge/config.md +115 -0
  5. package/.claude/commands/forge/convert.md +31 -0
  6. package/.claude/commands/forge/debug.md +31 -0
  7. package/.claude/commands/forge/discuss.md +78 -0
  8. package/.claude/commands/forge/execute.md +85 -0
  9. package/.claude/commands/forge/generate.md +21 -0
  10. package/.claude/commands/forge/help.md +18 -0
  11. package/.claude/commands/forge/init.md +21 -0
  12. package/.claude/commands/forge/insert-phase.md +99 -0
  13. package/.claude/commands/forge/new-milestone.md +114 -0
  14. package/.claude/commands/forge/new-project.md +24 -0
  15. package/.claude/commands/forge/pause-work.md +111 -0
  16. package/.claude/commands/forge/plan.md +129 -0
  17. package/.claude/commands/forge/quick.md +41 -0
  18. package/.claude/commands/forge/remove-phase.md +92 -0
  19. package/.claude/commands/forge/resume.md +22 -0
  20. package/.claude/commands/forge/status.md +87 -0
  21. package/.claude/commands/forge/team-add.md +24 -0
  22. package/.claude/commands/forge/team-create.md +22 -0
  23. package/.claude/commands/forge/team-remove.md +24 -0
  24. package/.claude/commands/forge/team-start.md +22 -0
  25. package/.claude/commands/forge/team-view.md +18 -0
  26. package/.claude/commands/forge/verify.md +95 -0
  27. package/.claude/hooks/forge-context-cleanup.cjs +79 -0
  28. package/.claude/hooks/forge-event-guard.cjs +36 -0
  29. package/.claude/hooks/forge-size-guard.cjs +55 -0
  30. package/.claude/rules/api-patterns.md +13 -98
  31. package/.claude/rules/context-efficiency.md +10 -0
  32. package/.claude/rules/security-baseline.md +18 -204
  33. package/.claude/rules/testing-standards.md +16 -177
  34. package/.claude/rules/ui-conventions.md +17 -142
  35. package/README.md +1 -0
  36. package/bin/forge.js +5 -3
  37. package/dist/bin/forge.js +5 -3
  38. package/dist/cli/index.d.ts.map +1 -1
  39. package/dist/cli/index.js +15 -1
  40. package/dist/cli/index.js.map +1 -1
  41. package/dist/commands/convert.d.ts +6 -0
  42. package/dist/commands/convert.d.ts.map +1 -0
  43. package/dist/commands/convert.js +132 -0
  44. package/dist/commands/convert.js.map +1 -0
  45. package/dist/commands/generate.d.ts.map +1 -1
  46. package/dist/commands/generate.js +3 -2
  47. package/dist/commands/generate.js.map +1 -1
  48. package/dist/commands/index.d.ts +4 -4
  49. package/dist/commands/index.d.ts.map +1 -1
  50. package/dist/commands/index.js +4 -4
  51. package/dist/commands/index.js.map +1 -1
  52. package/dist/generators/gsd-converter.d.ts +100 -0
  53. package/dist/generators/gsd-converter.d.ts.map +1 -0
  54. package/dist/generators/gsd-converter.js +335 -0
  55. package/dist/generators/gsd-converter.js.map +1 -0
  56. package/dist/templates/.claude/rules/api-patterns.md.template +212 -0
  57. package/dist/templates/.claude/rules/security-baseline.md.template +322 -0
  58. package/dist/templates/.claude/rules/testing-standards.md.template +280 -0
  59. package/dist/templates/.claude/rules/ui-conventions.md.template +264 -0
  60. package/dist/templates/.planning/forge.config.json.template +75 -0
  61. package/dist/templates/CLAUDE.md.template +161 -0
  62. package/dist/templates/PLAN.md.template +177 -0
  63. package/dist/templates/PROJECT.md.template +156 -0
  64. package/dist/templates/REQUIREMENTS.md.template +221 -0
  65. package/dist/templates/ROADMAP.md.template +130 -0
  66. package/dist/types/index.d.ts +2 -2
  67. package/dist/types/index.d.ts.map +1 -1
  68. package/dist/types/index.js +2 -2
  69. package/dist/types/index.js.map +1 -1
  70. package/dist/utils/index.d.ts +5 -5
  71. package/dist/utils/index.d.ts.map +1 -1
  72. package/dist/utils/index.js +5 -5
  73. package/dist/utils/index.js.map +1 -1
  74. package/dist/utils/template-client.d.ts.map +1 -1
  75. package/dist/utils/template-client.js +3 -2
  76. package/dist/utils/template-client.js.map +1 -1
  77. package/package.json +6 -4
  78. package/dist/git/__tests__/worktree.test.d.ts +0 -5
  79. package/dist/git/__tests__/worktree.test.d.ts.map +0 -1
  80. package/dist/git/__tests__/worktree.test.js +0 -121
  81. package/dist/git/__tests__/worktree.test.js.map +0 -1
  82. package/dist/git/codeowners.d.ts +0 -101
  83. package/dist/git/codeowners.d.ts.map +0 -1
  84. package/dist/git/codeowners.js +0 -216
  85. package/dist/git/codeowners.js.map +0 -1
  86. package/dist/git/commit.d.ts +0 -135
  87. package/dist/git/commit.d.ts.map +0 -1
  88. package/dist/git/commit.js +0 -223
  89. package/dist/git/commit.js.map +0 -1
  90. package/dist/git/hooks/commit-msg.d.ts +0 -8
  91. package/dist/git/hooks/commit-msg.d.ts.map +0 -1
  92. package/dist/git/hooks/commit-msg.js +0 -34
  93. package/dist/git/hooks/commit-msg.js.map +0 -1
  94. package/dist/git/hooks/pre-commit.d.ts +0 -8
  95. package/dist/git/hooks/pre-commit.d.ts.map +0 -1
  96. package/dist/git/hooks/pre-commit.js +0 -34
  97. package/dist/git/hooks/pre-commit.js.map +0 -1
  98. package/dist/git/pre-commit-hooks.d.ts +0 -117
  99. package/dist/git/pre-commit-hooks.d.ts.map +0 -1
  100. package/dist/git/pre-commit-hooks.js +0 -270
  101. package/dist/git/pre-commit-hooks.js.map +0 -1
  102. package/dist/git/wipe-protocol.d.ts +0 -281
  103. package/dist/git/wipe-protocol.d.ts.map +0 -1
  104. package/dist/git/wipe-protocol.js +0 -237
  105. package/dist/git/wipe-protocol.js.map +0 -1
  106. package/dist/git/worktree.d.ts +0 -69
  107. package/dist/git/worktree.d.ts.map +0 -1
  108. package/dist/git/worktree.js +0 -202
  109. package/dist/git/worktree.js.map +0 -1
@@ -1,237 +0,0 @@
1
- /**
2
- * The Wipe Protocol - Context Hygiene for FORGE
3
- *
4
- * Treats agent context as ephemeral, git as persistent.
5
- *
6
- * Lifecycle:
7
- * 1. Hydrate — Agent starts, reads CLAUDE.md + STATE.json + assigned task + contracts
8
- * 2. Execute — Agent writes code, runs tests within its domain
9
- * 3. Commit — Atomic git commit linked to task ID
10
- * 4. Terminate — Session ends, context wiped
11
- * 5. Reincarnate — Next task starts with fresh context, reads NEW git state
12
- */
13
- import { readFile } from "node:fs/promises";
14
- import { join } from "node:path";
15
- import { z } from "zod";
16
- import { createWorktree, getWorktree, cleanupWorktree } from "./worktree.js";
17
- // Schemas for FORGE artifacts
18
- export const TaskSchema = z.object({
19
- id: z.string(),
20
- title: z.string(),
21
- ownerRole: z.string(),
22
- status: z.enum(["pending", "in_progress", "completed", "blocked"]),
23
- deps: z.array(z.string()),
24
- allowedPaths: z.array(z.string()),
25
- acceptance: z.array(z.string()),
26
- verify: z.array(z.string()),
27
- commit: z.string().nullable(),
28
- requests: z.array(z.string()),
29
- priority: z.number(),
30
- });
31
- export const StateSchema = z.object({
32
- project: z.object({
33
- name: z.string(),
34
- status: z.string(),
35
- currentMilestone: z.string(),
36
- currentPhase: z.number(),
37
- }),
38
- tasks: z.array(TaskSchema),
39
- contracts: z.array(z.object({
40
- id: z.string(),
41
- path: z.string(),
42
- version: z.string(),
43
- publishedBy: z.string(),
44
- consumers: z.array(z.string()),
45
- })),
46
- eventsPointer: z.string(),
47
- });
48
- /**
49
- * Phase 1: Hydrate
50
- *
51
- * Agent starts. Reads all necessary context from the repository.
52
- * This is the ONLY state the agent receives - no conversation history.
53
- *
54
- * @param taskId - The task ID to hydrate for
55
- * @param basePath - Root of the FORGE project
56
- * @returns Hydration context with all necessary artifacts
57
- */
58
- export async function hydrate(taskId, basePath = "/home/parz/projects/forge") {
59
- // Read STATE.json to get task information
60
- const statePath = join(basePath, "state", "STATE.json");
61
- const stateRaw = await readFile(statePath, "utf-8");
62
- const state = StateSchema.parse(JSON.parse(stateRaw));
63
- // Find the assigned task
64
- const task = state.tasks.find((t) => t.id === taskId);
65
- if (!task) {
66
- throw new Error(`Task ${taskId} not found in STATE.json`);
67
- }
68
- // Read CLAUDE.md - the project constitution
69
- const claudePath = join(basePath, "CLAUDE.md");
70
- let claudeRules = "";
71
- try {
72
- claudeRules = await readFile(claudePath, "utf-8");
73
- }
74
- catch {
75
- // CLAUDE.md might not exist yet in early phases
76
- claudeRules = "# CLAUDE.md\n\nNo project rules defined yet.";
77
- }
78
- // Read contract files referenced by the task
79
- const contracts = new Map();
80
- const contractsPath = join(basePath, "contracts");
81
- // If task references specific contracts, load them
82
- // This would be populated from task.contracts field
83
- // For now, we just check if contracts directory exists
84
- return {
85
- claudeRules,
86
- state,
87
- task,
88
- contracts,
89
- };
90
- }
91
- /**
92
- * Phase 2: Execute
93
- *
94
- * Agent writes code, runs tests within its domain.
95
- * This is where the actual work happens.
96
- *
97
- * Note: This function is a placeholder - the actual execution
98
- * is done by the agent teammate. We just provide the isolation
99
- * context (worktree) and validation (allowedPaths).
100
- *
101
- * @param taskId - The task ID being executed
102
- * @param basePath - Root of the FORGE project
103
- * @returns Path to the worktree for execution
104
- */
105
- export async function execute(taskId, basePath = "/home/parz/projects/forge") {
106
- // Check if worktree already exists (resuming from pause)
107
- const existing = await getWorktree(taskId);
108
- if (existing) {
109
- return existing.path;
110
- }
111
- // Create new worktree for this task
112
- const worktreePath = await createWorktree({ taskId });
113
- // Return absolute path to worktree
114
- return join(basePath, worktreePath);
115
- }
116
- /**
117
- * Validate that files are within allowed paths for a task.
118
- *
119
- * Enforces the CODEOWNERS boundary - agents can only write
120
- * within their assigned domain.
121
- *
122
- * @param files - Files to validate
123
- * @param allowedPaths - Allowed path patterns
124
- * @throws Error if any file is out of scope
125
- */
126
- export function validateScope(files, allowedPaths) {
127
- for (const file of files) {
128
- const isAllowed = allowedPaths.some((pattern) => {
129
- // Simple glob matching - converts gitignore-style patterns to regex
130
- const regexPattern = pattern
131
- .replace(/\*\*/g, ".*")
132
- .replace(/\*/g, "[^/]*")
133
- .replace(/\?/g, "[^/]");
134
- const regex = new RegExp(`^${regexPattern}`);
135
- return regex.test(file);
136
- });
137
- if (!isAllowed) {
138
- throw new Error(`File ${file} is outside allowed paths: ${allowedPaths.join(", ")}`);
139
- }
140
- }
141
- }
142
- /**
143
- * Phase 3: Commit
144
- *
145
- * Atomic git commit linked to task ID.
146
- * Every task MUST result in exactly one commit.
147
- *
148
- * Format: type(scope): description
149
- * Example: feat(api-003): implement session authentication
150
- *
151
- * @param taskId - The task ID
152
- * @param message - Commit message (will be formatted)
153
- * @param basePath - Root of the FORGE project
154
- * @returns The commit hash
155
- */
156
- export async function commitTask(taskId, message, basePath = "/home/parz/projects/forge") {
157
- const { execa } = await import("execa");
158
- // Format the commit message to include task ID
159
- const formattedMessage = message.includes(taskId)
160
- ? message
161
- : `feat(${taskId}): ${message}`;
162
- // Stage all changes in the worktree
163
- await execa("git", ["add", "-A"], { cwd: join(basePath, `.worktrees/${taskId}`) });
164
- // Commit with formatted message
165
- const { stdout } = await execa("git", ["commit", "-m", formattedMessage], {
166
- cwd: join(basePath, `.worktrees/${taskId}`),
167
- });
168
- // Extract commit hash from output
169
- const commitHash = stdout.match(/\[([a-f0-9]+)\]/)?.[1] || "";
170
- return commitHash;
171
- }
172
- /**
173
- * Phase 4: Terminate
174
- *
175
- * Session ends. Context is wiped clean.
176
- * The agent's conversation history is discarded.
177
- *
178
- * Note: In Agent Teams, this happens naturally when the agent
179
- * exits. We just need to ensure the worktree is cleaned up.
180
- *
181
- * @param taskId - The task ID
182
- * @param keepWorktree - Whether to keep the worktree (for debugging)
183
- */
184
- export async function terminate(taskId, keepWorktree = false) {
185
- if (!keepWorktree) {
186
- await cleanupWorktree(taskId);
187
- }
188
- }
189
- /**
190
- * Phase 5: Reincarnate
191
- *
192
- * Next task starts with fresh context, reading the NEW git state.
193
- *
194
- * This happens naturally when a new agent spawns - they start
195
- * with a fresh context window and hydrate() to read current state.
196
- *
197
- * @param nextTaskId - The next task ID to work on
198
- * @param basePath - Root of the FORGE project
199
- * @returns Hydration context for the next task
200
- */
201
- export async function reincarnate(nextTaskId, basePath = "/home/parz/projects/forge") {
202
- // Reincarnation is just hydration with fresh context
203
- return hydrate(nextTaskId, basePath);
204
- }
205
- /**
206
- * Execute the full Wipe Protocol lifecycle for a task.
207
- *
208
- * This is the main entry point that orchestrates all phases.
209
- * Note that phases 2 (execute) and 4 (terminate) happen
210
- * externally - this just sets up and tears down.
211
- *
212
- * @param taskId - The task ID to execute
213
- * @param workCallback - Async function that does the actual work
214
- * @param basePath - Root of the FORGE project
215
- * @returns Commit hash from the completed task
216
- */
217
- export async function runWipeProtocol(taskId, workCallback, basePath = "/home/parz/projects/forge") {
218
- // Phase 1: Hydrate
219
- const context = await hydrate(taskId, basePath);
220
- // Phase 2: Execute (setup worktree, call the worker)
221
- const worktreePath = await execute(taskId, basePath);
222
- try {
223
- // Run the actual work (writes code, runs tests)
224
- const commitMessage = await workCallback(worktreePath);
225
- // Phase 3: Commit
226
- const commitHash = await commitTask(taskId, commitMessage, basePath);
227
- // Phase 4: Terminate (cleanup)
228
- await terminate(taskId);
229
- return commitHash;
230
- }
231
- catch (error) {
232
- // On error, keep worktree for debugging
233
- await terminate(taskId, true);
234
- throw error;
235
- }
236
- }
237
- //# sourceMappingURL=wipe-protocol.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"wipe-protocol.js","sourceRoot":"","sources":["../../src/git/wipe-protocol.ts"],"names":[],"mappings":"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"}
@@ -1,69 +0,0 @@
1
- /**
2
- * Git Worktree Management for FORGE
3
- *
4
- * Implements isolated worktree strategy for parallel agent execution.
5
- * Each task gets its own worktree to prevent merge conflicts during development.
6
- *
7
- * Commands (from FORGE spec):
8
- * - git worktree add .worktrees/{taskId} -b forge/{taskId}
9
- * - git worktree remove .worktrees/{taskId}
10
- */
11
- export interface WorktreeOptions {
12
- taskId: string;
13
- branchName?: string;
14
- baseBranch?: string;
15
- }
16
- export interface WorktreeInfo {
17
- taskId: string;
18
- branchName: string;
19
- path: string;
20
- commit: string;
21
- }
22
- export declare class WorktreeError extends Error {
23
- readonly code?: string | undefined;
24
- constructor(message: string, code?: string | undefined);
25
- }
26
- /**
27
- * Create a new git worktree for a task.
28
- *
29
- * Creates a branch `forge/{taskId}` and checks it out into `.worktrees/{taskId}`.
30
- * This gives each agent an isolated filesystem to work in.
31
- *
32
- * @param options - Task identification and branch configuration
33
- * @returns Path to the new worktree
34
- * @throws WorktreeError if worktree creation fails
35
- */
36
- export declare function createWorktree(options: WorktreeOptions): Promise<string>;
37
- /**
38
- * Get information about a worktree.
39
- *
40
- * @param taskId - Task ID to look up
41
- * @returns Worktree information or null if not found
42
- */
43
- export declare function getWorktree(taskId: string): Promise<WorktreeInfo | null>;
44
- /**
45
- * Merge a worktree's branch back into the base branch.
46
- *
47
- * Should only be called after CI passes. The worktree is removed after merge.
48
- *
49
- * @param taskId - Task ID whose branch to merge
50
- * @param targetBranch - Branch to merge into (default: main)
51
- * @throws WorktreeError if merge fails or has conflicts
52
- */
53
- export declare function mergeWorktree(taskId: string, targetBranch?: string): Promise<void>;
54
- /**
55
- * Remove a worktree.
56
- *
57
- * Safely removes the worktree after cleaning up any uncommitted changes.
58
- *
59
- * @param taskId - Task ID whose worktree to remove
60
- * @throws WorktreeError if removal fails
61
- */
62
- export declare function cleanupWorktree(taskId: string): Promise<void>;
63
- /**
64
- * List all FORGE worktrees.
65
- *
66
- * @returns Array of worktree information for all active tasks
67
- */
68
- export declare function listWorktrees(): Promise<WorktreeInfo[]>;
69
- //# sourceMappingURL=worktree.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/git/worktree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,aAAc,SAAQ,KAAK;aACO,IAAI,CAAC,EAAE,MAAM;gBAA9C,OAAO,EAAE,MAAM,EAAkB,IAAI,CAAC,EAAE,MAAM,YAAA;CAI3D;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB9E;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAyC9E;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,YAAY,GAAE,MAAe,GAC5B,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBnE;AAED;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CA4C7D"}
@@ -1,202 +0,0 @@
1
- /**
2
- * Git Worktree Management for FORGE
3
- *
4
- * Implements isolated worktree strategy for parallel agent execution.
5
- * Each task gets its own worktree to prevent merge conflicts during development.
6
- *
7
- * Commands (from FORGE spec):
8
- * - git worktree add .worktrees/{taskId} -b forge/{taskId}
9
- * - git worktree remove .worktrees/{taskId}
10
- */
11
- import { execa } from "execa";
12
- export class WorktreeError extends Error {
13
- code;
14
- constructor(message, code) {
15
- super(message);
16
- this.code = code;
17
- this.name = "WorktreeError";
18
- }
19
- }
20
- /**
21
- * Create a new git worktree for a task.
22
- *
23
- * Creates a branch `forge/{taskId}` and checks it out into `.worktrees/{taskId}`.
24
- * This gives each agent an isolated filesystem to work in.
25
- *
26
- * @param options - Task identification and branch configuration
27
- * @returns Path to the new worktree
28
- * @throws WorktreeError if worktree creation fails
29
- */
30
- export async function createWorktree(options) {
31
- const { taskId, branchName = `forge/${taskId}`, baseBranch = "main" } = options;
32
- const worktreePath = `.worktrees/${taskId}`;
33
- try {
34
- // Create the .worktrees directory if it doesn't exist
35
- await execa("mkdir", ["-p", ".worktrees"]);
36
- // Create the worktree with a new branch
37
- await execa("git", ["worktree", "add", "-b", branchName, worktreePath, baseBranch]);
38
- return worktreePath;
39
- }
40
- catch (error) {
41
- if (error instanceof Error) {
42
- throw new WorktreeError(`Failed to create worktree for task ${taskId}: ${error.message}`, error.code);
43
- }
44
- throw new WorktreeError(`Failed to create worktree for task ${taskId}`);
45
- }
46
- }
47
- /**
48
- * Get information about a worktree.
49
- *
50
- * @param taskId - Task ID to look up
51
- * @returns Worktree information or null if not found
52
- */
53
- export async function getWorktree(taskId) {
54
- try {
55
- const { stdout } = await execa("git", ["worktree", "list", "--porcelain"]);
56
- const lines = stdout.split("\n");
57
- let currentPath = null;
58
- let currentBranch = null;
59
- let currentCommit = null;
60
- for (const line of lines) {
61
- if (line.startsWith("worktree ")) {
62
- // Check if this is our target worktree
63
- const path = line.slice("worktree ".length);
64
- if (path.endsWith(`.worktrees/${taskId}`) || path.endsWith(`.worktrees/${taskId}/`)) {
65
- currentPath = path;
66
- }
67
- }
68
- else if (currentPath && line.startsWith("branch ")) {
69
- currentBranch = line.slice("branch ".length).replace("refs/heads/", "");
70
- }
71
- else if (currentPath && line.startsWith("commit ")) {
72
- currentCommit = line.slice("commit ".length);
73
- }
74
- else if (line === "") {
75
- // End of a worktree block
76
- if (currentPath && currentBranch && currentCommit) {
77
- return {
78
- taskId,
79
- branchName: currentBranch,
80
- path: currentPath,
81
- commit: currentCommit,
82
- };
83
- }
84
- // Reset
85
- currentPath = null;
86
- currentBranch = null;
87
- currentCommit = null;
88
- }
89
- }
90
- return null;
91
- }
92
- catch (error) {
93
- throw new WorktreeError(`Failed to get worktree info for task ${taskId}`);
94
- }
95
- }
96
- /**
97
- * Merge a worktree's branch back into the base branch.
98
- *
99
- * Should only be called after CI passes. The worktree is removed after merge.
100
- *
101
- * @param taskId - Task ID whose branch to merge
102
- * @param targetBranch - Branch to merge into (default: main)
103
- * @throws WorktreeError if merge fails or has conflicts
104
- */
105
- export async function mergeWorktree(taskId, targetBranch = "main") {
106
- const worktree = await getWorktree(taskId);
107
- if (!worktree) {
108
- throw new WorktreeError(`Worktree for task ${taskId} not found`);
109
- }
110
- try {
111
- // Checkout the target branch in the main repository
112
- await execa("git", ["checkout", targetBranch]);
113
- // Merge the worktree branch
114
- const branchName = worktree.branchName;
115
- await execa("git", ["merge", "--no-ff", branchName, "-m", `Merge ${branchName} into ${targetBranch}`]);
116
- // Clean up the worktree after successful merge
117
- await cleanupWorktree(taskId);
118
- }
119
- catch (error) {
120
- if (error instanceof Error) {
121
- throw new WorktreeError(`Failed to merge worktree for task ${taskId}: ${error.message}`, error.code);
122
- }
123
- throw new WorktreeError(`Failed to merge worktree for task ${taskId}`);
124
- }
125
- }
126
- /**
127
- * Remove a worktree.
128
- *
129
- * Safely removes the worktree after cleaning up any uncommitted changes.
130
- *
131
- * @param taskId - Task ID whose worktree to remove
132
- * @throws WorktreeError if removal fails
133
- */
134
- export async function cleanupWorktree(taskId) {
135
- const worktree = await getWorktree(taskId);
136
- if (!worktree) {
137
- // Already cleaned up, nothing to do
138
- return;
139
- }
140
- try {
141
- // Remove the worktree
142
- await execa("git", ["worktree", "remove", worktree.path]);
143
- }
144
- catch (error) {
145
- if (error instanceof Error) {
146
- throw new WorktreeError(`Failed to cleanup worktree for task ${taskId}: ${error.message}`, error.code);
147
- }
148
- throw new WorktreeError(`Failed to cleanup worktree for task ${taskId}`);
149
- }
150
- }
151
- /**
152
- * List all FORGE worktrees.
153
- *
154
- * @returns Array of worktree information for all active tasks
155
- */
156
- export async function listWorktrees() {
157
- try {
158
- const { stdout } = await execa("git", ["worktree", "list", "--porcelain"]);
159
- const lines = stdout.split("\n");
160
- const worktrees = [];
161
- let currentPath = null;
162
- let currentBranch = null;
163
- let currentCommit = null;
164
- for (const line of lines) {
165
- if (line.startsWith("worktree ")) {
166
- const path = line.slice("worktree ".length);
167
- // Only include FORGE worktrees
168
- if (path.includes(".worktrees/")) {
169
- currentPath = path;
170
- }
171
- }
172
- else if (currentPath && line.startsWith("branch ")) {
173
- currentBranch = line.slice("branch ".length).replace("refs/heads/", "");
174
- }
175
- else if (currentPath && line.startsWith("commit ")) {
176
- currentCommit = line.slice("commit ".length);
177
- }
178
- else if (line === "") {
179
- // End of a worktree block
180
- if (currentPath && currentBranch && currentCommit) {
181
- // Extract taskId from path
182
- const taskId = currentPath.match(/\.worktrees\/([^/]+)/)?.[1] || "unknown";
183
- worktrees.push({
184
- taskId,
185
- branchName: currentBranch,
186
- path: currentPath,
187
- commit: currentCommit,
188
- });
189
- }
190
- // Reset
191
- currentPath = null;
192
- currentBranch = null;
193
- currentCommit = null;
194
- }
195
- }
196
- return worktrees;
197
- }
198
- catch (error) {
199
- throw new WorktreeError("Failed to list worktrees");
200
- }
201
- }
202
- //# sourceMappingURL=worktree.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/git/worktree.ts"],"names":[],"mappings":"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"}