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:
1 parent
44c35a96dd
commit
5462a9e560
1 file changed
+126
@@ -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.
|
||||
Reference in new issue
Block a user