feat(automation): add composer

This commit is contained in:
Carlos Valente
2026-09-13 20:12:55 +02:00
parent b07544ab84
commit 79a535b1b3
21 changed files with 777 additions and 17 deletions
+114
View File
@@ -0,0 +1,114 @@
# Automation UI Foundation and Global Composer Tasks
## PR 1 — automation UI foundation
### Completed implementation
- [x] Start from clean `master` and retain the mixed branch as reference only.
- [x] Keep automation create/edit payloads definition-only.
- [x] Preserve global and event trigger references when definitions are edited.
- [x] Refuse deletion of definitions referenced by global triggers or rundown events.
- [x] Reject trigger bindings submitted to definition CRUD.
- [x] Persist normalized output values returned by server validation.
- [x] Support the full filter-operator contract, including `not_contains`.
- [x] Extract focused OSC, HTTP, Ontime, and output-card form components.
- [x] Add honest per-output test success/error feedback and failed-save retry behavior.
- [x] Add shared lifecycle labels and output summaries.
- [x] Clarify global trigger scope, duplicate behavior, and missing references.
- [x] Improve event trigger lifecycle labels and output visibility.
- [x] Keep recipes, composer code, and lifecycle-on-definition state out of the PR.
- [x] Cover shared lifecycle labels, the full filter-operator contract, controller rejection of trigger fields, and
definition output replacement with focused regression tests.
### Required before merge
- [x] Accept IPv6 OSC targets as well as IPv4 and hostnames.
- [x] Add a parser regression test using an IPv6 target such as `::1`.
- [x] Keep runtime-template hostname support and normalized persistence intact.
- [x] Remove stale output-form styles that no rendered component references.
- `oscSection`
- `httpSection`
- `actionSection`
- `outputCard`
- nested `test`
- [x] Run the browser smoke check:
- create and edit a definition;
- add, remove, and test OSC, HTTP, and Ontime outputs;
- retry a save after a server error;
- create/edit a global trigger;
- attach the same definition to an event;
- verify missing and duplicate states;
- verify narrow-panel horizontal scrolling and sticky headers.
- [x] Show the concise server validation message after a failed save instead of the full raw 422 response and submitted
definition; keep the form open and retryable.
- [x] Re-run final verification and inspect the final diff for temporary code, stale comments, generated files, and
recipe/composer leakage.
### Verification already observed
- [x] Server test pipeline: 51 files passed; 778 tests passed; 6 todo.
- [x] Client test pipeline: 34 files passed; 276 tests passed.
- [x] Client and server type checks passed.
- [x] Client and server lint passed.
- [x] Format check passed.
- [x] Client and server builds passed with only existing Vite warnings.
- [x] `git diff --check master...HEAD` passed.
### PR 1 checkpoint
- [x] IPv6 compatibility and stale-style cleanup are committed to their owning commits.
- [x] Added PR 1 regression coverage is committed separately from production behavior.
- [x] Browser smoke check is recorded.
- [x] PR 1 is self-sufficient and ready for human review.
## PR 2 — global automation composer and recipes
### Task 1: Define the composition contract
- [ ] Add a create-only command containing a definition plus zero or more global lifecycles.
- [ ] Return the created definition and trigger bindings.
- [ ] Keep persisted `Automation` and `Trigger` entities and ordinary CRUD unchanged.
- [ ] Document that zero lifecycles saves a reusable definition only.
### Task 2: Add atomic global composition creation
- [ ] Validate the definition and every lifecycle before writing.
- [ ] Normalize or reject duplicate lifecycle inputs consistently.
- [ ] Assign IDs and persist the definition and bindings in one settings write.
- [ ] Test success, invalid input, duplicate inputs, and no-partial-write failure behavior.
### Task 3: Build the manual composer
- [ ] Present separate Global trigger, Conditions, and Actions sections.
- [ ] Reuse the PR 1 output editor components where their contracts fit.
- [ ] Support multiple global lifecycles and definition-only save.
- [ ] Test failed-save retry and refresh of both definitions and triggers.
### Task 4: Move recipes onto the composer
- [ ] Restore the recipe catalog and parameter setup without restoring trigger ownership to definitions.
- [ ] Make every recipe declare global lifecycle defaults explicitly.
- [ ] Submit manual and recipe flows through the same composition command.
- [ ] Test representative OSC, HTTP, and Ontime recipes.
### Task 5: Evaluate complete usage counts
- [ ] Implement a pure aggregation over global triggers and all project rundowns.
- [ ] Test zero usage, both scopes, multiple rundowns, duplicates, and missing references.
- [ ] Confirm the read path performs no repeated per-definition scans or persisted counting.
- [ ] Ship the UI count only if both global and event usage are complete and cheap; otherwise record the decision to
defer it.
### Task 6: Integrate and verify
- [ ] Keep event-scoped recipes and event-composer navigation absent.
- [ ] Verify disabled automations, errors, modal keyboard behavior, and narrow layouts.
- [ ] Run full tests, type checks, lint, formatting, and builds.
- [ ] Review the final diff for stale compatibility code and scope leakage.
### PR 2 checkpoint
- [ ] Manual and recipe flows create global compositions atomically.
- [ ] Reusable definitions remain independently editable and attachable in both scopes.
- [ ] Usage information is complete or intentionally omitted.
- [ ] PR 2 is ready for human review.
+108
View File
@@ -0,0 +1,108 @@
# Automation UI Foundation and Global Composer Plan
## Decision
Keep the work split into two pull requests:
1. **PR 1 — automation UI foundation:** reusable definition editing, clearer global/event trigger surfaces, output
editing, and validation hardening.
2. **PR 2 — global automation composer and recipes:** one create flow that produces a reusable definition and zero or
more global trigger bindings.
The implementation confirms that this boundary is workable. PR 1 is useful without recipes and does not move lifecycle
ownership into automation definitions. PR 2 can therefore build on a stable definition/trigger model instead of
repairing the old mixed branch.
## Architecture decisions
- An automation definition owns its title, filters, and outputs.
- A trigger owns lifecycle, scope, and the reference to a definition.
- The composer is a create-time orchestration over those two existing resources; it is not a new persisted entity.
- The first composer creates global bindings only. Event-scoped recipes remain out of scope.
- Users may continue editing definitions and triggers independently after creation.
- Recipes use the same composition command as the manual composer.
- Usage is derived, not persisted. Show it only if complete global and event counts can be obtained with one bounded
aggregation; otherwise omit it.
## Current PR 1 assessment
Branch: `automation-ui`
Commits:
- `b38e5de9` — template-aware output validation and normalized persistence.
- `1732c7cc` — definition/output editing, clearer global/event trigger presentation, and regression coverage for the
definition/trigger boundary and shared presentation helpers.
The two commits can remain in one PR. Although the total diff is slightly above the normal review target, much of it is
the extraction of the existing output form into focused components, and the final behavior is one coherent foundation.
Do not create a third PR solely for the validation commit.
### Review result
The code-review findings are resolved:
- IPv6 support is restored in OSC target validation with a `::1` regression test while IPv4, hostname, and runtime
template handling remain covered.
- The obsolete `oscSection`, `httpSection`, `actionSection`, `outputCard`, and nested `test` styles left behind by the
output-card extraction have been removed.
The browser smoke check passed for definition creation/editing, all output types, failed-save retry, global trigger
editing, event attachment, duplicate and missing-reference states, and narrow-panel scrolling with sticky headers. It
revealed one small UX issue which is now fixed: server-side validation failures show the concise validation message (for
example, `Invalid OSC target`) instead of the complete raw 422 response and submitted definition.
No recipe, composer, lifecycle-on-definition, or event-scoped recipe work should be added while closing these items.
## PR 2 sequence
1. Define a create-only global composition request and response without changing definition CRUD.
2. Implement atomic server creation of one definition plus distinct global lifecycle bindings.
3. Build a manual `When -> If -> Then` composer using the PR 1 output editors.
4. Move recipes onto the same composition command and label their global scope explicitly.
5. Spike complete usage aggregation across global triggers and all project rundowns; ship the count only if the bounded
scan is cheap and does not widen persisted state.
6. Verify refresh, error recovery, disabled-automation behavior, responsive layout, and representative recipes.
## Pull request boundaries
### PR 1 includes
- Definition-only create/edit behavior and rejection of trigger fields at that boundary.
- Reference-safe deletion behavior and tests for global/event usages.
- Output cards, output summaries, test feedback, shared lifecycle labels, and trigger clarity.
- Template-aware OSC/HTTP validation.
- The minimum shared scrolling changes required by these screens.
### PR 1 excludes
- Recipe catalog or recipe picker.
- Composer API or UI.
- Lifecycle fields on automation definitions.
- Trigger reconciliation in definition CRUD.
- Usage counts.
- Event-scoped recipes.
### PR 2 includes
- A dedicated composition contract and atomic global creation path.
- Manual and recipe-driven composition using the same path.
- Definition-only save as an explicit composer option.
- Complete usage counts only if the aggregation spike meets the cost constraint.
### PR 2 excludes
- Event-scoped recipes or an event composer.
- Persisted usage counters.
- Trigger schema/title migration.
- Editing shared definitions through trigger rows.
- A general workflow engine.
## Verification gates
PR 1 must pass focused and full client/server automation tests, client/server type checks and lint, formatting, builds,
diff hygiene, and the browser smoke check. PR 2 repeats those gates and adds tests for atomicity, duplicate lifecycle
inputs, manual creation, recipe creation, failed-save retry, and any usage aggregation that ships.
Detailed progress is tracked in `tasks/automation-composer-todo.md`; the unrelated teleprompter plan in
`tasks/todo.md` remains untouched.