@chrono-meta/fh-gate 1.4.34 → 1.4.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CLAUDE.md CHANGED
@@ -103,17 +103,17 @@ Simplification guard: trivial denials with one obvious fix → state block + sin
103
103
 
104
104
  **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) → ② One-line proposal (new user / exploratory / returning branches) → ③ 5-skill cascade (plugin-recommender → synergy → .claudeignore → model → verify) → ④ Approval + setup
105
105
 
106
- **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 — origin: a fresh-clone sonnet sim rendered the returning menu off commit messages, `fh_signal_2026-06-11` FP8). Every variant opens with **🐿️ on its own line as the skeleton's first line** the marker is part of the skeleton, one salience unit with the menu, not a separate rule.
106
+ **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 — origin: a fresh-clone sonnet sim rendered the returning menu off commit messages, `fh_signal_2026-06-11` FP8). Every variant opens with **🐿️ then an identity-revealing welcome line on the SAME line** (🐿️ is no longer alone on its own line), followed by the menu — one salience unit, not a separate rule. (Put a space after 🐿️; the exact count is **not significant** — a markdown renderer collapses multiple mid-line spaces to one — so 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; the lid/onboarding-smoothness matters even though it is not the substance).
107
107
 
108
108
  - **New user** (no session files AND no mapped project tracks under `tracks/` — fresh clone/install; underscore meta dirs `_meta`/`_audit`/`_contrib` don't count): 2-door starter, never the returning menu —
109
109
 
110
- > 🐿️
111
- > *"Looks like you're new here! ① Create your first project (guided) · ② Map an existing project — and I can run `/install-wizard` to finish initial setup."*
110
+ > 🐿️ **Welcome to FH.** *Looks like you're new here! ① Create your first project (guided) · ② Map an existing project — and I can run `/install-wizard` to finish initial setup.*
112
111
 
113
112
  - **Returning user** (session files OR mapped project tracks exist): fixed 4-door menu —
114
113
 
115
- > 🐿️
116
- > *"① Map a project · ② Create a new project · ③ Accelerate a mapped project (work · Full-Harness · skills/agents/plugins) — {field candidates} · ④ Cross-project synergy"*
114
+ > 🐿️ **Welcome back to FH.** *① Map a project · ② Create a new project · ③ Accelerate a mapped project (work · Full-Harness · skills/agents/plugins) — {field candidates} · ④ Cross-project synergy*
115
+ >
116
+ > (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.")
117
117
 
118
118
  Render conditions: ①②③ always (③'s candidates composed live) · ④ only when **2+ project tracks** exist (underscore meta dirs don't count) — synergy findings flow back into each project, and may *propose* an FH contribution (`/field-harvest` → `tracks/_contrib`) as an **outcome of findings, never a standing door**.
119
119
 
@@ -121,7 +121,7 @@ Simplification guard: trivial denials with one obvious fix → state block + sin
121
121
 
122
122
  Compose session-card candidates **into door ③ (field) and the 🔧 door (FH-dev)**, never as a raw priority dump that replaces the menu. An urgent open item (time-windowed handoff · blocking external deadline) outranks the menu; an explicit task utterance skips it entirely (see Guards below); cadence reminders (§Cadence Rules) ride below it, they don't displace it. Canonical source: `fh_detail_protocols.md` Step 2 — keep branch tests and door labels in sync.
123
123
 
124
- **Identity marker**: every greeting response (Step ②) opens with 🐿️ on its own line. It is embedded in both skeletons above (do not strip it when composing doors); the exploratory branch template carries it in `fh_detail_protocols.md` Step 2.
124
+ **Identity marker**: every greeting response (Step ②) opens with 🐿️ then an identity-revealing welcome line **on the same line** (a space after 🐿️; exact count not significant — the renderer collapses it — the invariant is *same-line*, not 🐿️ alone) — new / exploratory = "Welcome to FH." · returning = "Welcome back to FH." · operator (FH-dev state) = "The FH operator — good to see you." It is embedded in all skeletons above (do not strip it when composing doors); the exploratory branch template (`fh_detail_protocols.md` Step 2) uses the "Welcome to FH." line.
125
125
 
126
126
  **Guards**: explicit task-entry utterance → skip onboarding · once per session · code/debug requests → start working directly · project routing is a suggestion, mention at most once
127
127
  **Metadata-is-not-intent guard**: the trigger is the user's **typed message only**. Session metadata — branch name (auto-derived from the first message, e.g. `claude/korean-greeting-*`), repo name, file paths — is **never** a task spec and never suppresses or redirects the greeting trigger. A bare greeting fires onboarding even when the branch name looks like a feature request; if the only "task" signal lives in metadata and not in what the user typed, treat the message as a greeting and run the greeting branch + door skeleton above.
@@ -227,6 +227,23 @@ post-compaction 2026-06-12). 2026-06-15+: headless `claude -p` draws from the ha
227
227
  subscription — prefer in-session Agent dispatch when the plan gate allows; take the headless fallback
228
228
  knowingly. Record sim results in the Axes 2–3 marker + sub-agent invocation log.
229
229
 
230
+ **Floor-tier canary (optional pre-screen — token-free, *below* the Sonnet sim)**: a local model weaker
231
+ than or comparable to Sonnet (e.g. `ollama run qwen3:8b` on the local host today; a cross-family local
232
+ panel — qwen3.x:27b / gemma4:12b-qat / gpt-oss:20b / devstral — on a GPU host once its remote-exec path
233
+ is live) can pre-screen a salience-dependent edit *before* the Sonnet dispatch is spent: a rule that
234
+ fires correctly on the floor model is *evidence of* robustness below Sonnet (one floor sample, not proof
235
+ — hold the asymmetric-skepticism discipline). Blind probe — feed the verbatim rule text + a scenario,
236
+ demand a strict YES/NO + one-line reason, judge whether the rule fired (mechanism dogfood-verified
237
+ 2026-06-20: a local `qwen3:8b` correctly gated the public install-wizard local-LLM-offload item in both
238
+ directions — a claim checkable against that skill — re-validating that day's salience-binding fix at a
239
+ sub-Sonnet tier). **Canary, NOT gate**: a PASS adds cheap floor confidence and you still run the Sonnet
240
+ sim; a FAIL never blocks alone — the opus orchestrator triages it as a *real salience gap* (fix the
241
+ rule) vs a *floor-model quirk* (small-model loop/hallucination, per the public "Local AI is not Opus"
242
+ finding + the cheap-oracle ceiling — a small model adds nothing where one grep already settles the
243
+ check). The terminal verdict stays with the frontier (Sonnet sim + opus judge) — no judge-only path, no
244
+ weak-local-judge regression of the judge-robustness principle (mechanical anchor over judge-only verdict).
245
+ The cross-family-panel upgrade spec lives in the private companion store's `handoff/` design note.
246
+
230
247
  **Axis ownership** (each skill is already complete — orchestrator only coordinates):
231
248
 
232
249
  | Axis | Skill | What it catches |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrono-meta/fh-gate",
3
- "version": "1.4.34",
3
+ "version": "1.4.36",
4
4
  "description": "FH runtime adapters — run FH governance, skills, and agents via Claude or Codex with machine-parseable gates.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -65,7 +65,7 @@ On **cadence-triggered** runs (7d), ask the operator one line before collecting:
65
65
 
66
66
  ## Step 1. Data Collection
67
67
 
68
- Collect from four sources (bash per source in §Collection-Bash):
68
+ Collect from five sources (bash per source in §Collection-Bash):
69
69
 
70
70
  | Source | Method | Cap |
71
71
  |---|---|---|
@@ -73,11 +73,14 @@ Collect from four sources (bash per source in §Collection-Bash):
73
73
  | arxiv | export API, latest by submittedDate | 6 items |
74
74
  | TLDR AI | RSS, title + link | 5 items |
75
75
  | The Batch (deeplearning.ai) | HTML scraping, title + issue slug | 5 items |
76
+ | GeekNews (news.hada.io) | Atom feed (`/rss/news` path), title + link, AI/agent/LLM-relevant | 5 items |
76
77
 
77
- Report progress: `📡 HN 15 items · arxiv 5 items · TLDR 5 items · Batch 5 items collected`
78
+ Report progress: `📡 HN 15 items · arxiv 5 items · TLDR 5 items · Batch 5 items · GeekNews 5 items collected`
78
79
 
79
80
  > **Detail**: See `SKILL_detail.md §Collection-Bash` — curl commands per source with parsing notes — read when executing Step 1.
80
81
 
82
+ **Knowledge-currency augment (on-demand, not weekly-scanned)**: distinct from the trend feeds above, these are fetched when a specific version/fact/spec needs confirming against the model's knowledge cutoff — `docs.anthropic.com` (official Claude/API docs · model IDs · pricing), arxiv (already a feed, also a currency target by ID), and Zenodo (research deposits incl. FH's own). Pull these into context for currency rather than scanning them for trends; in egress-restricted environments (e.g. a company network) route the fetch through the approved bridge (n8n), not a direct call.
83
+
81
84
  ---
