Automations reference a template
## Requirement (verbatim)
Operator interview, PRD Q4/Q7: "Also allow setting up automations to reference a template instead of writing a task body." Automation reference → "Live reference".
D5 Automations. Live reference. Each run uses the template as it is when the automation fires.
The settled inputs are the PRD (Task 11059) and the architecture (Task 11060) §5. C1–C4 are merged, so the editor (C3), the gallery and the task-detail line (C4) exist for the end-to-end oracles.
## Scope
- **Validation:**
- `TASK_PARAM_DEFAULTS` (`automation_actions.py:225`) gains `template_id: None`.
- `_task_validate` (:269) requires exactly one of a non-empty `body` or `template_id`. A `template_id` must be visible to the automation's org and published, otherwise 422 `action.params.template_id`.
- `title_template` still applies to event automations; otherwise the template title is used.
- **Fire** (`automation_fire.py`):
- `_build_task` resolves the template **live** and takes title, body, persona, autonomous and model from it. Explicit params are ignored for those fields.
- It copies assets via `copy_template_assets`.
- It never bumps the start counter (I-2).
- A missing template raises `TargetFailed` with `REASON_TEMPLATE_DELETED = "Template deleted"`; an unpublished, invisible or switched-off one raises `"Template unavailable"`. A blank task is never created.
- **UI** (`taskAction.tsx`):
- A **Body | Template** segmented control; Template shows a picker (`GET /api/templates`) and a read-only preview.
- The automation list and editor call `GET /api/templates/refs` and show "Template deleted" or "Template unavailable" from its `status`, never from a bare 404.
## Acceptance criteria (verbatim)
- **AC-15 Automation uses a template.** Oracle: in Automation → new automation with the "Create task" action, choose **Template** instead of writing a body, pick one, and save. Expected: the fire creates a task from the template's **current** content. Edit the template, fire again, and the new task has the edited text. Delete or unpublish the template (or lose access per AC-14): the automation shows "Template deleted" or "Template unavailable", and a fire records a failure with that reason instead of creating a blank task.
- **AC-4 Delete (end to end; owned here).** Oracle: delete a template that has started tasks and one automation pointing at it. Expected: the confirm names how many automations will stop. Afterwards the gallery no longer shows it, the task still shows the template's name as text, and the automation shows "Template deleted" (AC-15).
- **AC-14 Isolation (automation half).** … Turning the switch off later hides org A's templates from the gallery and from Start without deleting them. Automations that reference them stop and say why.
- **AC-20 Live on dev.** AC-1 through AC-19 pass on `dev.jaah.ai` after the deploy. Nothing global sits behind a flag that is off in the dev deployment.
Credentials & reach:
- Member flows (AC-6–10, 12, 15, 16) | Operator login acting in a tenant org with tasks:create | **verified** (`me/jaah/debug/main/operator-login`, environment `https://app.dev.jaah.ai`; `dev.jaah.ai` internal ALB timed out from runner nodes, so oracles use `app.dev.jaah.ai`)
- Org A / org B isolation and switch on/off (AC-13, 14) | Same operator login (acts in any tenant; the admin covers the org admin) + `org/console/dev-orgb-login` as org B's own admin | **verified**: both `credential_get` calls succeeded. Note: the org B row's stored base_url names a retired host; use app.dev.jaah.ai
Out of scope:
- N-3 No fill-in inputs, `{{placeholders}}` or variables in template text (D3). The automation `title_template` renderer (`apps/api/app/trigger_template.py`) is untouched and not reused for templates.
- N-2 No change to the task lifecycle, `start_task` preconditions, or persona prompts.
- N-1 No change to Playbooks.
- Do NOT touch: existing body-based automations, which must behave exactly as before; the template API (C1 and C1b; report gaps); the gallery and manage UI (C3, C4).
Done means:
- Tests:
- validate: body only OK, template only OK, both → 422, neither → 422, an unpublished or another org's template → 422;
- fire: uses the live content after an edit; never bumps `starts_90d`;
- a deleted template → `TargetFailed` "Template deleted" and no task row;
- unpublished or switched off → "Template unavailable" and no task row;
- body images are copied through `copy_template_assets`.
- On app.dev.jaah.ai, in a browser at desktop width and at 448px:
- AC-15 end to end: create the automation, fire it, edit the template in `/templates/:id`, fire it again and see the edited text, then unpublish and see "Template unavailable" plus a recorded fire failure.
- AC-4 end to end: delete a template that has a started task and this automation. The confirm names 1 automation; the gallery no longer shows it; the task detail shows the name as plain text; the automation shows "Template deleted".
- AC-14: an org template referenced by an automation, with the org switch turned off → "Template unavailable", and the fire fails with that reason. Then turn it back on.
- Attach screenshots of the Body|Template control, the picker and both failure states.
Activity
- Draft
- Ready