@manyoars/oars 0.4.1 → 0.5.2

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 (188) hide show
  1. package/README.md +79 -29
  2. package/dist/bin.js +3 -1
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +207 -21
  5. package/dist/club.d.ts +19 -0
  6. package/dist/club.js +132 -0
  7. package/dist/gate/hook-fill-main.js +1 -1
  8. package/dist/gate/hook-fill.d.ts +1 -1
  9. package/dist/gate/hook-fill.js +1 -1
  10. package/dist/gate/hook-main.js +7 -5
  11. package/dist/gate/hook.d.ts +12 -1
  12. package/dist/gate/hook.js +38 -7
  13. package/dist/hook-bin.js +23 -4
  14. package/dist/main.js +5 -0
  15. package/dist/node-floor.d.ts +10 -0
  16. package/dist/node-floor.js +23 -0
  17. package/dist/oars-hook.d.ts +2 -0
  18. package/dist/oars-hook.js +7 -0
  19. package/dist/sessions/allow.d.ts +1 -0
  20. package/dist/sessions/allow.js +1 -1
  21. package/dist/sessions/call-shape.d.ts +111 -0
  22. package/dist/sessions/call-shape.js +464 -0
  23. package/dist/sessions/candidates.d.ts +65 -0
  24. package/dist/sessions/candidates.js +236 -0
  25. package/dist/sessions/card-command.d.ts +24 -0
  26. package/dist/sessions/card-command.js +71 -0
  27. package/dist/sessions/card-font.d.ts +6 -0
  28. package/dist/sessions/card-font.js +36 -0
  29. package/dist/sessions/card-line.d.ts +30 -0
  30. package/dist/sessions/card-line.js +105 -0
  31. package/dist/sessions/card-render.d.ts +15 -0
  32. package/dist/sessions/card-render.js +146 -0
  33. package/dist/sessions/card.d.ts +59 -0
  34. package/dist/sessions/card.js +107 -0
  35. package/dist/sessions/cell-increments.d.ts +14 -3
  36. package/dist/sessions/cell-increments.js +79 -12
  37. package/dist/sessions/cells.d.ts +42 -4
  38. package/dist/sessions/cells.js +72 -18
  39. package/dist/sessions/codex-hook-bin.d.ts +1 -0
  40. package/dist/sessions/codex-hook-bin.js +24 -0
  41. package/dist/sessions/codex-hook-install.d.ts +21 -0
  42. package/dist/sessions/codex-hook-install.js +47 -0
  43. package/dist/sessions/codex-hook-view.d.ts +20 -0
  44. package/dist/sessions/codex-hook-view.js +20 -0
  45. package/dist/sessions/codex-hook.d.ts +77 -0
  46. package/dist/sessions/codex-hook.js +255 -0
  47. package/dist/sessions/codex.d.ts +9 -0
  48. package/dist/sessions/codex.js +104 -18
  49. package/dist/sessions/command.d.ts +17 -2
  50. package/dist/sessions/command.js +145 -33
  51. package/dist/sessions/copilot.d.ts +3 -0
  52. package/dist/sessions/copilot.js +12 -4
  53. package/dist/sessions/derive.js +2 -1
  54. package/dist/sessions/empty-state.d.ts +17 -0
  55. package/dist/sessions/empty-state.js +38 -0
  56. package/dist/sessions/exclusion.js +48 -3
  57. package/dist/sessions/extract.d.ts +16 -3
  58. package/dist/sessions/extract.js +281 -24
  59. package/dist/sessions/gemini.d.ts +2 -0
  60. package/dist/sessions/gemini.js +29 -2
  61. package/dist/sessions/harness-files.d.ts +27 -0
  62. package/dist/sessions/harness-files.js +109 -0
  63. package/dist/sessions/head-only.d.ts +7 -0
  64. package/dist/sessions/head-only.js +21 -0
  65. package/dist/sessions/hook-calls.js +4 -3
  66. package/dist/sessions/hooks.d.ts +1 -1
  67. package/dist/sessions/hooks.js +6 -2
  68. package/dist/sessions/identity.d.ts +6 -0
  69. package/dist/sessions/injected.d.ts +13 -0
  70. package/dist/sessions/injected.js +260 -0
  71. package/dist/sessions/install.d.ts +31 -20
  72. package/dist/sessions/install.js +80 -82
  73. package/dist/sessions/load-status.d.ts +41 -0
  74. package/dist/sessions/load-status.js +156 -0
  75. package/dist/sessions/machine-child-deps.d.ts +5 -0
  76. package/dist/sessions/machine-child-deps.js +83 -0
  77. package/dist/sessions/machine-child.d.ts +43 -0
  78. package/dist/sessions/machine-child.js +120 -0
  79. package/dist/sessions/machine-credential.d.ts +10 -0
  80. package/dist/sessions/machine-credential.js +20 -0
  81. package/dist/sessions/machine-enroll.d.ts +47 -0
  82. package/dist/sessions/machine-enroll.js +230 -0
  83. package/dist/sessions/machine-hold.d.ts +49 -0
  84. package/dist/sessions/machine-hold.js +88 -0
  85. package/dist/sessions/machine-ids.d.ts +6 -0
  86. package/dist/sessions/machine-ids.js +9 -0
  87. package/dist/sessions/machine-notice.d.ts +21 -0
  88. package/dist/sessions/machine-notice.js +89 -0
  89. package/dist/sessions/machine-pull.d.ts +40 -0
  90. package/dist/sessions/machine-pull.js +220 -0
  91. package/dist/sessions/machine-repo.d.ts +7 -0
  92. package/dist/sessions/machine-repo.js +30 -0
  93. package/dist/sessions/machine-scan-cache.d.ts +12 -0
  94. package/dist/sessions/machine-scan-cache.js +47 -0
  95. package/dist/sessions/machine-send.d.ts +12 -0
  96. package/dist/sessions/machine-send.js +156 -0
  97. package/dist/sessions/machine-stop.d.ts +22 -0
  98. package/dist/sessions/machine-stop.js +53 -0
  99. package/dist/sessions/machine.d.ts +41 -0
  100. package/dist/sessions/machine.js +89 -0
  101. package/dist/sessions/opencode.d.ts +2 -0
  102. package/dist/sessions/opencode.js +6 -0
  103. package/dist/sessions/otel.d.ts +21 -0
  104. package/dist/sessions/otel.js +109 -38
  105. package/dist/sessions/owner-only.d.ts +7 -0
  106. package/dist/sessions/owner-only.js +34 -0
  107. package/dist/sessions/pi.d.ts +13 -1
  108. package/dist/sessions/pi.js +27 -13
  109. package/dist/sessions/pool-books.d.ts +1 -1
  110. package/dist/sessions/pool-books.js +1 -1
  111. package/dist/sessions/pool-choices.d.ts +4 -2
  112. package/dist/sessions/pool-choices.js +4 -2
  113. package/dist/sessions/pool-command.d.ts +46 -6
  114. package/dist/sessions/pool-command.js +613 -136
  115. package/dist/sessions/pool-delta.d.ts +7 -0
  116. package/dist/sessions/pool-delta.js +28 -5
  117. package/dist/sessions/pool-due.d.ts +43 -0
  118. package/dist/sessions/pool-due.js +113 -0
  119. package/dist/sessions/pool-nightly.d.ts +9 -1
  120. package/dist/sessions/pool-nightly.js +65 -21
  121. package/dist/sessions/pool-outbox.d.ts +51 -5
  122. package/dist/sessions/pool-outbox.js +217 -24
  123. package/dist/sessions/pool-print.d.ts +1 -1
  124. package/dist/sessions/pool-raw.js +4 -3
  125. package/dist/sessions/pool-replica.d.ts +4 -4
  126. package/dist/sessions/pool-replica.js +26 -7
  127. package/dist/sessions/pool-send-lock.js +1 -1
  128. package/dist/sessions/pool-sent.d.ts +2 -0
  129. package/dist/sessions/pool-sent.js +21 -4
  130. package/dist/sessions/pool-wire.d.ts +176 -15
  131. package/dist/sessions/pool-wire.js +297 -33
  132. package/dist/sessions/pool.js +4 -2
  133. package/dist/sessions/public-vocabulary.d.ts +5 -0
  134. package/dist/sessions/public-vocabulary.js +16 -0
  135. package/dist/sessions/read-call-shape.js +12 -6
  136. package/dist/sessions/read-fit.d.ts +5 -0
  137. package/dist/sessions/read-fit.js +23 -2
  138. package/dist/sessions/read-interaction.js +1 -1
  139. package/dist/sessions/read-lead-lag.js +1 -1
  140. package/dist/sessions/read-readable.js +1 -1
  141. package/dist/sessions/read.d.ts +1 -1
  142. package/dist/sessions/recall-consequence.d.ts +2 -2
  143. package/dist/sessions/recall-consequence.js +14 -9
  144. package/dist/sessions/recall-object.d.ts +9 -2
  145. package/dist/sessions/receipt.d.ts +8 -0
  146. package/dist/sessions/receipt.js +78 -0
  147. package/dist/sessions/recovery-calls.d.ts +3 -2
  148. package/dist/sessions/recovery-calls.js +9 -3
  149. package/dist/sessions/redact.d.ts +11 -2
  150. package/dist/sessions/redact.js +201 -23
  151. package/dist/sessions/repo-root.d.ts +7 -0
  152. package/dist/sessions/repo-root.js +17 -13
  153. package/dist/sessions/reversion.d.ts +8 -0
  154. package/dist/sessions/reversion.js +114 -0
  155. package/dist/sessions/schema.d.ts +78 -4
  156. package/dist/sessions/schema.js +31 -1
  157. package/dist/sessions/session-shape.d.ts +2 -1
  158. package/dist/sessions/session-shape.js +15 -0
  159. package/dist/sessions/sources.d.ts +9 -0
  160. package/dist/sessions/sources.js +16 -5
  161. package/dist/sessions/steps.js +3 -2
  162. package/dist/sessions/store.d.ts +41 -2
  163. package/dist/sessions/store.js +68 -16
  164. package/dist/sessions/try-demo.d.ts +8 -0
  165. package/dist/sessions/try-demo.js +90 -0
  166. package/dist/sessions/try.d.ts +13 -0
  167. package/dist/sessions/try.js +50 -0
  168. package/dist/sessions/vscode-copilot.d.ts +4 -0
  169. package/dist/sessions/vscode-copilot.js +25 -18
  170. package/dist/telemetry/command.js +12 -6
  171. package/dist/telemetry/consent.d.ts +9 -3
  172. package/dist/telemetry/consent.js +25 -9
  173. package/dist/telemetry/fields.d.ts +11 -0
  174. package/dist/telemetry/fields.js +56 -0
  175. package/dist/telemetry/measures.d.ts +13 -0
  176. package/dist/telemetry/measures.js +30 -0
  177. package/dist/telemetry/observe.d.ts +15 -2
  178. package/dist/telemetry/observe.js +34 -7
  179. package/dist/telemetry/region.d.ts +6 -0
  180. package/dist/telemetry/region.js +28 -0
  181. package/dist/telemetry/report.js +1 -1
  182. package/dist/telemetry/schema.d.ts +3 -0
  183. package/dist/telemetry/schema.js +11 -1
  184. package/dist/telemetry/send.d.ts +5 -2
  185. package/dist/telemetry/send.js +15 -7
  186. package/dist/telemetry/words.d.ts +6 -0
  187. package/dist/telemetry/words.js +6 -0
  188. package/package.json +24 -5
