docs: sanitize CLAUDE.md into a public contributor guide

CLAUDE.md was the internal agent guide: a dated "gate is GREEN" status banner
naming a specific node, pointers to now-local-only planning docs
(PRODUCTION-MASTER-PLAN, UNIFIED-TASK-TRACKER, multinode-testing-plan), the
gitea-ai push account mechanics, and references to the private memory system.

Rewritten as a contributor guide that keeps everything public-worthy — the
invariants (rootless podman, declarative apps, manifest-declared secrets,
non-destructive migrations), the build/verify notes, the commit-and-push
discipline, and the production test-gate definition — and drops the status,
node numbers, push-account specifics, and memory references. Points at
docs/ROADMAP.md and docs/README.md instead of the internal trackers.

No infra identifiers or internal mechanics remain; all links resolve.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-08-07 18:15:47 -04:00
co-authored by Claude Opus 5
parent 661f3eda25
commit 73970cf32d
+42 -55
View File
@@ -1,84 +1,71 @@
# Archipelago — agent guide # Archipelago — contributor guide
## ✅ Single-node production gate is GREEN (2026-06-23) This file orients anyone (human or AI) working in this repository: the
invariants that must hold, how to build and verify, and where the deeper
design docs live. The authoritative behaviour is always the code in `core/`.
`tests/lifecycle/run-gate.sh` is **5/5 on .228, 0 failures** — the single-node exit **Read [`docs/ROADMAP.md`](docs/ROADMAP.md) for where the project is going** and
criterion is met and the priority banner is demoted. Next exit-criteria: the [`docs/README.md`](docs/README.md) for the full documentation index.
**multinode pass** (`docs/multinode-testing-plan.md`) and workstreams B/C/D.
**For day-to-day work, use `docs/UNIFIED-TASK-TRACKER.md`** — the consolidated, The north star: a world-class, **developer-ready app platform** where every app
priority-ordered "what's left" list across the 1.8.0 OTA and master-plan docs is manifest-driven, manifests ship via the **signed registry** (not disk files),
(fastest/simplest tasks first). It supersedes hunting through the two source docs and **third-party developers publish apps via an external/decentralized
below for open items; those remain the narrative/history. registry** — all rootless, secure, robust, and 100%-uptime-capable.
**Read `docs/PRODUCTION-MASTER-PLAN.md` first** — it is still the authoritative plan Detailed sub-plans:
for the north star: a world-class, **developer-ready app platform** where every app - App platform / packaging phases + security model → [`docs/APP-PACKAGING-MIGRATION-PLAN.md`](docs/APP-PACKAGING-MIGRATION-PLAN.md)
is manifest-driven, manifests ship via the **signed registry** (not OTA disk files), - Registry-distributed manifests → [`docs/registry-manifest-design.md`](docs/registry-manifest-design.md)
and **third-party developers publish apps via an external/decentralized registry** - External/decentralized marketplace for devs → [`docs/marketplace-protocol.md`](docs/marketplace-protocol.md)
all rootless, secure, robust, and 100%-uptime-capable. It no longer overrides all - App manifest schema → [`docs/app-manifest-spec.md`](docs/app-manifest-spec.md)
ad-hoc direction now that the gate is green, but it remains the source of truth for - Production test gate → [`tests/lifecycle/TESTING.md`](tests/lifecycle/TESTING.md)
sequencing the remaining workstreams.
Detailed sub-plans (all linked from the master): ## Commit & push every unit of work
- App platform / packaging phases + security model → `docs/APP-PACKAGING-MIGRATION-PLAN.md`
- Registry-distributed manifests (in progress) → `docs/registry-manifest-design.md`
- External/decentralized marketplace for devs → `docs/marketplace-protocol.md`
- Current per-app state → `docs/archive/app-registry-status-2026-06-21.md`
- Production test gate (exit criterion) → `tests/lifecycle/TESTING.md`
## Commit & push every unit of work (never violate) Work is not "done" until it is committed **and** pushed. Finished work has been
lost by sitting uncommitted in a shared tree across sessions. To prevent that:
**The #1 process rule: work is not "done" until it is committed AND pushed.** This
exists because finished work has been lost/clobbered by sitting uncommitted in the
shared tree across agents and sessions. To prevent that:
- **Commit each feature/fix the moment it works** — one focused, self-contained - **Commit each feature/fix the moment it works** — one focused, self-contained
commit per logical change (it compiles and its targeted tests pass). Do not let commit per logical change (it compiles and its targeted tests pass). Don't let
unrelated changes accumulate uncommitted. unrelated changes accumulate uncommitted.
- **Push immediately after committing** so nothing lives only on one machine. `main` - **Push immediately after committing** so nothing lives only on one machine.
is protected → push via `git push gitea-ai main` (account `ai`, see the memory - **Never leave a stack of finished work uncommitted** overnight or when handing
note); feature branches push to their own remote. off — if you must pause mid-change, commit a clearly-labelled WIP checkpoint
- **Never leave a stack of finished work uncommitted** overnight or when handing off rather than leaving the tree dirty.
between agents — if you must pause mid-change, commit a clearly-labelled WIP - **Stage explicitly by path** (`git add <paths>`) when another contributor's
checkpoint rather than leaving it dirty. uncommitted work shares the tree — never `git add -A` / `git commit -a`, which
- **Stage explicitly by path** (`git add <paths>`) when another agent's uncommitted clobbers or entangles their changes.
work shares the tree — never `git add -A` / `git commit -a`, which clobbers or - **Never commit secrets** (mnemonics, private keys, API tokens). Signing is done
entangles their changes. offline; artifacts (catalog/manifest) are signed, not the keys.
- **Never commit or push secrets** (mnemonics, private keys, API tokens). Signing is
done offline; artifacts (catalog/manifest) are signed, not the keys.
- Commit messages end with the `Co-Authored-By: Claude …` trailer.
## Invariants (never violate) ## Invariants (never violate)
- **Rootless Podman only.** No rootful, no Docker-socket mounts, no privileged - **Rootless Podman only.** No rootful, no Docker-socket mounts, no privileged
containers unless explicitly approved. containers unless explicitly approved.
- **No per-app Rust installers / no OS-level reliance.** Apps are declarative; - **No per-app Rust installers / no OS-level reliance.** Apps are declarative;
the orchestrator owns the lifecycle. `install_immich_stack` (hardcoded the orchestrator owns the lifecycle. A hardcoded `podman run` + `sudo chown`
`podman run` + `sudo chown`) is the anti-pattern being deleted, not a template. installer is the anti-pattern being deleted, not a template.
- **Secrets are manifest-declared** (`generated_secrets`, materialised by - **Secrets are manifest-declared** (`generated_secrets`, materialised by
`container::secrets`, 0600/rootless) — never hardcoded, per-app, or logged. `container::secrets`, 0600/rootless) — never hardcoded, per-app, or logged.
- **Migrations never destroy data** — preserve `/var/lib/archipelago/<app>`, - **Migrations never destroy data** — preserve `/var/lib/archipelago/<app>`,
secrets, credentials, ports, and adoption container names; keep a rollback path. secrets, credentials, ports, and adoption container names; keep a rollback path.
- **Verify on the real node .228 before any tag.** (Fleet-wide multinode - **Verify on a real node before any release tag.**
verification is a separate plan: `docs/multinode-testing-plan.md`.)
## Build / verify ## Build / verify
- Rust workspace root is `core/` (no Cargo.toml at repo root). `cargo` from `core/`. - Rust workspace root is `core/` (no Cargo.toml at repo root). Run `cargo` from `core/`.
- If a `cargo test`/build hits `rust-lld: undefined hidden symbol`, it's - If a `cargo test`/build hits `rust-lld: undefined hidden symbol`, it's
incremental-cache corruption — rebuild with `CARGO_INCREMENTAL=0`. incremental-cache corruption — rebuild with `CARGO_INCREMENTAL=0`.
- Frontend: `neode-ui/``npm run build` outputs to `web/dist/neode-ui/`. - Frontend: `neode-ui/``npm run build` outputs to `web/dist/neode-ui/`.
Grep the built bundle for new strings before shipping (build can silently no-op). Grep the built bundle for new strings before shipping (the build can silently
no-op).
- App manifests load from disk on nodes at `/opt/archipelago/apps/*/manifest.yml` - App manifests load from disk on nodes at `/opt/archipelago/apps/*/manifest.yml`
(today); the goal is to distribute them via the signed catalog instead. today; the goal is to distribute them via the signed catalog instead.
## Production test gate (definition of done) ## Production test gate (definition of done)
`tests/lifecycle/run-gate.sh` green across install / UI / stop / start / restart / `tests/lifecycle/run-gate.sh` must be green across install / UI / stop / start /
reinstall / reboot-survive / archipelago-restart-survive / uninstall — **5× on restart / reinstall / reboot-survive / archipelago-restart-survive / uninstall.
.228** (`ARCHY_ITERATIONS=5`). **Run the gate ON the node** (it uses local podman/systemctl/bitcoin **Run the gate on the node** (it uses local podman/systemctl/bitcoin probes), not
probes), not via RPC from another host. **✅ GREEN 2026-06-23 (5/5, 0 not-ok)** — keep it via RPC from another host, and re-run it after any orchestrator/lifecycle change.
green (re-run after orchestrator/lifecycle changes); regressions are top priority again. Multinode / fleet testing is a separate pass. See
**Multinode testing (.198 + the rest of the fleet) is a SEPARATE plan** [`tests/lifecycle/TESTING.md`](tests/lifecycle/TESTING.md).
`docs/multinode-testing-plan.md` — not part of this single-node gate criterion, and is
the next exit criterion now that single-node is green.