mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
build-pc.sh Windows temp-dir re-exec fixes; CI pin actions and no-cache ROM handling; original-N64 and Deck presets; D440 preset labelling; D442 All unlocked as a RAM/query-time override; D443 settings values (MSAA 16x, Restart game); D444 front-end Previous/Next paging; D447 Original-aspect pillarbox/letterbox. Outside contributions by dolent: PRs #120 and #121 (relabelled D445, D446), merged as dolent's original commits. Refs: D440 D441 D442 D443 D444 D445 D446 D447 D387 D283 #120 #121
174 lines
5.5 KiB
Python
174 lines
5.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Report the context cost of the docs that every agent session loads.
|
|
|
|
Usage:
|
|
python tools_pc/docs_budget.py # table of per-file budget rows + tier-1 total
|
|
python tools_pc/docs_budget.py --json # same data as JSON
|
|
python tools_pc/docs_budget.py --toc FILE # markdown TOC (## / ### headings) for FILE
|
|
|
|
For each tracked doc it prints path, bytes, lines, approx_tokens (bytes // 4),
|
|
the per-file budget in approx tokens, and OK/OVER. Missing files are reported
|
|
as "missing" and are not an error (docs/HANDOFF.md is optional). It then sums
|
|
the "tier 1" set (CLAUDE.md, AGENTS.md, docs/HANDOFF.md, docs/ROADMAP.md)
|
|
against TIER1_BUDGET. Exit code is 1 if any file or the tier-1 total is OVER,
|
|
else 0.
|
|
"""
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
# Approximate-token budgets for each tracked doc.
|
|
BUDGETS = {
|
|
"CLAUDE.md": 4000,
|
|
"AGENTS.md": 6000,
|
|
"docs/HANDOFF.md": 3000,
|
|
"docs/ROADMAP.md": 12000,
|
|
"docs/porting-notes.md": 60000,
|
|
"docs/dev/findings.md": 600000,
|
|
"docs/dev/findings-index.csv": 40000,
|
|
}
|
|
|
|
# Files whose approx tokens are summed for the tier-1 total.
|
|
TIER1_FILES = ["CLAUDE.md", "AGENTS.md", "docs/HANDOFF.md", "docs/ROADMAP.md"]
|
|
TIER1_BUDGET = 25000
|
|
|
|
|
|
def repo_root():
|
|
"""Repo root = parent dir of the script's directory."""
|
|
return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
|
|
def read_bytes(path):
|
|
"""Return (bytes, lines) for a file read as UTF-8 with errors='replace',
|
|
or None if the file is missing."""
|
|
try:
|
|
with open(path, "r", encoding="utf-8", errors="replace") as f:
|
|
text = f.read()
|
|
except OSError:
|
|
return None
|
|
return len(text.encode("utf-8")), len(text.splitlines())
|
|
|
|
|
|
def collect_rows():
|
|
"""Build the list of row dicts for every tracked doc."""
|
|
root = repo_root()
|
|
rows = []
|
|
for rel in BUDGETS:
|
|
full = os.path.join(root, *rel.split("/"))
|
|
data = read_bytes(full)
|
|
if data is None:
|
|
rows.append({
|
|
"path": rel,
|
|
"bytes": None,
|
|
"lines": None,
|
|
"approx_tokens": None,
|
|
"budget_tokens": BUDGETS[rel],
|
|
"status": "missing",
|
|
})
|
|
else:
|
|
nbytes, nlines = data
|
|
tokens = nbytes // 4
|
|
budget = BUDGETS[rel]
|
|
rows.append({
|
|
"path": rel,
|
|
"bytes": nbytes,
|
|
"lines": nlines,
|
|
"approx_tokens": tokens,
|
|
"budget_tokens": budget,
|
|
"status": "OK" if tokens <= budget else "OVER",
|
|
})
|
|
return rows
|
|
|
|
|
|
def tier1_total(rows):
|
|
total = 0
|
|
for row in rows:
|
|
if row["path"] in TIER1_FILES and row["approx_tokens"] is not None:
|
|
total += row["approx_tokens"]
|
|
return total
|
|
|
|
|
|
def print_table(rows, t1):
|
|
header = f"{'path':<28} {'bytes':>10} {'lines':>8} {'tokens':>9} {'budget':>9} status"
|
|
print(header)
|
|
for row in rows:
|
|
if row["status"] == "missing":
|
|
print(f"{row['path']:<28} missing")
|
|
else:
|
|
print(
|
|
f"{row['path']:<28} {row['bytes']:>10} {row['lines']:>8} "
|
|
f"{row['approx_tokens']:>9} {row['budget_tokens']:>9} {row['status']}"
|
|
)
|
|
t1_status = "OK" if t1 <= TIER1_BUDGET else "OVER"
|
|
print(f"{'TIER1 TOTAL':<28} {'':>10} {'':>8} {t1:>9} {TIER1_BUDGET:>9} {t1_status}")
|
|
|
|
|
|
def main(argv=None):
|
|
parser = argparse.ArgumentParser(
|
|
description="Report the context cost of agent-session docs and fail when over budget."
|
|
)
|
|
parser.add_argument("--toc", metavar="FILE", help="print a markdown TOC for FILE")
|
|
parser.add_argument("--json", action="store_true", help="print JSON instead of the table")
|
|
args = parser.parse_args(argv)
|
|
|
|
if args.toc:
|
|
return print_toc(args.toc)
|
|
|
|
rows = collect_rows()
|
|
t1 = tier1_total(rows)
|
|
|
|
if args.json:
|
|
payload = {
|
|
"rows": rows,
|
|
"tier1": {"total_tokens": t1, "budget_tokens": TIER1_BUDGET,
|
|
"status": "OK" if t1 <= TIER1_BUDGET else "OVER"},
|
|
}
|
|
print(json.dumps(payload, indent=2))
|
|
else:
|
|
print_table(rows, t1)
|
|
|
|
over = any(r["status"] == "OVER" for r in rows) or t1 > TIER1_BUDGET
|
|
return 1 if over else 0
|
|
|
|
|
|
def github_anchor(heading):
|
|
"""GitHub-style anchor: lowercase, strip non-alnum/space/hyphen, spaces -> hyphens."""
|
|
text = heading.lower()
|
|
text = re.sub(r"[^a-z0-9 \-]", "", text)
|
|
return text.replace(" ", "-")
|
|
|
|
|
|
def print_toc(path):
|
|
"""Print a markdown TOC of '## ' / '### ' headings, skipping fenced code blocks."""
|
|
try:
|
|
with open(path, "r", encoding="utf-8", errors="replace") as f:
|
|
lines = f.read().splitlines()
|
|
except OSError as e:
|
|
print(f"error: cannot read {path}: {e}", file=sys.stderr)
|
|
return 1
|
|
|
|
in_fence = False
|
|
for line in lines:
|
|
if line.lstrip().startswith("```"):
|
|
in_fence = not in_fence
|
|
continue
|
|
if in_fence:
|
|
continue
|
|
if line.startswith("### "):
|
|
heading = line[4:].strip()
|
|
print(f" - [{heading}](#{github_anchor(heading)})")
|
|
elif line.startswith("## "):
|
|
heading = line[3:].strip()
|
|
print(f"- [{heading}](#{github_anchor(heading)})")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Headings contain non-ASCII (arrows, em dashes); a cp1252 console can't print them.
|
|
if hasattr(sys.stdout, "reconfigure"):
|
|
sys.stdout.reconfigure(encoding="utf-8")
|
|
sys.exit(main())
|