82
85
 
83
86
  ## Step 2. Synthesis
@@ -50,7 +50,15 @@ curl -s --max-time 10 -L "https://www.deeplearning.ai/the-batch/"
50
50
 
51
51
  Extract `"title":"..."` + `"slug":"issue-\d+"` pattern → URL: `https://www.deeplearning.ai/the-batch/{slug}/`. Max 5 items.
52
52
 
53
- Report progress: `📡 HN 15 items · arxiv 5 items · TLDR 5 items · Batch 5 items collected`
53
+ ### GeekNews news.hada.io (RSS)
54
+
55
+ ```bash
56
+ curl -s --max-time 8 "https://news.hada.io/rss/news"
57
+ ```
58
+
59
+ Korean dev-news aggregator (HN-equivalent), AI-heavy. **The `/rss/news` path serves an Atom feed** (`<feed>`/`<entry>`, NOT RSS `<item>` — verified 2026-06-20: 50 `<entry>` elements, 0 `<item>`). Parse `<entry>` → `<title>` + `<link href>`; keep AI/agent/LLM/harness-relevant items only. `/rss/news` is a *general* dev-news feed, so if 0 AI-relevant items remain after filtering, **drop GeekNews from this run's progress line rather than padding to 5**. Endpoint verified HTTP 200 (2026-06-20); `/rss/new` and `/rss/topics` 404 — use `/rss/news`. Max 5 items.
60
+
61
+ Report progress: `📡 HN 15 items · arxiv 5 items · TLDR 5 items · Batch 5 items · GeekNews 5 items collected`
54
62
 
