@oneie/claude 0.6.0 → 0.7.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 (111) hide show
  1. package/agents/w1-recon.md +9 -4
  2. package/agents/w2-decide.md +51 -28
  3. package/agents/w3-edit.md +70 -78
  4. package/agents/w4-verify.md +164 -69
  5. package/commands/browser.md +98 -35
  6. package/commands/cc-connect.md +6 -0
  7. package/commands/chat.md +13 -1
  8. package/commands/close.md +45 -19
  9. package/commands/create.md +20 -10
  10. package/commands/db-sync.md +5 -1
  11. package/commands/deploy.md +174 -87
  12. package/commands/do-autonomous.md +31 -20
  13. package/commands/do-improve.md +4 -4
  14. package/commands/do-show.md +4 -3
  15. package/commands/do.md +53 -13
  16. package/commands/go.md +75 -0
  17. package/commands/improve.md +4 -2
  18. package/commands/kill.md +6 -8
  19. package/commands/notify.md +15 -2
  20. package/commands/oo-push.md +24 -9
  21. package/commands/rag.md +6 -0
  22. package/commands/release.md +46 -25
  23. package/commands/restart.md +5 -4
  24. package/commands/see.md +45 -35
  25. package/commands/skill-create.md +38 -5
  26. package/commands/sync.md +21 -11
  27. package/hooks/scripts/auto-continue.sh +70 -0
  28. package/hooks/scripts/branch-pin.sh +85 -0
  29. package/hooks/scripts/git-add-guard.sh +16 -5
  30. package/hooks/scripts/post-edit-check.sh +16 -0
  31. package/hooks/scripts/session-start.sh +13 -8
  32. package/hooks/scripts/sync-priority-todo.sh +5 -0
  33. package/package.json +1 -1
  34. package/rules/api.md +9 -0
  35. package/rules/design.md +13 -3
  36. package/rules/documentation.md +30 -71
  37. package/rules/engine.md +8 -1
  38. package/rules/ui.md +5 -1
  39. package/scripts/__pycache__/do-rank.cpython-313.pyc +0 -0
  40. package/scripts/browser-check.mjs +44 -103
  41. package/scripts/cc-events-proof.sh +13 -12
  42. package/scripts/chrome.mjs +381 -0
  43. package/scripts/do-analyze.sh +109 -4
  44. package/scripts/do-auto.sh +350 -43
  45. package/scripts/do-consumer-sweep.sh +72 -0
  46. package/scripts/do-derives-check.sh +88 -0
  47. package/scripts/do-fleet.sh +50 -1
  48. package/scripts/do-killswitch-audit.py +33 -14
  49. package/scripts/do-promise-lint.sh +150 -4
  50. package/scripts/do-promise-settle.sh +131 -9
  51. package/scripts/do-prove.sh +197 -17
  52. package/scripts/do-rank.py +606 -20
  53. package/scripts/do-rubric.py +21 -2
  54. package/scripts/do-signal.sh +157 -17
  55. package/scripts/do-smoke.sh +9 -0
  56. package/scripts/do-substrate-check.sh +49 -0
  57. package/scripts/do-tasks-wire-check.sh +81 -0
  58. package/scripts/do-tier.sh +90 -5
  59. package/scripts/do-ui-gate.sh +332 -0
  60. package/scripts/do-untracked-gate.sh +231 -0
  61. package/scripts/do-walk.sh +344 -0
  62. package/scripts/factory-check.sh +747 -0
  63. package/scripts/factory-repo.sh +1361 -0
  64. package/scripts/factory-tasks-check.sh +85 -0
  65. package/scripts/outcome-pull.ts +279 -0
  66. package/scripts/promise-manifest.mjs +167 -0
  67. package/scripts/reconcile-allow.txt +5 -0
  68. package/scripts/rubric-weights.json +64 -0
  69. package/scripts/spine-canary.sh +20 -0
  70. package/scripts/typedb-cluster-status.sh +128 -0
  71. package/scripts/typedb-env.sh +182 -0
  72. package/scripts/typedb-flap-recorder.sh +85 -0
  73. package/scripts/typedb-probes/containment-probe.py +88 -0
  74. package/scripts/typedb-probes/panic-probe-version.py +92 -0
  75. package/scripts/typedb-probes/panic-probe.py +77 -0
  76. package/scripts/typedb-scratch.sh +73 -0
  77. package/scripts/urls-lint.sh +58 -0
  78. package/scripts/w4-rubric.ts +96 -12
  79. package/scripts/wf-check.mjs +75 -0
  80. package/skills/ai-ui/SKILL.md +1 -1
  81. package/skills/astro/SKILL.md +177 -132
  82. package/skills/astro/add-content-collection.md +29 -13
  83. package/skills/astro/check-build.md +19 -13
  84. package/skills/astro/create-component.md +36 -9
  85. package/skills/astro/create-page.md +39 -10
  86. package/skills/astro/optimize-performance.md +36 -8
  87. package/skills/cli/SKILL.md +254 -220
  88. package/skills/dev/SKILL.md +1 -1
  89. package/skills/directory-autofill/SKILL.md +68 -0
  90. package/skills/docs/SKILL.md +4 -4
  91. package/skills/mcp/SKILL.md +186 -156
  92. package/skills/promise-make/SKILL.md +2 -2
  93. package/skills/puck/SKILL.md +465 -250
  94. package/skills/react19/SKILL.md +196 -296
  95. package/skills/reactflow/SKILL.md +387 -412
  96. package/skills/sdk/SKILL.md +167 -106
  97. package/skills/shadcn/SKILL.md +245 -201
  98. package/skills/signal/SKILL.md +5 -0
  99. package/skills/sui/SKILL.md +6 -1
  100. package/skills/tutorial/SKILL.md +15 -0
  101. package/skills/typedb/SKILL.md +427 -217
  102. package/skills/typedb/examples/python-patterns.py +11 -4
  103. package/skills/typedb/examples/query-patterns.tql +8 -3
  104. package/skills/typedb/examples/schema-patterns.tql +4 -2
  105. package/skills/typedb/reference/migration-2x-3x.md +19 -1
  106. package/skills/typedb/reference/python-driver.md +17 -1
  107. package/skills/voice/SKILL.md +117 -0
  108. package/skills/writer/SKILL.md +29 -12
  109. package/templates/template-feature.md +26 -1
  110. package/templates/template-tests.md +4 -0
  111. package/templates/template-todo.md +65 -10
