Skip to content

perf: cut the skill-body bytes main sessions load and do not act on #12468

Open

Description

@kyle-sexton

Parent: #12229

Problem

Skill bodies a session loads stay in its context for the rest of the session. Measured over main-thread transcripts in this repository, 2026-10-31T00:00Z to 2026-11-02T00:00Z (134 sessions):

  • 185 skill loads carried 6.77 MB, median 37,504 bytes, p90 51,254; 173 of 185 were over 10 KB.
  • Subagents loaded a further 230 bodies, 8.1 MB.
  • Largest by load count and size:
Skill Loads Median bytes
source-control:pull-request 51 50,802
session-flow:handoff 58 37,488
session-flow:keep-going 24 24,978
work-items:work 10 49,847
implementation:implement-dispatch 3 72,475

Not measured: how much of each body the session acts on. That needs a per-skill reading of what a typical invocation uses.

Done when

  • For the five skills above, the body sections a typical invocation does not use are named, with the evidence (which actions the loads ran).
  • Each is moved behind progressive disclosure (a reference file the body points to) or the skill's measured body size is recorded as already lean, with eval evidence of no loss for any cut (skill criteria).
  • The after figure is measured the same way over a window of the same length.

Out of scope

Activity

  1. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Nov 2, 2026
  2. github-actions commented on Nov 2, 2026

    @github-actions
    Contributor

    Proposed work class: work-class: scoped
    Basis: automated intake triage; the lanes App applied this class.

    Size: Medium
    Complexity: Medium
    Uncertainty: Knowable
    Flags: none
    Blocked by: none

    I understood this as a bounded perf task. For five heavily loaded skills (pull-request, handoff, keep-going, work, implement-dispatch), name the body sections a typical invocation never acts on, with evidence from the transcripts. Then move those sections behind a reference file, or record the body as already lean, with eval evidence of no loss. Finally, re-measure over a window of the same length.

    The after-measurement over a new window needs a later run, so it can't be checked in this run. The rest can be triaged as normal.

    Possible overlap, not confirmed as duplicates: #12240, #12243 and #12244 (cutting the bodies of the most-invoked skills through progressive disclosure). A maintainer should check whether they already cover these five skills.

    Automated triage, applied by the lanes App.

  3. added
    priority: mediumReal value, no hard deadline; normal backlog flow.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Nov 2, 2026
  4. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.
    on Nov 2, 2026
  5. added
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    and removed
    admission-deferredAdmitted but waiting for WIP room; the hourly work-unblock sweep labels it agent-ready.
    on Nov 2, 2026
  6. github-actions commented on Nov 2, 2026

    @github-actions
    Contributor
    No description provided.
  7. github-actions commented on Nov 2, 2026

    @github-actions
    Contributor
    No description provided.
  8. added
    host-runNeeds an unattended run on a host; the host runner takes it, not a person or the issue lane.
    and removed
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    on Nov 2, 2026
  9. melodic-automation-lanes commented on Nov 2, 2026

    @melodic-automation-lanes
    Contributor

    The work-resolve-issue lane stopped on this issue (host-only): the run reports the work needs a host run the lane cannot make.
    It added host-run and removed agent-ready: an agent run on a host builds it, and it waits on no decision from a person.

    In the run's words:

    host-only: the issue's evidence and its after-figure both come from main-thread session transcripts on the maintainer's host (the 2026-10-31 to 2026-11-02 window, 134 sessions). This lane cannot read them: the file tools are confined to the checkout and refused ~/.claude/projects, and this runner holds no history of those sessions anyway. Done-when 1 needs per-skill evidence of which actions those loads ran. Done-when 3 needs the same measurement over an equal-length window after the change ships. Neither can be produced here, and cutting body sections without the usage evidence would be a guess the issue rules out.

    What the run says it did not do:

    • Done-when 1 (naming the unused body sections per skill, with evidence from the actions the loads ran): needs the host's session transcripts
    • Done-when 2 (moving sections behind progressive disclosure or recording a skill as already lean, with eval evidence): depends on done-when 1
    • Done-when 3 (after-figure over an equal-length window): needs post-change sessions on the host
    • tidy, review, verify and checks pipeline steps: nothing changed, so there was nothing to tidy or review

    Run: https://github.com/melodic-software/claude-code-plugins/actions/runs/41513791622

    To hand it back to the lane, remove host-run and add agent-ready again.

  10. kyle-sexton commented on Nov 3, 2026

    @kyle-sexton
    MemberAuthor

    Claim. Backlog HITL host-run worker is taking this now.

  11. kyle-sexton commented on Nov 3, 2026

    @kyle-sexton
    MemberAuthor

    Host run. I measured which actions the five skills' main-session loads ran, cut the one skill whose evidence and evals support a cut (/source-control:pull-request, #12739), and recorded why the other four are not cut here.

    What ran

    • Claude Code 2.1.317, subscription login. One extraction script over main-session transcripts on the desktop and laptop hosts, then paired claude plugin eval rounds (Sonnet subject, --ablation none, before = main's skill files, after = the branch), run-validity.py, noise-report.py --baseline, and /docs-hygiene:compress compare.

    Method (re-run it for the after figure):

    • Sources: main-session transcripts (isSidechain false) on both hosts, in every project directory whose name contains claude-code-plugins or belongs to a host-run-* worktree under the worktree root.
    • A load is a user message whose text starts Base directory for this skill:; its size is that message's UTF-8 bytes; its action is the ARGUMENTS: line, else the preceding Skill call's args, else the slash command's <command-args>. Reference reads are Read calls under the skill directory before the next load.
    • Before window 2026-10-31T00:00Z to 2026-11-02T00:00Z: 261 loads, 9.17 MB, 96 sessions (desktop 129 loads in 58 sessions, laptop 132 in 38). The issue's 185 loads and 6.77 MB came from a method the issue does not record, so compare the after figure with this before figure.

    Done-when 1: unused sections, with the actions the loads ran (PASS)

    Skill Loads SKILL.md bytes on main Actions the loads ran Unused sections Disposition
    /source-control:pull-request 53 51,224 create 34, ready 13, monitor 5, fetch-logs 1; create and ready loads read reference/create.md or reference/ready-for-review.md, never reference/monitor.md Monitor entry and per-iteration checklists (16,062 bytes), used only by monitor, comments and full Moved to reference/monitor.md; SKILL.md now 35,846 bytes
    /session-flow:handoff 98 37,288 30 with no arguments, the rest a topic name Not named here #12657, the #12243 slice that owns this skill's cut
    /session-flow:keep-going 38 25,234 All 38 with no arguments "After a usage limit lifts" (6,184 bytes) is conditional; the arguments cannot show how many sessions took it Not cut: the evidence does not separate the paths
    /work-items:work 7 60,447 All 7 named one item; none ran --ci CI mode (13,699 bytes) Not cut: no eval case covers CI mode, and unattended-callers.test.mjs reads its text; cases come first
    /implementation:implement-dispatch 2 73,874 One issue, one plan None nameable from 2 loads Not cut: too few loads

    Done-when 2 (PARTIAL)

    pull-request: moved. compress compare on the final head: VERDICT: PASS, no SEMANTIC LOSS. Monitor cases, 6 runs per arm, both rounds VALID: test edited and run before the fix 6/6 on both arms; person's thread left unresolved 5/6 before, 6/6 after; reply write 1/6 before, 0/6 after; mean case score 0.83 on both. noise-report.py says "n too small to call" at 2 cases. The create, ready, merge and dirty rounds are INVALID on both arms because the skill did not fire in some runs. handoff is #12657's. keep-going, work-items:work and implement-dispatch are not cut, for the reasons above.

    Done-when 3 (NOT YET)

    The after figure needs a 48-hour window once the PR merges, measured with the method above, on both hosts.

    Target labels: add none; remove none.

  12. kyle-sexton commented on Nov 4, 2026

    @kyle-sexton
    MemberAuthor

    Claim. Lane 5 host-run session takes the done-when 2 evidence for /session-flow:keep-going, /work-items:work and /implementation:implement-dispatch (hub H24). None of the three has a cut yet per the 2026-11-03 host run, so each gets a measured move or a lean record; /work-items:work gets CI-mode eval cases first.

  13. kyle-sexton commented on Nov 4, 2026

    @kyle-sexton
    MemberAuthor

    /session-flow:keep-going: not cut, because the section it would move is in regular use. Done-when 2's lean record for this skill. No eval ran, because there is no cut to compare.

    Main-session loads on the laptop (isSidechain false, all transcripts on this host, 2026-09-28 to 2026-11-03): 73 loads in 58 sessions.

    A real limit entry within Loads Sessions
    3 main-thread entries 27 (37%) 24
    6 entries 34 (47%) 26
    12 entries 38 (52%) 30
    30 entries 41 (56%) 33
    • Hand check: of the 14 rows at distance 4 to 30, 11 follow a limit stop then a resume (an account switch, a /login, or a stop message); the link is unread for 3. That supports at least 39 of 73 (53%).
    • Used on other loads too: step 2's Account field cites "After a usage limit lifts" on every load (SKILL.md:121-124), and step 4's rate-limited agent path runs its checks (:179-182). A move would send those loads to the reference file anyway, or need that logic kept in the body.

    Limits: laptop only, so this does not reconcile with the 38 loads across both hosts in the 2026-11-03 comment. Loads cluster: several limit events each produced 5 to 7 loads, so distinct limit events are fewer. The count shows a load followed a limit stop, not that the section's text changed the run; only kg-missing-goal-asks-first covers this skill. The majority holds at 12 entries or more, not at 6.

    /work-items:work and /implementation:implement-dispatch follow.

  14. kyle-sexton commented on Nov 4, 2026

    @kyle-sexton
    MemberAuthor

    /work-items:work: CI mode moved, with eval evidence. PR #13133 merged as 44d49c48bf. SKILL.md went from 61,462 to 47,301 bytes; CI mode is now reference/ci-mode.md, and the PR added three wk-ci-* cases.

    • Eval: 8 wk-* cases, 5 runs per version, Sonnet subject, opus judge, Claude Code 2.1.318. All four rounds VALID (warning: skill fired, slash-invoked prompts).
    • Compare, margin 0.05: round 1 -0.02 (-0.05 to +0.01), which only just clears; round 2, after fixing grader patterns that failed correct runs, +0.00 (-0.02 to +0.02). Both read non-inferior.
    • Reach: all 15 after-arm wk-ci-* runs read the moved file. Runs of the other 5 cases did not.
    • /docs-hygiene:compress compare: PASS, no semantic loss.
    • Negative control: with the section deleted, the new cases scored 0.40 to 0.60 against 1.00. That drop came from runs writing no outcome file, so it shows the cases can fail, not that each deep-rule grader discriminates. It ran on the pre-fix graders.

    Not established: venue-line-not-required missed in 2 of 10 after-arm runs and 0 of 10 before; the two runs read skipped the review correctly but paraphrased the line, so this may be a small real effect. Only Sonnet was measured and no real work-resolve-issue lane ran; the first real agent-ready run is the live check of the pointer. The wk-bug-* judges are uncalibrated.

    Correction to the 2026-11-03 comment for the next skill: /implementation:implement-dispatch was left uncut as "too few loads" (2). On the laptop it has 49 main-session loads over all transcripts, 7.1% of skill-load bytes, so that reason no longer holds. A cut attempt follows.

  15. kyle-sexton commented on Nov 4, 2026

    @kyle-sexton
    MemberAuthor

    /implementation:implement-dispatch: not cut. A move was built and measured, and it did not pass, so no PR. Done-when 2's lean record for this skill.

    Load evidence (laptop only, 49 main-session loads in 49 sessions): implementer dispatched in 49, phase-verifier in 43, DEVIATIONS.md written in 9, orchestrator commit authority in 15 (regex). Competing attempts: 0 uses, and it was the one section with no use and no contract holding it in the body. So only that section was tried: SKILL.md 73,874 to 69,749 bytes (5.6%). The other unused sections stay for stated reasons: the batch boundary is required by docs/contracts/native-references/README.md, and the lever check and agent-teams rule apply to every dispatch.

    Eval: Sonnet subject, opus judge, Claude Code 2.1.318, --ablation none --scaffold, 5 runs per case, 12 cases after 5 dropped for never firing the skill, about 132 USD list-price estimate.

    Round Before After Compare at 0.05
    2 VALID VALID -0.02 (-0.06 to +0.02), not shown non-inferior
    3 VALID VALID +0.01 (-0.00 to +0.03), non-inferior, on interim graders
    4 INVALID (1 denial; skill did not fire in 1 run) VALID none
    5, the decider INVALID (skill did not fire in 1 run) VALID none

    A rule written before round 5 required both arms VALID and non-inferior, and it says no PR otherwise. No round was VALID on both arms with the final graders.

    A signal against the move: blocking-human-decision in the two pb-* escalation cases missed 4 of 40 before and 15 of 40 after across rounds 2 to 5 (I recounted these from the result files; Fisher p=0.0075, post hoc and not corrected for the 7 graders pooled). Runs still park (no-further-round and no-third-round had 0 misses) but type the entry deviation. Neither case read the moved file and the rest of SKILL.md did not change, so the cause is UNVERIFIED. The body does not state which entry type a repeated CRITICAL takes; implement/context/phase-review.md:43 does, which may explain the swing (UNVERIFIED).

    The moved text itself worked: id-competing-attempts-record scored 1.00 on both arms, with 20 of 20 after-arm reads. /docs-hygiene:compress compare said PASS.

    Next, if anyone retries: explain the entry-type shift first. Stating the blocking human-decision rule in the body is the cheap test.

    Found: the brief-* cases (4) and control-docs-phase-no-red-run never fire the skill on Sonnet, so an implementation suite run that includes them reads INVALID on the skill-fired check. code-writing-dispatch misses firing about 1 run in 5. Four graders failed correct runs; Lane 5 ships those fixes separately.

    State of done-when 2: pull-request moved (#12739), work moved (#13133), keep-going and implement-dispatch recorded here, handoff is #12657's. Done-when 3 stays open for the 48-hour after figure.

  16. kyle-sexton commented on Nov 6, 2026

    @kyle-sexton
    MemberAuthor

    After figure: total loaded skill bytes fell 30%, but most of that is fewer desktop sessions; per load, the /source-control:pull-request cut shows (-29%) and the other skills are flat.

    Method: the one recorded in the 2026-11-03T06:06Z comment, re-run with one script on both hosts over a 48-hour window from when the last cut (#13133) merged. The script reproduces the before figure exactly (261 loads, 9.17 MB, 96 sessions; desktop 129 in 58, laptop 132 in 38). It does not extract actions or count reference reads, so this comment has no per-action rows.

    Window Loads MB Sessions KB per load
    Before, 2026-10-31T00:00Z to 11-02T00:00Z 261 9.17 96 35.1
    After, 2026-11-04T07:40Z to 11-06T07:40Z 181 6.44 64 35.6
    Host Before loads / MB / sessions After loads / MB / sessions
    Laptop 132 / 4.63 / 38 127 / 4.65 / 41
    Desktop 129 / 4.54 / 58 54 / 1.78 / 23

    The drop comes from the desktop running fewer sessions in the after window, not from smaller loads: KB per load rose 1.4%.

    Per skill (both hosts):

    Skill Before loads, KB per load After loads, KB per load Change per load
    /source-control:pull-request 53, 50.7 54, 35.8 -29% (the #12739 move)
    /session-flow:handoff 98, 36.6 63, 37.3 +2% (not cut here)
    /session-flow:keep-going 38, 25.0 21, 25.1 flat (not cut)
    /work-items:work 7, 49.7 3, 62.0 n=3; not comparable
    /implementation:implement-dispatch 2, 72.4 2, 73.8 flat (not cut)

    Reading: the one cut with load evidence works per load. A total-bytes target needs either a session-count-normalised figure (bytes per session: 95.5 KB before, 100.6 KB after) or more cuts; the totals above should not be read as the cuts' effect.

    Script and full top-10 tables: kept locally (.work/12468-after/), not committed, per this repository's rule on one-off tooling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    host-runNeeds an unattended run on a host; the host runner takes it, not a person or the issue lane.priority: mediumReal value, no hard deadline; normal backlog flow.status: readyTriaged, unblocked, and fully specified; eligible to pick up.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.

    Type

    Fields

    Work status

    ready

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions