@samahlstrom/forge-cli 0.1.6 → 0.1.8

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.
@@ -0,0 +1,9 @@
1
+ interface RunOptions {
2
+ dryRun?: boolean;
3
+ phase?: string;
4
+ concurrency?: string;
5
+ budget?: string;
6
+ review?: boolean;
7
+ }
8
+ export declare function run(specId: string, options: RunOptions): Promise<void>;
9
+ export {};
@@ -0,0 +1,221 @@
1
+ import * as p from '@clack/prompts';
2
+ import chalk from 'chalk';
3
+ import { join } from 'node:path';
4
+ import { exists } from '../utils/fs.js';
5
+ import { bdReady, bdClose, bdUpdate, bdList } from '../utils/bd.js';
6
+ import { execaCommand } from 'execa';
7
+ export async function run(specId, options) {
8
+ const cwd = process.cwd();
9
+ const concurrency = parseInt(options.concurrency ?? '1', 10);
10
+ const budget = options.budget ? parseFloat(options.budget) : undefined;
11
+ const reviewEnabled = options.review !== false;
12
+ p.intro(chalk.bold('forge run') + chalk.dim(` — ${specId}`));
13
+ // Verify spec exists
14
+ const specDir = join(cwd, '.forge', 'specs', specId);
15
+ if (!(await exists(join(specDir, 'spec.yaml')))) {
16
+ p.cancel(`No spec.yaml found. Run /ingest ${specId} first.`);
17
+ process.exit(1);
18
+ }
19
+ // Verify beads exist
20
+ let allTasks;
21
+ try {
22
+ allTasks = await bdList({ labels: [`spec:${specId}`], type: 'task' }, cwd);
23
+ }
24
+ catch {
25
+ p.cancel('Could not query beads. Is bd initialized? Run: forge seed ' + specId);
26
+ process.exit(1);
27
+ }
28
+ if (allTasks.length === 0) {
29
+ p.cancel(`No task beads found for ${specId}. Run: forge seed ${specId}`);
30
+ process.exit(1);
31
+ }
32
+ const openTasks = allTasks.filter(t => t.status === 'open' || t.status === 'in_progress');
33
+ p.log.info(`${chalk.cyan(String(openTasks.length))} tasks remaining out of ${allTasks.length} total`);
34
+ if (options.dryRun) {
35
+ await showDryRun(specId, cwd);
36
+ p.outro(chalk.dim('Dry run complete — no tasks executed.'));
37
+ return;
38
+ }
39
+ // Warn about permissions
40
+ p.log.warn(chalk.yellow('Auto-pilot mode uses --dangerously-skip-permissions for unattended execution.'));
41
+ const confirm = await p.confirm({
42
+ message: 'Continue?',
43
+ initialValue: true,
44
+ });
45
+ if (p.isCancel(confirm) || !confirm) {
46
+ p.cancel('Run cancelled.');
47
+ process.exit(0);
48
+ }
49
+ // Main orchestration loop
50
+ let completed = 0;
51
+ let failed = 0;
52
+ let currentPhase = '';
53
+ const startTime = Date.now();
54
+ while (true) {
55
+ // Get ready tasks
56
+ const labelFilters = [`spec:${specId}`];
57
+ if (options.phase)
58
+ labelFilters.push(`phase:${options.phase}`);
59
+ let readyTasks;
60
+ try {
61
+ readyTasks = await bdReady(labelFilters, cwd);
62
+ }
63
+ catch {
64
+ readyTasks = [];
65
+ }
66
+ if (readyTasks.length === 0) {
67
+ // Check if there are still open tasks (blocked)
68
+ const remaining = await bdList({ labels: [`spec:${specId}`], type: 'task', status: 'open' }, cwd);
69
+ if (remaining.length === 0)
70
+ break; // All done
71
+ // Try closing eligible epics to unblock next phase
72
+ try {
73
+ await execaCommand('bd epic close-eligible', { shell: true, cwd, timeout: 10000 });
74
+ }
75
+ catch { /* ignore */ }
76
+ // Re-check ready tasks after epic closing
77
+ try {
78
+ readyTasks = await bdReady(labelFilters, cwd);
79
+ }
80
+ catch {
81
+ readyTasks = [];
82
+ }
83
+ if (readyTasks.length === 0) {
84
+ // Phase boundary or deadlock
85
+ if (reviewEnabled) {
86
+ const elapsed = formatElapsed(Date.now() - startTime);
87
+ p.log.info(`\n${chalk.bold('Phase checkpoint')} — ${completed} completed, ${failed} failed, ${remaining.length} remaining (${elapsed})`);
88
+ const cont = await p.confirm({
89
+ message: `${remaining.length} tasks blocked. Continue waiting for unblock?`,
90
+ initialValue: false,
91
+ });
92
+ if (p.isCancel(cont) || !cont)
93
+ break;
94
+ }
95
+ else {
96
+ break; // No review mode, just stop
97
+ }
98
+ }
99
+ }
100
+ if (readyTasks.length === 0)
101
+ continue;
102
+ // Detect phase transition
103
+ const taskPhase = readyTasks[0].labels?.find(l => l.startsWith('phase:')) ?? '';
104
+ if (taskPhase !== currentPhase) {
105
+ if (currentPhase && reviewEnabled) {
106
+ p.log.success(`\n${chalk.bold('Phase complete:')} ${currentPhase}`);
107
+ const cont = await p.confirm({
108
+ message: `Start ${taskPhase}?`,
109
+ initialValue: true,
110
+ });
111
+ if (p.isCancel(cont) || !cont)
112
+ break;
113
+ }
114
+ currentPhase = taskPhase;
115
+ p.log.step(chalk.bold(`\nStarting ${currentPhase}`));
116
+ }
117
+ // Pick tasks up to concurrency limit
118
+ const batch = readyTasks.slice(0, concurrency);
119
+ // Execute batch
120
+ const results = await Promise.allSettled(batch.map(task => executeTask(task, specId, cwd, budget)));
121
+ for (let i = 0; i < results.length; i++) {
122
+ const result = results[i];
123
+ const task = batch[i];
124
+ if (result.status === 'fulfilled' && result.value) {
125
+ completed++;
126
+ p.log.success(`${chalk.green('✓')} ${task.title}`);
127
+ try {
128
+ await bdClose(task.id, cwd);
129
+ }
130
+ catch (err) {
131
+ p.log.warn(`Failed to close ${task.id}: ${err}`);
132
+ }
133
+ }
134
+ else {
135
+ failed++;
136
+ const reason = result.status === 'rejected' ? result.reason : 'Task returned failure';
137
+ p.log.error(`${chalk.red('✗')} ${task.title}: ${reason}`);
138
+ try {
139
+ await bdUpdate(task.id, { status: 'open' }, cwd);
140
+ }
141
+ catch { /* ignore */ }
142
+ }
143
+ }
144
+ }
145
+ // Final summary
146
+ const elapsed = formatElapsed(Date.now() - startTime);
147
+ const summaryLines = [
148
+ `Completed: ${chalk.green(String(completed))}`,
149
+ `Failed: ${failed > 0 ? chalk.red(String(failed)) : chalk.dim('0')}`,
150
+ `Elapsed: ${chalk.cyan(elapsed)}`,
151
+ ];
152
+ p.note(summaryLines.join('\n'), 'Run complete');
153
+ p.outro(chalk.green('Done.'));
154
+ }
155
+ async function executeTask(task, specId, cwd, budget) {
156
+ const tier = task.labels?.find(l => l.startsWith('tier:'))?.replace('tier:', '') ?? 'T2';
157
+ const agent = task.labels?.find(l => l.startsWith('agent:'))?.replace('agent:', '') ?? '';
158
+ const filesLikely = task.metadata?.files_likely;
159
+ const specTaskId = task.metadata?.spec_task_id;
160
+ const filesStr = filesLikely?.length ? ` Target files: ${filesLikely.join(', ')}.` : '';
161
+ const prompt = `/deliver "${task.title} — ${task.description ?? ''}.${filesStr} Risk: ${tier}. Agent: ${agent}. Spec ref: ${specTaskId ?? task.id}"`;
162
+ const args = ['claude', '-p', '--dangerously-skip-permissions', '--output-format', 'json'];
163
+ if (budget)
164
+ args.push('--max-budget-usd', String(budget));
165
+ try {
166
+ // Write prompt to temp file to avoid shell escaping issues
167
+ const tmpFile = join('/tmp', `forge-run-${task.id}-${Date.now()}.txt`);
168
+ const { writeFile, unlink } = await import('node:fs/promises');
169
+ await writeFile(tmpFile, prompt);
170
+ try {
171
+ const result = await execaCommand(`cat "${tmpFile}" | ${args.join(' ')}`, { shell: true, cwd, timeout: 600000 });
172
+ // Parse result
173
+ let success = true;
174
+ try {
175
+ const parsed = JSON.parse(result.stdout);
176
+ if (parsed.is_error)
177
+ success = false;
178
+ }
179
+ catch {
180
+ // Non-JSON output, assume success if exit code was 0
181
+ }
182
+ return success;
183
+ }
184
+ finally {
185
+ try {
186
+ const { unlink: ul } = await import('node:fs/promises');
187
+ await ul(tmpFile);
188
+ }
189
+ catch { /* ignore */ }
190
+ }
191
+ }
192
+ catch (err) {
193
+ throw new Error(`claude -p failed: ${String(err)}`);
194
+ }
195
+ }
196
+ async function showDryRun(specId, cwd) {
197
+ const ready = await bdReady([`spec:${specId}`], cwd);
198
+ if (ready.length === 0) {
199
+ p.log.info('No ready tasks found.');
200
+ return;
201
+ }
202
+ p.log.step(`${ready.length} tasks ready to execute:`);
203
+ for (const task of ready) {
204
+ const tier = task.labels?.find(l => l.startsWith('tier:'))?.replace('tier:', '') ?? '?';
205
+ const phase = task.labels?.find(l => l.startsWith('phase:'))?.replace('phase:', '') ?? '?';
206
+ p.log.message(` ${chalk.dim(`P${phase}`)} ${chalk.cyan(tier)} ${task.title}`);
207
+ }
208
+ }
209
+ function formatElapsed(ms) {
210
+ const secs = Math.floor(ms / 1000);
211
+ if (secs < 60)
212
+ return `${secs}s`;
213
+ const mins = Math.floor(secs / 60);
214
+ const remSecs = secs % 60;
215
+ if (mins < 60)
216
+ return `${mins}m ${remSecs}s`;
217
+ const hrs = Math.floor(mins / 60);
218
+ const remMins = mins % 60;
219
+ return `${hrs}h ${remMins}m`;
220
+ }
221
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ interface SeedOptions {
2
+ force?: boolean;
3
+ }
4
+ export declare function seed(specId: string, options: SeedOptions): Promise<void>;
5
+ export {};
@@ -0,0 +1,57 @@
1
+ import * as p from '@clack/prompts';
2
+ import chalk from 'chalk';
3
+ import { join } from 'node:path';
4
+ import { exists } from '../utils/fs.js';
5
+ import { seedBeads } from '../utils/seed-beads.js';
6
+ import { bdCount } from '../utils/bd.js';
7
+ export async function seed(specId, options) {
8
+ const cwd = process.cwd();
9
+ p.intro(chalk.bold('forge seed') + chalk.dim(` — ${specId}`));
10
+ const specDir = join(cwd, '.forge', 'specs', specId);
11
+ // Verify spec.yaml exists
12
+ const specYamlPath = join(specDir, 'spec.yaml');
13
+ if (!(await exists(specYamlPath))) {
14
+ p.cancel(`No spec.yaml found at ${specYamlPath}. Run /ingest ${specId} first.`);
15
+ process.exit(1);
16
+ }
17
+ // Check if beads already exist for this spec
18
+ try {
19
+ const existingCount = await bdCount({ labels: [`spec:${specId}`] }, cwd);
20
+ if (existingCount > 0 && !options.force) {
21
+ const overwrite = await p.confirm({
22
+ message: `${existingCount} beads already exist for ${specId}. Re-create?`,
23
+ initialValue: false,
24
+ });
25
+ if (p.isCancel(overwrite) || !overwrite) {
26
+ p.cancel('Seed cancelled.');
27
+ process.exit(0);
28
+ }
29
+ }
30
+ }
31
+ catch {
32
+ // bd not initialized or count failed — proceed
33
+ }
34
+ const spinner = p.spinner();
35
+ spinner.start('Creating beads from spec.yaml...');
36
+ try {
37
+ const result = await seedBeads(specDir, specId, cwd);
38
+ spinner.stop('Beads created');
39
+ const lines = [
40
+ `Phases: ${chalk.cyan(String(result.phases))} epics`,
41
+ `Epics: ${chalk.cyan(String(result.epics))} epics`,
42
+ `Tasks: ${chalk.cyan(String(result.tasks))} tasks`,
43
+ `Deps: ${chalk.cyan(String(result.links))} blocking links`,
44
+ ];
45
+ p.note(lines.join('\n'), 'Beads seeded');
46
+ p.log.step('Next:');
47
+ p.log.message(` Run ${chalk.cyan(`forge run ${specId}`)} to start auto-pilot execution`);
48
+ p.log.message(` Or ${chalk.cyan('bd ready')} to see what tasks are available`);
49
+ }
50
+ catch (err) {
51
+ spinner.stop('Seeding failed');
52
+ p.log.error(String(err));
53
+ process.exit(1);
54
+ }
55
+ p.outro(chalk.green('Ready to execute.'));
56
+ }
57
+ //# sourceMappingURL=seed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed.js","sourceRoot":"","sources":["../../src/commands/seed.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -6,6 +6,8 @@ import { remove } from './commands/remove.js';
6
6
  import { upgrade } from './commands/upgrade.js';
7
7
  import { status } from './commands/status.js';
8
8
  import { doctor } from './commands/doctor.js';
9
+ import { seed } from './commands/seed.js';
10
+ import { run } from './commands/run.js';
9
11
  const program = new Command();
10
12
  program
11
13
  .name('forge')
@@ -47,5 +49,19 @@ program
47
49
  .command('doctor')
48
50
  .description('Diagnose harness health: check files, scripts, deps, and config')
49
51
  .action(doctor);
52
+ program
53
+ .command('seed <spec-id>')
54
+ .description('Create beads (bd tasks) from an approved spec.yaml decomposition')
55
+ .option('--force', 'Re-create beads even if they already exist')
56
+ .action(seed);
57
+ program
58
+ .command('run <spec-id>')
59
+ .description('Auto-pilot: orchestrate task execution from a seeded spec')
60
+ .option('--dry-run', 'Show execution plan without running')
61
+ .option('--phase <number>', 'Only execute tasks in a specific phase')
62
+ .option('--concurrency <number>', 'Max parallel tasks', '1')
63
+ .option('--budget <usd>', 'Max USD spend per task via claude -p')
64
+ .option('--no-review', 'Skip review gates between phases')
65
+ .action(run);
50
66
  program.parse();
51
67
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACL,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,2CAA2C,CAAC;KACxD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEnB,OAAO;KACL,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,uDAAuD,CAAC;KACpE,MAAM,CAAC,mBAAmB,EAAE,0CAA0C,CAAC;KACvE,MAAM,CAAC,SAAS,EAAE,kCAAkC,CAAC;KACrD,MAAM,CAAC,OAAO,EAAE,uCAAuC,CAAC;KACxD,MAAM,CAAC,eAAe,EAAE,2DAA2D,CAAC;KACpF,MAAM,CAAC,IAAI,CAAC,CAAC;AAEf,OAAO;KACL,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,0EAA0E,CAAC;KACvF,QAAQ,CAAC,YAAY,EAAE,8CAA8C,CAAC;KACtE,MAAM,CAAC,sBAAsB,EAAE,oCAAoC,EAAE,IAAI,CAAC;KAC1E,MAAM,CAAC,oBAAoB,EAAE,qCAAqC,CAAC;KACnE,MAAM,CAAC,MAAM,CAAC,CAAC;AAEjB,OAAO;KACL,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,qEAAqE,CAAC;KAClF,MAAM,CAAC,GAAG,CAAC,CAAC;AAEd,OAAO;KACL,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,2BAA2B,CAAC;KACxC,MAAM,CAAC,MAAM,CAAC,CAAC;AAEjB,OAAO;KACL,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,wDAAwD,CAAC;KACrE,MAAM,CAAC,SAAS,EAAE,uCAAuC,CAAC;KAC1D,MAAM,CAAC,OAAO,CAAC,CAAC;AAElB,OAAO;KACL,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,2DAA2D,CAAC;KACxE,MAAM,CAAC,MAAM,CAAC,CAAC;AAEjB,OAAO;KACL,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,iEAAiE,CAAC;KAC9E,MAAM,CAAC,MAAM,CAAC,CAAC;AAEjB,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ export interface BdIssue {
2
+ id: string;
3
+ title: string;
4
+ description: string;
5
+ status: string;
6
+ labels: string[];
7
+ priority: number;
8
+ parent?: string;
9
+ metadata?: Record<string, unknown>;
10
+ }
11
+ export interface BdCreateOpts {
12
+ title: string;
13
+ description?: string;
14
+ type?: string;
15
+ labels?: string[];
16
+ parent?: string;
17
+ metadata?: Record<string, unknown>;
18
+ deps?: string[];
19
+ }
20
+ export declare function bdCreate(opts: BdCreateOpts, cwd?: string): Promise<string>;
21
+ export declare function bdLink(from: string, to: string, type?: string, cwd?: string): Promise<void>;
22
+ export declare function bdReady(labels?: string[], cwd?: string): Promise<BdIssue[]>;
23
+ export declare function bdClose(id: string, cwd?: string): Promise<void>;
24
+ export declare function bdUpdate(id: string, opts: {
25
+ assignee?: string;
26
+ labels?: string[];
27
+ status?: string;
28
+ }, cwd?: string): Promise<void>;
29
+ export declare function bdList(filters: {
30
+ labels?: string[];
31
+ type?: string;
32
+ status?: string;
33
+ }, cwd?: string): Promise<BdIssue[]>;
34
+ export declare function bdShow(id: string, cwd?: string): Promise<BdIssue>;
35
+ export declare function bdCount(filters: {
36
+ labels?: string[];
37
+ }, cwd?: string): Promise<number>;
@@ -0,0 +1,81 @@
1
+ import { execaCommand } from 'execa';
2
+ export async function bdCreate(opts, cwd) {
3
+ const args = ['bd', 'create', JSON.stringify(opts.title)];
4
+ if (opts.description)
5
+ args.push('-d', JSON.stringify(opts.description));
6
+ if (opts.type)
7
+ args.push('-t', opts.type);
8
+ if (opts.labels?.length)
9
+ args.push('-l', opts.labels.join(','));
10
+ if (opts.parent)
11
+ args.push('--parent', opts.parent);
12
+ if (opts.metadata)
13
+ args.push('--metadata', JSON.stringify(JSON.stringify(opts.metadata)));
14
+ if (opts.deps?.length)
15
+ args.push('--deps', opts.deps.join(','));
16
+ args.push('--json');
17
+ const result = await execaCommand(args.join(' '), { shell: true, cwd, timeout: 15000 });
18
+ const parsed = JSON.parse(result.stdout);
19
+ return parsed.id ?? parsed.ID ?? parsed.issue_id ?? result.stdout.trim();
20
+ }
21
+ export async function bdLink(from, to, type = 'blocks', cwd) {
22
+ await execaCommand(`bd link ${from} ${to} --type ${type}`, { shell: true, cwd, timeout: 10000 });
23
+ }
24
+ export async function bdReady(labels, cwd) {
25
+ const args = ['bd', 'ready', '--json', '-n', '100'];
26
+ if (labels?.length)
27
+ args.push('-l', labels.join(','));
28
+ const result = await execaCommand(args.join(' '), { shell: true, cwd, timeout: 10000 });
29
+ if (!result.stdout.trim())
30
+ return [];
31
+ try {
32
+ const parsed = JSON.parse(result.stdout);
33
+ return Array.isArray(parsed) ? parsed : [parsed];
34
+ }
35
+ catch {
36
+ return [];
37
+ }
38
+ }
39
+ export async function bdClose(id, cwd) {
40
+ await execaCommand(`bd close ${id}`, { shell: true, cwd, timeout: 10000 });
41
+ }
42
+ export async function bdUpdate(id, opts, cwd) {
43
+ const args = ['bd', 'update', id];
44
+ if (opts.assignee)
45
+ args.push('-a', opts.assignee);
46
+ if (opts.status)
47
+ args.push('-s', opts.status);
48
+ args.push('--json');
49
+ await execaCommand(args.join(' '), { shell: true, cwd, timeout: 10000 });
50
+ }
51
+ export async function bdList(filters, cwd) {
52
+ const args = ['bd', 'list', '--json'];
53
+ if (filters.labels?.length)
54
+ args.push('-l', filters.labels.join(','));
55
+ if (filters.type)
56
+ args.push('-t', filters.type);
57
+ if (filters.status)
58
+ args.push('-s', filters.status);
59
+ const result = await execaCommand(args.join(' '), { shell: true, cwd, timeout: 10000 });
60
+ if (!result.stdout.trim())
61
+ return [];
62
+ try {
63
+ const parsed = JSON.parse(result.stdout);
64
+ return Array.isArray(parsed) ? parsed : [parsed];
65
+ }
66
+ catch {
67
+ return [];
68
+ }
69
+ }
70
+ export async function bdShow(id, cwd) {
71
+ const result = await execaCommand(`bd show ${id} --json`, { shell: true, cwd, timeout: 10000 });
72
+ return JSON.parse(result.stdout);
73
+ }
74
+ export async function bdCount(filters, cwd) {
75
+ const args = ['bd', 'count'];
76
+ if (filters.labels?.length)
77
+ args.push('-l', filters.labels.join(','));
78
+ const result = await execaCommand(args.join(' '), { shell: true, cwd, timeout: 10000 });
79
+ return parseInt(result.stdout.trim(), 10) || 0;
80
+ }
81
+ //# sourceMappingURL=bd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bd.js","sourceRoot":"","sources":["../../src/utils/bd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export interface SeedResult {
2
+ phases: number;
3
+ epics: number;
4
+ tasks: number;
5
+ links: number;
6
+ taskMap: Record<string, string>;
7
+ }
8
+ export declare function seedBeads(specDir: string, specId: string, cwd?: string): Promise<SeedResult>;
@@ -0,0 +1,93 @@
1
+ import { join } from 'node:path';
2
+ import { readText } from './fs.js';
3
+ import { bdCreate, bdLink } from './bd.js';
4
+ export async function seedBeads(specDir, specId, cwd) {
5
+ const { parse } = await import('yaml');
6
+ const specContent = await readText(join(specDir, 'spec.yaml'));
7
+ const spec = parse(specContent);
8
+ const taskMap = {}; // spec task id -> bd id
9
+ const epicMap = {}; // spec epic id -> bd id
10
+ const phaseEpicIds = []; // bd ids for phase-level epics
11
+ let linkCount = 0;
12
+ const effectiveCwd = cwd ?? process.cwd();
13
+ // Create phase epics and their child epics + tasks
14
+ for (let pi = 0; pi < spec.execution_plan.phases.length; pi++) {
15
+ const phase = spec.execution_plan.phases[pi];
16
+ const phaseNum = pi + 1;
17
+ // Create phase-level epic
18
+ const phaseBeadId = await bdCreate({
19
+ title: `Phase ${phaseNum}: ${phase.name}`,
20
+ type: 'epic',
21
+ labels: [`spec:${specId}`, `phase:${phaseNum}`],
22
+ metadata: { spec_phase_id: phase.id, rationale: phase.rationale },
23
+ }, effectiveCwd);
24
+ phaseEpicIds.push(phaseBeadId);
25
+ // Phase ordering: phase N+1 is blocked by phase N
26
+ if (pi > 0) {
27
+ await bdLink(phaseBeadId, phaseEpicIds[pi - 1], 'blocks', effectiveCwd);
28
+ linkCount++;
29
+ }
30
+ // Create epics within this phase
31
+ for (const epicId of phase.epics) {
32
+ const epic = spec.epics.find(e => e.id === epicId);
33
+ if (!epic)
34
+ continue;
35
+ const epicBeadId = await bdCreate({
36
+ title: epic.title,
37
+ type: 'epic',
38
+ parent: phaseBeadId,
39
+ labels: [`spec:${specId}`, `phase:${phaseNum}`, `domain:${epic.domain}`],
40
+ }, effectiveCwd);
41
+ epicMap[epic.id] = epicBeadId;
42
+ // Create tasks for each feature in this epic
43
+ for (const feature of epic.features) {
44
+ for (const task of feature.tasks) {
45
+ const taskBeadId = await bdCreate({
46
+ title: task.title,
47
+ description: task.description,
48
+ parent: epicBeadId,
49
+ labels: [
50
+ `spec:${specId}`,
51
+ `phase:${phaseNum}`,
52
+ `tier:${task.risk_tier}`,
53
+ `agent:${task.agent}`,
54
+ `feature:${feature.id}`,
55
+ ],
56
+ metadata: {
57
+ spec_task_id: task.id,
58
+ files_likely: task.files_likely,
59
+ },
60
+ }, effectiveCwd);
61
+ taskMap[task.id] = taskBeadId;
62
+ }
63
+ }
64
+ }
65
+ }
66
+ // Wire up task-level dependencies
67
+ for (const epic of spec.epics) {
68
+ for (const feature of epic.features) {
69
+ for (const task of feature.tasks) {
70
+ if (!task.dependencies?.length)
71
+ continue;
72
+ const thisBeadId = taskMap[task.id];
73
+ if (!thisBeadId)
74
+ continue;
75
+ for (const depId of task.dependencies) {
76
+ const depBeadId = taskMap[depId];
77
+ if (!depBeadId)
78
+ continue;
79
+ await bdLink(thisBeadId, depBeadId, 'blocks', effectiveCwd);
80
+ linkCount++;
81
+ }
82
+ }
83
+ }
84
+ }
85
+ return {
86
+ phases: spec.execution_plan.phases.length,
87
+ epics: Object.keys(epicMap).length,
88
+ tasks: Object.keys(taskMap).length,
89
+ links: linkCount,
90
+ taskMap,
91
+ };
92
+ }
93
+ //# sourceMappingURL=seed-beads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed-beads.js","sourceRoot":"","sources":["../../src/utils/seed-beads.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@samahlstrom/forge-cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Agent harness scaffolding for Claude Code — orchestration, decomposition, specialist agents, verification, and delivery.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,22 +33,38 @@
33
33
  "hooks": {
34
34
  "SessionStart": [
35
35
  {
36
- "command": "bash .forge/hooks/session-start.sh",
37
- "timeout": 10000
36
+ "matcher": "",
37
+ "hooks": [
38
+ {
39
+ "type": "command",
40
+ "command": "bash .forge/hooks/session-start.sh",
41
+ "timeout": 10000
42
+ }
43
+ ]
38
44
  }
39
45
  ],
40
46
  "PreToolUse": [
41
47
  {
42
48
  "matcher": "Edit|Write",
43
- "command": "bash .forge/hooks/pre-edit.sh",
44
- "timeout": 5000
49
+ "hooks": [
50
+ {
51
+ "type": "command",
52
+ "command": "bash .forge/hooks/pre-edit.sh",
53
+ "timeout": 5000
54
+ }
55
+ ]
45
56
  }
46
57
  ],
47
58
  "PostToolUse": [
48
59
  {
49
60
  "matcher": "Edit|Write",
50
- "command": "bash .forge/hooks/post-edit.sh",
51
- "timeout": 5000
61
+ "hooks": [
62
+ {
63
+ "type": "command",
64
+ "command": "bash .forge/hooks/post-edit.sh",
65
+ "timeout": 5000
66
+ }
67
+ ]
52
68
  }
53
69
  ]
54
70
  }
@@ -201,36 +201,45 @@ After approval, for each skill identified in pass-4:
201
201
 
202
202
  Use the `/skill-creator` skill's patterns for writing good skill files.
203
203
 
204
- ### Step 7: Execution Handoff
204
+ ### Step 7: Seed Beads
205
205
 
206
- After skills are generated, present the execution plan:
206
+ After skills are generated, create beads for all tasks in the plan:
207
+
208
+ 1. Run: `forge seed <spec-id>`
209
+ 2. This creates bd issues for every phase, epic, and task in spec.yaml
210
+ 3. Dependencies are wired so `bd ready` returns only unblocked tasks
211
+ 4. Report the counts to the user
212
+
213
+ ### Step 8: Execution Handoff
214
+
215
+ After beads are seeded, present the execution plan:
207
216
 
208
217
  ```
209
218
  Ready to execute. How would you like to proceed?
210
219
 
211
- 1. Phase-by-phase (recommended) — execute one phase at a time with review gates
212
- 2. Full auto execute all phases sequentially
213
- 3. Manual — I'll run /deliver for individual tasks myself
220
+ 1. Auto-pilot (recommended) — run `forge run <spec-id>` to execute all tasks automatically
221
+ 2. Phase-by-phaserun `forge run <spec-id> --phase 1` one phase at a time
222
+ 3. Manual — I'll run /deliver for individual tasks myself, using `bd ready` to pick the next one
214
223
  ```
215
224
 
216
- **Phase-by-phase mode** (recommended):
217
- - For each phase, iterate through its epics and tasks in dependency order
218
- - For each task, construct a `/deliver` call with the task's description from spec.yaml
219
- - After each phase completes, update spec.yaml status and ask user to review before next phase
220
- - Parallelizable phases: tasks without inter-dependencies can be delivered concurrently via subagents
225
+ **Auto-pilot mode** (recommended):
226
+ - User exits Claude Code and runs `forge run <spec-id>` in the terminal
227
+ - The orchestrator picks ready tasks via `bd ready`, invokes `claude -p` with `/deliver` for each
228
+ - Pauses between phases for review (use `--no-review` to skip)
229
+ - Each task runs in an isolated `claude -p` session to avoid context overflow
221
230
 
222
- **Constructing deliver calls from spec.yaml tasks**:
223
- ```
224
- /deliver "<task.title> <task.description>. Target files: <task.files_likely>. Risk: <task.risk_tier>. Spec ref: <task.id>"
225
- ```
231
+ **Manual mode**:
232
+ - User runs `bd ready -l "spec:<spec-id>"` to see available tasks
233
+ - Picks a task and runs `/deliver` with its description
234
+ - Closes the bead with `bd close <id>` when done
226
235
 
227
236
  ### Resuming
228
237
 
229
238
  If the session is interrupted, the user can run `/ingest <spec-id>` again. Check `spec.yaml` status:
230
239
  - `pending-analysis`: start from pass 1
231
240
  - `draft`: show the review gate
232
- - `approved`: resume skill generation or execution
233
- - `in-progress`: find the last completed phase and resume from the next one
241
+ - `approved`: resume skill generation, seeding, or execution
242
+ - `in-progress`: run `forge run <spec-id>` to resume it picks up where it left off via `bd ready`
234
243
 
235
244
  ## Output Protocol
236
245