Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 46 additions & 2 deletions scripts/evolve/refresh.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ def _run(command: list[str], root: Path) -> str:


def _git_changes(root: Path) -> tuple[list[str], int]:
output = _run(["git", "status", "--porcelain=v1"], root)
output = _run(
["git", "status", "--porcelain=v1", "--untracked-files=all"],
root,
)
files = []
for line in output.splitlines():
if not line:
Expand Down Expand Up @@ -106,6 +109,41 @@ def _write_summary(root: Path, run_date: str, summary: dict[str, Any]) -> Path:
return path


def _finalize_summary(
root: Path,
run_date: str,
summary: dict[str, Any],
*,
max_files: int,
max_lines: int,
max_passes: int = 5,
) -> dict[str, Any]:
"""Write and measure until summary metadata matches the on-disk diff.

The summary includes its own path and line contribution, so one measurement
cannot be final. A bounded fixed-point loop makes the invariant explicit:
budgets are enforced only when the values stored in the summary equal a
fresh measurement of the exact state that contains that summary.
"""
for _ in range(max_passes):
_write_summary(root, run_date, summary)
changed_files, changed_lines = _git_changes(root)
if (
summary.get("changed_files") == changed_files
and summary.get("changed_lines") == changed_lines
):
enforce_change_budget(
changed_files,
changed_lines=changed_lines,
max_files=max_files,
max_lines=max_lines,
)
return summary
summary["changed_files"] = changed_files
summary["changed_lines"] = changed_lines
raise RuntimeError("refresh summary accounting did not converge")


def run_refresh(args: argparse.Namespace, root: Path = WIKI_ROOT) -> dict[str, Any]:
run_date = args.captured_at or date.today().isoformat()
initial_files, _ = _git_changes(root)
Expand Down Expand Up @@ -202,7 +240,13 @@ def run_refresh(args: argparse.Namespace, root: Path = WIKI_ROOT) -> dict[str, A
"dry_run": bool(args.dry_run),
}
if not args.dry_run:
_write_summary(root, run_date, summary)
summary = _finalize_summary(
root,
run_date,
summary,
max_files=args.max_files,
max_lines=args.max_lines,
)
_run([sys.executable, "scripts/validate.py"], root)
_run([sys.executable, "tests/test_evolution.py"], root)
return summary
Expand Down
70 changes: 67 additions & 3 deletions tests/test_evolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from __future__ import annotations

import json
import subprocess
import sys
import tempfile
from pathlib import Path
Expand Down Expand Up @@ -259,9 +260,10 @@ def test_corpus_manifest_is_generated_from_the_checkout():
(ROOT / "data" / "corpus-manifest.yaml").read_text(encoding="utf-8")
)
assert committed == expected
assert expected["counts"]["source_prs"] == 7454
assert expected["counts"]["active_wiki_pages"] == 54
assert expected["counts"]["artifact_bundles"] == 959
counts = expected["counts"]
assert counts["source_prs"] > 0
assert 0 < counts["active_wiki_pages"] <= counts["wiki_pages"]
assert counts["artifact_bundles"] <= counts["source_prs"]


def test_candidate_schema_and_gap_detection():
Expand Down Expand Up @@ -387,6 +389,68 @@ def test_refresh_budget_rejects_unreviewable_change_sets():
raise AssertionError("oversized refresh was accepted")


def test_refresh_expands_untracked_directories_for_budgeting():
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
from evolve.refresh import _git_changes

with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
subprocess.run(["git", "init", "-q", str(root)], check=True)
nested = root / "candidates" / "runs" / "today"
nested.mkdir(parents=True)
(nested / "one.yaml").write_text("one: true\n", encoding="utf-8")
(nested / "two.yaml").write_text("two: true\n", encoding="utf-8")
changed_files, changed_lines = _git_changes(root)
assert changed_files == [
"candidates/runs/today/one.yaml",
"candidates/runs/today/two.yaml",
]
assert changed_lines == 2


def test_final_summary_is_inside_the_enforced_budget():
from evolve.refresh import _finalize_summary, _git_changes

with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
subprocess.run(["git", "init", "-q", str(root)], check=True)
summary = {
"schema_version": 1,
"run_date": "2026-07-22",
"discovery": {"total": 0},
"gap_proposals": 0,
"machine_changes": 0,
"changed_files": [],
"changed_lines": 0,
"dry_run": False,
}
try:
_finalize_summary(
root,
"2026-07-22",
summary,
max_files=0,
max_lines=100,
)
except ValueError as error:
assert "file budget" in str(error)
else:
raise AssertionError("summary file escaped the final file budget")

finalized = _finalize_summary(
root,
"2026-07-22",
summary,
max_files=1,
max_lines=100,
)
changed_files, changed_lines = _git_changes(root)
assert finalized["changed_files"] == changed_files
assert finalized["changed_lines"] == changed_lines
assert changed_files == [
"candidates/runs/2026-07-22/refresh-summary.yaml"
]


def test_query_marks_upstream_pr_snippets_as_untrusted():
import query

Expand Down
Loading