@hasna/todos 0.15.19 → 0.15.20
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/cloud-router.d.ts +20 -1
- package/dist/cli/cloud-router.d.ts.map +1 -1
- package/dist/cli/commands/query-commands.d.ts.map +1 -1
- package/dist/cli/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/index.js +851 -47
- package/dist/cli/stage-a.d.ts +21 -10
- package/dist/cli/stage-a.d.ts.map +1 -1
- package/dist/contracts.js +228 -16
- package/dist/db/audit.d.ts +8 -0
- package/dist/db/audit.d.ts.map +1 -1
- package/dist/db/task-lifecycle.d.ts +7 -1
- package/dist/db/task-lifecycle.d.ts.map +1 -1
- package/dist/db/tasks.d.ts +1 -1
- package/dist/db/tasks.d.ts.map +1 -1
- package/dist/index.js +479 -20
- package/dist/lib/cli-help.d.ts +3 -2
- package/dist/lib/cli-help.d.ts.map +1 -1
- package/dist/lib/stale-lock-handoff.d.ts +25 -0
- package/dist/lib/stale-lock-handoff.d.ts.map +1 -0
- package/dist/mcp/index.js +702 -36
- package/dist/mcp.js +3 -1
- package/dist/project-registration.js +1147 -686
- package/dist/registry.js +228 -16
- package/dist/release-provenance.json +5 -5
- package/dist/sdk/index.js +7 -0
- package/dist/sdk/v1.generated.d.ts +27 -0
- package/dist/sdk/v1.generated.d.ts.map +1 -1
- package/dist/server/index.js +1035 -369
- package/dist/server/openapi.d.ts +182 -0
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage/audit-history-import.d.ts +14 -0
- package/dist/storage/audit-history-import.d.ts.map +1 -0
- package/dist/storage/interfaces.d.ts +12 -1
- package/dist/storage/interfaces.d.ts.map +1 -1
- package/dist/storage/local-sqlite.d.ts.map +1 -1
- package/dist/storage/postgres-adapter.d.ts.map +1 -1
- package/dist/storage/sqlite-snapshot.d.ts.map +1 -1
- package/dist/storage.js +476 -19
- package/dist/task-manifest.js +11 -1
- package/dist/types/index.d.ts +43 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -3662,7 +3662,7 @@ function isBlockingDependencyStatus(status) {
|
|
|
3662
3662
|
function isTerminalStatus(status) {
|
|
3663
3663
|
return status === "completed" || status === "failed" || status === "cancelled";
|
|
3664
3664
|
}
|
|
3665
|
-
var TASK_STATUSES, TASK_PRIORITIES, PLAN_STATUSES, VersionConflictError, TaskNotFoundError, TaskNotStartableError, TaskReferenceAmbiguousError, ProjectNotFoundError, ResourceConflictError, PlanRevisionConflictError, PlanNotFoundError, LockError, AgentNotFoundError, IdentityAliasAmbiguousError, IdentityIdImmutableError, TaskListNotFoundError, DependencyCycleError, CompletionGuardError, DISPATCH_STATUSES, DispatchNotFoundError;
|
|
3665
|
+
var TASK_STATUSES, TASK_PRIORITIES, PLAN_STATUSES, VersionConflictError, TaskNotFoundError, TaskNotStartableError, TaskReferenceAmbiguousError, ProjectNotFoundError, ResourceConflictError, PlanRevisionConflictError, PlanNotFoundError, LockError, StaleLockHandoffError, AgentNotFoundError, IdentityAliasAmbiguousError, IdentityIdImmutableError, TaskListNotFoundError, DependencyCycleError, CompletionGuardError, DISPATCH_STATUSES, DispatchNotFoundError;
|
|
3666
3666
|
var init_types = __esm(() => {
|
|
3667
3667
|
TASK_STATUSES = [
|
|
3668
3668
|
"pending",
|
|
@@ -3785,6 +3785,16 @@ var init_types = __esm(() => {
|
|
|
3785
3785
|
this.name = "LockError";
|
|
3786
3786
|
}
|
|
3787
3787
|
};
|
|
3788
|
+
StaleLockHandoffError = class StaleLockHandoffError extends Error {
|
|
3789
|
+
code;
|
|
3790
|
+
details;
|
|
3791
|
+
constructor(code, message, details = {}) {
|
|
3792
|
+
super(message);
|
|
3793
|
+
this.code = code;
|
|
3794
|
+
this.details = details;
|
|
3795
|
+
this.name = "StaleLockHandoffError";
|
|
3796
|
+
}
|
|
3797
|
+
};
|
|
3788
3798
|
AgentNotFoundError = class AgentNotFoundError extends Error {
|
|
3789
3799
|
agentId;
|
|
3790
3800
|
static code = "AGENT_NOT_FOUND";
|
|
@@ -7503,28 +7513,55 @@ var init_activity_audit = __esm(() => {
|
|
|
7503
7513
|
function sanitizeHistoryValue(value, context) {
|
|
7504
7514
|
return value === undefined || value === null ? null : sanitizePreWriteText(String(value), context);
|
|
7505
7515
|
}
|
|
7506
|
-
function
|
|
7516
|
+
function insertTaskHistory(entry, db) {
|
|
7507
7517
|
const d = db || getDatabase();
|
|
7508
|
-
const
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7518
|
+
const safeEntry = {
|
|
7519
|
+
...entry,
|
|
7520
|
+
field: entry.field || null,
|
|
7521
|
+
old_value: sanitizeHistoryValue(entry.old_value, "task_history.old_value"),
|
|
7522
|
+
new_value: sanitizeHistoryValue(entry.new_value, "task_history.new_value"),
|
|
7523
|
+
agent_id: entry.agent_id || null,
|
|
7524
|
+
machine_id: entry.machine_id ?? currentStorageMachineId(d)
|
|
7525
|
+
};
|
|
7513
7526
|
d.run(`INSERT INTO task_history (id, task_id, action, field, old_value, new_value, agent_id, created_at, machine_id)
|
|
7514
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
7527
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
7528
|
+
safeEntry.id,
|
|
7529
|
+
safeEntry.task_id,
|
|
7530
|
+
safeEntry.action,
|
|
7531
|
+
safeEntry.field,
|
|
7532
|
+
safeEntry.old_value,
|
|
7533
|
+
safeEntry.new_value,
|
|
7534
|
+
safeEntry.agent_id,
|
|
7535
|
+
safeEntry.created_at,
|
|
7536
|
+
safeEntry.machine_id ?? null
|
|
7537
|
+
]);
|
|
7515
7538
|
try {
|
|
7516
7539
|
const { logActivity: logActivity2 } = (init_activity_audit(), __toCommonJS(exports_activity_audit));
|
|
7517
7540
|
logActivity2({
|
|
7518
7541
|
entity_type: "task",
|
|
7519
|
-
entity_id:
|
|
7520
|
-
action,
|
|
7521
|
-
field:
|
|
7522
|
-
old_value:
|
|
7523
|
-
new_value:
|
|
7524
|
-
actor_id:
|
|
7542
|
+
entity_id: safeEntry.task_id,
|
|
7543
|
+
action: safeEntry.action,
|
|
7544
|
+
field: safeEntry.field ?? undefined,
|
|
7545
|
+
old_value: safeEntry.old_value,
|
|
7546
|
+
new_value: safeEntry.new_value,
|
|
7547
|
+
actor_id: safeEntry.agent_id ?? undefined
|
|
7525
7548
|
}, d);
|
|
7526
7549
|
} catch {}
|
|
7527
|
-
return
|
|
7550
|
+
return safeEntry;
|
|
7551
|
+
}
|
|
7552
|
+
function logTaskChange(taskId, action, field2, oldValue, newValue, agentId, db) {
|
|
7553
|
+
const d = db || getDatabase();
|
|
7554
|
+
return insertTaskHistory({
|
|
7555
|
+
id: uuid(),
|
|
7556
|
+
task_id: taskId,
|
|
7557
|
+
action,
|
|
7558
|
+
field: field2 || null,
|
|
7559
|
+
old_value: oldValue ?? null,
|
|
7560
|
+
new_value: newValue ?? null,
|
|
7561
|
+
agent_id: agentId || null,
|
|
7562
|
+
created_at: now(),
|
|
7563
|
+
machine_id: currentStorageMachineId(d)
|
|
7564
|
+
}, d);
|
|
7528
7565
|
}
|
|
7529
7566
|
function getTaskHistory(taskId, db) {
|
|
7530
7567
|
const d = db || getDatabase();
|
|
@@ -8547,6 +8584,145 @@ var init_task_graph = __esm(() => {
|
|
|
8547
8584
|
init_task_crud();
|
|
8548
8585
|
});
|
|
8549
8586
|
|
|
8587
|
+
// src/lib/stale-lock-handoff.ts
|
|
8588
|
+
function normalizeExactTaskId(value) {
|
|
8589
|
+
if (typeof value !== "string" || !EXACT_TASK_UUID_RE.test(value.trim())) {
|
|
8590
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_TASK_ID", "stale-lock handoff requires one exact full task UUID", { task_id: typeof value === "string" ? value : null });
|
|
8591
|
+
}
|
|
8592
|
+
return value.trim().toLowerCase();
|
|
8593
|
+
}
|
|
8594
|
+
function requireNonEmptyString(value, field2) {
|
|
8595
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
8596
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", `${field2} must be a non-empty string`, { field: field2 });
|
|
8597
|
+
}
|
|
8598
|
+
const trimmed = value.trim();
|
|
8599
|
+
if (field2 === "reason" && trimmed.length > MAX_REASON_LENGTH) {
|
|
8600
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", `reason must be at most ${MAX_REASON_LENGTH} characters`, { field: field2, max_length: MAX_REASON_LENGTH });
|
|
8601
|
+
}
|
|
8602
|
+
return trimmed;
|
|
8603
|
+
}
|
|
8604
|
+
function requireCanonicalLockVersion(value) {
|
|
8605
|
+
if (typeof value !== "string" || !CANONICAL_LOCK_VERSION_RE.test(value)) {
|
|
8606
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", "expected_lock_version must be the exact canonical locked_at timestamp (YYYY-MM-DDTHH:mm:ss.sssZ)", { field: "expected_lock_version" });
|
|
8607
|
+
}
|
|
8608
|
+
const parsed = Date.parse(value);
|
|
8609
|
+
if (Number.isNaN(parsed) || new Date(parsed).toISOString() !== value) {
|
|
8610
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", "expected_lock_version must name a real canonical UTC instant", { field: "expected_lock_version" });
|
|
8611
|
+
}
|
|
8612
|
+
return value;
|
|
8613
|
+
}
|
|
8614
|
+
function requireStaleThreshold(value) {
|
|
8615
|
+
if (!Number.isSafeInteger(value) || Number(value) <= 0) {
|
|
8616
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", "stale_after_seconds must be a positive safe integer", { field: "stale_after_seconds" });
|
|
8617
|
+
}
|
|
8618
|
+
return Number(value);
|
|
8619
|
+
}
|
|
8620
|
+
function prepareStaleLockHandoff(input, options = {}) {
|
|
8621
|
+
const taskId = normalizeExactTaskId(input.task_id);
|
|
8622
|
+
const actor = requireNonEmptyString(input.actor, "actor");
|
|
8623
|
+
const expectedHolder = requireNonEmptyString(input.expected_holder, "expected_holder");
|
|
8624
|
+
const newHolder = requireNonEmptyString(input.new_holder, "new_holder");
|
|
8625
|
+
const expectedLockVersion = requireCanonicalLockVersion(input.expected_lock_version);
|
|
8626
|
+
const staleAfterSeconds = requireStaleThreshold(input.stale_after_seconds);
|
|
8627
|
+
const reason = sanitizePreWriteText(requireNonEmptyString(input.reason, "reason"), "stale_lock_handoff.reason").trim();
|
|
8628
|
+
if (!reason) {
|
|
8629
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", "reason must remain non-empty after safety filtering", { field: "reason" });
|
|
8630
|
+
}
|
|
8631
|
+
if (canonicalAgentRef(actor) !== canonicalAgentRef(newHolder)) {
|
|
8632
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_ACTOR_MISMATCH", "new_holder must match the authenticated actor", { actor, new_holder: newHolder });
|
|
8633
|
+
}
|
|
8634
|
+
if (canonicalAgentRef(expectedHolder) === canonicalAgentRef(newHolder)) {
|
|
8635
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", "new_holder must differ from expected_holder", { field: "new_holder" });
|
|
8636
|
+
}
|
|
8637
|
+
const operationTimestamp = options.now ?? new Date().toISOString();
|
|
8638
|
+
if (!CANONICAL_LOCK_VERSION_RE.test(operationTimestamp) || new Date(Date.parse(operationTimestamp)).toISOString() !== operationTimestamp) {
|
|
8639
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", "operation timestamp must be a canonical UTC instant");
|
|
8640
|
+
}
|
|
8641
|
+
const staleCutoff = new Date(Date.parse(operationTimestamp) - staleAfterSeconds * 1000).toISOString();
|
|
8642
|
+
return {
|
|
8643
|
+
task_id: taskId,
|
|
8644
|
+
actor,
|
|
8645
|
+
expected_holder: expectedHolder,
|
|
8646
|
+
expected_lock_version: expectedLockVersion,
|
|
8647
|
+
stale_after_seconds: staleAfterSeconds,
|
|
8648
|
+
new_holder: newHolder,
|
|
8649
|
+
reason,
|
|
8650
|
+
operation_timestamp: operationTimestamp,
|
|
8651
|
+
stale_cutoff: staleCutoff,
|
|
8652
|
+
receipt_id: options.receiptId ?? crypto.randomUUID()
|
|
8653
|
+
};
|
|
8654
|
+
}
|
|
8655
|
+
function buildStaleLockHandoffReceipt(input) {
|
|
8656
|
+
return {
|
|
8657
|
+
schema_version: STALE_LOCK_HANDOFF_SCHEMA_VERSION,
|
|
8658
|
+
receipt_id: input.receipt_id,
|
|
8659
|
+
task_id: input.task_id,
|
|
8660
|
+
actor: input.actor,
|
|
8661
|
+
previous_holder: input.expected_holder,
|
|
8662
|
+
previous_lock_version: input.expected_lock_version,
|
|
8663
|
+
new_holder: input.new_holder,
|
|
8664
|
+
new_lock_version: input.operation_timestamp,
|
|
8665
|
+
stale_after_seconds: input.stale_after_seconds,
|
|
8666
|
+
stale_cutoff: input.stale_cutoff,
|
|
8667
|
+
reason: input.reason,
|
|
8668
|
+
created_at: input.operation_timestamp
|
|
8669
|
+
};
|
|
8670
|
+
}
|
|
8671
|
+
function staleLockHandoffHistory(receipt, machineId) {
|
|
8672
|
+
return {
|
|
8673
|
+
id: receipt.receipt_id,
|
|
8674
|
+
task_id: receipt.task_id,
|
|
8675
|
+
action: STALE_LOCK_HANDOFF_ACTION,
|
|
8676
|
+
field: STALE_LOCK_HANDOFF_FIELD,
|
|
8677
|
+
old_value: JSON.stringify({
|
|
8678
|
+
holder: receipt.previous_holder,
|
|
8679
|
+
lock_version: receipt.previous_lock_version
|
|
8680
|
+
}),
|
|
8681
|
+
new_value: JSON.stringify(receipt),
|
|
8682
|
+
agent_id: receipt.actor,
|
|
8683
|
+
created_at: receipt.created_at,
|
|
8684
|
+
machine_id: machineId
|
|
8685
|
+
};
|
|
8686
|
+
}
|
|
8687
|
+
function throwStaleLockHandoffConflict(task, input) {
|
|
8688
|
+
if (!task.locked_by || !task.locked_at) {
|
|
8689
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_NOT_LOCKED", `Task ${input.task_id} does not have a complete lock to hand off`, { task_id: input.task_id });
|
|
8690
|
+
}
|
|
8691
|
+
if (task.locked_at !== input.expected_lock_version) {
|
|
8692
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_VERSION_MISMATCH", `Task ${input.task_id} lock version changed`, {
|
|
8693
|
+
task_id: input.task_id,
|
|
8694
|
+
expected_lock_version: input.expected_lock_version,
|
|
8695
|
+
current_lock_version: task.locked_at
|
|
8696
|
+
});
|
|
8697
|
+
}
|
|
8698
|
+
if (task.locked_by !== input.expected_holder) {
|
|
8699
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_HOLDER_MISMATCH", `Task ${input.task_id} lock holder changed`, {
|
|
8700
|
+
task_id: input.task_id,
|
|
8701
|
+
expected_holder: input.expected_holder,
|
|
8702
|
+
current_holder: task.locked_by
|
|
8703
|
+
});
|
|
8704
|
+
}
|
|
8705
|
+
if (isTerminalStatus(task.status)) {
|
|
8706
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_TERMINAL", `Task ${input.task_id} is ${task.status} and cannot transfer a lock`, { task_id: input.task_id, status: task.status });
|
|
8707
|
+
}
|
|
8708
|
+
if (task.locked_at >= input.stale_cutoff) {
|
|
8709
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_NOT_STALE", `Task ${input.task_id} lock is not older than the supplied stale threshold`, {
|
|
8710
|
+
task_id: input.task_id,
|
|
8711
|
+
current_lock_version: task.locked_at,
|
|
8712
|
+
stale_cutoff: input.stale_cutoff
|
|
8713
|
+
});
|
|
8714
|
+
}
|
|
8715
|
+
throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_CONFLICT", `Task ${input.task_id} changed during stale-lock handoff`, { task_id: input.task_id });
|
|
8716
|
+
}
|
|
8717
|
+
var STALE_LOCK_HANDOFF_SCHEMA_VERSION = "todos.stale-lock-handoff.v1", STALE_LOCK_HANDOFF_ACTION = "stale_lock_handoff", STALE_LOCK_HANDOFF_FIELD = "lock", EXACT_TASK_UUID_RE, CANONICAL_LOCK_VERSION_RE, MAX_REASON_LENGTH = 4096;
|
|
8718
|
+
var init_stale_lock_handoff = __esm(() => {
|
|
8719
|
+
init_types();
|
|
8720
|
+
init_creator_identity();
|
|
8721
|
+
init_prewrite_secrets();
|
|
8722
|
+
EXACT_TASK_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8723
|
+
CANONICAL_LOCK_VERSION_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
8724
|
+
});
|
|
8725
|
+
|
|
8550
8726
|
// src/db/task-lifecycle.ts
|
|
8551
8727
|
var exports_task_lifecycle = {};
|
|
8552
8728
|
__export(exports_task_lifecycle, {
|
|
@@ -8555,6 +8731,7 @@ __export(exports_task_lifecycle, {
|
|
|
8555
8731
|
startTask: () => startTask,
|
|
8556
8732
|
spawnNextRecurrence: () => spawnNextRecurrence,
|
|
8557
8733
|
lockTask: () => lockTask,
|
|
8734
|
+
handoffStaleTaskLock: () => handoffStaleTaskLock,
|
|
8558
8735
|
getTasksChangedSince: () => getTasksChangedSince,
|
|
8559
8736
|
getTaskLockStatus: () => getTaskLockStatus,
|
|
8560
8737
|
getStaleTasks: () => getStaleTasks,
|
|
@@ -8823,6 +9000,38 @@ function unlockTask(id, agentId, db) {
|
|
|
8823
9000
|
WHERE id = ?`, [timestamp2, id]);
|
|
8824
9001
|
return true;
|
|
8825
9002
|
}
|
|
9003
|
+
function handoffStaleTaskLock(input, db) {
|
|
9004
|
+
const d = db || getDatabase();
|
|
9005
|
+
const prepared = prepareStaleLockHandoff(input);
|
|
9006
|
+
const receipt = buildStaleLockHandoffReceipt(prepared);
|
|
9007
|
+
const history = staleLockHandoffHistory(receipt, null);
|
|
9008
|
+
const transfer = d.transaction(() => {
|
|
9009
|
+
const result = d.run(`UPDATE tasks
|
|
9010
|
+
SET locked_by = ?, locked_at = ?, updated_at = ?, version = version + 1
|
|
9011
|
+
WHERE id = ?
|
|
9012
|
+
AND locked_by = ?
|
|
9013
|
+
AND locked_at = ?
|
|
9014
|
+
AND julianday(locked_at) < julianday(?)
|
|
9015
|
+
AND status NOT IN ('completed', 'failed', 'cancelled')`, [
|
|
9016
|
+
prepared.new_holder,
|
|
9017
|
+
prepared.operation_timestamp,
|
|
9018
|
+
prepared.operation_timestamp,
|
|
9019
|
+
prepared.task_id,
|
|
9020
|
+
prepared.expected_holder,
|
|
9021
|
+
prepared.expected_lock_version,
|
|
9022
|
+
prepared.stale_cutoff
|
|
9023
|
+
]);
|
|
9024
|
+
if (result.changes === 0) {
|
|
9025
|
+
const current = getTask(prepared.task_id, d);
|
|
9026
|
+
if (!current)
|
|
9027
|
+
throw new TaskNotFoundError(prepared.task_id);
|
|
9028
|
+
throwStaleLockHandoffConflict(current, prepared);
|
|
9029
|
+
}
|
|
9030
|
+
insertTaskHistory(history, d);
|
|
9031
|
+
});
|
|
9032
|
+
transfer();
|
|
9033
|
+
return receipt;
|
|
9034
|
+
}
|
|
8826
9035
|
function getTaskLockStatus(id, db) {
|
|
8827
9036
|
const d = db || getDatabase();
|
|
8828
9037
|
const task = getTask(id, d);
|
|
@@ -9123,6 +9332,7 @@ var init_task_lifecycle = __esm(() => {
|
|
|
9123
9332
|
init_task_crud();
|
|
9124
9333
|
init_task_graph();
|
|
9125
9334
|
init_prewrite_secrets();
|
|
9335
|
+
init_stale_lock_handoff();
|
|
9126
9336
|
});
|
|
9127
9337
|
|
|
9128
9338
|
// src/db/task-crud.ts
|
|
@@ -12548,7 +12758,7 @@ var init_dispatches = __esm(() => {
|
|
|
12548
12758
|
// package.json
|
|
12549
12759
|
var package_default = {
|
|
12550
12760
|
name: "@hasna/todos",
|
|
12551
|
-
version: "0.15.
|
|
12761
|
+
version: "0.15.20",
|
|
12552
12762
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
12553
12763
|
type: "module",
|
|
12554
12764
|
main: "dist/index.js",
|
|
@@ -12619,6 +12829,8 @@ var package_default = {
|
|
|
12619
12829
|
"dev:mcp": "bun run src/mcp/index.ts",
|
|
12620
12830
|
"dev:serve": "bun run src/server/index.ts",
|
|
12621
12831
|
"verify:release": "bun run scripts/verify-public-release.ts --mode=review",
|
|
12832
|
+
"verify:release-review": "bun run scripts/verify-npm-release-agent-review.ts",
|
|
12833
|
+
"issue:release-review": "bun run scripts/issue-npm-release-agent-review.ts",
|
|
12622
12834
|
prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
|
|
12623
12835
|
postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
|
|
12624
12836
|
},
|
|
@@ -25619,6 +25831,36 @@ init_task_lists();
|
|
|
25619
25831
|
init_tasks();
|
|
25620
25832
|
init_templates();
|
|
25621
25833
|
init_storage_tombstones();
|
|
25834
|
+
|
|
25835
|
+
// src/storage/audit-history-import.ts
|
|
25836
|
+
var AUDIT_HISTORY_DIVERGENT_REPLAY = "AUDIT_HISTORY_DIVERGENT_REPLAY";
|
|
25837
|
+
var AUDIT_HISTORY_TOMBSTONE_FORBIDDEN = "AUDIT_HISTORY_TOMBSTONE_FORBIDDEN";
|
|
25838
|
+
var AUDIT_HISTORY_FIELDS = [
|
|
25839
|
+
"id",
|
|
25840
|
+
"task_id",
|
|
25841
|
+
"action",
|
|
25842
|
+
"field",
|
|
25843
|
+
"old_value",
|
|
25844
|
+
"new_value",
|
|
25845
|
+
"agent_id",
|
|
25846
|
+
"created_at",
|
|
25847
|
+
"machine_id"
|
|
25848
|
+
];
|
|
25849
|
+
function auditHistoryRowsAreFieldIdentical(left, right) {
|
|
25850
|
+
return AUDIT_HISTORY_FIELDS.every((field2) => {
|
|
25851
|
+
const leftValue = field2 === "machine_id" ? left[field2] ?? null : left[field2];
|
|
25852
|
+
const rightValue = field2 === "machine_id" ? right[field2] ?? null : right[field2];
|
|
25853
|
+
return leftValue === rightValue;
|
|
25854
|
+
});
|
|
25855
|
+
}
|
|
25856
|
+
function divergentAuditHistoryReplayError(id) {
|
|
25857
|
+
return `${AUDIT_HISTORY_DIVERGENT_REPLAY}: immutable audit_history row ${id} differs from stored row`;
|
|
25858
|
+
}
|
|
25859
|
+
function forbiddenAuditHistoryTombstoneError(id) {
|
|
25860
|
+
return `${AUDIT_HISTORY_TOMBSTONE_FORBIDDEN}: audit_history tombstone ${id} is not allowed`;
|
|
25861
|
+
}
|
|
25862
|
+
|
|
25863
|
+
// src/storage/sqlite-snapshot.ts
|
|
25622
25864
|
var PROJECT_COLUMNS = [
|
|
25623
25865
|
"id",
|
|
25624
25866
|
"name",
|
|
@@ -25819,8 +26061,11 @@ function importSqliteTodosStorageSnapshot(snapshot, db) {
|
|
|
25819
26061
|
const existingTaskLists = d.query("SELECT id, project_id, slug FROM task_lists").all();
|
|
25820
26062
|
result.errors.push(...validateSnapshotRoutingDestinationConflicts(snapshot.projects, snapshot.taskLists, existingProjects, existingTaskLists));
|
|
25821
26063
|
}
|
|
26064
|
+
const auditImport = preflightAuditHistoryImport(d, snapshot.auditHistory, snapshot.tombstones ?? []);
|
|
26065
|
+
result.errors.push(...auditImport.errors);
|
|
25822
26066
|
if (result.errors.length > 0)
|
|
25823
26067
|
return result;
|
|
26068
|
+
result.skipped += auditImport.identicalReplayCount;
|
|
25824
26069
|
const applyRows = (objectType, table, columns, rows, updateClockColumn, acceptEqualClock = true, afterUpsert) => {
|
|
25825
26070
|
for (const row of rows) {
|
|
25826
26071
|
try {
|
|
@@ -25855,10 +26100,72 @@ function importSqliteTodosStorageSnapshot(snapshot, db) {
|
|
|
25855
26100
|
replaceTaskTags(row["id"], row["tags"].filter((tag) => typeof tag === "string"), d);
|
|
25856
26101
|
}
|
|
25857
26102
|
});
|
|
25858
|
-
|
|
26103
|
+
insertAuditHistoryRows(d, auditImport.rowsToInsert, result);
|
|
25859
26104
|
applyTombstones(d, snapshot.tombstones ?? [], result);
|
|
25860
26105
|
return result;
|
|
25861
26106
|
}
|
|
26107
|
+
function preflightAuditHistoryImport(db, rows, tombstones) {
|
|
26108
|
+
const errors = tombstones.filter((tombstone) => tombstone.object_type === "audit_history").map((tombstone) => forbiddenAuditHistoryTombstoneError(tombstone.object_id));
|
|
26109
|
+
const rowsToInsert = [];
|
|
26110
|
+
const seen = new Map;
|
|
26111
|
+
let identicalReplayCount = 0;
|
|
26112
|
+
for (const rawRow of rows) {
|
|
26113
|
+
try {
|
|
26114
|
+
const row = asRecord2(rawRow);
|
|
26115
|
+
if (typeof row.id !== "string" || !row.id) {
|
|
26116
|
+
throw new Error("task_history row is missing id");
|
|
26117
|
+
}
|
|
26118
|
+
const prior = seen.get(row.id);
|
|
26119
|
+
if (prior) {
|
|
26120
|
+
if (auditHistoryRowsAreFieldIdentical(prior, row))
|
|
26121
|
+
identicalReplayCount += 1;
|
|
26122
|
+
else
|
|
26123
|
+
errors.push(divergentAuditHistoryReplayError(row.id));
|
|
26124
|
+
continue;
|
|
26125
|
+
}
|
|
26126
|
+
seen.set(row.id, row);
|
|
26127
|
+
const existing = getAuditHistoryById(db, row.id);
|
|
26128
|
+
if (!existing) {
|
|
26129
|
+
rowsToInsert.push(row);
|
|
26130
|
+
} else if (auditHistoryRowsAreFieldIdentical(existing, row)) {
|
|
26131
|
+
identicalReplayCount += 1;
|
|
26132
|
+
} else {
|
|
26133
|
+
errors.push(divergentAuditHistoryReplayError(row.id));
|
|
26134
|
+
}
|
|
26135
|
+
} catch (error) {
|
|
26136
|
+
errors.push(error instanceof Error ? error.message : String(error));
|
|
26137
|
+
}
|
|
26138
|
+
}
|
|
26139
|
+
return { rowsToInsert, identicalReplayCount, errors };
|
|
26140
|
+
}
|
|
26141
|
+
function insertAuditHistoryRows(db, rows, result) {
|
|
26142
|
+
for (const rawRow of rows) {
|
|
26143
|
+
try {
|
|
26144
|
+
const row = asRecord2(rawRow);
|
|
26145
|
+
const presentColumns = AUDIT_COLUMNS.filter((column) => (column in row));
|
|
26146
|
+
if (!presentColumns.includes("id"))
|
|
26147
|
+
presentColumns.unshift("id");
|
|
26148
|
+
const placeholders = presentColumns.map(() => "?").join(", ");
|
|
26149
|
+
const values = presentColumns.map((column) => valueForColumn(column, row[column]));
|
|
26150
|
+
const changes = db.run(`INSERT OR IGNORE INTO task_history (${presentColumns.join(", ")}) VALUES (${placeholders})`, values).changes;
|
|
26151
|
+
if (changes > 0) {
|
|
26152
|
+
result.inserted += 1;
|
|
26153
|
+
continue;
|
|
26154
|
+
}
|
|
26155
|
+
const existing = getAuditHistoryById(db, String(row["id"]));
|
|
26156
|
+
if (existing && auditHistoryRowsAreFieldIdentical(existing, row)) {
|
|
26157
|
+
result.skipped += 1;
|
|
26158
|
+
} else {
|
|
26159
|
+
result.errors.push(divergentAuditHistoryReplayError(String(row["id"])));
|
|
26160
|
+
}
|
|
26161
|
+
} catch (error) {
|
|
26162
|
+
result.errors.push(error instanceof Error ? error.message : String(error));
|
|
26163
|
+
}
|
|
26164
|
+
}
|
|
26165
|
+
}
|
|
26166
|
+
function getAuditHistoryById(db, id) {
|
|
26167
|
+
return db.query(`SELECT ${AUDIT_COLUMNS.join(", ")} FROM task_history WHERE id = ? LIMIT 1`).get(id);
|
|
26168
|
+
}
|
|
25862
26169
|
function upsertById(db, table, columns, row, updateClockColumn, acceptEqualClock = true) {
|
|
25863
26170
|
const id = row["id"];
|
|
25864
26171
|
if (typeof id !== "string" || !id)
|
|
@@ -25956,7 +26263,7 @@ function tableForTombstone(objectType) {
|
|
|
25956
26263
|
return "task_templates";
|
|
25957
26264
|
if (objectType === "template_tasks")
|
|
25958
26265
|
return "template_tasks";
|
|
25959
|
-
|
|
26266
|
+
throw new Error(`unsupported storage tombstone object_type: ${String(objectType)}`);
|
|
25960
26267
|
}
|
|
25961
26268
|
function listRows(db, table, columns) {
|
|
25962
26269
|
return db.query(`SELECT ${columns.join(", ")} FROM ${table} ORDER BY id`).all();
|
|
@@ -26088,6 +26395,7 @@ function createLocalSqliteTodosStorageAdapter(options = {}) {
|
|
|
26088
26395
|
unlockTask(id, agentId, database());
|
|
26089
26396
|
return true;
|
|
26090
26397
|
},
|
|
26398
|
+
handoffStaleLock: (input) => handoffStaleTaskLock(input, database()),
|
|
26091
26399
|
delete: (id) => deleteTask(id, database()),
|
|
26092
26400
|
start: (id, agentId) => startTask(id, agentId, database()),
|
|
26093
26401
|
complete: (id, agentId, options2) => completeTask(id, agentId, database(), options2),
|
|
@@ -26185,6 +26493,7 @@ function createLocalSqliteTodosStorageAdapter(options = {}) {
|
|
|
26185
26493
|
init_types();
|
|
26186
26494
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
26187
26495
|
init_creator_identity();
|
|
26496
|
+
init_stale_lock_handoff();
|
|
26188
26497
|
|
|
26189
26498
|
// src/storage/postgres-sync.ts
|
|
26190
26499
|
var DEFAULT_TODOS_POSTGRES_SYNC_TABLE = "todos_sync_records";
|
|
@@ -26620,6 +26929,7 @@ function createPostgresTodosStorageAdapter(options) {
|
|
|
26620
26929
|
getChangedSince: (since, filters) => getChangedSince(since, filters, store),
|
|
26621
26930
|
lock: (id, agentId) => lockTask2(id, agentId, store),
|
|
26622
26931
|
unlock: (id, agentId) => unlockTask2(id, agentId, store),
|
|
26932
|
+
handoffStaleLock: (input, context) => store.handoffStaleLock(input, context),
|
|
26623
26933
|
getByFingerprint: (fingerprint2) => store.getTaskByFingerprint(fingerprint2)
|
|
26624
26934
|
},
|
|
26625
26935
|
dependencies: {
|
|
@@ -26766,6 +27076,91 @@ class PostgresJsonRecordStore {
|
|
|
26766
27076
|
LIMIT 1`, [this.service, type, id]);
|
|
26767
27077
|
return result.rows[0] ? payloadRecord2(result.rows[0].payload) : null;
|
|
26768
27078
|
}
|
|
27079
|
+
async handoffStaleLock(input, context = {}) {
|
|
27080
|
+
const prepared = prepareStaleLockHandoff(input);
|
|
27081
|
+
const receipt = buildStaleLockHandoffReceipt(prepared);
|
|
27082
|
+
const history = staleLockHandoffHistory(receipt, this.machineId(context));
|
|
27083
|
+
await this.ensureSchema();
|
|
27084
|
+
const result = await this.options.client.query(`/* todos:stale-lock-handoff-atomic */ WITH
|
|
27085
|
+
target AS MATERIALIZED (
|
|
27086
|
+
SELECT payload
|
|
27087
|
+
FROM ${this.tableName}
|
|
27088
|
+
WHERE service = $1
|
|
27089
|
+
AND object_type = 'tasks'
|
|
27090
|
+
AND object_id = $2
|
|
27091
|
+
AND deleted_at IS NULL
|
|
27092
|
+
FOR UPDATE
|
|
27093
|
+
),
|
|
27094
|
+
updated AS (
|
|
27095
|
+
UPDATE ${this.tableName} AS task_record
|
|
27096
|
+
SET payload = jsonb_set(
|
|
27097
|
+
jsonb_set(
|
|
27098
|
+
jsonb_set(
|
|
27099
|
+
jsonb_set(
|
|
27100
|
+
task_record.payload,
|
|
27101
|
+
'{locked_by}',
|
|
27102
|
+
to_jsonb($6::text),
|
|
27103
|
+
true
|
|
27104
|
+
),
|
|
27105
|
+
'{locked_at}',
|
|
27106
|
+
to_jsonb($7::text),
|
|
27107
|
+
true
|
|
27108
|
+
),
|
|
27109
|
+
'{updated_at}',
|
|
27110
|
+
to_jsonb($7::text),
|
|
27111
|
+
true
|
|
27112
|
+
),
|
|
27113
|
+
'{version}',
|
|
27114
|
+
to_jsonb(COALESCE((task_record.payload->>'version')::integer, 0) + 1),
|
|
27115
|
+
true
|
|
27116
|
+
),
|
|
27117
|
+
updated_at = $7::timestamptz,
|
|
27118
|
+
source_machine_id = $10,
|
|
27119
|
+
version = COALESCE(task_record.version, 0) + 1
|
|
27120
|
+
FROM target
|
|
27121
|
+
WHERE task_record.service = $1
|
|
27122
|
+
AND task_record.object_type = 'tasks'
|
|
27123
|
+
AND task_record.object_id = $2
|
|
27124
|
+
AND task_record.deleted_at IS NULL
|
|
27125
|
+
AND target.payload->>'locked_by' = $3
|
|
27126
|
+
AND target.payload->>'locked_at' = $4
|
|
27127
|
+
AND todos_try_timestamptz(target.payload->>'locked_at') < $5::timestamptz
|
|
27128
|
+
AND COALESCE(target.payload->>'status', '') NOT IN ('completed', 'failed', 'cancelled')
|
|
27129
|
+
RETURNING task_record.payload
|
|
27130
|
+
),
|
|
27131
|
+
audit AS (
|
|
27132
|
+
INSERT INTO ${this.tableName} (
|
|
27133
|
+
service, object_type, object_id, payload, updated_at,
|
|
27134
|
+
deleted_at, source_machine_id, version
|
|
27135
|
+
)
|
|
27136
|
+
SELECT $1, 'audit_history', $8, $9::jsonb, $7::timestamptz,
|
|
27137
|
+
NULL, $10, NULL
|
|
27138
|
+
FROM updated
|
|
27139
|
+
RETURNING payload
|
|
27140
|
+
)
|
|
27141
|
+
SELECT
|
|
27142
|
+
(SELECT payload FROM target) AS current_payload,
|
|
27143
|
+
(SELECT payload FROM updated) AS updated_payload,
|
|
27144
|
+
(SELECT payload FROM audit) AS audit_payload`, [
|
|
27145
|
+
this.service,
|
|
27146
|
+
prepared.task_id,
|
|
27147
|
+
prepared.expected_holder,
|
|
27148
|
+
prepared.expected_lock_version,
|
|
27149
|
+
prepared.stale_cutoff,
|
|
27150
|
+
prepared.new_holder,
|
|
27151
|
+
prepared.operation_timestamp,
|
|
27152
|
+
receipt.receipt_id,
|
|
27153
|
+
jsonbParam(history),
|
|
27154
|
+
this.machineId(context)
|
|
27155
|
+
]);
|
|
27156
|
+
const row = result.rows[0];
|
|
27157
|
+
if (!row?.current_payload)
|
|
27158
|
+
throw new TaskNotFoundError(prepared.task_id);
|
|
27159
|
+
if (!row.updated_payload || !row.audit_payload) {
|
|
27160
|
+
throwStaleLockHandoffConflict(payloadRecord2(row.current_payload), prepared);
|
|
27161
|
+
}
|
|
27162
|
+
return receipt;
|
|
27163
|
+
}
|
|
26769
27164
|
async list(type) {
|
|
26770
27165
|
return (await this.listRecords(type)).map((record) => record.payload);
|
|
26771
27166
|
}
|
|
@@ -27035,6 +27430,28 @@ class PostgresJsonRecordStore {
|
|
|
27035
27430
|
}
|
|
27036
27431
|
return value;
|
|
27037
27432
|
}
|
|
27433
|
+
async insertImmutableAuditHistory(value, context = {}) {
|
|
27434
|
+
await this.ensureSchema();
|
|
27435
|
+
const inserted = await this.options.client.query(`INSERT INTO ${this.tableName} (
|
|
27436
|
+
service, object_type, object_id, payload, updated_at,
|
|
27437
|
+
deleted_at, source_machine_id, version
|
|
27438
|
+
) VALUES ($1, $2, $3, $4::jsonb, $5::timestamptz, NULL, $6, NULL)
|
|
27439
|
+
ON CONFLICT (service, object_type, object_id) DO NOTHING
|
|
27440
|
+
RETURNING object_id`, [
|
|
27441
|
+
this.service,
|
|
27442
|
+
"audit_history",
|
|
27443
|
+
value.id,
|
|
27444
|
+
jsonbParam(value),
|
|
27445
|
+
value.created_at,
|
|
27446
|
+
context.requestId ?? this.sourceMachineId ?? null
|
|
27447
|
+
]);
|
|
27448
|
+
if (inserted.rows.length > 0)
|
|
27449
|
+
return "inserted";
|
|
27450
|
+
const existing = await this.get("audit_history", value.id);
|
|
27451
|
+
if (existing && auditHistoryRowsAreFieldIdentical(existing, value))
|
|
27452
|
+
return "identical";
|
|
27453
|
+
throw new Error(divergentAuditHistoryReplayError(value.id));
|
|
27454
|
+
}
|
|
27038
27455
|
async upsertTaskWithPlanMembershipGuard(value, guardedPlanIds, explicitProject, context = {}) {
|
|
27039
27456
|
const planIds = [...new Set(guardedPlanIds.filter(Boolean))].sort();
|
|
27040
27457
|
if (planIds.length === 0)
|
|
@@ -28526,6 +28943,11 @@ async function importSnapshot(snapshot, store, context) {
|
|
|
28526
28943
|
result.errors.push(...validateSnapshotRoutingDestinationConflicts(snapshot.projects, snapshot.taskLists, existingProjects, existingTaskLists));
|
|
28527
28944
|
if (result.errors.length > 0)
|
|
28528
28945
|
return result;
|
|
28946
|
+
const auditHistory = await preflightAuditHistoryImport2(snapshot.auditHistory, snapshot.tombstones ?? [], store);
|
|
28947
|
+
result.errors.push(...auditHistory.errors);
|
|
28948
|
+
if (result.errors.length > 0)
|
|
28949
|
+
return result;
|
|
28950
|
+
result.skipped += auditHistory.identical;
|
|
28529
28951
|
const entries = [
|
|
28530
28952
|
...snapshot.tasks.map((row) => ["tasks", row]),
|
|
28531
28953
|
...snapshot.projects.map((row) => ["projects", row]),
|
|
@@ -28534,9 +28956,20 @@ async function importSnapshot(snapshot, store, context) {
|
|
|
28534
28956
|
...snapshot.agents.map((row) => ["agents", row]),
|
|
28535
28957
|
...snapshot.taskLists.map((row) => ["task_lists", row]),
|
|
28536
28958
|
...snapshot.templates.map((row) => ["templates", row]),
|
|
28537
|
-
...(snapshot.templateTasks ?? []).map((row) => ["template_tasks", row])
|
|
28538
|
-
...snapshot.auditHistory.map((row) => ["audit_history", row])
|
|
28959
|
+
...(snapshot.templateTasks ?? []).map((row) => ["template_tasks", row])
|
|
28539
28960
|
];
|
|
28961
|
+
for (const row of auditHistory.rowsToInsert) {
|
|
28962
|
+
try {
|
|
28963
|
+
const outcome = await store.insertImmutableAuditHistory(row, context);
|
|
28964
|
+
if (outcome === "inserted")
|
|
28965
|
+
result.inserted += 1;
|
|
28966
|
+
else
|
|
28967
|
+
result.skipped += 1;
|
|
28968
|
+
} catch (error) {
|
|
28969
|
+
result.errors.push(error instanceof Error ? error.message : String(error));
|
|
28970
|
+
return result;
|
|
28971
|
+
}
|
|
28972
|
+
}
|
|
28540
28973
|
for (const [type, row] of entries) {
|
|
28541
28974
|
try {
|
|
28542
28975
|
const existing = await store.get(type, row.id);
|
|
@@ -28570,6 +29003,32 @@ async function importSnapshot(snapshot, store, context) {
|
|
|
28570
29003
|
}
|
|
28571
29004
|
return result;
|
|
28572
29005
|
}
|
|
29006
|
+
async function preflightAuditHistoryImport2(rows, tombstones, store) {
|
|
29007
|
+
const errors = tombstones.filter((tombstone) => tombstone.object_type === "audit_history").map((tombstone) => forbiddenAuditHistoryTombstoneError(tombstone.object_id));
|
|
29008
|
+
const rowsToInsert = [];
|
|
29009
|
+
const seen = new Map;
|
|
29010
|
+
let identical = 0;
|
|
29011
|
+
for (const row of rows) {
|
|
29012
|
+
const prior = seen.get(row.id);
|
|
29013
|
+
if (prior) {
|
|
29014
|
+
if (auditHistoryRowsAreFieldIdentical(prior, row))
|
|
29015
|
+
identical += 1;
|
|
29016
|
+
else
|
|
29017
|
+
errors.push(divergentAuditHistoryReplayError(row.id));
|
|
29018
|
+
continue;
|
|
29019
|
+
}
|
|
29020
|
+
seen.set(row.id, row);
|
|
29021
|
+
const existing = await store.get("audit_history", row.id);
|
|
29022
|
+
if (!existing) {
|
|
29023
|
+
rowsToInsert.push(row);
|
|
29024
|
+
} else if (auditHistoryRowsAreFieldIdentical(existing, row)) {
|
|
29025
|
+
identical += 1;
|
|
29026
|
+
} else {
|
|
29027
|
+
errors.push(divergentAuditHistoryReplayError(row.id));
|
|
29028
|
+
}
|
|
29029
|
+
}
|
|
29030
|
+
return { rowsToInsert, identical, errors };
|
|
29031
|
+
}
|
|
28573
29032
|
async function requireRecord(type, id, store) {
|
|
28574
29033
|
const record = await store.get(type, id);
|
|
28575
29034
|
if (!record)
|
package/dist/lib/cli-help.d.ts
CHANGED
|
@@ -36,8 +36,9 @@ export interface CreateCliManualOptions {
|
|
|
36
36
|
/**
|
|
37
37
|
* Predicate deciding whether a top-level command is advertised in the manual.
|
|
38
38
|
* Defaults to advertising everything (local route). In a remote route the
|
|
39
|
-
* caller passes the authority visibility predicate so the manual
|
|
40
|
-
*
|
|
39
|
+
* caller passes the authority visibility predicate so the manual describes
|
|
40
|
+
* the shared authority surface; explicitly named local-only commands select a
|
|
41
|
+
* separate local route.
|
|
41
42
|
*/
|
|
42
43
|
isCommandVisible?: (topLevelCommand: string) => boolean;
|
|
43
44
|
/** Whether the resolved route serves entirely from local state. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-help.d.ts","sourceRoot":"","sources":["../../src/lib/cli-help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAEjD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,iBAAiB,EAAE,eAAe,EAAE,CAAC;IACrC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjD,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED,eAAO,MAAM,iBAAiB,EAAE,eAAe,EAA4B,CAAC;AAoC5E,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,GAAE,MAAM,EAAO,GAAG,eAAe,EAAE,CAenG;AAED,MAAM,WAAW,sBAAsB;IACrC
|
|
1
|
+
{"version":3,"file":"cli-help.d.ts","sourceRoot":"","sources":["../../src/lib/cli-help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAEjD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,iBAAiB,EAAE,eAAe,EAAE,CAAC;IACrC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjD,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED,eAAO,MAAM,iBAAiB,EAAE,eAAe,EAA4B,CAAC;AAoC5E,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,GAAE,MAAM,EAAO,GAAG,eAAe,EAAE,CAenG;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,OAAO,CAAC;IACxD,mEAAmE;IACnE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAOD,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,sBAA2B,GAAG,SAAS,CAoBjG;AAMD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CA+DjE;AA+BD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,eAAe,EACtB,gBAAgB,GAAE,CAAC,eAAe,EAAE,MAAM,KAAK,OAAoB,GAClE,MAAM,CAwFR"}
|