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.
134 lines
5.6 KiB
YAML
134 lines
5.6 KiB
YAML
# .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"
|