Both remaining agents were stopped for token budget and their partial work committed as WIP (75a6724dLA1 fix round,c6019424LA2). The handoff now carries: full worktree paths with branches and HEADs, exactly what each stopped agent had finished versus what it still owes, and a paste-ready kickoff prompt naming all three resumable items plus the two owed merge items. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
284 lines
16 KiB
Markdown
284 lines
16 KiB
Markdown
# 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 <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 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.
|
||
```
|