T-OTX2-setup-seeds-pytest-permission
Status: closed/obsoleted · Impact: low · Complexity: small
Auto-generated from a /sdlc:task-work post-mortem. Review and
promote to open/ready before picking up.
A project that adopts the plugin/lib/ + pytest.ini convention runs its
quality checks through pytest, but Bash(pytest:*) is not granted by
default — the first /sdlc:task-work run stalls on a permission prompt and
needs a manual /config grant plus a uv run --with pytest fallback. This
task has /sdlc:setup seed the Bash(pytest:*) permission when it detects
a pytest-based project, so adoption doesn’t hit that wall on the first run.
Surfaced by T-75LX-establish-plugin-lib-convention.
| Location | Role today |
|---|---|
plugin/skills/setup/SKILL.md | Initializes the docs/planning/<type>/ layout and seeds project config; does not seed a Bash(pytest:*) permission even when the project uses pytest |
plugin/skills/find-quality-checks/ | Detects quality runners (via detect_quality_runners.py) and writes the quality_checks: list to sdlc.yaml; can identify pytest but does not wire up the corresponding Bash permission |
.claude/settings.json (consumer project) | Holds the project’s Bash permission allowlist; Bash(pytest:*) is absent until a human adds it via /config |
plugin/skills/task-work/ (preflight_permissions probe) | Correctly flags the missing pytest permission at task-pickup time — but only after the project has already adopted the convention |
The originating post-mortem records the friction verbatim:
pytestwas not on PATH / not permitted initially; needed a/configgrant ofBash(pytest:*)plus auv run --with pytestfallback. Thepreflight_permissionsprobe flagged it correctly; projects adopting this pytest-based lib convention should seedBash(pytest:*)at setup.
The probe catching it is the correct safety net, but the ergonomic fix is to seed the permission proactively when setup already knows the project is pytest-based, so the first run doesn’t stall.
Proposed
Section titled “Proposed”When /sdlc:setup (or /sdlc:find-quality-checks, whichever owns
permission seeding) detects that the project uses pytest — a pytest.ini
at the root, a pytest entry in the detected quality runners, or a
plugin/lib/-shaped layout — it adds Bash(pytest:*) to the project’s
.claude/settings.json permission allowlist. Idempotent: re-running setup
on a project that already has the grant is a no-op.
Approach
Section titled “Approach”- Decide the owner:
/sdlc:setupvs/sdlc:find-quality-checks. The latter already probes for runners (detect_quality_runners.py) and knows when pytest is in play, so it’s the natural seeding point — butsetupis what runs first on adoption. Resolve where the permission write lands (likelyfind-quality-checkswrites the permission alongside thequality_checks:entry it already manages). - Detect the pytest signal (root
pytest.ini, a pytest quality verb, or theplugin/lib/layout) and, when present, ensureBash(pytest:*)is in.claude/settings.json’s permission allowlist. - Make the write idempotent — skip if the permission is already present.
- Verify on a fresh pytest-based fixture project that setup leaves
Bash(pytest:*)granted and that a second run is a no-op.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
plugin/skills/find-quality-checks/SKILL.md | modify | When pytest is among the selected runners, also seed Bash(pytest:*) into the project’s .claude/settings.json allowlist |
plugin/skills/find-quality-checks/detect_quality_runners.py | modify | Surface a pytest-detected signal the skill can act on for permission seeding (if not already exposed) |
plugin/skills/setup/SKILL.md | modify | Cross-reference / trigger the permission seed when the adopted layout is pytest-based |
(Ownership split between setup and find-quality-checks is the open
decision in Approach step 1; the touched files narrow once that’s settled.)
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: Running setup (or find-quality-checks) on a project with a root
pytest.iniresults inBash(pytest:*)present in the project’s.claude/settings.jsonpermission allowlist. - AC-2: A second run on the same project does not duplicate the permission entry (idempotent).
- AC-3: On a project with no pytest signal, no
Bash(pytest:*)permission is added. - AC-4: After seeding, a
/sdlc:task-workrun that invokes pytest does not stall on aBash(pytest:*)permission prompt.
Out of scope
Section titled “Out of scope”- Seeding permissions for other runners (ruff, mypy, etc.). This task is scoped to the pytest gap the lib convention introduced; a general “seed all detected-runner permissions” pass is a separate decision.
- Adding the
uv run --with pytestfallback to any skill — that fallback already works ad hoc; this task removes the need for it by granting the permission up front. - Changing the
preflight_permissionsprobe. It already flags the gap correctly; this task makes the gap not occur in the first place.
Dependencies
Section titled “Dependencies”- none
Discovery context
Section titled “Discovery context”Spawned by /sdlc:task-work post-mortem of T-75LX-establish-plugin-lib-convention on 2026-05-23.
Dedup search (spawn-from-post-mortem)
Section titled “Dedup search (spawn-from-post-mortem)”Bullet: pytest was not on PATH / not permitted initially; needed a /config grant of Bash(pytest:) plus a uv run —with pytest fallback. The preflight_permissions probe flagged it correctly; projects adopting this pytest-based lib convention should seed Bash(pytest:) at setup. Keywords searched: preflight_permissions, pytest-based, convention, permitted, initially, correctly, fallback, projects Excluded: 2026-05-23-establish-plugin-lib-convention Top candidates (score / status / headline):
- 26 / closed/done / 2026-05-21-task-work-step-6-inline-impl-fallback — /sdlc:task-work Step 6 declares Agent-tool dependency or describes inline fallback
- 19 / closed/done / 2026-05-20-investigate-sandbox-multiline-commit-denial — Document Claude Code sandbox fallback for the heredoc commit-message pattern
- 19 / open/draft / 2026-05-23-add-lease-protocol-library-and-schemas — Add lease-protocol library and payload schemas
- 17 / closed/done / 2026-05-21-project-local-skill-extension-mechanism — Project-local skill extension / shadowing mechanism
- 13 / closed/done / 2026-05-20-task-branches-use-task-prefix — Use task/
prefix for task-work branches (was feat/) Decision: SPAWNED