[mine-blindspots hyperthrive corpus] WorkflowWarStory heading gate too narrow (misses tasks/checklist docs) #163

Closed
opened 2026-07-27 15:07:11 +00:00 by jared · 2 comments
Owner

Context

Cross-project filing from a mine-blindspots run against the hyperthrive-websites repo as external corpus. Bucket (a): "rule exists, logic gap" — the heading-section gate is too narrow, so a matching incident pattern in a qualifying document is never scanned because the enclosing section never opens.

Problem

hyperthrive-websites/docs/onboarding-tasks.md, whole-document heading: # Immediate onboarding tasks for Claude Code. Its numbered step 2 (line 6):

2. ~~**Find the Smartlead wrapper**, read it, and document its interface in `/inventory/smartlead-api.md`.~~ **Superseded 2026-07-25** — done, at a different path: `docs/smartlead-api.md`...

This is exactly the incident-history-in-a-step shape WorkflowWarStory exists to catch (a dated "Superseded 2026-07-25" note embedded in a step, matching its own \b\d{4}-\d{2}-\d{2}\b pattern) — but the cop never scans this document at all, because its only heading, "Immediate onboarding tasks for Claude Code," never matches the section-opening gate.

Detection

plugins/os-aidd-lint/lib/aidd_lint/cops/workflow_war_story.rb:10:

SECTION_PATTERN = /workflow|process|steps/i

investigate (lines 21-27) only calls scan_section for headings matching this pattern. "Immediate onboarding tasks for Claude Code" contains none of "workflow", "process", or "steps", so scan_section never runs for this document's only section, and the dated incident note on line 6 — which would otherwise match INCIDENT_PATTERNS's \b\d{4}-\d{2}-\d{2}\b at line 15 — is never even reached for a match attempt.

Correction

- SECTION_PATTERN = /workflow|process|steps/i
+ SECTION_PATTERN = /workflow|process|steps|tasks|checklist|onboarding/i

Alternatively, gate section-opening on structural shape (a heading whose body contains a numbered list) rather than (or in addition to) heading-text keyword matching, so a document titled around "tasks" or "checklist" isn't structurally exempt.

Pass/fail examples

  • Must fail (flag): # Immediate onboarding tasks for Claude Code section containing a numbered step with **Superseded 2026-07-25**.
  • Must pass (no flag, already covered): a section titled # Workflow with no incident-pattern text in its steps.

Provenance

/os-aidd-lint:mine-blindspots run, external corpus hyperthrive-websites, bucket (a), cop citation workflow_war_story.rb:10 (SECTION_PATTERN), evidence hyperthrive-websites/docs/onboarding-tasks.md:6 (matches INCIDENT_PATTERNS at workflow_war_story.rb:15). Verified independently by a second agent pass against the live cop source and the live corpus file. 2026-07-27.

Fix direction

Broaden SECTION_PATTERN to include synonyms like tasks/checklist/onboarding, or gate section-opening on numbered-list structure in the body rather than solely on heading-text keywords.


Discoverer: hyperthrive-websites, session id unavailable, 2026-07-27. Filed from a mine-blindspots run against this repo as external corpus.

