open-walnut 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +247 -245
  3. package/dist/integrations/calendar/index.js +42 -36
  4. package/dist/integrations/jira/index.js +100 -78
  5. package/dist/integrations/ms-todo/index.js +94 -72
  6. package/dist/web/server.js +295 -293
  7. package/dist/web/static/assets/{OfficePreview-CEHO0xkd.js → OfficePreview-BlfHJAnI.js} +2 -2
  8. package/dist/web/static/assets/{docx-preview-CuZwjAMS.js → docx-preview-Cxj6saWk.js} +1 -1
  9. package/dist/web/static/assets/{index-ccs5s80D.js → index-7Z89132A.js} +1 -1
  10. package/dist/web/static/assets/{index-DLjK8dGE.js → index-8m4fXWae.js} +1 -1
  11. package/dist/web/static/assets/{index-BFF_G72i.js → index-B5OE08Hi.js} +276 -276
  12. package/dist/web/static/assets/{index-DR-LSqAg.js → index-BX-Q5nDs.js} +1 -1
  13. package/dist/web/static/assets/{index-DXtp_ZWh.js → index-BcvUZ0V6.js} +1 -1
  14. package/dist/web/static/assets/{index-D1dpOEzW.js → index-Bg08t19u.js} +1 -1
  15. package/dist/web/static/assets/{index-BRLxNhyy.js → index-BrQxDmgD.js} +1 -1
  16. package/dist/web/static/assets/{index-DtRwkh8J.js → index-C-ZIMUgb.js} +1 -1
  17. package/dist/web/static/assets/{index-DrWzb338.js → index-CJsj6NRK.js} +1 -1
  18. package/dist/web/static/assets/{index-unnPilnK.js → index-CPLhHJLE.js} +1 -1
  19. package/dist/web/static/assets/index-Cqfkxb49.css +32 -0
  20. package/dist/web/static/assets/{index-BBjg7m-_.js → index-DESxqmea.js} +1 -1
  21. package/dist/web/static/assets/{index-0MyC-yGG.js → index-Db4kYRIN.js} +1 -1
  22. package/dist/web/static/assets/{index-DOXm2Aye.js → index-Dmxn8BJB.js} +1 -1
  23. package/dist/web/static/assets/{index-C2YGUYGS.js → index-HOURQwyW.js} +1 -1
  24. package/dist/web/static/assets/{index-Bqg4_WEG.js → index-QcYRs4hO.js} +1 -1
  25. package/dist/web/static/assets/{index-DAOPV34I.js → index-i813E9y_.js} +1 -1
  26. package/dist/web/static/assets/{index-D9qPPm7h.js → index-ntIs-QCy.js} +1 -1
  27. package/dist/web/static/assets/{index-mWEwJcqw.js → index-qbtGSfLJ.js} +1 -1
  28. package/dist/web/static/assets/{jszip.min-DYFwy4PE.js → jszip.min-CjTDoW5q.js} +1 -1
  29. package/dist/web/static/assets/{pptx-preview.es-eu2nX9JC.js → pptx-preview.es-CW9hHNwC.js} +1 -1
  30. package/dist/web/static/index.html +2 -2
  31. package/package.json +1 -1
  32. package/dist/web/static/assets/index-DeYCGmOR.css +0 -32
@@ -816,7 +816,7 @@ var init_fs = __esm({
816
816
  });
817
817
 
818
818
  // src/core/types.ts
