---
phase: 06.5
plan: 05
type: execute
wave: 3
depends_on:
  - 06.5-01
  - 06.5-02
  - 06.5-03
  - 06.5-04
files_modified:
  - .planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VERIFICATION.md
  - docs/deploy/uat-06.5-client-fast-path.md
autonomous: false
requirements:
  - REQ-DEP-04
  - REQ-CLI-08
  - REQ-DEP-01
must_haves:
  truths:
    - "Operator executes the cold-start fallback drill on staging; freshly-provisioned machine serves bundled index.html when /data/client-assets/current does not exist; server logs show static_assets_source_bundled (REQ-DEP-01)"
    - "Operator pushes a client-only commit; deploy-staging workflow runs the fast-path job (not the full-image job); workflow completes in under 5 minutes; readlink /data/client-assets/current points at the new SHA's release dir; GC keeps last 5 (REQ-DEP-04)"
    - "Operator executes the rollback drill from ROLLBACK.md; symlink flips to the previous SHA via mv -T; 3-check probes return green; total rollback wall-clock under 60 seconds (REQ-DEP-04)"
    - "Operator confirms two-player CLI-08 fidelity survives a fast-path deploy: two browser windows log in, walk, chat, see each other (REQ-CLI-08)"
    - "Operator pushes a mixed-diff PR (client + server file in same commit); workflow routes to FULL path, NOT fast-path; 06.4 c01038f knobs honored (commit-message [skip-*] flags + workflow_dispatch inputs) (REQ-DEP-04)"
    - "06.5-VERIFICATION.md captures pass/fail signoff for all 5 drills with timestamps and operator initials; pnpm trace:check shows REQ-DEP-01 / REQ-DEP-04 / REQ-CLI-08 fully covered across required stages"
  artifacts:
    - path: ".planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VERIFICATION.md"
      provides: "Phase 06.5 verification doc — pass/fail for all 5 drills with operator signoff"
      contains: "REQ-DEP-04"
    - path: "docs/deploy/uat-06.5-client-fast-path.md"
      provides: "Updated with actual drill timestamps + operator initials (file pre-authored in Plan 03; this plan fills in the signoff)"
      contains: "Signoff"
  key_links:
    - from: ".planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VERIFICATION.md"
      to: "docs/deploy/uat-06.5-client-fast-path.md"
      via: "verification references UAT checklist as the executable runbook"
      pattern: "uat-06.5-client-fast-path"
    - from: ".planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VERIFICATION.md"
      to: "REQ-DEP-01 / REQ-DEP-04 / REQ-CLI-08"
      via: "explicit traceable-reqs stage checklist"
      pattern: "REQ-DEP"
---

<objective>
Operator-driven E2E verification of the entire Phase 06.5 split. This plan is NOT autonomous — it contains five sequential human-verify checkpoints because each drill requires real Fly machine state, real GH Actions workflow runs, and operator-eyeball confirmation that cannot be CI-automated (per VALIDATION.md § Manual-Only Verifications).

Drills executed in order:
1. **Cold-start fallback** (REQ-DEP-01) — destroy /data/client-assets, restart machine, confirm bundled fallback serves the page.
2. **Fast-path deploy** (REQ-DEP-04) — push a client-only commit, confirm fast-path job runs (not full path), 3-check probe passes, GC + symlink state correct, wall-clock under 5 minutes.
3. **Rollback drill** (REQ-DEP-04) — follow ROLLBACK.md end-to-end, mv -T flip back to previous SHA, verify 3-check, wall-clock under 60 seconds.
4. **Two-player CLI-08 fidelity** (REQ-CLI-08) — two-browser-window walk + chat after a fast-path deploy.
5. **Mixed-diff routing + 06.4 regression** (REQ-DEP-04) — push a client + server mixed commit, confirm full-path job runs (NOT fast-path); push with `[skip-staging-smoke]` in commit message, confirm full-path honors the knob.

Output: `06.5-VERIFICATION.md` documenting pass/fail with timestamps; `uat-06.5-client-fast-path.md` updated with operator initials and dates per Plan 03's signoff section.

Purpose: This is the phase exit gate. No drill can be faked; each one exercises real Fly infrastructure end-to-end. After this plan, REQ-DEP-04 int stage is verified, REQ-CLI-08 int stage carries forward (this drill is the proxy for Playwright cli-08 on the fast path), REQ-DEP-01 int stage is verified by the cold-start drill.
</objective>

