import subprocess
import sys
import tempfile
from pathlib import Path
from spotregen import make_sample_repo
tmp = tempfile.TemporaryDirectory()
root = make_sample_repo(Path(tmp.name) / "demo")
def spotregen(*args, drop=None):
"""Run `spotregen` in the sample repository; show the call and its output."""
done = subprocess.run(
[sys.executable, "-m", "spotregen", *args],
cwd=root,
capture_output=True,
text=True,
check=False,
)
print("$ spotregen", *args)
lines = (done.stdout + done.stderr).splitlines()
print("\n".join(x for x in lines if not (drop and drop in x)))
print(f"[exit {done.returncode}]")The deletion test
Definition 1 (The deletion test) Fowler’s deletion test asks what would be lost if a module were deleted. For one unit spotregen deletion-test lists the blast radius (every dependent, declared or not), the intent items with their evaluation and provenance coverage, and a verdict. The verdict is “regenerable” only if every intent item has an evaluation, every dependent is declared and the unit check reports no error.
Example 1 (A regenerable unit) A unit may be named by its dotted name or by any unique suffix.
spotregen("deletion-test", "core.calc")$ spotregen deletion-test core.calc
# Deletion test: samplepkg.core.calc
File `src/samplepkg/core/calc.py`, pace fast, risk low.
## Blast radius
| dependent | kind | declared | note |
|---|---|---|---|
| `docs/guide.qmd` | doc | yes | teaches add |
| `src/samplepkg/app/main.py` | code | yes | sums values with add |
| `tests/test_regen_eval_calc.py` | test | yes | evaluation |
## Knowledge outside the implementation
| intent | kind | evaluations | decisions |
|---|---|---|---|
| C-1 | contract | 1 | why-add |
Verdict: regenerable. 1 intent items, all evaluated; 3 dependents, all declared.
[exit 0]
The exit code is 0 exactly when the report contains Verdict: regenerable.
Example 2 (An undeclared dependent)
(root / "scripts").mkdir()
(root / "scripts" / "use_it.py").write_text("from samplepkg.core.calc import add\n")
spotregen("deletion-test", "core.calc")$ spotregen deletion-test core.calc
# Deletion test: samplepkg.core.calc
File `src/samplepkg/core/calc.py`, pace fast, risk low.
## Blast radius
| dependent | kind | declared | note |
|---|---|---|---|
| `docs/guide.qmd` | doc | yes | teaches add |
| `scripts/use_it.py` | code | NO | |
| `src/samplepkg/app/main.py` | code | yes | sums values with add |
| `tests/test_regen_eval_calc.py` | test | yes | evaluation |
## Knowledge outside the implementation
| intent | kind | evaluations | decisions |
|---|---|---|---|
| C-1 | contract | 1 | why-add |
## Gaps
- DEL01: scripts/use_it.py depends on the unit but is not a declared consumer
Verdict: NOT regenerable yet (1 gaps).
[exit 1]
The blast radius lists the script with declared = NO, the gaps name the finding that fails (DEL01) and the verdict is not regenerable. The exit code is 1.
A unit that matches nothing, or more than one unit, exits with code 2 and lists the known units.
spotregen("deletion-test", "nope")$ spotregen deletion-test nope
spotregen: "unknown unit 'nope'; known: ['samplepkg.core.calc']"
[exit 2]
Next: the regeneration bundle.