feat: initial repo setup (Phase 0 scaffolding)

- 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
This commit is contained in:
glm-5.3-flash committed 2026-09-30 07:45:40 +00:00
1 parent 357311d27b
commit 7f7f70b220
10 files changed
+660 -12

No files matched your search

+175
View File
@@ -0,0 +1,175 @@
# 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`, `cargo clippy --all-targets -- -D warnings`,
`cargo fmt --check`, `cargo doc --no-deps` 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 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.
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.
2. **Error handling** — `thiserror` for library error types. 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. **`tokio` is the async runtime** — all I/O is async. Use
`tokio::sync` primitives (`oneshot`, `mpsc`) for lifecycle
correlation; `parking_lot` for short-held internal locks. Do not
introduce blocking I/O on the async path.
4. **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).
5. **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.
6. **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.
7. **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).
8. **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) and `cargo test --all-features`
pass if features are added.
9. **Naming** — Rust standard: `snake_case` for functions/variables/
modules, `PascalCase` for types/traits, `SCREAMING_SNAKE_CASE` for
constants.
10. **Module structure** — one module per file under `src/`, re-exported
from `src/lib.rs`. Public API surface is `lib.rs` re-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.
```bash
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, and `phase-0.md` (vision, prior art,
open questions, converged recommendation). Read it before non-trivial
work. The SDD process lives in `docs/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.md` tracks 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; its `AccessControl`/identity seam is the
authorization story for network-facing blob ops.
- 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.