296 lines
56 KiB
Markdown
296 lines
56 KiB
Markdown
# How the settings-page plan was made and audited
|
|
|
|
Four inventory readers went through the repo first, one lens each: operator workflow (97 items), hard-coded site facts in code and scripts (132), config keys and the code that reads them (182), and what runs where (133): 544 items in all. The "what runs where" reader also verified NA Ingest live, read-only, on 2026-10-13 (LaunchAgents, data dir, Companion connections and the flash trigger, keychain item presence, interfaces, the DVS helper, sshd and the StatusPanel tasks on the three PCs).
|
|
Three designers then wrote independent plans from the same inventory: simplest, operations-first and teach-first.
|
|
Three judges scored each on completeness, simplicity, safety, multi-site and feasibility. Totals over the three judges: simplest 126, operations 127, teaching 117. Two judges picked operations and one picked simplest, so operations won and the ideas listed under "Judges' reasoning" were grafted onto it.
|
|
One synthesis produced the plan (second full revision, 844 lines; a partial third revision of sections 10-14).
|
|
Three audit rounds followed, each with four critics (completeness, simplicity, safety, feasibility), finding 47, 59 and 51 gaps. Each round's fixes were written into the next revision.
|
|
The loop did not converge: every revision added machinery (apply classes with SIGHUP reload, a queued-job runner, a stop flag, live-signal triples, a full-inventory diff with ignore lists) that the next round found unsafe, unteachable or infeasible, and the gap count stayed flat.
|
|
So instead of a fourth revision the plan was consolidated against a decisions list dated 2026-10-13: K1-K18 are the mechanisms kept, D1-D10 details pinned after this audit, C1-C13 the deliberate cuts, P0-P6 the phases, Q1-Q4 the questions only the user can answer. Those decisions override the source wherever they differ.
|
|
The table below judges every one of the 157 findings against that list, not against the revision that first answered it. Round 1 and 2 findings were addressed by the source's own revisions; where the decisions keep that mechanism the row says ADOPTED, where they cut it the row says CUT, and where a later critic replaced the ask the row says SUPERSEDED.
|
|
|
|
## Judges' reasoning
|
|
|
|
### Simplest (126)
|
|
|
|
Strengths
|
|
|
|
- The most exhaustive coverage table: every config key, check field, fix-kind field and hard-coded constant is either editable or "shown, not editable" with a reason, and the new keys pull constants out of code (hold time, grid, stale seconds, flash variable, cooldown, Dante max shared, export stamps, settings port).
|
|
- Machines are data, not code: hosts.<alias>.runs[] with a closed kind list and a probe per kind; the Ingest Mac is a host too, so its interfaces, Satellite and other agents show on the map.
|
|
- A safe apply order: validate (schema, load_config, make_page dry run), atomic write, restart the watchdog, prove it is up, only then import pages and run nav keys; page imports refused outright during a service; rollback re-runs the page and nav steps.
|
|
- Least invasive to the watchdog: an AST test checks the code's literal defaults against the schema instead of refactoring them out; a Phase 0 round-trip test proves today's config still builds byte-identical pages.
|
|
- A password-free edit gate (Unlock editing, typed APPLY, an address allow-list), a "Try it on a copy" sandbox, a generated "Where things are" page, a dedicated Spotify screen, and an import wizard whose cascade drops and lists everything that depended on a dropped computer.
|
|
|
|
Weaknesses
|
|
|
|
- No automatic rollback: if the watchdog does not come back the page only "offers Rollback", leaving the deck purple until someone clicks.
|
|
- Page freshness by hashing Companion's live export against the built file cannot work (Companion normalises what it imports); a stored build hash is what works.
|
|
- Fix templates fill the command box once and the string becomes a copy again, so task names, the playlist and the DVS path can drift.
|
|
- The draft lives only in the browser tab; "who changed it" is only a browser address; History auto-prunes.
|
|
- A text-only Overview with no live deck picture; "bridge" refused by name in shared code; 13 screens with Site, Companion and Schedules as grab-bags; NA moved into sites/na in Phase 0 before any UI exists.
|
|
|
|
### Operations (127, winner)
|
|
|
|
Strengths
|
|
|
|
- The fullest per-machine model: runs[] with kinds, watched:false, networks[] per interface, pingable:false for PCs that block ping and self:true for the Ingest Mac, seeded for all eight NA machines, with the per-OS probe commands spelled out, cached, and never waking a PC.
|
|
- Fix builders store template + params beside the generated run with a regenerate test, which structurally fixes the duplicated Spotify URI, task names and DVS path.
|
|
- The safest apply pipeline: server-side draft.json, History with a sidecar, atomic replace, automatic rollback on a traceback, typed APPLY during a service, layout re-import refused then, and install.sh never overwriting a page-edited config; pages and nav keys are detected by diffing the built page JSON rather than a hand-kept rule list.
|
|
- site.live_services separate from auto_fix.windows; a "What this key will say" preview on every key; the Companion screen flags vanished labels with a "rename to" dropdown and offers "Add a key for it"; the Dante screen offers "Watch it".
|
|
- An editor name per browser for History attribution, "Things only a person can do" as a live checklist, a walkthrough that ticks itself, a cheat sheet with contacts, phases that split editing/apply from layout and fleet setup, and the guideline fit enumerated 1-16.
|
|
|
|
Weaknesses
|
|
|
|
- Apply imports pages before restarting the watchdog, and rollback restores only the config, so a bad config can leave new pages on the deck over the old settings.
|
|
- No edit gate beyond a self-declared first name; anyone on the LAN can Apply.
|
|
- test_defaults_single_source demands ripping some fifty literal defaults out of the 2,500-line watchdog in Phase 0, the most invasive refactor of the three; config.json leaves the repo root in the same phase.
|
|
- 14 screens with two grab-bags ("Site & times", "Timing & limits" whose global thresholds have no config key); three window tables; deleting a computer is blocked until every reference is removed by hand.
|
|
- The playlist is only a field inside the SPOTIFY key's check (no screen, no link paste, no search); no sandbox; export stamps and the settings port stay constants; no nav_locations viewer or revert; Restart and Mute not said to respect the guard.
|
|
|
|
### Teaching (117)
|
|
|
|
Strengths
|
|
|
|
- Wizards that map one-to-one onto the user's own examples: Add a MIDI link with live pickers, Add or remove a HyperDeck adjusting the REC members too, Change the playlist by pasting a link, Add a computer, Add a Windows app task, New campus; plus a demo-mode walkthrough.
|
|
- The live Stream Deck picture on the Overview from sp_state with click-through to the key, a global search box, and a "Stream Deck" (where it sits) versus "Keys" (what it does) split a volunteer gets in one sentence.
|
|
- The safest Apply order (restart the watchdog, prove it, then pages and nav with a dry run shown), the key guide regenerated on every Apply, History never auto-pruned, and "Undo last apply" on the Overview.
|
|
- Makes alert_after_seconds and the fix cooldown editable with the key texts following; validates fix kinds in load_config; requires host or conn on ping checks; the settings server imports only load_config, CHECKS and make_page so a page bug cannot take the panel down.
|
|
- Per-field help with an example and "what you will see on the key"; "done by hand" ticks for things no probe can see; the nav_locations list with a Revert button.
|
|
|
|
Weaknesses
|
|
|
|
- The per-machine inventory is a code catalogue (machines.py) with NA facts in it, not data: weak on R3 and R5.
|
|
- The live-service guard is only a typed phrase and is conditioned on ALARMS being on, so muting alarms disables it; page re-imports are allowed during a service.
|
|
- No edit gate (a PIN is only an open question); drafts live in localStorage.
|
|
- Phase 4 is a single 1,800-line, 4-5 day big bang; tests are rebuilt from scratch rather than made config-driven; the regex-based schema sync is the weakest of the three.
|
|
- The Site screen is a grab-bag (ATEM, grid, hold time, cooldown, thresholds, the Windows app table, SSH key, webhook); no Logs screen; no install.sh non-clobber rule; {playlist} substitution has no fallback for restart keys.
|
|
|
|
### Ideas the judges asked to graft (and where they landed)
|
|
|
|
- From teaching: restart the watchdog and prove it started before pages are rebuilt or imported, and roll pages back too (K10).
|
|
- From teaching: the job wizards for the named asks (K4, P4) and "New campus from this one" (K17).
|
|
- From teaching: the live deck on the Overview from sp_state with click-through (K4); the "what this key will say" preview (K5); the key guide rebuilt on every Apply (K15); History never auto-pruned (K14); Undo the last change (K14); "done by hand" ticks (K8 manual_done); alert_after_seconds and the fix cooldown editable with the key texts following (K12); a global search box (D10).
|
|
- From simplest: the AST-based schema sync test and "defaults in code must equal the schema" instead of removing the defaults from the watchdog (K16); the Phase 0 round-trip test (K16, P0).
|
|
- From simplest: the password-free edit gate, later reduced from allow-list plus unlock plus typed APPLY to one editing code (K2, C3).
|
|
- From simplest: the new-campus cascade that drops and lists dependants, sites/_template, and export stamps as config with a mismatch warning (K17, K9).
|
|
- From simplest: the dedicated Spotify screen with link paste (K9), the generated "Where things are" page (K15, C12), the "Try it on a copy" sandbox (deferred, C4).
|
|
- From operations, kept as the base: draft.json on the server with the editor's name (K10), pages/nav detected by diffing the built JSON (K10), site.live_services (K9, K12), the runs[] model with watched:false, networks[] and pingable (K8), the Companion screen's rename-to and "Add a key for it" (K9), builders with template + params (K6), "Things only a person can do" (K15).
|
|
- Reviewer additions: probe whether tRPC can create custom variables and import the flash trigger before declaring those steps by hand (P1 spike); an Ingest self-check that python3 is 3.9-3.12 because telnetlib disappears in 3.13 (K12); explain the Stream Deck "use last page" setting beside the nav settings (K9 Advanced); a generic never_auto flag instead of "bridge" by name (K12); split settings.html into files; a dated folder for previous ATEM files (K14).
|
|
|
|
## Audit findings and what happened to them
|
|
|
|
Round 1 critics read the first full plan, round 2 the revision that answered them, round 3 the second full revision. Lenses are listed in the order completeness, simplicity, safety, feasibility. K, C, P and Q numbers refer to the decisions list (K = kept, C = cut, P = phase, Q = open question).
|
|
|
|
| Round | Lens | Severity | Finding | Disposition | How the plan handles it now |
|
|
|---|---|---|---|---|---|
|
|
| 1 | Completeness | major | Machine cards only echo what was typed into runs[]; a background task nobody listed stays invisible, so the drift R5 is about is reproduced one level up. | SUPERSEDED | Built as a full-inventory diff with Add/Ignore in revision 2; round 2 Simplicity showed it is vendor noise and it was cut (C5). K8 keeps a collapsed raw "Everything found on this computer" list on the card, so drift is visible on inspection but never counted on Overview. |
|
|
| 1 | Completeness | major | Checks have no builders: remote, process and pref checks still carry hand-typed app names and helper paths that fixes no longer do. | ADOPTED | K5 "Add a check" asks a question and picks the type; checks.*.{template,params} (K12) regenerate the command; the K16 regenerate test covers checks as well as fixes. |
|
|
| 1 | Completeness | major | The new-campus walkthrough omits the bootstrap (Command Line Tools, copying the folder), Companion pages existing, the trigger export, the quiet Tascam package, nav templates, surfaces. | SIMPLIFIED | K17 companion-objects/ (trigger export, quiet Tascam module, nav_templates per Companion version) is captured in P1 and deployed by install.sh (K13); K9 Companion lights cover pages exist, our pages and the quiet module; surfaces are not shown (C11). Copying the staged folder to a new Mac stays scp by hand (K13). |
|
|
| 1 | Completeness | minor | Changing the page number or name is refused by push_page's name rule, or leaves the old page live; no path forward. | SUPERSEDED | Replaced by round 3 Safety's marker-only rule: K10 accepts a page when every non-nav key carries our marker, whatever its name. Old-page cleanup waits on the P1 resetControl spike; until then Review lists the keys to delete by hand. |
|
|
| 1 | Completeness | minor | "Test this fix now" is offered for every fix, including PoE power-cycle, ATEM restore, dante-auto and pkill fixes. | ADOPTED | K7: Run this fix now only for start/reconnect kinds, never during a live service, always through the watchdog. |
|
|
| 1 | Completeness | minor | "HOLD 2s" and "WAIT 1 MIN" are hard-coded in the watchdog; the "config loaded" log line Apply waits for does not exist. | ADOPTED | K12 reads page_hold_ms and timing.fix_cooldown_seconds with defaults; started.json with the config sha (K10, K12) replaces the log line. |
|
|
| 1 | Completeness | minor | site.live_services is new and has no stated default, so the guard is empty on day one. | ADOPTED | K12: it defaults to auto_fix.windows and the P0 migration writes it into NA's config. |
|
|
| 1 | Completeness | minor | No builders for rtpmidi_start, ableton / ableton_restart or translate_restart; they fall to Custom with free-text names. | ADOPTED | K6 adds Start a Windows service (+task), Reopen Ableton with its last set, and Restart a Mac program with "also stop everything it started"; all 27 fixes map to builders. |
|
|
| 1 | Completeness | minor | solo-mode-agent.swift is "deployed unchanged" yet its paths are said to come from site.solo_dir. | ADOPTED | P5 generates the swift agent from a template with the Pro Tools parameters; K13 deploys remote-access/*.template. |
|
|
| 1 | Completeness | minor | Phase 0 removes hyperdeck_probe but TestHyperDeckProbe and the fix-kinds assertion are untouched, so Phase 0 cannot be green. | ADOPTED | K16 asserts CHECKS/FIX_KINDS equality against the exported FIX_KINDS (K12); D8 removes hyperdeck_probe and TestHyperDeckProbe/FakeDeck in P0. |
|
|
| 1 | Completeness | minor | The settings page and Companion's tablet view cannot link "to each other"; only one direction is possible. | ADOPTED | P0 writes the page address into the ALL key's note; the K15 cheat sheet carries the address. |
|
|
| 1 | Completeness | minor | The wireframe example "x32 not in Companion, rename to m32" contradicts the inventory. | NOT A GAP | A wireframe illustration only; K9 draws the connection list live from /api/connections and no canned example survives into the plan. |
|
|
| 1 | Simplicity | major | Engineering vocabulary (ids, hold_always, sp_state, --once, file names, raw shell) sits on nearly every primary surface. | ADOPTED | K15 wording rule and test over ui/strings.json, schema help and the Help pages: no underscored names, flags, extensions, Companion internals or launchd labels; raw strings only under Advanced. |
|
|
| 1 | Simplicity | major | "What runs where" is not the default view; Computers opens on dense cards. | ADOPTED | K8 Computers opens on the Map: one row per computer with a status word, what it does for the panel and the keys that turn red; click a row for the card. |
|
|
| 1 | Simplicity | major | Five gating concepts stack (per-tab unlock, editors list, name, typed APPLY, shared draft) plus a sandbox switch on two screens. | SIMPLIFIED | K2 one editing code plus a first name remembered by the browser; K3 one Editing toggle; a typed word only for Emergency and Stop (C3); one shared draft whose 409 names the person (K10); the training copy is deferred (C4). |
|
|
| 1 | Simplicity | major | Sixteen menu entries in five groups; the wizards for the user's own asks are buried last. | ADOPTED | K3 eight always-visible entries, Site setup and Fixes under a "Set up once" divider; K4 puts the job buttons on Overview. |
|
|
| 1 | Simplicity | major | Review & Apply exposes the pipeline (check names, a seven-step list, --once, raw diff, typed word). | ADOPTED | K10 Review is a plain-words diff with command edits in red and "what Apply will do"; K14 History rows are "Go back to this". |
|
|
| 1 | Simplicity | major | The key editor shows every field for every check type at full depth. | ADOPTED | K5 progressive fields with the two previews at the top; per-type raw fields and the 19 types under Advanced. |
|
|
| 1 | Simplicity | minor | Overview packs twelve blocks and puts Undo last apply on the home screen. | ADOPTED | K4 Overview: problems first, the deck, computers, jobs, status lines; Undo lives in History (K14). |
|
|
| 1 | Simplicity | minor | Four unexplained status marks on the checklists. | ADOPTED | K8 Setup lights are words: OK / Not done / Can't see from here / Not needed / Done by hand. |
|
|
| 1 | Simplicity | minor | The Companion screen is a page of internals (export stamps, grid, purple-after, trigger names). | ADOPTED | K9 Companion shows lights and live connections; address, variable names, nav, grid, purple-after and export stamps under Advanced. |
|
|
| 1 | Simplicity | minor | Three words for the same thing (key/tile/button, machine/computer/host, fix/builder/task); "Alias" is the first field on a card. | ADOPTED | K15 four words only (key, computer, fix, connection), enforced by the wording test. |
|
|
| 1 | Simplicity | minor | Help has no "start here"; the glossary is alphabetical. | ADOPTED | K15 Help opens on four cards; the glossary is grouped by action (hold fixes it / check the device / ask Chris). |
|
|
| 1 | Simplicity | minor | The read-aloud test is scheduled only in Phase 5. | ADOPTED | P1 exit criterion: a newcomer explains Overview, Computers and Help back in 20 minutes; D9 adds the same for Review & Apply, the Spotify section and one key editor at the end of P2. |
|
|
| 1 | Simplicity | minor | Routine code updates still need MacBook, scp, ssh install.sh; no "Update program" path on the page. | SIMPLIFIED | K13 "Install the staged folder" from the page as a one-shot launchd job; the staged folder still arrives by scp (no git credential on Ingest); pull_site.py is replaced by Export site bundle (K17). |
|
|
| 1 | Simplicity | minor | Schedules offers an editable "Alarms are armed" window; the Mute button does not say what it does. | ADOPTED | K9 one schedule and "alarms are always on" as one sentence everywhere; K4 button "Silence alarms until midnight". |
|
|
| 1 | Safety | blocker | The settings server is unauthenticated remote code execution on every private range with no CSRF defence; a draft's remote.cmd runs before Apply via --once and the probes. | SIMPLIFIED | K2 one editing code (a setting in the repo's config, lockout, origin check on writes); K6 command edits are red in Review and need the code again; K8 probes run a fixed set with quoted parameters; there is no --once preview. The address allow-list was cut (C3). Residual: one code over plain HTTP on the LAN. |
|
|
| 1 | Safety | major | Every Apply kickstarts the watchdog with no SIGTERM handler: a fix in flight is killed (HyperDeck left disabled), cooldowns, acks and tries lost, UI-only edits restart too. | ADOPTED | K12 SIGTERM handler lets the fix finish, fixes-running.json, state.json persists acks/tries/cooldowns, the HyperDeck re-enable sits in a finally; K10 waits for no fix and page-only changes skip the restart. The SIGHUP alternative was cut (C1). |
|
|
| 1 | Safety | major | Apply success and rollback hinge on sp_hb, which needs Companion: spurious rollbacks and a loop with no terminal state. | ADOPTED | K10 success = started.json newer than T with our sha, no traceback, alive after 10 s; rollback once; red notice until the next good Apply. |
|
|
| 1 | Safety | major | "Test this fix now" runs outside the watchdog, bypassing the recording guard, cooldown and logging; it can PoE-cycle. | ADOPTED | K7 test verb through the watchdog with the recording guard, cooldown and TEST logging; start/reconnect kinds only. |
|
|
| 1 | Safety | major | One draft.json, last PUT wins, no base version, no Apply lock. | ADOPTED | K10 one shared draft with base_sha and a 409 naming the person and the field; D1 adds a server-side apply.lock so a second Apply is refused outright. |
|
|
| 1 | Safety | major | Page rules incomplete: name-only safe_target, a renumbered page leaves an orphan, a missing variable is not a hard error. | SIMPLIFIED | K10 marker-only rule replaces the name rule; Companion-dependent checks are soft warnings so Apply still works with Companion down; old-page cleanup waits on the P1 resetControl spike (by hand until then). |
|
|
| 1 | Safety | major | The live-service guard is clock-only; add recording, stream and Resi signals. | SUPERSEDED | Round 2 Safety and Feasibility showed the stream and Resi signals are always true; K11 keeps the one real signal (a HyperDeck that follows the recording is recording) and C7 defers OBS to the spike. |
|
|
| 1 | Safety | major | An ATEM file upload replaces the switcher reference during a service; only "XML parses" is checked, no size cap, no entity guard. | ADOPTED | K9 upload or pick-newest with a diff and a tick; K11 refuses Apply while live; K10 writes config and xml together; K14 keeps dated copies; D3 caps uploads at 20 MB and refuses XML with a DOCTYPE or entities. |
|
|
| 1 | Safety | minor | Builders interpolate names and paths into shell strings without quoting. | ADOPTED | K6 shlex-quoted Mac parameters, the Windows regex, zsh -n / sh -n, byte-identical regenerate test; K16 metacharacter case. |
|
|
| 1 | Safety | minor | Secrets leak: the webhook in config, draft, history and diffs; module passwords from db.sqlite; fetch_page without includeSecrets=false. | ADOPTED | K2 webhook masked on every readable surface; K14 history bodies masked; K10 re-fetches with includeSecrets=false; C11 module id from /api/connections only, no DB rows. |
|
|
| 1 | Safety | minor | Page rollback re-runs the failing push; build hashes recorded before verification; "pages out of sync" is not persisted. | ADOPTED | K10 records a build only after a verified import; the K4 "Needs Chris" strip shows pages out of sync and failed-apply restored; red notice until the next good Apply. |
|
|
| 1 | Safety | minor | The typed word normalises a watchdog restart during a service; kickstart fails if the agent is not loaded. | SUPERSEDED | Its "queue the restart" fix was found unsafe by round 2 and 3 Safety and cut (C2); K11 refuses while live with an Emergency override that logs who and why; K10 bootstraps the plist if it is not loaded. |
|
|
| 1 | Feasibility | major | Apply success waits for a log line that does not exist and passes on the old process's heartbeat. | ADOPTED | K10 and K12 started.json {pid, started_at, config_sha} newer than T, no traceback, alive 10 s, polled 25 s (refined by round 3 Feasibility's log-rotation point). |
|
|
| 1 | Feasibility | major | "The whole test suite per site" ignores some sixty NA-specific assertions. | ADOPTED | P0 freezes tests/fixture-config.json; only test_sites_validate runs over every site (K16, K17). |
|
|
| 1 | Feasibility | major | Running run_once in the server process blocks 10-30 s with CoreMIDI and ssh and must scrape stdout. | SUPERSEDED | The --once preview was dropped after round 2 Safety (TCC prompt) and round 3 Feasibility (no-op flags); K10 validates with load_config on a temp file and make_page in memory only. |
|
|
| 1 | Feasibility | minor | The schema-sync test misses chained receivers and expression defaults; the glossary scan collects log strings. | ADOPTED | K16 receiver-aware AST walk, defaults compared where literal, the glossary test over fault words only. |
|
|
| 1 | Feasibility | minor | A restart loses acks, debounce, auto-fix tries and cooldowns; Review does not say so. | ADOPTED | K12 persists acks, tries and cooldowns in state.json keyed by check identity. |
|
|
| 1 | Feasibility | minor | build-hashes.json has no seed; a page-number change leaves the old page populated. | SUPERSEDED | P3 seeds the hashes from the live exports (round 3 Safety); the old-page reset depends on the P1 resetControl spike (round 2 Feasibility). |
|
|
| 1 | Feasibility | minor | Phase 0 flips install.sh to non-clobber before the UI exists, so an old-style config deploy silently does nothing. | ADOPTED | K13 and P2: install.sh stops overwriting site-owned files only once the page exists, with a diff notice. |
|
|
| 1 | Feasibility | minor | The page tools load config from their own folder, settings/ needs sys.path, the module version is not in /api/connections. | SIMPLIFIED | K10 make_page writes into the data dir and K13 deploys the tools there; C11 shows the version only if the spike finds it trivially; pull_site.py is replaced by Export site bundle (K17). |
|
|
| 1 | Feasibility | minor | Stop watchdog has no Start; the shared Spotify Automation permission is an assumption. | SIMPLIFIED | K11 allows Start while the watchdog is down and K10 bootstraps a missing agent; K9 shows one permission light; the P1 spike checks whether one Automation grant covers both agents. |
|
|
| 2 | Completeness | major | The live-now signals are hard-coded NA facts (the stream connection, the Resi encoder); add site.live_signals[]. | CUT | C7: the conn/var/value signal list was cut after round 3 Simplicity; K11 keeps the built-in "a HyperDeck is recording", derived from each site's own checks; OBS only if the spike finds the variable. |
|
|
| 2 | Completeness | major | The builder mapping is wrong for translate (open-only), captions (two agents) and dvs_ingest (chained ProdCom restart). | ADOPTED | K6 splits Start from Restart a Mac program, Restart helpers takes a list, dvs_ingest renders the ProdCom step inline; all 27 regenerate byte-identical. |
|
|
| 2 | Completeness | minor | "Sunday may run it by itself" bakes NA's day into strings.json. | ADOPTED | K15 wording test forbids day and site names in typed text; K9 builds the one schedule sentence from the windows. |
|
|
| 2 | Completeness | minor | No key can alarm on "a program is running on a Windows PC". | ADOPTED | K12 Windows remote checks batched per PC; K5 "Is a program running?" picks the type from the computer chosen. |
|
|
| 2 | Completeness | minor | spotify.name has a field but nothing reads it; labels keep the old playlist name. | ADOPTED | K12 reads spotify.{playlist,name,open_wait,play_wait}; K9 one link field plus name; the K6 Play builder derives the label. |
|
|
| 2 | Completeness | minor | Add or remove a HyperDeck leaves the kept decks' optional flag untouched. | ADOPTED | P4: the job asks per kept deck "may it have no disk?". |
|
|
| 2 | Completeness | minor | hosts.ssh is classed R, but the MIDI streams and pollers keep the old address after SIGHUP. | CUT | C1: no partial reload; every Apply restarts the watchdog. |
|
|
| 2 | Completeness | minor | The edit key written to the login keychain by install.sh over ssh may fail silently. | SUPERSEDED | The user chose (2026-10-13) to keep the code in config.json in the private repo (K2); nothing is written to the keychain. |
|
|
| 2 | Completeness | minor | The surfaces light has no data source. | CUT | C11: surfaces are not shown. |
|
|
| 2 | Completeness | minor | A changed SSH host key needs a Terminal step. | ADOPTED | K8 Setup tab: Forget the old login key. |
|
|
| 2 | Completeness | minor | The nav walk stops at the first 404; a new page never prompts a re-run. | SIMPLIFIED | C6 drops periodic detection; K9 shows "coloured on N of M pages" when the section opens, with Colour them now and Undo; the walk rule is a P1 spike item. |
|
|
| 2 | Completeness | minor | The ATEM file's origin folder is NA-specific screen text with no key. | ADOPTED | K12 atem.source_folder; K9 "pick newest from folder". |
|
|
| 2 | Completeness | minor | solo-mode-agent.swift's menu titles and bundle id are literals. | ADOPTED | P5 templates the swift agent with the Pro Tools parameters. |
|
|
| 2 | Completeness | minor | Add a MIDI link only picks an existing peer; no new-peer entry or "also watch" options. | SIMPLIFIED | P4 adds a typed fallback for session and peer; the extra Bonjour and Companion-connection tick boxes are not in the decisions. |
|
|
| 2 | Simplicity | major | History (and Undo) is reachable only through the unsaved-changes badge. | ADOPTED | K3 History is always in the menu; K14 Go back and Undo live there. |
|
|
| 2 | Simplicity | major | Editing needs an IP allow-list, the key and a name; a device on DHCP is refused without explanation. | ADOPTED | K2 code plus name only; no address allow-list (C3). |
|
|
| 2 | Simplicity | major | Four schedule notions (live, auto-fix's own windows, alarms armed, mute) plus timing on one screen. | ADOPTED | K9 one schedule, alarms always on, timing numbers under Advanced; K4 Silence alarms until midnight. |
|
|
| 2 | Simplicity | major | Two fix pickers per key; the preview answers only what the key says, not what holding does. | ADOPTED | K5 "HOLDING 2 s WILL" preview, one "When held" section with the builder inline, "also when the key is green". |
|
|
| 2 | Simplicity | major | Two edit homes each for Dante devices, the playlist, page numbers and HyperDecks. | ADOPTED | K9 the DEVICE LIST is the only home of the DANTE key's devices and Spotify has one link field; K5 the page number lives in the Keys tab header. |
|
|
| 2 | Simplicity | major | Half the keys point at gear that is not a computer and has no home. | ADOPTED | K8 Gear filter (address, kind, where, watched by, light); K15 "Which computer or device is that" card; C13. |
|
|
| 2 | Simplicity | major | The full-inventory probe shows vendor noise and counts it on Overview. | CUT | C5: the diff, ignore lists and Add/Ignore were cut; a collapsed raw list on the card (K8); no counts on Overview. |
|
|
| 2 | Simplicity | major | A change queued during a service is invisible; nothing says it is pending. | CUT | C2: no queue; K11 refuses while live, the draft stays saved and Review says when the service ends. |
|
|
| 2 | Simplicity | major | "Edit key", "SSH key", "nav keys" and "connection" collide with the three-word rule. | ADOPTED | K15: "editing code", "login key", "page-number buttons"; connection becomes the fourth defined word. |
|
|
| 2 | Simplicity | major | The settings page needs its own Spotify permission, a Test button and an extra Allow step. | ADOPTED | K9 one permission light; K7 Run now goes through the watchdog so the page never drives Spotify; the P1 spike checks the grant. |
|
|
| 2 | Simplicity | minor | Map cells are walls of text. | ADOPTED | K4 and K8: one status word per row, what it does, the keys that turn red. |
|
|
| 2 | Simplicity | minor | Six different "test" buttons with unclear effects. | ADOPTED | K9 read-only buttons say "Check ..." ; K7 "Run this fix now" is the one that acts. |
|
|
| 2 | Simplicity | minor | Update the program and the campus export sit on the normal Site screen; pull_site.py is a terminal step. | SIMPLIFIED | C12 Install the staged folder and Export site bundle sit under Site setup (set up once); the K17 export replaces pull_site.py; scp remains (K13). |
|
|
| 2 | Simplicity | minor | Per-editor drafts with take-over and discard add a multi-user merge concept. | ADOPTED | K10 one shared draft; the 409 names who changed what. |
|
|
| 2 | Simplicity | minor | The Keys grid draws three overlays; "+ New key" offers ALL, ALARMS and NET. | ADOPTED | K5 draws the 8x4 deck; fixed chips for ALL / ALARMS / NET. |
|
|
| 2 | Simplicity | minor | Overview carries admin wizards, gear, a log tail and duplicate lights. | ADOPTED | K4 problems, the deck, computers, three job buttons plus More jobs, status lines (round 3 Simplicity set the three). |
|
|
| 2 | Safety | major | kickstart SIGKILLs after launchd's 5 s; the 30 s join exceeds it; check-then-act race on fixes-running.json. | ADOPTED | K12 ExitTimeOut derived at install, join bounded, new fixes refused once SIGTERM arrives (RESTARTING SOON), HyperDeck re-enable in a finally; K10 waits first. |
|
|
| 2 | Safety | major | The stream and Resi signals are always true; a stale live-now.json is undefined. | ADOPTED | K11 HyperDeck recording only, live-now.json timestamped, older than 30 s = schedule only and said in Review; OBS deferred (C7). |
|
|
| 2 | Safety | major | Writing config during a service and queuing the restart: KeepAlive can relaunch on the unverified config mid-service. | CUT | C2: no queue; K11 refuses while live so disk and process never diverge. |
|
|
| 2 | Safety | major | The R class includes keys read only at start (pollers, ServiceMode, run()). | CUT | C1. |
|
|
| 2 | Safety | major | Code deploys validate only JSON; no code rollback; the page-driven install kills its own agent. | ADOPTED | K13 validates with the new code before bootout, keeps prev/ with --rollback, restarts the watchdog first and settings last, as a one-shot launchd job. |
|
|
| 2 | Safety | major | Reads (logs, the fleet inventory, history bodies, generated scripts) are open to every private address including Wi-Fi. | SIMPLIFIED | K2 deliberately keeps reads open so teaching needs no code (round 3 Simplicity); K1 narrows the bind to hosts.ingest.networks; the webhook is masked. Residual: the fleet map is visible to anyone on the LAN. |
|
|
| 2 | Safety | major | `test <fix>` carries no key or check context and could toggle the wrong deck or peer. | ADOPTED | K7 `test <key> <fix> <identity> <time>`, resolved exactly as a hold. |
|
|
| 2 | Safety | minor | atem-reference.xml is outside the transaction, replaced in place and not restored on rollback. | ADOPTED | K10 config and xml written together (.tmp + os.replace), hash in History, rollback restores both; K14 Go back names the file. |
|
|
| 2 | Safety | minor | Remote command strings are not syntax-checked; Windows `!` and `^` are allowed. | ADOPTED | K6 sh -n / zsh -n; the Windows regex excludes exclamation, caret, ampersand, pipe, percent and quotes; Custom under Advanced in red. |
|
|
| 2 | Safety | minor | Two writers for dante-map.json; sp_cmd read-modify-write from the page can clobber a hold. | SIMPLIFIED | K12 resurvey verb through the watchdog; C10 keeps page requests on the command variable like holds. Residual: a request can race a deck hold on sp_cmd. |
|
|
| 2 | Safety | minor | Hard validation needs Companion up; resetControl to blank a cell is untested. | ADOPTED | K10 soft live warnings; P1 spike "resetControl blanks a cell?" with a by-hand fallback. |
|
|
| 2 | Safety | minor | Stop, Revert nav, Prune, Re-import and Install have no confirmation; Mute sits under the guard. | ADOPTED | C3 one dialog style stating the consequence, a typed word for Stop and Emergency; K11 Silence alarms is never guarded. |
|
|
| 2 | Safety | minor | The --once preview triggers a TCC prompt; the ATEM snapshot opens a second client with no guard. | SIMPLIFIED | There is no --once preview in K10; "Check the switcher now" is in K11's guarded list. The ATEM client limit is not noted beside the button. |
|
|
| 2 | Safety | minor | wmic is gone on Windows 11 24H2; the edit key is made over ssh; Pull needs a stored git credential. | ADOPTED | K2 the code is a config setting in the repo; K13 no git credential and no Pull button; D4 Windows probes use Get-CimInstance and schtasks /Query /FO CSV, never wmic. |
|
|
| 2 | Safety | minor | The nav walk stops at a gap; hand-moved pages are not detected. | SUPERSEDED | Round 3 Feasibility put the walk rule in the P1 spike; periodic detection was cut (C6) in favour of the K9 count plus Colour them now. |
|
|
| 2 | Feasibility | major | The R apply class cannot work: start_pollers and Engine capture cfg once. | CUT | C1. |
|
|
| 2 | Feasibility | major | The 30 s graceful stop exceeds launchd's 5 s exit timeout; fix threads are anonymous daemon threads. | ADOPTED | K12 ExitTimeOut derived at install, a thread registry behind fixes-running.json, join at most ExitTimeOut-5; K16 SIGTERM mid-fix test. |
|
|
| 2 | Feasibility | major | The live signals are mostly always-true; use the OBS streaming variable. | SIMPLIFIED | K11 HyperDeck recording only; C7 adds OBS as a built-in kind only if the P1 spike finds the variable. |
|
|
| 2 | Feasibility | major | The test verb with an empty chk raises KeyError for HyperDeck and MIDI fixes. | ADOPTED | K7 verb carries key and identity; K12 identity per check type. |
|
|
| 2 | Feasibility | major | Phase 2 allows hold-ability edits a phase before pages can be re-imported. | ADOPTED | P2 refuses layout changes until P3 ("available after the layout step"). |
|
|
| 2 | Feasibility | major | Phase 0 "byte-identical, no re-import" contradicts its note changes; split into 0a/0b. | SIMPLIFIED | K16 roundtrip strips notes and P0 is "deck identical apart from key notes"; P0 stays one phase of about 1.5 days (no 0a/0b split). |
|
|
| 2 | Feasibility | minor | The marker rule misses the two static jump keys. | ADOPTED | K10 every non-nav key must carry our marker; P0 adds the markers in make_page. |
|
|
| 2 | Feasibility | minor | /api/program/install kills the agent that is running it. | ADOPTED | K13 one-shot launchd job, settings agent last, AbandonProcessGroup. |
|
|
| 2 | Feasibility | minor | "Pull from repo" does not fit the real setup (no clone, the alias points the other way). | ADOPTED | K13 drops Pull; scp staging plus Install the staged folder. |
|
|
| 2 | Feasibility | minor | install.sh cannot write the keychain over ssh. | ADOPTED | K2. |
|
|
| 2 | Feasibility | minor | A receiver-less AST walk will never pass against this code. | ADOPTED | K16 receiver-aware walk with a UI-only allowlist. |
|
|
| 2 | Feasibility | minor | moduleVersionId, resetControl and tRPC variable creation are unverified Companion facts. | ADOPTED | P1 spike with recorded answers and fallbacks; C11 version only if trivial. |
|
|
| 2 | Feasibility | minor | Acks persisted by check index re-attach to the wrong check after an edit. | SUPERSEDED | Round 3 Feasibility showed type-plus-sub keys collide too; K12 keys state by a per-type identity and drops it for keys whose checks changed. |
|
|
| 2 | Feasibility | minor | Two Automation grants are assumed; one very likely covers both agents. | ADOPTED | P1 spike; K9 one light. |
|
|
| 3 | Completeness | major | The server binds only hosts.ingest.networks; the template has no ingest record; an empty list is undefined. | ADOPTED | K1 always 127.0.0.1 plus every private-address interface when the list is empty (with a grey notice); K17 the template has an ingest self record with networks []. |
|
|
| 3 | Completeness | major | install.sh's deploy list omits the remote-access templates and companion-objects. | ADOPTED | K13 deploys both; K17 nav_templates/<version>.json. |
|
|
| 3 | Completeness | major | Windows batching with %ERRORLEVEL% expands before the command runs, so every check reports OK. | ADOPTED | K12 generates per-command conditional echo pairs (SPn=0 on success, SPn=1 otherwise), never a bare %ERRORLEVEL%, verified once on the Lighting PC. |
|
|
| 3 | Completeness | minor | No expected module per check type; a HyperDeck check on a generic TCP connection is silently wrong. | ADOPTED | K12 EXPECTED_MODULE filters the pickers and warns on mismatch; it lives in the K16 registry. |
|
|
| 3 | Completeness | minor | restart_page is optional but the Keys screen always has the tab and chips. | ADOPTED | K9 "this campus has no Restart page" switch (built in P3). |
|
|
| 3 | Completeness | minor | Windows cannot cross midnight. | ADOPTED | K18. |
|
|
| 3 | Completeness | minor | Add a MIDI link has no typed fallback when the Mac is off. | ADOPTED | P4. |
|
|
| 3 | Completeness | minor | The Ingest self record can be named by ssh fixes, remote checks and midi_peer (a runtime KeyError). | ADOPTED | K12 host validated (exists, has ssh, not self); builders switch to local for the self record. |
|
|
| 3 | Completeness | minor | The OBS streaming variable is seeded without verification. | ADOPTED | P1 spike reads it on and off air; C7 adds the kind only then. |
|
|
| 3 | Simplicity | major | About 25 destinations; Help doubles as the admin console. | SIMPLIFIED | K3 eight entries, the two set-up-once screens under a divider and readable by anyone (one rule: the code changes things); C12 admin actions sit there, Help keeps the recipes. Residual: a volunteer can open Site setup and see it. |
|
|
| 3 | Simplicity | major | Schedules asks for a Companion connection, variable and value to define a live signal. | CUT | C7. |
|
|
| 3 | Simplicity | major | "+ Add a check" lists 19 implementation types. | ADOPTED | K5 asks a question first; the 19 types sit under Advanced. |
|
|
| 3 | Simplicity | major | The walkthrough needs the editing code (Logs, History, the training copy). | ADOPTED | K2 reads are open; K15 the walkthrough needs no code; C4 defers the training copy. |
|
|
| 3 | Simplicity | major | The Overview problem line mixes room problems with admin notices. | ADOPTED | K4 room problems versus a grey "Needs Chris" strip. |
|
|
| 3 | Simplicity | minor | Three status vocabularies across Overview, Setup and Gear. | ADOPTED | D7 one legend for the whole page (OK / Problem + reason / Can't see from here / Not needed / Done by hand), printed once under the top bar's "?". |
|
|
| 3 | Simplicity | minor | The plan's own wireframes contain forbidden tokens; extend the wording test to the rendered DOM. | SIMPLIFIED | C8 keeps the test over strings, help and Help pages; K5 shows "Page 19" and chips. Residual: live Companion labels can appear raw in table cells. |
|
|
| 3 | Simplicity | minor | "Alarms are always on" next to a Pause button. | ADOPTED | K9 one sentence everywhere; K4 "Silence alarms until midnight". |
|
|
| 3 | Simplicity | minor | The page is "Status Panel Settings" and one menu entry is "Settings". | ADOPTED | K3 "Site setup". |
|
|
| 3 | Simplicity | minor | The Fixes catalogue is a second mental model beside "When held". | ADOPTED | K5 the builder sits inline under "When held"; K3 the Fixes catalogue sits under the "Set up once" divider. |
|
|
| 3 | Simplicity | minor | The Map lacks "keys that turn red"; Gear is a separate tab. | ADOPTED | K8 Map rows carry the keys that turn red; Gear is a filter (C13). |
|
|
| 3 | Simplicity | minor | ssh-keygen for the panel's own key is still a Terminal step. | ADOPTED | K8 Setup tab: Make the login key. |
|
|
| 3 | Simplicity | minor | Tuning numbers on the main screens. | ADOPTED | K9 every number under Advanced with its default beside it. |
|
|
| 3 | Simplicity | minor | Add a MIDI link is hidden under More jobs. | ADOPTED | K4 three job buttons. |
|
|
| 3 | Simplicity | minor | The "Not on the deck" tray is unexplained. | ADOPTED | K5 tray labelled "Shown inside the RF group (no key of their own)". |
|
|
| 3 | Simplicity | minor | Watchdog controls in two places, two magic words, second confirmations. | ADOPTED | C3 one confirmation style; D6 Start / Stop / Restart the watchdog live on Overview only, Stop behind the typed word. |
|
|
| 3 | Safety | blocker | No loopback listener, so /edit-key is unreachable and nobody can ever switch Editing on. | SUPERSEDED | There is no /edit-key page: the code is a config setting in the repo (K2, the user's choice 2026-10-13); K1 still binds 127.0.0.1 always. |
|
|
| 3 | Safety | blocker | setsid does not exist on macOS; the installer dies with the agent's process group half-way. | ADOPTED | K13 one-shot launchd job, AbandonProcessGroup on the settings plist, the watchdog bootstrapped first. |
|
|
| 3 | Safety | major | safe_target's name shortcut silently wipes hand-added keys. | ADOPTED | K10 marker-only rule; Review lists foreign keys by position; Apply refuses. |
|
|
| 3 | Safety | major | Raw commands behind one plaintext reusable code; no lockout; the allow-list off by default. | SIMPLIFIED | K2 lockout (5 tries, 10 min) and origin check; K6 Custom commands are red and re-ask the code. Admin code, RUN word and allow-list were cut (C3). Residual: one code on a LAN is a remote-command surface. |
|
|
| 3 | Safety | major | Probes interpolate names and paths from config into ssh lines. | ADOPTED | K8 quoted and regex-checked parameters; K16 metacharacter test proving the ssh line is inert. |
|
|
| 3 | Safety | major | A stale stop flag disables every fix forever. | CUT | C10: no stop flag; the SIGTERM handler plus the fixes-running.json wait cover it. |
|
|
| 3 | Safety | major | SIGHUP sent to old code kills the watchdog. | CUT | C1; K12 keeps the "(code X)" log line for install and rollback tracking. |
|
|
| 3 | Safety | major | The queued job has no hysteresis and no base_sha recheck; Start should be exempt from Emergency. | CUT | C2; K11 allows Start while the watchdog is down. |
|
|
| 3 | Safety | minor | A 409 merges silently. | ADOPTED | K10 "<name> changed this a moment ago - your change to <field> was not kept", with the field re-offered. |
|
|
| 3 | Safety | minor | history, draft and pending copies hold the unmasked webhook. | ADOPTED | D2 every file the settings agent writes in the data dir (draft, history, cache, log, code fallback) is 0600; K14 serves bodies masked; pending.json is gone (C2). |
|
|
| 3 | Safety | minor | Seeded build hashes are "assumed current". | ADOPTED | P3 seeds them from the live exports. |
|
|
| 3 | Safety | minor | A PC whose DefaultShell is not cmd returns garbage silently. | ADOPTED | K12 light plus refusal of cmd-batched checks for that PC (setting DefaultShell stays a by-hand step). |
|
|
| 3 | Safety | minor | Holds queued during the restart gap fire on the new process. | ADOPTED | K12 sp_cmd cleared once at start and logged. |
|
|
| 3 | Feasibility | major | cmd.exe %ERRORLEVEL% batching always reports OK. | ADOPTED | K12 (the same fix as round 3 Completeness). |
|
|
| 3 | Feasibility | major | A (key, type, sub) identity collides on the MIDI key; the test verb cannot pick a peer. | ADOPTED | K12 per-type identity (midi_peer = host, session, peer; remote = host, cmd; ...); K7 the verb carries it. |
|
|
| 3 | Feasibility | major | test_apply_class contradicts the R rows. | CUT | C1. |
|
|
| 3 | Feasibility | major | The LAN-only bind leaves /edit-key unreachable; interface names cannot be bound, only addresses. | ADOPTED | K1 and D5: bind by address (127.0.0.1 always, plus each LAN interface's IPv4), re-checked every minute and rebound on change. |
|
|
| 3 | Feasibility | major | install.sh copies atem-reference.xml (and nav_locations, built pages) over the data dir. | ADOPTED | K13 never overwrites site-owned files without --config, --site or --force-site-files, with a diff notice. |
|
|
| 3 | Feasibility | major | Phase 0b and Phase 2 bundle too much to test as single steps. | SIMPLIFIED | C1, C2, C4, C7 and C10 remove most of the load; P0 and P2 stay single phases (about 1.5 and 4 days). |
|
|
| 3 | Feasibility | minor | --skip-spotify is a no-op; the Preview shows unjudged keys green. | SIMPLIFIED | There is no preview run in K10, so there are no flags to get wrong. |
|
|
| 3 | Feasibility | minor | A `then` chain breaks byte-identical regeneration for dvs_ingest; restart_ok is misstated. | ADOPTED | C9 no chain executor; K6 renders the second step inline; byte-identical for all 27. |
|
|
| 3 | Feasibility | minor | ServiceMode._save clobbers persisted acks; live-now.json written every tick. | ADOPTED | K12 one atomic state.json writer that ServiceMode merges into; K11 live-now on change or every 5 s. |
|
|
| 3 | Feasibility | minor | ExitTimeOut 40 s is shorter than fixes legitimately run. | ADOPTED | K12 derived at install (max fix timeout + verify + 10, floor 60); re-enable in a finally. |
|
|
| 3 | Feasibility | minor | The page_number_N_name walk is unproven. | ADOPTED | P1 spike item; C6. |
|
|
| 3 | Feasibility | minor | The self record is referenceable by ssh fixes. | ADOPTED | K12 (the same fix as round 3 Completeness). |
|
|
| 3 | Feasibility | minor | Tailing a rotating log can miss the lines and trigger a false rollback. | ADOPTED | K10 and K12 started.json; the log is read only for tracebacks. |
|
|
|
|
Disposition totals over the 157 findings: ADOPTED 113, SIMPLIFIED 20, CUT 13, SUPERSEDED 10, NOT A GAP 1.
|
|
|
|
## Deliberate cuts and why
|
|
|
|
C1, partial reload. The watchdog will not re-read parts of its settings on a signal; every Apply restarts it, so the deck goes purple for about five seconds, outside services. What was lost is the comfort of changing a timing number without a restart. It is acceptable because the reload could never rebuild the pollers and the service mode (round 2 Feasibility), a signal sent to old code kills the process, and a whole family of apply-class tests disappears.
|
|
|
|
C2, queued apply. A change made during a live service is refused rather than saved for later; the draft stays and a person comes back to press Apply. What was lost is "it will go live by itself at 13:30". It is acceptable because the queue meant the file on disk disagreeing with the running process for hours, a job restarting the watchdog unattended in the gap between two services, and a pending state nobody could see; the Emergency override covers a real need.
|
|
|
|
C3, extra gates. There is no admin code, no address allow-list, no RUN re-typing and no second confirmations; one code, one dialog style, and a typed word only for Emergency during a service and for stopping the watchdog. What was lost is defence in depth around command edits. It is acceptable because an IP list is invisible to the person it blocks and one code is what volunteers can actually hold; raw command edits still turn red in Review and ask for the code again.
|
|
|
|
C4, training copy. The sandbox where a trainee could press Apply against a copy is deferred. What was lost is a risk-free place to practise editing. It is acceptable because reads are open to the LAN, so the whole walkthrough works with Editing off, and the copy can be added in a day once the page is driven by the config.
|
|
|
|
C5, full-inventory diff. Computers are not scanned for every agent, login item, port and service and diffed against the list, and there are no vendor ignore lists or Add/Ignore buttons. What was lost is an automatic "something new appeared on this computer". It is acceptable because on a real Mac or PC the list is Google, Adobe and Microsoft noise; the raw "Everything found on this computer" list on the card still shows it all when somebody looks.
|
|
|
|
C6, page-button probe. Nothing polls Companion to notice pages that were moved or added by hand. What was lost is an Overview line that appears by itself. It is acceptable because the count "coloured on N of M pages" when the Companion section opens, with Colour them now and Undo, covers the step the user keeps forgetting, and the background walk rule it would need is unproven.
|
|
|
|
C7, live-signal triples. The Schedules screen does not let anyone define "live" as a Companion connection, variable and value. What was lost is OBS or Resi counting as live. It is acceptable because only "a HyperDeck is recording" was ever a real signal, the triple was Companion jargon on a volunteer screen, and OBS can be added as a built-in kind once the spike finds its variable.
|
|
|
|
C8, DOM wording test. The wording test runs over the typed strings, schema help and Help pages, not over a rendered page. What was lost is catching jargon in table cells built from live data. It is acceptable because typed text is where the words live; a Companion label is a name, not a word; and a headless render test was heavy for the gain.
|
|
|
|
C9, chain executor. The watchdog gets no "then also run this fix" step. What was lost is a generic second-step mechanism. It is acceptable because only dvs_ingest needs it, the builder renders the ProdCom step inline, regeneration stays byte-identical and no new code path exists in the watchdog.
|
|
|
|
C10, stop flag and command folder. There is no stop.json and no commands/ folder for the watchdog to poll. What was lost is a file-based command channel from the page. It is acceptable because a stale flag could silently disable every fix; the SIGTERM handler and the fixes-running wait cover restarts, and page requests travel on the same command variable holds already use.
|
|
|
|
C11, surfaces and module versions. The page shows no surfaces table, no Satellite labels and no module version read from Companion's database. What was lost is "which Stream Decks are plugged in" and a version column. It is acceptable because the module id from /api/connections is what the expected-module check needs, the database read would expose module passwords, and a version appears only if the spike finds it trivially.
|
|
|
|
C12, admin pages. "Where things are" stays as one generated page, and "Things only Chris does" is folded into Site setup under the "Set up once" divider rather than living in Help. What was lost is a separate admin section in Help. It is acceptable because Help stays read-only and the admin actions sit in one labelled place that only the editing code can act on, which is the volunteer/admin split round 3 asked for.
|
|
|
|
C13, gear as a filter. Gear has no data model of its own beyond location and notes; it is a filter of the Computers list derived from the checks. What was lost is a separate gear register. It is acceptable because every device is already described by the check that watches it, and one list is one thing to teach.
|
|
|
|
C14, preview run. Review has no "Preview the deck with these settings" button that runs the watchdog once against the draft. What was lost is a dry run of the checks before Apply. It is acceptable because such a run could not judge the ATEM, Dante-map, Spotify and remote checks and would have shown those keys green (round 3 Feasibility), it would have run CoreMIDI and ssh from the settings process, and the key editor's "WHAT THIS KEY WILL SAY" line plus the in-memory page build at validate already answer what the key will show.
|
|
|
|
## Residual risks
|
|
|
|
- Every Apply restarts the watchdog (C1): about five seconds of purple deck, and holds pressed in that gap are dropped. Mitigation: Apply is refused during live services (K11), page-only changes skip the restart (K10), Review says it will happen, the SIGTERM handler lets a running fix finish (K12) and sp_cmd is cleared and logged at start.
|
|
- No queue (C2): a change wanted during a service waits for a person to come back and press Apply. Mitigation: the draft is saved, Review says when the service ends, the Emergency override (typed LIVE plus a reason, logged) exists, and Q2 pins the windows.
|
|
- Raw Custom commands (K6) are a remote-command surface on seven computers, guarded by one code over plain HTTP on a LAN. Mitigation: LAN-only binding narrowed by hosts.ingest.networks (K1), origin check and lockout (K2), the code asked again and the command shown red in Review (K6), zsh -n / sh -n, History naming the editor (K14), and the private repo's access list deciding who holds the code.
|
|
- Probes are parameterised, not fixed (K8): names and paths from the config reach ssh lines. Mitigation: shlex-quoted and regex-checked parameters, a fixed command set, the metacharacter test (K16), never run during a fix, 6 s timeout, never wake a PC.
|
|
- Windows DefaultShell (K12): the batched checks assume cmd.exe. Mitigation: a light on the PC's card and refusal of cmd-batched checks when the shell is not cmd; verified once on the Lighting PC; setting DefaultShell stays a by-hand system change for the user.
|
|
- Python 3.13 removes telnetlib, which netgear.py uses (K12 self-check for 3.9-3.12). Mitigation: the self-check light; a newer macOS at another campus would lose the Dante map and PoE cycling until telnetlib is replaced, which is not in this plan.
|
|
- Companion tRPC spike unknowns (P1): custom-variable creation, trigger import, resetControl blanking a cell, the OBS variable, the page walk, whether one Automation grant covers both agents. Mitigation: recorded answers before any Apply step depends on them, with fallbacks (by hand, "unknown", schedule-only).
|
|
- Reads are open on the LAN (K2): logs, history bodies and the fleet map are visible to anyone who joins the network. Mitigation: the webhook is masked everywhere, no secret is in History, the bind is narrowed to the named LAN interfaces (K1).
|
|
- The only live signal is a recording HyperDeck (K11, C7), and a stale live-now.json falls back to the schedule. Mitigation: Review says "schedule only" when stale, Q2 fills the windows, OBS follows the spike.
|
|
- Page requests share sp_cmd with deck holds (C10): a test or resurvey request can race a hold. Mitigation: it is the same read-then-clear path holds use today, Run now is rare and never live (K7), and the watchdog logs what it drops.
|
|
- The settings server binds addresses, not interface names (K1, D5): a DHCP change on the LAN port is picked up within a minute by the rebind check. Mitigation: the Ingest addresses are static today and a grey notice shows when the LAN list is empty.
|
|
|
|
## Still open (needs the user)
|
|
|
|
- Q1 Answered 2026-10-13: the editing code lives in config.json in the private repo; everyone with the repo has it.
|
|
- Q2 Answered 2026-10-13: changes wait only while a HyperDeck is recording; no clock windows at NA (Sunday 06:30-13:30 stays the auto-fix window).
|
|
- Q3 Answered 2026-10-13: Apollo Beach, Woonsocket and Southcoast, each with a Mac Studio already running Companion.
|
|
- Q4 Answered 2026-10-13: the unwatched connections stay unwatched.
|