File size: 21,912 Bytes
d0bc232
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/usr/bin/env python3
"""
ayncode

AynEngine AI Coding Edition (v2.0) - Sovereign CLI Developer Tool
Guided by the 5 Classical Arabic Lexicographical & Grammatical Pillars:
1. Al-Mufradāt (al-Rāghib) -> Ontological Domain Modeling & Teleology
2. Asās al-Balāghah (al-Zamakhsharī) -> Idiomatic Eloquence & Abstraction Integrity
3. Lisān al-ΚΏArab (Ibn ManαΊ“Ε«r) -> Exhaustive Error Taxonomy & State-Space
4. Kitāb al-ʿAyn (al-Farāhīdī) -> Atomic Primitive Decomposition
5. Al-Kitāb (Sībawayh) -> Syntactic Governance & AST Integrity
"""

import os
import sys
import argparse
from pathlib import Path

# Add repo root to path
script_path = Path(__file__).resolve()
BASE_DIR = script_path.parent if (script_path.parent / "core").exists() else script_path.parent.parent
sys.path.insert(0, str(BASE_DIR))

from core.coding_engine import AynCodingEngine
from core.mantiq_engine import AynMantiqEngine
from core.mantiq_dataset_generator import AynMantiqDatasetGenerator
from core.mantiq_purifier import AynMantiqPurifier

# ANSI Color formatting
BOLD = "\033[1m"
RESET = "\033[0m"
GREEN = "\033[32m"
CYAN = "\033[36m"
YELLOW = "\033[33m"
MAGENTA = "\033[35m"
RED = "\033[31m"

BANNER = f"""{CYAN}{BOLD}
   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—   β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
  β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β•šβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β•
  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  
  β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘  β•šβ–ˆβ–ˆβ•”β•  β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•  
  β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
  β•šβ•β•  β•šβ•β•   β•šβ•β•   β•šβ•β•  β•šβ•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β•β•
{RESET}{BOLD}πŸ›οΈ AynEngine AI Coding Edition (v2.0): Sovereign 5-Pillar Epistemic Engine{RESET}
"""

def print_banner():
    print(BANNER)

def cmd_gen(args, engine: AynCodingEngine):
    prompt = args.prompt
    lang = args.language.lower()
    output_path = Path(args.output) if args.output else None

    print(f"\n{CYAN}⚑ Synthesizing code grounded in 5-Pillar Epistemic Apparatus...{RESET}")
    print(f"Target Language: {BOLD}{lang.upper()}{RESET} | Mode: {BOLD}Zero-Loss Sovereign{RESET}\n")

    res = engine.synthesize(prompt=prompt, language=lang)

    print(f"\n{GREEN}{BOLD}════════════════════════════════════════════════════════════════════════════════{RESET}")
    print(f"{GREEN}{BOLD}βœ… SYNTHESIS COMPLETE in {res['duration_seconds']}s | Syntax Valid: {res['syntax_valid']}{RESET}")
    print(f"{GREEN}{BOLD}════════════════════════════════════════════════════════════════════════════════{RESET}\n")

    if res.get("mantiq_reasoning") and not args.code_only:
        print(f"{MAGENTA}{BOLD}πŸ›οΈ AYN-ENGINE CLASSICAL MANαΉ¬IQ & MORPHOLOGY REASONING:{RESET}")
        print(f"{MAGENTA}{res['mantiq_reasoning']}{RESET}\n")
        print(f"{CYAN}{'─'*80}{RESET}\n")

    if args.code_only:
        print(res["code"])
    else:
        print(res["raw_output"])

    if output_path:
        output_path.parent.mkdir(parents=True, exist_ok=True)
        output_path.write_text(res["code"], encoding="utf-8")
        print(f"\n{GREEN}πŸ’Ύ Code saved to {output_path.resolve()}{RESET}")

