@sapiom/harness 0.1.5 → 0.2.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 (245) hide show
  1. package/CHANGELOG.md +151 -0
  2. package/dist/cli/args.d.ts +16 -0
  3. package/dist/cli/args.d.ts.map +1 -0
  4. package/dist/cli/args.js +80 -0
  5. package/dist/cli/args.js.map +1 -0
  6. package/dist/cli/bin.js +30 -66
  7. package/dist/cli/bin.js.map +1 -1
  8. package/dist/cli/consent.js +1 -1
  9. package/dist/cli/settings.d.ts.map +1 -1
  10. package/dist/cli/settings.js +33 -1
  11. package/dist/cli/settings.js.map +1 -1
  12. package/dist/core/adapters/adapter.d.ts +2 -2
  13. package/dist/core/adapters/claude-code.d.ts +60 -2
  14. package/dist/core/adapters/claude-code.d.ts.map +1 -1
  15. package/dist/core/adapters/claude-code.js +119 -32
  16. package/dist/core/adapters/claude-code.js.map +1 -1
  17. package/dist/core/adapters/codex.d.ts +21 -2
  18. package/dist/core/adapters/codex.d.ts.map +1 -1
  19. package/dist/core/adapters/codex.js +53 -2
  20. package/dist/core/adapters/codex.js.map +1 -1
  21. package/dist/core/adapters/detect.d.ts +9 -0
  22. package/dist/core/adapters/detect.d.ts.map +1 -1
  23. package/dist/core/adapters/detect.js +9 -0
  24. package/dist/core/adapters/detect.js.map +1 -1
  25. package/dist/core/api-key-provider.d.ts +79 -0
  26. package/dist/core/api-key-provider.d.ts.map +1 -0
  27. package/dist/core/api-key-provider.js +91 -0
  28. package/dist/core/api-key-provider.js.map +1 -0
  29. package/dist/core/canvas-body.d.ts +28 -28
  30. package/dist/core/canvas-body.d.ts.map +1 -1
  31. package/dist/core/canvas-body.js +117 -55
  32. package/dist/core/canvas-body.js.map +1 -1
  33. package/dist/core/canvas-derive.d.ts +43 -0
  34. package/dist/core/canvas-derive.d.ts.map +1 -0
  35. package/dist/core/canvas-derive.js +95 -0
  36. package/dist/core/canvas-derive.js.map +1 -0
  37. package/dist/core/canvas-enrichment.d.ts +52 -127
  38. package/dist/core/canvas-enrichment.d.ts.map +1 -1
  39. package/dist/core/canvas-enrichment.js +17 -178
  40. package/dist/core/canvas-enrichment.js.map +1 -1
  41. package/dist/core/canvas-graph.d.ts +40 -1
  42. package/dist/core/canvas-graph.d.ts.map +1 -1
  43. package/dist/core/canvas-graph.js +71 -9
  44. package/dist/core/canvas-graph.js.map +1 -1
  45. package/dist/core/canvas-interconnections.d.ts +26 -8
  46. package/dist/core/canvas-interconnections.d.ts.map +1 -1
  47. package/dist/core/canvas-interconnections.js +132 -24
  48. package/dist/core/canvas-interconnections.js.map +1 -1
  49. package/dist/core/canvas-manifest-check.d.ts.map +1 -1
  50. package/dist/core/canvas-manifest-check.js +15 -2
  51. package/dist/core/canvas-manifest-check.js.map +1 -1
  52. package/dist/core/canvas-render.d.ts +8 -15
  53. package/dist/core/canvas-render.d.ts.map +1 -1
  54. package/dist/core/canvas-render.js +29 -41
  55. package/dist/core/canvas-render.js.map +1 -1
  56. package/dist/core/canvas-run-state.d.ts +50 -5
  57. package/dist/core/canvas-run-state.d.ts.map +1 -1
  58. package/dist/core/canvas-run-state.js +176 -11
  59. package/dist/core/canvas-run-state.js.map +1 -1
  60. package/dist/core/canvas-svg.d.ts +9 -4
  61. package/dist/core/canvas-svg.d.ts.map +1 -1
  62. package/dist/core/canvas-svg.js +84 -13
  63. package/dist/core/canvas-svg.js.map +1 -1
  64. package/dist/core/canvas-template.d.ts +9 -10
  65. package/dist/core/canvas-template.d.ts.map +1 -1
  66. package/dist/core/canvas-template.js +57 -20
  67. package/dist/core/canvas-template.js.map +1 -1
  68. package/dist/core/canvas-watcher.d.ts +22 -1
  69. package/dist/core/canvas-watcher.d.ts.map +1 -1
  70. package/dist/core/canvas-watcher.js +111 -30
  71. package/dist/core/canvas-watcher.js.map +1 -1
  72. package/dist/core/collector/normalizer.d.ts +8 -0
  73. package/dist/core/collector/normalizer.d.ts.map +1 -1
  74. package/dist/core/collector/normalizer.js +8 -0
  75. package/dist/core/collector/normalizer.js.map +1 -1
  76. package/dist/core/collector/store.d.ts +75 -1
  77. package/dist/core/collector/store.d.ts.map +1 -1
  78. package/dist/core/collector/store.js +334 -2
  79. package/dist/core/collector/store.js.map +1 -1
  80. package/dist/core/definition-slug-resolver.d.ts +13 -0
  81. package/dist/core/definition-slug-resolver.d.ts.map +1 -1
  82. package/dist/core/definition-slug-resolver.js +29 -0
  83. package/dist/core/definition-slug-resolver.js.map +1 -1
  84. package/dist/core/errors.d.ts +10 -4
  85. package/dist/core/errors.d.ts.map +1 -1
  86. package/dist/core/errors.js +11 -5
  87. package/dist/core/errors.js.map +1 -1
  88. package/dist/core/example-seed.d.ts +8 -0
  89. package/dist/core/example-seed.d.ts.map +1 -1
  90. package/dist/core/example-seed.js +47 -10
  91. package/dist/core/example-seed.js.map +1 -1
  92. package/dist/core/inject/system-prompt.d.ts +8 -0
  93. package/dist/core/inject/system-prompt.d.ts.map +1 -1
  94. package/dist/core/inject/system-prompt.js +3 -1
  95. package/dist/core/inject/system-prompt.js.map +1 -1
  96. package/dist/core/macros.d.ts.map +1 -1
  97. package/dist/core/macros.js +5 -6
  98. package/dist/core/macros.js.map +1 -1
  99. package/dist/core/paths.d.ts +1 -0
  100. package/dist/core/paths.d.ts.map +1 -1
  101. package/dist/core/paths.js +1 -0
  102. package/dist/core/paths.js.map +1 -1
  103. package/dist/core/record-archive.d.ts +187 -0
  104. package/dist/core/record-archive.d.ts.map +1 -0
  105. package/dist/core/record-archive.js +465 -0
  106. package/dist/core/record-archive.js.map +1 -0
  107. package/dist/core/rehydration.d.ts +72 -0
  108. package/dist/core/rehydration.d.ts.map +1 -0
  109. package/dist/core/rehydration.js +72 -0
  110. package/dist/core/rehydration.js.map +1 -0
  111. package/dist/core/render-local-run.d.ts +82 -0
  112. package/dist/core/render-local-run.d.ts.map +1 -0
  113. package/dist/core/render-local-run.js +105 -0
  114. package/dist/core/render-local-run.js.map +1 -0
  115. package/dist/core/render-log-slice.d.ts +30 -0
  116. package/dist/core/render-log-slice.d.ts.map +1 -0
  117. package/dist/core/render-log-slice.js +49 -0
  118. package/dist/core/render-log-slice.js.map +1 -0
  119. package/dist/core/render-run-state.d.ts.map +1 -1
  120. package/dist/core/render-run-state.js +30 -49
  121. package/dist/core/render-run-state.js.map +1 -1
  122. package/dist/core/resume-brief.d.ts +130 -0
  123. package/dist/core/resume-brief.d.ts.map +1 -0
  124. package/dist/core/resume-brief.js +404 -0
  125. package/dist/core/resume-brief.js.map +1 -0
  126. package/dist/core/rolling-summary.d.ts +130 -0
  127. package/dist/core/rolling-summary.d.ts.map +1 -0
  128. package/dist/core/rolling-summary.js +227 -0
  129. package/dist/core/rolling-summary.js.map +1 -0
  130. package/dist/core/run-local-bootstrap.d.ts +93 -0
  131. package/dist/core/run-local-bootstrap.d.ts.map +1 -0
  132. package/dist/core/run-local-bootstrap.js +155 -0
  133. package/dist/core/run-local-bootstrap.js.map +1 -0
  134. package/dist/core/run-state.d.ts +16 -1
  135. package/dist/core/run-state.d.ts.map +1 -1
  136. package/dist/core/run-state.js +75 -25
  137. package/dist/core/run-state.js.map +1 -1
  138. package/dist/core/session-manager.d.ts +11 -3
  139. package/dist/core/session-manager.d.ts.map +1 -1
  140. package/dist/core/session-manager.js +56 -7
  141. package/dist/core/session-manager.js.map +1 -1
  142. package/dist/core/session-record.d.ts +165 -0
  143. package/dist/core/session-record.d.ts.map +1 -0
  144. package/dist/core/session-record.js +470 -0
  145. package/dist/core/session-record.js.map +1 -0
  146. package/dist/core/spawn-target.d.ts +12 -0
  147. package/dist/core/spawn-target.d.ts.map +1 -0
  148. package/dist/core/spawn-target.js +187 -0
  149. package/dist/core/spawn-target.js.map +1 -0
  150. package/dist/core/stub-feedback.d.ts +52 -0
  151. package/dist/core/stub-feedback.d.ts.map +1 -0
  152. package/dist/core/stub-feedback.js +33 -0
  153. package/dist/core/stub-feedback.js.map +1 -0
  154. package/dist/core/task-manager.d.ts.map +1 -1
  155. package/dist/core/task-manager.js +9 -1
  156. package/dist/core/task-manager.js.map +1 -1
  157. package/dist/core/template-catalog.d.ts +48 -0
  158. package/dist/core/template-catalog.d.ts.map +1 -0
  159. package/dist/core/template-catalog.js +338 -0
  160. package/dist/core/template-catalog.js.map +1 -0
  161. package/dist/core/workflow-registry.d.ts.map +1 -1
  162. package/dist/core/workflow-registry.js +2 -2
  163. package/dist/core/workflow-registry.js.map +1 -1
  164. package/dist/core/workspace-watcher.d.ts.map +1 -1
  165. package/dist/core/workspace-watcher.js +4 -3
  166. package/dist/core/workspace-watcher.js.map +1 -1
  167. package/dist/index.d.ts +12 -0
  168. package/dist/index.d.ts.map +1 -1
  169. package/dist/index.js +21 -0
  170. package/dist/index.js.map +1 -1
  171. package/dist/profiles/default.d.ts.map +1 -1
  172. package/dist/profiles/default.js +9 -14
  173. package/dist/profiles/default.js.map +1 -1
  174. package/dist/server/actions.d.ts +139 -0
  175. package/dist/server/actions.d.ts.map +1 -0
  176. package/dist/server/actions.js +430 -0
  177. package/dist/server/actions.js.map +1 -0
  178. package/dist/server/auth-routes.d.ts +92 -0
  179. package/dist/server/auth-routes.d.ts.map +1 -0
  180. package/dist/server/auth-routes.js +151 -0
  181. package/dist/server/auth-routes.js.map +1 -0
  182. package/dist/server/canvas.d.ts.map +1 -1
  183. package/dist/server/canvas.js +7 -7
  184. package/dist/server/canvas.js.map +1 -1
  185. package/dist/server/fs.d.ts.map +1 -1
  186. package/dist/server/fs.js +17 -1
  187. package/dist/server/fs.js.map +1 -1
  188. package/dist/server/index.d.ts +12 -3
  189. package/dist/server/index.d.ts.map +1 -1
  190. package/dist/server/index.js +0 -0
  191. package/dist/server/index.js.map +1 -1
  192. package/dist/server/ingest.d.ts +11 -0
  193. package/dist/server/ingest.d.ts.map +1 -1
  194. package/dist/server/ingest.js +1 -0
  195. package/dist/server/ingest.js.map +1 -1
  196. package/dist/server/macros.d.ts +4 -6
  197. package/dist/server/macros.d.ts.map +1 -1
  198. package/dist/server/macros.js.map +1 -1
  199. package/dist/server/rest.d.ts +18 -6
  200. package/dist/server/rest.d.ts.map +1 -1
  201. package/dist/server/rest.js +185 -50
  202. package/dist/server/rest.js.map +1 -1
  203. package/dist/server/runs.d.ts +16 -15
  204. package/dist/server/runs.d.ts.map +1 -1
  205. package/dist/server/runs.js +15 -80
  206. package/dist/server/runs.js.map +1 -1
  207. package/dist/server/static.d.ts +15 -1
  208. package/dist/server/static.d.ts.map +1 -1
  209. package/dist/server/static.js +54 -4
  210. package/dist/server/static.js.map +1 -1
  211. package/dist/server/templates.d.ts +24 -0
  212. package/dist/server/templates.d.ts.map +1 -0
  213. package/dist/server/templates.js +54 -0
  214. package/dist/server/templates.js.map +1 -0
  215. package/dist/shared/types.d.ts +558 -66
  216. package/dist/shared/types.d.ts.map +1 -1
  217. package/dist/shared/types.js +19 -11
  218. package/dist/shared/types.js.map +1 -1
  219. package/dist/web/assets/index-DC65cskq.js +446 -0
  220. package/dist/web/assets/index-xtD-3FFa.css +32 -0
  221. package/dist/web/canvas/sess-boot/index.html +305 -0
  222. package/dist/web/index.html +4 -9
  223. package/package.json +8 -4
  224. package/dist/core/canvas-enrich.d.ts +0 -115
  225. package/dist/core/canvas-enrich.d.ts.map +0 -1
  226. package/dist/core/canvas-enrich.js +0 -186
  227. package/dist/core/canvas-enrich.js.map +0 -1
  228. package/dist/core/run-spend.d.ts +0 -55
  229. package/dist/core/run-spend.d.ts.map +0 -1
  230. package/dist/core/run-spend.js +0 -109
  231. package/dist/core/run-spend.js.map +0 -1
  232. package/dist/core/run-transactions.d.ts +0 -60
  233. package/dist/core/run-transactions.d.ts.map +0 -1
  234. package/dist/core/run-transactions.js +0 -129
  235. package/dist/core/run-transactions.js.map +0 -1
  236. package/dist/profiles/canvas-guidelines.d.ts +0 -20
  237. package/dist/profiles/canvas-guidelines.d.ts.map +0 -1
  238. package/dist/profiles/canvas-guidelines.js +0 -48
  239. package/dist/profiles/canvas-guidelines.js.map +0 -1
  240. package/dist/server/skills.d.ts +0 -51
  241. package/dist/server/skills.d.ts.map +0 -1
  242. package/dist/server/skills.js +0 -312
  243. package/dist/server/skills.js.map +0 -1
  244. package/dist/web/assets/index-DM84J83Y.js +0 -234
  245. package/dist/web/assets/index-DemtWW4L.css +0 -32
