merge(vt): slice 1c — metas/ and navs/ folders, no nav_ prefix (review-closed)
Owner decision 2026-09-07. Folder-scoped listing, one-time flat-file migration, content sanity on load. Narrow Opus review: MERGE-READY. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
commit
7cfe57827c
10 changed files with 707 additions and 170 deletions
|
|
@ -121,7 +121,7 @@ readiness/requeue adaptation. See
|
|||
| # | Divergence | Where (file:line) | Why it is safe / justified | Risk if assumption breaks | Retail oracle |
|
||||
|---|---|---|---|---|---|
|
||||
| AD-123 | **Filed 2026-09-07 at Campaign VT slice 1 Part A round 3 item 9.** Retail's real loot-profile picker (`aa()`, `uTank2/PluginCore.cs:7127-7154`) seeds ONLY `[None]` — there is no per-character auto loot file and no "mine only" filter for loot at all (`docs/research/vtank-kb/01-settings-and-profiles.md` section 3: "the loot default has no equivalent auto-name; loot profiles default to none"). MossTank keeps its own `ByCharacter`/"By char" auto-profile convention for loot anyway, for internal consistency with the Settings/Nav/Meta stores (all three of which DO have a real retail auto-file). | `src/AcDream.Plugins.MossTank/MossTankLootProfileStore.cs` (`ByCharacter`, `CurrentFileName`); `src/AcDream.Plugins.MossTank/VtankProfileDirectory.cs` (`ListLootProfiles`) | The auto file is a normal `.utl`, named the same `--Name_Server.utl` shape the other three auto-files use; a real VTank install never creates or reads this convention itself, so it is additive, not a collision with anything retail writes. | A user comparing acdream's loot picker to real VTank's own `cmbLootSet` sees an extra "By char" entry retail never shows, and (harmlessly) an extra `--Name_Server.utl` file in a shared real-VTank profile directory. | `aa()` (`uTank2/PluginCore.cs:7127-7154`). |
|
||||
| AD-122 | **Filed 2026-09-07 at Campaign VT slice 1 Part A round 3 item 7.** `VtankProfileDirectory.WriteCharacterBinding` writes a real `.cdf`'s Nav/Meta lines (4-5) as MossTank's own `.af` names (metaf's human-readable grammar), not VTank's native binary `.nav`/`.met`. When `ACDREAM_VTANK_PROFILE_DIR` points at a REAL installed VirindiTank profile folder for direct interop, the `.cdf` this store writes there names files a real VTank instance cannot load (it only reads `.nav`/`.met`). | `src/AcDream.Plugins.MossTank/VtankProfileDirectory.cs` (`WriteCharacterBinding`); `src/AcDream.Plugins.MossTank/MossTankMetaProfileStore.cs`/`MossTankRouteProfileStore.cs` (`.af` naming) | `.usd` settings and `.utl` loot stay real/binary-compatible; only Nav/Meta went `.af`-only for slice 1 (see `docs/research/vtank-kb/06-navigation-and-nav.md`/`07-meta-and-expressions.md`). acdream itself only ever reads its own `.cdf` writes back, so this is self-consistent as long as the two clients never share one profile directory. | A user pointing `ACDREAM_VTANK_PROFILE_DIR` at their real VTank install and then opening that character in real VTank gets a Nav/Meta load failure (wrong format for the recorded filename) even though Settings/Loot still work. | `da.q()`/`da.e()` (`refs/vtank/decompiled/da.cs:105-164`) — real VTank's own `.cdf` read/write. |
|
||||
| AD-122 | **Filed 2026-09-07 at Campaign VT slice 1 Part A round 3 item 7; naming updated 2026-09-07 at Campaign VT slice 1c.** `VtankProfileDirectory.WriteCharacterBinding` writes a real `.cdf`'s Nav/Meta lines (4-5) as MossTank's own `.af` names (metaf's human-readable grammar), not VTank's native binary `.nav`/`.met` — and, since slice 1c's two-folder layout (owner decision 2026-09-07: Meta and Nav profiles both use `.af` and are told apart by folder, not a file-name marker), those two lines are now the folder-relative real storage keys `metas/Name.af`/`navs/Name.af`, not a bare file name. When `ACDREAM_VTANK_PROFILE_DIR` points at a REAL installed VirindiTank profile folder for direct interop, the `.cdf` this store writes there names files a real VTank instance cannot load (wrong format, and — now — a subfolder path a real VTank's own flat-directory `.cdf` reader was never built to resolve). | `src/AcDream.Plugins.MossTank/VtankProfileDirectory.cs` (`WriteCharacterBinding`, `MetaFolder`/`NavFolder`); `src/AcDream.Plugins.MossTank/MossTankMetaProfileStore.cs`/`MossTankRouteProfileStore.cs` (`.af` naming, folder-qualified `CurrentFileName`) | `.usd` settings and `.utl` loot stay real/binary-compatible; only Nav/Meta went `.af`-only for slice 1 (see `docs/research/vtank-kb/06-navigation-and-nav.md`/`07-meta-and-expressions.md`). acdream itself only ever reads its own `.cdf` writes back, so this is self-consistent as long as the two clients never share one profile directory. | A user pointing `ACDREAM_VTANK_PROFILE_DIR` at their real VTank install and then opening that character in real VTank gets a Nav/Meta load failure (wrong format AND wrong path for the recorded filename) even though Settings/Loot still work. | `da.q()`/`da.e()` (`refs/vtank/decompiled/da.cs:105-164`) — real VTank's own `.cdf` read/write. |
|
||||
| AD-119 | **Filed 2026-09-03 at Campaign OVERHAUL v2 S4 chunk 1 (S4-c1 C2; `docs/research/2026-09-01-overhaul/s4-depth-alpha-packet.md` §6 R3).** Retail's portal-depth draws (`D3DPolyRender::DrawPortalPolyInternal` @0x0059bc90, the `BLEND_SRCALPHA`/`BLEND_INVSRCALPHA` `SetBlendFunction` call) keep color writes ENABLED with a zero-source-alpha `SRCALPHA`/`INVSRCALPHA` blend — every OTHER piece of R3's state (`DEPTHTEST_ALWAYS`, depth write on, `CULLMODE_NONE`, no stencil) is ported exactly. acdream instead disables the color-write mask outright on the SAME pipeline (`ColorWrite = false` alongside `Blend = GpuBlendMode.None`) and `portal_depth.frag`'s `main()` writes no color output at all — a write-mask substituting for a zero-alpha blend. | `src/AcDream.App/Rendering/PortalDepthMaskRenderer.Rhi.cs:92,100` (`CreatePortalPipeline`'s `Blend`/`ColorWrite` fields); `src/AcDream.App/Rendering/Shaders/portal_depth.frag` (empty `main()`, no color output) | Retail's blend equation is `dst' = src*srcAlpha + dst*(1-srcAlpha)`; with `srcAlpha` fixed at 0 this collapses to `dst' = dst` for every fragment regardless of its RGB — the destination color buffer is left byte-identical either way. A write mask reaches the SAME outcome (the destination is never touched) through a structurally simpler path — no blend-unit work per fragment, no fragment color output to author or keep in sync with a "must stay zero" alpha invariant — so the two are pixel-identical, not merely usually-equivalent. | None expected: the equivalence is provable from the blend algebra above, not measured, so no capture, transcript, or visual gate can distinguish the two. The write mask is in fact the SAFER of the two going forward — a future edit that gives `portal_depth.frag` a real color output (e.g. an authored debug tint) still writes nothing under today's mask, where a ported zero-alpha blend would depend on that same edit remembering to keep alpha at exactly 0. | `D3DPolyRender::DrawPortalPolyInternal` @0x0059bc90 (`SetBlendFunction(BLEND_SRCALPHA, BLEND_INVSRCALPHA, BLENDOP_ADD)`, `SetDepthBufferMode(DEPTHTEST_ALWAYS, ...)`, `SetCullMode(CULLMODE_NONE)`); `PortalDepthMaskRenderer.Rhi.cs` |
|
||||
| AD-120 | **Filed 2026-09-04 at the S4-c2 fix round 1 (M3).** Retail's `DrawMesh` row 1 immediate draw happens IN PLACE, inside the mesh draw call itself, the instant `curr_detail_surface != null` is observed for a translucent building-shell subset — there is no separate "later" point at which it could draw. acdream's walk stream-batches ORDINARY opaque instances into one deferred submission, so a translucent building-shell instance under building detail cannot draw "in place" in that same sense; `WbDrawDispatcher.SubmitToAlphaQueue`'s `RetailAlphaMeshAction.Immediate` branch instead draws it via `DrawImmediateAlphaInstance`/`DrawImmediateAlphaInstanceRhi` at the entity's own `AlphaSubmitMark` — the point `WalkFrameDriver.Replay` reaches that instance's alpha submission within the walk's existing turn order (after the entity's building/land-cell turn, same relative position an ordinary deferred instance would occupy). | `src/AcDream.App/Rendering/Wb/WbDrawDispatcher.cs` (`SubmitToAlphaQueue`, `DrawImmediateAlphaInstance`); `src/AcDream.App/Rendering/Wb/WbDrawDispatcher.Rhi.cs` (`DrawImmediateAlphaInstanceRhi`) | The walk's turn order already places a building's alpha-eligible instances at the correct relative position among that turn's other content (retail draws building shells within `DrawBuilding`, itself ordered exactly where the walk visits that building) — moving the draw from "mid-mesh-call" to "at the turn's alpha submission point" changes WHEN within one turn it executes, never WHICH turn, so it still lands between the same neighboring opaque/translucent content retail's own turn order would bracket it with. | A translucent building-shell instance under detail could theoretically composite differently than retail if some OTHER alpha content is submitted between the entity's own opaque stream mark and its alpha submission mark within the SAME turn — no such intervening content exists in the current walk (an entity's alpha submission immediately follows its own classification), so this is a structural note, not an observed symptom. | `D3DPolyRender::DrawMesh` @0x0059d4a0 (row 1); `RenderDeviceD3D::DrawBuilding` @0x0059f2a0 (`curr_detail_surface` install/clear) |
|
||||
| AD-121 | **Filed 2026-09-05 at #476 F1.** The opt-in retained Vulkan screenshot path requires the actual capture allocation to be host-coherent. CaptureBackbuffer rejects noncoherent memory with NotSupportedException before waiting or reading; it does not implement atom-safe isolated cache invalidation. | src/AcDream.App/Rendering/Gpu/Vk/VulkanGpuDevice.Resources.cs (RecordBackbufferCapture, CaptureBackbuffer); VulkanBackbufferCaptureValidityTests | After the copy, COPY/TRANSFER_WRITE to HOST/HOST_READ publishes the exact capture range; the existing DeviceWaitIdle supplies completion. A capture-local coherence check avoids stale mapped bytes without changing shared heap preferences, generic buffer reads or neighboring suballocations. Default capture-off gameplay is unchanged. | A device whose capture allocation is only host-visible cannot take these opt-in screenshots until a separately bounded isolated invalidation path exists. Failure is explicit; no successful PNG is fabricated. This is a diagnostic capability restriction, not a retail equivalence claim. | Device::GetScreenshotSurface00439160 and RenderDeviceD3D::GenerateSurfaceFromFrontBuffer005A0210 capture completed retail front-buffer contents; #476 paired proof is in476-capture-lifetime-diagnosis.md. Vulkan host visibility/completion requirements are in476-fix-round1-host-visibility.md. |
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ $env:ACDREAM_FRAME_HISTORY = "$scratch\frames.csv"
|
|||
| `ACDREAM_VULKAN_FORCE_UNSUPPORTED` | `=<feature-name>` (case-insensitive property name, e.g. `MultiDrawIndirect`) | Test knob (Slice V5): clears one named required Vulkan feature from the capability record to synthetically fail the gate, so the `NotSupportedException` → exit-code-4 → report path can be exercised on hardware that actually supports everything. | Deliberately breaks Vulkan startup when set to a matched feature name — this is a "make it fail on purpose" gate-testing flag, never appropriate for a normal or measurement run. | `null` → real capabilities used unmodified | `RuntimeOptions.VulkanForcedUnsupportedFeature` → `VulkanCapabilityRecord.Without` (`VulkanCapabilityRecord.cs:113-119`), consumed at `VulkanGraphicsContext.cs:339` |
|
||||
| `ACDREAM_VULKAN_PROBE` | `=1` | Runs the standalone Vulkan capability-probe/bring-up harness (opens its own window, runs the capability gate, presents synthetic V6c/V6d verification scenes, captures one screenshot) **instead of** the real client composition host, then exits. | This flag ALONE gates entry (`GameWindow.cs:828`); the former `ACDREAM_RENDER_BACKEND=vulkan` co-requisite died with the OpenGL backend (its class doc was corrected 2026-08-24). | `false` → normal composition host | `RuntimeOptions.VulkanCapabilityProbe` → `GameWindow.cs:828` → `VulkanBringUpHost` |
|
||||
| `ACDREAM_VULKAN_PROBE_FRAMES` | `=<int>` (non-negative) | Bounds the bring-up probe harness to N presented frames so it can run unattended in CI, instead of presenting until a human closes the window. | The frame budget never cuts a pending screenshot capture short — the loop stays open until the screenshot has been attempted even past the budget, so an unattended run's whole product (a PNG) is guaranteed. Zero (unset/unparseable/explicit `0`) keeps the interactive wait-for-close behavior. | `0` → interactive (wait for window close) | `RuntimeOptions.VulkanCapabilityProbeFrames` → `VulkanBringUpHost.cs:141-249` |
|
||||
| `ACDREAM_VTANK_PROFILE_DIR` | `=<path>` | Overrides the directory `IPluginHost.VtankProfiles` (a VTank-compatible plugin's real `.usd`/`.ast`/`.af` profile storage — see `AcDream.Plugins.MossTank.VtankProfileDirectory`) is rooted at, composed as a `FilePluginStorage`. Set it to a real installed VTank's own profile folder (e.g. `C:\Games\VirindiPlugins\VirindiTank`) for direct interop. | Redirects only that one plugin-storage root; no other startup behavior changes. An unset/empty-string value is treated as "no override" (`NullIfEmpty`); whitespace-only is NOT special-cased (matches every other `NullIfEmpty`-read flag, e.g. `ACDREAM_AC_DIR`/`ACDREAM_UI_PROBE_SCRIPT`) and would be used as a literal (almost certainly invalid) root. **Warning:** MossTank's own `.cdf` writes name its Nav/Meta profiles with the `.af` (metaf text) extension, not real VTank's native binary `.nav`/`.met` — pointed at a real installed VTank folder, that same character's Nav/Meta profiles become unloadable by the real VTank client sharing the directory (Settings `.usd` and Loot `.utl` stay real/binary-compatible; see register row AD-122). | unset → `<ApplicationPathSet.DataDirectory>/vtank` | `RuntimeOptions.VtankProfileDirectoryOverride` → `Program.cs` (composes `AppPluginHost`'s `vtankProfiles` argument). The Headless host has no equivalent override (its path overrides are `HeadlessPathOverrides`, not env vars) and always uses `HeadlessPathSet.VtankProfilesDirectory` (`<DataDirectory>/vtank`). |
|
||||
| `ACDREAM_VTANK_PROFILE_DIR` | `=<path>` | Overrides the directory `IPluginHost.VtankProfiles` (a VTank-compatible plugin's real `.usd`/`.ast`/`.af` profile storage — see `AcDream.Plugins.MossTank.VtankProfileDirectory`) is rooted at, composed as a `FilePluginStorage`. Set it to a real installed VTank's own profile folder (e.g. `C:\Games\VirindiPlugins\VirindiTank`) for direct interop. | Redirects only that one plugin-storage root; no other startup behavior changes. An unset/empty-string value is treated as "no override" (`NullIfEmpty`); whitespace-only is NOT special-cased (matches every other `NullIfEmpty`-read flag, e.g. `ACDREAM_AC_DIR`/`ACDREAM_UI_PROBE_SCRIPT`) and would be used as a literal (almost certainly invalid) root. **Warning:** MossTank writes Nav/Meta profiles under two dedicated subfolders of this directory — `metas/` for `MossTankMetaProfileStore`, `navs/` for `MossTankRouteProfileStore`, owner decision 2026-09-07 (Campaign VT slice 1c) — and its `.cdf` names them with the `.af` (metaf text) extension, not real VTank's native binary `.nav`/`.met`, at those folder-relative paths. Pointed at a real installed VTank folder, that same character's Nav/Meta profiles become unloadable by the real VTank client sharing the directory (wrong format, wrong subfolder — Settings `.usd` and Loot `.utl` stay real/binary-compatible, flat at the directory root; see register row AD-122). | unset → `<ApplicationPathSet.DataDirectory>/vtank` | `RuntimeOptions.VtankProfileDirectoryOverride` → `Program.cs` (composes `AppPluginHost`'s `vtankProfiles` argument). The Headless host has no equivalent override (its path overrides are `HeadlessPathOverrides`, not env vars) and always uses `HeadlessPathSet.VtankProfilesDirectory` (`<DataDirectory>/vtank`). |
|
||||
| `ACDREAM_DUMP_MOVE_TRUTH` | `=1` | Emits one `move-truth OUT` line per outbound movement record (MoveToState / AutonomousPosition): local resolved position vs the wire position/cell, ground contact, velocity (`MovementTruthDiagnosticController`). | **Automation apparatus, NOT a spent probe** — the canonical nine-stop soak (`tools/run-connected-r6-soak.ps1`) hard-gates on ≥2 of these lines per destination as its proof that production input produced outbound movement traffic; deleting it fails the soak at every stop (#437, deleted-and-restored 2026-08-24). Print volume follows the outbound send cadence. | off | `RuntimeOptions.DumpMoveTruth` → `GameWindow.cs` → `MovementTruthDiagnosticController` |
|
||||
|
||||
## Permanent diagnostics
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue