@chrono-meta/fh-gate 1.4.59 → 1.4.61

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 (32) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/CATALOG.md +83 -0
  3. package/CHEATSHEET.md +15 -2
  4. package/CLAUDE.md +143 -224
  5. package/README.ja.md +8 -7
  6. package/README.ko.md +7 -6
  7. package/README.md +36 -17
  8. package/README.zh.md +5 -5
  9. package/bin/fh-codex-doctor.js +34 -3
  10. package/bin/fh-gate.js +17 -5
  11. package/bin/fh-goal.js +13 -5
  12. package/bin/fh-run.js +13 -5
  13. package/knowledge/shared/harness-core/claude_md_gate_details.md +88 -1
  14. package/knowledge/shared/harness-core/fh_detail_protocols.md +2 -2
  15. package/knowledge/shared/harness-core/field_harness_diagnostic.md +48 -0
  16. package/knowledge/shared/harness-core/measurement-integrity-checklist.md +9 -2
  17. package/knowledge/shared/harness-core/multi_harness_evolution_loop.md +66 -0
  18. package/knowledge/shared/harness-core/onboarding_acceleration_autopilot.md +82 -0
  19. package/package.json +2 -1
  20. package/plugins/fh-commons/.claude-plugin/plugin.json +1 -1
  21. package/plugins/fh-meta/.claude-plugin/plugin.json +2 -2
  22. package/plugins/fh-meta/skills/fh/SKILL.md +71 -0
  23. package/plugins/fh-meta/skills/harness-doctor/SKILL.md +109 -10
  24. package/plugins/fh-meta/skills/salience-splitter/SKILL.md +1 -1
  25. package/plugins/fh-meta/skills/verify-bidirectional/SKILL.md +3 -3
  26. package/scripts/count_check.sh +8 -1
  27. package/scripts/fh-gate.sh +150 -13
  28. package/scripts/fh-goal.sh +46 -5
  29. package/scripts/fh-run.sh +11 -0
  30. package/scripts/selfcheck.sh +40 -10
  31. package/scripts/test_fh_gate_regressions.sh +208 -0
  32. package/templates/local_fh_context.md +1 -1
package/README.md CHANGED
@@ -72,6 +72,18 @@ claude
72
72
  > ✅ Claude reads `CLAUDE.md` and asks what project to connect or what task to start.
73
73
  > Say **"Connect a project"** → hub scans `../`, finds `.git` directories, creates `tracks/{project}/`.
74
74
 
75
+ **Your first 15 minutes** — what success looks like, and what to do with it:
76
+
77
+ 1. You'll know setup worked when a greeting ("hi") shows the 🐿️ door menu, and "Connect a project"
78
+ creates `tracks/{your-project}/`.
79
+ 2. Then grab an immediate win in the same session: say **"accelerate this project"** (ranked plan of
80
+ skills/plugins worth wiring, install-gated) or **"run /context-doctor"** (token-waste scan).
81
+ 3. One honest note: FH's core payoff is **compounding** — session records, harvested learnings,
82
+ cross-session memory. It shows from **session 2 onward**. Day one gives you the menu, the
83
+ acceleration plan, and governance gates; don't judge the compounding on day one.
84
+
85
+ Unfamiliar words on the way? → [`knowledge/shared/GLOSSARY.md`](knowledge/shared/GLOSSARY.md).
86
+
75
87
  **Plugin only (no clone):**
76
88
  ```bash
77
89
  claude plugin marketplace add https://github.com/chrono-meta/forge-harness.git # once
@@ -79,16 +91,20 @@ claude plugin install -s user fh-meta@forge-harness
79
91
  cd ~/projects/{your-project} && claude
80
92
  ```
81
93
 
82
- > ⚠️ **Plugin-only is partial synergy.** You get the skills and agents, but **not** Layer 1 — the
83
- > `CLAUDE.md` governance (active onboarding, the 4-axis gate, mode branching) and the compounding
84
- > context (`tracks/` memory accumulation, `harvest-loop` learning). Each skill runs the same in
85
- > isolation; what's missing is the orchestration that makes them compound across sessions. Clone the
86
- > hub (above) when you want the full set, not just the tools.
94
+ > ⚠️ **Plugin-only is partial synergy.** You get the skills and agents, but **not** the hub-side
95
+ > orchestration — the `CLAUDE.md` governance (active onboarding, the 4-axis gate, mode branching;
96
+ > automation layer) and the compounding context (`tracks/` memory accumulation, `harvest-loop`
97
+ > learning; methodology layer).
98
+ > Each skill runs the same in isolation; what's missing is the orchestration that makes them compound
99
+ > across sessions. Clone the hub (above) when you want the full set, not just the tools.
87
100
 
88
- > 🚪 **New here / just want the skills?** Start with the opinionated front door —
89
- > [`templates/starter_profile.md`](templates/starter_profile.md): one install command, a curated
90
- > first-five skills, and a zero-install governance gate (`npx fh-gate`). The other skills wait
91
- > until you need them.
101
+ **Which entry path is for you?**
102
+
103
+ | You are| Start with |
104
+ |---|---|
105
+ | Solo dev, one project, just trying it | [`templates/starter_profile.md`](templates/starter_profile.md) — one command, curated first-five skills |
106
+ | Multiple projects, want the compounding hub | Clone the hub (quickstart above) |
107
+ | CI / non-Claude runtime, gates only | `npx @chrono-meta/fh-gate` (zero-install governance gate) |
92
108
 
93
109
  ---
94
110
 
@@ -131,12 +147,13 @@ attention is spent only where a change is irreversible.
131
147
 
132
148
  Scale is the second point. A **skill, agent, or plugin** is a tool. A **harness** is a level up — a *star*:
133
149
  one project's tools, rules, gates, and memory bound into a single working body. **forge-harness is the
134
- galaxy those stars live in** it holds many harnesses in one gravity well, keeps them in orbit (a
135
- shared floor, no drift), and lets them evolve together instead of scattering. And the system is a
136
- *nursery*, not just a container: FH can run a field harness **in simulation inside its own sandbox** —
137
- expensive per run, cheaper in total, because the trial-and-error pools in one place and compounds and
138
- when the simulation holds, it **emits** the project as an independent, specialized harness. That is the
139
- goal it is built toward. In practice the gravity comes from four things:
150
+ galaxy those stars live in**: it binds many harnesses onto a shared floor to prevent drift, and lets
151
+ them evolve together instead of scattering.
152
+
153
+ This galaxy is more than a container. FH can run a field harness **in simulation inside its own
154
+ sandbox** expensive per run, cheaper in total, because the trial-and-error pools in one place and
155
+ compounds and when the simulation holds, it **emits** the project as an independent, specialized
156
+ harness. That is the goal it is built toward. In practice it works in four ways:
140
157
 
