@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/bin.js
CHANGED
|
@@ -5931,13 +5931,14 @@ Usage:
|
|
|
5931
5931
|
odla-ai app owners add <email> [--email <odla-account>] [--json]
|
|
5932
5932
|
odla-ai app owners remove <email> [--email <odla-account>] [--json]
|
|
5933
5933
|
odla-ai pm <goal|task|decision|bug> list [--app <id>] [--status <s>] [--severity <s>] [--column <c>] [--q <text>] [--json]
|
|
5934
|
-
odla-ai pm <goal|task|decision|bug> add --app <id> --title <t> [--severity high|--column doing|--goal <id>|--body <text>|--proof <text>]
|
|
5934
|
+
odla-ai pm <goal|task|decision|bug> add --app <id> --title <t> [--severity high|--column doing|--goal <id>|--description <text>|--body <text>|--proof <text>]
|
|
5935
5935
|
odla-ai pm <goal|task|decision|bug> get <id> [--json]
|
|
5936
|
-
odla-ai pm <goal|task|decision|bug> set <id> [--status <s>|--column <c>|--assignee <id>|--no-assignee|--goal <id>]
|
|
5937
|
-
odla-ai pm <goal|task|decision|bug> done <id>
|
|
5936
|
+
odla-ai pm <goal|task|decision|bug> set <id> [--status <s>|--column <c>|--assignee <id>|--no-assignee|--goal <id>|--decision <id>]
|
|
5937
|
+
odla-ai pm <goal|task|decision|bug> done <id> [--decision <accepted-decision-id>]
|
|
5938
5938
|
odla-ai pm <goal|task|decision|bug> comment <id> --body "..."
|
|
5939
5939
|
odla-ai pm <goal|task|decision|bug> comments <id> [--json]
|
|
5940
5940
|
odla-ai pm <goal|task|decision|bug> rm <id>
|
|
5941
|
+
odla-ai pm handoff --app <id> [--json]
|
|
5941
5942
|
odla-ai whoami [--json]
|
|
5942
5943
|
odla-ai runbook ask "<question>" [--app <id>] [--all] [--json]
|
|
5943
5944
|
odla-ai runbook search "<question>" [--app <id>] [--all] [--limit <n>] [--json]
|
|
@@ -6784,7 +6785,10 @@ var COMMAND_SURFACE = {
|
|
|
6784
6785
|
doctor: {},
|
|
6785
6786
|
help: {},
|
|
6786
6787
|
init: {},
|
|
6787
|
-
pm:
|
|
6788
|
+
pm: {
|
|
6789
|
+
...PM_ENTITIES,
|
|
6790
|
+
handoff: {}
|
|
6791
|
+
},
|
|
6788
6792
|
provision: {},
|
|
6789
6793
|
runbook: {
|
|
6790
6794
|
ask: {},
|
|
@@ -7982,6 +7986,7 @@ var FIELD_MAP = {
|
|
|
7982
7986
|
column: { key: "column" },
|
|
7983
7987
|
rank: { key: "rank", num: true },
|
|
7984
7988
|
goal: { key: "goalId" },
|
|
7989
|
+
decision: { key: "decisionId" },
|
|
7985
7990
|
assignee: { key: "assigneeId" },
|
|
7986
7991
|
due: { key: "dueAt", num: true },
|
|
7987
7992
|
proof: { key: "proof" },
|
|
@@ -8020,6 +8025,14 @@ function collectFields(parsed, allowClear) {
|
|
|
8020
8025
|
}
|
|
8021
8026
|
return out;
|
|
8022
8027
|
}
|
|
8028
|
+
function collectEntityFields(entity, parsed, allowClear) {
|
|
8029
|
+
const fields = collectFields(parsed, allowClear);
|
|
8030
|
+
if ((entity === "task" || entity === "bug") && fields.body !== void 0) {
|
|
8031
|
+
if (fields.description === void 0) fields.description = fields.body;
|
|
8032
|
+
delete fields.body;
|
|
8033
|
+
}
|
|
8034
|
+
return fields;
|
|
8035
|
+
}
|
|
8023
8036
|
function statusCol(entity, r) {
|
|
8024
8037
|
if (entity === "bug") return `${r.status ?? ""}/${r.severity ?? ""}`;
|
|
8025
8038
|
if (entity === "task") return String(r.column ?? "");
|
|
@@ -8034,7 +8047,14 @@ function emit(ctx, value, human) {
|
|
|
8034
8047
|
}
|
|
8035
8048
|
async function pmList(ctx, entity, parsed) {
|
|
8036
8049
|
const q = new URLSearchParams();
|
|
8037
|
-
const filters = {
|
|
8050
|
+
const filters = {
|
|
8051
|
+
status: "status",
|
|
8052
|
+
severity: "severity",
|
|
8053
|
+
column: "column",
|
|
8054
|
+
goal: "goalId",
|
|
8055
|
+
assignee: "assigneeId",
|
|
8056
|
+
decision: "decisionId"
|
|
8057
|
+
};
|
|
8038
8058
|
const app = stringOpt(parsed.options.app);
|
|
8039
8059
|
if (app) q.set("app", app);
|
|
8040
8060
|
for (const [flag, param] of Object.entries(filters)) {
|
|
@@ -8056,8 +8076,10 @@ async function pmList(ctx, entity, parsed) {
|
|
|
8056
8076
|
async function pmAdd(ctx, entity, parsed) {
|
|
8057
8077
|
const appId = stringOpt(parsed.options.app);
|
|
8058
8078
|
if (!appId) throw new Error("pm add needs --app <appId>");
|
|
8059
|
-
const input =
|
|
8079
|
+
const input = collectEntityFields(entity, parsed, false);
|
|
8060
8080
|
if (!input.title) throw new Error("pm add needs --title <title>");
|
|
8081
|
+
if (entity === "bug" && !input.description)
|
|
8082
|
+
throw new Error("pm bug add needs --description <context> (or --body <context>)");
|
|
8061
8083
|
const res = await pmRequest(ctx, "POST", `/${entity}`, { appId, input });
|
|
8062
8084
|
emit(ctx, res, () => ctx.out.log(`created ${entity} ${res.id}`));
|
|
8063
8085
|
}
|
|
@@ -8066,16 +8088,71 @@ async function pmGet(ctx, entity, id) {
|
|
|
8066
8088
|
emit(ctx, record5, () => printRecord(ctx, entity, record5));
|
|
8067
8089
|
}
|
|
8068
8090
|
async function pmSet(ctx, entity, id, parsed) {
|
|
8069
|
-
const patch2 =
|
|
8091
|
+
const patch2 = collectEntityFields(entity, parsed, true);
|
|
8070
8092
|
if (Object.keys(patch2).length === 0)
|
|
8071
8093
|
throw new Error("pm set needs at least one field flag (e.g. --status doing, --assignee me, --no-assignee)");
|
|
8072
8094
|
const res = await pmRequest(ctx, "PATCH", `/${entity}/${encodeURIComponent(id)}`, { patch: patch2 });
|
|
8073
8095
|
emit(ctx, res, () => ctx.out.log(res.record ? `${res.record.id} [${statusCol(entity, res.record)}] ${res.record.appId} ${res.record.title ?? ""}` : `updated ${entity} ${id}`));
|
|
8074
8096
|
}
|
|
8075
|
-
async function pmDone(ctx, entity, id) {
|
|
8076
|
-
const
|
|
8097
|
+
async function pmDone(ctx, entity, id, parsed) {
|
|
8098
|
+
const decisionId = stringOpt(parsed.options.decision);
|
|
8099
|
+
if (decisionId && entity !== "bug") throw new Error("--decision is only valid when completing a bug");
|
|
8100
|
+
const patch2 = { ...DONE[entity], ...decisionId ? { decisionId } : {} };
|
|
8101
|
+
const res = await pmRequest(ctx, "PATCH", `/${entity}/${encodeURIComponent(id)}`, { patch: patch2 });
|
|
8077
8102
|
emit(ctx, res, () => ctx.out.log(`${entity} ${id} \u2192 done`));
|
|
8078
8103
|
}
|
|
8104
|
+
async function allRecords(ctx, entity, appId) {
|
|
8105
|
+
const records = [];
|
|
8106
|
+
for (; ; ) {
|
|
8107
|
+
const q = new URLSearchParams({
|
|
8108
|
+
app: appId,
|
|
8109
|
+
limit: "100",
|
|
8110
|
+
offset: String(records.length)
|
|
8111
|
+
});
|
|
8112
|
+
const page = await pmRequest(ctx, "GET", `/${entity}?${q}`);
|
|
8113
|
+
records.push(...page.records);
|
|
8114
|
+
if (records.length >= page.total || page.records.length === 0) return records;
|
|
8115
|
+
}
|
|
8116
|
+
}
|
|
8117
|
+
async function pmHandoff(ctx, parsed) {
|
|
8118
|
+
const appId = stringOpt(parsed.options.app);
|
|
8119
|
+
if (!appId) throw new Error("pm handoff needs --app <appId>");
|
|
8120
|
+
const [goals, tasks, bugs] = await Promise.all([
|
|
8121
|
+
allRecords(ctx, "goal", appId),
|
|
8122
|
+
allRecords(ctx, "task", appId),
|
|
8123
|
+
allRecords(ctx, "bug", appId)
|
|
8124
|
+
]);
|
|
8125
|
+
const handoff = {
|
|
8126
|
+
appId,
|
|
8127
|
+
unmetGoals: goals.filter((record5) => record5.status !== "met"),
|
|
8128
|
+
activeTasks: tasks.filter((record5) => record5.column !== "done"),
|
|
8129
|
+
openBugs: bugs.filter((record5) => record5.status !== "fixed" && record5.status !== "wontfix")
|
|
8130
|
+
};
|
|
8131
|
+
const result = {
|
|
8132
|
+
...handoff,
|
|
8133
|
+
clean: !handoff.unmetGoals.length && !handoff.activeTasks.length && !handoff.openBugs.length
|
|
8134
|
+
};
|
|
8135
|
+
emit(ctx, result, () => {
|
|
8136
|
+
if (result.clean) {
|
|
8137
|
+
ctx.out.log(`${appId}: no unresolved PM work`);
|
|
8138
|
+
return;
|
|
8139
|
+
}
|
|
8140
|
+
ctx.out.log(`${appId}: authoritative PM handoff`);
|
|
8141
|
+
for (const [label, records] of [
|
|
8142
|
+
["unmet goals", result.unmetGoals],
|
|
8143
|
+
["active tasks", result.activeTasks],
|
|
8144
|
+
["open bugs", result.openBugs]
|
|
8145
|
+
]) {
|
|
8146
|
+
ctx.out.log(`${label}:`);
|
|
8147
|
+
if (!records.length) ctx.out.log("- (none)");
|
|
8148
|
+
else for (const record5 of records) printRecord(
|
|
8149
|
+
ctx,
|
|
8150
|
+
label === "unmet goals" ? "goal" : label === "active tasks" ? "task" : "bug",
|
|
8151
|
+
record5
|
|
8152
|
+
);
|
|
8153
|
+
}
|
|
8154
|
+
});
|
|
8155
|
+
}
|
|
8079
8156
|
async function pmComment(ctx, entity, id, parsed) {
|
|
8080
8157
|
const body = stringOpt(parsed.options.body);
|
|
8081
8158
|
if (!body) throw new Error('pm comment needs --body "..."');
|
|
@@ -8126,6 +8203,7 @@ var ALLOWED = [
|
|
|
8126
8203
|
"target",
|
|
8127
8204
|
"description",
|
|
8128
8205
|
"desc",
|
|
8206
|
+
"decision",
|
|
8129
8207
|
"limit",
|
|
8130
8208
|
"offset",
|
|
8131
8209
|
"q"
|
|
@@ -8148,6 +8226,10 @@ async function buildContext(parsed, deps) {
|
|
|
8148
8226
|
}
|
|
8149
8227
|
async function pmCommand(parsed, deps = {}) {
|
|
8150
8228
|
const word = parsed.positionals[1] ?? "";
|
|
8229
|
+
if (word === "handoff") {
|
|
8230
|
+
assertArgs(parsed, ALLOWED, 2);
|
|
8231
|
+
return pmHandoff(await buildContext(parsed, deps), parsed);
|
|
8232
|
+
}
|
|
8151
8233
|
const entity = ALIASES[word];
|
|
8152
8234
|
if (!entity) throw new Error(`unknown pm entity "${word}". Try "odla-ai pm bug list" (goal|task|decision|bug).`);
|
|
8153
8235
|
const action = parsed.positionals[2] ?? "list";
|
|
@@ -8168,7 +8250,7 @@ async function pmCommand(parsed, deps = {}) {
|
|
|
8168
8250
|
case "move":
|
|
8169
8251
|
return pmSet(ctx, entity, requireId(id, action), parsed);
|
|
8170
8252
|
case "done":
|
|
8171
|
-
return pmDone(ctx, entity, requireId(id, action));
|
|
8253
|
+
return pmDone(ctx, entity, requireId(id, action), parsed);
|
|
8172
8254
|
case "comment":
|
|
8173
8255
|
return pmComment(ctx, entity, requireId(id, action), parsed);
|
|
8174
8256
|
case "comments":
|
|
@@ -9749,4 +9831,4 @@ export {
|
|
|
9749
9831
|
exitCodeFor,
|
|
9750
9832
|
runCli
|
|
9751
9833
|
};
|
|
9752
|
-
//# sourceMappingURL=chunk-
|
|
9834
|
+
//# sourceMappingURL=chunk-7P7MI4WX.js.map
|