Incident to task automation kinds
## Requirement (verbatim)
4. "Incident → task: automation When kinds `incident`, `deploy_failed`, `health_breach` (automations.py When kinds) with the existing `task` action; files a `triage` or `coder` task carrying the incident body and suspect links; dedup per fingerprint; per-project severity threshold, quiet hours and auto-file vs draft. The fix PR references the incident; the incident closing after the fix's deploy marks the fixer survived and the origin incident_linked."
7 (verbatim): "Every behaviour change — filing a task, filing a revert, running probes — is behind the plan feature `production_qa` with org override and per-project opt-in."
Settled: D11 a failed deploy files a `triage` task ("combine incidents by type where reasonable"). Operator R1: only automations file; severity/types/environments/quiet hours live on the When; draft vs ready is the `task` action's `start`; opt-in offers "Create default automations". Architect A-1: quiet hours HOLD (state `held`), never draft; A-13 drafts block dedup. Relaxed AC-18 (operator R2, flagged for Finish): "log tail in body" → "run + job + failing step in body; tail fetched by the runner" (with `jaah-forge ci log`).
Design: architecture artifact of Task 12249, §6.1–6.5, §4 `events.flush/pre_file/post_file`, CP-raised event shape + `templates.py`, delivery reasons, §13 risks 7–9.
## Scope (architecture C5, minus revert filing which ships with regression)
- CP-raised non-HTTP kinds `incident`, `deploy_failed`, `health_breach` (the `user_registered` precedent) in `SOURCE_KINDS`, labels, web When choices; routing per §6.1 (`monitor`/`regression`/`lane_slowdown` → `incident`).
- `events.flush` after commit, own session, never raises: per trigger of that kind on the incident's project, a `received` delivery with `dedup_key = incident:{id}:{transition}:{incident_event_id}` (stopped trigger → `skipped`), then `fire_intake()`.
- `IncidentWhenConfig` `{min_severity: 'error', types, environments|null, quiet_hours|null}` with the §6.2 null-environment rule; incident-family automations target the event's own project, fan-out refused at save.
- Checks in order (§6.3): gate → `skipped` `production_qa_off`/`project_not_opted_in`; type/env/severity → `filtered`; quiet hours → `held`, `not_before` = window end, reason `held_quiet_hours`; cron job `release_held` flips due rows to `received` (re-runs every check); resolved → `filtered` `incident_resolved`; `events.pre_file` advisory lock + `incident_tasks` claim (open task incl. draft → `deduped` `incident_task_open`; done/deleted task releases first); unchanged hourly cap → `automation_fire.fire`; `events.post_file` binds claim (`triage`/`fix`); a fire filing nothing releases the claim. Two named call sites in `automation_fire.fire` for incident-family deliveries only. Leave a no-op hook in `post_file` for the revert filing the regression child adds.
- Default body template rendering the incident, suspects (PR, link, confidence, basis), deployment (run link, failing job/step, range, PRs) and ending `Incident: INC-<id> <url>`.
- "Create default automations" in the Production QA settings slot (§6.5), owned by the admin; panel shows "0 automations" with the button when none exist.
Credentials & reach:
- UI checks on dev — `org/console/dev-login` (org Admin), `https://dev.jaah.ai` — credential **verified**; environment **deferred** for this node (operator R4: run from a tailnet node)
- Scratch repo `pqa-test` + webhooks (AC-1..5, 18) — `me/users/roman@gmind.tech/github_admin` — **verified**
- Adapter deliveries — none — signed `curl` with the trigger's own Jaah-held secret — **verified**
- AC-5/19/27 on the Jaah project — `org/console/dev-login`; Jaah repo webhook config needs repo admin — **deferred** — tailnet constraint; the repo webhook is operator configuration in GitHub
- AC-29 gates — worktree only — **verified**
Out of scope: Do NOT turn `production_qa` on anywhere in code/seeds/migrations (D9). Do NOT edit the Jaah project's "watch Jaah Deploy" instruction (D10). Do NOT add an org trigger quota (D6). Do NOT file revert tasks here (regression child). Do NOT add a CP-side GitHub log read (R2). Epic out of scope (verbatim): "building an APM or log store; replacing the customer's monitor; auto-merging a revert without the project's policy; any scoring or ranking logic (the outcome ledger epic reads the states this epic writes)."
Done means:
- AC-15: "an `incident` automation with the `task` action on `pqa-test` files exactly one task (persona per the automation, `triage` or `coder`) whose body carries the incident (fingerprint, severity, environment, counts, top stack frames, vendor link) and the suspect PRs with their confidence. A second occurrence files nothing. The task links back to the incident." — integration test (Sentry/generic payload twice → one task) + live on dev.
- AC-16: "the incidents row is still written and updated, and no task is filed. The automation's run log shows the reason ('production QA off' or 'project not opted in'), not a silent skip." — test both OFF states.
- AC-17: "below-threshold incidents file nothing (reason logged). Inside quiet hours a task is filed as `draft`, or held until quiet hours end; the Architect chooses which and names it in the run log. Draft mode files a `draft` task that never dispatches until started." — chosen: held, run log "Held: quiet hours until HH:MM <tz>"; tests for each setting incl. release after the window and dedup of a reopen during the hold.
- AC-18 (relaxed): "a deploy with conclusion `failure` writes a `deploy_failed` incident fingerprinted (project, env, workflow, failing job) and files one `triage` task carrying the run link, the failing job and [failing step], and the commit range with its PRs. A second failure of the same job while that task is open updates the incident and files nothing. A failure of a different job is a separate incident." — test + live on `pqa-test` (fail twice same step, then a different step).
- AC-19: "after an operator turns `production_qa` ON for the Jaah org and opts the Jaah project in (D9), a failed Jaah Deploy run on dev files one triage task on the Jaah project within 60 s of the failure event, while no runner session references that PR." — fixture test with a recorded failed Jaah Deploy payload now; live via a fresh `workflow_dispatch` failure (NOT a redelivery — redelivery is deduped, arch risk 15) once the operator enables Jaah (deferred to operator enablement; Finish verifies).
- Dedup race: two concurrent deliveries for one incident → one task (advisory-lock test); a draft blocks a second filing.
- AC-26 (end-to-end OFF check): with the feature OFF everywhere, measurement rows still written and only filing suppressed — test.
- AC-29: `./dc check quick` green; changed-area tests green; merge lane full gate green.
Activity
- Draft
- Ready