File size: 39,074 Bytes
aae3922
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c1e920a
aae3922
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
"""
╔══════════════════════════════════════════════════════════╗
β•‘  OMNI-VIBE CORE β€” Specialized Swarm Architecture       β•‘
β•‘                                                        β•‘
β•‘  The Athanor: LiteRT engine, sub-second latency        β•‘
β•‘                                                        β•‘
β•‘  POSE ARCHITECT: full-stack schema + zero-config DB    β•‘
β•‘                  + Google OAuth out-of-the-box          β•‘
β•‘  POSE PAINTER:   Liquid Glass design system enforced   β•‘
β•‘                  across every generated app             β•‘
β•‘  POSE AUDITOR:   step-by-step reasoning, verify code   β•‘
β•‘                  before every hot-reload                β•‘
β•‘                                                        β•‘
β•‘  All Poses run locally β€” zero external API calls.      β•‘
β•‘  Sub-second Reflect-Select loop with regex engine.     β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
"""

import asyncio, json, os, re, time, uuid, textwrap, hashlib
from pathlib import Path
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass, field


# ═══════════════════════════════════════════════════════
#  POSES β€” The Specialized Swarm
# ═══════════════════════════════════════════════════════

@dataclass
class AuditFinding:
    line: int
    severity: str  # ERROR | WARN | INFO
    message: str
    fix: Optional[str] = None


# ─── LIQUID GLASS DESIGN SYSTEM ────────────────────────
#  Canonical CSS variables injected into every output

LIQUID_GLASS_CSS = """
:root {
  --glass-bg: rgba(255,255,255,.03);
  --glass-border: rgba(255,255,255,.06);
  --glass-hover: rgba(255,255,255,.08);
  --purple: #8B5CF6; --cyan: #06B6D4; --green: #10B981; --gold: #F59E0B;
  --text: #e0e0ff; --text2: #9090b0; --text3: #606080;
  --bg1: #0a0a1a; --bg2: #1a0a2e;
  --radius: 20px; --radius-sm: 12px;
  --font: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  --mono: 'SF Mono','Fira Code',monospace;
}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
body{font-family:var(--font);background:linear-gradient(135deg,var(--bg1),var(--bg2),#0a1a2e);color:var(--text);min-height:100vh;-webkit-font-smoothing:antialiased}
::selection{background:rgba(139,92,246,.5);color:#fff}
.glass{background:var(--glass-bg);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border:1px solid var(--glass-border);border-radius:var(--radius)}
.glass-hover:hover{background:var(--glass-hover);border-color:rgba(139,92,246,.2)}
.btn{display:inline-flex;align-items:center;gap:.5rem;padding:.75rem 1.75rem;background:linear-gradient(135deg,var(--purple),var(--cyan));border:none;border-radius:var(--radius-sm);color:#fff;font-weight:600;cursor:pointer;transition:transform .15s,box-shadow .15s}
.btn:hover{transform:translateY(-1px);box-shadow:0 4px 20px rgba(139,92,246,.4)}
.btn-outline{background:var(--glass-bg);border:1px solid var(--glass-border);color:var(--text2)}
.input-glass{width:100%;padding:.75rem 1rem;background:var(--glass-bg);border:1px solid var(--glass-border);border-radius:var(--radius-sm);color:var(--text);font-size:.95rem;outline:none;transition:border-color .15s,box-shadow .15s}
.input-glass:focus{border-color:rgba(139,92,246,.4);box-shadow:0 0 20px rgba(139,92,246,.1)}
.card{background:var(--glass-bg);backdrop-filter:blur(20px);border:1px solid var(--glass-border);border-radius:var(--radius);padding:1.5rem}
.gradient-text{background:linear-gradient(135deg,var(--purple),var(--cyan),var(--green));-webkit-background-clip:text;-webkit-text-fill-color:transparent}
"""

LIQUID_GLASS_LOGO = """
<svg width="48" height="48" viewBox="0 0 64 64" id="wizard-hat" style="filter:drop-shadow(0 0 20px rgba(139,92,246,.6))">
<defs><linearGradient id="hg" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:#8B5CF6"/><stop offset="50%" style="stop-color:#06B6D4"/><stop offset="100%" style="stop-color:#10B981"/></linearGradient></defs>
<path d="M32 8 L8 48 L32 40 L56 48 Z" fill="url(#hg)" stroke="rgba(255,255,255,.3)" stroke-width="1.5"/>
<ellipse cx="32" cy="48" rx="26" ry="7" fill="none" stroke="url(#hg)" stroke-width="2" opacity=".6"/>
</svg>
"""

# ─── ZERO-CONFIG DATABASE SCHEMA ───────────────────────

