Skip to content

feat: automatically protect rich-text code from prose grammar - #412

Merged
bartekplus merged 13 commits into
masterfrom
feat/automatic-rich-text-code-mode
Sep 25, 2026
Merged

bartekplus merged 13 commits into
masterfrom
feat/automatic-rich-text-code-mode

Conversation

@bartekplus

@bartekplus bartekplus commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Summary

Apply caret-local grammar and prediction-casing protection in rich-text code without changing saved settings or restarting the runtime. Supports semantic code/pre/kbd/samp, Quill code blocks/containers, and existing Monaco/CodeMirror/Ace markers. Code elsewhere in a composer does not disable the active prose paragraph.

The same resolver supplies a per-request suppressAutoCapitalize flag to the prediction pipeline. what . wa can offer and insert was in code while prose offers Was. Authored Wa/WA, raw candidate casing, and snippet content/metadata retain their existing behavior; results are not blindly lowercased. Explicit autocomplete and enabled code-safe grammar rules remain available.

Simplify/review pass — bcbd78f

No Ponytail review skill was installed in the available skill catalog, so this was a manual simplify pass. The PR discussion and inline threads were checked; there were no outstanding additional reviewer requests. The review and resolutions are posted here.

  • Replace nested override construction in the router with independent, explicit branches. Preserve undefined when no override applies and require literal true for casing suppression.
  • Remove a redundant selection type wrapper and duplicate readonly check; runtime API feature detection, fallback paths, and field exclusions are retained.
  • Share editor, caret, and synchronous property-override test fixtures. Verify restoration of inherited properties, nested overrides, and exact accessor descriptors even after exceptions.
  • Use the existing Quill type in the feature's browser test and replace nested polling with the existing non-waiting suggestion reader. Keep the displayed-text, Tab, DOM, and model assertions intact.
  • Add routing coverage for independent/combined site-count and casing overrides, including rejected truthy non-booleans; update the coverage mapping and shorten the feature documentation.

The baseline behavior IDs, existing tests, and CI gates are unchanged. No new dependencies, permissions, settings migrations, external requests, typed-text logging, or keyboard interception are introduced. Temporary validation tooling is absent from this commit and the PR diff.

Validation — final head bcbd78f

Both workflows completed successfully: Tests #1040 and CodeQL #1014.

Check Result
Full repository unit runner Passed
Central coverage registry validation Passed
Python build-tooling tests Passed
Oxlint, Prettier, TypeScript Passed
Chrome and Firefox smoke E2E Passed
Chrome full E2E 73 passed, 0 failed
Firefox full E2E 73 passed, 0 failed
Dedicated Google Docs cross-world fixtures 81 passed, 0 failed
CodeQL Passed

The named Quill code predictions keep lowercase through Tab and restore prose casing regression executed and passed in both final-head browser logs. Each production browser suite retains the repository's seven existing development-only skips; no skips were added.

Before publishing, the full unit runner also passed with the consolidated fixtures and added routing cases both before and after the production refactor. bun run check and bun run check:e2e:coverage passed on the exact source tree. Execution used the repository's Bun version in GitHub Actions, not a claimed local Bun installation. Current-head results are not carried forward from an earlier commit.

The earlier Slack-casing regression was proven to fail on unfixed code and pass after 27c56f0. All those regressions remain in this PR.

Earlier validation correction

The original failing unit fixture used an ineffective instance spy on jsdom's inherited Document.getSelection. It now exercises the actual selection API through scoped property overrides and restores descriptors. The earlier report that the new test passed and unrelated prediction/Google Docs tests were responsible was incorrect; those unrelated tests were not changed to hide the failure.

Scope and status

This is caret-local protection, not final replacement-range validation across inline code, prose-context clipping, or stale-prediction region tracking. Custom model-only styles and Google Docs canvas code formatting need dedicated adapters. Markdown parsing is unchanged.

The maintainer tested the original grammar protection in live Slack and reported the prediction-casing issue subsequently fixed here. Independent live Slack testing of the follow-up is not claimed. The PR remains draft and unmerged.

bartekplus and others added 11 commits September 25, 2026 15:50
Recognize Quill code-block editing DOM and semantic code/literal regions through a shared, uncached adapter resolver. Preserve existing Code-mode grammar semantics and field exclusions without changing settings, predictions, or keyboard handling.

Add selection-boundary, formatting-change, iframe, and shadow-root regressions plus real grammar-coordinator integration tests. Document the focused scope and remaining transaction-level safety work.
Verify that each grammar trigger receives the actual prose/protected hint through the real engine. Prove that composed-selection failures cannot silently fall back to a different valid prose caret. Document scoped fixtures and registered coverage, and restore the unchanged normal CI workflow set.

