Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .cursor/rules/00-read-dot-rules.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
description: Mandatory - read .rules/ before opening or updating any PR in this repo
alwaysApply: true
---

# Read `.rules/` first

Before you change anything in this repository, read **all** of `.rules/`:

- `.rules/00-overview.md` — the reading duty and the doc surfaces
- `.rules/10-maintenance.md` — hygiene, no dead code, keep the repo true A→Z
- `.rules/20-pre-prod-local.md` — the exact local gates that must pass
- `.rules/30-pr.md` — PR shape and the required attestation
- `.rules/40-agents.md` — keeping `AGENTS.md` accurate in the same PR
- `.rules/50-versioning.md` — automatic versioning
- `.rules/60-naming.md` — frozen `base` / `BASE_*` / domain-tag spellings

`.rules/contracts/` holds frozen, gate-pinned specs. Read the ones your change
touches; never weaken a gate or rewrite incentive, scoring, or consensus
semantics to make a diff pass.

## Hard requirements for every PR

1. There is no `docs/` tree. `README.md` is the only human doc, `AGENTS.md` is
the agent/operator contract, `.rules/` is this contract. Update them in the
same PR as the code.
2. Run every command in `.rules/20-pre-prod-local.md` locally before calling
anything ready, mergeable, or shippable.
3. Bump the workspace version: `cargo run -p xtask -- version bump`. CI fails a
PR whose version matches `main`.
4. Fill the attestation checkboxes in `.github/PULL_REQUEST_TEMPLATE.md`. Do not
mark a PR ready with an unticked box, and never tick a box you did not earn.
5. Self-check before you hand the PR over:

```bash
cargo run -p xtask -- rules-check
cargo run -p xtask -- version verify-bump --base origin/main
```
40 changes: 35 additions & 5 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,41 @@

<!-- What does this PR change, and why? -->

## Test plan
## Rules attestation (required — `pr-gate` fails a ready PR without all four)

- [ ] `cargo test --workspace` (or note the subset and why)
- [ ] `cargo fmt --all -- --check`
- [ ] Clippy / deny / xtask gates if this PR touches crates they cover
Tick only what you actually did. See [`.rules/30-pr.md`](../.rules/30-pr.md).

- [ ] I read all of `.rules/` before opening this PR and before marking it ready
- [ ] `AGENTS.md`, `README.md` and `.rules/` are accurate for this change, or N/A with a reason below
- [ ] Local pre-prod gates in `.rules/20-pre-prod-local.md` all passed
- [ ] Version bumped per `.rules/50-versioning.md`

Version before → after: <!-- e.g. 0.2.0 → 0.2.1 -->

N/A reasons (if any): <!-- which box, and why it does not apply -->

## Local gates run

<!-- Paste or trim; these are the commands from .rules/20-pre-prod-local.md -->

```text
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
cargo deny check
cargo run -p xtask -- loc-cap
cargo run -p xtask -- consensus-lint
cargo run -p xtask -- spec-check
cargo run -p xtask -- design-check
cargo run -p xtask -- external-docs-check
cargo run -p xtask -- rules-check
cargo run -p xtask -- version check
```

## Challenge verification (if this PR touches a challenge)

<!-- Healthz is not proof. Which submission did you simulate: baseline, cheat,
admin winners, edges, leaf → seal → sealed: true? -->

## Risk

Expand All @@ -17,4 +47,4 @@
I did **not** rename `BASE_*` environment variables, deployed host paths
(`/opt/base`, `/run/base`, …), GHCR `baseintelligence/base` package names, or
`base-*-v1` cryptographic domain tags, unless this PR’s purpose is a coordinated
cutover documented in `docs/NAMING.md`.
cutover documented in [`.rules/60-naming.md`](../.rules/60-naming.md).
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ jobs:
- name: xtask external-docs-check
run: cargo run -p xtask -- external-docs-check

# Repo discipline: .rules/ complete, no docs/ tree, PR template matches
# the attestation pr-gate enforces, local gate list matches this file,
# and no markdown link in those surfaces dangles.
- name: xtask rules-check
run: cargo run -p xtask -- rules-check

- name: xtask version check
run: cargo run -p xtask -- version check

- name: clippy with dcap feature (release path)
run: cargo clippy -p validator-bin --features dcap --all-targets -- -D warnings

