Skip to content

Read Carried Markdown Through markdown-it-py and Delete carried_text - #3431

Merged
ptr727 merged 8 commits into
developfrom
markdown-it-shared-reader
Oct 24, 2026
Merged

ptr727 merged 8 commits into
developfrom
markdown-it-shared-reader

Conversation

@ptr727

@ptr727 ptr727 commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

The follow-up #3416 named: the audit, scripts/carry.py, scripts/build_dist.py, and scripts/canonical_review.py now split a document at headings and code blocks markdown-it-py reads, and spec/carried_text.py, the last hand-written fence reader they shared, is gone.

What Changes

One Reader, Now a Parser

  • spec/fidelity_text.py replaces spec/carried_text.py. It parses block structure only, CommonMark plus tables. headings() reads top-level ATX headings, code_blocks() and code_lines() read fenced and indented code at any depth, and sections() is the one place a level-two region's extent is decided. section_span(), extract_section(), strip_sections(), and canonical_review.split_markdown() all slice from it.
  • normalize() and the two workflow-YAML masks it applies, _ACTION_PIN and _JOB_NEEDS, move into the same module unchanged. The audit, spec/audit_markdown.py, and scripts/carry.py all call normalize(), so one shared home is what the masks need.
  • The audit: spec/audit.py and spec/audit_markdown.py import from the new module. _atx_headings() and unfenced_text() read through it too, so presence checks and region extraction split a document alike.
  • scripts/carry.py: h2_headings() and section_span() call the shared reader. fence_step() is gone.
  • scripts/canonical_review.py: split_markdown() cuts regions at the shared reader's level-two headings.
  • scripts/build_dist.py: include markers and heading bodies read code lines and headings from the shared reader. A body leaving a fence open is a fence the parser reads as unclosed. _MAX_INDENT stays only for a marker line itself.

Running Them

  • scripts/carry.py, scripts/build_dist.py, and scripts/canonical_review.py each declare markdown-it-py>=4 in a PEP 723 block, in spec/audit.py's form.
  • Every caller now runs them as uv run --no-project --script:
    • the validate action and canonical-review-sweep.yml, which now sets up uv rather than Python;
    • host-setup/menu.sh and host-setup/menu.ps1, whose plain-Python helpers had no caller left and are removed;
    • RESYNC.md, STANDUP.md, OPERATIONS.md, scripts/README.md, docs/token-efficiency-plan.md, and the local-strict-review and skill-lifecycle skills, regenerated;
    • each script's own usage text and the commands its messages print.
  • Two plain-python3 importers stay safe. scripts/skills_install.py imports build_dist, and scripts/handoff.py imports carry. Both modules import the shared reader lazily, on the path that reads a region, so neither importer loads markdown-it-py.

Tests

  • tests/test_build_dist.py's check that importing build_dist loads no carried_text now imports skills_install in a fresh interpreter and checks that neither fidelity_text nor markdown_it loads. That is the invariant the plain-python3 install path relies on. tests/test_carry.py gains the same check for handoff.
  • The two per-line cache tests are gone, since nothing reads per line any more. The test that the accessor adds spec/ to sys.path once stays.
  • test_an_indented_heading_is_a_boundary_as_it_is_to_the_audit asserted the old reader's quirk, a four-space ## line read as a heading. It now asserts what the parser reads: three spaces open a heading, and four open an indented code block.
  • tests/test_fidelity_text.py covers the shared reader on constructed documents, a quoted or listed heading and a fence ending a file with no final newline among them. tests/import_probe.py holds the import probe both laziness tests share.
  • CI already installs tests/requirements.txt, which carries markdown-it-py, before the suite runs.

Behavior

  • The full audit sweep, every cataloged repository plus the fleet membership check, ran at develop 9f19b2a before the change and on this branch after it, both against the same hub main. The two outputs match line for line apart from the run stamp.

  • uv run --no-project --script scripts/canonical_review.py list and status print byte-identical output before and after, so every review unit key and digest is unchanged.

  • uv run --no-project --script scripts/build_dist.py --check reports the generated trees current, and a no-flag run rewrote nothing beyond the two edited skills' mirrors.

  • A probe compared the old and new region readers over every local Markdown file, heading boundaries, extract_section, and strip_sections alike. The fleet's own documents read identically. The only differences are in vendored third-party documents and are the parser being right where the line reader was not: a fence indented four spaces inside a list item, a fence whose closer is indented differently from its opener, and a ## inside an HTML comment block.

Local Review

local-strict-review passes ran at the frontier tier over the whole branch diff, each recorded before the next commit and attested after each push. The fixes they drove before the pull request opened:

  • A fence left open at a file with no final newline read as closed, so build_dist.py stopped refusing that include body. The last content line now counts.
  • A heading quoted in a blockquote or nested in a list item opened a region. Only top-level headings do now, which no tracked document's split depends on.
  • The rule for where a region ends was written three times. sections() now holds it.
  • build_dist.py rebuilt a code-line set the shared reader already returns.
  • The code_blocks() docstring claimed every region copier refuses an open fence. Only the include fill does, and it now says so. The heading_body() docstring names where an include body ends differently from a fidelity region.
  • scripts/README.md, host-setup/README.md, and the menu comments still described plain-Python paths.
  • The shared import probe moved out of a test module into tests/import_probe.py.

After the Pull Request Opened

The third pass, after the edit budget for the opening push was spent, and Copilot's round on that head raised the first two points below. Later passes raised the rest, and the last pass, on the current head, raised nothing:

  • An include body holding a fence its blockquote or list item ends, with no closing line, is refused, which the old stepper did not do. Filling one was tried and reverted. An end marker indented to a list item's content continues that item past the blank line the fill writes, so the fence swallows the marker on the next scan. Refusing is the loud outcome, no tracked source holds such a fence, and tests pin the list item and blockquote cases. The docstrings now give that reason.
  • The audit_markdown.py heading docstrings read as if only fenced headings are skipped. _atx_headings() now states that it reads top-level # headings only, and the readers built on it point there.
  • "which the fidelity checks read with too" read awkwardly in three docstrings, and now says "also use".
  • The laziness tests imported build_dist and carry directly. They now import skills_install and handoff, the real plain-python3 importers.
  • _unindented()'s docstring said a line indented past three spaces is code or a paragraph's continuation, which is false in a list item. It now says the bound is held on the line's own indentation in every container.
  • heading_body()'s docstring, and the skill-lifecycle skill, said a body ends at the next heading at its level or above. They now say a top-level # heading, since the shared reader reads a setext heading and one in a blockquote or list item as content.

Pre-Existing Findings, Filed

Pre-Existing Findings, Not Filed

  • --check sentence-length reports sentences this branch touched only to rename a command or a path: .agents/skills/skill-lifecycle/SKILL.md:18 and :19 and their generated copies, OPERATIONS.md:40, RESYNC.md:77, host-setup/README.md:119, host-setup/menu.ps1:252, host-setup/menu.sh:394 and :449, scripts/README.md:7, :381, and :385, scripts/build_dist.py:313 and the comment it moved into heading_body(), and scripts/carry.py:420. Class: style, on prose this change did not write.

Deferred

  • Read validate.py's Markdown and the README Link Definitions Through markdown-it-py #3426 covers spec/validate.py's own Markdown readers and the references() against _LINK_DEF split in spec/audit_markdown.py. repo-config/configure.sh runs spec/resolve_description.py, which imports validate, under a probed Python 3.7+, and reading link targets from tokens changes what the carried-link check sees. Each needs its own comparison, so this change stops at deleting carried_text.py.

Verification

