- backend.md: git/repo/update pinned as PATCH (omitted fields unchanged; present fields replaced wholesale) — R-3; 'already_exists' disclosure posture recorded (accepted create-scope oracle; resolve-side stays collapsed) — R-6; repo-id grammar pinned (owner/name segments, rejection- only parsing, percent-encoded flat record-file naming, two-placeholder http-route note) — R-5 - doors.md: alkssh hand-off tuple gains service + authorized-repo marker (ADR-016/D-3 amendment rounds missed this third tuple site) — R-4 - ADR-016: collapsed-space and broken code-span glitches — R-8 - AGENTS.md: lifecycle paragraph records both gate reviews complete and decomposition unblocked Verification: docs-only; cargo doc/test/clippy/fmt clean
223 lines
11 KiB
Markdown
223 lines
11 KiB
Markdown
# 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."
|
|
|
|
Commit in small, focused units — one commit per unit of work (a fix, a
|
|
feature, a doc change), not one large commit covering many topics. Push
|
|
regularly so work is never stranded locally.
|
|
|
|
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 in **conventional commits** style:
|
|
`<type>(<scope>): <summary>` — types are `feat`, `fix`, `docs`,
|
|
`chore`, `refactor`, `test`, `perf`, `build`, `ci`; the scope is
|
|
optional. 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
|
|
(crates will be published to crates.io once architecture lands; see the
|
|
ADRs in `docs/architecture/decisions/` for the stable-contract list once
|
|
it exists)
|
|
- 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 / protocol crate)
|
|
|
|
This is alkgit — a pure protocol crate (ADR-010, the alktty/alktunnels
|
|
template): the git smart protocol as producer/consumer halves on alkcall
|
|
channels (the `alk/git` ALPN), backend traits with a feature-gated
|
|
gitoxide (gix) implementation, no binary, no front doors (doors — alkhttp
|
|
`git` feature, alkssh — are family infrastructure; see
|
|
`docs/architecture/doors.md`). Single crate at the repo root (`src/`,
|
|
`tests/`). 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., "ACL must run before the first advertised ref line — ref
|
|
names leak repository existence").
|
|
|
|
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. Git protocol
|
|
sessions are long-lived streaming conversations; do not introduce
|
|
blocking I/O on the async path. Use `tokio::sync` primitives
|
|
(`oneshot`, `mpsc`) for correlation; `parking_lot` for short-held
|
|
internal locks.
|
|
|
|
4. **No secret material on the wire or in plaintext at rest** — the git
|
|
protocol, the call protocol payloads, and the metadata store carry no
|
|
private keys, API keys, tokens, or decrypted credentials. Stored
|
|
credential material lives in alkvault; metadata holds vault references.
|
|
Outbound credentials flow through `Capabilities` injected at the
|
|
assembly layer → `OperationContext.capabilities` → handler. See the
|
|
no-env-vars invariant below and the alkcall ADRs (ADR-010, ADR-017).
|
|
|
|
5. **No-env-vars invariant** — no handler reads outbound credentials from
|
|
any source other than `OperationContext.capabilities`. The credential
|
|
injection path is vault → assembly layer → `Capabilities` → handler.
|
|
This is a spec-level invariant, not a runtime convention.
|
|
|
|
6. **Visible-surface = authorized-surface** — the reason this project
|
|
exists (a self-hosted gitea got pwned via an internal API reachable
|
|
over the internet). Every operation exposed on the wire is gated by
|
|
alkcall's `AccessControl::check(peer_identity)`; ops with
|
|
`Visibility::Internal` are never wire-callable; no endpoint exists that
|
|
a caller cannot see themselves authorized for. There is no
|
|
unauthenticated endpoint unless a repo is explicitly public, and push
|
|
is always authenticated. This is a spec-level invariant.
|
|
|
|
7. **gitoxide for git primitives, no shelling out** — storage and pkt-line
|
|
come from the gix crates (pinned in the crate manifest). The
|
|
serving path never spawns the `git` binary (no GPL dependency, no
|
|
process-injection surface). The server half of the smart protocol is
|
|
ours; see `docs/research/git-protocol.md` for the inventory.
|
|
|
|
8. **License hygiene** — this project is MIT OR Apache-2.0. Never copy or
|
|
derive code from MPL-2.0-licensed reference projects; reading gitoxide
|
|
(MIT OR Apache-2.0) is fine. The policy and the rationale live in
|
|
`docs/research/reference-policy.md` — do not name the
|
|
incompatible-licensed project in docs, README, or commit messages.
|
|
|
|
9. **Wire formats are stable one-way doors** — once a wire surface is
|
|
published (the git smart protocol is defined upstream and not ours to
|
|
change; the one existing piece of alkgit-specific framing — the native
|
|
session preamble, ADR-016 — is pinned and in the OQ-03 freeze
|
|
inventory), its shape must not change. Protocol capability advertisement
|
|
is honest: never advertise what we don't serve.
|
|
|
|
10. **Feature flags** — optional surface is feature-gated: `gix`
|
|
(default-on; the backend implementations) and `sha256` (hash
|
|
algorithm passthrough; `sha1` is the default and pinned in the crate
|
|
manifest). The wire layer compiles without gix
|
|
(`default-features = false`). Verify both `cargo test` (default) and
|
|
`cargo test --all-features` pass if features are added.
|
|
|
|
11. **Bounded resources** — every protocol session carries wall-clock,
|
|
size, and round limits (max negotiation rounds, max receive-pack size,
|
|
session timeout). Git servers are internet-facing; unbounded loops and
|
|
unbounded buffers are bugs.
|
|
|
|
12. **Repo identity is registry-resolved** — repo names arriving on the
|
|
wire are IDs resolved against a server-side registry to configured
|
|
storage roots. Wire-supplied names are never used as filesystem paths
|
|
directly (path traversal is a protocol-level input, not a config
|
|
value).
|
|
|
|
13. **Naming** — Rust standard: `snake_case` for functions/variables/
|
|
modules, `PascalCase` for types/traits, `SCREAMING_SNAKE_CASE` for
|
|
constants.
|
|
|
|
14. **Module structure** — one module per file under `src/`, re-exported
|
|
from `src/lib.rs` (the alktty crate-root pattern). Public API surface
|
|
is `lib.rs` re-exports. Single crate at the repo root (ADR-010); the
|
|
gix backend implementation lives under the default-on `gix` feature;
|
|
`default-features = false` gives the wire/protocol layer only.
|
|
|
|
15. **Composability boundary ("ALPN as a service")** — alkgit is
|
|
front-door-blind: it consumes (identity, repo id, duplex stream,
|
|
limits) and depends on alkcall types only, never on alkhttp/alkssh,
|
|
and carries no http/channel-specific types below the stream. Doors
|
|
(alkhttp `git` feature, alkssh) are family infrastructure; a
|
|
downstream app embeds alkgit and brings its own doors. v1 is the
|
|
reduction to wire layer + backend traits + one gix implementation.
|
|
|
|
## 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 (per crate)
|
|
```
|
|
|
|
If feature flags are added, also run `cargo test --all-features` and
|
|
`cargo clippy --all-features --all-targets -- -D warnings`.
|
|
|
|
## Lifecycle Status
|
|
|
|
The project is in **SDD phase 1** (architecture committed, implementation
|
|
not yet begun). Phase 0 research is in `docs/research/`; the committed
|
|
architecture is `docs/architecture/` (ADR-010 is the structural
|
|
decision: pure protocol crate, `alk/git` ALPN, backend traits, no
|
|
binary/doors). POC code never merges to main — two modes: branch mode
|
|
(POC builds on repo code; git branch, findings merged into research
|
|
docs, branch dropped) or standalone mode (POC independent of repo code;
|
|
scratch project at `/workspace/<poc-name>`). POCs have relaxed
|
|
constraints (comments/unwrap acceptable) — they are exploration tools,
|
|
not production code. Open architecture questions live in
|
|
`docs/architecture/open-questions.md` (the active set: OQ-03 —
|
|
partially resolved, the publish freeze inventory — and OQ-05 —
|
|
sha256 policy, deferred on ecosystem need; OQ-16 — grant-key identity
|
|
namespace, deferred on the distributed phase. OQ-04 receive-pack, OQ-06
|
|
registry backing, and OQ-08 identity model are resolved: ADR-013,
|
|
ADR-012, ADR-011). Both gate reviews (001 pre-decomposition, 002
|
|
post-remediation) are complete and all their findings are resolved
|
|
(resolutions: ADR-015/016/017/018); the specs are in `reviewed` status
|
|
and decomposition into implementation tasks may begin.
|
|
|
|
## Architecture Context
|
|
|
|
- `docs/research/` — phase 0 research (current source of truth for design
|
|
direction):
|
|
- `vision.md` — vision, guiding principles, non-goals
|
|
- `gitoxide.md` — gix capability/version alignment (sha1 feature
|
|
pinning is mandatory; `default-features = false` without a hash
|
|
feature does not compile)
|
|
- `alk-stack.md` — alkcall/alkhttp/alktls/alkvault integration surface
|
|
- `git-protocol.md` — server-side smart-protocol inventory (what we
|
|
own: advertisement, ls-refs, fetch negotiation, receive-pack)
|
|
- `reference-policy.md` — license/reuse policy (MPL-2.0 prior art:
|
|
facts only, never code)
|
|
- `pocs.md` — POC-1..3 plan gating phase 0 completion
|
|
- Sibling crates (published, MIT OR Apache-2.0): `alkcall 0.8` (call +
|
|
channels RPC with ACL; `BiStream` is the git-session substrate),
|
|
`alkhttp 0.5` (HTTP serving + call adapters), `alktls 0.1` (rustls +
|
|
ACME), `alkvault 0.1` (secret encryption). Their architecture docs live
|
|
in their own repos; alkcall ADRs referenced above are at
|
|
`/workspace/@alkdev/alkcall/docs/architecture/decisions/`.
|
|
- gitoxide reference clone: `/workspace/gitoxide` (matches published
|
|
0.87.1 plus a few unreleased commits — pin crates.io versions; treat
|
|
the clone as a reading aid only, never a path dependency). |