Files
alkgit/AGENTS.md
T
glm-5.3-flash b9ab5e4c9e docs: two POC modes — branch vs standalone scratch project
- pocs.md: define both modes + per-POC assignment (POC-1/2 standalone at
  /workspace/alkgit-pocN, POC-3 branch mode); findings are the
  deliverable, POC source never merges to main
- sdd_process.md: phase 0 + POC Specialist sections cover both modes
- poc-specialist.md: mode determination up front, standalone environment
  section, 'stay in your lane' principle updated
- AGENTS.md: lifecycle status describes the two modes

Verified: none needed (markdown only)
2026-09-19 17:35:58 +00:00

10 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."

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 / git-server workspace)

This is alkgit — a self-hosted git server: repository storage, the git smart protocol served over HTTP and SSH interfaces, and the alkgitd binary that assembles it on the alk stack (alkcall, alkhttp, alktls, alkvault) and gitoxide (gix). The project is a cargo workspace of sub-crates under crates/. The conventions below apply to all work in crates/*/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 workspace 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; any alkgit-specific alkgit↔alkgit framing will get ADRs when it exists), 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: sha256 (hash algorithm passthrough; sha1 is the default and pinned in the workspace manifest) and acme (alktls ACME wiring in the binary). Base crates compile lean. 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. Public API surface is lib.rs re-exports. Workspace members under crates/: alkgit-core (storage), alkgit-transport (smart protocol), alkgit-http (http front door), alkgit-ssh (ssh front door), alkgitd (binary).

  15. Composability boundary ("ALPN as a service") — alkgit-core + alkgit-transport are front-door-blind: they consume (identity, repo id, duplex stream, limits) and depend on alkcall types only, never on alkhttp/alkgit-ssh, and carry no http/channel-specific types below the stream. The http and ssh crates are replaceable adapters; a downstream app embeds core + transport and brings its own front doors. v1 is the reduction to storage + ACL + protocol adapters.

Verification Commands

Run these before committing. All must pass.

cargo test                                    # full suite (workspace)
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 0 (exploration) — see docs/sdd_process.md and docs/research/README.md. There is no architecture yet (docs/architecture/ is empty; ADR numbering starts at 001 when phase 1 begins). 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. Until phase 1 produces ADRs, "the architecture says" has no referent — cite docs/research/ docs instead.

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).