<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-CONTEXT.md
@.planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-RESEARCH.md
@.planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VALIDATION.md
@docs/deploy/uat-06.5-client-fast-path.md
@docs/deploy/ROLLBACK.md
@.github/workflows/deploy-staging.yml
@scripts/client-release.sh

<interfaces>
<!-- All artifacts referenced here are produced by Plans 01-04. This plan modifies only verification + UAT signoff docs. -->
<!-- Operator must have: flyctl auth working, push access to main on the rebno repo, two browser windows, the two UAT_ACCOUNT_A/B credentials from staging secrets. -->
<!-- Staging URL: https://staging.rebno.decidel.com -->
<!-- Prod URL: https://rebno.decidel.com -->
<!-- This plan touches staging ONLY (per Plan 04 scope; RESEARCH § Open Question 1). -->
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Scaffold 06.5-VERIFICATION.md with the 5-drill matrix</name>
  <files>.planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VERIFICATION.md</files>
  <read_first>
    - docs/deploy/uat-06.5-client-fast-path.md (read after Plan 03 ships — the drill steps live there; this verification doc references them by section anchor, NOT by duplicating instructions)
    - .planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VALIDATION.md (§ Per-Task Verification Map — the verification doc's columns mirror the VALIDATION map's columns)
    - .planning/phases/06.3-*/06.3-VERIFICATION.md if it exists, OR a prior phase's VERIFICATION.md (e.g., 06.2-VERIFICATION.md) for shape/conventions
  </read_first>
  <action>
    Create `.planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VERIFICATION.md`. Header tag line: `[doc->REQ-DEP-04] [doc->REQ-CLI-08] [doc->REQ-DEP-01]`.

    Sections:

    **# Phase 06.5 — Verification** with subhead "Static client asset split — operator-driven E2E gate".

    **## Status** — A frontmatter-style table: `Phase`, `Status` (one of `pending`, `in_progress`, `passed`, `failed`), `Operator`, `Started` (timestamp), `Completed` (timestamp). Initial state: pending, blank operator/timestamps.

    **## Drill Matrix** — 5-row markdown table with columns: `Drill #`, `Requirement(s)`, `Description (one line)`, `Runbook anchor`, `Pass criteria (1-2 lines)`, `Pass/Fail`, `Timestamp`, `Notes`.

    Rows:
    1. Cold-start fallback (REQ-DEP-01) → anchor `uat-06.5-client-fast-path.md#cold-start-fallback-drill` (or whatever the actual heading slug is — verify by reading the file after Plan 03 ships) → pass: bundled `/` returns 200 + log line `static_assets_source_bundled` present.
    2. Fast-path deploy (REQ-DEP-04) → anchor `#fast-path-deploy-drill` → pass: GH Actions run shows fast-path job (NOT full-path), wall-clock < 5 min, readlink current = releases/<new-sha>, 3-check probes 200, GC ≤ 5 release dirs.
    3. Rollback drill (REQ-DEP-04) → anchor `#rollback-drill` → pass: mv -T rollback completes; 3-check 200 within 60 s.
    4. Two-player CLI-08 fidelity (REQ-CLI-08) → anchor `#two-player-cli-08-fidelity-check` → pass: both windows authenticate, see each other walk + chat for at least 30 seconds.
    5. Mixed-diff + 06.4 regression (REQ-DEP-04) → anchor `#06-4-carry-over-regression-check` → pass: mixed-diff PR routes to full-path; `[skip-staging-smoke]` honored on a follow-up commit.

    **## Traceability Check** — A `pnpm trace:check` excerpt as a fenced code block (operator pastes the output here at signoff time). Required stages per traceable-reqs.toml:
    - REQ-DEP-01: doc + impl + int — covered by Plan 02 (doc), Plan 01 (impl, unit, int), Plan 05 cold-start drill (int).
    - REQ-DEP-04: doc + impl + int — covered by Plan 03 (doc, impl), Plan 04 (impl, int), Plan 05 drills 2-3-5 (int).
    - REQ-CLI-08: doc + int — covered by Plan 03 (doc), Plan 05 drill 4 (int).

    **## Pitfall Cross-Check** — Confirm each RESEARCH-flagged pitfall was tested during one of the drills:
    | Pitfall | Test | Drill # | Status |
    |---------|------|---------|--------|
    | `ln -sfn` non-atomic | scripts/client-release.sh uses `mv -T` (Plan 03 bats test 8) | n/a (covered in Plan 03) | inherit |
    | tj-actions/changed-files banned | Plan 04 acceptance criterion grep | n/a (covered in Plan 04) | inherit |
    | `/healthz` wrong endpoint | All probes use `/health` | 2, 3 | verify |
    | Cold-start fallback works | Drill 1 | 1 | verify |
    | Live symlink swap visible to running server | Plan 01 integ test | n/a (covered in Plan 01) | inherit |
    | GC deletes current target | Plan 03 bats test 7 + readlink-protect | n/a (covered in Plan 03) | inherit |

    **## Signoff** — Operator initials block + date + final verdict (one of `phase passes`, `phase fails — see Notes`).

    The doc starts in `pending` state with all drill rows blank. Task 2 fills it in as drills execute.
  </action>
  <verify>
    <automated>bash -c 'set -e; F=.planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VERIFICATION.md; test -f $F; grep -F "[doc-&gt;REQ-DEP-04]" $F &gt;/dev/null; grep -F "[doc-&gt;REQ-CLI-08]" $F &gt;/dev/null; grep -F "[doc-&gt;REQ-DEP-01]" $F &gt;/dev/null; grep -c "## " $F | awk "{exit (\$1 &gt;= 4)?0:1}"; echo OK'</automated>
  </verify>
  <acceptance_criteria>
    - `.planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VERIFICATION.md` exists with `[doc->REQ-DEP-04]`, `[doc->REQ-CLI-08]`, `[doc->REQ-DEP-01]` tags
    - File has at least 4 `## ` sections (Status, Drill Matrix, Traceability Check, Signoff)
    - Drill Matrix table has exactly 5 rows (one per drill); each row names a Requirement, a Runbook anchor, a Pass criterion
    - Pitfall Cross-Check table includes the four RESEARCH-flagged pitfalls (ln -sfn, tj-actions, /healthz, cold-start)
    - Status field starts as `pending`
  </acceptance_criteria>
  <done>Verification doc scaffold ready; operator can fill in pass/fail + timestamps as Task 2 executes.</done>
</task>

<task type="checkpoint:human-action" gate="blocking">
  <name>Task 2: Operator-driven 5-drill E2E UAT</name>
  <files>.planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VERIFICATION.md, docs/deploy/uat-06.5-client-fast-path.md</files>
  <read_first>
    - docs/deploy/uat-06.5-client-fast-path.md (Plan 03 pre-authored the drill runbook — execute step-by-step)
    - docs/deploy/ROLLBACK.md (Plan 03 — Drill 3 follows this exactly)
    - .planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VERIFICATION.md (Task 1 scaffold — populate it during drill execution)
  </read_first>
  <what-built>
    Plans 01-04 produce: a resolver-driven static mount (apps/server), STATIC_ASSETS_DIR env on both fly toml files, scripts/client-release.sh + bats coverage, ROLLBACK.md + uat-06.5-client-fast-path.md runbooks, the restructured deploy-staging.yml with paths-filter + fast-path job + preserved 06.4 knobs. Task 1 produced the 06.5-VERIFICATION.md scaffold.

    All five drills are documented step-by-step in `docs/deploy/uat-06.5-client-fast-path.md` (pre-authored in Plan 03). The operator runs them in order and records pass/fail in 06.5-VERIFICATION.md per the matrix.
  </what-built>
  <action>
    This is a checkpoint:human-action task. The operator (not Claude) runs the five drills documented below and records pass/fail in 06.5-VERIFICATION.md. See `<how-to-verify>` for the step-by-step drill sequence.

    Claude's role on this task is limited to:
    (a) confirming all upstream plans (01-04) are merged and the prior deploy-staging full-path run landed Plan 01-04 changes;
    (b) presenting the operator with the runbook reference (`docs/deploy/uat-06.5-client-fast-path.md`);
    (c) after operator returns with the resume-signal, updating 06.5-VERIFICATION.md (the file created by Task 1) with the recorded pass/fail rows, timestamps, and trace:check output the operator provides;
    (d) if any drill fails, queueing a follow-up gap-closure plan via `/gsd-plan-phase 06.5 --gaps`.

    No code or config changes happen in this task. The five drills exercise real Fly infrastructure end-to-end and cannot be CI-automated (per VALIDATION.md § Manual-Only Verifications).
  </action>
  <verify>
    <automated>bash -c 'set -e; F=.planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-VERIFICATION.md; grep -F "Pass" $F &gt;/dev/null || { echo "VERIFICATION.md has no Pass entries — drills not yet executed"; exit 1; }; grep -F "REQ-DEP-01" $F &gt;/dev/null; grep -F "REQ-DEP-04" $F &gt;/dev/null; grep -F "REQ-CLI-08" $F &gt;/dev/null; echo OK_post_drills'</automated>
  </verify>
  <how-to-verify>
    Operator preflight (do these once before starting):
    1. Confirm Plans 01-04 are merged to main and the most recent deploy-staging run was the full-path version that landed Plans 01-04 (verify in GitHub Actions UI).
    2. `flyctl auth whoami` returns your account; `flyctl status -a rebno-staging` shows the machine running.
    3. Pull latest main on a clean checkout; `pnpm install` and `pnpm trace:check` baseline (capture output for after-comparison).
    4. Open `docs/deploy/uat-06.5-client-fast-path.md` in one tab, `06.5-VERIFICATION.md` in another, and a staging-URL browser window in a third.

    Execute drills (each drill = one row in 06.5-VERIFICATION.md):

    **Drill 1: Cold-start fallback (REQ-DEP-01)**
    Follow uat-06.5-client-fast-path.md § "Cold-start fallback drill". CAUTION: this destroys /data/client-assets on staging. Confirm staging is acceptable to clobber (no prod traffic).
    - SSH-clear: `flyctl ssh console -a rebno-staging -C "rm -rf /data/client-assets"`.
    - Restart machine: `flyctl machine restart -a rebno-staging` (find machine id with `flyctl machine list -a rebno-staging`).
    - Wait 30 seconds for boot. Then `curl -fsS https://staging.rebno.decidel.com/` returns 200 with bundled index.html.
    - `flyctl logs -a rebno-staging | grep static_assets_source` shows `static_assets_source_bundled` log entry from the resolver.
    - Record in 06.5-VERIFICATION.md row 1: timestamp + pass/fail + notes (e.g., observed bundled markup, no crashloop).

    **Drill 2: Fast-path deploy (REQ-DEP-04)**
    - Create a one-line CSS-only or text-only change under `apps/client/src/` (e.g., adjust a string in `apps/client/index.html` or a CSS class). Commit + push to main directly OR via a PR + squash-merge (whichever matches project flow).
    - Watch GH Actions: the `changes` job runs, then the `fast-path` job runs. The `full-path` job is SKIPPED (`if:` condition false).
    - Workflow run wall-clock < 5 minutes (timestamp captured for VERIFICATION row 2).
    - `flyctl ssh console -a rebno-staging -C "readlink /data/client-assets/current"` returns `/data/client-assets/releases/<new-sha>`.
    - `flyctl ssh console -a rebno-staging -C "ls /data/client-assets/releases/"` lists ≤ 5 release dirs (GC fired). If this is the very first fast-path deploy, expect exactly 1 release dir.
    - 3-check probes all green (CI run already enforced this; operator verifies the workflow logs show "3-check probes passed").
    - Hard-refresh the staging URL in the browser; the CSS/text change is visible.
    - Record in VERIFICATION row 2.

    **Drill 3: Rollback drill (REQ-DEP-04)**
    - Follow `docs/deploy/ROLLBACK.md` exactly.
    - Capture wall-clock from the `mv -T` invocation until the first green `curl` against `/`.
    - Confirm the rollback target SHA is now the value of `readlink current`.
    - Record in VERIFICATION row 3. Target: under 60 seconds.

    **Drill 4: Two-player CLI-08 fidelity (REQ-CLI-08)**
    - Open two browser windows (different incognito sessions or different browsers to avoid auth cookie collision). Log in as UAT_ACCOUNT_A and UAT_ACCOUNT_B (credentials from staging secrets — operator pulls from local password manager or `flyctl secrets list -a rebno-staging` references).
    - Both windows join the staging room (BNCentral or whichever room is the staging MVP target).
    - Each window walks around for ~30 seconds, sends at least 3 chat messages.
    - Both windows see each other's movement smoothly (no rubber-banding worse than baseline) AND see each other's chat messages.
    - Record in VERIFICATION row 4. Optional: short screen recording attached as artifact (matches the 06.1/06.2 CLI-08 milestone .mp4 pattern).

    **Drill 5: Mixed-diff routing + 06.4 regression (REQ-DEP-04)**
    - First test: create a commit that touches BOTH `apps/client/src/some-file` AND `apps/server/src/some-other-file` (a trivial whitespace change to each). Push. Watch GH Actions: the FULL-path job runs (not fast-path). The `changes` job's outputs should show `client=true, non_client=true`.
    - Second test (regression check on 06.4 knobs): create a server-touching commit with `[skip-staging-smoke]` in the commit message. Push. Watch the full-path workflow: the Playwright cli-08 smoke step should be SKIPPED (`if: ${{ env.SKIP_STAGING_SMOKE != 'true' }}` evaluates to false).
    - Third test (knob via workflow_dispatch): trigger `gh workflow run deploy-staging.yml -f skip_verification=true` (or via the GH UI), confirm verify-phase-5 is skipped.
    - Record all three sub-tests in VERIFICATION row 5.

    Final step: paste the output of `pnpm trace:check` into the Traceability Check section. All three REQs (REQ-DEP-01, REQ-DEP-04, REQ-CLI-08) MUST show the required stages as covered (no `missing_stage` findings for these IDs). If `pnpm trace:check` is deferred on CI (per CLAUDE.md), run it locally.

    Sign the doc at the bottom — operator initials + date + verdict.
  </how-to-verify>
  <resume-signal>
    Type `approved` to mark Phase 06.5 verified.
    Type `partial — drill N failed: <details>` if any drill fails — produces a follow-up gap-closure plan (`/gsd-plan-phase 06.5 --gaps`).
    Type `abort` to roll back the phase entirely (the symlink primitive itself ROLLBACK.md's the deploy).
  </resume-signal>
  <acceptance_criteria>
    - 06.5-VERIFICATION.md has all 5 drill rows filled with Pass/Fail, Timestamp, Notes.
    - All 5 drills marked Pass; OR if any Fail, a gap-closure plan is queued and this verification doc records the failure mode + the gap-closure plan reference.
    - `pnpm trace:check` output (or its `:json` variant) is pasted into VERIFICATION.md and shows REQ-DEP-01, REQ-DEP-04, REQ-CLI-08 all have their `required_stages` covered with no `missing_stage` for the phase reqs.
    - docs/deploy/uat-06.5-client-fast-path.md has operator initials + date in the Signoff section (the section pre-authored in Plan 03).
    - VERIFICATION.md `Status` field updated from `pending` → `passed` (or `failed`).
  </acceptance_criteria>
  <done>All 5 drills executed, signoff captured, traceability checked. Phase 06.5 is either verified-passing or a gap-closure plan is queued.</done>
</task>

</tasks>

<verification>
- 06.5-VERIFICATION.md exists and is fully populated.
- `pnpm trace:check` output proves REQ-DEP-01 / REQ-DEP-04 / REQ-CLI-08 have all required stages covered.
- docs/deploy/uat-06.5-client-fast-path.md signed off.
- All 5 drills passed (or, if not, gap-closure plan queued and named in the failed row's Notes).
</verification>

<success_criteria>
- Five drills exercising every locked decision from CONTEXT.md and every RESEARCH-flagged pitfall.
- Operator signoff on real staging infrastructure.
- Phase-gate traceability check green for all three REQ-IDs.
- Mixed-diff + 06.4 regression tests prevent silent reintroduction of the c01038f knobs being lost.
</success_criteria>

<threat_model>
## Trust Boundaries

| Boundary | Description |
|----------|-------------|
| operator → staging Fly machine via flyctl ssh | Drill 1 destroys volume content; drill 3 flips the live symlink. Operator-authorized actions on a non-production environment. |

## STRIDE Threat Register

| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-06.5-16 | Denial of Service | Drill 1 destroys staging volume content during business hours | accept | Staging is non-production. Operator runs the drill at a coordinated time. Bundled fallback ensures the site stays up DURING the drill (that's the drill's whole point). |
| T-06.5-17 | Tampering | Drill 5 mixed-diff commits introduce noise into git history | mitigate | Drill 5 commits are trivial whitespace; squash-merged or reverted post-drill. VERIFICATION.md records the commit SHAs so they can be reverted in a follow-up. |
| T-06.5-18 | Repudiation | operator skips a drill silently | mitigate | VERIFICATION.md Pass/Fail field is required per row; the `pnpm trace:check` cross-check enforces stage coverage; checkpoint `acceptance_criteria` makes this human-verifiable. |
</threat_model>

<output>
After completion, create `.planning/phases/06.5-static-client-asset-split-zero-cost-client-only-fly-deploys-/06.5-05-SUMMARY.md` documenting: (a) the final state of 06.5-VERIFICATION.md (link to the file; do NOT duplicate its contents), (b) the actual wall-clock for drills 2 + 3 (fast-path under 5 min, rollback under 60 s), (c) any UAT failures and their gap-closure plan references, (d) the `pnpm trace:check` output proving phase exit-gate is satisfied for REQ-DEP-01, REQ-DEP-04, REQ-CLI-08.
</output>
