From c9fc7f4a66b33388397aab27a55754d83a87a2c8 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 14 Aug 2026 16:30:38 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20Campaign=20LA=20session=20handoff=20?= =?UTF-8?q?=E2=80=94=20state,=20in-flight=20recovery,=20process,=20goal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../2026-08-14-campaign-la-handoff.md | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 docs/research/2026-08-14-campaign-la-handoff.md diff --git a/docs/research/2026-08-14-campaign-la-handoff.md b/docs/research/2026-08-14-campaign-la-handoff.md new file mode 100644 index 00000000..cd7dd77c --- /dev/null +++ b/docs/research/2026-08-14-campaign-la-handoff.md @@ -0,0 +1,202 @@ +# 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; F5–F8 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 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. 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. + +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. +```