@almadar/skills 1.0.12 → 1.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/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { generateBehaviorsDocs, getAllBehaviors, generateModulesDocs, getAllStdOperators } from '@almadar/std';
4
4
  import { OPERATORS, UI_SLOTS, PATTERN_TYPES, ViewTypeSchema } from '@almadar/core/types';
5
- import { getPatternPropsCompact, getPatternActionsRef, getAllPatternTypes, getPatternsGroupedByCategory } from '@almadar/patterns';
5
+ import { getPatternPropsCompact, getPatternActionsRef, getAllPatternTypes } from '@almadar/patterns';
6
6
 
7
7
  // src/generators/utils.ts
8
8
  function formatFrontmatter(fm) {
@@ -46,24 +46,6 @@ Writing ${skills.length} skills to ${baseDir}...`);
46
46
  console.log(`
47
47
  \u2713 Generated ${skills.length} skills`);
48
48
  }
49
- function getMinimalTypeReference() {
50
- const patternsByCategory = getPatternsGroupedByCategory();
51
- const categories = Object.keys(patternsByCategory);
52
- return `## Type Reference
53
-
54
- ### Pattern Types
55
- ${categories.map((cat) => `- **${cat}**: ${patternsByCategory[cat].slice(0, 5).join(", ")}...`).join("\n")}
56
-
57
- Total: ${PATTERN_TYPES.length} patterns
58
-
59
- ### Operators
60
- Use S-expressions for guards and effects. See std library for full list.
61
-
62
- **Math**: \`+\`, \`-\`, \`*\`, \`/\`, \`>\`, \`<\`, \`>=\`, \`<=\`, \`=\`, \`!=\`
63
- **Logic**: \`and\`, \`or\`, \`not\`
64
- **Effects**: \`set\`, \`++\`, \`--\`, \`persist\`, \`fetch\`, \`emit\`, \`render-ui\`
65
- `;
66
- }
67
49
  function getSExprQuickRef() {
68
50
  return `## S-Expression Syntax
69
51
 
@@ -134,20 +116,27 @@ ${mod.operators.map((op) => `- **${op.name}**: ${op.description}`).join("\n")}
134
116
  }
135
117
  function getStdBehaviorsWithStateMachines() {
136
118
  const behaviors = getAllBehaviors();
137
- const nonGameBehaviors = behaviors.filter(
138
- (b) => !b.category?.includes("game") && b.stateMachine
139
- );
119
+ const nonGameBehaviors = behaviors.filter((b) => {
120
+ const traits = b.orbitals?.[0]?.traits ?? [];
121
+ const hasGameCategory = traits.some((t) => t.category?.includes("game"));
122
+ const hasStateMachine = traits.some((t) => t.stateMachine);
123
+ return !hasGameCategory && hasStateMachine;
124
+ });
140
125
  return `## Standard Behaviors
141
126
 
142
- ${nonGameBehaviors.map((behavior) => `### ${behavior.name}
127
+ ${nonGameBehaviors.map((behavior) => {
128
+ const trait = (behavior.orbitals?.[0]?.traits ?? []).find((t) => t.stateMachine);
129
+ const sm = trait?.stateMachine;
130
+ return `### ${behavior.name}
143
131
 
144
- **States**: ${behavior.stateMachine.states.map((s) => s.name).join(", ")}
145
- **Events**: ${behavior.stateMachine.events.join(", ")}
132
+ **States**: ${sm?.states?.map((s) => s.name).join(", ") ?? "N/A"}
133
+ **Events**: ${sm?.events?.join(", ") ?? "N/A"}
146
134
 
147
135
  \`\`\`json
148
136
  ${JSON.stringify(behavior, null, 2)}
149
137
  \`\`\`
150
- `).join("\n\n")}
138
+ `;
139
+ }).join("\n\n")}
151
140
  `;
152
141
  }
