@terreno/mcp 0.31.0 → 56.0.0-beta.2

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 (116) hide show
  1. package/dist/bootstrap.d.ts.map +1 -1
  2. package/dist/bootstrap.js +8 -9
  3. package/dist/bootstrap.js.map +1 -1
  4. package/dist/docs/templates/bootstrap/frontend/app/_layout.template.tsx +1 -1
  5. package/dist/docs/upgrades/56.0.0-beta.2.md +59 -0
  6. package/dist/docs/versioned/next/README.md +2 -0
  7. package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +21 -0
  8. package/dist/docs/versioned/next/how-to/README.md +2 -0
  9. package/dist/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +445 -0
  10. package/dist/docs/versioned/next/implementationPlans/PLAN_INDEX.md +28 -50
  11. package/dist/docs/versioned/next/implementationPlans/b2b-platform-program.md +3 -2
  12. package/dist/docs/versioned/next/implementationPlans/comms-abstraction.md +98 -15
  13. package/dist/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +63 -13
  14. package/dist/docs/versioned/next/implementationPlans/comms-adapter-twilio-sms.md +65 -12
  15. package/dist/docs/versioned/next/implementationPlans/comms-adapter-twilio-verify.md +9 -3
  16. package/dist/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +180 -0
  17. package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci-research.md +126 -0
  18. package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +269 -0
  19. package/dist/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +52 -47
  20. package/dist/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +303 -0
  21. package/dist/docs/versioned/next/implementationPlans/syncdb-codegen.md +252 -0
  22. package/dist/docs/versioned/next/implementationPlans/syncdb-local-first.md +468 -420
  23. package/dist/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +425 -0
  24. package/dist/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +800 -0
  25. package/dist/docs/versioned/next/reference/README.md +2 -0
  26. package/dist/docs/versioned/next/reference/comms.md +132 -0
  27. package/dist/docs/versioned/next/reference/environment-variables.md +9 -0
  28. package/dist/docs/versioned/next/reference/syncdb.md +456 -0
  29. package/dist/docs/versioned/next/superpowers/plans/2026-07-28-admin-mobile-navigation.md +97 -0
  30. package/dist/docs/versioned/next/superpowers/specs/2026-07-28-admin-mobile-navigation-design.md +36 -0
  31. package/dist/docs/versioned/next/tasks/comms-abstraction.md +29 -16
  32. package/dist/docs/versioned/next/tasks/comms-adapter-sendgrid.md +17 -7
  33. package/dist/docs/versioned/next/tasks/comms-adapter-twilio-sms.md +17 -7
  34. package/dist/docs/versioned/next/tasks/comms-adapter-twilio-verify.md +3 -3
  35. package/dist/docs/versioned/next/tasks/comms-admin-dashboard.md +52 -0
  36. package/dist/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +215 -0
  37. package/dist/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +10 -10
  38. package/dist/docs/versioned/next/tasks/syncdb-codegen.md +65 -0
  39. package/dist/docs/versioned/next/tasks/syncdb-local-first.md +434 -117
  40. package/package.json +3 -3
  41. package/src/docs/templates/bootstrap/frontend/app/_layout.template.tsx +1 -1
  42. package/src/docs/upgrades/56.0.0-beta.2.md +59 -0
  43. package/src/docs/versioned/next/README.md +2 -0
  44. package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +21 -0
  45. package/src/docs/versioned/next/how-to/README.md +2 -0
  46. package/src/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +445 -0
  47. package/src/docs/versioned/next/implementationPlans/PLAN_INDEX.md +28 -50
  48. package/src/docs/versioned/next/implementationPlans/b2b-platform-program.md +3 -2
  49. package/src/docs/versioned/next/implementationPlans/comms-abstraction.md +98 -15
  50. package/src/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +63 -13
  51. package/src/docs/versioned/next/implementationPlans/comms-adapter-twilio-sms.md +65 -12
  52. package/src/docs/versioned/next/implementationPlans/comms-adapter-twilio-verify.md +9 -3
  53. package/src/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +180 -0
  54. package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci-research.md +126 -0
  55. package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +269 -0
  56. package/src/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +52 -47
  57. package/src/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +303 -0
  58. package/src/docs/versioned/next/implementationPlans/syncdb-codegen.md +252 -0
  59. package/src/docs/versioned/next/implementationPlans/syncdb-local-first.md +468 -420
  60. package/src/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +425 -0
  61. package/src/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +800 -0
  62. package/src/docs/versioned/next/reference/README.md +2 -0
  63. package/src/docs/versioned/next/reference/comms.md +132 -0
  64. package/src/docs/versioned/next/reference/environment-variables.md +9 -0
  65. package/src/docs/versioned/next/reference/syncdb.md +456 -0
  66. package/src/docs/versioned/next/superpowers/plans/2026-07-28-admin-mobile-navigation.md +97 -0
  67. package/src/docs/versioned/next/superpowers/specs/2026-07-28-admin-mobile-navigation-design.md +36 -0
  68. package/src/docs/versioned/next/tasks/comms-abstraction.md +29 -16
  69. package/src/docs/versioned/next/tasks/comms-adapter-sendgrid.md +17 -7
  70. package/src/docs/versioned/next/tasks/comms-adapter-twilio-sms.md +17 -7
  71. package/src/docs/versioned/next/tasks/comms-adapter-twilio-verify.md +3 -3
  72. package/src/docs/versioned/next/tasks/comms-admin-dashboard.md +52 -0
  73. package/src/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +215 -0
  74. package/src/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +10 -10
  75. package/src/docs/versioned/next/tasks/syncdb-codegen.md +65 -0
  76. package/src/docs/versioned/next/tasks/syncdb-local-first.md +434 -117
  77. package/dist/__tests__/bootstrap.test.d.ts +0 -2
  78. package/dist/__tests__/bootstrap.test.d.ts.map +0 -1
  79. package/dist/__tests__/bootstrap.test.js +0 -299
  80. package/dist/__tests__/bootstrap.test.js.map +0 -1
  81. package/dist/__tests__/databaseQuery.test.d.ts +0 -2
  82. package/dist/__tests__/databaseQuery.test.d.ts.map +0 -1
  83. package/dist/__tests__/databaseQuery.test.js +0 -83
  84. package/dist/__tests__/databaseQuery.test.js.map +0 -1
  85. package/dist/__tests__/docsRoot.test.d.ts +0 -2
  86. package/dist/__tests__/docsRoot.test.d.ts.map +0 -1
  87. package/dist/__tests__/docsRoot.test.js +0 -59
  88. package/dist/__tests__/docsRoot.test.js.map +0 -1
  89. package/dist/__tests__/inferPackages.test.d.ts +0 -2
  90. package/dist/__tests__/inferPackages.test.d.ts.map +0 -1
  91. package/dist/__tests__/inferPackages.test.js +0 -35
  92. package/dist/__tests__/inferPackages.test.js.map +0 -1
  93. package/dist/__tests__/preload.d.ts +0 -2
  94. package/dist/__tests__/preload.d.ts.map +0 -1
  95. package/dist/__tests__/preload.js +0 -12
  96. package/dist/__tests__/preload.js.map +0 -1
  97. package/dist/__tests__/prompts.test.d.ts +0 -2
  98. package/dist/__tests__/prompts.test.d.ts.map +0 -1
  99. package/dist/__tests__/prompts.test.js +0 -295
  100. package/dist/__tests__/prompts.test.js.map +0 -1
  101. package/dist/__tests__/resources.test.d.ts +0 -2
  102. package/dist/__tests__/resources.test.d.ts.map +0 -1
  103. package/dist/__tests__/resources.test.js +0 -352
  104. package/dist/__tests__/resources.test.js.map +0 -1
  105. package/dist/__tests__/search.test.d.ts +0 -2
  106. package/dist/__tests__/search.test.d.ts.map +0 -1
  107. package/dist/__tests__/search.test.js +0 -163
  108. package/dist/__tests__/search.test.js.map +0 -1
  109. package/dist/__tests__/tools.test.d.ts +0 -2
  110. package/dist/__tests__/tools.test.d.ts.map +0 -1
  111. package/dist/__tests__/tools.test.js +0 -540
  112. package/dist/__tests__/tools.test.js.map +0 -1
  113. package/dist/__tests__/upgradeGuide.test.d.ts +0 -2
  114. package/dist/__tests__/upgradeGuide.test.d.ts.map +0 -1
  115. package/dist/__tests__/upgradeGuide.test.js +0 -22
  116. package/dist/__tests__/upgradeGuide.test.js.map +0 -1
