@nonameolsson/nightjar 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -2
- package/dist/account.d.ts +12 -0
- package/dist/account.js +57 -0
- package/dist/account.js.map +1 -0
- package/dist/args.d.ts +2 -1
- package/dist/args.js +7 -2
- package/dist/args.js.map +1 -1
- package/dist/build.d.ts +4 -1
- package/dist/build.js +303 -47
- package/dist/build.js.map +1 -1
- package/dist/checks.d.ts +7 -0
- package/dist/checks.js +72 -8
- package/dist/checks.js.map +1 -1
- package/dist/config.d.ts +21 -0
- package/dist/config.js +79 -0
- package/dist/config.js.map +1 -1
- package/dist/doctor.js +5 -0
- package/dist/doctor.js.map +1 -1
- package/dist/fakes/machine.d.ts +1 -0
- package/dist/fakes/machine.js +14 -7
- package/dist/fakes/machine.js.map +1 -1
- package/dist/init.d.ts +1 -0
- package/dist/init.js +10 -2
- package/dist/init.js.map +1 -1
- package/dist/ledger.d.ts +1 -1
- package/dist/ledger.js +1 -1
- package/dist/ledger.js.map +1 -1
- package/dist/main.js +20 -4
- package/dist/main.js.map +1 -1
- package/dist/person-config.d.ts +1 -0
- package/dist/person-config.js +8 -3
- package/dist/person-config.js.map +1 -1
- package/dist/prompt.d.ts +63 -0
- package/dist/prompt.js +74 -0
- package/dist/prompt.js.map +1 -1
- package/dist/serve.d.ts +10 -0
- package/dist/serve.js +85 -0
- package/dist/serve.js.map +1 -0
- package/dist/settings.d.ts +7 -1
- package/dist/settings.js +12 -3
- package/dist/settings.js.map +1 -1
- package/dist/skills.d.ts +4 -0
- package/dist/skills.js +51 -0
- package/dist/skills.js.map +1 -0
- package/dist/status-shape.d.ts +1 -1
- package/dist/workflow.d.ts +33 -0
- package/dist/workflow.js +53 -0
- package/dist/workflow.js.map +1 -0
- package/dist/worktree.d.ts +16 -0
- package/dist/worktree.js +51 -2
- package/dist/worktree.js.map +1 -1
- package/docs/ticket-contract.md +10 -0
- package/package.json +1 -1
- package/schema/factory.schema.json +107 -0
- package/src/status-shape.ts +2 -2
package/README.md
CHANGED
|
@@ -16,7 +16,6 @@ Today the Tracker is GitHub Issues or Azure DevOps Boards, and the Code host is
|
|
|
16
16
|
|
|
17
17
|
## Install
|
|
18
18
|
|
|
19
|
-
> Not published to npm yet; until it is, install from a tarball (below). Check an install with `nightjar --help`.
|
|
20
19
|
|
|
21
20
|
Nightjar needs Node, but the repo it builds need not be a Node project. Install it once for your user, so the repo gets no `package.json` or `node_modules`:
|
|
22
21
|
|
|
@@ -128,6 +127,7 @@ A full one:
|
|
|
128
127
|
| `rules` | no | A text file, relative to the repo root, added to the agent's prompt. Conventions normally live in `CLAUDE.md` or `AGENTS.md`. |
|
|
129
128
|
| `model`, `effort` | no | The default model and effort of every session. |
|
|
130
129
|
| `review` | no | The read-only review of the whole diff, run before the draft pull request opens. `enabled: false` switches it off (on by default); `model` and `effort` are the review's own, else the defaults above. |
|
|
130
|
+
| `workflows`, `defaultWorkflow` | no | Work the repo adds to the build loop: see [Workflows](#workflows). A Feature picks a Workflow with a `**Workflow:**` line; `defaultWorkflow` is the one a Feature without the line gets. Left out, a build runs no Step. |
|
|
131
131
|
|
|
132
132
|
Model and effort are chosen, strongest first: the `--model` / `--effort` option, the Ticket's own `**Model:**` / `**Effort:**` line, then `factory.json`.
|
|
133
133
|
|
|
@@ -187,6 +187,7 @@ What is yours rather than the repo's lives outside it, in `config.json` under `$
|
|
|
187
187
|
| ---------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
188
188
|
| `dailyUsd` | `60` | The estimated spend per local day in a repo, from its `.factory/runs.jsonl`, at which a run pauses. `--watch` looks again after 30 minutes. |
|
|
189
189
|
| `assignee` | the signed-in person | Whose Features to build: `--once`, `--watch` and `doctor` take the Features assigned to this login with the Go, and `nightjar <id>` refuses one assigned to anyone else. |
|
|
190
|
+
| `profile` | none, the terminal's own login | Which Claude login the sessions use: a name (`work` is `~/.claude-work`), a path to the config folder, or `default` for `~/.claude`. `--profile` beats it. |
|
|
190
191
|
|
|
191
192
|
Nightjar refuses to start when the file is not JSON or a key is wrong or unknown, and names each one. `doctor` lists what it read.
|
|
192
193
|
|
|
@@ -207,6 +208,68 @@ nightjar contract ./tools/my-tracker.contract.js
|
|
|
207
208
|
|
|
208
209
|
`nightjar contract` runs the same contract suite the built-in Adapters meet over the harnesses a module exports, prints every behaviour, names each one that fails, and exits 1 if any does. Nightjar refuses to start when a named module cannot be loaded or lacks a method of the interface. [docs/custom-adapters.md](docs/custom-adapters.md) has a minimal module and a test harness.
|
|
209
210
|
|
|
211
|
+
## Workflows
|
|
212
|
+
|
|
213
|
+
A repo can add its own work to a build without Nightjar knowing what that work is. A **Workflow** is a named list of **Steps** in `factory.json`. A Step is a prompt given to the agent, and the prompt may name any skill. Nightjar's loop stays fixed: it keeps the branch, the commits, the Signals and the pull request, and a Workflow can only add Steps to it.
|
|
214
|
+
|
|
215
|
+
A Feature picks a Workflow with a line anywhere in its body, in the same shape as a Ticket's Model line:
|
|
216
|
+
|
|
217
|
+
```markdown
|
|
218
|
+
**Workflow:** design-review
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
With no such line, the Feature gets `defaultWorkflow` if `factory.json` sets one, else no Step runs and the build is as it was. A name no Workflow has marks the Feature as needing info, with a comment naming the Workflows that exist.
|
|
222
|
+
|
|
223
|
+
A design review built on a skill, in this case [Impeccable](https://github.com/pbakaus/impeccable) (any skill the agent can load works the same way):
|
|
224
|
+
|
|
225
|
+
```json
|
|
226
|
+
{
|
|
227
|
+
"ports": { "count": 1, "env": ["APP_PORT"] },
|
|
228
|
+
"workflows": {
|
|
229
|
+
"design-review": {
|
|
230
|
+
"serve": "npm run dev -- --port $APP_PORT",
|
|
231
|
+
"localNetwork": true,
|
|
232
|
+
"allowedCommands": ["npx playwright test *"],
|
|
233
|
+
"steps": [
|
|
234
|
+
{
|
|
235
|
+
"name": "critique",
|
|
236
|
+
"prompt": "/impeccable critique the screens this Feature changed. Write what is wrong, worst first, to the notes folder.",
|
|
237
|
+
"point": "afterAllTickets",
|
|
238
|
+
"model": "opus"
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"name": "polish",
|
|
242
|
+
"prompt": "/impeccable polish the screens, fixing what the critique in the notes folder found.",
|
|
243
|
+
"point": "afterAllTickets",
|
|
244
|
+
"until": "the critique's list is empty or only things a person must decide remain",
|
|
245
|
+
"maxRounds": 3,
|
|
246
|
+
"budgetUsd": 8
|
|
247
|
+
}
|
|
248
|
+
]
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
"defaultWorkflow": "design-review"
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
A Step has:
|
|
256
|
+
|
|
257
|
+
| Key | What it does |
|
|
258
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
259
|
+
| `name`, `prompt` | The Step's name, which its commit and the pull request body use, and what the agent is told. Nightjar adds the rule that nobody is at the keyboard: the agent decides, never asks in chat, and a question that truly blocks it goes into its structured answer, which makes the Step "blocked". |
|
|
260
|
+
| `point` | `afterEachTicket` runs after each Ticket is built and checked. `afterAllTickets` runs once, after every Ticket, before the review; it runs only when every Ticket of the Feature is built, and gets the Feature's diff against the base branch, so the agent picks its own targets. |
|
|
261
|
+
| `model`, `effort` | The Step's own; else the defaults. `--model` and `--effort` win over both. |
|
|
262
|
+
| `budgetUsd` | The most one run of the Step may cost; a Ticket's budget when left out. |
|
|
263
|
+
| `until`, `maxRounds` | A condition in plain words. After each round the agent reports whether it holds, and Nightjar runs the Step again, in the same session, until it does or `maxRounds` (3 by default) is reached. What is left goes into the pull request body. |
|
|
264
|
+
|
|
265
|
+
A Workflow can also have `serve`, a command started in the background in the worktree before its Steps and stopped after them (it reads its port from the variables of `ports.env`, so `ports` is required); `allowedCommands` and `allowedTools`, which its Steps may use besides the usual ones; and `localNetwork`, which lets its Steps reach localhost and nothing else. The fixed deny rules (committing, pushing, switching branches, the outside network, `gh`) cannot be loosened by any of these.
|
|
266
|
+
|
|
267
|
+
Steps share one notes folder, `.factory/notes/` in the worktree, which is never committed. Nightjar passes nothing else from one Step to the next, so a Step that needs what an earlier one found reads it there.
|
|
268
|
+
|
|
269
|
+
What a Step changes goes through the check command and its fix rounds, then is committed on its own, with a message naming the Workflow and the Step. Steps count against the daily spend limit and show in the cost of the pull request. A Step that hits its budget or time limit, cannot get the check green, answers in a shape not known, or reports itself blocked has its changes thrown away; the later Steps still run, and the pull request opens with that Step listed as not done. A Step the branch already holds is not run again when a later run goes on.
|
|
270
|
+
|
|
271
|
+
`nightjar doctor` looks up each `/skill` a Step's prompt names among the skills a headless Claude session loads. A skill that is missing is an error for that Workflow only: a Feature that picks it stops with a comment, and the others build as usual. (A word like `/tmp/notes` is a path, not a skill; a bare `/word` in a prompt is read as one.)
|
|
272
|
+
|
|
210
273
|
## Write a Feature
|
|
211
274
|
|
|
212
275
|
What a Ticket must hold (acceptance criteria, blocking links, optional Model and Effort lines) is the [Ticket contract](docs/ticket-contract.md). Write a Feature and its Tickets by hand on the Tracker, as in [Give the Go](#give-the-go), or as one Markdown file in the contract's shape and let Nightjar make them through the configured Tracker:
|
|
@@ -276,10 +339,11 @@ nightjar doctor
|
|
|
276
339
|
| `--watch` | Builds the Features assigned to you with the Go, oldest first, and looks again every 2 minutes. |
|
|
277
340
|
| `<id>` | Builds that Feature now, by its id on the Tracker (`nightjar 42`, `#42`, or `nightjar PROJ-123` from a Tracker module). It refuses a Feature not assigned to you, without the Go, or already carrying the working Signal. |
|
|
278
341
|
| `--use-api-key` | Lets the sessions bill `ANTHROPIC_API_KEY` instead of your Claude plan. |
|
|
342
|
+
| `--profile <name>` | Runs the sessions as that Claude login: `~/.claude-NAME`, a path as the folder itself, or `default` for `~/.claude`. It drops `CLAUDE_CODE_OAUTH_TOKEN`, which would win over the folder. `doctor` and every build name the account, organization, plan and config folder first. |
|
|
279
343
|
| `--model <model>` | The model of every session, over a Ticket's own line and `factory.json`. |
|
|
280
344
|
| `--effort <level>` | The effort of every session, over a Ticket's own line and `factory.json`. |
|
|
281
345
|
|
|
282
|
-
Pick exactly one of `doctor`, `--once`, `--watch` or a Feature id. `--use-api-key`, `--model` and `--effort` combine with any of them. `nightjar create [--dry-run] FILE` makes a Feature from a file ([Write a Feature](#write-a-feature)), and `nightjar contract MODULE` checks an Adapter module.
|
|
346
|
+
Pick exactly one of `doctor`, `--once`, `--watch` or a Feature id. `--use-api-key`, `--profile`, `--model` and `--effort` combine with any of them. `nightjar create [--dry-run] FILE` makes a Feature from a file ([Write a Feature](#write-a-feature)), and `nightjar contract MODULE` checks an Adapter module.
|
|
283
347
|
|
|
284
348
|
Before building, Nightjar checks the API-key choice, Node, `factory.json`, the Tracker and Code host logins (`gh`, or the Azure DevOps sign-in, and the Azure Repos repo when it is the Code host), that `claude` is installed and signed in, and commit signing, and prints what it found. A build stops at the first check that fails; `doctor` runs every check and lists each result as `ok`, `FAIL` (with how to fix it) or `skip` (when `factory.json` could not be read, so the logins it names are not tried). `doctor` refuses a repo with no check command. Exit code 2 means it refused to start, or a check failed; the message says why.
|
|
285
349
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Env } from './git.js';
|
|
2
|
+
export declare function profileEnv(profile: string | undefined, env: Env): Env;
|
|
3
|
+
export interface Account {
|
|
4
|
+
readonly loggedIn: boolean;
|
|
5
|
+
readonly email?: string;
|
|
6
|
+
readonly organization?: string;
|
|
7
|
+
readonly plan?: string;
|
|
8
|
+
readonly method?: string;
|
|
9
|
+
readonly folder?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function parseAccount(json: string): Account | null;
|
|
12
|
+
export declare function accountLine(a: Account): string;
|
package/dist/account.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Which Claude login the sessions use: the environment a profile gives them, and the account `claude auth status --json` names.
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
// The sessions' environment under `profile`: its config folder, and no token, which would win over that folder.
|
|
5
|
+
export function profileEnv(profile, env) {
|
|
6
|
+
if (profile === undefined)
|
|
7
|
+
return env;
|
|
8
|
+
const { CLAUDE_CONFIG_DIR: _dir, CLAUDE_CODE_OAUTH_TOKEN: _token, ...rest } = env;
|
|
9
|
+
if (profile === 'default')
|
|
10
|
+
return rest;
|
|
11
|
+
const home = env.HOME ?? homedir();
|
|
12
|
+
let folder = join(home, `.claude-${profile}`);
|
|
13
|
+
// a value with a slash is the folder itself; `~/` is the home folder
|
|
14
|
+
if (profile.startsWith('~/'))
|
|
15
|
+
folder = join(home, profile.slice(2));
|
|
16
|
+
else if (profile.includes('/'))
|
|
17
|
+
folder = profile;
|
|
18
|
+
return { ...rest, CLAUDE_CONFIG_DIR: folder };
|
|
19
|
+
}
|
|
20
|
+
const text = (value) => typeof value === 'string' && value !== '' ? value : undefined;
|
|
21
|
+
// The account in `claude auth status --json`, which has spelled its fields differently across versions; null when it is not JSON.
|
|
22
|
+
export function parseAccount(json) {
|
|
23
|
+
let value;
|
|
24
|
+
try {
|
|
25
|
+
value = JSON.parse(json);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
31
|
+
return null;
|
|
32
|
+
const f = value;
|
|
33
|
+
const fields = {
|
|
34
|
+
email: text(f.email) ?? text(f.emailAddress),
|
|
35
|
+
organization: text(f.orgName) ?? text(f.organizationName),
|
|
36
|
+
plan: text(f.subscriptionType),
|
|
37
|
+
method: text(f.authMethod),
|
|
38
|
+
folder: text(f.configDirectory)
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
loggedIn: f.loggedIn === true,
|
|
42
|
+
...Object.fromEntries(Object.entries(fields).filter((e) => e[1] !== undefined))
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// The account as one line, leaving out what the claude did not say.
|
|
46
|
+
export function accountLine(a) {
|
|
47
|
+
return [
|
|
48
|
+
a.email,
|
|
49
|
+
a.organization,
|
|
50
|
+
a.plan === undefined ? undefined : `${a.plan} plan`,
|
|
51
|
+
a.method === undefined ? undefined : `${a.method} login`,
|
|
52
|
+
a.folder === undefined ? undefined : `config ${a.folder}`
|
|
53
|
+
]
|
|
54
|
+
.filter((part) => part !== undefined)
|
|
55
|
+
.join(', ');
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.js","sourceRoot":"","sources":["../src/account.ts"],"names":[],"mappings":"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"}
|
package/dist/args.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Env } from './git.js';
|
|
2
|
-
export declare const USAGE = "usage: nightjar <--watch | --once | FEATURE | doctor> [--use-api-key] [--model M] [--effort LEVEL]\n\n --watch build the Features assigned to you with the Go, oldest first, and look again every 2 minutes\n --once build the oldest Feature assigned to you with the Go, then exit\n FEATURE build that Feature, by its id (42, #42, PROJ-123), now\n doctor check this machine and list the Features it would build, building nothing (--dry-run is the old name)\n --use-api-key let the sessions bill ANTHROPIC_API_KEY instead of your Claude plan\n --model M the model of every session, over a Ticket's own line and factory.json\n --effort LEVEL the effort of every session, over a Ticket's own line and factory.json\n\n nightjar init ask for the Tracker and Code host, write factory.json, create the Signal labels, check the logins\n nightjar create [--dry-run] FILE make a Feature and its Tickets on the Tracker from a Feature file\n nightjar contract MODULE check a module's own Tracker or Code host against the contract suites";
|
|
2
|
+
export declare const USAGE = "usage: nightjar <--watch | --once | FEATURE | doctor> [--use-api-key] [--profile NAME] [--model M] [--effort LEVEL]\n\n --watch build the Features assigned to you with the Go, oldest first, and look again every 2 minutes\n --once build the oldest Feature assigned to you with the Go, then exit\n FEATURE build that Feature, by its id (42, #42, PROJ-123), now\n doctor check this machine and list the Features it would build, building nothing (--dry-run is the old name)\n --use-api-key let the sessions bill ANTHROPIC_API_KEY instead of your Claude plan\n --profile NAME run the sessions as the Claude login in ~/.claude-NAME (a path is the folder itself, default is ~/.claude); over config.json's profile\n --model M the model of every session, over a Ticket's own line and factory.json\n --effort LEVEL the effort of every session, over a Ticket's own line and factory.json\n\n nightjar init ask for the Tracker and Code host, write factory.json, create the Signal labels, check the logins\n nightjar create [--dry-run] FILE make a Feature and its Tickets on the Tracker from a Feature file\n nightjar contract MODULE check a module's own Tracker or Code host against the contract suites";
|
|
3
3
|
export interface Args {
|
|
4
4
|
readonly mode: 'watch' | 'once' | 'feature' | 'doctor';
|
|
5
5
|
readonly feature?: string;
|
|
6
6
|
readonly useApiKey: boolean;
|
|
7
|
+
readonly profile?: string;
|
|
7
8
|
readonly model?: string;
|
|
8
9
|
readonly effort?: string;
|
|
9
10
|
}
|
package/dist/args.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export const USAGE = `usage: nightjar <--watch | --once | FEATURE | doctor> [--use-api-key] [--model M] [--effort LEVEL]
|
|
1
|
+
export const USAGE = `usage: nightjar <--watch | --once | FEATURE | doctor> [--use-api-key] [--profile NAME] [--model M] [--effort LEVEL]
|
|
2
2
|
|
|
3
3
|
--watch build the Features assigned to you with the Go, oldest first, and look again every 2 minutes
|
|
4
4
|
--once build the oldest Feature assigned to you with the Go, then exit
|
|
5
5
|
FEATURE build that Feature, by its id (42, #42, PROJ-123), now
|
|
6
6
|
doctor check this machine and list the Features it would build, building nothing (--dry-run is the old name)
|
|
7
7
|
--use-api-key let the sessions bill ANTHROPIC_API_KEY instead of your Claude plan
|
|
8
|
+
--profile NAME run the sessions as the Claude login in ~/.claude-NAME (a path is the folder itself, default is ~/.claude); over config.json's profile
|
|
8
9
|
--model M the model of every session, over a Ticket's own line and factory.json
|
|
9
10
|
--effort LEVEL the effort of every session, over a Ticket's own line and factory.json
|
|
10
11
|
|
|
@@ -16,6 +17,7 @@ export function parseArgs(argv) {
|
|
|
16
17
|
const chosen = { mode: null };
|
|
17
18
|
let feature;
|
|
18
19
|
let useApiKey = false;
|
|
20
|
+
let profile;
|
|
19
21
|
let model;
|
|
20
22
|
let effort;
|
|
21
23
|
const pick = (m) => {
|
|
@@ -35,12 +37,14 @@ export function parseArgs(argv) {
|
|
|
35
37
|
fault = pick('doctor');
|
|
36
38
|
else if (a === '--use-api-key')
|
|
37
39
|
useApiKey = true;
|
|
38
|
-
else if (a === '--model' || a === '--effort') {
|
|
40
|
+
else if (a === '--model' || a === '--effort' || a === '--profile') {
|
|
39
41
|
const value = argv[i + 1];
|
|
40
42
|
if (value === undefined || value.startsWith('--'))
|
|
41
43
|
return `${a} needs a value`;
|
|
42
44
|
if (a === '--model')
|
|
43
45
|
model = value;
|
|
46
|
+
else if (a === '--profile')
|
|
47
|
+
profile = value;
|
|
44
48
|
else
|
|
45
49
|
effort = value;
|
|
46
50
|
i += 1;
|
|
@@ -61,6 +65,7 @@ export function parseArgs(argv) {
|
|
|
61
65
|
mode,
|
|
62
66
|
useApiKey,
|
|
63
67
|
...(feature === undefined ? {} : { feature }),
|
|
68
|
+
...(profile === undefined ? {} : { profile }),
|
|
64
69
|
...(model === undefined ? {} : { model }),
|
|
65
70
|
...(effort === undefined ? {} : { effort })
|
|
66
71
|
};
|
package/dist/args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,KAAK,GAAG
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,KAAK,GAAG;;;;;;;;;;;;;wGAamF,CAAC;AAWzG,gEAAgE;AAChE,MAAM,UAAU,SAAS,CAAC,IAAuB;IAChD,MAAM,MAAM,GAAkC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC7D,IAAI,OAA2B,CAAC;IAChC,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,OAA2B,CAAC;IAChC,IAAI,KAAyB,CAAC;IAC9B,IAAI,MAA0B,CAAC;IAC/B,MAAM,IAAI,GAAG,CAAC,CAAe,EAAE,EAAE;QAChC,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;YAC5C,OAAO,qDAAqD,CAAC;QAC9D,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;QAChB,OAAO,IAAI,CAAC;IACb,CAAC,CAAC;IACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,KAAK,GAAkB,IAAI,CAAC;QAChC,IAAI,CAAC,KAAK,SAAS;YAAE,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;aACtC,IAAI,CAAC,KAAK,QAAQ;YAAE,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;aACzC,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,WAAW;YAAE,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;aAChE,IAAI,CAAC,KAAK,eAAe;YAAE,SAAS,GAAG,IAAI,CAAC;aAC5C,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,WAAW,EAAE,CAAC;YACnE,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,OAAO,GAAG,CAAC,gBAAgB,CAAC;YAC/E,IAAI,CAAC,KAAK,SAAS;gBAAE,KAAK,GAAG,KAAK,CAAC;iBAC9B,IAAI,CAAC,KAAK,WAAW;gBAAE,OAAO,GAAG,KAAK,CAAC;;gBACvC,MAAM,GAAG,KAAK,CAAC;YACpB,CAAC,IAAI,CAAC,CAAC;QACR,CAAC;aAAM,IAAI,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7C,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;YACxB,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC/B,CAAC;;YAAM,OAAO,oBAAoB,CAAC,EAAE,CAAC;QACtC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;IACzB,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IACxB,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,mBAAmB,CAAC;IAC9C,OAAO;QACN,IAAI;QACJ,SAAS;QACT,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;QAC7C,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;QAC7C,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;QACzC,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;KAC3C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAQ,EAAE,SAAkB;IACzD,IAAI,SAAS,IAAI,CAAC,GAAG,CAAC,iBAAiB;QAAE,OAAO,IAAI,CAAC;IACrD,OAAO,2JAA2J,CAAC;AACpK,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,QAAyB;IACxD,OAAO,QAAQ,KAAK,OAAO;QAC1B,CAAC,CAAC,0EAA0E;QAC5E,CAAC,CAAC,IAAI,CAAC;AACT,CAAC"}
|
package/dist/build.d.ts
CHANGED
|
@@ -2,9 +2,11 @@ import type { RunCheck } from './check.js';
|
|
|
2
2
|
import type { CodeHost, Pull } from './code-host.js';
|
|
3
3
|
import type { Env } from './git.js';
|
|
4
4
|
import { type Waiting } from './plan.js';
|
|
5
|
+
import type { Serve } from './serve.js';
|
|
5
6
|
import type { Session } from './session.js';
|
|
6
7
|
import type { StatusReport } from './status.js';
|
|
7
8
|
import type { ItemId, Tracker } from './tracker.js';
|
|
9
|
+
import { type WorkflowSettings } from './workflow.js';
|
|
8
10
|
export interface Limits {
|
|
9
11
|
readonly ticketUsd: number;
|
|
10
12
|
readonly ticketMinutes: number;
|
|
@@ -21,12 +23,13 @@ export interface Deps {
|
|
|
21
23
|
readonly session: Session;
|
|
22
24
|
readonly runCheck: RunCheck;
|
|
23
25
|
readonly runSetup: RunCheck;
|
|
26
|
+
readonly serve: Serve;
|
|
24
27
|
readonly now: () => Date;
|
|
25
28
|
readonly newId: () => string;
|
|
26
29
|
readonly say: (line: string) => void;
|
|
27
30
|
readonly status: StatusReport;
|
|
28
31
|
}
|
|
29
|
-
export interface Setup {
|
|
32
|
+
export interface Setup extends WorkflowSettings {
|
|
30
33
|
readonly root: string;
|
|
31
34
|
readonly repo: string;
|
|
32
35
|
readonly worktrees: string;
|