bartekplus commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner Author

Unit failure fixed; strict self-review follow-up

Reviewed the eight-file PR diff, the existing grammar coordinator/engine filtering, and the selection/helper integration. Fixes are pushed through 8e7615c.

Findings and resolutions

Finding Resolution
Failing nested-shadow fixture: the Document.getSelection instance spy did not affect the actual read in Bun/jsdom CI. The resolver therefore received an empty native selection. Supplement the real Selection object for composed-range fixtures and use scoped own-property overrides for document failures. Restore exact descriptors in finally; retain the correct code assertion.
False-passing negative tests: an expanded host range and an empty native selection could satisfy the assertions without exercising the intended branches. Collapse the foreign host range, assert API invocation, start the error test from verified prose, and check prose again after restoration.
Uncovered shadow-selection branches and fallback risk. Add code/prose positive controls for scoped and ordinary fallbacks, foreign-endpoint rejection, empty/multiple/expanded composed ranges, and a test proving a throwing composed API cannot use a different otherwise-valid fallback caret.
Vacuous trigger coverage: expecting null for an idle/paste pipeline with no matching rules did not prove propagation of code protection. Use a call-through spy on the real grammar engine; assert the actual hint and trigger for both prose and code across all four triggers.
Missing feature registration in the coverage inventory. Add three stable behaviors to both central registry files, without removing existing coverage, and validate the registry.
Incorrect earlier validation report. Correct the PR description: the new nested-shadow test was the failure, not unrelated prediction/Google Docs tests. Those unrelated tests remain unchanged.

No tests were disabled, no CI gates were weakened, and no production behavior was changed merely to make the fixtures pass. The temporary diagnostic workflow has been removed; the final diff contains no workflow changes.

Final validation on 8e7615c — completed successfully

Tests #1038 and CodeQL #1012 are both completed / success.

  • Full repository unit runner, coverage registry validation, and Python build-tooling tests: passed.
  • Oxlint, Prettier, TypeScript: passed.
  • Chrome and Firefox smoke E2E: passed.
  • Chrome and Firefox full E2E: passed.
  • Dedicated Google Docs cross-world fixture step in Chrome CI: passed (not live Docs).
  • CodeQL: passed.

These are final-head results from GitHub Actions, not pending jobs or a claimed local Bun build.

Scope boundary retained

This review does not turn caret-local grammar detection into transaction-wide code protection. Final replacement-range validation across inline-code boundaries, prose-only context clipping, stale-prediction region tokens, and autocomplete policy changes remain explicitly outside this focused PR. Live Slack/manual testing is not claimed. Keeping the PR draft and unmerged.

Carry caret-local suppression through the existing prediction request and
per-run override without changing saved settings or shared predictor state.
Preserve authored capitals, raw candidate casing, snippets and prose behavior.

Add a regression proven to fail on the prior code, request-isolation tests,
Tab-acceptance coverage and a real Quill code-to-prose browser regression.

bartekplus commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner Author

Fixed: prediction capitalization inside Slack code blocks

Commit: 27c56f0.

The reported what . wa → suggestion Was → Tab inserting Was came from the background prediction processor, not the local grammar engine. The original caret-local grammar protection was working, but sentence capitalization was still applied before the suggestion reached the popup.

The same live code-context resolver now supplies an optional suppressAutoCapitalize flag through the existing prediction request and per-run override. Only automatic sentence capitalization is suppressed; the shared/global setting is not modified, explicitly typed capitals remain meaningful, and candidate/snippet strings are not blindly lowercased. A subsequent prose request returns to normal capitalization.

Regression and review evidence

  • Ran the new regression against the old production code first: it failed with Was instead of was, and CamelCase instead of camelCase.
  • All 14 focused tests pass after the fix: sentence boundaries, next-word/mid-word requests, Wa/WA, original candidate and snippet casing, overlapping code/prose requests, live caret changes, formatting-only changes on a fresh request, and content-message forwarding.
  • A runtime regression exercises the real prediction processor, popup rendering and Tab acceptance: the code block ends with what . was.
  • The named full-browser regression Quill code predictions keep lowercase through Tab and restore prose casing executed and passed in both Chrome and Firefox. It uses real Quill code and prose in one composer and checks both displayed suggestions and accepted model/DOM text.
  • Coverage entries and documentation are updated. No shared capitalization setting is mutated, no lowercase-all workaround is used, and no new permissions, dependencies or external requests are introduced.
  • The temporary validation workflow/script are absent from the final commit and PR diff. Existing test gates remain unchanged.

