auv
AGENTS.md207 starsChanged 34 days agoApache-2.0View on GitHub
Concise but detailed reference for contributors working on AUV. Improve code when you touch it; avoid one-off patterns and keep the shared runtime model in view. - AUV turns application UI workflows into command-like, inspectable, replayable, and eventually shortcut-like operations. - AUV is not only a CLI wrapper and not a generic LLM agent. - Design around reusable typed operation APIs, first-party drivers, implicit run recording, artifact capture, replay, and inspection. - Keep CLI, MCP, library calls, and future UI…
- Installs packages
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,700 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository37 other files it gives its agents.
- .agents/skills/unsafe-checker/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .cursor/rules/rust-rustrover-cargo.mdcCursor rule
- ast-grepSkill
- auv-wayland-renderingSkill
- create-prSkill
- domain-cliSkill
- domain-cloud-nativeSkill
- domain-mlSkill
- domain-webSkill
- m01-ownershipSkill
- m02-resourceSkill
- m03-mutabilitySkill
- m04-zero-costSkill
- m05-type-drivenSkill
- m06-error-handlingSkill
- m07-concurrencySkill
- m09-domainSkill
- m10-performanceSkill
- m11-ecosystemSkill
- m12-lifecycleSkill
- m13-domain-errorSkill
- m14-mental-modelSkill
- m15-anti-patternSkill
- rust-call-graphSkill
- rust-code-navigatorSkill
- rust-deps-visualizerSkill
- rust-refactor-helperSkill
- rust-symbol-analyzerSkill
- rust-trait-explorerSkill
- simple-englishSkill
- unsafe-checkerSkill
- use-buf-pluginsSkill
- use-bufSkill
- use-pixiSkill
- use-protobufSkill
- auvSkill
The file
Show its rules and text
We split this AGENTS.md into the rules it gives an agent
92 rules. About 0 are common, 68 are distinctive, and 24 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈68
Distinctive · estimate
This author's own choices. Worth a look.
24
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 14
Keep CLI, MCP, library calls, and future UI surfaces on the same execution model.
- Distinctive: line 16
Prefer explicit boundaries between operation execution, drivers, Rust command frontends, run storage, and reference documentation.
- Very specific: line 18
Use docs/TERMS_AND_CONCEPTS.md as the shared vocabulary for run recording, inspection, trace data, artifacts, and viewer-facing APIs.
- Very specific: line 20
When a design introduces or changes a core term, update docs/TERMS_AND_CONCEPTS.md instead of defining the term only inside a transient …
- Distinctive: line 76
Before editing, classify the change as one of: bug fix, test-only, docs-only, narrow refactor, or approved feature.
- Distinctive: line 86
Do not implement TODOs, roadmap notes, or future-phase designs unless the owner names that slice.
- Distinctive: line 88
Do not run broad repository scans and turn the findings into drive-by changes.
- Distinctive: line 90
Do not mix unrelated cleanup into behavior changes.
- Distinctive: line 95
Avoid ad-hoc compatibility shims.
- Distinctive: line 104
When a good idea appears mid-task, do not implement it inline.
- Distinctive: line 108
When you decide *not* to implement something that a reader could plausibly expect — a field, an enum variant, a branch, an algorithm stage, …
- Distinctive: line 156
Keep visual presentation separate from input delivery:
- Distinctive: line 199
Run recording persists evidence on the AUV side from the same references.
- Distinctive: line 200
Do not route evidence through the client.
- Distinctive: line 201
Only caller-owned images may be uploaded as pixels.
- Distinctive: line 223
Inspection/viewer APIs: Read durable run data and artifacts.
- Distinctive: line 294
Do not treat CLI as the only architecture surface.
- Distinctive: line 300
Keep frontend entrypoints lean.
- Distinctive: line 302
Before planning or writing new utilities, commands, driver helpers, operation helpers, or artifact builders, search for existing internal …
- Distinctive: line 305
If the logic could become shared project infrastructure, propose the shared boundary instead of adding a one-off local copy.
- Distinctive: line 307
When modifying code, check for small, minimal progressive refactors that make the touched area clearer.
- Distinctive: line 309
Keep changes scoped to the task.
- Distinctive: line 311
Do not add backward-compatibility guards by default.
- Distinctive: line 320
Prefer idiomatic Rust naming:
- Distinctive: line 324
Keep public APIs small and documented.
- Distinctive: line 327
Avoid hardcoded Unix, macOS, or Windows path literals unless the path is truly platform-defined.
- Very specific: line 329
Prefer Path, PathBuf, component joins, and path-safe arguments over string concatenation.
- Distinctive: line 331
Do not move every literal into a constant.
- Very specific: line 338
Use observation sparingly.
- Very specific: line 345
Keep third-party names intact (for example Apple's VNRecognizedTextObservation).
- Distinctive: line 352
Prefer names that rely on the module boundary for context instead of repeating product, platform, protocol, or transport prefixes inside …
- Distinctive: line 360
Use nouns for resolved domain concepts and verbs for transformations or side effects.
- Distinctive: line 362
When a function derives a policy, configuration, selector, or trace decision from an event or request, name the domain result explicitly so …
- Distinctive: line 365
Avoid names that encode multiple layers of ownership into one symbol.
- Distinctive: line 366
If a name needs several qualifiers to be understandable, reconsider the module boundary or introduce a clearer local concept.
- Distinctive: line 368
Use dependency injection only at real external boundaries: filesystem, process, clock, environment, OS APIs, accessibility services, window …
- Very specific: line 371
Do not introduce Dependencies or Deps structs for internal functions that only call sibling helpers or forward parameters.
- Distinctive: line 373
Add clear, concise comments for utilities, parsing, OS interaction, accessibility traversal, geometry/math, FFI, scheduling, artifact …
- Distinctive: line 377
Avoid comments that repeat what the code already says.
- Distinctive: line 378
When moving, refactoring, fixing, or updating code, keep existing comments intact and move them with the code.
- Distinctive: line 380
If a comment is truly unnecessary, replace it with a clearer comment or remove it only when the surrounding code fully preserves the …
- Very specific: line 387
When using a workaround, add a NOTICE: comment explaining why it is needed, the root cause, and the removal condition.
- Distinctive: line 389
If a workaround was validated through SwiftPM, SourceKit, generated bridge output, platform documentation, or dependency source, include …
- Distinctive: line 398
Add regression tests for behavior changes and keep them narrow.
- Very specific: line 399
Use cargo test for the full suite and include regression tests for bug fixes.
- Distinctive: line 403
Prefer a unit test. If that is not possible, use the smallest higher-level automated test or recorded fixture that can still reproduce the …
- Distinctive: line 405
When a regression test maps to an external report, include the tracker identifier in the test name when practical.
- Distinctive: line 407
Add the report link as a comment directly above the regression test.
- Distinctive: line 410
Test through stable public behavior.
- Distinctive: line 411
Do not create new exports, dependency bags, wrapper services, or alternate code paths only to make private implementation details mockable.
- Distinctive: line 413
Avoid smoke-only tests for behavior changes.
- Distinctive: line 416
Prefer explicit assertions over overly broad table-driven tests.
- Distinctive: line 417
Use tables when the cases share the same behavior and the table improves readability.
- Distinctive: line 421
Use this root-cause block format in regression tests when relevant:
- Distinctive: line 434
Prefer deep modules over shallow modules.
- Distinctive: line 438
Do not split code by execution order alone.
- Distinctive: line 441
Keep cohesive domain flows together until there is proven pressure to split.
- Distinctive: line 444
Before creating a new service, trait, context object, or dependency struct, verify that it adds policy, validation, state, retry/error …
- Distinctive: line 447
If a new abstraction does not add those things, keep the logic as a private helper or inline it.
- Distinctive: line 449
Before defining a new reusable primitive — a struct, enum, type alias, constant, or shared helper — search the workspace (owning/domain …
- Distinctive: line 456
If one almost fits (missing a derive, method, or variant), extend it in its owning crate.
- Distinctive: line 458
Add a new primitive only for a genuinely distinct concept, never an ad-hoc copy.
- Distinctive: line 463
Avoid pass-through services and traits that only forward arguments to another layer with a similar signature.
- Distinctive: line 471
Do not extract tiny one-call helper functions just to name an implementation step, reduce line count, reduce nesting, or create a test seam.
- Distinctive: line 476
Keep reusable domain contracts and rendering/building logic in the crate or module that owns that domain.
- Distinctive: line 480
Prefer early returns and simple control flow when it improves readability.
- Distinctive: line 481
Do not introduce pass-through helpers or shallow modules solely to reduce indentation.
- Very specific: line 486
Prefer capability-oriented module names for platform-native interop layers, such as screen, window, tree, keyboard, clipboard, app, and …
- Very specific: line 489
Keep FFI and generated binding details behind narrow modules named native, binding, or ffi.
- Very specific: line 491
Do not make dependency names such as swift_bridge or broad terms such as bridge into durable public namespaces.
- Very specific: line 498
When adding a new Swift package or restructuring Swift sources, use Swift tooling such as swift package init to create the package skeleton …
- Distinctive: line 509
After generating those files, use SwiftPM-side checks so generated bridge types are visible to the IDE:
- Distinctive: line 513
Do not commit generated directories.
- Very specific: line 517
When a change touches Rust/Swift FFI declarations or Swift native source files, rerun scripts/generate-swift-bridge before validating.
- Distinctive: line 519
Run the SwiftPM build for every touched Swift package.
- Very specific: line 520
Treat SwiftPM and SourceKit errors as real compatibility issues even when cargo check succeeds.
- Distinctive: line 522
Keep availability guards, generated bridge types, and IDE-visible imports current.
- Very specific: line 530
Do not create or use docs/superpowers/specs/ or docs/superpowers/plans/ for this repository.
- Very specific: line 535
When an implementation is mostly complete, update durable reference material in the owning responsibility folder and its INDEX.md.
- Distinctive: line 537
Add, merge, or revise reference docs so completed and partially completed work is discoverable outside the original plan or spec.
- Distinctive: line 540
When editing design docs, preserve open questions and clearly label provisional names so the team can review them before implementation.
- Distinctive: line 542
When a document records a finished but non-active vertical proof, move it out of active references into an archive path and leave only a …
- Very specific: line 549
Use docs/ai/references/<responsibility>/ for durable project reference material: accepted design notes, implementation handoffs, evidence …
- Very specific: line 556
Use docs/archive/verticals/ for archived proofs that should remain recoverable but must not continue to bias active roadmap decisions.
- Very specific: line 558
Use docs/ai/explanations/ for committed explanatory material: tutorials, interactive explainers, conceptual walkthroughs, diagrams, and …
- Distinctive: line 562
Prefer English for committed explanations unless the user explicitly asks for another language.
- Very specific: line 567
Use docs/notes/<owner>/ for personal, exploratory, or scratch material, including rough HTML demos, temporary investigation notes, local …
- Very specific: line 570
Do not commit notes from docs/notes/<owner>/ unless the user explicitly asks for that exact material to be committed.
- Very specific: line 572
If a note becomes generally useful, move or rewrite it into docs/ai/explanations/ or docs/ai/references/ as appropriate before committing.
- Distinctive: line 578
Run formatting and tests before submitting changes that touch Rust code.
- Very specific: line 579
Use <type>(<crate-name>): <message> for code commit subjects and PR titles.
- Very specific: line 580
Use the exact crate name, for example feat(auv-driver-linux): add uinput support or refactor(auv-driver-common): share key parsing.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
AUV Agent Guide
Concise but detailed reference for contributors working on AUV. Improve code when you touch it; avoid one-off patterns and keep the shared runtime model in view.
Project Mission
- AUV turns application UI workflows into command-like, inspectable, replayable, and eventually shortcut-like operations.
- AUV is not only a CLI wrapper and not a generic LLM agent.
- Design around reusable typed operation APIs, first-party drivers, implicit run recording, artifact capture, replay, and inspection.
- Keep CLI, MCP, library calls, and future UI surfaces on the same execution model.
- Prefer explicit boundaries between operation execution, drivers, Rust command frontends, run storage, and reference documentation.
- Use
docs/TERMS_AND_CONCEPTS.mdas the shared vocabulary for run recording, inspection, trace data, artifacts, and viewer-facing APIs. - When a design introduces or changes a core term, update
docs/TERMS_AND_CONCEPTS.mdinstead of defining the term only inside a transient spec.
Many project details are still undecided. During design and implementation, communicate with users frequently and clearly to avoid misunderstandings, premature naming decisions, and avoidable rework.
Project Phase: Restore The AUV Core Lane
AUV is currently pulling its active roadmap back to the Application Use Via core: invoke, run recording, artifacts, inspection, app-local Rust commands, and distill/compile/run reuse across frontends. The former SkillBundle surface has been retired; do not reintroduce bundle execution, export, or verification as compatibility. The important work is to make the remaining execution surfaces agree on one shared execution model. Prefer changes that tighten or reconnect the existing core responsibilities over polishing one archived vertical proof.
There is no auv-runtime package or root Cargo package. Runtime is an
architectural responsibility distributed across typed operation modules,
frontend roots, drivers, and auv-tracing; do not recreate a catch-all runtime
crate without an owner-approved producer/consumer need.
The macOS AX copilot work remains valuable, but it is no longer the active
product lane. Treat candidate-action as a frozen archived vertical proof. Do
not present it as AUV itself, do not expand it with new action classes or
product polish, and do not route new roadmap work through TextEdit-only proof
paths.
Good convergence work usually has one of these shapes:
- Defines or tightens a shared contract in
docs/TERMS_AND_CONCEPTS.md, its owning domain crate, run records, artifacts, or typed command facts. - Reconnects invoke and typed Rust command surfaces so CLI, library, MCP, and future UI frontends share the same typed execution path.
- Connects an existing producer to an existing consumer with typed evidence,
for example
RecognitionResult -> CandidateRef -> action -> app-owned result. - Aligns typed driver results with tracing evidence, for example
InputActionResult -> app-owned result -> tracing events/artifacts. - Fixes a reproduced bug in a narrow path and adds a regression test.
- Turns a known boundary into explicit metadata, failure layers, fallback reasons, or validation errors.
- Finishes an owner-approved slice without expanding it into adjacent roadmap work.
Poor convergence work looks like broad cleanup, TODO chasing, opportunistic helper extraction, speculative backends, or implementing future APIs just because a doc mentions them. It also includes continuing to deepen the archived AX copilot vertical and then calling that AUV progress. If the change adds new surface area, it needs an explicit reason tied to the current contract.
Scope Discipline
Public capability claims must name an evidence level and link to current evidence. A live probe is not a support claim, and compilation is not behavior.
Before editing, classify the change as one of: bug fix, test-only, docs-only, narrow refactor, or approved feature. If none fits, ask for a smaller slice.
Some missing pieces are intentional deferrals, some are incomplete work, and some are real bugs. Do not guess which one you are looking at. Classify the gap from evidence, failing tests, owner instructions, or existing reference docs before implementing anything.
Scope rules:
- Do not implement TODOs, roadmap notes, or future-phase designs unless the owner names that slice.
- Do not run broad repository scans and turn the findings into drive-by changes. Search only to understand the assigned slice.
- Do not mix unrelated cleanup into behavior changes. Mention cleanup opportunities as follow-up candidates instead.
- Cross-layer changes are allowed when they are the approved contract slice, but the dependency direction must be clear. Example: contract type -> driver artifact -> read-side inspector test.
- Avoid ad-hoc compatibility shims. Versioned read compatibility for existing run artifacts or public records is allowed when the migration boundary and tests are explicit.
Owner approval means the owner named the function/module/behavior, accepted a concrete proposal, or asked for a specific next slice. A doc mentioning a future feature, a TODO marker, or a change that feels like "the obvious next thing" is not approval.
When a good idea appears mid-task, do not implement it inline. Record it as a candidate next slice with one sentence explaining why it matters, then finish the current slice.
When you decide not to implement something that a reader could plausibly
expect — a field, an enum variant, a branch, an algorithm stage, an API
surface, a fallback path, or any other surface that has been considered and
intentionally left out for the current slice — leave a TODO: or NOTICE:
marker at the type or call site where the deferral lives. The goal is to
make intent visible: a future reader (Codex, Claude, the owner, a reviewer)
must be able to tell not yet, on purpose apart from forgot to write it.
A missing marker forces the next reader to guess and frequently produces
unwanted scope expansion when an agent treats the absence as a gap.
A useful deferral marker names three things in one short comment: the gap
(what was considered but omitted), the reason it is deferred (why it does
not belong in this slice), and the trigger that would unlock it (what
condition or owner approval would re-open the decision). When the deferral
is already covered by a reference doc, the inline marker may simply cite
that doc instead of restating the rationale — for example,
// TODO(view-memory-v1): persistence deferred, see view-parser-view-memory-v0.md.
The rule is that something at the code site must point a reader to the
intentional gap.
Apply this discipline to:
- Enum variants you considered but chose not to add.
- Struct fields you considered but did not add.
- Algorithm stages, fallback paths, or recovery branches you reserved but did not implement.
- API surfaces you chose to keep private, omit, or stub for the current slice.
- Reader-side checks that mirror a producer-side guarantee (such as version rejection on a wire-shape field) when only the producer side has landed.
A deferral marker is not approval to implement the deferred work later without owner involvement. It is documentation of an existing decision so the decision survives the next read of the code.
Current Contract Seam
The active input-delivery seam is:
typed command or app-owned operation
-> auv-driver capability
-> InputActionResult
-> direct app-owned result + tracing event/artifact
-> separate verification when semantic success is requiredKeep visual presentation separate from input delivery:
auv-driver-overlay-macosis a visual trust/debug adapter. It may show an AUV cursor, a user cursor, movement, or click ripples, but it does not prove semantic success and must not be treated as the input backend.auv-driver/auv-driver-macosowns typed input delivery such asWindowTargetedMouse,WindowTargetedKeyboard, foreground fallback, disturbance metadata, attempts, and fallback reasons.- Command and app modules should consume or map typed driver results. Do not grow a parallel action-result schema unless a concrete gap is first documented.
- Verification remains separate from activation. A successful click, AX press,
or overlay animation is not semantic success without a verification result or
an explicit
activation_onlyboundary.
This seam stays in AUV core because multiple command and app paths depend on the shared driver result and tracing artifact.
The RecognitionResult -> Candidate promotion gate (candidate_promotion +
stability) was retired on 2026-07-23 (branch
refactor/retire-candidate-promotion-seam). The archived candidate-action
removal (#88, 2026-07-07) had already deleted its recording, read-side, and
execution consumers, leaving both modules with zero production callers and used
only by their own #[cfg(test)] blocks. Do not reintroduce this
promotion/stability seam without an owner-approved slice that names a concrete
production consumer.
Image Payloads
Captured pixels are large. One Retina window capture is about 25 MB of RGBA, and a display capture about 80 MB. Treat image bytes as a resource that the Runner owns. Do not treat them as ordinary response data.
- An API response must not carry full image pixels unless the caller explicitly asked for them. Return a reference plus metadata instead: bounds, origin, pixel size and scale. Add an explicit fetch for pixels, with bounded size and encoding.
- A client must never have to send pixels back that AUV produced. An operation on a capture that AUV made, such as OCR, detection or crop, must accept a reference to that capture.
- Results and streams, such as find-text evidence, scroll-until steps and recent frames, return references, metadata or bounded thumbnails by default. Full frames are opt-in.
- Run recording persists evidence on the AUV side from the same references. Do not route evidence through the client.
- Only caller-owned images may be uploaded as pixels. An example is an image the user supplies.
Captures, find-text evidence, scroll-until updates and OCR already
follow this rule: they use CaptureRef, and GetCaptureImage is the explicit
pixel fetch (see "Capture Frame" in docs/TERMS_AND_CONCEPTS.md). One existing
API predates it: ListRecentFramesResponse frames
(TODO(recent-frames-capture-refs)). Do not copy its shape into new APIs.
Architecture Surfaces
- Runtime responsibility: Typed operation modules own execution semantics;
frontend roots own run-context lifecycle;
auv-tracingowns recording and artifact persistence. This is not represented by an aggregate runtime crate. - Drivers: Expose platform or application capabilities through narrow, capability-oriented APIs.
- Rust operation crates: Describe reusable app/domain workflows through typed Rust APIs and app-local commands.
- Command frontends: Parse and present user-facing commands; they should call typed command or operation interfaces rather than duplicate behavior.
- Run storage: Owns durable records, artifacts, trace data, and replayable inputs.
- Inspection/viewer APIs: Read durable run data and artifacts; do not depend on transient CLI-only behavior.
- Reference docs: Record accepted terminology, design decisions, evidence, and implementation handoffs that should survive beyond a task thread.
Key Path Index
crates/auv-cli-invoke/: typed invoke commands, registry, direct results, and command-local argument parsing.crates/auv-cli/src/: root CLI, built-in MCP frontend, session frontend, and frontend-owned tracing contexts.crates/auv-tracing/: run contexts, trace dispatch, artifact persistence, and write-side stores.crates/auv-driver*/: shared and platform-specific driver capabilities.docs/README.md: documentation layout, placement rules, and quick entry points.docs/TERMS_AND_CONCEPTS.md: shared vocabulary for core AUV concepts.docs/ai/references/INDEX.md: responsibility-folder index for reference notes (start here when browsing references).docs/ai/references/<responsibility>/: durable reference notes by duty (runtime, invoke-cli, scan, apps/, archive/, …), plus evidence packs and handoffs.docs/ai/explanations/: committed tutorials, explainers, walkthroughs, and diagrams.docs/notes/<owner>/: personal or exploratory scratch material that should not be committed unless explicitly requested.
Commands
- Build
cargo build: compile the workspace in debug mode.cargo run: build and run the current CLI binary locally.
- Test
cargo test: run Rust unit and integration tests.
- Format and lint
cargo fmt: format Rust code usingrustfmt.cargo fmt --check: verify formatting without modifying files.cargo clippy --all-targets --all-features: run lint checks across the workspace.
- Development shell
nix develop: enter the repository development shell when using the provided flake.
Python Tooling
- Pixi is required only for Python or model work: changes to Python files,
pixi.toml,pixi.lock, Python package metadata, or model and evaluation environments. Rust, JavaScript, Protobuf, and documentation work does not need Pixi. - Load
.agents/skills/use-pixi/SKILL.mdbefore changing Pixi manifests, dependencies, environments, tasks, orpixi.lock. - Pixi owns the Python interpreter, Ruff, ty, root Python tasks, and
pixi.lockthrough the rootpixi.toml. Do not run barepip installor create ad-hoc virtual environments for repository Python code. - The
defaultenvironment carries only Ruff and ty, with no Python interpreter, so the workspace does not pin one Python version. Each Python package (an eval, a model tool) adds a feature that pins its ownpythonand dependencies, composed into a named environment, for exampleosworld = ["osworld"]. Packages can then use different Python versions. - Each Python package's
pyproject.tomlowns its runtime dependencies. Edit it first, then runpixi lock. Usepixi addonly for environment-only tools. ruff.tomlandty.tomlhold lint, format, and type-check policy. Python uses Ruff's default four-space indentation, not the Rustrustfmt.tomlsetting. A package that targets another Python version adds its ownruff.tomlwithextend = "../../ruff.toml"and atarget-version, and runs ty in its environment with its own project configuration.pixi run --locked checkruns the Ruff format check, Ruff lint, and ty.
Development Practices
- Do not treat CLI as the only architecture surface.
- Design changes should account for library calls, CLI frontends, run recording, replay, and inspection.
- Favor clear module boundaries; shared behavior belongs behind operation, driver, storage, Rust operation, or inspection boundaries rather than local one-off helpers.
- Keep frontend entrypoints lean; move reusable policy, validation, recording, replay, and persistence behavior into the modules that own those decisions.
- Before planning or writing new utilities, commands, driver helpers, operation helpers, or artifact builders, search for existing internal implementations first.
- If the logic could become shared project infrastructure, propose the shared boundary instead of adding a one-off local copy.
- When modifying code, check for small, minimal progressive refactors that make the touched area clearer.
- Keep changes scoped to the task; do not start broad cleanup or compatibility work unless the current change depends on it.
- Do not add backward-compatibility guards by default. If extended support is needed, document the compatibility boundary, why it matters, and the expected post-refactor shape before adding extra branches.
Rust Style
- Rust code uses the 2024 edition.
- The repository
rustfmt.tomlsets two-space indentation (tab_spaces = 2). - Prefer idiomatic Rust naming:
snake_casefor functions, modules, and variables.PascalCasefor types and traits.SCREAMING_SNAKE_CASEfor constants.
- Keep public APIs small and documented.
- For design terms that are still under discussion, mark them as provisional in docs rather than stabilizing them through code names too early.
- Avoid hardcoded Unix, macOS, or Windows path literals unless the path is truly platform-defined.
- Prefer
Path,PathBuf, component joins, and path-safe arguments over string concatenation. - Do not move every literal into a constant. One-time or two-time values should remain near usage when locality is clearer.
- For retry, timeout, backoff, geometry tolerance, and limit values, avoid one broad constant that silently governs unrelated behavior.
Naming & Comments
- Use
observationsparingly. Reserve it for information collected to inform the next action in a perception/decision/action loop. A capture, frame, query response, stored record, state snapshot, or streamed update is not an observation merely because it was read or emitted. Prefer its concrete domain name, such asCapturedFrame,ParsedViewport,FrameItem,DeviceStatus,ReadResult, orScrollUntilUpdate. Even in a decision loop, use the more specific name when it communicates the payload better. - Keep third-party names intact (for example Apple's
VNRecognizedTextObservation). When renaming first-party terms, migrate producers, consumers, proto/SDK fields, tests, and current documentation together. Add a migration notice to older design notes instead of rewriting historical evidence. Seedocs/ai/references/runtime/2026-10-08-domain-result-naming-migration.md. - Prefer names that rely on the module boundary for context instead of repeating product, platform, protocol, or transport prefixes inside every symbol.
- A well-named module should let exported functions use short action-first names; repeat the larger context only when the symbol crosses a boundary where that context is no longer obvious.
- Name functions after the domain operation they perform, not after the implementation layer that happens to contain them.
- Use nouns for resolved domain concepts and verbs for transformations or side effects.
- When a function derives a policy, configuration, selector, or trace decision from an event or request, name the domain result explicitly so callers understand what decision is being made.
- Avoid names that encode multiple layers of ownership into one symbol.
- If a name needs several qualifiers to be understandable, reconsider the module boundary or introduce a clearer local concept.
- Use dependency injection only at real external boundaries: filesystem, process, clock, environment, OS APIs, accessibility services, window servers, model runtimes, network, cache, and feature gates.
- Do not introduce
DependenciesorDepsstructs for internal functions that only call sibling helpers or forward parameters. - Add clear, concise comments for utilities, parsing, OS interaction, accessibility traversal, geometry/math, FFI, scheduling, artifact persistence, and architectural functions when the intent, invariant, or platform constraint is not obvious from names and local context.
- Avoid comments that repeat what the code already says.
- When moving, refactoring, fixing, or updating code, keep existing comments intact and move them with the code.
- If a comment is truly unnecessary, replace it with a clearer comment or remove it only when the surrounding code fully preserves the original context.
- Use markers:
TODO:follow-up work that is intentionally left for later.REVIEW:concerns that need another maintainer or design pass.NOTICE:magic numbers, workarounds, platform quirks, generated-code constraints, or important external context.
- When using a workaround, add a
NOTICE:comment explaining why it is needed, the root cause, and the removal condition. - If a workaround was validated through SwiftPM, SourceKit, generated bridge output, platform documentation, or dependency source, include the relevant file, command, issue, or URL in code-formatted text.
Testing Practices
- Focused unit tests live next to the code they cover with
#[cfg(test)]. - The current repo already has Rust unit coverage for invoke, tracing, driver, and CLI behavior.
- Add regression tests for behavior changes and keep them narrow.
- Use
cargo testfor the full suite and include regression tests for bug fixes. - For any investigated bug or issue, try to reproduce it first with a test-only reproduction before changing production code.
- Prefer a unit test. If that is not possible, use the smallest higher-level automated test or recorded fixture that can still reproduce the behavior.
- When a regression test maps to an external report, include the tracker identifier in the test name when practical.
- Add the report link as a comment directly above the regression test.
- For local investigations without a tracker, leave a short root-cause comment when it would help future maintainers understand why the test exists.
- Test through stable public behavior.
- Do not create new exports, dependency bags, wrapper services, or alternate code paths only to make private implementation details mockable.
- Avoid smoke-only tests for behavior changes.
- Assert the observable output, trace record, artifact, replay input, command result, or platform-facing call that would have caught the original failure.
- Prefer explicit assertions over overly broad table-driven tests.
- Use tables when the cases share the same behavior and the table improves readability; keep one-off or highly distinct scenarios as separate tests with clear names.
Use this root-cause block format in regression tests when relevant:
// ROOT CAUSE:
//
// If <condition>, <unexpected behavior> happened because <reason>.
//
// Before the fix, <old behavior>.
// The fix keeps <new invariant or behavior>.Module Design
- Prefer deep modules over shallow modules.
- A module should hide a meaningful decision: policy, persistence boundary, protocol/schema contract, scheduling semantics, replay semantics, artifact layout, driver capability, platform permission rule, or lifecycle concern.
- Do not split code by execution order alone.
- A module boundary should represent a stable responsibility that can be understood without reading all sibling files.
- Keep cohesive domain flows together until there is proven pressure to split.
- A 200-400 line cohesive Rust module is preferable to several shallow modules that pass the same context or options through each other.
- Before creating a new service, trait, context object, or dependency struct, verify that it adds policy, validation, state, retry/error handling, IO isolation, a reusable abstraction, or a platform boundary.
- If a new abstraction does not add those things, keep the logic as a private helper or inline it.
- Before defining a new reusable primitive — a struct, enum, type alias, constant, or shared helper — search the workspace (owning/domain crate and dependencies) for one that already carries the concept. Search by name (rg/grep) and by shape (ast-grep, else rg/grep), not exact name alone.
- Reuse an existing primitive when it fits; import a dependency's instead of copying it. A primitive that re-expresses another's shape and meaning is a duplicate — delete it and reuse the original.
- If one almost fits (missing a derive, method, or variant), extend it in its owning crate; do not fork a local variant.
- Add a new primitive only for a genuinely distinct concept, never an ad-hoc copy. Same-shape primitives are allowed only when meanings differ on purpose (ScreenPoint vs WindowPoint) and the name shows it; place a reusable primitive in its domain crate, and keep one private only when local and not a shared-concept duplicate.
- Avoid pass-through services and traits that only forward arguments to another layer with a similar signature.
- Adjacent layers should expose different abstractions:
- CLI frontends parse and present.
- Typed command and operation interfaces execute.
- Drivers expose capabilities.
- Storage owns persistence semantics.
- Inspectors read durable run data.
- Do not extract tiny one-call helper functions just to name an implementation step, reduce line count, reduce nesting, or create a test seam.
- Extract a helper only when it is reused by multiple production call sites, hides non-trivial branching, IO, parsing, normalization, error policy, or lifecycle logic, or names a stable domain concept.
- Keep reusable domain contracts and rendering/building logic in the crate or module that owns that domain.
- Frontend entrypoints should wire dependencies and call those boundaries instead of inlining large reusable contracts.
- Prefer early returns and simple control flow when it improves readability.
- Do not introduce pass-through helpers or shallow modules solely to reduce indentation.
Platform-Native Interop
- Prefer capability-oriented module names for platform-native interop layers,
such as
screen,window,tree,keyboard,clipboard,app, andpermission. - Keep FFI and generated binding details behind narrow modules named
native,binding, orffi. - Do not make dependency names such as
swift_bridgeor broad terms such asbridgeinto durable public namespaces.
macOS Swift Packages
- For macOS Swift native code, prefer
swift-bridgefor typed Rust/Swift interop unless a design explicitly chooses a different boundary. - When adding a new Swift package or restructuring Swift sources, use Swift
tooling such as
swift package initto create the package skeleton instead of hand-writing the project structure from scratch. - Adapt the generated manifest and sources to the repository layout after SwiftPM creates the skeleton.
- The macOS Swift packages use generated
swift-bridgetypes that are produced by Cargo during the real build. - For SourceKit or IDE indexing, run
scripts/generate-swift-bridgeto generate ignored files under:crates/auv-driver-macos/native/swift/Sources/AuvMacosNative/Generated/crates/auv-driver-overlay-macos/native/swift/Sources/AuvMacosOverlayNative/Generated/
- After generating those files, use SwiftPM-side checks so generated bridge
types are visible to the IDE:
cd crates/auv-driver-macos/native/swift && swift buildcd crates/auv-driver-overlay-macos/native/swift && swift build
- Do not commit generated directories.
- Regenerate bridge files after changing:
crates/auv-driver-macos/src/native/binding.rscrates/auv-driver-overlay-macos/src/native/binding.rs
- When a change touches Rust/Swift FFI declarations or Swift native source
files, rerun
scripts/generate-swift-bridgebefore validating. - Run the SwiftPM build for every touched Swift package.
- Treat SwiftPM and SourceKit errors as real compatibility issues even when
cargo checksucceeds. - Keep availability guards, generated bridge types, and IDE-visible imports current.
Documentation Workflow
- During active design or implementation, write specs, plans, and working notes
under
docs/ai/references/<responsibility>/(seedocs/ai/references/INDEX.md). - Do not create or use
docs/superpowers/specs/ordocs/superpowers/plans/for this repository. If a skill suggests those default locations, treat this repository guide as the override and place the document in the matching responsibility folder underdocs/ai/references/instead. - In-progress documents are the source of truth while the work is underway.
- When an implementation is mostly complete, update durable reference material
in the owning responsibility folder and its
INDEX.md. - Add, merge, or revise reference docs so completed and partially completed work is discoverable outside the original plan or spec. Prefer folding intermediate handoffs into one durable note rather than leaving long slice-code chains.
- When editing design docs, preserve open questions and clearly label provisional names so the team can review them before implementation.
- When a document records a finished but non-active vertical proof, move it out
of active references into an archive path and leave only a short tombstone at
the old location. Do not leave archived roadmap context sitting in
docs/ai/references/where agents will keep treating it as current guidance.
Documentation Placement
- Use
docs/ai/references/<responsibility>/for durable project reference material: accepted design notes, implementation handoffs, evidence packs, coverage reports, and records that should be useful to reviewers after the original task context is gone. Do not use engineering slice codes as folder or navigation labels. - Content in
docs/ai/references/should describe the current project state or a clearly labeled historical decision. - Use
docs/archive/verticals/for archived proofs that should remain recoverable but must not continue to bias active roadmap decisions. - Use
docs/ai/explanations/for committed explanatory material: tutorials, interactive explainers, conceptual walkthroughs, diagrams, and documents whose purpose is to teach or clarify an idea rather than record project evidence. - Prefer English for committed explanations unless the user explicitly asks for another language.
- For explanatory HTML files, name the file with the relevant module or feature
name in kebab case as the prefix, followed by a short description, for example
scroll-scan-visual-row-band.html. - Use
docs/notes/<owner>/for personal, exploratory, or scratch material, including rough HTML demos, temporary investigation notes, local run logs, and drafts that are not ready to be shared as durable project references. - Do not commit notes from
docs/notes/<owner>/unless the user explicitly asks for that exact material to be committed. - If a note becomes generally useful, move or rewrite it into
docs/ai/explanations/ordocs/ai/references/as appropriate before committing.
PR / Workflow Tips
- Run formatting and tests before submitting changes that touch Rust code.
- Use
<type>(<crate-name>): <message>for code commit subjects and PR titles. Use the exact crate name, for examplefeat(auv-driver-linux): add uinput supportorrefactor(auv-driver-common): share key parsing. - For changes across multiple crates, use the crate that primarily owns the
changed behavior. Do not replace its name with a generic layer such as
input. - For primarily documentation changes, including contributor instructions and
skills, use
chore(docs): <message>. - For repository tooling changes with no owning crate, use the relevant tooling scope instead of inventing a crate name.
- Pull requests should include:
- A short description.
- Relevant design or issue links.
- Verification commands run.
- Screenshots or trace artifacts when changing UI inspection, automation, or documentation visuals.
- Summarize changes, how they were tested, and follow-ups.
- Keep changes scoped.
- Improve legacy code you touch when the improvement is local and directly supports the task.
- Avoid one-off patterns.
Validation Commands
cargo fmt --checkcargo checkcargo testgit diff --checkcargo run --quiet -- invoke --helppixi run --locked check(only when Python files,pixi.toml,pixi.lock, or Python package metadata change)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

