@chrono-meta/fh-gate 1.4.49 → 1.4.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CATALOG.md CHANGED
@@ -8,6 +8,12 @@ AI reads this file first when searching past work. Open individual files for det
8
8
 
9
9
  <!-- Add entries in reverse date order (newest at top) -->
10
10
 
11
+ ### 2026-07-07 | forge-harness | #sister-asset, #cross-audit, #revfactory, #harness-100, #agent-composer, #benchmarking, #linkedin, #source-verification, #diffusion-llm
12
+ **File:** tracks/_audit/session_2026_07_07_revfactory-harness.md
13
+ Sister-asset cross-audit of `revfactory/harness` + `revfactory/harness-100` (AX TF lead-recommended benchmarking target) vs FH — their axis = one-shot team-architecture generation + a 200-harness ready library (breadth/quick-start); FH's axis = dynamic composition (`agent-composer`) + governance (4-axis gate, irreversibility floors, continuity), which their pipeline lacks entirely. Plus LinkedIn source-verification for the operator's 2 queued insight links: diffusion-LLM paradigm-shift paper confirmed accurate (ICML 2026 Outstanding Paper Award, JustGRPO, arXiv:2601.15165 via official ICML blog); "Claude Code loop-engineering" post confirmed to be about `k021/claude-code-skills` — the *same* sister-asset Gemini already analyzed, not new content.
14
+ - Decision: no functional import beyond a C-tier team-pattern naming label for `agent-composer` output; FH's governance moat holds (revfactory doesn't compete on that axis). Both LinkedIn links closed.
15
+ - Open: adopt 6-pattern naming in agent-composer (operator HITL); harness-100-style pre-built library stays gated behind the existing 3+-recurrence trigger.
16
+
11
17
  ### 2026-06-27 | forge-harness | #sister-asset, #cross-audit, #hermes-agent, #nous-research, #self-improving-agent, #skills, #memory, #messaging-gateway
12
18
  **File:** tracks/_contrib/session_2026_06_27_hermes-agent-nous-self-improving-cross-audit.md (committed via _contrib consent lane — authored in an ephemeral cloud session where tracks/_audit/ is gitignored/non-durable)
13
19
  Sister-asset cross-audit of **Hermes Agent (Nous Research)** vs FH, triggered by a LinkedIn post (esperer) distilling Hermes' official *Tips & Best Practices* (post = faithful doc summary, not original methodology; same summary circulates on Threads). ~90% of Hermes' best-practice surface is already present in FH (persistent memory · auto-skill-from-repetition · skill self-improvement · context economy · delegation · model selection — all grounded to `plugins/*/skills/`), and on the **self-improvement + governance** axis FH is *ahead*: Hermes *advises* "review auto-generated skills," FH *mechanically enforces* it (pre-commit 4-axis gate + steel/phantom-quench + HITL). Key honest finding — most apparent "gaps" dissolve: cron/daemon is a **deliberate FH boundary** (`self_evolution_routine.md` §8 "recommendation surface, not a daemon"), external-memory-providers **already audited** (companion-store pluggable, 2026-06-11). Only genuine absence = **messaging gateway** (Telegram/Slack daily-driver), which is a *delivery channel*, not methodology.
@@ -177,7 +183,7 @@ CC built-ins utilization imports (operator-approved; video claims verified 9/13
177
183
  ### 2026-06-10 | forge-harness | #ingest-gate, #contradiction-scan, #crossref-lint, #llm-wiki, #karpathy
178
184
  **File:** .claude/rules/sync_push_protocols.md (+ harness-doctor SKILL.md, probes.md)
179
185
  Karpathy LLM-Wiki sister-audit imports (operator-approved; convergence case n=5, citable primary source): I1 — contradiction scan as Sync step 3 (ingest gate, judged + verify-bidirectional pair): new knowledge grepped against existing claims before indexing, conflicts flagged in both files, old-claim removal is HITL. I2 — harness-doctor L4 knowledge cross-ref lint: no CATALOG entry = S-tier index orphan, no inbound ref = R-tier orphan page. Probes G-SYNC-01/G-LINT-01 added (30 total).
180
- - Decision: scale escape (W1) deliberately NOT built — watch-item with trigger (CATALOG hundreds of entries / repeated search misses); operator-preferred first remedy = skill-splitter-style CATALOG split-mapping, RAG hybrid only after that.
186
+ - Decision: scale escape (W1) deliberately NOT built — watch-item with trigger (CATALOG hundreds of entries / repeated search misses); operator-preferred first remedy = salience-splitter-style CATALOG split-mapping, RAG hybrid only after that.
181
187
  - Open: npm republish (harness-doctor SKILL.md shipped) — folded into the open 1.4.8 handoff.
182
188
 
183
189
  ### 2026-06-10 | forge-harness | #golden-probes, #offline-eval, #doc-code-coupling, #anthropic-4layer
@@ -282,7 +288,7 @@ Post-merge micro R-tier cleanup: corrected two prompt-regression probe expectati
282
288
 
283
289
  ### 2026-06-03 | forge-harness | #goal-quench, #skill-evolution, #mode-ladder, #sidecar-routing
284
290
  **File:** plugins/fh-meta/skills/goal-quench/SKILL.md
285
- Evolved goal-quench into a fluid core→pro→max mode ladder. Core: token-budget-gate + pipeline-conductor --quick; pro: +context-doctor +agent-composer; max: +plugin-recommender +cross-ecosystem-synergy-detection. Phase-1 budget verdict auto-recommends mode. Ran full-harness dogfood sweep (33 skills): fixed phantom refs, dead blocks, stale agent forks (4 deleted), trigger collision, and 3 skill-splitter splits.
291
+ Evolved goal-quench into a fluid core→pro→max mode ladder. Core: token-budget-gate + pipeline-conductor --quick; pro: +context-doctor +agent-composer; max: +plugin-recommender +cross-ecosystem-synergy-detection. Phase-1 budget verdict auto-recommends mode. Ran full-harness dogfood sweep (33 skills): fixed phantom refs, dead blocks, stale agent forks (4 deleted), trigger collision, and 3 salience-splitter splits.
286
292
  - Decision: RED tier reframed as max-mode decomposition on-ramp, not hard block
287
293
 
288
294
  ### 2026-06-02 | _audit | sister-asset, token-efficiency, compression, headroom
package/CHEATSHEET.md CHANGED
@@ -511,7 +511,7 @@ Claude agents feature
511
511
  |---|---|---|
512
512
  | `install-wizard` | First-install onboarding (zshrc, sentinels, the FH self-gate) | "first-time setup", "run the install wizard" |
513
513
  | `hub-cc-pr-reviewer` | Reads a PR diff → 8-matrix baseline-consistency check → review comment + merge call | "review this PR", "check this diff" |
514
- | `skill-splitter` | Splits an over-large SKILL.md that "does everything" into scoped files | "this skill is bloated", "SKILL.md too large", "split this skill" |
514
+ | `salience-splitter` | Splits an over-large SKILL.md that "does everything" into scoped files | "this skill is bloated", "SKILL.md too large", "split this skill" |
515
515
 
516
516
  ### Agents (sub-agents, dispatched — not slash commands)
517
517
 
package/CLAUDE.md CHANGED
@@ -142,7 +142,7 @@ Compose session-card candidates **into door ③ (field) and the 🔧 door (FH-de
142
142
 
143
143
  **Identity marker**: every greeting response (Step ②) opens with 🐿️ then an identity-revealing welcome line **on the same line** (a space after 🐿️; exact count not significant — the renderer collapses it — the invariant is *same-line*, not 🐿️ alone) — new / exploratory = "Welcome to FH." · returning = "Welcome back to FH." · operator (FH-dev state) = "The FH operator — good to see you." It is embedded in all skeletons above (do not strip it when composing doors); the exploratory branch template (`fh_detail_protocols.md` Step 2) uses the "Welcome to FH." line.
144
144
 
145
- **Guards**: explicit task-entry utterance → skip onboarding · once per session · code/debug requests → start working directly · project routing is a suggestion, mention at most once
145
+ **Guards**: explicit task-entry utterance → skip onboarding **menu** (the door skeleton / greeting) — but this **never skips the Mode D companion-store freshness load** (pull + INDEX read + card-vs-commit reconcile); that is a data-load, not the menu, and it fires even when the first message is a task (measured miss 2026-07-05: task-first entry skipped the companion-store pull → stale memory → wrong recommendations; now hook-backed via `scripts/fh_session_load.sh`, see `modes_and_value.md §Session-start freshness`) · once per session · code/debug requests → start working directly · project routing is a suggestion, mention at most once
146
146
  **Metadata-is-not-intent guard**: the trigger is the user's **typed message only**. Session metadata — branch name (auto-derived from the first message, e.g. `claude/korean-greeting-*`), repo name, file paths — is **never** a task spec and never suppresses or redirects the greeting trigger. A bare greeting fires onboarding even when the branch name looks like a feature request; if the only "task" signal lives in metadata and not in what the user typed, treat the message as a greeting and run the greeting branch + door skeleton above.
147
147
 
148
148
  ## New Skill Creation Pre-Commit Gate
@@ -285,6 +285,12 @@ unknown) and surface **one line** — then proceed, never block:
285
285
  inviolable; a pin is not a cap — tier-floor resolution §Floor governance) · field-project operation
286
286
  sessions (no FH asset modification) never see this notice — the Sonnet default stays friction-free.
287
287
 
288
+ > **Related — capability-escalation consent**: whether a session actually *escalates* to a stronger
289
+ > model or a cross-family sidecar (not just this advisory notice) is governed separately by
290
+ > `knowledge/shared/harness-core/capability_escalation_consent.md` — the negotiated-consent protocol
291
+ > (UAP `sidecar_consent`/`floorup_consent`) that decides ask-once vs. no-surprise floor-up/sidecar use.
292
+ > This notice is the passive advisory; that doc is the active escalation gate.
293
+
288
294
  ## Field-Harness Load-Bearing Change Gate (cross-family, pre-merge)
289
295
 
290
296
  The 4-axis gate above fires on **FH asset** changes. But the correlated blind spot it guards —
@@ -537,7 +543,7 @@ Proposal format: `"I see [X]. Want me to run /[skill] to [one-line description]?
537
543
  | "add this MCP server", "mount this MCP", "mcp.json에 추가", "connect this tool server" (external-MCP mount intent — **proactive**, fire *before* first tool call; mount intent only — a failing/erroring mounted server is `/mcp-circuit-breaker`'s row above) | `templates/.claude/rules/mcp_tool_gating.md` (name-keyed ask/allow table — never trust server annotations or names; fill §3 at mount time) |
538
544
  | "token budget", "how expensive", "estimate tokens", "will this cost a lot" | `/token-budget-gate` |
539
545
  | "did my rule change break anything", "regression check", "test harness changes" | `/prompt-regression` |
540
- | "SKILL.md too large", "split this skill", "skill is bloated", "skill file too long" | `/skill-splitter` |
546
+ | "SKILL.md too large", "split this skill", "skill is bloated", "skill file too long" | `/salience-splitter` |
541
547
  | "review for the team", "CTO review", "decision-maker", "share with leadership", "approval deck" | `/apex-review` |
542
548
  | "run full pipeline", "verify everything", "end-to-end sweep", "chain all verifications" | `/pipeline-conductor` |
543
549
  | "help me write a prompt", "build a prompt", "improve this prompt", "prompt template" | `/meta-prompt-builder` |
package/README.md CHANGED
@@ -214,7 +214,7 @@ two more signatures keep it running: `harvest-loop` (each session's lessons beco
214
214
  | `token-budget-gate` *(fh-commons)* | Pre-task token cost estimate | "How expensive is this?" |
215
215
  | `mcp-circuit-breaker` *(fh-commons)* | MCP tool failure pattern detection | "MCP keeps failing" |
216
216
  | `quench-challenger` *(fh-commons)* | Adversarial pressure-test agent | "Challenge this with a devil" |
217
- | *(+ additional assets)* | marketplace-gate · contention-layer · edit-manifest · fact-checker · goal-quench · hub-persona-auditor · install-doctor · memory-hygiene · persona-innovator · prompt-regression · public-surface-audit · skill-splitter | |
217
+ | *(+ additional assets)* | marketplace-gate · contention-layer · edit-manifest · fact-checker · goal-quench · hub-persona-auditor · install-doctor · memory-hygiene · persona-innovator · prompt-regression · public-surface-audit · salience-splitter | |
218
218
 
219
219
  | Active count | Diagnosis |
220
220
  |:---:|---|
@@ -233,7 +233,7 @@ two more signatures keep it running: `harvest-loop` (each session's lessons beco
233
233
  | Gate / Guard | `token-budget-gate` · `asset-placement-gate` · `marketplace-gate` |
234
234
  | Discovery | `plugin-recommender` · `cross-ecosystem-synergy-detection` · `frontier-digest` · `verify-bidirectional` |
235
235
  | Content / Simulation | `sim-conductor` · `apex-review` · `meta-prompt-builder` · `deep-clarify` |
236
- | Setup | `install-wizard` · `hub-cc-pr-reviewer` · `skill-splitter` |
236
+ | Setup | `install-wizard` · `hub-cc-pr-reviewer` · `salience-splitter` |
237
237
 
238
238
  > **Full phrasebook** — every skill + agent with its one-line definition and the plain-language phrase
239
239
  > that triggers it: [`CHEATSHEET.md` §12](CHEATSHEET.md#12-skills--agents--what-each-does-and-what-to-say).
@@ -0,0 +1,125 @@
1
+ # Capability-Escalation Consent Protocol
2
+
3
+ > **Principle**: any escalation that raises **cost or trust surface** — recruiting a **cross-family
4
+ > sidecar** (external model families see the work) or a **model-tier floor-up** (Sonnet → Opus, higher
5
+ > $/token) — is **consent-gated and negotiated up front**, never sprung silently. A user who was never
6
+ > asked, then finds a paid/external escalation happened, feels **blindsided (뒤통수)**. The harness
7
+ > must run **intelligently on Claude Code alone at the Sonnet floor** for anyone who declined, using
8
+ > **sub-agents** in place of cross-family sidecars — as a *first-class mode*, not a degraded one.
9
+
10
+ This is a **규약 (convention)**, not a per-call decision: the same answer holds for the whole session
11
+ once settled, and is **remembered across sessions** (UAP) so it is asked at most once.
12
+
13
+ ---
14
+
15
+ ## Two escalation axes (same consent shape)
16
+
17
+ | Axis | Escalation | Why it needs consent | Floor when declined |
18
+ |---|---|---|---|
19
+ | **(a) Cross-family sidecar** | recruit codex / agy / gemini / local-4090 as a verifier | work leaves the Claude boundary (external family sees it) + external billing | **Tier-3 CC-only sub-agent** (isolation-decorrelation, honest same-family note) |
20
+ | **(b) Model-tier floor-up** | Sonnet → Opus for a depth-heavy turn | higher $/token (Opus ≈ 3–5× Sonnet); the operator's real cost lever | **stay at Sonnet** (the established minimum-recommended floor) |
21
+
22
+ **Sonnet = minimum-recommended model is already established** — so the declined-floor is safe: the
23
+ harness is *designed* to run well at Sonnet, not crippled by it (`[[feedback_harness_aerodynamics_perceived_perf]]`).
24
+
25
+ ---
26
+
27
+ ## When consent is settled — two entry points
28
+
29
+ ### 1. Onboarding negotiation (install-wizard) — the no-surprise path
30
+
31
+ install-wizard **explicitly negotiates both axes** at setup, as named items:
32
+ - *"Allow cross-family sidecars (codex/agy/local) for adversarial verification of load-bearing changes? They add external-family decorrelation but external billing applies."* → records `sidecar_consent`.
33
+ - *"Allow automatic Sonnet→Opus floor-up on depth-heavy turns? Opus is ~3–5× the cost; declining keeps you at the Sonnet floor and asks per-occasion instead."* → records `floorup_consent`.
34
+
35
+ Settling this at onboarding is the **whole point**: the escalation is then *expected*, never a surprise
36
+ on the bill or the egress log.
37
+
38
+ ### 2. Runtime ask-once (for anyone who skipped onboarding setup) — the graceful path
39
+
40
+ A user who skipped explicit setup is **not** auto-escalated. Instead, the **first time** an escalation
41
+ is actually needed:
42
+ - **Ask once**, at the moment of need, framed with the cost/trust reason:
43
+ *"This turn needs Opus depth (higher cost) — proceed at Opus, or stay at Sonnet?"* /
44
+ *"This load-bearing change is best verified cross-family (external billing) — recruit a sidecar, or verify with CC sub-agents only?"*
45
+ - **Accept** → record consent (UAP), proceed, no re-ask.
46
+ - **Decline** → record decline (UAP), **mark the escalation "recommended only"** going forward (surface
47
+ it as a one-line recommendation when relevant, **never a re-nag**), and **proceed at the floor**
48
+ (Sonnet / Tier-3 sub-agent).
49
+
50
+ The ask fires **once per axis**; the answer is remembered. A declined axis becomes a standing floor, not
51
+ a per-turn question.
52
+
53
+ ---
54
+
55
+ ## The declined mode is first-class, not "degraded"
56
+
57
+ When an axis is declined (or no sidecar is reachable), the fallback is **the user's chosen normal
58
+ operating mode**, and must be framed that way:
59
+
60
+ - **Cross-family declined → Tier-3 CC-only sub-agent verification.** Multiple **isolated** Claude
61
+ sub-agents adversarially verify (isolation-decorrelation), with an **honest same-family note**
62
+ ("no cross-family diversity — verification is isolation-decorrelated only"). This is intelligent
63
+ operation, **not** "reduced value / degraded" language. (`[[feedback_judge_robustness_mechanical_anchor]]`
64
+ still holds: the governor keeps the terminal verdict + a mechanical anchor.)
65
+ - **Floor-up declined → stay at Sonnet**, run the turn with good harness structure. No apology framing.
66
+
67
+ **Reframe rule**: the Sidecar Resolution Protocol's Tier-3 line and auto-decorrelation's degrade ladder
68
+ must not read "no diversity; reduced value" for a *declined* user — that pathologizes their choice.
69
+ Distinguish **declined** (chosen floor — first-class) from **unavailable-but-wanted** (genuine
70
+ degrade-with-note). Only the latter carries the degrade framing.
71
+
72
+ ### Reconciliation with the corp fail-closed invariant
73
+
74
+ The pmh corp degrade-invariant (`local_pmh_context.md` auto-decorrelation Step 6) says a load-bearing
75
+ change with **no reachable cross-family panel → NOT-CONVERGED / ask operator**. That is the
76
+ **unavailable-but-expected** case (consent given, panel down). The **declined** case is different: the
77
+ user opted out, so Tier-3 sub-agent verification **is** the standing bar (with the honest same-family
78
+ note), and load-bearing changes proceed under it — not blocked. Membership: `floorup_consent`/
79
+ `sidecar_consent == declined` in the UAP routes to the first-class floor; absence of a *wanted* panel
80
+ routes to fail-closed.
81
+
82
+ ---
83
+
84
+ ## UAP persistence (behavioral pref — never domain content)
85
+
86
+ `operational_adaptation.md` UAP gains two fields:
87
+ - `sidecar_consent: accepted | declined | unset`
88
+ - `floorup_consent: accepted | declined | unset`
89
+
90
+ **READ** (session start / at point of need): `declined` → route to floor, surface as recommendation
91
+ only, no re-nag. `accepted` → escalation available (still per-need, no auto-run). `unset` → ask-once
92
+ on first need (runtime path above).
93
+ **WRITE**: on onboarding settle, or on the first runtime accept/decline.
94
+
95
+ Ephemeral/cloud sessions (UAP wiped) → operate from the **Sonnet floor + CC-only** default (the safe
96
+ floor), do not fabricate consent.
97
+
98
+ ---
99
+
100
+ ## Cost lens (why this IS the cost-governance mechanism)
101
+
102
+ The floor-up consent prompt is **the operator's cost lever made explicit** (measured: Sonnet-economized
103
+ ≈ 34× subscription; Opus-full 40–60×, `cost_report_2026-07-07`). Default Sonnet floor + escalate-Opus-
104
+ **only-where-depth-pays**-with-consent is precisely "amortize Opus on the turns that earn it." Pair with
105
+ a **free internal-model execution lane** where the environment has one (`[[feedback_multimodel_3lane_architecture]]`)
106
+ to offload exec cost off the paid API entirely. The protocol turns hard-won economizing into a mechanical default.
107
+
108
+ ---
109
+
110
+ ## Done When
111
+
112
+ - **Both axes negotiated at onboarding** (install-wizard names sidecar + floor-up as consent items). *[mandatory-pass — grep install-wizard for both items]*
113
+ - **Runtime ask-once wired** for `unset` consent at first need; decline → recommend-only + floor, no re-nag. *[judged — pair: Sonnet target-tier blind sim of a skipped-onboarding session hitting first floor-up]*
114
+ - **UAP fields present + READ applied** (`sidecar_consent`, `floorup_consent`). *[mandatory-pass — grep operational_adaptation.md]*
115
+ - **Declined-mode reframed first-class** (no "degraded/reduced-value" language on a declined user's Tier-3 path). *[judged — pair: challenger reads auto-decorrelation + Sidecar Resolution for pathologizing language]*
116
+ - **Corp fail-closed reconciled** (declined ≠ unavailable-but-wanted). *[judged — pair: the target-tier sim above exercises both branches]*
117
+
118
+ ## Guards
119
+
120
+ - **Human override inviolable** — a consent is a default, never a cap; the operator can always force a
121
+ tier/sidecar for a given turn (`[[feedback_verify_before_downgrade]]` floor governance).
122
+ - **Never auto-switch the session model** — the floor-up ASK proposes; the human acts (`/model`). The
123
+ protocol never flips the model itself.
124
+ - **Sonnet floor is a floor, not a ceiling** — declined-floor-up still escalates *within* Sonnet's
125
+ harness depth (sub-agents, good structure); it does not cap capability, only cost/trust surface.
@@ -37,12 +37,31 @@ ls ../ | grep -iE '(forge-harness|meta-harness|-harness|-hub)'
37
37
  ls .claude/registry/LOCAL_SKILL_REGISTRY.md 2>/dev/null
38
38
  ```
39
39
  - File exists and modified within 7 days → load into session
40
- - Missing or older than 7 days → regenerate:
40
+ - Missing or older than 7 days → regenerate.
41
+
42
+ **No hardcoded root — derive the install location (users install FH anywhere).** The projects root is
43
+ the *parent of the FH repo*, discovered at runtime, never a literal `~/projects` / `~/PycharmProjects`
44
+ (a hardcoded root silently returns 0 on any machine whose layout differs — the 2026-07-05 dead-path
45
+ `fail-open` bug: `find ~/projects` on a `~/PycharmProjects` machine → 0 catches → the registry is
46
+ overwritten empty and cross-project summon goes dark):
41
47
  ```bash
42
- find ~/projects -path "*/.claude/skills/*/SKILL.md" \
43
- -not -path "*/forge-harness/*" 2>/dev/null
48
+ HUB="${CLAUDE_PROJECT_DIR:-$(pwd)}" # FH 레포 위치 (설치 위치 무관, 감지)
49
+ ROOT="$(cd "$HUB/.." 2>/dev/null && pwd)" # 형제 프로젝트가 사는 부모 = 프로젝트 루트
50
+ # 두 레이아웃 모두 포착: .claude/skills/*/SKILL.md AND 루트-레벨 */SKILL.md (예: gstack).
51
+ # vendored(.venv·site-packages·node_modules·.git) 제외 — 없으면 playwright/streamlit 스킬까지 삼킴.
52
+ FOUND="$(find "$ROOT" -name SKILL.md \
53
+ -not -path "*/.venv/*" -not -path "*/site-packages/*" \
54
+ -not -path "*/node_modules/*" -not -path "*/.git/*" \
55
+ -not -path "$HUB/*" 2>/dev/null)" # exclude FH's own subtree by DERIVED path, not a name-literal (works when FH is cloned under any dir name)
44
56
  ```
45
- Group by project update `.claude/registry/LOCAL_SKILL_REGISTRY.md`. Propose cross-project skills when request maps to registry. Scan once per session.
57
+ Then **fail-closed** (irreversible-ish: a silent empty overwrite blinds the bus): if `$FOUND` is empty
58
+ **and** the existing registry has >0 entries, do **not** overwrite — flag `⚠️ scan returned 0 (root=$ROOT);
59
+ kept existing registry` and skip the rewrite. Only rewrite when the scan is non-empty (or the registry
60
+ was absent). Group by project (parent dir name). Record per skill: name · path · description · trigger
61
+ phrases · `requires_cwd` · `direct-executable` · `origin(FH|project|external)`+trust. **Non-FH skills are
62
+ propose-only (ask-tier), never auto-run** — a cross-project skill body is an injection surface. Propose
63
+ cross-project skills when a request maps to the registry. Scan once per session. (Detection belongs at
64
+ install too — `/install-wizard` records HUB/ROOT so the runtime never guesses; see install-wizard.)
46
65
 
47
66
  ### Step 2 — Active Proposal
48
67
 
@@ -1,7 +1,7 @@
1
1
  # Measurement-Integrity Checklist — cross-model measurement pre-flight
2
2
 
3
3
  > A cross-model measurement is only trustworthy if its **instrument** is verified first.
4
- > Measurement integrity is a *precondition*, not a result. Three observed failure modes, each with a
4
+ > Measurement integrity is a *precondition*, not a result. Four observed failure modes, each with a
5
5
  > concrete countermeasure. Consult this before any FH measurement that compares models (sims, sidecar
6
6
  > comparisons, capability-equalizer runs, the-bible model panels, A6-class experiments).
7
7
 
@@ -16,6 +16,7 @@ becomes a gate other skills invoke, revisit the weight.
16
16
  | 1 | **Silent model fallback** — passing a model *slug* silently resolved to a weaker model (e.g. an `agy` slug fell back to Flash) instead of the intended one. The run *looks* like the named model but isn't. | **Pin the display name, not the slug** (e.g. `"Gemini 3.1 Pro (High)"`, not a bare slug). Confirm the resolved identity, don't assume the slug binds. |
17
17
  | 2 | **Non-deterministic borderline verdicts** — contested/borderline cases flip across runs (observed: haiku 4/4 flip; flagship models flip too — flipping is **not** a tier signal). A single draw is noise, not a measurement. | **reps ≥ 3 on any borderline/contested verdict.** A single run on a contested case is inadmissible. Report the flip pattern (STABLE vs FLIP), not just the modal verdict. |
18
18
  | 3 | **Generic self-identity probe** — a probe any model passes ("are you working? → OK") proves nothing about *which* model answered. | **Use a discriminating probe** — one that two different models answer *differently*. A generic-pass probe is invalid. The probe is a **pattern, not a fixed string**: a probe that discriminates Opus 4.8 from Sonnet 4.6 today may both-pass a future model generation, so **re-validate the probe each model generation** (same staleness class `memory-hygiene` exists to catch). |
19
+ | 4 | **Serving-path / quantization variance** — the *same* display-name model served over two different backends (different quantization/infra) is a **different instrument** and yields materially different measurements. Observed: one GLM-5.2 model family gave effect-size delta **+0.21** when served via an internal NVFP4-quantized deployment vs **+0.08** via an OpenRouter relay — same model name, ~2.6× different effect (n=864, reps≥3). A correctly-pinned display name (item #1) is **necessary but not sufficient**. | **Pin *and record* the serving path** — backend host + quantization, not just the display name. Two runs are comparable only if the serving path matches; a name match across different infra is an implicit apples-to-oranges. When you cannot hold it fixed, **report the serving path as a measured variable**, not a constant. |
19
20
 
20
21
  ## Why these are entangled (and why they matter beyond their own scope)
21
22
 
@@ -28,10 +29,17 @@ single-draw artifact. Item #3 (discriminating probe) **embodies** the judge-robu
28
29
  mechanical-anchor principle — don't trust self-reported identity, prove it discriminatingly
29
30
  ([[feedback_judge_robustness_mechanical_anchor]]).
30
31
 
32
+ Item #4 (serving-path variance) **sharpens** item #1 into a two-part identity: #1 catches the *wrong
33
+ model* (a slug that fell back); #4 catches the *right model on the wrong instrument* (a correct name
34
+ served over a different quantization/backend). The verified identity a measurement records is therefore
35
+ **name + serving path**, not name alone — a family-decorrelation claim (cross-family sidecar) is only
36
+ sound once the serving path of each family is itself pinned, else "different family" silently smuggles
37
+ "different infra" ([[reference_measurement_serving_path_variance]]).
38
+
31
39
  ## Done When
32
40
 
33
- - The checklist enumerates all three failure modes, each with its countermeasure.
34
- *Check class: mandatory-pass (binary — three items present, each with a countermeasure).*
41
+ - The checklist enumerates all four failure modes, each with its countermeasure.
42
+ *Check class: mandatory-pass (binary — four items present, each with a countermeasure).*
35
43
  - The probe item specifies a **discriminating** test and rejects generic probes.
36
44
  *Check class: judged, pair: a probe that two different models both pass must FAIL this check; a
37
45
  discriminating one must distinguish them.*
@@ -57,3 +65,15 @@ mechanical log.
57
65
  ambiguity). Sister findings: [[feedback_correlated_blindspot_union_over_majority]] (reps≥3 prerequisite),
58
66
  [[feedback_judge_robustness_mechanical_anchor]] (discriminating-probe = mechanical anchor),
59
67
  [[reference_agy_model_catalog]] (display-name pin — agy slug fallback documented there).
68
+
69
+ **#4 added** (2026-07-05): serving-path variance surfaced in a cross-family verdict-invariance run
70
+ (n=864, borderline fixtures × 2 conditions × K=6 paraphrase × reps≥3). An identical GLM-5.2 model name
71
+ served over an internal NVFP4-quantized deployment vs an OpenRouter relay gave +0.21 vs +0.08
72
+ effect-size delta — quantifying that "same model name ⇒ same measurement" is false. Provenance +
73
+ generalizable finding: [[reference_measurement_serving_path_variance]].
74
+
75
+ **External corroboration** (2026-07): the local-LLM community independently reports the same hazard —
76
+ practitioners conflate "running model X" with running a *pruned/quantized derivative* of X (aggressive
77
+ low-bit quantization + expert pruning measurably degrade long-context quality while the model *name* is
78
+ unchanged). This is a general measurement pitfall, not FH-specific: a leaderboard or replication that
79
+ pins only the display name silently compares different instruments across serving paths.
@@ -167,6 +167,35 @@ buff and degrades that model's realized intelligence** — not just Claude's. Th
167
167
  is autocomplete/QA only, which is exactly its demoted role. (Derived 2026-07-03, operator + cross-vendor
168
168
  Gemini concurrence; extends the governor=native-CC point to every vendor.)
169
169
 
170
+ ### Batch-judging corollary — the native harness is for interactive/agentic work, not batch scoring
171
+
172
+ The vendor-native harness gives a model its highest capability for **interactive, agentic** tasks
173
+ (repo-grounded audit, multi-step design, tool-use) — but that *same* agentic loop is a **liability for
174
+ high-volume batch judging**: a deterministic verdict emitted over N fixtures, where there is nothing for a
175
+ tool-use loop to do. Measured 2026-07-04 (H1 verdict-invariance run): the native `codex exec` spins a full
176
+ agentic session per judge (hooks + reasoning ≈ an order of magnitude more tokens than a bare completion),
177
+ and native `agy -p` (once its headless permission-wait is cleared) returns *agentic prose* — a "Summary of
178
+ Work" — rather than a parseable last-line verdict. Both **complete**, but at a cost/parse profile wrong for
179
+ batch.
180
+
181
+ So the dispatch splits by *shape of the task*, not just by family:
182
+
183
+ - **Batch cross-family judging** (steel-quench Step 0.6 verdict-invariance, auto-decorrelation over many
184
+ items, any fixed-fixture flip count) → **clean completion APIs** (OpenRouter, model pinned by
185
+ *display-name* + `served`-field silent-route check) **+ free local** (a 4090 ollama endpoint). Clean,
186
+ cheap, parseable, per-call pinnable. *Caveat*: a local thinking model needs a large enough output budget
187
+ or it truncates inside `<think>` and emits an empty verdict — a config axis, not a capacity limit.
188
+ - **Interactive / agentic verification** (repo-grounded catching, the divergence audits where cross-family
189
+ disagreement *localizes* a bug) → the **native CLIs** (`codex`, `agy`/Antigravity), where the harness
190
+ earns its overhead.
191
+
192
+ This is **not** a contradiction of the harness-depth thesis — it *is* it. The harness lifts capability
193
+ exactly where judgment + tools + iteration matter; for a one-shot self-contained verdict the loop has no
194
+ work, so its depth becomes pure cost. Pick the naked API for batch scoring, the native harness for agentic
195
+ audit. (Derived 2026-07-04, operator + H1 measurement; the batch-side dual of the vendor-native thesis
196
+ above. The native-harness Gemini path via `agy` is headless-usable again once tool-permission auto-proceed
197
+ is set — see [[reference_agy_model_catalog]] for the pin/permission mechanics.)
198
+
170
199
  **Maintenance-Cost Rule** — a compatibility layer is cheap as a *thin entrypoint*, expensive when it
171
200
  *duplicates canonical knowledge*. The test:
172
201
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrono-meta/fh-gate",
3
- "version": "1.4.49",
3
+ "version": "1.4.50",
4
4
  "description": "FH runtime adapters — run FH governance, skills, and agents via Claude or Codex with machine-parseable gates.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -100,11 +100,20 @@ Local 4090 = **canary tier** (evidence-of, never terminal verdict).
100
100
 
101
101
  ## Step 6 — Degrade ladder (the intelligent scale-down)
102
102
 
103
+ **Consent branch first — declined ≠ degraded** (`[[capability_escalation_consent]]`): if the UAP has
104
+ `sidecar_consent: declined`, do **not** probe/recruit — route straight to **Tier-3 CC-only sub-agent
105
+ verification** (multiple isolated Claude sub-agents, isolation-decorrelation) as a **first-class chosen
106
+ mode**, with an honest *same-family* note but **no "reduced value / degraded" framing** — the user chose
107
+ this floor. `unset` → ask-once at first load-bearing need (accept → proceed; decline → record + this
108
+ branch). Only proceed to the discovery ladder below when consent is `accepted`.
109
+
103
110
  1. frontier cross-family CLI present → recruit it (decorrelated, at-floor) — best.
104
111
  2. only local 4090 present → canary pre-screen + in-session opus governor (canary, not full decorrelation).
105
112
  3. nothing present → in-session same-family + **honest below-floor/same-family note** (residual named).
106
113
 
107
- Env non-determinism (CLI presence varies) → **silent degrade, never hard-fail**.
114
+ Env non-determinism (CLI presence varies) → **silent degrade, never hard-fail**. Distinguish this
115
+ **unavailable-but-wanted** case (consent given, panel down → degrade-with-note; for a *load-bearing corp*
116
+ surface, fail-closed per `local_pmh_context.md`) from the **declined** case above (chosen floor, first-class).
108
117
 
109
118
  ## Step 7 — Output
110
119
 
@@ -117,7 +117,7 @@ Run the audit bash (§Step-Bash) and apply thresholds:
117
117
  | CLAUDE.md | Exceeds 300 lines | Section-by-section compression / move completed sections to archive |
118
118
  | MEMORY.md | Exceeds 180 lines | Check entry count + move `✅ CLOSED` items to archive section |
