@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.
- package/.claude-plugin/plugin.json +16 -0
- package/.mcp.json +12 -0
- package/README.md +204 -0
- package/agents/w1-recon.md +102 -0
- package/agents/w2-decide.md +164 -0
- package/agents/w3-edit.md +91 -0
- package/agents/w4-verify.md +416 -0
- package/commands/browser.md +55 -0
- package/commands/cc-connect.md +67 -0
- package/commands/claw.md +135 -0
- package/commands/close.md +143 -0
- package/commands/create.md +78 -0
- package/commands/deploy.md +415 -0
- package/commands/do-autonomous.md +80 -0
- package/commands/do-improve.md +51 -0
- package/commands/do-show.md +89 -0
- package/commands/do.md +226 -0
- package/commands/improve.md +99 -0
- package/commands/kill.md +45 -0
- package/commands/release.md +144 -0
- package/commands/see.md +161 -0
- package/commands/setup.md +75 -0
- package/commands/sync.md +185 -0
- package/hooks/hooks.json +90 -0
- package/hooks/lib/signal.sh +28 -0
- package/hooks/scripts/design-check.sh +83 -0
- package/hooks/scripts/post-edit-check.sh +32 -0
- package/hooks/scripts/session-end-verify.sh +51 -0
- package/hooks/scripts/session-start.sh +88 -0
- package/hooks/scripts/stop-reflect.sh +95 -0
- package/hooks/scripts/sync-todo-docs.sh +46 -0
- package/hooks/scripts/task-complete-verify.sh +52 -0
- package/hooks/scripts/tool-signal.sh +48 -0
- package/package.json +33 -0
- package/rules/api.md +50 -0
- package/rules/astro.md +206 -0
- package/rules/design.md +221 -0
- package/rules/documentation.md +218 -0
- package/rules/engine.md +297 -0
- package/rules/react.md +137 -0
- package/rules/ui.md +82 -0
- package/scripts/cc-connect.sh +345 -0
- package/scripts/do-analyze.sh +42 -0
- package/scripts/do-folder.sh +63 -0
- package/scripts/do-prove.sh +51 -0
- package/scripts/do-reconcile.sh +28 -0
- package/scripts/do-smoke.sh +60 -0
- package/scripts/do-survey.sh +30 -0
- package/scripts/do-tier.sh +43 -0
- package/skills/build/SKILL.md +52 -0
- package/skills/cloudflare/SKILL.md +503 -0
- package/skills/dev/SKILL.md +58 -0
- package/skills/do/SKILL.md +24 -0
- package/skills/oneie/SKILL.md +51 -0
- package/skills/perf/SKILL.md +45 -0
- package/skills/signal/SKILL.md +108 -0
- package/skills/sui/SKILL.md +441 -0
- package/skills/tutorial/SKILL.md +96 -0
- 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.*
|
package/rules/design.md
ADDED
|
@@ -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.
|