@auto-engineer/information-architect 1.8.0 → 1.10.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/package.json CHANGED
@@ -14,14 +14,14 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "fast-glob": "^3.3.2",
17
- "@auto-engineer/ai-gateway": "1.8.0",
18
- "@auto-engineer/message-bus": "1.8.0",
19
- "@auto-engineer/narrative": "1.8.0"
17
+ "@auto-engineer/message-bus": "1.10.0",
18
+ "@auto-engineer/narrative": "1.10.0",
19
+ "@auto-engineer/ai-gateway": "1.10.0"
20
20
  },
21
21
  "devDependencies": {
22
- "@auto-engineer/cli": "1.8.0"
22
+ "@auto-engineer/cli": "1.10.0"
23
23
  },
24
- "version": "1.8.0",
24
+ "version": "1.10.0",
25
25
  "scripts": {
26
26
  "build": "tsc && tsx ../../scripts/fix-esm-imports.ts && cp src/auto-ux-schema.json dist/",
27
27
  "test": "vitest run --reporter=dot",
@@ -164,8 +164,8 @@
164
164
  },
165
165
  "required": ["description", "items"]
166
166
  },
167
- "pages": {
168
- "description": "Top-level views composed of organisms, molecules, and atoms. Tied to routes.",
167
+ "templates": {
168
+ "description": "Page-level layout structures that place organisms into a layout. Templates define the skeletal framework and content structure without real data.",
169
169
  "type": "object",
170
170
  "properties": {
171
171
  "description": {
@@ -177,9 +177,6 @@
177
177
  "^[A-Z][a-zA-Z0-9]*$": {
178
178
  "type": "object",
179
179
  "properties": {
180
- "route": {
181
- "type": "string"
182
- },
183
180
  "description": {
184
181
  "type": "string"
185
182
  },
@@ -195,6 +192,44 @@
195
192
  },
196
193
  "required": ["organisms"]
197
194
  },
195
+ "specs": {
196
+ "type": "array",
197
+ "items": {
198
+ "type": "string"
199
+ },
200
+ "description": "Optional. Array of behavioral test specifications. Uses ' → ' to show nested context."
201
+ }
202
+ },
203
+ "required": ["description", "layout"]
204
+ }
205
+ }
206
+ }
207
+ },
208
+ "required": ["description", "items"]
209
+ },
210
+ "pages": {
211
+ "description": "Specific instances of templates with real representative content. Tied to routes and populated with actual data.",
212
+ "type": "object",
213
+ "properties": {
214
+ "description": {
215
+ "type": "string"
216
+ },
217
+ "items": {
218
+ "type": "object",
219
+ "patternProperties": {
220
+ "^[A-Z][a-zA-Z0-9]*$": {
221
+ "type": "object",
222
+ "properties": {
223
+ "route": {
224
+ "type": "string"
225
+ },
226
+ "description": {
227
+ "type": "string"
228
+ },
229
+ "template": {
230
+ "type": "string",
231
+ "description": "Reference to a template that defines the page's layout structure."
232
+ },
198
233
  "navigation": {
199
234
  "type": "array",
200
235
  "items": {
@@ -257,7 +292,7 @@
257
292
  "description": "Optional. Array of behavioral test specifications. Uses ' → ' to show nested context."
258
293
  }
259
294
  },
260
- "required": ["route", "description", "layout"]
295
+ "required": ["route", "description", "template"]
261
296
  }
262
297
  }
263
298
  }
@@ -265,5 +300,5 @@
265
300
  "required": ["description", "items"]
266
301
  }
267
302
  },
268
- "required": ["schema_description", "atoms", "molecules", "organisms", "pages"]
303
+ "required": ["schema_description", "atoms", "molecules", "organisms", "templates", "pages"]
269
304
  }
package/src/ia-agent.ts CHANGED
@@ -29,16 +29,33 @@ interface ItemsContainer {
29
29
  items?: Record<string, ComponentDefinition>;
30
30
  }
31
31
 
32
+ interface TemplateDefinition {
33
+ layout?: {
34
+ organisms?: string[];
35
+ };
36
+ }
37
+
38
+ interface TemplatesContainer {
39
+ items?: Record<string, TemplateDefinition>;
40
+ }
41
+
42
+ interface PageDefinition {
43
+ template?: string;
44
+ }
45
+
32
46
  interface IASchema {
33
47
  atoms?: ItemsContainer;
34
48
  molecules?: ItemsContainer;
35
49
  organisms?: ItemsContainer;
36
- pages?: Record<string, unknown>;
50
+ templates?: TemplatesContainer;
51
+ pages?: {
52
+ items?: Record<string, PageDefinition>;
53
+ };
37
54
  }
38
55
 
39
56
  export interface ValidationError {
40
57
  component: string;
41
- type: 'molecule' | 'organism';
58
+ type: 'molecule' | 'organism' | 'template' | 'page';
42
59
  field: string;
43
60
  invalidReferences: string[];
44
61
  message: string;
@@ -52,7 +69,9 @@ export function validateCompositionReferences(schema: unknown, designSystemAtoms
52
69
  const atomNames = new Set([...schemaAtoms, ...designSystemAtoms]);
53
70
  const moleculeNames = new Set(Object.keys(s.molecules?.items ?? {}));
54
71
  const organismNames = new Set(Object.keys(s.organisms?.items ?? {}));
72
+ const templateNames = new Set(Object.keys(s.templates?.items ?? {}));
55
73
 
74
+ // Validate molecules reference only atoms
56
75
  for (const [name, def] of Object.entries(s.molecules?.items ?? {})) {
57
76
  const referencedAtoms = def.composition?.atoms ?? [];
58
77
  const invalidAtoms = referencedAtoms.filter((atom: string) => !atomNames.has(atom));
@@ -67,6 +86,7 @@ export function validateCompositionReferences(schema: unknown, designSystemAtoms
67
86
  }
68
87
  }
69
88
 
89
+ // Validate organisms reference only molecules
70
90
  for (const [name, def] of Object.entries(s.organisms?.items ?? {})) {
71
91
  const referencedMolecules = def.composition?.molecules ?? [];
72
92
 
@@ -97,6 +117,35 @@ export function validateCompositionReferences(schema: unknown, designSystemAtoms
97
117
  }
98
118
  }
99
119
 
120
+ // Validate templates reference only organisms
121
+ for (const [name, def] of Object.entries(s.templates?.items ?? {})) {
122
+ const referencedOrganisms = def.layout?.organisms ?? [];
123
+ const invalidOrganisms = referencedOrganisms.filter((org: string) => !organismNames.has(org));
124
+ if (invalidOrganisms.length > 0) {
125
+ errors.push({
126
+ component: name,
127
+ type: 'template',
128
+ field: 'layout.organisms',
129
+ invalidReferences: invalidOrganisms,
130
+ message: `Template "${name}" references non-existent organisms: ${invalidOrganisms.join(', ')}`,
131
+ });
132
+ }
133
+ }
134
+
135
+ // Validate pages reference only templates
136
+ for (const [name, def] of Object.entries(s.pages?.items ?? {})) {
137
+ const referencedTemplate = def.template;
138
+ if (referencedTemplate && !templateNames.has(referencedTemplate)) {
139
+ errors.push({
140
+ component: name,
141
+ type: 'page',
142
+ field: 'template',
143
+ invalidReferences: [referencedTemplate],
144
+ message: `Page "${name}" references non-existent template: ${referencedTemplate}`,
145
+ });
146
+ }
147
+ }
148
+
100
149
  return errors;
101
150
  }
102
151
 
@@ -157,16 +206,68 @@ ${errorContext}
157
206
  IMPORTANT: Only generate pages and components that are directly referenced in the provided model's flows. Do NOT add any extra pages or components, and do NOT make assumptions outside the flows. If something is not mentioned in the flows, it should NOT appear in the output.
158
207
  IMPORTANT: try your best to reuse the existing atoms, and try not to generate atoms with context: like Submit Button, because the submit part is mainly irrelevant, instead just use the Button atom if provided.
159
208
 
160
- CRITICAL COMPOSITION RULES - THESE ARE STRICT AND MUST BE FOLLOWED:
209
+ CRITICAL COMPOSITION RULES - THESE ARE STRICT AND MUST BE FOLLOWED (Atomic Design Methodology):
161
210
  1. Atoms: Basic UI primitives (Button, Text, Input, Icon, etc.). Atoms do NOT compose other atoms.
162
211
  2. Molecules: Composed ONLY of atoms. A molecule's "composition.atoms" array must ONLY reference items that exist in "atoms.items".
163
212
  3. Organisms: Composed of atoms AND molecules. An organism's "composition.molecules" array must ONLY reference items that exist in "molecules.items". An organism MUST NOT reference other organisms.
164
- 4. Pages: Can reference organisms, molecules, and atoms.
213
+ 4. Templates: Page-level layout structures that place organisms into a layout. A template's "layout.organisms" array must ONLY reference items that exist in "organisms.items". Templates define the skeletal framework without real content.
214
+ 5. Pages: Specific instances of templates with real representative content. A page's "template" field must reference a template that exists in "templates.items". Pages are tied to routes and populated with actual data.
215
+
216
+ VISUAL DESIGN PRINCIPLES - Apply these to create beautiful, professional UIs:
217
+
218
+ 1. TYPOGRAPHY HIERARCHY (every component should consider text sizing):
219
+ - Headlines/Titles: Large size, bold weight, commanding presence
220
+ - Subheadings: Medium-large size, semi-bold weight, clear section breaks
221
+ - Body text: Comfortable reading size with good line height
222
+ - Labels/Captions: Small size, subtle color, supporting information
223
+
224
+ 2. COMPONENT PURPOSE & VISUAL ROLE:
225
+ - Molecules should be self-contained, visually complete units (cards, forms, list items)
226
+ - Organisms should compose molecules into meaningful sections (hero sections, feature grids, data tables)
227
+ - Templates define visual rhythm and spacing structure
228
+
229
+ 3. INTERACTIVE ELEMENTS:
230
+ - Every interactive molecule/organism should specify hover, focus, and active states in specs
231
+ - Forms need clear validation states (success, error, loading)
232
+ - Lists need empty states and loading states
233
+
234
+ 4. SEMANTIC NAMING FOR VISUAL CLARITY:
235
+ - Use descriptive names that hint at visual purpose: "HeroSection", "FeatureCard", "StatsGrid", "NavigationSidebar"
236
+ - Avoid generic names like "Section1" or "Component"
237
+
238
+ 5. LAYOUT CONSIDERATIONS IN TEMPLATES:
239
+ - Define clear visual regions: header, sidebar, main content, footer
240
+ - Consider responsive behavior in template specs
241
+ - Use common patterns: dashboard layout, marketing layout, form-centric layout
242
+
243
+ 6. TEMPLATE NAMING AND PURPOSE:
244
+ - Name templates based on their layout structure (e.g., SidebarLayout, CenteredLayout, FullWidthLayout)
245
+ - Templates should be reusable across different pages
246
+ - Include layout-related specs like "responsive sidebar" or "sticky header"
247
+
248
+ 7. ORGANISM DESCRIPTIONS SHOULD SPECIFY VISUAL ROLE:
249
+ Good: "Card grid displaying items with image, title, and action buttons"
250
+ Good: "Navigation bar with logo, menu items, and user actions"
251
+ Bad: "Shows items" (too vague)
252
+ Bad: "Navigation" (no visual details)
253
+
254
+ 8. SPECS SHOULD INCLUDE VISUAL BEHAVIORS:
255
+ Good specs:
256
+ - "displays loading skeleton while fetching data"
257
+ - "shows empty state with icon and action button when no items"
258
+ - "items have hover effect with shadow elevation"
259
+ - "responsive grid: 1 column mobile, 2 tablet, 3 desktop"
260
+ Bad specs (too vague):
261
+ - "shows data"
262
+ - "handles loading"
263
+ - "is responsive"
165
264
 
166
265
  VALIDATION CHECKLIST (the schema will be rejected if these rules are violated):
167
266
  - Every item in a molecule's "composition.atoms" MUST exist in "atoms.items"
168
267
  - Every item in an organism's "composition.molecules" MUST exist in "molecules.items"
169
268
  - An organism's "composition.molecules" MUST NOT contain names that only exist in "organisms.items"
269
+ - Every item in a template's "layout.organisms" MUST exist in "organisms.items"
270
+ - Every page's "template" MUST reference a template that exists in "templates.items"
170
271
  - Cross-check all composition references before finalizing the output
171
272
 
172
273
  $${atoms ? `Here is a list of available atomic components (atoms) from the design system. Use these atoms and their props as much as possible. Only create new atoms if absolutely necessary. And only put the new atoms created into the schema. \n\nAtoms:\n${JSON.stringify(atoms, null, 2)}\n` : ''}
@@ -181,25 +282,32 @@ Instructions:
181
282
 
182
283
  - NEVER generate any data_requirements queries or mutations if NONE were provided from the flow schema
183
284
  - Respond ONLY with a JSON object, no explanation, no markdown, no text before or after.
184
- - The JSON should have two main sections: "components" and "pages".
185
- - In "components", define composite UI elements (atoms, molecules, organisms) with:
285
+ - The JSON should have sections for: "atoms", "molecules", "organisms", "templates", and "pages".
286
+ - In "atoms", "molecules", and "organisms", define composite UI elements with:
186
287
  - A description
187
- - A "composition" field listing the building blocks used, grouped by type:
188
- - "atoms": for atomic UI primitives (e.g., Button, Text, InputField)
189
- - "molecules": for reusable, mid-level components (composed of atoms)
190
- - "organisms": for larger, smart UI components (composed of molecules)
191
- - Example:
288
+ - A "composition" field listing the building blocks used:
289
+ - For molecules: "atoms" array referencing atomic UI primitives
290
+ - For organisms: "molecules" array referencing molecule components
291
+ - Example for molecule:
192
292
  "composition": {
193
- "atoms": ["Button", "Text"],
194
- "molecules": ["SearchBar"],
195
- "organisms": ["TopNavBar"]
293
+ "atoms": ["Button", "Text"]
196
294
  }
197
- - In "pages", define each page as a key, with:
295
+ - Example for organism:
296
+ "composition": {
297
+ "molecules": ["SearchBar", "FilterPanel"]
298
+ }
299
+ - In "templates", define page-level layout structures with:
300
+ - description (what this layout structure provides - be specific about visual arrangement)
301
+ - layout.organisms (array of organisms that make up the template's skeleton)
302
+ - specs (optional array describing layout requirements like "responsive sidebar", "sticky header", "scrollable content area")
303
+ - Templates define the structural framework WITHOUT real content
304
+ - Common template patterns: DashboardTemplate (sidebar + main), MarketingTemplate (full-width sections), FormTemplate (centered narrow container)
305
+ - In "pages", define each page as a specific instance of a template, with:
198
306
  - route (URL path)
199
307
  - description
200
- - template (what wrapper does the page use)
308
+ - template (reference to a template in "templates.items" that defines the page's layout)
201
309
  - navigation (array of navigation actions, e.g., { "on": "Click Listing Card", "to": "ListingDetailPage" })
202
- - data_requirements (array, as above, for page-level data fetching)
310
+ - data_requirements (array for page-level data fetching - this is the "real content" that populates the template)
203
311
  - For each component or page, if there are any specs defined in the model's flow slices, look at slice.client.specs which is an array of strings.
204
312
  - These specs describe behavioral requirements with nested context preserved using ' → ' separator (e.g., "Form → Validation → shows error").
205
313
  - Assign these specs directly to the 'specs' field for the corresponding component/page.
@@ -209,17 +317,37 @@ Use the following structure as a template for your response:
209
317
  ----
210
318
  {
211
319
  "atoms": {
320
+ "description": "Basic UI primitives",
212
321
  "items": {
213
322
  "AtomName": {
214
- ....
323
+ "description": "What this atom does."
215
324
  }
216
325
  }
217
326
  },
218
327
  "molecules": {
328
+ "description": "Components composed from atoms - these are reusable visual units",
219
329
  "items": {
220
- "ComponentName": {
221
- "description": "What this component does.",
222
- "composition": { "primitives": ["Primitive1", "Primitive2"] },
330
+ "MoleculeName": {
331
+ "description": "What this molecule does and its visual appearance (e.g., 'Card displaying user info with avatar, name, and action button').",
332
+ "composition": { "atoms": ["Atom1", "Atom2"] },
333
+ "specs": [
334
+ "hover state shows shadow elevation",
335
+ "click navigates to detail view"
336
+ ]
337
+ }
338
+ }
339
+ },
340
+ "organisms": {
341
+ "description": "Smart UI components composed of molecules - these are visually complete sections",
342
+ "items": {
343
+ "OrganismName": {
344
+ "description": "What this organism does and its visual role (e.g., 'Hero section with headline, subtext, and CTA buttons').",
345
+ "composition": { "molecules": ["Molecule1", "Molecule2"] },
346
+ "specs": [
347
+ "displays loading skeleton while fetching",
348
+ "shows empty state when no data",
349
+ "hover effect on interactive cards"
350
+ ],
223
351
  "data_requirements": [
224
352
  {
225
353
  "type": "query",
@@ -233,18 +361,30 @@ Use the following structure as a template for your response:
233
361
  ]
234
362
  }
235
363
  }
236
- // ... more components
364
+ },
365
+ "templates": {
366
+ "description": "Page-level layout structures that define visual rhythm and regions",
367
+ "items": {
368
+ "TemplateName": {
369
+ "description": "What layout structure this template provides (e.g., 'Dashboard layout with collapsible sidebar and main content area').",
370
+ "layout": { "organisms": ["Organism1", "Organism2"] },
371
+ "specs": ["responsive sidebar collapses on mobile", "sticky header", "scrollable main content"]
372
+ }
373
+ }
237
374
  },
238
375
  "pages": {
239
- "PageName": {
240
- "route": "/route",
241
- "description": "What this page does.",
242
- "navigation": [{ "on": "Event", "to": "TargetPage" }],
243
- "data_requirements": [
244
- // ... as above
245
- ]
376
+ "description": "Specific instances of templates with real content",
377
+ "items": {
378
+ "PageName": {
379
+ "route": "/route",
380
+ "description": "What this page does.",
381
+ "template": "TemplateName",
382
+ "navigation": [{ "on": "Event", "to": "TargetPage" }],
383
+ "data_requirements": [
384
+ // ... as above
385
+ ]
386
+ }
246
387
  }
247
- // ... more pages
248
388
  }
249
389
  }
250
390
  ----