Orchestrata Ultimate › Gates › generated-artifacts

Gate: generated-artifacts

At a glance

Purpose Refuse a registered generated artifact that git ignores or does not track, and a generator that vanished while files still name it.
Where it runs The scripts/gates.py battery (registered as generated-artifacts, input root !always, never cached); scripts/health_check.py.
Trigger Every battery run (it is never reused from the cache); a health check.
Exact command python scripts/check_generated_artifacts.py
Blocks Exit 1 on violations, 2 when the gate could not do its job, 0 pass. Non-waivable.
Ruling / ADR RUL-030 (gate scripts/check_generated_artifacts.py RUL-030).
Last recorded verdict ok: true in the primary checkout's .cache/gates.json (file last written 2026-09-22 10:01 local). wt-MAP-PRECOMMIT has no .cache/gates.json.

What it refuses

A registered generated artifact that git ignores or does not track — and, in the other direction, a generator that has vanished while files still claim it produced them.

Why it exists

Module docstring:

"Generated-artifacts gate — the mechanism for ruling RUL-030. User ruling, 2026-08-13: 'generated artifacts belong in git.'

The dispute this settles is concrete. plans/ast-*.json and reports/run-tests-latest.json were committed by some sessions … and deliberately withheld by others, so the working tree carried a permanent diff nobody could resolve, and a reader could not tell whether a missing snapshot meant 'not regenerated' or 'we don't keep those'. A generated artifact is a snapshot of project state at a commit; if it is not in the commit, the commit does not describe the project."

The other direction has its own recorded incident:

"On 2026-07-09, commit 6a186c9d deleted scripts/ast_serializer/testgen/ (9 files, 2,392 lines) with the rationale 'audited, zero consumers', because the audit equated no importer with no consumer. For a generator, the consumer is its OUTPUT, not its callers: ~100 files under tests/generated_recovery/ still named ast_serializer.testgen in their headers, but that directory sits under --ignore=tests/generated_recovery in pytest addopts, so nothing ever executed those files and nothing went red. The deletion was invisible… Self-fulfilling."

The boundary (what counts as an artifact)

The docstring's mechanical test — three properties, all required:

  1. Derived — "reproducible by running a named generator, never hand-authored."
  2. Read — "something consumes it: a gate, a doc @import, a report, a human."
  3. A function of the commit — "regenerating it at the same commit on another machine yields the same content. This is what excludes machine-local caches, per-run telemetry, wall-clock logs and locks."

Exclusions live in NOT_ARTIFACTS with a reason each, "so the exclusions are visible and auditable rather than implicit in a .gitignore line nobody reads" (e.g. reports/test-durations.ndjson — "282 MB of append-only per-run telemetry").

How it runs

RUL-030 at commit time

The same ruling is why the codebase maps are regenerated at commit time. Commit b5468cb1c (2026-10-22): "The maps are tracked (RUL-030) but only the SessionStart hook rewrote them, so every new checkout showed them modified. The pre-commit hook now runs the map generator when a commit stages Python and stages both maps; a failure warns and never blocks." scripts/hooks/pre-commit's _refresh_maps carries the same comment ("docs/CODEBASE_MAP.md and docs/CODEBASE_MAP_FULL.md are tracked artifacts (RUL-030)"). That step is not this gate and never blocks a commit; this gate is what would refuse the maps being ignored or untracked.

Typical failures and how to fix them

Wiring