enver's picture
tools: add bin/ayncode
d0bc232 verified
Raw History Blame Contribute Delete
21.9 kB
#!/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()