55
63
  ---
56
64
 
@@ -102,7 +102,7 @@ Pasting tokens directly in chat exposes them in conversation history; environmen
102
102
 
103
103
  *(Run after Step 0-A·B pre-checks. Output results as environment card, then continue to Step 0-C.)*
104
104
 
105
- CC runs the detection bash automatically (injection pre-flight scan → FH_DIR/CC_HUB_DIR → cwd project info → plugins → MCP → zshrc hook → optional framework detection), then outputs the environment card.
105
+ CC runs the detection bash automatically (injection pre-flight scan → FH_DIR/CC_HUB_DIR → cwd project info → plugins → MCP → zshrc hook → optional framework detection → local LLM runtime, optional), then outputs the environment card.
106
106
 
107
107
  **Stop rule (behavioral)**: if `FH_DIR` is not set, output the bootstrap guidance and **do not proceed to subsequent Steps** — install FH first, then rerun.
108
108
 
@@ -135,7 +135,9 @@ Y (add integration plan items to Step 1) / N (add-only, keep existing rules) / S
135
135
 
136
136
  **[Prerequisite] install-doctor conflict diagnosis (only in environments without install history)**: if `~/.cc_sentinels/{project-name}_wizard_done` doesn't exist (first install), call `/install-doctor --plugin fh-meta` first. CONFLICT/WARNING items → add ❗ markers to Step 2 proposal list. Items the doctor already diagnosed (`FH plugin install` · `zshrc hook` · `.claudeignore`) → map results directly, skip re-diagnosis; all other items → check directly.
137
137
 
138
- Auto-check each item as PASS / MISS / FAIL. Check items: `.claudeignore` · `local_fh_context.md` · `zshrc hook` · `weekly_audit` freshness · `sentinel` setup · FH plugin install · `.git/info/exclude` · MCP plugin · `deep-insight` plugin (optional) · `fh_env_context.jsonc` · `phantom-gate` (Python + AI-output projects only) · domain pattern pack (optional, none ship by default).
138
+ Auto-check each item as PASS / MISS / FAIL. Check items: `.claudeignore` · `local_fh_context.md` · `zshrc hook` · `weekly_audit` freshness · `sentinel` setup · FH plugin install · `.git/info/exclude` · MCP plugin · `deep-insight` plugin (optional) · `fh_env_context.jsonc` · `phantom-gate` (Python + AI-output projects only) · domain pattern pack (optional, none ship by default) · local-LLM offload (optional — surface ONLY if the Step 0 bash emitted the literal line `Local LLM runtime: detected`; absent that line, this item does not exist).
139
+
140
+ **Local-LLM offload (conditional, recommend-only)**: when Step 0 detected a local LLM runtime (Ollama / LM Studio), surface one optional item — route to `/plugin-recommender` for local-model offload tooling. FH recommends, never rebuilds (no-reinvention). Two complementary offload shapes the user picks per workload: **input-side context routing** (a small local model returns line ranges, so the cloud model receives only the dense slices instead of whole files) and **output-side generation delegation** (the local model generates and self-reviews code while the frontier model decomposes and validates). The benefit is tier-dependent — largest in headless/scripted pipelines and on weaker cloud tiers; an interactive session already triages via targeted reads. Local models suit **bounded, well-specified** work (triage, codebase explanation, instructed maintenance), not long-horizon autonomous tasks where small models loop or hallucinate — so the frontier model keeps decomposition and validation. Skip silently when no local runtime is present.
139
141
 
140
142
  > **Detail**: See `SKILL_detail.md §Step1-Checks` — full check table with criteria and verification commands per item — read when executing Step 1.
141
143
 
@@ -128,6 +128,16 @@ FRAMEWORK=""
128
128
  for fw in streamlit django fastapi flask; do
129
129
  if grep -qi "$fw" requirements.txt pyproject.toml 2>/dev/null; then FRAMEWORK="$fw"; echo "Framework: $fw detected"; break; fi
130
130
  done
131
+
132
+ # Local LLM runtime (optional) — gates the conditional local-offload recommendation in Step 1.
133
+ # Ollama default :11434, LM Studio default :1234. Absence is the normal state (no offload item surfaced).
134
+ # Confirm the RESPONSE SHAPE, not just any HTTP 200 — Ollama /api/tags returns {"models":...},
135
+ # LM Studio /v1/models returns {"data":...}; this avoids a non-LLM service squatting the port.
136
+ for url in http://localhost:11434/api/tags http://localhost:1234/v1/models; do
137
+ if curl -sf -m 1 "$url" 2>/dev/null | grep -q '"models"\|"data"'; then
138
+ echo "Local LLM runtime: detected ($url)"; break
139
+ fi
140
+ done
131
141
  ```
132
142
 
133
143
  **Bootstrap guidance when FH_DIR is not set (stop immediately in Step 0):**
@@ -168,6 +178,7 @@ install-wizard — Environment Detection
168
178
  CC Hub: {CC_HUB_DIR or not set}
169
179
  Plugins: {installed plugin list}
170
180
  zshrc hook: {present/absent}
181
+ Local LLM: {runtime + url if detected — omit this row when none}
171
182
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
172
183
  ```
173
184
 
@@ -251,6 +262,7 @@ Auto-check the following items based on detected environment. Each item classifi
251
262
  | `fh_env_context.jsonc` | `.claude/rules/fh_env_context.jsonc` exists | `ls .claude/rules/fh_env_context.jsonc` |
252
263
  | `phantom-gate` | **(Python + AI-output projects only)** `phantom-gate` present in `requirements.txt` / `pyproject.toml` | `grep "phantom.gate" requirements.txt pyproject.toml 2>/dev/null` |
253
264
  | `Domain pattern pack applied` | (optional — only when a `{framework}_patterns.md` pack is present; none ship by default) framework-specific pattern checks | `knowledge/shared/{framework}_patterns.md` check (skip if file absent — the normal default) |
265
+ | `local-LLM offload` | (optional — only when Step 0 detected a local LLM runtime) recommend local-model offload tooling, recommend-only | route to `/plugin-recommender` (no install performed here; skip silently if no runtime detected) |
254
266
 
255
267
  ---
256
268
 
@@ -170,6 +170,56 @@ token only *contains* an example substring but is otherwise a real private value
170
170
 
171
171
  ---
172
172
 
173
+ ## Step 3c. Ignore-Verification — the gitignore-mistake safeguard (root-cause, runs before Step 4)
174
+
175
+ Steps 3/3b scan what **is** tracked. This step checks the inverse and the upstream cause: a file you
176
+ *intend* to be private that is **not actually ignored** — the gitignore mistake that becomes tomorrow's
177
+ tracked leak. For each expected-private path, `git check-ignore -v` reports whether it is ignored **and
178
+ by which layer** (committed `.gitignore` · local `.git/info/exclude` · global `core.excludesFile`). A
179
+ path that resolves to no ignore rule is a MISS — surface it before it is ever `git add`ed.
180
+
181
+ ```bash
182
+ # Expected-private set = conventional FH local-only files, EXTENDED with any `# private-path: <path>`
183
+ # lines the operator added to the gitignored pattern source (self-extends per repo — not a frozen
184
+ # operator snapshot). Built one-path-per-line + while-read so it is portable across bash AND zsh
185
+ # (zsh does not word-split an unquoted variable, so `for f in $VAR` would break). A non-existent file
186
+ # is skipped; an all-absent set emits n/a, never a silent pass.
187
+ present=$({ printf '%s\n' CLAUDE.local.md .claude/rules/.public-surface-patterns \
188
+ .claude/rules/local_fh_context.md tracks/_meta/user_adaptation_profile.md
189
+ grep -E '^# private-path:' .claude/rules/.public-surface-patterns 2>/dev/null \
190
+ | sed -E 's/^# private-path:[[:space:]]*//'; } \
191
+ | awk 'NF' | sort -u | while IFS= read -r f; do [ -e "$f" ] && printf '%s\n' "$f"; done)
192
+ [ -z "$present" ] && echo "n/a (no expected-private files present in this repo — add '# private-path:' lines to the pattern source if any exist)"
193
+ printf '%s\n' "$present" | while IFS= read -r f; do
194
+ [ -z "$f" ] && continue
195
+ # Tracked status is tested FIRST: a file can match an ignore rule yet still be force-added
196
+ # (`git add -f`) — the exact ignored-but-committed mechanism behind the PR #109 leak. Tracked wins,
197
+ # so an ignored-but-committed file reports TRACKED (not a false-clean OK).
198
+ if git ls-files --error-unmatch "$f" >/dev/null 2>&1; then
199
+ echo "TRACKED $f (already committed — Step 3 scans its contents; un-track if it must be private: git rm --cached)"
200
+ elif rule=$(git check-ignore -v "$f" 2>/dev/null); then
201
+ echo "OK $f → ignored by [$rule]"
202
+ else
203
+ echo "MISS $f (exists, NOT ignored, NOT tracked — one 'git add .' from a leak; add an ignore rule)"
204
+ fi
205
+ done
206
+ ```
207
+
208
+ - **OK** — ignored; the report names which layer covers it (operator-private files should resolve to
209
+ `.git/info/exclude` or `.gitignore`, never end up tracked).
210
+ - **MISS** — exists but no ignore rule covers it → counts as **🟠 MED** in the Step 4 verdict (a latent
211
+ leak, not yet a breach).
212
+ - **TRACKED** — already committed: Step 3 scans its *contents*; this also flags it for un-tracking if it
213
+ was meant to be private.
214
+
215
+ Why this is the safeguard for **gitignore mistakes** (a wrong assumption about what is ignored):
216
+ `.gitignore` is committed/shared, `.git/info/exclude` is local/personal, and a global `core.excludesFile`
217
+ ignores across all repos — `git check-ignore -v` is the one command that says *which* rule (if any)
218
+ applies, so an "I thought it was ignored" error surfaces here instead of in a public PR (the PR #109
219
+ class of leak). Diagnostic-only: this step never writes — it reports, the operator adds the ignore rule.
220
+
221
+ ---
222
+
173
223
  ## Step 4. Report
174
224
 
175
225
  ```
