[mine-blindspots hyperthrive corpus] TrailingProhibition misses comma-trailing prohibition clauses #160

Closed
opened 2026-07-27 15:07:03 +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" — tier-1 cop bug, not new rule.

Problem

hyperthrive-websites/context/stack/repo-structure.md:61:

- Credentials go in `.env`, never in markdown. `services.md` records *where* a credential lives, not the credential.

The prohibition "never in markdown" is comma-trailing (Credentials go in .env, never in markdown.) and is missed, while the adjacent line 62 —

- Client sites live in `clients/`, generated from `templates/`. Never edit a template to fix one client.

— is correctly caught, because its prohibition leads its own sentence after a full stop, not a comma.

Detection

plugins/os-aidd-lint/lib/aidd_lint/cops/trailing_prohibition.rb:19-24:

CLAUSE_SPLIT = /([.;]|--|—)\s+/

Commas are deliberately excluded from CLAUSE_SPLIT (per the comment at lines 20-24, to avoid false-positiving on ordinary contrastive asides like "the ledger, not your context, holds..."). This means a comma-trailing prohibition clause such as , never in markdown. is never split out as its own clause and never reaches STRONG_PROHIBITION matching at all — the whole sentence Credentials go in .env, never in markdown. is treated as one un-splittable unit.

Correction

- CLAUSE_SPLIT = /([.;]|--|—)\s+/
+ CLAUSE_SPLIT = /([.;]|--|—|,)\s+/

paired with restricting comma-splits to only fire when the resulting clause leads with an unambiguous strong-prohibition word (i.e., comma is a weaker delimiter than ./;/dash, so only trust it when STRONG_PROHIBITION itself confirms the clause), which is what avoids reintroducing the contrastive-aside false positives the original exclusion comment worried about.

