Summary
docs/guide/*.md is generated from docs/_pipeline/templates/*.md.dt. The only gate that detects drift between them is the Docs tier-drift CI job — and its path filter watches the templates, not the generated output.
A change that touches only docs/guide/*.md and leaves the template untouched sets docs-templates=false, skips the job, and ships with no gate at all.
OBSERVED_AT 2026-08-01T13:45:35Z main = 1ed2644e
.github/workflows/ci.yml:71
if echo "$files" | grep -qE '^(docs/_pipeline/templates/|docs/_pipeline/apps/|src/Reactor\.Cli/Docs/)'; then
docs-templates=true
'docs/_pipeline' in the filter block : True
'docs/guide' in the filter block : FALSE <- the artifact it protects
No unit-test gate compensates
The other two generated artifacts in this repo are gated by tests that run in the Unit Tests leg, which executes on every non-Markdown change:
| artifact |
gate |
runs when |
samples/ReactorGallery/reactor-search-index.json |
SearchIndexGeneratorTests.Index_IsUpToDate |
every non-md change |
skills/reactor.api.txt (+ plugins copy) |
ApiIndexGeneratorTests |
every non-md change |
docs/guide/*.md |
Docs tier-drift CI job only |
only when a template/app/CLI path changes |
Searched every test referencing md.dt — CrossLinkLintTests, DiagramTests, TierLintTests, TierLintOrchestratorTests, FlexPanelCssBehaviorFixtures, VersionSingleSourceTests. The only one touching both docs/guide and a compile step is VersionSingleSourceTests, and it is version-only — seven tests about version literals/tokens, Assert.Equal occurrences: 0.
Why this is reachable, not theoretical
Found while verifying a merge. git merge-tree on two open PRs reports:
CONFLICT (content): ... 5 files ...
Auto-merging docs/_pipeline/templates/data-system.md.dt
Auto-merging docs/guide/data-system.md <- generated output, SILENT
Auto-merging tests/.../DataGridEditFixtures.cs
Git merges the template and its generated output as two unrelated text files. It can interleave two generated outputs into a file the generator would never emit, and no conflict marker appears on either.
In that particular merge the template also changes, so the gate would fire. That is incidental. Any of these skips it:
- a merge where only one side changed the template, so only the output auto-merges
- a hand-edit of
docs/guide/*.md (forbidden by AGENTS.md — and this gate is what enforces it)
- a revert or cherry-pick touching only the output
The absence of a conflict marker is not evidence that regeneration can be skipped — and here nothing downstream will catch it either.
Suggested fix
Add docs/guide/ to the docs-templates filter at ci.yml:71:
if echo "$files" | grep -qE '^(docs/_pipeline/templates/|docs/_pipeline/apps/|src/Reactor\.Cli/Docs/|docs/guide/)'; then
The job already does the right comparison (docs compile --no-screenshots --ci then fails with "docs/guide is out of date with the doc templates" at :670) — it simply is not invited to run when only its subject changes.
Non-vacuity check for the fix: modify one byte of a committed docs/guide/*.md without touching any template, and confirm Docs tier-drift runs and fails. Under the current filter it does not run at all.
Surfaced by the #1010 session's observation that merge-tree's auto-merge lines matter more than its conflict list; filter and gate coverage verified independently here.
Summary
docs/guide/*.mdis generated fromdocs/_pipeline/templates/*.md.dt. The only gate that detects drift between them is theDocs tier-driftCI job — and its path filter watches the templates, not the generated output.A change that touches only
docs/guide/*.mdand leaves the template untouched setsdocs-templates=false, skips the job, and ships with no gate at all.No unit-test gate compensates
The other two generated artifacts in this repo are gated by tests that run in the
Unit Testsleg, which executes on every non-Markdown change:samples/ReactorGallery/reactor-search-index.jsonSearchIndexGeneratorTests.Index_IsUpToDateskills/reactor.api.txt(+ plugins copy)ApiIndexGeneratorTestsdocs/guide/*.mdDocs tier-driftCI job onlySearched every test referencing
md.dt—CrossLinkLintTests,DiagramTests,TierLintTests,TierLintOrchestratorTests,FlexPanelCssBehaviorFixtures,VersionSingleSourceTests. The only one touching bothdocs/guideand a compile step isVersionSingleSourceTests, and it is version-only — seven tests about version literals/tokens,Assert.Equaloccurrences: 0.Why this is reachable, not theoretical
Found while verifying a merge.
git merge-treeon two open PRs reports:Git merges the template and its generated output as two unrelated text files. It can interleave two generated outputs into a file the generator would never emit, and no conflict marker appears on either.
In that particular merge the template also changes, so the gate would fire. That is incidental. Any of these skips it:
docs/guide/*.md(forbidden byAGENTS.md— and this gate is what enforces it)Suggested fix
Add
docs/guide/to thedocs-templatesfilter atci.yml:71:The job already does the right comparison (
docs compile --no-screenshots --cithen fails with "docs/guide is out of date with the doc templates" at:670) — it simply is not invited to run when only its subject changes.Non-vacuity check for the fix: modify one byte of a committed
docs/guide/*.mdwithout touching any template, and confirmDocs tier-driftruns and fails. Under the current filter it does not run at all.Surfaced by the #1010 session's observation that
merge-tree's auto-merge lines matter more than its conflict list; filter and gate coverage verified independently here.