@@ -180,7 +230,7 @@ public-surface-audit — Operator-Private Token Scan
180
230
  🔴 HIGH ({count})
181
231
  {file}:{line} → {matched token} [class: username | company asset]
182
232
  🟠 MED ({count})
183
- {file}:{line} → {matched token} [class: absolute home path]
233
+ {file}:{line} → {matched token} [class: absolute home path | ignore-MISS (Step 3c)]
184
234
  🟡 LOW ({count})
185
235
  {file}:{line} → {matched token} [class: companion-store | private wiring]
186
236
 
@@ -9,7 +9,9 @@ model: opus
9
9
  # sim-conductor — Meta-Simulation Automation Orchestrator
10
10
 
11
11
  > Profiles target → derives personas → dispatches parallel agents → M/S/R triage → commit.
12
- > Personas are sourced installed-first → built-in fallback external install. Scale: 3 to 16 by task complexity.
12
+ > Personas are sourced installed-first → **filled from the persona-container schema** (6 slots, not an
13
+ > ad-hoc directive) → external install. Scale: 3 to 16, extensible to a crowd behind the
14
+ > marginal-coverage stop (§Scale).
13
15
 
14
16
  ## Invocation Triggers
15
17
 
@@ -97,12 +99,20 @@ Recommendation:
97
99
 
98
100
  #### Persona Discovery (after profile → before dispatch)
99
101
 
102
+ > **Schema**: `knowledge/shared/harness-core/persona_container_schema.md` — the 6-slot persona-definition
103
+ > container. ② below **fills** these slots (lens / internal-logic / external-grounding / output-protocol
104
+ > / cost-tier / lifecycle) instead of injecting a shapeless directive. The container is what makes a
105
+ > synthesized persona reproducible and cost-routable; the old "fallback palette" was undefined.
106
+
100
107
  After profiling, sim-conductor determines the needed perspective types, then maps each to the best available agent:
101
108
 
102
109
  ```
103
110
  For each needed perspective:
104
111
  ① Scan installed plugins + .claude/agents/ → exact match? → use it
105
- Built-in fallback palette approximate match? inject as prompt directive
112
+ Fill the 6-slot persona container lens · internal-logic · external-grounding · output-protocol
113
+ (= Step 1.5 parallax shape) · cost-tier · lifecycle → a defined, reproducible persona; the filled
114
+ container IS the dispatch prompt (replaces the old ad-hoc "fallback palette" directive). Assign
115
+ the cost-tier slot per §Scale cost-tier routing. [Schema: persona_container_schema.md]
106
116
  ③ GAP: no ①② match for a high-weight perspective
107
117
  → query /plugin-recommender: "find agents for [perspective] matching [artifact_type] context"
108
118
  → present: name · install command · estimated fit · token cost
@@ -113,8 +123,8 @@ Persona Discovery output:
113
123
 
114
124
  ```
115
125
  Persona Map:
116
- beginner → [installed agent: beginner] OR [ad-hoc directive]
117
- challenger → [installed agent: challenger] OR [ad-hoc directive]
126
+ beginner → [installed agent: beginner] OR [filled 6-slot container]
127
+ challenger → [installed agent: challenger] OR [filled 6-slot container]
118
128
  [profile-specific role] → ⚠️ GAP — plugin-recommender recommends: [X] (install? y/n)
119
129
  ```
120
130
 
@@ -203,7 +213,8 @@ sim-conductor does **not** run a fixed persona set. It derives needed perspectiv
203
213
 
204
214
  ```
205
215
  ① Installed first — scan installed plugins + .claude/agents/ for a matching persona/agent
