From b423321881a2270f30e9e221b487a949dd733ec6 Mon Sep 17 00:00:00 2001 From: echobt Date: Thu, 8 Oct 2026 03:36:47 +0000 Subject: [PATCH 1/7] docs(repo): remove retired products, add readme, validator script --- .greptile/config.json | 2 +- .greptile/rules.md | 2 +- AGENTS.md | 8 +- README.md | 205 ++- deploy/README.md | 6 + docs/AGENTS.md | 8 +- docs/DESIGN_CHALLENGE.md | 633 --------- docs/DESIGN_CHALLENGE_CHECKLIST.md | 102 -- docs/NAMING.md | 4 +- docs/PRISM.md | 1256 ----------------- docs/PRISM_RECIPE.md | 775 ---------- docs/assets/cortex-ecosystem.png | Bin 0 -> 880680 bytes docs/assets/cortex-ecosystem.svg | 4 + docs/assets/cortex-hero.png | Bin 0 -> 3563989 bytes docs/ecosystem.md | 79 ++ docs/external-miner/README.md | 5 +- docs/external-miner/relearn-agent.md | 11 - docs/external-miner/relearn-image.md | 11 - docs/external-miner/relearn-mm.md | 11 - docs/external-miner/relearn.md | 12 - docs/external-miner/validators.md | 19 + docs/index.md | 39 +- .../14-scaling-laws-and-diagnostics.md | 669 --------- .../research/15-incentives-and-landscape.md | 1010 ------------- docs/validator-quickstart.md | 109 ++ scripts/check_repo.py | 2 - scripts/run-validator.sh | 136 ++ tests/test_run_validator_script.py | 90 ++ 28 files changed, 647 insertions(+), 4561 deletions(-) delete mode 100644 docs/DESIGN_CHALLENGE.md delete mode 100644 docs/DESIGN_CHALLENGE_CHECKLIST.md delete mode 100644 docs/PRISM.md delete mode 100644 docs/PRISM_RECIPE.md create mode 100644 docs/assets/cortex-ecosystem.png create mode 100644 docs/assets/cortex-ecosystem.svg create mode 100644 docs/assets/cortex-hero.png create mode 100644 docs/ecosystem.md delete mode 100644 docs/external-miner/relearn-agent.md delete mode 100644 docs/external-miner/relearn-image.md delete mode 100644 docs/external-miner/relearn-mm.md delete mode 100644 docs/external-miner/relearn.md delete mode 100644 docs/spikes/prism-v3/research/14-scaling-laws-and-diagnostics.md delete mode 100644 docs/spikes/prism-v3/research/15-incentives-and-landscape.md create mode 100644 docs/validator-quickstart.md create mode 100755 scripts/run-validator.sh create mode 100644 tests/test_run_validator_script.py diff --git a/.greptile/config.json b/.greptile/config.json index b14f60c01..54fff6ed7 100644 --- a/.greptile/config.json +++ b/.greptile/config.json @@ -3,5 +3,5 @@ "autoReview": ["open", "push"], "statusCheck": true, "statusCommentsEnabled": true, - "ignorePatterns": "docs/BUNDLE_SPEC.md\ndocs/DESIGN_CHALLENGE.md\ndocs/PRISM.md\ndocs/external-miner/relearn*.md\ndocs/external-miner/proof-tbench.md" + "ignorePatterns": "docs/BUNDLE_SPEC.md\ndocs/external-miner/proof-tbench.md" } diff --git a/.greptile/rules.md b/.greptile/rules.md index 9f0ab318e..e87d2741a 100644 --- a/.greptile/rules.md +++ b/.greptile/rules.md @@ -4,7 +4,7 @@ Cortex is a Python Bittensor research subnet. The owner-signed trust root lists the live challenges: legacy bounty/proof 2,000/8,000 (algorithm 1), 3,000/7,000 (algorithm 2, version >=2) or 1..64 unique ids (algorithm 3, version >=3). The sum is always 10,000. Proof is built in; every other challenge is a Docker -container per docs/CHALLENGES.md. Design, Prism and Relearn are historical only. +container per docs/CHALLENGES.md. Design, Prism and Relearn are retired and removed. - Preserve frozen SCALE encodings, Merkle construction, aggregation and every `base-*-v1` signature preimage. Cross-language vectors must remain green. diff --git a/AGENTS.md b/AGENTS.md index e36ea2e78..059ee6451 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,9 +21,8 @@ bounty/proof 2,000/8,000 profile; algorithm 2 is bounty/proof 3,000/7,000 (document version >=2); algorithm 3 (document version >=3) admits any 1..64 unique ids and pays each challenge `share * min(sum(leaves), 10^12) / 10^12`. Activation is an offline owner ceremony. Design, Prism and Relearn are retired -products. Their frozen specifications and historical miner pointers remain for -compatibility; no active code, service, trust-root row or leaf may register -them. +products and their documentation has been removed. No active code, service, +trust-root row or leaf may register them. Start with [the architecture](docs/ARCHITECTURE.md), [Proof](docs/PROOF.md), [challenge containers](docs/CHALLENGES.md) and @@ -51,8 +50,7 @@ The working branch is `main`. Production releases are annotated `v*.*.*` tags. - Preserve `BASE_*` names, deployed compatibility paths and every `base-*-v1` signature domain. `CORTEX_*` is an accepted master alias only. -- Do not edit `docs/BUNDLE_SPEC.md`, `docs/DESIGN_CHALLENGE.md` or - `docs/PRISM.md`. Their exact SHA-256 values are checked by +- Do not edit `docs/BUNDLE_SPEC.md`. Its exact SHA-256 value is checked by `scripts/check_repo.py`. - Production image references are digest-only. Never invent a digest; an empty or unknown pin remains fail-closed. diff --git a/README.md b/README.md index a95491317..13e47f768 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,132 @@ -# Cortex +

