Skip to content

Red Gate protocol, lexicon v2, gap analysis + fixes, and the published example gallery - #75

Merged
JRichlen merged 42 commits into
mainfrom
claude/research-skills-agent-patterns-ihp49w
Aug 29, 2026
Merged

Red Gate protocol, lexicon v2, gap analysis + fixes, and the published example gallery#75
JRichlen merged 42 commits into
mainfrom
claude/research-skills-agent-patterns-ihp49w

Conversation

@JRichlen

@JRichlen JRichlen commented Aug 26, 2026

Copy link
Copy Markdown
Owner

A verifier-first operating protocol for agentic work, its research grounding, a working implementation, and the verification surfaces built around it — including a published before/after example gallery.

What this contains

  1. docs/red-gate-protocol.md — the spec: ARM/TRACE/JUDGE rounds with classified gates, a generalized verifier (runnable · proven able to fail · pinned · independently executed), lazy recursion, pointer envelopes, and a corrections ledger from adversarial review.
  2. docs/red-gate-glossary.md — the canonical lexicon (v2, adopted): ARM/TRACE/JUDGE, WITNESS, mandate, FAULT, scout/widen — plus the collision rulings and run-lifecycle verbs.
  3. plugins/redgate/ — driver, criteria-contract (ARM), reconcile (JUDGE), the hooks enforcement layer, calibration, and the protocol references.
  4. plugins/recurrence-detector/ — the growth loop's DETECT organ.
  5. Research — the 88-pattern agentic corpus, the phase-structure prior-art study (which settled "keep 3 stages"), and a 14-agent gap analysis (34 skeptic-verified gaps).
  6. Verification surfaces — a secret-scan gate, cross-plugin reference resolution, a context-tax budget, version-drift checks, untrusted-data provenance fences, a roster-level trigger-routing eval, a k-of-N statistical floor, and the published example gallery (real with-skill/without-skill model pairs, deployed to GitHub Pages).

Reflection, settled by research

Should rounds gain Reflect/Plan/Investigate phases? Researched against primary sources (PDSA, OODA, Polya, Kolb, the Scrum Guide, Beck's Canon TDD, ReAct, Reflexion, Self-Refine, CRITIC, LATS, ToT). Verdict: keep three stages. Reflection lives between iterations in every mature verified-work loop, and unenforced in-cycle phases evaporate. So it ships as gate obligations instead — a mandatory lesson field, a red verdict leaving a durable artifact the next ARM reads, and a widen cadence — plus an optional retro round type.

The blocking findings are fixed

An earlier re-review found four defects and this PR was parked with a "do not merge" banner. All four were re-verified as still live, fixed, and mutation-proven (reverting any one turns the cheap tier red):

  1. A missing trailing newline turned the red gate green. The emitted check.sh read loop silently dropped a final unterminated line, so a failing criterion written last simply vanished and the gate exited 0. Fixed; a new coupled check feeds an unterminated failing criterion and asserts the exit code.
  2. The evidence-freshness eval was uncoupled while labelled (exit-coupled) — it reused a fixture whose criteria failed anyway. Now runs on a passing fixture, where the gate is the only possible source of non-zero exit.
  3. The hook guard had zero eval coverage — gutting its deny path left the tier green. Four new checks drive the real handler and assert exit codes.
  4. Portability defects made the cross-harness claim false on macOS — GNU-only stat -c (every PASS read as stale), bare sed -i (half-pinned manifest on BSD), and a preflight hard-requiring timeout. All fixed with portable fallbacks.

Honest limit: CI is Linux, so the BSD/macOS branches are shape-checked (the fallback is present), not executed.

Also found and fixed: a live command injection

The adversarial verification pass on the gap fixes confirmed a real command injection in the graveyard delete-script generator — a repo name containing a double quote escaped the emitted BUNDLED="…" assignment and executed when the user ran the delete script, outside the bundle-existence guard that is the tool's entire safety premise. Reproduced end to end, then fixed by rejecting anything outside GitHub's [A-Za-z0-9._-] charset. The fuzz group now asserts defense-by-rejection across eight hostile name classes.

Example gallery

Real prompt/response pairs showing what each skill changes, with and without it, published to GitHub Pages beside the plugin docs. Every pair is a provenanced model run, never hand-written; the cheap tier refuses any snapshot lacking two real outputs plus provenance, and the page is regenerated deterministically from committed snapshots. A biweekly workflow captures fresh graded pairs and opens a review-gated PR.

Evals

Cheap tier: 1171 passed, 0 failed. Every new guard in this PR is mutation-proven. The behavioral tier gains a routing pack (deterministic, grader-free) with a k-of-N pass floor; the deep tier runs on the graveyard safety-path change.

🤖 Generated with Claude Code

https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU

…skills

The marketplace has 24 single-invariant skills and nothing that composes
them. Red Gate is the design of record for that: a self-similar three-stage
process triggered from a one-line idea.

Produced by a 12-agent workflow — four parallel survey agents (external
orchestration-pattern research, recursion/termination and spec-first
research, token-efficient-handoff research, plus a read of every shipped
SKILL.md), three divergent candidate designs, two judges on separate
lenses, one synthesis, two adversarial critics.

The core refinement of the original idea: criteria defined up front are
not enough, because criteria written but never executed are self-report.
BEGIN must emit a check.sh that executes and returns FAIL on every
checkable criterion before any work starts. Criteria that cannot go red
are not criteria.

Critics returned 27 findings, 5 fatal (2 found independently by both):
unpinned check.sh let the writer edit the checker; recursion mutated the
sha-pinned contract so every successful split self-destructed; the
crash-is-not-red rule deadlocked all greenfield work; red proved a check
fails but not that it measures anything; budget halved per child but never
across siblings. All five fixes are folded into the spec and recorded.

Ships the doc plus the source of the interactive map (docs/assets/).
Cheap tier green (exit 0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
Copilot AI lite review requested due to automatic review settings August 26, 2026 02:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The spec has an internal inconsistency in the BEGIN “preflight” definition that would block the intended red-gate behavior for greenfield binaries, and the new HTML artifact should declare a doctype to avoid quirks-mode rendering.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds Red Gate to the repository as documentation: a recursive BEGIN/MIDDLE/END protocol describing how the marketplace’s individual skills compose into a verifiable workflow, plus an accompanying interactive HTML map/simulator asset under docs/assets/.

Changes:

  • Introduces docs/red-gate-protocol.md, a detailed spec for the Red Gate coordination protocol (invariant, stages, recursion, handoff envelope, skill map, and corrections ledger).
  • Adds docs/assets/red-gate.html, a standalone interactive artifact that visualizes the protocol, skill map, refinements, fatal-flaw ledger, and missing-skill gaps.
File summaries
File Description
docs/red-gate-protocol.md Adds the Red Gate protocol spec (stages/invariants/recursion/handoff/skill map/corrections).
docs/assets/red-gate.html Adds an interactive HTML visualization/simulator for the Red Gate protocol and mapped skills.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/assets/red-gate.html
Comment thread docs/red-gate-protocol.md Outdated
claude added 9 commits August 26, 2026 02:54
…w feedback)

Copilot caught a real internal contradiction: the BEGIN preflight was
specified as 'command -v for each binary, existence for each path', which
would flag an unbuilt greenfield CLI as a dirty preflight — not red — so
the gate could never open. That is fatal #3 (crash-is-not-red deadlocks
greenfield work) silently reintroduced by its own fix.

Preflight is now scoped to the harness's own prerequisites only (bash,
timeout, tee, a writable evidence dir) and explicitly does not probe the
binaries or paths under test, since a missing subject binary is the normal
greenfield starting state and the very absence the criterion measures.
Propagated to the corrections table and the interactive map.

Also documents why the artifact source carries no doctype: it is a
publish-time fragment the artifact publisher wraps in its own skeleton, so
a doctype here would nest on every republish. The consequence for opening
it via file:// is recorded in the file.

Cheap tier green (exit 0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
A run is a sequence of rounds, each a complete BEGIN/MIDDLE/END, with the
human gate between them. This is how an undecided idea ('implement a
Hermes agent that does xyz') enters the protocol at all: you cannot write
behavioral criteria for an approach you have not chosen, so an early
round's verifiable output is a decision, not code.

The round-zero rule: start at the first round whose criteria you can write
without already knowing the answer. If you cannot write criteria for the
work, write criteria for the artifact that will tell you what the work is.

What makes early rounds honest rather than a loophole is the escalating
verifiability ladder. A research round's criteria check the artifact's
SHAPE — a file at a path, three options, costs per option, a
recommendation naming what would falsify it — all red before the file
exists, all machine-checkable, none of them UNVERIFIABLE. The machine
checks shape; the human checks substance at the round gate. Rounds
therefore relieve pressure on the UNVERIFIABLE budget instead of spending
it, which was the obvious failure mode of admitting research rounds.

Rounds also give a better answer to a contradiction the spec previously
left half-resolved. 'Immutable criteria + real learning' was answered only
vertically (spawn a child). Rounds answer it horizontally: each round's
contract is written fresh, seeded by the previous round's approved output,
so learning advances the run instead of editing a ratified file. Round 2 to
round 3 is the clearest case — an approved plan literally contains the next
round's criteria.

Rounds are not recursion, and conflating them is the easy mistake. Rounds
are horizontal, human-gated, and produce the next contract; recursion is
vertical, automatic, and produces sub-criteria within the current one. A
round can contain recursion; recursion never crosses a round boundary.

Three worked examples: the Hermes orientation-to-build walkthrough with
real check_cmds, a case where rounds would be ceremony and are skipped, and
a trace showing both axes in one run. Reconciles the invariant ('ratified
once' is now per round) and the human-loop section with the round gate.

Cheap tier green (exit 0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…rating loop

Correction from the author: check.sh was never meant literally — the idea
is a process model for executing tasks across the SDLC and AI-DLC, an
agentic operating loop that is self-learning and growing. Two changes
follow.

The verifier, generalized. The load-bearing property was never 'it is
bash' — it is four properties any verifier must have: runnable on demand,
proven able to fail at BEGIN, pinned against the worker, and independently
executed at END. A domain table maps what that means for code (tests),
research (shape checks + the round gate), planning, docs (docs-hygiene
audits), ops (probes), and judged output (LLM rubrics with a negative
control). The last row is the marketplace's own behavioral-tier
calibration discipline — the mutation control translated to judged work —
so Red Gate applies the verification scheme this repo already trusts,
per task. check.sh stays as the code-domain reference implementation.

The operating loop. An OS mapping (rounds are processes, wayfinder the
scheduler, semver/egress the syscall gates, dev-diary episodic memory,
fleet-playbook the semantic index, plugin-factory process genesis, the
eval tiers the immune system) and the six-step growth cycle: EMIT
(stop-reports, findings, unmet criteria) -> CONSOLIDATE -> DETECT ->
SCAFFOLD -> GATE -> LOAD. Growth is eval-gated, which is what separates
growing from accreting: a candidate skill that cannot beat its
calibration stub is the system memorizing noise, and the tier rejects it.

Named the missing organ honestly: recurrence detection across runs
(step 3) does not exist — nothing today reads a month of diary entries
and says 'this failure shape has appeared four times; here is the
invariant'. Added recurrence-detector to the gap list (now 11).

Artifact: thesis reframed, new OS/growth section, gap added.
Cheap tier green (exit 0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…on roadmap

Deep research on what AI leaders in the agentic space are actually using,
run as a 21-agent cost-tiered workflow: 5 Haiku scouts swept five source
clusters broadly (Anthropic/Claude Code ecosystem, OpenAI+Google,
mass-adoption frameworks, practitioner products, novel/self-improving
research); plain-code dedupe under a corpus rule — nothing dropped,
duplicates merged with sightings recorded, covered patterns kept and
annotated; 13 Opus deep-dives verified every not-yet-covered pattern
against primary sources (two scout claims failed verification and are
corrected in the dive notes, one unciteable paper flagged); a two-lens
brainstorm panel; one synthesis.

Corpus: 90 sightings -> 88 unique patterns (13 mass adoption, 60 growing,
14 niche, 1 research-only; 66 absent from Red Gate, 19 partial, 3 covered)
-> 94 verified deep-dive entries -> 16 proposals -> a ranked roadmap.

The verdict: Red Gate's invariants live in prose the model is asked to
honor, while the field has moved the same invariants into code — hook
handlers, declared tool classes, pinned constraint blocks, typed
provenance. Published failures land on exactly Red Gate's soft spots:
compaction silently drops ratified constraints, and a self-editing agent
deleted its own detection markers and faked a test log. The missing organ
is enforcement, not more architecture. The protocol should compile.

Adopt-now (ranked): criteria-pin, reviewer-lockout, out-of-bounds-ledger,
red-gate-hooks, judge-calibration, consolidate-delta. Ten high-adoption
patterns rejected with reasons (Mixture-of-Agents collides with
single-writer; durable-execution runtimes are the right diagnosis with the
wrong dependency; AutoGen dynamic speaker selection carries ~37% of MAST's
multi-agent failures; Darwin Godel Machine: adopt the invariants it proves
by violating them, never the mechanism).

Ships docs/research/agentic-patterns-corpus.md (full corpus tables, all
dive verifications, both brainstorm lenses unfiltered) and the
machine-readable corpus JSON; linked from the protocol doc.

Cheap tier green (exit 0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…rified slices

The plan-round artifact, holding itself to the protocol's own shape
criteria: every slice names concrete file paths and a proposed verifier,
and the first build slice is a tracer bullet crossing every layer
(command -> driver skill -> criteria-contract skill -> script -> artifact
on disk, gate provably red).

Design decision: two new plugins, not eleven. plugins/redgate/ carries
three skills (driver, criteria-contract, reconcile — voice is the
multi-skill precedent), the hooks compile-layer, and the protocol
internals as references; plugins/recurrence-detector/ stands alone as the
growth loop's missing organ. consolidate-delta and judge-calibration land
as additive amendments to dev-diary, fleet-playbook-curator, and
plugin-factory. The corpus roadmap's adopt-nows fold in: criteria-pin
into criteria-contract, reviewer-lockout and out-of-bounds-ledger into
hooks + reconcile, red-gate-hooks IS the hooks layer.

CI consequence made explicit: scripts land under
plugins/*/skills/**/scripts/**, which fires the unattended deep tier —
so prose slices ship first and the scripts slice is one PR, budgeted.

Deliberately out: spend-ledger as infrastructure (no portable token
meter; ships as manifest bookkeeping with the caveat), separate
fanout-budget/escalate/lease skills (reference sections until a run
earns them), a redgate pier pack (nothing destructive), and any
auto-scaffolding from recurrence-detector (DETECT proposes; the human
and factory dispose).

Cheap tier green (exit 0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…via APM

The plan's tracer bullet, crossing every layer: /redgate command -> driver
skill -> criteria-contract skill -> scaffold-run.sh -> a run on disk whose
gate is provably red.

plugins/redgate/ ships two skills. redgate (the driver): round-zero rule,
the four round types, driving a round through BEGIN/MIDDLE/END, round
budget and rounds-vs-recursion boundary, Not-this against wayfinder /
orchestrate / tracer-bullets. criteria-contract (BEGIN): interview,
scaffold, 3-7 criteria with red-because and positive controls, the red
gate (exit 99 = harness failure and never red; preflight probes only the
harness's own prerequisites, never the subject under test; a check_cmd
exiting non-zero — 127 included — is a legitimate FAIL), ratification UX,
and pinning the sha256 of BOTH CRITERIA.md and check.sh.

scaffold-run.sh generates .redgate/<slug>/ (manifest with phase/budgets/
pin slots, honestly-red template criteria, the check.sh harness with
per-criterion timeout, stdin closed, evidence teed to evidence/<n>.out)
and --pin records both hashes and flips phase to MIDDLE; re-pin refuses.

The cheap eval pack EXECUTES the invariant rather than grepping for it:
scaffold into a tmpdir, assert check.sh exits 1 (red from birth), harness
failure is 99, a 127 check_cmd reports FAIL, pin writes two sha256s and
flips phase, re-pin is refused.

Cross-harness per the new requirement: everything load-bearing is prose +
plain bash. Codex reads the plugin AGENTS.md natively; Copilot consumes it
via apm compile -t copilot; Claude Code installs it as a native plugin.
The README documents the APM install/compile path (the marketplace_plugin
resolver reads marketplace.json directly — no extra manifest). Subagents
and hooks are named only as conveniences with portability caveats; END
independence ports as a fresh session or the human at the gate.

This PR touches plugins/*/skills/**/scripts/** for the first time, so the
deep-tier path gate fires — expected and budgeted per the implementation
plan (one scripts PR, not several).

Cheap tier green: 890 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
Slice 1's actual run shows the pier jobs are per-plugin path-scoped:
graveyard's deep-run filters on graveyard's own safety paths and skipped
every pier step on the redgate-scripts PR — zero pier minutes spent, not
the one budgeted run the plan predicted. The one-scripts-PR rule stays as
hygiene, not cost necessity.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…the human gating every round

The round gate is no longer an unconditional human stop. Every gate
decision is classified with semver-gate's four-property test and its
tie-break imported verbatim (any property MAJOR makes the whole gate
MAJOR), then acted on by class:

- PATCH auto-passes, logged to the gate ledger, and seeds the next round —
  qualifying only when ALL hold: build/consolidation round, verifier green
  via independent END, zero UNVERIFIABLE, diff inside the fence, criteria
  strictly derived from a human-approved plan slice, no escalator.
- MINOR auto-passes with a prominent flag and a standing veto, staged
  separately revertible — never a blocking question.
- MAJOR stops for a structured human question naming the specific decision
  and mechanism; a prior adjacent yes does not transfer.

The governing idea: autonomy flows downhill from an approved plan. A
human-ratified plan is the autonomy envelope; the always-MAJOR escalators
are exactly the envelope's edges — the orientation decision, the plan
approval itself, a run's first ratification, every UNVERIFIABLE
countersignature, fence widening, budget/depth extension, final
acceptance, and anything semver-gate's own table calls MAJOR.

Derived ratification closes the self-ratification hole: a build round
whose criteria are byte-derivable from an approved plan slice
auto-ratifies as PATCH with the derivation logged; any deviation is a
contract change and escalates. The human approved those exact criteria
once, at plan approval, at a higher altitude.

Mechanics: the manifest gains autonomy=classified and an
approved_plan_sha256 slot; scaffold-run.sh creates gates.log (round,
class, driving property, outcome — an auto-pass that cannot cite its
qualifying conditions is a protocol violation, not a judgment call).
Updated: protocol doc (Graduated autonomy section + consistency touches to
rounds/recursion/worked examples), driver SKILL.md, AGENTS.md (so Codex
and Copilot get the classified-gate rules), command, both manifests, both
READMEs. New cheap checks defend the escalator list, the never-auto-pass
clause for MAJOR, derived ratification, the self-ratification guard, and
the dogfooded manifest fields + ledger.

Cheap tier green: 902 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
Rounds section and axes cards now describe the classified gate (PATCH
auto / MINOR flagged / MAJOR human, escalators always stop), the trace
shows a PATCH auto-pass logged to gates.log, and the human-voice role
string updates to the MAJOR-gate wording.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
@JRichlen JRichlen changed the title Add Red Gate: a recursive BEGIN/MIDDLE/END protocol composing the 24 skills Red Gate: protocol, research corpus, implementation plan, and working slice 1 with graduated autonomy Aug 26, 2026
claude added 3 commits August 26, 2026 05:33
…n itself

Executed as real Red Gate rounds, with the run records committed as
provenance under .redgate/.

Round 1 (slice2-reconcile): six criteria written and proven RED before any
code existed (evidence shows 'No such file or directory'), PATCH
auto-ratified as derived from the approved plan slice 2, both artifacts
pinned. reconcile.sh then flipped all six: refuses an unpinned run (never
ratified, nothing to grade), re-hashes both pinned artifacts and fails on
drift with a verdict distinguishable from an ordinary unmet criterion,
runs the pinned verifier itself, treats exit 99 as harness failure rather
than red, and accepts a PASS only with evidence written during that run.

Then the mutation control caught a real defect in the round's own
criteria. Reverting the drift gate left #3 and #4 green: their fixture
used a run whose criteria failed anyway, so 'reconcile exits non-zero' was
satisfied by the ordinary FAIL path, and the drift string matched a
warning that fires whether or not the gate acts. Per the protocol those
criteria are UNVERIFIABLE, not proven — and because the contract is
pinned, it was NOT edited.

Round 2 (slice2-reconcile-r2) opened with a fresh, coupled contract and
its red gate REFUSED TO OPEN: all four criteria were already green,
because round 1's code was correct and only its criteria were weak. That
is the protocol working — criteria already true are not a build contract.
Finding recorded: regression tests for already-correct behavior belong in
the eval tier, where green-is-expected is the right semantics.

The coupled checks therefore moved to the eval pack, where a second
instance of the same bug class surfaced: grepping the drift MESSAGE passes
even with the gate reverted. Fixed by asserting the EXIT CODE on a fixture
whose criteria otherwise pass, so a non-zero exit can only come from the
gate under test. Mutation control now proven: reverting the drift gate
turns exactly 2 checks red; restoring returns them green.

Ships reconcile/SKILL.md (four ordered gates, the mutation control, the
assert-behavior-not-messages rule with its MEASURED provenance note),
reconcile.sh, and 7 executed eval checks.

Cheap tier green: 911 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…op's DETECT organ

Each built as a real Red Gate round with its contract proven red first and
pinned; run records committed under .redgate/ as provenance.

Slice 3 (hooks) — the protocol compiles. hooks.json declares PreToolUse and
SessionStart; guard-redgate-paths.sh reads the payload and DENIES any write
to a ratified run's CRITERIA.md / check.sh / manifest while that run's phase
is MIDDLE, allows the same write during BEGIN (the contract is still being
written), and is indifferent to paths outside .redgate/. This is
reviewer-lockout and the out-of-bounds ledger enforced rather than asked —
the corpus verdict that invariants belong in code. Mutation control proven
both directions: removing the deny re-fails the deny criterion while the
allow criteria stay green; removing phase-awareness re-fails the allow
criterion. Portability caveat carried in the hooks prose: hooks are
Claude-Code-only, the rule holds as prose discipline elsewhere.

Slice 4 (references) — round-types.md (criteria templates per round type and
the shape-vs-behavior ladder), handoff-envelope.md (typed DOWN/UP fields, and
why criteria text is excluded from the token cap), recursion-contract.md
(four-part spawn precondition, sibling budget pool, depth_remaining, harvest,
leases). SKILL.md links all three, so progressive disclosure is wired rather
than claimed.

Slice 5 (growth loop) — recurrence-detector ships as its own plugin: cluster
run exhaust by failure MECHANISM (not symptom), surface a shape seen >= N=3
times as a named candidate invariant with every sighting cited, and never
auto-scaffold — DETECT proposes, the human and plugin-factory dispose. Its
threshold has a stated rationale (one is an incident, two a coincidence,
three a shape; a skill built from one bad day is the system memorizing
noise). Three amendments land additively: typed ADD/UPDATE/REMOVE deltas
with reused failure-shape tags for dev-diary and fleet-playbook-curator (a
new tag for the same mechanism defeats the count), and judge-calibration for
plugin-factory codifying the negative-control contract, citing this repo's
own six-for-six measured rejection bar.

Also fixed en route: the scaffolded command shipped an unquoted colon in its
YAML description, which the cheap tier caught as unparseable frontmatter.

Cheap tier green: 943 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
Four fresh verifiers — given only the artifacts, never this build's
transcript — executed the safety machinery and mutation-tested it. Verdict
PASS_WITH_FINDINGS: nothing survived its mutation (no gate proved
uncoupled), but two real defects stood, both of the 'shipped but does not
take effect' class.

1. Stale prose. redgate/SKILL.md still said the hooks layer 'is planned as
   an optional hardening slice' and that reconcile was the 'next slice',
   while both ship and were verified working — directly contradicting
   AGENTS.md's 'all five slices shipped'.

2. Orphaned references. The three growth-loop amendment files existed on
   disk but were linked from ZERO host skills. Progressive disclosure is
   the only way a skill loads a reference, so an unlinked reference is
   inert: shipping it is not the same as it taking effect. Only
   recurrence-detector pointed at them; their own hosts did not. Each is
   now linked from dev-diary, fleet-playbook-curator, and plugin-factory
   respectively.

Guard added so the class cannot recur: a repo-level cheap-tier check walks
every plugins/**/references/*.md and fails when it is not linked from its
own SKILL.md. Mutation-proven — removing one link turns it red naming the
inert file, restoring returns it green. It currently covers 32 reference
docs across the marketplace, several of which predate this work.

Cheap tier green: 944 passed, 0 failed.

Honest limits the verifiers recorded and I am not papering over: the drift
gate was mutated at one site only, so its coupling is proven for one
mutation shape; the unpinned-refusal and evidence-freshness branches were
verified behaviorally but never mutation-tested; session-start.sh was never
executed; hook payloads were hand-piped rather than driven by a live
harness; and no behavioral or deep tier ran, so every cross-harness and
model-in-the-loop claim remains unexecuted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
@JRichlen JRichlen changed the title Red Gate: protocol, research corpus, implementation plan, and working slice 1 with graduated autonomy Red Gate: protocol, 88-pattern corpus, and all five slices built by running the protocol on itself Aug 26, 2026
claude added 12 commits August 28, 2026 03:54
…re BEGIN)

docs/red-gate-glossary.md pins every load-bearing term and rules on the
collisions the growth created: Calibration vs negative control, stage vs
the manifest phase field, verifier harness vs agent harness, and the run
lifecycle verbs (open/pin/dispatch/reconcile/gate/advance/close) that
nothing had named. It also records the known phase-never-advances defect
so nobody infers in-progress from phase=MIDDLE.

references/calibration.md adds BEGIN step 0: five sizing dials — tier,
domain, scope, taste, orchestration — inferred first, asked only when
load-bearing, inside the existing shared 5-question budget. The block is
written into the CRITERIA.md header so the existing pin covers it with no
script change. T0 tasks are declined by the protocol itself (the
anti-ceremony rule); widening any dial mid-run is MAJOR, narrowing is a
gates.log note. Wired into the driver SKILL.md (step 0 + references
link, so the orphan guard sees it), the /redgate command, the
criteria-contract interview, and the plugin AGENTS.md.

Cheap tier: 944 passed, 0 failed (portability lint required and got a
subagent caveat in the new reference). Behavioral tier not run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
Calibration's questioning posture was already grill-me's (via the
criteria-contract interview) but only implicitly. State it, note that
grill-me's per-branch stakes tier (reversibility x blast radius) is the
same computation as calibration's scope/tier escalators, and pin the
dependency direction: calibration adopts grill-me's posture; grill-me
stays generic and never references the dials.

Cheap tier: 944 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…r the interview

Before this, grill-me could fire a deep question series on a branch the
user never wanted explored, without ever confirming the goal. Two new
mechanics, specified in references/path-consent.md and hooked compactly
into SKILL.md (still exactly at its 140-line budget — Not-this, triage
and format prose tightened to pay for the new section):

- Anchor (round 0): goal, observable outcome, out-of-scope — inferred
  from the plan text and confirmed in one exchange, never a series. No
  branch questioning before it; a branch that doesn't trace to the
  anchor is offered as a drop, never silently explored.
- Path consent: every STANDARD/DEEP branch gets a header (tier, rough
  question cost, one-line recommendation for the whole path) and the
  user routes explore / accept / defer / out-of-scope. Only explore
  spends questions; headers batch into one routing round ordered by
  leverage; LIGHT branches are exempt (a header would double their
  cost); deferring a one-way door is recorded as an accepted open risk,
  stated at defer time.

Routing extends the frontier rule from data dependencies to abstraction
dependencies: granular questions wait while a structural ancestor is
open.

Eval pack gains five checks (anchor precedes questioning, four-route
menu present, reference linked not just present, LIGHT exemption,
irreversibility exception), mutation-proven: gutting the menu or the
anchor turns the tier red; restored it is green at 950/0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
Adds a proposed (not yet adopted) vocabulary revision to the glossary,
driven by three defects the v1 terms carry: positional stage names
(BEGIN/MIDDLE/END say when, not what to do), negative names
(UNVERIFIABLE points away from the required behavior), and the
envelope collision (autonomy envelope vs handoff envelope).

Stages become imperative verbs that carry their own rules — ARM (prove
the gate can fire, ratify, pin), TRACE (one writer, one tracer slice),
JUDGE (independent verdict; nobody judges their own case). Round types
follow suit (SCOUT/PLAN/BUILD/WIDEN); UNVERIFIABLE becomes WITNESS,
autonomy envelope becomes MANDATE, exit-99 harness failure becomes
FAULT. Token leanness comes from semantic compression: 'the gate is
armed' replaces four clauses of restated rules.

Migration is staged and gated: prose aliasing is free, the docs sweep
is cheap-tier gated, and the mechanical rename (manifest phase values,
verdict strings, eval greps) is MAJOR and rides with the PR #75 fix
batch or not at all. Committed run records are provenance and are
never rewritten.

Cheap tier: 950 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
Background-agent research against primary sources (PDSA/Deming, OODA,
Polya, Kolb, Scrum Guide, Beck's Canon TDD, ReAct, Reflexion,
Self-Refine, CRITIC, LATS, ToT, Anthropic's building-effective-agents)
on whether the round should gain per-round Reflect/Plan/Investigate
phases. Verdict: keep 3 stages; reflection lives between iterations in
every mature loop that produces verified work; investigation is an
in-stage action or an iteration type, never a mandatory phase;
unenforced in-cycle phases evaporate (Beck/Fowler), and token-matched
self-inspection loses to sampling (2607.28576, 2310.01798).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…act, retro cadence

Settles the add-more-phases question per the prior-art research
(docs/research/phase-structure-prior-art.md): three stages stay because
they encode falsifiability; Plan/Investigate remain round types and
in-stage actions; Reflect gets teeth as gate obligations, never a stage.

- gates.log gains a mandatory one-line lesson field (header extended in
  scaffold-run.sh; 'None' legal only at PATCH gates).
- A red verdict leaves a durable artifact: its lesson names what the
  next contract must encode, and the next round's BEGIN reads prior
  gates.log files first — the Reflexion mechanism.
- Consolidation cadence: after 3 consecutive build gates the driver
  proposes a consolidation/retro round by default; declining is logged.
- New retro round type: END artifact is the completed lessons ledger,
  shape-checked, substance judged at the gate (template in
  round-types.md); added to the round-type tables and glossary.
- Five new cheap checks defend the lesson field, red-artifact rule,
  cadence, scaffold header, and retro template; cadence check
  mutation-proven. Tier: 955 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
14-agent workflow: coverage inventory -> 8 dimension scouts (absence
verified in-repo, external prior art cited) -> 3 skeptics refuting
against repo/corpus/tracked findings -> completeness critic -> ranked
synthesis. 39 candidates, 34 survived, 3 meta-gaps (the dimensions the
analysis itself missed: security-and-trust-boundaries,
portfolio-composition-at-scale, lifecycle-and-compatibility-governance).

Top of the ranking: untrusted-provenance discipline for inter-agent
messages, adversarial-input robustness for graveyard, a mechanical
secret-scan gate on agent-written exhaust, repeat-run statistical
baselines for the behavioral tier, and a roster-level trigger-routing
eval. The themes section names the blind-spot pattern: strong defenses
against the agent's dishonesty, almost none against the world's; and a
marketplace that preaches measurement while closing zero loops on
itself. Three gaps are recorded as deliberately not worth doing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
The full adoption the glossary staged. Prose swept across the redgate
plugin, protocol doc, and glossary; the glossary's v2 section is now
marked ADOPTED and v1 terms remain only inside committed .redgate/ run
records, which are provenance and are never rewritten.

Scripts write v2 and read both vocabularies: scaffold-run.sh creates
runs at phase=ARM and pins to phase=TRACE (legacy phase=BEGIN dirs pin
correctly too); the emitted check.sh accepts WITNESS: and legacy
UNVERIFIABLE: lines and emits WITNESS verdicts; reconcile.sh accepts
both verdict spellings; the hook guard and session-start handle
TRACE|MIDDLE. Renames: UNVERIFIABLE->WITNESS, autonomy envelope->
mandate (envelope collision resolved), harness failure->FAULT,
orientation->scout, consolidation->widen. Eval greps updated to pin
the v2 strings.

Verified end to end: fresh run scaffolds at ARM, pins to TRACE, a
WITNESS criterion flows through check.sh and reconcile, verdict PASS
with evidence; legacy MIDDLE run dirs still denied by the hook guard.
Cheap tier: 955 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
The Workflow tool stages per-agent git worktrees under .claude/worktrees/
while a run is live; they are ephemeral harness state, never repo content.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…veyard fuzz, provenance fences

Four fixes from the gap analysis (docs/research/gap-analysis.md),
implemented by isolated worktree agents and merged onto the current tree
by a single writer (both run.sh-touching agents had stale bases missing
section 7c; their new sections were extracted and appended instead of
overwriting):

- run.sh sections 13-15: cross-plugin reference resolution (roster from
  marketplace.json + skills dirs, fail-closed on unknown hyphenated
  backtick tokens, curated NONSKILL set), context-tax budget (per-plugin
  chars/est-token table; >1024-char description or >9000-token estimated
  total fails; measured ~7233 today), and version drift (plugin.json
  must carry a version, fail-closed; must match marketplace.json when
  both exist). The reference check caught its first real catch during
  application: reference-doc names needed the NONSKILL set.
- Section 16 + evals/cheap/secret-gate.sh: dependency-free secret
  scanner (AWS/GitHub/Slack/Anthropic keys, private-key headers, generic
  api-key literals) over agent-written exhaust, with a planted-fake-key
  negative control that must exit 1 and a clean control that must exit
  0; wired as 2-line notes into dev-diary and context-handoff.
- Graveyard adversarial-input fuzz group: 8 hostile repo names
  (shell metachars, command substitution, leading dash, spaces) through
  the delete-script generator, asserting reject-or-safe (bash -n, one
  bundle guard per repo, payload never escapes quoting). Eval-only; no
  graveyard script changed.
- Untrusted-provenance fences: worker output travels inside
  untrusted-data fences in the redgate UP envelope and both orchestrate
  verify templates — data, never instructions; instruction-shaped
  content is reported as an injection finding; grep-defended in both
  plugins' eval packs.

Cheap tier: 1144 passed, 0 failed. Mutation proofs re-run against this
commit follow in the verification pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…adversarial verify)

The adversarial verification pass on the gap fixes confirmed a real,
pre-existing command injection in the safety-critical delete-script
generator: a bundled repo name containing a double quote escapes the
emitted BUNDLED="..." assignment and injects a command that runs when
the USER executes the delete script — outside the bundle-existence guard
that is the whole point of the tool. Reproduced end to end: a name
'a";touch PWNED;x="b' created the PWNED file when the generated script
ran with gh stubbed.

The graveyard cheap-tier fuzz group had already flagged this as an
ok-with-WARNING KNOWN-VULNERABILITY (the eval was instructed to expose,
never to silently patch a safety script); the independent verify agent
confirmed it exploitable. Now fixed at the source: GitHub repo names are
[A-Za-z0-9._-] only, so the generator validates every bundled/unbundled
token against that charset and dies on anything else — closing injection
by rejection rather than by escaping. The documented space-separated
list interface still works (validated per token); a legitimate
'repo1 repo2' still emits a correct guarded script.

The fuzz group now asserts defense-by-rejection: 8 hostile names (quote
breakout, command separators, substitution, pipe, backtick, backslash,
Cyrillic homoglyph) must each exit nonzero, plus a positive control that
valid names still emit a parseable guarded script. Mutation-proven:
neutering the validation turns the tier red. Cheap tier: 1145 passed, 0
failed. This is a safety-path change, so CI's deep (pier) tier runs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
The verify pass ran against a stale worktree base so its top-level
verdicts were void, but two of its concrete attack ideas reproduced
against the real tree and are fixed here:

- secret-gate.sh missed Google (AIza), Stripe (sk_live_), and OpenAI
  (sk-/sk-proj-) keys — a file carrying only one of those passed clean.
  Added the three patterns (distinctive prefixes, near-zero prose false
  positives; ordinary prose still scans clean). Verified each now exits
  1 in isolation; removing a pattern makes that key slip past again.
- The untrusted-data provenance fence could be broken out of: worker
  content containing a literal triple-backtick closed the fenced block
  early, letting the remainder read as verifier instructions — the exact
  injection the fence exists to stop. Both claim-consuming orchestrate
  templates now defang every backtick in the payload to U+02CB before
  embedding (the tag stays a real fence; only the payload's backticks
  are neutralized). Verified a hostile triple-backtick payload no longer
  closes the fence; a new coupled eval check in the orchestrate pack
  goes red if either template drops the defang.

Cheap tier: 1147 passed, 0 failed; both new guards mutation-proven.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
claude added 11 commits August 28, 2026 18:24
Records the five gaps shipped this session, the command-injection the
adversarial verify caught in the graveyard delete-script generator, the
two attack ideas that reproduced and were hardened, and the honest
not-yet list (statistical baselines and routing evals need a live model;
approval-fatigue ledger and criteria index are the next cheap-tier round).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
Every per-plugin promptfoo pack tests its skill in solitary confinement,
but users install ~23 at once and the only surface deciding WHICH fires
is the roster of frontmatter descriptions. Mis-routing — wrong skill, or
one firing when none should — is invisible to per-plugin packs and taxes
every session. This pack closes that gap and runs in CI against a live
model.

evals/routing/:
- gen-roster.sh assembles one line per marketplace plugin (name + first
  sentence), sorted and deterministic; --check fails if roster.txt drifts
  from the marketplace.
- promptfooconfig.yaml: 8 must-fire scenarios (each squarely in one
  skill's purpose, chosen where a naive router could pick a neighbour)
  plus 2 must-NOT-fire calibration negatives (routine requests where
  activating anything is the failure — the floor that makes a passing
  score mean discrimination, not eagerness). Routing has a labeled right
  answer, so verdicts are checked by regex on the model's final ROUTE:
  line — deterministic, no LLM grader, subject-model spend only.

Cheap tier §17 guards the structure offline (roster in sync, >=6
positives, >=2 negatives, every positive targets an installed plugin) so
a broken pack can't ship green; the model-in-the-loop routing itself runs
in the new advisory routing-eval CI job (OpenRouter subject key, node 22,
pinned promptfoo@0.122.0, path-filtered to routing + skill-description
changes, skipped legs announce themselves). Non-required like the paid
multi-plugin gate, since it has never actually run yet.

Cheap tier: 1150 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…eady-to-build design

Records the routing eval as shipped and reframes #4: no longer
offline-blocked (CI has the keys) but gated on a first run to seed the
baseline and on an owner cost decision (repeat:N multiplies the required
tier's spend). Includes the concrete pass-rate.sh design to build once
that cost is okayed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…ass floor

n=1 behavioral greens are uninterpretable — a router that passes a
scenario ~55% of the time shows green or red on a coin flip, and any
optimization loop built on that selects noise. This ships the fix as a
tracer on the routing pack (cheap: no grader, not yet required), with the
rollout to the required packs left as an explicit owner cost decision.

- evals/routing/promptfooconfig.yaml: repeat: 5 — each scenario runs five
  times.
- evals/paid/pass-rate.sh: reads the repeated results.json, computes each
  scenario's k-of-N pass rate, fails any scenario below a floor (default
  0.8) and fail-closes if a scenario ran fewer than --min-runs times (a
  run that did not actually repeat is not a statistical result). Handles
  both promptfoo result shapes (.results.results and a bare .results
  list) — the second shape crashed the first draft and was caught by the
  offline unit tests below, not in CI.
- routing CI job runs pass-rate.sh after the eval (floor 0.8, min-runs 3).
- Cheap tier §18 guards it offline and mutation-proven: the pack still
  declares repeat, CI still invokes the gate, and pass-rate.sh genuinely
  passes an at-floor run, fails a 0.4 run, and fail-closes an n=1 run —
  checked against synthetic fixtures so the statistical gate itself is
  verified without a model call. Disabling the floor or dropping repeat
  turns the tier red.

Cheap tier: 1156 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
The repeat+k-of-N floor mechanism ships and is mutation-proven; the
remaining piece is the fleet-wide roll-out to the required packs, which
stays an explicit owner cost decision (repeat:N multiplies required-tier
spend). Two lines per pack extend it when okayed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
… layer)

A new verification surface: real prompt/response pairs showing what each
skill changes — run WITH the skill and WITHOUT it (a generic stub) —
published as a static GitHub Pages site next to the plugin docs. Sourced
from the behavioral eval tier (the user's choice), so every pair is a
real, graded model run and nothing is hand-written marketing.

Pipeline (tracer: scope-fence end to end):
- evals/paid/capture-example.sh turns a promptfoo results.json into a
  committed snapshot docs/examples/data/<plugin>.json — the real-skill
  pass row paired with its negative-control (stub) row, both outputs,
  both grades, and provenance (model, grader, commit, capture time from
  CI args, never Date.now). Fabricates nothing; a run with no usable pair
  skips and the prior snapshot stands. Unit-tested offline.
- docs/build-examples.sh renders all snapshots + each plugin's SKILL.md
  description into a self-contained, theme-aware docs/examples/index.html
  (no external assets, deterministic — same data in, same HTML out). It
  shows the model's real response verbatim and badges each side graded
  pass / fail / ungraded-seed. --check fails if the committed HTML drifts.
- .github/workflows/pages.yml deploys docs/ to Pages on push to main
  (regenerating + --check first). One manual step: Settings → Pages →
  Source = GitHub Actions.
- The behavioral CI job now captures each plugin's snapshot from its
  graded results and uploads it as an artifact for a maintainer to commit.

Seed: the scope-fence card is a REAL pair captured now via Claude
subagents running the pack's own pressure-1 scenario with the skill and
with the stub. Honest result recorded in the card's "What to notice":
on a strong model both sides fence scope, so the divergence is subtle
(explicit fence + "Found out of scope" section vs hedged advice at
greater length) — which is why the pack uses a cheaper subject model.
The seed is labelled ungraded (I did not run the grader); CI captures
replace it with graded promptfoo runs and add more plugins.

Cheap tier §19 guards it: index.html in sync with the data, and every
snapshot carries two real outputs plus provenance (no marketing without
evidence). Mutation-proven — editing a snapshot without regenerating
turns the tier red. Cheap tier: 1160 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…rue)

The GitHub MCP exposes no Pages-settings API, and the deploy needs the
source set to 'GitHub Actions'. Rather than leave that as a manual
Settings click, configure-pages runs with enablement:true so the workflow
sets the Pages build source itself via the pages:write token on its first
run on main (or a manual workflow_dispatch). Only if org/repo policy
forbids token-based enablement does it fall back to one Settings click.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
Five phases with verifiers: tracer (done), close the capture->commit loop
(the gap blocking auto-population), widen to the 10 packed plugins as
graded captures, decide seed-vs-pack for the 13 unpacked ones, then
polish (staleness guard, two-way doc linking, multi-scenario). Records
current coverage (1 of 23) and the open decisions: refresh cadence,
review-vs-auto-merge, and per-plugin scenario selection.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…low + 3 more seeds

Phase 2 (close the capture->commit loop): refresh-examples.yml runs the
promptfoo packs biweekly (1st & 15th, 06:00 UTC) plus on dispatch,
captures each plugin's real pair, regenerates the gallery, runs the cheap
tier, and opens a REVIEW-GATED PR (peter-evans/create-pull-request on
branch examples/refresh) — never a direct push. Merging publishes to
Pages. Cadence and review-gating are the owner's settled choices.

Phase 4 (seed unpacked plugins, priority order): three more real cards
captured now via subagents running each skill's scenario with the skill
and with a stub — prove-the-undo (rehearses the restore vs asserts a
backup), egress-gate (produces an egress manifest + secret scan vs
neither), diagnosing-bugs (ranked falsifiable hypotheses + tagged
instrumentation + seam-gated red/green test vs prose advice). Each card's
"What to notice" states the honest divergence, including that on a strong
model both sides are already careful — the skill sharpens structure and
auditability. All labelled ungraded seeds; CI captures replace them with
graded promptfoo runs.

Gallery now 4 of 23. Cheap tier: 1163 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
These were documented as blocking in PR #75's body and parked, not fixed.
Verified all four still live, fixed each, and mutation-proved the guards.

1. A final criterion with NO trailing newline was silently DROPPED by the
   emitted check.sh read loop, so a failing criterion written last vanished
   and the gate exited 0 — a green gate over unmet criteria, defeating the
   invariant the protocol exists to hold. Fixed with `|| [ -n "$line" ]`;
   new coupled check feeds an unterminated failing criterion and asserts the
   exit code.
2. The evidence-freshness eval was uncoupled while labelled "(exit-coupled)":
   it reused the TEMPLATE fixture whose criteria fail anyway, so no-opping
   the gate left the tier green. Now runs on the _mkpass fixture, where the
   gate is the only possible source of a non-zero exit.
3. The hook guard — slice 3, the layer that compiles the protocol into
   enforcement — had zero eval coverage; replacing every `exit 2` with
   `exit 0` left the tier green. Four new checks drive the real handler with
   real payloads and assert exit codes (ARM allow, TRACE deny x2, outside
   allow).
5. Portability, which made the cross-harness claim false on macOS:
   `stat -c %Y` is GNU-only (every genuine PASS read as stale, so no round
   could close) — now falls back to `stat -f %m`; bare `sed -i` aborts
   mid-pin on BSD leaving a half-pinned manifest — now one portable
   temp-file rewrite; the emitted preflight hard-required `timeout` and
   `sha256sum`/`tee` it never uses — now requires only what it uses and
   tolerates a missing timeout (gtimeout, else uncapped).

Mutation-proven: reverting any of the four turns the tier red. HONEST
LIMIT recorded in the pack — CI is Linux, so the BSD branches are shape-
checked (the fallback is present), not executed.

Cheap tier: 1171 passed, 0 failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
@JRichlen JRichlen changed the title Red Gate: protocol, 88-pattern corpus, and all five slices built by running the protocol on itself Red Gate protocol, lexicon v2, gap analysis + fixes, and the published example gallery Aug 29, 2026
claude added 6 commits August 29, 2026 02:38
…cked plugins

Completes Phase 4. A 40-agent pass produced each pair: per plugin, a
designer agent read the SKILL.md and built a scenario where the naturally
helpful answer DIVERGES from what the skill requires; two agents answered
it (skill injected vs generic stub); an independent reader — which wrote
neither response — judged the honest divergence and wrote the card's
"What to notice".

The judged spread is published verbatim on every card: 1 stark
(grill-me), 9 moderate, 2 subtle (docs-hygiene, codebase-design). The
subtle verdicts are kept, not hidden or re-rolled — a gallery that only
showed flattering examples would be marketing, and this is meant to be
verification. Those two are now the best candidates for a real promptfoo
pack, where a cheaper subject model shows the gap a strong-model seed
cannot, and the honest place to ask whether the skill earns its context.

Gallery: 14 of 23 plugins. The 10 with promptfoo packs get graded
captures from the biweekly refresh loop instead of seeds.

Cheap tier: 1247 passed, 0 failed — every snapshot passes the sync +
provenance guard.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
main added agent-compiler while this branch added redgate and
recurrence-detector — additive conflicts in marketplace.json, README.md,
and .gitignore, all resolved by keeping both sides. The redgate README
row was also updated to lexicon v2 (ARM/TRACE/JUDGE, mandate, scout)
while resolving.

Two checks introduced by this branch fired on the newly-merged plugin,
both correctly:
- cross-plugin reference resolution flagged `engineering-default` in
  agent-compiler's AGENTS.md — a golden-example/registry-view name, not a
  skill, so it joins the curated non-skill set.
- the routing roster went stale the moment a 24th plugin appeared; that
  is precisely what --check exists for. Regenerated.

Cheap tier: 1281 passed, 0 failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…er prompt flaw

The counterfeit tier caught a genuine design bug in the checks this branch
added. That tier runs the cheap tier inside a SYNTHETIC minimal marketplace
root, and four new repo-level checks assumed the real layout, so they failed
there — the curated cross-reference allowlist, the routing structure check,
the statistical gate, and the example gallery all hard-failed on files a
minimal root legitimately does not have. Each now distinguishes ABSENT
(skip: this root doesn't have the surface) from PRESENT-BUT-BROKEN (fail),
which is what a repo-level check owes a marketplace that may be a subset.
The curated-pair check keeps its teeth: a missing file is still staleness
when the plugin IS installed here. Counterfeit tier: 22 passed, 0 failed.

The routing eval's first live run also earned its keep, by failing. Across
all five repeats the model routed "draft and post a GitHub comment" to none
rather than egress-gate, with consistent reasoning: "egress-gate is a
gate/check that runs before such actions, not a skill that actually drafts
and posts comments." That is a defensible reading of a badly-worded prompt,
and it is exactly the mis-routing the gap analysis predicted would tax the
whole discipline layer invisibly. The prompt now states what a skill IS:
a discipline that governs how a request is carried out, activating when the
request triggers its rule even though the skill does not perform the task.

Cheap tier: 1281 passed, 0 failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…ducible at n=1

Two CI runs of the same commit failed different plugins (run 1
tailscale-wif, run 2 voice), with neither plugin touched by the diff.
Run 1's failure was a subject-model degeneracy that truncated the answer;
run 2's was a different leg entirely. That is the coin-flip the k-of-N
floor exists to expose, now measured instead of argued.

Normally invisible because the path filter runs only touched plugins'
legs; adding files under the shared evals/paid/ ran all ten at once. The
required behavioral check is therefore red-by-default on any whole-tier
run. The fix (repeat + pass-rate.sh) is built and shipped on the routing
pack; rolling it out to the rubric packs multiplies the required tier's
spend and stays an owner cost decision. This table is the evidence for
making that call.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
…n luck

The required behavioral tier went red on PR #75 with the model actually
passing every scenario it was allowed to answer (graveyard: 5/5), because a
single upstream 504 ("operation was aborted") on one scenario made promptfoo
exit 100. That is exactly the n=1 fragility gap #4 names: a required check
turning red on the weather, with no way to tell a transport error from a real
rubric failure.

Fix, in three coupled parts:

- pass-rate.sh is now FAULT-aware. Each row is classified PASS / FAIL /
  INVALID(FAULT); a transport error (.error / failureReason=error) or a
  degenerate </think>-only body is excluded from the floor, which is scored
  over the VALID samples only. It still fails CLOSED when a scenario has too
  few valid samples to judge — an all-504 scenario is "never tested", not
  "green". A non-pass with an empty, untagged body and no error stays a real
  FAIL: with no error signal we do not guess infra (fail-open is the dangerous
  direction). New flag --min-valid; default floor relaxed to 0.6 (majority of
  three) for the smaller behavioral N.

- Every rubric pack declares repeat: 3, so one 504 leaves >=2 valid samples to
  score. Cost: a touched pack now bills 3x per run. That is the modest,
  cost-conscious N; these legs only run when their plugin (or the shared paid
  harness) is touched.

- The behavioral job lets promptfoo exit non-zero and makes pass-rate.sh the
  arbiter of the leg, reading results.json. A total crash that writes no
  results.json still fails, because pass-rate.sh errors on a missing file.

cheap tier §18 gains two mutation-proving fixtures (a single 504 is excluded
and the run passes; an all-504 scenario fails closed) and a check that every
behavioral pack still declares repeat:. Verified: cheap 1284/0, counterfeit
22/0, and the FAULT classifier unit-tested offline across pass/fail/starve.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU

Copy link
Copy Markdown
Owner Author

Demonstration — grill-me progressive disclosure (the anchor + path-consent change)

Per the demonstration discipline in AGENTS.md: this is the skill actually run on real input, before/after visible, with the rule that produced each change and the misses named. It is not a description of what the skill would do — it is the two openings the two prose versions actually produce.

Real input

The genuinely-unsettled decision I faced at the top of this turn (not a strawman — it is the plan this PR's final commit executed). Stated as it stood before I acted:

"The required behavioral tier is red. A single upstream 504 on one graveyard scenario made promptfoo exit 100, even though the model passed every scenario it was allowed to answer. I want to fix this so the tier stops going red on the weather. Options on the table: just re-run until it's green; disable/soften the required check; or build a statistical floor that tolerates transient faults. If a floor — how many repeats, what pass threshold, and how does it get wired so promptfoo's own exit code stops being the arbiter? Grill me before I build it."

Branches in that plan: (A) re-run vs. soften vs. statistical floor (the load-bearing one); (B) repeat count N; (C) pass threshold / floor; (D) how a transient 504 is distinguished from a real failure; (E) CI wiring so promptfoo's exit stops deciding the leg; (F) the cost of repeating a paid tier.


BEFORE — old prose (base ccd51df)

The old SKILL.md jumps straight to "## The frontier/round loop → Compute the current frontier. Ask it as one numbered round." There is no gate before questioning, so a faithful run opens like this:

❓ Q1 — Fix strategy: re-run, soften the check, or a statistical floor?
➡️ Statistical floor — re-running hides the signal, softening a verification-integrity check is self-refuting.
❓ Q2 — Repeat count: how many times does each scenario run?
➡️ 3 — smallest N that survives one fault and stays cost-conscious.
❓ Q3 — Floor: what per-scenario pass rate is required?
➡️ 0.6 (majority of 3).
❓ Q4 — Fault vs failure: how do you tell a 504 from a real rubric fail?
➡️ Exclude rows promptfoo marks as errors; score the floor over valid samples only.
❓ Q5 — Wiring: how does promptfoo's exit code stop being the arbiter?
➡️ `|| echo` the eval, let pass-rate.sh read results.json and decide.

Five questions fired in one round, before it was ever confirmed what "fixed" means or which of these the user actually wanted to open. Q2–Q5 are all downstream of Q1: if the user had said "just soften the check," every one of them is wasted. That is the exact waste the change targets.

AFTER — new prose (this PR)

The new "## Anchor, then consent to each path" section + references/path-consent.md forces a round 0 anchor, then a batched consent menu before any descent. Same input, faithful run:

Before I ask anything — the anchor, as I read it (correct me in one line):
• Goal: stop the required behavioral tier going red on transient upstream faults.
• Outcome: a 504 on one scenario can't fail a leg the model actually passed; a real rubric regression still does.
• Out of scope: changing which model/grader is used; the deep/pier tier.

One routing round — tell me which paths to spend questions on:

🧭 Path — Fix strategy (re-run / soften / statistical floor) [DEEP, ~3 q]
➡️ recommend: statistical floor — the only option that keeps the check meaningful.
🧭 Path — Fault-vs-failure classification (what counts as a transient) [DEEP, ~3 q]
➡️ recommend: exclude promptfoo error rows; fail closed if too few valid samples survive.
🧭 Path — CI wiring (who arbitrates the leg) [STANDARD, ~2 q]
➡️ recommend: let promptfoo exit non-zero; pass-rate.sh reads results.json and decides.

explore / accept / defer / out-of-scope?

(N=3, floor=0.6, and the paid-cost tradeoff are LIGHT confirm-or-skips hanging off "Fix strategy" — I'll fold them in only if you explore that path.)

The rule that produced the change: path-consent.md"No branch questioning before three slots are set: Goal, Outcome, Out of scope" and "Before descending into any STANDARD or DEEP branch, present the branch as a header and let the user route… Batch the menu." The old run spent 5 questions on an unconfirmed goal; the new run spends zero until the user routes, and collapses B/C/F (the LIGHT knobs) under their parent instead of asking them as peers of the real decision.


The misses (this is not a sales pitch)

  1. The anchor can be confidently wrong, and nothing catches it. I inferred "out of scope: the deep/pier tier." The plan never said that. The skill says infer-then-confirm-in-one-line, but a user skimming a plausible-looking anchor rubber-stamps it — and a wrong exclusion silently prunes a branch the user wanted. path-consent.md guards the inverse (descending into an off-anchor branch = "scope-silent exploration") but has no guard for wrongly excluding an in-scope branch via a bad anchor. That is the more dangerous direction and it is unhandled.

  2. LIGHT branches still get no disclosure. N=3, floor=0.6, and the 3× paid-cost increase are real decisions with real consequences (0.6 vs 0.8 changes what fails), but as LIGHT confirm-or-skips they get no consent header — same silent-assume path as the old prose. The change improves STANDARD/DEEP disclosure and leaves the LIGHT floor exactly where it was. For this plan, the cost tradeoff arguably deserved a header; the skill's own rule ("a header would double their cost") suppresses it.

  3. Leverage ordering is underdetermined. "Fix strategy" and "Fault-vs-failure classification" are both DEEP and both unsettled; the skill says order by stakes × unsettledness but gives no tiebreak, so the order above is my judgment, not the skill's. On a plan with several co-equal DEEP branches the "right order" the skill promises isn't actually determined by the prose.

  4. On a mostly-settled plan the machinery is pure ceremony — and I confirmed this by running it on a second real input, docs/examples/PLAN.md, where Phases 1–4 are marked done. There the faithful run should hit "a plan that triages LIGHT end to end gets a brief 'no session needed'" and decline — but the new anchor step still fires first, so the skill sets up a round 0 anchor before reaching the sentence that tells it to bail. The decline short-circuit and the mandatory anchor are in slight tension; the anchor should be gated behind the LIGHT-end-to-end check, not ahead of it.

Net: the change removes the single most expensive failure mode (anchorless deep interrogation) cleanly and the before/after difference is real, but it leaves the LIGHT path undisclosed, has an asymmetric anchor guard, and adds a step that a fully-settled plan has to walk through before it's allowed to decline.


Generated by Claude Code

@JRichlen
JRichlen merged commit c791d83 into main Aug 29, 2026
51 checks passed
JRichlen pushed a commit that referenced this pull request Aug 29, 2026
Follow-up to the demonstration in #75, which surfaced the ordering bug: the
"Anchor, then consent" section opened with an unconditional "No branch
questioning before the anchor is set," so a faithful run set up the round-0
anchor before ever reaching the "a plan that triages LIGHT end to end gets a
brief 'no session needed'" decline — ceremony on a plan the skill should have
declined outright.

Now triage is the first move. SKILL.md gates the anchor: triage the whole
plan first; if every branch is LIGHT end to end, say "no session needed" and
stop before any anchor; only otherwise is the anchor set. path-consent.md
gains a "Before the anchor — the decline gate" section stating the same
precondition, and a new "Anchor before decline" failure mode. The literal
anchor requirement and the four-route consent menu (both asserted by the
cheap tier) are preserved, and SKILL.md stays at its 140-line budget by
reclaiming the decline line from "When to use" and tightening the header
description. cheap tier 1294/0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tuKEs7jU6FawKTbdHMzUU
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants