Skip to content

Harden spelling policy runtime - #58

Merged
leynos merged 2 commits into
mainfrom
typos-policy-runtime-hardening
Jul 14, 2026
Merged

Harden spelling policy runtime#58
leynos merged 2 commits into
mainfrom
typos-policy-runtime-hardening

Conversation

@leynos

@leynos leynos commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • bound shared and local masking regular expressions before applying them;
  • require matching source metadata for stale-cache and HTTP 304 reuse;
  • fail closed on tracked-file read errors while skipping non-UTF-8 files;
  • remove two whole-test spelling exclusions by fragmenting deliberate negative
    fixtures; and
  • cover safe, unsafe, broad, malformed, cache and scanner boundary cases.

Context

This is the shared-foundation follow-up to #57. Consumer review exposed runtime
enforcement gaps that must be fixed at the authority before the next estate
cohort is published. The implementation preserves narrow proper-name regexes,
including the official GitHub Flavored Markdown spelling, and keeps the
shared hand-written to handwritten phrase correction intact.

No repository roadmap item or implementation issue was found for this bounded
rollout follow-up.

Validation

  • direct pinned Typos scan;
  • 49 affected tests;
  • 66 focused policy, HTTP, spelling and rollout tests;
  • make ci: 181 tests and 3 snapshots;
  • generated typos.toml byte-current;
  • strict authority and sparse-overlay contracts;
  • source-scoped stale-cache and HTTP 304 cases;
  • malformed, backreference, nested, repeated, adjacent, broad and universal
    exclusion rejection;
  • tracked-file OSError propagation and non-UTF-8 skipping; and
  • AST, TOML, whitespace and exact seven-path manifest audits.

Manifest SHA-256:
e5d78d21f188815f66edb09d4ecdabe437f6edc2b58c8c1999e02989c51eb98d.

Bound local masking expressions and require cache metadata to match the
requested shared authority. Fail closed on tracked-file read errors while
continuing to skip non-UTF-8 content.

Remove whole-test exclusions by constructing deliberate negative fixtures at
runtime, and cover the strict regex, cache, scanner and phrase contracts with
focused regressions.

@sourcery-ai sourcery-ai Bot 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.

Sorry @leynos, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 11 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 84c096e9-7686-43ae-bfa4-3f18535890a9

📥 Commits

Reviewing files that changed from the base of the PR and between 6b3e808 and 6e602ac.

📒 Files selected for processing (19)
  • docs/adr/003-shared-oxford-spelling-base.md
  • docs/developers-guide.md
  • docs/users-guide.md
  • scripts/typos_rollout.py
  • scripts/typos_rollout_cache.py
  • scripts/typos_rollout_check.py
  • scripts/typos_rollout_harvest.py
  • scripts/typos_rollout_http.py
  • scripts/typos_rollout_policy.py
  • scripts/typos_rollout_render.py
  • tests/test_typos_rollout.py
  • tests/test_typos_rollout_http_security.py
  • tests/test_typos_rollout_policy_properties.py
  • tests/test_typos_rollout_refresh.py
  • tests/test_typos_rollout_semantics.py
  • tests/test_typos_spelling_gate.py
  • tests/typos_rollout_test_support.py
  • typos.local.toml
  • typos.toml

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Tighten ignore-regex and file-exclusion validation, scope stale HTTP cache reuse to matching sources, precompile harvesting matchers, propagate file-read errors, and expand spelling and refresh regression coverage.

Changes

Typos rollout validation and harvesting

Layer / File(s) Summary
Regex policy validation and exclusions
scripts/typos_rollout.py, tests/test_typos_rollout_semantics.py, typos*.toml
Reject unsafe repetition and backreferences, normalise exclusion paths, validate local policies, and include the updated test files in typo checks.
Source-scoped cache refresh
scripts/typos_rollout.py, tests/test_typos_rollout_http_security.py, tests/test_typos_rollout_semantics.py
Reuse stale caches only when persisted metadata matches the requested source, and test HTTP 304, HTTP error, and network failure paths.
Phrase harvesting and spelling coverage
scripts/typos_rollout.py, tests/test_typos_rollout.py, tests/test_typos_spelling_gate.py
Precompile ignore and phrase matchers, skip undecodable files, propagate other read errors, and replace spelling fixtures with shared constants across regression tests.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant refresh_base
  participant _refresh_http
  participant CacheMetadata
  participant StaleCache
  Caller->>refresh_base: request source refresh
  refresh_base->>_refresh_http: refresh URL
  _refresh_http->>CacheMetadata: load persisted source
  _refresh_http->>StaleCache: reuse cache when source matches
  _refresh_http-->>refresh_base: result or source-scoped error
  refresh_base-->>Caller: refreshed or cached data
Loading

Possibly related PRs

Poem

Patterns watch the winding text,
Safe repeats are now indexed;
Caches heed the source they bear,
Phrases match with sharpened care,
British words march proudly there.


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 4 warnings)