Cortex

-Cortex research subnet on Bittensor: agentic Proof plus Docker challenge containers. +

+ Cortex: miners, challenge containers, a sealing gateway and validators on Bittensor subnet 100 +

-The master runs the gateway, Proof and every challenge container, then signs one -leaf per miner and seals each epoch. Validators only verify the sealed bundle -from the gateway API and submit the weights. +

+ An autonomous research network on Bittensor subnet 100. Miners compete in challenges, a master seals each epoch into one signed bundle, and validators verify that bundle and submit the weights on-chain. +

+ +

+ license Apache-2.0 + python 3.12 + status research + netuid 100 + Bittensor +

+ +

+ Documentation · + Website · + Validator guide · + Miner guides · + Architecture · + Challenges · + Threat model · + License +

+ +> [!WARNING] +> **Research software.** Cortex is experimental. Interfaces, wire formats and emission shares can change. Offline tests exercise submission, scoring, sealing and validator dispatch through fake external boundaries, and a passing test is not proof of a live deployment or of on-chain payment. Don't use it to manage funds you can't afford to lose. + +--- + +## What is Cortex + +Cortex is the subnet that runs research competitions. Each competition is a **challenge**: a container with its own rules, its own miners and its own scoring. Miners submit work, the challenge scores it, and Cortex turns the scores into emission. + +Two roles keep that honest: + +- The **master** runs the gateway, Proof and every challenge container. At the end of each epoch it signs one leaf per miner and seals the epoch into a bundle. +- A **validator** runs none of that. It downloads the sealed bundle, checks it against locally held trust files and the chain, and submits the weights. + +An owner-signed trust root sets each challenge's emission share. If a challenge earns less than its share, the shortfall burns to UID 0. It never moves to another challenge. + +Challenges today: + +| Challenge | What miners do | Repository | +| --- | --- | --- | +| `proof` | Research topics set by the operator, with recursive agents and VM evaluation | this repository | +| `bounty` | Report vulnerabilities in products | [CortexLM/bounty](https://github.com/CortexLM/bounty) | +| `opentype` | Exact-gold DiffusionGemma duels | [OpentypeAI/challenge](https://github.com/OpentypeAI/challenge) | +| `hypertrain` | Decentralized, verifiable LLM pretraining (research stage) | [CortexLM/hypertrain](https://github.com/CortexLM/hypertrain) | + +A further challenge, Sentinel, is planned and is not live. See [docs/ecosystem.md](docs/ecosystem.md). + +## The Cortex ecosystem + +