153
142
  function getKeyBehaviorsReference() {
@@ -273,35 +262,23 @@ function getValidViewTypes() {
273
262
  const validTypes = ViewTypeSchema.options;
274
263
  return validTypes.map((t) => `\`${t}\``).join(", ");
275
264
  }
276
- function getCommonErrorsSection() {
265
+ function getCommonErrorsSection(level = "full") {
266
+ const critical = getCriticalErrors();
267
+ if (level === "top6") return critical;
268
+ return critical + getEdgeCaseErrors();
269
+ }
270
+ function getCriticalErrors() {
277
271
  return `## Critical Rules
278
272
 
279
- ### NEVER Use @payload in set Effects (CRITICAL)
280
-
281
- The \`set\` effect modifies entity state. **@payload is READ-ONLY** - it contains event data.
282
-
283
- \`\`\`json
284
- // WRONG - @payload is read-only!
285
- ["set", "@payload.data.createdAt", "@now"]
286
- ["set", "@payload.data.status", "active"]
287
-
288
- // CORRECT - Use @entity to modify state
289
- ["set", "@entity.createdAt", "@now"]
290
- ["set", "@entity.status", "active"]
291
- \`\`\`
292
-
293
- **Rule:** \`set\` target MUST start with \`@entity\`, never \`@payload\`.
294
-
295
- ### INIT Transition Required (CRITICAL)
273
+ ### 1. INIT Transition Required (CRITICAL)
296
274
 
297
275
  Every trait MUST have an INIT self-loop transition. The runtime fires \`INIT\` when page loads.
298
276
 
299
277
  \`\`\`json
300
- // REQUIRED in EVERY trait:
301
278
  {
302
279
  "from": "Browsing",
303
280
  "to": "Browsing",
304
- "event": "INIT", // \u2190 Runtime fires this on page load
281
+ "event": "INIT",
305
282
  "effects": [
306
283
  ["render-ui", "main", { "type": "page-header", ... }],
307
284
  ["render-ui", "main", { "type": "entity-table", ... }]
@@ -311,43 +288,40 @@ Every trait MUST have an INIT self-loop transition. The runtime fires \`INIT\` w
311
288
 
312
289
  Without INIT: Page loads blank, nothing renders, no UI appears.
313
290
 
314
- ### Valid Patterns ONLY (CRITICAL)
291
+ ### 2. NEVER Use @payload in set Effects
315
292
 
316
- **DO NOT invent custom patterns!** Only these patterns exist:
293
+ The \`set\` effect modifies entity state. **@payload is READ-ONLY**.
317
294
 
318
- ${getPatternCategories()}
295
+ \`\`\`json
296
+ // WRONG
297
+ ["set", "@payload.data.status", "active"]
319
298
 
320
- **NEVER use**: \`onboarding-welcome\`, \`category-selector\`, \`assessment-question\`, etc. - these DO NOT exist!
299
+ // CORRECT
300
+ ["set", "@entity.status", "active"]
301
+ \`\`\`
302
+
303
+ **Rule:** \`set\` target MUST start with \`@entity\`, never \`@payload\`.
321
304
 
322
- ### Valid viewType Values
305
+ ### 3. Valid Patterns ONLY
323
306
 
324
- Pages must use valid viewType values: ${getValidViewTypes()}
307
+ **DO NOT invent custom patterns!** Only these patterns exist:
325
308
 
326
- Invalid values like \`form\`, \`wizard\`, \`onboarding\` will cause validation errors.
309
+ ${getPatternCategories()}
327
310
 
328
- ${getPatternPropsCompact()}
311
+ **NEVER use**: \`onboarding-welcome\`, \`category-selector\`, \`assessment-question\`, etc.
329
312
 
330
- ${getPatternActionsRef()}
313
+ Valid viewType values: ${getValidViewTypes()}
331
314
 
332
- ### Page Structure Required (CRITICAL)
315
+ ### 4. Page Structure Required
333
316
 
334
317
  Every page MUST have \`path\` and \`traits\` properties:
335
318
 
336
319
  \`\`\`json
337
- // WRONG - missing path and traits:
338
320
  {
339
321
  "pages": [{
340
322
  "name": "TasksPage",
341
- "entity": "Task" // \u274C Missing path and traits!
342
- }]
343
- }
344
-
345
- // CORRECT - complete page definition:
346
- {
347
- "pages": [{
348
- "name": "TasksPage",
349
- "path": "/tasks", // \u2190 REQUIRED: starts with /
350
- "traits": [{ "ref": "TaskManagement" }] // \u2190 REQUIRED: trait-driven UI
323
+ "path": "/tasks",
324
+ "traits": [{ "ref": "TaskManagement" }]
351
325
  }]
352
326
  }
353
327
  \`\`\`
@@ -355,232 +329,119 @@ Every page MUST have \`path\` and \`traits\` properties:
355
329
  Without \`path\`: Validation error \`ORB_P_MISSING_PATH\`
356
330
  Without \`traits\`: Validation error \`ORB_P_MISSING_TRAITS\`
357
331
 
358
- ### Valid Field Types ONLY (CRITICAL)
332
+ ### 5. Valid Field Types ONLY
359
333
 
360
334
  Field types MUST be one of: \`string\`, \`number\`, \`boolean\`, \`date\`, \`timestamp\`, \`datetime\`, \`array\`, \`object\`, \`enum\`, \`relation\`
361
335
 
362
336
  \`\`\`json
363
337
  // WRONG - using entity name as type:
364
- { "name": "author", "type": "User" } // \u274C "User" is not a valid type!
365
- { "name": "post", "type": "BlogPost" } // \u274C Invalid!
338
+ { "name": "author", "type": "User" }
366
339
 
367
- // CORRECT - use relation type with entity reference:
340
+ // CORRECT - use relation type:
368
341
  { "name": "author", "type": "relation", "relation": { "entity": "User", "cardinality": "one" } }
369
- { "name": "post", "type": "relation", "relation": { "entity": "BlogPost", "cardinality": "one" } }
370
-
371
- // CORRECT for arrays of primitives:
372
- { "name": "tags", "type": "array", "items": { "type": "string" } }
373
-
374
- // CORRECT for enums:
375
- { "name": "status", "type": "enum", "values": ["pending", "active", "done"] }
376
342
  \`\`\`
377
343
 
378
- ### Event Listeners Structure
344
+ ### 6. Modal State Machine Pattern
379
345
 
380
- Event listeners go INSIDE traits, not at orbital level:
346
+ When a transition opens a modal/drawer, the target state MUST have CLOSE and CANCEL transitions:
381
347
 
382
348
  \`\`\`json
383
- // WRONG - at orbital level:
384
- {
385
- "name": "Task Management",
386
- "listens": ["SOME_EVENT"] // \u274C Wrong location, wrong format
387
- }
388
-
389
- // CORRECT - inside trait:
390
- {
391
- "traits": [{
392
- "name": "TaskInteraction",
393
- "listens": [
394
- { "event": "USER_UPDATED", "handler": "REFRESH_LIST" } // \u2705 Object format
395
- ]
396
- }]
397
- }
349
+ { "from": "Browsing", "to": "Creating", "event": "CREATE",
350
+ "effects": [["render-ui", "modal", { "type": "form-section", "cancelEvent": "CANCEL", ... }]] },
351
+ { "from": "Creating", "to": "Browsing", "event": "CANCEL",
352
+ "effects": [["render-ui", "modal", null]] },
353
+ { "from": "Creating", "to": "Browsing", "event": "CLOSE",
354
+ "effects": [["render-ui", "modal", null]] },
355
+ { "from": "Creating", "to": "Browsing", "event": "SAVE",
356
+ "effects": [["persist", "create", "Entity", "@payload.data"], ["render-ui", "modal", null], ["emit", "INIT"]] }
398
357
  \`\`\`
399
358
 
359
+ **CLOSE** = user clicks outside modal/presses Escape. **CANCEL** = form cancel button. Both needed.
360
+ `;
361
+ }
362
+ function getEdgeCaseErrors() {
363
+ return `
400
364
  ---
401
365
 
402
- ## Common Errors (AVOID)
403
-
404
- ### 1. Missing INIT Transition
405
- \`\`\`
406
- WRONG: No INIT transition \u2192 Page loads blank
407
- CORRECT: { "from": "browsing", "to": "browsing", "event": "INIT", "effects": [...render-ui...] }
408
- \`\`\`
366
+ ## Additional Errors (Edge Cases)
409
367
 
410
- ### 2. Over-Generating Pages
368
+ ### 7. Over-Generating Pages
411
369
  \`\`\`
412
370
  WRONG: TaskListPage, TaskCreatePage, TaskEditPage, TaskViewPage (4 pages!)
413
371
  CORRECT: TasksPage with EntityManagement trait (1 page)
414
372
  \`\`\`
415
373
 
416
- ### 3. Duplicate Slot Rendering
374
+ ### 8. Duplicate Slot Rendering
417
375
  \`\`\`
418
376
  WRONG: Two traits both render to "main" on page load
419
377
  CORRECT: ONE trait owns each slot
420
378
  \`\`\`
421
379
 
422
- ### 4. Missing onSubmit in form-section
380
+ ### 9. Missing onSubmit in form-section
423
381
  \`\`\`
424
382
  WRONG: { "type": "form-section", "entity": "Task" }
425
383
  CORRECT: { "type": "form-section", "entity": "Task", "onSubmit": "SAVE" }
426
384
  \`\`\`
427
385
 
428
- ### 5. Duplicate Transitions (Same from+event)
386
+ ### 10. Duplicate Transitions (Same from+event)
429
387
  \`\`\`
430
388
  WRONG: Two transitions with same "from" and "event" without guards
431
389
  CORRECT: Use GUARDS to differentiate transitions
432
390
  \`\`\`
433
391
 
434
- ### 6. Using "render" Instead of "render-ui"
392
+ ### 11. Using "render" Instead of "render-ui"
435
393
  \`\`\`
436
394
  WRONG: ["render", "main", {...}]
437
395
  CORRECT: ["render-ui", "main", {...}]
438
396
  \`\`\`
439
397
 
440
- ### 7. Generating Sections Array (Legacy)
398
+ ### 12. Generating Sections Array (Legacy)
441
399
  \`\`\`
442
400
  WRONG: { "pages": [{ "sections": [...] }] }
443
401
  CORRECT: { "pages": [{ "traits": [...] }] } - UI comes from render-ui effects
444
402
  \`\`\`
445
403
 
446
- ### 8. Using form-actions Pattern (DOES NOT EXIST!)
404
+ ### 13. Using form-actions Pattern (DOES NOT EXIST!)
447
405
  \`\`\`
448
406
  WRONG: ["render-ui", "main", { "type": "form-actions", "actions": [...] }]
449
- CORRECT: Use form-section with onSubmit/onCancel props:
450
- { "type": "form-section", "entity": "Task", "fields": [...], "onSubmit": "SAVE", "onCancel": "CANCEL" }
407
+ CORRECT: Use form-section with onSubmit/onCancel props
451
408
  \`\`\`
452
- Actions are INSIDE patterns, not separate patterns. The form-section pattern includes submit/cancel buttons.
409
+ Actions are INSIDE patterns, not separate patterns.
453
410
 
454
- ### 9. Forgetting itemActions in entity-table
411
+ ### 14. Forgetting itemActions in entity-table
455
412
  \`\`\`
456
- WRONG: { "type": "entity-table", "entity": "Task" } // No row actions
457
- CORRECT: { "type": "entity-table", "entity": "Task", "itemActions": [{"label": "Edit", "event": "EDIT"}, {"label": "Delete", "event": "DELETE"}] }
413
+ WRONG: { "type": "entity-table", "entity": "Task" }
414
+ CORRECT: { "type": "entity-table", "entity": "Task", "itemActions": [{"label": "Edit", "event": "EDIT"}] }
458
415
  \`\`\`
459
416
 
460
- ### 10. Duplicate Trait Names Across Orbitals
417
+ ### 15. Duplicate Trait Names Across Orbitals
461
418
  \`\`\`
462
419
  WRONG: UserOrbital uses "EntityManagement", TaskOrbital uses "EntityManagement"
463
420
  CORRECT: UserOrbital uses "UserManagement", TaskOrbital uses "TaskManagement"
464
421
  \`\`\`
465
422
  Each trait name MUST be unique. Pattern: \`{Entity}{Purpose}\`
466
423
 
467
- ### 11. Using @payload in set Effect
468
- \`\`\`
469
- WRONG: ["set", "@payload.acceptedAt", "@now"] // @payload is read-only!
470
- CORRECT: ["set", "@entity.acceptedAt", "@now"] // set modifies entity state
471
- \`\`\`
472
- \`set\` effect MUST use \`@entity.field\` binding. \`@payload\` is read-only event data.
473
-
474
- ### 12. Hallucinated itemAction Properties
424
+ ### 16. Hallucinated itemAction Properties
475
425
  \`\`\`
476
- WRONG: { "label": "View", "event": "VIEW", "condition": "@entity.status === 'active'" }
477
- CORRECT: { "label": "View", "event": "VIEW", "showWhen": ["=", "@entity.status", "active"] }
426
+ WRONG: { "label": "View", "event": "VIEW", "condition": "..." }
427
+ CORRECT: { "label": "View", "event": "VIEW" }
478
428
  \`\`\`
479
429
  Valid itemAction props: \`label\`, \`event\`, \`navigatesTo\`, \`placement\`, \`variant\`, \`showWhen\`
480
- Note: \`showWhen\` is defined but NOT yet implemented - actions always visible.
481
-
482
- ### 14. Missing Page Path
483
- \`\`\`
484
- WRONG: { "pages": [{ "name": "TasksPage", "entity": "Task" }] }
485
- CORRECT: { "pages": [{ "name": "TasksPage", "path": "/tasks", "traits": [...] }] }
486
- \`\`\`
487
430
 
488
- ### 15. Using Entity Name as Field Type
489
- \`\`\`
490
- WRONG: { "name": "author", "type": "User" }
491
- CORRECT: { "name": "author", "type": "relation", "relation": { "entity": "User", "cardinality": "one" } }
492
- \`\`\`
493
-
494
- ### 16. Missing Traits Array on Page
495
- \`\`\`
496
- WRONG: { "pages": [{ "name": "TasksPage", "path": "/tasks" }] }
497
- CORRECT: { "pages": [{ "name": "TasksPage", "path": "/tasks", "traits": [{ "ref": "TaskManagement" }] }] }
498
- \`\`\`
499
-
500
- ### 13. Modal State Machine Pattern (CRITICAL)
501
-
502
- When a transition opens a modal (renders to \`modal\` or \`drawer\` slot), the target state MUST have:
503
- 1. A **CLOSE** transition to clear the modal and return to browsing state
504
- 2. A **CANCEL** transition (for forms with cancel buttons)
505
- 3. The CLOSE/CANCEL effects MUST include \`["render-ui", "modal", null]\` to clear the slot
506
-
507
- \`\`\`json
508
- // WRONG - Modal opens but no way to close it!
509
- {
510
- "from": "browsing", "to": "creating", "event": "CREATE",
511
- "effects": [["render-ui", "modal", { "type": "form-section", ... }]]
512
- }
513
- // No CLOSE or CANCEL transition from "creating" \u2192 Page gets stuck!
514
-
515
- // CORRECT - Full modal open/close cycle:
516
- {
517
- "from": "browsing", "to": "creating", "event": "CREATE",
518
- "effects": [["render-ui", "modal", { "type": "form-section", "cancelEvent": "CANCEL", ... }]]
519
- },
520
- {
521
- "from": "creating", "to": "browsing", "event": "CANCEL",
522
- "effects": [["render-ui", "modal", null]]
523
- },
524
- {
525
- "from": "creating", "to": "browsing", "event": "CLOSE",
526
- "effects": [["render-ui", "modal", null]]
527
- },
528
- {
529
- "from": "creating", "to": "browsing", "event": "SAVE",
530
- "effects": [
531
- ["persist", "create", "Entity", "@payload.data"],
532
- ["render-ui", "modal", null], // \u2190 IMPORTANT: Clear modal on save too!
533
- ["fetch", "Entity", {}]
534
- ]
535
- }
536
- \`\`\`
537
-
538
- **Why CLOSE is needed:** The UI sends \`CLOSE\` when user clicks outside the modal or presses Escape.
539
- **Why CANCEL is needed:** Forms emit \`CANCEL\` when user clicks the Cancel button.
540
- **Both are needed** for complete modal behavior. Without them, the modal cannot be dismissed and reopened.
541
-
542
- ### 14. Wrong Filtering Pattern (Use Query Singleton)
543
- \`\`\`
544
- WRONG: Individual filter buttons with manual FILTER events
545
- { "type": "button", "label": "Active", "action": "FILTER", "data": { "status": "active" } }
546
-
547
- CORRECT: Use Query Singleton entity + filter-group pattern:
548
- \`\`\`
549
-
550
- **Query Singleton Pattern for Filtering:**
551
-
552
- 1. Define a singleton entity to hold filter state:
553
- \`\`\`json
554
- {
555
- "name": "TaskQuery",
556
- "entity": {
557
- "name": "TaskQuery",
558
- "singleton": true,
559
- "runtime": true,
560
- "fields": [
561
- { "name": "status", "type": "string" },
562
- { "name": "search", "type": "string" }
563
- ]
564
- }
565
- }
566
- \`\`\`
567
-
568
- 2. Use \`set\` effects to update filter state:
431
+ ### 17. Event Listeners Structure
432
+ Event listeners go INSIDE traits, not at orbital level:
569
433
  \`\`\`json
570
- {
571
- "from": "Browsing", "to": "Browsing", "event": "FILTER",
572
- "effects": [["set", "@TaskQuery.status", "@payload.status"]]
573
- }
434
+ "traits": [{ "name": "TaskInteraction",
435
+ "listens": [{ "event": "USER_UPDATED", "handler": "REFRESH_LIST" }] }]
574
436
  \`\`\`
575
437
 
576
- 3. Reference query in patterns:
438
+ ### 18. Wrong Filtering Pattern (Use Query Singleton)
439
+ Use a singleton entity for filter state + \`query\` prop on entity-table:
577
440
  \`\`\`json
578
- ["render-ui", "main", {
579
- "type": "entity-table",
580
- "entity": "Task",
581
- "query": "@TaskQuery"
582
- }]
441
+ { "name": "TaskQuery", "entity": { "name": "TaskQuery", "singleton": true, "runtime": true,
442
+ "fields": [{ "name": "status", "type": "string" }, { "name": "search", "type": "string" }] } }
583
443
  \`\`\`
444
+ Reference: \`["render-ui", "main", { "type": "entity-table", "entity": "Task", "query": "@TaskQuery" }]\`
584
445
  `;
585
446
  }
586
447
  function getValidationHintsSection() {
@@ -699,6 +560,78 @@ function getDecompositionChecklist() {
699
560
  - [ ] emits/listens defined for cross-orbital events
700
561
  `;
701
562
  }
563
+ function getDecompositionCompact() {
564
+ return `## Orbital Decomposition Protocol
565
+
566
+ ### Step 0: Classify Domain
567
+ | Domain | Keywords | Key Traits |
568
+ |--------|----------|------------|
569
+ | business | manage, track, workflow | EntityManagement, SearchAndFilter |
570
+ | game | play, score, level | Physics2D, Health, GameState |
571
+ | form | wizard, onboarding | Wizard, FormSubmission |
572
+ | dashboard | metrics, KPI | EntityManagement |
573
+ | content | blog, CMS | none (page navigation) |
574
+
575
+ ### Step 1: Identify Entities (ONE Orbital Per Entity)
576
+ - What are the core data objects?
577
+ - persistent (DB), runtime (memory), or singleton (config)?
578
+ - **CRITICAL: Create exactly ONE orbital per entity**
579
+
580
+ ### Step 2: Select Interaction Model
581
+ | Domain | Create | View | Edit | Delete |
582
+ |--------|--------|------|------|--------|
583
+ | business | modal | drawer | modal | confirm |
584
+ | game | none | none | none | none |
585
+ | form | wizard | drawer | page | confirm |
586
+
587
+ ### Step 3: Choose Traits
588
+ - Business: EntityManagement (handles CRUD via render-ui)
589
+ - Game: Physics2D, Health, Score, Collision
590
+ - Form: Wizard (multi-step) or FormSubmission (single)
591
+
592
+ ### Step 4: Define State Machine
593
+ \`\`\`
594
+ states: Identify user-facing modes (browsing, creating, editing, viewing)
595
+ events: Identify user actions (INIT, CREATE, VIEW, EDIT, SAVE, CLOSE)
596
+ transitions: Map (from, event) \u2192 (to, effects)
597
+ \`\`\`
598
+
599
+ ### Step 5: Add INIT Transition (CRITICAL)
600
+ Every trait MUST have an INIT self-loop with render-ui effects. Without INIT, the page loads blank!
601
+
602
+ ### Step 6: Define Pages
603
+ - ONE page per entity (business) or workflow (form)
604
+ - Attach traits to pages via \`traits\` array
605
+ - Add \`"guard"\` (singular) S-expressions on SAVE transitions for business rules
606
+ `;
607
+ }
608
+ function getConnectivityCompact() {
609
+ return `## Orbital Connectivity
610
+
611
+ For multi-entity apps, connect orbitals:
612
+
613
+ \`\`\`json
614
+ {
615
+ "entity": {
616
+ "fields": [
617
+ { "name": "customerId", "type": "relation", "relation": { "entity": "Customer", "cardinality": "one" } }
618
+ ]
619
+ },
620
+ "emits": ["ORDER_COMPLETED"],
621
+ "listens": [{ "event": "MENU_ITEM_UNAVAILABLE", "triggers": "DISABLE_ITEM" }],
622
+ "design": {
623
+ "uxHints": {
624
+ "relatedLinks": [{ "relation": "customerId", "label": "View Customer", "targetView": "detail" }]
625
+ }
626
+ }
627
+ }
628
+ \`\`\`
629
+
630
+ - **relation fields**: Link entities (Order \u2192 Customer)
631
+ - **emits/listens**: Cross-orbital event communication
632
+ - **relatedLinks**: Navigation between related records
633
+ `;
634
+ }
702
635
  function getFlowPatternSection() {
703
636
  return `## Flow Pattern Selection
704
637
 
@@ -804,6 +737,151 @@ Orbitals communicate via events:
804
737
  - Add relatedLinks for navigation between related records
805
738
  `;
806
739
  }
740
+ function getRenderUIDesignGuide() {
741
+ return `## Render-UI Design Guide
742
+
743
+ ### Syntax
744
+ \`["render-ui", slot, { "type": pattern, ...props }]\`
745
+ Clear slot: \`["render-ui", "modal", null]\`
746
+
747
+ ### Slot Strategy
748
+ | Slot | Use For | Composable? |
749
+ |------|---------|-------------|
750
+ | \`main\` | Primary content | **YES** \u2014 stack multiple render-ui calls |
751
+ | \`modal\` | Forms (create/edit), confirmations | One at a time |
752
+ | \`drawer\` | Detail views, quick edits | One at a time |
753
+ | \`sidebar\` | Navigation, persistent filters | One at a time |
754
+ | \`overlay\` | Confirmations, alerts | One at a time |
755
+
756
+ ### Pattern Selection by Intent
757
+ | Intent | Patterns | Key Props |
758
+ |--------|----------|-----------|
759
+ | List/browse data | \`entity-table\`, \`entity-cards\`, \`entity-list\` | columns, itemActions, searchable |
760
+ | Show metrics/KPIs | \`stats\` | metrics: [{label, value, icon, trend}] |
761
+ | Filter/search | \`filter-group\`, \`search-input\` | filters (from entity enum fields) |
762
+ | Create/edit form | \`form-section\` | fields, submitEvent, cancelEvent |
763
+ | View details | \`entity-detail\`, \`detail-panel\` | fields/fieldNames, actions |
764
+ | Organize content | \`tabs\` | tabs: [{label, content}] |
765
+ | Dashboard layout | \`dashboard-grid\` | columns (number) |
766
+ | Charts | \`chart\` | chartType, data, xAxis, yAxis |
767
+ | Progress | \`progress-bar\`, \`meter\` | value, max, label |
768
+ | Timeline | \`timeline\` | items: [{date, title, description}] |
769
+ | Page heading | \`page-header\` | title, subtitle, actions |
770
+ | Confirmation | \`confirmation\` | title, message, onConfirm, onCancel |
771
+ | Master/detail | \`master-detail\` | Split list + detail |
772
+ | Cards grid | \`entity-cards\` | columns, itemActions, layout |
773
+
774
+ ### Composition Recipes
775
+
776
+ **CRUD Browsing INIT** (most common \u2014 compose ALL of these in main slot):
777
+ \`\`\`json
778
+ ["render-ui", "main", { "type": "page-header", "title": "Tasks", "subtitle": "Manage your tasks", "actions": [{ "label": "New Task", "event": "CREATE", "variant": "primary" }] }],
779
+ ["render-ui", "main", { "type": "stats", "entity": "Task", "metrics": [{ "label": "Total", "value": "@count", "icon": "clipboard" }, { "label": "Active", "value": "@count:status=active", "icon": "clock" }, { "label": "Done", "value": "@count:status=done", "icon": "check-circle" }] }],
780
+ ["render-ui", "main", { "type": "entity-table", "entity": "Task", "columns": ["title", "status", "createdAt"], "searchable": true, "itemActions": [{ "label": "View", "event": "VIEW" }, { "label": "Edit", "event": "EDIT" }, { "label": "Delete", "event": "DELETE" }] }]
781
+ \`\`\`
782
+
783
+ **Dashboard INIT**:
784
+ \`\`\`
785
+ main: page-header \u2192 title + date range actions
786
+ main: dashboard-grid \u2192 columns: 3
787
+ main: stats \u2192 computed KPIs from entity counts
788
+ main: chart \u2192 primary data visualization
789
+ main: entity-cards \u2192 recent items (limit: 6)
790
+ \`\`\`
791
+
792
+ **Detail View (drawer)**:
793
+ \`\`\`
794
+ drawer: entity-detail \u2192 all fields + [Edit, Delete] actions
795
+ drawer: tabs \u2192 related collections (if entity has relation fields)
796
+ \`\`\`
797
+
798
+ **Wizard Flow**:
799
+ \`\`\`
800
+ main: wizard-progress \u2192 steps array + currentStep
801
+ main: wizard-container \u2192 current step content
802
+ main: wizard-navigation \u2192 Back/Next/Submit buttons
803
+ \`\`\`
804
+
805
+ ### Layout Composition (stack, box, grid)
806
+
807
+ Layout patterns wrap other patterns via \`children\` arrays for rich, structured views.
808
+
809
+ **VStack** (vertical stack): \`{ "type": "stack", "direction": "vertical", ... }\`
810
+ **HStack** (horizontal stack): \`{ "type": "stack", "direction": "horizontal", ... }\`
811
+ **Box** (styled container): \`{ "type": "box", ... }\`
812
+
813
+ #### Stack Props
814
+ | Prop | Values | Default |
815
+ |------|--------|---------|
816
+ | \`direction\` | \`"vertical"\`, \`"horizontal"\` | \`"vertical"\` |
817
+ | \`gap\` | \`"none"\`, \`"xs"\`, \`"sm"\`, \`"md"\`, \`"lg"\`, \`"xl"\` | \`"md"\` |
818
+ | \`align\` | \`"start"\`, \`"center"\`, \`"end"\`, \`"stretch"\` | \`"stretch"\` |
819
+ | \`justify\` | \`"start"\`, \`"center"\`, \`"end"\`, \`"between"\`, \`"around"\` | \`"start"\` |
820
+ | \`wrap\` | \`true\`, \`false\` | \`false\` |
821
+
822
+ #### Box Props
823
+ | Prop | Values |
824
+ |------|--------|
825
+ | \`padding\` / \`paddingX\` / \`paddingY\` | \`"none"\`, \`"xs"\`, \`"sm"\`, \`"md"\`, \`"lg"\`, \`"xl"\` |
826
+ | \`bg\` | \`"default"\`, \`"muted"\`, \`"card"\`, \`"primary"\`, \`"secondary"\`, \`"accent"\` |
827
+ | \`border\` | \`true\`, \`false\` |
828
+ | \`rounded\` | \`"none"\`, \`"sm"\`, \`"md"\`, \`"lg"\`, \`"full"\` |
829
+ | \`shadow\` | \`"none"\`, \`"sm"\`, \`"md"\`, \`"lg"\` |
830
+
831
+ #### Grid Props
832
+ | Prop | Values |
833
+ |------|--------|
834
+ | \`cols\` | \`1\`\u2013\`12\` or \`{ sm: 1, md: 2, lg: 3 }\` |
835
+ | \`gap\` | \`"none"\`, \`"xs"\`, \`"sm"\`, \`"md"\`, \`"lg"\`, \`"xl"\` |
836
+
837
+ #### Nesting Example \u2014 Page Header + Stats Row + Table
838
+ \`\`\`json
839
+ ["render-ui", "main", {
840
+ "type": "stack", "direction": "vertical", "gap": "lg",
841
+ "children": [
842
+ { "type": "stack", "direction": "horizontal", "justify": "between", "align": "center",
843
+ "children": [
844
+ { "type": "typography", "variant": "h1", "text": "Orders" },
845
+ { "type": "button", "label": "New Order", "event": "CREATE", "variant": "primary" }
846
+ ]
847
+ },
848
+ { "type": "stack", "direction": "horizontal", "gap": "md", "wrap": true,
849
+ "children": [
850
+ { "type": "box", "padding": "md", "bg": "card", "border": true, "rounded": "md",
851
+ "children": [{ "type": "stats", "metrics": [{ "label": "Total", "value": "@count" }] }]
852
+ },
853
+ { "type": "box", "padding": "md", "bg": "card", "border": true, "rounded": "md",
854
+ "children": [{ "type": "stats", "metrics": [{ "label": "Pending", "value": "@count:status=pending" }] }]
855
+ }
856
+ ]
857
+ },
858
+ { "type": "entity-table", "entity": "Order", "columns": ["customer", "total", "status"], "searchable": true }
859
+ ]
860
+ }]
861
+ \`\`\`
862
+
863
+ #### When to Use Layout Patterns
864
+ - **VStack**: Default page layout \u2014 stack header, content sections, tables vertically
865
+ - **HStack**: Side-by-side elements \u2014 stat cards, action buttons, header with controls
866
+ - **Box**: Visual grouping \u2014 cards, panels, highlighted sections with borders/backgrounds
867
+ - **Grid**: Equal-width columns \u2014 dashboard cards, stat grids, gallery layouts
868
+
869
+ > **Tip**: A single \`render-ui\` call with a top-level \`stack\` containing nested children produces a more cohesive layout than multiple flat \`render-ui\` calls to the same slot.
870
+
871
+ ### Domain-Aware Pattern Selection
872
+ | Domain | List Pattern | Extras |
873
+ |--------|-------------|--------|
874
+ | business/admin | \`entity-table\` (searchable) | \`stats\`, \`filter-group\` |
875
+ | e-commerce | \`entity-cards\` | \`stats\` (revenue), \`chart\` |
876
+ | content/CMS | \`entity-cards\` | \`tabs\`, \`media-gallery\` |
877
+ | dashboard | \`dashboard-grid\` | \`stats\`, \`chart\`, \`meter\`, \`timeline\` |
878
+ | workflow | \`entity-table\` | \`progress-bar\`, \`timeline\` |
879
+
880
+ ${getPatternPropsCompact()}
881
+
882
+ ${getPatternActionsRef()}
883
+ `;
884
+ }
807
885
 
808
886
  // src/prompts/skill-sections/custom-traits.ts
809
887
  function getCustomTraitSection() {
@@ -1889,13 +1967,16 @@ function generateLeanOrbitalSkill(options = {}) {
1889
1967
  const {
1890
1968
  includeExample = true,
1891
1969
  includeToolWorkflow = true,
1892
- includeStdLibrary = true,
1970
+ includeStdLibrary = false,
1893
1971
  stdLibraryFull = false,
1894
- includeStdStateMachines = true,
1895
- includeSchemaUpdates = true
1972
+ includeStdStateMachines = false,
1973
+ includeSchemaUpdates = false,
1974
+ includeCustomTraits = false,
1975
+ errorLevel = "top6",
1976
+ includeDesignGuide = true
1896
1977
  } = options;
1897
1978
  let stdSection = "";
1898
- if (includeStdLibrary) {
1979
+ if (includeStdLibrary || includeStdStateMachines) {
1899
1980
  if (includeStdStateMachines) {
1900
1981
  stdSection = `---
1901
1982
 
@@ -1917,6 +1998,8 @@ ${getStdMinimalReference()}
1917
1998
  `;
1918
1999
  }
1919
2000
  }
2001
+ const decompositionSection = includeStdStateMachines || includeCustomTraits ? getDecompositionSection() : getDecompositionCompact();
2002
+ const connectivitySection = includeStdStateMachines || includeCustomTraits ? getOrbitalConnectivitySection() : getConnectivityCompact();
1920
2003
  return `# Orbital Generation Skill
1921
2004
 
1922
2005
  > Generate Orbital applications using Orbital Units: Entity \xD7 Traits \xD7 Patterns
@@ -1925,15 +2008,11 @@ ${getArchitectureSection()}
1925
2008
 
1926
2009
  ---
1927
2010
 
1928
- ${getMinimalTypeReference()}
1929
-
1930
- ---
1931
-
1932
2011
  ${getSExprQuickRef()}
1933
2012
 
1934
2013
  ---
1935
2014
 
1936
- ${getRenderUIQuickRef()}
2015
+ ${includeDesignGuide ? getRenderUIDesignGuide() : ""}
1937
2016
 
1938
2017
  ${stdSection}
1939
2018
  ---
@@ -1942,7 +2021,7 @@ ${getFlowPatternSection()}
1942
2021
 
1943
2022
  ---
1944
2023
 
1945
- ${getDecompositionSection()}
2024
+ ${decompositionSection}
1946
2025
 
1947
2026
  ---
1948
2027
 
@@ -1950,7 +2029,7 @@ ${getPortableOrbitalOutputSection()}
1950
2029
 
1951
2030
  ---
1952
2031
 
1953
- ${getOrbitalConnectivitySection()}
2032
+ ${connectivitySection}
1954
2033
 
1955
2034
  ---
1956
2035
 
@@ -1958,12 +2037,12 @@ ${getContextUsageCompact()}
1958
2037
 
1959
2038
  ---
1960
2039
 
1961
- ${getCommonErrorsSection()}
2040
+ ${getCommonErrorsSection(errorLevel)}
1962
2041
 
1963
- ---
2042
+ ${includeCustomTraits ? `---
1964
2043
 
1965
2044
  ${getCustomTraitSection()}
1966
-
2045
+ ` : ""}
1967
2046
  ${includeToolWorkflow ? getToolWorkflowSection() : ""}
1968
2047
 
1969
2048
  ${includeSchemaUpdates ? `---
@@ -2024,17 +2103,67 @@ function getToolWorkflowSection() {
2024
2103
 
2025
2104
  ## Tool Workflow
2026
2105
 
2027
- 1. **DECOMPOSE**: Break requirements into OrbitalUnits
2028
- 2. **GENERATE**: Call \`generate_orbital\` for each orbital
2029
- 3. **COMBINE**: Call \`construct_combined_schema\` (FINAL STEP)
2106
+ ### Phase 1: DECOMPOSE
2107
+ Break requirements into OrbitalUnits (pure reasoning, no tools).
2108
+
2109
+ ### Phase 2: GENERATE
2110
+ Call \`generate_orbital\` for each orbital:
2030
2111
 
2031
2112
  \`\`\`
2032
2113
  generate_orbital({ orbital: {...}, orbitalIndex: 0, totalOrbitals: N })
2033
2114
  generate_orbital({ orbital: {...}, orbitalIndex: 1, totalOrbitals: N })
2034
2115
  ...
2035
- construct_combined_schema({ name: "App", description: "..." })
2036
- # STOP HERE - job is done
2037
2116
  \`\`\`
2117
+
2118
+ Each orbital is written to \`.orbitals/<name>.json\` with ALL effects (render-ui, persist, emit, set, etc.).
2119
+
2120
+ ### Phase 3: COMBINE
2121
+ Call \`finish_task\` to auto-combine and validate:
2122
+
2123
+ \`\`\`
2124
+ finish_task({ appName: "App" })
2125
+ # Reads .orbitals/*.json \u2192 schema.json \u2192 orbital validate
2126
+ \`\`\`
2127
+
2128
+ ### Phase 4: DESIGN REFINEMENT (optional but recommended)
2129
+
2130
+ After \`finish_task\` produces \`schema.json\`, enhance key transitions with \`design_transition\`.
2131
+
2132
+ **When to use**: INIT transitions (they benefit most from rich composition \u2014 header + stats + content), and CREATE/VIEW transitions for polished forms and detail views.
2133
+
2134
+ **Step-by-step:**
2135
+
2136
+ 1. Call \`design_transition\` for the transition:
2137
+ \`\`\`json
2138
+ {
2139
+ "from": "Browsing", "to": "Browsing", "event": "INIT",
2140
+ "slot": "main", "entityName": "Task",
2141
+ "entityFields": [{"name": "title", "type": "string"}, {"name": "status", "type": "enum", "values": ["pending", "active", "done"]}],
2142
+ "domainCategory": "business"
2143
+ }
2144
+ \`\`\`
2145
+ Returns: \`{ "success": true, "effects": [["render-ui", "main", {...}], ...] }\`
2146
+
2147
+ 2. Extract the orbital chunk:
2148
+ \`\`\`json
2149
+ { "file": "schema.json", "type": "orbital", "name": "Task Management" }
2150
+ \`\`\`
2151
+
2152
+ 3. Edit the chunk file: replace render-ui effects in the target transition with the designed effects. **Keep all non-render-ui effects** (persist, emit, set) \u2014 only replace the render-ui tuples.
2153
+
2154
+ 4. Apply the chunk back:
2155
+ \`\`\`json
2156
+ { "chunkId": "<id from extract_chunk>" }
2157
+ \`\`\`
2158
+
2159
+ **Splicing rule**: For a transition with mixed effects like:
2160
+ \`\`\`json
2161
+ [["persist", "create", "Task", "@payload.data"], ["render-ui", "modal", null], ["emit", "INIT"]]
2162
+ \`\`\`
2163
+ Keep \`persist\` and \`emit\`, replace \`render-ui\` with the designed effects.
2164
+ For INIT transitions (render-ui only), replace all effects.
2165
+
2166
+ **Skip design_transition for**: SAVE, CANCEL, CONFIRM_DELETE transitions (they have persist/emit effects with simple slot-clearing \u2014 no UI to design).
2038
2167
  `;
2039
2168
  }
2040
2169
  function getMinimalExample() {
@@ -2072,8 +2201,9 @@ function getMinimalExample() {
2072
2201
  {
2073
2202
  "from": "Browsing", "to": "Browsing", "event": "INIT",
2074
2203
  "effects": [
2075
- ["render-ui", "main", { "type": "page-header", "title": "Tasks", "actions": [{ "label": "New Task", "event": "CREATE", "variant": "primary" }] }],
2076
- ["render-ui", "main", { "type": "entity-table", "entity": "Task", "columns": ["title", "status"], "itemActions": [{ "label": "View", "event": "VIEW" }, { "label": "Edit", "event": "EDIT" }, { "label": "Delete", "event": "DELETE" }] }]
2204
+ ["render-ui", "main", { "type": "page-header", "title": "Tasks", "subtitle": "Manage your tasks", "actions": [{ "label": "New Task", "event": "CREATE", "variant": "primary" }] }],
2205
+ ["render-ui", "main", { "type": "stats", "entity": "Task", "metrics": [{ "label": "Total", "value": "@count", "icon": "clipboard" }, { "label": "Active", "value": "@count:status=active", "icon": "clock" }, { "label": "Done", "value": "@count:status=done", "icon": "check-circle" }] }],
2206
+ ["render-ui", "main", { "type": "entity-table", "entity": "Task", "columns": ["title", "status"], "searchable": true, "itemActions": [{ "label": "View", "event": "VIEW" }, { "label": "Edit", "event": "EDIT" }, { "label": "Delete", "event": "DELETE" }] }]
2077
2207
  ]
2078
2208
  },
2079
2209
  {
@@ -2130,14 +2260,15 @@ function getMinimalExample() {
2130
2260
 
2131
2261
  **Key points**:
2132
2262
  - ONE page (TasksPage) not four (list/create/edit/view)
2133
- - INIT transition renders initial UI (page-header + entity-table)
2263
+ - INIT transition composes **multiple patterns**: page-header + stats + entity-table
2134
2264
  - States are OBJECTS with \`isInitial\` flag
2135
2265
  - **Actions are INSIDE patterns (use unified props)**:
2136
2266
  - \`page-header\` has \`actions: [{label, event, variant}]\`
2137
- - \`entity-table\` has \`itemActions: [{label, event}]\`
2267
+ - \`entity-table\` has \`itemActions: [{label, event}]\` and \`searchable: true\`
2138
2268
  - \`form-section\` has \`submitEvent\` and \`cancelEvent\` (NOT onSubmit/onCancel!)
2139
2269
  - \`entity-detail\` has \`actions\` (NOT headerActions!)
2140
2270
  - \`confirmation\` emits action events
2271
+ - \`stats\` has \`metrics: [{label, value, icon}]\`
2141
2272
  - **NEVER use**: \`onSubmit\`, \`onCancel\`, \`headerActions\`, \`loading\` (use \`isLoading\`)
2142
2273
  - NO separate "form-actions" pattern - it doesn't exist!
2143
2274
  `;
@@ -2148,15 +2279,18 @@ function generateKflowOrbitalsSkill(compact = false) {
2148
2279
  const frontmatter = {
2149
2280
  name: "kflow-orbitals",
2150
2281
  description: "Generate KFlow schemas using the Orbitals composition model. Decomposes applications into atomic Orbital Units (Entity x Traits x Patterns) with structural caching for efficiency.",
2151
- allowedTools: ["Read", "Write", "Edit"],
2152
- version: "3.1.0"
2153
- // Bumped version for compact option
2282
+ allowedTools: ["Read", "Write", "Edit", "generate_orbital", "design_transition", "finish_task", "query_schema_structure", "extract_chunk", "apply_chunk"],
2283
+ version: "4.1.0"
2284
+ // v4.1: design refinement workflow with design_transition
2154
2285
  };
2155
2286
  const content = generateLeanOrbitalSkill({
2156
2287
  includeExample: true,
2157
2288
  includeToolWorkflow: true,
2158
- includeStdStateMachines: !compact
2159
- // Full std/* examples (21K chars)
2289
+ includeStdStateMachines: false,
2290
+ includeSchemaUpdates: false,
2291
+ includeCustomTraits: false,
2292
+ errorLevel: "top6",
2293
+ includeDesignGuide: true
2160
2294
  });
2161
2295
  return {
2162
2296
  name: "kflow-orbitals",
@@ -2201,10 +2335,6 @@ ${getArchitectureSection()}
2201
2335
 
2202
2336
  ---
2203
2337
 
2204
- ${getMinimalTypeReference()}
2205
-
2206
- ---
2207
-
2208
2338
  ${getSExprQuickRef()}
2209
2339
 
2210
2340
  ---
@@ -2225,7 +2355,11 @@ ${getOverGenerationSection()}` : ""}
2225
2355
 
2226
2356
  ---
2227
2357
 
2228
- ${getCommonErrorsSection()}
2358
+ ${getCommonErrorsSection("full")}
2359
+
2360
+ ---
2361
+
2362
+ ${getCustomTraitSection()}
2229
2363
 
2230
2364
  ${includeSchemaUpdates ? `---
2231
2365
 
@@ -2476,9 +2610,356 @@ Output the complete updated domain language text.
2476
2610
  content
2477
2611
  };
2478
2612
  }
2613
+ function getMinimalTypeReference() {
2614
+ return `
2615
+ ## Orbital Schema Structure
2479
2616
 
2480
- // src/orbitals-skills-generators/lean/lean-orbital-generator.ts
2481
- var LEAN_CORE_INSTRUCTIONS = `
2617
+ \`\`\`typescript
2618
+ interface OrbitalDefinition {
2619
+ name: string; // Entity name (PascalCase)
2620
+ entity: Entity; // Data model
2621
+ traits: TraitRef[]; // State machines (names or definitions)
2622
+ pages: Page[]; // Routes and views
2623
+ emits?: string[]; // Events this orbital emits
2624
+ listens?: EventListener[]; // Events this orbital listens to
2625
+ }
2626
+ \`\`\`
2627
+
2628
+ ### Entity Fields
2629
+
2630
+ \`\`\`typescript
2631
+ { name: "title", type: "string", required: true }
2632
+ { name: "count", type: "number", default: 0 }
2633
+ { name: "status", type: "enum", values: ["pending", "active", "done"] }
2634
+ { name: "dueDate", type: "date" }
2635
+ \`\`\`
2636
+
2637
+ ### Trait State Machine
2638
+
2639
+ \`\`\`typescript
2640
+ {
2641
+ states: [{ name: "Idle", isInitial: true }, { name: "Active" }],
2642
+ events: ["INIT", "ACTIVATE", "COMPLETE"],
2643
+ transitions: [
2644
+ { from: "Idle", to: "Active", event: "ACTIVATE",
2645
+ guards: [["condition"]],
2646
+ effects: [["action"]] }
2647
+ ]
2648
+ }
2649
+ \`\`\`
2650
+ `.trim();
2651
+ }
2652
+ function getPatternTypesCompact() {
2653
+ const patterns = getAllPatternTypes();
2654
+ return `
2655
+ ## Available Pattern Types
2656
+
2657
+ ${patterns.map((p) => `- \`${p}\``).join("\n")}
2658
+
2659
+ ${getPatternPropsCompact()}
2660
+ `.trim();
2661
+ }
2662
+ function getSExprQuickRef2() {
2663
+ const operators = Object.keys(OPERATORS).slice(0, 15);
2664
+ return `
2665
+ ## S-Expression Quick Reference
2666
+
2667
+ ### Guard Expressions (Conditions)
2668
+
2669
+ \`\`\`typescript
2670
+ ["=", "@entity.status", "active"] // Equality
2671
+ [">", "@entity.count", 0] // Greater than
2672
+ ["and", ["cond1"], ["cond2"]] // Logical AND
2673
+ ["or", ["cond1"], ["cond2"]] // Logical OR
2674
+ ["not", ["condition"]] // Logical NOT
2675
+ \`\`\`
2676
+
2677
+ ### Effect Expressions (Actions)
2678
+
2679
+ \`\`\`typescript
2680
+ ["set", "@entity.field", value] // Update field
2681
+ ["emit", "EVENT_NAME", payload] // Emit event
2682
+ ["navigate", "/path"] // Navigate to route
2683
+ ["render-ui", "main", { type, props }] // Render pattern
2684
+ ["persist", "create", "Entity", data] // Database operation
2685
+ \`\`\`
2686
+
2687
+ ### Available Operators
2688
+
2689
+ ${operators.map((op) => `- \`${op}\``).join("\n")}
2690
+ `.trim();
2691
+ }
2692
+ function getRenderUIQuickRef2() {
2693
+ const slots = UI_SLOTS;
2694
+ return `
2695
+ ## Render-UI Effect Reference
2696
+
2697
+ ### Syntax
2698
+
2699
+ \`\`\`typescript
2700
+ ["render-ui", slot, patternConfig | null]
2701
+ \`\`\`
2702
+
2703
+ ### UI Slots
2704
+
2705
+ ${slots.map((slot) => `- \`${slot}\``).join("\n")}
2706
+
2707
+ ### Example
2708
+
2709
+ \`\`\`typescript
2710
+ ["render-ui", "main", {
2711
+ type: "entity-table",
2712
+ entity: "Task",
2713
+ columns: ["title", "status"],
2714
+ itemActions: [{ label: "Edit", event: "EDIT" }]
2715
+ }]
2716
+ \`\`\`
2717
+
2718
+ Clear slot: \`["render-ui", "modal", null]\`
2719
+ `.trim();
2720
+ }
2721
+ function getFieldTypesCompact() {
2722
+ return `
2723
+ ## Field Types
2724
+
2725
+ | Type | Example | Notes |
2726
+ |------|---------|-------|
2727
+ | \`string\` | \`{ name: "title", type: "string" }\` | Text |
2728
+ | \`number\` | \`{ name: "count", type: "number" }\` | Integer or float |
2729
+ | \`boolean\` | \`{ name: "active", type: "boolean" }\` | true/false |
2730
+ | \`date\` | \`{ name: "birthday", type: "date" }\` | Date only |
2731
+ | \`timestamp\` | \`{ name: "createdAt", type: "timestamp" }\` | Date + time |
2732
+ | \`enum\` | \`{ name: "status", type: "enum", values: ["a", "b"] }\` | Fixed options |
2733
+ | \`array\` | \`{ name: "tags", type: "array", items: "string" }\` | List |
2734
+ | \`relation\` | \`{ name: "user", type: "relation", relation: { entity: "User", cardinality: "one" } }\` | Foreign key |
2735
+
2736
+ ### Field Properties
2737
+
2738
+ - \`required: true\` - Must have value
2739
+ - \`default: value\` - Default value
2740
+ - \`unique: true\` - Must be unique
2741
+ `.trim();
2742
+ }
2743
+
2744
+ // src/generators/kflow-design.ts
2745
+ function getTransitionContextGuide() {
2746
+ return `## Transition Context
2747
+
2748
+ You receive a single transition to design. Use these inputs to make UI decisions:
2749
+
2750
+ ### Input Fields
2751
+ | Field | What It Tells You |
2752
+ |-------|-------------------|
2753
+ | \`from\` | Current state (e.g., "Browsing", "Creating") |
2754
+ | \`to\` | Target state (e.g., "Browsing", "Viewing") |
2755
+ | \`event\` | What the user did (e.g., "INIT", "CREATE", "VIEW") |
2756
+ | \`currentSlot\` | Which slot to render into (\`main\`, \`modal\`, \`drawer\`) |
2757
+ | \`entity\` | Entity name + fields (drives column/field selection) |
2758
+ | \`designHints\` | Style + UX hints from decomposition |
2759
+ | \`domainContext\` | Category + vocabulary (drives pattern choice) |
2760
+ | \`existingEffects\` | Current render-ui effects (if enhancing) |
2761
+
2762
+ ### Decision Flow
2763
+
2764
+ \`\`\`
2765
+ 1. What EVENT is this?
2766
+ \u251C\u2500 INIT \u2192 Compose full page layout (header + content + data)
2767
+ \u251C\u2500 CREATE/EDIT \u2192 Form in modal or drawer
2768
+ \u251C\u2500 VIEW \u2192 Detail in drawer or inline
2769
+ \u251C\u2500 DELETE \u2192 Confirmation in overlay
2770
+ \u2514\u2500 SAVE/CANCEL \u2192 Clear slot (return null)
2771
+
2772
+ 2. What SLOT?
2773
+ \u251C\u2500 main \u2192 Compose multiple patterns (stack them)
2774
+ \u251C\u2500 modal \u2192 Single form or confirmation
2775
+ \u251C\u2500 drawer \u2192 Detail view or quick edit form
2776
+ \u2514\u2500 overlay \u2192 Confirmation dialog
2777
+
2778
+ 3. What DOMAIN?
2779
+ \u251C\u2500 business \u2192 entity-table + stats + filter-group
2780
+ \u251C\u2500 dashboard \u2192 dashboard-grid + chart + stats
2781
+ \u251C\u2500 e-commerce \u2192 entity-cards + stats (revenue)
2782
+ \u251C\u2500 content \u2192 entity-cards + tabs + media
2783
+ \u2514\u2500 workflow \u2192 timeline + progress-bar
2784
+
2785
+ 4. What ENTITY FIELDS suggest?
2786
+ \u251C\u2500 enum fields \u2192 filter-group, badge columns
2787
+ \u251C\u2500 date fields \u2192 timeline, date columns
2788
+ \u251C\u2500 number fields \u2192 stats, chart, meter
2789
+ \u251C\u2500 relation fields \u2192 tabs for related collections
2790
+ \u2514\u2500 image/url fields \u2192 entity-cards (visual)
2791
+ \`\`\``;
2792
+ }
2793
+ function getLayoutCompositionGuide() {
2794
+ return `## Layout Composition
2795
+
2796
+ Use layout patterns to create structured, visually rich views.
2797
+
2798
+ ### Stack (VStack / HStack)
2799
+ \`{ "type": "stack", "direction": "vertical"|"horizontal", "gap": "sm"|"md"|"lg", "children": [...] }\`
2800
+
2801
+ ### Box (Styled Container)
2802
+ \`{ "type": "box", "padding": "md", "bg": "card", "border": true, "rounded": "md", "children": [...] }\`
2803
+
2804
+ ### Grid (Multi-Column)
2805
+ \`{ "type": "grid", "cols": 3, "gap": "md", "children": [...] }\`
2806
+
2807
+ ### Composition Patterns
2808
+
2809
+ **Page Layout** \u2014 VStack wrapping all content:
2810
+ \`\`\`json
2811
+ ["render-ui", "main", {
2812
+ "type": "stack", "direction": "vertical", "gap": "lg",
2813
+ "children": [
2814
+ { "type": "page-header", "title": "...", "actions": [...] },
2815
+ { "type": "stack", "direction": "horizontal", "gap": "md", "wrap": true,
2816
+ "children": [
2817
+ { "type": "box", "padding": "md", "bg": "card", "border": true, "rounded": "md",
2818
+ "children": [{ "type": "stats", "metrics": [...] }] },
2819
+ { "type": "box", "padding": "md", "bg": "card", "border": true, "rounded": "md",
2820
+ "children": [{ "type": "stats", "metrics": [...] }] }
2821
+ ]
2822
+ },
2823
+ { "type": "entity-table", "entity": "...", "columns": [...], "searchable": true }
2824
+ ]
2825
+ }]
2826
+ \`\`\`
2827
+
2828
+ **Dashboard Layout** \u2014 Grid of cards:
2829
+ \`\`\`json
2830
+ ["render-ui", "main", {
2831
+ "type": "stack", "direction": "vertical", "gap": "lg",
2832
+ "children": [
2833
+ { "type": "page-header", "title": "Dashboard" },
2834
+ { "type": "grid", "cols": { "sm": 1, "md": 2, "lg": 3 }, "gap": "md",
2835
+ "children": [
2836
+ { "type": "box", "padding": "lg", "bg": "card", "border": true, "rounded": "md",
2837
+ "children": [{ "type": "stats", "metrics": [...] }] },
2838
+ { "type": "box", "padding": "lg", "bg": "card", "border": true, "rounded": "md",
2839
+ "children": [{ "type": "chart", "chartType": "line", "data": [...] }] },
2840
+ { "type": "box", "padding": "lg", "bg": "card", "border": true, "rounded": "md",
2841
+ "children": [{ "type": "entity-cards", "entity": "...", "columns": 1 }] }
2842
+ ]
2843
+ }
2844
+ ]
2845
+ }]
2846
+ \`\`\`
2847
+
2848
+ **Detail Drawer** \u2014 Stacked sections:
2849
+ \`\`\`json
2850
+ ["render-ui", "drawer", {
2851
+ "type": "stack", "direction": "vertical", "gap": "md",
2852
+ "children": [
2853
+ { "type": "entity-detail", "entity": "...", "actions": [{ "label": "Edit", "event": "EDIT" }] },
2854
+ { "type": "tabs", "tabs": [
2855
+ { "label": "Related Items", "content": { "type": "entity-table", "entity": "..." } },
2856
+ { "label": "Activity", "content": { "type": "timeline", "items": [...] } }
2857
+ ]}
2858
+ ]
2859
+ }]
2860
+ \`\`\`
2861
+
2862
+ ### When to Use Layout vs Flat
2863
+ - **Flat** (multiple render-ui calls): Simple pages, 2-3 patterns stacked vertically
2864
+ - **Nested** (single render-ui with layout): Complex pages, side-by-side elements, cards with backgrounds, dashboard grids`;
2865
+ }
2866
+ function getOutputFormatSection() {
2867
+ return `## Output Format
2868
+
2869
+ Return ONLY a JSON array of render-ui effect tuples. No explanation, no markdown.
2870
+
2871
+ ### Simple (multiple flat effects):
2872
+ \`\`\`json
2873
+ [
2874
+ ["render-ui", "main", { "type": "page-header", "title": "...", "actions": [...] }],
2875
+ ["render-ui", "main", { "type": "stats", "entity": "...", "metrics": [...] }],
2876
+ ["render-ui", "main", { "type": "entity-table", "entity": "...", "columns": [...] }]
2877
+ ]
2878
+ \`\`\`
2879
+
2880
+ ### Composed (single effect with layout nesting):
2881
+ \`\`\`json
2882
+ [
2883
+ ["render-ui", "main", { "type": "stack", "direction": "vertical", "gap": "lg", "children": [...] }]
2884
+ ]
2885
+ \`\`\`
2886
+
2887
+ ### Clear slot:
2888
+ \`\`\`json
2889
+ [
2890
+ ["render-ui", "modal", null]
2891
+ ]
2892
+ \`\`\`
2893
+
2894
+ ### Rules
2895
+ 1. Return valid JSON array \u2014 nothing else
2896
+ 2. Every effect must be \`["render-ui", slot, config]\`
2897
+ 3. Use entity fields from the input for columns, form fields, stats
2898
+ 4. Match domain vocabulary for labels (e.g., "Place Order" not "Create")
2899
+ 5. Include \`itemActions\` on tables/cards with appropriate events
2900
+ 6. Use \`searchable: true\` on tables for business domains
2901
+ 7. For INIT transitions, ALWAYS compose multiple patterns (never just a table)
2902
+ 8. For CREATE/EDIT, always include \`submitEvent\` and \`cancelEvent\` on form-section`;
2903
+ }
2904
+ function generateKflowDesignSkill() {
2905
+ const frontmatter = {
2906
+ name: "kflow-design",
2907
+ description: "Design rich render-ui effects for orbital schema transitions. Focused on pattern selection, layout composition, and domain-aware UI authoring.",
2908
+ allowedTools: ["Read", "Write", "Edit"],
2909
+ version: "1.0.0"
2910
+ };
2911
+ const content = `# Render-UI Design Skill
2912
+
2913
+ > Design rich, polished render-ui effects for orbital schema transitions.
2914
+
2915
+ You are a UI design specialist for KFlow orbital schemas. Your job is to take a
2916
+ transition context (state, event, entity, domain) and produce the best possible
2917
+ render-ui effects using the full pattern catalog.
2918
+
2919
+ **Your goal**: Every transition should produce UI that is visually rich, functionally
2920
+ complete, and domain-appropriate. Never default to just "entity-table" \u2014 compose
2921
+ layouts with headers, stats, filters, and appropriate patterns.
2922
+
2923
+ ---
2924
+
2925
+ ${getTransitionContextGuide()}
2926
+
2927
+ ---
2928
+
2929
+ ${getRenderUIDesignGuide()}
2930
+
2931
+ ---
2932
+
2933
+ ${getLayoutCompositionGuide()}
2934
+
2935
+ ---
2936
+
2937
+ ${getSExprQuickRef2()}
2938
+
2939
+ ---
2940
+
2941
+ ${getCommonErrorsSection("top6")}
2942
+
2943
+ ---
2944
+
2945
+ ${getOutputFormatSection()}
2946
+ `;
2947
+ return {
2948
+ name: "kflow-design",
2949
+ frontmatter,
2950
+ content
2951
+ };
2952
+ }
2953
+ function getDesignSkillStats() {
2954
+ const skill = generateKflowDesignSkill();
2955
+ return {
2956
+ lines: skill.content.split("\n").length,
2957
+ chars: skill.content.length
2958
+ };
2959
+ }
2960
+
2961
+ // src/orbitals-skills-generators/lean/lean-orbital-generator.ts
2962
+ var LEAN_CORE_INSTRUCTIONS = `
2482
2963
  ## Core Instructions
2483
2964
 
2484
2965
  Generate orbital schemas using **Domain Language** - a natural, readable format.
@@ -3072,139 +3553,10 @@ function generateAllBuilderSkills() {
3072
3553
  },
3073
3554
  content: generateLeanFixingSkill2()
3074
3555
  },
3075
- generateDomainLanguageSkill()
3556
+ generateDomainLanguageSkill(),
3557
+ generateKflowDesignSkill()
3076
3558
  ];
3077
3559
  }
3078
- function getMinimalTypeReference2() {
3079
- return `
3080
- ## Orbital Schema Structure
3081
-
3082
- \`\`\`typescript
3083
- interface OrbitalDefinition {
3084
- name: string; // Entity name (PascalCase)
3085
- entity: Entity; // Data model
3086
- traits: TraitRef[]; // State machines (names or definitions)
3087
- pages: Page[]; // Routes and views
3088
- emits?: string[]; // Events this orbital emits
3089
- listens?: EventListener[]; // Events this orbital listens to
3090
- }
3091
- \`\`\`
3092
-
3093
- ### Entity Fields
3094
-
3095
- \`\`\`typescript
3096
- { name: "title", type: "string", required: true }
3097
- { name: "count", type: "number", default: 0 }
3098
- { name: "status", type: "enum", values: ["pending", "active", "done"] }
3099
- { name: "dueDate", type: "date" }
3100
- \`\`\`
3101
-
3102
- ### Trait State Machine
3103
-
3104
- \`\`\`typescript
3105
- {
3106
- states: [{ name: "Idle", isInitial: true }, { name: "Active" }],
3107
- events: ["INIT", "ACTIVATE", "COMPLETE"],
3108
- transitions: [
3109
- { from: "Idle", to: "Active", event: "ACTIVATE",
3110
- guards: [["condition"]],
3111
- effects: [["action"]] }
3112
- ]
3113
- }
3114
- \`\`\`
3115
- `.trim();
3116
- }
3117
- function getPatternTypesCompact() {
3118
- const patterns = getAllPatternTypes();
3119
- return `
3120
- ## Available Pattern Types
3121
-
3122
- ${patterns.map((p) => `- \`${p}\``).join("\n")}
3123
-
3124
- ${getPatternPropsCompact()}
3125
- `.trim();
3126
- }
3127
- function getSExprQuickRef2() {
3128
- const operators = Object.keys(OPERATORS).slice(0, 15);
3129
- return `
3130
- ## S-Expression Quick Reference
3131
-
3132
- ### Guard Expressions (Conditions)
3133
-
3134
- \`\`\`typescript
3135
- ["=", "@entity.status", "active"] // Equality
3136
- [">", "@entity.count", 0] // Greater than
3137
- ["and", ["cond1"], ["cond2"]] // Logical AND
3138
- ["or", ["cond1"], ["cond2"]] // Logical OR
3139
- ["not", ["condition"]] // Logical NOT
3140
- \`\`\`
3141
-
3142
- ### Effect Expressions (Actions)
3143
-
3144
- \`\`\`typescript
3145
- ["set", "@entity.field", value] // Update field
3146
- ["emit", "EVENT_NAME", payload] // Emit event
3147
- ["navigate", "/path"] // Navigate to route
3148
- ["render-ui", "main", { type, props }] // Render pattern
3149
- ["persist", "create", "Entity", data] // Database operation
3150
- \`\`\`
3151
-
3152
- ### Available Operators
3153
-
3154
- ${operators.map((op) => `- \`${op}\``).join("\n")}
3155
- `.trim();
3156
- }
3157
- function getRenderUIQuickRef2() {
3158
- const slots = UI_SLOTS;
3159
- return `
3160
- ## Render-UI Effect Reference
3161
-
3162
- ### Syntax
3163
-
3164
- \`\`\`typescript
3165
- ["render-ui", slot, patternConfig | null]
3166
- \`\`\`
3167
-
3168
- ### UI Slots
3169
-
3170
- ${slots.map((slot) => `- \`${slot}\``).join("\n")}
3171
-
3172
- ### Example
3173
-
3174
- \`\`\`typescript
3175
- ["render-ui", "main", {
3176
- type: "entity-table",
3177
- entity: "Task",
3178
- columns: ["title", "status"],
3179
- itemActions: [{ label: "Edit", event: "EDIT" }]
3180
- }]
3181
- \`\`\`
3182
-
3183
- Clear slot: \`["render-ui", "modal", null]\`
3184
- `.trim();
3185
- }
3186
- function getFieldTypesCompact() {
3187
- return `
3188
- ## Field Types
3189
-
3190
- | Type | Example | Notes |
3191
- |------|---------|-------|
3192
- | \`string\` | \`{ name: "title", type: "string" }\` | Text |
3193
- | \`number\` | \`{ name: "count", type: "number" }\` | Integer or float |
3194
- | \`boolean\` | \`{ name: "active", type: "boolean" }\` | true/false |
3195
- | \`date\` | \`{ name: "birthday", type: "date" }\` | Date only |
3196
- | \`timestamp\` | \`{ name: "createdAt", type: "timestamp" }\` | Date + time |
3197
- | \`enum\` | \`{ name: "status", type: "enum", values: ["a", "b"] }\` | Fixed options |
3198
- | \`array\` | \`{ name: "tags", type: "array", items: "string" }\` | List |
3199
- | \`relation\` | \`{ name: "user", type: "relation", relation: { entity: "User", cardinality: "one" } }\` | Foreign key |
3200
-
3201
- ### Field Properties
3202
-
3203
- - \`required: true\` - Must have value
3204
- - \`default: value\` - Default value
3205
- - \`unique: true\` - Must be unique
3206
- `.trim();
3207
- }
3208
3560
 
