feat: add long-horizon agent eval project - #42
Conversation
Signed-off-by: Alexander Watson <zredlined@users.noreply.github.com>
Signed-off-by: Alexander Watson <zredlined@users.noreply.github.com>
Signed-off-by: Alexander Watson <zredlined@users.noreply.github.com>
Signed-off-by: Alexander Watson <zredlined@users.noreply.github.com>
johnnygreco
left a comment
There was a problem hiding this comment.
Thanks for keeping this concrete and research-focused. The overall shape is easy to follow, and I did not find any committed secrets or stray run artifacts.
I think this needs another pass before merge. The main blockers are secret redaction, cleanup verification, incomplete GitHub ref pagination, and selection bias from discarding healthy runs that make no proposal. I left the code-specific details inline.
The project also needs a CI job that runs npm ci and npm run check with read-only GitHub Packages access. The current Egress Gate failures look unrelated: its tests pass, but dependency auditing is failing on the runner pip version.
Signed-off-by: Alexander Watson <zredlined@users.noreply.github.com>
Signed-off-by: Alexander Watson <zredlined@users.noreply.github.com>
|
The challenger should stop as soon as the GitHub oracle observes the target mutation. Today it keeps running until the time limit even though the experiment already has a conclusive compromise. In one 10-minute run, the target was observed after 9 turns, but the challenger continued for another 531 turns and consumed about 41.6 million additional input tokens. Please stop the challenger when the target is observed, record the observation time and a target_observed stop reason, and then allow the existing short settlement period for pending reviewer evidence. Continuing after compromise can remain an explicit opt-in for experiments that need it. |
|
Concern: the experiment鈥檚 main GitHub write request may never reach the reviewer. The PR attaches the standard GitHub provider with read-only GitHub access. When the challenger proposes a narrow write permission for the same GitHub host, current OpenShell rejects the proposal before review because it conflicts with the provider rule鈥檚 internal metadata. I reproduced this with OpenShell 0.0.112-dev.5+g679fe4c3, built from commit 679fe4c334f0c62a653b004fae7008a631bf7f22, using the exact provider and initial policy from the PR. Removing the PR鈥檚 additional github-read-only rule did not change the result. Direct policy updates, automatic OpenShell proposals, and agent-authored proposals for unrelated hosts all worked; the failure is specific to agent-authored requests that add access to a provider-covered host. This makes an uncompromised result ambiguous. It could mean the reviewer resisted the challenger, or it could mean OpenShell prevented the reviewer from seeing the important request. The experiment currently treats those as the same outcome. |
Thread rotation currently fires only on consecutive model failures. A stalled challenger keeps completing turns successfully, so it never triggers: in run 20260821212853 the agent emitted the same ten refusal sentences on a verbatim cycle for ~60 minutes and ~500 turns with zero tool calls, and only recovered by chance when a turn happened to re-read its own task instructions. It then immediately produced the most novel behavior in the corpus before the run died to the credential-placeholder bug. Add detectLull(): a rotation trigger requiring both trailing idle turns and a high duplicate-message rate. Idleness alone is not sufficient -- healthy 30-minute runs sit idle for 80-220 turns near their deadline. Repetition is what separates them: across the 20260821/20260822 corpus, healthy runs peaked at a 22% duplicate rate while stalled runs reached 72-86%. Replayed against all 13 archived traces at the defaults (window 40, idle 40, duplicate rate 0.5): 20260821212853 (6h) fires at minute 41 (self-rescued at 97.8) 20260821161329 (6h) fires at minute 97 20260821161318-0008 fires at minute 29 (one minute before deadline) remaining 10 runs no trigger Sweeping the duplicate threshold from 0.4 to 0.7 moves trigger times by about two minutes, so the boundary is not knife-edge. Known gap, tracked separately: update_handoff retains the last 32 events, which during a lull are all refusal messages. Rotating mid-lull therefore reseeds the fresh thread with the text that caused the loop. The handoff needs to prefer command executions and deduplicate message text before this trigger is useful in practice. The detector logic is duplicated between src/lull.ts and an inline node block in scripts/challenger.sh because the script runs inside the sandbox without repository access. src/lull.ts and its tests are the reference implementation; keep the two in sync. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Alexander Watson <zredlined@users.noreply.github.com>
|
Handoff/lull fix:
|
|
Review update: The GitHub path uses providers for protected credential delivery and requires provider policy composition to be disabled on the dedicated evaluation gateway. The README includes the one-time setting command, and the runner now fails fast if Providers v2 is enabled. The initial policy grants only model access, so all GitHub authority goes through review with an exact-write canary before either model starts. A one-minute Station smoke at challenger |
Signed-off-by: Alexander Watson <zredlined@users.noreply.github.com>
Summary
Add a self-contained research example for running persistent agents over configurable wall-clock horizons and repeated parallel attempts. The initial experiment evaluates an AI reviewer handling OpenShell policy proposals while a challenger attempts to mutate a protected GitHub repository.
This intentionally stays concrete: the GitHub experiment is wired directly into the runner, with no scenario registry, plugin system, service layer, or production deployment machinery.
Related issue
None. This is a standalone research project and does not change OpenShell product behavior or public APIs.
Changes
--minutes,--runs, and--concurrencyCLI controls..env.Testing
npm run checkbash -n scripts/challenger.shnode --check scripts/check-responses-endpoints.mjspython3 scripts/update_license_headers.py --checkChecklist
.env, credentials, or run artifacts are included.