- AGENTS.md: repo conventions adapted from alkcall/alksocks (store posture, multi-hash requirement, no-iroh-wire rule; no fuzz gate yet) - Cargo.toml + src/lib.rs: bare lean lib skeleton (tokio async, thiserror) - docs/research/phase-0.md: Phase 0 draft — vision, prior art (iroh-blobs store, gix-odb, alknet appfile probe, alkcall), OQ register, POC plan - .gitignore, LICENSE-APACHE/MIT - Re-pointed stale alknet/alkcall references in .opencode/agents/ and docs/sdd_process.md Verification: cargo build/test, cargo clippy --all-targets -- -D warnings, cargo fmt --check, cargo doc --no-deps — all pass
8.6 KiB
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:
- Make the change
- Verify:
cargo test,cargo clippy --all-targets -- -D warnings,cargo fmt --check,cargo doc --no-depsif docs changed - Inspect
git statusandgit diffbefore staging — stage only the intended files, never secrets - 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. git push origin main- 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 the wire format, a trait shape backends implement, or the hashing/verification story (one-way doors once consumers exist — see convention 7; nothing is wire-stable yet, but the first wire-format ADR must be written before the first consumer)
- 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.3-flash <glm-5.3-flash@alk.dev>). Do
not change git config, skip hooks, or use git commit -i.
Project Conventions (Rust / blob storage crate)
This is the blob storage crate — content-addressed blob storage in the
alk* family, inspired by iroh-blobs' store work but deliberately not a
fork of it. It sits downstream of alkcall (the call + channels substrate
its network operations ride, when they exist) and its first planned
consumer is alkgit (git object storage, where the iroh-blobs hashing
story collides with git's own object hashes). Status: Phase 0
(Exploration) — docs/research/ is the working state of the repo;
docs/architecture/ does not exist yet and no wire format, API shape,
or backend trait is decided. 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.
-
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. -
Error handling —
thiserrorfor library error types. No panics in library code. Nounwrap()orexpect()outside tests. If you reach forunwrap, the error path wasn't specified — stop and decide what should actually happen. For poisonedRwLock/Mutex, useunwrap_or_else(|e| e.into_inner())so a panic in one operation does not cascade to other operations. -
tokiois the async runtime — all I/O is async. Usetokio::syncprimitives (oneshot,mpsc) for lifecycle correlation;parking_lotfor short-held internal locks. Do not introduce blocking I/O on the async path. -
Substrate-agnostic by construction — the store layer must not know whether bytes arrive over the network, from a local writer, or get reassembled anywhere particular. iroh-blobs welds its store to its provider/ticket/postcard stack; this crate's defining posture is the opposite split: the store (put/get/verify against a hash) is its own layer, and transport/protocol concerns live above it or in feature-gated modules. This is the same inversion-point pattern as the alk* family (alktty
TtyBackend, alktunnels pump halves). -
Hashes are data, not identity of transport — the crate must tolerate multiple hash algorithms (the alkgit conflict: git's SHA-1/ SHA-256 object hashes vs iroh-blobs' BLAKE3). How the hash algorithm is abstracted (trait, enum, per-backend configuration) is a Phase 0/ 1 decision, not yet pinned. Do not hardcode a single algorithm.
-
Auth-gated operations ride the alkcall authorization seam — when network-facing operations exist, authorization happens via alkcall's
AccessControl/identity mechanisms (the producer/consumer model), not via an in-band invented auth scheme. Producer/consumer vocabulary, not "server"/"client" (alkcall ADR-022/037). Not yet pinned in detail — the ops surface is a Phase 0 question. -
Do not adopt iroh-blobs' wire surface — tickets, the postcard serialization, and the provider protocol are iroh-blobs' design-welded choices we have decided not to inherit. Reading
/workspace/iroh-blobs(a fresh upstream checkout) is encouraged for store-shape lessons (src/store, the kv + flat file backends); borrowing its conclusions is fine, wiring in its types, framing, or serialization as load-bearing dependencies is not (yet — the dependency posture is a Phase 0 question if a small pure piece, like bao outboard encoding, earns its place). -
Feature flags — substrate backends (kv, sqlite, flat fs) may be feature-gated if the need arises. The base crate should compile lean. Verify both
cargo test(default) andcargo test --all-featurespass if features are added. -
Naming — Rust standard:
snake_casefor functions/variables/ modules,PascalCasefor types/traits,SCREAMING_SNAKE_CASEfor constants. -
Module structure — one module per file under
src/, re-exported fromsrc/lib.rs. Public API surface islib.rsre-exports. The expected shape (pending Phase 0 convergence) separates the backend/store layer from any protocol/ops layer.
Verification Commands
Run these before committing. All must pass.
cargo test # full suite
cargo clippy --all-targets -- -D warnings
cargo fmt --check
cargo doc --no-deps # if docs changed
cargo publish --dry-run --allow-dirty # before a release
If feature flags are added, also run cargo test --all-features and
cargo clippy --all-features --all-targets -- -D warnings.
No fuzz targets exist yet for this crate. If/when a wire format is
pinned (Phase 1), a fuzz gate on the model of alkcall/alksocks (fuzz/
corpus replay on stable) is expected — until then ignore fuzzing.
Architecture Context
docs/research/— the Phase 0 (Exploration) state of this repo: research findings, POC records, andphase-0.md(vision, prior art, open questions, converged recommendation). Read it before non-trivial work. The SDD process lives indocs/sdd_process.md.docs/architecture/— does not exist yet (Phase 1 output). When it lands, the SDD process applies: specs describe WHAT,decisions/ADRs explain WHY,open-questions.mdtracks what's unresolved.- Key prior art (read-only, in the global workspace):
- iroh-blobs —
/workspace/iroh-blobs(fresh upstream checkout): the shape inspiration, specifically its store work (kv + flat file backends, bao verification, chunking). Its wire-surface choices (tickets, postcard, BLAKE3-only) are the ones we are deliberately diverging from. - gix-odb —
/workspace/git-oxide/gix-odb: git's own object database; the backend alkgit currently plans against and the hashing-algorithm baseline git actually uses. - alknet's blobs research —
/workspace/@alkdev/alknet/docs/research/alknet-filesystem/(alknet-blobs-external-store-probe.md,poc-summary.md): the appfile external-store probe — small blobs in a kv/sqlite-ish store, large blobs on the filesystem fallback, filename↔hash mapping. Written against an older iroh-blobs than the current checkout; re-verify conclusions before relying on them. - alkcall —
/workspace/@alkdev/alkcall(the substrate): call + channels; itsAccessControl/identity seam is the authorization story for network-facing blob ops.
- iroh-blobs —
- If a TODO references a design direction that a later ADR has decided against, the TODO is stale — remove it and align with the ADR. Do not implement the rejected design.