docs(planning): add M0-M7 milestones layer + CLAUDE.md milestone discipline
Introduce a morale + scope-management layer above the roadmap. Seven
milestones (M0-M7) from "Connect & explore" to "v1.0", each defined by a
concrete playable scenario and ~6-10 weeks of work. Each milestone hit
triggers a recorded demo video + a freeze list of phases that go
off-limits until M7's polish pass.
M0 ("Connect & explore") is declared done retroactively — ~25 shipped
phases through 2026-05-12 (terrain, network, audio, particles, chat,
input, streaming, WB rendering migration, sky/lighting, particle system,
combat/spell/item data layers) are frozen. Currently working toward M1
("Walkable + clickable world"): L.2 collision + B.4 interaction, ~4-6
weeks.
CLAUDE.md gains a "Milestone discipline" section above the existing
"Roadmap discipline" — sets the two-altitude orientation (milestones
above, phases below), names M1 as the current target, and codifies the
four motivation rules: (1) one active milestone at a time, (2) frozen
phases off-limits, (3) recorded demo video per landing, (4) state both
altitudes at session start.
Addresses the "everything is half-built" feeling caused by per-phase
vertical-slice ships never adding up to a milestone-level "done" event.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d1d02c34c2
commit
ecb0f2d65f
2 changed files with 368 additions and 0 deletions
58
CLAUDE.md
58
CLAUDE.md
|
|
@ -526,6 +526,64 @@ spec path, the files it should read, the acceptance criteria (build + test
|
||||||
green), and the commit message style. Subagents inherit CLAUDE.md so they
|
green), and the commit message style. Subagents inherit CLAUDE.md so they
|
||||||
follow the same rules.
|
follow the same rules.
|
||||||
|
|
||||||
|
## Milestone discipline
|
||||||
|
|
||||||
|
acdream operates at **two altitudes** above the daily commit:
|
||||||
|
|
||||||
|
- **`docs/plans/2026-05-12-milestones.md`** — the morale + scope layer.
|
||||||
|
Seven milestones (M0–M7) from "Connect & explore" to "v1.0", each
|
||||||
|
defined by a concrete playable scenario and ~6–10 weeks of work. This
|
||||||
|
is where you orient when the project feels half-built and you're not
|
||||||
|
sure what to work on. Phases are too granular to feel like progress;
|
||||||
|
this doc is the multi-week target.
|
||||||
|
- **`docs/plans/2026-04-11-roadmap.md`** — the strategic roadmap (next
|
||||||
|
section). Phase-level index. This is where you orient when you know
|
||||||
|
the milestone and need the next concrete sub-phase.
|
||||||
|
|
||||||
|
**Currently working toward: M1 — Walkable + clickable world.** L.2
|
||||||
|
collision + B.4 interaction. Demo target: walk through Holtburg without
|
||||||
|
getting stuck, open the inn door, click an NPC, pick up an item.
|
||||||
|
Estimated 4–6 weeks from 2026-05-12.
|
||||||
|
|
||||||
|
**The four motivation-keeping rules:**
|
||||||
|
|
||||||
|
1. **One active milestone at a time.** Work that isn't on the critical
|
||||||
|
path to M1 gets filed in `docs/ISSUES.md` with a `post-M1` tag and
|
||||||
|
muted. This is the single rule that kills the "jumping between
|
||||||
|
things" feeling. If a phase isn't part of the current milestone, it
|
||||||
|
doesn't get touched — even if it's tempting, even if it would be
|
||||||
|
"quick", even if it would be "while I'm here."
|
||||||
|
|
||||||
|
2. **Frozen phases are off-limits.** M0's ~25 shipped phases are frozen
|
||||||
|
until M7's polish pass. Concretely: no rework on streaming, chat,
|
||||||
|
input, the WB rendering migration, sky/lighting, the particle
|
||||||
|
system, or the network handshake. Those are done. Don't revisit them
|
||||||
|
— even if you see something that could be 10% better. Visual
|
||||||
|
nice-to-haves and architecture second-guesses on frozen phases are
|
||||||
|
explicitly post-M7. The freeze list per milestone lives in the
|
||||||
|
milestones doc.
|
||||||
|
|
||||||
|
3. **Each milestone hit gets a recorded demo video.** When M1 lands,
|
||||||
|
record ~30 seconds of the demo scenario, drop it at
|
||||||
|
`docs/milestones/M1-walkable-clickable.mp4`, and pin a still + a
|
||||||
|
one-paragraph writeup at the top of `2026-05-12-milestones.md`. The
|
||||||
|
freeze list updates. The "currently working toward" line in this
|
||||||
|
CLAUDE.md updates to M2. **Crossing a milestone is a real event with
|
||||||
|
an artifact** — that's the morale instrument. Phases ship; milestones
|
||||||
|
land.
|
||||||
|
|
||||||
|
4. **State both altitudes at session start.** First action of any
|
||||||
|
session: "Currently working toward M1 — Walkable + clickable world.
|
||||||
|
Current phase: L.2. Next concrete step: [whatever]." This keeps the
|
||||||
|
high-level orientation visible alongside the immediate task and
|
||||||
|
makes mid-session drift obvious.
|
||||||
|
|
||||||
|
When reality and the milestones diverge — a phase grows beyond the
|
||||||
|
milestone's scope, a demo scenario turns out to be unreachable without
|
||||||
|
a new sub-phase, the order needs reshuffling — update the milestones
|
||||||
|
doc in the same session you discover the divergence. Same rule as the
|
||||||
|
roadmap.
|
||||||
|
|
||||||
## Roadmap discipline
|
## Roadmap discipline
|
||||||
|
|
||||||
acdream's plan lives in two files committed to the repo:
|
acdream's plan lives in two files committed to the repo:
|
||||||
|
|
|
||||||
310
docs/plans/2026-05-12-milestones.md
Normal file
310
docs/plans/2026-05-12-milestones.md
Normal file
|
|
@ -0,0 +1,310 @@
|
||||||
|
# acdream — milestones (morale + scope layer)
|
||||||
|
|
||||||
|
**Status:** Living document. Created 2026-05-12.
|
||||||
|
**Sits above:** [`docs/plans/2026-04-11-roadmap.md`](2026-04-11-roadmap.md) (the strategic phase index).
|
||||||
|
**Currently working toward:** **M1 — Walkable + clickable world.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Why this document exists
|
||||||
|
|
||||||
|
The roadmap is a phase index — week- to month-scale, ~50 phases by the time
|
||||||
|
v1.0 lands. Phases ship in vertical slices (architecture-first, horizontal
|
||||||
|
completion deferred), which is the right strategy for a solo open-source
|
||||||
|
project at this scale — but it leaves a chronic "everything is half-built"
|
||||||
|
feeling because no single phase ship feels like a real milestone.
|
||||||
|
|
||||||
|
This document sits **one altitude above** the roadmap. Each milestone is:
|
||||||
|
|
||||||
|
- **~6–10 weeks of focused work** (not a single phase, not a whole year).
|
||||||
|
- Defined by a **concrete playable scenario** that gets recorded as a demo
|
||||||
|
video when the milestone hits.
|
||||||
|
- A **scope-freeze event**: when a milestone lands, the phases it covers go
|
||||||
|
off-limits until v1.0's final polish pass (M7).
|
||||||
|
|
||||||
|
Crossing a milestone is a real event with an artifact. Phases ship; milestones
|
||||||
|
**land**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Operating rules
|
||||||
|
|
||||||
|
1. **One active milestone at a time.** Everything not on the critical path to
|
||||||
|
the current milestone gets filed in `docs/ISSUES.md` with a `post-MN` tag
|
||||||
|
and explicitly muted until the milestone hits. This is what kills the
|
||||||
|
jumping-between-things feeling.
|
||||||
|
|
||||||
|
2. **Frozen phases are off-limits.** "Frozen" means no rework, no polish, no
|
||||||
|
follow-up commits unless something is actively broken (player crash,
|
||||||
|
regression). Visual nice-to-haves, "while I'm here" cleanups, and
|
||||||
|
architecture second-guesses are all post-M7. The freeze is the discipline
|
||||||
|
mechanism that makes the milestone meaningful — without it, M0's many
|
||||||
|
shipped phases keep silently consuming attention.
|
||||||
|
|
||||||
|
3. **The milestone log is the morale instrument.** When a milestone hits:
|
||||||
|
- Record a ~30-second demo video showing the scenario end-to-end.
|
||||||
|
- Drop it in `docs/milestones/MN-<slug>.mp4` (create the directory on
|
||||||
|
first hit).
|
||||||
|
- Pin a still frame + one-paragraph writeup at the top of this doc.
|
||||||
|
- Update the freeze list. Update CLAUDE.md's "currently working toward"
|
||||||
|
line to the next milestone.
|
||||||
|
|
||||||
|
4. **State both altitudes at session start.** "Currently working toward M1.
|
||||||
|
Current phase: L.2 collision. Next concrete step: L.2d slice 1 spec." This
|
||||||
|
keeps the high-level orientation visible alongside the immediate task and
|
||||||
|
makes mid-session drift obvious.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The milestones
|
||||||
|
|
||||||
|
### M0 — "Connect & explore" — ✅ DONE (crossed months ago)
|
||||||
|
|
||||||
|
**Demo scenario:** Log in, walk Holtburg in chase camera, see other characters
|
||||||
|
animate, send a chat message and see the echo, watch day turn to night,
|
||||||
|
listen to footsteps and ambient audio.
|
||||||
|
|
||||||
|
**Phases included (frozen):**
|
||||||
|
|
||||||
|
| Phase | What landed |
|
||||||
|
|---|---|
|
||||||
|
| 1–3 | Terrain + per-vertex normals + per-cell texture blending |
|
||||||
|
| 4 | UDP codec + handshake + character login + WorldSession |
|
||||||
|
| 5 | ObjDesc: AnimPartChange + TextureChanges + SubPalettes + ObjScale |
|
||||||
|
| 6.1–6.7 | Motion + animation foundation (idle, frame playback, slerp, UpdateMotion, UpdatePosition) |
|
||||||
|
| 7.1 | EnvCell room geometry — walls/floors/ceilings |
|
||||||
|
| 9.1–9.2 | Translucent render pass + back-face culling |
|
||||||
|
| A.1–A.5 | Streaming landblock loader → two-tier streaming |
|
||||||
|
| B.1–B.3 | Outbound ack pump + player movement + physics MVP resolver |
|
||||||
|
| D.1, D.2a | 2D overlay + ImGui scaffold + `AcDream.UI.Abstractions` layer |
|
||||||
|
| E.1–E.5 | Motion hooks + audio + particles + combat wire + spell wire |
|
||||||
|
| F.1, F.2 | GameEvent dispatcher + item model + Appraise |
|
||||||
|
| G.1, G.2 | Sky + day/night + weather + dynamic lighting |
|
||||||
|
| H.1, I.1–I.8 | Chat wire + UI consolidation + holtburger inbound parity + combat translator |
|
||||||
|
| K, L.0 | Input architecture + retail bindings + Settings panel |
|
||||||
|
| N.0–N.6.1 | WB rendering migration (modern path mandatory) |
|
||||||
|
| C.1, C.1.5a/b | Particle system + portal/EnvCell static-script wiring |
|
||||||
|
| R.1–R.3 | Retail research infrastructure (PDB extract + named decomp) |
|
||||||
|
|
||||||
|
**Status:** This is everything shipped through 2026-05-12. ~25 phase ships.
|
||||||
|
**Worth saying out loud: this is the hard half of the project.** The engine
|
||||||
|
runs, the world renders correctly, the network connects, the input is wired,
|
||||||
|
the data layers for combat/spells/items/audio/particles all exist. What's
|
||||||
|
missing is the gameplay loop on top.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### M1 — "Walkable + clickable world" — 🟡 CURRENT (~4–6 weeks)
|
||||||
|
|
||||||
|
**Demo scenario:** Walk through Holtburg without getting stuck on the inn
|
||||||
|
doorway. Open the inn door. Click an NPC and see selection feedback. Pick
|
||||||
|
up an item from the ground.
|
||||||
|
|
||||||
|
**Phases to ship:**
|
||||||
|
- **L.2 (all sub-lanes a–f)** — Movement & Collision Conformance. Currently
|
||||||
|
active; L.2a slices 1+2+3 shipped 2026-05-12.
|
||||||
|
- **B.4** — `Use` / `UseWithTarget` / `PickUp` outbound messages.
|
||||||
|
|
||||||
|
**Freeze on landing:**
|
||||||
|
- L.2 zone (collision, cell ownership, transition parity, wire authority)
|
||||||
|
- B.4 zone (interaction outbound)
|
||||||
|
|
||||||
|
**What "M1 lands" looks like:** the existing Holtburg traversal works as a
|
||||||
|
retail player would expect. Doorways are walkable. Buildings have solid
|
||||||
|
walls. Outdoor cell seams report the right cell. Clicking an NPC selects it
|
||||||
|
and sends a usable selection state to the server. The Use action opens doors.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### M2 — "Kill a drudge" — 🔵 NEXT (~6–10 weeks after M1)
|
||||||
|
|
||||||
|
**Demo scenario:** Equip a sword. Walk to a drudge. Swing. See "You hit
|
||||||
|
Drudge for 12 slashing damage (87%)" in chat. Watch the swing animation
|
||||||
|
play. Drudge dies, drops loot. Pick up the loot. Open the inventory panel
|
||||||
|
and see it.
|
||||||
|
|
||||||
|
**Phases to ship:**
|
||||||
|
- **F.2 (panels)** — Inventory panel reading `ItemRepository` (data already
|
||||||
|
shipped in F.2 base; M2 ships the visual surface).
|
||||||
|
- **F.3** — Combat math + damage flow.
|
||||||
|
- **F.5a** — Visible-at-login dev panels (Attributes, Skills, Equipped,
|
||||||
|
Inventory list) — minimal ImGui surfaces, retail-skin deferred to M5.
|
||||||
|
- **L.1c** — Combat animation wiring (draw/sheath, attack swings by
|
||||||
|
stance/power/height, hit reactions, evades).
|
||||||
|
- **L.1b** — Command router + motion-state cleanup (prereq for L.1c).
|
||||||
|
|
||||||
|
**Freeze on landing:**
|
||||||
|
- Combat math zone
|
||||||
|
- Inventory zone (data + dev panel; retail-skin reopens in M5)
|
||||||
|
- L.1b/c combat-animation zone
|
||||||
|
|
||||||
|
**What "M2 lands" looks like:** the gameplay loop is real. You can fight,
|
||||||
|
take damage, kill things, see loot, manage your inventory. The game becomes
|
||||||
|
a game.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### M3 — "Cast a spell" — 🔵 (~3–4 weeks after M2)
|
||||||
|
|
||||||
|
**Demo scenario:** Cast Flame Bolt at a drudge. Watch the cast animation,
|
||||||
|
the projectile, the impact. Self-cast a buff (Strength Self). See the
|
||||||
|
enchantment in a buff list. Recall to lifestone — full recall animation,
|
||||||
|
correct teleport, correct re-spawn.
|
||||||
|
|
||||||
|
**Phases to ship:**
|
||||||
|
- **F.4** — Spell cast state machine (buffs + recalls first, projectile
|
||||||
|
spells second).
|
||||||
|
- **L.1d** — Spell-casting animation wiring (cast command classification,
|
||||||
|
windup, release, fizzle/interruption, recoil).
|
||||||
|
- **F.5 (Spellbook panel)** — dev-skin surface for learned spells + active
|
||||||
|
enchantments.
|
||||||
|
|
||||||
|
**Freeze on landing:**
|
||||||
|
- F.4 spell zone
|
||||||
|
- L.1d cast-animation zone
|
||||||
|
- Spellbook dev-panel surface
|
||||||
|
|
||||||
|
**What "M3 lands" looks like:** mages are real characters. Buffs work,
|
||||||
|
recalls work, the first projectile spells work. Combat from M2 + casting
|
||||||
|
from M3 = retail-equivalent gameplay loop for melee and casters.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### M4 — "Live in the world" — 🔵 (~6–10 weeks)
|
||||||
|
|
||||||
|
**Demo scenario:** Create a fresh character from scratch (no ACE admin).
|
||||||
|
Spawn. Talk to an NPC. Accept a quest. Walk to a dungeon entrance. Portal
|
||||||
|
in (pink-bubble loading). Walk through the dungeon. Complete the quest.
|
||||||
|
Walk back out.
|
||||||
|
|
||||||
|
**Phases to ship:**
|
||||||
|
- **H.3** — Emote scripts + quests + dialogs (122 EmoteType × 39 Trigger
|
||||||
|
mini-VM).
|
||||||
|
- **G.3** — Dungeon streaming + portal space + `PlayerTeleport` handling.
|
||||||
|
(Unblocked by L.2e from M1.)
|
||||||
|
- **H.4** — Character creation (`0xE000002 CharGen` + heritages + appearance
|
||||||
|
picker + preview).
|
||||||
|
- **L.1e** — Emote + posture animation wiring.
|
||||||
|
|
||||||
|
**Freeze on landing:**
|
||||||
|
- H.3 dialog/quest zone
|
||||||
|
- G.3 dungeon zone
|
||||||
|
- H.4 character-creation zone
|
||||||
|
- L.1e emote-animation zone
|
||||||
|
|
||||||
|
**What "M4 lands" looks like:** the world feels populated and interactive.
|
||||||
|
You can do quests, enter dungeons, create characters. Combined with M2/M3,
|
||||||
|
the client is **functionally playable** — minus visual polish.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### M5 — "Looks like retail" — 🟢 PARALLELIZABLE WITH M3/M4 (~4–8 weeks)
|
||||||
|
|
||||||
|
**Demo scenario:** Side-by-side screenshot of acdream vs retail at the same
|
||||||
|
location, same time of day, same character. Hard to tell apart at a glance.
|
||||||
|
Open the inventory panel — retail-skinned with the right font, icons, and
|
||||||
|
9-slice panel borders.
|
||||||
|
|
||||||
|
**Phases to ship:**
|
||||||
|
- **C.1.5c** — Sky-PES dispatch chain (closes #2 lightning, #28 aurora,
|
||||||
|
#29 cloud thinness).
|
||||||
|
- **C.2** — Dynamic point lights (fireplaces, lamps, torches with proper
|
||||||
|
local lighting).
|
||||||
|
- **C.3** — Palette range tuning (skin/hair/eye colors match retail).
|
||||||
|
- **C.4** — Double-sided translucent polys.
|
||||||
|
- **D.2b** — Custom retail-look UI backend.
|
||||||
|
- **D.3–D.7** — AcFont + dat sprites + core panels reskinned + HUD orbs +
|
||||||
|
cursor manager.
|
||||||
|
- **L.1f** — NPC/monster + item-use animation coverage.
|
||||||
|
|
||||||
|
**Freeze on landing:**
|
||||||
|
- Visual polish zone (C.1.5c, C.2, C.3, C.4)
|
||||||
|
- D.2b → D.7 UI-skin zone
|
||||||
|
- L.1f NPC-anim zone
|
||||||
|
|
||||||
|
**What "M5 lands" looks like:** the client visually convinces. Screenshots
|
||||||
|
become postable. The "old / broken vs retail" feeling that drives most of
|
||||||
|
the chronic ISSUES.md entries is gone.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### M6 — "Plugins ship" — 🟢 (~4 weeks)
|
||||||
|
|
||||||
|
**Demo scenario:** A third party (not you) writes a small plugin against
|
||||||
|
the published API — XP tracker, loot logger, simple chat filter — and it
|
||||||
|
loads cleanly. Sample plugin lives in the repo with documented build steps.
|
||||||
|
|
||||||
|
**Phases to ship:**
|
||||||
|
- Plugin API surface: stable contract over `AcDream.Core` + `AcDream.UI.Abstractions`,
|
||||||
|
versioned, with the world-state interfaces exposed.
|
||||||
|
- Plugin host: load isolation, lifecycle, error containment.
|
||||||
|
- Sample plugin (XP tracker or loot logger) — proves the API by using it.
|
||||||
|
- Plugin docs page.
|
||||||
|
|
||||||
|
**Freeze on landing:**
|
||||||
|
- Plugin API v1 surface (additive changes only post-freeze).
|
||||||
|
|
||||||
|
**What "M6 lands" looks like:** the differentiator vs the retail client is
|
||||||
|
real. acdream offers something retail never did, and the API is documented
|
||||||
|
well enough that other people can build on it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### M7 — "v1.0" — 🟢 (open-ended polish)
|
||||||
|
|
||||||
|
**Demo scenario:** Long-running stress test: log in, play for 4 hours
|
||||||
|
across outdoor + dungeon + portal + combat + spell + chat scenarios,
|
||||||
|
reconnect once mid-session, log out clean. No crashes, no protocol errors,
|
||||||
|
no visual regressions, no audio dropouts.
|
||||||
|
|
||||||
|
**Phases to ship:**
|
||||||
|
- **Phase M** — Network stack conformance (retransmit, ACK piggybacking,
|
||||||
|
echo/keepalive, fragment splitting, typed actions). Deferred until now
|
||||||
|
because ACE handles loss gracefully — but v1.0 needs proper network
|
||||||
|
hardening.
|
||||||
|
- **H.2** — Allegiance.
|
||||||
|
- **N.6 slice 2 + N.7–N.10** — Finish WB rendering migration (EnvCells,
|
||||||
|
sky/particles via WB, visibility manager, GL infrastructure
|
||||||
|
consolidation).
|
||||||
|
- **Phase J long-tail** — Player rig polish, group/fellowship UI, trade
|
||||||
|
window, salvage/tinker UI, house ownership, society UI, dev-mode tools.
|
||||||
|
- **L.1g** — Animation polish + conformance.
|
||||||
|
- Final visual + audio polish pass against ISSUES.md chronic backlog.
|
||||||
|
|
||||||
|
**What "M7 lands" looks like:** v1.0. Ship.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Estimated timeline
|
||||||
|
|
||||||
|
| Milestone | Effort | Cumulative |
|
||||||
|
|---|---|---|
|
||||||
|
| M0 | DONE | DONE |
|
||||||
|
| M1 | ~4–6 wk | ~5 wk |
|
||||||
|
| M2 | ~6–10 wk | ~13 wk |
|
||||||
|
| M3 | ~3–4 wk | ~17 wk |
|
||||||
|
| M4 | ~6–10 wk | ~25 wk |
|
||||||
|
| M5 | ~4–8 wk (parallel) | overlaps M3/M4 |
|
||||||
|
| M6 | ~4 wk | ~29 wk |
|
||||||
|
| M7 | open-ended | v1.0 |
|
||||||
|
|
||||||
|
**Roughly 9–12 months of focused solo work from 2026-05-12 to v1.0.** That's
|
||||||
|
honest for an open-source project of this scale. The biggest single rock is
|
||||||
|
M2 (combat math + animations + inventory panels lining up); M5 can be
|
||||||
|
chipped at in parallel by subagents while you drive M3/M4.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What this document is **not**
|
||||||
|
|
||||||
|
- **Not a release schedule.** Internal morale + scope layer only. If acdream
|
||||||
|
goes public-alpha at some point, that's a separate decision built on top
|
||||||
|
of one of these milestones.
|
||||||
|
- **Not immutable.** When reality and the milestones diverge, update the
|
||||||
|
milestones in the same session you discover the divergence. Same rule as
|
||||||
|
the roadmap.
|
||||||
|
- **Not a replacement for the roadmap.** Phases are still where the
|
||||||
|
implementation details live. This doc is the orientation layer above them.
|
||||||
|
- **Not granular enough for daily work.** Daily work happens at the phase /
|
||||||
|
sub-phase / commit level. The milestone is the multi-week target you're
|
||||||
|
aiming at.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue