@pebblehouse/odin-cli 0.19.0 → 0.21.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 +2 -0
- package/dist/index.js +106 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,6 +71,8 @@ odin search "RLS policies" --pebble odin # Scoped
|
|
|
71
71
|
odin tickets resolve ODIN-12 # Resolve a ticket key to its bet or task
|
|
72
72
|
odin tasks promote <slug> <task-id> --file ./bet.md # Promote a task to a bet (keeps its ticket ID)
|
|
73
73
|
odin tasks create <slug> "Fix" --follow-up-of ODIN-12 # Allocate ODIN-12A as a follow-up
|
|
74
|
+
odin tasks update <slug> ODIN-12 --roadmap <roadmap-id> # Attach a task to a leaf roadmap ('none' detaches; --roadmap-order <n|none>)
|
|
75
|
+
odin tasks list <slug> --roadmap <roadmap-id> # Tasks attached to a roadmap
|
|
74
76
|
```
|
|
75
77
|
|
|
76
78
|
### Roadmaps
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command25 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/auth/login.ts
|
|
7
7
|
import open from "open";
|
|
@@ -759,7 +759,7 @@ plansCmd.command("create <slug> <title>").description("Create a plan").option("-
|
|
|
759
759
|
process.stdout.write(JSON.stringify(res) + "\n");
|
|
760
760
|
if (res.error) process.exit(1);
|
|
761
761
|
});
|
|
762
|
-
plansCmd.command("update <slug> <id>").description("Update a plan").option("--title <title>", "New title").option("--description <description>", "New description").option("--status <status>", "Plan status (active|done|archived)").option("--bet-id <uuid>", "Link plan to a bet").option("--task-id <uuid>", "Link plan to a task").option("--clear-bet", "Clear the bet link").option("--clear-task", "Clear the task link").action(async (slug, id, opts) => {
|
|
762
|
+
plansCmd.command("update <slug> <id>").description("Update a plan").option("--title <title>", "New title").option("--description <description>", "New description").option("--status <status>", "Plan status (active|done|archived)").option("--bet-id <uuid>", "Link plan to a bet").option("--task-id <uuid>", "Link plan to a task").option("--clear-bet", "Clear the bet link").option("--clear-task", "Clear the task link").option("--pr-url <url>", "Bind the plan's pull request URL (claim-guarded on bet-linked plans)").option("--claim-id <id>", "Held delivery claim id").option("--claim-generation <n>", "Held claim generation").option("--skills-version <v>", "odin-skills version").action(async (slug, id, opts) => {
|
|
763
763
|
if (opts.betId && opts.clearBet) {
|
|
764
764
|
process.stderr.write("Cannot combine --bet-id with --clear-bet\n");
|
|
765
765
|
process.exit(1);
|
|
@@ -776,6 +776,11 @@ plansCmd.command("update <slug> <id>").description("Update a plan").option("--ti
|
|
|
776
776
|
else if (opts.clearBet) body.bet_id = null;
|
|
777
777
|
if (opts.taskId) body.task_id = opts.taskId;
|
|
778
778
|
else if (opts.clearTask) body.task_id = null;
|
|
779
|
+
if (opts.prUrl) body.pr_url = opts.prUrl;
|
|
780
|
+
Object.assign(body, {
|
|
781
|
+
...opts.claimId ? { claim_id: opts.claimId, claim_generation: Number(opts.claimGeneration) } : {},
|
|
782
|
+
...opts.skillsVersion ? { skills_version: opts.skillsVersion } : {}
|
|
783
|
+
});
|
|
779
784
|
const res = await apiRequest(`/pebbles/${slug}/plans/${id}`, {
|
|
780
785
|
method: "PUT",
|
|
781
786
|
body
|
|
@@ -802,12 +807,16 @@ plansCmd.command("add-phase <slug> <planId> <title>").description("Add a phase t
|
|
|
802
807
|
process.stdout.write(JSON.stringify(res) + "\n");
|
|
803
808
|
if (res.error) process.exit(1);
|
|
804
809
|
});
|
|
805
|
-
plansCmd.command("update-phase <slug> <planId> <phaseId>").description("Update a phase").option("--title <title>", "Phase title").option("--status <status>", "Phase status (pending|in_progress|done|skipped)").option("--notes <notes>", "Phase notes").option("--description <description>", "Phase description").action(async (slug, planId, phaseId, opts) => {
|
|
810
|
+
plansCmd.command("update-phase <slug> <planId> <phaseId>").description("Update a phase").option("--title <title>", "Phase title").option("--status <status>", "Phase status (pending|in_progress|done|skipped)").option("--notes <notes>", "Phase notes").option("--description <description>", "Phase description").option("--claim-id <id>", "Held delivery claim id").option("--claim-generation <n>", "Held claim generation").option("--skills-version <v>", "odin-skills version").action(async (slug, planId, phaseId, opts) => {
|
|
806
811
|
const body = {};
|
|
807
812
|
if (opts.title) body.title = opts.title;
|
|
808
813
|
if (opts.status) body.status = opts.status;
|
|
809
814
|
if (opts.notes) body.notes = opts.notes;
|
|
810
815
|
if (opts.description) body.description = opts.description;
|
|
816
|
+
Object.assign(body, {
|
|
817
|
+
...opts.claimId ? { claim_id: opts.claimId, claim_generation: Number(opts.claimGeneration) } : {},
|
|
818
|
+
...opts.skillsVersion ? { skills_version: opts.skillsVersion } : {}
|
|
819
|
+
});
|
|
811
820
|
const res = await apiRequest(`/pebbles/${slug}/plans/${planId}/phases/${phaseId}`, {
|
|
812
821
|
method: "PUT",
|
|
813
822
|
body
|
|
@@ -1276,7 +1285,7 @@ betsCmd.command("delete <slug> <id>").description("Delete a bet").action(async (
|
|
|
1276
1285
|
if (res.error) process.exit(1);
|
|
1277
1286
|
});
|
|
1278
1287
|
betsCmd.addCommand(depsCmd);
|
|
1279
|
-
betsCmd.command("transition <slug> <id>").description("Apply a guarded lifecycle operation (never a raw status write)").requiredOption("--op <operation>", "start_shaping | approve_ready | handoff | complete | return_to_shaping | archive | correct_stage | open_blocker | resolve_blocker | set_queued | clear_queued").requiredOption("--expected-revision <n>", "lifecycle_revision from `odin bets get`").option("--to <stage>", `Target stage for handoff/correct_stage (${STAGE_HELP})`).option("--reason <text>", "Reason (required for return loops, skips and return_to_shaping)").option("--note <text>", "Optional correction/resolution note").option("--actor <label>", "Persona slug or handle recorded on the event", "cli").option("--actor-kind <kind>", "human | persona", "human").option("--idempotency-key <key>", "Reuse the same key when retrying after a timeout").option("--payload <json>", "Extra payload JSON merged last (check_token/exceptions, category, blocker_id, owner_persona\u2026)").action(async (slug, id, opts) => {
|
|
1288
|
+
betsCmd.command("transition <slug> <id>").description("Apply a guarded lifecycle operation (never a raw status write)").requiredOption("--op <operation>", "start_shaping | approve_ready | handoff | complete | return_to_shaping | archive | correct_stage | open_blocker | resolve_blocker | set_queued | clear_queued").requiredOption("--expected-revision <n>", "lifecycle_revision from `odin bets get`").option("--to <stage>", `Target stage for handoff/correct_stage (${STAGE_HELP})`).option("--reason <text>", "Reason (required for return loops, skips and return_to_shaping)").option("--note <text>", "Optional correction/resolution note").option("--actor <label>", "Persona slug or handle recorded on the event", "cli").option("--actor-kind <kind>", "human | persona", "human").option("--idempotency-key <key>", "Reuse the same key when retrying after a timeout").option("--payload <json>", "Extra payload JSON merged last (check_token/exceptions, category, blocker_id, owner_persona\u2026)").option("--claim-id <id>", "Held delivery claim id").option("--claim-generation <n>", "Held claim generation").option("--skills-version <v>", "odin-skills version").action(async (slug, id, opts) => {
|
|
1280
1289
|
let extra = {};
|
|
1281
1290
|
if (opts.payload) {
|
|
1282
1291
|
try {
|
|
@@ -1287,7 +1296,16 @@ betsCmd.command("transition <slug> <id>").description("Apply a guarded lifecycle
|
|
|
1287
1296
|
}
|
|
1288
1297
|
}
|
|
1289
1298
|
const payload = { ...opts.to ? { to_stage: opts.to } : {}, ...opts.reason ? { reason: opts.reason } : {}, ...opts.note ? { note: opts.note } : {}, ...extra };
|
|
1290
|
-
const body = {
|
|
1299
|
+
const body = {
|
|
1300
|
+
operation: opts.op,
|
|
1301
|
+
expected_revision: Number(opts.expectedRevision),
|
|
1302
|
+
idempotency_key: opts.idempotencyKey ?? randomUUID(),
|
|
1303
|
+
actor_label: opts.actor,
|
|
1304
|
+
actor_kind: opts.actorKind,
|
|
1305
|
+
payload,
|
|
1306
|
+
...opts.claimId ? { claim_id: opts.claimId, claim_generation: Number(opts.claimGeneration) } : {},
|
|
1307
|
+
...opts.skillsVersion ? { skills_version: opts.skillsVersion } : {}
|
|
1308
|
+
};
|
|
1291
1309
|
const res = await apiRequest(`/pebbles/${slug}/bets/${id}/lifecycle`, { method: "POST", body });
|
|
1292
1310
|
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1293
1311
|
if (res.error) process.exit(1);
|
|
@@ -1308,9 +1326,32 @@ betsCmd.command("lifecycle-contract").description("Stages, transition matrix, Re
|
|
|
1308
1326
|
if (res.error) process.exit(1);
|
|
1309
1327
|
});
|
|
1310
1328
|
|
|
1311
|
-
// src/commands/
|
|
1329
|
+
// src/commands/delivery.ts
|
|
1312
1330
|
import { Command as Command15 } from "commander";
|
|
1313
|
-
var
|
|
1331
|
+
var deliveryCmd = new Command15("delivery").description("Delivery admission: claim, validate, release (DELIVERY-ADMISSION-REFERENCE.md)");
|
|
1332
|
+
var out = (res, okWhen) => {
|
|
1333
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1334
|
+
if (res.error || !okWhen(res.data)) process.exit(1);
|
|
1335
|
+
};
|
|
1336
|
+
deliveryCmd.command("claim <slug>").option("--bet <id>").requiredOption("--persona <slug>").requiredOption("--attempt-id <id>").option("--host <host>").action(async (slug, o) => {
|
|
1337
|
+
const res = await apiRequest(`/pebbles/${slug}/delivery/claim`, {
|
|
1338
|
+
method: "POST",
|
|
1339
|
+
body: { ...o.bet ? { bet_id: o.bet } : {}, persona: o.persona, attempt_id: o.attemptId, ...o.host ? { host: o.host } : {} }
|
|
1340
|
+
});
|
|
1341
|
+
out(res, (d) => ["granted", "no_work", "resource_wait"].includes(d?.outcome));
|
|
1342
|
+
});
|
|
1343
|
+
deliveryCmd.command("validate <slug> <betId>").requiredOption("--claim-id <id>").requiredOption("--claim-generation <n>").action(async (slug, betId, o) => {
|
|
1344
|
+
const res = await apiRequest(`/pebbles/${slug}/delivery/validate`, { method: "POST", body: { bet_id: betId, claim_id: o.claimId, claim_generation: Number(o.claimGeneration) } });
|
|
1345
|
+
out(res, (d) => d?.valid === true);
|
|
1346
|
+
});
|
|
1347
|
+
deliveryCmd.command("release <slug>").requiredOption("--claim-id <id>").requiredOption("--claim-generation <n>").option("--scope <scope>", "claim | migration", "claim").option("--actor <label>", "persona slug", "cli").action(async (slug, o) => {
|
|
1348
|
+
const res = await apiRequest(`/pebbles/${slug}/delivery/release`, { method: "POST", body: { claim_id: o.claimId, claim_generation: Number(o.claimGeneration), scope: o.scope, actor_label: o.actor } });
|
|
1349
|
+
out(res, (d) => d?.ok === true);
|
|
1350
|
+
});
|
|
1351
|
+
|
|
1352
|
+
// src/commands/tickets.ts
|
|
1353
|
+
import { Command as Command16 } from "commander";
|
|
1354
|
+
var ticketsCmd = new Command16("tickets").description("Resolve human-readable ticket IDs");
|
|
1314
1355
|
ticketsCmd.command("resolve <key>").description("Resolve a ticket key (e.g. ODIN-12, RATE-36A) to its bet or task, with historical candidates").action(async (key) => {
|
|
1315
1356
|
const res = await apiRequest(`/tickets/${encodeURIComponent(key.trim().toUpperCase())}`);
|
|
1316
1357
|
process.stdout.write(JSON.stringify(res) + "\n");
|
|
@@ -1323,9 +1364,9 @@ ticketsCmd.command("resolve <key>").description("Resolve a ticket key (e.g. ODIN
|
|
|
1323
1364
|
});
|
|
1324
1365
|
|
|
1325
1366
|
// src/commands/bet-comments.ts
|
|
1326
|
-
import { Command as
|
|
1367
|
+
import { Command as Command17 } from "commander";
|
|
1327
1368
|
import { readFileSync as readFileSync11 } from "fs";
|
|
1328
|
-
var betCommentsCmd = new
|
|
1369
|
+
var betCommentsCmd = new Command17("bet-comments").description("Manage bet comments");
|
|
1329
1370
|
betCommentsCmd.command("list <slug> <betId>").description("List comments for a bet (oldest first)").action(async (slug, betId) => {
|
|
1330
1371
|
const res = await apiRequest(`/pebbles/${slug}/bets/${betId}/comments`);
|
|
1331
1372
|
process.stdout.write(JSON.stringify(res) + "\n");
|
|
@@ -1352,11 +1393,11 @@ betCommentsCmd.command("create <slug> <betId> [body]").description("Post a comme
|
|
|
1352
1393
|
});
|
|
1353
1394
|
|
|
1354
1395
|
// src/commands/tasks.ts
|
|
1355
|
-
import { Command as
|
|
1396
|
+
import { Command as Command18 } from "commander";
|
|
1356
1397
|
import { readFileSync as readFileSync12 } from "fs";
|
|
1357
|
-
var tasksCmd = new
|
|
1398
|
+
var tasksCmd = new Command18("tasks").description("Manage tasks");
|
|
1358
1399
|
withListFlags(
|
|
1359
|
-
tasksCmd.command("list <slug>").description("List tasks for a pebble").option("--status <status>", "Filter by status").option("--bet <bet-id>", "Filter by bet ID")
|
|
1400
|
+
tasksCmd.command("list <slug>").description("List tasks for a pebble").option("--status <status>", "Filter by status").option("--bet <bet-id>", "Filter by bet ID").option("--roadmap <roadmap-id>", "Filter to tasks attached to this roadmap")
|
|
1360
1401
|
).action(async (slug, opts) => {
|
|
1361
1402
|
const resolved = resolveListParams(opts);
|
|
1362
1403
|
if (resolved.fatal) {
|
|
@@ -1367,6 +1408,7 @@ withListFlags(
|
|
|
1367
1408
|
const params = { ...resolved.params };
|
|
1368
1409
|
if (opts.status) params.status = opts.status;
|
|
1369
1410
|
if (opts.bet) params.bet_id = opts.bet;
|
|
1411
|
+
if (opts.roadmap) params.roadmap_id = opts.roadmap;
|
|
1370
1412
|
const res = await apiRequest(`/pebbles/${slug}/tasks`, { params });
|
|
1371
1413
|
emitListResult(res, "tasks", resolved);
|
|
1372
1414
|
});
|
|
@@ -1375,21 +1417,47 @@ tasksCmd.command("get <slug> <id>").description("Get a task by ID").action(async
|
|
|
1375
1417
|
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1376
1418
|
if (res.error) process.exit(1);
|
|
1377
1419
|
});
|
|
1378
|
-
tasksCmd.command("create <slug> <title>").description("Create a task").option("--source <source>", "Source agent", "claude-code").option("--description <description>", "Task description").option("--bet <bet-id>", "Parent bet ID").option("--status <status>", "Task status").option("--priority <priority>", "Task priority").option("--follow-up-of <key-or-uuid>", "Allocate a suffixed follow-up ticket in this ticket's family (e.g. ODIN-12 \u2192 ODIN-12A)").action(async (slug, title, opts) => {
|
|
1420
|
+
tasksCmd.command("create <slug> <title>").description("Create a task").option("--source <source>", "Source agent", "claude-code").option("--description <description>", "Task description").option("--bet <bet-id>", "Parent bet ID").option("--status <status>", "Task status").option("--priority <priority>", "Task priority").option("--follow-up-of <key-or-uuid>", "Allocate a suffixed follow-up ticket in this ticket's family (e.g. ODIN-12 \u2192 ODIN-12A)").option("--roadmap <roadmap-id>", "Attach to a leaf roadmap").option("--roadmap-order <n>", "Ordering among tasks on the roadmap").action(async (slug, title, opts) => {
|
|
1421
|
+
const roadmapOrder = opts.roadmapOrder !== void 0 ? Number(opts.roadmapOrder) : void 0;
|
|
1422
|
+
if (roadmapOrder !== void 0 && !Number.isInteger(roadmapOrder)) {
|
|
1423
|
+
process.stderr.write("--roadmap-order must be an integer or 'none'\n");
|
|
1424
|
+
process.exit(1);
|
|
1425
|
+
return;
|
|
1426
|
+
}
|
|
1379
1427
|
const res = await apiRequest(`/pebbles/${slug}/tasks`, {
|
|
1380
1428
|
method: "POST",
|
|
1381
|
-
body: {
|
|
1429
|
+
body: {
|
|
1430
|
+
title,
|
|
1431
|
+
source: opts.source,
|
|
1432
|
+
description: opts.description,
|
|
1433
|
+
bet_id: opts.bet,
|
|
1434
|
+
status: opts.status,
|
|
1435
|
+
priority: opts.priority,
|
|
1436
|
+
follow_up_of: opts.followUpOf,
|
|
1437
|
+
roadmap_id: opts.roadmap,
|
|
1438
|
+
roadmap_order: roadmapOrder
|
|
1439
|
+
}
|
|
1382
1440
|
});
|
|
1383
1441
|
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1384
1442
|
if (res.error) process.exit(1);
|
|
1385
1443
|
});
|
|
1386
|
-
tasksCmd.command("update <slug> <id>").description("Update a task").option("--title <title>", "New title").option("--description <description>", "New description").option("--status <status>", "New status").option("--priority <priority>", "New priority").option("--bet <bet-id>", "New parent bet ID").action(async (slug, id, opts) => {
|
|
1444
|
+
tasksCmd.command("update <slug> <id>").description("Update a task").option("--title <title>", "New title").option("--description <description>", "New description").option("--status <status>", "New status").option("--priority <priority>", "New priority").option("--bet <bet-id>", "New parent bet ID").option("--roadmap <roadmap-id|none>", "Attach to a leaf roadmap; 'none' detaches").option("--roadmap-order <n|none>", "Ordering among tasks on the roadmap; 'none' clears").action(async (slug, id, opts) => {
|
|
1387
1445
|
const body = {};
|
|
1388
1446
|
if (opts.title) body.title = opts.title;
|
|
1389
1447
|
if (opts.description) body.description = opts.description;
|
|
1390
1448
|
if (opts.status) body.status = opts.status;
|
|
1391
1449
|
if (opts.priority) body.priority = opts.priority;
|
|
1392
1450
|
if (opts.bet) body.bet_id = opts.bet;
|
|
1451
|
+
if (opts.roadmap !== void 0) body.roadmap_id = opts.roadmap === "none" ? null : opts.roadmap;
|
|
1452
|
+
if (opts.roadmapOrder !== void 0) {
|
|
1453
|
+
const order = opts.roadmapOrder === "none" ? null : Number(opts.roadmapOrder);
|
|
1454
|
+
if (order !== null && !Number.isInteger(order)) {
|
|
1455
|
+
process.stderr.write("--roadmap-order must be an integer or 'none'\n");
|
|
1456
|
+
process.exit(1);
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
body.roadmap_order = order;
|
|
1460
|
+
}
|
|
1393
1461
|
const res = await apiRequest(`/pebbles/${slug}/tasks/${id}`, {
|
|
1394
1462
|
method: "PUT",
|
|
1395
1463
|
body
|
|
@@ -1415,7 +1483,7 @@ tasksCmd.command("delete <slug> <id>").description("Delete a task").action(async
|
|
|
1415
1483
|
});
|
|
1416
1484
|
|
|
1417
1485
|
// src/commands/roadmaps.ts
|
|
1418
|
-
import { Command as
|
|
1486
|
+
import { Command as Command19 } from "commander";
|
|
1419
1487
|
import { readFileSync as readFileSync14 } from "fs";
|
|
1420
1488
|
|
|
1421
1489
|
// src/resolve-pebble.ts
|
|
@@ -1438,7 +1506,7 @@ function resolvePebbleSlug(explicit, cwd = process.cwd()) {
|
|
|
1438
1506
|
}
|
|
1439
1507
|
|
|
1440
1508
|
// src/commands/roadmaps.ts
|
|
1441
|
-
var roadmapsCmd = new
|
|
1509
|
+
var roadmapsCmd = new Command19("roadmaps").description("Manage roadmaps");
|
|
1442
1510
|
roadmapsCmd.command("list <slug>").description("List roadmaps for a pebble").option("--status <status>", "Filter by status").option("--all", "Include child roadmaps (default: top-level only)").action(async (slug, opts) => {
|
|
1443
1511
|
const params = { nesting: opts.all ? "all" : "top" };
|
|
1444
1512
|
if (opts.status) params.status = opts.status;
|
|
@@ -1524,11 +1592,11 @@ clientDraftCmd.command("save <roadmap-id>").description("Save the draft; --file
|
|
|
1524
1592
|
});
|
|
1525
1593
|
|
|
1526
1594
|
// src/commands/persona-runs.ts
|
|
1527
|
-
import { Command as
|
|
1595
|
+
import { Command as Command20 } from "commander";
|
|
1528
1596
|
import { readFileSync as readFileSync15 } from "fs";
|
|
1529
1597
|
import { join as join3 } from "path";
|
|
1530
1598
|
import { homedir as homedir2 } from "os";
|
|
1531
|
-
var personaRunsCmd = new
|
|
1599
|
+
var personaRunsCmd = new Command20("persona-runs").description(
|
|
1532
1600
|
"Manage per-persona per-session token usage rows"
|
|
1533
1601
|
);
|
|
1534
1602
|
personaRunsCmd.command("list <slug>").description("List persona runs for a pebble").option("--bet-id <id>", "Filter by bet_id").option("--plan-id <id>", "Filter by plan_id").option("--persona <name>", "Filter by persona name").option("--limit <n>", "Max rows", "50").action(async (slug, opts) => {
|
|
@@ -1625,9 +1693,9 @@ personaRunsCmd.command("capture").description("Read marker + transcript, compute
|
|
|
1625
1693
|
});
|
|
1626
1694
|
|
|
1627
1695
|
// src/commands/blog.ts
|
|
1628
|
-
import { Command as
|
|
1696
|
+
import { Command as Command21 } from "commander";
|
|
1629
1697
|
import { readFileSync as readFileSync16 } from "fs";
|
|
1630
|
-
var blogCmd = new
|
|
1698
|
+
var blogCmd = new Command21("blog").description("Manage blog posts");
|
|
1631
1699
|
blogCmd.command("list <slug>").description("List blog posts for a pebble").option("--status <status>", "Filter by status (draft, review, scheduled, published, archived)").option("--tag <tag>", "Filter by tag").option("--page <page>", "Page number", "1").option("--per-page <perPage>", "Results per page", "20").action(async (slug, opts) => {
|
|
1632
1700
|
const params = {};
|
|
1633
1701
|
if (opts.status) params.status = opts.status;
|
|
@@ -1692,8 +1760,8 @@ blogCmd.command("delete <slug> <id>").description("Delete a blog post").action(a
|
|
|
1692
1760
|
});
|
|
1693
1761
|
|
|
1694
1762
|
// src/commands/api-keys.ts
|
|
1695
|
-
import { Command as
|
|
1696
|
-
var apiKeysCmd = new
|
|
1763
|
+
import { Command as Command22 } from "commander";
|
|
1764
|
+
var apiKeysCmd = new Command22("api-keys").description("Manage API keys for server-to-server access");
|
|
1697
1765
|
apiKeysCmd.command("list <slug>").description("List API keys for a pebble").action(async (slug) => {
|
|
1698
1766
|
const res = await apiRequest(`/pebbles/${slug}/api-keys`);
|
|
1699
1767
|
process.stdout.write(JSON.stringify(res) + "\n");
|
|
@@ -1735,7 +1803,7 @@ apiKeysCmd.command("delete <slug> <id>").description("Permanently delete an API
|
|
|
1735
1803
|
});
|
|
1736
1804
|
|
|
1737
1805
|
// src/commands/pebble/index.ts
|
|
1738
|
-
import { Command as
|
|
1806
|
+
import { Command as Command23 } from "commander";
|
|
1739
1807
|
|
|
1740
1808
|
// src/commands/pebble/provisioner.ts
|
|
1741
1809
|
async function runProvisioner(ctx, steps) {
|
|
@@ -2148,7 +2216,7 @@ Hand off: /odin:eng-manager bet:${bet.data.id}
|
|
|
2148
2216
|
}
|
|
2149
2217
|
|
|
2150
2218
|
// src/commands/pebble/index.ts
|
|
2151
|
-
var pebbleCmd = new
|
|
2219
|
+
var pebbleCmd = new Command23("pebble").description(
|
|
2152
2220
|
"Provision and initialize pebbles (eng-infra, run-once)"
|
|
2153
2221
|
);
|
|
2154
2222
|
pebbleCmd.command("new <name>").description("Provision a new pebble from pebble-template (day-one)").option("--run", "Hand off to eng-manager on the init bet").option("--dir <path>", "Parent dir to clone into").option("--dry-run", "Print the plan; mutate nothing").action(async (name, opts) => {
|
|
@@ -2169,7 +2237,7 @@ pebbleCmd.command("provision <provider> <slug>").description("Run one provider s
|
|
|
2169
2237
|
});
|
|
2170
2238
|
|
|
2171
2239
|
// src/commands/create/index.ts
|
|
2172
|
-
import { Command as
|
|
2240
|
+
import { Command as Command24 } from "commander";
|
|
2173
2241
|
|
|
2174
2242
|
// src/commands/create/topology.ts
|
|
2175
2243
|
var ENVS = ["prd", "stg", "dev"];
|
|
@@ -2269,9 +2337,9 @@ var tokensStep = {
|
|
|
2269
2337
|
const supabaseAccessToken = await io.secret(
|
|
2270
2338
|
"Supabase Access Token (TF_VAR_SUPABASE_ACCESS_TOKEN):"
|
|
2271
2339
|
);
|
|
2272
|
-
const
|
|
2273
|
-
if (vercelTeamId)
|
|
2274
|
-
return
|
|
2340
|
+
const out2 = { vercelApiToken, vercelToken, supabaseAccessToken };
|
|
2341
|
+
if (vercelTeamId) out2.vercelTeamId = vercelTeamId;
|
|
2342
|
+
return out2;
|
|
2275
2343
|
}
|
|
2276
2344
|
};
|
|
2277
2345
|
var vercelStep2 = {
|
|
@@ -2595,17 +2663,17 @@ var ENV_KEY_MAP = {
|
|
|
2595
2663
|
SUPABASE_DB_PASSWORD: "supabaseDbPassword"
|
|
2596
2664
|
};
|
|
2597
2665
|
function capturedFromDoppler(prd, stg) {
|
|
2598
|
-
const
|
|
2666
|
+
const out2 = {};
|
|
2599
2667
|
for (const [dopplerKey, capKey] of Object.entries(SHARED_KEY_MAP)) {
|
|
2600
|
-
if (prd[dopplerKey])
|
|
2668
|
+
if (prd[dopplerKey]) out2[capKey] = prd[dopplerKey];
|
|
2601
2669
|
}
|
|
2602
|
-
if (prd.TF_VAR_APP_DOMAIN)
|
|
2670
|
+
if (prd.TF_VAR_APP_DOMAIN) out2.appDomain = prd.TF_VAR_APP_DOMAIN.replace(/^app\./, "");
|
|
2603
2671
|
for (const [env, cfg] of [["prd", prd], ["stg", stg]]) {
|
|
2604
2672
|
for (const [dopplerKey, capKey] of Object.entries(ENV_KEY_MAP)) {
|
|
2605
|
-
if (cfg[dopplerKey])
|
|
2673
|
+
if (cfg[dopplerKey]) out2[`${env}_${capKey}`] = cfg[dopplerKey];
|
|
2606
2674
|
}
|
|
2607
2675
|
}
|
|
2608
|
-
return
|
|
2676
|
+
return out2;
|
|
2609
2677
|
}
|
|
2610
2678
|
function assembleInputs(ctx) {
|
|
2611
2679
|
const c = ctx.captured;
|
|
@@ -2634,13 +2702,13 @@ function assembleInputs(ctx) {
|
|
|
2634
2702
|
}
|
|
2635
2703
|
|
|
2636
2704
|
// src/commands/create/index.ts
|
|
2637
|
-
var createCmd = new
|
|
2705
|
+
var createCmd = new Command24("create").description(
|
|
2638
2706
|
"Create and provision a new project end to end"
|
|
2639
2707
|
);
|
|
2640
2708
|
createCmd.command("project [name]").description("Guided self-serve project + parallel-env provisioning").option("--dry-run", "Print the plan; mutate nothing").action(
|
|
2641
2709
|
async (name, opts) => process.exit(await runCreate(name, { dryRun: opts.dryRun }))
|
|
2642
2710
|
);
|
|
2643
|
-
var setupCmd = new
|
|
2711
|
+
var setupCmd = new Command24("setup").description("Alias for `create project`").arguments("[name]").option("--dry-run", "Print the plan; mutate nothing").action(
|
|
2644
2712
|
async (name, opts) => process.exit(await runCreate(name, { dryRun: opts.dryRun }))
|
|
2645
2713
|
);
|
|
2646
2714
|
|
|
@@ -2667,7 +2735,7 @@ ${RESET}
|
|
|
2667
2735
|
${DIM}${cwd}${RESET}
|
|
2668
2736
|
`);
|
|
2669
2737
|
}
|
|
2670
|
-
var program = new
|
|
2738
|
+
var program = new Command25();
|
|
2671
2739
|
program.name("odin").description("CLI for Odin \u2014 the knowledge backbone for Pebble House").version(VERSION);
|
|
2672
2740
|
program.command("login").description("Authenticate with Odin via browser").option("--device", "Use the device-code flow (for headless or remote machines)").action(async (options) => {
|
|
2673
2741
|
printBanner();
|
|
@@ -2696,6 +2764,7 @@ program.addCommand(rulesCmd);
|
|
|
2696
2764
|
program.addCommand(briefsCmd);
|
|
2697
2765
|
program.addCommand(blueprintsCmd);
|
|
2698
2766
|
program.addCommand(betsCmd);
|
|
2767
|
+
program.addCommand(deliveryCmd);
|
|
2699
2768
|
program.addCommand(ticketsCmd);
|
|
2700
2769
|
program.addCommand(betCommentsCmd);
|
|
2701
2770
|
program.addCommand(tasksCmd);
|