Skip to content

TOESTUB contributor guide

This is the fix-it companion to the architectural governance policy. That page documents what the rules are. This page documents how to fix them.

Terminal window
# Scoped to your changed crate (repeat per directory)
cargo run -p vox-cli --features stub-check -- stub-check crates/your-crate
# With fix suggestions
cargo run -p vox-cli --features stub-check -- stub-check crates/your-crate --suggest-fixes
# Severity filter (only errors and criticals)
cargo run -p vox-cli --features stub-check -- stub-check crates/your-crate --severity error
# Full workspace CI scan (what CI runs)
cargo run -p vox-code-audit --bin toestub -- crates/

Output is JSON when you need to pipe it: append --format json. Schema: contracts/toestub/toestub-run-json.v1.schema.json.


Triggers: A .rs file exceeds 500 non-blank lines, or a struct/impl has more than 12 methods. Multi-tier thresholds (300/400/500 lines): see governance.md §God Object Limit — do not restate the numbers here, they drift.

Fix: Split using mod.rs + pub use. Preserve public API surfaces exactly via pub use re-exports so callers don’t break. Follow the god object defactor checklist step by step — it has a PowerShell inventory script and a per-crate cargo test matrix.

Typical split:

large_module/
// Before: large_module.rs (600 lines)
// After:
// mod.rs ← pub use submodule::*
// types.rs
// core.rs
// helpers.rs

False positive: Large generated files (e.g. include-fragment patterns). Add to contracts/toestub/suppressions.v1.json with a reason and owner.


arch/sprawl — Error (forbidden names) / Warning (directory sprawl)

Section titled “arch/sprawl — Error (forbidden names) / Warning (directory sprawl)”

Triggers: A directory contains more than 20 files, or a file uses a forbidden generic name (utils.rs, helpers.rs, misc.rs, etc.).

Fix for directory sprawl: Create a feature-named subdirectory and move related files into it. Example: 22 files in src/commands/ → split into src/commands/corpus/, src/commands/training/, etc.

Fix for forbidden names: Rename to something domain-specific. utils.rs → retry_policy.rs, schema_helpers.rs, etc.


Triggers: A fn in an examples/golden/ Vox file is not called from any @test block in the same file. Scoped to golden examples only — scripts and non-golden .vox files are not checked.

Fix: Add an @test block that calls the function before implementing it (the @test-first gate from contribution-loop.md):

@test
fn test_my_fn() {
let result = my_fn("input")
assert(result is "expected")
}
fn my_fn(x: str) to str {
// implement until the @test above passes
return x
}

Suppression (rare): If a function is intentionally a private helper used only by other helpers (not directly tested), suppress on that line:

fn _internal_helper() to str {
return "helper" // toestub-ignore(skeleton/no-test-for-pub-fn)
}

False positive: Helper functions that are called by other tested functions will not trigger this rule — only completely uncovered functions fire.


Triggers: A function body returns only a trivially-default value with no side effects: Ok(()), true, false, Vec::new(), None, String::new().

Fix: Implement the function body. If the function is genuinely a no-op by design (e.g. an optional hook), document why in a comment and suppress:

// toestub-ignore(skeleton/hollow-fn) — intentional no-op default hook
fn on_agent_pause(&self) -> Result<()> { Ok(()) }

False positive: Test builder helpers. Use // toestub-ignore(skeleton).


Triggers: Empty or near-empty function bodies.

Fix: Same as skeleton/hollow-fn. Implement or suppress with reason.


Triggers: todo!(), unimplemented!(), or todo!("...") in production code paths (outside tests/).

Fix: Implement the function. There are no valid uses of todo!() in merged production code. If the feature is deferred, remove the function entirely or return a proper Err(...) with a structured error type.

The VictoryClaimDetector co-fires when “done / complete / fixed” appears near unimplemented!(). Do not add completion comments to stub code.


Triggers: High-entropy strings or credential-shaped literals in source code.

Fix: Route through vox-secrets:

use vox_secrets::resolve_secret;
let key = resolve_secret(SecretId::MyApiKey)?;

Declare the SecretId variant in crates/vox-secrets/src/spec/ (ids.rs + registry/). See Secrets SSOT for the full lifecycle.

