@chrono-meta/fh-gate 1.4.70 → 1.4.72
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/.claude-plugin/marketplace.json +2 -2
- package/CATALOG.md +39 -1
- package/CLAUDE.md +1 -1
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/knowledge/shared/harness-core/loop_engineering.md +27 -1
- package/package.json +1 -1
- package/plugins/fh-commons/.claude-plugin/plugin.json +1 -1
- package/plugins/fh-meta/.claude-plugin/plugin.json +2 -2
- package/plugins/fh-meta/skills/dialogue-harvest/SKILL.md +79 -0
- package/plugins/fh-meta/skills/frontier-digest/SKILL_detail.md +29 -6
- package/plugins/fh-meta/skills/salience-splitter/SKILL.md +1 -1
- package/scripts/fh-gate.sh +76 -2
- package/scripts/test_fh_gate_regressions.sh +46 -2
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
13
13
|
"name": "fh-meta",
|
|
14
|
-
"version": "1.4.
|
|
14
|
+
"version": "1.4.72",
|
|
15
15
|
"description": "Hub meta-operations toolkit — 35 skills + 7 agents. New in 1.4.53: `fh-codex-doctor` (npm bin) — Codex adapter drift scanner; reads the documented M1/M2/M3 skill tier map + skill/agent source and reports codex-native/adapter-required/claude-native/unclassified per unit, wired into `npm test`/`prepublishOnly` (fail-closed on unclassified Claude-native primitives). New in 1.4.49: steel-quench gains Step 0.6 Verdict-Invariance Probe (groundedness axis — a load-bearing judged gate's verdict must track behavior, not rubric phrasing; measured flip-count over cross-family paraphrases; arXiv:2605.06161 Policy Invariance anchor); multi_model_sidecar_strategy §Vendor-native harness (a model is strongest in its own vendor CLI — Claude/CC, GPT/codex, Gemini/Antigravity; a universal router degrades all of them, so it stays an autocomplete/QA sidecar, never orchestration); predelete_check.sh fail-closed rewrite; memory-hygiene A-TMA anchor. New in 1.4.48: phantom-quench + steel-quench gain external frontier anchors (arXiv:2607.02052 package-hallucination; arXiv:2607.02057 prompt-coverage-adequacy); README model-flat claim reframed from a per-release point-curve to structural invariants (operation flattens across tiers; depth tier-order fixed within a generation). New in 1.4.47: onboarding step ① surfaces the Mode D companion-store session-start load in the auto-read salience anchor (previously only in the local binding + rules, so a greeting could skip the load). New in 1.4.46: context-doctor command-output axis (route to rtk/proxy for verbose CLI stdout, complementing .claudeignore; risk-gated to token-scarce envs). New in 1.4.41: context-doctor 2026 trigger vocab (context engineering/rot/collapse) + phantom-citation hardening; hub measurement-integrity-checklist (cross-model measurement pre-flight: display-name pin/reps≥3/discriminating probe). New in 1.4.40: install-wizard queryable-wiki scaffold (INDEX + session-start read + R/W/C ingest). New in 1.4.39: auto-decorrelation (cross-family verifier sidecar recruitment) + video-ingest (capability-routed video ingestion). New in 1.4.x: verify-axis check-class taxonomy (mandatory-pass/measured/judged), no-reinvention Tier-0 inventory, 7-class failure taxonomy, Destructive-Op Gate, Wave-T (Temper), tier-floor governance, Mode D Model Notice, FC consent lane, default-Sonnet guidance. New in 1.3.0: public-surface-audit, field-harvest Mode B auto-trigger, 4-axis gate scope ext. Validated cross-CLI: Claude Code, Codex, Gemini.",
|
|
16
16
|
"source": "./plugins/fh-meta"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
"name": "fh-commons",
|
|
20
|
-
"version": "1.4.
|
|
20
|
+
"version": "1.4.72",
|
|
21
21
|
"description": "Project-agnostic utility skills — 4 skills (convergence-loop · deliberation · mcp-circuit-breaker · token-budget-gate) + 1 agent (quench-challenger). Domain-independent utilities transplantable into any project.",
|
|
22
22
|
"source": "./plugins/fh-commons"
|
|
23
23
|
}
|
package/CATALOG.md
CHANGED
|
@@ -4,14 +4,52 @@ AI reads this file first when searching past work. Open individual files for det
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## 2026-07-26 — Confidentiality gate: scope decoupled from the 4-axis classifier (gate-locality N=5)
|
|
8
|
+
|
|
9
|
+
- **Origin**: source-reading a cross-audited sister asset (`PromptPartner/agentsmith`, `leak-gate.sh`).
|
|
10
|
+
Its `SCOPE=()` comment — *"an excluded file is a hole a real leak can sit in"* — asked of this repo
|
|
11
|
+
surfaced a different shape of the same hole: the pre-commit confidentiality scan sat below
|
|
12
|
+
`exit 0 # No FH assets staged`, so its trigger silently inherited the 4-axis asset pathspec. A commit
|
|
13
|
+
staging only non-asset paths skipped it entirely. Known-pair measured, both directions: the identical
|
|
14
|
+
leak line blocks in `CATALOG.md` and passes unseen in `README.md` alone. Surface: 46/241 tracked files
|
|
15
|
+
(19.1%) unscannable that way, 32 of them also outside npm `files[]`.
|
|
16
|
+
- **Repair**: the confidentiality/privacy guards moved into `run_universal_guards()`, invoked before the
|
|
17
|
+
early exit — they guard the publish boundary, not FH asset structure. Credential SHAPES imported from
|
|
18
|
+
the sister asset (the scan previously matched only operator-private identity tokens, so a live AWS/GitHub/
|
|
19
|
+
Anthropic key scanned clean), live-calibrated over the whole tree: one false positive, closed by an
|
|
20
|
+
exact-literal exemption. A push-time content scan was added over the commits a push actually publishes.
|
|
21
|
+
- **Verification**: 7 cross-family adversarial rounds (codex/gpt-5.5). 30 findings; 2 accepted as named
|
|
22
|
+
residuals with the success line narrowed to claim only what it checks, the rest fixed. One author
|
|
23
|
+
refutation withdrawn when the auditor showed `npm publish` is not a backstop for a public git repo.
|
|
24
|
+
Anchors: `scripts/universal_guard_check.sh` (pre-commit) and `scripts/prepush_guard_check.sh` (pre-push),
|
|
25
|
+
both testing the STAGED blob and scoring a hook runtime fault as its own failure class.
|
|
26
|
+
- **Also**: `validate_yaml.sh` was found to be the defect rather than the file it flagged (it grepped for
|
|
27
|
+
`': '` without checking whether the value was quoted, and its `--fix` folded quotes into an already-correct
|
|
28
|
+
string) — rewritten parse-first with an `UNCALIBRATED` degrade. `sync-to-be.sh` returned the status of its
|
|
29
|
+
last loop iteration, so a successful sync reported failure, the Stop-hook cooldown stamp was never written,
|
|
30
|
+
and the companion store went uncommitted for ~3.7h; introduced by the same-day patch that added mirror banners.
|
|
31
|
+
- **Residual**: three near-duplicate scan implementations remain; single-sourcing them is the next PR and the
|
|
32
|
+
real convergence — every leniency divergence found here was a propagation miss between those copies.
|
|
33
|
+
- Tags: `gate-locality` `confidentiality` `cross-family` `known-pair` `sister-asset` `publish-boundary`
|
|
34
|
+
|
|
7
35
|
## Sessions
|
|
8
36
|
|
|
9
37
|
<!-- Add entries in reverse date order (newest at top) -->
|
|
10
38
|
|
|
39
|
+
### 2026-07-26 | forge-harness · forge-wiki · llmwiki-template · llmwiki-qa | #gate-locality, #sync-guard, #instrument-calibration, #sister-asset, #cross-corpus-provenance, #wiki-consolidation
|
|
40
|
+
**File:** scripts/gate_pathspec_check.sh · scripts/sync_guard_check.sh · templates/.git-hooks/pre-commit · templates/regression_guard.sh · templates/CLAUDE.md · plugins/fh-meta/skills/dialogue-harvest/SKILL.md · plugins/fh-meta/skills/frontier-digest/SKILL_detail.md · knowledge/shared/harness-core/loop_engineering.md
|
|
41
|
+
FH self-dev session (PR #182 merged; 7 PRs merged across 4 repos). Three defects, each found by measurement rather than review, each closed with a calibrated regression anchor. **(1) Gate-locality, 4th recurrence**: the pre-commit gate and regression_guard both matched the literal `SKILL\.md`, which the string `SKILL_detail.md` does not contain — 17 files / 208,710 B / **27.7% of the skill-spec surface**, 16 of 17 carrying fenced code, entirely ungated. It leaked twice for real (371c04f, e661931 — single-file edits to a *grounding-audit skill's own* behavioral spec). Worst property: `salience-splitter` widened the hole every time it moved content out of SKILL.md, so coverage shrank as the diet succeeded. An adversarial pass argued name-by-name coverage cannot close the class in principle; the resulting **enumeration sweep found a real uncovered file on its first run** (`dialogue-harvest/calibration_pair.md`), and the fix was escalated from a name list to a directory scope. **(2) One-way sync silently overwrote session cards twice** (v9 7,567 B → v8 5,299 B; v10 likewise). Not carelessness — *induced*: the session-start rule says read the mirror first, so the mirror becomes where agents write. The close-checker missed it because "card-last violated" measures timestamp **order**, not overwrite. Fixed with a destination-newer abort (both callers), a mechanically-injected MIRROR COPY banner, and a 7-pair anchor; live calibration caught three self-defects in the fix itself — over-blocking (the exact failure the handoff warned would train the override reflex), a half-fix leaving sync_file open, and banner churn that re-transferred 265 files per run and destroyed the log as an instrument. **(3) dialogue-harvest first real corpus** exposed that single-author input makes provenance labels free; answered with **Step 4-b cross-corpus provenance** (absorbed / held-unused / **declined**), which immediately showed a 44 KB transcript in-house since 06-27 with **zero citations in 29 days** — containing the very kill-switch clause the same day's sister audit had just confirmed FH lacked.
|
|
42
|
+
- **Sister asset**: `PromptPartner/agentsmith` (255★, 10 days old) cross-audited; 3 cross-family adversarial legs all returned NOT-CONVERGED and the governor kept the verdict — P-2's grounds refuted outright (`leak-gate.sh` is fail-closed in behavior, only the vocabulary was absent), P-1 narrowed, a category error accepted, and an arithmetic error caught (mixed baselines: +3,218 → +2,687). Sidecars said *where to dig*; only source-grounding decided.
|
|
43
|
+
- **Wiki consolidation (4 stores)**: the propagation gap ran **opposite** to the assumption — forge-wiki's own upgrades were already downstream; what never came back was a 3.7+ compat fix, leaving the canonical repo with the narrowest Python range of the three. Reverse-harvested. `{FH_ROOT}` variable landed in all four (templates carried one operator's absolute paths into org-visible checkouts — the mirror image of public-surface protection). `llmwiki-template`'s missing `fw_mcp.py` was judged **declined, not a gap** (CONTRACT.md §54 states it).
|
|
44
|
+
- **Instrument failures, five in one session** (BRE-in-ERE · zsh no-word-split · stale cwd · `install` containing `stall` · a 404 JSON body passing a length check). Every one produced a *confident wrong value*; every one was caught only by a known-positive control or by opening the actual line. Two of them recurred **after** the rule against them was written — which is why both new anchors make the control mandatory-pass rather than advice.
|
|
45
|
+
- Decision: operator approved all pushes/merges; company-zone repo pushed via REST Contents API per the account rule (new files only, no overwrite).
|
|
46
|
+
|
|
11
47
|
### 2026-07-25 | forge-harness | #dialogue-harvest, #new-skill, #cookbook-tier0, #sister-triage, #cross-family-audit, #ruleset, #calibration
|
|
12
48
|
**File:** plugins/fh-meta/skills/dialogue-harvest/ · plugins/fh-meta/skills/asset-placement-gate/SKILL.md · plugins/fh-meta/skills/context-doctor/SKILL.md · tracks/_audit/session_2026_07_25_claude5-context-rules-sister.md · tracks/_meta/codex_decorrelation_audit_2026-07-25.md
|
|
13
49
|
FH self-dev session (PR #177 merged). **New skill `dialogue-harvest`**: mines argument-shaped corpora (AI dialogue logs) — sycophancy strip first, then induced-vs-independent provenance labeling per proposition (degrade direction fixed toward the induced flag); ships an EN+KO known-pair calibration corpus backing the measured Done When. Gate: challenger HIGH 1 MED 3 LOW 3 → 7/7 repaired (the HIGH: an EN-only calibration pair would vacuously pass a new-language re-run); blind Sonnet sims reproduce both language pairs, and the KO run self-declared UNCALIBRATED when denied the calibration file. **asset-placement-gate Step 0.6**: official corpora (built-ins · claude-plugins-official · Claude Cookbook) registered as the criterion-③ ground, judged-flag semantics; roster-wide cookbook mapping scan found 0 shadowed skills. **context-doctor**: built-in `/doctor`-first sister anchor (Claude 5 gen) with the skill's increment enumerated. **Sister triage** of Anthropic's Claude-5 context-engineering rules: the "no measurable loss" claim ships no method → closed empty on that axis, vendor-claim label; imports = the /doctor Tier-0 boundary + a live confirmation of the substrate-shed trigger. **Cross-family audit** (codex gpt-5.5, repo-grounded) of the "decorrelation as generative principle" proposition: both halves NARROWED — surviving increment is "premature same-family consensus is a bad stop condition for design search", valid only as divergence-then-selection on high-leverage underdetermined decisions; doctrine-ization stays deferred by design. persona-innovator frame scan: BVSR/QD/Best-of-N all lack FH's two clauses → keep the coinage, sister-link on doctrine-ization. **Server-side residual closed**: ruleset `main-no-force-push` (non_fast_forward on main) created and independently GET-verified.
|
|
14
|
-
- Decision: dialogue-harvest built on operator go (manual n=1 proof accepted); npm
|
|
50
|
+
- Decision: dialogue-harvest built on operator go (manual n=1 proof accepted); npm v1.4.70 published + tagged same session (operator approval, PR #179).
|
|
51
|
+
- **Third block (evening)**: **Matrix Benchmark v0+v1** (qasp-dev #27·#28) — the operator's "blind man with an ultrasonic cane at 60%" metaphor turned into numbers. Planted 4 defects + 2 traps in the admin-surrogate sandbox (calibrated known-pair), probed with isolated same-tier agents differing only in channel access: **detection 4/4 tied, attribution 2/4 (blind) vs 4/4 (matrix), traps 0/0** — the two blind misattributions were exactly the §3-b cell ("absent from source" vs "present but not rendered", both misread as source-defects: spec-optimism bias observed). Pre-registered predictions: 2/3 hit, 1 void. v1: attribution routed repairs (source-defects → code, spec-defect/environment → spec v2) and the AX-Lobby 3-channel E2E generation pattern reproduced locally (12/12 pass · web_rules 0/6 first pass · 3 BE-derived data-integrity assertions · §8 UNVERIFIED label · governor re-ran independently). Next (designed, not run): 3-condition escalation bench — "open eyes only where needed" — gated on semantic_anchor pull-forward wiring. Honest labels: n=1/condition exploratory; C1 blind-miss partially instruction-induced (fixed viewport).
|
|
52
|
+
- **Second half (same day)**: qasp direction review — the "!" located from records (verification moves to the front of the pipeline: mate PR #382 close handed the reviewer seat to AI; workflow inversion "know the criteria → implement → PR already passing"; act-1.5 dual timing; web E2E generation with 3-channel cognition). Its identity tension (§5 producer=verdict) closed as **qasp-dev governance §8 verdict-independence** (domain-respect unbundled from verdict-independence; UNVERIFIED=blocking label; promotion preconditions), codex-audited 8/8. **mate_rules split into mobile_rules (7 common) ⊃ mate extension (4 convention rules)** — full compatibility preserved, 1364 tests green, codex-audited 3/3. Company-handoff tasks landed dev-side: `--checklist` command, review-bot `--diff-json` surface (consumes pr-agent's own artifact), preflight workflow doc, and a mate-dev advisory CI lane (`qasp-rules.yml`, neutral check, 3 marked line-swap points for the company circuit). PR-review video triaged: mostly convergent with existing doctrine; template direction rejected by operator (human-PR fatigue, #382 precedent) — evidence must be a byproduct of pre-PR self-verification, not a demand on authors.
|
|
15
53
|
|
|
16
54
|
### 2026-07-24 (2) | forge-harness · forge-wiki · llmwiki-template | #sister-links, #full-gate, #frontier-digest-angle-rule, #query-refresh, #mapping, #light-harness, #graph-engineering
|
|
17
55
|
**File:** knowledge/shared/dialogue/memory_intent_recall.md · knowledge/shared/harness-core/field_harness_diagnostic.md · knowledge/shared/harness-core/multi_model_sidecar_strategy.md · plugins/fh-meta/skills/harness-doctor/SKILL.md · plugins/fh-meta/skills/frontier-digest/SKILL_detail.md · tracks/forge-wiki/ · tracks/llmwiki-template/
|
package/CLAUDE.md
CHANGED
|
@@ -263,7 +263,7 @@ Every new `SKILL.md` must clear a **6-item bar** (role-duplication via `/asset-p
|
|
|
263
263
|
|
|
264
264
|
## FH Improvement 4-Axis Auto-Gate (Self-Verification Orchestrator)
|
|
265
265
|
|
|
266
|
-
**FH 자산을 수정하면**(SKILL.md · `.claude/rules/*.md` · `knowledge/shared/rules/*.md` · `templates/` · `CLAUDE.md` · substantive `knowledge/`·`docs/*.md` · `AGENTS.md`) **4축 검증 체인이 그 세션 첫 커밋 전에 자동 실행된다.** 사용자 요청 불요 — 제안이 아니라 의무 단계다.
|
|
266
|
+
**FH 자산을 수정하면**(SKILL.md · **SKILL_detail.md** · `.claude/rules/*.md` · `knowledge/shared/rules/*.md` · `templates/` · `CLAUDE.md` · substantive `knowledge/`·`docs/*.md` · `AGENTS.md`) **4축 검증 체인이 그 세션 첫 커밋 전에 자동 실행된다.** 사용자 요청 불요 — 제안이 아니라 의무 단계다.
|
|
267
267
|
|
|
268
268
|
**기계 floor**: `git commit` 은 `templates/.git-hooks/pre-commit` 이 **하드 차단**한다. 축이 전부 PASS 할 때까지 커밋 자체가 안 된다. 아래 상세가 로드되지 않아도 **훅이 막는다** — 이 산문은 훅 위의 살리언스 층이지 유일 floor 가 아니다.
|
|
269
269
|
|
package/README.ja.md
CHANGED
|
@@ -198,7 +198,7 @@ FH_BACKEND=auto npx --package @chrono-meta/fh-gate fh-gate "src/foo.ts" full
|
|
|
198
198
|
# → FH_GATE_VERDICT: PASS | PENDING | BLOCKED | ESCALATE
|
|
199
199
|
```
|
|
200
200
|
|
|
201
|
-
`fh-gate` は両ランタイムに同じ FH ガバナンスプロンプトを使います。`FH_BACKEND=claude` は `claude --print` を、`FH_BACKEND=codex` は `codex exec` を実行し、`FH_BACKEND=auto` は両 CLI が揃っていれば Codex
|
|
201
|
+
`fh-gate` は両ランタイムに同じ FH ガバナンスプロンプトを使います。`FH_BACKEND=claude` は `claude --print` を、`FH_BACKEND=codex` は `codex exec` を実行し、`FH_BACKEND=auto` は両 CLI が揃っていれば Codex を優先します — ただし `auto` はフォールバック*選択*であり、レグは 1 つだけ走ります。`FH_BACKEND=cross` は両ファミリーを走らせて findings を union します(一方だけが見つけた指摘も指摘なので、投票ではなく union)。判定はレグ中で最も重いものです。コストは約 2 倍なので既定ではなく、判定・ゲート・不可逆な面の変更に使います。出力は実際に走ったレグを常に明示します(`FH_GATE_LEGS:`、`FH_GATE_DECORRELATED:`) — 片方のファミリーしかない環境では単一レグに縮退し、その事実を明記します。
|
|
202
202
|
|
|
203
203
|
Claude Code の外でスキルやエージェントを直接実行するには `fh-run` を使います:
|
|
204
204
|
|
package/README.ko.md
CHANGED
|
@@ -197,7 +197,7 @@ FH_BACKEND=auto npx --package @chrono-meta/fh-gate fh-gate "src/foo.ts" full
|
|
|
197
197
|
# → FH_GATE_VERDICT: PASS | PENDING | BLOCKED | ESCALATE
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
`fh-gate`는 두 런타임에 동일한 FH 거버넌스 프롬프트를 씁니다. `FH_BACKEND=claude`는 `claude --print`를, `FH_BACKEND=codex`는 `codex exec`를 실행하며, `FH_BACKEND=auto`는 두 CLI가 모두 있으면 Codex를
|
|
200
|
+
`fh-gate`는 두 런타임에 동일한 FH 거버넌스 프롬프트를 씁니다. `FH_BACKEND=claude`는 `claude --print`를, `FH_BACKEND=codex`는 `codex exec`를 실행하며, `FH_BACKEND=auto`는 두 CLI가 모두 있으면 Codex를 우선합니다 — 다만 `auto`는 폴백 *선택*이라 레그를 하나만 돌립니다. `FH_BACKEND=cross`는 두 패밀리를 모두 돌려 findings를 union 합니다(한쪽만 본 지적도 지적이므로 투표가 아니라 union). 판정은 레그 중 가장 무거운 것입니다. 비용이 약 2배라 기본값이 아니며, 판정·게이트·비가역 표면 변경에 씁니다. 출력은 실제로 돈 레그를 항상 밝힙니다(`FH_GATE_LEGS:`, `FH_GATE_DECORRELATED:`) — 한 패밀리만 설치된 머신에서는 단일 레그로 내려가되 그 사실을 명시합니다. 단일 패밀리 결과가 교차검증된 것처럼 읽히는 편이 더 나쁘기 때문입니다.
|
|
201
201
|
|
|
202
202
|
Claude Code 밖에서 스킬이나 에이전트를 직접 실행하려면 `fh-run`을 씁니다:
|
|
203
203
|
|
package/README.md
CHANGED
|
@@ -209,7 +209,7 @@ FH_BACKEND=auto npx --package @chrono-meta/fh-gate fh-gate "src/foo.ts" full
|
|
|
209
209
|
# → FH_GATE_VERDICT: PASS | PENDING | BLOCKED | ESCALATE
|
|
210
210
|
```
|
|
211
211
|
|
|
212
|
-
`fh-gate` uses the same FH governance prompt for both runtimes. `FH_BACKEND=claude` runs `claude --print`; `FH_BACKEND=codex` runs `codex exec`; `FH_BACKEND=auto` prefers Codex when both CLIs are present.
|
|
212
|
+
`fh-gate` uses the same FH governance prompt for both runtimes. `FH_BACKEND=claude` runs `claude --print`; `FH_BACKEND=codex` runs `codex exec`; `FH_BACKEND=auto` prefers Codex when both CLIs are present — note that `auto` is fallback *selection*: it runs ONE leg. `FH_BACKEND=cross` runs BOTH families and unions their findings (a finding only one family saw is still a finding, so it unions rather than votes); the verdict is the most severe across legs. It costs ~2x, so it is for load-bearing verdict/gate/irreversible-surface changes, not a default. The output always declares which legs actually ran (`FH_GATE_LEGS:`, `FH_GATE_DECORRELATED:`) — on a machine with only one family, `cross` degrades to that single leg and says so, because a single-family result that reads as cross-checked is worse than an honest one.
|
|
213
213
|
|
|
214
214
|
For direct skill or agent execution outside Claude Code, use `fh-run`:
|
|
215
215
|
|
package/README.zh.md
CHANGED
|
@@ -187,7 +187,7 @@ FH_BACKEND=auto npx --package @chrono-meta/fh-gate fh-gate "src/foo.ts" full
|
|
|
187
187
|
# → FH_GATE_VERDICT: PASS | PENDING | BLOCKED | ESCALATE
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
-
`fh-gate` 对两种运行时使用同一套 FH 治理提示。`FH_BACKEND=claude` 运行 `claude --print`;`FH_BACKEND=codex` 运行 `codex exec`;`FH_BACKEND=auto` 在两个 CLI 都存在时优先选择 Codex
|
|
190
|
+
`fh-gate` 对两种运行时使用同一套 FH 治理提示。`FH_BACKEND=claude` 运行 `claude --print`;`FH_BACKEND=codex` 运行 `codex exec`;`FH_BACKEND=auto` 在两个 CLI 都存在时优先选择 Codex —— 但 `auto` 是回退式*选择*,只运行一条腿。`FH_BACKEND=cross` 会运行两个模型家族并对 findings 取并集(只有一方发现的问题仍然是问题,因此是并集而非投票),判定取各腿中最严重者。成本约为 2 倍,因此并非默认值,适用于判定/门禁/不可逆面的变更。输出始终声明实际运行了哪些腿(`FH_GATE_LEGS:`、`FH_GATE_DECORRELATED:`) —— 在只装了一个家族的机器上,`cross` 会降级为单腿并明确说明,因为让单家族结果读起来像交叉验证过更糟。
|
|
191
191
|
|
|
192
192
|
若要在 Claude Code 之外直接执行技能或 agent,使用 `fh-run`:
|
|
193
193
|
|
|
@@ -71,7 +71,33 @@ instrument: the next slip finds its leg pre-diagnosed.
|
|
|
71
71
|
| harvest-loop Step 0-b/0-c evidence check | a harvest run misses completed items despite `fh_completed_*` existing |
|
|
72
72
|
| goal-quench mid-run checkpoint files (70/85/95%) | a /goal run blows through a threshold unnoticed |
|
|
73
73
|
| ~~Substrate-jump detector~~ | **BUILT 2026-07-10** (`scripts/substrate_jump_detector.sh`, SessionStart-wired) — same operator instruction; structure-enforcing class (out-of-context drift), permanent per the durable-mechanization criterion |
|
|
74
|
-
| Quarterly maturity checker (`quarterly_maturity_check.sh` —
|
|
74
|
+
| Quarterly maturity checker (`quarterly_maturity_check.sh`) — **still unbuilt, correctly so** | ⚠️ **TRIGGER WAS UNFIRING — condition rewritten 2026-07-26** (the row stays live; strikethrough in this table means BUILT and must not be used for anything else). Its condition was *"a quarterly re-diagnosis is missed >90d"*, which needs a **last-diagnosis date to measure from, and none exists**: `hub_maturity_roadmap.md` is still the shipped **template** (its own header says *"in actual hub operation… write an operating copy"*), no operating copy was ever created, §5's six indicators still hold their template descriptions rather than counters, and no quarterly diagnosis artifact exists in either store. A backlog row whose trigger cannot fire is not deferred — it is **dead**, and it reads as deferred. **New trigger (observable): the first quarterly re-diagnosis is actually run and dated.** Until an instance-zero exists there is nothing for a checker to check; building the checker first would be the checker-for-a-loop-that-never-ran. |
|
|
75
|
+
| **Tested kill switch for any FH path that runs unattended** — documented one-move stop, *actually exercised once*, recorded | FH runs a genuinely unattended loop. Today the only candidate is the launchd `frontier-digest` (09:00 daily); the moment a second one ships, or that one gains write authority beyond its digest file, this fires |
|
|
76
|
+
|
|
77
|
+
### On the kill-switch row — provenance and the boundary of what is being proposed
|
|
78
|
+
|
|
79
|
+
Added 2026-07-26 with **two independent sources naming the same gap**, which is why it is on the
|
|
80
|
+
backlog rather than in a signal:
|
|
81
|
+
1. **External transcript already in-house since 2026-06-27** (a private companion store's
|
|
82
|
+
cross-audit shelf, `raw_2026-06-27_loop-engineering-transcript.txt` — single-author, 44 KB)
|
|
83
|
+
— *"실수도 무인으로 쌓이기 때문에 브레이크가 필요하다"* · iteration cap ·
|
|
84
|
+
stop-on-stall · budget guard. **This corpus was never cited by any FH asset** (whole-repo grep, 0
|
|
85
|
+
references) — it sat unmined for 13 days while this very file was authored from a different sister.
|
|
86
|
+
Surfaced by the first real-corpus `dialogue-harvest` run.
|
|
87
|
+
2. **`agentsmith/profiles/autonomous-loops.md`** (2026-07-16) — *"a documented one-move stop you have
|
|
88
|
+
actually tested. No budget, no cap, no L3."* Cross-audit `session_2026_07_26_agentsmith-sister.md §I-4`.
|
|
89
|
+
|
|
90
|
+
**Measured absence, instrument-calibrated**: `kill switch` · `emergency stop` · `abort the run/loop` ·
|
|
91
|
+
`정지 스위치` · `tested stop` → **0 hits** repo-wide, with known-positive controls in the same run.
|
|
92
|
+
|
|
93
|
+
⚠️ **What is deliberately NOT proposed — do not relitigate**: the same two sources also teach
|
|
94
|
+
*stagnation-triggered stopping* ("stop when the number does not improve twice"). FH already
|
|
95
|
+
**considered and declined** that class — `hub_maturity_roadmap.md §(c) Trigger-based`: *"Stagnation
|
|
96
|
+
detection criteria + auto-alerts + trigger tags all require new infra. Simplification principle
|
|
97
|
+
violation risk."* That declination stands; reopening it needs new evidence about **that** decision,
|
|
98
|
+
not a fresh citation of the same idea. Separately, FH **already has** stall detection where it
|
|
99
|
+
measurably mattered — `auto-decorrelation` §sidecar liveness, built on a production miss.
|
|
100
|
+
The kill-switch row is narrower than either source's full prescription, on purpose.
|
|
75
101
|
|
|
76
102
|
## Done When (for a new/changed autonomous path)
|
|
77
103
|
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fh-meta",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.72",
|
|
4
4
|
"engines": {
|
|
5
5
|
"claudeCode": ">=1.0.0"
|
|
6
6
|
},
|
|
7
|
-
"description": "Hub meta-engineering toolkit — 35 skills + 7 agents. New in 1.4.70: dialogue-harvest (mines AI-dialogue logs — sycophancy strip first, induced-vs-independent provenance labeling, EN+KO known-pair calibration shipped); asset-placement-gate Step 0.6 official-corpora check (Claude Cookbook as Tier-0 consult corpus, judged-flag semantics); context-doctor built-in-/doctor-first sister anchor. New in 1.4.48: phantom-quench + steel-quench gain external frontier anchors (arXiv:2607.02052 package-hallucination; arXiv:2607.02057 prompt-coverage-adequacy); README model-flat claim reframed from a per-release point-curve to structural invariants (operation flattens across tiers; depth tier-order fixed within a generation). New in 1.4.47: onboarding step ① surfaces the Mode D companion-store session-start load in the auto-read salience anchor (previously only in the local binding + rules, so a greeting could skip the load). New in 1.4.46: context-doctor gains a command-output axis — routes to a command-output proxy/hook (rtk) to trim verbose CLI stdout, complementing .claudeignore; risk-gated to token-scarce environments (lossy filtering, off gate-input paths). New in 1.4.41: context-doctor 2026 trigger vocab (context engineering/rot/collapse) + phantom-citation hardening; hub measurement-integrity-checklist (cross-model measurement pre-flight: display-name pin/reps≥3/discriminating probe). New in 1.4.40: install-wizard scaffolds the companion store as a queryable wiki (INDEX + session-start read + Raw/Wiki/Conversation ingest axis). New in 1.4.39: auto-decorrelation (cross-family verifier sidecar recruitment, calibration-gated) + video-ingest (capability-routed video ingestion). New in 1.4.37: corpus-grounding-expander + persona-roster-expander (field-harvested verbatim-relay capability skills). New in 1.3.0: public-surface-audit (git-tracked private-token leak scan), field-harvest Mode B session-end auto-trigger, 4-axis gate scope extension (docs/ + AGENTS.md). New in 1.2.0: pipeline-conductor (4-pipeline gated sweep), return-path-gate (chain closure audit), goal-quench (Stop hook + quality gate), steel-quench Wave 5 (multi-model sidecar challenger), 2-layer architecture docs, YAML validation script. Validated cross-CLI: Claude Code, Codex, Gemini.",
|
|
7
|
+
"description": "Hub meta-engineering toolkit — 35 skills + 7 agents. New in 1.4.71: SKILL_detail.md brought inside the 4-axis gate — the gate matched the literal `SKILL.md`, which `SKILL_detail.md` does not contain, leaving 27.7% of the skill-spec surface ungated (measured; it leaked twice for real). Fix escalated from a name list to a directory scope after an enumeration sweep found a real uncovered file on its first run; anchored by scripts/gate_pathspec_check.sh (known-pair, wired into pre-commit). One-way mirror sync gains a destination-newer abort + mechanically injected mirror banner after two session cards were silently overwritten, anchored by scripts/sync_guard_check.sh. dialogue-harvest gains Step 4-b cross-corpus provenance (absorbed / held-unused / declined) for single-author corpora, where the original provenance labels were free and measured nothing. frontier-digest arxiv leg category-scoped after a relevance drift the staleness rule structurally could not catch (known-pair calibration recorded). templates/CLAUDE.md hub paths switched to {FH_ROOT} so a copied harness stops carrying one operator's absolute paths into org-visible checkouts. New in 1.4.70: dialogue-harvest (mines AI-dialogue logs — sycophancy strip first, induced-vs-independent provenance labeling, EN+KO known-pair calibration shipped); asset-placement-gate Step 0.6 official-corpora check (Claude Cookbook as Tier-0 consult corpus, judged-flag semantics); context-doctor built-in-/doctor-first sister anchor. New in 1.4.48: phantom-quench + steel-quench gain external frontier anchors (arXiv:2607.02052 package-hallucination; arXiv:2607.02057 prompt-coverage-adequacy); README model-flat claim reframed from a per-release point-curve to structural invariants (operation flattens across tiers; depth tier-order fixed within a generation). New in 1.4.47: onboarding step ① surfaces the Mode D companion-store session-start load in the auto-read salience anchor (previously only in the local binding + rules, so a greeting could skip the load). New in 1.4.46: context-doctor gains a command-output axis — routes to a command-output proxy/hook (rtk) to trim verbose CLI stdout, complementing .claudeignore; risk-gated to token-scarce environments (lossy filtering, off gate-input paths). New in 1.4.41: context-doctor 2026 trigger vocab (context engineering/rot/collapse) + phantom-citation hardening; hub measurement-integrity-checklist (cross-model measurement pre-flight: display-name pin/reps≥3/discriminating probe). New in 1.4.40: install-wizard scaffolds the companion store as a queryable wiki (INDEX + session-start read + Raw/Wiki/Conversation ingest axis). New in 1.4.39: auto-decorrelation (cross-family verifier sidecar recruitment, calibration-gated) + video-ingest (capability-routed video ingestion). New in 1.4.37: corpus-grounding-expander + persona-roster-expander (field-harvested verbatim-relay capability skills). New in 1.3.0: public-surface-audit (git-tracked private-token leak scan), field-harvest Mode B session-end auto-trigger, 4-axis gate scope extension (docs/ + AGENTS.md). New in 1.2.0: pipeline-conductor (4-pipeline gated sweep), return-path-gate (chain closure audit), goal-quench (Stop hook + quality gate), steel-quench Wave 5 (multi-model sidecar challenger), 2-layer architecture docs, YAML validation script. Validated cross-CLI: Claude Code, Codex, Gemini.",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "chrono-meta",
|
|
10
10
|
"email": "chrono-meta@users.noreply.github.com"
|
|
@@ -93,6 +93,79 @@ For each proposition, find the **first occurrence** of its core frame/key terms
|
|
|
93
93
|
Counterpart-authored content the user *selected* as valuable is listed separately, marked
|
|
94
94
|
"selection, not authorship" — selection is a real act but must not be recorded as the user's claim.
|
|
95
95
|
|
|
96
|
+
## Step 4-b. Cross-Corpus Provenance — the single-author mode (measured need, 2026-07-26)
|
|
97
|
+
|
|
98
|
+
Step 4 asks *"who first said this — the user or the counterpart?"* On a **single-author corpus**
|
|
99
|
+
(a video transcript, an article, a talk) there is no counterpart, so every proposition is stamped
|
|
100
|
+
`independent` **for free** and the differentiator does not fire at all. The first real-corpus run
|
|
101
|
+
measured exactly that: 12 propositions, 12 free labels, zero discrimination.
|
|
102
|
+
|
|
103
|
+
On a single-author corpus the load-bearing provenance axis is not *within* the document — it is
|
|
104
|
+
**between the corpus and the assets that were supposed to consume it**:
|
|
105
|
+
|
|
106
|
+
> *Which of these propositions reached our own assets, and which did we hold and never use?*
|
|
107
|
+
|
|
108
|
+
**Run it when** the corpus is single-author AND a downstream asset on the same topic exists.
|
|
109
|
+
Skip (and say so) when there is no plausible consumer — the question is meaningless without one.
|
|
110
|
+
|
|
111
|
+
1. **Name the consumer asset(s)** explicitly in the output header. Guessing is not allowed;
|
|
112
|
+
an unnamed consumer makes every verdict unfalsifiable.
|
|
113
|
+
2. **Grep locates candidates; the label is assigned by reading them.** A hit count is never a
|
|
114
|
+
verdict — a consumer that says *"we do not use kill switches"* matches the same pattern as one
|
|
115
|
+
that adopts them. So:
|
|
116
|
+
- **absorbed** — requires **quoting the supporting span** from the consumer. No quote, no
|
|
117
|
+
`absorbed`. (A count-only `absorbed` is the same defect as a whole-file parity grep going
|
|
118
|
+
green on a line that says "excluded" — measured in this repo the same day.)
|
|
119
|
+
- **held-unused** — absent from the consumer though the corpus has been in-house since {date}.
|
|
120
|
+
Before writing it, **try at least two term variants** (synonym / abbreviation / the concept
|
|
121
|
+
re-said in the consumer's own vocabulary). Concepts get absorbed under different words; a
|
|
122
|
+
literal-match zero is weak evidence of absence.
|
|
123
|
+
- **declined** — absent *because a named asset records a decision against it*. Cite the decision.
|
|
124
|
+
This tier is mandatory and load-bearing: without it, a re-proposal reopens a settled call
|
|
125
|
+
as if it were an oversight. (First run hit this immediately — stagnation-triggered stopping
|
|
126
|
+
was `held-unused` by grep and `declined` in fact, recorded in `hub_maturity_roadmap.md`.)
|
|
127
|
+
**Automation is prohibited here**: the first run produced 2 false positives out of 12, both
|
|
128
|
+
caught only by opening the matched line.
|
|
129
|
+
3. **Report the ingestion-to-citation gap** — corpus in-house date vs first citation by any asset.
|
|
130
|
+
A corpus with **zero citations** is the finding, not a null result.
|
|
131
|
+
|
|
132
|
+
**Instrument discipline (mandatory-pass, learned on the first run — four failures in one session):**
|
|
133
|
+
a **known-positive control** runs beside every measurement and its result is printed. A bare zero is
|
|
134
|
+
not publishable.
|
|
135
|
+
|
|
136
|
+
⚠️ **The control must be a separate search, not an alternation bolted onto the target pattern.**
|
|
137
|
+
`grep -E "core_term|title"` satisfies "a control ran" while proving nothing: `title` matches, the
|
|
138
|
+
command exits 0, and a malformed `core_term` still silently matches nothing. That is a vacuous pass.
|
|
139
|
+
The control's job is to prove **this pattern form, on this target, through this shell** can return a
|
|
140
|
+
hit at all — so run the *same pattern shape* against something you know contains it, as its own
|
|
141
|
+
command, and print both numbers. The four measured failure modes:
|
|
142
|
+
BRE `\|` inside an ERE pattern · unquoted `$VAR` under zsh (no word-splitting) · a stale `cd` making
|
|
143
|
+
paths unresolvable · substring collision (`install` contains `stall`). Each produced a *confident,
|
|
144
|
+
wrong* zero; each was caught only by the control. Do not redirect stderr away — three of the four
|
|
145
|
+
announced themselves there.
|
|
146
|
+
|
|
147
|
+
**Degrade direction — and the skip/degrade boundary, which must not be a matter of taste.**
|
|
148
|
+
`skip (N/A)` and `UNCALIBRATED` are **different states with different triggers**, and the boundary is
|
|
149
|
+
mechanical because otherwise the cheaper exit wins under time pressure:
|
|
150
|
+
|
|
151
|
+
| Situation | State | Why |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| Corpus is multi-speaker | **N/A** | Step 4 already answered provenance; 4-b's question does not arise |
|
|
154
|
+
| A consumer search was **run and recorded**, and no asset on the topic exists | **N/A**, quoting the search | A real negative, not a failure |
|
|
155
|
+
| A consumer is **named but does not resolve** (bad path, missing file) | **UNCALIBRATED** | Never N/A — a broken pointer is a tooling failure wearing absence's clothes |
|
|
156
|
+
| The known-positive control returns zero | **UNCALIBRATED** | The instrument is not measuring |
|
|
157
|
+
| No search was run | **UNCALIBRATED** | "I didn't look" is not "nothing is there" |
|
|
158
|
+
|
|
159
|
+
Under `UNCALIBRATED` the step emits **no** absorbed/held-unused/declined labels at all — a provenance
|
|
160
|
+
verdict is a claim about what an organization did with knowledge, and an uncalibrated one is worse
|
|
161
|
+
than none. Under `N/A` the step states the reason **and the search that established it**.
|
|
162
|
+
|
|
163
|
+
⚠️ **Known weakness, stated rather than papered over**: a hurried session's natural pull is to grep a
|
|
164
|
+
nearby-but-plausible file and report against it without flagging the substitution. The Sonnet
|
|
165
|
+
floor-sim of this step reached `UNCALIBRATED` correctly *and* named that same failure as the more
|
|
166
|
+
likely one in practice. The forcing function is the control returning zero alongside the
|
|
167
|
+
measurement — which is why the control is mandatory-pass and not advice.
|
|
168
|
+
|
|
96
169
|
## Step 5. Verification-Status Column
|
|
97
170
|
|
|
98
171
|
Each proposition gets a status: mechanically checkable / falsifiable-but-untested /
|
|
@@ -133,6 +206,12 @@ Routing is **proposal-only**: this skill writes nothing outside its output block
|
|
|
133
206
|
pair first** — re-running an existing-language pair for a new language is a vacuous pass, not a
|
|
134
207
|
measurement (check-class: **measured**; declare the result in the output header
|
|
135
208
|
`calibration:` field).
|
|
209
|
+
- **Single-author corpus with a named consumer ran Step 4-b** — each proposition carries
|
|
210
|
+
absorbed / held-unused / declined, the consumer asset is named, and the ingestion-to-citation gap
|
|
211
|
+
is reported; every grep in the step shows its known-positive control result inline, or the step
|
|
212
|
+
reports `UNCALIBRATED` and emits no labels (check-class: **mandatory-pass** — the control result
|
|
213
|
+
is either printed or the labels are absent; N/A when the corpus is multi-speaker or no consumer
|
|
214
|
+
asset exists, and the N/A must be stated).
|
|
136
215
|
- **Propositions are faithful to source spans** — no meaning drift (check-class: **judged**;
|
|
137
216
|
adversarial pairing: `phantom-quench` back-trace of each proposition to its source ref — a
|
|
138
217
|
proposition whose source span does not support it is an Unsupported finding).
|
|
@@ -26,17 +26,34 @@ Collection criteria: score > 10, keyword-relevant items only. Max 15 items.
|
|
|
26
26
|
### arxiv
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
|
|
29
|
+
# Category-scoped since 2026-07-26. Unscoped `all:` full-text matching drifted off-axis: the 07-26 run
|
|
30
|
+
# returned 6/6 fresh-but-irrelevant papers (diffusion world models, embodied QA, medical-education
|
|
31
|
+
# gamification, RF fingerprinting). Freshness was fine; relevance was not — so the staleness rule below
|
|
32
|
+
# could not catch it.
|
|
33
|
+
for Q in "LLM agent" "agent harness" "context engineering"; do
|
|
33
34
|
curl -s --max-time 8 \
|
|
34
|
-
"https://export.arxiv.org/api/query?search_query=all
|
|
35
|
+
"https://export.arxiv.org/api/query?search_query=cat:cs.SE+AND+all:%22${Q// /+}%22&max_results=2&sortBy=submittedDate&sortOrder=descending"
|
|
35
36
|
done
|
|
36
37
|
```
|
|
37
38
|
|
|
38
39
|
Max 6 items.
|
|
39
40
|
|
|
41
|
+
**Refresh rule — two independent triggers (both required, neither sufficient alone):**
|
|
42
|
+
- **Staleness**: a query's newest hit is >6 months old, two runs in a row → replace the query.
|
|
43
|
+
- **Relevance** (added 2026-07-26): ≥4 of 6 returned items are off-axis (not about LLM agents /
|
|
44
|
+
harnesses / agent evaluation / context engineering) → the query is drifting even though it is fresh.
|
|
45
|
+
Staleness and relevance fail independently; a fresh-but-irrelevant query passes the staleness check.
|
|
46
|
+
|
|
47
|
+
**Before adopting a replacement query, calibrate it on a known pair** (`measurement-integrity-checklist.md
|
|
48
|
+
§Instrument-Calibration`): pick one paper FH would clearly want and one it clearly would not, and confirm
|
|
49
|
+
the new query returns the first and excludes the second. A query that cannot separate a pair you already
|
|
50
|
+
know the answer to is not filtering — it is generating.
|
|
51
|
+
|
|
52
|
+
> Calibration on record (2026-07-26, for the `cat:cs.SE` scoping above):
|
|
53
|
+
> **positive** = *"Understanding Agent-Reactive Bugs at the Model-Harness Boundary"* → `cs.SE`, returned.
|
|
54
|
+
> **negative** = *"MedGame: Storytelling Gamification … Medical Education"* → `cs.CL`/`cs.HC`, excluded.
|
|
55
|
+
> `cat:cs.MA` was tested against the same pair and **rejected** — it kept roughly half the off-axis items.
|
|
56
|
+
|
|
40
57
|
### TLDR AI (RSS)
|
|
41
58
|
|
|
42
59
|
```bash
|
|
@@ -48,9 +65,15 @@ Parse `<item>` → title + link. Max 5 items.
|
|
|
48
65
|
### The Batch — deeplearning.ai (HTML scraping)
|
|
49
66
|
|
|
50
67
|
```bash
|
|
51
|
-
curl -s --max-time 10 -L "https://www.deeplearning.ai/the-batch
|
|
68
|
+
curl -s --max-time 10 -L "https://www.deeplearning.ai/the-batch"
|
|
52
69
|
```
|
|
53
70
|
|
|
71
|
+
⚠️ **No trailing slash.** `…/the-batch/` returns **HTTP 308** redirecting to the slash-less path (verified
|
|
72
|
+
2026-07-26); the 07-26 automated run read that 308 as a dead endpoint and skipped the leg. The slash-less
|
|
73
|
+
URL returns 200 directly, so the leg no longer depends on redirect-following at all — which matters
|
|
74
|
+
because the fetch path is not always `curl -L` (a WebFetch-based run does not follow redirects the same
|
|
75
|
+
way). Second collection endpoint to churn, after GeekNews `/rss/news` (2026-06-20).
|
|
76
|
+
|
|
54
77
|
Extract `"title":"..."` + `"slug":"issue-\d+"` pattern → URL: `https://www.deeplearning.ai/the-batch/{slug}/`. Max 5 items.
|
|
55
78
|
|
|
56
79
|
### GeekNews — news.hada.io (RSS)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
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). Triggers: "SKILL.md too large", "split this skill", "skill is bloated", "skill file too long", "CLAUDE.md 너무 커".
|
|
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). Triggers: "SKILL.md too large", "split this skill", "skill is bloated", "skill file too long", "CLAUDE.md 너무 커".'
|
|
4
4
|
user-invocable: true
|
|
5
5
|
allowed-tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
|
|
6
6
|
model: sonnet
|
package/scripts/fh-gate.sh
CHANGED
|
@@ -59,13 +59,87 @@ FH_TASK_DESCRIPTION="${FH_TASK_DESCRIPTION:-}"
|
|
|
59
59
|
FH_DIFF_PATH="${FH_DIFF_PATH:-}"
|
|
60
60
|
|
|
61
61
|
case "$FH_BACKEND" in
|
|
62
|
-
claude|codex|auto) ;;
|
|
62
|
+
claude|codex|auto|cross) ;;
|
|
63
63
|
*)
|
|
64
|
-
echo "ERROR: FH_BACKEND must be 'claude', 'codex', or '
|
|
64
|
+
echo "ERROR: FH_BACKEND must be 'claude', 'codex', 'auto', or 'cross' (got: $FH_BACKEND)" >&2
|
|
65
65
|
exit $EXIT_ARG_ERROR
|
|
66
66
|
;;
|
|
67
67
|
esac
|
|
68
68
|
|
|
69
|
+
# ── FH_BACKEND=cross — decorrelated review (2026-07-26) ───────────────────────────────────────
|
|
70
|
+
# `auto` is a FALLBACK: it picks codex if present, else claude, and runs ONE leg. That is backend
|
|
71
|
+
# SELECTION, not decorrelation. A same-family reviewer shares the author's optimistic reading, which
|
|
72
|
+
# is the failure mode the FH load-bearing gate exists to catch — and a 7-round cross-family audit of
|
|
73
|
+
# that gate found 30 issues an in-family pass had not.
|
|
74
|
+
#
|
|
75
|
+
# `cross` runs BOTH families and UNIONs their findings. Union, not vote: detection is the task, and a
|
|
76
|
+
# finding only one leg saw is still a finding (majority voting would discard exactly the decorrelated
|
|
77
|
+
# signal this mode is for). The verdict is the most severe across legs.
|
|
78
|
+
#
|
|
79
|
+
# THE INVARIANT THAT MATTERS MOST: the output declares WHICH LEGS ACTUALLY RAN (`FH_GATE_LEGS:`).
|
|
80
|
+
# `cross` is a REQUEST, not a guarantee — a machine may have only one family installed. When a leg is
|
|
81
|
+
# unavailable or errors, this degrades to the surviving leg and SAYS SO, loudly, in both the human and
|
|
82
|
+
# the machine-readable output. A single-leg result that reads as if it were cross-checked is the same
|
|
83
|
+
# class of defect as a check that did not run reading as PASS.
|
|
84
|
+
#
|
|
85
|
+
# COST: cross is ~2x. It is deliberately NOT a default — [[feedback_decorrelation_not_fanout_cost_boundary]]
|
|
86
|
+
# says match the parallelisation axis to the failure mode rather than multiply. Callers should request
|
|
87
|
+
# it for load-bearing verdict/gate/irreversible-surface changes, which is exactly the trigger the
|
|
88
|
+
# pre-commit load-bearing leg already computes.
|
|
89
|
+
if [[ "$FH_BACKEND" == "cross" ]]; then
|
|
90
|
+
_CROSS_LEGS=""; _CROSS_OUT=""; _CROSS_WORST="PASS"; _CROSS_RAN=0; _CROSS_ERR=""
|
|
91
|
+
_sev_rank() { case "$1" in PASS) echo 0 ;; PENDING) echo 1 ;; ESCALATE) echo 2 ;; BLOCKED) echo 3 ;; *) echo -1 ;; esac; }
|
|
92
|
+
for _leg in claude codex; do
|
|
93
|
+
command -v "$_leg" >/dev/null 2>&1 || { _CROSS_ERR="${_CROSS_ERR}${_CROSS_ERR:+, }$_leg (not installed)"; continue; }
|
|
94
|
+
# `set -e` is on: an assignment from a command substitution carries the child's exit status, and
|
|
95
|
+
# this child EXITS NON-ZERO BY DESIGN for every non-PASS verdict (PENDING 1 / BLOCKED 2 /
|
|
96
|
+
# ESCALATE 3). Written bare, the first leg that found anything would kill the whole cross run —
|
|
97
|
+
# i.e. cross would work only when there was nothing to find. `|| _legrc=$?` keeps the status
|
|
98
|
+
# without letting it abort. Verified against a BLOCKED leg, not assumed.
|
|
99
|
+
_legrc=0
|
|
100
|
+
_legout=$(FH_BACKEND="$_leg" "$0" "$@" 2>/dev/null) || _legrc=$?
|
|
101
|
+
if [ "$_legrc" -ge 10 ]; then
|
|
102
|
+
_CROSS_ERR="${_CROSS_ERR}${_CROSS_ERR:+, }$_leg (harness error $_legrc)"; continue
|
|
103
|
+
fi
|
|
104
|
+
_legverdict=$(printf '%s' "$_legout" | grep -m1 '^FH_GATE_VERDICT:' | awk '{print $2}')
|
|
105
|
+
[ -z "$_legverdict" ] && { _CROSS_ERR="${_CROSS_ERR}${_CROSS_ERR:+, }$_leg (no verdict line)"; continue; }
|
|
106
|
+
_CROSS_RAN=$((_CROSS_RAN+1))
|
|
107
|
+
_CROSS_LEGS="${_CROSS_LEGS}${_CROSS_LEGS:+,}$_leg"
|
|
108
|
+
[ "$(_sev_rank "$_legverdict")" -gt "$(_sev_rank "$_CROSS_WORST")" ] && _CROSS_WORST="$_legverdict"
|
|
109
|
+
_CROSS_OUT="${_CROSS_OUT}
|
|
110
|
+
# ── leg: $_leg (verdict $_legverdict) ──
|
|
111
|
+
$(printf '%s' "$_legout" | sed -n '/^---$/,$p')"
|
|
112
|
+
done
|
|
113
|
+
|
|
114
|
+
if [ "$_CROSS_RAN" -eq 0 ]; then
|
|
115
|
+
echo "ERROR: FH_BACKEND=cross — no leg produced a verdict (${_CROSS_ERR:-none available}). Failing closed." >&2
|
|
116
|
+
exit $EXIT_HARNESS_ERROR
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
printf 'FH_STATUS: SUCCESS\n'
|
|
120
|
+
printf 'FH_GATE_VERDICT: %s\n' "$_CROSS_WORST"
|
|
121
|
+
printf 'FH_GATE_MODE: cross\n'
|
|
122
|
+
printf 'FH_GATE_LEGS: %s\n' "$_CROSS_LEGS"
|
|
123
|
+
if [ "$_CROSS_RAN" -lt 2 ]; then
|
|
124
|
+
# Degraded, and it must be impossible to mistake this for a two-family result.
|
|
125
|
+
printf 'FH_GATE_DECORRELATED: no\n'
|
|
126
|
+
printf 'FH_GATE_DEGRADED: %s\n' "$_CROSS_ERR"
|
|
127
|
+
echo "WARN: FH_BACKEND=cross ran a SINGLE leg ($_CROSS_LEGS) — $_CROSS_ERR." >&2
|
|
128
|
+
echo " This verdict is NOT decorrelated. Treat it as $_CROSS_LEGS alone." >&2
|
|
129
|
+
else
|
|
130
|
+
printf 'FH_GATE_DECORRELATED: yes\n'
|
|
131
|
+
fi
|
|
132
|
+
printf '%s\n' "$_CROSS_OUT"
|
|
133
|
+
echo "→ fh-gate: cross mode — legs [$_CROSS_LEGS], union verdict $_CROSS_WORST" >&2
|
|
134
|
+
case "$_CROSS_WORST" in
|
|
135
|
+
PASS) exit $EXIT_PASS ;;
|
|
136
|
+
PENDING) exit $EXIT_PENDING ;;
|
|
137
|
+
BLOCKED) exit $EXIT_BLOCKED ;;
|
|
138
|
+
ESCALATE) exit $EXIT_ESCALATE ;;
|
|
139
|
+
*) exit $EXIT_HARNESS_ERROR ;;
|
|
140
|
+
esac
|
|
141
|
+
fi
|
|
142
|
+
|
|
69
143
|
# FH_TIMEOUT lands in command position via the unquoted ${_TIMEOUT_CMD} idiom below.
|
|
70
144
|
# `timeout DURATION COMMAND [ARG]...` treats the word after the duration as the command,
|
|
71
145
|
# so an unvalidated value word-splits into arbitrary execution with no shell metacharacters
|
|
@@ -34,7 +34,7 @@ while [ $# -gt 0 ]; do
|
|
|
34
34
|
esac
|
|
35
35
|
done
|
|
36
36
|
cat >/dev/null # consume the prompt on stdin
|
|
37
|
-
[ -n "$out" ] && printf '%s' "$FAKE_PAYLOAD" > "$out"
|
|
37
|
+
[ -n "$out" ] && printf '%s' "${FAKE_PAYLOAD_CODEX:-$FAKE_PAYLOAD}" > "$out"
|
|
38
38
|
exit 0
|
|
39
39
|
FAKE
|
|
40
40
|
chmod +x "$FAKEBIN/codex"
|
|
@@ -47,7 +47,7 @@ cat > "$FAKEBIN/claude" <<'FAKE'
|
|
|
47
47
|
#!/usr/bin/env bash
|
|
48
48
|
cat >/dev/null # consume the prompt on stdin
|
|
49
49
|
if [ -n "${FAKE_ENVELOPE:-}" ]; then printf '%s\n' "$FAKE_ENVELOPE"; exit 0; fi
|
|
50
|
-
printf '{"is_error":false,"subtype":"success","structured_output":%s}\n' "$FAKE_PAYLOAD"
|
|
50
|
+
printf '{"is_error":false,"subtype":"success","structured_output":%s}\n' "${FAKE_PAYLOAD_CLAUDE:-$FAKE_PAYLOAD}"
|
|
51
51
|
exit 0
|
|
52
52
|
FAKE
|
|
53
53
|
chmod +x "$FAKEBIN/claude"
|
|
@@ -201,6 +201,50 @@ printf '#!/usr/bin/env bash\nexit 1\n' > "$NOENT/od"; chmod +x "$NOENT/od"
|
|
|
201
201
|
check "no CSPRNG (openssl+od stubbed to fail) → fails closed" 10 \
|
|
202
202
|
env PATH="$NOENT:$PATH" FH_DRY_RUN=1 bash "$GATE" "package.json" quick test
|
|
203
203
|
|
|
204
|
+
echo
|
|
205
|
+
echo "── FH_BACKEND=cross (decorrelated review) ──"
|
|
206
|
+
# cross runs BOTH families and UNIONs. `auto` is fallback SELECTION and runs one leg; conflating the
|
|
207
|
+
# two would let a single-family verdict read as decorrelated, which is the defect class this mode
|
|
208
|
+
# exists to remove. These pairs pin: the union verdict, the leg accounting, and — most importantly —
|
|
209
|
+
# that a degraded (single-leg) run says so in machine-readable form.
|
|
210
|
+
CROSS_PASS='{"status":"SUCCESS","verdict":"PASS","findings_count":0,"findings_a":0,"findings_b":0,"findings":[]}'
|
|
211
|
+
CROSS_BLOCK='{"status":"SUCCESS","verdict":"BLOCKED","findings_count":1,"findings_a":1,"findings_b":0,"findings":[{"grade":"A","location":"x:1","title":"t","evidence":"e","fix":"f"}]}'
|
|
212
|
+
|
|
213
|
+
check_out() { # <name> <expected-exit> <grep-ere that MUST appear> -- <cmd...>
|
|
214
|
+
local name="$1" expect="$2" want="$3"; shift 3
|
|
215
|
+
local got
|
|
216
|
+
"$@" >"$TMPROOT/out" 2>"$TMPROOT/err"; got=$?
|
|
217
|
+
if [ "$got" -eq "$expect" ] && grep -qE "$want" "$TMPROOT/out"; then
|
|
218
|
+
printf 'PASS %-58s (exit %s)\n' "$name" "$got"; pass=$((pass + 1))
|
|
219
|
+
else
|
|
220
|
+
printf 'FAIL %-58s expected %s + /%s/, got %s\n' "$name" "$expect" "$want" "$got"
|
|
221
|
+
sed 's/^/ /' "$TMPROOT/out" | head -4; sed 's/^/ /' "$TMPROOT/err" | head -2
|
|
222
|
+
fail=$((fail + 1))
|
|
223
|
+
fi
|
|
224
|
+
}
|
|
225
|
+
run_cross() { # <claude-payload> <codex-payload>
|
|
226
|
+
env PATH="$FAKEBIN:$PATH" FH_BACKEND=cross FH_MODEL=fake \
|
|
227
|
+
FAKE_PAYLOAD_CLAUDE="$1" FAKE_PAYLOAD_CODEX="$2" FAKE_PAYLOAD="$1" \
|
|
228
|
+
bash "$GATE" "package.json" quick test
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
check_out "cross: both PASS → PASS, decorrelated" 0 'FH_GATE_DECORRELATED: yes' \
|
|
232
|
+
run_cross "$CROSS_PASS" "$CROSS_PASS"
|
|
233
|
+
# UNION, not vote: one leg blocking is enough. A majority rule would discard precisely the finding
|
|
234
|
+
# only the other family saw, which is the entire point of running two.
|
|
235
|
+
check_out "cross: one leg BLOCKED → union BLOCKED" 2 'FH_GATE_VERDICT: BLOCKED' \
|
|
236
|
+
run_cross "$CROSS_PASS" "$CROSS_BLOCK"
|
|
237
|
+
check_out "cross: both legs' findings survive the union" 2 'FH_GATE_LEGS: claude,codex' \
|
|
238
|
+
run_cross "$CROSS_BLOCK" "$CROSS_BLOCK"
|
|
239
|
+
# A machine with only one family is the COMMON case, not an edge case. It must not be silent.
|
|
240
|
+
ONELEG="$TMPROOT/oneleg"; mkdir -p "$ONELEG"; cp "$FAKEBIN/claude" "$ONELEG/claude"
|
|
241
|
+
check_out "cross: codex absent → single leg, DECORRELATED: no" 0 'FH_GATE_DECORRELATED: no' \
|
|
242
|
+
env PATH="$ONELEG:/usr/bin:/bin" FH_BACKEND=cross FH_MODEL=fake \
|
|
243
|
+
FAKE_PAYLOAD_CLAUDE="$CROSS_PASS" FAKE_PAYLOAD="$CROSS_PASS" \
|
|
244
|
+
bash "$GATE" "package.json" quick test
|
|
245
|
+
check "cross: no family available → fails closed" 10 \
|
|
246
|
+
env PATH="/usr/bin:/bin" FH_BACKEND=cross bash "$GATE" "package.json" quick test
|
|
247
|
+
|
|
204
248
|
echo
|
|
205
249
|
echo "────────────────────────────────────────────────────────────────────"
|
|
206
250
|
printf 'fh-gate regressions: %d passed, %d failed\n' "$pass" "$fail"
|