No description
  • Python 99.7%
  • Shell 0.2%
  • Dockerfile 0.1%
Find a file
Kai Siren 008d741c14
Some checks are pending
CI / Test (push) Waiting to run
CI / Docker (push) Waiting to run
TruffleHog / Scan for secrets (push) Waiting to run
CI / Lint & type-check (push) Waiting to run
Version bump guard / Require version bump on code changes (push) Waiting to run
chore(ci): remove codex-review-gate + undraft-and-poke-codex workflows
closes #37
2026-05-16 15:43:12 -07:00
.claude chore(lockdown): adopt agent-guard pre-tool-use delegate 2026-05-16 13:59:44 -07:00
.claude-plugin Fix author name from Kai Davis to Kai Siren 2026-04-24 19:23:47 -07:00
.coily rename: update cross-repo refs after coilyco-ai to agentic-os-kai 2026-05-15 02:29:57 -07:00
.gauntlet rename Weapon -> Trial throughout 2026-04-23 10:57:48 -07:00
.github/workflows chore(ci): remove codex-review-gate + undraft-and-poke-codex workflows 2026-05-16 15:43:12 -07:00
agents fix: subagent allowlists work under plugin namespace 2026-04-24 19:14:01 -07:00
docs docs: trim README + FEATURES to fit catalog-doc-size cap 2026-05-15 21:34:10 -07:00
gauntlet log: standardize on o11y in module docstring 2026-04-30 09:26:35 -07:00
scripts chore: adopt coilysiren/agentic-os v0.2.1 upstream-ref pre-commit suite 2026-05-15 23:30:36 -07:00
skills skills/gauntlet: auto-fix high risk in auto mode 2026-04-24 19:36:55 -07:00
tests rename Weapon -> Trial throughout 2026-04-23 10:57:48 -07:00
.dockerignore Add .dockerignore to exclude agent worktrees and caches 2026-04-19 04:25:07 -07:00
.gitignore chore: commit coily lockdown baseline, gitignore host-local Claude state 2026-04-24 15:42:10 -07:00
.pre-commit-config.yaml chore: adopt coilysiren/agentic-os v0.2.1 upstream-ref pre-commit suite 2026-05-15 23:30:36 -07:00
.python-version uv init 2026-04-10 01:10:53 -07:00
AGENTS.md rename: update cross-repo refs after coilyco-ai to agentic-os-kai 2026-05-15 02:29:57 -07:00
CLAUDE.md Convert CLAUDE.md symlink to @AGENTS.md import 2026-04-23 13:35:45 -07:00
docker-compose.yml Drop CliAdapter, WebDriverAdapter, demo_api, InMemoryHttpApi, rule assertions 2026-04-19 03:02:47 -07:00
Dockerfile fix: remove nonexistent main.py from mypy targets and Dockerfile CMD 2026-04-10 22:09:43 -07:00
pyproject.toml Tighten coverage to 99%, add README badges and local HTML coverage 2026-04-19 04:34:34 -07:00
README.md docs: trim README + FEATURES to fit catalog-doc-size cap 2026-05-15 21:34:10 -07:00
SCOPE.md rename Weapon -> Trial throughout 2026-04-23 10:57:48 -07:00
uv.lock Bump python-multipart in the uv group across 1 directory (#11) 2026-05-13 11:43:18 -07:00

⚔️🛡️🎯 Gauntlet

CI Python 3.13 mypy strict MCP server Claude Code plugin

Two-role adversarial MCP server that infers software correctness by observing how code behaves under sustained, targeted attack. Quality control for dark-factory environments where code is written by bots and verified by attack.

Run your service through the gauntlet. Point a host Claude Code agent at a running service, hand it the trial set, and the gauntlet is what the service survives. The host plays Attacker and Inspector; Gauntlet provides the deterministic tools (config loading, plan execution, risk-report assembly).

AI-written code can look correct while hiding behavioral failures. Traditional tests miss this because the same agent wrote code and tests. Gauntlet's Attacker context assumes the code is broken, and each Trial's blockers never load into that context, preserving a train/test split.

An Attacker uses a Trial aimed at a Target to generate Plans. Gauntlet's Drone executes those Plans as a User. An Inspector watches and surfaces Findings. Hidden Vitals are checked independently to produce a Clearance.

See docs/architecture.md for the model, docs/usage.md for the runbook, docs/development.md for dev setup.

Install

Gauntlet ships as a Claude Code plugin bundling the MCP server and the host skill:

claude plugin marketplace add coilysiren/gauntlet
claude plugin install gauntlet@coilysiren-gauntlet

Restart Claude Code so the skill, MCP server, and subagents register. Confirm with /mcp and "run gauntlet". No Anthropic creds needed; the host has auth.

Local dev: git clone ... && claude --plugin-dir path/to/gauntlet. Updates: enable auto-update under /plugin > Marketplaces, or /plugin marketplace update coilysiren-gauntlet + /reload-plugins.

The plugin delivers the MCP server, the gauntlet skill (orchestrator loop), gauntlet-author skill (spec to trial YAMLs), and gauntlet-attacker / -inspector / -holdout-evaluator subagents whose MCP allowlists enforce the train/test split.

MCP tools

  • list_trials - attacker-safe views, no blockers.
  • get_trial - full trial including blockers (orchestrator + holdout only).
  • execute_plan - run a Plan against the SUT.
  • start_run - init the per-run buffer, returns run_id.
  • record_iteration / read_iteration_records - per-trial iteration buffer (rejects blocker text).
  • record_holdout_result / read_holdout_results - holdout buffer.
  • assemble_run_report - per-trial RiskReport + Clearance; persists confirmed failures.
  • assemble_final_clearance - aggregate to one FinalClearance for the run.
  • replay_finding - re-execute a stored finding's ReplayBundle.
  • mutate_plans - deterministic plan variants (drop field, rotate users, etc.).
  • recurring_failures - findings showing up in 2+ of the last N runs.

The train/test split is enforced via per-role MCP allowlists (see agents/). The Attacker subagent literally cannot call get_trial.

Project config

your-project/
├── .gauntlet/
│   └── trials/
│       ├── task_ownership.yaml
│       └── ...

Trials define reusable attack strategies. blockers are externally observable truths about expected behavior, never loaded into the Attacker context:

title: Users cannot modify each other's tasks
description: >
  The task API must enforce resource ownership.
blockers:
  - A PATCH request by a non-owner is rejected with 403
  - The task body is unchanged after an unauthorized PATCH attempt
  - A GET by the owner after an unauthorized PATCH returns the original data

If the SUT requires auth, the orchestrator passes user_headers to execute_plan (a dict[str, dict[str, str]] mapping user names to headers). Users without an entry fall back to X-User: <name>.

See also

Cross-reference convention from coilysiren/agentic-os#59.