@odla-ai/cli 0.23.0 → 0.24.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 +8 -0
- package/dist/bin.cjs +92 -10
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-RZDRUVBT.js → chunk-7P7MI4WX.js} +93 -11
- package/dist/chunk-7P7MI4WX.js.map +1 -0
- package/dist/index.cjs +92 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-RZDRUVBT.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -6486,13 +6486,14 @@ Usage:
|
|
|
6486
6486
|
odla-ai app owners add <email> [--email <odla-account>] [--json]
|
|
6487
6487
|
odla-ai app owners remove <email> [--email <odla-account>] [--json]
|
|
6488
6488
|
odla-ai pm <goal|task|decision|bug> list [--app <id>] [--status <s>] [--severity <s>] [--column <c>] [--q <text>] [--json]
|
|
6489
|
-
odla-ai pm <goal|task|decision|bug> add --app <id> --title <t> [--severity high|--column doing|--goal <id>|--body <text>|--proof <text>]
|
|
6489
|
+
odla-ai pm <goal|task|decision|bug> add --app <id> --title <t> [--severity high|--column doing|--goal <id>|--description <text>|--body <text>|--proof <text>]
|
|
6490
6490
|
odla-ai pm <goal|task|decision|bug> get <id> [--json]
|
|
6491
|
-
odla-ai pm <goal|task|decision|bug> set <id> [--status <s>|--column <c>|--assignee <id>|--no-assignee|--goal <id>]
|
|
6492
|
-
odla-ai pm <goal|task|decision|bug> done <id>
|
|
6491
|
+
odla-ai pm <goal|task|decision|bug> set <id> [--status <s>|--column <c>|--assignee <id>|--no-assignee|--goal <id>|--decision <id>]
|
|
6492
|
+
odla-ai pm <goal|task|decision|bug> done <id> [--decision <accepted-decision-id>]
|
|
6493
6493
|
odla-ai pm <goal|task|decision|bug> comment <id> --body "..."
|
|
6494
6494
|
odla-ai pm <goal|task|decision|bug> comments <id> [--json]
|
|
6495
6495
|
odla-ai pm <goal|task|decision|bug> rm <id>
|
|
6496
|
+
odla-ai pm handoff --app <id> [--json]
|
|
6496
6497
|
odla-ai whoami [--json]
|
|
6497
6498
|
odla-ai runbook ask "<question>" [--app <id>] [--all] [--json]
|
|
6498
6499
|
odla-ai runbook search "<question>" [--app <id>] [--all] [--limit <n>] [--json]
|
|
@@ -7251,6 +7252,7 @@ var FIELD_MAP = {
|
|
|
7251
7252
|
column: { key: "column" },
|
|
7252
7253
|
rank: { key: "rank", num: true },
|
|
7253
7254
|
goal: { key: "goalId" },
|
|
7255
|
+
decision: { key: "decisionId" },
|
|
7254
7256
|
assignee: { key: "assigneeId" },
|
|
7255
7257
|
due: { key: "dueAt", num: true },
|
|
7256
7258
|
proof: { key: "proof" },
|
|
@@ -7289,6 +7291,14 @@ function collectFields(parsed, allowClear) {
|
|
|
7289
7291
|
}
|
|
7290
7292
|
return out;
|
|
7291
7293
|
}
|
|
7294
|
+
function collectEntityFields(entity, parsed, allowClear) {
|
|
7295
|
+
const fields = collectFields(parsed, allowClear);
|
|
7296
|
+
if ((entity === "task" || entity === "bug") && fields.body !== void 0) {
|
|
7297
|
+
if (fields.description === void 0) fields.description = fields.body;
|
|
7298
|
+
delete fields.body;
|
|
7299
|
+
}
|
|
7300
|
+
return fields;
|
|
7301
|
+
}
|
|
7292
7302
|
function statusCol(entity, r) {
|
|
7293
7303
|
if (entity === "bug") return `${r.status ?? ""}/${r.severity ?? ""}`;
|
|
7294
7304
|
if (entity === "task") return String(r.column ?? "");
|
|
@@ -7303,7 +7313,14 @@ function emit(ctx, value, human) {
|
|
|
7303
7313
|
}
|
|
7304
7314
|
async function pmList(ctx, entity, parsed) {
|
|
7305
7315
|
const q = new URLSearchParams();
|
|
7306
|
-
const filters = {
|
|
7316
|
+
const filters = {
|
|
7317
|
+
status: "status",
|
|
7318
|
+
severity: "severity",
|
|
7319
|
+
column: "column",
|
|
7320
|
+
goal: "goalId",
|
|
7321
|
+
assignee: "assigneeId",
|
|
7322
|
+
decision: "decisionId"
|
|
7323
|
+
};
|
|
7307
7324
|
const app = stringOpt(parsed.options.app);
|
|
7308
7325
|
if (app) q.set("app", app);
|
|
7309
7326
|
for (const [flag, param] of Object.entries(filters)) {
|
|
@@ -7325,8 +7342,10 @@ async function pmList(ctx, entity, parsed) {
|
|
|
7325
7342
|
async function pmAdd(ctx, entity, parsed) {
|
|
7326
7343
|
const appId = stringOpt(parsed.options.app);
|
|
7327
7344
|
if (!appId) throw new Error("pm add needs --app <appId>");
|
|
7328
|
-
const input =
|
|
7345
|
+
const input = collectEntityFields(entity, parsed, false);
|
|
7329
7346
|
if (!input.title) throw new Error("pm add needs --title <title>");
|
|
7347
|
+
if (entity === "bug" && !input.description)
|
|
7348
|
+
throw new Error("pm bug add needs --description <context> (or --body <context>)");
|
|
7330
7349
|
const res = await pmRequest(ctx, "POST", `/${entity}`, { appId, input });
|
|
7331
7350
|
emit(ctx, res, () => ctx.out.log(`created ${entity} ${res.id}`));
|
|
7332
7351
|
}
|
|
@@ -7335,16 +7354,71 @@ async function pmGet(ctx, entity, id) {
|
|
|
7335
7354
|
emit(ctx, record5, () => printRecord(ctx, entity, record5));
|
|
7336
7355
|
}
|
|
7337
7356
|
async function pmSet(ctx, entity, id, parsed) {
|
|
7338
|
-
const patch2 =
|
|
7357
|
+
const patch2 = collectEntityFields(entity, parsed, true);
|
|
7339
7358
|
if (Object.keys(patch2).length === 0)
|
|
7340
7359
|
throw new Error("pm set needs at least one field flag (e.g. --status doing, --assignee me, --no-assignee)");
|
|
7341
7360
|
const res = await pmRequest(ctx, "PATCH", `/${entity}/${encodeURIComponent(id)}`, { patch: patch2 });
|
|
7342
7361
|
emit(ctx, res, () => ctx.out.log(res.record ? `${res.record.id} [${statusCol(entity, res.record)}] ${res.record.appId} ${res.record.title ?? ""}` : `updated ${entity} ${id}`));
|
|
7343
7362
|
}
|
|
7344
|
-
async function pmDone(ctx, entity, id) {
|
|
7345
|
-
const
|
|
7363
|
+
async function pmDone(ctx, entity, id, parsed) {
|
|
7364
|
+
const decisionId = stringOpt(parsed.options.decision);
|
|
7365
|
+
if (decisionId && entity !== "bug") throw new Error("--decision is only valid when completing a bug");
|
|
7366
|
+
const patch2 = { ...DONE[entity], ...decisionId ? { decisionId } : {} };
|
|
7367
|
+
const res = await pmRequest(ctx, "PATCH", `/${entity}/${encodeURIComponent(id)}`, { patch: patch2 });
|
|
7346
7368
|
emit(ctx, res, () => ctx.out.log(`${entity} ${id} \u2192 done`));
|
|
7347
7369
|
}
|
|
7370
|
+
async function allRecords(ctx, entity, appId) {
|
|
7371
|
+
const records = [];
|
|
7372
|
+
for (; ; ) {
|
|
7373
|
+
const q = new URLSearchParams({
|
|
7374
|
+
app: appId,
|
|
7375
|
+
limit: "100",
|
|
7376
|
+
offset: String(records.length)
|
|
7377
|
+
});
|
|
7378
|
+
const page = await pmRequest(ctx, "GET", `/${entity}?${q}`);
|
|
7379
|
+
records.push(...page.records);
|
|
7380
|
+
if (records.length >= page.total || page.records.length === 0) return records;
|
|
7381
|
+
}
|
|
7382
|
+
}
|
|
7383
|
+
async function pmHandoff(ctx, parsed) {
|
|
7384
|
+
const appId = stringOpt(parsed.options.app);
|
|
7385
|
+
if (!appId) throw new Error("pm handoff needs --app <appId>");
|
|
7386
|
+
const [goals, tasks, bugs] = await Promise.all([
|
|
7387
|
+
allRecords(ctx, "goal", appId),
|
|
7388
|
+
allRecords(ctx, "task", appId),
|
|
7389
|
+
allRecords(ctx, "bug", appId)
|
|
7390
|
+
]);
|
|
7391
|
+
const handoff = {
|
|
7392
|
+
appId,
|
|
7393
|
+
unmetGoals: goals.filter((record5) => record5.status !== "met"),
|
|
7394
|
+
activeTasks: tasks.filter((record5) => record5.column !== "done"),
|
|
7395
|
+
openBugs: bugs.filter((record5) => record5.status !== "fixed" && record5.status !== "wontfix")
|
|
7396
|
+
};
|
|
7397
|
+
const result = {
|
|
7398
|
+
...handoff,
|
|
7399
|
+
clean: !handoff.unmetGoals.length && !handoff.activeTasks.length && !handoff.openBugs.length
|
|
7400
|
+
};
|
|
7401
|
+
emit(ctx, result, () => {
|
|
7402
|
+
if (result.clean) {
|
|
7403
|
+
ctx.out.log(`${appId}: no unresolved PM work`);
|
|
7404
|
+
return;
|
|
7405
|
+
}
|
|
7406
|
+
ctx.out.log(`${appId}: authoritative PM handoff`);
|
|
7407
|
+
for (const [label, records] of [
|
|
7408
|
+
["unmet goals", result.unmetGoals],
|
|
7409
|
+
["active tasks", result.activeTasks],
|
|
7410
|
+
["open bugs", result.openBugs]
|
|
7411
|
+
]) {
|
|
7412
|
+
ctx.out.log(`${label}:`);
|
|
7413
|
+
if (!records.length) ctx.out.log("- (none)");
|
|
7414
|
+
else for (const record5 of records) printRecord(
|
|
7415
|
+
ctx,
|
|
7416
|
+
label === "unmet goals" ? "goal" : label === "active tasks" ? "task" : "bug",
|
|
7417
|
+
record5
|
|
7418
|
+
);
|
|
7419
|
+
}
|
|
7420
|
+
});
|
|
7421
|
+
}
|
|
7348
7422
|
async function pmComment(ctx, entity, id, parsed) {
|
|
7349
7423
|
const body = stringOpt(parsed.options.body);
|
|
7350
7424
|
if (!body) throw new Error('pm comment needs --body "..."');
|
|
@@ -7395,6 +7469,7 @@ var ALLOWED = [
|
|
|
7395
7469
|
"target",
|
|
7396
7470
|
"description",
|
|
7397
7471
|
"desc",
|
|
7472
|
+
"decision",
|
|
7398
7473
|
"limit",
|
|
7399
7474
|
"offset",
|
|
7400
7475
|
"q"
|
|
@@ -7417,6 +7492,10 @@ async function buildContext(parsed, deps) {
|
|
|
7417
7492
|
}
|
|
7418
7493
|
async function pmCommand(parsed, deps = {}) {
|
|
7419
7494
|
const word = parsed.positionals[1] ?? "";
|
|
7495
|
+
if (word === "handoff") {
|
|
7496
|
+
assertArgs(parsed, ALLOWED, 2);
|
|
7497
|
+
return pmHandoff(await buildContext(parsed, deps), parsed);
|
|
7498
|
+
}
|
|
7420
7499
|
const entity = ALIASES[word];
|
|
7421
7500
|
if (!entity) throw new Error(`unknown pm entity "${word}". Try "odla-ai pm bug list" (goal|task|decision|bug).`);
|
|
7422
7501
|
const action = parsed.positionals[2] ?? "list";
|
|
@@ -7437,7 +7516,7 @@ async function pmCommand(parsed, deps = {}) {
|
|
|
7437
7516
|
case "move":
|
|
7438
7517
|
return pmSet(ctx, entity, requireId(id, action), parsed);
|
|
7439
7518
|
case "done":
|
|
7440
|
-
return pmDone(ctx, entity, requireId(id, action));
|
|
7519
|
+
return pmDone(ctx, entity, requireId(id, action), parsed);
|
|
7441
7520
|
case "comment":
|
|
7442
7521
|
return pmComment(ctx, entity, requireId(id, action), parsed);
|
|
7443
7522
|
case "comments":
|
|
@@ -7913,7 +7992,10 @@ var COMMAND_SURFACE = {
|
|
|
7913
7992
|
doctor: {},
|
|
7914
7993
|
help: {},
|
|
7915
7994
|
init: {},
|
|
7916
|
-
pm:
|
|
7995
|
+
pm: {
|
|
7996
|
+
...PM_ENTITIES,
|
|
7997
|
+
handoff: {}
|
|
7998
|
+
},
|
|
7917
7999
|
provision: {},
|
|
7918
8000
|
runbook: {
|
|
7919
8001
|
ask: {},
|