Final current-head CI: all jobs passed

Tests #1039 and CodeQL #1013 both completed successfully for 27c56f0.

  • Full unit runner, coverage registry, Python build-tooling tests: passed.
  • Oxlint, Prettier, TypeScript: passed.
  • Chrome and Firefox smoke suites: passed.
  • Chrome full suite: 73 passed, 0 failed.
  • Firefox full suite: 73 passed, 0 failed.
  • Dedicated Google Docs cross-world fixtures: 81 passed, 0 failed.
  • CodeQL: passed.

Each full browser run retains the repository's seven existing dev-only skips in production mode; no skips were added by this fix. Results are from completed jobs on the current commit, not from an earlier revision.

The user's live Slack test confirmed the initial grammar protection and exposed this additional prediction-casing bug. The follow-up was verified in automated real-Quill browser tests; a personal live Slack retest is not claimed. The PR remains draft and unmerged.

Replace nested prediction override construction with explicit independent
branches, retain native DOM selection types, and remove duplicate readonly
classification. Share test-only editor/caret/property fixtures with verified
exception-safe cleanup, reuse Quill types, and eliminate nested E2E polling.

Preserve all existing behavior and add combined casing/site-override coverage.
The full unit runner passes before and after the source refactor; static and
coverage checks pass on this tree. No workflow changes or weakened test gates.

@bartekplus bartekplus left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Simplify pass completed — bcbd78f

No Ponytail review skill was installed in the available skill catalog, so I performed the requested manual simplify pass. I read the PR diff and discussion and rechecked the inline review threads; there are no outstanding inline threads or additional external review requests. The two earlier follow-up comments remain addressed.

Findings addressed

Finding Change
Nested ternary/spread expression obscured how site suggestion-count overrides combine with code-casing suppression. Replace it with two independent branches and a typed local override. Preserve undefined when neither applies and require literal true, not truthiness.
Redundant DOM typing and repeated readonly classification. Use the repository's native Selection type and remove the second aria-readonly check already handled by the resolver. Keep runtime feature checks and all selection fallback/eligibility behavior.
Editor, caret, and property-override fixtures were duplicated across feature tests. Share the small test-only helpers in codeContextTestUtils.ts. Add regressions for exact accessor restoration, inherited properties, nested overrides, and exceptions.
The Quill browser test duplicated partial API types and nested two polling loops. Reuse the existing dependency's Quill type via a type-only import and call the non-waiting suggestion reader inside the existing waitUntil. Preserve all popup, Tab, DOM, and model assertions.
Combined per-site/per-request override behavior lacked direct routing coverage. Add eight cases covering absent/independent/combined overrides, code-to-prose transitions, and truthy non-booleans. Verify tab/frame and mid-word suffix propagation.
Feature documentation repeated implementation history and omitted the prediction-casing file from its focused test command. Condense the document while retaining the behavior contract, privacy constraints, scope limits, and test instructions. Update mappings under existing coverage IDs.

All actionable findings from this simplify pass are addressed. No existing test was removed or disabled, no baseline behavior ID changed, and no CI gate was weakened. The final commit contains no temporary workflow/script, dependency, permission, or saved-setting changes.

Validation

The full repository unit runner passed with the consolidated fixtures/new cases both before and after the production refactor. This verifies the simplified implementation against the same tests rather than rewriting expectations to fit it.

On the final PR head bcbd78f, Tests #1040 completed all jobs successfully; CodeQL #1014 also passed:

  • Full unit runner, coverage registry, and Python build-tooling tests: passed.
  • Oxlint, Prettier, and TypeScript: passed.
  • Chrome and Firefox smoke: passed.
  • Chrome full: 73 passed, 0 failed.
  • Firefox full: 73 passed, 0 failed.
  • Dedicated Google Docs cross-world fixtures: 81 passed, 0 failed.

The named Quill code predictions keep lowercase through Tab and restore prose casing case executed and passed in both final-head browser logs. The seven pre-existing development-only skips in each production browser suite are unchanged. Execution was in GitHub Actions using the repository's Bun version, not a claimed local Bun build.

This pass preserves the existing feature scope: it is not transaction-wide replacement-range validation or stale-region tracking. No independent live Slack retest is claimed. Leaving the PR draft and unmerged.

@bartekplus
bartekplus marked this pull request as ready for review September 25, 2026 18:13
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@bartekplus
bartekplus merged commit d5a6861 into master Sep 25, 2026
8 checks passed
@bartekplus
bartekplus deleted the feat/automatic-rich-text-code-mode branch September 25, 2026 18:14
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