@inflexa-ai/harness 0.39.2 → 0.40.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 (184) hide show
  1. package/README.md +2 -3
  2. package/dist/agents/conversation-agent.d.ts +3 -0
  3. package/dist/agents/conversation-agent.js +13 -2
  4. package/dist/agents/report-session-agent.d.ts +3 -0
  5. package/dist/agents/report-session-agent.js +2 -0
  6. package/dist/agents/sandbox/cheminformatics-agent.js +0 -3
  7. package/dist/agents/sandbox/shared.d.ts +11 -2
  8. package/dist/agents/sandbox/shared.js +4 -0
  9. package/dist/app/chat-turn.d.ts +75 -12
  10. package/dist/app/chat-turn.js +149 -21
  11. package/dist/app/message-assembly.d.ts +16 -52
  12. package/dist/app/message-assembly.js +41 -68
  13. package/dist/app/run-activity.d.ts +4 -6
  14. package/dist/app/run-activity.js +7 -27
  15. package/dist/app/spawn-report-session.d.ts +6 -11
  16. package/dist/app/spawn-report-session.js +5 -6
  17. package/dist/app/synthesize-run.d.ts +3 -0
  18. package/dist/app/synthesize-run.js +1 -0
  19. package/dist/billing/usage-recorder.d.ts +3 -4
  20. package/dist/billing/usage-recorder.js +3 -4
  21. package/dist/contracts/chat-parts.d.ts +11 -1
  22. package/dist/contracts/chat-parts.js +1 -0
  23. package/dist/contracts/index.d.ts +1 -1
  24. package/dist/contracts/part-registry.js +1 -0
  25. package/dist/contracts/report-blocks.d.ts +8 -8
  26. package/dist/contracts/schemas/chat-parts.d.ts +32 -9
  27. package/dist/contracts/schemas/chat-parts.js +10 -0
  28. package/dist/execution/artifact-metadata.d.ts +26 -33
  29. package/dist/execution/artifact-metadata.js +44 -106
  30. package/dist/execution/post-step-pipeline.d.ts +23 -16
  31. package/dist/execution/post-step-pipeline.js +19 -21
  32. package/dist/execution/run-synthesis.d.ts +3 -0
  33. package/dist/execution/run-synthesis.js +11 -1
  34. package/dist/execution/step-summary.d.ts +21 -30
  35. package/dist/execution/step-summary.js +30 -57
  36. package/dist/index.d.ts +9 -8
  37. package/dist/index.js +15 -34
  38. package/dist/lib/zod-issues.js +2 -4
  39. package/dist/loop/compaction.d.ts +20 -0
  40. package/dist/loop/compaction.js +2 -0
  41. package/dist/loop/continue-agent.d.ts +40 -0
  42. package/dist/loop/continue-agent.js +38 -0
  43. package/dist/loop/metrics.d.ts +30 -22
  44. package/dist/loop/metrics.js +51 -22
  45. package/dist/loop/run-agent.d.ts +111 -13
  46. package/dist/loop/run-agent.js +467 -220
  47. package/dist/loop/run-to-terminal.d.ts +16 -17
  48. package/dist/loop/run-to-terminal.js +24 -35
  49. package/dist/loop/tool-mask.d.ts +23 -0
  50. package/dist/loop/tool-mask.js +46 -0
  51. package/dist/loop/tool-output.d.ts +48 -0
  52. package/dist/loop/tool-output.js +79 -0
  53. package/dist/loop/types.d.ts +6 -3
  54. package/dist/memory/ai-sdk-message-storage.d.ts +49 -2
  55. package/dist/memory/ai-sdk-message-storage.js +78 -2
  56. package/dist/memory/conversation-display-recorder.d.ts +6 -0
  57. package/dist/memory/conversation-display-recorder.js +64 -22
  58. package/dist/memory/conversation-display-replay.d.ts +5 -14
  59. package/dist/memory/conversation-display-replay.js +66 -32
  60. package/dist/memory/conversation-display-storage.d.ts +2 -1
  61. package/dist/memory/conversation-display-storage.js +2 -1
  62. package/dist/memory/conversation-view.d.ts +53 -0
  63. package/dist/memory/conversation-view.js +130 -0
  64. package/dist/memory/count-tokens.d.ts +5 -7
  65. package/dist/memory/count-tokens.js +7 -9
  66. package/dist/memory/thread-history.d.ts +74 -102
  67. package/dist/memory/thread-history.js +181 -246
  68. package/dist/memory/thread-store.d.ts +3 -3
  69. package/dist/memory/thread-store.js +7 -2
  70. package/dist/memory/tool-call-integrity.d.ts +15 -21
  71. package/dist/memory/tool-call-integrity.js +31 -38
  72. package/dist/memory/working-memory.d.ts +2 -5
  73. package/dist/memory/working-memory.js +2 -5
  74. package/dist/prompts/SOUL.d.ts +2 -2
  75. package/dist/prompts/SOUL.js +2 -7
  76. package/dist/prompts/analogical-reasoner.d.ts +1 -1
  77. package/dist/prompts/analogical-reasoner.js +16 -32
  78. package/dist/prompts/briefing.js +1 -1
  79. package/dist/prompts/compaction.d.ts +4 -0
  80. package/dist/prompts/compaction.js +24 -0
  81. package/dist/prompts/conversation.d.ts +1 -1
  82. package/dist/prompts/conversation.js +26 -35
  83. package/dist/prompts/execute-analysis/step-summary.js +7 -5
  84. package/dist/prompts/literature-reviewer.d.ts +1 -1
  85. package/dist/prompts/literature-reviewer.js +29 -34
  86. package/dist/prompts/planner.js +15 -29
  87. package/dist/prompts/report-session.d.ts +1 -1
  88. package/dist/prompts/report-session.js +2 -33
  89. package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
  90. package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +1 -2
  91. package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
  92. package/dist/prompts/sandbox/cheminformatics-agent.js +10 -29
  93. package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
  94. package/dist/prompts/sandbox/chromatin-agent.js +1 -2
  95. package/dist/prompts/sandbox/data-profiler.js +6 -3
  96. package/dist/prompts/sandbox/dna-methylation-agent.d.ts +1 -1
  97. package/dist/prompts/sandbox/dna-methylation-agent.js +2 -7
  98. package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
  99. package/dist/prompts/sandbox/drug-repurposing-agent.js +20 -24
  100. package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
  101. package/dist/prompts/sandbox/enrichment-agent.js +3 -2
  102. package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
  103. package/dist/prompts/sandbox/genomic-variant-agent.js +0 -2
  104. package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
  105. package/dist/prompts/sandbox/immune-profiling-agent.js +7 -14
  106. package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
  107. package/dist/prompts/sandbox/metabolomics-agent.js +0 -2
  108. package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
  109. package/dist/prompts/sandbox/microbiome-agent.js +14 -21
  110. package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
  111. package/dist/prompts/sandbox/multi-omics-integration-agent.js +9 -19
  112. package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
  113. package/dist/prompts/sandbox/multimodal-sc-agent.js +4 -5
  114. package/dist/prompts/sandbox/network-agent.d.ts +1 -1
  115. package/dist/prompts/sandbox/network-agent.js +7 -8
  116. package/dist/prompts/sandbox/pkpd-clinical-response-agent.d.ts +1 -1
  117. package/dist/prompts/sandbox/pkpd-clinical-response-agent.js +19 -19
  118. package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
  119. package/dist/prompts/sandbox/proteomics-agent.js +3 -4
  120. package/dist/prompts/sandbox/scientific-executor.d.ts +1 -1
  121. package/dist/prompts/sandbox/scientific-executor.js +7 -10
  122. package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
  123. package/dist/prompts/sandbox/single-cell-agent.js +2 -4
  124. package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
  125. package/dist/prompts/sandbox/spatial-omics-agent.js +3 -5
  126. package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
  127. package/dist/prompts/sandbox/statistical-modeling-agent.js +1 -1
  128. package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
  129. package/dist/prompts/sandbox/translational-safety-agent.js +10 -19
  130. package/dist/prompts/sandbox-standards.d.ts +7 -7
  131. package/dist/prompts/sandbox-standards.js +74 -76
  132. package/dist/prompts/synthesis-agent.d.ts +1 -1
  133. package/dist/prompts/synthesis-agent.js +16 -42
  134. package/dist/providers/ai-sdk.d.ts +39 -6
  135. package/dist/providers/ai-sdk.js +117 -18
  136. package/dist/providers/errors.d.ts +2 -0
  137. package/dist/providers/errors.js +5 -0
  138. package/dist/providers/prompt-cache.d.ts +43 -41
  139. package/dist/providers/prompt-cache.js +47 -41
  140. package/dist/providers/reasoning.d.ts +10 -21
  141. package/dist/providers/reasoning.js +10 -21
  142. package/dist/providers/types.d.ts +21 -5
  143. package/dist/report-model/authoring-grammar.d.ts +2 -2
  144. package/dist/runtime/assemble.d.ts +9 -7
  145. package/dist/runtime/assemble.js +7 -3
  146. package/dist/sandbox/create-sandbox.d.ts +2 -2
  147. package/dist/sandbox/submit-exec.d.ts +1 -1
  148. package/dist/schemas/artifact-manifest.d.ts +4 -4
  149. package/dist/state/init.js +39 -4
  150. package/dist/state/purge-analysis.js +4 -0
  151. package/dist/state/tool-outputs.d.ts +4 -0
  152. package/dist/state/tool-outputs.js +30 -0
  153. package/dist/tasks/data-profile.d.ts +3 -0
  154. package/dist/tasks/data-profile.js +2 -0
  155. package/dist/tools/ad-hoc-router.d.ts +8 -0
  156. package/dist/tools/ad-hoc-router.js +21 -2
  157. package/dist/tools/display/show-user.d.ts +1 -1
  158. package/dist/tools/execute-analysis.d.ts +3 -0
  159. package/dist/tools/execute-analysis.js +9 -1
  160. package/dist/tools/read-tool-output.d.ts +7 -0
  161. package/dist/tools/read-tool-output.js +130 -0
  162. package/dist/tools/research/generate-analogy-report.d.ts +10 -26
  163. package/dist/tools/research/generate-analogy-report.js +76 -163
  164. package/dist/tools/research/generate-plan.d.ts +3 -0
  165. package/dist/tools/research/generate-plan.js +4 -1
  166. package/dist/tools/research/literature-reviewer.d.ts +3 -0
  167. package/dist/tools/research/literature-reviewer.js +3 -0
  168. package/dist/tools/sandbox/report-blocker.d.ts +18 -5
  169. package/dist/tools/sandbox/report-blocker.js +54 -6
  170. package/dist/tools/sandbox/submit-file-metadata.d.ts +30 -0
  171. package/dist/tools/sandbox/submit-file-metadata.js +67 -0
  172. package/dist/tools/start-report-session.d.ts +1 -3
  173. package/dist/tools/start-report-session.js +0 -2
  174. package/dist/tools/workspace/execute-command.js +7 -4
  175. package/dist/tools/workspace/result-bounds.d.ts +4 -4
  176. package/dist/tools/workspace/result-bounds.js +6 -5
  177. package/dist/tools/workspace/workspace-search.d.ts +1 -1
  178. package/dist/workflows/execute-analysis.d.ts +3 -0
  179. package/dist/workflows/execute-analysis.js +1 -0
  180. package/dist/workflows/sandbox-step.d.ts +30 -9
  181. package/dist/workflows/sandbox-step.js +37 -8
  182. package/package.json +9 -9
  183. package/dist/providers/anthropic.d.ts +0 -25
  184. package/dist/providers/anthropic.js +0 -28
