@hasna/todos 0.15.4 → 0.15.6
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/dist/cli/commands/delegate.d.ts +51 -0
- package/dist/cli/commands/delegate.d.ts.map +1 -0
- package/dist/cli/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/index.js +723 -229
- package/dist/cli/stage-a.d.ts.map +1 -1
- package/dist/contracts.js +13 -1
- package/dist/db/task-crud.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/lib/comment-cursor.d.ts +40 -0
- package/dist/lib/comment-cursor.d.ts.map +1 -0
- package/dist/lib/delegation-brief.d.ts +31 -0
- package/dist/lib/delegation-brief.d.ts.map +1 -0
- package/dist/lib/delegation-policy.d.ts +32 -0
- package/dist/lib/delegation-policy.d.ts.map +1 -0
- package/dist/lib/delegation-record.d.ts +50 -0
- package/dist/lib/delegation-record.d.ts.map +1 -0
- package/dist/lib/delegation-verify.d.ts +57 -0
- package/dist/lib/delegation-verify.d.ts.map +1 -0
- package/dist/mcp/index.js +36 -21
- package/dist/mcp.js +1 -1
- package/dist/registry.js +13 -1
- package/dist/release-provenance.json +5 -5
- package/dist/server/index.js +36 -21
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage.js +12 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2123,7 +2123,7 @@ var package_default;
|
|
|
2123
2123
|
var init_package = __esm(() => {
|
|
2124
2124
|
package_default = {
|
|
2125
2125
|
name: "@hasna/todos",
|
|
2126
|
-
version: "0.15.
|
|
2126
|
+
version: "0.15.6",
|
|
2127
2127
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
2128
2128
|
type: "module",
|
|
2129
2129
|
main: "dist/index.js",
|
|
@@ -6646,6 +6646,7 @@ var init_stage_a = __esm(() => {
|
|
|
6646
6646
|
"count",
|
|
6647
6647
|
"dashboard",
|
|
6648
6648
|
"dedupe",
|
|
6649
|
+
"delegate",
|
|
6649
6650
|
"delete",
|
|
6650
6651
|
"deps",
|
|
6651
6652
|
"dispatch",
|
|
@@ -6832,6 +6833,7 @@ var init_stage_a = __esm(() => {
|
|
|
6832
6833
|
"claim",
|
|
6833
6834
|
"comment",
|
|
6834
6835
|
"count",
|
|
6836
|
+
"delegate",
|
|
6835
6837
|
"delete",
|
|
6836
6838
|
"deps",
|
|
6837
6839
|
"doctor",
|
|
@@ -16243,6 +16245,18 @@ function updateTask(id, input, db) {
|
|
|
16243
16245
|
sets.push("assigned_to = ?");
|
|
16244
16246
|
params.push(input.assigned_to);
|
|
16245
16247
|
}
|
|
16248
|
+
if (input.assigned_by !== undefined) {
|
|
16249
|
+
sets.push("assigned_by = ?");
|
|
16250
|
+
params.push(input.assigned_by);
|
|
16251
|
+
}
|
|
16252
|
+
if (input.delegated_from !== undefined) {
|
|
16253
|
+
sets.push("delegated_from = ?");
|
|
16254
|
+
params.push(input.delegated_from);
|
|
16255
|
+
}
|
|
16256
|
+
if (input.delegation_depth !== undefined) {
|
|
16257
|
+
sets.push("delegation_depth = ?");
|
|
16258
|
+
params.push(input.delegation_depth);
|
|
16259
|
+
}
|
|
16246
16260
|
if (input.working_dir !== undefined) {
|
|
16247
16261
|
sets.push("working_dir = ?");
|
|
16248
16262
|
params.push(input.working_dir);
|
|
@@ -19317,6 +19331,45 @@ var init_tasks = __esm(() => {
|
|
|
19317
19331
|
init_calendar();
|
|
19318
19332
|
});
|
|
19319
19333
|
|
|
19334
|
+
// src/lib/comment-cursor.ts
|
|
19335
|
+
function encodeCommentCursor(comment) {
|
|
19336
|
+
return Buffer.from(JSON.stringify({ created_at: comment.created_at, id: comment.id }), "utf8").toString("base64url");
|
|
19337
|
+
}
|
|
19338
|
+
function decodeCommentCursor(value) {
|
|
19339
|
+
if (value.length > MAX_COMMENT_CURSOR_LENGTH)
|
|
19340
|
+
throw new Error("invalid comment cursor");
|
|
19341
|
+
let parsed;
|
|
19342
|
+
try {
|
|
19343
|
+
parsed = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
19344
|
+
} catch {
|
|
19345
|
+
throw new Error("invalid comment cursor");
|
|
19346
|
+
}
|
|
19347
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
19348
|
+
throw new Error("invalid comment cursor");
|
|
19349
|
+
const cursor = parsed;
|
|
19350
|
+
if (typeof cursor["created_at"] !== "string" || cursor["created_at"].length > 64 || !Number.isFinite(Date.parse(cursor["created_at"])) || typeof cursor["id"] !== "string" || !cursor["id"] || cursor["id"].length > 256) {
|
|
19351
|
+
throw new Error("invalid comment cursor");
|
|
19352
|
+
}
|
|
19353
|
+
return { created_at: cursor["created_at"], id: cursor["id"] };
|
|
19354
|
+
}
|
|
19355
|
+
function isStrictlyOlder(comment, before) {
|
|
19356
|
+
return comment.created_at < before.created_at || comment.created_at === before.created_at && comment.id < before.id;
|
|
19357
|
+
}
|
|
19358
|
+
function pageComments(all, options) {
|
|
19359
|
+
const ascending = [...all].sort((left, right) => left.created_at.localeCompare(right.created_at) || left.id.localeCompare(right.id));
|
|
19360
|
+
const scoped = options.before ? ascending.filter((comment) => isStrictlyOlder(comment, options.before)) : ascending;
|
|
19361
|
+
const comments = scoped.slice(-options.limit);
|
|
19362
|
+
const hasMore = scoped.length > comments.length;
|
|
19363
|
+
return {
|
|
19364
|
+
comments,
|
|
19365
|
+
count: comments.length,
|
|
19366
|
+
has_more: hasMore,
|
|
19367
|
+
next_cursor: hasMore && comments[0] ? encodeCommentCursor(comments[0]) : null,
|
|
19368
|
+
limit: options.limit
|
|
19369
|
+
};
|
|
19370
|
+
}
|
|
19371
|
+
var MAX_COMMENT_CURSOR_LENGTH = 1024;
|
|
19372
|
+
|
|
19320
19373
|
// src/lib/bulk-tags.ts
|
|
19321
19374
|
function parseTagList(raw) {
|
|
19322
19375
|
if (!raw)
|
|
@@ -20551,6 +20604,53 @@ function parseIntOption(value, flag) {
|
|
|
20551
20604
|
}
|
|
20552
20605
|
return n;
|
|
20553
20606
|
}
|
|
20607
|
+
function commentPageOptions(opts) {
|
|
20608
|
+
const requested = opts.commentsLimit !== undefined || opts.commentsCursor !== undefined;
|
|
20609
|
+
let limit = DEFAULT_CLI_COMMENT_PAGE;
|
|
20610
|
+
if (opts.commentsLimit !== undefined) {
|
|
20611
|
+
const parsed = Number(opts.commentsLimit);
|
|
20612
|
+
if (!Number.isSafeInteger(parsed) || parsed < 1 || parsed > MAX_CLI_COMMENT_PAGE) {
|
|
20613
|
+
handleError(new Error(`--comments-limit must be an integer between 1 and ${MAX_CLI_COMMENT_PAGE}`));
|
|
20614
|
+
}
|
|
20615
|
+
limit = parsed;
|
|
20616
|
+
}
|
|
20617
|
+
let before;
|
|
20618
|
+
if (opts.commentsCursor !== undefined) {
|
|
20619
|
+
try {
|
|
20620
|
+
before = decodeCommentCursor(opts.commentsCursor);
|
|
20621
|
+
} catch {
|
|
20622
|
+
handleError(new Error("--comments-cursor is not a valid comment cursor; pass the value from comments_page.next_cursor"));
|
|
20623
|
+
}
|
|
20624
|
+
}
|
|
20625
|
+
return {
|
|
20626
|
+
request: {
|
|
20627
|
+
...opts.commentsLimit !== undefined ? { limit } : {},
|
|
20628
|
+
...opts.commentsCursor !== undefined ? { cursor: opts.commentsCursor } : {}
|
|
20629
|
+
},
|
|
20630
|
+
requested,
|
|
20631
|
+
limit,
|
|
20632
|
+
...before ? { before } : {}
|
|
20633
|
+
};
|
|
20634
|
+
}
|
|
20635
|
+
function applyLocalCommentPage(task, page) {
|
|
20636
|
+
if (!task || !page.requested)
|
|
20637
|
+
return task;
|
|
20638
|
+
const paged = pageComments(task.comments, {
|
|
20639
|
+
limit: page.limit,
|
|
20640
|
+
...page.before ? { before: page.before } : {}
|
|
20641
|
+
});
|
|
20642
|
+
return {
|
|
20643
|
+
...task,
|
|
20644
|
+
comments: paged.comments,
|
|
20645
|
+
comments_page: {
|
|
20646
|
+
count: paged.count,
|
|
20647
|
+
limit: paged.limit,
|
|
20648
|
+
has_more: paged.has_more,
|
|
20649
|
+
next_cursor: paged.next_cursor,
|
|
20650
|
+
pagination_supported: true
|
|
20651
|
+
}
|
|
20652
|
+
};
|
|
20653
|
+
}
|
|
20554
20654
|
function isPathLike(input) {
|
|
20555
20655
|
return input.startsWith(".") || input.includes("/") || input.includes("\\");
|
|
20556
20656
|
}
|
|
@@ -21147,13 +21247,14 @@ function registerTaskCommands(program2) {
|
|
|
21147
21247
|
console.log(parts.join(" "));
|
|
21148
21248
|
}
|
|
21149
21249
|
});
|
|
21150
|
-
program2.command("show <id>").description("Show full task details").action(async (id) => {
|
|
21250
|
+
program2.command("show <id>").description("Show full task details").option("--comments-limit <n>", `Comments per page, 1-${MAX_CLI_COMMENT_PAGE} (default ${DEFAULT_CLI_COMMENT_PAGE})`).option("--comments-cursor <cursor>", "Read the next OLDER page; pass comments_page.next_cursor").action(async (id, opts) => {
|
|
21151
21251
|
const globalOpts = program2.opts();
|
|
21252
|
+
const page = commentPageOptions(opts);
|
|
21152
21253
|
const cloud = getTodosCloudClient();
|
|
21153
21254
|
let task2;
|
|
21154
21255
|
if (cloud) {
|
|
21155
21256
|
const remote = await cloudGetTask(cloud, await resolveTaskIdForCommand(id, cloud));
|
|
21156
|
-
const commentPage = remote ? await cloudListComments(cloud, remote.id) : null;
|
|
21257
|
+
const commentPage = remote ? await cloudListComments(cloud, remote.id, page.request) : null;
|
|
21157
21258
|
const relations = remote ? await cloudDetailRelations(cloud, remote.id) : null;
|
|
21158
21259
|
task2 = remote ? {
|
|
21159
21260
|
subtasks: [],
|
|
@@ -21173,7 +21274,7 @@ function registerTaskCommands(program2) {
|
|
|
21173
21274
|
} : null;
|
|
21174
21275
|
} else {
|
|
21175
21276
|
const resolvedId = resolveTaskId(id);
|
|
21176
|
-
task2 = getTaskWithRelations(resolvedId);
|
|
21277
|
+
task2 = applyLocalCommentPage(getTaskWithRelations(resolvedId), page);
|
|
21177
21278
|
}
|
|
21178
21279
|
if (!task2) {
|
|
21179
21280
|
handleError(new Error(`Task not found: ${id}`));
|
|
@@ -21264,8 +21365,9 @@ function registerTaskCommands(program2) {
|
|
|
21264
21365
|
}
|
|
21265
21366
|
}
|
|
21266
21367
|
});
|
|
21267
|
-
program2.command("inspect [id]").description("Full orientation for a task \u2014 details, description, dependencies, blocker, files, commits, comments. If no ID given, shows current in-progress task for --agent.").action(async (id) => {
|
|
21368
|
+
program2.command("inspect [id]").description("Full orientation for a task \u2014 details, description, dependencies, blocker, files, commits, comments. If no ID given, shows current in-progress task for --agent.").option("--comments-limit <n>", `Comments per page, 1-${MAX_CLI_COMMENT_PAGE} (default ${DEFAULT_CLI_COMMENT_PAGE})`).option("--comments-cursor <cursor>", "Read the next OLDER page; pass comments_page.next_cursor").action(async (id, opts) => {
|
|
21268
21369
|
const globalOpts = program2.opts();
|
|
21370
|
+
const page = commentPageOptions(opts);
|
|
21269
21371
|
const cloud = getTodosCloudClient();
|
|
21270
21372
|
let resolvedId = id ? await resolveTaskIdForCommand(id, cloud) : null;
|
|
21271
21373
|
if (!resolvedId && globalOpts.agent && !cloud) {
|
|
@@ -21285,7 +21387,7 @@ function registerTaskCommands(program2) {
|
|
|
21285
21387
|
let task2;
|
|
21286
21388
|
if (cloud) {
|
|
21287
21389
|
const remote = await cloudGetTask(cloud, resolvedId);
|
|
21288
|
-
const commentPage = remote ? await cloudListComments(cloud, remote.id) : null;
|
|
21390
|
+
const commentPage = remote ? await cloudListComments(cloud, remote.id, page.request) : null;
|
|
21289
21391
|
const relations = remote ? await cloudDetailRelations(cloud, remote.id) : null;
|
|
21290
21392
|
task2 = remote ? {
|
|
21291
21393
|
subtasks: [],
|
|
@@ -21305,7 +21407,7 @@ function registerTaskCommands(program2) {
|
|
|
21305
21407
|
}
|
|
21306
21408
|
} : null;
|
|
21307
21409
|
} else {
|
|
21308
|
-
task2 = getTaskWithRelations(resolvedId);
|
|
21410
|
+
task2 = applyLocalCommentPage(getTaskWithRelations(resolvedId), page);
|
|
21309
21411
|
}
|
|
21310
21412
|
if (!task2) {
|
|
21311
21413
|
handleError(new Error(`Task not found: ${id || resolvedId}`));
|
|
@@ -21981,7 +22083,7 @@ ${chalk3.cyan(sid)} ${statusColor(task2.status)} ${prioColor(task2.priority)} ${
|
|
|
21981
22083
|
}
|
|
21982
22084
|
});
|
|
21983
22085
|
}
|
|
21984
|
-
var DEFAULT_LIST_SCAN_LIMIT = 1e4;
|
|
22086
|
+
var DEFAULT_LIST_SCAN_LIMIT = 1e4, DEFAULT_CLI_COMMENT_PAGE = 100, MAX_CLI_COMMENT_PAGE = 500;
|
|
21985
22087
|
var init_task_commands = __esm(() => {
|
|
21986
22088
|
init_database();
|
|
21987
22089
|
init_projects();
|
|
@@ -38612,26 +38714,6 @@ function contextFromPrincipal(principal, body) {
|
|
|
38612
38714
|
function redactComment3(comment) {
|
|
38613
38715
|
return { ...comment, content: redactEvidenceText(comment.content) };
|
|
38614
38716
|
}
|
|
38615
|
-
function encodeCommentCursor(comment) {
|
|
38616
|
-
return Buffer.from(JSON.stringify({ created_at: comment.created_at, id: comment.id }), "utf8").toString("base64url");
|
|
38617
|
-
}
|
|
38618
|
-
function decodeCommentCursor(value) {
|
|
38619
|
-
if (value.length > 1024)
|
|
38620
|
-
throw new Error("invalid comment cursor");
|
|
38621
|
-
let parsed;
|
|
38622
|
-
try {
|
|
38623
|
-
parsed = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
38624
|
-
} catch {
|
|
38625
|
-
throw new Error("invalid comment cursor");
|
|
38626
|
-
}
|
|
38627
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
38628
|
-
throw new Error("invalid comment cursor");
|
|
38629
|
-
const cursor = parsed;
|
|
38630
|
-
if (typeof cursor["created_at"] !== "string" || cursor["created_at"].length > 64 || !Number.isFinite(Date.parse(cursor["created_at"])) || typeof cursor["id"] !== "string" || !cursor["id"] || cursor["id"].length > 256) {
|
|
38631
|
-
throw new Error("invalid comment cursor");
|
|
38632
|
-
}
|
|
38633
|
-
return { created_at: cursor["created_at"], id: cursor["id"] };
|
|
38634
|
-
}
|
|
38635
38717
|
function normalizeImportSnapshot(raw) {
|
|
38636
38718
|
const body = raw && typeof raw === "object" ? raw : {};
|
|
38637
38719
|
const arr = (v) => Array.isArray(v) ? v : [];
|
|
@@ -72729,16 +72811,425 @@ var init_dispatch3 = __esm(() => {
|
|
|
72729
72811
|
init_helpers();
|
|
72730
72812
|
});
|
|
72731
72813
|
|
|
72814
|
+
// src/lib/delegation-brief.ts
|
|
72815
|
+
import { createHash as createHash17 } from "crypto";
|
|
72816
|
+
function resolveDelegationBrief(input, sources) {
|
|
72817
|
+
const hasPath = typeof input.briefPath === "string" && input.briefPath.length > 0;
|
|
72818
|
+
const hasText = typeof input.briefText === "string" && input.briefText.length > 0;
|
|
72819
|
+
if (hasPath && hasText) {
|
|
72820
|
+
return {
|
|
72821
|
+
ok: false,
|
|
72822
|
+
reason: "conflict",
|
|
72823
|
+
message: "Pass either --brief <path> or --brief-text <text>, not both. " + "Two briefs means the worker is told two things and the [DISPATCH] record can only name one."
|
|
72824
|
+
};
|
|
72825
|
+
}
|
|
72826
|
+
if (!hasPath && !hasText) {
|
|
72827
|
+
return {
|
|
72828
|
+
ok: false,
|
|
72829
|
+
reason: "missing",
|
|
72830
|
+
message: "A delegation needs a brief: pass --brief <path> (or --brief - to read stdin), or --brief-text <text>. " + "A dispatched worker sees no announcement, no channel and no rule published after it starts, " + "so anything it is not told in the brief it will never learn."
|
|
72831
|
+
};
|
|
72832
|
+
}
|
|
72833
|
+
let text2;
|
|
72834
|
+
let source3;
|
|
72835
|
+
if (hasPath) {
|
|
72836
|
+
const path = input.briefPath;
|
|
72837
|
+
if (path === STDIN_SENTINEL) {
|
|
72838
|
+
try {
|
|
72839
|
+
text2 = sources.readStdin();
|
|
72840
|
+
} catch (error2) {
|
|
72841
|
+
return {
|
|
72842
|
+
ok: false,
|
|
72843
|
+
reason: "unreadable",
|
|
72844
|
+
message: `Could not read the brief from stdin: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
72845
|
+
};
|
|
72846
|
+
}
|
|
72847
|
+
source3 = "(stdin)";
|
|
72848
|
+
} else {
|
|
72849
|
+
try {
|
|
72850
|
+
text2 = sources.readFile(path);
|
|
72851
|
+
} catch (error2) {
|
|
72852
|
+
return {
|
|
72853
|
+
ok: false,
|
|
72854
|
+
reason: "unreadable",
|
|
72855
|
+
message: `Could not read the brief at ${path}: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
72856
|
+
};
|
|
72857
|
+
}
|
|
72858
|
+
source3 = path;
|
|
72859
|
+
}
|
|
72860
|
+
} else {
|
|
72861
|
+
text2 = input.briefText;
|
|
72862
|
+
source3 = "(--brief-text)";
|
|
72863
|
+
}
|
|
72864
|
+
if (text2.trim().length === 0) {
|
|
72865
|
+
return {
|
|
72866
|
+
ok: false,
|
|
72867
|
+
reason: "empty",
|
|
72868
|
+
message: `The brief at ${source3} is empty (it contains only whitespace). ` + "An empty brief is worse than no brief, because the dispatch record would claim the worker was briefed."
|
|
72869
|
+
};
|
|
72870
|
+
}
|
|
72871
|
+
return {
|
|
72872
|
+
ok: true,
|
|
72873
|
+
text: text2,
|
|
72874
|
+
source: source3,
|
|
72875
|
+
sha256: createHash17("sha256").update(text2, "utf8").digest("hex"),
|
|
72876
|
+
bytes: Buffer.byteLength(text2, "utf8")
|
|
72877
|
+
};
|
|
72878
|
+
}
|
|
72879
|
+
var STDIN_SENTINEL = "-";
|
|
72880
|
+
var init_delegation_brief = () => {};
|
|
72881
|
+
|
|
72882
|
+
// src/lib/delegation-policy.ts
|
|
72883
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
72884
|
+
import { homedir as homedir4 } from "os";
|
|
72885
|
+
import { join as join28 } from "path";
|
|
72886
|
+
function defaultDelegationEmbargoPath() {
|
|
72887
|
+
return process.env["TODOS_DELEGATION_EMBARGO_PATH"] || join28(homedir4(), ".hasna", "identities", "delegation-embargo.json");
|
|
72888
|
+
}
|
|
72889
|
+
function loadDelegationEmbargo(path = defaultDelegationEmbargoPath()) {
|
|
72890
|
+
try {
|
|
72891
|
+
const parsed = JSON.parse(readFileSync20(path, "utf8"));
|
|
72892
|
+
const entries = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.embargoed) ? parsed.embargoed : [];
|
|
72893
|
+
const names = new Set;
|
|
72894
|
+
for (const entry2 of entries) {
|
|
72895
|
+
const raw = typeof entry2 === "string" ? entry2 : entry2?.slug;
|
|
72896
|
+
if (typeof raw === "string" && raw.trim())
|
|
72897
|
+
names.add(normalizeAgentNameInput(raw));
|
|
72898
|
+
}
|
|
72899
|
+
return names;
|
|
72900
|
+
} catch {
|
|
72901
|
+
return new Set;
|
|
72902
|
+
}
|
|
72903
|
+
}
|
|
72904
|
+
function resolveDelegationDepthThreshold(flagValue) {
|
|
72905
|
+
const fromFlag = coerceThreshold(flagValue);
|
|
72906
|
+
if (fromFlag !== null)
|
|
72907
|
+
return { value: fromFlag, source: "flag" };
|
|
72908
|
+
const fromEnv = coerceThreshold(process.env["TODOS_DELEGATION_DEPTH_THRESHOLD"]);
|
|
72909
|
+
if (fromEnv !== null)
|
|
72910
|
+
return { value: fromEnv, source: "env" };
|
|
72911
|
+
return { value: null, source: "unset" };
|
|
72912
|
+
}
|
|
72913
|
+
function coerceThreshold(value) {
|
|
72914
|
+
if (value === undefined || value === null || value === "")
|
|
72915
|
+
return null;
|
|
72916
|
+
const parsed = typeof value === "number" ? value : Number.parseInt(String(value).trim(), 10);
|
|
72917
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0)
|
|
72918
|
+
return null;
|
|
72919
|
+
return parsed;
|
|
72920
|
+
}
|
|
72921
|
+
var DEFAULT_CLAIM_WINDOW_MINUTES = 30;
|
|
72922
|
+
var init_delegation_policy = () => {};
|
|
72923
|
+
|
|
72924
|
+
// src/lib/delegation-record.ts
|
|
72925
|
+
function formatDispatchComment(input) {
|
|
72926
|
+
const lines = [];
|
|
72927
|
+
lines.push(`${DISPATCH_COMMENT_MARKER} ${input.worker} <- ${input.dispatcher} @ ${input.dispatchedAt}`);
|
|
72928
|
+
lines.push(`runtime: ${input.runtime ?? "unspecified"}`);
|
|
72929
|
+
lines.push(`brief: ${input.briefSource} (${input.briefBytes} bytes, sha256 ${input.briefSha256})`);
|
|
72930
|
+
lines.push(`lineage: delegated_from=${input.dispatcher} delegation_depth=${input.depth} reports_to=${input.reportsTo}`);
|
|
72931
|
+
lines.push(`identity: ${input.identityOutcome}`);
|
|
72932
|
+
lines.push(`seat ${input.seatSlug}: ${input.seatOpenTasks} open, threshold ${input.depthThreshold === null ? "unset" : input.depthThreshold}${input.override ? `, OVERRIDE ${input.override}` : ""}`);
|
|
72933
|
+
lines.push(`claim deadline: ${input.claimDeadline}`);
|
|
72934
|
+
lines.push("started_at is deliberately NOT set: the worker claims with `todos start`.");
|
|
72935
|
+
return lines.join(`
|
|
72936
|
+
`);
|
|
72937
|
+
}
|
|
72938
|
+
function formatDispatchNotice(input) {
|
|
72939
|
+
const shortId = input.taskId.slice(0, 8);
|
|
72940
|
+
const override = input.override ? ` [${input.override}]` : "";
|
|
72941
|
+
return `${DISPATCH_COMMENT_MARKER} ${shortId} -> ${input.worker} ` + `(by ${input.dispatcher}, depth ${input.depth}, claim by ${input.claimDeadline})${override}`;
|
|
72942
|
+
}
|
|
72943
|
+
function claimDeadlineFrom(dispatchedAt, windowMinutes) {
|
|
72944
|
+
return new Date(dispatchedAt.getTime() + windowMinutes * 60000).toISOString();
|
|
72945
|
+
}
|
|
72946
|
+
var DISPATCH_COMMENT_MARKER = "[DISPATCH]";
|
|
72947
|
+
|
|
72948
|
+
// src/lib/delegation-verify.ts
|
|
72949
|
+
function missingDelegationLineage(persisted, expected) {
|
|
72950
|
+
const missing = [];
|
|
72951
|
+
if (!sameName(persisted.assigned_to, expected.assignedTo))
|
|
72952
|
+
missing.push("assigned_to");
|
|
72953
|
+
if (!sameName(persisted.assigned_by, expected.assignedBy))
|
|
72954
|
+
missing.push("assigned_by");
|
|
72955
|
+
if (!sameName(persisted.delegated_from, expected.delegatedFrom))
|
|
72956
|
+
missing.push("delegated_from");
|
|
72957
|
+
if (persisted.delegation_depth !== expected.depth)
|
|
72958
|
+
missing.push("delegation_depth");
|
|
72959
|
+
return missing;
|
|
72960
|
+
}
|
|
72961
|
+
function sameName(actual, wanted) {
|
|
72962
|
+
return typeof actual === "string" && actual.trim().toLowerCase() === wanted.trim().toLowerCase();
|
|
72963
|
+
}
|
|
72964
|
+
function partialDelegationMessage(missing, taskId) {
|
|
72965
|
+
return `The delegation was only PARTIALLY recorded on task ${taskId}: the authority accepted the update but did not ` + `persist ${missing.join(", ")}. ` + "The row may now be assigned without its handover lineage, so it is NOT safe to treat this as delegated. " + "This is an authority-version problem, not a connectivity, credential or storage-mode problem: the /v1 server " + "must be running a build that writes assigned_by, delegated_from and delegation_depth. " + "Re-run this exact command once it is, and the row will be completed in place.";
|
|
72966
|
+
}
|
|
72967
|
+
|
|
72968
|
+
// src/cli/commands/delegate.ts
|
|
72969
|
+
var exports_delegate = {};
|
|
72970
|
+
__export(exports_delegate, {
|
|
72971
|
+
registerDelegateCommands: () => registerDelegateCommands
|
|
72972
|
+
});
|
|
72973
|
+
import chalk12 from "chalk";
|
|
72974
|
+
import { readFileSync as readFileSync21 } from "fs";
|
|
72975
|
+
function registerDelegateCommands(program2) {
|
|
72976
|
+
program2.command("delegate <task> <worker>").description("Hand a filed task to a worker in one call: brief, depth, lineage, assignment, record and notice").option("--brief <path>", "Path to the self-sufficient brief; `-` reads stdin").option("--brief-text <text>", "Inline brief, as an alternative to --brief").option("--depth-threshold <n>", "Open-task count above which this delegation parks").option("--despite-depth", "Proceed past an armed depth threshold; recorded in the [DISPATCH] comment").option("--owner-directive", "Mark as an owner-directive dispatch: depth warns and never parks").option("--seat <slug>", "Seat whose open count is read (default: the lineage parent)").option("--runtime <name>", "Worker runtime label recorded in the comment (e.g. claude-code-subagent)").option("--reports-to <agent>", "Lineage parent for the worker identity (default: the dispatcher)").option("--reuse-identity", "Skip registration and reuse an existing worker identity").option("--depth <n>", "Explicit delegation_depth (default: the task's current depth + 1)").option("--channel <name>", "Channel for the one-line notice (default: $TODOS_DELEGATE_NOTICE_CHANNEL)").option("--no-post", "Skip the channel notice").option("--claim-window <minutes>", `Minutes before the claim deadline (default: ${DEFAULT_CLAIM_WINDOW_MINUTES})`).option("--assign-seat", "Allow <worker> to name a durable seat (a seat queue has no session watching it)").option("--dry-run", "Report all seven effects and perform none").option("-j, --json", "Output as JSON").action(async (taskRef, workerInput, opts) => {
|
|
72977
|
+
const globalOpts = program2.opts();
|
|
72978
|
+
const useJson = Boolean(opts.json || globalOpts.json);
|
|
72979
|
+
try {
|
|
72980
|
+
const brief = resolveDelegationBrief({ briefPath: opts.brief, briefText: opts.briefText }, {
|
|
72981
|
+
readFile: (path) => readFileSync21(path, "utf8"),
|
|
72982
|
+
readStdin: () => readFileSync21(0, "utf8")
|
|
72983
|
+
});
|
|
72984
|
+
if (!brief.ok)
|
|
72985
|
+
handleError(new Error(brief.message));
|
|
72986
|
+
const dispatcherIdentity = resolveWritableIdentity(globalOpts.agent);
|
|
72987
|
+
if (!dispatcherIdentity.agent_id) {
|
|
72988
|
+
handleError(new Error("Cannot delegate without a dispatcher identity: this verb records WHO handed the row over, " + "and a handover from nobody is not a handover. " + "Set TODOS_AGENT_ID=<name> for this session, or pass --agent <name>. " + "An identity persisted by `todos init` is deliberately not used \u2014 it is keyed on $HOME and names the station, not this session."));
|
|
72989
|
+
}
|
|
72990
|
+
const dispatcher = dispatcherIdentity.agent_id;
|
|
72991
|
+
const worker = await resolveValidatedAssignee(workerInput, Boolean(opts.assignSeat), (v) => `${taskRef} ${v} --assign-seat`);
|
|
72992
|
+
const embargo = loadDelegationEmbargo();
|
|
72993
|
+
const embargoedForm = [workerInput, worker].find((candidate) => embargo.has(normalizeAgentNameInput(candidate)));
|
|
72994
|
+
if (embargoedForm !== undefined) {
|
|
72995
|
+
handleError(new Error(`'${embargoedForm}' is under a delegation embargo and must not receive dispatched work. ` + "The embargo list is a file, not a constant \u2014 see TODOS_DELEGATION_EMBARGO_PATH."));
|
|
72996
|
+
}
|
|
72997
|
+
try {
|
|
72998
|
+
validateAgentName(worker);
|
|
72999
|
+
} catch (error2) {
|
|
73000
|
+
handleError(new Error(`Cannot delegate to '${worker}': ${error2 instanceof Error ? error2.message : String(error2)} ` + "Nothing was written \u2014 the task is unchanged and still unassigned."));
|
|
73001
|
+
}
|
|
73002
|
+
const reportsTo = (opts.reportsTo ?? dispatcher).trim();
|
|
73003
|
+
const seatSlug = (opts.seat ?? reportsTo).trim();
|
|
73004
|
+
const cloud = getTodosCloudClient();
|
|
73005
|
+
const taskId = await resolveTaskIdForCommand(taskRef, cloud);
|
|
73006
|
+
const db = cloud ? null : getDatabase();
|
|
73007
|
+
const task2 = cloud ? await cloudGetTask(cloud, taskId) : getTask(taskId, db);
|
|
73008
|
+
if (!task2)
|
|
73009
|
+
handleError(new Error(`Task not found: ${taskRef}`));
|
|
73010
|
+
const threshold = resolveDelegationDepthThreshold(opts.depthThreshold);
|
|
73011
|
+
const seatOpenTasks = cloud ? await cloudCountTasks(cloud, { assigned_to: seatSlug, status: "pending" }) : countTasks({ assigned_to: seatSlug, status: "pending" }, db);
|
|
73012
|
+
const override = opts.ownerDirective ? "owner-directive" : opts.despiteDepth ? "despite-depth" : null;
|
|
73013
|
+
const overThreshold = threshold.value !== null && seatOpenTasks > threshold.value;
|
|
73014
|
+
const parked = overThreshold && override === null;
|
|
73015
|
+
if (overThreshold && override === "owner-directive") {
|
|
73016
|
+
console.error(chalk12.yellow(`Warning: seat ${seatSlug} carries ${seatOpenTasks} open tasks (threshold ${threshold.value}); ` + "proceeding because this is an owner-directive dispatch."));
|
|
73017
|
+
}
|
|
73018
|
+
if (parked) {
|
|
73019
|
+
handleError(new Error(`Seat ${seatSlug} carries ${seatOpenTasks} open tasks, above the armed threshold of ${threshold.value} ` + `(from ${threshold.source}). Re-run with --despite-depth to proceed and have the override recorded, ` + "or --owner-directive if this row is an owner directive."));
|
|
73020
|
+
}
|
|
73021
|
+
const currentDepth = typeof task2.delegation_depth === "number" ? task2.delegation_depth : 0;
|
|
73022
|
+
const depth = opts.depth !== undefined ? Number.parseInt(opts.depth, 10) : currentDepth + 1;
|
|
73023
|
+
if (!Number.isSafeInteger(depth) || depth < 0) {
|
|
73024
|
+
handleError(new Error(`--depth must be a non-negative integer; got ${JSON.stringify(opts.depth)}`));
|
|
73025
|
+
}
|
|
73026
|
+
const dispatchedAtDate = new Date;
|
|
73027
|
+
const dispatchedAt = dispatchedAtDate.toISOString();
|
|
73028
|
+
const claimWindowMinutes = opts.claimWindow !== undefined ? Number.parseInt(opts.claimWindow, 10) : DEFAULT_CLAIM_WINDOW_MINUTES;
|
|
73029
|
+
if (!Number.isSafeInteger(claimWindowMinutes) || claimWindowMinutes <= 0) {
|
|
73030
|
+
handleError(new Error(`--claim-window must be a positive integer; got ${JSON.stringify(opts.claimWindow)}`));
|
|
73031
|
+
}
|
|
73032
|
+
const claimDeadline = claimDeadlineFrom(dispatchedAtDate, claimWindowMinutes);
|
|
73033
|
+
const record = {
|
|
73034
|
+
taskId: task2.id,
|
|
73035
|
+
worker,
|
|
73036
|
+
dispatcher,
|
|
73037
|
+
runtime: opts.runtime ?? null,
|
|
73038
|
+
briefSource: brief.source,
|
|
73039
|
+
briefSha256: brief.sha256,
|
|
73040
|
+
briefBytes: brief.bytes,
|
|
73041
|
+
depth,
|
|
73042
|
+
reportsTo,
|
|
73043
|
+
seatSlug,
|
|
73044
|
+
seatOpenTasks,
|
|
73045
|
+
depthThreshold: threshold.value,
|
|
73046
|
+
override,
|
|
73047
|
+
identityOutcome: opts.reuseIdentity ? "skipped" : "created",
|
|
73048
|
+
dispatchedAt,
|
|
73049
|
+
claimDeadline
|
|
73050
|
+
};
|
|
73051
|
+
if (opts.dryRun) {
|
|
73052
|
+
const previewChannel = opts.channel ?? process.env["TODOS_DELEGATE_NOTICE_CHANNEL"] ?? null;
|
|
73053
|
+
const preview = {
|
|
73054
|
+
dry_run: true,
|
|
73055
|
+
task: { id: task2.id, short_id: task2.short_id, title: task2.title },
|
|
73056
|
+
delegation: summarize4(record, {
|
|
73057
|
+
identityOutcome: opts.reuseIdentity ? "skipped" : "created",
|
|
73058
|
+
commentId: null,
|
|
73059
|
+
notice: { posted: false, channel: previewChannel, error: null }
|
|
73060
|
+
}),
|
|
73061
|
+
would: [
|
|
73062
|
+
"1. brief accepted (already validated)",
|
|
73063
|
+
`2. seat ${seatSlug}: ${seatOpenTasks} open, threshold ${threshold.value ?? "unset"}`,
|
|
73064
|
+
opts.reuseIdentity ? `3. registration SKIPPED (--reuse-identity); reusing ${worker}` : `3. register ${worker} with reports_to=${reportsTo}`,
|
|
73065
|
+
`4. assign to ${worker}; assigned_by=${dispatcher}, delegated_from=${dispatcher}, delegation_depth=${depth}`,
|
|
73066
|
+
"5. append the [DISPATCH] comment",
|
|
73067
|
+
opts.post === false ? "6. channel notice SKIPPED (--no-post)" : `6. post one notice to ${previewChannel ?? "(no channel resolved \u2014 set --channel or TODOS_DELEGATE_NOTICE_CHANNEL)"}`,
|
|
73068
|
+
`7. claim deadline ${claimDeadline}`
|
|
73069
|
+
]
|
|
73070
|
+
};
|
|
73071
|
+
if (useJson) {
|
|
73072
|
+
output(preview, true);
|
|
73073
|
+
return;
|
|
73074
|
+
}
|
|
73075
|
+
console.log(chalk12.dim("[dry-run] no writes performed"));
|
|
73076
|
+
for (const line of preview.would)
|
|
73077
|
+
console.log(` ${line}`);
|
|
73078
|
+
return;
|
|
73079
|
+
}
|
|
73080
|
+
let identityOutcome = "skipped";
|
|
73081
|
+
if (!opts.reuseIdentity) {
|
|
73082
|
+
identityOutcome = await registerWorkerIdentity(worker, reportsTo, cloud, db);
|
|
73083
|
+
}
|
|
73084
|
+
record.identityOutcome = identityOutcome;
|
|
73085
|
+
const mergedMetadata = {
|
|
73086
|
+
...task2.metadata && typeof task2.metadata === "object" ? task2.metadata : {},
|
|
73087
|
+
delegation: {
|
|
73088
|
+
worker,
|
|
73089
|
+
dispatcher,
|
|
73090
|
+
runtime: opts.runtime ?? null,
|
|
73091
|
+
brief_source: brief.source,
|
|
73092
|
+
brief_sha256: brief.sha256,
|
|
73093
|
+
dispatched_at: dispatchedAt,
|
|
73094
|
+
claim_deadline: claimDeadline,
|
|
73095
|
+
claim_window_minutes: claimWindowMinutes,
|
|
73096
|
+
depth,
|
|
73097
|
+
override
|
|
73098
|
+
}
|
|
73099
|
+
};
|
|
73100
|
+
const patch = {
|
|
73101
|
+
assigned_to: worker,
|
|
73102
|
+
assigned_by: dispatcher,
|
|
73103
|
+
delegated_from: dispatcher,
|
|
73104
|
+
delegation_depth: depth,
|
|
73105
|
+
metadata: mergedMetadata
|
|
73106
|
+
};
|
|
73107
|
+
const updated = cloud ? await cloudUpdateTask(cloud, task2.id, patch) : updateTask(task2.id, { ...patch, version: task2.version }, db);
|
|
73108
|
+
const missing = missingDelegationLineage(updated, {
|
|
73109
|
+
assignedTo: worker,
|
|
73110
|
+
assignedBy: dispatcher,
|
|
73111
|
+
delegatedFrom: dispatcher,
|
|
73112
|
+
depth
|
|
73113
|
+
});
|
|
73114
|
+
if (missing.length > 0) {
|
|
73115
|
+
handleError(new Error(partialDelegationMessage(missing, task2.id)));
|
|
73116
|
+
}
|
|
73117
|
+
const commentBody = formatDispatchComment(record);
|
|
73118
|
+
const comment = cloud ? await cloudAddComment(cloud, task2.id, { content: commentBody, agent_id: dispatcher }) : addComment({ task_id: task2.id, agent_id: dispatcher, content: commentBody }, db);
|
|
73119
|
+
const notice = opts.post === false ? { posted: false, channel: opts.channel ?? null, error: null } : postNotice(formatDispatchNotice(record), opts.channel ?? null);
|
|
73120
|
+
const payload = {
|
|
73121
|
+
task: updated,
|
|
73122
|
+
delegation: summarize4(record, {
|
|
73123
|
+
identityOutcome,
|
|
73124
|
+
commentId: comment.id,
|
|
73125
|
+
notice
|
|
73126
|
+
})
|
|
73127
|
+
};
|
|
73128
|
+
if (useJson) {
|
|
73129
|
+
output(payload, true);
|
|
73130
|
+
return;
|
|
73131
|
+
}
|
|
73132
|
+
console.log(chalk12.green(`Delegated ${updated.short_id ?? updated.id.slice(0, 8)} to ${worker}`));
|
|
73133
|
+
console.log(chalk12.dim(` by ${dispatcher}, depth ${depth}, seat ${seatSlug} has ${seatOpenTasks} open`));
|
|
73134
|
+
console.log(chalk12.dim(` brief ${brief.source} (sha256 ${brief.sha256.slice(0, 12)}\u2026)`));
|
|
73135
|
+
console.log(chalk12.dim(` claim by ${claimDeadline}; the worker claims with \`todos start\``));
|
|
73136
|
+
if (!notice.posted && opts.post !== false) {
|
|
73137
|
+
console.error(chalk12.yellow(`Warning: the channel notice was not posted: ${notice.error ?? "unknown reason"}`));
|
|
73138
|
+
}
|
|
73139
|
+
} catch (e) {
|
|
73140
|
+
handleError(e);
|
|
73141
|
+
}
|
|
73142
|
+
});
|
|
73143
|
+
}
|
|
73144
|
+
function summarize4(record, extra) {
|
|
73145
|
+
return {
|
|
73146
|
+
worker: record.worker,
|
|
73147
|
+
dispatcher: record.dispatcher,
|
|
73148
|
+
runtime: record.runtime,
|
|
73149
|
+
depth: record.depth,
|
|
73150
|
+
reports_to: record.reportsTo,
|
|
73151
|
+
brief: { source: record.briefSource, sha256: record.briefSha256, bytes: record.briefBytes },
|
|
73152
|
+
seat: {
|
|
73153
|
+
slug: record.seatSlug,
|
|
73154
|
+
open_tasks: record.seatOpenTasks,
|
|
73155
|
+
threshold: record.depthThreshold,
|
|
73156
|
+
parked: false,
|
|
73157
|
+
override: record.override
|
|
73158
|
+
},
|
|
73159
|
+
identity: { name: record.worker, reports_to: record.reportsTo, outcome: extra.identityOutcome },
|
|
73160
|
+
comment_id: extra.commentId,
|
|
73161
|
+
dispatched_at: record.dispatchedAt,
|
|
73162
|
+
claim_deadline: record.claimDeadline,
|
|
73163
|
+
notice: extra.notice,
|
|
73164
|
+
started_at_written: false
|
|
73165
|
+
};
|
|
73166
|
+
}
|
|
73167
|
+
async function registerWorkerIdentity(worker, reportsTo, cloud, db) {
|
|
73168
|
+
if (cloud) {
|
|
73169
|
+
const existing = (await cloudListAgents(cloud)).find((a) => normalizeAgentNameInput(a.name) === normalizeAgentNameInput(worker));
|
|
73170
|
+
if (existing)
|
|
73171
|
+
return "reused";
|
|
73172
|
+
try {
|
|
73173
|
+
await cloudRegisterAgent(cloud, { name: worker, reports_to: reportsTo });
|
|
73174
|
+
return "created";
|
|
73175
|
+
} catch (error2) {
|
|
73176
|
+
const status = error2 && typeof error2 === "object" ? error2.status : undefined;
|
|
73177
|
+
if (status === 409)
|
|
73178
|
+
return "reused";
|
|
73179
|
+
throw error2;
|
|
73180
|
+
}
|
|
73181
|
+
}
|
|
73182
|
+
if (getAgentByName(worker, db))
|
|
73183
|
+
return "reused";
|
|
73184
|
+
const result = registerAgent({ name: worker, reports_to: reportsTo }, db);
|
|
73185
|
+
return isAgentConflict(result) ? "reused" : "created";
|
|
73186
|
+
}
|
|
73187
|
+
function postNotice(line, channel) {
|
|
73188
|
+
const resolved = channel || process.env["TODOS_DELEGATE_NOTICE_CHANNEL"] || null;
|
|
73189
|
+
if (!resolved) {
|
|
73190
|
+
return {
|
|
73191
|
+
posted: false,
|
|
73192
|
+
channel: null,
|
|
73193
|
+
error: "no channel resolved: pass --channel <name>, set TODOS_DELEGATE_NOTICE_CHANNEL, " + "or pass --no-post to skip the notice deliberately"
|
|
73194
|
+
};
|
|
73195
|
+
}
|
|
73196
|
+
channel = resolved;
|
|
73197
|
+
const bin = process.env["TODOS_DELEGATE_NOTIFY_BIN"] || "conversations";
|
|
73198
|
+
try {
|
|
73199
|
+
const proc = Bun.spawnSync([bin, "send", "--channel", channel, line], { stdout: "pipe", stderr: "pipe" });
|
|
73200
|
+
if (proc.exitCode !== 0) {
|
|
73201
|
+
const stderr = new TextDecoder().decode(proc.stderr).trim();
|
|
73202
|
+
return { posted: false, channel, error: stderr || `${bin} exited ${proc.exitCode}` };
|
|
73203
|
+
}
|
|
73204
|
+
return { posted: true, channel, error: null };
|
|
73205
|
+
} catch (error2) {
|
|
73206
|
+
return { posted: false, channel, error: error2 instanceof Error ? error2.message : String(error2) };
|
|
73207
|
+
}
|
|
73208
|
+
}
|
|
73209
|
+
var init_delegate = __esm(() => {
|
|
73210
|
+
init_cloud_router();
|
|
73211
|
+
init_database();
|
|
73212
|
+
init_tasks();
|
|
73213
|
+
init_comments();
|
|
73214
|
+
init_agents();
|
|
73215
|
+
init_agent_names();
|
|
73216
|
+
init_creator_identity();
|
|
73217
|
+
init_delegation_brief();
|
|
73218
|
+
init_delegation_policy();
|
|
73219
|
+
init_assignee_guard();
|
|
73220
|
+
init_helpers();
|
|
73221
|
+
});
|
|
73222
|
+
|
|
72732
73223
|
// src/cli/commands/machines.tsx
|
|
72733
73224
|
var exports_machines = {};
|
|
72734
73225
|
__export(exports_machines, {
|
|
72735
73226
|
registerMachineCommands: () => registerMachineCommands
|
|
72736
73227
|
});
|
|
72737
|
-
import
|
|
73228
|
+
import chalk13 from "chalk";
|
|
72738
73229
|
import { execSync as execSync4 } from "child_process";
|
|
72739
|
-
import { readFileSync as
|
|
73230
|
+
import { readFileSync as readFileSync22, unlinkSync as unlinkSync3, writeFileSync as writeFileSync14 } from "fs";
|
|
72740
73231
|
import { tmpdir as tmpdir5 } from "os";
|
|
72741
|
-
import { join as
|
|
73232
|
+
import { join as join29 } from "path";
|
|
72742
73233
|
function getOrCreateLocalMachineName() {
|
|
72743
73234
|
return process.env["TODOS_MACHINE_NAME"] || __require("os").hostname() || "unknown";
|
|
72744
73235
|
}
|
|
@@ -72776,11 +73267,11 @@ function remoteTempPath(sshAddress) {
|
|
|
72776
73267
|
}
|
|
72777
73268
|
function readRemoteBridgeBundle(sshAddress) {
|
|
72778
73269
|
const remotePath = remoteTempPath(sshAddress);
|
|
72779
|
-
const localPath =
|
|
73270
|
+
const localPath = join29(tmpdir5(), `todos-bridge-pull-${uuid()}.json`);
|
|
72780
73271
|
try {
|
|
72781
73272
|
runSsh(sshAddress, `todos export --format bridge --allow-plaintext-sensitive --output ${shellQuote(remotePath)}`, 120000);
|
|
72782
73273
|
scpFromRemote(sshAddress, remotePath, localPath);
|
|
72783
|
-
return JSON.parse(
|
|
73274
|
+
return JSON.parse(readFileSync22(localPath, "utf-8"));
|
|
72784
73275
|
} finally {
|
|
72785
73276
|
try {
|
|
72786
73277
|
runSsh(sshAddress, `rm -f ${shellQuote(remotePath)}`, 1e4);
|
|
@@ -72791,7 +73282,7 @@ function readRemoteBridgeBundle(sshAddress) {
|
|
|
72791
73282
|
}
|
|
72792
73283
|
}
|
|
72793
73284
|
function writeLocalBridgeBundle() {
|
|
72794
|
-
const localPath =
|
|
73285
|
+
const localPath = join29(tmpdir5(), `todos-bridge-push-${uuid()}.json`);
|
|
72795
73286
|
writeFileSync14(localPath, JSON.stringify(createLocalBridgeBundle(), null, 2));
|
|
72796
73287
|
return localPath;
|
|
72797
73288
|
}
|
|
@@ -72828,17 +73319,17 @@ function registerMachineCommands(program2) {
|
|
|
72828
73319
|
const db = getDatabase();
|
|
72829
73320
|
const machines = listMachines(db, opts.all);
|
|
72830
73321
|
if (machines.length === 0) {
|
|
72831
|
-
console.log(
|
|
72832
|
-
console.log(
|
|
73322
|
+
console.log(chalk13.yellow("No machines registered."));
|
|
73323
|
+
console.log(chalk13.dim("Use `todos machines register` to add one."));
|
|
72833
73324
|
return;
|
|
72834
73325
|
}
|
|
72835
73326
|
for (const m of machines) {
|
|
72836
|
-
const primaryTag = m.is_primary ?
|
|
72837
|
-
const archivedTag = m.archived_at ?
|
|
72838
|
-
console.log(`${
|
|
72839
|
-
console.log(
|
|
72840
|
-
console.log(
|
|
72841
|
-
console.log(
|
|
73327
|
+
const primaryTag = m.is_primary ? chalk13.bold(" [PRIMARY]") : "";
|
|
73328
|
+
const archivedTag = m.archived_at ? chalk13.dim(" [ARCHIVED]") : "";
|
|
73329
|
+
console.log(`${chalk13.cyan(m.name)} (${m.id.slice(0, 8)})${primaryTag}${archivedTag}`);
|
|
73330
|
+
console.log(chalk13.dim(` Host: ${m.hostname ?? "unknown"} | Platform: ${m.platform ?? "unknown"}`));
|
|
73331
|
+
console.log(chalk13.dim(` SSH: ${m.ssh_address ?? "(not set)"}`));
|
|
73332
|
+
console.log(chalk13.dim(` Last seen: ${m.last_seen_at}`));
|
|
72842
73333
|
}
|
|
72843
73334
|
});
|
|
72844
73335
|
machinesCmd.command("register").description("Register a machine").argument("<name>", "Machine name").option("--hostname <host>", "OS hostname").option("--platform <platform>", "OS platform").option("--ssh <address>", "SSH address (e.g. user@host)").option("--arch <arch>", "Architecture (e.g. linux-arm64)").option("--tailscale-name <name>", "User-provided Tailscale/MagicDNS name").option("--tailscale-ip <ip>", "User-provided Tailscale IP").option("--lan-address <address>", "User-provided LAN address").option("--workspace <path>", "Local workspace path for this machine").option("--git-root <path>", "Local git root for this machine").option("--primary", "Set as primary machine").option("-j, --json", "Output as JSON").action((name, opts) => {
|
|
@@ -72860,17 +73351,17 @@ function registerMachineCommands(program2) {
|
|
|
72860
73351
|
console.log(JSON.stringify(machine));
|
|
72861
73352
|
return;
|
|
72862
73353
|
}
|
|
72863
|
-
console.log(
|
|
72864
|
-
console.log(
|
|
72865
|
-
console.log(
|
|
73354
|
+
console.log(chalk13.green(`Machine registered: ${machine.name} (${machine.id.slice(0, 8)})`));
|
|
73355
|
+
console.log(chalk13.dim(` Host: ${machine.hostname} | Platform: ${machine.platform}`));
|
|
73356
|
+
console.log(chalk13.dim(` Primary: ${machine.is_primary}`));
|
|
72866
73357
|
if (machine.ssh_address)
|
|
72867
|
-
console.log(
|
|
73358
|
+
console.log(chalk13.dim(` SSH: ${machine.ssh_address}`));
|
|
72868
73359
|
if (machine.metadata["tailscale_name"])
|
|
72869
|
-
console.log(
|
|
73360
|
+
console.log(chalk13.dim(` Tailscale: ${machine.metadata["tailscale_name"]}`));
|
|
72870
73361
|
if (machine.metadata["lan_address"])
|
|
72871
|
-
console.log(
|
|
73362
|
+
console.log(chalk13.dim(` LAN: ${machine.metadata["lan_address"]}`));
|
|
72872
73363
|
} catch (err) {
|
|
72873
|
-
console.error(
|
|
73364
|
+
console.error(chalk13.red(err instanceof Error ? err.message : String(err)));
|
|
72874
73365
|
process.exit(1);
|
|
72875
73366
|
}
|
|
72876
73367
|
});
|
|
@@ -72892,10 +73383,10 @@ function registerMachineCommands(program2) {
|
|
|
72892
73383
|
console.log(JSON.stringify(machine));
|
|
72893
73384
|
return;
|
|
72894
73385
|
}
|
|
72895
|
-
console.log(
|
|
72896
|
-
console.log(
|
|
73386
|
+
console.log(chalk13.green(`Heartbeat recorded: ${machine.name} (${machine.id.slice(0, 8)})`));
|
|
73387
|
+
console.log(chalk13.dim(` Last seen: ${machine.last_seen_at}`));
|
|
72897
73388
|
} catch (err) {
|
|
72898
|
-
console.error(
|
|
73389
|
+
console.error(chalk13.red(err instanceof Error ? err.message : String(err)));
|
|
72899
73390
|
process.exit(1);
|
|
72900
73391
|
}
|
|
72901
73392
|
});
|
|
@@ -72903,9 +73394,9 @@ function registerMachineCommands(program2) {
|
|
|
72903
73394
|
try {
|
|
72904
73395
|
const db = getDatabase();
|
|
72905
73396
|
const machine = setPrimaryMachine(name, db);
|
|
72906
|
-
console.log(
|
|
73397
|
+
console.log(chalk13.green(`Primary machine set to: ${machine.name} (${machine.id.slice(0, 8)})`));
|
|
72907
73398
|
} catch (err) {
|
|
72908
|
-
console.error(
|
|
73399
|
+
console.error(chalk13.red(err instanceof Error ? err.message : String(err)));
|
|
72909
73400
|
process.exit(1);
|
|
72910
73401
|
}
|
|
72911
73402
|
});
|
|
@@ -72914,13 +73405,13 @@ function registerMachineCommands(program2) {
|
|
|
72914
73405
|
const db = getDatabase();
|
|
72915
73406
|
const machine = getMachineByName(name, db);
|
|
72916
73407
|
if (!machine) {
|
|
72917
|
-
console.error(
|
|
73408
|
+
console.error(chalk13.red(`Machine '${name}' not found`));
|
|
72918
73409
|
process.exit(1);
|
|
72919
73410
|
}
|
|
72920
73411
|
archiveMachine(machine.id, db);
|
|
72921
|
-
console.log(
|
|
73412
|
+
console.log(chalk13.green(`Machine '${name}' archived`));
|
|
72922
73413
|
} catch (err) {
|
|
72923
|
-
console.error(
|
|
73414
|
+
console.error(chalk13.red(err instanceof Error ? err.message : String(err)));
|
|
72924
73415
|
process.exit(1);
|
|
72925
73416
|
}
|
|
72926
73417
|
});
|
|
@@ -72929,13 +73420,13 @@ function registerMachineCommands(program2) {
|
|
|
72929
73420
|
const db = getDatabase();
|
|
72930
73421
|
const machine = getMachineByName(name, db);
|
|
72931
73422
|
if (!machine) {
|
|
72932
|
-
console.error(
|
|
73423
|
+
console.error(chalk13.red(`Machine '${name}' not found`));
|
|
72933
73424
|
process.exit(1);
|
|
72934
73425
|
}
|
|
72935
73426
|
unarchiveMachine(machine.id, db);
|
|
72936
|
-
console.log(
|
|
73427
|
+
console.log(chalk13.green(`Machine '${name}' unarchived`));
|
|
72937
73428
|
} catch (err) {
|
|
72938
|
-
console.error(
|
|
73429
|
+
console.error(chalk13.red(err instanceof Error ? err.message : String(err)));
|
|
72939
73430
|
process.exit(1);
|
|
72940
73431
|
}
|
|
72941
73432
|
});
|
|
@@ -72944,13 +73435,13 @@ function registerMachineCommands(program2) {
|
|
|
72944
73435
|
const db = getDatabase();
|
|
72945
73436
|
const machine = getMachineByName(name, db);
|
|
72946
73437
|
if (!machine) {
|
|
72947
|
-
console.error(
|
|
73438
|
+
console.error(chalk13.red(`Machine '${name}' not found`));
|
|
72948
73439
|
process.exit(1);
|
|
72949
73440
|
}
|
|
72950
73441
|
deleteMachine(machine.id, db);
|
|
72951
|
-
console.log(
|
|
73442
|
+
console.log(chalk13.green(`Machine '${name}' deleted`));
|
|
72952
73443
|
} catch (err) {
|
|
72953
|
-
console.error(
|
|
73444
|
+
console.error(chalk13.red(err instanceof Error ? err.message : String(err)));
|
|
72954
73445
|
process.exit(1);
|
|
72955
73446
|
}
|
|
72956
73447
|
});
|
|
@@ -72959,39 +73450,39 @@ function registerMachineCommands(program2) {
|
|
|
72959
73450
|
const machines = listMachines(db);
|
|
72960
73451
|
const primary = getPrimaryMachine(db);
|
|
72961
73452
|
if (machines.length === 0) {
|
|
72962
|
-
console.log(
|
|
73453
|
+
console.log(chalk13.yellow("No machines registered."));
|
|
72963
73454
|
return;
|
|
72964
73455
|
}
|
|
72965
|
-
console.log(
|
|
73456
|
+
console.log(chalk13.bold(`
|
|
72966
73457
|
Machine Health`));
|
|
72967
|
-
console.log(
|
|
73458
|
+
console.log(chalk13.dim("\u2500".repeat(60)));
|
|
72968
73459
|
for (const m of machines) {
|
|
72969
|
-
const primaryTag = m.is_primary ?
|
|
73460
|
+
const primaryTag = m.is_primary ? chalk13.bold(" [PRIMARY]") : "";
|
|
72970
73461
|
const lastSeen = new Date(m.last_seen_at);
|
|
72971
73462
|
const nowDate = new Date;
|
|
72972
73463
|
const diffMs = nowDate.getTime() - lastSeen.getTime();
|
|
72973
73464
|
const diffMin = Math.round(diffMs / 60000);
|
|
72974
73465
|
let status;
|
|
72975
73466
|
if (diffMin < 5) {
|
|
72976
|
-
status =
|
|
73467
|
+
status = chalk13.green("online");
|
|
72977
73468
|
} else if (diffMin < 60) {
|
|
72978
|
-
status =
|
|
73469
|
+
status = chalk13.yellow("stale");
|
|
72979
73470
|
} else {
|
|
72980
|
-
status =
|
|
73471
|
+
status = chalk13.red("offline");
|
|
72981
73472
|
}
|
|
72982
|
-
console.log(`${
|
|
73473
|
+
console.log(`${chalk13.cyan(m.name)}${primaryTag} ${status} last: ${diffMin}m ago`);
|
|
72983
73474
|
}
|
|
72984
73475
|
if (!primary) {
|
|
72985
|
-
console.log(
|
|
73476
|
+
console.log(chalk13.yellow(`
|
|
72986
73477
|
Warning: No primary machine set.`));
|
|
72987
|
-
console.log(
|
|
73478
|
+
console.log(chalk13.dim("Use `todos machines set-primary <name>` to set one."));
|
|
72988
73479
|
}
|
|
72989
73480
|
});
|
|
72990
73481
|
machinesCmd.command("topology").description("Show local machine topology diagnostics").option("--stale-minutes <n>", "Minutes before a machine is considered stale", "30").option("--include-archived", "Include archived machines").option("-j, --json", "Output as JSON").action((opts) => {
|
|
72991
73482
|
try {
|
|
72992
73483
|
const staleMinutes = Number.parseInt(opts.staleMinutes, 10);
|
|
72993
73484
|
if (!Number.isFinite(staleMinutes) || staleMinutes < 1) {
|
|
72994
|
-
console.error(
|
|
73485
|
+
console.error(chalk13.red("Invalid --stale-minutes value. Must be a positive integer."));
|
|
72995
73486
|
process.exit(1);
|
|
72996
73487
|
}
|
|
72997
73488
|
const diagnostics = getMachineTopologyDiagnostics({
|
|
@@ -73002,26 +73493,26 @@ Warning: No primary machine set.`));
|
|
|
73002
73493
|
console.log(JSON.stringify(diagnostics));
|
|
73003
73494
|
return;
|
|
73004
73495
|
}
|
|
73005
|
-
console.log(
|
|
73496
|
+
console.log(chalk13.bold(`
|
|
73006
73497
|
Machine Topology`));
|
|
73007
|
-
console.log(
|
|
73498
|
+
console.log(chalk13.dim("\u2500".repeat(60)));
|
|
73008
73499
|
for (const machine of diagnostics.machines) {
|
|
73009
|
-
const stale = machine.stale ?
|
|
73500
|
+
const stale = machine.stale ? chalk13.red(` stale ${machine.stale_minutes}m`) : chalk13.green(" fresh");
|
|
73010
73501
|
const ts = machine.topology.tailscale_ip ? ` ts:${machine.topology.tailscale_ip}` : "";
|
|
73011
73502
|
const lan = machine.topology.lan_address ? ` lan:${machine.topology.lan_address}` : "";
|
|
73012
73503
|
const workspace = machine.topology.workspace_path ? `
|
|
73013
73504
|
workspace: ${machine.topology.workspace_path}` : "";
|
|
73014
|
-
console.log(`${
|
|
73505
|
+
console.log(`${chalk13.cyan(machine.name)}${stale}${chalk13.dim(ts + lan)}${chalk13.dim(workspace)}`);
|
|
73015
73506
|
}
|
|
73016
73507
|
if (diagnostics.path_issues.length > 0) {
|
|
73017
|
-
console.log(
|
|
73508
|
+
console.log(chalk13.yellow(`
|
|
73018
73509
|
Path diagnostics (${diagnostics.path_issues.length})`));
|
|
73019
73510
|
for (const issue of diagnostics.path_issues) {
|
|
73020
|
-
console.log(
|
|
73511
|
+
console.log(chalk13.yellow(` ${issue.type}: ${issue.message}`));
|
|
73021
73512
|
}
|
|
73022
73513
|
}
|
|
73023
73514
|
} catch (err) {
|
|
73024
|
-
console.error(
|
|
73515
|
+
console.error(chalk13.red(err instanceof Error ? err.message : String(err)));
|
|
73025
73516
|
process.exit(1);
|
|
73026
73517
|
}
|
|
73027
73518
|
});
|
|
@@ -73049,7 +73540,7 @@ Path diagnostics (${diagnostics.path_issues.length})`));
|
|
|
73049
73540
|
}, null, 2));
|
|
73050
73541
|
return;
|
|
73051
73542
|
}
|
|
73052
|
-
console.log(
|
|
73543
|
+
console.log(chalk13.dim(opts.machine ? `No remote SSH target found for machine '${opts.machine}'.` : "No remote machines with SSH addresses to sync."));
|
|
73053
73544
|
return;
|
|
73054
73545
|
}
|
|
73055
73546
|
const results = [];
|
|
@@ -73064,14 +73555,14 @@ Path diagnostics (${diagnostics.path_issues.length})`));
|
|
|
73064
73555
|
const record = { machine: target.name, pull };
|
|
73065
73556
|
if (!wantsJson(program2, opts)) {
|
|
73066
73557
|
const mode = opts.dryRun ? "would pull" : "pulled";
|
|
73067
|
-
console.log(
|
|
73558
|
+
console.log(chalk13.green(` ${target.name}: ${mode} ${formatBridgeImportSummary(pull)}`));
|
|
73068
73559
|
}
|
|
73069
73560
|
if (opts.push) {
|
|
73070
73561
|
const push = pushLocalBridgeBundle(ssh, Boolean(opts.dryRun));
|
|
73071
73562
|
record.push = push;
|
|
73072
73563
|
if (!wantsJson(program2, opts)) {
|
|
73073
73564
|
const mode = opts.dryRun ? "would push" : "pushed";
|
|
73074
|
-
console.log(
|
|
73565
|
+
console.log(chalk13.green(` ${target.name}: ${mode} ${formatBridgeImportSummary(push)}`));
|
|
73075
73566
|
}
|
|
73076
73567
|
}
|
|
73077
73568
|
results.push(record);
|
|
@@ -73079,7 +73570,7 @@ Path diagnostics (${diagnostics.path_issues.length})`));
|
|
|
73079
73570
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
73080
73571
|
results.push({ machine: target.name, error: message });
|
|
73081
73572
|
if (!wantsJson(program2, opts))
|
|
73082
|
-
console.log(
|
|
73573
|
+
console.log(chalk13.yellow(` ${target.name}: sync failed: ${message}`));
|
|
73083
73574
|
}
|
|
73084
73575
|
}
|
|
73085
73576
|
if (wantsJson(program2, opts)) {
|
|
@@ -73090,19 +73581,19 @@ Path diagnostics (${diagnostics.path_issues.length})`));
|
|
|
73090
73581
|
}, null, 2));
|
|
73091
73582
|
return;
|
|
73092
73583
|
}
|
|
73093
|
-
console.log(
|
|
73584
|
+
console.log(chalk13.bold(`
|
|
73094
73585
|
Sync ${opts.dryRun ? "dry-run" : "complete"}: ${results.length} machine(s) checked.`));
|
|
73095
73586
|
});
|
|
73096
73587
|
machinesCmd.command("tasks").description("List tasks from a remote machine via SSH").argument("<machine-name>", "Machine name (must have SSH address)").option("--status <status>", "Filter by status").action((machineName, opts) => {
|
|
73097
73588
|
const db = getDatabase();
|
|
73098
73589
|
const machine = getMachineByName(machineName, db);
|
|
73099
73590
|
if (!machine) {
|
|
73100
|
-
console.error(
|
|
73591
|
+
console.error(chalk13.red(`Machine '${machineName}' not found`));
|
|
73101
73592
|
process.exit(1);
|
|
73102
73593
|
}
|
|
73103
73594
|
const sshAddress = resolveMachineSshAddress(machine, getOrCreateLocalMachineName());
|
|
73104
73595
|
if (!sshAddress) {
|
|
73105
|
-
console.error(
|
|
73596
|
+
console.error(chalk13.red(`Machine '${machineName}' has no SSH address`));
|
|
73106
73597
|
process.exit(1);
|
|
73107
73598
|
}
|
|
73108
73599
|
try {
|
|
@@ -73110,19 +73601,19 @@ Sync ${opts.dryRun ? "dry-run" : "complete"}: ${results.length} machine(s) check
|
|
|
73110
73601
|
const tasks = bundle.data.tasks;
|
|
73111
73602
|
const filtered = opts.status ? tasks.filter((t) => t.status === opts.status) : tasks;
|
|
73112
73603
|
if (filtered.length === 0) {
|
|
73113
|
-
console.log(
|
|
73604
|
+
console.log(chalk13.dim(`No tasks on ${machineName}`));
|
|
73114
73605
|
return;
|
|
73115
73606
|
}
|
|
73116
|
-
console.log(
|
|
73607
|
+
console.log(chalk13.bold(`${filtered.length} task(s) on ${machineName}:
|
|
73117
73608
|
`));
|
|
73118
73609
|
for (const t of filtered) {
|
|
73119
73610
|
const check = t.status === "completed" ? "x" : " ";
|
|
73120
|
-
const prio = t.priority ?
|
|
73611
|
+
const prio = t.priority ? chalk13.yellow(`[${t.priority}]`) : "";
|
|
73121
73612
|
console.log(` [${check}] ${t.short_id || t.id.slice(0, 8)} ${prio} ${t.title}`);
|
|
73122
73613
|
}
|
|
73123
73614
|
} catch (error2) {
|
|
73124
73615
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
73125
|
-
console.error(
|
|
73616
|
+
console.error(chalk13.red(`Could not read tasks from ${sshAddress}: ${message}`));
|
|
73126
73617
|
process.exit(1);
|
|
73127
73618
|
}
|
|
73128
73619
|
});
|
|
@@ -73138,7 +73629,7 @@ var exports_api_key_commands = {};
|
|
|
73138
73629
|
__export(exports_api_key_commands, {
|
|
73139
73630
|
registerApiKeyCommands: () => registerApiKeyCommands
|
|
73140
73631
|
});
|
|
73141
|
-
import
|
|
73632
|
+
import chalk14 from "chalk";
|
|
73142
73633
|
function registerApiKeyCommands(program2) {
|
|
73143
73634
|
const apiKeys = program2.command("api-keys").alias("api-key").description("Generate, list, and revoke API keys for secured app/API access");
|
|
73144
73635
|
apiKeys.command("create <name>").alias("generate").description("Generate a new API key. The plaintext key is shown once.").option("--expires-at <iso>", "Optional ISO timestamp when this key expires").option("--permissions <list>", "Comma-separated permissions (default: *)").action((name, opts) => {
|
|
@@ -73150,12 +73641,12 @@ function registerApiKeyCommands(program2) {
|
|
|
73150
73641
|
output(created, true);
|
|
73151
73642
|
return;
|
|
73152
73643
|
}
|
|
73153
|
-
console.log(
|
|
73154
|
-
console.log(` ${
|
|
73155
|
-
console.log(` ${
|
|
73156
|
-
console.log(` ${
|
|
73644
|
+
console.log(chalk14.green("API key generated:"));
|
|
73645
|
+
console.log(` ${chalk14.dim("ID:")} ${created.record.id}`);
|
|
73646
|
+
console.log(` ${chalk14.dim("Name:")} ${created.record.name}`);
|
|
73647
|
+
console.log(` ${chalk14.dim("Prefix:")} ${created.record.prefix}`);
|
|
73157
73648
|
console.log();
|
|
73158
|
-
console.log(
|
|
73649
|
+
console.log(chalk14.yellow("Copy this key now. It will not be shown again:"));
|
|
73159
73650
|
console.log(created.key);
|
|
73160
73651
|
} catch (e) {
|
|
73161
73652
|
handleError(e);
|
|
@@ -73170,16 +73661,16 @@ function registerApiKeyCommands(program2) {
|
|
|
73170
73661
|
return;
|
|
73171
73662
|
}
|
|
73172
73663
|
if (keys.length === 0) {
|
|
73173
|
-
console.log(
|
|
73664
|
+
console.log(chalk14.dim("No API keys found."));
|
|
73174
73665
|
return;
|
|
73175
73666
|
}
|
|
73176
73667
|
for (const key of keys) {
|
|
73177
|
-
const state = key.revoked_at ?
|
|
73178
|
-
console.log(`${
|
|
73668
|
+
const state = key.revoked_at ? chalk14.red("revoked") : key.expires_at && key.expires_at < new Date().toISOString() ? chalk14.yellow("expired") : chalk14.green("active");
|
|
73669
|
+
console.log(`${chalk14.cyan(key.id)} ${chalk14.bold(key.name)} ${chalk14.dim(key.prefix)} ${state}`);
|
|
73179
73670
|
if (key.last_used_at)
|
|
73180
|
-
console.log(
|
|
73671
|
+
console.log(chalk14.dim(` last used: ${key.last_used_at}`));
|
|
73181
73672
|
if (key.expires_at)
|
|
73182
|
-
console.log(
|
|
73673
|
+
console.log(chalk14.dim(` expires: ${key.expires_at}`));
|
|
73183
73674
|
}
|
|
73184
73675
|
} catch (e) {
|
|
73185
73676
|
handleError(e);
|
|
@@ -73196,7 +73687,7 @@ function registerApiKeyCommands(program2) {
|
|
|
73196
73687
|
output(revoked, true);
|
|
73197
73688
|
return;
|
|
73198
73689
|
}
|
|
73199
|
-
console.log(
|
|
73690
|
+
console.log(chalk14.green(`Revoked API key: ${revoked.name} (${revoked.prefix})`));
|
|
73200
73691
|
} catch (e) {
|
|
73201
73692
|
handleError(e);
|
|
73202
73693
|
}
|
|
@@ -73212,7 +73703,7 @@ function registerApiKeyCommands(program2) {
|
|
|
73212
73703
|
if (!record) {
|
|
73213
73704
|
handleError(new Error("API key is invalid, revoked, or expired."));
|
|
73214
73705
|
}
|
|
73215
|
-
console.log(
|
|
73706
|
+
console.log(chalk14.green(`API key valid: ${record.name} (${record.prefix})`));
|
|
73216
73707
|
} catch (e) {
|
|
73217
73708
|
handleError(e);
|
|
73218
73709
|
}
|
|
@@ -73228,7 +73719,7 @@ var exports_environment_snapshots2 = {};
|
|
|
73228
73719
|
__export(exports_environment_snapshots2, {
|
|
73229
73720
|
registerEnvironmentSnapshotCommands: () => registerEnvironmentSnapshotCommands
|
|
73230
73721
|
});
|
|
73231
|
-
import
|
|
73722
|
+
import chalk15 from "chalk";
|
|
73232
73723
|
function printJson2(value) {
|
|
73233
73724
|
console.log(JSON.stringify(value, null, 2));
|
|
73234
73725
|
}
|
|
@@ -73250,7 +73741,7 @@ function registerEnvironmentSnapshotCommands(program2) {
|
|
|
73250
73741
|
printJson2(result);
|
|
73251
73742
|
return;
|
|
73252
73743
|
}
|
|
73253
|
-
console.log(
|
|
73744
|
+
console.log(chalk15.green("Captured") + ` ${result.snapshot.id}`);
|
|
73254
73745
|
console.log(`path: ${result.output_path}`);
|
|
73255
73746
|
console.log(`root: ${result.snapshot.root}`);
|
|
73256
73747
|
console.log(`git: ${result.snapshot.git.commit || "none"}${result.snapshot.git.is_dirty ? " dirty" : ""}`);
|
|
@@ -73260,13 +73751,13 @@ function registerEnvironmentSnapshotCommands(program2) {
|
|
|
73260
73751
|
if (result.task_verification_id)
|
|
73261
73752
|
console.log(`task verification: ${result.task_verification_id}`);
|
|
73262
73753
|
for (const warning of result.snapshot.warnings)
|
|
73263
|
-
console.log(
|
|
73754
|
+
console.log(chalk15.yellow(`warning: ${warning}`));
|
|
73264
73755
|
} catch (error2) {
|
|
73265
73756
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
73266
73757
|
if (globalOpts.json)
|
|
73267
73758
|
printJson2({ error: message });
|
|
73268
73759
|
else
|
|
73269
|
-
console.error(
|
|
73760
|
+
console.error(chalk15.red(`Error: ${message}`));
|
|
73270
73761
|
process.exit(1);
|
|
73271
73762
|
}
|
|
73272
73763
|
});
|
|
@@ -73292,7 +73783,7 @@ function registerEnvironmentSnapshotCommands(program2) {
|
|
|
73292
73783
|
if (globalOpts.json)
|
|
73293
73784
|
printJson2({ error: message });
|
|
73294
73785
|
else
|
|
73295
|
-
console.error(
|
|
73786
|
+
console.error(chalk15.red(`Error: ${message}`));
|
|
73296
73787
|
process.exit(1);
|
|
73297
73788
|
}
|
|
73298
73789
|
});
|
|
@@ -73306,7 +73797,7 @@ var exports_knowledge_commands = {};
|
|
|
73306
73797
|
__export(exports_knowledge_commands, {
|
|
73307
73798
|
registerKnowledgeCommands: () => registerKnowledgeCommands
|
|
73308
73799
|
});
|
|
73309
|
-
import
|
|
73800
|
+
import chalk16 from "chalk";
|
|
73310
73801
|
function parseRecordType(value) {
|
|
73311
73802
|
if (RECORD_TYPES.includes(value))
|
|
73312
73803
|
return value;
|
|
@@ -73342,13 +73833,13 @@ function commonFilters(opts) {
|
|
|
73342
73833
|
};
|
|
73343
73834
|
}
|
|
73344
73835
|
function printRecord(record) {
|
|
73345
|
-
console.log(`${
|
|
73836
|
+
console.log(`${chalk16.cyan(record.id.slice(0, 8))} ${chalk16.yellow(record.record_type)} ${record.title}`);
|
|
73346
73837
|
if (record.task_id)
|
|
73347
|
-
console.log(
|
|
73838
|
+
console.log(chalk16.dim(` task: ${record.task_id}`));
|
|
73348
73839
|
if (record.project_id)
|
|
73349
|
-
console.log(
|
|
73840
|
+
console.log(chalk16.dim(` project: ${record.project_id}`));
|
|
73350
73841
|
if (record.tags.length > 0)
|
|
73351
|
-
console.log(
|
|
73842
|
+
console.log(chalk16.dim(` tags: ${record.tags.join(", ")}`));
|
|
73352
73843
|
if (record.decision)
|
|
73353
73844
|
console.log(` decision: ${record.decision}`);
|
|
73354
73845
|
else if (record.content)
|
|
@@ -73401,7 +73892,7 @@ function registerKnowledgeCommands(program2) {
|
|
|
73401
73892
|
if (opts.json || globalOpts.json)
|
|
73402
73893
|
output(result, true);
|
|
73403
73894
|
else {
|
|
73404
|
-
console.log(
|
|
73895
|
+
console.log(chalk16.green(`Snapshot ${result.snapshot_id.slice(0, 8)} saved.`));
|
|
73405
73896
|
printRecord(result.record);
|
|
73406
73897
|
}
|
|
73407
73898
|
} catch (error2) {
|
|
@@ -73475,7 +73966,7 @@ var exports_risk_commands = {};
|
|
|
73475
73966
|
__export(exports_risk_commands, {
|
|
73476
73967
|
registerRiskCommands: () => registerRiskCommands
|
|
73477
73968
|
});
|
|
73478
|
-
import
|
|
73969
|
+
import chalk17 from "chalk";
|
|
73479
73970
|
function parseChoice(value, choices, label) {
|
|
73480
73971
|
if (choices.includes(value))
|
|
73481
73972
|
return value;
|
|
@@ -73514,16 +74005,16 @@ function commonFilters2(opts) {
|
|
|
73514
74005
|
};
|
|
73515
74006
|
}
|
|
73516
74007
|
function printRisk(risk) {
|
|
73517
|
-
const color = risk.severity === "critical" ?
|
|
73518
|
-
console.log(`${
|
|
74008
|
+
const color = risk.severity === "critical" ? chalk17.red : risk.severity === "high" ? chalk17.yellow : chalk17.white;
|
|
74009
|
+
console.log(`${chalk17.cyan(risk.id.slice(0, 8))} ${color(risk.severity)} ${chalk17.bold(risk.status)} ${risk.title}`);
|
|
73519
74010
|
if (risk.owner)
|
|
73520
|
-
console.log(
|
|
74011
|
+
console.log(chalk17.dim(` owner: ${risk.owner}`));
|
|
73521
74012
|
if (risk.due_at)
|
|
73522
|
-
console.log(
|
|
74013
|
+
console.log(chalk17.dim(` due: ${risk.due_at}`));
|
|
73523
74014
|
if (risk.plan_id)
|
|
73524
|
-
console.log(
|
|
74015
|
+
console.log(chalk17.dim(` plan: ${risk.plan_id}`));
|
|
73525
74016
|
if (risk.project_id)
|
|
73526
|
-
console.log(
|
|
74017
|
+
console.log(chalk17.dim(` project: ${risk.project_id}`));
|
|
73527
74018
|
if (risk.mitigation)
|
|
73528
74019
|
console.log(` mitigation: ${risk.mitigation}`);
|
|
73529
74020
|
}
|
|
@@ -73631,8 +74122,8 @@ function registerRiskCommands(program2) {
|
|
|
73631
74122
|
if (opts.json || globalOpts.json)
|
|
73632
74123
|
output(report, true);
|
|
73633
74124
|
else {
|
|
73634
|
-
console.log(`${
|
|
73635
|
-
console.log(
|
|
74125
|
+
console.log(`${chalk17.bold("Health")} ${report.status} (${report.score}/100)`);
|
|
74126
|
+
console.log(chalk17.dim(`${report.components.total_tasks} tasks \xB7 ${report.components.blocked_tasks} blocked \xB7 ${report.components.overdue_tasks} overdue \xB7 ${report.components.open_risks} open risks`));
|
|
73636
74127
|
for (const recommendation of report.recommendations)
|
|
73637
74128
|
console.log(`- ${recommendation}`);
|
|
73638
74129
|
}
|
|
@@ -73670,7 +74161,7 @@ var exports_retrospective_commands = {};
|
|
|
73670
74161
|
__export(exports_retrospective_commands, {
|
|
73671
74162
|
registerRetrospectiveCommands: () => registerRetrospectiveCommands
|
|
73672
74163
|
});
|
|
73673
|
-
import
|
|
74164
|
+
import chalk18 from "chalk";
|
|
73674
74165
|
function commonFilters3(opts) {
|
|
73675
74166
|
return {
|
|
73676
74167
|
project_id: opts.project,
|
|
@@ -73681,8 +74172,8 @@ function commonFilters3(opts) {
|
|
|
73681
74172
|
}
|
|
73682
74173
|
function printRetrospective(record) {
|
|
73683
74174
|
const report = record.report;
|
|
73684
|
-
console.log(`${
|
|
73685
|
-
console.log(
|
|
74175
|
+
console.log(`${chalk18.cyan(record.id.slice(0, 8))} ${chalk18.bold(record.title)} ${chalk18.dim(`${record.scope}:${report.scope_id.slice(0, 8)}`)}`);
|
|
74176
|
+
console.log(chalk18.dim(` tasks: ${report.summary.completed_tasks}/${report.summary.total_tasks} completed \xB7 missed: ${report.summary.missed_estimates} \xB7 blockers: ${report.summary.recurring_blockers} \xB7 failed checks: ${report.summary.failed_verifications}`));
|
|
73686
74177
|
for (const lesson of report.lessons.slice(0, 3))
|
|
73687
74178
|
console.log(` - ${lesson}`);
|
|
73688
74179
|
}
|
|
@@ -73760,7 +74251,7 @@ var exports_agent_reliability_commands = {};
|
|
|
73760
74251
|
__export(exports_agent_reliability_commands, {
|
|
73761
74252
|
registerAgentReliabilityCommands: () => registerAgentReliabilityCommands
|
|
73762
74253
|
});
|
|
73763
|
-
import
|
|
74254
|
+
import chalk19 from "chalk";
|
|
73764
74255
|
function parseNumber(value, fallback) {
|
|
73765
74256
|
if (!value)
|
|
73766
74257
|
return fallback;
|
|
@@ -73775,9 +74266,9 @@ function commonOptions(opts) {
|
|
|
73775
74266
|
};
|
|
73776
74267
|
}
|
|
73777
74268
|
function printScorecard(scorecard) {
|
|
73778
|
-
const color = scorecard.grade === "at_risk" ?
|
|
73779
|
-
console.log(`${
|
|
73780
|
-
console.log(
|
|
74269
|
+
const color = scorecard.grade === "at_risk" ? chalk19.red : scorecard.grade === "watch" ? chalk19.yellow : scorecard.grade === "excellent" ? chalk19.green : chalk19.white;
|
|
74270
|
+
console.log(`${chalk19.cyan(scorecard.agent_id.slice(0, 8))} ${color(`${scorecard.score}/100`)} ${chalk19.bold(scorecard.agent_name)} ${chalk19.dim(scorecard.grade)}`);
|
|
74271
|
+
console.log(chalk19.dim(` completed: ${scorecard.signals.tasks_completed} \xB7 failed: ${scorecard.signals.tasks_failed} \xB7 failed checks: ${scorecard.signals.failed_verifications} \xB7 failed runs: ${scorecard.signals.runs_failed} \xB7 stale locks: ${scorecard.signals.stale_task_locks + scorecard.signals.stale_resource_locks}`));
|
|
73781
74272
|
for (const recommendation of scorecard.recommendations.slice(0, 3))
|
|
73782
74273
|
console.log(` - ${recommendation}`);
|
|
73783
74274
|
}
|
|
@@ -73849,7 +74340,7 @@ var exports_onboarding_commands = {};
|
|
|
73849
74340
|
__export(exports_onboarding_commands, {
|
|
73850
74341
|
registerOnboardingCommands: () => registerOnboardingCommands
|
|
73851
74342
|
});
|
|
73852
|
-
import
|
|
74343
|
+
import chalk20 from "chalk";
|
|
73853
74344
|
import { resolve as resolve23 } from "path";
|
|
73854
74345
|
function registerOnboardingCommands(program2) {
|
|
73855
74346
|
program2.command("onboarding").alias("demo-fixtures").description("List, show, write, or import bundled local onboarding fixtures").option("--show <name>", "Show one fixture bridge bundle as JSON").option("--write <dir>", "Write all bundled fixture bridge bundles to a directory").option("--import <name>", "Dry-run or apply an onboarding fixture import").option("--apply", "Apply an onboarding fixture import. Defaults to dry-run.").option("--resolve-conflicts", "Safely merge existing local tasks while preserving divergent fields").action(async (opts) => {
|
|
@@ -73871,9 +74362,9 @@ function registerOnboardingCommands(program2) {
|
|
|
73871
74362
|
output(result, true);
|
|
73872
74363
|
return;
|
|
73873
74364
|
}
|
|
73874
|
-
console.log(
|
|
74365
|
+
console.log(chalk20.green(`Wrote ${result.written} onboarding fixture file(s) to ${result.directory}`));
|
|
73875
74366
|
for (const file of result.files)
|
|
73876
|
-
console.log(
|
|
74367
|
+
console.log(chalk20.dim(` ${file}`));
|
|
73877
74368
|
return;
|
|
73878
74369
|
}
|
|
73879
74370
|
if (opts.import) {
|
|
@@ -73887,7 +74378,7 @@ function registerOnboardingCommands(program2) {
|
|
|
73887
74378
|
return;
|
|
73888
74379
|
}
|
|
73889
74380
|
const mode = result.dry_run ? "Dry-run" : "Import";
|
|
73890
|
-
console.log(
|
|
74381
|
+
console.log(chalk20.bold(`${mode} ${result.ok ? "ready" : "has issues"}`));
|
|
73891
74382
|
for (const [key, count2] of Object.entries(result.inserted)) {
|
|
73892
74383
|
if (count2 > 0)
|
|
73893
74384
|
console.log(` ${key}: ${count2}`);
|
|
@@ -73897,9 +74388,9 @@ function registerOnboardingCommands(program2) {
|
|
|
73897
74388
|
console.log(` ${key} merged: ${count2}`);
|
|
73898
74389
|
}
|
|
73899
74390
|
if (result.conflicts.length > 0)
|
|
73900
|
-
console.log(
|
|
74391
|
+
console.log(chalk20.yellow(` conflicts: ${result.conflicts.length}`));
|
|
73901
74392
|
for (const issue of result.issues)
|
|
73902
|
-
console.error(
|
|
74393
|
+
console.error(chalk20.red(` ${issue}`));
|
|
73903
74394
|
return;
|
|
73904
74395
|
}
|
|
73905
74396
|
const fixtures = listOnboardingFixtures2();
|
|
@@ -73907,11 +74398,11 @@ function registerOnboardingCommands(program2) {
|
|
|
73907
74398
|
output(fixtures, true);
|
|
73908
74399
|
return;
|
|
73909
74400
|
}
|
|
73910
|
-
console.log(
|
|
74401
|
+
console.log(chalk20.bold(`${fixtures.length} bundled onboarding fixture(s):
|
|
73911
74402
|
`));
|
|
73912
74403
|
for (const fixture of fixtures) {
|
|
73913
|
-
console.log(` ${
|
|
73914
|
-
console.log(
|
|
74404
|
+
console.log(` ${chalk20.bold(fixture.name)} ${chalk20.dim(`[${fixture.version}]`)} ${chalk20.yellow(`${fixture.stats.tasks} tasks`)}`);
|
|
74405
|
+
console.log(chalk20.dim(` ${fixture.description}`));
|
|
73915
74406
|
}
|
|
73916
74407
|
} catch (e) {
|
|
73917
74408
|
handleError(e);
|
|
@@ -73927,7 +74418,7 @@ var exports_local_snapshot_commands = {};
|
|
|
73927
74418
|
__export(exports_local_snapshot_commands, {
|
|
73928
74419
|
registerLocalSnapshotCommands: () => registerLocalSnapshotCommands
|
|
73929
74420
|
});
|
|
73930
|
-
import
|
|
74421
|
+
import chalk21 from "chalk";
|
|
73931
74422
|
function splitTypes(value) {
|
|
73932
74423
|
if (!value)
|
|
73933
74424
|
return;
|
|
@@ -73961,9 +74452,9 @@ function registerLocalSnapshotCommands(program2) {
|
|
|
73961
74452
|
output(result, true);
|
|
73962
74453
|
return;
|
|
73963
74454
|
}
|
|
73964
|
-
console.log(
|
|
74455
|
+
console.log(chalk21.bold(`Changed snapshots: ${result.snapshots.length}`));
|
|
73965
74456
|
for (const snapshot of result.snapshots) {
|
|
73966
|
-
console.log(` ${snapshot.type} ${
|
|
74457
|
+
console.log(` ${snapshot.type} ${chalk21.dim(snapshot.cursor)} ${snapshot.fingerprint.slice(0, 12)}`);
|
|
73967
74458
|
}
|
|
73968
74459
|
return;
|
|
73969
74460
|
}
|
|
@@ -73982,7 +74473,7 @@ function registerLocalSnapshotCommands(program2) {
|
|
|
73982
74473
|
output(snapshot, true);
|
|
73983
74474
|
return;
|
|
73984
74475
|
}
|
|
73985
|
-
console.log(
|
|
74476
|
+
console.log(chalk21.bold(`${snapshot.type} snapshot`));
|
|
73986
74477
|
console.log(` count: ${snapshot.count}`);
|
|
73987
74478
|
console.log(` cursor: ${snapshot.cursor}`);
|
|
73988
74479
|
console.log(` fingerprint: ${snapshot.fingerprint}`);
|
|
@@ -73993,11 +74484,11 @@ function registerLocalSnapshotCommands(program2) {
|
|
|
73993
74484
|
output(resources, true);
|
|
73994
74485
|
return;
|
|
73995
74486
|
}
|
|
73996
|
-
console.log(
|
|
74487
|
+
console.log(chalk21.bold(`${resources.length} local snapshot resources:
|
|
73997
74488
|
`));
|
|
73998
74489
|
for (const resource of resources) {
|
|
73999
|
-
console.log(` ${
|
|
74000
|
-
console.log(
|
|
74490
|
+
console.log(` ${chalk21.bold(resource.type)} ${chalk21.dim(resource.uri)}`);
|
|
74491
|
+
console.log(chalk21.dim(` ${resource.description}`));
|
|
74001
74492
|
}
|
|
74002
74493
|
} catch (e) {
|
|
74003
74494
|
handleError(e);
|
|
@@ -77366,7 +77857,7 @@ __export(exports_sdk_integration_fixtures, {
|
|
|
77366
77857
|
TODOS_SDK_INTEGRATION_FIXTURE_GENERATED_AT: () => TODOS_SDK_INTEGRATION_FIXTURE_GENERATED_AT
|
|
77367
77858
|
});
|
|
77368
77859
|
import { mkdirSync as mkdirSync15, writeFileSync as writeFileSync15 } from "fs";
|
|
77369
|
-
import { join as
|
|
77860
|
+
import { join as join30 } from "path";
|
|
77370
77861
|
function source5(version) {
|
|
77371
77862
|
return {
|
|
77372
77863
|
packageName: "@hasna/todos",
|
|
@@ -77473,7 +77964,7 @@ function writeSdkIntegrationFixtures(directory, options = {}) {
|
|
|
77473
77964
|
];
|
|
77474
77965
|
const written = [];
|
|
77475
77966
|
for (const [name, payload] of files) {
|
|
77476
|
-
const file =
|
|
77967
|
+
const file = join30(directory, name);
|
|
77477
77968
|
writeFileSync15(file, `${JSON.stringify(payload, null, 2)}
|
|
77478
77969
|
`, "utf-8");
|
|
77479
77970
|
written.push(file);
|
|
@@ -77496,7 +77987,7 @@ var exports_sdk_fixture_commands = {};
|
|
|
77496
77987
|
__export(exports_sdk_fixture_commands, {
|
|
77497
77988
|
registerSdkFixtureCommands: () => registerSdkFixtureCommands
|
|
77498
77989
|
});
|
|
77499
|
-
import
|
|
77990
|
+
import chalk22 from "chalk";
|
|
77500
77991
|
import { resolve as resolve24 } from "path";
|
|
77501
77992
|
function registerSdkFixtureCommands(program2) {
|
|
77502
77993
|
program2.command("sdk-fixtures").description("List, show, or write local SDK integration fixtures").option("--show", "Print the full fixture pack JSON").option("--write <dir>", "Write fixture pack, bridge fixture, contract snapshots, and example index to a directory").action(async (opts) => {
|
|
@@ -77513,9 +78004,9 @@ function registerSdkFixtureCommands(program2) {
|
|
|
77513
78004
|
console.log(JSON.stringify(result));
|
|
77514
78005
|
return;
|
|
77515
78006
|
}
|
|
77516
|
-
console.log(
|
|
78007
|
+
console.log(chalk22.green(`Wrote ${result.files.length} SDK integration fixture file(s) to ${result.directory}`));
|
|
77517
78008
|
for (const file of result.files)
|
|
77518
|
-
console.log(
|
|
78009
|
+
console.log(chalk22.dim(` ${file}`));
|
|
77519
78010
|
return;
|
|
77520
78011
|
}
|
|
77521
78012
|
if (opts.show) {
|
|
@@ -77527,11 +78018,11 @@ function registerSdkFixtureCommands(program2) {
|
|
|
77527
78018
|
output(examples, true);
|
|
77528
78019
|
return;
|
|
77529
78020
|
}
|
|
77530
|
-
console.log(
|
|
78021
|
+
console.log(chalk22.bold(`${examples.length} local SDK integration example(s):
|
|
77531
78022
|
`));
|
|
77532
78023
|
for (const example of examples) {
|
|
77533
|
-
console.log(` ${
|
|
77534
|
-
console.log(
|
|
78024
|
+
console.log(` ${chalk22.bold(example.id)} ${chalk22.dim(`[${example.surface}]`)}`);
|
|
78025
|
+
console.log(chalk22.dim(` ${example.command}`));
|
|
77535
78026
|
}
|
|
77536
78027
|
} catch (e) {
|
|
77537
78028
|
handleError(e);
|
|
@@ -77547,7 +78038,7 @@ var exports_review_queue_commands = {};
|
|
|
77547
78038
|
__export(exports_review_queue_commands, {
|
|
77548
78039
|
registerReviewQueueCommands: () => registerReviewQueueCommands
|
|
77549
78040
|
});
|
|
77550
|
-
import
|
|
78041
|
+
import chalk23 from "chalk";
|
|
77551
78042
|
function splitList2(value) {
|
|
77552
78043
|
return value?.split(";").flatMap((part) => part.split(",")).map((item) => item.trim()).filter(Boolean);
|
|
77553
78044
|
}
|
|
@@ -77578,12 +78069,12 @@ function registerReviewQueueCommands(program2) {
|
|
|
77578
78069
|
return;
|
|
77579
78070
|
}
|
|
77580
78071
|
if (items.length === 0) {
|
|
77581
|
-
console.log(
|
|
78072
|
+
console.log(chalk23.dim("Review queue is empty."));
|
|
77582
78073
|
return;
|
|
77583
78074
|
}
|
|
77584
78075
|
for (const item of items) {
|
|
77585
78076
|
const assignee = item.claimed_by || item.reviewer || "(unclaimed)";
|
|
77586
|
-
console.log(`${
|
|
78077
|
+
console.log(`${chalk23.dim(item.task_id.slice(0, 8))} ${item.state.padEnd(17)} ${item.queue.padEnd(12)} ${assignee.padEnd(12)} ${item.title}`);
|
|
77587
78078
|
}
|
|
77588
78079
|
} catch (e) {
|
|
77589
78080
|
handleError(e);
|
|
@@ -77605,7 +78096,7 @@ function registerReviewQueueCommands(program2) {
|
|
|
77605
78096
|
output(item, true);
|
|
77606
78097
|
return;
|
|
77607
78098
|
}
|
|
77608
|
-
console.log(
|
|
78099
|
+
console.log(chalk23.green(`Review requested: ${item.task_id.slice(0, 8)} -> ${item.queue}`));
|
|
77609
78100
|
} catch (e) {
|
|
77610
78101
|
handleError(e);
|
|
77611
78102
|
}
|
|
@@ -77619,7 +78110,7 @@ function registerReviewQueueCommands(program2) {
|
|
|
77619
78110
|
output(item, true);
|
|
77620
78111
|
return;
|
|
77621
78112
|
}
|
|
77622
|
-
console.log(
|
|
78113
|
+
console.log(chalk23.green(`Review claimed: ${item.task_id.slice(0, 8)} by ${item.claimed_by}`));
|
|
77623
78114
|
} catch (e) {
|
|
77624
78115
|
handleError(e);
|
|
77625
78116
|
}
|
|
@@ -77633,7 +78124,7 @@ function registerReviewQueueCommands(program2) {
|
|
|
77633
78124
|
output(item, true);
|
|
77634
78125
|
return;
|
|
77635
78126
|
}
|
|
77636
|
-
console.log(
|
|
78127
|
+
console.log(chalk23.green(`Review approved: ${item.task_id.slice(0, 8)} by ${item.reviewer}`));
|
|
77637
78128
|
} catch (e) {
|
|
77638
78129
|
handleError(e);
|
|
77639
78130
|
}
|
|
@@ -77652,7 +78143,7 @@ function registerReviewQueueCommands(program2) {
|
|
|
77652
78143
|
output(item, true);
|
|
77653
78144
|
return;
|
|
77654
78145
|
}
|
|
77655
|
-
console.log(
|
|
78146
|
+
console.log(chalk23.yellow(`Review returned: ${item.task_id.slice(0, 8)} with ${item.changes_requested.length} requested change(s)`));
|
|
77656
78147
|
} catch (e) {
|
|
77657
78148
|
handleError(e);
|
|
77658
78149
|
}
|
|
@@ -77666,7 +78157,7 @@ function registerReviewQueueCommands(program2) {
|
|
|
77666
78157
|
output(item, true);
|
|
77667
78158
|
return;
|
|
77668
78159
|
}
|
|
77669
|
-
console.log(
|
|
78160
|
+
console.log(chalk23.yellow(`Review reopened: ${item.task_id.slice(0, 8)}`));
|
|
77670
78161
|
} catch (e) {
|
|
77671
78162
|
handleError(e);
|
|
77672
78163
|
}
|
|
@@ -77682,11 +78173,11 @@ function registerReviewQueueCommands(program2) {
|
|
|
77682
78173
|
return;
|
|
77683
78174
|
}
|
|
77684
78175
|
if (items.length === 0) {
|
|
77685
|
-
console.log(
|
|
78176
|
+
console.log(chalk23.dim("No review routing rules configured."));
|
|
77686
78177
|
return;
|
|
77687
78178
|
}
|
|
77688
78179
|
for (const rule of items) {
|
|
77689
|
-
console.log(`${rule.enabled ?
|
|
78180
|
+
console.log(`${rule.enabled ? chalk23.green("on ") : chalk23.gray("off")} ${rule.name.padEnd(16)} ${rule.queue.padEnd(12)} ${rule.reviewers.join(",") || "(no reviewers)"}`);
|
|
77690
78181
|
}
|
|
77691
78182
|
} catch (e) {
|
|
77692
78183
|
handleError(e);
|
|
@@ -77709,7 +78200,7 @@ function registerReviewQueueCommands(program2) {
|
|
|
77709
78200
|
output(rule, true);
|
|
77710
78201
|
return;
|
|
77711
78202
|
}
|
|
77712
|
-
console.log(
|
|
78203
|
+
console.log(chalk23.green(`Review routing rule saved: ${rule.name}`));
|
|
77713
78204
|
} catch (e) {
|
|
77714
78205
|
handleError(e);
|
|
77715
78206
|
}
|
|
@@ -77723,7 +78214,7 @@ function registerReviewQueueCommands(program2) {
|
|
|
77723
78214
|
output({ removed }, true);
|
|
77724
78215
|
return;
|
|
77725
78216
|
}
|
|
77726
|
-
console.log(removed ?
|
|
78217
|
+
console.log(removed ? chalk23.green("Review routing rule removed.") : chalk23.dim("No review routing rule matched."));
|
|
77727
78218
|
} catch (e) {
|
|
77728
78219
|
handleError(e);
|
|
77729
78220
|
}
|
|
@@ -77738,8 +78229,8 @@ var exports_roadmap_commands = {};
|
|
|
77738
78229
|
__export(exports_roadmap_commands, {
|
|
77739
78230
|
registerRoadmapCommands: () => registerRoadmapCommands
|
|
77740
78231
|
});
|
|
77741
|
-
import { readFileSync as
|
|
77742
|
-
import
|
|
78232
|
+
import { readFileSync as readFileSync23, writeFileSync as writeFileSync16 } from "fs";
|
|
78233
|
+
import chalk24 from "chalk";
|
|
77743
78234
|
function splitList3(value) {
|
|
77744
78235
|
return value?.split(";").flatMap((part) => part.split(",")).map((item) => item.trim()).filter(Boolean);
|
|
77745
78236
|
}
|
|
@@ -77786,7 +78277,7 @@ function registerRoadmapCommands(program2) {
|
|
|
77786
78277
|
output(roadmap, true);
|
|
77787
78278
|
return;
|
|
77788
78279
|
}
|
|
77789
|
-
console.log(
|
|
78280
|
+
console.log(chalk24.green(`Roadmap created: ${roadmap.id.slice(0, 8)} ${roadmap.name}`));
|
|
77790
78281
|
} catch (e) {
|
|
77791
78282
|
handleError(e);
|
|
77792
78283
|
}
|
|
@@ -77801,11 +78292,11 @@ function registerRoadmapCommands(program2) {
|
|
|
77801
78292
|
return;
|
|
77802
78293
|
}
|
|
77803
78294
|
if (items.length === 0) {
|
|
77804
|
-
console.log(
|
|
78295
|
+
console.log(chalk24.dim("No roadmaps configured."));
|
|
77805
78296
|
return;
|
|
77806
78297
|
}
|
|
77807
78298
|
for (const item of items)
|
|
77808
|
-
console.log(`${
|
|
78299
|
+
console.log(`${chalk24.dim(item.id.slice(0, 8))} ${item.status.padEnd(9)} ${item.name}`);
|
|
77809
78300
|
} catch (e) {
|
|
77810
78301
|
handleError(e);
|
|
77811
78302
|
}
|
|
@@ -77845,7 +78336,7 @@ function registerRoadmapCommands(program2) {
|
|
|
77845
78336
|
output(updated, true);
|
|
77846
78337
|
return;
|
|
77847
78338
|
}
|
|
77848
|
-
console.log(
|
|
78339
|
+
console.log(chalk24.green(`Roadmap updated: ${updated.id.slice(0, 8)} ${updated.name}`));
|
|
77849
78340
|
} catch (e) {
|
|
77850
78341
|
handleError(e);
|
|
77851
78342
|
}
|
|
@@ -77859,7 +78350,7 @@ function registerRoadmapCommands(program2) {
|
|
|
77859
78350
|
output({ deleted }, true);
|
|
77860
78351
|
return;
|
|
77861
78352
|
}
|
|
77862
|
-
console.log(deleted ?
|
|
78353
|
+
console.log(deleted ? chalk24.green("Roadmap deleted.") : chalk24.dim("No roadmap matched."));
|
|
77863
78354
|
} catch (e) {
|
|
77864
78355
|
handleError(e);
|
|
77865
78356
|
}
|
|
@@ -77887,7 +78378,7 @@ function registerRoadmapCommands(program2) {
|
|
|
77887
78378
|
output(milestone, true);
|
|
77888
78379
|
return;
|
|
77889
78380
|
}
|
|
77890
|
-
console.log(
|
|
78381
|
+
console.log(chalk24.green(`Milestone added: ${milestone.id.slice(0, 8)} ${milestone.title}`));
|
|
77891
78382
|
} catch (e) {
|
|
77892
78383
|
handleError(e);
|
|
77893
78384
|
}
|
|
@@ -77913,7 +78404,7 @@ function registerRoadmapCommands(program2) {
|
|
|
77913
78404
|
output(updated, true);
|
|
77914
78405
|
return;
|
|
77915
78406
|
}
|
|
77916
|
-
console.log(
|
|
78407
|
+
console.log(chalk24.green(`Milestone updated: ${updated.id.slice(0, 8)} ${updated.title}`));
|
|
77917
78408
|
} catch (e) {
|
|
77918
78409
|
handleError(e);
|
|
77919
78410
|
}
|
|
@@ -77938,7 +78429,7 @@ function registerRoadmapCommands(program2) {
|
|
|
77938
78429
|
output(release, true);
|
|
77939
78430
|
return;
|
|
77940
78431
|
}
|
|
77941
|
-
console.log(
|
|
78432
|
+
console.log(chalk24.green(`Release group saved: ${release.name}`));
|
|
77942
78433
|
} catch (e) {
|
|
77943
78434
|
handleError(e);
|
|
77944
78435
|
}
|
|
@@ -77951,7 +78442,7 @@ function registerRoadmapCommands(program2) {
|
|
|
77951
78442
|
if (opts.out) {
|
|
77952
78443
|
writeFileSync16(opts.out, content);
|
|
77953
78444
|
if (!globalOpts.json)
|
|
77954
|
-
console.log(
|
|
78445
|
+
console.log(chalk24.green(`Wrote roadmap export to ${opts.out}`));
|
|
77955
78446
|
}
|
|
77956
78447
|
if (globalOpts.json) {
|
|
77957
78448
|
output(opts.format === "markdown" ? { content } : JSON.parse(content), true);
|
|
@@ -77967,13 +78458,13 @@ function registerRoadmapCommands(program2) {
|
|
|
77967
78458
|
const globalOpts = globalOptions(program2);
|
|
77968
78459
|
try {
|
|
77969
78460
|
const { importRoadmapBundle: importRoadmapBundle2 } = await Promise.resolve().then(() => (init_roadmaps(), exports_roadmaps));
|
|
77970
|
-
const bundle = JSON.parse(
|
|
78461
|
+
const bundle = JSON.parse(readFileSync23(path, "utf8"));
|
|
77971
78462
|
const result = importRoadmapBundle2(bundle, { apply: Boolean(opts.apply) });
|
|
77972
78463
|
if (globalOpts.json) {
|
|
77973
78464
|
output(result, true);
|
|
77974
78465
|
return;
|
|
77975
78466
|
}
|
|
77976
|
-
console.log(result.applied ?
|
|
78467
|
+
console.log(result.applied ? chalk24.green(`Imported roadmap ${result.roadmap_id}`) : chalk24.dim(`Preview: ${result.milestones} milestones, ${result.releases} releases`));
|
|
77977
78468
|
} catch (e) {
|
|
77978
78469
|
handleError(e);
|
|
77979
78470
|
}
|
|
@@ -77989,7 +78480,7 @@ var exports_capacity_commands = {};
|
|
|
77989
78480
|
__export(exports_capacity_commands, {
|
|
77990
78481
|
registerCapacityCommands: () => registerCapacityCommands
|
|
77991
78482
|
});
|
|
77992
|
-
import
|
|
78483
|
+
import chalk25 from "chalk";
|
|
77993
78484
|
function splitDays(value) {
|
|
77994
78485
|
return value?.split(",").map((item) => Number(item.trim())).filter((item) => Number.isFinite(item));
|
|
77995
78486
|
}
|
|
@@ -78022,7 +78513,7 @@ function registerCapacityCommands(program2) {
|
|
|
78022
78513
|
output(profile, true);
|
|
78023
78514
|
return;
|
|
78024
78515
|
}
|
|
78025
|
-
console.log(
|
|
78516
|
+
console.log(chalk25.green(`Capacity saved: ${profile.agent_id} ${profile.minutes_per_day}m/day`));
|
|
78026
78517
|
} catch (e) {
|
|
78027
78518
|
handleError(e);
|
|
78028
78519
|
}
|
|
@@ -78040,7 +78531,7 @@ function registerCapacityCommands(program2) {
|
|
|
78040
78531
|
return;
|
|
78041
78532
|
}
|
|
78042
78533
|
if (profiles.length === 0) {
|
|
78043
|
-
console.log(
|
|
78534
|
+
console.log(chalk25.dim("No capacity profiles."));
|
|
78044
78535
|
return;
|
|
78045
78536
|
}
|
|
78046
78537
|
for (const profile of profiles) {
|
|
@@ -78059,7 +78550,7 @@ function registerCapacityCommands(program2) {
|
|
|
78059
78550
|
output({ removed }, true);
|
|
78060
78551
|
return;
|
|
78061
78552
|
}
|
|
78062
|
-
console.log(removed ?
|
|
78553
|
+
console.log(removed ? chalk25.green("Capacity profile removed.") : chalk25.dim("No capacity profile matched."));
|
|
78063
78554
|
} catch (e) {
|
|
78064
78555
|
handleError(e);
|
|
78065
78556
|
}
|
|
@@ -78098,7 +78589,7 @@ var exports_audit_ledger_commands = {};
|
|
|
78098
78589
|
__export(exports_audit_ledger_commands, {
|
|
78099
78590
|
registerAuditLedgerCommands: () => registerAuditLedgerCommands
|
|
78100
78591
|
});
|
|
78101
|
-
import
|
|
78592
|
+
import chalk26 from "chalk";
|
|
78102
78593
|
function globalOptions3(program2) {
|
|
78103
78594
|
const command = program2;
|
|
78104
78595
|
return command.optsWithGlobals?.() ?? program2.opts();
|
|
@@ -78154,7 +78645,7 @@ function registerAuditLedgerCommands(program2) {
|
|
|
78154
78645
|
output(checkpoint, true);
|
|
78155
78646
|
return;
|
|
78156
78647
|
}
|
|
78157
|
-
console.log(
|
|
78648
|
+
console.log(chalk26.green(`Audit checkpoint sealed: ${checkpoint.name} ${checkpoint.root_hash}`));
|
|
78158
78649
|
} catch (e) {
|
|
78159
78650
|
handleError(e);
|
|
78160
78651
|
}
|
|
@@ -78169,7 +78660,7 @@ function registerAuditLedgerCommands(program2) {
|
|
|
78169
78660
|
return;
|
|
78170
78661
|
}
|
|
78171
78662
|
if (checkpoints.length === 0) {
|
|
78172
|
-
console.log(
|
|
78663
|
+
console.log(chalk26.dim("No audit ledger checkpoints."));
|
|
78173
78664
|
return;
|
|
78174
78665
|
}
|
|
78175
78666
|
for (const checkpoint of checkpoints) {
|
|
@@ -78192,7 +78683,7 @@ function registerAuditLedgerCommands(program2) {
|
|
|
78192
78683
|
output(result, true);
|
|
78193
78684
|
return;
|
|
78194
78685
|
}
|
|
78195
|
-
console.log(result.ok ?
|
|
78686
|
+
console.log(result.ok ? chalk26.green("Audit ledger verified.") : chalk26.red(`Audit ledger failed: ${result.issues.join("; ")}`));
|
|
78196
78687
|
if (!result.ok)
|
|
78197
78688
|
process.exitCode = 1;
|
|
78198
78689
|
} catch (e) {
|
|
@@ -78211,7 +78702,7 @@ var exports_release_compatibility_commands = {};
|
|
|
78211
78702
|
__export(exports_release_compatibility_commands, {
|
|
78212
78703
|
registerReleaseCompatibilityCommands: () => registerReleaseCompatibilityCommands
|
|
78213
78704
|
});
|
|
78214
|
-
import
|
|
78705
|
+
import chalk27 from "chalk";
|
|
78215
78706
|
function globalOptions4(program2) {
|
|
78216
78707
|
const command = program2;
|
|
78217
78708
|
return command.optsWithGlobals?.() ?? program2.opts();
|
|
@@ -78243,7 +78734,7 @@ function registerReleaseCompatibilityCommands(program2) {
|
|
|
78243
78734
|
process.exitCode = 1;
|
|
78244
78735
|
return;
|
|
78245
78736
|
}
|
|
78246
|
-
console.log(report.ok ?
|
|
78737
|
+
console.log(report.ok ? chalk27.green("Release compatibility passed.") : chalk27.red("Release compatibility failed."));
|
|
78247
78738
|
if (!report.ok)
|
|
78248
78739
|
process.exitCode = 1;
|
|
78249
78740
|
} catch (error2) {
|
|
@@ -78326,14 +78817,14 @@ var exports_local_backup_commands = {};
|
|
|
78326
78817
|
__export(exports_local_backup_commands, {
|
|
78327
78818
|
registerLocalBackupCommands: () => registerLocalBackupCommands
|
|
78328
78819
|
});
|
|
78329
|
-
import
|
|
78820
|
+
import chalk28 from "chalk";
|
|
78330
78821
|
import { resolve as resolve25 } from "path";
|
|
78331
78822
|
function globalOptions6(program2) {
|
|
78332
78823
|
const command = program2;
|
|
78333
78824
|
return command.optsWithGlobals?.() ?? program2.opts();
|
|
78334
78825
|
}
|
|
78335
78826
|
function printCreateSummary(result) {
|
|
78336
|
-
console.log(
|
|
78827
|
+
console.log(chalk28.bold("todos local backup"));
|
|
78337
78828
|
if (result.output_path)
|
|
78338
78829
|
console.log(`File: ${result.output_path}`);
|
|
78339
78830
|
console.log(`Checksum: ${result.backup.checksum}`);
|
|
@@ -78373,13 +78864,13 @@ function registerLocalBackupCommands(program2) {
|
|
|
78373
78864
|
output(verification, true);
|
|
78374
78865
|
return;
|
|
78375
78866
|
}
|
|
78376
|
-
console.log(
|
|
78867
|
+
console.log(chalk28.bold(`Backup ${verification.ok ? "verified" : "has issues"}`));
|
|
78377
78868
|
console.log(`Checksum: ${verification.checksum.ok ? "ok" : "mismatch"}`);
|
|
78378
78869
|
console.log(`Bridge: ${verification.bridge_checksum.ok ? "ok" : "mismatch"}`);
|
|
78379
78870
|
for (const issue of verification.issues)
|
|
78380
|
-
console.error(
|
|
78871
|
+
console.error(chalk28.red(` ${issue}`));
|
|
78381
78872
|
for (const warning of verification.warnings)
|
|
78382
|
-
console.error(
|
|
78873
|
+
console.error(chalk28.yellow(` ${warning}`));
|
|
78383
78874
|
} catch (error2) {
|
|
78384
78875
|
handleError(error2);
|
|
78385
78876
|
}
|
|
@@ -78396,18 +78887,18 @@ function registerLocalBackupCommands(program2) {
|
|
|
78396
78887
|
output(result, true);
|
|
78397
78888
|
return;
|
|
78398
78889
|
}
|
|
78399
|
-
console.log(
|
|
78890
|
+
console.log(chalk28.bold(`${result.dry_run ? "Restore dry-run" : "Restore"} ${result.ok ? "ready" : "has issues"}`));
|
|
78400
78891
|
if (result.import_result) {
|
|
78401
78892
|
for (const [key, count2] of Object.entries(result.import_result.inserted)) {
|
|
78402
78893
|
if (count2 > 0)
|
|
78403
78894
|
console.log(` ${key}: ${count2}`);
|
|
78404
78895
|
}
|
|
78405
78896
|
if (result.import_result.conflicts.length > 0) {
|
|
78406
|
-
console.log(
|
|
78897
|
+
console.log(chalk28.yellow(` conflicts: ${result.import_result.conflicts.length}`));
|
|
78407
78898
|
}
|
|
78408
78899
|
}
|
|
78409
78900
|
for (const issue of result.issues)
|
|
78410
|
-
console.error(
|
|
78901
|
+
console.error(chalk28.red(` ${issue}`));
|
|
78411
78902
|
} catch (error2) {
|
|
78412
78903
|
handleError(error2);
|
|
78413
78904
|
}
|
|
@@ -78423,14 +78914,14 @@ function registerLocalBackupCommands(program2) {
|
|
|
78423
78914
|
output(report, true);
|
|
78424
78915
|
return;
|
|
78425
78916
|
}
|
|
78426
|
-
console.log(
|
|
78917
|
+
console.log(chalk28.bold(`Local integrity ${report.ok ? "ok" : "needs attention"}`));
|
|
78427
78918
|
console.log(`Quick check: ${report.sqlite.quick_check}`);
|
|
78428
78919
|
console.log(`Foreign key violations: ${report.sqlite.foreign_key_violations}`);
|
|
78429
78920
|
console.log(`Tasks: ${report.counts.tasks}`);
|
|
78430
78921
|
for (const issue of report.issues)
|
|
78431
|
-
console.error(
|
|
78922
|
+
console.error(chalk28.red(` ${issue}`));
|
|
78432
78923
|
for (const warning of report.warnings)
|
|
78433
|
-
console.error(
|
|
78924
|
+
console.error(chalk28.yellow(` ${warning}`));
|
|
78434
78925
|
} catch (error2) {
|
|
78435
78926
|
handleError(error2);
|
|
78436
78927
|
}
|
|
@@ -78924,7 +79415,7 @@ var init_hybrid = __esm(() => {
|
|
|
78924
79415
|
});
|
|
78925
79416
|
|
|
78926
79417
|
// src/storage/s3-artifacts.ts
|
|
78927
|
-
import { createHash as
|
|
79418
|
+
import { createHash as createHash18, createHmac as createHmac2 } from "crypto";
|
|
78928
79419
|
function createTodosS3ArtifactStore(options) {
|
|
78929
79420
|
const requestFetch = options.fetch ?? fetch;
|
|
78930
79421
|
const now4 = options.now ?? (() => new Date);
|
|
@@ -79096,7 +79587,7 @@ function toAmzDate(date) {
|
|
|
79096
79587
|
return date.toISOString().replace(/[:-]|\.\d{3}/g, "");
|
|
79097
79588
|
}
|
|
79098
79589
|
function sha256Hex(value) {
|
|
79099
|
-
return
|
|
79590
|
+
return createHash18("sha256").update(value).digest("hex");
|
|
79100
79591
|
}
|
|
79101
79592
|
function hmac(key, value) {
|
|
79102
79593
|
return createHmac2("sha256", key).update(value).digest();
|
|
@@ -79703,13 +80194,13 @@ __export(exports_storage_commands, {
|
|
|
79703
80194
|
s3CredentialsFromEnv: () => s3CredentialsFromEnv,
|
|
79704
80195
|
registerStorageCommands: () => registerStorageCommands
|
|
79705
80196
|
});
|
|
79706
|
-
import
|
|
80197
|
+
import chalk29 from "chalk";
|
|
79707
80198
|
function globalOptions7(program2) {
|
|
79708
80199
|
const command = program2;
|
|
79709
80200
|
return command.optsWithGlobals?.() ?? program2.opts();
|
|
79710
80201
|
}
|
|
79711
80202
|
function printStatus(status) {
|
|
79712
|
-
console.log(
|
|
80203
|
+
console.log(chalk29.bold("todos storage"));
|
|
79713
80204
|
console.log(`Mode: ${status.mode}`);
|
|
79714
80205
|
console.log(`Remote: ${status.remote_enabled ? "enabled" : "disabled"}`);
|
|
79715
80206
|
console.log(`Canonical RDS: ${status.canonical.cluster}/${status.canonical.database}`);
|
|
@@ -79720,12 +80211,12 @@ function printStatus(status) {
|
|
|
79720
80211
|
console.log(`Sync batch: ${status.sync.batch_size}`);
|
|
79721
80212
|
console.log(`Network: not used`);
|
|
79722
80213
|
for (const issue of status.issues)
|
|
79723
|
-
console.error(
|
|
80214
|
+
console.error(chalk29.red(` ${issue}`));
|
|
79724
80215
|
for (const warning of status.warnings)
|
|
79725
|
-
console.error(
|
|
80216
|
+
console.error(chalk29.yellow(` ${warning}`));
|
|
79726
80217
|
}
|
|
79727
80218
|
function printSyncPlan(plan) {
|
|
79728
|
-
console.log(
|
|
80219
|
+
console.log(chalk29.bold("todos storage sync-plan"));
|
|
79729
80220
|
console.log(`Mode: ${plan.status.mode}`);
|
|
79730
80221
|
console.log(`Dry run: yes`);
|
|
79731
80222
|
console.log(`Database: ${plan.postgres.configured ? "configured" : "not configured"}`);
|
|
@@ -79739,17 +80230,17 @@ function printSyncPlan(plan) {
|
|
|
79739
80230
|
console.log(statement);
|
|
79740
80231
|
}
|
|
79741
80232
|
for (const issue of plan.status.issues)
|
|
79742
|
-
console.error(
|
|
80233
|
+
console.error(chalk29.red(` ${issue}`));
|
|
79743
80234
|
for (const warning of plan.status.warnings)
|
|
79744
|
-
console.error(
|
|
80235
|
+
console.error(chalk29.yellow(` ${warning}`));
|
|
79745
80236
|
}
|
|
79746
80237
|
function printShadowStatus(report, enabled, shadowEnv) {
|
|
79747
|
-
console.log(
|
|
80238
|
+
console.log(chalk29.bold("todos storage shadow-status"));
|
|
79748
80239
|
console.log(`Shadow mirror: ${enabled ? "enabled" : "disabled"} (${shadowEnv})`);
|
|
79749
80240
|
console.log(`Service: ${report.service}`);
|
|
79750
80241
|
console.log(`Cloud reachable: ${report.cloud_reachable ? "yes" : "no"}`);
|
|
79751
80242
|
if (report.error) {
|
|
79752
|
-
console.error(
|
|
80243
|
+
console.error(chalk29.red(` ${report.error}`));
|
|
79753
80244
|
return;
|
|
79754
80245
|
}
|
|
79755
80246
|
console.log(`In sync: ${report.in_sync ? "yes" : "no"}`);
|
|
@@ -79757,7 +80248,7 @@ function printShadowStatus(report, enabled, shadowEnv) {
|
|
|
79757
80248
|
console.log(`Last mirror lag: ${report.last_mirror_lag_ms === null ? "n/a" : `${report.last_mirror_lag_ms}ms`}`);
|
|
79758
80249
|
console.log("Rows (local -> cloud):");
|
|
79759
80250
|
for (const entry2 of report.objects) {
|
|
79760
|
-
const flag = entry2.diff === 0 ? "" :
|
|
80251
|
+
const flag = entry2.diff === 0 ? "" : chalk29.yellow(` (diff ${entry2.diff > 0 ? "+" : ""}${entry2.diff})`);
|
|
79761
80252
|
console.log(` ${entry2.object_type.padEnd(14)} local=${String(entry2.local).padStart(6)} cloud=${String(entry2.cloud).padStart(6)} tombstones=${entry2.cloud_tombstones}${flag}`);
|
|
79762
80253
|
}
|
|
79763
80254
|
console.log(` ${"TOTAL".padEnd(14)} local=${String(report.totals.local).padStart(6)} cloud=${String(report.totals.cloud).padStart(6)} diff=${report.totals.diff}`);
|
|
@@ -79777,7 +80268,7 @@ function readOutboxDepth() {
|
|
|
79777
80268
|
}
|
|
79778
80269
|
}
|
|
79779
80270
|
function printArtifactPlan(plan) {
|
|
79780
|
-
console.log(
|
|
80271
|
+
console.log(chalk29.bold(`todos storage artifacts ${plan.direction}`));
|
|
79781
80272
|
console.log("Dry run: yes");
|
|
79782
80273
|
console.log("Network: not used");
|
|
79783
80274
|
console.log(`Total: ${plan.total}`);
|
|
@@ -79788,10 +80279,10 @@ function printArtifactPlan(plan) {
|
|
|
79788
80279
|
console.log(` ${artifact.status.padEnd(18)} ${artifact.id.slice(0, 8)} ${artifact.sha256?.slice(0, 12) ?? "no-sha"}`);
|
|
79789
80280
|
}
|
|
79790
80281
|
for (const error2 of plan.errors)
|
|
79791
|
-
console.error(
|
|
80282
|
+
console.error(chalk29.red(` ${error2}`));
|
|
79792
80283
|
}
|
|
79793
80284
|
function printArtifactResult(direction, result) {
|
|
79794
|
-
console.log(
|
|
80285
|
+
console.log(chalk29.bold(`todos storage artifacts ${direction}`));
|
|
79795
80286
|
console.log(`Uploaded: ${result.uploaded}`);
|
|
79796
80287
|
console.log(`Downloaded: ${result.downloaded}`);
|
|
79797
80288
|
console.log(`Skipped: ${result.skipped}`);
|
|
@@ -79799,7 +80290,7 @@ function printArtifactResult(direction, result) {
|
|
|
79799
80290
|
console.log(` ${artifact.id.slice(0, 8)} ${artifact.key}`);
|
|
79800
80291
|
}
|
|
79801
80292
|
for (const error2 of result.errors)
|
|
79802
|
-
console.error(
|
|
80293
|
+
console.error(chalk29.red(` ${error2}`));
|
|
79803
80294
|
}
|
|
79804
80295
|
function artifactFilter(opts) {
|
|
79805
80296
|
const limit = opts.limit ? Number.parseInt(opts.limit, 10) : undefined;
|
|
@@ -79878,7 +80369,7 @@ function registerStorageCommands(program2) {
|
|
|
79878
80369
|
return;
|
|
79879
80370
|
}
|
|
79880
80371
|
if (remoteAuthority.selected) {
|
|
79881
|
-
console.log(
|
|
80372
|
+
console.log(chalk29.bold("todos storage"));
|
|
79882
80373
|
console.log("Mode: http");
|
|
79883
80374
|
console.log("Transport: authenticated HTTP /v1");
|
|
79884
80375
|
console.log(`Authority: ${remoteAuthority.v1_base_url ?? "not configured"}`);
|
|
@@ -79886,7 +80377,7 @@ function registerStorageCommands(program2) {
|
|
|
79886
80377
|
console.log("Local fallback: disabled");
|
|
79887
80378
|
console.log("Network: not used (configuration diagnostic only)");
|
|
79888
80379
|
for (const issue of remoteAuthority.issues)
|
|
79889
|
-
console.error(
|
|
80380
|
+
console.error(chalk29.red(` ${issue}`));
|
|
79890
80381
|
if (!status.ok)
|
|
79891
80382
|
process.exitCode = 1;
|
|
79892
80383
|
return;
|
|
@@ -79931,7 +80422,7 @@ function registerStorageCommands(program2) {
|
|
|
79931
80422
|
output({ configured: false, message }, true);
|
|
79932
80423
|
return;
|
|
79933
80424
|
}
|
|
79934
|
-
console.log(
|
|
80425
|
+
console.log(chalk29.yellow(message));
|
|
79935
80426
|
return;
|
|
79936
80427
|
}
|
|
79937
80428
|
cloud = client;
|
|
@@ -79969,7 +80460,7 @@ function registerStorageCommands(program2) {
|
|
|
79969
80460
|
output({ shadow_enabled: false, message }, true);
|
|
79970
80461
|
return;
|
|
79971
80462
|
}
|
|
79972
|
-
console.log(
|
|
80463
|
+
console.log(chalk29.yellow(message));
|
|
79973
80464
|
return;
|
|
79974
80465
|
}
|
|
79975
80466
|
const { getDatabase: getDatabase2 } = await Promise.resolve().then(() => (init_database(), exports_database));
|
|
@@ -79981,7 +80472,7 @@ function registerStorageCommands(program2) {
|
|
|
79981
80472
|
output({ shadow_enabled: true, ...stats2 }, true);
|
|
79982
80473
|
return;
|
|
79983
80474
|
}
|
|
79984
|
-
console.log(
|
|
80475
|
+
console.log(chalk29.bold("todos storage shadow-drain"));
|
|
79985
80476
|
console.log(`Mirrored: ${stats2.mirrored}`);
|
|
79986
80477
|
console.log(`Retries: ${stats2.retries}`);
|
|
79987
80478
|
console.log(`Pending: ${stats2.pending}`);
|
|
@@ -79989,7 +80480,7 @@ function registerStorageCommands(program2) {
|
|
|
79989
80480
|
console.log(`Outbox depth: ${stats2.depth}`);
|
|
79990
80481
|
console.log(`Last mirror: ${stats2.lastMirrorAt ?? "never"}`);
|
|
79991
80482
|
if (stats2.lastError)
|
|
79992
|
-
console.error(
|
|
80483
|
+
console.error(chalk29.yellow(`Last error: ${stats2.lastError}`));
|
|
79993
80484
|
} catch (error2) {
|
|
79994
80485
|
handleError(error2);
|
|
79995
80486
|
}
|
|
@@ -80287,7 +80778,7 @@ var exports_scale_hardening_commands = {};
|
|
|
80287
80778
|
__export(exports_scale_hardening_commands, {
|
|
80288
80779
|
registerScaleHardeningCommands: () => registerScaleHardeningCommands
|
|
80289
80780
|
});
|
|
80290
|
-
import
|
|
80781
|
+
import chalk30 from "chalk";
|
|
80291
80782
|
function globalOptions8(program2) {
|
|
80292
80783
|
const command = program2;
|
|
80293
80784
|
return command.optsWithGlobals?.() ?? program2.opts();
|
|
@@ -80334,7 +80825,7 @@ function registerScaleHardeningCommands(program2) {
|
|
|
80334
80825
|
}
|
|
80335
80826
|
if (format !== "markdown")
|
|
80336
80827
|
throw new Error("--format must be json or markdown");
|
|
80337
|
-
console.log(
|
|
80828
|
+
console.log(chalk30.bold(`todos scale compaction
|
|
80338
80829
|
`));
|
|
80339
80830
|
console.log(`Mode: ${result.dry_run ? "dry run" : "applied"}`);
|
|
80340
80831
|
console.log(`Before: ${result.before.page_count} pages, ${result.before.freelist_count} free`);
|
|
@@ -80354,7 +80845,7 @@ var exports_pr_group_commands = {};
|
|
|
80354
80845
|
__export(exports_pr_group_commands, {
|
|
80355
80846
|
registerPrGroupCommands: () => registerPrGroupCommands
|
|
80356
80847
|
});
|
|
80357
|
-
import
|
|
80848
|
+
import chalk31 from "chalk";
|
|
80358
80849
|
function globalOptions9(program2) {
|
|
80359
80850
|
const command = program2;
|
|
80360
80851
|
return command.optsWithGlobals?.() ?? program2.opts();
|
|
@@ -80381,7 +80872,7 @@ function registerPrGroupCommands(program2) {
|
|
|
80381
80872
|
output(view, true);
|
|
80382
80873
|
return;
|
|
80383
80874
|
}
|
|
80384
|
-
console.log(`${
|
|
80875
|
+
console.log(`${chalk31.bold(view.group.id)} ${view.group.state} revision=${view.group.revision}`);
|
|
80385
80876
|
console.log(`authority=${view.authority} attempts=${view.attempts.length} events=${view.diagnostics.event_count}`);
|
|
80386
80877
|
} catch (error2) {
|
|
80387
80878
|
handleError(error2);
|
|
@@ -80399,7 +80890,7 @@ function registerPrGroupCommands(program2) {
|
|
|
80399
80890
|
output(history, true);
|
|
80400
80891
|
return;
|
|
80401
80892
|
}
|
|
80402
|
-
console.log(`${
|
|
80893
|
+
console.log(`${chalk31.bold(history.group_id)} events=${history.count} authority=${history.authority}`);
|
|
80403
80894
|
for (const event of history.events) {
|
|
80404
80895
|
console.log(`${String(event.sequence).padStart(4)} ${event.event_type} ${event.state}`);
|
|
80405
80896
|
}
|
|
@@ -80796,6 +81287,7 @@ var [
|
|
|
80796
81287
|
{ registerQueryCommands: registerQueryCommands2 },
|
|
80797
81288
|
{ registerMcpHooksCommands: registerMcpHooksCommands2 },
|
|
80798
81289
|
{ registerDispatchCommands: registerDispatchCommands2 },
|
|
81290
|
+
{ registerDelegateCommands: registerDelegateCommands2 },
|
|
80799
81291
|
{ registerMachineCommands: registerMachineCommands2 },
|
|
80800
81292
|
{ registerApiKeyCommands: registerApiKeyCommands2 },
|
|
80801
81293
|
{ registerEnvironmentSnapshotCommands: registerEnvironmentSnapshotCommands2 },
|
|
@@ -80827,6 +81319,7 @@ var [
|
|
|
80827
81319
|
Promise.resolve().then(() => (init_query_commands(), exports_query_commands)),
|
|
80828
81320
|
Promise.resolve().then(() => (init_mcp_hooks_commands(), exports_mcp_hooks_commands)),
|
|
80829
81321
|
Promise.resolve().then(() => (init_dispatch3(), exports_dispatch2)),
|
|
81322
|
+
Promise.resolve().then(() => (init_delegate(), exports_delegate)),
|
|
80830
81323
|
Promise.resolve().then(() => (init_machines3(), exports_machines)),
|
|
80831
81324
|
Promise.resolve().then(() => (init_api_key_commands(), exports_api_key_commands)),
|
|
80832
81325
|
Promise.resolve().then(() => (init_environment_snapshots3(), exports_environment_snapshots2)),
|
|
@@ -80857,6 +81350,7 @@ registerConfigServeCommands2(program2);
|
|
|
80857
81350
|
registerQueryCommands2(program2);
|
|
80858
81351
|
registerMcpHooksCommands2(program2);
|
|
80859
81352
|
registerDispatchCommands2(program2);
|
|
81353
|
+
registerDelegateCommands2(program2);
|
|
80860
81354
|
registerMachineCommands2(program2);
|
|
80861
81355
|
registerApiKeyCommands2(program2);
|
|
80862
81356
|
registerEnvironmentSnapshotCommands2(program2);
|