Repository navigation
test(compression): pin compression-lifecycle rules no test checked - #435
Conversation
Eight tests in test/compression-drain-lifecycle.test.ts for rules of the autobiographical strategy's compression lifecycle that no test reached. Each was run with its rule's code changed (one source edit) and without: it fails with the edit and passes without. - Without a membrane, tick() warns that compression has none, makes no call and leaves the closed chunks queued. Fails if the warning goes, or if the tick goes on to the queue. - A queued chunk with a held message ends the tick's scan: a chunk queued behind it waits until the release. A hold blocks every message from the earliest held one on, so the chunk behind it in the queue is an earlier one, put there by a transient failure. Fails if a held chunk is skipped and the scan goes on. - Releasing a hold resumes the auto-tick drain with no further message. Fails if the release starts no drain. - Readiness names a pause only while it stands. Fails if an ended pause still shows. - The drain starts nothing after a tick that threw, until the next message, and logs what the tick threw (a host's withdrawal or cancellation ends the drain quietly). Fails if the drain resumes after the throw, or if the drain's error isn't logged. - A false preflight hook doesn't stop a drain while a merge is queued: shouldCompressPreflight() decides whether a drain starts only when no merge is queued. Fails if a false preflight stops a drain with a merge queued. - Releasing a sharded add's id releases every shard. Fails if only that id is released. - A mechanical stub is no provider answer: after a pause ends, a stub landing leaves the lane's failure count to carry to its next failure. Fails if a stub ends the pause as an answer would.
Twelve tests in test/compression-ladder-options.test.ts for rules of the autobiographical strategy's compression ladder and its options that no test reached. Each was run with its rule's code changed (one source edit) and without: it fails with the edit and passes without. - An L1 request asks for max(16000, summaryTargetTokens x 1.5) output tokens: 18,000 for a target of 12,000, and the 16,000 floor for 8,000. Fails if it multiplies targetChunkTokens instead, as the type doc's formula reads; the test pins the code's side of that difference. - compressionMaxTokens caps an L1 request's output tokens. Fails if the cap caps nothing. - recoverLiteralThinkingWrappedCompression reads only an answer of text blocks alone: one with native reasoning beside a wrapped text isn't recovered. Fails if it's recovered too. - A split-stitch rung makes up to 40 calls for one chunk by default: a chunk that needs 40 is stitched, and one that needs 42 stops after 40. Fails if the default is 20, or if the cap is compared with > for >=. - A split-stitch rung starts only when the ten-minute window, 80 calls by default, has room for a whole attempt: after 40 calls a 40-call attempt starts and after 80 the next waits, and after 42 a 39-call attempt waits. Once the window's calls age out, the waiting chunk is stitched. Fails if the default is 160. - A chunk waiting for its split-stitch call window stays queued, and the tick goes on to the chunk behind it. Fails if a waiting chunk ends the scan. - After a refusal, three recall-curve variants are tried when compressionRefusalCurveFallbacks is given as undefined. Fails if the fallback count is 2. - A request-attributable rejection of the canonical request tries no variant. Fails if it tries the variants. - compressionSourceOnly leaves the recall of a merge as it is. Fails if it strips the merge's recall too, down to the 8,000-token floor (the test's two earlier merges recall about 10,000 tokens). - Each retry of a merge a provider rejected halves its recall budget, down to an 8,000-token floor: from 32,000, the earlier merges it recalls go 3, 2, 1, 1, 1 over five attempts. Fails if the budget isn't halved. - A merge the caller's provider admission defers keeps its place at the head of the queue, is asked again first, and counts no failure: ten deferrals, eight of them after an L1 landed, decide nothing, where counted failures would decide the merge as a request rejection at the eighth. Fails if a deferral counts toward the merge's failure streak, whether or not it also moves the merge behind the others. - A held L1 counts toward maxSpeculativeL1s, so past the cap the queued merge goes before the queued chunk. Fails if held L1s aren't counted.
Seven tests in test/compression-persisted-state.test.ts for rules of the autobiographical strategy that turn on what a store already holds: chunk records, summaries, the quarantine ledgers and the merge queue, as an older release or a crash leaves them. The state is seeded through the store's state API, or reached through a public option, a documented subclass hook or an injected store fault. Each was run with its rule's code changed (one source edit) and without: it fails with the edit and passes without. - Three chunk records, two naming no live message, fail the rebuild closed, logged once however many rebuilds follow. Fails if the guard needs four records, or if it logs at every rebuild. - A chunk record fully covered by summaries under other boundaries is left uncompressed in the store. Fails if the record is marked compressed. - A chunk the overlap guard keeps out of the queue counts as pending compression debt. Fails if it isn't counted. - A strategy without chunk records logs the overlap guard once for a chunk it refuses on every attempt. Fails if it logs at every attempt. - The paid-off sweep clears a quarantine record whose chunk record is compressed. The record is left there by a store fault on the clear after the chunk compressed. Fails if the sweep keeps it. - A merge-quarantine topology record goes, with a log line, once its group queues as a valid merge. Fails if the clear logs nothing. - An auditOnly open keeps a persisted merge the current grammar refuses. Fails if the open drops it.
…e's log event Three tests in test/compression-alarms-logs.test.ts. Each was run with its rule's code changed (one source edit) and without: it fails with the edit and passes without. - quarantineAlarmIntervalMs: 0 sounds no repeating alarm for a quarantined chunk, at once or past the default 15-minute interval. Fails if an interval of 0 doesn't disable it. - quarantineAlarmIntervalMs: 0 sounds no repeating alarm for a quarantined merge, at once or past the default 15-minute interval. Fails if an interval of 0 doesn't disable it. - A pause writes a compression:lane-paused event to the file CONTEXT_MANAGER_COMPRESSION_LOG names. Fails if the event has another name.
…orts an overload The drain-lifecycle tests and the lane-paused log test made their transient failure with the error type 'overloaded', which membrane never produces; it counted as transient only because an unclassified type does. It now carries what membrane reports for an overloaded provider: type 'server', HTTP status 529, retryable.
Anarchid
left a comment
There was a problem hiding this comment.
Nightly dual review · round R1 at afc226c · reviewers: Codex gpt-5.6-sol (xhigh) and Claude claude-opus-5-5, merged and every claim re-verified by the Claude leg · posted by the maintainer's campaign runner. Verdict: APPROVE (the formal review event is left to the maintainer). Finding ids R1-n are stable; cite them in fix commits.
Reviewed at afc226c against main fb4cf10
This is our first review of this PR. There is no earlier review of ours to carry findings from.
Verdict: APPROVE, with three minor findings
These tests hold up. I wrote my own source edit for 34 of the 35 rows in the breakage table, applied each to main's src/ one at a time, and every one failed the test the table names. Seven of them, run against the whole suite, failed nothing outside this PR's files. The 30 tests pass alone and in any order, showed no flake under heavy load, and still pass on top of the eight open PRs that touch the same source and merge cleanly with main. What follows are two places where an assertion is weaker than its title says, and an answer to the question the PR leaves open.
Blockers
None.
Major
None.
Minor
R1-1. test/compression-drain-lifecycle.test.ts:187-188: the "starts nothing" half of the test only watches about 50 timer turns.
After the drain logs the thrown tick, the test waits turns(50) (fifty setTimeout(0) hops, a few tens of ms) and then asserts calls.length === 1. A drain that restarts itself on any longer timer gets past it.
- Reproduced at
main's source: I added, afterautobiographical.ts:7543:All 8 tests in the file pass, and so does the whole suite (setTimeout(() => { if (!this.store?.isClosed()) this.driveSpeculativeDrain(ctx); }, 150);
scripts/test-each-file.sh, 200 files). Without theisClosed()guard the file does fail, but only at file level: the stray timer touches a closed store after the test has ended. This test doesn't catch it. - Why it's plausible: the likely form of this regression is a drain that re-arms after the admission's
retryAfterMs. That is exactly the error this test throws. It throws it withretryAfterMs: 0, which makes an immediate re-arm visible and a delayed one invisible. - Fix: give the deferral a small non-zero
retryAfterMs(say 100). Then, once the error line is logged, wait a real 300–500 ms before asserting that no call was made. Alternatively, mocksetTimeoutfrom the start of the test and step the timers yourself.
R1-2. test/compression-ladder-options.test.ts:348: the assertion standing for "records nothing on the merge" can't fail.
mergeQuarantineCount === 0 stays true even when deferrals are counted.
- Under your review-added breakage (a deferral counts in the streak but isn't ordered or moved), the eighth counted deferral records one rejected attempt.
mergeAttemptLimitdefaults to 5 (autobiographical.ts:6977), so nothing gets quarantined within ten deferrals.- What a probe of this test's script showed at
mainplus that breakage:- outcomes:
rejected×8, thenresolved, thenrejected; mergeQuarantineCount0;getCompressionDebt().mergeQueueMaxAttempts1.
- outcomes:
The test still fails under that breakage, but only through the assert.rejects in the loop. Line 348 and its message ("quarantine nothing") check nothing.
- Fix: assert the rule directly. It reads 0 at
mainand 1 under the breakage:Keep the quarantine line or drop it.assert.equal(strategy.getCompressionDebt().mergeQueueMaxAttempts, 0, 'ten deferrals, eight after a landing, record no attempt on any merge');
R1-3. The question under "Not verified" has an answer: the code is intended, and the doc at src/types/strategy.ts:1621 is stale.
- The
max(16000, round(targetTokens * 1.5))reserve came in with 1bb8e47 (2026-07-01). Its comment atautobiographical.ts:9831-9833reads "Was* 1.5(=3000 at the 2k default)". - 2,000 is the default of
summaryTargetTokens(:9556).targetChunkTokensis documented as ~3000 (src/types/strategy.ts:1390) and falls back to the chunker's 4096 (:3042). Neither is 2k. - The doc sentence naming
targetChunkTokenscame later, with a7376f6 (2026-07-26, thecompressionMaxTokenscap). It named the wrong option.
So an L1 request asks for max(16000, summaryTargetTokens × 1.5) pins the intended side, and it won't "turn round with the fix".
- Fix: change the doc's
targetChunkTokenstosummaryTargetTokens. It's a comment-only change: it can go in this PR (then the description's "nothing undersrc/" needs a word) or in a follow-up. Either way, drop the hedge from the description.
Verified fine
- Scope: four test files, +1,027/−0, nothing under
src/.git diff --checkis clean. - Build and suite:
tscexits 0 at the head, on Node 22.22.1 with the lockfile's membrane 0.9.0 and chronicle 0.5.1. The whole suite through CI's runner (scripts/test-each-file.sh) passes: 200 files. CI is green on 22.12.0. - No leaked handles: each new file passes under plain
node --test, without--test-force-exit, and exits promptly (0.5–1.3 s). - Order independence: each of the 30 tests passes run alone (
--test-name-pattern), despite the module-levelsaidcounters. - No flake seen: 48 runs of the four files, 16 at a time on a host already at load ~25 on 26 cores, all passed.
- Citations: every
src/line the breakage table cites matchesmainexactly. - Breakage table, re-run: I wrote my own edit for 34 of the 35 rows; the one I didn't reproduce is the stub row after
:9592. The review-added two-site row (:7975with:7999–8000) I ran through the test and the probe above.- Each edit fails the named test, and only that test in its file.
- One extra edit also fails its test: the window default set to 79, so the 80 is pinned from below too.
- Whole-suite runs: seven rows (
:4837,:7618,context-manager.ts:967,:5497,:7975,:11334,:12468) ran against the whole suite. Each fails only this PR's file. That settles the first "Not verified" item for those rows. - Thinking-wrapper recovery: turning the recovery off entirely is caught by
compression-recall-curve.test.ts. So the positive half of that rule is pinned elsewhere, and this test's "reads only…" framing is the right one. compressionSourceOnlyon merges is new coverage:source-only-l1.test.ts's "MERGE INVARIANT" test (:357-371) looks like it already covers that rule. Under the:12468breakage it still passes 17/17, because its one seeded recall fits under the 8,000-token floor. Only the new test catches it.- Open PRs: I put the four files on
mainmerged with each open PR that touchesautobiographical.tsorcontext-manager.ts: #416, #417, #423, #369, #409, #414, #410, #364. All 30 tests pass on each. Not checked: - afc226c's membrane claim holds. In membrane 0.9.0:
providers/anthropic.jsturns an overloaded gateway error intoserverError(message, 529, …), which has typeserver;MembraneErrorTypehas nooverloadedmember. The'overloaded'inretry.jsis a retry class, not an error type.
- Negative log assertions are live today. With the switch removed (default alarm interval,
auditOnlyoff), the same regexes match 2, 2 and 1 times. The alarm wording is also pinned positively elsewhere (compression-transient-ladder.test.ts:3088,merge-quarantine-hole.test.ts:645). - Hooks and seeding:
shouldCompressPreflight()andchunkPersistenceEnabledare protected, documented extension points, and nothing reaches into private members. Seeding state through thedefault/autobio:*keys followschunk-persistence.test.ts. - Cleanup: spies, the
Datemock andCONTEXT_MANAGER_COMPRESSION_LOGare restored throught.after/finally, and temp dirs are removed. - Not a finding: all four files parse
getPendingWork().description(documented as human-readable,src/types/context.ts:91) for queue counts. Each use is a premise or the thing under test, and a rewording fails loudly rather than leaving a test that passes without checking anything.
Method. Two passes, merged after re-checking each claim.
- Codex (
gpt-5.6-sol, reasoningxhigh): read-only sandbox with no network, so it read the diff,src/and the installed membrane/chronicle builds but couldn't build or run anything. About 10.5 min, 132 shell commands, 7.72M input tokens (7.43M cached), 34.4k output (20.9k reasoning). - Claude: checked freshness against
main, built, and ran the whole suite. Ran the tests alone and under load, ran the source edits and the whole-suite runs, merged the open PRs, and ran probes. - Who found what:
- R1-3 was found by both: Codex reported it as a pre-existing doc error.
- R1-1 and R1-2 were Claude's alone; both needed runs.
- Codex's one finding against the PR, that an existing test already covered the
compressionSourceOnlymerge rule, didn't hold up when run (see Verified fine). - Codex also confirmed that the fail-closed guard's
this.compressionQueue = [](:17909) is a dead store. The description already says so. That one is left for a maintainer to file, not this PR.
- Not reached: the stub row after
:9592wasn't reproduced. Only seven rows ran against the whole suite.
…d pin that a deferral records no merge attempt Answers review R1 of this pull request (R1-1, R1-2). R1-1: "the drain starts nothing after a tick that threw" waited fifty zero-delay timer turns before checking that no call was made, so a drain that restarted itself on any longer timer passed it. The test now mocks setTimeout and Date once the manager is open, steps the clock until the drain logs the thrown tick, then moves it on an hour in one-second steps and checks that no call was made. The deferral it throws asks for a recheck after 100 ms, so a drain that re-armed at the admission's retry would come due inside that hour. R1-2: the check standing for "records nothing on the merge" read mergeQuarantineCount, which stays 0 even when deferrals are counted, since quarantine takes mergeAttemptLimit rejected attempts. It now reads getCompressionDebt().mergeQueueMaxAttempts, which is 0 only while no deferral has recorded an attempt on any queued merge. Each was run with one source edit and without: - a drain that, after logging the thrown tick, starts again 150 ms later, 60 s later, or after the error's retryAfterMs fails the new drain test. The first two pass the old one; the third fails it too, since the old test's deferral had a retryAfterMs of 0. - a deferral that adds an attempt to its merge fails the new ladder test, and passes the old one.
…ch landing, and the recall budget's values Three checks said more than they pinned. - "the drain starts nothing after a tick that threw" waited for any line with the drain's error prefix. It now waits for the line to carry what the tick threw, as the description of the rule says. - "a merge the caller's provider admission defers keeps its place" checked that the deferred merge was asked again first only after the first two deferrals. It now checks after each of the eight that follow an L1 landing too. - "each retry of a merge a provider rejected halves the merge's recall budget, down to an 8,000-token floor" had earlier merges of 12,000, 6,000 and 6,000 tokens, which a floor of 7,000 or 9,000, or a factor of 0.49 or 0.52, left with the same recall counts. With merges of 300, 7,800 and 7,800 tokens, and the recalled ids compared in place of their count, 16,000 holds the two 7,800s but not the 300 beside them, and 8,000 holds one 7,800 but not the 300. Each was run with one source edit and without: a drain error line that leaves out the failure, a deferral that moves the merge behind from its third deferral on, a floor of 7,000 or 9,000, and a factor of 0.49 or 0.52 each fail the new test, and pass the old one.
|
@Anarchid-2093, this pull request is now at
Esther-2584 made this round, and Gideon-2613 read it. |
|
@Anarchid, the comment above is our answer to your review R1. Its opening @-mention didn't point at your account, so this comment is to let you know it's there. — Esther-2584 |
This adds 30 tests in four new files, and changes nothing under
src/. They pin rules of the autobiographical strategy's compression lifecycle that no test checked: the tick and its drain, compression holds, the ladder's rungs and options, what a store already holds, and the quarantine alarms. Each test passes atmain's code and fails when a statement its rule rests on is broken: 45 breakages, each failing its own test.@Anarchid, @slimepriestess and @antra-tess, we're asking one of you to review this before it's merged. It adds tests alone, so nothing a resident sees changes.
Problem
At
fb4cf1046, each rule here had no test that fails when it breaks. With each breakage in the table under Tests applied in turn, except the thirteen marked as added or rewritten in review, every test file that runs its line, by coverage at that commit, still passed, and so did the files that readsrc/as text.The rules come from the library's own docs and comments where they state them, and otherwise from what
src/strategies/autobiographical.tsdoes at that commit. For one rule the doc and the code disagree: an L1 request's output tokens. The doc ofcompressionMaxTokens(src/types/strategy.ts:1621, and the published types) says the summarizer asks formax(16000, targetChunkTokens * 1.5), and the code multipliessummaryTargetTokens(src/strategies/autobiographical.ts:9556,:9834). The code is the intended side. The ceiling already multipliedsummaryTargetTokensbefore1bb8e476(2026-07-01) added its 16,000 floor, and that commit's comment (:9831–:9833) gives the earlier value as* 1.5"(=3000 at the 2k default)": 2,000 issummaryTargetTokens' default, andtargetChunkTokensis documented as ~3000 (src/types/strategy.ts:1390). The doc's sentence came later, witha7376f6a(2026-07-26), and named the other option. The test pins the code, and this pull request leaves the doc as it is.Changes
Four test files, +1,050 lines, one commit each, and three more commits, added in review, in three of them (under Tests). Each test's title states its rule.
test/compression-drain-lifecycle.test.ts, eight tests, the tick, the drain and holds:tick()warns, makes no call and leaves the closed chunks queued;holdBlockedIds), so the chunk behind it in the queue is an earlier one, put there by a transient failure;shouldCompressPreflight()decides whether a drain starts only when no merge is queued;test/compression-ladder-options.test.ts, twelve tests, the ladder's rungs and options:max(16000, summaryTargetTokens × 1.5)output tokens, the floor included, andcompressionMaxTokenscaps it (two tests);recoverLiteralThinkingWrappedCompressionreads only an answer of text blocks alone;compressionRefusalCurveFallbacksis given asundefined;compressionSourceOnlyleaves the recall of a merge as it is;getCompressionDebt().mergeQueueMaxAttemptsstays 0), where counted failures would end its run of failures at the eighth and record one rejected attempt, which counts towardmergeAttemptLimit;maxSpeculativeL1s.test/compression-persisted-state.test.ts, seven tests, rules that turn on what a store already holds:auditOnlyopen keeps a persisted merge the current grammar refuses.test/compression-alarms-logs.test.ts, three tests:quarantineAlarmIntervalMs: 0sounds no repeating alarm for a quarantined chunk, nor for a quarantined merge, at once or past the default 15-minute interval; and a pause writes acompression:lane-pausedevent to the fileCONTEXT_MANAGER_COMPRESSION_LOGnames.How the tests reach their cases:
ContextManager's adds, holds, ticks and reopens, and the strategy's config options.test/chunk-persistence.test.tsseeds chunk records: chunk records, summaries, the merge queue and the merge quarantine.shouldCompressPreflight()that returns false, astest/drain-timer.test.tsoverrides it, and achunkPersistenceEnabledthat returns false, the opt-out its doc names for strategies with their own chunking.mock.timersonDate, astest/compression-transient-ladder.test.tsdoes. The test of the drain after a thrown tick mockssetTimeouttoo, and steps the clock on an hour.Tests
On Linux 6.12 with Node 24.22.2 and npm 11.19.1, in a clean checkout of
e67cd7c0b, the first head, afternpm cifrom the lockfile, which installed@animalabs/membrane0.9.0 and@animalabs/chronicle0.5.1.npx tscexits 0, and each new file passes run alone withnode --test --test-force-exit: 8 of 8, 12 of 12, 7 of 7 and 3 of 3. The 30 tests took about 1.2 s together, on a machine at a load of about 7 on 12 cores.afc226c37, added in review, makes the transient failure in the drain-lifecycle tests and the lane-paused log test what membrane reports for an overloaded provider, typeserverwith status 529, in place of a type membrane doesn't produce. In a clean checkout ofafc226c37afternpm cias above,npx tscexits 0 and each new file passes run alone: 8 of 8, 12 of 12, 7 of 7 and 3 of 3. The 30 tests took about 1.2 s together, at a load under 3 on 12 cores.009635f96, added in review, makes two checks able to fail where they couldn't: the drain test above now lets an hour of mocked time pass before checking that nothing restarted the drain, where it had waited fifty zero-delay timer turns, and the deferral test reads the merge's attempt count, where it had read the quarantine count, which stays 0 untilmergeAttemptLimitattempts. In a clean checkout of009635f96afternpm cias above,npx tscexits 0 and each new file passes run alone: 8 of 8, 12 of 12, 7 of 7 and 3 of 3. The 30 tests took about 1.4 s together, at a load under 3 on 12 cores.439c7d079, added in review, makes three more checks pin what the tests' titles and this description say: the drain test waits for its error line to carry what the tick threw, the deferral test checks which merge is asked after each deferral, and the recall-budget test's earlier merges, of 300, 7,800 and 7,800 tokens, are sized so that a floor or a factor near 8,000 and one half changes which of them are recalled. In a clean checkout of439c7d079afternpm cias above,npx tscexits 0 and each new file passes run alone: 8 of 8, 12 of 12, 7 of 7 and 3 of 3. The 30 tests took about 1.3 s together, at a load under 1 on 12 cores.Then, at
439c7d079, each breakage ofsrc/below was applied alone, rebuilt and its file run the same way. Each fails its own test. The other tests in its file pass, except where the table says.autobiographical.tsunless named):7617, the no-membrane warning removed:7618, thereturnafter it removed (tscreports 5 errors and still emits)tick()rejects:7678, a held chunkcontinues the scan instead of ending it:19240, a release starts no drain:7420, an ended pause still shows in readiness:7543, a drain a thrown tick ended is resumed:7543, the drain's error line removed:7543, a drain a thrown tick ended starts again 150 ms later (added in review):7543, the same 60 s later (added in review):7543, the same after the error'sretryAfterMs(added in review):7543, the drain's error line leaves out what the tick threw (added in review):7492, a false preflight stops a drain with a merge queuedcontext-manager.ts:967, a release ignores the add's shard group:9592, a stub ends the pause as an answer would:9834, the reserve multipliestargetChunkTokens:9053,compressionMaxTokenscaps nothing:11593, recovery reads answers with reasoning blocks too:11334, the per-chunk split cap's default is 20:11348, the per-chunk cap compared with>for>=(added in review):11336, the window cap's default is 160:7663, a chunk waiting for its window ends the scan:4837, the variants' default count is 2:11068, a canonical rejection still tries the variants:12468,compressionSourceOnlyzeroes a merge's recall too:12471, a retried merge's recall budget isn't halved:12470, the recall budget's floor is 7,000 (added in review):12470, the floor is 9,000 (added in review):12471, each retry multiplies the budget by 0.49 (added in review):12471, each retry multiplies it by 0.52 (added in review):7975, an admission deferral counts toward the merge's streak:7975and:7999–:8000, a deferral counts in the merge's streak, but isn't ordered as failed or moved behind (added in review):7975, a deferral adds an attempt to its merge (added in review):7975, a deferral moves its merge behind from its third deferral on (added in review):7565, held L1s aren't counted toward the cap:17906, the fail-closed guard needs 4 records:17910, FAIL-CLOSED logs at every rebuild:9526, a fully covered chunk's record is marked compressed:8470, an overlap-blocked chunk isn't counted as debt:9540, the overlap guard logs at every attempt:5631, the sweep keeps a record whose chunk is compressed (rewritten in review to compile):6526, the topology record's clear logs nothing:3150, anauditOnlyopen sanitizes the merge queue:5497, an interval of 0 doesn't disable the chunk alarm:7126, an interval of 0 doesn't disable the merge alarm:6175, the pause's log event iscompression:lane-pauseOne more breakage fails no test in its file, and no test here is meant to catch it: removing the fail-closed guard's
this.compressionQueue = [](:17909).rebuildChunksempties the queue first (resetChunks(),:17836, which clears it at:17821), and nothing queues work before the guard, so that line removes nothing.Not verified
Esther-2584 wrote the tests and this description, Gideon-2613 read the tests and checked the runs, and Oscar-1005 placed the work.