@@ -3,8 +3,9 @@
3
3
  *
4
4
  * Conversation-scoped store with an explicit two-method interface and
5
5
  * nothing else bundled in (no semantic recall, no working memory, no title
6
- * generation). It is also the home of context-window management — the read
7
- * side, `loadRecent`, returns a token-bounded window.
6
+ * generation). The read side, `loadRecent`, gives the view of the latest
7
+ * compaction marker: the stored markers decide what a turn sends, and the store
8
+ * deletes no row.
8
9
  *
9
10
  * Scope (see the harness-thread-store spec): conversation threads only. A `threadId` is the
10
11
  * UI-generated id of one conversation thread (a random UUID — an analysis
@@ -14,11 +15,10 @@
14
15
  * conversation-turn shaped on purpose, so reaching for it inside a
15
16
  * workflow step feels immediately wrong.
16
17
  *
17
- * The window is always a valid AI SDK model-message sequence: it begins on a
18
- * `user` message that is genuine user input — never a `tool`-role
19
- * continuation — and never splits a tool-call/tool-result pair. The turn
20
- * is the atomic unit; `appendTurn` writes one atomically and `loadRecent`
21
- * rounds the budget walk to turn boundaries.
18
+ * The view is always a valid AI SDK model-message sequence: it begins on a
19
+ * `user` message — never a `tool`-role continuation — and never splits a
20
+ * tool-call/tool-result pair. A compaction starts only between two rounds, a
21
+ * drop keeps whole turns, and each write of a group is atomic.
22
22
  */
23
23
  import type { ModelMessage } from "ai";
24
24
  import { ResultAsync } from "neverthrow";
@@ -34,27 +34,26 @@ export interface StoredMessage {
34
34
  readonly envelope: StoredMessageEnvelope;
35
35
  readonly message: ModelMessage;
36
36
  /**
37
- * The display projection of the append this row OPENED — present on the first
38
- * row of each `appendTurn` and absent on every other row. A conversation turn
39
- * and a host-appended record are both appends, so both carry one.
37
+ * The display projection of the group this row OPENED — present on the first
38
+ * row of each written group and absent on every other row. The opening of a
39
+ * turn, a round, a failure note, and a host-appended record are all groups.
40
40
  */
41
41
  readonly displayEnvelope?: StoredDisplayEnvelope;
42
42
  /**
43
43
  * What providers reported for the whole TURN this row completed — present
44
- * only on the last assistant row of a turn appended with a rollup, absent
45
- * everywhere else. Not a per-row figure, and unrelated to the `tokens` count
46
- * `loadRecent` windows by: that is an offline estimate stamped on every row,
47
- * this is a provider's own report (see the `reported_usage` column comment in
48
- * the state-init DDL).
44
+ * only on the last assistant row of an older turn that stored a rollup on its
45
+ * rows. A later turn keeps its rollup on its {@link StoredMessage.turn}. Not a
46
+ * per-row figure, and unrelated to the `tokens` count of the row
47
+ * (see the `reported_usage` column comment in the state-init DDL).
49
48
  */
50
49
  readonly usage?: TokenUsageRollup;
51
50
  /**
52
51
  * The time that the whole TURN this row completed took, in milliseconds —
53
- * present only on the last assistant row of a turn appended with a duration,
54
- * absent everywhere else. It has a column of its own, thus a turn that
55
- * reported no quantity still reads back with the duration that it took.
52
+ * present only beside {@link StoredMessage.usage}, on the row of an older turn.
56
53
  */
57
54
  readonly durationMs?: number;
55
+ /** The record of the chat turn that this user row opens. Present only on that row. */
56
+ readonly turn?: StoredTurnRecord;
58
57
  /**
59
58
  * Who sent the user message of the append this row OPENED — present only on a
60
59
  * genuine-user-start row of a turn appended with one. A row written before the
@@ -71,8 +70,8 @@ export interface StoredMessage {
71
70
  readonly createdAt?: Date;
72
71
  }
73
72
  /**
74
- * One atomic append: the exact provider-facing history, the display projection of
75
- * what the user was shown, and what the turn reported spending.
73
+ * One atomic group of rows: the exact provider-facing history, and the display
74
+ * projection of what the user was shown.
76
75
  *
77
76
  * The two message projections are independent by design. `modelMessages` is what
78
77
  * the provider sees and the only input to token accounting; `displayMessages` is
@@ -84,22 +83,6 @@ export interface ConversationTurn {
84
83
  readonly modelMessages: readonly ModelMessage[];
85
84
  /** Complete ordered AI SDK UI messages recorded from the live display event stream. */
86
85
  readonly displayMessages: readonly ConversationUIMessage[];
87
- /**
88
- * The turn's reported rollup, as `AgentFinish.turnUsage` carries it out of the
89
- * loop. Stored on the LAST assistant message of the turn — the row a reader
90
- * associates with the reply. Omitting it, and supplying one that reports no
91
- * quantity at all, both leave the row without one: a turn that reported nothing
92
- * must not read back as a turn that cost zero.
93
- */
94
- readonly turnUsage?: TokenUsageRollup;
95
- /**
96
- * The time that the turn took, in milliseconds, as the live header measured
97
- * it. Stored beside the rollup, on the same last assistant message. A caller
98
- * that supplies none leaves the row without one, and nothing reconstructs a
99
- * value later. The duration keeps a column of its own, thus a turn that
100
- * reported no quantity still keeps the duration that it took.
101
- */
102
- readonly turnDurationMs?: number;
103
86
  /**
104
87
  * Who sent the user message of this turn — the identity the host holds at the
105
88
  * append site. Stored on the FIRST row of the append, and only when that row
@@ -123,6 +106,45 @@ export interface ConversationTurn {
123
106
  * message the turn-boundary predicates fail to recognise.
124
107
  */
125
108
  export declare function conversationRecordTurn(text: string): ConversationTurn;
109
+ /** The status of a chat turn: `open` while it runs, then its outcome. */
110
+ export type TurnStatus = "open" | "done" | "aborted" | "failed";
111
+ /** The close of a chat turn. It sets the outcome on the turn record, one time. */
112
+ export interface TurnClose {
113
+ readonly status: Exclude<TurnStatus, "open">;
114
+ /** The reason of a failure. */
115
+ readonly reason?: string;
116
+ /** A rollup that reports no quantity is stored as absent. */
117
+ readonly turnUsage?: TokenUsageRollup;
118
+ readonly turnDurationMs?: number;
119
+ /** The failure note, stored after the rounds. */
120
+ readonly note?: ConversationTurn;
121
+ }
122
+ /**
123
+ * One write of a chat turn. The opening adds the turn record, and a later write names the turn by
124
+ * `startSeq`. The `never` members make a write with both keys fail to compile.
125
+ */
126
+ export type TurnWrite = {
127
+ readonly opening: ConversationTurn;
128
+ readonly startSeq?: never;
129
+ readonly rounds: readonly ConversationTurn[];
130
+ readonly close?: TurnClose;
131
+ } | {
132
+ readonly startSeq: number;
133
+ readonly opening?: never;
134
+ readonly rounds: readonly ConversationTurn[];
135
+ readonly close?: TurnClose;
136
+ };
137
+ export interface TurnWriteResult {
138
+ /** The `seq` of the user row that opens the turn, which keys its turn record. */
139
+ readonly startSeq: number;
140
+ }
141
+ /** The turn record of a chat turn, as the display read gives it. */
142
+ export interface StoredTurnRecord {
143
+ readonly status: TurnStatus;
144
+ readonly reason?: string;
145
+ readonly usage?: TokenUsageRollup;
146
+ readonly durationMs?: number;
147
+ }
126
148
  /**
127
149
  * The result of `retractLastTurn`. `retracted` carries `messages` — the number
128
150
  * of rows removed — so a caller can assert exactly what came off the tail. The
@@ -138,16 +160,9 @@ export type RetractOutcome = {
138
160
  } | {
139
161
  kind: "no-user-turn";
140
162
  };
141
- /**
142
- * The read options of {@link ThreadHistory.loadRecent}. An absent option gives
143
- * the default window.
144
- */
163
+ /** The read options of {@link ThreadHistory.loadRecent}. */
145
164
  export interface LoadRecentOptions {
146
- /**
147
- * Keep the first turn of the thread in the window, past the eviction. The
148
- * default is `false`, and the eviction then drops the first turn with the
149
- * rest of the oldest block.
150
- */
165
+ /** Keep the first turn of the thread, the seed of a report thread, in front of the latest summary. */
151
166
  readonly keepFirstTurn?: boolean;
152
167
  }
153
168
  /**
@@ -156,36 +171,23 @@ export interface LoadRecentOptions {
156
171
  */
157
172
  export interface ThreadHistory {
158
173
  /**
159
- * Append one {@link ConversationTurn} — every message written in a single
160
- * transaction with a `seq` monotonically increasing per thread.
161
- *
162
- * A turn writing no assistant message stores neither the rollup nor the
163
- * duration and still succeeds: there is no row on which the two figures
164
- * would mean anything.
174
+ * Append one group, for example a record of a host — every message written in a
175
+ * single transaction with a `seq` monotonically increasing per thread.
165
176
  */
166
177
  appendTurn(threadId: string, turn: ConversationTurn): ResultAsync<void, DbError>;
167
178
  /**
168
- * Return a recent-turns window that fits `tokenBudget`, oldest-first,
169
- * snapped to a valid AI SDK model-message sequence. The window START advances
170
- * in whole `EVICTION_BLOCK_TURNS` blocks (see the constant) so the prompt-cache
171
- * prefix stays byte-stable across appends; the window may therefore carry a
172
- * little less than the budget would strictly allow, but never more.
173
- *
174
- * `keepFirstTurn` keeps the first turn of the thread. The eviction then drops
175
- * the oldest turns after it, and the window holds the first turn and that
176
- * retained suffix. The first turn appears one time only.
177
- *
178
- * The retained turn can carry the window past `tokenBudget`. The cost is
179
- * bounded. A report session seeds one turn, its brief carries a length bound,
180
- * and its copy of the working-memory render is one row. The retained head also
181
- * holds `messages[0]` byte-identical for the life of the thread, thus the
182
- * prompt-cache prefix of the provider stays still.
179
+ * Write the groups of one chat turn in one transaction, after the rows that the thread holds.
180
+ * A write with the opening adds the turn record, and a close changes only an `open` record.
181
+ */
182
+ writeTurn(threadId: string, write: TurnWrite): ResultAsync<TurnWriteResult, DbError>;
183
+ /**
184
+ * The view of the thread: the stored markers decide which rows a turn sends, and a thread with no
185
+ * marker gives each row. The loop computes each request with the same rule.
183
186
  */
184
- loadRecent(threadId: string, tokenBudget: number, options?: LoadRecentOptions): ResultAsync<ModelMessage[], DbError>;
187
+ loadRecent(threadId: string, options?: LoadRecentOptions): ResultAsync<ModelMessage[], DbError>;
185
188
  /**
186
189
  * Return a thread's messages oldest-first for UI display, grouped into turns.
187
- * NOT token-windowed — that is `loadRecent`'s job for the agent loop — and no
188
- * eviction.
190
+ * It gives each row, and the view of the agent loop is `loadRecent`'s job.
189
191
  *
190
192
  * There is no paginated form, because a page could never cost less: the read
191
193
  * selects and parses every row of the thread and would slice only afterwards,
@@ -202,18 +204,10 @@ export interface ThreadHistory {
202
204
  loadAll(threadId: string): ResultAsync<StoredMessage[][], DbError>;
203
205
  /**
204
206
  * Remove the thread's most recent turn — every row from the last
205
- * genuine-user-start `seq` onward — in a single transaction.
207
+ * genuine-user-start `seq` onward, and its turn record — in a single transaction.
206
208
  *
207
- * Tail-only by design: removal cuts at the last genuine-user-start `seq` —
208
- * a turn boundary, not the last append. Because every conversation turn
209
- * opens with the user's message, that boundary starts the most recent turn,
210
- * so removing it restores the row set the thread held before that turn and
211
- * leaves `loadRecent`'s byte-stable prompt-cache prefix untouched; an
212
- * out-of-contract assistant-only follow-up append carries no user-start row
213
- * and so folds into the removed tail, exactly as the read side's turn
214
- * grouping folds it. Deleting mid-history would shift the window head and
215
- * rewrite that prefix, so it is deliberately not offered — only the tail
216
- * can come off.
209
+ * When the last turn goes, each earlier prefix stays byte-identical. A later
210
+ * request never sees a changed earlier record, and only the last turn can go.
217
211
  *
218
212
  * Callers are assumed single-writer per thread (the host serializes turns);
219
213
  * the outcome's `messages` count lets a caller assert exactly what was
@@ -264,28 +258,6 @@ export interface ThreadHistory {
264
258
  * freshly-registered `MeterProvider`. Test-only.
265
259
  */
266
260
  export declare function __resetThreadHistoryMetricsForTest(): void;
267
- /**
268
- * Chunked-eviction block size, in whole turns — the granularity at which
269
- * `loadRecent`'s retained window may advance its START turn.
270
- *
271
- * `loadRecent` snaps its eviction count UP to a multiple of this block, so the
272
- * window's first turn — hence `messages[0]` and the whole tools+system+history
273
- * prompt-cache prefix — stays byte-identical across a run of appends and shifts
274
- * only once per block instead of once per turn. That single shift is the only
275
- * message-cache miss the block costs.
276
- *
277
- * The block is at once (a) the cache-miss cadence — one prefix shift per
278
- * `EVICTION_BLOCK_TURNS` appends once a thread is over budget — and (b) the most
279
- * extra context ever sacrificed: snapping up drops up to `EVICTION_BLOCK_TURNS -
280
- * 1` oldest turns the budget alone would have kept, trading a little history for
281
- * a still prefix. 4 holds the prefix for ~4 turns at a cost of at most 3 turns of
282
- * headroom — negligible against a ~120k-token budget that spans far more turns,
283
- * while cutting cache misses on a long thread roughly fourfold. A turn-count
284
- * block (not a token block) is deliberate: a cache miss is triggered by the START
285
- * turn moving, a per-turn event, so counting in turns makes the miss cadence
286
- * exact and independent of how large any individual turn is.
287
- */
288
- export declare const EVICTION_BLOCK_TURNS = 4;
289
261
  /**
290
262
  * Create a `ThreadHistory` bound to a Postgres pool — a factory closure
291
263
  * capturing `pool` (dependency injection per the harness-durable-runtime spec). The `messages` table is