@wrongstack/core 0.250.0 → 0.256.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 (104) hide show
  1. package/dist/{agent-bridge-4gc0vfW2.d.ts → agent-bridge-BrxWHEOm.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-Dz-9kiE6.d.ts → agent-subagent-runner-US741uBH.d.ts} +17 -8
  3. package/dist/{brain-sCZ3lCjq.d.ts → brain-TjEEwSpw.d.ts} +18 -1
  4. package/dist/{compactor-BRfg3QPd.d.ts → compactor-C5sT4U7I.d.ts} +1 -1
  5. package/dist/{config-eSsrto5d.d.ts → config-DuAu23zm.d.ts} +16 -1
  6. package/dist/{context-CLz3z_E8.d.ts → context-CGdgA0q6.d.ts} +13 -0
  7. package/dist/coordination/index.d.ts +14 -14
  8. package/dist/coordination/index.js +153 -2
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/defaults/index.d.ts +25 -25
  11. package/dist/defaults/index.js +238 -42
  12. package/dist/defaults/index.js.map +1 -1
  13. package/dist/execution/index.d.ts +15 -15
  14. package/dist/execution/index.js +121 -22
  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-BjJpnLW4.d.ts → goal-preamble-UiEkbNmW.d.ts} +21 -10
  19. package/dist/{index-Dy8OwfBD.d.ts → index-CC0Mcm05.d.ts} +9 -9
  20. package/dist/{index-IehiNryU.d.ts → index-CitPrI3a.d.ts} +20 -7
  21. package/dist/index.d.ts +112 -42
  22. package/dist/index.js +759 -114
  23. package/dist/index.js.map +1 -1
  24. package/dist/infrastructure/index.d.ts +6 -6
  25. package/dist/infrastructure/index.js +12 -0
  26. package/dist/infrastructure/index.js.map +1 -1
  27. package/dist/kernel/index.d.ts +10 -10
  28. package/dist/kernel/index.js.map +1 -1
  29. package/dist/{llm-selector-D22R4AFz.d.ts → llm-selector-CJ4SyAFE.d.ts} +2 -2
  30. package/dist/{mcp-servers-DfXxCASH.d.ts → mcp-servers-D8YnLaEp.d.ts} +3 -3
  31. package/dist/models/index.d.ts +5 -5
  32. package/dist/{models-registry-DpanBg8D.d.ts → models-registry-ByZCdFuQ.d.ts} +1 -1
  33. package/dist/{multi-agent-coordinator-CnbEqpv0.d.ts → multi-agent-coordinator-DqTUEAeC.d.ts} +1 -1
  34. package/dist/{null-fleet-bus-Do1OLYpj.d.ts → null-fleet-bus-B5mfTJXT.d.ts} +17 -6
  35. package/dist/observability/index.d.ts +2 -2
  36. package/dist/{package-outdated-watcher-CA5GGB4C.d.ts → package-outdated-watcher-BSgR_kK-.d.ts} +24 -3
  37. package/dist/{parallel-eternal-engine-UZg1xOzE.d.ts → parallel-eternal-engine-C0juOszP.d.ts} +24 -10
  38. package/dist/{path-resolver-BaP06Owy.d.ts → path-resolver-CbkT-RMU.d.ts} +3 -3
  39. package/dist/{permission-DbWPbuoA.d.ts → permission-CwBBpCoF.d.ts} +1 -1
  40. package/dist/{permission-policy-AOk0LVsV.d.ts → permission-policy-B8rSu908.d.ts} +39 -2
  41. package/dist/{pipeline-D1n-gQI-.d.ts → pipeline-JG8XoudC.d.ts} +43 -3
  42. package/dist/{plan-templates-BUVRY0pU.d.ts → plan-templates-DPiQMkBz.d.ts} +5 -5
  43. package/dist/{provider-runner-D0HgUqwV.d.ts → provider-runner-hM7EXlLI.d.ts} +3 -3
  44. package/dist/{retry-policy-BVnkbMET.d.ts → retry-policy-Tg7LXkoK.d.ts} +1 -1
  45. package/dist/sdd/index.d.ts +8 -8
  46. package/dist/{secret-vault-CeVNiy_f.d.ts → secret-vault-BkYkJWQs.d.ts} +1 -1
  47. package/dist/security/index.d.ts +4 -4
  48. package/dist/security/index.js +89 -18
  49. package/dist/security/index.js.map +1 -1
  50. package/dist/{selector-Cb4_9-hf.d.ts → selector-DWsqVjGf.d.ts} +1 -1
  51. package/dist/{session-event-bridge-BhtkkFFy.d.ts → session-event-bridge-BAFWdgQ3.d.ts} +1 -1
  52. package/dist/{session-reader-CCOssnBS.d.ts → session-reader-CqRvaL5v.d.ts} +1 -1
  53. package/dist/{skill-Bj6Ezqb8.d.ts → skill-DGIXCtdv.d.ts} +6 -0
  54. package/dist/skills/index.d.ts +1 -1
  55. package/dist/storage/index.d.ts +10 -10
  56. package/dist/storage/index.js +8 -1
  57. package/dist/storage/index.js.map +1 -1
  58. package/dist/types/index.d.ts +19 -19
  59. package/dist/types/index.js +95 -25
  60. package/dist/types/index.js.map +1 -1
  61. package/dist/utils/index.d.ts +2 -2
  62. package/dist/utils/index.js +5 -0
  63. package/dist/utils/index.js.map +1 -1
  64. package/package.json +2 -2
  65. package/skills/api-design/SKILL.md +1 -0
  66. package/skills/api-design/SKILL.save.md +26 -0
  67. package/skills/audit-log/SKILL.md +9 -2
  68. package/skills/audit-log/SKILL.save.md +22 -0
  69. package/skills/bug-hunter/SKILL.md +10 -2
  70. package/skills/bug-hunter/SKILL.save.md +33 -0
  71. package/skills/chimera/SKILL.md +12 -18
  72. package/skills/chimera/SKILL.save.md +26 -0
  73. package/skills/docker-deploy/SKILL.md +1 -0
  74. package/skills/docker-deploy/SKILL.save.md +23 -0
  75. package/skills/git-flow/SKILL.md +23 -2
  76. package/skills/git-flow/SKILL.save.md +25 -0
  77. package/skills/multi-agent/SKILL.md +23 -2
  78. package/skills/multi-agent/SKILL.save.md +26 -0
  79. package/skills/node-modern/SKILL.md +2 -1
  80. package/skills/node-modern/SKILL.save.md +21 -0
  81. package/skills/observability/SKILL.md +1 -0
  82. package/skills/observability/SKILL.save.md +34 -0
  83. package/skills/output-standards/SKILL.md +133 -0
  84. package/skills/output-standards/SKILL.save.md +21 -0
  85. package/skills/prompt-engineering/SKILL.md +2 -1
  86. package/skills/prompt-engineering/SKILL.save.md +29 -0
  87. package/skills/react-modern/SKILL.md +2 -1
  88. package/skills/react-modern/SKILL.save.md +24 -0
  89. package/skills/refactor-planner/SKILL.md +9 -2
  90. package/skills/refactor-planner/SKILL.save.md +26 -0
  91. package/skills/research-web/SKILL.md +1 -0
  92. package/skills/research-web/SKILL.save.md +25 -0
  93. package/skills/sdd/SKILL.md +2 -1
  94. package/skills/sdd/SKILL.save.md +19 -0
  95. package/skills/security-scanner/SKILL.md +10 -3
  96. package/skills/security-scanner/SKILL.save.md +23 -0
  97. package/skills/skill-creator/SKILL.md +2 -1
  98. package/skills/skill-creator/SKILL.save.md +20 -0
  99. package/skills/tech-stack/SKILL.md +13 -226
  100. package/skills/tech-stack/SKILL.save.md +25 -0
  101. package/skills/testing/SKILL.md +1 -0
  102. package/skills/testing/SKILL.save.md +22 -0
  103. package/skills/typescript-strict/SKILL.md +2 -1
  104. package/skills/typescript-strict/SKILL.save.md +19 -0
@@ -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-UZg1xOzE.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-BjJpnLW4.js';
3
- import { P as Provider } from '../context-CLz3z_E8.js';
4
- import { b as BrainDecision, e as BrainDecisionRequest, B as BrainArbiter } from '../brain-sCZ3lCjq.js';
5
- import '../retry-policy-BVnkbMET.js';
6
- import '../compactor-BRfg3QPd.js';
7
- import '../config-eSsrto5d.js';
8
- import '../index-IehiNryU.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-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';
9
9
  import '../logger-B63L5bTg.js';
10
- import '../pipeline-D1n-gQI-.js';
10
+ import '../pipeline-JG8XoudC.js';
11
11
  import '../observability-D-HZN_mF.js';
12
- import '../permission-DbWPbuoA.js';
13
- import '../agent-subagent-runner-Dz-9kiE6.js';
12
+ import '../permission-CwBBpCoF.js';
13
+ import '../agent-subagent-runner-US741uBH.js';
14
14
  import '../goal-store-CV9Yz2X_.js';
15
- import '../multi-agent-coordinator-CnbEqpv0.js';
15
+ import '../multi-agent-coordinator-DqTUEAeC.js';
16
16
  import 'node:events';
17
- import '../skill-Bj6Ezqb8.js';
17
+ import '../skill-DGIXCtdv.js';
18
18
  import '../wstack-paths-CJjEwPXn.js';
