⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.
Context
checkContentLaneDeliverable (src/review/content-lane/registry-logic.ts:919-936) is the
deterministic "did this PR actually deliver the content file its linked issue names?" check — the guard
against a test-only PR closing a content issue via a bare Closes #N. It compares two things against
the same predicate:
const matchesSpec = (candidate: string): boolean =>
spec.entryFilePattern.test(candidate) || (spec.providerFilePattern?.test(candidate) ?? false);
const mentionedPath = extractPathTokens(issueText).find(matchesSpec); // :929 RAW token
…
const delivered = changedFiles.some((file) => matchesSpec(canonicalize(file))); // :932 canonicalized
entryFilePattern/providerFilePattern are compiled by globToRegExp
(packages/loopover-engine/src/signals/change-guardrail.ts:82-103), which canonicalizes the glob
first (canonicalize lowercases, packages/loopover-engine/src/signals/change-guardrail.ts:11-13) and
emits new RegExp("^…$") with no i flag. So the compiled pattern only ever matches lowercase
input.
Result: an issue body that writes the path with any capitalization — Registry/subnets/foo.json,
registry/Subnets/Foo.json — produces no mentionedPath. With no issueTitleImpliesEntryPattern
configured (or a title that doesn't match it), checkContentLaneDeliverable returns
{ verdict: "not-applicable" }, and the deliverable gate silently does not run for that issue —
the exact "test-only PR closes a content issue without ever delivering the content" gap the function's
own header (src/review/content-lane/registry-logic.ts:875-882) says it exists to close.
classifyRegistryPrScope in the same file already documents why this matters
(src/review/content-lane/registry-logic.ts:778-781): "globToRegExp compiles the spec patterns against
a CANONICALIZED path … so match on canonicalize(f), or an uppercase / ./-prefixed / backslash-separated
changed path silently fails to classify as a registry submission." The issue-body side never got that
treatment.
Requirements
checkContentLaneDeliverable must apply canonicalize to each token from extractPathTokens before
testing it with matchesSpec, exactly as it already does for changedFiles.
mentionedPath reported in the "missing" verdict must remain the original, non-canonicalized
token as written in the issue body — it is rendered into the public PR comment and must match what
the contributor and maintainer can see in the issue.
- Behaviour for an already-lowercase path token must be byte-identical to today.
- No change to
extractPathTokens, globToRegExp, canonicalize, or the issueTitleImpliesEntryPattern
fallback.
⚠️ Required pattern: mirror classifyRegistryPrScope's matchesPattern helper
(src/review/content-lane/registry-logic.ts:782), which canonicalizes the candidate at the point of
test while keeping the original string for anything user-visible. What does NOT satisfy this issue:
adding an i flag to the compiled globs (that changes guardrail matching repo-wide, which is a
separate, load-bearing behaviour); lowercasing inside extractPathTokens (that would also corrupt the
reported mentionedPath); or canonicalizing the whole issueText before tokenizing.
Deliverables
All Deliverables above are required in a single PR. A PR that satisfies only some of them — for
example canonicalizing the token (Deliverable 1) but also lowercasing the reported mentionedPath,
breaking the public-comment text — does not resolve this issue.
Test Coverage Requirements
This repo enforces 99%+ Codecov patch coverage, branch-counted, and vitest.config.ts's
coverage.include covers src/**/*.ts — this file is measured. Both arms of the
find(matchesSpec) outcome (a token that matches, and one that does not) need a test, as do both arms
of the mentionedPath ?? … fallback in the missing return.
Expected Outcome
The content-lane deliverable gate fires on an issue that names its target file with any capitalization,
instead of silently reporting not-applicable and letting a PR close a content issue without
delivering the content. The mentionedPath shown in the public comment still quotes the issue verbatim.
Links & Resources
src/review/content-lane/registry-logic.ts:875-936 (the check), :777-800 (classifyRegistryPrScope, the pattern to mirror)
packages/loopover-engine/src/signals/change-guardrail.ts:11-13, :82-103 (canonicalize / globToRegExp)
test/unit/content-lane-registry-logic.test.ts
Context
checkContentLaneDeliverable(src/review/content-lane/registry-logic.ts:919-936) is thedeterministic "did this PR actually deliver the content file its linked issue names?" check — the guard
against a test-only PR closing a content issue via a bare
Closes #N. It compares two things againstthe same predicate:
entryFilePattern/providerFilePatternare compiled byglobToRegExp(
packages/loopover-engine/src/signals/change-guardrail.ts:82-103), which canonicalizes the globfirst (
canonicalizelowercases,packages/loopover-engine/src/signals/change-guardrail.ts:11-13) andemits
new RegExp("^…$")with noiflag. So the compiled pattern only ever matches lowercaseinput.
Result: an issue body that writes the path with any capitalization —
Registry/subnets/foo.json,registry/Subnets/Foo.json— produces nomentionedPath. With noissueTitleImpliesEntryPatternconfigured (or a title that doesn't match it),
checkContentLaneDeliverablereturns{ verdict: "not-applicable" }, and the deliverable gate silently does not run for that issue —the exact "test-only PR closes a content issue without ever delivering the content" gap the function's
own header (
src/review/content-lane/registry-logic.ts:875-882) says it exists to close.classifyRegistryPrScopein the same file already documents why this matters(
src/review/content-lane/registry-logic.ts:778-781): "globToRegExp compiles the spec patterns againsta CANONICALIZED path … so match on canonicalize(f), or an uppercase /
./-prefixed / backslash-separatedchanged path silently fails to classify as a registry submission." The issue-body side never got that
treatment.
Requirements
checkContentLaneDeliverablemust applycanonicalizeto each token fromextractPathTokensbeforetesting it with
matchesSpec, exactly as it already does forchangedFiles.mentionedPathreported in the"missing"verdict must remain the original, non-canonicalizedtoken as written in the issue body — it is rendered into the public PR comment and must match what
the contributor and maintainer can see in the issue.
extractPathTokens,globToRegExp,canonicalize, or theissueTitleImpliesEntryPatternfallback.
Deliverables
checkContentLaneDeliverableinsrc/review/content-lane/registry-logic.tsreturns{ verdict: "missing", mentionedPath: "Registry/Subnets/Foo.json" }for an issue body namingRegistry/Subnets/Foo.jsonagainst a PR that changed no matching file — asserted by a new namedcase in
test/unit/content-lane-registry-logic.test.ts."delivered"verdict for that mixed-case issue body when the PR DOESchange
registry/subnets/foo.json.deliveredandmissing) isunchanged.
not-applicable(the change does not over-broaden the match).All Deliverables above are required in a single PR. A PR that satisfies only some of them — for
example canonicalizing the token (Deliverable 1) but also lowercasing the reported
mentionedPath,breaking the public-comment text — does not resolve this issue.
Test Coverage Requirements
This repo enforces 99%+ Codecov patch coverage, branch-counted, and
vitest.config.ts'scoverage.includecoverssrc/**/*.ts— this file is measured. Both arms of thefind(matchesSpec)outcome (a token that matches, and one that does not) need a test, as do both armsof the
mentionedPath ?? …fallback in themissingreturn.Expected Outcome
The content-lane deliverable gate fires on an issue that names its target file with any capitalization,
instead of silently reporting
not-applicableand letting a PR close a content issue withoutdelivering the content. The
mentionedPathshown in the public comment still quotes the issue verbatim.Links & Resources
src/review/content-lane/registry-logic.ts:875-936(the check),:777-800(classifyRegistryPrScope, the pattern to mirror)packages/loopover-engine/src/signals/change-guardrail.ts:11-13,:82-103(canonicalize/globToRegExp)test/unit/content-lane-registry-logic.test.ts