Skip to content
Verified: Accurate against commit b64377d40 View Commit

AGENTS.md

Agents Policy (Cross-Tool, Session-Critical)

Section titled “Agents Policy (Cross-Tool, Session-Critical)”

This file is the always-loaded policy surface for contributors and coding agents. Keep it short, stable, and implementation-oriented.

  • Use this file for non-negotiable project policy that should apply in every session.
  • Do not turn this file into a full repository table of contents.
  • Put detailed rationale and long reference maps in contributor docs, then link from here.

Primary navigation:

Research and Documentation Storage (IDE Agent Directive)

Section titled “Research and Documentation Storage (IDE Agent Directive)”

When working under the Vox repository, ALL research findings, architecture documents, and knowledge artifacts MUST be written to docs/src/architecture/ (or the appropriate docs/src/ subdirectory) in this repository — not to any IDE-private knowledge base (e.g., Antigravity’s ~/.gemini/antigravity/knowledge/). The Vox docs/ tree is the single source of truth for all project knowledge.

  • Research docs follow the naming pattern: *-research-2026.md, *-findings-2026.md
  • Architecture SSoT docs: *-ssot.md or descriptive names in docs/src/architecture/
  • After writing a page, set valid YAML frontmatter (title, description, category, status). Starlight docs-astro/src/utils/sidebar.mjs lists it automatically. Do not create or edit docs/src/architecture/research-index.md (retired; snapshot under docs/src/archive/).
  • Do not store Vox-specific research in IDE knowledge bases that are only accessible to one tool

Auto-generated documentation files (do not edit manually)

Section titled “Auto-generated documentation files (do not edit manually)”

Astro-generated (not committed — do not create or edit these files):

  • docs/src/SUMMARY.md — Sidebar is built from frontmatter by docs-astro/src/utils/sidebar.mjs at Astro build time. To change the sidebar, edit the target doc’s title, category, or sort_order frontmatter. This file is .gitignored.
  • docs/src/feed.xml — RSS feed generated by the @astrojs/rss Astro endpoint at build time. This file is .gitignored.

Committed and kept in sync by pre-commit hooks (lefthook.yml):

  • docs/src/reference/cli-command-surface.generated.md, docs/src/reference/mens-train-defaults.generated.md, docs/src/reference/env-vars.generated.md, docs/src/reference/config-keys.generated.md, docs/src/reference/mcp-tools.generated.md — regenerate with cargo run -p vox-cli -- ci command-sync.
  • docs/src/reference/plugin-catalog.generated.md, docs/src/reference/distribution-bundles.generated.md — regenerate with cargo run -p vox-cli -- ci generate-plugin-catalog-docs.
  • .cursorignore, .aiignore, .aiexclude — derived from .voxignore; regenerate with vox ci sync-ignore-files.

First-time setup (vox run scripts/setup.vox) installs the git hooks and the binaries they call (vox, toestub, vox-drift-check). Hooks never build and never regenerate these files; PR CI’s ssot-autoregen job regenerates them, and vox ci ssot-drift reports drift.

Manually-maintained files that are safe to edit:

  • docs/src/adr/index.md, docs/src/adr/README.md — hand-rolled ADR tables, not generated.
  • Individual ADR / architecture / how-to / tutorial / reference markdown files — these are the sources the generators read from.

Reading diffs cheaply (agents). Tracked generated artifacts are marked linguist-generated/-diff in .gitattributes, so GitHub and local git show/git diff already collapse them to “Binary files differ” — you never pay to read regenerated text. The set: docs/src/**/*.generated.md, contracts/reports/gui-surface-{coverage,registry}.v1.json, crates/vox-cli/tests/fixtures/command_catalog_paths_baseline.txt, and Cargo.lock (collapsed on GitHub, kept locally diffable for supply-chain review). The Astro/index files (SUMMARY.md, feed.xml, architecture-index.md) are .gitignored, so they are not in diffs at all. If a range still surfaces generated noise, exclude it explicitly rather than reading it, e.g. git diff <base>..<head> -- . ':(exclude)Cargo.lock' ':(exclude)contracts/reports/*.v1.json'. To understand a generated change, read the generator’s input, never the regenerated output line-by-line.