def cmd_audit(args, engine: AynCodingEngine):
    target = Path(args.target)
    if not target.exists():
        print(f"{RED}❌ Error: File or path not found: {target}{RESET}")
        sys.exit(1)

    files_to_audit = []
    if target.is_file():
        files_to_audit.append(target)
    else:
        for ext in ["*.py", "*.ts", "*.js", "*.rs", "*.go", "*.c", "*.cpp", "*.sql", "*.sh"]:
            files_to_audit.extend(list(target.rglob(ext)))

    if not files_to_audit:
        print(f"{YELLOW}⚠️ No source files found to audit in {target}{RESET}")
        return

    print(f"\n{CYAN}πŸ” Auditing {len(files_to_audit)} file(s) under 5-Pillar Epistemic Lens (Remote LLM)...{RESET}\n")

    for fpath in files_to_audit:
        print(f"{BOLD}πŸ“„ Auditing `{fpath.relative_to(Path.cwd()) if fpath.is_relative_to(Path.cwd()) else fpath}`...{RESET}")
        code = fpath.read_text(encoding="utf-8", errors="ignore")
        lang = args.language or fpath.suffix.lstrip('.') or "text"

        res = engine.audit(code=code, language=lang, filename=fpath.name)
        print(f"\n{res['audit_report']}\n")
        print(f"{CYAN}{'─'*80}{RESET}\n")

def cmd_audit_local(args, engine: AynCodingEngine):
    target = Path(args.target)
    if not target.exists():
        print(f"{RED}❌ Error: File or path not found: {target}{RESET}")
        sys.exit(1)

    if target.is_file():
        files = [target]
    elif args.language:
        files = list(target.rglob(f"*.{args.language.lstrip('.')}"))
    else:
        files = []
        for ext in ["py", "js", "ts", "rs", "go", "c", "cpp"]:
            files.extend(list(target.rglob(f"*.{ext}")))

    for fpath in files:
        code = fpath.read_text(encoding="utf-8", errors="ignore")
        lang = args.language or fpath.suffix.lstrip('.') or "python"
        res = engine.audit_local(code=code, language=lang, filename=fpath.name)

        score_color = GREEN if res["overall_epistemic_score"] >= 85 else YELLOW if res["overall_epistemic_score"] >= 70 else RED
        print(f"\n{CYAN}{BOLD}╔══════════════════════════════════════════════════════════════════════════════════╗{RESET}")
        print(f"{CYAN}{BOLD}β•‘ πŸ›οΈ  AYNENGINE 5-PILLAR EPISTEMIC AUDIT: {fpath.name:<41} β•‘{RESET}")
        print(f"{CYAN}{BOLD}╠══════════════════════════════════════════════════════════════════════════════════╣{RESET}")
        print(f"β•‘ {BOLD}Lines:{RESET} {res['total_lines']:<10} | {BOLD}Score:{RESET} {score_color}{res['overall_epistemic_score']}% ({res['grade']}){RESET} | {BOLD}Syntax Valid:{RESET} {GREEN if res['syntax_valid'] else RED}{res['syntax_valid']}{RESET}")
        print(f"{CYAN}{BOLD}β•Ÿβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•’{RESET}")
        print(f"β•‘ 1️⃣  Al-Mufradāt (Teleology):      {BOLD}{res['pillars']['pillar_1_mufradat_teleology']['score']}/10{RESET} -> {res['pillars']['pillar_1_mufradat_teleology']['critique']}")
        print(f"β•‘ 2️⃣  Asās al-Balāghah (Eloquence): {BOLD}{res['pillars']['pillar_2_asas_eloquence']['score']}/10{RESET} -> {res['pillars']['pillar_2_asas_eloquence']['critique']}")
        print(f"β•‘ 3️⃣  Lisān al-ΚΏArab (Coverage):    {BOLD}{res['pillars']['pillar_3_lisan_exhaustiveness']['score']}/10{RESET} -> {res['pillars']['pillar_3_lisan_exhaustiveness']['critique']}")
        print(f"β•‘ 4️⃣  Kitāb al-ΚΏAyn (Primitives):   {BOLD}{res['pillars']['pillar_4_ayn_decomposition']['score']}/10{RESET} -> {res['pillars']['pillar_4_ayn_decomposition']['critique']}")
        print(f"β•‘ 5️⃣  Al-Kitāb (Governance):        {BOLD}{res['pillars']['pillar_5_sibawayh_governance']['score']}/10{RESET} -> {res['pillars']['pillar_5_sibawayh_governance']['critique']}")
        print(f"{CYAN}{BOLD}β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•{RESET}\n")

def cmd_benchmark(args, engine: AynCodingEngine):
    target = Path(args.target)
    if not target.exists():
        print(f"{RED}❌ Error: Path not found: {target}{RESET}")
        sys.exit(1)

    ext = args.language or "js"
    files = [str(target)] if target.is_file() else [str(p) for p in target.rglob(f"*.{ext}")]

    if not files:
        print(f"{YELLOW}⚠️ No files found matching extension *.{ext} in {target}{RESET}")
        return

    print(f"\n{CYAN}⚑ Running AynEngine 5-Pillar Epistemic Benchmark on {len(files)} file(s)...{RESET}\n")
    bench = engine.benchmark_codebase(file_paths=files, language=args.language or "javascript")

    if "error" in bench:
        print(f"{RED}❌ {bench['error']}{RESET}")
        return

    m_color = GREEN if bench["macro_epistemic_score"] >= 85 else YELLOW if bench["macro_epistemic_score"] >= 70 else RED
    print(f"{GREEN}{BOLD}════════════════════════════════════════════════════════════════════════════════════════{RESET}")
    print(f"{BOLD}πŸ“Š BENCHMARK SUMMARY: {len(bench['file_audits'])} Files Audited | Macro Epistemic Score: {m_color}{bench['macro_epistemic_score']}% ({bench['macro_grade']}){RESET}")
    print(f"{GREEN}{BOLD}════════════════════════════════════════════════════════════════════════════════════════{RESET}")
    print(f"β€’ Pillar 1 (Teleology & Domain Types): {bench['pillar_averages']['p1_teleology']}/10")
    print(f"β€’ Pillar 2 (Eloquence & Anti-Leakage):  {bench['pillar_averages']['p2_eloquence']}/10")
    print(f"β€’ Pillar 3 (Error Coverage & States):   {bench['pillar_averages']['p3_exhaustiveness']}/10")
    print(f"β€’ Pillar 4 (Decomposition & Safety):   {bench['pillar_averages']['p4_decomposition']}/10")
    print(f"β€’ Pillar 5 (Governance & Contracts):    {bench['pillar_averages']['p5_governance']}/10\n")

    print(f"{BOLD}Per-File Breakdown:{RESET}")
    for f in bench["file_audits"]:
        f_color = GREEN if f["overall_epistemic_score"] >= 85 else YELLOW if f["overall_epistemic_score"] >= 70 else RED
        print(f"  β€’ {f['filename']:<35} : {f_color}{f['overall_epistemic_score']}% ({f['grade']}){RESET}")

def cmd_refactor(args, engine: AynCodingEngine):
    target = Path(args.target)
    if not target.is_file():
        print(f"{RED}❌ Error: Target must be an existing file: {target}{RESET}")
        sys.exit(1)

    code = target.read_text(encoding="utf-8", errors="ignore")
    lang = args.language or target.suffix.lstrip('.') or "python"
    goal = args.goal or "Purify architecture according to 5-Pillar Classical Standard"

    print(f"\n{CYAN}πŸ› οΈ Refactoring `{target.name}` to 5-Pillar Classical Standard...{RESET}")
    print(f"Goal: {goal}\n")

    res = engine.refactor(code=code, language=lang, goal=goal)

    print(f"\n{GREEN}{BOLD}βœ… REFACTORING COMPLETE in {res['duration_seconds']}s | Syntax Valid: {res['syntax_valid']}{RESET}\n")
    print(res["raw_output"])

    if args.in_place:
        target.write_text(res["refactored_code"], encoding="utf-8")
        print(f"\n{GREEN}πŸ’Ύ Updated {target.resolve()} in-place.{RESET}")
    elif args.output:
        out = Path(args.output)
        out.write_text(res["refactored_code"], encoding="utf-8")
        print(f"\n{GREEN}πŸ’Ύ Saved refactored code to {out.resolve()}.{RESET}")

