acdream/docs/research/2026-08-14-campaign-la-handoff.md
Erik c9fc7f4a66 docs: Campaign LA session handoff — state, in-flight recovery, process, goal
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>
2026-08-14 16:30:38 +02:00

11 KiB
Raw Blame History

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 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 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.

  1. LA1 fix round — main worktree, branch claude/acdream-launcher-credentials-4d2f7c. Findings: F1 (HIGH, required) the SessionStatusWriter must 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 TOLERATE process.paths (parse-and-ignore, like the existing policy) and explicitly REFUSE mode: "probe" with a named error; F4 production-shape the shared fixture (process.content, standardInput credential); F3 reconnect emits disconnected first + record the mid-play drop limitation; F5F8 minor hardening.
  2. LA2 implementer — worktree .claude/worktrees/acdream-la2, branch campaign-la2.
  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 <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.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 <path> 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 34 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. 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.