build: put .NET inside the local gates instead of one trailing CI step - #68

Merged
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates
Aug 20, 2026
Merged

build: put .NET inside the local gates instead of one trailing CI step#68
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

package.json had no dotnet:* scripts. So every one of these silently skipped a fifth of the codebase:

gatereached .NET before?
pnpm test
pnpm build
pnpm format:check❌ (TypeScript only)
pnpm check-all — "full CI parity" per CLAUDE.md
.husky/pre-commit (chains the above)

The only thing exercising the .NET port was a separate trailing step in pr-checks.yml. A developer could run every local gate green and still break the port; CLAUDE.md didn't even have a .NET section.

Fix

  • New dotnet:build, dotnet:test, dotnet:format, dotnet:format:check, wired into build, test, format, format:check.
  • format:check now chains all five languages. Previously it was oxfmt --check . and CI chained the other four by hand — two definitions of "formatted" that could drift apart. The CI step is now just pnpm format:check.
  • The trailing Build and test .NET step in pr-checks.yml is removed: pnpm build and pnpm test now cover it. (release.yml's copy is left alone — it sits next to dotnet pack.)
  • check-all collapses to typecheck && lint && format:check && test && build. Nothing is lost: each of those already fans out per language. It just stops listing half of them twice.
  • CLAUDE.md gets a .NET section and states that the SDK is now a prerequisite for pnpm test.

Corrected finding

The brief expected dotnet format --verify-no-changes to surface drift ("C# formatting has never been checked in this repo"). It passes clean as-is — nothing to fix. The gap was purely that nothing ran it locally.

Verification that the gate is real

  • Hand-broke whitespace in FileMetadata.cspnpm dotnet:format:check exits 2 with error WHITESPACE. Restored → green.
  • Deleted every obj/ and bin/ and re-ran → passes with no prior dotnet restore, so the CI ordering (format check before build) is safe.
  • pnpm test now reports the 46 .NET tests alongside TS/Python/Rust/Go.

🤖 Generated with Claude Code

https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC

@changeset-bot

changeset-botBot commented Aug 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bf172c6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
@smooai/filePatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

`package.json` had no `dotnet:*` scripts at all, so `pnpm test`, `pnpm build`,
`pnpm format:check` and `pnpm check-all` — the last of which CLAUDE.md calls
"full CI parity" — every one of them silently skipped a fifth of the codebase.
The husky pre-commit chains those same scripts, so it skipped it too. The only
thing exercising .NET was a separate trailing step in pr-checks.yml, which means
a developer could run every local gate green and still break the port.
- Adds `dotnet:build` / `dotnet:test` / `dotnet:format` / `dotnet:format:check`
and wires them into `build`, `test`, `format` and `format:check`.
- `format:check` now chains all five languages, so the local gate and the CI
step cannot disagree about what "formatted" means; pr-checks.yml's Format
step becomes plain `pnpm format:check`, and its trailing .NET step goes away
as a duplicate of `pnpm build` + `pnpm test`.
- `check-all` gets shorter without losing coverage: `typecheck`, `lint`, `test`
and `format:check` already fan out per language.
- CLAUDE.md gains the .NET section it never had, and says the SDK is now a
prerequisite for `pnpm test`.
`dotnet format --verify-no-changes` passes as-is — C# formatting has genuinely
never drifted, so there is nothing to clean up here. Verified the check is real
by hand-breaking whitespace in FileMetadata.cs (exit 2) and from a clean tree
with obj/ and bin/ deleted (no prior restore needed).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC
@brentrager
brentragerforce-pushed the fix/dotnet-local-gates branch from 6d1819c to bf172c6CompareAugust 20, 2026 18:29
@brentrager
brentrager merged commit 011a035 into mainAug 20, 2026
1 check passed
@brentrager
brentrager deleted the fix/dotnet-local-gates branch August 20, 2026 18:39
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brentrager
, '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

build: put .NET inside the local gates instead of one trailing CI step - #68

Merged
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates
Aug 20, 2026
Merged

build: put .NET inside the local gates instead of one trailing CI step#68
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

package.json had no dotnet:* scripts. So every one of these silently skipped a fifth of the codebase:

gatereached .NET before?
pnpm test
pnpm build
pnpm format:check❌ (TypeScript only)
pnpm check-all — "full CI parity" per CLAUDE.md
.husky/pre-commit (chains the above)

The only thing exercising the .NET port was a separate trailing step in pr-checks.yml. A developer could run every local gate green and still break the port; CLAUDE.md didn't even have a .NET section.

Fix

  • New dotnet:build, dotnet:test, dotnet:format, dotnet:format:check, wired into build, test, format, format:check.
  • format:check now chains all five languages. Previously it was oxfmt --check . and CI chained the other four by hand — two definitions of "formatted" that could drift apart. The CI step is now just pnpm format:check.
  • The trailing Build and test .NET step in pr-checks.yml is removed: pnpm build and pnpm test now cover it. (release.yml's copy is left alone — it sits next to dotnet pack.)
  • check-all collapses to typecheck && lint && format:check && test && build. Nothing is lost: each of those already fans out per language. It just stops listing half of them twice.
  • CLAUDE.md gets a .NET section and states that the SDK is now a prerequisite for pnpm test.

Corrected finding

The brief expected dotnet format --verify-no-changes to surface drift ("C# formatting has never been checked in this repo"). It passes clean as-is — nothing to fix. The gap was purely that nothing ran it locally.

Verification that the gate is real

  • Hand-broke whitespace in FileMetadata.cspnpm dotnet:format:check exits 2 with error WHITESPACE. Restored → green.
  • Deleted every obj/ and bin/ and re-ran → passes with no prior dotnet restore, so the CI ordering (format check before build) is safe.
  • pnpm test now reports the 46 .NET tests alongside TS/Python/Rust/Go.

🤖 Generated with Claude Code

https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC

@changeset-bot

changeset-botBot commented Aug 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bf172c6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
@smooai/filePatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

`package.json` had no `dotnet:*` scripts at all, so `pnpm test`, `pnpm build`,
`pnpm format:check` and `pnpm check-all` — the last of which CLAUDE.md calls
"full CI parity" — every one of them silently skipped a fifth of the codebase.
The husky pre-commit chains those same scripts, so it skipped it too. The only
thing exercising .NET was a separate trailing step in pr-checks.yml, which means
a developer could run every local gate green and still break the port.
- Adds `dotnet:build` / `dotnet:test` / `dotnet:format` / `dotnet:format:check`
and wires them into `build`, `test`, `format` and `format:check`.
- `format:check` now chains all five languages, so the local gate and the CI
step cannot disagree about what "formatted" means; pr-checks.yml's Format
step becomes plain `pnpm format:check`, and its trailing .NET step goes away
as a duplicate of `pnpm build` + `pnpm test`.
- `check-all` gets shorter without losing coverage: `typecheck`, `lint`, `test`
and `format:check` already fan out per language.
- CLAUDE.md gains the .NET section it never had, and says the SDK is now a
prerequisite for `pnpm test`.
`dotnet format --verify-no-changes` passes as-is — C# formatting has genuinely
never drifted, so there is nothing to clean up here. Verified the check is real
by hand-breaking whitespace in FileMetadata.cs (exit 2) and from a clean tree
with obj/ and bin/ deleted (no prior restore needed).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC
@brentrager
brentragerforce-pushed the fix/dotnet-local-gates branch from 6d1819c to bf172c6CompareAugust 20, 2026 18:29
@brentrager
brentrager merged commit 011a035 into mainAug 20, 2026
1 check passed
@brentrager
brentrager deleted the fix/dotnet-local-gates branch August 20, 2026 18:39
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brentrager
, '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

build: put .NET inside the local gates instead of one trailing CI step - #68

Merged
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates
Aug 20, 2026
Merged

build: put .NET inside the local gates instead of one trailing CI step#68
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

package.json had no dotnet:* scripts. So every one of these silently skipped a fifth of the codebase:

gatereached .NET before?
pnpm test
pnpm build
pnpm format:check❌ (TypeScript only)
pnpm check-all — "full CI parity" per CLAUDE.md
.husky/pre-commit (chains the above)

The only thing exercising the .NET port was a separate trailing step in pr-checks.yml. A developer could run every local gate green and still break the port; CLAUDE.md didn't even have a .NET section.

Fix

  • New dotnet:build, dotnet:test, dotnet:format, dotnet:format:check, wired into build, test, format, format:check.
  • format:check now chains all five languages. Previously it was oxfmt --check . and CI chained the other four by hand — two definitions of "formatted" that could drift apart. The CI step is now just pnpm format:check.
  • The trailing Build and test .NET step in pr-checks.yml is removed: pnpm build and pnpm test now cover it. (release.yml's copy is left alone — it sits next to dotnet pack.)
  • check-all collapses to typecheck && lint && format:check && test && build. Nothing is lost: each of those already fans out per language. It just stops listing half of them twice.
  • CLAUDE.md gets a .NET section and states that the SDK is now a prerequisite for pnpm test.

Corrected finding

The brief expected dotnet format --verify-no-changes to surface drift ("C# formatting has never been checked in this repo"). It passes clean as-is — nothing to fix. The gap was purely that nothing ran it locally.

Verification that the gate is real

  • Hand-broke whitespace in FileMetadata.cspnpm dotnet:format:check exits 2 with error WHITESPACE. Restored → green.
  • Deleted every obj/ and bin/ and re-ran → passes with no prior dotnet restore, so the CI ordering (format check before build) is safe.
  • pnpm test now reports the 46 .NET tests alongside TS/Python/Rust/Go.

🤖 Generated with Claude Code

https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC

@changeset-bot

changeset-botBot commented Aug 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bf172c6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
@smooai/filePatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

`package.json` had no `dotnet:*` scripts at all, so `pnpm test`, `pnpm build`,
`pnpm format:check` and `pnpm check-all` — the last of which CLAUDE.md calls
"full CI parity" — every one of them silently skipped a fifth of the codebase.
The husky pre-commit chains those same scripts, so it skipped it too. The only
thing exercising .NET was a separate trailing step in pr-checks.yml, which means
a developer could run every local gate green and still break the port.
- Adds `dotnet:build` / `dotnet:test` / `dotnet:format` / `dotnet:format:check`
and wires them into `build`, `test`, `format` and `format:check`.
- `format:check` now chains all five languages, so the local gate and the CI
step cannot disagree about what "formatted" means; pr-checks.yml's Format
step becomes plain `pnpm format:check`, and its trailing .NET step goes away
as a duplicate of `pnpm build` + `pnpm test`.
- `check-all` gets shorter without losing coverage: `typecheck`, `lint`, `test`
and `format:check` already fan out per language.
- CLAUDE.md gains the .NET section it never had, and says the SDK is now a
prerequisite for `pnpm test`.
`dotnet format --verify-no-changes` passes as-is — C# formatting has genuinely
never drifted, so there is nothing to clean up here. Verified the check is real
by hand-breaking whitespace in FileMetadata.cs (exit 2) and from a clean tree
with obj/ and bin/ deleted (no prior restore needed).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC
@brentrager
brentragerforce-pushed the fix/dotnet-local-gates branch from 6d1819c to bf172c6CompareAugust 20, 2026 18:29
@brentrager
brentrager merged commit 011a035 into mainAug 20, 2026
1 check passed
@brentrager
brentrager deleted the fix/dotnet-local-gates branch August 20, 2026 18:39
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brentrager
, '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

build: put .NET inside the local gates instead of one trailing CI step - #68

Merged
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates
Aug 20, 2026
Merged

build: put .NET inside the local gates instead of one trailing CI step#68
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

package.json had no dotnet:* scripts. So every one of these silently skipped a fifth of the codebase:

gatereached .NET before?
pnpm test
pnpm build
pnpm format:check❌ (TypeScript only)
pnpm check-all — "full CI parity" per CLAUDE.md
.husky/pre-commit (chains the above)

The only thing exercising the .NET port was a separate trailing step in pr-checks.yml. A developer could run every local gate green and still break the port; CLAUDE.md didn't even have a .NET section.

Fix

  • New dotnet:build, dotnet:test, dotnet:format, dotnet:format:check, wired into build, test, format, format:check.
  • format:check now chains all five languages. Previously it was oxfmt --check . and CI chained the other four by hand — two definitions of "formatted" that could drift apart. The CI step is now just pnpm format:check.
  • The trailing Build and test .NET step in pr-checks.yml is removed: pnpm build and pnpm test now cover it. (release.yml's copy is left alone — it sits next to dotnet pack.)
  • check-all collapses to typecheck && lint && format:check && test && build. Nothing is lost: each of those already fans out per language. It just stops listing half of them twice.
  • CLAUDE.md gets a .NET section and states that the SDK is now a prerequisite for pnpm test.

Corrected finding

The brief expected dotnet format --verify-no-changes to surface drift ("C# formatting has never been checked in this repo"). It passes clean as-is — nothing to fix. The gap was purely that nothing ran it locally.

Verification that the gate is real

  • Hand-broke whitespace in FileMetadata.cspnpm dotnet:format:check exits 2 with error WHITESPACE. Restored → green.
  • Deleted every obj/ and bin/ and re-ran → passes with no prior dotnet restore, so the CI ordering (format check before build) is safe.
  • pnpm test now reports the 46 .NET tests alongside TS/Python/Rust/Go.

🤖 Generated with Claude Code

https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC

@changeset-bot

changeset-botBot commented Aug 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bf172c6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
@smooai/filePatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

`package.json` had no `dotnet:*` scripts at all, so `pnpm test`, `pnpm build`,
`pnpm format:check` and `pnpm check-all` — the last of which CLAUDE.md calls
"full CI parity" — every one of them silently skipped a fifth of the codebase.
The husky pre-commit chains those same scripts, so it skipped it too. The only
thing exercising .NET was a separate trailing step in pr-checks.yml, which means
a developer could run every local gate green and still break the port.
- Adds `dotnet:build` / `dotnet:test` / `dotnet:format` / `dotnet:format:check`
and wires them into `build`, `test`, `format` and `format:check`.
- `format:check` now chains all five languages, so the local gate and the CI
step cannot disagree about what "formatted" means; pr-checks.yml's Format
step becomes plain `pnpm format:check`, and its trailing .NET step goes away
as a duplicate of `pnpm build` + `pnpm test`.
- `check-all` gets shorter without losing coverage: `typecheck`, `lint`, `test`
and `format:check` already fan out per language.
- CLAUDE.md gains the .NET section it never had, and says the SDK is now a
prerequisite for `pnpm test`.
`dotnet format --verify-no-changes` passes as-is — C# formatting has genuinely
never drifted, so there is nothing to clean up here. Verified the check is real
by hand-breaking whitespace in FileMetadata.cs (exit 2) and from a clean tree
with obj/ and bin/ deleted (no prior restore needed).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC
@brentrager
brentragerforce-pushed the fix/dotnet-local-gates branch from 6d1819c to bf172c6CompareAugust 20, 2026 18:29
@brentrager
brentrager merged commit 011a035 into mainAug 20, 2026
1 check passed
@brentrager
brentrager deleted the fix/dotnet-local-gates branch August 20, 2026 18:39
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brentrager
, '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

build: put .NET inside the local gates instead of one trailing CI step - #68

Merged
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates
Aug 20, 2026
Merged

build: put .NET inside the local gates instead of one trailing CI step#68
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

package.json had no dotnet:* scripts. So every one of these silently skipped a fifth of the codebase:

gatereached .NET before?
pnpm test
pnpm build
pnpm format:check❌ (TypeScript only)
pnpm check-all — "full CI parity" per CLAUDE.md
.husky/pre-commit (chains the above)

The only thing exercising the .NET port was a separate trailing step in pr-checks.yml. A developer could run every local gate green and still break the port; CLAUDE.md didn't even have a .NET section.

Fix

  • New dotnet:build, dotnet:test, dotnet:format, dotnet:format:check, wired into build, test, format, format:check.
  • format:check now chains all five languages. Previously it was oxfmt --check . and CI chained the other four by hand — two definitions of "formatted" that could drift apart. The CI step is now just pnpm format:check.
  • The trailing Build and test .NET step in pr-checks.yml is removed: pnpm build and pnpm test now cover it. (release.yml's copy is left alone — it sits next to dotnet pack.)
  • check-all collapses to typecheck && lint && format:check && test && build. Nothing is lost: each of those already fans out per language. It just stops listing half of them twice.
  • CLAUDE.md gets a .NET section and states that the SDK is now a prerequisite for pnpm test.

Corrected finding

The brief expected dotnet format --verify-no-changes to surface drift ("C# formatting has never been checked in this repo"). It passes clean as-is — nothing to fix. The gap was purely that nothing ran it locally.

Verification that the gate is real

  • Hand-broke whitespace in FileMetadata.cspnpm dotnet:format:check exits 2 with error WHITESPACE. Restored → green.
  • Deleted every obj/ and bin/ and re-ran → passes with no prior dotnet restore, so the CI ordering (format check before build) is safe.
  • pnpm test now reports the 46 .NET tests alongside TS/Python/Rust/Go.

🤖 Generated with Claude Code

https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC

@changeset-bot

changeset-botBot commented Aug 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bf172c6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
@smooai/filePatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

`package.json` had no `dotnet:*` scripts at all, so `pnpm test`, `pnpm build`,
`pnpm format:check` and `pnpm check-all` — the last of which CLAUDE.md calls
"full CI parity" — every one of them silently skipped a fifth of the codebase.
The husky pre-commit chains those same scripts, so it skipped it too. The only
thing exercising .NET was a separate trailing step in pr-checks.yml, which means
a developer could run every local gate green and still break the port.
- Adds `dotnet:build` / `dotnet:test` / `dotnet:format` / `dotnet:format:check`
and wires them into `build`, `test`, `format` and `format:check`.
- `format:check` now chains all five languages, so the local gate and the CI
step cannot disagree about what "formatted" means; pr-checks.yml's Format
step becomes plain `pnpm format:check`, and its trailing .NET step goes away
as a duplicate of `pnpm build` + `pnpm test`.
- `check-all` gets shorter without losing coverage: `typecheck`, `lint`, `test`
and `format:check` already fan out per language.
- CLAUDE.md gains the .NET section it never had, and says the SDK is now a
prerequisite for `pnpm test`.
`dotnet format --verify-no-changes` passes as-is — C# formatting has genuinely
never drifted, so there is nothing to clean up here. Verified the check is real
by hand-breaking whitespace in FileMetadata.cs (exit 2) and from a clean tree
with obj/ and bin/ deleted (no prior restore needed).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC
@brentrager
brentragerforce-pushed the fix/dotnet-local-gates branch from 6d1819c to bf172c6CompareAugust 20, 2026 18:29
@brentrager
brentrager merged commit 011a035 into mainAug 20, 2026
1 check passed
@brentrager
brentrager deleted the fix/dotnet-local-gates branch August 20, 2026 18:39
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brentrager
, '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

build: put .NET inside the local gates instead of one trailing CI step - #68

Merged
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates
Aug 20, 2026
Merged

build: put .NET inside the local gates instead of one trailing CI step#68
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

package.json had no dotnet:* scripts. So every one of these silently skipped a fifth of the codebase:

gatereached .NET before?
pnpm test
pnpm build
pnpm format:check❌ (TypeScript only)
pnpm check-all — "full CI parity" per CLAUDE.md
.husky/pre-commit (chains the above)

The only thing exercising the .NET port was a separate trailing step in pr-checks.yml. A developer could run every local gate green and still break the port; CLAUDE.md didn't even have a .NET section.

Fix

  • New dotnet:build, dotnet:test, dotnet:format, dotnet:format:check, wired into build, test, format, format:check.
  • format:check now chains all five languages. Previously it was oxfmt --check . and CI chained the other four by hand — two definitions of "formatted" that could drift apart. The CI step is now just pnpm format:check.
  • The trailing Build and test .NET step in pr-checks.yml is removed: pnpm build and pnpm test now cover it. (release.yml's copy is left alone — it sits next to dotnet pack.)
  • check-all collapses to typecheck && lint && format:check && test && build. Nothing is lost: each of those already fans out per language. It just stops listing half of them twice.
  • CLAUDE.md gets a .NET section and states that the SDK is now a prerequisite for pnpm test.

Corrected finding

The brief expected dotnet format --verify-no-changes to surface drift ("C# formatting has never been checked in this repo"). It passes clean as-is — nothing to fix. The gap was purely that nothing ran it locally.

Verification that the gate is real

  • Hand-broke whitespace in FileMetadata.cspnpm dotnet:format:check exits 2 with error WHITESPACE. Restored → green.
  • Deleted every obj/ and bin/ and re-ran → passes with no prior dotnet restore, so the CI ordering (format check before build) is safe.
  • pnpm test now reports the 46 .NET tests alongside TS/Python/Rust/Go.

🤖 Generated with Claude Code

https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC

@changeset-bot

changeset-botBot commented Aug 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bf172c6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
@smooai/filePatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

`package.json` had no `dotnet:*` scripts at all, so `pnpm test`, `pnpm build`,
`pnpm format:check` and `pnpm check-all` — the last of which CLAUDE.md calls
"full CI parity" — every one of them silently skipped a fifth of the codebase.
The husky pre-commit chains those same scripts, so it skipped it too. The only
thing exercising .NET was a separate trailing step in pr-checks.yml, which means
a developer could run every local gate green and still break the port.
- Adds `dotnet:build` / `dotnet:test` / `dotnet:format` / `dotnet:format:check`
and wires them into `build`, `test`, `format` and `format:check`.
- `format:check` now chains all five languages, so the local gate and the CI
step cannot disagree about what "formatted" means; pr-checks.yml's Format
step becomes plain `pnpm format:check`, and its trailing .NET step goes away
as a duplicate of `pnpm build` + `pnpm test`.
- `check-all` gets shorter without losing coverage: `typecheck`, `lint`, `test`
and `format:check` already fan out per language.
- CLAUDE.md gains the .NET section it never had, and says the SDK is now a
prerequisite for `pnpm test`.
`dotnet format --verify-no-changes` passes as-is — C# formatting has genuinely
never drifted, so there is nothing to clean up here. Verified the check is real
by hand-breaking whitespace in FileMetadata.cs (exit 2) and from a clean tree
with obj/ and bin/ deleted (no prior restore needed).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC
@brentrager
brentragerforce-pushed the fix/dotnet-local-gates branch from 6d1819c to bf172c6CompareAugust 20, 2026 18:29
@brentrager
brentrager merged commit 011a035 into mainAug 20, 2026
1 check passed
@brentrager
brentrager deleted the fix/dotnet-local-gates branch August 20, 2026 18:39
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brentrager
, '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

build: put .NET inside the local gates instead of one trailing CI step - #68

Merged
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates
Aug 20, 2026
Merged

build: put .NET inside the local gates instead of one trailing CI step#68
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

package.json had no dotnet:* scripts. So every one of these silently skipped a fifth of the codebase:

gatereached .NET before?
pnpm test
pnpm build
pnpm format:check❌ (TypeScript only)
pnpm check-all — "full CI parity" per CLAUDE.md
.husky/pre-commit (chains the above)

The only thing exercising the .NET port was a separate trailing step in pr-checks.yml. A developer could run every local gate green and still break the port; CLAUDE.md didn't even have a .NET section.

Fix

  • New dotnet:build, dotnet:test, dotnet:format, dotnet:format:check, wired into build, test, format, format:check.
  • format:check now chains all five languages. Previously it was oxfmt --check . and CI chained the other four by hand — two definitions of "formatted" that could drift apart. The CI step is now just pnpm format:check.
  • The trailing Build and test .NET step in pr-checks.yml is removed: pnpm build and pnpm test now cover it. (release.yml's copy is left alone — it sits next to dotnet pack.)
  • check-all collapses to typecheck && lint && format:check && test && build. Nothing is lost: each of those already fans out per language. It just stops listing half of them twice.
  • CLAUDE.md gets a .NET section and states that the SDK is now a prerequisite for pnpm test.

Corrected finding

The brief expected dotnet format --verify-no-changes to surface drift ("C# formatting has never been checked in this repo"). It passes clean as-is — nothing to fix. The gap was purely that nothing ran it locally.

Verification that the gate is real

  • Hand-broke whitespace in FileMetadata.cspnpm dotnet:format:check exits 2 with error WHITESPACE. Restored → green.
  • Deleted every obj/ and bin/ and re-ran → passes with no prior dotnet restore, so the CI ordering (format check before build) is safe.
  • pnpm test now reports the 46 .NET tests alongside TS/Python/Rust/Go.

🤖 Generated with Claude Code

https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC

@changeset-bot

changeset-botBot commented Aug 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bf172c6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
@smooai/filePatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

`package.json` had no `dotnet:*` scripts at all, so `pnpm test`, `pnpm build`,
`pnpm format:check` and `pnpm check-all` — the last of which CLAUDE.md calls
"full CI parity" — every one of them silently skipped a fifth of the codebase.
The husky pre-commit chains those same scripts, so it skipped it too. The only
thing exercising .NET was a separate trailing step in pr-checks.yml, which means
a developer could run every local gate green and still break the port.
- Adds `dotnet:build` / `dotnet:test` / `dotnet:format` / `dotnet:format:check`
and wires them into `build`, `test`, `format` and `format:check`.
- `format:check` now chains all five languages, so the local gate and the CI
step cannot disagree about what "formatted" means; pr-checks.yml's Format
step becomes plain `pnpm format:check`, and its trailing .NET step goes away
as a duplicate of `pnpm build` + `pnpm test`.
- `check-all` gets shorter without losing coverage: `typecheck`, `lint`, `test`
and `format:check` already fan out per language.
- CLAUDE.md gains the .NET section it never had, and says the SDK is now a
prerequisite for `pnpm test`.
`dotnet format --verify-no-changes` passes as-is — C# formatting has genuinely
never drifted, so there is nothing to clean up here. Verified the check is real
by hand-breaking whitespace in FileMetadata.cs (exit 2) and from a clean tree
with obj/ and bin/ deleted (no prior restore needed).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC
@brentrager
brentragerforce-pushed the fix/dotnet-local-gates branch from 6d1819c to bf172c6CompareAugust 20, 2026 18:29
@brentrager
brentrager merged commit 011a035 into mainAug 20, 2026
1 check passed
@brentrager
brentrager deleted the fix/dotnet-local-gates branch August 20, 2026 18:39
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brentrager
, '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

build: put .NET inside the local gates instead of one trailing CI step - #68

Merged
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates
Aug 20, 2026
Merged

build: put .NET inside the local gates instead of one trailing CI step#68
brentrager merged 1 commit into
mainfrom
fix/dotnet-local-gates

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

package.json had no dotnet:* scripts. So every one of these silently skipped a fifth of the codebase:

gatereached .NET before?
pnpm test
pnpm build
pnpm format:check❌ (TypeScript only)
pnpm check-all — "full CI parity" per CLAUDE.md
.husky/pre-commit (chains the above)

The only thing exercising the .NET port was a separate trailing step in pr-checks.yml. A developer could run every local gate green and still break the port; CLAUDE.md didn't even have a .NET section.

Fix

  • New dotnet:build, dotnet:test, dotnet:format, dotnet:format:check, wired into build, test, format, format:check.
  • format:check now chains all five languages. Previously it was oxfmt --check . and CI chained the other four by hand — two definitions of "formatted" that could drift apart. The CI step is now just pnpm format:check.
  • The trailing Build and test .NET step in pr-checks.yml is removed: pnpm build and pnpm test now cover it. (release.yml's copy is left alone — it sits next to dotnet pack.)
  • check-all collapses to typecheck && lint && format:check && test && build. Nothing is lost: each of those already fans out per language. It just stops listing half of them twice.
  • CLAUDE.md gets a .NET section and states that the SDK is now a prerequisite for pnpm test.

Corrected finding

The brief expected dotnet format --verify-no-changes to surface drift ("C# formatting has never been checked in this repo"). It passes clean as-is — nothing to fix. The gap was purely that nothing ran it locally.

Verification that the gate is real

  • Hand-broke whitespace in FileMetadata.cspnpm dotnet:format:check exits 2 with error WHITESPACE. Restored → green.
  • Deleted every obj/ and bin/ and re-ran → passes with no prior dotnet restore, so the CI ordering (format check before build) is safe.
  • pnpm test now reports the 46 .NET tests alongside TS/Python/Rust/Go.

🤖 Generated with Claude Code

https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC

@changeset-bot

changeset-botBot commented Aug 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bf172c6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
@smooai/filePatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

`package.json` had no `dotnet:*` scripts at all, so `pnpm test`, `pnpm build`,
`pnpm format:check` and `pnpm check-all` — the last of which CLAUDE.md calls
"full CI parity" — every one of them silently skipped a fifth of the codebase.
The husky pre-commit chains those same scripts, so it skipped it too. The only
thing exercising .NET was a separate trailing step in pr-checks.yml, which means
a developer could run every local gate green and still break the port.
- Adds `dotnet:build` / `dotnet:test` / `dotnet:format` / `dotnet:format:check`
and wires them into `build`, `test`, `format` and `format:check`.
- `format:check` now chains all five languages, so the local gate and the CI
step cannot disagree about what "formatted" means; pr-checks.yml's Format
step becomes plain `pnpm format:check`, and its trailing .NET step goes away
as a duplicate of `pnpm build` + `pnpm test`.
- `check-all` gets shorter without losing coverage: `typecheck`, `lint`, `test`
and `format:check` already fan out per language.
- CLAUDE.md gains the .NET section it never had, and says the SDK is now a
prerequisite for `pnpm test`.
`dotnet format --verify-no-changes` passes as-is — C# formatting has genuinely
never drifted, so there is nothing to clean up here. Verified the check is real
by hand-breaking whitespace in FileMetadata.cs (exit 2) and from a clean tree
with obj/ and bin/ deleted (no prior restore needed).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC
@brentrager
brentragerforce-pushed the fix/dotnet-local-gates branch from 6d1819c to bf172c6CompareAugust 20, 2026 18:29
@brentrager
brentrager merged commit 011a035 into mainAug 20, 2026
1 check passed
@brentrager
brentrager deleted the fix/dotnet-local-gates branch August 20, 2026 18:39
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brentrager