breakaway 1.5.0-main.45 → 1.5.0-main.47
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/package.json +1 -1
- package/scripts/tasks/cli.js +34 -1
- package/scripts/tasks.mjs +44 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "breakaway",
|
|
3
|
-
"version": "1.5.0-main.
|
|
3
|
+
"version": "1.5.0-main.47",
|
|
4
4
|
"description": "The task board for you and your coding agents: a Cloudflare Worker, its web app, Taskwarrior sync, and the CLI (npx breakaway).",
|
|
5
5
|
"license": "FSL-1.1-Apache-2.0",
|
|
6
6
|
"type": "module",
|
package/scripts/tasks/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ export const SUBCOMMANDS = {
|
|
|
9
9
|
agents: ['next', 'start', 'refine', 'new'],
|
|
10
10
|
github: ['fix', 'review'],
|
|
11
11
|
repos: ['add', 'init', 'modify', 'remove', 'setup'],
|
|
12
|
-
routines: ['add', 'modify', 'run', 'trigger', 'revoke', 'pause', 'resume'],
|
|
12
|
+
routines: ['add', 'modify', 'run', 'trigger', 'revoke', 'pause', 'resume', 'cap', 'new'],
|
|
13
13
|
features: ['list', 'add', 'show', 'modify'],
|
|
14
14
|
horizon: ['close'],
|
|
15
15
|
hook: ['session', 'wait'],
|
|
@@ -198,6 +198,39 @@ export function forceFields(force, by) {
|
|
|
198
198
|
return force ? { force: true, ...(by ? { by } : {}) } : {};
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Who writes a routine (BRK-220 section 5): every routines write says who asks, like `features` does, so the board
|
|
203
|
+
* can tell an agent from the owner and let only a routine maker's agent through. Nothing when no name is set.
|
|
204
|
+
* @template {Record<string, unknown>} T
|
|
205
|
+
* @param {T} body
|
|
206
|
+
* @param {string | undefined} by
|
|
207
|
+
*/
|
|
208
|
+
export function routineWrite(body, by) {
|
|
209
|
+
return by ? { ...body, by } : body;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* `routines new` (BRK-220 section 1, Make with an agent): the request that makes a routine maker's task from the
|
|
214
|
+
* owner's words and starts its agent, in the checkout's repository unless `--repo` names another. It says who asks,
|
|
215
|
+
* so the board refuses an agent's name: only the owner starts one.
|
|
216
|
+
* @param {string} prompt
|
|
217
|
+
* @param {{ repo?: string | null, force?: boolean, by?: string }} [options]
|
|
218
|
+
*/
|
|
219
|
+
export function routineMakerRequest(prompt, { repo = null, force = false, by } = {}) {
|
|
220
|
+
const text = String(prompt ?? '').trim();
|
|
221
|
+
if (!text)
|
|
222
|
+
return {
|
|
223
|
+
error:
|
|
224
|
+
'say what the routine should do, and when: npx breakaway routines new "Every Monday, update the changelog from what merged"',
|
|
225
|
+
};
|
|
226
|
+
const body = {
|
|
227
|
+
prompt: text,
|
|
228
|
+
...(repo ? { repo } : {}),
|
|
229
|
+
...(force ? { force: true } : {}),
|
|
230
|
+
};
|
|
231
|
+
return { request: ['POST', 'routines/agent', routineWrite(body, by)] };
|
|
232
|
+
}
|
|
233
|
+
|
|
201
234
|
/**
|
|
202
235
|
* `agents new`: the request that makes a task from a prompt and starts an agent on it. It's the checkout's repository
|
|
203
236
|
* unless `--repo` names another. It always says who asks, so the board refuses an agent's name: only the owner starts one.
|
package/scripts/tasks.mjs
CHANGED
|
@@ -67,6 +67,8 @@ import {
|
|
|
67
67
|
forceFields,
|
|
68
68
|
generalAgentRequest,
|
|
69
69
|
generalAgentSummary,
|
|
70
|
+
routineMakerRequest,
|
|
71
|
+
routineWrite,
|
|
70
72
|
githubRequest,
|
|
71
73
|
specLines,
|
|
72
74
|
specListLines,
|
|
@@ -237,6 +239,8 @@ Reading (list, next, claim, and add work in this checkout's repos
|
|
|
237
239
|
agents next start the next few ready tasks, one per area [--count <n>] [--dry-run] [--repo <slug>]
|
|
238
240
|
routines saved prompts the owner runs with a button, and their caps
|
|
239
241
|
routines run <slug> run one now: makes a RUN task and starts an agent on it [--note <text>] [--force]
|
|
242
|
+
routines new "<what you want>" start an agent that asks how the routines should run, then makes them and turns
|
|
243
|
+
them on [--repo <slug>] [--force] (owner)
|
|
240
244
|
features features by release: each one's progress and chase, and tags that could be features
|
|
241
245
|
features show <slug> one feature: its release, progress, what waits for you, its chase, and its tasks in order
|
|
242
246
|
chase <slug> start a chase (owner): the board starts an agent on every ready task in the feature and on
|
|
@@ -358,9 +362,9 @@ Working
|
|
|
358
362
|
--from <ref> (owner): made from the group <ref> is in on the Dependencies view: its open tasks
|
|
359
363
|
join, and tasks already in another feature stay there
|
|
360
364
|
features modify <slug> change one (owner): --title, --brief, --brief-file, --release <x.y.z|none>, --state open|shipped
|
|
361
|
-
routines add <slug> new routine (owner) --name <text> --prompt <text> | --prompt-file <path> [--done-when <text>] [--horizon now|next|later] [--gap <minutes>] [--daily <n>]
|
|
365
|
+
routines add <slug> new routine (owner, or the agent of a routine maker's task) --name <text> --prompt <text> | --prompt-file <path> [--done-when <text>] [--horizon now|next|later] [--gap <minutes>] [--daily <n>]
|
|
362
366
|
[--repo <slug>] the repository it runs in (default: the checkout's)
|
|
363
|
-
routines modify <slug> change one (owner): the same options (--repo <slug> moves it), and --enabled yes|no; --schedule "0 9 * * 1" runs it on a cron schedule (UTC), --schedule "" clears it; --trigger-start auto|wait sets whether a webhook or GitHub event starts the agent or waits for your Start; --github-events pr_merged,release_published,workflow_failed (or "") starts it on those GitHub events
|
|
367
|
+
routines modify <slug> change one (owner, or the agent of the routine maker's task that made it): the same options (--repo <slug> moves it), and --enabled yes|no; --schedule "0 9 * * 1" runs it on a cron schedule (UTC), --schedule "" clears it; --trigger-start auto|wait sets whether a webhook or GitHub event starts the agent or waits for your Start; --github-events pr_merged,release_published,workflow_failed (or "") starts it on those GitHub events
|
|
364
368
|
routines trigger <slug> new webhook/API trigger (owner): prints its secret once [--label <text>]
|
|
365
369
|
routines revoke <slug> <id> revoke a trigger
|
|
366
370
|
routines pause|resume stop or allow every routine [--daily-all <n>] sets the cap for all routines a day
|
|
@@ -1272,10 +1276,23 @@ const commands = {
|
|
|
1272
1276
|
};
|
|
1273
1277
|
};
|
|
1274
1278
|
const clean = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined));
|
|
1279
|
+
// Who writes (BRK-220 section 5): the owner, or a routine maker's agent while it holds its task.
|
|
1280
|
+
const by = opts.as ?? setting('AGENT');
|
|
1281
|
+
if (sub === 'new') {
|
|
1282
|
+
// Make with an agent (BRK-220 section 1): a routine maker's task in the checkout's repository unless --repo.
|
|
1283
|
+
const built = routineMakerRequest(args.slice(1).join(' '), {
|
|
1284
|
+
repo: opts.repo ?? (await checkoutRepo()).slug,
|
|
1285
|
+
force: Boolean(opts.force),
|
|
1286
|
+
by,
|
|
1287
|
+
});
|
|
1288
|
+
if (built.error || !built.request) fail(built.error ?? 'bad request');
|
|
1289
|
+
print(await call(...built.request), (d) => generalAgentSummary(d));
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1275
1292
|
if (sub === 'run') {
|
|
1276
1293
|
const { task, run } = await call('POST', `routines/${enc(need(args[1], 'routine'))}/run`, {
|
|
1277
1294
|
note: opts.note,
|
|
1278
|
-
...forceFields(opts.force,
|
|
1295
|
+
...forceFields(opts.force, by),
|
|
1279
1296
|
});
|
|
1280
1297
|
print({ task, run }, () => `Started ${task.wid}: ${run.url}`);
|
|
1281
1298
|
return;
|
|
@@ -1283,7 +1300,11 @@ const commands = {
|
|
|
1283
1300
|
if (sub === 'add') {
|
|
1284
1301
|
// A routine runs in one repository (CLD-127): --repo, else the checkout's (none: the board's default).
|
|
1285
1302
|
const repo = opts.repo ?? (await checkoutRepo()).slug ?? undefined;
|
|
1286
|
-
const { routine } = await call(
|
|
1303
|
+
const { routine } = await call(
|
|
1304
|
+
'POST',
|
|
1305
|
+
'routines',
|
|
1306
|
+
routineWrite(clean({ slug: need(args[1], 'slug'), ...fields(), repo }), by),
|
|
1307
|
+
);
|
|
1287
1308
|
print({ routine }, () => `Saved the routine ${routine.slug}. Run it: npx breakaway routines run ${routine.slug}`);
|
|
1288
1309
|
return;
|
|
1289
1310
|
}
|
|
@@ -1291,14 +1312,18 @@ const commands = {
|
|
|
1291
1312
|
const { routine } = await call(
|
|
1292
1313
|
'PATCH',
|
|
1293
1314
|
`routines/${enc(need(args[1], 'routine'))}`,
|
|
1294
|
-
clean({ ...fields(), repo: opts.repo }),
|
|
1315
|
+
routineWrite(clean({ ...fields(), repo: opts.repo }), by),
|
|
1295
1316
|
);
|
|
1296
1317
|
print({ routine }, () => `Saved ${routine.slug}.`);
|
|
1297
1318
|
return;
|
|
1298
1319
|
}
|
|
1299
1320
|
if (sub === 'trigger') {
|
|
1300
1321
|
const slug = need(args[1], 'routine');
|
|
1301
|
-
const { trigger, secret } = await call(
|
|
1322
|
+
const { trigger, secret } = await call(
|
|
1323
|
+
'POST',
|
|
1324
|
+
`routines/${enc(slug)}/triggers`,
|
|
1325
|
+
routineWrite({ label: opts.label }, by),
|
|
1326
|
+
);
|
|
1302
1327
|
print({ trigger, secret }, () =>
|
|
1303
1328
|
[
|
|
1304
1329
|
`Made trigger ${trigger.id} (${trigger.label}) for ${slug}. The secret is shown once; the board keeps only its hash:`,
|
|
@@ -1314,14 +1339,18 @@ const commands = {
|
|
|
1314
1339
|
await call(
|
|
1315
1340
|
'DELETE',
|
|
1316
1341
|
`routines/${enc(need(args[1], 'routine'))}/triggers/${enc(need(args[2], 'trigger id'))}`,
|
|
1317
|
-
{},
|
|
1342
|
+
routineWrite({}, by),
|
|
1318
1343
|
);
|
|
1319
1344
|
print({ ok: true }, () => 'Revoked.');
|
|
1320
1345
|
return;
|
|
1321
1346
|
}
|
|
1322
1347
|
if (sub === 'cap') {
|
|
1323
1348
|
// The cap for all routines a day (CLD-199), without pausing or resuming them.
|
|
1324
|
-
const { settings } = await call(
|
|
1349
|
+
const { settings } = await call(
|
|
1350
|
+
'PATCH',
|
|
1351
|
+
'routines/settings',
|
|
1352
|
+
routineWrite({ dailyCap: Number(need(args[1], 'runs a day')) }, by),
|
|
1353
|
+
);
|
|
1325
1354
|
print({ settings }, (d) => `All routines can run ${d.settings.dailyCap} times a day.`);
|
|
1326
1355
|
return;
|
|
1327
1356
|
}
|
|
@@ -1329,10 +1358,13 @@ const commands = {
|
|
|
1329
1358
|
const { settings } = await call(
|
|
1330
1359
|
'PATCH',
|
|
1331
1360
|
'routines/settings',
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1361
|
+
routineWrite(
|
|
1362
|
+
clean({
|
|
1363
|
+
paused: sub === 'pause',
|
|
1364
|
+
dailyCap: opts['daily-all'] === undefined ? undefined : Number(opts['daily-all']),
|
|
1365
|
+
}),
|
|
1366
|
+
by,
|
|
1367
|
+
),
|
|
1336
1368
|
);
|
|
1337
1369
|
print({ settings }, () => (settings.paused ? 'All routines are paused.' : 'Routines can run.'));
|
|
1338
1370
|
return;
|