119
119
  | memory/*.md single file | Exceeds 30K (300 lines) | Suggest splitting accumulated history into separate files |
120
- | SKILL.md (any) | > 300 lines AND no SKILL_detail.md | Propose `/skill-splitter` — governance-semantic split (not compression); compression removes content, splitting routes it on-demand |
120
+ | SKILL.md (any) | > 300 lines AND no SKILL_detail.md | Propose `/salience-splitter` — governance-semantic split (not compression); compression removes content, splitting routes it on-demand |
121
121
 
122
122
  **Frequency**: When explicitly called with `/context-doctor` or auto-invoked at session start when MEMORY.md is detected at 180+ lines.
123
123
 
@@ -259,7 +259,7 @@ context-doctor (token/context) · harness-doctor (structure) · sim-conductor (s
259
259
  |---|---|
260
260
  | Want to also check structure after resolving token waste | `/harness-doctor` |
261
261
  | Want to validate prescription results from external user perspective | `/sim-conductor Area A` |
262
- | SKILL.md diagnosed as over-loaded (> 300 lines, no SKILL_detail.md) | `/skill-splitter` — governance-semantic split |
262
+ | SKILL.md diagnosed as over-loaded (> 300 lines, no SKILL_detail.md) | `/salience-splitter` — governance-semantic split |
263
263
  | All three skills mentioned simultaneously | Three-Doctor Loop circuit activated — diagnosis→prescription→re-diagnosis cycle
264
264
 
265
265
  ## Done When
@@ -278,4 +278,4 @@ context-doctor (token/context) · harness-doctor (structure) · sim-conductor (s
278
278
  **→ Three-Doctor Loop chain (auto-propose after diagnosis):**
279
279
  - Prescription modifies SKILL.md / rules / CLAUDE.md → **propose `/harness-doctor`** re-check after fix (structural integrity)
280
280
  - Prescription addresses user-facing context (onboarding, README, install guides) → **propose `/sim-conductor Area A`** (external user impact validation)
281
- - SKILL.md detected as over-loaded → **auto-propose `/skill-splitter`**: `"I see [skill-name] SKILL.md is [N] lines with no SKILL_detail.md. Want me to run /skill-splitter to do a governance-semantic split?"`
281
+ - SKILL.md detected as over-loaded → **auto-propose `/salience-splitter`**: `"I see [skill-name] SKILL.md is [N] lines with no SKILL_detail.md. Want me to run /salience-splitter to do a governance-semantic split?"`
@@ -73,11 +73,11 @@ wc -l memory/MEMORY.md 2>/dev/null
73
73
  # memory/*.md files exceeding 30K
74
74
  find memory -name "*.md" -size +30k 2>/dev/null | xargs wc -l | sort -rn | head -10
75
75
 
76
- # SKILL.md files > 300 lines with no SKILL_detail.md (skill-splitter candidates)
76
+ # SKILL.md files > 300 lines with no SKILL_detail.md (salience-splitter candidates)
77
77
  find plugins -name "SKILL.md" 2>/dev/null | while read f; do
78
78
  lines=$(wc -l < "$f")
79
79
  detail=$(dirname "$f")/SKILL_detail.md
80
- [ "$lines" -gt 300 ] && [ ! -f "$detail" ] && echo "[skill-splitter candidate] $f ($lines lines)"
80
+ [ "$lines" -gt 300 ] && [ ! -f "$detail" ] && echo "[salience-splitter candidate] $f ($lines lines)"
81
81
  done
82
82
  ```
83
83
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: goal-quench
3
3
  description: >-
4
- Wraps /goal with a tiered safety + orchestration ladder. core (default): a token budget gate (pre-run estimate), mid-run budget thresholds, and an automatic post-run quality verification via pipeline-conductor — closing /goal's two gaps (Haiku evaluates completion, pipeline-conductor evaluates correctness). pro: adds context-doctor token reduction and agent-composer goal decomposition. max: adds plugin-recommender capability-gap fill and cross-ecosystem-synergy-detection pre-validation. The Phase-1 budget verdict auto-recommends the mode. Triggered by "goal with quality gate", "safe goal", "goal-quench", "orchestrate this goal", or before running /goal on high-stakes tasks.
4
+ Wraps /goal with a tiered safety + orchestration ladder. core (default): a token budget gate (pre-run estimate), mid-run budget thresholds, and an automatic post-run quality verification via pipeline-conductor — closing /goal's two gaps (Haiku evaluates completion, pipeline-conductor evaluates correctness). pro: adds context-doctor token reduction and agent-composer goal decomposition. max: adds internal-first capability-gap fill (LOCAL_SKILL_REGISTRY skill-bus scan → plugin-recommender external search → auto_project_mapping map/cluster) and cross-ecosystem-synergy-detection pre-validation. The Phase-1 budget verdict auto-recommends the mode. Triggered by "goal with quality gate", "safe goal", "goal-quench", "orchestrate this goal", or before running /goal on high-stakes tasks.
5
5
  user-invocable: true
6
6
  allowed-tools: ["Read", "Write", "Bash", "Grep"]
7
7
  model: sonnet
@@ -39,7 +39,7 @@ goal-quench is a ladder, not a fixed shape. The default (**core**) is the narrow
39
39
  |---|---|---|---|
40
40
  | **core** (default) | budget gate + mid-run thresholds + post-run quality gate | token-budget-gate, pipeline-conductor --quick | budget GREEN / YELLOW |
41
41
  | **pro** | token-reduction pre-pass + goal decomposition into Waves | + context-doctor, agent-composer | budget ORANGE |
42
- | **max** | capability-gap fill + synergy pre-validation before the run | + plugin-recommender, cross-ecosystem-synergy-detection | budget RED |
42
+ | **max** | **internal-first** capability-gap fill (skill-bus scan → external → map/cluster) + synergy pre-validation | + LOCAL_SKILL_REGISTRY scan, plugin-recommender, cross-ecosystem-synergy-detection, auto_project_mapping | budget RED |
43
43
 
44
44
  Each mode is a **superset** of the one before it — pro does everything core does, plus more. Nothing in core is removed by escalating.
45
45
 
@@ -105,6 +105,7 @@ The clean-streak graduation above governs **unattended-no-review** operation (ru
105
105
  - "goal-quench", before any long /goal session
106
106
  - `/goal-quench --pro`, `/goal-quench --max`, "orchestrate this goal", "decompose this goal", "optimize then run this goal"
107
107
  - "this goal is too big for one run", "find a tool for this goal if FH lacks one" (→ max mode)
108
+ - "assemble capabilities for this project", "develop project X with everything FH has", "what can FH + tools do for this project", "use all of FH's and others' sharp parts on this" (→ max mode, **project-dev capability-assembly** entry — internal skill-bus scan first, then external gap-fill, then map+cluster; token-efficient, non-expert-friendly)
108
109
  - Automatically proposed when user mentions `/goal` on tasks estimated > 15K tokens
109
110
  - Mode is auto-recommended by the Phase-1 budget verdict (GREEN/YELLOW → core, ORANGE → pro, RED → max)
110
111
 
@@ -190,14 +191,16 @@ goal-quench does **not** re-implement agent-composer's gates — its destructive
190
191
 
191
192
  > **Detail**: See `SKILL_detail.md §Queue-Format` — queue file format, plan-ready output text, sidecar `.active` fields — read when writing the queue (Step B) or the sidecar fields (Step D).
192
193
 
193
- ### Step C — plugin-recommender + synergy pre-validation · max only
194
+ ### Step C — capability fill: internal-first, then external · max only
194
195
 
195
- Triggered only when agent-composer Step 0.2 reports a capability **GAP** (`fit_score < 0.5` on a required-weight sub-task):
196
- 1. `plugin-recommender` searches FH + Codex + Claude Code marketplaces for a fitting skill/agent.
197
- 2. For each candidate, `cross-ecosystem-synergy-detection` pre-validates fit + overlap **before anything is installed**.
198
- 3. User decides: install / skip / general-purpose fallback (agent-composer's degraded-composition rule applies — `⚠️ degraded: [role]`).
196
+ Triggered only when agent-composer Step 0.2 reports a capability **GAP** (`fit_score < 0.5` on a required-weight sub-task). Fill order is **internal before external** — honors no-reinvention (use FH's + sibling projects' sharp parts before installing anything), and cheaper **on an internal hit** (a local registry read ≪ an external marketplace search; on an internal *miss* the scan is added overhead before the same external path):
199
197
 
200
- max mode never installs anything silently discovery and synergy-check are surfaced for approval first.
198
+ 1. **Internal scan first.** Run the `LOCAL_SKILL_REGISTRY` scan / Cross-Project Skill Bus (the runtime-root-derived scan under `.claude/registry/`) to check whether an existing **FH meta-skill or a sibling-project skill** already fills the gap. **Trust-gated dispatch** (the fields the registry carries are *consumed*, not just surfaced): an **FH meta-skill** hit → propose directly (Agent + Context Card, no install, token-cheap); a **non-FH sibling** hit → if `trust≠trusted` OR `writes≠read-only` → **ask-tier HITL before dispatch** (never propose-directly — sibling code is an injection surface), else propose. **Degrade direction**: if `.claude/registry/` is missing/malformed, treat as an internal-miss and **fall through to external (step 2), warn** — never silently skip capability fill (that drops the GAP sub-task unnoticed; capability-fill is a reversible surface → advisory-degrade per the Surface-Class Degrade Invariant).
199
+ 2. **External only if internal has nothing.** `plugin-recommender` searches FH + Codex + Claude Code marketplaces + external repos for a fitting skill/agent; `cross-ecosystem-synergy-detection` pre-validates fit + overlap **before anything is installed**.
200
+ 3. User decides: use-internal / install-external / skip / general-purpose fallback (agent-composer's degraded-composition rule applies — `⚠️ degraded: [role]`).
201
+ 4. **Approved external capability → map + cluster (deferred to session close).** An adopted external skill or a newly-relevant sibling project is registered via `auto_project_mapping` — but that write **edits CLAUDE.md's track-mapping table and creates `tracks/{project}/` (an FH-asset change that trips the 4-axis auto-gate and shifts the onboarding is-mapped signal — [[feedback_tracks_dir_is_mapped_signal]])**, so it is **deferred to session close**, not run mid-`/goal`-loop: it passes the 4-axis gate as its own change instead of interrupting the run. The **next** run then discovers the capability internally at step 1 — the loop compounds.
202
+
203
+ max mode never installs or maps anything silently — internal hit, external discovery, synergy-check, and mapping are all surfaced for approval first.
201
204
 
202
205
  ### Step D — scope-driven sidecar configuration · pro + max
203
206
 
@@ -308,8 +311,10 @@ After each goal-quench run, append a calibration entry to `tracks/_meta/goal_que
308
311
  - `token-budget-gate` — Phase 1 cost estimation (all modes)
309
312
  - `context-doctor` — Phase 1.5 Step A token-reduction pre-pass (pro + max)
310
313
  - `agent-composer` — Phase 1.5 Step B goal decomposition into Waves (pro + max)
311
- - `plugin-recommender` — Phase 1.5 Step C capability-gap fill (max only, GAP-triggered)
314
+ - `LOCAL_SKILL_REGISTRY` scan / Cross-Project Skill Bus — Phase 1.5 Step C internal-first scan (max only, GAP-triggered, before external)
315
+ - `plugin-recommender` — Phase 1.5 Step C external capability-gap fill (max only, GAP-triggered, only if no internal hit)
312
316
  - `cross-ecosystem-synergy-detection` — Phase 1.5 Step C pre-validation of discovered candidates (max only)
317
+ - `auto_project_mapping` — Phase 1.5 Step C map/cluster of an adopted external capability (max only, approval-gated, deferred to session close)
313
318
  - `pipeline-conductor` — Phase 3 quality gate (`--quick` for core/pro, `--full` for max; called by Stop hook)
314
319
  - `field-harvest` — capture calibration data as reusable pattern after 10 runs
315
320
 
@@ -321,7 +326,9 @@ After each goal-quench run, append a calibration entry to `tracks/_meta/goal_que
321
326
  Phase 1: token-budget-gate verdict output + mode resolved (core default, or pro/max via budget verdict / explicit flag)
322
327
  + .claude/goal-quench.active written (with mode: field) + thresholds injected
323
328
  + If pro/max: Phase 1.5 ran — context-doctor pre-pass + agent-composer plan;
324
- max additionally: GAP-triggered plugin-recommender + cross-ecosystem-synergy-detection pre-validation
329
+ max additionally: GAP-triggered internal LOCAL_SKILL_REGISTRY scan FIRST (trust-gated dispatch);
330
+ plugin-recommender + cross-ecosystem-synergy pre-validation ONLY if no internal hit;
331
+ auto_project_mapping map/cluster deferred to session close only if an external capability was adopted (each surfaced for approval)
325
332
  + Phase 3 (on next response after /goal): .pending file detected + pipeline-conductor run
326
333
  (--quick for core/pro, --full for max)
327
334
  + Verification verdict output (CLEAN/PENDING/BLOCKED/ESCALATE)
@@ -76,7 +76,7 @@ confirms the gap*, never a verdict the report emits on its own; surface each gap
76
76
  | CLAUDE.md 100~200 lines | S-tier warning |
77
77
  | CLAUDE.md 200+ lines | M-tier — separation or reduction needed |
78
78
  | 15+ `##` sections in CLAUDE.md | S-tier warning |
79
- | SKILL.md > 300 lines AND no `SKILL_detail.md` | S-tier — propose `/skill-splitter` (governance-semantic split, not compression) |
79
+ | SKILL.md > 300 lines AND no `SKILL_detail.md` | S-tier — propose `/salience-splitter` (governance-semantic split, not compression) |
80
80
  | Rules files unreferenced in CLAUDE.md | R-tier |
81
81
  | weekly_audit 14~30 days elapsed | S-tier |
82
82
  | weekly_audit 30+ days elapsed | M-tier |
@@ -318,7 +318,7 @@ Verdict: PASS (M-tier 0, "Structure healthy") | CONDITIONAL_PASS (S/R remain, no
318
318
  **Three-Doctor Loop chain** (auto-propose after prescription report):
319
319
  - M-tier + context/token waste → propose `/context-doctor`
320
320
  - M-tier + user-facing behavior changes → propose `/sim-conductor Area A`
321
- - SKILL.md S-tier (> 300 lines, no SKILL_detail.md) → auto-propose `/skill-splitter`: `"I see [skill] SKILL.md is [N] lines with no SKILL_detail.md. Want me to run /skill-splitter?"`
321
+ - SKILL.md S-tier (> 300 lines, no SKILL_detail.md) → auto-propose `/salience-splitter`: `"I see [skill] SKILL.md is [N] lines with no SKILL_detail.md. Want me to run /salience-splitter?"`
322
322
  - Both → propose full Three-Doctor Loop: context-doctor → sim-conductor Area A
323
323
 
324
324
  ---
@@ -137,7 +137,7 @@ FAIL routing: First FAIL → 1 re-synthesis allowed. FAIL after re-synthesis →
137
137
 
138
138
  ### Step 6 — Curator Lifecycle Review
139
139
 
140
- **6-1 SKILL.md Lifecycle**: 30+ day unused → [STALE] candidate. `pinned: true` → never touch. ≥70% overlap → merge candidate suggestion. **> 300 lines AND no `SKILL_detail.md`** → propose `/skill-splitter` (governance-semantic split — not compression; the grew-through-harvest pattern is a natural split trigger).
140
+ **6-1 SKILL.md Lifecycle**: 30+ day unused → [STALE] candidate. `pinned: true` → never touch. ≥70% overlap → merge candidate suggestion. **> 300 lines AND no `SKILL_detail.md`** → propose `/salience-splitter` (governance-semantic split — not compression; the grew-through-harvest pattern is a natural split trigger).
141
141
 
142
142
  **6-1-a Archive-candidate auto-tag**: When 0 invocations in 30 days detected (cross-check `tracks/_meta/skill_usage.md`), auto-append `#archive-candidate` tag to that skill's CATALOG.md entry. No file deletion — tag only. User reviews tagged entries at next session start.
143
143
 
@@ -139,7 +139,9 @@ Y (add integration plan items to Step 1) / N (add-only, keep existing rules) / S
139
139
 
140
140
  **[Prerequisite] install-doctor conflict diagnosis (only in environments without install history)**: if `~/.cc_sentinels/{project-name}_wizard_done` doesn't exist (first install), call `/install-doctor --plugin fh-meta` first. CONFLICT/WARNING items → add ❗ markers to Step 2 proposal list. Items the doctor already diagnosed (`FH plugin install` · `zshrc hook` · `.claudeignore`) → map results directly, skip re-diagnosis; all other items → check directly.
141
141
 
142
- Auto-check each item as PASS / MISS / FAIL. Check items: `.claudeignore` · `local_fh_context.md` · `zshrc hook` · `weekly_audit` freshness · `sentinel` setup · FH plugin install · `.git/info/exclude` · MCP plugin · `deep-insight` plugin (optional) · `fh_env_context.jsonc` · `phantom-gate` (Python + AI-output projects only) · domain pattern pack (optional, none ship by default) · local-LLM offload (optional — surface ONLY if the Step 0 bash emitted the literal line `Local LLM runtime: detected`; absent that line, this item does not exist).
142
+ Auto-check each item as PASS / MISS / FAIL. Check items: `.claudeignore` · `local_fh_context.md` · `zshrc hook` · `weekly_audit` freshness · `sentinel` setup · FH plugin install · `.git/info/exclude` · MCP plugin · `deep-insight` plugin (optional) · `fh_env_context.jsonc` · `phantom-gate` (Python + AI-output projects only) · domain pattern pack (optional, none ship by default) · local-LLM offload (optional — surface ONLY if the Step 0 bash emitted the literal line `Local LLM runtime: detected`; absent that line, this item does not exist) · **`env-delta SessionStart hook`** (Mode D — `scripts/fh_env_delta_scan.sh` registered in SessionStart; MISS if absent when the hub has sibling repos) · **`capability-escalation consent`** (per `[[capability_escalation_consent]]` — negotiate BOTH axes at onboarding so no later escalation is a surprise: *"Allow cross-family sidecars (external billing) for load-bearing verification?"* → `sidecar_consent`, and *"Allow Sonnet→Opus floor-up on depth-heavy turns (~3–5× cost)? Decline = stay at the Sonnet floor, asked per-occasion instead."* → `floorup_consent`; record both to the UAP. MISS if the UAP lacks either field — a skipped user is asked-once at first need, never sprung).
143
+
144
+ **env-delta detection (Mode D — the mechanical floor for claim ② auto-trigger)**: FH's "undeployed-asset discovery + auto-mapping" (CLAUDE.md claim ②) previously fired **only on explicit invocation** — a new sibling repo pulled, or a task-first session in an unmapped project, was **not** self-detected (the onboarding menu is suppressed on task-first entry by the metadata-is-not-intent / task-first guards, which are load-bearing and must stay). The `scripts/fh_env_delta_scan.sh` SessionStart hook (sibling of `fh_session_load.sh`) closes this **mechanically**: it scans the projects root for git repos that are neither mapped (`tracks/{name}/`) nor wizard-done nor skip-sentineled, and emits a **one-line PROPOSAL** into turn-0 context, firing regardless of task-first entry. It **proposes only** — mapping/install stays HITL; a skipped repo is recorded via a `{name}_mapping_skipped` sentinel so it never re-nags. This is the mechanical anchor over the prose/salience layer (three-family audit 2026-07-06 rated ② PARTIAL/THEATER precisely because the auto-trigger lived only in prose).
143
145
 
144
146
  **Local-LLM offload (conditional, recommend-only)**: when Step 0 detected a local LLM runtime (Ollama / LM Studio), surface one optional item — route to `/plugin-recommender` for local-model offload tooling. FH recommends, never rebuilds (no-reinvention). Two complementary offload shapes the user picks per workload: **input-side context routing** (a small local model returns line ranges, so the cloud model receives only the dense slices instead of whole files) and **output-side generation delegation** (the local model generates and self-reviews code while the frontier model decomposes and validates). The benefit is tier-dependent — largest in headless/scripted pipelines and on weaker cloud tiers; an interactive session already triages via targeted reads. Local models suit **bounded, well-specified** work (triage, codebase explanation, instructed maintenance), not long-horizon autonomous tasks where small models loop or hallucinate — so the frontier model keeps decomposition and validation. Skip silently when no local runtime is present.
145
147
 
@@ -103,38 +103,16 @@ literal private token.
103
103
 
104
104
  ## Step 3. Scan
105
105
 
106
- For each pattern in Step 1, grep the tracked set, then drop allowlisted hits.
107
-
108
- ```bash
109
- cd "$REPO_PATH" || exit 1
110
- # Build the tracked-file list once.
111
- git ls-files > /tmp/_psa_tracked.txt
112
-
113
- # Load your real patterns from the gitignored source (one "severity<TAB>regex" per line).
114
- PATTERN_SRC="${PSA_PATTERNS:-.claude/rules/.public-surface-patterns}"
115
- # Absent file ≠ CLEAN. An absent file is unconfigured (silent-failure risk); an EMPTY file is an
116
- # explicit "no tokens to protect" → CLEAN. Distinguish the two.
117
- [ -e "$PATTERN_SRC" ] || { echo "⚪ NOT CONFIGURED: no pattern source at $PATTERN_SRC. Create it (empty = explicit CLEAN) before trusting any verdict. Not scanning."; exit 2; }
118
-
119
- # One grep pass per pattern row; the regex comes from the file, never hardcoded here.
120
- while IFS=$'\t' read -r severity regex; do
121
- [ -z "$regex" ] && continue
122
- grep -nIE "$regex" $(cat /tmp/_psa_tracked.txt) 2>/dev/null | sed "s/^/[$severity] /"
123
- done < "$PATTERN_SRC"
124
- ```
125
-
126
- For each pattern, run `grep -nIE "<regex>" $(git ls-files)`:
127
- - `-n` → line numbers (required for `file:line` output)
128
- - `-I` → skip binary files
129
- - `-E` → extended regex (alternation in the pattern table)
130
-
131
- Then remove any hit whose `file` + matched `token` is on the Step 2 allowlist. Do this for **every**
106
+ For each pattern in Step 1, grep the tracked set, then drop allowlisted hits. Do this for **every**
132
107
  pattern row before producing the report — do not stop at the first HIT.
133
108
 
134
- **Binary / generated carve-out**: `-I` already skips binaries. Additionally note (do not auto-suppress)
135
- hits inside generated artifacts (e.g. `paper/*.html` exported from a private source) — these are real
136
- leaks on the public surface and must be reported, but the fix is "regenerate from a sanitized source",
137
- not "edit the HTML by hand". Flag them with a `(generated artifact)` note.
109
+ **Binary / generated carve-out**: skip binaries. Additionally note (do not auto-suppress) hits inside
110
+ generated artifacts (e.g. `paper/*.html` exported from a private source) — these are real leaks on the
111
+ public surface and must be reported, but the fix is "regenerate from a sanitized source," not "edit the
112
+ HTML by hand." Flag them with a `(generated artifact)` note.
113
+
114
+ > **Detail**: See `SKILL_detail.md §Step3-Scan-Script` — the grep-per-pattern bash implementation,
115
+ > flag reference (`-n`/`-I`/`-E`) — read when executing this step.
138
116
 
139
117
  ---
140
118
 
@@ -151,23 +129,13 @@ reports):
151
129
  `changeme`, `REDACTED`, `xxxx`, AWS-doc keys like `AKIAIOSFODNN7EXAMPLE`). A high-entropy *example* is
152
130
  not a secret.
153
131
 
154
- ```bash
155
- # FP-hygiene tests the MATCHED TOKEN only — never the whole line. A line-level `grep -v` would
156
- # suppress a real leak that merely *mentions* an example (e.g. `user=<realname> # see EXAMPLE.md`),
157
- # violating PSA's "allowlist tight" rule. So extract the matched span per hit and drop it only when
158
- # the span is *entirely* a placeholder/example (anchored ^…$).
159
- PLACEHOLDER='^(<[a-z0-9_-]+>|\{project\}|EXAMPLE|dummy|changeme|REDACTED|xxxx)$'
160
- grep -nIE "$regex" $(cat /tmp/_psa_tracked.txt) 2>/dev/null | while IFS= read -r hit; do
161
- tok=$(printf '%s' "$hit" | grep -oiE "$regex" | head -1)
162
- printf '%s' "$tok" | grep -qiE "$PLACEHOLDER" && continue # token IS a placeholder → drop
163
- printf '%s\n' "$hit"
164
- done
165
- ```
166
-
167
132
  This differs from the Step 2 allowlist: Step 2 suppresses by **file::token legitimacy**, Step 3b by
168
133
  **token value-shape**. Both run — Step 2 then Step 3b. Keep it tight (PSA's "allowlist tight" rule): if a
169
134
  token only *contains* an example substring but is otherwise a real private value, it still reports.
170
135
 
136
+ > **Detail**: See `SKILL_detail.md §Step3b-FP-Hygiene-Script` — the token-shape-only extraction bash
137
+ > implementation (never line-level) — read when executing this step.
138
+
171
139
  ---
172
140
 
173
141
  ## Step 3c. Ignore-Verification — the gitignore-mistake safeguard (root-cause, runs before Step 4)
@@ -178,39 +146,14 @@ tracked leak. For each expected-private path, `git check-ignore -v` reports whet
178
146
  by which layer** (committed `.gitignore` · local `.git/info/exclude` · global `core.excludesFile`). A
179
147
  path that resolves to no ignore rule is a MISS — surface it before it is ever `git add`ed.
180
148
 
181
- ```bash
182
- # Expected-private set = conventional FH local-only files, EXTENDED with any `# private-path: <path>`
183
- # lines the operator added to the gitignored pattern source (self-extends per repo — not a frozen
184
- # operator snapshot). Built one-path-per-line + while-read so it is portable across bash AND zsh
185
- # (zsh does not word-split an unquoted variable, so `for f in $VAR` would break). A non-existent file
186
- # is skipped; an all-absent set emits n/a, never a silent pass.
187
- present=$({ printf '%s\n' CLAUDE.local.md .claude/rules/.public-surface-patterns \
188
- .claude/rules/local_fh_context.md tracks/_meta/user_adaptation_profile.md
189
- grep -E '^# private-path:' .claude/rules/.public-surface-patterns 2>/dev/null \
190
- | sed -E 's/^# private-path:[[:space:]]*//'; } \
191
- | awk 'NF' | sort -u | while IFS= read -r f; do [ -e "$f" ] && printf '%s\n' "$f"; done)
192
- [ -z "$present" ] && echo "n/a (no expected-private files present in this repo — add '# private-path:' lines to the pattern source if any exist)"
193
- printf '%s\n' "$present" | while IFS= read -r f; do
194
- [ -z "$f" ] && continue
195
- # Tracked status is tested FIRST: a file can match an ignore rule yet still be force-added
196
- # (`git add -f`) — the exact ignored-but-committed mechanism behind the PR #109 leak. Tracked wins,
197
- # so an ignored-but-committed file reports TRACKED (not a false-clean OK).
198
- if git ls-files --error-unmatch "$f" >/dev/null 2>&1; then
199
- echo "TRACKED $f (already committed — Step 3 scans its contents; un-track if it must be private: git rm --cached)"
200
- elif rule=$(git check-ignore -v "$f" 2>/dev/null); then
201
- echo "OK $f → ignored by [$rule]"
202
- else
203
- echo "MISS $f (exists, NOT ignored, NOT tracked — one 'git add .' from a leak; add an ignore rule)"
204
- fi
205
- done
206
- ```
207
-
208
149
  - **OK** — ignored; the report names which layer covers it (operator-private files should resolve to
209
150
  `.git/info/exclude` or `.gitignore`, never end up tracked).
210
151
  - **MISS** — exists but no ignore rule covers it → counts as **🟠 MED** in the Step 4 verdict (a latent
211
152
  leak, not yet a breach).
212
153
  - **TRACKED** — already committed: Step 3 scans its *contents*; this also flags it for un-tracking if it
213
- was meant to be private.
154
+ was meant to be private. Tracked status is tested **before** ignore status — a file can match an
155
+ ignore rule yet still be force-added (`git add -f`), the exact ignored-but-committed mechanism behind
156
+ the PR #109 leak, so TRACKED must win over a false-clean OK.
214
157
 
215
158
  Why this is the safeguard for **gitignore mistakes** (a wrong assumption about what is ignored):
216
159
  `.gitignore` is committed/shared, `.git/info/exclude` is local/personal, and a global `core.excludesFile`
@@ -218,6 +161,10 @@ ignores across all repos — `git check-ignore -v` is the one command that says
218
161
  applies, so an "I thought it was ignored" error surfaces here instead of in a public PR (the PR #109
219
162
  class of leak). Diagnostic-only: this step never writes — it reports, the operator adds the ignore rule.
220
163
 
164
+ > **Detail**: See `SKILL_detail.md §Step3c-Ignore-Verification-Script` — the expected-private-path
165
+ > enumeration + `git check-ignore`/`git ls-files --error-unmatch` bash implementation, bash/zsh
166
+ > portability note — read when executing this step.
167
+
221
168
  ---
222
169
 
223
170
  ## Step 4. Report
@@ -0,0 +1,150 @@
1
+ ---
2
+ name: public-surface-audit-detail
3
+ description: On-demand execution detail for public-surface-audit — scan scripts, report/JSON templates, provenance.
4
+ load: on-demand
5
+ ---
6
+
7
+ ## §Step3-Scan-Script
8
+
9
+ ```bash
10
+ cd "$REPO_PATH" || exit 1
11
+ # Build the tracked-file list once.
12
+ git ls-files > /tmp/_psa_tracked.txt
13
+
14
+ # Load your real patterns from the gitignored source (one "severity<TAB>regex" per line).
15
+ PATTERN_SRC="${PSA_PATTERNS:-.claude/rules/.public-surface-patterns}"
16
+ # Absent file ≠ CLEAN. An absent file is unconfigured (silent-failure risk); an EMPTY file is an
17
+ # explicit "no tokens to protect" → CLEAN. Distinguish the two.
18
+ [ -e "$PATTERN_SRC" ] || { echo "⚪ NOT CONFIGURED: no pattern source at $PATTERN_SRC. Create it (empty = explicit CLEAN) before trusting any verdict. Not scanning."; exit 2; }
19
+
20
+ # One grep pass per pattern row; the regex comes from the file, never hardcoded here.
21
+ while IFS=$'\t' read -r severity regex; do
22
+ [ -z "$regex" ] && continue
23
+ grep -nIE "$regex" $(cat /tmp/_psa_tracked.txt) 2>/dev/null | sed "s/^/[$severity] /"
24
+ done < "$PATTERN_SRC"
25
+ ```
26
+
27
+ For each pattern, run `grep -nIE "<regex>" $(git ls-files)`:
28
+ - `-n` → line numbers (required for `file:line` output)
29
+ - `-I` → skip binary files
30
+ - `-E` → extended regex (alternation in the pattern table)
31
+
32
+ Then remove any hit whose `file` + matched `token` is on the Step 2 allowlist. Do this for **every**
33
+ pattern row before producing the report — do not stop at the first HIT.
34
+
35
+ **Binary / generated carve-out**: `-I` already skips binaries. Additionally note (do not auto-suppress)
36
+ hits inside generated artifacts (e.g. `paper/*.html` exported from a private source) — these are real
37
+ leaks on the public surface and must be reported, but the fix is "regenerate from a sanitized source",
38
+ not "edit the HTML by hand". Flag them with a `(generated artifact)` note.
39
+
40
+ ---
41
+
42
+ ## §Step3b-FP-Hygiene-Script
43
+
44
+ ```bash
45
+ # FP-hygiene tests the MATCHED TOKEN only — never the whole line. A line-level `grep -v` would
46
+ # suppress a real leak that merely *mentions* an example (e.g. `user=<realname> # see EXAMPLE.md`),
47
+ # violating PSA's "allowlist tight" rule. So extract the matched span per hit and drop it only when
48
+ # the span is *entirely* a placeholder/example (anchored ^…$).
49
+ PLACEHOLDER='^(<[a-z0-9_-]+>|\{project\}|EXAMPLE|dummy|changeme|REDACTED|xxxx)$'
50
+ grep -nIE "$regex" $(cat /tmp/_psa_tracked.txt) 2>/dev/null | while IFS= read -r hit; do
51
+ tok=$(printf '%s' "$hit" | grep -oiE "$regex" | head -1)
52
+ printf '%s' "$tok" | grep -qiE "$PLACEHOLDER" && continue # token IS a placeholder → drop
53
+ printf '%s\n' "$hit"
54
+ done
55
+ ```
56
+
57
+ This differs from the Step 2 allowlist: Step 2 suppresses by **file::token legitimacy**, Step 3b by
58
+ **token value-shape**. Both run — Step 2 then Step 3b. Keep it tight (PSA's "allowlist tight" rule): if a
59
+ token only *contains* an example substring but is otherwise a real private value, it still reports.
60
+
61
+ ---
62
+
63
+ ## §Step3c-Ignore-Verification-Script
64
+
65
+ ```bash
66
+ # Expected-private set = conventional FH local-only files, EXTENDED with any `# private-path: <path>`
67
+ # lines the operator added to the gitignored pattern source (self-extends per repo — not a frozen
68
+ # operator snapshot). Built one-path-per-line + while-read so it is portable across bash AND zsh
69
+ # (zsh does not word-split an unquoted variable, so `for f in $VAR` would break). A non-existent file
70
+ # is skipped; an all-absent set emits n/a, never a silent pass.
71
+ present=$({ printf '%s\n' CLAUDE.local.md .claude/rules/.public-surface-patterns \
72
+ .claude/rules/local_fh_context.md tracks/_meta/user_adaptation_profile.md
73
+ grep -E '^# private-path:' .claude/rules/.public-surface-patterns 2>/dev/null \
74
+ | sed -E 's/^# private-path:[[:space:]]*//'; } \
75
+ | awk 'NF' | sort -u | while IFS= read -r f; do [ -e "$f" ] && printf '%s\n' "$f"; done)
76
+ [ -z "$present" ] && echo "n/a (no expected-private files present in this repo — add '# private-path:' lines to the pattern source if any exist)"
77
+ printf '%s\n' "$present" | while IFS= read -r f; do
78
+ [ -z "$f" ] && continue
79
+ # Tracked status is tested FIRST: a file can match an ignore rule yet still be force-added
80
+ # (`git add -f`) — the exact ignored-but-committed mechanism behind the PR #109 leak. Tracked wins,
81
+ # so an ignored-but-committed file reports TRACKED (not a false-clean OK).
82
+ if git ls-files --error-unmatch "$f" >/dev/null 2>&1; then
83
+ echo "TRACKED $f (already committed — Step 3 scans its contents; un-track if it must be private: git rm --cached)"
84
+ elif rule=$(git check-ignore -v "$f" 2>/dev/null); then
85
+ echo "OK $f → ignored by [$rule]"
86
+ else
87
+ echo "MISS $f (exists, NOT ignored, NOT tracked — one 'git add .' from a leak; add an ignore rule)"
88
+ fi
89
+ done
90
+ ```
91
+
92
+ Why this is the safeguard for **gitignore mistakes** (a wrong assumption about what is ignored):
93
+ `.gitignore` is committed/shared, `.git/info/exclude` is local/personal, and a global `core.excludesFile`
94
+ ignores across all repos — `git check-ignore -v` is the one command that says *which* rule (if any)
95
+ applies, so an "I thought it was ignored" error surfaces here instead of in a public PR (the PR #109
96
+ class of leak). Diagnostic-only: this step never writes — it reports, the operator adds the ignore rule.
97
+
98
+ ---
99
+
100
+ ## §Report-Template
101
+
102
+ ```
103
+ public-surface-audit — Operator-Private Token Scan
104
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
105
+ Target: {REPO_PATH} | Tracked files scanned: {N}
106
+
107
+ 🔴 HIGH ({count})
108
+ {file}:{line} → {matched token} [class: username | company asset]
109
+ 🟠 MED ({count})
110
+ {file}:{line} → {matched token} [class: absolute home path | ignore-MISS (Step 3c)]
111
+ 🟡 LOW ({count})
112
+ {file}:{line} → {matched token} [class: companion-store | private wiring]
113
+
114
+ Allowlist-suppressed: {count} hit(s) (legitimate references — not leaks)
115
+
116
+ Verdict:
117
+ ⚪ NOT CONFIGURED — pattern source absent (nothing scanned — NOT a clean result; set up first)
118
+ 🟢 CLEAN — pattern source present (incl. empty), 0 HIGH + 0 MED + 0 LOW (after allowlist)
119
+ 🟡 REVIEW — 0 HIGH + 0 MED, LOW-only (drift, not a breach)
120
+ 🔴 LEAK — 1+ HIGH or 1+ MED (block publish / fix before commit)
121
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
122
+ ```
123
+
124
+ ---
125
+
126
+ ## §JSON-Schema
127
+
128
+ ```json
129
+ {
130
+ "target": "{REPO_PATH}",
131
+ "tracked_files": 0,
132
+ "findings": [
133
+ {"file": "path", "line": 42, "token": "<matched>", "severity": "HIGH", "class": "username"}
134
+ ],
135
+ "counts": {"HIGH": 0, "MED": 0, "LOW": 0, "suppressed": 0},
136
+ "verdict": "CLEAN"
137
+ }
138
+ ```
139
+
140
+ ---
141
+
142
+ ## §Sister-Asset-Provenance
143
+
144
+ Step 3b (FP hygiene) and Step 5 (`--json`) were imported from **garrytan/gstack** `gstack-redact`
145
+ (`lib/redact-engine.ts`) during a hands-on sister-asset cross-audit (2026-06-06; see
146
+ `tracks/_audit/session_2026_06_06_gstack_sister_handson.md`). They are adapted to PSA's operator-IP
147
+ ontology — `gstack-redact`'s generic secret/PII classes (AWS / PEM / JWT / hostname) stay out of PSA's
148
+ scope (orthogonal coverage: PSA = operator-IP leak, redact = generic secret). The reverse direction
149
+ (PSA's operator private-codename + bare-username classes, which `gstack-redact` structurally cannot
150
+ detect) is a candidate contribution back to gstack.
@@ -1,15 +1,25 @@
1
1
  ---
2
- name: skill-splitter
3
- description: Splits an over-loaded SKILL.md into always-loaded (SKILL.md) + on-demand (SKILL_detail.md) layers using a governance-semantic criterion not length, but when the content is needed. Connects the two files with imperative pointers. Based on paper §9.5 Protocol-Priority Split pattern. Diagnoses, classifies, splits, and verifies in one pass.
2
+ name: salience-splitter
3
+ description: Splits an over-loaded always-loaded context asset — a SKILL.md, CLAUDE.md, or memory index — into a lean always-loaded layer + an on-demand layer, using a governance-semantic criterion (not length, but when the content is needed), connected by imperative pointers. Based on paper §9.5 Protocol-Priority Split pattern. Diagnoses, classifies, splits, and verifies in one pass. Renamed from skill-splitter (old name still routes here).
4
4
  user-invocable: true
5
5
  allowed-tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
6
6
  model: sonnet
7
7
  ---
8
8
 
9
- # skill-splitter — SKILL.md Governance-Semantic Split
9
+ # salience-splitter — Governance-Semantic Context Split
10
10
 
11
- > A SKILL.md that does everything in one file is not simple — it is unscoped.
12
- > The goal is two files each smaller than the original, not one file and its appendix.
11
+ > **Renamed from `skill-splitter` (2026-07-05).** Old-name references still route here. The rename reflects
12
+ > the generalized scope: the split criterion applies to **any always-loaded context asset** a SKILL.md,
13
+ > a CLAUDE.md, or a memory index — not only skills. The label now names the substance (salience-tiering of
14
+ > always-loaded context), not one instance of it. Dogfood: applied to a memory index 2026-07-05.
15
+
16
+ > An always-loaded asset that holds everything in one layer is not simple — it is unscoped.
17
+ > The goal is a lean always-loaded layer + an on-demand layer, not one file and its appendix.
18
+
19
+ **Scope (all three share one criterion — salience: what must be in attention every load):**
20
+ - **SKILL.md** → always-loaded SKILL.md + on-demand `SKILL_detail.md`
21
+ - **CLAUDE.md** → lean rules + on-demand detail docs (imperative `> **Detail**: See …` pointers)
22
+ - **memory index** → hot `MEMORY.md` + on-demand `MEMORY_archive.md` (cold/closed/superseded entries)
13
23
 
14
24
  ## Trigger Phrases
15
25
 
@@ -19,7 +29,7 @@ model: sonnet
19
29
  | "context-doctor flagged this skill", "SKILL.md is bloated" | Post-diagnosis split |
20
30
  | "I can't see the key parts", "too much detail in the skill file" | Readability problem |
21
31
  | "separate the bash from the logic", "move the templates out" | Structural refactor request |
22
- | `/skill-splitter` | Explicit invocation |
32
+ | `/salience-splitter` | Explicit invocation |
23
33
 
24
34
  ---
25
35
 
@@ -63,7 +73,7 @@ Step 4 — Verify
63
73
 
64
74
  > **Detail**: See `SKILL_detail.md §Verification-Checklist` — pre-commit checklist table (8 checks) — read when running Step 4 verification.
65
75
 
66
- > **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.
76
+ > **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.
67
77
 
68
78
  > **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.
69
79
 
@@ -76,7 +86,7 @@ Pointers must be **imperative** (not advisory). The difference:
76
86
  | Form | Risk |
77
87
  |---|---|
78
88
  | Advisory: `"see SKILL_detail.md for details"` | Consumer agent may skip |
79
- | **Imperative**: `"> **Detail**: See \`SKILL_detail.md §SectionName\` — [what's there] — read when [specific condition]."` | Consumer agent loads on trigger |
89
+ | **Imperative**: `"> **Detail**: See \`SKILL_detail.md §<SectionName>\` — [what's there] — read when [specific condition]."` | Consumer agent loads on trigger |
80
90
 
81
91
  Every removed section must have exactly one imperative pointer at the point of removal in SKILL.md.
82
92
 
@@ -113,7 +123,7 @@ Run on a SKILL.md when **any one** of:
113
123
  ```
