Raxx · internal docs

internal · gated

Rebound Sprint — 2026-05-12

Context: On 2026-05-12 ~05:00 UTC, a naive conflict-resolver script (/tmp/auto-rebase.sh) applied YAML-style "concat both halves" resolution to Python, SQL, and JS files. Seven PRs landed on main with literal conflict markers in source. Emergency recovery PR #1781 reverts all seven and restores __init__.py. This document is the dispatch plan for re-merging the seven reverted PRs and draining 30+ additional backlog cards — path-isolated so no two PRs in the same burst touch the same file.

Root cause reminder: feedback_no_naive_conflict_resolver.md — never apply a single "strip markers" resolver across file types. Python, SQL, and JS require per-type-aware resolution or human review. Sequential merge (rebase one, land it, refetch main, rebase next) eliminates most collisions at source.

Rule for all bursts: Within a burst, NO TWO PRs may touch the same file. Between bursts, wait for all PRs in the prior burst to merge before dispatching the next burst.


Section A: The 7 Reverted PRs — Re-Merge Queue (top priority)

These must merge sequentially, one-at-a-time, each after #1781 has landed and a fresh git fetch origin main has been run. The original branches no longer exist on origin; each PR must be re-cut from the last-merged base.

Prerequisite: #1781 merges first. Do not start this queue until CI is green on clean main.

Dependency analysis (from PR file manifests)

Order PR Title Key shared files Blocks
1 #1764 feat(demo): POST /api/demo/propose __init__.py, feature_flags.yaml, routes/demo.py, services/demo_proposal_service.py, services/demo_session_service.py, console/migrations/…/0038_promote_demo_propose.py #1766 (also touches routes/demo.py, demo_session_service.py)
2 #1770 feat(privacy): shadow-analytics consent schema __init__.py, routes/privacy.py, services/consent_service.py, db/migrations/021_analytics_consent.sql #1765 (also touches routes/privacy.py, consent_service.py, same migration)
3 #1768 feat(shadow-analytics): client-side shadow aggregator __init__.py, feature_flags.yaml, routes/shadow.py, console/migrations/…/0036_promote_shadow_analytics_enabled.py #1771 (shares feature_flags.yaml)
4 #1772 feat(auth): passkey multi-enrollment hard gate __init__.py, feature_flags.yaml, routes/auth.py, services/passkey_enrollment_service.py, console/migrations/…/0037_promote_passkey_enrollment_gate.py #1771 (shares routes/auth.py, feature_flags.yaml)
5 #1766 feat(demo): POST /api/demo/session __init__.py, feature_flags.yaml, routes/demo.py, services/demo_session_service.py, console/migrations/…/0037_promote_demo_session.py depends on #1764 landing first
6 #1765 feat(privacy): consent schema + re-opt-in modal __init__.py, routes/privacy.py, services/consent_service.py, db/migrations/021_analytics_consent.sql, frontend/…/privacyAPI.js, frontend/…/ReOptInModal.js depends on #1770 landing first
7 #1771 feat(auth): account security page — passkey device management + backup codes UI feature_flags.yaml, routes/auth.py, frontend/…/App.js, frontend/…/AccountSecurityPage.js depends on #1772 and #1768 landing first

Re-merge protocol per PR

  1. Fetch clean main: git fetch origin main && git checkout main && git reset --hard origin/main
  2. Re-cut the feature branch from main (re-apply or cherry-pick original commits — do NOT use auto-rebase.sh)
  3. Run python3 -c "import ast; ast.parse(open('backend_v2/api/__init__.py').read())" — must not raise
  4. Run scripts/ci/run_smoke.sh locally
  5. Open new PR targeting main, push, wait for CI green
  6. Merge — then repeat from step 1 for the next PR

Hard constraint: __init__.py and feature_flags.yaml appear in almost every one of these seven PRs. Sequential merge is the ONLY safe path. Do not batch any two of these in parallel.