def cmd_pillars(args):
    print_banner()
    print(f"""
{BOLD}The 5 Classical Pillars of AynEngine AI Coding Edition:{RESET}

{GREEN}{BOLD}1. Al-Mufradāt fī Gharīb al-Qurʾān (Al-Rāghib al-Iṣfahānī, d. 502 AH){RESET}
   β€’ {CYAN}Core Discipline:{RESET} Ontological Domain Modeling & Teleology (Ghāyah).
   β€’ {CYAN}Coding Rule:{RESET} Every class, type, and function must have a singular, transparent Ghāyah.
     Eliminate amorphous generic names ('data', 'manager', 'process').
     Pure distinction between ontological essence (immutability) and accidental state.

{GREEN}{BOLD}2. Asās al-Balāghah (Al-Zamakhsharī, d. 538 AH){RESET}
   β€’ {CYAN}Core Discipline:{RESET} Idiomatic Eloquence (Balāghah) & Abstraction Integrity (αΈ€aqΔ«qah vs Majāz).
   β€’ {CYAN}Coding Rule:{RESET} Distinguish literal machine reality (CPU, IO, allocations) from metaphors (ORMs, proxies).
     Zero leaky abstractions (Majāz Mukhil). Eliminate stuttering boilerplate; write lean, high-impact code.

{GREEN}{BOLD}3. Lisān al-ΚΏArab (Ibn ManαΊ“Ε«r, d. 711 AH){RESET}
   β€’ {CYAN}Core Discipline:{RESET} Exhaustive State-Space, Edge-Case Coverage & Error Taxonomy.
   β€’ {CYAN}Coding Rule:{RESET} Exhaustive morphological coverage. Zero unhandled match arms, unhandled rejections,
     or silent failures. Explicit lifecycle state modeling: Init -> Active -> Degraded -> Closed -> Failed.

{GREEN}{BOLD}4. Kitāb al-ʿAyn (Al-Farāhīdī, d. 175 AH){RESET}
   β€’ {CYAN}Core Discipline:{RESET} Atomic Primitive Decomposition & Combinatorial Permutations.
   β€’ {CYAN}Coding Rule:{RESET} Decompose systems into orthogonal, irreducible primitives.
     Combinatorial state safety: Make illegal states unrepresentable in the type system.

{GREEN}{BOLD}5. Al-Kitāb (Sībawayh, d. 180 AH){RESET}
   β€’ {CYAN}Core Discipline:{RESET} Syntactic Governance (ΚΏΔ€mil/MaΚΏmΕ«l), Strict Typing & AST Integrity.
   β€’ {CYAN}Coding Rule:{RESET} Strict caller-callee hierarchy (Governor -> Governed -> Mutation).
     Zero circular dependencies. Strict static typing, pure data flow, and unambiguous contracts.
""")

