@hai3/framework 0.2.0-alpha.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.md +161 -0
- package/commands/hai3-fix-violation.md +48 -0
- package/commands/hai3-new-action.md +120 -0
- package/commands/hai3-quick-ref.md +63 -0
- package/commands/hai3-rules.md +43 -0
- package/commands/hai3-validate.md +49 -0
- package/dist/index.cjs +1397 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +842 -0
- package/dist/index.d.ts +842 -0
- package/dist/index.js +1264 -0
- package/dist/index.js.map +1 -0
- package/dist/types.cjs +19 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +440 -0
- package/dist/types.d.ts +440 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/llms.txt +52 -0
- package/package.json +57 -0
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# @hai3/framework
|
|
2
|
+
|
|
3
|
+
Plugin-based application framework for HAI3 applications. Orchestrates SDK packages into cohesive applications.
|
|
4
|
+
|
|
5
|
+
## Framework Layer
|
|
6
|
+
|
|
7
|
+
This package is part of the **Framework Layer (L2)** - it depends on SDK packages (@hai3/state, @hai3/screensets, @hai3/api, @hai3/i18n). It provides the plugin architecture and **owns the layout slices** (header, footer, menu, sidebar, screen, popup, overlay).
|
|
8
|
+
|
|
9
|
+
> **NOTE:** @hai3/uicore is deprecated. Layout slices are defined in @hai3/framework.
|
|
10
|
+
|
|
11
|
+
## Core Concepts
|
|
12
|
+
|
|
13
|
+
### Plugin Architecture
|
|
14
|
+
|
|
15
|
+
Build applications by composing plugins:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { createHAI3, screensets, themes, layout, navigation, i18n } from '@hai3/framework';
|
|
19
|
+
|
|
20
|
+
const app = createHAI3()
|
|
21
|
+
.use(screensets())
|
|
22
|
+
.use(themes())
|
|
23
|
+
.use(layout())
|
|
24
|
+
.use(navigation())
|
|
25
|
+
.use(i18n())
|
|
26
|
+
.build();
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Presets
|
|
30
|
+
|
|
31
|
+
Pre-configured plugin combinations:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { createHAI3App, presets } from '@hai3/framework';
|
|
35
|
+
|
|
36
|
+
// Full preset (default) - all plugins
|
|
37
|
+
const fullApp = createHAI3App();
|
|
38
|
+
|
|
39
|
+
// Or explicitly use presets
|
|
40
|
+
const minimalApp = createHAI3()
|
|
41
|
+
.use(presets.minimal()) // screensets + themes only
|
|
42
|
+
.build();
|
|
43
|
+
|
|
44
|
+
const headlessApp = createHAI3()
|
|
45
|
+
.use(presets.headless()) // screensets only
|
|
46
|
+
.build();
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Available Plugins
|
|
50
|
+
|
|
51
|
+
| Plugin | Provides | Dependencies |
|
|
52
|
+
|--------|----------|--------------|
|
|
53
|
+
| `screensets()` | screensetRegistry, screenSlice | - |
|
|
54
|
+
| `themes()` | themeRegistry, changeTheme action | - |
|
|
55
|
+
| `layout()` | header, footer, menu, sidebar, popup, overlay slices | screensets |
|
|
56
|
+
| `navigation()` | navigateToScreen, navigateToScreenset actions | screensets, routing |
|
|
57
|
+
| `routing()` | routeRegistry, URL sync | screensets |
|
|
58
|
+
| `i18n()` | i18nRegistry, setLanguage action | - |
|
|
59
|
+
| `effects()` | Core effect coordination | - |
|
|
60
|
+
|
|
61
|
+
### Built Application
|
|
62
|
+
|
|
63
|
+
After calling `.build()`, access registries and actions:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const app = createHAI3App();
|
|
67
|
+
|
|
68
|
+
// Access registries
|
|
69
|
+
app.screensetRegistry.getAll();
|
|
70
|
+
app.themeRegistry.getCurrent();
|
|
71
|
+
app.routeRegistry.hasScreen('demo', 'home');
|
|
72
|
+
app.i18nRegistry.t('common:title');
|
|
73
|
+
|
|
74
|
+
// Access store
|
|
75
|
+
const state = app.store.getState();
|
|
76
|
+
app.store.dispatch(someAction);
|
|
77
|
+
|
|
78
|
+
// Access actions
|
|
79
|
+
app.actions.navigateToScreen({ screensetId: 'demo', screenId: 'home' });
|
|
80
|
+
app.actions.changeTheme({ themeId: 'dark' });
|
|
81
|
+
app.actions.setLanguage({ language: 'es' });
|
|
82
|
+
|
|
83
|
+
// Cleanup
|
|
84
|
+
app.destroy();
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Creating Custom Plugins
|
|
88
|
+
|
|
89
|
+
Extend HAI3 with custom functionality:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import type { HAI3Plugin } from '@hai3/framework';
|
|
93
|
+
|
|
94
|
+
export function myPlugin(): HAI3Plugin {
|
|
95
|
+
return {
|
|
96
|
+
name: 'my-plugin',
|
|
97
|
+
dependencies: ['screensets'], // Optional dependencies
|
|
98
|
+
provides: {
|
|
99
|
+
registries: { myRegistry: createMyRegistry() },
|
|
100
|
+
slices: [mySlice],
|
|
101
|
+
effects: [initMyEffects],
|
|
102
|
+
actions: { myAction: myActionHandler },
|
|
103
|
+
},
|
|
104
|
+
onInit(app) {
|
|
105
|
+
// Initialize after app is built
|
|
106
|
+
},
|
|
107
|
+
onDestroy(app) {
|
|
108
|
+
// Cleanup when app is destroyed
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Key Rules
|
|
115
|
+
|
|
116
|
+
1. **Use presets for common cases** - `createHAI3App()` for full apps
|
|
117
|
+
2. **Compose plugins for customization** - Use `createHAI3().use()` pattern
|
|
118
|
+
3. **Dependencies are auto-resolved** - Plugin order doesn't matter
|
|
119
|
+
4. **Access via app instance** - All registries and actions on `app.*`
|
|
120
|
+
5. **NO React in this package** - Framework is headless, use @hai3/react for React bindings
|
|
121
|
+
|
|
122
|
+
## Re-exports
|
|
123
|
+
|
|
124
|
+
For convenience, this package re-exports from SDK packages:
|
|
125
|
+
|
|
126
|
+
- From @hai3/state: `eventBus`, `createStore`, `getStore`, `registerSlice`, `hasSlice`, `createSlice`
|
|
127
|
+
- From @hai3/screensets: `LayoutDomain`, `ScreensetCategory`, `screensetRegistry`, contracts/types
|
|
128
|
+
- From @hai3/api: `apiRegistry`, `BaseApiService`, `RestProtocol`, `MockPlugin`
|
|
129
|
+
- From @hai3/i18n: `i18nRegistry`, `Language`, `SUPPORTED_LANGUAGES`, `getLanguageMetadata`
|
|
130
|
+
|
|
131
|
+
**Layout Slices (owned by @hai3/framework):**
|
|
132
|
+
- `layoutReducer`, `layoutDomainReducers`, `LAYOUT_SLICE_NAME`
|
|
133
|
+
- Domain slices: `headerSlice`, `footerSlice`, `menuSlice`, `sidebarSlice`, `screenSlice`, `popupSlice`, `overlaySlice`
|
|
134
|
+
- Domain actions: `headerActions`, `footerActions`, `menuActions`, `sidebarActions`, `screenActions`, `popupActions`, `overlayActions`
|
|
135
|
+
- Individual reducer functions: `setMenuCollapsed`, `toggleSidebar`, `setActiveScreen`, etc.
|
|
136
|
+
|
|
137
|
+
**NOTE:** `createAction` is NOT exported to consumers. Actions should be handwritten functions in screensets that contain business logic and emit events via `eventBus.emit()`.
|
|
138
|
+
|
|
139
|
+
**NOTE:** "Selector" is Redux terminology and is not used in HAI3. Access state via `useAppSelector` hook from @hai3/react:
|
|
140
|
+
```typescript
|
|
141
|
+
const menu = useAppSelector((state: RootStateWithLayout) => state.layout.menu);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Exports
|
|
145
|
+
|
|
146
|
+
### Core
|
|
147
|
+
- `createHAI3` - App builder factory
|
|
148
|
+
- `createHAI3App` - Convenience function (full preset)
|
|
149
|
+
- `presets` - Available presets (full, minimal, headless)
|
|
150
|
+
|
|
151
|
+
### Plugins
|
|
152
|
+
- `screensets`, `themes`, `layout`, `navigation`, `routing`, `i18n`, `effects`
|
|
153
|
+
|
|
154
|
+
### Registries
|
|
155
|
+
- `createScreensetRegistry`, `createThemeRegistry`, `createRouteRegistry`
|
|
156
|
+
|
|
157
|
+
### Types
|
|
158
|
+
- `HAI3Config`, `HAI3Plugin`, `HAI3App`, `HAI3AppBuilder`
|
|
159
|
+
- `PluginFactory`, `PluginProvides`, `PluginLifecycle`
|
|
160
|
+
- `Preset`, `Presets`, `ScreensetsConfig`
|
|
161
|
+
- All re-exported types from SDK packages
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<!-- @standalone -->
|
|
2
|
+
# hai3:fix-violation - Fix Rule Violation
|
|
3
|
+
|
|
4
|
+
## AI WORKFLOW (REQUIRED)
|
|
5
|
+
1) Identify: Location (file:line), rule violated, category.
|
|
6
|
+
2) Route: Use .ai/GUIDELINES.md to find target file.
|
|
7
|
+
3) Summarize: Extract 3-7 applicable rules from target.
|
|
8
|
+
4) Fix: Apply correction.
|
|
9
|
+
5) Verify: Run checks.
|
|
10
|
+
6) Report: What violated, rule applied, changes made, results.
|
|
11
|
+
|
|
12
|
+
## STEP 1: Identify Violation
|
|
13
|
+
- Find violating code location (file:line).
|
|
14
|
+
- Classify category: typing | data flow | styling | registry | imports.
|
|
15
|
+
|
|
16
|
+
## STEP 2: Route to Target File
|
|
17
|
+
- Data flow/events -> .ai/targets/EVENTS.md
|
|
18
|
+
- API services -> .ai/targets/SCREENSETS.md
|
|
19
|
+
- src/screensets -> .ai/targets/SCREENSETS.md
|
|
20
|
+
- src/themes -> .ai/targets/THEMES.md
|
|
21
|
+
- Styling -> .ai/targets/STYLING.md
|
|
22
|
+
|
|
23
|
+
## STEP 3: Read and Summarize Rules
|
|
24
|
+
- REQUIRED: Read target file before making any change.
|
|
25
|
+
- Summarize 3-7 applicable rules internally.
|
|
26
|
+
|
|
27
|
+
## STEP 4: Apply Fix
|
|
28
|
+
Change code to comply with target file rules.
|
|
29
|
+
|
|
30
|
+
## STEP 5: Verify
|
|
31
|
+
Run: npm run arch:check && npm run lint && npm run type-check
|
|
32
|
+
REQUIRED: All checks must pass.
|
|
33
|
+
|
|
34
|
+
## STEP 6: Report
|
|
35
|
+
- What violated the rule.
|
|
36
|
+
- Which rule was applied.
|
|
37
|
+
- Changes made.
|
|
38
|
+
- Verification results.
|
|
39
|
+
|
|
40
|
+
## COMMON FIXES
|
|
41
|
+
- Direct dispatch: BAD dispatch(setMenuItems(items)) -> GOOD navigateToScreen(screenId)
|
|
42
|
+
- Hardcoded colors: BAD style with inline color -> GOOD className="text-primary"
|
|
43
|
+
- Import violations: BAD import from '@hai3/uikit/src/Foo' -> GOOD import from '@hai3/uikit'
|
|
44
|
+
- String literals: BAD screenId: 'dashboard' -> GOOD export const DASHBOARD_SCREEN_ID = 'dashboard'
|
|
45
|
+
- Inline component: Extract to screens/screen/components/ or uikit/ per SCREENSETS.md
|
|
46
|
+
- Inline style: BAD style with inline padding -> GOOD className="p-2" (except in uikit/base/)
|
|
47
|
+
- Inline data: Move to api/domain/mocks.ts, fetch via event-driven flow
|
|
48
|
+
- UIKit impurity: Move component from uikit/ to components/ if needs @hai3/uicore
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<!-- @standalone -->
|
|
2
|
+
# hai3:new-action - Create New Action
|
|
3
|
+
|
|
4
|
+
## AI WORKFLOW (REQUIRED)
|
|
5
|
+
1) Read .ai/targets/EVENTS.md before starting.
|
|
6
|
+
2) Summarize 3-6 key rules.
|
|
7
|
+
3) Gather requirements from user.
|
|
8
|
+
4) Create OpenSpec proposal for approval.
|
|
9
|
+
5) After approval, apply implementation.
|
|
10
|
+
|
|
11
|
+
## GATHER REQUIREMENTS
|
|
12
|
+
Ask user for:
|
|
13
|
+
- Action purpose (e.g., "navigate to screen", "load user data").
|
|
14
|
+
- Which screenset and domain (e.g., "chat/threads", "demo/navigation").
|
|
15
|
+
- Event payload data.
|
|
16
|
+
|
|
17
|
+
## STEP 1: Create OpenSpec Proposal
|
|
18
|
+
Create `openspec/changes/add-{screenset}-{action}/` with:
|
|
19
|
+
|
|
20
|
+
### proposal.md
|
|
21
|
+
```markdown
|
|
22
|
+
# Proposal: Add {ActionName} Action
|
|
23
|
+
|
|
24
|
+
## Summary
|
|
25
|
+
Add new action "{actionName}" to {screenset}/{domain} domain.
|
|
26
|
+
|
|
27
|
+
## Details
|
|
28
|
+
- Screenset: {screenset}
|
|
29
|
+
- Domain: {domain}
|
|
30
|
+
- Action: {actionName}
|
|
31
|
+
- Event: {eventName}
|
|
32
|
+
- Payload: {payloadFields}
|
|
33
|
+
|
|
34
|
+
## Implementation
|
|
35
|
+
Follow HAI3 event-driven flux pattern: Action -> Event -> Effect -> Slice.
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### tasks.md
|
|
39
|
+
```markdown
|
|
40
|
+
# Tasks: Add {ActionName} Action
|
|
41
|
+
|
|
42
|
+
- [ ] Define event in events/{domain}Events.ts
|
|
43
|
+
- [ ] Create action in actions/{domain}Actions.ts
|
|
44
|
+
- [ ] Create effect in effects/{domain}Effects.ts
|
|
45
|
+
- [ ] Validate: `npm run arch:check`
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## STEP 2: Wait for Approval
|
|
49
|
+
Tell user: "I've created an OpenSpec proposal at `openspec/changes/add-{screenset}-{action}/`. Please review and run `/openspec:apply add-{screenset}-{action}` to implement."
|
|
50
|
+
|
|
51
|
+
## STEP 3: Apply Implementation (after approval)
|
|
52
|
+
When user runs `/openspec:apply`, execute:
|
|
53
|
+
|
|
54
|
+
### 3.1 Define Event
|
|
55
|
+
In src/screensets/{screenset}/events/{domain}Events.ts:
|
|
56
|
+
```typescript
|
|
57
|
+
import { SCREENSET_ID } from '../ids';
|
|
58
|
+
|
|
59
|
+
const DOMAIN_ID = '{domain}';
|
|
60
|
+
|
|
61
|
+
export const {Domain}Events = {
|
|
62
|
+
{EventName}: `${SCREENSET_ID}/${DOMAIN_ID}/{eventName}` as const,
|
|
63
|
+
} as const;
|
|
64
|
+
|
|
65
|
+
export type {EventName}Payload = {
|
|
66
|
+
// payload fields
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
declare module '@hai3/state' {
|
|
70
|
+
interface EventPayloadMap {
|
|
71
|
+
[{Domain}Events.{EventName}]: {EventName}Payload;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 3.2 Create Action
|
|
77
|
+
In src/screensets/{screenset}/actions/{domain}Actions.ts:
|
|
78
|
+
```typescript
|
|
79
|
+
import { eventBus } from '@hai3/state';
|
|
80
|
+
import { {Domain}Events } from '../events/{domain}Events';
|
|
81
|
+
|
|
82
|
+
export const {actionName} = (params: ParamsType) => {
|
|
83
|
+
return (): void => {
|
|
84
|
+
eventBus.emit({Domain}Events.{EventName}, {
|
|
85
|
+
// payload
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 3.3 Create Effect
|
|
92
|
+
In src/screensets/{screenset}/effects/{domain}Effects.ts:
|
|
93
|
+
```typescript
|
|
94
|
+
import { eventBus, getStore } from '@hai3/state';
|
|
95
|
+
import { {Domain}Events } from '../events/{domain}Events';
|
|
96
|
+
|
|
97
|
+
export function init{Domain}Effects(): void {
|
|
98
|
+
const store = getStore();
|
|
99
|
+
eventBus.on({Domain}Events.{EventName}, (payload) => {
|
|
100
|
+
store.dispatch(set{Something}(payload.{field}));
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 3.4 Validate
|
|
106
|
+
```bash
|
|
107
|
+
npm run arch:check
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 3.5 Mark Tasks Complete
|
|
111
|
+
Update tasks.md to mark all completed tasks.
|
|
112
|
+
|
|
113
|
+
## RULES
|
|
114
|
+
- Actions use imperative names (selectScreen, changeTheme).
|
|
115
|
+
- Events use past-tense names (screenSelected, themeChanged).
|
|
116
|
+
- Actions are pure functions (no getState, no async thunks).
|
|
117
|
+
- Actions return void (not Promise).
|
|
118
|
+
- Effects update their own slice only.
|
|
119
|
+
- Cross-domain communication only via events.
|
|
120
|
+
- FORBIDDEN: Direct slice dispatch from actions/components.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<!-- @standalone -->
|
|
2
|
+
# hai3:quick-ref - Quick Reference
|
|
3
|
+
|
|
4
|
+
## Event-Driven
|
|
5
|
+
- REQUIRED: Action emits event via eventBus.emit('event/name', payload).
|
|
6
|
+
- REQUIRED: Effect subscribes via eventBus.on('event/name', handler).
|
|
7
|
+
- REQUIRED: Effect updates slice via store.dispatch(setSlice(data)).
|
|
8
|
+
- FORBIDDEN: Direct slice dispatch from actions or components.
|
|
9
|
+
|
|
10
|
+
## Imports
|
|
11
|
+
- Same package: BAD import from '@hai3/uikit/src/Foo' -> GOOD import from './Foo'.
|
|
12
|
+
- Cross-branch app: BAD import from '../../core/layout' -> GOOD import from '@/core/layout'.
|
|
13
|
+
- Cross-package: BAD import from '@hai3/uikit/src/internal' -> GOOD import from '@hai3/uikit'.
|
|
14
|
+
|
|
15
|
+
## Components
|
|
16
|
+
- REQUIRED: Check global @hai3/uikit first; screenset uikit only if missing.
|
|
17
|
+
- App/screensets: REQUIRED import { Button } from '@hai3/uikit'.
|
|
18
|
+
- FORBIDDEN: Raw HTML elements for UI.
|
|
19
|
+
- FORBIDDEN: Inline component definitions in *Screen.tsx.
|
|
20
|
+
|
|
21
|
+
## Component Placement
|
|
22
|
+
- REQUIRED: Screenset uikit/ structure: base/, composite/, icons/.
|
|
23
|
+
- REQUIRED: uikit/base/ for rare primitives (inline styles allowed).
|
|
24
|
+
- REQUIRED: uikit/composite/ for screenset composites (theme tokens only).
|
|
25
|
+
- REQUIRED: Shared components in screensets/{name}/components/.
|
|
26
|
+
- REQUIRED: Screen-local components in screens/{screen}/components/.
|
|
27
|
+
- REQUIRED: Screen files orchestrate components only.
|
|
28
|
+
|
|
29
|
+
## Registry
|
|
30
|
+
- REQUIRED: export const MY_DOMAIN = 'my-domain'.
|
|
31
|
+
- REQUIRED: class MyService extends BaseApiService.
|
|
32
|
+
- REQUIRED: declare module '@hai3/api' { interface ApiServicesMap }.
|
|
33
|
+
- REQUIRED: apiRegistry.register(MY_DOMAIN, MyService).
|
|
34
|
+
|
|
35
|
+
## Styling
|
|
36
|
+
- Inline styles ONLY in screensets/*/uikit/base/ (rare local primitives).
|
|
37
|
+
- BAD style={{ backgroundColor: '#fff' }} -> GOOD className="bg-background".
|
|
38
|
+
- BAD style={{ color: '#000' }} -> GOOD className="text-foreground".
|
|
39
|
+
- REQUIRED: Use Tailwind utilities, CSS variables elsewhere.
|
|
40
|
+
|
|
41
|
+
## i18n
|
|
42
|
+
- REQUIRED: i18nRegistry.registerLoader('screenset.demo', loader).
|
|
43
|
+
- REQUIRED: Use t('screenset.demo:screens.home.title') format.
|
|
44
|
+
- FORBIDDEN: Hardcoded strings in UI.
|
|
45
|
+
|
|
46
|
+
## Commands
|
|
47
|
+
- npm ci -> Install dependencies.
|
|
48
|
+
- npm run dev -> Start dev server.
|
|
49
|
+
- npm run arch:check -> Validate (CRITICAL before commits).
|
|
50
|
+
- npm run type-check -> TypeScript validation.
|
|
51
|
+
- npm run lint -> ESLint validation.
|
|
52
|
+
|
|
53
|
+
## Invariants
|
|
54
|
+
- REQUIRED: Event-driven architecture only.
|
|
55
|
+
- REQUIRED: Registries follow Open/Closed principle.
|
|
56
|
+
- REQUIRED: App deps limited to @hai3/react, @hai3/uikit, react, react-dom.
|
|
57
|
+
- REQUIRED: Cross-domain communication via events only.
|
|
58
|
+
- FORBIDDEN: String literals for IDs.
|
|
59
|
+
- FORBIDDEN: any type or unsafe casts.
|
|
60
|
+
|
|
61
|
+
## Docs
|
|
62
|
+
- .ai/GUIDELINES.md -> Routing table.
|
|
63
|
+
- .ai/targets/*.md -> Area-specific rules.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<!-- @standalone -->
|
|
2
|
+
# hai3:rules - Show HAI3 Rules for Specific Area
|
|
3
|
+
|
|
4
|
+
Ask the user which area they want rules for, or detect from context.
|
|
5
|
+
|
|
6
|
+
## ROUTING TABLE
|
|
7
|
+
|
|
8
|
+
| Area | Target file |
|
|
9
|
+
|------|-------------|
|
|
10
|
+
| Data flow / events | .ai/targets/EVENTS.md |
|
|
11
|
+
| API layer | .ai/targets/API.md |
|
|
12
|
+
| packages/uicore | .ai/targets/UICORE.md |
|
|
13
|
+
| packages/uikit | .ai/targets/UIKIT.md |
|
|
14
|
+
| packages/uikit-contracts | .ai/targets/UIKIT_CONTRACTS.md |
|
|
15
|
+
| src/screensets | .ai/targets/SCREENSETS.md |
|
|
16
|
+
| src/themes | .ai/targets/THEMES.md |
|
|
17
|
+
| Styling anywhere | .ai/targets/STYLING.md |
|
|
18
|
+
| AI documentation | .ai/targets/AI.md |
|
|
19
|
+
|
|
20
|
+
Then:
|
|
21
|
+
|
|
22
|
+
1. Read the applicable target file
|
|
23
|
+
2. Summarize the CRITICAL RULES section (3-7 rules)
|
|
24
|
+
3. List STOP CONDITIONS
|
|
25
|
+
4. Show PRE-DIFF CHECKLIST items
|
|
26
|
+
5. Provide common violation examples with fixes
|
|
27
|
+
|
|
28
|
+
Format output as:
|
|
29
|
+
|
|
30
|
+
## Critical Rules
|
|
31
|
+
[List 3-7 key rules in your own words]
|
|
32
|
+
|
|
33
|
+
## Stop Conditions
|
|
34
|
+
[When to stop and ask]
|
|
35
|
+
|
|
36
|
+
## Common Violations
|
|
37
|
+
[Show BAD -> GOOD examples]
|
|
38
|
+
|
|
39
|
+
## Pre-Diff Checklist
|
|
40
|
+
[Checklist from target file]
|
|
41
|
+
|
|
42
|
+
## Reference
|
|
43
|
+
Full rules: `.ai/targets/{FILE}.md`
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!-- @standalone -->
|
|
2
|
+
# hai3:validate - Validate Changes
|
|
3
|
+
|
|
4
|
+
## AI WORKFLOW (REQUIRED)
|
|
5
|
+
1) Read .ai/GUIDELINES.md and identify target file(s) for your changes.
|
|
6
|
+
2) Summarize 3-7 key rules from applicable target file(s).
|
|
7
|
+
3) Run validation checks.
|
|
8
|
+
4) Report results.
|
|
9
|
+
|
|
10
|
+
## STEP 1: Route to Target Files
|
|
11
|
+
- Use .ai/GUIDELINES.md ROUTING section.
|
|
12
|
+
- Read each applicable target file.
|
|
13
|
+
- Summarize rules internally (not written).
|
|
14
|
+
|
|
15
|
+
## STEP 2: Run Architecture Check
|
|
16
|
+
```bash
|
|
17
|
+
npm run arch:check
|
|
18
|
+
```
|
|
19
|
+
REQUIRED: Must pass with zero errors.
|
|
20
|
+
|
|
21
|
+
## STEP 3: Check Common Violations
|
|
22
|
+
- Direct slice dispatch (use event-driven actions instead).
|
|
23
|
+
- Inline styles outside base uikit folders (uikit/base/ only).
|
|
24
|
+
- Import violations (package internals, circular dependencies).
|
|
25
|
+
- String literal IDs (must use constants or enums).
|
|
26
|
+
- Inline component definitions in *Screen.tsx files.
|
|
27
|
+
- Inline data arrays (must use API services).
|
|
28
|
+
- @hai3/uicore imports in screensets/*/uikit/ folders.
|
|
29
|
+
- Screenset uikit component when global @hai3/uikit has equivalent.
|
|
30
|
+
|
|
31
|
+
## STEP 4: Verify Event-Driven Flow
|
|
32
|
+
- Actions emit events (not dispatch slices).
|
|
33
|
+
- Effects listen to events and update slices.
|
|
34
|
+
- No prop drilling or callback-based state mutation.
|
|
35
|
+
|
|
36
|
+
## STEP 5: Test via Chrome DevTools MCP
|
|
37
|
+
STOP: If MCP WebSocket is closed, fix connection first.
|
|
38
|
+
- Exercise all affected flows and screens.
|
|
39
|
+
- Verify UI uses @hai3/uikit and theme tokens.
|
|
40
|
+
- Verify event-driven behavior (no direct slice dispatch).
|
|
41
|
+
- Check for console errors or missing registrations.
|
|
42
|
+
|
|
43
|
+
## STEP 6: Report Results
|
|
44
|
+
- List rules verified.
|
|
45
|
+
- List any violations found.
|
|
46
|
+
- Confirm npm run arch:check passed.
|
|
47
|
+
|
|
48
|
+
## IF VIOLATIONS FOUND
|
|
49
|
+
Use hai3:fix-violation command to correct issues.
|