Do not hand-regenerate SSOT after a merge. Mechanical SSOT drift on a pull request is regenerated and committed automatically by the ssot-autoregen job in .github/workflows/ci.yml (same-repo PRs; it re-runs every generator ssot-drift verifies — run_ssot_drift in crates/vox-cli/src/commands/ci/run_body_helpers/docs.rs — with --write). So if you see a generated artifact drift, fix it at the source (the generator or its input); do not open a fix(#N): regenerate … after merge commit — that pattern cost 60+ commits historically. (Activation requires the repo secret SSOT_AUTOREGEN_TOKEN; without it the bot still commits but the gate must be nudged manually.)

Every Markdown file you create or substantially author under docs/src/ (excluding the auto-generated files above and docs/src/archive/) MUST begin with a YAML frontmatter block. This is not optional: the vox-doc-pipeline lint runs in the pre-push hook and on CI, and a missing or malformed block blocks the merge.

Minimum required keys (full template and the canonical category / status vocabularies live in the SSOT: docs/src/contributors/documentation-governance.md §Frontmatter):

---
title: "Page title"
description: "One specific sentence about what this page covers."
category: "Architecture SSOTs" # one of the canonical category values in the governance doc
topic: "doc-governance" # taxonomy prefLabel (contracts/documentation/kb-taxonomy.v1.yaml)
domain: "documentation" # taxonomy prefLabel
authorship: "llm-assisted" # human | llm-assisted | llm-generated (+ authorship_model for LLM)
---

Rules for any agent writing docs:

  • Write the frontmatter as part of creating the file — never author the body first and leave the block to a later pass. A new .md without frontmatter is an incomplete file.
  • New docs also need topic / domain prefLabels, authorship (plus authorship_model when LLM-written) and a 40-120 word <!-- kb:summary --> block directly under the H1 (SSOT: the governance section “KB facets (taxonomy contract)”). Never write authorship, origin or human_attested_by you cannot vouch for, and never set human_attested_by as an agent.
  • The facet backlog (contracts/documentation/kb-facet-backlog.v1.yaml) only shrinks. Adding backlog entries is USER-AUTHORIZED-ONLY (same discipline as crate-edges exceptions): never re-seed it to admit a doc you wrote, and do not backfill facets into existing docs in bulk.
  • Do not hand-add last_updated — the pipeline derives it from Git history.
  • Pick the category from the governance vocabulary; add status when the shipped-vs-aspirational distinction matters to readers.
  • Verify before pushing with the scoped lint: cargo run -p vox-doc-pipeline -- --lint-only --paths <your-file>.md (or just let the fast pre-push hook’s scoped doc-lint catch it).
  • Fenced vox code blocks in docs are compiled as doctests. Make them compile, or — only when the snippet is a genuine excerpt that depends on out-of-file symbols (inlining them would create a stub or a split-brain copy) — mark the block with a leading // vox:skip and a one-line reason.

.voxignore is the single source of truth for what files and directories should be excluded from AI context.

  • Edit .voxignore; derive .cursorignore, .aiignore, .aiexclude via vox ci sync-ignore-files
  • Do not edit derived ignore files directly — they are regenerated and tracked for drift
  • GitHub Copilot exclusions must be configured separately in GitHub Settings → Copilot → Content exclusion; see docs/agents/copilot-exclusions.md
  • Background research is in docs/src/archive/research-2026-q1/ (do not ingest — see §Archival Protocol).

Use Clavis for API keys, tokens, and credentials. Do not introduce new direct secret reads from environment variables in consumers.

  • Define and maintain secret metadata in crates/vox-secrets/src/spec/ (the SecretId enum lives in spec/ids.rs; entries live under spec/registry/).
  • Resolve secrets with vox_secrets::resolve_secret(...).
  • Keep resolver/source behavior in crates/vox-secrets/src/resolver.rs and crates/vox-secrets/src/sources/*.
  • After secret-surface changes, run vox ci secret-env-guard and vox ci secrets-parity.

Naming policy:

  • Use VOX_* for Vox-owned platform boundaries.
  • Keep provider-native keys as canonical when upstream compatibility matters.
  • Mark migration aliases as deprecated and expose them through doctor warnings.

API key lifecycle checklist:

  1. Add SecretId and SecretSpec entries in crates/vox-secrets/src/spec/ (spec/ids.rs for the enum, spec/registry/ for entries).
  2. Migrate callsites to vox_secrets::resolve_secret(...).
  3. Update vox secrets doctor workflow/profile expectations when requirements change.
  4. Keep docs in sync at docs/src/reference/secrets-ssot.md.

Two different concerns, two different controls. Do not conflate them — the previous single rule did, which is why it was unenforceable and silently violated.

1. Application crypto — must go through vox-crypto

Section titled “1. Application crypto — must go through vox-crypto”

Any cryptographic operation vox performs on vox’s own data — hashing, signing, verifying, sealing, symmetric encryption, key derivation, key storage — MUST call vox-crypto. Do not import chacha20poly1305, ed25519-dalek, x25519-dalek, blake3, sha2, or sha3 directly outside crates/vox-crypto/, and do not hand-roll a signature envelope, a nonce scheme, or a KDF anywhere else.

Standard primitives: ChaCha20-Poly1305 (AEAD), BLAKE3 (hashing), SHA3-256 (compliance), ed25519 (signing), X25519 (key agreement).

Permanently banned in application code: MD5, SHA-1, AEGIS, DES/3DES, RC4, ECB, and any construction requiring the caller to manage nonce uniqueness by hand.

Enforced by vox-code-audit detector vox/crypto/banned-crate-import.

2. Transport crypto — allowlisted, pinned, and ledgered

Section titled “2. Transport crypto — allowlisted, pinned, and ledgered”

TLS and QUIC crypto lives inside vetted third-party libraries. Vox does not reimplement it and MUST NOT route it through vox-crypto.

Providers in the resolved graph are recorded in contracts/crypto/transport-providers.v1.json with attribution and a reviewer. Adding, removing, or version-bumping a provider requires a ledger entry in the same PR. Ledger entries are USER-AUTHORIZED-ONLY; never add one yourself.

The workspace currently ships two providers, deliberately. ring is our explicit pin and reqwest 0.12’s choice; aws-lc-rs arrives with reqwest 0.13 via chromiumoxide and gix→jj-lib→vox-vcs, and cannot be steered from our manifests because jj-lib exposes no TLS feature. Removing it means dropping the browser plugin or VCS. The collapse path is a workspace-wide reqwest pin bump, not the hf-hub upgrade. hf-hub is on 1.0/reqwest 0.13 as of 2026-09-04 and both providers remain, because the root manifest pins reqwest 0.12 for 28 first-party crates. See plan Task 0.4 for the measured correction.

Cargo feature unification is per-package, so one crate enabling rustls/aws-lc-rs reintroduces it workspace-wide. The invariant is therefore checked against the resolved lockfile, not against manifest text — a regex cannot see a provider selected by a feature on a shared dependency.

A clean clone must build with only the pinned Rust toolchain, the platform C compiler, and Node+pnpm. No dependency may add cmake, nasm, Go, perl, or libclang. This is a property of the build, verified by a CI image lacking those tools — not a crate blacklist. (The old rule banned crates that “drag in cmake or nasm”; aws-lc-sys ≥ 0.41 provably does not on Windows, so the ban described a hazard that no longer existed while missing the real one.)

See: docs/src/architecture/cryptography-ssot-2026.md

The unified vox audit umbrella hosts:

  • vox audit code — vox-code-audit source-policy detectors
  • vox audit arch — vox-arch-check
  • vox audit retirement — vox ci retirement-audit (planned per CR-L6)
  • vox audit effort — AI-judged commit history audit (vox-effort-audit)
  • vox audit effort-route — routes audit findings to verified enforcement-artifact proposals (vox-effort-route)

New audit subcommands MUST emit findings JSONL with schema_version and a per-finding discriminator so downstream tooling can multiplex.

Model-Agnostic LLM Boundary (Required, SSOT)

Section titled “Model-Agnostic LLM Boundary (Required, SSOT)”

All LLM calls in this workspace MUST go through the model-agnostic facade at vox_actor_runtime::llm (infer_with_retry, llm_chat, llm_stream, llm_embed). Do NOT hardcode a vendor hostname (api.anthropic.com, api.openai.com, generativelanguage.googleapis.com, etc.) and do NOT instantiate a vendor SDK directly in workspace code.

Model selection lives in vox-orchestrator::models::{registry, select, autonomic} and is driven by config + policy. A new model — Claude, MENS revision, OpenAI, Mistral, Cohere, or anything future — slots in by registering a ModelRegistryEntry with a per-task-class score, NOT by editing call sites. MENS revisions are first-class candidates evaluated on the same scoring axes (latency, cost-per-token, quality-score, locality) as any external model.

Why this is a normative cross-tool rule. As frontier models ship (now monthly across providers), this boundary turns “adopt the better model” into a one-line config change instead of a workspace-wide sweep. Token-waste audits like vox audit effort (planned per docs/superpowers/specs/2026-05-28-effort-audit-core-design.md) self-improve when registry selection picks up a better-scoring judge — but only if every call site stays on the facade.

Enforcement.

  • vox-code-audit detector llm_provider_call (at crates/vox-code-audit/src/detectors/llm_provider_call.rs) flags violations as Error. Hostnames already covered: Anthropic, OpenAI, Cohere, Mistral, Together, Replicate, HuggingFace, Fireworks, Perplexity, Google (generativelanguage + aiplatform), OpenRouter. Add new provider hostnames to that detector when they’re integrated.
  • Languages covered: Vox, Rust, TypeScript.

Override (rare). Only via a documented inline deprecation marker during a tracked migration: // vox-deprecated-since="X.Y.Z" retire-by="X.Y.Z" reason="..." canonical="vox_actor_runtime::llm". No silent exceptions.

Vox skills are agentskills.io-format SKILL.md directories — the open standard read by 40+ agent harnesses (Claude Code, Cursor, Codex, Copilot, Gemini CLI, …). One skill set serves every tool; never maintain per-tool copies.

Use skills where they apply. Before starting a task, check whether an installed skill matches it: vox skill list / vox skill search <query> (MCP: vox_skill_list / vox_skill_search; GUI: Skills surface and /skill-name in the chat composer). If a skill’s description matches, load its body and follow it — that is the ecosystem-standard triggering model (description-based selection by the agent itself). For chat-routed models this happens via the tier-1 catalog injected into the system prompt and the vox_skill_use tier-2 tool (planned per Track B of the plan below).

One format, one SSOT. New skills MUST use spec-compliant YAML frontmatter (name matching the directory name, description 1–1024 chars); Vox extensions ride in metadata vox-* keys (vox-id, vox-category, vox-tools, vox-permissions, …). The parser SSOT is vox-plugin-host::skill_parser (YAML + legacy TOML), types in vox-plugin-types, runtime registry in vox-skills, first-party catalog in crates/vox-plugin-catalog/catalog.toml. Do not invent a parallel skill format, loader, or registry.

Discovery is automatic — never hand-register. Skill roots, highest precedence first: workspace .vox/skills/, .agents/skills/, .claude/skills/, then the same three under ~, then the vendored bundle assets/skills/ (roots + bare-dir discovery are planned per Track A; today plugin skills load from Plugin.toml roots and vox skill discover walks the workspace). Adding a new skill to either ecosystem — Vox-native or any external harness writing to .agents//.claude/ — means dropping a spec-compliant directory in a root; it is picked up on the next discovery pass with no registration code. Verify with vox skill discover; format is gated by vox ci agentskills-compliance and tool parity by vox ci plugin-skill-parity.

Search goes through vox-search. Keyword search over the registry is vox skill search / vox_skill_search. Richer skill retrieval (name/description/body, semantic matching for “which skill fits this task”) MUST be built on the existing vox-search hybrid stack (tantivy lexical + semantic indexer + RRF fusion — the engine behind the GUI palette’s vox_search_query), not a bespoke skill index.

Licensing for vendored skills. The spec’s frontmatter license field is optional and untrustworthy — only repo-level LICENSE files count as evidence. Record provenance (repo, SHA pin, license) in assets/skills/SOURCES.toml. Known non-redistributable: Anthropic’s docx/pdf/pptx/xlsx document skills (source-available, explicit no-redistribution terms) — never vendor them.

See: research docs/src/architecture/skill-ecosystem-interop-research-2026-06-12.md; plan docs/superpowers/plans/2026-06-12-skill-ecosystem-interop-and-awareness.md.

All project automation — CI prep, corpus transforms, training pipelines, install helpers, data migrations — MUST be written as .vox files and executed via vox run. Do not introduce new .ps1, .sh, or .py glue scripts.

Why: A single vox run scripts/foo.vox command shape is:

  • Type-checked by the Vox compiler before execution (vox check scripts/foo.vox)
  • Cross-platform (same file, same command on Windows/Linux/macOS)
  • Auditable via vox.script.* telemetry events
  • Free from shell-specific approval friction in IDE allowlists
  • A natural addition to the MENS training corpus

Execution tiers (choose based on need):

NeedCommandNotes
Pure computation, fast startupvox run --interp scripts/foo.voxNo compile step; interpreter isolation
Script-shaped (default)vox run scripts/foo.voxInterpreter; no cargo. Repeatable --caps
Native compile (opt-in)vox run --mode script scripts/foo.voxNeeds cargo + rustc; not a sandbox

Bootstrap exception: scripts/windows/vox-dev.ps1 and scripts/vox-dev.sh are retained as thin launchers only (≤10 lines of primary logic where possible). They forward to cargo run -p vox-cli -- run <args> to solve the chicken-and-egg problem of needing vox to run .vox before vox is built.

Security invariants:

  • Scripts that modify the Vox repository MUST be committed to VCS before an agent executes them
  • No .vox script may use shell_exec to bypass the compiler sandbox
  • Subprocess calls go through vox-actor-runtime process primitives (telemetry-observable)
  • Use the secrets crate (vox_secrets::resolve_secret(...)) for secrets — never env.get("MY_KEY") for sensitive values

Formatting Rust (Windows-safe). Never run cargo fmt --all on this workspace — it passes every crate’s target root to a single rustfmt process, which overflows the Windows CreateProcess command-line limit and dies with os error 206 (“The filename or extension is too long”). Routine work formats dirty .rs files only; do not sweep the whole repo unless you changed rustfmt.toml or are merging parallel-agent work:

vox run scripts/fmt.vox # write: dirty .rs only (default)
vox run scripts/fmt.vox -- --all # write: full workspace
vox run scripts/fmt.vox -- vox-cli # write: one workspace package
VOX_FMT_CHECK=1 vox run scripts/fmt.vox # check dirty only (local)
VOX_FMT_CHECK=1 vox run scripts/fmt.vox -- --all

scripts/fmt.vox runs rustfmt --config-path <repo root> in chunks of 50 paths (never cargo fmt --all). Dirty-file mode formats dirty .rs paths; --all / VOX_FMT_ALL=1 formats every target root from cargo metadata. The pre-push gate (vox ci pre-push → check_fmt) is always full-workspace rustfmt --check — dirty check is not CI parity. After a failed gate: vox run scripts/fmt.vox -- --all. A single crate: cargo fmt -p vox-cli.

Full rationale, execution tier map, security model, and migration plan: background research in docs/src/archive/research-2026-q1/ (do not ingest — see §Archival Protocol).

Vox source follows one rule for top-level declarations:

Bare-keyword blocks declare scope. Decorators modify declarations.

Bare-keyword blocks (each opens a scope with its own rules): type, fn, component, state_machine, routes, module, actor, workflow, activity (the last two stable per ADR-041 — see Implementation status below), and the data-layer soft keywords table, query, mutation, server, tool, resource, form, index (each dispatched only at declaration-head position, with no dedicated lexer token — see crates/vox-compiler/src/parser/descent/mod.rs). These eight replaced the equivalent decorator spellings — see §Retired Surfaces; the decorator spellings are hard parse errors as of 2026-06-30 (cd7cc96874).

Decorators (modifiers composed on top of a declaration): @pure, @deprecated, @require, @auth, @uses, @test, @v0, @durable, @scheduled (the last two stable per ADR-041 — see Implementation status below). Removed in v0.6.0: @endpoint (see §Retired Surfaces). Retired 2026-06-30: the decorator spellings of the eight data-layer keywords above (i.e. the @-prefixed forms of table/query/mutation/server/ tool/resource/form/index) are now hard parse errors — use the bare-keyword forms instead. @mcp.tool is a separate case: it still parses but is soft-deprecated (a warning, not an error) in favor of bare tool; @mcp.resource remains fully valid, non-deprecated syntax, though bare resource is preferred for new code. @v0 is a third case: it still parses today but lowers to a no-op (zero corpus uses) and is scheduled for retirement in a later phase of this program (not yet implemented) — do not use it in new code.

Decorators compose with bare-keyword blocks:

// vox:skip
@auth(scheme: bearer) table Task { … } // decorator on a bare-keyword declaration
@uses(net) fn fetch_remote() { … } // decorator on a function
@pure fn checksum(payload: bytes) { … } // purity declared via decorator

Rule for new features: Do NOT introduce a new bare keyword for behavior that can be expressed as a decorator. New execution semantics (durability, tracing, sandboxing, rate-limiting) belong as decorators on fn.

Implementation status. actor/workflow/activity and @durable/@scheduled are stable, backed by a durable runtime for the supported subset (ADR-041 supersedes the old ADR-028 reservation gate — out-of-subset behavior is now policed by the determinism lint, not a reservation gate). Contract: ADR-019, ADR-021, ADR-041. Drift between this section and pipeline.rs is checked by the docs-reality-audit-program.

Code Intelligence — Graphify (Required, SSOT)

Section titled “Code Intelligence — Graphify (Required, SSOT)”

Vox ships its own code-intelligence graph — vox graph (formerly vox graphify). It is a native Rust subcommand over this repo’s AST, not the Python scripts/coverage-graph/*.py scanners, which are separate report generators. When someone says “graphify” in a Vox context they mean vox graph.

Before you start, the corpus graphs must exist. A fresh clone has none, and an unbuilt graph fails silently — queries just return nothing, which reads like “no results” rather than “no index”:

Terminal window
vox graph status # per-corpus freshness; --strict exits non-zero when stale
vox graph refresh --auto # build/rebuild every stale corpus (do this once per clone)

vox doctor reports this as Graphify cache, so a new install sees it without knowing to look.

Reach for it instead of grep when the question is structural:

QuestionCommand
Where is this symbol / concept?vox graph query "<terms>"
Is this backend node reachable from a surface?vox graph coverage --kind <kind> (Surfaced / OrphanBackend / DeadEnd)
What does changing this crate rebuild?vox graph crate-map (Leiden communities + blast radius)
Why did all these crates recompile?vox graph why-rebuilt

rg still wins for literal strings and one-off greps. The graph wins for reachability, blast radius, and dead-surface questions — the ones where grep gives you mentions rather than structure, and where a missed call site becomes a bug.

Keep it fresh when it matters. The graph is keyed to a commit; after large refactors re-run vox graph refresh --auto, and treat worktree_drift on a corpus you are about to query as “rebuild first”. Snapshots are pruned with vox graph gc.

Cross-Platform Shell Discipline (Stable Rules)

Section titled “Cross-Platform Shell Discipline (Stable Rules)”

Scope of the PowerShell preference. The PS-first stance below is a host-side allowlisting and output-parsing preference, not a claim that agents produce better code in PowerShell than Bash. Project automation is Vox (see §VoxScript-First Glue Code). See docs/src/architecture/terminal-exec-policy-ssot.md for what this policy does and does not claim.

  • PowerShell 7 (pwsh) when available: On any host where pwsh is installed, prefer it for the two retained launcher files and for interactive terminal work, so behavior matches contracts/terminal/exec-policy.v1.yaml and vox shell check. On Windows, PowerShell is the default expectation even when only Windows PowerShell 5.1 (powershell.exe) is present.
  • CI vs local: Repository CI jobs often run under bash on Linux self-hosted runners (docs/src/ci/runner-contract.md); that does not override the local/agent preference for pwsh when you have it.
  • Prefer structured tooling and project CLIs (vox, cargo, pnpm, rg) over ad hoc shell pipelines. uv and Python are no longer preferred for project automation — use vox run instead.
  • Search Optimization: Do not run blind recursive searches (ripgrep searching) in the workspace root as it takes too long. Always narrow down the search path (e.g. to specific crate subdirectories like crates/vox-cli/) or use glob patterns. Prefer native rg via run_command with precise paths over the built-in grep_search tool, which can fail on Windows. Before reaching for rg at all, check §Code Intelligence — Graphify: for “who calls this”, “what is unreachable”, “what does this crate pull in”, a graph query beats any grep.
  • Dev launcher when vox is missing from PATH: scripts/windows/vox-dev.ps1 / scripts/vox-dev.sh — forwards argv to vox via cargo run -p vox-cli from the workspace root (optional env: VOX_REPO_ROOT, VOX_USE_PATH=1, VOX_DEV_FEATURES, VOX_DEV_QUIET=1). See docs/src/reference/cli.md (heading Bootstrap / dev launcher (missing vox on PATH)).
  • Do not rely on shell-specific one-liners as policy boundaries; approvals and allowlists vary across IDEs.
  • Keep commands decomposed into clear steps when safety or portability is at risk.

Environment-specific overlays (for example Antigravity on Windows) add stricter command-shape rules on top of this base; see GEMINI.md. If Claude Code is in use, also see CLAUDE.md for Claude-specific additions. For Cursor-specific rules see .cursor/rules/ — nine .mdc rule files covering build environment, CI runner conventions, CLI command registry, cross-platform source hygiene, data storage policy, documentation policy, retired surfaces, secrets policy, and VoxScript-first automation.

Live SSOT (scoped claim + evidence): docs/src/architecture/terminal-exec-policy-ssot.md. Vox stdlib vs shells: docs/src/architecture/vox-shell-stdlib-ssot-2026.md — std.fs / std.process are argv‑first Rust builtins; they do not lower to PowerShell/bash. Optional A/B eval design (not run, not required): docs/src/architecture/agent-shell-fluency-eval-design-2026.md. Archived 2026-Q1 background research is under docs/src/archive/research-2026-q1/ — do not ingest autonomously per §Archival Protocol.

Binding for all coding agents (Claude, Cursor, Codex, Copilot, human contributors):

When adding a new pub fn in Rust or a new fn in examples/golden/ Vox files, the failing test comes first. The implementation comes after — written until the test passes.

  • Rust: every new pub fn in crates/*/src/** (excluding main.rs, bin/, tests/, and files under 30 non-blank lines) requires at least one #[test], #[tokio::test], or #[cfg(test)] mod tests block in the same file before the commit lands. Detector: skeleton/untested-pub-api.
  • Vox golden examples: every new fn in examples/golden/**/*.vox must be exercised by an @test block in the same file. Detector: skeleton/no-test-for-pub-fn.
  • Task briefs to AI agents: start with the failing test, not the desired implementation. The test fixes inputs, outputs, and edge cases unambiguously and lets the agent verify its own work. See docs/src/contributors/coding-agents.md §Task brief format.

Why this is a normative cross-tool rule, not just a contributor guide:

In Vox, tests are not just regression catchers — they are training data for the MENS model. r_test (test pass rate) is 30 % of the planned GRPO reward. Test-covered code becomes a positive corpus example; uncovered or stubbed code becomes a negative example. Skipping the test step doesn’t just risk a regression, it weakens the model’s prior.

Enforcement:

  • Pre-commit hook (lefthook tdd-guard): blocks commits that introduce pub fn / fn without an adjacent test. Installed by vox run scripts/setup.vox.
  • CI: vox-code-audit reports skeleton/untested-pub-api (Warning) and skeleton/no-test-for-pub-fn (Warning). Default CI mode is legacy (Errors block, Warnings surface). PRs touching crates/vox-compiler/** or crates/vox-codegen/** additionally trigger cargo mutants to verify tests catch mutations, not just exist.
  • Override: // toestub-ignore(skeleton/untested-pub-api) — <reason> on the line above the pub fn, or a structured entry in contracts/toestub/suppressions.v1.json with owner and reason. Suppress only when refactoring is impractical, not to avoid the work.

Fix companion: docs/src/contributors/toestub-contributor-guide.md has rule-by-rule fix patterns.

Canonical budgets: contracts/budgets/test-tier-budgets.v1.yaml Full tier spec: docs/superpowers/specs/2026-05-27-test-suite-perf-and-gate-tiers-design.md §4 Full tier table + per-flag details: docs/src/contributors/local-ci-pre-push.md — do not restate the tier table here, it drifts.

Hosted CI is the gate; the laptop is not (Required, decided 2026-10-03). GitHub-hosted runners run clippy, the full suites, nightly and release builds. Locally, verify only what you touched: cargo check -p <crate> and cargo nextest run -p <crate> (or cargo test -p <crate> <filter>). Never run cargo clippy --workspace or a workspace-wide test locally to “pre-check” a push — that cost hours on a loaded machine and duplicated the gate. Evidence and plan: ci-and-build-loop-findings-2026.md.

  • Work reaches main only through a PR. Branch, batch commits, git push -u origin HEAD:<branch>, gh pr create --draft, read CI, self-review, mark ready, merge through the queue. The pre-push hook refuses a push to main (VOX_ALLOW_MAIN_PUSH=1 overrides for emergencies only).
  • Git hooks never build. They call the installed vox and toestub; vox ci dev-loop-guard (fast tier, local and CI) fails if a hook runs cargo run/build/test/clippy, calls an unregistered vox command, or .cargo/config.toml hardcodes [build] jobs.
  • No hardcoded CPU or job counts in config, the build broker, workflows or scripts: derive from the machine (available_parallelism, load). An env var may override; a literal default may not.
  • One target/ per worktree; never symlink target into another checkout — a shared build-dir lock serializes every worktree behind the slowest build.
  • Per-job spot-checks: reproduce a failing CI job by running that job’s exact command for the affected crate, not by re-pushing blindly.

Use vox ci pre-push to run any tier locally (default = fast, ≤60s: fmt, line-endings, ssot-drift, workflow-concurrency-guard, workflow-permissions (strict), scoped doc lint + doctest, drift-check, dev-loop-guard). It runs as the pre-push hook (advisory; hosted CI is authoritative). The full tier list (complete / full / full+cov / full+since / full+cov+since / ci-equivalent), their exact flags, and the --include-slow slow-test names live in local-ci-pre-push.md — not restated here.

Budget enforcement: --enforce-budgets compares total elapsed against contracts/budgets/test-tier-budgets.v1.yaml (warn at 1.2×, fail at 1.5× measured baseline). No-op if the budgets file is absent. CI also runs vox ci tier-budget-check --junit target/nextest/ci/junit.xml --profile full after each nextest run.

Workspace crate-dependency edges are CI-gated by vox ci crate-edges (exact edge-set ratchet + downward-only layer rule; contracts: contracts/ci/crate-edges.allow.v1.json and the layer map in docs/src/architecture/layers.toml, which vox-arch-check also reads — the single layer SSOT).

  1. Before adding a dep on another workspace crate: prefer a narrower -types/-core crate; or apply the defactor policy (rule 3). If the edge is genuinely needed, PROPOSE an exceptions ledger entry in your PR description and stop.
  2. exceptions entries are USER-AUTHORIZED-ONLY. Never write one yourself, and never regenerate a baseline (crate-edges.allow.v1.json, fan-in-snapshot.v1.json) to admit an edge you introduced. Tightening (vox ci crate-edges --tighten) is always allowed.
  3. Defactor policy: a helper under ~50 lines may be duplicated into the consumer with a // vox:defactored-from <crate> <date> comment instead of taking a crate edge. Larger shared surfaces get split into -types/-core crates. Never fork 100+ line chunks.
  4. New crates must be assigned a layer in docs/src/architecture/layers.toml [crates] at creation (L0 pure types … L4 plugins, L5 surfaces; see the file header and docs/src/architecture/where-things-live.md). Dependencies point same-layer or down.
  • GitHub-hosted CI is the gate. ci.yml’s required context (Check, Build, and Test (Rust)) is a thin gate job whose one step checks that linux, tests and ui succeeded. linux runs the local fast tier plus clippy on affected crates; it also runs cargo-deny licenses/bans/sources on dependency changes, and cargo clippy/rustdoc -D warnings on a detected toolchain bump. tests runs nextest on the same affected set in 3 parallel --partition hash:K/3 shards (a skipped tests counts only when linux planned none), under nextest profile ci-gate: ci minus a quarantine of tests red on main (issue #569; nightly still runs them). Never add a test to the quarantine to make your own PR green — only remove entries as they get fixed. ui (typecheck + vitest + Playwright) is required only on PRs that change crates/vox-gui/** or orch_daemon/mod.rs (it fails closed when the base SHA is missing). The merge queue additionally runs an advisory (non-blocking) Windows compile check. Jobs are capped at 30 min. nightly.yml and other scheduled workflows run the slow lanes, capped at 180 min. Caps are enforced by workflow-policy-guard (in ssot-drift). Over budget? Cache, shard, or move the job to nightly — never raise the cap.
  • What nightly defers, and what it doesn’t. Every normal PR does run nextest — on the affected-crate subset, in the tests shards. What is deferred to nightly is the full-workspace run’s llvm-cov coverage lane, and the full run for ordinary PRs. PRs touching Cargo.toml/Cargo.lock, .cargo/, .github/workflows/, contracts/ or .config/ run the full workspace suite (measured 2026-09-26: ~21 min of test execution on a 4-core hosted runner, which is why it is sharded). The one case where tests are skipped entirely is a detected toolchain bump: linux spends its budget on fresh clippy/rustdoc instead, and the tests fall to nightly’s full run.
  • Run CI locally first: vox ci pre-push (fast), --complete/--full for code changes, or run the PR gate’s linux job in Docker with act pull_request -j linux.
  • CI state comes to you. Failed/timed-out jobs on your branch and open nightly-failure issues are printed by the git pre-commit/pre-push hooks and injected by Claude Code hooks. When you see a block, fix it before continuing. vox ci status prints the same block on demand. Scheduled workflows that stop running (past ~2x their cadence) trigger their own Nightly stale: issues via a dead-man’s-switch workflow (ci-liveness.yml).
  • Concurrency required. Every push/PR-triggered workflow needs a top-level concurrency: block with cancel-in-progress: true (or a row in docs/src/ci/concurrency-exceptions.md), enforced by workflow-concurrency-guard.
  • Rust caches are main-only. Swatinem/rust-cache saves only from main branch runs; PR and merge_group runs restore but never save. The reason is the repository’s hard 10 GB Actions-cache budget with LRU eviction: a cache written from a PR run is scoped to refs/pull/N/merge, so no other ref can ever read it. Every such entry is write-only garbage that evicts the main-scope entries every job actually restores from. The same rule covers actions/cache, Swatinem/rust-cache, and actions/setup-node with a cache: input (use package-manager-cache: false); it is enforced by vox ci cache-key-lint.

Spec: docs/superpowers/specs/2026-09-21-hosted-primary-ci-design.md.

GUI Visual Verification Invariant (Normative Policy)

Section titled “GUI Visual Verification Invariant (Normative Policy)”

All GUI components, panels, and surfaces MUST have automated visual inspection verification in Playwright before merge.

  • Automated visual stepper suite: Any new or substantially modified GUI surface, panel, or interactive debugger must be backed by a deterministic Playwright spec (crates/vox-gui/ui/e2e/) executing stateful interaction sequences against mock IPC harnesses (installTauriMock / installTauriMockRich).
  • Visual evidence capture: Visual stepper tests must capture viewport screenshots into crates/vox-gui/ui/review-bundle/latest/ to provide evidence of layout stability, occlusion avoidance, and diagnostic rendering across themes and viewports.
  • Pre-merge verification: UI changes must pass pnpm --dir crates/vox-gui/ui test:e2e and pnpm --dir crates/vox-gui/ui typecheck before merging to prevent regressions in user-facing surfaces.

Derived from scanning 528 fix() commits — these classes recur. Each line is the cheapest place to catch the class before it lands again.

  • Toolchain-bump lint waves (the #1 perennial). Every rust-toolchain.toml bump (1.92→1.95→1.96…) introduces new clippy/rustdoc lints that fire workspace-wide and need a cleanup commit (e.g. manual_is_multiple_of, field_reassign_with_default arrived in 1.96). Cached clippy hides them. When bumping the toolchain, run a FRESH check before merging the bump: CARGO_INCREMENTAL=0 cargo clippy --workspace --all-targets -- -D warnings and RUSTDOCFLAGS='-D warnings' cargo doc --workspace --no-deps. A CI gate that does this when rust-toolchain.toml changes is the durable catch.
  • Pre-push clippy gap. The fast/default pre-push hook does not run clippy (only --complete and above do) — ~45 fixes were clippy errors that landed then got cleaned up. Before pushing Rust changes, run vox ci pre-push --complete or cargo clippy -p <touched-crate> -- -D warnings. Recurring offenders: unused_mut, field_reassign_with_default, len_zero, needless_range_loop.
  • Doc fences compiled as unintended doctests. A bare or rust-tagged fence in docs is compiled as a doctest; example snippets that aren’t meant to compile fail the rustdoc gate (“annotate as text so it isn’t compiled as Rust” recurs). Mark non-compiling examples ```text; for vox excerpts use ```vox + a leading // vox:skip with a reason (see §Markdown Hygiene).
  • Async handler / async-test regression (codegen). query/mutation handler emission must await (handler_await); and merges have silently reverted async tests to sync (vox-vcs cas_fallback). On a merge that touches async code/tests, re-confirm they’re still async before pushing.
  • SSOT / schema drift (largest class, 103 fixes) — already gated by vox ci ssot-drift (+ the ssot-autoregen PR bot). Don’t hand-regenerate after merge; see §Local CI Gate Tiers.
  • vox-gui sidecar missing in a fresh worktree. cargo build/test -p vox-gui fails inside tauri-build (“resource path … doesn’t exist”) the first time ANY git worktree add builds it — each worktree gets its own target/ (per-worktree by design, see .cargo/config.toml), so the release vox binary Tauri bundles as an externalBin sidecar doesn’t exist yet. crates/vox-gui/build.rs and vox doctor both name the missing path and the fix: run vox run scripts/gui-build.vox (or cargo build -p vox-cli --release then copy target/release/vox[.exe] to the triple-suffixed sidecar path) once per worktree before building vox-gui. The same worktree also lacks crates/vox-gui/ui/dist, which tauri.conf.json’s frontendDist points at, so cargo clippy --workspace --all-targets (and therefore vox ci pre-push --complete) fails there too until you run pnpm install && pnpm build in crates/vox-gui/ui. Three independent agents hit this on 2026-09-05 in three fresh worktrees; it is not a code problem and nothing should be committed to “fix” it.
  • Move + reformat = a duplicate definition, not a merge conflict. When one branch MOVES an item (function, impl, test) and another reformats or edits around its old position, git sees a delete at one site and an add at another, takes both, and produces a file that compiles-fails rather than merge-fails — the item is defined twice with no conflict markers to warn you. Observed 2026-09-04 merging bf1b73061 (which moved cargo_config_rustc_wrapper above the test module for clippy) into a branch that had reformatted around its old position. Union-resolving (“take both hunks”) is safe only for append-only registries — index tables, mod lists, match arms added at the end — and is actively wrong wherever one side may have moved something. The opposite naive resolution fails too, and more quietly: taking ONE side of a shared table or registry can yield a green test asserting something false — observed the same day, where #473 and main each correctly edited a different row of the writer table in workflow_permissions_guard.rs, so either side taken wholesale passes its own test and is wrong. Between the two there is no safe default: union-resolve breaks the build, one-side-wins breaks the assertion, and neither shows a marker. After resolving any Rust conflict, verify each item is defined once (grep -c 'fn <name>'), its call sites still resolve, cargo check -p <crate> is clean, and — for a table or registry — check every row against the merged tree, not against either side’s intent. A marker-free file is not evidence of a good merge.
  • Parallel-agent fmt drift. When multiple agents/worktrees touch overlapping crates concurrently, rustfmt drift from one session’s edits routinely lands unformatted in another’s commit. Before merging work assembled from parallel sessions, run vox run scripts/fmt.vox -- --all (or VOX_FMT_CHECK=1 vox run scripts/fmt.vox -- --all to check only) — the default dirty-only pass will miss files another agent formatted on a different worktree.

Coverage of these classes by detector + severity + enforcement point (and the still-open gaps) is tracked in detector-coverage-ledger.md — add a row when you add a detector.

PR & Review Discipline (Required, Cross-Tool)

Section titled “PR & Review Discipline (Required, Cross-Tool)”

CodeRabbit runs on demand (free tier, resumed 2026-10-09). It does not review automatically on this repository. When a PR is marked ready, comment @coderabbitai review once (not per push); triage its findings like any other review. It is advisory: never wait on it as a gate, never treat a PR as reviewed because CodeRabbit commented, and never tick its Autofix/Autopilot boxes — it must not push to the branch. Its status/skip boilerplate is turned off in .coderabbit.yaml. Review is still performed by the agent or human opening the PR, before asking for a merge.

Because no reviewer is guaranteed to look at a PR:

  • Review your own diff before proposing a merge. Read every hunk you are about to ship, not just the ones you remember writing. Run /code-review high (or an equivalent careful pass) over the full branch range, not the last commit.
  • Batch commits; push once when the branch is review-ready — not after every commit.
  • Don’t open a PR before it’s review-ready. Use a Draft if you must push early.

Verify security-relevant guards by mutation, not by observing green tests. Break the guard deliberately and confirm the test fails, then restore. A test that passes against both the fixed and unfixed code is worthless, and this repo has shipped several: a validator unit-tested directly still passed with every call site deleted, and a shell test asserting only “failed, no marker” could not distinguish failed closed from never ran. Guard the mutation with a before/after presence check — a concurrent cargo fmt or another agent can revert your edit and hand you a meaningless pass.

Never edit a tree another agent owns. “Completed” status is not sufficient; orphaned background shells keep writing. Verify what actually shipped by inspecting the committed object (git show <sha>:<path>), never the working tree — a clean working tree can hide a poisoned commit.

One-line takeaway: nothing reviews it but you.

Other CodeRabbit surfaces. Beyond the live .coderabbit.yaml, contracts/review/coderabbit-semantic-groups.v1.yaml and CodeRabbit entries in .github/workflows/ci.yml, contracts/operations/catalog.v1.yaml, and the secrets registry belong to the older paid-tier integration; do not rely on them for the free-tier flow above, and change them only in a PR that is about them.

Markdown Hygiene and Code Snippets (Doctest Policy)

Section titled “Markdown Hygiene and Code Snippets (Doctest Policy)”
  • All ````vox``` blocks in documentation must compile cleanly via vox-doc-pipeline’s dynamic doctest runner.
  • Always write inline ````vox``` blocks, do NOT use mdBook {{#include}} directives for new code.
  • If rendering invalid code for illustrative reasons, disable validation explicitly by using // vox:skip inside the snippet.
  • You MUST enforce syntax correctness programmatically over legacy include files.

Do NOT use the following retired symbols, crates, or env vars. Using them will result in hallucinations and broken integration:

Retired / DeprecatedCanonical Replacement (Use Instead)
vox-dei (old large orchestrator crate)vox-orchestrator
vox-ars (crate)vox-openclaw-runtime
KbStore, KbRouter, legacy vox_kb_* CRUD toolsvox_kb_search / vox_kb_get / vox_kb_cite (Library index) and the kb_findings inbox for anything model- or web-derived (retired KB Phase 3, D-02; no aliases)
vox-ludusvox-gamify
vox-lexer, vox-parser, vox-hir, vox-typeckvox-compiler (monolith)
@component fn Name()component Name() {}
@endpoint(kind: server|query|mutation) fn (removed v0.6.0)server name(...) to T / query name(...) to T / mutation name(...) to T (bare-keyword, no fn; the at-prefixed forms became hard parse errors 2026-06-30, cd7cc96874)
@py.import (Python interop)Removed — Python is no longer a Vox glue surface (see §VoxScript-First Glue Code)
@native (decorator)@place(native)
TURSO_URL / VOX_TURSO_URL / VOX_TURSO_TOKENVOX_DB_URL / VOX_DB_TOKEN
recall() / recall_async() (deprecated memory reads)MemoryManager::lookup_fact_by_key (async) or RAG / retrieval bundle — see crates/vox-orchestrator/src/memory/manager.rs
@capacitor/*, npx cap sync@tauri-apps/plugin-*, cargo tauri build
axum::serve, rust-embed (for generated desktop/mobile apps)Tauri 2 runtime (Axum is retained for native-binary/server targets only)
vox-sherpa-transcribe (Capacitor plugin)vox-tauri-stt (native Tauri STT plugin)
crates/vox-dashboard (deleted 2026-05-12, af5f26278; Axum dashboard retired per ADR-037)crates/vox-gui (Tauri 2)
crates/vox-oratio (crate renamed 81681e81b; the vox speech command keeps oratio as a visible alias)crates/vox-speech
vox-dei-shim (renamed 5463bc16c)vox-research-shim
vox-bootstrap (crate, deleted)voxup (crates/voxup/) / scripts/install.{sh,ps1}
Qwen 2.5 family (Qwen2.5-Coder-*)Qwen 3+ (Qwen/Qwen3-8B@b968826d9c46dd6066d109eabc6255188de91218 active fine-tuning; Qwen 3.5)
--isolation wasm|container|gvisor|microvminterpreter (vox run / --interp); repeatable --caps (ADR-048)
vox wasm runvox run (interpreter)
script-wasiinterpreter (no rustup wasm target)
ProbeOnlyExecutorInterpExecutor
MicroVmRuntime / Tier::MicroVminterpreter isolation (ADR-048); planner error-path stays
VoxMeshExecPolicy (SecretId)receiver-imposed --caps (placement config key survives)
exec_bundle_b64VoxScript source on the mesh stream

Memory-write APIs are not a simple retirement pair: for writing facts, use MemoryManager::persist_fact; sync_to_db() bulk-syncs MEMORY.md → DB only and is not a drop-in replacement for persist_fact.

Any vestigial code remaining from an active migration (e.g. Tauri convergence) MUST be marked with an inline deprecation annotation so vox ci retirement-audit can track it. Marker syntax: // vox-deprecated-since="0.6.0" retire-by="0.7.0" reason="tauri-convergence" canonical="..."

Every vestigial call site must carry this marker until it is fully removed by its respective migration task.

Single source of truth: Cargo.toml [workspace.package] version. All first-party crates inherit it via version.workspace = true, vox-plugin-* included. The [plugin] version in a code or composite Plugin.toml must equal it too: vox-plugin-host::load_code_plugin refuses any other (spec §4.2(d)), and vox ci plugin-surface-sync fails on drift. Skill-only plugins are not version-checked.

Version scheme: MAJOR.MINOR.PATCH+build.N (GITHASH) — MAJOR.MINOR/PATCH are human-bumped (or git-cliff on tag for PATCH); +build.N/(GITHASH) are injected automatically by vox-build-meta in build.rs on every commit.

After bumping MAJOR.MINOR: update CHANGELOG.md with a ## [X.Y.Z] - YYYY-MM-DD entry — vox-arch-check Rule 6 uses this date to flag crates that haven’t changed in the new release cycle (mark intentionally-stable crates staleness_exempt = true in layers.toml).

Documentation version = compiler version. Do not maintain a separate “doc version.” Release notes live under docs/news/YYYY-MM-DD-vX.Y.Z-release.md, same X.Y.Z as Cargo.toml.

Agents and contributors must strictly adhere to architectural invariants. Ensure you verify against skeleton code limits (TOESTUB), God Object constraints, and maximum sprawl limits.

Full details: See docs/agents/governance.md for the complete policy, line limits, and module freeze rules.

Vox Language Enforcement Rules (LLM Guard)

Section titled “Vox Language Enforcement Rules (LLM Guard)”

These rules apply to .vox source files and are enforced by vox stub-check (static) and the Vox runtime (dynamic). Agents writing Vox code MUST follow them.

Effect declarations (Phase 5):

  • Any pub fn, query fn, mutation fn, or server fn that calls http.*, net.*, fetch(, populi.*, or std.http.* MUST carry @uses(net) in the preceding decorator list.
  • A @pure fn MUST NOT call http, net, fs, db, random, time, log, or any async/await — the compiler will reject it.
  • Workflow bodies (workflow { }) MUST NOT call non-deterministic builtins: time.now(), random.*(), uuid(), crypto.random_bytes(). Use activity functions for side-effectful work instead.

Type boundaries (Phase 3):

  • ID parameters on query, mutation, server, or activity functions, or actor-message functions, MUST use Id[T] (e.g., Id[User]) rather than bare str. Lint: vox/types/id-required-at-boundary.
  • Error types on public boundaries MUST be named ADTs — Result[T, str] is flagged by vox/types/anonymous-error-type.

Decorator position (Phase 2):

  • Use @durable fn, @pure fn, @scheduled fn — NOT durable fn, pure fn, scheduled fn. The bare-keyword position is reserved for actor, workflow, activity, fn, type, component, routes, module, state_machine.
  • See the Grammar Unification section above for the full keyword table.

Auth / access control:

  • Every query, mutation, or server declaration should carry either @auth(...) for authenticated routes or an explicit open-access annotation. The legacy vox/auth/endpoint-missing-decorator lint targeted @endpoint fn, which was removed in v0.6.0; auth decoration enforcement for the bare-form decorators is tracked in Phase 6 of the language-rules plan.

State machines:

  • Every state in a state_machine { } block must have at least one -> outgoing transition, or be marked as a terminal state with a // terminal comment. Flagged by vox/state-machine/unreachable-state.

Generated files:

  • Do NOT manually edit files with a @generated-hash <hex> header. Re-run the generator (xtask gen-builtins or the appropriate script). Flagged by vox/codegen/generated-file-drift.

Full details and per-rule fix patterns: docs/src/architecture/vox-language-rules-and-enforcement-plan-2026.md and the per-phase child plans.

Do NOT read, ingest, or attempt to modify files in the archive/ or docs/src/archive/ directories when planning new features or writing new code. These directories are tombstoned. They exist for manual human reference only. If an LLM includes an archived pattern in new code, it is considered a severe system hallucination. If you need historical context about an archived pattern, ask the human operator to retrieve it; do not ingest the archive autonomously. See docs/agents/governance.md §Nomenclature for canonical migration paths.

Build Broker (Machine-Wide Cargo Coordination)

Section titled “Build Broker (Machine-Wide Cargo Coordination)”

Route every cargo invocation through the build broker; never run concurrent cargo commands against one workspace by hand, and never call the real cargo binary by an explicit resolved path (~/.cargo/bin/cargo, rustup run <toolchain> cargo, or Rust code built the same way) — that bypasses the broker’s queue. Plain cargo on PATH is correct: the broker is a cargo-named shim placed ahead of the rustup proxy, so PATH resolution is what makes interception work in the first place.

  • Installed by scripts/broker-install.vox (dry-run by default; --apply to build the shim, install it, and edit your shell profile). State and activation are checked by vox doctor.
  • Admission follows measured load (a build waits while the load average exceeds the core count). Tunables: VOX_BROKER_MAX_CONCURRENT (optional upper bound on simultaneous builds machine-wide) and VOX_BROKER_RESERVED_SLOTS (slots reserved for a build domain the broker’s file-lock semaphore can’t see, e.g. a containerised CI runner sharing the host’s CPU but not its mount namespace). Full reference: docs/src/contributors/build-broker-usage.md.
  • crates/vox-cargo-shim is excluded from the root workspace (its cargo-named binary can’t join workspace resolution) and is built with --manifest-path crates/vox-cargo-shim/Cargo.toml, never -p vox-cargo-shim.
  • Bypass shapes are caught by scripts/broker-bypass-lint.vox; known, not-this-plan’s-to-fix cases are recorded in scripts/broker-bypass-allowlist.txt with a reason, not silently skipped.