@oneie/claude 0.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 (59) hide show
  1. package/.claude-plugin/plugin.json +16 -0
  2. package/.mcp.json +12 -0
  3. package/README.md +204 -0
  4. package/agents/w1-recon.md +102 -0
  5. package/agents/w2-decide.md +164 -0
  6. package/agents/w3-edit.md +91 -0
  7. package/agents/w4-verify.md +416 -0
  8. package/commands/browser.md +55 -0
  9. package/commands/cc-connect.md +67 -0
  10. package/commands/claw.md +135 -0
  11. package/commands/close.md +143 -0
  12. package/commands/create.md +78 -0
  13. package/commands/deploy.md +415 -0
  14. package/commands/do-autonomous.md +80 -0
  15. package/commands/do-improve.md +51 -0
  16. package/commands/do-show.md +89 -0
  17. package/commands/do.md +226 -0
  18. package/commands/improve.md +99 -0
  19. package/commands/kill.md +45 -0
  20. package/commands/release.md +144 -0
  21. package/commands/see.md +161 -0
  22. package/commands/setup.md +75 -0
  23. package/commands/sync.md +185 -0
  24. package/hooks/hooks.json +90 -0
  25. package/hooks/lib/signal.sh +28 -0
  26. package/hooks/scripts/design-check.sh +83 -0
  27. package/hooks/scripts/post-edit-check.sh +32 -0
  28. package/hooks/scripts/session-end-verify.sh +51 -0
  29. package/hooks/scripts/session-start.sh +88 -0
  30. package/hooks/scripts/stop-reflect.sh +95 -0
  31. package/hooks/scripts/sync-todo-docs.sh +46 -0
  32. package/hooks/scripts/task-complete-verify.sh +52 -0
  33. package/hooks/scripts/tool-signal.sh +48 -0
  34. package/package.json +33 -0
  35. package/rules/api.md +50 -0
  36. package/rules/astro.md +206 -0
  37. package/rules/design.md +221 -0
  38. package/rules/documentation.md +218 -0
  39. package/rules/engine.md +297 -0
  40. package/rules/react.md +137 -0
  41. package/rules/ui.md +82 -0
  42. package/scripts/cc-connect.sh +345 -0
  43. package/scripts/do-analyze.sh +42 -0
  44. package/scripts/do-folder.sh +63 -0
  45. package/scripts/do-prove.sh +51 -0
  46. package/scripts/do-reconcile.sh +28 -0
  47. package/scripts/do-smoke.sh +60 -0
  48. package/scripts/do-survey.sh +30 -0
  49. package/scripts/do-tier.sh +43 -0
  50. package/skills/build/SKILL.md +52 -0
  51. package/skills/cloudflare/SKILL.md +503 -0
  52. package/skills/dev/SKILL.md +58 -0
  53. package/skills/do/SKILL.md +24 -0
  54. package/skills/oneie/SKILL.md +51 -0
  55. package/skills/perf/SKILL.md +45 -0
  56. package/skills/signal/SKILL.md +108 -0
  57. package/skills/sui/SKILL.md +441 -0
  58. package/skills/tutorial/SKILL.md +96 -0
  59. package/skills/typecheck/SKILL.md +66 -0
