feat(bug-fast-track): cheaper/shorter pipeline route for bug-fix tasks (ORCH-019)
A task carrying the Plane `Bug` label takes a shortened route that skips the `architecture` stage (one opus architect run + ADR + check_architecture_done), replacing heavy analysis with a lite package (bug-report + mandatory regression test plan). EVERY Quality Gate / sub-gate runs UNCHANGED — the route is a scheduler property, not a gate (root invariant NFR-1): STAGE_TRANSITIONS / QG_CHECKS / check_* / machine-verdict keys are byte-for-byte preserved. - src/bug_fast_track.py: new leaf (never-raise) — bug_fast_track_applies (local, network-free, checked first), is_bug_task (labels.has_label, Plane API source), skips_architecture (pure DB-backed routing predicate), snapshot. - src/db.py: additive idempotent tasks.track column (TEXT DEFAULT 'full') + set_task_track / get_task_track helpers (missing/NULL -> 'full', fail-safe). - src/stage_engine.py: routing-override on the analysis-exit edge (track='bug' -> development/developer, skipping architect); brd-review-clock stamp extended to analysis->development. get_next_stage/get_agent_for_stage stay pure. - src/webhooks/plane.py: classify task as bug in start_pipeline (applies-first short-circuit; never-raise -> full cycle on any error). - src/main.py: additive bug_fast_track block in GET /queue + POST /bug-fast-track/escalate (reset 'bug'->'full' to return to the full cycle). - src/config.py: bug_fast_track_enabled / _label / _repos flags (empty CSV -> self-hosting only). - src/notifications.py: optional 🐞 marker on the bug-track card (never-raise). - Prompts: analyst.md (lite bug package + escalation), reviewer.md (regression- test axis) — 52d canon preserved. - Docs: CLAUDE.md, README.md (env + API + section), docs/architecture/README.md, CHANGELOG.md, .env.example. - Tests: tests/test_bug_fast_track*.py + test_db_migrations.py + queue block (TC-01..TC-15). Full regression green (1551 passed). Kill-switch ORCH_BUG_FAST_TRACK_ENABLED=false -> 1:1 pre-ORCH-019 (zero regression; residual track column harmless). Refs: ORCH-019 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
49
src/db.py
49
src/db.py
@@ -140,6 +140,13 @@ def init_db():
|
||||
# irreversible step finishes honestly, then applied.
|
||||
_ensure_column(conn, "tasks", "cancelled_at", "TEXT")
|
||||
_ensure_column(conn, "tasks", "cancel_requested_at", "TEXT")
|
||||
# ORCH-019 (08-data-requirements.md): bug-fast-track task type. Additive,
|
||||
# idempotent (_ensure_column is a no-op once present) -> safe on the live shared
|
||||
# prod DB (enduro untouched). Values: 'full' (DEFAULT — ALL existing and non-bug
|
||||
# tasks) | 'bug' (a task carrying the Plane `Bug` label, set in start_pipeline
|
||||
# after a successful atomic create). Read in advance_stage for the routing-override
|
||||
# (skips architecture) — from the DB, NEVER from the network (NFR-4).
|
||||
_ensure_column(conn, "tasks", "track", "TEXT DEFAULT 'full'")
|
||||
# ORCH-026 (Level B): declarative task dependencies. job_deps stores the
|
||||
# directed edge "task_id (B) is blocked-by depends_on_task_id (A)". The
|
||||
# scheduler gate in claim_next_job keeps B queued until every A reaches
|
||||
@@ -487,6 +494,48 @@ def update_task_stage(task_id: int, stage: str):
|
||||
conn.close()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ORCH-019: bug-fast-track task type (tasks.track) helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
def set_task_track(task_id: int, track: str) -> None:
|
||||
"""ORCH-019: persist the task's pipeline track ('full' | 'bug').
|
||||
|
||||
Idempotent overwrite. Called from start_pipeline (after a successful atomic
|
||||
create, when the issue carries the `Bug` label) and from the escalate endpoint
|
||||
(reset 'bug' -> 'full' to return a complex bug to the full cycle).
|
||||
"""
|
||||
conn = get_db()
|
||||
try:
|
||||
conn.execute(
|
||||
"UPDATE tasks SET track = ? WHERE id = ?", (track, task_id)
|
||||
)
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def get_task_track(task_id: int) -> str:
|
||||
"""ORCH-019: read the task's pipeline track; missing/NULL -> 'full' (fail-safe).
|
||||
|
||||
Read in the hot advance_stage path for the routing-override (skips architecture).
|
||||
A non-existent row, a NULL value, or any read error degrades to 'full' so a bug
|
||||
can never be created by accident (fail-safe -> full cycle).
|
||||
"""
|
||||
try:
|
||||
conn = get_db()
|
||||
try:
|
||||
row = conn.execute(
|
||||
"SELECT track FROM tasks WHERE id = ?", (task_id,)
|
||||
).fetchone()
|
||||
finally:
|
||||
conn.close()
|
||||
if not row:
|
||||
return "full"
|
||||
return row["track"] or "full"
|
||||
except Exception: # noqa: BLE001 - fail-safe -> full cycle
|
||||
return "full"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Telegram live tracker helpers (feat/telegram-live-tracker)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user