@terreno/mcp 57.6.1 → 57.8.0

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.
Files changed (143) hide show
  1. package/dist/docs/resources/ui.md +5 -4
  2. package/dist/docs/upgrades/57.7.0.md +64 -0
  3. package/dist/docs/upgrades/57.8.0.md +61 -0
  4. package/dist/docs/upgrades/58.0.0.md +4 -0
  5. package/dist/docs/versioned/next/explanation/example-coverage.md +1 -0
  6. package/dist/docs/versioned/next/explanation/loop-engineering.md +32 -3
  7. package/dist/docs/versioned/next/explanation/model-router-actions.md +1 -1
  8. package/dist/docs/versioned/next/explanation/repository-settings.md +12 -5
  9. package/dist/docs/versioned/next/explanation/roadmap-process.md +41 -19
  10. package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +285 -22
  11. package/dist/docs/versioned/next/explanation/static-analysis.md +3 -2
  12. package/dist/docs/versioned/next/explanation/test-isolation.md +42 -0
  13. package/dist/docs/versioned/next/how-to/circleci.md +121 -64
  14. package/dist/docs/versioned/next/how-to/github-actions-ci.md +4 -3
  15. package/dist/docs/versioned/next/how-to/preview-demo.md +19 -0
  16. package/dist/docs/versioned/next/how-to/product-announcements.md +3 -0
  17. package/dist/docs/versioned/next/how-to/run-tests-locally.md +23 -2
  18. package/dist/docs/versioned/next/implementationPlans/IP_TEMPLATE.md +3 -1
  19. package/dist/docs/versioned/next/implementationPlans/admin-improvements.md +1 -1
  20. package/dist/docs/versioned/next/implementationPlans/admin-scripts-durable-jobs.md +2 -1
  21. package/dist/docs/versioned/next/implementationPlans/agent-ui-blocks.md +1 -0
  22. package/dist/docs/versioned/next/implementationPlans/ai-agents-and-failover.md +1 -0
  23. package/dist/docs/versioned/next/implementationPlans/ai-observability.md +1 -0
  24. package/dist/docs/versioned/next/implementationPlans/announcements-surfaces.md +1 -1
  25. package/dist/docs/versioned/next/implementationPlans/announcements.md +2 -1
  26. package/dist/docs/versioned/next/implementationPlans/app-mcp-server.md +1 -0
  27. package/dist/docs/versioned/next/implementationPlans/better-auth-strict-oauth-provider.md +2 -1
  28. package/dist/docs/versioned/next/implementationPlans/can-as-permission-seam.md +1 -1
  29. package/dist/docs/versioned/next/implementationPlans/collection-registry.md +1 -1
  30. package/dist/docs/versioned/next/implementationPlans/comms-adapter-expo-push.md +1 -1
  31. package/dist/docs/versioned/next/implementationPlans/comms-adapter-twilio-sms.md +1 -1
  32. package/dist/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +1 -1
  33. package/dist/docs/versioned/next/implementationPlans/compile-pipeline-dedup.md +2 -1
  34. package/dist/docs/versioned/next/implementationPlans/datatable-server-side-filtering.md +1 -1
  35. package/dist/docs/versioned/next/implementationPlans/demo-workshop.md +219 -0
  36. package/dist/docs/versioned/next/implementationPlans/describe-model-schema.md +1 -1
  37. package/dist/docs/versioned/next/implementationPlans/docs-reference-coverage.md +1 -1
  38. package/dist/docs/versioned/next/implementationPlans/docs-site-and-versioning.md +1 -1
  39. package/dist/docs/versioned/next/implementationPlans/examples-demo-coverage.md +1 -1
  40. package/dist/docs/versioned/next/implementationPlans/framework-audit-log.md +1 -1
  41. package/dist/docs/versioned/next/implementationPlans/gpt-chat-mascot.md +1 -0
  42. package/dist/docs/versioned/next/implementationPlans/inbound-webhooks.md +1 -1
  43. package/dist/docs/versioned/next/implementationPlans/knip-cleanup.md +1 -0
  44. package/dist/docs/versioned/next/implementationPlans/mcp-doc-sync-off-compile-path.md +2 -1
  45. package/dist/docs/versioned/next/implementationPlans/mcp-service-tokens.md +2 -1
  46. package/dist/docs/versioned/next/implementationPlans/migrate-admin-to-syncdb.md +2 -1
  47. package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +1 -1
  48. package/dist/docs/versioned/next/implementationPlans/mongodb-migrations-tooling.md +1 -1
  49. package/dist/docs/versioned/next/implementationPlans/notification-center.md +1 -1
  50. package/dist/docs/versioned/next/implementationPlans/org-management-ui.md +1 -1
  51. package/dist/docs/versioned/next/implementationPlans/password-reset-and-email-verification.md +1 -1
  52. package/dist/docs/versioned/next/implementationPlans/rate-limiting.md +1 -1
  53. package/dist/docs/versioned/next/implementationPlans/remove-legacy-realtime.md +1 -0
  54. package/dist/docs/versioned/next/implementationPlans/support-agent.md +1 -0
  55. package/dist/docs/versioned/next/implementationPlans/syncdb-codegen.md +1 -1
  56. package/dist/docs/versioned/next/implementationPlans/terreno-langfuse-integration.md +1 -1
  57. package/dist/docs/versioned/next/implementationPlans/upgrade-guides-and-skill.md +1 -1
  58. package/dist/docs/versioned/next/reference/ai.md +3 -1
  59. package/dist/docs/versioned/next/reference/announcement-release-packs.md +146 -0
  60. package/dist/docs/versioned/next/reference/announcements.md +7 -3
  61. package/dist/docs/versioned/next/reference/api.md +1 -0
  62. package/dist/docs/versioned/next/reference/environment-variables.md +1 -0
  63. package/dist/docs/versioned/next/reference/lifecycle-plugin.md +2 -2
  64. package/dist/docs/versioned/next/reference/test.md +1 -1
  65. package/dist/docs/versioned/next/reference/ui.md +79 -8
  66. package/dist/docs/versioned/next/tasks/can-as-permission-seam.md +4 -4
  67. package/dist/docs/versioned/next/tasks/collection-registry.md +6 -6
  68. package/dist/docs/versioned/next/tasks/demo-workshop.md +150 -0
  69. package/dist/docs/versioned/next/tasks/describe-model-schema.md +5 -5
  70. package/dist/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +6 -3
  71. package/package.json +2 -2
  72. package/src/docs/resources/ui.md +5 -4
  73. package/src/docs/upgrades/57.7.0.md +64 -0
  74. package/src/docs/upgrades/57.8.0.md +61 -0
  75. package/src/docs/upgrades/58.0.0.md +4 -0
  76. package/src/docs/versioned/next/explanation/example-coverage.md +1 -0
  77. package/src/docs/versioned/next/explanation/loop-engineering.md +32 -3
  78. package/src/docs/versioned/next/explanation/model-router-actions.md +1 -1
  79. package/src/docs/versioned/next/explanation/repository-settings.md +12 -5
  80. package/src/docs/versioned/next/explanation/roadmap-process.md +41 -19
  81. package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +285 -22
  82. package/src/docs/versioned/next/explanation/static-analysis.md +3 -2
  83. package/src/docs/versioned/next/explanation/test-isolation.md +42 -0
  84. package/src/docs/versioned/next/how-to/circleci.md +121 -64
  85. package/src/docs/versioned/next/how-to/github-actions-ci.md +4 -3
  86. package/src/docs/versioned/next/how-to/preview-demo.md +19 -0
  87. package/src/docs/versioned/next/how-to/product-announcements.md +3 -0
  88. package/src/docs/versioned/next/how-to/run-tests-locally.md +23 -2
  89. package/src/docs/versioned/next/implementationPlans/IP_TEMPLATE.md +3 -1
  90. package/src/docs/versioned/next/implementationPlans/admin-improvements.md +1 -1
  91. package/src/docs/versioned/next/implementationPlans/admin-scripts-durable-jobs.md +2 -1
  92. package/src/docs/versioned/next/implementationPlans/agent-ui-blocks.md +1 -0
  93. package/src/docs/versioned/next/implementationPlans/ai-agents-and-failover.md +1 -0
  94. package/src/docs/versioned/next/implementationPlans/ai-observability.md +1 -0
  95. package/src/docs/versioned/next/implementationPlans/announcements-surfaces.md +1 -1
  96. package/src/docs/versioned/next/implementationPlans/announcements.md +2 -1
  97. package/src/docs/versioned/next/implementationPlans/app-mcp-server.md +1 -0
  98. package/src/docs/versioned/next/implementationPlans/better-auth-strict-oauth-provider.md +2 -1
  99. package/src/docs/versioned/next/implementationPlans/can-as-permission-seam.md +1 -1
  100. package/src/docs/versioned/next/implementationPlans/collection-registry.md +1 -1
  101. package/src/docs/versioned/next/implementationPlans/comms-adapter-expo-push.md +1 -1
  102. package/src/docs/versioned/next/implementationPlans/comms-adapter-twilio-sms.md +1 -1
  103. package/src/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +1 -1
  104. package/src/docs/versioned/next/implementationPlans/compile-pipeline-dedup.md +2 -1
  105. package/src/docs/versioned/next/implementationPlans/datatable-server-side-filtering.md +1 -1
  106. package/src/docs/versioned/next/implementationPlans/demo-workshop.md +219 -0
  107. package/src/docs/versioned/next/implementationPlans/describe-model-schema.md +1 -1
  108. package/src/docs/versioned/next/implementationPlans/docs-reference-coverage.md +1 -1
  109. package/src/docs/versioned/next/implementationPlans/docs-site-and-versioning.md +1 -1
  110. package/src/docs/versioned/next/implementationPlans/examples-demo-coverage.md +1 -1
  111. package/src/docs/versioned/next/implementationPlans/framework-audit-log.md +1 -1
  112. package/src/docs/versioned/next/implementationPlans/gpt-chat-mascot.md +1 -0
  113. package/src/docs/versioned/next/implementationPlans/inbound-webhooks.md +1 -1
  114. package/src/docs/versioned/next/implementationPlans/knip-cleanup.md +1 -0
  115. package/src/docs/versioned/next/implementationPlans/mcp-doc-sync-off-compile-path.md +2 -1
  116. package/src/docs/versioned/next/implementationPlans/mcp-service-tokens.md +2 -1
  117. package/src/docs/versioned/next/implementationPlans/migrate-admin-to-syncdb.md +2 -1
  118. package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +1 -1
  119. package/src/docs/versioned/next/implementationPlans/mongodb-migrations-tooling.md +1 -1
  120. package/src/docs/versioned/next/implementationPlans/notification-center.md +1 -1
  121. package/src/docs/versioned/next/implementationPlans/org-management-ui.md +1 -1
  122. package/src/docs/versioned/next/implementationPlans/password-reset-and-email-verification.md +1 -1
  123. package/src/docs/versioned/next/implementationPlans/rate-limiting.md +1 -1
  124. package/src/docs/versioned/next/implementationPlans/remove-legacy-realtime.md +1 -0
  125. package/src/docs/versioned/next/implementationPlans/support-agent.md +1 -0
  126. package/src/docs/versioned/next/implementationPlans/syncdb-codegen.md +1 -1
  127. package/src/docs/versioned/next/implementationPlans/terreno-langfuse-integration.md +1 -1
  128. package/src/docs/versioned/next/implementationPlans/upgrade-guides-and-skill.md +1 -1
  129. package/src/docs/versioned/next/reference/ai.md +3 -1
  130. package/src/docs/versioned/next/reference/announcement-release-packs.md +146 -0
  131. package/src/docs/versioned/next/reference/announcements.md +7 -3
  132. package/src/docs/versioned/next/reference/api.md +1 -0
  133. package/src/docs/versioned/next/reference/environment-variables.md +1 -0
  134. package/src/docs/versioned/next/reference/lifecycle-plugin.md +2 -2
  135. package/src/docs/versioned/next/reference/test.md +1 -1
  136. package/src/docs/versioned/next/reference/ui.md +79 -8
  137. package/src/docs/versioned/next/tasks/can-as-permission-seam.md +4 -4
  138. package/src/docs/versioned/next/tasks/collection-registry.md +6 -6
  139. package/src/docs/versioned/next/tasks/demo-workshop.md +150 -0
  140. package/src/docs/versioned/next/tasks/describe-model-schema.md +5 -5
  141. package/src/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +6 -3
  142. package/dist/docs/ui-types-documentation.json +0 -33
  143. package/src/docs/ui-types-documentation.json +0 -33
