界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
开发与工程 · SKILL.md

salience-splitter

salience-splitter

【开发与工程】Splits an over-loaded always-loaded context asset (SKILL.md, CLAUDE.md, memory index) into a lean resident layer plus an on-demand layer, by when content is needed rather than by length, linked by imperative pointers. Alias: skill-splitter. Triggers: "SKILL.md too large", "split this skill", "skill is bloated", "skill file too long", "CLAUDE.md 너무 커".

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

name: salience-splitter description: 'Splits an over-loaded always-loaded context asset (SKILL.md, CLAUDE.md, memory index) into a lean resident layer plus an on-demand layer, by when content is needed rather than by length, linked by imperative pointers. Alias: skill-splitter. Triggers: "SKILL.md too large", "split this skill", "skill is bloated", "skill file too long", "CLAUDE.md 너무 커".' user-invocable: true allowed-tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob", "Agent"] model: sonnet

salience-splitter — Governance-Semantic Context Split

Renamed from skill-splitter (2026-07-05). Old-name references still route here. The rename reflects the generalized scope: the split criterion applies to any always-loaded context asset — a SKILL.md, a CLAUDE.md, or a memory index — not only skills. The label now names the substance (salience-tiering of always-loaded context), not one instance of it. Dogfood: applied to a memory index 2026-07-05.

An always-loaded asset that holds everything in one layer is not simple — it is unscoped. The goal is a lean always-loaded layer + an on-demand layer, not one file and its appendix.

Scope (all three share one criterion — salience: what must be in attention every load):

  • SKILL.md → always-loaded SKILL.md + on-demand SKILL_detail.md
  • CLAUDE.md → lean rules + on-demand detail docs (imperative > **Detail**: See … pointers)
  • memory index → hot MEMORY.md + on-demand MEMORY_archive.md (cold/closed/superseded entries)

Trigger Phrases

PhraseSituation
"this skill is getting too long", "trim the skill", "split this SKILL.md"Direct split request
"context-doctor flagged this skill", "SKILL.md is bloated"Post-diagnosis split
"I can't see the key parts", "too much detail in the skill file"Readability problem
"separate the bash from the logic", "move the templates out"Structural refactor request
/salience-splitterExplicit invocation

Core Principle — Governance-Semantic Criterion

The split criterion is NOT length. It is: when does this content need to be in memory?

LayerWhen neededExamples
SKILL.md (always-loaded)Every invocation — session boundaries, trigger recognition, step overview, decision tablesTriggers, principles, step names + criteria, key decision tables, Done When
SKILL_detail.md (on-demand)Only when executing a specific stepBash scripts, format templates, edge cases, step-by-step execution detail

Behavioral rules stay in SKILL.md — if a rule governs what counts (e.g. "these patterns = closed"), it is behavioral logic and must be always-loaded regardless of length.

One test: "If a consumer agent had only SKILL.md, could they recognize the trigger, understand the full step sequence, and make the key decisions?" → Yes = correct split. No = something behavioral is missing from SKILL.md.

Two floors this skill must not cross (behavioral — resident on purpose)

① A cut is measured, never eyeballed — and which measurement depends on what layer you are cutting from. Both branches forbid the same thing ("I read it and it looks redundant" is not a measurement); they differ in cost because the surfaces differ:

Cutting fromMeasurementWhy this one
Resident layer — CLAUDE.md, a memory index (loaded every session, for every task)Ablation harness: pre-registered question set · isolated arm B · reps>=3 · runner precondition bash scripts/ablation_calibrate.sh exits 0 (canon = scripts/probe_scope_check.sh header) · verdict line → .claude/regression/ablation_verdicts.mdA wrong cut here degrades every session silently, and the cost is unattributable after the fact
SKILL.md → SKILL_detail.md (loaded only when the skill is invoked)Cold-start sim: sim-conductor Area D-skill on SKILL.md alone must reach grade F (see Done When)The failure is scoped to one skill's invocation and the sim reproduces exactly that condition

🟥 ON A CONSUMER INSTALL THE RESIDENT ROW CANNOT BE RUN — say so rather than let a reader discover it. ablation_calibrate.sh and probe_scope_check.sh are deliberately not shipped (package_coverage_check.sh ACCEPTED_ABSENT): the procedure ablates this hub's resident CLAUDE.md, so an installer has nothing to point it at, and every run spends claude CLI calls on their account. So on an install:

Hub (this repo)Run the ablation. Verdict → .claude/regression/ablation_verdicts.md.
Consumer installThe harness is absent, so the measurement is unavailable — not waived. The floor holds in its degraded form: KEEP is the default and a CUT is not available. Record UNMEASURED — no ablation runner on this install; do not record a PASS.

