workflow-war-story: three gate-independent precision defects (16 of 17 current offenses are noise) #165

Closed
opened 2026-07-27 16:41:39 +00:00 by jared · 0 comments
Owner

Context

Surfaced while measuring the #163 heading-gate options against this repo's own corpus. These three defects are independent of #163's gate question and cost far more than it: over the 99 files bin/aidd-lint actually lints, WorkflowWarStory emits 17 offenses; fix these three and it emits 1. Sixteen of seventeen current findings are noise the cop produces regardless of which sections it opens.

Each defect has a purpose-built helper already in lib/ that the cop does not use.

1. Per-section double counting (should use Document#leaf_sections)

cops/workflow_war_story.rb:21 iterates document.sections, which is subtree-inclusive: a heading's body runs to the next heading of equal-or-lesser level, so an ancestor's body_lines fully contain every descendant's. A line under nested matching headings is flagged once per enclosing section.

document.rb:60-70 already documents this exact hazard: "Cops that scan section bodies for content (not headings) need the leaf sections only, or they double-count everything nested under an ancestor."

Invisible today (this repo has no nested workflow-headed sections, so emitted == unique == 17), but it is latent: measured with an all-sections gate the cop emits 165 for 84 unique lines.

Caveat for whoever implements this: leaf_sections rejects parents wholesale, so a parent's preamble lines before its first child heading would stop being scanned. That is a behavior change, not a pure fix, and needs its own test.

2. Table rows are scanned (should use Document#skip_mask)

scan_section guards on document.fence_mask only. Document#skip_mask (fence | table | frontmatter) exists and is unused here. Markdown table rows are therefore scanned as if they were step prose.

Real hits in this repo, all table rows in plugins/os-aidd-lint/references/tier2-catalog-validation.md:

:96  | Step 1 = pure rationale, no imperative (L150-L154) | **Revised on reconciliation ...
:97  | Empty-candidates rule x3 (L171-173, L263-264, L385-386) | **(a) duplicated-authority ...
:151 | Whole-file genre mismatch for smell #1 | **NOVEL observation ...

3. Dates and issue numbers inside inline code spans

A date or #-number inside backticks is a value being illustrated, not incident history. Same class as PathReferenceScanner::PLACEHOLDER_TOKEN -- a convention shown, not a fact asserted.

Real hits:

plugins/cc-architect/references/conventions/plugin-data-convention.md:30-32
  - `2024-01-15-heuristic-checkout-flow.md`      (a filename-format example)
plugins/cc-architect/references/defer-work/workflow.md:70-72
  - `2026-01-20-skill-brainstorming.md`          (same)
CLAUDE.md:75
  - **Dates are absolute** (e.g. `2026-06-03`)   (the date is the example)

Measured effect (99 in-scope files, unique offenses)

gate as shipped with all three fixed
current (workflow|process|steps) 17 1
widened (#163's fix) 17 1
structural (numbered-list body) 58 (62 emitted) 3
every section 84 (165 emitted) 48

The last row is why this matters beyond noise reduction: it is what makes the all-sections question on #163 answerable at a sane price.

Scope note

Fixes 1 and 2 are generic MarkdownCop hygiene -- worth checking whether other section-scanning cops have the same two defects rather than patching WorkflowWarStory alone. Fix 3 is a line-level filter and may belong next to the incident-pattern matching.

Discovered while working #163, 2026-07-27.

## Context Surfaced while measuring the #163 heading-gate options against this repo's own corpus. These three defects are independent of #163's gate question and cost far more than it: over the 99 files `bin/aidd-lint` actually lints, WorkflowWarStory emits 17 offenses; fix these three and it emits **1**. Sixteen of seventeen current findings are noise the cop produces regardless of which sections it opens. Each defect has a purpose-built helper already in `lib/` that the cop does not use. ### 1. Per-section double counting (should use `Document#leaf_sections`) `cops/workflow_war_story.rb:21` iterates `document.sections`, which is subtree-inclusive: a heading's body runs to the next heading of equal-or-lesser level, so an ancestor's `body_lines` fully contain every descendant's. A line under nested matching headings is flagged once per enclosing section. `document.rb:60-70` already documents this exact hazard: *"Cops that scan section bodies for content (not headings) need the leaf sections only, or they double-count everything nested under an ancestor."* Invisible today (this repo has no nested workflow-headed sections, so emitted == unique == 17), but it is latent: measured with an all-sections gate the cop emits **165** for **84** unique lines. **Caveat for whoever implements this:** `leaf_sections` rejects parents wholesale, so a parent's preamble lines before its first child heading would stop being scanned. That is a behavior change, not a pure fix, and needs its own test. ### 2. Table rows are scanned (should use `Document#skip_mask`) `scan_section` guards on `document.fence_mask` only. `Document#skip_mask` (fence | table | frontmatter) exists and is unused here. Markdown table rows are therefore scanned as if they were step prose. Real hits in this repo, all table rows in `plugins/os-aidd-lint/references/tier2-catalog-validation.md`: ``` :96 | Step 1 = pure rationale, no imperative (L150-L154) | **Revised on reconciliation ... :97 | Empty-candidates rule x3 (L171-173, L263-264, L385-386) | **(a) duplicated-authority ... :151 | Whole-file genre mismatch for smell #1 | **NOVEL observation ... ``` ### 3. Dates and issue numbers inside inline code spans A date or `#`-number inside backticks is a value being illustrated, not incident history. Same class as `PathReferenceScanner::PLACEHOLDER_TOKEN` -- a convention shown, not a fact asserted. Real hits: ``` plugins/cc-architect/references/conventions/plugin-data-convention.md:30-32 - `2024-01-15-heuristic-checkout-flow.md` (a filename-format example) plugins/cc-architect/references/defer-work/workflow.md:70-72 - `2026-01-20-skill-brainstorming.md` (same) CLAUDE.md:75 - **Dates are absolute** (e.g. `2026-06-03`) (the date is the example) ``` ## Measured effect (99 in-scope files, unique offenses) | gate | as shipped | with all three fixed | |---|---|---| | current (`workflow\|process\|steps`) | 17 | **1** | | widened (#163's fix) | 17 | 1 | | structural (numbered-list body) | 58 (62 emitted) | 3 | | every section | 84 (165 emitted) | 48 | The last row is why this matters beyond noise reduction: it is what makes the all-sections question on #163 answerable at a sane price. ## Scope note Fixes 1 and 2 are generic `MarkdownCop` hygiene -- worth checking whether other section-scanning cops have the same two defects rather than patching WorkflowWarStory alone. Fix 3 is a line-level filter and may belong next to the incident-pattern matching. Discovered while working #163, 2026-07-27.
jared 2026-07-27 17:13:35 +00:00
  • closed this issue
  • added the
    review
    label
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jared/cc-os#165
No description provided.