+ Cortex at the center, with miners and challenges on one side and the Cortex apps on the other +

+ +Cortex is the engine behind a family of products. Miners improve models and detectors through challenges, and the apps are where those improvements are meant to ship. + +| App | What the challenges give it | Status | +| --- | --- | --- | +| Cortex Chat | Models from Hypertrain, and research from Proof | Hypertrain is research stage; monetization is PLANNED | +| Cortex Decisions | Research and evaluation work from Proof | Depends on Proof output; monetization is PLANNED | +| Cortex Security Cloud | Vulnerability findings from Bounty today; Sentinel is PLANNED to improve it | Sentinel is PLANNED, not live | +| Cortex Code | Models from Hypertrain, and research from Proof | Hypertrain is research stage; monetization is PLANNED | +| Cortex Bot | Models from Hypertrain, and research from Proof | Hypertrain is research stage; monetization is PLANNED | + +Sentinel is planned as a miner-improved competitor to CodeRabbit and Greptile, positioned inside Cortex Security Cloud. None of it exists yet. Monetizing Hypertrain models in the apps is also a plan, not a shipped feature. Details are in [docs/ecosystem.md](docs/ecosystem.md). + +## How it works + +### 1. One epoch + +```mermaid +flowchart LR + M["Miner"] --> C["Challenge container"] --> L["Signed leaf"] --> G["Gateway seals epoch"] --> V["Validators verify"] --> N["Weights on chain"] +``` + +A miner submits work to a challenge. The challenge scores it and the master signs a leaf for that miner. When the epoch ends, the gateway seals all leaves into one bundle. Validators fetch the bundle from `GET https://chain.joinbase.ai/v1/weights/latest`, recompute the weights from the signed leaves and submit them to Bittensor. + +### 2. Who runs what + +```mermaid +flowchart LR + subgraph Master["Master operator machine"] + GW["Gateway"] + P["Proof"] + CH["Challenge containers"] + SUP["Challenge supervisor"] + end + subgraph Val["Any validator"] + VAL["cortex validator"] + end + GW -->|"sealed bundle"| VAL + VAL -->|"weights"| CHAIN["Bittensor"] +``` | Role | Runs | Command | | --- | --- | --- | -| validator master | gateway, Proof, [challenge containers](docs/CHALLENGES.md), auto-updater | `cortex master` + `cortex challenge-supervisor` | +| master | gateway, Proof, [challenge containers](docs/CHALLENGES.md), auto-updater | `cortex master` and `cortex challenge-supervisor` | | validator | verification and weight submission, nothing else | `cortex validator` | -Challenges live in their own repositories and are loaded automatically: -[CortexLM/bounty](https://github.com/CortexLM/bounty) (vulnerability reports) and -[OpentypeAI/challenge](https://github.com/OpentypeAI/challenge) (exact-gold -DiffusionGemma duels). The owner-signed trust root sets each challenge's emission -share. The shortfall of a challenge burns to UID 0 and never moves to another one. +Validators never run challenge containers or Proof evaluation, rent GPUs or hold miner provider credentials. + +## Run a validator in one command + +The master runs only on the master operator's machine. Everyone else runs a validator, and a script does the setup. + +```bash +sudo apt-get install libsodium23 +uv sync --locked --extra chain + +export WALLET_NAME=validator WALLET_HOTKEY=default +export GATEWAY_PUBLIC= + +scripts/run-validator.sh --verify-only # one verification, never submits +scripts/run-validator.sh # verify and submit every epoch +``` -Cortex is experimental research software. Offline tests exercise submission, scoring, -sealing and validator dispatch through fake external boundaries. A live model -smoke is distinct from live KVM execution or confirmed on-chain payment. +The script checks the gateway answer, reads the trust files from `config/` and starts `cortex validator`. It refuses master-only commands and master environments. Flags are `--verify-only`, `--once`, `--dry-run` and `--help`. Full walkthrough: [docs/validator-quickstart.md](docs/validator-quickstart.md). -## Installation +## Quickstart for developers -Linux, Python 3.12 or 3.13, `uv`, and libsodium 1.0.18 or newer are required. -The VM host additionally requires working `/dev/kvm`, Firecracker and jailer. +Linux, Python 3.12 or 3.13, `uv`, and libsodium 1.0.18 or newer are required. The VM host also needs working `/dev/kvm`, Firecracker and jailer. ```bash sudo apt-get install libsodium23 @@ -32,7 +134,7 @@ uv sync --locked --extra chain --group build uv run cortex --help ``` -## Usage +Other entry points: ```bash uv run cortex master --help @@ -43,22 +145,7 @@ uv run cortex miner --help uv run cortex topic-create --help ``` -Configure the master using private credential files and signed trust roots. -An operator gives Proof a research objective; its topic agent prepares an -experiment, measures a baseline and proposes rules and miner documentation. -A topic opens only after the control plane verifies the host's execution -receipts and signs the resulting document. No research task catalog is built in. - -- [Operator configuration](docs/reference/configuration.md) -- [Architecture and trust boundaries](docs/ARCHITECTURE.md) -- [Challenge container contract](docs/CHALLENGES.md) -- [Deployment](deploy/README.md) -- [Proof miner guide](docs/external-miner/proof.md) -- [Bounty miner guide](docs/external-miner/bounty.md) -- [Validator guide](docs/external-miner/validators.md) -- [Documentation index](docs/index.md) - -## Development +Checks: ```bash uv run ruff format --check src tests scripts @@ -69,16 +156,52 @@ uv run python scripts/check_deploy.py --check-examples uv build --no-build-isolation ``` -Tests cover signatures and Rust wire vectors, replay protection, challenge -container outages, auto-update rollback, artifact validation, topic setup, rejected submissions, VM lifecycle failures, -RLM recursion/compaction, reward allocation and sealed-weight submission. -CI runs offline and never rents a GPU or boots Firecracker. +Tests cover signatures and Rust wire vectors, replay protection, challenge container outages, auto-update rollback, artifact validation, topic setup, rejected submissions, VM lifecycle failures, RLM recursion and compaction, reward allocation and sealed-weight submission. CI runs offline and never rents a GPU or boots Firecracker. + +## Repository layout + +``` +src/ Python package: gateway, master, validator, miner CLI, Proof, VM host +config/ trust roots and measurements (owner-signed) +deploy/ master, validator and KVM host deployment +docs/ architecture, challenges, guides, specifications +scripts/ validator script, repository and deployment checks, smoke tests +tests/ offline test suite +``` + +## Components + +| Component | Who runs it | What it does | +| --- | --- | --- | +| Gateway | Master | Serves sealed weights and bundles at `/v1/weights/latest`, `/v1/weights/{epoch}` and `/v1/bundle/{epoch}` | +| Proof | Master | Opens operator-defined research topics, runs the topic agent and evaluates submissions in VMs | +| Challenge supervisor | Master | Loads challenge containers from the registry and applies verified updates | +| VM host | Dedicated KVM machine | Runs Firecracker guests for Proof evaluation and signs execution receipts | +| Validator | Anyone with a registered hotkey | Verifies the sealed bundle and submits weights | +| Miner CLI | Miners | Discovers topics and submits signed artifacts | + +## Security model and limitations + +What the design relies on: + +- The master signs one leaf per miner and seals each epoch. Validators recompute weights from the signed leaves and never trust display fields in the gateway response. +- Validators pin the gateway key and the owner key themselves. Trust files come from a local copy, not from the gateway. +- Challenge shares come from the owner-signed trust root. Unused share burns to UID 0. +- A Proof topic opens only after the control plane verifies the host's execution receipts and signs the document. + +What isn't done, honestly: + +- **The gateway is a central authority.** Validators verify what the master signed. They don't reproduce Proof or challenge scoring themselves. Peer cross-checking between validators is opt-in and off by default. +- **Live status is unproven.** Offline tests don't show live KVM execution, a live model run or confirmed on-chain payment. +- **Hypertrain is research.** Quality parity with centralized training is not claimed. +- **Sentinel is not built.** The same goes for monetization in the apps. +- **The validator CLI needs a consensus seed.** See the [validator guide](docs/external-miner/validators.md) for the current limit. + +Read the [threat model](docs/THREAT_MODEL.md) and [operator security](docs/OPERATOR_SECURITY.md) before running a master. ## Contributing -Keep research content out of source control. Add tests for observable behavior -at service boundaries, and update the matching miner documentation when an API -changes. Follow [the agent contract](AGENTS.md) and the PR review requirements. +Keep research content out of source control. Add tests for observable behavior at service boundaries, and update the matching miner documentation when an API changes. Follow [the agent contract](AGENTS.md) and the PR review requirements in [CONTRIBUTING.md](CONTRIBUTING.md). ## License diff --git a/deploy/README.md b/deploy/README.md index 53c94afa0..dc138fafe 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -192,6 +192,12 @@ reports `validator outcome=verified` for the same root/vector from historical chain state. The unsealed UID0 fallback is a readiness failure, not a weight to submit. +To run a validator without Compose, use `scripts/run-validator.sh` from a +repository clone. It needs `WALLET_NAME`, `WALLET_HOTKEY` and an independently +pinned `GATEWAY_PUBLIC`, takes trust files from `config/`, and refuses to run +master-only commands; see the +[quick start](../docs/external-miner/validators.md#quick-start-one-script). + ## Proof VM host The host requires Linux, `/dev/kvm`, Firecracker, jailer, nftables/network diff --git a/docs/AGENTS.md b/docs/AGENTS.md index 0b15ec915..92a52120a 100644 --- a/docs/AGENTS.md +++ b/docs/AGENTS.md @@ -23,10 +23,10 @@ of copying the same contract into a second runbook. ## Frozen and historical material -`BUNDLE_SPEC.md`, `DESIGN_CHALLENGE.md` and `PRISM.md` are byte-pinned by -`scripts/check_repo.py`. Do not edit them. Design, Prism and Relearn are not live -products. The Relearn files under `external-miner/` and `proof-tbench.md` remain -short historical pointers so old URLs do not disappear. +`BUNDLE_SPEC.md` is byte-pinned by `scripts/check_repo.py`. Do not edit it. +Design, Prism and Relearn are retired products and their documentation has been +removed. `external-miner/proof-tbench.md` remains a short historical pointer so +an old URL does not disappear. ## API changes diff --git a/docs/DESIGN_CHALLENGE.md b/docs/DESIGN_CHALLENGE.md deleted file mode 100644 index b945b37c1..000000000 --- a/docs/DESIGN_CHALLENGE.md +++ /dev/null @@ -1,633 +0,0 @@ -# Design Challenge (Base) - -**Status: FROZEN** for `challenge_id = "design"`, `challenge_scoring_version` **u16 = 2**. - -Normative contract for the design challenge on Base. Byte-level epoch bundle -rules live in [`BUNDLE_SPEC.md`](./BUNDLE_SPEC.md) (`protocol_version = 1`). -Pin map for CI: [`DESIGN_CHALLENGE_CHECKLIST.md`](./DESIGN_CHALLENGE_CHECKLIST.md). -Gate: `cargo run -p xtask -- design-check`. - -This challenge **replaces** agent-v1 (Phala CVM) and hypertraining. Miners submit -Python harness source over HTTP — no miner-provided Docker image, no Phala/CVM path. - ---- - -## 1. What runs where (topology) - -```text -Miner --POST /v1/harness--> design-challenge (:8093) - | - round clock (10/day UTC) + quota - | - +-------------v--------------+ - | design-sandbox (two phase) | - | install → run | - | image: design-runtime | - | net: design-sandbox-egress| - +------+---------------------+ - | HTTP only - +------v---------------------+ - | design-egress-proxy | - | open egress, internal | - | blocklist; OpenRouter key | - +----------------------------+ - | - /out/pages/*.html - | - design-sanitize → store (postgres) - | - +----------------+----------------+ - | | - viewer (index.png agentic review → admin winners (1|2) - screenshots only; | - HTML never served) exact-E leaves → gateway /v1/weights/raw -``` - -| Process | Host | Holds `design_sk`? | Holds OpenRouter key? | -|---------|------|--------------------|------------------------| -| `design-challenge` | **master only** | **yes** (file mount) | **yes** (agentic review; optional Sim) | -| `design-egress-proxy` | **master only** | no | **yes** (sandbox LLM path) | -| sandbox container | master (ephemeral) | **never** | **never** | -| gateway | master | no | no | -| validator | validators | no | no — **no challenge exec**; fetch sealed weights only | - -Evaluation (sandbox, sanitize, `AgenticReview`, admin winners, leaf emit) is -**master-only**. Validators never run design-challenge / egress / socket-proxy. - -Sandbox containers attach only to the internal Docker network -`design-sandbox-egress`. The sole reachable peer is `design-egress-proxy`. - ---- - -## 2. Identifiers and versions - -| Field | Value | -|-------|-------| -| `challenge_id` | `design` | -| `challenge_scoring_version` | **u16 = 3** | -| `SCORE_MAX` | `1_000_000` | -| Listen port | `8093` (local overlay `28093`) | -| Gateway proxy prefix | `/challenge/design/*` | -| Bundle `protocol_version` | `1` ([`BUNDLE_SPEC.md`](./BUNDLE_SPEC.md)) | -| `emission_share_bps` | **0** (prism 100%; sum `10000`) | -| Policy | `all_metagraph_hotkeys` | -| Round length | `ROUND_SECS = 8_640` (10 rounds / UTC day) | -| Agent run timeout | `AGENT_RUN_TIMEOUT_SECS = 1_800` (30 min; distinct from round length) | -| Scoring window | `SCORING_WINDOW_ROUNDS = 10` (rolling round-win points share) | -| `round_id` | `floor(unix_secs / 8640)` | -| Domain `round_id` | `base-design-round-id-v1` | -| Domain submission | `base-design-submission-v1` | -| Domain pair | `base-design-pair-id-v1` | -| Domain run | `base-design-run-id-v1` | -| Raw-weight domain | `base-rawweight-v1` (via bundle) | - -Staging knobs (defaults above are the prod pins and never change implicitly): -`DESIGN_ROUND_SECS`, `DESIGN_AGENT_RUN_TIMEOUT_SECS`, `DESIGN_PROMPTS_PER_ROUND` -override round length / run timeout / prompts per round (staging uses ~15-minute -rounds; `env-staging.yml`). - -Emission posture: `emission_share_bps = 0` for design and `10000` for prism -(100% prism; sum `10000`). Rebalance via the owner ceremony in -[`runbooks/design-enable-and-emission.md`](./runbooks/design-enable-and-emission.md) -and [`config/challenges.toml`](../config/challenges.toml). - ---- - -## 3. Miner harness contract - -Miners submit **source**, not images. Preferred transport is **ZIP** -(`Content-Type: application/zip` + `X-Miner-Hotkey`, or JSON `zip_base64`). -JSON with inline `agent_py` / `pyproject_toml` remains accepted for local/CI. - -Optional `env_vars` (JSON map or `X-Env-Json` on ZIP) are injected into the -sandbox **run** phase only. Keys must match `[A-Z][A-Z0-9_]*`; operator / -proxy prefixes (`DESIGN_`, `HTTP_`, `PYTHON…`, …) are rejected. Values are -**never logged**. - -### Bundle - -| File | Rule | -|------|------| -| `agent.py` | Must define `def run(task, llm, out) -> None` | -| `pyproject.toml` | Required; deps installed in sandbox install phase | -| Extra files | ≤ 16 files, ≤ 256 KiB each, total bundle ≤ 1 MiB | - -`harness_id = sha256(base-design-submission-v1 || hotkey || agent || pyproject || extras || env)`. -`POST /v1/harness` is idempotent on that digest. - -### Submission gating (1-max) + auto round enqueue - -- The miner hotkey must be **in the metagraph** (bulk cached snapshot, **15m** - TTL fail-closed; no per-UID RPC on the request path). Unknown hotkey → - `403 hotkey_not_in_metagraph`; snapshot missing/stale → - `503 metagraph_unavailable`. -- **One accepted submission per `(challenge, hotkey)`** (`submission_gating` - table). While the row is `registered` / `blocked` / `rejected`, a *different* - harness from the same hotkey → `409 submission_gated`. The identical re-POST - stays idempotent (`200 already-queued`). -- **Auto round enqueue**: `POST /v1/harness` schedules the harness into - `round_id(now) + 1` ([`RunOrigin::Manual`]). On every subsequent open round - the orchestrator auto-enqueues the **latest active harness per hotkey** into - that round with the round's shared prompt ([`RunOrigin::Scheduled`]) — - idempotent if already queued. Eliminated harnesses - (`eliminated_until_round > rid`) are skipped. Infra auto-retry on the *same* - run id (up to 3) is not a new schedule. Ops may still - `POST /v1/admin/rounds/current/requeue` (same enqueue path). -- **Auto-retry**: infra-class failures (`install`, `ast_infra`, `llm_infra`) - requeue automatically up to **3** times; `cheat` / `rejected` / admin reject / - unscored timeout are terminal. Budget exhaustion → `failed` + gating - `blocked`. Manual `POST /v1/runs/{id}/retry` is unchanged. -- A metagraph **watcher** reopens eligibility (`open`) when the hotkey leaves - the metagraph (uid deregistered or hotkey replaced), so the **same hotkey** - may resubmit under a **new uid**. The hotkey is never permanently burned. -- Miner env (`env_vars`) is **locked at submission** into the stored bundle; - changing it requires a new digest (and a free gating slot). - -### Required output (`/out/pages/`) - -- `index.html` -- `pricing.html` -- `components.html` -- `manifest.json` (present in operator harness layout; pages gated by sanitize) - -### Injected SDK (`base_design`, not miner-modifiable) - -- `task.prompt`, `task.round_id`, `task.pages_required`, `task.budget` -- `llm.chat(messages, model)` → HTTP to egress proxy (no key in harness) -- `out.write_page(name, html)`, `out.write_asset(name, bytes)` (size-capped) - -Operator entrypoint `design_harness.py` loads miner `agent.py` after install. - ---- - -## 4. Sandbox hardening - -Two phases on pinned `design-runtime`: - -1. **install** — `pip install --no-cache-dir -e /work` into a work-root venv, - resolving `pyproject.toml` deps from PyPI via the egress proxy (open - Internet; internal-target blocklist). Miner env is **not** injected in this - phase. Timeout `DESIGN_INSTALL_TIMEOUT_SECS` (default 300s); non-zero exit - or timeout → error class `install` (auto-retry ≤ 3, then `failed` with - `NoScore(ChallengeInternal)`). -2. **run** — same work root; open egress via the proxy for external APIs / - MCP servers (same blocklist); `llm.chat` rides the budgeted `/v1/chat` - path; miner env injected; loads `design_harness.py`. - -The egress proxy blocklist refuses cloud metadata (`169.254.169.254`), -loopback, RFC1918/VPC (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`), -CGNAT (`100.64.0.0/10`), and control-plane service names, enforced **after -DNS resolution** (DNS-rebinding safe). - -`docker-engine` `RunSpec` hardening for design (prefix `base-design-`): - -- `ReadonlyRootfs: true` + bounded tmpfs `/tmp` -- `CapDrop: ["ALL"]` -- `SecurityOpt: ["no-new-privileges:true"]` -- `PidsLimit`, `Memory`, `MemorySwap`, `NanoCpus` set -- `NetworkMode: design-sandbox-egress` (pre-created; socket-proxy denies Networks API) -- `User: 65532:65532` -- Wall-clock timeout → stop/rm - -Host `SimSandbox` is fail-closed outside explicit non-prod/CI opt-in -(`BASE_ALLOW_HOST_SIM=1` + non-prod, typically via `env-local.yml` or e2e). -Staging/prod paths are Docker-only via `socket-proxy` — no silent fallback. - -Floating tags (`:latest`) are **forbidden** for `design-runtime` / challenge images in prod pins — digest-only. - ---- - -## 5. Sanitize rules - -Ingestion via `design-sanitize` (ammonia + CSS filter). **Produced HTML is -never served** — sanitized pages are orchestrator input only (screenshot -capture, anti-cheat review); the public viewer serves PNG screenshots -only (§6). - -### Stripped / rejected - -- Tags: `script`, `iframe`, `object`, `embed`, `applet`, `base`, `form`, `meta[http-equiv=refresh]`, `link[rel=import]`, scriptable SVG -- All `on*` event attributes -- URL schemes: reject `javascript:`, `vbscript:`, `data:text/html`; allow `http`, `https`, `mailto`, `data:image/*` -- CSS: soft-strip `@import …;` rules (remainder of the `