19
- import '../selector-Cb4_9-hf.js';
20
- import '../session-event-bridge-BhtkkFFy.js';
19
+ import '../selector-DWsqVjGf.js';
20
+ import '../session-event-bridge-BAFWdgQ3.js';
21
21
 
22
22
  /**
23
23
  * AutonomyBrain — a self-driving decision layer for autonomous workflows.
@@ -139,6 +139,14 @@ function estimateRequestTokens(messages, systemPrompt, tools, calibrationKey = C
139
139
  total
140
140
  };
141
141
  }
142
+ function getCalibrationState(calibrationKey = CALIBRATION_GLOBAL_KEY) {
143
+ const cal = calState(calibrationKey);
144
+ return {
145
+ ratio: cal.ratio,
146
+ count: cal.count,
147
+ calibrated: cal.count >= MIN_SAMPLES_FOR_CALIBRATION
148
+ };
149
+ }
142
150
  function estimateRequestTokensCalibrated(messages, systemPrompt, tools, calibrationKey = CALIBRATION_GLOBAL_KEY) {
143
151
  const result = estimateRequestTokens(messages, systemPrompt, tools, calibrationKey);
144
152
  const cal = calState(calibrationKey);
@@ -1324,6 +1332,13 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
1324
1332
  tokens = this._estimator(ctx);
1325
1333
  } else if (msgCount === this._cachedMsgCount && toolCount === this._cachedToolCount && this._cachedTokens >= 0) {
1326
1334
  tokens = this._cachedTokens;
1335
+ } else if (this.tryStashedTokens(ctx, msgCount, toolCount) !== null) {
1336
+ const stashed = this.tryStashedTokens(ctx, msgCount, toolCount);
1337
+ const cal = getCalibrationState(`${ctx.provider?.id ?? "unknown"}/${ctx.model}`);
1338
+ tokens = cal.calibrated ? Math.round(stashed * Math.min(1.5, Math.max(0.5, cal.ratio))) : stashed;
1339
+ this._cachedTokens = tokens;
1340
+ this._cachedMsgCount = msgCount;
1341
+ this._cachedToolCount = toolCount;
1327
1342
  } else {
1328
1343
  tokens = estimateRequestTokensCalibrated(
1329
1344
  ctx.messages,
@@ -1356,6 +1371,25 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
1356
1371
  return next(ctx);
1357
1372
  };
1358
1373
  }
1374
+ /**
1375
+ * H1: try to read a pre-computed token total from `ctx.lastRequestTokens`
1376
+ * (set by the agent loop's pre-flight or its restash in emitContextPct).
1377
+ * Returns the uncalibrated total when the stash is valid for the current
1378
+ * context shape (positive number, and the message count it was computed
1379
+ * at matches the current one — otherwise tool results have been appended
1380
+ * since and the value is stale). Returns null when missing or stale so
1381
+ * the caller falls back to a fresh walk.
1382
+ */
1383
+ tryStashedTokens(ctx, msgCount, toolCount) {
1384
+ const stashed = ctx.lastRequestTokens;
1385
+ if (typeof stashed !== "number" || stashed <= 0) return null;
1386
+ const stashedAt = ctx.meta?.["lastRequestTokensAt"];
1387
+ if (typeof stashedAt !== "object" || stashedAt === null) return null;
1388
+ const meta = stashedAt;
1389
+ if (meta.msgCount !== msgCount) return null;
1390
+ if (typeof meta.toolCount === "number" && meta.toolCount !== toolCount) return null;
1391
+ return stashed;
1392
+ }
1359
1393
  /**
1360
1394
  * Returns true when the previous compaction at the same or higher pressure
1361
1395
  * level reduced nothing and context has not grown materially since. Prevents
@@ -1655,7 +1689,7 @@ var ToolExecutor = class _ToolExecutor {
1655
1689
  const tool = this.registry.get(use.name);
1656
1690
  if (!tool) {
1657
1691
  const result = this.unknownToolResult(use, () => this.registry.list().map((t) => t.name));
1658
- budget = this.decrementBudget(result, budget);
1692
+ budget = this.budgetForString(result.content, budget);
1659
1693
  return { result, tool, durationMs: Date.now() - start };
1660
1694
  }
1661
1695
  const validation = validateAgainstSchema(use.input, tool.inputSchema);
@@ -1672,20 +1706,20 @@ ${errorDetails}
1672
1706
  Please call the tool again with arguments that match its inputSchema. You can use the "tool-help" tool with name="${tool.name}" to see the exact expected schema.`,
1673
1707
  is_error: true
1674
1708
  };
1675
- budget = this.decrementBudget(result, budget);
1709
+ budget = this.budgetForString(result.content, budget);
1676
1710
  return { result, tool, durationMs: Date.now() - start };
1677
1711
  }
1678
1712
  const toolDangerousCaps = getDangerousCapabilities(tool);
1679
1713
  if (hasMalformedArguments(use.input)) {
1680
1714
  const result = this.malformedInputResult(use, extractMalformedRaw(use.input));
1681
- budget = this.decrementBudget(result, budget);
1715
+ budget = this.budgetForString(result.content, budget);
1682
1716
  return { result, tool, durationMs: Date.now() - start };
1683
1717
  }
1684
1718
  if (this.opts.hookRunner?.has("PreToolUse")) {
1685
1719
  const pre = await this.opts.hookRunner.preToolUse(tool.name, use.input, ctx);
1686
1720
  if (pre.block) {
1687
1721
  const result = this.blockedByHookResult(use, pre.reason);
1688
- budget = this.decrementBudget(result, budget);
1722
+ budget = this.budgetForString(result.content, budget);
1689
1723
  return { result, tool, durationMs: Date.now() - start };
1690
1724
  }
1691
1725
  if (pre.input) {
@@ -1701,7 +1735,7 @@ Validation errors:
1701
1735
  ${errorDetails}`,
1702
1736
  is_error: true
1703
1737
  };
1704
- budget = this.decrementBudget(result, budget);
1738
+ budget = this.budgetForString(result.content, budget);
1705
1739
  return { result, tool, durationMs: Date.now() - start };
1706
1740
  }
1707
1741
  use = { ...use, input: pre.input };
@@ -1716,7 +1750,7 @@ ${errorDetails}`,
1716
1750
  }
1717
1751
  if (effectivePermission === "deny") {
1718
1752
  const result = this.deniedResult(use, decision.reason);
1719
- budget = this.decrementBudget(result, budget);
1753
+ budget = this.budgetForString(result.content, budget);
1720
1754
  return { result, tool, durationMs: Date.now() - start };
1721
1755
  }
1722
1756
  if (effectivePermission === "confirm") {
@@ -1729,7 +1763,7 @@ ${errorDetails}`,
1729
1763
  content: `Tool "${tool.name}" denied by user.`,
1730
1764
  is_error: true
1731
1765
  };
1732
- budget = this.decrementBudget(result, budget);
1766
+ budget = this.budgetForString(result.content, budget);
1733
1767
  return { result, tool, durationMs: Date.now() - start };
1734
1768
  }
1735
1769
  } else {
@@ -1753,7 +1787,8 @@ ${errorDetails}`,
1753
1787
  "tool.has_dangerous_capabilities": toolCapsForAudit.length > 0
1754
1788
  });
1755
1789
  try {
1756
- let result = await this.executeTool(tool, use, ctx, budget);
1790
+ let { block: result, bytes } = await this.executeTool(tool, use, ctx, budget);
1791
+ budget -= bytes;
1757
1792
  if (this.opts.hookRunner?.has("PostToolUse")) {
1758
1793
  const post = await this.opts.hookRunner.postToolUse(
1759
1794
  tool.name,
@@ -1762,12 +1797,13 @@ ${errorDetails}`,
1762
1797
  ctx
1763
1798
  );
1764
1799
  if (post.additionalContext) {
1765
- result = { ...result, content: `${result.content}
1800
+ const appended = `
1766
1801
 
1767
- ${post.additionalContext}` };
1802
+ ${post.additionalContext}`;
1803
+ result = { ...result, content: `${result.content}${appended}` };
1804
+ budget = Math.max(0, budget - Buffer.byteLength(appended, "utf8"));
1768
1805
  }
1769
1806
  }
1770
- budget = this.decrementBudget(result, budget);
1771
1807
  span?.setAttribute("tool.is_error", !!result.is_error);
1772
1808
  span?.setAttribute(
1773
1809
  "tool.output_bytes",
@@ -1784,7 +1820,7 @@ ${post.additionalContext}` };
1784
1820
  content: `Tool "${tool.name}" threw: ${scrubbed}`,
1785
1821
  is_error: true
1786
1822
  };
1787
- budget = this.decrementBudget(result, budget);
1823
+ budget = this.budgetForString(result.content, budget);
1788
1824
  if (err instanceof Error) span?.recordError(err);
1789
1825
  span?.setAttribute("tool.is_error", true);
1790
1826
  return { result, tool, durationMs: Date.now() - start };
@@ -1804,7 +1840,7 @@ ${post.additionalContext}` };
1804
1840
  content: `Tool "${use.name}" execution failed: ${scrubbed}`,
1805
1841
  is_error: true
1806
1842
  };
1807
- budget = this.decrementBudget(result, budget);
1843
+ budget = this.budgetForString(result.content, budget);
1808
1844
  return { result, tool: this.registry.get(use.name), durationMs: 0 };
1809
1845
  }
1810
1846
  };
@@ -1853,14 +1889,20 @@ ${post.additionalContext}` };
1853
1889
  const output = await this.runWithTimeout(tool, use.input, ctx.signal, ctx, use.id);
1854
1890
  const text = this.serializer.serialize(output);
1855
1891
  const scrubbed = this.opts.secretScrubber.scrub(text);
1856
- const { text: capped } = this.serializer.enforceCap(scrubbed, budget);
1892
+ const { text: capped, newBudget } = this.serializer.enforceCap(scrubbed, budget);
1857
1893
  this.opts.renderer?.writeToolResult(tool.name, capped, false);
1858
1894
  return {
1859
- type: "tool_result",
1860
- tool_use_id: use.id,
1861
- name: tool.name,
1862
- content: capped,
1863
- is_error: false
1895
+ block: {
1896
+ type: "tool_result",
1897
+ tool_use_id: use.id,
1898
+ name: tool.name,
1899
+ content: capped,
1900
+ is_error: false
1901
+ },
1902
+ // `budget - newBudget` is the exact byte count enforceCap spent
1903
+ // (capped at `budget` so a truncated output shows as `budget`
1904
+ // consumed, matching the pre-fix `decrementBudget` semantics).
1905
+ bytes: budget - newBudget
1864
1906
  };
1865
1907
  }
1866
1908
  async runWithTimeout(tool, input, parentSignal, ctx, toolUseId) {
@@ -2000,9 +2042,19 @@ ${excerpt}`;
2000
2042
  is_error: true
2001
2043
  };
2002
2044
  }
2003
- decrementBudget(result, budget) {
2004
- const contentBytes = typeof result.content === "string" ? Buffer.byteLength(result.content, "utf8") : Buffer.byteLength(JSON.stringify(result.content), "utf8");
2005
- return Math.max(0, budget - contentBytes);
2045
+ /**
2046
+ * Subtract a string-content result's UTF-8 byte length from the
2047
+ * iteration output budget. Used for synthesized results (unknown tool,
2048
+ * validation error, blocked, threw) where the content is a small
2049
+ * string built in the executor. The success path no longer goes
2050
+ * through here — `executeTool` carries the exact byte count it spent
2051
+ * in its return value, derived from `enforceCap`'s `newBudget`.
2052
+ *
2053
+ * Floors the result at 0 to match the pre-fix `decrementBudget`
2054
+ * semantics (over-budget spends don't underflow the running total).
2055
+ */
2056
+ budgetForString(content, budget) {
2057
+ return Math.max(0, budget - Buffer.byteLength(content, "utf8"));
2006
2058
  }
