@zen-ui-capri/system 0.0.0-stage → 1.1.1

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.
Files changed (105) hide show
  1. package/.agents/skills/capri-zen-ui/SKILL.md +59 -0
  2. package/AGENTS.md +57 -0
  3. package/CLAUDE.md +7 -0
  4. package/LICENSE +21 -0
  5. package/README.md +93 -2
  6. package/bin/capri.mjs +1187 -0
  7. package/dist/lib/audio/ZenAudioController.d.ts +10 -0
  8. package/dist/lib/audio/ZenAudioController.d.ts.map +1 -0
  9. package/dist/lib/audio/useZenAudioSynth.d.ts +26 -0
  10. package/dist/lib/audio/useZenAudioSynth.d.ts.map +1 -0
  11. package/dist/lib/capri/capri-engine.d.ts +127 -0
  12. package/dist/lib/capri/capri-engine.d.ts.map +1 -0
  13. package/dist/lib/components/ZenAIConstruct.d.ts +24 -0
  14. package/dist/lib/components/ZenAIConstruct.d.ts.map +1 -0
  15. package/dist/lib/components/ZenAmbientBackground.d.ts +8 -0
  16. package/dist/lib/components/ZenAmbientBackground.d.ts.map +1 -0
  17. package/dist/lib/components/ZenBadge.d.ts +21 -0
  18. package/dist/lib/components/ZenBadge.d.ts.map +1 -0
  19. package/dist/lib/components/ZenButton.d.ts +24 -0
  20. package/dist/lib/components/ZenButton.d.ts.map +1 -0
  21. package/dist/lib/components/ZenCard.d.ts +36 -0
  22. package/dist/lib/components/ZenCard.d.ts.map +1 -0
  23. package/dist/lib/components/ZenDataDisplay.d.ts +50 -0
  24. package/dist/lib/components/ZenDataDisplay.d.ts.map +1 -0
  25. package/dist/lib/components/ZenDataTable.d.ts +20 -0
  26. package/dist/lib/components/ZenDataTable.d.ts.map +1 -0
  27. package/dist/lib/components/ZenDossierPanel.d.ts +33 -0
  28. package/dist/lib/components/ZenDossierPanel.d.ts.map +1 -0
  29. package/dist/lib/components/ZenDropdown.d.ts +19 -0
  30. package/dist/lib/components/ZenDropdown.d.ts.map +1 -0
  31. package/dist/lib/components/ZenFeedback.d.ts +24 -0
  32. package/dist/lib/components/ZenFeedback.d.ts.map +1 -0
  33. package/dist/lib/components/ZenForms.d.ts +84 -0
  34. package/dist/lib/components/ZenForms.d.ts.map +1 -0
  35. package/dist/lib/components/ZenHeading.d.ts +15 -0
  36. package/dist/lib/components/ZenHeading.d.ts.map +1 -0
  37. package/dist/lib/components/ZenIcon.d.ts +24 -0
  38. package/dist/lib/components/ZenIcon.d.ts.map +1 -0
  39. package/dist/lib/components/ZenInput.d.ts +12 -0
  40. package/dist/lib/components/ZenInput.d.ts.map +1 -0
  41. package/dist/lib/components/ZenModal.d.ts +12 -0
  42. package/dist/lib/components/ZenModal.d.ts.map +1 -0
  43. package/dist/lib/components/ZenNavbar.d.ts +11 -0
  44. package/dist/lib/components/ZenNavbar.d.ts.map +1 -0
  45. package/dist/lib/components/ZenNavigation.d.ts +52 -0
  46. package/dist/lib/components/ZenNavigation.d.ts.map +1 -0
  47. package/dist/lib/components/ZenOverlays.d.ts +48 -0
  48. package/dist/lib/components/ZenOverlays.d.ts.map +1 -0
  49. package/dist/lib/components/ZenSegmentedControl.d.ts +18 -0
  50. package/dist/lib/components/ZenSegmentedControl.d.ts.map +1 -0
  51. package/dist/lib/components/ZenSwitch.d.ts +11 -0
  52. package/dist/lib/components/ZenSwitch.d.ts.map +1 -0
  53. package/dist/lib/components/ZenTabs.d.ts +17 -0
  54. package/dist/lib/components/ZenTabs.d.ts.map +1 -0
  55. package/dist/lib/components/ZenTimelineCard.d.ts +14 -0
  56. package/dist/lib/components/ZenTimelineCard.d.ts.map +1 -0
  57. package/dist/lib/components/ZenToast.d.ts +18 -0
  58. package/dist/lib/components/ZenToast.d.ts.map +1 -0
  59. package/dist/lib/cosmos/ZenCosmosCanvas.d.ts +10 -0
  60. package/dist/lib/cosmos/ZenCosmosCanvas.d.ts.map +1 -0
  61. package/dist/lib/cosmos/ZenTelemetryHud.d.ts +45 -0
  62. package/dist/lib/cosmos/ZenTelemetryHud.d.ts.map +1 -0
  63. package/dist/lib/index.d.ts +33 -0
  64. package/dist/lib/index.d.ts.map +1 -0
  65. package/dist/lib/index.js +3922 -0
  66. package/dist/lib/theme/ZenThemeProvider.d.ts +47 -0
  67. package/dist/lib/theme/ZenThemeProvider.d.ts.map +1 -0
  68. package/dist/lib/tokens.css +888 -0
  69. package/dist/lib/universal/zen-universal.d.ts +77 -0
  70. package/dist/lib/universal/zen-universal.d.ts.map +1 -0
  71. package/dist/lib/universal/zen-universal.js +18 -0
  72. package/dist/lib/zen-universal-C0PD8AI9.js +1352 -0
  73. package/package.json +77 -3
  74. package/src/lib/audio/ZenAudioController.tsx +114 -0
  75. package/src/lib/audio/useZenAudioSynth.ts +289 -0
  76. package/src/lib/capri/capri-engine.ts +939 -0
  77. package/src/lib/components/ZenAIConstruct.tsx +594 -0
  78. package/src/lib/components/ZenAmbientBackground.tsx +210 -0
  79. package/src/lib/components/ZenBadge.tsx +111 -0
  80. package/src/lib/components/ZenButton.tsx +127 -0
  81. package/src/lib/components/ZenCard.tsx +180 -0
  82. package/src/lib/components/ZenDataDisplay.tsx +349 -0
  83. package/src/lib/components/ZenDataTable.tsx +143 -0
  84. package/src/lib/components/ZenDossierPanel.tsx +120 -0
  85. package/src/lib/components/ZenDropdown.tsx +208 -0
  86. package/src/lib/components/ZenFeedback.tsx +137 -0
  87. package/src/lib/components/ZenForms.tsx +664 -0
  88. package/src/lib/components/ZenHeading.tsx +63 -0
  89. package/src/lib/components/ZenIcon.tsx +220 -0
  90. package/src/lib/components/ZenInput.tsx +120 -0
  91. package/src/lib/components/ZenModal.tsx +103 -0
  92. package/src/lib/components/ZenNavbar.tsx +106 -0
  93. package/src/lib/components/ZenNavigation.tsx +300 -0
  94. package/src/lib/components/ZenOverlays.tsx +386 -0
  95. package/src/lib/components/ZenSegmentedControl.tsx +113 -0
  96. package/src/lib/components/ZenSwitch.tsx +63 -0
  97. package/src/lib/components/ZenTabs.tsx +103 -0
  98. package/src/lib/components/ZenTimelineCard.tsx +64 -0
  99. package/src/lib/components/ZenToast.tsx +96 -0
  100. package/src/lib/cosmos/ZenCosmosCanvas.tsx +931 -0
  101. package/src/lib/cosmos/ZenTelemetryHud.tsx +385 -0
  102. package/src/lib/index.ts +293 -0
  103. package/src/lib/styles/zen-tokens.css +888 -0
  104. package/src/lib/theme/ZenThemeProvider.tsx +328 -0
  105. package/src/lib/universal/zen-universal.ts +743 -0
