T-NUSP-run-quality-checks-logs-cwd-and-forwards-project-root
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.
run_quality_checks.py’s behavior depends on the cwd it was invoked
from — audit_entities.py failed in the lease-CLI task’s first run
because the runner was started from a non-worktree cwd, and the same
verb invoked directly from the worktree root passed 12/12. The
runner gives no diagnostic about where it started, so the operator
has to spelunk to figure out why. Two cheap fixes close the gap:
(1) log the cwd at the start of every run, and (2) when a verb
supports --project-root, forward the runner’s resolved
project-root to it so the verb stops inheriting whatever cwd the
runner happened to have. Cite
T-QC31-add-sdlc-lease-cli-commands for the live incident.
| Location | Role today |
|---|---|
plugin/scripts/run_quality_checks.py | Runs each declared verb in turn, captures exit codes, surfaces FAIL/OK summary. Does NOT log its starting cwd; does NOT inject --project-root into verbs that accept it. |
plugin/scripts/audit_entities.py | Accepts --project-root but receives whatever cwd the runner inherited from its invoker. Failure mode in the lease-CLI task: started in a non-worktree cwd, audited the wrong tree, reported drift. |
sdlc.yaml | Declares the verb list but has no syntax for “this verb supports --project-root, please pass it.” |
Proposed
Section titled “Proposed”run_quality_checks.pylogscwd=<absolute-path>as its first stdout line on every invocation, so a failing run’s transcript always self-documents the entry point.- The runner resolves its own intended project-root (the worktree
root — already known because
sdlc.yamlis discovered relative to it) and forwards it as--project-root <resolved-root>to verbs that accept the flag. Per-verb opt-in via a tiny addition tosdlc.yaml’s verb syntax (e.g.--project-root: trueper verb entry) OR a runner-side allowlist of well-known verbs that support it (smaller surface, easier to land). - Verbs that don’t accept
--project-rootare invoked unchanged.
Approach
Section titled “Approach”- Add the cwd log line as the first thing
main()does after argparse. One commit, trivially reviewable. - Decide the opt-in shape: per-verb config in
sdlc.yamlvs runner-side allowlist. Recommend the allowlist first (smaller blast radius) and graduate to the per-verb config if/when a third verb wants it. - Implement the forwarding: for each verb in the allowlist,
append
--project-root <resolved-root>to the invocation. - Regression test: a runner invocation from a deliberately wrong
cwd still produces correct verb behavior because the verb
receives the explicit
--project-root.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
plugin/scripts/run_quality_checks.py | modify | Add cwd log line; add --project-root forwarding to a runner-side allowlist of verbs. |
plugin/scripts/test_run_quality_checks.py (or wherever existing tests live) | modify | Add tests: (a) cwd log line is present in stdout; (b) audit_entities.py invoked from wrong cwd still audits the correct root. |
plugin/scripts/run_quality_checks.py module docstring | modify | Document the cwd-log invariant and the project-root forwarding allowlist as a maintenance note. |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: Every invocation of
run_quality_checks.pyprintscwd=<absolute-path>as its first stdout line. - AC-2: A regression test invokes the runner from a non-
worktree cwd and asserts
audit_entities.pystill audits the correct project root (via the forwarded--project-rootflag). - AC-3: Verbs not in the runner’s
--project-root-capable allowlist are invoked unchanged — backward-compatible by default. - AC-4: A failing run’s stderr / stdout transcript is now
self-diagnostic for the cwd-confusion class of failure (i.e.
a future operator hitting the same issue can read the
cwd=...line and immediately spot the mismatch).
Out of scope
Section titled “Out of scope”- Promoting the allowlist to a per-verb config field in
sdlc.yaml. Tracked as a future extension; the allowlist is enough for slice 1. - Forcing the runner itself to
chdirto the worktree root. Cwd is sometimes load-bearing for verbs that resolve relative paths (e.g. test runners); the explicit--project-rootforwarding is the lower-risk fix.
Dependencies
Section titled “Dependencies”- none
Discovery context
Section titled “Discovery context”Spawned by /sdlc:task-work post-mortem of T-QC31-add-sdlc-lease-cli-commands on 2026-05-23.
Dedup search (spawn-from-post-mortem)
Section titled “Dedup search (spawn-from-post-mortem)”Bullet: Quality runner is cwd-sensitive. First run reported audit_entities.py failing even though direct invocation passed (the runner started from a non-worktree cwd). Running from the worktree root made it pass 12/12. Suggests: run_quality_checks.py could log its working directory at start, or each verb could be invoked with an explicit —project-root if the verb supports it. Keywords searched: run_quality_checks, audit_entities, cwd-sensitive, non-worktree, project-root, invocation, directory, reported Excluded: 2026-05-23-add-sdlc-lease-cli-commands Top candidates (score / status / headline):
- 36 / closed/done / 2026-05-21-run-quality-checks-isolates-pre-existing-drift — run_quality_checks.py only fails on drift the current branch introduced
- 25 / closed/done / 2026-05-19-implement-entities-migrate — Implement /sdlc:entities-migrate to apply mechanical schema-drift fixes
- 21 / planning/draft / 2026-05-21-audit-entities-baseline-allow — audit_entities.py: distinguish pre-existing drift from PR-introduced drift
- 16 / closed/done / 2026-05-19-co-locate-skill-specific-scripts — Co-locate skill-specific scripts under their skill dir; promote when shared
- 16 / closed/done / 2026-05-19-task-work-uses-per-project-quality-checks — Make /sdlc:task-work quality-check commands per-project configurable Decision: SPAWNED Rationale: SPAWNED stands. The high-scoring top match (run_quality_checks-isolates-pre-existing-drift) is closed/done and addresses pre-existing-drift baselining, a distinct concern from cwd-logging or —project-root passthrough. The audit-entities-baseline-allow candidate is also about drift baselining, not invocation cwd.