@wrongstack/core 0.257.0 → 0.260.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 (65) hide show
  1. package/dist/{agent-bridge-BrxWHEOm.d.ts → agent-bridge-BbskZ7HH.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-US741uBH.d.ts → agent-subagent-runner-BNIGZx18.d.ts} +28 -8
  3. package/dist/{brain-TjEEwSpw.d.ts → brain-C2yDd7Lw.d.ts} +58 -1
  4. package/dist/{compactor-C5sT4U7I.d.ts → compactor-t0R_AIt_.d.ts} +1 -1
  5. package/dist/{config-DuAu23zm.d.ts → config-FG6As4H5.d.ts} +1 -1
  6. package/dist/{context-CGdgA0q6.d.ts → context-JFOVvu6z.d.ts} +22 -0
  7. package/dist/coordination/index.d.ts +14 -14
  8. package/dist/coordination/index.js +195 -33
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/defaults/index.d.ts +25 -25
  11. package/dist/defaults/index.js +908 -92
  12. package/dist/defaults/index.js.map +1 -1
  13. package/dist/execution/index.d.ts +15 -15
  14. package/dist/execution/index.js +134 -35
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/execution/prompt-enhancer.d.ts +1 -1
  17. package/dist/extension/index.d.ts +6 -6
  18. package/dist/{goal-preamble-UiEkbNmW.d.ts → goal-preamble-B1IXJtLX.d.ts} +11 -9
  19. package/dist/{goal-store-CV9Yz2X_.d.ts → goal-store-CPXz6Mml.d.ts} +4 -2
  20. package/dist/{index-CitPrI3a.d.ts → index-BPcg4N3M.d.ts} +5 -5
  21. package/dist/{index-CC0Mcm05.d.ts → index-CebbJB94.d.ts} +8 -8
  22. package/dist/index.d.ts +47 -43
  23. package/dist/index.js +1571 -284
  24. package/dist/index.js.map +1 -1
  25. package/dist/infrastructure/index.d.ts +6 -6
  26. package/dist/kernel/index.d.ts +9 -9
  27. package/dist/kernel/index.js.map +1 -1
  28. package/dist/{llm-selector-CJ4SyAFE.d.ts → llm-selector-DXxI2tlu.d.ts} +2 -2
  29. package/dist/{mcp-servers-D8YnLaEp.d.ts → mcp-servers-OwNHo43-.d.ts} +3 -3
  30. package/dist/models/index.d.ts +5 -5
  31. package/dist/{models-registry-ByZCdFuQ.d.ts → models-registry-Djlmq4uB.d.ts} +1 -1
  32. package/dist/{multi-agent-coordinator-DqTUEAeC.d.ts → multi-agent-coordinator-CEmrSCMJ.d.ts} +1 -1
  33. package/dist/{null-fleet-bus-B5mfTJXT.d.ts → null-fleet-bus-DT92xqgJ.d.ts} +13 -8
  34. package/dist/observability/index.d.ts +2 -2
  35. package/dist/{package-outdated-watcher-BSgR_kK-.d.ts → package-outdated-watcher-C70ag2G9.d.ts} +3 -3
  36. package/dist/{parallel-eternal-engine-C0juOszP.d.ts → parallel-eternal-engine-0SItuq5r.d.ts} +13 -9
  37. package/dist/{path-resolver-CbkT-RMU.d.ts → path-resolver-DKBh6Jlo.d.ts} +3 -3
  38. package/dist/{permission-CwBBpCoF.d.ts → permission-BJ7eO9Vl.d.ts} +1 -1
  39. package/dist/{permission-policy-B8rSu908.d.ts → permission-policy-DEXOfnpm.d.ts} +3 -2
  40. package/dist/{pipeline-JG8XoudC.d.ts → pipeline-zflkI2dp.d.ts} +2 -2
  41. package/dist/{plan-templates-DPiQMkBz.d.ts → plan-templates-BFXyRkEK.d.ts} +32 -11
  42. package/dist/{provider-runner-hM7EXlLI.d.ts → provider-runner-BC-uywtT.d.ts} +3 -3
  43. package/dist/{retry-policy-Tg7LXkoK.d.ts → retry-policy-Cavrzmtk.d.ts} +1 -1
  44. package/dist/sdd/index.d.ts +8 -8
  45. package/dist/sdd/index.js +20 -2
  46. package/dist/sdd/index.js.map +1 -1
  47. package/dist/{secret-vault-gxtFZYBt.d.ts → secret-vault-CDvDYXWX.d.ts} +1 -1
  48. package/dist/security/index.d.ts +4 -4
  49. package/dist/security/index.js +30 -1
  50. package/dist/security/index.js.map +1 -1
  51. package/dist/{selector-DWsqVjGf.d.ts → selector-B7AivHsu.d.ts} +1 -1
  52. package/dist/{session-event-bridge-BAFWdgQ3.d.ts → session-event-bridge-BmIDxdJd.d.ts} +1 -1
  53. package/dist/{session-reader-CqRvaL5v.d.ts → session-reader-DtofsB-2.d.ts} +1 -1
  54. package/dist/storage/index.d.ts +30 -21
  55. package/dist/storage/index.js +1264 -216
  56. package/dist/storage/index.js.map +1 -1
  57. package/dist/types/index.d.ts +19 -19
  58. package/dist/types/index.js +8 -0
  59. package/dist/types/index.js.map +1 -1
  60. package/dist/utils/index.d.ts +101 -3
  61. package/dist/utils/index.js +92 -1
  62. package/dist/utils/index.js.map +1 -1
  63. package/package.json +1 -1
  64. package/skills/output-standards/SKILL.md +14 -9
  65. package/skills/output-standards/SKILL.save.md +3 -2
