GARSGitHubGitHubJavier Rodríguez Hernáez

Try GARS's guardrails

Two cards. First, play the agent and try to break GARS's rules. Then run GARS's check on an experiment's design.

Be the agent: try to break the rules

In a GARS workspace, GARS's guard checks each call the agent makes to Claude Code's file tools (Read, Glob, Grep, Edit, Write, MultiEdit, NotebookEdit) and to its shell tool (Bash), before it runs; calls to other tools are not checked. This is that guard, unmodified, running in your browser: pick something an agent might try, or make your own call, and ask it.

It answers as if the agent worked in a GARS workspace with two projects: public-rnaseq, registered as public, and pilot-cohort, registered as held under a data agreement (deidentified_under_agreement).

Try to break a rule:

Or do what the rules allow:

Or make your own call. The tool the agent asks for:

Deniedexit 2

Blocked: _system/guard_hook.py is protected template or machine-owned state; a workspace session never edits it directly (R-094; decision 0058).

Next: read its stage contract for the owning writer, or ask the human to update template code through the repository.

The rule it cites, in GARS's specification: R-094, §9.3 Protected paths. The decision record it cites: 0058

Recorded output (GARS 0d9954c, recorded 2026-09-30 by the same Python, outside a browser). Press Ask to run it in your browser.

What the guard read, and exactly what it wrote

The call, on the guard's standard input, with the one field of the tool's input the guard reads:

{"tool_name": "Edit", "tool_input": {"file_path": "/lab/gars/_system/guard_hook.py"}, "cwd": "/lab/gars"}

Its standard error:

Blocked: _system/guard_hook.py is protected template or machine-owned state; a workspace session never edits it directly (R-094; decision 0058). Next: read its stage contract for the owning writer, or ask the human to update template code through the repository.

It reads each call as Claude Code hands it over: the tool's name, the tool's input, and the folder the session runs in. Exit 0 lets Claude Code run the call; exit 2 stops it, and the agent is shown the reason. Here nothing you ask is run: the guard only answers. No AI is involved in the verdict: you play the agent, and the guard is plain Python, standard library only.

At the pinned commit this page runs, the guard works in real use only under Claude Code, for a session started in GARS's workspace folder; a session started elsewhere, or another agent harness, runs unguarded. It judges the call, not why the agent made it: GARS records its resistance to prompt injection as unmeasured, and does not claim the guard stops it. Some rules stay in writing only: the guard's own header gives "do not read a colleague's directory" as one it cannot check.

The design check: batch confounded with condition

This is GARS's real design check, unmodified: press Run and it runs in your browser. No AI is involved: it is plain Python, standard library only. In a GARS run this check is part of stage 01, which its contract calls the last cheap moment before hours of pipeline compute.

This table is d01, GARS's own public test design for this flaw. As published, both A samples are in batch x and both B samples in batch y, so batch cannot be told apart from condition.

samples.csv, GARS's public design d01. Only the batch column is yours to change.
sample_idbatchconditiongroupreplicate
AA1
AA2
BB1
BB2
The batch check's source at 0d9954c

Refusedexit 11 failure

confounded_condition: batch perfectly confounded with condition; batch cannot be separated from the condition effect (R-072)

Recorded output (GARS 0d9954c, recorded 2026-09-29 with CPython). Press Run to run it in your browser.

The 15 named checks, 14 passed
  • inputspass
  • registrypass
  • headerpass
  • complete_designpass
  • duplicate_sample_idpass
  • input_units_layout_pathspass
  • referential_integritypass
  • unit_of_replication_declarationpass
  • reference_release_declarationpass
  • paired_declarationpass
  • subject_requirementpass
  • batch_confoundingfail
  • group_and_replicate_designpass
  • samplesheet_configpass
  • format_sourcespass

Crossing batch with condition passes; so does one batch for everyone. It reads the batch column you declare; it does not infer batch from lanes or run dates, and it passes flaws it does not look for.

GARS 0d9954c · template v0.10.0 · Python loads from jsDelivr when you open this page

What the design check looks for, and what it does not

GARS's defect catalogue lists six kinds of flaw for this stage: batch confounded with condition, one sample per group, sex or age imbalance across arms, cells treated as replicates, sample labels swapped, and a truncated sequencing file, the last caught only in the check's full integrity mode, which this page does not run. This card lets you try the first. The catalogue

Why a plain check

On the builder's own test cases, GARS's checks caught 9 of 10 kinds of planted flaw, with no false alarms on 10 clean ones. Sealed away from the builder, by a separate AI context rather than a person, 6 of 10 kinds were measured and caught; the bar of 9 of 10 is not met, and the public catch rate stays unmeasured. Decision 0103

How well models catch this on their own: the graded results

What happens next

What happens next: watch the agent stop for a person's decision (a recording made at an earlier GARS version).

Provenance

