ワンクリックで
generate-a-crux
Use when finding and statistically confirming a reproducible Crewrift crux before changing the policy.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Use when finding and statistically confirming a reproducible Crewrift crux before changing the policy.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Use when improving a Coworld player through one diagnosed failure and completed comparison evidence.
Use when compiling, validating, and uploading a notsus change as a new Crewrift policy version.
Use when decoding a Crewrift replay for authoritative deaths, survival, movement, roles, tasks, or rewards.
Use when verifying that the notsus Bedrock vote advisor fires before an advisor-sensitive evaluation.
Use when classifying a stuck, failed, empty, or zero-scoring evaluation as infrastructure or policy failure.
Use before evaluations or after roster churn to resolve live policy versions and restore the champion flag.
| name | generate-a-crux |
| description | Use when finding and statistically confirming a reproducible Crewrift crux before changing the policy. |
A crux game is a config (map + role assignment + field) where a specific rival policy reproducibly beats your policy at a fixed role and seat. A crux is the only honest justification for a behavior change: it isolates a single, reproducible deficit you can diff on replays. A leaderboard gap is NOT a crux — most "losses" in the standings are role-assignment / field / seed variance that vanish when you reconstruct and re-run. Confirm before believing.
Source 2 is strictly stronger (deterministic config). Prefer it when you have an own low-scoring episode.
league_605ff338-0a2e-4e62-aeda-559df9a9198f679961. sim.nim calls initRand(config.seed), so a pinned
seed makes map + task assignment + role assignment deterministic. This is THE crux
reproducibility lever.harness_core.wilson(k, n) returns (p, ci_low, ci_high).All shipped in ../../tools/ (the package universal/tools/ dir; in the live repo
they live in _harness/, run as uv run python _harness/<tool>.py).
eval.py — the league-faithful A/B CLI. One forced-role seat for the tested
policy, 7 top league players fill the rest. Prints win-rate + Wilson CIs. Use this
for the league-round source and as the canonical verdict path.league_eval.py — the engine eval.py calls (run_league_ab); both arms run
concurrently server-side. Use its functions directly when you script a swap
tournament (one arm per swapped rival).league_roster.py — live_members(client, league_id=...) returns all live
members ranked by best recent round score (rows: player_id, player_name, label,
policy_version_id, score); fetch_top_players(...) returns the top-N opponent
pvids excluding yourself. This is how you reconstruct a field and pick candidate
rivals to swap in.harness_core.py — wilson(k, n), forced_imposter_slots(seed, ...),
slot_role_config(...) for the seed-deterministic forced-role layout.metrics.py — offline per-episode diagnosis (uv run python _harness/metrics.py <run_dir> [--candidate <substr>] [--json]): win-rate, vote accuracy, where score is
lost. Use AFTER a crux is confirmed to diff WHY the rival wins.antfarm_run.py — artifact harvester (downloads results.json + replays per
episode) when you need raw logs for deep diagnosis. NOTE: this copy emits the
pre-2026-06-12 request shape and will 422 until patched to the unified roster
body — eval.py/league_eval.py are already patched, prefer them.Decide role (crew or imposter) and that you are fixing it. The requester's role is
chosen by picking a seat of that role in the seed-deterministic layout, not by
editing the layout. eval.py does this for you via requester_slot_for_role(role, seed).
You cannot recover the round's seed. Rebuild the matchup:
policy_version_id — stale pvids from old round results
are rejected as not-runnable, and bare player names with >1 live version are rejected
as ambiguous:
import league_roster
from coworld.api_client import CoworldApiClient
client = CoworldApiClient.from_login()
members = league_roster.live_members(
client, league_id="league_605ff338-0a2e-4e62-aeda-559df9a9198f")
# find the rival row, take members[i]["policy_version_id"]
--baseline, the rival as --candidate, your fixed
role, a pinned fresh seed, and the league top-7 filling the field:
uv run python _harness/eval.py \
--baseline <your-policy-label> \
--candidate <rival-policy-label-or-pvid> \
--role crew --num 30 --top-n 7 \
--game-config seed=679961 # pin a FRESH seed; vary it across a small set, see Step 3
--candidate/--baseline must be owned, uploaded policy labels; pass the rival as a
live pvid via --opponent <pvid> seating if it is not one of your owned policies.You have an own past experience-request episode (a config + seed your arm scored low in). Turn it into a multi-comparator crux:
game_config_overrides from that episode's request record,
including its seed and any forced-slots config. This config is re-runnable
verbatim.live_members), construct ONE
arm that re-runs that exact config with the rival's pvid swapped into YOUR seat, every
other seat unchanged. Run all rival arms (plus a re-run of your original) in
parallel — each is a separate single-roster-entry request. league_eval.run_arm /
run_league_ab is the concurrent submit/poll engine; the recon-sweep controller in
the source sessions ran ~20 arms in flight (tmp/crux/recon/sweep.py,
session-derived, not a shipped universal tool).seed via --game-config seed=<int> (arbitrary keys pass through; verified keys
include seed, tasksPerPlayer). To force imposter SEATS explicitly on top of the
seed, set imposterCount: 2, autoImposterCount: false, and a slots array of
per-seat {"role": "crew"|"imposter"} (the _harness forced_slots_config).If a strong IMPOSTER rival is the suspected crux, run its arm twice with identical
seed/field/seat: once default, once with --game-config buttonCalls=0 (this is the
ONLY accepted key — numberOfButtonCalls/maxButtonCalls/buttonCallsPerGame all
HTTP-400). If the edge survives buttonCalls=0, it's learnable behavior (an actionable
crux). If it vanishes, the edge is the one-per-game button mechanic — feeds the
"press build" lane, not a behavior fix.
eval.py prints, per arm: wins/n, win-rate p, and the 95% Wilson CI. A confirmed
crux requires the rival's Wilson CI to separate strictly ABOVE yours (non-overlapping
intervals) at your fixed role/seat.
A single config at n=30 often overlaps. Pool a same-direction deficit across related configs (same rival, several reconstructed rounds / several crux seeds) and run Wilson on the pooled k/n. The confirmed optimizer crux was pooled 167/540 (you, 0.31 [0.27,0.35]) vs 228/540 (rival, 0.42 [0.38,0.46]) — non-overlapping only after pooling; single rounds inside that pool overlapped. Do NOT pool opposite-direction results (that's just averaging away signal). If pooling at large n stays overlapping, it is variance — drop it (the source sweep ran some rivals to n=630 and they stayed inconclusive; those are NOT cruxes).
episodes[].participants[].position, not by matching pvid.live_members /
client.list_memberships(active_only=True) immediately before each submit.{"player": {"top_n": 7}} auto-fill draws
ONLY from the Competition-division champion pool, which is empty today (all play is in
Qualifiers), so it returns too few opponents and 400s. Use the explicit policy_ref
roster path (not champion-restricted) ranked by league_roster recent-round scores
instead. {"player": {"random": true}} draws WITH replacement (can dup, including your
own champion into an opponent seat) — fallback only.sleep gets reaped and the poller dies silently
(0-byte logfile, arms finish server-side, no verdict). Poll with Monitor + an
until-loop.antfarm_run.py 422s on the current server (pre-rework request shape). Use
eval.py/league_eval.py for arms; only reach for antfarm_run.py after it is
patched to the unified roster body, and only when you need the raw replay/log
download for diagnosis.You have generated a crux when:
Then record it for implementation: the rival, your fixed role/seat, the config(s)/seed(s), the pooled k/n and CIs, the per-episode replay ids, and a one-line who-does-better summary. (In the source workflow these were filed as Asana "Crux Games" tasks; file wherever your team tracks crux work.) If no rival's CI separates above you after pooling, record "not a crux — variance/hard map" and stop — that is also a successful outcome (it saves implementation cycles).