Section B: The 30+ New Slate — Path-Isolated Bursts

All bursts below are gated on Section A completing first (clean main after all 7 re-merges). Within each burst, file paths are non-overlapping.

Migration numbering note: console/migrations/versions/ filenames use a sequential prefix (00XX_). When two PRs both add a new migration file with the same prefix, they collide. The safest practice is to assign migration numbers at dispatch time from the current head, not in the card. Each burst that includes a migration-adding PR must merge sequentially within itself — see Section C for the full exclusion list.


Burst 1 — getraxx.com marketing site (purely frontend/getraxx-landing/ or getraxx pages in Antlers)

All cards touch only the getraxx landing surface. None touch __init__.py, feature_flags.yaml, or console migrations.

# Issue Title Primary files touched Conflict risk
1 #1613 feat(getraxx): add pipeline rail visual to hero frontend/trademaster_ui/src/pages/getraxx/HeroSection.jsx (new component) None — new file under getraxx pages; gated on operator variant decision from PR #1609 before dispatch
2 #593 Mobile QA pass — iOS Safari + Android Chrome for getraxx.com frontend/trademaster_ui/src/pages/getraxx/*.{js,css} (CSS fixes only, no new pages) Low — only getraxx page files; no shared infra
3 #578 fix(frontend): Backtest.js vs Backtesting.js consolidation frontend/trademaster_ui/src/pages/Backtest.js, frontend/trademaster_ui/src/pages/Backtesting.js Low — isolated to two non-getraxx pages; no shared infra

Burst 1 conflict note: #1613 is gated on an operator decision (mockup variant). If that decision is not yet recorded on #1613, do not dispatch it in this burst — dispatch #593 and #578 without it. #578 (Backtest consolidation) is grouped here because it touches Antlers pages but nothing shared with getraxx — it can run alongside #593 safely.


Burst 2 — DevOps / CI / IaC (touches only .github/, terraform/, scripts/ci/)

No application code files. No __init__.py, feature_flags.yaml, or console migrations.

# Issue Title Primary files touched Conflict risk
1 #726 ops(ci): GitHub Actions billing posture — runner strategy .github/workflows/*.yml (retry hardening on wrangler steps), docs/ops/runbooks/ci-runner-posture.md Low — workflow files only; distinct from deploy workflows touched by other bursts
2 #536 fix(infra): inject CF zone_id + account_id from vault, remove from terraform.tfvars terraform/freescout/terraform.tfvars, terraform/README.md None — isolated terraform/freescout subtree
3 #708 ops(dns): add raxx.app MX record for Postmark Inbound docs/ops/runbooks/freescout.md (DNS docs), Dyn DNS record (out-of-repo) None — docs only in-repo; PR #1759 already open for this card; check for duplicate before dispatching
4 #335 infra: GitHub Apps for agent identity attribution .github/workflows/ (add bot-token step), scripts/agents/ (mint script updates) Low — distinct scripts/agents files; no overlap with #726 workflow changes if scoped to separate workflow files

Burst 2 conflict note: #726 and #335 both touch .github/workflows/. Assign them to different workflow files at dispatch time, or merge them sequentially within this burst. If they must touch the same workflow file, promote to Section C (solo merge). #708 has an open PR (#1759) — verify #1759 is not already merged before dispatching #708 again.


Burst 3 — Docs only (touches only docs/)

Pure markdown. No application code. No shared state. All can run in parallel safely.

# Issue Title Primary files touched Conflict risk
1 #502 feat(trace): SC-14 DPIA scoping under GDPR Art. 35 docs/architecture/workflow-uuid-tracing.md (addendum) or new docs/legal/dpia-sc-trace.md Low — docs subtree only
2 #479 research(product): natural-language AI strategy authoring + execution docs/business/user-feedback/2026-04-29-natural-language-strategy-execution.md (new file) None — new file
3 #596 ops(vault): Phase 1 — audit per-secret env coverage docs/ops/vault-env-coverage.md (new file) None — new file
4 #649 feat(devops): new-surface deploy/preview convention doc docs/architecture/new-surface-convention.md (new), scripts/scaffold-new-surface.sh (new), .github/PULL_REQUEST_TEMPLATE.md (append only) Low — new files + append to PR template; PR template append is low risk
5 #1161 docs(architecture): Fidelity broker integration design PR #1161 is already open — verify not merged; touches docs/architecture only None — PR is already filed; check before dispatching

Burst 3 conflict note: #502 may write to the existing docs/architecture/workflow-uuid-tracing.md. If any other burst-3 card also modifies that file, split into separate burst slots. Based on current data no other burst-3 card touches that file.


Burst 4 — Console UI / Flask (touches only console/app/)

No Raptor (backend_v2/) code. No Antlers (frontend/trademaster_ui/) code. Console migrations are gated to Section C.

# Issue Title Primary files touched Conflict risk
1 #925 fix(rotation): provision GITHUB_API_SECRETS_TOKEN with secrets:write scope console/app/services/rotation_handlers/heroku.py (update _write_gh_secret()), console/tests/test_heroku_rotation_885_891.py Low — single rotation handler file; no shared console state
2 #350 infra: console PR previews via Heroku review apps console/app.json, console/README.md None — app.json update only; no code
3 #454 ops: Heroku Platform API tokens in vault are stale (401) Vault config + docs/security/web-surface-posture.md None — ops procedure + docs only

Burst 4 conflict note: All three cards touch isolated console files. #925 touches console/app/services/rotation_handlers/heroku.py only; #350 touches console/app.json; #454 touches vault configuration (out-of-repo) + docs. Zero overlap — all three can run in parallel.


Burst 5 — Antlers feature pages (each PR owns a distinct page subtree)

Each PR below is scoped to a dedicated page directory or isolated component file. None touch App.js, package.json, or shared components.

# Issue Title Primary files touched Conflict risk
1 #474 feat(auth): capture first name + account display name during onboarding frontend/trademaster_ui/src/pages/SetupWizard/ (step addition — new component) Low — SetupWizard subtree; new file
2 #488 feat(demo): Build demo Antlers UI — 6-step flow frontend/trademaster_ui/src/pages/Demo/ (new directory — PR #1776 already open for this) PR #1776 is already open; check before dispatching — do not double-dispatch
3 #663 feat(support): inline docs panel on ticket detail page frontend/support/src/pages/TicketDetail/ (new inline panel component) Low — support SPA subtree, separate from trademaster_ui
4 #664 feat(support): autocomplete deflection on new ticket form frontend/support/src/pages/NewTicket/ (new autocomplete component) Low — support SPA subtree; different page from #663

Burst 5 conflict note: #474 touches SetupWizard/ only. #488/#1776 touches pages/Demo/ only. #663 touches frontend/support/src/pages/TicketDetail/ only. #664 touches frontend/support/src/pages/NewTicket/ only. These are four fully distinct directories — parallel-safe. Do not dispatch #488 if PR #1776 is still open and un-merged.


Burst 6 — Backend new-module additions (isolated new files, no __init__.py or feature_flags.yaml)

These PRs each add a NEW module file and do NOT register it in __init__.py or touch feature_flags.yaml. This is the highest-risk burst — every card must be individually audited before dispatch to confirm no shared-file additions have crept in.

Gate check before dispatch: For each PR, run gh pr view <N> --json files and confirm zero overlap with backend_v2/api/__init__.py and backend_v2/api/feature_flags.yaml. If a card's scope statement says "register blueprint in __init__.py" or "add flag to feature_flags.yaml", it is disqualified from this burst and promoted to Section C.

# Issue Title Expected new files Risk flag
1 #503 feat(trace): SC-2 Raptor middleware — act_ and wfl_ event emission backend_v2/api/middleware/trace_events.py (new) Verify does NOT add a blueprint registration to __init__.py
2 #504 feat(trace): SC-3 system-action emission from MQ-A + order-router backend_v2/api/services/trace_emitter.py (new service shim) Low — service file only; no route registration
3 #505 feat(trace): SC-4 Render ID emission on every Antlers view render New Raptor response middleware backend_v2/api/middleware/render_id.py Verify does NOT register a blueprint
4 #506 feat(trace): SC-5 hash chain for trace_events workflow chains backend_v2/api/services/hash_chain.py (new) Low — pure service module
5 #484 ops: operator script to refresh static demo chain snapshots scripts/ops/refresh-demo-snapshots.sh (new script, not backend code) None — scripts/ only

Burst 6 conflict note: All five cards add files in distinct directories or non-overlapping services. None should touch __init__.py or feature_flags.yaml — but this MUST be confirmed at dispatch time by inspecting the actual branch diff. Any deviation from the scope statement requires promotion to Section C.


Burst 7 — Raptor support API (backend_v2/api/routes/support.py series, no cross-file collision if each is scoped to its own route file)

The support.raxx.app sub-cards (#652–#659, #1005–#1012) form a natural sequence. Most can be parallelized within their surface:

# Issue Title Primary files Conflict risk
1 #652 support.raxx.app sub-1: architect data model + API contract docs/architecture/support-raxx-app.md (design doc only) None — docs only
2 #653 support.raxx.app sub-2: DNS + CF Pages project + deploy workflow .github/workflows/deploy-support.yml (new), terraform/cloudflare/ (append) Low — new workflow file; check for collision with Burst 2 workflow work
3 #654 support.raxx.app sub-3: backend customer-scoped FreeScout proxy API backend_v2/api/routes/support.py (new), backend_v2/app.py (blueprint register) HIGH — backend_v2/app.py is a shared file; treat as Section C or confirm it can bypass __init__.py
4 #655 support.raxx.app sub-4: React support portal SPA frontend/support/src/ (new SPA directory) None — entirely new surface
5 #659 support.raxx.app sub-8: launch checklist — meta tags, brand lint, sitemap frontend/support/src/public/ (static assets), .github/workflows/deploy-support.yml (CI lint step append) Low — support SPA only; flag if it appends to same workflow as #653

Burst 7 conflict note: #652 is docs-only and can run in Burst 3 instead. #654 likely requires editing backend_v2/app.py (blueprint registration) — promote to Section C unless the developer can confirm the registration is handled via auto-discovery. Sub-cards #656–#658, #1005–#1012 are sequentially dependent on the portal SPA (#655) being present first; queue them after Burst 7 lands.


Burst 8 — Security / trace schema infrastructure (sequential-within-burst due to migration numbering)

These cards add Postgres migrations. Migration file prefix collisions are guaranteed if dispatched in parallel — treat each as solo within this burst.

# Issue Title Migration file Solo-within-burst required
1 #508 feat(trace): SC-7 admin replay API backend_v2/db/migrations/02X_trace_snapshots.sql (new) Yes — assign migration number at dispatch
2 #509 feat(trace): SC-8 user-facing trace API backend_v2/api/routes/trace.py (new) + migration Yes — wait for #508 to land before dispatching
3 #512 feat(trace): SC-15 admin-access user notification email backend_v2/api/services/admin_access_notify.py (new) Low — may not need a migration; confirm at dispatch
4 #514 feat(trace): SC-11 Timescale hypertable migration backend_v2/db/migrations/02X_timescale_hypertable.sql Yes — Timescale migration is high risk; must run last in this sequence; staging gate required first
5 #515 feat(trace): SC-12 Ed25519 subsystem signing docs/ops/trace-signing-key-rotation.md (new runbook) + Infisical key provisioning (out-of-repo) Low — mostly out-of-repo ops work; docs file is new

Burst 8 conflict note: #514 (Timescale migration) is the riskiest card in the entire sprint. Per the card's own scope: "run during a maintenance window; test on staging first." This card must be the last in Burst 8 and must have a pre-merge staging validation step. Do not run it in any parallel group.


Section C: Hard Exclusions — Solo Merge Only

These files, if touched by any PR, automatically disqualify that PR from any burst. It must merge alone, with a fresh git fetch origin main before its branch is cut.

C.1 Always-solo files

File Why
backend_v2/api/__init__.py Every blueprint registration lives here; concurrent edits produce guaranteed merge conflicts
backend_v2/api/feature_flags.yaml Shared flag registry; YAML-concat "works" but produces semantic duplicates and flag ordering conflicts
console/migrations/versions/00XX_*.py Sequential prefix numbers; two PRs adding 0039_*.py at the same time collide on the filename
frontend/trademaster_ui/package.json Dependency version conflicts; lock file churn cascades to CI
backend_v2/app.py Blueprint registration gateway; same problem as __init__.py

C.2 PRs confirmed to need solo merge (from open PR file manifests)

PR Trigger file(s) Solo cadence
#1774 (demo PostHog/Clarity) __init__.py, feature_flags.yaml, package.json, console migrations Solo after Section A lands
#1775 (demo paper-fill) __init__.py, feature_flags.yaml Solo after Section A #1764/#1766 land
#1776 (demo flow UI) feature_flags.yaml, package.json, console migrations Solo
#1777 (SC-13B RBAC gate) feature_flags.yaml, console migrations Solo
#1778 (backup codes backend) __init__.py, feature_flags.yaml, routes/auth.py, console migrations Solo
#1780 (GDPR delete pipeline) __init__.py, feature_flags.yaml, console migrations Solo

C.2 Rule for adding flags

Any PR that adds a new entry to feature_flags.yaml MUST also include the console_flag_promotions migration (00XX_promote_*.py) in the same PR. Per feedback_new_flag_needs_b1_migration_same_pr.md — this has caused B1 gate failures four times. The migration file prefix must be assigned at dispatch time from the current head migration number to avoid collisions.


Section D: Dispatch Sequence

Estimated cadence: ~25 min per burst (10 min dispatch + 15 min CI + merge wave). Solo merges: ~20 min each.

UTC         Action
----        ------
After #1781 merges (target: 05:30 UTC 2026-05-12)

06:00       Section A begins — sequential re-merge queue
            Merge #1764 (demo propose) — wait for CI
06:25       Merge #1770 (consent schema) — wait for CI
06:50       Merge #1768 (shadow aggregator) — wait for CI
07:15       Merge #1772 (passkey gate) — wait for CI
07:40       Merge #1766 (demo session API) — depends on #1764
08:05       Merge #1765 (re-opt-in flow) — depends on #1770
08:30       Merge #1771 (device mgmt UI) — depends on #1772 + #1768

09:00       CHECKPOINT — confirm clean main (AST parse __init__.py; smoke passes)

09:00       Burst 3 dispatch (docs-only — zero risk; run first for quick wins)
            #502, #479, #596, #649, #1161 — all parallel
09:25       Burst 3 merge wave

09:30       Burst 1 dispatch (getraxx marketing pages)
            #593, #578 in parallel; #1613 only if operator variant decision is recorded
09:55       Burst 1 merge wave

10:00       Burst 2 dispatch (DevOps/CI/IaC)
            #726, #536 in parallel; #335 and #708 confirm not already merged
10:25       Burst 2 merge wave

10:30       Burst 4 dispatch (console UI — isolated console files)
            #925, #350, #454 in parallel
10:55       Burst 4 merge wave

11:00       Burst 5 dispatch (Antlers feature pages — distinct page directories)
            #474, #663, #664 in parallel; #488 only if [PR #1776](https://github.com/raxx-app/TradeMasterAPI/pull/1776) not already open/merged
11:25       Burst 5 merge wave

11:30       Burst 6 dispatch (backend new-module additions — gate check required)
            Run gh pr files check before each dispatch; #503, #504, #505, #506, #484 in parallel
            ABORT any card whose diff shows __init__.py or feature_flags.yaml — promote to Section C queue
11:55       Burst 6 merge wave

12:00       Section C solo queue begins (open PRs: #1774, #1775, #1776, #1777, #1778, #1780)
            Each gets its own 20-min slot with fresh main fetch before branch cut
            Order: #1775 → #1776 → #1774 → #1777 → #1778 → #1780
            (demo backend before demo UI; RBAC gate before backup codes; GDPR delete last — widest blast radius)

13:40       Burst 7 dispatch (support.raxx.app surface)
            #652 (docs) in Burst 3 already; #653 (DNS+deploy), #655 (SPA) in parallel
            #654 — solo if it touches backend_v2/app.py
14:05       Burst 7 merge wave

14:10       Burst 8 dispatch (trace schema infrastructure — sequential within burst)
            #515 (key provisioning, mostly ops) — dispatch and merge
            #512 (admin notify, no migration) — dispatch and merge
            #508 (admin replay + trace_snapshots migration) — dispatch and merge
            #509 (user trace API + migration) — dispatch and merge
            #514 (Timescale hypertable) — LAST; staging gate required; maintenance window

Estimated wall time to fully drain: ~9 hours from #1781 merge (05:30 → ~14:30 UTC 2026-05-12)

Critical path items: - #1781 merge is the single earliest gate; everything blocks on it - Section A's 7 sequential re-merges are the longest sequential chain (~2.5 hours) - #514 (Timescale) requires staging validation — may slip to 2026-05-13 if staging is unavailable


Section E: Pre-Dispatch Checklist Per Burst

Before dispatching any burst (copy this into the dispatch comment):


Section F: Cards Not Yet Ready for Dispatch

These cards appeared in the ready-for-dev list but have open blockers:

Issue Title Blocker
#1613 feat(getraxx): pipeline rail visual to hero Operator mockup variant decision (B-3, B-4, or C) not yet recorded on issue
#402 review: secrets-store organization Architecture doc required first — design work, not implementation
#423 feat(docs): public customer docs at docs.raxx.app scripts/build-customer-docs.py and docs/customer/ content both need to exist first
#376 feat(deploy): production environment approval gate Requires staging infrastructure to be stable first; #1781 recovery must complete
#1251 feat(auth): backup code generation backend Overlaps with #1778 (same PR already open for this card) — confirm #1778 is the implementation before filing a duplicate dispatch
#1259 feat(trace): SC-13B live-mode RBAC gate PR #1777 is already open — check before dispatching
#315–320 [security] HIGH npm audit: rollup/workbox/serialize-javascript Dependency upgrades — touch package.json; must be solo merges; group as a dedicated npm-audit sprint separate from this plan

Appendix: File-to-Burst Quick Reference

File Always-solo? Burst if not solo
backend_v2/api/__init__.py YES
backend_v2/api/feature_flags.yaml YES
backend_v2/app.py YES
console/migrations/versions/00XX_*.py YES
frontend/trademaster_ui/package.json YES
backend_v2/api/middleware/trace_events.py No Burst 6
backend_v2/api/middleware/render_id.py No Burst 6
backend_v2/api/services/hash_chain.py No Burst 6
backend_v2/api/services/trace_emitter.py No Burst 6
backend_v2/api/services/admin_access_notify.py No Burst 8
frontend/trademaster_ui/src/pages/getraxx/ No Burst 1
frontend/trademaster_ui/src/pages/SetupWizard/ No Burst 5
frontend/trademaster_ui/src/pages/Demo/ No Burst 5
frontend/support/src/ No Burst 5 / Burst 7
.github/workflows/ (new files) No Burst 2
terraform/ No Burst 2
scripts/ (new files) No Burst 2 / Burst 6
docs/ No Burst 3
console/app/services/rotation_handlers/heroku.py No Burst 4
console/app.json No Burst 4