Queue C++ Scaffold — QA Validation Plan
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
0. Persona stance
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.
1. Workstreams in flight
| 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).
2. Per-card acceptance verification checklists
2.1 Card A — 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.
2.2 Card D — ADR-0085 status flip
| # | Check | How it is verified | Pass signal |
|---|---|---|---|
| D-1 | ADR status is Accepted |
grep -E "^\\*\\*Status:\\*\\*" docs/architecture/adr/0126-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/0126-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 |
2.3 Card B — CI 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 |
3. Architectural intent verification
These checks validate the spirit of the design doc, not just the letter of each card's AC.
3.1 Invariant P-1 — vcpkg.json as executable specification
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.
3.2 No fix-forward regression
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).
3.3 Tier-1 service alignment — propagation to Velvet C++ rewrite
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.
4. Test execution plan
4.1 When Card A's PR opens
- Detect: Watch the
gh pr list --search "vcpkg audit"or similar for the Card A PR opening. The branch will originate frommainper_shared-conventions.md. - Clone PR branch into this worktree's checkout space (read-only); do not push.
- Run static checks (A-3, A-4, A-6, A-7, A-8, A-9, A-10, A-11) using
git diff,jq,grep. ~5 min. - Run Docker build (A-1, A-2):
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.logExpected wall-clock: ~20 min cold-cache, <2 min warm. - Post inline review on Card A's PR with: - Per-AC checkbox table (the §2.1 grid filled in). - Build log summary (lines around any errors, or "build clean — vcpkg install resolved 9 packages in N seconds"). - Any P-1 / fix-forward findings as separate inline comments at specific file:line locations. - Recommendation (advisory only): pass / pass-with-followups / request-changes-non-blocking. QA never sets the PR to "Request changes" in the GitHub UI sense; recommendation lives in the comment body.
- Post-merge monitoring (A-12): subscribe to
raxx-queue-stagingdeploy attempts. If a 4th vcpkg-class bug surfaces, file a follow-up issue (type:reliability,area:queue, link to this plan).
4.2 When Card D lands (status flip on existing ADR file)
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.
4.3 When Card B opens (post-D, sketch refined into full plan)
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.
5. Pass/fail criteria
QA does not block merges. These criteria are advisory and surface as recommendations to the operator.
5.1 Card A — recommendation matrix
| 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. |
5.2 Card D — recommendation matrix
| 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. |
5.3 Card B — recommendation matrix
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.
5.4 How findings surface to the operator
- Inline PR review as the primary surface (Card A, D, B PRs).
- One-line summary in the operator's morning brief if open at digest time.
- No Slack DM unless a CRITICAL finding (e.g., Card A reintroduces a secret to the manifest, or merges with the build broken). Per
[[feedback_pre_launch_digest_notifications.md]], routine QA outputs go in the daily digest, not per-event pings.
6. Out of scope
This validation plan does not cover:
- Card C (
docs/sdlc/cpp-service-onboarding.md) — doc-only, future SOP. QA validation can apply the same template when that PR opens. - Card E (baseline bump to current vcpkg HEAD) — post-v1, separate PR. Re-derive checklist at that time.
- Card F (vcpkg-lock.json evaluation) — post-v1. ADR-0086 currently records "no lockfile for v1"; that decision is correct for now.
- Application-code correctness of the Queue scaffold — Drogon route handlers, libpqxx connection pool, sqitch migrations, GoogleTest suite are not under review here. They are accepted as sound per design doc §F and ADR-0076.
- Heroku platform configuration —
raxx-queue-stagingHeroku app, DATABASE_URL provisioning, sqitch deploy step are SRE responsibilities (#2021 addresses the DB schema gap separately). - Security review of new dependencies — security-agent handles CVE posture per its nightly scan. If Card A's exact-pinned versions surface a CVE delta vs the prior
version>=floors, security-agent's nightly run will catch it. - Performance / load characteristics — out of scope until Phase 2 of #2021 and beyond.
7. Risks and assumptions
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.
8. Acknowledgments
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.