design.md described what tireless does to an issue but never what it is for, and in one place said the opposite of the intent: §1 assigned "identifying what should be worked on" to the operator, which is the thing discovery automates. A reader — human or agent — would have concluded the system is human-triggered only and never built the lane. Rewrite §1 around continuous multi-repo development. Add §2.5, the autonomy boundary, as a table of which transitions are automatic and which are human, with the alternatives considered and why they lose. Add §2.6 on anchoring discovery to a tracking issue rather than making Job.issue a sum type, and what that buys. Add stage 6 for the lane, renumbering scheduling to 7 and hardening to 8, with the reasoning for placing a cheap stage late. Add §10 on tireless working on tireless: that a merged PR restarts the runner that opened it and why that is survivable but not free, which areas must be routed to the stronger lane because they are constraint-bearing, and the four questions dogfooding is expected to answer. Two new invariants. Admission is inherited (§2.5), and every constraint must be reachable from a binary's startup path — the rule the previous commit's orphaned guards violated. AGENTS.md symlinks CLAUDE.md: both agents look for their own filename, the implementation prompts tell them to, and a symlink is the only version of this that cannot drift. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013TxK1CWPkFXqdcXMJ4hVe6
4.4 KiB
tireless — agent instructions
Read doc/plan/design.md before making changes. It carries
the constraints, the staged plan, and the reasoning behind decisions that look
arbitrary in isolation.
House conventions live in ~/git/architecture
(generic.md is the baseline). This project's deliberate deviations are listed
at the bottom of readme.md.
tireless works on tireless. This repo is its own first subject, so changes here are both the product and the test of it. If you are an agent working from a tireless-authored issue, design.md §10 says what that implies — in particular, that some areas of this repo are constraint-bearing and are routed deliberately.
Invariants — do not "clean these up"
These are terms-of-service and safety constraints expressed as code. Each has tests. If one seems redundant, read design.md §3 before touching it.
-
Never construct a request to a model provider. Agents are spawned as the vendor's own binary and authenticate themselves. Adding an HTTP client that talks to
api.anthropic.comwould break the arrangement that lets a subscription back this app. -
Never read or forward agent credentials.
has_credentials()stats~/.claude.jsonand nothing more. Do not parse it, copy it, or pass its contents anywhere. -
Never set
ANTHROPIC_API_KEY. It reaches Claude Code only if an operator put it in the unit environment. Its presence selects pay-as-you-go; its absence selects the subscription. That choice is the operator's. -
Never point the OpenCode lane at Anthropic.
assert_not_anthropicis checked at startup against both provider id and base URL. Local gateways that merely serve an Anthropic-compatible surface (helexa cortex) are fine and are tested for. -
Never let a lane run unbounded. Every agent invocation passes through
tireless_core::budget::Governor. Provider rate-limit signals are checked first and are authoritative. -
Postgres is the authority on claims, not forge labels. Labels are a best-effort mirror. Do not make a decision by reading a label that could be made by reading the database.
-
Never use
--system-promptfor Claude Code; append instead. Replacing Claude Code's default discards the tool-use scaffolding that makes it a coding agent.SYSTEM_PROMPT_FLAGis--append-system-promptfor this reason. -
The four prompts in
prompt/are one set — edit them together.plan.cc.mdemits the structureimplement.oc.mdconsumes andtireless_core::plan::validateenforces. Changing one alone breaks the handoff silently, as a bad pull request rather than an error. Bumpcontract-version:in all four plusSYSTEM_PROMPT_CONTRACT_VERSIONtogether;PromptSet::loadrefuses a mismatched set. -
A plan is validated, not trusted. Never enqueue implementation work from a plan that has not passed
plan::validate. TheAcceptance(runnable stopping condition) andOut of scope(boundary) requirements exist because a small model needs them; do not relax them because a plan looks fine to a human reader. -
Admission is inherited, never invented. tireless may apply the opt-in label only to an issue descended from one a human opted in.
may_opt_in(JobKind::Discover)isfalseand must stay false: it is the only thing standing between "proposes work" and "generates its own work indefinitely". See design.md §2.5. This is not a policy to relax once the system is trusted — the failure it prevents is unbounded, not merely wrong. -
Every constraint above is reachable from a binary's startup path. A guard that exists as a tested function nobody calls is not a guard. If you add one, wire it into
Config::validateortireless_agent::preflight::runso it cannot be bypassed by a caller that forgot.
Quality gate
Before considering a change complete:
cargo fmt --all
cargo clippy --all-targets --all-features -- -D warnings
cargo test --workspace
cd dashboard && npm run lint && npm run build
This exact block is what a plan targeting this repo should use as its runnable
Acceptance (design.md §10.3).
Commits
Conventional Commits (type(scope): subject), imperative, under ~70 chars.
Commit autonomously when the work is a coherent, complete unit; hold off when
follow-ups on the same topic are likely. See generic.md §12.