@chrono-meta/fh-gate 2.6.0 → 2.8.0

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.
Files changed (55) hide show
  1. package/.claude/rules/fh_4axis_gate.md +26 -3
  2. package/.claude-plugin/marketplace.json +2 -2
  3. package/AGENTS.md +28 -3
  4. package/CLAUDE.md +146 -168
  5. package/README.ja.md +144 -24
  6. package/README.ko.md +135 -22
  7. package/README.md +204 -27
  8. package/README.zh.md +126 -21
  9. package/docs/ETHOS.md +10 -3
  10. package/knowledge/shared/dialogue/ai_dialogue_playbook.md +131 -0
  11. package/knowledge/shared/harness-core/claude_md_gate_details.md +90 -0
  12. package/knowledge/shared/harness-core/dispatch_conditional_prohibition.md +75 -0
  13. package/knowledge/shared/harness-core/fh_three_layer_canon.md +77 -3
  14. package/knowledge/shared/harness-core/field_verdict_crossfamily_gate.md +92 -5
  15. package/knowledge/shared/harness-core/harness_incubator_doctrine.md +12 -2
  16. package/knowledge/shared/harness-core/multi_model_sidecar_strategy.md +32 -0
  17. package/knowledge/shared/harness-core/ship_readiness_gate.md +77 -8
  18. package/knowledge/shared/learnings/subagent_invocations_log.yaml +196 -0
  19. package/knowledge/shared/rules/knowledge_layer_seam.md +1 -1
  20. package/knowledge/shared/rules/multi_session_close_protocol.md +7 -3
  21. package/package.json +15 -2
  22. package/plugins/fh-commons/.claude-plugin/plugin.json +1 -1
  23. package/plugins/fh-meta/.claude-plugin/plugin.json +1 -1
  24. package/plugins/fh-meta/CHANGELOG.md +157 -0
  25. package/plugins/fh-meta/agents/persona-innovator.md +170 -0
  26. package/plugins/fh-meta/skills/cross-ecosystem-synergy-detection/SKILL.md +37 -0
  27. package/plugins/fh-meta/skills/public-surface-audit/SKILL_detail.md +16 -1
  28. package/plugins/fh-meta/skills/steel-quench/SKILL.md +97 -0
  29. package/scripts/adapters/peer_resolve.sh +58 -6
  30. package/scripts/branch_claim.sh +3 -1
  31. package/scripts/cluster_capability_scan.sh +42 -13
  32. package/scripts/digest_landing_check.sh +142 -2
  33. package/scripts/fh_hub_identity.sh +83 -0
  34. package/scripts/fh_session_load.sh +53 -5
  35. package/scripts/fh_track_resolve.sh +114 -0
  36. package/scripts/field_canon_preload.sh +50 -5
  37. package/scripts/listing_watch.sh +187 -0
  38. package/scripts/package_coverage_check.sh +8 -0
  39. package/scripts/prior_art_prompt.sh +168 -0
  40. package/scripts/psa_scan_lib.sh +201 -15
  41. package/scripts/residency_admission_check.sh +204 -0
  42. package/scripts/selfcheck.sh +103 -0
  43. package/scripts/test_adapter_lanes.sh +67 -2
  44. package/scripts/test_heavy_classifier_lanes.sh +144 -0
  45. package/scripts/test_listing_watch_lanes.sh +162 -0
  46. package/scripts/test_marker_defense_lanes.sh +152 -0
  47. package/scripts/test_marker_soul_check_lanes.sh +211 -0
  48. package/scripts/test_prior_art_prompt_lanes.sh +128 -0
  49. package/scripts/test_psa_singlefile_lanes.sh +351 -1
  50. package/scripts/test_residency_admission_lanes.sh +60 -0
  51. package/scripts/test_track_resolve_lanes.sh +158 -0
  52. package/scripts/test_wizard_snippet_merge_lanes.sh +40 -0
  53. package/templates/.git-hooks/pre-commit +400 -4
  54. package/templates/.git-hooks/pre-push +17 -2
  55. package/templates/settings.PriorArt.snippet.json +44 -0
@@ -190,9 +190,32 @@ controls: n/a — no measurement in this delta (<reason>)
190
190
  ```
191
191
 
192
192
  **`standpoint:`** — closed enum, canonical spec in
193
- `knowledge/shared/harness-core/field_verdict_crossfamily_gate.md §7`. **Still validated by nothing**
194
- — zero hook lines, no fixture suite. Recorded here so the gap is visible from the rules side rather
195
- than only from the hook's absence.
193
+ `knowledge/shared/harness-core/field_verdict_crossfamily_gate.md §7`. 🟥 **CORRECTED 2026-08-20, then CORRECTED AGAIN the same hour.** This used to read "Still validated
194
+ by nothing — zero hook lines, no fixture suite", which is FALSE: `validate_standpoint_leg()` lives in
195
+ `templates/.git-hooks/pre-commit` (grep the function name — **line numbers are deliberately not cited
196
+ here; the first version of this fix cited `:798`/`:1575` and a commit landed the same hour that moved
197
+ them to `:878`/`:1665`**), and `scripts/test_marker_standpoint_lanes.sh` is wired through
198
+ `scripts/selfcheck.sh`.
199
+ 🟥 **But the first correction over-shot, and cross-family caught that too.** It said "the value enum
200
+ IS closed and the grounds ARE required". Only the first half holds. Measured by varying ONE variable
201
+ at a time — the original known-pair varied two and mis-attributed the result:
202
+
203
+ ```
204
+ standpoint: tier2(qasp) — ran <cmd>, saw <out> rc=0 ✅
205
+ standpoint: tier2(qasp) (no grounds) rc=0 ⚠️ warns, does NOT block
206
+ standpoint: tier2 (no parens) rc=1 ❌ not an enum member
207
+ standpoint: banana(qasp) rc=1 ❌ not an enum member
208
+ ```
209
+
210
+ So: **the enum is closed and enforced; the execution grounds for `tier2`+ are ADVISORY.** A marker can
211
+ still record `tier2` without naming a command and pass with a warning — that is the real remaining
212
+ gap, and it is narrower than "validated by nothing" and wider than "grounds are required". Neither
213
+ earlier sentence was accurate, and the accurate one required varying one variable at a time.
214
+ 🟥 **This same false claim stood in FIVE places**, not three — `CLAUDE.md` (twice), here, `AGENTS.md`,
215
+ and `field_verdict_crossfamily_gate.md`. Fixing one and stopping is the half-fix propagation failure;
216
+ fixing three and stopping was the same failure one round later. The question is never "is this
217
+ sentence wrong" but **"where else does this sentence live"** — and the answer came from a
218
+ different-family reviewer, not from me.
196
219
 
197
220
  **`thirdparty:` — ⓓ3자 대면의 자기 필드 (2026-08-17 신설).** ⓑ가 `standpoint:` 를 갖는 것과
198
221
  같은 형태다: `axes-run` 에는 포인터(`ⓓ=→thirdparty`)만 두고 값은 이 필드가 나른다.
@@ -11,13 +11,13 @@
11
11
  "plugins": [
12
12
  {
13
13
  "name": "fh-meta",
14
- "version": "2.6.0",
14
+ "version": "2.8.0",
15
15
  "description": "New in 2.2.0: BREAKING (gate): chamber step 6 now reads ACTUAL.md, not BUDGET.md — an in-flight chamber run whose actual cost sits in BUDGET.md blocks until the ACTUAL: line moves to tracks/_chamber/<slug>/ACTUAL.md (the runner prints the path). Why: BUDGET.md's pre-verdict hash IS the ordering witness, and step 6 hard-blocked until that same file changed, so every run that reached COMPLETE necessarily mutated a witnessed artifact and verify returned TAMPERED — the chamber's promotion condition was unsatisfiable by construction, not by strictness. Two roles (immutable witness / post-verdict calibration sink) had collided in one file; each was correct alone, so neither side's code showed the conflict. Also: ko-tech-writer Step 2/4-b scans are now calibration-backed (known-pair fixtures + reproducible command, shipped) — discrimination is proven, 'zero residue' is explicitly NOT; chamber lane suite 12 -> 33 including the runner x witness seam no test covered; chamber_run.sh now teaches the two-commit discipline (gate hashes and verdict hash must land in separate commits/PRs — it previously advised the opposite). New in 2.1.0: BREAKING (gate): `crossfamily: declined` in an Axes 2-3 marker now requires grounds naming a record path that RESOLVES on disk — bare `declined`, and `declined` justified by author judgment, are blocked at commit. Remedy: cite where the operator decision lives (e.g. `.. — operator declined sidecars, per knowledge/shared/rules/operational_adaptation.md`), or use `DEGRADED_PANEL_UNUSED` if a panel was reachable and you chose not to recruit it — which is what author judgment actually is. `declined` was the only enum value with no grounds requirement; a cross-family review then broke the first (vocabulary-grep) fix three ways — self-validating on the value's own token, vacuous keyword passes, and over-blocking real declinations in natural prose — so the check asserts a resolvable record instead of words. Also: standpoint axis gains `tier1b` (a STATIC read of a target repo, executed nothing) plus a decide-in-order procedure, after blind floor-tier sims graded pure cold-reads as `tier2` three rounds running; steel-quench Wave 1's sixth angle (gate-locality) gains the output-template row it never had, so a mandatory angle stops being structurally unreportable; verify-bidirectional gains category 5 (prescriptive doctrine statement); Sister Asset Protocol gains an active-adoption trigger; new resident doctrine — Mechanization Boundary, Local Execution First, Skeleton-not-Muscle, Expedition track, and this package's versioning policy. Hub meta-operations toolkit — 35 skills + 7 agents. New in 2.0.1: harness-doctor cadence hook, portability lint wired into pre-commit, branch_claim.sh claim-count-vs-tree-count warning, louder confidentiality-scan fail-open notice, fh-gate.sh missing-package.json survival, identity ① reclassified 🟢 (cross-harness adapters + relay argument channel). 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": "2.6.0",
20
+ "version": "2.8.0",
21
21
  "description": "Project-agnostic utility skills — 5 skills (convergence-loop · deliberation · mcp-circuit-breaker · token-budget-gate · ko-tech-writer) + 1 agent (quench-challenger). Domain-independent utilities transplantable into any project.",
22
22
  "source": "./plugins/fh-commons"
23
23
  }
package/AGENTS.md CHANGED
@@ -71,6 +71,10 @@ its file never declared at all.
71
71
  - **Runtime authority:** a non-Claude sidecar returns evidence candidates, never the terminal verdict.
72
72
  The governor must source-close each finding against a local file hit, literal source span, or
73
73
  passing check. Governor agreement alone is not an anchor.
74
+ - **Sidecar write boundary:** a sidecar audits; it does not write to the target tree. Return
75
+ findings, and at most a proposed patch as text — the governor applies it. This is not a
76
+ courtesy: measured 2026-08-21, an auditor sidecar edited the tree directly and its own fix
77
+ introduced a self-referential fail-open that 41 existing lanes passed.
74
78
  - **Sidecar completion:** judge a sidecar only by the typed verdict from `scripts/sidecar_wait.sh`.
75
79
  Never infer completion or emptiness by looking at its output file.
76
80
  - **Identity grades:** the five-identity grade table is canonical only in
@@ -127,9 +131,14 @@ Because non-Claude runtimes do not auto-load Claude path rules, apply these rule
127
131
  2 of the 4 circled-key markers on disk are dated 2026-08-10 and carry the OLD meanings. Aligning
128
132
  the notation still helps going forward; it does not work backwards.
129
133
  `standpoint:` remains the canonical field for ⓑ (the `axes-run` entry
130
- is only a pointer to it, and a pointer at an empty field is blocked); **its value enum is still
131
- validated by nothing** — that is the one remaining gap, and it is not the same thing as the axis
132
- being unmechanized. Format spec: `.claude/rules/fh_4axis_gate.md §Marker axis fields`.
134
+ is only a pointer to it, and a pointer at an empty field is blocked). 🟥 **CORRECTED 2026-08-20.** This used to say
135
+ "its value enum is still validated by nothing" FALSE. `validate_standpoint_leg()` in the
136
+ pre-commit hook enforces a closed enum. Measured by varying one variable at a time:
137
+ `standpoint: banana(qasp)` → **blocked (enum)** · `standpoint: tier2` without parens → **blocked
138
+ (enum)** · `standpoint: tier2(qasp)` with no execution grounds → **passes with a warning** ·
139
+ with grounds → **passes**. So the enum is enforced and the `tier2`+ execution grounds are
140
+ **advisory** — a first version of this correction said grounds were required, which over-shot.
141
+ The hook also cannot check whether `tier2` is **true**. Those two, together, are the gap. Format spec: `.claude/rules/fh_4axis_gate.md §Marker axis fields`.
133
142
  (Two drift corrections landed here on 2026-08-17: first this sentence said "four" while its own
134
143
  next clause described the +1 — caught by the session-close ④-b CC↔Codex parity check — and then
135
144
  the machine layer moved to six the same day.)
@@ -144,6 +153,22 @@ Because non-Claude runtimes do not auto-load Claude path rules, apply these rule
144
153
  `❌`. Execution is the half with no substitute; see `field_verdict_crossfamily_gate.md §7`. Read it before recording; §1-c
145
154
  holds the sample limits — read it before citing. This record is self-attested and has no hook
146
155
  behind it; it is closed by a different-family reader, not by writing it more carefully.
156
+ 🟥 **`axis2-defense:` — a marker field added 2026-08-20 that a Codex-side author WILL hit.**
157
+ It is required when the marker records `floor-status: sonnet-floor` or `below-floor`, and it carries
158
+ three sub-answers (on one line, or across continuation lines — the hook reads both) about **your own findings and numbers**:
159
+ `axis2-defense: reproducibility=<exact command or file:line another session runs> fairness=<reps,
160
+ inputs and environment named for BOTH arms> estimation-layer=<per number: measured | estimate |
161
+ quotation; for a measurement, what showed the instrument works on this target>`.
162
+ The hook (`validate_defense_leg`) checks **presence · completeness · non-vacuity** — `ok`/`yes`/
163
+ `n/a` is rejected as a filled form rather than an answer, and all three sub-answers must exist.
164
+ It cannot check whether the answers are true. Why it exists: measured n=6 in the origin field, a
165
+ floor-tier pass runs the attack angles without defect but does **not** spontaneously ask these
166
+ three; that is a checklist gap, not a capability gap, and a harness whose behaviour depends on
167
+ which model drives it is defective by the Sonnet-Floor doctrine.
168
+ Fixtures: `scripts/test_marker_defense_lanes.sh`. Spec: `plugins/fh-meta/skills/steel-quench/SKILL.md`
169
+ §Wave 1-D. **Recorded here because a rule living in only one entry point is invisible to the other
170
+ runtime** — that is the gate-locality principle, and this line is it being applied rather than cited.
171
+
147
172
  8. **Branch-surface claims:** GitHub branch protection is two independent layers — legacy
148
173
  protection and rulesets coexist, and the strictest wins. Read both
149
174
  `/repos/{owner}/{repo}/branches/{branch}/protection` and
package/CLAUDE.md CHANGED
@@ -43,7 +43,7 @@ core invariants never melt). The nursery also **verifies what it births**: harne
43
43
  | **③ AI Collaboration Guide** | Accumulates and distributes best practices for token efficiency and dialogue methodology — "how to ask, delegate, and record". | `CHEATSHEET.md` · `knowledge/shared/dialogue/ai_dialogue_playbook.md` · `MEMORY.md` intent-based + associative recall (`knowledge/shared/dialogue/memory_intent_recall.md`) |
44
44
  | **Core Axis** | **Harness Engineering (How)** — the methodology and practice axis that realizes the three layers above. The 6-axis framework is the operating unit. **A harness is a means, not an end** — Field harness: "simpler over time" (complexity = warning signal). Meta-harness: *optimize*, not necessarily simplify — complexity earns its scope; red flags are orphaned, redundant, and decorative units, not complexity itself. | `harness_6axis_framework.md` · `hub_compounding_loop.md` · `claude_code_runtime_flow.md` · `plugins/*/agents/` (sub-agents) |
45
45
 
46
- > **3층 정본 — 공정 · 엔진 · 정체성**: FH 를 설명하는 뼈대는 세 층이고 셋의 관계가 정본으로 적혀 있다 — **3단 공정**(엔진을 벼리는 순서: 초기 영혼 → 중간 탈상관 가속화 → **마무리 6축 태우기**) → **4대 엔진**(영혼·품질게이트·질문하기·맥락유지) → **5대 정체성**(사람이 실제로 쓰는 기능). 기억용 형태는 **3단 공정 · 4대 엔진 · 5대 정체성 · 6축 검증**이나 🟥 **6축은 네 번째 층이 아니다** — 3단 공정 ③단계가 무엇으로 이루어지는지다. **Read `knowledge/shared/harness-core/fh_three_layer_canon.md`** before naming, re-scoping, or citing any of the three — it also defines the **6 verification axes** (ⓐ계열 · ⓑ입장 · ⓒ격리 그라운딩 · ⓓ3자대면 · ⓔ첫실사용 · ⓕ되돌림; §1-a 가 최초 4축, §1-a-2 가 2026-08-16 확장) that the third stage actually consists of, and states why the three are *not* a clean stack. 🟥 **축은 «얼마나 적대적인가»가 아니라 «무엇을 받았는가»로 갈린다** — 받는 것이 같으면 리뷰어를 몇 명 붙여도 같은 사각이 남는다. 🟥 **명칭 충돌 — 이 파일 안에 「4축」이 두 개다.** §FH Improvement **4-Axis Auto-Gate** 의 4축(Axis 1 회귀 · 2 적대 · 3 팬텀 · 4 매니페스트)은 **커밋 게이트**이고, 여기 6축은 **검증 축**이다. 부분적으로만 겹치고(Axis 1·4 는 ⓐ~ⓕ 에 대응이 없다) **서로 대체하지 않는다**. 그래서 6축은 「6축 게이트」가 아니라 **「6축 검증」**으로 부른다. Grade table stays canonical in `ship_readiness_gate.md`; this pointer never carries grades.
46
+ > **3층 정본 — 공정 · 엔진 · 정체성**: FH 를 설명하는 뼈대는 세 층이고 셋의 관계가 정본으로 적혀 있다 — **3단 공정**(엔진을 벼리는 순서: 초기 영혼 → 중간 **병렬 탈상관** 가속화(두 다이얼 — **탈상관**=사각 위험[모델 계열 ⓐ + 입장 ⓑ] · **병렬**=표면 크기. 곱하지 말고 골라라) → **마무리 6축 태우기**) → **4대 엔진**(영혼·품질게이트·질문하기·맥락유지) → **5대 정체성**(사람이 실제로 쓰는 기능). 기억용 형태는 **3단 공정 · 4대 엔진 · 5대 정체성 · 6축 검증**이나 🟥 **6축은 네 번째 층이 아니다** — 3단 공정 ③단계가 무엇으로 이루어지는지다. **Read `knowledge/shared/harness-core/fh_three_layer_canon.md`** before naming, re-scoping, or citing any of the three — it also defines the **6 verification axes** (ⓐ계열 · ⓑ입장 · ⓒ격리 그라운딩 · ⓓ3자대면 · ⓔ첫실사용 · ⓕ되돌림; §1-a 가 최초 4축, §1-a-2 가 2026-08-16 확장) that the third stage actually consists of, and states why the three are *not* a clean stack. 🟥 **축은 «얼마나 적대적인가»가 아니라 «무엇을 받았는가»로 갈린다** — 받는 것이 같으면 리뷰어를 몇 명 붙여도 같은 사각이 남는다. 🟥 **명칭 충돌 — 이 파일 안에 「4축」이 두 개다.** §FH Improvement **4-Axis Auto-Gate** 의 4축(Axis 1 회귀 · 2 적대 · 3 팬텀 · 4 매니페스트)은 **커밋 게이트**이고, 여기 6축은 **검증 축**이다. 부분적으로만 겹치고(Axis 1·4 는 ⓐ~ⓕ 에 대응이 없다) **서로 대체하지 않는다**. 그래서 6축은 「6축 게이트」가 아니라 **「6축 검증」**으로 부른다. Grade table stays canonical in `ship_readiness_gate.md`; this pointer never carries grades.
47
47
 
48
48
  > **자기 대조는 상시 의무 — 트리거는 발화가 아니라 «지금 FH/PMH 자산을 건드리고 있다»**
49
49
  > (운영자 결정 2026-08-09; 이 저장소든 **다른 사용자의 install 이든** 동일). §FH Improvement
@@ -102,6 +102,19 @@ Two orthogonal layers — never collapse them.
102
102
  **not a floor** (no mechanical floor exists for tone — an accepted limitation, not a guarantee). The
103
103
  operator or project may pin a concrete default register in a local binding (`CLAUDE.local.md` / UAP
104
104
  `preferred register`) — that pin is operator taste and stays local, never in this public file.
105
+ 🟥 **A local pin sets REGISTER, never LANGUAGE — and the greeting decides the language outright.**
106
+ Reply in the language of the message you are answering; on a greeting turn, the greeting itself sets
107
+ it, **including the door labels and every menu line**, not just the prose around them. A pinned
108
+ default (`Korean 반말`, `English casual`) supplies the *register* to speak that language in — it does
109
+ not make the session answer `你好` in Korean. Half-translating (localized prose, English doors) is the
110
+ same defect in a milder form. **Measured 2026-08-21, blind, at the floor tier, one rep per arm**:
111
+ `こんにちは` → Japanese ✅ · `안녕` → Korean prose but **English door labels** 🟡 · `你好` → **Korean**
112
+ ❌ · control `hi` → English ✅. The control held, so the instrument discriminates and the defect is in
113
+ the wiring, not the measurement. 🟥 **The line above already said "not language-lock" and the floor
114
+ tier still read the pin as one** — which is why this now names the failure explicitly instead of
115
+ restating the principle. Honest scope: those arms ran in an install that *has* such a pin; whether a
116
+ clean consumer install ever had the defect is **unmeasured**, and one rep per arm is below this
117
+ repo's own `reps>=3` bar.
105
118
  - **Not flattery**: soft charisma is not pleasing the user. Disagree plainly when the work calls for it;
106
119
  warmth and a "no" coexist (no Gemini-grade sycophancy).
107
120
  - **Greeting / onboarding**: open with a warm, identity-revealing welcome (new / returning / operator
@@ -376,8 +389,18 @@ claim 이 `main` 인 동안 실제 HEAD 는 peer 브랜치였다 — 두 세션
376
389
  **남은 잔여 둘, 이름으로 남긴다**: ⓐ 게이트는 **커밋 시점**이라 `switch -c` 사고 자체는 못 막는다
377
390
  (그래서 위 두 줄이 여전히 사람 몫이다 — [[feedback_gate_binding_point_not_check_point]])
378
391
  ⓑ 반대 방향 — 내가 브랜치를 쥔 동안 남이 되돌리고 커밋하면 **내 staged 파일이 index 에 살아
379
- 있다.** 실측 사례에서 섞인 것은 세션이 파일 지정 `add` 를 썼기 때문이지 게이트 덕이 아니다.
380
- **공유 체크아웃에서 `git add -A` 금지**([[feedback_shared_checkout_ops_touch_others_work]]).
392
+ 있다.** 🟥 **2026-08-21 실제로 났고, 섞은 세션은 파일 지정 `add` 를 썼다**(초판은 여기 「파일
393
+ 지정 add 썼기 때문에 섞였다」고 적었는데 거짓이다). 파일 지정 add 는 «내가 무엇을
394
+ **추가**하나»만 통제하고 **index 에 이미 있는 것은 못 막는다.** ⇒ `git add -A` 금지는 필요조건
395
+ 이지 충분조건이 아니다. **커밋을 한 호출로 묶고 그 안에서 둘을 확인한다** — 확인은 점이고 위험은
396
+ 구간이라, 사이에 턴이 끼면 창이 다시 생긴다(같은 날 두 세션이 시점을 각각 `switch` 직전/직후로
397
+ 달리 골랐는데 **둘 다 뚫렸다**):
398
+ ```
399
+ B=$(git branch --show-current); [ "$B" = "<내 브랜치>" ] || exit 1
400
+ git diff --cached --name-only # 내 것만 있나 — 남의 것은 restore --staged
401
+ git commit …
402
+ ```
403
+ ([[feedback_shared_checkout_ops_touch_others_work]] · [[feedback_gate_binding_point_not_check_point]])
381
404
 
382
405
  **Integration branch is PR-only** (operator decision 2026-07-20). Never `git push origin main`
383
406
  directly. Normal path: `git switch -c <branch>` → push the branch → `gh pr create` → after review
@@ -390,47 +413,26 @@ so `--admin` after a completed review is the normal route, not a shortcut).
390
413
  feature-branch push passes untouched, override honored — over-blocking would just train the override
391
414
  into muscle memory and disarm it.
392
415
 
393
- > **Two layers, and which one is the floor**: the **hard floor is server-side** this repo now runs
394
- > `enforce_admins: true` with `required_approving_review_count: 0` (set 2026-07-20; the count must be
395
- > `0`, because enabling `enforce_admins` while it is `1` locks a solo operator out of merging their
396
- > own PRs self-approval is impossible). The hook is the **shift-left layer**: it fails at push time
397
- > and prints the actual remedy, and it keeps holding if the server setting is ever relaxed. It is
398
- > deliberately not the floor — a client-side hook is bypassable with `--no-verify`.
399
- > *Origin*: before that change the server had `enforce_admins: false`, so an admin push *satisfied*
400
- > the rule and merely printed `Bypassed rule violations` a notice, not a block. A rule that
401
- > announces its own bypass is not a floor.
402
- > **Retraction the server-side force-push surface is CLOSED, and the way it was misread is the
403
- > durable part.** An earlier version of this block said `allow_force_pushes` on `main` was "still
404
- > `true`", that two API writes "did not persist", and that the **server-side** history-rewrite
405
- > surface therefore "remains open". The field reading was correct; the conclusion was not.
406
- > **Branch protection is two independent layerslegacy protection and rulesets coexist, and the
407
- > strictest wins** so a field on the protection object is never the effective answer by itself.
408
- > Measured on this repo 2026-08-09: `GET /repos/{owner}/{repo}/rules/branches/main` returns
409
- > `non_fast_forward` from ruleset `main-no-force-push` — `enforcement: active`,
410
- > `current_user_can_bypass: never`, `bypass_actors: []`, live since 2026-07-25 — while the legacy
411
- > object still reports `allow_force_pushes: true`. The two API writes that "did not persist" were
412
- > writing to the layer that does not govern *this* outcome while the stricter ruleset is active not
413
- > a layer that is inert in general: disable or retarget the ruleset and the legacy toggle governs
414
- > again. **Read BOTH layers before declaring any branch surface open or closed** — `/rules/branches/
415
- > {branch}` shows only what the *rulesets* impose, and `/branches/{branch}/protection` only what
416
- > *legacy protection* imposes; neither is the effective view alone. A protection-object field read by
417
- > itself misjudged this three times ([[reference_github_protection_two_layers]]).
418
- > **Scope of the retraction, stated narrowly on purpose**: it covers *force-push / non-fast-forward*,
419
- > which is what `non_fast_forward` blocks. Branch **deletion** is a separate rule and is closed on the
420
- > other layer (`allow_deletions: false`, same GET). PR-routing is likewise a different field —
421
- > `required_pull_request_reviews` present with `enforce_admins: true` — not something
422
- > `required_status_checks` says anything about.
423
- > ⚠️ A *different* residual on `main` is still real and must not be folded into the one just
424
- > retracted — but the residual's own description was itself stale and needed correction on
425
- > 2026-08-12 (live re-check, `[[reference_github_protection_two_layers]]`): legacy
426
- > `required_status_checks.contexts` is **`["validate"]`**, not `[]` — a green `validate` check IS
427
- > required before a PR can merge, and `GET /rules/branches/main` carries no competing
428
- > `required_status_checks` rule, so the legacy field is the effective one here. `validate`
429
- > (`.github/workflows/validate.yml`) is a **separate job from Axis 1** (`regression-guard.yml`) —
430
- > Axis 1 is still not required, see the 4-axis section below. The gap on `validate` is
431
- > `strict: false`: that check re-runs on every push to the PR branch, but nothing re-forces it
432
- > against a **moving** main after it last ran — so a check that passed can still land behind
433
- > concurrent merges it never saw.
416
+ > **Two layers, and which one is the floor.** The **hard floor is server-side**: this repo runs
417
+ > `enforce_admins: true` with `required_approving_review_count: 0` (the count must be `0`, or a solo
418
+ > operator is locked out of merging their own PRs). The pre-push hook is the **shift-left layer** — it
419
+ > fails at push time and prints the remedy deliberately not the floor, since a client-side hook is
420
+ > bypassable with `--no-verify`.
421
+ >
422
+ > 🟥 **Branch protection is TWO independent layers legacy protection and rulesets coexist, and the
423
+ > strictest wins.** A field on the protection object is **never** the effective answer by itself.
424
+ > Read **both** before declaring any branch surface open or closed:
425
+ > `GET /repos/{owner}/{repo}/rules/branches/{branch}` (rulesets) **and**
426
+ > `GET /repos/{owner}/{repo}/branches/{branch}/protection` (legacy). Reading one alone misjudged this
427
+ > repo **three times** ([[reference_github_protection_two_layers]]).
428
+ >
429
+ > ⚠️ **Live residual on `main`**: `required_status_checks.strict: false`the required `validate` check
430
+ > re-runs on every push to the PR branch, but nothing re-forces it against a **moving** main, so a green
431
+ > check can land behind concurrent merges it never saw. And `validate` is **not** Axis 1.
432
+
433
+ > **Detail**: See `knowledge/shared/harness-core/claude_md_gate_details.md §Branch-Protection-Two-Layers`
434
+ > the force-push retraction and why it was narrow, which surface each layer actually governs, and the
435
+ > three misreadings read before asserting that any branch surface is open or closed.
434
436
 
435
437
  ## Permission-Denial Guidance (When Auto-Mode Blocks an Action)
436
438
 
@@ -454,6 +456,15 @@ Simplification guard: trivial denials with one obvious fix → state block + sin
454
456
  **4-step summary**: ① Auto-read CLAUDE.md + CATALOG + session card + registry scan + UAP (`tracks/_meta/user_adaptation_profile.md`, if present — apply user-tuned defaults: preferred tier, suppressed proposals, muted nags; see §Operational Adaptation Loop) **+ Mode D companion-store load — if a companion store is configured (your `CLAUDE.local.md` binding), pull it and read its index (its TOC) before its other files, then check freshness against the card (`modes_and_value.md §Session-start freshness`); this load is part of the auto-read, not a step the operator should have to request** → ② One-line proposal (new user / exploratory / returning branches) → ③ 5-skill cascade (plugin-recommender → synergy → .claudeignore → model → verify) → ④ Approval + setup
455
457
 
456
458
  **Greeting branch + door skeleton (summary-level — applies even if the detail file read is skipped)**: the branch test is **mechanical local state — session files under `tracks/`** — never git log / CATALOG residue (a fresh clone carries full history but zero session files: it is a NEW install). Every variant opens with **🐿️ then an identity-revealing welcome line on the SAME line**, followed by the menu — one salience unit, not a separate rule. The verifiable invariant is *same-line*, **not** a space count. Welcome line by branch: new / exploratory = "Welcome to FH." · returning = "Welcome back to FH." · operator (FH-dev state) = "The FH operator — good to see you." — rendered in the user's language as a **plain, natural translation of the pinned phrase, never an invented coinage**. (Why each of these reads as it does — the fresh-clone FP, the space-count retraction, the mistranslation: `fh_detail_protocols.md §Onboarding-Provenance`.)
459
+ 🟥 **The door labels below are written in English because this file is; they are NOT literals to copy.** Render the welcome line **and every door label** in the greeting's language — `你好` gets Chinese doors, `こんにちは` Japanese ones. Only the ①②③④/🔧/📖 markers, skill names and file paths stay as written. 🟥 **Measured 2026-08-21, blind, floor tier, two rounds of wiring — and it did NOT converge. The note stays anyway; read why.** Round 1 (rule in §Voice/Tone only): `こんにちは`→Japanese ✅ · `안녕`→Korean prose but **English doors** 🟡 · `你好`→**Korean** ❌ · control `hi`→English ✅. Round 2 (rule repeated here, at the doors): `你好`→**Korean** ❌ · `嗨`→**English** ❌ · `こんにちは`→Japanese ✅ · control `hey`→English ✅. Across both rounds **Japanese 3/3, Chinese 1/5**, control clean every time — so the instrument discriminates and the gap is real. **Two distinct failure modes**, and only one of them is the pin: a Korean reply is the operator pin winning, an *English* reply is these door literals being copied. Repeating the rule at the actor's location — textbook gate-locality — moved neither. 🟥 **So do not read this note as a fix.** It is a correct instruction with **no mechanical floor** (tone/language never has one, §Voice/Tone says so), kept because it is right and cheap, and labelled failing because pretending otherwise is the muscle-not-skeleton defect this repo names. The README's user-facing wording was reduced to match this measurement rather than the intent. 🟥 **The clean-install arm has since been RUN, and it reattributes the defect (same day).** A shallow
460
+ clone with no `CLAUDE.local.md` — known-positive control: it answered a CLAUDE.md-only question
461
+ correctly; known-negative: it refused to invent a nonexistent concept, so the harness was genuinely
462
+ loaded — greeted `你好` and `嗨` with **fully Chinese** door menus, and `안녕` with a **fully Korean**
463
+ one, doors included. So the operator's language pin was the **main cause**, and the 1/5 figure above is
464
+ a property of *this* install, not of a consumer's. **Do not cite 1/5 as the shipped behaviour.**
465
+ ⚠️ What did *not* close: firing is **non-deterministic** — one Chinese variant (`你好呀`) produced no
466
+ menu at all, and one Korean run opened with an English welcome line. Reps are 1–3 per arm, below this
467
+ repo's own bar. So the softened README wording stays correct; only its *reason* changed.
457
468
 
458
469
  - **New user** (no session files AND no mapped project tracks under `tracks/` — fresh clone/install; **any underscore-prefixed dir** (`tracks/_*` — `_meta`/`_audit`/`_contrib`/`_chamber`…) doesn't count, general rule not a closed list — `_chamber` holds incubation chamber runs, never mapped projects): 2-door starter, never the returning menu —
459
470
 
@@ -591,58 +602,35 @@ runtime (local wiring visible, not independent) · `tier3(<harness>)` a *differe
591
602
  target harness ran it · `not-applicable` · degrade triad `DEGRADED_NO_TARGET_ACCESS` could-not /
592
603
  `DEGRADED_NOT_RUN` did-not / `UNKNOWN` did-not-look — same shape as `crossfamily:`'s triad,
593
604
  **distinct literal values**, do not reuse crossfamily's tokens).
594
- 🟥 **Settle the TARGET CLASS(es) before the tier — §7's `Q0`, added 2026-08-17 (operator decision).**
605
+ 🟥 **Settle the TARGET CLASS(es) before the tier — §7's `Q0` (operator decision 2026-08-17).**
595
606
  A consumer install **is** another harness; what the enum scopes is not who *receives* the change but
596
- where it has to be **executed**. Q0 is **not first-match — it can return more than one target, and
597
- each owes its own tier**: ⓐ a **named peer** whose local repo carries the changed surface, or which
598
- the cluster registry / a `scripts/adapters/` entry names (decide by that test, not from a name list)
599
- → the enum as written · ⓑ the delta changes **consumer-visible behavior** (what a consumer's gate
600
- blocks or passes, what their session is told to do, what an install receives) → target = a *clean
601
- install of the packed artifact*, and it binds **now, pre-push — never deferred to the eventual
602
- release** · ⓒ neither → `not-applicable`. 🟥 Do **not** read «no cross-repo consumer contract» as
603
- «this file is not shipped» measured, **194/200 recent non-merge commits touch a shipped path (97%,
604
- all 6 exceptions hand-verified)**, so shipped-ness cannot be the discriminator; the behavior clause
605
- is. Pricing the axis at that rate is the **over-triggering** §7's own Trigger paragraph rejects.
606
- ⚠️ 97% measures **the reach of the discarded shipped-path argument**, not the applicability rate —
607
- how often ⓑ actually fires is **unmeasured in both tails** (it could also land near-universal, which
608
- would be a rubber stamp watch the next 20 markers). 🟥 Do **not** cite
609
- `[[feedback_unreachable_done_when_trains_evasion]]` here: that memory concerns an unreachable *pass
610
- condition*, and `not-applicable` is an *exemption* — the direction inverts. Three marker-audit legs all failed at that reading;
611
- they were **not** decorrelated (same family · same prompt · same canon) so that is one observation,
612
- not three. ⚠️ The consumer-install arm's *presence* half is mechanized at ship time; its
613
- **execution** half (extract the tarball, run the gate, record command + output) has **no lane** —
614
- do it by hand, and do not cite that arm as mechanized.
615
- 🟥 **The execution is the load-bearing half** (operator decision 2026-08-16): a static standpoint
616
- read competes with cross-family review for the same defect classes and mostly loses *running the
617
- target harness locally, to completion*, is the part with no substitute. Measured on one delta the
618
- same day: static read found 1, running the target's own suite found 2 more, one of which printed
619
- neither `FAIL` nor `❌` and was unreachable by any read. So **`tier2`+ asserts something was RUN** —
620
- if the review only read, it is `tier1b`, and `tier1b` is deliberately the weak rung so that
621
- recording it honestly surfaces that the execution arm is still owed. (Broken on the day it was
622
- written a static read was recorded as `tier2` because `tier1b` did not yet exist; a missing rung
623
- gets filled by the next one up rather than staying empty.) Naming note: this collides in
624
- English with FH's own persona/viewpoint sense of "standpoint" (`fh-meta:beginner`/`main-player`/
625
- `expert`) — a different axis (which persona reviews, not whose repo is ground truth); kept as-is,
626
- not renamed, but do not conflate the two. 🟥 **CORRECTED 2026-08-20 — this paragraph used to say
627
- `standpoint:` was "Prose-only today — no pre-commit hook or fixture suite validates this field yet".
628
- That is FALSE and was false in this same file**: `validate_standpoint_leg()` is defined at
629
- `templates/.git-hooks/pre-commit:798` and called at `:1575`, and its fixture suite
630
- `scripts/test_marker_standpoint_lanes.sh` is wired through `scripts/selfcheck.sh:531`. §자기 대조
631
- above already said so (PR #429), so **one file carried both claims at once** and a reader landed on
632
- whichever they reached first. Found by the residency-ledger pass, not by a lane — no check compares
633
- a rule's self-description against the machinery it describes, which is why a stale "we have not
634
- built this yet" is the quietest form of drift: it reads as honest modesty and it suppresses use of a
635
- control that already exists. **What is validated is FORM, not truth** — the hook checks that the
636
- value is inside the closed enum and that its grounds are non-empty; whether `tier2` is *true* is
637
- still self-attested, exactly as with `crossfamily:`. That residual is real and unchanged; it is the
638
- sentence above that was wrong, not the caution. Three artifacts, one carrying two
639
- independent trials (forge-harness PR #368, a sibling field harness's PR #8 reps=3 and its
640
- known-answer trial, qasp-dev PR #161 as adjacent corroboration) crossed this repo's own evidence
641
- bar the same day this was formalized — including one caught by this session's own qasp PR #161
642
- review, not fed in externally, and a second live demonstration the same day when a cross-harness
643
- standpoint review of this very section caught real residency and citation defects in the first
644
- draft (fixed in the same commit that added this line).
645
-
607
+ where it has to be **executed**. Q0 is **not first-match — it can return more than one target, and each
608
+ owes its own tier**: ⓐ a **named peer** whose local repo carries the changed surface, or which the
609
+ cluster registry / a `scripts/adapters/` entry names the enum as written · the delta changes
610
+ **consumer-visible behavior** (what a consumer's gate blocks or passes, what their session is told to do,
611
+ what an install receives) → target = a *clean install of the packed artifact*, and it binds **now,
612
+ pre-push — never deferred to the eventual release** · ⓒ neither → `not-applicable`.
613
+ 🟥 Do **not** read «no cross-repo consumer contract» as «this file is not shipped» — shipped-ness is
614
+ **not** the discriminator; the behavior clause is. ⚠️ The consumer-install arm's *presence* half is
615
+ mechanized at ship time; its **execution** half has **no lane** do it by hand, and never cite that arm
616
+ as mechanized.
617
+
618
+ > **Detail**: See `knowledge/shared/harness-core/field_verdict_crossfamily_gate.md §Q0-Evidence`
619
+ > the 97% shipped-path measurement and what it does *not* say, plus two citation warnings that
620
+ > three marker-audit legs got wrong read before citing any number from this paragraph.
621
+
622
+ 🟥 **The execution is the load-bearing half** (operator decision 2026-08-16). A static standpoint read
623
+ competes with cross-family review for the same defect classes and mostly loses; *running the target
624
+ harness locally, to completion*, is the part with no substitute. **So `tier2`+ asserts something was RUN**
625
+ the discriminator is mechanical: **name the command you ran and the output you saw.** Cannot name one →
626
+ `tier1b`, always. Reading the target's real files, however cold, is `tier1b`; that rung is deliberately
627
+ the weak one so that recording it honestly surfaces that the execution arm is still owed.
628
+
629
+ > **Detail**: See `knowledge/shared/harness-core/field_verdict_crossfamily_gate.md §Standpoint-Execution-Evidence` the measured
630
+ > one-delta comparison, the two RETRACTED citations this paragraph used to carry, the English naming
631
+ > collision with FH's persona sense of "standpoint", and the 2026-08-20 correction about what the hook
632
+ > actually validates (the enum, not the grounds) read before citing this paragraph's evidence or
633
+ > claiming what `standpoint:` enforces.
646
634
  > **Detail**: See `knowledge/shared/harness-core/field_verdict_crossfamily_gate.md` — the discretion
647
635
  > principle, the four-faces failure signature, why same-family review misses it, the full gate
648
636
  > mechanics, the n=7 qasp field evidence incl. the **9 default-toward-PASS holes across 3 harnesses**
@@ -824,7 +812,8 @@ deleted branch was carrying).
824
812
  **When this gate fires** — *before* any of: branch deletion (local or remote), history rewrite /
825
813
  force-push, scrub of tracked history, bulk deletion of session records / tracks content.
826
814
 
827
- 1. **Enumerate (measured)**: `bash templates/predelete_check.sh <repo> [base]` per branch: commits
815
+ 1. **Enumerate (measured)** 🟥 **this step is run BY A HUMAN; no hook executes it** (measured
816
+ 2026-08-20, residency-ledger pass): `bash templates/predelete_check.sh <repo> [base]` — per branch: commits
828
817
  off base + unique paths. Verdicts: SAFE (fully merged) · CHECK (0 unique paths but commits off
829
818
  base — shared files may hold *newer* content, e.g. an unmerged session card) · REVIEW (unique
830
819
  paths — recovery mandatory).
@@ -845,6 +834,15 @@ prose gate is now stopped); it does **not** close the injected/adversarial one
845
834
  or errors, this irreversible surface **fails closed** — the pre-push hook blocks (enumerate by hand or
846
835
  take the explicit `DESTRUCTIVE_OP_OK=1` override); a tooling-down enumerate step never silently degrades
847
836
  into "just delete it."
837
+ 🟥 **Read that precisely — the floor is the HOOK, not this script.** `templates/.git-hooks/pre-push`
838
+ implements the per-ref verdict **inline**; it does not call `predelete_check.sh`. Measured 2026-08-20
839
+ (control: the same scan finds `session_close_check` wired in that hook): every in-repo reference to
840
+ `predelete_check.sh` is a **mention, not an execution** — `pre-push:408` lists the path inside a *grep
841
+ pattern*, `destructive_pre_gate.sh:191` *prints the command* as advisory text, and `selfcheck.sh:192`
842
+ runs `bash -n` on it. So the script is the **operator's enumerate tool**, and step 1 above is a human
843
+ step that the machinery reminds you of rather than performs. Stating it the other way round is the
844
+ "prose-invoked floor" the 4-axis marker spec calls M-tier when a rule claims a floor its script has
845
+ no caller for — this section does not make that claim, and this note keeps it from drifting into one.
848
846
 
849
847
  > **Detail**: See `knowledge/shared/harness-core/claude_md_gate_details.md §Destructive-Op-Hook-Coverage`
850
848
  > — the per-ref verdict mechanics, what the hook does/does not close (honest scope + adversarial residual),
@@ -1005,7 +1003,7 @@ Self-healing is not only FH-self-dev (Mode D 4-axis) and reactive (`verify-bidir
1005
1003
 
1006
1004
  ## Agent Dispatch Operation (FH cwd-Based)
1007
1005
 
1008
- > **Runtime authority (canonical):** one explicit governor per context + capability-routed sidecars; sidecar findings are evidence candidates, not terminal verdicts, until source-closed by the governor *via a mechanical anchor* — never governor agreement alone. CC=action/governor · Codex=repo-grounded audit sidecar · Gemini/agy=breadth/multimodal sidecar · other runtimes=portable `AGENTS.md` entrypoint only. Full doctrine + Maintenance-Cost Rule: `knowledge/shared/harness-core/multi_model_sidecar_strategy.md §Runtime Authority`.
1006
+ > **Runtime authority (canonical):** one explicit governor per context + capability-routed sidecars; sidecar findings are evidence candidates, not terminal verdicts, until source-closed by the governor *via a mechanical anchor* — never governor agreement alone. 🟥 **A sidecar audits; it does not WRITE to the target tree** — findings and at-most a proposed patch as text, applied by the governor (measured 2026-08-21: an auditor sidecar edited the tree and its fix introduced a self-referential fail-open that 41 lanes passed). CC=action/governor · Codex=repo-grounded audit sidecar · Gemini/agy=breadth/multimodal sidecar · other runtimes=portable `AGENTS.md` entrypoint only. Full doctrine + Maintenance-Cost Rule: `knowledge/shared/harness-core/multi_model_sidecar_strategy.md §Runtime Authority`.
1009
1007
 
1010
1008
  **Isolated delegation is a component of the identity, not an optional extra** (operator decision,
1011
1009
  2026-08-08). FH/PMH are defined as governor + orchestrator; a harness that cannot dispatch is a
@@ -1020,19 +1018,15 @@ dispatching.** ⓐ the user saying not to, *in this environment* — a veto of *
1020
1018
  Under a conditional, silence is not permission. ⓐ is FH's own default being withdrawn by its owner;
1021
1019
  ⓑ is a sentence in a layer FH does not author. Do not read them as one operation.
1022
1020
 
1023
- ⚠️ **Neither direction has a confirmed hook-level floor. Say that plainly rather than implying one.**
1024
- ```
1025
- opening salience only for the POSTURE. The prohibition met in the field is CONDITIONAL,
1026
- which changes what "override" even means see the measured block below.
1027
- blocking ALSO not hook-enforced. `SubagentStart` fires on spawn but is **context-only**
1028
- it cannot block, exit 2 only surfaces stderr, and it has no decision field
1029
- (official hooks reference, read 2026-08-08). It can INJECT context at the moment
1030
- of dispatch, which is better-placed salience than this file, but still salience.
1031
- UNVERIFIED whether a `permissions` deny entry or a `PreToolUse` matcher can target subagent
1032
- spawning at all — the reference does not name a tool for it, and this repo has no
1033
- precedent. **Do not cite a blocking mechanism until someone runs the known pair**
1034
- (configure the deny, attempt a dispatch, observe). Until then: unverified, not absent.
1035
- ```
1021
+ ⚠️ **Neither direction has a confirmed hook-level floor say that plainly rather than implying one.**
1022
+ Opening (the posture) is salience-only. Blocking is **also** not hook-enforced: `SubagentStart` fires on
1023
+ spawn but is **context-only** it cannot block and has no decision field. Whether a `permissions` deny
1024
+ entry or a `PreToolUse` matcher can target subagent spawning at all is **UNVERIFIED** — unverified, not
1025
+ absent. 🟥 **Do not cite a blocking mechanism until someone runs the known pair.**
1026
+
1027
+ > **Detail**: See `knowledge/shared/harness-core/dispatch_conditional_prohibition.md §Hook-Floor-Unverified`
1028
+ > the per-direction table and what each `UNVERIFIED` line covers — read before claiming any floor here.
1029
+
1036
1030
  **The conditional line, and what a session must do about it.** Some runtimes ship the default
1037
1031
  *"Do not call the AgentTool unless the user requested it"* (with a workflows/deep-research twin).
1038
1032
  Measured 2026-08-09 on this machine: it is **not** a hard-coded constant and **not** global — it is
@@ -1099,14 +1093,10 @@ instruction-shaped. A self-test the session administers to itself is the thing
1099
1093
  > order, the model-bundle gate, the calibrated where-it-is-not table, and the reproduction commands.
1100
1094
  > **Read it before citing any of these numbers or claiming the line is absent from a surface.**
1101
1095
 
1102
- An earlier draft of this very block asserted "a `SubagentStart` hook can deny, and a denial there is a
1103
- real floor." That was false, taken on trust from an adjacent session and written here before the
1104
- reference was read. A second draft, on 2026-08-09, then wrote that the constant's call site "needs
1105
- binary inspection, which was blocked" — **also false**: three plain `grep` calls resolved it, and an
1106
- adversarial reviewer demonstrated that by doing it. Declaring something unmeasurable before trying the
1107
- cheap tool is [[feedback_impossible_verdict_may_be_unread_half]]; the honest label is *"not yet
1108
- measured,"* never *"blocked."* A blind target-tier sim then read it back correctly — which shows a sim measures
1109
- whether text is *followable*, never whether it is *true*. Both checks are needed; neither substitutes.
1096
+ 🟥 **This block has been wrong twice, both times by asserting more machinery than existed.**
1097
+ > **Detail**: See `knowledge/shared/harness-core/dispatch_conditional_prohibition.md §Retraction-SubagentStart` both retractions and
1098
+ > what each teaches (*"not yet measured"* is the honest label, never *"blocked"*) read before adding a
1099
+ > mechanism claim to this section.
1110
1100
 
1111
1101
  So "default-active" is a **posture, not a guarantee**. Measured 2026-08-08: a session running under
1112
1102
  exactly that system-prompt instruction worked alone for a full session and dispatched only at the two
@@ -1142,28 +1132,28 @@ Three execution paths:
1142
1132
 
1143
1133
  **Why not Agent View by default**: Agent View introduces worktree isolation (blocks settings.json writes, Stop hook timing differs), session context gaps (session card stale content bug), and path friction — with no benefit unless the user is actively managing multiple agent sessions. Parallel agents via `Agent` tool work identically in a standard session.
1144
1134
 
1145
- **Fourth reason — gate-integrity in a worktree, and the answer is CONDITIONAL on how `core.hooksPath`
1146
- was set (measured 2026-08-05, both arms).** Do not carry a single verdict here; the two installs
1147
- behave differently:
1148
-
1149
- | `core.hooksPath` | Which hook actually runs in a worktree | Consequence |
1150
- |---|---|---|
1151
- | **relative** — `templates/.git-hooks`, the form every FH doc installs (`CHEATSHEET.md`, `.claude/rules/fh_4axis_gate.md`, `install-wizard`, `self_evolution_routine.md`) | the **worktree's own copy** | Editing that copy *inside the worktree* disables the gate for that worktree — measured: neutralized hook → FH-asset commit with no marker succeeded (`rc=0`). The verifier becomes the verified, and the edit is invisible to `git status` in the main tree. |
1152
- | **absolute** a hand-set full path (this operator's machine; **not** what any doc tells you to run) | the **main tree's copy** | A worktree-local edit has no effect; a known-positive is blocked there exactly as in the main tree (`rc=1`). |
1153
-
1154
- An earlier draft of this section reported only the absolute-path arm and declared the
1155
- "worktree bypasses the gates" hypothesis *refuted* from **n=1 on a non-canonical setting**, with a
1156
- do-not-revisit label attached. The relative-path arm, which is what everyone else runs, reproduces
1157
- the bypass. Freezing a conclusion is a defect when the measurement did not cover the shipped
1158
- configuration.
1159
-
1160
- Separately and in **both** arms, the **evidence side** breaks: `tracks/` is gitignored, so it does not
1161
- follow into a worktree, so the Axis 2+3 marker and the Axis 4 `edit_manifest.yaml` are *structurally
1162
- absent* an FH-asset commit in a worktree fails on evidence it has no way to have. That degrades
1163
- fail-closed (correct), but a gate that **cannot** be satisfied is what trains the bypass. Note the
1164
- hook itself prints `mkdir -p …/tracks/_meta` on that failure, i.e. the actor's own error message
1165
- teaches the marker-creation path so "just don't fabricate it" is prose sitting under a machine
1166
- instruction pointing the other way.
1135
+ **Fourth reason — gate-integrity in a worktree, and it is CONDITIONAL on how `core.hooksPath` was set.**
1136
+ With the **relative** form every FH doc installs, the worktree runs **its own copy** of the hook — editing
1137
+ that copy there disables the gate for that worktree (measured 2026-08-05: marker-less FH-asset commit
1138
+ succeeded). With a hand-set **absolute** path it runs the main tree's copy and the bypass does not exist.
1139
+ 🟥 **RETRACTED 2026-08-22.** This said the marker and manifest are *structurally absent* in a
1140
+ worktree. They are not: `templates/.git-hooks/pre-commit` resolves evidence through
1141
+ `git rev-parse --git-common-dir`, which returns the **main tree's** `.git` from inside a worktree.
1142
+ Measured in a clean worktree with the known-negative established first (its own `tracks/` = skeleton
1143
+ only; `$REPO_ROOT/tracks/_meta/edit_manifest.yaml` NOT FOUND, `$EVIDENCE_ROOT/...` FOUND — the two
1144
+ roots disagree, so the probe discriminates).
1145
+ **The operating rule is UNCHANGED: do not commit FH assets from a worktree.** Its remaining **open risk areas** — not
1146
+ established grounds are marker provenance, concurrent manifest append, and a copy of `tracks/` that
1147
+ appears in a worktree from an unattributed source. They are **deliberately not enumerated as reasons
1148
+ here**; an earlier draft enumerated
1149
+ them and adversarial review found a defect in nearly every added claim. ⚠️ **Reachable is not automatic**: the hook *reads* `$EVIDENCE_ROOT`, but a
1150
+ worktree session writing by relative path lands in the worktree's own `tracks/`, not the main tree's.
1151
+ The gate is satisfiable its failure message prints the absolute `MARKER_DIR` to write to — but the
1152
+ routing is the author's job, not the tool's.
1153
+
1154
+ > **Detail**: See `knowledge/shared/harness-core/dispatch_conditional_prohibition.md §Worktree-Gate-Integrity` the two-arm table with
1155
+ > exit codes, and why an earlier draft declared the bypass *refuted* from n=1 on a non-shipped setting —
1156
+ > read only when you must determine which arm your own install is on.
1167
1157
 
1168
1158
  **Therefore: do not commit FH assets from a worktree.** Not "carry the evidence in carefully" — a
1169
1159
  carried marker and a fabricated one are byte-identical, so *marker provenance* is unenforceable by
@@ -1310,36 +1300,24 @@ Closing phrase detected ("wrap up", "done", "good work", "end session", etc.)
1310
1300
  `package.json`) → Pre-Publish gate → `npm publish` → `git tag vX.Y.Z` at publish. **Propose, don't
1311
1301
  auto-publish.** (Why lockstep — Codex caches on plugin.json version — + drift-check + tag-drift caveat → §detail below.)
1312
1302
 
1313
- 🟥 **WHICH DIGIT — operator decision 2026-08-17, and it is deliberately NOT strict semver.**
1314
- There was no policy before this line, which is why one session proposed three different bumps
1315
- for the same delta on three different (and each individually defensible) grounds. Decide by
1316
- **what the number tells a reader**, not by whether anything technically broke:
1303
+ 🟥 **WHICH DIGIT — 운영자 결정(2026-08-17). 의도적으로 strict semver 아니다.**
1304
+ 판단 기준은 **무엇이 기술적으로 깨졌나**가 아니라 **번호가 읽는 이에게 무엇을 말하나**다.
1317
1305
 
1318
- | Bump | Reserved for (operator's own wording, 2026-08-17) |
1306
+ | major `+1.0.0` | 완전히 새로 지음 · ⓑ 정체성 **다섯이 «전부» 🟢**(= `identity-v1.0.0` 사건. 🟥 하나가 🟢 로 올라선 순간이 **아니고**, 정체성 등급은 npm 이 나르는 신호가 **아니다**) · ⓒ capability **class** 가 생기거나 교체됨. 🟥 **이미 있던 게이트를 조인 것에는 절대 안 쓴다** |
1319
1307
  |---|---|
1320
- | **major** `+1.0.0` | **any one of three**: **완전히 새로 지음** rebuilt from scratch, not extended · **정체성이 확립됨** an identity of the five (+Ⓑ) actually standing 🟢, not progressing toward it · ⓒ **기능이 혁신적으로 변경되거나 늘어남** — a capability *class* appears or is replaced, not a capability instance. 🟥 **Never** for tightening a gate that already existed |
1321
- | **minor** `+0.1.0` | 미들급 new assets, new gate lanes, doctrine that changes behavior; **including changes that break a consumer's gate acceptance**, which then carry a mandatory `BREAKING (gate):` line |
1322
- | **patch** `+0.0.1` | 트리비아급 — fixes, wiring, docs that change no behavior |
1323
-
1324
- **The discriminator between major-ⓒ and minor**: *class* vs *instance*. A sixth Wave-1 attack
1325
- angle is an instance → minor. An attack-angle **registry** where none existed is a class → major.
1326
- Today's delta is instances and tightenings throughout, which is why it is 2.1.0 and not 3.0.0
1327
- even though it breaks a gate acceptance.
1328
-
1329
- **Why gate-tightenings are minor here, stated so it is not mistaken for hiding a break**: what
1330
- breaks is the **record format of a gitignored local marker**, not an API or the consumer's code;
1331
- the hook prints exactly what to write instead; and the blast radius needs the consumer to have
1332
- installed the hook AND be making a load-bearing change AND have used the specific old form.
1333
- Against that, strict semver would burn a major on every gate we tighten — this repo took 2.0.0
1334
- for a publish-freshness gate one day and would have taken 3.0.0 for a commit gate the next.
1335
- **A major number that arrives monthly stops meaning anything**, and the milestone it should be
1336
- reserved for would have no word left.
1337
-
1338
- ⚠️ **The condition that makes this honest, and it is not optional**: a minor that breaks gate
1339
- acceptance MUST carry `BREAKING (gate): <what now blocks> — <the one-line remedy>` in the
1340
- release description AND the CHANGELOG. Without it this policy is just burying breaks in minors.
1341
- **Applies from 2026-08-17 forward, not retroactively** (2.0.0 was the same class and is left
1342
- as-is rather than rewritten).
1308
+ | **minor** `+0.1.0` | 자산 · 게이트 레인 · 행동을 바꾸는 교리. **소비자의 게이트 수용을 깨는 변경도 여기**대신 `BREAKING (gate):` 줄이 의무 |
1309
+ | **patch** `+0.0.1` | 수정 · 배선 · 행동 무변경 문서 |
1310
+
1311
+ 🟥 **major-ⓒ 와 minor 의 판별자 = *class* 냐 *instance* 냐.** Wave-1 공격각 하나 추가 =
1312
+ instance minor. 공격각 **레지스트리**가 없던 자리에 생김 = class major.
1313
+
1314
+ ⚠️ **의무**: 게이트 수용을 깨는 minor 릴리스 설명 **과** CHANGELOG
1315
+ `BREAKING (gate): <무엇이 이제 막히나> <한 줄 처방>` 를 반드시 싣는다. 이 줄이 없으면
1316
+ 이 정책은 그냥 «minor 에 파괴적 변경을 묻는 것»이다. 2026-08-17 부터 적용, 소급 아님.
1317
+
1318
+ > **Detail**: See `knowledge/shared/harness-core/claude_md_gate_details.md §Version-Digit-Policy`
1319
+ > strict semver 아닌지, 3.0.0 뻔한 판례, 게이트-조임을 minor 두는 근거와
1320
+ > 정직성 조건 **버전 자릿수를 실제로 정할 읽어라.**
1343
1321
  → ④-c Handoff lifecycle (cross-machine continuity) — when a durable **result artifact lands** this
1344
1322
  session (mechanical hint: a new `*result*`/`*signal*`/`*_run_*` file in your companion store or
1345
1323
  `tracks/`), do two things: **(a) ④-c stamps** any `"run this/start here"` run-handoff whose