## Context Cross-project filing from a `mine-blindspots` run against the `hyperthrive-websites` repo as external corpus. Bucket (a): "rule exists, logic gap" — the heading-section gate is too narrow, so a matching incident pattern in a qualifying document is never scanned because the enclosing section never opens. ### Problem `hyperthrive-websites/docs/onboarding-tasks.md`, whole-document heading: `# Immediate onboarding tasks for Claude Code`. Its numbered step 2 (line 6): ``` 2. ~~**Find the Smartlead wrapper**, read it, and document its interface in `/inventory/smartlead-api.md`.~~ **Superseded 2026-07-25** — done, at a different path: `docs/smartlead-api.md`... ``` This is exactly the incident-history-in-a-step shape `WorkflowWarStory` exists to catch (a dated "Superseded 2026-07-25" note embedded in a step, matching its own `\b\d{4}-\d{2}-\d{2}\b` pattern) — but the cop never scans this document at all, because its only heading, "Immediate onboarding tasks for Claude Code," never matches the section-opening gate. ### Detection `plugins/os-aidd-lint/lib/aidd_lint/cops/workflow_war_story.rb:10`: ```ruby SECTION_PATTERN = /workflow|process|steps/i ``` `investigate` (lines 21-27) only calls `scan_section` for headings matching this pattern. "Immediate onboarding tasks for Claude Code" contains none of "workflow", "process", or "steps", so `scan_section` never runs for this document's only section, and the dated incident note on line 6 — which would otherwise match `INCIDENT_PATTERNS`'s `\b\d{4}-\d{2}-\d{2}\b` at line 15 — is never even reached for a match attempt. ### Correction ```diff - SECTION_PATTERN = /workflow|process|steps/i + SECTION_PATTERN = /workflow|process|steps|tasks|checklist|onboarding/i ``` Alternatively, gate section-opening on structural shape (a heading whose body contains a numbered list) rather than (or in addition to) heading-text keyword matching, so a document titled around "tasks" or "checklist" isn't structurally exempt. ### Pass/fail examples - **Must fail (flag):** `# Immediate onboarding tasks for Claude Code` section containing a numbered step with `**Superseded 2026-07-25**`. - **Must pass (no flag, already covered):** a section titled `# Workflow` with no incident-pattern text in its steps. ### Provenance `/os-aidd-lint:mine-blindspots` run, external corpus `hyperthrive-websites`, bucket (a), cop citation `workflow_war_story.rb:10` (`SECTION_PATTERN`), evidence `hyperthrive-websites/docs/onboarding-tasks.md:6` (matches `INCIDENT_PATTERNS` at `workflow_war_story.rb:15`). Verified independently by a second agent pass against the live cop source and the live corpus file. 2026-07-27. ### Fix direction Broaden `SECTION_PATTERN` to include synonyms like `tasks`/`checklist`/`onboarding`, or gate section-opening on numbered-list structure in the body rather than solely on heading-text keywords. -------- **Discoverer:** hyperthrive-websites, session id unavailable, 2026-07-27. Filed from a mine-blindspots run against this repo as external corpus.
Author
Owner

Decision memo — classified DECISION-NEEDED, nothing implemented

Headline: the heading gate is not where this cop's cost is. Its line filter is. Measured over the 99 files bin/aidd-lint actually lints in cc-os, the cop emits 17 offenses today. Fix three precision defects that have nothing to do with the gate — count each line once instead of once per enclosing section, skip markdown table rows, and ignore matches inside inline code spans — and those 17 drop to 1. Sixteen of the cop's seventeen current findings on this repo are noise it produces regardless of which sections it opens.

Two facts to hold onto before the options:

  • docs/onboarding-tasks.md is not in lint scope. paths.include covers plugins/**/skills|references|prompts/**, **/SKILL.md, **/CLAUDE.md. No gate change makes bin/aidd-lint catch the evidence file — only a direct cop invocation (a mine-blindspots run against an external corpus) reaches it. The gate change still matters for in-scope files with task/checklist-shaped headings; it just does not "close" the reported case in normal operation.
  • The cop double-counts. investigate iterates document.sections, which is subtree-inclusive; Document#leaf_sections exists with a comment saying exactly this. Invisible today (no nested workflow sections), roughly 2x under a wide gate. Numbers below give emitted and unique separately.

The options, measured (99 in-scope files, unique offenses)

sections opened as shipped with the three precision fixes
A. Leave it 36 17 1
B. Widen keywords (+tasks|checklist|onboarding) 52 17 (+0) 1 (+0)
C. Structural gate (heading keyword OR body has a numbered list) 140 58 (62 emitted) 3 (+2)
D. Scan every section 647 84 (165 emitted) 48 (+47)
E. Every section, CLAUDE.md-class only (the shipped StepBulk/SentenceComplexity pattern) 24 (29 emitted) 5 (+4)

