agent-bober 0.15.0 → 0.17.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 (301) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/CHANGELOG.md +30 -0
  4. package/README.md +127 -3
  5. package/agents/bober-architect.md +34 -0
  6. package/agents/bober-code-reviewer.md +2 -0
  7. package/agents/bober-curator.md +12 -0
  8. package/agents/bober-documenter.md +129 -0
  9. package/agents/bober-evaluator.md +46 -0
  10. package/agents/bober-generator.md +12 -0
  11. package/agents/bober-planner.md +8 -1
  12. package/dist/cli/commands/graph.js +3 -3
  13. package/dist/cli/commands/graph.js.map +1 -1
  14. package/dist/cli/commands/init.js +4 -0
  15. package/dist/cli/commands/init.js.map +1 -1
  16. package/dist/cli/commands/memory.d.ts +14 -0
  17. package/dist/cli/commands/memory.d.ts.map +1 -0
  18. package/dist/cli/commands/memory.js +132 -0
  19. package/dist/cli/commands/memory.js.map +1 -0
  20. package/dist/cli/index.js +6 -0
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/config/defaults.d.ts.map +1 -1
  23. package/dist/config/defaults.js +14 -3
  24. package/dist/config/defaults.js.map +1 -1
  25. package/dist/config/loader.d.ts.map +1 -1
  26. package/dist/config/loader.js +7 -0
  27. package/dist/config/loader.js.map +1 -1
  28. package/dist/config/role-providers.d.ts +29 -0
  29. package/dist/config/role-providers.d.ts.map +1 -0
  30. package/dist/config/role-providers.js +115 -0
  31. package/dist/config/role-providers.js.map +1 -0
  32. package/dist/config/schema.d.ts +383 -14
  33. package/dist/config/schema.d.ts.map +1 -1
  34. package/dist/config/schema.js +42 -0
  35. package/dist/config/schema.js.map +1 -1
  36. package/dist/contracts/eval-result.d.ts +112 -56
  37. package/dist/contracts/eval-result.d.ts.map +1 -1
  38. package/dist/contracts/eval-result.js +3 -0
  39. package/dist/contracts/eval-result.js.map +1 -1
  40. package/dist/contracts/sprint-contract.d.ts +30 -30
  41. package/dist/fleet/aggregator.d.ts +5 -0
  42. package/dist/fleet/aggregator.d.ts.map +1 -0
  43. package/dist/fleet/aggregator.js +39 -0
  44. package/dist/fleet/aggregator.js.map +1 -0
  45. package/dist/fleet/child-config.d.ts +12 -0
  46. package/dist/fleet/child-config.d.ts.map +1 -0
  47. package/dist/fleet/child-config.js +38 -0
  48. package/dist/fleet/child-config.js.map +1 -0
  49. package/dist/fleet/coordinator.d.ts +25 -0
  50. package/dist/fleet/coordinator.d.ts.map +1 -0
  51. package/dist/fleet/coordinator.js +40 -0
  52. package/dist/fleet/coordinator.js.map +1 -0
  53. package/dist/fleet/index.d.ts +40 -0
  54. package/dist/fleet/index.d.ts.map +1 -0
  55. package/dist/fleet/index.js +117 -0
  56. package/dist/fleet/index.js.map +1 -0
  57. package/dist/fleet/manifest.d.ts +51 -0
  58. package/dist/fleet/manifest.d.ts.map +1 -0
  59. package/dist/fleet/manifest.js +32 -0
  60. package/dist/fleet/manifest.js.map +1 -0
  61. package/dist/fleet/reporter.d.ts +32 -0
  62. package/dist/fleet/reporter.d.ts.map +1 -0
  63. package/dist/fleet/reporter.js +71 -0
  64. package/dist/fleet/reporter.js.map +1 -0
  65. package/dist/fleet/runner.d.ts +48 -0
  66. package/dist/fleet/runner.d.ts.map +1 -0
  67. package/dist/fleet/runner.js +104 -0
  68. package/dist/fleet/runner.js.map +1 -0
  69. package/dist/fleet/scaffolder.d.ts +12 -0
  70. package/dist/fleet/scaffolder.d.ts.map +1 -0
  71. package/dist/fleet/scaffolder.js +82 -0
  72. package/dist/fleet/scaffolder.js.map +1 -0
  73. package/dist/fleet/types.d.ts +21 -0
  74. package/dist/fleet/types.d.ts.map +1 -0
  75. package/dist/fleet/types.js +2 -0
  76. package/dist/fleet/types.js.map +1 -0
  77. package/dist/graph/cli.d.ts +6 -2
  78. package/dist/graph/cli.d.ts.map +1 -1
  79. package/dist/graph/cli.js +53 -12
  80. package/dist/graph/cli.js.map +1 -1
  81. package/dist/graph/pipeline-lifecycle.d.ts +9 -0
  82. package/dist/graph/pipeline-lifecycle.d.ts.map +1 -1
  83. package/dist/graph/pipeline-lifecycle.js +12 -0
  84. package/dist/graph/pipeline-lifecycle.js.map +1 -1
  85. package/dist/graph/preflight-injector.d.ts +14 -0
  86. package/dist/graph/preflight-injector.d.ts.map +1 -1
  87. package/dist/graph/preflight-injector.js +84 -4
  88. package/dist/graph/preflight-injector.js.map +1 -1
  89. package/dist/incident/types.d.ts +24 -24
  90. package/dist/mcp/tools/graph-schemas.d.ts +7 -7
  91. package/dist/mcp/tools/init.d.ts.map +1 -1
  92. package/dist/mcp/tools/init.js +2 -0
  93. package/dist/mcp/tools/init.js.map +1 -1
  94. package/dist/orchestrator/agent-loader.d.ts.map +1 -1
  95. package/dist/orchestrator/agent-loader.js +15 -1
  96. package/dist/orchestrator/agent-loader.js.map +1 -1
  97. package/dist/orchestrator/agentic-loop.d.ts +51 -0
  98. package/dist/orchestrator/agentic-loop.d.ts.map +1 -1
  99. package/dist/orchestrator/agentic-loop.js +123 -4
  100. package/dist/orchestrator/agentic-loop.js.map +1 -1
  101. package/dist/orchestrator/arch-lenses.d.ts +7 -0
  102. package/dist/orchestrator/arch-lenses.d.ts.map +1 -0
  103. package/dist/orchestrator/arch-lenses.js +22 -0
  104. package/dist/orchestrator/arch-lenses.js.map +1 -0
  105. package/dist/orchestrator/architect-agent.d.ts +16 -0
  106. package/dist/orchestrator/architect-agent.d.ts.map +1 -1
  107. package/dist/orchestrator/architect-agent.js +509 -1
  108. package/dist/orchestrator/architect-agent.js.map +1 -1
  109. package/dist/orchestrator/curator-agent.js +1 -1
  110. package/dist/orchestrator/curator-agent.js.map +1 -1
  111. package/dist/orchestrator/deploy/types.d.ts +2 -2
  112. package/dist/orchestrator/documenter-agent.d.ts +57 -0
  113. package/dist/orchestrator/documenter-agent.d.ts.map +1 -0
  114. package/dist/orchestrator/documenter-agent.js +195 -0
  115. package/dist/orchestrator/documenter-agent.js.map +1 -0
  116. package/dist/orchestrator/environment.d.ts +45 -0
  117. package/dist/orchestrator/environment.d.ts.map +1 -0
  118. package/dist/orchestrator/environment.js +151 -0
  119. package/dist/orchestrator/environment.js.map +1 -0
  120. package/dist/orchestrator/eval-lenses.d.ts +7 -0
  121. package/dist/orchestrator/eval-lenses.d.ts.map +1 -0
  122. package/dist/orchestrator/eval-lenses.js +19 -0
  123. package/dist/orchestrator/eval-lenses.js.map +1 -0
  124. package/dist/orchestrator/eval-persist.d.ts +25 -0
  125. package/dist/orchestrator/eval-persist.d.ts.map +1 -0
  126. package/dist/orchestrator/eval-persist.js +74 -0
  127. package/dist/orchestrator/eval-persist.js.map +1 -0
  128. package/dist/orchestrator/evaluator-agent.d.ts +23 -0
  129. package/dist/orchestrator/evaluator-agent.d.ts.map +1 -1
  130. package/dist/orchestrator/evaluator-agent.js +60 -3
  131. package/dist/orchestrator/evaluator-agent.js.map +1 -1
  132. package/dist/orchestrator/generator-agent.d.ts.map +1 -1
  133. package/dist/orchestrator/generator-agent.js +32 -0
  134. package/dist/orchestrator/generator-agent.js.map +1 -1
  135. package/dist/orchestrator/memory/distill.d.ts +60 -0
  136. package/dist/orchestrator/memory/distill.d.ts.map +1 -0
  137. package/dist/orchestrator/memory/distill.js +177 -0
  138. package/dist/orchestrator/memory/distill.js.map +1 -0
  139. package/dist/orchestrator/memory/eval-source.d.ts +20 -0
  140. package/dist/orchestrator/memory/eval-source.d.ts.map +1 -0
  141. package/dist/orchestrator/memory/eval-source.js +88 -0
  142. package/dist/orchestrator/memory/eval-source.js.map +1 -0
  143. package/dist/orchestrator/memory/retrieve.d.ts +45 -0
  144. package/dist/orchestrator/memory/retrieve.d.ts.map +1 -0
  145. package/dist/orchestrator/memory/retrieve.js +102 -0
  146. package/dist/orchestrator/memory/retrieve.js.map +1 -0
  147. package/dist/orchestrator/model-resolver.d.ts.map +1 -1
  148. package/dist/orchestrator/model-resolver.js +12 -0
  149. package/dist/orchestrator/model-resolver.js.map +1 -1
  150. package/dist/orchestrator/pipeline.d.ts +10 -0
  151. package/dist/orchestrator/pipeline.d.ts.map +1 -1
  152. package/dist/orchestrator/pipeline.js +111 -3
  153. package/dist/orchestrator/pipeline.js.map +1 -1
  154. package/dist/orchestrator/planner-agent.d.ts +22 -1
  155. package/dist/orchestrator/planner-agent.d.ts.map +1 -1
  156. package/dist/orchestrator/planner-agent.js +160 -4
  157. package/dist/orchestrator/planner-agent.js.map +1 -1
  158. package/dist/orchestrator/research-agent.js +2 -2
  159. package/dist/orchestrator/research-agent.js.map +1 -1
  160. package/dist/orchestrator/tools/handlers.d.ts +14 -0
  161. package/dist/orchestrator/tools/handlers.d.ts.map +1 -1
  162. package/dist/orchestrator/tools/handlers.js +29 -4
  163. package/dist/orchestrator/tools/handlers.js.map +1 -1
  164. package/dist/orchestrator/tools/schemas.js +5 -5
  165. package/dist/orchestrator/tools/schemas.js.map +1 -1
  166. package/dist/orchestrator/workflow/args-builder.d.ts +35 -0
  167. package/dist/orchestrator/workflow/args-builder.d.ts.map +1 -0
  168. package/dist/orchestrator/workflow/args-builder.js +142 -0
  169. package/dist/orchestrator/workflow/args-builder.js.map +1 -0
  170. package/dist/orchestrator/workflow/budget.d.ts +57 -0
  171. package/dist/orchestrator/workflow/budget.d.ts.map +1 -0
  172. package/dist/orchestrator/workflow/budget.js +80 -0
  173. package/dist/orchestrator/workflow/budget.js.map +1 -0
  174. package/dist/orchestrator/workflow/conformance.d.ts +27 -0
  175. package/dist/orchestrator/workflow/conformance.d.ts.map +1 -0
  176. package/dist/orchestrator/workflow/conformance.js +111 -0
  177. package/dist/orchestrator/workflow/conformance.js.map +1 -0
  178. package/dist/orchestrator/workflow/eligibility.d.ts +8 -0
  179. package/dist/orchestrator/workflow/eligibility.d.ts.map +1 -0
  180. package/dist/orchestrator/workflow/eligibility.js +10 -0
  181. package/dist/orchestrator/workflow/eligibility.js.map +1 -0
  182. package/dist/orchestrator/workflow/engine.d.ts +10 -0
  183. package/dist/orchestrator/workflow/engine.d.ts.map +1 -0
  184. package/dist/orchestrator/workflow/engine.js +2 -0
  185. package/dist/orchestrator/workflow/engine.js.map +1 -0
  186. package/dist/orchestrator/workflow/errors.d.ts +13 -0
  187. package/dist/orchestrator/workflow/errors.d.ts.map +1 -0
  188. package/dist/orchestrator/workflow/errors.js +26 -0
  189. package/dist/orchestrator/workflow/errors.js.map +1 -0
  190. package/dist/orchestrator/workflow/flusher.d.ts +19 -0
  191. package/dist/orchestrator/workflow/flusher.d.ts.map +1 -0
  192. package/dist/orchestrator/workflow/flusher.js +81 -0
  193. package/dist/orchestrator/workflow/flusher.js.map +1 -0
  194. package/dist/orchestrator/workflow/interpreter.d.ts +48 -0
  195. package/dist/orchestrator/workflow/interpreter.d.ts.map +1 -0
  196. package/dist/orchestrator/workflow/interpreter.js +92 -0
  197. package/dist/orchestrator/workflow/interpreter.js.map +1 -0
  198. package/dist/orchestrator/workflow/pure-sprint.d.ts +65 -0
  199. package/dist/orchestrator/workflow/pure-sprint.d.ts.map +1 -0
  200. package/dist/orchestrator/workflow/pure-sprint.js +82 -0
  201. package/dist/orchestrator/workflow/pure-sprint.js.map +1 -0
  202. package/dist/orchestrator/workflow/reconciler.d.ts +15 -0
  203. package/dist/orchestrator/workflow/reconciler.d.ts.map +1 -0
  204. package/dist/orchestrator/workflow/reconciler.js +65 -0
  205. package/dist/orchestrator/workflow/reconciler.js.map +1 -0
  206. package/dist/orchestrator/workflow/resume-cursor.d.ts +10 -0
  207. package/dist/orchestrator/workflow/resume-cursor.d.ts.map +1 -0
  208. package/dist/orchestrator/workflow/resume-cursor.js +25 -0
  209. package/dist/orchestrator/workflow/resume-cursor.js.map +1 -0
  210. package/dist/orchestrator/workflow/retry.d.ts +50 -0
  211. package/dist/orchestrator/workflow/retry.d.ts.map +1 -0
  212. package/dist/orchestrator/workflow/retry.js +100 -0
  213. package/dist/orchestrator/workflow/retry.js.map +1 -0
  214. package/dist/orchestrator/workflow/scheduler.d.ts +87 -0
  215. package/dist/orchestrator/workflow/scheduler.d.ts.map +1 -0
  216. package/dist/orchestrator/workflow/scheduler.js +158 -0
  217. package/dist/orchestrator/workflow/scheduler.js.map +1 -0
  218. package/dist/orchestrator/workflow/selector.d.ts +26 -0
  219. package/dist/orchestrator/workflow/selector.d.ts.map +1 -0
  220. package/dist/orchestrator/workflow/selector.js +54 -0
  221. package/dist/orchestrator/workflow/selector.js.map +1 -0
  222. package/dist/orchestrator/workflow/synthesizer.d.ts +52 -0
  223. package/dist/orchestrator/workflow/synthesizer.d.ts.map +1 -0
  224. package/dist/orchestrator/workflow/synthesizer.js +75 -0
  225. package/dist/orchestrator/workflow/synthesizer.js.map +1 -0
  226. package/dist/orchestrator/workflow/ts-engine.d.ts +13 -0
  227. package/dist/orchestrator/workflow/ts-engine.d.ts.map +1 -0
  228. package/dist/orchestrator/workflow/ts-engine.js +14 -0
  229. package/dist/orchestrator/workflow/ts-engine.js.map +1 -0
  230. package/dist/orchestrator/workflow/types.d.ts +55 -0
  231. package/dist/orchestrator/workflow/types.d.ts.map +1 -0
  232. package/dist/orchestrator/workflow/types.js +3 -0
  233. package/dist/orchestrator/workflow/types.js.map +1 -0
  234. package/dist/orchestrator/workflow/workflow-engine.d.ts +31 -0
  235. package/dist/orchestrator/workflow/workflow-engine.d.ts.map +1 -0
  236. package/dist/orchestrator/workflow/workflow-engine.js +70 -0
  237. package/dist/orchestrator/workflow/workflow-engine.js.map +1 -0
  238. package/dist/providers/anthropic.d.ts.map +1 -1
  239. package/dist/providers/anthropic.js +49 -6
  240. package/dist/providers/anthropic.js.map +1 -1
  241. package/dist/providers/claude-code.d.ts +44 -0
  242. package/dist/providers/claude-code.d.ts.map +1 -0
  243. package/dist/providers/claude-code.js +143 -0
  244. package/dist/providers/claude-code.js.map +1 -0
  245. package/dist/providers/factory.d.ts +16 -2
  246. package/dist/providers/factory.d.ts.map +1 -1
  247. package/dist/providers/factory.js +66 -12
  248. package/dist/providers/factory.js.map +1 -1
  249. package/dist/providers/google.d.ts.map +1 -1
  250. package/dist/providers/google.js +27 -3
  251. package/dist/providers/google.js.map +1 -1
  252. package/dist/providers/index.d.ts +3 -1
  253. package/dist/providers/index.d.ts.map +1 -1
  254. package/dist/providers/index.js +3 -1
  255. package/dist/providers/index.js.map +1 -1
  256. package/dist/providers/openai.d.ts.map +1 -1
  257. package/dist/providers/openai.js +24 -3
  258. package/dist/providers/openai.js.map +1 -1
  259. package/dist/providers/preflight.d.ts +22 -0
  260. package/dist/providers/preflight.d.ts.map +1 -0
  261. package/dist/providers/preflight.js +54 -0
  262. package/dist/providers/preflight.js.map +1 -0
  263. package/dist/providers/structured.d.ts +130 -0
  264. package/dist/providers/structured.d.ts.map +1 -0
  265. package/dist/providers/structured.js +205 -0
  266. package/dist/providers/structured.js.map +1 -0
  267. package/dist/providers/types.d.ts +28 -0
  268. package/dist/providers/types.d.ts.map +1 -1
  269. package/dist/state/history-rotation.d.ts +17 -0
  270. package/dist/state/history-rotation.d.ts.map +1 -0
  271. package/dist/state/history-rotation.js +84 -0
  272. package/dist/state/history-rotation.js.map +1 -0
  273. package/dist/state/history.d.ts +16 -4
  274. package/dist/state/history.d.ts.map +1 -1
  275. package/dist/state/history.js +62 -20
  276. package/dist/state/history.js.map +1 -1
  277. package/dist/state/index.d.ts +1 -1
  278. package/dist/state/index.d.ts.map +1 -1
  279. package/dist/state/index.js +1 -1
  280. package/dist/state/index.js.map +1 -1
  281. package/dist/state/memory.d.ts +60 -0
  282. package/dist/state/memory.d.ts.map +1 -0
  283. package/dist/state/memory.js +242 -0
  284. package/dist/state/memory.js.map +1 -0
  285. package/hooks/hooks.json +12 -2
  286. package/package.json +9 -5
  287. package/scripts/spike-claude-code-provider.mjs +66 -0
  288. package/scripts/spike-deepseek.mjs +63 -0
  289. package/scripts/sync-targets.json +12 -0
  290. package/scripts/update-all.mjs +255 -0
  291. package/skills/bober.architect/SKILL.md +13 -0
  292. package/skills/bober.architect/references/arch-lens-panel.md +126 -0
  293. package/skills/bober.eval/SKILL.md +9 -0
  294. package/skills/bober.eval/references/lens-panel.md +115 -0
  295. package/skills/bober.plan/SKILL.md +6 -0
  296. package/skills/bober.run/SKILL.md +23 -4
  297. package/skills/bober.run/references/lens-panel.md +115 -0
  298. package/skills/bober.sprint/SKILL.md +44 -2
  299. package/skills/bober.sprint/references/lens-panel.md +115 -0
  300. package/skills/shared/arch-lens-panel.md +126 -0
  301. package/skills/shared/lens-panel.md +115 -0
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Schema-constrained ("structured") output utilities.
3
+ *
4
+ * Provides a provider-agnostic single-shot structured call that makes JSON
5
+ * output reliable even on small local models (DeepSeek / Ollama / LM Studio),
6
+ * where the server may not honor a strict schema. It:
7
+ *
8
+ * 1. requests native structured output (`ChatParams.responseSchema`) AND
9
+ * injects the schema into the system prompt — belt-and-suspenders for
10
+ * models that ignore the native knob;
11
+ * 2. coerces the model's raw text into JSON, tolerating the failure modes
12
+ * 7B-class models exhibit (markdown fences, surrounding prose);
13
+ * 3. validates the parsed value against a caller-supplied validator
14
+ * (typically backed by a Zod schema); and
15
+ * 4. on failure, performs up to `maxRepairs` repair round-trips, feeding the
16
+ * validation error back to the model.
17
+ *
18
+ * See structured.test.ts for the recovery-rate fixture suite that pins the
19
+ * single-shot + one-repair reliability target.
20
+ */
21
+ // ── Errors ──────────────────────────────────────────────────────────
22
+ /** Raised by {@link coerceJson} when no JSON value can be extracted from text. */
23
+ export class JsonCoercionError extends Error {
24
+ raw;
25
+ constructor(message,
26
+ /** The raw model text that could not be coerced. */
27
+ raw) {
28
+ super(message);
29
+ this.raw = raw;
30
+ this.name = "JsonCoercionError";
31
+ }
32
+ }
33
+ /** Raised by {@link runStructuredAgent} when every attempt fails validation. */
34
+ export class StructuredOutputError extends Error {
35
+ raw;
36
+ attempts;
37
+ constructor(message,
38
+ /** The last raw model text seen. */
39
+ raw,
40
+ /** Total chat calls made before giving up. */
41
+ attempts) {
42
+ super(message);
43
+ this.raw = raw;
44
+ this.attempts = attempts;
45
+ this.name = "StructuredOutputError";
46
+ }
47
+ }
48
+ /**
49
+ * Build a {@link Validator} from a Zod schema (or anything exposing
50
+ * `safeParse`). Flattens issues into one human-readable string the model can
51
+ * act on during a repair round-trip.
52
+ */
53
+ export function zodValidator(schema) {
54
+ return (raw) => {
55
+ const parsed = schema.safeParse(raw);
56
+ if (parsed.success) {
57
+ return { ok: true, value: parsed.data };
58
+ }
59
+ const error = parsed.error.issues
60
+ .map((i) => `${i.path.map((p) => p.toString()).join(".") || "(root)"}: ${i.message}`)
61
+ .join("; ");
62
+ return { ok: false, error: error || "validation failed" };
63
+ };
64
+ }
65
+ // ── JSON coercion ───────────────────────────────────────────────────
66
+ /**
67
+ * Extract a JSON value from a model's raw text response.
68
+ *
69
+ * Handles the common local-model failure modes, in order:
70
+ * 1. direct `JSON.parse` (well-behaved providers / strict json mode);
71
+ * 2. strip a leading/trailing markdown code fence, then parse;
72
+ * 3. extract the substring spanning the first `{`/`[` to the matching last
73
+ * `}`/`]` (drops surrounding prose), then parse.
74
+ *
75
+ * @throws {JsonCoercionError} if nothing parses.
76
+ */
77
+ export function coerceJson(text) {
78
+ const trimmed = text.trim();
79
+ const direct = tryParse(trimmed);
80
+ if (direct.ok)
81
+ return direct.value;
82
+ const defenced = stripFences(trimmed);
83
+ const fenced = tryParse(defenced);
84
+ if (fenced.ok)
85
+ return fenced.value;
86
+ const span = extractJsonSpan(defenced);
87
+ if (span !== null) {
88
+ const spanned = tryParse(span);
89
+ if (spanned.ok)
90
+ return spanned.value;
91
+ }
92
+ throw new JsonCoercionError(`Could not extract JSON from model output (${String(text.length)} chars).`, text);
93
+ }
94
+ function tryParse(s) {
95
+ if (s.length === 0)
96
+ return { ok: false };
97
+ try {
98
+ return { ok: true, value: JSON.parse(s) };
99
+ }
100
+ catch {
101
+ return { ok: false };
102
+ }
103
+ }
104
+ /** Strip a single leading ```lang fence and matching trailing ``` fence. */
105
+ function stripFences(s) {
106
+ const fenceMatch = /^```[a-zA-Z0-9]*\s*\n?([\s\S]*?)\n?```$/.exec(s);
107
+ if (fenceMatch && fenceMatch[1] !== undefined) {
108
+ return fenceMatch[1].trim();
109
+ }
110
+ return s;
111
+ }
112
+ /**
113
+ * Return the substring from the first JSON open-bracket to the last matching
114
+ * close-bracket (object or array, whichever appears first), or null if none.
115
+ */
116
+ function extractJsonSpan(s) {
117
+ const firstObj = s.indexOf("{");
118
+ const firstArr = s.indexOf("[");
119
+ if (firstObj === -1 && firstArr === -1)
120
+ return null;
121
+ const useArray = firstObj === -1 || (firstArr !== -1 && firstArr < firstObj);
122
+ const start = useArray ? firstArr : firstObj;
123
+ const close = useArray ? "]" : "}";
124
+ const lastClose = s.lastIndexOf(close);
125
+ if (lastClose <= start)
126
+ return null;
127
+ return s.slice(start, lastClose + 1);
128
+ }
129
+ const SCHEMA_INSTRUCTION_HEADER = "You MUST respond with a single JSON value that conforms to the JSON Schema " +
130
+ "below. Respond with ONLY the JSON — no prose, no explanation, no markdown " +
131
+ "code fences.";
132
+ /**
133
+ * Run a single-shot structured-output call with coercion, validation, and
134
+ * bounded repair. Returns a validated, typed value.
135
+ *
136
+ * The returned `ChatResponse.text` is parsed via {@link coerceJson} and checked
137
+ * with `validate`. If either fails and repairs remain, the bad output and the
138
+ * error are fed back as a follow-up turn.
139
+ *
140
+ * @throws {StructuredOutputError} if no attempt produces a schema-valid value.
141
+ */
142
+ export async function runStructuredAgent(opts) {
143
+ const { client, model, schema, validate, prompt } = opts;
144
+ const maxRepairs = opts.maxRepairs ?? 1;
145
+ const maxAttempts = maxRepairs + 1;
146
+ const system = buildStructuredSystem(opts.system, schema);
147
+ const messages = [{ role: "user", content: prompt }];
148
+ let inputTokens = 0;
149
+ let outputTokens = 0;
150
+ let lastError = "";
151
+ let lastRaw = "";
152
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
153
+ const response = await client.chat({
154
+ model,
155
+ system,
156
+ messages,
157
+ responseSchema: schema,
158
+ ...(opts.maxTokens !== undefined ? { maxTokens: opts.maxTokens } : {}),
159
+ });
160
+ inputTokens += response.usage.inputTokens;
161
+ outputTokens += response.usage.outputTokens;
162
+ lastRaw = response.text;
163
+ lastError = "";
164
+ let parsed;
165
+ try {
166
+ parsed = coerceJson(response.text);
167
+ }
168
+ catch (e) {
169
+ lastError = e instanceof Error ? e.message : String(e);
170
+ }
171
+ if (lastError === "") {
172
+ const result = validate(parsed);
173
+ if (result.ok) {
174
+ return {
175
+ value: result.value,
176
+ attempts: attempt,
177
+ repaired: attempt > 1,
178
+ usage: { inputTokens, outputTokens },
179
+ };
180
+ }
181
+ lastError = result.error;
182
+ }
183
+ if (attempt < maxAttempts) {
184
+ pushRepair(messages, response.text, lastError);
185
+ }
186
+ }
187
+ throw new StructuredOutputError(`Structured output failed after ${String(maxAttempts)} attempt(s): ${lastError}`, lastRaw, maxAttempts);
188
+ }
189
+ /** Append the schema instruction + serialized schema to the base system prompt. */
190
+ function buildStructuredSystem(system, schema) {
191
+ const base = system.trim();
192
+ const block = `${SCHEMA_INSTRUCTION_HEADER}\n\nJSON Schema:\n${JSON.stringify(schema)}`;
193
+ return base.length > 0 ? `${base}\n\n${block}` : block;
194
+ }
195
+ /** Append the failed output + a corrective instruction as a new turn. */
196
+ function pushRepair(messages, rawText, error) {
197
+ messages.push({ role: "assistant", content: rawText });
198
+ messages.push({
199
+ role: "user",
200
+ content: `Your previous response could not be used: ${error}. ` +
201
+ "Return ONLY a corrected JSON value that conforms to the schema. " +
202
+ "No prose, no markdown fences.",
203
+ });
204
+ }
205
+ //# sourceMappingURL=structured.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured.js","sourceRoot":"","sources":["../../src/providers/structured.ts"],"names":[],"mappings":"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"}
@@ -130,6 +130,34 @@ export interface ChatParams {
130
130
  * default applies (high on Opus 4.8). Other adapters ignore it.
131
131
  */
132
132
  effort?: "low" | "medium" | "high" | "xhigh" | "max";
133
+ /**
134
+ * When set, requests schema-constrained ("structured") output. Each adapter
135
+ * maps this to its native mechanism — OpenAI / openai-compat
136
+ * `response_format: { type: "json_schema" }`, Gemini `responseSchema`,
137
+ * Anthropic forced-tool (`tool_choice`) — and upholds a single contract:
138
+ *
139
+ * **When `responseSchema` is set, `ChatResponse.text` holds a JSON document
140
+ * that best-effort conforms to this schema, and `toolCalls` is empty.**
141
+ *
142
+ * This keeps callers provider-agnostic: they always parse/validate
143
+ * `response.text`, regardless of how the provider produced it. `responseSchema`
144
+ * is for single-shot structured calls and is mutually exclusive with `tools`
145
+ * — when set, user `tools` are NOT forwarded. The `claude-code` adapter
146
+ * ignores it (no schema-constrainable surface). Local models that don't honor
147
+ * the native knob still receive a prompt-level schema instruction via
148
+ * `runStructuredAgent` (see `./structured`), which then validates and repairs
149
+ * the output.
150
+ */
151
+ responseSchema?: JsonSchemaObject;
152
+ /**
153
+ * When true, request the provider's *loose* JSON-object mode
154
+ * (`response_format: { type: "json_object" }` for OpenAI / openai-compat).
155
+ * Unlike `responseSchema` (strict json_schema, which DeepSeek rejects), this
156
+ * only guarantees the output is a syntactically valid JSON object — the caller
157
+ * must spell out the required fields in the prompt. Ignored by adapters that
158
+ * lack the knob. When both are set, `responseSchema` takes precedence.
159
+ */
160
+ jsonObjectMode?: boolean;
133
161
  }