@@ -0,0 +1,97 @@
1
+ # Admin Mobile Navigation Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** On viewports below 768px, replace the admin shell’s fixed sidebar with a hamburger-triggered left slide-over drawer.
6
+
7
+ **Architecture:** Keep navigation content in one shared internal component. `AdminShell` uses `useWindowDimensions` to switch between desktop rail and mobile header + overlay drawer. Drawer closes on backdrop, close button, and nav selection.
8
+
9
+ **Tech Stack:** React Native / Expo, `@terreno/ui` (`Box`, `Heading`, `Text`, `IconButton`), bun test + `@testing-library/react-native`.
10
+
11
+ ## Global Constraints
12
+
13
+ - Breakpoint: below 768px → mobile; 768px and above → desktop sidebar.
14
+ - Menu style: left slide-over drawer with dismissible backdrop.
15
+ - Accessibility: hamburger labeled "Open navigation menu"; close labeled "Close navigation menu".
16
+ - Do not change public `AdminShellProps` API unless required.
17
+ - Always support React Native Web.
18
+
19
+ ---
20
+
21
+ ### Task 1: Failing AdminShell responsive tests
22
+
23
+ **Files:**
24
+ - Create: `admin-frontend/src/AdminShell.test.tsx`
25
+
26
+ **Interfaces:**
27
+ - Consumes: `AdminShell` from `./AdminShell`; mocked `./useAdminConfig` and `expo-router`
28
+ - Produces: failing tests that assert desktop sidebar at ≥768, mobile header below 768, drawer open/close, nav closes drawer, a11y labels
29
+
30
+ - [ ] **Step 1: Write the failing test file**
31
+
32
+ Mock `useWindowDimensions` via a mutable width, mock `useAdminConfig` with a small config (Home + one model), mock `expo-router.router.push`. Assert:
33
+
34
+ 1. width 1024 → `admin-shell-sidebar` present; hamburger absent
35
+ 2. width 500 → sidebar absent; `admin-shell-menu-button` present with accessibilityLabel "Open navigation menu"
36
+ 3. press menu → `admin-shell-drawer` and backdrop appear; close button has "Close navigation menu"
37
+ 4. press backdrop / close → drawer gone
38
+ 5. open drawer, press Home nav → `router.push` called and drawer closed
39
+
40
+ - [ ] **Step 2: Run tests and confirm failure**
41
+
42
+ Run: `cd admin-frontend && bun test src/AdminShell.test.tsx`
43
+ Expected: FAIL (missing mobile UI / testIDs)
44
+
45
+ ---
46
+
47
+ ### Task 2: Implement responsive AdminShell
48
+
49
+ **Files:**
50
+ - Modify: `admin-frontend/src/AdminShell.tsx`
51
+ - Test: `admin-frontend/src/AdminShell.test.tsx`
52
+
53
+ **Interfaces:**
54
+ - Consumes: nav data from `useAdminConfig` (existing)
55
+ - Produces: `MOBILE_BREAKPOINT = 768`; shared sidebar body; mobile header; overlay drawer with backdrop
56
+
57
+ - [ ] **Step 1: Extract shared sidebar body**
58
+
59
+ Create an internal `AdminShellSidebarNav` that receives navigate callbacks, grouped models, scripts, screens, configurationPath, footer, sidebarVariant, and optional `onNavigate` that runs after each nav press (used to close the drawer).
60
+
61
+ - [ ] **Step 2: Wire responsive chrome**
62
+
63
+ ```tsx
64
+ const MOBILE_BREAKPOINT = 768;
65
+ const {width} = useWindowDimensions();
66
+ const isMobileLayout = width < MOBILE_BREAKPOINT;
67
+ const [isNavOpen, setIsNavOpen] = useState(false);
68
+ ```
69
+
70
+ Desktop: existing fixed 280px sidebar.
71
+ Mobile: compact header (`admin-shell-mobile-header`) with `IconButton` (`iconName="bars"`, testID `admin-shell-menu-button`) + "Admin" heading; main content full width.
72
+ When `isNavOpen`: absolute full-screen overlay (`admin-shell-drawer`) with backdrop (`admin-shell-drawer-backdrop`) and 280px panel containing close `IconButton` (`iconName="xmark"`, testID `admin-shell-drawer-close`) + shared nav. Close on backdrop, close button, and after navigate.
73
+
74
+ - [ ] **Step 3: Close drawer when resizing to desktop**
75
+
76
+ `useEffect` clears `isNavOpen` when `!isMobileLayout`.
77
+
78
+ - [ ] **Step 4: Run tests**
79
+
80
+ Run: `cd admin-frontend && bun test src/AdminShell.test.tsx`
81
+ Expected: PASS
82
+
83
+ - [ ] **Step 5: Compile and lint**
84
+
85
+ Run: `cd admin-frontend && bun run compile && bun run lint`
86
+ Expected: clean
87
+
88
+ ---
89
+
90
+ ### Task 3: Manual UI verification
91
+
92
+ **Files:** none (runtime check in example-frontend admin)
93
+
94
+ - [ ] **Step 1:** With backend + `frontend:web` running, open `/admin` as `admin@example.com`
95
+ - [ ] **Step 2:** Narrow viewport below 768 → hamburger header, no fixed sidebar
96
+ - [ ] **Step 3:** Open drawer, navigate, confirm close; widen to ≥768 → sidebar returns
97
+ - [ ] **Step 4:** Capture screenshot evidence under `.devdata/artifacts/`
@@ -0,0 +1,36 @@
1
+ # Admin Mobile Navigation Design
2
+
3
+ ## Goal
4
+
5
+ Make the admin shell usable on narrow devices by replacing its fixed 280px sidebar with a hamburger-triggered navigation drawer below 768px.
6
+
7
+ ## Responsive behavior
8
+
9
+ - At widths of 768px and above, preserve the existing sidebar and content layout.
10
+ - Below 768px, hide the fixed sidebar and show a compact header with an accessible hamburger button and the Admin label.
11
+ - Opening the hamburger displays the same grouped navigation in a left slide-over drawer above the page.
12
+ - A backdrop covers the remaining page and dismisses the drawer when pressed.
13
+ - The drawer also closes from its close button and after any navigation item is selected.
14
+
15
+ ## Component structure
16
+
17
+ Extract the sidebar body into a shared internal component so desktop and mobile render the same links, groups, configuration entry, and footer. `AdminShell` owns responsive width detection and drawer open state. The existing main content, top bar, breadcrumbs, and header actions remain unchanged apart from the added mobile header.
18
+
19
+ ## Accessibility
20
+
21
+ - The hamburger button has an "Open navigation menu" label.
22
+ - The drawer close button has a "Close navigation menu" label.
23
+ - Backdrop dismissal is available in addition to the explicit close button.
24
+ - Existing navigation labels and hints remain intact.
25
+
26
+ ## Testing
27
+
28
+ Add focused `AdminShell` tests covering:
29
+
30
+ - Desktop sidebar rendering at 768px and above.
31
+ - Mobile header rendering below 768px.
32
+ - Opening and closing the drawer.
33
+ - Closing after selecting a navigation item.
34
+ - Hamburger and close-button accessibility labels.
35
+
36
+ Run the admin frontend test suite, compile, lint, and responsive UI verification.
@@ -4,55 +4,68 @@ IP: [comms-abstraction](../implementationPlans/comms-abstraction.md)
4
4
 