What B newly flags. Exactly the ticket's case, verified live: docs/onboarding-tasks.md:6, heading "Immediate onboarding tasks for Claude Code"

2. ~~**Find the Smartlead wrapper** ... in /inventory/smartlead-api.md~~ **Superseded 2026-07-25** — done, at a different path

matching on 2026-07-25. On cc-os itself it opens 16 more sections and flags nothing new. That is silence, not precision: this repo has no tasks/checklist/onboarding-headed section carrying incident text.

What B still misses. Anything under a heading that names neither a workflow nor a task, e.g. cc-os-naming.md, heading "Registration mechanics":

(discovered 2026-07-04 in os-adr and os-doc-hygiene; fixed by deleting the lines).

That is a genuine war story, and it stays invisible under A, B and C. Only D or E reach it.

What C newly flags. Two, both arguably real:

tier2-catalog-validation.md:243 — 3. Genre-conditioned false-positive risk for smell #1 ...
judge.md:58 — the glob would silently miss (the #45 bug class: ...)

What D newly flags (47). The genuine cc-os-naming.md cluster above, plus a long tail of prose that cites issue numbers and dates as ordinary content — tier2-catalog-validation.md alone contributes ~15 lines like "smell #3 (duplicated-authority) is by far the strongest". #\d+ and a bare date are simply common in reference prose.

What E newly flags (4). CLAUDE.md:59 (a real status note: "Wording loops for os-adr Eval B ... are complete") plus three plugin CLAUDE.md lines that cite a #-number in passing.

Recommendation

Ship B, and file the three precision defects as their own ticket. Confidence 70%.

The single deciding reason: B is the only gate change with a measured cost of zero, and the question D and E turn on is a charter question, not a data question — is this cop's remit "workflow-shaped sections" or "any instruction section"? Data cannot answer that; you can. Meanwhile the precision work is worth more than any gate choice: it removes 16 of 17 current false positives, and it cuts D's price from 84 to 48, which is when D becomes worth re-asking.

Note the honest weakness in B: on this repo it is inert. It is a cheap, reversible bet that the external corpora mine-blindspots runs against write task/checklist headings more often than cc-os does — which is exactly what the hyperthrive run found.

Default if you say nothing: apply B (a one-line SECTION_PATTERN change), open a separate ticket for the leaf-section/table-mask/code-span precision defects, and leave D and E unmade.

## Decision memo — classified DECISION-NEEDED, nothing implemented **Headline: the heading gate is not where this cop's cost is. Its line filter is.** Measured over the 99 files `bin/aidd-lint` actually lints in cc-os, the cop emits 17 offenses today. Fix three precision defects that have nothing to do with the gate — count each line once instead of once per enclosing section, skip markdown table rows, and ignore matches inside inline code spans — and those 17 drop to **1**. Sixteen of the cop's seventeen current findings on this repo are noise it produces regardless of which sections it opens. Two facts to hold onto before the options: - **`docs/onboarding-tasks.md` is not in lint scope.** `paths.include` covers `plugins/**/skills|references|prompts/**`, `**/SKILL.md`, `**/CLAUDE.md`. No gate change makes `bin/aidd-lint` catch the evidence file — only a direct cop invocation (a mine-blindspots run against an external corpus) reaches it. The gate change still matters for in-scope files with task/checklist-shaped headings; it just does not "close" the reported case in normal operation. - **The cop double-counts.** `investigate` iterates `document.sections`, which is subtree-inclusive; `Document#leaf_sections` exists with a comment saying exactly this. Invisible today (no nested workflow sections), roughly 2x under a wide gate. Numbers below give emitted and unique separately. ### The options, measured (99 in-scope files, unique offenses) | | sections opened | as shipped | with the three precision fixes | |---|---|---|---| | **A. Leave it** | 36 | 17 | 1 | | **B. Widen keywords** (`+tasks\|checklist\|onboarding`) | 52 | 17 (+0) | 1 (+0) | | **C. Structural gate** (heading keyword OR body has a numbered list) | 140 | 58 (62 emitted) | 3 (+2) | | **D. Scan every section** | 647 | 84 (165 emitted) | 48 (+47) | | **E. Every section, CLAUDE.md-class only** (the shipped StepBulk/SentenceComplexity pattern) | — | 24 (29 emitted) | 5 (+4) | **What B newly flags.** Exactly the ticket's case, verified live: `docs/onboarding-tasks.md:6`, heading *"Immediate onboarding tasks for Claude Code"* — > `2. ~~**Find the Smartlead wrapper** ... in /inventory/smartlead-api.md~~ **Superseded 2026-07-25** — done, at a different path` matching on `2026-07-25`. **On cc-os itself it opens 16 more sections and flags nothing new.** That is silence, not precision: this repo has no tasks/checklist/onboarding-headed section carrying incident text. **What B still misses.** Anything under a heading that names neither a workflow nor a task, e.g. `cc-os-naming.md`, heading *"Registration mechanics"*: > (discovered 2026-07-04 in os-adr and os-doc-hygiene; fixed by deleting the lines). That is a genuine war story, and it stays invisible under A, B and C. Only D or E reach it. **What C newly flags.** Two, both arguably real: > `tier2-catalog-validation.md:243` — 3. **Genre-conditioned false-positive risk for smell #1** ... > `judge.md:58` — the glob would silently miss (the #45 bug class: ...) **What D newly flags (47).** The genuine `cc-os-naming.md` cluster above, plus a long tail of prose that cites issue numbers and dates as ordinary content — `tier2-catalog-validation.md` alone contributes ~15 lines like *"smell #3 (duplicated-authority) is by far the strongest"*. `#\d+` and a bare date are simply common in reference prose. **What E newly flags (4).** `CLAUDE.md:59` (a real status note: *"Wording loops for os-adr Eval B ... are complete"*) plus three plugin CLAUDE.md lines that cite a `#`-number in passing. ### Recommendation **Ship B, and file the three precision defects as their own ticket. Confidence 70%.** The single deciding reason: **B is the only gate change with a measured cost of zero, and the question D and E turn on is a charter question, not a data question** — is this cop's remit "workflow-shaped sections" or "any instruction section"? Data cannot answer that; you can. Meanwhile the precision work is worth more than any gate choice: it removes 16 of 17 current false positives, and it cuts D's price from 84 to 48, which is when D becomes worth re-asking. Note the honest weakness in B: on this repo it is inert. It is a cheap, reversible bet that the *external* corpora mine-blindspots runs against write task/checklist headings more often than cc-os does — which is exactly what the hyperthrive run found. **Default if you say nothing:** apply B (a one-line `SECTION_PATTERN` change), open a separate ticket for the leaf-section/table-mask/code-span precision defects, and leave D and E unmade.
Author
Owner

Option B shipped. Green on branch fix/163-workflow-war-story-heading-gate (commit 26846c1, branched from main at e493764). Not closing — needs sign-off.

Change. One line: SECTION_PATTERN = /workflow|process|steps|tasks|checklist|onboarding/i, plus a comment recording why this stayed a heading gate.

Corpus before/after (the 99 files bin/aidd-lint actually lints): sections opened 36 → 52, offenses 17 → 17, and the two offense sets are byte-identical (diff clean). Zero measured cost. As the memo said, on this repo that is silence rather than precision — cc-os has no task-headed section carrying incident text. The bet is that external corpora do, which is what the hyperthrive run found.

Tests. Three added to tests/cops/workflow_war_story_test.rb: the ticket's must-fail case (an # Immediate onboarding tasks for Claude Code section with **Superseded 2026-07-25** in a numbered step), a checklist-headed section with incident phrasing, and a must-pass tasks section with no incident text. Red first — 288 runs, 690 assertions, 2 failures — then:

288 runs, 693 assertions, 0 failures, 0 errors, 0 skips
Finished in 3.897114s, 73.9008 runs/s, 177.8239 assertions/s.

Two things this does NOT do, both deliberate.

  1. It does not make bin/aidd-lint catch the evidence file. in_scope?("docs/onboarding-tasks.md") is falsepaths.include covers plugins/**/skills|references|prompts/**, **/SKILL.md, **/CLAUDE.md. No gate change reaches that file in normal operation; only a direct cop invocation (a mine-blindspots run against an external corpus) does. Widening the scope globs is a separate decision and is not proposed here.

  2. The D/E scope question stays open, on purpose. Scanning every section (D), or every section in CLAUDE.md-class files only (E, the shipped StepBulk/SentenceComplexity pattern), would additionally catch real war stories that B still misses — e.g. cc-os-naming.md under the heading "Registration mechanics": "(discovered 2026-07-04 in os-adr and os-doc-hygiene; fixed by deleting the lines)." That is a charter-level call — is this cop's remit "workflow-shaped sections" or "any instruction section"? — and it is Jared's to make, not derivable from the corpus. Leaving this ticket open with B applied is the intended state.

Filed alongside: #165, the three gate-independent precision defects (per-section double counting vs. leaf_sections, unused skip_mask on table rows, dates/issue-numbers inside inline code spans). Those cost far more than the gate does — they account for 16 of the cop's 17 current offenses on this repo — and fixing them cuts option D's price from 84 unique offenses to 48, which is when the charter question above becomes worth re-asking.

Option B shipped. Green on branch `fix/163-workflow-war-story-heading-gate` (commit `26846c1`, branched from `main` at `e493764`). Not closing — needs sign-off. **Change.** One line: `SECTION_PATTERN = /workflow|process|steps|tasks|checklist|onboarding/i`, plus a comment recording why this stayed a heading gate. **Corpus before/after (the 99 files `bin/aidd-lint` actually lints):** sections opened **36 → 52**, offenses **17 → 17**, and the two offense sets are byte-identical (`diff` clean). Zero measured cost. As the memo said, on this repo that is silence rather than precision — cc-os has no task-headed section carrying incident text. The bet is that external corpora do, which is what the hyperthrive run found. **Tests.** Three added to `tests/cops/workflow_war_story_test.rb`: the ticket's must-fail case (an `# Immediate onboarding tasks for Claude Code` section with `**Superseded 2026-07-25**` in a numbered step), a checklist-headed section with incident phrasing, and a must-pass tasks section with no incident text. Red first — `288 runs, 690 assertions, 2 failures` — then: ``` 288 runs, 693 assertions, 0 failures, 0 errors, 0 skips Finished in 3.897114s, 73.9008 runs/s, 177.8239 assertions/s. ``` **Two things this does NOT do, both deliberate.** 1. **It does not make `bin/aidd-lint` catch the evidence file.** `in_scope?("docs/onboarding-tasks.md")` is `false` — `paths.include` covers `plugins/**/skills|references|prompts/**`, `**/SKILL.md`, `**/CLAUDE.md`. No gate change reaches that file in normal operation; only a direct cop invocation (a mine-blindspots run against an external corpus) does. Widening the *scope* globs is a separate decision and is not proposed here. 2. **The D/E scope question stays open, on purpose.** Scanning every section (D), or every section in CLAUDE.md-class files only (E, the shipped StepBulk/SentenceComplexity pattern), would additionally catch real war stories that B still misses — e.g. `cc-os-naming.md` under the heading *"Registration mechanics"*: *"(discovered 2026-07-04 in os-adr and os-doc-hygiene; fixed by deleting the lines)."* That is a charter-level call — is this cop's remit "workflow-shaped sections" or "any instruction section"? — and it is Jared's to make, not derivable from the corpus. Leaving this ticket open with B applied is the intended state. **Filed alongside: #165**, the three gate-independent precision defects (per-section double counting vs. `leaf_sections`, unused `skip_mask` on table rows, dates/issue-numbers inside inline code spans). Those cost far more than the gate does — they account for 16 of the cop's 17 current offenses on this repo — and fixing them cuts option D's price from 84 unique offenses to 48, which is when the charter question above becomes worth re-asking.
jared 2026-07-27 16:44:15 +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#163
No description provided.