From efd8edfcc20f8023a8832ba0efa1046143180261 Mon Sep 17 00:00:00 2001 From: Joseph Anglada Date: Sun, 25 Oct 2026 03:01:52 -0400 Subject: [PATCH] Fix non-cone sparse baseline materialization of root inputs --- scripts/research_baseline_sparse.py | 28 +++++++++++++--- tests/test_research_baseline_sparse.py | 45 +++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/scripts/research_baseline_sparse.py b/scripts/research_baseline_sparse.py index c92a7b947a..8e39e5ed74 100644 --- a/scripts/research_baseline_sparse.py +++ b/scripts/research_baseline_sparse.py @@ -22,6 +22,7 @@ Douglas Colkitt, with Claude Opus 5.5 assistance. Apache-2.0. The sparse contract follows Arham-Tahir64's PR3102. +Non-cone materialization repair for Joseph Anglada, with OpenAI Codex assistance. """ import argparse import json @@ -83,16 +84,30 @@ def sparse_omissions(record, root=ROOT): return omitted -def materialize_command(omitted): - """Cone-mode directories covering the omitted files (one research package each).""" +def materialize_command(omitted, cone=True): + """Cover omitted inputs using the checkout's existing pattern mode.""" dirs = set() + root_files = set() for name in omitted: parts = name.split("/") + if not cone and len(parts) == 1: + root_files.add(name) + continue if parts[0] == "research" and len(parts) > 2: dirs.add("/".join(parts[:2])) else: dirs.add("/".join(parts[:-1]) or ".") - return ["git", "sparse-checkout", "add", *sorted(dirs)] + if cone: + patterns = sorted(dirs) + else: + # A bare '.' is a literal pattern here: it does not restore LICENSE + # or any other root input. Anchor and escape patterns so root files + # and package names cannot select unrelated paths through wildcards. + def literal(name): + return "".join("\\" + c if c in "\\*?[] " else c for c in name) + patterns = sorted(["/" + literal(name) for name in root_files] + + ["/" + literal(name) + "/" for name in dirs]) + return ["git", "sparse-checkout", "add", *patterns] def report(record, root=ROOT): @@ -107,10 +122,15 @@ def report(record, root=ROOT): "next": next_command, "scope": "Every selected input is present. Nothing was verified; run the baseline next.", } + mode = subprocess.run(["git", "config", "--bool", "--get", "core.sparseCheckoutCone"], + cwd=root, capture_output=True, text=True) + if mode.returncode not in (0, 1): + mode.check_returncode() + cone = mode.returncode == 0 and mode.stdout.strip() == "true" return 2, { "status": "SPARSE_SELECTED_INPUTS_ABSENT", "omitted_files": len(omitted), "first_omitted": omitted[:5], - "materialize": materialize_command(omitted), + "materialize": materialize_command(omitted, cone=cone), "next": next_command, "scope": "This sparse checkout omits selected inputs (skip-worktree entries matching HEAD). " "Run the materialize command, then " + baseline + "; nothing was verified.", diff --git a/tests/test_research_baseline_sparse.py b/tests/test_research_baseline_sparse.py index 319f7ff8f8..cfb433e8bf 100644 --- a/tests/test_research_baseline_sparse.py +++ b/tests/test_research_baseline_sparse.py @@ -1,4 +1,7 @@ -"""The sparse preflight names omitted selected inputs instead of failing opaquely.""" +"""The sparse preflight names omitted selected inputs instead of failing opaquely. + +Non-cone repair regressions for Joseph Anglada, with OpenAI Codex assistance. +""" import contextlib import io import json @@ -148,6 +151,46 @@ def test_productive_schema_routes_package_inventory_to_selected_baseline(self): self.assertEqual(code, 2) self.assertEqual(result["next"], ["python3", "-B", "scripts/research_selected_baseline.py"]) + def test_non_cone_command_restores_root_inputs_without_unrelated_files(self): + self.explicit_manifest() + unusual = "license [copy] .txt" + manifest = self.root / self.record["source_manifest"] + inventory = json.loads(manifest.read_text(encoding="utf-8")) + inventory["files"][unusual] = "0" + inventory["files"]["research/pkg [a]/proof.md"] = "0" + manifest.write_text(json.dumps(inventory), encoding="utf-8") + decoys = ("license c .txt", "unrelated.txt", "other/LICENSE", + "research/pkg a/decoy.md", "other/research/pkg [a]/proof.md") + for name in (unusual, "research/pkg [a]/proof.md", *decoys): + path = self.root / name + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text("unrelated or literal input\n", encoding="utf-8") + self.git("add", ".") + self.commit("root inputs and decoys") + self.git("sparse-checkout", "set", "--no-cone", "/scripts/", "/docs/", + "/certificates/selected-result.json") + code, result = self.run_main() + self.assertEqual(code, 2) + self.assertIn("LICENSE", sparse.sparse_omissions(self.record, self.root)) + self.git(*result["materialize"][1:]) + self.assertEqual(self.run_main()[0], 0) + self.assertTrue((self.root / "LICENSE").is_file()) + self.assertTrue((self.root / unusual).is_file()) + self.assertTrue((self.root / "research/pkg [a]/proof.md").is_file()) + for name in decoys: + self.assertFalse((self.root / name).exists(), name) + + def test_invalid_sparse_mode_does_not_publish_a_command(self): + self.git("sparse-checkout", "set", "--cone", "scripts", "docs", "certificates") + original_run = subprocess.run + def fail_mode(argv, **kwargs): + if argv[:3] == ["git", "config", "--bool"]: + return subprocess.CompletedProcess(argv, 128, "", "injected config failure") + return original_run(argv, **kwargs) + with mock.patch.object(subprocess, "run", side_effect=fail_mode): + with self.assertRaises(subprocess.CalledProcessError): + self.run_main() + def test_cone_sparse_names_packages_and_reads_manifest_from_head(self): self.git("sparse-checkout", "set", "--cone", "scripts", "docs", "certificates") self.assertFalse((self.root / "research/audit/SOURCE.json").exists())