206
- Built-in fallbackinject role as prompt directive into general-purpose Agent (Path B)
216
+ Container fillfill the 6-slot persona container for the standpoint; the filled container IS the
217
+ dispatch prompt into a general-purpose Agent (Path B — replaces the old ad-hoc role directive)
207
218
  ③ External fetch — chain to /plugin-recommender when ①② insufficient for high-stakes tasks
208
219
  ```
209
220
 
@@ -220,7 +231,7 @@ FH ships a coherent **user-mastery spectrum** as real, reusable agents (not prom
220
231
 
221
232
  > **Lineage**: `beginner` / `main-player` / `expert` are the FH-native frontier successors to the field deep-insight `user` group (newcomer / power-user) — re-derived to FH grade with embedded methodology + Done-When, not name-copied. `challenger` is the advanced form of the field `devil-advocate`. The former standalone skeptic standpoint is folded into `challenger` U1.
222
233
 
223
- **Ad-hoc roles** (② tier — prompt-directive fallback): when the profile demands a standpoint with no shipped agent (e.g. "security auditor", "non-native reader"), inject the role as a directive into a general-purpose Agent. Prefer ① shipped agents; use ② only for genuinely task-specific one-offs.
234
+ **Ad-hoc roles** (② tier — container fill): when the profile demands a standpoint with no shipped agent (e.g. "security auditor", "non-native reader"), fill the 6-slot persona container for that standpoint the filled container is the dispatch prompt. Prefer ① shipped agents; use ② only for genuinely task-specific one-offs.
224
235
 
225
236
  #### Scale
226
237
 
@@ -229,8 +240,30 @@ FH ships a coherent **user-mastery spectrum** as real, reusable agents (not prom
229
240
  | **Minimum** | 3 | Routine Area A — most task-relevant 3 perspectives |
230
241
  | **Extended** | 4–8 | High-stakes publish / external release |
231
242
  | **Full** | Up to 16 parallel | Pre-major-version / architecture review |
232
-
233
- All personas run as **parallel Agents** — no sequential bottleneck. Use agent-composer Medium/Large fan-out for Extended/Full.
243
+ | **Crowd** | 16+ — **no fixed cap; bounded by the marginal-coverage stop** | Only when the marginal-coverage stop has demonstrably **not** fired at 16 — i.e. persona #17 is still decorrelated and finding-productive. **Not** chosen by artifact size or audience count (Full already covers those); the stop, not a headcount, opens this tier |
244
+
245
+ **Crowd is output-driven, never a target** (per the container schema): the 16-cap lifts only behind the
246
+ **marginal-coverage stop** — add a persona only if it is *decorrelated* (a distinct viewpoint, or — at
247
+ crowd scale — a different model family) from those already running; **stop when the marginal new-finding
248
+ rate → 0**. A crowd of identical-output personas is decorative (steel-quench Wave-1 angle #1). Do not
249
+ name a headcount goal; the count is whatever the stop allows.
250
+
251
+ **Cost-tier routing (the economy lever)** — each persona's `cost-tier` slot routes it to a model so
252
+ breadth is cheap and the verdict stays trustworthy:
253
+ - **floor-local / heavy-local** (e.g. a local Ollama sidecar) carry cheap *breadth* — extra decorrelated
254
+ standpoints at near-zero token cost. A heavier local (27–32B) is a stronger canary than a floor model,
255
+ but **on one probe, not a benchmark** (`[[persona-container-schema]]` §tier-distribution) — so a local
256
+ tier is a **canary, never the gate**.
257
+ - **frontier** carries the **terminal verdict** — the M/S/R triage and any auto-commit decision stay
258
+ frontier. This is the same anchor as Step 0.6: local breadth *decorrelates*, it does not *decide*.
259
+ - Cost-tier routing and the Step 0.6 cross-model gate are complementary, not duplicate: 0.6 *requires* a
260
+ non-session source for risk≥medium (blind-spot closure); cost-tier *distributes* breadth for economy.
261
+ A local-sidecar persona can satisfy both at once (cross-family **and** cheap), but only Step 0.6's
262
+ quoted-artifact rule lets it count as `external` coverage.
263
+
264
+ All personas run as **parallel Agents** — no sequential bottleneck. Use agent-composer Medium/Large
265
+ fan-out for Extended/Full; Crowd scale dispatches in decorrelated waves, re-checking the marginal-coverage
266
+ stop between waves rather than firing all at once.
234
267
 
235
268
  **Simplification guard**: Routine internal audits → ② built-in fallback at Minimum scale. Chain to ③ only when a needed perspective has no ①② match, or stakes are high.
236
269
 
@@ -296,7 +329,7 @@ Persona composition adapts to `artifact_type` from Step 0.3 profile:
296
329
  | Prompt / config | `beginner` | challenger | Interpretation errors, implicit assumptions |
297
330
  | Auth / security-sensitive | challenger + Security-auditor† | `main-player` (Heavy) | Attack surface, privilege escalation |
298
331
 
299
- † Security-auditor = built-in fallback role (② tier) injected as prompt directive.
332
+ † Security-auditor = ② tier — the 6-slot persona container filled for a security-auditor standpoint.
300
333
 
301
334
  All personas run in parallel. Findings = M/S/R → M-tier items fixed immediately.
302
335
 
@@ -356,6 +389,10 @@ positives erode reviewer trust.
356
389
  - Priority labels verbatim — Critical/Important/Suggestion carried as the persona set them.
357
390
  - No forced consensus or forced conflict — report Common opinions (2+ personas agree) and Conflicts
358
391
  (position A vs B, each with rationale) as-is. Feeds Step 2 M/S/R triage (M ← Critical or 2+ personas).
392
+ - Cost-tier aware triage — a frontier-tier persona's verdict is terminal; a floor/heavy-local persona's
393
+ finding enters only as decorrelated **breadth** (it can raise a standpoint to `covered`, never solely
394
+ set an M-tier on its own). This enforces in the aggregator the §Scale "local breadth decorrelates, it
395
+ does not decide" lock — without it, a local canary's finding would drive triage identically to frontier.
359
396
 
360
397
  **Zero-coverage map (mandatory synthesizer output)** — the synthesizer must emit, mechanically, the set
361
398
  of standpoints that produced **no** finding, not only the ones that did (judge-robustness swarm,
@@ -441,6 +478,30 @@ as normal. (This withdraws one privilege, not the run — the report and fixes s
441
478
 
442
479
  ---
443
480
 
481
+ ## Step 5 — Graduate a Proven Persona (optional, rare)
482
+
483
+ Most synthesized personas are **throwaway** — the run accelerated the work and the persona is discarded.
484
+ A persona earns a permanent home only by passing the container schema's **admission test** (the analogue
485
+ of "app-ification"; `[[persona-container-schema]]` §Lifecycle):
486
+
487
+ | Check | Criterion | Class |
488
+ |---|---|---|
489
+ | **Recurrence** | surfaced **≥1 unique S/M finding** (one no other persona in the run produced) across **≥2 distinct targets** — not a one-off lucky fire | measured |
490
+ | **Trust bar (skills only)** | if graduating into a *skill* rather than a project's persona set, additionally clears the **FH 6-item creation gate** | mandatory-pass |
491
+
492
+ - **Pass → into a project's static set**: route the write through `asset-placement-gate` (expected
493
+ verdict: project-local) before writing the filled container to the project's persona file (e.g.
494
+ the-bible `core/personas.json`) — sim-conductor proposes the target, the placement gate confirms it,
495
+ the operator approves. A project-local asset, not an FH change, but the cross-boundary write is still gated.
496
+ - **Pass → into a skill**: route through `asset-placement-gate` + the New-Skill creation gate (the
497
+ skill-foundry inversion — the trust bar is non-negotiable). This is **HITL**, never auto-graduated.
498
+ - **Fail the recurrence check** → stays ephemeral. Do not graduate on a single run.
499
+
500
+ Graduation is **never automatic** and is **out of scope for auto-commit** — it is a deliberate,
501
+ operator-approved promotion. A clean simulation that graduated nothing is a normal, complete run.
502
+
503
+ ---
504
+
444
505
  ## Human Gate Principle
445
506
 
446
507
  Convergence within an AI-AI loop is **provisional**. Elevated to final only after human gate.