add .dispatcher.yaml — signal-dispatcher contract
Declares this repo to the signal-dispatcher (auto-triage + fixer for prod errors). Sentry source is goon-foss/goon (EU region); fixer opens PRs to public/main with auto-fix/ branch prefix, never auto-merges, and the verifier waits for the source signal to go quiet (not just PR merge). Conservative policy: all severities open PRs only; nothing auto-merges until the classifier proves reliable.
This commit is contained in:
parent
b99552fbb7
commit
60ece70708
1 changed files with 134 additions and 0 deletions
134
.dispatcher.yaml
Normal file
134
.dispatcher.yaml
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
# .dispatcher.yaml — contract between a project and signal-dispatcher.
|
||||
# Lives in the ROOT of the project's own repo (here: goon-foss/goon), versioned
|
||||
# with the project. `dispatcher project-sync <path>` loads it into the DB.
|
||||
|
||||
schema_version: 1
|
||||
|
||||
project:
|
||||
name: goon
|
||||
description: >
|
||||
Self-hosted aggregator of adult (18+) scene metadata. FastAPI backend +
|
||||
APScheduler worker on Postgres 16. Ingests from TPDB and StashDB on a delta
|
||||
cron, cross-source dedup by perceptual hash + title + performer, plus a
|
||||
performer-driven backfill that scrapes ~25 public tube sites. On-demand
|
||||
stream resolution via yt-dlp and a P.A.C.K.E.R. unpacker. Expo / React
|
||||
Native mobile client (Android).
|
||||
keywords: [goon, tpdb, stashdb, tube, scene, performer, phash, yt-dlp, packer]
|
||||
|
||||
repo:
|
||||
url: https://github.com/goon-foss/goon
|
||||
default_branch: public/main # local `main` is a stale divergent line; prod work happens on public/main
|
||||
branch_prefix: auto-fix/
|
||||
pr_label: auto-fix
|
||||
require_ci_green_before_merge: true
|
||||
|
||||
deploy:
|
||||
mode: manual # no CD: deploy = scp + `docker compose restart`
|
||||
# Consequence: a merged PR is NOT live until a human deploys. The dispatcher
|
||||
# keeps the issue in `verifying` (deploy_pending=true) and closes it only once
|
||||
# Sentry actually goes quiet — never on merge alone.
|
||||
|
||||
worktree:
|
||||
base: /opt/dispatcher/worktrees/goon
|
||||
setup:
|
||||
- python3.12 -m venv .venv
|
||||
- .venv/bin/pip install -e ".[dev]"
|
||||
|
||||
ci:
|
||||
# -x stops at the first failure: fast for the fix loop. Note CI runs the full
|
||||
# suite (`pytest --tb=short`), so CI can surface failures this command hides.
|
||||
test_cmd: .venv/bin/pytest --tb=short -x -q
|
||||
lint_cmd: .venv/bin/ruff check app/ tests/
|
||||
pre_test: [] # tests use respx HTTP mocks + fixtures, no DB
|
||||
post_test: []
|
||||
timeout_min: 10
|
||||
|
||||
sources:
|
||||
sentry:
|
||||
# org_slug injected from env (SENTRY_ORG) — kept out of source to avoid linking
|
||||
# this public repo to a specific Sentry org identity.
|
||||
project_slug: goon # backend. Mobile (RN) is a SEPARATE Sentry project: `android`
|
||||
region_url: https://de.sentry.io # EU region — Sentry's API is region-scoped
|
||||
environments: [production]
|
||||
severity_map: {error: med, warning: low, fatal: high, info: low}
|
||||
ntfy:
|
||||
topics: [] # goon emits no custom alerts today
|
||||
slack: null
|
||||
|
||||
path_policy:
|
||||
# Tube scrapers: a broken selector means the SITE changed, not the code. An
|
||||
# LLM can write a plausible new selector but cannot know the correct one
|
||||
# without the live page — and the test fixture IS the HTML that just broke.
|
||||
# So: open a PR as a HYPOTHESIS, never auto-merge, a human verifies live.
|
||||
- paths: [app/connectors/direct_scrapers/, app/extractors/]
|
||||
mode: pr-hypothesis
|
||||
# Cross-source dedup: regressions here are genuine code bugs, but subtle.
|
||||
# Real fix attempts, but always PR — never auto-merge.
|
||||
- paths: [app/resolve/]
|
||||
mode: pr-only
|
||||
# Everything else (app/api/, app/scheduler/, ...) follows the policy table.
|
||||
|
||||
forbidden_paths:
|
||||
- alembic/versions/ # DB migrations — auto-edit is catastrophic
|
||||
- .github/workflows/
|
||||
- deploy/
|
||||
- docker-compose.yml
|
||||
- Dockerfile
|
||||
- pyproject.toml # dependency bumps are a separate decision
|
||||
- mobile/ # separate pipeline (OTA via scripts/publish_update.py)
|
||||
- app/static/ # APK + OTA bundle artifacts land here
|
||||
|
||||
protected_branches: [main]
|
||||
|
||||
fix_constraints:
|
||||
max_files_changed: 5
|
||||
max_lines_changed: 200
|
||||
|
||||
knowledge:
|
||||
doc_paths: [README.md, CONTRIBUTING.md, DEPLOY_BACKLOG.md, DISCLAIMER.md]
|
||||
# Injected into the classifier prompt. Derived from goon's live Sentry
|
||||
# (23 unresolved issues, 2026-05-22): transient upstream noise dominates.
|
||||
triage_hints: >
|
||||
Transient upstream failures dominate goon's Sentry and are NOT bugs:
|
||||
HTTPException with "upstream 4xx/5xx", "proxy error", "extraction failed
|
||||
temporarily", "img/tube fetch failed", "All connection attempts failed" —
|
||||
a remote site or CDN failed, not goon. Classify intent=noise unless one
|
||||
culprit sustains a high event rate. Smoke-test / health-check events
|
||||
("Smoke test ...", "Sentry init OK") are intent=noise, severity=low.
|
||||
Genuine bugs (intent=bug): NameError, ModuleNotFoundError, TypeError from a
|
||||
signature/constructor mismatch, psycopg IntegrityError / UniqueViolation in
|
||||
dedup or upsert paths, and encoding errors (UnicodeEncodeError). Read the
|
||||
UNDERLYING error, not the HTTPException prefix — an "img fetch failed"
|
||||
title can wrap a real UnicodeEncodeError bug.
|
||||
conventions: >
|
||||
Code identifiers and type hints are English; some inline comments are
|
||||
Polish. curl_cffi is pinned <0.15 until yt-dlp ships a compat release
|
||||
(see pyproject.toml). The performer-driven worker walks performers by
|
||||
last_searched_at NULLS FIRST — "completeness over recency" is intentional.
|
||||
Sentry before_send drops upstream 502/503/504, so absence of an alert is
|
||||
not proof of a fix.
|
||||
|
||||
# Seeds the `policies` table on `dispatcher project-sync`. Conservative on
|
||||
# purpose: goon starts fully PR-gated. Flip low/med Sentry bugs to
|
||||
# auto-merge-on-green only after the classifier proves reliable.
|
||||
policies:
|
||||
- priority: 50
|
||||
match_severity: [critical]
|
||||
ship_mode: pr-and-ntfy
|
||||
notify: [ntfy:urgent]
|
||||
max_attempts: 1
|
||||
verify_window: "1 hour"
|
||||
- priority: 60
|
||||
match_severity: [high]
|
||||
ship_mode: pr-and-ntfy
|
||||
notify: [ntfy:default]
|
||||
max_attempts: 2
|
||||
verify_window: "1 hour"
|
||||
- priority: 100
|
||||
match_severity: [low, med]
|
||||
match_intent: [bug, data_quality]
|
||||
match_source: [sentry]
|
||||
ship_mode: pr-and-ntfy
|
||||
notify: [ntfy:default]
|
||||
max_attempts: 2
|
||||
verify_window: "30 minutes"
|
||||
Loading…
Add table
Reference in a new issue