Skip to content

Widen Undeclared-Heading Advisory to copilot-instructions.md - #900

Merged
ptr727 merged 5 commits into
developfrom
fix/523-undeclared-heading-scope
Aug 22, 2026
Merged

Widen Undeclared-Heading Advisory to copilot-instructions.md#900
ptr727 merged 5 commits into
developfrom
fix/523-undeclared-heading-scope

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Summary

Extends the undeclared-H2 advisory (spec/section-model.md) to scan .github/copilot-instructions.md, not just AGENTS.md and GOVERNANCE.md. That gap is why ptr727/PhotoCleaner's repo-specific sections went undetected and duplicated a later OPERATIONS.md.

What this does and does not do

Re-measured against current develop before starting: nothing has touched spec/audit.py, spec/section-model.md, or spec/files.json since the most recent comment on #523, so the gap it describes is current, not stale.

  • Scope, widened: UNDECLARED_HEADING_SCANNED now includes .github/copilot-instructions.md, which already carries a declared section list in files.json.
  • Destination attribution, deliberately not attempted: neither OPERATIONS.md's six headings nor ARCHITECTURE.md's are declared as data anywhere today, and PhotoCleaner's actual headings (Development Workflow, Command Line Usage) matched neither name, so a heading-name match would have missed the exact case that motivated the issue. The finding stays structural — it names the heading as undeclared and points at section-model.md's destinations for a human to judge — consistent with the issue's own warning against a content-similarity heuristic. Declaring a heading-to-destination vocabulary (issue open question 2) and reaching ARCHITECTURE.md (open question 3) stay open.
  • Fence-awareness fix, bundled: the H2 scan wasn't using the existing unfenced_text helper, so a ## line inside a fenced code sample could misread as a real heading. Extracted into undeclared_h2_headings() and fixed while touching this code, since expanding scope to a file more likely to carry fenced examples made the gap more likely to bite.
  • Tests: no offline coverage existed for this advisory at all; added 6 table-driven --selftest cases (scope, case-insensitivity, H2-only, the fence fix, and the new copilot-instructions.md case).

Verification

  • python3 spec/audit.py --selftestSELFTEST PASS
  • python3 spec/validate.pySpec validation OK
  • python3 scripts/prose_lint.py --diff origin/develop spec/audit.py spec/section-model.md → clean

Closes#523.

The undeclared-H2 advisory (spec/section-model.md) only scanned
AGENTS.md and GOVERNANCE.md, so a repo's own content sitting in
.github/copilot-instructions.md was invisible to it, which is how
ptr727/PhotoCleaner's local sections went undetected and duplicated
a later OPERATIONS.md (#523).
Extend UNDECLARED_HEADING_SCANNED to include copilot-instructions.md,
which already carries a declared section list in files.json. Do not
attempt to name a destination file for an undeclared heading: neither
OPERATIONS.md's six headings nor ARCHITECTURE.md's are declared as
data anywhere, and PhotoCleaner's actual headings ("Development
Workflow", "Command Line Usage") matched neither, so a heading-name
match would have missed the case that motivated this. The finding
stays structural, naming the heading as undeclared and pointing at
section-model.md's destinations for a human to judge, per #523's own
warning against a content-similarity heuristic.
Also make the H2 scan fence-aware via the existing unfenced_text
helper, extracted the scan into undeclared_h2_headings() so it is
unit-tested, and added 6 selftest cases covering the new scope, the
fence fix, and the existing AGENTS.md/GOVERNANCE.md behavior.
CopilotAI lite review requested due to automatic review settings August 21, 2026 23:41
@coderabbitai

coderabbitaiBot commented Aug 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a7ba049c-b252-4b8c-81b4-2718c85495a1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Scan copilot-instructions.md for undeclared H2 headings (fence-aware)

🐞 Bug fix✨ Enhancement🧪 Tests📝 Documentation🕐 20-40 Minutes

Grey Divider

AI Description

• Extend undeclared-H2 advisory to also scan ".github/copilot-instructions.md".
• Make H2 detection fence-aware so code blocks can’t create false headings.
• Add table-driven selftests to cover scope, casing, H2-only, and fencing behavior.
Diagram

graph TD
A["spec/section-model.md"] --> B["spec/audit.py"] --> C["UNDECLARED_HEADING_SCANNED"] --> D["Carried docs (AGENTS/GOV/.github)"]
B --> E["undeclared_h2_headings()"] --> F["unfenced_text()"] --> G["DRIFT advisory findings"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use a Markdown parser (AST) for heading extraction
  • ➕ More robust handling of edge cases (nested structures, atypical fencing, indentation)
  • ➕ Reduces reliance on line-prefix heuristics
  • ➖ Adds dependency/complexity for a lightweight advisory
  • ➖ May be overkill given the limited H2-only scope and existing unfenced_text helper
2. Declare OPERATIONS/ARCHITECTURE heading vocab and map to destinations
  • ➕ Could make the advisory more actionable by suggesting a likely target document
  • ➕ Moves ambiguity resolution into data/config rather than heuristics
  • ➖ Requires curating and maintaining a heading-to-destination vocabulary
  • ➖ Still imperfect when repos use differently worded headings (the motivating case)
3. Broaden scan to additional carried docs beyond the current set
  • ➕ Catches undeclared sections wherever they appear, increasing coverage
  • ➖ May increase noise by flagging legitimate repo-local sections in docs not governed by the model
  • ➖ Needs careful scoping to avoid undermining the advisory’s intent

Recommendation: The PR’s approach is appropriate: widen scope only to a file already participating in the declared-section system, keep the finding structural (undeclared heading) rather than guessing destinations, and harden the extractor against fenced-code false positives. Consider an AST-based parser only if heading parsing edge cases continue to accumulate, and consider destination attribution only after destinations/headings are first modeled as data.

Files changed (2) +77 / -6

Enhancement (1) +75 / -6
audit.pyExpand undeclared-H2 scan scope and add fence-aware heading extractor + selftests+75/-6

Expand undeclared-H2 scan scope and add fence-aware heading extractor + selftests

• Adds UNDECLARED_HEADING_SCANNED to include .github/copilot-instructions.md in the undeclared-heading advisory. Extracts heading detection into undeclared_h2_headings() using unfenced_text() to ignore fenced code blocks, and adds six table-driven selftest cases covering scope and parsing behavior.

spec/audit.py

Documentation (1) +2 / -0
section-model.mdDocument copilot-instructions.md inclusion and rationale for structural-only advisory+2/-0

Document copilot-instructions.md inclusion and rationale for structural-only advisory

• Updates the section model documentation to state that the undeclared-heading advisory also scans .github/copilot-instructions.md. Clarifies that the advisory does not attempt to infer a destination document for undeclared headings due to missing destination vocab data and heading-name mismatch risks.

spec/section-model.md

CopilotAI 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.

🟢 Approval recommended

The scope expansion and fence-aware fix are low-risk and come with selftest coverage; the remaining feedback is a minor helper-contract tightening.

Pull request overview

Extends the undeclared level-two heading advisory in the spec audit to also scan .github/copilot-instructions.md, and makes the heading scan fence-aware to avoid false positives from fenced code samples.

Changes:

  • Widened the undeclared-heading advisory scope to include .github/copilot-instructions.md.
  • Refactored the advisory into undeclared_h2_headings() and made it ignore fenced code blocks via unfenced_text().
  • Added table-driven --selftest coverage for the advisory behavior (scope, casing, H2-only, fence handling).
File summaries
FileDescription
spec/section-model.mdDocuments that the undeclared-heading advisory also applies to .github/copilot-instructions.md and clarifies why it remains structural-only.
spec/audit.pyImplements the widened scope, adds a fence-aware helper for undeclared H2 headings, and adds selftests covering the new behavior.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadspec/audit.py Outdated
Copilot review: the docstring said the function reads lowercased
declared, but it trusted the caller to have already normalized it.
Normalize inside the helper so the contract holds for any caller,
plus a selftest case with an un-normalized declared set.
Also parenthesize the implicitly-concatenated string literal in the
new selftest fixture (ruff ISC004), caught by CI, not by the local
ruff-less environment this was authored in.
@qodo-code-review

qodo-code-reviewBot commented Aug 21, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (1)📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Docstring wraps sentences across lines✗ Dismissed📜 Skill insight✧ Quality
Description
The new undeclared_h2_headings() docstring wraps mid-sentence across multiple lines, and mixes
multiple sentences/clauses on a single line. This violates the one-sentence-per-line comment
structure rule.
Code

spec/audit.py[R455-458]

+ Scoped to `## ` only: the section model's unit is the H2, and an H1 title or a nested H3 is not itself a+ section this check judges. Fence-aware via unfenced_text, so a `## ` line inside a fenced code sample -+ documenting the heading syntax itself, or a `##`-prefixed shell comment - is not misread as a real+ heading; per unfenced_text's own docstring, a checker left fence-blind is a document read two ways.
Relevance

●●● Strong

Recent prose-review precedent accepts rewriting dense explanatory prose for grammatical clarity and
accuracy.

PR-#555
PR-#621

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2826725 requires one sentence per line and forbids mid-sentence wraps. The
undeclared_h2_headings() docstring breaks a sentence across multiple lines and combines multiple
sentences/clauses on the same line.

spec/audit.py[452-459]
Skill: comment-and-doc-style

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The `undeclared_h2_headings()` docstring is wrapped across lines mid-sentence.
## Issue Context
Multi-line comments/docstrings must be structured as one sentence per line, with no mid-sentence wraps.
## Fix Focus Areas
- spec/audit.py[452-459]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Spaced hyphen used as dash✓ Resolved📜 Skill insight✧ Quality
Description
The new prose uses  -  as a dash in sentences (e.g., code sample - documenting ... and a
selftest label flagged - ...). This violates the rule against spaced hyphen dashes.
Code

spec/audit.py[R456-457]

+ section this check judges. Fence-aware via unfenced_text, so a `## ` line inside a fenced code sample -+ documenting the heading syntax itself, or a `##`-prefixed shell comment - is not misread as a real
Relevance

●●● Strong

Recent style precedent explicitly accepts replacing spaced-hyphen dashes in prose.

PR-#383
PR-#621

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2826777 forbids using  -  as a dash in prose. The docstring uses `code sample -
documenting ... and the selftest label uses flagged - ...`.

spec/audit.py[456-457]
spec/audit.py[2920-2920]
Skill: comment-and-doc-style

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Prose uses spaced hyphen ` - ` as a dash to interrupt/join sentences.
## Issue Context
Replace with commas, parentheses, or split into two sentences.
## Fix Focus Areas
- spec/audit.py[456-457]
- spec/audit.py[2920-2920]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Multi-line comment block added✓ Resolved📜 Skill insight⚙ Maintainability
Description
New multi-line comment blocks add elaborative prose instead of staying to one line (or two lines
only for a constraint). This violates the comment concision requirement.
Code

spec/audit.py[R422-425]

+# Carried files scanned for an undeclared H2 heading (spec/section-model.md).+# Started as AGENTS.md and GOVERNANCE.md, the two files section-model.md's split governs.+# #523 added .github/copilot-instructions.md, after a repo's local content sat there undetected, duplicating a later OPERATIONS.md.+UNDECLARED_HEADING_SCANNED = ("AGENTS.md", "GOVERNANCE.md", ".github/copilot-instructions.md")
Relevance

●●● Strong

Recent audit.py precedent accepts concise, clearer comment rewrites and prose-style fixes.

PR-#555
PR-#621

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2826677 requires comments to be short (one line by default). The new comments at
UNDECLARED_HEADING_SCANNED and the undeclared-heading advisory block are multi-line explanatory
prose.

spec/audit.py[422-425]
spec/audit.py[1891-1896]
Skill: comment-and-doc-style

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Several newly added comments are multi-line prose blocks.
## Issue Context
Comments should be one line by default; second line only for a genuine constraint.
## Fix Focus Areas
- spec/audit.py[422-425]
- spec/audit.py[1891-1896]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (2)
4. PR title not Title Case 📘 Rule violation⚙ Maintainability
Description
The PR title Widen undeclared-heading advisory to copilot-instructions.md is not in Title Case
because significant words like undeclared-heading and advisory are lowercase. This violates the
repository rule for Title Case PR titles.
Code

spec/section-model.md[94]

+The undeclared-heading advisory above also runs against `.github/copilot-instructions.md`, not only `AGENTS.md` and `GOVERNANCE.md`, since that file has its own declared sections in `files.json` and is where repo-specific content has accumulated undetected before. It names the heading as undeclared and points at this doc's destinations, and it does not attempt to name which destination a given heading belongs in, since neither `OPERATIONS.md`'s six headings nor `ARCHITECTURE.md`'s are declared anywhere as data, and matching by heading name would miss content filed under a differently worded heading regardless.
Relevance

●●● Strong

Title Case is a deterministic naming rule, and repository history consistently accepts
capitalization corrections.

PR-#12
PR-#308

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2826422 requires Title Case for PR titles; the current title includes multiple
significant words in lowercase (e.g., undeclared-heading, advisory).

Rule 2826422: Enforce Title Case for Pull Request Titles with Lowercase Short Bind Words

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The PR title is not in Title Case.
## Issue Context
Rule requires capitalizing significant words and keeping only short bind words (and/or/in/of/the/a) lowercase when not first/last.
## Fix Focus Areas
- spec/section-model.md[94-94]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Docstring contains prose semicolon✓ Resolved📜 Skill insight✧ Quality
Description
The new undeclared_h2_headings() docstring uses a semicolon as prose punctuation (`heading; per
...`). This violates the no-semicolons-in-prose rule.
Code

spec/audit.py[458]

+ heading; per unfenced_text's own docstring, a checker left fence-blind is a document read two ways.
Relevance

●●● Strong

Recent style precedent explicitly accepts removing semicolons used in prose.

PR-#383
PR-#621

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2826756 disallows semicolons in agent-authored prose. The new docstring line uses
heading; per ....

spec/audit.py[458-458]
Skill: comment-and-doc-style

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
A docstring uses a semicolon as prose punctuation.
## Issue Context
Semicolons are disallowed in agent-authored prose; prefer a period or rewrite into two sentences.
## Fix Focus Areas
- spec/audit.py[458-458]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

6. Comments reference #523 task✓ Resolved📜 Skill insight✧ Quality
Description
New comments embed ticket/PR context (e.g., #523) in code comments and selftest labels. This
violates the guidance that task context belongs in the PR description, not in code comments.
Code

spec/audit.py[R423-425]

+# Started as AGENTS.md and GOVERNANCE.md, the two files section-model.md's split governs.+# #523 added .github/copilot-instructions.md, after a repo's local content sat there undetected, duplicating a later OPERATIONS.md.+UNDECLARED_HEADING_SCANNED = ("AGENTS.md", "GOVERNANCE.md", ".github/copilot-instructions.md")
Relevance

●●● Strong

Recent repository precedent accepts removing contextual inaccuracies and unsupported references from
explanatory prose.

PR-#555
PR-#469

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2827092 forbids task/PR-context references in comments. The new comments and a new
selftest label explicitly reference #523.

spec/audit.py[423-425]
spec/audit.py[1893-1894]
spec/audit.py[2887-2887]
spec/audit.py[2920-2920]
Skill: python-codestyle

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Code comments include task/issue references (e.g., `#523`).
## Issue Context
Task context should live in PR description or external tracking, not in long-lived code comments.
## Fix Focus Areas
- spec/audit.py[423-425]
- spec/audit.py[1893-1894]
- spec/audit.py[2887-2887]
- spec/audit.py[2920-2920]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 67 rules
✅ Skills: 5 invoked
comment-and-doc-style
dotnet-codestyle
python-codestyle
shell-codestyle
workflow-ci-contract
Review mode: ⚖️ Balanced: This changes runtime audit behavior and parsing semantics across multiple paths, so it warrants a careful single-pass review, but the logic remains localized and is not dense enough to justify extended redundancy.

Grey Divider

Tip of the day
💡 Did you know, you can commit Qodo's fix in one click with committable suggestions (GitHub & GitLab)

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

CopilotAI review requested due to automatic review settings August 21, 2026 23:45
Comment threadspec/section-model.md
Comment threadspec/audit.py
Comment threadspec/audit.py Outdated
Comment threadspec/audit.py Outdated
Comment threadspec/audit.py Outdated
Comment threadspec/audit.py Outdated

CopilotAI 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.

🟢 Approval recommended

The scope expansion and fence-awareness change are small, well-contained, and covered by new selftests.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

CI's format-check job caught this, not the check job: the multi-line
set comprehension fits ruff's line-length on one line.
CopilotAI review requested due to automatic review settings August 21, 2026 23:48

CopilotAI 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.

🟢 Approval recommended

The change is small, well-scoped, and includes selftests; the only feedback is a minor docstring/implementation mismatch note.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

spec/audit.py:463

  • The docstring says the normalization is “case-folded”, but the implementation uses .lower(), which is not full Unicode case-folding (and makes the docstring inaccurate). Use .casefold() for both extracted headings and declared names (or update the docstring to say “lowercased”).
 h2s = {ln[3:].strip().lower() for ln in unfenced_text(text).split("\n") if ln.startswith("## ")}
return sorted(h2s - {d.strip().lower() for d in declared})
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot suppressed finding: the docstring said case-folded but the
code uses .lower(), and every other case-insensitive comparison in
this file (heading_texts, hub-name matching) already says lowercased
in its own docstring. Match that vocabulary rather than switch this
one call site to .casefold() and diverge from the rest of the file.
CopilotAI review requested due to automatic review settings August 21, 2026 23:52

CopilotAI 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.

🟢 Approval recommended

The change is narrowly scoped, reuses the existing unfenced_text() behavior to avoid false positives, and adds selftests covering the new scope and the fenced-heading parsing fix.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@ptr727

Copy link
Copy Markdown
OwnerAuthor

Answering the suppressed finding from the round on 9d710aef (1 finding):

spec/audit.py:463 — "The docstring says the normalization is 'case-folded', but the implementation uses .lower(), which is not full Unicode case-folding (and makes the docstring inaccurate). Use .casefold() for both extracted headings and declared names (or update the docstring to say 'lowercased')."

Fixed in 3eed107: corrected the docstring to say "lowercased" rather than switching the implementation to .casefold(). Every other case-insensitive heading/section-name comparison already in this file (heading_texts(), the hub-name match in template_ref_outside_verbatim()) uses .lower() and says "lowercased" in its own docstring; switching only this one call site to .casefold() would diverge from that established convention for headings that are ASCII English prose, where the two are behaviorally identical.

qodo-code-review (advisory, under evaluation per
docs/pr-reviewer-evaluation.md) flagged real violations:
- Comments referencing #523: task context belongs in the PR
description and commit history, not in long-lived code comments.
- The undeclared-section advisory's existing 5-line comment block
grew by 2 lines instead of staying the same length; restored it
to 5 lines with the scope note folded into the existing line.
- A new 3-line comment where the sibling TEMPLATE_REF_SCANNED
constant sets a 1-line precedent; matched it.
- A spaced hyphen and a semicolon in the new docstring, both banned
in agent-authored prose regardless of the syntax carrying them.
CopilotAI review requested due to automatic review settings August 21, 2026 23:59
@ptr727ptr727 changed the title Widen undeclared-heading advisory to copilot-instructions.mdWiden Undeclared-Heading Advisory to copilot-instructions.mdAug 21, 2026

CopilotAI 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.

🟢 Approval recommended

The scope expansion is narrowly implemented, the fence-awareness fix reduces false positives, and the added selftests cover the new behavior.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@ptr727
ptr727 merged commit 03e88e8 into developAug 22, 2026
9 checks passed
ptr727 added a commit that referenced this pull request Aug 22, 2026
## Summary
Follow-up to #900, addressing findings raised on the #900 -> #901
promotion PR review (qodo-code-review and CodeRabbit, both advisory
reviewers on this PR since CodeRabbit is only enabled against `main` as
a base).
- **Real bug, verified independently**: `unfenced_text()` toggled its
fenced state on *any* line starting with `` ``` `` or `~~~`, regardless
of marker family or length. A `~~~` line nested inside a `` ``` `` block
closed the wrong fence, and a shorter `` ``` `` inside a longer `` ````
`` closed a fence it should not have been able to close. Confirmed both
failure modes against the actual code before fixing, and fixed per
CommonMark: a fence closes only on the same marker character, at least
as long as the opener. `unfenced_text` is a pre-existing helper several
other checks (README shields/links) already depend on, so this fixes it
for all of them, not just the new undeclared-heading advisory. Added 5
regression cases; the full existing selftest suite (readme
shields/links) still passes unchanged.
- **Real duplication**: `TEMPLATE_REF_SCANNED` and
`UNDECLARED_HEADING_SCANNED` were two identical tuples that could
silently drift apart on a future edit to one and not the other. Made the
second an alias of the first.
- **Real prose issues**: two over-length sentences in
`section-model.md`, one of them also past-tense change-framing ("has
accumulated undetected before" -> present tense), plus three
over-25-word sentences in new `audit.py` comments/docstrings. Split per
`comment-and-doc-style`.
Two findings from the same review round were judged not real and
declined in the PR conversation on #901 with evidence, no code change: a
PR-title Title-Case false positive (the cited rule actually allows
lowercase "to"), and a "docstring too internal" finding contradicted by
existing precedent in the same file (`strip_sections`' docstring already
names `extract_section`).
## Verification
- `python3 spec/audit.py --selftest` -> `SELFTEST PASS`, including the 5
new `unfenced_text` cases and the full pre-existing suite unchanged
- `python3 spec/validate.py` -> `Spec validation OK`
- `ruff check .` / `ruff format --check .` -> clean
- `python3 scripts/prose_lint.py --diff origin/develop spec/audit.py
spec/section-model.md` -> clean
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Clarified that undeclared-heading checks include
`.github/copilot-instructions.md`.
* Documented heading-scan behavior, including H2-only matching,
normalization, and fenced-content handling.
* **Bug Fixes**
* Improved fenced-content detection to correctly recognize compatible
closing fences.
* Ensured undeclared-heading scans consistently use the configured
template references.
* **Tests**
* Added coverage for fence rules and related heading-scan behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
ptr727 added a commit that referenced this pull request Aug 22, 2026
## Summary
Follow-up to #902, addressing a finding raised on the #900 -> #901
promotion PR review (CodeRabbit).
`unfenced_text()` (fixed in #902) now handles fence marker family,
length, and indentation correctly, but `extract_section()` and
`strip_sections()` still used the original naive toggle-on-any-marker
logic. Verified independently before fixing: a `~~~` line nested inside
a `` ``` `` block made both exit the fenced state early, so a following
`## ` line could end the region short.
This is not cosmetic for `extract_section()`: it is what the verbatim
byte-for-byte section check hashes, so a nested example inside a fenced
code sample could silently truncate what gets compared against the hub
canonical.
Extracted the corrected per-line fence logic from `unfenced_text()` into
`_fence_step()`, a single pure function all three now call, so the
fence-matching rule lives in exactly one place instead of three
near-duplicates that can drift apart the way the first two already had.
Added a regression case covering the nested-marker scenario for both
functions, on top of the existing `extract_section` and `strip_sections`
(via `template_ref_outside_verbatim`) coverage, which still passes
unchanged.
## Verification
- `python3 spec/audit.py --selftest` -> `SELFTEST PASS`, including the
new nested-fence regression and the full pre-existing suite unchanged
- `python3 spec/validate.py` -> `Spec validation OK`
- `ruff check .` / `ruff format --check .` -> clean
- `python3 scripts/prose_lint.py --diff origin/develop spec/audit.py` ->
clean
ptr727 added a commit that referenced this pull request Aug 22, 2026
## Summary
Follow-up to #903, addressing a finding raised on the #900 -> #901
promotion PR review (CodeRabbit).
Per CommonMark, a backtick-fenced opener's info string may not itself
contain a backtick (the spec's own reasoning: otherwise inline code
spans could be misread as a new fence). \`_fence_step()\` accepted an
opener like `` ```md` `` regardless, so a heading right after it was
hidden from the scan. Verified independently against the actual code
before fixing. A tilde fence has no such restriction and is unaffected.
Also split the two over-25-word docstring sentences flagged in the same
review round.
## Verification
- `python3 spec/audit.py --selftest` -> `SELFTEST PASS`, including 3 new
regression cases and the full pre-existing suite unchanged
- `python3 spec/validate.py` -> `Spec validation OK`
- `ruff check .` / `ruff format --check .` -> clean
- `python3 scripts/prose_lint.py --diff origin/develop spec/audit.py` ->
clean
## A note on scope
This is the fourth follow-up PR (#901 -> #902 -> #903 -> this one)
chasing progressively deeper CommonMark fence-parsing edge cases that
CodeRabbit's automated review keeps finding one round at a time against
`_fence_step()`. Each one has been real and independently verified, but
I want to flag the pattern rather than silently keep going: CommonMark
has more edge cases than these four (unterminated fences at EOF, tab
expansion in indentation, and others), and a sufficiently persistent
automated reviewer may keep surfacing them. Worth a decision on where
"correct enough" is for a fleet-internal audit tool versus a full
CommonMark implementation.
ptr727 added a commit that referenced this pull request Aug 22, 2026
## Summary
Follow-up to #904, addressing a suppressed Copilot finding raised on the
#900 -> #901 promotion PR review.
`undeclared_h2_headings()`'s docstring read as if a bare \`##\`-prefixed
shell comment is never misread as a heading anywhere, when that only
holds inside a fenced code sample, the same as the heading-syntax
example right beside it. Reworded so both read as one example of fenced
content rather than two independent claims.
## Verification
- \`python3 spec/audit.py --selftest\` -> \`SELFTEST PASS\`
- \`python3 spec/validate.py\` -> \`Spec validation OK\`
- \`ruff check .\` / \`ruff format --check .\` -> clean
- \`python3 scripts/prose_lint.py --diff origin/develop spec/audit.py\`
-> clean
ptr727 added a commit that referenced this pull request Aug 22, 2026
## Summary
- Widen the undeclared-H2 advisory to scan
`.github/copilot-instructions.md`, so a repo's own content sitting there
is no longer invisible to the audit.
## Included Work
- `03e88e8` Widen Undeclared-Heading Advisory to copilot-instructions.md
(#900).
## Tracking
Fixes#523.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **Bug Fixes**
- Improved documentation audits to detect undeclared H2 headings across
all supported instruction and governance files.
- Heading checks now ignore fenced code, normalize spacing and
capitalization, and exclude unrelated heading levels.
- Improved handling of fenced content, including marker type, length,
indentation, and trailing text.
- **Documentation**
- Updated enforcement guidance to include repository instruction files
and clarify where undeclared headings should be documented.
- **Tests**
- Added coverage for nested, fenced, case-insensitive,
whitespace-normalized, declared, and undeclared headings.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for freeto 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.

2 participants

@ptr727