def cmd_mantiq_dataset(args):
    print_banner()
    output_path = Path(args.output) if args.output else BASE_DIR / "data/ayn_mantiq_epistemic_dataset.jsonl"
    print(f"{CYAN}πŸ›οΈ Synthesizing Epistemic ManαΉ­iq & Morphology Training Dataset...{RESET}")
    generator = AynMantiqDatasetGenerator()
    records = generator.build_dataset(output_file=output_path)
    print(f"\n{GREEN}{BOLD}βœ… Dataset Generated Successfully:{RESET} {len(records)} records")
    print(f"πŸ“ Output File: {output_path.resolve()}\n")
    for idx, r in enumerate(records, 1):
        print(f"{CYAN}[{idx}/{len(records)}] {BOLD}{r['id']}{RESET} (Domain: {r['domain']})")
        print(f"   Prompt: {r['instruction']}")
        print(f"   Scratchpad Preview: {r['thought'].splitlines()[1] if len(r['thought'].splitlines()) > 1 else ''}\n")

def cmd_mantiq_audit(args):
    print_banner()
    target = Path(args.target)
    if not target.is_file():
        print(f"{RED}❌ Error: Target must be an existing file: {target}{RESET}")
        sys.exit(1)
    code = target.read_text(encoding="utf-8", errors="ignore")
    print(f"{CYAN}βš–οΈ Executing Ghazalian ManαΉ­iq Fallacy Audit on `{target.name}`...{RESET}\n")
    engine = AynMantiqEngine()
    critique = engine.audit_logic_fallacies(code)
    status_icon = f"{GREEN}βœ… VALID{RESET}" if critique.is_valid else f"{RED}⚠️ FALLACIES DETECTED{RESET}"
    print(f"Status: {status_icon}")
    print(f"Citation: {critique.axiom_citation}")
    if critique.detected_fallacies:
        print(f"Detected Fallacies: {', '.join([f.value for f in critique.detected_fallacies])}")
    print(f"Remediation: {critique.remediation}\n")

def cmd_purify(args):
    print_banner()
    target = Path(args.target)
    if not target.is_file():
        print(f"{RED}❌ Error: Target must be an existing file: {target}{RESET}")
        sys.exit(1)
    code = target.read_text(encoding="utf-8", errors="ignore")
    print(f"{CYAN}🌿 Purifying `{target.name}` from unlogical artifacts (Manṭiq & Al-Mufradāt)...{RESET}\n")
    report = AynMantiqPurifier.purify_python_code(code)
    print(f"{GREEN}{BOLD}βœ… PURIFICATION COMPLETE:{RESET}")
    for j in report.classical_justifications:
        print(f" β€’ {j}")
    print("\n--- Purified Code Preview ---")
    print(report.purified_code[:600] + ("..." if len(report.purified_code) > 600 else ""))

    if args.in_place:
        target.write_text(report.purified_code, encoding="utf-8")
        print(f"\n{GREEN}πŸ’Ύ Updated {target.resolve()} in-place.{RESET}")
    elif args.output:
        out = Path(args.output)
        out.write_text(report.purified_code, encoding="utf-8")
        print(f"\n{GREEN}πŸ’Ύ Saved purified code to {out.resolve()}.{RESET}")

