Skip to content

T-HQ56-safe-grep-helper-for-ac-shell

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.

Acceptance criteria that take the shape “grep X across this directory returns zero matches” are common (negative-presence ACs: “no caller writes raw git push”, “no script imports the legacy module”, etc.). Each one currently re-derives its own exclusions for test files, vendored dependencies, and build artifacts. The footgun is live: the lease-CLI’s AC-10 shipped twice — the first cut greped recursively and matched a test file’s docstring containing “git push” plus compiled bytecode (__pycache__/*.pyc). A shared helper with safe defaults would prevent that across all future grep-based ACs. Cite T-QC31-add-sdlc-lease-cli-commands for the live incident.

LocationRole today
apps/sdlc/lib/services/*/ops/The op-verb roster (D-H7FS-op-substrate-surface). No verb covers “grep these source files, excluding the obvious noise.”
Grep-based ACs across docs/planning/tasks/Each negative-presence AC spells out its own exclusions inline in the AC text; the exclusion logic is per-AC and nothing is shared.

A new sdlc CLI op verb — deterministic ops are CLI verbs per D-H7FS-op-substrate-surface; proposed home sdlc project safe-grep, path confirmed at definition — that exposes:

  • sdlc project safe-grep <pattern> <dir> — recursive grep with sane defaults: excludes tests/, *.test.ts, node_modules/, .git/, dist/, and *.lock; returns matches in a stable path:line:text shape; exits 0 on no-match and 1 on match, so an AC invocation reads the exit code directly.
  • An --include-tests opt-in flag for the rare AC that actually wants to see test-file matches.
  • Honors an allow-legacy-ref: <token> opt-in marker on individual source lines (any comment syntax). When a line carries this marker AND the line’s content contains the named <token>, the line is excluded from the 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. This subsumes T-AVDD-ac-grep-allow-legacy-ref-marker.
  • A short guidance note explaining when an AC should reach for this op vs raw grep, and when to use the allow-legacy-ref: marker on a forbidden-token line that legitimately documents migration history.

Existing grep-based ACs (the lease AC-10 shape, any other negative- presence ACs we find in the planning corpus) get retrofitted in a follow-up sweep — out of scope here.

  1. Survey the existing grep-based ACs in docs/planning/tasks/ to confirm the common exclusion set. Look for “grep” appearing in AC text.
  2. Confirm the op’s home on the D-H7FS surface. Proposed: project safe-grep — the grep runs over the consuming project’s tree, and project is the consuming-project hub.
  3. Implement the op and its tests (apps/sdlc/lib/services/project/tests/safe-grep.test.ts).
  4. Document in the op descriptor’s summary/help text, and add a pointer for AC authors in the Acceptance-criteria guidance of apps/sdlc/lib/model/entities/task/implementation-ready.md.
LocationKindChange
apps/sdlc/lib/services/project/ops/safe-grep.tsnewThe op verb: recursive grep + standard exclusions + --include-tests opt-in + allow-legacy-ref filtering.
apps/sdlc/lib/services/project/tests/safe-grep.test.tsnewTests covering: default exclusions hide test/vendored matches; pattern matches still surface in real source; --include-tests re-enables test-file matches; marker suppress/mismatch semantics.
apps/sdlc/lib/model/entities/task/implementation-ready.mdmodifyOne-line pointer in the Acceptance-criteria guidance: reach for the op for negative-presence ACs.
  • AC-1: sdlc project safe-grep "<some-pattern>" apps/sdlc/ excludes matches under tests/, node_modules/, and .git/ by default.
  • AC-2: sdlc project safe-grep "<pattern>" <dir> --include-tests includes test-file matches in the output.
  • AC-3: Exit code is 0 when there are no matches and 1 when there are matches, so an AC can invoke the op directly as a gate: sdlc project safe-grep "git push" apps/sdlc/lib/services/lease/ fails the check iff matches survive.
  • AC-4: At least one existing AC in the planning corpus is retrofitted to call the op as a proof of usability.
  • AC-5: A source file containing the literal forbidden token on a line carrying an allow-legacy-ref: <token> marker (where <token> is the literal forbidden token) is excluded from the match set. A line containing the forbidden token without the marker is still matched.
  • AC-6: An allow-legacy-ref: marker that names a different token than the line actually contains does NOT exclude the line — the marker must name the exact forbidden token being excused (audit trail).
  • AC-7: The op’s help text or the service README documents the marker shape and at least one worked example.
  • Sweeping every grep-based AC across docs/planning/tasks/ to retrofit them. Track that as a follow-up if AC-4 surfaces several candidates.
  • Building a richer code-search tool (e.g. AST-aware). The need here is just “grep with safer defaults”, not a full search index.
  • none

Spawned by /sdlc:task-work post-mortem of T-QC31-add-sdlc-lease-cli-commands on 2026-05-23.

Bullet: AC-10 grep test footgun. First cut greped the CLI source directory recursively and matched the test file’s docstring containing ‘git push’ plus a compiled pycache/*.pyc. Fixed by greping only top-level .py files in the CLI dir (excluding tests/ and pycache/). Suggests: grep-based ACs should default to skipping test files and bytecode, OR a project-wide grep helper that already handles those exclusions would be safer than each AC re-deriving them. Keywords searched: project-wide, recursively, re-deriving, containing, grep-based, exclusions, directory, docstring Excluded: 2026-05-23-add-sdlc-lease-cli-commands Top candidates (score / status / headline):

  • 14 / closed/superseded / 2026-05-20-setup-obsidian-backlog-dir-mismatch — Fix /sdlc:setup —obsidian writing backlog.base into singular backlog/ dir
  • 10 / in-progress / 2026-05-23-add-lease-protocol-library-and-schemas — Add lease-protocol library and payload schemas
  • 7 / closed/done / 2026-05-20-pluralize-recognizes-backlog-as-plural — pluralize() should treat ‘backlog’ as already-plural
  • 7 / in-progress / 2026-05-22-move-plugin-runtime-state-to-sdlc-dir — Migrate sdlc plugin runtime state from .claude/ to .sdlc/
  • 7 / closed/done / 2026-05-23-establish-plugin-lib-convention — Establish plugin/lib/ convention for Python libraries Decision: SPAWNED

Bullet: AC-10’s grep guard tripped on a comment string. The pre-existing CLI test test_no_git_push_shells_in_cli does a bare substring grep for ‘git push’. Adding the namespace-guard wiring required a comment that contained the phrase (‘translate a git push plumbing error into …’); had to rephrase to ‘git-plumbing error’ to satisfy the grep. The substring-grep AC has known false-positive shape — see T-HQ56-safe-grep-helper-for-ac-shell (already spawned from the CLI task’s post-mortem) for the fix. Keywords searched: test_no_git_push_shells_in_cli, safe-grep-helper-for-ac-shell, namespace-guard, substring-grep, false-positive, pre-existing, git-plumbing, substring Excluded: 2026-05-23-add-lease-namespace-conflict-guard Top candidates (score / status / headline):

  • 34 / closed/done / 2026-05-21-run-quality-checks-isolates-pre-existing-drift — run_quality_checks.py only fails on drift the current branch introduced
  • 14 / planning/draft / 2026-05-21-audit-entities-baseline-allow — audit_entities.py: distinguish pre-existing drift from PR-introduced drift
  • 13 / closed/done / 2026-05-21-pr-check-cursor-bootstrap-misses-existing-comments — pr-check cursor: pin bootstrap behavior and filter self-posted orchestrator comments
  • 8 / planning/draft / 2026-05-23-dogfood-baseline-smoke-test — Dogfood smoke-test script for new quality-check verbs before declaring done
  • 6 / planning/draft / 2026-05-23-start-task-drops-orphan-stashes — start_task.py detects pre-existing stashes referencing files absent on the rebase target and prompts to drop them Decision: LINKED-EXISTING 2026-05-24-safe-grep-helper-for-ac-shell Rationale: Bullet explicitly self-links to this already-spawned task (the AC-10 substring-grep footgun is precisely what this task fixes). Override the scorer’s SPAWNED verdict — keyword overlap on the top candidates is about pre-existing-drift handling in run_quality_checks, not the AC-shell grep helper. This is the canonical destination for the bullet. Linked from the post-mortem of T-K3RR-add-lease-namespace-conflict-guard on 2026-05-24.

← Back to Tasks