Expand Down
73 changes: 73 additions & 0 deletions .github/workflows/pr-gate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: pr-gate

# A PR is not reviewable until its author attests to having read `.rules/` and
# to having run the local pre-prod gates, and until the workspace version has
# moved. Both checks live in xtask so the template, the gate, and the rules
# text cannot drift apart (`.rules/30-pr.md`, `.rules/50-versioning.md`).
#
# `edited` and `ready_for_review` are in the trigger list on purpose: ticking a
# checkbox or flipping a draft must re-run the gate.

on:
pull_request:
branches: [main]
types:
- opened
- edited
- reopened
- synchronize
- ready_for_review
- converted_to_draft

permissions:
contents: read

env:
CARGO_TERM_COLOR: always

jobs:
pr-gate:
name: rules attestation · version bump
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.96.0"

- name: Cache cargo
uses: Swatinem/rust-cache@v2

# Via env, never inline interpolation: a PR body is untrusted input.
- name: Materialize PR body
env:
PR_BODY: ${{ github.event.pull_request.body }}
run: printf '%s' "$PR_BODY" > "$RUNNER_TEMP/pr-body.md"

- name: xtask pr-check (rules attestation)
env:
DRAFT_FLAG: ${{ github.event.pull_request.draft && '--draft' || '' }}
run: |
set -euo pipefail
# shellcheck disable=SC2086
cargo run -p xtask -- pr-check --body-file "$RUNNER_TEMP/pr-body.md" $DRAFT_FLAG

- name: Fetch base branch
env:
BASE_REF: ${{ github.event.pull_request.base.ref }}
run: |
set -euo pipefail
git fetch --no-tags origin "+refs/heads/$BASE_REF:refs/remotes/origin/$BASE_REF"

- name: xtask version verify-bump
env:
BASE_REF: ${{ github.event.pull_request.base.ref }}
run: |
set -euo pipefail
cargo run -p xtask -- version verify-bump --base "origin/$BASE_REF"
57 changes: 57 additions & 0 deletions .rules/00-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# 00 — You must read `.rules/` before you open a PR

**This directory is the contract for every coding agent and every human who
touches `CortexLM/cortex`.** Read all of it before you open a pull request, and
again before you mark one ready for review. A PR body that does not attest to
this is not reviewable and CI will fail it.

There is no `docs/` tree. The three doc surfaces are:

| Surface | Audience | Rule |
|---------|----------|------|
| [`README.md`](../README.md) | humans arriving at the repo | the only human-facing document; keep it true |
| [`AGENTS.md`](../AGENTS.md) | agents / operators | repo map, non-negotiables, verification duties |
| `.rules/` (this directory) | agents / reviewers | how to work, what must pass, how to version |

## Read order

| File | What it binds you to |
|------|----------------------|
| `00-overview.md` | this page: the reading duty itself |
| [`10-maintenance.md`](10-maintenance.md) | code and repo hygiene; keeping the repo true A→Z |
| [`20-pre-prod-local.md`](20-pre-prod-local.md) | the exact local gates that must pass before "ready" |
| [`30-pr.md`](30-pr.md) | PR shape, attestation, commit subjects |
| [`40-agents.md`](40-agents.md) | keeping `AGENTS.md` accurate in the same PR |
| [`50-versioning.md`](50-versioning.md) | automatic versioning (command + CI gate) |
| [`60-naming.md`](60-naming.md) | frozen `base` / `BASE_*` / domain-tag spellings |

[`contracts/`](contracts/README.md) holds the **frozen normative specs** —
bundle bytes, the design challenge freeze, prism, the threat model, and the
miner-facing docs. They are pinned by `xtask` gates. You do not need to read
all of them for every PR; you **must** read the ones your change touches, and
you must never weaken or rewrite their incentive, scoring, or consensus
semantics.

## The short version

1. Read this directory. Read the contracts you touch.
2. Make the change. Delete what you replaced; leave no dead code.
3. Update `AGENTS.md`, `README.md`, and `.rules/` in the **same** PR when
behaviour, layout, commands, routes, or deploy shape change.
4. Run every gate in [`20-pre-prod-local.md`](20-pre-prod-local.md) locally.
Green locally is the precondition for "ready", staging, and prod.
5. Bump the version per [`50-versioning.md`](50-versioning.md).
6. Fill the PR template's attestation honestly. Do not tick a box you did not
earn.