False positive: Content-addressed hashes, test fixture values. Suppress with // toestub-ignore(security/hardcoded-secret) — SHA256 test fixture.


Triggers: A .vox code block in docs/src/ fails to compile cleanly in vox-doc-pipeline (neither a valid {{#include ../../../examples/golden/hello.vox:display}} nor a complete, compilable .vox declaration).

Fix:

fn hello(name: str) to str {
return "Hello " + name + "!"
}
fn illustrative_example() to str {
return "ok"
}

Triggers: CRLF (\r\n) line endings in tracked source files. Common on Windows with default git settings.

Fix:

Terminal window
# Prevent future CRLF on this machine
git config --global core.autocrlf false
# Fix existing files (from repo root)
cargo run -p vox-cli -- ci line-endings --fix

Check .gitattributes — * text=auto eol=lf is set repo-wide. If git is converting anyway, confirm core.autocrlf is false or input.


Triggers: A mod foo; declaration in a .rs file where foo is never subsequently used (use, pub use, or direct path reference). Only private mod declarations are flagged; pub mod is assumed to be reachable from other files.

Fix: Either wire the module (use crate::foo::Bar;) or delete the mod declaration and its file if the module is unused.


Triggers: Near-duplicate blocks of code detected heuristically (typically ≥5 identical or near-identical lines appearing in multiple locations).

Fix: Extract the shared logic to a named function or macro in a common module. The heuristic has false positives on table-driven data; suppress those with a short reason comment.


Triggers: Use of a retired crate, symbol, or environment variable from the AGENTS.md retired surfaces table.

Fix: Use the canonical replacement. Common cases:

FoundReplace with
Legacy orchestrator codenamevox-orchestrator
Legacy ARS crate labelvox-openclaw-runtime
Legacy Ludus crate labelvox-gamify
recall() / recall_async() (deprecated memory reads)MemoryManager::lookup_fact_by_key (async) or RAG/retrieval bundle
Legacy Turso URL env aliasVOX_DB_URL

Triggers: .unwrap() in non-test code paths (heuristic; test paths are skipped).

Fix: Replace with ?, a match, or .expect("invariant: reason") when the invariant is truly guaranteed. Prefer ? in most cases.


Triggers: “Done / solved / fixed / complete” style comments or strings. victory-claim/hack (Info) fires for HACK, FIXME adjacent to stub code.

Fix: Remove the completion claim, or implement the code the claim refers to.


magic-value/* — Warning / Error (sub-id varies)

Section titled “magic-value/* — Warning / Error (sub-id varies)”

Triggers: Hard-coded ports, very long strings, large integer literals outside of clearly named constant context.

Fix: Extract to a named constant or move to contracts/scaling/policy.yaml for values that belong to the policy surface.


Triggers: A struct field typed as String with a comment listing the valid values (common in config structs).

Fix: Replace with a #[derive(Debug, Clone, serde::Deserialize)] enum.


scaling/surfaces — Info/Warning (14 sub-rules)

Section titled “scaling/surfaces — Info/Warning (14 sub-rules)”

Triggers: Scaling anti-patterns: blocking I/O in async, unbounded reads, SQL SELECT without LIMIT, Regex::new() in a hot path, etc.

These are mostly Info severity — CI rarely blocks on them. When you see them: either fix the pattern (prefer tokio::fs over std::fs in async) or suppress with a short reason:

// toestub-ignore(scaling/blocking-in-async) — intentional sync read at startup
let config = std::fs::read_to_string(path)?;

See TOESTUB scaling rules SSOT for all 14 sub-rule IDs.


Same-line inline suppression (preferred for one-offs):

// toestub-ignore(rule/id) — short reason why
fn the_function() { ... }

Persistent suppression contract (for intentional waivers, especially legacy files): add an entry to contracts/toestub/suppressions.v1.json:

{
"rule": "arch/god_object",
"path": "crates/vox-oratio/src/backends/candle_engine.rs",
"owner": "platform-ci",
"reason": "near-threshold at 499 lines; refactor tracked in wave-9",
"expires": "2026-07-01"
}

Schema: contracts/toestub/suppression.v1.schema.json. Before adding a suppression, refactor first. The suppression file is for genuine waivers, not for avoiding the work.