@wrongstack/core 0.109.1 → 0.141.0

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 (67) hide show
  1. package/dist/{agent-bridge-mOxbpFcg.d.ts → agent-bridge-r9y6gdn4.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-DukQLUcS.d.ts → agent-subagent-runner-1GeQE_L0.d.ts} +7 -8
  3. package/dist/{brain-Dfv4Y82E.d.ts → brain-Cp_3GIS2.d.ts} +14 -3
  4. package/dist/{compactor-DXLxLcmU.d.ts → compactor-BueGt7LG.d.ts} +9 -1
  5. package/dist/{config-BSU-6vah.d.ts → config-BaVThgnT.d.ts} +104 -3
  6. package/dist/{context-CNRYfhUv.d.ts → context-C7G_MtLV.d.ts} +38 -1
  7. package/dist/coordination/index.d.ts +12 -13
  8. package/dist/coordination/index.js +229 -17
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/defaults/index.d.ts +26 -27
  11. package/dist/defaults/index.js +886 -721
  12. package/dist/defaults/index.js.map +1 -1
  13. package/dist/execution/index.d.ts +15 -16
  14. package/dist/execution/index.js +535 -322
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/extension/index.d.ts +6 -7
  17. package/dist/{goal-preamble-CI8lxeY1.d.ts → goal-preamble-iuIUTQwk.d.ts} +48 -18
  18. package/dist/{index-BWRN6wOb.d.ts → index-BZdezm3g.d.ts} +9 -10
  19. package/dist/{index-DIKEcfgC.d.ts → index-CPweVoFM.d.ts} +7 -6
  20. package/dist/index.d.ts +51 -52
  21. package/dist/index.js +752 -545
  22. package/dist/index.js.map +1 -1
  23. package/dist/infrastructure/index.d.ts +6 -7
  24. package/dist/infrastructure/index.js +64 -19
  25. package/dist/infrastructure/index.js.map +1 -1
  26. package/dist/kernel/index.d.ts +10 -11
  27. package/dist/kernel/index.js.map +1 -1
  28. package/dist/llm-selector-CP72f1lC.d.ts +58 -0
  29. package/dist/{mcp-servers-CXCsANdY.d.ts → mcp-servers-Bl5LTvQg.d.ts} +3 -3
  30. package/dist/{mode-ARA3HrkY.d.ts → mode-CZlO9iU1.d.ts} +1 -1
  31. package/dist/models/index.d.ts +157 -53
  32. package/dist/models/index.js +475 -20
  33. package/dist/models/index.js.map +1 -1
  34. package/dist/{models-registry-DU64QxQa.d.ts → models-registry-D90K9UnM.d.ts} +1 -1
  35. package/dist/{multi-agent-coordinator-51LvnXkD.d.ts → multi-agent-coordinator-QWEzJDlm.d.ts} +1 -1
  36. package/dist/{null-fleet-bus-D09hMzFQ.d.ts → null-fleet-bus-BUyfqh23.d.ts} +13 -10
  37. package/dist/observability/index.d.ts +2 -2
  38. package/dist/{parallel-eternal-engine-B2CbsKpc.d.ts → parallel-eternal-engine-Dj2SYzha.d.ts} +24 -11
  39. package/dist/{path-resolver-DDJiMAtX.d.ts → path-resolver-DRjQBkoO.d.ts} +3 -3
  40. package/dist/{permission-BDv7z0mk.d.ts → permission-B7nKnEvQ.d.ts} +1 -1
  41. package/dist/{permission-policy-dF74EpDp.d.ts → permission-policy-8-6zBmfA.d.ts} +2 -13
  42. package/dist/{pipeline-BqiA_UMr.d.ts → pipeline-BG7UgbDc.d.ts} +2 -2
  43. package/dist/{plan-templates-BdDxl9cI.d.ts → plan-templates-CkKNPU3I.d.ts} +6 -6
  44. package/dist/{provider-runner-BUunikwY.d.ts → provider-runner-BNpuIyOL.d.ts} +3 -3
  45. package/dist/{retry-policy-BcmuT_V0.d.ts → retry-policy-rutAfVeR.d.ts} +1 -1
  46. package/dist/sdd/index.d.ts +8 -9
  47. package/dist/sdd/index.js +208 -1
  48. package/dist/sdd/index.js.map +1 -1
  49. package/dist/{secret-vault-DrOhc2i5.d.ts → secret-vault-BTcC_T5v.d.ts} +3 -2
  50. package/dist/security/index.d.ts +5 -7
  51. package/dist/security/index.js +4 -35
  52. package/dist/security/index.js.map +1 -1
  53. package/dist/{selector-C7wcdqMA.d.ts → selector-4vDFZKt3.d.ts} +1 -1
  54. package/dist/{session-event-bridge-BpJ5trO9.d.ts → session-event-bridge-DWlvglC2.d.ts} +2 -2
  55. package/dist/{session-reader-DDz1Ek4V.d.ts → session-reader-BAtCxdaw.d.ts} +1 -1
  56. package/dist/storage/index.d.ts +14 -15
  57. package/dist/storage/index.js +140 -134
  58. package/dist/storage/index.js.map +1 -1
  59. package/dist/types/index.d.ts +19 -20
  60. package/dist/types/index.js +186 -102
  61. package/dist/types/index.js.map +1 -1
  62. package/dist/utils/index.d.ts +38 -15
  63. package/dist/utils/index.js +62 -33
  64. package/dist/utils/index.js.map +1 -1
  65. package/dist/{wstack-paths-_lqjzErq.d.ts → wstack-paths-DD50Omgn.d.ts} +3 -0
  66. package/package.json +2 -2
  67. package/dist/models-registry-B6_KfS65.d.ts +0 -95