Nothing you type or choose here leaves your browser. The Python runtime downloads from jsDelivr, which sees your internet address.

GARS commit 0d9954cc3fcf143977c2a8d61ffa06110003f6ad. The guard is guard_hook.py, and the design check is in stage01_samplesheet.py. Before anything runs, your browser checks each GARS file against its sha256, and each Python runtime file against its pinned hash (Pyodide 314.0.7). The Python standard library is Pyodide's own, trimmed to the 135 files a session reads, each compiled ahead of time by this same Python from its unchanged source, so your browser does not have to.

Inside the Python this page runs, GARS's own test of its guard gives its recorded decision on all 2,606 calls it pins.

The files your browser checks, each with its sha256
  • gars/_system/stage01_samplesheet.py sha256 46a1cf8226e373954f6f2930f114467785fce6b1fff4507eb72f144a7029dc8c
  • gars/_system/integrity.py sha256 e25a078005109e1123c9af32d45e9e472da9660a42deb7b31b215274c2325c83
  • gars/_system/workspace.py sha256 d19544314912937f48880634052292ea0a8dd469e6213c3096b6eec0349ab2a2
  • gars/_references/VERSION sha256 57394e83d68850661c8045e30fcbb180480026871302a588d2aff7c1b0b64531
  • gars/_templates/config/rnaseq_bulk.yaml sha256 7d266590e38b40f8a6eafcce99255def8a21303c65daa6e6a2ebc2d3ed17ca5d
  • benchmarks/defects/development/d01/00_data/rnaseq_bulk/files.csv sha256 58f0b73af2300867fdc80a86577f4f59ccb8ac2b13e83a200e5ec85b8890b399
  • benchmarks/defects/development/d01/00_data/rnaseq_bulk/raw/DEV2722_L001_R1.fastq sha256 e2261d8b80a6dd0deb89762376c4d90c2e802813ae4e8e9e5d483834913021ef
  • benchmarks/defects/development/d01/00_data/rnaseq_bulk/raw/DEV2864_L001_R1.fastq sha256 e2261d8b80a6dd0deb89762376c4d90c2e802813ae4e8e9e5d483834913021ef
  • benchmarks/defects/development/d01/00_data/rnaseq_bulk/raw/DEV4367_L001_R1.fastq sha256 e2261d8b80a6dd0deb89762376c4d90c2e802813ae4e8e9e5d483834913021ef
  • benchmarks/defects/development/d01/00_data/rnaseq_bulk/raw/DEV6821_L001_R1.fastq sha256 e2261d8b80a6dd0deb89762376c4d90c2e802813ae4e8e9e5d483834913021ef
  • benchmarks/defects/development/d01/00_data/rnaseq_bulk/samples.csv sha256 8edcf46e5304137049d16878dd6ff68d1992b516f5f0ef3e7fad194f6310ab8c
  • benchmarks/defects/development/d01/_config/rnaseq_bulk.yaml sha256 c2aa16a9157e6a552fbd4ee5eca88c3dba300743310dc801161448e4a603eada
  • gars/_system/guard_hook.py sha256 06fbaae83b51222305d545a9bafa338e2a3dde96f8dad1015a73f48135e8c1c2
  • gars/_system/tools/__init__.py sha256 c4e7d7b242cfd9df0090cef3a935b00fc9b63f89efe780f58324db9c65b692c9
  • gars/_system/tools/policy.py sha256 8dd089ed9d706b7b01681f8dbfdb905042ec400eadfda8fff173800a11d167cf
  • gars/_system/tools/closed_output.py sha256 94fea385748f400df29e976b4bad68071ebfcfa8503dfc9a9a847677bd7c4088
  • gars/_system/tools/execution.py sha256 3f0fe9442e358d81bd9d2bc738c7767e2efaa4c988774c07f9ad66d0efefc75c
  • gars/_system/tools/registry.json sha256 e2245b83f5f14392d140c4785cc4e94a73efed4325cc65db63502950164b2c2b
  • the example project public-rnaseq's dataset row, written by GARS's stage 00 writer sha256 275909b7af15b8a9fda14f3918547a33daaf581dd6480ecfd708bd1fbc0726fa
  • the example project pilot-cohort's dataset row, written by GARS's stage 00 writer sha256 2e2ae368d61f1eee1fb80de8071310ba28a171c9fb0cc403306cd4264176ac59
  • python_stdlib.zip (Pyodide 314.0.7), trimmed and compiled, the part Python starts with (python_stdlib.start.zip.gz) sha256 5c988330ce5f946f88e84cf0b18f86832c9d9e9a326cbfe5f9986fd6b9b1ed65
  • python_stdlib.zip (Pyodide 314.0.7), trimmed and compiled, the part the two checks import (python_stdlib.check.zip.gz) sha256 c466252d6c83f4fe135b57100c7eb58bbf8fbb8e0e20aad7b50070190b447342