@@ -1,17 +1,33 @@
1
1
  import { VOCAB_VERSION, type RepoSize } from './public-vocabulary.js';
2
- import { type ArgClass, type TargetClass } from './call-shape.js';
2
+ import { type ArgClass, type ArgFeature, type ArgName, type ArgValue, type ChangeKind, type DiffShape, type DirectoryKind, type ExtensionClass, type NameKind, type PathDepth, type PatternFeature, type TargetClass, type ValueSize } from './call-shape.js';
3
3
  import type { Cell } from './cells.js';
4
4
  import type { Redactor } from './redact.js';
5
5
  import type { Motif } from './motif.js';
6
+ import type { Recall } from './recall-object.js';
6
7
  import type { Read, ReadAsOf } from './read.js';
7
8
  import { type RecoveryCalls } from './recovery-calls.js';
8
- import { type PromptIntervention, type Frame, type FrameStack, type Harness, type LanguageShare, type PromptClass, type PromptObservation, type SessionObservation, type StepEdge, type StepObservation, type ToolObservation, type ToolStatus, type Usage } from './schema.js';
9
- export declare const SKELETON_FORMAT = 3;
9
+ import { type EditDigest, type PromptIntervention, type Frame, type FrameStack, type Harness, type LanguageShare, type PromptClass, type PromptObservation, type SessionObservation, type StepEdge, type StepObservation, type ToolObservation, type ToolStatus, type Usage } from './schema.js';
10
+ export declare const SKELETON_FORMAT = 7;
11
+ /** The formats the parser reads, oldest first: the client builds only the last. */
12
+ export declare const READ_FORMATS: readonly [3, 4, 5, 6, 7];
13
+ export type SkeletonFormat = (typeof READ_FORMATS)[number];
14
+ /** The tool fields format 4 added: a format 3 batch that holds one is holding a field it does not define. */
15
+ export declare const FORMAT_4_TOOL_FIELDS: readonly ["argFeatures", "argValues", "changeKind"];
16
+ /** The tool fields format 5 added: a batch of format 4 or 3 that holds one is holding a field it does not define. */
17
+ export declare const FORMAT_5_TOOL_FIELDS: readonly ["names", "namesDropped", "templates", "templatesDropped", "diffShape"];
18
+ /** The batch fields format 6 added: a batch of an older format that holds one is holding a field it does not define. */
19
+ export declare const FORMAT_6_BATCH_FIELDS: readonly ["recommendations"];
20
+ /** The format that added exposure. A batch of an older format holds no `recommendations`, and its failed calls are checked with the rule they were built under. */
21
+ export declare const EXPOSURE_FORMAT = 6;
22
+ /** The format that added edit digests. */
23
+ export declare const DIGEST_FORMAT = 7;
24
+ /** The tool fields format 7 added: a batch of format 6 or older that holds one is holding a field it does not define. */
25
+ export declare const FORMAT_7_TOOL_FIELDS: readonly ["digests"];
10
26
  /**
11
27
  * The version of the field list: every field name a batch can hold (`BATCH_FIELDS` in `pool-outbox.ts`). It moves with any field added, so a server told the version knows which names a batch may carry,
12
28
  * and a test pins the list to it (`pool-wire-additive.test.ts`). A field is deprecated and left on the list, never removed (conclusion section 17, rule 3).
13
29
  */