2007
2059
  /**
2008
2060
  * Compute the suggestedPattern string for a tool+input pair.
@@ -8300,6 +8352,35 @@ var DefaultErrorHandler = class {
8300
8352
  return null;
8301
8353
  }
8302
8354
  };
8355
+ function stripFrontmatter(raw) {
8356
+ if (!raw.startsWith("---")) return raw;
8357
+ const end = raw.indexOf("\n---", 4);
8358
+ if (end === -1) return raw;
8359
+ let body = raw.slice(end + 4);
8360
+ if (body.startsWith("\n")) body = body.slice(1);
8361
+ return body;
8362
+ }
8363
+ function compactSkillBody(body) {
8364
+ const sections = [];
8365
+ const overviewMatch = body.match(/##\s*Overview\s*\n([\s\S]*?)(?=\n##|\n$|$)/i);
8366
+ const overview = overviewMatch?.[1];
8367
+ if (overview?.trim()) {
8368
+ sections.push(overview.trim().slice(0, 200));
8369
+ }
8370
+ const rulesMatch = body.match(/##\s*Rules\s*\n([\s\S]*?)(?=\n##|\n$|$)/i);
8371
+ const rules = rulesMatch?.[1];
8372
+ if (rules?.trim()) {
8373
+ const trimmed = rules.trim().slice(0, 350);
8374
+ const ruleLines = trimmed.split("\n").filter((l) => /^\s*[-*]\s/.test(l) || /^\s*\d+[.)]\s/.test(l)).slice(0, 6).join("\n");
8375
+ if (ruleLines) sections.push(ruleLines);
8376
+ }
8377
+ if (sections.length === 0) {
8378
+ const first = body.trim().slice(0, 200);
8379
+ if (first) sections.push(first);
8380
+ }
8381
+ const result = sections.join("\n\n");
8382
+ return result.length > 450 ? result.slice(0, 447) + "\u2026" : result;
8383
+ }
8303
8384
  var DefaultSkillLoader = class {
8304
8385
  dirs;
8305
8386
  cache;
@@ -8381,6 +8462,24 @@ var DefaultSkillLoader = class {
8381
8462
  if (!m) throw new Error(`Skill "${name}" not found`);
8382
8463
  return fs.readFile(m.path, "utf8");
8383
8464
  }
8465
+ async readSaveBody(name) {
8466
+ const m = await this.find(name);
8467
+ if (!m) throw new Error(`Skill "${name}" not found`);
8468
+ const savePath = path2.join(path2.dirname(m.path), "SKILL.save.md");
8469
+ try {
8470
+ return await fs.readFile(savePath, "utf8");
8471
+ } catch {
8472
+ const full = await fs.readFile(m.path, "utf8");
8473
+ const body = stripFrontmatter(full);
8474
+ const compact = compactSkillBody(body);
8475
+ if (compact) {
8476
+ return `## Overview
8477
+
8478
+ ${compact}`;
8479
+ }
8480
+ return body.trim().slice(0, 300);
8481
+ }
8482
+ }
8384
8483
  };
8385
8484
  function parseFrontmatter(raw) {
8386
8485
  if (!raw.startsWith("---")) return {};