# Campaign LA — session handoff (2026-08-14) **Read this first, then `docs/plans/2026-08-14-launcher-campaign.md` (the plan + ledger), then `docs/superpowers/specs/2026-08-14-launcher-campaign-design.md` (the approved design).** Memory crib: `claude-memory/project_launcher_direction.md`. ## Worktrees (full paths — work in the campaign worktree, NOT the repo root) | Purpose | Full path | Branch | HEAD at handoff | |---|---|---|---| | **Campaign branch — START HERE** | `C:\Users\erikn\source\repos\acdream\.claude\worktrees\acdream-launcher-credentials-4d2f7c` | `claude/acdream-launcher-credentials-4d2f7c` | `75a6724d` | | LA2 slice | `C:\Users\erikn\source\repos\acdream\.claude\worktrees\acdream-la2` | `campaign-la2` | `c6019424` | | LA3 slice | `C:\Users\erikn\source\repos\acdream\.claude\worktrees\acdream-la3` | `campaign-la3` | `26feba81` | | LA7a slice (merged — removable) | `C:\Users\erikn\source\repos\acdream\.claude\worktrees\acdream-la7a` | `campaign-la7a` | `0c8643a7` | The repo root `C:\Users\erikn\source\repos\acdream` is on `main` and is NOT where this campaign happens. --- ## 1. What Campaign LA is One external product — the **acdream launcher** — that is simultaneously the installer, the updater, and the multi-server / multi-account / multi-character session launcher (ThwargLauncher UX model), on **Windows and Linux**; plus the one client-side feature the launcher flow exposes as missing, the **retail character-management screen**. Design decisions already made and NOT to be re-litigated (spec §2): - Avalonia UI; `AcDream.Launcher` (thin) + `AcDream.Launcher.Core` (BCL-only). - **Credentials in a plaintext file — user-decided.** 0600 on Linux; never in logs, arguments, session configs, or the status stream. - **Approach A, file-contract orchestrator:** the launcher speaks NO game protocol. Config file in → password via child stdin → JSONL status events out. (Launcher embedding Runtime was REJECTED: a probe login that fails to tear down gracefully poisons the ACE account ~3 min.) - Full CRUD in the launcher UI; hand-editing JSON is never required. - Character enumeration by **headless probe** (connect → CharacterList → graceful disconnect BEFORE EnterWorld → exit) plus cache-from-observation. - **Retail char-select has NO 3D preview** — recon-corrected. Retail's `gmCharacterManagementUI` is a flat listbox + Enter/Delete/Restore + dialogs; the rotating-model viewport is character-CREATION-only. Create Character is a future campaign. - Everything (launch + install + update) in ONE campaign. - **Linux posture (user-directed):** the full launcher stack ships Linux-tested in this campaign; GUI *client* launches stay Windows-only until Slice L resumes later. The launcher renders gui/guiSelect disabled on Linux with an explicit Slice-L note. --- ## 2. Slice ledger at handoff | Slice | State | Commits | |---|---|---| | LA0 `AcDream.Platform` extraction | **DONE** (review closed) | `cb6502c8`, `a49e92df`, `7a839cba` | | LA1 launch contract (App CLI + status writer + roster seam) | implemented; Opus review FIX-FIRST; **fix round WIP — stopped mid-task**, see §3 | `db9ad53c` (MIXED — see §4), note `e1322a06`, WIP `75a6724d` | | LA2 probe mode + idle policy | **WIP — stopped mid-task**, see §3 | `c6019424` on branch `campaign-la2` | | LA3 `AcDream.Launcher.Core` | implemented; review FIX-FIRST (12 findings); **fix round LANDED — all 12 fixed, 94/94 Windows + WSL**; owes narrow re-review, then merge | `37d74e44`, `26feba81` on branch `campaign-la3` | | LA7a character wire messages | **DONE + MERGED** | `6a32f375`, `4338b1c1`, `0c8643a7`, merge `fa2de1c4` | | LA4 Avalonia UI | not started (needs LA3) | — | | LA5 plugin hosting | not started (needs LA1) | — | | LA6 login commands | not started (needs LA1, LA5) | — | | LA7b char-select state + flow | not started (needs LA1) | — | | LA8 authored char-select screen | not started (needs LA7b) | — | | LA9 installer / LA10 updater / LA11 closeout | not started | — | Register: **AD-97** filed (guid-only CharacterRestore request is an adaptation — retail sends ≥16 bytes, we send 8; ACE ignores the tail). --- ## 3. Work STOPPED MID-TASK — resume these first Two agents were **killed for token budget** and their partial work is **committed as clearly-marked WIP**. Build/test state at both WIP commits is UNVERIFIED — build and test before trusting either. 1. **LA1 fix round — WIP at `75a6724d`** (campaign worktree/branch). DONE in the WIP: F1 best-effort `SessionStatusWriter` (never throws into login/teardown, creates its parent directory), F2 App reader tolerance (parse-and-ignore `process.paths`, explicit named refusal of `mode: "probe"`), F5 `--session-config` argument hardening, new tests. **STILL OWED:** F4 production-shape the shared fixture (`tests/Fixtures/campaign-la/session-config-shared-fixture.json` — add `process.content`, switch credential to `standardInput`/`session`, assert values on BOTH sides; this was the agent's literal next step); F3 reconnect emits `disconnected` before the second `connected` + record the mid-play wire-drop limitation in the plan's status-stream section; F6 `exited` idempotency + distinct reason strings; F7 make the Runtime redaction test structural (assert the exact serialized property set per event kind); F8 platform-guard file-set test + fix the overstating `isLinux` comment; optional `RuntimeOptions.PrintMembers` redaction of `LivePass`. Then: run Runtime/App/Headless Release suites (+ WSL for Runtime/Headless) and dispatch the NARROW re-review. 2. **LA2 — WIP at `c6019424`** (worktree `...\acdream-la2`, branch `campaign-la2`). DONE in the WIP: probe flag through `LiveSessionConnectOptions`, the `StartCore` short-circuit before selection, the `mode` field with the `JsonRequired`→semantic-validation move, host exit-code mapping, 34 tests passing including 3 probe tests (agent's last report before the stop). **STILL OWED:** idle-policy unit tests (its next step), full Runtime+Headless Release suites on Windows AND WSL, then the Opus dual-lens review. 3. **LA3 fix round — COMPLETE at `26feba81`** (worktree `.claude/worktrees/acdream-la3`, branch `campaign-la3`). All 12 findings fixed: the CRITICAL `"paths": {}` emission (now omitted entirely), probe composition (`ComposeProbe` + `mode` field), graceful stop (Linux SIGINT via `libc kill`, Windows gap filed as **ISSUES #397** with the CREATE_NEW_PROCESS_GROUP + CTRL_BREAK direction), 0600 temp-file window, the Launcher.Core dependency-boundary guard, non-throwing parser/tailer, monotonic supervisor state, `0x`-prefix id parsing, uint `SecondsGreyedOut`, and `MalformedStatusEvent`. 94/94 Windows AND WSL. **NEXT: narrow re-review of `26feba81`, then merge `campaign-la3`** (with the two owed merge items below). **To recover:** `git -C log --oneline -3` and `git status` per branch. If a fix round committed, run its narrow re-review; if it did not, re-dispatch it from the finding list above (the reviews' full text is in the original session transcript, but the finding summaries here are sufficient to re-derive the work). **Owed at merge time (do not lose these):** - **Cross-assembly contract test** when LA1+LA3 meet: feed an `AcDream.Launcher.Core` composer-produced document to BOTH host loaders (App + Headless) and assert it parses. This is the permanent anti-drift enforcement for the pinned contract. - **CI lane**: add `tests/AcDream.Launcher.Core.Tests` to `.github/workflows/headless-portability.yml` (both `paths:` filters + the Linux test array), mirroring what LA0 did for `AcDream.Platform.Tests`. - After LA2 lands, App's reader must refuse `mode: "probe"` (covered by LA1 fix-round F2 — verify it actually landed). --- ## 4. Landmines / lessons from this session 1. **Never run git state commands in a worktree while an implementer agent is live in it.** `git add ` scopes the ADD; `git commit` commits the whole INDEX. A docs commit swept 37 in-progress LA1 files into `db9ad53c`; the marker commit `e1322a06` documents it. Memory: `claude-memory/feedback_no_commits_beside_live_agents.md`. 2. **Auto-created agent worktrees can be based on stale history.** The first LA3 dispatch landed on a spell-bar-era commit. Always create the worktree yourself from the campaign HEAD and make the agent verify its base commit as its first action. 3. **PowerShell 5.1 mangles double quotes inside heredoc commit messages** — keep git commit bodies quote-free. 4. **The pinned contract must live on disk, not in agent prompts.** It now does (plan §"Pinned launch-contract schema (v1, BINDING)"). The LA3 CRITICAL was a direct consequence of it living only in prompts. 5. **Reviews have caught something tests could not, four slices running:** lost Linux CI lanes (LA0), a real-but-mislabeled wire deviation (LA7a → AD-97), a cross-worktree contract break (LA3), an observability sink that could fail the transaction it observes (LA1). Do not downgrade the review step. --- ## 5. How we work (binding process) - **Fable plans, sequences, integrates. Sonnet implements bounded slices. Opus reviews every slice boundary, dual-lens:** (a) architectural — ownership, layering, dependency-guard integrity, seams; (b) retail fidelity against `docs/research/named-retail/` wherever the slice touches retail behavior. Findings → fix round → NARROW re-review of the fixes → slice DONE in ledger. - Max 3–4 agents in parallel INCLUDING children; subagents never spawn subagents. Every implementer prompt carries: spec+plan paths, files to read first, the pinned contract text if relevant, acceptance criteria, commit style, and a base-commit verification as its first action. - One implementer per worktree; that agent owns the worktree's git index. - `dotnet build` + `dotnet test` green before a slice is DONE; ≥1 commit per slice tagged `Campaign LA`; every retail deviation adds its `docs/architecture/retail-divergence-register.md` row in the same commit; **no workarounds without explicit user approval**. - Linux: every slice touching Launcher.Core/Headless/Runtime/Bake/Platform runs its test projects under WSL or native Ubuntu before it is DONE. - The ONLY stop-and-wait is a user connected/visual gate. Everything else is Claude's call — never present the user a work-order menu. - Keep the plan ledger, `docs/plans/2026-04-11-roadmap.md`, the CLAUDE.md Current-state pointer, and `claude-memory/` current as slices land. --- ## 6. Kickoff prompt for the new session Paste this as the FIRST message of the new session (it names the three resumable work items explicitly), then set the goal in §7. ```text Resume Campaign LA (the acdream launcher). Work in C:\Users\erikn\source\repos\acdream\.claude\worktrees\acdream-launcher-credentials-4d2f7c on branch claude/acdream-launcher-credentials-4d2f7c. Read docs/research/2026-08-14-campaign-la-handoff.md first, then the ledger in docs/plans/2026-08-14-launcher-campaign.md. Three items are waiting, all recoverable from git — two are partial work from agents that were stopped mid-task for token budget, and their build/test state is UNVERIFIED: 1. LA1 fix round — WIP commit 75a6724d on this branch. An agent had completed findings F1 (best-effort SessionStatusWriter that never throws into the login/teardown transactions and creates its parent directory), F2 (App reader tolerates process.paths and explicitly refuses mode:"probe"), and F5 (--session-config argument hardening). It was stopped just as it started F4. Finish: F4 production-shape tests/Fixtures/campaign-la/session-config-shared-fixture.json (add process.content, switch the credential to standardInput/session, assert values in BOTH host suites), F3 (reconnect emits disconnected before the second connected; record the mid-play wire-drop limitation in the plan's status-stream section), F6 (exited idempotency + distinct reason strings), F7 (make the Runtime redaction test structural — assert the exact serialized property set per event kind), F8 (platform-guard file-set test + fix the overstating isLinux comment), and optionally redact LivePass from RuntimeOptions.PrintMembers. Then build, run Runtime/App/Headless Release suites plus WSL for Runtime/Headless, and dispatch the narrow re-review. 2. LA2 — WIP commit c6019424 in worktree C:\Users\erikn\source\repos\acdream\.claude\worktrees\acdream-la2 (branch campaign-la2). An agent had implemented the probe flag through LiveSessionConnectOptions, the StartCore short-circuit before selection, the mode field with the JsonRequired-to-semantic-validation move, and the host exit-code mapping, with 34 tests green including 3 probe tests. It was stopped before writing the idle-policy unit tests. Finish those, run the Runtime+Headless Release suites on Windows and WSL, then dispatch the Opus dual-lens review. 3. LA3 — COMPLETE at 26feba81 in worktree C:\Users\erikn\source\repos\acdream\.claude\worktrees\acdream-la3 (branch campaign-la3). All 12 review findings fixed, 94/94 Windows and WSL. It needs only a narrow Opus re-review of 26feba81 against the finding list in §3 of the handoff, then merge into the campaign branch. At the LA1+LA3 merge, do not lose the two owed items: the cross-assembly contract test (feed a Launcher.Core composer document to BOTH host loaders) and adding tests/AcDream.Launcher.Core.Tests to the Linux CI lane in .github/workflows/headless-portability.yml. After those land, continue the ledger: LA4 (Avalonia UI), LA5 (plugin hosting), LA6 (login commands), LA7b (char-select state+flow), LA8 (authored screen), LA9 (installer), LA10 (updater), LA11 (closeout). ``` ## 7. The goal to set Set this with `/goal` in the new session (it is the same directive this session ran under, refreshed for the current state): ```text GOAL: Ship Campaign LA — the acdream launcher/installer/updater + retail character-select screen. Work in C:\Users\erikn\source\repos\acdream\.claude\worktrees\acdream-launcher-credentials-4d2f7c (branch claude/acdream-launcher-credentials-4d2f7c). Start at docs/research/2026-08-14-campaign-la-handoff.md, then the ledger in docs/plans/2026-08-14-launcher-campaign.md. Finish the three waiting items first — LA1 fix round (WIP 75a6724d, unverified), LA2 (WIP c6019424 on campaign-la2, unverified), LA3 (complete at 26feba81 on campaign-la3, owes a narrow re-review then merge) — then continue slice by slice. Process, per slice: 1. Fable plans/sequences/integrates — never present work-order menus; pick and announce. 2. Sonnet subagents implement bounded slices. Each prompt carries spec+plan paths, the exact files to read first, the pinned contract text when relevant, acceptance criteria (build+test green), commit style, and a base-commit verification as first action. Subagents may not spawn subagents. Hard cap 3-4 agents in parallel including children. One implementer per worktree; that agent owns the index — the orchestrator makes no git state changes in a worktree while an agent is live in it. 3. Every slice boundary gets an Opus dual-lens review: (a) architectural — ownership, layering, dependency-guard integrity, seams; (b) retail fidelity against docs/research/named-retail/ wherever the slice touches retail behavior. Fix findings, then a narrow re-review of the fixes. 4. dotnet build + dotnet test green before any slice is declared done; Linux (WSL or native Ubuntu) runs for every slice touching Launcher.Core/Headless/Runtime/Bake/ Platform. One commit per slice minimum, tagged "Campaign LA". Any retail deviation adds its divergence-register row in the same commit. No workarounds without explicit approval. 5. As slices land: update the plan ledger, docs/plans/2026-04-11-roadmap.md, the CLAUDE.md Current state pointer, and claude-memory/. 6. The only stop-and-wait is a user connected/visual gate (launch modes vs local ACE, character-probe round-trip, char-select visual matrix, first-run wizard, update swap). When a slice reaches one: write the exact test script under docs/research/, announce the gate, and keep driving any slices not blocked behind it. DONE = all slices code-complete, automated gates green, dual reviews closed, and the connected-gate checklist delivered to the user in one script document. ```