# 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..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 (keychain, 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. | ADOPTED | K2: the agent makes the code on first start in the GUI session, with a 0600 file fallback. | | 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 ` carries no key or check context and could toggle the wrong deck or peer. | ADOPTED | K7 `test