@pebblehouse/odin-cli 0.18.1 → 0.18.3

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.
Files changed (2) hide show
  1. package/dist/index.js +25 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1225,9 +1225,9 @@ depsCmd.command("remove <slug> <bet-id>").description("Remove a blocked-by depen
1225
1225
 
1226
1226
  // src/commands/bets.ts
1227
1227
  var betsCmd = new Command14("bets").description("Manage bets");
1228
- var STAGE_HELP = "pitch, shaping, ready, planning, building, review, qa, shipping, done, archived (legacy: shaped, betting, active, blocked)";
1228
+ var STAGE_HELP = "pitch, shaping, ready, planning, building, review, qa, shipping, done, archived";
1229
1229
  withListFlags(
1230
- betsCmd.command("list <slug>").description("List bets for a pebble").option("--status <status>", `Status (${STAGE_HELP})`)
1230
+ betsCmd.command("list <slug>").description("List bets for a pebble").option("--status <status>", `Stage (${STAGE_HELP})`)
1231
1231
  ).action(async (slug, opts) => {
1232
1232
  const resolved = resolveListParams(opts);
1233
1233
  if (resolved.fatal) {
@@ -1245,21 +1245,20 @@ betsCmd.command("get <slug> <id>").description("Get a bet by ID").action(async (
1245
1245
  process.stdout.write(JSON.stringify(res) + "\n");
1246
1246
  if (res.error) process.exit(1);
1247
1247
  });
1248
- betsCmd.command("create <slug> <title>").description("Create a bet").option("--source <source>", "Source agent", "claude-code").option("--content <content>", "Bet content").option("--file <path>", "Read content from file").option("--status <status>", "pitch (default) or shaped (transitional)").option("--priority <priority>", "Bet priority").option("--appetite <appetite>", "Bet appetite").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) => {
1248
+ betsCmd.command("create <slug> <title>").description("Create a bet").option("--source <source>", "Source agent", "claude-code").option("--content <content>", "Bet content").option("--file <path>", "Read content from file").option("--priority <priority>", "Bet priority").option("--appetite <appetite>", "Bet appetite").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) => {
1249
1249
  const content = opts.file ? readFileSync10(opts.file, "utf-8") : opts.content ?? "";
1250
1250
  const res = await apiRequest(`/pebbles/${slug}/bets`, {
1251
1251
  method: "POST",
1252
- body: { title, source: opts.source, content, status: opts.status, priority: opts.priority, appetite: opts.appetite, follow_up_of: opts.followUpOf }
1252
+ body: { title, source: opts.source, content, priority: opts.priority, appetite: opts.appetite, follow_up_of: opts.followUpOf }
1253
1253
  });
1254
1254
  process.stdout.write(JSON.stringify(res) + "\n");
1255
1255
  if (res.error) process.exit(1);
1256
1256
  });
1257
- betsCmd.command("update <slug> <id>").description("Update a bet").option("--title <title>", "New title").option("--content <content>", "New content").option("--file <path>", "Read content from file").option("--status <status>", `New status \u2014 legacy-governed bets only; lifecycle-governed bets use \`odin bets transition\` (${STAGE_HELP})`).option("--priority <priority>", "New priority").option("--appetite <appetite>", "New appetite").action(async (slug, id, opts) => {
1257
+ betsCmd.command("update <slug> <id>").description("Update a bet's title, content, priority or appetite (stage changes: odin bets transition)").option("--title <title>", "New title").option("--content <content>", "New content").option("--file <path>", "Read content from file").option("--priority <priority>", "New priority").option("--appetite <appetite>", "New appetite").action(async (slug, id, opts) => {
1258
1258
  const body = {};
1259
1259
  if (opts.title) body.title = opts.title;
1260
1260
  if (opts.file) body.content = readFileSync10(opts.file, "utf-8");
1261
1261
  else if (opts.content) body.content = opts.content;
1262
- if (opts.status) body.status = opts.status;
1263
1262
  if (opts.priority) body.priority = opts.priority;
1264
1263
  if (opts.appetite) body.appetite = opts.appetite;
1265
1264
  const res = await apiRequest(`/pebbles/${slug}/bets/${id}`, {
@@ -1398,11 +1397,11 @@ tasksCmd.command("update <slug> <id>").description("Update a task").option("--ti
1398
1397
  process.stdout.write(JSON.stringify(res) + "\n");
1399
1398
  if (res.error) process.exit(1);
1400
1399
  });
1401
- tasksCmd.command("promote <slug> <id>").description("Promote a task to a bet, keeping its ticket ID and history").option("--content <content>", "Shaped bet markdown").option("--file <path>", "Read bet markdown from file").option("--status <status>", "Bet status (pitch | shaped)", "shaped").option("--priority <priority>", "Bet priority").action(async (slug, id, opts) => {
1400
+ tasksCmd.command("promote <slug> <id>").description("Promote a task to a bet, keeping its ticket ID and history (the bet starts in pitch)").option("--content <content>", "Shaped bet markdown").option("--file <path>", "Read bet markdown from file").option("--priority <priority>", "Bet priority").action(async (slug, id, opts) => {
1402
1401
  const content = opts.file ? readFileSync12(opts.file, "utf-8") : opts.content;
1403
1402
  const res = await apiRequest(`/pebbles/${slug}/tasks/${id}/promote`, {
1404
1403
  method: "POST",
1405
- body: { content, status: opts.status, priority: opts.priority }
1404
+ body: { content, priority: opts.priority }
1406
1405
  });
1407
1406
  process.stdout.write(JSON.stringify(res) + "\n");
1408
1407
  if (res.error) process.exit(1);
@@ -1419,8 +1418,8 @@ tasksCmd.command("delete <slug> <id>").description("Delete a task").action(async
1419
1418
  import { Command as Command18 } from "commander";
1420
1419
  import { readFileSync as readFileSync13 } from "fs";
1421
1420
  var roadmapsCmd = new Command18("roadmaps").description("Manage roadmaps");
1422
- roadmapsCmd.command("list <slug>").description("List roadmaps for a pebble").option("--status <status>", "Filter by status").action(async (slug, opts) => {
1423
- const params = {};
1421
+ 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) => {
1422
+ const params = { nesting: opts.all ? "all" : "top" };
1424
1423
  if (opts.status) params.status = opts.status;
1425
1424
  const res = await apiRequest(`/pebbles/${slug}/roadmaps`, { params });
1426
1425
  process.stdout.write(JSON.stringify(res) + "\n");
@@ -1431,21 +1430,33 @@ roadmapsCmd.command("get <slug> <id>").description("Get a roadmap by ID (include
1431
1430
  process.stdout.write(JSON.stringify(res) + "\n");
1432
1431
  if (res.error) process.exit(1);
1433
1432
  });
1434
- roadmapsCmd.command("create <slug> <title>").description("Create a roadmap").option("--source <source>", "Source agent", "claude-code").option("--content <content>", "Roadmap content").option("--file <path>", "Read content from file").option("--status <status>", "Roadmap status").action(async (slug, title, opts) => {
1433
+ roadmapsCmd.command("create <slug> <title>").description("Create a roadmap").option("--source <source>", "Source agent", "claude-code").option("--content <content>", "Roadmap content").option("--file <path>", "Read content from file").option("--status <status>", "Roadmap status").option("--parent <id>", "Parent roadmap UUID (nesting is capped at 2 levels)").option("--starts-on <date>", "Start date, YYYY-MM-DD").option("--ends-on <date>", "End date, YYYY-MM-DD").action(async (slug, title, opts) => {
1435
1434
  const content = opts.file ? readFileSync13(opts.file, "utf-8") : opts.content ?? "";
1436
1435
  const res = await apiRequest(`/pebbles/${slug}/roadmaps`, {
1437
1436
  method: "POST",
1438
- body: { title, source: opts.source, content, status: opts.status }
1437
+ body: {
1438
+ title,
1439
+ source: opts.source,
1440
+ content,
1441
+ status: opts.status,
1442
+ parent_roadmap_id: opts.parent,
1443
+ starts_on: opts.startsOn,
1444
+ ends_on: opts.endsOn
1445
+ }
1439
1446
  });
1440
1447
  process.stdout.write(JSON.stringify(res) + "\n");
1441
1448
  if (res.error) process.exit(1);
1442
1449
  });
1443
- roadmapsCmd.command("update <slug> <id>").description("Update a roadmap").option("--title <title>", "New title").option("--content <content>", "New content").option("--file <path>", "Read content from file").option("--status <status>", "New status").action(async (slug, id, opts) => {
1450
+ roadmapsCmd.command("update <slug> <id>").description("Update a roadmap").option("--title <title>", "New title").option("--content <content>", "New content").option("--file <path>", "Read content from file").option("--status <status>", "New status").option("--parent <id>", 'New parent roadmap UUID, or the literal "null" to promote to top level').option("--starts-on <date>", 'New start date YYYY-MM-DD, or the literal "null" to clear').option("--ends-on <date>", 'New end date YYYY-MM-DD, or the literal "null" to clear').action(async (slug, id, opts) => {
1444
1451
  const body = {};
1445
1452
  if (opts.title) body.title = opts.title;
1446
1453
  if (opts.file) body.content = readFileSync13(opts.file, "utf-8");
1447
1454
  else if (opts.content) body.content = opts.content;
1448
1455
  if (opts.status) body.status = opts.status;
1456
+ const nullable = (v) => v === void 0 ? void 0 : v === "null" ? null : v;
1457
+ if (opts.parent !== void 0) body.parent_roadmap_id = nullable(opts.parent);
1458
+ if (opts.startsOn !== void 0) body.starts_on = nullable(opts.startsOn);
1459
+ if (opts.endsOn !== void 0) body.ends_on = nullable(opts.endsOn);
1449
1460
  const res = await apiRequest(`/pebbles/${slug}/roadmaps/${id}`, {
1450
1461
  method: "PUT",
1451
1462
  body
@@ -2074,7 +2085,7 @@ Re-run \`odin pebble new ${name}\` after acting.
2074
2085
  const body = renderInitBetBody(slug, report);
2075
2086
  const bet = await apiRequest(`/pebbles/${slug}/bets`, {
2076
2087
  method: "POST",
2077
- body: { title: `Initialize ${slug}`, source: "odin-cli", content: body, status: "shaped" }
2088
+ body: { title: `Initialize ${slug}`, source: "odin-cli", content: body }
2078
2089
  });
2079
2090
  process.stdout.write(JSON.stringify(bet) + "\n");
2080
2091
  if (opts.run && bet.data?.id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pebblehouse/odin-cli",
3
- "version": "0.18.1",
3
+ "version": "0.18.3",
4
4
  "type": "module",
5
5
  "description": "CLI for Odin — the knowledge backbone for Pebble House",
6
6
  "bin": {