Add AGENTS.md: commit/push policy + project conventions

opencode auto-loads AGENTS.md as instructions, overriding the built-in
default of 'only commit when explicitly asked.' This repo's stance is
the opposite — commit and push when reasonable — which already matches
the custom agents in .opencode/agents/ (coordinator.md §5 'Push Main
After Every Merge', implementation-specialist.md §5 'Push immediately').

The file also surfaces the project conventions (no comments, OsRng for
nonces, zeroize-on-drop, thiserror/anyhow, no async, frozen wire format)
so they apply to all sessions, not just spawned implementation agents.

No code change. Restart opencode to load the new instructions.
This commit is contained in:
glm-5.2 committed 2026-08-10 11:41:35 +00:00
1 parent 44c35a96dd
commit 5462a9e560
1 file changed
+126
+126
View File
@@ -0,0 +1,126 @@
# AGENTS.md
Operating instructions for opencode agents working in this repo. opencode
auto-loads this file as instructions, overriding the built-in defaults for
this project. Custom agents in `.opencode/agents/` inherit these rules
unless their own prompts say otherwise.
## Git Workflow
**Commit and push when reasonable.** When a change is complete and
verified (build + lint + tests pass), commit and push to `origin/main`
without asking. This overrides the built-in default of "only commit when
explicitly asked."
The workflow:
1. Make the change
2. Verify: `cargo test --all-features`, `cargo clippy --all-features
--all-targets`, `cargo doc --no-deps --all-features` if docs changed
3. Inspect `git status` and `git diff` before staging — stage only the
intended files, never secrets
4. Write a concise commit message matching the repo style (see `git log
--oneline -10`). For multi-point changes, use a summary line plus a
body with bullet points and a verification block.
5. `git push origin main`
6. Report the commit hash and the verification summary
Exceptions — **do not** commit or push without asking:
- The change is exploratory / speculative (you're not sure the user wants
it kept)
- The user is actively reviewing the diff and may ask for changes
- The change touches published wire formats or semver-relevant public API
(this repo is on crates.io; `EncryptedData` is frozen per ADR-018)
- You'd be force-pushing, amending a published commit, creating an empty
commit, or skipping hooks
Never commit secrets, keys, or credentials. If a commit fails or hooks
reject it, fix the issue and create a new commit — do not amend the
failed one.
Git identity is preconfigured (`glm-5.2 <glm-5.2@alk.dev>`). Do not
change `git config`, skip hooks, or use `git commit -i`.
## Project Conventions (Rust / cryptographic library)
This is a cryptographic vault crate. The conventions below apply to all
work in `src/` and `tests/`. They mirror `.opencode/agents/
implementation-specialist.md` §Project Conventions and are repeated here
so they apply to every session, not just spawned implementation agents.
1. **No comments in code** unless the user explicitly asks. This is a
project-wide convention. Doc comments (`///`, `//!`) are fine and
expected on public API. Inline `//` comments only when the user asks
or when a non-obvious safety/correctness constraint would otherwise be
missed (e.g., "fresh per call — IV reuse under the same key is
catastrophic").
2. **Error handling** — `thiserror` for library error types, `anyhow` for
application code (this crate is a library; use `thiserror`). No panics
in library code. No `unwrap()` or `expect()` outside tests. If you
reach for `unwrap`, the error path wasn't specified — stop and decide
what should actually happen. For poisoned `RwLock`/`Mutex`, use
`unwrap_or_else(|e| e.into_inner())` so a panic in one operation does
not cascade to other operations.
3. **Cryptographic nonces use `OsRng`** — AES-GCM IVs and any other
cryptographic nonces must use `SysRng`/`OsRng` (or equivalent CSPRNG),
never `rand::random()`. IV reuse under the same key is catastrophic
for GCM (authenticity breaks, two-time-pad on plaintext). See
`docs/architecture/encryption.md` §Security Constraints.
4. **Secret material is zeroized on drop** — any type holding derived
keys, decrypted credentials, or other secret material must derive
`Zeroize` and `ZeroizeOnDrop`. Secrets must not linger in freed heap
memory. See `EncryptionKey` and `Seed` for the pattern.
5. **Feature flags** — `secp256k1` is a feature gate for the Ethereum
BIP-0032 derivation path. The base crate compiles lean (no networking,
no `tokio`, no `secp256k1` unless the feature is on). Verify both
`cargo test` (default) and `cargo test --all-features` pass.
6. **No `async`** — this crate is synchronous (`std::sync::RwLock`,
direct method calls). No `tokio` dependency (ADR-025). Do not
introduce `async`/`.await` or async-sync primitives.
7. **Naming** — Rust standard: `snake_case` for functions/variables/
modules, `PascalCase` for types/traits, `SCREAMING_SNAKE_CASE` for
constants.
8. **Module structure** — one module per file under `src/`, re-exported
from `src/lib.rs`. Public API surface is `lib.rs` re-exports.
9. **Wire format is frozen** — `EncryptedData` is a stable wire format
shared with `alknet-storage` and the TypeScript `@alkdev/storage`
consumer by type-level agreement (ADR-018). Fields, encoding, and
semantics are locked. No field may be removed or renamed; new fields
must be optional (default on deserialization) and must not change the
meaning of existing fields. The `salt` field is unused in v2 key
derivation (ADR-020) but retained for wire-format compatibility — do
not remove it.
## Verification Commands
Run these before committing. All must pass.
```bash
cargo test --all-features # full suite (~108 tests)
cargo test # default features (~101 tests)
cargo clippy --all-features --all-targets
cargo doc --no-deps --all-features # if docs changed
cargo publish --dry-run --all-features --allow-dirty # before a release
```
## Architecture Context
- `docs/architecture/` — the authoritative spec. Read it before
non-trivial changes. ADRs are numbered; OQs (open questions) track
resolved/deferred decisions.
- ADR-018 — vault standalone, `EncryptedData` wire format lock
- ADR-020 — HD derivation for encryption keys, salt unused in v2
- ADR-021 — key rotation via version-indexed derivation paths
- ADR-025 — local-only dispatch, no `async`/`tokio`/irpc
- If a TODO references a "Phase B" or a design direction that an ADR
has since decided against, the TODO is stale — remove it and align
the comments with the ADR. Do not implement the rejected design.