14
- export declare const FIELD_LIST_VERSION = 8;
30
+ export declare const FIELD_LIST_VERSION = 14;
15
31
  export declare const BUNDLE_FORMAT = 1;
16
32
  /** One constant: the pool serves only the vocabulary version the client holds. */
17
33
  export { VOCAB_VERSION };
@@ -84,8 +100,50 @@ export interface SkeletonTool {
84
100
  targetClass?: TargetClass | typeof OTHER;
85
101
  /** The classes of the call's arguments as a sorted set, derived at capture (`argClassOf`); never a value. Absent on a call captured before it. */
86
102
  argClass?: Array<ArgClass | typeof OTHER>;
103
+ /** Each sent key's value features (layer 1), sorted by key: closed-list members only, never the value. Only a key in `keys` has one. Absent when none is sent. */
104
+ argFeatures?: SkeletonArgFeature[];
105
+ /** Each sent key's closed value (layer 1): a boolean as `true` or `false`, or a member of its tool's list in `CLOSED_ARG_VALUES`. Only a key in `keys` has one. Absent when none is sent. */
106
+ argValues?: SkeletonArgValue[];
107
+ /** What changed from the previous call of the same tool in the same prompt (layer 1), a sorted set of `CHANGE_KINDS` members. Absent on the first such call and on a call captured before it. */
108
+ changeKind?: Array<ChangeKind | typeof OTHER>;
109
+ /** The name tokens of the call's values (layer 2), sorted by kind and name: file, directory, and variable names, flag values that are names, a custom agent's name. Each passed the one gate (`wireName`); never a value. Absent when none is sent. */
110
+ names?: SkeletonArgName[];
111
+ /** A `count` bucket of the name tokens the call held that were not sent: one the redactor changes, an exclusion term matches, or that has no name shape. Absent when none was dropped; never the names. */
112
+ namesDropped?: number;
113
+ /** The old and new text of an Edit (one pair), a MultiEdit (one pair per edit, in order), or a Write (a new digest only), each a digest of the exact text, plain so the same text matches across sessions. Never the text. Absent on any other call. */
114
+ digests?: SkeletonDigest[];
115
+ /** One template per shell command of the call (layer 3), in the order the commands run: its program, subcommand, and flags, and every literal argument as a slot of `TEMPLATE_SLOTS`. Each kept word passed the one gate (`wireName`, `wireFlag`); never an argument. Absent when none is sent. */
116
+ templates?: string[];
117
+ /** A `count` bucket of the templates the call held that were not sent: one with a kept word the redactor changes, an exclusion term matches, or that has no name shape. Absent when none was dropped; never the templates. */
118
+ templatesDropped?: number;
119
+ /** What an edit did (layer 3), a sorted set of `DIFF_SHAPES` members: the shape of the change and never its text. Absent for a call that is no edit and for one that changed nothing. */
120
+ diffShape?: Array<DiffShape | typeof OTHER>;
87
121
  steps: SkeletonStep[];
88
122
  }
123
+ /** One edit's digests: the first 32 hex digits of the SHA-256 of the exact UTF-8 text. A Write has `new` alone, never the digest of an empty string for `old`. */
124
+ export interface SkeletonDigest {
125
+ old?: string;
126
+ new: string;
127
+ }
128
+ /** One sent key's value features as the wire holds them: each a closed-list member, or `other` for one this reader does not know. */
129
+ export interface SkeletonArgFeature {
130
+ key: string;
131
+ valueSize: ValueSize | typeof OTHER;
132
+ pathDepth?: PathDepth | typeof OTHER;
133
+ extension?: ExtensionClass | typeof OTHER;
134
+ dirKind?: DirectoryKind | typeof OTHER;
135
+ patternFeatures?: Array<PatternFeature | typeof OTHER>;
136
+ }
137
+ /** One name token as the wire holds it: its kind from the closed list (`other` for one this reader does not know) and the name as sent, which has the shape of a name (`other` when it has none). */
138
+ export interface SkeletonArgName {
139
+ kind: NameKind | typeof OTHER;
140
+ name: string;
141
+ }
142
+ /** One sent key's closed value as the wire holds it, or `other` for one off the list this reader holds. */
143
+ export interface SkeletonArgValue {
144
+ key: string;
145
+ enumValue: string;
146
+ }
89
147
  /**
90
148
  * A prompt's usage as `tokens` buckets: `thinking` is a token count (the thinking tokens of the output), so it takes the same edges as the rest. A category the source
91
149
  * never recorded is null, never the bucket of zero: a prompt with no counts at all sends five nulls, and a partial total sends a number only for the categories it observed.
@@ -117,6 +175,17 @@ export type Team = (typeof TEAMS)[number];
117
175
  /** Whether the repository is public or private (an operator's setting, read locally, never looked up). */
118
176
  export declare const REPO_VISIBILITIES: readonly ["public", "private", "unknown"];
119
177
  export type RepoVisibility = (typeof REPO_VISIBILITIES)[number];
