Progressive Disclosure

Every lesson in this course builds one system: a stablecoin reserve attestation registry that discovers issuers, reads the PDFs they publish, and refuses to publish a field it could not read. What it is and where this lesson sits.

Tier
4 Expert
Build position
20
Throughlines
A Context economics · B Instruction packaging · E Tool surface and trust boundary
Verdict
load-bearing
Commit
3048c1c
Demo
scripts/terms/demo-20.ts
Runs in
the course repository

Keep a short index resident, keep the long bodies on disk, and fetch a body only when something asks for it. Tool schemas, skill bodies, standing instructions, reference documents — anything that would otherwise sit in the context on every turn whether it is used or not.

Term 14 built one instance of this, for skills, and measured a single loadout. This term is the policy: the same move applied across the whole resident surface at once. It earns its own unit because the policy has an answer that is not "disclose everything", and the arithmetic that finds it is four lines long.

The failure it fixes

You are paying for material you are not using. A dozen tool schemas, four skill bodies, a standing-instructions file and a handful of reference documents are in the context on turn one and on turn four hundred, and most of them are irrelevant to almost every turn. That is the obvious waste and disclosure fixes it.

The failure disclosure itself introduces is the one worth the unit. Every piece of advice you will read says defer the load, so people defer everything — and deferring is not free. You still pay the index on every turn, and on the turns where the body is needed you pay the index and the body and an extra round trip to go get it. For something needed on almost every turn, that is strictly more expensive than never deferring it at all. Nobody measures this, because the thing that got measured was average context length, and average context length went down.

The mechanism

Two costs, per item:

resident    body                                  every turn
disclosed   index + p × (body + round trip)       every turn

where p is how often the item is genuinely needed. Setting them equal gives the break-even load rate:

p* = (body − index) / (body + round trip)

Above p*, keep it resident. Below it, disclose. That is the entire technique, and src/disclosure.ts is cost() computing it per item and policy() pricing the three ways to run a surface: everything resident, everything disclosed, and each item on its own side.

ROUND_TRIP_TOKENS is a stated constant (350) and it is load-bearing. A model that omits the round trip makes disclosure look strictly better than resident in every case, which erases the decision this unit exists to make.

The receipt

npx tsx scripts/terms/demo-20.ts runs this over the repository's own resident surface — the standing-rules file, the extraction prompt, three skills, four reference documents:

item                          rate   index    body   resident  disclosed  break-even  verdict
CLAUDE.md                     1.00      27     332       332        709        0.45  resident
prompt:extract-fields         0.95      26     428       428        765        0.52  resident
skill:extraction              0.70      20      56        56        304        0.09  resident
skill:provenance              0.25      18      54        54        119        0.09  resident
skill:refusal                 0.60      16      46        46        254        0.08  resident
doc:15-hooks                  0.05      57    1520      1520        151        0.78  disclosed
doc:13-git-worktrees          0.05      54    1350      1350        139        0.76  disclosed
doc:26-tool-poisoning         0.05      57    1293      1293        139        0.75  disclosed
doc:i4-design-vs-operating    0.05      27    3542      3542        222        0.90  disclosed

expected tokens per turn:
  everything resident   8621
  everything disclosed  2801
  each on its own side  1566   saves 1235 (44.1%) against the better of the two

Forty-four percent below the better of the two pieces of standard advice, and the number comes entirely from not following either one everywhere.

The line that makes it concrete:

  disclosing CLAUDE.md would cost 377 MORE tokens per turn, not fewer,
  because it is needed on 100% of turns and its break-even is 45%.

Note the shape of the two columns. The small, hot items — skills — have break-evens under 0.10, which means almost any real use makes them cheaper resident. The large, cold items have break-evens near 0.80, which means they would have to be needed on four turns in five before residency paid. The surface separates cleanly, and it separates by both size and rate, which is why a rule of thumb about either one alone gets half of it wrong.

The crossover that does not exist

I built the growth model expecting to find a catalogue size past which the resident index costs more than the bodies it defers. There is no such point. Both quantities grow linearly in the number of items — the index at the mean index size, the deferred volume at the mean load rate times the mean body — so their ratio is fixed. Whichever is larger at one item is larger at a thousand.

The demo reports that as a null result rather than deleting the question:

  index overtakes expected loaded volume at: never — both grow linearly,
  so there is no crossover to find.

What actually bites is the window, which does not grow at all:

    10 items -> index    329 tokens, 0.16% of a 200k window
    50 items -> index   1617 tokens, 0.81% of a 200k window
   200 items -> index   6697 tokens, 3.35% of a 200k window
  1000 items -> index  33549 tokens, 16.77% of a 200k window
  the index alone passes 5% of the window at 299 items.
  Past there the index needs an index.

Two hundred and ninety-nine items. Every individual disclosure decision was correct the whole way, and the surface still outgrew its own budget, because the index is resident and residency is what disclosure was supposed to be avoiding. Past that point the index itself has to be disclosed — a catalogue you search rather than read — and nothing anywhere announces the moment.

Break it first (mutations)

mutation                                     tests                 demo
the round trip is not charged                5 failed | 12 passed  exit 0
everything is disclosed, as advised          6 failed | 11 passed  exit 1
the mixed policy is just all-disclosed       1 failed | 16 passed  exit 1
break-even ignores the index cost            1 failed | 16 passed  exit 0
index budget measured against whole window   1 failed | 16 passed  exit 1

Two survive the demo, and they are the two that would ship. Not charging the round trip leaves every headline number looking sane — the split still happens, the saving is still real, and disclosure is quietly overvalued at the margin. Computing the break-even without subtracting the index has the same character: the verdicts stay right for this surface and go wrong for a surface whose descriptions are long. Only a test that isolates the term catches either.

Where it overlaps

Line A is context economics and this is the term where the resident/deferred decision becomes a number rather than a preference. Line B is instruction packaging: term 9 made a package non-resident and human-triggered, term 14 made it model-triggered, and this asks whether it should be a package at all. Line E is the tool surface, and everything here applies unchanged to tool schemas — an MCP server exposing forty tools is forty resident descriptions whose bodies you are already deferring.

Interstitial I is the collision with term 12. Everything in this unit pushes material later; caching requires the stable material to be first and byte-identical. Applying both correctly and naively raises the bill, and that page reproduces it.

Sharp edges

  1. loadRate is the whole model and you probably do not have it. Every rate in the receipt is stated, not observed. Real ones come from logging which items were actually loaded across a real workload. A break-even computed from a guessed rate is a guess with a decimal point on it, which is worse than an admitted guess.

  2. The round trip is not one number. 350 tokens is a stand-in. The real cost is a full re-send of everything above the insertion point, which depends on where the conversation is and interacts directly with caching. Interstitial I is where that gets priced.

  3. A description short enough to be cheap may be too short to trigger on. The index is what the model decides from. Shrinking it lowers resident cost and raises the silent-miss rate from term 14, and nothing reports the misses.

  4. Disclosure adds a place to be attacked. A deferred body is fetched at runtime, which means the fetch is a tool call, which means term 26's tool poisoning applies to a surface that used to be static text reviewed at commit time.

  5. The index grows monotonically and nothing prunes it. Items get added; they rarely get removed. The 299-item budget breach arrives by accretion, and the only defence is measuring the index as a first-class number instead of a rounding error.

A personal teaching project, in development. The registry it builds is a teaching artifact and is not an assurance opinion about any issuer. Not affiliated with or endorsed by any employer, or by any vendor whose tools it describes. Where a unit depends on a specific flag or path, it names the version it was verified against. All units.