5
5
  ## Phase 1 — Package + contracts
6
6
 
7
- - [ ] **Task 1.1**: Scaffold `@terreno/comms` workspace package
7
+ - [x] **Task 1.1**: Scaffold `@terreno/comms` workspace package
8
8
  - Description: `comms/` package with tsconfig/biome/bun test setup mirroring `feature-flags/`; root workspace entry + `comms:*` scripts
9
9
  - Files: `comms/package.json`, `comms/tsconfig.json`, `comms/biome.jsonc`, root `package.json`
10
10
  - Depends on: none
11
11
  - Acceptance: `bun run comms:compile` and `bun run comms:lint` pass
12
12
  - [ ] **Task 1.2**: Provider interfaces and message types
13
- - Description: `MailProvider`, `SmsProvider`, `PushProvider`, `VerificationProvider`, `SendResult`, `DeliveryEvent` per IP
13
+ - Description: `MailProvider`, `SmsProvider`, `PushProvider`, `VerificationProvider`, `SendResult` (incl. `errorCode`/`errorClass`), `DeliveryEvent`, `CommsHookContext`, `OptOutEvent` per IP
14
+ - Status: base provider/message contracts shipped; `errorCode`/`errorClass`, `CommsHookContext`, and `OptOutEvent` remain
14
15
  - Files: `comms/src/types.ts`
15
16
  - Depends on: 1.1
16
17
  - Acceptance: types compile and are exported
17
- - [ ] **Task 1.3**: Console adapters
18
+ - [x] **Task 1.3**: Console adapters
18
19
  - Description: dev adapters for all four channels logging via `logger.info`
19
20
  - Files: `comms/src/adapters/console.ts` + tests
20
21
  - Depends on: 1.2
21
22
  - Acceptance: each adapter returns `accepted: true` and logs
22
23
  - [ ] **Task 1.4**: `CommsMessage` model + `logSend`
23
- - Description: delivery log model with five-type pattern, `description` on every field, plugins, static `logSend` that never throws
24
+ - Description: delivery log model with five-type pattern, `description` on every field, plugins, static `logSend` that never throws; dashboard-ready fields (`errorCode`, `errorClass`, `attempts[]`, `attemptCount`, `lastAttemptAt`, `retriedFromId`/`retriedById`, `templateId`, retained `payload`)
24
25
  - Files: `comms/src/models/commsMessage.ts` + tests
25
26
  - Depends on: 1.1
26
- - Acceptance: send logging survives a forced model error (logged, not thrown)
27
+ - Acceptance: send logging survives a forced model error (logged, not thrown); attempts append per attempt
28
+ - Status: model and non-throwing `logSend` shipped; dashboard-ready fields remain
27
29
  - [ ] **Task 1.5**: `commsService` send facade
28
- - Description: `sendMail`/`sendSms`/`sendPushToUser`/`startVerification`/`checkVerification`; template render helper; unconfigured-channel behavior (501 in prod, console fallback in dev)
30
+ - Description: `sendMail`/`sendSms`/`sendPushToUser`/`startVerification`/`checkVerification`; template render helper; unconfigured-channel behavior (501 in prod, console fallback in dev); inline retry on `errorClass: "transient"` only
31
+ - Status: send facade, templates, and unconfigured-channel behavior shipped; inline transient retry remains
29
32
  - Files: `comms/src/commsService.ts`, `comms/src/templates.ts` + tests
30
33
  - Depends on: 1.2, 1.3, 1.4
31
- - Acceptance: unit tests cover happy path + unconfigured channel in both env modes
34
+ - Acceptance: unit tests cover happy path + unconfigured channel in both env modes; permanent failures do not retry
35
+ - [ ] **Task 1.6**: Lifecycle hooks
36
+ - Description: `beforeSend` (mutate/cancel), `onSend`, `onError`, `onRetry`, `onOptOut`, `onDeliveryEvent` wiring in the facade; every hook wrapped so a throw is logged and never changes the send outcome
37
+ - Files: `comms/src/commsService.ts` + tests
38
+ - Depends on: 1.5
39
+ - Acceptance: one test per hook (fires with correct context) plus one throwing-hook test per hook
40
+ - [ ] **Task 1.7**: Payload retention + redaction
41
+ - Description: `retainPayloadDays` (default 30) storage of rendered payload post-`redactPayload`; expiry cleanup clears `payload` without touching the log row
42
+ - Files: `comms/src/commsService.ts`, `comms/src/models/commsMessage.ts` + tests
43
+ - Depends on: 1.4, 1.5
44
+ - Acceptance: payload stored redacted; expired payload cleared; `retainPayloadDays: 0` stores nothing
32
45
 
33
46
  ## Phase 2 — CommsApp + routes
34
47
 
35
- - [ ] **Task 2.1**: `PushToken` model
48
+ - [x] **Task 2.1**: `PushToken` model
36
49
  - Description: model per IP with unique token upsert semantics
37
50
  - Files: `comms/src/models/pushToken.ts` + tests
38
51
  - Depends on: 1.1
39
52
  - Acceptance: duplicate token registration updates the existing row
40
- - [ ] **Task 2.2**: `CommsApp` TerrenoPlugin
53
+ - [x] **Task 2.2**: `CommsApp` TerrenoPlugin
41
54
  - Description: options wiring, `getCommsService()` accessor, route mounting on `register()`
42
55
  - Files: `comms/src/commsApp.ts` + tests
43
56
  - Depends on: 1.5, 2.1
44
57
  - Acceptance: plugin registers on `TerrenoApp` and service accessor returns configured providers
45
- - [ ] **Task 2.3**: Push token routes
46
- - Description: modelRouter with `preCreate` owner injection, `OwnerQueryFilter`, deactivate on delete
58
+ - [x] **Task 2.3**: Push token routes
59
+ - Description: custom idempotent registration/list/deactivation endpoints plus modelRouter owner read; persisted `userId` scoping
47
60
  - Files: `comms/src/routes/pushTokens.ts` + supertest
48
61
  - Depends on: 2.2
49
62
  - Acceptance: acceptance criteria bullets 2 pass under supertest
50
- - [ ] **Task 2.4**: Admin delivery explorer
63
+ - [x] **Task 2.4**: Admin delivery explorer
51
64
  - Description: `GET /comms/messages` admin-only, paginated, filtered; OpenAPI builder
52
65
  - Files: `comms/src/routes/commsExplorer.ts` + supertest
53
66
  - Depends on: 2.2
54
67
  - Acceptance: non-admin gets 403; filters work
55
- - [ ] **Task 2.5**: `sendPushToUser` token resolution + pruning
68
+ - [x] **Task 2.5**: `sendPushToUser` token resolution + pruning
56
69
  - Description: resolve active tokens per user; deactivate tokens whose `SendResult` reports permanent failure
57
70
  - Files: `comms/src/commsService.ts` + tests
58
71
  - Depends on: 2.1, 1.5
@@ -60,17 +73,17 @@ IP: [comms-abstraction](../implementationPlans/comms-abstraction.md)
60
73
 
61
74
  ## Phase 3 — Integration + docs
62
75
 
63
- - [ ] **Task 3.1**: example-backend registration
76
+ - [x] **Task 3.1**: example-backend registration
64
77
  - Description: register `CommsApp` with console adapters; env-gated
65
78
  - Files: `example-backend/src/server.ts`
66
79
  - Depends on: 2.2
67
80
  - Acceptance: backend boots; `/comms/pushTokens` in `/openapi.json`
68
- - [ ] **Task 3.2**: Reference docs + rules
81
+ - [x] **Task 3.2**: Reference docs + rules
69
82
  - Description: `docs/reference/comms.md`, rulesync source rule, `bun run rules`
70
83
  - Files: `docs/reference/comms.md`, `.rulesync/**`
71
84
  - Depends on: 2.x
72
85
  - Acceptance: `bun run rules:check` passes
73
- - [ ] **Task 3.3**: CI + publish wiring
86
+ - [x] **Task 3.3**: CI + publish wiring
74
87
  - Description: `comms-ci` workflow; add `@terreno/comms` to `publish-on-tag.yml`
75
88
  - Files: `.github/workflows/comms-ci.yml`, `.github/workflows/publish-on-tag.yml`
76
89
  - Depends on: 1.x
@@ -9,21 +9,31 @@ IP: [comms-adapter-sendgrid](../implementationPlans/comms-adapter-sendgrid.md)
9
9
  - Files: `comms/src/adapters/sendgrid.ts`
10
10
  - Depends on: comms-abstraction Phase 1
11
11
  - Acceptance: mocked-client tests for text/html/template sends
12
- - [ ] **Task 1.2**: Error mapping
13
- - Description: 4xx → `accepted: false` + message; full response body into `CommsMessage.metadata`; never throws
12
+ - [ ] **Task 1.2**: Error classification
13
+ - Description: HTTP status → `errorCode`/`errorClass` per the IP table (400 permanent, 401/403 config, 429/5xx transient); full response body into `CommsMessage.metadata`; never throws
14
14
  - Files: `comms/src/adapters/sendgrid.ts`
15
15
  - Depends on: 1.1
16
- - Acceptance: unverified-sender and bad-address fixtures covered
17
- - [ ] **Task 1.3**: Peer dep + registration + docs
16
+ - Acceptance: unverified-sender (config), bad-address (permanent), and 429 (transient) fixtures assert `errorClass`; permanent skips the inline retry
17
+ - [ ] **Task 1.3**: Dashboard metadata + hooks coverage
18
+ - Description: capture `x-message-id`; `metadata.consoleUrl` Email Activity deep link; `onError` fires with the classified `SendResult`
19
+ - Files: `comms/src/adapters/sendgrid.ts` + tests
20
+ - Depends on: 1.2
21
+ - Acceptance: accepted-send test asserts message id + consoleUrl; failed-send test asserts onError invocation
22
+ - [ ] **Task 1.4**: Peer dep + registration + docs
18
23
  - Description: optional peer `@sendgrid/mail`; env-gated example-backend registration with fail-fast; reference + env docs incl. sender-verification checklist
19
24
  - Files: `comms/package.json`, `example-backend/src/server.ts`, `docs/reference/comms.md`, `docs/reference/environment-variables.md`
20
25
  - Depends on: 1.1
21
26
  - Acceptance: boot without key skips registration; compile passes without the SDK installed
22
27
 
23
- ## Phase 2 — Delivery events (gated on inbound-webhooks)
28
+ ## Phase 2 — Delivery events + opt-outs (gated on inbound-webhooks)
24
29
 
25
30
  - [ ] **Task 2.1**: Event Webhook route
26
- - Description: ECDSA signature verification via inbound-webhooks; delivered/bounce/dropped/open → `DeliveryEvent`
31
+ - Description: ECDSA signature verification via inbound-webhooks; event mapping per the IP table → `DeliveryEvent`; `x-message-id` prefix correlation
27
32
  - Files: `comms/src/adapters/sendgrid.ts`, webhook registration
28
33
  - Depends on: inbound-webhooks IP
29
- - Acceptance: signed fixture updates `CommsMessage.status`; unsigned rejected 401
34
+ - Acceptance: signed fixtures per event type update `CommsMessage.status` (+ `errorCode` for bounce/dropped); unsigned rejected 401
35
+ - [ ] **Task 2.2**: Opt-out events
36
+ - Description: `spamreport`/`unsubscribe`/`group_unsubscribe` → `OptOutEvent` → consumer `onOptOut`
37
+ - Files: `comms/src/adapters/sendgrid.ts` + tests
38
+ - Depends on: 2.1
39
+ - Acceptance: spamreport fixture fires `onOptOut`; subsequent `dropped` classified `permanent`
@@ -9,21 +9,31 @@ IP: [comms-adapter-twilio-sms](../implementationPlans/comms-adapter-twilio-sms.m
9
9
  - Files: `comms/src/adapters/twilioSms.ts`
10
10
  - Depends on: comms-abstraction Phase 1
11
11
  - Acceptance: mocked-client tests cover both sender configs
12
- - [ ] **Task 1.2**: E.164 validation + error mapping
13
- - Description: `libphonenumber-js` normalization; Twilio error codes into `SendResult.error` + metadata
12
+ - [ ] **Task 1.2**: E.164 validation + error classification
13
+ - Description: `libphonenumber-js` normalization; Twilio error-code → `errorCode`/`errorClass` map per the IP table (unknown codes → `transient`); full error payload into `CommsMessage.metadata`; Twilio SDK calls wrapped with `withApiErrorHandling`
14
14
  - Files: `comms/src/adapters/twilioSms.ts`
15
15
  - Depends on: 1.1
16
- - Acceptance: invalid number → 400 before API call; API failure → `accepted: false`
17
- - [ ] **Task 1.3**: Peer dep + example-backend registration + docs
16
+ - Acceptance: invalid number → 400 before API call; fixtures for at least one code per class (e.g. 21610 permanent, 20429 transient, 20003 config) assert `errorClass`; permanent failures skip the inline retry
17
+ - [ ] **Task 1.3**: Dashboard metadata + hooks coverage
18
+ - Description: `metadata.consoleUrl` deep link per message SID; `onError` fires with the classified `SendResult`
19
+ - Files: `comms/src/adapters/twilioSms.ts` + tests
20
+ - Depends on: 1.2
21
+ - Acceptance: failed-send test asserts consoleUrl and onError invocation
22
+ - [ ] **Task 1.4**: Peer dep + example-backend registration + docs
18
23
  - Description: optional peer `twilio`; env-gated registration; reference + env-var docs
19
24
  - Files: `comms/package.json`, `example-backend/src/server.ts`, `docs/reference/comms.md`, `docs/reference/environment-variables.md`
20
25
  - Depends on: 1.1
21
26
  - Acceptance: compile + boot without twilio installed when unconfigured
22
27
 
23
- ## Phase 2 — Delivery callbacks (gated on inbound-webhooks)
28
+ ## Phase 2 — Delivery callbacks + opt-outs (gated on inbound-webhooks)
24
29
 
25
30
  - [ ] **Task 2.1**: Status callback route
26
- - Description: webhook endpoint with Twilio signature verification via inbound-webhooks framework
31
+ - Description: webhook endpoint with Twilio signature verification via inbound-webhooks framework; status mapping per IP table incl. `ErrorCode` propagation
27
32
  - Files: `comms/src/adapters/twilioSms.ts`, webhook registration
28
33
  - Depends on: inbound-webhooks IP
29
- - Acceptance: signed payload updates `CommsMessage.status`; unsigned rejected 401
34
+ - Acceptance: signed payload updates `CommsMessage.status` (+ `errorCode` on failure); unsigned rejected 401
35
+ - [ ] **Task 2.2**: STOP/START opt-out handling
36
+ - Description: inbound keyword webhook → `OptOutEvent` → consumer `onOptOut`; opt-in (START) emitted symmetrically
37
+ - Files: `comms/src/adapters/twilioSms.ts`, webhook registration + tests
38
+ - Depends on: 2.1
39
+ - Acceptance: STOP fixture fires `onOptOut` with `reason: "sms-stop"`; 21610 on later sends classified `permanent`
@@ -7,11 +7,11 @@ IP: [comms-adapter-twilio-verify](../implementationPlans/comms-adapter-twilio-ve
7
7
  - Files: `comms/src/adapters/twilioVerify.ts`
8
8
  - Depends on: comms-abstraction Phase 1
9
9
  - Acceptance: mocked-client tests for approved/pending/expired/max-attempts
10
- - [ ] **Task 2**: Redacted logging
11
- - Description: `CommsMessage` rows with channel `verification`, last-4 destination, no codes
10
+ - [ ] **Task 2**: Redacted logging + error classification
11
+ - Description: `CommsMessage` rows with channel `verification`, fully redacted destination, no codes, and verification channel metadata on start; `errorCode`/`errorClass` mapping (rate-limit transient, expired/max-attempts permanent, bad SID config); rows flagged non-retryable; `onError` fires on failures
12
12
  - Files: `comms/src/adapters/twilioVerify.ts`
13
13
  - Depends on: Task 1
14
- - Acceptance: log assertion tests prove no code/full destination in any row
14
+ - Acceptance: log assertion tests prove no code/full destination in any row; failure fixtures assert class + onError
15
15
  - [ ] **Task 3**: Registration + docs
16
16
  - Description: env-gated example-backend registration; fail-fast on missing service SID; reference + env docs
17
17
  - Files: `example-backend/src/server.ts`, `docs/reference/comms.md`, `docs/reference/environment-variables.md`
@@ -0,0 +1,52 @@
1
+ # Tasks: Comms admin dashboard (errors, retries, log digging)
2
+
3
+ IP: [comms-admin-dashboard](../implementationPlans/comms-admin-dashboard.md)
4
+
5
+ ## Phase 1 — Backend routes
6
+
7
+ - [ ] **Task 1.1**: Upgrade explorer to `commsDashboard.ts` list + detail
8
+ - Description: rich filters (channel/provider/status/errorClass/errorCode/userId/to/templateId/dates/`q`), pagination, `GET /comms/messages/:id` with attempts + metadata + retained payload
9
+ - Files: `comms/src/routes/commsDashboard.ts` + supertest
10
+ - Depends on: comms-abstraction Phase 2 (incl. hooks/error-taxonomy additions)
11
+ - Acceptance: every filter covered by a supertest case; non-admin 403
12
+ - [ ] **Task 1.2**: `retryMessage` facade + retry route
13
+ - Description: retryability validation (status, errorClass, payload retention, channel configured, not verification), linked rows via `retriedFromId`/`retriedById`, hooks fire with `isRetry: true`, acting admin recorded
14
+ - Files: `comms/src/commsService.ts`, `comms/src/routes/commsDashboard.ts` + tests
15
+ - Depends on: 1.1
16
+ - Acceptance: each non-retryable reason returns 400 with its stable `code`; successful retry creates a linked row
17
+ - [ ] **Task 1.3**: `retryMany` + `/comms/stats`
18
+ - Description: bulk retry with cap + skipped reasons; aggregation by channel × provider × status with day buckets and failure rate
19
+ - Files: `comms/src/routes/commsDashboard.ts` + tests
20
+ - Depends on: 1.2
21
+ - Acceptance: stats counts match list totals for the same filter/range; cap enforced
22
+
23
+ ## Phase 2 — Admin screens
24
+
25
+ - [ ] **Task 2.1**: `CommsDashboardScreen`
26
+ - Description: stats cards, filter bar (URL-persisted), DataTable with status badges + inline retry
27
+ - Files: `admin-frontend/src/comms/CommsDashboardScreen.tsx`, `CommsStatusBadge.tsx`, `useCommsDashboardApi.tsx` + tests
28
+ - Depends on: 1.1, 1.3
29
+ - Acceptance: loading/error/empty states; filters round-trip through the URL
30
+ - [ ] **Task 2.2**: `CommsMessageDetail`
31
+ - Description: attempt timeline, provider console links, JSON viewer for payload/metadata, confirmed retry button with disabled-reason tooltips
32
+ - Files: `admin-frontend/src/comms/CommsMessageDetail.tsx` + tests
33
+ - Depends on: 1.2, 2.1
34
+ - Acceptance: non-retryable rows show the specific reason; retry navigates to the new row
35
+ - [ ] **Task 2.3**: Example app + admin-spa wiring
36
+ - Description: expo-router screens under `app/admin/comms/`, admin-spa nav entry, `bun run sdk`
37
+ - Files: `example-frontend/app/admin/comms/*`, `example-frontend/store/openApiSdk.ts`, admin-spa nav
38
+ - Depends on: 2.1, 2.2
39
+ - Acceptance: frontend verification in the running example app with screenshots on the PR
40
+
41
+ ## Phase 3 — Bulk retry UI + docs
42
+
43
+ - [ ] **Task 3.1**: "Retry all failed" flow
44
+ - Description: filtered bulk retry with count confirmation modal; skipped-reason summary toast
45
+ - Files: `admin-frontend/src/comms/CommsDashboardScreen.tsx` + tests
46
+ - Depends on: 1.3, 2.1
47
+ - Acceptance: confirmation shows the exact count; result summarizes retried/skipped
48
+ - [ ] **Task 3.2**: Docs + rules
49
+ - Description: dashboard section in comms reference, admin reference update, rulesync
50
+ - Files: `docs/reference/comms.md`, `docs/reference/admin.md`, `.rulesync/**`
51
+ - Depends on: 2.x
52
+ - Acceptance: `bun run rules:check` passes
@@ -0,0 +1,215 @@
1
+ # Task List: Migrate CI/CD to CircleCI
2
+
3
+ See: [`docs/implementationPlans/migrate-cicd-to-circleci.md`](../implementationPlans/migrate-cicd-to-circleci.md)
4
+ Research: [`docs/implementationPlans/migrate-cicd-to-circleci-research.md`](../implementationPlans/migrate-cicd-to-circleci-research.md)
5
+
6
+ ## Instructions for the implementing agent
7
+
8
+ - Dual-run every phase: CircleCI green → flip required checks → delete GHA twin. Never enable tag publish on both systems.
9
+ - Do not store plaintext GCP JSON keys in CircleCI if OIDC is available; migrate `preview-cleanup` off `GCP_SA_KEY`.
10
+ - Pin orb versions (including `circleci/node` with Bun support ≥7.2.0).
11
+ - Prefer path parameters that mirror existing GHA path filters.
12
+ - Update docs in the same PR that changes the source of truth for how CI runs.
13
+ - After Phase 0, confirm CircleCI project follows the GitHub default branch `master`.
14
+
15
+ ## Phase 0: Prerequisites
16
+
17
+ - [ ] **Task 0.1**: Confirm CircleCI org/plan and project link
18
+ - Description: Verify the requester-created CircleCI organization, plan, and that `FlourishHealth/terreno` is connected with permission to report GitHub checks. Enable **dynamic config** / setup workflows for the project. Record org slug + project slug in the IP header or how-to doc.
19
+ - Files: `docs/how-to/circleci.md` (stub OK)
20
+ - Depends on: none (human prerequisite)
21
+ - Acceptance: a manual “hello” pipeline can be triggered from the project; dynamic config is enabled.
22
+
23
+ - [ ] **Task 0.2**: Create CircleCI Contexts (empty shells)
24
+ - Description: Create contexts named in the IP (`terreno-npm`, `terreno-netlify`, `terreno-expo`, `terreno-gcp`, `terreno-e2e`, `terreno-release`, `terreno-agentic`, `terreno-github-api`). Document which GitHub secrets map into each. Do not paste secret values into the repo.
25
+ - Files: `docs/how-to/circleci.md`
26
+ - Depends on: Task 0.1
27
+ - Acceptance: contexts exist; mapping table is complete; access restrictions noted for `terreno-release`.
28
+
29
+ - [ ] **Task 0.3**: Inventory required GitHub checks
30
+ - Description: List current branch-protection required checks and map each to the GHA job `name:` and the future CircleCI job name. Start from `docs/explanation/repository-settings.md` and live settings.
31
+ - Files: `docs/how-to/circleci.md` or a short table in the IP
32
+ - Depends on: none
33
+ - Acceptance: table covers policies, rulesync, package CI, fingerprint, and CD-related checks.
34
+
35
+ ## Phase 1: Foundation
36
+
37
+ - [ ] **Task 1.1**: Add setup + continue config skeleton
38
+ - Description: Create `.circleci/config.yml` with `setup: true` using `circleci/path-filtering` (and `circleci/continuation`). Create `.circleci/continue-config.yml` with parameters for each package/area and a no-op `config-ok` job that always runs.
39
+ - Files: `.circleci/config.yml`, `.circleci/continue-config.yml`
40
+ - Depends on: Task 0.1
41
+ - Acceptance: push triggers setup → continuation; `config-ok` is green.
42
+
43
+ - [ ] **Task 1.2**: Shared Bun + cache commands
44
+ - Description: Add reusable commands (inline or orb) for installing Bun via `circleci/node`, `bun install --frozen-lockfile`, and cache keys equivalent to today’s GHA bun cache. Pin Bun policy (`latest` vs pin) consistently with EAS jobs that need a pin.
45
+ - Files: `.circleci/continue-config.yml`
46
+ - Depends on: Task 1.1
47
+ - Acceptance: a sample job restores cache on second run; install is frozen-lockfile.
48
+
49
+ - [ ] **Task 1.3**: Path-filter mapping
50
+ - Description: Encode path → parameter mapping for api, ai, ui, rtk, comms, mcp-server, admin-*, example-*, demo, docs/website, terraform, e2e-relevant sets, matching current workflow path filters.
51
+ - Files: `.circleci/config.yml`
52
+ - Depends on: Task 1.1
53
+ - Acceptance: a docs-only change sets docs/deploy params without setting `run-api`.
54
+
55
+ ## Phase 2: Package CI + policy
56
+
57
+ - [ ] **Task 2.1**: Port package CI jobs
58
+ - Description: Port api/ai/rtk/ui/ui-demo/comms/mcp-server/example-frontend/example-backend(+script)/admin-spa CI to CircleCI jobs gated by path params. Include Mongo service where GHA used it. Fix mcp branch filter to `master`.
59
+ - Files: `.circleci/continue-config.yml`, possibly package scripts unchanged
60
+ - Depends on: Task 1.2, Task 1.3
61
+ - Acceptance: dual-run green for each package on a change that touches it; GHA still required.
62
+
63
+ - [ ] **Task 2.2**: Port Docker build-only job
64
+ - Description: Port `example-backend-docker.yml` to CircleCI remote Docker / machine with layer caching replacement for `type=gha`.
65
+ - Files: `.circleci/continue-config.yml`
66
+ - Depends on: Task 2.1
67
+ - Acceptance: PR touching `example-backend/**` builds the image without pushing.
68
+
69
+ - [ ] **Task 2.3**: Port repo-policies + rulesync + DCO
70
+ - Description: Port `repo-policies.yml`, `rulesync-check.yml`, and fork DCO checks. DCO must use GitHub API via `terreno-github-api` context.
71
+ - Files: `.circleci/continue-config.yml`
72
+ - Depends on: Task 0.2, Task 1.2
73
+ - Acceptance: intentional barrel-import / dirty rulesync / missing DCO on a fork PR fails the CircleCI job.
74
+
75
+ - [ ] **Task 2.4**: Dual-run cutover for Phase 2
76
+ - Description: Add CircleCI checks to branch protection; remove GHA package/policy workflows once trusted; delete corresponding `.github/workflows/*-ci.yml` and policy workflows.
77
+ - Files: `.github/workflows/*`, `docs/explanation/repository-settings.md`
78
+ - Depends on: Task 2.1, Task 2.2, Task 2.3
79
+ - Acceptance: required checks are CircleCI-only for these surfaces; GHA files gone.
80
+
81
+ ## Phase 3: Playwright E2E
82
+
83
+ - [ ] **Task 3.1**: Port `e2e-ci` and `admin-spa-integration`
84
+ - Description: Mongo replica set, E2E secrets context, Playwright browsers, artifact store for reports. Skip Dependabot-equivalent if applicable.
85
+ - Files: `.circleci/continue-config.yml`
86
+ - Depends on: Task 2.1, Task 0.2
87
+ - Acceptance: matrix (or equivalent) passes on master; artifacts downloadable.
88
+
89
+ - [ ] **Task 3.2**: Dual-run cutover for E2E
90
+ - Description: Flip required checks if any; delete GHA e2e/admin-spa-integration workflows.
91
+ - Files: `.github/workflows/e2e-ci.yml`, `admin-spa-integration.yml`, `admin-spa-ci.yml` as applicable
92
+ - Depends on: Task 3.1
93
+ - Acceptance: GHA twins deleted; CircleCI owns e2e.
94
+
95
+ ## Phase 4: Netlify deploys
96
+
97
+ - [ ] **Task 4.1**: Port demo / frontend-example / docs Netlify workflows
98
+ - Description: Build + `netlify-cli` deploy prod/preview; preserve alias naming (`pr-N`); recreate GitHub Deployment statuses via API if still desired.
99
+ - Files: `.circleci/continue-config.yml`
100
+ - Depends on: Task 0.2, Task 1.3
101
+ - Acceptance: preview deploy URL posted or visible; prod deploy on master path filter.
102
+
103
+ - [ ] **Task 4.2**: Preview cleanup port
104
+ - Description: On PR close, clean Netlify/GCP preview resources from CircleCI (webhook or GitHub App → pipeline). Prefer OIDC over `GCP_SA_KEY`.
105
+ - Files: `.circleci/continue-config.yml`
106
+ - Depends on: Task 4.1
107
+ - Acceptance: closing a PR removes preview resources; no orphaned Cloud Run `pr-N` services in a test PR.
108
+
109
+ - [ ] **Task 4.3**: Dual-run cutover for Netlify
110
+ - Description: Delete GHA deploy workflows after CircleCI trusted.
111
+ - Files: `.github/workflows/demo-deploy.yml`, `frontend-example-deploy.yml`, `docs-deploy.yml`, `preview-cleanup.yml`
112
+ - Depends on: Task 4.1, Task 4.2
113
+ - Acceptance: GHA deploy twins deleted.
114
+
115
+ ## Phase 5: EAS + fingerprint
116
+
117
+ - [ ] **Task 5.1**: Relocate CI scripts
118
+ - Description: Move EAS/fingerprint shell scripts from `.github/workflows/scripts/` to `scripts/ci/` (or `.circleci/scripts/`) and update callers.
119
+ - Files: `scripts/ci/*`, old script paths
120
+ - Depends on: none
121
+ - Acceptance: scripts runnable locally with documented env; no broken references.
122
+
123
+ - [ ] **Task 5.2**: Port eas-pr, eas-dev-build, fingerprint-gate
124
+ - Description: CircleCI jobs using `EXPO_TOKEN`; PR comments and label gate via GitHub API; manual pipeline for eas-dev-build.
125
+ - Files: `.circleci/continue-config.yml`
126
+ - Depends on: Task 5.1, Task 0.2
127
+ - Acceptance: fingerprint change fails until `fingerprint-acknowledged`; EAS update/build path works on a test PR.
128
+
129
+ - [ ] **Task 5.3**: Dual-run cutover for EAS
130
+ - Description: Delete GHA eas/fingerprint workflows after trust.
131
+ - Files: `.github/workflows/eas-pr.yml`, `eas-dev-build.yml`, `fingerprint-gate.yml`
132
+ - Depends on: Task 5.2
133
+ - Acceptance: GHA twins deleted; CircleCI checks required where fingerprint was required.
134
+
135
+ ## Phase 6: GCP CD + OIDC
136
+
137
+ - [ ] **Task 6.1**: Add CircleCI OIDC provider in terraform
138
+ - Description: Extend or add module so GCP trusts CircleCI OIDC alongside GitHub during dual-run. Wire terreno terraform root; document outputs for CircleCI project settings.
139
+ - Files: `terraform/modules/**`, terreno/Flourish terraform roots, `terraform/README.md`
140
+ - Depends on: Task 0.1
141
+ - Acceptance: `gcloud` auth from a CircleCI job succeeds with WIF (no JSON key).
142
+
143
+ - [ ] **Task 6.2**: Port `cd.yml`
144
+ - Description: Path-filtered terraform fmt/preview/apply + Docker build/push + Cloud Run deploys + mcp-test/deploy. Preserve concurrency semantics (do not cancel in-flight prod applies).
145
+ - Files: `.circleci/continue-config.yml`
146
+ - Depends on: Task 6.1
147
+ - Acceptance: terraform preview on PR; apply+deploy on master for a safe test path; GitHub Deployment records optional but documented.
148
+
149
+ - [ ] **Task 6.3**: Dual-run cutover for CD
150
+ - 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).
151
+ - Files: `.github/workflows/cd.yml`, terraform OIDC
152
+ - Depends on: Task 6.2
153
+ - Acceptance: only CircleCI performs terreno CD; no double apply.
154
+
155
+ ## Phase 7: npm publish
156
+
157
+ - [ ] **Task 7.1**: Port publish-on-tag + manual feature-flags publish
158
+ - Description: Reproduce package publish graph, upgrade-docs gate, version bump, Zoom notify, demo dispatch, docs version cut. Use `terreno-release` + `terreno-npm` contexts.
159
+ - Files: `.circleci/continue-config.yml`
160
+ - Depends on: Task 0.2, Task 2.1
161
+ - Acceptance: dry-run or package-by-package rehearsal documented; Zoom path tested against a sandbox webhook if available.
162
+
163
+ - [ ] **Task 7.2**: Single-writer tag cutover
164
+ - Description: In one coordinated change: enable CircleCI tag pipeline; delete/disable `.github/workflows/publish-on-tag.yml` and manual GHA publish; verify no double publish.
165
+ - Files: `.github/workflows/publish-on-tag.yml`, `publish-feature-flags-manual.yml`
166
+ - Depends on: Task 7.1
167
+ - Acceptance: next tag publishes once from CircleCI only.
168
+
169
+ ## Phase 8: Mobile (post-v1, required for CC1)
170
+
171
+ - [ ] **Task 8.1**: Port Maestro + Appium Android
172
+ - Description: Port `maestro-e2e` and Android half of `demo-appium-ci` to CircleCI Linux VM with emulator strategy documented.
173
+ - Files: `.circleci/continue-config.yml`
174
+ - Depends on: Task 5.2
175
+ - Acceptance: manual pipeline runs Android Appium and Maestro successfully.
176
+
177
+ - [ ] **Task 8.2**: Port Appium iOS on CircleCI macOS
178
+ - Description: Select macOS resource class/image with Working WDA; port iOS job; compare flake rate to GHA `macos-15`.
179
+ - Files: `.circleci/continue-config.yml`
180
+ - Depends on: Task 8.1
181
+ - Acceptance: iOS Appium green on a representative run; then delete GHA Appium workflow.
182
+
183
+ ## Phase 9: GitHub-native + agentic replacements
184
+
185
+ - [ ] **Task 9.1**: Replace CodeQL workflow
186
+ - Description: Implement SARIF upload to GitHub Code Scanning from CircleCI or an approved SAST substitute; delete `codeql-analysis.yml` only when coverage is accepted.
187
+ - Files: `.circleci/continue-config.yml`, `.github/workflows/codeql-analysis.yml`
188
+ - Depends on: Task 0.2
189
+ - Acceptance: Security tab still receives results **or** explicit maintainer sign-off on alternative.
190
+
191
+ - [ ] **Task 9.2**: Replace Dependabot auto-merge + triage + roadmap-generate + docs-audit
192
+ - Description: Implement CircleCI (or Renovate) equivalents; wire issue/schedule triggers without leaving required logic on GHA.
193
+ - Files: `.circleci/continue-config.yml`, corresponding GHA deletions
194
+ - Depends on: Task 0.2
195
+ - Acceptance: each former workflow’s acceptance behavior has an owner on CircleCI; GHA files deleted.
196
+
197
+ - [ ] **Task 9.3**: Replace architectural review + gh-aw agentics
198
+ - Description: Per lockfile (`update-rules`, `update-docs`, daily improvers) and `architectural-pr-review` / `agentics-maintenance`: either port to CircleCI scheduled/PR pipelines with the same scripts or **retire** with maintainer sign-off. CC1 forbids leaving them on GHA.
199
+ - Files: `.github/workflows/*lock*`, `architectural-pr-review.yml`, `agentics-maintenance.yml`, `.circleci/continue-config.yml`
200
+ - Depends on: Task 0.2
201
+ - Acceptance: written retire-or-port decision for each; no gh-aw workflows remain if ported/retired.
202
+
203
+ ## Phase 10: Cleanup
204
+
205
+ - [ ] **Task 10.1**: Docs sweep
206
+ - Description: Update CONTRIBUTING, repository-settings, terraform README, deploy guides, AGENTS/Cursor Cloud CI notes to CircleCI-first. Remove stale GHA instructions.
207
+ - Files: `docs/**`, `CONTRIBUTING.md`, `AGENTS.md` / rules as needed
208
+ - Depends on: Phases 2–7 at minimum; 8–9 for full CC1
209
+ - Acceptance: `rg -n "GitHub Actions" docs/explanation/repository-settings.md` and deploy docs reflect CircleCI as source of truth.
210
+
211
+ - [ ] **Task 10.2**: Final GHA workflow purge + IP close
212
+ - Description: Ensure `.github/workflows` has no CI/CD yml left (except intentionally empty dir or README). Update `PLAN_INDEX.md`; archive IP when Complete.
213
+ - Files: `.github/workflows/`, `docs/implementationPlans/PLAN_INDEX.md`
214
+ - Depends on: Task 9.3, Task 10.1, Task 8.2
215
+ - Acceptance: `ls .github/workflows/*.yml` is empty (or only an agreed stub); IP status Complete.