@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.
@@ -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":"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"}
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;AAM3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,eAAO,MAAM,uBAAuB,8BAA8B,CAAC;AAEnE,+EAA+E;AAC/E,eAAO,MAAM,4BAA4B,mCAAmC,CAAC;AAE7E,kFAAkF;AAClF,eAAO,MAAM,+BAA+B,sCAAsC,CAAC;AAEnF,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,OAAO,4BAA4B,CAAC;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,MAAM,EAAE,cAAc,EAAE,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,OAAO,+BAA+B,CAAC;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,OAAO,uBAAuB,CAAC;IAC/C,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,cAAc,EAAE,cAAc,EAAE,CAAC;IACjC,oBAAoB,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,OAAO,uBAAuB,CAAC;IAC/C,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,OAAO,uBAAuB,CAAC;IAC/C,IAAI,EAAE,cAAc,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,OAAO,uBAAuB,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,mBAAmB,EAAE,cAAc,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,OAAO,uBAAuB,CAAC;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IACnB,oBAAoB,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzE,cAAc,EAAE,iBAAiB,EAAE,CAAC;IACpC,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,aAAa,EAAE,iBAAiB,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAcD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,cAAc,CAE3D;AAqCD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,EAAE,EAAE,CAoCzE;AAYD,wBAAgB,aAAa,CAAC,MAAM,GAAE,WAAgB,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,eAAe,EAAE,CAmBxF;AAED,wBAAgB,qBAAqB,CAAC,MAAM,GAAE,WAAgB,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,iBAAiB,EAAE,CA2BlG;AAkCD,wBAAgB,eAAe,CAAC,MAAM,GAAE,WAAgB,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,iBAAiB,EAAE,CAgB5F;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,kBAAkB,CAyBjF;AAED,wBAAgB,sBAAsB,CAAC,MAAM,GAAE,WAAgB,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,uBAAuB,CAoBvG;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,cAAc,EAAE,CAM7E;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,iBAAiB,GAAG,IAAI,CAenF;AAED,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAE/D;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAC7C,YAAY,EAAE,IAAI,EAAE,EACpB,MAAM,EAAE,IAAI,EAAE,GACb,mBAAmB,CASrB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,mBAAmB,GAAG,IAAI,CAahG;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,EAAE,IAAI,EAAE,EACb,KAAK,EAAE,cAAc,EAAE,EACvB,WAAW,GAAE,MAAiC,GAC7C,sBAAsB,CAaxB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,GAAE,WAAgB,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,sBAAsB,CAKzG"}
@@ -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;AAkED,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"}
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(`^${placeholder}$`).test(trimmed) || new RegExp(`=\\s*['"]?${placeholder}['"]?$`).test(trimmed);
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 ?? REDACTION_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, REDACTION_PLACEHOLDER = "[REDACTED]", DEFAULT_PATTERNS, DEFAULT_ALLOWLIST, customRedactors;
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 blockedByRows = d.query(`SELECT t.* FROM tasks t
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 blocked_by = blockedByRows.map(rowToTask);
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.0",
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
- blocked_by: edges.filter((edge) => edge.depends_on === taskId).map((edge) => ({ task_id: edge.task_id, depends_on: edge.depends_on }))
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 && (reqOrigin === `http://localhost:${port}` || reqOrigin === "http://localhost:0") ? {
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 serverUrl = `http://localhost:${port}`;
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.0",
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(`^${placeholder}$`).test(trimmed) || new RegExp(`=\\s*['"]?${placeholder}['"]?$`).test(trimmed);
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 ?? REDACTION_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, REDACTION_PLACEHOLDER = "[REDACTED]", DEFAULT_PATTERNS, DEFAULT_ALLOWLIST, customRedactors;
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 blockedByRows = d.query(`SELECT t.* FROM tasks t
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 blocked_by = blockedByRows.map(rowToTask);
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.0",
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.0",
3
+ "packageVersion": "0.13.2",
4
4
  "repository": "https://github.com/hasna/todos.git",
5
- "gitCommit": "f1e13ecb6f374dacff6905a78e7dbd60a92883bb",
6
- "gitTree": "e6d133cf8c25a83c7085b7edf52cb8a7e7745fdb",
7
- "sourceTreeSha256": "fa93e1e4b62bdd70bd753daf4e86b47ec2aa92a1e6a6f091a2924c30649391f4",
8
- "generatedAt": "2026-07-25T17:29:55.000Z"
5
+ "gitCommit": "cb914c5f9ccfabb39983b5156f4c1cec78e00c1f",
6
+ "gitTree": "3693d6d0fd8f3bdd2581fc915e91264caf08760d",
7
+ "sourceTreeSha256": "4a1b890d4a3b4ffc73d605e7aa3ccbcba2deb6c72d3604a1db733b57c0c25e00",
8
+ "generatedAt": "2026-07-28T15:00:57.000Z"
9
9
  }