819
- var VALID_PRIORITIES, PIN_TIER_POLICY, SESSION_MODELS, SESSION_MODEL_CLI_MAP, VALID_SESSION_MODEL_IDS, SESSION_EFFORT_IDS, VALID_SESSION_EFFORT_IDS, SESSION_MODES, SESSION_MODE_IDS, VALID_SESSION_MODE_IDS, SESSION_MODE_CLI_MAP, SESSION_MODE_LABELS, DEFAULT_AGENT_ENGINE_PROVIDER;
819
+ var VALID_PRIORITIES, PIN_TIER_POLICY, SESSION_MODELS, SESSION_MODEL_CLI_MAP, VALID_SESSION_MODEL_IDS, SESSION_EFFORT_IDS, VALID_SESSION_EFFORT_IDS, SESSION_MODES, SESSION_MODE_IDS, VALID_SESSION_MODE_IDS, SESSION_MODE_CLI_MAP, SESSION_MODE_LABELS;
820
820
  var init_types = __esm({
821
821
  "src/core/types.ts"() {
822
822
  "use strict";
@@ -868,7 +868,6 @@ var init_types = __esm({
868
868
  VALID_SESSION_MODE_IDS = new Set(SESSION_MODE_IDS);
869
869
  SESSION_MODE_CLI_MAP = Object.fromEntries(SESSION_MODES.map((m) => [m.id, m.cli]));
870
870
  SESSION_MODE_LABELS = Object.fromEntries(SESSION_MODES.map((m) => [m.id, m.label]));
871
- DEFAULT_AGENT_ENGINE_PROVIDER = "claude-code";
872
871
  }
873
872
  });
874
873
 
@@ -1386,10 +1385,32 @@ var init_model_catalog = __esm({
1386
1385
  }
1387
1386
  });
1388
1387
 
1389
- // src/core/ssh-config-scanner.ts
1390
- import fs5 from "fs/promises";
1391
- import path6 from "path";
1388
+ // src/core/claude-cli-detect.ts
1389
+ import { execFileSync } from "child_process";
1390
+ import fs5 from "fs";
1392
1391
  import os3 from "os";
1392
+ import path6 from "path";
1393
+ var _CLAUDE_CREDENTIALS_HOME;
1394
+ var init_claude_cli_detect = __esm({
1395
+ "src/core/claude-cli-detect.ts"() {
1396
+ "use strict";
1397
+ init_constants();
1398
+ _CLAUDE_CREDENTIALS_HOME = os3.homedir();
1399
+ }
1400
+ });
1401
+
1402
+ // src/agent/providers/default-provider.ts
1403
+ var init_default_provider = __esm({
1404
+ "src/agent/providers/default-provider.ts"() {
1405
+ "use strict";
1406
+ init_claude_cli_detect();
1407
+ }
1408
+ });
1409
+
1410
+ // src/core/ssh-config-scanner.ts
1411
+ import fs6 from "fs/promises";
1412
+ import path7 from "path";
1413
+ import os4 from "os";
1393
1414
  function isGitServerHost(h) {
1394
1415
  if (h.user === "git") return true;
1395
1416
  const gitPrefix = /^(git|github|gitlab|bitbucket|codecommit|ssh\.github)\./i;
@@ -1405,10 +1426,10 @@ function shortLabelForFqdn(hostname) {
1405
1426
  return `${first.slice(0, 12)}\u2026${first.slice(-8)}`;
1406
1427
  }
1407
1428
  async function scanSshConfig(configPath) {
1408
- const sshConfigPath = configPath ?? path6.join(os3.homedir(), ".ssh", "config");
1429
+ const sshConfigPath = configPath ?? path7.join(os4.homedir(), ".ssh", "config");
1409
1430
  let mtimeMs2;
1410
1431
  try {
1411
- mtimeMs2 = (await fs5.stat(sshConfigPath)).mtimeMs;
1432
+ mtimeMs2 = (await fs6.stat(sshConfigPath)).mtimeMs;
1412
1433
  } catch {
1413
1434
  return /* @__PURE__ */ new Map();
1414
1435
  }
@@ -1421,7 +1442,7 @@ async function scanSshConfig(configPath) {
1421
1442
  async function parseSshConfigFile(sshConfigPath) {
1422
1443
  const discovered = /* @__PURE__ */ new Map();
1423
1444
  try {
1424
- const content = await fs5.readFile(sshConfigPath, "utf-8");
1445
+ const content = await fs6.readFile(sshConfigPath, "utf-8");
1425
1446
  const lines = content.split("\n");
1426
1447
  let currentHost = null;
1427
1448
  for (const rawLine of lines) {
@@ -1508,7 +1529,7 @@ var init_ssh_config_scanner = __esm({
1508
1529
  });
1509
1530
 
1510
1531
  // src/core/config-manager.ts
1511
- import fs6 from "fs/promises";
1532
+ import fs7 from "fs/promises";
1512
1533
  import yaml from "js-yaml";
1513
1534
  function migrateConfigToProjectOnly(config) {
1514
1535
  let changed = false;
@@ -1581,13 +1602,13 @@ function migrateConfigToProjectOnly(config) {
1581
1602
  }
1582
1603
  async function readRawConfigContent() {
1583
1604
  try {
1584
- const primary = await fs6.readFile(CONFIG_FILE, "utf-8");
1605
+ const primary = await fs7.readFile(CONFIG_FILE, "utf-8");
1585
1606
  if (primary.trim()) return primary;
1586
1607
  throw new Error("config.yaml is empty");
1587
1608
  } catch (primaryErr) {
1588
1609
  let backup;
1589
1610
  try {
1590
- backup = await fs6.readFile(CONFIG_BACKUP_FILE, "utf-8");
1611
+ backup = await fs7.readFile(CONFIG_BACKUP_FILE, "utf-8");
1591
1612
  } catch {
1592
1613
  return null;
1593
1614
  }
@@ -1597,7 +1618,7 @@ async function readRawConfigContent() {
1597
1618
  backup: CONFIG_BACKUP_FILE
1598
1619
  });
1599
1620
  try {
1600
- await fs6.writeFile(CONFIG_FILE, backup, "utf-8");
1621
+ await fs7.writeFile(CONFIG_FILE, backup, "utf-8");
1601
1622
  } catch {
1602
1623
  }
1603
1624
  return backup;
@@ -1606,10 +1627,10 @@ async function readRawConfigContent() {
1606
1627
  async function writeFileAtomic2(filePath, content) {
1607
1628
  const tmp = `${filePath}.tmp-${process.pid}-${Date.now().toString(36)}`;
1608
1629
  try {
1609
- await fs6.writeFile(tmp, content, "utf-8");
1610
- await fs6.rename(tmp, filePath);
1630
+ await fs7.writeFile(tmp, content, "utf-8");
1631
+ await fs7.rename(tmp, filePath);
1611
1632
  } catch (err) {
1612
- await fs6.rm(tmp, { force: true }).catch(() => {
1633
+ await fs7.rm(tmp, { force: true }).catch(() => {
1613
1634
  });
1614
1635
  throw err;
1615
1636
  }
@@ -1743,7 +1764,7 @@ async function seedConfigDefaults() {
1743
1764
  const config = await getConfig();
1744
1765
  let needsWrite = false;
1745
1766
  try {
1746
- const raw = await fs6.readFile(CONFIG_FILE, "utf-8");
1767
+ const raw = await fs7.readFile(CONFIG_FILE, "utf-8");
1747
1768
  if (!raw.includes("available_models")) {
1748
1769
  needsWrite = true;
1749
1770
  }
@@ -1771,6 +1792,7 @@ var init_config_manager = __esm({
1771
1792
  init_constants();
1772
1793
  init_types();
1773
1794
  init_model_catalog();
1795
+ init_default_provider();
1774
1796
  init_ssh_config_scanner();
1775
1797
  DEFAULT_CONFIG = {
1776
1798
  version: 1,
@@ -1782,12 +1804,12 @@ var init_config_manager = __esm({
1782
1804
  // so this never re-routes an established setup.
1783
1805
  defaults: { priority: "none", platform: "local" },
1784
1806
  provider: { type: "claude-code" },
1785
- // Which ENGINE answers a Personal AI chat turn. 'walnut-agent' = today's in-process
1786
- // agent loop; 'claude-code' routes the turn into a lane-bound `claude` session.
1787
- // NOTE: getConfig() spreads the parsed file OVER these defaults at the TOP
1788
- // level, so a config.yaml with any `agent:` section replaces this whole object
1789
- // — resolveAgentEngineProvider() (below) is what actually applies the default.
1790
- agent: { provider: DEFAULT_AGENT_ENGINE_PROVIDER }
1807
+ // Which ENGINE answers a Personal AI chat turn is NOT defaulted here: it follows
1808
+ // the AI provider (Settings → AI Provider) — see resolveAgentEngineProvider().
1809
+ // getConfig() spreads the parsed file OVER these defaults at the TOP level, so
1810
+ // anything put in this object is dropped by any config.yaml with an `agent:`
1811
+ // section; the resolver is what actually applies the rule.
1812
+ agent: {}
1791
1813
  };
1792
1814
  CONFIG_BACKUP_FILE = `${CONFIG_FILE}.bak`;
1793
1815
  writeLock = Promise.resolve();
@@ -2126,7 +2148,7 @@ var init_format = __esm({
2126
2148
  // src/utils/file-ops.ts
2127
2149
  import crypto4 from "crypto";
2128
2150
  import fsp4 from "fs/promises";
2129
- import path7 from "path";
2151
+ import path8 from "path";
2130
2152
  var MAX_READ_SIZE;
2131
2153
  var init_file_ops = __esm({
2132
2154
  "src/utils/file-ops.ts"() {
@@ -2137,17 +2159,17 @@ var init_file_ops = __esm({
2137
2159
  });
2138
2160
 
2139
2161
  // src/core/memory-file.ts
2140
- import fs7 from "fs";
2141
- import path8 from "path";
2162
+ import fs8 from "fs";
2163
+ import path9 from "path";
2142
2164
  function resolveMemoryPath(agentId) {
2143
2165
  if (!agentId || agentId === "general") return MEMORY_FILE;
2144
- return path8.join(agentMemoryDir(agentId), "MEMORY.md");
2166
+ return path9.join(agentMemoryDir(agentId), "MEMORY.md");
2145
2167
  }
2146
2168
  function ensureMemoryFile(agentId) {
2147
2169
  const filePath = resolveMemoryPath(agentId);
2148
- if (fs7.existsSync(filePath)) return;
2149
- fs7.mkdirSync(path8.dirname(filePath), { recursive: true });
2150
- fs7.writeFileSync(filePath, DEFAULT_TEMPLATE, "utf-8");
2170
+ if (fs8.existsSync(filePath)) return;
2171
+ fs8.mkdirSync(path9.dirname(filePath), { recursive: true });
2172
+ fs8.writeFileSync(filePath, DEFAULT_TEMPLATE, "utf-8");
2151
2173
  }
2152
2174
  var DEFAULT_TEMPLATE;
2153
2175
  var init_memory_file = __esm({
@@ -2167,15 +2189,15 @@ description: >
2167
2189
 
2168
2190
  // src/core/tmp-sweep.ts
2169
2191
  import fsp5 from "fs/promises";
2170
- import path9 from "path";
2192
+ import path10 from "path";
2171
2193
  function sweepDirs() {
2172
2194
  return [
2173
2195
  WALNUT_HOME,
2174
2196
  SYNC_DIR,
2175
- path9.join(WALNUT_HOME, "sessions"),
2176
- path9.join(WALNUT_HOME, "sessions", "transcripts"),
2197
+ path10.join(WALNUT_HOME, "sessions"),
2198
+ path10.join(WALNUT_HOME, "sessions", "transcripts"),
2177
2199
  TASKS_DIR,
2178
- path9.join(TASKS_DIR, "outbox"),
2200
+ path10.join(TASKS_DIR, "outbox"),
2179
2201
  CONVERSATIONS_DIR,
2180
2202
  MEMORY_DIR,
2181
2203
  DAILY_DIR,
@@ -2196,7 +2218,7 @@ async function sweepOrphanAtomicTmpFiles() {
2196
2218
  const entries = await fsp5.readdir(dir, { withFileTypes: true });
2197
2219
  for (const entry of entries) {
2198
2220
  if (!entry.isFile() || !ORPHAN_RE.test(entry.name)) continue;
2199
- const full = path9.join(dir, entry.name);
2221
+ const full = path10.join(dir, entry.name);
2200
2222
  try {
2201
2223
  const st = await fsp5.stat(full);
2202
2224
  if (st.mtimeMs > cutoff) continue;
@@ -2229,10 +2251,10 @@ var init_tmp_sweep = __esm({
2229
2251
 
2230
2252
  // src/core/init.ts
2231
2253
  import fsp6 from "fs/promises";
2232
- import fs8 from "fs";
2254
+ import fs9 from "fs";
2233
2255
  async function migrateLegacyMemoryFile() {
2234
2256
  try {
2235
- if (fs8.existsSync(LEGACY_MEMORY_FILE) && !fs8.existsSync(MEMORY_FILE)) {
2257
+ if (fs9.existsSync(LEGACY_MEMORY_FILE) && !fs9.existsSync(MEMORY_FILE)) {
2236
2258
  await fsp6.rename(LEGACY_MEMORY_FILE, MEMORY_FILE);
2237
2259
  log.memory.info("Migrated MEMORY.md into memory/ folder", { from: LEGACY_MEMORY_FILE, to: MEMORY_FILE });
2238
2260
  }
@@ -2449,15 +2471,15 @@ var init_integration_registry = __esm({
2449
2471
 
2450
2472
  // src/core/task-db.ts
2451
2473
  import Database from "better-sqlite3";
2452
- import fs9 from "fs";
2453
- import path10 from "path";
2474
+ import fs10 from "fs";
2475
+ import path11 from "path";
2454
2476
  import yaml2 from "js-yaml";
2455
2477
  function getDb() {
2456
2478
  if (db) return db;
2457
2479
  if (initAttempted) throw initError;
2458
2480
  initAttempted = true;
2459
2481
  try {
2460
- fs9.mkdirSync(path10.dirname(TASK_DB_PATH), { recursive: true });
2482
+ fs10.mkdirSync(path11.dirname(TASK_DB_PATH), { recursive: true });
2461
2483
  const handle = new Database(TASK_DB_PATH);
2462
2484
  handle.pragma("journal_mode = WAL");
2463
2485
  handle.pragma("busy_timeout = 5000");
@@ -2675,8 +2697,8 @@ function migrateToProjectOnly(handle) {
2675
2697
  }
2676
2698
  try {
2677
2699
  handle.pragma("wal_checkpoint(TRUNCATE)");
2678
- if (!fs9.existsSync(TASK_DB_PRE_V5_BACKUP_PATH)) {
2679
- fs9.copyFileSync(TASK_DB_PATH, TASK_DB_PRE_V5_BACKUP_PATH);
2700
+ if (!fs10.existsSync(TASK_DB_PRE_V5_BACKUP_PATH)) {
2701
+ fs10.copyFileSync(TASK_DB_PATH, TASK_DB_PRE_V5_BACKUP_PATH);
2680
2702
  log.task.info("task-db v5: wrote pre-migration backup", { path: TASK_DB_PRE_V5_BACKUP_PATH });
2681
2703
  }
2682
2704
  } catch (err) {
@@ -3103,7 +3125,7 @@ var init_task_db = __esm({
3103
3125
  init_constants();
3104
3126
  init_logging();
3105
3127
  init_phase();
3106
- TASK_DB_PATH = path10.join(TASKS_DIR, "tasks.sqlite");
3128
+ TASK_DB_PATH = path11.join(TASKS_DIR, "tasks.sqlite");
3107
3129
  EXPLICIT_TASK_COLUMNS = [
3108
3130
  "id",
3109
3131
  "title",
@@ -3264,8 +3286,8 @@ var init_task_db = __esm({
3264
3286
  });
3265
3287
 
3266
3288
  // src/core/task-db-migration.ts
3267
- import fs10 from "fs";
3268
- import path11 from "path";
3289
+ import fs11 from "fs";
3290
+ import path12 from "path";
3269
3291
  import yaml3 from "js-yaml";
3270
3292
  async function runMigrationIfNeeded() {
3271
3293
  const db2 = getDb();
@@ -3276,7 +3298,7 @@ async function runMigrationIfNeeded() {
3276
3298
  if (existing.n > 0) {
3277
3299
  return { migrated: false, count: existing.n };
3278
3300
  }
3279
- if (!fs10.existsSync(TASKS_FILE)) {
3301
+ if (!fs11.existsSync(TASKS_FILE)) {
3280
3302
  return { migrated: false, count: 0 };
3281
3303
  }
3282
3304
  const store = await readJsonFile(TASKS_FILE, { version: 1, tasks: [] });
@@ -3433,9 +3455,9 @@ async function runMigrationIfNeeded() {
3433
3455
  }
3434
3456
  const after = db2.prepare("SELECT COUNT(*) AS n FROM tasks").get();
3435
3457
  const count = after.n;
3436
- const backupPath = path11.join(path11.dirname(TASKS_FILE), "tasks.json.migrated-from-json.backup");
3458
+ const backupPath = path12.join(path12.dirname(TASKS_FILE), "tasks.json.migrated-from-json.backup");
3437
3459
  try {
3438
- fs10.copyFileSync(TASKS_FILE, backupPath);
3460
+ fs11.copyFileSync(TASKS_FILE, backupPath);
3439
3461
  } catch (err) {
3440
3462
  log.task.warn("task-db migration: backup copy failed (non-fatal)", {
3441
3463
  path: backupPath,
@@ -3459,9 +3481,9 @@ var init_task_db_migration = __esm({
3459
3481
  });
3460
3482
 
3461
3483
  // src/core/memory-dir-migration.ts
3462
- import fs11 from "fs";
3484
+ import fs12 from "fs";
3463
3485
  import fsp7 from "fs/promises";
3464
- import path12 from "path";
3486
+ import path13 from "path";
3465
3487
  function bodyOf(content) {
3466
3488
  const fm = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);
3467
3489
  return fm ? content.slice(fm[0].length) : content;
@@ -3479,7 +3501,7 @@ ${legacyBody}
3479
3501
  }
3480
3502
  function mtimeMs(file) {
3481
3503
  try {
3482
- return fs11.statSync(file).mtimeMs;
3504
+ return fs12.statSync(file).mtimeMs;
3483
3505
  } catch {
3484
3506
  return 0;
3485
3507
  }
@@ -3488,24 +3510,24 @@ function findCandidates(root) {
3488
3510
  const out = [];
3489
3511
  let level1;
3490
3512
  try {
3491
- level1 = fs11.readdirSync(root, { withFileTypes: true });
3513
+ level1 = fs12.readdirSync(root, { withFileTypes: true });
3492
3514
  } catch {
3493
3515
  return out;
3494
3516
  }
3495
3517
  for (const cat of level1) {
3496
3518
  if (!cat.isDirectory()) continue;
3497
- const catDir = path12.join(root, cat.name);
3498
- if (fs11.existsSync(path12.join(catDir, MEMORY_FILE_NAME))) continue;
3519
+ const catDir = path13.join(root, cat.name);
3520
+ if (fs12.existsSync(path13.join(catDir, MEMORY_FILE_NAME))) continue;
3499
3521
  let level2;
3500
3522
  try {
3501
- level2 = fs11.readdirSync(catDir, { withFileTypes: true });
3523
+ level2 = fs12.readdirSync(catDir, { withFileTypes: true });
3502
3524
  } catch {
3503
3525
  continue;
3504
3526
  }
3505
3527
  for (const proj of level2) {
3506
3528
  if (!proj.isDirectory()) continue;
3507
- const sourceDir = path12.join(catDir, proj.name);
3508
- if (!fs11.existsSync(path12.join(sourceDir, MEMORY_FILE_NAME))) continue;
3529
+ const sourceDir = path13.join(catDir, proj.name);
3530
+ if (!fs12.existsSync(path13.join(sourceDir, MEMORY_FILE_NAME))) continue;
3509
3531
  out.push({ category: cat.name, project: proj.name, sourceDir });
3510
3532
  }
3511
3533
  }
@@ -3519,11 +3541,11 @@ async function drainDir(from, to) {
3519
3541
  return;
3520
3542
  }
3521
3543
  for (const name of entries) {
3522
- const target = path12.join(to, name);
3523
- if (fs11.existsSync(target)) continue;
3524
- await fsp7.rename(path12.join(from, name), target).catch((err) => {
3544
+ const target = path13.join(to, name);
3545
+ if (fs12.existsSync(target)) continue;
3546
+ await fsp7.rename(path13.join(from, name), target).catch((err) => {
3525
3547
  log.memory.warn("memory-dir migration: entry move failed", {
3526
- from: path12.join(from, name),
3548
+ from: path13.join(from, name),
3527
3549
  to: target,
3528
3550
  error: String(err)
3529
3551
  });
@@ -3535,23 +3557,23 @@ async function drainDir(from, to) {
3535
3557
  async function migrateProjectMemoryDirs() {
3536
3558
  const result = { ran: false, moved: 0, merged: 0 };
3537
3559
  try {
3538
- if (!fs11.existsSync(PROJECTS_MEMORY_DIR)) return result;
3539
- if (fs11.existsSync(MEMORY_DIR_MIGRATION_MARKER)) return result;
3560
+ if (!fs12.existsSync(PROJECTS_MEMORY_DIR)) return result;
3561
+ if (fs12.existsSync(MEMORY_DIR_MIGRATION_MARKER)) return result;
3540
3562
  result.ran = true;
3541
3563
  const candidates = findCandidates(PROJECTS_MEMORY_DIR);
3542
3564
  const touchedCategories = new Set(candidates.map((c) => c.category));
3543
3565
  for (const c of candidates) {
3544
- const targetDir = path12.join(PROJECTS_MEMORY_DIR, c.project);
3566
+ const targetDir = path13.join(PROJECTS_MEMORY_DIR, c.project);
3545
3567
  const label = `${c.category}/${c.project}`;
3546
3568
  try {
3547
- if (!fs11.existsSync(targetDir)) {
3569
+ if (!fs12.existsSync(targetDir)) {
3548
3570
  await fsp7.rename(c.sourceDir, targetDir);
3549
3571
  result.moved += 1;
3550
3572
  continue;
3551
3573
  }
3552
- const sourceMem = path12.join(c.sourceDir, MEMORY_FILE_NAME);
3553
- const targetMem = path12.join(targetDir, MEMORY_FILE_NAME);
3554
- if (!fs11.existsSync(targetMem)) {
3574
+ const sourceMem = path13.join(c.sourceDir, MEMORY_FILE_NAME);
3575
+ const targetMem = path13.join(targetDir, MEMORY_FILE_NAME);
3576
+ if (!fs12.existsSync(targetMem)) {
3555
3577
  await fsp7.rename(sourceMem, targetMem);
3556
3578
  await drainDir(c.sourceDir, targetDir);
3557
3579
  result.moved += 1;
@@ -3573,7 +3595,7 @@ async function migrateProjectMemoryDirs() {
3573
3595
  }
3574
3596
  }
3575
3597
  for (const cat of touchedCategories) {
3576
- await fsp7.rmdir(path12.join(PROJECTS_MEMORY_DIR, cat)).catch(() => {
3598
+ await fsp7.rmdir(path13.join(PROJECTS_MEMORY_DIR, cat)).catch(() => {
3577
3599
  });
3578
3600
  }
3579
3601
  await fsp7.writeFile(
@@ -3601,7 +3623,7 @@ var init_memory_dir_migration = __esm({
3601
3623
  "use strict";
3602
3624
  init_constants();
3603
3625
  init_logging();
3604
- MEMORY_DIR_MIGRATION_MARKER = path12.join(PROJECTS_MEMORY_DIR, ".migrated-project-only");
3626
+ MEMORY_DIR_MIGRATION_MARKER = path13.join(PROJECTS_MEMORY_DIR, ".migrated-project-only");
3605
3627
  MEMORY_FILE_NAME = "MEMORY.md";
3606
3628
  }
3607
3629
  });
@@ -3977,11 +3999,11 @@ var init_jira_client = __esm({
3977
3999
  return this.request("GET", "/rest/api/3/myself");
3978
4000
  }
3979
4001
  // ── HTTP transport ──
3980
- async request(method, path14, body) {
4002
+ async request(method, path15, body) {
3981
4003
  let lastError = null;
3982
4004
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
3983
4005
  try {
3984
- return await this.doRequest(method, path14, body);
4006
+ return await this.doRequest(method, path15, body);
3985
4007
  } catch (err) {
3986
4008
  lastError = err instanceof Error ? err : new Error(String(err));
3987
4009
  const status = err.statusCode;
@@ -3990,16 +4012,16 @@ var init_jira_client = __esm({
3990
4012
  }
3991
4013
  if (attempt < MAX_RETRIES) {
3992
4014
  const backoff = INITIAL_BACKOFF_MS * Math.pow(2, attempt);
3993
- this.logger.debug("Jira API retrying", { method, path: path14, attempt: attempt + 1, backoff });
4015
+ this.logger.debug("Jira API retrying", { method, path: path15, attempt: attempt + 1, backoff });
3994
4016
  await new Promise((r) => setTimeout(r, backoff));
3995
4017
  }
3996
4018
  }
3997
4019
  }
3998
4020
  throw lastError ?? new Error("Jira request failed");
3999
4021
  }
4000
- doRequest(method, path14, body) {
4022
+ doRequest(method, path15, body) {
4001
4023
  return new Promise((resolve, reject) => {
4002
- const url = new URL(path14, this.baseUrl);
4024
+ const url = new URL(path15, this.baseUrl);
4003
4025
  const isHttps = url.protocol === "https:";
4004
4026
  const transport = isHttps ? https : http;
4005
4027
  const bodyStr = body ? JSON.stringify(body) : void 0;
@@ -4032,14 +4054,14 @@ var init_jira_client = __esm({
4032
4054
  }
4033
4055
  return;
4034
4056
  }
4035
- const err = new Error(`Jira API ${method} ${path14} \u2192 ${status}: ${raw.slice(0, 500)}`);
4057
+ const err = new Error(`Jira API ${method} ${path15} \u2192 ${status}: ${raw.slice(0, 500)}`);
4036
4058
  err.statusCode = status;
4037
4059
  reject(err);
4038
4060
  });
4039
4061
  });
4040
4062
  req.on("error", reject);
4041
4063
  req.setTimeout(3e4, () => {
4042
- req.destroy(new Error(`Jira API ${method} ${path14} timed out after 30s`));
4064
+ req.destroy(new Error(`Jira API ${method} ${path15} timed out after 30s`));
4043
4065
  });
4044
4066
  if (bodyStr) req.write(bodyStr);
4045
4067
  req.end();
@@ -4268,7 +4290,7 @@ __export(sync_exports, {
4268
4290
  mapToLocal: () => mapToLocal,
4269
4291
  syncTasks: () => syncTasks
4270
4292
  });
4271
- import path13 from "path";
4293
+ import path14 from "path";
4272
4294
  function getJiraConfig(config) {
4273
4295
  return config.plugins?.jira;
4274
4296
  }
@@ -4678,7 +4700,7 @@ var init_sync = __esm({
4678
4700
  init_jira_client();
4679
4701
  init_workflow();
4680
4702
  init_adf();
4681
- JIRA_SYNC_FILE = path13.join(SYNC_DIR, "jira-sync.json");
4703
+ JIRA_SYNC_FILE = path14.join(SYNC_DIR, "jira-sync.json");
4682
4704
  syncLog = createSubsystemLogger("jira");
4683
4705
  LOCAL_TO_JIRA_PRIORITY = {
4684
4706
  immediate: "Highest",