atris 3.71.3 → 3.72.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.
@@ -7,7 +7,7 @@
7
7
  'use strict';
8
8
 
9
9
  const crypto = require('crypto');
10
- const { compareEvents, fold, foldWithPrefixes } = require('./campaign-core');
10
+ const { compareEvents, fold, foldWithSummaryPrefixes } = require('./campaign-core');
11
11
  const { judgeReading } = require('./campaign-reading');
12
12
 
13
13
  const SCHEMA = 'atris.campaign.trace';
@@ -55,16 +55,14 @@ function foldOrder(events) {
55
55
  }
56
56
 
57
57
  function compactState(view, run) {
58
- const missions = { proposed: 0, claimed: 0, running: 0, ended: 0, vetoed: 0, dropped: 0 };
59
- for (const m of view.missions) missions[m.status] = (missions[m.status] || 0) + 1;
60
58
  return {
61
59
  state: view.state,
62
60
  reading: readingOf(run).value,
63
- confidence: view.answer.confidence,
61
+ confidence: view.confidence,
64
62
  judge_runs: view.judge_runs,
65
63
  budget: view.budget,
66
- missions,
67
- open_asks: view.asks.length,
64
+ missions: view.mission_counts,
65
+ open_asks: view.open_asks,
68
66
  };
69
67
  }
70
68
 
@@ -141,21 +139,49 @@ function buildTrace(events, options = {}) {
141
139
  // Reuse one event traversal and retain only the compact state needed for
142
140
  // ended missions. Reading lookup below still uses the original position.
143
141
  const prefixStates = ended.length
144
- ? foldWithPrefixes(sequence, ended.map((m) => Math.max(1, m.firstPos === null ? m.endPos : m.firstPos)),
145
- (view) => compactState(view, null)).prefixes
142
+ ? foldWithSummaryPrefixes(sequence, ended.map((m) => Math.max(1, m.firstPos === null ? m.endPos : m.firstPos))).prefixes
146
143
  : new Map();
147
144
  const lastRunBefore = (pos) => {
148
- let found = null;
149
- for (const run of judgeRuns) if (run.pos < pos) found = run;
150
- return found;
145
+ let lo = 0;
146
+ let hi = judgeRuns.length;
147
+ while (lo < hi) {
148
+ const mid = Math.floor((lo + hi) / 2);
149
+ if (judgeRuns[mid].pos < pos) lo = mid + 1;
150
+ else hi = mid;
151
+ }
152
+ return judgeRuns[lo - 1] || null;
153
+ };
154
+ const firstRunAfter = (pos) => {
155
+ let lo = 0;
156
+ let hi = judgeRuns.length;
157
+ while (lo < hi) {
158
+ const mid = Math.floor((lo + hi) / 2);
159
+ if (judgeRuns[mid].pos <= pos) lo = mid + 1;
160
+ else hi = mid;
161
+ }
162
+ return judgeRuns[lo] || null;
163
+ };
164
+ const judgeChangedBetween = (beforePos, afterPos) => {
165
+ let lo = 0;
166
+ let hi = judgeChanges.length;
167
+ while (lo < hi) {
168
+ const mid = Math.floor((lo + hi) / 2);
169
+ if (judgeChanges[mid] <= beforePos) lo = mid + 1;
170
+ else hi = mid;
171
+ }
172
+ return lo < judgeChanges.length && judgeChanges[lo] < afterPos;
151
173
  };
152
- const firstRunAfter = (pos) => judgeRuns.find((run) => run.pos > pos) || null;
153
174
 
154
175
  // Where the campaign finished, if it did: the first position whose prefix is done.
155
176
  let finishPos = null;
156
177
  if (final.state === 'done') {
157
178
  let lo = 0;
158
179
  let hi = sequence.length - 1;
180
+ for (const [count, snapshot] of prefixStates) {
181
+ if (snapshot.state === 'done') { hi = count - 1; break; }
182
+ lo = count;
183
+ }
184
+
159
185
  while (lo < hi) {
160
186
  const mid = Math.floor((lo + hi) / 2);
161
187
  if (fold(sequence.slice(0, mid + 1)).state === 'done') hi = mid;
@@ -190,7 +216,7 @@ function buildTrace(events, options = {}) {
190
216
  const batch = batches.get(`${before ? before.pos : -1}:${after ? after.pos : 'open'}`);
191
217
  const size = batch.missions.length;
192
218
  const outcome = outcomeOf(m);
193
- const judgeChanged = before && after && judgeChanges.some(pos => pos > before.pos && pos < after.pos);
219
+ const judgeChanged = before && after && judgeChangedBetween(before.pos, after.pos);
194
220
  const readBefore = readingOf(before);
195
221
  // A replacement baseline is real campaign state, but cannot score earlier
196
222
  // work. Null also prevents a replacement pass becoming fallback RSI proof.
@@ -226,7 +252,7 @@ function buildTrace(events, options = {}) {
226
252
  step: i + 1,
227
253
  at: m.endAt,
228
254
  batch: { index: batch.index, size },
229
- state_before: { ...prefixStates.get(Math.max(1, startPos)), reading: readingOf(lastRunBefore(startPos)).value },
255
+ state_before: compactState(prefixStates.get(Math.max(1, startPos)), lastRunBefore(startPos)),
230
256
  action,
231
257
  outcome,
232
258
  cost_usd: folded.cost_usd === undefined || folded.cost_usd === null ? m.endData.cost_usd : folded.cost_usd,
@@ -93,7 +93,11 @@ const SYSTEM_TOOLS = {
93
93
 
94
94
  function defaultRun(cmd, args) {
95
95
  const full = SYSTEM_TOOLS[cmd];
96
- return spawnSync(full && fs.existsSync(full) ? full : cmd, args, { encoding: 'utf8', timeout: 3000 });
96
+ const options = { encoding: 'utf8', timeout: 3000 };
97
+ // Environment listings grow with local jobs; keep a finite allowance above
98
+ // Node's default 1 MiB without changing the deadline or failed-read policy.
99
+ if (cmd === 'ps') options.maxBuffer = 8 * 1024 * 1024;
100
+ return spawnSync(full && fs.existsSync(full) ? full : cmd, args, options);
97
101
  }
98
102
 
99
103
  function parseFreePct(text) {