ZERO_DB_SCHEMA = """
-- Omni-Vibe Zero-Config Database
-- Uses SQLite (built-in, zero setup) with WAL mode

CREATE TABLE IF NOT EXISTS users (
    id TEXT PRIMARY KEY,
    email TEXT UNIQUE NOT NULL,
    name TEXT,
    avatar_url TEXT,
    google_id TEXT UNIQUE,
    created_at TEXT DEFAULT (datetime('now')),
    updated_at TEXT DEFAULT (datetime('now'))
);

CREATE TABLE IF NOT EXISTS sessions (
    id TEXT PRIMARY KEY,
    user_id TEXT NOT NULL REFERENCES users(id),
    token TEXT UNIQUE NOT NULL,
    expires_at TEXT NOT NULL,
    created_at TEXT DEFAULT (datetime('now'))
);

CREATE TABLE IF NOT EXISTS items (
    id TEXT PRIMARY KEY,
    user_id TEXT NOT NULL REFERENCES users(id),
    title TEXT NOT NULL,
    content TEXT,
    status TEXT DEFAULT 'active',
    created_at TEXT DEFAULT (datetime('now')),
    updated_at TEXT DEFAULT (datetime('now'))
);

CREATE INDEX IF NOT EXISTS idx_items_user ON items(user_id);
CREATE INDEX IF NOT EXISTS idx_sessions_token ON sessions(token);
"""

# ─── GOOGLE OAUTH SERVER-SIDE ──────────────────────────

GOOGLE_OAUTH_PY = """
import os, json, httpx
from urllib.parse import urlencode

GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", "")
GOOGLE_CLIENT_SECRET = os.environ.get("GOOGLE_CLIENT_SECRET", "")
GOOGLE_REDIRECT = os.environ.get("GOOGLE_REDIRECT_URI", "http://localhost:8080/auth/callback")

def get_auth_url(state: str = "") -> str:
    params = {
        "client_id": GOOGLE_CLIENT_ID,
        "redirect_uri": GOOGLE_REDIRECT,
        "response_type": "code",
        "scope": "openid email profile",
        "state": state,
    }
    return f"https://accounts.google.com/o/oauth2/v2/auth?{urlencode(params)}"

async def exchange_code(code: str) -> dict:
    async with httpx.AsyncClient() as c:
        resp = await c.post("https://oauth2.googleapis.com/token", data={
            "code": code, "client_id": GOOGLE_CLIENT_ID,
            "client_secret": GOOGLE_CLIENT_SECRET,
            "redirect_uri": GOOGLE_REDIRECT, "grant_type": "authorization_code",
        })
        tokens = resp.json()
        user = await c.get("https://www.googleapis.com/oauth2/v2/userinfo",
            headers={"Authorization": f"Bearer {tokens['access_token']}"})
        return {**tokens, "user": user.json()}
"""

GOOGLE_OAUTH_JS = """
// Google OAuth client-side β€” Liquid Glass styled
async function initGoogleAuth() {
  const btn = document.getElementById('google-auth-btn');
  if (!btn) return;
  
  btn.addEventListener('click', () => {
    const state = crypto.randomUUID();
    localStorage.setItem('oauth_state', state);
    window.location.href = `/auth/google?state=${state}`;
  });
  
  // Check for callback
  const params = new URLSearchParams(window.location.search);
  if (params.get('code')) {
    const resp = await fetch('/auth/callback?' + params.toString());
    const data = await resp.json();
    if (data.user) {
      localStorage.setItem('user', JSON.stringify(data.user));
      window.location.href = '/';
    }
  }
}
document.addEventListener('DOMContentLoaded', initGoogleAuth);
"""


# ═══════════════════════════════════════════════════════
#  POSE ARCHITECT β€” Full-Stack Schema Generator
# ═══════════════════════════════════════════════════════