178
+ /** Where a session ran, as a trusted machine states it for a batch it admitted: the five host classes an enrollment knows (`HOST_CLASSES` in `machine.ts`, not imported: the pool bundles this file). */
179
+ export declare const CLAIMED_HOST_CLASSES: readonly ["local", "vps", "cloud", "ci", "hosted"];
180
+ export type ClaimedHostClass = (typeof CLAIMED_HOST_CLASSES)[number];
181
+ /** What started the session, as an enrollment declares it. */
182
+ export declare const CLAIMED_LAUNCHERS: readonly ["interactive", "orchestrated", "scheduled", "ci", "hosted-run", "unknown"];
183
+ export type ClaimedLauncher = (typeof CLAIMED_LAUNCHERS)[number];
184
+ /** The host class and launcher the trusted machine states for a batch a cloud VM held: a claim of the depositor's own machine, never a fact the pool stamped. `other` is a value this reader does not know. */
185
+ export interface Claimed {
186
+ hostClass: ClaimedHostClass | typeof OTHER;
187
+ launcher: ClaimedLauncher | typeof OTHER;
188
+ }
120
189
  /** What the pool can state about whom a deposit covers. It is not a filter: no read uses it. Anything not read locally is `unknown`. */
121
190
  export interface Coverage {
122
191
  orgSize: OrgSize;
@@ -188,8 +257,22 @@ export interface DeltaEntry {
188
257
  metric: DeltaMetric | typeof OTHER;
189
258
  change: number;
190
259
  }
260
+ /** Whether a recommendation reached the asker (`shown`) or was withheld by the holdback (`held`). The local row's arm, as the closed list holds it. */
261
+ export declare const RECOMMENDATION_ARMS: readonly ["shown", "held"];
262
+ export type RecommendationArm = (typeof RECOMMENDATION_ARMS)[number];
263
+ /**
264
+ * One recommendation of the session as the local row holds it: its `id`, the `arm` it was drawn into, the `poolVersion` it answered from, and the window of calls it covers, `from` up to but not including `to`, as positions in the
265
+ * main run's calls that are not sidechain (the line the local consequence window reads). It holds no text, query, or evidence. `other` is an arm this reader does not know.
266
+ */
267
+ export interface SkeletonRecommendation {
268
+ id: string;
269
+ arm: RecommendationArm | typeof OTHER;
270
+ poolVersion: string;
271
+ from: number;
272
+ to: number;
273
+ }
191
274
  export interface SessionSkeleton {
192
- format: typeof SKELETON_FORMAT;
275
+ format: SkeletonFormat;
193
276
  /** The vocabulary version the client built the batch under: stored with it, so a read can tell a batch of an older list from a current one. */
194
277
  vocabVersion: string;
195
278
  /** `FIELD_LIST_VERSION` as the client held it: the fields a batch of this version may carry. */
@@ -200,8 +283,12 @@ export interface SessionSkeleton {
200
283
  transcripts: SkeletonTranscript[];
201
284
  /** One for the batch: a hash of the main transcript's non-null call durations in call order, only with `MIN_TIMED_CALLS` of them; a subagent's calls never join it. */
202
285
  timingPrint: string | null;
286
+ /** Only on a batch a trusted machine admitted from a held branch: the machine writes it from its own enrollment record, never the client that built the batch. */
287
+ claimed?: Claimed;
203
288
  /** The batch's client-built delta entries (Section 2, "Deltas"): changes between the client's own before and after windows, each carried once, by the batch of the session that filled the after window. */
204
289
  deltas: DeltaEntry[];
290
+ /** The recommendations the main session was shown or held back from (format 6), in window order. Absent when it had none, and a pool reads absent as unknown exposure, never as unexposed. */
291
+ recommendations?: SkeletonRecommendation[];
205
292
  }
206
293
  /** One main session and the subagents it spawned, as the local store holds them. */
207
294
  export interface SessionRecords {
@@ -223,12 +310,15 @@ export interface TranscriptRoot {
223
310
  export declare const MIN_TIMED_CALLS = 50;
224
311
  /** A session has ended once no transcript of it has gained a line for this long (`session_idle_hours`, spec Section 7). */
225
312
  export declare const SESSION_IDLE_HOURS = 6;
313
+ /** No session leaves this machine sooner than this after it ends, whatever `session_idle_hours` is: time for `oars sessions deposit --deny` or a delete to act on it first. Today the longer idle window governs; this is the floor under it. */
314
+ export declare const HOLD_WINDOW_MS: number;
226
315
  /**
227
- * Whether a session's batch may be built at `now`: no transcript of it, main or subagent, has gained a line for `SESSION_IDLE_HOURS`. A transcript gains a line when capture sees it change, which
228
- * stamps a new `rev` in epoch milliseconds, but a transcript can grow after the last capture, so `written` (the newest write to any raw file of the session, 0 when none is known) counts too: the
229
- * session was last active at the later of the two. A subagent that died without an end marker holds its session back at most that long.
316
+ * Whether a session's batch may be built at `now`: no transcript of it, main or subagent, has gained a line for `SESSION_IDLE_HOURS`. A transcript was last active at its own last line (`tsLast`, the
317
+ * session's clock, not ours), or at its capture (`rev`, epoch milliseconds) when it has none, so a store captured a minute ago from days-old transcripts holds sessions that ended days ago. A transcript can
318
+ * also grow after the last capture, so `written` (the newest write to any raw file of the session, 0 when none is known) counts when it is later than every capture: a write at or before the capture is the
319
+ * file arriving, not the session going on. A last line later than the capture is a bad clock, and the capture caps it. A person's build (`sender` false) takes the ended session at once. The sender, which builds and sends in one run, also waits `HOLD_WINDOW_MS` after the newest capture, so a session oars is seeing for the first time (a days-old transcript of a new harness) leaves no sooner than an hour later, time for `--deny` or a delete. A subagent that died without an end marker holds its session back at most that long.
230
320
  */
231
- export declare const hasEnded: (records: SessionRecords, now: number, written: number) => boolean;
321
+ export declare const hasEnded: (records: SessionRecords, now: number, written: number, idleMs?: number, sender?: boolean) => boolean;
232
322
  /** Every main session of a store, with its records. */
233
323
  export declare const sessionsOf: (store: {
234
324
  sessions: readonly SessionObservation[];
@@ -262,18 +352,64 @@ export declare const OPEN_GATE: WireGate;
262
352
  * `NAME_MAX` characters, because a secret, an employer's name, or a mis-parsed command is not a name and nothing downstream can take it back. `keys` (t870) sends its names through this same function.
263
353
  */
264
354
  export declare const wireName: (gate: WireGate, name: string, hasShape?: (name: string) => boolean) => string;
355
+ /**
356
+ * A call's key names as the wire holds them (t870): names only, never a value. A public tool (one with a pinned input list) sends the names on its list and counts the rest; any other tool sends a name only when it passes the
357
+ * name gate, and a tool that went as `private` sends none, so a private tool's keys name no private work. `dropped` counts the distinct names not sent.
358
+ */
359
+ export declare const wireKeys: (stored: readonly string[], native: string | undefined, gate: WireGate) => {
360
+ keys: string[];
361
+ dropped: number;
362
+ };
363
+ /** Whether a closed value is one the wire may carry for a tool's key: a boolean's two words, or a member of the tool's list. */
364
+ export declare const isClosedValue: (native: string | undefined, key: string, value: string) => boolean;
365
+ /**
366
+ * A call's value features as the wire sends them (layer 1): only a sent key's, and only closed-list members, so a hand-edited record never puts a value on the wire. An entry whose size is off its list is dropped whole, a
367
+ * path or pattern field off its list is left out, and a pattern holding no listed feature sends none.
368
+ */
369
+ export declare const wireFeatures: (stored: readonly ArgFeature[] | undefined, sent: ReadonlySet<string>) => ArgFeature[];
370
+ /** A call's closed values as the wire sends them (layer 1): only a sent key's, and only a value `isClosedValue` admits. */
371
+ export declare const wireValues: (stored: readonly ArgValue[] | undefined, sent: ReadonlySet<string>, native: string | undefined) => ArgValue[];
372
+ /** A call's change kinds as the wire sends them: the closed-list members, in the list's order. */
373
+ export declare const wireChange: (stored: readonly ChangeKind[] | undefined) => ChangeKind[];
374
+ /** A call's diff shapes as the wire sends them: the closed-list members, in the list's order. */
375
+ export declare const wireDiffShape: (stored: readonly DiffShape[] | undefined) => DiffShape[];
376
+ /**
377
+ * A call's name tokens as the wire sends them (layer 2): every stored token whose kind is on the closed list, through the one gate (`wireName`): a token the operator's exclusion terms or the redactor's secret shapes match, or that has no name shape,
378
+ * is dropped and counted in `dropped`. No floor, no threshold: a name is sent as it is.
379
+ */
380
+ export declare const wireNames: (stored: readonly ArgName[] | undefined, gate: WireGate) => {
381
+ names: ArgName[];
382
+ dropped: number;
383
+ };
384
+ /** A call's edit digests as the wire sends them: a pair whose digest is not that shape is dropped whole, so a corrupt store row costs the pair and never the deposit. */
385
+ export declare const wireDigests: (stored: readonly EditDigest[] | undefined) => SkeletonDigest[];
386
+ /** Whether a received template has the shape the wire sends: the pool's check, which holds no operator terms and no redactor. */
387
+ export declare const isWireTemplate: (template: string) => boolean;
388
+ /**
389
+ * A call's command templates as the wire sends them (layer 3): every stored template whose kept words (program, subcommand, flags) all clear the one gate, as a name or a flag does. A template with a word the redactor changes, an exclusion term matches, or that
390
+ * has no name shape is dropped whole and counted in `dropped`. No floor, no threshold: a template is sent as it is, and a literal is only ever a slot.
391
+ */
392
+ export declare const wireTemplates: (stored: readonly string[] | undefined, gate: WireGate) => {
393
+ templates: string[];
394
+ dropped: number;
395
+ };
265
396
  /**
266
397
  * A stored tool's steps as the wire holds them: each shell step's identity is replaced by the projected command, and every long-tail name (a native name, MCP server, skill, host, program, or pull name) is
267
398
  * sent as it is after the gate, or `private` when it counts as redacted. A `private` program holds no pull. The one place a deposit and a local read take it from.
268
399
  */
269
400
  export declare const projectedSteps: (tool: ToolObservation, read: ShellReader, harness: Harness, gate?: WireGate) => StepObservation[];
401
+ /**
402
+ * The recommendations of one session, from the local rows after `deriveConsequences` has given each its window. Only a row that showed or withheld something is carried: a miss recommended nothing, so it is neither shown nor held, and
403
+ * a row with no window has no calls to place. They go in window order, then by id, so one store builds one batch.
404
+ */
405
+ export declare const recommendationsOf: (recalls: readonly Recall[], session: string) => SkeletonRecommendation[];
270
406
  /** The hash a batch's timing print is made with, over the durations in call order: the client's `contentHash` (D1's `hP`). */
271
407
  export type Print = (durations: readonly number[]) => string;
272
408
  /**
273
409
  * The skeleton of a session; null when any record of it was captured before steps and frames, or a transcript of it has no root, which holds no closed reading to send. The batch holds the main
274
410
  * transcript's run first, then each subagent's as its own run; its `id` is the main session's, and its one `timingPrint` is over the main transcript's calls alone.
275
411
  */
276
- export declare const skeletonOf: (records: SessionRecords, id: string, read: ShellReader, print: Print, deltas?: readonly DeltaEntry[], gate?: WireGate, coverage?: Coverage) => SessionSkeleton | null;
412
+ export declare const skeletonOf: (records: SessionRecords, id: string, read: ShellReader, print: Print, deltas?: readonly DeltaEntry[], gate?: WireGate, coverage?: Coverage, recommendations?: readonly SkeletonRecommendation[]) => SessionSkeleton | null;
277
413
  /**
278
414
  * The version bucket of a session that recorded none: Cursor, Gemini, and Grok Build keep no harness version in their local files, and neither does a VS Code Copilot Chat session whose requests carry no `agent.extensionVersion`, so their cells are
279
415
  * `<harness>/unknown/<model>`. It is the one non-numeric word a bundle can be asked for, so those harnesses are served the cells they have.
@@ -304,23 +440,27 @@ export interface Extension {
304
440
  /** The fields a client may send a literal beside (`<field>Literal`) when the field itself says `other`: the enumerated fields, whose values a closed list holds. */
305
441
  export declare const ENUMERATED_FIELDS: ReadonlySet<string>;
306
442
  /**
307
- * The fields that may be absent at format 3, by the level of the batch that holds them. An absent one reads as null, or as empty for a list, exactly as a sent null does, so a batch with all of them left out is
443
+ * The fields that may be absent at formats 3, 4, and 5 (a format 4 batch reads `OPTIONAL.tool` less `FORMAT_5_TOOL_FIELDS`, and a format 3 batch also less `FORMAT_4_TOOL_FIELDS`), by the level of the batch that holds them. An absent one reads as null, or as empty for a list, exactly as a sent null does, so a batch with all of them left out is
308
444
  * served from what remains. A field the cells need to be sound (a harness, a status, a bucket of tokens) is never here.
309
445
  */
310
446
  export declare const OPTIONAL: {
311
- readonly batch: readonly ["timingPrint", "deltas"];
447
+ readonly batch: readonly ["timingPrint", "deltas", "claimed", "recommendations"];
312
448
  readonly frame: readonly ["harnessVersion", "model", "effort", "day", "shell", "reach", "repoKey", "orgSize", "team", "repoVisibility", "hour"];
313
449
  readonly stack: readonly ["size", "languageShares"];
314
450
  readonly prompt: readonly ["wallSec", "explore", "usageResponses", "intervention"];
315
- readonly tool: readonly ["prompt", "durationMs", "errorCode", "recoveryCalls", "keys", "keysDropped", "targetClass", "argClass"];
451
+ readonly tool: readonly ["prompt", "durationMs", "errorCode", "recoveryCalls", "keys", "keysDropped", "targetClass", "argClass", "argFeatures", "argValues", "changeKind", "names", "namesDropped", "templates", "templatesDropped", "diffShape", "digests"];
316
452
  readonly step: readonly ["tokens", "ms", "allocated", "parent", "skill", "edges", "remainingTokens"];
317
453
  readonly transcript: readonly ["spawnedIn"];
318
454
  };
319
455
  /** The most bytes (as JSON) one field this reader does not know, or one literal, may hold: an enumerated value or a literal never needs more, and a newer client's larger structure belongs in a new format version. The deposit's own cap is no part of this. */
320
456
  export declare const MAX_EXTENSION_BYTES: number;
321
457
  export declare const HARNESSES: readonly ["claude-code", "cursor", "codex", "copilot", "gemini", "grok", "opencode", "pi", "vscode-copilot", "otel"];
458
+ export declare const PLATFORMS: ReadonlySet<string>;
459
+ export declare const SHELLS: ReadonlySet<string>;
322
460
  /** The registries a package comes from; a pull may also come from a skill, plugin, or MCP registry. */
323
461
  export declare const PACKAGE_REGISTRIES: readonly ["npm", "pypi", "crates", "go", "rubygems", "homebrew"];
462
+ /** Whether the harness's table names this native, so it can cross as itself; anything else (including the literal) crosses as `private`. */
463
+ export declare const admittedNative: (harness: WireHarness, native: string) => boolean;
324
464
  /** A parsed batch: the skeleton every derivation reads, the bag of what this reader did not know, and the count of values it read as `other`. Only the skeleton is ever served from. */
325
465
  export interface ParsedSkeleton {
326
466
  ok: true;
@@ -347,6 +487,8 @@ export interface StrataCell {
347
487
  export interface BundleFloors {
348
488
  public: number;
349
489
  disclosure: number;
490
+ /** The floor a cell of closed public vocabulary is served at, at most `public`. Absent in a bundle signed before the pool split its floor by cell class. */
491
+ clear?: number;
350
492
  families?: FamilyFloors;
351
493
  }
352
494
  /** A floor per read family, keyed by the family's name as the pool states it. A client applies none and prints only the families it knows, so a name this version has never heard of (a family a later pool adds) is carried as stated and not refused. */
@@ -401,7 +543,7 @@ export interface Bundle {
401
543
  harness: Harness;
402
544
  harnessVersion: string;
403
545
  vocabVersion: string;
404
- /** The public floor the pool applied (`floors.public`): every cell and read is at or above it except a family on a lower floor of its own, which states its floor on each read and in `floors.families`. */
546
+ /** The public floor the pool applied (`floors.public`): every cell and read is at or above it except a family on a lower floor of its own, which states its floor on each read and in `floors.families`. A clear cell is held to `floors.clear`, so a read on clear cells alone states that floor, the lowest among the cells it cites. */
405
547
  floor: number;
406
548
  asOf: ReadAsOf;
407
549
  cells: Cell[];
@@ -415,18 +557,37 @@ export interface Bundle {
415
557
  }
416
558
  /** The signature covers these exact bytes, so nothing has to be canonicalized on either side. */
417
559
  export interface SignedBundle {
560
+ /** Names the signing key (S17). A bundle with no `kid` is read as `LEGACY_KEY_ID`, the name a pre-key-id sign-in pins its one key under. */
561
+ kid?: string;
418
562
  payload: string;
419
563
  /** Ed25519 over the payload's UTF-8 bytes, in base64. */
420
564
  signature: string;
421
565
  }
566
+ /** The key id of a bundle that names none, and of a sign-in file written before key ids: the pool's default `BUNDLE_KEY_ID`. */
567
+ export declare const LEGACY_KEY_ID = "k1";
568
+ /** Key ids this release no longer trusts: the way a leaked signing key is rotated out (docs/pool.md, "Rotating the bundle signing key"). A bundle signed under one is refused even when its key is pinned. */
569
+ export declare const RETIRED_KEY_IDS: ReadonlySet<string>;
422
570
  /** The public half of the pool's key, as a client pins it at login. */
423
571
  export interface PinnedKey {
424
572
  kty: string;
425
573
  crv: string;
426
574
  x: string;
427
575
  }
576
+ /** The keys pinned for one server, by key id. One entry until the pool rotates its key. */
577
+ export interface PinnedKeys {
578
+ [kid: string]: PinnedKey;
579
+ }
580
+ /**
581
+ * Public keys this release of oars ships, by key id: the only way a key id the login did not pin becomes trusted, because a server at a pool's URL must not be able to introduce a key by naming a new id (S17). Empty until the pool's first rotation
582
+ * (docs/pool.md, "Rotating the bundle signing key"); a bundle is checked against the keys pinned at login and these, a shipped key winning under a shared id, so a server cannot shadow it with a key of its own.
583
+ */
584
+ export declare const RELEASE_KEYS: Readonly<PinnedKeys>;
585
+ /** The first key id a login offers that the server's entry does not hold and no release ships, or none: such an id could only have come from the server. */
586
+ export declare const unpinnedKid: (held: PinnedKeys, offered: PinnedKeys, released?: PinnedKeys) => string | undefined;
587
+ /** A key id as the pool sends them: letters, digits, dot, dash, and underscore, 1 to 32 characters. */
588
+ export declare const isKeyId: (kid: string) => boolean;
428
589
  /** The bundle, only when the pinned key signed these bytes for the harness and version that were asked for: another harness's or version's bundle, under a good signature, is still the wrong answer. */
429
- export declare const verifyBundle: (signed: unknown, key: PinnedKey, harness: Harness, harnessVersion: string) => Promise<{
590
+ export declare const verifyBundle: (signed: unknown, keys: PinnedKeys, harness: Harness, harnessVersion: string, retired?: ReadonlySet<string>, released?: PinnedKeys) => Promise<{
430
591
  ok: true;
431
592
  bundle: Bundle;
432
593
  } | {