@@ -222,6 +222,7 @@ export const todoRouter = modelRouter("/todos", Todo, {
222
222
  ```
223
223
 
224
224
  Do not add `endpoints: (router) => { router.get(...) }` when an action fits.
225
+ Action config supports `allowAnonymous: true` as a per-action override; it does not change authentication for CRUD or sibling actions.
225
226
 
226
227
  ## modelRouter array operations
227
228
 
@@ -239,6 +239,7 @@ secrets and `PUBLIC_API_URL` / `COMMS_WEBHOOK_PUBLIC_URL` as above. See
239
239
  | Variable | Read by | Required | Default | Secret | Scope |
240
240
  |----------|---------|----------|---------|--------|-------|
241
241
  | `ADMIN_SPA_ENABLED` | example-backend | ❌ | — | No | server |
242
+ | `ANNOUNCEMENTS_UPLOAD_TOKEN` | example-backend `AnnouncementsApp` | ❌ | example deploy: `terreno-example-announcement-upload` | Yes outside the example app | server |
242
243
  | `ADMIN_SPA_DIST_DIR` | example-backend Dockerfile | ❌ | — | No | server |
243
244
  | `ADMIN_SPA_DEV_PROXY` | admin-spa plugin | ❌ | — | No | server |
244
245
  | `ADMIN_SPA_BACKEND_URL` | admin-spa tests | ❌ | — | No | tooling |
@@ -14,7 +14,7 @@ loops that invoke those stages; they are not stages and must not appear as `stag
14
14
  | `terreno-2-pick` | approved task + branch/state | one implemented slice, then Roast, then the next task | Roast, or Brew when the list is done |
15
15
  | `terreno-3-roast` | Pick result + current diff | independent requirement/evidence verdict for the current task | emit Pick if tasks remain, else Brew; never invoke Pick; pass a task-scoped briefing; do not spawn two unconstrained reviewers |
16
16
  | `terreno-4-brew` | Roast PASS for every in-scope task + branch/evidence | pushed head + PR + product-CI trigger check + review-bot wait + attached evidence | Taste |
17
- | `terreno-5-taste` | PR + current state | one current-head reaction; before push: pull latest `master`, re-verify last-run failed tests locally, run root `prepush` when present (otherwise affected-package checks) in a no-context subagent, then watch CI | null or fresh Taste |
17
+ | `terreno-5-taste` | PR + current state | one current-head reaction; before push: fetch latest `master` (merge only when needed), re-verify last-run failed tests locally, run root `prepush` when present (otherwise affected-package checks) in a no-context subagent, then watch CI; invoked directly, repeats bounded reactions until terminal | null or fresh Taste |
18
18
 
19
19
  Outer loops (not stages):
20
20
 
@@ -51,7 +51,7 @@ until async review bots (Bugbot, CodeQL, and similar) on the current head have r
51
51
  preferring provider CLI watch hooks or harness event subscriptions over sleep polling.
52
52
  Taste then waits in a loop for product CI using GitHub CLI (`gh pr checks --watch`,
53
53
  `gh run watch`) or CircleCI CLI (`circleci run watch`) until jobs are terminal or the
54
- wait times out. Before any push, Taste always pulls latest `master`, records last-run
54
+ wait times out. Before any push, Taste fetches latest `master` (merging it only when needed), records last-run
55
55
  failed tests and re-verifies them locally, then spawns a
56
56
  fresh subagent with no parent conversation. If the repository root defines a `prepush`
57
57
  package script, Taste runs it as the authoritative local gate; otherwise it falls back
@@ -148,7 +148,7 @@ the demo compiles. Add a story plus `demoConfig.tsx` registration for new
148
148
  components, or an allowlist entry with a specific reason — not "hard to demo".
149
149
  The allowlist is limited to shell/providers, React context objects, thin RN
150
150
  list wrappers, subcomponents already exercised by a parent story
151
- (Filter, Table, DateTimeField, HeightField, ConsentFormScreen), and
151
+ (DropdownPanel, Table, DateTimeField, HeightField, ConsentFormScreen), and
152
152
  product surfaces that belong in `example-frontend` rather than the isolated
153
153
  UI demo (announcements and in-app notifications).
154
154
  Standalone picker sheets (`NumberPickerActionSheet`, `DecimalRangeActionSheet`)
@@ -226,6 +226,69 @@ overrides it:
226
226
  | Helper | `{testID}.helper` |
227
227
  | Show/hide toggle | `{testID}.visibility-toggle` |
228
228
 
229
+ ### DropdownPanel
230
+
231
+ `DropdownPanel` is the compositional dropdown behind the DataTable filter popovers. A
232
+ trigger opens an anchored panel of arbitrary composed content with an optional
233
+ Apply / Clear / Cancel footer, so it also fits non-filter panels (bulk actions, column
234
+ pickers, sort menus).
235
+
236
+ ``````typescript
237
+ <DropdownPanel
238
+ label="Filters"
239
+ onApply={applyDraft}
240
+ onCancel={resetDraft}
241
+ onClear={clearDraft}
242
+ onOpenChange={(isOpen) => isOpen && seedDraft()}
243
+ width={340}
244
+ >
245
+ <FilterSelectMenu title="Due date" options={DUE_DATE_OPTIONS} value={dueDate} onChange={setDueDate} />
246
+ <FilterBoolean title="Urgent tasks only" value={urgentOnly} onChange={setUrgentOnly} />
247
+ </DropdownPanel>
248
+ ``````
249
+
250
+ > `Filter` is the former name and stays exported as a deprecated alias (with `FilterProps`)
251
+ > until Terreno 58. The `FilterSelectMenu` / `FilterBoolean` / `FilterAccordion` /
252
+ > `FilterChangesBadge` controls keep their names.
253
+
254
+ #### Positioning
255
+
256
+ The panel never renders inside its parent's clipping or stacking context: on web it is
257
+ portaled to `document.body` with fixed positioning, and on native it is teleported to the
258
+ `TerrenoProvider` portal host (falling back to an inline absolute overlay when no host is
259
+ mounted). `computeDropdownPanelLayout` then anchors it to the measured trigger:
260
+
261
+ | Situation | Behavior |
262
+ | --- | --- |
263
+ | Panel fits beside the trigger | Left edges line up (`align="start"`) |
264
+ | Left-aligned panel would cross the right viewport edge | Right edges line up instead (`align="auto"`, the default) |
265
+ | Panel is wider than the viewport | Narrowed to the viewport minus the 8px screen margins |
266
+ | Less than 160px below the trigger, and more above | Flipped above the trigger |
267
+ | Content taller than the space on screen | Panel body scrolls; the footer stays pinned |
268
+
269
+ Pass `align="start"` or `align="end"` to pin the side explicitly, and `maxPanelHeight` to
270
+ cap the height below what the viewport allows.
271
+
272
+ #### Trigger
273
+
274
+ The default trigger is a `Button` (or a compact icon trigger with `iconOnly`). Style it
275
+ with `triggerVariant` (any `Button` variant), `triggerSize`, and `fullWidth`, or replace
276
+ it entirely with `renderTrigger` when the design needs chrome the button variants do not
277
+ cover:
278
+
279
+ ``````typescript
280
+ <DropdownPanel
281
+ fullWidth
282
+ renderTrigger={({isOpen, toggle}) => <MyPill active={isOpen} onPress={toggle} />}
283
+ width={300}
284
+ >
285
+ {fields}
286
+ </DropdownPanel>
287
+ ``````
288
+
289
+ `variant` still sets both the trigger and the Apply button; `triggerVariant` and
290
+ `applyButtonVariant` override each independently.
291
+
229
292
  ### GPTChat
230
293
 
231
294
  Streaming chat surface for `@terreno/ai`. Histories, messages, submit, and optional MCP/tools stay under consumer control.
@@ -257,9 +320,17 @@ images once per mount.
257
320
  ### SplitPage
258
321
 
259
322
  Master-detail layout. Pass `listViewData` plus `renderListViewItem` for the list, and
260
- `renderContent` for the detail pane. On large screens both panes stay visible. On small
323
+ `renderContent` or children for the detail pane. On large screens both panes stay visible. On small
261
324
  screens the detail replaces the list until the user goes back.
262
325
 
326
+ `desktopChildrenMinWidth` opts into a minimum pixel width for each desktop child when there
327
+ are one or two children. `narrowViewportChildLabels` opts into a labeled full-width pager on
328
+ the narrow viewport. `narrowBelowWidth` uses that viewport when the window is at or below the
329
+ given pixel width; when omitted, the narrow viewport follows `isNarrowViewport()`. These props
330
+ are web only; the native `SplitPage` ignores them. See `SplitPageProps` for when each prop
331
+ applies and what is ignored.
332
+ `IconButton`'s `backgroundOpacity` tints only that button's background.
333
+
263
334
  ```typescript
264
335
  import {SplitPage, Text} from "@terreno/ui";
265
336
 
@@ -564,7 +635,7 @@ import {
564
635
  mediaQuery,
565
636
  mediaQueryLargerThan,
566
637
  mediaQuerySmallerThan,
567
- isMobileDevice,
638
+ isNarrowViewport,
568
639
  } from "@terreno/ui";
569
640
 
570
641
  // Read the current breakpoint
@@ -582,9 +653,9 @@ if (mediaQuerySmallerThan("lg")) {
582
653
  console.log("Smaller than large");
583
654
  }
584
655
 
585
- // Detect mobile
586
- if (isMobileDevice()) {
587
- console.info("Running on mobile device");
656
+ // Current window is below the desktop breakpoint
657
+ if (isNarrowViewport()) {
658
+ console.info("Narrow viewport");
588
659
  }
589
660
  ``````
590
661
 
@@ -610,7 +681,7 @@ Web (desktop staff):
610
681
 
611
682
  On web, `sm` (320) and `md` (375) still classify widths below 1024 so layouts can remain accessible.
612
683
 
613
- `isMobileDevice()` is true below the supported desktop floor: native width < 1024 (`xl`), web width < 1024 (`lg`).
684
+ `isNarrowViewport()` is true below the supported desktop floor: native width < 1024 (`xl`), web width < 1024 (`lg`). `isMobileDevice()` is the same check and is deprecated in favor of `isNarrowViewport`.
614
685
 
615
686
  Responsive `Box` direction props update automatically when the window resizes or a device rotates:
616
687
 
@@ -811,10 +882,10 @@ columns; web shows one **More filters** popover and native includes them in the
811
882
 
812
883
  | Platform | Chrome |
813
884
  | --- | --- |
814
- | Web | Toolbar search + per-column `Filter` popovers (`column.filter`) |
885
+ | Web | Toolbar search + per-column `DropdownPanel` popovers (`column.filter`) |
815
886
  | Native | Toolbar search + one **Filters** sheet (`Modal`) with the same fields |
816
887
 
817
- Column headers use `Filter` with `iconOnly`, which renders a compact icon trigger
888
+ Column headers use `DropdownPanel` with `iconOnly`, which renders a compact icon trigger
818
889
  (24px at the default `triggerSize="sm"`, 32px with `triggerSize="default"`) instead
819
890
  of a labeled button. Give it an accessible name with `triggerAccessibilityLabel`.
820
891
 
@@ -4,7 +4,7 @@ IP: [can-as-permission-seam.md](../implementationPlans/can-as-permission-seam.md
4
4
 
5
5
  ## Phase 1 — `assertAllowed`
6
6
 
7
- - [ ] **Task 1.1**: Helper + unit tests
7
+ - [x] **Task 1.1**: Helper + unit tests
8
8
  - Delivers: `assertAllowed` implements legacy `checkPermissions` and `accessControl.can()`; double-gate test (access allow + permissions deny → allow)
9
9
  - Files: `api/src/rbac/assertAllowed.ts`, `api/src/rbac/assertAllowed.test.ts`
10
10
  - Blocked by: none (can land before MCP adapters; executors wiring waits on unified writes if MCP still duplicates checks)
@@ -12,7 +12,7 @@ IP: [can-as-permission-seam.md](../implementationPlans/can-as-permission-seam.md
12
12
 
13
13
  ## Phase 2 — Hot path
14
14
 
15
- - [ ] **Task 2.1**: Middleware + executors
15
+ - [x] **Task 2.1**: Middleware + executors
16
16
  - Delivers: `permissionMiddleware` and `executeCreate/Update/Delete` call `assertAllowed`; `buildAccessPermissions` not used on requests
17
17
  - Files: `api/src/permissions.ts`, `api/src/sync/executors.ts`, `api/src/api.ts`, `api/src/rbac/modelRouterAccess.ts`, tests
18
18
  - Blocked by: 1.1; unified-mutation-executors Phase 2 so MCP is included automatically
@@ -20,12 +20,12 @@ IP: [can-as-permission-seam.md](../implementationPlans/can-as-permission-seam.md
20
20
 
21
21
  ## Phase 3 — Consumers and docs
22
22
 
23
- - [ ] **Task 3.1**: example-backend dual config
23
+ - [x] **Task 3.1**: example-backend dual config
24
24
  - Delivers: routers with `access` drop redundant AND `permissions` where RBAC is the intent
25
25
  - Files: `example-backend/src/**` model routers
26
26
  - Blocked by: 2.1
27
27
  - Acceptance: example-backend tests pass
28
- - [ ] **Task 3.2**: Docs + breaking changelog
28
+ - [x] **Task 3.2**: Docs + breaking changelog
29
29
  - Files: `docs/reference/api.md`, `docs/how-to/create-a-model.md`, `docs/implementationPlans/rbac-permissions.md` pointer, changelog
30
30
  - Blocked by: 2.1
31
31
  - Skills: `update-docs`
@@ -4,12 +4,12 @@ IP: [collection-registry.md](../implementationPlans/collection-registry.md)
4
4
 
5
5
  ## Phase 1 — Dual-write catalog
6
6
 
7
- - [ ] **Task 1.1**: `CollectionRegistry` module
7
+ - [x] **Task 1.1**: `CollectionRegistry` module
8
8
  - Delivers: `registerCollection`, `replaceCollectionOptions`, `getCollection`, `listCollections`, `clearCollectionRegistry` with unit tests (unknown path no-op, options replace)
9
9
  - Files: `api/src/collectionRegistry.ts`, `api/src/collectionRegistry.test.ts`
10
10
  - Blocked by: none
11
11
  - Acceptance: bun tests for the module pass without wiring modelRouter
12
- - [ ] **Task 1.2**: Dual-write from `modelRouter`
12
+ - [x] **Task 1.2**: Dual-write from `modelRouter`
13
13
  - Delivers: `modelRouter` / `_buildModelRouter` write the catalog in addition to existing `register*` / `update*`
14
14
  - Files: `api/src/api.ts`
15
15
  - Blocked by: 1.1
@@ -17,12 +17,12 @@ IP: [collection-registry.md](../implementationPlans/collection-registry.md)
17
17
 
18
18
  ## Phase 2 — Surfaces read the catalog
19
19
 
20
- - [ ] **Task 2.1**: MCP and realtime views
20
+ - [x] **Task 2.1**: MCP and realtime views
21
21
  - Delivers: `getMCPRegistry` / realtime finders read `CollectionRegistry`; arrays in those files removed
22
22
  - Files: `api/src/mcp/registry.ts`, `api/src/realtime/registry.ts`, related tests
23
23
  - Blocked by: 1.2
24
24
  - Acceptance: MCP and realtime tests pass; `updateMCPRegistryOptions` updates the shared record
25
- - [ ] **Task 2.2**: Sync view + keep validation
25
+ - [x] **Task 2.2**: Sync view + keep validation
26
26
  - Delivers: sync lookup uses catalog; `registerSync` validation + index promises still run
27
27
  - Files: `api/src/sync/registry.ts`, `api/src/sync/*.test.ts`
28
28
  - Blocked by: 1.2
@@ -30,12 +30,12 @@ IP: [collection-registry.md](../implementationPlans/collection-registry.md)
30
30
 
31
31
  ## Phase 3 — Contract
32
32
 
33
- - [ ] **Task 3.1**: Single writer + clear-all
33
+ - [x] **Task 3.1**: Single writer + clear-all
34
34
  - Delivers: `modelRouter` only writes `CollectionRegistry`; wrapper register/update/clear functions; tests that used independent clears updated
35
35
  - Files: `api/src/api.ts`, registry wrappers, tests
36
36
  - Blocked by: 2.1, 2.2
37
37
  - Acceptance: one `replaceCollectionOptions` is enough for MCP+sync options identity
38
- - [ ] **Task 3.2**: Docs + changelog
38
+ - [x] **Task 3.2**: Docs + changelog
39
39
  - Files: `docs/explanation/modular-api-design.md`, `docs/reference/api.md`, changelog
40
40
  - Blocked by: 3.1
41
41
  - Skills: `update-docs`
@@ -0,0 +1,150 @@
1
+ # Task List: Demo workshop
2
+
3
+ See: [`docs/implementationPlans/demo-workshop.md`](../implementationPlans/demo-workshop.md)
4
+
5
+ **RTK deprecation flag:** None
6
+
7
+ ## Instructions for the implementing agent
8
+
9
+ - Work the frontier: any task whose blockers are complete. The tracer is Task 1.1 (Button).
10
+ - Do not start iOS work, a translation catalog, or an addon API.
11
+ - Docs named on a task ship in that task. Use the `update-docs` skill.
12
+ - UI tasks also use `verify-ui-changes` and `terreno-ui`.
13
+ - Visual tasks use `review-chart-visuals` for the PNG diff workflow, then the new demo how-to.
14
+ - Run the task's verification command before handoff. `bun run lint` and `bun run demo:compile` on every demo task.
15
+
16
+ ## Phase 1: Catalog, snippets, and preview bar
17
+
18
+ - [x] **Task 1.1**: Button catalog contract
19
+ - Delivers: Button has a copyable usage snippet, resolvable related links, stable stories, one declarative interaction list, and typed control defaults.
20
+ - Files: `demo/demoConfig.tsx`, `demo/story-config/Button.config.tsx`, `demo/stories/Button.stories.tsx`, `demo/collectRegisteredStoryRenders.ts`, `demo/app/demo/[component].tsx`, `demo/README.md`
21
+ - Blocked by: none
22
+ - Acceptance: a unit test fails when a related name does not resolve, when an excluded story has an empty reason, or when a boolean control defaults to `""`. Button's snippet renders and copies. `showInDemo: false` hides a Button story in demo mode and leaves it on the dev route.
23
+ - Verification: `bun test demo/collectRegisteredStoryRenders.ts demo/demoConfig` (or the new colocated test), `bun run demo:compile`, and a web demo pass that opens Button, copies the snippet, and follows one related link.
24
+ - Docs: `demo/README.md` catalog-contract section
25
+ - Skills: `update-docs`, `terreno-ui`, `verify-ui-changes`
26
+
27
+ - [x] **Task 1.2**: Search, categories, and related links
28
+ - Delivers: the home grid and dev index filter by text and category, and every component's related row is links.
29
+ - Files: `demo/components/DemoHomePage.tsx`, `demo/components/DevHomePage.tsx`, `demo/app/demo/[component].tsx`, story configs whose `related` strings do not resolve, `demo/README.md`
30
+ - Blocked by: Task 1.1
31
+ - Acceptance: searching "button" shows Button; choosing a category hides other categories; a broken related name fails the catalog test; the home grid still does not nest pressables (`demo/components/DemoCard.test.tsx`).
32
+ - Verification: catalog unit test, `demo/components/DemoCard.test.tsx`, and a web demo pass of search, category filter, and a related link.
33
+ - Docs: `demo/README.md`
34
+ - Skills: `update-docs`, `terreno-ui`, `verify-ui-changes`
35
+
36
+ - [x] **Task 1.3**: Usage snippet on every component
37
+ - Delivers: every registered story config has `usageExample`, and the component page can copy it.
38
+ - Files: `demo/story-config/*.config.tsx`, `demo/app/demo/[component].tsx`, `scripts/check-demo-coverage.ts` or a sibling check, `demo/README.md`
39
+ - Blocked by: Task 1.1
40
+ - Acceptance: `bun run check:demo-coverage` (or the new snippet check it calls) fails when any registered config lacks a non-empty `usageExample`. The Button page copy control still works.
41
+ - Verification: the check command, plus one web copy action on a second component (TextField).
42
+ - Docs: `demo/README.md`
43
+ - Skills: `update-docs`, `verify-ui-changes`
44
+
45
+ - [x] **Task 1.4**: Preview toolbar and URL state
46
+ - Delivers: demo and dev component routes change theme, viewport, background, locale, right-to-left, and reduced motion from the URL. Embeds apply that state and hide the bar.
47
+ - Files: `demo/components/DemoChrome.tsx`, `demo/app/_layout.tsx`, `demo/app/demo/_layout.tsx`, `demo/app/dev/_layout.tsx`, `demo/contexts/EmbedModeContext.tsx`, `docs/how-to/preview-demo.md`, `demo/README.md`
48
+ - Blocked by: Task 1.1
49
+ - Acceptance: Button at a documented query uses the dark remap and the 375 viewport. Consent or date stories that already read locale receive the toolbar locale. Embed hides the bar. Reloading keeps the query.
50
+ - Verification: a focused demo unit test for query parse/serialize, `bun run demo:compile`, and a web demo pass of the Button query plus one embed URL.
51
+ - Docs: `docs/how-to/preview-demo.md`, `demo/README.md`
52
+ - Skills: `update-docs`, `terreno-ui`, `verify-ui-changes`
53
+
54
+ ## Phase 2: Web proof and health
55
+
56
+ - [ ] **Task 2.1**: Web interaction and axe for Button
57
+ - Delivers: Playwright runs Button's step list and axe against the Button stories.
58
+ - Files: `scripts/demo/runWebStoryChecks.ts`, `demo/story-config/Button.config.tsx`, root `package.json` (axe dependency if needed), `.circleci/config.yml`, `.circleci/continue-config.yml`, `docs/how-to/run-tests-locally.md`, `docs/reference/test.md`
59
+ - Blocked by: Task 1.1
60
+ - Acceptance: the Button interaction steps pass in Chromium. A serious axe violation fails the command. An excluded story with a reason is skipped. The job is required for `ui/**` and `demo/**` pull requests.
61
+ - Verification: `bun run demo:web-checks --only=Button` (the script this task adds) locally against demo web, then the CircleCI path-filter test if one exists beside `.circleci/`.
62
+ - Docs: `docs/how-to/run-tests-locally.md`, `docs/reference/test.md`
63
+ - Skills: `update-docs`, `verify-ui-changes`
64
+
65
+ - [ ] **Task 2.2**: Web visual harness for Button
66
+ - Delivers: one cropped web PNG baseline for each stable Button story, compared with the chart pixel matcher.
67
+ - Files: `scripts/demo/compareDemoSnapshots.ts`, `demo/rendered-snapshots/web/`, `scripts/charts/compareChartImages.ts` (reuse only), `docs/how-to/compare-demo-snapshots.md`, `docs/reference/ui.md`
68
+ - Blocked by: Task 1.1
69
+ - Acceptance: `bun run demo:snapshots:compare --only=Button` passes against the new goldens and fails when a golden is missing. Chart compare still passes for the existing chart fixtures.
70
+ - Verification: the new compare command and `bun run ui:charts:compare`.
71
+ - Docs: `docs/how-to/compare-demo-snapshots.md`, `docs/reference/ui.md`, `docs/how-to/compare-chart-rendered-snapshots.md` (pointer only)
72
+ - Skills: `update-docs`, `review-chart-visuals`
73
+
74
+ - [ ] **Task 2.3**: Web proof for every stable story
75
+ - Delivers: every stable story has interaction steps or an exclusion reason, an axe run, and a web PNG baseline.
76
+ - Files: `demo/story-config/*.config.tsx`, `demo/stories/*.stories.tsx`, `demo/rendered-snapshots/web/`, the web check and snapshot scripts
77
+ - Blocked by: Task 2.1, Task 2.2
78
+ - Acceptance: the web check and snapshot commands, with no `--only`, exit 0. Removing one stable story's golden or steps fails the matching command. Excluded stories name a reason.
79
+ - Verification: `bun run demo:web-checks` and `bun run demo:snapshots:compare`.
80
+ - Docs: `docs/how-to/compare-demo-snapshots.md`, `docs/reference/test.md`
81
+ - Skills: `update-docs`, `review-chart-visuals`
82
+
83
+ - [ ] **Task 2.4**: Story health and CI summary
84
+ - Delivers: the component page shows render, interaction, accessibility, and visual status from `demo/story-health.json`. CI stores that file and writes a check summary.
85
+ - Files: `demo/app/demo/[component].tsx`, `scripts/demo/writeStoryHealth.ts`, `.circleci/continue-config.yml`, `docs/reference/test.md`
86
+ - Blocked by: Task 2.3
87
+ - Acceptance: Button shows a pass row after the web commands. A forced failing story shows fail. A missing health file shows not-run. The CircleCI job summary lists failed story ids. The job does not call `gh pr comment`.
88
+ - Verification: unit test for health rendering, the web commands, and a CI config test or review that the job uploads artifacts and writes the summary.
89
+ - Docs: `docs/reference/test.md`, `demo/README.md`
90
+ - Skills: `update-docs`, `verify-ui-changes`
91
+
92
+ ## Phase 3: Android
93
+
94
+ - [ ] **Task 3.1**: Android proof for Button
95
+ - Delivers: a CircleCI Android emulator job runs Button's steps, accessibility-tree assertions, and a cropped Android PNG.
96
+ - Files: `.circleci/config.yml`, `.circleci/continue-config.yml`, `scripts/demo/generateMaestroFlows.ts`, `.maestro/flows/demo/generated/`, `demo/rendered-snapshots/android/`, `docs/how-to/circleci.md`, `docs/how-to/run-tests-locally.md`
97
+ - Blocked by: Task 2.1
98
+ - Acceptance: Pixel 6 API 34 runs the generated Button flow. The job is required when `ui/**` or `demo/**` changes. A missing Android golden fails the job. Web axe is unchanged.
99
+ - Verification: the local Maestro command documented in the how-to, against an emulator, for the Button flow. Record the CircleCI job name.
100
+ - Docs: `docs/how-to/circleci.md`, `docs/how-to/run-tests-locally.md`, `docs/reference/test.md`
101
+ - Skills: `update-docs`, `verify-ui-changes`
102
+
103
+ - [ ] **Task 3.2**: Android proof for every stable story
104
+ - Delivers: every stable story has an Android flow, accessibility-tree check, and PNG, or an exclusion reason.
105
+ - Files: generated Maestro flows, `demo/rendered-snapshots/android/`, `demo/story-health.json` writer
106
+ - Blocked by: Task 3.1, Task 2.3
107
+ - Acceptance: the Android job without `--only` exits 0. Health on Button includes the Android columns. An excluded story is absent from the Android failure list and its reason is in the summary.
108
+ - Verification: the Android compare and Maestro commands across the stable catalog.
109
+ - Docs: `docs/how-to/compare-demo-snapshots.md`, `docs/reference/test.md`
110
+ - Skills: `update-docs`, `review-chart-visuals`
111
+
112
+ ## Phase 4: Major versions
113
+
114
+ - [ ] **Task 4.1**: Version manifest and dropdown
115
+ - Delivers: production stays on the current major, `versions.json` lists released majors and a `preview/<major>` branch, and the top bar dropdown navigates there. The default is the highest released major.
116
+ - Files: `scripts/demo/publishDemoVersions.ts`, `scripts/ci/netlify-deploy.sh`, `demo/components/DemoChrome.tsx`, `docs/how-to/demo-versions.md`, `.circleci/continue-config.yml`
117
+ - Blocked by: Task 1.4
118
+ - Acceptance: a unit test of the manifest builder marks `preview/58` as preview and not current, marks 57 as current, and omits `pr-*` aliases. The dropdown on the home page shows those labels. `versions.json` on the production origin sends CORS headers the aliases can read.
119
+ - Verification: the manifest unit test, a deploy dry-run, and a web demo pass of the dropdown.
120
+ - Docs: `docs/how-to/demo-versions.md`, `demo/README.md`
121
+ - Skills: `update-docs`, `verify-ui-changes`
122
+
123
+ - [ ] **Task 4.2**: Freeze the previous major and backfill 56
124
+ - Delivers: moving master from 57 to a later major freezes 57 on alias `v57`. Alias `v56` serves the last master commit whose package major is 56.
125
+ - Files: `scripts/demo/publishDemoVersions.ts`, `.circleci/continue-config.yml`, `docs/how-to/demo-versions.md`
126
+ - Blocked by: Task 4.1
127
+ - Acceptance: a test with a fake deploy history freezes the previous production deploy when the major increases, and leaves 57 updating on ordinary master commits. The backfill command documents the git revision it deployed for 56.
128
+ - Verification: unit test of the freeze decision, plus the one-time 56 alias deploy recorded in the how-to.
129
+ - Docs: `docs/how-to/demo-versions.md`
130
+ - Skills: `update-docs`
131
+
132
+ - [ ] **Task 4.3**: Docs embeds follow the demo major
133
+ - Delivers: a 57 docs page embeds the 57 demo. The next docs version embeds the 58 preview when the manifest lists it.
134
+ - Files: `website/docusaurus.config.ts`, `website/src/components/ComponentDemo/index.tsx`, `docs/how-to/demo-versions.md`, the docs reference page that describes component embeds
135
+ - Blocked by: Task 4.1
136
+ - Acceptance: `ComponentDemo` for the 57 docs build requests the 57 demo URL with `?embed=1`. When the manifest has an unreleased preview, the next docs build uses that preview URL. A missing preview falls back to production.
137
+ - Verification: a website unit test or build-arg test for the URL choice, and `bun run website:build`.
138
+ - Docs: `docs/how-to/demo-versions.md` and the existing component-embed reference section
139
+ - Skills: `update-docs`
140
+
141
+ ## Phase 5: MCP catalog
142
+
143
+ - [ ] **Task 5.1**: Public demo catalog tools
144
+ - Delivers: `terreno_list_demo_stories` and `terreno_get_demo_story` return Button's snippet, route, story ids, and the version manifest URL.
145
+ - Files: `demo/demo-catalog.json`, `demo/package.json`, `mcp-server/src/tools.ts`, MCP tests, `docs/reference/mcp-server.md`
146
+ - Blocked by: Task 1.3, Task 4.1
147
+ - Acceptance: `terreno_get_demo_story` for Button includes `usageExample` and a `/demo/Button` route. The list tool filters by category. The response points at production `versions.json`. A catalog drift test fails when a registered component is missing from the JSON.
148
+ - Verification: `cd mcp-server && bun test` for the new tool tests, and `bun run demo:catalog` followed by the drift check.
149
+ - Docs: `docs/reference/mcp-server.md`, `demo/README.md`
150
+ - Skills: `update-docs`
@@ -4,12 +4,12 @@ IP: [describe-model-schema.md](../implementationPlans/describe-model-schema.md)
4
4
 
5
5
  ## Phase 1 — Descriptor + MCP
6
6
 
7
- - [ ] **Task 1.1**: `describeModel` / `describeModelForRouter`
7
+ - [x] **Task 1.1**: `describeModel` / `describeModelForRouter`
8
8
  - Delivers: field graph + snapshot tests on a fixture schema
9
9
  - Files: `api/src/schemaMetadata.ts`, `api/src/schemaMetadata.test.ts`
10
10
  - Blocked by: none
11
11
  - Acceptance: snapshots for enum, ref, array, subdocument, system fields
12
- - [ ] **Task 1.2**: MCP Zod from descriptor
12
+ - [x] **Task 1.2**: MCP Zod from descriptor
13
13
  - Delivers: `schemaGenerator.ts` maps `FieldDescription`; no SchemaType switch for kinds already in the descriptor
14
14
  - Files: `api/src/mcp/schemaGenerator.ts`, `api/src/mcp/schemaGenerator.test.ts`
15
15
  - Blocked by: 1.1
@@ -17,7 +17,7 @@ IP: [describe-model-schema.md](../implementationPlans/describe-model-schema.md)
17
17
 
18
18
  ## Phase 2 — Admin
19
19
 
20
- - [ ] **Task 2.1**: `extractFieldMeta` from descriptor
20
+ - [x] **Task 2.1**: `extractFieldMeta` from descriptor
21
21
  - Delivers: admin config fields built from `describeModel`, not OpenAPI property walk
22
22
  - Files: `admin-backend/src/adminApp.ts`, admin-backend tests
23
23
  - Blocked by: 1.1
@@ -25,12 +25,12 @@ IP: [describe-model-schema.md](../implementationPlans/describe-model-schema.md)
25
25
 
26
26
  ## Phase 3 — OpenAPI + docs
27
27
 
28
- - [ ] **Task 3.1**: `getOpenApiSpecForModel` from descriptor
28
+ - [x] **Task 3.1**: `getOpenApiSpecForModel` from descriptor
29
29
  - Delivers: OpenAPI properties derived from `ModelDescription`; populate still applied
30
30
  - Files: `api/src/populate.ts`, `api/src/openApi.test.ts` / example-backend openapi snapshot if required
31
31
  - Blocked by: 1.1
32
32
  - Acceptance: OpenAPI tests pass; any snapshot diff is reviewed in the PR
33
- - [ ] **Task 3.2**: Docs + export
33
+ - [x] **Task 3.2**: Docs + export
34
34
  - Files: `docs/explanation/schema-metadata.md`, `docs/reference/api.md`, `docs/how-to/create-a-model.md`, admin reference, `api/src/index.ts`, changelog
35
35
  - Blocked by: 1.2, 2.1, 3.1
36
36
  - Skills: `update-docs`
@@ -103,19 +103,21 @@ Research: [`docs/implementationPlans/migrate-cicd-to-circleci-research.md`](../i
103
103
  - Files: `.circleci/continue-config.yml`
104
104
  - Depends on: Task 0.2, Task 1.3
105
105
  - Acceptance: preview deploy URL posted or visible; prod deploy on master path filter.
106
- - Note: Path filters and preview jobs exist. Live Netlify still runs on GHA until `terreno-netlify` is filled; CircleCI skips. Cleanup on PR close is GHA `preview-cleanup.yml`.
106
+ - Note: CircleCI is the only Netlify deployer; jobs fail when `terreno-netlify` is empty. PR close triggers CircleCI `preview-cleanup` through `preview-cleanup.yml`.
107
107
 
108
108
  - [ ] **Task 4.2**: Preview cleanup port
109
109
  - Description: On PR close, clean Netlify/GCP preview resources from CircleCI (webhook or GitHub App → pipeline). Prefer OIDC over `GCP_SA_KEY`.
110
110
  - Files: `.circleci/continue-config.yml`
111
111
  - Depends on: Task 4.1
112
112
  - Acceptance: closing a PR removes preview resources; no orphaned Cloud Run `pr-N` services in a test PR.
113
+ - Note: Cutover code landed on branch `move-cd-to-circleci` (GHA deploy workflows disabled; CircleCI deploy jobs fail on empty contexts). Check off after contexts are filled and the acceptance is observed.
113
114
 
114
115
  - [ ] **Task 4.3**: Dual-run cutover for Netlify
115
116
  - Description: Delete GHA deploy workflows after CircleCI trusted.
116
117
  - Files: `.github/workflows/demo-deploy.yml`, `frontend-example-deploy.yml`, `docs-deploy.yml`, `preview-cleanup.yml`
117
118
  - Depends on: Task 4.1, Task 4.2
118
119
  - Acceptance: GHA deploy twins deleted.
120
+ - Note: Cutover code landed on branch `move-cd-to-circleci` (GHA deploy workflows disabled; CircleCI deploy jobs fail on empty contexts). Check off after contexts are filled and the acceptance is observed.
119
121
 
120
122
  ## Phase 5: EAS + fingerprint
121
123
 
@@ -150,13 +152,14 @@ Research: [`docs/implementationPlans/migrate-cicd-to-circleci-research.md`](../i
150
152
  - Files: `.circleci/continue-config.yml`
151
153
  - Depends on: Task 6.1
152
154
  - Acceptance: terraform preview on PR; apply+deploy on master for a safe test path; GitHub Deployment records optional but documented.
153
- - Note: Path filters exist. Live GCP still runs on GHA until `terreno-gcp` is filled; CircleCI skips apply.
155
+ - Note: CircleCI is the only GCP deployer; jobs fail when `terreno-gcp` is empty. `gcp-cd-prod` runs MCP `test:ci` before the MCP deploy.
154
156
 
155
157
  - [ ] **Task 6.3**: Dual-run cutover for CD
156
158
  - Description: Single deployer: disable GHA `cd.yml` when CircleCI CD is required; remove GitHub OIDC provider only after GHA CD is gone (or keep read-only if other repos need it — document).
157
159
  - Files: `.github/workflows/cd.yml`, terraform OIDC
158
160
  - Depends on: Task 6.2
159
161
  - Acceptance: only CircleCI performs terreno CD; no double apply.
162
+ - Note: Cutover code landed on branch `move-cd-to-circleci` (GHA deploy workflows disabled; CircleCI deploy jobs fail on empty contexts). Check off after contexts are filled and the acceptance is observed.
160
163
 
161
164
  ## Phase 7: npm publish
162
165
 
@@ -200,7 +203,7 @@ Research: [`docs/implementationPlans/migrate-cicd-to-circleci-research.md`](../i
200
203
  - Depends on: Task 0.2
201
204
  - Acceptance: Security tab still receives results **or** explicit maintainer sign-off on alternative.
202
205
 
203
- - [ ] **Task 9.2**: Replace Dependabot auto-merge + triage + roadmap-generate + docs-audit
206
+ - [ ] **Task 9.2**: Replace Dependabot auto-merge + triage + docs-audit (roadmap workflows stay on GitHub Actions, decided 2026-09-26)
204
207
  - Description: Implement CircleCI (or Renovate) equivalents; wire issue/schedule triggers without leaving required logic on GHA.
205
208
  - Files: `.circleci/continue-config.yml`, corresponding GHA deletions
206
209
  - Depends on: Task 0.2
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "@modelcontextprotocol/node": "^2.0.0",
12
12
  "@modelcontextprotocol/server": "^2.0.0",
13
13
  "@sentry/bun": "^10.39.0",
14
- "@terreno/api": "57.6.1",
14
+ "@terreno/api": "57.8.0",
15
15
  "express": "^5.2.1",
16
16
  "luxon": "^3.7.2",
17
17
  "minisearch": "^7.2.0",
@@ -104,5 +104,5 @@
104
104
  "test:coverage": "bun run ../scripts/check-coverage.ts"
105
105
  },
106
106
  "type": "module",
107
- "version": "57.6.1"
107
+ "version": "57.8.0"
108
108
  }
@@ -253,7 +253,7 @@ radiusSm, radiusMd, radiusLg, radiusXl, radius2xl, radius3xl
253
253
  ## Utilities
254
254
 
255
255
  ```typescript
256
- import { useStoredState, MediaQuery, isMobileDevice } from "@terreno/ui";
256
+ import { useStoredState, MediaQuery, isNarrowViewport } from "@terreno/ui";
257
257
 
258
258
  // Persist state to storage
259
259
  const [value, setValue] = useStoredState("key", defaultValue);
@@ -263,9 +263,10 @@ const [value, setValue] = useStoredState("key", defaultValue);
263
263
  <DesktopLayout />
264
264
  </MediaQuery>
265
265
 
266
- // Device detection
267
- if (isMobileDevice()) {
268
- // Mobile-specific code
266
+ // Current window is below the desktop breakpoint.
267
+ // isMobileDevice() is deprecated in favor of isNarrowViewport().
268
+ if (isNarrowViewport()) {
269
+ // Narrow-viewport code
269
270
  }
270
271
  ```
271
272
 
@@ -0,0 +1,64 @@
1
+ # Upgrading to 57.7.0
2
+
3
+ **Action required:** No
4
+ **Affected packages:** @terreno/ui
5
+
6
+ ## Summary
7
+
8
+ Bump every `@terreno/*` package together to `57.7.0`. `@terreno/ui`'s `Filter` is now `DropdownPanel`. Existing `Filter` and `FilterProps` imports keep working until Terreno 58. Panels stay on screen, render through the `TerrenoProvider` portal on native, and accept styled or custom triggers. No Expo upgrade is required if you are already on `57.x`.
9
+
10
+ ## Breaking changes
11
+
12
+ None
13
+
14
+ ## Deprecations
15
+
16
+ ### `Filter` and `FilterProps`
17
+
18
+ **What changed**
19
+
20
+ `Filter` is renamed to `DropdownPanel`. `Filter` and `FilterProps` stay exported as deprecated aliases and are removed in Terreno 58. `FilterSelectMenu`, `FilterBoolean`, `FilterAccordion`, and `FilterChangesBadge` keep their names.
21
+
22
+ **Why**
23
+
24
+ The control is a general compositional dropdown (trigger, anchored panel, optional Apply/Clear/Cancel footer), not a filter-only widget.
25
+
26
+ **Migration**
27
+
28
+ ```tsx
29
+ // Before
30
+ import {Filter} from "@terreno/ui";
31
+
32
+ <Filter label="Status">{children}</Filter>;
33
+
34
+ // After
35
+ import {DropdownPanel} from "@terreno/ui";
36
+
37
+ <DropdownPanel label="Status">{children}</DropdownPanel>;
38
+ ```
39
+
40
+ ## Changed behavior
41
+
42
+ ### Panels stay on screen and escape clipping
43
+
44
+ **What changed**
45
+
46
+ `DropdownPanel` (including the `Filter` alias) right-aligns to its trigger when a left-aligned panel would cross the right viewport edge, clamps to an 8px screen margin, flips above the trigger when there is no usable room below, and scrolls its body with the footer pinned when the content is taller than the space available. On native it renders through the `TerrenoProvider` portal host, so the panel is no longer clipped inside scroll views or cards. Without a host it stays an inline overlay.
47
+
48
+ **Why**
49
+
50
+ Left-aligned panels ran off screen, and inline overlays were clipped by parent scroll views.
51
+
52
+ **Migration**
53
+
54
+ No call-site change is required. Pass `align` or `maxPanelHeight` to override the automatic layout. Apps that position their own panels can call `computeDropdownPanelLayout`.
55
+
56
+ ## New capabilities
57
+
58
+ `DropdownPanel` triggers accept `triggerVariant` (any `Button` variant), `applyButtonVariant`, `triggerSize` on labeled triggers, `fullWidth`, and `renderTrigger` for a fully custom trigger.
59
+
60
+ ## Verification
61
+
62
+ - `bun add` every `@terreno/*` dependency to `57.7.0`, then `bun run compile` at the app root
63
+ - Open a screen that uses `Filter` or `DropdownPanel` and confirm the panel stays inside the viewport, including near the right edge and inside a scrolling parent
64
+ - Replace `Filter` imports with `DropdownPanel` before upgrading to Terreno 58