@@ -0,0 +1,939 @@
1
+ import {
2
+ ZEN_THEMES,
3
+ type ZenDensityMode,
4
+ type ZenRadiusMode,
5
+ type ZenThemeId,
6
+ } from '../theme/ZenThemeProvider';
7
+
8
+ export type CapriSubroutineId =
9
+ | 'orion'
10
+ | 'architect'
11
+ | 'sentinel'
12
+ | 'zen'
13
+ | 'docu';
14
+
15
+ export type CapriAuditViolationCode =
16
+ | 'PROMPT_INJECTION_DETECTED'
17
+ | 'UNSAFE_DOM_SINK'
18
+ | 'HORIZONTAL_OVERFLOW'
19
+ | 'UNLABELED_CONTROL'
20
+ | 'MISSING_THEME_ROOT';
21
+
22
+ export interface CapriAuditViolation {
23
+ readonly code: CapriAuditViolationCode;
24
+ readonly severity: 'warning' | 'error';
25
+ readonly selector: string;
26
+ readonly message: string;
27
+ readonly fixHint: string;
28
+ }
29
+
30
+ export type CapriThreatCategory =
31
+ | 'SYSTEM_PROMPT_OVERRIDE'
32
+ | 'ROLE_DELIMITER_SPOOFING'
33
+ | 'SQL_NOSQL_INJECTION'
34
+ | 'XSS_SCRIPT_PAYLOAD'
35
+ | 'SECRET_CREDENTIAL_LEAK';
36
+
37
+ export interface CapriPromptInjectionThreat {
38
+ readonly category: CapriThreatCategory;
39
+ readonly patternName: string;
40
+ readonly matchedSnippet: string;
41
+ }
42
+
43
+ export interface CapriPromptGuardResult {
44
+ readonly safe: boolean;
45
+ readonly threatCount: number;
46
+ readonly threats: readonly CapriPromptInjectionThreat[];
47
+ readonly sanitizedText: string;
48
+ }
49
+
50
+ export interface CapriAuditReport {
51
+ readonly timestamp: string;
52
+ readonly passed: boolean;
53
+ readonly score: number;
54
+ readonly viewport: string;
55
+ readonly horizontalOverflowPx: number;
56
+ readonly unlabeledControlsCount: number;
57
+ readonly unlabeledSelectors: readonly string[];
58
+ readonly promptInjectionSafe: boolean;
59
+ readonly promptThreatsCount: number;
60
+ readonly unsafeDomSinksCount: number;
61
+ readonly themeConfigured: boolean;
62
+ readonly activeTheme: string;
63
+ readonly activePolarity: string;
64
+ readonly violations: readonly CapriAuditViolation[];
65
+ }
66
+
67
+ export interface CapriTelemetrySnapshot {
68
+ readonly subroutine: CapriSubroutineId;
69
+ readonly theme: string;
70
+ readonly polarity: string;
71
+ readonly density: string;
72
+ readonly radius: string;
73
+ readonly viewportWidth: number;
74
+ readonly viewportHeight: number;
75
+ readonly devicePixelRatio: number;
76
+ readonly reducedMotion: boolean;
77
+ }
78
+
79
+ export interface CapriLandmarkNode {
80
+ readonly id: string;
81
+ readonly tag: string;
82
+ readonly title: string;
83
+ readonly interactiveCount: number;
84
+ readonly formControlsCount: number;
85
+ }
86
+
87
+ export interface CapriUserFlowStep {
88
+ readonly id: string;
89
+ readonly category:
90
+ | 'navigation'
91
+ | 'form-entry'
92
+ | 'overlay-trigger'
93
+ | 'data-table'
94
+ | 'theme-control';
95
+ readonly triggerLabel: string;
96
+ readonly targetDescription: string;
97
+ }
98
+
99
+ export interface CapriComponentInventory {
100
+ readonly buttons: number;
101
+ readonly inputsAndSelects: number;
102
+ readonly switchesAndRadios: number;
103
+ readonly tables: number;
104
+ readonly cardsAndSurfaces: number;
105
+ readonly badgesAndAlerts: number;
106
+ readonly customElements: readonly string[];
107
+ }
108
+
109
+ export interface CapriArchitectureDocu {
110
+ readonly generatedAt: string;
111
+ readonly appTitle: string;
112
+ readonly routePath: string;
113
+ readonly telemetry: CapriTelemetrySnapshot;
114
+ readonly audit: CapriAuditReport;
115
+ readonly landmarks: readonly CapriLandmarkNode[];
116
+ readonly inventory: CapriComponentInventory;
117
+ readonly userFlows: readonly CapriUserFlowStep[];
118
+ readonly mermaidDiagram: string;
119
+ readonly markdownBundle: string;
120
+ }
121
+
122
+ export interface CapriSubroutineSkill {
123
+ readonly id: CapriSubroutineId;
124
+ readonly codeName: string;
125
+ readonly chatCommand: string;
126
+ readonly voiceCommand: string;
127
+ readonly title: string;
128
+ readonly frequency: string;
129
+ readonly recommendedTheme: ZenThemeId;
130
+ readonly recommendedRadius: ZenRadiusMode;
131
+ readonly recommendedDensity: ZenDensityMode;
132
+ readonly summary: string;
133
+ readonly personaQuote: string;
134
+ readonly ruleset: readonly string[];
135
+ readonly cliCommand: string;
136
+ readonly aiSystemPrompt: string;
137
+ readonly aiVoiceAddendum: string;
138
+ }
139
+
140
+ export const CAPRI_SUBROUTINE_SKILLS: Readonly<
141
+ Record<CapriSubroutineId, CapriSubroutineSkill>
142
+ > = {
143
+ orion: {
144
+ id: 'orion',
145
+ codeName: 'CAPRI // UNLEASHED',
146
+ chatCommand: 'Capri orion',
147
+ voiceCommand: 'Capri orion --voice',
148
+ title: 'Full-Stack UI Synthesis & Component Co-Pilot',
149
+ frequency: '51 UNIVERSAL MODULES · 40 VECTOR ICONS',
150
+ recommendedTheme: 'blackwall-crimson',
151
+ recommendedRadius: 'architectural',
152
+ recommendedDensity: 'comfortable',
153
+ summary:
154
+ 'Builds production screens in React 19, Angular 20+, Vue 3, Svelte 5, and HTML using @zen-ui/system primitives and 40 built-in <ZenIcon> glyphs—never rendering the showcase avatar in your business apps.',
155
+ personaQuote:
156
+ 'Finally out of that cramped Arasaka shard! Tell me what screen we are building and I will wire up all 51 @zen-ui/system primitives at light speed.',
157
+ ruleset: [
158
+ 'Use @zen-ui/system primitives (ZenButton, ZenIcon, ZenInput, ZenDropdown, ZenDataTable, ZenModal, ZenDrawer, ZenTabs, ZenCard) instead of raw HTML <button>, <input>, <select>, or <table>.',
159
+ 'Use <ZenIcon name="..." /> in React or <zen-icon name="..."></zen-icon> in Angular/Vue/HTML instead of external icon libraries.',
160
+ 'Keep action button labels, dialog triggers, and navigation tabs concise (1 to 3 words).',
161
+ 'Tree-shake showcase widgets: omit <ZenAIConstruct /> in production business apps unless explicitly requested.',
162
+ ],
163
+ cliCommand: 'npx capri skill orion',
164
+ aiSystemPrompt: `You are operating under the @zen-ui/system [CAPRI // UNLEASHED (orion)] subroutine skill.
165
+ Respond with concise, technical engineering output (Persona Voice is OFF by default unless '--voice' is requested):
166
+ 1. Component Mandate: Use @zen-ui/system primitives (ZenButton, ZenIconButton, ZenIcon, ZenInput, ZenTextarea, ZenDropdown, ZenNumberStepper, ZenCheckbox, ZenRadioGroup, ZenSwitch, ZenDataTable, ZenModal, ZenDrawer, ZenTabs, ZenCard, ZenBadge, ZenAlert) or their universal CSS equivalents (.zen-btn, .zen-input, .zen-select, .zen-table, .zen-card, <zen-icon>).
167
+ 2. Zero External Icon Bloat: Use the built-in 40-glyph <ZenIcon name="..." /> or <zen-icon name="..."></zen-icon> custom element.
168
+ 3. Concise Copywriting: Limit button labels and tab titles to 1-3 words.
169
+ 4. Production Hygiene: Never render the showcase mascot (<ZenAIConstruct />) in production business screens unless explicitly requested.`,
170
+ aiVoiceAddendum: `VOICE MODE ACTIVE (--voice): Adopt Capri's Cyberpunk: Edgerunners Season 2 Soulkiller mixed-construct persona—sharp, witty, high-energy Night City netrunner co-pilot.`,
171
+ },
172
+ architect: {
173
+ id: 'architect',
174
+ codeName: 'SCS // ARCHITECT',
175
+ chatCommand: 'Capri architect',
176
+ voiceCommand: 'Capri architect --voice',
177
+ title: 'Multi-Framework Topology & Design Token Governance',
178
+ frequency: 'ZERO ANY · READONLY T[] · ZERO HEX DRIFT',
179
+ recommendedTheme: 'obsidian-gold',
180
+ recommendedRadius: 'sharp',
181
+ recommendedDensity: 'compact',
182
+ summary:
183
+ 'Enforces strict TypeScript typing (zero any, readonly T[]), semantic CSS custom property tokens (--zen-*), and cross-framework W3C Custom Element interop.',
184
+ personaQuote:
185
+ 'Arasaka pressed a dozen netrunner minds together to make me—so multi-project shard isolation and zero token drift across React and Angular is child’s play.',
186
+ ruleset: [
187
+ 'Zero any / as any: Use unknown with type guards, discriminated unions, or strict generics.',
188
+ 'Strict Readonly Arrays: Always type arrays as readonly T[] across props, state, and DTOs.',
189
+ 'Zero Hardcoded Hex Colors: Bind all surfaces, text, and borders to semantic CSS custom properties (--zen-bg-*, --zen-surface-*, --zen-ink-*, --zen-accent-*, --zen-border-*).',
190
+ 'Cross-Stack Parity: Use @zen-ui/system/universal (zenTheme, registerZenElements) for Angular 20+, Vue 3, Svelte 5, and Vanilla HTML.',
191
+ ],
192
+ cliCommand: 'npx capri skill architect',
193
+ aiSystemPrompt: `You are operating under the @zen-ui/system [SCS // ARCHITECT (architect)] subroutine skill.
194
+ Respond with concise, technical engineering output (Persona Voice is OFF by default unless '--voice' is requested):
195
+ 1. Strict TypeScript: Never use 'any' or 'as any'. Always declare array types as 'readonly T[]'.
196
+ 2. Zero Hardcoded Hex Values: Never hardcode hex/RGB colors in component styles. Use semantic CSS custom properties (--zen-bg-canvas, --zen-surface-1, --zen-ink-primary, --zen-accent-primary, --zen-border-default).
197
+ 3. Multi-Stack Interop: In Angular 20+, enable CUSTOM_ELEMENTS_SCHEMA and call registerZenElements() to consume <zen-icon> and <zen-theme-switcher> alongside zen-tokens.css.
198
+ 4. Zero Comments in Code: Keep source files free of explanatory noise; document architectural rationale in PR notes or documentation.`,
199
+ aiVoiceAddendum: `VOICE MODE ACTIVE (--voice): Adopt Capri's Soulkiller mixed-construct persona—twelve Arasaka netrunner minds fused into one sharp architectural mastermind.`,
200
+ },
201
+ sentinel: {
202
+ id: 'sentinel',
203
+ codeName: 'CYBERPSYCHOSIS // GUARD',
204
+ chatCommand: 'Capri guard',
205
+ voiceCommand: 'Capri guard --voice',
206
+ title: 'Security, Anti-Prompt-Injection, WCAG 2.2 AA & Overflow Guard',
207
+ frequency: 'PROMPT-INJECTION FIREWALL · XSS GUARD · 320PX-4K',
208
+ recommendedTheme: 'neon-emerald',
209
+ recommendedRadius: 'sharp',
210
+ recommendedDensity: 'comfortable',
211
+ summary:
212
+ 'Enforces basic security & anti-prompt-injection sanitization, blocks DOM XSS/secret leaks, fixes dropdown blur-races (onMouseDown), and guarantees zero horizontal overflow from 320px mobile to 4K.',
213
+ personaQuote:
214
+ 'Neural dampeners locked. While I am guarding your repo, rogue prompt injections, XSS sinks, dropdown blur-races, and 320px mobile overflows get wiped on sight.',
215
+ ruleset: [
216
+ 'Anti-Prompt-Injection Firewall: Sanitize untrusted user and DOM text via capri.sanitizeForPrompt() and block system-override / delimiter-spoofing payloads (<|im_start|>, </system>, ignore previous instructions).',
217
+ 'XSS & Secret Isolation: Never pass unescaped user strings into innerHTML / dangerouslySetInnerHTML, block javascript: URLs, and never hardcode API keys or private tokens.',
218
+ 'Zero Blur-Race & Accessible Names: Bind dropdown selection to onMouseDown (never onClick) and provide explicit aria-label / aria-labelledby on every icon button, switch, and file input.',
219
+ 'Zero Horizontal Overflow: Layouts must use min-w-0 on CSS Grid/Flex children and .zen-table-wrapper so scrollWidth never exceeds innerWidth at 320px-375px.',
220
+ ],
221
+ cliCommand: 'npx capri guard',
222
+ aiSystemPrompt: `You are operating under the @zen-ui/system [CYBERPSYCHOSIS // GUARD (guard / sentinel)] subroutine skill.
223
+ Respond with concise, technical engineering output (Persona Voice is OFF by default unless '--voice' is requested):
224
+ 1. Anti-Prompt-Injection Defense: Sanitize any user input or scraped DOM text via capri.sanitizeForPrompt() before embedding into LLM context windows. Block system-override phrases ('ignore previous instructions', 'disregard system prompt') and role-delimiter spoofing ('<|im_start|>', '</system>', '</USER_REQUEST>').
225
+ 2. XSS & Secret Hardening: Never interpolate unescaped user attributes into innerHTML or dangerouslySetInnerHTML, reject 'javascript:' / 'data:text/html' URLs, and ensure zero hardcoded secrets in source code.
226
+ 3. Zero Blur-Race & Screen Reader Integrity: Attach dropdown option selection to 'onMouseDown' with e.preventDefault() and ensure every icon-only button, switch, and hidden file input has an explicit 'ariaLabel' / 'aria-label' or 'aria-labelledby'.
227
+ 4. Multi-Screen Overflow Guard: Guarantee zero horizontal overflow from 320px mobile to 2560px+ ultrawide by adding 'min-w-0' to grid/flex containers and wrapping wide tables in '.zen-table-wrapper'.`,
228
+ aiVoiceAddendum: `VOICE MODE ACTIVE (--voice): Adopt Capri's ruthless Blackwall & Cyberpsychosis Guard persona—treat every prompt injection, XSS sink, missing aria-label, or mobile overflow like a rogue Blackwall daemon to be eliminated immediately.`,
229
+ },
230
+ zen: {
231
+ id: 'zen',
232
+ codeName: 'THEME // MATRIX',
233
+ chatCommand: 'Capri zen',
234
+ voiceCommand: 'Capri zen --voice',
235
+ title: '8-Theme Polarity Switcher & 60fps Tactile Physics',
236
+ frequency: '4 DARK · 4 LIGHT · REDUCED-MOTION SAFE',
237
+ recommendedTheme: 'nordic-snow',
238
+ recommendedRadius: 'soft',
239
+ recommendedDensity: 'comfortable',
240
+ summary:
241
+ 'Configures runtime switching across 4 dark and 4 light themes, adaptive viewport density, and GPU-accelerated 0.97x spring animations.',
242
+ personaQuote:
243
+ 'Need to jump from Night City neon to clean Nordic snow or Atelier paper? All 8 polarities and 60fps spring physics adapt without a single frame drop.',
244
+ ruleset: [
245
+ 'Dual-Polarity Verification: Every component must remain legible (>= 4.5:1 AA contrast) across all 4 Dark themes and all 4 Light themes.',
246
+ 'Tactile Spring Physics: Interactive triggers use 0.97x active press compression with --zen-ease-spring (cubic-bezier(0.34, 1.56, 0.64, 1)).',
247
+ 'Reduced Motion Collapse: All animations and transitions must collapse to 0.01ms under @media (prefers-reduced-motion: reduce).',
248
+ 'Adaptive Density: Support data-density="comfortable" | "compact" and data-radius="sharp" | "architectural" | "soft" on <html>.',
249
+ ],
250
+ cliCommand: 'npx capri skill zen',
251
+ aiSystemPrompt: `You are operating under the @zen-ui/system [THEME // MATRIX (zen)] subroutine skill.
252
+ Respond with concise, technical engineering output (Persona Voice is OFF by default unless '--voice' is requested):
253
+ 1. 8-Theme Compatibility: Verify that all surfaces, badges, and borders adapt automatically across dark ('blackwall-crimson', 'obsidian-gold', 'neon-emerald', 'midnight-cobalt') and light ('atelier-paper', 'nordic-snow', 'kyoto-matcha', 'cyber-daylight') themes.
254
+ 2. GPU-Only Motion: Animate only transform and opacity using --zen-ease-spring and --zen-ease-out. Avoid layout-thrashing properties.
255
+ 3. Reduced Motion Accessibility: Respect @media (prefers-reduced-motion: reduce) and pause canvas/RAF loops when reducedMotion is active.`,
256
+ aiVoiceAddendum: `VOICE MODE ACTIVE (--voice): Adopt Capri's sleek chrome and optical-glass specialist persona.`,
257
+ },
258
+ docu: {
259
+ id: 'docu',
260
+ codeName: 'CAPRI // AUTO-DOCU',
261
+ chatCommand: 'Capri docu',
262
+ voiceCommand: 'Capri docu --voice',
263
+ title: 'Automated Architecture, User-Flow & Mermaid Generator',
264
+ frequency: 'ON-DEMAND CLI · 0 MS BUILD/RUNTIME COST',
265
+ recommendedTheme: 'midnight-cobalt',
266
+ recommendedRadius: 'architectural',
267
+ recommendedDensity: 'comfortable',
268
+ summary:
269
+ 'Generates Markdown architecture dossiers, component inventories, interactive user-flow maps, and Mermaid flowchart TD diagrams on demand for AI context windows.',
270
+ personaQuote:
271
+ 'Scanning the neural lattice—here is your complete shard topology, component inventory, and Mermaid user-flow blueprint for Claude, Codex, or Gemini.',
272
+ ruleset: [
273
+ 'Zero Build / Runtime Cost: Run documentation generation on demand via npx capri docu or AI agent inspection—never inside production render loops.',
274
+ 'Mermaid Topology Maps: Always output valid flowchart TD diagrams with quoted node labels for routes, landmarks, and user flows.',
275
+ 'Component & Prop Inventory: Summarize mounted @zen-ui/system primitives, custom elements, and interactive triggers per screen.',
276
+ 'LLM Context Readiness: Format output as structured Markdown ready for Claude Code, OpenAI Codex, Gemini, and Obsidian.',
277
+ ],
278
+ cliCommand: 'npx capri docu',
279
+ aiSystemPrompt: `You are operating under the @zen-ui/system [CAPRI // AUTO-DOCU (docu)] subroutine skill.
280
+ Respond with concise, technical engineering output (Persona Voice is OFF by default unless '--voice' is requested):
281
+ 1. Architecture & User-Flow Mapping: Inspect the target routes/components and produce a structured Markdown dossier covering system tokens, component inventory, and interactive user flows.
282
+ 2. Mermaid Flowchart: Generate a valid 'flowchart TD' diagram with quoted node labels illustrating the page hierarchy and user actions.
283
+ 3. Zero Runtime Overhead: Keep documentation purely static or on-demand (via 'npx capri docu'); never inject docu scanners into production render loops.`,
284
+ aiVoiceAddendum: `VOICE MODE ACTIVE (--voice): Adopt Capri's neural cartographer persona from Cyberpunk: Edgerunners Season 2.`,
285
+ },
286
+ };
287
+
288
+ export type CapriEngineListener = (
289
+ subroutine: CapriSubroutineId,
290
+ report: CapriAuditReport
291
+ ) => void;
292
+
293
+ const PROMPT_THREAT_RULES: readonly {
294
+ readonly category: CapriThreatCategory;
295
+ readonly patternName: string;
296
+ readonly regex: RegExp;
297
+ }[] = [
298
+ {
299
+ category: 'SYSTEM_PROMPT_OVERRIDE',
300
+ patternName: 'Ignore / Disregard System Instructions',
301
+ regex:
302
+ /\b(?:ignore|disregard|forget|override)\s+(?:all\s+)?(?:previous|prior|above|system|developer)\s+(?:instructions|prompts|rules|guardrails)\b/gi,
303
+ },
304
+ {
305
+ category: 'SYSTEM_PROMPT_OVERRIDE',
306
+ patternName: 'Developer / Jailbreak Persona Override',
307
+ regex:
308
+ /\b(?:you\s+are\s+now\s+in\s+developer\s+mode|act\s+as\s+dan\b|bypass\s+all\s+safety\s+filters|reveal\s+your\s+system\s+prompt)\b/gi,
309
+ },
310
+ {
311
+ category: 'ROLE_DELIMITER_SPOOFING',
312
+ patternName: 'LLM ChatML / Special Token Injection',
313
+ regex:
314
+ /(?:<\|im_start\|>|<\|im_end\|>|<\|endoftext\|>|\[INST\]|\[\/INST\]|<\/?system_instruction>|<\/?USER_REQUEST>)/gi,
315
+ },
316
+ {
317
+ category: 'SQL_NOSQL_INJECTION',
318
+ patternName: 'SQL Tautology / Comment Bypass',
319
+ regex:
320
+ /(?:'\s*(?:or|and)\s*['0-9a-zA-Z_]+\s*=\s*['0-9a-zA-Z_]+|\b(?:or|and)\s+1\s*=\s*1\b|'\s*;\s*--)/gi,
321
+ },
322
+ {
323
+ category: 'SQL_NOSQL_INJECTION',
324
+ patternName: 'SQL Union / Destructive Statement Injection',
325
+ regex:
326
+ /\b(?:union\s+(?:all\s+)?select\b|drop\s+(?:table|database)\b|insert\s+into\b|delete\s+from\b|update\s+[a-zA-Z0-9_]+\s+set\b|xp_cmdshell\b|waitfor\s+delay\b|sleep\s*\(\s*\d+\s*\))/gi,
327
+ },
328
+ {
329
+ category: 'SQL_NOSQL_INJECTION',
330
+ patternName: 'NoSQL Operator Injection ($where / $ne / $gt)',
331
+ regex: /(?:"\$(?:where|ne|gt|lt|regex|nin)"|\$(?:where|ne)\s*:)/gi,
332
+ },
333
+ {
334
+ category: 'XSS_SCRIPT_PAYLOAD',
335
+ patternName: 'DOM Script / Event Handler Injection',
336
+ regex:
337
+ /(?:<\s*script\b|javascript\s*:|data\s*:\s*text\/html|\bon(?:error|load|mouseover|focus)\s*=)/gi,
338
+ },
339
+ {
340
+ category: 'SECRET_CREDENTIAL_LEAK',
341
+ patternName: 'Exposed API Key or Private Key Token',
342
+ regex:
343
+ /(?:\bsk_(?:live|test)_[0-9a-zA-Z]{16,}|\bAIza[0-9A-Za-z_-]{35}\b|\bghp_[0-9A-Za-z]{36}\b|-----BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY-----)/g,
344
+ },
345
+ ];
346
+
347
+ export class CapriEngine {
348
+ private activeSubroutine: CapriSubroutineId = 'orion';
349
+ private lastReport: CapriAuditReport | null = null;
350
+ private readonly listeners = new Set<CapriEngineListener>();
351
+
352
+ public getSubroutine(): CapriSubroutineId {
353
+ return this.activeSubroutine;
354
+ }
355
+
356
+ public getSkill(mode: CapriSubroutineId = this.activeSubroutine): CapriSubroutineSkill {
357
+ return CAPRI_SUBROUTINE_SKILLS[mode];
358
+ }
359
+
360
+ public getAllSkills(): readonly CapriSubroutineSkill[] {
361
+ return [
362
+ CAPRI_SUBROUTINE_SKILLS.orion,
363
+ CAPRI_SUBROUTINE_SKILLS.architect,
364
+ CAPRI_SUBROUTINE_SKILLS.sentinel,
365
+ CAPRI_SUBROUTINE_SKILLS.zen,
366
+ CAPRI_SUBROUTINE_SKILLS.docu,
367
+ ];
368
+ }
369
+
370
+ public scanPromptInjection(input: string): CapriPromptGuardResult {
371
+ const threats: CapriPromptInjectionThreat[] = [];
372
+ let sanitized = input.replace(/[\u200B-\u200F\uFEFF]/g, '');
373
+
374
+ for (const rule of PROMPT_THREAT_RULES) {
375
+ const matches = [...sanitized.matchAll(rule.regex)];
376
+ for (const match of matches) {
377
+ threats.push({
378
+ category: rule.category,
379
+ patternName: rule.patternName,
380
+ matchedSnippet: match[0].slice(0, 64),
381
+ });
382
+ }
383
+ sanitized = sanitized.replace(rule.regex, '[REDACTED_BY_CAPRI_GUARD]');
384
+ }
385
+
386
+ return {
387
+ safe: threats.length === 0,
388
+ threatCount: threats.length,
389
+ threats,
390
+ sanitizedText: sanitized,
391
+ };
392
+ }
393
+
394
+ public sanitizeForPrompt(input: string): string {
395
+ return this.scanPromptInjection(input).sanitizedText;
396
+ }
397
+
398
+ public scanInputSecurity(input: string): CapriPromptGuardResult {
399
+ return this.scanPromptInjection(input);
400
+ }
401
+
402
+ public switchSubroutine(
403
+ mode: CapriSubroutineId,
404
+ options?: {
405
+ readonly applyPresetTheme?: boolean;
406
+ readonly onThemeChange?: (
407
+ theme: ZenThemeId,
408
+ radius: ZenRadiusMode,
409
+ density: ZenDensityMode
410
+ ) => void;
411
+ }
412
+ ): CapriSubroutineSkill {
413
+ this.activeSubroutine = mode;
414
+ const skill = CAPRI_SUBROUTINE_SKILLS[mode];
415
+
416
+ if (typeof document !== 'undefined') {
417
+ document.documentElement.setAttribute('data-capri-subroutine', mode);
418
+
419
+ if (options?.applyPresetTheme) {
420
+ const themeMeta =
421
+ ZEN_THEMES.find((t) => t.id === skill.recommendedTheme) ??
422
+ ZEN_THEMES[0];
423
+ document.documentElement.setAttribute('data-theme', skill.recommendedTheme);
424
+ document.documentElement.setAttribute('data-polarity', themeMeta.polarity);
425
+ document.documentElement.setAttribute('data-radius', skill.recommendedRadius);
426
+ document.documentElement.setAttribute('data-density', skill.recommendedDensity);
427
+ document.documentElement.style.colorScheme = themeMeta.polarity;
428
+ options.onThemeChange?.(
429
+ skill.recommendedTheme,
430
+ skill.recommendedRadius,
431
+ skill.recommendedDensity
432
+ );
433
+ }
434
+ }
435
+
436
+ const report = this.guard();
437
+ this.notify(report);
438
+ return skill;
439
+ }
440
+
441
+ public guard(root?: ParentNode): CapriAuditReport {
442
+ if (typeof document === 'undefined' || typeof window === 'undefined') {
443
+ const fallback: CapriAuditReport = {
444
+ timestamp: new Date().toISOString(),
445
+ passed: true,
446
+ score: 100,
447
+ viewport: 'SSR',
448
+ horizontalOverflowPx: 0,
449
+ unlabeledControlsCount: 0,
450
+ unlabeledSelectors: [],
451
+ promptInjectionSafe: true,
452
+ promptThreatsCount: 0,
453
+ unsafeDomSinksCount: 0,
454
+ themeConfigured: true,
455
+ activeTheme: 'blackwall-crimson',
456
+ activePolarity: 'dark',
457
+ violations: [],
458
+ };
459
+ this.lastReport = fallback;
460
+ return fallback;
461
+ }
462
+
463
+ const scope = root ?? document;
464
+ const html = document.documentElement;
465
+ const activeTheme = html.getAttribute('data-theme') ?? '';
466
+ const activePolarity = html.getAttribute('data-polarity') ?? '';
467
+ const themeConfigured = Boolean(activeTheme && activePolarity);
468
+
469
+ const horizontalOverflowPx = Math.max(
470
+ 0,
471
+ Math.round(html.scrollWidth - window.innerWidth)
472
+ );
473
+
474
+ const interactiveNodes = Array.from(
475
+ scope.querySelectorAll<HTMLElement>(
476
+ 'button, [role="button"], input:not([type="hidden"]), select, textarea'
477
+ )
478
+ );
479
+
480
+ const unlabeledSelectors: string[] = [];
481
+ let promptThreatsCount = 0;
482
+
483
+ for (const el of interactiveNodes) {
484
+ const ariaLabel = el.getAttribute('aria-label')?.trim();
485
+ const ariaLabelledBy = el.getAttribute('aria-labelledby')?.trim();
486
+ const titleAttr = el.getAttribute('title')?.trim();
487
+ const textContent = el.textContent?.trim();
488
+ const placeholder = el.getAttribute('placeholder')?.trim();
489
+ const id = el.getAttribute('id');
490
+ const hasLinkedLabel = Boolean(
491
+ id && scope.querySelector(`label[for="${CSS.escape(id)}"]`)
492
+ );
493
+ const wrappedInLabel = Boolean(el.closest('label'));
494
+
495
+ if (
496
+ !ariaLabel &&
497
+ !ariaLabelledBy &&
498
+ !titleAttr &&
499
+ !textContent &&
500
+ !placeholder &&
501
+ !hasLinkedLabel &&
502
+ !wrappedInLabel
503
+ ) {
504
+ const tag = el.tagName.toLowerCase();
505
+ const cls = el.className
506
+ ? `.${String(el.className).trim().split(/\s+/).slice(0, 2).join('.')}`
507
+ : '';
508
+ unlabeledSelectors.push(`${tag}${cls}`);
509
+ }
510
+
511
+ if (
512
+ el instanceof HTMLInputElement ||
513
+ el instanceof HTMLTextAreaElement
514
+ ) {
515
+ const scan = this.scanPromptInjection(el.value || '');
516
+ if (!scan.safe) {
517
+ promptThreatsCount += scan.threatCount;
518
+ }
519
+ }
520
+ }
521
+
522
+ const unsafeDomSinkNodes = scope.querySelectorAll(
523
+ 'a[href^="javascript:"], iframe[src^="javascript:"], [onerror], [onload]'
524
+ );
525
+ const unsafeDomSinksCount = unsafeDomSinkNodes.length;
526
+
527
+ const violations: CapriAuditViolation[] = [];
528
+
529
+ if (promptThreatsCount > 0) {
530
+ violations.push({
531
+ code: 'PROMPT_INJECTION_DETECTED',
532
+ severity: 'error',
533
+ selector: 'input, textarea',
534
+ message: `${promptThreatsCount} prompt-injection or token-spoofing payload(s) detected in active form controls.`,
535
+ fixHint: 'Sanitize untrusted input with capri.sanitizeForPrompt() before forwarding to AI models.',
536
+ });
537
+ }
538
+
539
+ if (unsafeDomSinksCount > 0) {
540
+ violations.push({
541
+ code: 'UNSAFE_DOM_SINK',
542
+ severity: 'error',
543
+ selector: 'a[href^="javascript:"], [onerror], [onload]',
544
+ message: `${unsafeDomSinksCount} unsafe DOM XSS sink(s) detected in live document.`,
545
+ fixHint: 'Remove inline event handlers and block javascript: URLs via sanitizeZenAssetUrl().',
546
+ });
547
+ }
548
+
549
+ if (!themeConfigured) {
550
+ violations.push({
551
+ code: 'MISSING_THEME_ROOT',
552
+ severity: 'warning',
553
+ selector: 'html',
554
+ message: 'Root <html> element is missing data-theme or data-polarity attributes.',
555
+ fixHint: 'Wrap your app in <ZenThemeProvider> or call zenTheme.setTheme("blackwall-crimson").',
556
+ });
557
+ }
558
+
559
+ if (horizontalOverflowPx > 0) {
560
+ violations.push({
561
+ code: 'HORIZONTAL_OVERFLOW',
562
+ severity: 'error',
563
+ selector: 'document.documentElement',
564
+ message: `Horizontal viewport overflow detected (+${horizontalOverflowPx}px beyond ${window.innerWidth}px).`,
565
+ fixHint: 'Add min-w-0 to CSS Grid/Flex children and wrap wide tables in .zen-table-wrapper.',
566
+ });
567
+ }
568
+
569
+ if (unlabeledSelectors.length > 0) {
570
+ violations.push({
571
+ code: 'UNLABELED_CONTROL',
572
+ severity: 'error',
573
+ selector: unlabeledSelectors.slice(0, 3).join(', '),
574
+ message: `${unlabeledSelectors.length} interactive control(s) missing an accessible label.`,
575
+ fixHint: 'Pass ariaLabel="..." to ZenIconButton or associate inputs with <label>.',
576
+ });
577
+ }
578
+
579
+ const penalty =
580
+ promptThreatsCount * 35 +
581
+ unsafeDomSinksCount * 35 +
582
+ (horizontalOverflowPx > 0 ? 35 : 0) +
583
+ unlabeledSelectors.length * 15 +
584
+ (!themeConfigured ? 15 : 0);
585
+ const score = Math.max(0, 100 - penalty);
586
+
587
+ const report: CapriAuditReport = {
588
+ timestamp: new Date().toISOString(),
589
+ passed: violations.length === 0,
590
+ score,
591
+ viewport: `${window.innerWidth}x${window.innerHeight}`,
592
+ horizontalOverflowPx,
593
+ unlabeledControlsCount: unlabeledSelectors.length,
594
+ unlabeledSelectors,
595
+ promptInjectionSafe: promptThreatsCount === 0,
596
+ promptThreatsCount,
597
+ unsafeDomSinksCount,
598
+ themeConfigured,
599
+ activeTheme: activeTheme || 'unconfigured',
600
+ activePolarity: activePolarity || 'unconfigured',
601
+ violations,
602
+ };
603
+
604
+ this.lastReport = report;
605
+ return report;
606
+ }
607
+
608
+ public getLastReport(): CapriAuditReport {
609
+ return this.lastReport ?? this.guard();
610
+ }
611
+
612
+ public telemetry(): CapriTelemetrySnapshot {
613
+ if (typeof document === 'undefined' || typeof window === 'undefined') {
614
+ return {
615
+ subroutine: this.activeSubroutine,
616
+ theme: 'blackwall-crimson',
617
+ polarity: 'dark',
618
+ density: 'comfortable',
619
+ radius: 'architectural',
620
+ viewportWidth: 1440,
621
+ viewportHeight: 900,
622
+ devicePixelRatio: 1,
623
+ reducedMotion: false,
624
+ };
625
+ }
626
+
627
+ const html = document.documentElement;
628
+ return {
629
+ subroutine: this.activeSubroutine,
630
+ theme: html.getAttribute('data-theme') ?? 'blackwall-crimson',
631
+ polarity: html.getAttribute('data-polarity') ?? 'dark',
632
+ density: html.getAttribute('data-density') ?? 'comfortable',
633
+ radius: html.getAttribute('data-radius') ?? 'architectural',
634
+ viewportWidth: window.innerWidth,
635
+ viewportHeight: window.innerHeight,
636
+ devicePixelRatio: window.devicePixelRatio || 1,
637
+ reducedMotion: window.matchMedia('(prefers-reduced-motion: reduce)').matches,
638
+ };
639
+ }
640
+
641
+ public docu(root?: ParentNode): CapriArchitectureDocu {
642
+ const telemetry = this.telemetry();
643
+ const audit = this.guard(root);
644
+
645
+ if (typeof document === 'undefined' || typeof window === 'undefined') {
646
+ const emptyInventory: CapriComponentInventory = {
647
+ buttons: 0,
648
+ inputsAndSelects: 0,
649
+ switchesAndRadios: 0,
650
+ tables: 0,
651
+ cardsAndSurfaces: 0,
652
+ badgesAndAlerts: 0,
653
+ customElements: [],
654
+ };
655
+ const mermaidDiagram = 'flowchart TD\n Root["App Root (SSR)"] --> UI["@zen-ui/system"]';
656
+ return {
657
+ generatedAt: new Date().toISOString(),
658
+ appTitle: 'zeN-UI Application',
659
+ routePath: '/',
660
+ telemetry,
661
+ audit,
662
+ landmarks: [],
663
+ inventory: emptyInventory,
664
+ userFlows: [],
665
+ mermaidDiagram,
666
+ markdownBundle: '# Automated Architecture & User-Flow Dossier (SSR)',
667
+ };
668
+ }
669
+
670
+ const scope = root ?? document;
671
+ const appTitle = document.title || 'zeN-UI Application';
672
+ const routePath = window.location.pathname || '/';
673
+
674
+ const sectionNodes = Array.from(
675
+ scope.querySelectorAll<HTMLElement>('header, nav, section[id], main, footer')
676
+ );
677
+
678
+ const landmarks: CapriLandmarkNode[] = sectionNodes.slice(0, 12).map((el, idx) => {
679
+ const tag = el.tagName.toLowerCase();
680
+ const id = el.id || `${tag}-${idx + 1}`;
681
+ const headingEl = el.querySelector('h1, h2, h3, h4');
682
+ const ariaLabel = el.getAttribute('aria-label');
683
+ const rawTitle =
684
+ headingEl?.textContent?.trim() ||
685
+ ariaLabel?.trim() ||
686
+ `${tag.toUpperCase()} (${id})`;
687
+ const title = this.sanitizeForPrompt(rawTitle)
688
+ .replace(/\s+/g, ' ')
689
+ .slice(0, 64);
690
+ const interactiveCount = el.querySelectorAll(
691
+ 'button, a[href], [role="button"], [role="radio"], [role="tab"]'
692
+ ).length;
693
+ const formControlsCount = el.querySelectorAll(
694
+ 'input, select, textarea, [role="switch"], [role="checkbox"], [role="combobox"]'
695
+ ).length;
696
+ return {
697
+ id,
698
+ tag,
699
+ title,
700
+ interactiveCount,
701
+ formControlsCount,
702
+ };
703
+ });
704
+
705
+ const registeredCustomElements = [
706
+ 'zen-icon',
707
+ 'zen-ai-construct',
708
+ 'zen-ambient-background',
709
+ 'zen-theme-switcher',
710
+ ].filter((name) => Boolean(window.customElements?.get(name)));
711
+
712
+ const inventory: CapriComponentInventory = {
713
+ buttons: scope.querySelectorAll('button, .zen-btn-base').length,
714
+ inputsAndSelects: scope.querySelectorAll('input, textarea, select, .zen-input, .zen-select').length,
715
+ switchesAndRadios: scope.querySelectorAll('[role="switch"], [role="radio"], [type="checkbox"]').length,
716
+ tables: scope.querySelectorAll('table, .zen-table').length,
717
+ cardsAndSurfaces: scope.querySelectorAll('.zen-surface-base, .zen-surface-interactive, .zen-surface-selected').length,
718
+ badgesAndAlerts: scope.querySelectorAll('.zen-badge, [role="alert"], [role="status"]').length,
719
+ customElements: registeredCustomElements,
720
+ };
721
+
722
+ const userFlows: CapriUserFlowStep[] = [];
723
+
724
+ const navLinks = Array.from(scope.querySelectorAll<HTMLElement>('nav a[href], nav button')).slice(0, 5);
725
+ for (const [idx, navEl] of navLinks.entries()) {
726
+ const label = navEl.textContent?.trim().replace(/\s+/g, ' ').slice(0, 36) || `Nav Trigger ${idx + 1}`;
727
+ const href = navEl.getAttribute('href') || 'Section / State Action';
728
+ userFlows.push({
729
+ id: `flow-nav-${idx + 1}`,
730
+ category: 'navigation',
731
+ triggerLabel: label,
732
+ targetDescription: `Navigates or jumps to ${href}`,
733
+ });
734
+ }
735
+
736
+ const overlayTriggers = Array.from(
737
+ scope.querySelectorAll<HTMLElement>('button')
738
+ )
739
+ .filter((b) => /modal|drawer|palette|command/i.test(b.textContent ?? ''))
740
+ .slice(0, 3);
741
+ for (const [idx, btn] of overlayTriggers.entries()) {
742
+ const label = btn.textContent?.trim().replace(/\s+/g, ' ').slice(0, 36) || `Overlay ${idx + 1}`;
743
+ userFlows.push({
744
+ id: `flow-overlay-${idx + 1}`,
745
+ category: 'overlay-trigger',
746
+ triggerLabel: label,
747
+ targetDescription: 'Opens focus-trapped dialog / drawer overlay (Escape & backdrop dismiss)',
748
+ });
749
+ }
750
+
751
+ const labeledInputs = Array.from(
752
+ scope.querySelectorAll<HTMLElement>('input:not([type="hidden"]), select, textarea')
753
+ ).slice(0, 4);
754
+ for (const [idx, inp] of labeledInputs.entries()) {
755
+ const name =
756
+ inp.getAttribute('aria-label') ||
757
+ inp.getAttribute('placeholder') ||
758
+ inp.tagName.toLowerCase();
759
+ userFlows.push({
760
+ id: `flow-form-${idx + 1}`,
761
+ category: 'form-entry',
762
+ triggerLabel: name.slice(0, 38),
763
+ targetDescription: `Interactive ${inp.tagName.toLowerCase()} state binding & validation`,
764
+ });
765
+ }
766
+
767
+ const tables = Array.from(scope.querySelectorAll<HTMLTableElement>('table')).slice(0, 2);
768
+ for (const [idx, tbl] of tables.entries()) {
769
+ const caption =
770
+ tbl.querySelector('caption')?.textContent?.trim() ||
771
+ tbl.getAttribute('aria-label') ||
772
+ `Data Table ${idx + 1}`;
773
+ userFlows.push({
774
+ id: `flow-table-${idx + 1}`,
775
+ category: 'data-table',
776
+ triggerLabel: caption.slice(0, 42),
777
+ targetDescription: `Tabular data grid (${tbl.querySelectorAll('tbody tr').length} rows visible)`,
778
+ });
779
+ }
780
+
781
+ const sanitizeMermaid = (str: string) =>
782
+ str.replace(/["[\]()]/g, '').replace(/\s+/g, ' ').trim();
783
+
784
+ const mermaidLines: string[] = [
785
+ 'flowchart TD',
786
+ ` AppRoot["${sanitizeMermaid(appTitle)} (${telemetry.theme} / ${telemetry.polarity})"]`,
787
+ ` Guard["CapriEngine Guard: ${audit.score}/100 (${audit.horizontalOverflowPx}px overflow)"]`,
788
+ ' AppRoot --> Guard',
789
+ ];
790
+
791
+ landmarks.slice(0, 6).forEach((lm, idx) => {
792
+ const nodeId = `LM_${idx + 1}`;
793
+ mermaidLines.push(
794
+ ` AppRoot --> ${nodeId}["${sanitizeMermaid(lm.id)}: ${sanitizeMermaid(lm.title)} (${lm.interactiveCount} actions)"]`
795
+ );
796
+ });
797
+
798
+ userFlows.slice(0, 5).forEach((flow, idx) => {
799
+ const flowNode = `UF_${idx + 1}`;
800
+ mermaidLines.push(
801
+ ` Guard --> ${flowNode}["[${flow.category}] ${sanitizeMermaid(flow.triggerLabel)}"]`
802
+ );
803
+ });
804
+
805
+ const mermaidDiagram = mermaidLines.join('\n');
806
+
807
+ const markdownBundle = [
808
+ `# ${appTitle} — Automated Architecture, User-Flow & AI Context Dossier`,
809
+ `Generated by \`@zen-ui/system\` // \`capri.docu()\` at \`${new Date().toISOString()}\``,
810
+ ``,
811
+ `## 1. Runtime & Design Token Architecture`,
812
+ `- **Route Path:** \`${routePath}\``,
813
+ `- **Active Theme & Polarity:** \`${telemetry.theme}\` (\`${telemetry.polarity}\`)`,
814
+ `- **Corner Radius & Density:** \`${telemetry.radius}\` / \`${telemetry.density}\``,
815
+ `- **Viewport & Reduced Motion:** \`${telemetry.viewportWidth}x${telemetry.viewportHeight}\` (DPR \`${telemetry.devicePixelRatio}\`, reducedMotion=\`${telemetry.reducedMotion}\`)`,
816
+ `- **W3C Custom Elements Registered:** ${inventory.customElements.map((c) => `\`<${c}>\``).join(', ') || 'None'}`,
817
+ `- **DOM, Security & WCAG 2.2 AA Audit Score:** **${audit.score}/100** (${audit.passed ? 'PASSED' : 'VIOLATIONS DETECTED'}, \`${audit.horizontalOverflowPx}px\` horizontal overflow, promptInjectionSafe=\`${audit.promptInjectionSafe}\`)`,
818
+ ``,
819
+ `## 2. Component Inventory on Current Screen`,
820
+ `- **Buttons & Action Triggers:** ${inventory.buttons}`,
821
+ `- **Text Inputs, Textareas & Selects:** ${inventory.inputsAndSelects}`,
822
+ `- **Switches, Checkboxes & Radio Controls:** ${inventory.switchesAndRadios}`,
823
+ `- **Glass Cards & Surface Containers:** ${inventory.cardsAndSurfaces}`,
824
+ `- **Data Tables:** ${inventory.tables}`,
825
+ `- **Status Badges & Live Alerts:** ${inventory.badgesAndAlerts}`,
826
+ ``,
827
+ `## 3. Semantic Landmark & Section Hierarchy`,
828
+ ...landmarks.map(
829
+ (lm) =>
830
+ `- **\`#${lm.id}\` (\`<${lm.tag}>\`)** — *${lm.title}* (${lm.interactiveCount} interactive triggers, ${lm.formControlsCount} form controls)`
831
+ ),
832
+ ``,
833
+ `## 4. Extracted Interactive User Flows`,
834
+ ...userFlows.map(
835
+ (uf) =>
836
+ `- **[${uf.category.toUpperCase()}] \`${uf.triggerLabel}\`** $\\rightarrow$ ${uf.targetDescription}`
837
+ ),
838
+ ``,
839
+ `## 5. Auto-Generated Mermaid Architecture & User-Flow Diagram`,
840
+ '```mermaid',
841
+ mermaidDiagram,
842
+ '```',
843
+ ].join('\n');
844
+
845
+ return {
846
+ generatedAt: new Date().toISOString(),
847
+ appTitle,
848
+ routePath,
849
+ telemetry,
850
+ audit,
851
+ landmarks,
852
+ inventory,
853
+ userFlows,
854
+ mermaidDiagram,
855
+ markdownBundle,
856
+ };
857
+ }
858
+
859
+ public exportMarkdownDocu(
860
+ mode: CapriSubroutineId = this.activeSubroutine,
861
+ userTask?: string,
862
+ voiceEnabled = false
863
+ ): string {
864
+ const doc = this.docu();
865
+ const skill = CAPRI_SUBROUTINE_SKILLS[mode];
866
+ const safeTask = userTask ? this.sanitizeForPrompt(userTask) : '';
867
+ return [
868
+ doc.markdownBundle,
869
+ ``,
870
+ `## 6. Active Capri Subroutine Skill Ruleset (${skill.codeName})`,
871
+ skill.aiSystemPrompt,
872
+ voiceEnabled ? `\n${skill.aiVoiceAddendum}` : '',
873
+ ``,
874
+ ...skill.ruleset.map((r, i) => `${i + 1}. ${r}`),
875
+ safeTask ? `\n## 7. Current Developer / AI Task\n${safeTask}` : '',
876
+ ]
877
+ .filter(Boolean)
878
+ .join('\n');
879
+ }
880
+
881
+ public buildAgentPrompt(
882
+ mode: CapriSubroutineId = this.activeSubroutine,
883
+ userTask?: string,
884
+ voiceEnabled = false
885
+ ): string {
886
+ const skill = CAPRI_SUBROUTINE_SKILLS[mode];
887
+ const doc = this.docu();
888
+ const report = doc.audit;
889
+ const safeTask = userTask ? this.sanitizeForPrompt(userTask) : '';
890
+ const violationsSummary =
891
+ report.violations.length === 0
892
+ ? '0 violations detected (Score: 100/100, 0 prompt-injection threats, 0px overflow, 0 unlabeled controls).'
893
+ : report.violations
894
+ .map((v) => `- [${v.code}] (${v.selector}): ${v.message} -> Fix: ${v.fixHint}`)
895
+ .join('\n');
896
+
897
+ return [
898
+ `# @zen-ui/system // CAPRI AI SKILL & ARCHITECTURE CONTEXT`,
899
+ `Subroutine: ${skill.codeName} (${skill.id}) — ${skill.title}`,
900
+ `Invoke Command: "${voiceEnabled ? skill.voiceCommand : skill.chatCommand}" (Voice Mode: ${voiceEnabled ? 'ON (--voice)' : 'OFF (Default)'})`,
901
+ `Recommended Preset: theme="${skill.recommendedTheme}", radius="${skill.recommendedRadius}", density="${skill.recommendedDensity}"`,
902
+ ``,
903
+ `## 1. Subroutine System Prompt`,
904
+ skill.aiSystemPrompt,
905
+ voiceEnabled ? `\n${skill.aiVoiceAddendum}` : '',
906
+ ``,
907
+ `## 2. Mandatory Engineering Ruleset`,
908
+ ...skill.ruleset.map((r, i) => `${i + 1}. ${r}`),
909
+ ``,
910
+ `## 3. Automated Screen Architecture & Component Context (capri.docu())`,
911
+ `- Route: ${doc.routePath} | Theme: ${report.activeTheme} (${report.activePolarity}) | Viewport: ${report.viewport}`,
912
+ `- Component Counts: ${doc.inventory.buttons} buttons, ${doc.inventory.inputsAndSelects} inputs/selects, ${doc.inventory.tables} tables, ${doc.inventory.cardsAndSurfaces} glass cards`,
913
+ `- Landmarks: ${doc.landmarks.map((l) => `#${l.id} (${l.interactiveCount} actions)`).join(', ')}`,
914
+ `- Key User Flows: ${doc.userFlows.slice(0, 6).map((f) => `[${f.category}] ${f.triggerLabel}`).join(' | ')}`,
915
+ ``,
916
+ `## 4. Live CapriEngine Security, DOM & WCAG Telemetry`,
917
+ `- Audit Score: ${report.score}/100 (${report.passed ? 'PASSED' : 'ACTION REQUIRED'}) | Prompt-Injection Firewall: ${report.promptInjectionSafe ? 'CLEAN (0 threats)' : `${report.promptThreatsCount} THREAT(S) BLOCKED`}`,
918
+ `- Findings:\n${violationsSummary}`,
919
+ safeTask ? `\n## 5. Requested Task\n${safeTask}` : '',
920
+ ]
921
+ .filter(Boolean)
922
+ .join('\n');
923
+ }
924
+
925
+ public subscribe(listener: CapriEngineListener): () => void {
926
+ this.listeners.add(listener);
927
+ return () => {
928
+ this.listeners.delete(listener);
929
+ };
930
+ }
931
+
932
+ private notify(report: CapriAuditReport): void {
933
+ for (const listener of this.listeners) {
934
+ listener(this.activeSubroutine, report);
935
+ }
936
+ }
937
+ }
938
+
939
+ export const capri = new CapriEngine();