|
1 | 1 | # 120 — Shutdown planning UI: instantiate a runbook into a real outage |
2 | 2 |
|
3 | | -Status: TODO |
| 3 | +Status: DONE (2026-09-07 — `pb_public/shutdown_plan.html` + migration U for the |
| 4 | +delete gap; smoke test 122 → 124 assertions, green) |
4 | 5 | Milestone: M2 Shutdown Runbooks + Punch List (v0.10.0) |
5 | 6 | Depends on: 110 |
6 | 7 |
|
@@ -46,21 +47,44 @@ if a genuinely new component is needed. |
46 | 47 |
|
47 | 48 | ## Acceptance criteria |
48 | 49 |
|
49 | | -- [ ] From a seeded database, a signed-in user can create a shutdown from the |
| 50 | +- [x] From a seeded database, a signed-in user can create a shutdown from the |
50 | 51 | tie-in template against a project + system, and 22 `shutdown_steps` are |
51 | 52 | created with their groups, offsets and hold points intact. |
52 | | -- [ ] Missing `shutdown_roles` can be created inline; the shutdown's steps then |
| 53 | +- [x] Missing `shutdown_roles` can be created inline; the shutdown's steps then |
53 | 54 | resolve to real role records with contact details. |
54 | | -- [ ] A step can be bound to a project tag; an unmatched hint warns and does not |
| 55 | +- [x] A step can be bound to a project tag; an unmatched hint warns and does not |
55 | 56 | block saving. |
56 | | -- [ ] Steps can be added, removed, reordered and edited **before** execution, |
| 57 | +- [x] Steps can be added, removed, reordered and edited **before** execution, |
57 | 58 | and the page never writes a `shutdown_step_events` record. |
58 | | -- [ ] Wall-clock times are derived at render — confirmed by changing |
| 59 | +- [x] Wall-clock times are derived at render — confirmed by changing |
59 | 60 | `planned_window_start` and seeing every window step's time move with no |
60 | 61 | other write. |
61 | | -- [ ] An unauthenticated visitor cannot create or edit; the page says so rather |
| 62 | +- [x] An unauthenticated visitor cannot create or edit; the page says so rather |
62 | 63 | than failing silently. |
63 | | -- [ ] Page JS stays within the ~50 KB budget; no new library; no build step. |
| 64 | +- [x] Page JS stays within the ~50 KB budget; no new library; no build step. |
| 65 | + |
| 66 | +## Execution notes (2026-09-07) |
| 67 | + |
| 68 | +- **Spec item 4 needed a schema change.** Every collection shipped |
| 69 | + `deleteRule: null`, so "remove a step" was impossible as written. Raised, and |
| 70 | + resolved by maintainer ruling: migration U, a guarded rule that permits the |
| 71 | + delete only while the step has no events. ADR 0019 carries the amendment. |
| 72 | +- **Roles are created before steps, not offered after.** `shutdown_steps` holds |
| 73 | + `responsible_role` as a relation and has no text-key fallback, so a step |
| 74 | + copied before its role record existed would lose which role it wanted. The |
| 75 | + page therefore creates the project's roles from the template's role table |
| 76 | + (titles prefilled, contacts blank) and then binds the steps; the planner |
| 77 | + fills in contacts on the plan page, flagged by a banner. This satisfies spec |
| 78 | + item 2's intent — the contact details are the point — without a schema change. |
| 79 | +- **Two bugs the render check caught that the API tests could not**: the page |
| 80 | + called a `lcAuth.authFetch()` helper that does not exist in this codebase |
| 81 | + (rendered a blank shell), and sorted systems by `sequence` when the field is |
| 82 | + `startup_sequence` (400, empty picker). Both fixed. |
| 83 | + |
| 84 | +**Coverage gap worth a future task:** `scripts/browser_test.sh` covers only the |
| 85 | +accountless field path, so no office page has render coverage. This task shipped |
| 86 | +an empty shell and a 400 that only a throwaway headless check caught. A small |
| 87 | +office-path browser suite would have caught both automatically. |
64 | 88 |
|
65 | 89 | ## Guardrails |
66 | 90 |
|
|
0 commit comments