Initial commit: Add project files
ci / backend (push) Failing after 12s
ci / frontend (push) Failing after 19s
ci / static (push) Failing after 45s

This commit is contained in:
2026-08-02 05:15:36 +09:00
commit dcd1322d41
636 changed files with 122352 additions and 0 deletions
+174
View File
@@ -0,0 +1,174 @@
#!/usr/bin/env python3
from __future__ import annotations
import csv
import json
import py_compile
import re
import shutil
import sys
import xml.etree.ElementTree as ET
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
ERRORS: list[str] = []
WARNINGS: list[str] = []
CHECKS: list[str] = []
def ok(message: str) -> None:
CHECKS.append(message)
def fail(message: str) -> None:
ERRORS.append(message)
def warn(message: str) -> None:
WARNINGS.append(message)
def active_files(pattern: str):
for path in ROOT.rglob(pattern):
rel = path.relative_to(ROOT)
if rel.parts[:1] == ("attachments",):
continue
if rel.parts[:2] == ("research", "original"):
continue
if rel.parts[:1] == ("tests",):
continue
if any(part in {"bin", "obj", "node_modules", "__pycache__"} for part in rel.parts):
continue
yield path
required = [
"README.md",
"AGENTS.md",
"global.json",
"KArtSell.sln",
"docs/v12/00_EXECUTIVE_INTEGRATED_PROPOSAL.md",
"docs/v12/07_WBS_MASTER.csv",
"docs/v12/08_TECH_DEBT_REGISTER.csv",
"docs/v12/09_TRACEABILITY_MATRIX.csv",
"db/migrations/0012_signal_engine_integrated_hardening.sql",
"research/hardening/TEST_RESULTS.txt",
"attachments/original/K-ArtSell_12_2_complete_package(1).zip",
"attachments/original/K-ArtSell_퀀트투자자문_SI_본프로그램착수_누적고도화_통합실행기준서_v10.0(1).docx",
"attachments/original/KArtSell_v11_implementation_acceleration(1).zip",
"attachments/original/KArtSell_Aegis_v11_1_hardening(1).zip",
]
for name in required:
if not (ROOT / name).exists():
fail(f"missing required file: {name}")
if not ERRORS:
ok(f"required files present: {len(required)}")
for path in active_files("*.json"):
try:
json.loads(path.read_text(encoding="utf-8"))
except Exception as exc:
fail(f"invalid JSON {path.relative_to(ROOT)}: {exc}")
ok("JSON parse complete")
for path in [*active_files("*.csproj"), *active_files("*.props")]:
try:
ET.parse(path)
except Exception as exc:
fail(f"invalid XML {path.relative_to(ROOT)}: {exc}")
ok("MSBuild XML parse complete")
for path in active_files("*.csv"):
try:
with path.open(encoding="utf-8-sig", newline="") as handle:
rows = list(csv.reader(handle))
if not rows:
fail(f"empty CSV {path.relative_to(ROOT)}")
else:
width = len(rows[0])
bad = [i + 1 for i, row in enumerate(rows) if len(row) != width]
if bad:
fail(f"ragged CSV {path.relative_to(ROOT)} rows {bad[:10]}")
except Exception as exc:
fail(f"invalid CSV {path.relative_to(ROOT)}: {exc}")
ok("CSV structure complete")
for path in active_files("*.py"):
try:
py_compile.compile(str(path), doraise=True)
except Exception as exc:
fail(f"Python compile failed {path.relative_to(ROOT)}: {exc}")
ok("Python compile complete")
for path in active_files("*.yaml"):
text = path.read_text(encoding="utf-8")
if "\t" in text:
fail(f"YAML contains tab indentation: {path.relative_to(ROOT)}")
if not text.strip():
fail(f"empty YAML: {path.relative_to(ROOT)}")
ok("YAML basic checks complete")
source_files = [*active_files("*.cs"), *active_files("*.sql")]
patterns = {
"AllowAnonymous()": "anonymous module endpoint",
"IGenericRepository": "generic repository",
"DateTime.Now": "direct wall-clock use",
"DateTime.UtcNow": "direct wall-clock use",
}
for token, label in patterns.items():
hits = [str(p.relative_to(ROOT)) for p in source_files if token in p.read_text(encoding="utf-8")]
if hits:
fail(f"{label} pattern {token}: {hits}")
select_star = []
for path in source_files:
text = path.read_text(encoding="utf-8")
if re.search(r"\bselect\s+\*", text, flags=re.IGNORECASE):
select_star.append(str(path.relative_to(ROOT)))
if select_star:
fail(f"SELECT * prohibited: {select_star}")
ok("prohibited source pattern scan complete")
for path in active_files("Endpoint.cs"):
text = path.read_text(encoding="utf-8")
if "Roles(" not in text and "Policies(" not in text:
fail(f"endpoint lacks Roles/Policies: {path.relative_to(ROOT)}")
ok("endpoint authorization declarations complete")
for path in active_files("*.cs"):
if f"{Path('Domain')}" in str(path.relative_to(ROOT)):
text = path.read_text(encoding="utf-8")
for token in ["using Dapper", "using Npgsql", "using FastEndpoints", "using Hangfire", "HttpContext", "DbConnection"]:
if token in text:
fail(f"domain framework dependency {token}: {path.relative_to(ROOT)}")
ok("domain dependency scan complete")
migration_names = sorted(p.name for p in (ROOT / "db" / "migrations").glob("*.sql"))
if not all(re.match(r"^\d{4}_[a-z0-9_]+\.sql$", name) for name in migration_names):
fail("migration filename format must be NNNN_snake_case.sql")
if len(migration_names) != len(set(migration_names)):
fail("duplicate migration filename")
ok(f"migration ordering complete: {len(migration_names)} scripts")
for path in active_files("*"):
if path.is_file() and path.name.lower() in {"testfile", "temp", "tmp"}:
fail(f"placeholder file: {path.relative_to(ROOT)}")
ok("placeholder scan complete")
if not (ROOT / "frontend" / "pnpm-lock.yaml").exists():
warn("frontend/pnpm-lock.yaml is missing by design; G0 must generate and review it")
if shutil.which("dotnet") is None:
warn("dotnet SDK unavailable in current validation environment")
if shutil.which("pnpm") is None:
warn("pnpm unavailable in current validation environment")
print("K-ArtSell Aegis v12.0 static validation")
print(f"root={ROOT}")
for message in CHECKS:
print(f"PASS: {message}")
for message in WARNINGS:
print(f"WARN: {message}")
for message in ERRORS:
print(f"FAIL: {message}")
print(f"summary: pass={len(CHECKS)} warn={len(WARNINGS)} fail={len(ERRORS)}")
sys.exit(1 if ERRORS else 0)