toga-ai 1.0.604 → 1.0.606

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,14 +3,14 @@
3
3
  | Doc | Summary | Files |
4
4
  |-----|---------|-------|
5
5
  | [Tools (1.0 Internal-Tools App) Architecture](architecture.md) | **Tools** is a standalone 1.0 (`App_`) application that houses many small internal tools behind simple interfaces, gated by Client_True staff persona. | tools/index.php, tools/.ebextensions/020_setup_git_libraries.config, tools/_/app/framework.php, tools/_/app/frameworkindex.php, tools/assets/img/favicon/favicon.ico, tools/assets/img/favicon/favicon-32x32.png, tools/assets/img/favicon/favicon-16x16.png, tools/assets/img/favicon/apple-touch-icon.png, tools/_/app/auth.php, tools/_/app/nav.php, tools/common/header.php, tools/common/footer.php, tools/mvc/get.php, tools/mvc/_TEMPLATE/get.php, tools/docs/ADDING_A_TOOL.md, tools/assets/css/theme.css, tools/assets/js/theme.js |
6
- | [ClickUp Sprint Dashboard (tools /clickup/react)](features/clickup-sprint-dashboard.md) | A native **ClickUp sprint dashboard** in the 1.0 `tools` app at route `/clickup/react`, built for a wall-mounted **TV display** ("TOGa IQ" internal sprint metri | tools/_/app/clickup/sprint.php, tools/v2/sprints/tile/index.php, tools/v2/sprints/current/index.php, tools/v2/sprints/status-breakdown/index.php, tools/v2/sprints/worktype-breakdown/index.php, tools/v2/sprints/points-by-dev/index.php, tools/v2/sprints/burndown/index.php, tools/assets/clickup/sprint-dashboard.html, tools/mvc/clickup/react/get.php, tools/mvc/login/get.php, tools/_/app/nav.php |
6
+ | [Developer Dashboard (ClickUp Sprint, tools /developer)](features/clickup-sprint-dashboard.md) | A native **ClickUp sprint dashboard** in the 1.0 `tools` app at route `/developer` (the **"Developer Dashboard"**, renamed from `/clickup/react` / "Clickup" — s | tools/_/app/clickup/sprint.php, tools/v2/sprints/tile/index.php, tools/v2/sprints/current/index.php, tools/v2/sprints/status-breakdown/index.php, tools/v2/sprints/worktype-breakdown/index.php, tools/v2/sprints/points-by-dev/index.php, tools/v2/sprints/burndown/index.php, tools/assets/clickup/sprint-dashboard.html, tools/mvc/developer/get.php, tools/mvc/login/get.php, tools/_/app/nav.php |
7
7
  | [CloudFront Client Setup](features/cloudfront-client-setup.md) | An SSO-gated admin tool at **`/devops/cloudfront-clients`** in the Tools 1.0 app that onboards a client onto **CloudFront + Route 53 across multiple AWS account | tools/_/app/devops/cloudfront.php, tools/mvc/devops/cloudfront-clients/get.php, tools/mvc/devops/cloudfront-clients/post.php, tools/assets/js/cloudfront-clients.js, tools/assets/css/cloudfront-clients.css, tools/_/app/nav.php, tools/_/app/frameworkindex.php, tools/config.production.ini |
8
8
  | [Design Demo Admin](features/design-demo-admin.md) | A self-serve admin UI at **`/design`** in the SSO-protected **Tools** app that lets the design team publish self-contained "Claude Design" HTML exports as **ver | tools/_/app/design/github.php, tools/mvc/design/get.php, tools/mvc/design/post.php, tools/assets/css/design.css, tools/assets/js/design.js, tools/_/app/frameworkindex.php, tools/_/app/nav.php, tools/composer.json |
9
9
  | [Tools — Developers Folder (UUID & Password Generators)](features/developer-tools.md) | The first two tools shipped in the Tools app, both under the **Developers** folder and gated to personas **Development Team** / **TOGa Technology**. | tools/mvc/developers/uuid/get.php, tools/mvc/developers/password/get.php, tools/mvc/developers/password/post.php |
10
10
  | [/errors Curation Console (Tools → shared Core Logs DB)](features/errors-curation-console.md) | Internal-only triage/curation screen for the 2.0 Issue/Event error-reporting pipeline, built as a 1.0 Tools MVC page reading the **shared Core Logs DB** through | tools/mvc/errors/get.php, tools/mvc/errors/post.php, tools/mvc/errors/issue/get.php, tools/assets/css/style.css, tools/_/app/nav.php, tools/config.production.ini |
11
11
  | [Legacy Email Notifier (tools /email-migration/notify)](features/legacy-email-notifier.md) | An SSO-gated admin tool at **`/email-migration/notify`** (nav group **Email Migration** > **Legacy Notifier**, personas `['TOGa Technology','Development Team']` | tools/mvc/email-migration/notify/get.php, tools/mvc/email-migration/notify/post.php, tools/_/app/nav.php |
12
12
  | [Tools MVC — Routing, CSRF & App_Database Access Patterns](features/mvc-data-access-patterns.md) | The load-bearing 1.0 (`App_`) framework conventions a developer needs when adding a page to the Tools app — URL routing, CSRF, and DB access through `App_Databa | tools/_/app/nav.php, tools/mvc/get.php, library/app/error.php, library/app/database.php |
13
- | [OneUptime Monitor Status Panel & Outage Alerting (tools /clickup/react)](features/oneuptime-monitor-status-panel.md) | A live **operational monitor column** on the wall-display dashboard at `/clickup/react`. | tools/assets/clickup/sprint-dashboard.html, tools/mvc/clickup/react/get.php |
13
+ | [OneUptime Monitor Status Panel & Outage Alerting (tools /developer)](features/oneuptime-monitor-status-panel.md) | A live **operational monitor column** on the wall-display dashboard at `/developer` (the route was renamed from `/clickup/react` — the internal asset path `asse | tools/assets/clickup/sprint-dashboard.html, tools/_/app/clickup/monitors.php, tools/v2/monitors/status/index.php, tools/mvc/developer/get.php |
14
14
  | [Tools Persona-Gated Navigation (App_Nav)](features/persona-gated-navigation.md) | `App_Nav` is the Tools app's two-level, **persona-gated** navigation. | tools/_/app/nav.php, tools/mvc/get.php |
15
15
  | [Tools SAML SSO Consumer & Persona-Gated Auth (App_Auth)](features/saml-sso-auth.md) | `App_Auth` is the Tools app's authentication layer: it consumes the SAML gateway `?saml=` handoff (see the 2.0 SAML downstream integration contract), establishe | tools/_/app/auth.php, tools/mvc/sso/initiate/get.php, tools/mvc/sso/get.php, tools/mvc/login/get.php, tools/mvc/login/post.php, tools/mvc/logout/get.php, tools/mvc/get.php, tools/config.production.ini, tools/config.local.ini |
16
16
  | [Talos Knowledge Base Admin UI (KB Documents + Vocabulary)](features/talos-kb-documents-admin.md) | > **PER-AI-MODEL, DATA-DRIVEN SCOPING (2026-07-29).** The KB-documents and Vocabulary admin > UIs were refactored from a single hard-coded **"development-team"* | tools/mvc/talos/kb-documents/get.php, tools/mvc/talos/kb-documents/post.php, tools/mvc/talos/knowledge-bases/get.php, tools/mvc/talos/knowledge-bases/post.php, tools/mvc/talos/vocabulary/get.php, tools/mvc/talos/vocabulary/post.php, tools/_/app/talos/s3.php, tools/_/app/talos/bedrock.php, tools/_/app/pg.php, tools/_/app/model/true/aimodels.php, tools/_/app/model/true/vectorindexes.php, tools/_/app/model/true/aimodels_vectorindexes.php, tools/_/app/worker.php, tools/_/app/nav.php, tools/config.production.ini, tools/config.alpha.ini, tools/.platform/httpd/conf.d/timeouts.conf, tools/.platform/hooks/prebuild/01-install-php-pgsql.sh, tools/.platform/hooks/postdeploy/01-restart-php.sh |
@@ -117,21 +117,29 @@ authenticated user gets the dashboard's explicit empty-state (see
117
117
 
118
118
  ## Wall-display routes & third-party browser dependencies
119
119
 
120
- Tools is no longer only a click-through internal-tool shell: `/clickup/react` is an
121
- **unattended wall display** that holds a full-screen colour state **indefinitely** — an ambient,
122
- always-on status surface rather than a page someone visits (see
120
+ Tools is no longer only a click-through internal-tool shell: `/developer` (renamed from
121
+ `/clickup/react`) is an **unattended wall display** that holds a full-screen colour state
122
+ **indefinitely** — an ambient, always-on status surface rather than a page someone visits (see
123
123
  `features/clickup-sprint-dashboard.md` and `features/oneuptime-monitor-status-panel.md`). Two
124
124
  architectural consequences:
125
125
 
126
- - **One cross-origin browser dependency.** Every other fetch in this app is same-origin and
127
- authenticated by the SSO session cookie. The monitor column is the sole exception: the browser
128
- POSTs directly to the OneUptime **public** status-page API on another host (CORS-open, no
129
- credentials, raw JSON — not the api2 envelope). Nothing proxies it server-side today, so an
130
- upstream CORS or availability change breaks that panel in the browser with no server-side signal.
131
- - **Iframed pages carry their own permission policy.** `mvc/clickup/react/get.php` embeds its
132
- asset in an iframe, and browser autoplay policy is scoped **per-iframe** — an iframed page that
133
- must play audio needs `allow="… autoplay"` on the frame or it is blocked silently. Unattended
134
- displays additionally never receive the user gesture browsers require before audio plays.
126
+ - **No cross-origin browser dependency any more — it is server-proxied.** Every fetch in this app
127
+ is now same-origin and authenticated by the SSO session cookie, including the monitor column:
128
+ the browser GETs `/v2/monitors/status/` (`App_Clickup_Monitors`), and the server does the
129
+ cross-origin POST to the OneUptime **public** status-page API, reduces ~250 KB → ~1 KB, caches
130
+ ~5s (APCu) and returns the api2 envelope. This removed the app's last cross-origin browser
131
+ dependency and the CORS / edge-cache / autoplay coupling it carried; the status-page ID moved
132
+ from a hardcoded HTML constant into config (`[oneuptime] status_page_id`, default
133
+ `DEFAULT_STATUS_PAGE_ID`).
134
+ - **Iframed pages carry their own permission policy.** `mvc/developer/get.php` embeds its asset in
135
+ an iframe, and browser autoplay policy is scoped **per-iframe** — an iframed page that must play
136
+ audio needs `allow="… autoplay"` on the frame or it is blocked silently. Unattended displays
137
+ additionally never receive the user gesture browsers require before audio plays.
138
+ - **`crypto.randomUUID()` is undefined on a non-secure origin.** Browser code served over plain
139
+ HTTP by hostname/LAN IP (not `localhost`) has no secure context, so `crypto.randomUUID()` and
140
+ `crypto.subtle` throw. The dashboard now guards its per-request `transactionId` behind a helper
141
+ (randomUUID → `getRandomValues` v4 → non-crypto id); any browser code in this app that must run
142
+ over a non-secure origin must do the same rather than call `crypto.randomUUID` unguarded.
135
143
 
136
144
  ## Adding a tool
137
145
 
@@ -157,11 +165,15 @@ Create `mvc/<folder>/<tool>/get.php` (copy `mvc/_TEMPLATE/get.php`), add one ent
157
165
  workflow's clear_env gotcha); a rotation does not un-expose git history. (Location only — no
158
166
  value recorded here.)
159
167
  - **SSO initiation + replay defense are open items** — see `features/saml-sso-auth.md`.
160
- - **Unproxied third-party polling from the browser (`/clickup/react`).** The monitor column pulls
161
- ~250 KB from OneUptime every 5s — ~3 MB/min **per open tab** — to render about six numbers, and
162
- hardcodes the status-page ID in the HTML asset. Recommended fix: a small server-side endpoint
163
- (e.g. `/v2/monitors/status/`) that fetches, reduces and caches ~5s, moving the ID into config and
164
- removing the cross-origin dependency. Advisory, not scheduled.
168
+ - **~~Unproxied third-party polling from the browser~~ (resolved 2026-08-18).** The monitor column
169
+ used to pull ~250 KB from OneUptime cross-origin every poll (per open tab) and hardcode the
170
+ status-page ID in the HTML. It is now served by a same-origin server-side proxy
171
+ `/v2/monitors/status/` (`App_Clickup_Monitors`) that fetches, reduces to ~1 KB and caches ~5s
172
+ (APCu), with the status-page ID in config — one upstream fetch shared across all tabs, no
173
+ cross-origin dependency. See `features/oneuptime-monitor-status-panel.md`. **Framework gotcha
174
+ found building it (prod incident CV-2):** never call `curl_close()` in App_ code — it is
175
+ deprecated in PHP 8.5 and the strict error handler promotes that `E_DEPRECATED` to a fatal
176
+ (500). It is a no-op since PHP 8.0; drop it (or `unset($ch)`).
165
177
  - **Framework-level Sentry error reporting is an open gap.** Prod printed "Sentry is not
166
178
  installed" because `sentry/sentry` was missing from `composer.json` (added `^4.10`; sibling
167
179
  apps use `^4.10`/`^4.19`). But even with Sentry in `vendor/`, the 1.0 framework does **not**
@@ -170,6 +182,13 @@ Create `mvc/<folder>/<tool>/get.php` (copy `mvc/_TEMPLATE/get.php`), add one ent
170
182
  composer package must `require_once` the autoloader itself.
171
183
 
172
184
  ## Change history
185
+ - 2026-08-18 — Renamed the wall-display route `/clickup/react` → `/developer` ("Developer
186
+ Dashboard"; folder `mvc/clickup/react/` → `mvc/developer/`, old route now 404s). Removed the
187
+ app's last cross-origin browser dependency: the OneUptime monitor column is now a same-origin
188
+ server-side proxy `/v2/monitors/status/` (`App_Clickup_Monitors`, ~250 KB→~1 KB, APCu ~5s,
189
+ status-page ID in config), resolving the "unproxied third-party polling" known issue. Recorded
190
+ the `curl_close()`-is-fatal-in-PHP-8.5-under-the-strict-handler framework gotcha (prod incident
191
+ CV-2) and the `crypto.randomUUID()` non-secure-origin gotcha. (jcardinal)
173
192
  - 2026-08-14 — Corrected the session model: sessions were on the file handler on per-instance
174
193
  local disk (not Redis as previously assumed), so every deploy logged everyone out; moved to the
175
194
  shared ElastiCache Redis `rediscluster` handler via `App_Framework_Tools::startSession()`
@@ -1,12 +1,12 @@
1
1
  ---
2
- title: ClickUp Sprint Dashboard (tools /clickup/react)
2
+ title: Developer Dashboard (ClickUp Sprint, tools /developer)
3
3
  framework: "1.0"
4
4
  repo: tools
5
5
  project: Tools
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-08-14
9
+ updated: 2026-08-18
10
10
  owners: [kyalamarthi, jcardinal]
11
11
  files:
12
12
  - tools/_/app/clickup/sprint.php
@@ -17,7 +17,7 @@ files:
17
17
  - tools/v2/sprints/points-by-dev/index.php
18
18
  - tools/v2/sprints/burndown/index.php
19
19
  - tools/assets/clickup/sprint-dashboard.html
20
- - tools/mvc/clickup/react/get.php
20
+ - tools/mvc/developer/get.php
21
21
  - tools/mvc/login/get.php
22
22
  - tools/_/app/nav.php
23
23
  related:
@@ -32,12 +32,13 @@ related:
32
32
 
33
33
  ## Summary
34
34
 
35
- A native **ClickUp sprint dashboard** in the 1.0 `tools` app at route `/clickup/react`,
36
- built for a wall-mounted **TV display** ("TOGa IQ" internal sprint metrics). It replaces a
35
+ A native **ClickUp sprint dashboard** in the 1.0 `tools` app at route `/developer` (the
36
+ **"Developer Dashboard"**, renamed from `/clickup/react` / "Clickup" — see the rename note
37
+ below), built for a wall-mounted **TV display** ("TOGa IQ" internal sprint metrics). It replaces a
37
38
  standalone Node/Express prototype from a prior session, folding the dashboard into `tools`
38
39
  so it runs on the existing App\_ framework + SSO with no separate service.
39
40
 
40
- The page is now a **two-column split**: this sprint board at 80%, and an operational
41
+ The page is now a **two-column split**: this sprint board at 75%, and an operational
41
42
  **monitor status column** filling the rest — documented separately in
42
43
  [OneUptime Monitor Status Panel](./oneuptime-monitor-status-panel.md). The sprint board itself
43
44
  was left byte-for-byte unchanged when that landed (its component was renamed `SprintBoard` and
@@ -60,7 +61,7 @@ connection (registry string `'db_team'`, from the `[database_team]` config secti
60
61
  (`{success, data, errors}`) so the tool is a faithful stand-in for api2.
61
62
 
62
63
  **Auth is done by hand as JSON**, not the HTML auth card: `App_Auth::isLoggedIn()` +
63
- `App_Nav::personasForRoute('/clickup/react')` + `hasAnyPersona`; on failure it returns a
64
+ `App_Nav::personasForRoute('/developer')` + `hasAnyPersona`; on failure it returns a
64
65
  JSON **401/403** so the fetch-based UI gets a clean error instead of an HTML login page.
65
66
 
66
67
  Two 1.0-framework gotchas this engine had to work around (both reusable beyond this
@@ -87,6 +88,11 @@ Babel-standalone from CDN, JSX inside a `<script type="text/babel">`. **No build
87
88
  npm, no bundler.** It fetches `/v2/sprints/*` **same-origin**, so the SSO session cookie
88
89
  authenticates the calls automatically. Do not mistake this for a bundled React app.
89
90
 
91
+ **Charts fill the card width.** Sprint Burndown and Sprint Points By Dev use
92
+ `preserveAspectRatio="none"` (was `"xMidYMid meet"`) so the SVGs stretch left-to-right to fill
93
+ the card instead of letterboxing with side margins. Tradeoff: text stretches slightly —
94
+ acceptable on a wall TV.
95
+
90
96
  ### Retiring a work type or a departed developer — filter client-side, not in the mock
91
97
 
92
98
  Two `ALL_CAPS` constants near the top of the HTML drop rows from the **live** API responses,
@@ -113,18 +119,45 @@ dropped alongside STRETCH — with that category retired it tracked "Committed"
113
119
  earn a second line. The legend derives from the `BURNDOWN_SERIES` constant, so it updated
114
120
  itself; add or remove a line there rather than editing the legend.
115
121
 
116
- ### Embed page — `mvc/clickup/react/get.php`
122
+ ### Embed page — `mvc/developer/get.php`
117
123
 
118
124
  A PHP MVC view that `requireAuth`s, then embeds `sprint-dashboard.html` in an iframe
119
- (cache-busted by `filemtime`). Heading "Clickup Dashboard", subtitle notes the data is
120
- "…refreshed every 5 min." The frame is `allow="fullscreen; autoplay"` — **autoplay is
121
- load-bearing**, not decorative: it is what lets the monitor column's outage beeps sound (see
125
+ (cache-busted by `filemtime`). Heading "Developer Dashboard", iframe titled likewise. The frame
126
+ is `allow="fullscreen; autoplay"` — **autoplay is load-bearing**, not decorative: it is what lets
127
+ the monitor column's outage beeps sound (see
122
128
  [the monitor panel doc](./oneuptime-monitor-status-panel.md)).
123
129
 
130
+ **Full-screen lives on the parent page, not inside the React frame.** The in-frame "Full screen"
131
+ / "Exit" buttons were removed; a single "Full screen" button now sits on `mvc/developer/get.php`
132
+ (left-aligned, padding below) and fullscreens the **iframe element** itself (Esc or a second click
133
+ exits; label toggles). `.cur-frame:fullscreen{position:fixed;width:100vw;height:100vh}` sizes it.
134
+ The old **"Live"** pill and its pulse CSS were removed.
135
+
136
+ ### Route/name rename — `/clickup/react` → `/developer`
137
+
138
+ The nav label "Clickup" → **"Developer"** and the route `/clickup/react` → **`/developer`**; the
139
+ route folder moved `mvc/clickup/react/` → `mvc/developer/` (the old route now 404s "Page Not
140
+ Found", verified). Every persona lookup was updated from `personasForRoute('/clickup/react')` to
141
+ `'/developer'` in `nav.php`, `mvc/developer/get.php`, `sprint.php`, and `monitors.php`.
142
+ **Deliberately left unchanged (not user-facing):** the internal asset path
143
+ `assets/clickup/sprint-dashboard.html`, the `App_Clickup_*` class names, and the
144
+ `_/app/clickup/` folder.
145
+
146
+ ### DEV-only mock-alert previewer — `MONITOR_MOCK_MODE`
147
+
148
+ Separate from `USE_MOCK`. When `MONITOR_MOCK_MODE` is true, an on-screen **clickable badge**
149
+ (Prev / Next / numbered dots) steps canned monitor scenarios (all-operational → one/two degraded
150
+ → offline → mixed), driving the monitor panel, standing edge tint, center popup and Web-Audio
151
+ beeps exactly as a live transition would — so the alert states can be reviewed without a real
152
+ outage. Keyboard (m / ← / → / 0-9) also works but only when the iframe holds focus (unreliable in
153
+ an iframe), which is why the clickable buttons are the primary control. **Must be `false` for any
154
+ deployed build.** (Reusable note: driving canned MODELS through the same alert hook is a clean way
155
+ to demo edge-triggered alerts.)
156
+
124
157
  ### Nav — `_/app/nav.php`
125
158
 
126
159
  Registered under the **"Dashboard"** nav folder as
127
- `['label'=>'Clickup','route'=>'/clickup/react']`, persona-gated like every folder (see
160
+ `['label'=>'Developer','route'=>'/developer']`, persona-gated like every folder (see
128
161
  [persona-gated-navigation](./persona-gated-navigation.md)). The old Power BI embed nav entry
129
162
  (`/clickup/dashboard`) was **removed** — the page file stays on disk, just unlinked — because
130
163
  the React dashboard supersedes it.
@@ -195,6 +228,19 @@ the React dashboard supersedes it.
195
228
  unaffected — the live API returns `points`. One-word fix (`count:` → `points:`) if anyone
196
229
  needs the mock; deliberately left alone as out of scope.
197
230
 
231
+ - **`USE_MOCK = true` renders the WHOLE dashboard from fixtures and makes ZERO API calls** — this
232
+ was the real "all systems operational / no live data" bug (the master mock switch had been left
233
+ `true`). Diagnostic symptom set: green status + a suspiciously round monitor count ("37
234
+ monitors" is literally the `MONITOR_MOCK.total` constant, not live data) + **zero network
235
+ requests** + identical output across private / cache-cleared windows. Distinct from
236
+ `MONITOR_MOCK_MODE` (the alert previewer above) and from the broken `StatusChart` mock below.
237
+ Fix is `USE_MOCK = false`. It was diagnosed by inspecting the running server directly (curl of
238
+ the served asset + the `/v2` route), not through the browser.
239
+ - **`crypto.randomUUID()` crashes the page to a black screen on a non-secure origin.** The page
240
+ stamps a per-request `transactionId` header with `crypto.randomUUID()`, which exists **only in a
241
+ secure context**; over plain HTTP by hostname/LAN IP it is `undefined` and throws before React
242
+ mounts. Guarded by a `transactionId()` helper (randomUUID → getRandomValues v4 → non-crypto id).
243
+ Full write-up in [the monitor panel doc](./oneuptime-monitor-status-panel.md).
198
244
  - **The old Power BI embed page (`mvc/clickup/dashboard/get.php`) keeps ~6 fixed colour
199
245
  literals on purpose — do NOT theme them.** Its card/frame colour `#0b1020` is matched to the
200
246
  embedded Power BI report canvas so nothing flashes white while the iframe loads. Themed
@@ -203,6 +249,17 @@ the React dashboard supersedes it.
203
249
  [App-Wide Colour Theme](./theme-light-dark.md).
204
250
 
205
251
  ## Change history
252
+ - 2026-08-18 — **Renamed to the "Developer Dashboard" at `/developer`** (was "Clickup" /
253
+ `/clickup/react`; route folder moved `mvc/clickup/react/` → `mvc/developer/`, old route now
254
+ 404s; all `personasForRoute` refs updated; internal `assets/clickup/…` path + `App_Clickup_*`
255
+ names left unchanged). Full-screen control moved from the React frame to the parent page (it
256
+ fullscreens the iframe element) and the "Live" pill was removed. Charts now
257
+ `preserveAspectRatio="none"` to fill the card width. Added the DEV-only `MONITOR_MOCK_MODE`
258
+ alert previewer (clickable badge stepping canned scenarios). Recorded two gotchas: the real
259
+ all-green-no-fetch bug was `USE_MOCK = true` (whole dashboard from fixtures, zero API calls, "37
260
+ monitors" = `MONITOR_MOCK.total`), and `crypto.randomUUID()` black-screening the page on a
261
+ non-secure origin. Monitor column now widened to 75% and fed by a server-side proxy (see the
262
+ monitor panel doc). (jcardinal)
206
263
  - 2026-08-14 — Retired the **STRETCH** work type (KPI tile, colour, Work Type slice) and removed
207
264
  the blue **"All"** burndown series, leaving Target + Committed; added the client-side
208
265
  `RETIRED_WORK_TYPES` / `FORMER_DEVS` response filters (editing the `USE_MOCK` fixtures does