114
124
  Step 1 classification table produced
115
125
  + SKILL.md trimmed: triggers · principles · step overview · decision tables · Done When retained
116
- + SKILL.md has imperative pointer for every removed section (> **Detail**: See SKILL_detail.md §X)
126
+ + SKILL.md has imperative pointer for every removed section (> **Detail**: See SKILL_detail.md §<X>)
117
127
  + SKILL_detail.md created: ## §SectionName header for every pointer in SKILL.md
118
128
  + phantom-quench: 0 phantoms (all §pointers resolve)
119
129
  → Fallback (skill unavailable): run §Verification-Checklist manually from SKILL_detail.md
@@ -1,10 +1,10 @@
1
1
  ---
2
- name: skill-splitter-detail
3
- description: Detail reference for skill-splitter — content classification algorithm, pointer format variants, verification checklist. Load when executing a specific step.
2
+ name: salience-splitter-detail
3
+ description: Detail reference for salience-splitter — content classification algorithm, pointer format variants, verification checklist. Load when executing a specific step.
4
4
  load: on-demand
5
5
  ---
6
6
 
7
- # skill-splitter — Detail Reference
7
+ # salience-splitter — Detail Reference
8
8
 
9
9
  > Load when executing a specific step. SKILL.md contains the core principle, step overview, pointer format requirement, and Done When.
10
10
 
@@ -70,13 +70,13 @@ Behavioral rules always pass this test (even if rarely triggered, the consumer n
70
70
  ### Standard pointer (single section reference)
71
71
 
72
72
  ```markdown
73
- > **Detail**: See `SKILL_detail.md §SectionName` — [one-line description of what's there] — read when [specific condition that triggers need].
73
+ > **Detail**: See `SKILL_detail.md §<SectionName>` — [one-line description of what's there] — read when [specific condition that triggers need].
74
74
  ```
75
75
 
76
76
  ### Multi-item pointer (several related sections)
77
77
 
78
78
  ```markdown
79
- > **Detail**: See `SKILL_detail.md §SectionName-A` (bash scripts) · SectionName-B` (format templates) — read when executing this step.
79
+ > **Detail**: See `SKILL_detail.md §<SectionName-A>` (bash scripts) · `§<SectionName-B>` (format templates) — read when executing this step.
80
80
  ```
81
81
 
82
82
  ### Pointer placement rules
@@ -96,7 +96,7 @@ Advisory (risky — consumer may skip):
96
96
 
97
97
  Imperative (required form):
98
98
  ```
99
- "> **Detail**: See `SKILL_detail.md §Step6-Detail` — bash for STALE detection, memory scan, skill usage leaderboard — read when executing Step 6."
99
+ "> **Detail**: See `SKILL_detail.md §<Step6-Detail>` — bash for STALE detection, memory scan, skill usage leaderboard — read when executing Step 6."
100
100
  ```
101
101
 
102
102
  The imperative form includes: