@manyoars/oars 0.1.1 → 0.3.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 (240) hide show
  1. package/README.md +134 -26
  2. package/dist/api.js +1 -1
  3. package/dist/bin.js +6 -29
  4. package/dist/cli.d.ts +6 -3
  5. package/dist/cli.js +370 -72
  6. package/dist/commands/keys.d.ts +31 -0
  7. package/dist/commands/keys.js +65 -0
  8. package/dist/commands/login.d.ts +1 -1
  9. package/dist/commands/login.js +3 -5
  10. package/dist/errors.d.ts +13 -13
  11. package/dist/errors.js +28 -11
  12. package/dist/gate/checks.d.ts +68 -0
  13. package/dist/gate/checks.js +584 -0
  14. package/dist/gate/command.d.ts +14 -0
  15. package/dist/gate/command.js +61 -0
  16. package/dist/gate/hook-fill-main.d.ts +1 -0
  17. package/dist/gate/hook-fill-main.js +16 -0
  18. package/dist/gate/hook-fill.d.ts +38 -0
  19. package/dist/gate/hook-fill.js +94 -0
  20. package/dist/gate/hook-main.d.ts +1 -0
  21. package/dist/gate/hook-main.js +35 -0
  22. package/dist/gate/hook-process.d.ts +14 -0
  23. package/dist/gate/hook-process.js +64 -0
  24. package/dist/gate/hook.d.ts +46 -0
  25. package/dist/gate/hook.js +256 -0
  26. package/dist/gate/install.d.ts +25 -0
  27. package/dist/gate/install.js +126 -0
  28. package/dist/gate/local-bin.d.ts +8 -0
  29. package/dist/gate/local-bin.js +36 -0
  30. package/dist/gate/notes.d.ts +19 -0
  31. package/dist/gate/notes.js +27 -0
  32. package/dist/gate/novelty.d.ts +35 -0
  33. package/dist/gate/novelty.js +99 -0
  34. package/dist/gate/policy.d.ts +25 -0
  35. package/dist/gate/policy.js +73 -0
  36. package/dist/gate/record.d.ts +120 -0
  37. package/dist/gate/record.js +125 -0
  38. package/dist/gate/registry-state.d.ts +10 -0
  39. package/dist/gate/registry-state.js +30 -0
  40. package/dist/gate/registry.d.ts +56 -0
  41. package/dist/gate/registry.js +94 -0
  42. package/dist/gate/replay.d.ts +20 -0
  43. package/dist/gate/replay.js +257 -0
  44. package/dist/gate/report.d.ts +50 -0
  45. package/dist/gate/report.js +89 -0
  46. package/dist/gate/scope.d.ts +7 -0
  47. package/dist/gate/scope.js +27 -0
  48. package/dist/gate/transcripts.d.ts +68 -0
  49. package/dist/gate/transcripts.js +232 -0
  50. package/dist/hook-bin.d.ts +1 -0
  51. package/dist/hook-bin.js +25 -0
  52. package/dist/issuer.d.ts +16 -0
  53. package/dist/issuer.js +55 -0
  54. package/dist/main.d.ts +1 -0
  55. package/dist/main.js +64 -0
  56. package/dist/oidc.js +1 -1
  57. package/dist/sessions/actions.d.ts +35 -0
  58. package/dist/sessions/actions.js +351 -0
  59. package/dist/sessions/allow.d.ts +14 -0
  60. package/dist/sessions/allow.js +51 -0
  61. package/dist/sessions/archive.d.ts +11 -0
  62. package/dist/sessions/archive.js +38 -0
  63. package/dist/sessions/audit.d.ts +42 -0
  64. package/dist/sessions/audit.js +104 -0
  65. package/dist/sessions/baseline.d.ts +62 -0
  66. package/dist/sessions/baseline.js +188 -0
  67. package/dist/sessions/capture-runtime.d.ts +10 -0
  68. package/dist/sessions/capture-runtime.js +12 -0
  69. package/dist/sessions/cell-increments.d.ts +43 -0
  70. package/dist/sessions/cell-increments.js +209 -0
  71. package/dist/sessions/cells.d.ts +79 -0
  72. package/dist/sessions/cells.js +181 -0
  73. package/dist/sessions/codex.d.ts +53 -0
  74. package/dist/sessions/codex.js +679 -0
  75. package/dist/sessions/command.d.ts +117 -0
  76. package/dist/sessions/command.js +373 -0
  77. package/dist/sessions/copilot.d.ts +40 -0
  78. package/dist/sessions/copilot.js +432 -0
  79. package/dist/sessions/cursor.d.ts +24 -0
  80. package/dist/sessions/cursor.js +324 -0
  81. package/dist/sessions/derive.d.ts +57 -0
  82. package/dist/sessions/derive.js +320 -0
  83. package/dist/sessions/exclusion.d.ts +81 -0
  84. package/dist/sessions/exclusion.js +353 -0
  85. package/dist/sessions/extract.d.ts +179 -0
  86. package/dist/sessions/extract.js +1774 -0
  87. package/dist/sessions/fold.d.ts +17 -0
  88. package/dist/sessions/fold.js +71 -0
  89. package/dist/sessions/frame.d.ts +24 -0
  90. package/dist/sessions/frame.js +95 -0
  91. package/dist/sessions/gemini.d.ts +37 -0
  92. package/dist/sessions/gemini.js +613 -0
  93. package/dist/sessions/gold-arms.d.ts +67 -0
  94. package/dist/sessions/gold-arms.js +172 -0
  95. package/dist/sessions/gold.d.ts +197 -0
  96. package/dist/sessions/gold.js +463 -0
  97. package/dist/sessions/graph.d.ts +12 -0
  98. package/dist/sessions/graph.js +34 -0
  99. package/dist/sessions/grok.d.ts +36 -0
  100. package/dist/sessions/grok.js +421 -0
  101. package/dist/sessions/hook-calls.d.ts +3 -0
  102. package/dist/sessions/hook-calls.js +47 -0
  103. package/dist/sessions/hook-index.d.ts +53 -0
  104. package/dist/sessions/hook-index.js +157 -0
  105. package/dist/sessions/hooks.d.ts +13 -0
  106. package/dist/sessions/hooks.js +170 -0
  107. package/dist/sessions/identity.d.ts +22 -0
  108. package/dist/sessions/identity.js +101 -0
  109. package/dist/sessions/install.d.ts +54 -0
  110. package/dist/sessions/install.js +201 -0
  111. package/dist/sessions/lineage.d.ts +19 -0
  112. package/dist/sessions/lineage.js +118 -0
  113. package/dist/sessions/mcp.d.ts +6 -0
  114. package/dist/sessions/mcp.js +153 -0
  115. package/dist/sessions/merkle.d.ts +7 -0
  116. package/dist/sessions/merkle.js +28 -0
  117. package/dist/sessions/motif.d.ts +43 -0
  118. package/dist/sessions/motif.js +59 -0
  119. package/dist/sessions/package-resolve.d.ts +30 -0
  120. package/dist/sessions/package-resolve.js +183 -0
  121. package/dist/sessions/pending.d.ts +34 -0
  122. package/dist/sessions/pending.js +142 -0
  123. package/dist/sessions/pool-command.d.ts +44 -0
  124. package/dist/sessions/pool-command.js +542 -0
  125. package/dist/sessions/pool-delta.d.ts +54 -0
  126. package/dist/sessions/pool-delta.js +190 -0
  127. package/dist/sessions/pool-outbox.d.ts +63 -0
  128. package/dist/sessions/pool-outbox.js +260 -0
  129. package/dist/sessions/pool-print.d.ts +26 -0
  130. package/dist/sessions/pool-print.js +68 -0
  131. package/dist/sessions/pool-wire.d.ts +225 -0
  132. package/dist/sessions/pool-wire.js +620 -0
  133. package/dist/sessions/pool.d.ts +32 -0
  134. package/dist/sessions/pool.js +164 -0
  135. package/dist/sessions/projection.d.ts +75 -0
  136. package/dist/sessions/projection.js +165 -0
  137. package/dist/sessions/public-vocabulary.d.ts +73 -0
  138. package/dist/sessions/public-vocabulary.js +302 -0
  139. package/dist/sessions/query.d.ts +111 -0
  140. package/dist/sessions/query.js +246 -0
  141. package/dist/sessions/read-adoption.d.ts +2 -0
  142. package/dist/sessions/read-adoption.js +27 -0
  143. package/dist/sessions/read-call-shape.d.ts +2 -0
  144. package/dist/sessions/read-call-shape.js +25 -0
  145. package/dist/sessions/read-change.d.ts +2 -0
  146. package/dist/sessions/read-change.js +30 -0
  147. package/dist/sessions/read-cost.d.ts +4 -0
  148. package/dist/sessions/read-cost.js +37 -0
  149. package/dist/sessions/read-day-move.d.ts +3 -0
  150. package/dist/sessions/read-day-move.js +65 -0
  151. package/dist/sessions/read-fit.d.ts +7 -0
  152. package/dist/sessions/read-fit.js +41 -0
  153. package/dist/sessions/read-interaction.d.ts +5 -0
  154. package/dist/sessions/read-interaction.js +62 -0
  155. package/dist/sessions/read-lead-lag.d.ts +15 -0
  156. package/dist/sessions/read-lead-lag.js +81 -0
  157. package/dist/sessions/read-live.d.ts +6 -0
  158. package/dist/sessions/read-live.js +38 -0
  159. package/dist/sessions/read-method.d.ts +2 -0
  160. package/dist/sessions/read-method.js +29 -0
  161. package/dist/sessions/read-next-step.d.ts +2 -0
  162. package/dist/sessions/read-next-step.js +35 -0
  163. package/dist/sessions/read-order.d.ts +54 -0
  164. package/dist/sessions/read-order.js +62 -0
  165. package/dist/sessions/read-readable.d.ts +8 -0
  166. package/dist/sessions/read-readable.js +24 -0
  167. package/dist/sessions/read-recovery.d.ts +20 -0
  168. package/dist/sessions/read-recovery.js +97 -0
  169. package/dist/sessions/read-rows.d.ts +13 -0
  170. package/dist/sessions/read-rows.js +47 -0
  171. package/dist/sessions/read-substitution.d.ts +5 -0
  172. package/dist/sessions/read-substitution.js +51 -0
  173. package/dist/sessions/read-support.d.ts +48 -0
  174. package/dist/sessions/read-support.js +73 -0
  175. package/dist/sessions/read-tool-day.d.ts +2 -0
  176. package/dist/sessions/read-tool-day.js +26 -0
  177. package/dist/sessions/read-version-boundary.d.ts +31 -0
  178. package/dist/sessions/read-version-boundary.js +95 -0
  179. package/dist/sessions/read.d.ts +79 -0
  180. package/dist/sessions/read.js +84 -0
  181. package/dist/sessions/recall-consequence.d.ts +45 -0
  182. package/dist/sessions/recall-consequence.js +179 -0
  183. package/dist/sessions/recall-object.d.ts +137 -0
  184. package/dist/sessions/recall-object.js +77 -0
  185. package/dist/sessions/recall-pool.d.ts +19 -0
  186. package/dist/sessions/recall-pool.js +96 -0
  187. package/dist/sessions/recall-push.d.ts +26 -0
  188. package/dist/sessions/recall-push.js +95 -0
  189. package/dist/sessions/recall-reads.d.ts +117 -0
  190. package/dist/sessions/recall-reads.js +410 -0
  191. package/dist/sessions/recall-render.d.ts +19 -0
  192. package/dist/sessions/recall-render.js +168 -0
  193. package/dist/sessions/redact.d.ts +6 -0
  194. package/dist/sessions/redact.js +54 -0
  195. package/dist/sessions/repo-root.d.ts +10 -0
  196. package/dist/sessions/repo-root.js +101 -0
  197. package/dist/sessions/schema.d.ts +644 -0
  198. package/dist/sessions/schema.js +148 -0
  199. package/dist/sessions/session-shape.d.ts +73 -0
  200. package/dist/sessions/session-shape.js +342 -0
  201. package/dist/sessions/sources.d.ts +50 -0
  202. package/dist/sessions/sources.js +159 -0
  203. package/dist/sessions/steps.d.ts +105 -0
  204. package/dist/sessions/steps.js +250 -0
  205. package/dist/sessions/store.d.ts +297 -0
  206. package/dist/sessions/store.js +1478 -0
  207. package/dist/sessions/strata.d.ts +26 -0
  208. package/dist/sessions/strata.js +77 -0
  209. package/dist/sessions/survival.d.ts +25 -0
  210. package/dist/sessions/survival.js +230 -0
  211. package/dist/sessions/verify.d.ts +53 -0
  212. package/dist/sessions/verify.js +286 -0
  213. package/dist/sessions/vocab-load.d.ts +26 -0
  214. package/dist/sessions/vocab-load.js +61 -0
  215. package/dist/sessions/vscode-copilot.d.ts +38 -0
  216. package/dist/sessions/vscode-copilot.js +477 -0
  217. package/package.json +4 -5
  218. package/vocab/crates.json +1 -0
  219. package/vocab/go.json +1 -0
  220. package/vocab/harness.json +1 -0
  221. package/vocab/homebrew.json +1 -0
  222. package/vocab/manifest.json +1 -0
  223. package/vocab/maven.json +1 -0
  224. package/vocab/models.json +1 -0
  225. package/vocab/npm.json +1 -0
  226. package/vocab/programs.json +1 -0
  227. package/vocab/pypi.json +1 -0
  228. package/vocab/rubygems.json +1 -0
  229. package/dist/commands/deploy-input.d.ts +0 -35
  230. package/dist/commands/deploy-input.js +0 -107
  231. package/dist/commands/deploy.d.ts +0 -22
  232. package/dist/commands/deploy.js +0 -120
  233. package/dist/commands/status.d.ts +0 -7
  234. package/dist/commands/status.js +0 -18
  235. package/dist/commands/test-charge.d.ts +0 -11
  236. package/dist/commands/test-charge.js +0 -34
  237. package/dist/journal.d.ts +0 -26
  238. package/dist/journal.js +0 -58
  239. package/parity/deploy-plans/paid-api.json +0 -34
  240. package/parity/deploy-plans/per-task-agent.json +0 -34
