Spaces:
Running on Zero
Running on Zero
| #!/usr/bin/env python3 | |
| """Phase 0 gate — deterministic pre-flight, NO model, NO parser logic. | |
| Reproduces the Build-Plan Phase 0 gate (docs/BUILD-PLAN.md): | |
| - the fixture's line count must be 1316 | |
| - print the distinct top-level `type` counts | |
| And confirms the Phase-0 capability check: we can enumerate ~/.claude/projects | |
| and read a .jsonl (TRACE-CONTRACT §1). | |
| This is a pre-flight only. Turn/token/provenance numbers belong to Phase 1+. | |
| Run: python3 tools/phase0_check.py | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import sys | |
| from collections import Counter | |
| from pathlib import Path | |
| REPO = Path(__file__).resolve().parent.parent | |
| FIXTURE = REPO / "fixtures" / "sample-session.jsonl" | |
| EXPECTED_LINES = 1316 # TRACE-CONTRACT §6 — ground truth | |
| def type_counts(path: Path) -> tuple[int, int, Counter]: | |
| """Return (parsed_lines, parse_failures, Counter of top-level `type`).""" | |
| counts: Counter = Counter() | |
| parsed = 0 | |
| failures = 0 | |
| with path.open(encoding="utf-8") as fh: | |
| for line in fh: | |
| line = line.strip() | |
| if not line: | |
| continue | |
| parsed += 1 | |
| try: | |
| obj = json.loads(line) | |
| except json.JSONDecodeError: | |
| failures += 1 | |
| continue | |
| counts[obj.get("type", "<none>")] += 1 | |
| return parsed, failures, counts | |
| def enumerate_projects() -> tuple[int, int]: | |
| """Phase-0 capability check: can we walk ~/.claude/projects and see sessions?""" | |
| root = Path.home() / ".claude" / "projects" | |
| if not root.is_dir(): | |
| return 0, 0 | |
| dirs = [p for p in root.iterdir() if p.is_dir()] | |
| sessions = list(root.glob("**/*.jsonl")) | |
| return len(dirs), len(sessions) | |
| def main() -> int: | |
| if not FIXTURE.exists(): | |
| print(f"FAIL — fixture missing: {FIXTURE}") | |
| return 1 | |
| parsed, failures, counts = type_counts(FIXTURE) | |
| print("Her · हेर — Phase 0 pre-flight") | |
| print("=" * 52) | |
| print(f"fixture : {FIXTURE}") | |
| print(f"line count : {parsed} (expected {EXPECTED_LINES})") | |
| print(f"json parse errors: {failures}") | |
| print("-" * 52) | |
| print("top-level `type` counts:") | |
| width = max(len(k) for k in counts) if counts else 0 | |
| for name, n in sorted(counts.items(), key=lambda kv: (-kv[1], kv[0])): | |
| print(f" {name:<{width}} {n}") | |
| print(f" {'TOTAL':<{width}} {sum(counts.values())}") | |
| print("-" * 52) | |
| n_dirs, n_sessions = enumerate_projects() | |
| print(f"~/.claude/projects: {n_dirs} project dirs, {n_sessions} sessions readable") | |
| print("=" * 52) | |
| ok = (parsed == EXPECTED_LINES) and (failures == 0) | |
| print("GATE:", "PASS ✓" if ok else "FAIL ✗") | |
| return 0 if ok else 1 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |