fix(vt): C separate exports/meta/ and exports/nav/ .af directories

Item C (slice-1 fix round). MossTankMetaProfileStore and
MossTankRouteProfileStore both wrote their .af exports into the same
flat "exports/" directory keyed only by profile name — a Meta profile
and a route (Navigation) profile sharing a name (e.g. both named
"Same") would silently clobber each other's .af file on save, with no
error and no warning.

- MossTankMetaProfileStore.WriteLegacyExport now writes to
  "exports/meta/{name}.af".
- MossTankRouteProfileStore.WriteLegacyExport now writes to
  "exports/nav/{name}.af".
- Both class docs updated to name the collision this avoids and point at
  the sibling store's subdirectory.
- MossTankPanelTests: existing NavCommandsImportAndExportExactVtankNavFiles
  and MetaCommandsImportAndExportExactVtankMetFiles updated to the new
  paths. New MetaAndRouteExportsWithTheSameNameDoNotCollide saves a Meta
  and a route profile both named "Same" and asserts both .af files exist
  with their own correct content — verified failing before the fix
  (asserted false on the meta file's existence once both paths were
  reverted to the flat "exports/" root, confirming the collision is real
  and this test catches it).

Full MossTank suite: 569/569 passing (568 -> 569, one new test).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-09-06 22:26:17 +02:00
parent e5bc5c6a3f
commit d0247dbb19
3 changed files with 49 additions and 7 deletions

View file

@ -195,7 +195,12 @@ internal sealed class MossTankMetaProfileStore
/// <c>.af</c> is the only VTank-compatible export format now (Campaign
/// VT slice 1 Part A — MossTank no longer authors the binary
/// <c>.met</c> format at all, matching <see cref="VtankMetaProfileSerializer"/>'s
/// demotion to a one-shot import).
/// demotion to a one-shot import). Exports live under
/// <c>exports/meta/</c> — a distinct subdirectory from
/// <see cref="MossTankRouteProfileStore"/>'s <c>exports/nav/</c> — so a
/// Meta profile and a route (Navigation) profile sharing the same name
/// cannot silently overwrite each other's <c>.af</c> file (both stores
/// used to write into the same flat <c>exports/</c> root).
/// </summary>
private void WriteLegacyExport(string name, MetaProfile profile)
{
@ -204,7 +209,7 @@ internal sealed class MossTankMetaProfileStore
try
{
_host.Storage.WriteText(
$"exports/{LegacyFileName(name)}.af",
$"exports/meta/{LegacyFileName(name)}.af",
MetafSerializer.SaveMeta(profile));
}
catch (Exception error)

View file

@ -264,7 +264,12 @@ internal sealed class MossTankRouteProfileStore
/// <c>.af</c> is the only VTank-compatible export format now (Campaign
/// VT slice 1 Part A — MossTank no longer authors the binary
/// <c>.nav</c> format at all, matching <see cref="VtankNavRouteSerializer"/>'s
/// demotion to a one-shot import).
/// demotion to a one-shot import). Exports live under
/// <c>exports/nav/</c> — a distinct subdirectory from
/// <see cref="MossTankMetaProfileStore"/>'s <c>exports/meta/</c> — so a
/// route (Navigation) profile and a Meta profile sharing the same name
/// cannot silently overwrite each other's <c>.af</c> file (both stores
/// used to write into the same flat <c>exports/</c> root).
/// </summary>
private void WriteLegacyExport(string name, NavigationSettings settings)
{
@ -273,7 +278,7 @@ internal sealed class MossTankRouteProfileStore
try
{
_host.Storage.WriteText(
$"exports/{LegacyFileName(name)}.af",
$"exports/nav/{LegacyFileName(name)}.af",
MetafSerializer.SaveNav(settings));
}
catch (Exception error)