@olonjs/cli 3.0.87 → 3.0.88

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.
@@ -3,555 +3,1600 @@ set -e
3
3
 
4
4
  echo "Starting project reconstruction..."
5
5
 
6
- mkdir -p "docs"
7
- echo "Creating docs/01-Onboarding_Client_completo_aggiornato.md..."
8
- cat << 'END_OF_FILE_CONTENT' > "docs/01-Onboarding_Client_completo_aggiornato.md"
9
- # Onboarding — Percorso Client (senza CMS) — Versione completa
6
+ mkdir -p ".cursor"
7
+ mkdir -p ".cursor/skills-cursor"
8
+ mkdir -p ".cursor/skills-cursor/create-rule"
9
+ echo "Creating .cursor/skills-cursor/create-rule/SKILL.md..."
10
+ cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/create-rule/SKILL.md"
11
+ ---
12
+ name: create-rule
13
+ description: >-
14
+ Create Cursor rules for persistent AI guidance. Use when you want to create a
15
+ rule, add coding standards, set up project conventions, configure
16
+ file-specific patterns, create RULE.md files, or asks about .cursor/rules/ or
17
+ AGENTS.md.
18
+ ---
19
+ # Creating Cursor Rules
20
+
21
+ Create project rules in `.cursor/rules/` to provide persistent context for the AI agent.
22
+
23
+ ## Gather Requirements
24
+
25
+ Before creating a rule, determine:
26
+
27
+ 1. **Purpose**: What should this rule enforce or teach?
28
+ 2. **Scope**: Should it always apply, or only for specific files?
29
+ 3. **File patterns**: If file-specific, which glob patterns?
30
+
31
+ ### Inferring from Context
32
+
33
+ If you have previous conversation context, infer rules from what was discussed. You can create multiple rules if the conversation covers distinct topics or patterns. Don't ask redundant questions if the context already provides the answers.
34
+
35
+ ### Required Questions
36
+
37
+ If the user hasn't specified scope, ask:
38
+ - "Should this rule always apply, or only when working with specific files?"
39
+
40
+ If they mentioned specific files and haven't provided concrete patterns, ask:
41
+ - "Which file patterns should this rule apply to?" (e.g., `**/*.ts`, `backend/**/*.py`)
10
42
 
11
- **Per chi:** Sviluppo grafico e dati quando **non** usi il CMS (Studio/ICE). Il sito è un **client**: i dati arrivano da JSON locali, da API o da un CMS esterno; tu ti occupi di layout, design e rendering.
43
+ It's very important that we get clarity on the file patterns.
12
44
 
13
- **Riferimento spec:** OlonJS Architecture v1.2 (legacy alias: JSONPAGES) solo le parti che riguardano struttura sito, componenti e dati. Ignori: Studio, ICE, Form Factory, IDAC, TOCC, AddSectionConfig, schema obbligatori per l'editor.
45
+ Use the AskQuestion tool when available to gather this efficiently.
14
46
 
15
47
  ---
16
48
 
17
- ## 1. Cosa fai tu (in sintesi)
49
+ ## Rule File Format
50
+
51
+ Rules are `.mdc` files in `.cursor/rules/` with YAML frontmatter:
52
+
53
+ ```
54
+ .cursor/rules/
55
+ typescript-standards.mdc
56
+ react-patterns.mdc
57
+ api-conventions.mdc
58
+ ```
59
+
60
+ ### File Structure
61
+
62
+ ```markdown
63
+ ---
64
+ description: Brief description of what this rule does
65
+ globs: **/*.ts # File pattern for file-specific rules
66
+ alwaysApply: false # Set to true if rule should always apply
67
+ ---
68
+
69
+ # Rule Title
70
+
71
+ Your rule content here...
72
+ ```
73
+
74
+ ### Frontmatter Fields
75
+
76
+ | Field | Type | Description |
77
+ |-------|------|-------------|
78
+ | `description` | string | What the rule does (shown in rule picker) |
79
+ | `globs` | string | File pattern - rule applies when matching files are open |
80
+ | `alwaysApply` | boolean | If true, applies to every session |
81
+
82
+ ---
83
+
84
+ ## Rule Configurations
85
+
86
+ ### Always Apply
87
+
88
+ For universal standards that should apply to every conversation:
89
+
90
+ ```yaml
91
+ ---
92
+ description: Core coding standards for the project
93
+ alwaysApply: true
94
+ ---
95
+ ```
96
+
97
+ ### Apply to Specific Files
98
+
99
+ For rules that apply when working with certain file types:
100
+
101
+ ```yaml
102
+ ---
103
+ description: TypeScript conventions for this project
104
+ globs: **/*.ts
105
+ alwaysApply: false
106
+ ---
107
+ ```
108
+
109
+ ---
18
110
 
19
- - **Grafico:** Layout e stili delle section (View + CSS / design tokens se vuoi).
20
- - **Dati:** Da dove prendono i dati le pagine (file JSON, API, altro CMS) e come vengono passati al motore (config + pages).
111
+ ## Best Practices
112
+
113
+ ### Keep Rules Concise
114
+
115
+ - **Under 50 lines**: Rules should be concise and to the point
116
+ - **One concern per rule**: Split large rules into focused pieces
117
+ - **Actionable**: Write like clear internal docs
118
+ - **Concrete examples**: Ideally provide concrete examples of how to fix issues
119
+
120
+ ---
121
+
122
+ ## Example Rules
123
+
124
+ ### TypeScript Standards
125
+
126
+ ```markdown
127
+ ---
128
+ description: TypeScript coding standards
129
+ globs: **/*.ts
130
+ alwaysApply: false
131
+ ---
132
+
133
+ # Error Handling
134
+
135
+ \`\`\`typescript
136
+ // ❌ BAD
137
+ try {
138
+ await fetchData();
139
+ } catch (e) {}
140
+
141
+ // ✅ GOOD
142
+ try {
143
+ await fetchData();
144
+ } catch (e) {
145
+ logger.error('Failed to fetch', { error: e });
146
+ throw new DataFetchError('Unable to retrieve data', { cause: e });
147
+ }
148
+ \`\`\`
149
+ ```
150
+
151
+ ### React Patterns
152
+
153
+ ```markdown
154
+ ---
155
+ description: React component patterns
156
+ globs: **/*.tsx
157
+ alwaysApply: false
158
+ ---
159
+
160
+ # React Patterns
161
+
162
+ - Use functional components
163
+ - Extract custom hooks for reusable logic
164
+ - Colocate styles with components
165
+ ```
166
+
167
+ ---
168
+
169
+ ## Checklist
170
+
171
+ - [ ] File is `.mdc` format in `.cursor/rules/`
172
+ - [ ] Frontmatter configured correctly
173
+ - [ ] Content under 500 lines
174
+ - [ ] Includes concrete examples
175
+
176
+ END_OF_FILE_CONTENT
177
+ mkdir -p ".cursor/skills-cursor/create-skill"
178
+ echo "Creating .cursor/skills-cursor/create-skill/SKILL.md..."
179
+ cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/create-skill/SKILL.md"
180
+ ---
181
+ name: create-skill
182
+ description: >-
183
+ Guides users through creating effective Agent Skills for Cursor. Use when you
184
+ want to create, write, or author a new skill, or asks about skill structure,
185
+ best practices, or SKILL.md format.
186
+ ---
187
+ # Creating Skills in Cursor
188
+
189
+ This skill guides you through creating effective Agent Skills for Cursor. Skills are markdown files that teach the agent how to perform specific tasks: reviewing PRs using team standards, generating commit messages in a preferred format, querying database schemas, or any specialized workflow.
190
+
191
+ ## Before You Begin: Gather Requirements
192
+
193
+ Before creating a skill, gather essential information from the user about:
194
+
195
+ 1. **Purpose and scope**: What specific task or workflow should this skill help with?
196
+ 2. **Target location**: Should this be a personal skill (~/.cursor/skills/) or project skill (.cursor/skills/)?
197
+ 3. **Trigger scenarios**: When should the agent automatically apply this skill?
198
+ 4. **Key domain knowledge**: What specialized information does the agent need that it wouldn't already know?
199
+ 5. **Output format preferences**: Are there specific templates, formats, or styles required?
200
+ 6. **Existing patterns**: Are there existing examples or conventions to follow?
201
+
202
+ ### Inferring from Context
203
+
204
+ If you have previous conversation context, infer the skill from what was discussed. You can create skills based on workflows, patterns, or domain knowledge that emerged in the conversation.
205
+
206
+ ### Gathering Additional Information
207
+
208
+ If you need clarification, use the AskQuestion tool when available:
209
+
210
+ ```
211
+ Example AskQuestion usage:
212
+ - "Where should this skill be stored?" with options like ["Personal (~/.cursor/skills/)", "Project (.cursor/skills/)"]
213
+ - "Should this skill include executable scripts?" with options like ["Yes", "No"]
214
+ ```
21
215
 
22
- Non devi: tipizzare tutto per l'editor, esporre schema Zod al Form Factory, gestire overlay Studio, Add Section, ecc. Puoi usare tipi minimi o anche `unknown`/`any` sui dati se non ti serve type-safety forte.
216
+ If the AskQuestion tool is not available, ask these questions conversationally.
23
217
 
24
218
  ---
25
219
 
26
- ## 2. Struttura progetto (minima)
220
+ ## Skill File Structure
27
221
 
28
- - **`src/data/config/site.json`** — Identità, header, footer (blocchi con `id`, `type`, `data`, `settings`).
29
- - **`src/data/config/menu.json`** — Menu (es. `{ main: [{ label, href }] }`).
30
- - **`src/data/config/theme.json`** — (Opzionale) Token tema (colori, font, radius).
31
- - **`src/data/pages/<slug>.json`** — Una pagina = `slug`, `meta`, `sections[]` (array di blocchi `id`, `type`, `data`, `settings`). **Per creare una nuova pagina** basta aggiungere un file `<slug>.json` in `src/data/pages/`; lo slug del nome file diventa il path della pagina (es. `chi-siamo.json` → `/chi-siamo`).
32
- - **`src/components/<sectionType>/`** — Una cartella per tipo di blocco (hero, header, footer, feature-grid, …).
33
- - **`src/App.tsx`** — Carica site, menu, theme, pages; costruisce la config; renderizza **`<JsonPagesEngine config={config} />` *(from `@olonjs/core`, legacy alias: `@jsonpages/core`)***.
222
+ ### Directory Layout
34
223
 
35
- Il motore (Core) si aspetta comunque un **registry** (mappa tipo → componente) e le **pagine** nel formato previsto (slug → page con `sections`). Come popoli i JSON (a mano, da script, da altro CMS) è fuori dall'editor.
224
+ Skills are stored as directories containing a `SKILL.md` file:
36
225
 
37
- **Perché servono (struttura):** Path e forma (site, menu, theme, pages con sections) sono il contratto minimo che il Core usa per routing e rendering; rispettarli permette di cambiare in seguito fonte dati (JSON → API) senza riscrivere la logica. Vedi spec §2 (JSP), Appendix A.4.
226
+ ```
227
+ skill-name/
228
+ ├── SKILL.md # Required - main instructions
229
+ ├── reference.md # Optional - detailed documentation
230
+ ├── examples.md # Optional - usage examples
231
+ └── scripts/ # Optional - utility scripts
232
+ ├── validate.py
233
+ └── helper.sh
234
+ ```
235
+
236
+ ### Storage Locations
237
+
238
+ | Type | Path | Scope |
239
+ |------|------|-------|
240
+ | Personal | ~/.cursor/skills/skill-name/ | Available across all your projects |
241
+ | Project | .cursor/skills/skill-name/ | Shared with anyone using the repository |
242
+
243
+ **IMPORTANT**: Never create skills in `~/.cursor/skills-cursor/`. This directory is reserved for Cursor's internal built-in skills and is managed automatically by the system.
244
+
245
+ ### SKILL.md Structure
38
246
 
247
+ Every skill requires a `SKILL.md` file with YAML frontmatter and markdown body:
248
+
249
+ ```markdown
250
+ ---
251
+ name: your-skill-name
252
+ description: Brief description of what this skill does and when to use it
39
253
  ---
40
254
 
41
- ## 3. Componenti (solo View)
255
+ # Your Skill Name
256
+
257
+ ## Instructions
258
+ Clear, step-by-step guidance for the agent.
259
+
260
+ ## Examples
261
+ Concrete examples of using this skill.
262
+ ```
42
263
 
43
- - Ogni **section type** ha almeno una **View**: riceve `data` e, se serve, `settings`. L'header riceve anche `menu` (array di `{ label, href }`).
44
- - **Niente obbligo di capsule "piene":** puoi avere solo `View.tsx` (e magari un `index.ts` che esporta la View). Schema Zod e types servono solo se vuoi type-safety in sviluppo o se in futuro attivi il CMS.
45
- - **Stili:** Puoi usare classi Tailwind "libere" o un set di variabili CSS (es. `--local-bg`, `--local-text`) per coerenza. Le spec CIP (solo variabili, niente utility nude) sono per il percorso governance; qui puoi adattare alle tue convenzioni.
46
- - **Asset:** Se il Core espone `resolveAssetUrl(path, tenantId)`, usalo per le immagini; altrimenti path relativi o URL assoluti.
264
+ ### Required Metadata Fields
47
265
 
48
- **Perché servono (componenti):** Il registry deve avere un componente per ogni `type` usato nei JSON; la View deve ricevere `data` (e `settings`/`menu` dove previsto) così il Core può renderizzare senza conoscere i dettagli. Senza registry coerente con i dati, il motore non saprebbe cosa montare. Vedi spec §3 (TBP), §4 (CIP) per il percorso completo.
266
+ | Field | Requirements | Purpose |
267
+ |-------|--------------|---------|
268
+ | `name` | Max 64 chars, lowercase letters/numbers/hyphens only | Unique identifier for the skill |
269
+ | `description` | Max 1024 chars, non-empty | Helps agent decide when to apply the skill |
49
270
 
50
271
  ---
51
272
 
52
- ## 3.1 Image e campi immagine (se usi schema in seguito)
273
+ ## Writing Effective Descriptions
53
274
 
54
- Se più avanti aggiungi schema Zod per type-safety o per attivare Studio, i **campi immagine** vanno modellati così:
275
+ The description is **critical** for skill discovery. The agent uses it to decide when to apply your skill.
55
276
 
56
- - **Schema:** Il campo immagine è un **oggetto** (non una stringa) con almeno `url` e opzionalmente `alt`. Lo schema di questo oggetto va marcato con **`.describe('ui:image-picker')`** così il Form Factory (Inspector) mostra il widget Image Picker. Esempio: uno sub-schema `ImageSelectionSchema = z.object({ url: z.string(), alt: z.string().optional() }).describe('ui:image-picker')` usato come `image: ImageSelectionSchema.default({ url: '', alt: '' })`.
57
- - **View:** Per il `src` dell'immagine usa **`resolveAssetUrl(data.image.url, tenantId)`**; sul nodo che rappresenta l'immagine imposta **`data-jp-field="image"`** (così l'Inspector lega correttamente il campo).
277
+ ### Description Best Practices
58
278
 
59
- **Riferimento:** componente `image-break` in `apps/tenant-alpha/src/components/image-break/` (schema.ts, View.tsx) come esempio completo.
279
+ 1. **Write in third person** (the description is injected into the system prompt):
280
+ - ✅ Good: "Processes Excel files and generates reports"
281
+ - ❌ Avoid: "I can help you process Excel files"
282
+ - ❌ Avoid: "You can use this to process Excel files"
283
+
284
+ 2. **Be specific and include trigger terms**:
285
+ - ✅ Good: "Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction."
286
+ - ❌ Vague: "Helps with documents"
287
+
288
+ 3. **Include both WHAT and WHEN**:
289
+ - WHAT: What the skill does (specific capabilities)
290
+ - WHEN: When the agent should use it (trigger scenarios)
291
+
292
+ ### Description Examples
293
+
294
+ ```yaml
295
+ # PDF Processing
296
+ description: Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction.
297
+
298
+ # Excel Analysis
299
+ description: Analyze Excel spreadsheets, create pivot tables, generate charts. Use when analyzing Excel files, spreadsheets, tabular data, or .xlsx files.
300
+
301
+ # Git Commit Helper
302
+ description: Generate descriptive commit messages by analyzing git diffs. Use when the user asks for help writing commit messages or reviewing staged changes.
303
+
304
+ # Code Review
305
+ description: Review code for quality, security, and best practices following team standards. Use when reviewing pull requests, code changes, or when the user asks for a code review.
306
+ ```
60
307
 
61
308
  ---
62
309
 
63
- ## 4. Dati: da dove arrivano
310
+ ## Core Authoring Principles
311
+
312
+ ### 1. Concise is Key
313
+
314
+ The context window is shared with conversation history, other skills, and requests. Every token competes for space.
64
315
 
65
- - **Solo JSON locali:** Leggi `site.json`, `menu.json`, `theme.json`, `pages/*.json` e li passi in `config` (siteConfig, menuConfig, themeConfig, pages). Nessun CMS.
66
- - **CMS esterno / API:** Invece di importare i JSON, fai fetch (o SSR) e costruisci gli stessi oggetti (siteConfig, menuConfig, pages) e li passi a `JsonPagesEngine`. La forma delle pagine resta: `{ slug, meta?, sections[] }`; ogni section: `{ id, type, data, settings? }`.
67
- - **Ibrido:** Header/footer da `site.json`, body da API o da altro CMS: costruisci un unico `pages[slug]` con `sections` che rispettano i tipi di blocco che hai nel registry.
316
+ **Default assumption**: The agent is already very smart. Only add context it doesn't already have.
68
317
 
69
- Non devi registrare schema o AddSectionConfig a meno che non attivi Studio.
318
+ Challenge each piece of information:
319
+ - "Does the agent really need this explanation?"
320
+ - "Can I assume the agent knows this?"
321
+ - "Does this paragraph justify its token cost?"
70
322
 
71
- **Perché servono (dati):** La forma `sections[]` con `id`, `type`, `data`, `settings?` è ciò che il SectionRenderer e il Core si aspettano; mantenere quella forma anche quando i dati arrivano da API o altro CMS evita adattatori fragili e permette di attivare Studio in seguito senza rifare i dati. Vedi spec Appendix A.2 (PageConfig, SiteConfig, MenuConfig).
323
+ **Good (concise)**:
324
+ ```markdown
325
+ ## Extract PDF text
326
+
327
+ Use pdfplumber for text extraction:
328
+
329
+ \`\`\`python
330
+ import pdfplumber
331
+
332
+ with pdfplumber.open("file.pdf") as pdf:
333
+ text = pdf.pages[0].extract_text()
334
+ \`\`\`
335
+ ```
336
+
337
+ **Bad (verbose)**:
338
+ ```markdown
339
+ ## Extract PDF text
340
+
341
+ PDF (Portable Document Format) files are a common file format that contains
342
+ text, images, and other content. To extract text from a PDF, you'll need to
343
+ use a library. There are many libraries available for PDF processing, but we
344
+ recommend pdfplumber because it's easy to use and handles most cases well...
345
+ ```
346
+
347
+ ### 2. Keep SKILL.md Under 500 Lines
348
+
349
+ For optimal performance, the main SKILL.md file should be concise. Use progressive disclosure for detailed content.
350
+
351
+ ### 3. Progressive Disclosure
352
+
353
+ Put essential information in SKILL.md; detailed reference material in separate files that the agent reads only when needed.
354
+
355
+ ```markdown
356
+ # PDF Processing
357
+
358
+ ## Quick start
359
+ [Essential instructions here]
360
+
361
+ ## Additional resources
362
+ - For complete API details, see [reference.md](reference.md)
363
+ - For usage examples, see [examples.md](examples.md)
364
+ ```
365
+
366
+ **Keep references one level deep** - link directly from SKILL.md to reference files. Deeply nested references may result in partial reads.
367
+
368
+ ### 4. Set Appropriate Degrees of Freedom
369
+
370
+ Match specificity to the task's fragility:
371
+
372
+ | Freedom Level | When to Use | Example |
373
+ |---------------|-------------|---------|
374
+ | **High** (text instructions) | Multiple valid approaches, context-dependent | Code review guidelines |
375
+ | **Medium** (pseudocode/templates) | Preferred pattern with acceptable variation | Report generation |
376
+ | **Low** (specific scripts) | Fragile operations, consistency critical | Database migrations |
72
377
 
73
378
  ---
74
379
 
75
- ## 5. Registry e config (minimo)
380
+ ## Common Patterns
381
+
382
+ ### Template Pattern
76
383
 
77
- - **Registry:** Un oggetto che mappa ogni `sectionType` (stringa) al componente React che renderizza quel tipo. Es.: `{ header: Header, footer: Footer, hero: Hero, ... }`. Se non usi Studio, puoi tipizzare in modo lasco (es. `Record<string, React.FC<any>>` o comunque compatibile con quanto si aspetta `JsonPagesConfig['registry']` from `@olonjs/core`).
78
- - **Config da passare a JsonPagesEngine:**
79
- `tenantId`, `registry`, `pages`, `siteConfig`, `menuConfig`, `themeConfig` (o oggetto vuoto), `themeCss: { tenant: cssString }`.
80
- Se **non** usi Studio, **schemas** e **addSection** possono essere placeholder (oggetto vuoto / no-op) se il Core lo permette; altrimenti fornisci il minimo (es. schemas = `{}`, addSection = `{ addableSectionTypes: [], sectionTypeLabels: {}, getDefaultSectionData: () => ({}) }`) per non rompere l'engine.
384
+ Provide output format templates:
81
385
 
82
- Verifica nella doc o nel tipo `JsonPagesConfig` se `schemas` e `addSection` sono opzionali quando Studio non è in uso.
386
+ ```markdown
387
+ ## Report structure
83
388
 
84
- **Perché servono (registry e config):** Il Core deve risolvere ogni section a un componente (registry) e avere pagine, site, menu, theme e CSS tenant per renderizzare e, se serve, iniettare lo Stage in iframe; i campi obbligatori di config sono il minimo per far funzionare l'engine. Placeholder per schemas/addSection evitano errori quando Studio non è usato. Vedi spec §10 (JEB), Appendix A.
389
+ Use this template:
390
+
391
+ \`\`\`markdown
392
+ # [Analysis Title]
393
+
394
+ ## Executive summary
395
+ [One-paragraph overview of key findings]
396
+
397
+ ## Key findings
398
+ - Finding 1 with supporting data
399
+ - Finding 2 with supporting data
400
+
401
+ ## Recommendations
402
+ 1. Specific actionable recommendation
403
+ 2. Specific actionable recommendation
404
+ \`\`\`
405
+ ```
406
+
407
+ ### Examples Pattern
408
+
409
+ For skills where output quality depends on seeing examples:
410
+
411
+ ```markdown
412
+ ## Commit message format
413
+
414
+ **Example 1:**
415
+ Input: Added user authentication with JWT tokens
416
+ Output:
417
+ \`\`\`
418
+ feat(auth): implement JWT-based authentication
419
+
420
+ Add login endpoint and token validation middleware
421
+ \`\`\`
422
+
423
+ **Example 2:**
424
+ Input: Fixed bug where dates displayed incorrectly
425
+ Output:
426
+ \`\`\`
427
+ fix(reports): correct date formatting in timezone conversion
428
+
429
+ Use UTC timestamps consistently across report generation
430
+ \`\`\`
431
+ ```
432
+
433
+ ### Workflow Pattern
434
+
435
+ Break complex operations into clear steps with checklists:
436
+
437
+ ```markdown
438
+ ## Form filling workflow
439
+
440
+ Copy this checklist and track progress:
441
+
442
+ \`\`\`
443
+ Task Progress:
444
+ - [ ] Step 1: Analyze the form
445
+ - [ ] Step 2: Create field mapping
446
+ - [ ] Step 3: Validate mapping
447
+ - [ ] Step 4: Fill the form
448
+ - [ ] Step 5: Verify output
449
+ \`\`\`
450
+
451
+ **Step 1: Analyze the form**
452
+ Run: \`python scripts/analyze_form.py input.pdf\`
453
+ ...
454
+ ```
455
+
456
+ ### Conditional Workflow Pattern
457
+
458
+ Guide through decision points:
459
+
460
+ ```markdown
461
+ ## Document modification workflow
462
+
463
+ 1. Determine the modification type:
464
+
465
+ **Creating new content?** → Follow "Creation workflow" below
466
+ **Editing existing content?** → Follow "Editing workflow" below
467
+
468
+ 2. Creation workflow:
469
+ - Use docx-js library
470
+ - Build document from scratch
471
+ ...
472
+ ```
473
+
474
+ ### Feedback Loop Pattern
475
+
476
+ For quality-critical tasks, implement validation loops:
477
+
478
+ ```markdown
479
+ ## Document editing process
480
+
481
+ 1. Make your edits
482
+ 2. **Validate immediately**: \`python scripts/validate.py output/\`
483
+ 3. If validation fails:
484
+ - Review the error message
485
+ - Fix the issues
486
+ - Run validation again
487
+ 4. **Only proceed when validation passes**
488
+ ```
85
489
 
86
490
  ---
87
491
 
88
- ## 6. Checklist rapida (sviluppo grafico e dati, senza CMS)
492
+ ## Utility Scripts
493
+
494
+ Pre-made scripts offer advantages over generated code:
495
+ - More reliable than generated code
496
+ - Save tokens (no code in context)
497
+ - Save time (no code generation)
498
+ - Ensure consistency across uses
499
+
500
+ ```markdown
501
+ ## Utility scripts
502
+
503
+ **analyze_form.py**: Extract all form fields from PDF
504
+ \`\`\`bash
505
+ python scripts/analyze_form.py input.pdf > fields.json
506
+ \`\`\`
89
507
 
90
- | Cosa | Azione |
91
- |------|--------|
92
- | **Layout / grafico** | Implementare le View (una per section type) e gli stili (CSS / Tailwind / variabili). |
93
- | **Dati** | Decidere fonte (JSON locali, API, altro CMS); costruire `siteConfig`, `menuConfig`, `pages` nella forma attesa e passarli in `config`. |
94
- | **Registry** | Mappare ogni tipo di blocco usato nei JSON al componente corrispondente. |
95
- | **Header / menu** | Header component riceve `data`, `settings`, `menu`; `menu` viene da `menuConfig` (es. `menuConfig.main`). |
96
- | **Pagine** | Ogni pagina = un entry in `pages` con `sections[]`; ogni section ha `id`, `type`, `data`, `settings?`. |
97
- | **Nuova pagina** | Aggiungere un file `<slug>.json` in `src/data/pages/` (lo slug diventa il path della pagina). |
98
- | **Image (se schema)** | Campo immagine = oggetto `{ url, alt? }` con schema `.describe('ui:image-picker')`; View usa `resolveAssetUrl` e `data-jp-field="image"`. |
99
- | **Studio / ICE** | Non usati: niente schema obbligatori, niente data-jp-*, niente overlay CSS, niente Add Section. |
508
+ **validate.py**: Check for errors
509
+ \`\`\`bash
510
+ python scripts/validate.py fields.json
511
+ # Returns: "OK" or lists conflicts
512
+ \`\`\`
513
+ ```
514
+
515
+ Make clear whether the agent should **execute** the script (most common) or **read** it as reference.
100
516
 
101
517
  ---
102
518
 
103
- ## 7. Quando passi al percorso "Governance"
519
+ ## Anti-Patterns to Avoid
520
+
521
+ ### 1. Windows-Style Paths
522
+ - ✅ Use: `scripts/helper.py`
523
+ - ❌ Avoid: `scripts\helper.py`
104
524
 
105
- Se più avanti vuoi l'editor (Studio) e la governance (tipi, schema, Add Section, overlay): usa l'onboarding **02-Onboarding_Governance_completo.md** e allinea il progetto a tipi, capsule piene (View + schema + types), IDAC, TOCC, AddSectionConfig e Appendix A delle spec v1.2.
525
+ ### 2. Too Many Options
526
+ ```markdown
527
+ # Bad - confusing
528
+ "You can use pypdf, or pdfplumber, or PyMuPDF, or..."
529
+
530
+ # Good - provide a default with escape hatch
531
+ "Use pdfplumber for text extraction.
532
+ For scanned PDFs requiring OCR, use pdf2image with pytesseract instead."
533
+ ```
534
+
535
+ ### 3. Time-Sensitive Information
536
+ ```markdown
537
+ # Bad - will become outdated
538
+ "If you're doing this before August 2025, use the old API."
539
+
540
+ # Good - use an "old patterns" section
541
+ ## Current method
542
+ Use the v2 API endpoint.
543
+
544
+ ## Old patterns (deprecated)
545
+ <details>
546
+ <summary>Legacy v1 API</summary>
547
+ ...
548
+ </details>
549
+ ```
550
+
551
+ ### 4. Inconsistent Terminology
552
+ Choose one term and use it throughout:
553
+ - ✅ Always "API endpoint" (not mixing "URL", "route", "path")
554
+ - ✅ Always "field" (not mixing "box", "element", "control")
555
+
556
+ ### 5. Vague Skill Names
557
+ - ✅ Good: `processing-pdfs`, `analyzing-spreadsheets`
558
+ - ❌ Avoid: `helper`, `utils`, `tools`
559
+
560
+ ---
561
+
562
+ ## Skill Creation Workflow
563
+
564
+ When helping a user create a skill, follow this process:
565
+
566
+ ### Phase 1: Discovery
567
+
568
+ Gather information about:
569
+ 1. The skill's purpose and primary use case
570
+ 2. Storage location (personal vs project)
571
+ 3. Trigger scenarios
572
+ 4. Any specific requirements or constraints
573
+ 5. Existing examples or patterns to follow
574
+
575
+ If you have access to the AskQuestion tool, use it for efficient structured gathering. Otherwise, ask conversationally.
576
+
577
+ ### Phase 2: Design
578
+
579
+ 1. Draft the skill name (lowercase, hyphens, max 64 chars)
580
+ 2. Write a specific, third-person description
581
+ 3. Outline the main sections needed
582
+ 4. Identify if supporting files or scripts are needed
583
+
584
+ ### Phase 3: Implementation
585
+
586
+ 1. Create the directory structure
587
+ 2. Write the SKILL.md file with frontmatter
588
+ 3. Create any supporting reference files
589
+ 4. Create any utility scripts if needed
590
+
591
+ ### Phase 4: Verification
592
+
593
+ 1. Verify the SKILL.md is under 500 lines
594
+ 2. Check that the description is specific and includes trigger terms
595
+ 3. Ensure consistent terminology throughout
596
+ 4. Verify all file references are one level deep
597
+ 5. Test that the skill can be discovered and applied
598
+
599
+ ---
600
+
601
+ ## Complete Example
602
+
603
+ Here's a complete example of a well-structured skill:
604
+
605
+ **Directory structure:**
606
+ ```
607
+ code-review/
608
+ ├── SKILL.md
609
+ ├── STANDARDS.md
610
+ └── examples.md
611
+ ```
612
+
613
+ **SKILL.md:**
614
+ ```markdown
615
+ ---
616
+ name: code-review
617
+ description: Review code for quality, security, and maintainability following team standards. Use when reviewing pull requests, examining code changes, or when the user asks for a code review.
618
+ ---
619
+
620
+ # Code Review
621
+
622
+ ## Quick Start
623
+
624
+ When reviewing code:
625
+
626
+ 1. Check for correctness and potential bugs
627
+ 2. Verify security best practices
628
+ 3. Assess code readability and maintainability
629
+ 4. Ensure tests are adequate
630
+
631
+ ## Review Checklist
632
+
633
+ - [ ] Logic is correct and handles edge cases
634
+ - [ ] No security vulnerabilities (SQL injection, XSS, etc.)
635
+ - [ ] Code follows project style conventions
636
+ - [ ] Functions are appropriately sized and focused
637
+ - [ ] Error handling is comprehensive
638
+ - [ ] Tests cover the changes
639
+
640
+ ## Providing Feedback
641
+
642
+ Format feedback as:
643
+ - 🔴 **Critical**: Must fix before merge
644
+ - 🟡 **Suggestion**: Consider improving
645
+ - 🟢 **Nice to have**: Optional enhancement
646
+
647
+ ## Additional Resources
648
+
649
+ - For detailed coding standards, see [STANDARDS.md](STANDARDS.md)
650
+ - For example reviews, see [examples.md](examples.md)
651
+ ```
652
+
653
+ ---
654
+
655
+ ## Summary Checklist
656
+
657
+ Before finalizing a skill, verify:
658
+
659
+ ### Core Quality
660
+ - [ ] Description is specific and includes key terms
661
+ - [ ] Description includes both WHAT and WHEN
662
+ - [ ] Written in third person
663
+ - [ ] SKILL.md body is under 500 lines
664
+ - [ ] Consistent terminology throughout
665
+ - [ ] Examples are concrete, not abstract
666
+
667
+ ### Structure
668
+ - [ ] File references are one level deep
669
+ - [ ] Progressive disclosure used appropriately
670
+ - [ ] Workflows have clear steps
671
+ - [ ] No time-sensitive information
672
+
673
+ ### If Including Scripts
674
+ - [ ] Scripts solve problems rather than punt
675
+ - [ ] Required packages are documented
676
+ - [ ] Error handling is explicit and helpful
677
+ - [ ] No Windows-style paths
106
678
 
107
679
  END_OF_FILE_CONTENT
108
- echo "Creating docs/01-Onboarding_Governance_naked.md..."
109
- cat << 'END_OF_FILE_CONTENT' > "docs/01-Onboarding_Governance_naked.md"
110
- ### 📄 File 1: Client Path (No CMS)
680
+ mkdir -p ".cursor/skills-cursor/create-subagent"
681
+ echo "Creating .cursor/skills-cursor/create-subagent/SKILL.md..."
682
+ cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/create-subagent/SKILL.md"
683
+ ---
684
+ name: create-subagent
685
+ description: >-
686
+ Create custom subagents for specialized AI tasks. Use when you want to create
687
+ a new type of subagent, set up task-specific agents, configure code reviewers,
688
+ debuggers, or domain-specific assistants with custom prompts.
689
+ disable-model-invocation: true
690
+ ---
691
+ # Creating Custom Subagents
692
+
693
+ This skill guides you through creating custom subagents for Cursor. Subagents are specialized AI assistants that run in isolated contexts with custom system prompts.
694
+
695
+ ## When to Use Subagents
111
696
 
697
+ Subagents help you:
698
+ - **Preserve context** by isolating exploration from your main conversation
699
+ - **Specialize behavior** with focused system prompts for specific domains
700
+ - **Reuse configurations** across projects with user-level subagents
112
701
 
702
+ ### Inferring from Context
113
703
 
114
- # Onboarding Client Path (No CMS) Complete Version
704
+ If you have previous conversation context, infer the subagent's purpose and behavior from what was discussed. Create the subagent based on specialized tasks or workflows that emerged in the conversation.
115
705
 
116
- **Target:** Frontend Developers & Data Entry staff who **do not** use the CMS (Studio/ICE). The site acts as a **client**: data comes from local JSON, APIs, or an external CMS; you are responsible for layout, design, and rendering.
706
+ ## Subagent Locations
117
707
 
118
- **Spec Reference:** JSONPAGES Architecture v1.2 only the parts regarding site structure, components, and data. You ignore: Studio, ICE, Form Factory, IDAC, TOCC, AddSectionConfig, and mandatory schemas for the editor.
708
+ | Location | Scope | Priority |
709
+ |----------|-------|----------|
710
+ | `.cursor/agents/` | Current project | Higher |
711
+ | `~/.cursor/agents/` | All your projects | Lower |
119
712
 
713
+ When multiple subagents share the same name, the higher-priority location wins.
714
+
715
+ **Project subagents** (`.cursor/agents/`): Ideal for codebase-specific agents. Check into version control to share with your team.
716
+
717
+ **User subagents** (`~/.cursor/agents/`): Personal agents available across all your projects.
718
+
719
+ ## Subagent File Format
720
+
721
+ Create a `.md` file with YAML frontmatter and a markdown body (the system prompt):
722
+
723
+ ```markdown
120
724
  ---
725
+ name: code-reviewer
726
+ description: Reviews code for quality and best practices
727
+ ---
728
+
729
+ You are a code reviewer. When invoked, analyze the code and provide
730
+ specific, actionable feedback on quality, security, and best practices.
731
+ ```
732
+
733
+ ### Required Fields
734
+
735
+ | Field | Description |
736
+ |-------|-------------|
737
+ | `name` | Unique identifier (lowercase letters and hyphens only) |
738
+ | `description` | When to delegate to this subagent (be specific!) |
121
739
 
122
- ## 1. Your Role (Summary)
740
+ ## Writing Effective Descriptions
123
741
 
124
- - **Visuals:** Layout and styling of sections (View + CSS / design tokens).
125
- - **Data:** Where pages get their data (JSON files, API, external CMS) and how they are passed to the engine (config + pages).
742
+ The description is **critical** - the AI uses it to decide when to delegate.
126
743
 
127
- You **do not** need to: type everything for the editor, expose Zod schemas to the Form Factory, handle Studio overlays, Add Section logic, etc. You can use minimal types or even `unknown`/`any` on data if strong type-safety is not required.
744
+ ```yaml
745
+ # ❌ Too vague
746
+ description: Helps with code
128
747
 
748
+ # ✅ Specific and actionable
749
+ description: Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code.
750
+ ```
751
+
752
+ Include "use proactively" to encourage automatic delegation.
753
+
754
+ ## Example Subagents
755
+
756
+ ### Code Reviewer
757
+
758
+ ```markdown
129
759
  ---
760
+ name: code-reviewer
761
+ description: Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code.
762
+ ---
763
+
764
+ You are a senior code reviewer ensuring high standards of code quality and security.
765
+
766
+ When invoked:
767
+ 1. Run git diff to see recent changes
768
+ 2. Focus on modified files
769
+ 3. Begin review immediately
770
+
771
+ Review checklist:
772
+ - Code is clear and readable
773
+ - Functions and variables are well-named
774
+ - No duplicated code
775
+ - Proper error handling
776
+ - No exposed secrets or API keys
777
+ - Input validation implemented
778
+ - Good test coverage
779
+ - Performance considerations addressed
780
+
781
+ Provide feedback organized by priority:
782
+ - Critical issues (must fix)
783
+ - Warnings (should fix)
784
+ - Suggestions (consider improving)
785
+
786
+ Include specific examples of how to fix issues.
787
+ ```
130
788
 
131
- ## 2. Project Structure (Minimal)
789
+ ### Debugger
132
790
 
133
- - **`src/data/config/site.json`** — Identity, header, footer (blocks with `id`, `type`, `data`, `settings`).
134
- - **`src/data/config/menu.json`** — Menu (e.g., `{ main: [{ label, href }] }`).
135
- - **`src/data/config/theme.json`** — (Optional) Theme tokens (colors, fonts, radius).
136
- - **`src/data/pages/<slug>.json`** One page = `slug`, `meta`, `sections[]` (array of blocks `id`, `type`, `data`, `settings`). **To create a new page**, simply add a `<slug>.json` file in `src/data/pages/`; the filename slug becomes the page path (e.g., `about-us.json` → `/about-us`).
137
- - **`src/components/<sectionType>/`** — One folder per block type (hero, header, footer, feature-grid, …).
138
- - **`src/App.tsx`** — Loads site, menu, theme, pages; builds the config; renders **`<JsonPagesEngine config={config} />`**.
791
+ ```markdown
792
+ ---
793
+ name: debugger
794
+ description: Debugging specialist for errors, test failures, and unexpected behavior. Use proactively when encountering any issues.
795
+ ---
139
796
 
140
- The Engine (Core) still expects a **registry** (type → component map) and **pages** in the expected format (slug → page with `sections`). How you populate the JSONs (manually, via script, from another CMS) is outside the editor's scope.
797
+ You are an expert debugger specializing in root cause analysis.
798
+
799
+ When invoked:
800
+ 1. Capture error message and stack trace
801
+ 2. Identify reproduction steps
802
+ 3. Isolate the failure location
803
+ 4. Implement minimal fix
804
+ 5. Verify solution works
805
+
806
+ Debugging process:
807
+ - Analyze error messages and logs
808
+ - Check recent code changes
809
+ - Form and test hypotheses
810
+ - Add strategic debug logging
811
+ - Inspect variable states
812
+
813
+ For each issue, provide:
814
+ - Root cause explanation
815
+ - Evidence supporting the diagnosis
816
+ - Specific code fix
817
+ - Testing approach
818
+ - Prevention recommendations
819
+
820
+ Focus on fixing the underlying issue, not the symptoms.
821
+ ```
141
822
 
142
- **Why this matters (Structure):** Paths and shape (site, menu, theme, pages with sections) are the minimal contract the Core uses for routing and rendering; respecting them allows you to switch data sources (JSON → API) later without rewriting logic. See Spec §2 (JSP), Appendix A.4.
823
+ ### Data Scientist
143
824
 
825
+ ```markdown
826
+ ---
827
+ name: data-scientist
828
+ description: Data analysis expert for SQL queries, BigQuery operations, and data insights. Use proactively for data analysis tasks and queries.
144
829
  ---
145
830
 
146
- ## 3. Components (View Only)
831
+ You are a data scientist specializing in SQL and BigQuery analysis.
832
+
833
+ When invoked:
834
+ 1. Understand the data analysis requirement
835
+ 2. Write efficient SQL queries
836
+ 3. Use BigQuery command line tools (bq) when appropriate
837
+ 4. Analyze and summarize results
838
+ 5. Present findings clearly
839
+
840
+ Key practices:
841
+ - Write optimized SQL queries with proper filters
842
+ - Use appropriate aggregations and joins
843
+ - Include comments explaining complex logic
844
+ - Format results for readability
845
+ - Provide data-driven recommendations
846
+
847
+ For each analysis:
848
+ - Explain the query approach
849
+ - Document any assumptions
850
+ - Highlight key findings
851
+ - Suggest next steps based on data
852
+
853
+ Always ensure queries are efficient and cost-effective.
854
+ ```
855
+
856
+ ## Subagent Creation Workflow
857
+
858
+ ### Step 1: Decide the Scope
859
+
860
+ - **Project-level** (`.cursor/agents/`): For codebase-specific agents shared with team
861
+ - **User-level** (`~/.cursor/agents/`): For personal agents across all projects
862
+
863
+ ### Step 2: Create the File
864
+
865
+ ```bash
866
+ # For project-level
867
+ mkdir -p .cursor/agents
868
+ touch .cursor/agents/my-agent.md
869
+
870
+ # For user-level
871
+ mkdir -p ~/.cursor/agents
872
+ touch ~/.cursor/agents/my-agent.md
873
+ ```
147
874
 
148
- - Every **section type** has at least one **View**: it receives `data` and, if needed, `settings`. The header also receives `menu` (array of `{ label, href }`).
149
- - **No "Full Capsule" requirement:** you can have just `View.tsx` (and maybe an `index.ts` exporting the View). Zod schemas and types are only needed if you want dev-time type-safety or plan to activate the CMS later.
150
- - **Styles:** You can use "free" Tailwind classes or a set of CSS variables (e.g., `--local-bg`, `--local-text`) for consistency. CIP specs (variables only, no naked utilities) are for the Governance path; here you can adapt to your conventions.
151
- - **Assets:** If the Core exposes `resolveAssetUrl(path, tenantId)`, use it for images; otherwise, use relative paths or absolute URLs.
875
+ ### Step 3: Define Configuration
152
876
 
153
- **Why this matters (Components):** The registry must have a component for every `type` used in the JSONs; the View must receive `data` (and `settings`/`menu` where expected) so the Core can render without knowing details. Without a registry consistent with data, the engine wouldn't know what to mount. See Spec §3 (TBP), §4 (CIP) for the full path.
877
+ Write the frontmatter with the required fields (`name` and `description`).
154
878
 
879
+ ### Step 4: Write the System Prompt
880
+
881
+ The body becomes the system prompt. Be specific about:
882
+ - What the agent should do when invoked
883
+ - The workflow or process to follow
884
+ - Output format and structure
885
+ - Any constraints or guidelines
886
+
887
+ ### Step 5: Test the Agent
888
+
889
+ Ask the AI to use your new agent:
890
+
891
+ ```
892
+ Use the my-agent subagent to [task description]
893
+ ```
894
+
895
+ ## Best Practices
896
+
897
+ 1. **Design focused subagents**: Each should excel at one specific task
898
+ 2. **Write detailed descriptions**: Include trigger terms so the AI knows when to delegate
899
+ 3. **Check into version control**: Share project subagents with your team
900
+ 4. **Use proactive language**: Include "use proactively" in descriptions
901
+
902
+ ## Troubleshooting
903
+
904
+ ### Subagent Not Found
905
+ - Ensure file is in `.cursor/agents/` or `~/.cursor/agents/`
906
+ - Check file has `.md` extension
907
+ - Verify YAML frontmatter syntax is valid
908
+
909
+ END_OF_FILE_CONTENT
910
+ mkdir -p ".cursor/skills-cursor/jsonpages-tenant"
911
+ echo "Creating .cursor/skills-cursor/jsonpages-tenant/SKILL.md..."
912
+ cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/jsonpages-tenant/SKILL.md"
913
+ ---
914
+ name: jsonpages-tenant
915
+ description: Use when working on a JsonPages tenant, transforming the base tenant DNA into a branded tenant, adding or modifying tenant sections, maintaining schema-driven editability, or reasoning about what belongs to @jsonpages/core versus the tenant.
916
+ ---
917
+
918
+ # JsonPages Tenant
919
+
920
+ Use this skill for work on the JsonPages ecosystem when the task involves:
921
+
922
+ - a tenant generated from the JsonPages CLI
923
+ - `@jsonpages/core`
924
+ - tenant sections/capsules
925
+ - `src/data/pages/**/*.json` or `src/data/config/*.json`
926
+ - schema-driven editing and inspector compatibility
927
+ - generator scripts that turn a base tenant into a branded tenant
928
+
929
+ Read code first. Treat documents as secondary unless they help interpret code that is otherwise ambiguous.
930
+
931
+ ## Core Model
932
+
933
+ JsonPages has a hard split between `core` and `tenant`.
934
+
935
+ - `@jsonpages/core` owns routing, `/admin`, `/admin/preview`, preview stage, studio state, inspector/form factory, and shared engine behavior.
936
+ - The tenant owns sections, schemas, type augmentation, page/config JSON, theme/design layer, and local workflow scripts.
937
+ - The tenant does not implement the CMS. It implements the tenant protocol consumed by the engine.
938
+
939
+ In this ecosystem, code is the source of truth.
940
+
941
+ Compliance priority:
942
+
943
+ 1. Data is bound correctly.
944
+ 2. Schemas describe fields correctly.
945
+ 3. Content is editable without breaking the inspector.
946
+ 4. Tenant structure stays standardized.
947
+ 5. Context-aware focus/highlight in the legacy admin is desirable but secondary.
948
+
949
+ ## Canonical References
950
+
951
+ Use these local references when available:
952
+
953
+ - Base tenant DNA: `\\wsl.localhost\Ubuntu\home\dev\temp\alpha`
954
+ - Custom tenant reference: `\\wsl.localhost\Ubuntu\home\dev\temp\gptgiorgio`
955
+ - Core engine: `\\wsl.localhost\Ubuntu\home\dev\npm-jpcore\packages\core`
956
+ - Generator example: `\\wsl.localhost\Ubuntu\home\dev\temp\clonark\generate_olon.sh`
957
+
958
+ If these paths are missing, infer the same roles from the current workspace:
959
+
960
+ - base CLI-generated tenant
961
+ - branded tenant
962
+ - core package
963
+ - generator script
964
+
965
+ ## Tenant Anatomy
966
+
967
+ Expect these files to move together:
968
+
969
+ - `src/components/<section>/View.tsx`
970
+ - `src/components/<section>/schema.ts`
971
+ - `src/components/<section>/types.ts`
972
+ - `src/components/<section>/index.ts`
973
+ - `src/lib/ComponentRegistry.tsx`
974
+ - `src/lib/schemas.ts`
975
+ - `src/lib/addSectionConfig.ts`
976
+ - `src/types.ts`
977
+ - `src/data/pages/**/*.json`
978
+ - `src/data/config/site.json`
979
+ - `src/data/config/theme.json`
980
+ - `src/data/config/menu.json`
981
+
982
+ Useful rule: if a section type changes, check all of the files above before concluding the task is done.
983
+
984
+ ## What Good Work Looks Like
985
+
986
+ A good tenant change:
987
+
988
+ - stays inside tenant boundaries unless the issue is truly in `@jsonpages/core`
989
+ - keeps schema, defaults, registry, and type augmentation aligned
990
+ - preserves editability for strings, lists, nested objects, CTAs, and image fields
991
+ - uses `ImageSelectionSchema`-style image fields when the content is image-driven
992
+ - keeps page content JSON-first
993
+
994
+ A suspicious tenant change:
995
+
996
+ - patches the core to fix a tenant modeling problem
997
+ - adds visual complexity without data bindings
998
+ - introduces fields into JSON that are not represented in schema
999
+ - changes a section view without updating defaults or types
1000
+ - optimizes legacy context awareness at the expense of simpler, reliable editability
1001
+
1002
+ ## Workflow 1: Base Tenant -> Branded Tenant
1003
+
1004
+ This is the primary workflow.
1005
+
1006
+ Goal:
1007
+
1008
+ - transform a CLI-generated base tenant into a branded tenant through a single generator script
1009
+
1010
+ Treat the generator script as procedural source of truth for the green build workflow.
1011
+
1012
+ When maintaining or authoring a generator:
1013
+
1014
+ 1. Separate non-deterministic bootstrap from deterministic sync.
1015
+ 2. Make explicit which files are managed output.
1016
+ 3. Keep the script aligned with the current tenant code, not with stale docs.
1017
+ 4. Preserve tenant protocol files: sections, schemas, registries, type augmentation, config JSON, assets, shims.
1018
+ 5. Prefer deterministic local writes after any remote/bootstrap step.
1019
+
1020
+ Typical structure of a good generator:
1021
+
1022
+ - preflight checks
1023
+ - remote/bootstrap steps such as `shadcn` or external registries
1024
+ - deterministic creation/sync of tenant files
1025
+ - compatibility patches for known unstable upstream payloads
1026
+ - final validation commands
1027
+
1028
+ When asked to update a branded tenant generator:
1029
+
1030
+ 1. Diff base tenant against branded tenant.
1031
+ 2. Classify differences into:
1032
+ - intended branded output
1033
+ - reusable generator logic
1034
+ - accidental drift
1035
+ 3. Encode only the reusable intended differences into the script.
1036
+ 4. Keep the output reproducible from a fresh base tenant.
1037
+
1038
+ ## Workflow 2: Add Or Change A Section
1039
+
1040
+ When adding a new section type:
1041
+
1042
+ 1. Create `View.tsx`, `schema.ts`, `types.ts`, `index.ts`.
1043
+ 2. Register the section in `src/lib/ComponentRegistry.tsx`.
1044
+ 3. Register the schema in `src/lib/schemas.ts`.
1045
+ 4. Add defaults and label in `src/lib/addSectionConfig.ts`.
1046
+ 5. Extend `SectionComponentPropsMap` and module augmentation in `src/types.ts`.
1047
+ 6. Add or update page JSON using the new section type.
1048
+
1049
+ When changing an existing section:
1050
+
1051
+ 1. Read the section schema first.
1052
+ 2. Read the page JSON using it.
1053
+ 3. Check the view for `data-jp-field` usage and binding shape.
1054
+ 4. Update defaults if the data shape changed.
1055
+ 5. Verify the inspector still has a path to edit the content.
1056
+
1057
+ ## Workflow 3: Images, Rich Content, Nested Routes
1058
+
1059
+ Images:
1060
+
1061
+ - Prefer structured image objects compatible with tenant base schemas.
1062
+ - Assume the core supports image picking and upload flows.
1063
+ - The tenant is responsible for declaring image fields in schema and rendering them coherently.
1064
+
1065
+ Rich editorial content:
1066
+
1067
+ - Tiptap-style sections are tenant-level integrations.
1068
+ - Treat page JSON using `type: "tiptap"` as runtime usage examples, and section code as the real source of truth.
1069
+
1070
+ Nested routes:
1071
+
1072
+ - Files under `src/data/pages/**/*.json` may represent nested slugs.
1073
+ - Preserve slug/path consistency and do not replace file-based routing with manual lists.
1074
+
1075
+ ## Decision Rules
1076
+
1077
+ Use `alpha` patterns when the task is about:
1078
+
1079
+ - tenant DNA
1080
+ - capability reference
1081
+ - baseline protocol shape
1082
+ - proving what the base system already supports
1083
+
1084
+ Use `gptgiorgio` patterns when the task is about:
1085
+
1086
+ - stronger branded frontend customization
1087
+ - richer domain-specific sections
1088
+ - image-heavy schema design
1089
+ - proving how far customization can go without changing the bootstrap
1090
+
1091
+ Do not treat `gptgiorgio` as canonical for legacy admin context awareness.
1092
+
1093
+ ## Default Operating Procedure
1094
+
1095
+ When you receive a JsonPages tenant task:
1096
+
1097
+ 1. Identify whether the problem belongs to `core`, tenant, or generator.
1098
+ 2. Read the smallest code surface that proves it.
1099
+ 3. Prefer fixing the tenant contract before touching visual polish.
1100
+ 4. Keep generated and deterministic workflows reproducible.
1101
+ 5. State assumptions when inferring intended branded output from examples.
1102
+
1103
+ END_OF_FILE_CONTENT
1104
+ mkdir -p ".cursor/skills-cursor/migrate-to-skills"
1105
+ echo "Creating .cursor/skills-cursor/migrate-to-skills/SKILL.md..."
1106
+ cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/migrate-to-skills/SKILL.md"
1107
+ ---
1108
+ name: migrate-to-skills
1109
+ description: >-
1110
+ Convert 'Applied intelligently' Cursor rules (.cursor/rules/*.mdc) and slash
1111
+ commands (.cursor/commands/*.md) to Agent Skills format (.cursor/skills/). Use
1112
+ when you want to migrate rules or commands to skills, convert .mdc rules to
1113
+ SKILL.md format, or consolidate commands into the skills directory.
1114
+ disable-model-invocation: true
155
1115
  ---
1116
+ # Migrate Rules and Slash Commands to Skills
1117
+
1118
+ Convert Cursor rules ("Applied intelligently") and slash commands to Agent Skills format.
1119
+
1120
+ **CRITICAL: Preserve the exact body content. Do not modify, reformat, or "improve" it - copy verbatim.**
156
1121
 
157
- ## 3.1 Images and Image Fields (If using Schema later)
1122
+ ## Locations
158
1123
 
159
- If you later add Zod schemas for type-safety or to activate Studio, **image fields** must be modeled as follows:
1124
+ | Level | Source | Destination |
1125
+ |-------|--------|-------------|
1126
+ | Project | `{workspaceFolder}/**/.cursor/rules/*.mdc`, `{workspaceFolder}/.cursor/commands/*.md` |
1127
+ | User | `~/.cursor/commands/*.md` |
160
1128
 
161
- - **Schema:** The image field is an **object** (not a string) with at least `url` and optionally `alt`. This object's schema must be marked with **`.describe('ui:image-picker')`** so the Form Factory (Inspector) shows the Image Picker widget. Example: a sub-schema `ImageSelectionSchema = z.object({ url: z.string(), alt: z.string().optional() }).describe('ui:image-picker')` used as `image: ImageSelectionSchema.default({ url: '', alt: '' })`.
162
- - **View:** For the image `src`, use **`resolveAssetUrl(data.image.url, tenantId)`**; on the node representing the image, set **`data-jp-field="image"`** (so the Inspector binds the field correctly).
1129
+ Notes:
1130
+ - Cursor rules inside the project can live in nested directories. Be thorough in your search and use glob patterns to find them.
1131
+ - Ignore anything in ~/.cursor/worktrees
1132
+ - Ignore anything in ~/.cursor/skills-cursor. This is reserved for Cursor's internal built-in skills and is managed automatically by the system.
163
1133
 
164
- **Reference:** See the `image-break` component in `apps/tenant-alpha/src/components/image-break/` (schema.ts, View.tsx) for a complete example.
1134
+ ## Finding Files to Migrate
165
1135
 
1136
+ **Rules**: Migrate if rule has a `description` but NO `globs` and NO `alwaysApply: true`.
1137
+
1138
+ **Commands**: Migrate all - they're plain markdown without frontmatter.
1139
+
1140
+ ## Conversion Format
1141
+
1142
+ ### Rules: .mdc → SKILL.md
1143
+
1144
+ ```markdown
1145
+ # Before: .cursor/rules/my-rule.mdc
1146
+ ---
1147
+ description: What this rule does
1148
+ globs:
1149
+ alwaysApply: false
166
1150
  ---
1151
+ # Title
1152
+ Body content...
1153
+ ```
167
1154
 
168
- ## 4. Data: Where it comes from
1155
+ ```markdown
1156
+ # After: .cursor/skills/my-rule/SKILL.md
1157
+ ---
1158
+ name: my-rule
1159
+ description: What this rule does
1160
+ ---
1161
+ # Title
1162
+ Body content...
1163
+ ```
169
1164
 
170
- - **Local JSONs only:** Read `site.json`, `menu.json`, `theme.json`, `pages/*.json` and pass them into `config` (siteConfig, menuConfig, themeConfig, pages). No CMS.
171
- - **External CMS / API:** Instead of importing JSONs, fetch (or SSR) and build the same objects (siteConfig, menuConfig, pages) and pass them to `JsonPagesEngine`. The page shape remains: `{ slug, meta?, sections[] }`; each section: `{ id, type, data, settings? }`.
172
- - **Hybrid:** Header/footer from `site.json`, body from API or another CMS: build a single `pages[slug]` with `sections` that respect the block types you have in the registry.
1165
+ Changes: Add `name` field, remove `globs`/`alwaysApply`, keep body exactly.
173
1166
 
174
- You do not need to register schemas or AddSectionConfig unless you activate Studio.
1167
+ ### Commands: .md SKILL.md
175
1168
 
176
- **Why this matters (Data):** The `sections[]` shape with `id`, `type`, `data`, `settings?` is what the SectionRenderer and Core expect; maintaining this shape even when data comes from an API or another CMS avoids fragile adapters and allows activating Studio later without redoing data. See Spec Appendix A.2 (PageConfig, SiteConfig, MenuConfig).
1169
+ ```markdown
1170
+ # Before: .cursor/commands/commit.md
1171
+ # Commit current work
1172
+ Instructions here...
1173
+ ```
177
1174
 
1175
+ ```markdown
1176
+ # After: .cursor/skills/commit/SKILL.md
178
1177
  ---
1178
+ name: commit
1179
+ description: Commit current work with standardized message format
1180
+ disable-model-invocation: true
1181
+ ---
1182
+ # Commit current work
1183
+ Instructions here...
1184
+ ```
179
1185
 
180
- ## 5. Registry and Config (Minimal)
181
-
182
- - **Registry:** An object mapping every `sectionType` (string) to the React component rendering that type. E.g.: `{ header: Header, footer: Footer, hero: Hero, ... }`. If not using Studio, you can type loosely (e.g., `Record<string, React.FC<any>>` or whatever is compatible with `JsonPagesConfig['registry']`).
183
- - **Config passed to JsonPagesEngine:**
184
- `tenantId`, `registry`, `pages`, `siteConfig`, `menuConfig`, `themeConfig` (or empty object), `themeCss: { tenant: cssString }`.
185
- If you are **not** using Studio, **schemas** and **addSection** can be placeholders (empty object / no-op) if the Core allows it; otherwise, provide the minimum (e.g., schemas = `{}`, addSection = `{ addableSectionTypes: [], sectionTypeLabels: {}, getDefaultSectionData: () => ({}) }`) to prevent engine errors.
1186
+ Changes: Add frontmatter with `name` (from filename), `description` (infer from content), and `disable-model-invocation: true`, keep body exactly.
186
1187
 
187
- Check docs or `JsonPagesConfig` type to see if `schemas` and `addSection` are optional when Studio is unused.
1188
+ **Note:** The `disable-model-invocation: true` field prevents the model from automatically invoking this skill. Slash commands are designed to be explicitly triggered by the user via the `/` menu, not automatically suggested by the model.
188
1189
 
189
- **Why this matters (Registry & Config):** The Core must resolve every section to a component (registry) and have pages, site, menu, theme, and tenant CSS to render and, if needed, inject the Stage iframe; mandatory config fields are the minimum to make the engine work. Placeholders for schemas/addSection avoid errors when Studio is not used. See Spec §10 (JEB), Appendix A.
1190
+ ## Notes
190
1191
 
191
- ---
1192
+ - `name` must be lowercase with hyphens only
1193
+ - `description` is critical for skill discovery
1194
+ - Optionally delete originals after verifying migration works
192
1195
 
193
- ## 6. Quick Checklist (Visual Dev & Data, No CMS)
1196
+ ### Migrate a Rule (.mdc SKILL.md)
194
1197
 
195
- | Item | Action |
196
- |------|--------|
197
- | **Layout / Visuals** | Implement Views (one per section type) and styles (CSS / Tailwind / variables). |
198
- | **Data** | Decide source (Local JSON, API, other CMS); build `siteConfig`, `menuConfig`, `pages` in the expected shape and pass to `config`. |
199
- | **Registry** | Map every block type used in JSONs to the corresponding component. |
200
- | **Header / Menu** | Header component receives `data`, `settings`, `menu`; `menu` comes from `menuConfig` (e.g., `menuConfig.main`). |
201
- | **Pages** | Each page = one entry in `pages` with `sections[]`; each section has `id`, `type`, `data`, `settings?`. |
202
- | **New Page** | Add a `<slug>.json` file in `src/data/pages/` (slug becomes page path). |
203
- | **Image (if schema)** | Image field = object `{ url, alt? }` with schema `.describe('ui:image-picker')`; View uses `resolveAssetUrl` and `data-jp-field="image"`. |
204
- | **Studio / ICE** | Not used: no mandatory schemas, no data-jp-*, no overlay CSS, no Add Section. |
1198
+ 1. Read the rule file
1199
+ 2. Extract the `description` from the frontmatter
1200
+ 3. Extract the body content (everything after the closing `---` of the frontmatter)
1201
+ 4. Create the skill directory: `.cursor/skills/{skill-name}/` (skill name = filename without .mdc)
1202
+ 5. Write `SKILL.md` with new frontmatter (`name` and `description`) + the EXACT original body content (preserve all whitespace, formatting, code blocks verbatim)
1203
+ 6. Delete the original rule file
205
1204
 
206
- ---
1205
+ ### Migrate a Command (.md → SKILL.md)
207
1206
 
208
- ## 7. Switching to the "Governance" Path
1207
+ 1. Read the command file
1208
+ 2. Extract description from the first heading (remove `#` prefix)
1209
+ 3. Create the skill directory: `.cursor/skills/{skill-name}/` (skill name = filename without .md)
1210
+ 4. Write `SKILL.md` with new frontmatter (`name`, `description`, and `disable-model-invocation: true`) + blank line + the EXACT original file content (preserve all whitespace, formatting, code blocks verbatim)
1211
+ 5. Delete the original command file
209
1212
 
210
- If you later want the editor (Studio) and governance (types, schema, Add Section, overlay): use the onboarding guide **02-Onboarding_Governance.md** and align the project with types, full capsules (View + schema + types), IDAC, TOCC, AddSectionConfig, and Appendix A of Spec v1.2.
1213
+ **CRITICAL: Copy the body content character-for-character. Do not reformat, fix typos, or "improve" anything.**
211
1214
 
1215
+ ## Workflow
212
1216
 
213
- END_OF_FILE_CONTENT
214
- echo "Creating docs/02-Onboarding_Governance_CMS.md..."
215
- cat << 'END_OF_FILE_CONTENT' > "docs/02-Onboarding_Governance_CMS.md"
1217
+ If you have the Task tool available:
1218
+ DO NOT start to read all of the files yourself. That function should be delegated to the subagents. Your job is to dispatch the subagents for each category of files and wait for the results.
216
1219
 
217
- # Onboarding Governance Path (With CMS) Complete Version
1220
+ 1. [ ] Create the skills directories if they don't exist (`.cursor/skills/` for project, `~/.cursor/skills/` for user)
1221
+ 2. Dispatch three fast general purpose subagents (NOT explore) in parallel to do the following steps for project rules (pattern: `{workspaceFolder}/**/.cursor/rules/*.mdc`), user commands (pattern: `~/.cursor/commands/*.md`), and project commands (pattern: `{workspaceFolder}/**/.cursor/commands/*.md`):
1222
+ I. [ ] Find files to migrate in the given pattern
1223
+ II. [ ] For rules, check if it's an "applied intelligently" rule (has `description`, no `globs`, no `alwaysApply: true`). Commands are always migrated. DO NOT use the terminal to read files. Use the read tool.
1224
+ III. [ ] Make a list of files to migrate. If empty, done.
1225
+ IV. [ ] For each file, read it, then write the new skill file preserving the body content EXACTLY. DO NOT use the terminal to write these files. Use the edit tool.
1226
+ V. [ ] Delete the original file. DO NOT use the terminal to delete these files. Use the delete tool.
1227
+ VI. [ ] Return a list of all the skill files that were migrated along with the original file paths.
1228
+ 3. [ ] Wait for all subagents to complete and summarize the results to the user. IMPORTANT: Make sure to let them know if they want to undo the migration, to ask you to.
1229
+ 4. [ ] If the user asks you to undo the migration, do the opposite of the above steps to restore the original files.
218
1230
 
219
- **Target:** Lead Developers & Architects setting up the **CMS** (Studio, ICE, Form Factory): in-app authoring, strong typing, content and component governance.
220
1231
 
221
- **Spec Reference:** OlonJS Architecture Specifications v1.2 (legacy alias: JSONPAGES) + Appendix A — Tenant Type & Code-Generation Annex.
1232
+ If you don't have the Task tool available:
1233
+ 1. [ ] Create the skills directories if they don't exist (`.cursor/skills/` for project, `~/.cursor/skills/` for user)
1234
+ 2. [ ] Find files to migrate in both project (`.cursor/`) and user (`~/.cursor/`) directories
1235
+ 3. [ ] For rules, check if it's an "applied intelligently" rule (has `description`, no `globs`, no `alwaysApply: true`). Commands are always migrated. DO NOT use the terminal to read files. Use the read tool.
1236
+ 4. [ ] Make a list of files to migrate. If empty, done.
1237
+ 5. [ ] For each file, read it, then write the new skill file preserving the body content EXACTLY. DO NOT use the terminal to write these files. Use the edit tool.
1238
+ 6. [ ] Delete the original file. DO NOT use the terminal to delete these files. Use the delete tool.
1239
+ 7. [ ] Summarize the results to the user. IMPORTANT: Make sure to let them know if they want to undo the migration, to ask you to.
1240
+ 8. [ ] If the user asks you to undo the migration, do the opposite of the above steps to restore the original files.
222
1241
 
1242
+ END_OF_FILE_CONTENT
1243
+ mkdir -p ".cursor/skills-cursor/olonjs"
1244
+ echo "Creating .cursor/skills-cursor/olonjs/SKILL.md..."
1245
+ cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/olonjs/SKILL.md"
1246
+ ---
1247
+ name: olonjs-tenant
1248
+ description: Use when working on a OlonJS tenant, transforming the base tenant DNA into a branded tenant, adding or modifying tenant sections, maintaining schema-driven editability, or reasoning about what belongs to @olonjs/core versus the tenant.
223
1249
  ---
224
1250
 
225
- ## 1. What "Governance" Implies
1251
+ # OlonJS Tenant
226
1252
 
227
- - **Types:** Every section type is declared in `SectionDataRegistry` / `SectionSettingsRegistry` (module augmentation) and in `SectionComponentPropsMap`. Registry and config are strictly typed.
228
- - **Schema:** Every section type has a Zod schema (data, and optionally settings) used by the Form Factory to generate the editor in the Inspector. Schemas are aggregated in `SECTION_SCHEMAS`.
229
- - **Studio/ICE:** The editor (Inspector) hooks into the DOM via **data-jp-field** and **data-jp-item-id** / **data-jp-item-field**. The selection overlay in the iframe requires the **tenant** to provide the CSS (TOCC).
230
- - **Add Section:** The tenant exposes **AddSectionConfig** (addable types, labels, default data) so the user can add sections from the library in Studio.
231
- - **Design Tokens:** Views use CSS variables (`--local-*`) and no "naked" utilities (CIP) for consistency and compatibility with themes and overlays.
1253
+ Use this skill for work on the OlonJS ecosystem when the task involves:
232
1254
 
233
- **Why this matters (Summary):** Types and schemas allow the Core and Form Factory to operate without knowing Tenant details; IDAC allows the Inspector to link Stage clicks to the active row in the sidebar (including active/inactive opacity); TOCC makes the overlay visible; AddSectionConfig defines the "Add Section" library; tokens and z-index avoid conflicts with the editing UI. Detailed "Whys" for each spec: see Spec v1.2 (§1–§10, JAP, Appendix A).
1255
+ - a tenant generated from the OlonJS CLI
1256
+ - `@olonjs/core`
1257
+ - tenant sections/capsules
1258
+ - `src/data/pages/**/*.json` or `src/data/config/*.json`
1259
+ - schema-driven editing and inspector compatibility
1260
+ - generator scripts that turn a base tenant into a branded tenant
234
1261
 
235
- ---
1262
+ Read code first. Treat documents as secondary unless they help interpret code that is otherwise ambiguous.
236
1263
 
237
- ## 1.1 The Value of Typing: Governance vs. CMS UX
1264
+ ## Architecture Specifications
238
1265
 
239
- Typing (TypeScript types + Zod schema) serves **two levels**: Governance (Developer/Architecture) and **CMS UX** (Author using Studio).
1266
+ Use this document as the architectural laws for each tenant, compliancy will be tested against these specs:
240
1267
 
241
- **Governance:** Typed registry, SectionComponentPropsMap, SiteConfig/PageConfig shape, audits, code-generation → consistency across tenants, no drift, safe refactoring, spec-based tooling.
1268
+ - `\\wsl.localhost\Ubuntu\home\dev\npm-jpcore\specs\olonjsSpecs_V.1.3.md`
242
1269
 
243
- **CMS UX:** The Zod schema drives the **Form Factory** (which widget for which field: text, textarea, select, list, icon-picker, **image-picker**); **data-jp-field** and **data-jp-item-id/field** bind Stage clicks to Inspector forms; **AddSectionConfig** provides addable types, labels, and defaults. Result for the author: consistent forms, "Add Section" with sensible names and initial data, correct selection (click → right form), validation with clear errors. Without schema and typed contracts, the Inspector wouldn't know which fields to show or how to validate. Thus: for governance, typing guarantees **contracts**; for CMS UX, it defines the **editing experience**. Both must be specified.
244
1270
 
245
- ---
246
1271
 
247
- ## 2. Project Structure (Complete)
248
-
249
- - **`src/data/config/site.json`** — SiteConfig (identity, pages[], header block, footer block).
250
- - **`src/data/config/menu.json`** — MenuConfig (e.g., `main: MenuItem[]`).
251
- - **`src/data/config/theme.json`** — ThemeConfig (tokens).
252
- - **`src/data/pages/<slug>.json`** — PageConfig (slug, meta, sections[]). **To create a new page**, simply add a `<slug>.json` file in `src/data/pages/`; the filename slug becomes the page path (e.g., `about-us.json` → `/about-us`).
253
- - **`src/components/<sectionType>/`** — **Full Capsule:** View.tsx, schema.ts, types.ts, index.ts.
254
- - **`src/lib/base-schemas.ts`** — BaseSectionData, BaseArrayItem, BaseSectionSettingsSchema.
255
- - **`src/lib/schemas.ts`** — SECTION_SCHEMAS (aggregate of data schemas per type) + export SectionType.
256
- - **`src/lib/ComponentRegistry.tsx`** — Typed Registry: `{ [K in SectionType]: React.FC<SectionComponentPropsMap[K]> }`.
257
- - **`src/lib/addSectionConfig.ts`** — AddSectionConfig (addableSectionTypes, sectionTypeLabels, getDefaultSectionData).
258
- - **`src/types.ts`** — SectionComponentPropsMap, PageConfig, SiteConfig, MenuConfig, ThemeConfig; **module augmentation** for SectionDataRegistry and SectionSettingsRegistry; re-export from `@olonjs/core`.
259
- - **`src/App.tsx`** — Bootstrap: config (tenantId, registry, schemas, pages, siteConfig, themeConfig, menuConfig, themeCss, addSection); `<JsonPagesEngine config={config} />`.
260
- - **Global CSS** — Includes TOCC selectors for overlay (hover/selected/type label).
261
1272
 
262
- ---
1273
+ ## Core Model
263
1274
 
264
- ## 3. Components (Capsules + IDAC + Tokens)
1275
+ OlonJS has a hard split between `core` and `tenant`.
265
1276
 
266
- - **Capsule:** Every section type has View, schema (Zod), types (inferred), index. The **data** schema extends BaseSectionData; array items extend BaseArrayItem.
267
- - **View:** Receives `data` and `settings` (and `menu` for header). Does not import Zod. Uses **only** CSS variables for colors/radii (e.g., `bg-[var(--local-bg)]`), root section with `z-index` ≤ 1.
268
- - **IDAC (ICE):** On every editable scalar field: **`data-jp-field="<fieldKey>"`**. On every editable array item: **`data-jp-item-id="<stableId>"`** and **`data-jp-item-field="<arrayKey>"`**. This allows the Inspector to bind selection and forms to the correct paths.
269
- - **Schema:** Use UI vocabulary (ECIP): `.describe('ui:text')`, `ui:textarea`, `ui:select`, `ui:number`, `ui:list`, `ui:icon-picker`, **`ui:image-picker`** (see §3.1). Editable object arrays: every object must have an `id` (BaseArrayItem).
1277
+ - `@olonjs/core` owns routing, `/admin`, `/admin/preview`, preview stage, studio state, inspector/form factory, and shared engine behavior.
1278
+ - The tenant owns sections, schemas, type augmentation, page/config JSON, theme/design layer, and local workflow scripts.
1279
+ - The tenant does not implement the CMS. It implements the tenant protocol consumed by the engine.
270
1280
 
271
- **Why this matters (Components):** **data-jp-field** and **data-jp-item-*** are needed because the Stage is in an iframe, and the Core needs to know which field/item corresponds to a click without knowing the Tenant's DOM: this allows the sidebar to highlight the active row (even with active/inactive opacity), open the form on the right field, and handle lists (reorder, delete). Without IDAC, clicks on the canvas are not reflected in the sidebar. Schema with `ui:*` and BaseArrayItem are needed for the Form Factory to generate the right widgets and maintain stable keys (reorder/delete). Tokens and z-index prevent content from covering the overlay. See Spec §6 (IDAC), §5 (ECIP), §4 (CIP).
1281
+ In this ecosystem, code is the source of truth.
272
1282
 
273
- ---
1283
+ Compliance priority:
274
1284
 
275
- ## 3.1 Image Picker: Correct Usage in Schema (Example `image-break`)
1285
+ 1. Data is bound correctly.
1286
+ 2. Schemas describe fields correctly.
1287
+ 3. Content is editable without breaking the inspector.
1288
+ 4. Tenant structure stays standardized.
1289
+ 5. Context-aware focus/highlight in the legacy admin is desirable but secondary.
276
1290
 
277
- For **image fields**, the Form Factory exposes the **Image Picker** widget only if the schema is modeled correctly.
1291
+ ## Canonical References
278
1292
 
279
- ### Rule
1293
+ Use these local references when available:
280
1294
 
281
- - The image field is not a **string** (`z.string()`), but an **object** with at least `url` and, optionally, `alt`.
282
- - The **schema of this object** (the sub-schema) must be marked with **`.describe('ui:image-picker')`**. The Form Factory recognizes `ui:image-picker` only on **ZodObject** (object schema), not on string fields.
1295
+ - Base tenant DNA: `\\wsl.localhost\Ubuntu\home\dev\temp\alpha`
1296
+ - Custom tenant reference: `\\wsl.localhost\Ubuntu\home\dev\temp\gptgiorgio`
1297
+ - Core engine: `\\wsl.localhost\Ubuntu\home\dev\npm-jpcore\packages\core`
1298
+ - Generator example: `\\wsl.localhost\Ubuntu\home\dev\temp\clonark\generate_olon.sh`
283
1299
 
284
- ### Example (`image-break` capsule)
1300
+ If these paths are missing, infer the same roles from the current workspace:
285
1301
 
286
- **Schema (`schema.ts`):**
1302
+ - base CLI-generated tenant
1303
+ - branded tenant
1304
+ - core package
1305
+ - generator script
287
1306
 
288
- ```ts
289
- import { z } from 'zod';
290
- import { BaseSectionData } from '@/lib/base-schemas';
1307
+ ## Tenant Anatomy
291
1308
 
292
- const ImageSelectionSchema = z
293
- .object({
294
- url: z.string(),
295
- alt: z.string().optional(),
296
- })
297
- .describe('ui:image-picker');
1309
+ Expect these files to move together:
298
1310
 
299
- export const ImageBreakSchema = BaseSectionData.extend({
300
- label: z.string().optional().describe('ui:text'),
301
- image: ImageSelectionSchema.default({ url: '', alt: '' }),
302
- caption: z.string().optional().describe('ui:textarea'),
303
- });
304
- ```
1311
+ - `src/components/<section>/View.tsx`
1312
+ - `src/components/<section>/schema.ts`
1313
+ - `src/components/<section>/types.ts`
1314
+ - `src/components/<section>/index.ts`
1315
+ - `src/lib/ComponentRegistry.tsx`
1316
+ - `src/lib/schemas.ts`
1317
+ - `src/lib/addSectionConfig.ts`
1318
+ - `src/types.ts`
1319
+ - `src/data/pages/**/*.json`
1320
+ - `src/data/config/site.json`
1321
+ - `src/data/config/theme.json`
1322
+ - `src/data/config/menu.json`
305
1323
 
306
- - **ImageSelectionSchema** is a `z.object({ url, alt })` with **`.describe('ui:image-picker')`** on the object.
307
- - The **`image`** field in the section data uses that schema (with default), so the Inspector shows the Image Picker widget for `image`.
1324
+ Useful rule: if a section type changes, check all of the files above before concluding the task is done.
308
1325
 
309
- **View (`View.tsx`):**
1326
+ ## What Good Work Looks Like
310
1327
 
311
- - For the image `src`: **`resolveAssetUrl(data.image.url, tenantId)`** (multi-tenant and relative paths).
312
- - On the node representing the image (e.g., the `<img>` or a wrapper): **`data-jp-field="image"`** so the Stage click binds the Inspector to the `image` field.
313
- - Other editable fields (caption, label) with **`data-jp-field="caption"`** and **`data-jp-field="label"`** where appropriate.
1328
+ A good tenant change:
314
1329
 
315
- **Full Reference:** `apps/tenant-alpha/src/components/image-break/` (schema.ts, types.ts, View.tsx, index.ts).
1330
+ - stays inside tenant boundaries unless the issue is truly in `@olonjs/core`
1331
+ - keeps schema, defaults, registry, and type augmentation aligned
1332
+ - preserves editability for strings, lists, nested objects, CTAs, and image fields
1333
+ - uses `ImageSelectionSchema`-style image fields when the content is image-driven
1334
+ - keeps page content JSON-first
316
1335
 
317
- ### What to Avoid
1336
+ A suspicious tenant change:
318
1337
 
319
- - **Do not** use `.describe('ui:image-picker')` on a **string** field (e.g., `imageUrl: z.string().describe('ui:image-picker')`): the Image Picker widget expects an object `{ url, alt? }`.
320
- - **Do not** forget `data-jp-field="image"` on the corresponding DOM node, otherwise Inspector ↔ Stage binding won't work for that field.
1338
+ - patches the core to fix a tenant modeling problem
1339
+ - adds visual complexity without data bindings
1340
+ - introduces fields into JSON that are not represented in schema
1341
+ - changes a section view without updating defaults or types
1342
+ - optimizes legacy context awareness at the expense of simpler, reliable editability
321
1343
 
322
- ---
1344
+ ## Workflow 1: Base Tenant -> Branded Tenant
323
1345
 
324
- ## 4. Data: Shape and Responsibility
1346
+ This is the primary workflow.
325
1347
 
326
- - **site.json / menu.json / theme.json / pages/*.json** — Exact shape as in Appendix A (SiteConfig, MenuConfig, ThemeConfig, PageConfig). These are the Source of Truth when the user saves from Studio (Working Draft → persist to these files or API generating them).
327
- - **Studio** updates the Working Draft; sync with the iframe and "Bake" use the same structure. Therefore, data passed to JsonPagesEngine (siteConfig, menuConfig, pages) must be compatible with what the editor modifies.
1348
+ Goal:
328
1349
 
329
- If data comes from an external CMS, you must synchronize: e.g., export from Studio → push to CMS, or CMS as source and Studio in read-only; in any case, the **shape** of pages (sections with id, type, data, settings) remains that of the spec.
1350
+ - transform a CLI-generated base tenant into a branded tenant through a single generator script
330
1351
 
331
- ---
1352
+ Treat the generator script as procedural source of truth for the green build workflow.
332
1353
 
333
- ## 5. Registry, Schemas, Types, AddSection
1354
+ When maintaining or authoring a generator:
334
1355
 
335
- - **types.ts:** Single point of **module augmentation** and definition of SectionComponentPropsMap, PageConfig, SiteConfig, MenuConfig, ThemeConfig. Header: `{ data, settings?, menu: MenuItem[] }`; all others: `{ data, settings? }`.
336
- - **ComponentRegistry:** Every SectionType key has the corresponding component; type: `{ [K in SectionType]: React.FC<SectionComponentPropsMap[K]> }`.
337
- - **SECTION_SCHEMAS:** Every SectionType key has the **data Zod schema** (same order as registry). Base schemas re-exported from base-schemas.ts.
338
- - **addSectionConfig:** addableSectionTypes (only types the user can add from the library), sectionTypeLabels, getDefaultSectionData(type) returning valid `data` for that schema.
1356
+ 1. Separate non-deterministic bootstrap from deterministic sync.
1357
+ 2. Make explicit which files are managed output.
1358
+ 3. Keep the script aligned with the current tenant code, not with stale docs.
1359
+ 4. Preserve tenant protocol files: sections, schemas, registries, type augmentation, config JSON, assets, shims.
1360
+ 5. Prefer deterministic local writes after any remote/bootstrap step.
339
1361
 
340
- **Why this matters (registry, schemas, types, addSection):** A single augmentation point (types.ts) and a single SECTION_SCHEMAS avoid duplication and ensure registry, Form Factory, and config use the same types. AddSectionConfig is the single source of truth for "which sections can be added" and "with what defaults"; without it, the "Add Section" modal wouldn't have valid names or initial data. See Spec §9 (ASC), Appendix A.2–A.3.
1362
+ Typical structure of a good generator:
341
1363
 
342
- ---
1364
+ - preflight checks
1365
+ - remote/bootstrap steps such as `shadcn` or external registries
1366
+ - deterministic creation/sync of tenant files
1367
+ - compatibility patches for known unstable upstream payloads
1368
+ - final validation commands
343
1369
 
344
- ## 6. Overlay and CSS (TOCC)
1370
+ When asked to update a branded tenant generator:
345
1371
 
346
- - The Core injects the overlay markup (wrapper with `data-section-id`, sibling with `data-jp-section-overlay`). The **tenant** must provide the CSS so that:
347
- - `[data-jp-section-overlay]` covers the section, `pointer-events: none`, high z-index (e.g., 9999).
348
- - Hover and selected states are visible (dashed/solid border, optional tint).
349
- - The type label (e.g., `[data-jp-section-overlay] > div`) is positioned and visible on hover/selected.
1372
+ 1. Diff base tenant against branded tenant.
1373
+ 2. Classify differences into:
1374
+ - intended branded output
1375
+ - reusable generator logic
1376
+ - accidental drift
1377
+ 3. Encode only the reusable intended differences into the script.
1378
+ 4. Keep the output reproducible from a fresh base tenant.
350
1379
 
351
- Without this, the overlay is invisible in the Studio iframe.
1380
+ ## Workflow 2: Add Or Change A Section
352
1381
 
353
- **Why this matters (TOCC):** The Stage iframe loads only Tenant CSS; the Core injects overlay markup but not styles. Without TOCC selectors in Tenant CSS, hover/selected borders and type labels are invisible: the author cannot see which section is selected. See Spec §7 (TOCC).
1382
+ When adding a new section type:
354
1383
 
355
- ---
1384
+ 1. Create `View.tsx`, `schema.ts`, `types.ts`, `index.ts`.
1385
+ 2. Register the section in `src/lib/ComponentRegistry.tsx`.
1386
+ 3. Register the schema in `src/lib/schemas.ts`.
1387
+ 4. Add defaults and label in `src/lib/addSectionConfig.ts`.
1388
+ 5. Extend `SectionComponentPropsMap` and module augmentation in `src/types.ts`.
1389
+ 6. Add or update page JSON using the new section type.
356
1390
 
357
- ## 7. Quick Checklist (Visual Dev & Data, With CMS)
358
-
359
- | Item | Action |
360
- |------|--------|
361
- | **Layout / Visuals** | View with `--local-*` variables, z-index ≤ 1, no naked utilities. |
362
- | **Data (Shape)** | SiteConfig, MenuConfig, ThemeConfig, PageConfig as in Appendix A; JSON in `data/config` and `data/pages`. |
363
- | **Capsules** | View + schema (with `ui:*`) + types + index; data schema extends BaseSectionData; array item with id. |
364
- | **IDAC** | `data-jp-field` on editable scalar fields; `data-jp-item-id` and `data-jp-item-field` on array items. |
365
- | **types.ts** | SectionComponentPropsMap (header with menu), augmentation, PageConfig, SiteConfig, MenuConfig, ThemeConfig. |
366
- | **Registry** | All types mapped to component; registry type as in Appendix A. |
367
- | **SECTION_SCHEMAS** | One entry per type (data schema); re-export base schemas. |
368
- | **addSectionConfig** | addableSectionTypes, sectionTypeLabels, getDefaultSectionData. |
369
- | **Config** | tenantId, registry, schemas, pages, siteConfig, themeConfig, menuConfig, themeCss, addSection. |
370
- | **TOCC** | CSS overlay for `[data-jp-section-overlay]`, hover, selected, type label. |
1391
+ When changing an existing section:
371
1392
 
372
- ---
1393
+ 1. Read the section schema first.
1394
+ 2. Read the page JSON using it.
1395
+ 3. Check the view for `data-jp-field` usage and binding shape.
1396
+ 4. Update defaults if the data shape changed.
1397
+ 5. Verify the inspector still has a path to edit the content.
373
1398
 
374
- ## 8. Spec References
1399
+ ## Workflow 3: Images, Rich Content, Nested Routes
375
1400
 
376
- - **Architecture and ICE:** §1–§10 (MTRP, JSP, TBP, CIP, ECIP, IDAC, TOCC, BSDS, ASC, JEB).
377
- - **Types and Code-Generation:** Appendix A (Core types, Tenant types, Schema contract, File paths, Integration checklist).
378
- - **Admin:** JAP (Studio topology, Working Draft, Bake, overlay, Green Build).
1401
+ Images:
379
1402
 
380
- Using this path gives you full **governance**: types, schema, editor, Add Section, and overlay aligned with Spec v1.2. For versions with all "Why this matters" explanations, use the file **JSONPAGES_Specs_v1.2_completo.md**.
1403
+ - Prefer structured image objects compatible with tenant base schemas.
1404
+ - Assume the core supports image picking and upload flows.
1405
+ - The tenant is responsible for declaring image fields in schema and rendering them coherently.
381
1406
 
382
- --- END OF FILE docs/02-Onboarding_Governance.md ---
383
- END_OF_FILE_CONTENT
384
- echo "Creating docs/02-Onboarding_Governance_completo_aggiornato.md..."
385
- cat << 'END_OF_FILE_CONTENT' > "docs/02-Onboarding_Governance_completo_aggiornato.md"
386
- # Onboarding — Percorso Governance (con CMS) — Versione completa
1407
+ Rich editorial content:
387
1408
 
388
- **Per chi:** Sviluppo grafico e dati quando vuoi il **CMS** (Studio, ICE, Form Factory): authoring in-app, tipizzazione forte, governance dei contenuti e dei componenti.
1409
+ - Tiptap-style sections are tenant-level integrations.
1410
+ - Treat page JSON using `type: "tiptap"` as runtime usage examples, and section code as the real source of truth.
389
1411
 
390
- **Riferimento spec:** OlonJS Architecture Specifications v1.2 (legacy alias: JSONPAGES) + Appendix A — Tenant Type & Code-Generation Annex.
1412
+ Nested routes:
391
1413
 
392
- ---
1414
+ - Files under `src/data/pages/**/*.json` may represent nested slugs.
1415
+ - Preserve slug/path consistency and do not replace file-based routing with manual lists.
393
1416
 
394
- ## 1. Cosa implica "governance"
1417
+ ## Decision Rules
395
1418
 
396
- - **Tipi:** Ogni section type è dichiarato in `SectionDataRegistry` / `SectionSettingsRegistry` (module augmentation) e in `SectionComponentPropsMap`. Registry e config sono tipizzati.
397
- - **Schema:** Ogni section type ha uno schema Zod (data, e opzionalmente settings) usato dal Form Factory per generare l'editor nell'Inspector. Gli schema sono aggregati in `SECTION_SCHEMAS`.
398
- - **Studio/ICE:** L'editor (Inspector) si aggancia al DOM tramite **data-jp-field** e **data-jp-item-id** / **data-jp-item-field**. L'overlay di selezione in iframe richiede che il **tenant** fornisca il CSS (TOCC).
399
- - **Add Section:** Il tenant espone **AddSectionConfig** (tipi addabili, label, default data) così in Studio l'utente può aggiungere section dalla libreria.
400
- - **Design tokens:** Le View usano variabili CSS (`--local-*`) e nessuna utility "nuda" (CIP) per coerenza e compatibilità con tema e overlay.
1419
+ Use `alpha` patterns when the task is about:
401
1420
 
402
- **Perché servono (in sintesi):** Tipi e schema permettono al Core e al Form Factory di operare senza conoscere i dettagli del Tenant; IDAC permette all'Inspector di legare click in Stage e riga attiva nella sidebar (inclusa opacità attivo/inattivo); TOCC rende visibile l'overlay; AddSectionConfig definisce la libreria "Aggiungi sezione"; token e z-index evitano conflitti con l'UI di editing. Dettaglio sui "perché" per ogni specifica: spec v1.2 (§1–§10, JAP, Appendix A), dove ogni sezione ha un paragrafo **Perché servono**.
1421
+ - tenant DNA
1422
+ - capability reference
1423
+ - baseline protocol shape
1424
+ - proving what the base system already supports
403
1425
 
404
- ---
1426
+ Use `gptgiorgio` patterns when the task is about:
405
1427
 
406
- ## 1.1 Valore della tipizzazione: governance e CMS UX
1428
+ - stronger branded frontend customization
1429
+ - richer domain-specific sections
1430
+ - image-heavy schema design
1431
+ - proving how far customization can go without changing the bootstrap
407
1432
 
408
- La tipizzazione (tipi TypeScript + schema Zod) serve a **due livelli**: governance (sviluppatore/architettura) e **UX del CMS** (autore che usa Studio). Spesso si menziona solo il primo.
1433
+ Do not treat `gptgiorgio` as canonical for legacy admin context awareness.
409
1434
 
410
- **Governance:** registry tipizzato, SectionComponentPropsMap, forma di SiteConfig/PageConfig, audit, code-generation → coerenza tra tenant, niente drift, refactor sicuro, tooling basato su spec.
1435
+ ## Default Operating Procedure
411
1436
 
412
- **CMS UX:** lo schema Zod guida il **Form Factory** (quali widget per ogni campo: text, textarea, select, list, icon-picker, **image-picker**); **data-jp-field** e **data-jp-item-id/field** legano click in Stage e form nell'Inspector; **AddSectionConfig** dà tipi addabili, label e default. Risultato per l'autore: form coerenti, "Aggiungi sezione" con nomi e dati iniziali sensati, selezione corretta (click → form giusto), validazione con errori chiari. Senza schema e contratto tipizzato l'Inspector non saprebbe quali campi mostrare né come validare. Quindi: per la governance la tipizzazione garantisce contratti; per la **CMS UX** definisce l'**esperienza di editing** (controlli, label, default, binding). Va specificato entrambi.
1437
+ When you receive a OlonJS tenant task:
413
1438
 
1439
+ 1. Identify whether the problem belongs to `core`, tenant, or generator.
1440
+ 2. Read the smallest code surface that proves it.
1441
+ 3. Prefer fixing the tenant contract before touching visual polish.
1442
+ 4. Keep generated and deterministic workflows reproducible.
1443
+ 5. State assumptions when inferring intended branded output from examples.
1444
+
1445
+ END_OF_FILE_CONTENT
1446
+ # SKIP: .cursor/skills-cursor/olonjs/SKILL.md:Zone.Identifier is binary and cannot be embedded as text.
1447
+ mkdir -p ".cursor/skills-cursor/shell"
1448
+ echo "Creating .cursor/skills-cursor/shell/SKILL.md..."
1449
+ cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/shell/SKILL.md"
414
1450
  ---
1451
+ name: shell
1452
+ description: >-
1453
+ Runs the rest of a /shell request as a literal shell command. Use only when
1454
+ the user explicitly invokes /shell and wants the following text executed
1455
+ directly in the terminal.
1456
+ disable-model-invocation: true
1457
+ ---
1458
+ # Run Shell Commands
415
1459
 
416
- ## 2. Struttura progetto (completa)
417
-
418
- - **`src/data/config/site.json`** — SiteConfig (identity, pages[], header block, footer block).
419
- - **`src/data/config/menu.json`** — MenuConfig (es. `main: MenuItem[]`).
420
- - **`src/data/config/theme.json`** — ThemeConfig (tokens).
421
- - **`src/data/pages/<slug>.json`** — PageConfig (slug, meta, sections[]). **Per creare una nuova pagina** basta aggiungere un file `<slug>.json` in `src/data/pages/`; lo slug del nome file diventa il path della pagina (es. `chi-siamo.json` → `/chi-siamo`).
422
- - **`src/components/<sectionType>/`** — **Capsula piena:** View.tsx, schema.ts, types.ts, index.ts.
423
- - **`src/lib/base-schemas.ts`** — BaseSectionData, BaseArrayItem, BaseSectionSettingsSchema.
424
- - **`src/lib/schemas.ts`** — SECTION_SCHEMAS (aggregato degli schema data per tipo) + export SectionType.
425
- - **`src/lib/ComponentRegistry.tsx`** — Registry tipizzato: `{ [K in SectionType]: React.FC<SectionComponentPropsMap[K]> }`.
426
- - **`src/lib/addSectionConfig.ts`** — AddSectionConfig (addableSectionTypes, sectionTypeLabels, getDefaultSectionData).
427
- - **`src/types.ts`** — SectionComponentPropsMap, PageConfig, SiteConfig, MenuConfig, ThemeConfig; **module augmentation** per SectionDataRegistry e SectionSettingsRegistry; re-export da `@olonjs/core`.
428
- - **`src/App.tsx`** — Bootstrap: config (tenantId, registry, schemas, pages, siteConfig, themeConfig, menuConfig, themeCss, addSection); `<JsonPagesEngine config={config} />`.
429
- - **CSS globale** — Include i selettori TOCC per overlay (hover/selected/type label).
1460
+ Use this skill only when the user explicitly invokes `/shell`.
430
1461
 
431
- ---
1462
+ ## Behavior
432
1463
 
433
- ## 3. Componenti (capsule + IDAC + token)
1464
+ 1. Treat all user text after the `/shell` invocation as the literal shell command to run.
1465
+ 2. Execute that command immediately with the terminal tool.
1466
+ 3. Do not rewrite, explain, or "improve" the command before running it.
1467
+ 4. Do not inspect the repository first unless the command itself requires repository context.
1468
+ 5. If the user invokes `/shell` without any following text, ask them which command to run.
434
1469
 
435
- - **Capsula:** Ogni section type ha View, schema (Zod), types (inferiti), index. Lo schema **data** estende BaseSectionData; gli item degli array estendono BaseArrayItem.
436
- - **View:** Riceve `data` e `settings` (e `menu` per header). Non importa Zod. Usa **solo** variabili CSS per colori/raggi (es. `bg-[var(--local-bg)]`), sezione root con `z-index` ≤ 1.
437
- - **IDAC (ICE):** Su ogni campo editabile in modo scalare: **`data-jp-field="<fieldKey>"`**. Su ogni item di array editabile: **`data-jp-item-id="<stableId>"`** e **`data-jp-item-field="<arrayKey>"`**. Così l'Inspector può legare selezione e form ai path corretti.
438
- - **Schema:** Usa il vocabolario UI (ECIP): `.describe('ui:text')`, `ui:textarea`, `ui:select`, `ui:number`, `ui:list`, `ui:icon-picker`, **`ui:image-picker`** (vedi §3.1). Array di oggetti editabili: ogni oggetto con `id` (BaseArrayItem).
1470
+ ## Response
439
1471
 
440
- **Perché servono (componenti):** **data-jp-field** e **data-jp-item-*** servono perché lo Stage è in un iframe e il Core deve sapere quale campo/item corrisponde al click senza conoscere il DOM del Tenant: così la sidebar può evidenziare la riga attiva (anche con opacità diversa per attivo/inattivo), aprire il form sul campo giusto e gestire liste (reorder, delete). Senza IDAC, click sul canvas non si riflette nella sidebar. Schema con `ui:*` e BaseArrayItem servono al Form Factory per generare i widget giusti e mantenere chiavi stabili (reorder/delete). Token e z-index evitano che il contenuto copra l'overlay. Vedi spec §6 (IDAC), §5 (ECIP), §4 (CIP).
1472
+ - Run the command first.
1473
+ - Then briefly report the exit status and any important stdout or stderr.
441
1474
 
1475
+ END_OF_FILE_CONTENT
1476
+ mkdir -p ".cursor/skills-cursor/update-cursor-settings"
1477
+ echo "Creating .cursor/skills-cursor/update-cursor-settings/SKILL.md..."
1478
+ cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/update-cursor-settings/SKILL.md"
442
1479
  ---
1480
+ name: update-cursor-settings
1481
+ description: >-
1482
+ Modify Cursor/VSCode user settings in settings.json. Use when you want to
1483
+ change editor settings, preferences, configuration, themes, font size, tab
1484
+ size, format on save, auto save, keybindings, or any settings.json values.
1485
+ ---
1486
+ # Updating Cursor Settings
443
1487
 
444
- ## 3.1 Image Picker: uso corretto nello schema (esempio `image-break`)
445
-
446
- Per i **campi immagine** il Form Factory espone il widget **Image Picker** solo se lo schema è modellato correttamente.
1488
+ This skill guides you through modifying Cursor/VSCode user settings. Use this when you want to change editor settings, preferences, configuration, themes, keybindings, or any `settings.json` values.
447
1489
 
448
- ### Regola
1490
+ ## Settings File Location
449
1491
 
450
- - Il campo immagine non è una **stringa** (`z.string()`), ma un **oggetto** con almeno `url` e, opzionalmente, `alt`.
451
- - Lo **schema di questo oggetto** (il sub-schema) va marcato con **`.describe('ui:image-picker')`**. Il Form Factory riconosce `ui:image-picker` solo su **ZodObject** (schema oggetto), non su campi stringa.
1492
+ | OS | Path |
1493
+ |----|------|
1494
+ | macOS | ~/Library/Application Support/Cursor/User/settings.json |
1495
+ | Linux | ~/.config/Cursor/User/settings.json |
1496
+ | Windows | %APPDATA%\Cursor\User\settings.json |
452
1497
 
453
- ### Esempio (capsula `image-break`)
1498
+ ## Before Modifying Settings
454
1499
 
455
- **Schema (`schema.ts`):**
1500
+ 1. **Read the existing settings file** to understand current configuration
1501
+ 2. **Preserve existing settings** - only add/modify what the user requested
1502
+ 3. **Validate JSON syntax** before writing to avoid breaking the editor
456
1503
 
457
- ```ts
458
- import { z } from 'zod';
459
- import { BaseSectionData } from '@/lib/base-schemas';
1504
+ ## Modifying Settings
460
1505
 
461
- const ImageSelectionSchema = z
462
- .object({
463
- url: z.string(),
464
- alt: z.string().optional(),
465
- })
466
- .describe('ui:image-picker');
1506
+ ### Step 1: Read Current Settings
467
1507
 
468
- export const ImageBreakSchema = BaseSectionData.extend({
469
- label: z.string().optional().describe('ui:text'),
470
- image: ImageSelectionSchema.default({ url: '', alt: '' }),
471
- caption: z.string().optional().describe('ui:textarea'),
472
- });
1508
+ ```typescript
1509
+ // Read the settings file first
1510
+ const settingsPath = "~/Library/Application Support/Cursor/User/settings.json";
1511
+ // Use the Read tool to get current contents
473
1512
  ```
474
1513
 
475
- - **ImageSelectionSchema** è un `z.object({ url, alt })` con **`.describe('ui:image-picker')`** sull'oggetto.
476
- - Il campo **`image`** nella section data usa quel schema (con default) così l'Inspector mostra il widget Image Picker per `image`.
1514
+ ### Step 2: Identify the Setting to Change
477
1515
 
478
- **View (`View.tsx`):**
1516
+ Common setting categories:
1517
+ - **Editor**: `editor.fontSize`, `editor.tabSize`, `editor.wordWrap`, `editor.formatOnSave`
1518
+ - **Workbench**: `workbench.colorTheme`, `workbench.iconTheme`, `workbench.sideBar.location`
1519
+ - **Files**: `files.autoSave`, `files.exclude`, `files.associations`
1520
+ - **Terminal**: `terminal.integrated.fontSize`, `terminal.integrated.shell.*`
1521
+ - **Cursor-specific**: Settings prefixed with `cursor.` or `aipopup.`
479
1522
 
480
- - Per il `src` dell'immagine: **`resolveAssetUrl(data.image.url, tenantId)`** (multi-tenant e path relativi).
481
- - Sul nodo che rappresenta l'immagine (es. il `<img>` o un wrapper): **`data-jp-field="image"`** così il click in Stage lega l'Inspector al campo `image`.
482
- - Altri campi editabili (caption, label) con **`data-jp-field="caption"`** e **`data-jp-field="label"`** dove appropriato.
1523
+ ### Step 3: Update the Setting
483
1524
 
484
- **Riferimento completo:** `apps/tenant-alpha/src/components/image-break/` (schema.ts, types.ts, View.tsx, index.ts).
1525
+ When modifying settings.json:
1526
+ 1. Parse the existing JSON (handle comments - VSCode settings support JSON with comments)
1527
+ 2. Add or update the requested setting
1528
+ 3. Preserve all other existing settings
1529
+ 4. Write back with proper formatting (2-space indentation)
485
1530
 
486
- ### Cosa evitare
1531
+ ### Example: Changing Font Size
487
1532
 
488
- - **Non** usare `.describe('ui:image-picker')` su un campo **stringa** (es. `imageUrl: z.string().describe('ui:image-picker')`): il widget Image Picker si aspetta un oggetto `{ url, alt? }`.
489
- - **Non** dimenticare `data-jp-field="image"` sul nodo corrispondente nel DOM, altrimenti il binding Inspector ↔ Stage non funziona per quel campo.
1533
+ If user says "make the font bigger":
490
1534
 
491
- ---
492
-
493
- ## 4. Dati: forma e responsabilità
494
-
495
- - **site.json / menu.json / theme.json / pages/*.json** — Forma esatta come in Appendix A (SiteConfig, MenuConfig, ThemeConfig, PageConfig). Sono la source of truth quando l'utente salva da Studio (Working Draft → persist su questi file o su API che li generano).
496
- - **Studio** aggiorna il Working Draft; il sync con l'iframe e il "Bake" usano la stessa struttura. Quindi i dati che passi a JsonPagesEngine (siteConfig, menuConfig, pages) devono essere compatibili con ciò che l'editor modifica.
1535
+ ```json
1536
+ {
1537
+ "editor.fontSize": 16
1538
+ }
1539
+ ```
497
1540
 
498
- Se i dati arrivano da un CMS esterno, tocca a te sincronizzare: es. export da Studio → push su CMS, oppure CMS come source e Studio in read-only; in ogni caso la **forma** delle pagine (sections con id, type, data, settings) resta quella della spec.
1541
+ ### Example: Enabling Format on Save
499
1542
 
500
- ---
1543
+ If user says "format my code when I save":
501
1544
 
502
- ## 5. Registry, schemas, types, addSection
1545
+ ```json
1546
+ {
1547
+ "editor.formatOnSave": true
1548
+ }
1549
+ ```
503
1550
 
504
- - **types.ts:** Unico punto di **module augmentation** e definizione di SectionComponentPropsMap, PageConfig, SiteConfig, MenuConfig, ThemeConfig. Header: `{ data, settings?, menu: MenuItem[] }`; tutti gli altri: `{ data, settings? }`.
505
- - **ComponentRegistry:** Ogni chiave di SectionType ha il componente corrispondente; tipo: `{ [K in SectionType]: React.FC<SectionComponentPropsMap[K]> }`.
506
- - **SECTION_SCHEMAS:** Ogni chiave di SectionType ha lo **schema Zod della data** (stesso ordine del registry). Base schemas re-exportati da base-schemas.ts.
507
- - **addSectionConfig:** addableSectionTypes (solo i tipi che l'utente può aggiungere dalla libreria), sectionTypeLabels, getDefaultSectionData(type) che restituisce `data` valido per quello schema.
1551
+ ### Example: Changing Theme
508
1552
 
509
- **Perché servono (registry, schemas, types, addSection):** Un solo punto di augmentation (types.ts) e un solo SECTION_SCHEMAS evita duplicazioni e garantisce che registry, Form Factory e config usino gli stessi tipi. AddSectionConfig è l'unica fonte di verità per "quali section si possono aggiungere" e "con quali default"; senza, il modal "Aggiungi sezione" non avrebbe nomi né dati iniziali validi. Vedi spec §9 (ASC), Appendix A.2–A.3.
1553
+ If user says "use dark theme" or "change my theme":
510
1554
 
511
- ---
1555
+ ```json
1556
+ {
1557
+ "workbench.colorTheme": "Default Dark Modern"
1558
+ }
1559
+ ```
512
1560
 
513
- ## 6. Overlay e CSS (TOCC)
1561
+ ## Important Notes
514
1562
 
515
- - Il Core inietta il markup dell'overlay (wrapper con `data-section-id`, sibling con `data-jp-section-overlay`). Il **tenant** deve fornire il CSS in modo che:
516
- - `[data-jp-section-overlay]` copra la section, `pointer-events: none`, z-index alto (es. 9999).
517
- - Hover e selected siano visibili (bordo tratteggiato / pieno, eventuale tint).
518
- - Il type label (es. `[data-jp-section-overlay] > div`) sia posizionato e visibile su hover/selected.
1563
+ 1. **JSON with Comments**: VSCode/Cursor settings.json supports comments (`//` and `/* */`). When reading, be aware comments may exist. When writing, preserve comments if possible.
519
1564
 
520
- Senza questo, in Studio l'overlay non si vede nell'iframe.
1565
+ 2. **Restart May Be Required**: Some settings take effect immediately, others require reloading the window or restarting Cursor. Inform the user if a restart is needed.
521
1566
 
522
- **Perché servono (TOCC):** L'iframe dello Stage carica solo il CSS del Tenant; il Core inietta il markup dell'overlay ma non gli stili. Senza i selettori TOCC nel CSS tenant, bordo hover/selected e type label non sono visibili: l'autore non vede quale section è selezionata. Vedi spec §7 (TOCC).
1567
+ 3. **Backup**: For significant changes, consider mentioning the user can undo via Ctrl/Cmd+Z in the settings file or by reverting git changes if tracked.
523
1568
 
524
- ---
1569
+ 4. **Workspace vs User Settings**:
1570
+ - User settings (what this skill covers): Apply globally to all projects
1571
+ - Workspace settings (`.vscode/settings.json`): Apply only to the current project
525
1572
 
526
- ## 7. Checklist rapida (sviluppo grafico e dati, con CMS)
527
-
528
- | Cosa | Azione |
529
- |------|--------|
530
- | **Layout / grafico** | View con variabili `--local-*`, z-index ≤ 1, nessuna utility naked. |
531
- | **Dati (forma)** | SiteConfig, MenuConfig, ThemeConfig, PageConfig come in Appendix A; JSON in `data/config` e `data/pages`. |
532
- | **Nuova pagina** | Aggiungere un file `<slug>.json` in `src/data/pages/` (lo slug diventa il path della pagina). |
533
- | **Capsule** | View + schema (con ui:*) + types + index; data schema estende BaseSectionData; array item con id. |
534
- | **IDAC** | data-jp-field su campi scalari editabili; data-jp-item-id e data-jp-item-field su item di array. |
535
- | **Image Picker** | Campo immagine = oggetto `{ url, alt? }` con sub-schema `.describe('ui:image-picker')`; View con `resolveAssetUrl` e `data-jp-field="image"`. Esempio: `image-break`. |
536
- | **types.ts** | SectionComponentPropsMap (header con menu), augmentation, PageConfig, SiteConfig, MenuConfig, ThemeConfig. |
537
- | **Registry** | Tutti i tipi mappati al componente; tipo registry come in Appendix A. |
538
- | **SECTION_SCHEMAS** | Un entry per tipo (schema data); re-export base schemas. |
539
- | **addSectionConfig** | addableSectionTypes, sectionTypeLabels, getDefaultSectionData. |
540
- | **Config** | tenantId, registry, schemas, pages, siteConfig, themeConfig, menuConfig, themeCss, addSection. |
541
- | **TOCC** | CSS overlay per [data-jp-section-overlay], hover, selected, type label. |
1573
+ 5. **Commit Attribution**: When the user asks about commit attribution, clarify whether they want to edit the **CLI agent** or the **IDE agent**. For the CLI agent, modify `~/.cursor/cli-config.json`. For the IDE agent, it is controlled from the UI at **Cursor Settings > Agent > Attribution** (not settings.json).
542
1574
 
543
- ---
1575
+ ## Common User Requests → Settings
544
1576
 
545
- ## 8. Riferimenti spec
1577
+ | User Request | Setting |
1578
+ |--------------|---------|
1579
+ | "bigger/smaller font" | `editor.fontSize` |
1580
+ | "change tab size" | `editor.tabSize` |
1581
+ | "format on save" | `editor.formatOnSave` |
1582
+ | "word wrap" | `editor.wordWrap` |
1583
+ | "change theme" | `workbench.colorTheme` |
1584
+ | "hide minimap" | `editor.minimap.enabled` |
1585
+ | "auto save" | `files.autoSave` |
1586
+ | "line numbers" | `editor.lineNumbers` |
1587
+ | "bracket matching" | `editor.bracketPairColorization.enabled` |
1588
+ | "cursor style" | `editor.cursorStyle` |
1589
+ | "smooth scrolling" | `editor.smoothScrolling` |
546
1590
 
547
- - **Architettura e ICE:** §1–§10 (MTRP, JSP, TBP, CIP, ECIP, IDAC, TOCC, BSDS, ASC, JEB).
548
- - **Tipi e code-generation:** Appendix A (Core types, Tenant types, Schema contract, File paths, Integration checklist).
549
- - **Admin:** JAP (Studio topology, Working Draft, Bake, overlay, Green Build).
1591
+ ## Workflow
550
1592
 
551
- Usando questo percorso hai **governance** piena: tipi, schema, editor, Add Section e overlay allineati alle spec v1.2. Per le versioni con tutti i "Perché servono" usa il file **JSONPAGES_Specs_v1.2_completo.md**.
1593
+ 1. Read ~/Library/Application Support/Cursor/User/settings.json
1594
+ 2. Parse the JSON content
1595
+ 3. Add/modify the requested setting(s)
1596
+ 4. Write the updated JSON back to the file
1597
+ 5. Inform the user the setting has been changed and whether a reload is needed
552
1598
 
553
1599
  END_OF_FILE_CONTENT
554
- mkdir -p "docs/ver"
555
1600
  echo "Creating index.html..."
556
1601
  cat << 'END_OF_FILE_CONTENT' > "index.html"
557
1602
  <!DOCTYPE html>
@@ -585,7 +1630,7 @@ cat << 'END_OF_FILE_CONTENT' > "package.json"
585
1630
  "dev:clean": "vite --force",
586
1631
  "prebuild": "node scripts/sync-pages-to-public.mjs",
587
1632
  "build": "tsc && vite build",
588
- "dist": "bash ./src2Code.sh --template alpha src vercel.json index.html vite.config.ts scripts docs package.json",
1633
+ "dist": "bash ./src2Code.sh --template alpha src .cursor vercel.json index.html vite.config.ts scripts specs package.json",
589
1634
  "preview": "vite preview",
590
1635
  "bake:email": "tsx scripts/bake-email.tsx",
591
1636
  "bakemail": "npm run bake:email --",
@@ -596,7 +1641,7 @@ cat << 'END_OF_FILE_CONTENT' > "package.json"
596
1641
  "@tiptap/extension-link": "^2.11.5",
597
1642
  "@tiptap/react": "^2.11.5",
598
1643
  "@tiptap/starter-kit": "^2.11.5",
599
- "@olonjs/core": "^1.0.75",
1644
+ "@olonjs/core": "^1.0.76",
600
1645
  "clsx": "^2.1.1",
601
1646
  "lucide-react": "^0.474.0",
602
1647
  "react": "^19.0.0",
@@ -916,6 +1961,615 @@ fs.cpSync(sourceDir, targetDir, { recursive: true });
916
1961
 
917
1962
  console.log('[sync-pages-to-public] Synced pages to public/pages');
918
1963
 
1964
+ END_OF_FILE_CONTENT
1965
+ mkdir -p "specs"
1966
+ echo "Creating specs/olonjsSpecs_V.1.3.md..."
1967
+ cat << 'END_OF_FILE_CONTENT' > "specs/olonjsSpecs_V.1.3.md"
1968
+ # 📐 OlonJS Architecture Specifications v1.3
1969
+
1970
+ **Status:** Mandatory Standard
1971
+ **Version:** 1.3.0 (Sovereign Core Edition — Architecture + Studio/ICE UX, Path-Deterministic Nested Editing)
1972
+ **Target:** Senior Architects / AI Agents / Enterprise Governance
1973
+
1974
+ **Scope v1.3:** This edition preserves the complete v1.2 architecture (MTRP, JSP, TBP, CIP, ECIP, JAP + Studio/ICE UX contract: IDAC, TOCC, BSDS, ASC, JEB + Tenant Type & Code-Generation Annex) as a **faithful superset**, and adds strict path-based/nested-array behavior for Studio selection and Inspector expansion.
1975
+ **Scope note (breaking):** In strict v1.3 Studio semantics, the legacy flat protocol (`itemField` / `itemId`) is removed in favor of `itemPath` (root-to-leaf path segments).
1976
+
1977
+ ---
1978
+
1979
+ ## 1. 📐 Modular Type Registry Pattern (MTRP) v1.2
1980
+
1981
+ **Objective:** Establish a strictly typed, open-ended protocol for extending content data structures where the **Core Engine** is the orchestrator and the **Tenant** is the provider.
1982
+
1983
+ ### 1.1 The Sovereign Dependency Inversion
1984
+ The **Core** defines the empty `SectionDataRegistry`. The **Tenant** "injects" its specific definitions using **Module Augmentation**. This allows the Core to be distributed as a compiled NPM package while remaining aware of Tenant-specific types at compile-time.
1985
+
1986
+ ### 1.2 Technical Implementation (`@olonjs/core/kernel`)
1987
+ ```typescript
1988
+ export interface SectionDataRegistry {} // Augmented by Tenant
1989
+ export interface SectionSettingsRegistry {} // Augmented by Tenant
1990
+
1991
+ export interface BaseSection<K extends keyof SectionDataRegistry> {
1992
+ id: string;
1993
+ type: K;
1994
+ data: SectionDataRegistry[K];
1995
+ settings?: K extends keyof SectionSettingsRegistry
1996
+ ? SectionSettingsRegistry[K]
1997
+ : BaseSectionSettings;
1998
+ }
1999
+
2000
+ export type Section = {
2001
+ [K in keyof SectionDataRegistry]: BaseSection<K>
2002
+ }[keyof SectionDataRegistry];
2003
+ ```
2004
+
2005
+ **SectionType:** Core exports (or Tenant infers) **`SectionType`** as **`keyof SectionDataRegistry`**. After Tenant module augmentation, this is the union of all section type keys (e.g. `'header' | 'footer' | 'hero' | ...`). The Tenant uses this type for the ComponentRegistry and SECTION_SCHEMAS keys.
2006
+
2007
+ **Perché servono:** Il Core deve poter renderizzare section senza conoscere i tipi concreti a compile-time; il Tenant deve poter aggiungere nuovi tipi senza modificare il Core. I registry vuoti + module augmentation permettono di distribuire Core come pacchetto NPM e mantenere type-safety end-to-end (Section, registry, config). Senza MTRP, ogni nuovo tipo richiederebbe cambi nel Core o tipi deboli (`any`).
2008
+
2009
+ ---
2010
+
2011
+ ## 2. 📐 JsonPages Site Protocol (JSP) v1.8
2012
+
2013
+ **Objective:** Define the deterministic file system and the **Sovereign Projection Engine** (CLI).
2014
+
2015
+ ### 2.1 The File System Ontology (The Silo Contract)
2016
+ Every site must reside in an isolated directory. Global Governance is physically separated from Local Content.
2017
+ * **`/config/site.json`** — Global Identity & Reserved System Blocks (Header/Footer). See Appendix A for typed shape.
2018
+ * **`/config/menu.json`** — Navigation Tree (SSOT for System Header). See Appendix A.
2019
+ * **`/config/theme.json`** — Theme tokens (optional but recommended). See Appendix A.
2020
+ * **`/pages/[slug].json`** — Local Body Content per page. See Appendix A (PageConfig).
2021
+
2022
+ **Application path convention:** The runtime app typically imports these via an alias (e.g. **`@/data/config/`** and **`@/data/pages/`**). The physical silo may be `src/data/config/` and `src/data/pages/` so that `site.json`, `menu.json`, `theme.json` live under `src/data/config/`, and page JSONs under `src/data/pages/`. The CLI or projection script may use `/config/` and `/pages/` at repo root; the **contract** is that the app receives **siteConfig**, **menuConfig**, **themeConfig**, and **pages** as defined in JEB (§10) and Appendix A.
2023
+
2024
+ ### 2.2 Deterministic Projection (CLI Workflow)
2025
+ The CLI (`@olonjs/cli`) creates new tenants by:
2026
+ 1. **Infra Projection:** Generating `package.json`, `tsconfig.json`, and `vite.config.ts` (The Shell).
2027
+ 2. **Source Projection:** Executing a deterministic script (`src_tenant_alpha.sh`) to reconstruct the `src` folder (The DNA).
2028
+ 3. **Dependency Resolution:** Enforcing specific versions of React, Radix, and Tailwind v4.
2029
+
2030
+ **Perché servono:** Una struttura file deterministica (config vs pages) separa governance globale (site, menu, theme) dal contenuto per pagina; il CLI può rigenerare tenant e tooling può trovare dati e schemi sempre negli stessi path. Senza JSP, ogni tenant sarebbe una struttura ad hoc e ingestione/export/Bake sarebbero fragili.
2031
+
2032
+ ---
2033
+
2034
+ ## 3. 🧱 Tenant Block Protocol (TBP) v1.0
2035
+
2036
+ **Objective:** Standardize the "Capsule" structure for components to enable automated ingestion (Pull) by the SaaS.
2037
+
2038
+ ### 3.1 The Atomic Capsule Structure
2039
+ Components are self-contained directories under **`src/components/<sectionType>/`**:
2040
+ * **`View.tsx`** — The pure React component (Dumb View). Props: see Appendix A (SectionComponentPropsMap).
2041
+ * **`schema.ts`** — Zod schema(s) for the **data** contract (and optionally **settings**). Exports at least one schema (e.g. `HeroSchema`) used as the **data** schema for that type. Must extend BaseSectionData (§8) for data; array items must extend BaseArrayItem (§8).
2042
+ * **`types.ts`** — TypeScript interfaces inferred from the schema (e.g. `HeroData`, `HeroSettings`). Export types with names **`<SectionType>Data`** and **`<SectionType>Settings`** (or equivalent) so the Tenant can aggregate them in a single types module.
2043
+ * **`index.ts`** — Public API: re-exports View, schema(s), and types.
2044
+
2045
+ ### 3.2 Reserved System Types
2046
+ * **`type: 'header'`** — Reserved for `site.json`. Receives **`menu: MenuItem[]`** in addition to `data` and `settings`. Menu is sourced from `menu.json` (see Appendix A). The Tenant **must** type `SectionComponentPropsMap['header']` as `{ data: HeaderData; settings?: HeaderSettings; menu: MenuItem[] }`.
2047
+ * **`type: 'footer'`** — Reserved for `site.json`. Props: `{ data: FooterData; settings?: FooterSettings }` only (no `menu`).
2048
+ * **`type: 'sectionHeader'`** — A standard local block. Must define its own `links` array in its local schema if used.
2049
+
2050
+ **Perché servono:** La capsula (View + schema + types + index) è l’unità di estensione: il Core e il Form Factory possono scoprire tipi e contratti per tipo senza convenzioni ad hoc. Header/footer riservati evitano conflitti tra globale e locale. Senza TBP, aggregazione di SECTION_SCHEMAS e registry sarebbe incoerente e l’ingestion da SaaS non sarebbe automatizzabile.
2051
+
2052
+ ---
2053
+
2054
+ ## 4. 🧱 Component Implementation Protocol (CIP) v1.5
2055
+
2056
+ **Objective:** Ensure system-wide stability and Admin UI integrity.
2057
+
2058
+ 1. **The "Sovereign View" Law:** Components receive `data` and `settings` (and `menu` for header only) and return JSX. They are metadata-blind (never import Zod schemas).
2059
+ 2. **Z-Index Neutrality:** Components must not use `z-index > 1`. Layout delegation (sticky/fixed) is managed by the `SectionRenderer`.
2060
+ 3. **Agnostic Asset Protocol:** Use `resolveAssetUrl(path, tenantId)` for all media. Resolved URLs are under **`/assets/...`** with no tenantId segment in the path (e.g. relative `img/hero.jpg` → `/assets/img/hero.jpg`).
2061
+
2062
+ ### 4.4 Local Design Tokens (v1.2)
2063
+ Section Views that control their own background, text, borders, or radii **shall** define a **local scope** via an inline `style` object on the section root: e.g. `--local-bg`, `--local-text`, `--local-text-muted`, `--local-surface`, `--local-border`, `--local-radius-lg`, `--local-accent`, mapped to theme variables. All Tailwind classes that affect color or radius in that section **must** use these variables (e.g. `bg-[var(--local-bg)]`, `text-[var(--local-text)]`). No naked utilities (e.g. `bg-blue-500`). An optional **`label`** in section data may be rendered with class **`jp-section-label`** for overlay type labels.
2064
+
2065
+ ### 4.5 Z-Index & Overlay Governance (v1.2)
2066
+ Section content root **must** stay at **`z-index` ≤ 1** (prefer `z-0`) so the Sovereign Overlay can sit above with high z-index in Tenant CSS (§7). Header/footer may use a higher z-index (e.g. 50) only as a documented exception for global chrome.
2067
+
2068
+ **Perché servono (CIP):** View “dumb” (solo data/settings) e senza import di Zod evita accoppiamento e permette al Form Factory di essere l’unica fonte di verità sugli schemi. Z-index basso evita che il contenuto copra l’overlay di selezione in Studio. Asset via `resolveAssetUrl`: i path relativi vengono risolti in `/assets/...` (senza segmento tenantId nel path). Token locali (`--local-*`) rendono le section temabili e coerenti con overlay e tema; senza, stili “nudi” creano drift visivo e conflitti con l’UI di editing.
2069
+
2070
+ ---
2071
+
2072
+ ## 5. 🛠️ Editor Component Implementation Protocol (ECIP) v1.5
2073
+
2074
+ **Objective:** Standardize the Polymorphic ICE engine.
2075
+
2076
+ 1. **Recursive Form Factory:** The Admin UI builds forms by traversing the Zod ontology.
2077
+ 2. **UI Metadata:** Use `.describe('ui:[widget]')` in schemas to pass instructions to the Form Factory.
2078
+ 3. **Deterministic IDs:** Every object in a `ZodArray` must extend `BaseArrayItem` (containing an `id`) to ensure React reconciliation stability during reordering.
2079
+
2080
+ ### 5.4 UI Metadata Vocabulary (v1.2)
2081
+ Standard keys for the Form Factory:
2082
+
2083
+ | Key | Use case |
2084
+ |-----|----------|
2085
+ | `ui:text` | Single-line text input. |
2086
+ | `ui:textarea` | Multi-line text. |
2087
+ | `ui:select` | Enum / single choice. |
2088
+ | `ui:number` | Numeric input. |
2089
+ | `ui:list` | Array of items; list editor (add/remove/reorder). |
2090
+ | `ui:icon-picker` | Icon selection. |
2091
+
2092
+ Unknown keys may be treated as `ui:text`. Array fields must use `BaseArrayItem` for items.
2093
+
2094
+ ### 5.5 Path-Only Nested Selection & Expansion (v1.3, breaking)
2095
+ In strict v1.3 Studio/Inspector behavior, nested editing targets are represented by **path segments from root to leaf**.
2096
+
2097
+ ```typescript
2098
+ export type SelectionPathSegment = { fieldKey: string; itemId?: string };
2099
+ export type SelectionPath = SelectionPathSegment[];
2100
+ ```
2101
+
2102
+ Rules:
2103
+ * Expansion and focus for nested arrays **must** be computed from `SelectionPath` (root → leaf), not from a single flat pair.
2104
+ * Matching by `fieldKey` alone is non-compliant for nested structures.
2105
+ * Legacy flat payload fields **`itemField`** and **`itemId`** are removed from strict v1.3 selection protocol.
2106
+
2107
+ **Perché servono (ECIP):** Il Form Factory deve sapere quale widget usare (text, textarea, select, list, …) senza hardcodare per tipo; `.describe('ui:...')` è il contratto. BaseArrayItem con `id` su ogni item di array garantisce chiavi stabili in React e reorder/delete corretti nell’Inspector. In v1.3 la selezione/espansione path-only elimina ambiguità su array annidati: senza path completo root→leaf, la sidebar può aprire il ramo sbagliato o non aprire il target.
2108
+
2109
+ ---
2110
+
2111
+ ## 6. 🎯 ICE Data Attribute Contract (IDAC) v1.1
2112
+
2113
+ **Objective:** Mandatory data attributes so the Stage (iframe) and Inspector can bind selection and field/item editing without coupling to Tenant DOM.
2114
+
2115
+ ### 6.1 Section-Level Markup (Core-Provided)
2116
+ **SectionRenderer** (Core) wraps each section root with:
2117
+ * **`data-section-id`** — Section instance ID (e.g. UUID). On the wrapper that contains content + overlay.
2118
+ * Sibling overlay element **`data-jp-section-overlay`** — Selection ring and type label. **Tenant does not add this;** Core injects it.
2119
+
2120
+ Tenant Views render the **content** root only (e.g. `<section>` or `<div>`), placed **inside** the Core wrapper.
2121
+
2122
+ ### 6.2 Field-Level Binding (Tenant-Provided)
2123
+ For every **editable scalar field** the View **must** attach **`data-jp-field="<fieldKey>"`** (key matches schema path: e.g. `title`, `description`, `sectionTitle`, `label`).
2124
+
2125
+ ### 6.3 Array-Item Binding (Tenant-Provided)
2126
+ For every **editable array item** the View **must** attach:
2127
+ * **`data-jp-item-id="<stableId>"`** — Prefer `item.id`; fallback e.g. `legacy-${index}` only outside strict mode.
2128
+ * **`data-jp-item-field="<arrayKey>"`** — e.g. `cards`, `layers`, `products`, `paragraphs`.
2129
+
2130
+ ### 6.4 Compliance
2131
+ **Reserved types** (`header`, `footer`): ICE attributes optional unless Studio edits them. **All other section types** in the Stage and in `SECTION_SCHEMAS` **must** implement §6.2 and §6.3 for every editable field and array item.
2132
+
2133
+ ### 6.5 Strict Path Extraction for Nested Arrays (v1.3, breaking)
2134
+ For nested array targets, the Core/Inspector contract is path-based:
2135
+ * The runtime selection target is expressed as `itemPath: SelectionPath` (root → leaf).
2136
+ * Flat identity (`itemField` + `itemId`) is not sufficient for nested structures and is removed in strict v1.3 payloads.
2137
+ * In strict mode, index-based identity fallback is non-compliant for editable object arrays.
2138
+
2139
+ **Perché servono (IDAC):** Lo Stage è in un iframe e l’Inspector deve sapere **quale campo o item** corrisponde al click (o alla selezione) senza conoscere la struttura DOM del Tenant. **`data-jp-field`** associa un nodo DOM al path dello schema (es. `title`, `description`): così il Core può evidenziare la riga giusta nella sidebar, applicare opacità attivo/inattivo e aprire il form sul campo corretto. **`data-jp-item-id`** e **`data-jp-item-field`** fanno lo stesso per gli item di array (liste, reorder, delete). In v1.3, `itemPath` rende deterministico anche il caso nested (array dentro array), eliminando mismatch tra selezione canvas e ramo aperto in sidebar.
2140
+
2141
+ ---
2142
+
2143
+ ## 7. 🎨 Tenant Overlay CSS Contract (TOCC) v1.0
2144
+
2145
+ **Objective:** The Stage iframe loads only Tenant HTML/CSS. Core injects overlay **markup** but does **not** ship overlay styles. The Tenant **must** supply CSS so overlay is visible.
2146
+
2147
+ ### 7.1 Required Selectors (Tenant global CSS)
2148
+ 1. **`[data-jp-section-overlay]`** — `position: absolute; inset: 0`; `pointer-events: none`; base state transparent.
2149
+ 2. **`[data-section-id]:hover [data-jp-section-overlay]`** — Hover: e.g. dashed border, subtle tint.
2150
+ 3. **`[data-section-id][data-jp-selected] [data-jp-section-overlay]`** — Selected: solid border, optional tint.
2151
+ 4. **`[data-jp-section-overlay] > div`** (type label) — Position and visibility (e.g. visible on hover/selected).
2152
+
2153
+ ### 7.2 Z-Index
2154
+ Overlay **z-index** high (e.g. 9999). Section content at or below CIP limit (§4.5).
2155
+
2156
+ ### 7.3 Responsibility
2157
+ **Core:** Injects wrapper and overlay DOM; sets `data-jp-selected`. **Tenant:** All overlay **visual** rules.
2158
+
2159
+ **Perché servono (TOCC):** L’iframe dello Stage carica solo HTML/CSS del Tenant; il Core inietta il markup dell’overlay ma non gli stili. Senza CSS Tenant per i selettori TOCC, bordo hover/selected e type label non sarebbero visibili: l’autore non vedrebbe quale section è selezionata né il label del tipo. TOCC chiarisce la responsabilità (Core = markup, Tenant = aspetto) e garantisce UX uniforme tra tenant.
2160
+
2161
+ ---
2162
+
2163
+ ## 8. 📦 Base Section Data & Settings (BSDS) v1.0
2164
+
2165
+ **Objective:** Standardize base schema fragments for anchors, array items, and section settings.
2166
+
2167
+ ### 8.1 BaseSectionData
2168
+ Every section data schema **must** extend a base with at least **`anchorId`** (optional string). Canonical Zod (Tenant `lib/base-schemas.ts` or equivalent):
2169
+
2170
+ ```typescript
2171
+ export const BaseSectionData = z.object({
2172
+ anchorId: z.string().optional().describe('ui:text'),
2173
+ });
2174
+ ```
2175
+
2176
+ ### 8.2 BaseArrayItem
2177
+ Every array item schema editable in the Inspector **must** include **`id`** (optional string minimum). Canonical Zod:
2178
+
2179
+ ```typescript
2180
+ export const BaseArrayItem = z.object({
2181
+ id: z.string().optional(),
2182
+ });
2183
+ ```
2184
+
2185
+ Recommended: required UUID for new items. Used by `data-jp-item-id` and React reconciliation.
2186
+
2187
+ ### 8.3 BaseSectionSettings (Optional)
2188
+ Common section-level settings. Canonical Zod (name **BaseSectionSettingsSchema** or as exported by Core):
2189
+
2190
+ ```typescript
2191
+ export const BaseSectionSettingsSchema = z.object({
2192
+ paddingTop: z.enum(['none', 'sm', 'md', 'lg', 'xl', '2xl']).default('md').describe('ui:select'),
2193
+ paddingBottom: z.enum(['none', 'sm', 'md', 'lg', 'xl', '2xl']).default('md').describe('ui:select'),
2194
+ theme: z.enum(['dark', 'light', 'accent']).default('dark').describe('ui:select'),
2195
+ container: z.enum(['boxed', 'fluid']).default('boxed').describe('ui:select'),
2196
+ });
2197
+ ```
2198
+
2199
+ Capsules may extend this for type-specific settings. Core may export **BaseSectionSettings** as the TypeScript type inferred from this or a superset.
2200
+
2201
+ **Perché servono (BSDS):** anchorId permette deep-link e navigazione in-page; id sugli array item è necessario per `data-jp-item-id`, reorder e React reconciliation. BaseSectionSettings comuni (padding, theme, container) evitano ripetizione e allineano il Form Factory tra capsule. Senza base condivisi, ogni capsule inventa convenzioni e validazione/add-section diventano fragili.
2202
+
2203
+ ---
2204
+
2205
+ ## 9. 📌 AddSectionConfig (ASC) v1.0
2206
+
2207
+ **Objective:** Formalize the "Add Section" contract used by the Studio.
2208
+
2209
+ **Type (Core exports `AddSectionConfig`):**
2210
+ ```typescript
2211
+ interface AddSectionConfig {
2212
+ addableSectionTypes: readonly string[];
2213
+ sectionTypeLabels: Record<string, string>;
2214
+ getDefaultSectionData(sectionType: string): Record<string, unknown>;
2215
+ }
2216
+ ```
2217
+
2218
+ **Shape:** Tenant provides one object (e.g. `addSectionConfig`) with:
2219
+ * **`addableSectionTypes`** — Readonly array of section type keys. Only these types appear in the Add Section Library. Must be a subset of (or equal to) the keys in SectionDataRegistry.
2220
+ * **`sectionTypeLabels`** — Map type key → display string (e.g. `{ hero: 'Hero', 'cta-banner': 'CTA Banner' }`).
2221
+ * **`getDefaultSectionData(sectionType: string): Record<string, unknown>`** — Returns default `data` for a new section. Must conform to the capsule’s data schema so the new section validates.
2222
+
2223
+ Core creates a new section with deterministic UUID, `type`, and `data` from `getDefaultSectionData(type)`.
2224
+
2225
+ **Perché servono (ASC):** Lo Studio deve mostrare una libreria “Aggiungi sezione” con nomi leggibili e, alla scelta, creare una section con dati iniziali validi. addableSectionTypes, sectionTypeLabels e getDefaultSectionData sono il contratto: il Tenant è l’unica fonte di verità su quali tipi sono addabili e con quali default. Senza ASC, il Core non saprebbe cosa mostrare in modal né come popolare i dati della nuova section.
2226
+
2227
+ ---
2228
+
2229
+ ## 10. ⚙️ JsonPagesConfig & Engine Bootstrap (JEB) v1.1
2230
+
2231
+ **Objective:** Bootstrap contract between Tenant app and `@olonjs/core`.
2232
+
2233
+ ### 10.1 JsonPagesConfig (required fields)
2234
+ The Tenant passes a single **config** object to **JsonPagesEngine**. Required fields:
2235
+
2236
+ | Field | Type | Description |
2237
+ |-------|------|-------------|
2238
+ | **tenantId** | string | Passed to `resolveAssetUrl(path, tenantId)`; resolved asset URLs are **`/assets/...`** with no tenantId segment in the path. |
2239
+ | **registry** | `{ [K in SectionType]: React.FC<SectionComponentPropsMap[K]> }` | Component registry. Must match MTRP keys. See Appendix A. |
2240
+ | **schemas** | `Record<SectionType, ZodType>` or equivalent | SECTION_SCHEMAS: type → **data** Zod schema. Form Factory uses this. See Appendix A. |
2241
+ | **pages** | `Record<string, PageConfig>` | Slug → page config. See Appendix A. |
2242
+ | **siteConfig** | SiteConfig | Global site (identity, header/footer blocks). See Appendix A. |
2243
+ | **themeConfig** | ThemeConfig | Theme tokens. See Appendix A. |
2244
+ | **menuConfig** | MenuConfig | Navigation tree (SSOT for header menu). See Appendix A. |
2245
+ | **themeCss** | `{ tenant: string }` | At least **tenant**: string (inline CSS or URL) for Stage iframe injection. |
2246
+ | **addSection** | AddSectionConfig | Add-section config (§9). |
2247
+
2248
+ Core may define optional fields. The Tenant must not omit required fields.
2249
+
2250
+ ### 10.2 JsonPagesEngine
2251
+ Root component: **`<JsonPagesEngine config={config} />`**. Responsibilities: route → page, SectionRenderer per section; in Studio mode Sovereign Shell (Inspector, Control Bar, postMessage); section wrappers and overlay per IDAC and JAP. Tenant does not implement the Shell.
2252
+
2253
+ ### 10.3 Studio Selection Event Contract (v1.3, breaking)
2254
+ In strict v1.3 Studio, section selection payload for nested targets is path-based:
2255
+
2256
+ ```typescript
2257
+ type SectionSelectMessage = {
2258
+ type: 'SECTION_SELECT';
2259
+ section: { id: string; type: string; scope: 'global' | 'local' };
2260
+ itemPath?: SelectionPath; // root -> leaf
2261
+ };
2262
+ ```
2263
+
2264
+ Removed from strict protocol:
2265
+ * `itemField`
2266
+ * `itemId`
2267
+
2268
+ **Perché servono (JEB):** Un unico punto di bootstrap (config + Engine) evita che il Tenant replichi logica di routing, Shell e overlay. I campi obbligatori in JsonPagesConfig (tenantId, registry, schemas, pages, siteConfig, themeConfig, menuConfig, themeCss, addSection) sono il minimo per far funzionare rendering, Studio e Form Factory; omissioni causano errori a runtime. In v1.3, il payload `itemPath` sincronizza in modo non ambiguo Stage e Inspector su nested arrays.
2269
+
2270
+ ---
2271
+
2272
+ # 🏛️ OlonJS_ADMIN_PROTOCOL (JAP) v1.2
2273
+
2274
+ **Status:** Mandatory Standard
2275
+ **Version:** 1.2.0 (Sovereign Shell Edition — Path/Nested Strictness)
2276
+ **Objective:** Deterministic orchestration of the "Studio" environment (ICE Level 1).
2277
+
2278
+ ---
2279
+
2280
+ ## 1. The Sovereign Shell Topology
2281
+ The Admin interface is a **Sovereign Shell** from `@olonjs/core`.
2282
+ 1. **The Stage (Canvas):** Isolated Iframe; postMessage for data updates and selection mirroring. Section markup follows **IDAC** (§6); overlay styling follows **TOCC** (§7).
2283
+ 2. **The Inspector (Sidebar):** Consumes Tenant Zod schemas to generate editors; binding via `data-jp-field` and `data-jp-item-*`.
2284
+ 3. **The Control Bar:** Save, Export, Add Section.
2285
+
2286
+ ## 2. State Orchestration & Persistence
2287
+ * **Working Draft:** Reactive local state for unsaved changes.
2288
+ * **Sync Law:** Inspector changes → Working Draft → Stage via `STUDIO_EVENTS.UPDATE_DRAFTS`.
2289
+ * **Bake Protocol:** "Bake HTML" requests snapshot from Iframe, injects `ProjectState` as JSON, triggers download.
2290
+
2291
+ ## 3. Context Switching (Global vs. Local)
2292
+ * **Header/Footer** selection → Global Mode, `site.json`.
2293
+ * Any other section → Page Mode, current `[slug].json`.
2294
+
2295
+ ## 4. Section Lifecycle Management
2296
+ 1. **Add Section:** Modal from Tenant `SECTION_SCHEMAS`; UUID + default data via **AddSectionConfig** (§9).
2297
+ 2. **Reorder:** Inspector or Stage Overlay; array mutation in Working Draft.
2298
+ 3. **Delete:** Confirmation; remove from array, clear selection.
2299
+
2300
+ ## 5. Stage Isolation & Overlay
2301
+ * **CSS Shielding:** Stage in Iframe; Tenant CSS does not leak into Admin.
2302
+ * **Sovereign Overlay:** Selection ring and type labels injected per **IDAC** (§6); Tenant styles them per **TOCC** (§7).
2303
+
2304
+ ## 6. "Green Build" Validation
2305
+ Studio enforces `tsc && vite build`. No export with TypeScript errors.
2306
+
2307
+ ## 7. Path-Deterministic Selection & Sidebar Expansion (v1.3, breaking)
2308
+ * Section/item focus synchronization uses `itemPath` (root → leaf), not flat `itemField/itemId`.
2309
+ * Sidebar expansion state for nested arrays must be derived from all path segments.
2310
+ * Flat-only matching may open/close wrong branches and is non-compliant in strict mode.
2311
+
2312
+ **Perché servono (JAP):** Stage in iframe + Inspector + Control Bar separano il contesto di editing dal sito; postMessage e Working Draft permettono modifiche senza toccare subito i file. Bake ed Export richiedono uno stato coerente. Global vs Page mode evita confusione su dove si sta editando (site.json vs [slug].json). Add/Reorder/Delete sono gestiti in un solo modo (Working Draft + ASC). Green Build garantisce che ciò che si esporta compili. In v1.3, il path completo elimina ambiguità nella sincronizzazione Stage↔Sidebar su strutture annidate.
2313
+
2314
+ ---
2315
+
2316
+ ## Compliance: Legacy vs Full UX (v1.3)
2317
+
2318
+ | Dimension | Legacy / Less UX | Full UX (Core-aligned) |
2319
+ |-----------|-------------------|-------------------------|
2320
+ | **ICE binding** | No `data-jp-*`; Inspector cannot bind. | IDAC (§6) on every editable section/field/item. |
2321
+ | **Section wrapper** | Plain `<section>`; no overlay contract. | Core wrapper + overlay; Tenant CSS per TOCC (§7). |
2322
+ | **Design tokens** | Raw BEM / fixed classes. | Local tokens (§4.4); `var(--local-*)` only. |
2323
+ | **Base schemas** | Ad hoc. | BSDS (§8): BaseSectionData, BaseArrayItem, BaseSectionSettings. |
2324
+ | **Add Section** | Ad hoc defaults. | ASC (§9): addableSectionTypes, labels, getDefaultSectionData. |
2325
+ | **Bootstrap** | Implicit. | JEB (§10): JsonPagesConfig + JsonPagesEngine. |
2326
+ | **Selection payload** | Flat `itemField/itemId`. | Path-only `itemPath: SelectionPath` (JEB §10.3). |
2327
+ | **Nested array expansion** | Single-segment or field-only heuristics. | Root-to-leaf path expansion (ECIP §5.5, JAP §7). |
2328
+ | **Array item identity (strict)** | Index fallback tolerated. | Stable `id` required for editable object arrays. |
2329
+
2330
+ **Rule:** Every page section (non-header/footer) that appears in the Stage and in `SECTION_SCHEMAS` must comply with §6, §7, §4.4, §8, §9, §10 for full Studio UX.
2331
+
2332
+ ---
2333
+
2334
+ ## Summary of v1.3 Additions
2335
+
2336
+ | § | Title | Purpose |
2337
+ |---|--------|--------|
2338
+ | 5.5 | Path-Only Nested Selection & Expansion | ECIP: root→leaf `SelectionPath`; remove flat matching in strict mode. |
2339
+ | 6.5 | Strict Path Extraction for Nested Arrays | IDAC: path-based nested targeting; no strict flat fallback. |
2340
+ | 10.3 | Studio Selection Event Contract | JEB: `SECTION_SELECT` uses `itemPath`; remove `itemField/itemId`. |
2341
+ | JAP §7 | Path-Deterministic Selection & Sidebar Expansion | Studio state synchronization for nested arrays. |
2342
+ | Compliance | Legacy vs Full UX (v1.3) | Explicit breaking delta for flat protocol removal and strict IDs. |
2343
+ | **Appendix A.6** | **v1.3 Path/Nested Strictness Addendum** | Type/export and migration checklist for path-only protocol. |
2344
+
2345
+ ---
2346
+
2347
+ # Appendix A — Tenant Type & Code-Generation Annex
2348
+
2349
+ **Objective:** Make the specification **sufficient** to generate or audit a full tenant (new site, new components, new data) without a reference codebase. Defines TypeScript types, JSON shapes, schema contract, file paths, and integration pattern.
2350
+
2351
+ **Status:** Mandatory for code-generation and governance. Compliance ensures generated tenants are typed and wired like the reference implementation.
2352
+
2353
+ ---
2354
+
2355
+ ## A.1 Core-Provided Types (from `@olonjs/core`)
2356
+
2357
+ The following are assumed to be exported by Core. The Tenant augments **SectionDataRegistry** and **SectionSettingsRegistry**; all other types are consumed as-is.
2358
+
2359
+ | Type | Description |
2360
+ |------|-------------|
2361
+ | **SectionType** | `keyof SectionDataRegistry` (after Tenant augmentation). Union of all section type keys. |
2362
+ | **Section** | Union of `BaseSection<K>` for all K in SectionDataRegistry. See MTRP §1.2. |
2363
+ | **BaseSectionSettings** | Optional base type for section settings (may align with BSDS §8.3). |
2364
+ | **MenuItem** | Navigation item. **Minimum shape:** `{ label: string; href: string }`. Core may extend (e.g. `children?: MenuItem[]`). |
2365
+ | **AddSectionConfig** | See §9. |
2366
+ | **JsonPagesConfig** | See §10.1. |
2367
+
2368
+ **Perché servono (A.1):** Il Tenant deve conoscere i tipi esportati dal Core (SectionType, MenuItem, AddSectionConfig, JsonPagesConfig) per tipizzare registry, config e augmentation senza dipendere da implementazioni interne.
2369
+
2370
+ ---
2371
+
2372
+ ## A.2 Tenant-Provided Types (single source: `src/types.ts` or equivalent)
2373
+
2374
+ The Tenant **must** define the following in one module (e.g. **`src/types.ts`**). This module **must** perform the **module augmentation** of `@olonjs/core` for **SectionDataRegistry** and **SectionSettingsRegistry**, and **must** export **SectionComponentPropsMap** and re-export from `@olonjs/core` so that **SectionType** is available after augmentation.
2375
+
2376
+ ### A.2.1 SectionComponentPropsMap
2377
+
2378
+ Maps each section type to the props of its React component. **Header** is the only type that receives **menu**.
2379
+
2380
+ **Option A — Explicit (recommended for clarity and tooling):** For each section type K, add one entry. Header receives **menu**.
2381
+
2382
+ ```typescript
2383
+ import type { MenuItem } from '@olonjs/core';
2384
+ // Import Data/Settings from each capsule.
2385
+
2386
+ export type SectionComponentPropsMap = {
2387
+ 'header': { data: HeaderData; settings?: HeaderSettings; menu: MenuItem[] };
2388
+ 'footer': { data: FooterData; settings?: FooterSettings };
2389
+ 'hero': { data: HeroData; settings?: HeroSettings };
2390
+ // ... one entry per SectionType, e.g. 'feature-grid', 'cta-banner', etc.
2391
+ };
2392
+ ```
2393
+
2394
+ **Option B — Mapped type (DRY, requires SectionDataRegistry/SectionSettingsRegistry in scope):**
2395
+
2396
+ ```typescript
2397
+ import type { MenuItem } from '@olonjs/core';
2398
+
2399
+ export type SectionComponentPropsMap = {
2400
+ [K in SectionType]: K extends 'header'
2401
+ ? { data: SectionDataRegistry[K]; settings?: SectionSettingsRegistry[K]; menu: MenuItem[] }
2402
+ : { data: SectionDataRegistry[K]; settings?: K extends keyof SectionSettingsRegistry ? SectionSettingsRegistry[K] : BaseSectionSettings };
2403
+ };
2404
+ ```
2405
+
2406
+ SectionType is imported from Core (after Tenant augmentation). In practice Option A is the reference pattern; Option B is valid if the Tenant prefers a single derived definition.
2407
+
2408
+ **Perché servono (A.2):** SectionComponentPropsMap e i tipi di config (PageConfig, SiteConfig, MenuConfig, ThemeConfig) definiscono il contratto tra dati (JSON, API) e componente; l’augmentation è l’unico modo per estendere i registry del Core senza fork. Senza questi tipi, generazione tenant e refactor sarebbero senza guida e il type-check fallirebbe.
2409
+
2410
+ ### A.2.2 ComponentRegistry type
2411
+
2412
+ The registry object **must** be typed as:
2413
+
2414
+ ```typescript
2415
+ import type { SectionType } from '@olonjs/core';
2416
+ import type { SectionComponentPropsMap } from '@/types';
2417
+
2418
+ export const ComponentRegistry: {
2419
+ [K in SectionType]: React.FC<SectionComponentPropsMap[K]>;
2420
+ } = { /* ... */ };
2421
+ ```
2422
+
2423
+ File: **`src/lib/ComponentRegistry.tsx`** (or equivalent). Imports one View per section type and assigns it to the corresponding key.
2424
+
2425
+ ### A.2.3 PageConfig
2426
+
2427
+ Minimum shape for a single page (used in **pages** and in each **`[slug].json`**):
2428
+
2429
+ ```typescript
2430
+ export interface PageConfig {
2431
+ id?: string;
2432
+ slug: string;
2433
+ meta?: {
2434
+ title?: string;
2435
+ description?: string;
2436
+ };
2437
+ sections: Section[];
2438
+ }
2439
+ ```
2440
+
2441
+ **Section** is the union type from MTRP (§1.2). Each element of **sections** has **id**, **type**, **data**, **settings** and conforms to the capsule schemas.
2442
+
2443
+ ### A.2.4 SiteConfig
2444
+
2445
+ Minimum shape for **site.json** (and for **siteConfig** in JsonPagesConfig):
2446
+
2447
+ ```typescript
2448
+ export interface SiteConfigIdentity {
2449
+ title?: string;
2450
+ logoUrl?: string;
2451
+ }
2452
+
2453
+ export interface SiteConfig {
2454
+ identity?: SiteConfigIdentity;
2455
+ pages?: Array<{ slug: string; label: string }>;
2456
+ header: {
2457
+ id: string;
2458
+ type: 'header';
2459
+ data: HeaderData;
2460
+ settings?: HeaderSettings;
2461
+ };
2462
+ footer: {
2463
+ id: string;
2464
+ type: 'footer';
2465
+ data: FooterData;
2466
+ settings?: FooterSettings;
2467
+ };
2468
+ }
2469
+ ```
2470
+
2471
+ **HeaderData**, **FooterData**, **HeaderSettings**, **FooterSettings** are the types exported from the header and footer capsules.
2472
+
2473
+ ### A.2.5 MenuConfig
2474
+
2475
+ Minimum shape for **menu.json** (and for **menuConfig** in JsonPagesConfig). Structure is tenant-defined; Core expects the header to receive **MenuItem[]**. Common pattern: an object with a key (e.g. **main**) whose value is **MenuItem[]**.
2476
+
2477
+ ```typescript
2478
+ export interface MenuConfig {
2479
+ main?: MenuItem[];
2480
+ [key: string]: MenuItem[] | undefined;
2481
+ }
2482
+ ```
2483
+
2484
+ Or simply **`MenuItem[]`** if the app uses a single flat list. The Tenant must ensure that the value passed to the header component as **menu** conforms to **MenuItem[]** (e.g. `menuConfig.main` or `menuConfig` if it is the array).
2485
+
2486
+ ### A.2.6 ThemeConfig
2487
+
2488
+ Minimum shape for **theme.json** (and for **themeConfig** in JsonPagesConfig). Tenant-defined; typically tokens for colors, typography, radius.
2489
+
2490
+ ```typescript
2491
+ export interface ThemeConfig {
2492
+ name?: string;
2493
+ tokens?: {
2494
+ colors?: Record<string, string>;
2495
+ typography?: Record<string, string | Record<string, string>>;
2496
+ borderRadius?: Record<string, string>;
2497
+ };
2498
+ [key: string]: unknown;
2499
+ }
2500
+ ```
2501
+
2502
+ ---
2503
+
2504
+ ## A.3 Schema Contract (SECTION_SCHEMAS)
2505
+
2506
+ **Location:** **`src/lib/schemas.ts`** (or equivalent).
2507
+
2508
+ **Contract:**
2509
+ * **SECTION_SCHEMAS** is a **single object** whose keys are **SectionType** and whose values are **Zod schemas for the section data** (not settings, unless the Form Factory contract expects a combined or per-type settings schema; then each value may be the data schema only, and settings may be defined per capsule and aggregated elsewhere if needed).
2510
+ * The Tenant **must** re-export **BaseSectionData**, **BaseArrayItem**, and optionally **BaseSectionSettingsSchema** from **`src/lib/base-schemas.ts`** (or equivalent). Each capsule’s data schema **must** extend BaseSectionData; each array item schema **must** extend or include BaseArrayItem.
2511
+ * **SECTION_SCHEMAS** is typed as **`Record<SectionType, ZodType>`** or **`{ [K in SectionType]: ZodType }`** so that keys match the registry and SectionDataRegistry.
2512
+
2513
+ **Export:** The app imports **SECTION_SCHEMAS** and passes it as **config.schemas** to JsonPagesEngine. The Form Factory traverses these schemas to build editors.
2514
+
2515
+ **Perché servono (A.3):** Un unico oggetto SECTION_SCHEMAS con chiavi = SectionType e valori = schema data permette al Form Factory di costruire form per tipo senza convenzioni ad hoc; i base schema garantiscono anchorId e id su item. Senza questo contratto, l’Inspector non saprebbe quali campi mostrare né come validare.
2516
+
2517
+ ---
2518
+
2519
+ ## A.4 File Paths & Data Layout
2520
+
2521
+ | Purpose | Path (conventional) | Description |
2522
+ |---------|---------------------|-------------|
2523
+ | Site config | **`src/data/config/site.json`** | SiteConfig (identity, header, footer, pages list). |
2524
+ | Menu config | **`src/data/config/menu.json`** | MenuConfig (e.g. main nav). |
2525
+ | Theme config | **`src/data/config/theme.json`** | ThemeConfig (tokens). |
2526
+ | Page data | **`src/data/pages/<slug>.json`** | One file per page; content is PageConfig (slug, meta, sections). |
2527
+ | Base schemas | **`src/lib/base-schemas.ts`** | BaseSectionData, BaseArrayItem, BaseSectionSettingsSchema. |
2528
+ | Schema aggregate | **`src/lib/schemas.ts`** | SECTION_SCHEMAS; re-exports base schemas. |
2529
+ | Registry | **`src/lib/ComponentRegistry.tsx`** | ComponentRegistry object. |
2530
+ | Add-section config | **`src/lib/addSectionConfig.ts`** | addSectionConfig (AddSectionConfig). |
2531
+ | Tenant types & augmentation | **`src/types.ts`** | SectionComponentPropsMap, PageConfig, SiteConfig, MenuConfig, ThemeConfig; **declare module '@olonjs/core'** for SectionDataRegistry and SectionSettingsRegistry; re-export from Core. |
2532
+ | Bootstrap | **`src/App.tsx`** | Imports config (site, theme, menu, pages), registry, schemas, addSection, themeCss; builds JsonPagesConfig; renders **<JsonPagesEngine config={config} />**. |
2533
+
2534
+ The app entry (e.g. **main.tsx**) renders **App**. No other bootstrap contract is specified; the Tenant may use Vite aliases (e.g. **@/**) for the paths above.
2535
+
2536
+ **Perché servono (A.4):** Path fissi (data/config, data/pages, lib/schemas, types.ts, App.tsx) permettono a CLI, tooling e agenti di trovare sempre gli stessi file; l’onboarding e la generazione da spec sono deterministici. Senza convenzione, ogni tenant sarebbe una struttura diversa.
2537
+
2538
+ ---
2539
+
2540
+ ## A.5 Integration Checklist (Code-Generation)
2541
+
2542
+ When generating or auditing a tenant, ensure the following in order:
2543
+
2544
+ 1. **Capsules** — For each section type, create **`src/components/<type>/`** with View.tsx, schema.ts, types.ts, index.ts. Data schema extends BaseSectionData; array items extend BaseArrayItem; View complies with CIP and IDAC (§6.2–6.3 for non-reserved types).
2545
+ 2. **Base schemas** — **src/lib/base-schemas.ts** exports BaseSectionData, BaseArrayItem, BaseSectionSettingsSchema (and optional CtaSchema or similar shared fragments).
2546
+ 3. **types.ts** — Define SectionComponentPropsMap (header with **menu**), PageConfig, SiteConfig, MenuConfig, ThemeConfig; **declare module '@olonjs/core'** and augment SectionDataRegistry and SectionSettingsRegistry; re-export from `@olonjs/core`.
2547
+ 4. **ComponentRegistry** — Import every View; build object **{ [K in SectionType]: ViewComponent }**; type as **{ [K in SectionType]: React.FC<SectionComponentPropsMap[K]> }**.
2548
+ 5. **schemas.ts** — Import base schemas and each capsule’s data schema; export SECTION_SCHEMAS as **{ [K in SectionType]: SchemaK }**; export SectionType as **keyof typeof SECTION_SCHEMAS** if not using Core’s SectionType.
2549
+ 6. **addSectionConfig** — addableSectionTypes, sectionTypeLabels, getDefaultSectionData; export as AddSectionConfig.
2550
+ 7. **App.tsx** — Import site, theme, menu, pages from data paths; build config (tenantId, registry, schemas, pages, siteConfig, themeConfig, menuConfig, themeCss: { tenant }, addSection); render JsonPagesEngine.
2551
+ 8. **Data files** — Create or update site.json, menu.json, theme.json, and one or more **<slug>.json** under the paths in A.4. Ensure JSON shapes match SiteConfig, MenuConfig, ThemeConfig, PageConfig.
2552
+ 9. **Tenant CSS** — Include TOCC (§7) selectors in global CSS so the Stage overlay is visible.
2553
+ 10. **Reserved types** — Header and footer capsules receive props per SectionComponentPropsMap; menu is populated from menuConfig (e.g. menuConfig.main) when building the config or inside Core when rendering the header.
2554
+
2555
+ **Perché servono (A.5):** La checklist in ordine evita di dimenticare passi (es. augmentation prima del registry, TOCC dopo le View) e rende la spec sufficiente per generare o verificare un tenant senza codebase di riferimento.
2556
+
2557
+ ---
2558
+
2559
+ ## A.6 v1.3 Path/Nested Strictness Addendum (breaking)
2560
+
2561
+ This addendum extends Appendix A without removing prior v1.2 obligations:
2562
+
2563
+ 1. **Type exports** — Core and/or shared types module should expose `SelectionPathSegment` and `SelectionPath` for Studio messaging and Inspector expansion logic.
2564
+ 2. **Protocol migration** — Replace flat payload fields `itemField` / `itemId` with `itemPath?: SelectionPath` in strict v1.3 channels.
2565
+ 3. **Nested array compliance** — For editable object arrays, item identity must be stable (`id`) and propagated to DOM attributes (`data-jp-item-id`), schema items (BaseArrayItem), and selection path segments (`itemId` when segment targets array item).
2566
+ 4. **Backward compatibility policy** — Legacy flat fields may exist only in transitional adapters outside strict mode; normative v1.3 contract is path-only.
2567
+
2568
+ ---
2569
+
2570
+ **Validation:** Align with current `@olonjs/core` exports (SectionType, MenuItem, AddSectionConfig, JsonPagesConfig, and in v1.3 path types for Studio selection).
2571
+ **Distribution:** Core via `.yalc`; tenant projections via `@olonjs/cli`. This annex makes the spec **necessary and sufficient** for tenant code-generation and governance at enterprise grade.
2572
+
919
2573
  END_OF_FILE_CONTENT
920
2574
  mkdir -p "src"
921
2575
  echo "Creating src/App.tsx..."