Status: Active — awaiting Card A PR open
Date: 2026-05-13 UTC
Owner: qa-agent (file findings only; operator decides per [[project_qa_agent]])
Triggering design doc: docs/architecture/queue-cpp-scaffold-review-2026-05-13.md (#2032, merged 2026-05-13T23:55:56Z UTC)
ADRs in scope: ADR-0085 (vcpkg version pinning), ADR-0086 (lockfile policy), ADR-0087 (CI manifest guard)
Refs: #2021, #2028, #2030, #2031
This plan is written by the qa-agent persona. It validates that reality matches architectural intent. It does not gate merges. Findings are surfaced to the operator as inline PR review comments and the operator decides remediation. Read-only against in-flight branches; this worktree never modifies Card A, D, or B.
| Card | Owner | Scope | Critical path | Status as of 2026-05-13 UTC |
|---|---|---|---|---|
| A | feature-developer | queue/vcpkg.json full audit + exact-pin migration against builtin-baseline=3508985146f1b1d248c67ead13f8f54be5b4f5da. Unblocks #2021. |
Yes | PR not yet opened |
| D | software-architect | ADR-0085 status Proposed → Accepted |
No (parallel) | ADR drafted at Proposed |
| B | feature-developer (post-D, post-A) | CI vcpkg-manifest-check job for #2030 |
No (hardening) | Sequenced after Card A merges green |
Cards C, E, F are out of scope for this validation pass (see §6).
queue/vcpkg.json audit + exact-pin| # | Check | How it is verified | Pass signal |
|---|---|---|---|
| A-1 | Clean Docker build from a fresh clone of Card A's branch | git clone … && git checkout <card-a-branch> && docker build queue/ (or equivalent heroku container:push simulation) |
vcpkg install phase exits 0; compile phase produces /app/bin/queue-server; final image tag created |
| A-2 | No vcpkg version/feature errors in build log | grep -E "(does not have a feature|could not satisfy|not in database|version not found)" build.log |
Zero matches |
| A-3 | Exact-pin migration complete | git diff origin/main..HEAD -- queue/vcpkg.json |
Every dependency block has "version" and no "version>=" remains |
| A-4 | Baseline SHA unchanged | jq -r .['"'"'builtin-baseline'"'"'] queue/vcpkg.json on Card A's branch |
Returns 3508985146f1b1d248c67ead13f8f54be5b4f5da (baseline bump is Card E, not Card A — per design doc §F + §15-E) |
| A-5 | Version rationale documented | queue/vcpkg-notes.md exists (per design doc §C and Card A AC) or PR body contains per-package rationale or inline comments in vcpkg.json |
One of the three present |
| A-6 | --depth 1 not reintroduced in Dockerfile |
grep -n "git clone" queue/Dockerfile |
Line 32 (or wherever the vcpkg clone lives) contains git clone https://github.com/microsoft/vcpkg.git with no --depth flag |
| A-7 | drogon feature set correct | jq '.dependencies[] \| select(.name=="drogon") \| .features' queue/vcpkg.json |
["postgres"] exactly — openssl is not in the list (regression check for #2031) |
| A-8 | libpqxx version resolves | jq '.dependencies[] \| select(.name=="libpqxx") \| .version' queue/vcpkg.json |
Returns a version that exists at the pinned baseline (expected 7.9.2 per design doc §3 timeline, but any baseline-resident exact version satisfies this AC) |
| A-9 | All 9 packages exact-pinned | jq '.dependencies[] \| .name' queue/vcpkg.json \| wc -l and jq '.dependencies[] \| select(.version)' queue/vcpkg.json \| jq -s length |
Both equal 9 (drogon, nlohmann-json, spdlog, sentry-native, curl, openssl, libpqxx, jwt-cpp, gtest) |
| A-10 | No scope creep: application code untouched | git diff --name-only origin/main..HEAD |
Only queue/vcpkg.json and optionally queue/vcpkg-notes.md modified. CMakeLists.txt, src/, include/, tests/ unchanged. Flag — do NOT reject — if Dockerfile changes are present, since Dockerfile-side fixes are explicitly in #2028 scope |
| A-11 | PR body attests local verification | PR description contains "Verified: vcpkg install ran clean in container on YYYY-MM-DD UTC" per design doc §C (Invariant P-1) |
Present |
| A-12 | Staging deploy proof (post-merge) | After Card A merges to main, SRE attempts heroku container:push web -a raxx-queue-staging and runs Phases 1-5 of #2021 |
Deploy progresses through Phases 1-5 without a 4th vcpkg-class bug. If a 4th bug surfaces, Card A is incomplete — file a follow-up finding rather than re-open A |
Note on A-12: SRE executes the deploy. QA monitors the result. QA does not gate the deploy attempt.
| # | Check | How it is verified | Pass signal |
|---|---|---|---|
| D-1 | ADR status is Accepted |
grep -E "^\\*\\*Status:\\*\\*" docs/architecture/adr/0085-vcpkg-version-pinning-policy.md |
Reads **Status:** Accepted |
| D-2 | Acceptance date stamp present | Same file, **Date:** or new acceptance footer |
2026-05-13 UTC (or a later date if operator review takes additional time — UTC always per [[feedback_utc_times]]) |
| D-3 | Acceptance notes reference the triggering incident | ADR body | Mentions the 2026-05-13 UTC three-bug deploy incident OR explicitly links to docs/architecture/queue-cpp-scaffold-review-2026-05-13.md |
| D-4 | References design doc + Card A as first implementation | ADR body | Both links present |
| D-5 | ADR lives in docs/architecture/adr/ |
ls docs/architecture/adr/0085-vcpkg-version-pinning-policy.md |
File exists at expected path |
| D-6 | Consequences section addresses operator objections (if any surface) | ADR body | Either: no objections surfaced, OR each objection has a one-paragraph rebuttal in the Consequences section |
vcpkg-manifest-check (sketch only; full plan post-D)This sketch will be re-validated against Card B's actual PR when it opens.
| # | Check | How it is verified | Pass signal |
|---|---|---|---|
| B-1 | New job exists in .github/workflows/ |
git diff --name-only origin/main..HEAD -- .github/workflows/ |
New workflow file OR addition to an existing queue-specific workflow |
| B-2 | Trigger is correct | Workflow on.pull_request.paths block |
Includes queue/vcpkg.json and queue/Dockerfile |
| B-3 | Runs vcpkg install --dry-run |
Workflow run: step |
Contains vcpkg install --dry-run --triplet x64-linux --x-manifest-root=queue/ |
| B-4 | Full vcpkg clone (no --depth 1) |
Workflow setup step | git clone https://github.com/microsoft/vcpkg.git with no --depth flag |
| B-5 | Cache configured for <2 min completion | Workflow contains actions/cache@v3 (or v4) keyed on hashFiles('queue/vcpkg.json') |
Cache step present; target warm-cache time documented in PR body |
| B-6 | Dockerfile --depth regression check |
Workflow contains a grep step that fails if queue/Dockerfile contains git clone --depth for the vcpkg clone |
Present per design doc §6 |
| B-7 | Negative test evidence | PR body or workflow comment shows a deliberately-broken vcpkg.json (invalid feature) failed the check |
Demonstrated |
| B-8 | Non-queue/** PRs unaffected |
Workflow paths filter limits firing to queue-touching PRs |
Verified — does not add CI time to other PRs |
| B-9 | Fails PR on non-zero vcpkg exit | Default GH Actions behavior; confirm no continue-on-error: true |
No suppression |
These checks validate the spirit of the design doc, not just the letter of each card's AC.
Design doc §2 declares: "A vcpkg.json must be verified against its pinned builtin-baseline via a clean vcpkg install in a fresh container before any PR that touches it is opened. No exceptions. No fix-forward."
Card A's end state must satisfy this. Verification: - The PR body contains the verification attestation (A-11). - The CI guard (Card B) will, post-merge, enforce this on every subsequent PR. - Until Card B lands, A-11 + the operator's "no more fix-forwards" rule are the controls.
The design doc §3 ("Why fix-forward is wrong here") rejects the bug-by-bug-one-line-PR pattern. Card A must be one PR that audits all 9 packages at once, not a chain of small PRs.
Verification: Card A's PR diff covers all 9 packages with documented version choices. If only the libpqxx fix lands and other packages stay on version>=, Card A is incomplete and QA flags this as a process-invariant violation (P-1 + the operator's stated remediation pattern).
Per [[project_language_tier_philosophy]], Queue is the first tier-1 C++ service; Velvet and MQ-A rewrites are anticipated. ADR-0085's policy is written as a tier-1 policy, not a Queue-specific policy.
Verification: - ADR-0085 §"Applies to" names Queue and future tier-1 services (already correct in the draft). - The policy does not depend on Queue-specific facts (e.g., Drogon, libpqxx) — it applies generically to any vcpkg manifest at a pinned baseline. - The mandatory-validation step is service-agnostic.
If Velvet's C++ rewrite scaffold PR opens at a later date, this validation plan can be re-used by swapping queue/ paths for velvet/ paths. No re-derivation of policy needed.
gh pr list --search "vcpkg audit" or similar for the Card A PR opening. The branch will originate from main per _shared-conventions.md.git diff, jq, grep. ~5 min.sh
cd $(mktemp -d)
git clone https://github.com/raxx-app/TradeMasterAPI.git
cd TradeMasterAPI && git checkout <card-a-branch>
docker build queue/ 2>&1 | tee /tmp/card-a-build.log
Expected wall-clock: ~20 min cold-cache, <2 min warm.raxx-queue-staging deploy attempts. If a 4th vcpkg-class bug surfaces, file a follow-up issue (type:reliability, area:queue, link to this plan).ADR-0085 is a doc-only change. Validation is purely static: 1. Read the post-merge ADR file. 2. Run §2.2 checks D-1 through D-6. 3. Post a single inline review on the Card D PR with the checklist outcome. ~10 min.
When Card B's PR opens, re-derive the §2.3 checklist into a full plan and execute:
1. Static workflow YAML review (B-1 through B-9).
2. Trigger the workflow on the PR itself (it self-tests when modifying .github/workflows/). Confirm pass on the current valid manifest.
3. Validate negative-test evidence in PR body (B-7).
4. Post inline review.
QA does not block merges. These criteria are advisory and surface as recommendations to the operator.
| Outcome | Trigger |
|---|---|
| Pass (recommend merge) | All A-1 through A-11 green. A-12 deferred to post-merge SRE deploy. |
| Pass with follow-up | A-1 through A-9 green; A-10 shows scope creep that operator may want to accept (e.g., a typo fix in a comment in CMakeLists.txt) or A-5 has rationale in only one of the three accepted locations and that location is shallow. File follow-up issue but do not block. |
| Recommend changes (non-blocking) | One or more of: A-3 incomplete (still version>= somewhere); A-4 baseline changed without explicit Card-E scope claim; A-6 --depth 1 regression; A-7 openssl feature back in drogon list. Comment surfaces the specific gap; operator decides. |
| Recommend hold | A-1 fails (build broken). The PR cannot demonstrate Invariant P-1. Comment recommends author re-runs vcpkg install locally and iterates before re-requesting review. |
| Outcome | Trigger |
|---|---|
| Pass | D-1 through D-5 green; D-6 either no-objections-surfaced or addressed in Consequences. |
| Pass with follow-up | D-1 through D-5 green; D-6 reveals operator objection that ADR acknowledges without resolution — file follow-up to track. |
| Recommend changes | D-1 not flipped (still says Proposed); D-3 missing incident reference; D-4 missing design-doc link. |
Refined when Card B opens. Initial sketch: pass if B-1 through B-9 green; recommend changes if any of the regression checks (B-4, B-6) are missing — those are the ones that prevent today's incident from recurring.
[[feedback_pre_launch_digest_notifications.md]], routine QA outputs go in the daily digest, not per-event pings.This validation plan does not cover:
docs/sdlc/cpp-service-onboarding.md) — doc-only, future SOP. QA validation can apply the same template when that PR opens.raxx-queue-staging Heroku app, DATABASE_URL provisioning, sqitch deploy step are SRE responsibilities (#2021 addresses the DB schema gap separately).version>= floors, security-agent's nightly run will catch it.Risk R-1: Card A's audit may surface a 4th or 5th package whose pinned version is unavailable at the baseline. The design doc anticipated this (§3 "Bug catalogue" row 4+). If this happens, Card A's PR may take longer than the 2-4 hour size estimate. QA does not block on duration — just notes it.
Risk R-2: If the operator decides during Card D review to flip the policy to version#N (port-revision pin, per ADR-0085 §"Alternatives Considered"), Card A's exact-version choices will need to be re-evaluated. Low probability — design doc §C explicitly rejects version#N as overkill for v1.
Risk R-3: Card B may surface a vcpkg tooling version mismatch (the dry-run flag's behavior varies across vcpkg releases). The design doc OQ-3 anticipates this. If Card B's CI uses a different vcpkg HEAD than the Card A author's local container, version-resolution differences could produce false-positive CI failures. Mitigation: Card B pins the vcpkg tool clone to the baseline SHA, matching Card A's authoring environment.
Assumption A-1: SRE executes the post-Card-A staging deploy attempt and surfaces the result. QA does not run heroku container:push against raxx-queue-staging.
Assumption A-2: Card A's PR author follows _shared-conventions.md and branches from main. QA verifies via git log origin/main..HEAD showing only Card-A-authored commits.
This plan implements the qa-agent persona's stated responsibility per [[project_qa_agent]]: confirm reality matches architectural intent, file findings, do not gatekeep. The design doc author (software-architect) and the Card A implementer (feature-developer) own the work; this plan validates whether the work meets the design's bar.