@@ -1,23 +1,23 @@
1
- export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, E as EternalAutonomyEngine, c as EternalAutonomyOptions, d as EternalEngineState, H as HybridCompactor, I as IterationStage, P as ParallelEngineState, e as ParallelEternalEngine, f as ParallelEternalOptions, g as ParallelIterationStage, T as ToolExecutor } from '../parallel-eternal-engine-C0juOszP.js';
2
- export { A as AutoCompactionMiddleware, a as AutonomousRunner, b as AutonomousRunnerOptions, c as AutonomyPromptContributorOptions, C as CompactorStrategy, D as DefaultSkillLoader, d as DoneCheckResult, e as DoneConditionChecker, I as IntelligentCompactor, f as IntelligentCompactorOptions, S as SelectiveCompactor, g as SelectiveCompactorOptions, h as SkillLoaderOptions, i as StrategyCompactorOptions, j as buildGoalPreamble, k as createStrategyCompactor, m as makeAutonomyPromptContributor } from '../goal-preamble-UiEkbNmW.js';
3
- import { P as Provider } from '../context-CGdgA0q6.js';
4
- import { b as BrainDecision, e as BrainDecisionRequest, B as BrainArbiter } from '../brain-TjEEwSpw.js';
5
- import '../retry-policy-Tg7LXkoK.js';
6
- import '../compactor-C5sT4U7I.js';
7
- import '../config-DuAu23zm.js';
8
- import '../index-CitPrI3a.js';
1
+ export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, E as EternalAutonomyEngine, c as EternalAutonomyOptions, d as EternalEngineState, H as HybridCompactor, I as IterationStage, P as ParallelEngineState, e as ParallelEternalEngine, f as ParallelEternalOptions, g as ParallelIterationStage, T as ToolExecutor } from '../parallel-eternal-engine-0SItuq5r.js';
2
+ export { A as AutoCompactionMiddleware, a as AutonomousRunner, b as AutonomousRunnerOptions, c as AutonomyPromptContributorOptions, C as CompactorStrategy, D as DefaultSkillLoader, d as DoneCheckResult, e as DoneConditionChecker, I as IntelligentCompactor, f as IntelligentCompactorOptions, S as SelectiveCompactor, g as SelectiveCompactorOptions, h as SkillLoaderOptions, i as StrategyCompactorOptions, j as buildGoalPreamble, k as createStrategyCompactor, m as makeAutonomyPromptContributor } from '../goal-preamble-B1IXJtLX.js';
3
+ import { P as Provider } from '../context-JFOVvu6z.js';
4
+ import { b as BrainDecision, e as BrainDecisionRequest, B as BrainArbiter } from '../brain-C2yDd7Lw.js';
5
+ import '../retry-policy-Cavrzmtk.js';
6
+ import '../compactor-t0R_AIt_.js';
7
+ import '../config-FG6As4H5.js';
8
+ import '../index-BPcg4N3M.js';
9
9
  import '../logger-B63L5bTg.js';
10
- import '../pipeline-JG8XoudC.js';
10
+ import '../pipeline-zflkI2dp.js';
11
11
  import '../observability-D-HZN_mF.js';
12
- import '../permission-CwBBpCoF.js';
13
- import '../agent-subagent-runner-US741uBH.js';
14
- import '../goal-store-CV9Yz2X_.js';
15
- import '../multi-agent-coordinator-DqTUEAeC.js';
12
+ import '../permission-BJ7eO9Vl.js';
13
+ import '../agent-subagent-runner-BNIGZx18.js';
14
+ import '../goal-store-CPXz6Mml.js';
15
+ import '../multi-agent-coordinator-CEmrSCMJ.js';
16
16
  import 'node:events';
17
17
  import '../skill-DGIXCtdv.js';
18
18
  import '../wstack-paths-CJjEwPXn.js';
19
- import '../selector-DWsqVjGf.js';
20
- import '../session-event-bridge-BAFWdgQ3.js';
19
+ import '../selector-B7AivHsu.js';
20
+ import '../session-event-bridge-BmIDxdJd.js';
21
21
 
22
22
  /**
23
23
  * AutonomyBrain — a self-driving decision layer for autonomous workflows.
@@ -2546,13 +2546,32 @@ var MAX_JOURNAL_ENTRIES = 500;
2546
2546
  function goalFilePath(projectRoot) {
2547
2547
  return resolveWstackPaths({ projectRoot }).projectGoal;
2548
2548
  }
2549
- async function loadGoal(filePath) {
2549
+ async function loadGoal(filePath, events) {
2550
+ const t0 = Date.now();
2550
2551
  let raw;
2551
2552
  try {
2552
2553
  raw = await fs.readFile(filePath, "utf8");
2553
2554
  } catch (err) {
2554
2555
  const code = err.code;
2555
- if (code === "ENOENT") return null;
2556
+ if (code === "ENOENT") {
2557
+ events?.emit("storage.read", {
2558
+ sessionId: "~boot~",
2559
+ store: "goal",
2560
+ filePath,
2561
+ operation: "load",
2562
+ outcome: "success",
2563
+ durationMs: Date.now() - t0
2564
+ });
2565
+ return null;
2566
+ }
2567
+ events?.emit("storage.error", {
2568
+ sessionId: "~boot~",
2569
+ store: "goal",
2570
+ filePath,
2571
+ operation: "load",
2572
+ error: err instanceof Error ? err.message : String(err),
2573
+ recoverable: false
2574
+ });
2556
2575
  throw err;
2557
2576
  }
2558
2577
  try {
@@ -2565,8 +2584,25 @@ async function loadGoal(filePath) {
2565
2584
  message: "invalid schema \u2014 consider deleting and re-creating",
2566
2585
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
2567
2586
  }));
2587
+ events?.emit("storage.read", {
2588
+ sessionId: "~boot~",
2589
+ store: "goal",
2590
+ filePath,
2591
+ operation: "load",
2592
+ outcome: "failure",
2593
+ durationMs: Date.now() - t0,
2594
+ error: "invalid_schema"
2595
+ });
2568
2596
  return null;
2569
2597
  }
2598
+ events?.emit("storage.read", {
2599
+ sessionId: "~boot~",
2600
+ store: "goal",
2601
+ filePath,
2602
+ operation: "load",
2603
+ outcome: "success",
2604
+ durationMs: Date.now() - t0
2605
+ });
2570
2606
  return parsed;
2571
2607
  } catch {
2572
2608
  console.warn(JSON.stringify({
@@ -2576,13 +2612,39 @@ async function loadGoal(filePath) {
2576
2612
  message: "JSON parse failed \u2014 consider deleting and re-creating",
2577
2613
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
2578
2614
  }));
2615
+ events?.emit("storage.read", {
2616
+ sessionId: "~boot~",
2617
+ store: "goal",
2618
+ filePath,
2619
+ operation: "load",
2620
+ outcome: "failure",
2621
+ durationMs: Date.now() - t0,
2622
+ error: "parse_failed"
2623
+ });
2579
2624
  return null;
2580
2625
  }
2581
2626
  }
2582
- async function saveGoal(filePath, goal) {
2627
+ async function saveGoal(filePath, goal, events) {
2628
+ const t0 = Date.now();
2583
2629
  try {
2584
2630
  await atomicWrite(filePath, JSON.stringify(goal, null, 2), { mode: 384 });
2631
+ events?.emit("storage.write", {
2632
+ sessionId: "~boot~",
2633
+ store: "goal",
2634
+ filePath,
2635
+ operation: "save",
2636
+ outcome: "success",
2637
+ durationMs: Date.now() - t0
2638
+ });
2585
2639
  } catch (err) {
2640
+ events?.emit("storage.error", {
2641
+ sessionId: "~boot~",
2642
+ store: "goal",
2643
+ filePath,
2644
+ operation: "save",
2645
+ error: err instanceof Error ? err.message : String(err),
2646
+ recoverable: false
2647
+ });
2586
2648
  throw new FsError({
2587
2649
  message: err instanceof Error ? err.message : String(err),
2588
2650
  code: ERROR_CODES.FS_ATOMIC_WRITE_FAILED,
@@ -2938,7 +3000,7 @@ var EternalAutonomyEngine = class {
2938
3000
  const emit = (stage) => {
2939
3001
  this.opts.onStage?.(stage);
2940
3002
  };
2941
- const goal = await loadGoal(this.goalPath);
3003
+ const goal = await loadGoal(this.goalPath, this.opts.events);
2942
3004
  if (!goal) {
2943
3005
  emit({ phase: "stopped" });
2944
3006
  this.stopRequested = true;
@@ -3042,7 +3104,7 @@ var EternalAutonomyEngine = class {
3042
3104
  emit({ phase: "reflect", status, note });
3043
3105
  let iterationIndex = 0;
3044
3106
  try {
3045
- const reloaded = await loadGoal(this.goalPath);
3107
+ const reloaded = await loadGoal(this.goalPath, this.opts.events);
3046
3108
  iterationIndex = reloaded?.iterations ?? 0;
3047
3109
  } catch {
3048
3110
  }
@@ -3362,12 +3424,12 @@ ${recentJournal}` : "No prior iterations.",
3362
3424
  }
3363
3425
  }
3364
3426
  async appendIterationEntry(entry) {
3365
- const current = await loadGoal(this.goalPath);
3427
+ const current = await loadGoal(this.goalPath, this.opts.events);
3366
3428
  if (!current) {
3367
3429
  return;
3368
3430
  }
3369
3431
  const updated = appendJournal(current, entry);
3370
- await saveGoal(this.goalPath, updated);
3432
+ await saveGoal(this.goalPath, updated, this.opts.events);
3371
3433
  }
3372
3434
  /**
3373
3435
  * Persistent per-todo failure counter. Skipped silently when the goal
@@ -3376,11 +3438,11 @@ ${recentJournal}` : "No prior iterations.",
3376
3438
  * the counter to rotate past stuck todos once they cross `todoMaxAttempts`.
3377
3439
  */
