@almadar/skills 1.0.13 → 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.d.ts +86 -12
- package/dist/index.js +732 -387
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
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
|
|
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
|
|
|
@@ -280,35 +262,23 @@ function getValidViewTypes() {
|
|
|
280
262
|
const validTypes = ViewTypeSchema.options;
|
|
281
263
|
return validTypes.map((t) => `\`${t}\``).join(", ");
|
|
282
264
|
}
|
|
283
|
-
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() {
|
|
284
271
|
return `## Critical Rules
|
|
285
272
|
|
|
286
|
-
###
|
|
287
|
-
|
|
288
|
-
The \`set\` effect modifies entity state. **@payload is READ-ONLY** - it contains event data.
|
|
289
|
-
|
|
290
|
-
\`\`\`json
|
|
291
|
-
// WRONG - @payload is read-only!
|
|
292
|
-
["set", "@payload.data.createdAt", "@now"]
|
|
293
|
-
["set", "@payload.data.status", "active"]
|
|
294
|
-
|
|
295
|
-
// CORRECT - Use @entity to modify state
|
|
296
|
-
["set", "@entity.createdAt", "@now"]
|
|
297
|
-
["set", "@entity.status", "active"]
|
|
298
|
-
\`\`\`
|
|
299
|
-
|
|
300
|
-
**Rule:** \`set\` target MUST start with \`@entity\`, never \`@payload\`.
|
|
301
|
-
|
|
302
|
-
### INIT Transition Required (CRITICAL)
|
|
273
|
+
### 1. INIT Transition Required (CRITICAL)
|
|
303
274
|
|
|
304
275
|
Every trait MUST have an INIT self-loop transition. The runtime fires \`INIT\` when page loads.
|
|
305
276
|
|
|
306
277
|
\`\`\`json
|
|
307
|
-
// REQUIRED in EVERY trait:
|
|
308
278
|
{
|
|
309
279
|
"from": "Browsing",
|
|
310
280
|
"to": "Browsing",
|
|
311
|
-
"event": "INIT",
|
|
281
|
+
"event": "INIT",
|
|
312
282
|
"effects": [
|
|
313
283
|
["render-ui", "main", { "type": "page-header", ... }],
|
|
314
284
|
["render-ui", "main", { "type": "entity-table", ... }]
|
|
@@ -318,43 +288,40 @@ Every trait MUST have an INIT self-loop transition. The runtime fires \`INIT\` w
|
|
|
318
288
|
|
|
319
289
|
Without INIT: Page loads blank, nothing renders, no UI appears.
|
|
320
290
|
|
|
321
|
-
###
|
|
291
|
+
### 2. NEVER Use @payload in set Effects
|
|
322
292
|
|
|
323
|
-
|
|
293
|
+
The \`set\` effect modifies entity state. **@payload is READ-ONLY**.
|
|
324
294
|
|
|
325
|
-
|
|
295
|
+
\`\`\`json
|
|
296
|
+
// WRONG
|
|
297
|
+
["set", "@payload.data.status", "active"]
|
|
298
|
+
|
|
299
|
+
// CORRECT
|
|
300
|
+
["set", "@entity.status", "active"]
|
|
301
|
+
\`\`\`
|
|
326
302
|
|
|
327
|
-
**
|
|
303
|
+
**Rule:** \`set\` target MUST start with \`@entity\`, never \`@payload\`.
|
|
328
304
|
|
|
329
|
-
### Valid
|
|
305
|
+
### 3. Valid Patterns ONLY
|
|
330
306
|
|
|
331
|
-
|
|
307
|
+
**DO NOT invent custom patterns!** Only these patterns exist:
|
|
332
308
|
|
|
333
|
-
|
|
309
|
+
${getPatternCategories()}
|
|
334
310
|
|
|
335
|
-
|
|
311
|
+
**NEVER use**: \`onboarding-welcome\`, \`category-selector\`, \`assessment-question\`, etc.
|
|
336
312
|
|
|
337
|
-
${
|
|
313
|
+
Valid viewType values: ${getValidViewTypes()}
|
|
338
314
|
|
|
339
|
-
### Page Structure Required
|
|
315
|
+
### 4. Page Structure Required
|
|
340
316
|
|
|
341
317
|
Every page MUST have \`path\` and \`traits\` properties:
|
|
342
318
|
|
|
343
319
|
\`\`\`json
|
|
344
|
-
// WRONG - missing path and traits:
|
|
345
|
-
{
|
|
346
|
-
"pages": [{
|
|
347
|
-
"name": "TasksPage",
|
|
348
|
-
"entity": "Task" // \u274C Missing path and traits!
|
|
349
|
-
}]
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// CORRECT - complete page definition:
|
|
353
320
|
{
|
|
354
321
|
"pages": [{
|
|
355
322
|
"name": "TasksPage",
|
|
356
|
-
"path": "/tasks",
|
|
357
|
-
"traits": [{ "ref": "TaskManagement" }]
|
|
323
|
+
"path": "/tasks",
|
|
324
|
+
"traits": [{ "ref": "TaskManagement" }]
|
|
358
325
|
}]
|
|
359
326
|
}
|
|
360
327
|
\`\`\`
|
|
@@ -362,232 +329,119 @@ Every page MUST have \`path\` and \`traits\` properties:
|
|
|
362
329
|
Without \`path\`: Validation error \`ORB_P_MISSING_PATH\`
|
|
363
330
|
Without \`traits\`: Validation error \`ORB_P_MISSING_TRAITS\`
|
|
364
331
|
|
|
365
|
-
### Valid Field Types ONLY
|
|
332
|
+
### 5. Valid Field Types ONLY
|
|
366
333
|
|
|
367
334
|
Field types MUST be one of: \`string\`, \`number\`, \`boolean\`, \`date\`, \`timestamp\`, \`datetime\`, \`array\`, \`object\`, \`enum\`, \`relation\`
|
|
368
335
|
|
|
369
336
|
\`\`\`json
|
|
370
337
|
// WRONG - using entity name as type:
|
|
371
|
-
{ "name": "author", "type": "User" }
|
|
372
|
-
{ "name": "post", "type": "BlogPost" } // \u274C Invalid!
|
|
338
|
+
{ "name": "author", "type": "User" }
|
|
373
339
|
|
|
374
|
-
// CORRECT - use relation type
|
|
340
|
+
// CORRECT - use relation type:
|
|
375
341
|
{ "name": "author", "type": "relation", "relation": { "entity": "User", "cardinality": "one" } }
|
|
376
|
-
{ "name": "post", "type": "relation", "relation": { "entity": "BlogPost", "cardinality": "one" } }
|
|
377
|
-
|
|
378
|
-
// CORRECT for arrays of primitives:
|
|
379
|
-
{ "name": "tags", "type": "array", "items": { "type": "string" } }
|
|
380
|
-
|
|
381
|
-
// CORRECT for enums:
|
|
382
|
-
{ "name": "status", "type": "enum", "values": ["pending", "active", "done"] }
|
|
383
342
|
\`\`\`
|
|
384
343
|
|
|
385
|
-
###
|
|
344
|
+
### 6. Modal State Machine Pattern
|
|
386
345
|
|
|
387
|
-
|
|
346
|
+
When a transition opens a modal/drawer, the target state MUST have CLOSE and CANCEL transitions:
|
|
388
347
|
|
|
389
348
|
\`\`\`json
|
|
390
|
-
|
|
391
|
-
{
|
|
392
|
-
|
|
393
|
-
"
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
"traits": [{
|
|
399
|
-
"name": "TaskInteraction",
|
|
400
|
-
"listens": [
|
|
401
|
-
{ "event": "USER_UPDATED", "handler": "REFRESH_LIST" } // \u2705 Object format
|
|
402
|
-
]
|
|
403
|
-
}]
|
|
404
|
-
}
|
|
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"]] }
|
|
405
357
|
\`\`\`
|
|
406
358
|
|
|
359
|
+
**CLOSE** = user clicks outside modal/presses Escape. **CANCEL** = form cancel button. Both needed.
|
|
360
|
+
`;
|
|
361
|
+
}
|
|
362
|
+
function getEdgeCaseErrors() {
|
|
363
|
+
return `
|
|
407
364
|
---
|
|
408
365
|
|
|
409
|
-
##
|
|
410
|
-
|
|
411
|
-
### 1. Missing INIT Transition
|
|
412
|
-
\`\`\`
|
|
413
|
-
WRONG: No INIT transition \u2192 Page loads blank
|
|
414
|
-
CORRECT: { "from": "browsing", "to": "browsing", "event": "INIT", "effects": [...render-ui...] }
|
|
415
|
-
\`\`\`
|
|
366
|
+
## Additional Errors (Edge Cases)
|
|
416
367
|
|
|
417
|
-
###
|
|
368
|
+
### 7. Over-Generating Pages
|
|
418
369
|
\`\`\`
|
|
419
370
|
WRONG: TaskListPage, TaskCreatePage, TaskEditPage, TaskViewPage (4 pages!)
|
|
420
371
|
CORRECT: TasksPage with EntityManagement trait (1 page)
|
|
421
372
|
\`\`\`
|
|
422
373
|
|
|
423
|
-
###
|
|
374
|
+
### 8. Duplicate Slot Rendering
|
|
424
375
|
\`\`\`
|
|
425
376
|
WRONG: Two traits both render to "main" on page load
|
|
426
377
|
CORRECT: ONE trait owns each slot
|
|
427
378
|
\`\`\`
|
|
428
379
|
|
|
429
|
-
###
|
|
380
|
+
### 9. Missing onSubmit in form-section
|
|
430
381
|
\`\`\`
|
|
431
382
|
WRONG: { "type": "form-section", "entity": "Task" }
|
|
432
383
|
CORRECT: { "type": "form-section", "entity": "Task", "onSubmit": "SAVE" }
|
|
433
384
|
\`\`\`
|
|
434
385
|
|
|
435
|
-
###
|
|
386
|
+
### 10. Duplicate Transitions (Same from+event)
|
|
436
387
|
\`\`\`
|
|
437
388
|
WRONG: Two transitions with same "from" and "event" without guards
|
|
438
389
|
CORRECT: Use GUARDS to differentiate transitions
|
|
439
390
|
\`\`\`
|
|
440
391
|
|
|
441
|
-
###
|
|
392
|
+
### 11. Using "render" Instead of "render-ui"
|
|
442
393
|
\`\`\`
|
|
443
394
|
WRONG: ["render", "main", {...}]
|
|
444
395
|
CORRECT: ["render-ui", "main", {...}]
|
|
445
396
|
\`\`\`
|
|
446
397
|
|
|
447
|
-
###
|
|
398
|
+
### 12. Generating Sections Array (Legacy)
|
|
448
399
|
\`\`\`
|
|
449
400
|
WRONG: { "pages": [{ "sections": [...] }] }
|
|
450
401
|
CORRECT: { "pages": [{ "traits": [...] }] } - UI comes from render-ui effects
|
|
451
402
|
\`\`\`
|
|
452
403
|
|
|
453
|
-
###
|
|
404
|
+
### 13. Using form-actions Pattern (DOES NOT EXIST!)
|
|
454
405
|
\`\`\`
|
|
455
406
|
WRONG: ["render-ui", "main", { "type": "form-actions", "actions": [...] }]
|
|
456
|
-
CORRECT: Use form-section with onSubmit/onCancel props
|
|
457
|
-
{ "type": "form-section", "entity": "Task", "fields": [...], "onSubmit": "SAVE", "onCancel": "CANCEL" }
|
|
407
|
+
CORRECT: Use form-section with onSubmit/onCancel props
|
|
458
408
|
\`\`\`
|
|
459
|
-
Actions are INSIDE patterns, not separate patterns.
|
|
409
|
+
Actions are INSIDE patterns, not separate patterns.
|
|
460
410
|
|
|
461
|
-
###
|
|
411
|
+
### 14. Forgetting itemActions in entity-table
|
|
462
412
|
\`\`\`
|
|
463
|
-
WRONG: { "type": "entity-table", "entity": "Task" }
|
|
464
|
-
CORRECT: { "type": "entity-table", "entity": "Task", "itemActions": [{"label": "Edit", "event": "EDIT"}
|
|
413
|
+
WRONG: { "type": "entity-table", "entity": "Task" }
|
|
414
|
+
CORRECT: { "type": "entity-table", "entity": "Task", "itemActions": [{"label": "Edit", "event": "EDIT"}] }
|
|
465
415
|
\`\`\`
|
|
466
416
|
|
|
467
|
-
###
|
|
417
|
+
### 15. Duplicate Trait Names Across Orbitals
|
|
468
418
|
\`\`\`
|
|
469
419
|
WRONG: UserOrbital uses "EntityManagement", TaskOrbital uses "EntityManagement"
|
|
470
420
|
CORRECT: UserOrbital uses "UserManagement", TaskOrbital uses "TaskManagement"
|
|
471
421
|
\`\`\`
|
|
472
422
|
Each trait name MUST be unique. Pattern: \`{Entity}{Purpose}\`
|
|
473
423
|
|
|
474
|
-
###
|
|
424
|
+
### 16. Hallucinated itemAction Properties
|
|
475
425
|
\`\`\`
|
|
476
|
-
WRONG:
|
|
477
|
-
CORRECT:
|
|
478
|
-
\`\`\`
|
|
479
|
-
\`set\` effect MUST use \`@entity.field\` binding. \`@payload\` is read-only event data.
|
|
480
|
-
|
|
481
|
-
### 12. Hallucinated itemAction Properties
|
|
482
|
-
\`\`\`
|
|
483
|
-
WRONG: { "label": "View", "event": "VIEW", "condition": "@entity.status === 'active'" }
|
|
484
|
-
CORRECT: { "label": "View", "event": "VIEW", "showWhen": ["=", "@entity.status", "active"] }
|
|
426
|
+
WRONG: { "label": "View", "event": "VIEW", "condition": "..." }
|
|
427
|
+
CORRECT: { "label": "View", "event": "VIEW" }
|
|
485
428
|
\`\`\`
|
|
486
429
|
Valid itemAction props: \`label\`, \`event\`, \`navigatesTo\`, \`placement\`, \`variant\`, \`showWhen\`
|
|
487
|
-
Note: \`showWhen\` is defined but NOT yet implemented - actions always visible.
|
|
488
|
-
|
|
489
|
-
### 14. Missing Page Path
|
|
490
|
-
\`\`\`
|
|
491
|
-
WRONG: { "pages": [{ "name": "TasksPage", "entity": "Task" }] }
|
|
492
|
-
CORRECT: { "pages": [{ "name": "TasksPage", "path": "/tasks", "traits": [...] }] }
|
|
493
|
-
\`\`\`
|
|
494
|
-
|
|
495
|
-
### 15. Using Entity Name as Field Type
|
|
496
|
-
\`\`\`
|
|
497
|
-
WRONG: { "name": "author", "type": "User" }
|
|
498
|
-
CORRECT: { "name": "author", "type": "relation", "relation": { "entity": "User", "cardinality": "one" } }
|
|
499
|
-
\`\`\`
|
|
500
|
-
|
|
501
|
-
### 16. Missing Traits Array on Page
|
|
502
|
-
\`\`\`
|
|
503
|
-
WRONG: { "pages": [{ "name": "TasksPage", "path": "/tasks" }] }
|
|
504
|
-
CORRECT: { "pages": [{ "name": "TasksPage", "path": "/tasks", "traits": [{ "ref": "TaskManagement" }] }] }
|
|
505
|
-
\`\`\`
|
|
506
|
-
|
|
507
|
-
### 13. Modal State Machine Pattern (CRITICAL)
|
|
508
|
-
|
|
509
|
-
When a transition opens a modal (renders to \`modal\` or \`drawer\` slot), the target state MUST have:
|
|
510
|
-
1. A **CLOSE** transition to clear the modal and return to browsing state
|
|
511
|
-
2. A **CANCEL** transition (for forms with cancel buttons)
|
|
512
|
-
3. The CLOSE/CANCEL effects MUST include \`["render-ui", "modal", null]\` to clear the slot
|
|
513
|
-
|
|
514
|
-
\`\`\`json
|
|
515
|
-
// WRONG - Modal opens but no way to close it!
|
|
516
|
-
{
|
|
517
|
-
"from": "browsing", "to": "creating", "event": "CREATE",
|
|
518
|
-
"effects": [["render-ui", "modal", { "type": "form-section", ... }]]
|
|
519
|
-
}
|
|
520
|
-
// No CLOSE or CANCEL transition from "creating" \u2192 Page gets stuck!
|
|
521
|
-
|
|
522
|
-
// CORRECT - Full modal open/close cycle:
|
|
523
|
-
{
|
|
524
|
-
"from": "browsing", "to": "creating", "event": "CREATE",
|
|
525
|
-
"effects": [["render-ui", "modal", { "type": "form-section", "cancelEvent": "CANCEL", ... }]]
|
|
526
|
-
},
|
|
527
|
-
{
|
|
528
|
-
"from": "creating", "to": "browsing", "event": "CANCEL",
|
|
529
|
-
"effects": [["render-ui", "modal", null]]
|
|
530
|
-
},
|
|
531
|
-
{
|
|
532
|
-
"from": "creating", "to": "browsing", "event": "CLOSE",
|
|
533
|
-
"effects": [["render-ui", "modal", null]]
|
|
534
|
-
},
|
|
535
|
-
{
|
|
536
|
-
"from": "creating", "to": "browsing", "event": "SAVE",
|
|
537
|
-
"effects": [
|
|
538
|
-
["persist", "create", "Entity", "@payload.data"],
|
|
539
|
-
["render-ui", "modal", null], // \u2190 IMPORTANT: Clear modal on save too!
|
|
540
|
-
["fetch", "Entity", {}]
|
|
541
|
-
]
|
|
542
|
-
}
|
|
543
|
-
\`\`\`
|
|
544
|
-
|
|
545
|
-
**Why CLOSE is needed:** The UI sends \`CLOSE\` when user clicks outside the modal or presses Escape.
|
|
546
|
-
**Why CANCEL is needed:** Forms emit \`CANCEL\` when user clicks the Cancel button.
|
|
547
|
-
**Both are needed** for complete modal behavior. Without them, the modal cannot be dismissed and reopened.
|
|
548
|
-
|
|
549
|
-
### 14. Wrong Filtering Pattern (Use Query Singleton)
|
|
550
|
-
\`\`\`
|
|
551
|
-
WRONG: Individual filter buttons with manual FILTER events
|
|
552
|
-
{ "type": "button", "label": "Active", "action": "FILTER", "data": { "status": "active" } }
|
|
553
|
-
|
|
554
|
-
CORRECT: Use Query Singleton entity + filter-group pattern:
|
|
555
|
-
\`\`\`
|
|
556
|
-
|
|
557
|
-
**Query Singleton Pattern for Filtering:**
|
|
558
|
-
|
|
559
|
-
1. Define a singleton entity to hold filter state:
|
|
560
|
-
\`\`\`json
|
|
561
|
-
{
|
|
562
|
-
"name": "TaskQuery",
|
|
563
|
-
"entity": {
|
|
564
|
-
"name": "TaskQuery",
|
|
565
|
-
"singleton": true,
|
|
566
|
-
"runtime": true,
|
|
567
|
-
"fields": [
|
|
568
|
-
{ "name": "status", "type": "string" },
|
|
569
|
-
{ "name": "search", "type": "string" }
|
|
570
|
-
]
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
\`\`\`
|
|
574
430
|
|
|
575
|
-
|
|
431
|
+
### 17. Event Listeners Structure
|
|
432
|
+
Event listeners go INSIDE traits, not at orbital level:
|
|
576
433
|
\`\`\`json
|
|
577
|
-
{
|
|
578
|
-
"
|
|
579
|
-
"effects": [["set", "@TaskQuery.status", "@payload.status"]]
|
|
580
|
-
}
|
|
434
|
+
"traits": [{ "name": "TaskInteraction",
|
|
435
|
+
"listens": [{ "event": "USER_UPDATED", "handler": "REFRESH_LIST" }] }]
|
|
581
436
|
\`\`\`
|
|
582
437
|
|
|
583
|
-
|
|
438
|
+
### 18. Wrong Filtering Pattern (Use Query Singleton)
|
|
439
|
+
Use a singleton entity for filter state + \`query\` prop on entity-table:
|
|
584
440
|
\`\`\`json
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
"entity": "Task",
|
|
588
|
-
"query": "@TaskQuery"
|
|
589
|
-
}]
|
|
441
|
+
{ "name": "TaskQuery", "entity": { "name": "TaskQuery", "singleton": true, "runtime": true,
|
|
442
|
+
"fields": [{ "name": "status", "type": "string" }, { "name": "search", "type": "string" }] } }
|
|
590
443
|
\`\`\`
|
|
444
|
+
Reference: \`["render-ui", "main", { "type": "entity-table", "entity": "Task", "query": "@TaskQuery" }]\`
|
|
591
445
|
`;
|
|
592
446
|
}
|
|
593
447
|
function getValidationHintsSection() {
|
|
@@ -706,6 +560,78 @@ function getDecompositionChecklist() {
|
|
|
706
560
|
- [ ] emits/listens defined for cross-orbital events
|
|
707
561
|
`;
|
|
708
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
|
+
}
|
|
709
635
|
function getFlowPatternSection() {
|
|
710
636
|
return `## Flow Pattern Selection
|
|
711
637
|
|
|
@@ -811,6 +737,151 @@ Orbitals communicate via events:
|
|
|
811
737
|
- Add relatedLinks for navigation between related records
|
|
812
738
|
`;
|
|
813
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
|
+
}
|
|
814
885
|
|
|
815
886
|
// src/prompts/skill-sections/custom-traits.ts
|
|
816
887
|
function getCustomTraitSection() {
|
|
@@ -1896,13 +1967,16 @@ function generateLeanOrbitalSkill(options = {}) {
|
|
|
1896
1967
|
const {
|
|
1897
1968
|
includeExample = true,
|
|
1898
1969
|
includeToolWorkflow = true,
|
|
1899
|
-
includeStdLibrary =
|
|
1970
|
+
includeStdLibrary = false,
|
|
1900
1971
|
stdLibraryFull = false,
|
|
1901
|
-
includeStdStateMachines =
|
|
1902
|
-
includeSchemaUpdates =
|
|
1972
|
+
includeStdStateMachines = false,
|
|
1973
|
+
includeSchemaUpdates = false,
|
|
1974
|
+
includeCustomTraits = false,
|
|
1975
|
+
errorLevel = "top6",
|
|
1976
|
+
includeDesignGuide = true
|
|
1903
1977
|
} = options;
|
|
1904
1978
|
let stdSection = "";
|
|
1905
|
-
if (includeStdLibrary) {
|
|
1979
|
+
if (includeStdLibrary || includeStdStateMachines) {
|
|
1906
1980
|
if (includeStdStateMachines) {
|
|
1907
1981
|
stdSection = `---
|
|
1908
1982
|
|
|
@@ -1924,6 +1998,8 @@ ${getStdMinimalReference()}
|
|
|
1924
1998
|
`;
|
|
1925
1999
|
}
|
|
1926
2000
|
}
|
|
2001
|
+
const decompositionSection = includeStdStateMachines || includeCustomTraits ? getDecompositionSection() : getDecompositionCompact();
|
|
2002
|
+
const connectivitySection = includeStdStateMachines || includeCustomTraits ? getOrbitalConnectivitySection() : getConnectivityCompact();
|
|
1927
2003
|
return `# Orbital Generation Skill
|
|
1928
2004
|
|
|
1929
2005
|
> Generate Orbital applications using Orbital Units: Entity \xD7 Traits \xD7 Patterns
|
|
@@ -1932,15 +2008,11 @@ ${getArchitectureSection()}
|
|
|
1932
2008
|
|
|
1933
2009
|
---
|
|
1934
2010
|
|
|
1935
|
-
${getMinimalTypeReference()}
|
|
1936
|
-
|
|
1937
|
-
---
|
|
1938
|
-
|
|
1939
2011
|
${getSExprQuickRef()}
|
|
1940
2012
|
|
|
1941
2013
|
---
|
|
1942
2014
|
|
|
1943
|
-
${
|
|
2015
|
+
${includeDesignGuide ? getRenderUIDesignGuide() : ""}
|
|
1944
2016
|
|
|
1945
2017
|
${stdSection}
|
|
1946
2018
|
---
|
|
@@ -1949,7 +2021,7 @@ ${getFlowPatternSection()}
|
|
|
1949
2021
|
|
|
1950
2022
|
---
|
|
1951
2023
|
|
|
1952
|
-
${
|
|
2024
|
+
${decompositionSection}
|
|
1953
2025
|
|
|
1954
2026
|
---
|
|
1955
2027
|
|
|
@@ -1957,7 +2029,7 @@ ${getPortableOrbitalOutputSection()}
|
|
|
1957
2029
|
|
|
1958
2030
|
---
|
|
1959
2031
|
|
|
1960
|
-
${
|
|
2032
|
+
${connectivitySection}
|
|
1961
2033
|
|
|
1962
2034
|
---
|
|
1963
2035
|
|
|
@@ -1965,12 +2037,12 @@ ${getContextUsageCompact()}
|
|
|
1965
2037
|
|
|
1966
2038
|
---
|
|
1967
2039
|
|
|
1968
|
-
${getCommonErrorsSection()}
|
|
2040
|
+
${getCommonErrorsSection(errorLevel)}
|
|
1969
2041
|
|
|
1970
|
-
|
|
2042
|
+
${includeCustomTraits ? `---
|
|
1971
2043
|
|
|
1972
2044
|
${getCustomTraitSection()}
|
|
1973
|
-
|
|
2045
|
+
` : ""}
|
|
1974
2046
|
${includeToolWorkflow ? getToolWorkflowSection() : ""}
|
|
1975
2047
|
|
|
1976
2048
|
${includeSchemaUpdates ? `---
|
|
@@ -2031,17 +2103,67 @@ function getToolWorkflowSection() {
|
|
|
2031
2103
|
|
|
2032
2104
|
## Tool Workflow
|
|
2033
2105
|
|
|
2034
|
-
1
|
|
2035
|
-
|
|
2036
|
-
|
|
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:
|
|
2037
2111
|
|
|
2038
2112
|
\`\`\`
|
|
2039
2113
|
generate_orbital({ orbital: {...}, orbitalIndex: 0, totalOrbitals: N })
|
|
2040
2114
|
generate_orbital({ orbital: {...}, orbitalIndex: 1, totalOrbitals: N })
|
|
2041
2115
|
...
|
|
2042
|
-
construct_combined_schema({ name: "App", description: "..." })
|
|
2043
|
-
# STOP HERE - job is done
|
|
2044
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).
|
|
2045
2167
|
`;
|
|
2046
2168
|
}
|
|
2047
2169
|
function getMinimalExample() {
|
|
@@ -2079,8 +2201,9 @@ function getMinimalExample() {
|
|
|
2079
2201
|
{
|
|
2080
2202
|
"from": "Browsing", "to": "Browsing", "event": "INIT",
|
|
2081
2203
|
"effects": [
|
|
2082
|
-
["render-ui", "main", { "type": "page-header", "title": "Tasks", "actions": [{ "label": "New Task", "event": "CREATE", "variant": "primary" }] }],
|
|
2083
|
-
["render-ui", "main", { "type": "
|
|
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" }] }]
|
|
2084
2207
|
]
|
|
2085
2208
|
},
|
|
2086
2209
|
{
|
|
@@ -2137,14 +2260,15 @@ function getMinimalExample() {
|
|
|
2137
2260
|
|
|
2138
2261
|
**Key points**:
|
|
2139
2262
|
- ONE page (TasksPage) not four (list/create/edit/view)
|
|
2140
|
-
- INIT transition
|
|
2263
|
+
- INIT transition composes **multiple patterns**: page-header + stats + entity-table
|
|
2141
2264
|
- States are OBJECTS with \`isInitial\` flag
|
|
2142
2265
|
- **Actions are INSIDE patterns (use unified props)**:
|
|
2143
2266
|
- \`page-header\` has \`actions: [{label, event, variant}]\`
|
|
2144
|
-
- \`entity-table\` has \`itemActions: [{label, event}]\`
|
|
2267
|
+
- \`entity-table\` has \`itemActions: [{label, event}]\` and \`searchable: true\`
|
|
2145
2268
|
- \`form-section\` has \`submitEvent\` and \`cancelEvent\` (NOT onSubmit/onCancel!)
|
|
2146
2269
|
- \`entity-detail\` has \`actions\` (NOT headerActions!)
|
|
2147
2270
|
- \`confirmation\` emits action events
|
|
2271
|
+
- \`stats\` has \`metrics: [{label, value, icon}]\`
|
|
2148
2272
|
- **NEVER use**: \`onSubmit\`, \`onCancel\`, \`headerActions\`, \`loading\` (use \`isLoading\`)
|
|
2149
2273
|
- NO separate "form-actions" pattern - it doesn't exist!
|
|
2150
2274
|
`;
|
|
@@ -2155,15 +2279,18 @@ function generateKflowOrbitalsSkill(compact = false) {
|
|
|
2155
2279
|
const frontmatter = {
|
|
2156
2280
|
name: "kflow-orbitals",
|
|
2157
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.",
|
|
2158
|
-
allowedTools: ["Read", "Write", "Edit"],
|
|
2159
|
-
version: "
|
|
2160
|
-
//
|
|
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
|
|
2161
2285
|
};
|
|
2162
2286
|
const content = generateLeanOrbitalSkill({
|
|
2163
2287
|
includeExample: true,
|
|
2164
2288
|
includeToolWorkflow: true,
|
|
2165
|
-
includeStdStateMachines:
|
|
2166
|
-
|
|
2289
|
+
includeStdStateMachines: false,
|
|
2290
|
+
includeSchemaUpdates: false,
|
|
2291
|
+
includeCustomTraits: false,
|
|
2292
|
+
errorLevel: "top6",
|
|
2293
|
+
includeDesignGuide: true
|
|
2167
2294
|
});
|
|
2168
2295
|
return {
|
|
2169
2296
|
name: "kflow-orbitals",
|
|
@@ -2208,10 +2335,6 @@ ${getArchitectureSection()}
|
|
|
2208
2335
|
|
|
2209
2336
|
---
|
|
2210
2337
|
|
|
2211
|
-
${getMinimalTypeReference()}
|
|
2212
|
-
|
|
2213
|
-
---
|
|
2214
|
-
|
|
2215
2338
|
${getSExprQuickRef()}
|
|
2216
2339
|
|
|
2217
2340
|
---
|
|
@@ -2232,7 +2355,11 @@ ${getOverGenerationSection()}` : ""}
|
|
|
2232
2355
|
|
|
2233
2356
|
---
|
|
2234
2357
|
|
|
2235
|
-
${getCommonErrorsSection()}
|
|
2358
|
+
${getCommonErrorsSection("full")}
|
|
2359
|
+
|
|
2360
|
+
---
|
|
2361
|
+
|
|
2362
|
+
${getCustomTraitSection()}
|
|
2236
2363
|
|
|
2237
2364
|
${includeSchemaUpdates ? `---
|
|
2238
2365
|
|
|
@@ -2483,11 +2610,358 @@ Output the complete updated domain language text.
|
|
|
2483
2610
|
content
|
|
2484
2611
|
};
|
|
2485
2612
|
}
|
|
2613
|
+
function getMinimalTypeReference() {
|
|
2614
|
+
return `
|
|
2615
|
+
## Orbital Schema Structure
|
|
2616
|
+
|
|
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 = `
|
|
2963
|
+
## Core Instructions
|
|
2486
2964
|
|
|
2487
|
-
// src/orbitals-skills-generators/lean/lean-orbital-generator.ts
|
|
2488
|
-
var LEAN_CORE_INSTRUCTIONS = `
|
|
2489
|
-
## Core Instructions
|
|
2490
|
-
|
|
2491
2965
|
Generate orbital schemas using **Domain Language** - a natural, readable format.
|
|
2492
2966
|
|
|
2493
2967
|
**Output Format**: Domain Language text (NOT JSON)
|
|
@@ -3079,139 +3553,10 @@ function generateAllBuilderSkills() {
|
|
|
3079
3553
|
},
|
|
3080
3554
|
content: generateLeanFixingSkill2()
|
|
3081
3555
|
},
|
|
3082
|
-
generateDomainLanguageSkill()
|
|
3556
|
+
generateDomainLanguageSkill(),
|
|
3557
|
+
generateKflowDesignSkill()
|
|
3083
3558
|
];
|
|
3084
3559
|
}
|
|
3085
|
-
function getMinimalTypeReference2() {
|
|
3086
|
-
return `
|
|
3087
|
-
## Orbital Schema Structure
|
|
3088
|
-
|
|
3089
|
-
\`\`\`typescript
|
|
3090
|
-
interface OrbitalDefinition {
|
|
3091
|
-
name: string; // Entity name (PascalCase)
|
|
3092
|
-
entity: Entity; // Data model
|
|
3093
|
-
traits: TraitRef[]; // State machines (names or definitions)
|
|
3094
|
-
pages: Page[]; // Routes and views
|
|
3095
|
-
emits?: string[]; // Events this orbital emits
|
|
3096
|
-
listens?: EventListener[]; // Events this orbital listens to
|
|
3097
|
-
}
|
|
3098
|
-
\`\`\`
|
|
3099
|
-
|
|
3100
|
-
### Entity Fields
|
|
3101
|
-
|
|
3102
|
-
\`\`\`typescript
|
|
3103
|
-
{ name: "title", type: "string", required: true }
|
|
3104
|
-
{ name: "count", type: "number", default: 0 }
|
|
3105
|
-
{ name: "status", type: "enum", values: ["pending", "active", "done"] }
|
|
3106
|
-
{ name: "dueDate", type: "date" }
|
|
3107
|
-
\`\`\`
|
|
3108
|
-
|
|
3109
|
-
### Trait State Machine
|
|
3110
|
-
|
|
3111
|
-
\`\`\`typescript
|
|
3112
|
-
{
|
|
3113
|
-
states: [{ name: "Idle", isInitial: true }, { name: "Active" }],
|
|
3114
|
-
events: ["INIT", "ACTIVATE", "COMPLETE"],
|
|
3115
|
-
transitions: [
|
|
3116
|
-
{ from: "Idle", to: "Active", event: "ACTIVATE",
|
|
3117
|
-
guards: [["condition"]],
|
|
3118
|
-
effects: [["action"]] }
|
|
3119
|
-
]
|
|
3120
|
-
}
|
|
3121
|
-
\`\`\`
|
|
3122
|
-
`.trim();
|
|
3123
|
-
}
|
|
3124
|
-
function getPatternTypesCompact() {
|
|
3125
|
-
const patterns = getAllPatternTypes();
|
|
3126
|
-
return `
|
|
3127
|
-
## Available Pattern Types
|
|
3128
|
-
|
|
3129
|
-
${patterns.map((p) => `- \`${p}\``).join("\n")}
|
|
3130
|
-
|
|
3131
|
-
${getPatternPropsCompact()}
|
|
3132
|
-
`.trim();
|
|
3133
|
-
}
|
|
3134
|
-
function getSExprQuickRef2() {
|
|
3135
|
-
const operators = Object.keys(OPERATORS).slice(0, 15);
|
|
3136
|
-
return `
|
|
3137
|
-
## S-Expression Quick Reference
|
|
3138
|
-
|
|
3139
|
-
### Guard Expressions (Conditions)
|
|
3140
|
-
|
|
3141
|
-
\`\`\`typescript
|
|
3142
|
-
["=", "@entity.status", "active"] // Equality
|
|
3143
|
-
[">", "@entity.count", 0] // Greater than
|
|
3144
|
-
["and", ["cond1"], ["cond2"]] // Logical AND
|
|
3145
|
-
["or", ["cond1"], ["cond2"]] // Logical OR
|
|
3146
|
-
["not", ["condition"]] // Logical NOT
|
|
3147
|
-
\`\`\`
|
|
3148
|
-
|
|
3149
|
-
### Effect Expressions (Actions)
|
|
3150
|
-
|
|
3151
|
-
\`\`\`typescript
|
|
3152
|
-
["set", "@entity.field", value] // Update field
|
|
3153
|
-
["emit", "EVENT_NAME", payload] // Emit event
|
|
3154
|
-
["navigate", "/path"] // Navigate to route
|
|
3155
|
-
["render-ui", "main", { type, props }] // Render pattern
|
|
3156
|
-
["persist", "create", "Entity", data] // Database operation
|
|
3157
|
-
\`\`\`
|
|
3158
|
-
|
|
3159
|
-
### Available Operators
|
|
3160
|
-
|
|
3161
|
-
${operators.map((op) => `- \`${op}\``).join("\n")}
|
|
3162
|
-
`.trim();
|
|
3163
|
-
}
|
|
3164
|
-
function getRenderUIQuickRef2() {
|
|
3165
|
-
const slots = UI_SLOTS;
|
|
3166
|
-
return `
|
|
3167
|
-
## Render-UI Effect Reference
|
|
3168
|
-
|
|
3169
|
-
### Syntax
|
|
3170
|
-
|
|
3171
|
-
\`\`\`typescript
|
|
3172
|
-
["render-ui", slot, patternConfig | null]
|
|
3173
|
-
\`\`\`
|
|
3174
|
-
|
|
3175
|
-
### UI Slots
|
|
3176
|
-
|
|
3177
|
-
${slots.map((slot) => `- \`${slot}\``).join("\n")}
|
|
3178
|
-
|
|
3179
|
-
### Example
|
|
3180
|
-
|
|
3181
|
-
\`\`\`typescript
|
|
3182
|
-
["render-ui", "main", {
|
|
3183
|
-
type: "entity-table",
|
|
3184
|
-
entity: "Task",
|
|
3185
|
-
columns: ["title", "status"],
|
|
3186
|
-
itemActions: [{ label: "Edit", event: "EDIT" }]
|
|
3187
|
-
}]
|
|
3188
|
-
\`\`\`
|
|
3189
|
-
|
|
3190
|
-
Clear slot: \`["render-ui", "modal", null]\`
|
|
3191
|
-
`.trim();
|
|
3192
|
-
}
|
|
3193
|
-
function getFieldTypesCompact() {
|
|
3194
|
-
return `
|
|
3195
|
-
## Field Types
|
|
3196
|
-
|
|
3197
|
-
| Type | Example | Notes |
|
|
3198
|
-
|------|---------|-------|
|
|
3199
|
-
| \`string\` | \`{ name: "title", type: "string" }\` | Text |
|
|
3200
|
-
| \`number\` | \`{ name: "count", type: "number" }\` | Integer or float |
|
|
3201
|
-
| \`boolean\` | \`{ name: "active", type: "boolean" }\` | true/false |
|
|
3202
|
-
| \`date\` | \`{ name: "birthday", type: "date" }\` | Date only |
|
|
3203
|
-
| \`timestamp\` | \`{ name: "createdAt", type: "timestamp" }\` | Date + time |
|
|
3204
|
-
| \`enum\` | \`{ name: "status", type: "enum", values: ["a", "b"] }\` | Fixed options |
|
|
3205
|
-
| \`array\` | \`{ name: "tags", type: "array", items: "string" }\` | List |
|
|
3206
|
-
| \`relation\` | \`{ name: "user", type: "relation", relation: { entity: "User", cardinality: "one" } }\` | Foreign key |
|
|
3207
|
-
|
|
3208
|
-
### Field Properties
|
|
3209
|
-
|
|
3210
|
-
- \`required: true\` - Must have value
|
|
3211
|
-
- \`default: value\` - Default value
|
|
3212
|
-
- \`unique: true\` - Must be unique
|
|
3213
|
-
`.trim();
|
|
3214
|
-
}
|
|
3215
3560
|
|
|
3216
3561
|
// src/prompts/generation-prompts.ts
|
|
3217
3562
|
function getOrbitalDecompositionPrompt() {
|
|
@@ -3251,7 +3596,7 @@ ${getArchitectureSection()}
|
|
|
3251
3596
|
|
|
3252
3597
|
---
|
|
3253
3598
|
|
|
3254
|
-
${
|
|
3599
|
+
${getMinimalTypeReference()}
|
|
3255
3600
|
|
|
3256
3601
|
---
|
|
3257
3602
|
|
|
@@ -3385,6 +3730,6 @@ Use with: \`uses: [{ from: "std/behaviors/crud", as: "CRUD" }]\`
|
|
|
3385
3730
|
`;
|
|
3386
3731
|
}
|
|
3387
3732
|
|
|
3388
|
-
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,
|
|
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 };
|
|
3389
3734
|
//# sourceMappingURL=index.js.map
|
|
3390
3735
|
//# sourceMappingURL=index.js.map
|