@@ -1,23 +1,32 @@
1
1
  ---
2
2
  name: astro
3
- description: Build Astro 6 pages with React 19 islands + Cloudflare Workers runtime. Covers adapter v13, SSR vs prerender, cloudflare:workers env, bundle-size rules.
3
+ description: Build pages, layouts and API routes in `one.ie/web` — Astro 6 + React 19 islands on Cloudflare Workers. Covers the real astro.config.mjs shape, adapter v13, SSR vs prerender, the `(await import('cloudflare:workers')).env` access pattern, and the LOCKED bundle-size rules. Use when editing `.astro` files, `astro.config.mjs`, or `src/pages/api/**`. For the `template/` tree use `template:astro` (Astro 7) instead.
4
4
  user-invocable: true
5
5
  allowed-tools: Read, Write, Edit, Glob, Grep, Bash
6
6
  ---
7
7
 
8
- # Astro 6 on Cloudflare Workers
8
+ # Astro 6 on Cloudflare Workers — `one.ie/web`
9
9
 
10
- Server-rendered pages with strategic React islands, running on `@astrojs/cloudflare@13` + Workers with Static Assets (Pages-era is retired — see `docs/cf-workers-migration-todo.md`).
10
+ **Which tree:** this skill describes `one.ie/web` only Astro 6, single Cloudflare
11
+ adapter. `template/site` is a **different major** (Astro 7) with its own conventions;
12
+ use the `template:astro` skill there. Every claim below was checked against
13
+ `one.ie/web/astro.config.mjs` and `one.ie/web/package.json` on 2026-08-02.
14
+
15
+ Server-rendered pages with strategic React islands, on `@astrojs/cloudflare@13` +
16
+ Workers with Static Assets (the Pages era is retired).
11
17
 
12
18
  ## Stack
13
19
 
14
- | Package | Version (2026-04-18) | Role |
20
+ | Package | Declared (2026-08-02) | Role |
15
21
  |---|---|---|
16
- | `astro` | `^6.1.7` | Framework |
17
- | `@astrojs/cloudflare` | `^13.1.10` | Workers adapter (no longer supports Pages) |
18
- | `@astrojs/react` | `^5.0.3` | React 19 islands |
19
- | `@astrojs/node` | `^10.0.5` | **Dev-only** (standalone mode, avoids miniflare dev issues) |
20
- | `wrangler` | `^4.83.0` | Workers CLI |
22
+ | `astro` | `^6.2.2` (6.3.7 installed) | Framework |
23
+ | `@astrojs/cloudflare` | `^13.3.1` | Workers adapter (no longer supports Pages) |
24
+ | `@astrojs/react` | `^5.0.4` | React 19 islands |
25
+ | `@astrojs/node` | `^10.0.6` | Declared but **unused** not imported by `astro.config.mjs` |
26
+ | `wrangler` | `^4.14.0` | Workers CLI |
27
+
28
+ `@astrojs/node` is a leftover dependency. There is no dev/prod adapter swap in this
29
+ tree — don't add one back on the strength of the package being present.
21
30
 
22
31
  ## Works With
23
32
 