## Self-enforcement

```bash
cargo run -p xtask -- rules-check
```

That gate fails if `docs/` comes back, if a `.rules/` file goes missing, if
`AGENTS.md` / `README.md` stop pointing here, if the PR template drifts from
the attestation CI requires, if `20-pre-prod-local.md` stops listing a command
CI actually runs, or if any markdown link in these surfaces points at a file
that does not exist.
63 changes: 63 additions & 0 deletions .rules/10-maintenance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# 10 — Maintenance: keep the repo true A→Z

## Code hygiene

- `unsafe_code` is **forbidden**. No `unwrap` / `expect` outside tests
(`clippy::unwrap_used` / `expect_used` are `deny` in `Cargo.toml`).
- Clippy `pedantic` is on for the whole workspace and CI runs
`-D warnings`. Do not `#[allow]` your way past a lint without a comment
explaining the constraint.
- Per-crate cap: **1500 non-test LOC** (`cargo run -p xtask -- loc-cap`).
Split a crate rather than raising the cap.
- Consensus crates (see `xtask/consensus-crates.txt`) must not use `HashMap`,
`f32`/`f64`, `wrapping_*`, or bare `u128` arithmetic
(`cargo run -p xtask -- consensus-lint`).

## No dead code, no stale text

- Replace, do not accumulate. When you supersede a function, module, script,
compose overlay, or workflow, delete the old one in the same PR.
- Comments state constraints the code cannot. Do not narrate the diff and do
not leave "TODO(agent)" breadcrumbs in shipped code.
- A command written in `README.md`, `AGENTS.md`, `.rules/`, or `deploy/` must
be a command that works today. If you rename a flag or a script, grep for it
and fix every mention.
- Markdown links must resolve. `cargo run -p xtask -- rules-check` checks the
links in `README.md`, `AGENTS.md`, `SECURITY.md`, `deploy/*.md`, and all of
`.rules/`.

## Documentation surfaces (there are only three)

| Change you make | What you must also update |
|-----------------|---------------------------|
| New / removed crate, bin, or top-level directory | `AGENTS.md` monorepo map, `README.md` if a human would look for it |
| New / changed HTTP route, quota, round, or scoring rule | the relevant contract in [`contracts/`](contracts/README.md) **and** [`contracts/external-miner/`](contracts/external-miner/README.md) **and** the public miner repo |
| New / changed local or CI command | [`20-pre-prod-local.md`](20-pre-prod-local.md), `README.md`, and `.github/workflows/ci.yml` together |
| New / changed deploy topology, compose overlay, secret path | `deploy/README.md` + `deploy/AGENTS.md` |
| New rule for agents | a numbered file in `.rules/` (and `rules_check.rs` if it is machine-checkable) |

Historical `docs/evidence/` and `docs/spikes/` were removed with the rest of
the doc site. Code comments that still cite those paths are provenance notes
pointing at git history before that commit; treat them as history, never as
spec. Do not re-create the tree, and do not edit consensus-adjacent hashed
artifacts (`crates/db/migrations/*.sql`, `crates/prism-recipe/anchors/*.json`,
`crates/design-prompts/prompts/*.json`) just to tidy a comment.

## Frozen contracts

`contracts/BUNDLE_SPEC.md` and `contracts/DESIGN_CHALLENGE.md` are frozen and
pinned by `spec-check` / `design-check`. `contracts/THREAT_MODEL.md` D19 is
pinned word-for-word by `external-docs-check`.

- Never weaken a gate to make a diff pass. Change the product, then the spec,
then the pin — deliberately, as the point of the PR.
- Never rewrite incentive, scoring, or consensus semantics as a side effect of
a refactor, rename, or docs pass.
- Never rename `BASE_*` env vars, deployed paths, GHCR package paths, or
`base-*-v1` crypto domain tags. See [`60-naming.md`](60-naming.md).

## Before you call anything done

Run [`20-pre-prod-local.md`](20-pre-prod-local.md) in full, bump the version
per [`50-versioning.md`](50-versioning.md), and fill the attestation in
[`30-pr.md`](30-pr.md).
Loading
Loading