Each command below ran in the worktree on this branch.

  • uv run --no-project --with-requirements tests/requirements.txt python -m unittest discover -s tests at the final head -> Ran 2872 tests ... OK (skipped=7)
  • uv run --no-project --script spec/audit.py, before and after -> identical apart from the run stamp, rerun after the review fixes that touched region code. One downstream repository's own main moved between runs, which only its header line shows.
  • uv run --no-project --script scripts/build_dist.py --check -> Generated skill distributions are current.
  • uv run --no-project --script scripts/canonical_review.py list and status, before and after -> byte-identical
  • uvx ruff@latest format --check . and uvx ruff@latest check . -> clean
  • uvx mypy@latest -> Success: no issues found in 76 source files
  • python3 scripts/repo_gate.py -> composite-actions, eol, eol-coverage, and sha-pin report 0 issues
  • uvx --from actionlint-py actionlint .github/workflows/canonical-review-sweep.yml -> clean
  • npx markdownlint-cli2 over the changed Markdown -> 0 issues
  • shellcheck host-setup/menu.sh -> clean, and host-setup/menu.ps1 parses with no errors under pwsh
  • python3 spec/validate.py -> Spec validation OK
  • The prose gate over the diff reports only comment-added lines, which is why this pull request carries the comments label. Most are comments that moved with the code they describe.

🤖 Generated with Claude Code

ptr727 and others added 3 commits October 24, 2026 09:44
The audit, carry.py, build_dist.py, and canonical_review.py now split a
document at the headings and code blocks markdown-it-py reads, through
spec/fidelity_text.py, which replaces spec/carried_text.py and also holds
normalize() and its workflow-YAML masks.

The three scripts declare markdown-it-py inline and every caller runs
them through uv run --no-project --script. build_dist and carry import
the reader lazily, so skills_install.py and handoff.py, which import
them under a plain python3, load no third-party library.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A heading quoted in a blockquote or nested in a list item no longer
opens a region, since neither opens a section of the document. A fence
left open at a file with no final newline now reads as open, so
build_dist.py refuses that body again.

The import probe both laziness tests share moves to tests/import_probe.py,
and the READMEs and menu comments that still described a plain-Python
path now describe uv.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fidelity_text.sections() returns each level-two heading with the line
that ends its region, and section_span, strip_sections, and
canonical_review.split_markdown all slice from it. build_dist.py takes
its code lines from the shared reader, and its docstring names where
an include body ends differently from a fidelity region.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings October 24, 2026 17:29
@ptr727 ptr727 added the comments Permits the comment lines the pull request adds or edits, which the prose gate otherwise refuses label Oct 24, 2026
@ptr727

ptr727 commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head c83c8850c4f93bc4fa0e1ac3a0b4d3b68e569dd3, the content this pull request carries at that commit against develop, and it recorded 2 findings.

@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

heading_texts() and ordered_headings() now say a quoted or listed
heading is content. The open-fence refusal names every container,
blockquote included, and a test pins that case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

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.

🟡 Changes recommended

Unresolved moderate findings remain in fence handling and the lazy-import regression test, along with documentation nits.

2 open issues
What changed in this PR

This pull request replaces the shared hand-written Markdown reader with a markdown-it-py-based parser, updates dependent tooling and callers to use it through uv, and removes spec/carried_text.py.

Changes:

  • Adds spec/fidelity_text.py for shared headings, code blocks, sections, and normalization.
  • Updates audit, carry, distribution, canonical-review tooling, workflows, menus, documentation, and generated skill mirrors.
  • Adds parser and lazy-import tests while preserving plain-Python importer behavior.

Review findings:

  • [P1] Moderate — scripts/build_dist.py: unclosed fences that end with a blockquote or list container should not be rejected; add the requested regression test.
  • [P2] Nit — scripts/build_dist.py, scripts/canonical_review.py, and scripts/carry.py: correct the extra “with” in the changed docstrings.
  • [P2] Nit — spec/audit_markdown.py: document that heading checks only inspect top-level headings.
  • [P2] Nit — spec/fidelity_text.py: align the fence-refusal explanation with container boundaries.
  • [P2] Moderate — tests/test_carry.py: probe handoff to verify the production lazy-import path.
File Reviewed change
tests/​test_fidelity_text.py Tests shared Markdown parsing and section behavior.
tests/​test_carry.py Tests carry’s lazy Markdown-reader import behavior.
tests/​test_canonical_review.py Updates canonical-review command expectations.
tests/​test_build_dist.py Tests parser-based generation and lazy imports.
tests/​import_probe.py Provides fresh-interpreter import checks.
STANDUP.md Updates carry commands to use uv.
spec/​fidelity_text.py Adds the shared Markdown parser and fidelity helpers.
spec/​carried_text.py Removes the obsolete hand-written reader.
spec/​audit.py Imports fidelity helpers from the new reader.
spec/​audit_markdown.py Uses the shared reader for headings and fenced content.
scripts/​README.md Documents dependencies and updated commands.
scripts/​carry.py Uses lazy shared-reader access for section operations.
scripts/​canonical_review.py Uses shared section boundaries and adds script metadata.
scripts/​build_dist.py Uses shared code-block parsing and adds script metadata.
RESYNC.md Updates resync carry commands to use uv.
OPERATIONS.md Updates local build and canonical-review commands.
host-setup/​README.md Documents lazy uv requirements for menu actions.
host-setup/​menu.sh Replaces Python menu execution with uv script execution.
host-setup/​menu.ps1 Replaces Python menu execution with uv script execution.
docs/​token-efficiency-plan.md Updates skill regeneration instructions.
.github/​workflows/​canonical-review-sweep.yml Sets up uv and runs canonical review through it.
.github/​skills/​skill-lifecycle/​SKILL.md Updates the generated GitHub skill mirror.
.github/​skills/​local-strict-review/​SKILL.md Updates the generated GitHub review mirror.
.github/​actions/​validate/​action.yml Runs validation commands through uv.
.claude-plugin/​fleet-skills/​skills/​skill-lifecycle/​SKILL.md Updates the generated Claude skill mirror.
.claude-plugin/​fleet-skills/​skills/​local-strict-review/​SKILL.md Updates the generated Claude review mirror.
.claude-plugin/​fleet-skills/​.source-digests/​skill-lifecycle Refreshes the generated skill digest.
.claude-plugin/​fleet-skills/​.source-digests/​local-strict-review Refreshes the generated skill digest.
.agents/​skills/​skill-lifecycle/​SKILL.md Updates the authored skill lifecycle commands.
.agents/​skills/​local-strict-review/​SKILL.md Updates the authored canonical-review commands.

Review effort: Lite

Comment thread scripts/build_dist.py Resolved
Comment thread spec/audit_markdown.py Resolved
@codecov

codecov Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.76%. Comparing base (9f19b2a) to head (9275528).
⚠️ Report is 3 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #3431      +/-   ##
===========================================
- Coverage    80.81%   80.76%   -0.05%     
===========================================
  Files           23       23              
  Lines         8859     8839      -20     
===========================================
- Hits          7159     7139      -20     
  Misses        1700     1700              