def main():
    parser = argparse.ArgumentParser(
        description="AynEngine AI Coding Edition: Sovereign 5-Pillar Epistemic Code Engine",
        formatter_class=argparse.RawDescriptionHelpFormatter
    )
    parser.add_argument(
        "--provider",
        type=str,
        default=os.getenv("AYN_PROVIDER", "deepseek"),
        choices=["deepseek", "openai", "ollama", "offline"],
        help="LLM inference provider or offline mode (default: deepseek)"
    )
    parser.add_argument(
        "--model",
        type=str,
        default=os.getenv("AYN_MODEL", None),
        help="Model identifier override (e.g., ayncoding-gemma2, ayncoding-model)"
    )
    subparsers = parser.add_subparsers(dest="subcommand", help="Available subcommands")

    # Command: gen
    p_gen = subparsers.add_parser("gen", help="Synthesize complete code from a prompt")
    p_gen.add_argument("prompt", type=str, help="Coding specification or prompt")
    p_gen.add_argument("-l", "--language", type=str, default="python", help="Target programming language (default: python)")
    p_gen.add_argument("-o", "--output", type=str, help="Output file path to save code")
    p_gen.add_argument("--code-only", action="store_true", help="Print only raw code without epistemic rationale")

    # Command: audit (remote LLM)
    p_audit = subparsers.add_parser("audit", help="Perform 5-Pillar Epistemic Code Audit via LLM")
    p_audit.add_argument("target", type=str, help="File or directory to audit")
    p_audit.add_argument("-l", "--language", type=str, help="Explicit language override")

    # Command: audit-local (offline static epistemic auditor)
    p_audit_local = subparsers.add_parser("audit-local", help="Perform offline 5-Pillar Static Epistemic Audit (deterministic)")
    p_audit_local.add_argument("target", type=str, help="File to audit")
    p_audit_local.add_argument("-l", "--language", type=str, help="Language override (python, javascript, rust, etc.)")

    # Command: benchmark
    p_bench = subparsers.add_parser("benchmark", help="Run 5-Pillar Epistemic Benchmark across multiple files")
    p_bench.add_argument("target", type=str, help="File or directory containing source files")
    p_bench.add_argument("-l", "--language", type=str, help="File extension / language to filter (default: js)")

    # Command: refactor
    p_refactor = subparsers.add_parser("refactor", help="Refactor code to 5-Pillar standards")
    p_refactor.add_argument("target", type=str, help="File to refactor")
    p_refactor.add_argument("-g", "--goal", type=str, help="Specific refactoring goal")
    p_refactor.add_argument("-l", "--language", type=str, help="Language override")
    p_refactor.add_argument("-o", "--output", type=str, help="Output file")
    p_refactor.add_argument("-i", "--in-place", action="store_true", help="Overwrite file in-place")

    # Command: pillars
    p_pillars = subparsers.add_parser("pillars", help="Explain the 5 Classical Pillars and their software mappings")

    # Command: mantiq-dataset
    p_mantiq_data = subparsers.add_parser("mantiq-dataset", help="Synthesize Epistemic ManαΉ­iq & Morphology training dataset")
    p_mantiq_data.add_argument("-o", "--output", type=str, help="Output JSONL filepath")

    # Command: mantiq-audit
    p_mantiq_audit = subparsers.add_parser("mantiq-audit", help="Audit code for Classical Logic fallacies (Dawr, Tasalsul, Majaz Mukhil)")
    p_mantiq_audit.add_argument("target", type=str, help="File to audit")

    # Command: purify
    p_purify = subparsers.add_parser("purify", help="Purge unlogical artifacts, bare exceptions, and amorphous names")
    p_purify.add_argument("target", type=str, help="File to purify")
    p_purify.add_argument("-o", "--output", type=str, help="Output file")
    p_purify.add_argument("-i", "--in-place", action="store_true", help="Overwrite file in-place")

    args = parser.parse_args()

    if not args.subcommand:
        print_banner()
        parser.print_help()
        sys.exit(0)

    if args.subcommand == "pillars":
        cmd_pillars(args)
        sys.exit(0)
    elif args.subcommand == "mantiq-dataset":
        cmd_mantiq_dataset(args)
        sys.exit(0)
    elif args.subcommand == "mantiq-audit":
        cmd_mantiq_audit(args)
        sys.exit(0)
    elif args.subcommand == "purify":
        cmd_purify(args)
        sys.exit(0)

    # Initialize Engine for operational commands
    engine = AynCodingEngine(provider=args.provider, model=args.model)

    if args.subcommand == "gen":
        cmd_gen(args, engine)
    elif args.subcommand == "audit":
        cmd_audit(args, engine)
    elif args.subcommand == "audit-local":
        cmd_audit_local(args, engine)
    elif args.subcommand == "benchmark":
        cmd_benchmark(args, engine)
    elif args.subcommand == "refactor":
        cmd_refactor(args, engine)

if __name__ == "__main__":
    main()