Skip to content

Implement auto-fix for markdown flavor validation rule - #169

Merged
jeduden merged 3 commits into
mainfrom
claude/continue-complex-work-EByEZ
Apr 26, 2026
Merged

Implement auto-fix for markdown flavor validation rule#169
jeduden merged 3 commits into
mainfrom
claude/continue-complex-work-EByEZ

Conversation

@jeduden

@jeduden jeduden commented Apr 25, 2026

Copy link
Copy Markdown
Owner

Summary

Implements the auto-fix functionality for the markdown flavor validation rule (MDS034), enabling mdsmith fix to automatically correct unsupported markdown features based on the configured flavor.

Key Changes

  • Added fix.go: New module implementing byte-range edit infrastructure for fixing six unsupported markdown features:

    • Heading IDs (removes {#id} attribute blocks)
    • Strikethrough (removes ~~ delimiters)
    • Task lists (removes [x] checkboxes while preserving bullets)
    • Superscript (removes ^ delimiters)
    • Subscript (removes ~ delimiters)
    • Bare-URL autolinks (wraps URLs in angle brackets <url>)
  • Updated rule.go: Refactored Fix() method to:

    • First apply GitHub Alerts marker stripping (line-level edit)
    • Re-parse the rewritten source so AST offsets stay valid
    • Then delegate to fixByteRangeFeatures() for the six byte-range features in the same call
    • Only apply fixes for features unsupported by the configured flavor
  • Added comprehensive test coverage (fix_test.go):

    • Tests for each fixable feature in isolation
    • Tests verifying features are preserved when the flavor supports them
    • Composition test for alerts + byte-range fixes in a single Fix() call
    • Multi-edit composition test ensuring two edits on the same line compose correctly
    • Graceful skip test for nested inline markup (e.g. ~~*bold*~~)
  • Added golden test fixtures: Six markdown files demonstrating the expected output after fixing each feature type for CommonMark flavor

Implementation Details

applyEdits sorts edits by ascending start offset and builds the output in a single forward pass: it appends each unchanged span from the source, then the edit's replacement bytes, advancing a cursor across non-overlapping edits. The output buffer is pre-sized from the cumulative size delta so the build runs in O(len(src) + total edit work) without per-edit reallocation.

The dual-parser technique detects features like heading IDs and strikethrough by parsing with an extended markdown parser, while bare URLs are detected on the standard CommonMark AST to correctly skip URLs inside code spans and fences.

delimiterPairEdits only rewrites wrappers with a single Text child; nested inline markup (emphasis, links, code spans) declines the fix and leaves the diagnostic for the user, since locating the wrapper marker through nested children would require recursively reconstructing each child's own marker span.

The plan status for MDS034 is now marked complete (✅).

https://claude.ai/code/session_01HyTXePzdUP6WLrwX571gk8

Copilot AI review requested due to automatic review settings April 25, 2026 07:27
@codecov

codecov Bot commented Apr 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.05882% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.65%. Comparing base (bae6afa) to head (c28cc13).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
internal/rules/markdownflavor/rule.go 72.72% 1 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #169      +/-   ##
==========================================
+ Coverage   89.60%   89.65%   +0.05%     
==========================================
  Files         112      113       +1     
  Lines       12062    12163     +101     
==========================================
+ Hits        10808    10905      +97     
- Misses        796      798       +2     
- Partials      458      460       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Implements auto-fix support for MDS034 (markdown flavor validation) so mdsmith fix can rewrite unsupported Markdown constructs into flavor-compatible syntax.

Changes:

  • Added a byte-range edit framework to remove/transform six unsupported feature syntaxes (heading IDs, strikethrough, task lists, superscript, subscript, bare URLs).
  • Refactored MDS034’s Fix() flow to run GitHub Alerts marker stripping first, then apply byte-range fixes depending on configured flavor support.
  • Added unit tests and golden “fixed” fixtures; marked plan 86 complete in planning docs.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
plan/86_markdown-flavor-validation.md Marks the plan’s auto-fix acceptance criteria as complete and documents what is fixed.
internal/rules/markdownflavor/rule.go Refactors Fix() into GitHub Alerts stripping + delegation to byte-range fix pipeline.
internal/rules/markdownflavor/fix.go New byte-range edit collection + application logic for six fixable features.
internal/rules/markdownflavor/fix_test.go New focused unit tests for each fix plus a multi-edit composition test.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-task-list.md Golden output for task list fix under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-superscript.md Golden output for superscript fix under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-subscript.md Golden output for subscript fix under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-strikethrough.md Golden output for strikethrough fix under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-heading-id.md Golden output for heading ID fix under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-bare-url.md Golden output for bare URL autolink wrapping under CommonMark.
PLAN.md Updates plan 86 status to ✅ in the top-level plan index.

Comment thread internal/rules/markdownflavor/rule.go Outdated
Comment thread internal/rules/markdownflavor/fix.go
Comment thread internal/rules/markdownflavor/fix.go Outdated
Comment thread internal/rules/markdownflavor/fix_test.go
jeduden pushed a commit that referenced this pull request Apr 25, 2026
Resolves four review comments on PR #169:

- delimiterPairEdits was off-by-one for wrappers with nested inline
  markup (`~~*bold*~~` would have produced `~bold~`); rewrite to
  accept only single-Text-child wrappers and decline gracefully when
  emphasis, links, or breaks appear inside, leaving the diagnostic
  for manual resolution.
- Fix() no longer returns early after stripping GitHub Alert markers.
  After alerts are removed it re-parses the rewritten source and runs
  the byte-range pipeline on the new AST so heading IDs / strike-
  through / bare URLs in alert-bearing docs get fixed in one call.
- applyEdits now builds the output in a single ascending-order pass
  with a pre-sized buffer (was O(n*m) due to per-edit slice copies).
- Add tests covering: alerts + bare URL composition, nested-inline
  rejection (single-child and multi-sibling), FlavorAny no-op, and
  the supports-branch returns in dualNodeEdits for super/sub.

Also drops dead defensive code (Extra type assertion, marker bounds
checks, taskCheckBox guards, applyEdits overlap check) per repo
guidance to trust framework guarantees, lifting fix.go to 100%
statement coverage and addressing the codecov patch gate.
@jeduden
jeduden requested a review from Copilot April 25, 2026 08:07
jeduden pushed a commit that referenced this pull request Apr 25, 2026
Resolves four review comments on PR #169:

- delimiterPairEdits was off-by-one for wrappers with nested inline
  markup (`~~*bold*~~` would have produced `~bold~`); rewrite to
  accept only single-Text-child wrappers and decline gracefully when
  emphasis, links, or breaks appear inside, leaving the diagnostic
  for manual resolution.
- Fix() no longer returns early after stripping GitHub Alert markers.
  After alerts are removed it re-parses the rewritten source and runs
  the byte-range pipeline on the new AST so heading IDs / strike-
  through / bare URLs in alert-bearing docs get fixed in one call.
- applyEdits now builds the output in a single ascending-order pass
  with a pre-sized buffer (was O(n*m) due to per-edit slice copies).
- Add tests covering: alerts + bare URL composition, nested-inline
  rejection (single-child and multi-sibling), FlavorAny no-op, and
  the supports-branch returns in dualNodeEdits for super/sub.

Also drops dead defensive code (Extra type assertion, marker bounds
checks, taskCheckBox guards, applyEdits overlap check) per repo
guidance to trust framework guarantees, lifting fix.go to 100%
statement coverage and addressing the codecov patch gate.
@jeduden
jeduden force-pushed the claude/continue-complex-work-EByEZ branch from 76e22e2 to 8f916c7 Compare April 25, 2026 08:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds auto-fix support to MDS034 (markdown flavor validation) so mdsmith fix can rewrite unsupported Markdown constructs to a flavor-compatible form.

Changes:

  • Introduces a byte-range edit pipeline to fix six unsupported feature types (heading IDs, strikethrough, task lists, super/subscript, bare-URL autolinks).
  • Refactors MDS034 Fix() to compose GitHub Alerts marker stripping with the new byte-range fixes, including re-parsing when the source changes.
  • Adds unit tests plus fixed-output fixtures and marks plan 86 complete.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
plan/86_markdown-flavor-validation.md Marks the MDS034 plan slice complete and documents the set of auto-fixes.
internal/rules/markdownflavor/rule.go Composes alert stripping + byte-range fixing; re-parses after alert edits to keep offsets correct.
internal/rules/markdownflavor/fix.go New edit collection + application pipeline for fixable flavor features.
internal/rules/markdownflavor/fix_test.go Adds focused and composition tests for each fix behavior.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-task-list.md Golden fixed output for task list removal under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-superscript.md Golden fixed output for superscript removal under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-subscript.md Golden fixed output for subscript removal under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-strikethrough.md Golden fixed output for strikethrough removal under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-heading-id.md Golden fixed output for heading-id attribute stripping under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-bare-url.md Golden fixed output for bare-URL wrapping under CommonMark.
PLAN.md Updates plan index to reflect plan 86 completion.

Comment thread internal/rules/markdownflavor/fix_test.go Outdated
jeduden pushed a commit that referenced this pull request Apr 25, 2026
Address PR #169 review nit: TestRuleFixMultipleFeaturesOnOneLine's
doc comment described "reverse-order edit application", which was
true of the prior implementation. applyEdits now sorts edits in
ascending start order and builds the output in a single forward
pass, so update the comment to match.
@jeduden
jeduden requested a review from Copilot April 25, 2026 08:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Implements auto-fix support for MDS034 (markdown flavor validation), allowing mdsmith fix to rewrite several unsupported Markdown constructs based on the configured flavor.

Changes:

  • Added a byte-range edit pipeline to remove/transform six fixable feature types (e.g., heading IDs, strikethrough, task lists, super/subscript, bare URLs).
  • Refactored Rule.Fix() to compose GitHub Alerts marker stripping with the new byte-range feature fixes (including re-parsing when alerts are stripped).
  • Added unit tests and rule fixtures (golden “fixed/” outputs) for CommonMark auto-fix behavior.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
plan/86_markdown-flavor-validation.md Marks the plan as complete and records the implemented fix scope.
internal/rules/markdownflavor/rule.go Composes alert stripping with byte-range fixes, re-parsing as needed.
internal/rules/markdownflavor/fix.go Implements edit collection + single-pass application for fixable features.
internal/rules/markdownflavor/fix_test.go Adds targeted unit coverage for each fix plus composition cases.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-task-list.md Golden fixed output for task-list marker removal under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-superscript.md Golden fixed output for superscript marker removal under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-subscript.md Golden fixed output for subscript marker removal under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-strikethrough.md Golden fixed output for strikethrough marker removal under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-heading-id.md Golden fixed output for heading ID attribute removal under CommonMark.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-bare-url.md Golden fixed output for bare URL wrapping under CommonMark.
PLAN.md Updates the plan index to reflect completion of plan 86.

Comment thread internal/rules/markdownflavor/fix.go
@jeduden jeduden added queue Add to a PR to enqueue it queue:active Applied automatically when a PR is in an active batch labels Apr 25, 2026
@jeduden

jeduden commented Apr 25, 2026

Copy link
Copy Markdown
Owner Author

🟢 Merge Queue — picked up

This PR is in the queue and will be batched with other queue-labelled PRs.

Next: No action needed — you'll get another comment when CI starts on the batch. View merge queue run.

@jeduden jeduden added queue Add to a PR to enqueue it and removed queue Add to a PR to enqueue it queue:active Applied automatically when a PR is in an active batch labels Apr 25, 2026
@jeduden

jeduden commented Apr 25, 2026

Copy link
Copy Markdown
Owner Author

Merge Queue — requeued

The merge queue hit an error while processing this PR:

batch creation failed: merge-queue-action must run in a checked-out git working tree — add an 'actions/checkout' step with 'fetch-depth: 0' and a pushable token before this action.

View merge queue run.

Next: No action needed — the queue will retry on the next tick.

@jeduden jeduden added queue:active Applied automatically when a PR is in an active batch and removed queue Add to a PR to enqueue it labels Apr 25, 2026
@jeduden

jeduden commented Apr 25, 2026

Copy link
Copy Markdown
Owner Author

🟢 Merge Queue — picked up

This PR is in the queue and will be batched with other queue-labelled PRs.

Next: No action needed — you'll get another comment when CI starts on the batch. View merge queue run.

@jeduden jeduden removed the queue:active Applied automatically when a PR is in an active batch label Apr 25, 2026
@jeduden

jeduden commented Apr 25, 2026

Copy link
Copy Markdown
Owner Author

Merge Queue — requeued

The merge queue hit an error while processing this PR:

batch creation failed: merge-queue-action must run in a checked-out git working tree — add an 'actions/checkout' step with 'fetch-depth: 0' and a pushable token before this action.

View merge queue run.

Next: No action needed — the queue will retry on the next tick.

@jeduden jeduden added queue Add to a PR to enqueue it queue:active Applied automatically when a PR is in an active batch and removed queue Add to a PR to enqueue it labels Apr 25, 2026
@jeduden

jeduden commented Apr 25, 2026

Copy link
Copy Markdown
Owner Author

🟢 Merge Queue — picked up

This PR is in the queue and will be batched with other queue-labelled PRs.

Next: No action needed — you'll get another comment when CI starts on the batch. View merge queue run.

@jeduden jeduden added queue:active Applied automatically when a PR is in an active batch and removed queue Add to a PR to enqueue it labels Apr 26, 2026
@jeduden

jeduden commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

🟢 Merge Queue — picked up

This PR is in the queue and will be batched with other queue-labelled PRs.

Next: No action needed — you'll get another comment when CI starts on the batch. View merge queue run.

@jeduden jeduden added queue Add to a PR to enqueue it and removed queue:active Applied automatically when a PR is in an active batch labels Apr 26, 2026
@jeduden

jeduden commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

Merge Queue — requeued

The merge queue hit an error while processing this PR:

batch creation failed: git push origin merge-queue/batch-168-1777185119:refs/heads/merge-queue/batch-168-1777185119 failed (exit 128): fatal: could not read Username for 'https://github.com': terminal prompts disabled

View merge queue run.

Next: No action needed — the queue will retry on the next tick.

@jeduden jeduden added queue:active Applied automatically when a PR is in an active batch and removed queue Add to a PR to enqueue it labels Apr 26, 2026
@jeduden

jeduden commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

🟢 Merge Queue — picked up

This PR is in the queue and will be batched with other queue-labelled PRs.

Next: No action needed — you'll get another comment when CI starts on the batch. View merge queue run.

@jeduden jeduden removed the queue:active Applied automatically when a PR is in an active batch label Apr 26, 2026
@jeduden

jeduden commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

Merge Queue — requeued

The merge queue hit an error while processing this PR:

batch creation failed: git push origin merge-queue/batch-169-1777185136:refs/heads/merge-queue/batch-169-1777185136 failed (exit 128): fatal: could not read Username for 'https://github.com': terminal prompts disabled

View merge queue run.

Next: No action needed — the queue will retry on the next tick.

@jeduden jeduden added queue Add to a PR to enqueue it queue:active Applied automatically when a PR is in an active batch and removed queue Add to a PR to enqueue it labels Apr 26, 2026
@jeduden

jeduden commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

🟢 Merge Queue — picked up

This PR is in the queue and will be batched with other queue-labelled PRs.

Next: No action needed — you'll get another comment when CI starts on the batch. View merge queue run.

@jeduden jeduden removed the queue:active Applied automatically when a PR is in an active batch label Apr 26, 2026
@jeduden

jeduden commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

Merge Queue — requeued

The merge queue hit an error while processing this PR:

batch creation failed: git push origin merge-queue/batch-169-1777185153:refs/heads/merge-queue/batch-169-1777185153 failed (exit 128): fatal: could not read Username for 'https://github.com': terminal prompts disabled

View merge queue run.

Next: No action needed — the queue will retry on the next tick.

@jeduden jeduden added queue Add to a PR to enqueue it queue:active Applied automatically when a PR is in an active batch labels Apr 26, 2026
@jeduden

jeduden commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

🟢 Merge Queue — picked up

This PR is in the queue and will be batched with other queue-labelled PRs.

Next: No action needed — you'll get another comment when CI starts on the batch. View merge queue run.

@jeduden jeduden removed the queue Add to a PR to enqueue it label Apr 26, 2026
@jeduden

jeduden commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

Merge Queue — requeued

The merge queue hit an error while processing this PR:

batch creation failed: git push origin merge-queue/batch-169-1777185169:refs/heads/merge-queue/batch-169-1777185169 failed (exit 128): fatal: could not read Username for 'https://github.com': terminal prompts disabled

View merge queue run.

Next: No action needed — the queue will retry on the next tick.

@jeduden

jeduden commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

🟢 Merge Queue — picked up

This PR is in the queue and will be batched with other queue-labelled PRs.

Next: No action needed — you'll get another comment when CI starts on the batch. View merge queue run.

claude added 3 commits April 26, 2026 13:56
Adds byte-range edit pipeline to markdown-flavor (MDS034) Fix so
heading IDs, strikethrough, task lists, superscript, subscript, and
bare-URL autolinks are auto-fixed when the configured flavor does
not support them. Fix() now runs the existing GitHub Alert handler
first (line-based, handles lazy continuation), then dispatches to
the new fixByteRangeFeatures pass which collects edits from the
dual-parser AST and the bare-URL detector and applies them in
reverse start order.

Six fixed/ fixtures and 14 unit tests cover each feature plus a
combined case (strikethrough + heading ID + bare URL on adjacent
lines) that exercises reverse-order edit composition.
Resolves four review comments on PR #169:

- delimiterPairEdits was off-by-one for wrappers with nested inline
  markup (`~~*bold*~~` would have produced `~bold~`); rewrite to
  accept only single-Text-child wrappers and decline gracefully when
  emphasis, links, or breaks appear inside, leaving the diagnostic
  for manual resolution.
- Fix() no longer returns early after stripping GitHub Alert markers.
  After alerts are removed it re-parses the rewritten source and runs
  the byte-range pipeline on the new AST so heading IDs / strike-
  through / bare URLs in alert-bearing docs get fixed in one call.
- applyEdits now builds the output in a single ascending-order pass
  with a pre-sized buffer (was O(n*m) due to per-edit slice copies).
- Add tests covering: alerts + bare URL composition, nested-inline
  rejection (single-child and multi-sibling), FlavorAny no-op, and
  the supports-branch returns in dualNodeEdits for super/sub.

Also drops dead defensive code (Extra type assertion, marker bounds
checks, taskCheckBox guards, applyEdits overlap check) per repo
guidance to trust framework guarantees, lifting fix.go to 100%
statement coverage and addressing the codecov patch gate.
Address PR #169 review nit: TestRuleFixMultipleFeaturesOnOneLine's
doc comment described "reverse-order edit application", which was
true of the prior implementation. applyEdits now sorts edits in
ascending start order and builds the output in a single forward
pass, so update the comment to match.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Implements the remaining auto-fix pipeline for rule MDS034 (markdown-flavor) so mdsmith fix can rewrite certain unsupported Markdown constructs into flavor-compatible syntax (instead of only emitting diagnostics), while preserving correct AST byte offsets after alert-marker stripping.

Changes:

  • Added a byte-range edit pipeline (fix.go) to auto-fix six unsupported feature types (heading IDs, strikethrough, task lists, superscript, subscript, bare-URL autolinks).
  • Refactored Rule.Fix() to compose GitHub Alerts marker stripping with the byte-range fix pass, including a re-parse step when the alert rewrite changes bytes.
  • Added unit tests and folder-based golden fixed/ fixtures validating fix output.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
plan/86_markdown-flavor-validation.md Marks the plan complete and records the now-implemented fix surface area.
internal/rules/markdownflavor/rule.go Updates Fix() to apply alert stripping + reparse + byte-range feature fixes in one call.
internal/rules/markdownflavor/fix.go Introduces edit collection + applyEdits infrastructure and concrete fix implementations for six features.
internal/rules/markdownflavor/fix_test.go Adds focused unit tests for each fixer and composition/edge-case behavior.
internal/rules/MDS034-markdown-flavor/fixed/commonmark-*.md Adds golden outputs for Fix() under CommonMark flavor for each newly fixable feature.
PLAN.md Updates the plan index row for plan 86 to ✅.

@jeduden

jeduden commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

🟢 Merge Queue — picked up

This PR is in the queue and will be batched with other queue-labelled PRs.

Next: No action needed — you'll get another comment when CI starts on the batch. View merge queue run.

@jeduden

jeduden commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

🔵 Merge Queue — CI running

Merged into batch branch merge-queue/batch-169-1777212736. View CI run.

Next: No action needed — you'll be notified when CI completes.

@jeduden

jeduden commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

Merge Queue — merged

This PR landed on main via commit c323541. CI run that validated the merge.

Next: Done — nothing more to do here.

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