@hasna/todos 0.11.90 → 0.11.92

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.
Files changed (37) hide show
  1. package/README.md +7 -2
  2. package/dist/cli/cloud-router.d.ts +57 -25
  3. package/dist/cli/cloud-router.d.ts.map +1 -1
  4. package/dist/cli/commands/agent-commands.d.ts.map +1 -1
  5. package/dist/cli/commands/plan-template-commands.d.ts.map +1 -1
  6. package/dist/cli/commands/project-commands.d.ts.map +1 -1
  7. package/dist/cli/commands/query-commands.d.ts.map +1 -1
  8. package/dist/cli/commands/storage-commands.d.ts.map +1 -1
  9. package/dist/cli/commands/task-commands.d.ts.map +1 -1
  10. package/dist/cli/helpers.d.ts +15 -1
  11. package/dist/cli/helpers.d.ts.map +1 -1
  12. package/dist/cli/index.js +19594 -30654
  13. package/dist/cli/output-redaction.d.ts +5 -0
  14. package/dist/cli/output-redaction.d.ts.map +1 -0
  15. package/dist/cli/stage-a.d.ts +45 -0
  16. package/dist/cli/stage-a.d.ts.map +1 -0
  17. package/dist/contracts.js +196 -97
  18. package/dist/index.js +517 -313
  19. package/dist/lib/package-version.d.ts +1 -1
  20. package/dist/lib/package-version.d.ts.map +1 -1
  21. package/dist/lib/redaction.d.ts.map +1 -1
  22. package/dist/lib/tmux.d.ts.map +1 -1
  23. package/dist/mcp/index.js +837 -6847
  24. package/dist/mcp.js +118 -20
  25. package/dist/registry.js +196 -97
  26. package/dist/release-provenance.json +5 -3
  27. package/dist/sdk/index.js +37 -2
  28. package/dist/sdk/v1.generated.d.ts +72 -3
  29. package/dist/sdk/v1.generated.d.ts.map +1 -1
  30. package/dist/server/index.js +2213 -8136
  31. package/dist/server/openapi.d.ts +366 -2
  32. package/dist/server/openapi.d.ts.map +1 -1
  33. package/dist/server/v1.d.ts.map +1 -1
  34. package/dist/storage.js +112 -14
  35. package/dist/types/index.d.ts +2 -2
  36. package/dist/types/index.d.ts.map +1 -1
  37. package/package.json +9 -6
package/dist/contracts.js CHANGED
@@ -2427,7 +2427,7 @@ var init_schema = __esm(() => {
2427
2427
  });
2428
2428
 
2429
2429
  // src/db/machines.ts
2430
- import { existsSync as existsSync2 } from "fs";
2430
+ import { existsSync } from "fs";
2431
2431
  import { hostname as osHostname, platform as osPlatform, arch as osArch } from "os";
2432
2432
  import { resolve } from "path";
2433
2433
  import { spawnSync } from "child_process";
@@ -2637,7 +2637,7 @@ function getMachineTopologyDiagnostics(opts = {}, db, at = new Date) {
2637
2637
  message: `${project.name} has ${distinctPaths.length} different machine-local paths`
2638
2638
  });
2639
2639
  }
2640
- if (localRow && !existsSync2(localRow.path)) {
2640
+ if (localRow && !existsSync(localRow.path)) {
2641
2641
  pathIssues.push({
2642
2642
  type: "path_missing",
2643
2643
  project_id: project.id,
@@ -2648,7 +2648,7 @@ function getMachineTopologyDiagnostics(opts = {}, db, at = new Date) {
2648
2648
  message: `Local path does not exist on this machine: ${localRow.path}`
2649
2649
  });
2650
2650
  }
2651
- if (!localRow && project.path && machineById.has(localMachine.id) && !existsSync2(project.path)) {
2651
+ if (!localRow && project.path && machineById.has(localMachine.id) && !existsSync(project.path)) {
2652
2652
  pathIssues.push({
2653
2653
  type: "path_missing",
2654
2654
  project_id: project.id,
@@ -3036,8 +3036,8 @@ __export(exports_database, {
3036
3036
  LOCK_EXPIRY_MINUTES: () => LOCK_EXPIRY_MINUTES
3037
3037
  });
3038
3038
  import { Database } from "bun:sqlite";
3039
- import { existsSync as existsSync3, mkdirSync } from "fs";
3040
- import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
3039
+ import { existsSync as existsSync2, mkdirSync } from "fs";
3040
+ import { dirname, join, resolve as resolve2 } from "path";
3041
3041
  function isInMemoryDb(path) {
3042
3042
  return path === ":memory:" || path.startsWith("file::memory:");
3043
3043
  }
@@ -3046,12 +3046,12 @@ function findNearestProjectDb(startDir) {
3046
3046
  const stopAt = gitRoot ? resolve2(gitRoot) : resolve2(startDir);
3047
3047
  let dir = resolve2(startDir);
3048
3048
  while (true) {
3049
- const candidate = join2(dir, ".hasna", "todos", "todos.db");
3050
- if (existsSync3(candidate))
3049
+ const candidate = join(dir, ".hasna", "todos", "todos.db");
3050
+ if (existsSync2(candidate))
3051
3051
  return candidate;
3052
3052
  if (dir === stopAt)
3053
3053
  break;
3054
- const parent = dirname2(dir);
3054
+ const parent = dirname(dir);
3055
3055
  if (parent === dir)
3056
3056
  break;
3057
3057
  dir = parent;
@@ -3061,9 +3061,9 @@ function findNearestProjectDb(startDir) {
3061
3061
  function findGitRoot(startDir) {
3062
3062
  let dir = resolve2(startDir);
3063
3063
  while (true) {
3064
- if (existsSync3(join2(dir, ".git")))
3064
+ if (existsSync2(join(dir, ".git")))
3065
3065
  return dir;
3066
- const parent = dirname2(dir);
3066
+ const parent = dirname(dir);
3067
3067
  if (parent === dir)
3068
3068
  break;
3069
3069
  dir = parent;
@@ -3084,11 +3084,11 @@ function getDbPath() {
3084
3084
  if (process.env["TODOS_DB_SCOPE"] === "project") {
3085
3085
  const gitRoot = findGitRoot(cwd);
3086
3086
  if (gitRoot) {
3087
- return join2(gitRoot, ".hasna", "todos", "todos.db");
3087
+ return join(gitRoot, ".hasna", "todos", "todos.db");
3088
3088
  }
3089
3089
  }
3090
3090
  const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
3091
- return join2(home, ".hasna", "todos", "todos.db");
3091
+ return join(home, ".hasna", "todos", "todos.db");
3092
3092
  }
3093
3093
  function getDatabasePath() {
3094
3094
  return getDbPath();
@@ -3096,8 +3096,8 @@ function getDatabasePath() {
3096
3096
  function ensureDir(filePath) {
3097
3097
  if (isInMemoryDb(filePath))
3098
3098
  return;
3099
- const dir = dirname2(resolve2(filePath));
3100
- if (!existsSync3(dir)) {
3099
+ const dir = dirname(resolve2(filePath));
3100
+ if (!existsSync2(dir)) {
3101
3101
  mkdirSync(dir, { recursive: true });
3102
3102
  }
3103
3103
  }
@@ -3368,26 +3368,26 @@ var init_types = __esm(() => {
3368
3368
  });
3369
3369
 
3370
3370
  // src/lib/sync-utils.ts
3371
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, readdirSync, statSync, writeFileSync } from "fs";
3372
- import { join as join3 } from "path";
3371
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
3372
+ import { join as join2 } from "path";
3373
3373
  function getHomeDir() {
3374
3374
  return process.env["HOME"] || process.env["USERPROFILE"] || "~";
3375
3375
  }
3376
3376
  function getTodosGlobalDir() {
3377
- return join3(getHomeDir(), ".hasna", "todos");
3377
+ return join2(getHomeDir(), ".hasna", "todos");
3378
3378
  }
3379
3379
  function ensureDir2(dir) {
3380
- if (!existsSync4(dir))
3380
+ if (!existsSync3(dir))
3381
3381
  mkdirSync2(dir, { recursive: true });
3382
3382
  }
3383
3383
  function listJsonFiles(dir) {
3384
- if (!existsSync4(dir))
3384
+ if (!existsSync3(dir))
3385
3385
  return [];
3386
3386
  return readdirSync(dir).filter((f) => f.endsWith(".json"));
3387
3387
  }
3388
3388
  function readJsonFile(path) {
3389
3389
  try {
3390
- return JSON.parse(readFileSync2(path, "utf-8"));
3390
+ return JSON.parse(readFileSync(path, "utf-8"));
3391
3391
  } catch {
3392
3392
  return null;
3393
3393
  }
@@ -3397,14 +3397,14 @@ function writeJsonFile(path, data) {
3397
3397
  `);
3398
3398
  }
3399
3399
  function readHighWaterMark(dir) {
3400
- const path = join3(dir, ".highwatermark");
3401
- if (!existsSync4(path))
3400
+ const path = join2(dir, ".highwatermark");
3401
+ if (!existsSync3(path))
3402
3402
  return 1;
3403
- const val = parseInt(readFileSync2(path, "utf-8").trim(), 10);
3403
+ const val = parseInt(readFileSync(path, "utf-8").trim(), 10);
3404
3404
  return isNaN(val) ? 1 : val;
3405
3405
  }
3406
3406
  function writeHighWaterMark(dir, value) {
3407
- writeFileSync(join3(dir, ".highwatermark"), String(value));
3407
+ writeFileSync(join2(dir, ".highwatermark"), String(value));
3408
3408
  }
3409
3409
  function getFileMtimeMs(path) {
3410
3410
  try {
@@ -3430,10 +3430,10 @@ var init_sync_utils = __esm(() => {
3430
3430
  });
3431
3431
 
3432
3432
  // src/lib/config.ts
3433
- import { existsSync as existsSync5 } from "fs";
3434
- import { dirname as dirname3, join as join4 } from "path";
3433
+ import { existsSync as existsSync4 } from "fs";
3434
+ import { dirname as dirname2, join as join3 } from "path";
3435
3435
  function getConfigPath() {
3436
- return join4(getTodosGlobalDir(), "config.json");
3436
+ return join3(getTodosGlobalDir(), "config.json");
3437
3437
  }
3438
3438
  function normalizeAgent(agent) {
3439
3439
  return agent.trim().toLowerCase();
@@ -3441,7 +3441,7 @@ function normalizeAgent(agent) {
3441
3441
  function loadConfig() {
3442
3442
  if (cached)
3443
3443
  return cached;
3444
- if (!existsSync5(getConfigPath())) {
3444
+ if (!existsSync4(getConfigPath())) {
3445
3445
  cached = {};
3446
3446
  return cached;
3447
3447
  }
@@ -3454,7 +3454,7 @@ function loadConfig() {
3454
3454
  }
3455
3455
  function saveConfig(config) {
3456
3456
  const configPath = getConfigPath();
3457
- ensureDir2(dirname3(configPath));
3457
+ ensureDir2(dirname2(configPath));
3458
3458
  writeJsonFile(configPath, config);
3459
3459
  cached = config;
3460
3460
  return config;
@@ -4139,7 +4139,8 @@ var init_redaction = __esm(() => {
4139
4139
  "input_tokens",
4140
4140
  "output_tokens",
4141
4141
  "prompt_tokens",
4142
- "completion_tokens"
4142
+ "completion_tokens",
4143
+ "cost_tokens"
4143
4144
  ]);
4144
4145
  });
4145
4146
 
@@ -4523,7 +4524,7 @@ var init_runner_sandbox = __esm(() => {
4523
4524
  // src/lib/event-hooks.ts
4524
4525
  import { createHash, randomUUID } from "crypto";
4525
4526
  import { appendFileSync, mkdirSync as mkdirSync3 } from "fs";
4526
- import { dirname as dirname4, resolve as resolve6 } from "path";
4527
+ import { dirname as dirname3, resolve as resolve6 } from "path";
4527
4528
  import { createConnection } from "net";
4528
4529
  function safeName(name) {
4529
4530
  const trimmed = name.trim();
@@ -4662,7 +4663,7 @@ async function deliverHook(hook, envelope) {
4662
4663
  output = line.trim();
4663
4664
  } else if (hook.target === "file") {
4664
4665
  const filePath = resolve6(hook.file_path);
4665
- mkdirSync3(dirname4(filePath), { recursive: true });
4666
+ mkdirSync3(dirname3(filePath), { recursive: true });
4666
4667
  appendFileSync(filePath, line);
4667
4668
  } else if (hook.target === "socket") {
4668
4669
  await writeSocket(hook.socket_path, line);
@@ -4781,9 +4782,9 @@ var init_event_hooks = __esm(() => {
4781
4782
 
4782
4783
  // node_modules/.bun/@hasna+events@0.1.11/node_modules/@hasna/events/dist/index.js
4783
4784
  import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
4784
- import { existsSync as existsSync6 } from "fs";
4785
+ import { existsSync as existsSync5 } from "fs";
4785
4786
  import { homedir } from "os";
4786
- import { join as join5 } from "path";
4787
+ import { join as join4 } from "path";
4787
4788
  import { createHmac, timingSafeEqual } from "crypto";
4788
4789
  import { randomUUID as randomUUID2 } from "crypto";
4789
4790
  import { spawn } from "child_process";
@@ -4884,7 +4885,7 @@ function channelMatchesEvent(channel, event) {
4884
4885
  return channel.filters.some((filter) => eventMatchesFilter(event, filter));
4885
4886
  }
4886
4887
  function getEventsDataDir(override) {
4887
- return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join5(homedir(), ".hasna", "events");
4888
+ return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join4(homedir(), ".hasna", "events");
4888
4889
  }
4889
4890
 
4890
4891
  class JsonEventsStore {
@@ -4894,9 +4895,9 @@ class JsonEventsStore {
4894
4895
  deliveriesPath;
4895
4896
  constructor(dataDir = getEventsDataDir()) {
4896
4897
  this.dataDir = dataDir;
4897
- this.channelsPath = join5(dataDir, "channels.json");
4898
- this.eventsPath = join5(dataDir, "events.json");
4899
- this.deliveriesPath = join5(dataDir, "deliveries.json");
4898
+ this.channelsPath = join4(dataDir, "channels.json");
4899
+ this.eventsPath = join4(dataDir, "events.json");
4900
+ this.deliveriesPath = join4(dataDir, "deliveries.json");
4900
4901
  }
4901
4902
  async init() {
4902
4903
  await mkdir(this.dataDir, { recursive: true, mode: 448 });
@@ -4968,7 +4969,7 @@ class JsonEventsStore {
4968
4969
  };
4969
4970
  }
4970
4971
  async ensureArrayFile(path) {
4971
- if (!existsSync6(path)) {
4972
+ if (!existsSync5(path)) {
4972
4973
  await writeFile(path, `[]
4973
4974
  `, { encoding: "utf-8", mode: 384 });
4974
4975
  }
@@ -5741,7 +5742,7 @@ var init_shared_events = __esm(() => {
5741
5742
  });
5742
5743
 
5743
5744
  // src/lib/secret-redaction.ts
5744
- import { readFileSync as readFileSync3, existsSync as existsSync7 } from "fs";
5745
+ import { readFileSync as readFileSync2, existsSync as existsSync6 } from "fs";
5745
5746
  function registerCustomRedactor(fn) {
5746
5747
  customRedactors.push(fn);
5747
5748
  }
@@ -5806,9 +5807,9 @@ function scanAndRedactText(text, options = {}) {
5806
5807
  };
5807
5808
  }
5808
5809
  function scanFileForSecrets(path, options = {}) {
5809
- if (!existsSync7(path))
5810
+ if (!existsSync6(path))
5810
5811
  throw new Error(`File not found: ${path}`);
5811
- const content = readFileSync3(path, "utf8");
5812
+ const content = readFileSync2(path, "utf8");
5812
5813
  return scanAndRedactText(content, options);
5813
5814
  }
5814
5815
  function safeStringify(value, space) {
@@ -9334,8 +9335,8 @@ var init_boards = __esm(() => {
9334
9335
 
9335
9336
  // src/lib/artifact-store.ts
9336
9337
  import { createHash as createHash2 } from "crypto";
9337
- import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync4, rmSync, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
9338
- import { basename, dirname as dirname5, join as join6, resolve as resolve7 } from "path";
9338
+ import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync3, rmSync, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
9339
+ import { basename, dirname as dirname4, join as join5, resolve as resolve7 } from "path";
9339
9340
  import { tmpdir as tmpdir2 } from "os";
9340
9341
  function isInMemoryDb2(path) {
9341
9342
  return path === ":memory:" || path.startsWith("file::memory:");
@@ -9347,15 +9348,15 @@ function artifactStoreRoot() {
9347
9348
  return resolve7(process.env["TODOS_ARTIFACTS_DIR"]);
9348
9349
  const dbPath = getDatabasePath();
9349
9350
  if (isInMemoryDb2(dbPath))
9350
- return join6(tmpdir2(), "hasna-todos-artifacts");
9351
- return join6(dirname5(resolve7(dbPath)), "artifacts");
9351
+ return join5(tmpdir2(), "hasna-todos-artifacts");
9352
+ return join5(dirname4(resolve7(dbPath)), "artifacts");
9352
9353
  }
9353
9354
  function artifactStorePath(relativePath) {
9354
9355
  const normalized = relativePath.replace(/\\/g, "/");
9355
9356
  if (normalized.includes("..") || normalized.startsWith("/") || normalized.length === 0) {
9356
9357
  throw new Error("Invalid artifact store path");
9357
9358
  }
9358
- return join6(artifactStoreRoot(), normalized);
9359
+ return join5(artifactStoreRoot(), normalized);
9359
9360
  }
9360
9361
  function sha256(buffer) {
9361
9362
  return createHash2("sha256").update(buffer).digest("hex");
@@ -9396,12 +9397,12 @@ function mediaTypeFor(path, textLike) {
9396
9397
  }
9397
9398
  function storeArtifactContent(input) {
9398
9399
  const sourcePath = resolve7(input.path);
9399
- if (!existsSync8(sourcePath))
9400
+ if (!existsSync7(sourcePath))
9400
9401
  return null;
9401
9402
  const sourceStat = statSync2(sourcePath);
9402
9403
  if (!sourceStat.isFile())
9403
9404
  throw new Error(`Artifact path is not a file: ${input.path}`);
9404
- const sourceBuffer = readFileSync4(sourcePath);
9405
+ const sourceBuffer = readFileSync3(sourcePath);
9405
9406
  const sourceSha = sha256(sourceBuffer);
9406
9407
  const textLike = isTextLike(sourceBuffer, input.path);
9407
9408
  let storedBuffer = sourceBuffer;
@@ -9413,10 +9414,10 @@ function storeArtifactContent(input) {
9413
9414
  redactionStatus = "redacted";
9414
9415
  }
9415
9416
  const storedSha = sha256(storedBuffer);
9416
- const relativePath = join6("sha256", storedSha.slice(0, 2), storedSha).replace(/\\/g, "/");
9417
+ const relativePath = join5("sha256", storedSha.slice(0, 2), storedSha).replace(/\\/g, "/");
9417
9418
  const destination = artifactStorePath(relativePath);
9418
- if (!existsSync8(destination)) {
9419
- mkdirSync4(dirname5(destination), { recursive: true });
9419
+ if (!existsSync7(destination)) {
9420
+ mkdirSync4(dirname4(destination), { recursive: true });
9420
9421
  writeFileSync2(destination, storedBuffer);
9421
9422
  }
9422
9423
  const createdAt = input.created_at || new Date().toISOString();
@@ -9475,7 +9476,7 @@ function verifyStoredArtifact(input) {
9475
9476
  };
9476
9477
  }
9477
9478
  const storedPath = artifactStorePath(store.relative_path);
9478
- if (!existsSync8(storedPath)) {
9479
+ if (!existsSync7(storedPath)) {
9479
9480
  return {
9480
9481
  id: input.id,
9481
9482
  path: input.path,
@@ -9488,7 +9489,7 @@ function verifyStoredArtifact(input) {
9488
9489
  message: "stored artifact content is missing"
9489
9490
  };
9490
9491
  }
9491
- const buffer = readFileSync4(storedPath);
9492
+ const buffer = readFileSync3(storedPath);
9492
9493
  const actualSha = sha256(buffer);
9493
9494
  const actualSize = buffer.length;
9494
9495
  const ok = actualSha === store.sha256 && actualSize === store.size_bytes;
@@ -9508,7 +9509,7 @@ function exportStoredArtifactContent(input) {
9508
9509
  const report = verifyStoredArtifact(input);
9509
9510
  if (report.status !== "ok" || !report.relative_path || !report.actual_sha256 || report.actual_size_bytes === null)
9510
9511
  return null;
9511
- const content = readFileSync4(artifactStorePath(report.relative_path));
9512
+ const content = readFileSync3(artifactStorePath(report.relative_path));
9512
9513
  return {
9513
9514
  artifact_id: input.id,
9514
9515
  sha256: report.actual_sha256,
@@ -9534,7 +9535,7 @@ function importStoredArtifactContent(content) {
9534
9535
  };
9535
9536
  }
9536
9537
  const destination = artifactStorePath(content.relative_path);
9537
- mkdirSync4(dirname5(destination), { recursive: true });
9538
+ mkdirSync4(dirname4(destination), { recursive: true });
9538
9539
  writeFileSync2(destination, buffer);
9539
9540
  return {
9540
9541
  id: content.artifact_id,
@@ -9555,29 +9556,29 @@ function getArtifactStoreRoot(dbPath) {
9555
9556
  return resolve7(process.env["TODOS_ARTIFACTS_DIR"]);
9556
9557
  const path = dbPath ?? getDatabasePath();
9557
9558
  if (isInMemoryDb2(path))
9558
- return join6(tmpdir2(), "hasna-todos-artifacts");
9559
- return join6(dirname5(resolve7(path)), "artifacts");
9559
+ return join5(tmpdir2(), "hasna-todos-artifacts");
9560
+ return join5(dirname4(resolve7(path)), "artifacts");
9560
9561
  }
9561
9562
  function computeContentHash(path) {
9562
- return sha256(readFileSync4(resolve7(path)));
9563
+ return sha256(readFileSync3(resolve7(path)));
9563
9564
  }
9564
9565
  function storeArtifactFile(input) {
9565
9566
  const sourcePath = resolve7(input.sourcePath);
9566
- if (!existsSync8(sourcePath)) {
9567
+ if (!existsSync7(sourcePath)) {
9567
9568
  throw new Error(`Source file not found: ${input.sourcePath}`);
9568
9569
  }
9569
9570
  if (!statSync2(sourcePath).isFile()) {
9570
9571
  throw new Error(`Source path is not a file: ${input.sourcePath}`);
9571
9572
  }
9572
- const buffer = readFileSync4(sourcePath);
9573
+ const buffer = readFileSync3(sourcePath);
9573
9574
  const contentHash = sha256(buffer);
9574
9575
  const mimeType = mediaTypeFor(sourcePath, isTextLike(buffer, sourcePath));
9575
9576
  const storageMode = input.storageMode ?? "copy";
9576
9577
  let localPath = sourcePath;
9577
9578
  if (storageMode === "copy") {
9578
9579
  const fileName = input.name && input.name.trim().length > 0 ? basename(input.name) : basename(sourcePath);
9579
- const destination = join6(getArtifactStoreRoot(input.dbPath), input.artifactId, fileName);
9580
- mkdirSync4(dirname5(destination), { recursive: true });
9580
+ const destination = join5(getArtifactStoreRoot(input.dbPath), input.artifactId, fileName);
9581
+ mkdirSync4(dirname4(destination), { recursive: true });
9581
9582
  writeFileSync2(destination, buffer);
9582
9583
  localPath = destination;
9583
9584
  }
@@ -9586,11 +9587,11 @@ function storeArtifactFile(input) {
9586
9587
  function deleteStoredArtifactFile(localPath, storageMode, _dbPath2) {
9587
9588
  if (storageMode === "reference")
9588
9589
  return false;
9589
- if (!localPath || !existsSync8(localPath))
9590
+ if (!localPath || !existsSync7(localPath))
9590
9591
  return false;
9591
9592
  rmSync(localPath, { force: true });
9592
9593
  try {
9593
- rmSync(dirname5(localPath), { recursive: false });
9594
+ rmSync(dirname4(localPath), { recursive: false });
9594
9595
  } catch {}
9595
9596
  return true;
9596
9597
  }
@@ -9612,7 +9613,7 @@ function buildArtifactExportManifest(artifacts, dbPath) {
9612
9613
  }
9613
9614
  function writeArtifactExportManifest(manifest, outputPath) {
9614
9615
  const destination = resolve7(outputPath);
9615
- mkdirSync4(dirname5(destination), { recursive: true });
9616
+ mkdirSync4(dirname4(destination), { recursive: true });
9616
9617
  writeFileSync2(destination, `${JSON.stringify(manifest, null, 2)}
9617
9618
  `);
9618
9619
  return destination;
@@ -10752,28 +10753,126 @@ var init_tasks = __esm(() => {
10752
10753
  init_boards();
10753
10754
  init_calendar();
10754
10755
  });
10755
-
10756
- // src/lib/package-version.ts
10757
- import { existsSync, readFileSync } from "fs";
10758
- import { dirname, join } from "path";
10759
- import { fileURLToPath } from "url";
10760
- function getPackageVersion(fromUrl = import.meta.url) {
10761
- try {
10762
- let dir = dirname(fileURLToPath(fromUrl));
10763
- for (let i = 0;i < 5; i++) {
10764
- const pkgPath = join(dir, "package.json");
10765
- if (existsSync(pkgPath)) {
10766
- return JSON.parse(readFileSync(pkgPath, "utf-8")).version || "0.0.0";
10767
- }
10768
- const parent = dirname(dir);
10769
- if (parent === dir)
10770
- break;
10771
- dir = parent;
10756
+ // package.json
10757
+ var package_default = {
10758
+ name: "@hasna/todos",
10759
+ version: "0.11.92",
10760
+ description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
10761
+ type: "module",
10762
+ main: "dist/index.js",
10763
+ types: "dist/index.d.ts",
10764
+ bin: {
10765
+ todos: "dist/cli/index.js",
10766
+ "todos-mcp": "dist/mcp/index.js",
10767
+ "todos-serve": "dist/server/index.js"
10768
+ },
10769
+ exports: {
10770
+ ".": {
10771
+ types: "./dist/index.d.ts",
10772
+ import: "./dist/index.js"
10773
+ },
10774
+ "./sdk": {
10775
+ types: "./dist/sdk/index.d.ts",
10776
+ import: "./dist/sdk/index.js"
10777
+ },
10778
+ "./mcp": {
10779
+ types: "./dist/mcp.d.ts",
10780
+ import: "./dist/mcp.js"
10781
+ },
10782
+ "./registry": {
10783
+ types: "./dist/registry.d.ts",
10784
+ import: "./dist/registry.js"
10785
+ },
10786
+ "./contracts": {
10787
+ types: "./dist/contracts.d.ts",
10788
+ import: "./dist/contracts.js"
10789
+ },
10790
+ "./storage": {
10791
+ types: "./dist/storage.d.ts",
10792
+ import: "./dist/storage.js"
10772
10793
  }
10773
- } catch {
10774
- return "0.0.0";
10794
+ },
10795
+ workspaces: [
10796
+ "dashboard"
10797
+ ],
10798
+ files: [
10799
+ "dist",
10800
+ "dashboard/dist",
10801
+ "LICENSE",
10802
+ "README.md"
10803
+ ],
10804
+ scripts: {
10805
+ build: "rm -rf dist dashboard/dist && cd dashboard && bun install --frozen-lockfile && bun run build && cd .. && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/server/index.ts --outdir dist/server --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/sdk/index.ts --outdir dist/sdk --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/index.ts src/mcp.ts src/registry.ts src/contracts.ts src/storage.ts --outdir dist --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && tsc --emitDeclarationOnly --outDir dist",
10806
+ "build:server": "rm -rf dist && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/server/index.ts --outdir dist/server --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/sdk/index.ts --outdir dist/sdk --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/index.ts src/mcp.ts src/registry.ts src/contracts.ts src/storage.ts --outdir dist --target bun --external '@hasna/contracts' --external '@hasna/contracts/*'",
10807
+ migrate: "bun run src/server/index.ts migrate",
10808
+ "backfill:comment-redaction": "bun run src/server/index.ts redact-comments",
10809
+ "generate:sdk": "bun run scripts/generate-sdk.ts",
10810
+ "build:dashboard": "cd dashboard && bun install --frozen-lockfile && bun run build",
10811
+ typecheck: "tsc --noEmit",
10812
+ test: "bun test",
10813
+ "test:no-cloud": "bun test src/no-cloud-boundary.test.ts src/local-first.test.ts src/lib/public-release-gate.test.ts",
10814
+ "dev:cli": "bun run src/cli/index.tsx",
10815
+ "dev:mcp": "bun run src/mcp/index.ts",
10816
+ "dev:serve": "bun run src/server/index.ts",
10817
+ "verify:release": "bun run scripts/verify-public-release.ts --mode=review",
10818
+ prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
10819
+ postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
10820
+ },
10821
+ keywords: [
10822
+ "todos",
10823
+ "tasks",
10824
+ "mcp",
10825
+ "ai",
10826
+ "coding-agent",
10827
+ "claude",
10828
+ "codex",
10829
+ "gemini",
10830
+ "tui",
10831
+ "cli",
10832
+ "dashboard"
10833
+ ],
10834
+ publishConfig: {
10835
+ registry: "https://registry.npmjs.org",
10836
+ access: "public"
10837
+ },
10838
+ repository: {
10839
+ type: "git",
10840
+ url: "https://github.com/hasna/todos.git"
10841
+ },
10842
+ homepage: "https://github.com/hasna/todos",
10843
+ bugs: {
10844
+ url: "https://github.com/hasna/todos/issues"
10845
+ },
10846
+ engines: {
10847
+ bun: ">=1.0.0"
10848
+ },
10849
+ packageManager: "bun@1.3.14",
10850
+ author: "Andrei Hasna <andrei@hasna.com>",
10851
+ license: "Apache-2.0",
10852
+ dependencies: {
10853
+ "@hasna/contracts": "0.5.2",
10854
+ "@hasna/events": "^0.1.11",
10855
+ "@modelcontextprotocol/sdk": "^1.12.1",
10856
+ chalk: "^5.4.1",
10857
+ commander: "^13.1.0",
10858
+ ink: "^5.2.0",
10859
+ react: "^18.3.1",
10860
+ zod: "^3.24.2"
10861
+ },
10862
+ overrides: {
10863
+ "fast-uri": "3.1.2"
10864
+ },
10865
+ devDependencies: {
10866
+ "@types/bun": "^1.2.4",
10867
+ "@types/react": "^18.3.18",
10868
+ "bun-types": "1.3.9",
10869
+ typescript: "^5.7.3"
10775
10870
  }
10776
- return "0.0.0";
10871
+ };
10872
+
10873
+ // src/lib/package-version.ts
10874
+ function getPackageVersion(_fromUrl = import.meta.url) {
10875
+ return package_default.version || "0.0.0";
10777
10876
  }
10778
10877
 
10779
10878
  // src/mcp/token-utils.ts
@@ -13360,7 +13459,7 @@ var TODOS_JSON_CONTRACTS_MANIFEST = createJsonContractsManifest({
13360
13459
  });
13361
13460
  // src/lib/onboarding-fixtures.ts
13362
13461
  import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync3 } from "fs";
13363
- import { join as join7 } from "path";
13462
+ import { join as join6 } from "path";
13364
13463
 
13365
13464
  // src/lib/local-bridge.ts
13366
13465
  init_database();
@@ -14267,7 +14366,7 @@ function writeOnboardingFixtureFiles(directory) {
14267
14366
  mkdirSync5(directory, { recursive: true });
14268
14367
  const files = [];
14269
14368
  for (const fixture of allFixtures()) {
14270
- const path = join7(directory, `${fixture.summary.name}.bridge.json`);
14369
+ const path = join6(directory, `${fixture.summary.name}.bridge.json`);
14271
14370
  writeFileSync3(path, `${JSON.stringify(fixture.bundle, null, 2)}
14272
14371
  `, "utf-8");
14273
14372
  files.push(path);
@@ -14284,8 +14383,8 @@ function importOnboardingFixture(options = {}) {
14284
14383
  // src/lib/local-backups.ts
14285
14384
  init_database();
14286
14385
  import { createHash as createHash3 } from "crypto";
14287
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
14288
- import { dirname as dirname6, resolve as resolve8 } from "path";
14386
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
14387
+ import { dirname as dirname5, resolve as resolve8 } from "path";
14289
14388
  import { mkdirSync as mkdirSync6 } from "fs";
14290
14389
  var TODOS_LOCAL_BACKUP_KIND = "hasna.todos.local-backup";
14291
14390
  var TODOS_LOCAL_BACKUP_SCHEMA_VERSION = 1;
@@ -14393,13 +14492,13 @@ function createLocalBackup(options = {}, db) {
14393
14492
  }
14394
14493
  function writeLocalBackupFile(backup, outputPath) {
14395
14494
  const path = resolve8(outputPath);
14396
- mkdirSync6(dirname6(path), { recursive: true });
14495
+ mkdirSync6(dirname5(path), { recursive: true });
14397
14496
  writeFileSync4(path, `${JSON.stringify(backup, null, 2)}
14398
14497
  `);
14399
14498
  return path;
14400
14499
  }
14401
14500
  function readLocalBackupFile(path) {
14402
- return JSON.parse(readFileSync5(resolve8(path), "utf-8"));
14501
+ return JSON.parse(readFileSync4(resolve8(path), "utf-8"));
14403
14502
  }
14404
14503
  function verifyLocalBackup(value, options = {}, db) {
14405
14504
  const verifiedAt = options.verified_at ?? now();
@@ -15093,7 +15192,7 @@ function renderLocalSnapshotMarkdown(snapshot) {
15093
15192
  }
15094
15193
  // src/lib/sdk-integration-fixtures.ts
15095
15194
  import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync5 } from "fs";
15096
- import { join as join8 } from "path";
15195
+ import { join as join7 } from "path";
15097
15196
 
15098
15197
  // src/cli-mcp-parity.ts
15099
15198
  function source4(version) {
@@ -17049,7 +17148,7 @@ function writeSdkIntegrationFixtures(directory, options = {}) {
17049
17148
  ];
17050
17149
  const written = [];
17051
17150
  for (const [name, payload] of files) {
17052
- const file = join8(directory, name);
17151
+ const file = join7(directory, name);
17053
17152
  writeFileSync5(file, `${JSON.stringify(payload, null, 2)}
17054
17153
  `, "utf-8");
17055
17154
  written.push(file);
@@ -18331,8 +18430,8 @@ function renderLocalAuditLedgerMarkdown(ledger) {
18331
18430
  // src/lib/release-compatibility.ts
18332
18431
  init_migrations();
18333
18432
  init_schema();
18334
- import { readFileSync as readFileSync6 } from "fs";
18335
- import { join as join9, resolve as resolve9 } from "path";
18433
+ import { readFileSync as readFileSync5 } from "fs";
18434
+ import { join as join8, resolve as resolve9 } from "path";
18336
18435
  import { Database as Database2 } from "bun:sqlite";
18337
18436
  var LOCAL_RELEASE_COMPATIBILITY_SCHEMA_VERSION = 1;
18338
18437
  var EXPECTED_PACKAGE_NAME = "@hasna/todos";
@@ -18378,7 +18477,7 @@ function warn(id, message, details) {
18378
18477
  return { id, status: "warning", message, details };
18379
18478
  }
18380
18479
  function readPackageJson(root) {
18381
- return JSON.parse(readFileSync6(join9(root, "package.json"), "utf8"));
18480
+ return JSON.parse(readFileSync5(join8(root, "package.json"), "utf8"));
18382
18481
  }
18383
18482
  function sortedKeys(value) {
18384
18483
  return Object.keys(value ?? {}).sort((left, right) => left.localeCompare(right));