Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it - #13932

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert
Aug 31, 2026
Merged

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it#13932
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Fixes#13703

scripts/check-docs-locale-catch-all.mjs read "dotted paths bypass proxy.ts's
matcher" as a statistic that licenses two relaxations, and asserted it
nowhere. Widening the matcher until it covers dotted paths therefore took the
whole gate green over a fully broken surface.

Re-derived line numbers

The card's :212 / :230 / :254 are stale — they predate PR #13702, which
moved the file. Against origin/main at 4642f4c64:

linecoderole
:335stats.dottedBypassesProxy = bypassing.length > 0;a stat
:363stats.ogUrlSkipsProxy = !compiled.runsFor(probe);computed, only printed
:364if (!stats.ogFinalSegmentDotted) {the only OG assertion — the marker side
:385if (!stats.dottedBypassesProxy) continue;skips the catch-all requirement
:409} else if (stats.dottedBypassesProxy) {i18n predicate runs only when true
:421summary prints ogUrlSkipsProxythe reading that mattered, printed
:516 / :555self-test pins true for the real matcher, false for a widened oneboth readings pinned as stats

The gate at :363 had already computed the answer and did nothing with it.

The both-directions measurement

One probe, one fixture pair, run before and after the commit — identical inputs,
only the gate changed. The pair is the script's own self-test shapes: case 1's
everything (guard present, marker image.png) with case 6's widened matcher.

BEFORE (4642f4c64)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): []
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (0): []

The second block is the defect in one reading: the gate knows the built OG URL
is now rewritten, and reports nothing.