Pass/fail examples

  • Must fail (flag): Credentials go in .env, never in markdown.
  • Must not regress (no flag): the ledger, not your context, holds... (comma-led clause starting with "not" alone, not an unambiguous strong-prohibition word — should stay unflagged per the cop's existing false-positive concern, since bare "not" is not in STRONG_PROHIBITION).

Provenance

/os-aidd-lint:mine-blindspots run, external corpus hyperthrive-websites, bucket (a), cop citation trailing_prohibition.rb:19-24 (CLAUSE_SPLIT), evidence hyperthrive-websites/context/stack/repo-structure.md:61. Verified independently by a second agent pass against the live cop source and the live corpus file. 2026-07-27.

Fix direction

Allow a comma to act as a clause-split delimiter only when the clause immediately following it leads with an unambiguous strong-prohibition word (reusing STRONG_PROHIBITION itself as the gate), so ordinary contrastive asides are not affected but a comma-trailing prohibition is caught.


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" — tier-1 cop bug, not new rule. ### Problem `hyperthrive-websites/context/stack/repo-structure.md:61`: ``` - Credentials go in `.env`, never in markdown. `services.md` records *where* a credential lives, not the credential. ``` The prohibition "never in markdown" is comma-trailing (`Credentials go in .env, never in markdown.`) and is missed, while the adjacent line 62 — ``` - Client sites live in `clients/`, generated from `templates/`. Never edit a template to fix one client. ``` — is correctly caught, because its prohibition leads its own sentence after a full stop, not a comma. ### Detection `plugins/os-aidd-lint/lib/aidd_lint/cops/trailing_prohibition.rb:19-24`: ```ruby CLAUSE_SPLIT = /([.;]|--|—)\s+/ ``` Commas are deliberately excluded from `CLAUSE_SPLIT` (per the comment at lines 20-24, to avoid false-positiving on ordinary contrastive asides like "the ledger, not your context, holds..."). This means a comma-trailing prohibition clause such as `, never in markdown.` is never split out as its own clause and never reaches `STRONG_PROHIBITION` matching at all — the whole sentence `Credentials go in .env, never in markdown.` is treated as one un-splittable unit. ### Correction ```diff - CLAUSE_SPLIT = /([.;]|--|—)\s+/ + CLAUSE_SPLIT = /([.;]|--|—|,)\s+/ ``` paired with restricting comma-splits to only fire when the resulting clause leads with an unambiguous strong-prohibition word (i.e., comma is a weaker delimiter than `.`/`;`/dash, so only trust it when `STRONG_PROHIBITION` itself confirms the clause), which is what avoids reintroducing the contrastive-aside false positives the original exclusion comment worried about. ### Pass/fail examples - **Must fail (flag):** `Credentials go in `.env`, never in markdown.` - **Must not regress (no flag):** `the ledger, not your context, holds...` (comma-led clause starting with "not" alone, not an unambiguous strong-prohibition word — should stay unflagged per the cop's existing false-positive concern, since bare "not" is not in `STRONG_PROHIBITION`). ### Provenance `/os-aidd-lint:mine-blindspots` run, external corpus `hyperthrive-websites`, bucket (a), cop citation `trailing_prohibition.rb:19-24` (`CLAUSE_SPLIT`), evidence `hyperthrive-websites/context/stack/repo-structure.md:61`. Verified independently by a second agent pass against the live cop source and the live corpus file. 2026-07-27. ### Fix direction Allow a comma to act as a clause-split delimiter only when the clause immediately following it leads with an unambiguous strong-prohibition word (reusing `STRONG_PROHIBITION` itself as the gate), so ordinary contrastive asides are not affected but a comma-trailing prohibition is caught. -------- **Discoverer:** hyperthrive-websites, session id unavailable, 2026-07-27. Filed from a mine-blindspots run against this repo as external corpus.
Author
Owner

Classified DECISION-NEEDED — not implemented. Decision memo below.

Headline

Widening CLAUSE_SPLIT to commas catches 1 real miss and creates ~14 new flags on this repo alone, most of them on prose already written in the shape the cop is trying to produce. Recommend closing as wontfix.

What I measured

I prototyped the ticket's exact fix direction (comma added to CLAUSE_SPLIT, gated so only STRONG_PROHIBITION-leading clauses fire) and ran it over the 99 files in this repo's own lint scope. 14 new offenses. A representative sample, verbatim:

File:line Clause the cop would newly flag
skills/mine-blindspots/SKILL.md:18 never a sequential queue.
skills/mine-blindspots/SKILL.md:26 never a routine ticket.
os-doc-hygiene/skills/calibrate/SKILL.md:553 never per-cluster.
os-sdlc/skills/fix-lints/SKILL.md:42 never you.
os-vault/skills/design-template/SKILL.md:94 never separate templates.
os-shortcuts/skills/wrap/SKILL.md:22 never force-push,
os-adr/skills/create/SKILL.md:31 only if this replaces an existing ADR

These are all the same construction: X, never Y. — an emphatic appositive where the prohibition is the bullet's punchline. Parallel fan-out, never a sequential queue. is good writing. The cop's remedy message would tell the author to "promote it to its own bullet leading with Never/Only" — but it already is the bullet, and the prohibition already carries the emphasis. That is bad advice at volume.

Options

Option A — implement as filed. Comma joins CLAUSE_SPLIT, gated on STRONG_PROHIBITION.

  • Newly caught (the ticket's target): Credentials go in .env, never in markdown. — genuinely worth splitting.
  • Newly flagged (collateral): the 14 above.
  • Still correctly ignored: the ledger, not your context, holds... — bare not is not in STRONG_PROHIBITION, so the original false-positive concern in the code comment does hold.

So the ticket's gate works exactly as designed. The problem is not the gate; it is that the comma construction is legitimately common in well-written imperative prose in a way the semicolon/dash construction is not.

Option B — comma split, but only when the prohibition clause is NOT terminal (X, never Y, and then Z.).

  • Kills all 14 above (every one is terminal).
  • Also kills the ticket's own targetCredentials go in .env, never in markdown. is terminal too. Net zero. Not viable.

Option C — no change. The evidence case stays missed.

  • Still missed: - Credentials go in .env, never in markdown.
  • Cost of the miss: low. The prohibition sits adjacent to its subject and reads clearly. This is the mildest instance of the smell the cop exists for — the clause is not buried behind a rationale, which is the actual failure mode the cop was written to catch.

Recommendation

Option C — close as wontfix, and amend the code comment at CLAUSE_SPLIT to cite this measurement so a future mining run does not re-file the same ticket. Confidence 80%.

Single deciding reason: the fix trades one soft catch for fourteen flags on prose that is already in the shape the cop wants — the signal-to-noise ratio inverts.

Default if nothing is said

No change ships. The comma exclusion stays as written. CLAUSE_SPLIT is untouched on branch aidd-lint-trailing-prohibition-gaps.

Classified **DECISION-NEEDED** — not implemented. Decision memo below. ## Headline Widening CLAUSE_SPLIT to commas catches 1 real miss and creates ~14 new flags on this repo alone, most of them on prose already written in the shape the cop is trying to produce. Recommend closing as wontfix. ## What I measured I prototyped the ticket's exact fix direction (comma added to CLAUSE_SPLIT, gated so only STRONG_PROHIBITION-leading clauses fire) and ran it over the 99 files in this repo's own lint scope. **14 new offenses.** A representative sample, verbatim: | File:line | Clause the cop would newly flag | |---|---| | skills/mine-blindspots/SKILL.md:18 | `never a sequential queue.` | | skills/mine-blindspots/SKILL.md:26 | `never a routine ticket.` | | os-doc-hygiene/skills/calibrate/SKILL.md:553 | `never per-cluster.` | | os-sdlc/skills/fix-lints/SKILL.md:42 | `never you.` | | os-vault/skills/design-template/SKILL.md:94 | `never separate templates.` | | os-shortcuts/skills/wrap/SKILL.md:22 | `never force-push,` | | os-adr/skills/create/SKILL.md:31 | `only if this replaces an existing ADR` | These are all the same construction: **`X, never Y.`** — an emphatic appositive where the prohibition is the bullet's punchline. `Parallel fan-out, never a sequential queue.` is *good* writing. The cop's remedy message would tell the author to "promote it to its own bullet leading with Never/Only" — but it already is the bullet, and the prohibition already carries the emphasis. That is bad advice at volume. ## Options **Option A — implement as filed.** Comma joins CLAUSE_SPLIT, gated on STRONG_PROHIBITION. - **Newly caught (the ticket's target):** `Credentials go in `.env`, never in markdown.` — genuinely worth splitting. - **Newly flagged (collateral):** the 14 above. - **Still correctly ignored:** `the ledger, not your context, holds...` — bare `not` is not in STRONG_PROHIBITION, so the original false-positive concern in the code comment does hold. So the ticket's gate works exactly as designed. The problem is not the gate; it is that the comma construction is *legitimately common* in well-written imperative prose in a way the semicolon/dash construction is not. **Option B — comma split, but only when the prohibition clause is NOT terminal** (`X, never Y, and then Z.`). - Kills all 14 above (every one is terminal). - **Also kills the ticket's own target** — `Credentials go in `.env`, never in markdown.` is terminal too. Net zero. Not viable. **Option C — no change.** The evidence case stays missed. - **Still missed:** `- Credentials go in `.env`, never in markdown.` - **Cost of the miss:** low. The prohibition sits adjacent to its subject and reads clearly. This is the mildest instance of the smell the cop exists for — the clause is not buried behind a rationale, which is the actual failure mode the cop was written to catch. ## Recommendation **Option C — close as wontfix, and amend the code comment at CLAUSE_SPLIT to cite this measurement** so a future mining run does not re-file the same ticket. Confidence **80%**. **Single deciding reason:** the fix trades one soft catch for fourteen flags on prose that is already in the shape the cop wants — the signal-to-noise ratio inverts. ## Default if nothing is said No change ships. The comma exclusion stays as written. CLAUSE_SPLIT is untouched on branch `aidd-lint-trailing-prohibition-gaps`.
Author
Owner

Closing as wontfix per Jared's decision, 2026-07-27.

The measurement that decided it — the ticket's exact fix direction (comma added to CLAUSE_SPLIT, gated so only STRONG_PROHIBITION-leading clauses fire), prototyped and run over the 99 files in this repo's own lint scope:

1 real catch, 14 new flags.

The catch is the ticket's evidence line, Credentials go in .env, never in markdown. The 14 are essentially all one construction — the emphatic appositive X, never Y.:

File:line Would newly flag
mine-blindspots/SKILL.md:18 never a sequential queue.
mine-blindspots/SKILL.md:26 never a routine ticket.
os-doc-hygiene/calibrate/SKILL.md:553 never per-cluster.
os-sdlc/fix-lints/SKILL.md:42 never you.
os-vault/design-template/SKILL.md:94 never separate templates.
os-shortcuts/wrap/SKILL.md:22 never force-push,
os-adr/create/SKILL.md:31 only if this replaces an existing ADR

The proposed gate is not the problem — it works exactly as designed, and the original false-positive worry in the code comment (the ledger, not your context, holds...) does stay unflagged, because bare not is not in STRONG_PROHIBITION. The problem is that X, never Y. is good writing that already leads with its prohibition and has nowhere to be promoted to. Parallel fan-out, never a sequential queue. is the shape this cop exists to produce.

Also considered and rejected: gating the comma split on the clause being non-terminal. That kills all 14 — and kills the ticket's own target too, which is terminal. Net zero.

Rationale pinned in the source so a future mine-blindspots run does not re-file this: commit 5ca7a2a on branch aidd-lint-trailing-prohibition-gaps extends the CLAUSE_SPLIT comment with the issue number, the 1-vs-14 numbers, the construction, and the wontfix disposition.

Sibling issues #158, #159 and #161 from the same mining run are implemented and labelled review on that branch.

**Closing as wontfix per Jared's decision, 2026-07-27.** The measurement that decided it — the ticket's exact fix direction (comma added to CLAUSE_SPLIT, gated so only STRONG_PROHIBITION-leading clauses fire), prototyped and run over the 99 files in this repo's own lint scope: **1 real catch, 14 new flags.** The catch is the ticket's evidence line, `Credentials go in `.env`, never in markdown.` The 14 are essentially all one construction — the emphatic appositive `X, never Y.`: | File:line | Would newly flag | |---|---| | mine-blindspots/SKILL.md:18 | `never a sequential queue.` | | mine-blindspots/SKILL.md:26 | `never a routine ticket.` | | os-doc-hygiene/calibrate/SKILL.md:553 | `never per-cluster.` | | os-sdlc/fix-lints/SKILL.md:42 | `never you.` | | os-vault/design-template/SKILL.md:94 | `never separate templates.` | | os-shortcuts/wrap/SKILL.md:22 | `never force-push,` | | os-adr/create/SKILL.md:31 | `only if this replaces an existing ADR` | The proposed gate is not the problem — it works exactly as designed, and the original false-positive worry in the code comment (`the ledger, not your context, holds...`) does stay unflagged, because bare `not` is not in STRONG_PROHIBITION. The problem is that `X, never Y.` is *good* writing that already leads with its prohibition and has nowhere to be promoted to. `Parallel fan-out, never a sequential queue.` is the shape this cop exists to produce. Also considered and rejected: gating the comma split on the clause being non-terminal. That kills all 14 — and kills the ticket's own target too, which is terminal. Net zero. **Rationale pinned in the source** so a future mine-blindspots run does not re-file this: commit `5ca7a2a` on branch `aidd-lint-trailing-prohibition-gaps` extends the CLAUSE_SPLIT comment with the issue number, the 1-vs-14 numbers, the construction, and the wontfix disposition. Sibling issues #158, #159 and #161 from the same mining run are implemented and labelled `review` on that branch.
jared 2026-07-27 16:48:06 +00:00
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#160
No description provided.