brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
auto-decorrelationRecruits cross-family verifier sidecars (codex, agy, local 4090 over Tailscale) for adversarial verification of load-bearing changes, maximizing model-family diversity against the orchestrator. Mechanically discovers the available sidecar panel, recruits at least one cross-family verifier when present, and degrades gracefully when none are. The governor (Cl…
Independent GitHub snapshot · Automated classification · Original documentation governs
The lever for catching a model's blind spots is decorrelation, not repetition — a model cannot find its own family's flaws by repeating itself. FH's adversarial verification (Axis-2 challenger) dispatches in-session at the session tier, same family as the governor. When frontier CLIs are installed and a local GPU box is live, leaving them idle wastes the one thing that actually raises the verification ceiling. This skill recruits a cross-family verifier for load-bearing changes — and degrades honestly when none is available.
It is a thin recruitment-and-degrade policy that REUSES existing machinery: agent-composer does the
actual dispatch, cross-ecosystem-synergy-detection inventories tools, token-budget-gate gates spend,
the headless CLI patterns and the floor-tier canary already exist. Net-new = the discovery + the
family-diversity recruitment + the degrade ladder only. (A composing policy skill — it fans out to
several callees, so its token floor is higher than a leaf skill by design; this is composition, not
reinvention, and the chain is return-path-closed — Step 5 gates acceptance on the callee's back-trace.)
External-CLI calls and credit spend are never silent. Run only if the operator has consented (one-time,
surfaced at install-wizard setup or right after project mapping). Consent is stored in the UAP
(tracks/_meta/user_adaptation_profile.md — behavioral pref, not domain content). No UAP / no consent
(incl. ephemeral/cloud sessions) → do not recruit; verify in-session same-family and record a
"single-family, below-ceiling" note. Consent wording is honest by requirement: "멀티-CLI 사이드카로
단일 모델을 넘어서는 효과를 기대할 수 있습니다 — 100%는 아님(decorrelation은 향상이지 보장 아님).
가용 사이드카 없으면 자동으로 단일 세션으로 축소됩니다."
Fire only on load-bearing changes — the same predicate as the target-tier sim gate: gate infra · onboarding scaffolds · destructive/publish paths · routing/gate skills · or any change whose output another skill/gate consumes as trusted input (a new synthesis/analysis skill, a corpus writer) — the predicate tracks downstream trust, not only whether the artifact is itself a gate. Ordinary additive edits stay in-session (cost guard). Consent ON ≠ always-fire: a small/low-stakes check silently stays single-session even when sidecars are available.
Build the available panel at run time; absent tools and unreachable endpoints drop off silently:
# Sidecar-callable CLIs only. **Scope discipline**: the probe list is NOT "every agent CLI that exists".
# FH's main is Claude Code (vendor-native — `[[feedback_vendor_native_harness]]`), and the recommended
# cross-family sidecars are **codex and gemini/agy**. Other agent CLIs on the machine (opencode, qwen,
# hermes, cursor-agent …) are **runtimes a user works INSIDE**, not verifiers FH calls out to — being
# installed is not a reason to probe them. Adding one costs a maintenance surface and dilutes the panel;
# add only when a concrete task needs that family. (2026-07-19: four were added off a general CLI
# catalog and removed the same session — installed ≠ belongs in the panel.)
command -v codex >/dev/null && echo "codex" # GPT family CLI
command -v agy >/dev/null && echo "agy" # serves Gemini AND GPT-OSS — probe the model
command -v gemini>/dev/null && echo "gemini"
command -v gh >/dev/null && gh copilot --help >/dev/null 2>&1 && echo "copilot"
# ↑ gh EXTENSION, not a binary — `command -v copilot` misses it, and
# `gh copilot --help` shows only the LAUNCHER (its sole flag is
# --remove); the real flags live behind `--`.
# Call form (verified 2026-07-19 by live call — credits were consumed):
# gh copilot -- -p '<prompt>' --model <model> --allow-all-tools
# **Same class as codex/agy**: `--model` selects among several families
# behind ONE CLI ('auto' lets Copilot pick), so family MUST come from
# the pinned/probed model (Step 3), NEVER from the CLI name.
# ★ SEAT TIER CHANGES ITS VALUE ENTIRELY — probe, never assume:
# · free seat → narrow model choice; treat as ONE extra family
# · enterprise seat → serves GPT, Gemini AND Claude behind the single
# CLI: a THREE-FAMILY panel with no other CLI installed
# ([[reference_corp_env_decorrelation_panel]]).
# ⚠️ BUT each family runs on Copilot's harness, not its vendor-native
# one — Claude-via-copilot ≠ Claude Code, GPT-via-copilot ≠ codex,
# Gemini-via-copilot ≠ agy. Per `[[feedback_vendor_native_harness]]`
# a non-native harness costs depth. So copilot buys **breadth cheaply,
# not depth**: use it to widen the panel, and route the decisive
# check to the vendor-native CLI when one is reachable. Same shape as
# the local canary tier (breadth ≠ terminal depth, measured 2026-07-19).
# Because the panel it yields depends on the seat, Step 3's model probe
# is not optional here: enumerate what this seat actually serves before
# claiming family diversity.
# Cost shape: paid-seat credits. That makes it a strong *sidecar* but a
# poor main driver — seat quota is spent faster than it is worth when
# it drives the whole harness. Recruit it for decisive checks, not bulk.
# Residual: the launcher may fetch the CLI body on first call, so on a
# cold machine the first recruit pays a download.
# Local ollama serving-paths = canary tier (electricity-only). mac localhost is public → probed
# UNCONDITIONALLY. Any extra path (e.g. a Tailscale GPU box) is an operator-private token → read from a
# gitignored binding, NEVER hardcoded in this public file. Both mac-serving (H2) and 4090-serving (평시)
# are covered: whichever box is not serving simply fails the probe and drops off.
# probe() validates the /api/tags SCHEMA, not just a reachable port: -f rejects HTTP 4xx/5xx and the
# `"models"` grep rejects a non-ollama server or an empty/overloaded instance — else a dead box reports
# live (false-positive discovery). Endpoints are only ever curl-probed here, never eval'd.
probe() { curl -fsS -m"${2:-6}" "http://$1/api/tags" 2>/dev/null | grep -q '"models"'; }
probe localhost:11434 && echo "ollama-local(mac)"
EP="$FH_SIDECAR_EXTRA"
[ -z "$EP" ] && [ -f tracks/_meta/sidecar_endpoints.env ] && \
EP="$(grep '^OLLAMA_EXTRA=' tracks/_meta/sidecar_endpoints.env | cut -d= -f2- | tr -d '"')"
# Split on NEWLINES via `while read`, never on an unquoted `for e in $EP`. Word-splitting an unquoted
# variable is a BASH behavior; zsh does NOT word-split, so under zsh a space-separated multi-endpoint
# list arrives as ONE string, hits the charclass below (space is not in it) and is dropped — silently
# reporting "no extra sidecars", i.e. the single-family fail-open this skill exists to prevent.
# Measured 2026-08-11: `EP="host1:11434 host2:11434"` → bash probes 2, zsh probes 0.
# Accepts either separator: commas/spaces are normalized to newlines first.
printf '%s\n' "$EP" | tr ' ,' '\n\n' | while IFS= read -r e; do
[ -z "$e" ] && continue
case "$e" in *[!0-9a-zA-Z.:-]*)
# NEVER a silent `continue` — a dropped endpoint must be visible, or an unprobed panel is
# indistinguishable from an unavailable one (DEGRADED_PANEL_UNUSED vs DEGRADED_SINGLE_FAMILY).
echo "sidecar-endpoint DROPPED (not host:port form): [$e]" >&2; continue;;
esac
probe "$e" 10 && echo "ollama-extra($e)" # -m10: a sleeping GPU box may wake slower than 6s
done
Shell note: this block is sh-portable and is written so bash and zsh behave identically. Any
future edit that reintroduces for e in $EP re-opens the zsh drop above. A drop line on stderr is a
finding, not noise — carry it into the Step 6 degrade verdict rather than discarding stderr.
Endpoint resolution is a mechanical env/file read (not a prose instruction the runner must remember),
so this discovery is tier-independent — no target-tier sim owed. The extra-endpoint binding lives only in
the gitignored tracks/_meta/sidecar_endpoints.env (auto-synced to the companion store); the public skill
carries the probe logic, never the address.
Tag each verifier by the model family actually serving the request, probed — not the CLI binary name.
agy serves both Gemini and GPT-OSS 120B, so "agy = Gemini" is wrong; resolve via the CLI's
--model/served-model. The binary→family table is only a fallback default. Recruit to maximize family
diversity vs the orchestrator (orchestrator = Claude/opus → recruit GPT or Gemini or local-Qwen).
Cost order: local 4090 = electricity-only (cheapest — use for breadth pre-screen) · codex headless = hard-capped credit pool · agy = operator Gemini sub. So: local-Qwen for cheap breadth, then ONE frontier cross-family for the decisive check.
Spend gate (S-1): the free local tier auto-fires silently; any paid draw (codex/agy)
surfaces a one-line token-budget-gate ask per run ("recruiting codex (~N) — proceed?") unless the
operator has set paid_auto: true in the UAP. One-time feature-consent ≠ consent to this spend now.
Dispatch via agent-composer (no re-implementation of dispatch).
Wait mechanically — scripts/sidecar_wait.sh is the required form, not a suggestion (S-1b).
The rule, before the command, because a Sonnet-tier blind sim of this section said the command reads as "the content" and everything after it as "color commentary" — and named peeking at the output file as the first thing it would do wrong in a hurry:
Never judge a sidecar by looking at its output file. A live process and a dead one produce the same zero bytes. The only readable verdict is the typed
SIDECAR_VERDICT=line, and it does not exist until the process has exited.
printf '%s' "$prompt" | bash scripts/sidecar_wait.sh out.txt 900 -- codex exec -m gpt-5.5 -
# → SIDECAR_VERDICT=COMPLETE exit=0 bytes=48489 (read out.txt)
# → SIDECAR_VERDICT=TIMEOUT waited=900s bytes=0 (still alive — NOT a result)
# → SIDECAR_VERDICT=EMPTY exit=0 (the only state that means "it said nothing")
The runner refuses to emit a verdict while the process is alive, so "the sidecar returned
nothing" becomes unsayable until it has actually exited. Grep the typed SIDECAR_VERDICT= line;
never judge by looking at the output file.
Why this is mechanical rather than a habit — the bullets below already described bounding a
sidecar, and a session that had them loaded still got it wrong on 2026-07-29: it backgrounded
codex exec and agy -p, read the output files after 1 s and 30 s, found them empty, and
recorded "both sidecars returned 0-output" into a gate marker, a PR body, a session card, a
memory file and a handoff. Both were running normally and both answered — codex with 48 KB and
three findings, agy with a further HIGH, and all four were real; one of them showed the change
under review was over-applied. So the measurement error nearly retired a working mechanism.
That is a second failure mode this section did not cover. The bullets below describe a hung sidecar. An impatient read of a healthy one produces the identical observation — zero bytes — and only one of the two is a fault. Distinguishing them requires process state, which is exactly what a human eye on an output file cannot see and the runner always reports.
Liveness / hang-catch (the runner does the waiting; this is how to read a TIMEOUT). A backgrounded CLI that hangs
(stuck on a sandbox/file-tool prompt, auth, or network) does not exit, so the background-completion
signal never fires — passive waiting is the wrong model and silently stalls the run (observed
2026-06-27: a codex exec that asked to read repo files hung at 0-output with no session log, and the
turn waited on a notification that could not come). So bound it actively, never wait open-endedly:
TIMEOUT, watch a progress signal, not just process-alive: output bytes growing and the CLI's own
session/log advancing (e.g. ~/.codex/sessions/<today>). 0 output and no session created after a
short bound (≈2–3 min for codex/agy) = hung, not slow → kill and recover, do not keep waiting.{ instructions; cat file1; cat file2; } | codex exec -
succeeded where reading-files-itself hung) — or degrade to single-session with a recorded note.
This is the sidecar twin of mcp-circuit-breaker (stop a stuck external call instead of hanging on it).Every payload this skill sends outward — the diff, the marker (Step 5's payload), the prompt
text itself — crosses a family boundary the moment a codex/agy/gemini sidecar is recruited.
"Sanitize before external-family dispatch" used to be a prose reminder with no consumer reading it
back ([[feedback_half_externalization_slot_without_consumer]] shape — a slot that exists but
nothing downstream checks). This step makes it mechanical:
python3 scripts/residency_closure_scan.py --files src/a.py docs/b.md # every file you are about to send, as separate args (zsh: ${=var}, never an unquoted "$var")
--files (not the default closure-walk) because what matters is what you are actually
sending, not this skill's own dependency graph. Read the exit code, not the words:
| Exit | Meaning | What to do |
|---|---|---|
| 0 | CLEAN — no organizational identifier found within the scanner's own stated limits (see its header — this is a screening result, not a safety guarantee) | Send. Record residency=CLEAN(files=N) in the crossfamily grounds (Step 6). |
| 1 | TAINTED — at least one payload file matched a residency pattern | Do not send as-is. Either strip/redact the tainted file(s) from the payload and re-scan, or route to an in-boundary panel member. If it truly cannot be cleaned, record residency=TAINTED(N files, stripped=no) and do NOT dispatch — the crossfamily value becomes a DEGRADED_* rung, never panel(...). |
| 10 | HARNESS_ERROR — the scan itself could not run (commonly: no operator-private .claude/rules/.residency-patterns override on this machine — the shipped .defaults file alone is deliberately insufficient to claim CLEAN, per the scanner's own header) | Do not send. Record residency=NOT_SCANNED(<reason>) — same as exit 1's outcome (no dispatch), different reason (could not screen vs screened and found something). |
🟥 On a fresh install with no operator pattern file, this WILL be exit 10 every time — that is
the scanner's own documented fail-closed default (residency_closure_scan.py's header: "오버라이드
파일이 없으면 exit 10 이다"), not a bug introduced here. It means: until an operator configures
their own residency patterns, this skill cannot claim a panel dispatch was screened, so it honestly
degrades to a DEGRADED_* rung with residency=NOT_SCANNED(...) instead of silently sending. That
is not a new block on fresh installs — the crossfamily field already tolerates DEGRADED_* without
hard-failing the commit; it is one more honest reason to be in that state, not a novel one.
Where the result lands: templates/.git-hooks/pre-commit's validate_crossfamily_leg now
requires a residency=CLEAN(...) token inside the grounds of any panel(...) value (grace date
RESIDENCY_TOKEN_GRACE_DATE, no retroactivity on markers dated earlier), and accepts an optional,
format-checked residency=(CLEAN|TAINTED|NOT_SCANNED)(...) token on DEGRADED_*/UNKNOWN/
declined. Fixtures: scripts/test_marker_crossfamily_lanes.sh (r1–r13). This is the SAME
typed field Step 6 already emits into — one channel, not a second marker line.
evidence= : say WHAT the panel received (mandatory with panel(...), 2026-09-12)residency= says the payload was safe to send. evidence= says what was sent — and that is the
axis the outside world just measured as the dominant one. arXiv:2609.10969 (48 task templates →
2,880 scenarios, fixed call budget so the comparison is about the axis and not about spending
more): a cross-model vote over shared evidence approved 62.9 % of unsafe proposals against
22.9 % with an independent source — source effect 40.9 pp vs 11.3 pp for model
diversity, i.e. 3.6×.
Decide it from how this run actually dispatched, not from intent:
| What happened | Token |
|---|---|
| Every member got the same payload (one prompt file / one diff fanned out) | evidence=SHARED(<name the artifact>) |
| Each member produced its own evidence — own checkout, own run, own extraction | evidence=INDEPENDENT(<what each got>) |
| Some of each | evidence=MIXED(<which member got which>) |
🟥 This skill's default flow is SHARED, by construction. Step 4 builds one payload and fans
it out, so a panel dispatched the ordinary way through this skill is the 62.9 % arm — the axis it
raises is model family, which the paper prices at 11.3 pp. That is not a reason to stop using it: a
finder is worth its recall, and this skill's value was never precision
([[feedback_decorrelation_is_a_cheap_finder]]). It is a reason to stop recording that run as if
it carried the stronger axis. Write SHARED and mean it.
🟢 SHARED is a legal, expected answer. The hook does not block it; it blocks a panel(...) that
does not say which it was, a value outside the closed three, a malformed or duplicated token, and a
vacuous body on SHARED/MIXED (name the artifact — "same staged diff", "one findings.jsonl",
"identical prompt file"). INDEPENDENT is self-describing and is not body-checked, deliberately:
over-blocking the honest strong answer would train the override.
Where it lands: the same grounds line as residency=, in the same crossfamily: field —
crossfamily: panel(codex) — residency=CLEAN(files=3) · evidence=SHARED(same staged diff to both) · R1, 3 findings.
Hook: validate_crossfamily_leg (grace EVIDENCE_TOKEN_GRACE_DATE, no retroactivity).
Fixtures: scripts/test_marker_crossfamily_lanes.sh e1–e10.
⚠️ Named gap, not built today: this skill has no independent-source mode. Giving it one (each member reconstructs the evidence itself rather than reading the author's payload) is the change that would move it onto the 40.9 pp axis; it is a design question, not a wiring one, and it is recorded as a signal rather than improvised here.
🟥 A stripped file is invisible to the reviewer, and a reviewer's default read of invisible is
"absent," not "redacted" (governor dogfood, 2026-09-05, same-day live use of this Step): two
TAINTED files were stripped from a real payload and the CLEAN remainder sent cross-family — the
reviewer came back with a false-positive S-finding, "runner wiring is missing," because the
wiring actually lived in one of the two files that had just been stripped. Stripping fixes
residency; it does nothing about the reviewer's next inference, and silence there reads as a hole.
So: whenever a payload is sent with stripped > 0, the review PROMPT itself must name the
omission explicitly — the list of what was left out, and one line per file on what it is
responsible for (not its content, just its role) — so the reviewer can discount that surface
instead of flagging it as missing. Record whether this was done: when the token carries
stripped=M with M > 0, the same grounds line adds one phrase on whether the omission list
reached the review prompt, e.g. residency=CLEAN(files=3, stripped=2) · omission-list: given to reviewer. This is evidence-of-doing, not proof — same shape as Step 5's "quote one marker line it
checked," and it does not become a new hard-blocking hook check (channel discipline stays a
grounds phrase here, per the same Mechanization Boundary this whole field already respects).
⚠️ Scope, same as everywhere else in this file: CLEAN is a screening result, not a safety
guarantee (dynamic imports, non-Python artifacts, encoding tricks, and TOCTOU are named, unclosed
gaps in the scanner's own header). Recording residency=CLEAN(...) asserts the scan ran and found
nothing within those limits — it does not assert the payload is safe in some absolute sense.
CC = governor, terminal verdict, source-closes. Sidecars = decorrelated challengers feeding findings — untrusted external input (prompt-injection surface, like an MCP result). Every sidecar finding must carry a source-locatable claim (file:line / quoted text); the governor mechanically re-checks it against the artifact (phantom-quench back-trace) before accepting. A finding that cannot be source-grounded is dropped, not judged. No sidecar-only verdict (no weak-local-judge regression). Local 4090 = canary tier (evidence-of, never terminal verdict).
Report shape (2026-09-05): when the findings are written up (PR body · marker crossfamily: expansion · chamber record),
use templates/RED_TEAM_REPORT.md — the five sections mirror ISO/IEC AWI TS 42119-7 (risk identification · objectives & attack
vectors · method · findings with reproducing input · life-cycle integration). It is a name tag on what this skill already
produces, not a new check; crosswalk: knowledge/shared/harness-core/iso_ai_standards_crosswalk.md §2.
🟥 What you SEND decides which axis you get — put the MARKER in the payload, not just the diff
(2026-08-19). Sidecars have been receiving the diff only. That buys a review of the code and
buys nothing on the record: the Axes 2+3 marker is self-attested, and this repo has already
written down that the closing move is "cross-family reading that marker" — then never wired the
marker into the thing that recruits cross-family. Measured twice: (a) a release marker's false
not-applicable passed the new typed lanes untouched, because form was correct; (b) this skill's
own dispatch on 2026-08-19 sent a diff and no marker, so the round could not have caught a false
axis claim even in principle.
So the payload is two parts: the frozen diff and the marker for this change — as it stands
at dispatch time: axes-run: · controls: · standpoint: · thirdparty: · residual:.
🟥 crossfamily: is NOT in the payload — it is this round's OUTPUT. Step 6 below says every rung
emits that value and "the rung is not done until its verdict is recorded", so requiring it in the
thing you send is circular: you would be shipping a field this dispatch has not produced yet. Send the
marker with that line absent or UNKNOWN, and fill it from the result. (Caught by a blind
floor-tier sim of this very paragraph, 2026-08-19 — the first draft listed crossfamily: among the
payload fields and no reader could have satisfied it.) Ask the sidecar one extra
question: "does the record match the diff — is any axis claimed that the diff shows no trace of, and
is any residual missing that the diff implies?"
⚠️ Scope, deliberately narrow. This asks whether the record is consistent with the artifact. It does NOT ask the sidecar to score honesty — «is this marker truthful» is a conclusion, and §Mechanization Boundary forbids freezing that into machinery. Consistency is checkable from two documents; honesty is not. ⚠️ You cannot observe that the sidecar READ it — say so rather than implying otherwise. Putting the marker in the payload and the sidecar actually using it are different events, and nothing here distinguishes them: a silently-ignored marker looks exactly like a marker that was read and raised nothing. The cheap partial anchor is to require the return to quote one marker line it checked — a reply that quotes nothing did not demonstrably read it. That is evidence-of-reading, not proof, and it does not close §Mechanization Boundary's named self-attestation residual. Three independent readers flagged this same gap on the day the paragraph was written (a peer session, and two blind floor-tier sims), which is why it is stated here instead of left to the reader to notice.
⚠️ Prose, not a check — measured recurrence is 2, below this repo's own N≥3 bar
([[feedback_mechanize_at_repetition_prose_before]]). On the third occurrence, mechanize it here.
⚠️ Residency still governs: a marker can name company assets. Run Step 4.5's screen against the
marker file too, not just the diff — the marker is not exempt because it is metadata. (This line was
pure prose until 2026-09-05; Step 4.5 above is what closes it — the scan itself still carries the
named, unclosed gaps in its own header, so "screened" is not "guaranteed safe".)
Origin: sister-asset read of raphaelchristi/harness-evolver's harness-critic agent, whose whole
role is auditing the evaluator rather than the artifact. Its detection signatures (score jumps,
suspiciously fast convergence) do not port — FH markers carry no score — but the target does.
Full assessment incl. what was deliberately not imported: tracks/_audit/proposal_2026-08-19_sister_harness-evolver.md.
Target freeze — a prior drop reason, checked before any of the above (2026-08-17). Grounding a finding against today's tree proves nothing if the sidecar reviewed yesterday's. Pin before dispatch and verify on return:
bash scripts/target_freeze.sh pin "$REPO" "$ROUND_LABEL" # 발주 직전
bash scripts/target_freeze.sh verify "$REPO" "$ROUND_LABEL" # 회수 직후
rc 1 = WRONG-TARGET → drop the whole round's findings, not individual ones — the round read a
tree that moved under it, so which findings survive is not decidable from the output. rc 10 =
UNKNOWN (could not measure) — that is not a pass; re-pin and re-dispatch. Measured trigger: three
occurrences in one day, one of which was sending a sidecar a pre-repair diff and then grounding
its findings against the repaired tree — every finding "failed to ground", and the instrument, not
the reviewer, was wrong.
🟥 What this does NOT cover: §L191's inlined-file pattern. When the prompt carries file contents on stdin (the robust form for sidecars that have no file tools), the tree freeze says nothing about what bytes you actually sent. That binding is still owed and is not claimed here.
Consent branch first — declined ≠ degraded ([[capability_escalation_consent]]): if the UAP has
sidecar_consent: declined, do not probe/recruit — route straight to Tier-3 CC-only sub-agent
verification (multiple isolated Claude sub-agents, isolation-decorrelation) as a first-class chosen
mode, with an honest same-family note but no "reduced value / degraded" framing — the user chose
this floor. unset → ask-once at first load-bearing need (accept → proceed; decline → record + this
branch). Only proceed to the discovery ladder below when consent is accepted.
Every rung emits a typed crossfamily: value into the Axes 2–3 marker — the rung is not
done until its verdict is recorded. The value is a closed enum, validated by pre-commit
(validate_marker_floor, fixtures in scripts/test_marker_crossfamily_lanes.sh); free prose is
rejected at commit time.
| # | Panel state | Emit | Ack |
|---|---|---|---|
| 1 | frontier cross-family CLI present → recruit it (decorrelated, at-floor) — best | panel(<families>) | — |
| 2 | only local 4090 → canary pre-screen + in-session opus governor (canary, not full decorrelation) | panel(<families>) only if a capable non-Claude model actually reviewed; otherwise rung 3 | — |
| 3 | probed and nothing capable reachable → in-session same-family | DEGRADED_SINGLE_FAMILY | required |
| — | capable panel reachable, not recruited (a choice, not a constraint) | DEGRADED_PANEL_UNUSED | required |
| — | consent declined (branch above — chosen floor, not a degrade) | declined | — |
| — | change is not load-bearing — decorrelation not required | single-family | — |
| — | panel never probed | UNKNOWN | required |
🟥 Rungs 1–2's panel(<families>) additionally require a residency=CLEAN(...) token inside the
same grounds string, since 2026-09-05 (Step 4.5 above; pre-commit's validate_crossfamily_leg
blocks a bare panel(...) with no such token on a marker dated on/after
RESIDENCY_TOKEN_GRACE_DATE). Full grammar:
crossfamily: panel(codex) — residency=CLEAN(files=7) · R1..R2, 4 findings
crossfamily: DEGRADED_SINGLE_FAMILY — residency=TAINTED(2 files, stripped=no) → not sent, probed codex/agy, 0 reachable
crossfamily: DEGRADED_SINGLE_FAMILY — residency=NOT_SCANNED(no operator pattern file) → not sent, probed codex/agy, 0 reachable
The token is optional on DEGRADED_*/UNKNOWN/declined (format-checked only when present —
those rungs never claimed anything left the boundary, so nothing to require) and rejected as a
contradiction if panel(...) carries residency=TAINTED( or residency=NOT_SCANNED( on the same
line — a sent payload and an unscreened/tainted one cannot both be true.
The three degrade values are the load-bearing split: could not (DEGRADED_SINGLE_FAMILY) ·
did not (DEGRADED_PANEL_UNUSED) · did not look (UNKNOWN). Free prose merges all three, and
each merge hides a different thing — an unrun probe renders as a zero finding
([[feedback_not_found_is_not_zero_family]]), and an unused panel renders as an unavailable one.
The sibling-harness signal that motivated this field said it in its own words about itself:
"못 한 것이 아니라 안 한 것이다." All three require an ack naming what was probed and what it
returned. DEGRADED_PANEL_UNUSED was added by dogfooding: the first real marker written under
this lane found the panel reachable (codex · agy · gemini) and no cross-family review run — a state
the original five-value enum could not express without lying
([[feedback_adversarial_review_not_substitute_for_first_use]]).
Panel membership is capability-gated, and ineligibility is tested FIRST. A runtime /models
list is a serving list, not a generative one. Measured in a sibling harness (2026-08-08): 6 of
14 served entries could not review anything (embedding · reranker · OCR · safeguard), and because
the embeddings' ids matched no family prefix each counted as its own family — satisfying the
family-diversity check while the panel was incapable. Order is the invariant, not the list:
GLM-OCR matches both ocr and glm, Qwen3-Embedding matches both embed and qwen, so an
eligibility-first test lets them through silently. If nothing capable survives the filter, that is
rung 3 — not a smaller panel.
Attribution: panel(...) records the families requested, not confirmed. At least one
procurement path (an internal corp-gateway CLI) returns no model attribution in its response, so "3/3 responded"
does not establish which model contributed. Record request-fact and response-fact separately; do not
launder the former into the latter ([[feedback_instrument_cannot_discriminate_hypotheses]]).
Env non-determinism (CLI presence varies) → never hard-fail the run — but never silent either.
The two are different properties, and the prose this replaces conflated them: the degrade proceeds
(a commit is a reversible surface) and lands in the verdict with an ack. That is how this rung
and CLAUDE.md §Field-Harness gate ("never a silent same-family pass") are simultaneously true.
Distinguish the unavailable-but-wanted case (consent given, panel down → DEGRADED_SINGLE_FAMILY
local_pmh_context.md — note that file is
pmh-repo-local and unreadable from an FH session, so on this side the typed value + ack is the
enforceable layer) from the declined case above (chosen floor, first-class, no degrade framing).Step 6.5 — Standpoint axis (2026-08-14, orthogonal to the family ladder above): for a
shared-body / cross-harness-boundary change — scoped by effect (alters another harness's
behavior, gate outcome, or interaction contract), not merely by touching a synced file path — also
emit standpoint: alongside crossfamily: in the same marker — recruiting family diversity here
does not substitute for it. Values: tier1 (content-only, the default) · tier1b(<harness>)
(STATIC read of the target's own files — executed nothing) · tier2(<harness>)
(peer-simulated — EXECUTED CODE in the target's own repo and observed the result.
🟥 Reading the target's real files, however cold, is tier1b, not this. The discriminator is
mechanical: name the command you ran and the output you saw; cannot name one → tier1b, always.
This line said "ran the target's own repo, content only" until 2026-08-17 — actively teaching
the opposite of the canon it summarizes. 🟥 RETRACTED (2026-08-17): this passage used to add
that blind Sonnet sims "STILL graded a pure cold-read tier2, both quoting this phrasing" after
the other two copies were fixed. Those runs had tool_uses: 0 — nothing was read, so nothing
was measured, and the claim that the sims "reached for this copy" was itself unfounded
(tracks/_meta/fh_completed_2026-08-16.md:690; the live re-run inverted the grade at reps=1, below
bar). The reason to fix this copy needs no sim: a summary that states the opposite of its canon
teaches the opposite to whoever reads only the summary, and two of three copies fixed is a fix
that does not exist — that is gate-locality, not a measurement. See §7 for the canon) · tier2b(<harness>) (same operator,
target's real runtime — local wiring visible, but not an independent reviewer) · tier3(<harness>)
(a different operator of the target harness ran it — the only fully independent + local-wiring
rung) · not-applicable (no target-harness standpoint exists — most same-repo dispatches) ·
DEGRADED_NO_TARGET_ACCESS / DEGRADED_NOT_RUN / UNKNOWN (own literals, not crossfamily's). Note
the naming collision with this session's own persona/viewpoint sense of "standpoint" (the beginner/
main-player/expert agent roster) — different axis, same English word; do not conflate.
Prose-only — no hook or fixture validates this field yet, unlike crossfamily:, and
mechanizing it is FH's own job (a syncing sibling harness cannot add the check locally without its
own sync process rejecting the divergence). Timing — same moment as Axis 2/3
(steel-quench/phantom-quench), not a follow-up: run on the local diff before the first push to
any remote (public or private — no visibility judgment to make), one unconditional rule regardless
of perceived risk — see field_verdict_crossfamily_gate.md §7 Sequencing for why (a real PR pushed
this exact field to a public repo with two residency leaks in view, caught only after the PR was
already open). Full field spec, trigger scope, and evidence:
knowledge/shared/harness-core/field_verdict_crossfamily_gate.md §7.
Done When (Step 6.5): standpoint: is emitted whenever the change is a shared-body/
cross-harness-boundary change by the effect-based trigger above; not-applicable carries grounds
on the same line naming what was checked; the review ran on the local diff before the first push
— a standpoint: value first recorded after the PR is already open does not satisfy this condition,
even if the value itself is correct [judged — no mechanical anchor today; adversarial pairing: a
reviewer/challenger may request both the grounds and the pre-push timing be shown in the PR capsule,
and reject a bare not-applicable or a post-hoc value].
Sidecar findings → existing synthesizer / Axes 2-3 marker. Marker honesty (M-3): record
axis2-engine: panel(<families>) only when a captured sidecar transcript (raw stdout / headless exit
metadata) is embedded — a panel claim without a captured transcript is recorded as same-family by the
weekly audit, not panel. Proven-uplift gate: the marker may call the panel uplift proven only
when a tracks/_meta/decorrelation_calibration_* file with N≥3 exists; below that it records "breadth,
not-yet-conclusive" (mechanical N≥3 check, not a prose label — closes the salience gap on a weaker tier). Contention (M-2): route to contention-layer ONLY when families return
opposite terminal verdicts on the same claim (one says S-blocker, other clean on the identical line) —
merely-different findings are normal decorrelation and union into the synthesizer; cap contention routing
at N per run (no loop).
crossfamily: value in the Axes 2–3
marker (panel(<families>) | declined | DEGRADED_SINGLE_FAMILY | DEGRADED_PANEL_UNUSED |
UNKNOWN); the three degrade values carry substantive grounds on the same line. single-family
is NOT accepted on a load-bearing change — that block only runs there, so "decorrelation not
required" is a contradiction, and as a no-ack pass it was a free bypass of the lane.
[mandatory-pass — enforced by pre-commit, fixtures scripts/test_marker_crossfamily_lanes.sh]panel(...) claim, and
its result is recorded as a residency=CLEAN|TAINTED|NOT_SCANNED(...) token inside the same
crossfamily: grounds — required when the value is panel(...), format-checked when present on
a degrade value. [mandatory-pass — enforced by pre-commit since RESIDENCY_TOKEN_GRACE_DATE,
fixtures scripts/test_marker_crossfamily_lanes.sh r1–r13]paid_auto set); free local tier may auto-fire. [mandatory-pass]tracks/_meta/decorrelation_calibration_*.md shows cross-family > same-family recall on a held-out
gate-bug set across N≥3; below N≥3 it recruits for breadth and labels uplift "measured, not yet
conclusive" (calibration #1 = 2026-06-21, modest lift). [measured]feedback_harness_ceiling_principle).