The degrade direction is the whole point: an unavailable measurement makes cutting harder, never easier. A consumer who wants the resident row runs it against their own resident asset by copying the two scripts out of the hub — that is a deliberate act, not a default. Concretely, that means taking scripts/ablation_calibrate.sh and scripts/probe_scope_check.sh from the hub repo, running the calibrator until it exits 0 on your machine (it is a known-pair, not a formality — it is what proves the runner discriminates at all), and pointing the arms at YOUR resident file rather than the hub's. The verdict lands in your own .claude/regression/ablation_verdicts.md. 🟡 Named gap, surfaced by a blind floor-tier read of this very section (2026-08-27): two questions this skill does not answer, and pretending otherwise would be worse than saying so — (i) whether a section may ever be deleted OUTRIGHT rather than trimmed-with-a-pointer (every path here assumes the pointer), and (ii) whether verified duplication — two files grep-confirmed to carry the same text — is still subject to the full ablation, or whether that is the one case where "redundant" is a measurement rather than an impression. Both are open; treat them as KEEP until decided.

Arm B answering confidently wrong is a KEEP, not a pass — fluency is not recall, and that is the whole reason the arm is isolated. The same reading applies to the sim: a consumer that improvises plausibly without the moved rule is grade P, not F.

This skill is the one that executes resident removal, so the procedure is named here rather than assumed — an earlier version left the judgment "mentally", which is exactly the eyeball path both branches exist to replace. Do not read the resident row onto the SKILL.md row: requiring a full ablation for every ambiguous SKILL.md section would price routine splitting out of existence, which is how a floor turns into a bypass trainer (cross-family review 2026-08-11 flagged exactly that over-block in the first draft of this section).

② Every split must re-ask whether the destination is inside the gate. Moving content to a new path can move it out of the 4-axis gate's pathspec — the gate-locality class has recurred four times, most sharply when SKILL_detail.md fell outside a literal SKILL\.md term and 27.7% of the skill-spec surface went ungated (it leaked twice for real). .claude/rules/fh_4axis_gate.md names this skill as the producer that widens that hole every time the diet succeeds. So coverage is re-verified mechanically at split time, not assumed:

bash scripts/gate_pathspec_check.sh    # exit 0 = known-pair coverage holds, 1 = a pair broke

A destination path the gate does not match is not a "later" item: ship the pathspec update in the same commit as the split — the split and its coverage are one change, and separating them is how the surface silently shrinks.


Step Overview

Step 1 — Diagnose
    Read target SKILL.md → classify every section as Always / On-demand / Ambiguous
    → Produce classification table

Step 2 — Draft SKILL.md (trimmed)
    Keep: triggers · principles · step names + one-line criteria · decision tables · Done When
    Remove: bash scripts · format templates · multi-step execution detail · edge case catalogs
    Add: imperative pointer for each removed section → SKILL_detail.md §SectionName

Step 3 — Draft SKILL_detail.md
    One ## §SectionName header per pointer in SKILL.md
    Move removed content under its section
    Front-matter: name, description, load: on-demand
    → Gate check (Floor ②): destination path inside the 4-axis pathspec?
      bash scripts/gate_pathspec_check.sh — not-matched = update the pathspec in THIS commit

Step 4 — Verify
    phantom-quench: every §pointer in SKILL.md resolves to ## §SectionName in SKILL_detail.md
    sim-conductor Area D-skill: consumer agent with SKILL.md only → must reach grade F
      (grade scale — sim-conductor SKILL.md §Area-D: F = Functional/PASS · P = Partial · B = Broken)
    → Any pointer mismatch or grade P/B → fix before commit

Step 4 pointer↔header comparison — run it, don't eyeball it. Both sides need normalizing or the check produces ~100% false positives: real headers are written ## §Name — description, so a naive compare never matches. And extraction must be anchored to the declared pointer form (see "Imperative Pointer Format" below — a blockquote line whose bolded lead is followed by See), not to "a mention of the detail file": any prose that discusses a pointer, quoted or not, is otherwise collected as one. That is not hypothetical — a paragraph on this page names an example section, and a backtick-only filter counted it as a live pointer:

S="plugins/{plugin}/skills/{name}"   # the skill dir being split
# pointer side: any bolded-lead "See" line (the marker word varies — **Detail**, **Template**, …),
# and ALL §names on it (a documented variant puts two pointers on one line)
diff <(grep -E '^> \*\*[A-Za-z]+\*\*: See ' "$S/SKILL.md" \
         | grep -oE '§[A-Za-z0-9_-]+' | sed 's/^§//' | sort -u) \
     <(grep '^## §' "$S/SKILL_detail.md" | sed 's/^## §//; s/ *—.*//' | sort -u)
# rc=0 → every pointer resolves and every §header has a pointer. rc=1 → the diff names both directions
#         ("<" = pointer with no section · ">" = section with no pointer, i.e. an orphan).

Calibrate before trusting it (this check was wrong twice while being written — each narrowing looked reasonable and produced false orphans): run it across sibling skills and confirm it discriminates. Measured 2026-08-11 over 6 FH skills: 5 exit 0, steel-quench exits 1 on a real orphan (§Phase0 — no pointer anywhere in its SKILL.md), and this page's own prose example is not collected. A version of this check that flags everything, or nothing, is not measuring.

