@hasna/todos 0.15.49 → 0.15.51

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/index.js CHANGED
@@ -2123,7 +2123,7 @@ var package_default;
2123
2123
  var init_package = __esm(() => {
2124
2124
  package_default = {
2125
2125
  name: "@hasna/todos",
2126
- version: "0.15.49",
2126
+ version: "0.15.51",
2127
2127
  description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
2128
2128
  type: "module",
2129
2129
  main: "dist/index.js",
@@ -2182,6 +2182,7 @@ var init_package = __esm(() => {
2182
2182
  files: [
2183
2183
  "dist",
2184
2184
  "dashboard/dist",
2185
+ "postinstall.js",
2185
2186
  "LICENSE",
2186
2187
  "README.md"
2187
2188
  ],
@@ -2208,7 +2209,7 @@ var init_package = __esm(() => {
2208
2209
  "test:attested-container-compatibility-vector": "bun test scripts/attested-container-compatibility-vector.test.ts",
2209
2210
  "issue:release-review": "bun run scripts/issue-npm-release-agent-review.ts",
2210
2211
  prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
2211
- postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
2212
+ postinstall: "node postinstall.js"
2212
2213
  },
2213
2214
  keywords: [
2214
2215
  "todos",
@@ -2242,13 +2243,15 @@ var init_package = __esm(() => {
2242
2243
  author: "Andrei Hasna <andrei@hasna.com>",
2243
2244
  license: "Apache-2.0",
2244
2245
  dependencies: {
2245
- "@hasna/contracts": "0.14.0",
2246
+ "@hasna/contracts": "0.14.2",
2246
2247
  "@hasna/events": "^0.1.11",
2248
+ "@hasna/paths": "0.1.0",
2247
2249
  "@modelcontextprotocol/sdk": "^1.12.1",
2248
2250
  chalk: "^5.4.1",
2249
2251
  commander: "^13.1.0",
2250
2252
  ink: "^5.2.0",
2251
2253
  react: "^18.3.1",
2254
+ "signal-exit": "3.0.7",
2252
2255
  zod: "3.25.76"
2253
2256
  },
2254
2257
  overrides: {
@@ -2491,6 +2494,101 @@ var init_types = __esm(() => {
2491
2494
  };
2492
2495
  });
2493
2496
 
2497
+ // node_modules/.bun/@hasna+paths@0.1.0/node_modules/@hasna/paths/dist/index.js
2498
+ import { homedir } from "os";
2499
+ import { join } from "path";
2500
+ function assertApp(app) {
2501
+ if (typeof app !== "string" || app.length === 0) {
2502
+ throw new TypeError("paths: app must be a non-empty string");
2503
+ }
2504
+ if (!APP_SLUG_RE.test(app)) {
2505
+ throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
2506
+ }
2507
+ }
2508
+ function envOf(options) {
2509
+ return options.env ?? process.env;
2510
+ }
2511
+ function envValue(options, kind) {
2512
+ const value = envOf(options)[KIND_ENV[kind]];
2513
+ return typeof value === "string" && value.length > 0 ? value : undefined;
2514
+ }
2515
+ function isMacOS(platform) {
2516
+ return platform === "darwin";
2517
+ }
2518
+ function baseDir(kind, options) {
2519
+ const override = envValue(options, kind);
2520
+ if (override)
2521
+ return override;
2522
+ const home = options.home ?? homedir();
2523
+ const platform = options.platform ?? process.platform;
2524
+ if (isMacOS(platform)) {
2525
+ switch (kind) {
2526
+ case "config":
2527
+ case "data":
2528
+ return join(home, "Library", "Application Support", "Hasna");
2529
+ case "cache":
2530
+ return join(home, "Library", "Caches", "Hasna");
2531
+ case "state":
2532
+ return join(home, "Library", "Logs", "Hasna");
2533
+ }
2534
+ }
2535
+ switch (kind) {
2536
+ case "config":
2537
+ return join(home, ".config", "hasna");
2538
+ case "data":
2539
+ return join(home, ".local", "share", "hasna");
2540
+ case "state":
2541
+ return join(home, ".local", "state", "hasna");
2542
+ case "cache":
2543
+ return join(home, ".cache", "hasna");
2544
+ }
2545
+ }
2546
+ function resolvePath(kind, options) {
2547
+ assertApp(options.app);
2548
+ const appSegment = options.internal === true ? join("internal", options.app) : options.app;
2549
+ return join(baseDir(kind, options), appSegment);
2550
+ }
2551
+ function dataDir(options) {
2552
+ return resolvePath("data", options);
2553
+ }
2554
+ var KIND_ENV, APP_SLUG_RE;
2555
+ var init_dist = __esm(() => {
2556
+ KIND_ENV = {
2557
+ config: "HASNA_CONFIG_HOME",
2558
+ data: "HASNA_DATA_HOME",
2559
+ state: "HASNA_STATE_HOME",
2560
+ cache: "HASNA_CACHE_HOME"
2561
+ };
2562
+ APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
2563
+ });
2564
+
2565
+ // src/lib/paths.ts
2566
+ import { existsSync } from "fs";
2567
+ import { homedir as homedir2 } from "os";
2568
+ import { join as join2, resolve } from "path";
2569
+ function effectiveHome(env = process.env) {
2570
+ return env.HOME || env.USERPROFILE || homedir2();
2571
+ }
2572
+ function legacyHomeDir(env = process.env) {
2573
+ return join2(effectiveHome(env), ".hasna", "todos");
2574
+ }
2575
+ function resolverHome(env = process.env) {
2576
+ return dataDir({ app: "todos", home: effectiveHome(env), env });
2577
+ }
2578
+ function adoptResolverHome(resolved, env = process.env) {
2579
+ const dataOverride = env.HASNA_DATA_HOME;
2580
+ if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
2581
+ return true;
2582
+ return existsSync(join2(resolved, "todos.db")) || existsSync(join2(resolved, "config.json"));
2583
+ }
2584
+ function getTodosDir(env = process.env) {
2585
+ const resolved = resolverHome(env);
2586
+ return resolve(adoptResolverHome(resolved, env) ? resolved : legacyHomeDir(env));
2587
+ }
2588
+ var init_paths = __esm(() => {
2589
+ init_dist();
2590
+ });
2591
+
2494
2592
  // src/lib/sync-utils.ts
2495
2593
  var exports_sync_utils = {};
2496
2594
  __export(exports_sync_utils, {
@@ -2510,22 +2608,22 @@ __export(exports_sync_utils, {
2510
2608
  TODO_SYNC_FINGERPRINT_KEY: () => TODO_SYNC_FINGERPRINT_KEY,
2511
2609
  HOME: () => HOME
2512
2610
  });
2513
- import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
2611
+ import { existsSync as existsSync2, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
2514
2612
  import { createHash } from "crypto";
2515
- import { homedir } from "os";
2516
- import { join } from "path";
2613
+ import { homedir as homedir3 } from "os";
2614
+ import { join as join3 } from "path";
2517
2615
  function getHomeDir() {
2518
- return process.env["HOME"] || process.env["USERPROFILE"] || homedir();
2616
+ return process.env["HOME"] || process.env["USERPROFILE"] || homedir3();
2519
2617
  }
2520
2618
  function getTodosGlobalDir() {
2521
- return join(getHomeDir(), ".hasna", "todos");
2619
+ return getTodosDir();
2522
2620
  }
2523
2621
  function ensureDir(dir) {
2524
- if (!existsSync(dir))
2622
+ if (!existsSync2(dir))
2525
2623
  mkdirSync(dir, { recursive: true });
2526
2624
  }
2527
2625
  function listJsonFiles(dir) {
2528
- if (!existsSync(dir))
2626
+ if (!existsSync2(dir))
2529
2627
  return [];
2530
2628
  return readdirSync(dir).filter((f) => f.endsWith(".json"));
2531
2629
  }
@@ -2541,14 +2639,14 @@ function writeJsonFile(path, data) {
2541
2639
  `);
2542
2640
  }
2543
2641
  function readHighWaterMark(dir) {
2544
- const path = join(dir, ".highwatermark");
2545
- if (!existsSync(path))
2642
+ const path = join3(dir, ".highwatermark");
2643
+ if (!existsSync2(path))
2546
2644
  return 1;
2547
2645
  const val = parseInt(readFileSync(path, "utf-8").trim(), 10);
2548
2646
  return isNaN(val) ? 1 : val;
2549
2647
  }
2550
2648
  function writeHighWaterMark(dir, value) {
2551
- writeFileSync(join(dir, ".highwatermark"), String(value));
2649
+ writeFileSync(join3(dir, ".highwatermark"), String(value));
2552
2650
  }
2553
2651
  function getFileMtimeMs(path) {
2554
2652
  try {
@@ -2603,6 +2701,7 @@ function hasSyncFingerprintChanged(record) {
2603
2701
  }
2604
2702
  var TODO_SYNC_FINGERPRINT_KEY = "todos_sync_fingerprint", HOME;
2605
2703
  var init_sync_utils = __esm(() => {
2704
+ init_paths();
2606
2705
  HOME = getHomeDir();
2607
2706
  });
2608
2707
 
@@ -2624,10 +2723,10 @@ __export(exports_config, {
2624
2723
  getAgentTaskListId: () => getAgentTaskListId,
2625
2724
  getAgentPoolForProject: () => getAgentPoolForProject
2626
2725
  });
2627
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
2628
- import { dirname, join as join2 } from "path";
2726
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
2727
+ import { dirname, join as join4 } from "path";
2629
2728
  function getConfigPath() {
2630
- return join2(getTodosGlobalDir(), "config.json");
2729
+ return join4(getTodosGlobalDir(), "config.json");
2631
2730
  }
2632
2731
  function resetConfig() {
2633
2732
  cached = null;
@@ -2638,7 +2737,7 @@ function normalizeAgent(agent) {
2638
2737
  function loadConfig() {
2639
2738
  if (cached)
2640
2739
  return cached;
2641
- if (!existsSync2(getConfigPath())) {
2740
+ if (!existsSync3(getConfigPath())) {
2642
2741
  cached = {};
2643
2742
  return cached;
2644
2743
  }
@@ -2661,7 +2760,7 @@ function updateConfig(patch) {
2661
2760
  }
2662
2761
  function getTodosAiConfig() {
2663
2762
  const configPath = getConfigPath();
2664
- if (!existsSync2(configPath))
2763
+ if (!existsSync3(configPath))
2665
2764
  return {};
2666
2765
  const parsed = JSON.parse(readFileSync2(configPath, "utf8"));
2667
2766
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -5721,7 +5820,7 @@ var init_page_validation = __esm(() => {
5721
5820
  // src/cli/cloud-router.ts
5722
5821
  import { resolveStorageClient } from "@hasna/contracts/client/storage";
5723
5822
  import { randomUUID } from "crypto";
5724
- import { resolve as resolvePath } from "path";
5823
+ import { resolve as resolvePath2 } from "path";
5725
5824
  function emitTodosLocalFallbackNotice(env) {
5726
5825
  if (todosLocalFallbackNoticeEmitted)
5727
5826
  return;
@@ -6707,11 +6806,11 @@ function resolveCloudProjectRef(projects, ref) {
6707
6806
  const input = ref.trim();
6708
6807
  const normalizedRef = input.toLowerCase();
6709
6808
  const pathLike = input.startsWith(".") || input.includes("/") || input.includes("\\");
6710
- const normalizedPath = pathLike ? resolvePath(input) : undefined;
6809
+ const normalizedPath = pathLike ? resolvePath2(input) : undefined;
6711
6810
  const slug = cloudProjectSlug(pathLike ? cloudProjectPathBasename(input) : input);
6712
6811
  const matchGroups = [
6713
6812
  uniqueProjectMatches(projects, (project) => project.id.toLowerCase() === normalizedRef),
6714
- uniqueProjectMatches(projects, (project) => project.path === input || normalizedPath !== undefined && resolvePath(project.path) === normalizedPath),
6813
+ uniqueProjectMatches(projects, (project) => project.path === input || normalizedPath !== undefined && resolvePath2(project.path) === normalizedPath),
6715
6814
  uniqueProjectMatches(projects, (project) => project.name.toLowerCase() === normalizedRef),
6716
6815
  uniqueProjectMatches(projects, (project) => project.task_list_id === input || cloudProjectSlug(project.name) === slug || cloudProjectSlug(cloudProjectPathBasename(project.path)) === slug),
6717
6816
  uniqueProjectMatches(projects, (project) => project.id.toLowerCase().startsWith(normalizedRef))
@@ -11718,9 +11817,9 @@ var init_schema = __esm(() => {
11718
11817
  });
11719
11818
 
11720
11819
  // src/db/machines.ts
11721
- import { existsSync as existsSync3 } from "fs";
11820
+ import { existsSync as existsSync4 } from "fs";
11722
11821
  import { hostname as osHostname, platform as osPlatform, arch as osArch } from "os";
11723
- import { resolve } from "path";
11822
+ import { resolve as resolve2 } from "path";
11724
11823
  import { spawnSync } from "child_process";
11725
11824
  function parseMetadata(value) {
11726
11825
  if (!value)
@@ -11751,7 +11850,7 @@ function discoverGitRoot(workspacePath) {
11751
11850
  }
11752
11851
  function topologyMetadata(input, existing = {}) {
11753
11852
  const next = { ...existing };
11754
- const workspacePath = input.workspace_path ? resolve(input.workspace_path) : undefined;
11853
+ const workspacePath = input.workspace_path ? resolve2(input.workspace_path) : undefined;
11755
11854
  const entries = {
11756
11855
  tailscale_name: input.tailscale_name,
11757
11856
  tailscale_ip: input.tailscale_ip,
@@ -11925,7 +12024,7 @@ function getMachineTopologyDiagnostics(opts = {}, db, at = new Date) {
11925
12024
  message: `${project.name} has ${distinctPaths.length} different machine-local paths`
11926
12025
  });
11927
12026
  }
11928
- if (localRow && !existsSync3(localRow.path)) {
12027
+ if (localRow && !existsSync4(localRow.path)) {
11929
12028
  pathIssues.push({
11930
12029
  type: "path_missing",
11931
12030
  project_id: project.id,
@@ -11936,7 +12035,7 @@ function getMachineTopologyDiagnostics(opts = {}, db, at = new Date) {
11936
12035
  message: `Local path does not exist on this machine: ${localRow.path}`
11937
12036
  });
11938
12037
  }
11939
- if (!localRow && project.path && machineById.has(localMachine.id) && !existsSync3(project.path)) {
12038
+ if (!localRow && project.path && machineById.has(localMachine.id) && !existsSync4(project.path)) {
11940
12039
  pathIssues.push({
11941
12040
  type: "path_missing",
11942
12041
  project_id: project.id,
@@ -12525,18 +12624,18 @@ __export(exports_database, {
12525
12624
  LOCK_EXPIRY_MINUTES: () => LOCK_EXPIRY_MINUTES
12526
12625
  });
12527
12626
  import { Database } from "bun:sqlite";
12528
- import { existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
12529
- import { dirname as dirname2, join as join3, resolve as resolve2 } from "path";
12627
+ import { existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
12628
+ import { dirname as dirname2, join as join5, resolve as resolve3 } from "path";
12530
12629
  function isInMemoryDb(path) {
12531
12630
  return path === ":memory:" || path.startsWith("file::memory:");
12532
12631
  }
12533
12632
  function findNearestProjectDb(startDir) {
12534
12633
  const gitRoot = findGitRoot(startDir);
12535
- const stopAt = gitRoot ? resolve2(gitRoot) : resolve2(startDir);
12536
- let dir = resolve2(startDir);
12634
+ const stopAt = gitRoot ? resolve3(gitRoot) : resolve3(startDir);
12635
+ let dir = resolve3(startDir);
12537
12636
  while (true) {
12538
- const candidate = join3(dir, ".hasna", "todos", "todos.db");
12539
- if (existsSync4(candidate))
12637
+ const candidate = join5(dir, ".hasna", "todos", "todos.db");
12638
+ if (existsSync5(candidate))
12540
12639
  return candidate;
12541
12640
  if (dir === stopAt)
12542
12641
  break;
@@ -12548,9 +12647,9 @@ function findNearestProjectDb(startDir) {
12548
12647
  return null;
12549
12648
  }
12550
12649
  function findGitRoot(startDir) {
12551
- let dir = resolve2(startDir);
12650
+ let dir = resolve3(startDir);
12552
12651
  while (true) {
12553
- if (existsSync4(join3(dir, ".git")))
12652
+ if (existsSync5(join5(dir, ".git")))
12554
12653
  return dir;
12555
12654
  const parent = dirname2(dir);
12556
12655
  if (parent === dir)
@@ -12560,7 +12659,7 @@ function findGitRoot(startDir) {
12560
12659
  return null;
12561
12660
  }
12562
12661
  function getGlobalDbPath() {
12563
- return join3(getHomeDir(), ".hasna", "todos", "todos.db");
12662
+ return join5(getTodosGlobalDir(), "todos.db");
12564
12663
  }
12565
12664
  function hasExplicitProjectArg(args = process.argv.slice(2)) {
12566
12665
  return args.some((arg) => arg === "--project" || arg.startsWith("--project="));
@@ -12598,7 +12697,7 @@ function getDbPath() {
12598
12697
  if (process.env["TODOS_DB_SCOPE"] === "project") {
12599
12698
  const gitRoot = findGitRoot(cwd);
12600
12699
  if (gitRoot && canCreateScopedProjectDb()) {
12601
- return join3(gitRoot, ".hasna", "todos", "todos.db");
12700
+ return join5(gitRoot, ".hasna", "todos", "todos.db");
12602
12701
  }
12603
12702
  }
12604
12703
  return getGlobalDbPath();
@@ -12609,8 +12708,8 @@ function getDatabasePath() {
12609
12708
  function ensureDir2(filePath) {
12610
12709
  if (isInMemoryDb(filePath))
12611
12710
  return;
12612
- const dir = dirname2(resolve2(filePath));
12613
- if (!existsSync4(dir)) {
12711
+ const dir = dirname2(resolve3(filePath));
12712
+ if (!existsSync5(dir)) {
12614
12713
  mkdirSync2(dir, { recursive: true });
12615
12714
  }
12616
12715
  }
@@ -13453,9 +13552,9 @@ __export(exports_helpers, {
13453
13552
  });
13454
13553
  import chalk from "chalk";
13455
13554
  import { execSync } from "child_process";
13456
- import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2, writeSync } from "fs";
13555
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2, writeSync } from "fs";
13457
13556
  import { tmpdir } from "os";
13458
- import { dirname as dirname3, join as join4, resolve as resolve3, sep } from "path";
13557
+ import { dirname as dirname3, join as join6, resolve as resolve4, sep } from "path";
13459
13558
  function jsonModeRequested(argv = process.argv) {
13460
13559
  return argv.some((arg) => arg === "--json" || /^-[a-z]+$/i.test(arg) && arg.includes("j"));
13461
13560
  }
@@ -13527,11 +13626,13 @@ async function resolveTaskIdForCommand(input, cloud = getTodosCloudClient()) {
13527
13626
  }
13528
13627
  function cloudTaskIdCachePath() {
13529
13628
  const home = process.env["HOME"] || process.env["USERPROFILE"];
13530
- return home ? join4(home, ".hasna", "todos", "cloud-task-id-cache.json") : null;
13629
+ if (!home)
13630
+ return null;
13631
+ return join6(getTodosGlobalDir(), "cloud-task-id-cache.json");
13531
13632
  }
13532
13633
  function readCloudTaskIdCache() {
13533
13634
  const path = cloudTaskIdCachePath();
13534
- if (!path || !existsSync5(path))
13635
+ if (!path || !existsSync6(path))
13535
13636
  return { version: 1, tasks: [] };
13536
13637
  try {
13537
13638
  const parsed = JSON.parse(readFileSync3(path, "utf8"));
@@ -13595,12 +13696,12 @@ function detectGitRoot() {
13595
13696
  }
13596
13697
  }
13597
13698
  function isPathWithin(child, parent) {
13598
- const normalizedChild = resolve3(child);
13599
- const normalizedParent = resolve3(parent);
13699
+ const normalizedChild = resolve4(child);
13700
+ const normalizedParent = resolve4(parent);
13600
13701
  return normalizedChild === normalizedParent || normalizedChild.startsWith(`${normalizedParent}${sep}`);
13601
13702
  }
13602
13703
  function shouldSkipAutoProjectForGitRoot(gitRoot) {
13603
- const normalized = resolve3(gitRoot);
13704
+ const normalized = resolve4(gitRoot);
13604
13705
  if (process.platform !== "win32" && (normalized === "/tmp" || normalized.startsWith("/tmp/"))) {
13605
13706
  return true;
13606
13707
  }
@@ -13608,7 +13709,7 @@ function shouldSkipAutoProjectForGitRoot(gitRoot) {
13608
13709
  }
13609
13710
  function resolveExplicitProject(input) {
13610
13711
  const db = getDatabase();
13611
- const byPath = getProjectByPath(resolve3(input), db);
13712
+ const byPath = getProjectByPath(resolve4(input), db);
13612
13713
  if (byPath)
13613
13714
  return byPath;
13614
13715
  const id = resolvePartialId(db, "projects", input);
@@ -13780,6 +13881,7 @@ var init_helpers = __esm(() => {
13780
13881
  init_projects();
13781
13882
  init_lock_display();
13782
13883
  init_package_version();
13884
+ init_sync_utils();
13783
13885
  init_types();
13784
13886
  stdoutRetryBuffer = new SharedArrayBuffer(4);
13785
13887
  stdoutRetrySignal = new Int32Array(stdoutRetryBuffer);
@@ -13869,14 +13971,14 @@ var init_completion_guard = __esm(() => {
13869
13971
 
13870
13972
  // src/lib/event-emission-safety.ts
13871
13973
  import { tmpdir as tmpdir2 } from "os";
13872
- import { resolve as resolve4, sep as sep2 } from "path";
13974
+ import { resolve as resolve5, sep as sep2 } from "path";
13873
13975
  function envFlag(name) {
13874
13976
  const value = process.env[name]?.trim().toLowerCase();
13875
13977
  return value === "1" || value === "true" || value === "yes" || value === "on";
13876
13978
  }
13877
13979
  function isUnder(parent, child) {
13878
- const normalizedParent = resolve4(parent);
13879
- const normalizedChild = resolve4(child);
13980
+ const normalizedParent = resolve5(parent);
13981
+ const normalizedChild = resolve5(child);
13880
13982
  return normalizedChild === normalizedParent || normalizedChild.startsWith(`${normalizedParent}${sep2}`);
13881
13983
  }
13882
13984
  function databasePathFromDatabase(db) {
@@ -13927,9 +14029,9 @@ __export(exports_workspace_trust, {
13927
14029
  getWorkspaceTrustStatus: () => getWorkspaceTrustStatus,
13928
14030
  checkWorkspacePermission: () => checkWorkspacePermission
13929
14031
  });
13930
- import { relative, resolve as resolve5 } from "path";
14032
+ import { relative, resolve as resolve6 } from "path";
13931
14033
  function normalizePath(path) {
13932
- return resolve5(path);
14034
+ return resolve6(path);
13933
14035
  }
13934
14036
  function unique2(values) {
13935
14037
  return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
@@ -14120,9 +14222,9 @@ __export(exports_runner_sandbox, {
14120
14222
  explainRunnerSandbox: () => explainRunnerSandbox,
14121
14223
  checkRunnerSandbox: () => checkRunnerSandbox
14122
14224
  });
14123
- import { relative as relative2, resolve as resolve6 } from "path";
14225
+ import { relative as relative2, resolve as resolve7 } from "path";
14124
14226
  function normalizePath2(path) {
14125
- return resolve6(path);
14227
+ return resolve7(path);
14126
14228
  }
14127
14229
  function unique3(values) {
14128
14230
  return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
@@ -14326,7 +14428,7 @@ __export(exports_event_hooks, {
14326
14428
  });
14327
14429
  import { createHash as createHash4, randomUUID as randomUUID2 } from "crypto";
14328
14430
  import { appendFileSync, mkdirSync as mkdirSync4 } from "fs";
14329
- import { dirname as dirname4, resolve as resolve7 } from "path";
14431
+ import { dirname as dirname4, resolve as resolve8 } from "path";
14330
14432
  import { createConnection } from "net";
14331
14433
  function safeName(name) {
14332
14434
  const trimmed = name.trim();
@@ -14464,7 +14566,7 @@ async function deliverHook(hook, envelope) {
14464
14566
  if (hook.target === "stdout") {
14465
14567
  output2 = line.trim();
14466
14568
  } else if (hook.target === "file") {
14467
- const filePath = resolve7(hook.file_path);
14569
+ const filePath = resolve8(hook.file_path);
14468
14570
  mkdirSync4(dirname4(filePath), { recursive: true });
14469
14571
  appendFileSync(filePath, line);
14470
14572
  } else if (hook.target === "socket") {
@@ -14585,9 +14687,9 @@ var init_event_hooks = __esm(() => {
14585
14687
  // node_modules/.bun/@hasna+events@0.1.16/node_modules/@hasna/events/dist/index.js
14586
14688
  import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
14587
14689
  import { Buffer as Buffer2 } from "buffer";
14588
- import { existsSync as existsSync6 } from "fs";
14589
- import { homedir as homedir2 } from "os";
14590
- import { join as join5 } from "path";
14690
+ import { existsSync as existsSync7 } from "fs";
14691
+ import { homedir as homedir4 } from "os";
14692
+ import { join as join7 } from "path";
14591
14693
  import { createHmac, timingSafeEqual } from "crypto";
14592
14694
  import { randomUUID as randomUUID3 } from "crypto";
14593
14695
  import { spawn } from "child_process";
@@ -14688,7 +14790,7 @@ function channelMatchesEvent(channel, event) {
14688
14790
  return channel.filters.some((filter) => eventMatchesFilter(event, filter));
14689
14791
  }
14690
14792
  function getEventsDataDir(override) {
14691
- return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join5(homedir2(), ".hasna", "events");
14793
+ return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join7(homedir4(), ".hasna", "events");
14692
14794
  }
14693
14795
 
14694
14796
  class JsonEventsStore {
@@ -14697,12 +14799,12 @@ class JsonEventsStore {
14697
14799
  channelsPath;
14698
14800
  eventsPath;
14699
14801
  deliveriesPath;
14700
- constructor(dataDir = getEventsDataDir()) {
14701
- this.dataDir = dataDir;
14702
- this.runtime = localJsonRuntime(dataDir);
14703
- this.channelsPath = join5(dataDir, "channels.json");
14704
- this.eventsPath = join5(dataDir, "events.json");
14705
- this.deliveriesPath = join5(dataDir, "deliveries.json");
14802
+ constructor(dataDir2 = getEventsDataDir()) {
14803
+ this.dataDir = dataDir2;
14804
+ this.runtime = localJsonRuntime(dataDir2);
14805
+ this.channelsPath = join7(dataDir2, "channels.json");
14806
+ this.eventsPath = join7(dataDir2, "events.json");
14807
+ this.deliveriesPath = join7(dataDir2, "deliveries.json");
14706
14808
  }
14707
14809
  async init() {
14708
14810
  await mkdir(this.dataDir, { recursive: true, mode: 448 });
@@ -14819,7 +14921,7 @@ class JsonEventsStore {
14819
14921
  };
14820
14922
  }
14821
14923
  async ensureArrayFile(path) {
14822
- if (!existsSync6(path)) {
14924
+ if (!existsSync7(path)) {
14823
14925
  await writeFile(path, `[]
14824
14926
  `, { encoding: "utf-8", mode: 384 });
14825
14927
  }
@@ -14849,7 +14951,7 @@ class JsonEventsStore {
14849
14951
  });
14850
14952
  }
14851
14953
  }
14852
- function localJsonRuntime(dataDir = getEventsDataDir()) {
14954
+ function localJsonRuntime(dataDir2 = getEventsDataDir()) {
14853
14955
  return {
14854
14956
  mode: "local-files",
14855
14957
  name: "json-events-store",
@@ -14862,7 +14964,7 @@ function localJsonRuntime(dataDir = getEventsDataDir()) {
14862
14964
  durable: true,
14863
14965
  idempotency: "best-effort-local",
14864
14966
  replayCursors: true,
14865
- description: `Local JSON files in ${dataDir}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
14967
+ description: `Local JSON files in ${dataDir2}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
14866
14968
  };
14867
14969
  }
14868
14970
  function encodeLocalJsonEventCursor(offset, options = {}) {
@@ -15041,7 +15143,7 @@ async function dispatchCommand(event, channel) {
15041
15143
  HASNA_EVENT_SCHEMA_VERSION: event.schemaVersion,
15042
15144
  HASNA_EVENT_JSON: eventJson
15043
15145
  };
15044
- return new Promise((resolve8) => {
15146
+ return new Promise((resolve9) => {
15045
15147
  const child = spawn(channel.command.command, channel.command.args ?? [], {
15046
15148
  cwd: channel.command.cwd,
15047
15149
  env,
@@ -15059,7 +15161,7 @@ async function dispatchCommand(event, channel) {
15059
15161
  });
15060
15162
  child.on("error", (error) => {
15061
15163
  clearTimeout(timeout);
15062
- resolve8({
15164
+ resolve9({
15063
15165
  attempt: 1,
15064
15166
  status: "failed",
15065
15167
  startedAt,
@@ -15072,7 +15174,7 @@ async function dispatchCommand(event, channel) {
15072
15174
  child.on("close", (code, signal) => {
15073
15175
  clearTimeout(timeout);
15074
15176
  const success = code === 0;
15075
- resolve8({
15177
+ resolve9({
15076
15178
  attempt: 1,
15077
15179
  status: success ? "success" : "failed",
15078
15180
  startedAt,
@@ -15414,7 +15516,7 @@ function normalizeRetryPolicy(policy) {
15414
15516
  };
15415
15517
  }
15416
15518
  var HASNA_EVENTS_DIR_ENV = "HASNA_EVENTS_DIR", HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME", LOCAL_JSON_EVENT_CURSOR_PREFIX = "local-json-v1:", DEFAULT_EVENT_PAGE_LIMIT = 100, MAX_EVENT_PAGE_LIMIT = 1000, DEFAULT_SIGNATURE_TOLERANCE_MS, EventValidationError, defaultEventTypeCatalog, APP_EVENT_V1_MAX_DATA_BYTES;
15417
- var init_dist = __esm(() => {
15519
+ var init_dist2 = __esm(() => {
15418
15520
  DEFAULT_SIGNATURE_TOLERANCE_MS = 5 * 60 * 1000;
15419
15521
  EventValidationError = class EventValidationError extends Error {
15420
15522
  eventType;
@@ -15837,7 +15939,7 @@ function emitSharedTaskEventQuiet(input) {
15837
15939
  }
15838
15940
  var SOURCE = "todos";
15839
15941
  var init_shared_events = __esm(() => {
15840
- init_dist();
15942
+ init_dist2();
15841
15943
  init_database();
15842
15944
  init_projects();
15843
15945
  init_task_lists();
@@ -16594,14 +16696,14 @@ var init_task_parent_integrity = __esm(() => {
16594
16696
  });
16595
16697
 
16596
16698
  // src/lib/creator-identity.ts
16597
- import { existsSync as existsSync7, rmSync } from "fs";
16598
- import { join as join6 } from "path";
16699
+ import { existsSync as existsSync8, rmSync } from "fs";
16700
+ import { join as join8 } from "path";
16599
16701
  function identityFilePath() {
16600
- return join6(getTodosGlobalDir(), "identity.json");
16702
+ return join8(getTodosGlobalDir(), "identity.json");
16601
16703
  }
16602
16704
  function readPersistedIdentity() {
16603
16705
  const path = identityFilePath();
16604
- if (!existsSync7(path))
16706
+ if (!existsSync8(path))
16605
16707
  return null;
16606
16708
  const parsed = readJsonFile(path);
16607
16709
  if (!parsed || typeof parsed.agent_id !== "string" || !parsed.agent_id.trim())
@@ -16631,7 +16733,7 @@ function persistIdentity(identity) {
16631
16733
  }
16632
16734
  function clearPersistedIdentity() {
16633
16735
  const path = identityFilePath();
16634
- if (!existsSync7(path))
16736
+ if (!existsSync8(path))
16635
16737
  return false;
16636
16738
  try {
16637
16739
  rmSync(path);
@@ -18164,17 +18266,17 @@ function sanitizeCreateTaskInput(input) {
18164
18266
  return {
18165
18267
  ...input,
18166
18268
  title: sanitizePreWriteText(input.title, "task.title"),
18167
- description: input.description !== undefined ? sanitizePreWriteText(input.description, "task.description") : undefined,
18269
+ description: input.description == null ? input.description : sanitizePreWriteText(input.description, "task.description"),
18168
18270
  tags: input.tags !== undefined ? sanitizePreWriteValue(input.tags, "task.tags") : undefined,
18169
18271
  metadata: input.metadata !== undefined ? sanitizePreWriteValue(input.metadata, "task.metadata") : undefined,
18170
- reason: input.reason !== undefined ? sanitizePreWriteText(input.reason, "task.reason") : undefined
18272
+ reason: input.reason == null ? input.reason : sanitizePreWriteText(input.reason, "task.reason")
18171
18273
  };
18172
18274
  }
18173
18275
  function sanitizeUpdateTaskInput(input) {
18174
18276
  return {
18175
18277
  ...input,
18176
18278
  title: input.title !== undefined ? sanitizePreWriteText(input.title, "task.title") : undefined,
18177
- description: input.description !== undefined ? sanitizePreWriteText(input.description, "task.description") : undefined,
18279
+ description: input.description == null ? input.description : sanitizePreWriteText(input.description, "task.description"),
18178
18280
  tags: input.tags !== undefined ? sanitizePreWriteValue(input.tags, "task.tags") : undefined,
18179
18281
  metadata: input.metadata !== undefined ? sanitizePreWriteValue(input.metadata, "task.metadata") : undefined
18180
18282
  };
@@ -20188,28 +20290,28 @@ var init_boards = __esm(() => {
20188
20290
 
20189
20291
  // src/lib/artifact-store.ts
20190
20292
  import { createHash as createHash5 } from "crypto";
20191
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync4, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync3 } from "fs";
20192
- import { basename as basename2, dirname as dirname5, join as join7, resolve as resolve8 } from "path";
20293
+ import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync4, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync3 } from "fs";
20294
+ import { basename as basename2, dirname as dirname5, join as join9, resolve as resolve9 } from "path";
20193
20295
  import { tmpdir as tmpdir3 } from "os";
20194
20296
  function isInMemoryDb2(path) {
20195
20297
  return path === ":memory:" || path.startsWith("file::memory:");
20196
20298
  }
20197
20299
  function artifactStoreRoot() {
20198
20300
  if (process.env["HASNA_TODOS_ARTIFACTS_DIR"])
20199
- return resolve8(process.env["HASNA_TODOS_ARTIFACTS_DIR"]);
20301
+ return resolve9(process.env["HASNA_TODOS_ARTIFACTS_DIR"]);
20200
20302
  if (process.env["TODOS_ARTIFACTS_DIR"])
20201
- return resolve8(process.env["TODOS_ARTIFACTS_DIR"]);
20303
+ return resolve9(process.env["TODOS_ARTIFACTS_DIR"]);
20202
20304
  const dbPath = getDatabasePath();
20203
20305
  if (isInMemoryDb2(dbPath))
20204
- return join7(tmpdir3(), "hasna-todos-artifacts");
20205
- return join7(dirname5(resolve8(dbPath)), "artifacts");
20306
+ return join9(tmpdir3(), "hasna-todos-artifacts");
20307
+ return join9(dirname5(resolve9(dbPath)), "artifacts");
20206
20308
  }
20207
20309
  function artifactStorePath(relativePath) {
20208
20310
  const normalized = relativePath.replace(/\\/g, "/");
20209
20311
  if (normalized.includes("..") || normalized.startsWith("/") || normalized.length === 0) {
20210
20312
  throw new Error("Invalid artifact store path");
20211
20313
  }
20212
- return join7(artifactStoreRoot(), normalized);
20314
+ return join9(artifactStoreRoot(), normalized);
20213
20315
  }
20214
20316
  function sha2562(buffer) {
20215
20317
  return createHash5("sha256").update(buffer).digest("hex");
@@ -20249,8 +20351,8 @@ function mediaTypeFor(path, textLike) {
20249
20351
  return "application/octet-stream";
20250
20352
  }
20251
20353
  function storeArtifactContent(input) {
20252
- const sourcePath = resolve8(input.path);
20253
- if (!existsSync8(sourcePath))
20354
+ const sourcePath = resolve9(input.path);
20355
+ if (!existsSync9(sourcePath))
20254
20356
  return null;
20255
20357
  const sourceStat = statSync2(sourcePath);
20256
20358
  if (!sourceStat.isFile())
@@ -20267,9 +20369,9 @@ function storeArtifactContent(input) {
20267
20369
  redactionStatus = "redacted";
20268
20370
  }
20269
20371
  const storedSha = sha2562(storedBuffer);
20270
- const relativePath = join7("sha256", storedSha.slice(0, 2), storedSha).replace(/\\/g, "/");
20372
+ const relativePath = join9("sha256", storedSha.slice(0, 2), storedSha).replace(/\\/g, "/");
20271
20373
  const destination = artifactStorePath(relativePath);
20272
- if (!existsSync8(destination)) {
20374
+ if (!existsSync9(destination)) {
20273
20375
  mkdirSync5(dirname5(destination), { recursive: true });
20274
20376
  writeFileSync3(destination, storedBuffer);
20275
20377
  }
@@ -20329,7 +20431,7 @@ function verifyStoredArtifact(input) {
20329
20431
  };
20330
20432
  }
20331
20433
  const storedPath = artifactStorePath(store.relative_path);
20332
- if (!existsSync8(storedPath)) {
20434
+ if (!existsSync9(storedPath)) {
20333
20435
  return {
20334
20436
  id: input.id,
20335
20437
  path: input.path,
@@ -21930,8 +22032,8 @@ function normalizeAgentNameInput(name) {
21930
22032
 
21931
22033
  // src/lib/assignee-validation.ts
21932
22034
  import { readFileSync as readFileSync5 } from "fs";
21933
- import { homedir as homedir3 } from "os";
21934
- import { join as join8 } from "path";
22035
+ import { homedir as homedir5 } from "os";
22036
+ import { join as join10 } from "path";
21935
22037
  function describeAssigneeFilter(input, ctx) {
21936
22038
  const raw = input.trim();
21937
22039
  const normalized = normalizeAgentNameInput(raw);
@@ -21950,7 +22052,7 @@ function describeAssigneeFilter(input, ctx) {
21950
22052
  };
21951
22053
  }
21952
22054
  function defaultSeatRosterPath() {
21953
- return process.env["TODOS_SEAT_ROSTER_PATH"] || join8(homedir3(), ".hasna", "identities", "hasna-seats.roster.json");
22055
+ return process.env["TODOS_SEAT_ROSTER_PATH"] || join10(homedir5(), ".hasna", "identities", "hasna-seats.roster.json");
21954
22056
  }
21955
22057
  function loadSeatSlugs(path = defaultSeatRosterPath()) {
21956
22058
  try {
@@ -22756,7 +22858,7 @@ __export(exports_task_routing, {
22756
22858
  setTaskWorkflowPointers: () => setTaskWorkflowPointers,
22757
22859
  getTaskRouteState: () => getTaskRouteState
22758
22860
  });
22759
- import { existsSync as existsSync9, statSync as statSync3 } from "fs";
22861
+ import { existsSync as existsSync10, statSync as statSync3 } from "fs";
22760
22862
  function machineLocalPath(project, db) {
22761
22863
  const machineId = process.env["TODOS_MACHINE_ID"];
22762
22864
  if (!machineId)
@@ -22796,7 +22898,7 @@ function routeConcurrencyKey(task, project, taskList, projectPath) {
22796
22898
  }
22797
22899
  function directoryExists(path) {
22798
22900
  try {
22799
- return existsSync9(path) && statSync3(path).isDirectory();
22901
+ return existsSync10(path) && statSync3(path).isDirectory();
22800
22902
  } catch {
22801
22903
  return false;
22802
22904
  }
@@ -23025,7 +23127,7 @@ __export(exports_task_commands, {
23025
23127
  escapeTerminalControls: () => escapeTerminalControls
23026
23128
  });
23027
23129
  import chalk3 from "chalk";
23028
- import { basename as basename3, resolve as resolve9 } from "path";
23130
+ import { basename as basename3, resolve as resolve10 } from "path";
23029
23131
  function escapeTerminalControls(value) {
23030
23132
  return value.replace(/[\u0000-\u001f\u007f-\u009f]/g, (character) => {
23031
23133
  const code = character.charCodeAt(0);
@@ -23068,11 +23170,11 @@ async function cloudDetailGitRefs(cloud, id) {
23068
23170
  function resolveProjectIdOrSlug(input) {
23069
23171
  const db = getDatabase();
23070
23172
  if (isPathLike(input)) {
23071
- const projectPath = resolve9(input);
23173
+ const projectPath = resolve10(input);
23072
23174
  const byPath2 = getProjectByPath(projectPath, db);
23073
23175
  return (byPath2 ?? ensureProject(basename3(projectPath), projectPath, db)).id;
23074
23176
  }
23075
- const byPath = getProjectByPath(resolve9(input), db);
23177
+ const byPath = getProjectByPath(resolve10(input), db);
23076
23178
  if (byPath)
23077
23179
  return byPath.id;
23078
23180
  const byId = getProject(input, db);
@@ -23481,7 +23583,7 @@ function registerTaskCommands(program2) {
23481
23583
  task_list_id: taskListId2,
23482
23584
  tags: parseTags(opts.tags),
23483
23585
  metadata: buildExpectationMetadata(opts),
23484
- working_dir: opts.workingDir ? resolve9(opts.workingDir) : process.cwd(),
23586
+ working_dir: opts.workingDir ? resolve10(opts.workingDir) : process.cwd(),
23485
23587
  project_id: projectId2,
23486
23588
  assigned_to: opts.assign,
23487
23589
  plan_id: plan?.id
@@ -23518,7 +23620,7 @@ function registerTaskCommands(program2) {
23518
23620
  task_list_id: taskListId,
23519
23621
  tags: parseTags(opts.tags),
23520
23622
  metadata: buildExpectationMetadata(opts),
23521
- working_dir: opts.workingDir ? resolve9(opts.workingDir) : process.cwd(),
23623
+ working_dir: opts.workingDir ? resolve10(opts.workingDir) : process.cwd(),
23522
23624
  project_id: projectId,
23523
23625
  assigned_to: opts.assign,
23524
23626
  plan_id: planId,
@@ -24264,7 +24366,7 @@ ${chalk3.cyan(sid)} ${statusColor(task2.status)} ${prioColor(task2.priority)} ${
24264
24366
  tags: opts.tags ? opts.tags.split(",").map((t) => t.trim()) : undefined,
24265
24367
  plan_id: plan?.id ?? (opts.clearPlan ? null : undefined),
24266
24368
  ...reparent2,
24267
- working_dir: opts.workingDir ? resolve9(opts.workingDir) : opts.clearWorkingDir ? null : undefined,
24369
+ working_dir: opts.workingDir ? resolve10(opts.workingDir) : opts.clearWorkingDir ? null : undefined,
24268
24370
  estimated_minutes: opts.estimated !== undefined ? parseIntOption(opts.estimated, "--estimated") : undefined,
24269
24371
  sla_minutes: opts.slaMinutes !== undefined || opts.sla !== undefined ? parseIntOption(opts.slaMinutes ?? opts.sla, "--sla-minutes") : undefined,
24270
24372
  due_at: opts.due !== undefined ? opts.due === "" ? null : opts.due.length === 10 ? opts.due + "T00:00:00.000Z" : opts.due : undefined,
@@ -24309,7 +24411,7 @@ ${chalk3.cyan(sid)} ${statusColor(task2.status)} ${prioColor(task2.priority)} ${
24309
24411
  tags: opts.tags ? opts.tags.split(",").map((t) => t.trim()) : undefined,
24310
24412
  plan_id: planId,
24311
24413
  ...reparent,
24312
- working_dir: opts.workingDir ? resolve9(opts.workingDir) : opts.clearWorkingDir ? null : undefined,
24414
+ working_dir: opts.workingDir ? resolve10(opts.workingDir) : opts.clearWorkingDir ? null : undefined,
24313
24415
  estimated_minutes: opts.estimated !== undefined ? parseIntOption(opts.estimated, "--estimated") : undefined,
24314
24416
  sla_minutes: opts.slaMinutes !== undefined || opts.sla !== undefined ? parseIntOption(opts.slaMinutes ?? opts.sla, "--sla-minutes") : undefined,
24315
24417
  due_at: opts.due !== undefined ? opts.due === "" ? null : opts.due.length === 10 ? opts.due + "T00:00:00.000Z" : opts.due : undefined,
@@ -24827,8 +24929,8 @@ var init_plan_comments = __esm(() => {
24827
24929
  });
24828
24930
 
24829
24931
  // src/lib/plan-artifacts.ts
24830
- import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
24831
- import { join as join9, resolve as resolve10 } from "path";
24932
+ import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
24933
+ import { join as join11, resolve as resolve11 } from "path";
24832
24934
  function assertSafePathSegment(value, label) {
24833
24935
  const trimmed = value.trim();
24834
24936
  if (!trimmed || trimmed === "." || trimmed === ".." || trimmed.includes("/") || trimmed.includes("\\")) {
@@ -24871,7 +24973,7 @@ function resolvePlanArtifactProject(input) {
24871
24973
  const ref = input.project_id || input.project_ref;
24872
24974
  if (!ref)
24873
24975
  throw new Error("Plan artifacts require a project id or project reference");
24874
- const byPath = getProjectByPath(resolve10(ref), db);
24976
+ const byPath = getProjectByPath(resolve11(ref), db);
24875
24977
  if (byPath)
24876
24978
  return byPath;
24877
24979
  const resolvedId = resolvePartialId(db, "projects", ref);
@@ -24888,8 +24990,8 @@ function resolvePlanArtifactProject(input) {
24888
24990
  function resolvePlanArtifactPaths(input) {
24889
24991
  const project = resolvePlanArtifactProject(input);
24890
24992
  const projectId = assertSafePathSegment(project.id, "project id");
24891
- const projectRoot = resolve10(project.path);
24892
- const directory = join9(projectRoot, ".hasna", "todos", "plans", projectId);
24993
+ const projectRoot = resolve11(project.path);
24994
+ const directory = join11(projectRoot, ".hasna", "todos", "plans", projectId);
24893
24995
  const planId = input.plan_id ? assertSafePathSegment(input.plan_id, "plan id") : null;
24894
24996
  const planSlug = input.plan_slug ? assertSafePathSegment(slugify(input.plan_slug), "plan slug") : null;
24895
24997
  const fileName = planId ? planSlug ? `${planSlug}--${planId.slice(0, 8)}.md` : `${planId}.md` : null;
@@ -24897,7 +24999,7 @@ function resolvePlanArtifactPaths(input) {
24897
24999
  project_id: project.id,
24898
25000
  project_root: projectRoot,
24899
25001
  directory,
24900
- file_path: fileName ? join9(directory, fileName) : directory
25002
+ file_path: fileName ? join11(directory, fileName) : directory
24901
25003
  };
24902
25004
  }
24903
25005
  function resolvePlanArtifactCandidatePaths(plan, db) {
@@ -25063,7 +25165,7 @@ function readPlanArtifact(plan, db) {
25063
25165
  return null;
25064
25166
  const d = db || getDatabase();
25065
25167
  const paths = resolvePlanArtifactCandidatePaths(plan, d);
25066
- const path = existsSync10(paths.primary.file_path) ? paths.primary.file_path : existsSync10(paths.legacy.file_path) ? paths.legacy.file_path : null;
25168
+ const path = existsSync11(paths.primary.file_path) ? paths.primary.file_path : existsSync11(paths.legacy.file_path) ? paths.legacy.file_path : null;
25067
25169
  if (!path)
25068
25170
  return null;
25069
25171
  const markdown = readFileSync6(path, "utf8");
@@ -25078,7 +25180,7 @@ function inspectPlanArtifact(plan, db) {
25078
25180
  return null;
25079
25181
  const d = db || getDatabase();
25080
25182
  const paths = resolvePlanArtifactCandidatePaths(plan, d);
25081
- const path = existsSync10(paths.primary.file_path) ? paths.primary.file_path : existsSync10(paths.legacy.file_path) ? paths.legacy.file_path : null;
25183
+ const path = existsSync11(paths.primary.file_path) ? paths.primary.file_path : existsSync11(paths.legacy.file_path) ? paths.legacy.file_path : null;
25082
25184
  if (!path) {
25083
25185
  return {
25084
25186
  path: paths.primary.file_path,
@@ -26554,7 +26656,7 @@ __export(exports_builtin_templates, {
26554
26656
  BUILTIN_TEMPLATES: () => BUILTIN_TEMPLATES
26555
26657
  });
26556
26658
  import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync5 } from "fs";
26557
- import { join as join10 } from "path";
26659
+ import { join as join12 } from "path";
26558
26660
  function templateMetadata(template) {
26559
26661
  return {
26560
26662
  source: BUILTIN_TEMPLATE_LIBRARY_SOURCE,
@@ -26613,7 +26715,7 @@ function writeBuiltinTemplateFiles(directory) {
26613
26715
  mkdirSync7(directory, { recursive: true });
26614
26716
  const files = [];
26615
26717
  for (const entry of exportBuiltinTemplateFiles()) {
26616
- const path = join10(directory, entry.filename);
26718
+ const path = join12(directory, entry.filename);
26617
26719
  writeFileSync5(path, `${JSON.stringify(entry.template, null, 2)}
26618
26720
  `, "utf-8");
26619
26721
  files.push(path);
@@ -28305,16 +28407,16 @@ var init_saved_search_views = __esm(() => {
28305
28407
  });
28306
28408
 
28307
28409
  // src/lib/claude-tasks.ts
28308
- import { existsSync as existsSync11, readFileSync as readFileSync7, readdirSync as readdirSync2, writeFileSync as writeFileSync6 } from "fs";
28309
- import { join as join11 } from "path";
28410
+ import { existsSync as existsSync12, readFileSync as readFileSync7, readdirSync as readdirSync2, writeFileSync as writeFileSync6 } from "fs";
28411
+ import { join as join13 } from "path";
28310
28412
  function getTaskListDir(taskListId) {
28311
- return join11(HOME, ".claude", "tasks", taskListId);
28413
+ return join13(HOME, ".claude", "tasks", taskListId);
28312
28414
  }
28313
28415
  function readClaudeTask(dir, filename) {
28314
- return readJsonFile(join11(dir, filename));
28416
+ return readJsonFile(join13(dir, filename));
28315
28417
  }
28316
28418
  function writeClaudeTask(dir, task) {
28317
- writeJsonFile(join11(dir, `${task.id}.json`), task);
28419
+ writeJsonFile(join13(dir, `${task.id}.json`), task);
28318
28420
  }
28319
28421
  function toClaudeStatus(status) {
28320
28422
  if (status === "pending" || status === "in_progress" || status === "completed") {
@@ -28326,14 +28428,14 @@ function toSqliteStatus(status) {
28326
28428
  return status;
28327
28429
  }
28328
28430
  function readPrefixCounter(dir) {
28329
- const path = join11(dir, ".prefix-counter");
28330
- if (!existsSync11(path))
28431
+ const path = join13(dir, ".prefix-counter");
28432
+ if (!existsSync12(path))
28331
28433
  return 0;
28332
28434
  const val = parseInt(readFileSync7(path, "utf-8").trim(), 10);
28333
28435
  return isNaN(val) ? 0 : val;
28334
28436
  }
28335
28437
  function writePrefixCounter(dir, value) {
28336
- writeFileSync6(join11(dir, ".prefix-counter"), String(value));
28438
+ writeFileSync6(join13(dir, ".prefix-counter"), String(value));
28337
28439
  }
28338
28440
  function formatPrefixedSubject(title, prefix, counter) {
28339
28441
  const padded = String(counter).padStart(5, "0");
@@ -28360,7 +28462,7 @@ function taskToClaudeTask(task, claudeTaskId, existingMeta) {
28360
28462
  }
28361
28463
  function pushToClaudeTaskList(taskListId, projectId, options = {}) {
28362
28464
  const dir = getTaskListDir(taskListId);
28363
- if (!existsSync11(dir))
28465
+ if (!existsSync12(dir))
28364
28466
  ensureDir(dir);
28365
28467
  const filter = {};
28366
28468
  if (projectId)
@@ -28369,7 +28471,7 @@ function pushToClaudeTaskList(taskListId, projectId, options = {}) {
28369
28471
  const existingByTodosId = new Map;
28370
28472
  const files = listJsonFiles(dir);
28371
28473
  for (const f of files) {
28372
- const path = join11(dir, f);
28474
+ const path = join13(dir, f);
28373
28475
  const ct = readClaudeTask(dir, f);
28374
28476
  if (ct?.metadata?.["todos_id"]) {
28375
28477
  existingByTodosId.set(ct.metadata["todos_id"], { task: ct, mtimeMs: getFileMtimeMs(path) });
@@ -28458,7 +28560,7 @@ function pushToClaudeTaskList(taskListId, projectId, options = {}) {
28458
28560
  }
28459
28561
  function pullFromClaudeTaskList(taskListId, projectId, options = {}) {
28460
28562
  const dir = getTaskListDir(taskListId);
28461
- if (!existsSync11(dir)) {
28563
+ if (!existsSync12(dir)) {
28462
28564
  return { pushed: 0, pulled: 0, errors: [`Task list directory not found: ${dir}`] };
28463
28565
  }
28464
28566
  const files = readdirSync2(dir).filter((f) => f.endsWith(".json"));
@@ -28478,7 +28580,7 @@ function pullFromClaudeTaskList(taskListId, projectId, options = {}) {
28478
28580
  }
28479
28581
  for (const f of files) {
28480
28582
  try {
28481
- const filePath = join11(dir, f);
28583
+ const filePath = join13(dir, f);
28482
28584
  const ct = readClaudeTask(dir, f);
28483
28585
  if (!ct)
28484
28586
  continue;
@@ -28551,20 +28653,20 @@ var init_claude_tasks = __esm(() => {
28551
28653
  });
28552
28654
 
28553
28655
  // src/lib/agent-tasks.ts
28554
- import { existsSync as existsSync12 } from "fs";
28555
- import { join as join12 } from "path";
28656
+ import { existsSync as existsSync13 } from "fs";
28657
+ import { join as join14 } from "path";
28556
28658
  function agentBaseDir(agent) {
28557
28659
  const key = `TODOS_${agent.toUpperCase()}_TASKS_DIR`;
28558
- return process.env[key] || getAgentTasksDir(agent) || process.env["TODOS_AGENT_TASKS_DIR"] || join12(getTodosGlobalDir(), "agents");
28660
+ return process.env[key] || getAgentTasksDir(agent) || process.env["TODOS_AGENT_TASKS_DIR"] || join14(getTodosGlobalDir(), "agents");
28559
28661
  }
28560
28662
  function getTaskListDir2(agent, taskListId) {
28561
- return join12(agentBaseDir(agent), agent, taskListId);
28663
+ return join14(agentBaseDir(agent), agent, taskListId);
28562
28664
  }
28563
28665
  function readAgentTask(dir, filename) {
28564
- return readJsonFile(join12(dir, filename));
28666
+ return readJsonFile(join14(dir, filename));
28565
28667
  }
28566
28668
  function writeAgentTask(dir, task) {
28567
- writeJsonFile(join12(dir, `${task.id}.json`), task);
28669
+ writeJsonFile(join14(dir, `${task.id}.json`), task);
28568
28670
  }
28569
28671
  function taskToAgentTask(task, externalId, existingMeta) {
28570
28672
  return withSyncFingerprint({
@@ -28589,7 +28691,7 @@ function metadataKey(agent) {
28589
28691
  }
28590
28692
  function pushToAgentTaskList(agent, taskListId, projectId, options = {}) {
28591
28693
  const dir = getTaskListDir2(agent, taskListId);
28592
- if (!existsSync12(dir))
28694
+ if (!existsSync13(dir))
28593
28695
  ensureDir(dir);
28594
28696
  const filter = {};
28595
28697
  if (projectId)
@@ -28598,7 +28700,7 @@ function pushToAgentTaskList(agent, taskListId, projectId, options = {}) {
28598
28700
  const existingByTodosId = new Map;
28599
28701
  const files = listJsonFiles(dir);
28600
28702
  for (const f of files) {
28601
- const path = join12(dir, f);
28703
+ const path = join14(dir, f);
28602
28704
  const at = readAgentTask(dir, f);
28603
28705
  if (at?.metadata?.["todos_id"]) {
28604
28706
  existingByTodosId.set(at.metadata["todos_id"], { task: at, mtimeMs: getFileMtimeMs(path) });
@@ -28674,7 +28776,7 @@ function pushToAgentTaskList(agent, taskListId, projectId, options = {}) {
28674
28776
  }
28675
28777
  function pullFromAgentTaskList(agent, taskListId, projectId, options = {}) {
28676
28778
  const dir = getTaskListDir2(agent, taskListId);
28677
- if (!existsSync12(dir)) {
28779
+ if (!existsSync13(dir)) {
28678
28780
  return { pushed: 0, pulled: 0, errors: [`Task list directory not found: ${dir}`] };
28679
28781
  }
28680
28782
  const files = listJsonFiles(dir);
@@ -28693,7 +28795,7 @@ function pullFromAgentTaskList(agent, taskListId, projectId, options = {}) {
28693
28795
  }
28694
28796
  for (const f of files) {
28695
28797
  try {
28696
- const filePath = join12(dir, f);
28798
+ const filePath = join14(dir, f);
28697
28799
  const at = readAgentTask(dir, f);
28698
28800
  if (!at)
28699
28801
  continue;
@@ -29101,8 +29203,8 @@ __export(exports_project_bootstrap, {
29101
29203
  discoverProjectWorkspace: () => discoverProjectWorkspace,
29102
29204
  bootstrapProject: () => bootstrapProject
29103
29205
  });
29104
- import { existsSync as existsSync13, readFileSync as readFileSync8, statSync as statSync4 } from "fs";
29105
- import { basename as basename4, dirname as dirname6, resolve as resolve11 } from "path";
29206
+ import { existsSync as existsSync14, readFileSync as readFileSync8, statSync as statSync4 } from "fs";
29207
+ import { basename as basename4, dirname as dirname6, resolve as resolve12 } from "path";
29106
29208
  function safeStat(path) {
29107
29209
  try {
29108
29210
  return statSync4(path);
@@ -29111,7 +29213,7 @@ function safeStat(path) {
29111
29213
  }
29112
29214
  }
29113
29215
  function canonicalPath(input) {
29114
- const resolved = resolve11(input);
29216
+ const resolved = resolve12(input);
29115
29217
  const stats = safeStat(resolved);
29116
29218
  if (stats?.isFile())
29117
29219
  return dirname6(resolved);
@@ -29120,7 +29222,7 @@ function canonicalPath(input) {
29120
29222
  function findUp(start, marker) {
29121
29223
  let current = canonicalPath(start);
29122
29224
  while (true) {
29123
- if (existsSync13(resolve11(current, marker)))
29225
+ if (existsSync14(resolve12(current, marker)))
29124
29226
  return current;
29125
29227
  const parent = dirname6(current);
29126
29228
  if (parent === current)
@@ -29131,8 +29233,8 @@ function findUp(start, marker) {
29131
29233
  function readPackageJson(path) {
29132
29234
  if (!path)
29133
29235
  return null;
29134
- const file = resolve11(path, "package.json");
29135
- if (!existsSync13(file))
29236
+ const file = resolve12(path, "package.json");
29237
+ if (!existsSync14(file))
29136
29238
  return null;
29137
29239
  try {
29138
29240
  const parsed = JSON.parse(readFileSync8(file, "utf-8"));
@@ -29154,7 +29256,7 @@ function workspaceMarker(root, rootPackage) {
29154
29256
  if (rootPackage?.workspaces)
29155
29257
  markers.push("package.json#workspaces");
29156
29258
  for (const marker of ["pnpm-workspace.yaml", "turbo.json", "nx.json", "lerna.json", "rush.json", "bun.lock", "bun.lockb"]) {
29157
- if (existsSync13(resolve11(root, marker)))
29259
+ if (existsSync14(resolve12(root, marker)))
29158
29260
  markers.push(marker);
29159
29261
  }
29160
29262
  const kind = markers.find((marker) => marker !== "bun.lock" && marker !== "bun.lockb") ?? null;
@@ -29488,9 +29590,9 @@ __export(exports_extract, {
29488
29590
  buildCodebaseIndex: () => buildCodebaseIndex,
29489
29591
  EXTRACT_TAGS: () => EXTRACT_TAGS
29490
29592
  });
29491
- import { existsSync as existsSync14, readFileSync as readFileSync9, statSync as statSync5 } from "fs";
29593
+ import { existsSync as existsSync15, readFileSync as readFileSync9, statSync as statSync5 } from "fs";
29492
29594
  import { createHash as createHash7 } from "crypto";
29493
- import { relative as relative3, resolve as resolve12, join as join13 } from "path";
29595
+ import { relative as relative3, resolve as resolve13, join as join15 } from "path";
29494
29596
  function stableHash(value) {
29495
29597
  return createHash7("sha256").update(value).digest("hex");
29496
29598
  }
@@ -29498,9 +29600,9 @@ function normalizePathForMatch(value) {
29498
29600
  return value.replace(/\\/g, "/").replace(/^\.\//, "");
29499
29601
  }
29500
29602
  function readGitignorePatterns(basePath) {
29501
- const root = statSync5(basePath).isFile() ? resolve12(basePath, "..") : basePath;
29502
- const gitignorePath = join13(root, ".gitignore");
29503
- if (!existsSync14(gitignorePath))
29603
+ const root = statSync5(basePath).isFile() ? resolve13(basePath, "..") : basePath;
29604
+ const gitignorePath = join15(root, ".gitignore");
29605
+ if (!existsSync15(gitignorePath))
29504
29606
  return [];
29505
29607
  try {
29506
29608
  return readFileSync9(gitignorePath, "utf-8").split(`
@@ -29634,7 +29736,7 @@ function collectFiles(basePath, extensions, excludes, respectGitignore) {
29634
29736
  return files.sort();
29635
29737
  }
29636
29738
  function buildCodebaseIndex(options) {
29637
- const basePath = resolve12(options.path);
29739
+ const basePath = resolve13(options.path);
29638
29740
  const tags = options.patterns || [...EXTRACT_TAGS];
29639
29741
  const extensions = options.extensions ? new Set(options.extensions.map((e) => e.startsWith(".") ? e : `.${e}`)) : DEFAULT_EXTENSIONS;
29640
29742
  const excludes = options.exclude || [];
@@ -29642,10 +29744,10 @@ function buildCodebaseIndex(options) {
29642
29744
  const files = collectFiles(basePath, extensions, excludes, respectGitignore);
29643
29745
  const indexed = [];
29644
29746
  for (const file of files) {
29645
- const fullPath = statSync5(basePath).isFile() ? basePath : join13(basePath, file);
29747
+ const fullPath = statSync5(basePath).isFile() ? basePath : join15(basePath, file);
29646
29748
  try {
29647
29749
  const source = readFileSync9(fullPath, "utf-8");
29648
- const relPath = statSync5(basePath).isFile() ? relative3(resolve12(basePath, ".."), fullPath) : file;
29750
+ const relPath = statSync5(basePath).isFile() ? relative3(resolve13(basePath, ".."), fullPath) : file;
29649
29751
  indexed.push({
29650
29752
  file: relPath,
29651
29753
  checksum: stableHash(source).slice(0, 24),
@@ -29665,7 +29767,7 @@ function buildCodebaseIndex(options) {
29665
29767
  };
29666
29768
  }
29667
29769
  function extractTodos(options, db) {
29668
- const basePath = resolve12(options.path);
29770
+ const basePath = resolve13(options.path);
29669
29771
  const tags = options.patterns || [...EXTRACT_TAGS];
29670
29772
  const extensions = options.extensions ? new Set(options.extensions.map((e) => e.startsWith(".") ? e : `.${e}`)) : DEFAULT_EXTENSIONS;
29671
29773
  const excludes = options.exclude || [];
@@ -29673,10 +29775,10 @@ function extractTodos(options, db) {
29673
29775
  const files = collectFiles(basePath, extensions, excludes, respectGitignore);
29674
29776
  const allComments = [];
29675
29777
  for (const file of files) {
29676
- const fullPath = statSync5(basePath).isFile() ? basePath : join13(basePath, file);
29778
+ const fullPath = statSync5(basePath).isFile() ? basePath : join15(basePath, file);
29677
29779
  try {
29678
29780
  const source = readFileSync9(fullPath, "utf-8");
29679
- const relPath = statSync5(basePath).isFile() ? relative3(resolve12(basePath, ".."), fullPath) : file;
29781
+ const relPath = statSync5(basePath).isFile() ? relative3(resolve13(basePath, ".."), fullPath) : file;
29680
29782
  const comments = extractFromSource(source, relPath, tags);
29681
29783
  allComments.push(...comments);
29682
29784
  } catch {}
@@ -29770,7 +29872,7 @@ async function watchSourceTodos(options, onRun) {
29770
29872
  const interval = Math.max(100, options.interval_ms || 2000);
29771
29873
  const once = options.once !== false && (!options.max_runs || options.max_runs <= 1);
29772
29874
  const maxRuns = options.max_runs ?? (once ? 1 : Number.POSITIVE_INFINITY);
29773
- const root = resolve12(options.path);
29875
+ const root = resolve13(options.path);
29774
29876
  const runs = [];
29775
29877
  let previous = new Map;
29776
29878
  for (let runNumber = 1;runNumber <= maxRuns; runNumber++) {
@@ -31006,7 +31108,7 @@ __export(exports_project_commands, {
31006
31108
  });
31007
31109
  import chalk5 from "chalk";
31008
31110
  import { readFileSync as readFileSync10, statSync as statSync6 } from "fs";
31009
- import { basename as basename5, resolve as resolve13, sep as sep3 } from "path";
31111
+ import { basename as basename5, resolve as resolve14, sep as sep3 } from "path";
31010
31112
  function collectOption(value, previous = []) {
31011
31113
  return [...previous, value];
31012
31114
  }
@@ -31085,8 +31187,8 @@ function countTasksForDeregistration(tasks) {
31085
31187
  };
31086
31188
  }
31087
31189
  function pathIsWithinPrefix(projectPath, prefix) {
31088
- const normalizedPath = resolve13(projectPath);
31089
- const normalizedPrefix = resolve13(prefix);
31190
+ const normalizedPath = resolve14(projectPath);
31191
+ const normalizedPrefix = resolve14(prefix);
31090
31192
  return normalizedPath === normalizedPrefix || normalizedPath.startsWith(`${normalizedPrefix}${sep3}`);
31091
31193
  }
31092
31194
  function resolveTaskListFilter(input, projectId) {
@@ -31298,7 +31400,7 @@ function registerProjectCommands(program2) {
31298
31400
  }
31299
31401
  let content;
31300
31402
  if (opts.file !== undefined) {
31301
- const commentFilePath = resolve13(opts.file);
31403
+ const commentFilePath = resolve14(opts.file);
31302
31404
  let isRegularFile = false;
31303
31405
  try {
31304
31406
  isRegularFile = statSync6(commentFilePath).isFile();
@@ -31723,7 +31825,7 @@ function registerProjectCommands(program2) {
31723
31825
  if (opts.update) {
31724
31826
  const patch = {
31725
31827
  ...opts.name !== undefined ? { name: opts.name } : {},
31726
- ...opts.path !== undefined ? { path: resolve13(opts.path) } : {},
31828
+ ...opts.path !== undefined ? { path: resolve14(opts.path) } : {},
31727
31829
  ...opts.description !== undefined ? { description: opts.description } : {}
31728
31830
  };
31729
31831
  if (Object.keys(patch).length === 0) {
@@ -31767,7 +31869,7 @@ function registerProjectCommands(program2) {
31767
31869
  return;
31768
31870
  }
31769
31871
  if (opts.add) {
31770
- const projectPath = resolve13(opts.add);
31872
+ const projectPath = resolve14(opts.add);
31771
31873
  const name = opts.name || basename5(projectPath);
31772
31874
  let parentId;
31773
31875
  if (opts.parent !== undefined) {
@@ -31896,7 +31998,7 @@ function registerProjectCommands(program2) {
31896
31998
  if (!resolved) {
31897
31999
  handleError(new Error(`Project not found: ${projectId}`));
31898
32000
  }
31899
- const entry = setMachineLocalPath2(resolved, resolve13(projectPath));
32001
+ const entry = setMachineLocalPath2(resolved, resolve14(projectPath));
31900
32002
  if (useJson) {
31901
32003
  output(entry, true);
31902
32004
  } else {
@@ -31958,7 +32060,7 @@ function registerProjectCommands(program2) {
31958
32060
  const patterns = opts.pattern ? opts.pattern.split(",").map((t) => t.trim().toUpperCase()) : undefined;
31959
32061
  const taskListId = opts.list ? resolveTaskListId(opts.list) : undefined;
31960
32062
  const result = extractTodos2({
31961
- path: resolve13(scanPath),
32063
+ path: resolve14(scanPath),
31962
32064
  patterns,
31963
32065
  project_id: projectId,
31964
32066
  task_list_id: taskListId,
@@ -32019,7 +32121,7 @@ Indexed ${result.index.files.length} file(s), ${result.index.total_symbols} symb
32019
32121
  const taskListId = opts.list ? resolveTaskListId(opts.list) : undefined;
32020
32122
  const maxRuns = opts.maxRuns ? parseInt(opts.maxRuns, 10) : 1;
32021
32123
  const result = await watchSourceTodos2({
32022
- path: resolve13(scanPath),
32124
+ path: resolve14(scanPath),
32023
32125
  patterns,
32024
32126
  project_id: projectId,
32025
32127
  task_list_id: taskListId,
@@ -32057,7 +32159,7 @@ Indexed ${result.index.files.length} file(s), ${result.index.total_symbols} symb
32057
32159
  const writeOutput = async (content) => {
32058
32160
  if (opts.output) {
32059
32161
  const { writeFileSync: writeFileSync7 } = await import("fs");
32060
- writeFileSync7(resolve13(opts.output), content.endsWith(`
32162
+ writeFileSync7(resolve14(opts.output), content.endsWith(`
32061
32163
  `) ? content : `${content}
32062
32164
  `);
32063
32165
  } else {
@@ -32075,12 +32177,12 @@ Indexed ${result.index.files.length} file(s), ${result.index.total_symbols} symb
32075
32177
  const exported = opts.encrypt ? createEncryptedBridgeBundle2(bundle, { profile: opts.encryptionProfile }) : bundle;
32076
32178
  const json = JSON.stringify(exported, null, 2);
32077
32179
  await writeOutput(json);
32078
- emitLocalEventHooksQuiet3({ type: "export.finished", payload: { format: "bridge", encrypted: Boolean(opts.encrypt), project_id: projectId, output: opts.output ? resolve13(opts.output) : null, stats: bundle.stats } });
32180
+ emitLocalEventHooksQuiet3({ type: "export.finished", payload: { format: "bridge", encrypted: Boolean(opts.encrypt), project_id: projectId, output: opts.output ? resolve14(opts.output) : null, stats: bundle.stats } });
32079
32181
  if (!opts.encrypt && !opts.allowPlaintextSensitive) {
32080
32182
  console.error(chalk5.dim("Bridge export redacted sensitive fields. Use --encrypt for an encrypted local bundle when a lossless legacy snapshot is required."));
32081
32183
  }
32082
32184
  if (opts.output && !globalOpts.json) {
32083
- console.log(chalk5.green(`${opts.encrypt ? "Encrypted bridge export" : "Bridge export"} written to ${resolve13(opts.output)}`));
32185
+ console.log(chalk5.green(`${opts.encrypt ? "Encrypted bridge export" : "Bridge export"} written to ${resolve14(opts.output)}`));
32084
32186
  }
32085
32187
  return;
32086
32188
  }
@@ -32093,7 +32195,7 @@ Indexed ${result.index.files.length} file(s), ${result.index.total_symbols} symb
32093
32195
  await writeOutput(JSON.stringify(tasks, null, 2));
32094
32196
  }
32095
32197
  const { emitLocalEventHooksQuiet: emitLocalEventHooksQuiet2 } = await Promise.resolve().then(() => (init_event_hooks(), exports_event_hooks));
32096
- emitLocalEventHooksQuiet2({ type: "export.finished", payload: { format: opts.format, project_id: projectId, output: opts.output ? resolve13(opts.output) : null, count: exportedCount } });
32198
+ emitLocalEventHooksQuiet2({ type: "export.finished", payload: { format: opts.format, project_id: projectId, output: opts.output ? resolve14(opts.output) : null, count: exportedCount } });
32097
32199
  });
32098
32200
  program2.command("bridge-import <file>").description("Dry-run or apply a local hasna/todos bridge export bundle").option("--apply", "Apply the import. Defaults to dry-run.").option("--decrypt", "Decrypt an encrypted bridge export before importing").option("--resolve-conflicts", "Safely merge existing local tasks by filling blank fields, unioning tags, and recording unresolved divergences").action(async (file, opts) => {
32099
32201
  const globalOpts = program2.opts();
@@ -32101,13 +32203,13 @@ Indexed ${result.index.files.length} file(s), ${result.index.total_symbols} symb
32101
32203
  const { readFileSync: readFileSync11 } = await import("fs");
32102
32204
  const { importLocalBridgeBundle: importLocalBridgeBundle2 } = await Promise.resolve().then(() => (init_local_bridge(), exports_local_bridge));
32103
32205
  const { decryptBridgeBundle: decryptBridgeBundle2, isEncryptedBridgeBundle: isEncryptedBridgeBundle2 } = await Promise.resolve().then(() => (init_local_encryption(), exports_local_encryption));
32104
- const parsed = JSON.parse(readFileSync11(resolve13(file), "utf-8"));
32206
+ const parsed = JSON.parse(readFileSync11(resolve14(file), "utf-8"));
32105
32207
  const bundle = isEncryptedBridgeBundle2(parsed) ? opts.decrypt ? decryptBridgeBundle2(parsed) : (() => {
32106
32208
  throw new Error("Bridge bundle is encrypted. Re-run with --decrypt and the configured key environment variable set.");
32107
32209
  })() : parsed;
32108
32210
  const result = importLocalBridgeBundle2(bundle, { dryRun: !opts.apply, conflictStrategy: opts.resolveConflicts ? "safe_merge" : "skip" });
32109
32211
  const { emitLocalEventHooksQuiet: emitLocalEventHooksQuiet2 } = await Promise.resolve().then(() => (init_event_hooks(), exports_event_hooks));
32110
- emitLocalEventHooksQuiet2({ type: "import.finished", payload: { file: resolve13(file), dry_run: result.dry_run, ok: result.ok, inserted: result.inserted, skipped: result.skipped, conflicts: result.conflicts.length, issues: result.issues.length } });
32212
+ emitLocalEventHooksQuiet2({ type: "import.finished", payload: { file: resolve14(file), dry_run: result.dry_run, ok: result.ok, inserted: result.inserted, skipped: result.skipped, conflicts: result.conflicts.length, issues: result.issues.length } });
32111
32213
  if (globalOpts.json) {
32112
32214
  output(result, true);
32113
32215
  return;
@@ -32137,9 +32239,9 @@ Indexed ${result.index.files.length} file(s), ${result.index.total_symbols} symb
32137
32239
  try {
32138
32240
  const { readFileSync: readFileSync11 } = await import("fs");
32139
32241
  const { importTodosMarkdown: importTodosMarkdown2 } = await Promise.resolve().then(() => (init_todos_md(), exports_todos_md));
32140
- const result = importTodosMarkdown2(readFileSync11(resolve13(file), "utf-8"), { dryRun: !opts.apply, conflictStrategy: opts.resolveConflicts ? "safe_merge" : "skip" });
32242
+ const result = importTodosMarkdown2(readFileSync11(resolve14(file), "utf-8"), { dryRun: !opts.apply, conflictStrategy: opts.resolveConflicts ? "safe_merge" : "skip" });
32141
32243
  const { emitLocalEventHooksQuiet: emitLocalEventHooksQuiet2 } = await Promise.resolve().then(() => (init_event_hooks(), exports_event_hooks));
32142
- emitLocalEventHooksQuiet2({ type: "import.finished", payload: { file: resolve13(file), format: "todos.md", dry_run: result.dry_run, ok: result.ok, inserted: result.inserted, skipped: result.skipped, issues: result.issues.length } });
32244
+ emitLocalEventHooksQuiet2({ type: "import.finished", payload: { file: resolve14(file), format: "todos.md", dry_run: result.dry_run, ok: result.ok, inserted: result.inserted, skipped: result.skipped, issues: result.issues.length } });
32143
32245
  if (globalOpts.json) {
32144
32246
  output(result, true);
32145
32247
  return;
@@ -35272,7 +35374,7 @@ async function retryOnTransientPostgresError(fn, attempts = 2, delayMs = 150) {
35272
35374
  lastError = error;
35273
35375
  if (!isTransientPostgresError(error) || attempt === attempts)
35274
35376
  throw error;
35275
- await new Promise((resolve14) => setTimeout(resolve14, delayMs * attempt));
35377
+ await new Promise((resolve15) => setTimeout(resolve15, delayMs * attempt));
35276
35378
  }
35277
35379
  }
35278
35380
  throw lastError;
@@ -36401,8 +36503,8 @@ class SqliteTodosProjectRegistrationBackend {
36401
36503
  async transaction(fn) {
36402
36504
  const previous = sqliteTransactionTails.get(this.db) ?? Promise.resolve();
36403
36505
  let release;
36404
- const current = new Promise((resolve14) => {
36405
- release = resolve14;
36506
+ const current = new Promise((resolve15) => {
36507
+ release = resolve15;
36406
36508
  });
36407
36509
  sqliteTransactionTails.set(this.db, current);
36408
36510
  await previous;
@@ -39165,8 +39267,8 @@ var init_ai = __esm(() => {
39165
39267
  });
39166
39268
 
39167
39269
  // src/lib/access-profiles.ts
39168
- function resolveAccessProfile(envValue) {
39169
- const raw = (envValue ?? process.env["TODOS_PROFILE"] ?? "full").toLowerCase();
39270
+ function resolveAccessProfile(envValue2) {
39271
+ const raw = (envValue2 ?? process.env["TODOS_PROFILE"] ?? "full").toLowerCase();
39170
39272
  if (ACCESS_PROFILES.includes(raw))
39171
39273
  return raw;
39172
39274
  if (raw === "readonly")
@@ -40791,7 +40893,7 @@ function errorResult(runId, error) {
40791
40893
  return createTodosAiFailureResult(runId, "internal_error", "optional AI runtime failed");
40792
40894
  }
40793
40895
  async function withLoadDeadline(operation, controller, timeoutMs) {
40794
- return new Promise((resolve14, reject) => {
40896
+ return new Promise((resolve15, reject) => {
40795
40897
  let settled = false;
40796
40898
  const settle = (callback) => {
40797
40899
  if (settled)
@@ -40805,11 +40907,11 @@ async function withLoadDeadline(operation, controller, timeoutMs) {
40805
40907
  controller.abort(error);
40806
40908
  settle(() => reject(error));
40807
40909
  }, timeoutMs);
40808
- Promise.resolve().then(operation).then((value) => settle(() => resolve14(value)), (error) => settle(() => reject(error)));
40910
+ Promise.resolve().then(operation).then((value) => settle(() => resolve15(value)), (error) => settle(() => reject(error)));
40809
40911
  });
40810
40912
  }
40811
40913
  async function withInterrupt(operation, controller) {
40812
- return new Promise((resolve14, reject) => {
40914
+ return new Promise((resolve15, reject) => {
40813
40915
  let settled = false;
40814
40916
  const settle = (callback) => {
40815
40917
  if (settled)
@@ -40824,7 +40926,7 @@ async function withInterrupt(operation, controller) {
40824
40926
  settle(() => reject(error));
40825
40927
  };
40826
40928
  process.once("SIGINT", onInterrupt);
40827
- Promise.resolve().then(operation).then((value) => settle(() => resolve14(value)), (error) => settle(() => reject(error)));
40929
+ Promise.resolve().then(operation).then((value) => settle(() => resolve15(value)), (error) => settle(() => reject(error)));
40828
40930
  });
40829
40931
  }
40830
40932
  function throwIfAborted(signal) {
@@ -41112,14 +41214,14 @@ async function findFreePort(start) {
41112
41214
  var DEFAULT_PORT = 19427;
41113
41215
 
41114
41216
  // src/lib/db-backup.ts
41115
- import { existsSync as existsSync15, copyFileSync, mkdirSync as mkdirSync8, readFileSync as readFileSync12, renameSync, statSync as statSync7, writeFileSync as writeFileSync7, unlinkSync } from "fs";
41116
- import { dirname as dirname7, join as join14, resolve as resolve14 } from "path";
41217
+ import { existsSync as existsSync16, copyFileSync, mkdirSync as mkdirSync8, readFileSync as readFileSync12, renameSync, statSync as statSync7, writeFileSync as writeFileSync7, unlinkSync } from "fs";
41218
+ import { dirname as dirname7, join as join16, resolve as resolve15 } from "path";
41117
41219
  import { Database as Database2 } from "bun:sqlite";
41118
41220
  function resolveDbPath(dbPath) {
41119
41221
  if (dbPath)
41120
- return resolve14(dbPath);
41222
+ return resolve15(dbPath);
41121
41223
  if (process.env["TODOS_DB_PATH"] && process.env["TODOS_DB_PATH"] !== ":memory:") {
41122
- return resolve14(process.env["TODOS_DB_PATH"]);
41224
+ return resolve15(process.env["TODOS_DB_PATH"]);
41123
41225
  }
41124
41226
  const db = getDatabase();
41125
41227
  const filename = db.filename;
@@ -41129,7 +41231,7 @@ function resolveDbPath(dbPath) {
41129
41231
  }
41130
41232
  function backupDatabase(outputPath, sourcePath) {
41131
41233
  const source = resolveDbPath(sourcePath);
41132
- if (!existsSync15(source))
41234
+ if (!existsSync16(source))
41133
41235
  throw new Error(`Database not found: ${source}`);
41134
41236
  mkdirSync8(dirname7(outputPath), { recursive: true });
41135
41237
  closeDatabase();
@@ -41152,9 +41254,9 @@ function backupDatabase(outputPath, sourcePath) {
41152
41254
  };
41153
41255
  }
41154
41256
  function checkDatabaseIntegrity(dbPath) {
41155
- const path = dbPath ? resolve14(dbPath) : resolveDbPath();
41257
+ const path = dbPath ? resolve15(dbPath) : resolveDbPath();
41156
41258
  const errors = [];
41157
- if (!existsSync15(path)) {
41259
+ if (!existsSync16(path)) {
41158
41260
  return {
41159
41261
  schema_version: DB_BACKUP_SCHEMA,
41160
41262
  path,
@@ -41217,9 +41319,9 @@ function checkDatabaseIntegrity(dbPath) {
41217
41319
  };
41218
41320
  }
41219
41321
  function defaultBackupPath(dbPath) {
41220
- const base = dbPath ? dirname7(resolve14(dbPath)) : dirname7(resolveDbPath());
41322
+ const base = dbPath ? dirname7(resolve15(dbPath)) : dirname7(resolveDbPath());
41221
41323
  const stamp = new Date().toISOString().replace(/[:.]/g, "-");
41222
- return join14(base, "backups", `todos-${stamp}.db`);
41324
+ return join16(base, "backups", `todos-${stamp}.db`);
41223
41325
  }
41224
41326
  var DB_BACKUP_SCHEMA = "todos.db_backup.v1";
41225
41327
  var init_db_backup = __esm(() => {
@@ -41236,7 +41338,7 @@ __export(exports_evidence_redaction, {
41236
41338
  TODOS_EVIDENCE_REDACTION_CONFIRM: () => TODOS_EVIDENCE_REDACTION_CONFIRM
41237
41339
  });
41238
41340
  import { chmodSync } from "fs";
41239
- import { join as join15 } from "path";
41341
+ import { join as join17 } from "path";
41240
41342
  function unique4(values) {
41241
41343
  return Array.from(new Set((values ?? []).map((value) => value.trim()).filter(Boolean)));
41242
41344
  }
@@ -41583,7 +41685,7 @@ function redactEvidenceRows(options, db) {
41583
41685
  }
41584
41686
  function defaultEvidenceRedactionBackupPath(dbPath) {
41585
41687
  const base = defaultBackupPath(dbPath);
41586
- return join15(base.replace(/\.db$/, ""), "pre-redaction.db");
41688
+ return join17(base.replace(/\.db$/, ""), "pre-redaction.db");
41587
41689
  }
41588
41690
  var TODOS_EVIDENCE_REDACTION_SCHEMA = "todos.evidence_redaction.v1", TODOS_EVIDENCE_REDACTION_CONFIRM = "REDACT_TODOS_EVIDENCE";
41589
41691
  var init_evidence_redaction = __esm(() => {
@@ -41599,7 +41701,7 @@ __export(exports_retention_cleanup, {
41599
41701
  applyRetentionCleanup: () => applyRetentionCleanup,
41600
41702
  RETENTION_CLEANUP_CONFIRMATION: () => RETENTION_CLEANUP_CONFIRMATION
41601
41703
  });
41602
- import { existsSync as existsSync16, unlinkSync as unlinkSync2 } from "fs";
41704
+ import { existsSync as existsSync17, unlinkSync as unlinkSync2 } from "fs";
41603
41705
  function normalizeScopes(scopes) {
41604
41706
  if (!scopes || scopes.length === 0)
41605
41707
  return [...ALL_SCOPES];
@@ -41802,7 +41904,7 @@ function applyRetentionCleanup(input, db) {
41802
41904
  for (const artifact of report.candidates.artifact_files) {
41803
41905
  try {
41804
41906
  const path = artifactStorePath(artifact.relative_path);
41805
- if (!existsSync16(path)) {
41907
+ if (!existsSync17(path)) {
41806
41908
  report.warnings.push(`stored artifact already missing: ${artifact.relative_path}`);
41807
41909
  continue;
41808
41910
  }
@@ -42478,8 +42580,8 @@ __export(exports_local_extensions, {
42478
42580
  discoverLocalExtensions: () => discoverLocalExtensions
42479
42581
  });
42480
42582
  import { createHash as createHash13, createVerify } from "crypto";
42481
- import { existsSync as existsSync17, readdirSync as readdirSync3, readFileSync as readFileSync13, statSync as statSync8 } from "fs";
42482
- import { basename as basename6, join as join16, resolve as resolve15 } from "path";
42583
+ import { existsSync as existsSync18, readdirSync as readdirSync3, readFileSync as readFileSync13, statSync as statSync8 } from "fs";
42584
+ import { basename as basename6, join as join18, resolve as resolve16 } from "path";
42483
42585
  function isObject(value) {
42484
42586
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
42485
42587
  }
@@ -42737,11 +42839,11 @@ function verifyExtensionSignature(input) {
42737
42839
  return verifier.verify(input.public_key, decodeSignature(input.signature));
42738
42840
  }
42739
42841
  function inspectExtensionSource(source2) {
42740
- const resolved = resolve15(source2);
42741
- if (!existsSync17(resolved))
42842
+ const resolved = resolve16(source2);
42843
+ if (!existsSync18(resolved))
42742
42844
  throw new Error(`extension source not found: ${source2}`);
42743
42845
  const stat = statSync8(resolved);
42744
- const manifestPath = stat.isDirectory() ? [join16(resolved, "todos.extension.json"), join16(resolved, "extension.json")].find(existsSync17) : resolved;
42846
+ const manifestPath = stat.isDirectory() ? [join18(resolved, "todos.extension.json"), join18(resolved, "extension.json")].find(existsSync18) : resolved;
42745
42847
  if (!manifestPath)
42746
42848
  throw new Error(`extension directory ${source2} is missing todos.extension.json`);
42747
42849
  const raw = readFileSync13(manifestPath);
@@ -42835,26 +42937,26 @@ function testExtensionCompatibility(sourceOrManifest) {
42835
42937
  function projectExtensionSources(projectPath) {
42836
42938
  if (!projectPath)
42837
42939
  return [];
42838
- const root = resolve15(projectPath);
42940
+ const root = resolve16(projectPath);
42839
42941
  const candidates = [
42840
- join16(root, "todos.extension.json"),
42841
- join16(root, ".todos", "todos.extension.json")
42942
+ join18(root, "todos.extension.json"),
42943
+ join18(root, ".todos", "todos.extension.json")
42842
42944
  ];
42843
- const extensionDir = join16(root, ".todos", "extensions");
42844
- if (existsSync17(extensionDir)) {
42945
+ const extensionDir = join18(root, ".todos", "extensions");
42946
+ if (existsSync18(extensionDir)) {
42845
42947
  for (const entry2 of readdirSync3(extensionDir)) {
42846
42948
  if (entry2.startsWith("."))
42847
42949
  continue;
42848
- const full = join16(extensionDir, entry2);
42950
+ const full = join18(extensionDir, entry2);
42849
42951
  if (statSync8(full).isDirectory() || entry2.endsWith(".json"))
42850
42952
  candidates.push(full);
42851
42953
  }
42852
42954
  }
42853
- return candidates.filter(existsSync17);
42955
+ return candidates.filter(existsSync18);
42854
42956
  }
42855
42957
  function discoverLocalExtensions(options = {}) {
42856
42958
  const config = loadConfig();
42857
- const projectPath = options.project_path ? resolve15(options.project_path) : null;
42959
+ const projectPath = options.project_path ? resolve16(options.project_path) : null;
42858
42960
  const configuredSources = [
42859
42961
  ...config.extension_sources || [],
42860
42962
  ...projectPath ? config.project_overrides?.[projectPath]?.extension_sources || [] : []
@@ -42862,7 +42964,7 @@ function discoverLocalExtensions(options = {}) {
42862
42964
  const sources = Array.from(new Set([
42863
42965
  ...configuredSources,
42864
42966
  ...projectExtensionSources(projectPath || undefined)
42865
- ])).map((source2) => projectPath && !source2.startsWith("/") ? resolve15(projectPath, source2) : resolve15(source2));
42967
+ ])).map((source2) => projectPath && !source2.startsWith("/") ? resolve16(projectPath, source2) : resolve16(source2));
42866
42968
  const warnings = [];
42867
42969
  const discovered = [];
42868
42970
  for (const source2 of sources) {
@@ -43122,9 +43224,9 @@ __export(exports_policy_packs, {
43122
43224
  getPolicyPack: () => getPolicyPack,
43123
43225
  explainPolicyPack: () => explainPolicyPack
43124
43226
  });
43125
- import { relative as relative4, resolve as resolve16 } from "path";
43227
+ import { relative as relative4, resolve as resolve17 } from "path";
43126
43228
  function normalizePath3(path) {
43127
- return resolve16(path);
43229
+ return resolve17(path);
43128
43230
  }
43129
43231
  function unique6(values) {
43130
43232
  return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
@@ -43179,7 +43281,7 @@ function commandMatches(commands, pattern) {
43179
43281
  }
43180
43282
  function pathMatches(paths, pattern, root) {
43181
43283
  return paths.filter((path) => {
43182
- const candidate = path.startsWith("/") ? path : resolve16(root, path);
43284
+ const candidate = path.startsWith("/") ? path : resolve17(root, path);
43183
43285
  if (!isPathInside3(root, candidate))
43184
43286
  return matchesPattern3(path, pattern);
43185
43287
  return matchesPattern3(path, pattern) || matchesPattern3(relative4(root, candidate), pattern);
@@ -48923,8 +49025,8 @@ class SqliteTodosTaskManifestBackend {
48923
49025
  async serialized(run) {
48924
49026
  const previous = sqliteTails.get(this.db) ?? Promise.resolve();
48925
49027
  let release;
48926
- const current = new Promise((resolve17) => {
48927
- release = resolve17;
49028
+ const current = new Promise((resolve18) => {
49029
+ release = resolve18;
48928
49030
  });
48929
49031
  const tail = previous.then(() => current);
48930
49032
  sqliteTails.set(this.db, tail);
@@ -51267,8 +51369,8 @@ class SqliteTodosTaskSubtreeTransferBackend {
51267
51369
  async serialized(run) {
51268
51370
  const previous = sqliteTails2.get(this.db) ?? Promise.resolve();
51269
51371
  let release;
51270
- const current = new Promise((resolve17) => {
51271
- release = resolve17;
51372
+ const current = new Promise((resolve18) => {
51373
+ release = resolve18;
51272
51374
  });
51273
51375
  const tail = previous.then(() => current);
51274
51376
  sqliteTails2.set(this.db, tail);
@@ -52703,8 +52805,8 @@ var exports_doctor = {};
52703
52805
  __export(exports_doctor, {
52704
52806
  runTodosDoctor: () => runTodosDoctor
52705
52807
  });
52706
- import { chmodSync as chmodSync2, copyFileSync as copyFileSync2, existsSync as existsSync18, mkdirSync as mkdirSync9, statSync as statSync9 } from "fs";
52707
- import { basename as basename7, dirname as dirname8, join as join17 } from "path";
52808
+ import { chmodSync as chmodSync2, copyFileSync as copyFileSync2, existsSync as existsSync19, mkdirSync as mkdirSync9, statSync as statSync9 } from "fs";
52809
+ import { basename as basename7, dirname as dirname8, join as join19 } from "path";
52708
52810
  function tableExists3(db, table) {
52709
52811
  return Boolean(db.query("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(table));
52710
52812
  }
@@ -52798,7 +52900,7 @@ function findMissingProjectRoots(db) {
52798
52900
  continue;
52799
52901
  if (!row.path.startsWith("/"))
52800
52902
  continue;
52801
- if (!existsSync18(row.path))
52903
+ if (!existsSync19(row.path))
52802
52904
  missing++;
52803
52905
  }
52804
52906
  return missing;
@@ -52858,16 +52960,16 @@ function databasePermissionsAreUnsafe(dbPath) {
52858
52960
  function createBackup(dbPath) {
52859
52961
  if (dbPath === ":memory:" || dbPath.startsWith("file::memory:"))
52860
52962
  return;
52861
- if (!existsSync18(dbPath))
52963
+ if (!existsSync19(dbPath))
52862
52964
  return;
52863
52965
  const stamp = now().replace(/[:.]/g, "-");
52864
- const backupDir = join17(dirname8(dbPath), `${basename7(dbPath)}.backup-${stamp}`);
52966
+ const backupDir = join19(dirname8(dbPath), `${basename7(dbPath)}.backup-${stamp}`);
52865
52967
  const files = [];
52866
52968
  mkdirSync9(backupDir, { recursive: true });
52867
52969
  for (const source2 of [dbPath, `${dbPath}-wal`, `${dbPath}-shm`]) {
52868
- if (!existsSync18(source2))
52970
+ if (!existsSync19(source2))
52869
52971
  continue;
52870
- const target = join17(backupDir, basename7(source2));
52972
+ const target = join19(backupDir, basename7(source2));
52871
52973
  copyFileSync2(source2, target);
52872
52974
  files.push(target);
52873
52975
  }
@@ -53126,7 +53228,7 @@ var init_doctor = __esm(() => {
53126
53228
  });
53127
53229
 
53128
53230
  // src/server/routes.ts
53129
- import { join as join18, resolve as resolve17, sep as sep4 } from "path";
53231
+ import { join as join20, resolve as resolve18, sep as sep4 } from "path";
53130
53232
  function parseFieldsParam(url) {
53131
53233
  const fieldsParam = url.searchParams.get("fields");
53132
53234
  return fieldsParam ? fieldsParam.split(",").map((f) => f.trim()).filter(Boolean) : undefined;
@@ -53963,9 +54065,9 @@ function handleStaticFiles(path, method, ctx, json5, serveStaticFile2) {
53963
54065
  if (!ctx.dashboardExists || method !== "GET" && method !== "HEAD")
53964
54066
  return null;
53965
54067
  if (path !== "/") {
53966
- const filePath = join18(ctx.dashboardDir, path);
53967
- const resolvedFile = resolve17(filePath);
53968
- const resolvedBase = resolve17(ctx.dashboardDir);
54068
+ const filePath = join20(ctx.dashboardDir, path);
54069
+ const resolvedFile = resolve18(filePath);
54070
+ const resolvedBase = resolve18(ctx.dashboardDir);
53969
54071
  if (!resolvedFile.startsWith(resolvedBase + sep4) && resolvedFile !== resolvedBase) {
53970
54072
  return json5({ error: "Forbidden" }, 403);
53971
54073
  }
@@ -53973,7 +54075,7 @@ function handleStaticFiles(path, method, ctx, json5, serveStaticFile2) {
53973
54075
  if (res2)
53974
54076
  return res2;
53975
54077
  }
53976
- const indexPath = join18(ctx.dashboardDir, "index.html");
54078
+ const indexPath = join20(ctx.dashboardDir, "index.html");
53977
54079
  const res = serveStaticFile2(indexPath);
53978
54080
  if (res)
53979
54081
  return res;
@@ -54080,7 +54182,7 @@ class TodosShadowOutbox {
54080
54182
  const remaining = deadline - Date.now();
54081
54183
  if (remaining <= 0)
54082
54184
  break;
54083
- await new Promise((resolve18) => setTimeout(resolve18, Math.min(200, remaining)));
54185
+ await new Promise((resolve19) => setTimeout(resolve19, Math.min(200, remaining)));
54084
54186
  }
54085
54187
  }
54086
54188
  return this.getStats();
@@ -60972,8 +61074,8 @@ var exports_mention_resolver = {};
60972
61074
  __export(exports_mention_resolver, {
60973
61075
  resolveMentions: () => resolveMentions
60974
61076
  });
60975
- import { existsSync as existsSync19, readdirSync as readdirSync4, readFileSync as readFileSync14, statSync as statSync10 } from "fs";
60976
- import { basename as basename8, isAbsolute, join as join19, relative as relative5, resolve as resolve18, sep as sep5 } from "path";
61077
+ import { existsSync as existsSync20, readdirSync as readdirSync4, readFileSync as readFileSync14, statSync as statSync10 } from "fs";
61078
+ import { basename as basename8, isAbsolute, join as join21, relative as relative5, resolve as resolve19, sep as sep5 } from "path";
60977
61079
  function blankResolution(parsed) {
60978
61080
  return {
60979
61081
  input: parsed.input,
@@ -60996,7 +61098,7 @@ function backlink(kind, key2, label, target = key2) {
60996
61098
  return { kind, key: key2, label, target };
60997
61099
  }
60998
61100
  function normalizeWorkspace(workspace) {
60999
- return resolve18(workspace || process.cwd());
61101
+ return resolve19(workspace || process.cwd());
61000
61102
  }
61001
61103
  function isInside(root, absolutePath) {
61002
61104
  const rel = relative5(root, absolutePath);
@@ -61064,14 +61166,14 @@ function resolveFile(parsed, workspace) {
61064
61166
  resolution.warnings.push("path is empty or escapes the workspace");
61065
61167
  return resolution;
61066
61168
  }
61067
- const absolutePath = resolve18(workspace, relPath);
61169
+ const absolutePath = resolve19(workspace, relPath);
61068
61170
  if (!isInside(workspace, absolutePath)) {
61069
61171
  resolution.path = relPath;
61070
61172
  resolution.warnings.push("path escapes the workspace");
61071
61173
  return resolution;
61072
61174
  }
61073
61175
  resolution.path = relPath;
61074
- if (!existsSync19(absolutePath)) {
61176
+ if (!existsSync20(absolutePath)) {
61075
61177
  resolution.warnings.push("file does not exist in the local workspace");
61076
61178
  return resolution;
61077
61179
  }
@@ -61104,7 +61206,7 @@ function walkSourceFiles(root, current = root, files = []) {
61104
61206
  if (SKIP_DIRS2.has(entry2.name))
61105
61207
  continue;
61106
61208
  }
61107
- const absolutePath = join19(current, entry2.name);
61209
+ const absolutePath = join21(current, entry2.name);
61108
61210
  if (entry2.isDirectory()) {
61109
61211
  if (!SKIP_DIRS2.has(entry2.name))
61110
61212
  walkSourceFiles(root, absolutePath, files);
@@ -63920,7 +64022,7 @@ __export(exports_release_compatibility, {
63920
64022
  LOCAL_RELEASE_COMPATIBILITY_SCHEMA_VERSION: () => LOCAL_RELEASE_COMPATIBILITY_SCHEMA_VERSION
63921
64023
  });
63922
64024
  import { readFileSync as readFileSync15 } from "fs";
63923
- import { join as join20, resolve as resolve19 } from "path";
64025
+ import { join as join22, resolve as resolve20 } from "path";
63924
64026
  import { Database as Database3 } from "bun:sqlite";
63925
64027
  function pass(id, message, details) {
63926
64028
  return { id, status: "passed", message, details };
@@ -63932,7 +64034,7 @@ function warn(id, message, details) {
63932
64034
  return { id, status: "warning", message, details };
63933
64035
  }
63934
64036
  function readPackageJson2(root) {
63935
- return JSON.parse(readFileSync15(join20(root, "package.json"), "utf8"));
64037
+ return JSON.parse(readFileSync15(join22(root, "package.json"), "utf8"));
63936
64038
  }
63937
64039
  function sortedKeys(value) {
63938
64040
  return Object.keys(value ?? {}).sort((left, right) => left.localeCompare(right));
@@ -64028,7 +64130,7 @@ function checkChangelog() {
64028
64130
  ];
64029
64131
  }
64030
64132
  function createReleaseCompatibilityReport(options = {}) {
64031
- const root = resolve19(options.root ?? process.cwd());
64133
+ const root = resolve20(options.root ?? process.cwd());
64032
64134
  const packageJson = readPackageJson2(root);
64033
64135
  const simulatedLevels = options.simulated_levels ?? defaultSimulationLevels();
64034
64136
  const checks = [
@@ -69903,7 +70005,7 @@ __export(exports_verification_providers, {
69903
70005
  getVerificationRecord: () => getVerificationRecord,
69904
70006
  discoverVerificationProviderCapabilities: () => discoverVerificationProviderCapabilities
69905
70007
  });
69906
- import { existsSync as existsSync20, readFileSync as readFileSync16 } from "fs";
70008
+ import { existsSync as existsSync21, readFileSync as readFileSync16 } from "fs";
69907
70009
  function normalizeName6(name) {
69908
70010
  const normalized = name.trim().toLowerCase();
69909
70011
  if (!/^[a-z0-9][a-z0-9_-]{0,63}$/.test(normalized)) {
@@ -70000,7 +70102,7 @@ function classifyLog(text) {
70000
70102
  async function sleep3(ms) {
70001
70103
  if (ms <= 0)
70002
70104
  return;
70003
- await new Promise((resolve20) => setTimeout(resolve20, ms));
70105
+ await new Promise((resolve21) => setTimeout(resolve21, ms));
70004
70106
  }
70005
70107
  async function runCommandProvider(provider, input) {
70006
70108
  const commandTemplate = input.command || provider.command;
@@ -70055,7 +70157,7 @@ Timed out after ${provider.timeout_ms}ms`);
70055
70157
  };
70056
70158
  }
70057
70159
  function runCiLogProvider(input) {
70058
- const text = input.log_text ?? (input.log_path && existsSync20(input.log_path) ? readFileSync16(input.log_path, "utf-8") : "");
70160
+ const text = input.log_text ?? (input.log_path && existsSync21(input.log_path) ? readFileSync16(input.log_path, "utf-8") : "");
70059
70161
  return {
70060
70162
  status: classifyLog(text),
70061
70163
  attempts: 1,
@@ -70067,7 +70169,7 @@ function runBrowserProvider(input) {
70067
70169
  if (!input.artifact_path) {
70068
70170
  return { status: "unknown", attempts: 1, exit_code: null, output_summary: "browser provider needs a screenshot or artifact path" };
70069
70171
  }
70070
- if (!existsSync20(input.artifact_path)) {
70172
+ if (!existsSync21(input.artifact_path)) {
70071
70173
  return { status: "failed", attempts: 1, exit_code: null, output_summary: `artifact not found: ${input.artifact_path}` };
70072
70174
  }
70073
70175
  return {
@@ -72359,7 +72461,7 @@ __export(exports_local_backups, {
72359
72461
  });
72360
72462
  import { createHash as createHash16 } from "crypto";
72361
72463
  import { readFileSync as readFileSync17, writeFileSync as writeFileSync8 } from "fs";
72362
- import { dirname as dirname9, resolve as resolve20 } from "path";
72464
+ import { dirname as dirname9, resolve as resolve21 } from "path";
72363
72465
  import { mkdirSync as mkdirSync10 } from "fs";
72364
72466
  function stableJson2(value) {
72365
72467
  if (value === null || typeof value !== "object")
@@ -72461,14 +72563,14 @@ function createLocalBackup(options = {}, db) {
72461
72563
  return backup;
72462
72564
  }
72463
72565
  function writeLocalBackupFile(backup, outputPath) {
72464
- const path = resolve20(outputPath);
72566
+ const path = resolve21(outputPath);
72465
72567
  mkdirSync10(dirname9(path), { recursive: true });
72466
72568
  writeFileSync8(path, `${JSON.stringify(backup, null, 2)}
72467
72569
  `);
72468
72570
  return path;
72469
72571
  }
72470
72572
  function readLocalBackupFile(path) {
72471
- return JSON.parse(readFileSync17(resolve20(path), "utf-8"));
72573
+ return JSON.parse(readFileSync17(resolve21(path), "utf-8"));
72472
72574
  }
72473
72575
  function verifyLocalBackup(value, options = {}, db) {
72474
72576
  const verifiedAt = options.verified_at ?? now();
@@ -72665,7 +72767,7 @@ __export(exports_onboarding_fixtures, {
72665
72767
  TODOS_ONBOARDING_FIXTURE_LIBRARY_VERSION: () => TODOS_ONBOARDING_FIXTURE_LIBRARY_VERSION
72666
72768
  });
72667
72769
  import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync9 } from "fs";
72668
- import { join as join21 } from "path";
72770
+ import { join as join23 } from "path";
72669
72771
  function emptyData() {
72670
72772
  return {
72671
72773
  projects: [],
@@ -73001,7 +73103,7 @@ function writeOnboardingFixtureFiles(directory) {
73001
73103
  mkdirSync11(directory, { recursive: true });
73002
73104
  const files = [];
73003
73105
  for (const fixture of allFixtures()) {
73004
- const path = join21(directory, `${fixture.summary.name}.bridge.json`);
73106
+ const path = join23(directory, `${fixture.summary.name}.bridge.json`);
73005
73107
  writeFileSync9(path, `${JSON.stringify(fixture.bundle, null, 2)}
73006
73108
  `, "utf-8");
73007
73109
  files.push(path);
@@ -78669,7 +78771,7 @@ Last seen: ${agent.last_seen_at}`
78669
78771
  `Suggested names: ${suggestions.slice(0, 8).join(", ")}`,
78670
78772
  allActive.length > 0 ? `Active agents (avoid these names): ${allActive.map((a) => `${a.name} (seen ${Math.round((Date.now() - new Date(a.last_seen_at).getTime()) / 60000)}m ago)`).join(", ")}` : "No active agents.",
78671
78773
  `
78672
- To restrict names, configure agent_pool or project_pools in ~/.hasna/todos/config.json`
78774
+ To restrict names, configure agent_pool or project_pools in the todos data home config file (default <data home>/config.json)`
78673
78775
  ];
78674
78776
  return { content: [{ type: "text", text: lines2.join(`
78675
78777
  `) }] };
@@ -79221,16 +79323,16 @@ __export(exports_environment_snapshots, {
79221
79323
  captureEnvironmentSnapshot: () => captureEnvironmentSnapshot
79222
79324
  });
79223
79325
  import { createHash as createHash20 } from "crypto";
79224
- import { existsSync as existsSync21, readFileSync as readFileSync19, statSync as statSync11 } from "fs";
79326
+ import { existsSync as existsSync22, readFileSync as readFileSync19, statSync as statSync11 } from "fs";
79225
79327
  import { hostname as hostname2, platform, arch } from "os";
79226
- import { dirname as dirname10, join as join22, resolve as resolve21 } from "path";
79328
+ import { dirname as dirname10, join as join24, resolve as resolve22 } from "path";
79227
79329
  import { tmpdir as tmpdir4 } from "os";
79228
79330
  function sha2567(value) {
79229
79331
  return createHash20("sha256").update(value).digest("hex");
79230
79332
  }
79231
79333
  function fileRecord(root, relativePath) {
79232
- const path = join22(root, relativePath);
79233
- if (!existsSync21(path))
79334
+ const path = join24(root, relativePath);
79335
+ if (!existsSync22(path))
79234
79336
  return null;
79235
79337
  const stat = statSync11(path);
79236
79338
  if (!stat.isFile())
@@ -79242,7 +79344,7 @@ function manifestRecord(root, relativePath) {
79242
79344
  const base = fileRecord(root, relativePath);
79243
79345
  if (!base)
79244
79346
  return null;
79245
- const parsed = readJsonFile(join22(root, relativePath));
79347
+ const parsed = readJsonFile(join24(root, relativePath));
79246
79348
  if (!parsed)
79247
79349
  return { ...base, redacted: {} };
79248
79350
  const redacted = redactValue({
@@ -79337,15 +79439,15 @@ function commandEnv(env, includeValues) {
79337
79439
  function defaultSnapshotDir() {
79338
79440
  const dbPath = getDatabasePath();
79339
79441
  if (dbPath === ":memory:" || dbPath.startsWith("file::memory:"))
79340
- return join22(tmpdir4(), "hasna-todos", "environment-snapshots");
79341
- return join22(dirname10(resolve21(dbPath)), "environment-snapshots");
79442
+ return join24(tmpdir4(), "hasna-todos", "environment-snapshots");
79443
+ return join24(dirname10(resolve22(dbPath)), "environment-snapshots");
79342
79444
  }
79343
79445
  function snapshotWithId(snapshot) {
79344
79446
  const digest4 = sha2567(JSON.stringify(snapshot)).slice(0, 24);
79345
79447
  return { id: `env_${digest4}`, ...snapshot };
79346
79448
  }
79347
79449
  function captureEnvironmentSnapshot(input = {}) {
79348
- const root = resolve21(input.root || process.cwd());
79450
+ const root = resolve22(input.root || process.cwd());
79349
79451
  const env = input.env || process.env;
79350
79452
  const warnings = [];
79351
79453
  const manifests = MANIFEST_FILES.map((file) => manifestRecord(root, file)).filter((file) => Boolean(file));
@@ -79385,13 +79487,13 @@ function captureEnvironmentSnapshot(input = {}) {
79385
79487
  });
79386
79488
  }
79387
79489
  function writeEnvironmentSnapshot(snapshot, outputPath) {
79388
- const path = outputPath ? resolve21(outputPath) : join22(defaultSnapshotDir(), `${snapshot.id}.json`);
79490
+ const path = outputPath ? resolve22(outputPath) : join24(defaultSnapshotDir(), `${snapshot.id}.json`);
79389
79491
  ensureDir(dirname10(path));
79390
79492
  writeJsonFile(path, snapshot);
79391
79493
  return path;
79392
79494
  }
79393
79495
  function readEnvironmentSnapshot(path) {
79394
- const snapshot = readJsonFile(resolve21(path));
79496
+ const snapshot = readJsonFile(resolve22(path));
79395
79497
  if (!snapshot || snapshot.schema_version !== 1 || typeof snapshot.id !== "string") {
79396
79498
  throw new Error(`Invalid environment snapshot: ${path}`);
79397
79499
  }
@@ -80102,8 +80204,8 @@ class SqlitePrGroupLedgerPersistence {
80102
80204
  async transaction(fn) {
80103
80205
  const previous = sqliteTransactionTails2.get(this.db) ?? Promise.resolve();
80104
80206
  let release;
80105
- const current = new Promise((resolve22) => {
80106
- release = resolve22;
80207
+ const current = new Promise((resolve23) => {
80208
+ release = resolve23;
80107
80209
  });
80108
80210
  sqliteTransactionTails2.set(this.db, current);
80109
80211
  await previous;
@@ -80201,27 +80303,27 @@ __export(exports_serve, {
80201
80303
  SECURITY_HEADERS: () => SECURITY_HEADERS,
80202
80304
  MIME_TYPES: () => MIME_TYPES
80203
80305
  });
80204
- import { existsSync as existsSync22 } from "fs";
80205
- import { join as join23, dirname as dirname11, extname } from "path";
80306
+ import { existsSync as existsSync23 } from "fs";
80307
+ import { join as join25, dirname as dirname11, extname } from "path";
80206
80308
  import { fileURLToPath } from "url";
80207
80309
  function resolveDashboardDir() {
80208
80310
  const candidates = [];
80209
80311
  try {
80210
80312
  const scriptDir = dirname11(fileURLToPath(import.meta.url));
80211
- candidates.push(join23(scriptDir, "..", "dashboard", "dist"));
80212
- candidates.push(join23(scriptDir, "..", "..", "dashboard", "dist"));
80313
+ candidates.push(join25(scriptDir, "..", "dashboard", "dist"));
80314
+ candidates.push(join25(scriptDir, "..", "..", "dashboard", "dist"));
80213
80315
  } catch {}
80214
80316
  if (process.argv[1]) {
80215
80317
  const mainDir = dirname11(process.argv[1]);
80216
- candidates.push(join23(mainDir, "..", "dashboard", "dist"));
80217
- candidates.push(join23(mainDir, "..", "..", "dashboard", "dist"));
80318
+ candidates.push(join25(mainDir, "..", "dashboard", "dist"));
80319
+ candidates.push(join25(mainDir, "..", "..", "dashboard", "dist"));
80218
80320
  }
80219
- candidates.push(join23(process.cwd(), "dashboard", "dist"));
80321
+ candidates.push(join25(process.cwd(), "dashboard", "dist"));
80220
80322
  for (const candidate of candidates) {
80221
- if (existsSync22(candidate))
80323
+ if (existsSync23(candidate))
80222
80324
  return candidate;
80223
80325
  }
80224
- return join23(process.cwd(), "dashboard", "dist");
80326
+ return join25(process.cwd(), "dashboard", "dist");
80225
80327
  }
80226
80328
  function getProvidedApiKey(req) {
80227
80329
  const headerKey = req.headers.get("x-api-key");
@@ -80293,7 +80395,7 @@ function json4(data, status3 = 200, headers) {
80293
80395
  });
80294
80396
  }
80295
80397
  function serveStaticFile(filePath) {
80296
- if (!existsSync22(filePath))
80398
+ if (!existsSync23(filePath))
80297
80399
  return null;
80298
80400
  const ext = extname(filePath);
80299
80401
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
@@ -80394,7 +80496,7 @@ data: ${data}
80394
80496
  filteredSseClients.delete(client);
80395
80497
  }
80396
80498
  const dashboardDir = resolveDashboardDir();
80397
- const dashboardExists = existsSync22(dashboardDir);
80499
+ const dashboardExists = existsSync23(dashboardDir);
80398
80500
  if (!dashboardExists) {
80399
80501
  console.error(`
80400
80502
  Dashboard not found at: ${dashboardDir}`);
@@ -82281,12 +82383,12 @@ __export(exports_config_serve_commands, {
82281
82383
  registerConfigServeCommands: () => registerConfigServeCommands
82282
82384
  });
82283
82385
  import chalk7 from "chalk";
82284
- import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync20, writeFileSync as writeFileSync10 } from "fs";
82285
- import { dirname as dirname12, join as join24 } from "path";
82386
+ import { existsSync as existsSync24, mkdirSync as mkdirSync12, readFileSync as readFileSync20, writeFileSync as writeFileSync10 } from "fs";
82387
+ import { dirname as dirname12, join as join26 } from "path";
82286
82388
  function registerConfigServeCommands(program2) {
82287
82389
  program2.command("config").description("View or update configuration").option("--get <key>", "Get a config value").option("--set <key=value>", "Set a config value (e.g. completion_guard.enabled=true)").action((opts) => {
82288
82390
  const globalOpts = program2.opts();
82289
- const configPath = join24(getTodosGlobalDir(), "config.json");
82391
+ const configPath = join26(getTodosGlobalDir(), "config.json");
82290
82392
  if (opts.get) {
82291
82393
  const config2 = loadConfig();
82292
82394
  const keys = opts.get.split(".");
@@ -82323,7 +82425,7 @@ function registerConfigServeCommands(program2) {
82323
82425
  }
82324
82426
  obj[keys[keys.length - 1]] = parsedValue;
82325
82427
  const dir = dirname12(configPath);
82326
- if (!existsSync23(dir))
82428
+ if (!existsSync24(dir))
82327
82429
  mkdirSync12(dir, { recursive: true });
82328
82430
  writeFileSync10(configPath, JSON.stringify(config2, null, 2));
82329
82431
  if (globalOpts.json) {
@@ -83503,8 +83605,8 @@ __export(exports_routing_doctor, {
83503
83605
  classifyTaskRouting: () => classifyTaskRouting,
83504
83606
  TODOS_ROUTING_DOCTOR_SCHEMA_VERSION: () => TODOS_ROUTING_DOCTOR_SCHEMA_VERSION
83505
83607
  });
83506
- import { copyFileSync as copyFileSync3, existsSync as existsSync24, mkdirSync as mkdirSync13, writeFileSync as writeFileSync11 } from "fs";
83507
- import { basename as basename9, dirname as dirname13, join as join25 } from "path";
83608
+ import { copyFileSync as copyFileSync3, existsSync as existsSync25, mkdirSync as mkdirSync13, writeFileSync as writeFileSync11 } from "fs";
83609
+ import { basename as basename9, dirname as dirname13, join as join27 } from "path";
83508
83610
  function normalizePath5(path) {
83509
83611
  if (!path)
83510
83612
  return null;
@@ -83806,16 +83908,16 @@ function evaluateTaskRouting(ctx) {
83806
83908
  function createBackup2(dbPath, generatedAt) {
83807
83909
  if (dbPath === ":memory:" || dbPath.startsWith("file::memory:"))
83808
83910
  return;
83809
- if (!existsSync24(dbPath))
83911
+ if (!existsSync25(dbPath))
83810
83912
  return;
83811
83913
  const stamp = generatedAt.replace(/[:.]/g, "-");
83812
- const backupDir = join25(dirname13(dbPath), `${basename9(dbPath)}.routing-doctor-backup-${stamp}`);
83914
+ const backupDir = join27(dirname13(dbPath), `${basename9(dbPath)}.routing-doctor-backup-${stamp}`);
83813
83915
  const files = [];
83814
83916
  mkdirSync13(backupDir, { recursive: true });
83815
83917
  for (const source3 of [dbPath, `${dbPath}-wal`, `${dbPath}-shm`]) {
83816
- if (!existsSync24(source3))
83918
+ if (!existsSync25(source3))
83817
83919
  continue;
83818
- const target = join25(backupDir, basename9(source3));
83920
+ const target = join27(backupDir, basename9(source3));
83819
83921
  copyFileSync3(source3, target);
83820
83922
  files.push(target);
83821
83923
  }
@@ -83919,7 +84021,7 @@ function runRoutingDoctor(options = {}) {
83919
84021
  }
83920
84022
  const applied = repairs.filter((r) => r.applied);
83921
84023
  if (applied.length > 0) {
83922
- const undoPath = options.undoRecordPath ?? join25(process.cwd(), `todos-routing-doctor-undo-${generatedAt.replace(/[:.]/g, "-")}.json`);
84024
+ const undoPath = options.undoRecordPath ?? join27(process.cwd(), `todos-routing-doctor-undo-${generatedAt.replace(/[:.]/g, "-")}.json`);
83923
84025
  const undoRecord = {
83924
84026
  schema_version: TODOS_ROUTING_DOCTOR_SCHEMA_VERSION,
83925
84027
  purpose: "Undo record for routing-doctor --apply. Restore each field with the prior value below.",
@@ -84018,10 +84120,10 @@ __export(exports_task_route_sources, {
84018
84120
  });
84019
84121
  import { Database as Database4 } from "bun:sqlite";
84020
84122
  import { createHash as createHash21 } from "crypto";
84021
- import { existsSync as existsSync25, readdirSync as readdirSync5, statSync as statSync12 } from "fs";
84022
- import { basename as basename10, dirname as dirname14, join as join26, resolve as resolve22 } from "path";
84123
+ import { existsSync as existsSync26, readdirSync as readdirSync5, statSync as statSync12 } from "fs";
84124
+ import { basename as basename10, dirname as dirname14, join as join28, resolve as resolve23 } from "path";
84023
84125
  function normalizePath6(input) {
84024
- return resolve22(input);
84126
+ return resolve23(input);
84025
84127
  }
84026
84128
  function sourceStoreId(sourceDbPath) {
84027
84129
  const digest4 = createHash21("sha256").update(sourceDbPath).digest("hex").slice(0, 16);
@@ -84083,8 +84185,8 @@ function discoverStoresUnderRoot(sourceRoot) {
84083
84185
  const rootPath = normalizePath6(sourceRoot);
84084
84186
  const errors2 = [];
84085
84187
  const stores = [];
84086
- if (!existsSync25(rootPath)) {
84087
- const ref = createStoreRef(join26(rootPath, TODO_STORE_RELATIVE_PATH));
84188
+ if (!existsSync26(rootPath)) {
84189
+ const ref = createStoreRef(join28(rootPath, TODO_STORE_RELATIVE_PATH));
84088
84190
  errors2.push({
84089
84191
  ...ref,
84090
84192
  code: "SOURCE_ROOT_MISSING",
@@ -84096,7 +84198,7 @@ function discoverStoresUnderRoot(sourceRoot) {
84096
84198
  try {
84097
84199
  rootStat = statSync12(rootPath);
84098
84200
  } catch (error2) {
84099
- const ref = createStoreRef(join26(rootPath, TODO_STORE_RELATIVE_PATH));
84201
+ const ref = createStoreRef(join28(rootPath, TODO_STORE_RELATIVE_PATH));
84100
84202
  errors2.push({
84101
84203
  ...ref,
84102
84204
  code: "SOURCE_ROOT_UNREADABLE",
@@ -84109,8 +84211,8 @@ function discoverStoresUnderRoot(sourceRoot) {
84109
84211
  return { stores, errors: errors2 };
84110
84212
  }
84111
84213
  function scanDirectory(dir, depth) {
84112
- const candidate = join26(dir, TODO_STORE_RELATIVE_PATH);
84113
- if (existsSync25(candidate)) {
84214
+ const candidate = join28(dir, TODO_STORE_RELATIVE_PATH);
84215
+ if (existsSync26(candidate)) {
84114
84216
  stores.push(createStoreRef(candidate));
84115
84217
  }
84116
84218
  if (depth >= ROOT_SCAN_MAX_DEPTH)
@@ -84130,7 +84232,7 @@ function discoverStoresUnderRoot(sourceRoot) {
84130
84232
  for (const entry2 of entries) {
84131
84233
  if (!entry2.isDirectory() || SKIPPED_SCAN_DIRS.has(entry2.name))
84132
84234
  continue;
84133
- scanDirectory(join26(dir, entry2.name), depth + 1);
84235
+ scanDirectory(join28(dir, entry2.name), depth + 1);
84134
84236
  }
84135
84237
  }
84136
84238
  scanDirectory(rootPath, 0);
@@ -84156,7 +84258,7 @@ function collectStoreRefs(input) {
84156
84258
  };
84157
84259
  }
84158
84260
  function openReadonlyStore(ref) {
84159
- if (!existsSync25(ref.source_db_path)) {
84261
+ if (!existsSync26(ref.source_db_path)) {
84160
84262
  throw Object.assign(new Error(`Store does not exist: ${ref.source_db_path}`), { code: "STORE_MISSING" });
84161
84263
  }
84162
84264
  return new Database4(ref.source_db_path, { readonly: true, create: false });
@@ -84330,7 +84432,7 @@ var init_task_route_sources = __esm(() => {
84330
84432
  init_task_crud();
84331
84433
  init_redaction();
84332
84434
  init_task_routing();
84333
- TODO_STORE_RELATIVE_PATH = join26(".hasna", "todos", "todos.db");
84435
+ TODO_STORE_RELATIVE_PATH = join28(".hasna", "todos", "todos.db");
84334
84436
  SKIPPED_SCAN_DIRS = new Set([
84335
84437
  ".git",
84336
84438
  ".hg",
@@ -85301,9 +85403,14 @@ Blocked:`));
85301
85403
  const globalOpts = program2.opts();
85302
85404
  const json7 = opts.json || globalOpts.json;
85303
85405
  const filters = {};
85304
- if (opts.project)
85305
- filters.project_id = opts.project;
85406
+ const projectRef = opts.project ?? globalOpts.project;
85407
+ if (typeof projectRef === "string" && projectRef.trim() === "") {
85408
+ handleError(new Error("--project requires a non-empty project reference"));
85409
+ }
85306
85410
  const cloud = getTodosCloudClient();
85411
+ if (projectRef) {
85412
+ filters.project_id = cloud ? await cloudResolveProjectRef(cloud, projectRef) : resolveExplicitProject(projectRef).id;
85413
+ }
85307
85414
  const work = cloud ? await cloudActiveWork(cloud, Object.keys(filters).length ? filters : {}) : getActiveWork(Object.keys(filters).length ? filters : undefined, getDatabase());
85308
85415
  if (json7) {
85309
85416
  console.log(JSON.stringify(work, null, 2));
@@ -85869,9 +85976,9 @@ Findings`));
85869
85976
  const db = getDatabase();
85870
85977
  const row = db.query("SELECT COUNT(*) as count FROM tasks").get();
85871
85978
  const { statSync: statSync13 } = await import("fs");
85872
- const { join: join27 } = await import("path");
85873
- const { getHomeDir: getHomeDir2 } = await Promise.resolve().then(() => (init_sync_utils(), exports_sync_utils));
85874
- const dbPath = process.env["HASNA_TODOS_DB_PATH"] || process.env["TODOS_DB_PATH"] || join27(getHomeDir2(), ".hasna", "todos", "todos.db");
85979
+ const { join: join29 } = await import("path");
85980
+ const { getTodosGlobalDir: getTodosGlobalDir2 } = await Promise.resolve().then(() => (init_sync_utils(), exports_sync_utils));
85981
+ const dbPath = process.env["HASNA_TODOS_DB_PATH"] || process.env["TODOS_DB_PATH"] || join29(getTodosGlobalDir2(), "todos.db");
85875
85982
  let size = "unknown";
85876
85983
  try {
85877
85984
  size = `${(statSync13(dbPath).size / 1024 / 1024).toFixed(1)} MB`;
@@ -88029,21 +88136,21 @@ __export(exports_mcp_hooks_commands, {
88029
88136
  });
88030
88137
  import chalk10 from "chalk";
88031
88138
  import { execSync as execSync3 } from "child_process";
88032
- import { existsSync as existsSync26, readFileSync as readFileSync22, writeFileSync as writeFileSync13, mkdirSync as mkdirSync14, chmodSync as chmodSync3 } from "fs";
88033
- import { dirname as dirname15, join as join27 } from "path";
88139
+ import { existsSync as existsSync27, readFileSync as readFileSync22, writeFileSync as writeFileSync13, mkdirSync as mkdirSync14, chmodSync as chmodSync3 } from "fs";
88140
+ import { dirname as dirname15, join as join29 } from "path";
88034
88141
  function getMcpBinaryPath() {
88035
88142
  try {
88036
88143
  const p = execSync3("which todos-mcp", { encoding: "utf-8" }).trim();
88037
88144
  if (p)
88038
88145
  return p;
88039
88146
  } catch {}
88040
- const bunBin = join27(HOME2, ".bun", "bin", "todos-mcp");
88041
- if (existsSync26(bunBin))
88147
+ const bunBin = join29(HOME2, ".bun", "bin", "todos-mcp");
88148
+ if (existsSync27(bunBin))
88042
88149
  return bunBin;
88043
88150
  return "todos-mcp";
88044
88151
  }
88045
88152
  function readJsonFile2(path) {
88046
- if (!existsSync26(path))
88153
+ if (!existsSync27(path))
88047
88154
  return {};
88048
88155
  try {
88049
88156
  return JSON.parse(readFileSync22(path, "utf-8"));
@@ -88053,19 +88160,19 @@ function readJsonFile2(path) {
88053
88160
  }
88054
88161
  function writeJsonFile2(path, data) {
88055
88162
  const dir = dirname15(path);
88056
- if (!existsSync26(dir))
88163
+ if (!existsSync27(dir))
88057
88164
  mkdirSync14(dir, { recursive: true });
88058
88165
  writeFileSync13(path, JSON.stringify(data, null, 2) + `
88059
88166
  `);
88060
88167
  }
88061
88168
  function readTomlFile(path) {
88062
- if (!existsSync26(path))
88169
+ if (!existsSync27(path))
88063
88170
  return "";
88064
88171
  return readFileSync22(path, "utf-8");
88065
88172
  }
88066
88173
  function writeTomlFile(path, content) {
88067
88174
  const dir = dirname15(path);
88068
- if (!existsSync26(dir))
88175
+ if (!existsSync27(dir))
88069
88176
  mkdirSync14(dir, { recursive: true });
88070
88177
  writeFileSync13(path, content);
88071
88178
  }
@@ -88130,7 +88237,7 @@ function unregisterClaude(_global) {
88130
88237
  }
88131
88238
  }
88132
88239
  function registerCodex(binPath) {
88133
- const configPath = join27(HOME2, ".codex", "config.toml");
88240
+ const configPath = join29(HOME2, ".codex", "config.toml");
88134
88241
  let content = readTomlFile(configPath);
88135
88242
  content = removeTomlBlock(content, "mcp_servers.todos");
88136
88243
  const block = `
@@ -88144,7 +88251,7 @@ args = ["--stdio"]
88144
88251
  console.log(chalk10.green(`Codex CLI: registered in ${configPath}`));
88145
88252
  }
88146
88253
  function unregisterCodex() {
88147
- const configPath = join27(HOME2, ".codex", "config.toml");
88254
+ const configPath = join29(HOME2, ".codex", "config.toml");
88148
88255
  let content = readTomlFile(configPath);
88149
88256
  if (!content.includes("[mcp_servers.todos]")) {
88150
88257
  console.log(chalk10.dim(`Codex CLI: todos not found in ${configPath}`));
@@ -88156,7 +88263,7 @@ function unregisterCodex() {
88156
88263
  console.log(chalk10.green(`Codex CLI: unregistered from ${configPath}`));
88157
88264
  }
88158
88265
  function registerGemini(binPath) {
88159
- const configPath = join27(HOME2, ".gemini", "settings.json");
88266
+ const configPath = join29(HOME2, ".gemini", "settings.json");
88160
88267
  const config = readJsonFile2(configPath);
88161
88268
  if (!config["mcpServers"]) {
88162
88269
  config["mcpServers"] = {};
@@ -88170,7 +88277,7 @@ function registerGemini(binPath) {
88170
88277
  console.log(chalk10.green(`Gemini CLI: registered in ${configPath}`));
88171
88278
  }
88172
88279
  function unregisterGemini() {
88173
- const configPath = join27(HOME2, ".gemini", "settings.json");
88280
+ const configPath = join29(HOME2, ".gemini", "settings.json");
88174
88281
  const config = readJsonFile2(configPath);
88175
88282
  const servers = config["mcpServers"];
88176
88283
  if (!servers || !("todos" in servers)) {
@@ -88204,7 +88311,7 @@ function unregisterTakumi(global) {
88204
88311
  }
88205
88312
  }
88206
88313
  function cursorConfigPath(global) {
88207
- return global ? join27(HOME2, ".cursor", "mcp.json") : join27(process.cwd(), ".cursor", "mcp.json");
88314
+ return global ? join29(HOME2, ".cursor", "mcp.json") : join29(process.cwd(), ".cursor", "mcp.json");
88208
88315
  }
88209
88316
  function registerCursor(binPath, global) {
88210
88317
  const configPath = cursorConfigPath(global);
@@ -88290,8 +88397,8 @@ function registerMcpHooksCommands(program2) {
88290
88397
  if (p)
88291
88398
  todosBin = p;
88292
88399
  } catch {}
88293
- const hooksDir = join27(process.cwd(), ".claude", "hooks");
88294
- if (!existsSync26(hooksDir))
88400
+ const hooksDir = join29(process.cwd(), ".claude", "hooks");
88401
+ if (!existsSync27(hooksDir))
88295
88402
  mkdirSync14(hooksDir, { recursive: true });
88296
88403
  const hookScript = `#!/usr/bin/env bash
88297
88404
  # Auto-generated by: todos hooks install
@@ -88316,11 +88423,11 @@ esac
88316
88423
 
88317
88424
  exit 0
88318
88425
  `;
88319
- const hookPath = join27(hooksDir, "todos-sync.sh");
88426
+ const hookPath = join29(hooksDir, "todos-sync.sh");
88320
88427
  writeFileSync13(hookPath, hookScript);
88321
88428
  execSync3(`chmod +x "${hookPath}"`);
88322
88429
  console.log(chalk10.green(`Hook script created: ${hookPath}`));
88323
- const settingsPath = join27(process.cwd(), ".claude", "settings.json");
88430
+ const settingsPath = join29(process.cwd(), ".claude", "settings.json");
88324
88431
  const settings = readJsonFile2(settingsPath);
88325
88432
  if (!settings["hooks"]) {
88326
88433
  settings["hooks"] = {};
@@ -89251,7 +89358,7 @@ Artifacts:`));
89251
89358
  const gitDir = execSync3("git rev-parse --git-dir", { encoding: "utf-8" }).trim();
89252
89359
  const hookPath = `${gitDir}/hooks/post-commit`;
89253
89360
  const marker = "# todos-auto-link";
89254
- if (existsSync26(hookPath)) {
89361
+ if (existsSync27(hookPath)) {
89255
89362
  const existing = readFileSync22(hookPath, "utf-8");
89256
89363
  if (existing.includes(marker)) {
89257
89364
  console.log(chalk10.yellow("Hook already installed."));
@@ -89278,7 +89385,7 @@ $(dirname "$0")/../../scripts/post-commit-hook.sh
89278
89385
  const gitDir = execSync3("git rev-parse --git-dir", { encoding: "utf-8" }).trim();
89279
89386
  const hookPath = `${gitDir}/hooks/post-commit`;
89280
89387
  const marker = "# todos-auto-link";
89281
- if (!existsSync26(hookPath)) {
89388
+ if (!existsSync27(hookPath)) {
89282
89389
  console.log(chalk10.dim("No post-commit hook found."));
89283
89390
  return;
89284
89391
  }
@@ -89534,10 +89641,10 @@ var init_delegation_brief = () => {};
89534
89641
 
89535
89642
  // src/lib/delegation-policy.ts
89536
89643
  import { readFileSync as readFileSync23 } from "fs";
89537
- import { homedir as homedir4 } from "os";
89538
- import { join as join28 } from "path";
89644
+ import { homedir as homedir6 } from "os";
89645
+ import { join as join30 } from "path";
89539
89646
  function defaultDelegationEmbargoPath() {
89540
- return process.env["TODOS_DELEGATION_EMBARGO_PATH"] || join28(homedir4(), ".hasna", "identities", "delegation-embargo.json");
89647
+ return process.env["TODOS_DELEGATION_EMBARGO_PATH"] || join30(homedir6(), ".hasna", "identities", "delegation-embargo.json");
89541
89648
  }
89542
89649
  function loadDelegationEmbargo(path = defaultDelegationEmbargoPath()) {
89543
89650
  try {
@@ -89882,7 +89989,7 @@ import chalk13 from "chalk";
89882
89989
  import { execSync as execSync4 } from "child_process";
89883
89990
  import { readFileSync as readFileSync25, unlinkSync as unlinkSync3, writeFileSync as writeFileSync14 } from "fs";
89884
89991
  import { tmpdir as tmpdir5 } from "os";
89885
- import { join as join29 } from "path";
89992
+ import { join as join31 } from "path";
89886
89993
  function getOrCreateLocalMachineName() {
89887
89994
  return process.env["TODOS_MACHINE_NAME"] || __require("os").hostname() || "unknown";
89888
89995
  }
@@ -89920,7 +90027,7 @@ function remoteTempPath(sshAddress) {
89920
90027
  }
89921
90028
  function readRemoteBridgeBundle(sshAddress) {
89922
90029
  const remotePath = remoteTempPath(sshAddress);
89923
- const localPath = join29(tmpdir5(), `todos-bridge-pull-${uuid()}.json`);
90030
+ const localPath = join31(tmpdir5(), `todos-bridge-pull-${uuid()}.json`);
89924
90031
  try {
89925
90032
  runSsh(sshAddress, `todos export --format bridge --allow-plaintext-sensitive --output ${shellQuote(remotePath)}`, 120000);
89926
90033
  scpFromRemote(sshAddress, remotePath, localPath);
@@ -89935,7 +90042,7 @@ function readRemoteBridgeBundle(sshAddress) {
89935
90042
  }
89936
90043
  }
89937
90044
  function writeLocalBridgeBundle() {
89938
- const localPath = join29(tmpdir5(), `todos-bridge-push-${uuid()}.json`);
90045
+ const localPath = join31(tmpdir5(), `todos-bridge-push-${uuid()}.json`);
89939
90046
  writeFileSync14(localPath, JSON.stringify(createLocalBridgeBundle(), null, 2));
89940
90047
  return localPath;
89941
90048
  }
@@ -90994,7 +91101,7 @@ __export(exports_onboarding_commands, {
90994
91101
  registerOnboardingCommands: () => registerOnboardingCommands
90995
91102
  });
90996
91103
  import chalk20 from "chalk";
90997
- import { resolve as resolve23 } from "path";
91104
+ import { resolve as resolve24 } from "path";
90998
91105
  function registerOnboardingCommands(program2) {
90999
91106
  program2.command("onboarding").alias("demo-fixtures").description("List, show, write, or import bundled local onboarding fixtures").option("--show <name>", "Show one fixture bridge bundle as JSON").option("--write <dir>", "Write all bundled fixture bridge bundles to a directory").option("--import <name>", "Dry-run or apply an onboarding fixture import").option("--apply", "Apply an onboarding fixture import. Defaults to dry-run.").option("--resolve-conflicts", "Safely merge existing local tasks while preserving divergent fields").action(async (opts) => {
91000
91107
  const globalOpts = program2.opts();
@@ -91010,7 +91117,7 @@ function registerOnboardingCommands(program2) {
91010
91117
  return;
91011
91118
  }
91012
91119
  if (opts.write) {
91013
- const result = writeOnboardingFixtureFiles2(resolve23(opts.write));
91120
+ const result = writeOnboardingFixtureFiles2(resolve24(opts.write));
91014
91121
  if (globalOpts.json) {
91015
91122
  output(result, true);
91016
91123
  return;
@@ -94511,7 +94618,7 @@ __export(exports_sdk_integration_fixtures, {
94511
94618
  TODOS_SDK_INTEGRATION_FIXTURE_GENERATED_AT: () => TODOS_SDK_INTEGRATION_FIXTURE_GENERATED_AT
94512
94619
  });
94513
94620
  import { mkdirSync as mkdirSync15, writeFileSync as writeFileSync15 } from "fs";
94514
- import { join as join30 } from "path";
94621
+ import { join as join32 } from "path";
94515
94622
  function source5(version) {
94516
94623
  return {
94517
94624
  packageName: "@hasna/todos",
@@ -94618,7 +94725,7 @@ function writeSdkIntegrationFixtures(directory, options = {}) {
94618
94725
  ];
94619
94726
  const written = [];
94620
94727
  for (const [name, payload] of files) {
94621
- const file = join30(directory, name);
94728
+ const file = join32(directory, name);
94622
94729
  writeFileSync15(file, `${JSON.stringify(payload, null, 2)}
94623
94730
  `, "utf-8");
94624
94731
  written.push(file);
@@ -94642,7 +94749,7 @@ __export(exports_sdk_fixture_commands, {
94642
94749
  registerSdkFixtureCommands: () => registerSdkFixtureCommands
94643
94750
  });
94644
94751
  import chalk22 from "chalk";
94645
- import { resolve as resolve24 } from "path";
94752
+ import { resolve as resolve25 } from "path";
94646
94753
  function registerSdkFixtureCommands(program2) {
94647
94754
  program2.command("sdk-fixtures").description("List, show, or write local SDK integration fixtures").option("--show", "Print the full fixture pack JSON").option("--write <dir>", "Write fixture pack, bridge fixture, contract snapshots, and example index to a directory").action(async (opts) => {
94648
94755
  const globalOpts = program2.opts();
@@ -94653,7 +94760,7 @@ function registerSdkFixtureCommands(program2) {
94653
94760
  writeSdkIntegrationFixtures: writeSdkIntegrationFixtures2
94654
94761
  } = await Promise.resolve().then(() => (init_sdk_integration_fixtures(), exports_sdk_integration_fixtures));
94655
94762
  if (opts.write) {
94656
- const result = writeSdkIntegrationFixtures2(resolve24(opts.write));
94763
+ const result = writeSdkIntegrationFixtures2(resolve25(opts.write));
94657
94764
  if (globalOpts.json) {
94658
94765
  console.log(JSON.stringify(result));
94659
94766
  return;
@@ -95472,7 +95579,7 @@ __export(exports_local_backup_commands, {
95472
95579
  registerLocalBackupCommands: () => registerLocalBackupCommands
95473
95580
  });
95474
95581
  import chalk28 from "chalk";
95475
- import { resolve as resolve25 } from "path";
95582
+ import { resolve as resolve26 } from "path";
95476
95583
  function globalOptions8(program2) {
95477
95584
  const command = program2;
95478
95585
  return command.optsWithGlobals?.() ?? program2.opts();
@@ -95494,10 +95601,10 @@ function registerLocalBackupCommands(program2) {
95494
95601
  const projectId = opts.projectId ?? autoProject(globalOpts);
95495
95602
  const backupBundle = createLocalBackup2({
95496
95603
  project_id: projectId,
95497
- output_path: opts.output ? resolve25(opts.output) : undefined
95604
+ output_path: opts.output ? resolve26(opts.output) : undefined
95498
95605
  });
95499
95606
  const result = {
95500
- output_path: opts.output ? resolve25(opts.output) : null,
95607
+ output_path: opts.output ? resolve26(opts.output) : null,
95501
95608
  backup: backupBundle
95502
95609
  };
95503
95610
  if (opts.json || globalOpts.json) {
@@ -95668,8 +95775,8 @@ class TodosShadowMirror {
95668
95775
  async flush() {
95669
95776
  if (this.idle())
95670
95777
  return;
95671
- await new Promise((resolve26) => {
95672
- this.idleResolvers.push(resolve26);
95778
+ await new Promise((resolve27) => {
95779
+ this.idleResolvers.push(resolve27);
95673
95780
  this.pump();
95674
95781
  });
95675
95782
  }
@@ -95681,8 +95788,8 @@ class TodosShadowMirror {
95681
95788
  return;
95682
95789
  const resolvers = this.idleResolvers;
95683
95790
  this.idleResolvers = [];
95684
- for (const resolve26 of resolvers)
95685
- resolve26();
95791
+ for (const resolve27 of resolvers)
95792
+ resolve27();
95686
95793
  }
95687
95794
  pump() {
95688
95795
  if (this.pumping)
@@ -98192,6 +98299,41 @@ async function registerOptionalEventsCommands(program3) {
98192
98299
  }
98193
98300
  registerUnavailableEventsCommands(program3);
98194
98301
  }
98302
+ function commandForArgs(root, args) {
98303
+ let command = root;
98304
+ for (let index = 0;index < args.length; index += 1) {
98305
+ const arg = args[index];
98306
+ if (arg.startsWith("-")) {
98307
+ const exact = command.options.find((candidate) => candidate.long === arg || candidate.short === arg);
98308
+ const inline = command.options.find((candidate) => candidate.long !== undefined && arg.startsWith(`${candidate.long}=`) || candidate.short !== undefined && arg.startsWith(`${candidate.short}=`));
98309
+ const option = exact ?? inline;
98310
+ if (option?.required || option?.optional) {
98311
+ if (exact)
98312
+ index += 1;
98313
+ } else if (!option && !arg.includes("=")) {
98314
+ const next = args[index + 1];
98315
+ const nextIsCommand = next !== undefined && !next.startsWith("-") && command.commands.some((candidate) => candidate.name() === next || candidate.aliases().includes(next));
98316
+ if (next !== undefined && !next.startsWith("-") && !nextIsCommand)
98317
+ index += 1;
98318
+ }
98319
+ continue;
98320
+ }
98321
+ const child = command.commands.find((candidate) => candidate.name() === arg || candidate.aliases().includes(arg));
98322
+ if (!child)
98323
+ break;
98324
+ command = child;
98325
+ }
98326
+ return command;
98327
+ }
98328
+ function unsupportedActiveFormatOption(command, args) {
98329
+ if (command.name() !== "active")
98330
+ return null;
98331
+ const activeIndex = args.indexOf("active");
98332
+ if (activeIndex < 0)
98333
+ return null;
98334
+ const format = (arg) => arg === "--format" || arg.startsWith("--format=");
98335
+ return args.slice(activeIndex + 1).find(format) ?? args.slice(0, activeIndex).find(format) ?? null;
98336
+ }
98195
98337
  program2.name("todos").description("Universal task management for AI coding agents").version(getPackageVersion()).option("--project <path>", "Project path").option("-j, --json", "Output as JSON").option("--agent <name>", "Agent name").option("--session <id>", "Session ID");
98196
98338
  var authority;
98197
98339
  try {
@@ -98323,6 +98465,10 @@ await registerOptionalEventsCommands(program2);
98323
98465
  registerHelpCommands2(program2, authority.route, remoteCommandCapabilities);
98324
98466
  applyTodosCliHelpVisibility(program2, authority.route, remoteCommandCapabilities);
98325
98467
  try {
98468
+ const activeFormat = unsupportedActiveFormatOption(commandForArgs(program2, process.argv.slice(2)), process.argv.slice(2));
98469
+ if (activeFormat) {
98470
+ throw new Error(`ACTIVE_FORMAT_UNSUPPORTED: ${activeFormat} is not supported by todos active; use --json for machine-readable output`);
98471
+ }
98326
98472
  if (metadataRequested) {
98327
98473
  const unavailableCommand = getUnavailableTodosCliRemoteMetadataCommand(authority.route, remoteCommandCapabilities, process.argv.slice(2));
98328
98474
  if (unavailableCommand) {