class PoseArchitect:
    """
    Generates full-stack application architectures.
    Every output includes: zero-config SQLite DB + Google OAuth.
    """

    STACKS = {
        "html":   {"backend": None,         "frontend": "Vanilla HTML/CSS/JS + Liquid Glass"},
        "flask":  {"backend": "Flask+SQLite","frontend": "Jinja2 + Liquid Glass"},
        "fastapi": {"backend": "FastAPI+SQLite","frontend": "HTMX + Liquid Glass"},
        "node":   {"backend": "Express+better-sqlite3","frontend": "Vanilla + Liquid Glass"},
    }

    def design(self, prompt: str) -> Dict:
        """Analyze prompt and design the full-stack schema."""
        p = prompt.lower()

        # Detect stack
        stack = "html"
        if any(w in p for w in ["api","backend","server","flask","fastapi"]):
            stack = "fastapi" if "fastapi" in p else "flask"
        elif any(w in p for w in ["node","express","javascript backend"]):
            stack = "node"
        elif any(w in p for w in ["app","saas","platform","dashboard","database"]):
            stack = "fastapi"

        # Detect features
        features = []
        if any(w in p for w in ["auth","login","signup","oauth","google"]):
            features.append("google-oauth")
        if any(w in p for w in ["database","db","storage","data","crud"]):
            features.append("zero-db")
        if any(w in p for w in ["dashboard","admin","panel"]):
            features.append("dashboard")
        if any(w in p for w in ["landing","page","homepage","marketing"]):
            features.append("landing-page")
        if any(w in p for w in ["dark","theme","purple","glass","gradient"]):
            features.append("liquid-glass-theme")

        schema = {
            "stack": self.STACKS[stack],
            "features": features,
            "has_db": "zero-db" in features,
            "has_auth": "google-oauth" in features,
            "has_dashboard": "dashboard" in features,
            "files_needed": self._compute_files(stack, features),
            "landing_title": self._extract_title(prompt),
        }
        return schema

    def _compute_files(self, stack: str, features: List[str]) -> List[str]:
        files = ["index.html"]
        if "google-oauth" in features:
            files.extend(["auth.py", "static/auth.js"])
        if "zero-db" in features:
            files.append("database.py")
        if stack in ("flask", "fastapi"):
            files.extend(["app.py", "requirements.txt"])
        if stack == "fastapi":
            files.append("Dockerfile")
        if "dashboard" in features:
            files.append("templates/dashboard.html")
        return files

    def _extract_title(self, prompt: str) -> str:
        """Extract a meaningful title from the prompt."""
        for phrase in ["called ", "named ", "titled "]:
            if phrase in prompt.lower():
                idx = prompt.lower().find(phrase) + len(phrase)
                end = min(prompt.find(" ", idx + 1) if " " in prompt[idx:] else len(prompt), idx + 30)
                name = prompt[idx:end].strip().rstrip(".,;!?")
                if name: return name
        for w in ["startup", "saas", "app", "platform", "labs", "studio"]:
            if w in prompt.lower():
                return f"{w.title()} β€” Omni-Vibe"
        return "Omni-Vibe App"

    def generate_backend(self, schema: Dict) -> str:
        """Generate zero-config backend code."""
        if not schema["has_db"] and not schema["has_auth"]:
            return ""

        code = []
        if schema["stack"]["backend"] and "Flask" in schema["stack"]["backend"]:
            code.append("from flask import Flask, request, jsonify, redirect, session\n")
            code.append("import sqlite3, os, uuid, hashlib\n\n")
            code.append("app = Flask(__name__)\napp.secret_key = os.environ.get('SECRET_KEY', 'omni-vibe-dev')\n\n")
            code.append("# ─── Zero-Config Database ───\n")
            code.append("DB = os.environ.get('DATABASE_URL', 'app.db')\n\n")
            code.append("def get_db():\n    conn = sqlite3.connect(DB)\n    conn.row_factory = sqlite3.Row\n    conn.execute('PRAGMA journal_mode=WAL')\n    return conn\n\n")
            code.append("# ─── Init Schema ───\n")
            code.append("def init_db():\n    with get_db() as db:\n")
            for line in ZERO_DB_SCHEMA.strip().split("\n"):
                if line.strip() and not line.startswith("--"):
                    code.append(f"        db.execute('''{line.strip()}''')\n")
            code.append("    print('βœ… Omni-Vibe DB initialized')\n\ninit_db()\n\n")

            if schema["has_auth"]:
                code.append("# ─── Google OAuth ───\n")
                code.append(GOOGLE_OAUTH_PY.strip() + "\n\n")

        elif schema["stack"]["backend"] and "FastAPI" in schema["stack"]["backend"]:
            code.append("from fastapi import FastAPI, Request, HTTPException\n")
            code.append("from fastapi.responses import JSONResponse, RedirectResponse\n")
            code.append("import sqlite3, os, uuid\n\n")
            code.append("app = FastAPI(title='Omni-Vibe')\n\n")

        return "".join(code)


# ═══════════════════════════════════════════════════════
#  POSE PAINTER β€” Liquid Glass Design Enforcer
# ═══════════════════════════════════════════════════════

