diff --git a/AGENTS.md b/AGENTS.md index 9b36b18..4331939 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -45,6 +45,9 @@ flat JSON in a writable `state/` mount. **NVIDIA Sync** alias — host `spark-32d0`, user `modelo`, key-based; injected into `~/.ssh/config` via an `Include`. `modelo27`/`spark-27ea` is a second Spark on another LAN). `reset --hard` is safe: `.env`/`config.toml`/`state/` are gitignored. + **Deploy-key gotcha:** each repo the Spark clones needs its *own* Gitea deploy key plus its own + `Host` alias — Gitea refuses to reuse one SSH key across two repos' deploy keys, and the default + `immense-voyage.local` block already carries matrix-bridge's key. - **Onboard a repo:** create a Matrix room named like the repo, invite this bot → it auto-joins, maps the room to `/` (+ `~/Projects/` on the Mac), and posts an onboarding message. Pick review agents in-chat: `agents +reviewer +security -adjudicator`. @@ -84,6 +87,13 @@ flat JSON in a writable `state/` mount. - **Reuse matrix-bridge's Mac wrappers + Spark→Mac SSH key** (don't duplicate the seam). - **Auto-map by name:** room `` → Gitea `/` + `~/Projects/`; mapping persists to `state/` (mirrors matrix-bridge D14). One room per repo. +- **No wedge-detection heartbeat** (adjudicated 2026-07-29). A healthcheck badge restarts nothing + under this compose setup, the tile that would show it lives in spark-control (so it's a two-repo + change), and serial per-room polling with a 10-min review budget makes any staleness threshold + either too loose to be timely or noisy mid-review. Reopens only on an *observed* wedge **plus** + confirmation the spark-control tile already renders Docker health. The cheaper half of the same + goal is the ROADMAP fold-in: bound the unbounded awaits and die if the poll task dies, so + `restart: unless-stopped` handles it. ## Sovereignty @@ -93,36 +103,21 @@ revisit this — local inference via Spark Control would be the path. ## Current state -**LIVE and proven.** Bot runs on the Spark (`docker compose up -d`), `@reviewer` maps each review room -to its repo, and the subagent panel is configured in-chat. Proven end-to-end on **ten31-site PR #4** -(2026-06-28): threaded review → `merge` + `yes` → force_merge → auto-publish → thread redacted — and -the previously-unproven bit, **headless `claude -p` spawning the reviewer/adjudicator/security -subagents, works**. The ten31-site colleague is onboarded; the pipeline is in steady use. +**LIVE and in steady use.** The bot runs on the Spark, maps each review room to its repo, and is proven +end-to-end on **ten31-site PR #4** (2026-06-28): threaded review → `merge` + `yes` → force_merge → +auto-publish → thread redacted, with headless `claude -p` genuinely spawning the reviewer / adjudicator / +security subagents. ten31-site is the only repo onboarded so far. -Deployed to the Spark at `063e694`: a merge always redacts its thread on success, and a failed -post-merge deploy posts its "deploy manually" warning at top level so it survives the redaction -instead of orphaning the thread. `clear`/`resolve` redacts an orphaned thread without touching the PR. +Running on the Spark at `063e694` (a merge always redacts its thread; a failed post-merge deploy warns at +top level rather than orphaning one; `clear`/`resolve` clears an orphan without touching the PR). `master` +is only docs ahead of that, so **no redeploy is pending**. No test suite: verification means exercising +the bot in a real review room. -**Deploy gotcha (still true):** the Spark needs a *dedicated* per-repo Gitea deploy key + a `Host` -alias (the default `immense-voyage.local` block uses matrix-bridge's key); Gitea won't reuse one SSH -key across repos' deploy keys. Redeploy via the Spark Control tile, or `ssh modelo32`. - -**Known issue / next fix (the concrete next step):** the poll loop prunes a PR's thread root from -state when it leaves the open list (`src/bot.py` ~L594) *without redacting*, so a PR merged or closed -**outside** the bot (the Gitea web UI) still orphans its thread, un-redactable by the bot afterward. -The merge-redact fix covers bot-driven merges only; the prune should redact before dropping the root. - -**Backlog adjudicated 2026-07-18** (`9adcdc8`): ROADMAP is down to one phase. Phase 2 (subagent panel, -`agents +/-`) deleted as finished; Phase 4 deleted because spark-control has shipped this bot's tile -since v0.28.0; deploy-on-a-non-static-repo dropped (no repo needs it, and the deploy step is hardcoded -to the static-site publish script, so a per-repo deploy-command field would have to come first). -That left two items: onboard 3 repos, and a wedged-loop heartbeat. - -**Backlog adjudicated 2026-07-29:** the heartbeat is **dropped** — a healthcheck badge doesn't restart -anything here, spark-control's tile would need its own change to read it, and serial per-room polling -(a review may run 10 min) makes any staleness threshold either too loose to be timely or noisy -mid-review; no wedge has ever been observed. Reopens only on an *observed* wedge **plus** confirmation -the tile already renders Docker health. In its place ROADMAP carries a **fold-in**: bound the two -unbounded awaits in `src/bot.py` (`await proc.wait()` after the timeout kill in `ssh_run`; -`client.room_send` in `say()`) and stop the process if the poll task ever dies, so -`restart: unless-stopped` + the tile cover it. Phase 3's onboard-3-repos verify item stands. +**Next steps, in priority order:** +1. **Fix the orphaned-thread prune** (`src/bot.py` ~L594): the poll loop drops a PR's thread root from + state when the PR leaves the open list *without redacting*, so a PR merged or closed in the Gitea web + UI strands its thread and `clear` can no longer reach it. Redact before dropping the root. +2. **`/triage` the 3 untriaged inbox items** tagged for this repo — adjudication never reads the inbox, so + their content is still unknown here. +3. Onboard a 2nd/3rd repo, then watch one poll cycle (`docker compose logs -f`) for a long review + head-of-line-blocking the next room — ROADMAP Phase 3's verify item, and the real scaling limit.