Instructions charge no retention tier and are bounded by their own cap (#446) - #450
Merged
Conversation
…and has a cap of its own instruction is recorded at full exposure and charges `fullTokens`, the cap that exists so `self context` fits its 3,000-token budget — a budget no instruction is in. A ~190-token procedure was refused three times at 930/1000, the `--demote` remedy pointed at goals and conventions, and `--demote` refused workspace-scoped records. The table is the contract, so the decision is made here before any code. Three rulings: §D-14, an instruction charges no retention tier at any exposure and is bounded by `StoreConfig.instructionTokens` (default 2,000) counted per render target; §D-15, the two refusals that cap raises, neither of which names `--demote`, a goal, an objective or a convention; §D-16, `--demote` leaves `instruction add` and a placement of an instruction is refused by no cap. Restated against them: A23, A24, A25, A28, B5–B9, B18, B19, C23, D12, E9, E18, F14, G1, G4. New: A36–A42, B21, B22, E20, E21, F16, F17 — 161 designed cells. The "cap exemption" line under "what this table does not cover" is retired and replaced by the two things that are still not covered: what a demoted instruction costs the context budget, and gating a `--scope` move against the instruction cap. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: rayim <rayim@inflike.com>
…ts own The retention tiers exist so `self context` fits its 3,000-token budget. An instruction is in no part of that projection — `views.ts` keeps a full-exposure one out and `instruction render` prints every one of them whole however far the store stands over the caps — and yet it was recorded at full exposure and charged `fullTokens` like a goal. A record nothing ever elides was competing for the room set aside for records that are, and the `--demote` remedy pointed at goals and conventions to free it (#446). `@superself/fold` does not change and `FOLD_VERSION` stays at 1: `tierCharacters` keeps counting every full-exposure record, and the CLI subtracts the instructions where it reads a cap's usage, so `state add`, `state place`, `state confirm` and every cap refusal report a tier without them. The predicate is the shipped one, read off the folded entity where there is one and off the composed payload's labels where there is not — the label is the mechanism, so a raw `state add --label instruction` follows the rule exactly as the render already does. In its place: `StoreConfig.instructionTokens`, default 2,000, counted per render target over instruction-labelled records at any exposure. `CappedTier` carries it as a third kind so one path still reads, compares and refuses every cap. `--demote` leaves `instruction add`, whose refusal now names the room that exists — a shorter successor, or a larger cap — and never a goal, an objective or a convention. A placement of an instruction is refused by no cap at all. Cells: A23, A24, A25, A28, B5–B9, B18, B19, C23, D12, E9, E18, F14, G4 restated; A36–A42, B21, B22, E20, E21, F16, F17 new. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: rayim <rayim@inflike.com>
…ction add` `docs.test.mjs`'s G1 holds the cli.md row byte-identical to the contract's own syntax line, so the flag leaving the verb leaves both. The golden fixture is regenerated: the one line that moved is the root usage listing's. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: rayim <rayim@inflike.com>
…y replace The self-adversarial pass over #446's cells found A25 and A41 passing under the old rule as well as the new one. A25 asserted that the add names no demotion, in a store whose full tier was nowhere near its cap — so it proved nothing about the tier. It now fills the tier to `fullTokens` with the goal and the convention the old refusal advertised demoting: the state #446 reported, and the add lands. A41 asserted that a `--label convention` add lands, which every cap admits; it now seeds a full tier the convention overflows, so the two caps are told apart by the one label that decides them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: rayim <rayim@inflike.com>
tonite31
force-pushed
the
fix/446-instruction-cap
branch
from
September 4, 2026 14:12
d9f7ae6 to
33ed86d
Compare
…e cap holds Three defects the first review round of #446 found, all on the credit side of the ruling this branch makes: a tier that charges an instruction nothing was still crediting one back. `holdsSeat` read a retention tier through `occupiesTier` alone, so a full-exposure instruction held a seat the tier's own usage never charges it for. `--demote <instruction-id>` on an ordinary full add therefore bought room nothing was paying for — with a 50-token record, a 23-token instruction and `fullTokens: 60` the 30-token add a bare `state add` was refused went through, the tier read 80 of 60 afterwards, and the instruction left the manual for nothing — and `--supersedes <instruction-id>` did the same through `vacatedTokens`. The tier branch now excludes an instruction, `requireDemotionsEnough` sums what a demotion frees through `holdsSeat` rather than through raw characters, and `requireDemotableSeat` refuses an instruction target by name, before its scope and exposure clauses: a project-scoped full instruction passes both and frees nothing. `shareLines` counted the rendered set while the cap counts every exposure, so a store holding one demoted instruction printed a share smaller than the number its own cap refusal states, and a store whose instructions were all demoted printed "no instructions recorded" over a manual it was still being refused adds against. The share counts through `chargesInstructionCap` — the predicate the cap itself is summed with — and prints wherever the cap is charged. `labelsAreInstruction` tested membership with `in`, which walks `Object.prototype`, so `--label constructor` read as a preset source at the gate while `sourceOf` folded the record with `source === undefined`: one record, two answers about which cap it charges. `Object.hasOwn` is the test now. Beside them: `remembered` is inlined into its one caller, B19 asserts the cap its share lines name so it can no longer pass against the pre-#446 build, and A24, E21 and F16 read the log across their refusals as A36 and A42 do. New cells A43, A44, A45 and B23; A24, B19, E21 and F16 amended. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: rayim <rayim@inflike.com>
…d cap The design half of review round 1 of #446. §D-14 gains the rule the code was missing: the subtraction runs both ways, so a tier that charges an instruction nothing can be credited nothing for one either. §D-15 scopes the `--supersedes` credit to the add path, where it is true — the confirm judges the unit's own net movement and credits no such link — and F17's row loses the clause that claimed it at confirm time, which that cell never asserted. §D-16 gains the wording `--demote` refuses an instruction target with. §D-6 says the share is counted through the cap's own predicate and prints wherever the cap is charged. Two "does not cover" bullets were stale. The legacy-label bullet said such records "still charge the same tier"; they charge `instructionTokens` now, and a store that used the label freely may already stand over the 2,000 default — reproduced at 2240 of 2000, rendering whole and refusing instruction adds alone. The bullet describing `--demote <id>` as the remedy for an instruction add past the full tier described a rule this branch retired, and cited A23 and A25 as refusals they no longer are; it is deleted. `docs/reference/cli.md` gains `instructionTokens` beside the two retention caps, with its own remedy sentence, and the `--demote <id>` clause is scoped to the tiers it frees room in. Group counts: A 45, B 23, 165 designed cells. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: rayim <rayim@inflike.com>
Round 2 of #450's review: --demote naming a proposed instruction now takes the instruction refusal instead of the proposed one, holdsSeat and heldCharacters are pinned equal with more than one record of each kind, cli.md's instructionTokens bullet is pinned against the built refusal and tells the parser and by-name --demote paths apart, B23 seeds every lifecycle state B12 claims it does, and a listing whose instructions are all demoted says so beside the share instead of printing only the number. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: rayim <rayim@inflike.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.
Closes #446.
self instruction addwas refused once the project's full tier reachedits 1,000-token cap — a cap that exists so
self contextfits its3,000-token budget, a budget no instruction is in.
instruction renderprints every instruction whole however far the store stands over the caps,
and
views.tskeeps a full-exposure one out of the context projectionentirely. A record nothing ever elides was competing for the room set aside
for the records that are, and the
--demoteremedy pointed at goals andconventions to free it.
The case table is amended first, in its own commit, and the code follows it.
Decisions
predicate is the shipped one,
labels.includes("instruction") && source === undefined.@superself/folddoes not change andFOLD_VERSIONstaysat 1:
tierCharacterskeeps counting everything, and the CLI subtractsthe instructions where it reads a cap's usage — so
state add,state place,state confirmand every cap refusal report the tier withoutthem.
StoreConfig.instructionTokens,beside
fullTokens/indexTokens, default 2,000, counted per rendertarget (project / workspace) exactly as
tierOfsplits the tiers, overinstruction-labelled records at any exposure.
retentionCapsreturns itas a third field.
instruction addrefuses only against the instruction cap, and nevernames
--demote, a goal, an objective or a convention:instructions hold <n> of the <cap>-token <scope> instruction cap and this text adds <m> more — retire or supersede one with a shorter text, or raise instructionTokens in config.json<estimate note>. A--supersedespredecessor is creditedbefore the comparison, so the remedy the refusal advertises works.
--demoteleavesinstruction add— an unknown option the parserrefuses. It shipped yesterday and is unreleased. A raw
state add --label instruction --demote <id>is refused by name toward the room that doesexist.
state confirmof a proposed instruction checks the instruction cap,in
requireTierRoom's wording family:confirming this would put the <scope> instructions over their cap (<n> of <cap> tokens held)<estimate note> — retire or supersede one ….state placeon an instruction isrefused by no cap at all: no tier holds it, and the instruction cap counts
it at any exposure.
state add --label instructionis exempt from the tiers andchecked against the instruction cap through the same predicate — the label
is the mechanism, so the raw verb follows it, as Instruction records: rules and tool notes every session receives whole, outside the context render budget #440's table settled for
the render.
instructions hold <n> tokens — <n> of the <cap>-token <scope> instruction cap (<pct>%)<estimate note>, one lineper occupied target, note on the last line only.
self help placementstates that instructions charge no retentiontier and that
instruction addis bounded byinstructionTokens(default2,000) instead.
Cells
docs/maintainers/case-tables/440-instructions.md, amendment list"review round: #446", 161 designed cells (the branch is rebased onto main,
which gained #445's G17).
G1, G4.
--demoteunknown), A38 (the tiercount excludes the instruction), A39 (raising the cap admits the add), A40
(the raw verb lands at a full tier's cap), A41 (the raw verb judged by the
instruction cap; a preset label beside it is not), A42 (
--demoteon a rawinstruction add), B21 (one share per target), B22 (neither tier's refusal
counts an instruction, at full or at index), E20 (promotion with both caps
at their limits), E21 (every placement lands, naming no demotion), F16 (the
confirm refusal), F17 (raising the cap lands the confirm).
refusals), §D-16 (
--demoteand the placement gate). The "cap exemption"line under "what this table does not cover" is retired and replaced by what
still is not covered: what a demoted instruction costs the context budget,
and gating a
--scopemove against the instruction cap.Gates
Run to completion locally:
pnpm --filter superself typecheck,pnpm --filter superself build,node test/structure.mjs(function ceiling 30,dead exports 0), and
node --testoninstruction.test.mjs(65),instruction-context.test.mjs(31),instruction-place.test.mjs(21),instruction-render.test.mjs(27),docs,guide,golden,skill,place,preset-caps,context,state,structure,handoff, and theeleven other suites that assert cap wording (
agent-consent,derivation,render-gate-documents,skill-context,scope-move,runbook,workspace-scope,confirm-owner,tokens,workspace-direction,search-live) — all green. The golden fixture is regenerated; its onlychange is the root usage listing's
instruction addline.A self-adversarial pass reverted each half of the change in turn: dropping
the tier subtraction fails ten cells (A23, A28, A38, A41, B18, B22, D12, E9,
E18, F14) and dropping the instruction-cap gate fails fourteen (A23–A25, A28,
A36, A38–A42, C23, F14, F16, F17). Two restated cells that passed under both
rules — A25 and A41 — were strengthened until they did not.
CI runs the whole suite; it is the referee.
🤖 Generated with Claude Code
Review round 1
One blocking finding, five
should, three optional; all nine applied.1 (blocking) — the credit side. A tier that charges an instruction nothing
was still crediting one back.
holdsSeatread a retention tier throughoccupiesTieralone, so a full-exposure instruction held a seat the tier's ownusage never charges it for: with a 50-token record, a 23-token instruction and
fullTokens: 60, the 30-tokenstate addthat a bare add is refused wentthrough with
--demote <instruction-id>, the tier read 80 of 60 afterwards,and the instruction had left the manual.
--supersedes <instruction-id>boughtthe same room through
vacatedTokens. Three edits: the tier branch ofholdsSeatexcludes an instruction,requireDemotionsEnoughsums what ademotion frees through
holdsSeatrather than through raw characters, andrequireDemotableSeatrefuses an instruction target by name — before its scopeand exposure clauses, because a project-scoped full instruction passes both and
frees nothing:
--demote <id> is an instruction — it charges no retention tier, so demoting it frees no room; name a goal, decision, convention or index record with --demote. New cells A43 (the--demoterefusal) and A44 (the--supersedescredit gone: the refusal states the tier's own 50 of 60).2 (should) — share line vs cap.
shareLinescounted the rendered set whilethe cap counts every exposure, so a store holding one demoted instruction
printed a share smaller than the number its own cap refusal states, and a store
whose instructions were all demoted printed "no instructions recorded" over a
manual it was still being refused adds against. The share counts through
chargesInstructionCap— the predicate the cap itself is summed with — andprints wherever the cap is charged. §D-6 and the comment at
instruction.tsare amended; new cell B23 holds both halves.
3 (should) — two stale "does not cover" bullets. The legacy-label bullet
said such records "still charge the same tier"; they charge
instructionTokensnow, and a store that used the label freely may already stand over the 2,000
default — reproduced at 2240 of 2000, rendering whole and refusing instruction
adds alone. The bullet describing
--demote <id>as the remedy for an add pastthe full tier described the retired rule and cited A23/A25 as refusals they no
longer are; deleted.
4 (should) — F17's row. It claimed a
--supersedespredecessor is creditedat confirm time. The confirm judges the unit's own net movement and credits no
such link (a 24-token successor superseding a 23-token live instruction is
refused at
23 of 30), and the cell never asserted it. The clause is deletedand the credit is stated in §D-15, on the add path, where it is true. No code
change.
5 (should) —
docs/reference/cli.md. The caps bullet gainsinstructionTokens(default 2,000, per render target) with its own remedysentence, and the
--demote <id>clause is scoped to the two retention tiers.6 (should) —
labelsAreInstruction. It tested membership within, whichwalks
Object.prototype, so--label constructor— ortoString, or__proto__— read as a preset source at the gate whilesourceOffolded therecord with
source === undefined: one record, two answers about which cap itcharges.
Object.hasOwnis the test now, the localSOURCE_LABELSand itsbuild-time
Record<EntitySource, true>guard both kept. New cell A45.7, 8, 9 (optional). B19 asserts the cap its two share lines name, so it
can no longer pass against the pre-#446 build.
rememberedis inlined intousageReader, its one caller. A24, E21 and F16 readevents().lengthacross their refusals, as A36 and A42 do.Table: groups A 45 and B 23, 165 designed cells, and the "review round:
#446" list gains a round-1 sub-list naming each cell and why.
Gates, each to completion on the dev VM:
typecheck,build,node test/structure.mjs(ceiling 30, dead exports 0), andnode --testoninstruction(69),instruction-render(27),instruction-place(21),instruction-context(31),place(16),preset-caps(29),context(15),docs(13),guide(14),golden(3),skill(44),state(8) — all green.Self-adversarial pass: reverting the
holdsSeattier exclusion alone failsA44; reverting the
requireDemotableSeatclause alone fails A43 (thetwo halves of the blocking finding guard one cell each, rather than 1(a)
guarding both); reverting the share-line predicate fails B23. All three
restored, all cells green again.
Review round 2
No blocking finding, three
should, three optional; all six applied.1 (should) —
--demote <proposed instruction>misdirected. The proposedclause in
requireDemotablefired beforerequireDemotableSeat's instructionclause, so naming a proposed instruction with
--demotetook--demote <id> is still proposed — it holds no place in the full tier until confirmed, aremedy that only led to A43's refusal once the caller confirmed it. The
instruction clause is hoisted into
requireDemotable, above the proposed and!isLiveclauses: kind is judged before lifecycle, and it now precedes everyclause but the one naming the record being placed. §D-16 and A43's row are
amended to say so; new cell A46 drives
--demote <a proposed instruction>on a full add at the cap and asserts the instruction wording, nothing
recorded.
2 (should) —
cli.md'sinstructionTokensbullet was unpinned. Nothingin
docs.test.mjschecked the bullet named the cap, its 2,000 default, "perrender target", or a remedy matching the built refusal (
INSTRUCTION_REMEDYin
state.ts). New cell G18 pins all four. While there, the bullet's--demotesentence was imprecise: it read both paths as "refused by name,"but
instruction adddeclares no such flag at all — the parser refuses it asunknown option '--demote'— and only a rawstate add --label instruction --demote <id>is refused by name. The bullet now says both, and G18 is addedto a new "round 2" sub-list beside the round-1 one.
3 (should) — B12 delegated a proof B23 didn't carry. B12's row credited
B23 with proving the token total holds a demoted instruction and excludes a
proposal, a superseded and a retracted one, but B23 seeded only the full and
the demoted instruction. B23 now also seeds one proposed, one superseded (via
its predecessor) and one retracted instruction, and asserts the share equals
confirmed + demoted alone and equals the next refusal's held number — the
same 51 either way. B12's row is amended to point at B23 truthfully.
4 (optional) — the
--artifactorphan. Pre-existing and not moved:state add --label instruction --artifact <path>past the instruction capstill registers the artifact and then refuses the record, because
resolveArtifactRefruns before the cap gate inentityAdd. The commentabove the call was wrong about the ordering ("after every other check"); it
now says the cap gate follows it. Added to the case table's "does not cover"
list with one sentence.
5 (optional) — an all-demoted listing printed only the share line. When
every charged instruction is demoted,
sectionsis empty andlistRowsprinted nothing beside the share — a reader could read the bare number as
"nothing is recorded."
instructionListnow adds one line beside the sharein that case:
every instruction is demoted — self context carries them as index lines; instruction render prints none.listRowsis also guarded soMath.max(...[])is never evaluated on the empty path. §D-6 and B23 (whichalready seeded an all-demoted store) are amended to assert it.
6 (optional) — one rule spelled twice.
holdsSeat's tier branch excludesan instruction with
!isInstruction, andheldCharacterssubtractsinstructionTierCharacters— the same rule, kept twice because one runsbefore a demotion's credit is summed and the other after the fold's own sum.
A comment on
instructionTierCharactersnow namesholdsSeatas itscomplement. New cell A47 pins them equal with two instructions and two
ordinary records seeded (not one of each), driven through a tier refusal's
numbers as A28 and A38 are: the held count is the sum of
entityCharactersover the two ordinary records alone.
Bookkeeping. A24's and E21's rows are reworded to carry the
events().lengthclaim the round-1 sub-list credited them with — A24's ownoutcome is a landing, so the claim now names F16, the confirm that actually
refuses. A44's row is reworded the same way.
Table: groups A 47 (A46, A47 new) and G 18 (G18 new), 168 designed cells,
and a new "round 2" sub-list names A46, A47, G18, B23, B12, A24 and E21 with
one sentence each.
Gates, each to completion on the dev VM:
typecheck,build,node test/structure.mjs(ceiling 30, dead exports 0), andnode --testoninstruction(71, +2),instruction-context(31),instruction-place(21),instruction-render(27),place(16),preset-caps(29),docs(14, +1),guide(14),golden(3),skill(44) — all green.Self-adversarial pass: reverting the
requireDemotablehoist (moving theinstruction clause back into
requireDemotableSeat, after the proposed and!isLiveclauses) fails A46 alone; every other cell in the file stillpasses. Restored, and the suite is green again.