@@ -1,6 +1,7 @@
1
1
  import { randomBytes, randomUUID, createHash } from 'crypto';
2
2
  import * as fsp from 'fs/promises';
3
- import * as path12 from 'path';
3
+ import * as path13 from 'path';
4
+ import 'fs';
4
5
  import * as os from 'os';
5
6
  import { hostname } from 'os';
6
7
 
@@ -12,9 +13,9 @@ function expectDefined(value, label) {
12
13
  return value;
13
14
  }
14
15
  async function atomicWrite(targetPath, content, opts = {}) {
15
- const dir = path12.dirname(targetPath);
16
+ const dir = path13.dirname(targetPath);
16
17
  await fsp.mkdir(dir, { recursive: true });
17
- const tmp = path12.join(dir, `.${path12.basename(targetPath)}.${randomBytes(6).toString("hex")}.tmp`);
18
+ const tmp = path13.join(dir, `.${path13.basename(targetPath)}.${randomBytes(6).toString("hex")}.tmp`);
18
19
  try {
19
20
  if (typeof content === "string") {
20
21
  await fsp.writeFile(tmp, content, { flag: "wx", encoding: opts.encoding ?? "utf8" });
@@ -53,9 +54,9 @@ async function ensureDir(dir) {
53
54
  await fsp.mkdir(dir, { recursive: true });
54
55
  }
55
56
  async function withFileLock(targetPath, fn, opts = {}) {
56
- const dir = path12.dirname(targetPath);
57
+ const dir = path13.dirname(targetPath);
57
58
  await fsp.mkdir(dir, { recursive: true });
58
- const lockPath = path12.join(dir, `.${path12.basename(targetPath)}.lock`);
59
+ const lockPath = path13.join(dir, `.${path13.basename(targetPath)}.lock`);
59
60
  const timeoutMs = opts.timeoutMs ?? 5e3;
60
61
  const staleMs = opts.staleMs ?? 3e4;
61
62
  const started = Date.now();
@@ -233,11 +234,11 @@ var DefaultSessionStore = class _DefaultSessionStore {
233
234
  }
234
235
  /** Absolute path to the session index file. */
235
236
  get indexFile() {
236
- return path12.join(this.dir, "_index.jsonl");
237
+ return path13.join(this.dir, "_index.jsonl");
237
238
  }
238
239
  /** Join session ID to its absolute path within the store directory. */
239
240
  sessionPath(id, ext) {
240
- return path12.join(this.dir, `${id}${ext}`);
241
+ return path13.join(this.dir, `${id}${ext}`);
241
242
  }
242
243
  /**
243
244
  * Ensure the directory implied by the session ID exists. When the ID
@@ -245,7 +246,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
245
246
  * subdirectory so sessions group naturally by day.
246
247
  */
247
248
  async ensureShardDir(id) {
248
- const dirPath = path12.dirname(path12.join(this.dir, id));
249
+ const dirPath = path13.dirname(path13.join(this.dir, id));
249
250
  await ensureDir(dirPath);
250
251
  return dirPath;
251
252
  }
@@ -253,7 +254,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
253
254
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
254
255
  const id = meta.id && meta.id.length > 0 ? meta.id : generateSessionId(startedAt, meta.model ?? meta.provider);
255
256
  const shardDir = await this.ensureShardDir(id);
256
- const file = path12.join(shardDir, `${path12.basename(id)}.jsonl`);
257
+ const file = path13.join(shardDir, `${path13.basename(id)}.jsonl`);
257
258
  let handle;
258
259
  try {
259
260
  handle = await fsp.open(file, "a", 384);
@@ -271,8 +272,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
271
272
  onClose: (s) => this.appendToIndex(s)
272
273
  });
273
274
  } catch (err) {
274
- await handle.close().catch(() => {
275
- });
275
+ await handle.close().catch((e) => console.warn(`[session-store] handle.close() failed: ${e}`));
276
276
  throw err;
277
277
  }
278
278
  }
@@ -303,8 +303,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
303
303
  );
304
304
  return { writer, data };
305
305
  } catch (err) {
306
- await handle.close().catch(() => {
307
- });
306
+ await handle.close().catch((e) => console.warn(`[session-store] handle.close() failed: ${e}`));
308
307
  throw err;
309
308
  }
310
309
  }
@@ -461,7 +460,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
461
460
  continue;
462
461
  if (entry.isDirectory()) {
463
462
  const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
464
- ids.push(...await this.collectSessionIds(path12.join(dir, entry.name), childPrefix, depth + 1));
463
+ ids.push(...await this.collectSessionIds(path13.join(dir, entry.name), childPrefix, depth + 1));
465
464
  } else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
466
465
  if (entry.name === "_index.jsonl") continue;
467
466
  const base = entry.name.replace(/\.jsonl$/, "");
