docs(docs): 📝 Add detailed architecture documentation for multi-host sync between plum and apricot hosts, explaining roles, workflow, and technical specifics
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
d2a36929d0
commit
c40872e476
1 changed files with 65 additions and 0 deletions
65
CLAUDE.md
65
CLAUDE.md
|
|
@ -81,6 +81,71 @@ All inference routes through **model-boss coordinator** (port 8210). No direct m
|
|||
- **rag-retrieval** (optional): Contextual retrieval for commit analysis
|
||||
- **git**: All operations via `asyncio.create_subprocess_exec` (no shell)
|
||||
|
||||
## Multi-host sync (plum ↔ apricot)
|
||||
|
||||
The same ~68 repos are checked out on two machines. ACS keeps them in sync **and
|
||||
up to date** in both directions. Internalize this model before touching anything
|
||||
that pushes, pulls, or discovers repos.
|
||||
|
||||
**Forgejo is the hub — there is no direct host-to-host git.** Both hosts push to
|
||||
and pull from the same `origin` (`forge.nasty.sh:2222` / `forge.black.local`).
|
||||
plum talks to apricot only over HTTP (port 8200) for LLM message generation and
|
||||
commit recording — never git-to-git.
|
||||
|
||||
### Roles
|
||||
|
||||
| Host | What runs | LLM | How |
|
||||
|------|-----------|-----|-----|
|
||||
| **apricot** (Fedora, primary) | ACS daemon, `auto-commit-applications.service` (port 8200) | local (model-boss :8210) | Full 11-stage pipeline per repo each cycle |
|
||||
| **plum** (macOS MacBook) | `commits-tray --commit-local` LaunchAgent | none — forwards to apricot | Scans local repos, gets messages from apricot's `/generate-message`, commits+pushes locally, reports via `/record-commit` |
|
||||
|
||||
### Stay-up-to-date (the pull half) — runs every cycle, even with nothing to commit
|
||||
|
||||
- **apricot**: `pre_cycle_sync()` (`git/operations.py`) per repo — orphan-recover →
|
||||
`fetch` → if behind **and clean** → `git pull --rebase`. **Dirty trees are never
|
||||
pulled or stashed** (other agents may be mid-edit); the dirty changes commit this
|
||||
cycle, push, and the *next* cycle pulls clean. Gated by `pre_cycle_pull=True`
|
||||
(`config.py`, default on).
|
||||
- **plum**: `_push_if_safe()` (`tray/local_agent.py`) — `git fetch --quiet` first,
|
||||
then if clean-but-behind → `git merge --ff-only`. This path runs even when a repo
|
||||
has no local changes, so plum's clean checkouts self-heal toward `origin`.
|
||||
|
||||
### Stay-in-sync (the push half)
|
||||
|
||||
- **apricot**: pipeline COMMIT → PUSH; on rejection, `git pull --rebase` then retry
|
||||
(`pipeline/stages/push.py`).
|
||||
- **plum**: secret **prefilter** strips denylisted files (`tray/prefilter.py`) →
|
||||
stage *allowed paths only* (never blanket `git add -A`) → message from apricot →
|
||||
commit → `_push_if_safe` push. Repos with a non-empty staging index are skipped
|
||||
(don't clobber in-progress manual work).
|
||||
|
||||
### Divergence (both ahead and behind)
|
||||
|
||||
Neither host force-anything. Both hand off to Claude Code recovery — apricot via
|
||||
`recovery/claude_fallback.py`, plum via `_invoke_claude_recovery` (with a stall
|
||||
cooldown so a stuck repo isn't retried every cycle). Recovery commands are
|
||||
allowlisted: no `--force`, `--hard`, `--no-verify`.
|
||||
|
||||
### Branch/remote are config-driven, not hardcoded
|
||||
|
||||
`git_remote` / `git_branch` come from settings/per-directory overrides; each repo
|
||||
syncs whatever branch its checkout tracks (e.g. this repo: `origin/main`). Don't
|
||||
assume `master`.
|
||||
|
||||
### Known failure mode — keep these distinct
|
||||
|
||||
1. **Data repos** (the ~68 monitored checkouts): self-heal via the pull/push halves
|
||||
above. Drift only if `pre_cycle_pull` is off (apricot) or `--commit-local` is
|
||||
absent from plum's LaunchAgent — **`--commit-local` is OFF by default for
|
||||
safety**, so a plum tray launched without it neither commits nor fast-forwards,
|
||||
and its checkouts silently fall behind.
|
||||
2. **The ACS tooling itself on plum** (the `commits-tray` code plum executes): this
|
||||
is plum's *local checkout of this repo*, which can drift far behind apricot
|
||||
(the source of the past "~1000-commit-stale" tray). It does **not** self-heal
|
||||
like a data repo, because the stale code is what would do the healing. Mitigation
|
||||
pattern: have plum run apricot's current tray code over SSH rather than its own
|
||||
local copy. Don't conflate this with data-repo sync.
|
||||
|
||||
## Configuration
|
||||
|
||||
All settings via env vars prefixed `AUTO_COMMIT_` or `~/.config/commits/startup-config.json`.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue