acdream/docs/research/2026-08-20-vtank-plugin-milestone-handoff.md
Erik 690f21889e docs: handoff for the VTank-class plugin automation milestone
The requirements research from 2026-07-29 was nearly lost: it lives in a
session titled "graphics" because it was one strand of a session about
something else, and could not be found again by any search. The research
itself was committed (6077ce4d) and survived; this makes it findable and
usable by a session picking the work up cold.

Contents: reading order, the architectural conclusion not to relitigate
(VTank's meta FSM, expressions and loot engine are plugin-land, not
host-land; the K2 headless triad is already the right substrate), the
five dependency-ordered steps, every relevant file path, and the project
rules that bind the work.

Two things the handoff adds beyond relaying the research. First, a
changed-since section: three of the research's "gap" rows have closed —
vendor landed 2026-08-08, fellowship 2026-08-12, secure trade 2026-08-14 —
so step 4's substrate is materially stronger than when the plan was
written, and §3's gap table is the part that has aged. Second, every path
is verified against the live tree as of today rather than copied forward:
WorldEntitySnapshot is still exactly four fields, IPluginHost is unchanged,
there is still no enchantment-enumerating view and no point-goal movement
primitive, and IHeadlessBotPolicy is internal to AcDream.Headless so step 1
mirrors its shape rather than re-exporting the type.

All 30 path references were checked programmatically. Also records that
claude-memory/ is a junction that resolves in the main checkout but not
inside a worktree, which would otherwise read as a broken pointer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 15:50:58 +02:00

11 KiB
Raw Blame History

Handoff — VTank-class plugin automation milestone

Written 2026-08-20 for a fresh session picking this up cold.

You are inheriting a completed requirements-research phase and an unstarted implementation. Nothing has been built yet. The research is thorough and was done at xhigh effort against primary sources — read it before designing anything, and do not re-derive it. This document tells you where everything is, what has changed since the research was written, and what to do first.


1. Start here, in this order

# Path Why
1 docs/research/2026-07-29-vtank-plugin-automation-requirements.md The research. 384 lines. Full VTank capability inventory, the implied host-API surface, mapping to acdream, and the 5-step milestone.
2 docs/plans/2026-07-29-post-vulkan-work-intake.md Where the milestone is filed (C-bucket candidate), line 35.
3 claude-memory/project_plugin_requirement.md (see note below) Why plugins are a day-1 architectural constraint, not a nice-to-have.
4 CLAUDE.md § "Code Structure Rules" rule 3, and § "UI strategy" The binding constraints on this work (see §6 below).

Rows 12 are committed to the repo. Paths verified 2026-08-20.

claude-memory/ is a junction, not tracked content. It resolves in the main checkout (C:\Users\erikn\source\repos\acdream) but not inside a git worktree, and git ls-files claude-memory/ returns nothing. The files really live under C:\Users\erikn\.claude\projects\C--Users-erikn-source-repos-acdream\memory\. If you are working in a worktree and a claude-memory/... path does not resolve, that is why — read it from the main checkout or the real path.


2. The architectural conclusion — do not relitigate

VTank's meta state machine, expression language and loot-rule engine are plugin-land, not host-land. VTank itself was built on Decal's primitives; acdream ships the equivalent primitive layer and a VTank-like engine then becomes an acdream plugin — potentially file-compatible with .met / .nav / .utl, whose encodings the research already decodes.

The second conclusion: the K2 headless-bot triad is already the right substrate. Synchronous borrowed reads, generation-gated typed commands with attempt semantics, and an ordered delta stream are exactly what a VTank-class engine needs, and VTank's 293 ms meta tick maps cleanly onto Tick. So this milestone is largely a bridging and query-surface exercise, not new architecture.


3. The five steps (dependency-ordered)

  1. Plugin↔Runtime bridge — the enabler, gates everything else. Mirror the K2 triad into BCL-only Plugin.Abstractions: per-plugin Tick(view, commands), generation-gated command groups, ordered event observer. This upgrades plugins to headless-bot parity.
  2. Entity/property query surface. Names, classification, weenie type, physics position on entity snapshots; query verbs; per-object property bags in the retail key space; ID-request command + ID-arrived event.
  3. Spell/enchantment surface. Enumerable active enchantments (spell id, layer, seconds remaining), can-cast prediction, explicit cast-on-target, cast-outcome events.
  4. Interaction/transaction commands. use-by-id, apply-on, give, container take-specific, salvage, vendor buy/sell — over the existing one-transaction gate, with receipts as events.
  5. Nav/move-to layer. Point-goal movement with arrival/stuck/off-course events plus a server-confirmed-arrival variant, follow-entity, jump.

(1) gates all. (2) and (3) are independent once (1) lands. (5) is last and is the only genuinely new machinery — everything else is exposure of state that already exists Runtime-side.


4. What changed since the research was written

The research is dated 2026-07-29. Three weeks and several campaigns have landed since, and three of its "gap" rows have closed. Verified today:

Research said Reality on 2026-08-20
"vendor = M4 Slices 56 in flight" Landed, user-accepted 2026-08-08. RuntimeVendorRangeQuery, VendorShopItemMaterializer. The six-slice world-interaction program is COMPLETE.
"Fellowship state: not in Runtime views yet" Landed. Campaign FA code-complete 2026-08-12: RuntimeFellowshipState, RuntimeAllegianceState.
(not mentioned — postdates it) Secure trade shipped 2026-08-14: RuntimeTradeState.

Net effect: step 4's substrate is materially stronger than when the plan was written. Re-read §3 of the research against the live tree before scoping — its gap table is the one part that has aged.

Still true, verified today:

  • WorldEntitySnapshot is still exactly four fields — (uint Id, uint SourceId, Vector3 Position, Quaternion Rotation). The step-2 gap is real and unchanged.
  • IPluginHost still exposes only { HasUi, Log, State, Events, Selection, Ui }.
  • There is no enchantment-enumerating view; the state lives in RuntimeCharacterState / GameRuntimeGameplayViews.
  • There is no point-goal movement primitive. Movement is WASD-intent-shaped.

5. Every file you will need, verified 2026-08-20

The plugin API you are extending (BCL-only — see §6):

src/AcDream.Plugin.Abstractions/IPluginHost.cs          <- the surface to grow
src/AcDream.Plugin.Abstractions/IGameState.cs
src/AcDream.Plugin.Abstractions/IEvents.cs
src/AcDream.Plugin.Abstractions/ISelectionService.cs
src/AcDream.Plugin.Abstractions/IUiRegistry.cs          <- AddMarkupPanel; already a better-typed "Meta Views"
src/AcDream.Plugin.Abstractions/IAcDreamPlugin.cs
src/AcDream.Plugin.Abstractions/IPluginLogger.cs
src/AcDream.Plugin.Abstractions/WorldEntitySnapshot.cs  <- the 4-field snapshot to enrich

The Runtime surface you are mirroring (all three interfaces are public):

src/AcDream.Runtime/GameRuntimeViews.cs          :259  public interface IGameRuntimeView
src/AcDream.Runtime/GameRuntimeCommands.cs       :489  public interface IGameRuntimeCommands
src/AcDream.Runtime/GameRuntimeEvents.cs         :100  public interface IRuntimeEventObserver
src/AcDream.Runtime/GameRuntimeGameplayViews.cs        gameplay projections incl. enchantments

The pattern to copy — note IHeadlessBotPolicy is internal to AcDream.Headless, so you are mirroring the shape, not re-exporting the type:

src/AcDream.Headless/Policies/HeadlessBotPolicy.cs :8  internal interface IHeadlessBotPolicy
                                                   :12 void Tick(IGameRuntimeView, IGameRuntimeCommands)

Runtime gameplay state owners (what step 24 will expose):

src/AcDream.Runtime/Gameplay/RuntimeCharacterState.cs      vitals/skills/spellbook/enchantments
src/AcDream.Runtime/Gameplay/RuntimeInventoryState.cs
src/AcDream.Runtime/Gameplay/RuntimeActionState.cs         selection/combat/cast intent, transaction gate
src/AcDream.Runtime/Gameplay/RuntimeFellowshipState.cs     (new since research)
src/AcDream.Runtime/Gameplay/RuntimeAllegianceState.cs     (new since research)
src/AcDream.Runtime/Gameplay/RuntimeTradeState.cs          (new since research)
src/AcDream.Runtime/Gameplay/RuntimeVendorRangeQuery.cs
src/AcDream.Runtime/Gameplay/VendorShopItemMaterializer.cs

Plugin loading/hosting:

src/AcDream.Core/Plugins/PluginLoader.cs
src/AcDream.Core/Plugins/LoadedPlugin.cs
src/AcDream.Core/Plugins/PluginAssemblyLoadContext.cs
src/AcDream.Plugins.Smoke/SmokePlugin.cs                <- the worked example

Domain background (read on demand — junction, see the note in §1):

claude-memory/project_modern_runtime_architecture.md    Slice-J ownership truth
claude-memory/project_linux_headless_bots.md            Slice K; the BINDING #368 contract
claude-memory/project_interaction_pipeline.md           use / pickup / appraisal flow

6. Constraints that bind this work

  1. AcDream.Plugin.Abstractions is BCL-only. No App namespaces, no Runtime types leaking through, no third-party packages. Plugin gameplay UI goes through IUiRegistry.AddMarkupPanel and nothing else. This is what keeps plugins insulated from presentation churn — see CLAUDE.md rule 3.
  2. Hosts give Runtime ONE of everything — the BINDING #368 contract in claude-memory/project_linux_headless_bots.md. Read it before adding a second anything.
  3. Every C-bucket item gets a brainstormed spec before code — the intake doc's own sequencing note, and the roadmap rules in CLAUDE.md. Use superpowers:brainstorming, then superpowers:writing-plans.
  4. This is not the active milestone. M4 "Live in the world" is current. This is filed as a post-M4 C-bucket candidate. Confirm with the user that they want it started before doing anything beyond the spec — CLAUDE.md's one-active-milestone rule exists specifically to prevent this kind of drift.
  5. No workarounds without explicit approval, and any retail deviation introduced gets its row in docs/architecture/retail-divergence-register.md in the same commit.

7. First action

Read the research end to end, then re-verify its §3 gap table against the live tree (three rows are already stale — see §4). Then bring the user a brainstormed spec for step 1 only. Step 1 gates everything else, it is the smallest coherent slice, and getting the bridge shape wrong is the one mistake that would be expensive to undo.

Do not start with the nav layer, however tempting — it is step 5 for a reason. Route automation needs combat and loot reads to decide when to move.


8. Provenance

  • Research commit: 6077ce4d"docs: VTank requirements research — the plugin-automation milestone model", 2026-07-29, authored Fable 5, xhigh.
  • Originating session: local_dce33067-349e-45dd-916f-479bfae6cbc6, titled "graphics", branch claude/git-sync-status-5fb1d2, worktree peaceful-blackburn-5333f0. The misleading title is why it could not be found by search — the VTank research was one strand of a session about something else entirely.
  • Related sessions, if the VTank content is ever needed rather than the acdream plan: local_79a15007 (repos/metas — authoring VTank .af metaf scripts) and local_19297181 (dereth-workspace — code consuming ILootRuleProcessor / VirindiTank loot rules).
  • The research's own source list — Wayback wiki snapshots plus metaf, virindi-public-clone, ACE.BaseMod, vtank-routes, vtank-loot-profiles — is at the end of the research doc. The live virindi.net wiki is unreachable (self-signed TLS; the HTTP wiki returns a database error), so use the Wayback snapshots cited there rather than trying the live site.