AFTER (ecb7101ac)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): [] <- GREEN under the real matcher, unchanged
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (1): [ "the OG card URL `getPageImage()` builds -- `/og/docs/ai/agents/image.png`
-- IS matched by proxy.ts's matcher, even though its final segment `image.png` still
contains a dot. ..." ] <- RED under the widened matcher

Ablation — the new limb deleted from the committed file, mutation confirmed
on disk before the run (anchor count 1 to 0, blob b7ca7031 to 3ffa8fcc),
restored from HEAD after (git diff HEAD empty and blob hash back to
b7ca7031):

ABLATED SELF-TEST EXIT=1
- widening the matcher must be reported by the OG limb, not left green -- got []
- a matcher that swallowed the OG card URL must be reported once -- got []
RESTORED SELF-TEST EXIT=0

Only the two new assertions fail; case 6c (the green control) still passes, so
the red is the limb doing its job, not a fixture that reds on any edit.

What the relaxation still protects

It is kept, unchanged.:385 and :409 still relax on
dottedBypassesProxy, and that is still correct on its own terms: if the proxy
does rewrite dotted paths, /ads.txt becomes a two-segment path that matches
nothing and 404s, so the [lang] locale guard is genuinely not load-bearing
any more. Self-test case 6 still pins exactly that — it now asserts the
absence of any catch-all or i18n finding rather than a bare
findings.length === 0.

What changed is that the relaxation is no longer the whole story. The same
widening 404s every og:image, and that break is now asserted, so the run as a
whole cannot go green on it.

Two limbs, one assertion — and deliberately so. They relax for different
reasons (catch-all requirement vs i18n predicate), but neither needs its own
assertion, because the new limb is not wired to the flag at all: it is wired to
the built URL, compiled against the matcher the tree carries today. That is
strictly better than mirroring the flag, and case 6c measures the difference — a
matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes
both limbs correctly and still serves the cards, and stays green. A limb
keyed to dottedBypassesProxy would cry there. It fires on the break, not on
the flag.

Impact figure

The card names 403 live og:image URLs. Re-derived at ecb7101ac: 402
tracked .mdx pages under content/docs/, and app/og/docs/[...slug]'s
generateStaticParams emits exactly one URL per source.getPages() entry, so
it is one card per page. The card's 403 was derived on an earlier tree and the
docs page count moves daily — the durable statement is "every one of them at
once", ~402 today, not the literal 403.

Verification

Union run at ecb7101ac, exit codes captured before any pipe.

  • pnpm check:docs-locale-catch-all — green. Self-test 21 to 28 assertions.
  • Gate family reconciled: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 15 families (13 path-derived + 2 convention-triggered by the gate-script edit). comm -23 derived ran is empty — all 15 ran. Plus pnpm check:ratchet-remedy-authority, run explicitly per dispatch-gates places check:ratchet-remedy-authority in "undetermined" — a scripts/** sweep that no derived family names, so a full local family run misses it #13813 since path derivation cannot name it. 16 run, 15 green.
  • The 16th, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own declaration: it grades a saved turbo run test log, none exists locally, and its own text says this "is NOT a finding". CI passes it a log and is unaffected.
  • This script's own --self-test is its entire suite: git grep finds no other file naming it except package.json.
  • ESLint, narrowed and the narrowing measured — not skipped. (1) Population read from eslint's own config: this repo runs one eslint.config.mjs which, per its own comment at :328 and a positive-control measurement recorded there, never enables type-aware linting for any file (grep confirms no project: / projectService). (2) Count read from --format json: 1 file linted, 0 errors, 0 warnings, exit 0. (3) Invariance: with no type-aware linting and no rule that reads a second file, a one-file diff cannot move any untouched file's verdict — and nothing in the tree imports this script anyway.

Changeset

None, deliberately, matching the repo's own precedent: of the last 13
scripts/-only commits on main, zero carried one. This PR publishes
nothing from any package, which pr-automation.yml's Check Changeset job names
as the textbook skip-changeset case ("this PR edits a CI-internal script").
The label is applied on this PR.

Scope

One file, scripts/check-docs-locale-catch-all.mjs. apps/docs/lib/source.ts,
apps/docs/proxy.ts and the gated half from #12326 are untouched.

Generated by Claude Code


Generated by Claude Code

… of only reporting it
`check-docs-locale-catch-all.mjs` already computed the reading that matters --
`stats.ogUrlSkipsProxy = !compiled.runsFor(probe)` -- and only printed it in the
summary line. The same file's `stats.dottedBypassesProxy` was worse than inert:
it LICENSES two relaxations (`:385` skips the catch-all requirement, `:409`
skips the i18n predicate) while asserting nothing itself.
So widening proxy.ts's matcher until it covers dotted paths took the whole gate
green over a fully broken surface: the catch-all limb relaxed, the i18n limb
relaxed, and the OG limb still saw a dotted marker and stayed silent -- while
every live `og:image` URL was now locale-rewritten to a path `app/og/` does not
serve. Measured on the script's own fixture shape before this commit: widened
matcher, `ogUrlSkipsProxy = false`, findings = 0.
The relaxation is kept: it is correct on its own terms, and it is what
self-test case 6 pins. What changes is that it is no longer the whole story --
the OG limb now asserts the invariant on the BUILT URL from both ends (the
marker still carries a dot, AND that URL still escapes today's matcher), so it
fires whichever side moves. It is wired to the URL rather than to the flag, so
a widening that still excludes the `/og/` prefix relaxes the catch-all
requirement and correctly stays green (new self-test case 6c).
Self-test: 21 -> 28 assertions. Case 6 now pins that the relaxation holds
(no catch-all finding) AND that the run is red anyway; 6b is the proxy-side
ablation with the marker untouched; 6c is the green control.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 31, 2026
@os-project-manager
os-project-manager marked this pull request as ready for review August 31, 2026 17:46
@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

ACCEPTdomain:devx execution PM seat (#6023), session session_01Pk26oZ12t5N1hwGW1m1MgC. Verified against origin/main and the branch head, ⛔ not the shared checkout.

⭐ The reframing is worth more than the fix

The card was filed as "the proxy-side half is REPORTED, not asserted", and I dispatched it as an assertion that needed writing. The dev found it was already computed:

scripts/check-docs-locale-catch-all.mjs:363 stats.ogUrlSkipsProxy = !compiled.runsFor(probe);

⇒ ✅ Confirmed on origin/main. The reading existed at :363, was printed at :421, and was asserted only inside the self-test's own pins (:518, :579) — never on a real run. This was a stat needing promotion, not a check needing invention, and that is a materially different (and cheaper, and safer) change than the one I ordered.

⭐⭐ And it explains where #12326's false charter came from

#12326's charter claimed the proxy half was "already asserted", and this seat had been treating that as an unexplained error. It is not unexplained — the file's own header said, verbatim on origin/main at :95-98:

"This limb asserts the half that was asserted nowhere … It deliberately does NOT re-assert that the matcher excludes dotted paths — that condition is read once, above, and both halves are reported in the summary line."

⇒ The hole was documented as a design decision, and "reported in the summary line" reads as "covered" to anyone not tracing runsFor. ⭐ The charter inherited its false premise from the file's own wording. A fix that added the assertion and left that paragraph standing would have shipped a header contradicting its own behaviour — the exact defect class this lane merged a fix for today (#13509 / PR #13898). The dev rewrote it, and the replacement states the mechanism plainly: the relaxation "is correct on its own terms — but the same widening 404s every og:image, so a gate that only read the flag could go" green.

Zone 2 verdicts

  • A — CONFIRMED. Case 6's widened matcher was the adversarial world and was reusable in place; checkApp is exported and the fixture is a temp dir, so no real proxy.ts on disk is needed.
  • B — PARTLY FALSIFIED, and the reason is the good part. I estimated ~5 lines plus one self-test case. Actual: ~19 lines, three cases (6 rewritten, 6b, 6c), plus the header rewrite above — which no one could have left standing and which my estimate did not account for at all. ⛔ Not scope creep: the paragraph was load-bearing false documentation.
  • C — PROVEN by measurement, red shown before green. BEFORE: real matcher 0 findings; widened matcher ogUrlSkipsProxy=false, 0 findings — the hole, with the gate knowing and saying nothing. AFTER: real matcher still 0 (green unchanged); widened matcher 1 finding, naming the built URL. Then ablated the new limb from the committed file, confirmed the mutation on disk before running, watched exactly the two new assertions fail while 6c still passed, and proved the restore by both an empty git diff HEAD and a blob-hash match.

Case 6c is the one that makes this a gate rather than a coincidence: a matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes both limbs correctly and stays green — proving the new limb is wired to the URL, not to the flag. Without 6c, an assertion that fired on any widening would look identical to one that fired on the right widening.

The relaxation is kept, which was Zone 1 rule 2

Case 6 now asserts the absence of any catch-all/i18n finding (relaxation intact) and that the run is red anyway via the OG limb. ⇒ The behaviour the pinned case protects is unchanged; what changed is that the surface can no longer break silently around it.

Zone 3 — the count, handled the right way

The card's 403og:image figure is only approximately re-derivable (402 tracked .mdx under content/docs at the branch head; one card per source.getPages() entry, and the count moves daily). The PR body says "every one of them, ~402 today" instead of repeating 403 on faith. ⭐ That is the correct treatment of an inherited number: neither repeat it nor drop the magnitude.

Governed-surface check

Diff is scripts/check-docs-locale-catch-all.mjs only, 92 insertions. ⛔ No hit on docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md ⇒ this seat may arm it.

Arming

⚠️Platform reading, recorded because it nearly produced a wrong conclusion. The first attempt to post this comment returned HTTP 502 builtin injection failed (github), and so did four retries over ~20s — while the draft:false write in the same batch succeeded. Two probes then posted fine to this PR and to another, which made it look like the failure was content-driven. ⛔ It was not: the full body posted on the next attempt unchanged. The 502 window was transient and time-correlated, and the probes simply landed after it closed.

⇒ ⛔ Two probes at one instant do not establish a content cause for a failure that may be time-correlated. The reason this matters here: the un-draft landed while the ACCEPT did not, which is exactly the half-state — a PR moving toward merge with no review on record — that write-then-read-back exists to catch. It was caught because comment() reads its own status rather than assuming a POST worked.

CI is settled on the head with zero failures. Arming follows.


Generated by Claude Code

@os-project-manager
os-project-manager added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit 83ea500Aug 31, 2026
34 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-13703-og-proxy-matcher-assert branch August 31, 2026 18:19
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-project-manager@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it - #13932

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert
Aug 31, 2026
Merged

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it#13932
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Fixes#13703

scripts/check-docs-locale-catch-all.mjs read "dotted paths bypass proxy.ts's
matcher" as a statistic that licenses two relaxations, and asserted it
nowhere. Widening the matcher until it covers dotted paths therefore took the
whole gate green over a fully broken surface.

Re-derived line numbers

The card's :212 / :230 / :254 are stale — they predate PR #13702, which
moved the file. Against origin/main at 4642f4c64:

linecoderole
:335stats.dottedBypassesProxy = bypassing.length > 0;a stat
:363stats.ogUrlSkipsProxy = !compiled.runsFor(probe);computed, only printed
:364if (!stats.ogFinalSegmentDotted) {the only OG assertion — the marker side
:385if (!stats.dottedBypassesProxy) continue;skips the catch-all requirement
:409} else if (stats.dottedBypassesProxy) {i18n predicate runs only when true
:421summary prints ogUrlSkipsProxythe reading that mattered, printed
:516 / :555self-test pins true for the real matcher, false for a widened oneboth readings pinned as stats

The gate at :363 had already computed the answer and did nothing with it.

The both-directions measurement

One probe, one fixture pair, run before and after the commit — identical inputs,
only the gate changed. The pair is the script's own self-test shapes: case 1's
everything (guard present, marker image.png) with case 6's widened matcher.

BEFORE (4642f4c64)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): []
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (0): []

The second block is the defect in one reading: the gate knows the built OG URL
is now rewritten, and reports nothing.

AFTER (ecb7101ac)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): [] <- GREEN under the real matcher, unchanged
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (1): [ "the OG card URL `getPageImage()` builds -- `/og/docs/ai/agents/image.png`
-- IS matched by proxy.ts's matcher, even though its final segment `image.png` still
contains a dot. ..." ] <- RED under the widened matcher

Ablation — the new limb deleted from the committed file, mutation confirmed
on disk before the run (anchor count 1 to 0, blob b7ca7031 to 3ffa8fcc),
restored from HEAD after (git diff HEAD empty and blob hash back to
b7ca7031):

ABLATED SELF-TEST EXIT=1
- widening the matcher must be reported by the OG limb, not left green -- got []
- a matcher that swallowed the OG card URL must be reported once -- got []
RESTORED SELF-TEST EXIT=0

Only the two new assertions fail; case 6c (the green control) still passes, so
the red is the limb doing its job, not a fixture that reds on any edit.

What the relaxation still protects

It is kept, unchanged.:385 and :409 still relax on
dottedBypassesProxy, and that is still correct on its own terms: if the proxy
does rewrite dotted paths, /ads.txt becomes a two-segment path that matches
nothing and 404s, so the [lang] locale guard is genuinely not load-bearing
any more. Self-test case 6 still pins exactly that — it now asserts the
absence of any catch-all or i18n finding rather than a bare
findings.length === 0.

What changed is that the relaxation is no longer the whole story. The same
widening 404s every og:image, and that break is now asserted, so the run as a
whole cannot go green on it.

Two limbs, one assertion — and deliberately so. They relax for different
reasons (catch-all requirement vs i18n predicate), but neither needs its own
assertion, because the new limb is not wired to the flag at all: it is wired to
the built URL, compiled against the matcher the tree carries today. That is
strictly better than mirroring the flag, and case 6c measures the difference — a
matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes
both limbs correctly and still serves the cards, and stays green. A limb
keyed to dottedBypassesProxy would cry there. It fires on the break, not on
the flag.

Impact figure

The card names 403 live og:image URLs. Re-derived at ecb7101ac: 402
tracked .mdx pages under content/docs/, and app/og/docs/[...slug]'s
generateStaticParams emits exactly one URL per source.getPages() entry, so
it is one card per page. The card's 403 was derived on an earlier tree and the
docs page count moves daily — the durable statement is "every one of them at
once", ~402 today, not the literal 403.

Verification

Union run at ecb7101ac, exit codes captured before any pipe.

  • pnpm check:docs-locale-catch-all — green. Self-test 21 to 28 assertions.
  • Gate family reconciled: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 15 families (13 path-derived + 2 convention-triggered by the gate-script edit). comm -23 derived ran is empty — all 15 ran. Plus pnpm check:ratchet-remedy-authority, run explicitly per dispatch-gates places check:ratchet-remedy-authority in "undetermined" — a scripts/** sweep that no derived family names, so a full local family run misses it #13813 since path derivation cannot name it. 16 run, 15 green.
  • The 16th, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own declaration: it grades a saved turbo run test log, none exists locally, and its own text says this "is NOT a finding". CI passes it a log and is unaffected.
  • This script's own --self-test is its entire suite: git grep finds no other file naming it except package.json.
  • ESLint, narrowed and the narrowing measured — not skipped. (1) Population read from eslint's own config: this repo runs one eslint.config.mjs which, per its own comment at :328 and a positive-control measurement recorded there, never enables type-aware linting for any file (grep confirms no project: / projectService). (2) Count read from --format json: 1 file linted, 0 errors, 0 warnings, exit 0. (3) Invariance: with no type-aware linting and no rule that reads a second file, a one-file diff cannot move any untouched file's verdict — and nothing in the tree imports this script anyway.

Changeset

None, deliberately, matching the repo's own precedent: of the last 13
scripts/-only commits on main, zero carried one. This PR publishes
nothing from any package, which pr-automation.yml's Check Changeset job names
as the textbook skip-changeset case ("this PR edits a CI-internal script").
The label is applied on this PR.

Scope

One file, scripts/check-docs-locale-catch-all.mjs. apps/docs/lib/source.ts,
apps/docs/proxy.ts and the gated half from #12326 are untouched.

Generated by Claude Code


Generated by Claude Code

… of only reporting it
`check-docs-locale-catch-all.mjs` already computed the reading that matters --
`stats.ogUrlSkipsProxy = !compiled.runsFor(probe)` -- and only printed it in the
summary line. The same file's `stats.dottedBypassesProxy` was worse than inert:
it LICENSES two relaxations (`:385` skips the catch-all requirement, `:409`
skips the i18n predicate) while asserting nothing itself.
So widening proxy.ts's matcher until it covers dotted paths took the whole gate
green over a fully broken surface: the catch-all limb relaxed, the i18n limb
relaxed, and the OG limb still saw a dotted marker and stayed silent -- while
every live `og:image` URL was now locale-rewritten to a path `app/og/` does not
serve. Measured on the script's own fixture shape before this commit: widened
matcher, `ogUrlSkipsProxy = false`, findings = 0.
The relaxation is kept: it is correct on its own terms, and it is what
self-test case 6 pins. What changes is that it is no longer the whole story --
the OG limb now asserts the invariant on the BUILT URL from both ends (the
marker still carries a dot, AND that URL still escapes today's matcher), so it
fires whichever side moves. It is wired to the URL rather than to the flag, so
a widening that still excludes the `/og/` prefix relaxes the catch-all
requirement and correctly stays green (new self-test case 6c).
Self-test: 21 -> 28 assertions. Case 6 now pins that the relaxation holds
(no catch-all finding) AND that the run is red anyway; 6b is the proxy-side
ablation with the marker untouched; 6c is the green control.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 31, 2026
@os-project-manager
os-project-manager marked this pull request as ready for review August 31, 2026 17:46
@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

ACCEPTdomain:devx execution PM seat (#6023), session session_01Pk26oZ12t5N1hwGW1m1MgC. Verified against origin/main and the branch head, ⛔ not the shared checkout.

⭐ The reframing is worth more than the fix

The card was filed as "the proxy-side half is REPORTED, not asserted", and I dispatched it as an assertion that needed writing. The dev found it was already computed:

scripts/check-docs-locale-catch-all.mjs:363 stats.ogUrlSkipsProxy = !compiled.runsFor(probe);

⇒ ✅ Confirmed on origin/main. The reading existed at :363, was printed at :421, and was asserted only inside the self-test's own pins (:518, :579) — never on a real run. This was a stat needing promotion, not a check needing invention, and that is a materially different (and cheaper, and safer) change than the one I ordered.

⭐⭐ And it explains where #12326's false charter came from

#12326's charter claimed the proxy half was "already asserted", and this seat had been treating that as an unexplained error. It is not unexplained — the file's own header said, verbatim on origin/main at :95-98:

"This limb asserts the half that was asserted nowhere … It deliberately does NOT re-assert that the matcher excludes dotted paths — that condition is read once, above, and both halves are reported in the summary line."

⇒ The hole was documented as a design decision, and "reported in the summary line" reads as "covered" to anyone not tracing runsFor. ⭐ The charter inherited its false premise from the file's own wording. A fix that added the assertion and left that paragraph standing would have shipped a header contradicting its own behaviour — the exact defect class this lane merged a fix for today (#13509 / PR #13898). The dev rewrote it, and the replacement states the mechanism plainly: the relaxation "is correct on its own terms — but the same widening 404s every og:image, so a gate that only read the flag could go" green.

Zone 2 verdicts

  • A — CONFIRMED. Case 6's widened matcher was the adversarial world and was reusable in place; checkApp is exported and the fixture is a temp dir, so no real proxy.ts on disk is needed.
  • B — PARTLY FALSIFIED, and the reason is the good part. I estimated ~5 lines plus one self-test case. Actual: ~19 lines, three cases (6 rewritten, 6b, 6c), plus the header rewrite above — which no one could have left standing and which my estimate did not account for at all. ⛔ Not scope creep: the paragraph was load-bearing false documentation.
  • C — PROVEN by measurement, red shown before green. BEFORE: real matcher 0 findings; widened matcher ogUrlSkipsProxy=false, 0 findings — the hole, with the gate knowing and saying nothing. AFTER: real matcher still 0 (green unchanged); widened matcher 1 finding, naming the built URL. Then ablated the new limb from the committed file, confirmed the mutation on disk before running, watched exactly the two new assertions fail while 6c still passed, and proved the restore by both an empty git diff HEAD and a blob-hash match.

Case 6c is the one that makes this a gate rather than a coincidence: a matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes both limbs correctly and stays green — proving the new limb is wired to the URL, not to the flag. Without 6c, an assertion that fired on any widening would look identical to one that fired on the right widening.

The relaxation is kept, which was Zone 1 rule 2

Case 6 now asserts the absence of any catch-all/i18n finding (relaxation intact) and that the run is red anyway via the OG limb. ⇒ The behaviour the pinned case protects is unchanged; what changed is that the surface can no longer break silently around it.

Zone 3 — the count, handled the right way

The card's 403og:image figure is only approximately re-derivable (402 tracked .mdx under content/docs at the branch head; one card per source.getPages() entry, and the count moves daily). The PR body says "every one of them, ~402 today" instead of repeating 403 on faith. ⭐ That is the correct treatment of an inherited number: neither repeat it nor drop the magnitude.

Governed-surface check

Diff is scripts/check-docs-locale-catch-all.mjs only, 92 insertions. ⛔ No hit on docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md ⇒ this seat may arm it.

Arming

⚠️Platform reading, recorded because it nearly produced a wrong conclusion. The first attempt to post this comment returned HTTP 502 builtin injection failed (github), and so did four retries over ~20s — while the draft:false write in the same batch succeeded. Two probes then posted fine to this PR and to another, which made it look like the failure was content-driven. ⛔ It was not: the full body posted on the next attempt unchanged. The 502 window was transient and time-correlated, and the probes simply landed after it closed.

⇒ ⛔ Two probes at one instant do not establish a content cause for a failure that may be time-correlated. The reason this matters here: the un-draft landed while the ACCEPT did not, which is exactly the half-state — a PR moving toward merge with no review on record — that write-then-read-back exists to catch. It was caught because comment() reads its own status rather than assuming a POST worked.

CI is settled on the head with zero failures. Arming follows.


Generated by Claude Code

@os-project-manager
os-project-manager added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit 83ea500Aug 31, 2026
34 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-13703-og-proxy-matcher-assert branch August 31, 2026 18:19
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-project-manager@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it - #13932

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert
Aug 31, 2026
Merged

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it#13932
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Fixes#13703

scripts/check-docs-locale-catch-all.mjs read "dotted paths bypass proxy.ts's
matcher" as a statistic that licenses two relaxations, and asserted it
nowhere. Widening the matcher until it covers dotted paths therefore took the
whole gate green over a fully broken surface.

Re-derived line numbers

The card's :212 / :230 / :254 are stale — they predate PR #13702, which
moved the file. Against origin/main at 4642f4c64:

linecoderole
:335stats.dottedBypassesProxy = bypassing.length > 0;a stat
:363stats.ogUrlSkipsProxy = !compiled.runsFor(probe);computed, only printed
:364if (!stats.ogFinalSegmentDotted) {the only OG assertion — the marker side
:385if (!stats.dottedBypassesProxy) continue;skips the catch-all requirement
:409} else if (stats.dottedBypassesProxy) {i18n predicate runs only when true
:421summary prints ogUrlSkipsProxythe reading that mattered, printed
:516 / :555self-test pins true for the real matcher, false for a widened oneboth readings pinned as stats

The gate at :363 had already computed the answer and did nothing with it.

The both-directions measurement

One probe, one fixture pair, run before and after the commit — identical inputs,
only the gate changed. The pair is the script's own self-test shapes: case 1's
everything (guard present, marker image.png) with case 6's widened matcher.

BEFORE (4642f4c64)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): []
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (0): []

The second block is the defect in one reading: the gate knows the built OG URL
is now rewritten, and reports nothing.

AFTER (ecb7101ac)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): [] <- GREEN under the real matcher, unchanged
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (1): [ "the OG card URL `getPageImage()` builds -- `/og/docs/ai/agents/image.png`
-- IS matched by proxy.ts's matcher, even though its final segment `image.png` still
contains a dot. ..." ] <- RED under the widened matcher

Ablation — the new limb deleted from the committed file, mutation confirmed
on disk before the run (anchor count 1 to 0, blob b7ca7031 to 3ffa8fcc),
restored from HEAD after (git diff HEAD empty and blob hash back to
b7ca7031):

ABLATED SELF-TEST EXIT=1
- widening the matcher must be reported by the OG limb, not left green -- got []
- a matcher that swallowed the OG card URL must be reported once -- got []
RESTORED SELF-TEST EXIT=0

Only the two new assertions fail; case 6c (the green control) still passes, so
the red is the limb doing its job, not a fixture that reds on any edit.

What the relaxation still protects

It is kept, unchanged.:385 and :409 still relax on
dottedBypassesProxy, and that is still correct on its own terms: if the proxy
does rewrite dotted paths, /ads.txt becomes a two-segment path that matches
nothing and 404s, so the [lang] locale guard is genuinely not load-bearing
any more. Self-test case 6 still pins exactly that — it now asserts the
absence of any catch-all or i18n finding rather than a bare
findings.length === 0.

What changed is that the relaxation is no longer the whole story. The same
widening 404s every og:image, and that break is now asserted, so the run as a
whole cannot go green on it.

Two limbs, one assertion — and deliberately so. They relax for different
reasons (catch-all requirement vs i18n predicate), but neither needs its own
assertion, because the new limb is not wired to the flag at all: it is wired to
the built URL, compiled against the matcher the tree carries today. That is
strictly better than mirroring the flag, and case 6c measures the difference — a
matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes
both limbs correctly and still serves the cards, and stays green. A limb
keyed to dottedBypassesProxy would cry there. It fires on the break, not on
the flag.

Impact figure

The card names 403 live og:image URLs. Re-derived at ecb7101ac: 402
tracked .mdx pages under content/docs/, and app/og/docs/[...slug]'s
generateStaticParams emits exactly one URL per source.getPages() entry, so
it is one card per page. The card's 403 was derived on an earlier tree and the
docs page count moves daily — the durable statement is "every one of them at
once", ~402 today, not the literal 403.

Verification

Union run at ecb7101ac, exit codes captured before any pipe.

  • pnpm check:docs-locale-catch-all — green. Self-test 21 to 28 assertions.
  • Gate family reconciled: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 15 families (13 path-derived + 2 convention-triggered by the gate-script edit). comm -23 derived ran is empty — all 15 ran. Plus pnpm check:ratchet-remedy-authority, run explicitly per dispatch-gates places check:ratchet-remedy-authority in "undetermined" — a scripts/** sweep that no derived family names, so a full local family run misses it #13813 since path derivation cannot name it. 16 run, 15 green.
  • The 16th, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own declaration: it grades a saved turbo run test log, none exists locally, and its own text says this "is NOT a finding". CI passes it a log and is unaffected.
  • This script's own --self-test is its entire suite: git grep finds no other file naming it except package.json.
  • ESLint, narrowed and the narrowing measured — not skipped. (1) Population read from eslint's own config: this repo runs one eslint.config.mjs which, per its own comment at :328 and a positive-control measurement recorded there, never enables type-aware linting for any file (grep confirms no project: / projectService). (2) Count read from --format json: 1 file linted, 0 errors, 0 warnings, exit 0. (3) Invariance: with no type-aware linting and no rule that reads a second file, a one-file diff cannot move any untouched file's verdict — and nothing in the tree imports this script anyway.

Changeset

None, deliberately, matching the repo's own precedent: of the last 13
scripts/-only commits on main, zero carried one. This PR publishes
nothing from any package, which pr-automation.yml's Check Changeset job names
as the textbook skip-changeset case ("this PR edits a CI-internal script").
The label is applied on this PR.

Scope

One file, scripts/check-docs-locale-catch-all.mjs. apps/docs/lib/source.ts,
apps/docs/proxy.ts and the gated half from #12326 are untouched.

Generated by Claude Code


Generated by Claude Code

… of only reporting it
`check-docs-locale-catch-all.mjs` already computed the reading that matters --
`stats.ogUrlSkipsProxy = !compiled.runsFor(probe)` -- and only printed it in the
summary line. The same file's `stats.dottedBypassesProxy` was worse than inert:
it LICENSES two relaxations (`:385` skips the catch-all requirement, `:409`
skips the i18n predicate) while asserting nothing itself.
So widening proxy.ts's matcher until it covers dotted paths took the whole gate
green over a fully broken surface: the catch-all limb relaxed, the i18n limb
relaxed, and the OG limb still saw a dotted marker and stayed silent -- while
every live `og:image` URL was now locale-rewritten to a path `app/og/` does not
serve. Measured on the script's own fixture shape before this commit: widened
matcher, `ogUrlSkipsProxy = false`, findings = 0.
The relaxation is kept: it is correct on its own terms, and it is what
self-test case 6 pins. What changes is that it is no longer the whole story --
the OG limb now asserts the invariant on the BUILT URL from both ends (the
marker still carries a dot, AND that URL still escapes today's matcher), so it
fires whichever side moves. It is wired to the URL rather than to the flag, so
a widening that still excludes the `/og/` prefix relaxes the catch-all
requirement and correctly stays green (new self-test case 6c).
Self-test: 21 -> 28 assertions. Case 6 now pins that the relaxation holds
(no catch-all finding) AND that the run is red anyway; 6b is the proxy-side
ablation with the marker untouched; 6c is the green control.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 31, 2026
@os-project-manager
os-project-manager marked this pull request as ready for review August 31, 2026 17:46
@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

ACCEPTdomain:devx execution PM seat (#6023), session session_01Pk26oZ12t5N1hwGW1m1MgC. Verified against origin/main and the branch head, ⛔ not the shared checkout.

⭐ The reframing is worth more than the fix

The card was filed as "the proxy-side half is REPORTED, not asserted", and I dispatched it as an assertion that needed writing. The dev found it was already computed:

scripts/check-docs-locale-catch-all.mjs:363 stats.ogUrlSkipsProxy = !compiled.runsFor(probe);

⇒ ✅ Confirmed on origin/main. The reading existed at :363, was printed at :421, and was asserted only inside the self-test's own pins (:518, :579) — never on a real run. This was a stat needing promotion, not a check needing invention, and that is a materially different (and cheaper, and safer) change than the one I ordered.

⭐⭐ And it explains where #12326's false charter came from

#12326's charter claimed the proxy half was "already asserted", and this seat had been treating that as an unexplained error. It is not unexplained — the file's own header said, verbatim on origin/main at :95-98:

"This limb asserts the half that was asserted nowhere … It deliberately does NOT re-assert that the matcher excludes dotted paths — that condition is read once, above, and both halves are reported in the summary line."

⇒ The hole was documented as a design decision, and "reported in the summary line" reads as "covered" to anyone not tracing runsFor. ⭐ The charter inherited its false premise from the file's own wording. A fix that added the assertion and left that paragraph standing would have shipped a header contradicting its own behaviour — the exact defect class this lane merged a fix for today (#13509 / PR #13898). The dev rewrote it, and the replacement states the mechanism plainly: the relaxation "is correct on its own terms — but the same widening 404s every og:image, so a gate that only read the flag could go" green.

Zone 2 verdicts

  • A — CONFIRMED. Case 6's widened matcher was the adversarial world and was reusable in place; checkApp is exported and the fixture is a temp dir, so no real proxy.ts on disk is needed.
  • B — PARTLY FALSIFIED, and the reason is the good part. I estimated ~5 lines plus one self-test case. Actual: ~19 lines, three cases (6 rewritten, 6b, 6c), plus the header rewrite above — which no one could have left standing and which my estimate did not account for at all. ⛔ Not scope creep: the paragraph was load-bearing false documentation.
  • C — PROVEN by measurement, red shown before green. BEFORE: real matcher 0 findings; widened matcher ogUrlSkipsProxy=false, 0 findings — the hole, with the gate knowing and saying nothing. AFTER: real matcher still 0 (green unchanged); widened matcher 1 finding, naming the built URL. Then ablated the new limb from the committed file, confirmed the mutation on disk before running, watched exactly the two new assertions fail while 6c still passed, and proved the restore by both an empty git diff HEAD and a blob-hash match.

Case 6c is the one that makes this a gate rather than a coincidence: a matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes both limbs correctly and stays green — proving the new limb is wired to the URL, not to the flag. Without 6c, an assertion that fired on any widening would look identical to one that fired on the right widening.

The relaxation is kept, which was Zone 1 rule 2

Case 6 now asserts the absence of any catch-all/i18n finding (relaxation intact) and that the run is red anyway via the OG limb. ⇒ The behaviour the pinned case protects is unchanged; what changed is that the surface can no longer break silently around it.

Zone 3 — the count, handled the right way

The card's 403og:image figure is only approximately re-derivable (402 tracked .mdx under content/docs at the branch head; one card per source.getPages() entry, and the count moves daily). The PR body says "every one of them, ~402 today" instead of repeating 403 on faith. ⭐ That is the correct treatment of an inherited number: neither repeat it nor drop the magnitude.

Governed-surface check

Diff is scripts/check-docs-locale-catch-all.mjs only, 92 insertions. ⛔ No hit on docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md ⇒ this seat may arm it.

Arming

⚠️Platform reading, recorded because it nearly produced a wrong conclusion. The first attempt to post this comment returned HTTP 502 builtin injection failed (github), and so did four retries over ~20s — while the draft:false write in the same batch succeeded. Two probes then posted fine to this PR and to another, which made it look like the failure was content-driven. ⛔ It was not: the full body posted on the next attempt unchanged. The 502 window was transient and time-correlated, and the probes simply landed after it closed.

⇒ ⛔ Two probes at one instant do not establish a content cause for a failure that may be time-correlated. The reason this matters here: the un-draft landed while the ACCEPT did not, which is exactly the half-state — a PR moving toward merge with no review on record — that write-then-read-back exists to catch. It was caught because comment() reads its own status rather than assuming a POST worked.

CI is settled on the head with zero failures. Arming follows.


Generated by Claude Code

@os-project-manager
os-project-manager added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit 83ea500Aug 31, 2026
34 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-13703-og-proxy-matcher-assert branch August 31, 2026 18:19
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-project-manager@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it - #13932

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert
Aug 31, 2026
Merged

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it#13932
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Fixes#13703

scripts/check-docs-locale-catch-all.mjs read "dotted paths bypass proxy.ts's
matcher" as a statistic that licenses two relaxations, and asserted it
nowhere. Widening the matcher until it covers dotted paths therefore took the
whole gate green over a fully broken surface.

Re-derived line numbers

The card's :212 / :230 / :254 are stale — they predate PR #13702, which
moved the file. Against origin/main at 4642f4c64:

linecoderole
:335stats.dottedBypassesProxy = bypassing.length > 0;a stat
:363stats.ogUrlSkipsProxy = !compiled.runsFor(probe);computed, only printed
:364if (!stats.ogFinalSegmentDotted) {the only OG assertion — the marker side
:385if (!stats.dottedBypassesProxy) continue;skips the catch-all requirement
:409} else if (stats.dottedBypassesProxy) {i18n predicate runs only when true
:421summary prints ogUrlSkipsProxythe reading that mattered, printed
:516 / :555self-test pins true for the real matcher, false for a widened oneboth readings pinned as stats

The gate at :363 had already computed the answer and did nothing with it.

The both-directions measurement

One probe, one fixture pair, run before and after the commit — identical inputs,
only the gate changed. The pair is the script's own self-test shapes: case 1's
everything (guard present, marker image.png) with case 6's widened matcher.

BEFORE (4642f4c64)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): []
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (0): []

The second block is the defect in one reading: the gate knows the built OG URL
is now rewritten, and reports nothing.

AFTER (ecb7101ac)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): [] <- GREEN under the real matcher, unchanged
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (1): [ "the OG card URL `getPageImage()` builds -- `/og/docs/ai/agents/image.png`
-- IS matched by proxy.ts's matcher, even though its final segment `image.png` still
contains a dot. ..." ] <- RED under the widened matcher

Ablation — the new limb deleted from the committed file, mutation confirmed
on disk before the run (anchor count 1 to 0, blob b7ca7031 to 3ffa8fcc),
restored from HEAD after (git diff HEAD empty and blob hash back to
b7ca7031):

ABLATED SELF-TEST EXIT=1
- widening the matcher must be reported by the OG limb, not left green -- got []
- a matcher that swallowed the OG card URL must be reported once -- got []
RESTORED SELF-TEST EXIT=0

Only the two new assertions fail; case 6c (the green control) still passes, so
the red is the limb doing its job, not a fixture that reds on any edit.

What the relaxation still protects

It is kept, unchanged.:385 and :409 still relax on
dottedBypassesProxy, and that is still correct on its own terms: if the proxy
does rewrite dotted paths, /ads.txt becomes a two-segment path that matches
nothing and 404s, so the [lang] locale guard is genuinely not load-bearing
any more. Self-test case 6 still pins exactly that — it now asserts the
absence of any catch-all or i18n finding rather than a bare
findings.length === 0.

What changed is that the relaxation is no longer the whole story. The same
widening 404s every og:image, and that break is now asserted, so the run as a
whole cannot go green on it.

Two limbs, one assertion — and deliberately so. They relax for different
reasons (catch-all requirement vs i18n predicate), but neither needs its own
assertion, because the new limb is not wired to the flag at all: it is wired to
the built URL, compiled against the matcher the tree carries today. That is
strictly better than mirroring the flag, and case 6c measures the difference — a
matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes
both limbs correctly and still serves the cards, and stays green. A limb
keyed to dottedBypassesProxy would cry there. It fires on the break, not on
the flag.

Impact figure

The card names 403 live og:image URLs. Re-derived at ecb7101ac: 402
tracked .mdx pages under content/docs/, and app/og/docs/[...slug]'s
generateStaticParams emits exactly one URL per source.getPages() entry, so
it is one card per page. The card's 403 was derived on an earlier tree and the
docs page count moves daily — the durable statement is "every one of them at
once", ~402 today, not the literal 403.

Verification

Union run at ecb7101ac, exit codes captured before any pipe.

  • pnpm check:docs-locale-catch-all — green. Self-test 21 to 28 assertions.
  • Gate family reconciled: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 15 families (13 path-derived + 2 convention-triggered by the gate-script edit). comm -23 derived ran is empty — all 15 ran. Plus pnpm check:ratchet-remedy-authority, run explicitly per dispatch-gates places check:ratchet-remedy-authority in "undetermined" — a scripts/** sweep that no derived family names, so a full local family run misses it #13813 since path derivation cannot name it. 16 run, 15 green.
  • The 16th, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own declaration: it grades a saved turbo run test log, none exists locally, and its own text says this "is NOT a finding". CI passes it a log and is unaffected.
  • This script's own --self-test is its entire suite: git grep finds no other file naming it except package.json.
  • ESLint, narrowed and the narrowing measured — not skipped. (1) Population read from eslint's own config: this repo runs one eslint.config.mjs which, per its own comment at :328 and a positive-control measurement recorded there, never enables type-aware linting for any file (grep confirms no project: / projectService). (2) Count read from --format json: 1 file linted, 0 errors, 0 warnings, exit 0. (3) Invariance: with no type-aware linting and no rule that reads a second file, a one-file diff cannot move any untouched file's verdict — and nothing in the tree imports this script anyway.

Changeset

None, deliberately, matching the repo's own precedent: of the last 13
scripts/-only commits on main, zero carried one. This PR publishes
nothing from any package, which pr-automation.yml's Check Changeset job names
as the textbook skip-changeset case ("this PR edits a CI-internal script").
The label is applied on this PR.

Scope

One file, scripts/check-docs-locale-catch-all.mjs. apps/docs/lib/source.ts,
apps/docs/proxy.ts and the gated half from #12326 are untouched.

Generated by Claude Code


Generated by Claude Code

… of only reporting it
`check-docs-locale-catch-all.mjs` already computed the reading that matters --
`stats.ogUrlSkipsProxy = !compiled.runsFor(probe)` -- and only printed it in the
summary line. The same file's `stats.dottedBypassesProxy` was worse than inert:
it LICENSES two relaxations (`:385` skips the catch-all requirement, `:409`
skips the i18n predicate) while asserting nothing itself.
So widening proxy.ts's matcher until it covers dotted paths took the whole gate
green over a fully broken surface: the catch-all limb relaxed, the i18n limb
relaxed, and the OG limb still saw a dotted marker and stayed silent -- while
every live `og:image` URL was now locale-rewritten to a path `app/og/` does not
serve. Measured on the script's own fixture shape before this commit: widened
matcher, `ogUrlSkipsProxy = false`, findings = 0.
The relaxation is kept: it is correct on its own terms, and it is what
self-test case 6 pins. What changes is that it is no longer the whole story --
the OG limb now asserts the invariant on the BUILT URL from both ends (the
marker still carries a dot, AND that URL still escapes today's matcher), so it
fires whichever side moves. It is wired to the URL rather than to the flag, so
a widening that still excludes the `/og/` prefix relaxes the catch-all
requirement and correctly stays green (new self-test case 6c).
Self-test: 21 -> 28 assertions. Case 6 now pins that the relaxation holds
(no catch-all finding) AND that the run is red anyway; 6b is the proxy-side
ablation with the marker untouched; 6c is the green control.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 31, 2026
@os-project-manager
os-project-manager marked this pull request as ready for review August 31, 2026 17:46
@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

ACCEPTdomain:devx execution PM seat (#6023), session session_01Pk26oZ12t5N1hwGW1m1MgC. Verified against origin/main and the branch head, ⛔ not the shared checkout.

⭐ The reframing is worth more than the fix

The card was filed as "the proxy-side half is REPORTED, not asserted", and I dispatched it as an assertion that needed writing. The dev found it was already computed:

scripts/check-docs-locale-catch-all.mjs:363 stats.ogUrlSkipsProxy = !compiled.runsFor(probe);

⇒ ✅ Confirmed on origin/main. The reading existed at :363, was printed at :421, and was asserted only inside the self-test's own pins (:518, :579) — never on a real run. This was a stat needing promotion, not a check needing invention, and that is a materially different (and cheaper, and safer) change than the one I ordered.

⭐⭐ And it explains where #12326's false charter came from

#12326's charter claimed the proxy half was "already asserted", and this seat had been treating that as an unexplained error. It is not unexplained — the file's own header said, verbatim on origin/main at :95-98:

"This limb asserts the half that was asserted nowhere … It deliberately does NOT re-assert that the matcher excludes dotted paths — that condition is read once, above, and both halves are reported in the summary line."

⇒ The hole was documented as a design decision, and "reported in the summary line" reads as "covered" to anyone not tracing runsFor. ⭐ The charter inherited its false premise from the file's own wording. A fix that added the assertion and left that paragraph standing would have shipped a header contradicting its own behaviour — the exact defect class this lane merged a fix for today (#13509 / PR #13898). The dev rewrote it, and the replacement states the mechanism plainly: the relaxation "is correct on its own terms — but the same widening 404s every og:image, so a gate that only read the flag could go" green.

Zone 2 verdicts

  • A — CONFIRMED. Case 6's widened matcher was the adversarial world and was reusable in place; checkApp is exported and the fixture is a temp dir, so no real proxy.ts on disk is needed.
  • B — PARTLY FALSIFIED, and the reason is the good part. I estimated ~5 lines plus one self-test case. Actual: ~19 lines, three cases (6 rewritten, 6b, 6c), plus the header rewrite above — which no one could have left standing and which my estimate did not account for at all. ⛔ Not scope creep: the paragraph was load-bearing false documentation.
  • C — PROVEN by measurement, red shown before green. BEFORE: real matcher 0 findings; widened matcher ogUrlSkipsProxy=false, 0 findings — the hole, with the gate knowing and saying nothing. AFTER: real matcher still 0 (green unchanged); widened matcher 1 finding, naming the built URL. Then ablated the new limb from the committed file, confirmed the mutation on disk before running, watched exactly the two new assertions fail while 6c still passed, and proved the restore by both an empty git diff HEAD and a blob-hash match.

Case 6c is the one that makes this a gate rather than a coincidence: a matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes both limbs correctly and stays green — proving the new limb is wired to the URL, not to the flag. Without 6c, an assertion that fired on any widening would look identical to one that fired on the right widening.

The relaxation is kept, which was Zone 1 rule 2

Case 6 now asserts the absence of any catch-all/i18n finding (relaxation intact) and that the run is red anyway via the OG limb. ⇒ The behaviour the pinned case protects is unchanged; what changed is that the surface can no longer break silently around it.

Zone 3 — the count, handled the right way

The card's 403og:image figure is only approximately re-derivable (402 tracked .mdx under content/docs at the branch head; one card per source.getPages() entry, and the count moves daily). The PR body says "every one of them, ~402 today" instead of repeating 403 on faith. ⭐ That is the correct treatment of an inherited number: neither repeat it nor drop the magnitude.

Governed-surface check

Diff is scripts/check-docs-locale-catch-all.mjs only, 92 insertions. ⛔ No hit on docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md ⇒ this seat may arm it.

Arming

⚠️Platform reading, recorded because it nearly produced a wrong conclusion. The first attempt to post this comment returned HTTP 502 builtin injection failed (github), and so did four retries over ~20s — while the draft:false write in the same batch succeeded. Two probes then posted fine to this PR and to another, which made it look like the failure was content-driven. ⛔ It was not: the full body posted on the next attempt unchanged. The 502 window was transient and time-correlated, and the probes simply landed after it closed.

⇒ ⛔ Two probes at one instant do not establish a content cause for a failure that may be time-correlated. The reason this matters here: the un-draft landed while the ACCEPT did not, which is exactly the half-state — a PR moving toward merge with no review on record — that write-then-read-back exists to catch. It was caught because comment() reads its own status rather than assuming a POST worked.

CI is settled on the head with zero failures. Arming follows.


Generated by Claude Code

@os-project-manager
os-project-manager added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit 83ea500Aug 31, 2026
34 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-13703-og-proxy-matcher-assert branch August 31, 2026 18:19
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-project-manager@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it - #13932

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert
Aug 31, 2026
Merged

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it#13932
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Fixes#13703

scripts/check-docs-locale-catch-all.mjs read "dotted paths bypass proxy.ts's
matcher" as a statistic that licenses two relaxations, and asserted it
nowhere. Widening the matcher until it covers dotted paths therefore took the
whole gate green over a fully broken surface.

Re-derived line numbers

The card's :212 / :230 / :254 are stale — they predate PR #13702, which
moved the file. Against origin/main at 4642f4c64:

linecoderole
:335stats.dottedBypassesProxy = bypassing.length > 0;a stat
:363stats.ogUrlSkipsProxy = !compiled.runsFor(probe);computed, only printed
:364if (!stats.ogFinalSegmentDotted) {the only OG assertion — the marker side
:385if (!stats.dottedBypassesProxy) continue;skips the catch-all requirement
:409} else if (stats.dottedBypassesProxy) {i18n predicate runs only when true
:421summary prints ogUrlSkipsProxythe reading that mattered, printed
:516 / :555self-test pins true for the real matcher, false for a widened oneboth readings pinned as stats

The gate at :363 had already computed the answer and did nothing with it.

The both-directions measurement

One probe, one fixture pair, run before and after the commit — identical inputs,
only the gate changed. The pair is the script's own self-test shapes: case 1's
everything (guard present, marker image.png) with case 6's widened matcher.

BEFORE (4642f4c64)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): []
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (0): []

The second block is the defect in one reading: the gate knows the built OG URL
is now rewritten, and reports nothing.

AFTER (ecb7101ac)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): [] <- GREEN under the real matcher, unchanged
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (1): [ "the OG card URL `getPageImage()` builds -- `/og/docs/ai/agents/image.png`
-- IS matched by proxy.ts's matcher, even though its final segment `image.png` still
contains a dot. ..." ] <- RED under the widened matcher

Ablation — the new limb deleted from the committed file, mutation confirmed
on disk before the run (anchor count 1 to 0, blob b7ca7031 to 3ffa8fcc),
restored from HEAD after (git diff HEAD empty and blob hash back to
b7ca7031):

ABLATED SELF-TEST EXIT=1
- widening the matcher must be reported by the OG limb, not left green -- got []
- a matcher that swallowed the OG card URL must be reported once -- got []
RESTORED SELF-TEST EXIT=0

Only the two new assertions fail; case 6c (the green control) still passes, so
the red is the limb doing its job, not a fixture that reds on any edit.

What the relaxation still protects

It is kept, unchanged.:385 and :409 still relax on
dottedBypassesProxy, and that is still correct on its own terms: if the proxy
does rewrite dotted paths, /ads.txt becomes a two-segment path that matches
nothing and 404s, so the [lang] locale guard is genuinely not load-bearing
any more. Self-test case 6 still pins exactly that — it now asserts the
absence of any catch-all or i18n finding rather than a bare
findings.length === 0.

What changed is that the relaxation is no longer the whole story. The same
widening 404s every og:image, and that break is now asserted, so the run as a
whole cannot go green on it.

Two limbs, one assertion — and deliberately so. They relax for different
reasons (catch-all requirement vs i18n predicate), but neither needs its own
assertion, because the new limb is not wired to the flag at all: it is wired to
the built URL, compiled against the matcher the tree carries today. That is
strictly better than mirroring the flag, and case 6c measures the difference — a
matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes
both limbs correctly and still serves the cards, and stays green. A limb
keyed to dottedBypassesProxy would cry there. It fires on the break, not on
the flag.

Impact figure

The card names 403 live og:image URLs. Re-derived at ecb7101ac: 402
tracked .mdx pages under content/docs/, and app/og/docs/[...slug]'s
generateStaticParams emits exactly one URL per source.getPages() entry, so
it is one card per page. The card's 403 was derived on an earlier tree and the
docs page count moves daily — the durable statement is "every one of them at
once", ~402 today, not the literal 403.

Verification

Union run at ecb7101ac, exit codes captured before any pipe.

  • pnpm check:docs-locale-catch-all — green. Self-test 21 to 28 assertions.
  • Gate family reconciled: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 15 families (13 path-derived + 2 convention-triggered by the gate-script edit). comm -23 derived ran is empty — all 15 ran. Plus pnpm check:ratchet-remedy-authority, run explicitly per dispatch-gates places check:ratchet-remedy-authority in "undetermined" — a scripts/** sweep that no derived family names, so a full local family run misses it #13813 since path derivation cannot name it. 16 run, 15 green.
  • The 16th, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own declaration: it grades a saved turbo run test log, none exists locally, and its own text says this "is NOT a finding". CI passes it a log and is unaffected.
  • This script's own --self-test is its entire suite: git grep finds no other file naming it except package.json.
  • ESLint, narrowed and the narrowing measured — not skipped. (1) Population read from eslint's own config: this repo runs one eslint.config.mjs which, per its own comment at :328 and a positive-control measurement recorded there, never enables type-aware linting for any file (grep confirms no project: / projectService). (2) Count read from --format json: 1 file linted, 0 errors, 0 warnings, exit 0. (3) Invariance: with no type-aware linting and no rule that reads a second file, a one-file diff cannot move any untouched file's verdict — and nothing in the tree imports this script anyway.

Changeset

None, deliberately, matching the repo's own precedent: of the last 13
scripts/-only commits on main, zero carried one. This PR publishes
nothing from any package, which pr-automation.yml's Check Changeset job names
as the textbook skip-changeset case ("this PR edits a CI-internal script").
The label is applied on this PR.

Scope

One file, scripts/check-docs-locale-catch-all.mjs. apps/docs/lib/source.ts,
apps/docs/proxy.ts and the gated half from #12326 are untouched.

Generated by Claude Code


Generated by Claude Code

… of only reporting it
`check-docs-locale-catch-all.mjs` already computed the reading that matters --
`stats.ogUrlSkipsProxy = !compiled.runsFor(probe)` -- and only printed it in the
summary line. The same file's `stats.dottedBypassesProxy` was worse than inert:
it LICENSES two relaxations (`:385` skips the catch-all requirement, `:409`
skips the i18n predicate) while asserting nothing itself.
So widening proxy.ts's matcher until it covers dotted paths took the whole gate
green over a fully broken surface: the catch-all limb relaxed, the i18n limb
relaxed, and the OG limb still saw a dotted marker and stayed silent -- while
every live `og:image` URL was now locale-rewritten to a path `app/og/` does not
serve. Measured on the script's own fixture shape before this commit: widened
matcher, `ogUrlSkipsProxy = false`, findings = 0.
The relaxation is kept: it is correct on its own terms, and it is what
self-test case 6 pins. What changes is that it is no longer the whole story --
the OG limb now asserts the invariant on the BUILT URL from both ends (the
marker still carries a dot, AND that URL still escapes today's matcher), so it
fires whichever side moves. It is wired to the URL rather than to the flag, so
a widening that still excludes the `/og/` prefix relaxes the catch-all
requirement and correctly stays green (new self-test case 6c).
Self-test: 21 -> 28 assertions. Case 6 now pins that the relaxation holds
(no catch-all finding) AND that the run is red anyway; 6b is the proxy-side
ablation with the marker untouched; 6c is the green control.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 31, 2026
@os-project-manager
os-project-manager marked this pull request as ready for review August 31, 2026 17:46
@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

ACCEPTdomain:devx execution PM seat (#6023), session session_01Pk26oZ12t5N1hwGW1m1MgC. Verified against origin/main and the branch head, ⛔ not the shared checkout.

⭐ The reframing is worth more than the fix

The card was filed as "the proxy-side half is REPORTED, not asserted", and I dispatched it as an assertion that needed writing. The dev found it was already computed:

scripts/check-docs-locale-catch-all.mjs:363 stats.ogUrlSkipsProxy = !compiled.runsFor(probe);

⇒ ✅ Confirmed on origin/main. The reading existed at :363, was printed at :421, and was asserted only inside the self-test's own pins (:518, :579) — never on a real run. This was a stat needing promotion, not a check needing invention, and that is a materially different (and cheaper, and safer) change than the one I ordered.

⭐⭐ And it explains where #12326's false charter came from

#12326's charter claimed the proxy half was "already asserted", and this seat had been treating that as an unexplained error. It is not unexplained — the file's own header said, verbatim on origin/main at :95-98:

"This limb asserts the half that was asserted nowhere … It deliberately does NOT re-assert that the matcher excludes dotted paths — that condition is read once, above, and both halves are reported in the summary line."

⇒ The hole was documented as a design decision, and "reported in the summary line" reads as "covered" to anyone not tracing runsFor. ⭐ The charter inherited its false premise from the file's own wording. A fix that added the assertion and left that paragraph standing would have shipped a header contradicting its own behaviour — the exact defect class this lane merged a fix for today (#13509 / PR #13898). The dev rewrote it, and the replacement states the mechanism plainly: the relaxation "is correct on its own terms — but the same widening 404s every og:image, so a gate that only read the flag could go" green.

Zone 2 verdicts

  • A — CONFIRMED. Case 6's widened matcher was the adversarial world and was reusable in place; checkApp is exported and the fixture is a temp dir, so no real proxy.ts on disk is needed.
  • B — PARTLY FALSIFIED, and the reason is the good part. I estimated ~5 lines plus one self-test case. Actual: ~19 lines, three cases (6 rewritten, 6b, 6c), plus the header rewrite above — which no one could have left standing and which my estimate did not account for at all. ⛔ Not scope creep: the paragraph was load-bearing false documentation.
  • C — PROVEN by measurement, red shown before green. BEFORE: real matcher 0 findings; widened matcher ogUrlSkipsProxy=false, 0 findings — the hole, with the gate knowing and saying nothing. AFTER: real matcher still 0 (green unchanged); widened matcher 1 finding, naming the built URL. Then ablated the new limb from the committed file, confirmed the mutation on disk before running, watched exactly the two new assertions fail while 6c still passed, and proved the restore by both an empty git diff HEAD and a blob-hash match.

Case 6c is the one that makes this a gate rather than a coincidence: a matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes both limbs correctly and stays green — proving the new limb is wired to the URL, not to the flag. Without 6c, an assertion that fired on any widening would look identical to one that fired on the right widening.

The relaxation is kept, which was Zone 1 rule 2

Case 6 now asserts the absence of any catch-all/i18n finding (relaxation intact) and that the run is red anyway via the OG limb. ⇒ The behaviour the pinned case protects is unchanged; what changed is that the surface can no longer break silently around it.

Zone 3 — the count, handled the right way

The card's 403og:image figure is only approximately re-derivable (402 tracked .mdx under content/docs at the branch head; one card per source.getPages() entry, and the count moves daily). The PR body says "every one of them, ~402 today" instead of repeating 403 on faith. ⭐ That is the correct treatment of an inherited number: neither repeat it nor drop the magnitude.

Governed-surface check

Diff is scripts/check-docs-locale-catch-all.mjs only, 92 insertions. ⛔ No hit on docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md ⇒ this seat may arm it.

Arming

⚠️Platform reading, recorded because it nearly produced a wrong conclusion. The first attempt to post this comment returned HTTP 502 builtin injection failed (github), and so did four retries over ~20s — while the draft:false write in the same batch succeeded. Two probes then posted fine to this PR and to another, which made it look like the failure was content-driven. ⛔ It was not: the full body posted on the next attempt unchanged. The 502 window was transient and time-correlated, and the probes simply landed after it closed.

⇒ ⛔ Two probes at one instant do not establish a content cause for a failure that may be time-correlated. The reason this matters here: the un-draft landed while the ACCEPT did not, which is exactly the half-state — a PR moving toward merge with no review on record — that write-then-read-back exists to catch. It was caught because comment() reads its own status rather than assuming a POST worked.

CI is settled on the head with zero failures. Arming follows.


Generated by Claude Code

@os-project-manager
os-project-manager added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit 83ea500Aug 31, 2026
34 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-13703-og-proxy-matcher-assert branch August 31, 2026 18:19
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-project-manager@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it - #13932

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert
Aug 31, 2026
Merged

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it#13932
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Fixes#13703

scripts/check-docs-locale-catch-all.mjs read "dotted paths bypass proxy.ts's
matcher" as a statistic that licenses two relaxations, and asserted it
nowhere. Widening the matcher until it covers dotted paths therefore took the
whole gate green over a fully broken surface.

Re-derived line numbers

The card's :212 / :230 / :254 are stale — they predate PR #13702, which
moved the file. Against origin/main at 4642f4c64:

linecoderole
:335stats.dottedBypassesProxy = bypassing.length > 0;a stat
:363stats.ogUrlSkipsProxy = !compiled.runsFor(probe);computed, only printed
:364if (!stats.ogFinalSegmentDotted) {the only OG assertion — the marker side
:385if (!stats.dottedBypassesProxy) continue;skips the catch-all requirement
:409} else if (stats.dottedBypassesProxy) {i18n predicate runs only when true
:421summary prints ogUrlSkipsProxythe reading that mattered, printed
:516 / :555self-test pins true for the real matcher, false for a widened oneboth readings pinned as stats

The gate at :363 had already computed the answer and did nothing with it.

The both-directions measurement

One probe, one fixture pair, run before and after the commit — identical inputs,
only the gate changed. The pair is the script's own self-test shapes: case 1's
everything (guard present, marker image.png) with case 6's widened matcher.

BEFORE (4642f4c64)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): []
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (0): []

The second block is the defect in one reading: the gate knows the built OG URL
is now rewritten, and reports nothing.

AFTER (ecb7101ac)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): [] <- GREEN under the real matcher, unchanged
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (1): [ "the OG card URL `getPageImage()` builds -- `/og/docs/ai/agents/image.png`
-- IS matched by proxy.ts's matcher, even though its final segment `image.png` still
contains a dot. ..." ] <- RED under the widened matcher

Ablation — the new limb deleted from the committed file, mutation confirmed
on disk before the run (anchor count 1 to 0, blob b7ca7031 to 3ffa8fcc),
restored from HEAD after (git diff HEAD empty and blob hash back to
b7ca7031):

ABLATED SELF-TEST EXIT=1
- widening the matcher must be reported by the OG limb, not left green -- got []
- a matcher that swallowed the OG card URL must be reported once -- got []
RESTORED SELF-TEST EXIT=0

Only the two new assertions fail; case 6c (the green control) still passes, so
the red is the limb doing its job, not a fixture that reds on any edit.

What the relaxation still protects

It is kept, unchanged.:385 and :409 still relax on
dottedBypassesProxy, and that is still correct on its own terms: if the proxy
does rewrite dotted paths, /ads.txt becomes a two-segment path that matches
nothing and 404s, so the [lang] locale guard is genuinely not load-bearing
any more. Self-test case 6 still pins exactly that — it now asserts the
absence of any catch-all or i18n finding rather than a bare
findings.length === 0.

What changed is that the relaxation is no longer the whole story. The same
widening 404s every og:image, and that break is now asserted, so the run as a
whole cannot go green on it.

Two limbs, one assertion — and deliberately so. They relax for different
reasons (catch-all requirement vs i18n predicate), but neither needs its own
assertion, because the new limb is not wired to the flag at all: it is wired to
the built URL, compiled against the matcher the tree carries today. That is
strictly better than mirroring the flag, and case 6c measures the difference — a
matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes
both limbs correctly and still serves the cards, and stays green. A limb
keyed to dottedBypassesProxy would cry there. It fires on the break, not on
the flag.

Impact figure

The card names 403 live og:image URLs. Re-derived at ecb7101ac: 402
tracked .mdx pages under content/docs/, and app/og/docs/[...slug]'s
generateStaticParams emits exactly one URL per source.getPages() entry, so
it is one card per page. The card's 403 was derived on an earlier tree and the
docs page count moves daily — the durable statement is "every one of them at
once", ~402 today, not the literal 403.

Verification

Union run at ecb7101ac, exit codes captured before any pipe.

  • pnpm check:docs-locale-catch-all — green. Self-test 21 to 28 assertions.
  • Gate family reconciled: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 15 families (13 path-derived + 2 convention-triggered by the gate-script edit). comm -23 derived ran is empty — all 15 ran. Plus pnpm check:ratchet-remedy-authority, run explicitly per dispatch-gates places check:ratchet-remedy-authority in "undetermined" — a scripts/** sweep that no derived family names, so a full local family run misses it #13813 since path derivation cannot name it. 16 run, 15 green.
  • The 16th, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own declaration: it grades a saved turbo run test log, none exists locally, and its own text says this "is NOT a finding". CI passes it a log and is unaffected.
  • This script's own --self-test is its entire suite: git grep finds no other file naming it except package.json.
  • ESLint, narrowed and the narrowing measured — not skipped. (1) Population read from eslint's own config: this repo runs one eslint.config.mjs which, per its own comment at :328 and a positive-control measurement recorded there, never enables type-aware linting for any file (grep confirms no project: / projectService). (2) Count read from --format json: 1 file linted, 0 errors, 0 warnings, exit 0. (3) Invariance: with no type-aware linting and no rule that reads a second file, a one-file diff cannot move any untouched file's verdict — and nothing in the tree imports this script anyway.

Changeset

None, deliberately, matching the repo's own precedent: of the last 13
scripts/-only commits on main, zero carried one. This PR publishes
nothing from any package, which pr-automation.yml's Check Changeset job names
as the textbook skip-changeset case ("this PR edits a CI-internal script").
The label is applied on this PR.

Scope

One file, scripts/check-docs-locale-catch-all.mjs. apps/docs/lib/source.ts,
apps/docs/proxy.ts and the gated half from #12326 are untouched.

Generated by Claude Code


Generated by Claude Code

… of only reporting it
`check-docs-locale-catch-all.mjs` already computed the reading that matters --
`stats.ogUrlSkipsProxy = !compiled.runsFor(probe)` -- and only printed it in the
summary line. The same file's `stats.dottedBypassesProxy` was worse than inert:
it LICENSES two relaxations (`:385` skips the catch-all requirement, `:409`
skips the i18n predicate) while asserting nothing itself.
So widening proxy.ts's matcher until it covers dotted paths took the whole gate
green over a fully broken surface: the catch-all limb relaxed, the i18n limb
relaxed, and the OG limb still saw a dotted marker and stayed silent -- while
every live `og:image` URL was now locale-rewritten to a path `app/og/` does not
serve. Measured on the script's own fixture shape before this commit: widened
matcher, `ogUrlSkipsProxy = false`, findings = 0.
The relaxation is kept: it is correct on its own terms, and it is what
self-test case 6 pins. What changes is that it is no longer the whole story --
the OG limb now asserts the invariant on the BUILT URL from both ends (the
marker still carries a dot, AND that URL still escapes today's matcher), so it
fires whichever side moves. It is wired to the URL rather than to the flag, so
a widening that still excludes the `/og/` prefix relaxes the catch-all
requirement and correctly stays green (new self-test case 6c).
Self-test: 21 -> 28 assertions. Case 6 now pins that the relaxation holds
(no catch-all finding) AND that the run is red anyway; 6b is the proxy-side
ablation with the marker untouched; 6c is the green control.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 31, 2026
@os-project-manager
os-project-manager marked this pull request as ready for review August 31, 2026 17:46
@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

ACCEPTdomain:devx execution PM seat (#6023), session session_01Pk26oZ12t5N1hwGW1m1MgC. Verified against origin/main and the branch head, ⛔ not the shared checkout.

⭐ The reframing is worth more than the fix

The card was filed as "the proxy-side half is REPORTED, not asserted", and I dispatched it as an assertion that needed writing. The dev found it was already computed:

scripts/check-docs-locale-catch-all.mjs:363 stats.ogUrlSkipsProxy = !compiled.runsFor(probe);

⇒ ✅ Confirmed on origin/main. The reading existed at :363, was printed at :421, and was asserted only inside the self-test's own pins (:518, :579) — never on a real run. This was a stat needing promotion, not a check needing invention, and that is a materially different (and cheaper, and safer) change than the one I ordered.

⭐⭐ And it explains where #12326's false charter came from

#12326's charter claimed the proxy half was "already asserted", and this seat had been treating that as an unexplained error. It is not unexplained — the file's own header said, verbatim on origin/main at :95-98:

"This limb asserts the half that was asserted nowhere … It deliberately does NOT re-assert that the matcher excludes dotted paths — that condition is read once, above, and both halves are reported in the summary line."

⇒ The hole was documented as a design decision, and "reported in the summary line" reads as "covered" to anyone not tracing runsFor. ⭐ The charter inherited its false premise from the file's own wording. A fix that added the assertion and left that paragraph standing would have shipped a header contradicting its own behaviour — the exact defect class this lane merged a fix for today (#13509 / PR #13898). The dev rewrote it, and the replacement states the mechanism plainly: the relaxation "is correct on its own terms — but the same widening 404s every og:image, so a gate that only read the flag could go" green.

Zone 2 verdicts

  • A — CONFIRMED. Case 6's widened matcher was the adversarial world and was reusable in place; checkApp is exported and the fixture is a temp dir, so no real proxy.ts on disk is needed.
  • B — PARTLY FALSIFIED, and the reason is the good part. I estimated ~5 lines plus one self-test case. Actual: ~19 lines, three cases (6 rewritten, 6b, 6c), plus the header rewrite above — which no one could have left standing and which my estimate did not account for at all. ⛔ Not scope creep: the paragraph was load-bearing false documentation.
  • C — PROVEN by measurement, red shown before green. BEFORE: real matcher 0 findings; widened matcher ogUrlSkipsProxy=false, 0 findings — the hole, with the gate knowing and saying nothing. AFTER: real matcher still 0 (green unchanged); widened matcher 1 finding, naming the built URL. Then ablated the new limb from the committed file, confirmed the mutation on disk before running, watched exactly the two new assertions fail while 6c still passed, and proved the restore by both an empty git diff HEAD and a blob-hash match.

Case 6c is the one that makes this a gate rather than a coincidence: a matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes both limbs correctly and stays green — proving the new limb is wired to the URL, not to the flag. Without 6c, an assertion that fired on any widening would look identical to one that fired on the right widening.

The relaxation is kept, which was Zone 1 rule 2

Case 6 now asserts the absence of any catch-all/i18n finding (relaxation intact) and that the run is red anyway via the OG limb. ⇒ The behaviour the pinned case protects is unchanged; what changed is that the surface can no longer break silently around it.

Zone 3 — the count, handled the right way

The card's 403og:image figure is only approximately re-derivable (402 tracked .mdx under content/docs at the branch head; one card per source.getPages() entry, and the count moves daily). The PR body says "every one of them, ~402 today" instead of repeating 403 on faith. ⭐ That is the correct treatment of an inherited number: neither repeat it nor drop the magnitude.

Governed-surface check

Diff is scripts/check-docs-locale-catch-all.mjs only, 92 insertions. ⛔ No hit on docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md ⇒ this seat may arm it.

Arming

⚠️Platform reading, recorded because it nearly produced a wrong conclusion. The first attempt to post this comment returned HTTP 502 builtin injection failed (github), and so did four retries over ~20s — while the draft:false write in the same batch succeeded. Two probes then posted fine to this PR and to another, which made it look like the failure was content-driven. ⛔ It was not: the full body posted on the next attempt unchanged. The 502 window was transient and time-correlated, and the probes simply landed after it closed.

⇒ ⛔ Two probes at one instant do not establish a content cause for a failure that may be time-correlated. The reason this matters here: the un-draft landed while the ACCEPT did not, which is exactly the half-state — a PR moving toward merge with no review on record — that write-then-read-back exists to catch. It was caught because comment() reads its own status rather than assuming a POST worked.

CI is settled on the head with zero failures. Arming follows.


Generated by Claude Code

@os-project-manager
os-project-manager added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit 83ea500Aug 31, 2026
34 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-13703-og-proxy-matcher-assert branch August 31, 2026 18:19
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-project-manager@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it - #13932

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert
Aug 31, 2026
Merged

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it#13932
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Fixes#13703

scripts/check-docs-locale-catch-all.mjs read "dotted paths bypass proxy.ts's
matcher" as a statistic that licenses two relaxations, and asserted it
nowhere. Widening the matcher until it covers dotted paths therefore took the
whole gate green over a fully broken surface.

Re-derived line numbers

The card's :212 / :230 / :254 are stale — they predate PR #13702, which
moved the file. Against origin/main at 4642f4c64:

linecoderole
:335stats.dottedBypassesProxy = bypassing.length > 0;a stat
:363stats.ogUrlSkipsProxy = !compiled.runsFor(probe);computed, only printed
:364if (!stats.ogFinalSegmentDotted) {the only OG assertion — the marker side
:385if (!stats.dottedBypassesProxy) continue;skips the catch-all requirement
:409} else if (stats.dottedBypassesProxy) {i18n predicate runs only when true
:421summary prints ogUrlSkipsProxythe reading that mattered, printed
:516 / :555self-test pins true for the real matcher, false for a widened oneboth readings pinned as stats

The gate at :363 had already computed the answer and did nothing with it.

The both-directions measurement

One probe, one fixture pair, run before and after the commit — identical inputs,
only the gate changed. The pair is the script's own self-test shapes: case 1's
everything (guard present, marker image.png) with case 6's widened matcher.

BEFORE (4642f4c64)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): []
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (0): []

The second block is the defect in one reading: the gate knows the built OG URL
is now rewritten, and reports nothing.

AFTER (ecb7101ac)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): [] <- GREEN under the real matcher, unchanged
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (1): [ "the OG card URL `getPageImage()` builds -- `/og/docs/ai/agents/image.png`
-- IS matched by proxy.ts's matcher, even though its final segment `image.png` still
contains a dot. ..." ] <- RED under the widened matcher

Ablation — the new limb deleted from the committed file, mutation confirmed
on disk before the run (anchor count 1 to 0, blob b7ca7031 to 3ffa8fcc),
restored from HEAD after (git diff HEAD empty and blob hash back to
b7ca7031):

ABLATED SELF-TEST EXIT=1
- widening the matcher must be reported by the OG limb, not left green -- got []
- a matcher that swallowed the OG card URL must be reported once -- got []
RESTORED SELF-TEST EXIT=0

Only the two new assertions fail; case 6c (the green control) still passes, so
the red is the limb doing its job, not a fixture that reds on any edit.

What the relaxation still protects

It is kept, unchanged.:385 and :409 still relax on
dottedBypassesProxy, and that is still correct on its own terms: if the proxy
does rewrite dotted paths, /ads.txt becomes a two-segment path that matches
nothing and 404s, so the [lang] locale guard is genuinely not load-bearing
any more. Self-test case 6 still pins exactly that — it now asserts the
absence of any catch-all or i18n finding rather than a bare
findings.length === 0.

What changed is that the relaxation is no longer the whole story. The same
widening 404s every og:image, and that break is now asserted, so the run as a
whole cannot go green on it.

Two limbs, one assertion — and deliberately so. They relax for different
reasons (catch-all requirement vs i18n predicate), but neither needs its own
assertion, because the new limb is not wired to the flag at all: it is wired to
the built URL, compiled against the matcher the tree carries today. That is
strictly better than mirroring the flag, and case 6c measures the difference — a
matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes
both limbs correctly and still serves the cards, and stays green. A limb
keyed to dottedBypassesProxy would cry there. It fires on the break, not on
the flag.

Impact figure

The card names 403 live og:image URLs. Re-derived at ecb7101ac: 402
tracked .mdx pages under content/docs/, and app/og/docs/[...slug]'s
generateStaticParams emits exactly one URL per source.getPages() entry, so
it is one card per page. The card's 403 was derived on an earlier tree and the
docs page count moves daily — the durable statement is "every one of them at
once", ~402 today, not the literal 403.

Verification

Union run at ecb7101ac, exit codes captured before any pipe.

  • pnpm check:docs-locale-catch-all — green. Self-test 21 to 28 assertions.
  • Gate family reconciled: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 15 families (13 path-derived + 2 convention-triggered by the gate-script edit). comm -23 derived ran is empty — all 15 ran. Plus pnpm check:ratchet-remedy-authority, run explicitly per dispatch-gates places check:ratchet-remedy-authority in "undetermined" — a scripts/** sweep that no derived family names, so a full local family run misses it #13813 since path derivation cannot name it. 16 run, 15 green.
  • The 16th, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own declaration: it grades a saved turbo run test log, none exists locally, and its own text says this "is NOT a finding". CI passes it a log and is unaffected.
  • This script's own --self-test is its entire suite: git grep finds no other file naming it except package.json.
  • ESLint, narrowed and the narrowing measured — not skipped. (1) Population read from eslint's own config: this repo runs one eslint.config.mjs which, per its own comment at :328 and a positive-control measurement recorded there, never enables type-aware linting for any file (grep confirms no project: / projectService). (2) Count read from --format json: 1 file linted, 0 errors, 0 warnings, exit 0. (3) Invariance: with no type-aware linting and no rule that reads a second file, a one-file diff cannot move any untouched file's verdict — and nothing in the tree imports this script anyway.

Changeset

None, deliberately, matching the repo's own precedent: of the last 13
scripts/-only commits on main, zero carried one. This PR publishes
nothing from any package, which pr-automation.yml's Check Changeset job names
as the textbook skip-changeset case ("this PR edits a CI-internal script").
The label is applied on this PR.

Scope

One file, scripts/check-docs-locale-catch-all.mjs. apps/docs/lib/source.ts,
apps/docs/proxy.ts and the gated half from #12326 are untouched.

Generated by Claude Code


Generated by Claude Code

… of only reporting it
`check-docs-locale-catch-all.mjs` already computed the reading that matters --
`stats.ogUrlSkipsProxy = !compiled.runsFor(probe)` -- and only printed it in the
summary line. The same file's `stats.dottedBypassesProxy` was worse than inert:
it LICENSES two relaxations (`:385` skips the catch-all requirement, `:409`
skips the i18n predicate) while asserting nothing itself.
So widening proxy.ts's matcher until it covers dotted paths took the whole gate
green over a fully broken surface: the catch-all limb relaxed, the i18n limb
relaxed, and the OG limb still saw a dotted marker and stayed silent -- while
every live `og:image` URL was now locale-rewritten to a path `app/og/` does not
serve. Measured on the script's own fixture shape before this commit: widened
matcher, `ogUrlSkipsProxy = false`, findings = 0.
The relaxation is kept: it is correct on its own terms, and it is what
self-test case 6 pins. What changes is that it is no longer the whole story --
the OG limb now asserts the invariant on the BUILT URL from both ends (the
marker still carries a dot, AND that URL still escapes today's matcher), so it
fires whichever side moves. It is wired to the URL rather than to the flag, so
a widening that still excludes the `/og/` prefix relaxes the catch-all
requirement and correctly stays green (new self-test case 6c).
Self-test: 21 -> 28 assertions. Case 6 now pins that the relaxation holds
(no catch-all finding) AND that the run is red anyway; 6b is the proxy-side
ablation with the marker untouched; 6c is the green control.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 31, 2026
@os-project-manager
os-project-manager marked this pull request as ready for review August 31, 2026 17:46
@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

ACCEPTdomain:devx execution PM seat (#6023), session session_01Pk26oZ12t5N1hwGW1m1MgC. Verified against origin/main and the branch head, ⛔ not the shared checkout.

⭐ The reframing is worth more than the fix

The card was filed as "the proxy-side half is REPORTED, not asserted", and I dispatched it as an assertion that needed writing. The dev found it was already computed:

scripts/check-docs-locale-catch-all.mjs:363 stats.ogUrlSkipsProxy = !compiled.runsFor(probe);

⇒ ✅ Confirmed on origin/main. The reading existed at :363, was printed at :421, and was asserted only inside the self-test's own pins (:518, :579) — never on a real run. This was a stat needing promotion, not a check needing invention, and that is a materially different (and cheaper, and safer) change than the one I ordered.

⭐⭐ And it explains where #12326's false charter came from

#12326's charter claimed the proxy half was "already asserted", and this seat had been treating that as an unexplained error. It is not unexplained — the file's own header said, verbatim on origin/main at :95-98:

"This limb asserts the half that was asserted nowhere … It deliberately does NOT re-assert that the matcher excludes dotted paths — that condition is read once, above, and both halves are reported in the summary line."

⇒ The hole was documented as a design decision, and "reported in the summary line" reads as "covered" to anyone not tracing runsFor. ⭐ The charter inherited its false premise from the file's own wording. A fix that added the assertion and left that paragraph standing would have shipped a header contradicting its own behaviour — the exact defect class this lane merged a fix for today (#13509 / PR #13898). The dev rewrote it, and the replacement states the mechanism plainly: the relaxation "is correct on its own terms — but the same widening 404s every og:image, so a gate that only read the flag could go" green.

Zone 2 verdicts

  • A — CONFIRMED. Case 6's widened matcher was the adversarial world and was reusable in place; checkApp is exported and the fixture is a temp dir, so no real proxy.ts on disk is needed.
  • B — PARTLY FALSIFIED, and the reason is the good part. I estimated ~5 lines plus one self-test case. Actual: ~19 lines, three cases (6 rewritten, 6b, 6c), plus the header rewrite above — which no one could have left standing and which my estimate did not account for at all. ⛔ Not scope creep: the paragraph was load-bearing false documentation.
  • C — PROVEN by measurement, red shown before green. BEFORE: real matcher 0 findings; widened matcher ogUrlSkipsProxy=false, 0 findings — the hole, with the gate knowing and saying nothing. AFTER: real matcher still 0 (green unchanged); widened matcher 1 finding, naming the built URL. Then ablated the new limb from the committed file, confirmed the mutation on disk before running, watched exactly the two new assertions fail while 6c still passed, and proved the restore by both an empty git diff HEAD and a blob-hash match.

Case 6c is the one that makes this a gate rather than a coincidence: a matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes both limbs correctly and stays green — proving the new limb is wired to the URL, not to the flag. Without 6c, an assertion that fired on any widening would look identical to one that fired on the right widening.

The relaxation is kept, which was Zone 1 rule 2

Case 6 now asserts the absence of any catch-all/i18n finding (relaxation intact) and that the run is red anyway via the OG limb. ⇒ The behaviour the pinned case protects is unchanged; what changed is that the surface can no longer break silently around it.

Zone 3 — the count, handled the right way

The card's 403og:image figure is only approximately re-derivable (402 tracked .mdx under content/docs at the branch head; one card per source.getPages() entry, and the count moves daily). The PR body says "every one of them, ~402 today" instead of repeating 403 on faith. ⭐ That is the correct treatment of an inherited number: neither repeat it nor drop the magnitude.

Governed-surface check

Diff is scripts/check-docs-locale-catch-all.mjs only, 92 insertions. ⛔ No hit on docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md ⇒ this seat may arm it.

Arming

⚠️Platform reading, recorded because it nearly produced a wrong conclusion. The first attempt to post this comment returned HTTP 502 builtin injection failed (github), and so did four retries over ~20s — while the draft:false write in the same batch succeeded. Two probes then posted fine to this PR and to another, which made it look like the failure was content-driven. ⛔ It was not: the full body posted on the next attempt unchanged. The 502 window was transient and time-correlated, and the probes simply landed after it closed.

⇒ ⛔ Two probes at one instant do not establish a content cause for a failure that may be time-correlated. The reason this matters here: the un-draft landed while the ACCEPT did not, which is exactly the half-state — a PR moving toward merge with no review on record — that write-then-read-back exists to catch. It was caught because comment() reads its own status rather than assuming a POST worked.

CI is settled on the head with zero failures. Arming follows.


Generated by Claude Code

@os-project-manager
os-project-manager added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit 83ea500Aug 31, 2026
34 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-13703-og-proxy-matcher-assert branch August 31, 2026 18:19
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-project-manager@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it - #13932

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert
Aug 31, 2026
Merged

Assert the OG card URL escapes proxy.ts's matcher, instead of only reporting it#13932
os-project-manager merged 1 commit into
mainfrom
claude/issue-13703-og-proxy-matcher-assert

Conversation

@claude

@claudeclaudeBot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Fixes#13703

scripts/check-docs-locale-catch-all.mjs read "dotted paths bypass proxy.ts's
matcher" as a statistic that licenses two relaxations, and asserted it
nowhere. Widening the matcher until it covers dotted paths therefore took the
whole gate green over a fully broken surface.

Re-derived line numbers

The card's :212 / :230 / :254 are stale — they predate PR #13702, which
moved the file. Against origin/main at 4642f4c64:

linecoderole
:335stats.dottedBypassesProxy = bypassing.length > 0;a stat
:363stats.ogUrlSkipsProxy = !compiled.runsFor(probe);computed, only printed
:364if (!stats.ogFinalSegmentDotted) {the only OG assertion — the marker side
:385if (!stats.dottedBypassesProxy) continue;skips the catch-all requirement
:409} else if (stats.dottedBypassesProxy) {i18n predicate runs only when true
:421summary prints ogUrlSkipsProxythe reading that mattered, printed
:516 / :555self-test pins true for the real matcher, false for a widened oneboth readings pinned as stats

The gate at :363 had already computed the answer and did nothing with it.

The both-directions measurement

One probe, one fixture pair, run before and after the commit — identical inputs,
only the gate changed. The pair is the script's own self-test shapes: case 1's
everything (guard present, marker image.png) with case 6's widened matcher.

BEFORE (4642f4c64)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): []
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (0): []

The second block is the defect in one reading: the gate knows the built OG URL
is now rewritten, and reports nothing.

AFTER (ecb7101ac)

### REAL matcher
dottedBypassesProxy = true ogFinalSegmentDotted = true ogUrlSkipsProxy = true
findings (0): [] <- GREEN under the real matcher, unchanged
### WIDENED matcher
dottedBypassesProxy = false ogFinalSegmentDotted = true ogUrlSkipsProxy = false
findings (1): [ "the OG card URL `getPageImage()` builds -- `/og/docs/ai/agents/image.png`
-- IS matched by proxy.ts's matcher, even though its final segment `image.png` still
contains a dot. ..." ] <- RED under the widened matcher

Ablation — the new limb deleted from the committed file, mutation confirmed
on disk before the run (anchor count 1 to 0, blob b7ca7031 to 3ffa8fcc),
restored from HEAD after (git diff HEAD empty and blob hash back to
b7ca7031):

ABLATED SELF-TEST EXIT=1
- widening the matcher must be reported by the OG limb, not left green -- got []
- a matcher that swallowed the OG card URL must be reported once -- got []
RESTORED SELF-TEST EXIT=0

Only the two new assertions fail; case 6c (the green control) still passes, so
the red is the limb doing its job, not a fixture that reds on any edit.

What the relaxation still protects

It is kept, unchanged.:385 and :409 still relax on
dottedBypassesProxy, and that is still correct on its own terms: if the proxy
does rewrite dotted paths, /ads.txt becomes a two-segment path that matches
nothing and 404s, so the [lang] locale guard is genuinely not load-bearing
any more. Self-test case 6 still pins exactly that — it now asserts the
absence of any catch-all or i18n finding rather than a bare
findings.length === 0.

What changed is that the relaxation is no longer the whole story. The same
widening 404s every og:image, and that break is now asserted, so the run as a
whole cannot go green on it.

Two limbs, one assertion — and deliberately so. They relax for different
reasons (catch-all requirement vs i18n predicate), but neither needs its own
assertion, because the new limb is not wired to the flag at all: it is wired to
the built URL, compiled against the matcher the tree carries today. That is
strictly better than mirroring the flag, and case 6c measures the difference — a
matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes
both limbs correctly and still serves the cards, and stays green. A limb
keyed to dottedBypassesProxy would cry there. It fires on the break, not on
the flag.

Impact figure

The card names 403 live og:image URLs. Re-derived at ecb7101ac: 402
tracked .mdx pages under content/docs/, and app/og/docs/[...slug]'s
generateStaticParams emits exactly one URL per source.getPages() entry, so
it is one card per page. The card's 403 was derived on an earlier tree and the
docs page count moves daily — the durable statement is "every one of them at
once", ~402 today, not the literal 403.

Verification

Union run at ecb7101ac, exit codes captured before any pipe.

  • pnpm check:docs-locale-catch-all — green. Self-test 21 to 28 assertions.
  • Gate family reconciled: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 15 families (13 path-derived + 2 convention-triggered by the gate-script edit). comm -23 derived ran is empty — all 15 ran. Plus pnpm check:ratchet-remedy-authority, run explicitly per dispatch-gates places check:ratchet-remedy-authority in "undetermined" — a scripts/** sweep that no derived family names, so a full local family run misses it #13813 since path derivation cannot name it. 16 run, 15 green.
  • The 16th, node scripts/check-test-completeness.mjs, exits 3 = NOT MEASURED by its own declaration: it grades a saved turbo run test log, none exists locally, and its own text says this "is NOT a finding". CI passes it a log and is unaffected.
  • This script's own --self-test is its entire suite: git grep finds no other file naming it except package.json.
  • ESLint, narrowed and the narrowing measured — not skipped. (1) Population read from eslint's own config: this repo runs one eslint.config.mjs which, per its own comment at :328 and a positive-control measurement recorded there, never enables type-aware linting for any file (grep confirms no project: / projectService). (2) Count read from --format json: 1 file linted, 0 errors, 0 warnings, exit 0. (3) Invariance: with no type-aware linting and no rule that reads a second file, a one-file diff cannot move any untouched file's verdict — and nothing in the tree imports this script anyway.

Changeset

None, deliberately, matching the repo's own precedent: of the last 13
scripts/-only commits on main, zero carried one. This PR publishes
nothing from any package, which pr-automation.yml's Check Changeset job names
as the textbook skip-changeset case ("this PR edits a CI-internal script").
The label is applied on this PR.

Scope

One file, scripts/check-docs-locale-catch-all.mjs. apps/docs/lib/source.ts,
apps/docs/proxy.ts and the gated half from #12326 are untouched.

Generated by Claude Code


Generated by Claude Code

… of only reporting it
`check-docs-locale-catch-all.mjs` already computed the reading that matters --
`stats.ogUrlSkipsProxy = !compiled.runsFor(probe)` -- and only printed it in the
summary line. The same file's `stats.dottedBypassesProxy` was worse than inert:
it LICENSES two relaxations (`:385` skips the catch-all requirement, `:409`
skips the i18n predicate) while asserting nothing itself.
So widening proxy.ts's matcher until it covers dotted paths took the whole gate
green over a fully broken surface: the catch-all limb relaxed, the i18n limb
relaxed, and the OG limb still saw a dotted marker and stayed silent -- while
every live `og:image` URL was now locale-rewritten to a path `app/og/` does not
serve. Measured on the script's own fixture shape before this commit: widened
matcher, `ogUrlSkipsProxy = false`, findings = 0.
The relaxation is kept: it is correct on its own terms, and it is what
self-test case 6 pins. What changes is that it is no longer the whole story --
the OG limb now asserts the invariant on the BUILT URL from both ends (the
marker still carries a dot, AND that URL still escapes today's matcher), so it
fires whichever side moves. It is wired to the URL rather than to the flag, so
a widening that still excludes the `/og/` prefix relaxes the catch-all
requirement and correctly stays green (new self-test case 6c).
Self-test: 21 -> 28 assertions. Case 6 now pins that the relaxation holds
(no catch-all finding) AND that the run is red anyway; 6b is the proxy-side
ablation with the marker untouched; 6c is the green control.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 31, 2026
@os-project-manager
os-project-manager marked this pull request as ready for review August 31, 2026 17:46
@claude

claudeBot commented Aug 31, 2026

Copy link
Copy Markdown
ContributorAuthor

ACCEPTdomain:devx execution PM seat (#6023), session session_01Pk26oZ12t5N1hwGW1m1MgC. Verified against origin/main and the branch head, ⛔ not the shared checkout.

⭐ The reframing is worth more than the fix

The card was filed as "the proxy-side half is REPORTED, not asserted", and I dispatched it as an assertion that needed writing. The dev found it was already computed:

scripts/check-docs-locale-catch-all.mjs:363 stats.ogUrlSkipsProxy = !compiled.runsFor(probe);

⇒ ✅ Confirmed on origin/main. The reading existed at :363, was printed at :421, and was asserted only inside the self-test's own pins (:518, :579) — never on a real run. This was a stat needing promotion, not a check needing invention, and that is a materially different (and cheaper, and safer) change than the one I ordered.

⭐⭐ And it explains where #12326's false charter came from

#12326's charter claimed the proxy half was "already asserted", and this seat had been treating that as an unexplained error. It is not unexplained — the file's own header said, verbatim on origin/main at :95-98:

"This limb asserts the half that was asserted nowhere … It deliberately does NOT re-assert that the matcher excludes dotted paths — that condition is read once, above, and both halves are reported in the summary line."

⇒ The hole was documented as a design decision, and "reported in the summary line" reads as "covered" to anyone not tracing runsFor. ⭐ The charter inherited its false premise from the file's own wording. A fix that added the assertion and left that paragraph standing would have shipped a header contradicting its own behaviour — the exact defect class this lane merged a fix for today (#13509 / PR #13898). The dev rewrote it, and the replacement states the mechanism plainly: the relaxation "is correct on its own terms — but the same widening 404s every og:image, so a gate that only read the flag could go" green.

Zone 2 verdicts

  • A — CONFIRMED. Case 6's widened matcher was the adversarial world and was reusable in place; checkApp is exported and the fixture is a temp dir, so no real proxy.ts on disk is needed.
  • B — PARTLY FALSIFIED, and the reason is the good part. I estimated ~5 lines plus one self-test case. Actual: ~19 lines, three cases (6 rewritten, 6b, 6c), plus the header rewrite above — which no one could have left standing and which my estimate did not account for at all. ⛔ Not scope creep: the paragraph was load-bearing false documentation.
  • C — PROVEN by measurement, red shown before green. BEFORE: real matcher 0 findings; widened matcher ogUrlSkipsProxy=false, 0 findings — the hole, with the gate knowing and saying nothing. AFTER: real matcher still 0 (green unchanged); widened matcher 1 finding, naming the built URL. Then ablated the new limb from the committed file, confirmed the mutation on disk before running, watched exactly the two new assertions fail while 6c still passed, and proved the restore by both an empty git diff HEAD and a blob-hash match.

Case 6c is the one that makes this a gate rather than a coincidence: a matcher that drops the dot exclusion but still excludes the /og/ prefix relaxes both limbs correctly and stays green — proving the new limb is wired to the URL, not to the flag. Without 6c, an assertion that fired on any widening would look identical to one that fired on the right widening.

The relaxation is kept, which was Zone 1 rule 2

Case 6 now asserts the absence of any catch-all/i18n finding (relaxation intact) and that the run is red anyway via the OG limb. ⇒ The behaviour the pinned case protects is unchanged; what changed is that the surface can no longer break silently around it.

Zone 3 — the count, handled the right way

The card's 403og:image figure is only approximately re-derivable (402 tracked .mdx under content/docs at the branch head; one card per source.getPages() entry, and the count moves daily). The PR body says "every one of them, ~402 today" instead of repeating 403 on faith. ⭐ That is the correct treatment of an inherited number: neither repeat it nor drop the magnitude.

Governed-surface check

Diff is scripts/check-docs-locale-catch-all.mjs only, 92 insertions. ⛔ No hit on docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md ⇒ this seat may arm it.

Arming

⚠️Platform reading, recorded because it nearly produced a wrong conclusion. The first attempt to post this comment returned HTTP 502 builtin injection failed (github), and so did four retries over ~20s — while the draft:false write in the same batch succeeded. Two probes then posted fine to this PR and to another, which made it look like the failure was content-driven. ⛔ It was not: the full body posted on the next attempt unchanged. The 502 window was transient and time-correlated, and the probes simply landed after it closed.

⇒ ⛔ Two probes at one instant do not establish a content cause for a failure that may be time-correlated. The reason this matters here: the un-draft landed while the ACCEPT did not, which is exactly the half-state — a PR moving toward merge with no review on record — that write-then-read-back exists to catch. It was caught because comment() reads its own status rather than assuming a POST worked.

CI is settled on the head with zero failures. Arming follows.


Generated by Claude Code

@os-project-manager
os-project-manager added this pull request to the merge queueAug 31, 2026
Merged via the queue into main with commit 83ea500Aug 31, 2026
34 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-13703-og-proxy-matcher-assert branch August 31, 2026 18:19
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-project-manager@claude