init: llm-wiki-haness 하네스 설계
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verify that R2 workflow sources are connected to deterministic gateways."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from typing import Any, Iterable
|
||||
|
||||
|
||||
DEFAULT_ROOT = Path(__file__).resolve().parents[2]
|
||||
RESULT_SCHEMA = "workflow-connection-result/v1"
|
||||
WRITER_SOURCES = (
|
||||
Path("harness/source/agents/bodies/wiki-doc-author.md"),
|
||||
Path("harness/source/agents/bodies/wiki-source-summarizer.md"),
|
||||
)
|
||||
GLOBAL_REPORT_SOURCE = Path(".agents/plugins/wiki-superpowers/skills/wiki-workflow/SKILL.md")
|
||||
WRITER_REQUIRED = (
|
||||
"harness/runtime/document_commit.py",
|
||||
"document-commit/v1",
|
||||
"document-commit-result/v1",
|
||||
"--dry-run",
|
||||
"plan_sha256",
|
||||
"--expected-plan-sha256",
|
||||
"--apply",
|
||||
)
|
||||
WRITER_FORBIDDEN = (
|
||||
"자동 rollback 미구현",
|
||||
"**C4. Parent hub Cluster 갱신**",
|
||||
"**M5. Parent hub Cluster 점검**",
|
||||
"### Step 6: Parent hub Cluster 갱신",
|
||||
)
|
||||
REPORT_REQUIRED = (
|
||||
"proof-request/v1",
|
||||
"harness/runtime/proof_runner.py",
|
||||
"proof-runner-result/v1",
|
||||
"proof-manifest/v1",
|
||||
"manifest_sha256",
|
||||
"proof_count",
|
||||
"pass_count",
|
||||
"fail_count",
|
||||
"1~3",
|
||||
"실패",
|
||||
)
|
||||
SEMANTIC_WORKFLOW_SOURCES = (
|
||||
Path("harness/source/skills/project-spec.md"),
|
||||
Path("harness/source/skills/branch-spec.md"),
|
||||
Path("harness/source/skills/sync.md"),
|
||||
)
|
||||
SEMANTIC_REQUIRED = (
|
||||
"semantic_surface_extractor.py",
|
||||
"semantic_candidate_builder.py",
|
||||
"wiki-semantic-coherence-auditor",
|
||||
"semantic_audit.py",
|
||||
"semantic certificate",
|
||||
)
|
||||
PARENT_CERTIFICATE_SOURCE = Path("harness/source/skills/branch-from-project.md")
|
||||
PARENT_CERTIFICATE_REQUIRED = (
|
||||
"semantic_certificate.py",
|
||||
"--mode hub",
|
||||
"--path raw/project-notes/<project>.md",
|
||||
)
|
||||
|
||||
|
||||
class ConnectionCheckError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
def _finding(code: str, path: Path, token: str) -> dict[str, str]:
|
||||
return {"code": code, "path": path.as_posix(), "token": token}
|
||||
|
||||
|
||||
def _require_tokens(path: Path, text: str, tokens: Iterable[str]) -> list[dict[str, str]]:
|
||||
return [_finding("MISSING_REQUIRED_CONNECTION", path, token) for token in tokens if token not in text]
|
||||
|
||||
|
||||
def _report_sources(root: Path) -> list[Path]:
|
||||
body_root = root / "harness/source/agents/bodies"
|
||||
sources = [
|
||||
path.relative_to(root)
|
||||
for path in body_root.glob("*.md")
|
||||
if "§7.1" in path.read_text(encoding="utf-8") or "Self-Grep" in path.read_text(encoding="utf-8")
|
||||
]
|
||||
sources.append(GLOBAL_REPORT_SOURCE)
|
||||
return sorted(set(sources), key=lambda item: item.as_posix())
|
||||
|
||||
|
||||
def check(root: Path) -> dict[str, Any]:
|
||||
root = root.resolve(strict=True)
|
||||
findings: list[dict[str, str]] = []
|
||||
for relative in WRITER_SOURCES:
|
||||
path = root / relative
|
||||
if not path.is_file():
|
||||
findings.append(_finding("MISSING_CONNECTION_SOURCE", relative, ""))
|
||||
continue
|
||||
text = path.read_text(encoding="utf-8")
|
||||
findings.extend(_require_tokens(relative, text, WRITER_REQUIRED))
|
||||
findings.extend(
|
||||
_finding("FORBIDDEN_DIRECT_WRITE_CONTRACT", relative, token)
|
||||
for token in WRITER_FORBIDDEN
|
||||
if token in text
|
||||
)
|
||||
|
||||
for relative in SEMANTIC_WORKFLOW_SOURCES:
|
||||
path = root / relative
|
||||
if not path.is_file():
|
||||
findings.append(_finding("MISSING_CONNECTION_SOURCE", relative, ""))
|
||||
continue
|
||||
findings.extend(_require_tokens(relative, path.read_text(encoding="utf-8"), SEMANTIC_REQUIRED))
|
||||
parent_path = root / PARENT_CERTIFICATE_SOURCE
|
||||
if not parent_path.is_file():
|
||||
findings.append(_finding("MISSING_CONNECTION_SOURCE", PARENT_CERTIFICATE_SOURCE, ""))
|
||||
else:
|
||||
findings.extend(_require_tokens(PARENT_CERTIFICATE_SOURCE, parent_path.read_text(encoding="utf-8"), PARENT_CERTIFICATE_REQUIRED))
|
||||
|
||||
reporters = _report_sources(root)
|
||||
for relative in reporters:
|
||||
path = root / relative
|
||||
if not path.is_file():
|
||||
findings.append(_finding("MISSING_CONNECTION_SOURCE", relative, ""))
|
||||
continue
|
||||
findings.extend(_require_tokens(relative, path.read_text(encoding="utf-8"), REPORT_REQUIRED))
|
||||
|
||||
findings.sort(key=lambda item: (item["path"], item["code"], item["token"]))
|
||||
return {
|
||||
"schema_version": RESULT_SCHEMA,
|
||||
"status": "PASS" if not findings else "FAIL",
|
||||
"writer_sources": len(WRITER_SOURCES),
|
||||
"semantic_workflow_sources": len(SEMANTIC_WORKFLOW_SOURCES) + 1,
|
||||
"report_sources": len(reporters),
|
||||
"findings": findings,
|
||||
}
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--root", type=Path, default=DEFAULT_ROOT)
|
||||
args = parser.parse_args(argv)
|
||||
try:
|
||||
result = check(args.root)
|
||||
exit_code = 0 if result["status"] == "PASS" else 1
|
||||
except (ConnectionCheckError, OSError, UnicodeError, ValueError) as exc:
|
||||
result = {
|
||||
"schema_version": RESULT_SCHEMA,
|
||||
"status": "ERROR",
|
||||
"errors": [{"code": "WORKFLOW_CONNECTION_ERROR", "message": str(exc)}],
|
||||
}
|
||||
exit_code = 2
|
||||
json.dump(result, sys.stdout, ensure_ascii=False, indent=2, sort_keys=True)
|
||||
sys.stdout.write("\n")
|
||||
return exit_code
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user