@@ -493,15 +492,15 @@ var DefaultSessionStore = class _DefaultSessionStore {
493
492
  * sidecars, and the session directory (fleet.json, shared/, subagents/).
494
493
  */
495
494
  async deleteSession(id) {
496
- await fsp.unlink(this.sessionPath(id, ".jsonl")).catch(() => void 0);
497
- await fsp.unlink(this.sessionPath(id, ".summary.json")).catch(() => void 0);
498
- const shardDir = path12.dirname(path12.join(this.dir, id));
499
- const base = path12.basename(id);
495
+ await fsp.unlink(this.sessionPath(id, ".jsonl")).catch((err) => console.warn(`[session-store] delete .jsonl failed: ${err}`));
496
+ await fsp.unlink(this.sessionPath(id, ".summary.json")).catch((err) => console.warn(`[session-store] delete .summary.json failed: ${err}`));
497
+ const shardDir = path13.dirname(path13.join(this.dir, id));
498
+ const base = path13.basename(id);
500
499
  for (const ext of [".plan.json", ".todos.json"]) {
501
- await fsp.unlink(path12.join(shardDir, `${base}${ext}`)).catch(() => void 0);
500
+ await fsp.unlink(path13.join(shardDir, `${base}${ext}`)).catch((err) => console.warn(`[session-store] delete ${ext} failed: ${err}`));
502
501
  }
503
- const sessDir = path12.join(shardDir, base);
504
- await fsp.rm(sessDir, { recursive: true, force: true }).catch(() => void 0);
502
+ const sessDir = path13.join(shardDir, base);
503
+ await fsp.rm(sessDir, { recursive: true, force: true }).catch((err) => console.warn(`[session-store] delete session dir failed: ${err}`));
505
504
  await this.writeTombstone(id);
506
505
  }
507
506
  async delete(id) {
@@ -512,7 +511,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
512
511
  let deleted = 0;
513
512
  let activeSessionId = null;
514
513
  try {
515
- const raw = await fsp.readFile(path12.join(this.dir, "active.json"), "utf8");
514
+ const raw = await fsp.readFile(path13.join(this.dir, "active.json"), "utf8");
516
515
  const active = JSON.parse(raw);
517
516
  activeSessionId = active.sessionId ?? null;
518
517
  } catch {
@@ -520,11 +519,11 @@ var DefaultSessionStore = class _DefaultSessionStore {
520
519
  const entries = await fsp.readdir(this.dir, { withFileTypes: true }).catch(() => []);
521
520
  for (const entry of entries) {
522
521
  if (!entry.isDirectory()) continue;
523
- const dateDir = path12.join(this.dir, entry.name);
522
+ const dateDir = path13.join(this.dir, entry.name);
524
523
  const files = await fsp.readdir(dateDir, { withFileTypes: true }).catch(() => []);
525
524
  for (const file of files) {
526
525
  if (!file.isFile() || !file.name.endsWith(".jsonl")) continue;
527
- const jsonlPath = path12.join(dateDir, file.name);
526
+ const jsonlPath = path13.join(dateDir, file.name);
528
527
  try {
529
528
  const stat5 = await fsp.stat(jsonlPath);
530
529
  if (stat5.mtimeMs >= cutoff) continue;
@@ -542,7 +541,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
542
541
  }
543
542
  for (const entry of entries) {
544
543
  if (!entry.isDirectory()) continue;
545
- const dateDir = path12.join(this.dir, entry.name);
544
+ const dateDir = path13.join(this.dir, entry.name);
546
545
  try {
547
546
  const remaining = await fsp.readdir(dateDir);
548
547
  if (remaining.length === 0) {
@@ -707,7 +706,7 @@ var FileSessionWriter = class {
707
706
  this.meta = meta;
708
707
  this.events = events;
709
708
  this.resumed = opts.resumed ?? false;
710
- this.manifestFile = opts.dir ? path12.join(opts.dir, `${path12.basename(id)}.summary.json`) : "";
709
+ this.manifestFile = opts.dir ? path13.join(opts.dir, `${path13.basename(id)}.summary.json`) : "";
711
710
  this.filePath = opts.filePath ?? "";
712
711
  this.secretScrubber = opts.secretScrubber;
713
712
  this.onCloseCb = opts.onClose;
@@ -1027,7 +1026,7 @@ function userInputTitle(content) {
1027
1026
  var QueueStore = class {
1028
1027
  file;
1029
1028
  constructor(opts) {
1030
- this.file = path12.join(opts.dir, "queue.json");
1029
+ this.file = path13.join(opts.dir, "queue.json");
1031
1030
  }
1032
1031
  async write(items) {
1033
1032
  if (items.length === 0) {
@@ -1094,7 +1093,7 @@ var DefaultAttachmentStore = class {
1094
1093
  let data = input.data;
1095
1094
  if (this.spoolDir && bytes >= this.spoolThreshold) {
1096
1095
  await fsp.mkdir(this.spoolDir, { recursive: true });
1097
- spooledPath = path12.join(this.spoolDir, `${id}.bin`);
1096
+ spooledPath = path13.join(this.spoolDir, `${id}.bin`);
1098
1097
  await atomicWrite(spooledPath, input.data, {
1099
1098
  encoding: input.kind === "image" ? "base64" : "utf8"
1100
1099
  });
@@ -1305,7 +1304,7 @@ var FileMemoryBackend = class {
1305
1304
  }
1306
1305
  async remember(scope, entry, filePath) {
1307
1306
  const file = this.resolveFile(filePath, scope);
1308
- await ensureDir(path12.dirname(file));
1307
+ await ensureDir(path13.dirname(file));
1309
1308
  let existing = "";
1310
1309
  try {
1311
1310
  existing = await fsp.readFile(file, "utf8");
@@ -1322,39 +1321,41 @@ ${line}`;
1322
1321
  }
1323
1322
  async forget(scope, query, filePath) {
1324
1323
  const file = this.resolveFile(filePath, scope);
1325
- let existing;
1326
- try {
1327
- existing = await fsp.readFile(file, "utf8");
1328
- } catch {
1329
- return 0;
1330
- }
1331
- const needle = query.toLowerCase();
1332
- const idMatcher = /mem_\d+_\w+/;
1333
- let removed = 0;
1334
- const lines = existing.split("\n").filter((line) => {
1335
- const trimmed = line.trim();
1336
- if (!trimmed.startsWith("- ")) return true;
1337
- if (idMatcher.test(query)) {
1338
- const entryIdMatch = /mem_\d+_\w+/.exec(trimmed);
1339
- if (entryIdMatch && entryIdMatch[0] === query) {
1324
+ return withFileLock(file, async () => {
1325
+ let existing;
1326
+ try {
1327
+ existing = await fsp.readFile(file, "utf8");
1328
+ } catch {
1329
+ return 0;
1330
+ }
1331
+ const needle = query.toLowerCase();
1332
+ const idMatcher = /mem_\d+_\w+/;
1333
+ let removed = 0;
1334
+ const lines = existing.split("\n").filter((line) => {
1335
+ const trimmed = line.trim();
1336
+ if (!trimmed.startsWith("- ")) return true;
1337
+ if (idMatcher.test(query)) {
1338
+ const entryIdMatch = /mem_\d+_\w+/.exec(trimmed);
1339
+ if (entryIdMatch && entryIdMatch[0] === query) {
1340
+ removed++;
1341
+ return false;
1342
+ }
1343
+ }
1344
+ if (trimmed.toLowerCase().includes(needle)) {
1340
1345
  removed++;
1341
1346
  return false;
1342
1347
  }
1348
+ return true;
1349
+ });
1350
+ if (removed > 0) {
1351
+ if (lines.length === 0 || lines.length === 1 && !lines[0]?.trim()) {
1352
+ await atomicWrite(file, "");
1353
+ } else {
1354
+ await atomicWrite(file, lines.join("\n"));
1355
+ }
1343
1356
  }
1344
- if (trimmed.toLowerCase().includes(needle)) {
1345
- removed++;
1346
- return false;
1347
- }
1348
- return true;
1357
+ return removed;
1349
1358
  });
1350
- if (removed > 0) {
1351
- if (lines.length === 0 || lines.length === 1 && !lines[0]?.trim()) {
1352
- await atomicWrite(file, "");
1353
- } else {
1354
- await atomicWrite(file, lines.join("\n"));
1355
- }
1356
- }
1357
- return removed;
1358
1359
  }
1359
1360
  async readAll(scope, filePath) {
1360
1361
  const file = this.resolveFile(filePath, scope);
@@ -1715,8 +1716,8 @@ ${body.trim()}`);
1715
1716
  if (!this.persistBackup || scope === "project-agents") return;
1716
1717
  try {
1717
1718
  const content = await this.backend.readAll(scope, this.files[scope]);
1718
- const { writeFile: writeFile6, mkdir: mkdir5 } = await import('fs/promises');
1719
- await mkdir5(this.backupDir, { recursive: true });
1719
+ const { writeFile: writeFile6, mkdir: mkdir6 } = await import('fs/promises');
1720
+ await mkdir6(this.backupDir, { recursive: true });
1720
1721
  await writeFile6(`${this.backupDir}/${scope}.md`, content, "utf8");
1721
1722
  } catch {
1722
1723
  }
@@ -2067,7 +2068,7 @@ var SessionMemoryConsolidator = class {
2067
2068
  for (const op of parsed.operations) {
2068
2069
  switch (op.action) {
2069
2070
  case "add": {
2070
- if (op.text && op.text.trim()) {
2071
+ if (op.text?.trim()) {
2071
2072
  await this.memoryStore.remember(op.text.trim(), void 0, {
2072
2073
  type: op.type,
2073
2074
  tags: op.tags,
@@ -2172,16 +2173,14 @@ function deepFreeze(obj) {
2172
2173
  }
2173
2174
  return Object.freeze(obj);
2174
2175
  }
2175
-
2176
- // src/security/config-secrets.ts
2177
- function decryptConfigSecrets(cfg, vault) {
2176
+ function decryptConfigSecrets(cfg, vault, opts) {
2177
+ const warn = ((msg) => console.warn(msg));
2178
2178
  return walk(cfg, vault, (v, key) => {
2179
2179
  try {
2180
2180
  return vault.decrypt(v);
2181
2181
  } catch (err) {
2182
- console.warn(
2183
- `[secret-vault] Failed to decrypt "${key}":`,
2184
- err instanceof Error ? err.message : err
2182
+ warn(
2183
+ `[secret-vault] Failed to decrypt "${key}": ${err instanceof Error ? err.message : err}`
2185
2184
  );
2186
2185
  return "";
2187
2186
  }
@@ -2439,12 +2438,14 @@ var DefaultConfigLoader = class {
2439
2438
  }
2440
2439
  async load(opts = {}) {
2441
2440
  let cfg = { ...BEHAVIOR_DEFAULTS };
2442
- const [global, local] = await Promise.all([
2441
+ const [global, local, inProject] = await Promise.all([
2443
2442
  this.readJson(this.paths.globalConfig),
2444
- this.readJson(this.paths.projectLocalConfig)
2443
+ this.readJson(this.paths.projectLocalConfig),
2444
+ this.readJson(this.paths.inProjectConfig)
2445
2445
  ]);
2446
2446
  cfg = deepMerge(cfg, global);
2447
2447
  cfg = deepMerge(cfg, local);
2448
+ cfg = deepMerge(cfg, inProject);
2448
2449
  for (const [key, fn] of Object.entries(ENV_MAP)) {
2449
2450
  const v = process.env[key];
2450
2451
  if (v) fn(cfg, v);
@@ -2643,7 +2644,7 @@ var RecoveryLock = class {
2643
2644
  sessionStore;
2644
2645
  probe;
2645
2646
  constructor(opts) {
2646
- this.file = path12.join(opts.dir, LOCK_FILE);
2647
+ this.file = path13.join(opts.dir, LOCK_FILE);
2647
2648
  this.pid = opts.pid ?? process.pid;
2648
2649
  this.hostname = opts.hostname ?? os.hostname();
2649
2650
  this.maxAgeMs = opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
@@ -2701,7 +2702,7 @@ var RecoveryLock = class {
2701
2702
  * null return before calling this.
2702
2703
  */
2703
2704
  async write(sessionId) {
2704
- await ensureDir(path12.dirname(this.file));
2705
+ await ensureDir(path13.dirname(this.file));
2705
2706
  const lock = {
2706
2707
  v: 1,
2707
2708
  sessionId,
@@ -3188,7 +3189,7 @@ var AnnotationsStore = class {
3188
3189
  if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
3189
3190
  throw new Error(`Invalid sessionId: ${sessionId}`);
3190
3191
  }
3191
- return path12.join(this.dir, `${sessionId}.annotations.json`);
3192
+ return path13.join(this.dir, `${sessionId}.annotations.json`);
3192
3193
  }
3193
3194
  async readFile(sessionId) {
3194
3195
  const fp = this.filePath(sessionId);
@@ -3345,7 +3346,7 @@ var ReplayLogStore = class {
3345
3346
  out.push({
3346
3347
  sessionId,
3347
3348
  entryCount: all.length,
3348
- path: path12.join(this.dir, name)
3349
+ path: path13.join(this.dir, name)
3349
3350
  });
3350
3351
  }
3351
3352
  return out.sort((a, b) => a.sessionId.localeCompare(b.sessionId));
@@ -3355,7 +3356,7 @@ var ReplayLogStore = class {
3355
3356
  if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
3356
3357
  throw new Error(`Invalid sessionId: ${sessionId}`);
3357
3358
  }
3358
- return path12.join(this.dir, `${sessionId}.replay.jsonl`);
3359
+ return path13.join(this.dir, `${sessionId}.replay.jsonl`);
3359
3360
  }
3360
3361
  async readAll(sessionId) {
3361
3362
  const fp = this.filePath(sessionId);
@@ -3544,7 +3545,7 @@ var SessionRecovery = class {
3544
3545
  if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
3545
3546
  throw new Error(`Invalid sessionId: ${sessionId}`);
3546
3547
  }
3547
- return path12.join(this.dir, `${sessionId}.jsonl`);
3548
+ return path13.join(this.dir, `${sessionId}.jsonl`);
3548
3549
  }
3549
3550
  };
3550
3551
  var GENESIS_PREV = "0".repeat(64);
@@ -3667,7 +3668,7 @@ var ToolAuditLog = class {
3667
3668
  if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
3668
3669
  throw new Error(`Invalid sessionId: ${sessionId}`);
3669
3670
  }
3670
- return path12.join(this.dir, `${sessionId}.audit.jsonl`);
3671
+ return path13.join(this.dir, `${sessionId}.audit.jsonl`);
3671
3672
  }
3672
3673
  async readAll(sessionId) {
3673
3674
  const fp = this.filePath(sessionId);
@@ -3852,7 +3853,7 @@ var DefaultSessionRewinder = class {
3852
3853
  sessionsDir;
3853
3854
  projectRoot;
3854
3855
  async listCheckpoints(sessionId) {
3855
- const file = path12.join(this.sessionsDir, `${sessionId}.jsonl`);
3856
+ const file = path13.join(this.sessionsDir, `${sessionId}.jsonl`);
3856
3857
  const raw = await fsp.readFile(file, "utf8");
3857
3858
  const events = parseEvents(raw);
3858
3859
  const fileCountMap = /* @__PURE__ */ new Map();
@@ -3877,7 +3878,7 @@ var DefaultSessionRewinder = class {
3877
3878
  return checkpoints;
3878
3879
  }
3879
3880
  async rewindToCheckpoint(sessionId, checkpointIndex) {
3880
- const file = path12.join(this.sessionsDir, `${sessionId}.jsonl`);
3881
+ const file = path13.join(this.sessionsDir, `${sessionId}.jsonl`);
3881
3882
  const raw = await fsp.readFile(file, "utf8");
3882
3883
  const events = parseEvents(raw);
3883
3884
  let targetIdx = -1;
@@ -3912,7 +3913,7 @@ var DefaultSessionRewinder = class {
3912
3913
  return { ...result, toPromptIndex: checkpointIndex, removedEvents };
3913
3914
  }
3914
3915
  async rewindLastN(sessionId, n) {
3915
- const file = path12.join(this.sessionsDir, `${sessionId}.jsonl`);
3916
+ const file = path13.join(this.sessionsDir, `${sessionId}.jsonl`);
3916
3917
  const raw = await fsp.readFile(file, "utf8");
3917
3918
  const events = parseEvents(raw);
3918
3919
  const checkpoints = [];
@@ -3941,7 +3942,7 @@ var DefaultSessionRewinder = class {
3941
3942
  return { ...result, toPromptIndex: targetIndex, removedEvents: snapshotsToRevert.length };
3942
3943
  }
3943
3944
  async rewindToStart(sessionId) {
3944
- const file = path12.join(this.sessionsDir, `${sessionId}.jsonl`);
3945
+ const file = path13.join(this.sessionsDir, `${sessionId}.jsonl`);
3945
3946
  const raw = await fsp.readFile(file, "utf8");
3946
3947
  const events = parseEvents(raw);
3947
3948
  const allSnapshots = [];
@@ -3977,10 +3978,10 @@ async function revertSnapshots(snapshots, projectRoot) {
3977
3978
  for (const snapshot of snapshots) {
3978
3979
  for (const file of snapshot.files) {
3979
3980
  try {
3980
- const absPath = path12.resolve(file.path);
3981
- const root = path12.resolve(projectRoot);
3982
- const rel = path12.relative(root, absPath);
3983
- if (rel.startsWith("..") || path12.isAbsolute(rel)) {
3981
+ const absPath = path13.resolve(file.path);
3982
+ const root = path13.resolve(projectRoot);
3983
+ const rel = path13.relative(root, absPath);
3984
+ if (rel.startsWith("..") || path13.isAbsolute(rel)) {
3984
3985
  errors.push(`${file.path}: path resolves outside project root \u2014 skipping`);
3985
3986
  continue;
3986
3987
  }
@@ -4561,11 +4562,11 @@ var color = {
4561
4562
  bgGreen: wrap("42", "49")
4562
4563
  };
4563
4564
  function projectHash(absRoot) {
4564
- return createHash("sha256").update(path12.resolve(absRoot)).digest("hex").slice(0, 12);
4565
+ return createHash("sha256").update(path13.resolve(absRoot)).digest("hex").slice(0, 12);
4565
4566
  }
4566
4567
  function projectSlug(absRoot) {
4567
- const base = slugify(path12.basename(absRoot));
4568
- const hash = createHash("sha256").update(path12.resolve(absRoot)).digest("hex").slice(0, 6);
4568
+ const base = slugify(path13.basename(absRoot));
4569
+ const hash = createHash("sha256").update(path13.resolve(absRoot)).digest("hex").slice(0, 6);
4569
4570
  return `${base}-${hash}`;
4570
4571
  }
4571
4572
  function slugify(name) {
@@ -4573,42 +4574,43 @@ function slugify(name) {
4573
4574
  }
4574
4575
  function resolveWstackPaths(opts) {
4575
4576
  const home = opts.userHome ?? os.homedir();
4576
- const globalRoot = opts.globalRoot ?? path12.join(home, ".wrongstack");
4577
+ const globalRoot = opts.globalRoot ?? path13.join(home, ".wrongstack");
4577
4578
  const hash = projectHash(opts.projectRoot);
4578
4579
  const slug = projectSlug(opts.projectRoot);
4579
- const projectDir = path12.join(globalRoot, "projects", slug);
4580
+ const projectDir = path13.join(globalRoot, "projects", slug);
4580
4581
  return {
4581
4582
  globalRoot,
4582
4583
  configDir: globalRoot,
4583
- globalConfig: path12.join(globalRoot, "config.json"),
4584
- secretsKey: path12.join(globalRoot, ".key"),
4585
- globalMemory: path12.join(globalRoot, "memory.md"),
4586
- globalSkills: path12.join(globalRoot, "skills"),
4587
- globalPrompts: path12.join(globalRoot, "prompts"),
4588
- cacheDir: path12.join(globalRoot, "cache"),
4589
- modelsCache: path12.join(globalRoot, "cache", "models.dev.json"),
4590
- modelsOverlayCache: path12.join(globalRoot, "cache", "models-overlay.json"),
4591
- historyFile: path12.join(globalRoot, "history"),
4592
- logFile: path12.join(globalRoot, "logs", "wrongstack.log"),
4584
+ globalConfig: path13.join(globalRoot, "config.json"),
4585
+ secretsKey: path13.join(globalRoot, ".key"),
4586
+ globalMemory: path13.join(globalRoot, "memory.md"),
4587
+ globalSkills: path13.join(globalRoot, "skills"),
4588
+ globalPrompts: path13.join(globalRoot, "prompts"),
4589
+ cacheDir: path13.join(globalRoot, "cache"),
4590
+ modelsCache: path13.join(globalRoot, "cache", "models.dev.json"),
4591
+ modelsOverlayCache: path13.join(globalRoot, "cache", "models-overlay.json"),
4592
+ historyFile: path13.join(globalRoot, "history"),
4593
+ logFile: path13.join(globalRoot, "logs", "wrongstack.log"),
4593
4594
  projectDir,
4594
- projectCodebaseIndex: path12.join(projectDir, "codebase-index"),
4595
- projectMemory: path12.join(projectDir, "memory.md"),
4596
- projectSessions: path12.join(projectDir, "sessions"),
4597
- projectTrust: path12.join(projectDir, "trust.json"),
4598
- projectMeta: path12.join(projectDir, "meta.json"),
4599
- projectLocalConfig: path12.join(projectDir, "config.local.json"),
4600
- inProjectAgentsFile: path12.join(opts.projectRoot, ".wrongstack", "AGENTS.md"),
4601
- inProjectSkills: path12.join(opts.projectRoot, ".wrongstack", "skills"),
4602
- inProjectWorktrees: path12.join(opts.projectRoot, ".wrongstack", "worktrees"),
4595
+ projectCodebaseIndex: path13.join(projectDir, "codebase-index"),
4596
+ projectMemory: path13.join(projectDir, "memory.md"),
4597
+ projectSessions: path13.join(projectDir, "sessions"),
4598
+ projectTrust: path13.join(projectDir, "trust.json"),
4599
+ projectMeta: path13.join(projectDir, "meta.json"),
4600
+ projectLocalConfig: path13.join(projectDir, "config.local.json"),
4601
+ inProjectConfig: path13.join(opts.projectRoot, ".wrongstack", "config.json"),
4602
+ inProjectAgentsFile: path13.join(opts.projectRoot, ".wrongstack", "AGENTS.md"),
4603
+ inProjectSkills: path13.join(opts.projectRoot, ".wrongstack", "skills"),
4604
+ inProjectWorktrees: path13.join(opts.projectRoot, ".wrongstack", "worktrees"),
4603
4605
  projectHash: hash,
4604
4606
  projectSlug: slug,
4605
- projectGoal: path12.join(projectDir, "goal.json"),
4606
- projectSpecs: path12.join(projectDir, "specs"),
4607
- projectTaskGraphs: path12.join(projectDir, "task-graphs"),
4608
- projectSddSession: path12.join(projectDir, "sdd-session.json"),
4609
- projectPlan: path12.join(projectDir, "plan.json"),
4610
- projectAutophase: path12.join(projectDir, "autophase"),
4611
- syncConfig: path12.join(globalRoot, "sync.json")
4607
+ projectGoal: path13.join(projectDir, "goal.json"),
4608
+ projectSpecs: path13.join(projectDir, "specs"),
4609
+ projectTaskGraphs: path13.join(projectDir, "task-graphs"),
4610
+ projectSddSession: path13.join(projectDir, "sdd-session.json"),
4611
+ projectPlan: path13.join(projectDir, "plan.json"),
4612
+ projectAutophase: path13.join(projectDir, "autophase"),
4613
+ syncConfig: path13.join(globalRoot, "sync.json")
4612
4614
  };
4613
4615
  }
4614
4616
 
@@ -4671,16 +4673,20 @@ async function loadGoal(filePath) {
4671
4673
  let raw;
4672
4674
  try {
4673
4675
  raw = await fsp.readFile(filePath, "utf8");
4674
- } catch {
4675
- return null;
4676
+ } catch (err) {
4677
+ const code = err.code;
4678
+ if (code === "ENOENT") return null;
4679
+ throw err;
4676
4680
  }
4677
4681
  try {
4678
4682
  const parsed = JSON.parse(raw);
4679
4683
  if (parsed?.version !== 1 || typeof parsed.goal !== "string" || !Array.isArray(parsed.journal)) {
4684
+ console.warn(`[goal-store] Corrupt goal.json at ${filePath} \u2014 invalid schema. Consider deleting it and re-creating.`);
4680
4685
  return null;
4681
4686
  }
4682
4687
  return parsed;
4683
4688
  } catch {
4689
+ console.warn(`[goal-store] Corrupt goal.json at ${filePath} \u2014 JSON parse failed. Consider deleting it and re-creating.`);
4684
4690
  return null;
4685
4691
  }
4686
4692
  }
@@ -4807,9 +4813,9 @@ function parseProgressFromText(text) {
4807
4813
  const re = /\[progress:\s*(\d{1,3})%\]\s*(?:[—\-]\s*(.+))?/i;
4808
4814
  const m = text.match(re);
4809
4815
  if (!m) return null;
4810
- const progress = Math.min(100, Math.max(0, Number.parseInt(m[1], 10)));
4816
+ const progress = Math.min(100, Math.max(0, Number.parseInt(m[1] ?? "0", 10)));
4811
4817
  const note = m[2]?.trim() || void 0;
4812
- return { progress, note };
4818
+ return note === void 0 ? { progress } : { progress, note };
4813
4819
  }
4814
4820
  function recordProgress(goal, progress, note) {
4815
4821
  const clamped = Math.min(100, Math.max(0, progress));
@@ -4829,7 +4835,7 @@ function computeTrend(history) {
4829
4835
  const recent = history.slice(-5);
4830
4836
  const deltas = [];
4831
4837
  for (let i = 1; i < recent.length; i++) {
4832
- deltas.push(recent[i].progress - recent[i - 1].progress);
4838
+ deltas.push((recent[i]?.progress ?? 0) - (recent[i - 1]?.progress ?? 0));
4833
4839
  }
4834
4840
  if (deltas.length < 2) return void 0;
4835
4841
  const avgDelta = deltas.reduce((a, b) => a + b, 0) / deltas.length;
@@ -4851,7 +4857,7 @@ var DefaultPromptStore = class {
4851
4857
  if (!file.endsWith(".json")) continue;
4852
4858
  try {
4853
4859
  const raw = JSON.parse(
4854
- await fsp.readFile(path12.join(this.dir, file), "utf8")
4860
+ await fsp.readFile(path13.join(this.dir, file), "utf8")
4855
4861
  );
4856
4862
  entries.push(raw.entry);
4857
4863
  } catch {
@@ -4864,7 +4870,7 @@ var DefaultPromptStore = class {
4864
4870
  );
4865
4871
  }
4866
4872
  async get(id) {
4867
- const file = path12.join(this.dir, `${id}.json`);
4873
+ const file = path13.join(this.dir, `${id}.json`);
4868
4874
  try {
4869
4875
  const raw = JSON.parse(await fsp.readFile(file, "utf8"));
4870
4876
  return raw.entry;
@@ -4874,12 +4880,12 @@ var DefaultPromptStore = class {
4874
4880
  }
4875
4881
  async save(entry) {
4876
4882
  await ensureDir(this.dir);
4877
- const file = path12.join(this.dir, `${entry.id}.json`);
4883
+ const file = path13.join(this.dir, `${entry.id}.json`);
4878
4884
  const raw = { version: 1, entry };
4879
4885
  await atomicWrite(file, JSON.stringify(raw, null, 2));
4880
4886
  }
4881
4887
  async delete(id) {
4882
- const file = path12.join(this.dir, `${id}.json`);
4888
+ const file = path13.join(this.dir, `${id}.json`);
4883
4889
  try {
4884
4890
  await fsp.unlink(file);
4885
4891
  return true;
@@ -4913,7 +4919,7 @@ var CloudSync = class {
4913
4919
  this.paths = paths;
4914
4920
  this.getConfig = getConfig;
4915
4921
  this.setConfig = setConfig;
4916
- this.statePath = path12.join(paths.globalRoot, "sync-state.json");
4922
+ this.statePath = path13.join(paths.globalRoot, "sync-state.json");
4917
4923
  }
4918
4924
  paths;
4919
4925
  getConfig;
@@ -5020,7 +5026,7 @@ var CloudSync = class {
5020
5026
  const rel = segments.slice(2).join("/");
5021
5027
  const destPath = resolvePulledCategoryPath(cat, localPath, rel, entry.path);
5022
5028
  const blobData = await this.getBlob(token, owner, repoName, entry.sha);
5023
- await fsp.mkdir(path12.dirname(destPath), { recursive: true });
5029
+ await fsp.mkdir(path13.dirname(destPath), { recursive: true });
5024
5030
  await fsp.writeFile(destPath, Buffer.from(blobData, "base64"));
5025
5031
  }
5026
5032
  const localRev = await this.hashLocalCategories(cfg.categories);
@@ -5127,7 +5133,7 @@ var CloudSync = class {
5127
5133
  const files = await this.walkDir(localPath, localPath);
5128
5134
  for (const file of files) {
5129
5135
  const content = await fsp.readFile(file, "utf8");
5130
- const rel = path12.relative(localPath, file).replace(/\\/g, "/");
5136
+ const rel = path13.relative(localPath, file).replace(/\\/g, "/");
5131
5137
  entries.push({ path: `data/${cat}/${rel}`, content, mode: "100644" });
5132
5138
  hashes.push(content);
5133
5139
  }
@@ -5184,7 +5190,7 @@ var CloudSync = class {
5184
5190
  const results = [];
5185
5191
  const entries = await fsp.readdir(dir, { withFileTypes: true });
5186
5192
  for (const entry of entries) {
5187
- const full = path12.join(dir, entry.name);
5193
+ const full = path13.join(dir, entry.name);
5188
5194
  if (entry.isDirectory()) {
5189
5195
  results.push(...await this.walkDir(full, base));
5190
5196
  } else {
@@ -5201,15 +5207,15 @@ function resolvePulledCategoryPath(cat, localPath, rel, remotePath) {
5201
5207
  return localPath;
5202
5208
  }
5203
5209
  if (!rel) return localPath;
5204
- const normalizedRel = path12.normalize(rel);
5205
- const traversesUp = normalizedRel === ".." || normalizedRel.startsWith(`..${path12.sep}`);
5206
- if (path12.isAbsolute(normalizedRel) || traversesUp) {
5210
+ const normalizedRel = path13.normalize(rel);
5211
+ const traversesUp = normalizedRel === ".." || normalizedRel.startsWith(`..${path13.sep}`);
5212
+ if (path13.isAbsolute(normalizedRel) || traversesUp) {
5207
5213
  throw new Error(`Refusing CloudSync path traversal: ${remotePath}`);
5208
5214
  }
5209
- const dest = path12.resolve(localPath, normalizedRel);
5210
- const root = path12.resolve(localPath);
5211
- const relative3 = path12.relative(root, dest);
5212
- if (relative3.startsWith("..") || path12.isAbsolute(relative3)) {
5215
+ const dest = path13.resolve(localPath, normalizedRel);
5216
+ const root = path13.resolve(localPath);
5217
+ const relative3 = path13.relative(root, dest);
5218
+ if (relative3.startsWith("..") || path13.isAbsolute(relative3)) {
5213
5219
  throw new Error(`Refusing CloudSync path outside category root: ${remotePath}`);
5214
5220
  }
5215
5221
  return dest;