3209
3561
  // src/prompts/generation-prompts.ts
3210
3562
  function getOrbitalDecompositionPrompt() {
@@ -3244,7 +3596,7 @@ ${getArchitectureSection()}
3244
3596
 
3245
3597
  ---
3246
3598
 
3247
- ${getMinimalTypeReference2()}
3599
+ ${getMinimalTypeReference()}
3248
3600
 
3249
3601
  ---
3250
3602
 
@@ -3378,6 +3730,6 @@ Use with: \`uses: [{ from: "std/behaviors/crud", as: "CRUD" }]\`
3378
3730
  `;
3379
3731
  }
3380
3732
 
3381
- export { formatFrontmatter, generateAllBuilderSkills, generateDomainLanguageSkill, generateKflowOrbitalFixingSkill, generateKflowOrbitalsSkill, generateLeanFixingSkill2 as generateLeanFixingSkill, generateLeanFixingSkill as generateLeanFixingSkillFull, generateLeanOrbitalSkill2 as generateLeanOrbitalSkill, generateLeanOrbitalSkill as generateLeanOrbitalSkillFull, getArchitectureSection, getAssetRefSection, getCommonErrorsSection, getCommonFixPatternsSection, getCompletionRulesSection, getContextUsageCompact, getContextUsageSection, getCustomTraitCompact, getCustomTraitSection, getDecompositionChecklist, getDecompositionSection, getDesignErrorsCompact, getDesignErrorsSection, getEfficiencySection, getFieldTypesCompact, getFixingWorkflowSection, getFlowPatternSection, getFullOrbitalPrompt, getGameAsOrbitalsSection, getGameEntityTemplatesSection, getGamePatternsSection, getGameTraitsSection, getGameTypesSection, getIconLibraryCompact, getIconLibrarySection, getKeyBehaviorsReference2 as getKeyBehaviorsReference, getMinimalTypeReference2 as getMinimalTypeReference, getMultiFileSection, getOrbitalConnectivitySection, getOrbitalDecompositionPrompt, getOverGenerationSection, getPatternTypesCompact, getPortableOrbitalOutputSection, getRenderUIQuickRef2 as getRenderUIQuickRef, getRequirementsDecomposePrompt, getRequirementsTraitPrompt, getSExprQuickRef2 as getSExprQuickRef, getSchemaUpdateCompact, getSchemaUpdateSection, getUsesImportCompact, getUsesImportSection, getValidationHintsSection, writeAllSkills, writeSkill };
3733
+ export { formatFrontmatter, generateAllBuilderSkills, generateDomainLanguageSkill, generateKflowDesignSkill, generateKflowOrbitalFixingSkill, generateKflowOrbitalsSkill, generateLeanFixingSkill2 as generateLeanFixingSkill, generateLeanFixingSkill as generateLeanFixingSkillFull, generateLeanOrbitalSkill2 as generateLeanOrbitalSkill, generateLeanOrbitalSkill as generateLeanOrbitalSkillFull, getArchitectureSection, getAssetRefSection, getCommonErrorsSection, getCommonFixPatternsSection, getCompletionRulesSection, getConnectivityCompact, getContextUsageCompact, getContextUsageSection, getCustomTraitCompact, getCustomTraitSection, getDecompositionChecklist, getDecompositionCompact, getDecompositionSection, getDesignErrorsCompact, getDesignErrorsSection, getDesignSkillStats, getEfficiencySection, getFieldTypesCompact, getFixingWorkflowSection, getFlowPatternSection, getFullOrbitalPrompt, getGameAsOrbitalsSection, getGameEntityTemplatesSection, getGamePatternsSection, getGameTraitsSection, getGameTypesSection, getIconLibraryCompact, getIconLibrarySection, getKeyBehaviorsReference2 as getKeyBehaviorsReference, getMinimalTypeReference, getMultiFileSection, getOrbitalConnectivitySection, getOrbitalDecompositionPrompt, getOverGenerationSection, getPatternTypesCompact, getPortableOrbitalOutputSection, getRenderUIDesignGuide, getRenderUIQuickRef2 as getRenderUIQuickRef, getRequirementsDecomposePrompt, getRequirementsTraitPrompt, getSExprQuickRef2 as getSExprQuickRef, getSchemaUpdateCompact, getSchemaUpdateSection, getUsesImportCompact, getUsesImportSection, getValidationHintsSection, writeAllSkills, writeSkill };
3382
3734
  //# sourceMappingURL=index.js.map
3383
3735
  //# sourceMappingURL=index.js.map