@clemrig/factory 0.6.1 → 0.7.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 +56 -26
- package/dist/app/define.js +1 -1
- package/dist/app/define.js.map +1 -1
- package/dist/app/init.d.ts +1 -0
- package/dist/app/init.js +1 -0
- package/dist/app/init.js.map +1 -1
- package/dist/app/run.d.ts +2 -1
- package/dist/app/run.js +16 -4
- package/dist/app/run.js.map +1 -1
- package/dist/app/workflows/implement.d.ts +1 -1
- package/dist/app/workflows/implement.js +290 -73
- package/dist/app/workflows/implement.js.map +1 -1
- package/dist/cli/help.d.ts +1 -1
- package/dist/cli/help.js +4 -2
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/init.d.ts +3 -2
- package/dist/cli/init.js +10 -3
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/run.js +1 -1
- package/dist/cli/run.js.map +1 -1
- package/dist/domain/definition.d.ts +2 -0
- package/dist/domain/definition.js +1 -0
- package/dist/domain/definition.js.map +1 -1
- package/dist/domain/description.d.ts +51 -0
- package/dist/domain/description.js +78 -0
- package/dist/domain/description.js.map +1 -0
- package/dist/domain/plan.d.ts +2 -0
- package/dist/domain/plan.js +15 -0
- package/dist/domain/plan.js.map +1 -1
- package/dist/domain/pull-request.d.ts +42 -8
- package/dist/domain/pull-request.js +287 -24
- package/dist/domain/pull-request.js.map +1 -1
- package/dist/domain/review.d.ts +9 -1
- package/dist/domain/review.js +30 -5
- package/dist/domain/review.js.map +1 -1
- package/dist/system/browser.d.ts +29 -0
- package/dist/system/browser.js +84 -0
- package/dist/system/browser.js.map +1 -0
- package/dist/system/github.d.ts +15 -0
- package/dist/system/github.js +36 -2
- package/dist/system/github.js.map +1 -1
- package/dist/system/run-files.d.ts +14 -0
- package/dist/system/run-files.js +69 -2
- package/dist/system/run-files.js.map +1 -1
- package/dist/system/templates.d.ts +3 -2
- package/dist/system/templates.js +8 -3
- package/dist/system/templates.js.map +1 -1
- package/package.json +3 -3
- package/prompts/implement/describe.md +74 -0
- package/prompts/implement/implement.md +25 -8
- package/prompts/implement/plan.md +35 -7
- package/prompts/implement/review.md +43 -16
- package/templates/init/factory.ts +23 -5
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ An idea becomes an issue; the operator specifies it with an agent; one run then
|
|
|
7
7
|
## Requirements
|
|
8
8
|
|
|
9
9
|
- macOS or Linux, Node.js 24 or later, npm.
|
|
10
|
-
- For the `implement` run: Git, a GitHub repository whose remote is `origin`, with `origin/HEAD` naming the main branch (`git clone` sets it; otherwise `git remote set-head origin --auto`), and the [GitHub CLI](https://cli.github.com) `gh` logged in (`gh auth login`).
|
|
10
|
+
- For the `implement` run: Git, a GitHub repository whose remote is `origin`, with `origin/HEAD` naming the main branch (`git clone` sets it; otherwise `git remote set-head origin --auto`), and the [GitHub CLI](https://cli.github.com) `gh` 2.99.0 or later (it attaches screenshots to the pull request), logged in (`gh auth login`).
|
|
11
11
|
- For agents run by Claude Code: the `claude` CLI 2.1.296 or later in the `PATH`, logged in with a claude.ai subscription (`claude`, then `/login`) or given an API key (`ANTHROPIC_API_KEY`).
|
|
12
12
|
- For agents run by Codex: the `codex` CLI 0.160.1 or later in the `PATH`, logged in with a ChatGPT account or an API key (`codex login`) or given an API key (`CODEX_API_KEY`); Codex works only in a Git repository.
|
|
13
13
|
- For agents run by Pi: the `pi` CLI (`@earendil-works/pi-coding-agent` 1.1.0 or later) in the `PATH`, connected to the provider each Pi profile names (`pi`, then `/login`, or the provider's API key).
|
|
@@ -23,11 +23,11 @@ factory init
|
|
|
23
23
|
factory doctor
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
`factory init` creates `.factory/` and the `issue` skill in the current directory, then installs `.factory
|
|
26
|
+
`factory init` creates `.factory/` and the `issue` skill in the current directory, then installs `.factory/`, with [Playwright CLI](https://github.com/microsoft/playwright-cli), the agents' browser, and downloads the Chromium it opens; when the download fails, it gives the command that runs it again. It refuses, writing nothing, an existing `.factory/` or an existing `.agents/skills/issue` or `.claude/skills/issue`. When `.claude`, `.claude/skills` or `.agents` are links, the skill's link is made to resolve from the folder it really lands in, and none is made when `.claude/skills` leads to `.agents/skills`. Set the repository's checks in `.factory/factory.ts`, run `factory doctor`, then commit `.factory/`, `.agents/` and `.claude/skills/`: another machine only needs `npm ci --prefix .factory`, then `.factory/node_modules/.bin/playwright-cli install-browser chromium` for the agents' browser.
|
|
27
27
|
|
|
28
28
|
```
|
|
29
29
|
.factory/
|
|
30
|
-
package.json pins the exact factory
|
|
30
|
+
package.json pins the exact factory and Playwright CLI versions
|
|
31
31
|
factory.ts the repository's factory: checks, budget, agents, own workflows
|
|
32
32
|
workflows/ask/
|
|
33
33
|
index.ts an example workflow of the repository
|
|
@@ -51,9 +51,9 @@ The global `factory` command uses the nearest `.factory/` holding a `package.jso
|
|
|
51
51
|
4. **Executing.** `factory run implement --issue <slug>`: starting the run approves the spec. It runs without the operator; follow it in `factory ui`.
|
|
52
52
|
5. **To Approve → Done.** Review and merge the pull request. After `git pull`, `plan.md` is on the main branch: the issue is done. Its folder stays.
|
|
53
53
|
|
|
54
|
-
A failed run stops; past `prepare`, it leaves the repository on the branch `<slug>`, with the agent's changes, for inspection. When the cause has passed (a timeout, the budget, the network, a Git hook), `factory resume <RUN_ID>` starts the stopped stage again, its agent in the same conversation: the repository must still be on `<slug>` at the commit where the run stopped (the plan's commit, or the starting commit before it), with its changes in progress and none in `.factory/`; a delivery that stopped after its commit resumes once `git reset --soft <plan commit>` puts the changes back in progress, as the refusal says, a run whose pull request is recorded in its state, stopped once its delivery was done, does not resume, and neither does, past
|
|
54
|
+
A failed run stops; past `prepare`, it leaves the repository on the branch `<slug>`, with the agent's changes, for inspection. When the cause has passed (a timeout, the budget, the network, a Git hook), or when the checks or the review stopped it at their maximum of corrections and you grant one more round, `factory resume <RUN_ID>` starts the stopped stage again (each resumption allows that loop one more correction), its agent in the same conversation: the repository must still be on `<slug>` at the commit where the run stopped (the plan's commit, or the starting commit before it), with its changes in progress and none in `.factory/`; a delivery that stopped after its commit resumes once `git reset --soft <plan commit>` puts the changes back in progress, as the refusal says, a run whose pull request is recorded in its state, stopped once its delivery was done, does not resume, unless it stopped while attaching its screenshots, which it then attaches without any condition on the repository, and neither does, past `prepare`, a run started with an earlier version of the factory. Otherwise, clean up, fix what is needed (often the spec, committed and pushed again) and start a new run: it starts again from the main branch, recreates the branch and replaces the pull request's content. Requested changes on a pull request are fixed the same way, or by hand on the branch. An issue is abandoned by deleting its folder (and closing its pull request, if any).
|
|
55
55
|
|
|
56
|
-
`issue-save` lists every problem of a draft at once, refuses a spec for an issue that has no `issue.md`, replaces the file if it exists and commits nothing; each save is a run. The skill tells the agent never to write in `.factory/issues/` directly, commit or run `implement`. Pi reads a project's skills once the project is trusted; Codex ignores a `SKILL.md` that is itself a link, hence the folder link.
|
|
56
|
+
`issue-save` lists every problem of a draft's format at once, then, for a valid spec, its dependencies that are no issue, refuses a spec for an issue that has no `issue.md`, replaces the file if it exists and commits nothing; each save is a run. The skill tells the agent never to write in `.factory/issues/` directly, commit or run `implement`. Pi reads a project's skills once the project is trusted; Codex ignores a `SKILL.md` that is itself a link, hence the folder link.
|
|
57
57
|
|
|
58
58
|
### Issues
|
|
59
59
|
|
|
@@ -61,30 +61,51 @@ An issue is a folder `.factory/issues/<slug>/` holding at least one of the files
|
|
|
61
61
|
|
|
62
62
|
- `issue.md`: a `# ` title, then a description.
|
|
63
63
|
- `spec.md`: a `# ` title, then exactly `## Objective`, `## Scope`, `## Out of scope`, `## Acceptance criteria`, `## Constraints` and `## Dependencies`, in this order, with nothing before the first and none empty (`None.`). Acceptance criteria holds only `- AC<n>: <criterion>` items numbered from AC1 without gaps; an indented line continues an item. Dependencies holds only `- <slug>` items, each another issue of the repository that must be delivered first, or `None.`. The spec says what and why, not how; headings stay in English, the content may be in any language. `issue-save` and `implement` read it the same way; `issue-save` also refuses a dependency that is no issue of the repository.
|
|
64
|
-
- `plan.md`: written by the run, in
|
|
64
|
+
- `plan.md`: written by the run, in the language of the spec's content: the approach, what the code already does that the change must keep (Existing), steps that each name the criteria they serve, their files, the cases they must handle besides their main path and their tests, and the risks.
|
|
65
65
|
|
|
66
66
|
### The `implement` run
|
|
67
67
|
|
|
68
68
|
| Stage | What it does |
|
|
69
69
|
|---|---|
|
|
70
|
-
| `prepare` | Refuses to start, listing every reason, unless the repository is on the main branch without any change in progress, the main branch matches `origin` after `git fetch`, `spec.md` is valid (otherwise it says to fix it with `/issue <slug>`), each of its dependencies is delivered (its `plan.md` is on the main branch), the issue has no `plan.md` (an issue already delivered is never restarted), its slug does not name the main branch (its branch would replace it)
|
|
71
|
-
| `plan`, `planned` | The `plan` agent receives the slug and the spec
|
|
70
|
+
| `prepare` | Refuses to start, listing every reason, unless the repository is on the main branch without any change in progress, the main branch matches `origin` after `git fetch`, `spec.md` is valid (otherwise it says to fix it with `/issue <slug>`), each of its dependencies is delivered (its `plan.md` is on the main branch), the issue has no `plan.md` (an issue already delivered is never restarted), its slug does not name the main branch (its branch would replace it), `gh` is 2.99.0 or later, logged in, and finds the repository on GitHub; then the repository's checks must pass on the main branch, before any agent; then, under a lock of the working tree (`factory-implement.lock` in its Git directory, held for that step only) and unless the repository moved meanwhile (another run is using it: the run stops), creates (or recreates) the branch `<slug>` from the approved start commit. Branches are read and pushed by their full reference: a tag of the same name never stands in for them |
|
|
71
|
+
| `plan`, `planned` | The `plan` agent receives the slug and the spec. It first explores the code where the spec changes it (mechanisms, invariants, conventions, test tools), handing each area of a spec that touches several to a sub-agent when its profile allows it, then answers with a plan: what the code already does that the change must keep, and steps with their criteria, the files expected, the situations to handle besides the main path and their tests. The plan says what must be true, not how to write it; the implementing agent may take a better way and records it as a deviation; every criterion must be served by a step, otherwise the plan goes back to it (2 times at most) |
|
|
72
72
|
| `commit-plan` | Writes `plan.md` and commits it alone (`docs: plan <slug>`): the run's reference commit |
|
|
73
|
-
| `implement`, `implemented` | The `implement` agent receives the spec and the
|
|
74
|
-
| `verify` | The repository's checks, in order, a check with `when` only if a file changed since the reference commit matches it; a failure, a timeout or a command that cannot start goes back to `implement` with the command, the cause and the end of its output (3 times at most). What each check wrote is kept in the run's folder, for the review (over 2 MiB per stream, its end, marked as truncated) |
|
|
75
|
-
| `diff` | Every change since the reference commit, new files included, with each file's added and removed lines; the run stops if it is over 2 MiB. Over 1,500 lines of diff, the change is large: its diff is kept in the run's folder instead of being sent in the review's request |
|
|
76
|
-
| `review`, `reviewed` | The `review` agent, in a new conversation for each review, receives the spec, the changes (the diff, or for a large change where to read it), the checks and where their output is, never the implementing agent's answer. It judges each criterion `met` or `not_met
|
|
73
|
+
| `implement`, `implemented` | The `implement` agent receives the spec, the plan and the run's browser, in one conversation for the run, and answers with evidence for each criterion and its deviations from the plan; the run stops if it committed, switched branches or changed `.factory/`, whatever it answered |
|
|
74
|
+
| `verify` | The repository's checks, in order, a check with `when` only if a file changed since the reference commit matches it; a failure, a timeout or a command that cannot start goes back to `implement` with the command, the cause and the end of its output (3 times at most). What each check wrote is kept in the run's folder, for the review, and a failed check's whole output in `checks/failed-<n>-<name>.log`, the run's `n`th failure, resumptions included, whose path the run journals (over 2 MiB per stream, its end, marked as truncated) |
|
|
75
|
+
| `diff` | Every change since the reference commit, new files included, with each file's added and removed lines; the run stops if it is over 2 MiB. Over 1,500 lines of diff, the change is large: its diff is kept in the run's folder instead of being sent in the review's request. |
|
|
76
|
+
| `review`, `reviewed` | The `review` agent, in a new conversation for each review, receives the spec, the changes (the diff, or for a large change where to read it), the checks and where their output is, and the run's browser, never the implementing agent's answer. It judges each criterion `met` or `not_met`, with its decisive evidence, and gives each finding a nature. From the second round on, once it has answered on its own, it receives in the same conversation the previous review: it checks each earlier criterion and finding against the code, lists those now fixed with their proof, keeps those that still hold, with the same nature, judges how they were fixed, and answers its whole review again. Every review judged is kept in the run. An unmet criterion or a blocking finding goes back to `implement` (2 times at most) with the other findings, to fix as well when that is safe, and the implementing agent fixes the mechanism that let a defect happen, wherever the change has it, rather than adding a guard per case |
|
|
77
|
+
| `describe`, `described` | Once the change is approved, the `describe` agent explains it for the pull request (see below) and takes its screenshots. It receives the spec, the plan, the changes, the checks, the approved review, the deviations from the plan, whether the repository is public, the screenshots folder and the run's browser, never the implementing agent's summary. Its guide must name changed files only, each once, its screenshots must be distinct images of the folder, 10 MB at most, and the pull request's body must stay under 60,000 characters; otherwise its answer goes back to it (2 times at most) |
|
|
77
78
|
| `deliver` | Commits the changes with the plan's conventional commit subject, force-pushes `<slug>` to `origin`, updates the branch's open pull request or opens one with `gh`, then returns to the main branch |
|
|
79
|
+
| `attach` | When there are screenshots: replaces the pull request's body with one that shows them and uploads them (`gh pr edit --attach`) |
|
|
78
80
|
|
|
79
81
|
A finding's nature alone decides whether it blocks the change: `incorrect_behavior`, `data_loss`, `outage`, `security`, `regression` and `spec_violation` block it; `weak_test`, `maintainability` and `documentation` do not.
|
|
80
82
|
|
|
81
|
-
If its profile allows it, the reviewer runs commands (tests, reproductions) and, on a large change,
|
|
83
|
+
If its profile allows it, the reviewer runs commands (tests, reproductions, the application in a browser) and, on a large change or one that spans several applications or layers, splits the review between sub-agents (the `Agent` tool), each taking one part, and one more the paths across them: failures, interruptions, concurrency, recovery. It reports a defect once with every place it occurs, so that it is fixed everywhere at once. Neither the reviewer nor the describing agent changes the repository:
|
|
82
84
|
|
|
83
|
-
- The `diff` stage records the tree it reviews, and the review always
|
|
84
|
-
- After each call, even a failed one, what the
|
|
85
|
+
- The `diff` stage records the tree it reviews, and the review and the description always start from it: what an interrupted call left behind is put back first, on a resumed run too, and counts as that call's change. A resumed review or description whose tree Git has since pruned is refused.
|
|
86
|
+
- After each call, even a failed one, what the agent changed is put back (`.gitignore` files first, so that an ignored file is never taken for an addition), and it starts again in a new conversation, once per run.
|
|
85
87
|
- A second change, a commit or a branch switch stops the run. So does a list of changed files longer than the 2 MiB the run reads from Git, which leaves the repository as it is for inspection.
|
|
86
88
|
|
|
87
|
-
A malformed agent response goes back to that agent, 2 times at most. The
|
|
89
|
+
A malformed agent response goes back to that agent, 2 times at most. The text the agents write for people (the plan, the deviations, the review's evidence and findings, the description) is in the language of the spec's content, the commit subject in English, and written for a reader who knows neither the spec nor the code: things named by what they do, an identifier only beside its meaning, a sentence or two per item. Agents change no data they did not create: they use what the repository's instructions provide for tests, or create their own. The run's result shows the pull request, the review rounds, the checks passed and the merge's danger.
|
|
90
|
+
|
|
91
|
+
#### The browser
|
|
92
|
+
|
|
93
|
+
The `implement`, `review` and `describe` agents check a change that shows in a web interface in a browser: they start the application as the repository's agent instructions say, and stop everything they started before answering. When `.factory/` installs Playwright CLI, as `factory init` does, the run writes in its folder a command that runs it from the run's own workspace (a `browser/` folder holding `.playwright`), so that every session the agents open stays there, out of the repository and away from yours; it keeps its files in the run's folder, reports them by their absolute path and uses the downloaded Chromium (a repository's own `.playwright/cli.config.json` is not read), and it refuses `kill-all`, which would end your browsers too. The agents receive it as `browser`. Playwright CLI keeps its browser open after the agent that opened it, so at the end of each of these agents' stages the run closes every session of that workspace (`close-all`). The prompts name no tool: an agent without this command uses its own, such as a Pi extension. The repository's agent instructions must say how to start the application.
|
|
94
|
+
|
|
95
|
+
#### The pull request
|
|
96
|
+
|
|
97
|
+
Its title is the commit subject. Its body, for a reader who remembers nothing of the issue, short where it is read and folded where it is detail:
|
|
98
|
+
|
|
99
|
+
- a warning first when the operator delivered the change despite its review (see below), then a caution when merging is a one-way door (reverting does not walk it back: a migration that transforms data, a published contract, an external effect);
|
|
100
|
+
- a table at a glance: the files changed with their lines, links to the spec at the starting commit and to `plan.md`, the run's ID; the door and the blast radius; the criteria met, the checks and the screenshots; how the review ended and what it left;
|
|
101
|
+
- **Why**: the spec's Objective;
|
|
102
|
+
- **What changes**, one item per change, a change to what already existed among them, **How it works** (Mermaid diagrams of how components interact or how data flows, sketches of a tree as a diff, pseudocode; none when the text suffices), **Merge danger** (a table: door, blast radius, rollback, what to do after the merge) and **Review guide** (the file to start with, then the files in reading order, every group's list folded when the change has more than 10 files; the run lists the others), written by the `describe` agent with as many items as the change calls for;
|
|
103
|
+
- **Needs your judgment**: the review rounds, what stays open, the non-blocking findings with their nature and the deviations from the plan; folded, what earlier reviews found and later rounds fixed, with the proof, and the plan's assumptions;
|
|
104
|
+
- **Evidence**: the screenshots of the new state, or why there are none; the criteria met; the checks passed or skipped; each criterion with the review's evidence, folded.
|
|
105
|
+
|
|
106
|
+
No text of the run opens a code block or a comment that would swallow the rest of the body: the factory escapes them.
|
|
107
|
+
|
|
108
|
+
When the review still asks for changes after its last round, the run stops; `factory resume <RUN_ID>` gives it one more round, and `factory resume <RUN_ID> --accept-review` delivers it as the review left it, on your decision: the pull request then opens with a warning and lists, under Needs your judgment, the unmet criteria and blocking findings left open. What comes from the run (the spec, the criteria, the checks, the review, the deviations, the risks) is put together by the factory, never rewritten by an agent; the implementing agent's own summary is not shown. In a public repository, anyone can see the screenshots: the describing agent shows only test or seed data. The screenshots are kept in the run's folder and uploaded once the pull request is open; the body names them by file only, never by a path of the machine. A failed upload leaves the pull request recorded, saying again that its screenshots are coming, and fails the run; `factory resume` only uploads them again.
|
|
88
109
|
|
|
89
110
|
### Kanban
|
|
90
111
|
|
|
@@ -99,7 +120,7 @@ A malformed agent response goes back to that agent, 2 times at most. The pull re
|
|
|
99
120
|
| To Approve | the last `implement` run completed, and `plan.md` is not on the main branch |
|
|
100
121
|
| Done | `plan.md` is on the main branch |
|
|
101
122
|
|
|
102
|
-
The files are read in the working tree, the main branch is the local branch `origin/HEAD` names, and runs are those of `.factory/runs/`. A card shows the issue's title (the `# ` line of `issue.md`; its slug without one), its slug, the newest pull request its `implement` runs recorded (a new run updates the same one) and, for each workflow shown on cards, its last run on the issue: its steps (done, current, failed or to come), its duration and its estimated cost. `implement` shows six steps: prepare, plan, implement, verify, review and deliver. The title opens the newest of these runs in the runs dashboard. The most recently active issue comes first in its column; the page refreshes every 2 seconds. What may leave the board incomplete is listed above it: a `factory.ts` that does not load (`factory ui` loads it when it starts: restart it once fixed), an unreadable `issue.md` or run, or a main branch Git cannot read (`origin/HEAD` missing: `git remote set-head origin --auto` sets it).
|
|
123
|
+
The files are read in the working tree, the main branch is the local branch `origin/HEAD` names, and runs are those of `.factory/runs/`. A card shows the issue's title (the `# ` line of `issue.md`; its slug without one), its slug, the newest pull request its `implement` runs recorded (a new run updates the same one) and, for each workflow shown on cards, its last run on the issue: its steps (done, current, failed or to come), its duration and its estimated cost. `implement` shows six steps: prepare, plan, implement, verify, review and deliver (the description and the screenshots' upload included). The title opens the newest of these runs in the runs dashboard. The most recently active issue comes first in its column; the page refreshes every 2 seconds. What may leave the board incomplete is listed above it: a `factory.ts` that does not load (`factory ui` loads it when it starts: restart it once fixed), an unreadable `issue.md` or run, or a main branch Git cannot read (`origin/HEAD` missing: `git remote set-head origin --auto` sets it).
|
|
103
124
|
|
|
104
125
|
## Adapt the factory
|
|
105
126
|
|
|
@@ -111,28 +132,35 @@ import ask from "./workflows/ask/index.ts";
|
|
|
111
132
|
|
|
112
133
|
const minutes = 60_000;
|
|
113
134
|
const opus = { runtime: "claude-code", model: "claude-opus-5-5", thinking: "high" } as const;
|
|
114
|
-
const
|
|
135
|
+
const planner = { ...opus, tools: ["Read", "Grep", "Glob", "Agent"], timeoutMs: 30 * minutes } satisfies AgentProfile;
|
|
136
|
+
const checker = {
|
|
137
|
+
...opus,
|
|
138
|
+
tools: ["Read", "Grep", "Glob", "Bash"],
|
|
139
|
+
permissionMode: "dontAsk",
|
|
140
|
+
timeoutMs: 30 * minutes,
|
|
141
|
+
} satisfies AgentProfile;
|
|
115
142
|
|
|
116
143
|
export default defineFactory({
|
|
117
144
|
verify: [{ name: "test", command: ["npm", "test"], timeoutMs: 10 * minutes }],
|
|
118
145
|
maxCostUsd: 25,
|
|
119
146
|
profiles: {
|
|
120
|
-
plan:
|
|
147
|
+
plan: planner,
|
|
121
148
|
implement: {
|
|
122
149
|
...opus,
|
|
123
150
|
tools: ["Read", "Grep", "Glob", "Edit", "Write", "Bash"],
|
|
124
151
|
permissionMode: "dontAsk",
|
|
125
152
|
timeoutMs: 60 * minutes,
|
|
126
153
|
},
|
|
127
|
-
review:
|
|
154
|
+
review: { ...checker, tools: [...checker.tools, "Agent"], timeoutMs: 60 * minutes },
|
|
155
|
+
describe: checker,
|
|
128
156
|
},
|
|
129
157
|
workflows: [ask],
|
|
130
158
|
});
|
|
131
159
|
```
|
|
132
160
|
|
|
133
161
|
- `verify`: the repository's checks, at least one: `{ name, command, timeoutMs }`, the command an executable and its arguments, run without a shell in the repository. They run in order and stop at the first failure: on the main branch before the run's agents, then after each implementation. A check may add `when`, globs of the files whose change makes it run (`when: ["scripts/*deploy*", "caddy/**"]`): it is for a long validation, such as a rehearsal, that only some changes call for; it never runs on the main branch, and after an implementation only if a file changed since the plan matches it.
|
|
134
|
-
- `maxCostUsd`: the budget of an `implement` run, in USD; `factory run implement --issue <slug> --max-cost-usd 40` changes it for one run. Codex announces no cost, so
|
|
135
|
-
- `profiles`: the agents of `plan`, `implement` and `review` (see Profiles below). Each profile decides what its agent may do: here, `plan`
|
|
162
|
+
- `maxCostUsd`: the budget of an `implement` run, in USD; `factory run implement --issue <slug> --max-cost-usd 40` changes it for one run. Codex announces no cost, so the agents of `implement` (`plan`, `implement`, `review`, `describe`) cannot run with Codex.
|
|
163
|
+
- `profiles`: the agents of `plan`, `implement` and `review`, and optionally `describe`, which writes the pull request (the review's profile without it; see Profiles below). Each profile decides what its agent may do: here, `plan` only reads the repository, handing areas of a large spec to sub-agents (`Agent`); `implement` also edits it and runs commands, and `permissionMode: "dontAsk"` refuses any other tool instead of waiting for a permission prompt; `review` and `describe` read it and run commands, such as tests, reproductions or the application in a browser (they must not change the repository: the run puts back what they change). `Agent` in the review's tools lets it split the review of a large change between sub-agents. Without a way to start the application and a browser, `describe` takes no screenshot and says why.
|
|
136
164
|
- `workflows` (optional): the repository's own workflows.
|
|
137
165
|
|
|
138
166
|
`defineFactory` lists every problem at once, each agent's profile checked on its own even when other fields are wrong; it also refuses a workflow not made by `defineWorkflow`, or named like another, `issue-save` and `implement` included. Any other default export of `factory.ts` is refused.
|
|
@@ -255,7 +283,7 @@ Each agent runs with this machine's and this repository's configuration, as you
|
|
|
255
283
|
|
|
256
284
|
```sh
|
|
257
285
|
factory run WORKFLOW [--INPUT VALUE…] [--max-cost-usd USD] [--json]
|
|
258
|
-
factory resume RUN_ID [--max-cost-usd USD] [--json]
|
|
286
|
+
factory resume RUN_ID [--max-cost-usd USD] [--accept-review] [--json]
|
|
259
287
|
factory status [RUN_ID] [--json]
|
|
260
288
|
factory ui [--port 4321]
|
|
261
289
|
factory doctor [--json]
|
|
@@ -267,9 +295,9 @@ The run executes in the foreground. The terminal shows each stage's start and en
|
|
|
267
295
|
|
|
268
296
|
**Ctrl-C** stops the run's child processes and ends the run as `failed` with its cause before its next stage, or instead of completing; a second Ctrl-C kills the remaining child processes and quits at once (exit code 130, the run may then stay `running`); commands that Codex runs in their own process groups are stopped by Codex on the first Ctrl-C, not by the second.
|
|
269
297
|
|
|
270
|
-
**Resume.** `factory resume RUN_ID` runs a failed run again in the foreground, under the same ID, at the stage where it stopped: its input, data, corrections, cost and agents' conversations are kept, the stage's journal starts with why the run had stopped (`Resumed after: …`), and its agent is told so and asked to continue rather than start over. The workflow is the one `factory.ts` defines now, its prompts are read again, and its runtimes are checked as for `factory run`. The budget is the one given with `--max-cost-usd`, else the run's own, else the workflow's; a run that already spent it does not resume without a higher one. The run's budget still counts its whole cost, but calls that announced no cost before the resumption, such as a call stopped by its timeout, no longer fail it; their cost counts only if the runtime includes it in the total it later announces for the resumed session, and the run's cost stays marked partial. The run's duration leaves out the time it spent stopped. Only a failed run resumes, and by one command at a time: a run left `running` after a second Ctrl-C does not, and a workflow may refuse to resume from the state of the repository, as `implement` does. A resumed stage starts over: what it did before it failed must be safe to do again. A run stopped by a correction maximum resumes at the stage that asked for it: the checks may pass after a fix by hand,
|
|
298
|
+
**Resume.** `factory resume RUN_ID` runs a failed run again in the foreground, under the same ID, at the stage where it stopped (with `--accept-review`, an `implement` run its review stopped by asking for changes is delivered as the review left it: see The pull request): its input, data, corrections, cost and agents' conversations are kept, the stage's journal starts with why the run had stopped (`Resumed after: …`), and its agent is told so and asked to continue rather than start over. The workflow is the one `factory.ts` defines now, its prompts are read again, and its runtimes are checked as for `factory run`. The budget is the one given with `--max-cost-usd`, else the run's own, else the workflow's; a run that already spent it does not resume without a higher one. The run's budget still counts its whole cost, but calls that announced no cost before the resumption, such as a call stopped by its timeout, no longer fail it; their cost counts only if the runtime includes it in the total it later announces for the resumed session, and the run's cost stays marked partial. The run's duration leaves out the time it spent stopped. Only a failed run resumes, and by one command at a time: a run left `running` after a second Ctrl-C does not, and a workflow may refuse to resume from the state of the repository, as `implement` does. A resumed stage starts over: what it did before it failed must be safe to do again. A run stopped by a correction maximum resumes at the stage that asked for it, which may then take one more correction: the checks may pass after a fix by hand, and a gate judging the same answer sends it back once more.
|
|
271
299
|
|
|
272
|
-
`factory status` lists the repository's runs or shows one; while `factory.ts` cannot load, `status` and `ui` say so and still show the runs with the default rendering. `factory ui` serves on `127.0.0.1` (port chosen by the system unless `--port` sets it, URL printed; Ctrl-C stops it) the Kanban on `/` and, under `/runs/`, a read-only dashboard of the repository's runs: the runs with workflow, status, current stage, duration, estimated cost and last update, and for a run its runtimes, its launches (the first one, then each resumption), each with a strip of its stages sized by duration, then its stages beside the selected one's detail (start, duration, outcome, the agent call's model, settings, tools and tokens as they come, the journal and the tool calls), the correction counters and the result. It follows a running run as it goes. To watch on another machine, forward the same port through SSH: `ssh -L 4321:127.0.0.1:4321 machine`, run `factory ui --port 4321` there, and open `http://localhost:4321/`. `factory doctor` checks Node, loads the workflows, reads their prompts, lists each workflow's options and checks each runtime's executable, version and connection, without any provider request.
|
|
300
|
+
`factory status` lists the repository's runs or shows one; while `factory.ts` cannot load, `status` and `ui` say so and still show the runs with the default rendering. `factory ui` serves on `127.0.0.1` (port chosen by the system unless `--port` sets it, URL printed; Ctrl-C stops it) the Kanban on `/` and, under `/runs/`, a read-only dashboard of the repository's runs: the runs with workflow, status, current stage, duration, estimated cost and last update, and for a run its runtimes, its launches (the first one, then each resumption), each with a strip of its stages sized by duration, then its stages beside the selected one's detail (start, duration, outcome, the agent call's model, settings, tools and tokens as they come, a folded Output section with the agent's answer and the correction sent back or not, the journal and the tool calls), the correction counters and the result. It follows a running run as it goes. To watch on another machine, forward the same port through SSH: `ssh -L 4321:127.0.0.1:4321 machine`, run `factory ui --port 4321` there, and open `http://localhost:4321/`. `factory doctor` checks Node, loads the workflows, reads their prompts, lists each workflow's options and checks each runtime's executable, version and connection, without any provider request.
|
|
273
301
|
|
|
274
302
|
## Data
|
|
275
303
|
|
|
@@ -282,8 +310,10 @@ Tokens and costs are the figures each runtime announces: Claude Code announces a
|
|
|
282
310
|
- No release or observation stage: an issue is done once merged. Requested changes on a pull request are not handled by a run.
|
|
283
311
|
- Runs are local: Executing and Blocked show only on the machine of the run; Done shows after `git pull`. A refusal at `prepare` is a failed run, so the issue looks Blocked until its next run; after a second Ctrl-C a run may stay `running`, and its issue looks Executing until its next run.
|
|
284
312
|
- The repository is used in place: one `implement` run at a time, since it needs a clean tree and stops if another run moved the repository during its starting checks; after a failure, the operator cleans up, or leaves the branch as it is to resume the run. The repository's Git hooks run on the run's commits, and a failing hook fails the run.
|
|
285
|
-
- The factory's own agents (`plan`, `implement`, `review`) cannot run on Codex, since `maxCostUsd` is required and Codex announces no cost; the repository's own workflows and the `issue` skill can use Codex.
|
|
313
|
+
- The factory's own agents (`plan`, `implement`, `review`, `describe`) cannot run on Codex, since `maxCostUsd` is required and Codex announces no cost; the repository's own workflows and the `issue` skill can use Codex.
|
|
286
314
|
- Runtimes are not sandboxes: the implementing agent's tools can run any command its profile allows, bounded only by its prompt, the repository's agent instructions and the run's checks.
|
|
315
|
+
- The rule that a public repository's screenshots show only test or seed data holds only through the describing agent's prompt. The factory does not check the Mermaid syntax: GitHub shows an error in place of an invalid diagram.
|
|
316
|
+
- Screenshots show the new state only, never the previous one; no videos.
|
|
287
317
|
- Not in this version: changing the factory's prompts, correction maximums, pull request format or columns from a repository; columns added by a workflow; backlog priority; actions or drag-and-drop on the board; resuming a run left `running` after its process was killed, detached runs, logs `--follow` and stop; local settings or profile overrides; graph drawing in the dashboard; runs or issues of several repositories; `factory new`; a shared stage library; a test harness for workflows; CI, cron or Git hook triggers; notifications; Windows.
|
|
288
318
|
|
|
289
319
|
## License
|
package/dist/app/define.js
CHANGED
|
@@ -34,7 +34,7 @@ export function defineFactory(definition) {
|
|
|
34
34
|
const profiles = typeof given.profiles === "object" && given.profiles !== null
|
|
35
35
|
? given.profiles
|
|
36
36
|
: {};
|
|
37
|
-
for (const role of ["plan", "implement", "review"]) {
|
|
37
|
+
for (const role of ["plan", "implement", "review", "describe"]) {
|
|
38
38
|
const profile = profiles[role];
|
|
39
39
|
// A profile that is not an object is already reported by the definition.
|
|
40
40
|
if (typeof profile === "object" && profile !== null)
|
package/dist/app/define.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/app/define.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAiB,MAAM,eAAe,CAAC;AAC3E,OAAO,EACL,kBAAkB,GAEnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAqBtD,MAAM,OAAO,GAAG,IAAI,OAAO,EAA4B,CAAC;AAExD,2FAA2F;AAC3F,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAChD,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QACpB,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,UAA6B;IACzD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,EAAE,CAChC,QAAQ,CAAC,IAAI,CACX,CAAC,OAAO,EAAE,EAAE,CACV,OAAO,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,CACrE,CAAC;IACJ,kEAAkE;IAClE,MAAM,KAAK,GACT,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1E,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IAClE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClD,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE;QAC3C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC,aAAa,KAAK,uCAAuC,CAAC,CAAC;aACtE,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC/B,QAAQ,CAAC,IAAI,CACX,aAAa,KAAK,iCAAiC,QAAQ,CAAC,IAAI,EAAE,CACnE,CAAC;;YACC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAChC,yEAAyE;IACzE,oCAAoC;IACpC,MAAM,QAAQ,GACZ,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI;QAC3D,CAAC,CAAC,KAAK,CAAC,QAAQ;QAChB,CAAC,CAAC,EAAE,CAAC;IACT,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/app/define.ts"],"names":[],"mappings":"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"}
|
package/dist/app/init.d.ts
CHANGED
package/dist/app/init.js
CHANGED
package/dist/app/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/app/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,mBAAmB,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/app/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,mBAAmB,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/app/run.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export declare function startRun(factory: Factory, name: string, options: Record
|
|
|
9
9
|
/**
|
|
10
10
|
* Resumes a failed run of the repository at the stage where it stopped, with
|
|
11
11
|
* its workflow as `factory.ts` defines it now and its prompts read again;
|
|
12
|
-
* `--max-cost-usd`
|
|
12
|
+
* `--max-cost-usd` sets its budget, and `--accept-review` delivers an
|
|
13
|
+
* implement run its review stopped by asking for changes.
|
|
13
14
|
*/
|
|
14
15
|
export declare function resumeRun(factory: Factory, runId: string, options: Record<string, string | boolean>, hooks: RunHooks): Promise<StartedRun>;
|
package/dist/app/run.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { resumeRun as resume, startRun as start, } from "@clemrig/flow";
|
|
1
|
+
import { exceededEdge, resumeRun as resume, startRun as start, } from "@clemrig/flow";
|
|
2
2
|
import { loadPrompts, workflowOf } from "../system/factory.js";
|
|
3
3
|
import { asOptionsError, inputFromOptions, parseBudget } from "./options.js";
|
|
4
|
+
import { DELIVERY } from "../domain/delivery.js";
|
|
4
5
|
import { loadRun } from "./runs.js";
|
|
5
6
|
/**
|
|
6
7
|
* Starts a workflow of the factory from `factory run` options, with its prompts
|
|
@@ -30,19 +31,30 @@ export async function startRun(factory, name, options, hooks) {
|
|
|
30
31
|
/**
|
|
31
32
|
* Resumes a failed run of the repository at the stage where it stopped, with
|
|
32
33
|
* its workflow as `factory.ts` defines it now and its prompts read again;
|
|
33
|
-
* `--max-cost-usd`
|
|
34
|
+
* `--max-cost-usd` sets its budget, and `--accept-review` delivers an
|
|
35
|
+
* implement run its review stopped by asking for changes.
|
|
34
36
|
*/
|
|
35
37
|
export async function resumeRun(factory, runId, options, hooks) {
|
|
36
|
-
const { "max-cost-usd": budget, ...others } = options;
|
|
38
|
+
const { "max-cost-usd": budget, "accept-review": acceptReview, ...others } = options;
|
|
37
39
|
const [unknown] = Object.keys(others);
|
|
38
40
|
if (unknown)
|
|
39
41
|
throw new Error(`Unknown option --${unknown} for resume`);
|
|
40
42
|
const maxCostUsd = budget === undefined ? undefined : parseBudget(budget);
|
|
41
|
-
const
|
|
43
|
+
const run = await loadRun(factory, runId);
|
|
44
|
+
const workflow = workflowOf(factory, run.workflow);
|
|
45
|
+
// Delivering despite the review is the operator's decision, on the review
|
|
46
|
+
// that stopped the run by asking for changes past their maximum: the gate
|
|
47
|
+
// judges it again, and accepts it.
|
|
48
|
+
if (acceptReview !== undefined &&
|
|
49
|
+
(acceptReview !== true ||
|
|
50
|
+
run.workflow !== DELIVERY ||
|
|
51
|
+
exceededEdge(workflow, run) !== "reviewed.changes"))
|
|
52
|
+
throw new Error(`--accept-review only resumes a run of ${DELIVERY} stopped by its review asking for changes, and takes no value`);
|
|
42
53
|
return resume({
|
|
43
54
|
workflow,
|
|
44
55
|
runId,
|
|
45
56
|
maxCostUsd,
|
|
57
|
+
...(acceptReview ? { data: { acceptedReview: true } } : {}),
|
|
46
58
|
prompts: () => loadPrompts(factory, workflow),
|
|
47
59
|
dir: factory.dir,
|
|
48
60
|
configDir: factory.factoryDir,
|
package/dist/app/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/app/run.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/app/run.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAEZ,SAAS,IAAI,MAAM,EAEnB,QAAQ,IAAI,KAAK,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAgB,WAAW,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,OAAgB,EAChB,IAAY,EACZ,OAAyC,EACzC,KAAe;IAEf,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC3C,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IACrD,MAAM,UAAU,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1E,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAChD,IAAI,CAAC;QACH,OAAO,MAAM,KAAK,CAChB;YACE,QAAQ;YACR,KAAK;YACL,UAAU;YACV,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC;YAC7C,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,OAAO,CAAC,UAAU;YAC7B,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,EACD,KAAK,CACN,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,cAAc,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,OAAgB,EAChB,KAAa,EACb,OAAyC,EACzC,KAAe;IAEf,MAAM,EACJ,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,YAAY,EAC7B,GAAG,MAAM,EACV,GAAG,OAAO,CAAC;IACZ,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtC,IAAI,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,aAAa,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1E,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnD,0EAA0E;IAC1E,0EAA0E;IAC1E,mCAAmC;IACnC,IACE,YAAY,KAAK,SAAS;QAC1B,CAAC,YAAY,KAAK,IAAI;YACpB,GAAG,CAAC,QAAQ,KAAK,QAAQ;YACzB,YAAY,CAAC,QAAQ,EAAE,GAAG,CAAC,KAAK,kBAAkB,CAAC;QAErD,MAAM,IAAI,KAAK,CACb,yCAAyC,QAAQ,+DAA+D,CACjH,CAAC;IACJ,OAAO,MAAM,CACX;QACE,QAAQ;QACR,KAAK;QACL,UAAU;QACV,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC;QAC7C,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,SAAS,EAAE,OAAO,CAAC,UAAU;QAC7B,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,EACD,KAAK,CACN,CAAC;AACJ,CAAC"}
|
|
@@ -3,6 +3,6 @@ import type { FactoryDefinition } from "../../domain/definition.js";
|
|
|
3
3
|
type Settings = Pick<FactoryDefinition, "verify" | "profiles"> & {
|
|
4
4
|
maxCostUsd?: number;
|
|
5
5
|
};
|
|
6
|
-
/** Plans, implements, checks and reviews an approved spec, then
|
|
6
|
+
/** Plans, implements, checks and reviews an approved spec, then describes it in the pull request it opens. */
|
|
7
7
|
export declare function implement(definition: Settings): import("@clemrig/flow").Workflow;
|
|
8
8
|
export {};
|