Self-contained handoff for a fresh session: what the campaign is and which decisions are settled, the slice ledger with commits, the in-flight slices and how to recover them from git, the two owed merge items (cross-assembly contract test, Launcher.Core CI lane), the session landmines (index-sweep, stale agent worktrees, contract-in-prompts), the binding process, and the goal text to set. Committed via pathspec so a live implementer agent index in this worktree is untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
11 KiB
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.
Branch: claude/acdream-launcher-credentials-4d2f7c
Worktree: .claude/worktrees/acdream-launcher-credentials-4d2f7c
HEAD at handoff: 498f1c11
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
gmCharacterManagementUIis 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 returned FIX-FIRST; fix round IN FLIGHT | db9ad53c (MIXED — see §4), note e1322a06 |
| LA2 probe mode + idle policy | implementer IN FLIGHT | branch campaign-la2 (base 498f1c11) |
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 IN FLIGHT at handoff — recover these first
Three agents were running when this handoff was written. Their results arrive as task notifications in the ORIGINAL session only; a new session must verify state from git instead of waiting.
- LA1 fix round — main worktree, branch
claude/acdream-launcher-credentials-4d2f7c. Findings: F1 (HIGH, required) theSessionStatusWritermust never throw into the login/teardown transactions and must create its parent directory (an unwritable/missing status path currently fails a healthy session — first-run trigger); F2 App reader must TOLERATEprocess.paths(parse-and-ignore, like the existingpolicy) and explicitly REFUSEmode: "probe"with a named error; F4 production-shape the shared fixture (process.content,standardInputcredential); F3 reconnect emitsdisconnectedfirst + record the mid-play drop limitation; F5–F8 minor hardening. - LA2 implementer — worktree
.claude/worktrees/acdream-la2, branchcampaign-la2. - LA3 fix round — COMPLETE at
26feba81(worktree.claude/worktrees/acdream-la3, branchcampaign-la3). All 12 findings fixed: the CRITICAL"paths": {}emission (now omitted entirely), probe composition (ComposeProbe+modefield), graceful stop (Linux SIGINT vialibc 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, uintSecondsGreyedOut, andMalformedStatusEvent. 94/94 Windows AND WSL. NEXT: narrow re-review of26feba81, then mergecampaign-la3(with the two owed merge items below).
To recover: git -C <worktree> 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.Corecomposer-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.Teststo.github/workflows/headless-portability.yml(bothpaths:filters + the Linux test array), mirroring what LA0 did forAcDream.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
- Never run git state commands in a worktree while an implementer agent is
live in it.
git add <path>scopes the ADD;git commitcommits the whole INDEX. A docs commit swept 37 in-progress LA1 files intodb9ad53c; the marker commite1322a06documents it. Memory:claude-memory/feedback_no_commits_beside_live_agents.md. - 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.
- PowerShell 5.1 mangles double quotes inside heredoc commit messages — keep git commit bodies quote-free.
- 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.
- 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 testgreen before a slice is DONE; ≥1 commit per slice taggedCampaign LA; every retail deviation adds itsdocs/architecture/retail-divergence-register.mdrow 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, andclaude-memory/current as slices land.
6. 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):
GOAL: Ship Campaign LA — the acdream launcher/installer/updater + retail character-select screen.
Start at docs/research/2026-08-14-campaign-la-handoff.md, then the ledger in
docs/plans/2026-08-14-launcher-campaign.md. Recover the three in-flight slices
first (LA1 fix round on the campaign branch, LA2 on campaign-la2, LA3 fix round
on campaign-la3) by inspecting git state, 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.