@terreno/agent-plugin 0.0.0-stage → 57.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/.claude-plugin/plugin.json +32 -0
  2. package/CHANGELOG.md +2124 -0
  3. package/LICENSE +21 -0
  4. package/README.md +57 -2
  5. package/agents/pre-commit.md +65 -0
  6. package/agents/ui-verifier.md +93 -0
  7. package/package.json +32 -4
  8. package/references/async-review-bots.md +76 -0
  9. package/references/documentation-contract.md +61 -0
  10. package/references/execution-state.schema.json +77 -0
  11. package/references/github-attention-contract.md +165 -0
  12. package/references/independent-review.md +31 -0
  13. package/references/lifecycle-contract.md +211 -0
  14. package/references/loop-engineering.md +125 -0
  15. package/references/pick-roast-loop.md +112 -0
  16. package/references/pr-deployments.md +69 -0
  17. package/references/product-ci.md +164 -0
  18. package/references/push-ownership.md +91 -0
  19. package/references/stage-result.schema.json +82 -0
  20. package/references/subagent-briefing.md +43 -0
  21. package/references/testing-plan.md +163 -0
  22. package/references/user-guide.md +171 -0
  23. package/skills/1-grow/SKILL.md +145 -0
  24. package/skills/1-grow/references/grilling.md +243 -0
  25. package/skills/2-pick/SKILL.md +170 -0
  26. package/skills/2-pick/references/mocking.md +34 -0
  27. package/skills/2-pick/references/testing.md +43 -0
  28. package/skills/3-roast/SKILL.md +168 -0
  29. package/skills/4-brew/SKILL.md +201 -0
  30. package/skills/5-taste/SKILL.md +311 -0
  31. package/skills/ai-prompt-governance/SKILL.md +100 -0
  32. package/skills/attach-pr-media/SKILL.md +89 -0
  33. package/skills/attach-pr-media/scripts/upload-pr-media.sh +151 -0
  34. package/skills/backend-test-env/SKILL.md +64 -0
  35. package/skills/backfill-regression/SKILL.md +101 -0
  36. package/skills/backfill-user-guide/SKILL.md +96 -0
  37. package/skills/bootstrap-mcp-server/SKILL.md +244 -0
  38. package/skills/building-admin-interfaces/SKILL.md +83 -0
  39. package/skills/building-admin-interfaces/agents/openai.yaml +4 -0
  40. package/skills/building-admin-interfaces/references/nav-and-shell.md +42 -0
  41. package/skills/building-admin-interfaces/references/patterns-and-tools.md +73 -0
  42. package/skills/building-admin-interfaces/references/screens-and-routes.md +50 -0
  43. package/skills/building-terreno-apps/SKILL.md +280 -0
  44. package/skills/building-terreno-apps/agents/openai.yaml +4 -0
  45. package/skills/building-terreno-apps/references/navigation.md +102 -0
  46. package/skills/building-terreno-apps/references/route-structure.md +91 -0
  47. package/skills/building-terreno-apps/references/screen-patterns.md +191 -0
  48. package/skills/debug-syncdb-with-mcp/SKILL.md +75 -0
  49. package/skills/deploy-gcp/SKILL.md +73 -0
  50. package/skills/deploy-gcp/references/troubleshooting.md +29 -0
  51. package/skills/generate-release-announcements/SKILL.md +145 -0
  52. package/skills/generate-sdk/SKILL.md +156 -0
  53. package/skills/mongoose-schema-safety/SKILL.md +164 -0
  54. package/skills/pick-roast-loop/SKILL.md +152 -0
  55. package/skills/planning-loop/SKILL.md +161 -0
  56. package/skills/prd/SKILL.md +138 -0
  57. package/skills/set-up-social-login/SKILL.md +76 -0
  58. package/skills/store-assets/SKILL.md +221 -0
  59. package/skills/store-assets/examples/screenshots.yaml +31 -0
  60. package/skills/store-assets/examples/storeAssets.config.json +44 -0
  61. package/skills/store-assets/scripts/banner.ts +165 -0
  62. package/skills/store-assets/scripts/config.ts +255 -0
  63. package/skills/store-assets/scripts/devClient.ts +635 -0
  64. package/skills/store-assets/scripts/devices.ts +286 -0
  65. package/skills/store-assets/scripts/icon.ts +81 -0
  66. package/skills/store-assets/scripts/maestro/goHome.yaml +21 -0
  67. package/skills/store-assets/scripts/maestro/login.yaml +27 -0
  68. package/skills/store-assets/scripts/maestro/openApp.yaml +26 -0
  69. package/skills/store-assets/scripts/screenshots.ts +848 -0
  70. package/skills/taste-sweep/SKILL.md +172 -0
  71. package/skills/terreno-backend-api/SKILL.md +355 -0
  72. package/skills/terreno-backend-api/agents/openai.yaml +4 -0
  73. package/skills/terreno-backend-api/references/custom-routes.md +132 -0
  74. package/skills/terreno-backend-api/references/model-router.md +116 -0
  75. package/skills/terreno-backend-api/references/server-setup.md +116 -0
  76. package/skills/terreno-backend-tests/SKILL.md +176 -0
  77. package/skills/terreno-data-fetching/SKILL.md +276 -0
  78. package/skills/terreno-data-fetching/agents/openai.yaml +4 -0
  79. package/skills/terreno-data-fetching/references/auth-and-tokens.md +93 -0
  80. package/skills/terreno-data-fetching/references/realtime.md +45 -0
  81. package/skills/terreno-data-fetching/references/sdk-customization.md +84 -0
  82. package/skills/terreno-frontend-tests/SKILL.md +190 -0
  83. package/skills/terreno-mobile-tests/SKILL.md +127 -0
  84. package/skills/terreno-test-setup/SKILL.md +81 -0
  85. package/skills/terreno-test-setup/references/backend.md +131 -0
  86. package/skills/terreno-test-setup/references/frontend.md +169 -0
  87. package/skills/terreno-test-setup/references/mobile.md +134 -0
  88. package/skills/terreno-ui/SKILL.md +252 -0
  89. package/skills/terreno-ui/agents/openai.yaml +4 -0
  90. package/skills/terreno-ui/references/data-display.md +85 -0
  91. package/skills/terreno-ui/references/feedback.md +122 -0
  92. package/skills/terreno-ui/references/forms.md +119 -0
  93. package/skills/terreno-ui/references/layout.md +124 -0
  94. package/skills/terreno-ui/references/theming.md +87 -0
  95. package/skills/update-docs/SKILL.md +82 -0
  96. package/skills/upgrading-terreno/SKILL.md +86 -0
  97. package/skills/upgrading-terreno/references/ordering.md +40 -0
  98. package/skills/verify-ui-changes/SKILL.md +605 -0
