First-party content checks

Use Node.js 22 and PowerShell 7 from the repository root. Install the locked npm dependencies and checksum-pinned native tools once, then run the shared checks:

npm ci --ignore-scripts
pwsh ./scripts/install-content-tools.ps1
pwsh ./scripts/check.ps1 content

The native installer supports Windows x64 and Linux x64. It downloads into ignored artifacts/content-tools, verifies both archive and executable SHA-256 hashes, and reuses an installation only when the executable still matches the manifest. pwsh ./scripts/install-content-tools.ps1 -Verify checks it without downloading. Windows uses upstream ShellCheck's x86 executable under WoW64. No global installs, Docker daemon, application service, browser, or deployment credentials are needed.

check.ps1 full installs locked npm dependencies and includes these checks and their rejection fixtures alongside the existing solution and packaging checks. Native-tool installation is an explicit prerequisite; CI performs it before the shared full command. The required build-test check keeps its name and fails when any content check fails, independently of Git hooks.

Formatter and linter ownership

Content Formatter Additional checks
C# SDK dotnet format Existing analyzers; explicit accessibility (IDE0040) and readonly fields (IDE0044) are warnings
Markdown, JSON/JSONC, YAML, CSS, JavaScript Exactly pinned Prettier Markdown structure via markdownlint-cli2's Prettier-compatible preset
Bash scripts Exactly pinned shfmt ShellCheck, including Bash workflow run blocks through actionlint
GitHub workflows Prettier actionlint and the protected-source cache policy
Markdown links and images None Offline lychee file and anchor checks

EditorConfig and Prettier use two spaces for first-party content and shell scripts, LF line endings, and an 80-column code target. Markdown preserves authored prose wrapping; Prettier still formats tables, lists, and code fences. C# retains its existing four-space conventions. Razor, HTML, XML, and PowerShell are outside the new formatter's scope.

Apply formatting with pwsh ./scripts/check.ps1 format -Fix, then inspect the diff. That command includes C#, Prettier, and shfmt. npm run format applies only the content formatters; npm run format:check verifies them without changing files. Neither command rewrites prose to meet a style guide. Markdownlint's compatible preset disables overlapping rules; MD060 is also disabled because Prettier owns table layout. The PR body template alone permits a level-two opening heading, since GitHub supplies the title.

The runner enumerates tracked and new non-ignored files through Git, including root documentation and .github documents. It excludes generated output, dependencies, and .agents/skills. Package-manager lockfiles keep their generated formatting. Prettier's ignore file and Markdownlint's config keep editor checks within the same boundary. Vendored skills and their provenance are preserved.

Editor and optional hook use

The VS Code recommendations select local Prettier for its file types and the C# extension for C#/Razor. Markdownlint reads the repository configuration. Use the check-content and format-first-party-content tasks for the same command-line checks, including shell formatting. Visual Studio users can invoke those commands from its PowerShell terminal; EditorConfig remains authoritative for C#.

The existing opt-in Husky hook retains staged C# formatting and adds a content check when relevant files are staged. That content check verifies the working tree, including unstaged work; it never rewrites or stages content. Install the content prerequisites before opting into the hook. See hook setup.

Workflow compatibility and exceptions

GitHub supports cache-mode: none, but actionlint 1.7.12 does not recognize that key. The actionlint configuration suppresses only that specific root-key diagnostic in the protected-source deployment workflows, including manual documentation publication. The cache-policy check independently requires none and rejects job overrides that permit caching. Other workflow errors still fail, and the regression suite covers missing/changed cache policy. Remove these exceptions once the pinned actionlint supports the key.

ShellCheck exceptions sit next to the affected code or at the top of fixture scripts, with a reason: intentional literal variable expressions, a sourced library constant, the EXIT-trap callback, or deliberate glob matching. There is no repository-wide suppression of shell diagnostics.

Recorded validation

On 2026-09-22, Windows x64 with Node.js 22.23.2 and PowerShell 7.6.5 passed the shared full check: locked restore, format verification, Release build with zero warnings, all 72 .NET tests, frontend publish and portability guard, smoke-package checks, and all five isolated shell suites. After review fixes, the complete content gate and all seven content regression groups passed again. The fixtures reject formatting drift, skipped Markdown heading levels, missing files/images and anchors, invalid workflow syntax, shell word splitting, and changed deployment cache policy; formatter fixes pass the same check. They also verify Prettier's file-type and vendor exclusions.

Injected C# accessibility defects failed the Release build with IDE0040; a runtime-initialized mutable field failed dotnet format with IDE0044. The latter is enforced by formatting verification, not by this SDK's build analyzer. Native tool installation, reuse without downloads, and rejection of a corrupted executable were verified on Windows.

The Ubuntu 24.04 CI gate for PR #114 also passed the content checks, all seven regression groups, and the full solution gate. The tree tested at d5e0bb6 exactly matches merge commit f8db700 on main, including the initial mechanical formatting commit 1f646a6.

After the merge, pwsh ./scripts/check.ps1 format -Fix -Serial was rerun on Windows against f8db700. C# formatting, Prettier, and shfmt all completed successfully; git diff --exit-code confirmed that the overall sweep produced no changes. The separate mechanical PR originally planned is therefore already covered by the merged PR. The external-link schedule has not yet run. These formatting checks did not start application services, deploy, or establish browser acceptance.

Local lychee configuration uses offline mode and anchor checking. Missing files, images, and fragments fail PR validation. Remote URLs are excluded from this gate; their availability cannot block unrelated work. Rendered HTML can be added when a documentation-site build exists.

External-link maintenance runs weekly and can be dispatched manually. It has read-only permissions, four concurrent requests, a 15-second request timeout, one retry, a 15-minute job limit, and seven-day artifact retention. It produces a report without posting issues or comments. Owner ostomachion reviews failures, distinguishes temporary outages from stale links, and submits focused corrections. It is not a required PR check. Run the same report locally with pwsh ./scripts/check.ps1 external-links.

Maintaining tool pins

package.json and its lockfile pin npm tools; Dependabot checks the root tooling package weekly. The native tool manifest records exact versions, upstream release URLs, archive checksums, and executable checksums for each platform. ostomachion reviews native-tool releases monthly and whenever workflow syntax outgrows a pin. Verify upstream release assets and executable hashes, change the manifest in a focused PR, and run content checks and rejection fixtures on both platforms. A new formatter version may require a separate mechanical sweep PR.

Upstream references: Prettier installation, Markdownlint compatibility, actionlint configuration, ShellCheck, shfmt, and lychee anchors.