agentic-team 0.0.0-stage → 6.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.
Files changed (118) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +184 -2
  3. package/bin/build-template.js +208 -0
  4. package/bin/index.js +1139 -0
  5. package/package.json +41 -4
  6. package/template/.claude-plugin/plugin.json +10 -0
  7. package/template/.orchestra/README.md +401 -0
  8. package/template/.orchestra/blueprints/README.md +87 -0
  9. package/template/.orchestra/blueprints/api-only.md +46 -0
  10. package/template/.orchestra/blueprints/component-crud-resource.md +25 -0
  11. package/template/.orchestra/blueprints/saas-starter.md +69 -0
  12. package/template/.orchestra/config.yml +277 -0
  13. package/template/.orchestra/roles/orchestrator.md +105 -0
  14. package/template/.orchestra/roles/product-manager.md +438 -0
  15. package/template/.orchestra/scripts/compact-diff.awk +45 -0
  16. package/template/.orchestra/stacks/README.md +81 -0
  17. package/template/.orchestra/stacks/_lib/common.sh +3095 -0
  18. package/template/.orchestra/stacks/_repo/setup.sh +1109 -0
  19. package/template/.orchestra/stacks/backend-hono/claude/commands/endpoint.md +13 -0
  20. package/template/.orchestra/stacks/backend-hono/claude/skills/api-endpoint/SKILL.md +111 -0
  21. package/template/.orchestra/stacks/backend-hono/claude/skills/testing/SKILL.md +75 -0
  22. package/template/.orchestra/stacks/backend-hono/setup.sh +5945 -0
  23. package/template/.orchestra/stacks/backend-hono/stack.md +195 -0
  24. package/template/.orchestra/stacks/mobile-android-native/claude/commands/component.md +13 -0
  25. package/template/.orchestra/stacks/mobile-android-native/claude/skills/design-component/SKILL.md +58 -0
  26. package/template/.orchestra/stacks/mobile-android-native/setup.sh +607 -0
  27. package/template/.orchestra/stacks/mobile-android-native/stack.md +138 -0
  28. package/template/.orchestra/stacks/mobile-expo/claude/commands/component.md +12 -0
  29. package/template/.orchestra/stacks/mobile-expo/claude/skills/design-component/SKILL.md +92 -0
  30. package/template/.orchestra/stacks/mobile-expo/setup.sh +470 -0
  31. package/template/.orchestra/stacks/mobile-expo/stack.md +141 -0
  32. package/template/.orchestra/stacks/mobile-ios-native/claude/commands/component.md +12 -0
  33. package/template/.orchestra/stacks/mobile-ios-native/claude/skills/design-component/SKILL.md +58 -0
  34. package/template/.orchestra/stacks/mobile-ios-native/setup.sh +468 -0
  35. package/template/.orchestra/stacks/mobile-ios-native/stack.md +130 -0
  36. package/template/.orchestra/stacks/web-nextjs/claude/commands/component.md +12 -0
  37. package/template/.orchestra/stacks/web-nextjs/claude/skills/design-component/SKILL.md +100 -0
  38. package/template/.orchestra/stacks/web-nextjs/claude/skills/design-tokens/SKILL.md +61 -0
  39. package/template/.orchestra/stacks/web-nextjs/setup.sh +128 -0
  40. package/template/.orchestra/stacks/web-nextjs/stack.md +170 -0
  41. package/template/.orchestra/stacks/web-vite-react/claude/commands/component.md +12 -0
  42. package/template/.orchestra/stacks/web-vite-react/claude/skills/design-component/SKILL.md +100 -0
  43. package/template/.orchestra/stacks/web-vite-react/claude/skills/design-tokens/SKILL.md +61 -0
  44. package/template/.orchestra/stacks/web-vite-react/setup.sh +185 -0
  45. package/template/.orchestra/stacks/web-vite-react/stack.md +177 -0
  46. package/template/.orchestra/trackers/github.sh +467 -0
  47. package/template/CLAUDE.md +54 -0
  48. package/template/agents/architect.md +83 -0
  49. package/template/agents/engineer-high.md +17 -0
  50. package/template/agents/engineer-low.md +17 -0
  51. package/template/agents/engineer-max.md +17 -0
  52. package/template/agents/engineer-medium.md +17 -0
  53. package/template/agents/engineer-xhigh.md +17 -0
  54. package/template/agents/lead.md +870 -0
  55. package/template/agents/milestone-reviewer.md +63 -0
  56. package/template/agents/orchestrator.md +105 -0
  57. package/template/agents/product-manager.md +438 -0
  58. package/template/agents/reviewer.md +301 -0
  59. package/template/agents/scaffolder.md +180 -0
  60. package/template/agents/tracker.md +202 -0
  61. package/template/commands/blueprint.md +23 -0
  62. package/template/commands/create-role.md +64 -0
  63. package/template/commands/export.md +45 -0
  64. package/template/commands/help.md +55 -0
  65. package/template/commands/hotfix.md +12 -0
  66. package/template/commands/orchestrator.md +12 -0
  67. package/template/commands/pm.md +18 -0
  68. package/template/commands/rewind.md +61 -0
  69. package/template/commands/setup.md +14 -0
  70. package/template/commands/start.md +29 -0
  71. package/template/commands/status.md +11 -0
  72. package/template/commands/sync.md +73 -0
  73. package/template/commands/verifier.md +53 -0
  74. package/template/hooks/audit-context.sh +153 -0
  75. package/template/hooks/enforce-role.sh +175 -0
  76. package/template/hooks/protect-system-files.sh +123 -0
  77. package/template/hooks/review-rounds.sh +172 -0
  78. package/template/rules/acceptance-check.orchestra.md +11 -0
  79. package/template/rules/analytics-kpi.orchestra.md +56 -0
  80. package/template/rules/code-standards.orchestra.md +34 -0
  81. package/template/rules/comments.orchestra.md +77 -0
  82. package/template/rules/commit-format.orchestra.md +20 -0
  83. package/template/rules/dependency-upgrade.orchestra.md +112 -0
  84. package/template/rules/design-parity.orchestra.md +170 -0
  85. package/template/rules/observability.orchestra.md +118 -0
  86. package/template/rules/performance.orchestra.md +186 -0
  87. package/template/rules/phase-limits.orchestra.md +3 -0
  88. package/template/rules/pull-request.orchestra.md +213 -0
  89. package/template/rules/role-boundaries.orchestra.md +117 -0
  90. package/template/rules/security.orchestra.md +106 -0
  91. package/template/rules/stuck-detection.orchestra.md +25 -0
  92. package/template/rules/testing-standards.orchestra.md +214 -0
  93. package/template/rules/tracker-authority.orchestra.md +190 -0
  94. package/template/rules/verification-gate.orchestra.md +56 -0
  95. package/template/skills/accessibility/SKILL.md +31 -0
  96. package/template/skills/android-testing/SKILL.md +112 -0
  97. package/template/skills/architecture/SKILL.md +175 -0
  98. package/template/skills/auth-setup/SKILL.md +105 -0
  99. package/template/skills/best-practices/SKILL.md +29 -0
  100. package/template/skills/code-optimizer/SKILL.md +27 -0
  101. package/template/skills/core-web-vitals/SKILL.md +32 -0
  102. package/template/skills/crud-api/SKILL.md +32 -0
  103. package/template/skills/debug/SKILL.md +28 -0
  104. package/template/skills/deployment/SKILL.md +104 -0
  105. package/template/skills/error-handling/SKILL.md +154 -0
  106. package/template/skills/frontend-design/SKILL.md +30 -0
  107. package/template/skills/fullstack-infrastructure/SKILL.md +108 -0
  108. package/template/skills/ios-testing/SKILL.md +100 -0
  109. package/template/skills/mobile-testing/SKILL.md +102 -0
  110. package/template/skills/observability/SKILL.md +91 -0
  111. package/template/skills/project-structure/SKILL.md +114 -0
  112. package/template/skills/push-notifications/SKILL.md +146 -0
  113. package/template/skills/react-best-practices/SKILL.md +31 -0
  114. package/template/skills/realtime/SKILL.md +146 -0
  115. package/template/skills/review/SKILL.md +82 -0
  116. package/template/skills/testing/SKILL.md +44 -0
  117. package/template/skills/web-quality-audit/SKILL.md +47 -0
  118. package/template/skills/web-testing/SKILL.md +120 -0
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: best-practices
3
+ description: "Web application hardening — security headers, CSP, input handling, browser compatibility. Use for any phase preparing a web app for production."
4
+ ---
5
+
6
+ # Skill: Best Practices
7
+
8
+ ## When to Use
9
+ Phase involves web application security, compatibility, or production hardening.
10
+
11
+ ## Checklist
12
+ - [ ] HTTPS everywhere — no mixed HTTP/HTTPS content
13
+ - [ ] Content Security Policy (CSP) header configured
14
+ - [ ] Security headers set: X-Frame-Options, X-Content-Type-Options, Referrer-Policy
15
+ - [ ] No vulnerable dependencies (`npm audit` clean)
16
+ - [ ] Feature detection, not browser detection (`if ('fetch' in window)` not `if (isChrome)`)
17
+ - [ ] Valid HTML5 doctype, charset first in `<head>`
18
+ - [ ] Viewport meta tag present: `<meta name="viewport" content="width=device-width, initial-scale=1">`
19
+ - [ ] Passive event listeners for scroll/touch events
20
+ - [ ] No `innerHTML` with user input — use `textContent` or sanitize
21
+ - [ ] All user input validated + sanitized on both client and server
22
+
23
+ ## Common Mistakes
24
+ - Mixed HTTP/HTTPS content → browsers block mixed requests
25
+ - XSS via `innerHTML` or `dangerouslySetInnerHTML` without sanitization
26
+ - Synchronous XHR blocking main thread → use `fetch` with async/await
27
+ - Browser detection (`navigator.userAgent`) → breaks on new browsers, use feature detection
28
+ - Missing security headers → easy attack vectors
29
+ - Using `eval()` or `new Function()` with user input → code injection
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: code-optimizer
3
+ description: "Performance work — query shape, memory, bundle, hot paths. Use for any phase that optimises existing code rather than adding behaviour."
4
+ ---
5
+
6
+ # Skill: Code Optimizer
7
+
8
+ ## When to Use
9
+ Phase involves performance optimization, refactoring for speed, or audit of existing code performance.
10
+
11
+ ## Checklist
12
+ - [ ] **Database:** N+1 queries eliminated, proper indexes on WHERE/JOIN columns, connection pooling configured
13
+ - [ ] **Memory:** No unbounded caches/arrays, streams used for large data, event listeners cleaned up
14
+ - [ ] **Algorithmic:** No nested loops over large datasets (O(n^2)), use Map/Set for lookups instead of Array.find
15
+ - [ ] **I/O:** Parallel fetch with `Promise.all` where independent, no sequential awaits for unrelated data
16
+ - [ ] **Bundle:** No barrel file imports (`import { x } from './utils'`), use direct imports for tree-shaking
17
+ - [ ] **Dead Code:** Remove unused imports, functions, files — verify with `npx tsc --noEmit` + grep
18
+ - [ ] **Caching:** Expensive computations cached (LRU, memoize), HTTP cache headers set for static assets
19
+ - [ ] **Rendering:** Avoid layout thrashing (batch DOM reads before writes), use `content-visibility: auto` for offscreen content
20
+
21
+ ## Common Mistakes
22
+ - Sequential `await` for independent promises → use `Promise.all([a(), b(), c()])`
23
+ - Importing from barrel files (`index.ts` re-exports) → prevents tree-shaking, bloats bundle
24
+ - Array.find/filter in loops → O(n*m), convert to Map/Set for O(1) lookup
25
+ - Missing database indexes on frequently queried columns → full table scans
26
+ - Unbounded in-memory caches → memory leak over time, use LRU with max size
27
+ - Not cleaning up event listeners, intervals, subscriptions → memory leak
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: core-web-vitals
3
+ description: "Frontend performance against LCP, INP and CLS. Use for any phase targeting page experience metrics or a Lighthouse score."
4
+ ---
5
+
6
+ # Skill: Core Web Vitals
7
+
8
+ ## When to Use
9
+ Phase involves frontend performance optimization targeting Google's page experience metrics.
10
+
11
+ ## Checklist
12
+ - [ ] **LCP (Largest Contentful Paint) <= 2.5s:**
13
+ - Preload LCP image with `<link rel="preload" fetchpriority="high">`
14
+ - Inline critical CSS (< 14KB)
15
+ - No render-blocking JavaScript in `<head>` (defer or async)
16
+ - Server response time (TTFB) < 800ms
17
+ - [ ] **INP (Interaction to Next Paint) <= 200ms:**
18
+ - No long tasks (> 50ms) on main thread — break up with `requestIdleCallback` or `scheduler.yield()`
19
+ - Event handlers return quickly — defer heavy work
20
+ - Avoid forced synchronous layouts (read then write DOM, not interleaved)
21
+ - [ ] **CLS (Cumulative Layout Shift) <= 0.1:**
22
+ - All images/videos have explicit `width` and `height` or `aspect-ratio`
23
+ - No content injected above existing content after load
24
+ - Fonts use `font-display: swap` with `size-adjust` to minimize shift
25
+ - Reserve space for dynamic content (ads, embeds, lazy content)
26
+
27
+ ## Common Mistakes
28
+ - Images without dimensions → causes layout shift on load
29
+ - Web fonts blocking text rendering → use `font-display: swap`
30
+ - Client-side rendering for LCP element → server-render or prerender it
31
+ - Synchronous third-party scripts in `<head>` → blocks rendering
32
+ - Dynamic banners/modals pushing content down → reserve space or use overlay
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: crud-api
3
+ description: "Creating a resource with standard create/read/update/delete routes. Use for any phase adding a new REST or RPC resource."
4
+ ---
5
+
6
+ # Skill: CRUD API
7
+
8
+ ## When to Use
9
+ Phase involves creating a new resource with standard create/read/update/delete operations.
10
+
11
+ ## Checklist
12
+ - [ ] Define resource schema (Zod or equivalent validation)
13
+ - [ ] Create migration for DB table
14
+ - [ ] Implement endpoints: POST (create), GET (list + detail), PUT/PATCH (update), DELETE
15
+ - [ ] Add input validation on all mutation endpoints
16
+ - [ ] Add pagination on list endpoint (cursor-based preferred over offset)
17
+ - [ ] Add filtering and sorting on list endpoint
18
+ - [ ] Return consistent error format (status code + message + details)
19
+ - [ ] Add proper HTTP status codes: 201 (created), 200 (success), 404 (not found), 422 (validation)
20
+ - [ ] Test all CRUD operations + edge cases (not found, duplicate, invalid input)
21
+
22
+ ## Common Mistakes
23
+ - No pagination on list endpoints (will crash with large datasets)
24
+ - Using offset pagination (slow on large tables) → use cursor-based
25
+ - Not validating request body → runtime crashes
26
+ - Returning 200 for everything → use semantic HTTP codes
27
+ - DELETE without checking ownership → authorization bypass
28
+
29
+ ## Patterns
30
+ - Schema → Type → Validation → Migration flow
31
+ - Repository pattern for DB access (separate query logic from handler)
32
+ - Consistent error response: `{ error: { code, message, details } }`
@@ -0,0 +1,28 @@
1
+ ---
2
+ name: debug
3
+ description: "Investigating a bug whose cause is not obvious — unexpected behaviour, a production incident, a flaky test. Use when the fix is not yet known."
4
+ ---
5
+
6
+ # Skill: Debug
7
+
8
+ ## When to Use
9
+ Phase involves investigating a complex bug, unexpected behavior, or production issue that isn't immediately obvious.
10
+
11
+ ## Checklist
12
+ - [ ] **Document current state:** exact error message, steps to reproduce, expected vs actual behavior
13
+ - [ ] **Map the system:** trace the execution path from input to error — which files, functions, APIs are involved?
14
+ - [ ] **Gather evidence BEFORE hypothesizing:** read logs, check git blame, inspect network requests, check env vars
15
+ - [ ] **Form hypotheses:** list 2-3 possible causes ranked by likelihood
16
+ - [ ] **Test each hypothesis minimally:** change ONE thing, observe result, revert if wrong
17
+ - [ ] **Check external factors:** dependency versions, API changes, environment differences (dev vs prod)
18
+ - [ ] **Verify the fix:** reproduce the original bug, apply fix, confirm it's resolved, check for regressions
19
+ - [ ] **Document root cause:** what happened, why, and what prevents it from recurring
20
+
21
+ ## Common Mistakes
22
+ - Assuming the bug is where the error appears → trace upstream, the root cause is often elsewhere
23
+ - Changing multiple things at once → can't tell which change fixed it
24
+ - Not reproducing before fixing → you might fix a different bug
25
+ - Treating your own code with less skepticism → YOUR code is the most likely source
26
+ - Proposing fixes without evidence → "I think it might be X" without testing is guessing
27
+ - Not checking if the bug exists in other environments → might be env-specific
28
+ - Fixing the symptom, not the cause → bug will return in a different form
@@ -0,0 +1,104 @@
1
+ ---
2
+ name: deployment
3
+ description: "Getting a service to production and back again — health, release gating, smoke, rollback, migrations. Use for any phase that touches CI/CD, containers, environment configuration, or a deploy."
4
+ ---
5
+
6
+ # Skill: Deployment
7
+
8
+ Implements `.claude/rules/observability.orchestra.md`. Read it first; this is
9
+ the working checklist.
10
+
11
+ ## The fact everything else follows from
12
+
13
+ **Nothing here protects a release except being able to undo it.**
14
+
15
+ There is no percentage canary on the platforms this stack targets. What
16
+ stands between a broken build and every user is three things, in order: the
17
+ healthcheck that decides whether the new deployment is promoted, a smoke test
18
+ against the real URL afterwards, and putting the last good commit back when
19
+ that smoke fails.
20
+
21
+ Rollback is the same path as a normal deploy, deliberately. An untested
22
+ recovery path is not a recovery path.
23
+
24
+ ## Health is two endpoints
25
+
26
+ | Endpoint | Question | Cost | Fails when |
27
+ |---|---|---|---|
28
+ | `/health` | is the process up? | no dependencies | it doesn't answer |
29
+ | `/ready` | can it serve? | probes every dependency | **503**, naming the one that failed |
30
+
31
+ The platform healthcheck points at **`/ready`**. This is load-bearing: the
32
+ previous deployment keeps serving until the new one answers 200, so a
33
+ readiness probe that returns 200 with an unreachable database does not
34
+ mislead a dashboard — it promotes a broken release.
35
+
36
+ - [ ] `/ready` probes every dependency the service cannot serve without
37
+ - [ ] it answers 503 and names the failed dependency, not a bare status
38
+ - [ ] there is a test that **makes it fail** — a probe that cannot fail is
39
+ worse than none
40
+ - [ ] adding a dependency adds its probe and its failing test in the same
41
+ change
42
+ - [ ] `healthcheckPath` in the platform config points at `/ready`, not
43
+ `/health`
44
+
45
+ ## Releasing
46
+
47
+ - [ ] deploy is gated on the healthcheck, with an overlap window so the old
48
+ instance drains rather than being cut
49
+ - [ ] a smoke test runs against the deployed URL, not against localhost
50
+ - [ ] the smoke failing triggers rollback, and the rollback is exercised
51
+ - [ ] the `last-good-deploy` tag moves **only after the smoke passes** — so
52
+ it always names a release observed working, never one that merely
53
+ deployed
54
+ - [ ] release and commit sha reach the error monitor and every log line
55
+
56
+ ## Environment
57
+
58
+ - [ ] every variable is read through one validating schema, and boot fails
59
+ loudly when a required one is missing
60
+ - [ ] `.env.example` is **generated from that schema**, never written beside
61
+ it — a hand-kept example is wrong the first time somebody forgets, and
62
+ a new engineer trusts it anyway
63
+ - [ ] `.env` gitignored, always
64
+ - [ ] a secret that was ever committed is rotated; deleting the commit is not
65
+ the fix
66
+
67
+ ## Migrations
68
+
69
+ - [ ] run automatically on deploy, never by hand
70
+ - [ ] forward-compatible with the previous release, because both run at once
71
+ during the overlap window
72
+ - [ ] a destructive change is two deploys: stop using the column, then drop
73
+ it
74
+
75
+ ## Containers
76
+
77
+ - [ ] multi-stage build, runtime stage carries no build tooling
78
+ - [ ] non-root user
79
+ - [ ] `.dockerignore` covers `node_modules`, `.git`, test output
80
+ - [ ] SIGTERM drains in-flight requests before exit — the overlap window is
81
+ wasted if the process dies instantly
82
+
83
+ ## Feature flags
84
+
85
+ A risky change ships dark. The lookup must never be able to take the service
86
+ down: bounded by a timeout, failures reported and answered with the flag's
87
+ own fallback rather than thrown into a handler. For a kill switch the
88
+ fallback is **false** — if we cannot ask whether a risky path is allowed, the
89
+ answer is no.
90
+
91
+ Flags live in one typed registry. A string literal at a call site is how they
92
+ rot.
93
+
94
+ ## Common mistakes
95
+
96
+ - **A readiness probe that returns a constant.** It passes review, passes
97
+ CI, and promotes a release with a dead database.
98
+ - Pointing the platform healthcheck at `/health`. Liveness answers yes while
99
+ nothing works.
100
+ - Rolling back by hand through a dashboard. The path nobody scripted is the
101
+ path nobody can run at 3am.
102
+ - Tagging the deploy as good when it deployed, rather than when it was
103
+ observed working.
104
+ - Secrets in the image, or in a build argument, which is the same thing.
@@ -0,0 +1,154 @@
1
+ ---
2
+ name: error-handling
3
+ description: "What to do when something fails — typed errors, propagation, what the user sees, and degrading instead of crashing. Use for any phase that adds a failure path, a catch, or an error response."
4
+ ---
5
+
6
+ # Skill: Error Handling
7
+
8
+ The rule is in `.claude/rules/observability.orchestra.md` and a check
9
+ enforces it: **a catch either handles the error meaningfully or reports it and
10
+ rethrows.** `scripts/policy-check.mjs` fails the gate on an empty catch and on
11
+ a catch whose only body is a log.
12
+
13
+ That check proves a catch is not empty. It cannot tell whether the user got a
14
+ correct outcome. This skill is about the part that needs a person.
15
+
16
+ ## The fact everything else follows from
17
+
18
+ **"Handled" means the caller gets a correct outcome — not that the crash was
19
+ hidden.**
20
+
21
+ ```ts
22
+ try {
23
+ await chargeCard(order);
24
+ } catch (e) {
25
+ reportError(e);
26
+ return { ok: true }; // the gate passes. the customer was not charged.
27
+ }
28
+ ```
29
+
30
+ Reported, rethrown-shaped, and wrong. Nothing downstream can tell the
31
+ difference between a payment that succeeded and one that vanished. Deciding
32
+ which of those two this is, is the entire job.
33
+
34
+ ## Three kinds of failure, three different answers
35
+
36
+ | Kind | Example | Answer |
37
+ |---|---|---|
38
+ | **Expected** | invalid input, not found, conflict | Not exceptional. Return it as a value or throw a typed error the boundary maps to a status. |
39
+ | **Transient** | timeout, 503 from a provider, deadlock | Retry if idempotent, with backoff and a bound. Then give up deliberately. |
40
+ | **A bug** | undefined is not a function, a broken invariant | Do not catch it here. Let it reach the boundary, be reported with its stack, and answer 500. |
41
+
42
+ The most common mistake is treating the third as the first: a broad `catch`
43
+ around a whole handler turns every bug into a polite message and the defect
44
+ is never seen again.
45
+
46
+ ## Typed at the boundary
47
+
48
+ The backend stack ships `AppError` with a closed `ErrorCode` union, and
49
+ `toErrorBody` maps it to a status and a body. Use it.
50
+
51
+ ```ts
52
+ throw new AppError("not_found", "Order not found");
53
+ ```
54
+
55
+ - **Never throw a bare `Error` across a route boundary.** It becomes a 500,
56
+ which tells the caller nothing and pages someone for a 404.
57
+ - **Never let internal detail into the response.** `toErrorBody` returns the
58
+ minimum for anything unrecognised, deliberately — a stack trace in a body
59
+ is an information leak, and the message often contains a query.
60
+ - The code is a **closed union**, not a string. A new failure mode is a new
61
+ member and a new status, decided once, rather than a literal invented at a
62
+ call site.
63
+
64
+ Adding a code is a real decision: it is part of the API contract, and a
65
+ client will branch on it.
66
+
67
+ ## Validate once, at the edge
68
+
69
+ Parse input at the boundary and let everything inside work with a type that
70
+ cannot be invalid. A function that re-checks its arguments is a function that
71
+ does not trust its own signature — and the check will disagree with the
72
+ schema eventually.
73
+
74
+ That is why the boundary owns validation and the interior does not:
75
+ `.claude/rules/security.orchestra.md` puts it in the same place for the same
76
+ reason.
77
+
78
+ ## Keep the cause
79
+
80
+ ```ts
81
+ throw new AppError("internal", "could not load order"); // no
82
+ throw new Error("could not load order", { cause: original }); // yes
83
+ ```
84
+
85
+ Wrapping is fine; discarding is not. The original stack is the only thing
86
+ that says which line failed. When you rethrow, carry the cause; when you
87
+ report, report the cause too.
88
+
89
+ ## What the user sees
90
+
91
+ Two audiences, two texts, and they are rarely the same string.
92
+
93
+ - **The user** gets something actionable: what happened, and what they can do.
94
+ Not an error code alone, and never a stack.
95
+ - **The operator** gets the detail, in the log, with the correlation id — so
96
+ a user quoting `x-request-id` from a bug report leads straight to the line.
97
+ The request logger echoes that header back for exactly this reason.
98
+
99
+ If a screen can fail, it has a failure state, and the failure state has a way
100
+ forward. `.claude/skills/review/SKILL.md` treats a missing one as a finding.
101
+
102
+ ## Degrading instead of failing
103
+
104
+ Some dependencies are not required to answer. Say so explicitly, and say what
105
+ the answer is without them.
106
+
107
+ ```ts
108
+ // Recommendations are a nice-to-have; the page renders without them.
109
+ const recommended = await getRecommendations(userId).catch((e) => {
110
+ report(e);
111
+ return [];
112
+ });
113
+ ```
114
+
115
+ This is the one place an error is swallowed, and it carries a comment saying
116
+ why failure is acceptable — the exception named in the observability rule.
117
+ Two conditions, both required:
118
+
119
+ 1. The feature is genuinely optional to the outcome.
120
+ 2. The failure is still **reported**, so "optional" does not quietly become
121
+ "permanently broken".
122
+
123
+ For anything gating a risky path the fallback is **false** — the same
124
+ direction the feature-flag registry falls, and for the same reason.
125
+
126
+ ## Failure paths are tested, not assumed
127
+
128
+ - Every catch you write has a test that reaches it. An untested error path is
129
+ usually a broken error path — it is the code least likely to have been run
130
+ even once.
131
+ - Provider failures are faked **at the HTTP boundary**, never by mocking your
132
+ own wrapper: the wrapper is where a provider's change bites you, so mocking
133
+ it tests nothing. `.claude/rules/testing-standards.orchestra.md`.
134
+ - The cases worth writing: a 500 from the provider, a timeout, a malformed
135
+ body, and the retry that eventually gives up.
136
+
137
+ Coverage will not tell you these exist. Mutation testing would, which is why
138
+ it is wired even while it waits on the compiler.
139
+
140
+ ## Anti-patterns
141
+
142
+ - **`catch (e) { report(e) }` in a write path.** The caller now believes the
143
+ write happened.
144
+ - **Catching to convert everything to `null`.** The caller has no idea
145
+ whether "nothing" means empty or broken.
146
+ - **One broad try/catch wrapping an entire handler.** It catches your bugs
147
+ along with the expected failures, and turns both into the same response.
148
+ - **Retrying a non-idempotent write.** This is how a customer gets charged
149
+ twice.
150
+ - **A message that names the wrong actor.** "Something went wrong" when the
151
+ input was invalid sends the user looking in the wrong place.
152
+ - **Logging and rethrowing at every level.** One failure, six lines, and none
153
+ of them the one with the stack. Report where you handle it, not on the way
154
+ past.
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: frontend-design
3
+ description: "Building UI that looks deliberate rather than generic — typography, colour, spacing, motion. Use for any phase where visual quality is part of the acceptance criteria."
4
+ ---
5
+
6
+ # Skill: Frontend Design
7
+
8
+ ## When to Use
9
+ Phase involves building UI that needs to look polished, professional, and distinctive — not generic.
10
+
11
+ ## Checklist
12
+ - [ ] **Bold aesthetic direction:** commit to a clear visual concept — not timid, not generic
13
+ - [ ] **Distinctive typography:** avoid overused fonts (Inter, Roboto, Arial) — choose fonts with character
14
+ - [ ] **Cohesive color scheme:** limited palette (3-5 colors) with sharp accent colors
15
+ - [ ] **Intentional layout:** use asymmetry, overlap, or diagonal elements where appropriate — not everything grid-aligned
16
+ - [ ] **Layered shadows:** multiple transparent shadows instead of solid borders (`box-shadow: 0 1px 2px rgba(0,0,0,0.1), 0 4px 12px rgba(0,0,0,0.05)`)
17
+ - [ ] **Concentric border radius:** outer radius = inner radius + padding (nested elements)
18
+ - [ ] **Micro-interactions:** hover states, focus transitions, loading animations — all < 300ms
19
+ - [ ] **Staggered enter animations:** split elements, ~100ms delay between each
20
+ - [ ] **Font smoothing:** `-webkit-font-smoothing: antialiased` for crisp text
21
+ - [ ] **Tabular numbers:** `font-variant-numeric: tabular-nums` for data tables and counters
22
+ - [ ] **Optical alignment:** icons and text optically centered, not geometrically
23
+
24
+ ## Common Mistakes
25
+ - Generic AI-slop aesthetics → every AI tool produces the same look, be distinctive
26
+ - Solid borders everywhere → layered transparent shadows look more refined
27
+ - Geometric centering for icons → optical centering looks correct to the eye
28
+ - Harsh easing functions → use `cubic-bezier(0.4, 0, 0.2, 1)` for natural motion
29
+ - Missing exit animations → enter with animation, exit abruptly looks broken
30
+ - System fonts without thought → typography is 80% of visual quality
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: fullstack-infrastructure
3
+ description: "TypeScript and React conventions that hold in any app — types, hooks, rendering, data flow, performance, i18n. Which libraries, which structure and which tooling are decided by .orchestra/stacks/, not here. Use when writing TypeScript or React in any app."
4
+ ---
5
+
6
+ # TypeScript & React Conventions
7
+
8
+ What is true regardless of which stack scaffolded the app.
9
+
10
+ ## What this file does not decide
11
+
12
+ It used to carry a tech stack table and a monorepo tree of its own, naming an
13
+ ORM, an auth scheme, an HTTP client and a component kit. Every one of those is
14
+ decided somewhere that can enforce it, and a skill restating a choice is a
15
+ second source of truth: whichever the agent reads last wins, and nothing
16
+ notices when they drift apart.
17
+
18
+ | Question | Answered by |
19
+ |---|---|
20
+ | Which libraries, package manager, tooling | `.orchestra/stacks/<stack>/setup.sh` — it installs them |
21
+ | Where a new file goes | `.claude/skills/project-structure/SKILL.md` |
22
+ | Where a component comes from | the web `stack.md`, and `src/components/README.md` |
23
+ | What "handled" means for an error | `.claude/skills/error-handling/SKILL.md` |
24
+ | Testing, commits, security, observability | `.claude/rules/*.orchestra.md` |
25
+
26
+ What the stacks scaffold today, for orientation only: Drizzle rather than
27
+ Prisma, server-side sessions rather than JWT, `fetch` in
28
+ `src/integrations/<provider>/` rather than an Axios wrapper class, feature-first
29
+ `src/features/<domain>/` rather than a layer-first tree.
30
+
31
+ **If this file ever disagrees with a stack, the stack is right** — it is the
32
+ thing that actually ran.
33
+
34
+ ## TypeScript
35
+
36
+ - `strict`, with no per-file exemptions.
37
+ - No `any`. Use `unknown` and narrow it — `any` disables the checker at
38
+ exactly the boundary you added it to guard.
39
+ - `interface` for object shapes, `type` for unions and intersections.
40
+ - Discriminated unions for anything with states. A boolean pair that can
41
+ express `loading && error` is a bug waiting for a screenshot.
42
+ - Explicit return types on exported functions. Inference is fine inside a
43
+ module and a liability across one — a return type that changes silently is
44
+ a breaking change nobody reviewed.
45
+ - Prefer a union of literals to an enum. It erases at compile time and
46
+ narrows without an import.
47
+
48
+ ## React
49
+
50
+ - Function components only.
51
+ - Custom hooks are prefixed `use` — the linter's rules-of-hooks check keys
52
+ off the name, so a mis-named hook is simply unchecked.
53
+ - `useMemo` and `useCallback` where a measurement says they help. Applied by
54
+ reflex they add allocation and a dependency array to get wrong.
55
+ - Composition over prop drilling. Context for what is genuinely ambient
56
+ (theme, locale, session), not to avoid passing two props.
57
+ - Stable keys from the data. An array index makes React reuse the wrong node
58
+ the first time the list reorders, and the bug looks like corrupted state.
59
+ - `React.lazy` with `Suspense` at route boundaries.
60
+
61
+ ## Data flow
62
+
63
+ - **Server cache and client state are different things.** Copying a response
64
+ into a client store gives you two truths and a stale one.
65
+ - Every backend call goes through a wrapper in `src/integrations/<provider>/`
66
+ — never a raw client call from a component. That is where the timeout, the
67
+ retry bound and the error mapping live, and it is the only place a test can
68
+ hold. See `.claude/skills/project-structure/SKILL.md`.
69
+ - Which cache or store library, if any, is the stack's decision. If a project
70
+ adopts one, it goes in the stack's `setup.sh` so it is installed and
71
+ covered — not named here.
72
+
73
+ ## Classes vs functions
74
+
75
+ **Class** when there is lifecycle to hold: an SDK that needs init and
76
+ teardown, or shared configuration across calls.
77
+ **Function** when it is stateless and single-purpose — `formatDate`,
78
+ `slugify`.
79
+
80
+ Prefer writing a small utility to adding a dependency for it. Reach for a
81
+ package when the implementation is genuinely hard — dates, time zones,
82
+ collation — not when it is twelve lines.
83
+
84
+ ## Performance
85
+
86
+ - Lazy load routes and anything heavy below the fold.
87
+ - Virtualize long lists.
88
+ - Debounce or throttle high-frequency events at the source, not in the
89
+ handler.
90
+ - Derive loading and error state from the request, not from booleans set by
91
+ hand in three places.
92
+
93
+ ## Environment variables
94
+
95
+ Validated at startup against a schema, so the process refuses to boot on bad
96
+ configuration rather than failing on the first request that needs it.
97
+
98
+ `.env.example` is **generated from that schema**, never written beside it —
99
+ see `.claude/rules/security.orchestra.md`.
100
+
101
+ ## i18n
102
+
103
+ Ask whether it is needed before the first string is written; retrofitting
104
+ means touching every component.
105
+
106
+ When it is: every user-facing string is a key, namespaced by feature. No
107
+ concatenated sentences — word order is not universal, and a sentence built
108
+ from three fragments cannot be translated correctly into most languages.
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: ios-testing
3
+ description: "Testing strategy for native iOS apps — Swift, SwiftUI, XCTest and XCUITest. Use for any phase that writes or changes tests in a native iOS app."
4
+ ---
5
+
6
+ # Skill: iOS Testing
7
+
8
+ ## The fact everything else follows from
9
+
10
+ **A unit test does not prove the app launches.**
11
+
12
+ An iOS app dies for reasons no XCTest sees: a missing Info.plist key, an
13
+ entitlement the provisioning profile lacks, a `@main` that throws before the
14
+ first view, a bundle resource that was never copied. The suite is green and
15
+ the app crashes on the splash screen.
16
+
17
+ So the launch test is not the top of a pyramid you get to later. It is the
18
+ first test worth writing.
19
+
20
+ ## The layers
21
+
22
+ | Layer | What belongs here | Runs on |
23
+ |---|---|---|
24
+ | Unit | Pure logic and view models — no UIKit, no SwiftUI | Host, fast |
25
+ | View | SwiftUI views: state transitions and the accessibility tree | Simulator |
26
+ | Integration | The real networking stack, stubbed at the transport | Simulator |
27
+ | UI (XCUITest) | 3–5 journeys, one of them launch | Real simulator |
28
+ | Build | `xcodebuild` for a device architecture | The gate |
29
+
30
+ ## Stub the transport, not your client
31
+
32
+ ```swift
33
+ final class StubProtocol: URLProtocol { /* … */ }
34
+
35
+ let config = URLSessionConfiguration.ephemeral
36
+ config.protocolClasses = [StubProtocol.self]
37
+ let session = URLSession(configuration: config)
38
+ ```
39
+
40
+ Register a `URLProtocol` subclass and the real `URLSession` runs — your
41
+ request building, your headers, your decoding, your error mapping.
42
+
43
+ Injecting a `MockAPIClient` instead tests the mock. The client is the thing
44
+ that breaks when the API changes, so it is the thing that must stay in the
45
+ test.
46
+
47
+ ## Query the accessibility tree
48
+
49
+ ```swift
50
+ app.buttons["Add water"].tap() // yes — the accessible name
51
+ app.buttons["btn_add_water"].tap() // no — an identifier nobody hears
52
+ ```
53
+
54
+ XCUITest resolves elements through the accessibility tree, which is the same
55
+ tree VoiceOver uses. Query by label and **a control with no accessible name
56
+ fails the test** — accessibility becomes something the suite enforces.
57
+
58
+ Use `accessibilityIdentifier` only where the visible label genuinely changes
59
+ with locale or data, and keep the label correct anyway.
60
+
61
+ ## Swift Testing for units, XCTest for UI
62
+
63
+ `import Testing` with `@Test` and `#expect` is the current framework for unit
64
+ and view tests — clearer failures, real parameterised cases, native async.
65
+
66
+ XCUITest is still XCTest. Do not try to unify them.
67
+
68
+ Both need `await` discipline: a `@MainActor` view model tested from a
69
+ non-isolated context passes locally and races in CI.
70
+
71
+ ## Never
72
+
73
+ - **Snapshot tests as the main assertion.** A recorded PNG changes with every
74
+ OS point release, gets re-recorded without being read, and passes while the
75
+ button does nothing. Assert state and the accessibility tree instead.
76
+ - Testing that SwiftUI re-renders, or that `NavigationStack` navigates.
77
+ Assert that the action fires with the right argument.
78
+ - Sleeping to wait. `XCTestExpectation` and `waitForExistence(timeout:)`
79
+ exist; a `sleep` is a flake with a delay.
80
+ - A simulator-only definition of done. The simulator has no memory pressure,
81
+ no thermal throttling, no real camera and a different keyboard.
82
+
83
+ ## The build is part of the suite
84
+
85
+ Build for a **device** architecture in the gate, not only the simulator.
86
+ Simulator builds are x86/arm64-host and skip code signing, so a missing
87
+ entitlement, an unsupported architecture or a bad bitcode setting only
88
+ appears when a real build is attempted.
89
+
90
+ A release build additionally runs optimisation and dead-code stripping,
91
+ which is where `#if DEBUG` mistakes surface.
92
+
93
+ ## Release risk
94
+
95
+ An App Store release cannot be rolled back. There is no equivalent of an
96
+ over-the-air JavaScript update unless one was deliberately built.
97
+
98
+ That makes phased release and a server-side kill switch part of the testing
99
+ strategy rather than an operational afterthought — see
100
+ `.claude/rules/observability.orchestra.md`.