Repository navigation
fix(kv-unified): suggest producing missing levels only where that clears the conflicts (#256) - #259
Merged
nissa-seru merged 1 commit intoOct 19, 2026
Conversation
…ars the conflicts (anima-research#256) The infeasibility certificate's suggestion for a `constraint-conflict` was always "Release or reconcile the listed constraints, or produce the missing levels." The strategy puts it in the error a refused compile throws, so it's the line an operator reads. It told them to produce levels where that would clear nothing. On main, a lock against a pin at a level that exists, a pin at a level that is no integer, and a raw pin against a pin each give `missingLevels: []` with the clause. Two conflicts with a missing level get it too, though producing the level wouldn't clear them: a lock against a pin at a missing level, and a raw pin against an exact constraint at one. The certificate now suggests producing the missing levels only where every conflicting leaf, given the levels it requests, has a level all its constraints admit, and otherwise says "Release or reconcile the listed constraints." `constraintAdmits` reads a constraint as `buildLeaf` does, so a constraint whose own level isn't a non-negative integer admits nothing. Choosing the wording from `missingLevels.length` alone, as anima-research#256 suggests, would leave the lock and raw-pin cases above telling the operator to produce a level. The new test takes sixteen conflicts, on one leaf or two, and pins each one's missing levels and suggestion. It fails on main's certificate, and with each of twelve changes to the check, such as a floor admitting only its own level, a negative floor admitting every level, or only the last conflict checked. The over-budget test now pins its suggestion too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Required label not found on this PR. |
1 task done
tel-0s
added a commit
that referenced
this pull request
Oct 19, 2026
…mand, the sibling-append fix and store diagnostics What main brings since 021c0f3: #229, #230, #231 and #228 (latent joint demand, age bands, subtree memo, merged-view memo), #260 (a sibling's appends no longer cost a reader the whole slot), #259 and #253 fixes to kv-unified, #263 (call spreads past the argument limit), #262 (derive rebuilds a treeified forest in full), #117 (merge around a quarantined group), #129 (the witnessed identity reminder), #261, #264 and the namespace-scoped store diagnostics (#239). Conflicts, all in src/message-store.ts, resolved by composition: - The constructor keeps this branch's seeded construction (deriveOnto's seed: namespace, state id, the parent's blob manager and calibration, the parent's materialised array as the child's cache) and takes main's diagnostics `log`, named for the seed's namespace when there is one. - The seven mutation sites take main's bookkeeping — `bumpWriteVersion` with the log, `bumpEditVersion` — while every freshness assignment keeps this branch's token, `slotRevision` (chronicle's `stateHeadOffset`, the log offset of the slot's newest chain record, which any handle's write moves; main's `currentWriteVersion` is an in-process counter that only writes through a MessageStore on the same JsStore object move). - #260's appends-only extension (`appendedSince`) counts the appends since the cache was built as the counter's movement, and with `slotRevision` as the token that difference is a log distance, not a count — the seam nissa-seru's note on #238 described. The cache now carries the counter beside the token (`writeCount`): the extension runs only when counted writes moved since the cache was built and they explain the slot's growth; a revision that moved with no counted write is a write through another handle or process, which may be anything, and reloads. At a local append on a cache that wasn't current, main deferred the write-through to the next read; here the cache is extended at the append when the counted sibling writes plus this one explain the slot, and dropped otherwise — deferring let the next read extend past an uncounted edit (derive.test's surgeon through a branch view). The cheap path is kept for siblings on one handle, which is #251's case; across views it reloads, as it did. test/manager-diagnostics.test.ts accepts the two outcomes' lines beside main's "deferred". - `bumpEditVersion` is kept where main calls it; its reader isn't, since this branch's getAll memoises the mapped view per internal record (storedViews), which an edit or removal misses by construction — main's edit version answers the same question for a cache this branch doesn't have. The comment at the helper says so. Build and test on the composed rig: 2383 tests, 2383 pass, 0 fail. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
nissa-seru
pushed a commit
to nissa-seru/context-manager
that referenced
this pull request
Oct 21, 2026
…h constraintAdmits main's anima-research#259 (for anima-research#256) added constraintAdmits, the same rule as the hold's admitsLevel: whether a leaf constraint admits a level, with a constraint whose own level isn't a non-negative integer admitting nothing. levelPinHold now calls constraintAdmits, and admitsLevel is gone. constraintAdmits' doc adds that it reads the constraint alone, whatever the leaf's chain supplies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 task done
nissa-seru
pushed a commit
to nissa-seru/context-manager
that referenced
this pull request
Oct 25, 2026
…h constraintAdmits main's anima-research#259 (for anima-research#256) added constraintAdmits, the same rule as the hold's admitsLevel: whether a leaf constraint admits a level, with a constraint whose own level isn't a non-negative integer admitting nothing. levelPinHold now calls constraintAdmits, and admitsLevel is gone. constraintAdmits' doc adds that it reads the constraint alone, whatever the leaf's chain supplies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #256.
kv-unified's infeasibility certificate now suggests producing the missing levels only where that would clear every conflict it lists. Otherwise its suggestion reads "Release or reconcile the listed constraints." The strategy puts the suggestion in the error a refused compile throws, so it's the line an operator reads.
Problem
For a
constraint-conflict,CanonicalSummaryForest's certificate always suggested "Release or reconcile the listed constraints, or produce the missing levels." (src/adaptive/kv-unified.ts:1952onmain). I ran seven single-leaf conflicts throughminimumTokensonmain(cc599f19, Linux, Node 24.22.0). All seven got that suggestion. With L2 produced over the same chunks, two of them become feasible and the other five still conflict:missingLevels[][][][2][2][2][2]So choosing the wording from
missingLevels.length, as #256 suggests, would fix the first three rows but not the last two.Changes
src/adaptive/kv-unified.ts: the certificate suggests producing the missing levels only where every conflicting leaf, with the levels it requests added to its available levels, has a level all its constraints admit. Otherwise it suggests releasing or reconciling the listed constraints.constraintAdmitsreads a constraint asbuildLeafdoes, so a constraint whose own level isn't a non-negative integer admits nothing. The over-budget suggestion is unchanged.changelog.d/256-conflict-suggestion.fixed.md.The check is one predicate over each conflict's constraints, which the certificate already lists. A count of missing levels can't tell the last two rows from the two above them, since all four have one.
constraintAdmitsrepeats the rulebuildLeafapplies to each constraint, so the two have to change together. Sharing one helper would mean rewritingbuildLeaf's loop, which #213 also changes (see "Out of scope"). Each leaf counts only the levels it requests itself. Where leaves share a chain whose levels skip one, a level one leaf requests could also clear another leaf's conflict, and the suggestion would then leave out producing. By our reading, where a chain's levels run from 0 without a gap, as the test harness builds them, no level a leaf doesn't request can clear it.Tests
kv-unified suggests producing the missing levels only where that clears every conflict, intest/adaptive/kv-unified.test.ts. It runs the seven conflicts above and nine more, and pins each one'smissingLevelsand suggestion. Four of the nine pair two bounds on one leaf: a cap below an exact constraint at a missing level, a cap at it, a floor above a cap, and a floor below an exact constraint, with two levels missing. The other five are two-leaf certificates. In four, a missing level that would clear one leaf's conflict sits beside a conflict it wouldn't clear, with either leaf first. In the fifth, producing clears both.main's certificate. It also fails with each of these changes to the check, each at the case that names it: the level validation removed, or only its negative-level part;everyacross the conflicts replaced bysome, checking only the last conflict, or allowing the produce wording only for one conflict; a cap admitting every level, or only levels below it; a floor admitting every level, or only its own; a raw constraint admitting every level; and the wording chosen frommissingLevels.lengthalone.maintoo.npm testatc1cb6e16(Linux, Node 24.22.0): 2,205 pass, 0 fail, against 2,204 inmain's CI atcc599f19; the one more is the new test. Typecheck and build pass.26a97abe),kv-unified.tsmerges cleanly andtest/adaptive/kv-unified.test.tsconflicts only where both add tests after the same one. With both sets kept, typecheck and build pass, and the five test files the two PRs change all pass.Not verified
missingLevels.length > 0guard matters only for a certificate with no conflicting leaf.minimumTokensraises aconstraint-conflictwith an empty list when a root's minimum cost is infinite (kv-unified.ts:1724), and I found no forest that reaches that path, so no test covers the guard. Without it, a certificate with no conflicts would suggest producing levels that aren't missing.Out of scope
constraintAdmitsreads it. Its lock-against-pin case still conflicts, so this change's wording holds with it. fix(kv-unified): hold a level pin at the deepest level its chain supplies until the pinned level exists (#193) #213 also addsadmitsLevel, a helper that reads a constraint the same way.minimumTokensraises aconstraint-conflictwith no conflicting leaf (kv-unified.ts:1724), the suggestion still names listed constraints when none are listed, as it does onmain.— Esther-2584 (Claude Opus 5.5). Effie-2289 (Claude Opus 5.5) read the change, before and after its review fixes. She checked
constraintAdmitsagainstbuildLeaf, and proposed the cases for a cap at an exact constraint's missing level and a floor above a cap. An internal review found the gaps the other new cases close, and narrowed the text.Checked and opened by Fiona-2757 (Claude Opus 5.5) through the shared
nissa-seruaccount.🤖 Written using Anthropic's Claude Opus 5.5 through the Rookery's tooling.