@hasna/todos 0.13.0 → 0.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/dist/cli/cloud-router.d.ts +21 -5
- package/dist/cli/cloud-router.d.ts.map +1 -1
- package/dist/cli/commands/config-serve-commands.d.ts.map +1 -1
- package/dist/cli/commands/project-commands.d.ts.map +1 -1
- package/dist/cli/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/index.js +468 -238
- package/dist/contracts.js +20 -10
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/task-crud.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +80 -13
- package/dist/lib/dependency-graph.d.ts +108 -0
- package/dist/lib/dependency-graph.d.ts.map +1 -1
- package/dist/lib/redaction.d.ts.map +1 -1
- package/dist/mcp/index.js +28 -13
- package/dist/mcp.js +2 -2
- package/dist/registry.js +20 -10
- package/dist/release-provenance.json +5 -5
- package/dist/server/index.js +65 -30
- package/dist/server/port.d.ts +52 -0
- package/dist/server/port.d.ts.map +1 -0
- package/dist/server/serve.d.ts.map +1 -1
- package/dist/storage/interfaces.d.ts +14 -0
- package/dist/storage/interfaces.d.ts.map +1 -1
- package/dist/storage.js +21 -9
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
* Local-only; machine-readable JSON for MCP and CLI.
|
|
4
4
|
*/
|
|
5
5
|
import type { Database } from "bun:sqlite";
|
|
6
|
+
import type { Task } from "../types/index.js";
|
|
6
7
|
export declare const DEPENDENCY_GRAPH_SCHEMA = "todos.dependency_graph.v1";
|
|
8
|
+
/** Machine-readable edge read for a single task (`todos deps <id> --json`). */
|
|
9
|
+
export declare const TASK_DEPENDENCY_EDGES_SCHEMA = "todos.task_dependency_edges.v1";
|
|
10
|
+
/** Machine-readable whole-project graph (`todos deps --project <ref> --json`). */
|
|
11
|
+
export declare const PROJECT_DEPENDENCY_GRAPH_SCHEMA = "todos.project_dependency_graph.v1";
|
|
7
12
|
export interface DependencyNode {
|
|
8
13
|
id: string;
|
|
9
14
|
short_id: string | null;
|
|
@@ -13,6 +18,63 @@ export interface DependencyNode {
|
|
|
13
18
|
plan_id: string | null;
|
|
14
19
|
project_id: string | null;
|
|
15
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* A single dependency edge: `task_id` depends on `depends_on` (the prerequisite
|
|
23
|
+
* must complete before the dependent can run). Same orientation as the
|
|
24
|
+
* `task_dependencies` table and the cloud `/v1/tasks/:id/dependencies` payload.
|
|
25
|
+
*/
|
|
26
|
+
export interface DependencyEdge {
|
|
27
|
+
task_id: string;
|
|
28
|
+
depends_on: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A task's direct dependency edges, resolved to nodes with id + status so a
|
|
32
|
+
* scheduler can honor ordering without a second lookup and without scraping
|
|
33
|
+
* human output.
|
|
34
|
+
*
|
|
35
|
+
* Field orientation — every name means exactly what it says (regression
|
|
36
|
+
* 4599ef37: `blocked_by` used to carry the DEPENDENTS, so schedulers consuming
|
|
37
|
+
* it by name gated the wrong side and deadlocked the upstream task of every
|
|
38
|
+
* chain):
|
|
39
|
+
* - `dependencies` = this task's PREREQUISITES (upstream). This task depends
|
|
40
|
+
* on them; they must complete first.
|
|
41
|
+
* - `blocked_by` = the subset of `dependencies` that is still incomplete —
|
|
42
|
+
* the tasks blocking this one RIGHT NOW. Empty means dispatchable. A
|
|
43
|
+
* completed or cancelled prerequisite no longer blocks (same rule as
|
|
44
|
+
* `getBlockedTasks`/`getBlockingDeps`).
|
|
45
|
+
* - `blocks` = this task's DEPENDENTS (downstream). They depend on this
|
|
46
|
+
* task; this task blocks THEM. Matches the human `Blocks:` output.
|
|
47
|
+
* A scheduler gating "is this runnable" cares about `blocked_by`.
|
|
48
|
+
*/
|
|
49
|
+
export interface TaskDependencyEdges {
|
|
50
|
+
schema_version: typeof TASK_DEPENDENCY_EDGES_SCHEMA;
|
|
51
|
+
task_id: string;
|
|
52
|
+
/**
|
|
53
|
+
* The root task's short id when the caller already holds the row (local
|
|
54
|
+
* store); `null` from a self-hosted authority, where surfacing it would cost
|
|
55
|
+
* an extra round trip and consumers key on `task_id` anyway.
|
|
56
|
+
*/
|
|
57
|
+
short_id: string | null;
|
|
58
|
+
dependencies: DependencyNode[];
|
|
59
|
+
blocked_by: DependencyNode[];
|
|
60
|
+
blocks: DependencyNode[];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The full dependency graph for a project in one read: every in-scope task as a
|
|
64
|
+
* node (with status) plus the adjacency list, so a scheduler can compute a
|
|
65
|
+
* runnable order and detect cycles in a single call. `edges` are the edges
|
|
66
|
+
* whose dependent (`task_id`) is one of `nodes`; a `depends_on` may reference a
|
|
67
|
+
* task outside `nodes` (a cross-project prerequisite). `cycles` are computed
|
|
68
|
+
* over exactly the returned `edges`.
|
|
69
|
+
*/
|
|
70
|
+
export interface ProjectDependencyGraph {
|
|
71
|
+
schema_version: typeof PROJECT_DEPENDENCY_GRAPH_SCHEMA;
|
|
72
|
+
generated_at: string;
|
|
73
|
+
project_id: string | null;
|
|
74
|
+
nodes: DependencyNode[];
|
|
75
|
+
edges: DependencyEdge[];
|
|
76
|
+
cycles: string[][];
|
|
77
|
+
}
|
|
16
78
|
export interface BlockedTaskReport {
|
|
17
79
|
schema_version: typeof DEPENDENCY_GRAPH_SCHEMA;
|
|
18
80
|
task: DependencyNode;
|
|
@@ -63,6 +125,18 @@ export interface GraphFilter {
|
|
|
63
125
|
status?: string[];
|
|
64
126
|
limit?: number;
|
|
65
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Project a full task row down to the compact {@link DependencyNode} used by the
|
|
130
|
+
* machine-readable dependency reads. Exported so callers that already hold task
|
|
131
|
+
* rows (e.g. the cloud CLI path hydrating remote edges) emit the same shape.
|
|
132
|
+
*/
|
|
133
|
+
export declare function toDependencyNode(task: Task): DependencyNode;
|
|
134
|
+
/**
|
|
135
|
+
* Detect dependency cycles over an explicit edge list (`task_id -> depends_on`).
|
|
136
|
+
* A `depends_on` that never appears as a `task_id` is a leaf (no outgoing
|
|
137
|
+
* edges), so a cycle is only reported when it is fully contained in `edges`.
|
|
138
|
+
*/
|
|
139
|
+
export declare function detectCyclesFromEdges(edges: DependencyEdge[]): string[][];
|
|
66
140
|
export declare function getReadyTasks(filter?: GraphFilter, db?: Database): ReadyTaskReport[];
|
|
67
141
|
export declare function getBlockedTaskReports(filter?: GraphFilter, db?: Database): BlockedTaskReport[];
|
|
68
142
|
export declare function getCriticalPath(filter?: GraphFilter, db?: Database): CriticalPathEntry[];
|
|
@@ -70,4 +144,38 @@ export declare function getUnlockImpact(taskId: string, db?: Database): UnlockIm
|
|
|
70
144
|
export declare function analyzeDependencyGraph(filter?: GraphFilter, db?: Database): DependencyGraphAnalysis;
|
|
71
145
|
export declare function getDependents(taskId: string, db?: Database): DependencyNode[];
|
|
72
146
|
export declare function getBlockers(taskId: string, db?: Database): BlockedTaskReport | null;
|
|
147
|
+
export { isBlockingDependencyStatus } from "../types/index.js";
|
|
148
|
+
/**
|
|
149
|
+
* Assemble a {@link TaskDependencyEdges} payload from already-resolved task
|
|
150
|
+
* rows. Pure (no DB access) so both the local reader below and the cloud CLI
|
|
151
|
+
* path — which hydrates remote edges via `cloudGetTaskRelations` — emit the
|
|
152
|
+
* identical versioned shape. `blocked_by` is derived here from the incomplete
|
|
153
|
+
* prerequisites so no caller can reintroduce the inverted orientation
|
|
154
|
+
* (regression 4599ef37).
|
|
155
|
+
*/
|
|
156
|
+
export declare function buildTaskDependencyEdges(task: {
|
|
157
|
+
id: string;
|
|
158
|
+
short_id: string | null;
|
|
159
|
+
}, dependencies: Task[], blocks: Task[]): TaskDependencyEdges;
|
|
160
|
+
/**
|
|
161
|
+
* Read a single task's direct dependency edges as a machine-readable,
|
|
162
|
+
* versioned payload (`todos deps <id> --json`). Returns `null` when the task
|
|
163
|
+
* does not exist. Edges whose target row is missing (a dangling dependency) are
|
|
164
|
+
* skipped here; use {@link analyzeDependencyGraph} for missing-edge reporting.
|
|
165
|
+
*/
|
|
166
|
+
export declare function getTaskDependencyEdges(taskId: string, db?: Database): TaskDependencyEdges | null;
|
|
167
|
+
/**
|
|
168
|
+
* Assemble a {@link ProjectDependencyGraph} from resolved nodes and edges.
|
|
169
|
+
* Pure (no DB access) so the local reader and the cloud CLI path share one
|
|
170
|
+
* shape. `edges` are filtered to those whose dependent (`task_id`) is a node;
|
|
171
|
+
* cycles are detected over that filtered set.
|
|
172
|
+
*/
|
|
173
|
+
export declare function buildProjectDependencyGraph(projectId: string | null, tasks: Task[], edges: DependencyEdge[], generatedAt?: string): ProjectDependencyGraph;
|
|
174
|
+
/**
|
|
175
|
+
* Read a whole project's dependency graph in one call (`todos deps --project
|
|
176
|
+
* <ref> --json`): every in-scope task as a node plus the adjacency list and any
|
|
177
|
+
* cycles. `filter.project_id` scopes the nodes; an absent scope reads every
|
|
178
|
+
* task in the local store.
|
|
179
|
+
*/
|
|
180
|
+
export declare function getProjectDependencyGraph(filter?: GraphFilter, db?: Database): ProjectDependencyGraph;
|
|
73
181
|
//# sourceMappingURL=dependency-graph.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-graph.d.ts","sourceRoot":"","sources":["../../src/lib/dependency-graph.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"dependency-graph.d.ts","sourceRoot":"","sources":["../../src/lib/dependency-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redaction.d.ts","sourceRoot":"","sources":["../../src/lib/redaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE9E,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;
|
|
1
|
+
{"version":3,"file":"redaction.d.ts","sourceRoot":"","sources":["../../src/lib/redaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE9E,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AA6FD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUxD;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAe1C;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE,CAOjE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,qBAAqB,IAAI,kBAAkB,CAK1D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,GAAG,kBAAkB,CAQtF"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -41,6 +41,9 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
41
41
|
var __require = import.meta.require;
|
|
42
42
|
|
|
43
43
|
// src/types/index.ts
|
|
44
|
+
function isBlockingDependencyStatus(status) {
|
|
45
|
+
return status !== "completed" && status !== "cancelled";
|
|
46
|
+
}
|
|
44
47
|
var TASK_STATUSES, VersionConflictError, TaskNotFoundError, ProjectNotFoundError, ResourceConflictError, PlanNotFoundError, LockError, AgentNotFoundError, IdentityAliasAmbiguousError, IdentityIdImmutableError, TaskListNotFoundError, DependencyCycleError, CompletionGuardError, DispatchNotFoundError;
|
|
45
48
|
var init_types = __esm(() => {
|
|
46
49
|
TASK_STATUSES = [
|
|
@@ -4131,8 +4134,8 @@ function ensureDir(filePath) {
|
|
|
4131
4134
|
function openDatabase(path) {
|
|
4132
4135
|
ensureDir(path);
|
|
4133
4136
|
const db = new Database(path);
|
|
4134
|
-
db.run("PRAGMA journal_mode = WAL");
|
|
4135
4137
|
db.run("PRAGMA busy_timeout = 5000");
|
|
4138
|
+
db.run("PRAGMA journal_mode = WAL");
|
|
4136
4139
|
db.run("PRAGMA foreign_keys = ON");
|
|
4137
4140
|
runMigrations(db);
|
|
4138
4141
|
ensureAgentIdentitySchema(db);
|
|
@@ -9107,11 +9110,15 @@ function secretPatterns() {
|
|
|
9107
9110
|
return [...customPatterns(), ...DEFAULT_SECRET_PATTERNS];
|
|
9108
9111
|
}
|
|
9109
9112
|
function isRedactionPlaceholderMatch(match) {
|
|
9110
|
-
const placeholder = String.raw`\[REDACTED(?:_[A-Z_]+)?\]`;
|
|
9111
9113
|
const trimmed = match.trim();
|
|
9112
|
-
return new RegExp(`^${
|
|
9114
|
+
return new RegExp(`^${REDACTION_PLACEHOLDER}$`).test(trimmed) || new RegExp(`=\\s*['"]?${REDACTION_PLACEHOLDER}['"]?$`).test(trimmed);
|
|
9115
|
+
}
|
|
9116
|
+
function isRedactionPlaceholderKey(key) {
|
|
9117
|
+
return new RegExp(`^${REDACTION_PLACEHOLDER}$`).test(key.trim());
|
|
9113
9118
|
}
|
|
9114
9119
|
function isSecretKey(key) {
|
|
9120
|
+
if (isRedactionPlaceholderKey(key))
|
|
9121
|
+
return false;
|
|
9115
9122
|
if (NON_SECRET_USAGE_KEYS.has(key.toLowerCase()))
|
|
9116
9123
|
return false;
|
|
9117
9124
|
if (DEFAULT_SECRET_KEY_PATTERN.test(key))
|
|
@@ -9169,7 +9176,7 @@ function upsertSecretSafetyConfig(input) {
|
|
|
9169
9176
|
saveConfig({ ...config, secret_safety: next });
|
|
9170
9177
|
return next;
|
|
9171
9178
|
}
|
|
9172
|
-
var DEFAULT_SECRET_PATTERNS, DEFAULT_SECRET_KEY_PATTERN, NON_SECRET_USAGE_KEYS;
|
|
9179
|
+
var DEFAULT_SECRET_PATTERNS, DEFAULT_SECRET_KEY_PATTERN, NON_SECRET_USAGE_KEYS, REDACTION_PLACEHOLDER;
|
|
9173
9180
|
var init_redaction = __esm(() => {
|
|
9174
9181
|
init_config2();
|
|
9175
9182
|
DEFAULT_SECRET_PATTERNS = [
|
|
@@ -9193,6 +9200,7 @@ var init_redaction = __esm(() => {
|
|
|
9193
9200
|
"completion_tokens",
|
|
9194
9201
|
"cost_tokens"
|
|
9195
9202
|
]);
|
|
9203
|
+
REDACTION_PLACEHOLDER = String.raw`\[REDACTED(?:_[A-Z_]+)?\]`;
|
|
9196
9204
|
});
|
|
9197
9205
|
|
|
9198
9206
|
// src/lib/secret-redaction.ts
|
|
@@ -9228,7 +9236,7 @@ function scanTextForSecrets(text, options = {}) {
|
|
|
9228
9236
|
};
|
|
9229
9237
|
}
|
|
9230
9238
|
function redactText(text, options = {}) {
|
|
9231
|
-
const placeholder = options.placeholder ??
|
|
9239
|
+
const placeholder = options.placeholder ?? REDACTION_PLACEHOLDER2;
|
|
9232
9240
|
let out = text;
|
|
9233
9241
|
for (const { pattern, allowlist_ok } of DEFAULT_PATTERNS) {
|
|
9234
9242
|
out = out.replace(new RegExp(pattern.source, pattern.flags), (match) => {
|
|
@@ -9255,7 +9263,7 @@ function redactExportRecord(record) {
|
|
|
9255
9263
|
}
|
|
9256
9264
|
return base;
|
|
9257
9265
|
}
|
|
9258
|
-
var SECRET_REDACTION_SCHEMA,
|
|
9266
|
+
var SECRET_REDACTION_SCHEMA, REDACTION_PLACEHOLDER2 = "[REDACTED]", DEFAULT_PATTERNS, DEFAULT_ALLOWLIST, customRedactors;
|
|
9259
9267
|
var init_secret_redaction = __esm(() => {
|
|
9260
9268
|
init_redaction();
|
|
9261
9269
|
SECRET_REDACTION_SCHEMA = ["todos", "secret_redaction", "v1"].join(".");
|
|
@@ -13420,10 +13428,11 @@ function getTaskWithRelations(id, db) {
|
|
|
13420
13428
|
JOIN task_dependencies td ON td.depends_on = t.id
|
|
13421
13429
|
WHERE td.task_id = ?`).all(id);
|
|
13422
13430
|
const dependencies = depRows.map(rowToTask);
|
|
13423
|
-
const
|
|
13431
|
+
const blocked_by = dependencies.filter((dep) => isBlockingDependencyStatus(dep.status));
|
|
13432
|
+
const blocksRows = d.query(`SELECT t.* FROM tasks t
|
|
13424
13433
|
JOIN task_dependencies td ON td.task_id = t.id
|
|
13425
13434
|
WHERE td.depends_on = ?`).all(id);
|
|
13426
|
-
const
|
|
13435
|
+
const blocks = blocksRows.map(rowToTask);
|
|
13427
13436
|
const comments = d.query("SELECT * FROM task_comments WHERE task_id = ? ORDER BY created_at").all(id);
|
|
13428
13437
|
const parent = task.parent_id ? getTask(task.parent_id, d) : null;
|
|
13429
13438
|
const checklist = getChecklist(id, d);
|
|
@@ -13432,6 +13441,7 @@ function getTaskWithRelations(id, db) {
|
|
|
13432
13441
|
subtasks,
|
|
13433
13442
|
dependencies,
|
|
13434
13443
|
blocked_by,
|
|
13444
|
+
blocks,
|
|
13435
13445
|
comments,
|
|
13436
13446
|
parent,
|
|
13437
13447
|
checklist
|
|
@@ -20421,6 +20431,7 @@ async function cloudResolveTaskListRef(client, ref, projectId) {
|
|
|
20421
20431
|
}
|
|
20422
20432
|
var UUID_RE, CLOUD_MODES, VALID_STORAGE_MODES, completionCapabilityCache;
|
|
20423
20433
|
var init_cloud_router = __esm(() => {
|
|
20434
|
+
init_types();
|
|
20424
20435
|
init_redaction();
|
|
20425
20436
|
init_http_client();
|
|
20426
20437
|
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -34187,7 +34198,7 @@ var package_default;
|
|
|
34187
34198
|
var init_package = __esm(() => {
|
|
34188
34199
|
package_default = {
|
|
34189
34200
|
name: "@hasna/todos",
|
|
34190
|
-
version: "0.13.
|
|
34201
|
+
version: "0.13.2",
|
|
34191
34202
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
34192
34203
|
type: "module",
|
|
34193
34204
|
main: "dist/index.js",
|
|
@@ -34239,7 +34250,7 @@ var init_package = __esm(() => {
|
|
|
34239
34250
|
"backfill:comment-redaction": "bun run src/server/index.ts redact-comments",
|
|
34240
34251
|
"generate:sdk": "bun run scripts/generate-sdk.ts",
|
|
34241
34252
|
"build:dashboard": "cd dashboard && bun install --frozen-lockfile && bun run build",
|
|
34242
|
-
typecheck: "tsc --noEmit",
|
|
34253
|
+
typecheck: "tsc --noEmit -p tsconfig.typecheck.json",
|
|
34243
34254
|
test: "bun test",
|
|
34244
34255
|
"test:no-cloud": "bun test src/no-cloud-boundary.test.ts src/local-first.test.ts src/lib/public-release-gate.test.ts",
|
|
34245
34256
|
"dev:cli": "bun run src/cli/index.tsx",
|
|
@@ -45832,9 +45843,11 @@ async function removeDependency2(taskId, dependsOn, store) {
|
|
|
45832
45843
|
}
|
|
45833
45844
|
async function listDependencies(taskId, store) {
|
|
45834
45845
|
const edges = await store.list("dependencies");
|
|
45846
|
+
const incoming = edges.filter((edge) => edge.depends_on === taskId).map((edge) => ({ task_id: edge.task_id, depends_on: edge.depends_on }));
|
|
45835
45847
|
return {
|
|
45836
45848
|
dependencies: edges.filter((edge) => edge.task_id === taskId).map((edge) => ({ task_id: edge.task_id, depends_on: edge.depends_on })),
|
|
45837
|
-
|
|
45849
|
+
blocks: incoming,
|
|
45850
|
+
blocked_by: incoming
|
|
45838
45851
|
};
|
|
45839
45852
|
}
|
|
45840
45853
|
async function addVerification(input, store, context) {
|
|
@@ -51489,7 +51502,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
51489
51502
|
const path = url.pathname;
|
|
51490
51503
|
const method = req.method;
|
|
51491
51504
|
const reqOrigin = req.headers.get("origin") || undefined;
|
|
51492
|
-
const corsHeaders = reqOrigin &&
|
|
51505
|
+
const corsHeaders = reqOrigin && reqOrigin === `http://localhost:${ctx.port}` ? {
|
|
51493
51506
|
"Access-Control-Allow-Origin": reqOrigin,
|
|
51494
51507
|
"Access-Control-Allow-Methods": "GET, POST, PATCH, DELETE, OPTIONS",
|
|
51495
51508
|
"Access-Control-Allow-Headers": "Content-Type, X-API-Key, Authorization",
|
|
@@ -51777,7 +51790,9 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
51777
51790
|
};
|
|
51778
51791
|
process.on("SIGINT", shutdown);
|
|
51779
51792
|
process.on("SIGTERM", shutdown);
|
|
51780
|
-
const
|
|
51793
|
+
const boundPort = server.port ?? port;
|
|
51794
|
+
ctx.port = boundPort;
|
|
51795
|
+
const serverUrl = `http://localhost:${boundPort}`;
|
|
51781
51796
|
console.log(`Todos Dashboard running at ${serverUrl}`);
|
|
51782
51797
|
if (shouldOpen) {
|
|
51783
51798
|
try {
|
package/dist/mcp.js
CHANGED
|
@@ -41,7 +41,7 @@ var __require = import.meta.require;
|
|
|
41
41
|
// package.json
|
|
42
42
|
var package_default = {
|
|
43
43
|
name: "@hasna/todos",
|
|
44
|
-
version: "0.13.
|
|
44
|
+
version: "0.13.2",
|
|
45
45
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
46
46
|
type: "module",
|
|
47
47
|
main: "dist/index.js",
|
|
@@ -93,7 +93,7 @@ var package_default = {
|
|
|
93
93
|
"backfill:comment-redaction": "bun run src/server/index.ts redact-comments",
|
|
94
94
|
"generate:sdk": "bun run scripts/generate-sdk.ts",
|
|
95
95
|
"build:dashboard": "cd dashboard && bun install --frozen-lockfile && bun run build",
|
|
96
|
-
typecheck: "tsc --noEmit",
|
|
96
|
+
typecheck: "tsc --noEmit -p tsconfig.typecheck.json",
|
|
97
97
|
test: "bun test",
|
|
98
98
|
"test:no-cloud": "bun test src/no-cloud-boundary.test.ts src/local-first.test.ts src/lib/public-release-gate.test.ts",
|
|
99
99
|
"dev:cli": "bun run src/cli/index.tsx",
|
package/dist/registry.js
CHANGED
|
@@ -3424,6 +3424,9 @@ var init_machines = __esm(() => {
|
|
|
3424
3424
|
});
|
|
3425
3425
|
|
|
3426
3426
|
// src/types/index.ts
|
|
3427
|
+
function isBlockingDependencyStatus(status) {
|
|
3428
|
+
return status !== "completed" && status !== "cancelled";
|
|
3429
|
+
}
|
|
3427
3430
|
var TASK_STATUSES, TASK_PRIORITIES, PLAN_STATUSES, VersionConflictError, TaskNotFoundError, ProjectNotFoundError, ResourceConflictError, PlanNotFoundError, LockError, AgentNotFoundError, IdentityAliasAmbiguousError, IdentityIdImmutableError, TaskListNotFoundError, DependencyCycleError, CompletionGuardError, DISPATCH_STATUSES, DispatchNotFoundError;
|
|
3428
3431
|
var init_types = __esm(() => {
|
|
3429
3432
|
TASK_STATUSES = [
|
|
@@ -4123,8 +4126,8 @@ function ensureDir(filePath) {
|
|
|
4123
4126
|
function openDatabase(path) {
|
|
4124
4127
|
ensureDir(path);
|
|
4125
4128
|
const db = new Database(path);
|
|
4126
|
-
db.run("PRAGMA journal_mode = WAL");
|
|
4127
4129
|
db.run("PRAGMA busy_timeout = 5000");
|
|
4130
|
+
db.run("PRAGMA journal_mode = WAL");
|
|
4128
4131
|
db.run("PRAGMA foreign_keys = ON");
|
|
4129
4132
|
runMigrations(db);
|
|
4130
4133
|
ensureAgentIdentitySchema(db);
|
|
@@ -4955,11 +4958,15 @@ function secretPatterns() {
|
|
|
4955
4958
|
return [...customPatterns(), ...DEFAULT_SECRET_PATTERNS];
|
|
4956
4959
|
}
|
|
4957
4960
|
function isRedactionPlaceholderMatch(match) {
|
|
4958
|
-
const placeholder = String.raw`\[REDACTED(?:_[A-Z_]+)?\]`;
|
|
4959
4961
|
const trimmed = match.trim();
|
|
4960
|
-
return new RegExp(`^${
|
|
4962
|
+
return new RegExp(`^${REDACTION_PLACEHOLDER}$`).test(trimmed) || new RegExp(`=\\s*['"]?${REDACTION_PLACEHOLDER}['"]?$`).test(trimmed);
|
|
4963
|
+
}
|
|
4964
|
+
function isRedactionPlaceholderKey(key) {
|
|
4965
|
+
return new RegExp(`^${REDACTION_PLACEHOLDER}$`).test(key.trim());
|
|
4961
4966
|
}
|
|
4962
4967
|
function isSecretKey(key) {
|
|
4968
|
+
if (isRedactionPlaceholderKey(key))
|
|
4969
|
+
return false;
|
|
4963
4970
|
if (NON_SECRET_USAGE_KEYS.has(key.toLowerCase()))
|
|
4964
4971
|
return false;
|
|
4965
4972
|
if (DEFAULT_SECRET_KEY_PATTERN.test(key))
|
|
@@ -5020,7 +5027,7 @@ function upsertSecretSafetyConfig(input) {
|
|
|
5020
5027
|
saveConfig({ ...config, secret_safety: next });
|
|
5021
5028
|
return next;
|
|
5022
5029
|
}
|
|
5023
|
-
var DEFAULT_SECRET_PATTERNS, DEFAULT_SECRET_KEY_PATTERN, NON_SECRET_USAGE_KEYS;
|
|
5030
|
+
var DEFAULT_SECRET_PATTERNS, DEFAULT_SECRET_KEY_PATTERN, NON_SECRET_USAGE_KEYS, REDACTION_PLACEHOLDER;
|
|
5024
5031
|
var init_redaction = __esm(() => {
|
|
5025
5032
|
init_config2();
|
|
5026
5033
|
DEFAULT_SECRET_PATTERNS = [
|
|
@@ -5044,6 +5051,7 @@ var init_redaction = __esm(() => {
|
|
|
5044
5051
|
"completion_tokens",
|
|
5045
5052
|
"cost_tokens"
|
|
5046
5053
|
]);
|
|
5054
|
+
REDACTION_PLACEHOLDER = String.raw`\[REDACTED(?:_[A-Z_]+)?\]`;
|
|
5047
5055
|
});
|
|
5048
5056
|
|
|
5049
5057
|
// src/lib/workspace-trust.ts
|
|
@@ -6683,7 +6691,7 @@ function scanTextForSecrets(text, options = {}) {
|
|
|
6683
6691
|
};
|
|
6684
6692
|
}
|
|
6685
6693
|
function redactText(text, options = {}) {
|
|
6686
|
-
const placeholder = options.placeholder ??
|
|
6694
|
+
const placeholder = options.placeholder ?? REDACTION_PLACEHOLDER2;
|
|
6687
6695
|
let out = text;
|
|
6688
6696
|
for (const { pattern, allowlist_ok } of DEFAULT_PATTERNS) {
|
|
6689
6697
|
out = out.replace(new RegExp(pattern.source, pattern.flags), (match) => {
|
|
@@ -6744,7 +6752,7 @@ function redactExportRecord(record) {
|
|
|
6744
6752
|
function getDefaultSecretPatterns() {
|
|
6745
6753
|
return DEFAULT_PATTERNS.map((p) => ({ name: p.name, source: p.pattern.source }));
|
|
6746
6754
|
}
|
|
6747
|
-
var SECRET_REDACTION_SCHEMA,
|
|
6755
|
+
var SECRET_REDACTION_SCHEMA, REDACTION_PLACEHOLDER2 = "[REDACTED]", DEFAULT_PATTERNS, DEFAULT_ALLOWLIST, customRedactors;
|
|
6748
6756
|
var init_secret_redaction = __esm(() => {
|
|
6749
6757
|
init_redaction();
|
|
6750
6758
|
SECRET_REDACTION_SCHEMA = ["todos", "secret_redaction", "v1"].join(".");
|
|
@@ -8801,10 +8809,11 @@ function getTaskWithRelations(id, db) {
|
|
|
8801
8809
|
JOIN task_dependencies td ON td.depends_on = t.id
|
|
8802
8810
|
WHERE td.task_id = ?`).all(id);
|
|
8803
8811
|
const dependencies = depRows.map(rowToTask);
|
|
8804
|
-
const
|
|
8812
|
+
const blocked_by = dependencies.filter((dep) => isBlockingDependencyStatus(dep.status));
|
|
8813
|
+
const blocksRows = d.query(`SELECT t.* FROM tasks t
|
|
8805
8814
|
JOIN task_dependencies td ON td.task_id = t.id
|
|
8806
8815
|
WHERE td.depends_on = ?`).all(id);
|
|
8807
|
-
const
|
|
8816
|
+
const blocks = blocksRows.map(rowToTask);
|
|
8808
8817
|
const comments = d.query("SELECT * FROM task_comments WHERE task_id = ? ORDER BY created_at").all(id);
|
|
8809
8818
|
const parent = task.parent_id ? getTask(task.parent_id, d) : null;
|
|
8810
8819
|
const checklist = getChecklist(id, d);
|
|
@@ -8813,6 +8822,7 @@ function getTaskWithRelations(id, db) {
|
|
|
8813
8822
|
subtasks,
|
|
8814
8823
|
dependencies,
|
|
8815
8824
|
blocked_by,
|
|
8825
|
+
blocks,
|
|
8816
8826
|
comments,
|
|
8817
8827
|
parent,
|
|
8818
8828
|
checklist
|
|
@@ -11823,7 +11833,7 @@ var init_tasks = __esm(() => {
|
|
|
11823
11833
|
// package.json
|
|
11824
11834
|
var package_default = {
|
|
11825
11835
|
name: "@hasna/todos",
|
|
11826
|
-
version: "0.13.
|
|
11836
|
+
version: "0.13.2",
|
|
11827
11837
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
11828
11838
|
type: "module",
|
|
11829
11839
|
main: "dist/index.js",
|
|
@@ -11875,7 +11885,7 @@ var package_default = {
|
|
|
11875
11885
|
"backfill:comment-redaction": "bun run src/server/index.ts redact-comments",
|
|
11876
11886
|
"generate:sdk": "bun run scripts/generate-sdk.ts",
|
|
11877
11887
|
"build:dashboard": "cd dashboard && bun install --frozen-lockfile && bun run build",
|
|
11878
|
-
typecheck: "tsc --noEmit",
|
|
11888
|
+
typecheck: "tsc --noEmit -p tsconfig.typecheck.json",
|
|
11879
11889
|
test: "bun test",
|
|
11880
11890
|
"test:no-cloud": "bun test src/no-cloud-boundary.test.ts src/local-first.test.ts src/lib/public-release-gate.test.ts",
|
|
11881
11891
|
"dev:cli": "bun run src/cli/index.tsx",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"packageName": "@hasna/todos",
|
|
3
|
-
"packageVersion": "0.13.
|
|
3
|
+
"packageVersion": "0.13.2",
|
|
4
4
|
"repository": "https://github.com/hasna/todos.git",
|
|
5
|
-
"gitCommit": "
|
|
6
|
-
"gitTree": "
|
|
7
|
-
"sourceTreeSha256": "
|
|
8
|
-
"generatedAt": "2026-07-
|
|
5
|
+
"gitCommit": "cb914c5f9ccfabb39983b5156f4c1cec78e00c1f",
|
|
6
|
+
"gitTree": "3693d6d0fd8f3bdd2581fc915e91264caf08760d",
|
|
7
|
+
"sourceTreeSha256": "4a1b890d4a3b4ffc73d605e7aa3ccbcba2deb6c72d3604a1db733b57c0c25e00",
|
|
8
|
+
"generatedAt": "2026-07-28T15:00:57.000Z"
|
|
9
9
|
}
|