134
162
  /**
135
163
  * Stop reason indicating why the model stopped generating.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/providers/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/providers/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export declare function historyActivePath(projectRoot: string): string;
2
+ export declare function historyArchivePath(projectRoot: string): string;
3
+ /**
4
+ * Rotate the active history file if it exceeds maxActiveLines.
5
+ *
6
+ * When the active file has more than maxActiveLines non-empty lines,
7
+ * the oldest (count - maxActiveLines) lines are appended to the archive
8
+ * and the active file is atomically rewritten with the newest maxActiveLines
9
+ * lines via temp-file + rename.
10
+ *
11
+ * Pass maxActiveLines from config; callers must NOT call loadConfig here
12
+ * (loadConfig throws when no bober.config.json exists). Default: 2000.
13
+ *
14
+ * No-op when the active file does not exist or has <= maxActiveLines entries.
15
+ */
16
+ export declare function rotateIfNeeded(projectRoot: string, maxActiveLines?: number): Promise<void>;
17
+ //# sourceMappingURL=history-rotation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-rotation.d.ts","sourceRoot":"","sources":["../../src/state/history-rotation.ts"],"names":[],"mappings":"AAoCA,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE9D;AAID;;;;;;;;;;;;GAYG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,MAAa,GAC5B,OAAO,CAAC,IAAI,CAAC,CAsCf"}
@@ -0,0 +1,84 @@
1
+ // ── history-rotation.ts ─────────────────────────────────────────────
2
+ //
3
+ // Crash-safe rotation: when active history.jsonl exceeds maxActiveLines,
4
+ // move the oldest (count - maxActiveLines) entries to history.archive.jsonl,
5
+ // then atomically rewrite active with the remaining tail.
6
+ //
7
+ // Crash-safety ordering (Option B — idempotent, preferred):
8
+ //
9
+ // 1. Write the new-active TEMP file (tail lines only)
10
+ // 2. Append the overflow (oldest lines) to history.archive.jsonl
11
+ // 3. rename(temp, activeFile) ← COMMIT POINT (atomic on same fs)
12
+ //
13
+ // If the process crashes before step 3:
14
+ // - archive may hold the overflow entries AND active still holds all entries
15
+ // - loadHistory (archive-then-active) returns every entry; archive entries
16
+ // are a subset of active → union has no drops but has duplicates
17
+ // - this is acceptable: the contract (C4) tests the union and
18
+ // tolerates de-duplication when crash state is loaded.
19
+ //
20
+ // If the process crashes after step 3:
21
+ // - active is the tail only; archive has the overflow → no loss, no dup.
22
+ //
23
+ // The rename is the single atomic commit: everything before it is recoverable.
24
+ import { readFile, writeFile, appendFile, rename } from "node:fs/promises";
25
+ import { randomBytes } from "node:crypto";
26
+ import { join } from "node:path";
27
+ import { ensureDir } from "./helpers.js";
28
+ // ── Path helpers ─────────────────────────────────────────────────────
29
+ const BOBER_DIR = ".bober";
30
+ const HISTORY_FILE = "history.jsonl";
31
+ const HISTORY_ARCHIVE_FILE = "history.archive.jsonl";
32
+ export function historyActivePath(projectRoot) {
33
+ return join(projectRoot, BOBER_DIR, HISTORY_FILE);
34
+ }
35
+ export function historyArchivePath(projectRoot) {
36
+ return join(projectRoot, BOBER_DIR, HISTORY_ARCHIVE_FILE);
37
+ }
38
+ // ── Rotation ─────────────────────────────────────────────────────────
39
+ /**
40
+ * Rotate the active history file if it exceeds maxActiveLines.
41
+ *
42
+ * When the active file has more than maxActiveLines non-empty lines,
43
+ * the oldest (count - maxActiveLines) lines are appended to the archive
44
+ * and the active file is atomically rewritten with the newest maxActiveLines
45
+ * lines via temp-file + rename.
46
+ *
47
+ * Pass maxActiveLines from config; callers must NOT call loadConfig here
48
+ * (loadConfig throws when no bober.config.json exists). Default: 2000.
49
+ *
50
+ * No-op when the active file does not exist or has <= maxActiveLines entries.
51
+ */
52
+ export async function rotateIfNeeded(projectRoot, maxActiveLines = 2000) {
53
+ let content;
54
+ try {
55
+ content = await readFile(historyActivePath(projectRoot), "utf-8");
56
+ }
57
+ catch {
58
+ // Active file does not exist yet — nothing to rotate
59
+ return;
60
+ }
61
+ const lines = content.split("\n").filter((line) => line.trim().length > 0);
62
+ if (lines.length <= maxActiveLines) {
63
+ // Within limit — no rotation needed
64
+ return;
65
+ }
66
+ const overflowCount = lines.length - maxActiveLines;
67
+ const overflowLines = lines.slice(0, overflowCount);
68
+ const tailLines = lines.slice(overflowCount);
69
+ const activePath = historyActivePath(projectRoot);
70
+ const archPath = historyArchivePath(projectRoot);
71
+ // Ensure .bober/ directory exists (it should, but guard anyway)
72
+ await ensureDir(join(projectRoot, BOBER_DIR));
73
+ // Step 1: Write the new-active TEMP file (tail lines only)
74
+ const rnd = randomBytes(4).toString("hex");
75
+ const tmp = `${activePath}.${process.pid}.${Date.now()}.${rnd}.tmp`;
76
+ const newActiveContent = tailLines.join("\n") + "\n";
77
+ await writeFile(tmp, newActiveContent, { encoding: "utf-8" });
78
+ // Step 2: Append the overflow (oldest lines) to history.archive.jsonl
79
+ const overflowContent = overflowLines.join("\n") + "\n";
80
+ await appendFile(archPath, overflowContent, "utf-8");
81
+ // Step 3: Atomic commit — rename temp over active (commit point)
82
+ await rename(tmp, activePath);
83
+ }
84
+ //# sourceMappingURL=history-rotation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-rotation.js","sourceRoot":"","sources":["../../src/state/history-rotation.ts"],"names":[],"mappings":"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"}
@@ -10,14 +10,14 @@ export declare const HistoryEntrySchema: z.ZodObject<{
10
10
  sprintId: z.ZodOptional<z.ZodString>;
11
11
  details: z.ZodRecord<z.ZodString, z.ZodUnknown>;
12
12
  }, "strip", z.ZodTypeAny, {
13
- timestamp: string;
14
13
  details: Record<string, unknown>;
14
+ timestamp: string;
15
15
  event: string;
16
16
  phase: "evaluating" | "failed" | "init" | "planning" | "curating" | "generating" | "rework" | "complete";
17
17
  sprintId?: string | undefined;
18
18
  }, {
19
- timestamp: string;
20
19
  details: Record<string, unknown>;
20
+ timestamp: string;
21
21
  event: string;
22
22
  phase: "evaluating" | "failed" | "init" | "planning" | "curating" | "generating" | "rework" | "complete";
23
23
  sprintId?: string | undefined;
@@ -25,13 +25,25 @@ export declare const HistoryEntrySchema: z.ZodObject<{
25
25
  export type HistoryEntry = z.infer<typeof HistoryEntrySchema>;
26
26
  /**
27
27
  * Append a history entry to the JSONL log file.
28
+ * After appending, triggers rotation if active history exceeds maxActiveLines.
29
+ * Rotation uses a hardcoded default of 2000 — do NOT call loadConfig here
30
+ * (loadConfig throws when no bober.config.json exists in test fixtures).
28
31
  */
29
32
  export declare function appendHistory(projectRoot: string, entry: HistoryEntry): Promise<void>;
30
33
  /**
31
- * Load all history entries from the JSONL log.
32
- * Skips malformed lines.
34
+ * Load all history entries from both archive (if present) and active JSONL logs.
35
+ * Returns entries in chronological order: archive (oldest) first, then active (newest).
36
+ * Skips malformed lines. Signature is unchanged — always returns the full stream.
33
37
  */
34
38
  export declare function loadHistory(projectRoot: string): Promise<HistoryEntry[]>;
39
+ /**
40
+ * Load at most `limit` of the most-recent history entries from the ACTIVE log only.
41
+ * Does NOT read from history.archive.jsonl — use loadHistory for the full stream.
42
+ * Returns entries newest-last (ascending chronological order within the tail).
43
+ */
44
+ export declare function loadRecentHistory(projectRoot: string, { limit }: {
45
+ limit: number;
46
+ }): Promise<HistoryEntry[]>;
35
47
  /**
36
48
  * Update the human-readable progress.md file with current state.
37
49
  */
@@ -1 +1 @@
1
- {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/state/history.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAmBrD,eAAO,MAAM,WAAW,yGAStB,CAAC;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;EAM7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D;;GAEG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,EAAE,CAAC,CAyBzB;AAID;;GAEG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,cAAc,EAAE,EAC3B,IAAI,EAAE,QAAQ,GAAG,IAAI,GACpB,OAAO,CAAC,IAAI,CAAC,CAuFf"}
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/state/history.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAoBrD,eAAO,MAAM,WAAW,yGAStB,CAAC;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;EAM7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AA6B9D;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,EAAE,CAAC,CAmBzB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3B,OAAO,CAAC,YAAY,EAAE,CAAC,CAYzB;AAID;;GAEG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,cAAc,EAAE,EAC3B,IAAI,EAAE,QAAQ,GAAG,IAAI,GACpB,OAAO,CAAC,IAAI,CAAC,CAuFf"}
@@ -2,6 +2,7 @@ import { readFile, writeFile, appendFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { z } from "zod";
4
4
  import { ensureDir } from "./helpers.js";
5
+ import { rotateIfNeeded, historyArchivePath } from "./history-rotation.js";
5
6
  // ── Constants ───────────────────────────────────────────────────────
6
7
  const BOBER_DIR = ".bober";
7
8
  const HISTORY_FILE = "history.jsonl";
@@ -30,9 +31,34 @@ export const HistoryEntrySchema = z.object({
30
31
  sprintId: z.string().optional(),
31
32
  details: z.record(z.string(), z.unknown()),
32
33
  });
34
+ // ── Parse Helpers ───────────────────────────────────────────────────
35
+ /**
36
+ * Parse a JSONL content string into HistoryEntry objects.
37
+ * Skips malformed or invalid lines without throwing.
38
+ */
39
+ function parseEntries(content) {
40
+ const lines = content.split("\n").filter((line) => line.trim().length > 0);
41
+ const entries = [];
42
+ for (const line of lines) {
43
+ try {
44
+ const parsed = JSON.parse(line);
45
+ const result = HistoryEntrySchema.safeParse(parsed);
46
+ if (result.success) {
47
+ entries.push(result.data);
48
+ }
49
+ }
50
+ catch {
51
+ // Skip malformed lines
52
+ }
53
+ }
54
+ return entries;
55
+ }
33
56
  // ── History Operations ──────────────────────────────────────────────
34
57
  /**
35
58
  * Append a history entry to the JSONL log file.
59
+ * After appending, triggers rotation if active history exceeds maxActiveLines.
60
+ * Rotation uses a hardcoded default of 2000 — do NOT call loadConfig here
61
+ * (loadConfig throws when no bober.config.json exists in test fixtures).
36
62
  */
37
63
  export async function appendHistory(projectRoot, entry) {
38
64
  const boberDir = join(projectRoot, BOBER_DIR);
@@ -46,35 +72,51 @@ export async function appendHistory(projectRoot, entry) {
46
72
  }
47
73
  const line = JSON.stringify(entry) + "\n";
48
74
  await appendFile(historyPath(projectRoot), line, "utf-8");
75
+ // Rotate if needed — default limit 2000; no loadConfig call (would throw in test fixtures)
76
+ await rotateIfNeeded(projectRoot, 2000);
49
77
  }
50
78
  /**
51
- * Load all history entries from the JSONL log.
52
- * Skips malformed lines.
79
+ * Load all history entries from both archive (if present) and active JSONL logs.
80
+ * Returns entries in chronological order: archive (oldest) first, then active (newest).
81
+ * Skips malformed lines. Signature is unchanged — always returns the full stream.
53
82
  */
54
83
  export async function loadHistory(projectRoot) {
55
- let content;
84
+ // Read archive (ENOENT is normal on first run — treat as empty)
85
+ let archiveContent = "";
56
86
  try {
57
- content = await readFile(historyPath(projectRoot), "utf-8");
87
+ archiveContent = await readFile(historyArchivePath(projectRoot), "utf-8");
58
88
  }
59
89
  catch {
60
- // File doesn't exist yet
61
- return [];
90
+ // Archive does not exist yet — normal, treat as empty
62
91
  }
63
- const lines = content.split("\n").filter((line) => line.trim().length > 0);
64
- const entries = [];
65
- for (const line of lines) {
66
- try {
67
- const parsed = JSON.parse(line);
68
- const result = HistoryEntrySchema.safeParse(parsed);
69
- if (result.success) {
70
- entries.push(result.data);
71
- }
72
- }
73
- catch {
74
- // Skip malformed lines
75
- }
92
+ // Read active file (ENOENT is normal before first append — treat as empty)
93
+ let activeContent = "";
94
+ try {
95
+ activeContent = await readFile(historyPath(projectRoot), "utf-8");
76
96
  }
77
- return entries;
97
+ catch {
98
+ // Active file does not exist yet
99
+ }
100
+ // Concatenate: archive (older) first, active (newer) second
101
+ return [...parseEntries(archiveContent), ...parseEntries(activeContent)];
102
+ }
103
+ /**
104
+ * Load at most `limit` of the most-recent history entries from the ACTIVE log only.
105
+ * Does NOT read from history.archive.jsonl — use loadHistory for the full stream.
106
+ * Returns entries newest-last (ascending chronological order within the tail).
107
+ */
108
+ export async function loadRecentHistory(projectRoot, { limit }) {
109
+ let activeContent;
110
+ try {
111
+ activeContent = await readFile(historyPath(projectRoot), "utf-8");
112
+ }
113
+ catch {
114
+ // Active file does not exist yet
115
+ return [];
116
+ }
117
+ const entries = parseEntries(activeContent);
118
+ // Return the newest `limit` entries (tail of the array), preserving ascending order
119
+ return entries.slice(-limit);
78
120
  }
79
121
  // ── Progress Markdown ───────────────────────────────────────────────
80
122
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/state/history.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/state/history.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  export { saveContract, loadContract, listContracts, updateContract, } from "./sprint-state.js";
2
2
  export { saveSpec, loadSpec, loadLatestSpec, listSpecs, } from "./plan-state.js";
3
- export { PhaseSchema, HistoryEntrySchema, type Phase, type HistoryEntry, appendHistory, loadHistory, updateProgress, } from "./history.js";
3
+ export { PhaseSchema, HistoryEntrySchema, type Phase, type HistoryEntry, appendHistory, loadHistory, loadRecentHistory, updateProgress, } from "./history.js";
4
4
  export { saveResearch, readResearch, listResearch, } from "./research-state.js";
5
5
  export { saveDesign, readDesign, } from "./design-state.js";
6
6
  export { saveOutline, readOutline, } from "./outline-state.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,SAAS,GACV,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAEL,WAAW,EACX,kBAAkB,EAElB,KAAK,KAAK,EACV,KAAK,YAAY,EAEjB,aAAa,EACb,WAAW,EACX,cAAc,GACf,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,UAAU,EACV,UAAU,GACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,OAAO,EACP,QAAQ,EACR,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,UAAU,EACV,UAAU,EACV,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,oBAAoB,EACpB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAKxB;;;GAGG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOvE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,SAAS,GACV,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAEL,WAAW,EACX,kBAAkB,EAElB,KAAK,KAAK,EACV,KAAK,YAAY,EAEjB,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,cAAc,GACf,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,UAAU,EACV,UAAU,GACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,OAAO,EACP,QAAQ,EACR,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,UAAU,EACV,UAAU,EACV,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,oBAAoB,EACpB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAKxB;;;GAGG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOvE"}
@@ -6,7 +6,7 @@ export {
6
6
  // Zod schemas
7
7
  PhaseSchema, HistoryEntrySchema,
8
8
  // Functions
9
- appendHistory, loadHistory, updateProgress, } from "./history.js";
9
+ appendHistory, loadHistory, loadRecentHistory, updateProgress, } from "./history.js";
10
10
  export { saveResearch, readResearch, listResearch, } from "./research-state.js";
11
11
  export { saveDesign, readDesign, } from "./design-state.js";
12
12
  export { saveOutline, readOutline, } from "./outline-state.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,SAAS,GACV,MAAM,iBAAiB,CAAC;AAEzB,OAAO;AACL,cAAc;AACd,WAAW,EACX,kBAAkB;AAIlB,YAAY;AACZ,aAAa,EACb,WAAW,EACX,cAAc,GACf,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,UAAU,EACV,UAAU,GACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,OAAO,EACP,QAAQ,EACR,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,UAAU,EACV,UAAU,EACV,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,oBAAoB,EACpB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,GAKd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,MAAM,SAAS,GAAG,QAAQ,CAAC;AAC3B,MAAM,OAAO,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AAE1J;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB;IACtD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAC/C,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;IAE3B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,SAAS,GACV,MAAM,iBAAiB,CAAC;AAEzB,OAAO;AACL,cAAc;AACd,WAAW,EACX,kBAAkB;AAIlB,YAAY;AACZ,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,cAAc,GACf,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,UAAU,EACV,UAAU,GACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,OAAO,EACP,QAAQ,EACR,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,UAAU,EACV,UAAU,EACV,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,oBAAoB,EACpB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,GAKd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,MAAM,SAAS,GAAG,QAAQ,CAAC;AAC3B,MAAM,OAAO,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AAE1J;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB;IACtD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAC/C,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;IAE3B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}