@@ -0,0 +1,85 @@
1
+ # Data Display — @terreno/ui
2
+
3
+ ## Text and Heading
4
+
5
+ ```tsx
6
+ <Text size="md" color="primary" bold truncate>
7
+ Body copy
8
+ </Text>
9
+
10
+ <Heading size="lg" color="primary" align="center">
11
+ Page Title
12
+ </Heading>
13
+ ```
14
+
15
+ Sizes: `sm`, `md`, `lg`, `xl`, `2xl` (responsive web/mobile values).
16
+
17
+ ## Badge
18
+
19
+ ```tsx
20
+ <Badge status="success" value="Active" />
21
+ <Badge status="warning" value="Pending" />
22
+ <Badge status="error" value="Failed" />
23
+ ```
24
+
25
+ ## DataTable
26
+
27
+ ```tsx
28
+ <DataTable
29
+ columns={[
30
+ {key: "name", label: "Name", width: 200, sortable: true},
31
+ {key: "status", label: "Status", width: 100, columnType: "boolean"},
32
+ {key: "created", label: "Created", width: 150, columnType: "date"},
33
+ ]}
34
+ data={rows}
35
+ onSortChange={setSort}
36
+ onRowClick={(row) => navigate(row.id)}
37
+ pageSize={20}
38
+ totalRowCount={total}
39
+ onPageChange={setPage}
40
+ sticky
41
+ loading={isLoading}
42
+ />
43
+ ```
44
+
45
+ Column types: `text`, `date`, `number`, `boolean`, `custom`.
46
+
47
+ For admin tables, prefer `AdminModelTable` from `@terreno/admin-frontend`.
48
+
49
+ ## Link
50
+
51
+ ```tsx
52
+ <Link href="https://example.com" text="Learn more" />
53
+ ```
54
+
55
+ ## Avatar
56
+
57
+ ```tsx
58
+ <Avatar name="Jane Doe" src={imageUrl} size="md" />
59
+ ```
60
+
61
+ ## Pagination
62
+
63
+ Standalone pagination when not using DataTable's built-in controls:
64
+
65
+ ```tsx
66
+ <Pagination
67
+ page={currentPage}
68
+ totalPages={totalPages}
69
+ onPageChange={setPage}
70
+ />
71
+ ```
72
+
73
+ ## Date formatting
74
+
75
+ Always use Luxon:
76
+
77
+ ```tsx
78
+ import {DateTime} from "luxon";
79
+
80
+ const formatted = DateTime.fromISO(isoString).toLocaleString(DateTime.DATETIME_MED);
81
+ ```
82
+
83
+ ## Selectable text
84
+
85
+ Add `selectable` to `Text` when users may copy the content (IDs, error messages, data values).
@@ -0,0 +1,122 @@
1
+ # Feedback — @terreno/ui
2
+
3
+ ## Spinner
4
+
5
+ ```tsx
6
+ <Spinner />
7
+ <Spinner size="lg" />
8
+ ```
9
+
10
+ Use in loading states inside `Page` or centered in `Box`.
11
+
12
+ ## Modal
13
+
14
+ ```tsx
15
+ <Modal
16
+ visible={isVisible}
17
+ onDismiss={() => setIsVisible(false)}
18
+ title="Confirm Action"
19
+ size="sm" // sm | md | lg
20
+ primaryButtonText="Confirm"
21
+ primaryButtonOnClick={handleConfirm}
22
+ secondaryButtonText="Cancel"
23
+ secondaryButtonOnClick={() => setIsVisible(false)}
24
+ persistOnBackgroundClick={false}
25
+ >
26
+ <Text>Are you sure?</Text>
27
+ </Modal>
28
+ ```
29
+
30
+ Renders as ActionSheet on mobile, centered dialog on web.
31
+
32
+ ## Button confirmation
33
+
34
+ ```tsx
35
+ <Button
36
+ text="Delete"
37
+ variant="destructive"
38
+ withConfirmation
39
+ confirmationText="This cannot be undone."
40
+ onClick={handleDelete}
41
+ />
42
+ ```
43
+
44
+ ## Toast
45
+
46
+ `TerrenoProvider` must wrap the app. Use the `useToast` hook from `@terreno/ui`:
47
+
48
+ ```tsx
49
+ import {useToast} from "@terreno/ui";
50
+
51
+ const MyScreen: React.FC = () => {
52
+ const toast = useToast();
53
+
54
+ const handleSave = useCallback(async (): Promise<void> => {
55
+ try {
56
+ await saveMutation().unwrap();
57
+ toast.success("Saved");
58
+ } catch (err) {
59
+ toast.catch(err, "Save failed");
60
+ }
61
+ }, [saveMutation, toast]);
62
+ };
63
+ ```
64
+
65
+ `useToast` exposes `success`, `info`, `warn`, `error`, `show`, `hide`, and `catch` (for API errors).
66
+
67
+ ## Banner
68
+
69
+ ```tsx
70
+ <Banner
71
+ text="Service is temporarily unavailable."
72
+ status="warning"
73
+ />
74
+ ```
75
+
76
+ Use `OfflineBanner` from `@terreno/ui` when showing network connectivity status (see example-frontend todos screen).
77
+
78
+ ## ErrorPage
79
+
80
+ Full-page error state:
81
+
82
+ ```tsx
83
+ <ErrorPage
84
+ title="Something went wrong"
85
+ message="We couldn't load your data."
86
+ onRetry={refetch}
87
+ />
88
+ ```
89
+
90
+ ## ErrorBoundary
91
+
92
+ Wrap risky subtrees:
93
+
94
+ ```tsx
95
+ <ErrorBoundary>
96
+ <RiskyComponent />
97
+ </ErrorBoundary>
98
+ ```
99
+
100
+ ## Loading + error pattern on Page
101
+
102
+ ```tsx
103
+ if (isLoading) {
104
+ return (
105
+ <Page title="Items">
106
+ <Box alignItems="center" padding={8}>
107
+ <Spinner />
108
+ </Box>
109
+ </Page>
110
+ );
111
+ }
112
+
113
+ if (error) {
114
+ return (
115
+ <Page title="Items">
116
+ <ErrorPage title="Failed to load" onRetry={refetch} />
117
+ </Page>
118
+ );
119
+ }
120
+ ```
121
+
122
+ Never ship a screen without loading and error states.
@@ -0,0 +1,119 @@
1
+ # Forms — @terreno/ui
2
+
3
+ All form fields share common props:
4
+
5
+ ```typescript
6
+ interface BaseFieldProps {
7
+ onChange: (value: string) => void;
8
+ value?: string;
9
+ title?: string; // label above field
10
+ placeholder?: string;
11
+ disabled?: boolean;
12
+ errorText?: string; // red error below field
13
+ helperText?: string; // gray helper below field
14
+ iconName?: IconName;
15
+ testID?: string;
16
+ }
17
+ ```
18
+
19
+ ## TextField
20
+
21
+ ```tsx
22
+ <TextField
23
+ title="Name"
24
+ value={name}
25
+ onChange={setName}
26
+ type="text" // text | email | password | phoneNumber | search | url
27
+ errorText={nameError}
28
+ helperText="Required"
29
+ multiline
30
+ rows={3}
31
+ grow // auto-expand height
32
+ trimOnBlur
33
+ />
34
+ ```
35
+
36
+ ## SelectField
37
+
38
+ ```tsx
39
+ <SelectField
40
+ title="Status"
41
+ options={[
42
+ {label: "Active", value: "active"},
43
+ {label: "Inactive", value: "inactive"},
44
+ ]}
45
+ value={status}
46
+ onChange={setStatus}
47
+ requireValue
48
+ />
49
+ ```
50
+
51
+ ## DateTimeField
52
+
53
+ ```tsx
54
+ import {DateTime} from "luxon";
55
+
56
+ <DateTimeField
57
+ title="Due Date"
58
+ type="date" // date | datetime | time
59
+ value={dueDate} // ISO string
60
+ onChange={setDueDate}
61
+ showTimezone
62
+ />
63
+ ```
64
+
65
+ Always use Luxon for formatting displayed dates.
66
+
67
+ ## Other fields
68
+
69
+ | Field | Use for |
70
+ |-------|---------|
71
+ | `TextArea` | Multi-line text |
72
+ | `NumberField` | Numeric input |
73
+ | `EmailField` | Email with validation |
74
+ | `PhoneNumberField` | Phone formatting |
75
+ | `BooleanField` | Toggle with label |
76
+ | `CheckBox` | Checkbox without field chrome |
77
+ | `RadioField` | Radio group |
78
+ | `MultiselectField` | Multiple selection |
79
+ | `AddressField` | Structured address |
80
+ | `PasswordField` | Password with show/hide |
81
+ | `SignatureField` | Draw signature (consent flows) |
82
+
83
+ ## TapToEdit
84
+
85
+ Use `TapToEdit` for values that should stay read-only until the user taps the pencil. Pass `setValue` for the in-progress edit and `onSave` to persist.
86
+
87
+ ```tsx
88
+ <TapToEdit
89
+ onSave={handleSaveName}
90
+ setValue={setName}
91
+ title="Name"
92
+ type="text"
93
+ value={name}
94
+ />
95
+ ```
96
+
97
+ `onSave` may be async. Cancel restores the value from when editing started. Do not omit `setValue` when `editable` is true.
98
+
99
+ ## Form pattern
100
+
101
+ ```tsx
102
+ const [email, setEmail] = useState<string>("");
103
+ const [emailError, setEmailError] = useState<string | undefined>();
104
+
105
+ const handleSubmit = useCallback(async (): Promise<void> => {
106
+ if (!email.trim()) {
107
+ setEmailError("Email is required");
108
+ return;
109
+ }
110
+ setEmailError(undefined);
111
+ await saveMutation({email}).unwrap();
112
+ }, [email, saveMutation]);
113
+ ```
114
+
115
+ Check validation at the start of handlers and return early.
116
+
117
+ ## Admin forms
118
+
119
+ For admin CRUD, use `AdminModelForm` from `@terreno/admin-frontend` — it auto-generates fields from the backend `/admin/config` metadata.
@@ -0,0 +1,124 @@
1
+ # Layout — @terreno/ui
2
+
3
+ ## Box
4
+
5
+ Core flex primitive. All layout should use Box.
6
+
7
+ ```tsx
8
+ <Box
9
+ direction="row" // row | column
10
+ justifyContent="between" // start | end | center | between | around
11
+ alignItems="center" // start | end | center | baseline | stretch
12
+ flex="grow" // grow | shrink | none
13
+ gap={2} // 0-12 spacing scale
14
+ padding={4}
15
+ paddingX={2}
16
+ marginBottom={2}
17
+ width="100%"
18
+ color="base" // surface color token
19
+ border="default"
20
+ rounding="md"
21
+ shadow
22
+ onClick={handlePress} // makes it pressable
23
+ scroll // wraps in ScrollView
24
+ testID="my-box"
25
+ />
26
+ ```
27
+
28
+ ### Spacing scale
29
+
30
+ `0→0px, 1→4px, 2→8px, 3→12px, 4→16px, 5→24px, 6→32px, 7→40px, 8→48px, 9→56px, 10→64px, 11→72px, 12→80px`
31
+
32
+ Prefer `gap` over margin. Prefer `padding` over margin.
33
+
34
+ ## Page
35
+
36
+ Full-screen layout with optional header, back button, scroll, and footer.
37
+
38
+ ```tsx
39
+ <Page
40
+ title="Settings"
41
+ backButton
42
+ scroll
43
+ loading={isLoading}
44
+ maxWidth={800}
45
+ padding={2}
46
+ footer={<Button text="Save" onClick={save} />}
47
+ >
48
+ {children}
49
+ </Page>
50
+ ```
51
+
52
+ Use `Page` instead of wrapping content in `ScrollView` manually.
53
+
54
+ ## Card
55
+
56
+ Box wrapper with default rounding and shadow.
57
+
58
+ ```tsx
59
+ <Card padding={4} color="base">
60
+ <Text>Grouped content</Text>
61
+ </Card>
62
+ ```
63
+
64
+ ## ListDetailLayout
65
+
66
+ Prefer this for list/detail screens. Use it as a route group's `_layout.tsx`: on a phone the
67
+ list pushes the `[id]` route; on a tablet or wide browser (layout width ≥ 768) the list stays in
68
+ a left pane and the detail opens beside it. The open item is the URL, so deep links and back work,
69
+ and it stays open across rotation and resize.
70
+
71
+ ```tsx
72
+ // app/mail/_layout.tsx
73
+ export const unstable_settings = {initialRouteName: "index"};
74
+ const MailLayout: React.FC = () => (
75
+ <ListDetailLayout
76
+ detailHref={(id) => `/mail/${id}`}
77
+ emptyDetail={<Text>Select a message</Text>}
78
+ indexHref="/mail"
79
+ list={<MailList />}
80
+ />
81
+ );
82
+ // app/mail/index.tsx
83
+ const MailIndex: React.FC = () => <ListDetailIndex />;
84
+ // In MailList rows: const {selectedId, select} = useListDetail();
85
+ // <Box accessibilityState={{selected: id === selectedId}} onClick={() => select(id)} ... />
86
+ ```
87
+
88
+ Keep list filters and search text in the route or a store: the list remounts at the breakpoint.
89
+ See `docs/how-to/build-list-detail-screens.md`.
90
+
91
+ ## SplitPage
92
+
93
+ Use only for list/detail views without their own routes (for example inside a modal); prefer
94
+ `ListDetailLayout` otherwise. Master-detail layout. On large screens the list and detail sit side by side. On small
95
+ screens, selecting a list item replaces the list with the detail pane.
96
+
97
+ ```tsx
98
+ <SplitPage
99
+ listViewData={items}
100
+ renderListViewItem={({item}) => <Text>{item.name}</Text>}
101
+ renderContent={(index) => <ItemDetail index={index} />}
102
+ />
103
+ ```
104
+
105
+ ## Responsive breakpoints
106
+
107
+ Policy: `docs/explanation/responsive-design.md`. Width tables: `docs/reference/ui.md`.
108
+
109
+ Box supports `smDirection`, `mdDirection`, `lgDirection`, and `xlDirection`. Tokens are
110
+ platform-specific: native `sm` 320 / `md` 375 / `lg` 600 / `xl` 1024; web `lg` 1024 / `xl` 1280.
111
+ The desktop floor is `isSupportedDesktopWidth({width})`: web `lg` and native `xl`, both 1024pt.
112
+ Below that floor, keep the mobile layout. Native tablets (`lg`, 600–1023pt) do not get the desktop split.
113
+
114
+ ```tsx
115
+ <Box direction="column" mdDirection="row" lgDirection="row" xlDirection="column">
116
+ ```
117
+
118
+ ## Do not
119
+
120
+ - Use raw `View` when Box props cover the need
121
+ - Use `Dimensions.get()` — prefer `useWindowDimensions` if sizing is needed
122
+ - Add a raw pixel cutoff such as 768. Use Box breakpoint props or `isSupportedDesktopWidth`
123
+ - Use `SafeAreaView` — Page handles safe areas
124
+ - Put hex colors in style when `color="primary"` works
@@ -0,0 +1,87 @@
1
+ # Theming — @terreno/ui
2
+
3
+ ## Three-layer architecture
4
+
5
+ 1. **Primitives** — raw color/spacing values (`neutral500`, `primary500`, `spacing4`)
6
+ 2. **Config** — semantic maps (`text.primary`, `surface.base`, `border.default`)
7
+ 3. **Computed theme** — resolved values consumed by components
8
+
9
+ ## TerrenoProvider
10
+
11
+ ```tsx
12
+ import {TerrenoProvider} from "@terreno/ui";
13
+
14
+ <TerrenoProvider colorScheme="system">
15
+ <App />
16
+ </TerrenoProvider>
17
+ ```
18
+
19
+ Required at the app root. Provides theme context and toast support.
20
+
21
+ ## useTheme
22
+
23
+ ```tsx
24
+ import {useTheme} from "@terreno/ui";
25
+
26
+ const {colorScheme, colorSchemeSetting, setColorScheme, theme, setTheme, setPrimitives, resetTheme} =
27
+ useTheme();
28
+ ```
29
+
30
+ ## Component color props
31
+
32
+ Use semantic props instead of hex:
33
+
34
+ ```tsx
35
+ <Box color="base"> {/* theme.surface.base */}
36
+ <Text color="primary"> {/* theme.text.primary */}
37
+ <Text color="inverted"> {/* on dark backgrounds */}
38
+ <Text color="error"> {/* error state */}
39
+ </Box>
40
+ ```
41
+
42
+ Surface colors: `base`, `primary`, `disabled`, `error`, etc.
43
+ Text colors: `primary`, `inverted`, `secondaryLight`, `error`, etc.
44
+ Border colors: `default`, `dark`, `focus`, `error`, `success`, `warning`.
45
+
46
+ ## Spacing and radius
47
+
48
+ Use numeric spacing props (0-12) on Box, Page padding, and gap:
49
+
50
+ ```tsx
51
+ <Box padding={4} gap={3} rounding="md">
52
+ ```
53
+
54
+ Radius tokens: `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `circle`.
55
+
56
+ ## Customizing theme
57
+
58
+ ```tsx
59
+ setTheme({surface: {primary: "secondary500"}});
60
+ setPrimitives({accent500: "#FF6B35"});
61
+ ```
62
+
63
+ Reset with `resetTheme()`.
64
+
65
+ ## Fonts
66
+
67
+ - Body: Nunito (`text` font family)
68
+ - Headings: Titillium Web (`title` font family)
69
+
70
+ Load fonts in root `_layout.tsx` via `useFonts` (see example-frontend).
71
+
72
+ ## Dark mode
73
+
74
+ Set `TerrenoProvider colorScheme` to `"light"`, `"dark"`, or `"system"`.
75
+ The default is deterministic `"light"`; `"system"` follows React Native's
76
+ current system scheme. `themeColorSchemeOptions` exposes those three choices
77
+ as Light, Dark, and Follow system. Call `setColorScheme("system")` to change
78
+ the choice after startup. `colorSchemeSetting` keeps the selected choice, while
79
+ `useTheme().colorScheme` is always the resolved `"light"` or `"dark"` value.
80
+ The exported `lightThemeConfig` and `darkThemeConfig` match the Flourish Health
81
+ Figma modes.
82
+
83
+ ## Do not
84
+
85
+ - Hardcode `#hex` when a theme token exists
86
+ - Use `style={{padding: 16}}` when `padding={4}` works
87
+ - Import colors from a separate constants file instead of theme props
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: update-docs
3
+ description: >-
4
+ Keep Terreno docs in sync whenever behavior, public API, architecture, or
5
+ operator workflow changes. Read architecture docs first; write Diátaxis pages
6
+ in the same slice; regenerate generated docs. Lifecycle composition: Pick when
7
+ behavior and docs change together; Roast proves docs; Brew is the final docs
8
+ gate.
9
+ ---
10
+ # Update Docs
11
+
12
+ Use whenever behavior, public API, architecture, or operator workflow changes. Docs are
13
+ the architecture source. Code implements them.
14
+
15
+ ## When to run
16
+
17
+ Always run in the same slice as the change. Skip only a pure internal refactor that does
18
+ not change APIs, UI, architecture, data flow, env/config, or operator steps. Record that
19
+ skip. Missing docs for a user-visible or architectural change is a failed slice.
20
+
21
+ ## Workflow
22
+
23
+ 1. **Read the current architecture**
24
+ - Open explanation and reference docs for the affected area before editing code or docs.
25
+ - If docs and code disagree, resolve both in this slice.
26
+
27
+ 2. **Map the change to Diátaxis**
28
+
29
+ | Change | Page |
30
+ | --- | --- |
31
+ | First-run path | `docs/tutorials/` |
32
+ | Operator task | `docs/how-to/` |
33
+ | API, props, env, commands | `docs/reference/` |
34
+ | Why the system is shaped this way | `docs/explanation/` |
35
+ | UI component | generated `docs/reference/components/` plus a demo story |
36
+
37
+ The one exception to this layout is the
38
+ [`testing plan`](../../references/testing-plan.md) spots. The e2e guide stays at
39
+ `docs/testing/e2e.md` (with any pages it links) and the manual
40
+ regression suites stay in `docs/regression/<area>.md`, or wherever the repository's
41
+ `## Testing conventions` table points. Never move them into a Diátaxis directory.
42
+
43
+ The [`user guide`](../../references/user-guide.md) is the other exception. It is
44
+ written for the app's end users, not developers: one page per feature under
45
+ `docs/user-guide/<area>/<feature>.md`, or wherever the repository's
46
+ `## User guide conventions` table points. When a change alters what a user sees or
47
+ does, update its guide page with the Diátaxis pages, in the user-guide page format.
48
+
49
+ 3. **Write the page**
50
+ - Update the existing section in place.
51
+ - Lead with the next action or canonical fact.
52
+ - Use the page's standard headings. Prefer tables.
53
+ - One minimal current example. No implementation chronology.
54
+ - Never hand-edit generated output.
55
+
56
+ 4. **Regenerate generated docs** when UI types or OpenAPI-derived pages change:
57
+
58
+ ```bash
59
+ cd ui && bun run compile && bun run types
60
+ bun run website:generate
61
+ ```
62
+
63
+ 5. **Verify**
64
+
65
+ ```bash
66
+ bun run website:build
67
+ ```
68
+
69
+ 6. **Sync agent copies** when agent-facing guidance changed:
70
+
71
+ ```bash
72
+ bun run rules
73
+ bun run skills:sync
74
+ ```
75
+
76
+ 7. **Record** every docs file created or updated in the PR `Verification` table.
77
+
78
+ ## Integration
79
+
80
+ Pick, Roast, and Brew require this skill for user-visible or architectural work.
81
+ Brew does not open or update the PR until the docs in this slice match the shipped
82
+ behavior.
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: upgrading-terreno
3
+ description: >-
4
+ Upgrade Terreno lockstep @terreno/* packages. Trigger with "upgrade Terreno",
5
+ "bump @terreno packages", "update to the latest Terreno", or "upgrade terreno version".
6
+ targets: ['*']
7
+ ---
8
+
9
+ # Upgrade Terreno
10
+
11
+ Perform a lockstep `@terreno/*` upgrade. Human-facing twin: `docs/how-to/upgrade-terreno.md`. Ordering detail: [references/ordering.md](references/ordering.md).
12
+
13
+ Do **not** duplicate Expo SDK steps. At step 6 invoke the `upgrading-expo` skill by name.
14
+
15
+ ## Preconditions (refuse, do not warn)
16
+
17
+ Stop immediately and do not mutate the tree if any of these fail:
18
+
19
+ 1. `git status --short` is **not empty** — refuse. Ask the user to commit or stash. A dirty tree has no safe rollback.
20
+ 2. The current branch is the default branch (`master` or `main`) — refuse. Create or switch to a feature branch first.
21
+ 3. Tests on this HEAD have not been shown passing — refuse. Run the app’s usual test command once so later failures are attributable to the upgrade.
22
+
23
+ ## Determine versions
24
+
25
+ 1. Prefer MCP `application_info` from `terreno-mcp-local`.
26
+ 2. Else read every `package.json` that lists `@terreno/*`.
27
+ 3. `fromVersion` = lowest installed `@terreno/*` semver. `toVersion` = user target or latest GitHub release.
28
+
29
+ ## Fetch notes
30
+
31
+ Call hosted MCP `terreno_get_upgrade_guide` with `fromVersion` and `toVersion`. Read every concatenated note. A “no bundled notes” line means **unknown**, not no-op.
32
+
33
+ ## Syncdb / RTK platform migration
34
+
35
+ If `fromVersion` is before `56.0.0-beta.2` and `toVersion` is `56.0.0-beta.2` or later, **stop**. This range crosses `@terreno/syncdb` and the RTK collection-CRUD deprecation. It is a platform migration, not a routine bump.
36
+
37
+ Offer exactly two options; do not automate the data-layer migration inside this flow:
38
+
39
+ 1. Routine lockstep bump only (stay on RTK collection hooks for now).
40
+ 2. Separate follow-up: `docs/how-to/migrate-rtk-to-syncdb.md`.
41
+
42
+ Wait for the user to pick.
43
+
44
+ ## Plan and confirm (no mutations yet)
45
+
46
+ Print, then **stop until the user confirms**:
47
+
48
+ - `fromVersion` and `toVersion`
49
+ - Notes returned (or the gap warning)
50
+ - Packages affected
51
+ - Ordered steps 1–10 below
52
+
53
+ Do not install, edit lockfiles, or regenerate the client before confirmation.
54
+
55
+ If the caller is an unattended agent whose **invoking task already names** `fromVersion`, `toVersion`, and authorizes the bump (for example Pick Task 5.1), print the same plan into the transcript and treat that task as confirmation. Do not skip the printed plan. Do not skip the stop when a human is in the loop.
56
+
57
+ ## Ordered steps (verification gate after each phase)
58
+
59
+ Match `docs/how-to/upgrade-terreno.md`. After each phase, run its gate. **If compile or tests fail, stop. Do not continue.**
60
+
61
+ Compile means a **typecheck** (`tsc --noEmit` or `bun run compile` when that script typechecks). `bun build` / bundlers that ignore TypeScript errors are not a passing gate.
62
+
63
+ 1. Clean git tree + branch (already enforced).
64
+ 2. Record current `@terreno/*` versions (`application_info` / `package.json`).
65
+ 3. `terreno_get_upgrade_guide` for the range (already fetched). Apply note migrations that are code edits **after** confirmation, in this same order.
66
+ 4. Bump **backend** packages: `@terreno/api`, `@terreno/test`, `@terreno/admin-backend`, `@terreno/blocks` (when the app lists it; `ai` and `ui` depend on it), `@terreno/ai`, `@terreno/api-health`, `@terreno/comms`, `@terreno/feature-flags`, `@terreno/mcp`. `bun install`.
67
+ 5. Backend `bun run compile` and backend tests. Gate: both pass.
68
+ 6. Expo SDK — invoke **`upgrading-expo`**. Skip only when Terreno majors do not require a new Expo (same Expo line). Gate: `npx expo-doctor` / install --fix as that skill requires; native rebuild if peers moved.
69
+ 7. Bump **frontend** packages: `@terreno/ui`, `@terreno/rtk`, `@terreno/syncdb`, `@terreno/admin-frontend`, `@terreno/admin-spa`. `bun install`.
70
+ 8. Start the **upgraded** backend. Regenerate the typed client (`bun run sdk` in the frontend).
71
+ 9. `bun run compile`, `bun run lint`, and the app tests. Gate: all pass.
72
+ 10. Run the app, log in, exercise changed screens.
73
+
74
+ ## Failure handling
75
+
76
+ Report all three:
77
+
78
+ 1. What succeeded (last passing step number).
79
+ 2. What failed (command and first error line).
80
+ 3. Rollback: `git reset --hard` on this branch, or `git checkout <pre-upgrade-sha> -- package.json bun.lock && bun install`.
81
+
82
+ On a **multi-version** jump failure: retry **version by version** (`from` → next recorded note version → …) to isolate the breaking version. Keep the failing consumer file. The first version whose typecheck fails is the isolate. Do not continue past a failed compile or test run.
83
+
84
+ ## Final report
85
+
86
+ Print `fromVersion` → `toVersion`, notes applied, packages bumped, gates that passed, and remaining human follow-ups (native store binaries, RTK migration if deferred).