141
158
  **① Assemble** — FH runs a *cluster* of harnesses at optimized token cost and hands you the right one for
142
159
  the project. You don't wire up skills one by one; you get a **harness** — its plugins, skills, and agents
@@ -220,7 +237,7 @@ FH_BACKEND=codex npx --package @chrono-meta/fh-gate fh-goal --prompt "Implement
220
237
 
221
238
  The broader FH automation layer still depends on Claude Code for sub-agents, hooks, and slash commands. The portable path is shared documents plus runtime adapters, not separate Codex and Claude forks.
222
239
 
223
- **Recommended posture — Claude Code as orchestrator, others as sidecars.** FH's automation layer (auto-firing hooks, sub-agent dispatch, onboarding, memory) is Claude-Code-native, so the fullest experience runs **Claude Code as the main orchestrator with Gemini, Codex, or Antigravity (`agy`) as actively-used sidecars**. You can also run a **non-CC runtime as your main agent** — you keep the full methodology layer and M1 skills through `fh-gate`/`fh-run`, but you do **not** get the autopilot layer: hooks don't auto-fire, M2 agent-dispatch steps need the adapter (or interactive approval), and M3 skills are reference-only. This is a deliberate two-layer boundary, not a gap to be closed. Per-runtime detail: [`docs/codex-compat.md`](docs/codex-compat.md) (tier-by-tier) and [`multi_model_sidecar_strategy.md`](knowledge/shared/harness-core/multi_model_sidecar_strategy.md) (sidecar engines, including the Gemini→`agy` succession at the 2026-06-18 EOL).
240
+ **Recommended posture — Claude Code as orchestrator, others as sidecars.** FH's automation layer (auto-firing hooks, sub-agent dispatch, onboarding, memory) is Claude-Code-native, so the fullest experience runs **Claude Code as the main orchestrator with Gemini, Codex, or Antigravity (`agy`) as actively-used sidecars**. You can also run a **non-CC runtime as your main agent** — you keep the full methodology layer and M1 skills (M1 = runs on any runtime as written; M2 = needs agent dispatch; M3 = Claude-Code-native — the portability tiers detailed in [`docs/codex-compat.md`](docs/codex-compat.md)) through `fh-gate`/`fh-run`, but you do **not** get the autopilot layer: hooks don't auto-fire, M2 agent-dispatch steps need the adapter (or interactive approval), and M3 skills are reference-only. This is a deliberate two-layer boundary, not a gap to be closed. Per-runtime detail: [`docs/codex-compat.md`](docs/codex-compat.md) (tier-by-tier) and [`multi_model_sidecar_strategy.md`](knowledge/shared/harness-core/multi_model_sidecar_strategy.md) (sidecar engines, including the Gemini→`agy` succession at the 2026-06-18 EOL).
224
241
 
225
242
  **Empirical result (2026-05-31)**: Applied to OpenCode's AI-generated `permission/arity.ts` (163 lines, CI green). Current gate semantics classify this as BLOCKED: 2 A-grade findings CI didn't catch (short-token overflow in allowlist, executor tools absent from arity table).
226
243
 
