@clemrig/factory 0.3.0 → 0.5.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.
- package/README.md +118 -23
- package/dist/app/board.d.ts +7 -0
- package/dist/app/board.js +47 -0
- package/dist/app/board.js.map +1 -0
- package/dist/app/define.d.ts +27 -0
- package/dist/app/define.js +68 -0
- package/dist/app/define.js.map +1 -0
- package/dist/app/doctor.js +5 -4
- package/dist/app/doctor.js.map +1 -1
- package/dist/app/factory.js +10 -2
- package/dist/app/factory.js.map +1 -1
- package/dist/app/run.d.ts +6 -0
- package/dist/app/run.js +25 -2
- package/dist/app/run.js.map +1 -1
- package/dist/app/workflows/implement.d.ts +8 -0
- package/dist/app/workflows/implement.js +297 -0
- package/dist/app/workflows/implement.js.map +1 -0
- package/dist/app/workflows/issue-save.d.ts +2 -0
- package/dist/app/workflows/issue-save.js +35 -0
- package/dist/app/workflows/issue-save.js.map +1 -0
- package/dist/cli/application.js +4 -4
- package/dist/cli/application.js.map +1 -1
- package/dist/cli/help.d.ts +1 -1
- package/dist/cli/help.js +8 -3
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/init.d.ts +2 -2
- package/dist/cli/init.js +4 -4
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/run.d.ts +3 -1
- package/dist/cli/run.js +44 -38
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/ui.d.ts +5 -2
- package/dist/cli/ui.js +20 -7
- package/dist/cli/ui.js.map +1 -1
- package/dist/domain/board.d.ts +65 -0
- package/dist/domain/board.js +95 -0
- package/dist/domain/board.js.map +1 -0
- package/dist/domain/definition.d.ts +15 -0
- package/dist/domain/definition.js +28 -0
- package/dist/domain/definition.js.map +1 -0
- package/dist/domain/delivery.d.ts +9 -0
- package/dist/domain/delivery.js +10 -0
- package/dist/domain/delivery.js.map +1 -0
- package/dist/domain/issue.d.ts +11 -0
- package/dist/domain/issue.js +22 -0
- package/dist/domain/issue.js.map +1 -0
- package/dist/domain/parsed.d.ts +8 -0
- package/dist/domain/parsed.js +2 -0
- package/dist/domain/parsed.js.map +1 -0
- package/dist/domain/plan.d.ts +24 -0
- package/dist/domain/plan.js +49 -0
- package/dist/domain/plan.js.map +1 -0
- package/dist/domain/pull-request.d.ts +17 -0
- package/dist/domain/pull-request.js +32 -0
- package/dist/domain/pull-request.js.map +1 -0
- package/dist/domain/review.d.ts +36 -0
- package/dist/domain/review.js +45 -0
- package/dist/domain/review.js.map +1 -0
- package/dist/domain/spec.d.ts +18 -0
- package/dist/domain/spec.js +118 -0
- package/dist/domain/spec.js.map +1 -0
- package/dist/domain/verification.d.ts +16 -0
- package/dist/domain/verification.js +11 -0
- package/dist/domain/verification.js.map +1 -0
- package/dist/index.d.ts +8 -4
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/system/checks.d.ts +32 -0
- package/dist/system/checks.js +49 -0
- package/dist/system/checks.js.map +1 -0
- package/dist/system/factory.d.ts +7 -5
- package/dist/system/factory.js +19 -19
- package/dist/system/factory.js.map +1 -1
- package/dist/system/git.d.ts +25 -0
- package/dist/system/git.js +73 -0
- package/dist/system/git.js.map +1 -0
- package/dist/system/github.d.ts +8 -0
- package/dist/system/github.js +52 -0
- package/dist/system/github.js.map +1 -0
- package/dist/system/issues.d.ts +24 -0
- package/dist/system/issues.js +66 -0
- package/dist/system/issues.js.map +1 -0
- package/dist/system/lock.d.ts +8 -0
- package/dist/system/lock.js +35 -0
- package/dist/system/lock.js.map +1 -0
- package/dist/system/templates.d.ts +2 -1
- package/dist/system/templates.js +69 -3
- package/dist/system/templates.js.map +1 -1
- package/package.json +6 -4
- package/prompts/implement/implement.md +21 -0
- package/prompts/implement/plan.md +20 -0
- package/prompts/implement/review.md +17 -0
- package/templates/init/factory.ts +37 -2
- package/templates/skills/issue/SKILL.md +82 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { agent, code, defineWorkflow, END, gate, node, retry, schemaGate, step, z, } from "@clemrig/flow";
|
|
2
|
+
import { isSlug } from "../../domain/issue.js";
|
|
3
|
+
import { planCommitMessage, planOutput, planProblem, renderPlan, } from "../../domain/plan.js";
|
|
4
|
+
import { DELIVERY } from "../../domain/delivery.js";
|
|
5
|
+
import { pullRequestBody } from "../../domain/pull-request.js";
|
|
6
|
+
import { implementationOutput, implementationProblem, reviewChanges, reviewOutput, reviewProblem, } from "../../domain/review.js";
|
|
7
|
+
import { parseSpec } from "../../domain/spec.js";
|
|
8
|
+
import { failureFeedback, seconds, } from "../../domain/verification.js";
|
|
9
|
+
import { runChecks } from "../../system/checks.js";
|
|
10
|
+
import * as git from "../../system/git.js";
|
|
11
|
+
import * as github from "../../system/github.js";
|
|
12
|
+
import { withTreeLock } from "../../system/lock.js";
|
|
13
|
+
import { artifactPath, hasArtifact, readArtifact, writeArtifact, } from "../../system/issues.js";
|
|
14
|
+
function facts(state) {
|
|
15
|
+
return state.data;
|
|
16
|
+
}
|
|
17
|
+
/** Corrections the review asked for so far. */
|
|
18
|
+
function reviewRounds(state) {
|
|
19
|
+
return state.retries?.["reviewed.changes"] ?? 0;
|
|
20
|
+
}
|
|
21
|
+
function short(commit) {
|
|
22
|
+
return commit.slice(0, 7);
|
|
23
|
+
}
|
|
24
|
+
/** Journals each check as it starts and passes: they can take minutes. */
|
|
25
|
+
function journalChecks(log, where = "") {
|
|
26
|
+
return ({ check, ...event }) => log(event.status === "started"
|
|
27
|
+
? `Running ${check.name}${where}: ${check.command.join(" ")}`
|
|
28
|
+
: `${check.name} passed in ${seconds(event.durationMs)}`);
|
|
29
|
+
}
|
|
30
|
+
/** Every reason not to start, found without changing anything; then the base must pass its checks. */
|
|
31
|
+
async function prepare(definition, { dir, state, log }) {
|
|
32
|
+
const slug = String(state.input.issue);
|
|
33
|
+
const base = await git.defaultBranch(dir);
|
|
34
|
+
const problems = [];
|
|
35
|
+
// The run commits and force-pushes on the branch the slug names.
|
|
36
|
+
if (slug === base)
|
|
37
|
+
problems.push(`Issue ${slug} names the main branch: its branch would replace ${base}; rename the issue`);
|
|
38
|
+
if ((await git.currentBranch(dir)) !== base)
|
|
39
|
+
problems.push(`Switch to ${base} first`);
|
|
40
|
+
if (await git.hasChanges(dir))
|
|
41
|
+
problems.push("Commit or discard the changes in progress first");
|
|
42
|
+
await git.fetchBranch(dir, base);
|
|
43
|
+
if ((await git.commitOf(dir, "HEAD")) !==
|
|
44
|
+
(await git.commitOf(dir, git.remoteRef(base))))
|
|
45
|
+
problems.push(`${base} must match origin/${base}: push or pull first`);
|
|
46
|
+
const text = await readArtifact(dir, slug, "spec");
|
|
47
|
+
const spec = text === undefined ? undefined : parseSpec(text);
|
|
48
|
+
if (!spec)
|
|
49
|
+
problems.push(`Issue ${slug} has no spec.md`);
|
|
50
|
+
else if (!spec.ok)
|
|
51
|
+
problems.push(...spec.problems.map((problem) => `spec.md: ${problem}`));
|
|
52
|
+
if (await hasArtifact(dir, slug, "plan"))
|
|
53
|
+
problems.push(`Issue ${slug} is already delivered (its plan.md is on ${base}): start a new issue`);
|
|
54
|
+
if (!(await github.isAuthenticated(dir)))
|
|
55
|
+
problems.push("gh is not logged in: run gh auth login");
|
|
56
|
+
if (problems.length > 0 || !spec?.ok || text === undefined)
|
|
57
|
+
throw new Error(["Cannot start:", ...problems.map((problem) => `- ${problem}`)].join("\n"));
|
|
58
|
+
log(`Starting point valid: ${base} matches origin, spec with ${spec.value.criteria.length} criteria, gh logged in`);
|
|
59
|
+
const baseCommit = await git.commitOf(dir, "HEAD");
|
|
60
|
+
const checks = await runChecks(dir, definition.verify, journalChecks(log, ` on ${base}`));
|
|
61
|
+
if (!checks.ok)
|
|
62
|
+
throw new Error(`${base} does not pass its own checks:\n${failureFeedback(checks.check, checks.cause, checks.output)}`);
|
|
63
|
+
// One run at a time per working tree: another one started during the checks
|
|
64
|
+
// may have moved it. Checking and taking the tree happen under one lock, so
|
|
65
|
+
// that two runs never both find it free; the branch starts from the approved
|
|
66
|
+
// commit, never from theirs.
|
|
67
|
+
await withTreeLock(dir, async () => {
|
|
68
|
+
const branch = await git.currentBranch(dir);
|
|
69
|
+
const head = await git.commitOf(dir, "HEAD");
|
|
70
|
+
if (branch !== base || head !== baseCommit)
|
|
71
|
+
throw new Error(`The repository moved while ${base}'s checks ran (now ${branch || "detached"} at ${short(head)}): another run is using it; start again once it is done`);
|
|
72
|
+
await git.switchTo(dir, slug, baseCommit);
|
|
73
|
+
});
|
|
74
|
+
log(`Created branch ${slug} from ${base} at ${short(baseCommit)}`);
|
|
75
|
+
return {
|
|
76
|
+
slug,
|
|
77
|
+
title: spec.value.title,
|
|
78
|
+
spec: text,
|
|
79
|
+
criteria: spec.value.criteria,
|
|
80
|
+
base,
|
|
81
|
+
baseCommit,
|
|
82
|
+
specPath: artifactPath(slug, "spec"),
|
|
83
|
+
planPath: artifactPath(slug, "plan"),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/** The implementing agent may not commit, switch branches or touch .factory/: the run stops if it did. */
|
|
87
|
+
async function guard({ dir, state }) {
|
|
88
|
+
const { slug, planCommit } = facts(state);
|
|
89
|
+
if ((await git.commitOf(dir, "HEAD")) !== planCommit ||
|
|
90
|
+
(await git.currentBranch(dir)) !== slug)
|
|
91
|
+
throw new Error("The implementing agent committed or switched branches: the run stops");
|
|
92
|
+
if (await git.hasChanges(dir, ".factory"))
|
|
93
|
+
throw new Error("The implementing agent changed .factory/: the run stops");
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* A failed run resumes on its branch, at the commit its stage started from,
|
|
97
|
+
* with its changes in progress and none in .factory/ but the plan it may have
|
|
98
|
+
* written; `prepare` checks everything again, and a delivered run is done.
|
|
99
|
+
*/
|
|
100
|
+
async function resumeProblem({ dir, state, }) {
|
|
101
|
+
if (state.stage === "prepare")
|
|
102
|
+
return undefined;
|
|
103
|
+
// Stopped once its last stage was done, such as by Ctrl-C.
|
|
104
|
+
const { pullRequest } = state.data;
|
|
105
|
+
if (typeof pullRequest === "string")
|
|
106
|
+
return `the run already delivered its pull request ${pullRequest}`;
|
|
107
|
+
const { slug, baseCommit, planPath } = facts(state);
|
|
108
|
+
// Until the plan is committed, the branch is at the run's starting commit.
|
|
109
|
+
const { planCommit } = state.data;
|
|
110
|
+
const expected = typeof planCommit === "string" ? planCommit : baseCommit;
|
|
111
|
+
const branch = await git.currentBranch(dir);
|
|
112
|
+
const head = await git.commitOf(dir, "HEAD");
|
|
113
|
+
const problems = [];
|
|
114
|
+
if (branch !== slug || head !== expected)
|
|
115
|
+
problems.push(`the repository must be on ${slug} at ${short(expected)}, where the run stopped, with its changes in progress; it is on ${branch || "a detached HEAD"} at ${short(head)}${state.stage === "deliver" && branch === slug
|
|
116
|
+
? `; if the run already committed its changes, git reset --soft ${short(expected)} puts them back in progress`
|
|
117
|
+
: ""}`);
|
|
118
|
+
// `commit-plan` writes the plan again before committing it.
|
|
119
|
+
if (await git.hasChanges(dir, ".factory", state.stage === "commit-plan" ? planPath : undefined))
|
|
120
|
+
problems.push(".factory/ has changes in progress, which a run never delivers: discard them");
|
|
121
|
+
return problems.length ? problems.join("; ") : undefined;
|
|
122
|
+
}
|
|
123
|
+
/** Plans, implements, checks and reviews an approved spec, then opens its pull request. */
|
|
124
|
+
export function implement(definition) {
|
|
125
|
+
return defineWorkflow({
|
|
126
|
+
name: DELIVERY,
|
|
127
|
+
input: z.object({
|
|
128
|
+
issue: z
|
|
129
|
+
.string()
|
|
130
|
+
.refine(isSlug, "Expected lowercase words separated by hyphens"),
|
|
131
|
+
}),
|
|
132
|
+
maxCostUsd: definition.maxCostUsd,
|
|
133
|
+
initial: "prepare",
|
|
134
|
+
// The issue's card shows these steps; each check counts in the step it checks.
|
|
135
|
+
steps: [
|
|
136
|
+
{ name: "prepare", stages: ["prepare"] },
|
|
137
|
+
{ name: "plan", stages: ["plan", "planned", "commit-plan"] },
|
|
138
|
+
{ name: "implement", stages: ["implement", "implemented"] },
|
|
139
|
+
{ name: "verify", stages: ["verify"] },
|
|
140
|
+
{ name: "review", stages: ["diff", "review", "reviewed"] },
|
|
141
|
+
{ name: "deliver", stages: ["deliver"] },
|
|
142
|
+
],
|
|
143
|
+
nodes: {
|
|
144
|
+
prepare: node(step((context) => prepare(definition, context)), { ok: "plan" }),
|
|
145
|
+
plan: node(agent({
|
|
146
|
+
profile: definition.profiles.plan,
|
|
147
|
+
schema: planOutput,
|
|
148
|
+
context: ({ state }) => ({
|
|
149
|
+
issue: facts(state).slug,
|
|
150
|
+
spec: facts(state).spec,
|
|
151
|
+
}),
|
|
152
|
+
}), { ok: "planned" }),
|
|
153
|
+
planned: node(schemaGate({
|
|
154
|
+
schema: planOutput,
|
|
155
|
+
into: "plan",
|
|
156
|
+
check: (plan, { state }) => planProblem(plan, facts(state).criteria),
|
|
157
|
+
}), { ok: "commit-plan", invalid: retry("plan", 2) }),
|
|
158
|
+
"commit-plan": node(step(async ({ dir, state, log }) => {
|
|
159
|
+
const { slug, title, specPath, baseCommit, plan } = facts(state);
|
|
160
|
+
await writeArtifact(dir, slug, "plan", renderPlan(plan, { title, specPath, baseCommit }));
|
|
161
|
+
const planCommit = await git.commit(dir, planCommitMessage(slug), [
|
|
162
|
+
artifactPath(slug, "plan"),
|
|
163
|
+
]);
|
|
164
|
+
log(`Committed plan.md (${plan.steps.length} steps) as ${short(planCommit)}`);
|
|
165
|
+
return { planCommit };
|
|
166
|
+
}), { ok: "implement" }),
|
|
167
|
+
implement: node(agent({
|
|
168
|
+
profile: definition.profiles.implement,
|
|
169
|
+
schema: implementationOutput,
|
|
170
|
+
context: ({ state }) => {
|
|
171
|
+
const { slug, spec, plan } = facts(state);
|
|
172
|
+
return { issue: slug, spec, plan };
|
|
173
|
+
},
|
|
174
|
+
}), { ok: "implemented" }),
|
|
175
|
+
implemented: node(gate(["ok", "invalid"], async (context) => {
|
|
176
|
+
// First what the agent did, whatever it answered: a malformed
|
|
177
|
+
// response must not hide a change it may not make.
|
|
178
|
+
await guard(context);
|
|
179
|
+
const parsed = implementationOutput.safeParse(context.state.output);
|
|
180
|
+
if (!parsed.success)
|
|
181
|
+
return {
|
|
182
|
+
outcome: "invalid",
|
|
183
|
+
reason: `Invalid structured output:\n${z.prettifyError(parsed.error)}`,
|
|
184
|
+
};
|
|
185
|
+
const problem = implementationProblem(parsed.data, facts(context.state).criteria);
|
|
186
|
+
if (problem)
|
|
187
|
+
return { outcome: "invalid", reason: problem };
|
|
188
|
+
return {
|
|
189
|
+
outcome: "ok",
|
|
190
|
+
reason: "Structured output and invariants valid: implementation",
|
|
191
|
+
data: { implementation: parsed.data },
|
|
192
|
+
};
|
|
193
|
+
}), { ok: "verify", invalid: retry("implement", 2) }),
|
|
194
|
+
verify: node(code(["passed", "failed"], async ({ dir, log }) => {
|
|
195
|
+
const checks = await runChecks(dir, definition.verify, journalChecks(log));
|
|
196
|
+
if (checks.ok)
|
|
197
|
+
return {
|
|
198
|
+
outcome: "passed",
|
|
199
|
+
reason: "Every check passed",
|
|
200
|
+
data: { checks: checks.passed },
|
|
201
|
+
};
|
|
202
|
+
return {
|
|
203
|
+
outcome: "failed",
|
|
204
|
+
reason: `${checks.check.name} failed: ${checks.cause}`,
|
|
205
|
+
feedback: failureFeedback(checks.check, checks.cause, checks.output),
|
|
206
|
+
};
|
|
207
|
+
}), { passed: "diff", failed: retry("implement", 3) }),
|
|
208
|
+
diff: node(step(async ({ dir, state, log }) => {
|
|
209
|
+
const diff = await git.stagedDiff(dir, facts(state).planCommit);
|
|
210
|
+
if (diff.truncated)
|
|
211
|
+
throw new Error("The changes are too large to review (over 2 MiB of diff): the run stops");
|
|
212
|
+
const files = diff.text.match(/^diff --git /gm)?.length ?? 0;
|
|
213
|
+
log(`Changes since the plan: ${files} files, ${diff.text.split("\n").length} diff lines`);
|
|
214
|
+
return { diff: diff.text };
|
|
215
|
+
}), { ok: "review" }),
|
|
216
|
+
review: node(agent({
|
|
217
|
+
profile: definition.profiles.review,
|
|
218
|
+
schema: reviewOutput,
|
|
219
|
+
// A new conversation for each review; a correction of its format resumes it.
|
|
220
|
+
session: (state) => `review-${reviewRounds(state)}`,
|
|
221
|
+
context: ({ state }) => {
|
|
222
|
+
const { slug, spec, diff, checks } = facts(state);
|
|
223
|
+
return { issue: slug, spec, diff, checks };
|
|
224
|
+
},
|
|
225
|
+
}), { ok: "reviewed" }),
|
|
226
|
+
reviewed: node(gate(["approved", "changes", "invalid"], async ({ state }) => {
|
|
227
|
+
const parsed = reviewOutput.safeParse(state.output);
|
|
228
|
+
if (!parsed.success)
|
|
229
|
+
return {
|
|
230
|
+
outcome: "invalid",
|
|
231
|
+
reason: `Invalid structured output:\n${z.prettifyError(parsed.error)}`,
|
|
232
|
+
};
|
|
233
|
+
const problem = reviewProblem(parsed.data, facts(state).criteria);
|
|
234
|
+
if (problem)
|
|
235
|
+
return { outcome: "invalid", reason: problem };
|
|
236
|
+
const changes = reviewChanges(parsed.data);
|
|
237
|
+
if (changes)
|
|
238
|
+
return {
|
|
239
|
+
outcome: "changes",
|
|
240
|
+
reason: "The review requires changes",
|
|
241
|
+
feedback: changes,
|
|
242
|
+
data: { review: parsed.data },
|
|
243
|
+
};
|
|
244
|
+
return {
|
|
245
|
+
outcome: "approved",
|
|
246
|
+
reason: "Every criterion is met and nothing blocks",
|
|
247
|
+
data: { review: parsed.data },
|
|
248
|
+
};
|
|
249
|
+
}), {
|
|
250
|
+
approved: "deliver",
|
|
251
|
+
changes: retry("implement", 2),
|
|
252
|
+
invalid: retry("review", 2),
|
|
253
|
+
}),
|
|
254
|
+
deliver: node(step(async ({ dir, state, log }) => {
|
|
255
|
+
const { slug, base, plan, specPath, planPath, baseCommit, criteria, implementation, review, checks, } = facts(state);
|
|
256
|
+
const commit = await git.commit(dir, `${plan.commit}\n\nSpec: ${specPath}`);
|
|
257
|
+
log(`Committed "${plan.commit}" as ${short(commit)}`);
|
|
258
|
+
await git.forcePush(dir, slug);
|
|
259
|
+
log(`Pushed ${slug}, replacing any earlier version of the branch`);
|
|
260
|
+
const pullRequest = await github.openPullRequest(dir, {
|
|
261
|
+
base,
|
|
262
|
+
head: slug,
|
|
263
|
+
title: plan.commit,
|
|
264
|
+
body: pullRequestBody({
|
|
265
|
+
criteria,
|
|
266
|
+
implementation,
|
|
267
|
+
review,
|
|
268
|
+
checks,
|
|
269
|
+
reviewRounds: reviewRounds(state),
|
|
270
|
+
specPath,
|
|
271
|
+
planPath,
|
|
272
|
+
baseCommit,
|
|
273
|
+
runId: state.id,
|
|
274
|
+
}),
|
|
275
|
+
});
|
|
276
|
+
log(`Pull request: ${pullRequest}`);
|
|
277
|
+
await git.switchTo(dir, base);
|
|
278
|
+
log(`Back on ${base}`);
|
|
279
|
+
return { pullRequest };
|
|
280
|
+
}), { ok: END }),
|
|
281
|
+
},
|
|
282
|
+
resumeProblem,
|
|
283
|
+
// Also called for a failed run, which opened no pull request.
|
|
284
|
+
presentResult: (state) => {
|
|
285
|
+
const { pullRequest, checks } = facts(state);
|
|
286
|
+
if (typeof pullRequest !== "string")
|
|
287
|
+
return [];
|
|
288
|
+
const rounds = reviewRounds(state);
|
|
289
|
+
return [
|
|
290
|
+
`Pull request: ${pullRequest}`,
|
|
291
|
+
`Review: approved ${rounds === 0 ? "at the first review" : `after ${rounds} round${rounds === 1 ? "" : "s"} of changes`}`,
|
|
292
|
+
`Checks passed: ${checks.map(({ name }) => name).join(", ")}`,
|
|
293
|
+
];
|
|
294
|
+
},
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=implement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"implement.js","sourceRoot":"","sources":["../../../src/app/workflows/implement.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { defineWorkflow, END, node, step, z } from "@clemrig/flow";
|
|
2
|
+
import { isSlug, parseIssue } from "../../domain/issue.js";
|
|
3
|
+
import { parseSpec } from "../../domain/spec.js";
|
|
4
|
+
import { hasArtifact, readDraft, writeArtifact } from "../../system/issues.js";
|
|
5
|
+
const input = z.object({
|
|
6
|
+
issue: z
|
|
7
|
+
.string()
|
|
8
|
+
.refine(isSlug, "Expected lowercase words separated by hyphens"),
|
|
9
|
+
kind: z.enum(["issue", "spec"]),
|
|
10
|
+
file: z.string().min(1),
|
|
11
|
+
});
|
|
12
|
+
/** Checks a draft written by an agent, then writes it as the issue's issue.md or spec.md. */
|
|
13
|
+
export const issueSave = defineWorkflow({
|
|
14
|
+
name: "issue-save",
|
|
15
|
+
input,
|
|
16
|
+
initial: "save",
|
|
17
|
+
nodes: {
|
|
18
|
+
save: node(step(async ({ dir, state }) => {
|
|
19
|
+
const { issue, kind, file } = state.input;
|
|
20
|
+
if (kind === "spec" && !(await hasArtifact(dir, issue, "issue")))
|
|
21
|
+
throw new Error(`Issue ${issue} does not exist: save its issue.md first`);
|
|
22
|
+
const text = await readDraft(file);
|
|
23
|
+
const parsed = kind === "issue" ? parseIssue(text) : parseSpec(text);
|
|
24
|
+
if (!parsed.ok)
|
|
25
|
+
throw new Error([
|
|
26
|
+
`Invalid ${kind}.md draft ${file}:`,
|
|
27
|
+
...parsed.problems.map((problem) => `- ${problem}`),
|
|
28
|
+
].join("\n"));
|
|
29
|
+
return { path: await writeArtifact(dir, issue, kind, text) };
|
|
30
|
+
}), { ok: END }),
|
|
31
|
+
},
|
|
32
|
+
// Also called for a failed run, which saved nothing.
|
|
33
|
+
presentResult: ({ data }) => typeof data.path === "string" ? [`Saved ${data.path}`] : [],
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=issue-save.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-save.js","sourceRoot":"","sources":["../../../src/app/workflows/issue-save.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE/E,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC;IACrB,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,MAAM,CAAC,MAAM,EAAE,+CAA+C,CAAC;IAClE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACxB,CAAC,CAAC;AAGH,6FAA6F;AAC7F,MAAM,CAAC,MAAM,SAAS,GAAG,cAAc,CAAC;IACtC,IAAI,EAAE,YAAY;IAClB,KAAK;IACL,OAAO,EAAE,MAAM;IACf,KAAK,EAAE;QACL,IAAI,EAAE,IAAI,CACR,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;YAC5B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,KAAc,CAAC;YACnD,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,WAAW,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;gBAC9D,MAAM,IAAI,KAAK,CACb,SAAS,KAAK,0CAA0C,CACzD,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACrE,IAAI,CAAC,MAAM,CAAC,EAAE;gBACZ,MAAM,IAAI,KAAK,CACb;oBACE,WAAW,IAAI,aAAa,IAAI,GAAG;oBACnC,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,OAAO,EAAE,CAAC;iBACpD,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;YACJ,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QAC/D,CAAC,CAAC,EACF,EAAE,EAAE,EAAE,GAAG,EAAE,CACZ;KACF;IACD,qDAAqD;IACrD,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAC1B,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;CAC9D,CAAC,CAAC"}
|
package/dist/cli/application.js
CHANGED
|
@@ -5,7 +5,7 @@ import { noOptions, parseArgs } from "./args.js";
|
|
|
5
5
|
import { doctor } from "./doctor.js";
|
|
6
6
|
import { help } from "./help.js";
|
|
7
7
|
import { TerminalReporter } from "./reporter.js";
|
|
8
|
-
import { run } from "./run.js";
|
|
8
|
+
import { resume, run } from "./run.js";
|
|
9
9
|
import { status } from "./status.js";
|
|
10
10
|
import { ui } from "./ui.js";
|
|
11
11
|
/** `--port`: a fixed port, so that an SSH tunnel can forward the same one. */
|
|
@@ -33,10 +33,10 @@ export async function main(argv, directory) {
|
|
|
33
33
|
noOptions(args);
|
|
34
34
|
return await doctor(factoryDir, args.json);
|
|
35
35
|
}
|
|
36
|
-
if (args.command === "run") {
|
|
36
|
+
if (args.command === "run" || args.command === "resume") {
|
|
37
37
|
const factory = await openFactory(factoryDir);
|
|
38
38
|
const reporter = new TerminalReporter((state) => presentResult(factory, state), args.json);
|
|
39
|
-
return await run(factory, args, reporter);
|
|
39
|
+
return await (args.command === "run" ? run : resume)(factory, args, reporter);
|
|
40
40
|
}
|
|
41
41
|
if (!["status", "ui"].includes(args.command))
|
|
42
42
|
throw new Error(`Unknown command ${args.command}; see factory help`);
|
|
@@ -51,7 +51,7 @@ export async function main(argv, directory) {
|
|
|
51
51
|
if (error)
|
|
52
52
|
process.stderr.write(`factory: factory.ts cannot be loaded, results use the default rendering: ${error}\n`);
|
|
53
53
|
if (args.command === "ui")
|
|
54
|
-
return await ui(factory, dashboardPort);
|
|
54
|
+
return await ui(factory, dashboardPort, error);
|
|
55
55
|
const reporter = new TerminalReporter((state) => presentResult(factory, state), args.json);
|
|
56
56
|
return await status(factory, reporter, args.positional[0]);
|
|
57
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application.js","sourceRoot":"","sources":["../../src/cli/application.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"application.js","sourceRoot":"","sources":["../../src/cli/application.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/help.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const help = "factory \u2014
|
|
1
|
+
export declare const help = "factory \u2014 this repository's issues, from spec to pull request, with .factory/\n\n factory init create .factory/ here and install it\n factory doctor [--json] check Node, workflows, prompts and runtimes\n factory run WORKFLOW [--INPUT VALUE\u2026] [--max-cost-usd USD] [--json]\n factory resume RUN_ID [--max-cost-usd USD] [--json]\n factory status [RUN_ID] [--json] list this repository's runs, or show one\n factory ui [--port N] serve the live read-only Kanban, runs under /runs/\n\nCommands other than init and help use the nearest .factory/ in the current directory\nor a parent, with the factory version installed there. factory doctor lists each\nworkflow's input options. factory run issue-save saves an issue or its spec;\nfactory run implement --issue SLUG takes a pushed spec to a pull request.\n.factory/.env is loaded; shell variables take precedence.\n--max-cost-usd fails the run once its agents' announced cost exceeds it, instead\nof the workflow's maxCostUsd. --json writes events, then the result, as JSON lines.\nCtrl-C stops a run, which ends failed; press it again to quit at once.\nfactory resume starts a failed run again at the stage where it stopped, with its\ndata and its agents' conversations.\nExit codes: 0 completed, 1 error or failed run, 130 second Ctrl-C.\n";
|
package/dist/cli/help.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
export const help = `factory —
|
|
1
|
+
export const help = `factory — this repository's issues, from spec to pull request, with .factory/
|
|
2
2
|
|
|
3
3
|
factory init create .factory/ here and install it
|
|
4
4
|
factory doctor [--json] check Node, workflows, prompts and runtimes
|
|
5
5
|
factory run WORKFLOW [--INPUT VALUE…] [--max-cost-usd USD] [--json]
|
|
6
|
+
factory resume RUN_ID [--max-cost-usd USD] [--json]
|
|
6
7
|
factory status [RUN_ID] [--json] list this repository's runs, or show one
|
|
7
|
-
factory ui [--port N] serve
|
|
8
|
+
factory ui [--port N] serve the live read-only Kanban, runs under /runs/
|
|
8
9
|
|
|
9
10
|
Commands other than init and help use the nearest .factory/ in the current directory
|
|
10
11
|
or a parent, with the factory version installed there. factory doctor lists each
|
|
11
|
-
workflow's input options.
|
|
12
|
+
workflow's input options. factory run issue-save saves an issue or its spec;
|
|
13
|
+
factory run implement --issue SLUG takes a pushed spec to a pull request.
|
|
14
|
+
.factory/.env is loaded; shell variables take precedence.
|
|
12
15
|
--max-cost-usd fails the run once its agents' announced cost exceeds it, instead
|
|
13
16
|
of the workflow's maxCostUsd. --json writes events, then the result, as JSON lines.
|
|
14
17
|
Ctrl-C stops a run, which ends failed; press it again to quit at once.
|
|
18
|
+
factory resume starts a failed run again at the stage where it stopped, with its
|
|
19
|
+
data and its agents' conversations.
|
|
15
20
|
Exit codes: 0 completed, 1 error or failed run, 130 second Ctrl-C.
|
|
16
21
|
`;
|
|
17
22
|
//# sourceMappingURL=help.js.map
|
package/dist/cli/help.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;CAoBnB,CAAC"}
|
package/dist/cli/init.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `factory init`: creates `.factory/` in `cwd` from the templates, pinned to this
|
|
3
|
-
* factory version, then installs it. An existing
|
|
4
|
-
* a failed installation keeps the files.
|
|
3
|
+
* factory version, and the `issue` skill, then installs it. An existing
|
|
4
|
+
* `.factory/` or skill is refused untouched; a failed installation keeps the files.
|
|
5
5
|
*/
|
|
6
6
|
export declare function init(cwd: string): Promise<number>;
|
package/dist/cli/init.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { createFactory, installFactory } from "../app/init.js";
|
|
2
2
|
/**
|
|
3
3
|
* `factory init`: creates `.factory/` in `cwd` from the templates, pinned to this
|
|
4
|
-
* factory version, then installs it. An existing
|
|
5
|
-
* a failed installation keeps the files.
|
|
4
|
+
* factory version, and the `issue` skill, then installs it. An existing
|
|
5
|
+
* `.factory/` or skill is refused untouched; a failed installation keeps the files.
|
|
6
6
|
*/
|
|
7
7
|
export async function init(cwd) {
|
|
8
8
|
const { factoryDir, version } = await createFactory(cwd);
|
|
9
|
-
process.stdout.write(`Created ${factoryDir}; installing @clemrig/factory ${version}…\n`);
|
|
9
|
+
process.stdout.write(`Created ${factoryDir} and the issue skill (.agents/skills/issue, linked from .claude/skills/issue); installing @clemrig/factory ${version}…\n`);
|
|
10
10
|
const install = await installFactory(factoryDir);
|
|
11
11
|
if (!install.ok) {
|
|
12
12
|
process.stderr.write(`${install.output}\n`);
|
|
13
13
|
throw new Error("Installation failed; .factory/ is kept: run npm install --prefix .factory");
|
|
14
14
|
}
|
|
15
|
-
process.stdout.write(
|
|
15
|
+
process.stdout.write("Next: set your checks in .factory/factory.ts, run factory doctor, commit .factory/, .agents/ and .claude/skills/, then use /issue in Claude Code, Codex or Pi\n");
|
|
16
16
|
return 0;
|
|
17
17
|
}
|
|
18
18
|
//# sourceMappingURL=init.js.map
|
package/dist/cli/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,GAAW;IACpC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;IACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,WAAW,UAAU,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,GAAW;IACpC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;IACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,WAAW,UAAU,8GAA8G,OAAO,KAAK,CAChJ,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,CAAC;IACjD,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QAC5C,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,iKAAiK,CAClK,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC"}
|
package/dist/cli/run.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Factory } from "../app/factory.js";
|
|
2
2
|
import type { Arguments } from "./args.js";
|
|
3
3
|
import type { TerminalReporter } from "./reporter.js";
|
|
4
|
-
/** `factory run`: the run executes in the foreground
|
|
4
|
+
/** `factory run`: the run executes in the foreground. */
|
|
5
5
|
export declare function run(factory: Factory, args: Arguments, reporter: TerminalReporter): Promise<number>;
|
|
6
|
+
/** `factory resume`: a failed run starts again, in the foreground, at the stage where it stopped. */
|
|
7
|
+
export declare function resume(factory: Factory, args: Arguments, reporter: TerminalReporter): Promise<number>;
|
package/dist/cli/run.js
CHANGED
|
@@ -1,47 +1,39 @@
|
|
|
1
|
-
import { killChildProcesses } from "@clemrig/flow";
|
|
2
|
-
import { startRun } from "../app/run.js";
|
|
1
|
+
import { killChildProcesses, } from "@clemrig/flow";
|
|
2
|
+
import { resumeRun, startRun } from "../app/run.js";
|
|
3
3
|
/**
|
|
4
|
-
* Starts the run
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Starts or resumes the run in the repository, as the current directory so
|
|
5
|
+
* that relative paths in workflow code resolve there, and waits for its end.
|
|
6
|
+
* The first SIGINT or SIGTERM stops it before its next stage (child processes
|
|
7
|
+
* are stopped at once); a second one kills the child process groups and exits
|
|
8
|
+
* with 130.
|
|
7
9
|
*/
|
|
8
|
-
async function execute(factory,
|
|
9
|
-
const started = await startRun(factory, name, options, {
|
|
10
|
-
onEvent: reporter.event,
|
|
11
|
-
});
|
|
12
|
-
for (const runtime of started.runtimes)
|
|
13
|
-
reporter.runtime(runtime.detail);
|
|
14
|
-
let interrupted = false;
|
|
15
|
-
const interrupt = (signal) => {
|
|
16
|
-
if (interrupted) {
|
|
17
|
-
killChildProcesses();
|
|
18
|
-
process.exit(130);
|
|
19
|
-
}
|
|
20
|
-
interrupted = true;
|
|
21
|
-
reporter.detail(`${signal} received: stopping the run; press Ctrl-C again to quit at once`);
|
|
22
|
-
started.stop(new Error(`Run interrupted by ${signal}`));
|
|
23
|
-
};
|
|
24
|
-
process.on("SIGINT", interrupt);
|
|
25
|
-
process.on("SIGTERM", interrupt);
|
|
26
|
-
try {
|
|
27
|
-
return await started.done;
|
|
28
|
-
}
|
|
29
|
-
finally {
|
|
30
|
-
process.off("SIGINT", interrupt);
|
|
31
|
-
process.off("SIGTERM", interrupt);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/** `factory run`: the run executes in the foreground, with the repository as the current directory. */
|
|
35
|
-
export async function run(factory, args, reporter) {
|
|
36
|
-
const name = args.positional[0];
|
|
37
|
-
if (!name)
|
|
38
|
-
throw new Error(`Usage: factory run WORKFLOW [--INPUT VALUE…]; workflows: ${[...factory.workflows.keys()].join(", ") || "none"}`);
|
|
39
|
-
// Relative paths in workflow code resolve in the repository, wherever the command was started.
|
|
10
|
+
async function execute(factory, launch, reporter) {
|
|
40
11
|
const previous = process.cwd();
|
|
41
12
|
process.chdir(factory.dir);
|
|
42
13
|
let state;
|
|
43
14
|
try {
|
|
44
|
-
|
|
15
|
+
const started = await launch({ onEvent: reporter.event });
|
|
16
|
+
for (const runtime of started.runtimes)
|
|
17
|
+
reporter.runtime(runtime.detail);
|
|
18
|
+
let interrupted = false;
|
|
19
|
+
const interrupt = (signal) => {
|
|
20
|
+
if (interrupted) {
|
|
21
|
+
killChildProcesses();
|
|
22
|
+
process.exit(130);
|
|
23
|
+
}
|
|
24
|
+
interrupted = true;
|
|
25
|
+
reporter.detail(`${signal} received: stopping the run; press Ctrl-C again to quit at once`);
|
|
26
|
+
started.stop(new Error(`Run interrupted by ${signal}`));
|
|
27
|
+
};
|
|
28
|
+
process.on("SIGINT", interrupt);
|
|
29
|
+
process.on("SIGTERM", interrupt);
|
|
30
|
+
try {
|
|
31
|
+
state = await started.done;
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
process.off("SIGINT", interrupt);
|
|
35
|
+
process.off("SIGTERM", interrupt);
|
|
36
|
+
}
|
|
45
37
|
}
|
|
46
38
|
finally {
|
|
47
39
|
process.chdir(previous);
|
|
@@ -49,4 +41,18 @@ export async function run(factory, args, reporter) {
|
|
|
49
41
|
reporter.result(state);
|
|
50
42
|
return state.status === "completed" ? 0 : 1;
|
|
51
43
|
}
|
|
44
|
+
/** `factory run`: the run executes in the foreground. */
|
|
45
|
+
export async function run(factory, args, reporter) {
|
|
46
|
+
const name = args.positional[0];
|
|
47
|
+
if (!name)
|
|
48
|
+
throw new Error(`Usage: factory run WORKFLOW [--INPUT VALUE…]; workflows: ${[...factory.workflows.keys()].join(", ") || "none"}`);
|
|
49
|
+
return execute(factory, (hooks) => startRun(factory, name, args.options, hooks), reporter);
|
|
50
|
+
}
|
|
51
|
+
/** `factory resume`: a failed run starts again, in the foreground, at the stage where it stopped. */
|
|
52
|
+
export async function resume(factory, args, reporter) {
|
|
53
|
+
const runId = args.positional[0];
|
|
54
|
+
if (!runId)
|
|
55
|
+
throw new Error("Usage: factory resume RUN_ID [--max-cost-usd USD]; factory status lists the runs");
|
|
56
|
+
return execute(factory, (hooks) => resumeRun(factory, runId, args.options, hooks), reporter);
|
|
57
|
+
}
|
|
52
58
|
//# sourceMappingURL=run.js.map
|
package/dist/cli/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
|