Orphan check covers ^## , not ^## § — and the two checks have different jobs. The diff above compares §-prefixed headers against pointers; a header written without the § prefix is invisible to it. Measured across this repo's SKILL_detail.md files: 139 ## headers vs 97 ## §, so 42 (30%) sit outside the comparison entirely and would pass forever. So run both, and read them as one rule:

diff (§ side)   → pointer↔header agreement, both directions
grep '^## '     → coverage net: any header the diff could not see
resolution      → give it the § prefix AND a pointer (then the diff covers it), or merge it away

A non-§ header listed by the grep and left alone is not a pass — it is the orphan the §-only scan used to hide.

Detail: See SKILL_detail.md §Verification-Checklist — pre-commit checklist table (8 checks) — read when running Step 4 verification.

Detail: See SKILL_detail.md §Split-Execution — step-by-step trimming procedure, SKILL_detail.md front-matter format, orphan-section check — read when executing Steps 2–3.

Detail: See SKILL_detail.md §Classification — ambiguous content decision algorithm, behavioral-vs-implementation test, 12 annotated examples — read when unsure which layer a section belongs to.


Imperative Pointer Format (required)

Pointers must be imperative (not advisory). The difference:

FormRisk
Advisory: "see SKILL_detail.md for details"Consumer agent may skip
Imperative: "> **Detail**: See \SKILL_detail.md §` — [what's there] — read when [specific condition]."`Consumer agent loads on trigger

Every removed section must have exactly one imperative pointer at the point of removal in SKILL.md.

Detail: See SKILL_detail.md §Pointers — pointer format variants, multi-pointer blocks, pointer placement rules — read when writing pointers.


Target Selection

Run on a SKILL.md when any one of:

  • context-doctor flags the file as oversized
  • SKILL.md exceeds ~300 lines
  • sim-conductor Area D-skill grades P or B (cold-start fails)
  • Consumer agent reports "could not proceed — too much detail before step 1"

Not a target: SKILL.md that has no bash scripts, format templates, or multi-step execution detail. Splitting a file with only behavioral content adds structure without governance value.


Connected Skills

SituationSkill
Diagnose which SKILL.md files are candidates/context-doctor or /harness-doctor
Verify §pointer grounding after split/phantom-quench
Verify cold-start still works after split/sim-conductor D skill <name>
Check new SKILL_detail.md for phantom claims/phantom-quench
Adversarial review of the split result/steel-quench

Done When

Common to all three scopes (§Scope declares SKILL.md · CLAUDE.md · memory index — the conditions below are the ones that hold whatever was split; scope-specific conditions follow):

Step 1 classification table produced
  (mandatory-pass — the table exists and every section carries a verdict)
+ Every AMBIGUOUS section carries the measurement its layer requires (Floor ①)
  (measured — resident layer: ablation verdict line in .claude/regression/ablation_verdicts.md
   (pre-registered set, isolated arm B, reps>=3) · SKILL.md layer: cold-start sim grade F.
   Eyeball judgment = NOT met on either branch)
+ Gate coverage re-verified for every destination path introduced by the split
  (mandatory-pass — `bash scripts/gate_pathspec_check.sh` exits 0, or the pathspec update
   ships in the same commit)
+ No behavioral rule lives only in the on-demand layer
  (judged — pair: an isolated consumer read that has ONLY the always-loaded layer and must reach
   a decision the moved rule governs; author re-reading their own split does not satisfy this)

Scope-specific — SKILL.md split:

+ SKILL.md trimmed: triggers · principles · step overview · decision tables · Done When retained
+ Imperative pointer for every removed section; SKILL_detail.md carries one ## §header per pointer
  (mandatory-pass — Step 4 normalized diff exits 0, both directions)
+ phantom-quench: 0 phantoms (all §pointers resolve)
  → Fallback (skill unavailable): run §Verification-Checklist manually from SKILL_detail.md
+ sim-conductor Area D-skill: grade F (consumer completes core task from SKILL.md alone)
  (measured — grade scale, sim-conductor SKILL.md §Area-D: F = Functional/PASS · P = Partial · B = Broken)
  → Fallback (skill unavailable): manually confirm "trigger → step overview → key decision → Done When" present

Scope-specific — CLAUDE.md split: the resident file keeps the rule and an imperative > **Detail**: See … pointer; the detail destination is inside the gate pathspec (Floor ②); a cold top-level session can still act on the rule without opening the detail file (judged — pair: a blind sim at the tier the rule must survive on, not the author's re-read). ⚠️ Resident-footprint claims are measured only by a fresh top-level /context — file char counts are not resident measurements, and an agent-view window cannot measure it at all.

Scope-specific — memory index split: every demoted entry is reachable from the archive by the recall path the index declares (mandatory-pass — grep the archive for the demoted entry's own nouns and hit it); the hot index keeps one line per surviving entry.

Not done: an on-demand section with no pointer from the always-loaded layer (orphan) — scan ^## , not ^## § (30% of real headers carry no §). Not done: consumer grade P (Partial) or B (Broken) after split — a behavioral rule was moved out when it should have stayed. Not done: a section CUT on "it looked redundant" with no ablation verdict line.

我的收藏