Everything spotregen knows about a repository comes from three kinds of TOML files below regen/. This page describes them and every finding the static check can report.
The three file kinds
Definition 1 (Architecture)regen/architecture.toml is the compilation target: the shape every regenerated module must fit into. There is exactly one.
Definition 2 (Unit)regen/units/<unit>.toml describes one regenerable module: where it lives, what it promises (intent), which tests judge it (evaluations) and who depends on it (consumers). The file stem is conventionally the module name without the package.
Definition 3 (Decision)regen/decisions/<id>.toml is a provenance record: the driver, the decision, the rejected alternatives, the evidence, the assumptions and a review date. The file stem is the decision id.
architecture.toml
Table 1: Keys of regen/architecture.toml.
key
required
meaning
package
yes
top-level package name
source_dir
yes
directory (relative to the root) that holds the package, for example src
[allowed]
yes
per subpackage (or top-level module), the subpackages it may import; "__init__" is the package’s __init__.py
[pace]
no
per pace, the verification a change at that pace needs
known_cycles
no
accepted import cycles, each a pair of subpackages
An intent item has the three parts of Fowler, Regenerative Software, ch. 3: the scope (where the requirement applies), the invariant (what must remain true) and the reason (why the invariant matters). The fields statement and kind of spotregen < 0.2.0 are rejected with exit code 2 and a hint.
decisions/<id>.toml
Required: title, date, driver, decision, approved_by. Optional: status (default active), origin (default human), invariant, evidence, assumes, review_after, and [[alternatives]] with option and rejected_because. Evidence entries start with file: (must exist in the repository), commit: (must be a commit of it), KB: (an entry of the knowledge-base directory, checked only if that directory exists) or url: (never fetched).
Vocabularies
The values below are read from spotregen.spec, so this page cannot drift from the loader. A value outside its vocabulary stops the tool with exit code 2.
pace fast, medium, slow
risk low, medium, high
consumer kind code, test, script, book, doc, external, operational, human
decision status active, superseded, expired
decision origin human, machine
Only the consumer kinds code, test, script, book and doc (files in this repository) are checked against the tree. external is a file in a downstream repository, written <repo>:<path>; operational and human are free text. They cannot be checked, so keep them current when a contract changes.
What counts as a consumer
A Python file under scan_dirs is a consumer of a unit when an import statement names the module, or imports one of its public names through a package that re-exports it. A document matched by doc_globs is a consumer when its text names the module, imports its leaf from the parent package or imports a re-exported public name. Attribute access through an imported package is not detected.
NoteFixed conventions
These are part of the schema and shared between repositories that use the tool:
An evaluation file must contain pytest.mark.regen and import only names listed in the unit’s public (EVAL02, EVAL03).
Files under tests/ are shown as kind test in the deletion report, everything else in Python as code.
The directories .venv, __pycache__, _site, _freeze and reference (the quartodoc output) are never scanned for consumers.
When kb_dir is unset and REGEN_KB_DIR is not exported, KB: evidence is not checked.
Finding codes
A finding is rendered as one line, LEVEL CODE where: message, the level padded to 7 and the code to 7 characters. Errors fail the check; warnings ask for attention and fail it only with --strict. The line format, the codes and their levels are a stability contract.
import astimport refrom pathlib import Pathfrom IPython.display import Markdownfrom spotregen import checksMEANING = {"ARCH00": "a source file of the package does not parse","ARCH01": "a subpackage imports a subpackage that `[allowed]` does not permit","ARCH02": "a subpackage is missing from `[allowed]`","ARCH03": "an allowed edge is unused, or a listed subpackage does not exist","ARCH04": "a new import cycle, not listed in `known_cycles`","ARCH05": "a cycle listed in `known_cycles` no longer exists","UNIT01": "the unit's module does not exist or does not parse","UNIT02": "`path` is not the file of the module the record names","UNIT03": "a name in `public` is not defined in the module","UNIT04": "the module imports a package module that is not in `depends_on`","UNIT05": "an entry of `depends_on` is not imported","UNIT06": "the record declares no intent item","EVAL01": "an evaluation file or a named evaluation does not exist, or the file does not parse","EVAL02": "an evaluation file lacks the pytest marker `regen`","EVAL03": "an evaluation imports a name of the unit that is not public","EVAL04": "an intent item names no evaluation","EVAL05": "an evaluation is not linked to any intent item","PROV01": "an intent item or the architecture cites an unknown decision","PROV02": "evidence of a decision does not resolve (file, commit, KB entry or prefix)","PROV03": "an active decision is past its `review_after` date","PROV04": "an intent item rests on a decision that is not active","PROV05": "no intent item or architecture entry cites the decision","DEL01": "a file in the repository depends on the unit but is not a declared consumer","DEL02": "a declared consumer in the repository does not exist","DEL03": "a declared consumer no longer references the unit",}# Findings are built by Finding(...) and by local helpers (declared_at, at_item, at),# all of which take the level and the code as their first two positional arguments.found = {}for node in ast.walk(ast.parse(Path(checks.__file__).read_text(encoding="utf-8"))):if (isinstance(node, ast.Call)andlen(node.args) >=2andall(isinstance(a, ast.Constant) andisinstance(a.value, str) for a in node.args[:2])and node.args[0].value in ("error", "warning")and re.fullmatch(r"[A-Z]{3,4}\d\d", node.args[1].value) ): found.setdefault(node.args[1].value, set()).add(node.args[0].value)assertset(found) ==set(MEANING), set(found) ^set(MEANING)assertall(len(levels) ==1for levels in found.values())rows = ["| code | level | meaning |", "|:--|:--|:--|"]for code insorted(MEANING): rows.append(f"| {code} | {next(iter(found[code]))} | {MEANING[code]} |")Markdown("\n".join(rows))
Table 3: Every finding code, its level and meaning. The codes and levels are read from the source of spotregen.checks: a code that is added, removed or changes its level stops the render until this table is updated.
code
level
meaning
ARCH00
error
a source file of the package does not parse
ARCH01
error
a subpackage imports a subpackage that [allowed] does not permit
ARCH02
error
a subpackage is missing from [allowed]
ARCH03
warning
an allowed edge is unused, or a listed subpackage does not exist
ARCH04
error
a new import cycle, not listed in known_cycles
ARCH05
warning
a cycle listed in known_cycles no longer exists
DEL01
error
a file in the repository depends on the unit but is not a declared consumer
DEL02
error
a declared consumer in the repository does not exist
DEL03
warning
a declared consumer no longer references the unit
EVAL01
error
an evaluation file or a named evaluation does not exist, or the file does not parse
EVAL02
error
an evaluation file lacks the pytest marker regen
EVAL03
error
an evaluation imports a name of the unit that is not public
EVAL04
error
an intent item names no evaluation
EVAL05
warning
an evaluation is not linked to any intent item
PROV01
error
an intent item or the architecture cites an unknown decision
PROV02
error
evidence of a decision does not resolve (file, commit, KB entry or prefix)
PROV03
warning
an active decision is past its review_after date
PROV04
warning
an intent item rests on a decision that is not active
PROV05
warning
no intent item or architecture entry cites the decision
UNIT01
error
the unit’s module does not exist or does not parse
UNIT02
error
path is not the file of the module the record names
UNIT03
error
a name in public is not defined in the module
UNIT04
error
the module imports a package module that is not in depends_on
UNIT05
warning
an entry of depends_on is not imported
UNIT06
error
the record declares no intent item
The prefixes group the checks: ARCH (compilation: allowed imports between subpackages, import cycles), UNIT (a unit record against its module), EVAL (the evaluation files and their links to intent items), PROV (decision records and the citations of them) and DEL (every dependent inside the repository is a declared consumer, and every declared consumer exists).
Exit codes and summary lines
Table 4: Exit codes. Exit 2 covers a malformed record (including invalid TOML), an unknown unit, a missing regen/architecture.toml and argparse errors.
command
exit 0
exit 1
exit 2
check
no error (with --strict: no finding)
an error, or a warning with --strict
spec or argument error
deletion-test
the report says Verdict: regenerable
any other verdict
spec, unit or argument error
status, context, compact, measures, new-unit
success
spec, unit or argument error; with measures --mutation-score also evaluations that fail on the unchanged module
mutate
every mutant killed
a mutant survived
spec, unit or argument error, no evaluation file, or evaluations that fail on the unchanged module
claude, local
the last attempt’s evaluations pass
they do not
spec, unit or missing-tool error
The summary lines regen check: N units, E errors, W warnings and regen compact: N candidates keep their regen prefix. Messages on standard error start with spotregen:.
Run records
The drivers write a run.toml per run. Its field protocol names the procedure that produced the run: regeneration for spotregen claude, regeneration-local-sessions for spotregen local and canary for spotregen local --canary. Archived runs written before 0.7.0 carry the values blind-regeneration and blind-regeneration-local-sessions.
Stability contract
Pinned by the test suite and treated as MAJOR-relevant even in 0.x: the finding codes and levels, the line format and order, the summary lines, the exit codes, the Markdown of status, deletion-test and context, the TOML schema, the regen/ directory and REGEN_KB_DIR. Context bundles are byte-identical across releases, because archived runs record the SHA-256 of the bundle they were given (bundle_sha256). Additions to the schema are optional only.