Skip to content

PR #482 Split — Implementation Plan

Status: Frozen (2026-05-20). This is the plan that was executed; the actual split landed as PRs #498–#502. Do not edit retroactively — for the as-executed history see git log and those PRs.

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Working directory. Every git/gh command below assumes you run from the repository root. To make this portable across machines, set a single environment variable once before starting and the rest of the plan uses relative paths:

export REPO_ROOT="$(git rev-parse --show-toplevel)"
cd "$REPO_ROOT"

Earlier drafts of this plan hardcoded D:/TradAI/tradai via git -C; that path leaks the original author's machine layout and is not portable to Linux/macOS runners.

Goal: Split PR #482 (fix/474-review-blockers-cleanmain, 34 files, +2234 / −494) into five focused, independent PRs without losing any work.

Architecture: Five branches off origin/main, each carrying one concern. Path-based extraction with git checkout <src> -- <paths> and explicit git rm --ignore-unmatch for moved-source deletions (the --ignore-unmatch flag makes the cleanup step retryable if some of the listed files are already missing). Original branch and PR stay untouched as safety net.

Tech Stack: git, GitHub CLI (gh).

Source spec: docs/superpowers/specs/2026-05-20-pr-482-split-design.md


Task 0: Setup — backup tag and fetch main

Files: - None modified. Tag and remote update only.

  • Step 1: Verify clean working tree

Run: git status Expected: nothing to commit, working tree clean (we're currently on docs/pr-482-split-design after committing the spec — that is fine).

  • Step 2: Fetch latest main
git fetch origin main
  • Step 3: Create and push the backup tag
git tag backup/pr-482-pre-split fix/474-review-blockers-clean
git push origin backup/pr-482-pre-split

Expected: * [new tag] backup/pr-482-pre-split -> backup/pr-482-pre-split

  • Step 4: Confirm PR #482 is still OPEN
gh pr view 482 --json state,headRefName

Expected: {"state":"OPEN","headRefName":"fix/474-review-blockers-clean"}

  • Step 5: Print rename-aware diff inventory (reference for later tasks)
git diff origin/main fix/474-review-blockers-clean --name-status --find-renames=50%

This is the source of truth for which files each split touches. Keep the output handy.


Task 1: PR-5 split/security-audit-refresh

Files: - Modify: .pip-audit-ignore.txt - Modify: uv.lock

  • Step 1: Create the split branch off main
git checkout -b split/security-audit-refresh origin/main

Expected: Switched to a new branch 'split/security-audit-refresh'

  • Step 2: Extract the two files from #482
git checkout fix/474-review-blockers-clean -- \
  .pip-audit-ignore.txt \
  uv.lock
  • Step 3: Verify exactly two files are staged
git status --short
git diff --staged --stat

Expected status --short output:

M  .pip-audit-ignore.txt
M  uv.lock
Expected --stat: only those two files; sum should be roughly +21 -15.

If anything else appears, STOP and investigate before continuing.

  • Step 4: Commit
git commit -m "$(cat <<'EOF'
chore(security): refresh pip-audit ignores and lock file

Split from #482 — bundles the dependency-audit refresh on its own so it
can land independently of the API verification changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
  • Step 5: Push the branch
git push -u origin split/security-audit-refresh
  • Step 6: Open the PR
gh pr create --repo tradai-bot/tradai --base main \
  --head split/security-audit-refresh \
  --title "chore(security): refresh pip-audit ignores and lock file" \
  --body "$(cat <<'EOF'
Split from #482 — carries only the security/dependency-audit refresh.

## Changes
- Refresh `.pip-audit-ignore.txt` with current exemptions.
- Regenerate `uv.lock` to match.

## Testing
- `just check` was green on the source branch (#482) for this slice.

## Context
See #482 for the original combined PR. The original PR stays open as a safety net until all splits land.

Related: #482
EOF
)"

Expected: PR URL printed. Note it down.


Task 2: PR-4 split/demo-script-fixes

Files: - Modify: scripts/demo/06-results-kpis.sh - Modify: scripts/demo/11-promote-production.sh - Modify: scripts/demo/13-rollback.sh - Modify: scripts/demo/14-cleanup.sh - Modify: scripts/demo/lib.sh

  • Step 1: Create the split branch off main
git checkout -b split/demo-script-fixes origin/main
  • Step 2: Extract the five demo scripts
git checkout fix/474-review-blockers-clean -- \
  scripts/demo/06-results-kpis.sh \
  scripts/demo/11-promote-production.sh \
  scripts/demo/13-rollback.sh \
  scripts/demo/14-cleanup.sh \
  scripts/demo/lib.sh
  • Step 3: Verify exactly five files staged
git status --short
git diff --staged --stat

Expected: 5 modified files in scripts/demo/, total roughly +45 -5.

  • Step 4: Eyeball the diff for unexpected content
git diff --staged scripts/demo/14-cleanup.sh

(14-cleanup.sh has the largest add — confirm it's the sentinel-cleanup logic, not unrelated changes.)

  • Step 5: Commit
git commit -m "$(cat <<'EOF'
fix(demo): restore alarm state, use sentinel cleanup names, align with from_version schema

Split from #482 — carries only the demo-script fixes. Restores alarm state
after fire coverage, uses sentinel cleanup names to avoid clobbering real
resources, and updates the promote/rollback flows to the from_version /
to_stage schema.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
  • Step 6: Push and open PR
git push -u origin split/demo-script-fixes

gh pr create --repo tradai-bot/tradai --base main \
  --head split/demo-script-fixes \
  --title "fix(demo): restore alarm state, use sentinel cleanup names, align with from_version schema" \
  --body "$(cat <<'EOF'
Split from #482 — carries only the demo-script fixes.

## Changes
- `06-results-kpis.sh`: align KPI query with current schema.
- `11-promote-production.sh`: use `from_version` / `to_stage` payload.
- `13-rollback.sh`: same payload alignment as promote.
- `14-cleanup.sh`: sentinel cleanup names so the script never deletes real resources.
- `lib.sh`: small helper adjustment.

## Testing
- `bash -n scripts/demo/06-results-kpis.sh scripts/demo/11-promote-production.sh scripts/demo/13-rollback.sh scripts/demo/14-cleanup.sh`

## Context
See #482 for the combined PR.

Related: #482
EOF
)"

Task 3: PR-1 split/backend-traceability

Files: - Modify: services/backend/src/tradai/backend/api/routes.py - Modify: services/backend/src/tradai/backend/api/schemas.py - Modify: services/backend/src/tradai/backend/core/settings.py - Modify: services/backend/src/tradai/backend/infrastructure/local.py - Modify: services/backend/src/tradai/backend/infrastructure/memory.py - Modify: services/backend/tests/unit/test_backtest_routes.py - Modify: services/backend/tests/unit/test_memory.py

  • Step 1: Create the split branch off main
git checkout -b split/backend-traceability origin/main
  • Step 2: Extract backend source and test files
git checkout fix/474-review-blockers-clean -- \
  services/backend/src/tradai/backend/api/routes.py \
  services/backend/src/tradai/backend/api/schemas.py \
  services/backend/src/tradai/backend/core/settings.py \
  services/backend/src/tradai/backend/infrastructure/local.py \
  services/backend/src/tradai/backend/infrastructure/memory.py \
  services/backend/tests/unit/test_backtest_routes.py \
  services/backend/tests/unit/test_memory.py
  • Step 3: Verify exactly seven files staged
git status --short
git diff --staged --stat

Expected: 7 modified files under services/backend/, total roughly +127 -5.

  • Step 4: Run the backend unit tests on the split branch
uv run pytest services/backend/tests/unit/test_backtest_routes.py services/backend/tests/unit/test_memory.py -q --no-cov

Expected: PASS (per the source PR's testing notes).

If tests fail, STOP. The likely cause is an unstaged dependency — re-inspect git diff between the split branch and the source branch on these files.

  • Step 5: Commit
git commit -m "$(cat <<'EOF'
fix(backend): populate top-level mlflow_run_id for local/in-memory backtest paths

Split from #482 — carries only the backend traceability fix.

Ensures the local executor and in-memory repository populate the top-level
mlflow_run_id field on backtest results, so the trace context (job_id,
mlflow_run_id, trace_id, git_commit) is complete on every execution path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
  • Step 6: Push and open PR
git push -u origin split/backend-traceability

gh pr create --repo tradai-bot/tradai --base main \
  --head split/backend-traceability \
  --title "fix(backend): populate top-level mlflow_run_id for local/in-memory backtest paths" \
  --body "$(cat <<'EOF'
Split from #482 — carries only the backend traceability fix.

## Changes
- Populate top-level `mlflow_run_id` on local executor results.
- Populate the same field on in-memory repository writes.
- Adjust schema and settings to surface the field.
- Add route and repository unit tests covering the new behavior.

## Testing
- `uv run pytest services/backend/tests/unit/test_backtest_routes.py services/backend/tests/unit/test_memory.py -q --no-cov`
- `just lint`
- `just typecheck`

## Context
See #482 for the combined PR. The verification scripts in the sibling split rely on this fix.

Related: #482
EOF
)"

Task 4: PR-2 split/verification-scripts

This is the most complex task: 5 modified docs, 1 new endpoint-audit script, 4 new issue-417 scripts, and 6 explicit deletions for files moved from docs/verification/ to scripts/verification/.

Files: - Modify: docs/reference/api.md - Modify: docs/verification/E2E-VERIFICATION-LOG.md - Modify: docs/verification/e2e-verification-report-20260428.md - Modify: docs/verification/issue91-independent-verification-20260423.md - Modify: docs/verification/issue91.md - Delete: docs/verification/api-endpoint-audit.sh - Delete: docs/verification/config-versioning-e2e-aws.sh - Delete: docs/verification/issue89-verify.sh - Delete: docs/verification/issue90-verify.sh - Delete: docs/verification/issue91-verify.sh - Delete: docs/verification/issue92-verify.sh - Create (via checkout): scripts/verification/api-endpoint-audit.sh - Create (via checkout): scripts/verification/config-versioning-e2e-aws.sh - Create (via checkout): scripts/verification/issue-417-alarm-fire-coverage.sh - Create (via checkout): scripts/verification/issue-417-auth-coverage.sh - Create (via checkout): scripts/verification/issue-417-non-freqai-backtest.sh - Create (via checkout): scripts/verification/issue-417-running-after-launch.sh - Create (via checkout): scripts/verification/issue89-verify.sh - Create (via checkout): scripts/verification/issue90-verify.sh - Create (via checkout): scripts/verification/issue91-verify.sh - Create (via checkout): scripts/verification/issue92-verify.sh

  • Step 1: Create the split branch off main
git checkout -b split/verification-scripts origin/main
  • Step 2: Pull in the modified docs and the new/moved scripts
git checkout fix/474-review-blockers-clean -- \
  docs/reference/api.md \
  docs/verification/E2E-VERIFICATION-LOG.md \
  docs/verification/e2e-verification-report-20260428.md \
  docs/verification/issue91-independent-verification-20260423.md \
  docs/verification/issue91.md \
  scripts/verification/

The trailing-slash form scripts/verification/ pulls every file under that directory from the source branch. The directory does not exist on main, so it is created in full.

  • Step 3: Explicitly delete the old docs/verification/ shell scripts

git checkout <ref> -- <path> does not delete files that exist locally but not on the ref. The six scripts moved out of docs/verification/ must be removed by hand:

git rm --ignore-unmatch \
  docs/verification/api-endpoint-audit.sh \
  docs/verification/config-versioning-e2e-aws.sh \
  docs/verification/issue89-verify.sh \
  docs/verification/issue90-verify.sh \
  docs/verification/issue91-verify.sh \
  docs/verification/issue92-verify.sh

--ignore-unmatch lets the step be re-run safely if one or more of the listed files are already missing from the working tree.

  • Step 4: Verify the full file set is staged
git status --short

Expected (exact set):

M  docs/reference/api.md
M  docs/verification/E2E-VERIFICATION-LOG.md
M  docs/verification/e2e-verification-report-20260428.md
M  docs/verification/issue91-independent-verification-20260423.md
M  docs/verification/issue91.md
D  docs/verification/api-endpoint-audit.sh
D  docs/verification/config-versioning-e2e-aws.sh
D  docs/verification/issue89-verify.sh
D  docs/verification/issue90-verify.sh
D  docs/verification/issue91-verify.sh
D  docs/verification/issue92-verify.sh
A  scripts/verification/api-endpoint-audit.sh
A  scripts/verification/config-versioning-e2e-aws.sh
A  scripts/verification/issue-417-alarm-fire-coverage.sh
A  scripts/verification/issue-417-auth-coverage.sh
A  scripts/verification/issue-417-non-freqai-backtest.sh
A  scripts/verification/issue-417-running-after-launch.sh
A  scripts/verification/issue89-verify.sh
A  scripts/verification/issue90-verify.sh
A  scripts/verification/issue91-verify.sh
A  scripts/verification/issue92-verify.sh

If anything is missing or extra, STOP and reconcile against the Task 0 Step 5 inventory.

  • Step 5: Run shellcheck syntax parse on every new/moved .sh
bash -n \
  scripts/verification/api-endpoint-audit.sh \
  scripts/verification/issue-417-alarm-fire-coverage.sh \
  scripts/verification/issue-417-auth-coverage.sh \
  scripts/verification/issue-417-non-freqai-backtest.sh \
  scripts/verification/issue-417-running-after-launch.sh \
  scripts/verification/issue89-verify.sh \
  scripts/verification/issue90-verify.sh \
  scripts/verification/issue91-verify.sh \
  scripts/verification/issue92-verify.sh \
  scripts/verification/config-versioning-e2e-aws.sh

Expected: silent exit (return code 0).

  • Step 6: Commit
git commit -m "$(cat <<'EOF'
chore(verification): relocate audit scripts and add issue-417 coverage scripts

Split from #482 — carries the verification-script relocation and the new
issue-417 coverage scripts. Moves shell-based audits from docs/verification/
to scripts/verification/, hardens api-endpoint-audit.sh against false
positives, and adds dedicated coverage for auth, alarm-fire, non-freqai
backtest, and running-after-launch flows.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
  • Step 7: Push and open PR
git push -u origin split/verification-scripts

gh pr create --repo tradai-bot/tradai --base main \
  --head split/verification-scripts \
  --title "chore(verification): relocate audit scripts and add issue-417 coverage scripts" \
  --body "$(cat <<'EOF'
Split from #482 — carries the verification-script relocation and the new issue-417 coverage scripts.

## Changes
- Move `*.sh` audit scripts from `docs/verification/` to `scripts/verification/` (renames).
- Rewrite `api-endpoint-audit.sh` to fail-fast on regressions and remove the 503-as-success exemption.
- Add four issue-417 coverage scripts: alarm-fire-coverage, auth-coverage, non-freqai-backtest, running-after-launch.
- Update `docs/reference/api.md` and four `docs/verification/*.md` artefacts to align with the from_version / to_stage schema and document validation as 422.

## Testing
- `bash -n` parse for every new/moved shell script.

## Context
See #482 for the combined PR.

Related: #482
EOF
)"

Task 5: PR-3 split/postman-drift-gate

Files: - Modify: .github/workflows/ci.yml - Modify: postman/aws-dev-tradai.postman_collection.json - Create: scripts/dev/regenerate-postman-schemas.py - Create: tests/unit/test_regenerate_postman_schemas.py

  • Step 1: Create the split branch off main
git checkout -b split/postman-drift-gate origin/main
  • Step 2: Extract the Postman files
git checkout fix/474-review-blockers-clean -- \
  .github/workflows/ci.yml \
  postman/aws-dev-tradai.postman_collection.json \
  scripts/dev/regenerate-postman-schemas.py \
  tests/unit/test_regenerate_postman_schemas.py
  • Step 3: Verify exactly four files staged
git status --short
git diff --staged --stat

Expected: 4 files (2 M, 2 A), total roughly +1186 -157.

  • Step 4: Spot-check the CI change is only the drift gate
git diff --staged .github/workflows/ci.yml

Expected: ~5-line addition adding a job that runs scripts/dev/regenerate-postman-schemas.py and fails on drift. Nothing unrelated.

  • Step 5: Run the Postman regenerator unit test on the split branch
uv run pytest tests/unit/test_regenerate_postman_schemas.py -q --no-cov

Expected: PASS.

  • Step 6: Commit
git commit -m "$(cat <<'EOF'
feat(postman): add schema drift gate and harden collection tests

Split from #482 — carries only the Postman work.

Adds scripts/dev/regenerate-postman-schemas.py with normalized nullable refs
and default collection path, a unit test covering it, and a CI job that
fails on drift between the committed collection and what the regenerator
produces. Updates the collection itself so collection-level tests fail on
unexpected status codes instead of accepting any 4xx/5xx.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
  • Step 7: Push and open PR
git push -u origin split/postman-drift-gate

gh pr create --repo tradai-bot/tradai --base main \
  --head split/postman-drift-gate \
  --title "feat(postman): add schema drift gate and harden collection tests" \
  --body "$(cat <<'EOF'
Split from #482 — carries only the Postman work.

## Changes
- New `scripts/dev/regenerate-postman-schemas.py` with normalized nullable refs.
- New `tests/unit/test_regenerate_postman_schemas.py` covering normalizer behavior.
- New CI job (`.github/workflows/ci.yml`) that fails the build on Postman schema drift.
- Regenerated `postman/aws-dev-tradai.postman_collection.json` — collection-level tests now reject unexpected 4xx/5xx instead of accepting them.

## Testing
- `uv run pytest tests/unit/test_regenerate_postman_schemas.py -q --no-cov`
- Manual: drift gate runs locally via `python scripts/dev/regenerate-postman-schemas.py --check`.

## Context
See #482 for the combined PR.

Related: #482
EOF
)"

Task 6: Union-diff sanity check + comment on PR #482

Files: - None modified. Verification only.

  • Step 1: Confirm every file in #482 is covered by exactly one split
git fetch origin \
  split/security-audit-refresh \
  split/demo-script-fixes \
  split/backend-traceability \
  split/verification-scripts \
  split/postman-drift-gate

# The set of files changed in #482 vs main (NO rename detection, so D + A appear separately and match the split form):
git diff origin/main fix/474-review-blockers-clean --name-only --no-renames | sort > /tmp/pr482-files.txt

# The union of files changed across the five split branches vs main:
{
  git diff origin/main origin/split/security-audit-refresh --name-only
  git diff origin/main origin/split/demo-script-fixes      --name-only
  git diff origin/main origin/split/backend-traceability   --name-only
  git diff origin/main origin/split/verification-scripts   --name-only
  git diff origin/main origin/split/postman-drift-gate     --name-only
} | sort -u > /tmp/splits-files.txt

diff /tmp/pr482-files.txt /tmp/splits-files.txt

Expected: diff produces NO OUTPUT (exit code 0).

If diff shows lines: a file was either missed (present in #482, absent from splits) or duplicated/leaked (absent from #482, present in splits). Investigate before continuing.

Then verify the content (not just the file list) is identical by reconstructing the union and comparing to #482:

git diff origin/main fix/474-review-blockers-clean -- \
  $(cat /tmp/pr482-files.txt) > /tmp/pr482-content.diff

# Reconstruct: apply all five splits onto main in a temporary branch
git checkout -b _union-check origin/main
for b in split/security-audit-refresh split/demo-script-fixes split/backend-traceability split/verification-scripts split/postman-drift-gate; do
  git merge --no-edit "origin/$b"
done
git diff origin/main HEAD > /tmp/union-content.diff
git checkout docs/pr-482-split-design
git branch -D _union-check

diff /tmp/pr482-content.diff /tmp/union-content.diff

Expected: only metadata differences (e.g., diff header ordering). Substantive content lines should be identical.

  • Step 2: Post a comment on PR #482 linking the splits

Collect the five PR URLs printed by the earlier tasks, then:

gh pr comment 482 --repo tradai-bot/tradai --body "$(cat <<'EOF'
This PR has been split into five focused PRs for easier review. The branch and PR remain open as a safety net until all five splits land.

- PR-1 (backend traceability): <URL from Task 3>
- PR-2 (verification scripts): <URL from Task 4>
- PR-3 (Postman drift gate): <URL from Task 5>
- PR-4 (demo script fixes): <URL from Task 2>
- PR-5 (security audit refresh): <URL from Task 1>

Backup tag: `backup/pr-482-pre-split` (pushed before the split).

Once all five splits merge, this PR will be closed. Please review the splits instead of this one.
EOF
)"

Replace the <URL ...> placeholders with the actual URLs before running.

  • Step 3: Do NOT merge or close PR #482

Per the safety plan, PR #482 stays open as a fallback. The user closes it manually after the splits land.


Task 7: Push the spec branch and open its PR

The spec and plan were both committed locally on docs/pr-482-split-design during planning. Push the branch and open a small PR so the design lives in main.

Files: - Already committed: docs/superpowers/specs/2026-05-20-pr-482-split-design.md - Already committed: docs/superpowers/plans/2026-05-20-pr-482-split.md

  • Step 1: Switch back to the docs branch and push
git checkout docs/pr-482-split-design
git push -u origin docs/pr-482-split-design
  • Step 2: Open the PR
gh pr create --repo tradai-bot/tradai --base main \
  --head docs/pr-482-split-design \
  --title "docs(superpowers): PR #482 split design and plan" \
  --body "$(cat <<'EOF'
Adds the design spec and implementation plan that drove the split of PR #482 into five focused PRs.

## Files
- `docs/superpowers/specs/2026-05-20-pr-482-split-design.md`
- `docs/superpowers/plans/2026-05-20-pr-482-split.md`

## Context
See #482 and the five split PRs referenced in its closing comment.
EOF
)"

Definition of done

  • backup/pr-482-pre-split tag pushed to origin.
  • Five split branches pushed: split/security-audit-refresh, split/demo-script-fixes, split/backend-traceability, split/verification-scripts, split/postman-drift-gate.
  • Five PRs open against main.
  • Union-diff sanity check passes.
  • PR #482 has a comment linking the five splits.
  • PR #482 is still OPEN (do not merge or close).
  • Spec/plan PR opened from docs/pr-482-split-design.
  • fix/474-review-blockers-clean has had zero new commits since plan execution started.