package/rules/astro.md ADDED
@@ -0,0 +1,206 @@
1
+ ---
2
+ paths:
3
+ - "**/*.astro"
4
+ ---
5
+
6
+ # Astro Rules
7
+
8
+ Apply to `*.astro`
9
+
10
+ ---
11
+
12
+ ## Structure
13
+
14
+ ```
15
+ src/pages/ # Routes
16
+ src/layouts/ # Layouts
17
+ src/components/ # Components
18
+ ```
19
+
20
+ ---
21
+
22
+ ## Frontmatter
23
+
24
+ ```astro
25
+ ---
26
+ interface Props {
27
+ title: string
28
+ }
29
+ const { title } = Astro.props
30
+ ---
31
+ ```
32
+
33
+ Always TypeScript. Always typed.
34
+
35
+ ---
36
+
37
+ ## Hydration
38
+
39
+ ```
40
+ ┌────────────────────┬─────────────────────────────────────┐
41
+ │ client:load │ Critical, above-fold, interactive │
42
+ ├────────────────────┼─────────────────────────────────────┤
43
+ │ client:visible │ Below-fold, lazy │
44
+ ├────────────────────┼─────────────────────────────────────┤
45
+ │ client:idle │ Non-critical widgets │
46
+ ├────────────────────┼─────────────────────────────────────┤
47
+ │ client:only="react"│ Client-only, skip SSR │
48
+ └────────────────────┴─────────────────────────────────────┘
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Islands
54
+
55
+ ```astro
56
+ <!-- Static — no JS shipped -->
57
+ <AgentCard agent={agent} />
58
+
59
+ <!-- Interactive — hydrates -->
60
+ <AgentCard client:load agent={agent} onClick={handle} />
61
+
62
+ <!-- Lazy — hydrates when visible -->
63
+ <ColonyGraph client:visible highways={highways} />
64
+ ```
65
+
66
+ Only add `client:*` when interactivity is needed.
67
+
68
+ ---
69
+
70
+ ## Imports
71
+
72
+ ```astro
73
+ ---
74
+ // Good — path aliases
75
+ import Layout from "@/layouts/Layout.astro"
76
+ import { ColonyEditor } from "@/components/graph/ColonyEditor"
77
+
78
+ // Bad — relative paths
79
+ import Layout from "../../../layouts/Layout.astro"
80
+ ---
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Styles
86
+
87
+ ```astro
88
+ <!-- Scoped -->
89
+ <style>
90
+ .container { ... }
91
+ </style>
92
+
93
+ <!-- Global (sparingly) -->
94
+ <style is:global>
95
+ .colony-graph { ... }
96
+ </style>
97
+
98
+ <!-- Tailwind (preferred) -->
99
+ <div class="bg-[#0a0a0f] p-4 rounded-lg">
100
+ ```
101
+
102
+ ---
103
+
104
+ ## With Substrate
105
+
106
+ ```astro
107
+ ---
108
+ import Layout from "@/layouts/Layout.astro"
109
+ import { ColonyEditor } from "@/components/graph/ColonyEditor"
110
+ ---
111
+
112
+ <Layout title="Colony">
113
+ <ColonyEditor client:load />
114
+ </Layout>
115
+ ```
116
+
117
+ - `client:load` — interactive graph needs JS
118
+ - Colony state lives in React component
119
+ - Astro handles routing, layout, SSR shell
120
+
121
+ ---
122
+
123
+ ---
124
+
125
+ ## Performance — lazy imports inside islands
126
+
127
+ **Every `client:*` island ships its entire static import graph on first load.**
128
+ Any component not needed for the initial render that is statically imported will
129
+ block FCP/LCP.
130
+
131
+ **Rule:** Any heavy component inside a hydrated island that is NOT required for
132
+ first render MUST use `lazy()` + `Suspense`.
133
+
134
+ ### `inlineStylesheets` — LOCKED to `'auto'` on Workers
135
+
136
+ `astro.config.mjs` MUST set `build: { inlineStylesheets: 'auto' }` (Astro's
137
+ default). **Never `'always'`.** Under the Cloudflare adapter, `'always'`
138
+ inlines the full stylesheet into every route's serialized manifest entry —
139
+ with N routes, the worker-entry chunk grows by N × stylesheet size. On a
140
+ ~100-route site that single config flag adds ~8 MiB and breaks the 3 MiB
141
+ gzipped upload limit. Diagnose by checking for a multi-MB string literal in
142
+ worker-entry: `awk 'length > 100000 { print NR, length }' dist/server/chunks/worker-entry_*.mjs`.
143
+
144
+ **Known heavy modules to always lazy-import inside islands:**
145
+
146
+ | Module | Why |
147
+ |--------|-----|
148
+ | `@/components/ai-elements/attachments` | ~281 KB — file-picker, previews |
149
+ | `@/components/ai-elements/speech-input` | mic/audio APIs |
150
+ | `@/components/ai-elements/voice-menu` | voice controls |
151
+ | `@/components/pay/PayPanel` | payment UI |
152
+ | `@/components/chat/MessageList` | scroll list |
153
+
154
+ ```tsx
155
+ // ✅ Correct — deferred until user action
156
+ const AttachmentsPreview = lazy(() =>
157
+ import('@/components/chat/AttachmentsPreview')
158
+ .then(m => ({ default: m.AttachmentsPreview })))
159
+
160
+ // Inside JSX:
161
+ <Suspense fallback={null}>
162
+ <AttachmentsPreview />
163
+ </Suspense>
164
+
165
+ // ❌ Wrong — pulls 281 KB into the initial island bundle
166
+ import { Attachments } from '@/components/ai-elements/attachments'
167
+ ```
168
+
169
+ **Testing:** run `npx lighthouse <url> --chrome-flags="--headless --no-sandbox" --output=json`
170
+ then check `audits['unused-javascript'].details.items` — items > 50 KB are candidates
171
+ for lazy conversion.
172
+
173
+ ---
174
+
175
+ ## Dark mode — WCAG AA contrast invariant
176
+
177
+ **Default:** `<html class="dark">` — Lighthouse always runs in dark mode
178
+ (no `localStorage`). All contrast checks happen against dark tokens.
179
+
180
+ **Dark mode brand token rule:**
181
+ Brand fills lighten to L≥65% in dark mode (so they're visible on dark
182
+ backgrounds). At L≥65%, `#fff` text fails WCAG AA. `on-*` labels MUST flip
183
+ to `#000` in `html.dark`.
184
+
185
+ In `Layout.astro` `html.dark` block, always include:
186
+
187
+ ```css
188
+ html.dark {
189
+ --color-primary: hsl(216 55% 65%); /* L=65 — needs dark label */
190
+ --color-secondary: hsl(219 14% 65%); /* L=65 — needs dark label */
191
+ --color-tertiary: hsl(105 22% 65%); /* L=65 — needs dark label */
192
+ --color-on-primary: #000; /* ← REQUIRED for WCAG AA */
193
+ --color-on-secondary: #000; /* ← REQUIRED for WCAG AA */
194
+ --color-on-tertiary: #000; /* ← REQUIRED for WCAG AA */
195
+ }
196
+ ```
197
+
198
+ **The JS `onLabel()` function in Layout.astro handles theme overrides** (stored
199
+ themes from the editor). The CSS defaults above handle the no-localStorage case
200
+ (Lighthouse, first visit, SSR).
201
+
202
+ Threshold: `L < 60 → #fff`, `L ≥ 60 → #000`. Default dark brand L=65, so always `#000`.
203
+
204
+ ---
205
+
206
+ *Astro 6. Islands. Fast. 100% Lighthouse.*
@@ -0,0 +1,221 @@
1
+ ---
2
+ paths:
3
+ - "one.ie/web/**/*.tsx"
4
+ - "one.ie/web/**/*.astro"
5
+ - "one.ie/web/**/*.css"
6
+ ---
7
+
8
+ # Design System Rules
9
+
10
+ Apply to `one.ie/web/**/*.tsx`, `one.ie/web/**/*.astro`, `one.ie/web/**/*.css`
11
+
12
+ The design system is **6 tokens**. Spec: [`design.md`](../../design.md). Showcase: `/design`.
13
+ The build itself enforces this — `--color-*: initial` in `Layout.astro` strips Tailwind's
14
+ default palette so wrong colors emit no CSS. Don't fight the enforcement.
15
+
16
+ ---
17
+
18
+ ## The 6 editable tokens (the only colors a user can pick)
19
+
20
+ | Token | Use for |
21
+ | --- | --- |
22
+ | `background` | Card surfaces, sidebars, page-level panels |
23
+ | `foreground` | Inner content rectangles inside cards |
24
+ | `font` | All body text |
25
+ | `primary` | Main CTAs, brand accents, focus rings |
26
+ | `secondary` | Supporting actions, secondary buttons |
27
+ | `tertiary` | Highlights, success checks, accents |
28
+
29
+ ## Plus 5 invariants (never editable)
30
+
31
+ `white` · `black` · `transparent` · `destructive` (errors/deletes) · `success` (confirms).
32
+
33
+ ## Plus derived helpers (auto-computed — don't set directly)
34
+
35
+ Color: `on-primary` · `on-secondary` · `on-tertiary` (auto-contrast labels for brand fills) · `border` (= font @ 10%) · `border-strong` (= font @ 20%) · `muted` (= font @ 60%) · `faint` (= font @ 40%) · `ring` (= primary) · `page` (= background mixed with 4% font — L0 page shell).
36
+
37
+ Polish constants (baked, not exposed): `--radius-sm` 6px · `--radius-md` 10px · `--radius-lg` 16px · `--shadow-card` · `--shadow-pop` · `--ease` 120ms.
38
+
39
+ ## Three depth levels
40
+
41
+ | Level | Surface | Where |
42
+ | --- | --- | --- |
43
+ | L0 page | `--color-page` | `<body>`, full-bleed shell |
44
+ | L1 card | `--color-background` | Cards, sidebar, popovers, dropdowns |
45
+ | L2 content | `--color-foreground` | Card body, inputs, code blocks |
46
+
47
+ Sidebar = L1. Inputs = L2. There is no L3. A card header/footer shares the card surface; never tint them separately.
48
+
49
+ ---
50
+
51
+ ## Allowed utilities
52
+
53
+ ```
54
+ bg-{background|foreground|primary|secondary|tertiary|destructive|success|white|black|transparent}
55
+ text-{font|primary|secondary|tertiary|on-primary|on-secondary|on-tertiary|destructive|success|white|black}
56
+ border-{font|primary|secondary|tertiary}
57
+ ring-{primary|secondary|tertiary}
58
+ ```
59
+
60
+ **Use the auto-contrast `on-*` labels on brand fills** — they stay readable when the user picks any color:
61
+
62
+ ```tsx
63
+ <button className="bg-primary text-on-primary">Primary</button>
64
+ <button className="bg-tertiary text-on-tertiary">Tertiary</button>
65
+ ```
66
+
67
+ For muted text, borders, and focus rings, use alpha modifiers or `var()` — these are CSS-only helpers, not Tailwind utilities:
68
+
69
+ ```tsx
70
+ text-font/60 // muted body text
71
+ text-font/40 // disabled / placeholder
72
+ border-font/10 // subtle borders
73
+ bg-primary/20 // tinted brand backgrounds
74
+ style={{ borderColor: 'var(--color-border)' }} // when alpha modifier won't fit
75
+ ```
76
+
77
+ The `--color-{border,muted,ring}` CSS vars exist (defined in `Layout.astro`) but are not Tailwind tokens — Tailwind v4 chokes on `var()` references inside `@theme`. Use them via `var()` only when needed.
78
+
79
+ ---
80
+
81
+ ## Banned
82
+
83
+ - ❌ Any Tailwind palette class: `bg-zinc-*`, `text-indigo-*`, `border-slate-*`, `text-emerald-*`, etc.
84
+ - ❌ Hex literals in JSX/CSS: `#fff`, `#0a0a0f`, `style={{ color: '#abc' }}`
85
+ - ❌ Raw `hsl(...)` / `rgb(...)` outside `Layout.astro` (token source) and `design.astro` (showcase)
86
+ - ❌ Adding a 7th token. Derive with alpha modifiers or `color-mix()`.
87
+ - ❌ Mixing icon sets. Lucide only — via `<Icon>` / `<IconBadge>` (in `web/src/components/ui/`).
88
+ - ❌ Inline SVG icons in React components. Import from `lucide-react` and wrap.
89
+ - ❌ Unicode icon glyphs (☀ ☾ ▾ ✓ ✗). They render differently across OSes — use lucide.
90
+
91
+ ---
92
+
93
+ ## Patterns
94
+
95
+ ### Card (header · body · footer)
96
+
97
+ One shape, three slots. Header and footer share the card surface; only the body switches to `foreground`.
98
+
99
+ ```tsx
100
+ <article
101
+ className="bg-background border rounded-2xl flex flex-col"
102
+ style={{ borderColor: 'var(--color-border)', boxShadow: 'var(--shadow-card)' }}
103
+ >
104
+ <header className="flex items-start justify-between gap-4 px-5 pt-5">
105
+ <div>
106
+ <h3 className="text-base font-bold">Title</h3>
107
+ <p className="text-font/60 text-sm">Meta</p>
108
+ </div>
109
+ <span className="px-2.5 py-1 rounded-full text-xs bg-foreground text-font/60 border" style={{ borderColor: 'var(--color-border)' }}>badge</span>
110
+ </header>
111
+
112
+ <div className="mx-5 mt-4 p-4 bg-foreground rounded-xl border" style={{ borderColor: 'var(--color-border)' }}>
113
+ {/* L2 — data, inputs, charts */}
114
+ </div>
115
+
116
+ <footer
117
+ className="flex items-center justify-between gap-3 px-5 py-4 mt-4 border-t"
118
+ style={{ borderColor: 'var(--color-border)' }}
119
+ >
120
+ <span className="text-font/60 text-sm">Updated 2m ago</span>
121
+ <div className="flex gap-2">
122
+ <button className="px-4 py-2 rounded-lg text-font">Cancel</button>
123
+ <button className="px-4 py-2 rounded-lg bg-primary text-on-primary">Save</button>
124
+ </div>
125
+ </footer>
126
+ </article>
127
+ ```
128
+
129
+ ### Icons
130
+
131
+ One source: `lucide-react`. Two wrappers in `web/src/components/ui/`:
132
+
133
+ ```tsx
134
+ import { Send, Zap } from 'lucide-react'
135
+ import { Icon } from '@/components/ui/Icon'
136
+ import { IconBadge } from '@/components/ui/IconBadge'
137
+
138
+ // Inline — inherits parent color via currentColor
139
+ <Icon icon={Send} size="md" />
140
+
141
+ // Colored badge — feature grids, list rows, profile blocks
142
+ <IconBadge icon={Zap} tone="primary" size="md" />
143
+ ```
144
+
145
+ `Icon` sizes: `sm` 14 · `md` 16 · `lg` 20 · `xl` 24. Stroke is locked to 1.5.
146
+ `IconBadge` tones: `primary` · `secondary` · `tertiary` · `neutral`. Surface is `color-mix(tone 14%, foreground)` — brighter than the card outer, tinted toward the tone color.
147
+
148
+ In Astro pages where you can't easily import React, use inline SVG with `viewBox="0 0 24 24"`, `stroke="currentColor"`, `stroke-width="1.5"`, `stroke-linecap="round"`, `stroke-linejoin="round"`. Copy paths from `lucide.dev`. Never use unicode glyphs.
149
+
150
+ ### Form fields
151
+
152
+ Inputs use `background` (sunken), not `foreground` (raised). The card body is `foreground`; inputs sink back to `background` so they stand out as interactive surfaces against the body.
153
+
154
+ ```tsx
155
+ <div className="flex flex-col gap-1.5">
156
+ <label htmlFor="name" className="text-sm font-medium">Name</label>
157
+ <input
158
+ id="name"
159
+ type="text"
160
+ className="px-3.5 py-2.5 rounded-lg bg-background text-font border focus:outline-none"
161
+ style={{ borderColor: 'var(--color-border)' }}
162
+ placeholder="Ada Lovelace"
163
+ />
164
+ <span className="text-xs text-font/60">Shown on your public profile</span>
165
+ </div>
166
+ ```
167
+
168
+ Focus uses `--color-ring` border + 3px `ring/25` glow. Error uses `aria-invalid='true'` → border `destructive`. Placeholder uses `--color-muted`. Checkbox/radio also use `bg-background` so they pop against the body.
169
+
170
+ ### Buttons (6 variants)
171
+
172
+ ```tsx
173
+ <button className="bg-primary text-white rounded-lg px-4 py-2 hover:brightness-110">Primary</button>
174
+ <button className="bg-secondary text-white rounded-lg px-4 py-2 hover:brightness-110">Secondary</button>
175
+ <button className="bg-tertiary text-white rounded-lg px-4 py-2 hover:brightness-110">Tertiary</button>
176
+ <button className="border border-primary text-font rounded-lg px-4 py-2">Outline</button>
177
+ <button className="text-font rounded-lg px-4 py-2">Ghost</button>
178
+ <button className="bg-font text-foreground rounded-lg px-4 py-2 hover:brightness-95">Inverse</button>
179
+ ```
180
+
181
+ ### Muted text
182
+
183
+ ```tsx
184
+ <p className="text-font/60">Secondary copy</p>
185
+ <p className="text-font/40">Disabled / hint</p>
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Enforcement
191
+
192
+ Three layers, all automatic:
193
+
194
+ 1. **Build-time kill** — `Layout.astro` declares `--color-*: initial` in `@theme`,
195
+ wiping Tailwind's default palette. `bg-zinc-950` produces no CSS.
196
+ 2. **PostToolUse hook** — `.claude/hooks/design-check.sh` greps every Write/Edit
197
+ to `one.ie/web/**/*.{tsx,astro,css}` for banned patterns. Exit 2 on violation feeds
198
+ the diff back to Claude as a tool error; the model self-corrects next turn.
199
+ 3. **This rule** — auto-loaded on the same files via `.claude/settings.json`,
200
+ so the constraints are in context before the first character is written.
201
+
202
+ The hook allowlists `Layout.astro` (token source) and `design.astro` (showcase).
203
+ There is no opt-out for other files.
204
+
205
+ ---
206
+
207
+ ## Don't
208
+
209
+ - Don't introduce a 7th token. Derive instead.
210
+ - Don't use `text-zinc-*` etc. — they emit no CSS, but stop the next reader from trusting the codebase.
211
+ - Don't write `style={{ color: '...' }}` — break the token enforcement.
212
+ - Don't use shadcn's `accent` name; it's `tertiary` here.
213
+ - Don't flip brand colors with mode — only surfaces flip.
214
+ - Don't add a 4th depth level. Page → card → content. A card header is not a 4th surface.
215
+ - Don't pick off-scale radii or spacing. Snap to `radius-sm/md/lg` (6/10/16) and 4/8/12/16/20/24/32.
216
+ - Don't animate longer than 200ms. Use `var(--ease)` (120ms) for color/border/filter.
217
+ - Don't tint a card's header or footer with a different background — they share the card surface.
218
+
219
+ ---
220
+
221
+ *6 tokens. 3 depths. 1 card. 1 input. 6 button variants. The build refuses to compile anything else.*
@@ -0,0 +1,218 @@
1
+ # Documentation Rules
2
+
3
+ Apply to all TODOs and `/do` workflows.
4
+
5
+ **Principle:** Document BEFORE implementation (W2), edit alongside code (W3), verify consistency (W4).
6
+
7
+ ---
8
+
9
+ ## The Three Phases
10
+
11
+ ### **W2 — Planning Phase: Document the Plan**
12
+
13
+ Before any code is written, explicitly list which docs will change:
14
+
15
+ ```markdown
16
+ ### Documentation Updates (W2)
17
+
18
+ **New docs:**
19
+ - `docs/feature.md` — {purpose}
20
+
21
+ **Docs modified:**
22
+ - `docs/dictionary.md` — add term {name}
23
+ - `docs/routing.md` — update loop L{N}
24
+ - `docs/rubrics.md` — add dimension {name}
25
+
26
+ **Schema changes:**
27
+ - New TypeDB entities, D1 migrations, TypeQL functions
28
+ ```
29
+
30
+ **Why:** Naming decisions, API design, and lifecycle implications must be documented before code is written. The docs ARE the spec.
31
+
32
+ ---
33
+
34
+ ### **W3 — Edit Phase: Update Docs + Code in Parallel**
35
+
36
+ **For every code file edited, edit the corresponding doc:**
37
+
38
+ | Code File | Related Doc |
39
+ |-----------|-------------|
40
+ | `nanoclaw/src/types.ts` | `docs/dictionary.md` — add new type terms |
41
+ | `src/engine/world.ts` | `docs/DSL.md` — update signal grammar |
42
+ | `src/engine/loop.ts` | `docs/routing.md` — update L1-L7 loops |
43
+ | `src/pages/api/*.ts` | `docs/lifecycle.md` — update lifecycle stage |
44
+ | `src/schema/*.tql` | `docs/one-ontology.md` — update dimension/entity |
45
+ | Feature-specific file | `docs/feature.md` — update feature spec |
46
+
47
+ **Pattern:** If you're adding a new field to a TypeScript interface, add it to the doc that defines that interface. If you're changing a loop, update the loop diagram in the doc.
48
+
49
+ ---
50
+
51
+ ### **W4 — Verify Phase: Check Docs Match Code**
52
+
53
+ **Docs consistency checklist:**
54
+
55
+ 1. **Terminology** — All renamed concepts updated everywhere
56
+ ```bash
57
+ grep -r "old-name" docs/ -- ignore new-name where intentional (dead names)
58
+ ```
59
+
60
+ 2. **Examples** — Code examples in docs match actual implementation
61
+ ```
62
+ - TypeScript interfaces in examples match src/types.ts
63
+ - TypeQL in examples match src/schema/*.tql
64
+ - Function signatures match actual exports
65
+ ```
66
+
67
+ 3. **Cross-references** — Links don't 404
68
+ ```
69
+ - [dictionary.md](dictionary.md) exists and links back to source
70
+ - Code file references match real paths (no moved files)
71
+ ```
72
+
73
+ 4. **Metaphor consistency** — 7-skin mappings still valid
74
+ ```
75
+ - Ant: pheromone/strength/resistance → brain: synapse/weight
76
+ - Team: signal/mark → org: decision/approval
77
+ - Check metaphors.md if touching path/signal semantics
78
+ ```
79
+
80
+ 5. **Rubric dimensions** — New quality scoring documented
81
+ ```
82
+ - If W4 adds a rubric dimension (e.g., "documentation"), it goes in rubrics.md
83
+ - Scoring rules and edge cases documented
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Which Docs Are Always in Scope
89
+
90
+ These six docs are the **source of truth** and must stay in sync with code:
91
+
92
+ | Doc | Locks | Update when |
93
+ |-----|-------|-------------|
94
+ | **dictionary.md** | Canonical names, types, entities | Any naming change |
95
+ | **DSL.md** | Signal grammar, mark/warn/fade verbs | Signal behavior changes |
96
+ | **one-ontology.md** | 6 dimensions, actor/group/thing/path/signal/hypothesis | Type system changes |
97
+ | **routing.md** | L1-L7 loops, signal flow, priority formula | Loop/routing changes |
98
+ | **lifecycle.md** | Agent journey stages, revenue flow | Lifecycle/economic changes |
99
+ | **rubrics.md** | Code rubric (security/stability/simplicity/speed) + agent rubric (fit/form/truth/taste) | Rubric changes or new dimensions |
100
+
101
+ **Feature-specific docs** (rich-messages.md, webhooks.md, etc.) are updated per feature. Always link back to the six core docs.
102
+
103
+ ---
104
+
105
+ ## The Workflow Integration
106
+
107
+ ### Hook: Pre-W2 — Load Source Docs
108
+
109
+ When a TODO is created, auto-load relevant source docs:
110
+
111
+ ```
112
+ /do {name}-todo.md
113
+ ├─ [Hook] Load: dictionary.md, DSL.md, rubrics.md
114
+ ├─ [W1] Recon code (reads files)
115
+ ├─ [W2] Decide code + **document changes needed in docs**
116
+ │ (explicit list: what terms change, what loops change, what's new)
117
+ ├─ [W3] Edit code (spawns Sonnet agents)
118
+ │ + [Hook] Suggest: "Also edit X doc for {Y change}"
119
+ └─ [W4] Verify code + **verify docs match** (cross-check task)
120
+ ```
121
+
122
+ ### Hook: Post-W4 — Validate Doc Consistency
123
+
124
+ After W4 completes, auto-run consistency checks:
125
+
126
+ ```bash
127
+ # Terminology consistency
128
+ grep -r "old-term" docs/ | flag if > 0 (not on deadname list)
129
+
130
+ # Cross-references
131
+ markdown-link-check docs/*.md
132
+
133
+ # Metaphor alignment (if touching signal/path semantics)
134
+ grep -l "signal\|strength\|resistance" src/changed-files.txt | xargs -I {} \
135
+ check if metaphors.md still applies
136
+
137
+ # Rubric scoring (if W4 added dimensions)
138
+ grep "rubric\|dimension" src/changed-files.txt | flag for rubrics.md review
139
+ ```
140
+
141
+ ---
142
+
143
+ ## Example: rich-messages-todo (Retrospective)
144
+
145
+ **What should have happened (W2):**
146
+
147
+ ```markdown
148
+ ### Documentation Updates (W2)
149
+
150
+ **New docs:**
151
+ - None (extends existing types)
152
+
153
+ **Docs modified:**
154
+ - `docs/dictionary.md` — add "Rich Messages" section, explain `data.rich` convention
155
+ - `docs/rich-messages.md` — add PaymentMetadata type, Payment flow section
156
+ - `docs/template-todo.md` — add "Documentation Updates (W2 + W4)" section
157
+
158
+ **Schema changes:**
159
+ - `nanoclaw/src/types.ts` — RichMessage.thread, RichMessage.payment added (Cycle 1 & 3)
160
+ - `migrations/0010_payment_columns.sql` — new D1 columns for payment tracking
161
+ ```
162
+
163
+ **What actually happened:**
164
+
165
+ - ✅ Docs updated (rich-messages.md, dictionary.md, template-todo.md) — **AFTER W4**
166
+ - ⚠️ Should have been planned in W2, preventing surprises in W3
167
+
168
+ **Lesson:** Next TODO follows: document in W2, edit in W3, verify in W4. No surprises.
169
+
170
+ ---
171
+
172
+ ## Rules for `/do` (The Command)
173
+
174
+ When running `/do {name}-todo.md`, the workflow enforces:
175
+
176
+ 1. **W2 must explicitly call out doc changes** — no surprise doc edits in W3
177
+ 2. **W3 spawns edit agents for both code AND docs** — parallel edits
178
+ 3. **W4 includes doc consistency check** — not just code tests
179
+ 4. **The code rubric (security/stability/simplicity/speed) applies to docs too** — simplicity means fewer words; stability means no broken links; security means no sensitive data exposed; speed means lean docs = fewer tokens to read
180
+
181
+ ---
182
+
183
+ *Documentation is not a post-mortem. It's the blueprint. Build it first. Verify it matches.*
184
+
185
+ ---
186
+
187
+ ## Loop Close — propagate matrix (inlined, no separate file)
188
+
189
+ `/close` runs this matrix automatically after rubric + feedback signal. Each row is a bash + Edit-tool dispatch, zero agent spawns.
190
+
191
+ | Trigger (detected from W3 diff) | Target doc | Edit |
192
+ |---|---|---|
193
+ | any change | source-of-truth doc(s) from plan frontmatter | always — even if only touch-verified |
194
+ | 6-dim, L1-L8, or locked-rule change | root `CLAUDE.md` | edit the relevant section |
195
+ | directory contract change (new component family, new pattern) | nearest `CLAUDE.md` (e.g., `one.ie/web/src/components/CLAUDE.md`) | append / edit section |
196
+ | public surface change (new CLI verb, API route family, SDK export, MCP tool) | root `README.md` + feature doc | append row(s) |
197
+ | feature doc named in plan | feature doc | sync verb/component/endpoint counts |
198
+ | rename across W3 | every `**/*.md` containing old name | inline replace (auto-grep) |
199
+
200
+ Anchor mismatch → log to `docs/improvements.md` for manual W2 next cycle (no halt — the cycle still closes; the propagate task surfaces next iteration).
201
+
202
+ **Learnings entry** (append to `docs/learnings.md` on each close):
203
+
204
+ ```
205
+ - YYYY-MM-DD · cycle N · wave N|gate · {one sentence} · rubric=0.NN · source=w1|w2|w3|w4|cycle
206
+ ```
207
+
208
+ W4 code rubric applies to docs too: security (no sensitive data), stability (no broken links, accurate references), simplicity (fewer words, no bloat), speed (lean = fewer tokens to read).
209
+
210
+ ### W4 doc-sync hard gate (zero LLM)
211
+
212
+ W4 must pass three bash checks before the rubric runs. Detail in `.claude/commands/do.md` W4 section. Summary:
213
+
214
+ 1. **stale-name check** — every old identifier in W3's rename list has 0 hits in `**/*.md`
215
+ 2. **broken-link check** — `markdown-link-check` on every touched doc returns 0 broken
216
+ 3. **contract-staleness check** — every dir whose code was touched has `CLAUDE.md` mtime ≥ newest code mtime
217
+
218
+ Any fail → cycle does NOT close. No rubric until docs match code.