Fase 4 Items 2+3 (CC 2.1.114→181 gap-review). New orchestrated scanner `skill-listing-scanner.mjs` (prefix SKL) flags every active skill whose description exceeds the verified 1,536-char listing cap (CC 2.1.105, changelog L1502). Past the cap, Claude Code silently truncates the description the model reads to route skill invocation — dropping the trigger phrases at the tail. HOME-scoped over all user + plugin skills via enumerateSkills (COL is the model). - CA-SKL-001 (medium): description > 1,536 chars. Remediation folds in Item 2(b) — recommends disableBundledSkills + skillOverrides + trimming (designvalg A: no standalone GAP-check, which would fire for nearly everyone). - Designvalg B: v1 ships the verified cap ONLY. The aggregate 2%-of-context listing budget is deferred — it needs a context-window assumption that would turn a verified fact into a guess (would carry a CALIBRATION_NOTE if added). - Choice C: recognize the skillOverrides settings key (CC 2.1.129) in KNOWN_KEYS. Left OUT of TYPE_CHECKS — the value is a per-skill object (off/user-invocable-only/name-only), not a string; a 'string' check (as the plan sketched) would create a NEW false positive. Verify-first deviation. Registration: scan-orchestrator (13th scanner), humanizer (SKL → 'Wasted tokens' + static/_default translations), scoring SCANNER_AREA_MAP (→ Token Efficiency; no 11th area), README badge 12→13, CLAUDE.md (finding-id + test-count), docs/scanner-internals.md, gap-matrix + plan status notes. Snapshots reseeded hermetically (SEED_SNAPSHOT/UPDATE_SNAPSHOT): SKL entry with 0 findings in empty HOME, scanners_ok 11→12, claudeMdEstimatedTokens bump from the CLAUDE.md edits flowing through the cascade. Contamination grep clean. Suite 868/868 (856 baseline + 11 SKL + 1 skillOverrides). RED→GREEN logged per cycle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ter3E2JSi1Khgmuf2kady8
9.1 KiB
Plan — Fase 4 Items 2 + 3 (skill-listing token-styring)
Skrevet: 2026-06-18 · Scope: kun config-audit/ · Status: ✅ LEVERT 2026-06-18. Designvalg bekreftet: A=fold inn i SKL, B=v1 KUN 1 536-cap (aggregat utsatt), C=skillOverrides i KNOWN_KEYS (IKKE TYPE_CHECKS — verdien er objekt; avvik fra §C-skissen, verify-først). Syklus 1+3+4 ferdig; Syklus 2 (aggregat CA-SKL-002) gjenstår som valgfri stretch. Suite 868/868. Detaljer i STATE.md.
Forrige: Fase 4 Item 1 (4.7→modell-nøytral) levert som 8376dab. Baseline 856/856 grønn.
Mål
Lukke matrise-radene 167 + 169 (skill-listing token-styring): gjøre config-audit i stand til å anbefale/varsle om skill-listing-budsjett før CC selv trunkerer det. Item 2(a) (false-positive) er allerede gjort (Batch 1).
Verifiserte fakta (changelog-cache, CC 2.1.181 — re-verifisert 2026-06-18 FØR skriving)
| Fakta | Versjon | Changelog-linje |
|---|---|---|
disableBundledSkills + CLAUDE_CODE_DISABLE_BUNDLED_SKILLS — skjuler bundled skills/workflows/built-in slash commands fra modellen |
2.1.169 | L176 |
| Skill-listing-truncation-varsel viser nå antall berørte beskrivelser | 2.1.178 | L64 |
Truncation-varsel flyttet fra startup til /doctor |
2.1.144 | L666 |
skillOverrides: off / user-invocable-only / name-only (kollapser beskrivelse) |
2.1.129 | L995 |
| Per-beskrivelse listing-cap hevet 250 → 1 536 tegn + startup-varsel ved truncation | 2.1.105 | L1502 |
| Skill-tegnbudsjett skalerer med kontekstvindu = 2 % av kontekst | 2.1.32 | L2860 |
Matrise-korreksjon (verify-først): rad 170s hypotetiske settings-nøkler skillListingBudgetFraction / maxSkillDescriptionChars finnes ikke som nøkler. Budsjettet (2 % kontekst) og cap-en (1 536 tegn) er interne CC-mekanismer. Ekte config-levere er skillOverrides (2.1.129) + disableBundledSkills (2.1.169).
Item 2 — disableBundledSkills som token-lever (matrise-rad 166 + 167)
2(a) — false-positive-fiks → ✅ ALLEREDE GJORT (Batch 1)
disableBundledSkills ligger allerede i KNOWN_KEYS (scanners/settings-validator.mjs:25) + TYPE_CHECKS boolean (:53), og dekkes av testen NEW_KEYS (tests/scanners/settings-validator.test.mjs:133,176-180). Ingen kode. Matrise-rad 166 markert DONE.
2(b) — anbefaling (matrise-rad 167)
Designfunn: GAP-checks (scanners/feature-gap-scanner.mjs:91 GAP_CHECKS) er binære {id,tier,title,recommendation,check} der finding fyres når check() = false. En ren binær «disableBundledSkills ikke satt»-check ville fyre for nær alle brukere → støy + dårlig råd (lever-en fjerner ALLE bundled skills; bare verdt det ved faktisk listing-press).
Anbefalt (DESIGNVALG A — confirm): IKKE en frittstående GAP-check. Folde disableBundledSkills-anbefalingen inn som en remediation-lever i Item 3s SKL-scanner (fyres bare ved kvantitativt budsjett-press). Substansen i Item 2(b) leveres dermed via Item 3. Matrise-rad 167 omklassifiseres «folded into SKL (Item 3)».
Alternativ: frittstående tier-4 GAP-check gated på antall aktive skills (krever skill-enumerering → samme kobling som Item 3; mer kode, mer støyrisiko).
Item 3 — SKL-scanner: skill-listing-budsjett (matrise-rad 169)
Ny scanner scanners/skill-listing-scanner.mjs, prefiks SKL (ledig; bekreftet mot alle eksisterende prefikser). Finding-IDs CA-SKL-NNN.
Hva den gjør
- Primær (høy konfidens): flagg hver aktiv skill-beskrivelse > 1 536 tegn — verifisert hard cap → CC trunkerer den. Severity medium. Dette er rock-solid (ikke estimat).
- Aggregat (estimat, lavere konfidens): sum av skill-beskrivelse-tegn på tvers av ALLE aktive skills (user + plugin + bundled). Varsle når summen nærmer seg/overskrider budsjett. Budsjett = 2 % av kontekst → krever kontekstvindu-antakelse (se DESIGNVALG B). Merk med
CALIBRATION_NOTE-mønster (jf. TOK) og ±-usikkerhet — IKKE lat som vi vet brukerens kontekstvindu. - Remediation (alle funn): trim beskrivelse < 1 536;
skillOverrides: name-only(kollaps);disableBundledSkills: true(fjern bundled). ← her bor Item 2(b).
Gjenbruk (ikke gjenoppfinn)
- Aktiv-skill-enumerering:
enumerateSkills(pluginList)iscanners/lib/active-config-reader.mjs:465→{name, source:'user'|'plugin', pluginName, path, bytes, estimatedTokens}. Dekker user + plugin skills (bredere enn project-local). - Beskrivelse-uttrekk:
parseFrontmatter(content)?.frontmatter?.description(scanners/lib/yaml-parser.mjs), nøyaktig som TOK pattern F (token-hotspots.mjs:381-411). Les fil viareadTextFile(lib/file-discovery.mjs). estimateTokens()(active-config-reader.mjs:35) — markdown = bytes/4. Brukes hvis budsjett uttrykkes i tokens.
Avgrensning mot eksisterende TOK pattern F
TOK pattern F flagger project-local skill-md med beskrivelse > 500 tegn (strukturell «bloat»-heuristikk, SKILL_DESCRIPTION_THRESHOLD, token-hotspots.mjs:53). SKL er en annen linse: ALLE aktive skills (ikke bare project-local) + den verifiserte 1 536-cap-en (hard truncation) + aggregat-budsjett. Dokumentér de to linsene eksplisitt i begge scanner-headere så det ikke leses som duplikat.
⚠️ Åpne designvalg — BEKREFT med operatør FØR kode (per syklus)
- A — Item 2(b)-plassering: anbefalt = folde inn i SKL-remediation (ikke frittstående GAP-check). [Alternativ: tier-4 GAP-check.]
- B — kontekstvindu-antakelse for aggregat-budsjettet: anbefalt = konservativ default 200k tokens (2 % ⇒ budsjett), eksplisitt merket estimat m/
CALIBRATION_NOTE. Eventuelt: dropp aggregat-sjekken i v1 og lever KUN den verifiserte 1 536-cap-en (høyest konfidens, null gjetting) — minst risiko. [Anbefaler å starte med per-beskrivelse-cap; aggregat som stretch.] - C (valgfri relatert quick-win):
skillOverridesmangler iKNOWN_KEYS→ egen unknown-key false-positive (matrise-rad 170, L/S). Hvis SKL anbefalerskillOverrides, bør nøkkelen samtidig legges iKNOWN_KEYS+TYPE_CHECKS('string') for konsistens. Egen mini-syklus.
Utførelsesrekkefølge (hver = ratifisert failing-test-først, Iron Law)
Syklus 1 — Item 3 SKL-scanner (per-beskrivelse 1 536-cap):
- Failing test:
tests/scanners/skill-listing-scanner.test.mjs+ fixture med en skill-beskrivelse > 1 536 tegn → forventCA-SKL-001. (RED: scanner finnes ikke.) - Skriv
scanners/skill-listing-scanner.mjs(gjenbruk enumerateSkills + parseFrontmatter). - Registrer: import +
SCANNERS-entry iscanners/scan-orchestrator.mjs:19-65; humanizer-entry ilib/humanizer-data.mjs(SKL.static+_default) +SCANNER_TO_CATEGORYilib/humanizer.mjs:30-43(kategori'Wasted tokens'). - README-badge
scanners-12→13(validert avself-audit.mjs countScannerShape()); CLAUDE.md scanner-tabell +docs/scanner-internals.md. - Snapshot-reseed (HERMETISK):
SEED_SNAPSHOT=1(v5.0.0/) +UPDATE_SNAPSHOT=1(default-output/) — scan-orchestrator + posture endres hvis fixturenmarketplace-mediumtrigges. Verifisergit diff tests/snapshots/+ kontaminerings-grep.
Syklus 2 — Item 3 aggregat-budsjett (HVIS designvalg B = inkluder): failing test for sum-over-budsjett → CA-SKL-002; CALIBRATION_NOTE; kontekstvindu-konstant.
Syklus 3 — Item 2(b) remediation: verifiser at SKL-funn lister disableBundledSkills + skillOverrides + trim som levere (test på recommendation-tekst).
(Valgfri) Syklus 4 — designvalg C: skillOverrides i KNOWN_KEYS+TYPE_CHECKS + utvid NEW_KEYS-testen.
Verifisering (testbare kriterier)
node --test 'tests/**/*.test.mjs'grønn (baseline 856 + nye SKL-tester).- Failing-test-først bevist per syklus (RED → GREEN logget).
- Fixture med beskrivelse > 1 536 tegn → nøyaktig
CA-SKL-funn; fixture med korte beskrivelser → 0 SKL-funn. node scanners/self-audit.mjs --check-readmeren (badge 13 matcher).git diff tests/snapshots/reseedet bevisst, kontaminerings-grep ren (sadhguru/vegnorm/pluginCount).- Ingen ny
Opus 4.x-æra-stempling i ny scanner (gjenbruk modell-nøytral framing fra Item 1).
Scope-gjerde
Kun config-audit/. Item 2(a) ferdig. Items 2(b)/3 = ny kode → ratifisert design (A+B) + failing-test-først per syklus. IKKE auto-eskalér; bekreft A/B FØR første scanner-linje.
Risiko
- Aggregat-budsjett er et estimat (ukjent kontekstvindu) — håndteres med CALIBRATION_NOTE + å lede med den verifiserte 1 536-cap-en. Ved tvil: lever KUN per-beskrivelse-cap i v1.
- Snapshot-drift: ny orkestrert scanner endrer scan-orchestrator/posture-snapshots → MÅ reseedes hermetisk (
hermeticEnv()), ALDRI rånode scanners/.... - Matrise er agent-generert (2 kjente versjonsfeil) — fakta over er re-verifisert mot changelog; re-verifiser nye påstander før skriving.
Pekere
- Kartlegging (denne sesjonen): scanner-registrering, GAP-mekanisme, enumerateSkills, snapshot-mønster — alt ankret i koden over.
- Gap-matrise:
docs/cc-2.1.x-gap-matrix.mdrad 166 (✅ DONE), 167 (Item 2b), 169 (Item 3), 170 (skillOverrides quick-win). - Mønster-katalog:
knowledge/prompt-cache-patterns.md(rad 167/169 retargetet hit).