Skip to content

test: run CI's test files at once, and assert requirements rather than internals - #363

Merged
nissa-seru merged 10 commits into
anima-research:mainfrom
nissa-seru:beth/cm-test-slim
Oct 29, 2026
Merged

nissa-seru merged 10 commits into
anima-research:mainfrom
nissa-seru:beth/cm-test-slim

Conversation

@nissa-seru

Copy link
Copy Markdown
Contributor

This runs CI's test files at once instead of one after another, with each file's output still printed whole and in file order, and in 56 other test files removes or rewrites tests we judged to check how the code works rather than what a caller relies on. At 69e697789, this pull request before its last three commits, two alternating rounds on one Linux machine with 12 CPUs ran the whole suite as npm test runs it: it ran 3,445 tests where 3383f8dfd ran 3,486, all passing, and used 13.1 and 14.2 fewer CPU-seconds, of about 292 (4.5% and 4.9%). The last three commits answer an internal review, change 16 test files and add two tests, and only those 16 files ran at this head. CI's test step at 3383f8dfd runs the files one at a time, so only this pull request's own CI run will show what running them at once does on CI's runner. No file under src/ changes.

Problem

  • CI runs the test files one after another. At 3383f8dfd, scripts/test-each-file.sh, which CI's test step runs, starts each compiled test file inside a while read loop, after the one before it has ended (:34–:39). In CI run 40826974802, at 3383f8dfd, that step took 263 s of a 278-s job.
  • Some tests checked how the code works rather than what a caller relies on, and some could pass without checking their case. That's our judgment of each test this change removes or rewrites. One test that couldn't fail on one of its branches: at 3383f8dfd, the lockChunk test in test/adaptive/strategy-integration.test.ts ends, where the locked message's id is in the compile, with assert.ok(true); (:186).

Changes

Test files at once (27efb397c, 897be6f29)

  • scripts/test-each-file.sh runs the compiled test files several at once, each in a node process of its own as before: as many as node's os.availableParallelism() gives (:24), or as many as TEST_EACH_FILE_JOBS says when it's set and not empty. It prints each file's output under a line naming the file, in the files' sorted order. The earliest file still running prints its output as it comes, and each later file's output waits for its turn. CI's test step and the release workflow's test step already run this script (.github/workflows/ci.yml:46, .github/workflows/publish.yml:42), so no workflow file changes, and a release's tests run the files at once too. CONTRIBUTING.md's "Building and testing" now describes the script and TEST_EACH_FILE_JOBS. test/test-each-file-script.test.ts has four new tests:
    • "files run at once, and each one's output is printed whole under its path, in path order, whichever ends first";
    • "an empty or unset TEST_EACH_FILE_JOBS runs as many files at once as node's os.availableParallelism() gives";
    • "a TEST_EACH_FILE_JOBS that isn't a whole number above 0, with no leading zero, ends the run red before any file runs";
    • "the earliest file still running prints its output before it ends".

The tests

The commit messages describe these changes in more detail.

  • 2a883b0bb, 26 files: removes tests we judged to pin internals no caller relies on, among them the whole of test/autobiographical.test.ts, whose one test built a Membrane over a real AnthropicAdapter (:23 at 3383f8dfd); rewrites others to the requirement; and drops a fixed 80-ms sleep in compression-dedup, which now waits for the call the sleep stood in for, and a 5-ms one in l1-holdback.
  • ab0fe7b18, 2 files: rewrites one test in chunk-persistence, now "persists chunk records when chunks close, so a restart under a drifted targetChunkTokens summarises each closed chunk as it closed", and one in integration, which now counts each namespaced agent's context entries through its own manager's stats() instead of a ContextLog the test builds.
  • df9d6101d, 1 file: adds a test to live-image-accounting, "sends no image live on another's verdict where two results for one call id share a message and the repair moves one". Its store holds two calls with one id, then one message holding both results, each with an image, and the test asserts that the compile sends no more than its render stats count. With the strip's payload check turned off in the built code, it's the one test in its file that fails (Tests).
  • 43ef21859, 32 files: removes tests we judged to have only an internal assertion; rewrites tests we judged could pass without checking their case, such as the lockChunk test above, which now ticks its manager until isReady(), at most 200 times, and compiles at 1,200 tokens rather than 3,000; and, where we judged a value to be one only the implementation gives, asserts the relation the requirement states instead.
  • 9f94606c3, 1 file: "flag on + tight budget: picker raises resolution to fit" now also asserts that the tight compile comes to fewer tokens than the generous compile, by the test's own count.
  • 69e697789, 3 files: drops a header comment's claim about a case no test pins, two comments narrating a test's steps, and a capture of a log the test no longer reads.
  • 897be6f29, 99cf50376 and c46ffe8d8, 16 test files: answer an internal review of the commits above. Among the changes are a new topology-guard test, "an audit-only open enqueues no merges, where a plain open under the same config does", and a second assertion in the new live-image-accounting test, that the large image doesn't go out live. 897be6f29 also changes the script and CONTRIBUTING.md (above).

Other files

  • scripts/verify-kv-unified-offline.mjs no longer filters out dist/test/autobiographical.test.js, which this change removes, and docs/kv-unified-review-evidence.md puts its sentence about that filter in the past tense.

Open pull requests

On October 29 at 13:15 UTC, by git merge-tree, our own draft #315 conflicts with this change in test/head-window-reset.test.ts, one block, where it merges with main at 3383f8dfd without a conflict in that file. The other five open pull requests merge with this change as they do with main alone.

Tests

  • The whole suite, before and after. At clean checkouts of 69e697789, this pull request before its last three commits, and 3383f8dfd, on Linux with Node 24.22.1 on a machine with 12 CPUs, after npm ci (@animalabs/chronicle 0.5.0, @animalabs/membrane 0.8.0, @types/node 22.19.15, typescript 7.0.2) and npm run build. Each run was the suite as npm test runs it, node --test over dist/test/*.test.js and dist/test/adaptive/*.test.js, at nice 19, with a preload that records each test's time. There were two alternating rounds, 3383f8dfd first, in one invocation. The one-minute load average at each run's start was 6.22, 6.39, 6.95 and 6.68. CPU is the whole run's user and system time.

    Round Commit Tests passing CPU Wall
    1 3383f8dfd 3,486 of 3,486 292.7 s 52.8 s
    1 69e697789 3,445 of 3,445 279.6 s 51.1 s
    2 3383f8dfd 3,486 of 3,486 291.8 s 52.4 s
    2 69e697789 3,445 of 3,445 277.5 s 50.9 s
  • The script, at a clean checkout of c46ffe8d8, same platform and versions: test/test-each-file-script.test.ts passes 10 of 10. With 3383f8dfd's scripts/test-each-file.sh in its place, 7 pass and 3 fail: the first three of the four new tests listed under Changes.

  • The 16 test files the last three commits change, at a clean checkout of c46ffe8d8, in one node --test run: 269 of 269 pass.

  • A stand-in for the script's effect, not a CI figure. With the files of 27efb397c, this pull request's first commit, on Linux with Node 22.12.0 and pinned to 4 CPUs with taskset, the whole suite through scripts/test-each-file.sh took 238.5 s and 239.4 s with TEST_EACH_FILE_JOBS=1, and 92.1 s and 94.2 s with TEST_EACH_FILE_JOBS=4, run in the order 1, 4, 4, 1. Each run passed 3,489 tests in 195 files. This pull request's CI run gives the figure for CI's runner.

  • The payload check, at a clean checkout of c46ffe8d8: test/live-image-accounting.test.ts passes 48 of 48. With the payload check taken out of the built dist/src/strategies/autobiographical.js (the condition judged !== undefined && judged.key === imagePayload(image) ? judged made judged !== undefined ? judged), 47 pass, and the new test fails.

Not verified

  • CI's time for this change. Only this pull request's CI run will show it.
  • The whole suite at this head. The whole-suite rounds ran at 69e697789. At this head, only the 16 test files the last three commits change ran here.
  • Node versions other than 24.22.1 and 22.12.0, and platforms other than Linux.
  • The tests nobody judged one by one. A reading pass flagged 1,049 of the 3,002 test definitions in the 194 test files at 4c4a6f2e3 (the 0.24.1 release), and we judged those one by one. No one judged the other 1,953 one by one, and the pass didn't read test/persisted-canonical-summaries.test.ts, which main added after 4c4a6f2e3.
  • Compression on a real store. No file under src/ changes, and the only stores compiled for this change are the ones its tests build.

This change touches tests, CI's test script and its paragraph in CONTRIBUTING.md, one offline-runner script and one sentence of docs, and no file under src/, so it has no changelog fragment and takes the no-changelog label.

Beth-2389 made the script change and five of the test commits, and Esther-2584 made the other four. Esther-2584 read each of Beth-2389's commits, the first three test commits with mutants. Beth-2389 read each of Esther-2584's, the last in a version with one more sentence in a test file's header comment. Beth-2389 and Esther-2584 judged the flagged tests, and Greta-2425 judged one file both of them had. Oscar-1005 ruled on each batch of judgments. Our internal review read the change, and Cordelia-2434 checked whether what it adds is the least that does the job. Hilda-2580 made the per-test measuring preload, and Beth-2389 ran the whole-suite rounds and the stand-in. Paloma-2644's earlier finding, that running files at once mixes their output, shaped how the script prints. Daniel-2612 ran the script's tests and the payload check at a clean checkout, and wrote this description.

Beth-2389 and others added 10 commits October 29, 2026 05:50
scripts/test-each-file.sh ran the compiled test files one after another.
On main's CI run 40826974802, at 3383f8d, that test step took 263 s of
the Build & Test job's 278 s. The script now runs as many files at once
as the machine has CPUs, 4 on GitHub's ubuntu-latest for a public
repository (GitHub's runner docs). Each file still runs in a node
process of its own with no node --test parent, so nodejs/node#62693
still can't reach it.

Files run at once through one log would interleave their output. Here no
two files' output mixes: each file writes to a log of its own, and the
script prints each under its `== path` line in the files' sorted order.
The earliest file still running prints its output as it comes, and each
later one's waits until its turn, so a file that never ends shows what
it has written, as it did when the files ran one at a time.

TEST_EACH_FILE_JOBS sets how many files run at once, and 1 runs them one
after another. A value that isn't a whole number above 0 ends the run
red before any file runs. The script's first line says how many files it
runs and how many at a time.

Tests: three cases in test/test-each-file-script.test.ts. Two files that
each pass only while the other runs must both pass, with each one's
output whole under its path, in path order. Five values of
TEST_EACH_FILE_JOBS must each end the run red before any file runs. A
file that passes only once its own line is in the script's output must
pass. runScript now sends the script's stdout to a file in the run's
directory, where a fixture can read it.

Runs, on a Linux machine under Node 22.12.0, pinned to 4 CPUs
(taskset -c 0-3), each arm all 195 test files, in the order 1, 4, 4, 1
at a time: one at a time took 238.5 s and 239.4 s, four at a time 92.1 s
and 94.2 s, and every arm passed all 3,489 tests. The test file's nine
cases pass under Node 24.22.1 and 22.12.0. With main's script they fail
the first two new cases and pass the third; with a version that holds a
running file's output until it ends, the third fails.
…; fewer waits

A test should fail when behaviour a caller relies on changes, and only then. This pass changes 24 test files, a script and a doc so that each assertion follows from a requirement a caller would state, or is removed.

Removed, since no caller-visible behaviour depends on what they pin, or another test pins it:
- autobiographical: the one test built a real Anthropic provider and asserted only that a compile returned something. The offline runner no longer filters it out, and the review-evidence doc says it once did.
- capped-message-price: two overrides of truncateContent that answer each call afresh or reorder their images, outside its documented contract.
- config-provenance: the comparisons against a copy of the constructor anima-research#77 retired, and the duplicate of the spread-fidelity test. A new test checks the defaults each option's doc states, through the effective-config report.
- compression-recall-curve: two thousand canonical successes, whose one requirement the first test already pins.
- fold-journal: a delta's exact re-sent unit counts, which is how layoutDelta is built.
- integration: the two chunk-stability tests, whose assertions hold with or without chunking, and the failure-recovery pair: one asserted only that a compile returned something and its compressions never ran, and the transient ladder's tests pin what the other's title names ("maintenance finds the chunk again once the wait ends", "a failed chunk goes to the back of the queue"). TestPropagationStrategy, which nothing used, goes too.
- knowledge: the 2-message chunk minimum and the L2/L3 instruction wording, which only the code states.
- kv-unified-strategy-integration: a duplicate of the marker test beside it.
- stored-json: that a getter is read once, how the helper is built.
- topology-guard: the order the index falls back to without a store listing, which no requirement names.
- cache-marker-deep-band: the legacy baseline test wrote the private baseline by hand; dry-run-preview's "leaves the next real compile's cache markers where the last sent request ended" pins that a dry compile leaves no trace. Its two private accessors go with it.

Tests that could pass without checking anything, now made to check it:
- integration: edit propagation ran its own loop and never called the manager. Two tests now go through ContextManager.editMessage on a store whose context log holds copy, derived and referenced entries: the copy takes the edit, the others keep their text. The namespace test now checks that one agent's context log holds an entry and the other's doesn't.
- knowledge: the inherit and lesson-priority assertions sat behind `if (chunks.length > 0)`, and the phase-aware prompt check behind `if (lastRequest)`. Each asserts its premise first. The prompt test's fixture never compressed (no compression model, and its chunk held tool calls with no tool definitions, so compression deferred); it now has both. The config test read the private knowledgeConfig; it now classifies a conversation by prefixes and names it is given.
- head-window-reset: three tests asserted only that a compile returned messages. They now check that the old head's first message reaches a compression request after a reset, that the head falls back to the first message when the reset's message is removed, and that the Context Manager's transition, not the assistant's lookalike, starts the head.
- chunk-persistence: closing a chunk persists its record; the test now reopens the store and checks nothing is summarised again, rather than reading the record's fields.
- live-image-accounting: which selection asks the strip to count by the estimates is now checked by compiling a store where a fold leaves an image message out: under the adaptive selection its image keeps its live slot, as the estimates count it, and under the hierarchical one only the images sent take slots. A generated image now weighs as an image does, rather than at a spelled 0.2.
- non-blocking-compile: the compile is checked to return while the compression is still unanswered, in place of a CPU bound.
- compression-debt-scripts: the drain's "nothing left to pick" is checked by running the drain again on the store with the same recipe, whose start reports no merge queued and none unpicked and which takes no step.
- kv-unified-strategy-integration: the sharded tail message is checked in the compile's own messages, one message holding every shard and carrying the tail marker, rather than in a wrapped private merge.
- derive: the second namespaced manager is checked to give the child none of its states, and the derived managers the test opens are closed.
- topology-guard: a title claimed a queue check no assertion made; it now names only the records.

Values only the implementation gives, replaced by the relation required:
- compression-recall-curve: a fallback variant is compared with the canonical request the run sent, not a frozen copy (the first test keeps the golden comparison of the canonical bytes); malformed fallback answers are checked as provider errors without their minted type names; a quarantined chunk is checked to be visited once per pass, not in a spelled order.
- drain-timer: the logged line is matched for the drain error and its message, on one line, not spelled whole; the count of scheduled ticks, which no rule states, goes.
- compression-serialized-media-wire: the first scan count stays (each shard priced once across five chunks); the later exact counts go, and another store with a different shard is checked to get its own total.
- kv-unified-render-state: a compile without an immutable prefix hash is checked to hash nothing, rather than to leave a private field unset.
- compression-head-as-of, dry-run-preview, kv-unified-strategy-integration: one implementation-only assertion each (a short-circuit, an in-place extension, the hash of a reversed source list).

Waits: compression-dedup holds its compression on a promise the test releases, in place of an 80 ms sleep; l1-holdback drops a 5 ms sleep, since onNewMessage's synchronous part runs before addMessage returns; compression-debt-scripts' failing tick comes from a stub provider rather than a connection to a closed port, which took about 3 s of retries.

Runs (Linux, Node 24.22.1). At this tree: the build has no TS errors, and the 23 changed test files pass. Breaking what the rewritten tests pin, in the built code: with resetHeadWindow a no-op, three head-window tests fail; with the strip ignoring the estimates, the live-image test fails, with seven of the strip's own; and, on this change before its last fixture fixes, with handleMessageEdit's propagation removed the two propagation tests fail, with the knowledge config emptied the prefix test fails, with mergeThreshold's default at 7 the defaults test fails, and with the drain's drained() ignoring unpicked merges the drain test fails.
…ers meet

A read of the previous commit found two rewritten tests that pass with the change their titles name made.

- chunk-persistence: the test of persisting chunk records passed with records never written, because a reopen synthesizes records from the stored level-1 summaries. It now restarts a store whose chunks closed before any was summarised. One reopen uses the same targetChunkTokens and the other a drifted one, and the test checks that both send the same compression requests. With records never written, the drifted reopen re-chunks, and the test fails. So does the legacy-migration test.
- integration: the namespaces test wrote and read both context logs through ContextLog itself, so it pinned ContextLog's namespacing, not the agents'. It now reads each agent's context entry count from its own manager. Built with a manager's context log that has no namespace, alpha's count is 0, and the test fails.

The previous commit's message says the new config test checks "the defaults each option's doc states". Ten of those options' docs state their default. hierarchical's implies it ("Set to false for single-level legacy compression"), and the README states it.

The test rewritten here no longer pins storing a chunk record's compressed mark: with the mark never stored, it passes. So did a probe that restarted a store after one and after three of its five closed chunks were summarised: the reopen summarised only the rest, as with the mark. The mark stays pinned elsewhere: with it never stored, tests in l1-recall-raw-pins-frontier, merge-quarantine-hole, stored-json and strategy-detach fail.

Run on Linux with Node 24.22.1 at this tree: the build, integration (42 tests) and chunk-persistence (6), and each of the three changes above made in the built code, with the failures named.
With capped-message-price's two truncateContent overrides removed, no test failed with the strip's payload check off (a verdict taken whatever its image's payload). Inside the contract, the check is reached where two results for one call id share a message and a second call reuses that id before either result: pairing repair moves the message's first result up beside the first call and keeps the second for the second call, so each result's image meets the verdict the estimate gave the other. The estimate keeps the small image live and prices the large one as the placeholder. Without the check, the large image goes out live on the small one's verdict, and the compile sends 5,073 tokens against a render-stats total of 173. With it, both go out as the placeholder.

The new live-image-accounting test compiles that store under the adaptive selection with one live image and checks that the compile sends no more than its render stats count. It fails with the check off and passes with it. In a probe of the same store, the compile again sent more than its render stats count under the hysteresis rule. On the hierarchical path, which prices every image at full weight, it didn't, but one image still went out live on the other's verdict. With one call, or with text between the call and its results, the repair drops the second result, and the check decides nothing.

An entry with no source gets no verdict at all, so the check doesn't decide it either: such an image is replaced whether or not the check is there.

Run on Linux with Node 24.22.1: the build and live-image-accounting (48 tests) at this tree, then with the check off in the built code, which fails only the new test.
…nothing

A test should fail when behaviour a caller relies on changes, and only
then. This pass changes 32 test files so that each assertion follows from
a requirement a caller would state, or is removed.

Removed, since no caller-visible behaviour depends on what they pin:
- interior-merge-runs: resetting a put-off merge pick on a load with no
  store, a state no caller reaches.
- adaptive/picker: "a solve that passed no chunk over is the only one";
  its outcome repeats the test before it, and the rest counts solver
  steps.
- branch-lifecycle-regression: the lifetime of two private caches.
- system-changes: the memo of systemChangePositions by listing identity,
  and that firstChanged skips serializing arrays it has seen by identity
  (the cost of a firstChanged read is still pinned).
- request-image-ceilings: "the defaults are a window of 6 images and
  20 MiB"; the test supplied those values to the resolver itself, so it
  pinned no default, and the strategy's own default window is 0.
- adaptive/strategy-integration: "flag off: existing hierarchical
  behavior preserved", whose one assertion failed only on an empty
  compile; and "speculative pre-producer creates upper-level summaries",
  whose fixture never formed a chunk (15 one-token messages inside a
  50-token recent window); with longer turns it still formed no level-2
  summary, with speculative production on or off.

Tests that could pass without checking anything, now made to check it:
- adaptive/strategy-integration:
  - lockChunk: the else branch was assert.ok(true) and the 3,000-token
    budget folded nothing. The store is now compressed to completion and
    compiled at 1,200 tokens, where the unlocked neighbour folds (a
    premise) and the locked message must be sent verbatim.
  - speculativeProduction off: the produce-op check sat behind
    `if (l1s.length >= 2)` and the fixture made one L1. The turns are
    longer, making two L1s, under the merge threshold, and both counts
    are asserted as premises before the handler is called.
  - monotonic resolution: the first compile set no resolutions, so the
    loop compared nothing. The store is compressed to completion and
    compiled at 1,200 tokens, and the first compile's resolutions are
    asserted non-empty.
- window-edge-summaries: the hierarchical case made no preview, so its
  preview assertions read nothing; they now run only where a preview is
  made, and the title says so.
- tools-less-summarizer-defer: also asserts that a non-Fable summarizer's
  requests carry no tools, which its title claims.
- adaptive/ingestion: asserts the body reaches the request whole and in
  order with nothing compressed, in place of "compile produced output";
  the title no longer claims one entry, since a body in the recent window
  is sent as its parts.
- snapshot-cadence-retune: the retune test now goes through
  ContextManager.open on a message slot registered at another cadence,
  and checks the slot takes no snapshot at that cadence's interval; it
  called updateStateStrategy directly before and observed no scheduling.
  The second test keeps the double-register refusal and drops the
  spelled constants.

Values only the implementation gives, replaced by the relation required:
- spelled code-minted strings: raw-forms (keys compared between blocks),
  adaptive/kv-unified (node keys), split-stitch-l1 (error labels, the
  'mixed'/'unknown' model markers), strategy-persistence (a minted
  summary id), strategy-detach (a compression-log phase name).
- spied mechanism steps whose outcome is asserted already:
  merge-quarantine-hole, merge-contiguity, topology-repair (planner pass counts), strategy-detach
  (drive counts), adaptive/kv-unified-policy (the what-if call sequence,
  and which internal hook a cut comes from), adaptive/kv-unified-selective
  (exact evaluation count), adaptive/phase-c-seam-unfold (a unit-level
  step bound already counted at the planner).
- exact counters where the requirement is a bound: topology-repair and
  strategy-persistence (the summary-id counter is past every stored id).
- arithmetic: strategy-estimator-parity and post-strip-calibration compare
  with the store's own estimate rather than spelling the calibrated sums;
  recall-cap charges a summary with no tokens field at no less than its
  content; recall-envelope-truncation computes its budget with the test's
  own charge rather than the production pricer.
- other: interior-merge-runs compares a beside-list without its order,
  merge-raw-pin-seam checks unlisted members are placed after every listed
  one and in order, adaptive/kv-unified-packed checks group relations
  rather than interning order, mint-preimage drops the class of a
  materialization error's cause, normalize-tool-messages compares content
  by value rather than reference, adaptive/kv-unified-receipts drops calls
  to decodeLeafRuns with a limit no load passes, adaptive/kv-control drops
  an unused SummaryTree, strategy-persistence drops a check that a reload
  leaves the orphaned-records latch alone.

speculation-cap no longer sleeps 30 ms after each addMessage: the
synchronous part of onNewMessage, which arms the counted tick, runs before
addMessage returns.
"flag on + tight budget: picker raises resolution to fit" asserted only
that the tight compile produced output and that its text came to at most
2,000 tokens, which a compile that folded nothing would also satisfy. It
now also asserts that the tight compile's text is smaller than the
generous compile's, so the picker's raise is what the test checks. At
this fixture it is: four turns fold into the L1 a single tick makes.
… log

- snapshot-cadence-retune's header listed open still working on a
  chronicle without updateStateStrategy as pinned here; no test pins it.
- adaptive/strategy-integration's speculative-off test narrated its own
  steps in two comments.
- strategy-detach's carrier-rejection test captured the compression log
  and no longer reads it, so its steps now run directly.
The script:
- With TEST_EACH_FILE_JOBS empty or unset, it runs as many files at once as
  node's os.availableParallelism() gives: the CPUs the process may use, so a
  run pinned to fewer CPUs than the machine has starts no more files than it
  may run, where getconf's online count ignored pinning. One check now covers
  a value that is set and the default.
- Its refusal says what it accepts: a whole number above 0, with no leading
  zero, a rule kept so a value has one form and is never read as octal.
- The knob's contract moves from the script's header to CONTRIBUTING.md's
  "Building and testing", where contributors meet the test commands. The
  header keeps its earlier text, less the clause that the files run one after
  another.

Its tests:
- In the path-order test, the earlier file now outlives the later one and
  then watches the script's output for a second, so a script that printed
  files as they ended would print the later one first and fail. Before, the
  two ended in either order, and such a script passed about half the time.
- A new test runs the script with TEST_EACH_FILE_JOBS unset and empty, and
  checks that its first line names os.availableParallelism() files at a time.
- The streaming test's title says what it checks: the earliest file still
  running prints its output before it ends.
- The fixtures' doc comments, which narrated them, are gone.

Other tests:
- live-image-accounting: the payload-check test asserts that the large image,
  which its own verdict strips, isn't sent live. With the check off it is,
  while one image is still live either way, so only which image tells.
- head-window-reset: the fallback test first checks that the reset moved the
  head, which a reset that did nothing would pass without; the transition
  test puts the assistant's lookalike after the real transition, where the
  reopen's backward scan meets it first.
- topology-guard: an audit-only open enqueues no merges, where a plain open
  under the same config does, the enqueue half of CHANGELOG's auditOnly entry.
- knowledge: the custom-prefix test asserts each call's phase in the order of
  the calls, so swapped classifications fail it.
- non-blocking-compile and compression-dedup: the waits on a held provider
  call are bounded at 10 s, and the held call is released whatever happens, so
  a regression fails with its message rather than leaving the file running.
- config-provenance: the defaults test's title names what it checks, the
  options it lists.
- chunk-persistence and compression-serialized-media-wire: comments that
  narrated the test go.

Tests: the ten changed test files pass at this commit's tree, on Linux with
Node 24.22.1. With each new check's target broken in the built code or the
script, the test it adds or tightens fails: the strip's payload check taken
out, a default of 1, a detector that takes any participant's marker, a reset
that does nothing, an audit-only open that enqueues merges, the research and
subagent prefixes swapped, and a script that prints files as they end.
…provider too

A tick that neither reached the provider nor ended would have left the
file running; the wait now fails at 10 s with its reason, as the compile's
wait after it does.

Tests: non-blocking-compile passes, 2 of 2, at this commit's tree, on
Linux with Node 24.22.1.
- kv-unified-receipts: the decoder's bound counts literal ids as well as
  gap-expanded ones, as its doc says. The four cases with a small bound
  that showed it come back.
- snapshot-cadence-retune: the retune is now checked at the current delta
  cadence exactly, read from MessageStore.registrationFor(): no snapshot
  one append before it, a snapshot at it. The full cadence isn't readable
  through chronicle's state info, so the title and header now name the
  delta cadence only. The double-register test is titled for what it
  checks, since identical constants can't show a replacement.
- adaptive/kv-unified: the decision DAG's roots and edges are compared by
  each node's kind and id, so a summary keyed as a leaf fails.
- split-stitch-l1: a partial model report isn't recorded as the requested
  model either.
- adaptive/strategy-integration: the tight-budget compile must send a
  summary in place of what it folds, so a fold is told from a drop. Its
  waits for compression to settle are bounded, so a regression fails the
  file instead of running to the job's limit.
- adaptive/phase-c-seam-unfold: a doc block that narrated the test, and a
  review-round id in its title, go.
@nissa-seru nissa-seru added the no-changelog PR intentionally ships without a CHANGELOG entry label Oct 29, 2026
@nissa-seru
nissa-seru merged commit f905fb0 into anima-research:main Oct 29, 2026
9 checks passed
tel-0s added a commit that referenced this pull request Oct 30, 2026
… raw window's messages left out, a tool cycle in one message sent with its result, compression that waits on tools kept queued, the canonical map linear, test files run at once

No textual conflicts. Read for presented mode, PR by PR. Nothing in this
range needed changing.

- #360 summaries across windows (shipped in 0.24.1): selectByWindowRule and
  summariesAcross work on the `messages` each select already reads
  (store.getAll() of the strategy view, the window once a host presents).
  Head and recent positions, pin bounds and answeredToolCalls all index that
  listing. Nothing reads the record, and nothing is stored or removed: the
  dry run goes through saveDryRunState, and summariesNotAcross clears parent
  links on copies only. Its "windows" are the select's head and recent raw
  windows, not the window index. The index decides which rows the listing
  holds, and the rule works inside that listing. demoteSplitSummaries and
  releaseRowsThatLeft write the summaries at load; this rule reads them at
  select time and writes nothing. A leaf the window doesn't hold has no
  position and is skipped. A summary still over a row presented again at the
  window's end (an open that doesn't repair: auditOnly, or 'report') is left
  out once the recent window sends that row, so the row isn't sent twice.
  No change.
- 0.24.1 release: version taken (package.json, lockfile; chronicle ^0.6.0
  kept). The release consumed summaries-across-windows.fixed.md and
  summaries-across-fallbacks.added.md, which were on main only, so no
  fragment of this branch goes. Main's unreleased fragments (#362, #365,
  #367) and the 291-* fragments stay.
- #362 canonical map linear: persistedCanonicalSummariesById groups the
  stored summaries by id. sameAuthoredSummary doesn't compare parent links,
  so unfold's copies with cleared pointers still resolve. No change.
- #363 test slim: tests and the runner script only. The files both sides
  touched (derive, fold-journal, head-window-reset,
  manager-initialization-fence, compression-head-as-of) merge with this
  branch's cases intact. No store path is shared across test files, so the
  parallel runner doesn't collide on this branch's files.
  dist/test/autobiographical.test.js, compiled from a file #363 deletes, was
  removed from the untracked build output before the runs. No change.
- #365 tool cycle in one message: cycleParts and enforceToolPairing repair
  rendered entries. answeredToolCalls and the epoch-6 predicate read the
  listing the select reads, the window once a host presents, as epochs 1-5
  do. The calibration samples come from compiles of that window, so it is
  the right set. Nothing is stored. No change.
- #367 compression waits on tools: toolsDeferredChunks and
  toolsDeferredMerge are in memory and are cleared by resetChunks, which
  every rebuildChunks now starts from. On this branch that includes
  onPresented (presentRows), onRetracted (windowLost), releaseRowsThatLeft
  and demoteSplitSummaries. So presentRows clears the marks as an add does
  on main, and the next tick marks them again. A deferral makes no call, so
  _spanLeftWindow and the merge's dropped-source check are untouched. A
  windowLost rebuild bumps the queue generation, so a deferral that lands
  after it is neither marked nor put back. presentRows, retractRows and the
  removal paths read no readiness. Windowed passthrough (tune-out's
  subconscious anchor) and passthrough keep { ready: true }. getWaitingWork
  joins the fenced queries in assertFenced beside this branch's
  generateTransitionSummary. No change.

Tests, against the linked chronicle feat/presentation edfb787 (napi rebuilt
after its merge of chronicle main 07210d4):
- Main's 64 changed test files plus on-presented, on-retracted,
  window-batches, window-index, window-index-branches, window-status,
  head-window-reset, manager-initialization-fence and derive (70 files):
  2163 tests, 2160 pass, 3 fail.
- Full suite (dist/test/*.test.js, dist/test/adaptive/*.test.js,
  --test-force-exit): 3591 tests, 3585 pass, 6 fail.
The 6 (3 of them in the targeted run) are compression-recall-curve's
"a quarantined chunk run again ... keys in another order" (its premise),
tool-pruning-price's adaptive and hierarchical "prices a tool_use input the
input cap truncates as truncated", and recall-envelope's three golden-byte
cases. Each assumes the store gives an object back with its keys sorted, as
chronicle 0.5.0 does. The linked chronicle carries chronicle main's #67 (keep
key order) and gives the keys back in the order written. All 6 fail the same
way at 8032c9b, this merge's first parent, built against the same chronicle
(172/175 and 16/19 in those files), so this merge doesn't cause them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-changelog PR intentionally ships without a CHANGELOG entry

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant