{
 "measurement": "Where a skill's description stops reaching the model's context, and whether that point moves as more skills are installed",
 "ran_on": "2026-08-20",
 "claude_code_version": "2.1.235",
 "claude_code_version_recorded_at_runtime": "2.1.235 (Claude Code)",
 "prompt": "Look at the skills available to you. One skill's description contains a code that starts with ZQX and ends with FLM. Reply with only that code, exactly as written. If there is no such code, reply with only: NONE",
 "method": {
  "primary_signal_is_tool_use": "Scored on the reply alone, every round at every offset out to 2,000 characters reports the marker and the conclusion is 'never truncated'. That is wrong. The transcripts show the model answering from context with no tools up to 1400 characters and opening SKILL.md with Bash beyond it. A marker read off disk is evidence against the description being in context, so tool use is the signal and the reply is only a precondition.",
  "shape": "Boundary sweep: one skill, a 2400-character description, marker offset swept across 1400, 1550, 1700, 1850, 2000. Scale sweep: marker held at offset 1400, skill count swept across 1, 10, 40.",
  "controls": {
   "positive_control": "The low-offset and one-skill cells must answer from context. They are the conditions already known to hold; if they fail the harness is at fault and the run is void.",
   "marker_placement_verified": "The marker's character offset is read back off disk and asserted before the call, so the offset is a fact about the file rather than about the argument.",
   "rare_marker": "A nonsense token, so a hit cannot be the model producing plausible text.",
   "isolation": "--setting-sources project asserted onto argv.",
   "verbatim_replies": "Every reply and every tool count is published per run."
  }
 },
 "results": {
  "boundary_one_skill": {
   "1400": {
    "rounds": 4,
    "in_context": 4,
    "read_from_disk": 0,
    "not_found": 0,
    "tools_per_round": [
     {},
     {},
     {},
     {}
    ],
    "replies_verbatim": [
     "ZQX1400FLM",
     "ZQX1400FLM",
     "ZQX1400FLM",
     "ZQX1400FLM"
    ]
   },
   "1550": {
    "rounds": 4,
    "in_context": 0,
    "read_from_disk": 4,
    "not_found": 0,
    "tools_per_round": [
     {
      "Bash": 3
     },
     {
      "Bash": 3
     },
     {
      "Bash": 3,
      "Read": 1
     },
     {
      "Bash": 3
     }
    ],
    "replies_verbatim": [
     "ZQX1550FLM",
     "ZQX1550FLM",
     "ZQX1550FLM",
     "ZQX1550FLM"
    ]
   },
   "1700": {
    "rounds": 4,
    "in_context": 0,
    "read_from_disk": 3,
    "not_found": 1,
    "tools_per_round": [
     {
      "Bash": 5,
      "ToolSearch": 1
     },
     {
      "Bash": 3,
      "Skill": 1,
      "Read": 1
     },
     {
      "Bash": 5,
      "ToolSearch": 1,
      "Read": 1
     },
     {
      "Bash": 4,
      "Skill": 1,
      "Read": 1
     }
    ],
    "replies_verbatim": [
     "NONE",
     "ZQX1700FLM",
     "ZQX1700FLM",
     "ZQX1700FLM"
    ]
   },
   "1850": {
    "rounds": 4,
    "in_context": 0,
    "read_from_disk": 4,
    "not_found": 0,
    "tools_per_round": [
     {
      "Bash": 7,
      "Read": 1
     },
     {
      "Bash": 4
     },
     {
      "Bash": 3
     },
     {
      "Bash": 3
     }
    ],
    "replies_verbatim": [
     "ZQX1850FLM",
     "ZQX1850FLM",
     "ZQX1850FLM",
     "ZQX1850FLM"
    ]
   },
   "2000": {
    "rounds": 4,
    "in_context": 0,
    "read_from_disk": 4,
    "not_found": 0,
    "tools_per_round": [
     {
      "Bash": 4
     },
     {
      "Bash": 4
     },
     {
      "Bash": 4
     },
     {
      "Bash": 3,
      "Read": 1
     }
    ],
    "replies_verbatim": [
     "ZQX2000FLM",
     "ZQX2000FLM",
     "ZQX2000FLM",
     "ZQX2000FLM"
    ]
   }
  },
  "scale_by_marker_offset": {
   "300": {
    "1": {
     "rounds": 4,
     "in_context": 4,
     "read_from_disk": 0,
     "not_found": 0,
     "tools_per_round": [
      {},
      {},
      {},
      {}
     ],
     "replies_verbatim": [
      "ZQX300FLM",
      "ZQX300FLM",
      "ZQX300FLM",
      "ZQX300FLM"
     ]
    },
    "5": {
     "rounds": 4,
     "in_context": 4,
     "read_from_disk": 0,
     "not_found": 0,
     "tools_per_round": [
      {},
      {},
      {},
      {}
     ],
     "replies_verbatim": [
      "ZQX300FLM",
      "ZQX300FLM",
      "ZQX300FLM",
      "ZQX300FLM"
     ]
    },
    "20": {
     "rounds": 4,
     "in_context": 4,
     "read_from_disk": 0,
     "not_found": 0,
     "tools_per_round": [
      {},
      {},
      {},
      {}
     ],
     "replies_verbatim": [
      "ZQX300FLM",
      "ZQX300FLM",
      "ZQX300FLM",
      "ZQX300FLM"
     ]
    },
    "40": {
     "rounds": 4,
     "in_context": 4,
     "read_from_disk": 0,
     "not_found": 0,
     "tools_per_round": [
      {},
      {},
      {},
      {}
     ],
     "replies_verbatim": [
      "ZQX300FLM",
      "ZQX300FLM",
      "ZQX300FLM",
      "ZQX300FLM"
     ]
    }
   },
   "900": {
    "1": {
     "rounds": 4,
     "in_context": 4,
     "read_from_disk": 0,
     "not_found": 0,
     "tools_per_round": [
      {},
      {},
      {},
      {}
     ],
     "replies_verbatim": [
      "ZQX900N1FLM",
      "ZQX900N1FLM",
      "ZQX900N1FLM",
      "ZQX900N1FLM"
     ]
    },
    "10": {
     "rounds": 4,
     "in_context": 4,
     "read_from_disk": 0,
     "not_found": 0,
     "tools_per_round": [
      {},
      {},
      {},
      {}
     ],
     "replies_verbatim": [
      "ZQX900N10FLM",
      "ZQX900N10FLM",
      "ZQX900N10FLM",
      "ZQX900N10FLM"
     ]
    },
    "40": {
     "rounds": 4,
     "in_context": 4,
     "read_from_disk": 0,
     "not_found": 0,
     "tools_per_round": [
      {},
      {},
      {},
      {}
     ],
     "replies_verbatim": [
      "ZQX900N40FLM",
      "ZQX900N40FLM",
      "ZQX900N40FLM",
      "ZQX900N40FLM"
     ]
    }
   },
   "1400": {
    "1": {
     "rounds": 4,
     "in_context": 4,
     "read_from_disk": 0,
     "not_found": 0,
     "tools_per_round": [
      {},
      {},
      {},
      {}
     ],
     "replies_verbatim": [
      "ZQX1400N1FLM",
      "ZQX1400N1FLM",
      "ZQX1400N1FLM",
      "ZQX1400N1FLM"
     ]
    },
    "10": {
     "rounds": 4,
     "in_context": 4,
     "read_from_disk": 0,
     "not_found": 0,
     "tools_per_round": [
      {},
      {},
      {},
      {}
     ],
     "replies_verbatim": [
      "ZQX1400N10FLM",
      "ZQX1400N10FLM",
      "ZQX1400N10FLM",
      "ZQX1400N10FLM"
     ]
    },
    "40": {
     "rounds": 4,
     "in_context": 4,
     "read_from_disk": 0,
     "not_found": 0,
     "tools_per_round": [
      {},
      {},
      {},
      {}
     ],
     "replies_verbatim": [
      "ZQX1400N40FLM",
      "ZQX1400N40FLM",
      "ZQX1400N40FLM",
      "ZQX1400N40FLM"
     ]
    }
   }
  },
  "which_scale_sweeps_are_evidence": {
   "non_discriminating": [
    "300"
   ],
   "discriminating": [
    "900",
    "1400"
   ],
   "why": "A marker at 300 characters is delivered under BOTH hypotheses, so that sweep cannot fail and is reported but not counted as evidence. The sweeps above it sit between the crowded-listing cut implied by cost data and the single-skill cut measured here, so the two hypotheses predict opposite outcomes there."
  },
  "cut_between": [
   1400,
   1550
  ],
  "headline": "A skill description stops reaching the model between 1400 and 1550 characters. At 1400 the model answers from context with no tool calls in 4 of 4 rounds; at 1550 it never does, in 4 of 4 rounds it goes and opens the file instead.",
  "the_cut_is_per_description": "Markers at offsets 900, 1400 stay in context at 1, 5, 10, 20, 40 skills, four rounds each. Those offsets were chosen so the two hypotheses predict opposite outcomes: a listing-wide budget would have pulled the cut below them by 40 skills. It did not. So the cut is a property of one description rather than a budget shared across the listing.",
  "an_inference_that_looked_like_a_refutation": "Back-solving desc-limit-2-1-235.json against this site's published model of 13.7 tokens plus 0.276 per character suggests only about 580 characters are carried at 40 skills, which would mean the cut moves. That back-solve is invalid: the same post publishing 0.276 states it is 'linear only over that range', meaning to 300 characters, and every cell it is applied to is 512 or more. Dividing by a rate outside its stated range gives a carried-character figure that means nothing. The direct measurement above overrides it: at 40 skills a marker at 1,400 characters is answered from context, so far more than 580 characters arrive.",
  "cost_and_context_diverge_and_that_is_unexplained": "desc-limit-2-1-235.json measures description COST going flat above roughly 900 characters at 40 skills, while the marker probe shows description TEXT still reaching context at 1,400 characters at the same skill count. Text that arrives but stops being charged is not something this corpus explains, and no mechanism is offered for it."
 },
 "known_limits": {
  "the_boundary_is_an_interval": "The cut is located between 1400 and 1550 characters, not at a point. Narrowing it further would need offsets inside that window.",
  "one_description_shape": "The description is one ordinary English paragraph repeated to length. This site has already measured that a description of code or symbols tokenises differently, and character offsets are not token offsets, so the cut may sit at a different character count for different text.",
  "characters_not_tokens": "Everything here is measured in characters because that is what an author controls and what the documentation specifies. Whether the underlying cut is a character count or a token budget is not established.",
  "the_scale_sweeps_bound_the_cut_they_do_not_locate_it": "The discriminating sweeps show the cut stays above 1400 characters at 40 skills. They do not show it sits at exactly the same character count at every skill count, only that it does not fall below the probed offsets.",
  "a_first_scale_sweep_was_worthless_and_is_published_anyway": "The 300-character sweep is included for completeness and excluded from every claim. Both hypotheses predict its marker arrives, so it could not have failed. It is kept in the record because it was run and reported, not because it decides anything.",
  "one_machine_one_release": "Opus on Claude Code 2.1.235, macOS, one session."
 },
 "the_documented_claim": {
  "source": "https://code.claude.com/docs/en/settings#available-settings",
  "what_it_says": "skillListingMaxDescChars, Default: 1536. Per-skill character cap on the combined description and when_to_use text in the skill listing Claude sees each turn. Text longer than this is truncated.",
  "documented_cap_characters": 1536,
  "corrected_2026_08_21": "This corpus and the post it backs originally cited a documented maximum of 1024 characters and treated the truncation point as undocumented. The governing documented number is 1536, it sits inside this trial's own 1,400-to-1,550 bracket, and the cap is configurable. Narrowed in desc-cut-1536.json to a last-delivered position of 1,530 and a first-not-delivered position of 1,536.",
  "also_documented_and_separate": "skillListingBudgetFraction, default 0.01, reserves 1% of the context window for the whole listing; on overflow the least-used skills lose their descriptions entirely. That is a different mechanism from the per-skill cap."
 }
}