Skip to content

Gate hard-wrapped markdown instead of only documenting the rule #285

Description

@FrankRay78

Problem

.claude/memory/feedback_markdown_soft_wrap.md tells Claude to author each markdown paragraph, bullet and table row as a single unwrapped line, and explicitly names docs, READMEs, memory files and PR bodies. It is written, it is indexed in MEMORY.md, and it still did not land.

On the #281 branch, bbd6454 committed four hard-wrapped paragraphs into .claude/commands/speckit.reviewissue.md. 211726c then unwrapped them as a separate rework commit — 5 insertions against 23 deletions, pure churn. The file was touched 3 times in a 4-commit branch, and one of those touches existed only to undo the previous one.

The reason the rule failed is worth stating, because it will recur: the surrounding text in that file is itself hard-wrapped legacy prose, so matching local style and following the written rule pointed in opposite directions. Local style won.

Motivation

A memory that fails after being written is the signal to escalate, not to restate. The repo's own preference order puts a deterministic mechanism above a memory entry precisely for this case, and .claude/memory/feedback_audit_class_after_two_failures.md says the second occurrence of a failure shape is the point to fix the class rather than the instance.

There is direct in-repo precedent for the mechanism. .claude/hooks/ already carries three gates that decide markdown- and code-shape invariants — no-skipped-tests.sh, traceability-gate.sh, green-gate.sh — each with a --check mode and a committed *.tests.sh fixture matrix.

Proposal

A .claude/hooks/ gate that rejects a commit introducing hard-wrapped markdown prose, following the existing --check + *.tests.sh pattern.

The binding constraint is that it must inspect added lines only. Almost every long-lived markdown file in this repo is hard-wrapped throughout, so a whole-file check would fail on contact with nearly any doc commit.

The hard part, stated up front

Distinguishing an added hard-wrapped paragraph line from a legitimately short line is the whole difficulty, and a naive length test will not do it. Lines that are short for good reasons include headings, list items, table rows, blockquote lines, fenced-code content, link-reference definitions, and the last line of any paragraph.

A false-positive gate firing on ordinary doc commits would be worse than the memory that currently fails, so the acceptance bar should be behavioural rather than aspirational.

Acceptance criteria (draft — expect the review to sharpen these)

  • A commit adding a hard-wrapped prose paragraph to a markdown file is rejected, naming the file and line.
  • A commit adding soft-wrapped prose to a markdown file passes.
  • Editing a line inside an existing hard-wrapped paragraph, without re-wrapping it, is not rejected — otherwise the gate forces unrelated reflows, which is the diff noise the rule exists to prevent.
  • Headings, list items, table rows, blockquote lines, fenced-code content and link-reference definitions are never flagged.
  • The gate runs on bbd6454 and fails, and on 211726c and passes. These two commits are the real before/after and are the RED-GREEN evidence for this change.
  • A --check mode exists for CI and manual scans, matching the three existing hooks.
  • A committed *.tests.sh fixture matrix covers each criterion above.

Out of scope

  • Re-wrapping existing hard-wrapped files. The memory explicitly forbids tidying them, and doing it would produce exactly the reflow diffs this is meant to avoid.
  • Any change to feedback_markdown_soft_wrap.md's substance. The rule is right; only its enforcement is missing.
  • Adding a hard-wrap step to any formatter or hook, which the memory forbids outright.
  • Markdown outside this repository — issue bodies and PR bodies are composed by hand and land via gh, where no commit hook can see them.

Open questions

  • Is a commit hook the right gate at all, or should this be a --check run in CI only? A PreToolUse hook that fails closed blocks every commit when it misfires, and this check is more heuristic than the three that exist.
  • What is the right threshold, and should it be a threshold at all? A paragraph line that ends well short of the wrap column while the next line continues the sentence is the real signal, and that is a shape test rather than a length test.

Related

  • .claude/memory/feedback_markdown_soft_wrap.md — the rule this enforces.
  • .claude/memory/feedback_audit_class_after_two_failures.md — why the second occurrence is the point to mechanise.
  • docs/study/281.md — row 3 records this failure.
  • .claude/hooks/README.md — the --check + *.tests.sh convention any new gate should follow.
  • Commits bbd6454 and 211726c on the merged feature/281-triageable-review branch — the before/after pair.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions