@samahlstrom/forge-cli 0.1.7 → 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.
- package/dist/commands/run.d.ts +9 -0
- package/dist/commands/run.js +221 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/seed.d.ts +5 -0
- package/dist/commands/seed.js +57 -0
- package/dist/commands/seed.js.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/bd.d.ts +37 -0
- package/dist/utils/bd.js +81 -0
- package/dist/utils/bd.js.map +1 -0
- package/dist/utils/seed-beads.d.ts +8 -0
- package/dist/utils/seed-beads.js +93 -0
- package/dist/utils/seed-beads.js.map +1 -0
- package/package.json +1 -1
- package/templates/core/skill-ingest.md.hbs +25 -16
|
@@ -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,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;
|
|
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>;
|
package/dist/utils/bd.js
ADDED
|
@@ -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,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
|
@@ -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:
|
|
204
|
+
### Step 7: Seed Beads
|
|
205
205
|
|
|
206
|
-
After skills are generated,
|
|
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.
|
|
212
|
-
2.
|
|
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-phase — run `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
|
-
**
|
|
217
|
-
-
|
|
218
|
-
-
|
|
219
|
-
-
|
|
220
|
-
-
|
|
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
|
-
**
|
|
223
|
-
|
|
224
|
-
|
|
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`:
|
|
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
|
|