@@ -0,0 +1,404 @@
1
+ /**
2
+ * The "portable continue" brief: a bounded markdown reconstruction of a prior
3
+ * session, rendered from the SessionRecord our own events already produce (see
4
+ * core/session-record.ts).
5
+ *
6
+ * Why this exists rather than a vendor resume: `claude --resume` / `codex
7
+ * resume` only work when that agent, on this machine, still holds that
8
+ * conversation. H1 (SAP-2057) made us stop pretending otherwise; this is the
9
+ * other half — for every row where the agent does NOT hold it, start a fresh
10
+ * session seeded with what we recorded. Because the input is our normalized
11
+ * record and the output is plain text, the same code path serves claude-code
12
+ * (`--append-system-prompt`) and codex (`developer_instructions`), and would
13
+ * serve a harness with no prompt flag at all via post-ready injection.
14
+ *
15
+ * HONESTY IS THE PRODUCT HERE. A brief that reads like restored memory is
16
+ * worse than no brief: the agent will assert a file's contents or a command's
17
+ * outcome it never saw. So the header says outright that this is a
18
+ * reconstruction, `record.limitations` are spelled out, and every omission
19
+ * (dropped turns, clamped text, capped file lists) is stated in the text
20
+ * rather than silently applied.
21
+ *
22
+ * BUDGET. The brief is capped at `maxTokens` (default
23
+ * {@link RESUME_BRIEF_DEFAULT_MAX_TOKENS}), estimated at
24
+ * {@link CHARS_PER_TOKEN} characters per token — deliberately a crude
25
+ * estimator, since the consumer is a system prompt with room to spare, not a
26
+ * hard API limit, and a tokenizer dependency here would have to be right for
27
+ * two different vendors' tokenizers anyway. What gets squeezed, in order:
28
+ *
29
+ * 1. turns, oldest-first — the newest are the ones that explain what is in
30
+ * flight right now, and an old turn is the most verbose thing here per
31
+ * unit of usefulness;
32
+ * 2. the derived digests (files written, commands run). They go AFTER turns,
33
+ * not before, because they are hard-capped ({@link MAX_FILES} /
34
+ * {@link MAX_COMMANDS}) at a few hundred tokens for a whole session,
35
+ * where each turn costs a comparable amount on its own — trading a
36
+ * whole-session view for one more ancient turn is a bad deal. They can
37
+ * also be recovered by looking at the repository, so this only bites
38
+ * once every turn is already gone;
39
+ * 3. only then the rolling summary, tail-clamped. It is squeezed last
40
+ * because it is the one section that is a lossy fold of turns already
41
+ * dropped in step 1: cutting it loses history nothing else carries.
42
+ *
43
+ * The honesty header and the identity block are never dropped — a brief
44
+ * without them is a lie, not a shorter brief — so they act as a floor of
45
+ * roughly {@link RESUME_BRIEF_MIN_TOKENS} tokens that a smaller `maxTokens`
46
+ * cannot squeeze below.
47
+ */
48
+ import * as path from "node:path";
49
+ /** Default token ceiling for a brief — see the module header on the estimate. */
50
+ export const RESUME_BRIEF_DEFAULT_MAX_TOKENS = 6000;
51
+ /** Turns considered before budgeting; the budget may keep fewer, never more. */
52
+ export const RESUME_BRIEF_DEFAULT_MAX_TURNS = 12;
53
+ /**
54
+ * Characters per token. Roughly right for English prose and code across both
55
+ * vendors' tokenizers, and biased the safe way: real text averages slightly
56
+ * more than 4 chars/token, so this over-counts and lands under the ceiling.
57
+ */
58
+ export const CHARS_PER_TOKEN = 4;
59
+ /**
60
+ * Floor the budget can never squeeze below — the honesty header plus the
61
+ * identity block. Approximate (it moves with the header's wording); it exists
62
+ * so callers can reason about "what does maxTokens: 200 even mean" rather than
63
+ * as an assertion about exact size.
64
+ */
65
+ export const RESUME_BRIEF_MIN_TOKENS = 400;
66
+ /** Per-turn clamps, so one pathological prompt can't consume the whole budget. */
67
+ const MAX_PROMPT_CHARS = 1200;
68
+ const MAX_ASSISTANT_CHARS = 1200;
69
+ /** How much of a tool call's target (path or command) to show. */
70
+ const MAX_TOOL_TARGET_CHARS = 80;
71
+ /** Tool calls listed per turn before the rest are counted rather than named. */
72
+ const MAX_TOOLS_PER_TURN = 12;
73
+ /** Entries in the derived digests. */
74
+ const MAX_FILES = 30;
75
+ const MAX_COMMANDS = 10;
76
+ const MAX_COMMAND_CHARS = 120;
77
+ /** The marker `truncateForPayload` (core/collector/normalizer.ts) leaves. */
78
+ const CLAMP_MARKER = "…[truncated]";
79
+ /** The crude char-count estimate the budget is enforced against. */
80
+ export function estimateBriefTokens(text) {
81
+ return Math.ceil(text.length / CHARS_PER_TOKEN);
82
+ }
83
+ /** Clamp `text` to `maxChars`, marking the cut so nothing reads as complete
84
+ * when it isn't. */
85
+ function clamp(text, maxChars) {
86
+ const trimmed = text.trim();
87
+ if (trimmed.length <= maxChars)
88
+ return trimmed;
89
+ return `${trimmed.slice(0, maxChars).trimEnd()}${CLAMP_MARKER}`;
90
+ }
91
+ /**
92
+ * The tool's target as a human would name it: the file it edited, the command
93
+ * it ran, or — failing both — a clamped slice of the raw input.
94
+ *
95
+ * `toolInput` is a string on the wire for both harnesses: claude-code's
96
+ * normalizer stores `JSON.stringify(tool_input)` and codex's tailer stores the
97
+ * function call's raw `arguments`, so a JSON parse covers both and a plain
98
+ * string (an untruncated free-text argument) falls through to the raw slice.
99
+ * Never throws on malformed input — a brief must render from whatever was
100
+ * recorded, including a payload the collector truncated mid-JSON.
101
+ */
102
+ export function describeToolTarget(call, cwd) {
103
+ const parsed = parseToolInput(call.input);
104
+ if (parsed) {
105
+ const filePath = firstString(parsed, ["file_path", "filePath", "notebook_path", "path"]);
106
+ if (filePath)
107
+ return clamp(displayPath(filePath, cwd), MAX_TOOL_TARGET_CHARS);
108
+ const command = readCommand(parsed);
109
+ if (command)
110
+ return clamp(command, MAX_TOOL_TARGET_CHARS);
111
+ }
112
+ if (!call.input)
113
+ return null;
114
+ // No structure to read — show a slice of what was recorded rather than
115
+ // nothing, on one line so a turn's tool list stays scannable.
116
+ return clamp(call.input.replace(/\s+/g, " "), MAX_TOOL_TARGET_CHARS);
117
+ }
118
+ function parseToolInput(input) {
119
+ if (!input)
120
+ return null;
121
+ try {
122
+ const parsed = JSON.parse(input);
123
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)
124
+ ? parsed
125
+ : null;
126
+ }
127
+ catch {
128
+ return null;
129
+ }
130
+ }
131
+ function firstString(source, keys) {
132
+ for (const key of keys) {
133
+ const value = source[key];
134
+ if (typeof value === "string" && value.length > 0)
135
+ return value;
136
+ }
137
+ return null;
138
+ }
139
+ /** claude-code's Bash carries `command` as a string; codex's shell tool carries
140
+ * it as an argv array (`["bash", "-lc", "…"]`). Both read as one line here. */
141
+ function readCommand(source) {
142
+ const command = source.command;
143
+ if (typeof command === "string" && command.length > 0)
144
+ return command.replace(/\s+/g, " ").trim();
145
+ if (Array.isArray(command)) {
146
+ const joined = command.filter((part) => typeof part === "string").join(" ").trim();
147
+ return joined.length > 0 ? joined.replace(/\s+/g, " ") : null;
148
+ }
149
+ return null;
150
+ }
151
+ /** Paths under the session's cwd read far better relative; anything else (or a
152
+ * record with no recorded cwd) stays absolute so it's never ambiguous. */
153
+ function displayPath(filePath, cwd) {
154
+ if (!cwd || !path.isAbsolute(filePath))
155
+ return filePath;
156
+ const relative = path.relative(cwd, filePath);
157
+ return relative && !relative.startsWith("..") ? relative : filePath;
158
+ }
159
+ /** Tools whose input names a file the session wrote to. Read-only tools are
160
+ * deliberately excluded: "files touched" that includes everything the agent
161
+ * merely looked at stops being a signal. */
162
+ const WRITE_TOOL_NAMES = new Set([
163
+ "write",
164
+ "edit",
165
+ "multiedit",
166
+ "notebookedit",
167
+ "update",
168
+ "apply_patch",
169
+ "str_replace_editor",
170
+ ]);
171
+ const SHELL_TOOL_NAMES = new Set(["bash", "shell", "run_terminal_cmd", "local_shell"]);
172
+ /**
173
+ * Files touched and commands run, derived from `tool.call` inputs. Exported
174
+ * for tests and because the same derivation is worth reusing anywhere that
175
+ * needs "what did this session actually do to the tree".
176
+ */
177
+ export function deriveDigests(record) {
178
+ const fileCounts = new Map();
179
+ const commands = [];
180
+ const seenCommands = new Set();
181
+ for (const turn of record.turns) {
182
+ for (const call of turn.toolCalls) {
183
+ const name = (call.name ?? "").toLowerCase();
184
+ const parsed = parseToolInput(call.input);
185
+ if (WRITE_TOOL_NAMES.has(name)) {
186
+ const filePath = parsed
187
+ ? firstString(parsed, ["file_path", "filePath", "notebook_path", "path"])
188
+ : null;
189
+ if (filePath) {
190
+ const display = displayPath(filePath, record.cwd);
191
+ fileCounts.set(display, (fileCounts.get(display) ?? 0) + 1);
192
+ }
193
+ }
194
+ else if (SHELL_TOOL_NAMES.has(name)) {
195
+ const command = parsed ? readCommand(parsed) : null;
196
+ if (command && !seenCommands.has(command)) {
197
+ seenCommands.add(command);
198
+ commands.push(clamp(command, MAX_COMMAND_CHARS));
199
+ }
200
+ }
201
+ }
202
+ }
203
+ // Insertion order is chronological; both digests read newest-first, which is
204
+ // what a reader scanning for "where did this leave off" wants.
205
+ const files = [...fileCounts.entries()].reverse().map(([display, count]) => ({ display, count }));
206
+ return {
207
+ files: files.slice(0, MAX_FILES),
208
+ totalFiles: files.length,
209
+ commands: commands.reverse().slice(0, MAX_COMMANDS),
210
+ totalCommands: commands.length,
211
+ };
212
+ }
213
+ /** Plain-language wording for each machine-readable gap on the record.
214
+ * Addressed to the agent reading the brief, so it says what to do about the
215
+ * gap rather than merely naming it — the web view (web/src/lib/
216
+ * session-record-view.ts) words the same codes for a human reader. */
217
+ const LIMITATION_PROSE = {
218
+ "truncated-tool-output": "Tool output was size-capped when recorded. Any command result quoted below may be cut off — re-run it rather than trusting the excerpt.",
219
+ "assistant-narration-gap": "Only the final assistant message of each turn was recorded. Whatever was said between tool calls — including reasoning for a change — is missing.",
220
+ "missing-assistant-text": "At least one turn has no assistant text at all (Codex records none). Those turns show prompts and tool calls only.",
221
+ "incomplete-final-turn": "The last turn never completed — the session ended mid-turn, so its work may be half-applied.",
222
+ "compacted-archive": "This brief was built from the session's archived copy, whose tool inputs and results are clipped to keep it bounded. The conversation is whole, but any payload quoted below is an excerpt — re-read the file or re-run the command rather than trusting it.",
223
+ "dropped-early-turns": "The archived copy had room only for the most recent turns; earlier ones are gone. Treat what follows as the tail of a longer session — ask before assuming why something earlier was done.",
224
+ };
225
+ function renderTurn(turn, cwd) {
226
+ const lines = [];
227
+ const when = turn.promptAt ?? turn.completedAt;
228
+ lines.push(`### Turn ${turn.index}${when ? ` · ${when}` : ""}${turn.incomplete ? " · never completed" : ""}`);
229
+ if (turn.prompt !== null) {
230
+ lines.push("", "**Prompt:**", "", blockquote(clamp(turn.prompt, MAX_PROMPT_CHARS)));
231
+ }
232
+ else {
233
+ lines.push("", "**Prompt:** _not recorded — our recording started mid-turn, or the agent started this turn itself._");
234
+ }
235
+ if (turn.toolCalls.length > 0) {
236
+ const shown = turn.toolCalls.slice(0, MAX_TOOLS_PER_TURN).map((call) => {
237
+ const target = describeToolTarget(call, cwd);
238
+ return `\`${call.name ?? "unknown tool"}\`${target ? ` ${target}` : ""}`;
239
+ });
240
+ const overflow = turn.toolCalls.length - shown.length;
241
+ lines.push("", `**Tools:** ${shown.join(" · ")}${overflow > 0 ? ` · …and ${overflow} more` : ""}`);
242
+ }
243
+ if (turn.assistantText !== null) {
244
+ lines.push("", "**Reply:**", "", blockquote(clamp(turn.assistantText, MAX_ASSISTANT_CHARS)));
245
+ }
246
+ else if (!turn.incomplete) {
247
+ lines.push("", "**Reply:** _not recorded._");
248
+ }
249
+ return lines.join("\n");
250
+ }
251
+ function blockquote(text) {
252
+ return text
253
+ .split("\n")
254
+ .map((line) => `> ${line}`)
255
+ .join("\n");
256
+ }
257
+ /**
258
+ * The fixed preamble. Never dropped by the budget: an unlabelled
259
+ * reconstruction is the failure mode this whole feature exists to avoid.
260
+ */
261
+ const HONESTY_HEADER = `# Continuing a prior session — reconstruction, not restored context
262
+
263
+ You are a **fresh session**. The agent that ran the session described below is
264
+ gone and none of its context is loaded. What follows was assembled by the
265
+ Sapiom Harness from its own recorded events — it is a briefing about that
266
+ session, not a replay of it, and it is partial by construction.
267
+
268
+ Treat every claim here as something a colleague told you, not as something you
269
+ remember. Before you rely on any of it — what a file contains, what a command
270
+ returned, whether a task was finished — check the current state of the
271
+ repository yourself. If the brief and the working tree disagree, the working
272
+ tree is right.`;
273
+ /**
274
+ * Render a bounded brief for `record`. Pure and synchronous; the caller
275
+ * supplies the rolling summary and any registry-only context (title, branch,
276
+ * bound workflow) it can resolve.
277
+ */
278
+ export function buildResumeBrief(record, options = {}) {
279
+ const maxTokens = options.maxTokens ?? RESUME_BRIEF_DEFAULT_MAX_TOKENS;
280
+ const maxTurns = options.maxTurns ?? RESUME_BRIEF_DEFAULT_MAX_TURNS;
281
+ const budgetChars = Math.max(0, maxTokens) * CHARS_PER_TOKEN;
282
+ const identity = renderIdentity(record, options);
283
+ // The floor: these two are unconditional, so everything else is budgeted
284
+ // against whatever remains after them.
285
+ const fixed = `${HONESTY_HEADER}\n\n${identity}`;
286
+ const digests = deriveDigests(record);
287
+ const renderedTurns = (maxTurns > 0 ? record.turns.slice(-maxTurns) : []).map((turn) => renderTurn(turn, record.cwd));
288
+ // Mutable knobs, squeezed in the order the module header documents: the
289
+ // derived digests first (recoverable from the tree), then turns oldest-first,
290
+ // then — only if the summary alone still overflows — the summary itself.
291
+ let summaryText = options.summary?.trim() ?? "";
292
+ let keepFiles = true;
293
+ let keepCommands = true;
294
+ let keptTurns = renderedTurns.length;
295
+ const assemble = () => {
296
+ const parts = [fixed];
297
+ const summarySection = renderSummary(summaryText);
298
+ if (summarySection)
299
+ parts.push(summarySection);
300
+ const dropped = [];
301
+ const filesSection = keepFiles ? renderFiles(digests) : null;
302
+ if (filesSection)
303
+ parts.push(filesSection);
304
+ else if (!keepFiles && digests.files.length > 0)
305
+ dropped.push("files written");
306
+ const commandsSection = keepCommands ? renderCommands(digests) : null;
307
+ if (commandsSection)
308
+ parts.push(commandsSection);
309
+ else if (!keepCommands && digests.commands.length > 0)
310
+ dropped.push("commands run");
311
+ if (record.turns.length > 0) {
312
+ const heading = ["## Recent turns"];
313
+ const omitted = record.turns.length - keptTurns;
314
+ if (omitted > 0) {
315
+ heading.push("", `_The earliest ${omitted} of ${record.turns.length} recorded turns are omitted here to fit the context budget._`);
316
+ }
317
+ if (keptTurns === 0)
318
+ heading.push("", "_No turns fit the context budget._");
319
+ parts.push(heading.join("\n"));
320
+ parts.push(...renderedTurns.slice(renderedTurns.length - keptTurns));
321
+ }
322
+ if (dropped.length > 0) {
323
+ parts.push(`_Also omitted to fit the context budget: ${dropped.join(", ")}._`);
324
+ }
325
+ return parts.join("\n\n").trimEnd() + "\n";
326
+ };
327
+ const over = () => assemble().length > budgetChars;
328
+ // 1. Turns, oldest-first.
329
+ while (keptTurns > 0 && over())
330
+ keptTurns -= 1;
331
+ // 2. Derived digests, once no turn is left to give. Commands go first — the
332
+ // shorter list, and the one most cheaply reconstructed from the repo.
333
+ if (over())
334
+ keepCommands = false;
335
+ if (over())
336
+ keepFiles = false;
337
+ // 3. Last resort. Only reachable when the fixed preamble plus the summary
338
+ // alone overflow, which means either the summary was produced outside its
339
+ // own ≤500-word contract or `maxTokens` is below the preamble floor. Each
340
+ // pass strictly shortens `summaryText`, so this terminates.
341
+ while (summaryText.length > 0 && over()) {
342
+ const overflow = assemble().length - budgetChars;
343
+ summaryText = clamp(summaryText, Math.max(0, summaryText.length - overflow - CLAMP_MARKER.length));
344
+ if (summaryText === CLAMP_MARKER)
345
+ summaryText = "";
346
+ }
347
+ return assemble();
348
+ }
349
+ function renderIdentity(record, options) {
350
+ const lines = ["## What the prior session was", ""];
351
+ if (options.title)
352
+ lines.push(`- **Title:** ${options.title}`);
353
+ lines.push(`- **Directory:** ${record.cwd ?? "not recorded"}`);
354
+ if (options.gitBranch)
355
+ lines.push(`- **Git branch:** ${options.gitBranch}`);
356
+ lines.push(`- **Agent:** ${record.harness}`);
357
+ if (options.workflow) {
358
+ const { name, path: workflowPath, definitionId } = options.workflow;
359
+ lines.push(`- **Bound workflow:** ${name} (\`${workflowPath}\`)${definitionId !== null ? ` — definition ${definitionId}` : " — not yet linked to a deployed definition"}`);
360
+ }
361
+ else {
362
+ lines.push("- **Bound workflow:** none");
363
+ }
364
+ const span = [record.startedAt, record.endedAt].filter(Boolean).join(" → ");
365
+ if (span)
366
+ lines.push(`- **Ran:** ${span}`);
367
+ lines.push(`- **Recorded turns:** ${record.turnCount}`);
368
+ if (record.limitations.length > 0) {
369
+ lines.push("", "**Known gaps in this reconstruction:**", "");
370
+ for (const limitation of record.limitations)
371
+ lines.push(`- ${LIMITATION_PROSE[limitation]}`);
372
+ }
373
+ return lines.join("\n");
374
+ }
375
+ function renderSummary(summary) {
376
+ const trimmed = summary?.trim();
377
+ if (!trimmed)
378
+ return null;
379
+ return `## Rolling summary of the prior session\n\n${trimmed}`;
380
+ }
381
+ function renderFiles(digests) {
382
+ if (digests.files.length === 0)
383
+ return null;
384
+ const lines = ["## Files the prior session wrote to", "", "_Derived from recorded tool calls, newest first._", ""];
385
+ for (const file of digests.files) {
386
+ lines.push(`- \`${file.display}\`${file.count > 1 ? ` (${file.count} edits)` : ""}`);
387
+ }
388
+ if (digests.totalFiles > digests.files.length) {
389
+ lines.push(`- …and ${digests.totalFiles - digests.files.length} more`);
390
+ }
391
+ return lines.join("\n");
392
+ }
393
+ function renderCommands(digests) {
394
+ if (digests.commands.length === 0)
395
+ return null;
396
+ const lines = ["## Shell commands it ran", "", "_Distinct commands, newest first._", ""];
397
+ for (const command of digests.commands)
398
+ lines.push(`- \`${command}\``);
399
+ if (digests.totalCommands > digests.commands.length) {
400
+ lines.push(`- …and ${digests.totalCommands - digests.commands.length} more`);
401
+ }
402
+ return lines.join("\n");
403
+ }
404
+ //# sourceMappingURL=resume-brief.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume-brief.js","sourceRoot":"","sources":["../../src/core/resume-brief.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Rolling session summary — the thing that makes rehydration good rather than
3
+ * merely possible.
4
+ *
5
+ * A resume brief built from the last N turns alone tells a fresh session what
6
+ * just happened; it cannot tell it what the session was *for*. So, opt-in, we
7
+ * periodically fold the whole record down to a ≤500-word summary and cache it
8
+ * at `<generated>/<harnessSessionId>/summary.md`. The brief
9
+ * (core/resume-brief.ts) picks it up when it's there and degrades cleanly to
10
+ * last-N-turns when it isn't — which is the default, since this is
11
+ * setting-gated (`HarnessSettings.rollingSummary`).
12
+ *
13
+ * NEVER BLOCKS A TURN. Everything here is fire-and-forget off the ingest path:
14
+ * `noteEvent` returns synchronously, the fold runs as a headless one-shot
15
+ * `TaskManager` job (a separate process, a cheap model, `--max-turns 1` — the
16
+ * bounded shape `HarnessAdapter.launchTask` exists for), and every failure
17
+ * mode short-circuits to "no summary". A user's session must never be slower,
18
+ * or fail, because a summary didn't happen.
19
+ *
20
+ * The task does not write the file itself. It is asked for the summary text
21
+ * and nothing else; we write `summary.md` from its `resultText` when it
22
+ * completes. Two reasons: the target lives under `<generated>/`, outside the
23
+ * session's cwd — which codex's `workspace-write` sandbox forbids and
24
+ * claude-code's `acceptEdits` shouldn't be asked to reach — and a task that
25
+ * writes its own output can half-write it, where a task that returns text
26
+ * either produces a whole summary or none.
27
+ *
28
+ * WHERE IT DOESN'T WORK: `launchTask` is optional on the adapter contract and
29
+ * codex has no non-interactive mode wired for it, so a codex session simply
30
+ * never produces a summary and its briefs are last-N-turns. That is a real
31
+ * gap, stated rather than papered over; the brief is honest either way.
32
+ */
33
+ import type { AnalyticsEvent, BackgroundTask, HarnessKind, SessionRecord } from "../shared/types.js";
34
+ /** Filename under `<generated>/<harnessSessionId>/`. */
35
+ export declare const ROLLING_SUMMARY_FILE = "summary.md";
36
+ /** Completed turns that must accumulate before a re-fold is worth its cost. */
37
+ export declare const ROLLING_SUMMARY_TURN_INTERVAL = 10;
38
+ /** The contract stated in the prompt, and the clamp applied to what comes back. */
39
+ export declare const ROLLING_SUMMARY_MAX_WORDS = 500;
40
+ /**
41
+ * Model alias for the fold. A summary of text we already hold is the cheapest
42
+ * possible LLM job — pinning a small model here keeps an opt-in background
43
+ * feature from quietly costing what the user's own session does.
44
+ */
45
+ export declare const ROLLING_SUMMARY_MODEL = "haiku";
46
+ /** Hard turn cap: one turn in, one summary out. */
47
+ export declare const ROLLING_SUMMARY_MAX_TURNS = 1;
48
+ /** Macro id the task is registered under — also TaskManager's dedupe key, so
49
+ * a session can never have two folds in flight at once. */
50
+ export declare const ROLLING_SUMMARY_MACRO_ID = "rolling-summary";
51
+ /**
52
+ * Token budget for the material handed to the fold. Larger than a brief's
53
+ * (this is throwaway input to a cheap model, not a system prompt competing
54
+ * with the user's own context) but still bounded, so a marathon session can't
55
+ * turn one fold into a huge request.
56
+ */
57
+ export declare const ROLLING_SUMMARY_INPUT_MAX_TOKENS = 20000;
58
+ /** Absolute path of a session's cached summary. */
59
+ export declare function rollingSummaryPath(generatedRoot: string, harnessSessionId: string): string;
60
+ /**
61
+ * The cached summary for a session, or null when there is none — never throws.
62
+ * A brief that fails to find a summary is a brief without one, not an error.
63
+ */
64
+ export declare function readRollingSummary(generatedRoot: string, harnessSessionId: string): Promise<string | null>;
65
+ /** Trim `text` to at most `maxWords` words, marking the cut. */
66
+ export declare function clampToWords(text: string, maxWords?: number): string;
67
+ /**
68
+ * The one-shot prompt handed to `launchTask`. The material is the record
69
+ * rendered by {@link buildResumeBrief} at a larger budget — deliberately the
70
+ * same renderer the brief uses, so the fold reads exactly the shape a future
71
+ * brief will present, and there is one place where "what a record looks like
72
+ * as text" is defined.
73
+ *
74
+ * `previous` is folded back in rather than discarded: the record itself is
75
+ * capped at the input budget, so on a long session the earliest turns are
76
+ * already gone from the material, and the last summary is the only surviving
77
+ * account of them.
78
+ */
79
+ export declare function buildRollingSummaryPrompt(record: SessionRecord, previous: string | null): string;
80
+ /** What the summarizer needs from the outside world. All injectable, so the
81
+ * unit tests drive it without a filesystem or a spawned process. */
82
+ export interface RollingSummarizerDeps {
83
+ /** Root the per-session generated dirs live under. */
84
+ generatedRoot: string;
85
+ /** The `HarnessSettings.rollingSummary` gate, re-read per fold so toggling
86
+ * the setting takes effect without a restart. Never throws. */
87
+ enabled: () => Promise<boolean>;
88
+ /** Reads the reconstructed record for a session (SessionRecordReader.read). */
89
+ readRecord: (harnessSessionId: string) => Promise<SessionRecord | null>;
90
+ /** The live session, for the harness kind and cwd the task runs as. Returns
91
+ * undefined once the session is gone from the registry. */
92
+ getSession: (harnessSessionId: string) => {
93
+ harness: HarnessKind;
94
+ cwd: string;
95
+ } | undefined;
96
+ /** TaskManager.run, narrowed to what this needs. */
97
+ runTask: (req: {
98
+ macroId: string;
99
+ label: string;
100
+ harnessSessionId: string;
101
+ harness: HarnessKind;
102
+ cwd: string;
103
+ prompt: string;
104
+ model: string;
105
+ maxTurns: number;
106
+ }) => Promise<BackgroundTask>;
107
+ /** Completed turns between folds. Default {@link ROLLING_SUMMARY_TURN_INTERVAL}. */
108
+ turnInterval?: number;
109
+ /** Diagnostics sink. Defaults to console.error — a fold failing is worth a
110
+ * log line and nothing more. */
111
+ onError?: (err: unknown) => void;
112
+ }
113
+ export interface RollingSummarizer {
114
+ /**
115
+ * Feed one normalized analytics event. Synchronous and total: it counts
116
+ * `turn.completed`, triggers a fold on the interval and on `session.end`,
117
+ * and ignores everything else. Any work it starts is detached.
118
+ */
119
+ noteEvent(event: AnalyticsEvent): void;
120
+ /**
121
+ * Feed a task status change (TaskManager.onStatusChange). A completed fold
122
+ * task's `resultText` is what becomes `summary.md`.
123
+ */
124
+ noteTaskStatus(task: BackgroundTask): void;
125
+ /** Resolves when no fold this summarizer started is still in flight. For
126
+ * tests and for shutdown; production callers never need to await it. */
127
+ idle(): Promise<void>;
128
+ }
129
+ export declare function createRollingSummarizer(deps: RollingSummarizerDeps): RollingSummarizer;
130
+ //# sourceMappingURL=rolling-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rolling-summary.d.ts","sourceRoot":"","sources":["../../src/core/rolling-summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGrG,wDAAwD;AACxD,eAAO,MAAM,oBAAoB,eAAe,CAAC;AACjD,+EAA+E;AAC/E,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,mFAAmF;AACnF,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,UAAU,CAAC;AAC7C,mDAAmD;AACnD,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C;4DAC4D;AAC5D,eAAO,MAAM,wBAAwB,oBAAoB,CAAC;AAC1D;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,QAAS,CAAC;AAEvD,mDAAmD;AACnD,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAE1F;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQxB;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAkC,GAAG,MAAM,CAI/F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CA+BhG;AAED;qEACqE;AACrE,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,aAAa,EAAE,MAAM,CAAC;IACtB;oEACgE;IAChE,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,+EAA+E;IAC/E,UAAU,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IACxE;gEAC4D;IAC5D,UAAU,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK;QAAE,OAAO,EAAE,WAAW,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC5F,oDAAoD;IACpD,OAAO,EAAE,CAAC,GAAG,EAAE;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,gBAAgB,EAAE,MAAM,CAAC;QACzB,OAAO,EAAE,WAAW,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KAClB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAC9B,oFAAoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;qCACiC;IACjC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACvC;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAC3C;6EACyE;IACzE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,GAAG,iBAAiB,CAgGtF"}