@@ -0,0 +1,181 @@
1
+ // The cell (recall spec Section 2.5): counts for one motif in one frame bucket in one UTC week (or, for a live cell, one UTC day), order 0. Cells are computed from the capture records, which
2
+ // stay the primary record, so a cell file can be dropped and rebuilt and any later derivation can run over old data. Nothing here reads raw.
3
+ import { closedFrame, utcDay } from './frame.js';
4
+ import { classMotif, motifsOf, stepsOfCall } from './motif.js';
5
+ import { bucketOf } from './pool-wire.js';
6
+ import { CALL_SHAPE_METHOD, cellRef, contentHash, METHODS } from './read.js';
7
+ import { NO_RECALLS } from './recall-consequence.js';
8
+ import { EXTRACTOR_VERSION, harnessOf } from './schema.js';
9
+ export const UNKNOWN = 'unknown';
10
+ /** The class name an effort cell carries: a class motif with no prompt class in it, so a read of prompt classes skips it by this prefix. */
11
+ export const EFFORT_CLASS = 'effort:';
12
+ /**
13
+ * Rule 3: effort is not in a cell's key. The one cell that holds it pairs it with the bucket of the prompt's thinking tokens, which is the fact an effort level explains, and it
14
+ * carries `week` and `exposure` but no frame axis: rule 3 bars joining `effort` to `model` or `harnessVersion`, and the pair would be four dimensions over `q_dims`.
15
+ */
16
+ export const effortClass = (effort, thinking) => `${EFFORT_CLASS}${effort}/thinking:${String(bucketOf('tokens', thinking))}`;
17
+ /** The frame bucket of a cell that joins no axis. */
18
+ export const NO_AXES = '-';
19
+ const ONE_OPERATOR = 1;
20
+ /**
21
+ * A harness version's bucket: its patch by tens. 70.5 percent of one operator's later prompts ran a version not yet seen, so an
22
+ * exact-version cell goes stale in days; a reader compares buckets by distance instead. A version with no patch stands for itself.
23
+ */
24
+ export const harnessBucket = (version) => {
25
+ if (version === null)
26
+ return UNKNOWN;
27
+ const found = /^(\d+\.\d+)\.(\d+)/.exec(version);
28
+ return found === null ? version : `${found[1] ?? ''}.${String(Math.floor(Number(found[2]) / 10))}x`;
29
+ };
30
+ /** Only what most comparisons cross: platform, shell, and stack are on the frame and in the records, so a later extractor can add them without new capture. */
31
+ export const frameBucketOf = (frame) => [frame.harness, harnessBucket(frame.harnessVersion), frame.model ?? UNKNOWN].join('/');
32
+ export const bucketFields = (bucket) => {
33
+ const [harness = UNKNOWN, version = UNKNOWN, model = UNKNOWN] = bucket.split('/');
34
+ return { harness, harnessBucket: version, model };
35
+ };
36
+ /** The frame bucket of a (name, `platform`, `shell`) cell: fit's third pool form. Rule 3 lets the two join each other and a name within `q_dims`, but not a version or a model beside them, so the cell is version-free and model-free. */
37
+ export const ENVIRONMENT_BUCKET = 'env:';
38
+ export const environmentBucketOf = (frame) => `${ENVIRONMENT_BUCKET}${frame.platform}:${frame.shell ?? UNKNOWN}`;
39
+ export const isEnvironmentCell = (cell) => cell.frameBucket.startsWith(ENVIRONMENT_BUCKET);
40
+ export const environmentFieldsOf = (bucket) => {
41
+ const held = bucket.slice(ENVIRONMENT_BUCKET.length);
42
+ const at = held.indexOf(':');
43
+ return { platform: held.slice(0, at), shell: held.slice(at + 1) };
44
+ };
45
+ /** A one-step named call with no flag and no pull: the name that is one dimension. A call with no identity (a file read, an edit) is its action alone, so it counts. A flag or a pull is a second dimension of its own, so its cell would be four with the pair. */
46
+ const isPlainCall = (motif) => {
47
+ const [only] = motif.steps;
48
+ if (motif.level !== 'named' || motif.steps.length !== 1 || only === undefined)
49
+ return false;
50
+ return only.identity === null || !('program' in only.identity) || (only.identity.flags.length === 0 && (only.identity.pulls?.length ?? 0) === 0);
51
+ };
52
+ const DAY_MS = 86_400_000;
53
+ /** The Monday of the UTC week a UTC day falls in, as a day: the week's name in a cell. An unknown day is an unknown week. */
54
+ export const weekStartOf = (day) => {
55
+ if (day === UNKNOWN)
56
+ return UNKNOWN;
57
+ const millis = Date.parse(day);
58
+ return new Date(millis - ((new Date(millis).getUTCDay() + 6) % 7) * DAY_MS).toISOString().slice(0, 10);
59
+ };
60
+ /** The last UTC day a cell can hold: its day, or the Sunday that closes its week. A check that evidence predates a day reads this, since a week's cell may hold any of its seven days. */
61
+ export const lastDayOfCell = (cell) => (cell.grain === 'week' && cell.day !== UNKNOWN ? new Date(Date.parse(cell.day) + 6 * DAY_MS).toISOString().slice(0, 10) : cell.day);
62
+ const cellIds = new WeakMap();
63
+ /** `cell:<contentHash>`: a cell that counts differently is a different cell, so a read's inputs pin what it read. */
64
+ export const cellIdOf = (cell) => {
65
+ const known = cellIds.get(cell);
66
+ if (known !== undefined)
67
+ return known;
68
+ const id = cellRef(contentHash(cell));
69
+ cellIds.set(cell, id);
70
+ return id;
71
+ };
72
+ const newTally = (motifId, frameBucket, grain, day, exposed) => ({ motifId, frameBucket, grain, day, sessions: new Set(), ok: 0, failed: 0, tokens: 0, durationMs: 0, exposed });
73
+ const compare = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
74
+ /** A frame for a record captured before frames existed, from the fields it does hold, held to the same public vocabulary. */
75
+ const oldFrame = (parts) => closedFrame({
76
+ harness: parts.harness,
77
+ harnessVersion: parts.version,
78
+ model: parts.model === '' ? null : parts.model,
79
+ effort: parts.effort,
80
+ day: utcDay(parts.ts),
81
+ platform: parts.platform,
82
+ shell: null,
83
+ stack: { languages: [], frameworks: [], size: null },
84
+ });
85
+ const mostUsedModel = (models) => [...Object.entries(models)].sort(([a, one], [b, two]) => two - one || compare(a, b))[0]?.[0] ?? null;
86
+ const framedPrompt = (prompt, harness, version, ts, platform) => prompt.frame ?? oldFrame({ harness, version, model: prompt.model, effort: prompt.efforts[0] ?? null, ts: prompt.ts ?? ts, platform });
87
+ /** One line of work (spec Section 2.3): a window never crosses a prompt, a sidechain, or a transcript. */
88
+ const linesOf = (tools) => {
89
+ const lines = new Map();
90
+ for (const tool of tools) {
91
+ const key = `${tool.session}\n${String(tool.side)}\n${String(tool.prompt)}`;
92
+ const line = lines.get(key);
93
+ if (line === undefined)
94
+ lines.set(key, [tool]);
95
+ else
96
+ line.push(tool);
97
+ }
98
+ return [...lines.values()].map((line) => line.sort((a, b) => a.n - b.n));
99
+ };
100
+ export const deriveCells = (store, graph = NO_RECALLS) => {
101
+ const tallies = new Map();
102
+ const motifs = new Map();
103
+ const tallyAt = (motif, frameBucket, grain, day, exposed) => {
104
+ const key = `${motif.motifId}/${frameBucket}/${grain}/${day}/${String(exposed)}`;
105
+ const found = tallies.get(key);
106
+ if (found !== undefined)
107
+ return found;
108
+ const fresh = newTally(motif.motifId, frameBucket, grain, day, exposed);
109
+ tallies.set(key, fresh);
110
+ return fresh;
111
+ };
112
+ /** The tallies one occurrence counts into: its week cell, and for a one-step shape motif with a known day its live cell too (rule 6). A window of two or more steps, a named motif, and a class motif have no day cell. */
113
+ const talliesOf = (motif, frame, exposed, frameBucket = frameBucketOf(frame)) => {
114
+ motifs.set(motif.motifId, motif);
115
+ const day = frame.day ?? UNKNOWN;
116
+ const weekly = tallyAt(motif, frameBucket, 'week', weekStartOf(day), exposed);
117
+ const tallies = motif.level === 'shape' && motif.steps.length === 1 && day !== UNKNOWN ? [weekly, tallyAt(motif, frameBucket, 'day', day, exposed)] : [weekly];
118
+ // Fit's (name, platform, shell) cell: a week cell beside the versioned one, counting the same call.
119
+ return isPlainCall(motif) ? [...tallies, tallyAt(motif, environmentBucketOf(frame), 'week', weekStartOf(day), exposed)] : tallies;
120
+ };
121
+ const sessions = new Map([...store.sessions, ...store.subagents].map((session) => [session.session, session]));
122
+ const prompts = new Map(store.prompts.map((prompt) => [`${prompt.session}#${String(prompt.index)}`, prompt]));
123
+ for (const line of linesOf(store.tools)) {
124
+ const [first] = line;
125
+ const session = first === undefined ? undefined : sessions.get(first.session);
126
+ if (first === undefined || session === undefined)
127
+ continue;
128
+ const harness = harnessOf(session);
129
+ const version = first.harnessVersion ?? session.env.harness;
130
+ const prompt = prompts.get(`${first.session}#${String(first.prompt)}`);
131
+ const frame = prompt === undefined
132
+ ? (session.frame ?? oldFrame({ harness, version, model: mostUsedModel(session.models), effort: null, ts: first.ts ?? session.tsFirst, platform: session.env.os }))
133
+ : framedPrompt(prompt, harness, version, first.ts, session.env.os);
134
+ const placed = line.flatMap((tool) => graph.place(tool, stepsOfCall(tool, harness)));
135
+ const steps = placed.map(({ step }) => step);
136
+ for (const { motif, start } of motifsOf(steps)) {
137
+ const window = steps.slice(start, start + motif.steps.length);
138
+ const status = window.at(-1)?.status;
139
+ for (const tally of talliesOf(motif, frame, placed.slice(start, start + motif.steps.length).some(({ exposed }) => exposed))) {
140
+ tally.sessions.add(first.parent);
141
+ if (status === 'ok')
142
+ tally.ok += 1;
143
+ if (status === 'error')
144
+ tally.failed += 1;
145
+ for (const step of window) {
146
+ tally.tokens += step.tokens;
147
+ tally.durationMs += step.durationMs;
148
+ }
149
+ }
150
+ }
151
+ }
152
+ for (const prompt of store.prompts) {
153
+ const session = sessions.get(prompt.session);
154
+ const frame = framedPrompt(prompt, harnessOf(session ?? {}), session?.env.harness ?? null, null, session?.env.os ?? UNKNOWN);
155
+ const exposed = graph.exposedPrompt(prompt.session, prompt.index);
156
+ const effort = frame.effort === null ? [] : talliesOf(classMotif(effortClass(frame.effort, prompt.usage.thinking)), frame, exposed, NO_AXES);
157
+ for (const tally of [...talliesOf(classMotif(prompt.cls), frame, exposed), ...effort]) {
158
+ tally.sessions.add(prompt.session);
159
+ if (prompt.errors > 0)
160
+ tally.failed += 1;
161
+ else
162
+ tally.ok += 1;
163
+ const { input, cacheWrite, cacheRead, output } = prompt.usage;
164
+ tally.tokens += input + cacheWrite + cacheRead + output;
165
+ tally.durationMs += (prompt.wallSec ?? 0) * 1000;
166
+ }
167
+ }
168
+ const cells = [...tallies.values()]
169
+ .sort((a, b) => compare(a.motifId, b.motifId) || compare(a.frameBucket, b.frameBucket) || compare(a.grain, b.grain) || compare(a.day, b.day) || Number(a.exposed) - Number(b.exposed))
170
+ .map((tally) => ({ motifId: tally.motifId, frameBucket: tally.frameBucket, grain: tally.grain, day: tally.day, sessions: tally.sessions.size, clusters: ONE_OPERATOR, ok: tally.ok, failed: tally.failed, tokens: tally.tokens, durationMs: tally.durationMs, exposed: tally.exposed }));
171
+ return { cells, motifs: [...motifs.values()].sort((a, b) => compare(a.motifId, b.motifId)) };
172
+ };
173
+ export const serializeCells = (cells) => cells.map((cell) => `${JSON.stringify(cell)}\n`).join('');
174
+ /** The fields of an error row a recovery read depends on, as text: only those, so a change elsewhere is not a new pool, and sorted, so record order is not one either. */
175
+ const errorRowsRead = (errors) => errors.map(({ session, agent, toolUseId, prompt, tool, sig, ts, next, editFollowed }) => JSON.stringify([session, agent ?? null, toolUseId ?? null, prompt, tool, sig, ts, next, editFollowed])).sort();
176
+ export const poolOf = (set, errors) => ({
177
+ cells: set.cells,
178
+ motifs: new Map(set.motifs.map((motif) => [motif.motifId, motif])),
179
+ version: contentHash([EXTRACTOR_VERSION, METHODS, CALL_SHAPE_METHOD, set.cells.map(cellIdOf), errorRowsRead(errors)]),
180
+ lastDay: set.cells.reduce((last, cell) => (cell.day !== UNKNOWN && (last === null || cell.day > last) ? cell.day : last), null),
181
+ });
@@ -0,0 +1,53 @@
1
+ /** The Codex home for an environment; a test passes its own so it never reads the real one. */
2
+ export declare const codexRoot: (env: {
3
+ [name: string]: string | undefined;
4
+ }, home?: string) => string;
5
+ type Obj = {
6
+ [key: string]: unknown;
7
+ };
8
+ /** A rollout file found in the store, before its lines are read. */
9
+ export interface CodexSession {
10
+ /** The rollout's key: the thread uuid in the file name (Codex's own session id), `<thread>_<rollout>` for a reverted thread's file when the thread itself is not in the store (else its file is folded into the thread's, `revisions`), else the file's stem. */
11
+ id: string;
12
+ /** `session_meta.cwd`; null when the first line names none. */
13
+ folder: string | null;
14
+ /** `session_meta.parent_thread_id`: set for a spawned agent's rollout, which is deposited as a subagent of that thread. */
15
+ parent: string | null;
16
+ /** `session_meta.agent_role` (protocol.rs:3486), when the spawned agent has one. */
17
+ agentRole: string | null;
18
+ /** `session_meta.forked_from_id`: the thread whose history a fork copied, to match its copied records against. */
19
+ forkedFrom: string | null;
20
+ /**
21
+ * The rollouts of the thread's reverts, folded into this one (thread-store/src/local/revert_thread.rs:15-18): each starts at `from`, the ordinal it
22
+ * takes from `history_base.end_ordinal_exclusive`, and supersedes the records at or after it in every earlier file. Empty for a thread never reverted.
23
+ */
24
+ revisions: {
25
+ file: string;
26
+ from: number;
27
+ at: number;
28
+ }[];
29
+ /** `session_meta.timestamp` in milliseconds (a fresh `started_at` for each new rollout, rollout/src/recorder.rs:953-966); 0 when absent. A fork is matched against the lineage as of this time. */
30
+ started: number;
31
+ file: string;
32
+ size: number;
33
+ mtimeMs: number;
34
+ }
35
+ export interface CodexStore {
36
+ sessions: CodexSession[];
37
+ /** The session as transcript text for `captureSession`; throws when the file cannot be read. */
38
+ transcript: (session: CodexSession) => Promise<string>;
39
+ /** Files skipped because their id is not a safe file name (it names a skeleton), counted so the skip is never silent. */
40
+ rejected: number;
41
+ /** Files that could not be inspected, reported once each and never fatal; the reason names no path, so a log line built from it leaks none. */
42
+ unreadable: {
43
+ file: string;
44
+ reason: string;
45
+ }[];
46
+ }
47
+ /** The non-blank lines of a rollout that are not JSON (a torn write), kept so `captureSession` counts them and the deposit line reports them. */
48
+ export declare const rolloutBadLines: (text: string) => string[];
49
+ /** One rollout as the lines `captureSession` reads. */
50
+ export declare const rolloutLines: (text: string, fallbackId: string, parentText?: string) => Obj[];
51
+ /** Opens the Codex store under `root`; undefined when it holds no `sessions` folder, so a machine without Codex is skipped silently. */
52
+ export declare const openCodexStore: (root: string) => Promise<CodexStore | undefined>;
53
+ export {};