opencastle 0.33.9 → 0.34.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 (112) hide show
  1. package/dist/cli/init.d.ts.map +1 -1
  2. package/dist/cli/init.js +39 -17
  3. package/dist/cli/init.js.map +1 -1
  4. package/dist/cli/stack-config.d.ts.map +1 -1
  5. package/dist/cli/stack-config.js +5 -0
  6. package/dist/cli/stack-config.js.map +1 -1
  7. package/dist/cli/types.d.ts +1 -1
  8. package/dist/cli/types.d.ts.map +1 -1
  9. package/dist/orchestrator/plugins/cloudflare/config.d.ts +3 -0
  10. package/dist/orchestrator/plugins/cloudflare/config.d.ts.map +1 -0
  11. package/dist/orchestrator/plugins/cloudflare/config.js +23 -0
  12. package/dist/orchestrator/plugins/cloudflare/config.js.map +1 -0
  13. package/dist/orchestrator/plugins/coolify/config.d.ts +3 -0
  14. package/dist/orchestrator/plugins/coolify/config.d.ts.map +1 -0
  15. package/dist/orchestrator/plugins/coolify/config.js +28 -0
  16. package/dist/orchestrator/plugins/coolify/config.js.map +1 -0
  17. package/dist/orchestrator/plugins/drizzle/config.d.ts +3 -0
  18. package/dist/orchestrator/plugins/drizzle/config.d.ts.map +1 -0
  19. package/dist/orchestrator/plugins/drizzle/config.js +15 -0
  20. package/dist/orchestrator/plugins/drizzle/config.js.map +1 -0
  21. package/dist/orchestrator/plugins/expo/config.d.ts +3 -0
  22. package/dist/orchestrator/plugins/expo/config.d.ts.map +1 -0
  23. package/dist/orchestrator/plugins/expo/config.js +23 -0
  24. package/dist/orchestrator/plugins/expo/config.js.map +1 -0
  25. package/dist/orchestrator/plugins/index.d.ts.map +1 -1
  26. package/dist/orchestrator/plugins/index.js +12 -0
  27. package/dist/orchestrator/plugins/index.js.map +1 -1
  28. package/dist/orchestrator/plugins/sentry/config.d.ts +3 -0
  29. package/dist/orchestrator/plugins/sentry/config.d.ts.map +1 -0
  30. package/dist/orchestrator/plugins/sentry/config.js +28 -0
  31. package/dist/orchestrator/plugins/sentry/config.js.map +1 -0
  32. package/dist/orchestrator/plugins/stripe/config.d.ts +3 -0
  33. package/dist/orchestrator/plugins/stripe/config.d.ts.map +1 -0
  34. package/dist/orchestrator/plugins/stripe/config.js +42 -0
  35. package/dist/orchestrator/plugins/stripe/config.js.map +1 -0
  36. package/dist/orchestrator/plugins/types.d.ts +1 -1
  37. package/dist/orchestrator/plugins/types.d.ts.map +1 -1
  38. package/package.json +1 -1
  39. package/src/cli/init.ts +43 -22
  40. package/src/cli/stack-config.ts +5 -0
  41. package/src/cli/types.ts +1 -1
  42. package/src/dashboard/dist/data/convoys/demo-api-v2.json +3 -3
  43. package/src/dashboard/dist/data/convoys/demo-auth-revamp.json +4 -4
  44. package/src/dashboard/dist/data/convoys/demo-dashboard-ui.json +12 -12
  45. package/src/dashboard/dist/data/convoys/demo-data-pipeline.json +3 -3
  46. package/src/dashboard/dist/data/convoys/demo-deploy-ci.json +1 -1
  47. package/src/dashboard/dist/data/convoys/demo-docs-update.json +3 -3
  48. package/src/dashboard/dist/data/convoys/demo-perf-opt.json +4 -4
  49. package/src/dashboard/node_modules/.vite/deps/_metadata.json +6 -6
  50. package/src/dashboard/public/data/convoys/demo-api-v2.json +3 -3
  51. package/src/dashboard/public/data/convoys/demo-auth-revamp.json +4 -4
  52. package/src/dashboard/public/data/convoys/demo-dashboard-ui.json +12 -12
  53. package/src/dashboard/public/data/convoys/demo-data-pipeline.json +3 -3
  54. package/src/dashboard/public/data/convoys/demo-deploy-ci.json +1 -1
  55. package/src/dashboard/public/data/convoys/demo-docs-update.json +3 -3
  56. package/src/dashboard/public/data/convoys/demo-perf-opt.json +4 -4
  57. package/src/orchestrator/customizations/agents/skill-matrix.json +24 -4
  58. package/src/orchestrator/customizations/agents/skill-matrix.md +5 -0
  59. package/src/orchestrator/plugins/cloudflare/SKILL.md +111 -0
  60. package/src/orchestrator/plugins/cloudflare/config.ts +24 -0
  61. package/src/orchestrator/plugins/cloudflare/references/deployment.md +147 -0
  62. package/src/orchestrator/plugins/cloudflare/references/storage.md +118 -0
  63. package/src/orchestrator/plugins/cloudflare/references/workers.md +135 -0
  64. package/src/orchestrator/plugins/convex/SKILL.md +62 -20
  65. package/src/orchestrator/plugins/convex/references/auth-auth0.md +116 -0
  66. package/src/orchestrator/plugins/convex/references/auth-clerk.md +113 -0
  67. package/src/orchestrator/plugins/convex/references/auth-convex-auth.md +143 -0
  68. package/src/orchestrator/plugins/convex/references/auth-setup.md +87 -0
  69. package/src/orchestrator/plugins/convex/references/auth-workos.md +114 -0
  70. package/src/orchestrator/plugins/convex/references/components-advanced.md +134 -0
  71. package/src/orchestrator/plugins/convex/references/components.md +171 -0
  72. package/src/orchestrator/plugins/convex/references/function-budget.md +232 -0
  73. package/src/orchestrator/plugins/convex/references/hot-path-rules.md +371 -0
  74. package/src/orchestrator/plugins/convex/references/migrations-component.md +170 -0
  75. package/src/orchestrator/plugins/convex/references/migrations.md +259 -0
  76. package/src/orchestrator/plugins/convex/references/occ-conflicts.md +126 -0
  77. package/src/orchestrator/plugins/convex/references/performance-audit.md +80 -0
  78. package/src/orchestrator/plugins/convex/references/quickstart.md +176 -0
  79. package/src/orchestrator/plugins/convex/references/subscription-cost.md +252 -0
  80. package/src/orchestrator/plugins/coolify/SKILL.md +134 -0
  81. package/src/orchestrator/plugins/coolify/config.ts +29 -0
  82. package/src/orchestrator/plugins/coolify/references/applications.md +65 -0
  83. package/src/orchestrator/plugins/coolify/references/ci-cd-webhooks.md +73 -0
  84. package/src/orchestrator/plugins/coolify/references/databases-services.md +57 -0
  85. package/src/orchestrator/plugins/coolify/references/docker-compose.md +121 -0
  86. package/src/orchestrator/plugins/coolify/references/infrastructure.md +77 -0
  87. package/src/orchestrator/plugins/drizzle/SKILL.md +123 -0
  88. package/src/orchestrator/plugins/drizzle/config.ts +16 -0
  89. package/src/orchestrator/plugins/drizzle/references/migrations.md +112 -0
  90. package/src/orchestrator/plugins/drizzle/references/query-patterns.md +127 -0
  91. package/src/orchestrator/plugins/drizzle/references/schema-patterns.md +105 -0
  92. package/src/orchestrator/plugins/expo/SKILL.md +114 -0
  93. package/src/orchestrator/plugins/expo/config.ts +24 -0
  94. package/src/orchestrator/plugins/expo/references/eas-build.md +73 -0
  95. package/src/orchestrator/plugins/expo/references/native-modules.md +71 -0
  96. package/src/orchestrator/plugins/expo/references/routing.md +83 -0
  97. package/src/orchestrator/plugins/index.ts +12 -0
  98. package/src/orchestrator/plugins/linear/SKILL.md +21 -3
  99. package/src/orchestrator/plugins/sentry/SKILL.md +94 -0
  100. package/src/orchestrator/plugins/sentry/config.ts +29 -0
  101. package/src/orchestrator/plugins/sentry/references/error-patterns.md +112 -0
  102. package/src/orchestrator/plugins/sentry/references/performance.md +66 -0
  103. package/src/orchestrator/plugins/sentry/references/sdk-setup.md +108 -0
  104. package/src/orchestrator/plugins/stripe/SKILL.md +138 -0
  105. package/src/orchestrator/plugins/stripe/config.ts +43 -0
  106. package/src/orchestrator/plugins/stripe/references/api-patterns.md +57 -0
  107. package/src/orchestrator/plugins/stripe/references/projects-setup.md +30 -0
  108. package/src/orchestrator/plugins/stripe/references/upgrade-guide.md +105 -0
  109. package/src/orchestrator/plugins/types.ts +1 -1
  110. package/src/orchestrator/skills/backbone-scaffolding/EXAMPLES.md +1 -1
  111. package/src/orchestrator/skills/backbone-scaffolding/SKILL.md +32 -16
  112. package/src/orchestrator/plugins/convex/REFERENCE.md +0 -9
@@ -0,0 +1,114 @@
1
+ ---
2
+ name: expo-development
3
+ description: "Scaffolds Expo/React Native apps, configures EAS Build profiles, manages native modules via CNG, sets up Expo Router navigation, and uses EAS Update for OTA deployments. Use when creating React Native apps with Expo, configuring EAS builds, setting up Expo Router, managing native modules, or deploying OTA updates."
4
+ ---
5
+
6
+ # Expo Development
7
+
8
+ ## Topic Routing
9
+
10
+ Read the matching reference before writing code for any of these topics:
11
+
12
+ | Topic | Reference |
13
+ |-------|-----------|
14
+ | EAS Build & deployment | `references/eas-build.md` |
15
+ | Expo Router & navigation | `references/routing.md` |
16
+ | Native modules & CNG | `references/native-modules.md` |
17
+
18
+ ## Critical Rules
19
+
20
+ **Project Setup**
21
+ - Use `npx create-expo-app@latest` for new projects — always target the latest SDK
22
+ - Use Continuous Native Generation (CNG) — never eject; prefer `npx expo prebuild` when native config is needed
23
+ - Configure `app.json` / `app.config.ts` for all project metadata — never modify native projects directly when using CNG
24
+
25
+ **Expo Router**
26
+ - File-based routing in `app/` — define `_layout.tsx` in each directory for `<Stack>`, `<Tabs>`, or `<Drawer>`
27
+ - Use `Link` for declarative navigation, `useRouter()` for imperative — configure `scheme` in app.json for deep links
28
+
29
+ **EAS Build**
30
+ - Define `development` / `preview` / `production` profiles in `eas.json`
31
+ - Preview: `"distribution": "internal"` + `"channel": "preview"` — Development: add `"developmentClient": true`
32
+ - Production: `"channel": "production"` + `"autoIncrement": true`
33
+
34
+ **EAS Update (OTA)**
35
+ - `eas update --channel production` for JS-only changes — no app store review
36
+ - Set `"runtimeVersion": { "policy": "fingerprint" }` — mismatched runtimeVersion forces a new binary build
37
+
38
+ **Native Modules**
39
+ - Prefer Expo SDK packages over community alternatives — install with `npx expo install` for version resolution
40
+ - Config plugins (`app.plugin.js`) modify native projects at prebuild time — never edit `ios/` or `android/` directly
41
+ - Custom native code: `npx create-expo-module` scaffolds Swift + Kotlin module
42
+
43
+ **Security**
44
+ - Store API keys and secrets in EAS Secrets — never hardcode in `app.json` or source code
45
+ - Use `expo-secure-store` for device-side secret storage
46
+
47
+ ## Workflow: New Project → Build → Deploy
48
+
49
+ 1. **Scaffold** — `npx create-expo-app@latest my-app --template default@sdk-55`
50
+ 2. **Verify local** — `cd my-app && npx expo start` → confirm app loads in simulator
51
+ 3. **Init EAS** — `eas init && eas build:configure` → creates `eas.json` with profiles
52
+ 4. **Build preview** — `eas build --profile preview --platform ios`
53
+ 5. **Check status** — `eas build:list` → wait for `finished` status; if `errored` → `eas build:view <id>` → fix config → rebuild
54
+ 6. **Test** — install preview build on device via QR code or TestFlight
55
+ 7. **Build production** — `eas build --profile production --platform all`
56
+ 8. **Submit** — `eas submit --platform ios && eas submit --platform android`
57
+
58
+ ## Workflow: OTA Update
59
+
60
+ 1. **Make JS-only changes** — modify components, styles, or logic (no native module changes)
61
+ 2. **Deploy** — `eas update --channel production --message "Fix: button alignment"`
62
+ 3. **Verify** — `eas update:list` → confirm update published with correct `runtimeVersion`
63
+ 4. **Rollback if needed** — `eas update:republish --group <previous-group-id>`
64
+
65
+ > If `runtimeVersion` mismatch: a new binary build is required — OTA cannot bridge native changes.
66
+
67
+ ## Build Failure Recovery
68
+
69
+ ```
70
+ Build failed → check logs
71
+ ├── "Provisioning profile" error → eas credentials → fix iOS signing
72
+ ├── "SDK version mismatch" → npx expo install --fix → rebuild
73
+ ├── "Metro bundler" error → check JS syntax → npx expo start to reproduce
74
+ ├── "Native module" error → npx expo prebuild --clean → verify config plugins
75
+ └── "EAS secret" missing → eas secret:create → rebuild
76
+ ```
77
+
78
+ ## Screen with Expo Router
79
+
80
+ ```tsx
81
+ // app/user/[id].tsx
82
+ import { useLocalSearchParams } from 'expo-router';
83
+ import { View, Text } from 'react-native';
84
+
85
+ export default function UserScreen() {
86
+ const { id } = useLocalSearchParams<{ id: string }>();
87
+ return (
88
+ <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
89
+ <Text>User {id}</Text>
90
+ </View>
91
+ );
92
+ }
93
+ ```
94
+
95
+ ## EAS Build Profile
96
+
97
+ ```json
98
+ {
99
+ "build": {
100
+ "development": {
101
+ "developmentClient": true,
102
+ "distribution": "internal"
103
+ },
104
+ "preview": {
105
+ "distribution": "internal",
106
+ "channel": "preview"
107
+ },
108
+ "production": {
109
+ "channel": "production",
110
+ "autoIncrement": true
111
+ }
112
+ }
113
+ }
114
+ ```
@@ -0,0 +1,24 @@
1
+ import type { PluginConfig } from '../types.js';
2
+
3
+ export const config: PluginConfig = {
4
+ id: 'expo',
5
+ name: 'Expo',
6
+ category: 'tech',
7
+ subCategory: 'framework',
8
+ label: 'Expo',
9
+ hint: 'React Native framework with EAS builds and OTA updates',
10
+ skillName: 'expo-development',
11
+ mcpServerKey: 'Expo',
12
+ mcpConfig: {
13
+ type: 'http',
14
+ url: 'https://mcp.expo.dev/mcp',
15
+ },
16
+ authType: 'oauth',
17
+ envVars: [],
18
+ agentToolMap: {
19
+ 'developer': ['search_documentation', 'read_documentation', 'add_library'],
20
+ 'testing-expert': ['automation_take_screenshot', 'automation_tap', 'automation_find_view'],
21
+ },
22
+ docsUrl: null,
23
+ officialDocs: 'https://docs.expo.dev/',
24
+ };
@@ -0,0 +1,73 @@
1
+ # EAS Build & Deployment
2
+
3
+ ## Build Profiles
4
+
5
+ Define in `eas.json` at project root:
6
+
7
+ - **development** — installs `expo-dev-client`, `distribution: internal`
8
+ - **preview** — for TestFlight/internal testing, `distribution: internal`
9
+ - **production** — for app store submission, `autoIncrement: true`
10
+
11
+ ## Commands
12
+
13
+ ```bash
14
+ # Build for iOS
15
+ eas build --platform ios --profile preview
16
+
17
+ # Build for Android
18
+ eas build --platform android --profile preview
19
+
20
+ # Submit to App Store
21
+ eas submit --platform ios
22
+
23
+ # Submit to Google Play
24
+ eas submit --platform android
25
+ ```
26
+
27
+ ## EAS Update (OTA)
28
+
29
+ ```bash
30
+ # Deploy JS-only update
31
+ eas update --channel production --message "Fix button alignment"
32
+
33
+ # Check update status
34
+ eas update:list
35
+ ```
36
+
37
+ ## Runtime Version Policy
38
+
39
+ Use fingerprint policy in `app.json`:
40
+
41
+ ```json
42
+ {
43
+ "expo": {
44
+ "runtimeVersion": {
45
+ "policy": "fingerprint"
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ This auto-detects binary-incompatible changes and forces a new build.
52
+
53
+ ## EAS Workflows
54
+
55
+ Define CI/CD in `.eas/workflows/`:
56
+
57
+ ```yaml
58
+ name: build-and-deploy
59
+ on:
60
+ push:
61
+ branches: [main]
62
+ jobs:
63
+ build:
64
+ type: build
65
+ params:
66
+ platform: ios
67
+ profile: production
68
+ submit:
69
+ type: submit
70
+ needs: [build]
71
+ params:
72
+ platform: ios
73
+ ```
@@ -0,0 +1,71 @@
1
+ # Native Modules & CNG
2
+
3
+ ## Continuous Native Generation (CNG)
4
+
5
+ CNG regenerates native projects from `app.json` config:
6
+
7
+ ```bash
8
+ # Generate native projects (don't commit these)
9
+ npx expo prebuild
10
+
11
+ # Clean and regenerate
12
+ npx expo prebuild --clean
13
+ ```
14
+
15
+ Add `ios/` and `android/` to `.gitignore` when using CNG.
16
+
17
+ ## Installing Expo SDK Packages
18
+
19
+ Always use `npx expo install` — it resolves compatible versions:
20
+
21
+ ```bash
22
+ npx expo install expo-camera expo-location expo-notifications
23
+ ```
24
+
25
+ ## Config Plugins
26
+
27
+ Modify native projects at prebuild time without manual edits:
28
+
29
+ ```js
30
+ // app.plugin.js
31
+ const { withInfoPlist } = require('@expo/config-plugins');
32
+
33
+ module.exports = function myPlugin(config) {
34
+ return withInfoPlist(config, (config) => {
35
+ config.modResults.NSCameraUsageDescription = 'App needs camera access';
36
+ return config;
37
+ });
38
+ };
39
+ ```
40
+
41
+ Register in `app.json`:
42
+
43
+ ```json
44
+ {
45
+ "expo": {
46
+ "plugins": ["./app.plugin.js"]
47
+ }
48
+ }
49
+ ```
50
+
51
+ ## Creating Custom Modules
52
+
53
+ ```bash
54
+ npx create-expo-module my-native-module
55
+ ```
56
+
57
+ This scaffolds a module with iOS (Swift) and Android (Kotlin) native code.
58
+
59
+ ## Expo SDK Package Selection
60
+
61
+ | Need | Package |
62
+ |------|---------|
63
+ | Camera | `expo-camera` |
64
+ | Location | `expo-location` |
65
+ | Push notifications | `expo-notifications` |
66
+ | File system | `expo-file-system` |
67
+ | Secure storage | `expo-secure-store` |
68
+ | Auth | `expo-auth-session` |
69
+ | SQLite | `expo-sqlite` |
70
+ | Haptics | `expo-haptics` |
71
+ | Image picker | `expo-image-picker` |
@@ -0,0 +1,83 @@
1
+ # Expo Router & Navigation
2
+
3
+ ## File-Based Routing
4
+
5
+ Routes map to files in the `app/` directory:
6
+
7
+ | File | Route |
8
+ |------|-------|
9
+ | `app/index.tsx` | `/` |
10
+ | `app/about.tsx` | `/about` |
11
+ | `app/user/[id].tsx` | `/user/:id` |
12
+ | `app/(tabs)/_layout.tsx` | Tab navigator |
13
+ | `app/(auth)/login.tsx` | `/login` (grouped) |
14
+
15
+ ## Layout Files
16
+
17
+ Every directory can have a `_layout.tsx` that wraps its children:
18
+
19
+ ```tsx
20
+ import { Stack } from 'expo-router';
21
+
22
+ export default function RootLayout() {
23
+ return (
24
+ <Stack>
25
+ <Stack.Screen name="index" options={{ title: 'Home' }} />
26
+ <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
27
+ </Stack>
28
+ );
29
+ }
30
+ ```
31
+
32
+ ## Navigation
33
+
34
+ ```tsx
35
+ import { Link, useRouter } from 'expo-router';
36
+
37
+ // Declarative
38
+ <Link href="/user/123">View Profile</Link>
39
+
40
+ // Imperative
41
+ const router = useRouter();
42
+ router.push('/user/123');
43
+ router.replace('/home');
44
+ router.back();
45
+ ```
46
+
47
+ ## Deep Linking
48
+
49
+ Configure in `app.json`:
50
+
51
+ ```json
52
+ {
53
+ "expo": {
54
+ "scheme": "myapp",
55
+ "web": {
56
+ "bundler": "metro"
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ URLs like `myapp://user/123` automatically resolve to `app/user/[id].tsx`.
63
+
64
+ ## Tab Navigation
65
+
66
+ ```tsx
67
+ import { Tabs } from 'expo-router';
68
+ import { Ionicons } from '@expo/vector-icons';
69
+
70
+ export default function TabLayout() {
71
+ return (
72
+ <Tabs>
73
+ <Tabs.Screen
74
+ name="index"
75
+ options={{
76
+ title: 'Home',
77
+ tabBarIcon: ({ color }) => <Ionicons name="home" color={color} size={24} />,
78
+ }}
79
+ />
80
+ </Tabs>
81
+ );
82
+ }
83
+ ```
@@ -21,8 +21,14 @@ import { config as playwright } from './playwright/config.js';
21
21
  import { config as vitest } from './vitest/config.js';
22
22
  import { config as figma } from './figma/config.js';
23
23
  import { config as resend } from './resend/config.js';
24
+ import { config as stripe } from './stripe/config.js';
24
25
  import { config as nextjs } from './nextjs/config.js';
25
26
  import { config as astro } from './astro/config.js';
27
+ import { config as sentry } from './sentry/config.js';
28
+ import { config as drizzle } from './drizzle/config.js';
29
+ import { config as cloudflare } from './cloudflare/config.js';
30
+ import { config as coolify } from './coolify/config.js';
31
+ import { config as expo } from './expo/config.js';
26
32
 
27
33
  export type { PluginConfig, McpServerConfig, McpInput, EnvVarRequirement } from './types.js';
28
34
 
@@ -44,8 +50,14 @@ export const PLUGINS: Record<string, PluginConfig> = {
44
50
  vitest,
45
51
  figma,
46
52
  resend,
53
+ stripe,
47
54
  nextjs,
48
55
  astro,
56
+ sentry,
57
+ drizzle,
58
+ cloudflare,
59
+ coolify,
60
+ expo,
49
61
  linear,
50
62
  jira,
51
63
  trello,
@@ -7,7 +7,7 @@ description: "Creates and names Linear issues, assigns labels and priorities, ma
7
7
 
8
8
  # Task Management with Linear
9
9
 
10
- For project-specific team ID, workflow state UUIDs, and label UUIDs, see [tracker-config.md](../../.opencastle/project/tracker-config.md).
10
+ For project-specific team ID, workflow state UUIDs, and label UUIDs, see [tracker-config.md](../../.opencastle/project/tracker-config.md). For status transitions, follow the **Status Update Procedure** section below.
11
11
 
12
12
  ## MCP Tool Examples
13
13
 
@@ -16,8 +16,8 @@ For project-specific team ID, workflow state UUIDs, and label UUIDs, see [tracke
16
16
  { "teamId": "TEAM_UUID", "title": "[UI] Build PriceRangeFilter", "description": "Objective: ...\nFiles: ...\nAC: ...", "labelIds": ["LABEL_UUID"], "priority": 2 }
17
17
  // → { "id": "TAS-42", "url": "https://linear.app/team/TAS-42" }
18
18
 
19
- // Update issue status
20
- { "issueId": "TAS-42", "stateId": "IN_PROGRESS_UUID" }
19
+ // Update issue status (see Status Update Procedure)
20
+ { "issueId": "TAS-42", "stateId": "<UUID from tracker-config.md>" }
21
21
 
22
22
  // Search issues
23
23
  { "query": "is:open assignee:me", "teamId": "TEAM_UUID" }
@@ -76,3 +76,21 @@ Group related issues under a Linear project; issues track individual subtasks.
76
76
  6. On completion: verify all issues Done/Cancelled, run build/lint/test.
77
77
 
78
78
  If creation fails: check team ID and state UUIDs in [tracker-config.md](../../.opencastle/project/tracker-config.md); retry once. If board state is inconsistent on resume: re-read all issue statuses before proceeding.
79
+
80
+ ## Status Update Procedure
81
+
82
+ > ⚠️ `update_issue` requires a workflow state **UUID** — passing a name like `"In Progress"` always fails with `stateId must be a UUID`.
83
+
84
+ 1. **Read UUIDs from [tracker-config.md](../../.opencastle/project/tracker-config.md)** before any status transition. Names returned by `list_issues`/`get_issue` are display-only, not valid `stateId` values.
85
+ 2. **If `tracker-config.md` has no state UUIDs**, skip status updates and log a warning.
86
+
87
+ ```json
88
+ // ✅ UUID from tracker-config.md
89
+ { "issueId": "TAS-42", "stateId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }
90
+ // ❌ FAILS — name, not UUID
91
+ { "issueId": "TAS-42", "status": "In Progress" }
92
+ ```
93
+
94
+ ## One-Time Setup: Discover Workflow State UUIDs
95
+
96
+ If `tracker-config.md` lacks state UUIDs, ask the user to populate them from Linear Settings → Teams → Workflow (UUID in browser URL per state) or via the GraphQL `workflowStates { nodes { id name } }` query.
@@ -0,0 +1,94 @@
1
+ ---
2
+ name: sentry-monitoring
3
+ description: "Sentry error monitoring, SDK initialization, performance tracing, source maps, session replay, and release tracking. Use when adding Sentry to a project, capturing errors with context, setting up distributed tracing, configuring source maps, or debugging production issues."
4
+ ---
5
+
6
+ # Sentry Monitoring
7
+
8
+ ## Topic Routing
9
+
10
+ Read the matching reference before writing code for any of these topics:
11
+
12
+ | Topic | Reference |
13
+ |-------|-----------|
14
+ | SDK setup & initialization | `references/sdk-setup.md` |
15
+ | Error capture & context enrichment | `references/error-patterns.md` |
16
+ | Performance tracing & spans | `references/performance.md` |
17
+
18
+ ## Critical Rules
19
+
20
+ **SDK Initialization**
21
+ - Next.js requires separate init files: `instrumentation-client.ts` (browser), `sentry.server.config.ts` (Node), `sentry.edge.config.ts` (edge runtime)
22
+ - Call `Sentry.init()` as early as possible — before any other imports that might throw
23
+ - Set `sendDefaultPii: true` to capture authenticated user context automatically
24
+ - Use `npx @sentry/wizard@latest -i nextjs` for guided setup; it creates all init files and patches `next.config.ts`
25
+
26
+ **Error Capture**
27
+ - Use `Sentry.captureException(err)` for caught errors; uncaught errors are captured automatically
28
+ - Enrich errors with `Sentry.setContext()`, `Sentry.setTag()`, `Sentry.setUser()` before or inside the capture call
29
+ - Add breadcrumbs with `Sentry.addBreadcrumb()` to build a debugging trail leading to the error
30
+ - Override fingerprinting via `event.fingerprint` in `beforeSend` to control issue grouping
31
+
32
+ **Performance**
33
+ - Set `tracesSampleRate: 1.0` in development, `0.1` (or lower) in production to control costs
34
+ - Use `Sentry.startSpan()` for custom instrumentation around expensive operations
35
+ - Core Web Vitals are captured automatically by the browser SDK — no extra config needed
36
+
37
+ **Source Maps**
38
+ - Wrap `next.config.ts` with `withSentryConfig()` to auto-upload source maps at build time
39
+ - Set `SENTRY_AUTH_TOKEN` in CI environment; generate at Organization Settings → Auth Tokens
40
+ - Enable `tunnelRoute: '/monitoring'` to proxy Sentry requests through your server and avoid ad-blockers
41
+
42
+ **Releases & Replay**
43
+ - Associate commits by setting `SENTRY_RELEASE` or letting the wizard configure it automatically
44
+ - Enable Session Replay with `replaysSessionSampleRate` and `replaysOnErrorSampleRate` for visual debugging
45
+ - Never expose the DSN in server-side code that handles secrets — DSN is safe for client-side use only
46
+
47
+ ## Next.js Init Pattern
48
+
49
+ ```typescript
50
+ // instrumentation-client.ts (browser) — mirrors sentry.server.config.ts / sentry.edge.config.ts
51
+ import * as Sentry from '@sentry/nextjs';
52
+
53
+ Sentry.init({
54
+ dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
55
+ tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0,
56
+ sendDefaultPii: true,
57
+ // Browser-only options:
58
+ replaysSessionSampleRate: 0.1,
59
+ replaysOnErrorSampleRate: 1.0,
60
+ integrations: [Sentry.replayIntegration()],
61
+ });
62
+ ```
63
+
64
+ ## Capture with Context
65
+
66
+ ```typescript
67
+ import * as Sentry from '@sentry/nextjs';
68
+
69
+ try {
70
+ await processOrder(orderId);
71
+ } catch (err) {
72
+ Sentry.withScope((scope) => {
73
+ scope.setTag('action', 'process-order');
74
+ scope.setContext('order', { orderId, userId });
75
+ Sentry.captureException(err);
76
+ });
77
+ throw err; // re-throw after capturing
78
+ }
79
+ ```
80
+
81
+ ## Reference Files
82
+
83
+ - `references/sdk-setup.md` — Init patterns for Next.js, React, Node.js; wizard usage; config options
84
+ - `references/error-patterns.md` — captureException, context enrichment, breadcrumbs, fingerprinting, error boundaries
85
+ - `references/performance.md` — tracesSampleRate, startSpan, distributed tracing, custom instrumentation
86
+
87
+ ## Quick Workflow: Add Sentry to a Next.js app
88
+ 1. Run `npx @sentry/wizard@latest -i nextjs` — select your Sentry org and project when prompted
89
+ 2. Wizard creates `instrumentation-client.ts`, `sentry.server.config.ts`, `sentry.edge.config.ts`, and patches `next.config.ts`
90
+ 3. Set `NEXT_PUBLIC_SENTRY_DSN` in `.env.local` and `SENTRY_AUTH_TOKEN` in `.env.local` (and CI secrets)
91
+ 4. Adjust `tracesSampleRate` in each init file — verify Sentry receives a test event before merging
92
+ 5. Add `global-error.tsx` and call `Sentry.captureException` inside it for App Router error boundaries
93
+ - **If events not appearing:** check DSN matches the project → verify `tunnelRoute` is configured → confirm `SENTRY_AUTH_TOKEN` is set for source map uploads
94
+ - **If source maps missing:** confirm `withSentryConfig` wraps the Next.js config → check build logs for upload errors
@@ -0,0 +1,29 @@
1
+ import type { PluginConfig } from '../types.js';
2
+
3
+ export const config: PluginConfig = {
4
+ id: 'sentry',
5
+ name: 'Sentry',
6
+ category: 'tech',
7
+ subCategory: 'observability',
8
+ label: 'Sentry',
9
+ hint: 'Error monitoring, performance tracing, and observability',
10
+ skillName: 'sentry-monitoring',
11
+ mcpServerKey: 'Sentry',
12
+ mcpConfig: {
13
+ type: 'stdio',
14
+ command: 'npx',
15
+ args: ['@sentry/mcp-server@latest'],
16
+ },
17
+ authType: 'env-token',
18
+ envVars: [
19
+ { name: 'SENTRY_ACCESS_TOKEN', hint: 'Create at Settings \u2192 Auth Tokens in sentry.io' },
20
+ ],
21
+ agentToolMap: {
22
+ 'developer': ['search_errors', 'get_issue_details', 'search_issues', 'create_sentry_issue'],
23
+ 'devops-expert': ['list_projects', 'get_project_stats', 'search_errors'],
24
+ 'security-expert': ['search_errors', 'get_issue_details', 'list_projects'],
25
+ },
26
+ docsUrl: null,
27
+ officialDocs: 'https://docs.sentry.io/',
28
+ mcpPackage: '@sentry/mcp-server',
29
+ };
@@ -0,0 +1,112 @@
1
+ # Sentry Error Patterns
2
+
3
+ ## Basic Capture
4
+
5
+ ```typescript
6
+ import * as Sentry from '@sentry/nextjs';
7
+
8
+ // Caught error
9
+ try {
10
+ await riskyOperation();
11
+ } catch (err) {
12
+ Sentry.captureException(err);
13
+ }
14
+
15
+ // Custom message
16
+ Sentry.captureMessage('Payment declined', 'warning');
17
+ ```
18
+
19
+ ## Context Enrichment
20
+
21
+ ```typescript
22
+ // Set user (persists for subsequent events in the session)
23
+ Sentry.setUser({ id: user.id, email: user.email });
24
+
25
+ // Structured context object
26
+ Sentry.setContext('order', { orderId, amount, currency });
27
+
28
+ // Searchable tag
29
+ Sentry.setTag('tenant', organizationSlug);
30
+
31
+ // Scoped enrichment (one-off, does not persist)
32
+ Sentry.withScope((scope) => {
33
+ scope.setTag('action', 'checkout');
34
+ scope.setContext('cart', { itemCount, total });
35
+ scope.setLevel('fatal');
36
+ Sentry.captureException(err);
37
+ });
38
+ ```
39
+
40
+ ## Breadcrumbs
41
+
42
+ ```typescript
43
+ Sentry.addBreadcrumb({
44
+ category: 'payment',
45
+ message: 'User clicked pay button',
46
+ level: 'info',
47
+ data: { amount: 99.99 },
48
+ });
49
+ ```
50
+
51
+ ## Custom Fingerprinting
52
+
53
+ ```typescript
54
+ // sentry.client.config.ts
55
+ Sentry.init({
56
+ dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
57
+ beforeSend(event) {
58
+ // Group all DB timeout errors together regardless of query
59
+ if (event.exception?.values?.[0]?.value?.includes('timeout')) {
60
+ event.fingerprint = ['database-timeout'];
61
+ }
62
+ return event;
63
+ },
64
+ });
65
+ ```
66
+
67
+ ## Error Boundaries (React / Next.js App Router)
68
+
69
+ ```typescript
70
+ // app/global-error.tsx
71
+ 'use client';
72
+ import * as Sentry from '@sentry/nextjs';
73
+ import { useEffect } from 'react';
74
+
75
+ export default function GlobalError({ error, reset }: { error: Error; reset: () => void }) {
76
+ useEffect(() => {
77
+ Sentry.captureException(error);
78
+ }, [error]);
79
+
80
+ return (
81
+ <html>
82
+ <body>
83
+ <h2>Something went wrong</h2>
84
+ <button onClick={reset}>Try again</button>
85
+ </body>
86
+ </html>
87
+ );
88
+ }
89
+ ```
90
+
91
+ ### Wrapping components
92
+
93
+ ```typescript
94
+ import * as Sentry from '@sentry/react';
95
+
96
+ export const SafeWidget = Sentry.withErrorBoundary(MyWidget, {
97
+ fallback: <p>This widget failed to load</p>,
98
+ });
99
+ ```
100
+
101
+ ## Server Action Instrumentation
102
+
103
+ ```typescript
104
+ 'use server';
105
+ import * as Sentry from '@sentry/nextjs';
106
+
107
+ export async function submitForm(data: FormData) {
108
+ return await Sentry.withServerActionInstrumentation('submitForm', async () => {
109
+ // Your server action logic here
110
+ });
111
+ }
112
+ ```