T7.6 - CR-014/D2/D9/D10: the Ready for QA gate, notification only, shipped off
Marlena's ask: QA sees inbound work ahead of time, not after the fact. The rung: 'Ready for QA' sits between In Progress and QC in BOTH ladders (wp-creation-app.js STATUS_ORDER, server/app.py STATUS_ORDER) and in Field View's list - inside the T7.3 transition model, not beside it: entering it from an unreleased state crosses the release gates, and 'Issue' (hold) stays a branch. The dashboard filter and the navigator grouping learned the state from the ladder without their own edits. Who hears (D2): the QA GROUP, a multi-pick of project members on the SOP wizard's team step, stored as account ids at data.sop.project.qaGroupIds. Entering Ready for QA emails that list and nobody else. A rejection emails the owner AND the same list (amended answer), returns the package to In Progress, and REQUIRES a fresh comment - server-enforced on both write paths (the first version accepted any old comment already on the record, which made every rejection after the first one free; the gate now demands a new entry). Accept and reject are real buttons on the release banner; the comment modal enforces its field; qa_ready / qa_rejected / status_changed all land in the audit history. The link (X1): wp_link() now opens THE package - wp-creation-index.html ?project&wp=<id>, which the creator boots directly and login.html?next= round-trips for a signed-out recipient. It previously pointed at the suite root, which is exactly the failure X1 names; assignment mail inherits the fix. Email discipline (D10 + standing rules): ships OFF (the stored setting the admin console already owns; PUT /api/settings is admin-only, 403 for anyone else, and audited). With it off, transitions write outbox rows marked 'skipped' and the sink receives nothing. With it on, the probe runs a REAL SMTP conversation against an in-process capture sink and asserts the count and the exact recipient set. A dead SMTP host leaves a 'failed' outbox row with the error recorded. The SMTP password exists only in the environment. DEVIATION, stated: the task's Do-paragraph asks the email to include location and a scope summary; the done-when list (and CLAUDE.md) says no customer IP in a message body. The done-when wins: bodies carry the WP number, who moved it, and the deep link. A location canary planted on the package is asserted absent from every captured message. If the fuller body is wanted, that is a product call - needs Nick. Found while building, logged not fixed (BL-021): project_sop_team() reads sop.data['project'], a path pushSOP never writes - the critical-reopen email has never actually reached the PM/CM. One-line fix, owned by T9.9. Field View (D9): 'Ready for QA' is carried by TEXT on the card at 390px. Verification (each probe run alone): NEW tests/qa_gate_check.py 40/40. Regressions: hold_check 50/50, pipeline_check 44/44, aggregates_check 16/16, frame_check 39/39, validation_check 83/83. Items: CR-014, D2, D9, D10 (X1, X3 honored) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -280,6 +280,7 @@ python tests/form_structure_check.py # F6/D3 - rail, disclosure, one open sectio
|
||||
python tests/hold_check.py # CR-015/A1/D4 - the hold clears, gates hold 50 checks
|
||||
python tests/warning_check.py # A2 - one warning, a badge from anywhere 17 checks
|
||||
python tests/triage_check.py # A6 - the sidebar answers the stand-up 16 checks
|
||||
python tests/qa_gate_check.py # CR-014/D2/D9/D10 - QA gate + capture sink 40 checks
|
||||
```
|
||||
|
||||
**Three probes were re-pointed at `T7.1`.** `sections_check.py` 5b drove the live
|
||||
|
||||
@@ -457,3 +457,20 @@ deliberately deferred.
|
||||
departure intentional, not a blanket disabling of the guard. If it is to be
|
||||
kept, `T7.2`'s side navigation is the place to make saving obvious enough that
|
||||
the prompt stops being a surprise.
|
||||
|
||||
### BL-021 — `project_sop_team()` reads a path `pushSOP` never writes
|
||||
|
||||
- **Found during:** T7.6
|
||||
- **Where:** `server/app.py`, `project_sop_team()`
|
||||
- **What:** the function reads `sop.data["project"]`, but `ProjectData.pushSOP`
|
||||
stores every SOP row as `data = {sop: ..., state: ...}` — the project block
|
||||
lives at `data["sop"]["project"]`. The lookup therefore always returns `[]`,
|
||||
and the critical-constraint-reopened email (Phase S wave) has never actually
|
||||
reached the PM or CM it names as recipients; only the owner and distribution
|
||||
got it. Found while writing `project_qa_group()` for `CR-014`, which reads the
|
||||
correct path (and tolerates the flat one for safety).
|
||||
- **Why not now:** T7.6 is scoped to the QA gate; fixing another feature's
|
||||
recipient list inside it is the drive-by CLAUDE.md forbids. The fix is one
|
||||
line, but it deserves its own verification against the capture sink.
|
||||
- **Suggested wave or follow-up:** wave 9 backlog sweep (`T9.9`), verified with
|
||||
the `tests/qa_gate_check.py` sink pattern.
|
||||
|
||||
Reference in New Issue
Block a user