AGENTS.md · git:20260930.33f417a · 2026-09-30 · sha256 4e6ee0b6fdd2377d
AGENTS.md git:20260930.33f417aA
Immutable. This exact content never changes and is served at /api/v1/blob/4e6ee0b6fdd2377d.
# AGENTS.md
Guidance for work in this repository.
## Start here
- [Current architecture](docs/architecture.md): implemented behavior and source map.
- [V1 contract](specs/2026-09-05-ironlint-v1-design.md): release requirements.
- [Active plan](plans/2026-09-29-durability-simplification.md): resume block,
current packet, dependencies, and evidence.
- [V1 release baseline](plans/2026-09-05-ironlint-v1-implementation.md): completed
release packets and verification evidence. Read only the relevant packet and
contract sections before tracing code; do not load the whole documentation tree.
Keep these documents current when behavior or scope changes. The active follow-up
plan covers separately authorized engineering work; the completed v1 plan retains
its release evidence. Do not duplicate execution plans, create a historical
planning archive, or revive removed roadmap items.
## Current implementation and target
IronLint is a Rust command-check evaluator for AI coding workflows. `version: 1`
policies use `run`, optional `files`, and `on: [accept]` or `[change, accept]`.
The versioned core/CLI, schema-7 output, bounded execution, local consent, and
read-only inspection are implemented. Unversioned configuration and the former
execution paths have been removed. `ironlint schema` and `init` both expose the
v1 format. Core release verification uses local Docker feature E2E tests.
Harness compatibility and external enforcement qualification belong to
adapter/integration owners, not the core release gate.
Pi is the only adapter available for new installation. Claude Code, Codex, and
OpenCode registrations remain recognizable only so `init --uninstall` can
safely remove owned artifacts while preserving user edits. The optional Git
pre-commit hook is installed only with `--git-hook` and runs complete v1
acceptance.
## V1 contracts
- `accept` runs every check once in check-ID order. `change` filters opted-in
checks by known paths; unknown paths run all change checks. Bare globs such as
`*.rs` match at any depth. Every check must include acceptance.
- Commands run via `sh -c` in the supplied root, with stdin closed. Only
`IRONLINT_ROOT`, `IRONLINT_EVENT`, and `IRONLINT_BIN` are supplied as reserved
variables. Retained environment, output caps, and deadlines are specified in
the v1 contract. Paths are env values, never spliced into `run`.
- CLI exits: 0 successful evaluation (including empty change selection), 1
config/input failure, 2 violation, 3 execution/incomplete error, 4 untrusted
policy. Schema 7 distinguishes `pass`, `violation`, `error`, and `not_run`.
An enforcing consumer requires a complete acceptance pass, not exit 0 alone.
- Trust is CLI execution consent, keyed by canonical config path and policy/script
hash. Keep the core evaluator independent of consent. Read-only inspection never
requires trust. Consent is not isolation or authority over repository acceptance.
- An integration claiming enforced acceptance must bind approved policy/evaluator and a complete
result to the exact candidate, with publication authority inaccessible to checks.
- Binary name: `ironlint`. Commit `Cargo.lock`; build and test with `--locked`.
## Validation and working rules
- Bug fixes start with a failing regression, then the smallest shared root-cause
fix and focused test. Trace direct callers before editing or deleting code.
- Request a separate agent review after an integrated implementation batch.
Review concrete regressions; do not repeat broad reviews without new evidence.
- Rust source must meet at least 80% region coverage per file and cognitive
complexity at most 15. Refactor rather than suppress the lints.
- Run one Cargo build/test/coverage operation per target directory at a time.
- Installation/adapter tests use a temporary home/config directory. Never exercise
them against the developer's live trust store or hook installation.
- Remove transient build/scratch artifacts produced by the task; keep the normal
iterative `target/`. Mutation testing is optional investigation, not a CI gate.
- Keep provenance-stamped Pi adapter fixtures intact while its suite is active.
Run `adapter-drift-audit` when the Pi harness contract changes. Live harness
verification is adapter-owned; the fixture suite tests only the stable CLI
contract.
```sh
cargo test --locked
cargo clippy --locked --all-targets -- -D warnings
cargo fmt --all --check
bash scripts/ci-coverage.sh
bash scripts/ci-adapters.sh
bash tests/e2e/features/run.sh
```
The adapter script needs isolated `XDG_CONFIG_HOME` when run locally. Core release
validation requires the local feature suite, not a live harness or hosted repository.
Fixture tests cannot prove repository enforcement. Publishing requires task authorization.
<!-- graft:start -->
## Graft — repo context graph
This repo is indexed in the ignored, regenerable `graft/` cache: small linked
markdown nodes that explain each system and carry exact file:line spans.
Refresh it after code changes; source and the current contract take precedence
over stale generated concept summaries.
For ANY task here — understanding how something works, finding where code lives,
or scoping a change — get context from the graph before grepping or opening
source files. Re-ask freely (it's cheap) and reuse literal identifiers you
already have (symbol, error string, file name) as the query. New to this repo?
Run `graft map` first — a token-budgeted orientation (dir clusters, hubs,
hotspots), no LLM, no key.
- Run `graft ask "<your question>" --source` → ranked nodes with the relevant
code spans inlined (each hit's ≤8-line crux by default; `--full` for whole
definitions when the crux isn't enough). Match the tool to the task shape:
for understanding or editing, the top node IS the answer — cite its
`covers:` file:line spans and edit straight from `--source`. For
exhaustive tasks ("every occurrence / every caller of this pattern"), ranked
results are top-N, not complete — run `graft grep "<literal>"` instead
(exhaustive over indexed files, grouped by enclosing symbol), falling back
to raw `grep -rn` only for unindexed files.
- `graft skeleton <file>` → every definition's signature + span, ~10× cheaper
than reading the file; use it to skim an API surface.
- `graft callers <symbol>` gives precomputed, exact edges — who calls this.
Add `--direction out` for what it calls, or `--depth N` to walk
transitively for the full blast radius. For structural questions, skip
ranking and use this directly.
- Or browse: `graft/INDEX.md` lists every node; follow the links.
- Monorepos and folders of multiple repos rank fairly across sub-projects —
hits carry `[scope/]` labels naming which one they're from. Narrow with
`graft ask "<task>" --in <scope>/` once you know where you're working.
If a returned span is truncated ("+N more lines"), open the file at that exact
range before finalizing. Only open source files when a node genuinely lacks a
needed detail, and then at the exact file:line the node points to — never
re-read whole files.
After big code changes, refresh the graph with `graft build` (deterministic,
no API key, $0).
<!-- graft:end -->