class PosePainter:
    """
    Enforces the Liquid Glass design system on every generated app.
    Injects canonical CSS, logo SVG, and ensures consistent theming.
    """

    LG_COMPONENTS = {
        "navbar": """
<nav class="glass" style="padding:1rem 2rem;display:flex;align-items:center;justify-content:space-between">
  <div style="display:flex;align-items:center;gap:.75rem">
    {LOGO}
    <span class="gradient-text" style="font-weight:700;font-size:1.1rem">{TITLE}</span>
  </div>
  <div style="display:flex;gap:1rem">
    <a href="/" class="btn-outline btn" style="padding:.5rem 1rem;font-size:.85rem">Home</a>
    <a href="/dashboard" class="btn-outline btn" style="padding:.5rem 1rem;font-size:.85rem">Dashboard</a>
    <button id="google-auth-btn" class="btn" style="padding:.5rem 1rem;font-size:.85rem">Sign In</button>
  </div>
</nav>
""",
        "hero": """
<section style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:80vh;padding:2rem;text-align:center">
  <h1 class="gradient-text" style="font-size:clamp(2.5rem,8vw,5rem);font-weight:800;line-height:1.1">{TITLE}</h1>
  <p style="font-size:1.25rem;color:var(--text2);margin-top:1.5rem;max-width:600px">{SUBTITLE}</p>
  <div style="display:flex;gap:1rem;margin-top:2.5rem">
    <button class="btn" onclick="document.getElementById('cta-section').scrollIntoView({behavior:'smooth'})">Get Started</button>
    <button class="btn btn-outline">Learn More</button>
  </div>
</section>
""",
        "features": """
<section style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1.5rem;padding:3rem 2rem;max-width:1200px;margin:0 auto">
  {FEATURE_CARDS}
</section>
""",
        "feature_card": """
<div class="card glass-hover">
  <div style="font-size:2rem;margin-bottom:.75rem">{ICON}</div>
  <h3 style="color:var(--{COLOR});font-size:1.15rem;margin-bottom:.5rem">{TITLE}</h3>
  <p style="color:var(--text2);font-size:.9rem;line-height:1.5">{DESCRIPTION}</p>
</div>
""",
        "footer": """
<footer class="glass" style="margin-top:3rem;padding:2rem;text-align:center;color:var(--text3);font-size:.85rem">
  <p>Built with <span class="gradient-text" style="font-weight:600">Omni-Vibe Studio</span> β€” Liquid Glass Design System</p>
  <p style="margin-top:.5rem">Zero-config Β· Google OAuth Β· SQLite Β· Pinggy Deploy</p>
</footer>
""",
    }

    def paint(self, code: str, schema: Dict) -> str:
        """Inject Liquid Glass design system into generated code."""
        title = schema.get("landing_title", "Omni-Vibe App")

        # 1. Inject canonical CSS if not present
        if "liquid-glass" not in code.lower() and "--glass-bg" not in code:
            code = code.replace("</head>",
                f"<style>\n/* Liquid Glass Design System β€” Omni-Vibe */\n{LIQUID_GLASS_CSS.strip()}\n</style>\n</head>")

        # 2. Replace <!-- WIZARD-LOGO --> with actual SVG
        code = code.replace("<!-- WIZARD-LOGO -->", LIQUID_GLASS_LOGO)

        # 3. Inject navbar if missing
        if "<nav" not in code.lower() and "navbar" not in code.lower() and schema.get("has_auth"):
            navbar = self.LG_COMPONENTS["navbar"].replace("{LOGO}", LIQUID_GLASS_LOGO).replace("{TITLE}", title)
            code = code.replace("<body>", f"<body>\n{navbar}")

        # 4. Ensure gradient-text class exists
        if "gradient-text" not in code and ".gradient-text" not in code:
            if "</style>" in code:
                code = code.replace("</style>",
                    ".gradient-text{background:linear-gradient(135deg,var(--purple),var(--cyan),var(--green));-webkit-background-clip:text;-webkit-text-fill-color:transparent}\n</style>")

        # 5. Inject Google OAuth JS if auth is needed
        if schema.get("has_auth") and "google-auth" not in code:
            code = code.replace("</body>",
                f"<script>\n{GOOGLE_OAUTH_JS.strip()}\n</script>\n</body>")

        return code


# ═══════════════════════════════════════════════════════
#  POSE AUDITOR β€” Step-by-Step Code Verification
# ═══════════════════════════════════════════════════════

