maxpool 1.10.1 → 1.10.3
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.
- package/package.json +1 -1
- package/src/account-manager.js +4 -0
- package/src/capacity-ledger.js +21 -1
- package/src/server.js +34 -2
package/package.json
CHANGED
package/src/account-manager.js
CHANGED
|
@@ -3010,7 +3010,11 @@ export class AccountManager {
|
|
|
3010
3010
|
* cycle is no longer a truthful capacity observation — flag it partial (B2/SC6).
|
|
3011
3011
|
* It still displays; it is excluded from averages. */
|
|
3012
3012
|
restoreCapacityState(payload, now = Date.now(), downtimeMs = null) {
|
|
3013
|
+
// Preserve the test seam across the ledger swap (fromSerialized returns a fresh
|
|
3014
|
+
// instance; without this the zero-floor harness override dies on any restore).
|
|
3015
|
+
const floorOverride = this.capacity?._readFloorOverride ?? null;
|
|
3013
3016
|
this.capacity = CapacityLedger.fromSerialized(payload);
|
|
3017
|
+
this.capacity._readFloorOverride = floorOverride;
|
|
3014
3018
|
// Partial is keyed on MAXPOOL'S OWN downtime, NEVER on the account's last request:
|
|
3015
3019
|
// an account parked >10min mid-cycle is normal fleet rotation, and keying on its
|
|
3016
3020
|
// last request discarded valid observations on every reload (red-team F3). The
|
package/src/capacity-ledger.js
CHANGED
|
@@ -31,6 +31,10 @@ const SCHEMA_VERSION = 3;
|
|
|
31
31
|
// Two closes this far apart are the SAME boundary observed twice (a clock-close and a
|
|
32
32
|
// stamp-advance racing across the boundary second), not two windows.
|
|
33
33
|
const SAME_BOUNDARY_MS = 5_000;
|
|
34
|
+
|
|
35
|
+
// The minimum span of a COMPLETE cycle per window (80% of nominal): a real one is
|
|
36
|
+
// flagged partial by the writer, so a complete cycle below this is corrupt history.
|
|
37
|
+
const READ_FLOOR_MS = { ses: 4 * 3600_000, wk: 5 * 86400_000 };
|
|
34
38
|
const MAX_CYCLES_PER_WINDOW = 50;
|
|
35
39
|
const MAX_DAY_BUCKETS = 10;
|
|
36
40
|
|
|
@@ -54,6 +58,9 @@ export class CapacityLedger {
|
|
|
54
58
|
// Cleared per account+window once that window's first boundary is behind us.
|
|
55
59
|
this._joinedMidWindow = false;
|
|
56
60
|
this._utilObservedAt = 0; // last utilization-reading arrival (see estimateFromUtilization)
|
|
61
|
+
// Test seam ONLY: real-window fixtures are laborious for every close-cycle test,
|
|
62
|
+
// so tests may zero the read floor. Production never touches this.
|
|
63
|
+
this._readFloorOverride = null;
|
|
57
64
|
}
|
|
58
65
|
|
|
59
66
|
/** Restore from a serialized payload (state.json). Tolerant: unknown schemaVersion →
|
|
@@ -324,7 +331,20 @@ export class CapacityLedger {
|
|
|
324
331
|
* are observations, not capacity). */
|
|
325
332
|
windowStats(name, window) {
|
|
326
333
|
const rec = this._accounts.get(name);
|
|
327
|
-
|
|
334
|
+
// READ-TIME FLOOR. A cycle marked complete + never-disabled but spanning far less
|
|
335
|
+
// than its window is junk from a writer bug — the live ledger held a 0.5-second /
|
|
336
|
+
// 588-token "cycle" (clock-close and stamp-advance racing at one boundary, the fold
|
|
337
|
+
// refused on an endedAt mismatch) and it dragged this account's Avg3 down ~188k.
|
|
338
|
+
// Unlike the WRITE-time floor I tried first (reverted: it punished accounts that
|
|
339
|
+
// were merely idle early in their window), at read time a genuinely short cycle is
|
|
340
|
+
// already flagged complete:false by the writer — so a complete sub-floor cycle is
|
|
341
|
+
// definitionally corrupt, never a real observation.
|
|
342
|
+
const floor = (this._readFloorOverride ?? READ_FLOOR_MS)[window] ?? 0;
|
|
343
|
+
// >= floor, with a 1s tolerance for the accrue-vs-close clock race (an accrue can
|
|
344
|
+
// stamp Date.now() a tick AFTER the close computed its boundary, making a 0-span
|
|
345
|
+
// cycle read as -1ms — found by debugging a D2 failure that only reproduced in-file).
|
|
346
|
+
const closed = (rec?.[window]?.closed || []).filter(c =>
|
|
347
|
+
c.complete && !c.disabledDuring && (c.endedAt - c.startedAt) >= floor - 1_000);
|
|
328
348
|
if (!closed.length) return null;
|
|
329
349
|
const avg = (arr) => arr.length ? Math.round(arr.reduce((a, b) => a + b, 0) / arr.length) : null;
|
|
330
350
|
const tokens = closed.map(c => c.tokens);
|
package/src/server.js
CHANGED
|
@@ -1991,7 +1991,23 @@ function stripRejectedBlockClass(body, errorBody) {
|
|
|
1991
1991
|
// and keeping the original would resend the exact body that just 400'd. Except
|
|
1992
1992
|
// messages[0], which must survive as a `user` turn (see the same guard above).
|
|
1993
1993
|
if (kept.length === 0) {
|
|
1994
|
-
|
|
1994
|
+
// messages[0] must survive AS A USER TURN — Anthropic requires the first message
|
|
1995
|
+
// to be `user`, and preserving the original role (what this did until
|
|
1996
|
+
// 2026-08-24) left a system-first transcript system-first: the guard silently
|
|
1997
|
+
// not doing the one thing it exists for.
|
|
1998
|
+
if (messages.length === 0) {
|
|
1999
|
+
messages.push({ role: 'user', content: [{ type: 'text', text: '(content removed)' }] });
|
|
2000
|
+
continue;
|
|
2001
|
+
}
|
|
2002
|
+
// A SYSTEM turn is never dropped. Every other role can go — the turn carried
|
|
2003
|
+
// nothing but a poisoned block, and a gap is harmless. A system is an
|
|
2004
|
+
// INSTRUCTION channel: deleting it changes how the session behaves with no
|
|
2005
|
+
// signal to anyone, which is worse than the loud 400 the repair is fixing.
|
|
2006
|
+
// Keep the turn as a placeholder so its position and presence survive.
|
|
2007
|
+
if (msg?.role === 'system') {
|
|
2008
|
+
messages.push({ ...msg, content: [{ type: 'text', text: '(content removed)' }] });
|
|
2009
|
+
continue;
|
|
2010
|
+
}
|
|
1995
2011
|
continue;
|
|
1996
2012
|
}
|
|
1997
2013
|
messages.push({ ...msg, content: kept });
|
|
@@ -2169,7 +2185,23 @@ function stripForeignThinkingBlocks(body) {
|
|
|
2169
2185
|
// Reachable only since the role gate was removed — before that, non-assistant
|
|
2170
2186
|
// turns were never dropped at all.
|
|
2171
2187
|
if (kept.length === 0) {
|
|
2172
|
-
|
|
2188
|
+
// messages[0] must survive AS A USER TURN — Anthropic requires the first message
|
|
2189
|
+
// to be `user`, and preserving the original role (what this did until
|
|
2190
|
+
// 2026-08-24) left a system-first transcript system-first: the guard silently
|
|
2191
|
+
// not doing the one thing it exists for.
|
|
2192
|
+
if (messages.length === 0) {
|
|
2193
|
+
messages.push({ role: 'user', content: [{ type: 'text', text: '(content removed)' }] });
|
|
2194
|
+
continue;
|
|
2195
|
+
}
|
|
2196
|
+
// A SYSTEM turn is never dropped. Every other role can go — the turn carried
|
|
2197
|
+
// nothing but a poisoned block, and a gap is harmless. A system is an
|
|
2198
|
+
// INSTRUCTION channel: deleting it changes how the session behaves with no
|
|
2199
|
+
// signal to anyone, which is worse than the loud 400 the repair is fixing.
|
|
2200
|
+
// Keep the turn as a placeholder so its position and presence survive.
|
|
2201
|
+
if (msg?.role === 'system') {
|
|
2202
|
+
messages.push({ ...msg, content: [{ type: 'text', text: '(content removed)' }] });
|
|
2203
|
+
continue;
|
|
2204
|
+
}
|
|
2173
2205
|
continue;
|
|
2174
2206
|
}
|
|
2175
2207
|
messages.push({ ...msg, content: kept });
|