@terreno/mcp 57.0.0 → 57.1.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.
- package/dist/bootstrap.d.ts +1 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +381 -191
- package/dist/bootstrap.js.map +1 -1
- package/dist/docs/guidelines/api/skills/mongoose-schema-safety/SKILL.md +8 -0
- package/dist/docs/resources/overview.md +6 -1
- package/dist/docs/resources/rtk.md +3 -1
- package/dist/docs/resources/syncdb.md +43 -0
- package/dist/docs/upgrades/56.0.0-beta.2.md +34 -0
- package/dist/docs/upgrades/57.1.0.md +126 -0
- package/dist/docs/versioned/next/README.md +15 -3
- package/dist/docs/versioned/next/explanation/README.md +3 -0
- package/dist/docs/versioned/next/explanation/admin-consent-migration.md +15 -0
- package/dist/docs/versioned/next/explanation/admin-plugin-frontend.md +12 -0
- package/dist/docs/versioned/next/explanation/announcements/rtk-deprecation.md +29 -0
- package/dist/docs/versioned/next/explanation/authentication.md +51 -58
- package/dist/docs/versioned/next/explanation/local-first-data.md +52 -0
- package/dist/docs/versioned/next/explanation/loop-engineering.md +117 -0
- package/dist/docs/versioned/next/explanation/repository-settings.md +8 -0
- package/dist/docs/versioned/next/explanation/roadmap-process.md +22 -9
- package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +39 -0
- package/dist/docs/versioned/next/how-to/README.md +3 -0
- package/dist/docs/versioned/next/how-to/admin-add-model.md +41 -0
- package/dist/docs/versioned/next/how-to/admin-custom-home.md +31 -0
- package/dist/docs/versioned/next/how-to/admin-custom-widget.md +42 -0
- package/dist/docs/versioned/next/how-to/admin-import-prebuilt.md +25 -0
- package/dist/docs/versioned/next/how-to/circleci.md +173 -0
- package/dist/docs/versioned/next/how-to/configure-better-auth.md +13 -10
- package/dist/docs/versioned/next/how-to/expose-mcp-tools.md +194 -0
- package/dist/docs/versioned/next/how-to/install-agent-skills.md +46 -0
- package/dist/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +26 -1
- package/dist/docs/versioned/next/how-to/websocket-integration.md +2 -1
- package/dist/docs/versioned/next/implementationPlans/ModularAPI.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/README.md +31 -17
- package/dist/docs/versioned/next/implementationPlans/admin-improvements-research.md +136 -0
- package/dist/docs/versioned/next/implementationPlans/admin-improvements.md +157 -527
- package/dist/docs/versioned/next/implementationPlans/admin-only-research.md +4 -0
- package/dist/docs/versioned/next/implementationPlans/admin-only.md +3 -1
- package/dist/docs/versioned/next/implementationPlans/admin-script-runner.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/admin-ui-v2-django-parity.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +160 -130
- package/dist/docs/versioned/next/implementationPlans/apierror-standard-error-redesign.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/b2b-platform-program.md +5 -4
- package/dist/docs/versioned/next/implementationPlans/comms-abstraction-research.md +48 -0
- package/dist/docs/versioned/next/implementationPlans/comms-abstraction.md +152 -62
- package/dist/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +9 -9
- package/dist/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +1 -1
- package/dist/docs/versioned/next/implementationPlans/consent-forms.md +4 -0
- package/dist/docs/versioned/next/implementationPlans/design-blend-skill.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/docs-site-and-versioning.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/feature-flags-openfeature.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/feature-flags.md +4 -0
- package/dist/docs/versioned/next/implementationPlans/infra-mcp-research.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/infra-mcp.md +3 -3
- package/dist/docs/versioned/next/implementationPlans/mcp-boost-parity.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci-research.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +2 -2
- package/dist/docs/versioned/next/implementationPlans/model-router-actions.md +4 -0
- package/dist/docs/versioned/next/implementationPlans/model-router-mcp.md +5 -4
- package/dist/docs/versioned/next/implementationPlans/offline-mode.md +3 -1
- package/dist/docs/versioned/next/implementationPlans/oss-launch-program.md +11 -2
- package/dist/docs/versioned/next/implementationPlans/pluggable-database-sqlite-research.md +150 -0
- package/dist/docs/versioned/next/implementationPlans/pluggable-database-sqlite.md +247 -0
- package/dist/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +1 -1
- package/dist/docs/versioned/next/implementationPlans/public-roadmap-github.md +2 -2
- package/dist/docs/versioned/next/implementationPlans/rbac-permissions.md +52 -15
- package/dist/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +13 -12
- package/dist/docs/versioned/next/implementationPlans/syncdb-codegen-research.md +137 -0
- package/dist/docs/versioned/next/implementationPlans/syncdb-codegen.md +63 -59
- package/dist/docs/versioned/next/implementationPlans/syncdb-local-first.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/terreno-langfuse-integration.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/upgrade-banner.md +4 -0
- package/dist/docs/versioned/next/reference/README.md +6 -1
- package/dist/docs/versioned/next/reference/admin-config.md +51 -0
- package/dist/docs/versioned/next/reference/ai.md +15 -1
- package/dist/docs/versioned/next/reference/api.md +18 -0
- package/dist/docs/versioned/next/reference/comms.md +88 -7
- package/dist/docs/versioned/next/reference/environment-variables.md +9 -1
- package/dist/docs/versioned/next/reference/{rtk.md → legacy/rtk.md} +11 -7
- package/dist/docs/versioned/next/reference/lifecycle-plugin.md +54 -0
- package/dist/docs/versioned/next/reference/mcp-server.md +7 -0
- package/dist/docs/versioned/next/reference/syncdb.md +30 -3
- package/dist/docs/versioned/next/tasks/README.md +21 -10
- package/dist/docs/versioned/next/tasks/admin-improvements.md +189 -353
- package/dist/docs/versioned/next/tasks/admin-only.md +2 -0
- package/dist/docs/versioned/next/tasks/agentic-sdlc-plugin.md +54 -160
- package/dist/docs/versioned/next/tasks/comms-abstraction.md +30 -24
- package/dist/docs/versioned/next/tasks/comms-adapter-sendgrid.md +4 -4
- package/dist/docs/versioned/next/tasks/consent-forms.md +2 -0
- package/dist/docs/versioned/next/tasks/feature-flags.md +2 -0
- package/dist/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +14 -10
- package/dist/docs/versioned/next/tasks/model-router-actions.md +2 -0
- package/dist/docs/versioned/next/tasks/model-router-mcp.md +27 -27
- package/dist/docs/versioned/next/tasks/offline-mode.md +2 -0
- package/dist/docs/versioned/next/tasks/pluggable-database-sqlite.md +44 -0
- package/dist/docs/versioned/next/tasks/public-roadmap-github.md +1 -1
- package/dist/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +15 -15
- package/dist/docs/versioned/next/tasks/syncdb-codegen.md +37 -31
- package/dist/docs/versioned/next/tasks/upgrade-banner.md +2 -0
- package/dist/index.js +24 -55
- package/dist/index.js.map +1 -1
- package/dist/local/localServer.d.ts.map +1 -1
- package/dist/local/localServer.js +9 -8
- package/dist/local/localServer.js.map +1 -1
- package/dist/local/localTools.d.ts +1 -1
- package/dist/local/localTools.d.ts.map +1 -1
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +44 -45
- package/dist/prompts.js.map +1 -1
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +9 -2
- package/dist/resources.js.map +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +4 -2
- package/dist/tools.js.map +1 -1
- package/package.json +7 -3
- package/src/docs/guidelines/api/skills/mongoose-schema-safety/SKILL.md +8 -0
- package/src/docs/resources/overview.md +6 -1
- package/src/docs/resources/rtk.md +3 -1
- package/src/docs/resources/syncdb.md +43 -0
- package/src/docs/upgrades/56.0.0-beta.2.md +34 -0
- package/src/docs/upgrades/57.1.0.md +126 -0
- package/src/docs/versioned/next/README.md +15 -3
- package/src/docs/versioned/next/explanation/README.md +3 -0
- package/src/docs/versioned/next/explanation/admin-consent-migration.md +15 -0
- package/src/docs/versioned/next/explanation/admin-plugin-frontend.md +12 -0
- package/src/docs/versioned/next/explanation/announcements/rtk-deprecation.md +29 -0
- package/src/docs/versioned/next/explanation/authentication.md +51 -58
- package/src/docs/versioned/next/explanation/local-first-data.md +52 -0
- package/src/docs/versioned/next/explanation/loop-engineering.md +117 -0
- package/src/docs/versioned/next/explanation/repository-settings.md +8 -0
- package/src/docs/versioned/next/explanation/roadmap-process.md +22 -9
- package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +39 -0
- package/src/docs/versioned/next/how-to/README.md +3 -0
- package/src/docs/versioned/next/how-to/admin-add-model.md +41 -0
- package/src/docs/versioned/next/how-to/admin-custom-home.md +31 -0
- package/src/docs/versioned/next/how-to/admin-custom-widget.md +42 -0
- package/src/docs/versioned/next/how-to/admin-import-prebuilt.md +25 -0
- package/src/docs/versioned/next/how-to/circleci.md +173 -0
- package/src/docs/versioned/next/how-to/configure-better-auth.md +13 -10
- package/src/docs/versioned/next/how-to/expose-mcp-tools.md +194 -0
- package/src/docs/versioned/next/how-to/install-agent-skills.md +46 -0
- package/src/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +26 -1
- package/src/docs/versioned/next/how-to/websocket-integration.md +2 -1
- package/src/docs/versioned/next/implementationPlans/ModularAPI.md +1 -0
- package/src/docs/versioned/next/implementationPlans/README.md +31 -17
- package/src/docs/versioned/next/implementationPlans/admin-improvements-research.md +136 -0
- package/src/docs/versioned/next/implementationPlans/admin-improvements.md +157 -527
- package/src/docs/versioned/next/implementationPlans/admin-only-research.md +4 -0
- package/src/docs/versioned/next/implementationPlans/admin-only.md +3 -1
- package/src/docs/versioned/next/implementationPlans/admin-script-runner.md +1 -0
- package/src/docs/versioned/next/implementationPlans/admin-ui-v2-django-parity.md +1 -0
- package/src/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +160 -130
- package/src/docs/versioned/next/implementationPlans/apierror-standard-error-redesign.md +1 -0
- package/src/docs/versioned/next/implementationPlans/b2b-platform-program.md +5 -4
- package/src/docs/versioned/next/implementationPlans/comms-abstraction-research.md +48 -0
- package/src/docs/versioned/next/implementationPlans/comms-abstraction.md +152 -62
- package/src/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +9 -9
- package/src/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +1 -1
- package/src/docs/versioned/next/implementationPlans/consent-forms.md +4 -0
- package/src/docs/versioned/next/implementationPlans/design-blend-skill.md +1 -0
- package/src/docs/versioned/next/implementationPlans/docs-site-and-versioning.md +1 -0
- package/src/docs/versioned/next/implementationPlans/feature-flags-openfeature.md +1 -0
- package/src/docs/versioned/next/implementationPlans/feature-flags.md +4 -0
- package/src/docs/versioned/next/implementationPlans/infra-mcp-research.md +1 -0
- package/src/docs/versioned/next/implementationPlans/infra-mcp.md +3 -3
- package/src/docs/versioned/next/implementationPlans/mcp-boost-parity.md +1 -0
- package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci-research.md +1 -0
- package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +2 -2
- package/src/docs/versioned/next/implementationPlans/model-router-actions.md +4 -0
- package/src/docs/versioned/next/implementationPlans/model-router-mcp.md +5 -4
- package/src/docs/versioned/next/implementationPlans/offline-mode.md +3 -1
- package/src/docs/versioned/next/implementationPlans/oss-launch-program.md +11 -2
- package/src/docs/versioned/next/implementationPlans/pluggable-database-sqlite-research.md +150 -0
- package/src/docs/versioned/next/implementationPlans/pluggable-database-sqlite.md +247 -0
- package/src/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +1 -1
- package/src/docs/versioned/next/implementationPlans/public-roadmap-github.md +2 -2
- package/src/docs/versioned/next/implementationPlans/rbac-permissions.md +52 -15
- package/src/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +13 -12
- package/src/docs/versioned/next/implementationPlans/syncdb-codegen-research.md +137 -0
- package/src/docs/versioned/next/implementationPlans/syncdb-codegen.md +63 -59
- package/src/docs/versioned/next/implementationPlans/syncdb-local-first.md +1 -0
- package/src/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +1 -0
- package/src/docs/versioned/next/implementationPlans/terreno-langfuse-integration.md +1 -0
- package/src/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +1 -0
- package/src/docs/versioned/next/implementationPlans/upgrade-banner.md +4 -0
- package/src/docs/versioned/next/reference/README.md +6 -1
- package/src/docs/versioned/next/reference/admin-config.md +51 -0
- package/src/docs/versioned/next/reference/ai.md +15 -1
- package/src/docs/versioned/next/reference/api.md +18 -0
- package/src/docs/versioned/next/reference/comms.md +88 -7
- package/src/docs/versioned/next/reference/environment-variables.md +9 -1
- package/src/docs/versioned/next/reference/{rtk.md → legacy/rtk.md} +11 -7
- package/src/docs/versioned/next/reference/lifecycle-plugin.md +54 -0
- package/src/docs/versioned/next/reference/mcp-server.md +7 -0
- package/src/docs/versioned/next/reference/syncdb.md +30 -3
- package/src/docs/versioned/next/tasks/README.md +21 -10
- package/src/docs/versioned/next/tasks/admin-improvements.md +189 -353
- package/src/docs/versioned/next/tasks/admin-only.md +2 -0
- package/src/docs/versioned/next/tasks/agentic-sdlc-plugin.md +54 -160
- package/src/docs/versioned/next/tasks/comms-abstraction.md +30 -24
- package/src/docs/versioned/next/tasks/comms-adapter-sendgrid.md +4 -4
- package/src/docs/versioned/next/tasks/consent-forms.md +2 -0
- package/src/docs/versioned/next/tasks/feature-flags.md +2 -0
- package/src/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +14 -10
- package/src/docs/versioned/next/tasks/model-router-actions.md +2 -0
- package/src/docs/versioned/next/tasks/model-router-mcp.md +27 -27
- package/src/docs/versioned/next/tasks/offline-mode.md +2 -0
- package/src/docs/versioned/next/tasks/pluggable-database-sqlite.md +44 -0
- package/src/docs/versioned/next/tasks/public-roadmap-github.md +1 -1
- package/src/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +15 -15
- package/src/docs/versioned/next/tasks/syncdb-codegen.md +37 -31
- package/src/docs/versioned/next/tasks/upgrade-banner.md +2 -0
- package/dist/docs/versioned/next/implementationPlans/PLAN_INDEX.md +0 -73
- package/dist/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +0 -303
- package/src/docs/versioned/next/implementationPlans/PLAN_INDEX.md +0 -73
- package/src/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +0 -303
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Local-first data in Terreno
|
|
2
|
+
|
|
3
|
+
Terreno's default frontend data path is **local-first**: the on-device store is what your UI reads and writes, and the server reconciles changes asynchronously. This is a different mental model from request/response fetching with RTK Query.
|
|
4
|
+
|
|
5
|
+
## What local-first means here
|
|
6
|
+
|
|
7
|
+
In `@terreno/syncdb`, a TinyBase `MergeableStore` on the device is the **UI source of truth**. When a user taps "save," the mutation applies to local state immediately and lands in a durable outbox. The client then pushes the change to `@terreno/api` over the sync protocol (socket deltas with HTTP snapshot catch-up). The server remains the **authority** for permissions, validation, and conflict resolution — but the UI does not wait on the network for every write.
|
|
8
|
+
|
|
9
|
+
There is no server-first mode and no opt-in flag: if you use syncdb, you adopt this model for every synced collection.
|
|
10
|
+
|
|
11
|
+
## Mental model shift
|
|
12
|
+
|
|
13
|
+
| Server-first (RTK Query) | Local-first (syncdb) |
|
|
14
|
+
|--------------------------|----------------------|
|
|
15
|
+
| UI reads from cache filled by HTTP | UI reads from the local store |
|
|
16
|
+
| Writes call the API, then invalidate/refetch | Writes apply locally, then reconcile |
|
|
17
|
+
| Loading spinners track request lifecycle | Sync status tracks outbox + connectivity |
|
|
18
|
+
| Optimistic updates are manual and fragile | Optimistic state is the default path |
|
|
19
|
+
| Conflicts are rare / ignored | Conflicts are explicit and must be resolved |
|
|
20
|
+
|
|
21
|
+
Think **apply locally, then reconcile** instead of **request, wait, update cache**.
|
|
22
|
+
|
|
23
|
+
## What you stop doing
|
|
24
|
+
|
|
25
|
+
1. **Manual optimistic updates** — `onQueryStarted` patches, temporary IDs, and rollback logic for writes.
|
|
26
|
+
2. **Write-level loading spinners** — `isLoading` on mutations for "saving…" UX; the row updates instantly.
|
|
27
|
+
3. **Refetch orchestration** — `invalidatesTags`, `refetch()`, and list/detail cache coordination after mutations.
|
|
28
|
+
4. **Treating the network as the read path** — list screens blocked on `isLoading` for every navigation.
|
|
29
|
+
|
|
30
|
+
RTK Query remains appropriate for **non-synced** endpoints: `/auth/me`, admin RPC, AI routes, and anything that should stay request/response.
|
|
31
|
+
|
|
32
|
+
## What you start doing
|
|
33
|
+
|
|
34
|
+
1. **Conflict resolution UI** — When the server rejects a mutation (409 / `sync:nack`), the user must choose a strategy (`useServer` or `keepMine`). Use `ConflictSheet` from `@terreno/ui` or build your own with `useConflicts`.
|
|
35
|
+
2. **Sync-status UX** — Surface offline state, queued mutations, and drain progress with `useSyncStatus` (and optionally `SyncStatusBanner`).
|
|
36
|
+
3. **Encryption at rest (web)** — Web persistence uses AES-GCM via the default `createServerKeyProvider`; understand key fetch and `onDecryptFailure` for support flows.
|
|
37
|
+
4. **Key lifecycle on logout** — Call `syncDb.stop()` and consider `wipeLocalData` when the authenticated user changes so one account does not read another's local store.
|
|
38
|
+
5. **Backend sync registration** — Every synced collection needs `syncPlugin`, `isDeletedPlugin`, and a `sync` block on `modelRouter`, plus `SyncApp` and `RealtimeApp` on the server.
|
|
39
|
+
|
|
40
|
+
## Tradeoffs
|
|
41
|
+
|
|
42
|
+
**Gains:** instant UI, offline writes with a durable outbox, simpler screen code, and one write path on the server (sync and REST share `modelRouter`).
|
|
43
|
+
|
|
44
|
+
**Costs:** larger conceptual surface (conflicts, sync status, local storage), mandatory replica-set MongoDB for realtime, and migration work for existing RTK Query screens.
|
|
45
|
+
|
|
46
|
+
Server-first fetching is simpler when you only need online CRUD with no offline requirement — but Terreno's blessed path for collection data is local-first.
|
|
47
|
+
|
|
48
|
+
## Related docs
|
|
49
|
+
|
|
50
|
+
- [syncdb reference](../reference/syncdb.md) — API ground truth
|
|
51
|
+
- [Migrate from RTK to syncdb](../how-to/migrate-rtk-to-syncdb.md) — step-by-step migration
|
|
52
|
+
- [Authentication architecture](authentication.md) — Better Auth + socket sessions
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Loop engineering
|
|
2
|
+
|
|
3
|
+
Terreno separates engineering method from orchestration:
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
LOOP
|
|
7
|
+
orchestrate / persist / wait
|
|
8
|
+
retry / stop / escalate
|
|
9
|
+
|
|
|
10
|
+
v
|
|
11
|
+
GROW
|
|
12
|
+
shape
|
|
13
|
+
|
|
|
14
|
+
v
|
|
15
|
+
PICK
|
|
16
|
+
build
|
|
17
|
+
|
|
|
18
|
+
v
|
|
19
|
+
ROAST
|
|
20
|
+
prove
|
|
21
|
+
|
|
|
22
|
+
v
|
|
23
|
+
BREW
|
|
24
|
+
submit
|
|
25
|
+
|
|
|
26
|
+
v
|
|
27
|
+
TASTE
|
|
28
|
+
react once
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Repository knowledge composes underneath every invocation:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
lifecycle stage + project skills + IP/task/state + evidence
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Why fresh invocations
|
|
38
|
+
|
|
39
|
+
One enormous agent context accumulates assumptions, stale external state, and confidence
|
|
40
|
+
in its own implementation. The lifecycle instead makes every stage reconstructable from
|
|
41
|
+
durable artifacts. Pick can retry from exact Roast evidence; Roast can verify without the
|
|
42
|
+
implementer's assumptions; Taste can react to the current PR head rather than an old
|
|
43
|
+
green result.
|
|
44
|
+
|
|
45
|
+
The outer loop decides **when, who, what next, when to retry, when to wait, and when to
|
|
46
|
+
escalate**. Stages decide how to perform one transition correctly.
|
|
47
|
+
|
|
48
|
+
## The five transitions
|
|
49
|
+
|
|
50
|
+
| Stage | Question | Primary evidence |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| Grow | Is the work shaped and approved? | IP/tasks, decisions, criterion→verification map |
|
|
53
|
+
| Pick | Was this slice implemented carefully? | red/green tests, checks, internal reviews |
|
|
54
|
+
| Roast | Does the result actually satisfy the IP? | independent requirement→evidence verdict |
|
|
55
|
+
| Brew | Is the verified result correctly submitted? | final checks, commit/head, PR, artifacts |
|
|
56
|
+
| Taste | What is actionable on the current PR head now? | CI, mergeability, reviews, bounded fixes |
|
|
57
|
+
|
|
58
|
+
Roast is not another implementation review. It independently proves or disproves
|
|
59
|
+
acceptance criteria. Taste is not a resident watcher. It observes once, acts once, emits
|
|
60
|
+
`PASS`, `FAIL`, `BLOCKED`, or `PENDING`, then exits.
|
|
61
|
+
|
|
62
|
+
## Portable plugin, local knowledge
|
|
63
|
+
|
|
64
|
+
The reusable plugin defines contracts, invariants, evidence, and transitions. Repo-local
|
|
65
|
+
skills define exact API/UI/database patterns, commands, test environments, generated
|
|
66
|
+
code, deployment, and safety rules.
|
|
67
|
+
|
|
68
|
+
Each stage inspects available skills and loads those whose descriptions match the
|
|
69
|
+
affected domain. A useful skill is optional when absent; a capability required by
|
|
70
|
+
repository policy is a hard gate and produces `BLOCKED` if unavailable.
|
|
71
|
+
|
|
72
|
+
Stages also load architecture docs before acting. Docs are the design; code implements
|
|
73
|
+
them. Missing docs for a user-visible or architectural change is `FAIL`.
|
|
74
|
+
|
|
75
|
+
This lets the same Pick method compose with backend API and test-environment knowledge,
|
|
76
|
+
while Roast composes with UI conventions and real-app verification.
|
|
77
|
+
|
|
78
|
+
### Terreno's current project-skill layer
|
|
79
|
+
|
|
80
|
+
The canonical sources remain under `.rulesync/skills/` and are generated for supported
|
|
81
|
+
agents. The current high-value composition points include:
|
|
82
|
+
|
|
83
|
+
| Domain | Repo-local skills stages may discover |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| Backend/API/data | `terreno-backend-api`, `mongoose-schema-safety`, `backend-test-env`, `generate-sdk`, `terreno-data-fetching` |
|
|
86
|
+
| UI/app | `terreno-ui`, `building-terreno-apps`, `building-native-ui`, `verify-ui-changes` |
|
|
87
|
+
| AI/prompts | `ai-prompt-governance` |
|
|
88
|
+
| Docs/submission | `update-docs`, `commit`, `create-pr`, `fix-conflicts` |
|
|
89
|
+
| Deployment/runtime | `deploy-gcp`, Expo deployment/workflow skills |
|
|
90
|
+
|
|
91
|
+
This inventory is descriptive, not a plugin dependency list. Stages inspect the actual
|
|
92
|
+
catalog on every invocation.
|
|
93
|
+
|
|
94
|
+
## State and evidence
|
|
95
|
+
|
|
96
|
+
The IP remains the design/scope source of truth. The task file remains the execution
|
|
97
|
+
checklist. Lightweight loop-owned state stores only current stage/attempt/task,
|
|
98
|
+
branch/head/PR, the previous structured result, artifacts, attempted approaches, and next
|
|
99
|
+
transition.
|
|
100
|
+
|
|
101
|
+
The fallback state location is `.terreno/pipeline/<slug>.json`; the outer loop preserves
|
|
102
|
+
or transports it and Brew excludes it from commits unless repository policy says
|
|
103
|
+
otherwise. Stage results follow the plugin's JSON-schema-backed YAML contract and never
|
|
104
|
+
contain chain-of-thought or transcripts.
|
|
105
|
+
|
|
106
|
+
## Retry and stop rules
|
|
107
|
+
|
|
108
|
+
- Roast failure returns exact expected/actual evidence to a fresh Pick.
|
|
109
|
+
- Engineering retries require a new hypothesis and preserve failed approaches.
|
|
110
|
+
- Taste `PENDING` lets the outer loop wait and invoke fresh Taste against current state.
|
|
111
|
+
- Human decisions are `BLOCKED`, never arbitrary retries.
|
|
112
|
+
- Taste `PASS` requires all current-head checks terminal/non-failing, no conflicts, and
|
|
113
|
+
no actionable review findings.
|
|
114
|
+
|
|
115
|
+
The detailed contract, schemas, and three execution scenarios live under
|
|
116
|
+
[`plugins/terreno-planning/references/`](https://github.com/FlourishHealth/terreno/tree/master/plugins/terreno-planning/references).
|
|
117
|
+
|
|
@@ -36,6 +36,14 @@ descriptions):
|
|
|
36
36
|
- Require branches to be up to date before merging
|
|
37
37
|
- Do not allow bypassing the above settings
|
|
38
38
|
|
|
39
|
+
### CircleCI dual-run (in progress)
|
|
40
|
+
|
|
41
|
+
Package CI / policy / Playwright twins live under `.circleci/` (see
|
|
42
|
+
[how-to/circleci.md](../how-to/circleci.md)). **Keep requiring the existing GitHub
|
|
43
|
+
Actions check names** until a twin is trusted; then add the CircleCI job name and
|
|
44
|
+
remove the GHA workflow. Do not require CircleCI deploy jobs yet (deploys not
|
|
45
|
+
ported).
|
|
46
|
+
|
|
39
47
|
## Merge settings
|
|
40
48
|
|
|
41
49
|
**Path:** Settings → General → Pull Requests
|
|
@@ -22,10 +22,10 @@ Discussion (Ideas/RFC)
|
|
|
22
22
|
▼
|
|
23
23
|
Issue: Status = Shaping ─────────────────────────────┐
|
|
24
24
|
│ IP approved → roadmap-item
|
|
25
|
-
|
|
25
|
+
Grow writes IP + task list ────────────────────────┤ (sets IP field, Shaping → Planned)
|
|
26
26
|
(docs/implementationPlans/ + docs/tasks/) ▼
|
|
27
27
|
Issue: Status = Planned
|
|
28
|
-
│
|
|
28
|
+
│ Pick → Roast → Brew
|
|
29
29
|
▼
|
|
30
30
|
PR: Fixes #NNN
|
|
31
31
|
│ merge
|
|
@@ -34,17 +34,17 @@ Blend writes IP + task list ─────────────────
|
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
The planning pipeline (the `terreno-planning` plugin) drives the design-and-build half;
|
|
37
|
-
the roadmap skills drive the public-tracking half. They meet at one handoff: **
|
|
37
|
+
the roadmap skills drive the public-tracking half. They meet at one handoff: **Grow
|
|
38
38
|
writes the IP, and once it is Approved hands off to `roadmap-item`.**
|
|
39
39
|
|
|
40
40
|
| Transition | Who owns it | Authoritative artifact |
|
|
41
41
|
| ---------- | ----------- | ---------------------- |
|
|
42
42
|
| Idea debated and shaped | Community + maintainers | GitHub Discussion |
|
|
43
43
|
| Discussion → first tracking issue (`Shaping`) | `roadmap-promote` | GitHub Issue + Project |
|
|
44
|
-
| Design, scope, acceptance criteria | `terreno-1-
|
|
45
|
-
| Task breakdown for implementation | `terreno-1-
|
|
44
|
+
| Design, scope, acceptance criteria | `terreno-1-grow` | `docs/implementationPlans/<slug>.md` |
|
|
45
|
+
| Task breakdown for implementation | `terreno-1-grow` | `docs/tasks/<slug>.md` |
|
|
46
46
|
| Approved IP → issue `Planned` + `IP` field set | `roadmap-item` | GitHub Issue + Project |
|
|
47
|
-
| Implement, verify, submit, review | `terreno-2-
|
|
47
|
+
| Implement, verify, submit, review | `terreno-2-pick` … `terreno-5-taste` | the PR |
|
|
48
48
|
| Sprint estimates, assignees, internal-only work | Linear | Linear |
|
|
49
49
|
| Public rendered list | CI (`roadmap:generate`) | `ROADMAP.md` |
|
|
50
50
|
|
|
@@ -60,7 +60,7 @@ The `terreno-planning` plugin is meant to run in any Terreno repo, including one
|
|
|
60
60
|
Discussions and no roadmap board (Flourish, most consumer apps). There, only the design-and-build
|
|
61
61
|
half applies:
|
|
62
62
|
|
|
63
|
-
- **
|
|
63
|
+
- **Grow** still writes the IP + task list — that dual-file model is the source of truth
|
|
64
64
|
everywhere. It detects the absence of `.github/roadmap-fields.yml` and the `roadmap-item`
|
|
65
65
|
skill and **skips the roadmap handoff** instead of inventing issues or labels.
|
|
66
66
|
- Sprint execution is tracked in Linear and linked from the IP header; it is never copied
|
|
@@ -236,9 +236,9 @@ is the variable the generator reads.
|
|
|
236
236
|
|
|
237
237
|
## Maintainer skills
|
|
238
238
|
|
|
239
|
-
|
|
239
|
+
Five agent skills cover the recurring roadmap work. Each one researches, proposes, and then
|
|
240
240
|
**stops for a maintainer to approve** before touching GitHub — roadmap decisions are the most
|
|
241
|
-
human part of the process, so none of them mutate state on their own. All
|
|
241
|
+
human part of the process, so none of them mutate state on their own. All five are
|
|
242
242
|
`disable-model-invocation`, meaning an agent will not start them on its own initiative;
|
|
243
243
|
you invoke them explicitly.
|
|
244
244
|
|
|
@@ -248,6 +248,19 @@ you invoke them explicitly.
|
|
|
248
248
|
| `roadmap-promote` | Maintainers accepted an Ideas or RFC discussion and it needs a tracked issue that links back to the thread |
|
|
249
249
|
| `roadmap-item` | An approved IP needs its public tracking issue, or an existing entry's scope changed |
|
|
250
250
|
| `roadmap-review` | Recurring hygiene: status drift, stale items, untriaged backlog, promotion candidates, then regenerate `ROADMAP.md` |
|
|
251
|
+
| `roadmap-frontier` | A destination is too large or uncertain for one IP/context and needs a map, a small unblocked frontier, and repeated Grow → Taste delivery loops |
|
|
252
|
+
|
|
253
|
+
### Huge features: frontier maps
|
|
254
|
+
|
|
255
|
+
A frontier map is one low-resolution roadmap issue with an observable destination,
|
|
256
|
+
resolved-decision index, current frontier, fog, and explicit out-of-scope boundary. Child
|
|
257
|
+
tickets hold the detail and native blocking relationships. Work only the **frontier**:
|
|
258
|
+
open, unblocked, unclaimed tickets.
|
|
259
|
+
|
|
260
|
+
Decision tickets resolve one question. Delivery tickets link one approved IP/task pair and
|
|
261
|
+
run the complete planning pipeline. After each ticket, update the map, graduate clarified
|
|
262
|
+
fog into precise tickets, and return to the frontier with a fresh agent context. The map
|
|
263
|
+
closes only when the destination is reached and no in-scope fog or open child tickets remain.
|
|
251
264
|
|
|
252
265
|
Sources live in `.rulesync/skills/`; run `bun run rules` after editing to regenerate the
|
|
253
266
|
per-agent mirrors.
|
|
@@ -885,3 +885,42 @@ ad-hoc backfill scripts.
|
|
|
885
885
|
- **Tasks:** *(not yet written)*
|
|
886
886
|
- **RTK flag:** None
|
|
887
887
|
- **Depends on:** —
|
|
888
|
+
|
|
889
|
+
---
|
|
890
|
+
|
|
891
|
+
# Shipped, umbrella, and declined IPs
|
|
892
|
+
|
|
893
|
+
Tracking issues created for IPs that previously lacked a `**Roadmap issue:**` header.
|
|
894
|
+
Add each to the **Terreno Roadmap** project with the `IP` field set to the slug below.
|
|
895
|
+
|
|
896
|
+
| IP slug | GitHub issue | Status |
|
|
897
|
+
|---------|--------------|--------|
|
|
898
|
+
| `admin-only` | https://github.com/FlourishHealth/terreno/issues/1075 | Shipped |
|
|
899
|
+
| `admin-ui-v2-django-parity` | https://github.com/FlourishHealth/terreno/issues/1076 | Shipped |
|
|
900
|
+
| `admin-script-runner` | https://github.com/FlourishHealth/terreno/issues/1077 | Shipped |
|
|
901
|
+
| `consent-forms` | https://github.com/FlourishHealth/terreno/issues/1078 | Shipped |
|
|
902
|
+
| `upgrade-banner` | https://github.com/FlourishHealth/terreno/issues/1079 | Shipped |
|
|
903
|
+
| `apierror-standard-error-redesign` | https://github.com/FlourishHealth/terreno/issues/1080 | Shipped |
|
|
904
|
+
| `syncdb-local-first` | https://github.com/FlourishHealth/terreno/issues/1081 | Shipped |
|
|
905
|
+
| `feature-flags-openfeature` | https://github.com/FlourishHealth/terreno/issues/1082 | Shipped |
|
|
906
|
+
| `design-blend-skill` | https://github.com/FlourishHealth/terreno/issues/1083 | Shipped |
|
|
907
|
+
| `ModularAPI` | https://github.com/FlourishHealth/terreno/issues/1084 | Shipped |
|
|
908
|
+
| `mcp-boost-parity` | https://github.com/FlourishHealth/terreno/issues/1085 | In progress |
|
|
909
|
+
| `docs-site-and-versioning` | https://github.com/FlourishHealth/terreno/issues/1086 | Planned |
|
|
910
|
+
| `syncdb-codegen` | https://github.com/FlourishHealth/terreno/issues/1087 | Planned |
|
|
911
|
+
| `migrate-cicd-to-circleci` | https://github.com/FlourishHealth/terreno/issues/1088 | Planned |
|
|
912
|
+
| `rbac-permissions` | https://github.com/FlourishHealth/terreno/issues/1089 | Planned |
|
|
913
|
+
| `infra-mcp` | https://github.com/FlourishHealth/terreno/issues/1090 | Planned (blocked) |
|
|
914
|
+
| `comms-admin-dashboard` | https://github.com/FlourishHealth/terreno/issues/1091 | Planned |
|
|
915
|
+
| `model-router-mcp` | https://github.com/FlourishHealth/terreno/issues/1092 | Planned |
|
|
916
|
+
| `terreno-langfuse-integration` | https://github.com/FlourishHealth/terreno/issues/1093 | Future |
|
|
917
|
+
| `oss-launch-program` | https://github.com/FlourishHealth/terreno/issues/1094 | In progress |
|
|
918
|
+
| `b2b-platform-program` | https://github.com/FlourishHealth/terreno/issues/1095 | Planned |
|
|
919
|
+
| `offline-mode` | https://github.com/FlourishHealth/terreno/issues/1096 | Declined |
|
|
920
|
+
| `model-router-actions` | https://github.com/FlourishHealth/terreno/issues/1097 | Declined |
|
|
921
|
+
| `feature-flags` | https://github.com/FlourishHealth/terreno/issues/1098 | Declined |
|
|
922
|
+
| `admin-improvements` | https://github.com/FlourishHealth/terreno/issues/1099 | Declined |
|
|
923
|
+
|
|
924
|
+
Research and design sub-documents share the parent IP's issue: `admin-only-research` →
|
|
925
|
+
#1075; `infra-mcp-research` → #1090; `migrate-cicd-to-circleci-research` → #1088;
|
|
926
|
+
`syncdb-phase-c-design`, `terreno-syncdb-2`, and `syncdb-api-inventory` → #1081.
|
|
@@ -12,10 +12,13 @@ Problem-oriented, practical steps. Use these when you know what you want to do.
|
|
|
12
12
|
|
|
13
13
|
## Contents
|
|
14
14
|
|
|
15
|
+
- [CircleCI](circleci.md) — Dual-run CI on CircleCI (package CI / policy / e2e; deploys later)
|
|
15
16
|
- [Create a Mongoose model](create-a-model.md) — Define models with proper conventions
|
|
16
17
|
- [Add GitHub OAuth authentication](add-github-oauth.md) — Enable GitHub login for your API
|
|
17
18
|
- [Configure Better Auth](configure-better-auth.md) — Set up Better Auth with social OAuth (Google, GitHub, Apple)
|
|
18
19
|
- [Add WebSocket integration](websocket-integration.md) — Set up real-time Socket.io connections
|
|
20
|
+
- [Expose Model Context Protocol tools](expose-mcp-tools.md) — Turn `modelRouter` models into MCP tools an LLM can call
|
|
21
|
+
- [Install agent skills](install-agent-skills.md) — Install Grow/Pick/Roast/Brew/Taste and domain skills with `npx skills`
|
|
19
22
|
- [Call external APIs](call-external-apis.md) — Authenticated HTTP client, retries, and error normalization for third-party integrations
|
|
20
23
|
- [Deploy to Google Cloud Platform](deploy-to-gcp.md) — Deploy demo and example apps to GCS with CDN
|
|
21
24
|
- [Migrate from @terreno/rtk to @terreno/syncdb](migrate-rtk-to-syncdb.md) — Move data sync to the local-first layer
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Add a model to the admin
|
|
2
|
+
|
|
3
|
+
Add `admin` directly to the model's existing `modelRouter` options:
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
export const userRouter = modelRouter("/users", User, {
|
|
7
|
+
admin: {
|
|
8
|
+
displayName: "Users",
|
|
9
|
+
listFields: ["email", "name", "admin", "created"],
|
|
10
|
+
searchFields: ["email", "name"],
|
|
11
|
+
sortableFields: ["email", "name", "created"],
|
|
12
|
+
filters: [{field: "admin", kind: "boolean", label: "Admin user"}],
|
|
13
|
+
},
|
|
14
|
+
permissions: {
|
|
15
|
+
create: [Permissions.IsAdmin],
|
|
16
|
+
delete: [Permissions.IsAdmin],
|
|
17
|
+
list: [Permissions.IsAdmin],
|
|
18
|
+
read: [Permissions.IsAdmin],
|
|
19
|
+
update: [Permissions.IsAdmin],
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Register that router with `TerrenoApp`, then register `AdminApp`. The model appears in
|
|
25
|
+
`GET /admin/config` and at `/admin/User` without a duplicate `AdminApp.models` entry.
|
|
26
|
+
|
|
27
|
+
If the same Mongoose model is mounted at two `routePath`s (different filters or list
|
|
28
|
+
columns), `/admin/config` keeps `name` as the model name for the registered entry and
|
|
29
|
+
suffixes the others with the route slug (for example `Food-archived-foods`) so each list
|
|
30
|
+
is reachable.
|
|
31
|
+
|
|
32
|
+
Common fields:
|
|
33
|
+
|
|
34
|
+
- `listFields`: columns and fields exposed to admin CRUD.
|
|
35
|
+
- `searchFields`: string fields matched by the list search box (`q`) as a
|
|
36
|
+
case-insensitive partial (`$regex`) query.
|
|
37
|
+
- `sortableFields`: the only columns with sorting enabled.
|
|
38
|
+
- `filters`: typed filter drawer controls.
|
|
39
|
+
- `fieldsets`: grouped form sections.
|
|
40
|
+
- `readonlyFields` / `hiddenFields`: display-only or omitted form fields.
|
|
41
|
+
- `adminPermissions`: optional admin-specific permission methods.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Customize the admin home
|
|
2
|
+
|
|
3
|
+
Configure home slots on `AdminApp`:
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
new AdminApp({
|
|
7
|
+
home: {
|
|
8
|
+
title: "Operations",
|
|
9
|
+
slots: {
|
|
10
|
+
contentTop: ["feature-flags-overrides"],
|
|
11
|
+
main: ["modelStats"],
|
|
12
|
+
navGlobal: ["scriptRunner"],
|
|
13
|
+
sidebar: ["versionConfig", "recentActivity"],
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Built-in IDs include `modelStats`, `modelsGrid`, `scriptRunner`, `versionConfig`, and
|
|
20
|
+
`recentActivity`. Plugins add IDs such as `feature-flags-overrides`.
|
|
21
|
+
|
|
22
|
+
For an app-specific widget, implement `AdminHomeWidgetProps` and register it:
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
<AdminProvider widgets={{home: {operationsSummary: OperationsSummary}}} api={api}>
|
|
26
|
+
<AdminHome api={api} />
|
|
27
|
+
</AdminProvider>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then place `"operationsSummary"` in a home slot. Unknown IDs render a visible missing-widget
|
|
31
|
+
placeholder in development instead of crashing the dashboard.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Add a custom admin field widget
|
|
2
|
+
|
|
3
|
+
1. Name the widget in model admin metadata:
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
admin: {
|
|
7
|
+
displayName: "Articles",
|
|
8
|
+
listFields: ["title", "body"],
|
|
9
|
+
fieldOverrides: {body: {widget: "rich-text"}},
|
|
10
|
+
}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Implement the field widget:
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
const RichTextWidget: React.FC<AdminFieldWidgetProps> = ({
|
|
17
|
+
value,
|
|
18
|
+
onChange,
|
|
19
|
+
readOnly,
|
|
20
|
+
}) => (
|
|
21
|
+
<RichTextEditor
|
|
22
|
+
disabled={Boolean(readOnly)}
|
|
23
|
+
onChange={onChange}
|
|
24
|
+
value={typeof value === "string" ? value : ""}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
3. Register it once around the admin routes:
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
<AdminProvider
|
|
33
|
+
api={api}
|
|
34
|
+
apiBase="/admin"
|
|
35
|
+
routeBase="/admin"
|
|
36
|
+
widgets={{fields: {"rich-text": RichTextWidget}}}
|
|
37
|
+
>
|
|
38
|
+
<AdminRoutes />
|
|
39
|
+
</AdminProvider>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Host registrations override built-ins with the same ID.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Import pre-built admins
|
|
2
|
+
|
|
3
|
+
Register first-party plugins on the same `TerrenoApp` as `AdminApp`:
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
const app = new TerrenoApp({userModel: User})
|
|
7
|
+
.register(new FeatureFlagsApp())
|
|
8
|
+
.register(new ConsentApp({auditTrail: true}))
|
|
9
|
+
.register(new DocumentStorageApp({bucketName: process.env.GCS_BUCKET ?? ""}))
|
|
10
|
+
.register(new AIAdminApp())
|
|
11
|
+
.register(new AdminApp({home: {slots: {main: ["modelStats"]}}}));
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`AdminApp` aggregates each plugin's `adminContribution()`:
|
|
15
|
+
|
|
16
|
+
- `FeatureFlagsApp`: FeatureFlag model and `feature-flags-overrides` home widget.
|
|
17
|
+
- `ConsentApp`: ConsentForm and ConsentResponse models plus consent field-widget IDs.
|
|
18
|
+
- `DocumentStorageApp`: `documents` custom screen.
|
|
19
|
+
- `AIAdminApp`: `ai-requests` custom screen and explorer API.
|
|
20
|
+
|
|
21
|
+
Wrap frontend admin routes in `AdminProvider`. First-party widgets are already in the built-in
|
|
22
|
+
registry, so no consumer-side switch statement or custom-screen map is required.
|
|
23
|
+
|
|
24
|
+
`featureFlagAdminConfig` and `AdminApp.models` remain compatibility paths, but new integrations
|
|
25
|
+
should use plugin contributions and `modelRouter({admin: ...})`.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# CircleCI (Terreno)
|
|
2
|
+
|
|
3
|
+
Dual-run migration from GitHub Actions. See
|
|
4
|
+
[`docs/implementationPlans/migrate-cicd-to-circleci.md`](../implementationPlans/migrate-cicd-to-circleci.md).
|
|
5
|
+
|
|
6
|
+
**Status (2026-08-20):** CircleCI is **disabled**. GitHub Actions is the CI of
|
|
7
|
+
record. Setup/path-filtering is parked in `.circleci/config.setup.yml`;
|
|
8
|
+
`.circleci/config.yml` is a no-op (`workflows.disabled.when: false`). Real jobs
|
|
9
|
+
remain in `.circleci/continue-config.yml`. To re-enable, copy `config.setup.yml`
|
|
10
|
+
over `config.yml`.
|
|
11
|
+
|
|
12
|
+
**Parked (2026-08-17):** Phase 1–3 config is in-repo (package CI, repo policy, Playwright
|
|
13
|
+
e2e). **Deploys are not ported yet** (Netlify, GCP CD, EAS, npm publish). GHA remains
|
|
14
|
+
required until CircleCI twins are trusted.
|
|
15
|
+
|
|
16
|
+
## Project setup (maintainers)
|
|
17
|
+
|
|
18
|
+
1. Link `FlourishHealth/terreno` in CircleCI (GitHub App).
|
|
19
|
+
2. Default branch: `master`.
|
|
20
|
+
3. Enable **dynamic config** / setup workflows for the project (required for
|
|
21
|
+
`.circleci/config.yml` `setup: true`).
|
|
22
|
+
4. Build forked PRs if you want DCO + rulesync on forks.
|
|
23
|
+
|
|
24
|
+
Org/project slug: _(record after Phase 0.1 — e.g. `flourishhealth/terreno`)_.
|
|
25
|
+
|
|
26
|
+
## Config layout
|
|
27
|
+
|
|
28
|
+
| File | Role |
|
|
29
|
+
|------|------|
|
|
30
|
+
| `.circleci/config.yml` | Active CircleCI config (currently a disabled no-op) |
|
|
31
|
+
| `.circleci/config.setup.yml` | Parked setup workflow + `path-filtering` (copy over `config.yml` to re-enable) |
|
|
32
|
+
| `.circleci/continue-config.yml` | Real jobs/workflows gated by those params |
|
|
33
|
+
|
|
34
|
+
Smoke job `config-ok` always runs on continuation.
|
|
35
|
+
|
|
36
|
+
`.circleci/**` sets `run-circleci-config`, which starts the `circleci-config`
|
|
37
|
+
workflow: one job from each ported family (package CI, policy, example apps,
|
|
38
|
+
`e2e` with `spec: login`, admin-spa). `comms/**` also sets
|
|
39
|
+
`run-example-backend` and `run-example-backend-script`, matching the GitHub
|
|
40
|
+
Actions twins.
|
|
41
|
+
|
|
42
|
+
## Contexts (create empty shells, then fill)
|
|
43
|
+
|
|
44
|
+
Do **not** paste secret values into the repo. Create these CircleCI Contexts and restrict
|
|
45
|
+
`terreno-release` to tag/release pipelines when publish is ported.
|
|
46
|
+
|
|
47
|
+
| Context | Maps from GHA | Used by (planned / current) |
|
|
48
|
+
|---------|---------------|------------------------------|
|
|
49
|
+
| `terreno-npm` | `NPM_TOKEN` | publish (deferred) |
|
|
50
|
+
| `terreno-netlify` | `NETLIFY_*` | deploys (deferred) |
|
|
51
|
+
| `terreno-expo` | `EXPO_TOKEN` | EAS (deferred) |
|
|
52
|
+
| `terreno-gcp` | OIDC / WIF (no long-lived key for CD) | GCP CD (deferred) |
|
|
53
|
+
| `terreno-e2e` | `E2E_TOKEN_SECRET`, `E2E_REFRESH_TOKEN_SECRET`, `E2E_SESSION_SECRET` | `e2e`, `admin-spa-integration` |
|
|
54
|
+
| `terreno-release` | `REPO_ADMIN_TOKEN`, Zoom webhooks | publish (deferred) |
|
|
55
|
+
| `terreno-agentic` | `CURSOR_API_KEY` | agentic replacements (deferred) |
|
|
56
|
+
| `terreno-github-api` | PAT (`pull-requests`, `contents`, …) | `dco`, PR comments later |
|
|
57
|
+
|
|
58
|
+
Until contexts exist, e2e jobs may use **project env vars for `E2E_*` secrets only**
|
|
59
|
+
(or the in-job `ci-e2e-*-secret` fallbacks). **Do not** put `GITHUB_TOKEN` (or any
|
|
60
|
+
GitHub PAT) in project env vars — those are injected into every job, including
|
|
61
|
+
`bun` scripts from the PR. Create `terreno-github-api`, restrict it to this
|
|
62
|
+
project, leave fork-PR secret passing off, and attach that context **only** to
|
|
63
|
+
`dco` (and later comment jobs). DCO skips if `GITHUB_TOKEN` is unset.
|
|
64
|
+
|
|
65
|
+
After contexts exist, attach them on the matching jobs in
|
|
66
|
+
`.circleci/continue-config.yml` (see comments in the `workflows:` section).
|
|
67
|
+
|
|
68
|
+
## Check name map (GHA → CircleCI)
|
|
69
|
+
|
|
70
|
+
Branch protection still requires **GitHub Actions** names during dual-run. CircleCI
|
|
71
|
+
checks appear as CircleCI job names in the GitHub Checks UI.
|
|
72
|
+
|
|
73
|
+
| GHA job `name:` / workflow | CircleCI job |
|
|
74
|
+
|----------------------------|--------------|
|
|
75
|
+
| Repository policies / No barrel imports | `no-barrel-imports` |
|
|
76
|
+
| Explicit any baseline | `explicit-any` |
|
|
77
|
+
| License coverage | `license-coverage` |
|
|
78
|
+
| Verify rules are in sync | `rulesync-check` |
|
|
79
|
+
| `dco` | `dco` |
|
|
80
|
+
| Run all tests (API CI) | `api-ci` |
|
|
81
|
+
| Run all tests (AI CI) | `ai-ci` |
|
|
82
|
+
| RTK Lint and Build | `rtk-ci` |
|
|
83
|
+
| UI Lint, Build, Types, and Tests | `ui-ci` |
|
|
84
|
+
| Demo TypeScript Check (UI dependency) | `ui-demo-typecheck` |
|
|
85
|
+
| Demo Lint and TypeScript Check | `ui-demo-ci` |
|
|
86
|
+
| Lint, compile, and test communications | `comms-ci` |
|
|
87
|
+
| Lint, Build, and Test (MCP) | `mcp-server-ci` |
|
|
88
|
+
| Build Docker Image (MCP) | `mcp-server-docker` |
|
|
89
|
+
| Example Frontend Lint and Test | `example-frontend-ci` |
|
|
90
|
+
| Example Backend Lint, Build, and Test | `example-backend-ci` |
|
|
91
|
+
| Run admin script CLI | `example-backend-script-runner` |
|
|
92
|
+
| Build backend Docker image | `example-backend-docker` |
|
|
93
|
+
| Admin SPA Build and E2E | `admin-spa-ci` |
|
|
94
|
+
| E2E · `<spec>` | `e2e` (matrix `spec`) |
|
|
95
|
+
| E2E Load · syncdb-loadlab | `e2e-load` (trigger-gated, see below) |
|
|
96
|
+
| Admin SPA Backend Integration E2E | `admin-spa-integration` |
|
|
97
|
+
| _(new)_ CircleCI path-filter parity | `circleci-parity` |
|
|
98
|
+
| _(smoke)_ | `config-ok` |
|
|
99
|
+
|
|
100
|
+
Deferred phases keep their GHA checks for now; these are the planned CircleCI job
|
|
101
|
+
names so branch protection can be remapped in one pass later:
|
|
102
|
+
|
|
103
|
+
| GHA job `name:` / workflow (not yet ported) | Planned CircleCI job |
|
|
104
|
+
|---------------------------------------------|----------------------|
|
|
105
|
+
| Fingerprint gate (`fingerprint-gate.yml`) | `fingerprint-gate` (Phase 5) |
|
|
106
|
+
| EAS PR update/build (`eas-pr.yml`) | `eas-pr` (Phase 5) |
|
|
107
|
+
| EAS dev build (`eas-dev-build.yml`) | `eas-dev-build`, manual pipeline (Phase 5) |
|
|
108
|
+
| CD terraform preview/apply (`cd.yml`) | `cd-terraform`, `cd-deploy` (Phase 6) |
|
|
109
|
+
| Preview cleanup (`preview-cleanup.yml`) | `preview-cleanup` (Phase 6) |
|
|
110
|
+
| Netlify demo / frontend / docs deploys | `deploy-demo`, `deploy-example-frontend`, `deploy-docs` (Phase 4) |
|
|
111
|
+
| Publish on tag (`publish-on-tag.yml`) | `publish-npm` (Phase 7, single-writer cutover) |
|
|
112
|
+
| Appium / Maestro | `appium-android`, `appium-ios`, `maestro` (Phase 8) |
|
|
113
|
+
|
|
114
|
+
## Path-filter parity guard
|
|
115
|
+
|
|
116
|
+
`bun run check:circleci-parity` fails when a GHA `paths:` entry has no mapping to
|
|
117
|
+
its CircleCI parameter — otherwise the twin silently never runs. It runs as the
|
|
118
|
+
`circleci-parity` job (CircleCI) and the **CircleCI path-filter parity** job
|
|
119
|
+
(GitHub Actions `repo-policies`). Add new packages/paths to the mapping in
|
|
120
|
+
`.circleci/config.setup.yml` (or `config.yml` when enabled) and to `WORKFLOW_PARAMETERS` in
|
|
121
|
+
`scripts/check-circleci-parity/lib.ts`.
|
|
122
|
+
|
|
123
|
+
## Config-only changes
|
|
124
|
+
|
|
125
|
+
When CircleCI is enabled, `.circleci/config.yml` / `continue-config.yml` /
|
|
126
|
+
`example-frontend/playwright.circleci.config.ts` edits set `run-circleci-config`,
|
|
127
|
+
which runs a representative slice (`api-ci`, `ui-ci`, `example-backend-ci`,
|
|
128
|
+
`no-barrel-imports`, `e2e` spec `login`) so config changes are actually exercised
|
|
129
|
+
instead of only hitting the always-on smoke jobs. While disabled, keep the mapping
|
|
130
|
+
in `config.setup.yml` in sync; `check:circleci-parity` reads that file first. CircleCI e2e
|
|
131
|
+
pre-starts a static `bun expo export` on `:8082` (`NODE_OPTIONS=--max-old-space-size=3072`
|
|
132
|
+
for the export only) and reuses it (60s test timeout, `large` Docker). Keeping Metro
|
|
133
|
+
alive next to Chromium gets SIGKILL on 8GB. `xlarge` is not on this project's plan.
|
|
134
|
+
|
|
135
|
+
## Nightly load test
|
|
136
|
+
|
|
137
|
+
`e2e-load` (syncdb-loadlab) is never PR-blocking. Trigger the **setup** pipeline
|
|
138
|
+
with `run-e2e-load`. Setup skips path-filtering and continues with a differently
|
|
139
|
+
named continuation parameter (`e2e-load`) so CircleCI does not report conflicting
|
|
140
|
+
pipeline parameters.
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{"run-e2e-load": true}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
This replaces the GHA cron / `workflow_dispatch` / `load-test` label triggers in
|
|
147
|
+
`e2e-load-nightly.yml`.
|
|
148
|
+
|
|
149
|
+
## Local validation
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
circleci config validate .circleci/config.yml
|
|
153
|
+
circleci config validate .circleci/continue-config.yml
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Dual-run drift
|
|
157
|
+
|
|
158
|
+
While both systems run, keep these in sync when editing a GHA workflow:
|
|
159
|
+
|
|
160
|
+
1. `paths:` → mapping in `.circleci/config.setup.yml` (or `config.yml` when enabled; enforced by `check:circleci-parity`)
|
|
161
|
+
2. e2e `spec:` matrix → `e2e` workflow matrix in `continue-config.yml`
|
|
162
|
+
3. New package CI workflow → new param + job + `WORKFLOW_PARAMETERS` entry
|
|
163
|
+
|
|
164
|
+
## Not in this phase
|
|
165
|
+
|
|
166
|
+
- Netlify / docs / demo / example-frontend **deploys**
|
|
167
|
+
- GCP `cd.yml`, preview-cleanup, OIDC
|
|
168
|
+
- EAS / fingerprint
|
|
169
|
+
- npm publish-on-tag
|
|
170
|
+
- Appium / Maestro
|
|
171
|
+
- CodeQL, Dependabot auto-merge, triage, gh-aw agentics
|
|
172
|
+
|
|
173
|
+
Keep matching `.github/workflows/*` until dual-run cutover deletes them per phase.
|