@@ -25,54 +34,51 @@ Server-rendered pages with strategic React islands, running on `@astrojs/cloudfl
25
34
  |------------|---------------------------------------------------------------------------------------|
26
35
  | `/react19` | React components inside islands — pick `client:load` / `client:visible` / `client:only`. |
27
36
  | `/cloudflare` | `wrangler.toml`, `[assets]` binding, secrets, `wrangler tail`, Workers+Assets semantics. |
28
- | `/deploy` | 8-step `bun run deploy` pipeline — Astro build is step 3; bundle-size rules live here. |
29
37
  | `/signal` | `src/pages/api/*.ts` — every API route is the substrate's HTTP surface. |
30
38
  | `/shadcn` | shadcn components live inside islands; dark-theme tokens + hydration strategy. |
31
- | `/sui` | SSR pages reading on-chain data — use `client:only="react"` to keep worker under 10 MiB. |
32
- | `/typedb` | SSR data fetching — Astro pages call `readParsed()` from `src/lib/typedb.ts`. |
39
+ | `/sui` | SSR pages reading on-chain data — use `client:only="react"` to keep the worker small. |
40
+ | `/typedb` | SSR data fetching — pages call `typedbQuery()` from `src/lib/substrate.ts`. |
33
41
 
34
- Auto-loads on `*.astro`: `.claude/rules/astro.md`.
42
+ Auto-loads on `*.astro`: `.claude/rules/astro.md`. The deploy pipeline (8 steps,
43
+ Astro build is step 3) is the `/deploy` **command**, not a skill:
44
+ `.claude/commands/deploy.md`.
35
45
 
36
- ## Dual-Adapter Config (the ONE pattern)
46
+ ## The Config (the ONE shape)
37
47
 
38
- `astro.config.mjs` swaps adapters at NODE_ENV time. Node standalone for dev (fast reload, no miniflare flakes), Cloudflare Workers for prod.
48
+ One adapter, always Cloudflare. `astro.config.mjs` is ~200 lines three Vite plugins,
49
+ a large `optimizeDeps` block, and a Durable-Object export plugin. **Read the file for
50
+ the rest; the load-bearing shape is:**
39
51
 
40
52
  ```js
41
- // astro.config.mjs — the working shape
42
- import react from "@astrojs/react";
43
- import cloudflare from "@astrojs/cloudflare";
44
- import node from "@astrojs/node";
45
- import tailwindcss from "@tailwindcss/vite";
46
- import { defineConfig } from "astro/config";
47
-
48
- const isDev = process.env.NODE_ENV !== "production";
49
- const adapter = isDev
50
- ? node({ mode: "standalone" })
51
- : cloudflare({ platformProxy: { enabled: true } });
52
-
53
+ // astro.config.mjs — the parts this skill's rules depend on
53
54
  export default defineConfig({
54
- site: "https://one.ie",
55
- integrations: [react()],
56
- output: "server", // all routes SSR unless prerender=true per-page
57
- adapter,
58
- markdown: {
59
- syntaxHighlight: false, // LOCKED — saves ~5.8 MiB of Shiki from worker
60
- },
61
- vite: {
62
- ssr: {
63
- noExternal: ["recharts", "lucide-react"],
64
- external: [
65
- "node:async_hooks",
66
- "@mysten/sui", "@mysten/bcs",
67
- "shiki", "@shikijs/core", "@shikijs/types",
68
- ],
69
- },
70
- // ...tailwind, aliases, chunks
71
- },
72
- });
55
+ output: 'server', // all routes SSR unless prerender=true
56
+ adapter: cloudflare({
57
+ prerenderEnvironment: 'node', // prerender under node, not workerd
58
+ imageService: 'passthrough',
59
+ sessions: false,
60
+ remoteBindings: false,
61
+ // NOT { enabled: true } — loading [env.production] during build sync
62
+ // makes Miniflare evaluate the DO before the export plugin runs
63
+ platformProxy: { environment: undefined },
64
+ }),
65
+ integrations: [react(), devWarmupIntegration()],
66
+ build: { inlineStylesheets: 'auto' }, // LOCKED — never 'always'
67
+ markdown: { syntaxHighlight: false }, // LOCKED — keeps Shiki out of the worker
68
+ security: { checkOrigin: false },
69
+ vite: { /* ssr.external, ssr.noExternal, optimizeDeps, plugins — see the file */ },
70
+ })
73
71
  ```
74
72
 
75
- **Why `platformProxy: { enabled: true }`**: proxies CF bindings (KV, D1, R2, secrets) into dev via `wrangler.toml`, so SSR code can read them with the same `env` shape as production. Leave it on.
73
+ **Don't copy a `vite.ssr` list out of this skill.** `astro.config.mjs` §
74
+ `vite.ssr.external` is the authority (`.claude/commands/deploy.md` Rule 2 says so
75
+ explicitly: *never reconcile that file to a doc*). Note the direction — `recharts`,
76
+ Stripe, `@xyflow/react`, `motion`, `media-chrome` and the 100ms packages are
77
+ **external**; `react`, `react-dom`, `@astrojs/react`, `better-auth` and `kysely` are
78
+ **noExternal**. Getting that backwards breaks the build.
79
+
80
+ A companion `ssrExternalPlugin()` also swaps three packages for tiny SSR stubs
81
+ (`pusher-js`, `media-chrome/react`, `@mux/mux-player-react` → `src/lib/stubs/`).
76
82
 
77
83
  ## Adapter v13 — What Changed from Astro 5/v12
78
84
 
@@ -80,14 +86,16 @@ export default defineConfig({
80
86
  |---|---|---|---|
81
87
  | Pages support | ✓ | **removed** | Deploy target is Workers + Static Assets only |
82
88
  | `output: "hybrid"` | ✓ | **removed** | Use `"server"` + `prerender = true` per-page, or `"static"` + `prerender = false` |
83
- | `Astro.locals.runtime` | populated | **removed** | `import { env } from "cloudflare:workers"` |
84
- | `prerenderEnvironment` | n/a | `workerd` default | Set to `"node"` only if prerender breaks under workerd |
85
- | `imageService` default | `"compile"` | `"cloudflare-binding"` | Needs `imagesBindingName` (default `"IMAGES"`) |
86
- | `sessionKVBindingName` | n/a | default `"SESSION"` | Astro session driver reads this binding |
87
- | `workerEntryPoint` | option | **removed** | Adapter emits `dist/_worker.js/index.js` |
89
+ | `Astro.locals.runtime` | populated | **removed** | Use `cloudflare:workers` (see below) |
90
+ | `prerenderEnvironment` | n/a | `workerd` default | ONE sets `'node'` prerender breaks under workerd here |
91
+ | `imageService` default | `"compile"` | `"cloudflare-binding"` | ONE overrides to `'passthrough'` no IMAGES binding needed |
92
+ | `sessionKVBindingName` | n/a | default `"SESSION"` | ONE sets `sessions: false`; the `SESSION` KV is used directly |
93
+ | `workerEntryPoint` | option | **removed** | Adapter emits the bundled entry; `dist/server/wrangler.json` injects it |
88
94
  | `cloudflareModules` | option | **removed** | Use Vite's built-in WASM/text imports |
89
95
 
90
- **Migration memory (save in `.claude/memory/`):** check adapter + deploy-target compatibility BEFORE bumping Astro major. Astro 6's `@astrojs/cloudflare@13` dropped Pages in a single minor jump; ~8-commit cascade to fix.
96
+ **Migration memory:** check adapter + deploy-target compatibility BEFORE bumping
97
+ Astro major. Astro 6's `@astrojs/cloudflare@13` dropped Pages in a single minor jump;
98
+ ~8-commit cascade to fix.
91
99
 
92
100
  ## Output Modes (Astro 6)
93
101
 
@@ -103,39 +111,47 @@ export const prerender = false // force SSR — runs in worker
103
111
  | `"server"` | SSR | ONE's choice — most routes are dynamic; static pages opt in |
104
112
  | `"hybrid"` | — | **removed** in Astro 6; use `"server"` + per-page `prerender = true` |
105
113
 
106
- **ONE's rule:** `output: "server"`. Static shell pages export `prerender = true` AND load heavy islands with `client:only="react"`. That collapses the page handler to a ~63-byte stub — the worker doesn't ship React for pre-rendered pages.
114
+ **ONE's rule:** `output: "server"`. Static shell pages export `prerender = true` AND
115
+ load heavy islands with `client:only="react"`, so the worker ships no React for them.
116
+ Current split in `src/pages`: 53 files `prerender = true`, 601 `prerender = false`.
107
117
 
108
118
  ## cloudflare:workers — The Canonical Env Import
109
119
 
120
+ **Always the dynamic form.** A top-level `import { env } from "cloudflare:workers"`
121
+ is not used anywhere in this tree (0 files under `src/`); the dynamic import is (407 files). The
122
+ static import resolves at module-eval time, which breaks prerender and any non-worker
123
+ context that touches the module.
124
+
110
125
  ```ts
111
126
  // src/pages/api/whatever.ts (SSR API route)
112
- import { env } from "cloudflare:workers";
127
+ import type { APIRoute } from "astro";
113
128
 
114
- export const GET: APIRoute = async ({ request }) => {
115
- const paths = await env.KV.get("paths.json", "json");
129
+ type Env = { DB?: D1Database; SESSION?: KVNamespace }
130
+
131
+ async function getEnv(): Promise<Env> {
132
+ return (await import('cloudflare:workers' as string)).env as Env
133
+ }
134
+
135
+ export const GET: APIRoute = async () => {
136
+ const env = await getEnv()
137
+ if (!env.DB) return Response.json({ error: 'no_db' }, { status: 503 })
116
138
  const { results } = await env.DB.prepare("SELECT * FROM signals LIMIT 10").all();
117
- return Response.json({ paths, signals: results });
139
+ return Response.json({ signals: results });
118
140
  };
119
141
  ```
120
142
 
121
- **Typing (wrangler 4):**
122
- ```bash
123
- bun wrangler types # emits worker-configuration.d.ts from wrangler.toml bindings
124
- ```
125
-
126
- Pipe it into dev/build scripts so `env.KV`, `env.DB` etc. are typed against actual bindings:
127
-
128
- ```jsonc
129
- // package.json scripts
130
- {
131
- "dev": "wrangler types && astro dev",
132
- "build": "wrangler types && astro build"
133
- }
134
- ```
143
+ **Typing.** There is no `worker-configuration.d.ts` in this tree and `wrangler types`
144
+ is not wired into any script. Bindings are typed by hand in `src/env.d.ts` — the
145
+ `Runtime` interface lists every binding (`DB`, `CONTENT`, `SESSION`, `CHAT_CACHE`,
146
+ `ANALYTICS_HUB`, `WORKFLOW_RUN`, …) alongside `App.Locals`. Add a new binding there
147
+ when you add it to `wrangler.toml`. Routes that declare a narrow local `Env` type (as
148
+ above) are the prevailing pattern.
135
149
 
136
150
  ### Legacy `Astro.locals.runtime.env` (compat shim)
137
151
 
138
- ONE still has code reading `locals?.runtime?.env?.DB` from the Astro 5 era. The Cycle 1 shim (`src/env.d.ts`) keeps this working until we migrate callers. **New code uses `import { env } from "cloudflare:workers"` directly** — it's typed, guaranteed populated on Workers, and survives the shim's removal.
152
+ `src/env.d.ts` still declares `runtime?: Runtime` on `App.Locals`, and 7 files read
153
+ `locals?.runtime?.env?.*` from the Astro 5 era. **New code uses the dynamic
154
+ `cloudflare:workers` import** — it survives the shim's removal.
139
155
 
140
156
  ## Hydration Directives (unchanged in Astro 6)
141
157
 
@@ -147,7 +163,11 @@ client:only="react" → Client-only, skip SSR entirely (heavy deps, keeps worker
147
163
  client:media="(min-width: 768px)" → Hydrate on media query match
148
164
  ```
149
165
 
150
- **Bundle rule (LOCKED, CLAUDE.md):** heavy components (shiki, @mysten/sui, recharts if not chunked) MUST be `client:only="react"` OR listed in `vite.ssr.external`. Otherwise the SSR worker crosses 10 MiB and deploy fails.
166
+ **Bundle rule (LOCKED):** heavy components (shiki, recharts, Stripe, 100ms, Puck)
167
+ MUST be `client:only="react"` OR listed in `vite.ssr.external`. Both together is the
168
+ common case — `ssr.external` is only safe when the package never executes on the
169
+ server path, and `client:only` is what guarantees that. 216 `client:only="react"`
170
+ uses across pages and components today.
151
171
 
152
172
  ## Page Patterns
153
173
 
@@ -172,9 +192,9 @@ export const prerender = true;
172
192
  // src/pages/dashboard.astro
173
193
  import Layout from "@/layouts/Layout.astro";
174
194
  import Dashboard from "@/components/Dashboard";
175
- import { env } from "cloudflare:workers";
176
195
 
177
- const paths = await env.KV.get("paths.json", "json") ?? [];
196
+ const { env } = await import('cloudflare:workers' as string);
197
+ const paths = (await env.CHAT_CACHE?.get("paths.json", "json")) ?? [];
178
198
  ---
179
199
  <Layout title="Dashboard">
180
200
  <Dashboard client:load paths={paths} />
@@ -186,65 +206,78 @@ const paths = await env.KV.get("paths.json", "json") ?? [];
186
206
  ```ts
187
207
  // src/pages/api/signal.ts
188
208
  import type { APIRoute } from "astro";
189
- import { env } from "cloudflare:workers";
209
+
210
+ export const prerender = false
190
211
 
191
212
  export const POST: APIRoute = async ({ request }) => {
213
+ const { env } = await import('cloudflare:workers' as string);
192
214
  const signal = await request.json();
193
- await env.KV.put(`signal:${Date.now()}`, JSON.stringify(signal));
215
+ await env.CHAT_CACHE.put(`signal:${Date.now()}`, JSON.stringify(signal));
194
216
  return Response.json({ received: true });
195
217
  };
196
218
  ```
197
219
 
198
220
  ## Bundle-Size Rules (LOCKED — do not revert)
199
221
 
200
- The Worker upload must stay under **3 MiB gzipped** on the CF free tier (10 MiB paid).
201
- Wrangler reports both `Total Upload` and `gzip` only the gzip number counts.
202
- See `.claude/commands/deploy.md § Bundle Size` for full diagnosis.
222
+ Wrangler reports both `Total Upload` (uncompressed) and `gzip` only gzip counts.
223
+ The documented ceiling is **3 MiB gzipped** free tier / 10 MiB paid, but this
224
+ account's real ceiling is **unconfirmed**: deploys at 3.22 MiB (2026-07-08) and
225
+ 4.43 MiB (2026-07-19) both succeeded. Treat the current number as a floor to watch,
226
+ not a hard gate, and re-run the diagnosis if it keeps climbing.
227
+ `.claude/commands/deploy.md § Bundle Size Rules` + § Verified Bundle Numbers is the
228
+ authority — reconcile to it, not to this table.
203
229
 
204
230
  | Rule | Where | Saves |
205
231
  |---|---|---|
206
232
  | `markdown: { syntaxHighlight: false }` | `astro.config.mjs` | ~5.8 MiB (Shiki grammars/WASM) |
207
- | `ssr.external: ["shiki", "@mysten/sui", "@mysten/bcs", "node:async_hooks"]` | `astro.config.mjs` | Bare imports — safe only if package never runs server-side (shiki callers are all `client:only`) |
208
- | `prerender = true` + `client:only="react"` on shell pages | per-page | Handler collapses to ~63-byte stub |
209
- | `build: { inlineStylesheets: 'auto' }` — **NEVER `'always'`** | `astro.config.mjs` | ~8 MiB at 100+ routes. `'always'` inlines the full Tailwind stylesheet into every route's manifest entry, ballooning worker-entry by N×stylesheet-size. `'auto'` ships one external `<link>` referenced once. |
233
+ | `vite.ssr.external` for heavy packages | `astro.config.mjs` | Bare imports — safe only if the package never runs server-side (shiki's callers are all `client:only`) |
234
+ | `prerender = true` + `client:only="react"` on shell pages | per-page | Page handler collapses to a stub; no React in the worker |
235
+ | `build: { inlineStylesheets: 'auto' }` — **NEVER `'always'`** | `astro.config.mjs` | ~8 MiB at 100+ routes. `'always'` inlines the full Tailwind stylesheet into every route's manifest entry. `'auto'` ships one external `<link>`. |
236
+ | `react-dom/server` → `react-dom/server.edge` alias, production only | `astro.config.mjs` `vite.resolve.alias` | Ships the edge build instead of the Node build |
210
237
 
211
238
  Verified deltas:
212
239
  - 2026-04-15: 21 MiB Pages → 9.5 MiB Worker (Rules 1-3). Pages deploy FAILED → Workers ✓.
213
- - 2026-05-22: worker-entry 9.5 MiB → 672 KiB (Rule 4). gzip 3.3 MiB → 2.1 MiB. Deploy unblocked on free tier.
240
+ - 2026-05-22: worker-entry 9.5 MiB → 672 KiB (Rule 4). gzip 3.3 MiB → 2.1 MiB.
214
241
 
215
242
  ## Dev Commands
216
243
 
217
244
  ```bash
218
- bun run dev # localhost:4321, Node standalone (fast HMR, no miniflare)
219
- bun run build # astro build dist/ + dist/_worker.js/index.js
220
- bun run preview # wrangler dev against dist/ (production-shape check)
221
-
222
- # Per-env wrangler dev (hits real CF bindings)
223
- bun wrangler dev --remote # against production KV/D1 — use with care
224
- bun wrangler dev --local # local miniflare + local KV (default)
225
-
226
- # Types
227
- bun wrangler types # regenerate worker-configuration.d.ts
228
- astro check # tsc on .astro files + tsconfig
245
+ bun run dev # localhost:4321 regenerates playbook meta + promises, then astro dev
246
+ bun run build # builds @oneie/sdk, astro build, patches dist/server/wrangler.json
247
+ bun run preview # astro preview (NOT wrangler — see dev:wrangler for production shape)
248
+ bun run dev:wrangler # build + wrangler dev against dist/server/wrangler.json on :8787
249
+ bun run check # astro check
250
+ bun run typecheck # tsc --noEmit
251
+ bun run verify # build SDK + typecheck + vitest — the gate
252
+
253
+ # Bindings against real CF resources
254
+ bun wrangler dev --remote # production KV/D1 — use with care
229
255
  ```
230
256
 
257
+ There is no `wrangler types` step. Bindings are hand-typed in `src/env.d.ts`.
258
+
231
259
  ## Dynamic Routes
232
260
 
261
+ Real routes in this tree:
262
+
233
263
  ```
234
264
  src/pages/
235
- agents/[id].astro → /agents/donal, /agents/amara
236
- envelopes/[...path].astro catch-all
237
- api/memory/[uid].ts /api/memory/tony-tiger
265
+ p/[slug].astro → /p/my-landing-page
266
+ studio/[agent].astro /studio/donal
267
+ u/[slug]/[...path].astro catch-all under a workspace
268
+ go/[id].ts → a dynamic API-shaped route (.ts, not .astro)
269
+ tasks/[...view].astro → catch-all
238
270
  ```
239
271
 
240
272
  ```astro
241
273
  ---
242
- // src/pages/agents/[id].astro
243
- const { id } = Astro.params;
244
- if (!id) return new Response(null, { status: 404 });
274
+ // src/pages/studio/[agent].astro
275
+ export const prerender = false
276
+ const { agent } = Astro.params;
277
+ if (!agent) return new Response(null, { status: 404 });
245
278
  ---
246
- <Layout title={`Agent: ${id}`}>
247
- <AgentCard client:load agentId={id} />
279
+ <Layout title={`Studio: ${agent}`}>
280
+ <AgentCard client:load agentId={agent} />
248
281
  </Layout>
249
282
  ```
250
283
 
@@ -256,68 +289,80 @@ if (!id) return new Response(null, { status: 404 });
256
289
  | API routes | `src/pages/api/**/*.ts` |
257
290
  | Layouts | `src/layouts/*.astro` |
258
291
  | React islands | `src/components/**/*.tsx` |
259
- | Styles | `src/styles/global.css` |
292
+ | Content collections | `src/content.config.ts` + `src/content/` |
260
293
  | Astro config | `astro.config.mjs` |
261
- | Worker config | `wrangler.toml` |
262
- | Locals types | `src/env.d.ts` |
294
+ | Worker config | `wrangler.toml` (`main` intentionally omitted) |
295
+ | Binding + Locals types | `src/env.d.ts` |
263
296
 
264
297
  ## Performance Budgets (from `text/speed.md`)
265
298
 
266
- | Metric | Budget |
299
+ | Metric | Measured |
267
300
  |---|---|
268
- | Routing (in-memory) | <0.005ms |
269
- | Gateway health | <10ms |
270
- | API route TTFB | <200ms |
271
- | Full page TTFB | <500ms |
301
+ | Routing decision (in-memory) | <0.005ms (320 tests) |
302
+ | KV read / highway cache (edge) | <10ms |
303
+ | `ask()` round-trip (no LLM) | 50–200ms |
304
+ | Chat TTFB p50 (browser) | ~97ms — gate ≤100ms |
305
+ | Agent first SSE token (end-to-end) | ~500ms |
272
306
 
273
- Static pages served from `[assets]` binding don't count against request quota — pre-render anything that doesn't need SSR.
307
+ Static pages served from the `[assets]` binding don't count against request quota —
308
+ pre-render anything that doesn't need SSR.
274
309
 
275
310
  ## Common Tasks
276
311
 
312
+ Five sub-workflows live beside this file: `create-page.md`, `create-component.md`,
313
+ `add-content-collection.md`, `check-build.md`, `optimize-performance.md`.
314
+
277
315
  ### Add a new page
278
316
 
279
- 1. Create `src/pages/<name>.astro` with Layout import
317
+ 1. Create `src/pages/<name>.astro` with a Layout import
280
318
  2. If mostly static → `export const prerender = true`
281
- 3. If needs CF bindings → `import { env } from "cloudflare:workers"` in frontmatter
282
- 4. React islands: default to `client:visible`; use `client:load` only for above-fold critical UI
319
+ 3. If it needs CF bindings → `await import('cloudflare:workers')` in frontmatter
320
+ 4. React islands: default to `client:visible`; `client:load` only for above-fold critical UI
283
321
 
284
322
  ### Add an API route
285
323
 
286
- 1. Create `src/pages/api/<name>.ts`
324
+ 1. Create `src/pages/api/<name>.ts`, `export const prerender = false`
287
325
  2. Export `GET` / `POST` / `PUT` / `DELETE` as `APIRoute`
288
- 3. Read bindings via `import { env } from "cloudflare:workers"`
289
- 4. Return `Response.json(...)` or `new Response(...)`
326
+ 3. Read bindings via `(await import('cloudflare:workers')).env`
327
+ 4. Authorize before touching workspace data (`authorizeWorkspace` from `@/lib/analytics/authz`)
328
+ 5. Return `Response.json(...)` or `new Response(...)`
290
329
 
291
330
  ### Convert static component to interactive
292
331
 
293
332
  1. Create `.tsx` in `src/components/`
294
- 2. Import into `.astro` page
333
+ 2. Import into the `.astro` page
295
334
  3. Pick directive: above-fold → `client:load`, below-fold → `client:visible`, heavy → `client:only="react"`
296
335
 
297
336
  ### Type a new binding
298
337
 
299
- 1. Add binding to `wrangler.toml` (`[[kv_namespaces]]`, `[[d1_databases]]`, etc.)
300
- 2. Run `bun wrangler types` updates `worker-configuration.d.ts`
301
- 3. `env.NEW_BINDING` is now typed everywhere
338
+ 1. Add the binding to `wrangler.toml` (`[[kv_namespaces]]`, `[[d1_databases]]`, etc.)
339
+ 2. Add the field to the `Runtime.env` interface in `src/env.d.ts` (by hand — no codegen)
340
+ 3. Narrow it in the route's local `Env` type where you read it
302
341
 
303
342
  ## Gotchas
304
343
 
305
- - **Dev uses Node, prod uses workerd.** Behavior can diverge. Always `bun run preview` before deploy for production-shape smoke.
306
- - **`import.meta.env.*`** is build-time only. For runtime secrets/bindings use `env` from `cloudflare:workers`.
344
+ - **Dev and prod both run the Cloudflare adapter**, but dev goes through Vite +
345
+ Miniflare. Behaviour still diverges `bun run dev:wrangler` for a production-shape smoke.
346
+ - **A top-level `import { env } from "cloudflare:workers"` breaks prerender.** Always
347
+ the dynamic form. Zero files in this tree use the static one.
348
+ - **`import.meta.env.*`** is build-time only. Runtime secrets/bindings come from `env`.
307
349
  - **Shiki will crash your deploy** if imported from SSR. All callers must be `client:only="react"`.
308
- - **`output: "hybrid"`** throws in Astro 6. If you see it in old docs or snippets, replace with `"server"` + `prerender = true` per page.
309
- - **`Astro.locals.runtime.env`** is a v12 pattern. ONE has a compat shim but new code must use `cloudflare:workers`.
310
- - **`wrangler types`** must run before `astro build` or bindings are untyped. Script it in `package.json`.
350
+ - **`output: "hybrid"`** throws in Astro 6. Replace with `"server"` + per-page `prerender = true`.
351
+ - **Never delete a `vite.ssr.external` entry to match a doc snippet** the config file is
352
+ the authority and the list is longer than any snippet.
353
+ - **`platformProxy: { enabled: true }`** is wrong here. This tree uses
354
+ `{ environment: undefined }` so `astro build` doesn't make Miniflare evaluate the
355
+ Durable Object before `durableObjectExportsPlugin` has run.
311
356
 
312
357
  ## References
313
358
 
314
359
  - [Astro Cloudflare adapter](https://docs.astro.build/en/guides/integrations-guide/cloudflare/) — authoritative for v13
315
360
  - [CF Workers framework guide — Astro](https://developers.cloudflare.com/workers/frameworks/framework-guides/astro/)
316
- - `docs/cf-workers-migration-todo.md` — C1+C2+C3 shipped; `dev.one.ie` live on Workers
317
- - `docs/deploy.md` — bundle-size diagnosis + LOCKED rules
361
+ - `.claude/commands/deploy.md` — 8-step pipeline, 5 LOCKED bundle rules, verified bundle numbers, rollback
318
362
  - `.claude/rules/astro.md` — auto-loaded on `*.astro` edits
363
+ - `one.ie/web/astro.config.mjs` — the authority for adapter options and every `vite.ssr` list
319
364
 
320
365
  ---
321
366
 
322
- **Version**: 2.0.0 — Astro 6 + CF Workers+Assets (2026-04-18)
323
- **Previous**: 1.0.0 (Astro 5 + CF Pages)
367
+ **Version**: 3.0.0 — reconciled against `one.ie/web` (2026-08-02)
368
+ **Previous**: 2.0.0 (2026-04-18, described a dual-adapter config this tree never had)
@@ -1,30 +1,46 @@
1
1
  # Add Content Collection
2
2
 
3
3
  **Category:** astro
4
- **Version:** 1.0.0
5
- **Used By:** agent-frontend, agent-builder
4
+ **Version:** 2.0.0
5
+ **Used By:** `astro` skill · `/do` W3 edit wave
6
6
 
7
7
  ## Purpose
8
8
 
9
- Creates Astro content collection with schema.
9
+ Adds a collection to `one.ie/web/src/content.config.ts`. This tree is on the Astro
10
+ Content Layer — every collection declares a **`loader`**; the legacy `type: 'content'`
11
+ shape is gone. Five collections exist today: `videos`, `playbook`, `moversPlaybook`,
12
+ `legal`, `blog`.
10
13
 
11
14
  ## Example
12
15
 
13
16
  ```typescript
14
- import { defineCollection, z } from 'astro:content';
15
-
16
- const blog = defineCollection({
17
- schema: z.object({
18
- title: z.string(),
19
- date: z.date(),
20
- author: z.string(),
21
- tags: z.array(z.string()),
22
- }),
17
+ // src/content.config.ts
18
+ import { defineCollection, z } from "astro:content";
19
+ import { glob } from "astro/loaders";
20
+
21
+ const GuideSchema = z.object({
22
+ title: z.string(),
23
+ order: z.number().default(0),
24
+ publishedAt: z.coerce.date(), // coerce — frontmatter dates arrive as strings
25
+ tags: z.array(z.string()).default([]),
26
+ draft: z.boolean().default(false),
23
27
  });
24
28
 
25
- export const collections = { blog };
29
+ const guides = defineCollection({
30
+ loader: glob({ pattern: "**/*.md", base: "./src/content/guides" }),
31
+ schema: GuideSchema,
32
+ });
33
+
34
+ // Append to the single exported object — do not add a second export.
35
+ export const collections = { videos, playbook, moversPlaybook, legal, blog, guides };
26
36
  ```
27
37
 
38
+ Then create `src/content/guides/` and put the markdown in it. Read it with
39
+ `getCollection('guides')`; filter `draft` yourself — the schema defaults it, it
40
+ doesn't exclude it.
41
+
28
42
  ## Version History
29
43
 
44
+ - **2.0.0** (2026-08-02): Rewritten for the Content Layer `loader` API and the real
45
+ `content.config.ts`. The 1.0.0 example used the pre-Astro-5 shape with no loader.
30
46
  - **1.0.0** (2025-10-18): Initial implementation
@@ -1,29 +1,35 @@
1
1
  # Check Astro Build
2
2
 
3
3
  **Category:** astro
4
- **Version:** 1.0.0
5
- **Used By:** agent-quality, agent-ops
4
+ **Version:** 2.0.0
5
+ **Used By:** `astro` skill · `/do` W4 verify wave
6
6
 
7
7
  ## Purpose
8
8
 
9
- Runs Astro build check and reports errors.
9
+ Verify `one.ie/web` compiles before shipping. `astro check` emits **human-readable
10
+ text, not JSON** — parse the exit code, not the stdout.
10
11
 
11
12
  ## Example
12
13
 
13
14
  ```bash
14
- bunx astro check --minimumSeverity warning
15
- ```
15
+ cd one.ie/web
16
16
 
17
- **Output:**
18
- ```json
19
- {
20
- "success": true,
21
- "errors": 0,
22
- "warnings": 0,
23
- "files": 252
24
- }
17
+ bun run verify # THE gate: builds @oneie/sdk, then tsc --noEmit, then vitest run
18
+ bun run check # astro check — types inside .astro templates
19
+ bun run typecheck # tsc --noEmit only (fastest signal on .ts/.tsx)
20
+ bun run build # full production build; the only thing that catches bundler breaks
25
21
  ```
26
22
 
23
+ `astro check` prints a summary line of the form
24
+ `Result (N files): X errors, Y warnings, Z hints` and exits non-zero on errors.
25
+
26
+ **Build the SDK first.** `bun run typecheck` on its own reports phantom `TS2307`
27
+ module-not-found errors when `packages/sdk/dist` is stale or missing — `bun run verify`
28
+ already does the SDK build, which is why it is the gate. In a `/do` worktree also
29
+ confirm `node_modules` is present; a partial install fakes a ratchet violation.
30
+
27
31
  ## Version History
28
32
 
33
+ - **2.0.0** (2026-08-02): Replaced the invented JSON output with the real commands and
34
+ exit-code contract; added the build-SDK-first trap.
29
35
  - **1.0.0** (2025-10-18): Initial implementation