Skip to content

Add pattern guard, lint stack and contributor hooks (fold-in phase 1) - #76

Merged
ThatGuyMcd merged 15 commits into
mainfrom
chore/fold-guards
Oct 25, 2026
Merged

ThatGuyMcd merged 15 commits into
mainfrom
chore/fold-guards

Conversation

@swhitt

@swhitt swhitt commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator

TL;DR: We're folding the release patch layers (the 1.0.7 capsule plus all the ReleaseOverlay pipelines) into normal source, so main is exactly what ships on every platform, Mac included. This PR is step 1: guardrails so the layer pile can't grow while we do it. Zero game changes. No files change under runtime-recomp/src, patches/, extern/ or online IDs.

What you get

🛑 Pattern guard New overlay layers and pipelines get blocked. Existing ones are baselined (transition-layer label = escape hatch)
🧹 Lint + format ruff and shfmt enforced in CI. C++ format comes later with the fold
🪝 Hooks Opt-in pre-commit. Claude/Codex sessions can't add a layer (tested live)
🔒 Pinned bytes Formatters can't touch patches, SDK receipts or the 1.0.7 capsule bases
👥 CODEOWNERS Rule files only

@ThatGuyMcd bit's after merge

  • Apply .github/ruleset-main.json (needs admin)
  • Sanity-check CODEOWNERS

Heads up

  • One-time Python/shell reformat in d6690f6. Code is identical. Already in .git-blame-ignore-revs.
  • Not tested on a real Windows box yet: Setup-Windows.cmd.

Next: the fold PR. I've already reproduced the v1.0.11 online IDs, so cross-play stays as is.

pattern_guard.py rejects new overlay CMake, source swaps, string-replace
pipelines, capsule files and identity literals. Existing hits live in
architecture/pattern-guard-baseline.txt, which only shrinks. check.py
--suite takes comma lists and runs the guard by default.
ruff with a per-file baseline, clang-tidy, gersemi and dkr_enable_warnings,
plus a blocking lint job and an advisory tidy job. Formatters only report
until the autofix commits land. Stop clang-format sorting includes since
order matters in spliced TUs.
Formatting only: ASTs match HEAD apart from isort order, split imports,
one not-in rewrite and one unused re import. Baseline regenerated, 90 to
50 files. Listed in .git-blame-ignore-revs.
Fixers never see patches/, receipts or capsules; check_pinned_bytes.py
proves it. Setup scripts install the hooks, Build offers to. ruff format
and shfmt now block in the lint job.
AGENTS.md is the shared guidance. .claude/settings.json and
.codex/hooks.json wire the same scripts/agent_hooks: block edits that
bring back a patch layer, report lint findings after edits, and refuse to
stop with a new pattern-guard violation. pattern_guard gains check_content
for would-be file contents. New scripts are pyright strict.
The 1.0.7 capsule pins base_sha256 for 562 first-party files and rebuilds
its roles from them; the reformat commit changed one (test_generator.py).
Restore it, keep ruff and the fixers off those directories, and make the
pinned-bytes hook check every base except the 5 that already drifted.
Explain in AGENTS.md which files must keep their bytes, including the
capsule bases until the fold. Add check_pinned_bytes.py, bootstrap_hooks.py
and .git-blame-ignore-revs to CODEOWNERS.
@swhitt
swhitt marked this pull request as ready for review October 25, 2026 21:58
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review 🔄 Running since 2026-10-25T21:59:03.186119Z 898ad17 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The hook timeout can overwrite restored files, and default checks introduce undocumented build prerequisites and downloads.

2 open issues
What changed in this PR

Adds contributor guardrails ahead of folding patch layers into first-party source, without changing game runtime sources or online identities.

Changes:

  • Adds pattern-guard fixtures, pinned-byte validation, and agent lifecycle hooks.
  • Configures linting, formatting, ownership, merge policies, and platform hook integration.
  • Expands contributor checks and CTest coverage, alongside mechanical Python and shell formatting.

Unresolved issues:

  • Critical — scripts/agent_hooks/post_edit_check.py:105: Timeout handling leaves formatter subprocesses running, allowing them to overwrite files after snapshots are restored.
  • Moderate — scripts/check.py:22: Automatic discovery adds build-dependent tests to the default suite, breaking its documented Git-and-Python-only requirements.
  • Moderate — scripts/check.py:22: Discovery also includes real pre-commit integration tests that can download dependencies and fail offline, violating the default command’s no-download behavior.
File Description
tests/​fixtures/​pattern-guard/​PG013/​positive/​patches/​feature/​README.md Unregistered layer documentation fixture.
tests/​fixtures/​pattern-guard/​PG013/​positive/​patches/​feature/​PLAYTEST.txt Disallowed layer notes fixture.
tests/​fixtures/​pattern-guard/​PG013/​positive/​patches/​android/​surface.patch Unregistered dependency patch fixture.
tests/​fixtures/​pattern-guard/​PG013/​negative/​patches/​rt64/​README.md Allowed dependency documentation fixture.
tests/​fixtures/​pattern-guard/​PG013/​negative/​patches/​rt64/​0001-cache-limit.patch Allowed registered patch fixture.
tests/​fixtures/​pattern-guard/​PG013/​negative/​patches/​README.md Allowed patch-directory documentation fixture.
tests/​fixtures/​pattern-guard/​PG013/​negative/​patches/​manifest.json Registers the allowed dependency patch.
tests/​fixtures/​pattern-guard/​PG012/​positive/​scripts/​hook_guest.py Guest-code rewrite violation fixture.
tests/​fixtures/​pattern-guard/​PG012/​positive/​runtime-recomp/​cmake/​HookGuest.cmake CMake guest-code rewrite fixture.
tests/​fixtures/​pattern-guard/​PG012/​negative/​scripts/​guest_hooks.py Allowlisted guest-hook script fixture.
tests/​fixtures/​pattern-guard/​PG012/​negative/​scripts/​generate_probe.py Separate probe-generation fixture.
tests/​fixtures/​pattern-guard/​PG012/​negative/​runtime-recomp/​cmake/​Ledger.cmake Unrelated ledger-rewrite fixture.
tests/​fixtures/​pattern-guard/​PG011/​positive/​runtime-recomp/​src/​game/​polish_symbols.hpp Generated symbol-header violation fixture.
tests/​fixtures/​pattern-guard/​PG011/​positive/​runtime-recomp/​build/​generated/​feature.hpp Committed build-output violation fixture.
tests/​fixtures/​pattern-guard/​PG011/​negative/​runtime-recomp/​symbols/​polish.toml Allowed symbol-table fixture.
tests/​fixtures/​pattern-guard/​PG011/​negative/​runtime-recomp/​src/​game/​symbols.hpp Ordinary source-header fixture.
tests/​fixtures/​pattern-guard/​PG011/​negative/​runtime-recomp/​src/​game/​generated/​selawik_font.h Allowed generated asset-header fixture.
tests/​fixtures/​pattern-guard/​PG010/​positive/​scripts/​salt.py Identity-salt violation fixture.
tests/​fixtures/​pattern-guard/​PG010/​positive/​runtime-recomp/​src/​game/​netplay/​identity.cpp Identity-digest splicing fixture.
tests/​fixtures/​pattern-guard/​PG010/​positive/​runtime-recomp/​cmake/​Identity.cmake Configure-time identity hashing fixture.
tests/​fixtures/​pattern-guard/​PG010/​negative/​runtime-recomp/​src/​game/​netplay/​legacy_identity.hpp Allowlisted identity definition fixture.
tests/​fixtures/​pattern-guard/​PG010/​negative/​runtime-recomp/​src/​game/​mods/​catalog.cpp Non-identity hash constant fixture.
tests/​fixtures/​pattern-guard/​PG010/​negative/​runtime-recomp/​cmake/​LegacyMods.cmake Allowed package-hash fixture.
tests/​fixtures/​pattern-guard/​PG009/​positive/​runtime-recomp/​src/​game/​feature.cpp Build-specific include violation fixtures.
tests/​fixtures/​pattern-guard/​PG009/​negative/​runtime-recomp/​src/​game/​feature.cpp Portable include fixtures.
tests/​fixtures/​pattern-guard/​PG008/​positive/​patches/​rt64/​0001-sidebar.patch First-party patch-target violation fixture.
tests/​fixtures/​pattern-guard/​PG008/​positive/​patches/​manifest.json Registers the first-party-targeting fixture.
tests/​fixtures/​pattern-guard/​PG008/​negative/​patches/​rt64/​0001-cache-limit.patch Valid dependency-target patch fixture.
tests/​fixtures/​pattern-guard/​PG008/​negative/​patches/​manifest.json Registers the valid dependency fixture.
tests/​fixtures/​pattern-guard/​PG007/​positive/​runtime-recomp/​CMakeLists.txt Unregistered staged-patch reference fixture.
tests/​fixtures/​pattern-guard/​PG007/​positive/​patches/​rt64/​0002-unlisted.patch Unlisted patch fixture.
tests/​fixtures/​pattern-guard/​PG007/​positive/​patches/​rt64/​0001-cache-limit.patch Checksum-mismatch fixture input.
tests/​fixtures/​pattern-guard/​PG007/​positive/​patches/​manifest.json Deliberately incorrect checksum fixture.
tests/​fixtures/​pattern-guard/​PG007/​negative/​runtime-recomp/​tests/​cmake/​build_iteration/​CMakeLists.txt Allowed synthetic staged-patch fixture.
tests/​fixtures/​pattern-guard/​PG007/​negative/​runtime-recomp/​CMakeLists.txt Registered staged-patch reference fixture.
tests/​fixtures/​pattern-guard/​PG007/​negative/​patches/​rt64/​0001-cache-limit.patch Correctly registered patch fixture.
tests/​fixtures/​pattern-guard/​PG007/​negative/​patches/​manifest.json Matching patch checksum fixture.
tests/​fixtures/​pattern-guard/​PG006/​positive/​patches/​feature/​native/​feature.hpp First-party header in a layer fixture.
tests/​fixtures/​pattern-guard/​PG006/​positive/​patches/​feature/​native/​feature.cpp First-party implementation in a layer fixture.
tests/​fixtures/​pattern-guard/​PG006/​positive/​patches/​feature/​hooks.toml Layer-owned hook definition fixture.
tests/​fixtures/​pattern-guard/​PG006/​negative/​runtime-recomp/​src/​game/​feature.cpp In-place first-party source fixture.
tests/​fixtures/​pattern-guard/​PG006/​negative/​patches/​rt64/​0001-new-file.patch Allowed dependency file-addition fixture.
tests/​fixtures/​pattern-guard/​PG006/​negative/​patches/​manifest.json Registers the file-addition patch.
tests/​fixtures/​pattern-guard/​PG005/​positive/​tools/​manifest.json Source-capsule role manifest fixture.
tests/​fixtures/​pattern-guard/​PG005/​positive/​release/​source-capsule/​notes.txt Frozen source-capsule fixture.
tests/​fixtures/​pattern-guard/​PG005/​positive/​patches/​feature/​stage-receipt.json Layer receipt violation fixture.
tests/​fixtures/​pattern-guard/​PG005/​positive/​.gitattributes Capsule attribute violation fixture.
tests/​fixtures/​pattern-guard/​PG005/​negative/​tools/​other/​manifest.json Ordinary manifest fixture.
tests/​fixtures/​pattern-guard/​PG005/​negative/​modding/​reference-us-v77/​receipt.json Allowed SDK receipt fixture.
tests/​fixtures/​pattern-guard/​PG005/​negative/​docs/​adr/​0001-retire-source-capsule.md Historical capsule documentation fixture.
tests/​fixtures/​pattern-guard/​PG005/​negative/​.gitattributes Ordinary patch attribute fixture.
tests/​fixtures/​pattern-guard/​PG004/​positive/​scripts/​feature_pipeline.py First-party string-rewrite pipeline fixture.
tests/​fixtures/​pattern-guard/​PG004/​negative/​scripts/​render_table.py Data-only generation fixture.
tests/​fixtures/​pattern-guard/​PG004/​negative/​scripts/​guest_hooks.py Allowlisted rewrite-script fixture.
tests/​fixtures/​pattern-guard/​PG004/​negative/​scripts/​count_sources.py Read-only source inspection fixture.
tests/​fixtures/​pattern-guard/​PG003/​positive/​runtime-recomp/​CMakeLists.txt First-party source-swap violation fixtures.
tests/​fixtures/​pattern-guard/​PG003/​negative/​runtime-recomp/​CMakeLists.txt Allowed target and dependency operations.
tests/​fixtures/​pattern-guard/​PG003/​negative/​runtime-recomp/​cmake/​StagedPatch.cmake Dependency source-swap helper fixture.
tests/​fixtures/​pattern-guard/​PG002/​positive/​scripts/​configure.sh Configure-hook injection fixture.
tests/​fixtures/​pattern-guard/​PG002/​positive/​runtime-recomp/​cmake/​Overlay.cmake Deferred overlay invocation fixture.
tests/​fixtures/​pattern-guard/​PG002/​positive/​.github/​workflows/​build.yml Workflow configure-hook injection fixture.
tests/​fixtures/​pattern-guard/​PG002/​negative/​runtime-recomp/​cmake/​ProjectTests.cmake Non-overlay deferred-call fixture.
tests/​fixtures/​pattern-guard/​PG002/​negative/​runtime-recomp/​cmake/​Notes.cmake Comment-only hook reference fixture.
tests/​fixtures/​pattern-guard/​PG002/​negative/​docs/​history.md Historical hook documentation fixture.
tests/​fixtures/​pattern-guard/​PG001/​positive/​patches/​feature/​ReleaseOverlay.cmake Overlay CMake violation fixture.
tests/​fixtures/​pattern-guard/​PG001/​positive/​patches/​feature/​CMakeLists.txt Layer build-definition violation fixture.
tests/​fixtures/​pattern-guard/​PG001/​negative/​runtime-recomp/​cmake/​Feature.cmake Allowed in-place CMake fixture.
tests/​fixtures/​pattern-guard/​PG001/​negative/​patches/​rt64/​0001-cache-limit.patch Allowed dependency patch fixture.
tests/​fixtures/​pattern-guard/​PG001/​negative/​patches/​README.md Allowed patch documentation fixture.
tests/​fixtures/​pattern-guard/​PG001/​negative/​patches/​manifest.json Registers the allowed patch fixture.
Setup-Windows.cmd Adds prerequisite checks and hook bootstrap.
Setup-macOS.sh Adds hook bootstrap and opt-out argument.
Setup-Linux.sh Adds hook bootstrap and opt-out argument.
scripts/​water_patch_baseline.py Mechanical Python formatting.
scripts/​verify_ios_compile.py Mechanical Python formatting.
scripts/​validate_release_metadata.py Mechanical Python formatting.
scripts/​tests/​test_verify_ios_compile.py Mechanical test formatting.
scripts/​tests/​test_verify_android_compile.py Mechanical test formatting.
scripts/​tests/​test_update_release.py Formatting and import ordering.
scripts/​tests/​test_package_ios.py Formatting and import ordering.
scripts/​test_update_appimage.py Mechanical Python formatting.
scripts/​startup_flow_policy.py Mechanical Python formatting.
scripts/​stage_magic_code_sdk.py Mechanical Python formatting.
scripts/​scan_for_game_assets.py Mechanical Python formatting.
scripts/​run_host_shader_tool.py Mechanical Python formatting.
scripts/​README.md Documents guard execution and suite selection.
scripts/​qualify-updater-linux.sh Mechanical shell formatting.
scripts/​qualify-updater-arm.sh Mechanical shell formatting.
scripts/​prepare_legacy_menu_fragment.py Formatting and import ordering.
scripts/​prepare_legacy_character_fragment.py Mechanical Python formatting.
scripts/​package_source.py Formatting and import ordering.
scripts/​package_ios.py Formatting and import ordering.
scripts/​normalize-water-adapter.py Mechanical Python formatting.
scripts/​magic_code_hook_inventory.py Mechanical Python formatting.
scripts/​macos_build_lock.py Mechanical Python formatting.
scripts/​legacy_spawn_asset_type_policy.py Formatting and import ordering.
scripts/​legacy_model_reference_policy.py Formatting and import ordering.
scripts/​legacy_model_cache_policy.py Mechanical Python formatting.
scripts/​host_task_policy.py Mechanical Python formatting.
scripts/​generate_revision_policy.py Formatting and import ordering.
scripts/​generate_recomp_config.py Mechanical Python formatting.
scripts/​compose-lava.py Formatting and import ordering.
scripts/​check.py Adds guard suite and automatic test discovery.
scripts/​check_pinned_bytes.py Verifies patch, SDK, and capsule checksums.
scripts/​audit_replay_boundary.py Mechanical Python formatting.
scripts/​audio_queue_policy.py Formatting and import ordering.
scripts/​agent_hooks/​stop_check.py Blocks completion on newly introduced violations.
scripts/​agent_hooks/​session_start.py Prints guidance and records session baseline.
scripts/​agent_hooks/​run Selects Python and launches agent hooks.
scripts/​agent_hooks/​pre_edit_guard.py Checks planned edits before execution.
scripts/​agent_hooks/​post_edit_check.py Reports lint findings and restores fixer changes.
scripts/​adapt-water-reference.py Mechanical Python formatting.
runtime-recomp/​tests/​water_profile_policy_tests.py Formatting and import ordering.
runtime-recomp/​tests/​test_startup_flow_pipeline.py Formatting and import ordering.
runtime-recomp/​tests/​owned_content_identity_tests.py Mechanical test formatting.
runtime-recomp/​tests/​magic_code_pipeline_tests.py Mechanical test formatting.
runtime-recomp/​tests/​live_lod_pipeline_tests.py Mechanical test formatting.
runtime-recomp/​tests/​legacy_memory_pipeline_tests.py Formatting and import ordering.
runtime-recomp/​tests/​legacy_behaviour_pipeline_tests.py Formatting and import ordering.
runtime-recomp/​tests/​launcher_copy_source_tests.py Formatting and import ordering.
runtime-recomp/​tests/​hud_reference_source_tests.py Mechanical test formatting.
runtime-recomp/​tests/​host_task_policy_tests.py Mechanical test formatting.
runtime-recomp/​tests/​harness_report_tests.py Mechanical test formatting.
runtime-recomp/​tests/​finish_presentation_pipeline_tests.py Mechanical test formatting.
runtime-recomp/​tests/​developer_entrypoint_tests.py Mechanical test formatting.
runtime-recomp/​tests/​build_iteration_tests.py Formatting and import ordering.
runtime-recomp/​tests/​asset_scan_tests.py Adds docstring spacing.
runtime-recomp/​tests/​android_startup_contract_tests.py Mechanical test formatting.
runtime-recomp/​CMakeLists.txt Registers pattern-guard and agent-hook tests.
runtime-recomp/​cmake/​Warnings.cmake Defines opt-in target warning policies.
runtime-recomp/​cmake/​generate_revision_symbol_map.py Mechanical Python formatting.
pyproject.toml Configures Ruff and scoped strict Pyright checks.
docs/​DEVELOPMENT.md Updates contributor-check documentation.
CONTRIBUTING.md Documents architecture, tooling, and review practices.
CLAUDE.md Points agents to authoritative project guidance.
Build-Windows.cmd Reports missing or outdated hooks.
Build-macOS.sh Reports missing or outdated hooks.
Build-Linux.sh Reports missing or outdated hooks.
AGENTS.md Defines agent workflow and architecture constraints.
.pre-commit-config.yaml Configures lint, format, guard, and checksum hooks.
.gitignore Excludes local agent permissions and session state.
.github/​ruleset-main.json Defines intended branch-protection requirements.
.github/​PULL_REQUEST_TEMPLATE.md Adds architecture and verification checklist.
.github/​CODEOWNERS Assigns ownership to policy files.
.git-blame-ignore-revs Records the mechanical formatting commit.
.gersemirc Configures CMake formatting.
.editorconfig Defines shell formatting options.
.codex/​hooks.json Wires Codex session and edit hooks.
.claude/​settings.json Wires Claude session and edit hooks.
.clang-tidy Defines scoped C/C++ analysis checks.
.clang-format Preserves load-bearing include order.

Review effort: Balanced

Comment thread scripts/agent_hooks/post_edit_check.py Resolved
Comment thread scripts/check.py Resolved
post_edit_check killed only pre-commit, so a formatter it had started could
rewrite the file after the snapshots were restored. Run pre-commit in its own
process group and kill and reap the group first. Regression test included.
Build-dependent tests (CMake, Ninja) and the real pre-commit run move to
the opt-in host-tools suite, so check.py's default needs no build tools
and downloads nothing. CTest still runs them.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Missing capsule files can evade integrity checks, and Windows setup can discard a working Python launcher.

1 open issue
1 previously missed issue

In code that hasn't changed since last review

Medium severity Preserve a working Python launcher during fallback selection

Setup-Windows.cmd:28

The && set applies to the entire if command. When py -3 succeeds, the skipped fallback leaves a successful error level, so this still overwrites PYTHON=py -3 with PYTHON=python. On systems where python is absent or is the Microsoft Store stub, Setup then passes its Python prerequisite check but cannot install the hooks. Keep the fallback probe and assignment inside a conditional block so a working launcher is preserved.

2 resolved since last review

Review effort: Balanced

Comment thread scripts/check_pinned_bytes.py Resolved
Pins for capsule objects and deltas came only from files on disk, so a
deleted object a manifest still references passed. Derive them from the
manifest too, and track CRLF normalisation on the pin instead of by name.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

One or more issues must be addressed before approval.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment thread scripts/agent_hooks/post_edit_check.py Resolved
Snapshot-and-restore could roll back a save made by another editor while
pre-commit ran. Copy the edited files and lint config into a scratch git
repo, report the fixer diffs from there, and check pinned bytes read-only.
@swhitt
swhitt requested a balanced review from Copilot October 25, 2026 23:02
@ThatGuyMcd
ThatGuyMcd merged commit 723acf5 into main Oct 25, 2026
13 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Two critical issues remain: macOS build-kit test failures and a manifest-order bypass of first-party patch protection.

2 open issues
1 resolved since last review

Review effort: Balanced

Comment on lines +1426 to +1427
"DKRPatternGuard|pattern_guard_tests.py"
"DKRAgentHooks|agent_hooks_tests.py"
baseline = {}
return [
finding
for finding in pattern_guard.check_content(root, path, text)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants