Baseline gate: no XP spend before the first submission completes - #2
Open
devin-ai-integration[bot] wants to merge 7 commits into
Open
Baseline gate: no XP spend before the first submission completes#2devin-ai-integration[bot] wants to merge 7 commits into
devin-ai-integration[bot] wants to merge 7 commits into
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Investigation findings
The pre-baseline spend is not one bug in one file — it is the ordering baked into three places, none of which ever says "measure before you have a ladder result", so each one looks reasonable alone:
docs/getting-started.md— beat 5 uploads, beat 6 was "First evaluation" ("Run a hosted batch sized by the lab's eval-design binding"). Submission appeared only in the closing block, as an option: "If they want to submit, help them submit."AGENTS.md— the loop table puts 2 Evaluate and 3 Read ahead of 10 Submit — the gate, and then says "Steps 1–3 and 6–8 are cheap and fast by design — no gates". For a lab with a baseline that is exactly right; for a lab without one, "cheap" is spend against no reference.skills/seed-a-policy/SKILL.md— handed a freshly seeded policy line straight intorun-eval: "the first eval goes throughrun-evalandsurvey".Two things the fix had to respect. First, non-negotiable #5 — submission "requires the human's explicit go-ahead, every time" — so "baseline first" cannot mean an automatic submit; it means propose first, and spend nothing until the human's baseline lands. Second,
submit's preconditions demand "a verdict-rungab-compareresult against the current baseline", which a baseline submission can never satisfy: that precondition was itself part of the loop that forced an eval before the first submission.Outside this repo, the same ordering is mirrored in
Metta-AI/optimizer-agent(skills/seed-a-new-policy/SKILL.md), inMetta-AI/optimizer-skills(skills/seed-a-new-policy/SKILL.md,starter-pack/SKILL.md,starter-pack/cards/seed.md,playbooks/optimize-policy.md), and — authoritatively, since it is what a live session actually follows — in the Devin playbook "Run an Agent Optimization Loop for a Coworld Policy" (!optimize_policy), whose step 3 is "Diagnose the current policy with a smoke + diagnostic XP eval" with submission at step 10. Those are tracked separately (one issue per mirror repo, and replacement wording handed to the playbook's publisher); this PR is the reference implementation.The change
A ninth non-negotiable plus a real check, so the rule survives a future edit that reorders the prose:
tools/check_baseline_gate.sh <lab>is the enforcement. It reads the lab'sWORKING_CONTEXT.md→## Baseline submissionblock and exits0only whenstate: completedand a realladder resultis recorded;1= no baseline yet (with the permitted next step printed, specialized per state),2= cannot tell (no lab, missing block, unrecognized state) — an unknown baseline is not a baseline. Placeholder text like*(rank + score + date)*is voided, so an untouched template never passes.run-eval(step 0 of its method, before any body is composed),ab-compare,experiment(before the record is even opened — designing an experiment you may not run is not a useful pause point). That is what makes this a gate rather than an ordering: reordering the docs no longer unblocks the spend, because the skills ask the script.skills/submitnow distinguishes the two submissions it can perform: the baseline submission carries no evidence preconditions (it is the reference everything later is measured against) and records the gate state; a promotion submission keeps the full evidence bar. Consent is unchanged for both.skills/seed-a-policyexits intosubmit, notrun-eval.docs/getting-started.mdgains beat 6, "The baseline submission — before any measurement spend" (old beat 6 → 7), including the decline path: recordstate: blocked, say optimization is on hold, and explicitly do not fall back to "we'll just run a small diagnostic instead" — that fallback is the failure mode this beat exists to prevent.games/_template/WORKING_CONTEXT.mdgains the## Baseline submissionfield (state/policy/league/submission/ladder result), so the gate has a per-lab input that a resuming agent can read with no chat history (#7).Evidence
The repo has no test harness, so the check ships with its own:
tools/check_baseline_gate.sh --self-testbuilds a fixture per state and asserts the exit code that decides whether XP can be spent.Against this repo as it ships (no lab installed), the gate blocks, which is the correct default:
bash -nclean; the script is plain bash + coreutils (macOS and Linux), matching the existing hooks intools/.Treat this as a proposal: every commit in this repo's history is authored by James Boggs (james@softmax.com), so the doctrine here is not mine to change unilaterally — in particular the wording of non-negotiable #9 and the decision to have
submitdistinguish baseline from promotion submissions are the two calls a maintainer should review before merge.Harness enforcement (added after the first review round), and what it does not cover
The doc +
check_baseline_gate.shhalf above binds an agent that reads a skill and chooses to call the script. A liverun showed that is not enough: a session composed "go straight to hosted XP" as a recommended option on its own,
without any file telling it to. So both harnesses now gate at the tool boundary, where the agent gets no say.
harness/claude-code/settings.jsonandharness/codex/hooks.jsongain aPreToolUsehook onBash(
tools/baseline_pretooluse_gate.sh) and aSessionStarthook (tools/baseline_session_start.sh).The
PreToolUsehook parsestool_input.command, matches only concrete spending forms(
coworld xp-request,ab-compare,eval-sweep/eval_sweep,eval_request.py, the experimentrecord.pyentrypoint), calls the gate, and returns the vendor-supported deny response:
{"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "..."}}Gate exit
1(no baseline) and exit2(cannot tell) both deny; a missing gate script denies. Failing closed isdeliberate: an unknown baseline is not a baseline.
Matching is narrow on purpose. An earlier revision matched the bare words
experimentandrun-eval, which deniedls experiments/,read skills/ab-compare/SKILL.md, andgit commit -m "experiment run notes". A gate that blocksreading the docs teaches people to turn it off. Those are now explicit allow cases in the self-test.
The
SessionStarthook injects the restriction only when no baseline exists, so a lab that is past its baseline seesnothing. That is what stops the model from composing hosted-XP-first as a menu option in the first place.
This covers cloned-repo users only. It does not cover the platform Participate flow. A newcomer who arrives through
the Participate button on the game page has no clone, no
settings.json, and no hooks, so nothing here can fire forthem. The load-bearing fix for that path is the platform payload itself, and it is a separate PR against
Metta-AI/metta: https://github.com/Metta-AI/metta/pull/20476. The prose mirrors arehttps://github.com/Metta-AI/optimizer-agent/pull/6 and https://github.com/Metta-AI/optimizer-skills/pull/10.
Evidence for this half:
tools/baseline_pretooluse_gate.sh --self-testpasses 16 cases (5 allow, incl. a realisticpayload with fields after
tool_input; 9 deny; plus completed-baseline-allows and gate-unavailable-denies). Thesedfallback used whenpython3is absent additionally matches the raw payload, so an escaped-quote command such asbash -c "coworld xp-request ..."cannot slip through a truncated extraction. Both harness JSON files parse, bothscripts are
bash -nclean,git diff --checkis clean.shellcheckis not available on this machine.Link to Devin session: https://app.devin.ai/sessions/0c0b9632b5a84c7db7c0abaf26cfd036
Requested by: @arisklar6