Flag Coverage Δ
python-3.13 80.76% <100.00%> (-0.05%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 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.

_atx_headings() states that it reads top-level `#` headings only, and
the readers built on it point there. The marker indentation comment and
the menu prerequisite comment now say what they mean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head c872b98989b50e270da4cfb1e6a80056a8241e5c, the content this pull request carries at that commit against develop, and it recorded 1 finding.

ptr727 and others added 2 commits October 24, 2026 11:01
build_dist.py refuses only a top-level fence left open, since the blank
line the fill writes before the end marker ends a blockquote or a list
item, and a fence it holds, in the destination too. CodeBlock records
whether a container holds the block.

The laziness tests now import skills_install and handoff, the real
plain-python3 importers, rather than the modules they import.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An end marker indented to a list item's content continues that item
past the blank line the fill writes, so a fence the item leaves open
swallows the marker on the next scan. build_dist.py again refuses every
fence left open, and tests pin the list item and blockquote cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head 6d1efc6e595636b77e3a4629fe4d66f53e64d346, the content this pull request carries at that commit against develop, and it recorded 2 findings.

@ptr727

ptr727 commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

Answers to the findings with no thread in Copilot's round on c83c885 (3), #3431 (review)

  1. scripts/build_dist.py, scripts/canonical_review.py, and scripts/carry.py docstrings, "correct the extra 'with'": Fixed in 6262678. Each now says the fidelity checks "also use" the shared reader.
  2. spec/fidelity_text.py, "align the fence-refusal explanation with container boundaries": Fixed in 6d1efc6. The code_blocks() docstring now says a fence its container or the document ends can run on into whatever follows it once copied, and heading_body() gives the list item case that keeps the refusal, per the declined thread on scripts/build_dist.py.
  3. tests/test_carry.py, "probe handoff to verify the production lazy-import path": Fixed in 6262678. The laziness tests now import handoff and skills_install in a fresh interpreter, rather than carry and build_dist.

heading_body() and the skill-lifecycle skill now say a body ends at the
next top-level `#` heading, since a setext heading and one in a
blockquote or list item are content to the shared reader. The marker
indentation docstring no longer claims how CommonMark reads such a line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head 92755285296367cd800f9efacc29fa8042756a18, the content this pull request carries at that commit against develop, and it recorded 0 findings.

@ptr727
ptr727 merged commit d3d75dc into develop Oct 24, 2026
13 checks passed
@ptr727
ptr727 deleted the markdown-it-shared-reader branch October 24, 2026 19:00
ptr727 added a commit that referenced this pull request Oct 24, 2026
…xes to Main (#3434)

## Summary

Promotes the pull requests merged into develop since release 2.0.1158.

- [#3422](#3422):
`drive-pr` and `backlog-burndown` have every draft of a pull request
body go in a file named for its repository and branch. Two lanes sharing
one `pr-body.md` had published each other's drafts.
- [#3423](#3423): in
`pr_review.py`, an earlier partial round outranks a head round reading
`unknown`, printing `coverage=PARTIAL` and exiting 42.
- [#3427](#3427): the
prose gate takes run-block heredoc bodies from its patched Bash lexer's
heredoc tokens and lexes each alone, so an apostrophe in a body no
longer hides later comments. Inline Markdown comments are numbered with
code spans masked. The gate's size ceiling moves from 1800 to 1840
lines, as the maintainer decided on that pull request. Two edge cases
are deferred to #3429 and #3430, and a pre-existing one is filed as
#3428.
- [#3431](#3431): deletes
`spec/carried_text.py` and reads carried Markdown regions through
markdown-it-py in the new `spec/fidelity_text.py`. `carry.py`,
`build_dist.py`, and `canonical_review.py` carry PEP 723 metadata, and
every caller runs them as `uv run --no-project --script`. The full audit
sweep is identical before and after. The `validate.py` remainder is
#3426, and a pre-existing include-marker gap is #3432.
- [#3433](#3433):
`pr-review-conduct` and `scripts/README.md` say exactly when the
earlier-partial path exits 42, following #3423.

Closes #3412
Closes #3413
Closes #3414
Closes #3425

## Constituent coverage

Each change this promotion carries had coverage on its own pull request
into develop, at its merged head:

| Pull request | Merged head | Coverage |
| --- | --- | --- |
| [#3422](#3422) |
`b645b429` | attested local pass, and a Copilot table naming exactly the
changed files, `coverage=table` |
| [#3423](#3423) |
`3f893b65` | attested local pass, and a carried Copilot table,
`coverage=carried:table` |
| [#3427](#3427) |
`2511b62b` | attested local pass, and a carried Copilot table,
`coverage=carried:table` |
| [#3431](#3431) |
`92755285` | attested local pass, `coverage=local` |
| [#3433](#3433) |
`cceba3af` | attested local pass, `coverage=local` |

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comments Permits the comment lines the pull request adds or edits, which the prose gate otherwise refuses

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants