Skip to content

T-AVDD-ac-grep-allow-legacy-ref-marker

Status: closed/superseded · Impact: medium · Complexity: small

Auto-generated from a /sdlc:task-work post-mortem. Review and promote to open/ready before picking up.

Tasks whose ACs are shaped as “grep returns zero hits for the old path/symbol” (a common shape for migrations) routinely match legitimate prose: comments documenting the migration as an anti-pattern, test constants intentionally encoding the forbidden string for regression coverage, changelog references. The implementer of T-G834-move-plugin-runtime-state-to-sdlc-dir had to rephrase comments and assemble a test constant from string fragments (".claude" + "/" + "worktrees/") just to satisfy the grep gate. An opt-in # allow-legacy-ref: <token> marker on a single line would let prose document migration history without weakening the AC’s coverage of real regressions.

LocationRole today
The setup_planning.pyandrun_evals.py comments documenting<migrated from v2 — no role recorded>
A test constant FORBIDDEN_CLAUDE_WORKTREES_LINE in<migrated from v2 — no role recorded>

Path-grep ACs that need to forbid a token but tolerate a finite number of deliberate references support a single-line opt-in marker:

# allow-legacy-ref: .claude/worktrees/ (documents the pre-migration layout)

Lines carrying this marker are excluded from the grep’s match set. The marker names the exact token being excused (so reviewers can audit every excused line), and a free-form trailing comment captures the reason.

The reference implementation is a small wrapper script (e.g. plugin/scripts/grep_with_allow.py) that runs the underlying grep, post-filters out lines bearing a matching # allow-legacy-ref: <prefix> annotation, and exits zero/nonzero on the filtered count. ACs that adopt it cite the wrapper instead of bare grep.

  1. Decide the marker syntax. Default proposal: a per-line trailing comment of the form # allow-legacy-ref: <token>, where <token> must appear on the same line for the suppression to apply. Strict per-line scoping avoids “this whole file is excluded” ambiguity.
  2. Implement plugin/scripts/grep_with_allow.py (new). Wraps grep -rn -E <pattern> <paths>, post-filters lines carrying # allow-legacy-ref: <substring-of-match>, prints surviving matches to stdout, exits zero iff zero matches survive.
  3. Add a small test fixture (e.g. plugin/scripts/test_grep_with_allow.py) covering: match with no marker (fail), match with matching marker (suppress), match with non-matching marker (fail), nested directory traversal.
  4. Document the marker in plugin/conventions/ (likely a short new doc, or appended to an existing AC-pattern doc if one exists).
  5. Optionally retrofit setup_planning.py’s test constant assembly and run_evals.py comments to use the marker — the originating task already shipped without the marker, so this is cleanup not a blocker.
LocationKindChange
plugin/scripts/grep_with_allow.pynewwrapper that
plugin/scripts/test_grep_with_allow.pynewfixture
plugin/conventions/<new-or-appended>.mdmodifydocument the marker
plugin/skills/setup/setup_planning.pymodifyadopt the
plugin/skills/setup/tests/run_evals.pymodifyrestore
  • AC-1: plugin/scripts/grep_with_allow.py -E '\.claude/worktrees/' plugin/ exits zero on a tree where every literal occurrence of the forbidden token sits on a line bearing # allow-legacy-ref: .claude/worktrees/ and exits nonzero on a tree that contains an un-annotated occurrence.
  • AC-2: A new fixture in plugin/scripts/test_grep_with_allow.py pins the suppress / non-suppress / mismatched-token semantics.
  • AC-3: At least one existing path-grep AC in the plugin (the originating task’s AC-1 is the canonical case) is rewritable against the wrapper without weakening the regression it protects.
  • Generalizing the marker beyond grep (e.g. teaching the audit runner or the SKILL.md linter about it). Path-grep ACs are the observed pain point; expanding scope is a follow-up.
  • Migrating every existing grep AC in the plugin to use the wrapper. This task ships the mechanism; adoption is per-task.
  • none

Spawned by /sdlc:task-work post-mortem of T-G834-move-plugin-runtime-state-to-sdlc-dir on 2026-05-22.

Bullet: AC-1 grep matched legitimate comments documenting the migration as an anti-pattern (in setup_planning.py, run_evals.py) and one test constant (FORBIDDEN_CLAUDE_WORKTREES_LINE) - required rephrasing comments and assembling the test constant from string fragments. Awkward; suggests path-grep ACs ought to allow an opt-in # allow-legacy-ref: marker for prose that documents migration history without weakening the AC. Keywords searched: forbidden_claude_worktrees_line, allow-legacy-ref, setup_planning, anti-pattern, documenting, legitimate, rephrasing, assembling Excluded: 2026-05-22-move-plugin-runtime-state-to-sdlc-dir Top candidates (score / status / headline):

  • 16 / closed/done / 2026-05-19-co-locate-skill-specific-scripts — Co-locate skill-specific scripts under their skill dir; promote when shared
  • 15 / closed/done / 2026-05-20-pluralize-recognizes-backlog-as-plural — pluralize() should treat ‘backlog’ as already-plural
  • 10 / planning/draft / 2026-05-21-promote-pluralize-to-shared-helper — Promote pluralize() + IRREGULAR_PLURALS to a shared helper
  • 9 / closed/done / 2026-05-20-regen-walks-skill-co-located-scripts — regen.mjs walks plugin/skills//*.py for script reference pages
  • 7 / closed/done / 2026-05-19-sdlc-setup-seeds-hooks-gitignore-unignore — Have /sdlc:setup seed the .claude/hooks/ un-ignore lines in .gitignore Decision: SPAWNED

← Back to Tasks