class PoseAuditor:
    """
    Step-by-step reasoning: verifies code correctness before hot-reload.
    Returns structured findings with severity and suggested fixes.
    """

    VOID = {'br','hr','img','input','meta','link','area','base','col','embed','source','track','wbr'}
    SVG_VOID = VOID | {'lineargradient','defs','stop','animate','animatetransform','fegaussianblur','femerge','femergenode','ellipse','path','circle','rect','polygon','polyline','g','use','svg'}

    def audit(self, code: str, schema: Dict = None) -> List[AuditFinding]:
        """Full audit: HTML validity, JS correctness, accessibility, security, simplicity."""
        findings = []

        # STEP 1: HTML validity
        findings.extend(self._audit_html(code))

        # STEP 2: JS correctness
        findings.extend(self._audit_js(code))

        # STEP 3: Liquid Glass compliance
        if schema and schema.get("features"):
            findings.extend(self._audit_liquid_glass(code))

        # STEP 4: STABLE VIBE β€” simplicity verification (Painter must strip SaaS)
        findings.extend(self._audit_simplicity(code, schema))

        # STEP 5: Security & best practices
        findings.extend(self._audit_security(code, schema))

        return findings

    def _audit_html(self, code: str) -> List[AuditFinding]:
        findings = []
        stack = []

        for m in re.finditer(r'<(?P<closing>/)?(?P<tag>\w+)(?:\s[^>]*?)?(?P<self>/)?>', code, re.IGNORECASE):
            t = m.group('tag').lower()
            if t in self.SVG_VOID: continue
            if m.group('self'): continue
            if m.group('closing'):
                if stack and stack[-1] == t: stack.pop()
                else: findings.append(AuditFinding(
                    line=code[:m.start()].count('\n')+1, severity="ERROR",
                    message=f"Unmatched closing tag </{t}>",
                    fix=f"Remove or match with opening <{t}>"))
            else: stack.append(t)

        for t in stack:
            findings.append(AuditFinding(
                line=1, severity="ERROR",
                message=f"Unclosed tag <{t}>",
                fix=f"Add </{t}> before parent closes"))

        # Check DOCTYPE
        if '<html' in code.lower() and not code.strip().startswith('<!'):
            findings.append(AuditFinding(line=1, severity="WARN",
                message="Missing DOCTYPE declaration",
                fix="Add <!DOCTYPE html> at line 1"))

        return findings

    def _audit_js(self, code: str) -> List[AuditFinding]:
        findings = []
        scripts = re.findall(r'<script[^>]*>(.*?)</script>', code, re.DOTALL | re.IGNORECASE)

        for i, script in enumerate(scripts):
            lines = script.split('\n')
            for ln, line in enumerate(lines, 1):
                # Common typos
                typos = {
                    "console.loge(": "console.log(",
                    "docment.": "document.",
                    "getElementbyId": "getElementById",
                    "innerHtml": "innerHTML",
                    "functon ": "function ",
                    "retrun": "return",
                    "alet(": "alert(",
                    "consts ": "const ",
                }
                for typo, fix in typos.items():
                    if typo in line:
                        findings.append(AuditFinding(
                            line=ln, severity="ERROR",
                            message=f"Typo: {typo.strip('(')} β†’ {fix.strip('(')}",
                            fix=f"Replace '{typo}' with '{fix}'"))

        return findings

    def _audit_liquid_glass(self, code: str) -> List[AuditFinding]:
        findings = []
        if "--glass-bg" not in code and "var(--glass" not in code:
            findings.append(AuditFinding(line=1, severity="WARN",
                message="Liquid Glass CSS variables not detected",
                fix="Inject Liquid Glass design system CSS"))
        return findings

    def _audit_security(self, code: str, schema: Dict) -> List[AuditFinding]:
        findings = []
        # Check for innerHTML usage (XSS risk)
        if re.search(r'\.innerHTML\s*=', code) and "sanitize" not in code.lower():
            findings.append(AuditFinding(line=1, severity="WARN",
                message="innerHTML assignment detected without sanitization β€” XSS risk",
                fix="Use textContent or DOMPurify.sanitize()"))
        return findings

    def _audit_simplicity(self, code: str, schema: Dict) -> List[AuditFinding]:
        """
        STABLE VIBE: Verify Painter produced a single, elegant Liquid Glass
        landing page β€” no SaaS complexity, no broken asset paths.
        """
        findings = []

        # 1. No dashboard/multi-page routing β€” must be single-page
        saas_routes = ['/dashboard', '/admin', '/settings', '/login', '/register', '/signup',
                       '/api/', '/app/', '/profile', '/billing', '/tasks', '/items']
        for route in saas_routes:
            if route in code and f'href="{route}"' in code:
                findings.append(AuditFinding(line=1, severity="ERROR",
                    message=f"SaaS route detected: {route} β€” STABLE VIBE requires single landing page",
                    fix=f"Remove navigation link to {route}"))

        # 2. No database initialization scripts in the HTML
        db_patterns = ['CREATE TABLE', 'INSERT INTO', 'sqlite3', 'better-sqlite3',
                       'mongoose', 'prisma', 'supabase', 'firebase', 'mongodb']
        for pat in db_patterns:
            if pat.lower() in code.lower():
                findings.append(AuditFinding(line=1, severity="ERROR",
                    message=f"Database reference '{pat}' found in HTML β€” strip backend complexity",
                    fix="Remove database initialization from frontend code"))

        # 3. No external asset paths β€” must use relative paths or inline everything
        external_assets = re.findall(r'(?:src|href)=["\'](https?://[^"\']+)["\']', code)
        # Allow: HF Spaces URLs, Google Fonts, Google OAuth endpoints
        allowed_prefixes = ('https://huggingface.co', 'https://accounts.google.com',
                           'https://oauth2.googleapis.com', 'https://fonts.googleapis.com',
                           'https://cdnjs.cloudflare.com', 'https://fonts.gstatic.com')
        for asset in external_assets:
            if not any(asset.startswith(p) for p in allowed_prefixes):
                findings.append(AuditFinding(line=1, severity="WARN",
                    message=f"External asset: {asset[:80]} β€” prefer inline or relative paths",
                    fix="Inline the resource or use a relative path"))

        # 4. Must have exactly one <html> document (no iframes with separate apps)
        html_count = len(re.findall(r'<html', code, re.IGNORECASE))
        if html_count > 1:
            findings.append(AuditFinding(line=1, severity="ERROR",
                message=f"Multiple <html> documents ({html_count}) β€” must be single page",
                fix="Merge into one HTML document"))

        # 5. Must have Liquid Glass CSS variables
        if "--glass-bg" not in code and "var(--glass" not in code:
            findings.append(AuditFinding(line=1, severity="ERROR",
                message="Liquid Glass CSS variables missing β€” Painter must enforce",
                fix="Inject the Liquid Glass design system CSS"))

        # 6. Must have wizard-hat SVG (brand identity)
        if 'wizard-hat' not in code.lower() and 'wizard_hat' not in code.lower():
            findings.append(AuditFinding(line=1, severity="WARN",
                message="Wizard hat SVG missing β€” brand element required",
                fix="Add the wizard hat SVG logo"))

        return findings

    def heal_findings(self, code: str, findings: List[AuditFinding]) -> Tuple[str, int]:
        """Apply all ERROR-level fixes."""
        fixed = code
        count = 0
        for f in findings:
            if f.severity == "ERROR" and f.fix:
                # Apply typo fixes
                for typo, fix in [
                    ("console.loge(", "console.log("),
                    ("docment.", "document."),
                    ("getElementbyId", "getElementById"),
                    ("innerHtml", "innerHTML"),
                    ("functon ", "function "),
                    ("retrun", "return"),
                    ("alet(", "alert("),
                ]:
                    if typo in fixed:
                        fixed = fixed.replace(typo, fix)
                        count += 1
        return fixed, count


# ═══════════════════════════════════════════════════════
#  OMNI-VIBE ENGINE β€” Swarm Orchestrator
# ═══════════════════════════════════════════════════════

class OmniVibeEngine:
    """The Athanor: all three Poses running as a synchronized swarm."""

    def __init__(self):
        self.architect = PoseArchitect()
        self.painter = PosePainter()
        self.auditor = PoseAuditor()

    def pose(self, prompt: str) -> Dict:
        """All three Poses analyze the prompt in parallel."""
        return {
            "architect": self.architect.design(prompt),
            "painter": {"design_system": "Liquid Glass", "components": sorted(self.painter.LG_COMPONENTS.keys())},
            "auditor": {"strategy": "step-by-step reasoning", "checks": ["HTML validity", "JS correctness", "Liquid Glass compliance", "Simplicity (no SaaS)", "Security"]},
        }

    def generate(self, prompt: str) -> Tuple[str, Dict]:
        """
        Full Omni-Vibe generation:
        1. Architect designs the full-stack schema
        2. Painter enforces Liquid Glass design
        3. Auditor verifies every line
        Returns (code, schema)
        """
        schema = self.architect.design(prompt)

        # Determine what to generate
        if schema["features"] and any(f in schema["features"] for f in ["landing-page", "dashboard"]):
            code = self._generate_frontend(prompt, schema)
        elif schema["stack"]["backend"]:
            code = self.architect.generate_backend(schema)
        else:
            code = self._generate_frontend(prompt, schema)

        # Painter: enforce Liquid Glass
        code = self.painter.paint(code, schema)

        # Auditor: verify and fix
        findings = self.auditor.audit(code, schema)
        code, fixes = self.auditor.heal_findings(code, findings)

        return code, schema

    def _generate_frontend(self, prompt: str, schema: Dict) -> str:
        """Generate a Liquid Glass frontend."""
        title = schema["landing_title"]
        has_auth = schema.get("has_auth", False)

        features_html = ""
        default_features = [
            ("⚑", "purple", "Zero-Delay", "Real-time streaming with sub-second hot reload in sandboxed iframe."),
            ("πŸ”„", "cyan", "Reflect-Select", "Autonomous code healing β€” errors fixed before you see them."),
            ("πŸš€", "green", "Ghost Deploy", "One-click publish to HF Spaces with instant live URL."),
        ]
        for icon, color, ftitle, desc in default_features:
            features_html += self.painter.LG_COMPONENTS["feature_card"].format(
                ICON=icon, COLOR=color, TITLE=ftitle, DESCRIPTION=desc)

        hero_subtitle = "Built with Omni-Vibe Studio β€” specialized AI swarm with zero-config database, Google OAuth, and Liquid Glass design."

        auth_section = ""
        if has_auth:
            auth_section = """
<section id="cta-section" class="glass" style="max-width:500px;margin:3rem auto;padding:2.5rem;text-align:center">
  <h3 class="gradient-text" style="font-size:1.5rem;margin-bottom:1rem">Get Started</h3>
  <p style="color:var(--text2);margin-bottom:1.5rem">Sign in with Google β€” no password required.</p>
  <button id="google-auth-btn" class="btn" style="width:100%;justify-content:center">
    <svg width="20" height="20" viewBox="0 0 24 24"><path fill="currentColor" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z"/><path fill="currentColor" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/><path fill="currentColor" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/><path fill="currentColor" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/></svg>
    Sign in with Google
  </button>
</section>"""

        return f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>{title}</title>
<style>
/* Omni-Vibe Liquid Glass Design System */
{LIQUID_GLASS_CSS.strip()}
</style>
</head>
<body>

<!-- Liquid Glass Wizard Logo -->
<div style="position:fixed;top:20px;left:50%;transform:translateX(-50%);z-index:100">
  {LIQUID_GLASS_LOGO}
</div>

<!-- Navbar -->
<nav class="glass" style="padding:1rem 2rem;display:flex;align-items:center;justify-content:space-between;margin:0 1rem">
  <div style="display:flex;align-items:center;gap:.75rem">
    {LIQUID_GLASS_LOGO.replace('width="48"','width="32"').replace('height="48"','height="32"')}
    <span class="gradient-text" style="font-weight:700;font-size:1.1rem">{title}</span>
  </div>
  <div style="display:flex;gap:1rem">
    {'''<button id="google-auth-btn" class="btn" style="padding:.5rem 1.25rem;font-size:.85rem">Sign In</button>''' if has_auth else '<button class="btn btn-outline" style="padding:.5rem 1.25rem;font-size:.85rem">Documentation</button>'}
  </div>
</nav>

<!-- Hero -->
<section style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:80vh;padding:2rem;text-align:center;margin-top:-60px">
  <h1 class="gradient-text" style="font-size:clamp(2.5rem,8vw,5rem);font-weight:800;line-height:1.1">{title}</h1>
  <p style="font-size:1.25rem;color:var(--text2);margin-top:1.5rem;max-width:600px">{hero_subtitle}</p>
  <div style="display:flex;gap:1rem;margin-top:2.5rem">
    <button class="btn">Get Started</button>
    <button class="btn btn-outline">Learn More</button>
  </div>
</section>

<!-- Features -->
<section style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1.5rem;padding:3rem 2rem;max-width:1200px;margin:0 auto">
  {features_html}
</section>

{auth_section}

<!-- Footer -->
<footer class="glass" style="margin-top:3rem;padding:2rem;text-align:center;color:var(--text3);font-size:.85rem">
  <p>Built with <span class="gradient-text" style="font-weight:600">Omni-Vibe Studio</span> β€” Liquid Glass Design System</p>
  <p style="margin-top:.5rem">Zero-config Β· Google OAuth Β· SQLite Β· Ghost Deploy Β· Pinggy</p>
</footer>

{f'''<script>
{GOOGLE_OAUTH_JS.strip()}
</script>''' if has_auth else ''}

<script>
// Wizard hat pulse animation
const hat = document.querySelector('#wizard-hat');
if (hat) {{
  let p = 0;
  function animate() {{
    p += 0.02;
    hat.style.transform = `scale(${{1 + Math.sin(p) * 0.06}})`;
    hat.style.filter = `drop-shadow(0 0 ${{18 + Math.sin(p * 1.5) * 8}}px rgba(139,92,246,.6))`;
    requestAnimationFrame(animate);
  }}
  animate();
}}
</script>

</body>
</html>"""


# ═══════════════════════════════════════════════════════
#  REFLECT-SELECT β€” Sub-Second Loop
# ═══════════════════════════════════════════════════════

class ReflectSelect:
    """Sub-second Reflect-Select using compiled regex patterns."""
    VOID = PoseAuditor.SVG_VOID
    PATTERNS = [
        (re.compile(r"console\.loge\("), "console.log("),
        (re.compile(r"docment\."), "document."),
        (re.compile(r"getElementbyId"), "getElementById"),
        (re.compile(r"innerHtml"), "innerHTML"),
        (re.compile(r"functon\s"), "function "),
        (re.compile(r"retrun"), "return"),
    ]

    def heal(self, code: str, errors: List[str] = None) -> Tuple[str, int, int]:
        errors_list = self._detect(code)
        if errors: errors_list.extend(errors)
        errors_list = list(set(errors_list))
        found = len(errors_list)
        if not found: return code, 0, 0
        fixed = 0
        for i in range(15):
            if not errors_list: break
            code = self._apply_fixes(code, errors_list)
            fixed += 1
            errors_list = self._detect(code)
        return code, found, fixed

    def _detect(self, code: str) -> List[str]:
        e = []
        # HTML
        if "<html" in code.lower() or code.startswith("<!"):
            stack = []
            for m in re.finditer(r'<(?P<closing>/)?(?P<tag>\w+)(?:\s[^>]*?)?(?P<self>/)?>', code, re.IGNORECASE):
                t = m.group('tag').lower()
                if t in self.VOID: continue
                if m.group('self'): continue
                if m.group('closing'):
                    if stack and stack[-1]==t: stack.pop()
                    else: e.append(f"Unmatched </{t}>")
                else: stack.append(t)
            for t in stack: e.append(f"Unclosed <{t}>")
        # Python
        elif code.startswith("import") or "def " in code:
            try: compile(code,'<s>','exec')
            except SyntaxError as se: e.append(f"Syntax: {se}")
        # Generic bracket check
        if code.count('(')!=code.count(')'): e.append("Parenthesis mismatch")
        if code.count('{')!=code.count('}'): e.append("Brace mismatch")
        return e

    def _apply_fixes(self, code: str, errors: List[str]) -> str:
        for pat, rep in self.PATTERNS:
            code = pat.sub(rep, code)
        # Close unclosed HTML tags
        for tag in re.findall(r'Unclosed <(\w+)>', '\n'.join(errors)):
            if tag.lower() not in self.VOID:
                close = code.lower().rfind('</body>') or code.lower().rfind('</html>')
                if close >= 0:
                    code = code[:close] + f'</{tag}>\n' + code[close:]
        return code

    def validate(self, code: str) -> Dict:
        e = self._detect(code)
        return {"success": len(e)==0, "errors": e}


# ═══════════════════════════════════════════════════════
#  STATE
# ═══════════════════════════════════════════════════════

@dataclass
class State:
    engine: OmniVibeEngine = field(default_factory=OmniVibeEngine)
    reflect: ReflectSelect = field(default_factory=ReflectSelect)
    sessions: Dict = field(default_factory=dict)
    codes: Dict = field(default_factory=dict)
    sandbox: Dict = field(default_factory=dict)
    publish_ready: Dict = field(default_factory=dict)

state = State()


# ═══════════════════════════════════════════════════════
#  COMPATIBILITY EXPORTS
# ═══════════════════════════════════════════════════════

# Expose the old API for server.py compatibility
class Orchestrator:
    """Backward-compatible wrapper around OmniVibeEngine."""
    def pose(self, prompt: str) -> Dict:
        plan = state.engine.pose(prompt)
        return {
            "model": "omni-vibe-swarm",
            "domain": plan["architect"]["stack"]["backend"] and "fullstack" or "frontend",
            "plan": plan,
        }
    def generate(self, prompt: str):
        code, schema = state.engine.generate(prompt)
        # Yield chunks for SSE streaming
        chunk_size = max(1, len(code) // 20)
        for i in range(0, len(code), chunk_size):
            yield code[i:i+chunk_size]
            time.sleep(0.02)
        state.codes["_last_schema"] = schema

def sandbox_validate(code: str) -> Dict:
    return state.reflect.validate(code)

print("πŸ§™β€β™‚οΈ Omni-Vibe Core β€” Swarm Synchronized")
print("   Pose Architect: full-stack + zero-DB + Google OAuth")
print("   Pose Painter: Liquid Glass design system")
print("   Pose Auditor: step-by-step verification")
print("   Athanor ready β€” Steady Gold")