Skip to content

Samples gate: six known-debt entries name NodeTypes that no longer exist (#1786) - #2472

Merged
rbuergi merged 2 commits into
mainfrom
fix/1786-samples-gate-dead-entries
Aug 27, 2026
Merged

rbuergi merged 2 commits into
mainfrom
fix/1786-samples-gate-dead-entries

Conversation

@rbuergi

@rbuergi rbuergi commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

.github/samples-gate.allow still carried six compile entries for FutuRe/{AmericasIns,AsiaRe,EuropeRe}/{LineOfBusiness,TransactionMapping} — NodeTypes that b63fbf057/091a57a6c retired to plain Markdown nodes when #2030 landed. Read from the file, those six lines assert that six NodeTypes are still failing to compile in production, which is the condition #1786 reports. They have named nothing for a week.

Why the gate's own ratchet could not retire them

Stale-detection asks did this subject pass? (bake.Types.Any(t => t.Success && t.NodePath == e.Scope)), so it retires an entry whose type now compiles. A subject that no longer exists never passes and never fails — the tester prints unverifiable allow entry (check skipped or scope absent this run) and stays green. Six such lines were printed on every main run since #2030.

That default is correct there and is left unchanged: the tester is shared with the satellite repos, which stage a subset of their tree, so "listed but absent" is genuinely unknowable for them.

It is not unknowable here: stage-samples-gate.sh copies all eight packages and stage-doc-gate.sh copies the whole Doc tree, unconditionally. So in this repo "absent" means retired, and it is decidable statically.

GateAllowEntrySubjectGuard

Every entry in both allow files must name a subject this repo still ships:

  • type-level (compile/render/tests) → a node file whose content.$type is NodeTypeDefinition;
  • package-level (install/idempotence) → a package directory;
  • the first path segment must be a package the lane's staging script actually stages — parsed from the script so the two cannot drift, with the parse itself asserted non-empty.

It complements the gate rather than duplicating it: stale-detection catches fixed, this catches gone.

Proven non-vacuous

With the six lines restored the guard fails naming all six and saying what each became:

.github/samples-gate.allow:1 'FutuRe/AmericasIns/LineOfBusiness compile'
  — samples/Graph/Data/FutuRe/AmericasIns/LineOfBusiness.json is not a NodeType any more (nodeType: Markdown)

TheResolverIsNotVacuous pins the resolver from both sides — a live NodeType resolves as a NodeType, the six retired files resolve and are rejected, a fabricated path resolves to nothing, and the Doc lane's Doc/ prefix really addresses the documentation tree — so it cannot degrade into a check that answers "found" for everything.

The two PensionFund entries stay: separately diagnosed debt this issue does not own, both still naming live subjects.

Verification

  • dotnet build test/MeshWeaver.Graph.Test/MeshWeaver.Graph.Test.csproj -c Release -warnaserror → 0 Warning(s), 0 Error(s)
  • guard red with the six lines present (both tests, one fails naming all six), green with them removed

No What's New entry — CI-internal, no user-visible effect.

Part of #1786.

🤖 Generated with Claude Code

… exist (#1786)

`.github/samples-gate.allow` still carried six `compile` entries for
`FutuRe/{AmericasIns,AsiaRe,EuropeRe}/{LineOfBusiness,TransactionMapping}` —
NodeTypes that `b63fbf057`/`091a57a6c` retired to plain `Markdown` nodes when
#2030 landed. Read from the file, those six lines say "six NodeTypes are still
failing to compile in production", which is exactly the condition #1786 reports
and exactly what a reader will believe. They have named nothing for a week.

**Why the ratchet could not retire them.** The gate's stale-detection asks *did
this subject pass?* — `bake.Types.Any(t => t.Success && t.NodePath == e.Scope)` —
so it retires an entry whose type now COMPILES. A subject that no longer EXISTS
never passes and never fails: the tester prints `unverifiable allow entry (check
skipped or scope absent this run)` and stays green. That is the right default
THERE and stays unchanged: the tester is shared with the satellite repos, which
stage a SUBSET of their tree, so "listed but absent" is genuinely unknowable for
them and failing it would break them.

It is not unknowable here. `stage-samples-gate.sh` copies all eight packages and
`stage-doc-gate.sh` copies the whole Doc tree, unconditionally — so in THIS repo
"absent" means retired, and it can be decided statically off the files.

**`GateAllowEntrySubjectGuard`** does that: every entry in both allow files must
name a subject the repo still ships — a type-level check (`compile`/`render`/
`tests`) must resolve to a node file whose content is a `NodeTypeDefinition`, a
package-level check (`install`/`idempotence`) to a package directory, and the
package must be one the lane's staging script actually stages (parsed from the
script, so the two cannot drift). It complements the gate rather than duplicating
it: stale-detection catches "fixed", this catches "gone".

Proven non-vacuous, not asserted to be: with the six lines restored the guard
fails naming all six and saying what each became —

    .github/samples-gate.allow:1 'FutuRe/AmericasIns/LineOfBusiness compile'
      — samples/Graph/Data/FutuRe/AmericasIns/LineOfBusiness.json is not a
        NodeType any more (nodeType: Markdown)

and the second test pins the resolver from both sides (a live NodeType resolves
AS a NodeType; the six retired files resolve and are rejected; a fabricated path
resolves to nothing; the Doc lane's `Doc/` prefix really addresses the tree), so
it cannot degrade into a check that answers "found" for everything.

The two `PensionFund` entries stay: both are separately diagnosed debt this issue
does not own, and both still name live subjects.

No What's New entry — CI-internal, no user-visible effect.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 27, 2026 06:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR keeps the samples content gate’s “known debt” allowlist accurate by removing entries that refer to NodeTypes that have been retired, and adds a unit-test guard to ensure allowlist entries always point at subjects that this repo still ships (so “gone” debt can’t silently persist as “unverifiable”).

Changes:

  • Added GateAllowEntrySubjectGuard tests to validate that each allowlist entry resolves to an existing, correctly-typed subject within the staged trees.
  • Removed six obsolete compile allowlist entries for retired FutuRe/*/{LineOfBusiness,TransactionMapping} NodeTypes from .github/samples-gate.allow.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
test/MeshWeaver.Graph.Test/GateAllowEntrySubjectGuard.cs Adds the guard tests that resolve allowlist scopes to actual shipped node files/directories and fail on retired/absent subjects.
.github/samples-gate.allow Removes six allow entries that referred to NodeTypes that no longer exist as NodeTypes.
Suppressed comments (1)

test/MeshWeaver.Graph.Test/GateAllowEntrySubjectGuard.cs:55

  • Static collections are forbidden across the repo (AGENTS.md “No static collections — ever”, and enforced by NoStaticCollectionsTest). This static HashSet will be flagged by the architecture guard; make it an instance field to avoid process-wide state.
    private static readonly IReadOnlySet<string> PackageLevelChecks =
        new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "install", "idempotence" };

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copilot flagged the `static readonly` sets against AGENTS.md's "No static
collections". They are the sanctioned shape — immutable, write-once reserved-word
lookups, the same shape `GateAllowlist.Checks` already ships — and
`NoStaticCollectionsTest` would not have fired either (it reflects over
`MeshWeaver.*.dll` in its OWN bin, which never contains another test assembly, and
matches on the FIELD type, which was `IReadOnlySet<>`).

But the collections policy also says `HashSet<T>` → `ImmutableHashSet<T>`, and a
`new HashSet<…>` initializer behind a read-only interface is exactly the shape a
reader has to reason about rather than see. Making the type immutable removes the
question instead of answering it, and costs nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

994 tests   990 ✅  16m 14s ⏱️
  9 suites    4 💤
  9 files      0 ❌

Results for commit 3f3b0af.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

4 482 tests   4 376 ✅  12m 18s ⏱️
    9 suites    106 💤
    9 files        0 ❌

Results for commit 3f3b0af.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

1 480 tests   1 480 ✅  6m 50s ⏱️
    8 suites      0 💤
    8 files        0 ❌

Results for commit 3f3b0af.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

   10 files     10 suites   7m 59s ⏱️
2 399 tests 2 397 ✅ 2 💤 0 ❌
2 400 runs  2 398 ✅ 2 💤 0 ❌

Results for commit 3f3b0af.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

959 tests   959 ✅  6m 23s ⏱️
  8 suites    0 💤
  8 files      0 ❌

Results for commit 3f3b0af.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

    8 files      8 suites   7m 34s ⏱️
1 091 tests   899 ✅ 192 💤 0 ❌
1 684 runs  1 492 ✅ 192 💤 0 ❌

Results for commit 3f3b0af.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results

    52 files      52 suites   57m 20s ⏱️
11 403 tests 11 099 ✅ 304 💤 0 ❌
11 999 runs  11 695 ✅ 304 💤 0 ❌

Results for commit 3f3b0af.

@rbuergi
rbuergi merged commit b6ecc99 into main Aug 27, 2026
23 checks passed
@rbuergi
rbuergi deleted the fix/1786-samples-gate-dead-entries branch August 28, 2026 08:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants