Generic provider-agnostic PR/issue watcher service (pr-watch@<instance>) [epic #796] #801
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Parent epic: #796 (Agent Roster + webUI oversight + health watch family). Design-first — this issue tracks design before implementation; implementation slots AFTER the current MS delivery queue (M5-001 pivot > #790 > #791 > #792) unless reprioritized. Origin: Jason (Discord 2026-07-16 20:20Z) via Mos.
Goal
Codify the ad-hoc PR-watch capability as a generic, provider-agnostic PR/issue watcher service — configurable and deployable against any git-based forge (GitHub, Gitea, GitLab, Forgejo, …), running as pure code with NO agentic intervention, bound to repos at a 1:1 service:repo ratio. The natural shape is a systemd template unit
pr-watch@<instance>(one instance per watched repo).Why (cautionary spec)
The existing
jarvis-brain infra/fleet-enhance-nightly gitea_pr_watch.pyran a silent crash-loop for ~4 weeks unnoticed (the gitea-pr-watch blackhole). The generic service therefore MUST be health-watch-integrated / self-announcing from day one — a dead instance must surface via the fleet health watch (enhance Tier-2 watch-the-watchers), never fail silent.Prior art to mine (do NOT reinvent)
gitea_pr_watch.py(jarvis-brain infra/fleet-enhance-nightly) incl. today's #65 fix + the pending P0 broaden-except ((subprocess.CalledProcessError, OSError)so a missingtmuxbinary can't reopen the poison-loop). Its 4-week silent failure = the cautionary spec above.prwatch0agent-session notify semantics = the behavioral spec to REPLACE with code: head-move, mergeable-flip, terminal-pipeline events (CI reaching a terminal state). These are the events the service emits.Design decisions (to resolve in the design doc)
~/.config/mosaic/tools/_lib/credentials.sh/load_credentials); never inline secrets; no secret value in any output/log.pr-watch@<instance>resolves an instance config (forge kind, repo, endpoint, credential key, event set, webhook|poll, interval). Deploy-clone model (not dev checkout).load-buffer -, notify failure returns status and never aborts the state write — no poison-loop), state-file dedup.pr-watch@<instance>unit within one sweep (self-announcing).Coordination / overlaps
pr-watch@<instance>is one of the failures it must surface. Align the service's health signal with enhance'slatest.jsoncontract.gitea_pr_watch.pyis enhance's decoupled fast-follow (not this issue) — but this generic service must carry the same OSError-safe notify from the start.Firewall
Operator-agnostic → mosaicstack/stack proper (per the framework firewall). No SOUL/USER/operator specifics in the service; instance configs + credentials are operator data supplied at deploy, not shipped.
Acceptance (design phase)
A design doc under
docs/design/(provider abstraction, webhook-vs-poll, credential handling, instance/unit model, event semantics, health-watch integration, test plan). Standard MS gates on any subsequent implementation (TDD ≥85%, independent review, secrev on the credential surface, trunk-based squash PR, merge + descendant-green + issue close).