3378
3440
  async bumpTodoAttempt(todoId) {
3379
- const current = await loadGoal(this.goalPath);
3441
+ const current = await loadGoal(this.goalPath, this.opts.events);
3380
3442
  if (!current) return;
3381
3443
  const attempts = { ...current.todoAttempts ?? {} };
3382
3444
  attempts[todoId] = (attempts[todoId] ?? 0) + 1;
3383
- await saveGoal(this.goalPath, { ...current, todoAttempts: attempts });
3445
+ await saveGoal(this.goalPath, { ...current, todoAttempts: attempts }, this.opts.events);
3384
3446
  }
3385
3447
  /**
3386
3448
  * Flip the mission to `completed` and journal it. Called from two
@@ -3390,7 +3452,7 @@ ${recentJournal}` : "No prior iterations.",
3390
3452
  * goal is already `completed`.
3391
3453
  */
3392
3454
  async markGoalCompleted(action, note) {
3393
- const current = await loadGoal(this.goalPath);
3455
+ const current = await loadGoal(this.goalPath, this.opts.events);
3394
3456
  if (!current) return;
3395
3457
  if (current.goalState === "completed") return;
3396
3458
  const withFlag = { ...current, goalState: "completed" };
@@ -3400,7 +3462,7 @@ ${recentJournal}` : "No prior iterations.",
3400
3462
  status: "success",
3401
3463
  note: note.slice(0, 240)
3402
3464
  });
3403
- await saveGoal(this.goalPath, withEntry);
3465
+ await saveGoal(this.goalPath, withEntry, this.opts.events);
3404
3466
  this.opts.onEternalStop?.();
3405
3467
  }
3406
3468
  /**
@@ -3409,10 +3471,10 @@ ${recentJournal}` : "No prior iterations.",
3409
3471
  * `onEternalStop` so the REPL returns to normal mode.
3410
3472
  */
3411
3473
  async clearGoalManually(note) {
3412
- const current = await loadGoal(this.goalPath);
3474
+ const current = await loadGoal(this.goalPath, this.opts.events);
3413
3475
  if (current) {
3414
3476
  const abandoned = { ...current, goalState: "abandoned" };
3415
- await saveGoal(this.goalPath, abandoned);
3477
+ await saveGoal(this.goalPath, abandoned, this.opts.events);
3416
3478
  }
3417
3479
  try {
3418
3480
  const { unlink: unlink3 } = await import('fs/promises');
@@ -3488,16 +3550,16 @@ ${recentJournal}` : ""
3488
3550
  * Persist a progress update from the agent's [PROGRESS: N%] output.
3489
3551
  */
3490
3552
  async updateProgress(progress, note) {
3491
- const current = await loadGoal(this.goalPath);
3553
+ const current = await loadGoal(this.goalPath, this.opts.events);
3492
3554
  if (!current) return;
3493
3555
  const updated = recordProgress(current, progress, note);
3494
- await saveGoal(this.goalPath, updated);
3556
+ await saveGoal(this.goalPath, updated, this.opts.events);
3495
3557
  }
3496
3558
  async persistEngineState(state) {
3497
- const current = await loadGoal(this.goalPath);
3559
+ const current = await loadGoal(this.goalPath, this.opts.events);
3498
3560
  if (!current) return;
3499
3561
  if (current.engineState === state) return;
3500
- await saveGoal(this.goalPath, { ...current, engineState: state });
3562
+ await saveGoal(this.goalPath, { ...current, engineState: state }, this.opts.events);
3501
3563
  }
3502
3564
  };
3503
3565
 
@@ -3846,6 +3908,20 @@ var SubagentBudget = class _SubagentBudget {
3846
3908
  };
3847
3909
 
3848
3910
  // src/coordination/agent-subagent-runner.ts
3911
+ function withDisabledToolFiltering(factory) {
3912
+ return async (config) => {
3913
+ const result = await factory(config);
3914
+ const disabled = config.disabledTools ?? [];
3915
+ if (disabled.length === 0) return result;
3916
+ const registry = result.agent.tools;
3917
+ if (registry && typeof registry.unregister === "function") {
3918
+ for (const toolName of disabled) {
3919
+ registry.unregister(toolName);
3920
+ }
3921
+ }
3922
+ return result;
3923
+ };
3924
+ }
3849
3925
  function makeAgentSubagentRunner(opts) {
3850
3926
  const format = opts.formatTaskInput ?? defaultFormatTaskInput;
3851
3927
  return async (task, ctx) => {
@@ -6655,17 +6731,17 @@ function normalize(text) {
6655
6731
  return ` ${text.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim()} `;
6656
6732
  }
6657
6733
  function scoreAgents(task, catalog = AGENT_CATALOG) {
6658
- const hay = normalize(task);
6734
+ const haySet = new Set(normalize(task).split(/\s+/).filter(Boolean));
6659
6735
  const out = [];
6660
6736
  for (const def of Object.values(catalog)) {
6661
6737
  if (!def?.config?.role) continue;
6662
6738
  let score = 0;
6663
6739
  const matched = [];
6664
6740
  for (const kw of def.capability.keywords) {
6665
- const needle = normalize(kw);
6666
- if (hay.includes(needle.trimEnd() + " ") || hay.includes(" " + needle.trimStart())) {
6667
- const words = kw.trim().split(/\s+/).length;
6668
- score += words;
6741
+ const needleWords = normalize(kw).split(/\s+/).filter(Boolean);
6742
+ const allPresent = needleWords.every((w) => haySet.has(w));
6743
+ if (allPresent) {
6744
+ score += needleWords.length;
6669
6745
  matched.push(kw);
6670
6746
  }
6671
6747
  }
@@ -7828,7 +7904,8 @@ var ParallelEternalEngine = class {
7828
7904
  doneCondition: { type: "all_tasks_done" }
7829
7905
  };
7830
7906
  this.coordinator = new DefaultMultiAgentCoordinator(config);
7831
- const runner = makeAgentSubagentRunner({ factory: this.agentFactory });
7907
+ const filteredFactory = withDisabledToolFiltering(this.agentFactory);
7908
+ const runner = makeAgentSubagentRunner({ factory: filteredFactory });
7832
7909
  this.coordinator.setRunner?.(runner);
7833
7910
  try {
7834
7911
  while (!this.stopRequested) {
@@ -7863,7 +7940,7 @@ var ParallelEternalEngine = class {
7863
7940
  this.opts.onStage?.(stage);
7864
7941
  };
7865
7942
  this.iterations++;
7866
- const goal = await loadGoal(this.goalPath);
7943
+ const goal = await loadGoal(this.goalPath, this.opts.events);
7867
7944
  if (!goal) {
7868
7945
  this.stopRequested = true;
7869
7946
  emit({ phase: "stopped" });
@@ -7881,7 +7958,8 @@ var ParallelEternalEngine = class {
7881
7958
  doneCondition: { type: "all_tasks_done" }
7882
7959
  };
7883
7960
  this.coordinator = new DefaultMultiAgentCoordinator(config);
7884
- const runner = makeAgentSubagentRunner({ factory: this.agentFactory });
7961
+ const filteredFactory = withDisabledToolFiltering(this.agentFactory);
7962
+ const runner = makeAgentSubagentRunner({ factory: filteredFactory });
7885
7963
  this.coordinator.setRunner?.(runner);
7886
7964
  }
7887
7965
  emit({ phase: "decompose" });
@@ -7990,13 +8068,17 @@ ${personaLine}Task: ${task}
7990
8068
  role: route.role,
7991
8069
  tools: route.definition.config.tools,
7992
8070
  systemPromptOverride: route.definition.config.prompt,
7993
- timeoutMs: this.timeoutMs
8071
+ timeoutMs: this.timeoutMs,
8072
+ // Disable delegation — subagents are leaf workers, not orchestrators
8073
+ disabledTools: ["delegate"]
7994
8074
  } : {
7995
8075
  id: subagentId,
7996
8076
  name: `slot-${subagentId.slice(-6)}`,
7997
8077
  // Let the coordinator apply its default budget (roster or generic).
7998
8078
  // Hardcoding low limits here defeats the x10 budget improvement.
7999
- timeoutMs: this.timeoutMs
8079
+ timeoutMs: this.timeoutMs,
8080
+ // Disable delegation — subagents are leaf workers, not orchestrators
8081
+ disabledTools: ["delegate"]
8000
8082
  }
8001
8083
  );
8002
8084
  subagentIds.push(subagentId);
@@ -8142,10 +8224,10 @@ ${lastFew}` : "No prior iterations.",
8142
8224
  // Helpers
8143
8225
  // -------------------------------------------------------------------------
8144
8226
  async appendIterationEntry(entry) {
8145
- const current = await loadGoal(this.goalPath);
8227
+ const current = await loadGoal(this.goalPath, this.opts.events);
8146
8228
  if (!current) return;
8147
8229
  const updated = appendJournal(current, entry);
8148
- await saveGoal(this.goalPath, updated);
8230
+ await saveGoal(this.goalPath, updated, this.opts.events);
8149
8231
  const entryWithMeta = {
8150
8232
  at: (this.opts.now?.() ?? /* @__PURE__ */ new Date()).toISOString(),
8151
8233
  iteration: updated.iterations,
@@ -8157,10 +8239,10 @@ ${lastFew}` : "No prior iterations.",
8157
8239
  await this.appendIterationEntry({ source: "manual", task, status: "failure", note });
8158
8240
  }
8159
8241
  async persistState(state) {
8160
- const current = await loadGoal(this.goalPath);
8242
+ const current = await loadGoal(this.goalPath, this.opts.events);
8161
8243
  if (!current) return;
8162
8244
  if (current.engineState === state) return;
8163
- await saveGoal(this.goalPath, { ...current, engineState: state });
8245
+ await saveGoal(this.goalPath, { ...current, engineState: state }, this.opts.events);
8164
8246
  }
8165
8247
  };
8166
8248
 
@@ -8471,6 +8553,8 @@ function compactSkillBody(body) {
8471
8553
  var DefaultSkillLoader = class {
8472
8554
  dirs;
8473
8555
  cache;
8556
+ entriesCache;
8557
+ bodyCache = /* @__PURE__ */ new Map();
8474
8558
  constructor(opts) {
8475
8559
  this.dirs = [
8476
8560
  { dir: opts.paths.inProjectSkills, source: "project" },
@@ -8529,6 +8613,7 @@ var DefaultSkillLoader = class {
8529
8613
  return lines.join("\n");
8530
8614
  }
8531
8615
  async listEntries() {
8616
+ if (this.entriesCache) return this.entriesCache;
8532
8617
  const skills = await this.list();
8533
8618
  const entries = [];
8534
8619
  for (const s of skills) {
@@ -8539,33 +8624,47 @@ var DefaultSkillLoader = class {
8539
8624
  } catch {
8540
8625
  }
8541
8626
  }
8627
+ this.entriesCache = entries;
8542
8628
  return entries;
8543
8629
  }
8544
8630
  invalidateCache() {
8545
8631
  this.cache = void 0;
8632
+ this.entriesCache = void 0;
8633
+ this.bodyCache.clear();
8546
8634
  }
8547
8635
  async readBody(name) {
8636
+ const cached = this.bodyCache.get(name);
8637
+ if (cached !== void 0) return cached;
8548
8638
  const m = await this.find(name);
8549
8639
  if (!m) throw new Error(`Skill "${name}" not found`);
8550
- return fs.readFile(m.path, "utf8");
8640
+ const body = await fs.readFile(m.path, "utf8");
8641
+ this.bodyCache.set(name, body);
8642
+ return body;
8551
8643
  }
8552
8644
  async readSaveBody(name) {
8645
+ const key = `save:${name}`;
8646
+ const cached = this.bodyCache.get(key);
8647
+ if (cached !== void 0) return cached;
8553
8648
  const m = await this.find(name);
8554
8649
  if (!m) throw new Error(`Skill "${name}" not found`);
8555
8650
  const savePath = path2.join(path2.dirname(m.path), "SKILL.save.md");
8651
+ let result;
8556
8652
  try {
8557
- return await fs.readFile(savePath, "utf8");
8653
+ result = await fs.readFile(savePath, "utf8");
8558
8654
  } catch {
8559
8655
  const full = await fs.readFile(m.path, "utf8");
8560
8656
  const body = stripFrontmatter(full);
8561
8657
  const compact = compactSkillBody(body);
8562
8658
  if (compact) {
8563
- return `## Overview
8659
+ result = `## Overview
8564
8660
 
8565
8661
  ${compact}`;
8662
+ } else {
8663
+ result = body.trim().slice(0, 300);
8566
8664
  }
8567
- return body.trim().slice(0, 300);
8568
8665
  }
8666
+ this.bodyCache.set(key, result);
8667
+ return result;
8569
8668
  }
8570
8669
  };
8571
8670
  function parseFrontmatter(raw) {