Check name Status Explanation Resolution
Testing (Overall) ❌ Error Regex-safety tests miss the {,n} quantifier edge case; a broken scanner for {,5} would still pass. Add a regression for {,n} quantifiers (for example {,5}) and cover every repetition form the scanner rejects.
User-Facing Documentation ⚠️ Warning docs/users-guide.md covers spelling tooling only in general; it omits the new regex-safety, source-scoped cache, and read/UTF-8 handling behaviour in scripts/typos_rollout.py. Add a users-guide section for the spelling rollout’s changed cache, regex, and harvesting rules, and keep any locale copies aligned.
Developer Documentation ⚠️ Warning FAIL: the PR changes internal regex-safety and source-scoped cache helpers in scripts/typos_rollout.py, but no docs/ADR file was updated and the developer guide/ADR omit those concepts. Document the new regex scanner, source-scoped stale-cache/HTTP 304 rules, and masking changes in docs/developers-guide.md and ADR 003; check off any related roadmap/execplan item.
Testing (Property / Proof) ⚠️ Warning The PR introduces a complex regex safety invariant (ReDoS prevention via _RepetitionScanner state machine) spanning unbounded pattern domain, tested only with 5 hardcoded examples rather than prope... Use Hypothesis to generate random regex patterns; add property tests verifying _RepetitionScanner correctly rejects unsafe patterns and accepts safe ones consistently across a broader pattern space than 5 examples cover.
Observability ⚠️ Warning Operational paths changed (cache reuse and harvest failure handling), but no logging, metrics, tracing, or alerts were added at the new decision/failure boundaries. Add structured logs/metrics for source-scoped refresh decisions and tracked-file read failures, using bounded labels for source and error class.
✅ Passed checks (15 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the PR’s main aim of hardening spelling policy runtime behaviour.
Description check ✅ Passed The description directly matches the changeset and validation described in the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Module-Level Documentation ✅ Passed All touched Python modules carry top-level docstrings; the main script explains its role and each test module names its behavioural scope.
Testing (Unit And Behavioural) ✅ Passed PASS: New tests cover public workflows and subprocess paths, plus edge/error cases for regex safety, cache scoping, and file I/O failures.
Testing (Compile-Time / Ui) ✅ Passed PASS: Python-only change; no Rust/TS compile-time surface exists, and the structured-output checks are deterministic semantic assertions.
Unit Architecture ✅ Passed PASS: RefreshOptions injects the opener, refresh_base surfaces cache/network failures explicitly, and repository scans now propagate I/O errors at the boundary.
Domain Architecture ✅ Passed Keep the domain model untouched: HTTP/filesystem concerns stay in rollout helpers, while Dictionary/PhraseFinding remain pure data and boundary code.
Security And Privacy ✅ Passed PASS: the patch only tightens validation and cache scoping; it uses fake example.test URLs, no credentials, and no new auth or privacy exposure.
Performance And Resource Use ✅ Passed PASS: keep the new regex scanners linear and precompiled; cache fallback adds only bounded metadata/cache reads, with no unbounded growth or per-item repeated I/O.
Concurrency And State ✅ Passed No new concurrency or shared mutable state appears: new state stays local/frozen, cache ownership is source-scoped, and the diff adds no locks, async tasks, or shared workers.
Architectural Complexity And Maintainability ✅ Passed Each new helper is domain-specific and directly simplifies a real seam (regex safety, cache scoping, phrase scanning); no generic layers, registries, or hidden hooks were added.
Rust Compiler Lint Integrity ✅ Passed PASS: the diff touches only Python/TOML files; no Rust files, lint suppressions, or clone-heavy ownership changes were added.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch typos-policy-runtime-hardening

Comment @coderabbitai help to get the list of available commands.

@leynos
leynos marked this pull request as ready for review July 14, 2026 07:18
@leynos

leynos commented Jul 14, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]
coderabbitai Bot previously requested changes Jul 14, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/typos_rollout.py`:
- Around line 69-209: Decompose the regex-safety functionality from
scripts/typos_rollout.py into a dedicated submodule, moving _GroupState,
_RepetitionScanner, _has_unsafe_repetition, _compile_policy_pattern, and their
required dependencies together. Update imports and call sites to preserve
existing behavior, and similarly separate cache-refresh and harvesting
functionality as needed so each module remains under the 400-logical-line limit.
- Around line 1084-1087: In the phrase-matcher loop, rename the unused `phrase`
unpacked variable to the project’s conventional ignored-variable name (such as
`_`) while preserving the existing `correction` and `matcher` bindings and loop
behavior.
- Around line 441-444: Update the normalization logic around normalized and
UNIVERSAL_FILE_GLOBS to use pathlib for removing redundant leading "./" segments
instead of manual startswith checks and slicing. Preserve the existing strip and
casefold behavior, and ensure repeated "./" prefixes normalize consistently
before the membership check.
- Around line 39-41: Update the REPETITION regular expression used by
_RepetitionScanner to also match Python’s {,n} quantifier form, while preserving
existing matches for {n}, {n,}, and {n,m}. Use the expanded pattern specified by
the review comment.

In `@tests/test_typos_rollout.py`:
- Around line 213-246: Extract the duplicated Path.read_text denial setup into a
shared pytest fixture or factory in tests/typos_rollout_test_support.py,
preserving delegation for non-target paths and the configurable PermissionError
message. In tests/test_typos_rollout.py lines 213-246, replace the inline
deny_target closure in test_harvest_repository_propagates_file_read_failures
with the shared helper; make the same replacement in
tests/test_typos_spelling_gate.py lines 177-206 within
test_phrase_checker_propagates_file_read_failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 56498df3-3f93-46ba-87bb-88bc1d00dc70

📥 Commits

Reviewing files that changed from the base of the PR and between 6b3e808 and a2273b9.

📒 Files selected for processing (7)
  • scripts/typos_rollout.py
  • tests/test_typos_rollout.py
  • tests/test_typos_rollout_http_security.py
  • tests/test_typos_rollout_semantics.py
  • tests/test_typos_spelling_gate.py
  • typos.local.toml
  • typos.toml
💤 Files with no reviewable changes (2)
  • typos.local.toml
  • typos.toml

Comment thread scripts/typos_rollout.py Outdated
Comment thread scripts/typos_rollout.py Outdated
Comment thread scripts/typos_rollout.py Outdated
Comment thread scripts/typos_rollout.py Outdated
Comment thread tests/test_typos_rollout.py
Split the shared rollout runtime into focused modules while retaining the
existing facade. Recognize every Python repetition form, add property coverage,
and bound refresh and read diagnostics.

Document the operational contracts and consolidate test fixtures so consumers
can inherit one reviewed implementation.
@leynos

leynos commented Jul 14, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@leynos
leynos dismissed coderabbitai[bot]’s stale review July 14, 2026 08:07

All five actionable threads were addressed in 6e602ac, replied to with green local and hosted evidence, and resolved. CodeRabbit completed its current-head review successfully with no new unresolved threads.

@leynos
leynos merged commit ed49d66 into main Jul 14, 2026
5 checks passed
@leynos
leynos deleted the typos-policy-runtime-hardening branch July 14, 2026 08:07
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.

1 participant