@@ -258,7 +275,9 @@ All four movements ship. Temper was named before it was built — deliberately (
258
275
  two more signatures keep it running: `harvest-loop` (each session's lessons become permanent skills) and
259
276
  `agent-composer` (orchestrate the dispatch). The other skills wait until you need them — full list below.
260
277
 
261
- ## 37 skills · 8 agents
278
+ ## 38 skills · 8 agents
279
+
280
+ > Count = non-deprecated skills (deprecated redirect stubs — kept only for old-name routing — excluded).
262
281
 
263
282
  <details>
264
283
  <summary>Full asset activation check</summary>
package/README.zh.md CHANGED
@@ -127,11 +127,11 @@ Project B ──→ 在 CLAUDE.md 中连接中枢
127
127
 
128
128
  规模是第二个重点。**技能、agent 或插件** 是一个工具。**框架** 高出一级 —— 是一颗 *星*:
129
129
  一个项目的工具、规则、门禁与记忆,绑成一个运作的整体。**forge-harness 就是这些星所栖居的
130
- 星系** —— 它把众多框架收进同一个引力井,让它们保持在轨(共享的下限、无漂移),并让它们
131
- 一起演化而不是四散。而且这个系不只是容器,更是*育星摇篮 (nursery)*:FH 可以在自己的沙箱里
132
- **以仿真方式跑一个现场框架** —— 单次昂贵,总体更便宜,因为试错汇聚在一处并复利累积 —— 当仿真
133
- 验证通过,它就把该项目**孵化输出**为一个独立的、特化的框架。这就是它所朝向的目标。实际上,
134
- 这份引力来自四件事:
130
+ 星系**:它把众多框架绑定在共享的下限之上以防止漂移,并让它们一起演化而不是四散。
131
+
132
+ 这个星系不只是容器。FH 可以在自己的沙箱里**以仿真方式跑一个现场框架** —— 单次昂贵,总体
133
+ 更便宜,因为试错汇聚在一处并复利累积 —— 当仿真验证通过,它就把该项目**输出 (emit)** 为一个
134
+ 独立的、特化的框架。这就是它所朝向的目标。实际上,它以四种方式运作:
135
135
 
136
136
  **① 组装 (Assemble)** —— FH 以优化后的 token 成本运行一整 *簇* 框架,并把最合适的那个交到你手上。
137
137
  你不是一个个去接线技能;你得到的是一个 **框架** —— 连同它的插件、技能与 agent —— 已按需组装好。
@@ -117,15 +117,25 @@ function extractBacktickNames(line) {
117
117
  return names;
118
118
  }
119
119
 
120
+ // The tier table IS this doctor's instrument. If it cannot be read or parsed, every skill
121
+ // comes back documentedTier=null, no M1 rule can ever fire, findings is empty, and the report
122
+ // says OK with --strict exiting 0 — a broken instrument reporting "no violations". An
123
+ // unreadable source (permissions, wrong root) and a parse yielding zero rows (the table's
124
+ // markdown drifted, e.g. bold dropped from `| **M1 |`) both land there, so both are reported
125
+ // as an instrument failure rather than a clean bill of health.
120
126
  function documentedTiers(root) {
121
127
  const sources = [
122
128
  path.join(root, 'AGENTS.md'),
123
129
  ];
124
130
  const tiers = new Map();
125
131
  const evidence = [];
132
+ const sourceErrors = [];
126
133
  for (const source of sources) {
127
134
  const text = maybeReadText(source);
128
- if (!text) continue;
135
+ if (!text) {
136
+ sourceErrors.push(`${rel(root, source)}: missing or unreadable`);
137
+ continue;
138
+ }
129
139
  const lines = text.split('\n');
130
140
  lines.forEach((line, index) => {
131
141
  const tierMatch = line.match(/\|\s*\*\*(M[123])\b/);
@@ -137,7 +147,12 @@ function documentedTiers(root) {
137
147
  }
138
148
  });
139
149
  }
140
- return { tiers, evidence };
150
+ if (tiers.size === 0 && sourceErrors.length === 0) {
151
+ sourceErrors.push(
152
+ `${rel(root, sources[0])}: readable but yielded 0 tier rows — the tier table format drifted`
153
+ );
154
+ }
155
+ return { tiers, evidence, sourceErrors };
141
156
  }
142
157
 
143
158
  function compatDocTierMentions(root, skillNames) {
@@ -333,7 +348,13 @@ function buildReport(root) {
333
348
  }
334
349
 
335
350
  return {
336
- status: findings.some((f) => f.severity === 'HIGH') ? 'DRIFT' : 'OK',
351
+ // INSTRUMENT_ERROR outranks both: without a tier table this run measured nothing, and
352
+ // "measured nothing" must not be reported as OK (nor as DRIFT, which would claim a
353
+ // finding it never made).
354
+ status: docs.sourceErrors.length > 0
355
+ ? 'INSTRUMENT_ERROR'
356
+ : findings.some((f) => f.severity === 'HIGH') ? 'DRIFT' : 'OK',
357
+ instrumentErrors: docs.sourceErrors,
337
358
  root,
338
359
  counts,
339
360
  agentCards: loadAgentCards(root),
@@ -411,6 +432,16 @@ function main() {
411
432
  } else {
412
433
  printText(report);
413
434
  }
435
+ // An instrument failure is not a passing run. It exits non-zero unconditionally — not only
436
+ // under --strict — because the failure mode it guards is precisely a caller reading exit 0
437
+ // as "no drift" when nothing was measured. 10 = harness error, distinct from 1 = drift found.
438
+ if (report.status === 'INSTRUMENT_ERROR') {
439
+ for (const err of report.instrumentErrors) {
440
+ process.stderr.write(`ERROR: tier source unusable — ${err}\n`);
441
+ }
442
+ process.stderr.write(' Nothing was classified, so no drift could be detected. Failing closed.\n');
443
+ process.exit(10);
444
+ }
414
445
  if (args.strict && report.counts.findings.HIGH > 0) {
415
446
  process.exit(1);
416
447
  }
package/bin/fh-gate.js CHANGED
@@ -1,9 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
+ // Thin wrapper — the exit code IS the contract (0 PASS / 1 PENDING / 2 BLOCKED /
4
+ // 3 ESCALATE / 10 harness-error / 11 arg-error / 12 dry-run). execFileSync throws on any
5
+ // non-zero exit, so an uncaught throw collapsed every one of them into node's own exit 1 —
6
+ // i.e. BLOCKED arrived at the caller as PENDING ("proceed with awareness"). Propagate the
7
+ // real status, and fail closed (10) when there is no status to propagate.
3
8
  const { execFileSync } = require('child_process');
4
9
  const path = require('path');
5
- execFileSync(
6
- path.join(__dirname, '..', 'scripts', 'fh-gate.sh'),
7
- process.argv.slice(2),
8
- { stdio: 'inherit' }
9
- );
10
+ try {
11
+ execFileSync(
12
+ path.join(__dirname, '..', 'scripts', 'fh-gate.sh'),
13
+ process.argv.slice(2),
14
+ { stdio: 'inherit' }
15
+ );
16
+ } catch (err) {
17
+ if (typeof err.status === 'number') process.exit(err.status);
18
+ // Killed by a signal, or the script could not be spawned at all: no verdict exists.
19
+ console.error(`fh-gate: could not run the gate (${err.signal || err.code || err.message}) — failing closed`);
20
+ process.exit(10);
21
+ }
package/bin/fh-goal.js CHANGED
@@ -1,9 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
+ // Thin wrapper — propagate the script's real exit status. execFileSync throws on non-zero,
4
+ // so an uncaught throw collapsed every distinct status into node's own exit 1.
3
5
  const { execFileSync } = require('child_process');
4
6
  const path = require('path');
5
- execFileSync(
6
- path.join(__dirname, '..', 'scripts', 'fh-goal.sh'),
7
- process.argv.slice(2),
8
- { stdio: 'inherit' }
9
- );
7
+ try {
8
+ execFileSync(
9
+ path.join(__dirname, '..', 'scripts', 'fh-goal.sh'),
10
+ process.argv.slice(2),
11
+ { stdio: 'inherit' }
12
+ );
13
+ } catch (err) {
14
+ if (typeof err.status === 'number') process.exit(err.status);
15
+ console.error(`fh-goal: could not run (${err.signal || err.code || err.message}) — failing closed`);
16
+ process.exit(10);
17
+ }
package/bin/fh-run.js CHANGED
@@ -1,9 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
+ // Thin wrapper — propagate the script's real exit status. execFileSync throws on non-zero,
4
+ // so an uncaught throw collapsed every distinct status into node's own exit 1.
3
5
  const { execFileSync } = require('child_process');
4
6
  const path = require('path');
5
- execFileSync(
6
- path.join(__dirname, '..', 'scripts', 'fh-run.sh'),
7
- process.argv.slice(2),
8
- { stdio: 'inherit' }
9
- );
7
+ try {
8
+ execFileSync(
9
+ path.join(__dirname, '..', 'scripts', 'fh-run.sh'),
10
+ process.argv.slice(2),
11
+ { stdio: 'inherit' }
12
+ );
13
+ } catch (err) {
14
+ if (typeof err.status === 'number') process.exit(err.status);
15
+ console.error(`fh-run: could not run (${err.signal || err.code || err.message}) — failing closed`);
16
+ process.exit(10);
17
+ }
@@ -103,9 +103,79 @@ pass/block verdict* — e.g. `agent-composer`, `goal-quench`, `asset-placement-g
103
103
 
104
104
  ---
105
105
 
106
+ ## §Cross-Family-Complement
107
+
108
+ Execution detail for CLAUDE.md §FH Improvement 4-Axis Auto-Gate → *Cross-family complement*. The rule
109
+ that a load-bearing change recruits ≥1 different-family auditor, that it is autonomous once consented,
110
+ and that the governor keeps the terminal verdict + source-grounds every finding — all stay in CLAUDE.md.
111
+
112
+ **Sidecar mapping (per the UAP)** — pick by task class, not by preference:
113
+
114
+ | Task class | Recruit | Why |
115
+ |---|---|---|
116
+ | Repo-grounded code / security audit | `codex` (`gpt-5.5`, xhigh) | reads the actual tree; strongest on verdict-code logic |
117
+ | Breadth / multimodal / frontier scan | `agy` (Gemini) | wide recall, video + image ingest |
118
+ | Batch / free-tier arm | local 4090 over Tailscale | no token cost; weaker judge — anchor it |
119
+
120
+ **Degrade**: when no different-family auditor is reachable, say so and fall back to single-session — but
121
+ note the exception in §Field-Harness Load-Bearing Change Gate, where an unreachable cross-family panel is
122
+ **NOT-CONVERGED** rather than a silent same-family pass (that surface is pre-merge and irreversible-adjacent).
123
+
124
+ **Dogfood evidence (2026-06-27)**: a cross-family pass caught a HIGH execution-side-effect blind spot that
125
+ the same-family reviewers **and** the target-tier sim all shared. That is the decorrelation value made
126
+ concrete: the miss was not a depth failure (the sim ran at the right tier) but a *correlation* failure —
127
+ every reviewer in the Claude family read the change the same optimistic way. Decorrelation is the only
128
+ lever that moves a correlated blind spot; more same-family review does not.
129
+
130
+ ---
131
+
132
+ ## §Destructive-Op-Hook-Coverage
133
+
134
+ Execution detail for CLAUDE.md §Destructive-Op Gate. The **order invariant** (enumerate → recover →
135
+ destroy), the **3 steps**, the `DESTRUCTIVE_OP_OK=1` override, and the **fail-closed degrade direction**
136
+ stay in CLAUDE.md — they are load-bearing every session. What follows is the mechanics + honest scope.
137
+
138
+ **Per-ref verdict (pre-push hook)**: the hook detects the destructive refspec on stdin — *delete* = local
139
+ SHA all-zeros; *force* = remote SHA not an ancestor of local — then judges each ref:
140
+
141
+ | Ref state | Verdict | Hook action |
142
+ |---|---|---|
143
+ | Branch delete, fully merged | SAFE | allowed |
144
+ | Branch delete, commits off base + 0 unique paths | CHECK | **blocked** — needs a judged content look |
145
+ | Branch delete, unique paths present | REVIEW | **blocked** — recovery mandatory |
146
+ | Force / non-ff push | — | **always blocked** |
147
+ | Tag / notes delete | — | **always blocked** |
148
+
149
+ The verdict is load-bearing, not decorative: a merged-branch cleanup passes, a silent-loss CHECK does not.
150
+ This is the enumerate step as a mechanical floor rather than prose.
151
+
152
+ **What it does and does NOT close (honest)**: it closes the **honest-weak-model** gap — an agent that
153
+ simply *forgot* the prose gate is now mechanically stopped. It does **not** close the
154
+ **injected/adversarial** gap: an agent under instruction can set the override or pass `--no-verify`, and a
155
+ client-side hook is readable and bypassable by design. The hard floor for the adversarial case is
156
+ **server-side branch protection** (GitHub *Restrict deletions* / *Restrict force pushes*) — this hook is
157
+ the honest-model floor, branch protection is the hard floor.
158
+
159
+ **Scope**: covers only git pushes *from a hook-installed repo*. `npm publish` is mechanized separately via
160
+ `prepublishOnly` (see §Pre-Publish-Hook-Coverage (c)); the remaining non-git surface — a separate-repo
161
+ `gh repo create --public` / visibility flip — is genuinely un-hookable and stays prose +
162
+ `PRE-PUBLISH-CHECKLIST.md`.
163
+
164
+ **Portability defect class**: the hook is bash-3.2 safe (macOS default `/bin/bash`). The original draft
165
+ used a bash-4 associative array that crashed **fail-OPEN** on 3.2 — caught in test. Worth naming: a
166
+ portability break in a gate degrades toward permissive unless the gate is written to fail closed on its
167
+ own errors.
168
+
169
+ **Origin (2026-06-10 branch cleanup)**: pre-deletion enumeration recovered a parallel session's card
170
+ (weekly-audit completion + #88 merge state) that existed **only on an unmerged branch** with zero unique
171
+ paths — exactly the CHECK class, and invisible to "is it merged?" intuition. Deletion without the gate
172
+ destroys live state without anyone noticing. This is why the loss class is called *silent*.
173
+
174
+ ---
175
+
106
176
  ## §Pre-Publish-Hook-Coverage
107
177
 
108
- **Hook coverage — two distinct actions (refined 2026-06-17)**:
178
+ **Hook coverage — three distinct actions** (refined 2026-06-17 for (a)/(b); (c) added 2026-06-27):
109
179
  - **(a) repo-go-public** (`gh repo create --public` / a visibility flip) is irreversible and usually in a
110
180
  **separate repo** — the FH pre-commit hook **cannot** catch it. That stays **AI-behavioral** (proactive
111
181
  trigger) **+ a portable checklist** (`templates/PRE-PUBLISH-CHECKLIST.md`), run on any repo/machine.
@@ -126,6 +196,23 @@ pass/block verdict* — e.g. `agent-composer`, `goal-quench`, `asset-placement-g
126
196
  plaintext only (encoded tokens out of scope); a line-split backstop catches a token wrapped across
127
197
  lines; `PUBLIC_SURFACE_OK=1` overrides and is logged to a gitignored audit trail for the weekly audit.
128
198
  Residuals (split-encoding, override-not-populated, override abuse) are documented, not silent.
199
+ - **(c) `npm publish`** — mechanically gated by `scripts/public_surface_scan_files.sh`, wired into
200
+ `prepublishOnly` (`npm run release` also runs it *outside* the lifecycle). Unlike (b) it scans the
201
+ **full content of the exact npm-published file set** (`npm pack --dry-run`), *not* a commit diff — so a
202
+ token committed **before the scan existed**, or carried in a `files[]` entry, is still caught at the
203
+ registry boundary. HIGH/MED block; `PUBLIC_SURFACE_OK=1` overrides + logs. **Fail-closed** when patterns
204
+ or the file set are unresolved, when the parse looks partial, **or when the gitignored operator override
205
+ is absent** — defaults-only would otherwise green-PASS a HIGH company literal on a fresh clone or CI runner.
206
+
207
+ **Named residuals for (c)** — it is a denylist **on the npm CLI path with scripts enabled**, not a
208
+ universal secret-scanner:
209
+
210
+ | # | Residual | Mitigation |
211
+ |---|---|---|
212
+ | i | `npm publish --ignore-scripts`, a CI `.npmrc` with `ignore-scripts=true`, or `pnpm`/`yarn publish` **skip the lifecycle hook entirely** | route publishes through `npm run release`, or add an explicit CI scan step |
213
+ | ii | scans only the **loaded patterns** — an **un-patterned secret shape** (an API key the patterns don't describe) still ships | pattern coverage is the limit; pair with a real secret-scanner if that shape matters |
214
+ | iii | on a runner without the gitignored override it is **defaults-only** unless populated | populate the override in each authoring env (esp. the company env) |
215
+ | iv | scans **working-tree content, not the final tarball bytes** | benign today (content-neutral lifecycle: prepare=chmod, no prepack) — **re-open if a content-generating publish lifecycle is added** (cross-family audit 2026-06-27) |
129
216
 
130
217
  > Origin: 2026-06-05 `phantom-gate` shipped public, then needed a private→de-company-scrub→re-public
131
218
  > round-trip (`fh_signal_2026-06-05_fh-direct`). PSA existed but nothing forced it pre-publish. 2026-06-17
@@ -96,13 +96,13 @@ Identity marker: every greeting response opens with **🐿️ then an identity-r
96
96
  > 🐿️ **Welcome to FH.** *forge-harness is a tool hub for rapidly setting up Claude Code projects. It supports plugin recommendations, project setup, and harness diagnostics. What would you like to work on?*
97
97
 
98
98
  **Returning user** (branch test above) — open with the fixed 4-door menu (the doors are stable; the contents are composed live). A summary copy lives in CLAUDE.md §Active Onboarding — keep branch tests and door labels in sync when editing:
99
- > 🐿️ **Welcome back to FH.** *What would you like to start? ① Map a project · ② Create a new project · ③ Accelerate a mapped project (work · Full-Harness · skills/agents/plugins) — {field candidates} · ④ Cross-project synergy*
99
+ > 🐿️ **Welcome back to FH.** *What would you like to start? ① Map a project · ② Create a new project · ③ Accelerate **or diagnose** a mapped project (work · Full-Harness · skills/agents/plugins · 진단) — {field candidates} · ④ Cross-project synergy*
100
100
  >
101
101
  > (When **FH-dev state exists** — the operator — the welcome line is **"The FH operator — good to see you."** in place of "Welcome back to FH.")
102
102
 
103
103
  - **① Map a project** → routes to `auto_project_mapping.md`; after a successful mapping, offer the §6 Full-Harness promotion prompt
104
104
  - **② Create a new project** → Step 3-0 (new project setup)
105
- - **③ Accelerate a mapped project** → compose live from `CATALOG.md` / active tracks / the session card's **field-side** candidates — never hardcode a track name; read current state each time so the menu cannot go stale. **Acceleration levers** (offer per project state, each user-approved):
105
+ - **③ Accelerate or diagnose a mapped project** → compose live from `CATALOG.md` / active tracks / the session card's **field-side** candidates — never hardcode a track name; read current state each time so the menu cannot go stale. Picking ③ with a *fix/diagnose* intent ("고칠 거 있나", "점검") routes to the **Field-Harness Diagnostic** (CLAUDE.md §Field-Harness Diagnostic) rather than the install plan. **Acceleration levers** (offer per project state, each user-approved):
106
106
  - **Full-Harness promotion** for projects still on light mapping (`auto_project_mapping.md` §6)
107
107
  - **Skill-ification** of repeated patterns (`#skill-candidate` tag at 3+ recurrences → SKILL.md draft; FH skill gates — diet · Done When · triggers — apply to field skills too)
108
108
  - **Sub-agent proposals** (`.claude/agents/*.md`, invocation rules in `operations.md`)
@@ -0,0 +1,48 @@
1
+ # Field-Harness Diagnostic — compose → rank → HITL (detail)
2
+
3
+ > Always-loaded summary: `CLAUDE.md §Field-Harness Diagnostic`. This file is the detail home —
4
+ > the full lens table, dogfood examples, and guard rationale. Read when actually running the
5
+ > diagnostic on a mapped project.
6
+
7
+ The Load-Bearing Change Gate fires on a **specific field code change**. This diagnostic is its
8
+ **on-demand pull sibling**: when the operator, working in a mapped project, asks to *diagnose* or
9
+ *improve* the harness itself ("진단해줘", "개선해줘", "check this project"), don't hand-pick one
10
+ skill — **compose the checks FH already has into a single ranked diagnostic list and get per-item
11
+ approval.** The value is that the operator asks once and the harness surfaces *everything* worth
12
+ fixing, ranked, instead of the operator having to know which of a dozen skills to invoke. Every fix
13
+ is HITL — the diagnostic **proposes**, never auto-edits.
14
+
15
+ ## Composition (no-reinvention — every row is an existing check; the diagnostic only *routes and ranks*)
16
+
17
+ | Lens | Existing check | Catches (real examples from 2026-07-08) |
18
+ |---|---|---|
19
+ | **Confidentiality / leak** | `/public-surface-audit` (incl. Step 3c ignore-verification) | a hardcoded internal API host literal in a SKILL body; a `local_*_context.md` that is **tracked** when it should be gitignored (the gitignore-mistake class) |
20
+ | **Split integrity** | `/phantom-quench` **Step 2.7** (bidirectional) | orphan detail sections + phantom pointers in a SKILL.md ↔ SKILL_detail.md pair |
21
+ | **Token / salience** | salience-split candidates (`/context-doctor` · `/salience-splitter` targets) | oversized always-loaded SKILL.md / CLAUDE.md — trim candidates |
22
+ | **Structure** | `/harness-doctor` (L1–L4) | orphaned/redundant/decorative units, missing Done-When, ≥70% overlap |
23
+ | **Verdict/gate degrade** | `scripts/degrade_direction_scan.sh` | a field verdict/gate helper that degrades toward permissive (advisory pre-screen) |
24
+ | **Loop-readiness** (황민호 loop-eng 5-question lens, 2026-07-10 — detail home: `loop_engineering.md`, incl. the FH loop inventory + design-time discipline) | *Loop-runtime axis — net-new vs Structure* (harness-doctor scans static form; this scans whether the path closes a loop). **Mechanical grep**: `/goal-quench`·`/loop` wiring present · check-class token declared. **Judged**: is the persisted state (card/handoff/memory) actually reloaded · is the declared check-class anchored, not judged-only · does the path halt. Done-When *presence* → see Structure row (no double-grep). **Adversarial pair** (for the judged sub-checks — decorrelated, behavior-vs-checklist): a target-tier blind sim that *runs* the path and observes whether it halts + persists, rather than re-checklisting it (the harness litmus shares this lens's axis, so it is a co-lens, not the adversary). | an agent path that *runs but doesn't loop*: no completion criterion (Done-When absent), judged-only validation with no anchor, no halt/budget guard (runaway/cost), or no state carried to the next run — the 5 questions (initiate · complete · validate · halt · persist) with 0 answers |
25
+
26
+ ## Output
27
+
28
+ One ranked list, `M` (must-fix) / `S` (should-fix) / `R` (recommended) — same tiering as
29
+ harness-doctor — each item stating *lens · file:line · one-line fix*. **Then HITL**: the operator
30
+ approves per item (or a batch); an approved fix routes to the owning skill's normal path (and, if it
31
+ is itself a load-bearing field change, through the Load-Bearing Change Gate). **Nothing is
32
+ auto-fixed** — the diagnostic's job is the *intelligent list*, the human's job is the *go*.
33
+
34
+ ## Guards
35
+
36
+ - **(a) Project-level ask only** — fires on a project-level "진단/개선" ask, not a single-file edit
37
+ request (those go straight to the relevant skill).
38
+ - **(b) Once per ask** — not a per-turn nag.
39
+ - **(c) Company residency** — run leak/confidentiality lenses locally, sanitize before any
40
+ cross-family dispatch, and *surface* company-sensitive findings (tracked company hosts,
41
+ git-history rewrites) for operator decision rather than auto-fixing them. Dogfood 2026-07-08: the
42
+ `local_pmh_context.md` tracked-company-hosts finding was surfaced, not auto-untracked — history
43
+ rewrite is the operator's call.
44
+ - **(d) Autonomy floor** — the compose/rank judgment is trusted at opus-tier+; below-floor, run the
45
+ individual checks and present raw rather than silently skipping a lens.
46
+
47
+ **Scale to the ask**: a quick "뭐 고칠 거 있어?" runs the cheap mechanical lenses (leak · split ·
48
+ token); "제대로 진단해줘" runs all six + harness-doctor depth.
@@ -17,6 +17,7 @@ becomes a gate other skills invoke, revisit the weight.
17
17
  | 2 | **Non-deterministic borderline verdicts** — contested/borderline cases flip across runs (observed: haiku 4/4 flip; flagship models flip too — flipping is **not** a tier signal). A single draw is noise, not a measurement. | **reps ≥ 3 on any borderline/contested verdict.** A single run on a contested case is inadmissible. Report the flip pattern (STABLE vs FLIP), not just the modal verdict. |
18
18
  | 3 | **Generic self-identity probe** — a probe any model passes ("are you working? → OK") proves nothing about *which* model answered. | **Use a discriminating probe** — one that two different models answer *differently*. A generic-pass probe is invalid. The probe is a **pattern, not a fixed string**: a probe that discriminates Opus 4.8 from Sonnet 4.6 today may both-pass a future model generation, so **re-validate the probe each model generation** (same staleness class `memory-hygiene` exists to catch). |
19
19
  | 4 | **Serving-path / quantization variance** — the *same* display-name model served over two different backends (different quantization/infra) is a **different instrument** and yields materially different measurements. Observed: one GLM-5.2 model family gave effect-size delta **+0.21** when served via an internal NVFP4-quantized deployment vs **+0.08** via an OpenRouter relay — same model name, ~2.6× different effect (n=864, reps≥3). A correctly-pinned display name (item #1) is **necessary but not sufficient**. | **Pin *and record* the serving path** — backend host + quantization, not just the display name. Two runs are comparable only if the serving path matches; a name match across different infra is an implicit apples-to-oranges. When you cannot hold it fixed, **report the serving path as a measured variable**, not a constant. |
20
+ | 5 | **Injected-context contamination (blind-sim class)** — a subagent dispatched to evaluate a *modified* instruction file answers from the **auto-injected project context** (claudeMd/memory baked into its system prompt at spawn) instead of reading the target. Observed twice in one session (2026-07-17): a "blind sim" quoted section numbering that existed only in the pre-edit file, and a second sim cited trigger-table rows that had been **deleted** from the file it claimed to have read — tool-use count 0–1 in both. The measurement *looks* grounded (fluent, plausibly cited) but the instrument never touched the target. A prompt-line telling it to ignore injected context is **not sufficient** — both runs had one. | **Force mechanical grounding a stale answer cannot fake**: ① stage the target at a **neutral path** (tmp copy) the injection cannot cover; ② require **verbatim quotes** (or grep line-number output) from that path for every claim; ③ design the probe around a **content discriminator** — something present only in the new version, or *absent* from it (a deleted row cited = instant invalidation); ④ treat **tool-use count as a validity signal** — a sim that "read two files" with 0–1 tool calls is invalid regardless of answer quality. Re-run, don't argue with a contaminated result. |
20
21
 
21
22
  ## Why these are entangled (and why they matter beyond their own scope)
22
23
 
@@ -36,10 +37,16 @@ served over a different quantization/backend). The verified identity a measureme
36
37
  sound once the serving path of each family is itself pinned, else "different family" silently smuggles
37
38
  "different infra" ([[reference_measurement_serving_path_variance]]).
38
39
 
40
+ Item #5 (injected-context contamination) is item #3's sibling on the *input* side: #3 proves *who*
41
+ answered, #5 proves *what they actually read*. Both reduce to the same mechanical-anchor rule — never
42
+ accept a measurement's self-report (of identity or of grounding) when a discriminating mechanical
43
+ check is available. Its sharpest tool is the **deleted-content discriminator**: a probe target that no
44
+ longer contains X makes any answer citing X self-invalidating — certainty no prompt instruction buys.
45
+
39
46
  ## Done When
40
47
 
41
- - The checklist enumerates all four failure modes, each with its countermeasure.
42
- *Check class: mandatory-pass (binary — four items present, each with a countermeasure).*
48
+ - The checklist enumerates all five failure modes, each with its countermeasure.
49
+ *Check class: mandatory-pass (binary — five items present, each with a countermeasure).*
43
50
  - The probe item specifies a **discriminating** test and rejects generic probes.
44
51
  *Check class: judged, pair: a probe that two different models both pass must FAIL this check; a
45
52
  discriminating one must distinguish them.*
@@ -0,0 +1,66 @@
1
+ # Multi-Harness Evolution Loop — audit → persona → fix → devolution-check → settle
2
+
3
+ > Operator-forged pattern (2026-07-17). The operator ran this sequence once across three harnesses
4
+ > and named it afterward: *"오늘 내가 제시한 기법 자체가 fh·pmh를 진화시킬 수 있는 루프였을 거라고
5
+ > 생각해."* This doc is the harvest — the loop as a repeatable protocol, with its n=1 evidence and
6
+ > a promotion gate. It is a **composition of existing FH checks** (no-reinvention: every phase
7
+ > routes to an existing asset); what is net-new is the loop shape and its two doctrine points below.
8
+
9
+ ## The loop (5 phases)
10
+
11
+ | Phase | What runs | Existing asset routed | Check class |
12
+ |---|---|---|---|
13
+ | **1. Structure audit** | harness-doctor lens per harness **+ a cluster lens across them** (registry freshness · track sync · cross-refs · skill-bus reachability · gate propagation · orchestration artifacts) | `/harness-doctor` · LOCAL_SKILL_REGISTRY · Field-Harness gates | mechanical + judged |
14
+ | **2. Persona usability audit** | beginner (cold-read, minutes-to-first-value) · main-player (daily intent-utterance test: do natural phrases reach the right skill?) · expert (frontier bar, external citations mandatory) — per harness | fh-meta persona agents (beginner / main-player / expert) | judged, adversarially paired by tier diversity |
15
+ | **3. Fix application** | fixer agents per repo, **verify-before-act on every claimed defect** (a false finding gets skipped with evidence, not applied); each repo's own gates honored, HITL-deferred items go to a ranked backlog instead of being forced | fixer dispatch + per-repo 4-axis / pre-commit gates | mechanical (grep-verify per fix) |
16
+ | **4. Devolution check** | adversarial regression audit of the fixes themselves — *"is anything now WORSE than before?"* — cross-family (codex) on public repos, same-family with an honest residency note on company repos; **iterate fix→re-verify until CONVERGED** | `auto-decorrelation` posture · codex headless · target-tier blind sim | cross-family + mechanical anchor |
17
+ | **5. Settle** | canonical wiki node + INDEX pointer (machine side) **+ operator-readable report pushed to where the operator actually reads** (Obsidian/iCloud mirror) + ranked M/S/R backlog of operator-decision items | wiki 규약 · sync-wiki-to-icloud | mandatory-pass (artifacts exist) |
18
+
19
+ ## Two doctrine points (the net-new judgment content)
20
+
21
+ 1. **Usability is a first-class diagnostic axis, not polish.** The loop's n=1 run found the same
22
+ root defect in all three harnesses — *the routing surface was narrower than the user's real
23
+ daily utterances* — and structure-only audits (phase 1 alone) had missed it for months. The
24
+ operator's framing is the axis: "성능이 좋아도 결국 사용하기 쉽고 직관적이어야" — a harness whose
25
+ speech doesn't reach is failing regardless of internal rigor. Phase 2 is therefore not optional
26
+ decoration on phase 1; it is the half of the diagnosis that structure scans cannot see.
27
+ 2. **Improvement without a devolution check is half a loop.** Phase 4 exists because phase 3's
28
+ fixes are themselves AI-authored changes — the same optimistic-author blind spot the
29
+ cross-family gate guards. In the n=1 run, phase 4 caught a real regression that phases 1–3
30
+ produced (a README layer mis-attribution that made vague wording *wrong*), plus two S-tier
31
+ follow-ups in the field fixes. "다 하고 나서 기존보다 어떻게 개선되었는지, 오히려 퇴화한 부분은
32
+ 없는지 점검" — the loop is not done at "fixes applied"; it is done at CONVERGED.
33
+
34
+ ## Guards (inherited, restated for the loop)
35
+
36
+ - **Residency**: company-token repos never go to an external model family; their devolution check
37
+ runs same-family with the limitation recorded, not hidden.
38
+ - **Verify-before-act**: every audit finding is re-verified against disk before a fixer applies it
39
+ (n=1 run: one "typo" finding was in-house jargon — correctly skipped with source evidence).
40
+ - **HITL boundary**: judgment items (canonical-count decisions, dual-source direction, gate
41
+ loosening, architecture surgery) are never auto-applied — they land in the ranked backlog.
42
+ - **Autonomy floor**: compose/rank judgments at opus-tier+; the loop was designed to run
43
+ autonomously on an explicit operator go ("자체적으로 돌아줘"), not as a standing daemon.
44
+
45
+ ## n=1 evidence (2026-07-17)
46
+
47
+ Three harnesses (FH hub + two mapped field harnesses), 21 agents total (12 audit · 2 fixer ·
48
+ 7 verification). Outcomes: hub always-loaded footprint over-threshold closed (TARGET-rooted
49
+ 95.8k → 79.9k chars); three repos' routing surfaces extended to cover the measured daily
50
+ utterances; ~10 phantom references replaced with disk-verified targets; registry brought to
51
+ parity (mirror-dedup for the fork, lockline for the irreversible-execution skill); one real
52
+ regression caught and fixed by the cross-family pass; final verdicts CONVERGED across all three
53
+ repos. Ranked residual backlog delivered for operator decisions.
54
+
55
+ ## Promotion gate
56
+
57
+ This doc is the pattern's home at **n=1**. Per evidence-threshold build discipline, do NOT build a
58
+ skill or runner from it yet. Promotion path: a second full run (n=2, ideally on a different harness
59
+ set or triggered from a field cwd) → then decide skill-ification (`/harness-evolution-loop`
60
+ orchestrator skill, chamber-screened) vs staying a documented protocol. Cadence candidate
61
+ (quarterly, alongside the harness-doctor 30-day cadence) is also an n≥2 decision.
62
+
63
+ Related: `harness_6axis_framework.md` (axes 5–6) · `field_harness_diagnostic.md` (single-project
64
+ pull sibling) · `hub_compounding_loop.md` (the learning-return this loop feeds) ·
65
+ `measurement-integrity-checklist.md` (phase-4 instrument hygiene — the n=1 run also invalidated a
66
+ contaminated sim and re-ran it with a verbatim-quote protocol).
@@ -0,0 +1,82 @@
1
+ # Onboarding / Acceleration Autopilot — discover → compose → rank → install-HITL (detail)
2
+
3
+ > Always-loaded summary: `CLAUDE.md §Onboarding / Acceleration Autopilot`. This file is the detail
4
+ > home — the full Phase-0 branch logic (including the chamber / simulate-first honesty boundary),
5
+ > provenance, and guard evidence. Read when executing the autopilot on an onboarding or
6
+ > acceleration door.
7
+
8
+ The **install-direction twin of the Field-Harness Diagnostic**: same `compose → rank → HITL`
9
+ engine, but it decides *what to install/wire* instead of *what to fix*. When the operator enters an
10
+ onboarding / acceleration door (returning-menu ①②③: "새 프로젝트", "하네스 작성/작성해줘",
11
+ "이 프로젝트 가속화", "harness-ify", "accelerate this project"), don't hand-run one skill —
12
+ **auto-discover the local state, let the innovator center a recommend cascade, produce a ranked
13
+ install plan, and gate every install.**
14
+
15
+ ## Flow
16
+
17
+ 1. **Phase 0 — State Audit + branch (auto-discovery)**: read the target's existing
18
+ `.claude/agents|skills`, `CLAUDE.md`, mapped `tracks/`, **locally-connected sibling repos** (the
19
+ env-delta SessionStart hook already emits "N unmapped sibling repos"), and the
20
+ `LOCAL_SKILL_REGISTRY` + stack/language. Then **branch**: *new-build* (no prior harness) ·
21
+ *extend-existing* (harness present → found→extend, never fork) · *maintain* (mature harness →
22
+ route to the Field-Harness Diagnostic instead).
23
+
24
+ **New-build sub-branch — simulate-first (incubator doctrine)**: judge the project's character
25
+ before building. Clear · small · low failure-cost → build immediately (current flow). Uncertain ·
26
+ exploratory · failure-expensive → **flag simulate-first as an option**: doctrine says such a
27
+ project *should* be chamber-simulated before emit. The chamber **run orchestration is wired**
28
+ (`scripts/chamber_run.sh` — an intent-driven, resumable 7-step runner: budget-entry cap,
29
+ ≥3-blind-persona gate, Emission Gate, G4 ledger auto-append; run #3 exercised it 2026-07-14).
30
+ But a **live one-command autonomous simulate→EMIT of a field harness is NOT yet a capability**:
31
+ step-4 persona dispatch is human/Claude-driven (bash cannot spawn the isolated Agents — the
32
+ honest muscle boundary), the EMIT terminus is HITL, and **EMIT has never fired — the ledger's
33
+ real runs are honest KILLs** (the chamber to date *screens*, it has not *birthed*). So today this
34
+ branch = a one-line HITL recommendation to run the chamber (`chamber_run.sh`), then fall back to
35
+ Full-Harness Mode §6 (`auto_project_mapping.md`) for the actual onboarding; the runner gates and
36
+ records a human-driven run — it must **not** be presented as a push-button autonomous emit. The
37
+ same branch applies to a **new capability of an existing harness** — the
38
+ incubate-in-chamber-then-transplant flow is likewise run-orchestrated but not autonomously
39
+ emitting today. Rationale + economics:
40
+ `knowledge/shared/harness-core/harness_incubator_doctrine.md §3`.
41
+
42
+ This audit-and-branch pre-step is imported from the revfactory/harness Phase-0 State Audit
43
+ (sister-audit 2026-07-07) — it tightens FH's found→extend reflex and is the "이미 로컬에 연결돼
44
+ 있으면 자동 탐색" mechanism.
45
+
46
+ 2. **Innovator-centered recommend**: `persona-innovator` centers the cascade (Mode I on
47
+ acceleration / Mode F on FH-dev), composing `plugin-recommender` (Tier 0 platform → Tier 1
48
+ official → Tier 2/3) + `cross-ecosystem-synergy-detection` (locally-connected skills worth
49
+ wiring) + inferred technical level (conversation-cue read, also imported from revfactory) to
50
+ shape *what* and *how much*.
51
+
52
+ 3. **Ranked install plan**: one list, `M`/`S`/`R`, each item = *what · why · source (Tier 0
53
+ built-in / Tier 1 official / local sibling / FH scaffold) · exact install command*.
54
+ No-reinvention: an official/built-in that covers the need ranks above a net-new scaffold.
55
+
56
+ 4. **Install — HITL, non-overwriting**: per-item approval; **never clobber an existing `.claude/`**
57
+ (propose merge/skip if present — this is FH's edge over revfactory's post-plan auto-write and
58
+ harness-100's raw `cp`). Any generated/installed FH asset runs the **4-axis gate**; a field
59
+ scaffold runs `asset-placement-gate` + `steel-quench`. **"끝까지 해줘 / 자율로 완주" →
60
+ full-autonomy**: run the whole plan under the `/goal-quench` budget+quality gate (token cost
61
+ accepted by the operator), still non-overwriting and still gated per asset — autonomy removes
62
+ the per-item *prompt*, never the *gate*.
63
+
64
+ ## Guards
65
+
66
+ - **(a) Non-overwriting is inviolable** — the one thing both revfactory surfaces get wrong; FH
67
+ proposes merge, never clobbers.
68
+ - **(b) No-reinvention** — Tier 0/1 first, scaffold only what adds governance.
69
+ - **(c) Company residency** — discovery of a company sibling repo surfaces it, does not
70
+ auto-map/leak it; promoted to a machine field (`residency` on the skill registry,
71
+ `fh_detail_protocols.md §1-c`) so any derived recommendation naming a `company` /
72
+ `operator-private` entry lands only in gitignored `tracks/_meta/` or the private companion store,
73
+ never a tracked public file (chamber run #7, 2026-07-14 — the guard was prose-only and the field
74
+ didn't exist).
75
+ - **(d) Autonomy floor** — the discover/rank judgment is trusted at opus-tier+; below-floor,
76
+ present the raw recommend and ask.
77
+ - **(e) Once per door-entry** — not a per-turn nag.
78
+
79
+ This is the door ③ (accelerate; a *diagnose* intent on the same door routes to the Field-Harness
80
+ Diagnostic instead) engine and the new-project/harness-write path made autonomous —
81
+ the operator asks once and the harness discovers, ranks, and (on request) installs everything worth
82
+ wiring.