<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>V-Sekai Fire — Manuals</title>
<link>https://v-sekai-fire.github.io/manuals/decisions.html</link>
<atom:link href="https://v-sekai-fire.github.io/manuals/decisions.xml" rel="self" type="application/rss+xml"/>
<description></description>
<generator>quarto-1.9.37</generator>
<lastBuildDate>Wed, 06 May 2026 00:00:00 GMT</lastBuildDate>
<item>
  <title>Replace Jaeger with VictoriaTraces for trace storage</title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-observability-stack-victoriatraces.html</link>
  <description><![CDATA[ 





<section id="context" class="level2">
<h2 class="anchored" data-anchor-id="context">Context</h2>
<p>Jaeger all-in-one with Badger storage was chosen as the Apache 2.0 replacement for Tempo. VictoriaMetrics ships VictoriaTraces — an Apache 2.0 trace backend that accepts OTLP directly. VictoriaMetrics benchmarks report 3.7× less RAM and 2.6× less CPU vs Tempo.</p>
<p>Using VictoriaTraces puts all three storage backends (metrics, logs, traces) under the same vendor, drops Badger’s single-node limit, and matches the port and CLI-flag conventions already in use.</p>
</section>
<section id="decision" class="level2">
<h2 class="anchored" data-anchor-id="decision">Decision</h2>
<p>Replace Jaeger all-in-one with VictoriaTraces in the single-machine observability stack.</p>
<ul>
<li>VictoriaTraces listens on 10428 (HTTP, UI + query + OTLP HTTP ingest).</li>
<li>OTEL Collector exports traces via <code>otlphttp/traces</code> to <code>http://localhost:10428/insert/opentelemetry</code>.</li>
<li>Data persists at <code>/var/lib/victoriatraces</code> on the shared Fly volume.</li>
<li>Jaeger is removed entirely; no separate query UI process is needed.</li>
</ul>
<p>Port map after this change:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 21%">
<col style="width: 33%">
<col style="width: 45%">
</colgroup>
<thead>
<tr class="header">
<th>Service</th>
<th>Port</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>VictoriaMetrics</td>
<td>8428</td>
<td>Metrics storage and PromQL</td>
</tr>
<tr class="even">
<td>VictoriaLogs</td>
<td>9428</td>
<td>Log storage and query</td>
</tr>
<tr class="odd">
<td>VictoriaTraces</td>
<td>10428</td>
<td>Trace storage and query</td>
</tr>
<tr class="even">
<td>OTEL Collector</td>
<td>4317 (gRPC), 4318 (HTTP)</td>
<td>OTLP ingest, routes to the above</td>
</tr>
</tbody>
</table>
</section>
<section id="consequences" class="level2">
<h2 class="anchored" data-anchor-id="consequences">Consequences</h2>
<ul>
<li>All four services are now Apache 2.0; the three storage backends are from VictoriaMetrics.</li>
<li>VictoriaTraces query UI is at <code>http://...:10428/select/vmui</code>.</li>
<li><code>fly proxy 10428:10428</code> replaces the former <code>fly proxy 16686:16686</code> for trace inspection.</li>
<li>No explicit trace TTL is configured; add <code>-retentionPeriod</code> if disk pressure becomes a concern.</li>
</ul>


</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-observability-stack-victoriatraces.html</guid>
  <pubDate>Wed, 06 May 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Observability stack with VictoriaMetrics, VictoriaLogs, and Tempo</title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-observability-stack-victoriametrics-tempo.html</link>
  <description><![CDATA[ 





<section id="context" class="level2">
<h2 class="anchored" data-anchor-id="context">Context</h2>
<p>The stack needs metrics, logs, and traces. Options considered: Grafana Cloud (cost), self-hosted Prometheus+Loki+Tempo (three separate apps), or a compact single-machine stack.</p>
</section>
<section id="decision" class="level2">
<h2 class="anchored" data-anchor-id="decision">Decision</h2>
<p>Run VictoriaMetrics (metrics), VictoriaLogs (logs), and Grafana Tempo (traces) under supervisord in a single Fly Machine, with an OpenTelemetry Collector as the ingest router.</p>
<ul>
<li>OTEL Collector listens on 4317 (gRPC) and 4318 (HTTP) on the private network.</li>
<li>Collector routes: metrics -&gt; VictoriaMetrics (8428 via Prometheus remote write), logs -&gt; VictoriaLogs (9428 OTLP), traces -&gt; Tempo (5317 OTLP internal).</li>
<li>Data persists on a 10 GB Fly volume.</li>
</ul>
</section>
<section id="consequences" class="level2">
<h2 class="anchored" data-anchor-id="consequences">Consequences</h2>
<ul>
<li>OTLP ports must not be exposed publicly — they accept unauthenticated writes.</li>
<li>Other Fly apps send telemetry to <code>multiplayer-fabric-observability.internal:4317</code> or <code>:4318</code>.</li>
<li>Grafana Tempo v3 config changed significantly from v2: <code>ingester</code> and <code>compactor</code> top-level keys were removed; <code>-target=all</code> flag is required to run all components.</li>
<li>See <a href="../decisions/20260506-ghcr-package-ownership-same-repo.html">GHCR package ownership decision</a> for why the zone binary image was renamed and moved to <code>multiplayer-fabric-zone</code>.</li>
</ul>


</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-observability-stack-victoriametrics-tempo.html</guid>
  <pubDate>Wed, 06 May 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Observability stack with VictoriaMetrics, VictoriaLogs, and Jaeger</title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-observability-stack-victoriametrics-jaeger.html</link>
  <description><![CDATA[ 





<section id="context" class="level2">
<h2 class="anchored" data-anchor-id="context">Context</h2>
<p>Grafana Tempo was chosen for trace storage in the initial stack but is licensed under AGPL-3.0, which requires any service modifications to be open-sourced. Jaeger (Apache 2.0, CNCF graduated) fits the permissive-license constraint: it is OTLP-native since v1.35 and commonly deployed alongside VictoriaMetrics.</p>
</section>
<section id="decision" class="level2">
<h2 class="anchored" data-anchor-id="decision">Decision</h2>
<p>Replace Grafana Tempo with Jaeger all-in-one in the single-machine observability stack.</p>
<ul>
<li>Jaeger listens on 14317 (OTLP gRPC, internal) and exposes its UI on 16686.</li>
<li>OTEL Collector routes traces to <code>localhost:14317</code> instead of the former Tempo port (5317).</li>
<li>Jaeger uses Badger embedded storage (<code>/var/lib/jaeger/data</code> and <code>/var/lib/jaeger/keys</code>) persisted on the same 10 GB Fly volume.</li>
<li><code>tempo-config.yaml</code> is deleted; Jaeger is configured entirely via CLI flags in <code>supervisord.conf</code>.</li>
</ul>
<p>Port map after this change:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 21%">
<col style="width: 33%">
<col style="width: 45%">
</colgroup>
<thead>
<tr class="header">
<th>Service</th>
<th>Port</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>VictoriaMetrics</td>
<td>8428</td>
<td>Metrics storage and PromQL</td>
</tr>
<tr class="even">
<td>VictoriaLogs</td>
<td>9428</td>
<td>Log storage and query</td>
</tr>
<tr class="odd">
<td>Jaeger UI</td>
<td>16686</td>
<td>Trace storage and query</td>
</tr>
<tr class="even">
<td>OTEL Collector</td>
<td>4317 (gRPC), 4318 (HTTP)</td>
<td>OTLP ingest, routes to the above</td>
</tr>
</tbody>
</table>
</section>
<section id="consequences" class="level2">
<h2 class="anchored" data-anchor-id="consequences">Consequences</h2>
<ul>
<li>Jaeger UI replaces the Tempo query endpoint: <code>fly proxy 16686:16686</code> instead of <code>fly proxy 3200:3200</code>.</li>
<li>Badger is ephemeral-safe only with <code>--badger.ephemeral=false</code>; this flag must be set or traces are lost on restart.</li>
<li>No explicit trace TTL is configured; traces accumulate until disk pressure. Add <code>--badger.span-store-ttl</code> if retention limits are needed.</li>
<li>Jaeger’s Badger backend does not support distributed mode; acceptable for a single-machine stack.</li>
</ul>


</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-observability-stack-victoriametrics-jaeger.html</guid>
  <pubDate>Wed, 06 May 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>GHCR packages must be built by the repo that consumes them</title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-ghcr-package-ownership-same-repo.html</link>
  <description><![CDATA[ 





<section id="context" class="level2">
<h2 class="anchored" data-anchor-id="context">Context</h2>
<p>The zone server binary was built by <code>multiplayer-fabric-baker</code> and pushed to <code>ghcr.io/v-sekai-fire/godot-zone-double</code>. The zone deploy workflow (in <code>multiplayer-fabric-zone</code>) used <code>--local-only</code> with <code>docker/login-action</code> to pull that image, but received 403 Forbidden.</p>
<p>GitHub Container Registry ties package write access to the repository whose <code>GITHUB_TOKEN</code> created it. The zone repo’s token could not push to a package owned by the baker repo, and could not pull a private package owned by another repo without package-scoped access.</p>
</section>
<section id="decision" class="level2">
<h2 class="anchored" data-anchor-id="decision">Decision</h2>
<p>Each repository builds and publishes the GHCR images it directly uses in its own deploy:</p>
<ul>
<li><code>multiplayer-fabric-baker</code> builds and owns <code>godot-editor-double</code>.</li>
<li><code>multiplayer-fabric-zone</code> builds and owns <code>multiplayer-fabric-zone-godot</code> (renamed from <code>godot-zone-double</code> to reflect ownership).</li>
</ul>
<p><code>workflow_run</code> triggers only fire within the same repository, so the zone binary build workflow must live in the zone repo for the deploy to auto-trigger after a successful build.</p>
</section>
<section id="consequences" class="level2">
<h2 class="anchored" data-anchor-id="consequences">Consequences</h2>
<ul>
<li>Package names must reflect the owning repo to avoid confusion.</li>
<li>Moving a package between repos requires deleting it (needs <code>delete:packages</code> API scope) and rebuilding, or renaming.</li>
<li>Cross-repo GHCR access requires either a PAT with <code>read:packages</code> scope or making the package public.</li>
</ul>


</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-ghcr-package-ownership-same-repo.html</guid>
  <pubDate>Wed, 06 May 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Use WebTransport over QUIC for game traffic</title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260501-webtransport-over-quic-for-game-traffic.html</link>
  <description><![CDATA[ 





<section id="context" class="level2">
<h2 class="anchored" data-anchor-id="context">Context</h2>
<p>The zone server needs low-latency bidirectional communication between clients and the Godot game server. HTTP/1.1 and WebSocket both run over TCP, which head-of-line blocks on packet loss and degrades real-time game state.</p>
</section>
<section id="decision" class="level2">
<h2 class="anchored" data-anchor-id="decision">Decision</h2>
<p>Use WebTransport (HTTP/3 over QUIC) for all game traffic. Clients connect to the Elixir gateway on UDP port 443, which proxies into the Godot zone server on UDP port 7443.</p>
</section>
<section id="consequences" class="level2">
<h2 class="anchored" data-anchor-id="consequences">Consequences</h2>
<ul>
<li>UDP eliminates TCP head-of-line blocking.</li>
<li>Fly.io passes UDP without DNAT, so the app must bind to the same port clients connect to.</li>
<li>Port 443 requires running as root (or CAP_NET_BIND_SERVICE). The gateway container runs as root.</li>
<li>Datagrams are used for game state messages. Streams are avoided for ping/pong to sidestep stream half-close deadlock (client must close write side before server response fires).</li>
<li>Cloudflare’s proxy cannot forward QUIC/UDP. All game-traffic DNS records must be DNS-only (no proxy).</li>
</ul>


</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260501-webtransport-over-quic-for-game-traffic.html</guid>
  <pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Godot double precision template_release for zone servers</title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260501-godot-double-precision-template-release-for-zone.html</link>
  <description><![CDATA[ 





<section id="context" class="level2">
<h2 class="anchored" data-anchor-id="context">Context</h2>
<p>Zone servers run the game simulation headlessly. Two Godot build targets are candidates: <code>editor</code> (includes import tools) and <code>template_release</code> (runtime only). Precision must match the rest of the V-Sekai stack.</p>
</section>
<section id="decision" class="level2">
<h2 class="anchored" data-anchor-id="decision">Decision</h2>
<p>Build zone server binaries as <code>target=template_release precision=double</code> with no Mono. Build from the V-Sekai fork at <code>V-Sekai-fire/multiplayer-fabric-build@b27142e94</code>.</p>
</section>
<section id="consequences" class="level2">
<h2 class="anchored" data-anchor-id="consequences">Consequences</h2>
<ul>
<li><code>template_release</code> has no import or export tools, making it smaller and faster to start.</li>
<li><code>libstdc++-static</code> must be included in the AlmaLinux 9 build environment because <code>template_release</code> links libstdc++ statically.</li>
<li>The binary filename is <code>godot.linuxbsd.template_release.double.x86_64</code>.</li>
<li><code>--headless</code> flag is required at runtime.</li>
<li>Double precision matches the physics and networking precision of the rest of the stack.</li>
</ul>


</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260501-godot-double-precision-template-release-for-zone.html</guid>
  <pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Fly.io for deployment</title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260501-fly-io-for-deployment.html</link>
  <description><![CDATA[ 





<section id="context" class="level2">
<h2 class="anchored" data-anchor-id="context">Context</h2>
<p>The stack requires a platform that supports UDP (for QUIC/WebTransport), private networking between services, persistent volumes, and on-demand machines for job workloads (asset baking).</p>
</section>
<section id="decision" class="level2">
<h2 class="anchored" data-anchor-id="decision">Decision</h2>
<p>Deploy all services on Fly.io in the <code>iad</code> (Ashburn, Virginia) region.</p>
<ul>
<li>Machines handle deployment; Terraform (fly-apps/fly provider v0.0.21) manages resources (apps, IPs, volumes, secrets) but not machines, due to Machines API limitations in the provider.</li>
<li>Private networking uses Fly’s 6PN (WireGuard mesh). All <code>.internal</code> DNS resolves to IPv6 only, requiring <code>socket_options: [:inet6]</code> in any Erlang/Elixir TCP stack.</li>
<li>Dedicated IPv4 is required for UDP. Fly passes UDP without DNAT; the app must bind to the same port clients connect to.</li>
<li>On-demand machines (Fly Machines API) are used for the baker — one machine per bake job, exits when done.</li>
</ul>
</section>
<section id="consequences" class="level2">
<h2 class="anchored" data-anchor-id="consequences">Consequences</h2>
<ul>
<li>All services must be in the same region to communicate over the private network without egress charges.</li>
<li><code>.flycast</code> requires <code>[[services]]</code> on the target app; <code>.internal</code> works without it.</li>
<li>Cloudflare proxy must be disabled for UDP/QUIC endpoints; DNS-only records point directly to the Fly IP.</li>
<li>Terraform state is stored on a <code>tfstate</code> orphan branch in the infra repo to avoid requiring a remote backend.</li>
</ul>


</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260501-fly-io-for-deployment.html</guid>
  <pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>CockroachDB with mTLS and role-separated access</title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260501-cockroachdb-with-mtls-role-separation.html</link>
  <description><![CDATA[ 





<section id="context" class="level2">
<h2 class="anchored" data-anchor-id="context">Context</h2>
<p>The stack needs a relational database reachable by the Elixir gateway and the Phoenix zone backend. It must support schema migrations (DDL) separately from application queries (DML) to limit blast radius if application credentials are compromised.</p>
</section>
<section id="decision" class="level2">
<h2 class="anchored" data-anchor-id="decision">Decision</h2>
<p>Run a single-node CockroachDB on Fly.io with mTLS for all connections and three application roles:</p>
<ul>
<li><code>gateway_admin</code> — DDL access for Ecto migrations</li>
<li><code>gateway_writer</code> — DML access for the running application</li>
<li><code>gateway_reader</code> — read-only access</li>
</ul>
<p>Certs are generated by <code>gen_crdb_certs.sh</code> with 100-year validity and stored as Fly secrets. The node cert must include both <code>serverAuth</code> and <code>clientAuth</code> in <code>extendedKeyUsage</code> because CockroachDB uses the node cert for internal gRPC client authentication.</p>
</section>
<section id="consequences" class="level2">
<h2 class="anchored" data-anchor-id="consequences">Consequences</h2>
<ul>
<li><code>--advertise-addr</code> must be <code>localhost</code>. A flycast address routes the internal gRPC loopback through Fly’s NAT, breaking the admin UI.</li>
<li><code>prepare: :unnamed</code> is required in Postgrex to avoid statement-cache OOM on single-node deployments.</li>
<li>Port 26257 is never publicly exposed. Access is via Fly’s private network (6PN) using <code>socket_options: [:inet6]</code> in Ecto, because <code>.internal</code> DNS returns only AAAA records.</li>
<li>The <code>root</code> cert is provisioned on the CRDB machine only. <code>gateway_admin</code> is the highest-privilege cert available to the application.</li>
</ul>


</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260501-cockroachdb-with-mtls-role-separation.html</guid>
  <pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title></title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/present-proposal-template.html</link>
  <description><![CDATA[ 





<section id="proposal-title" class="level1">
<h1>[Proposal Title]</h1>
<section id="the-context" class="level2">
<h2 class="anchored" data-anchor-id="the-context">The Context</h2>
<p>Describe the circumstances that led to this proposal. Give enough background that someone unfamiliar with the area can understand why the work matters. State what you were trying to accomplish, not what solution you reached for first.</p>
</section>
<section id="the-problem-statement" class="level2">
<h2 class="anchored" data-anchor-id="the-problem-statement">The Problem Statement</h2>
<p>State the specific problem, limitation, or gap being addressed. Be concrete. A reader should be able to confirm whether a proposed solution actually solves it.</p>
</section>
<section id="design" class="level2">
<h2 class="anchored" data-anchor-id="design">Design</h2>
<p>Detail the proposed solution precisely enough that it could be implemented without improvising the design. Include code, diagrams, or examples where they reduce ambiguity. Vague or underspecified proposals cannot be acted on.</p>
</section>
<section id="cris-score" class="level2">
<h2 class="anchored" data-anchor-id="cris-score">CRIS Score</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 12%">
<col style="width: 4%">
<col style="width: 83%">
</colgroup>
<thead>
<tr class="header">
<th>Factor</th>
<th>Score</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C</strong>omplexity</td>
<td>0–10</td>
<td>[10 = simple, well-understood; 0 = novel or high-risk — why]</td>
</tr>
<tr class="even">
<td><strong>R</strong>each</td>
<td>0–10</td>
<td>[10 = affects everyone; 0 = affects almost no one — why]</td>
</tr>
<tr class="odd">
<td><strong>I</strong>mpediment</td>
<td>0–10</td>
<td>[10 = total blocker with no workaround; 0 = trivial to work around — why]</td>
</tr>
<tr class="even">
<td><strong>S</strong>takeholder</td>
<td>0–10</td>
<td>[10 = critical dependency for a major project; 0 = no project depends on it — why]</td>
</tr>
<tr class="odd">
<td><strong>Total</strong></td>
<td></td>
<td>[Average of four factors (0–10); 8–10 = build now, 6–8 = schedule soon, 4–6 = evaluate, 0–4 = defer]</td>
</tr>
</tbody>
</table>
</section>
<section id="the-downsides" class="level2">
<h2 class="anchored" data-anchor-id="the-downsides">The Downsides</h2>
<p>Describe the costs, risks, or trade-offs. Every proposal has them.</p>
</section>
<section id="the-road-not-taken" class="level2">
<h2 class="anchored" data-anchor-id="the-road-not-taken">The Road Not Taken</h2>
<p>Describe the alternatives considered and why this approach was chosen over them.</p>
</section>
<section id="status" class="level2">
<h2 class="anchored" data-anchor-id="status">Status</h2>
<p>Status: Draft <!-- Draft | Proposed | Rejected | Accepted | Deprecated | Superseded by [Link/Reference] --></p>
</section>
<section id="decision-makers" class="level2">
<h2 class="anchored" data-anchor-id="decision-makers">Decision Makers</h2>
<ul>
<li>[Name or role]</li>
</ul>
</section>
<section id="tags" class="level2">
<h2 class="anchored" data-anchor-id="tags">Tags</h2>
<ul>
<li>[relevant-tag-1], [relevant-tag-2], YYYYMMDD-this-filename-without-extension, present-proposal-template</li>
</ul>
<!-- Always include the filename (without .md) as the last tag.
     This makes the document findable by filename from any grep or
     code-search tool, the same way Godot Engine source files are
     cross-referenced by their basename. -->
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<!-- Written in Bibtex format -->
<pre><code>@misc{v_sekai_2026,
  title = {V-Sekai},
  year  = {2026},
  url   = {https://v-sekai.org/}
}</code></pre>


</section>
</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/present-proposal-template.html</guid>
  <pubDate>Thu, 07 May 2026 13:27:28 GMT</pubDate>
</item>
<item>
  <title></title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-intercept-smoke-test.html</link>
  <description><![CDATA[ 





<section id="maglev-intercept-cross-platform-tilt-shift-smoke-test" class="level1">
<h1>Maglev Intercept: Cross-Platform Tilt-Shift Smoke Test</h1>
<section id="the-context" class="level2">
<h2 class="anchored" data-anchor-id="the-context">The Context</h2>
<p>The stack: <code>multiplayer-fabric-gateway</code> (Elixir, UDP 443 → zone UDP 7443, WebTransport/QUIC datagrams), <code>multiplayer-fabric-zone</code> (headless Godot <code>template_release double</code>), <code>multiplayer-fabric-uro</code> (Phoenix shard registry and asset API), single-node CockroachDB on Fly’s 6PN private network.</p>
<p>Zone authority is geometric — <code>ZoneRange.contains(hilbert3D(pos))</code> determines ownership, gossip-learned, with uniqueness proven under <code>DisjointRanges</code>. Scores and persistent player state sit in a reserved logical partition of the 30-bit Hilbert space (the persona partition), governed by the same invariant as spatial zones. This is the first attempt to load all four layers together under cross-platform input.</p>
</section>
<section id="the-problem-statement" class="level2">
<h2 class="anchored" data-anchor-id="the-problem-statement">The Problem Statement</h2>
<p>The full scenario — cross-platform clients, authoritative rolling-core physics, and a causal cross-zone score commit — is too complex to build and validate in one pass. A system assembled from untested parts at full complexity has no debuggable baseline.</p>
</section>
<section id="design" class="level2">
<h2 class="anchored" data-anchor-id="design">Design</h2>
<p>Players start mid-breach on a moving Maglev Data-Courier train, fight drones, retrieve Quantum Data-Cores rolling across the banking floor, and slot them into the mainframe terminal within 3 minutes. The PCVR client sees the car as a waist-height diorama; the Steam Deck client sees the same instance as an isometric action-RPG.</p>
<p>Each layer is a separate cycle — a working system and a gate before the next begins.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Cycle</th>
<th>C</th>
<th>What it proves</th>
<th>Depends on</th>
<th>Document</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>8</td>
<td>Terraform applies Fly.io resources; all apps, IPs, volumes, and secrets present</td>
<td>—</td>
<td><a href="../decisions/20260506-maglev-cycle-0-infra.html">cycle-0</a></td>
</tr>
<tr class="even">
<td>1</td>
<td>6</td>
<td>Gateway + zone handshake; one Godot datagram end-to-end</td>
<td>0</td>
<td><a href="../decisions/20260506-maglev-cycle-1-gateway-handshake.html">cycle-1</a></td>
</tr>
<tr class="odd">
<td>2</td>
<td>7</td>
<td>OTEL → VictoriaTraces/Metrics/Logs live (parallel)</td>
<td>1</td>
<td><a href="../decisions/20260506-maglev-cycle-2-observability.html">cycle-2</a></td>
</tr>
<tr class="even">
<td>3</td>
<td>7</td>
<td>Baker: train scene + VRM avatars via aria-storage → uro (parallel)</td>
<td>1</td>
<td><a href="../decisions/20260506-maglev-cycle-3-baker.html">cycle-3</a></td>
</tr>
<tr class="odd">
<td>4</td>
<td>8</td>
<td>Direct uro → CockroachDB connection; mTLS, IPv6, prepare:unnamed (parallel)</td>
<td>1</td>
<td><a href="../decisions/20260506-maglev-cycle-4-db-connection.html">cycle-4</a></td>
</tr>
<tr class="even">
<td>5</td>
<td>7</td>
<td>Zone-console (ratatui TUI) connects and shows tick rate (parallel)</td>
<td>1</td>
<td><a href="../decisions/20260506-maglev-cycle-5-zone-console.html">cycle-5</a></td>
</tr>
<tr class="odd">
<td>6</td>
<td>6</td>
<td>16 clients (14 taskweft bots + PCVR + Steam Deck); broadcast at MMOG load</td>
<td>1, 2</td>
<td><a href="../decisions/20260506-maglev-cycle-6-mmog-load.html">cycle-6</a></td>
</tr>
<tr class="even">
<td>7</td>
<td>7</td>
<td>IK routing and merge: format proven at 1 Hz, merge logic at 10 Hz</td>
<td>6</td>
<td><a href="../decisions/20260506-maglev-cycle-7-ik-routing.html">cycle-7</a></td>
</tr>
<tr class="odd">
<td>8</td>
<td>6</td>
<td>Full headset-rate IK merged without head-of-line blocking</td>
<td>7</td>
<td><a href="../decisions/20260506-maglev-cycle-8-ik-merge.html">cycle-8</a></td>
</tr>
<tr class="even">
<td>9</td>
<td>6</td>
<td>Banking train + stationary cores replicate; VRM avatars load from chunk store</td>
<td>8, 3</td>
<td><a href="../decisions/20260506-maglev-cycle-9-physics-vrm.html">cycle-9</a></td>
</tr>
<tr class="odd">
<td>10</td>
<td>6</td>
<td>Rolling cores under banking + causal ordering of core-slot events</td>
<td>9, 2, 5</td>
<td><a href="../decisions/20260506-maglev-cycle-10-dynamic-physics-score.html">cycle-10</a></td>
</tr>
<tr class="even">
<td>11</td>
<td>6</td>
<td>Full causal write: persona zone commits; uro persists score</td>
<td>10, 4</td>
<td><a href="../decisions/20260506-maglev-cycle-11-db-write.html">cycle-11</a></td>
</tr>
<tr class="odd">
<td>12</td>
<td>3</td>
<td>Game cycle planning: scoped ADRs and estimates for drone AI, combat, grab, slot, timer, camera modes</td>
<td>9</td>
<td><a href="../decisions/20260506-maglev-cycle-12-game-planning.html">cycle-12</a></td>
</tr>
</tbody>
</table>
<p>Taskweft-confirmed ordering: 13 cycles (0–12) running in number order. Cycle 0 gates everything. Parallel tracks 2–5 all start after Cycle 1; Cycle 2 (observability) must complete before Cycle 6; Cycle 3 (baker) must complete before Cycle 9; Cycle 5 (zone-console) must complete before Cycle 10; bake jobs (1–3 h) always complete before the networking cycles (≥1 day each).</p>
<p>Cycle 7 combines 1 Hz routing and 10 Hz merge into one cycle; Cycle 8 adds full headset rate. If the team is confident in the merge after Cycle 7, Cycle 8 can be skipped.</p>
<p><code>multiplayer-fabric-predictive-bvh</code> (interest management via predictive BVH) is exercised in Cycle 10: with 16 moving clients the BVH computes at least 2 distinct interest zones, verified in zone-console. Full cross-zone interest management (multiple zone servers) is left for a separate cycle series.</p>
</section>
<section id="cris-score" class="level2">
<h2 class="anchored" data-anchor-id="cris-score">CRIS Score</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 9%">
<col style="width: 3%">
<col style="width: 87%">
</colgroup>
<thead>
<tr class="header">
<th>Factor</th>
<th>Score</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C</strong>omplexity</td>
<td>4</td>
<td>Merging a 6-DOF IK stream with gamepad input in one physics tick, plus a cross-zone causal score commit, is untested in this codebase.</td>
</tr>
<tr class="even">
<td><strong>R</strong>each</td>
<td>10</td>
<td>Every future gameplay module runs on the gateway, zone server, replication cycle, and persona zone these cycles exercise.</td>
</tr>
<tr class="odd">
<td><strong>I</strong>mpediment</td>
<td>9</td>
<td>Physics desync or a broken persona write path blocks game design; either requires rewriting the netcode layer.</td>
</tr>
<tr class="even">
<td><strong>S</strong>takeholder</td>
<td>10</td>
<td>Primary proof-of-concept for the V-Sekai Fire multiplayer fabric.</td>
</tr>
<tr class="odd">
<td><strong>Total</strong></td>
<td>8.25</td>
<td>Build now.</td>
</tr>
</tbody>
</table>
</section>
<section id="the-downsides" class="level2">
<h2 class="anchored" data-anchor-id="the-downsides">The Downsides</h2>
<p>Cycle 10 requires Cyberprep art assets and MToon shaders tuned for both targets before it can run. Physics replication will stress WebTransport bandwidth. If the persona zone goes down, that player’s attributes are offline until it recovers. The shared-world UX for a standing VR player and a seated thumbstick player needs a separate design pass that cannot begin until Cycle 10 is stable.</p>
<p>Three gaps against industry par remain out of scope for this smoke test. Network condition simulation (artificial latency, jitter, packet loss) is standard in Unity Netcode, Photon, and Mirror but is not injected in these cycles. Reconnect storm testing — all 16 clients disconnecting and reconnecting simultaneously — is absent; VRChat’s largest outage traced to this failure mode. Automated CI/CD execution is also absent; industry runs a 5-minute smoke gate on every deploy, whereas these cycles are human-run, week-scale exercises.</p>
</section>
<section id="the-road-not-taken" class="level2">
<h2 class="anchored" data-anchor-id="the-road-not-taken">The Road Not Taken</h2>
<p>A steampunk skyship setting was rejected — it conflicts with the anime/VRM art targets and drifts toward fantasy MMO conventions.</p>
<p>Building the full scenario in one pass was the original plan, dropped when the staging approach proved easier to attribute failures.</p>
</section>
<section id="status" class="level2">
<h2 class="anchored" data-anchor-id="status">Status</h2>
<p>Status: Draft</p>
</section>
<section id="decision-makers" class="level2">
<h2 class="anchored" data-anchor-id="decision-makers">Decision Makers</h2>
<ul>
<li>Lead Architect / Fabric Maintainer</li>
<li>Game Director</li>
</ul>
</section>
<section id="tags" class="level2">
<h2 class="anchored" data-anchor-id="tags">Tags</h2>
<ul>
<li>smoke-test, cross-platform, tilt-shift, cyberprep, in-medias-res, persona-zone, shared-nothing, galls-law, 20260506-maglev-intercept-smoke-test, present-proposal-template</li>
</ul>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<pre><code>@misc{gall_1975,
  author = {Gall, John},
  title  = {Systemantics: How Systems Work and Especially How They Fail},
  year   = {1975}
}

@misc{v_sekai_2026,
  title = {V-Sekai},
  year  = {2026},
  url   = {https://v-sekai.org/}
}</code></pre>


</section>
</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-intercept-smoke-test.html</guid>
  <pubDate>Thu, 07 May 2026 13:27:28 GMT</pubDate>
</item>
<item>
  <title></title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-9-physics-vrm.html</link>
  <description><![CDATA[ 





<section id="maglev-cycle-9-physics-and-vrm-loading" class="level1">
<h1>Maglev Cycle 9: Physics and VRM Loading</h1>
<section id="the-context" class="level2">
<h2 class="anchored" data-anchor-id="the-context">The Context</h2>
<p>The gateway merges two input types at full rate after Cycle 9. This cycle loads the Maglev train scene with stationary cores on a banking train, verifies replication across clients, and confirms VRM avatar loading from the chunk store. Banking is a scene parameter change; VRM loading is verified in the same session as physics baseline.</p>
<p>Baked assets from Cycle 3 must be available in the chunk store before this cycle begins. Banking and VRM loading are combined here to reduce the number of cycles before the first physics demo.</p>
</section>
<section id="the-problem-statement" class="level2">
<h2 class="anchored" data-anchor-id="the-problem-statement">The Problem Statement</h2>
<p>Physics replication to clients with different frame rates requires validation before dynamic forces are added. Adding banking motion and rolling cores at the same time as replication makes any failure unattributable. This cycle proves the replication layer works before the physics is made dynamic.</p>
</section>
<section id="design" class="level2">
<h2 class="anchored" data-anchor-id="design">Design</h2>
<p>Load the Maglev train scene (greyboxed for this cycle: a CSG floor + banking pivot is sufficient) on the zone server. The train banks on a fixed schedule. Quantum Data-Cores sit stationary on the floor under authoritative physics (held by a constraint). The zone server sends datagram state each tick; both clients display the core and avatar positions.</p>
<p>The PCVR client sees the car as a waist-height diorama; the Steam Deck client sees the same instance as an isometric action-RPG. Both load <code>mire.vrm</code> (baked in Cycle 3 from <code>multiplayer-fabric-humanoid-project/humanoid/art/mire/mire.vrm</code>) as the avatar.</p>
<p>Pass criteria:</p>
<ul class="task-list">
<li><label><input type="checkbox">Zone server loads the Maglev train scene from the chunk store</label></li>
<li><label><input type="checkbox">Core positions agree between both clients each tick for 60 seconds under continuous banking</label></li>
<li><label><input type="checkbox">Zone server tick rate holds at 20 Hz with physics active</label></li>
<li><label><input type="checkbox"><code>mire.vrm</code> loads from the chunk store on both clients without error; humanoid skeleton root present</label></li>
<li><label><input type="checkbox">No entity desync over the run</label></li>
</ul>
</section>
<section id="estimate" class="level2">
<h2 class="anchored" data-anchor-id="estimate">Estimate</h2>
<p><strong>10 days</strong> (2026-06-02 → 2026-06-16). First cycle to load game assets and run physics. The zone server initial deploy took 2 days; adding a physics scene, banking animation, and VRM loading from the chunk store is the first substantial game dev work with no prior baseline. Projecting 2× the zone-console build time (6 working days) plus physics integration overhead.</p>
</section>
<section id="cris-score" class="level2">
<h2 class="anchored" data-anchor-id="cris-score">CRIS Score</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 9%">
<col style="width: 3%">
<col style="width: 86%">
</colgroup>
<thead>
<tr class="header">
<th>Factor</th>
<th>Score</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C</strong>omplexity</td>
<td>6</td>
<td>Physics replication to clients with different frame rates is untested, but a static scene removes the dynamic normal force variable.</td>
</tr>
<tr class="even">
<td><strong>R</strong>each</td>
<td>10</td>
<td>Cycle 10 cannot begin until replication itself is verified.</td>
</tr>
<tr class="odd">
<td><strong>I</strong>mpediment</td>
<td>9</td>
<td>A replication bug here means Cycle 10 results are unreliable.</td>
</tr>
<tr class="even">
<td><strong>S</strong>takeholder</td>
<td>10</td>
<td>Gate for Cycle 10 and beyond.</td>
</tr>
<tr class="odd">
<td><strong>Total</strong></td>
<td>8.75</td>
<td>Build after Cycles 8 and 6 pass.</td>
</tr>
</tbody>
</table>
</section>
<section id="the-downsides" class="level2">
<h2 class="anchored" data-anchor-id="the-downsides">The Downsides</h2>
<p>A passing Cycle 9 does not validate rolling physics or causal ordering; those require Cycle 10.</p>
</section>
<section id="the-road-not-taken" class="level2">
<h2 class="anchored" data-anchor-id="the-road-not-taken">The Road Not Taken</h2>
<p>Starting with rolling cores was rejected — replication and rolling-core physics are easier to separate when cores are stationary.</p>
</section>
<section id="status" class="level2">
<h2 class="anchored" data-anchor-id="status">Status</h2>
<p>Status: Draft</p>
</section>
<section id="decision-makers" class="level2">
<h2 class="anchored" data-anchor-id="decision-makers">Decision Makers</h2>
<ul>
<li>Lead Architect / Fabric Maintainer</li>
<li>Game Director</li>
</ul>
</section>
<section id="tags" class="level2">
<h2 class="anchored" data-anchor-id="tags">Tags</h2>
<ul>
<li>maglev-cycle-9, physics-vrm, replication, galls-law, 20260506-maglev-cycle-9-physics-vrm, present-proposal-template</li>
</ul>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<pre><code>@misc{v_sekai_2026,
  title = {V-Sekai},
  year  = {2026},
  url   = {https://v-sekai.org/}
}</code></pre>


</section>
</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-9-physics-vrm.html</guid>
  <pubDate>Thu, 07 May 2026 13:27:28 GMT</pubDate>
</item>
<item>
  <title></title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-8-ik-merge.html</link>
  <description><![CDATA[ 





<section id="maglev-cycle-8-full-rate-ik-merge" class="level1">
<h1>Maglev Cycle 8: Full-Rate IK Merge</h1>
<section id="the-context" class="level2">
<h2 class="anchored" data-anchor-id="the-context">The Context</h2>
<p>Cycle 7 confirms routing and merge at 10 Hz. Cycle 8 raises the PCVR client to operating rate — continuous 6-DOF IK at headset cadence — alongside full-rate gamepad input, and verifies the gateway merges both without head-of-line blocking.</p>
</section>
<section id="the-problem-statement" class="level2">
<h2 class="anchored" data-anchor-id="the-problem-statement">The Problem Statement</h2>
<p>6-DOF IK datagrams arrive an order of magnitude more frequently than gamepad events. The gateway’s merge path must handle that rate differential without blocking lower-frequency gamepad events. A head-of-line stall on the IK queue would delay or drop gamepad events silently.</p>
</section>
<section id="design" class="level2">
<h2 class="anchored" data-anchor-id="design">Design</h2>
<p>The PCVR client sends 6-DOF IK datagrams at full headset rate. The Steam Deck client sends gamepad datagrams at normal cadence. Both arrive on UDP 443. The gateway merges them per tick and forwards to the zone server on UDP 7443. The world is static.</p>
<p>Pass criteria:</p>
<ul class="task-list">
<li><label><input type="checkbox">Zone server processes ticks containing both input types without stalls or skipped events</label></li>
<li><label><input type="checkbox">No gamepad datagram is silently dropped over 60 seconds under full IK load</label></li>
<li><label><input type="checkbox">Gateway CPU stays within budget under both streams at full rate</label></li>
</ul>
</section>
<section id="estimate" class="level2">
<h2 class="anchored" data-anchor-id="estimate">Estimate</h2>
<p><strong>5 days</strong> (2026-05-26 → 2026-06-02). The merge path is an extension of Cycle 7; the risk is head-of-line behaviour under load, which requires profiling time. A hardware re-run on physical Meta Quest hardware before Cycle 9 adds 1 day outside this window.</p>
</section>
<section id="cris-score" class="level2">
<h2 class="anchored" data-anchor-id="cris-score">CRIS Score</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 9%">
<col style="width: 3%">
<col style="width: 87%">
</colgroup>
<thead>
<tr class="header">
<th>Factor</th>
<th>Score</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C</strong>omplexity</td>
<td>6</td>
<td>Merging a continuous high-frequency IK stream with low-frequency gamepad input without head-of-line effects is untested in this codebase.</td>
</tr>
<tr class="even">
<td><strong>R</strong>each</td>
<td>10</td>
<td>Cross-platform play at operating rate requires this path; Cycles 9 and beyond add physics and persistence on top of it.</td>
</tr>
<tr class="odd">
<td><strong>I</strong>mpediment</td>
<td>9</td>
<td>A head-of-line bug here makes physics results in Cycle 9 and beyond unreliable for the gamepad client.</td>
</tr>
<tr class="even">
<td><strong>S</strong>takeholder</td>
<td>10</td>
<td>Gate for cross-platform physics and score.</td>
</tr>
<tr class="odd">
<td><strong>Total</strong></td>
<td>8.25</td>
<td>Build after Cycle 7 passes.</td>
</tr>
</tbody>
</table>
</section>
<section id="the-downsides" class="level2">
<h2 class="anchored" data-anchor-id="the-downsides">The Downsides</h2>
<p>The Meta XR Simulator on macOS covers the initial run, but Cycle 8 must be re-run on physical hardware before Cycle 9 begins — the simulator does not reproduce real headset IK datagram rates under motion.</p>
</section>
<section id="the-road-not-taken" class="level2">
<h2 class="anchored" data-anchor-id="the-road-not-taken">The Road Not Taken</h2>
<p>Skipping Cycles 7 and 5 together was rejected — a failure at full rate conflates routing bugs with rate bugs, leaving both unattributable.</p>
</section>
<section id="status" class="level2">
<h2 class="anchored" data-anchor-id="status">Status</h2>
<p>Status: Draft</p>
</section>
<section id="decision-makers" class="level2">
<h2 class="anchored" data-anchor-id="decision-makers">Decision Makers</h2>
<ul>
<li>Lead Architect / Fabric Maintainer</li>
</ul>
</section>
<section id="tags" class="level2">
<h2 class="anchored" data-anchor-id="tags">Tags</h2>
<ul>
<li>maglev-cycle-8, ik-merge, heterogeneous-input, galls-law, 20260506-maglev-cycle-8-ik-merge, present-proposal-template</li>
</ul>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<pre><code>@misc{v_sekai_2026,
  title = {V-Sekai},
  year  = {2026},
  url   = {https://v-sekai.org/}
}</code></pre>


</section>
</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-8-ik-merge.html</guid>
  <pubDate>Thu, 07 May 2026 13:27:28 GMT</pubDate>
</item>
<item>
  <title></title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-7-ik-routing.html</link>
  <description><![CDATA[ 





<section id="maglev-cycle-7-ik-routing-and-merge" class="level1">
<h1>Maglev Cycle 7: IK Routing and Merge</h1>
<section id="the-context" class="level2">
<h2 class="anchored" data-anchor-id="the-context">The Context</h2>
<p>Two same-type Godot clients share a zone after Cycle 6. Cycle 7 swaps one Steam Deck client for a PCVR client and confirms that a single 6-DOF IK datagram travels through the gateway and reaches the zone server. The rate and merge logic are not yet in scope.</p>
</section>
<section id="the-problem-statement" class="level2">
<h2 class="anchored" data-anchor-id="the-problem-statement">The Problem Statement</h2>
<p>A PCVR client’s IK datagram format differs structurally from a gamepad datagram. The gateway has never parsed one. Before testing merge behaviour at full IK rate, the routing path itself must be shown to work for at least one IK datagram.</p>
</section>
<section id="design" class="level2">
<h2 class="anchored" data-anchor-id="design">Design</h2>
<p>The PCVR client — running the solved <code>multiplayer-fabric-interaction-system</code> addon via <code>xr_controller_interaction_helper.gd</code> and <code>xr_action_host.gd</code> — starts at 1 Hz IK and ramps to 10 Hz. The Steam Deck client sends gamepad datagrams at normal cadence. The gateway routes and merges both streams to the zone server on UDP 7443. The world is static.</p>
<p>The 1 Hz phase confirms the IK datagram format parses correctly. The 10 Hz phase confirms the gateway’s merge logic is correct under concurrent input before full rate is introduced.</p>
<p>Pass criteria:</p>
<ul class="task-list">
<li><label><input type="checkbox">Zone server receives and logs at least one IK datagram without parse error at 1 Hz</label></li>
<li><label><input type="checkbox">Zone server receives a merged tick containing both input types at 10 Hz</label></li>
<li><label><input type="checkbox">No gamepad datagram dropped over 60 seconds at 10 Hz</label></li>
<li><label><input type="checkbox">No gateway crash or restart</label></li>
</ul>
</section>
<section id="estimate" class="level2">
<h2 class="anchored" data-anchor-id="estimate">Estimate</h2>
<p><strong>5 days</strong> (2026-05-19 → 2026-05-26). The IK datagram format is new but the gateway routing path is identical to gamepad. The interaction system (<code>xr_controller_interaction_helper.gd</code>) is solved; the work is serialization format definition and gateway route registration.</p>
</section>
<section id="cris-score" class="level2">
<h2 class="anchored" data-anchor-id="cris-score">CRIS Score</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 10%">
<col style="width: 3%">
<col style="width: 86%">
</colgroup>
<thead>
<tr class="header">
<th>Factor</th>
<th>Score</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C</strong>omplexity</td>
<td>7</td>
<td>IK datagram format is new to the gateway but the routing path is identical to gamepad; one datagram per second removes rate risk.</td>
</tr>
<tr class="even">
<td><strong>R</strong>each</td>
<td>10</td>
<td>Cycle 8 (full-rate IK) cannot begin without a proven merge baseline.</td>
</tr>
<tr class="odd">
<td><strong>I</strong>mpediment</td>
<td>9</td>
<td>A parse failure here blocks all cross-platform work.</td>
</tr>
<tr class="even">
<td><strong>S</strong>takeholder</td>
<td>10</td>
<td>Gate for Cycle 8 and all subsequent cross-platform cycles.</td>
</tr>
<tr class="odd">
<td><strong>Total</strong></td>
<td>9.0</td>
<td>Build after Cycle 6 passes.</td>
</tr>
</tbody>
</table>
</section>
<section id="the-downsides" class="level2">
<h2 class="anchored" data-anchor-id="the-downsides">The Downsides</h2>
<p>10 Hz IK does not trigger head-of-line pressure; that stress test is Cycle 8 at full headset rate.</p>
</section>
<section id="the-road-not-taken" class="level2">
<h2 class="anchored" data-anchor-id="the-road-not-taken">The Road Not Taken</h2>
<p>Going straight to full headset rate was rejected — a routing bug and a head-of-line bug at the same time are harder to separate than routing at 1 Hz and merge at 10 Hz in one cycle.</p>
</section>
<section id="status" class="level2">
<h2 class="anchored" data-anchor-id="status">Status</h2>
<p>Status: Draft</p>
</section>
<section id="decision-makers" class="level2">
<h2 class="anchored" data-anchor-id="decision-makers">Decision Makers</h2>
<ul>
<li>Lead Architect / Fabric Maintainer</li>
</ul>
</section>
<section id="tags" class="level2">
<h2 class="anchored" data-anchor-id="tags">Tags</h2>
<ul>
<li>maglev-cycle-7, ik-routing-merge, heterogeneous-input, galls-law, 20260506-maglev-cycle-7-ik-routing-merge, present-proposal-template</li>
</ul>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<pre><code>@misc{v_sekai_2026,
  title = {V-Sekai},
  year  = {2026},
  url   = {https://v-sekai.org/}
}</code></pre>


</section>
</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-7-ik-routing.html</guid>
  <pubDate>Thu, 07 May 2026 13:27:28 GMT</pubDate>
</item>
<item>
  <title></title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-6-mmog-load.html</link>
  <description><![CDATA[ 





<section id="maglev-cycle-6-dual-same-type-clients" class="level1">
<h1>Maglev Cycle 6: Dual Same-Type Clients</h1>
<section id="the-context" class="level2">
<h2 class="anchored" data-anchor-id="the-context">The Context</h2>
<p>With one Godot client verified end-to-end and the observability stack live (Cycle 2), the next question is whether the gateway can multiplex two same-type connections into one zone server tick while keeping both clients synchronized. Observability must be running before this cycle begins — a broadcast failure here is unattributable without gateway traces.</p>
</section>
<section id="the-problem-statement" class="level2">
<h2 class="anchored" data-anchor-id="the-problem-statement">The Problem Statement</h2>
<p>16 clients in one zone is the minimum to qualify as MMOG load. 14 are taskweft bots (~15 MB each, not full Godot processes); 1 is the PCVR human; 1 is the Steam Deck human. Connection-slot handling, datagram ordering, and state broadcast to 16 sockets have not been tested under concurrent load.</p>
</section>
<section id="design" class="level2">
<h2 class="anchored" data-anchor-id="design">Design</h2>
<p>16 clients connect to the gateway simultaneously. All receive datagram state from the same zone server instance each tick. One static entity in an empty world.</p>
<p>Pass criteria:</p>
<ul class="task-list">
<li><label><input type="checkbox">All 16 clients receive consistent entity state each tick for 60 seconds</label></li>
<li><label><input type="checkbox">No client observes a tick gap or duplicate</label></li>
<li><label><input type="checkbox">Zone-console shows 16 entities at 20 Hz</label></li>
<li><label><input type="checkbox">Gateway process memory stays flat under 16 connections</label></li>
<li><label><input type="checkbox">All 14 bots disconnect and reconnect simultaneously; gateway recovers within 5 seconds and all clients resync without a restart</label></li>
<li><label><input type="checkbox">Under 100 ms injected latency and 2% packet loss, no client desyncs over 30 seconds</label></li>
</ul>
</section>
<section id="estimate" class="level2">
<h2 class="anchored" data-anchor-id="estimate">Estimate</h2>
<p><strong>5 days</strong> (2026-05-13 → 2026-05-19). Taskweft bots are proven (93 PropCheck properties passing). The work is wiring 14 bots to the gateway and adding the reconnect storm and network condition harnesses. No prior multi-bot gateway test exists in the history; projecting from the gateway build pace.</p>
</section>
<section id="cris-score" class="level2">
<h2 class="anchored" data-anchor-id="cris-score">CRIS Score</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 10%">
<col style="width: 3%">
<col style="width: 86%">
</colgroup>
<thead>
<tr class="header">
<th>Factor</th>
<th>Score</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C</strong>omplexity</td>
<td>6</td>
<td>16 same-type connections; taskweft bots are proven infrastructure but have not been combined with the gateway at this count.</td>
</tr>
<tr class="even">
<td><strong>R</strong>each</td>
<td>10</td>
<td>All subsequent cycles run at 16-client load.</td>
</tr>
<tr class="odd">
<td><strong>I</strong>mpediment</td>
<td>9</td>
<td>A desync at 16 clients means the gateway’s broadcast path is broken before heterogeneous input is added.</td>
</tr>
<tr class="even">
<td><strong>S</strong>takeholder</td>
<td>10</td>
<td>Gate for Cycles 7–10.</td>
</tr>
<tr class="odd">
<td><strong>Total</strong></td>
<td>8.75</td>
<td>Build after Cycles 1 and 2 pass.</td>
</tr>
</tbody>
</table>
</section>
<section id="the-downsides" class="level2">
<h2 class="anchored" data-anchor-id="the-downsides">The Downsides</h2>
<p>16 same-type bots leave the heterogeneous input path unvalidated.</p>
</section>
<section id="the-road-not-taken" class="level2">
<h2 class="anchored" data-anchor-id="the-road-not-taken">The Road Not Taken</h2>
<p>Starting immediately with heterogeneous IK and gamepad inputs at 16-client scale was rejected — a broadcast failure at full complexity would be ambiguous between gateway capacity and input-mux issues. Cycle 6 uses uniform bots to isolate the broadcast path.</p>
</section>
<section id="status" class="level2">
<h2 class="anchored" data-anchor-id="status">Status</h2>
<p>Status: Draft</p>
</section>
<section id="decision-makers" class="level2">
<h2 class="anchored" data-anchor-id="decision-makers">Decision Makers</h2>
<ul>
<li>Lead Architect / Fabric Maintainer</li>
</ul>
</section>
<section id="tags" class="level2">
<h2 class="anchored" data-anchor-id="tags">Tags</h2>
<ul>
<li>maglev-cycle-6, mmog-load, gateway, smoke-test, galls-law, 20260506-maglev-cycle-6-mmog-load, present-proposal-template</li>
</ul>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<pre><code>@misc{v_sekai_2026,
  title = {V-Sekai},
  year  = {2026},
  url   = {https://v-sekai.org/}
}</code></pre>


</section>
</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-6-mmog-load.html</guid>
  <pubDate>Thu, 07 May 2026 13:27:28 GMT</pubDate>
</item>
<item>
  <title></title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-5-zone-console.html</link>
  <description><![CDATA[ 





<section id="maglev-cycle-5-zone-console-tui-observer" class="level1">
<h1>Maglev Cycle 5: Zone-Console TUI Observer</h1>
<section id="the-context" class="level2">
<h2 class="anchored" data-anchor-id="the-context">The Context</h2>
<p><code>multiplayer-fabric-zone-console</code> is a ratatui TUI that observes the zone over WebTransport. It is in the production stack and is the operator’s primary visibility into zone health during and after mission cycles. Cycle 5 depends only on Cycle 1 (zone server live) and runs in parallel with the game-logic track.</p>
</section>
<section id="the-problem-statement" class="level2">
<h2 class="anchored" data-anchor-id="the-problem-statement">The Problem Statement</h2>
<p>The zone-console has not connected to the zone server under the Fly deployment and confirmed it can display entity state and tick rate. Without a passing Cycle 5, operators have no real-time view into the zone during Cycles 9–10, where physics desync and causal ordering failures are the primary risks.</p>
</section>
<section id="design" class="level2">
<h2 class="anchored" data-anchor-id="design">Design</h2>
<p>Start zone-console targeting the Fly zone server. Confirm the TUI displays: connected status, current tick rate (targeting 20 Hz), and at least one entity visible in the entity list.</p>
<p>Pass criteria:</p>
<ul class="task-list">
<li><label><input type="checkbox">zone-console connects without error</label></li>
<li><label><input type="checkbox">Tick rate displayed at 15 Hz or above (full 20 Hz target confirmed in Cycle 10)</label></li>
<li><label><input type="checkbox">At least one entity visible in the TUI entity list</label></li>
<li><label><input type="checkbox">Clean disconnect on exit with no orphaned connection</label></li>
</ul>
</section>
<section id="estimate" class="level2">
<h2 class="anchored" data-anchor-id="estimate">Estimate</h2>
<p><strong>2 days</strong> (2026-05-09 → 2026-05-12, parallel). Zone-console was built from scratch in 6 working days (2026-04-21–28). The work here is connecting the existing TUI to the deployed Fly gateway rather than a local target — config and endpoint change only.</p>
</section>
<section id="cris-score" class="level2">
<h2 class="anchored" data-anchor-id="cris-score">CRIS Score</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 12%">
<col style="width: 4%">
<col style="width: 83%">
</colgroup>
<thead>
<tr class="header">
<th>Factor</th>
<th>Score</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C</strong>omplexity</td>
<td>7</td>
<td>WebTransport observer is simpler than the game clients; the risk is ratatui rendering on headless CI.</td>
</tr>
<tr class="even">
<td><strong>R</strong>each</td>
<td>9</td>
<td>Operators need this during Cycles 4–2 to confirm tick rate holds under dynamic physics load.</td>
</tr>
<tr class="odd">
<td><strong>I</strong>mpediment</td>
<td>7</td>
<td>A missing observer does not block gameplay but leaves Cycles 4–2 without operator-facing monitoring.</td>
</tr>
<tr class="even">
<td><strong>S</strong>takeholder</td>
<td>10</td>
<td>Operator visibility tool for the production stack.</td>
</tr>
<tr class="odd">
<td><strong>Total</strong></td>
<td>8.25</td>
<td>Build after Cycle 1 passes, in parallel with Cycles 6–11.</td>
</tr>
</tbody>
</table>
</section>
<section id="the-downsides" class="level2">
<h2 class="anchored" data-anchor-id="the-downsides">The Downsides</h2>
<p>A passing Cycle 5 does not validate zone-console under load; the full 20 Hz tick rate and entity count targets are confirmed during Cycle 10.</p>
</section>
<section id="the-road-not-taken" class="level2">
<h2 class="anchored" data-anchor-id="the-road-not-taken">The Road Not Taken</h2>
<p>Deferring to after Cycle 10 was rejected — the observer is needed during Cycle 10 to confirm tick rate holds at 20 Hz under dynamic physics load.</p>
</section>
<section id="status" class="level2">
<h2 class="anchored" data-anchor-id="status">Status</h2>
<p>Status: Draft</p>
</section>
<section id="decision-makers" class="level2">
<h2 class="anchored" data-anchor-id="decision-makers">Decision Makers</h2>
<ul>
<li>Lead Architect / Fabric Maintainer</li>
</ul>
</section>
<section id="tags" class="level2">
<h2 class="anchored" data-anchor-id="tags">Tags</h2>
<ul>
<li>maglev-cycle-5, zone-console, ratatui, observer, galls-law, 20260506-maglev-cycle-5-zone-console, present-proposal-template</li>
</ul>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<pre><code>@techreport{20260506_cycle1,
  title       = {Maglev Cycle 1: Godot Client Gateway Handshake},
  institution = {V-Sekai Fire},
  year        = {2026},
  type        = {Architecture Decision Record},
  note        = {decisions/20260506-maglev-cycle-1-gateway-handshake.md}
}

@techreport{20260501_webtransport,
  title       = {Use WebTransport over QUIC for game traffic},
  institution = {V-Sekai Fire},
  year        = {2026},
  type        = {Architecture Decision Record},
  note        = {decisions/20260501-webtransport-over-quic-for-game-traffic.md}
}

@misc{v_sekai_2026,
  title = {V-Sekai},
  year  = {2026},
  url   = {https://v-sekai.org/}
}</code></pre>


</section>
</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-5-zone-console.html</guid>
  <pubDate>Thu, 07 May 2026 13:27:28 GMT</pubDate>
</item>
<item>
  <title></title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-4-db-connection.html</link>
  <description><![CDATA[ 





<section id="maglev-cycle-4-cockroachdb-connection" class="level1">
<h1>Maglev Cycle 4: CockroachDB Connection</h1>
<section id="the-context" class="level2">
<h2 class="anchored" data-anchor-id="the-context">The Context</h2>
<p>Cycle 10 confirms cross-zone causal ordering via VClock.le gating. Cycle 4 verifies the database write path independently: <code>multiplayer-fabric-uro</code> writes a single test record to CockroachDB over Fly’s 6PN without any game logic or causal path involved.</p>
</section>
<section id="the-problem-statement" class="level2">
<h2 class="anchored" data-anchor-id="the-problem-statement">The Problem Statement</h2>
<p>The Ecto connection from uro to CockroachDB over Fly’s 6PN using the <code>gateway_writer</code> role has not been exercised under the Fly network topology. Verifying it in isolation means any failure in Cycle 11 is attributable to the causal path, not the connection.</p>
</section>
<section id="design" class="level2">
<h2 class="anchored" data-anchor-id="design">Design</h2>
<p>Trigger a test write from <code>multiplayer-fabric-uro</code> directly — a single row to a test table — using the <code>gateway_writer</code> role. The connection uses mTLS (cert generated by <code>gen_crdb_certs.sh</code>), port 26257 over Fly’s 6PN private network (IPv6 only, <code>socket_options: [:inet6]</code>), and <code>prepare: :unnamed</code> in Postgrex to prevent statement-cache OOM on the single-node deployment.</p>
<p>Pass criteria:</p>
<ul class="task-list">
<li><label><input type="checkbox">Row appears in CockroachDB within one second of the trigger</label></li>
<li><label><input type="checkbox">mTLS handshake succeeds; no cert or auth error</label></li>
<li><label><input type="checkbox"><code>gateway_writer</code> role has DML access; <code>gateway_admin</code> is not used at runtime</label></li>
<li><label><input type="checkbox">Connection reuse works across multiple sequential writes (<code>prepare: :unnamed</code> confirmed)</label></li>
</ul>
</section>
<section id="estimate" class="level2">
<h2 class="anchored" data-anchor-id="estimate">Estimate</h2>
<p><strong>1 day</strong> (2026-05-09, parallel). The uro CockroachDB connection is already working on Fly (commit “Fix CockroachDB connection on Fly: inet6 socket + unnamed prepare”, 2026-05-05). This cycle validates the existing connection against the pass criteria checklist.</p>
</section>
<section id="cris-score" class="level2">
<h2 class="anchored" data-anchor-id="cris-score">CRIS Score</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 9%">
<col style="width: 3%">
<col style="width: 87%">
</colgroup>
<thead>
<tr class="header">
<th>Factor</th>
<th>Score</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C</strong>omplexity</td>
<td>8</td>
<td>A direct Ecto write over Fly’s 6PN is well-understood; the only unknown is the Fly network topology between uro and the CockroachDB node.</td>
</tr>
<tr class="even">
<td><strong>R</strong>each</td>
<td>10</td>
<td>Cycle 11 cannot safely write mission scores until the connection itself is verified.</td>
</tr>
<tr class="odd">
<td><strong>I</strong>mpediment</td>
<td>7</td>
<td>A connection failure here blocks Cycle 11 but not the mission gameplay in Cycles 6–10.</td>
</tr>
<tr class="even">
<td><strong>S</strong>takeholder</td>
<td>10</td>
<td>Gate for Cycle 11.</td>
</tr>
<tr class="odd">
<td><strong>Total</strong></td>
<td>8.75</td>
<td>Build after Cycle 2 passes.</td>
</tr>
</tbody>
</table>
</section>
<section id="the-downsides" class="level2">
<h2 class="anchored" data-anchor-id="the-downsides">The Downsides</h2>
<p>A passing Cycle 4 does not validate the causal write path.</p>
</section>
<section id="the-road-not-taken" class="level2">
<h2 class="anchored" data-anchor-id="the-road-not-taken">The Road Not Taken</h2>
<p>Testing the DB connection as part of Cycle 11 was rejected — a connection failure inside the causal write path is harder to distinguish from a VClock gating failure.</p>
</section>
<section id="status" class="level2">
<h2 class="anchored" data-anchor-id="status">Status</h2>
<p>Status: Draft</p>
</section>
<section id="decision-makers" class="level2">
<h2 class="anchored" data-anchor-id="decision-makers">Decision Makers</h2>
<ul>
<li>Lead Architect / Fabric Maintainer</li>
</ul>
</section>
<section id="tags" class="level2">
<h2 class="anchored" data-anchor-id="tags">Tags</h2>
<ul>
<li>maglev-cycle-4, db-connection, cockroachdb, galls-law, 20260506-maglev-cycle-4-db-connection, present-proposal-template</li>
</ul>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<pre><code>@techreport{20260501_crdb,
  title       = {CockroachDB with mTLS and role-separated access},
  institution = {V-Sekai Fire},
  year        = {2026},
  type        = {Architecture Decision Record},
  note        = {decisions/20260501-cockroachdb-with-mtls-role-separation.md}
}

@techreport{20260501_fly,
  title       = {Fly.io for deployment},
  institution = {V-Sekai Fire},
  year        = {2026},
  type        = {Architecture Decision Record},
  note        = {decisions/20260501-fly-io-for-deployment.md}
}

@misc{v_sekai_2026,
  title = {V-Sekai},
  year  = {2026},
  url   = {https://v-sekai.org/}
}</code></pre>


</section>
</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-4-db-connection.html</guid>
  <pubDate>Thu, 07 May 2026 13:27:28 GMT</pubDate>
</item>
<item>
  <title></title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-3-baker.html</link>
  <description><![CDATA[ 





<section id="maglev-cycle-3-baker-pipeline" class="level1">
<h1>Maglev Cycle 3: Baker Pipeline</h1>
<section id="the-context" class="level2">
<h2 class="anchored" data-anchor-id="the-context">The Context</h2>
<p>The Maglev train scene and player VRM avatars must be baked before Cycle 9 (physics replication), which is the first cycle to load actual game assets into the zone server. The baker pipeline runs as an on-demand Fly Machine, depends only on the Fly infrastructure proven in Cycle 1, and can run in parallel with Cycles 6–9.</p>
<p><code>multiplayer-fabric-baker</code> uses Godot in headless editor mode (<code>godot.linuxbsd.editor.double.x86_64</code>, built from <code>multiplayer-fabric-baker</code> via <code>ghcr.io/v-sekai-fire/godot-editor-double:latest</code>) to validate and export scenes. <code>aria-storage</code> chunks the output using casync/desync <code>.caibx</code> format with zstd compression, uploads chunks to the zone-backend chunk store, and posts the <code>.caibx</code> index to uro at <code>/storage/:id/bake</code>.</p>
</section>
<section id="the-problem-statement" class="level2">
<h2 class="anchored" data-anchor-id="the-problem-statement">The Problem Statement</h2>
<p>The Cyberprep train environment (MToon shaders, banking train geometry) and the test VRM avatar have not been validated and stored through the baker pipeline under the Fly deployment. Without baked assets in the chunk store, the zone server in Cycle 9 cannot load the scene.</p>
</section>
<section id="design" class="level2">
<h2 class="anchored" data-anchor-id="design">Design</h2>
<p>Trigger two bake jobs via the Fly Machines API:</p>
<ol type="1">
<li><strong>Train environment bake</strong>: <code>multiplayer-fabric-baker</code> validates the Maglev train scene (greybox CSG geometry is acceptable for cycle validation), exports it, chunks it with aria-storage, and posts the index to uro.</li>
<li><strong>Avatar bake</strong>: same pipeline for <code>multiplayer-fabric-humanoid-project/humanoid/art/mire/mire.vrm</code> (51 MB), used by both PCVR and Steam Deck clients in Cycle 9.</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">flyctl</span> machine run registry.fly.io/multiplayer-fabric-baker:latest <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb1-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--app</span> multiplayer-fabric-baker <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb1-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--env</span> ASSET_ID=<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>uuid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb1-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--env</span> URO_URL=https://hub.chibifire.com <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb1-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--</span> avatar scenes/<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>uuid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>.tscn out/<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>uuid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>.scn</span></code></pre></div></div>
<p>Pass criteria:</p>
<ul class="task-list">
<li><label><input type="checkbox">Both bake jobs exit 0</label></li>
<li><label><input type="checkbox"><code>.caibx</code> index appears in uro at <code>/storage/:id/bake</code> for each asset</label></li>
<li><label><input type="checkbox">Zone server can fetch and assemble the train scene from the chunk store before Cycle 9 begins</label></li>
</ul>
</section>
<section id="estimate" class="level2">
<h2 class="anchored" data-anchor-id="estimate">Estimate</h2>
<p><strong>3 days</strong> (2026-05-09 → 2026-05-13, parallel). The baker pipeline is in production on Fly (14 days of commits 2026-04-23 to 2026-05-06). The work is Maglev-specific bake config (MToon shader settings, VRM export params) and a Fly Machine invocation test. <code>mire.vrm</code> and a greyboxed train scene are the placeholder inputs, so no art track blocks this cycle.</p>
</section>
<section id="cris-score" class="level2">
<h2 class="anchored" data-anchor-id="cris-score">CRIS Score</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 9%">
<col style="width: 3%">
<col style="width: 87%">
</colgroup>
<thead>
<tr class="header">
<th>Factor</th>
<th>Score</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C</strong>omplexity</td>
<td>7</td>
<td>The baker pipeline is in production use; the only unknowns are the Maglev-specific MToon shader configuration and VRM avatar export settings.</td>
</tr>
<tr class="even">
<td><strong>R</strong>each</td>
<td>10</td>
<td>Cycles 10–4 cannot load game assets without baked chunk store entries.</td>
</tr>
<tr class="odd">
<td><strong>I</strong>mpediment</td>
<td>9</td>
<td>A bake failure before Cycle 9 blocks the entire physics and scenario track.</td>
</tr>
<tr class="even">
<td><strong>S</strong>takeholder</td>
<td>10</td>
<td>Required before the first physics cycle and the full Maglev mission scenario.</td>
</tr>
<tr class="odd">
<td><strong>Total</strong></td>
<td>8.75</td>
<td>Build after Cycle 1 passes, in parallel with Cycles 6–9.</td>
</tr>
</tbody>
</table>
</section>
<section id="the-downsides" class="level2">
<h2 class="anchored" data-anchor-id="the-downsides">The Downsides</h2>
<p>Building the Cyberprep environment with MToon shaders tuned for both Steam Deck and PCVR requires dedicated art work. Bake failures surface late if the pipeline is not tested early; running this cycle in parallel with Cycles 6–9 surfaces them while networking cycles are still running.</p>
</section>
<section id="the-road-not-taken" class="level2">
<h2 class="anchored" data-anchor-id="the-road-not-taken">The Road Not Taken</h2>
<p>Deferring the bake to just before Cycle 9 was rejected — a failed bake stalls the physics track after the networking cycles that preceded Cycle 9 have already completed.</p>
</section>
<section id="status" class="level2">
<h2 class="anchored" data-anchor-id="status">Status</h2>
<p>Status: Draft</p>
</section>
<section id="decision-makers" class="level2">
<h2 class="anchored" data-anchor-id="decision-makers">Decision Makers</h2>
<ul>
<li>Lead Architect / Fabric Maintainer</li>
<li>Game Director</li>
</ul>
</section>
<section id="tags" class="level2">
<h2 class="anchored" data-anchor-id="tags">Tags</h2>
<ul>
<li>maglev-cycle-3, baker, aria-storage, vrm, galls-law, 20260506-maglev-cycle-3-baker, present-proposal-template</li>
</ul>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<pre><code>@techreport{20260501_fly,
  title       = {Fly.io for deployment},
  institution = {V-Sekai Fire},
  year        = {2026},
  type        = {Architecture Decision Record},
  note        = {decisions/20260501-fly-io-for-deployment.md}
}

@techreport{20260506_ghcr,
  title       = {GHCR packages must be built by the repo that consumes them},
  institution = {V-Sekai Fire},
  year        = {2026},
  type        = {Architecture Decision Record},
  note        = {decisions/20260506-ghcr-package-ownership-same-repo.md}
}

@misc{v_sekai_2026,
  title = {V-Sekai},
  year  = {2026},
  url   = {https://v-sekai.org/}
}</code></pre>


</section>
</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-3-baker.html</guid>
  <pubDate>Thu, 07 May 2026 13:27:28 GMT</pubDate>
</item>
<item>
  <title></title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-2-observability.html</link>
  <description><![CDATA[ 





<section id="maglev-cycle-2-observability-stack" class="level1">
<h1>Maglev Cycle 2: Observability Stack</h1>
<section id="the-context" class="level2">
<h2 class="anchored" data-anchor-id="the-context">The Context</h2>
<p>The observability stack — OTEL Collector (4317/4318), VictoriaMetrics (8428), VictoriaLogs (9428), VictoriaTraces (10428) — is infrastructure-level and depends only on the Fly deployment being live after Cycle 1. It can run in parallel with the game-logic track (Cycles 3–10) and the DB connection (Cycle 9).</p>
</section>
<section id="the-problem-statement" class="level2">
<h2 class="anchored" data-anchor-id="the-problem-statement">The Problem Statement</h2>
<p>No cycle verifies that traces from <code>multiplayer-fabric-gateway</code>, <code>multiplayer-fabric-zone</code>, and <code>multiplayer-fabric-uro</code> reach VictoriaTraces, or that metrics reach VictoriaMetrics. Without this, any failure in Cycles 3–10 has no trace evidence to debug against.</p>
</section>
<section id="design" class="level2">
<h2 class="anchored" data-anchor-id="design">Design</h2>
<p>Start the observability stack on the Fly deployment:</p>
<ul>
<li>VictoriaMetrics on port 8428</li>
<li>VictoriaLogs on port 9428</li>
<li>VictoriaTraces on port 10428 (replaces Jaeger; <code>fly proxy 10428:10428</code> for local inspection)</li>
<li>OTEL Collector on 4317 (gRPC) and 4318 (HTTP), routing to all three backends</li>
</ul>
<p>Trigger a single gateway request and a single zone tick. The zone server binary includes the <code>opentelemetry-godot</code> module compiled into the engine (verify with <code>--test --test-case="*OTel*"</code> before the run). Verify each service emits OTLP spans to the Collector.</p>
<p>Pass criteria:</p>
<ul class="task-list">
<li><label><input type="checkbox">VictoriaTraces UI at <code>http://localhost:10428/select/vmui</code> shows spans from at least one gateway request</label></li>
<li><label><input type="checkbox">VictoriaMetrics at port 8428 returns a non-empty result for a zone-server metric query</label></li>
<li><label><input type="checkbox">VictoriaLogs at port 9428 shows at least one log line from uro</label></li>
<li><label><input type="checkbox">All four services are Apache 2.0 (no Tempo, no Jaeger)</label></li>
</ul>
</section>
<section id="estimate" class="level2">
<h2 class="anchored" data-anchor-id="estimate">Estimate</h2>
<p><strong>3 days</strong> (2026-05-09 → 2026-05-13, parallel). VictoriaMetrics/Logs/Traces share a config pattern; the only unknown is Fly volume persistence. Comparable to the zone-console Fly deploy (2 days of config commits on 2026-04-24–25).</p>
</section>
<section id="cris-score" class="level2">
<h2 class="anchored" data-anchor-id="cris-score">CRIS Score</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 7%">
<col style="width: 2%">
<col style="width: 89%">
</colgroup>
<thead>
<tr class="header">
<th>Factor</th>
<th>Score</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C</strong>omplexity</td>
<td>7</td>
<td>All four Victoria backends share port conventions and the OTEL Collector config is well-documented; the only unknown is Fly volume persistence under the single-machine deployment.</td>
</tr>
<tr class="even">
<td><strong>R</strong>each</td>
<td>10</td>
<td>Every failure in Cycles 3–10 requires trace evidence to diagnose; without this cycle no networking or physics failure is attributable.</td>
</tr>
<tr class="odd">
<td><strong>I</strong>mpediment</td>
<td>7</td>
<td>A missing observability stack does not block Cycles 3–10 but leaves failures in Cycles 3–10 impossible to root-cause.</td>
</tr>
<tr class="even">
<td><strong>S</strong>takeholder</td>
<td>10</td>
<td>Required for any post-mission debugging of physics desync or score write failures.</td>
</tr>
<tr class="odd">
<td><strong>Total</strong></td>
<td>8.5</td>
<td>Build after Cycle 1 passes, in parallel with Cycles 9 and 6–11. Must complete before Cycle 3 begins.</td>
</tr>
</tbody>
</table>
</section>
<section id="the-downsides" class="level2">
<h2 class="anchored" data-anchor-id="the-downsides">The Downsides</h2>
<p>A passing Cycle 2 does not validate trace volume or retention under mission load; that stress only appears during Cycles 9–2.</p>
</section>
<section id="the-road-not-taken" class="level2">
<h2 class="anchored" data-anchor-id="the-road-not-taken">The Road Not Taken</h2>
<p>Deferring observability to after Cycle 11 was rejected — a failure in Cycle 8 (dynamic physics) or Cycle 10 (score write) with no trace evidence requires rerunning the entire cycle with instrumentation added, doubling the debugging time.</p>
</section>
<section id="status" class="level2">
<h2 class="anchored" data-anchor-id="status">Status</h2>
<p>Status: In Progress (producer side complete 2026-05-07; verification pending)</p>
<p>The observability stack itself is deployed and running on Fly (machine <code>781ed59b437968</code> started, volume <code>observability_data</code> 10GB iad attached) per <code>verify_fly_state</code> workflow output. The producer side has now been wired in all three apps:</p>
<ul>
<li>✅ <a href="https://github.com/V-Sekai-fire/multiplayer-fabric-gateway/pull/8">gateway PR #8</a> — <code>:opentelemetry</code> deps + <code>gateway.dispatch</code> span around <code>Gateway.Router.handle/1</code></li>
<li>✅ <a href="https://github.com/V-Sekai-fire/multiplayer-fabric-zone-backend/pull/13">uro PR #13</a> — <code>:opentelemetry_phoenix</code> + <code>:opentelemetry_ecto</code> automatic instrumentation</li>
<li>✅ <a href="https://github.com/V-Sekai-fire/multiplayer-fabric-zone/pull/3">zone PR #3</a> — bootstrapped <code>project/main.gd</code> initializing the engine’s <code>module_open_telemetry</code>, emits <code>zone.boot</code> span</li>
</ul>
<p>All ship to <code>multiplayer-fabric-observability.internal:4318</code> (OTLP/HTTP over Fly’s 6PN). End-to-end verification runs via <a href="https://github.com/V-Sekai-fire/multiplayer-fabric-infra/blob/main/.github/workflows/verify_observability.yml"><code>.github/workflows/verify_observability.yml</code></a> on <code>multiplayer-fabric-infra</code> — uses <code>flyctl ssh console -C</code> to query the Victoria* APIs from inside the observability machine (the OTLP ports are intentionally private). Pending: trigger the verify workflow after redeploys land and confirm the cycle 1 ping span is visible in VictoriaTraces.</p>
</section>
<section id="decision-makers" class="level2">
<h2 class="anchored" data-anchor-id="decision-makers">Decision Makers</h2>
<ul>
<li>Lead Architect / Fabric Maintainer</li>
</ul>
</section>
<section id="tags" class="level2">
<h2 class="anchored" data-anchor-id="tags">Tags</h2>
<ul>
<li>maglev-cycle-2, observability, victoriatraces, victoriametrics, otel, galls-law, 20260506-maglev-cycle-2-observability, present-proposal-template</li>
</ul>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<pre><code>@techreport{20260506_observability_victoriatraces,
  title       = {Replace Jaeger with VictoriaTraces for trace storage},
  institution = {V-Sekai Fire},
  year        = {2026},
  type        = {Architecture Decision Record},
  note        = {decisions/20260506-observability-stack-victoriatraces.md}
}

@misc{v_sekai_2026,
  title = {V-Sekai},
  year  = {2026},
  url   = {https://v-sekai.org/}
}</code></pre>


</section>
</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-2-observability.html</guid>
  <pubDate>Thu, 07 May 2026 13:27:28 GMT</pubDate>
</item>
<item>
  <title></title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-12-game-planning.html</link>
  <description><![CDATA[ 





<section id="maglev-cycle-12-game-cycle-planning" class="level1">
<h1>Maglev Cycle 12: Game Cycle Planning</h1>
<section id="the-context" class="level2">
<h2 class="anchored" data-anchor-id="the-context">The Context</h2>
<p>Cycles 0–5 prove the networking, physics, and persistence layers. Cycle 9 is the first cycle to run a real physics scene with assets; by the time it passes, the team has actual frame budget data from zone-console, a working grab-ready physics scene, and the interaction system (<code>xr_controller_interaction_helper.gd</code>) half-integrated. That is the earliest point at which game cycle estimates are reliable.</p>
</section>
<section id="the-problem-statement" class="level2">
<h2 class="anchored" data-anchor-id="the-problem-statement">The Problem Statement</h2>
<p>Six game systems remain unbuilt for the vertical slice and have no prior baseline in this codebase. Estimating them before Cycle 9 passes produces numbers with no evidence. Cycle 12 produces scoped ADRs and estimates for each remaining system using the Cycle 9 scene as a measured baseline.</p>
</section>
<section id="design" class="level2">
<h2 class="anchored" data-anchor-id="design">Design</h2>
<p>Run Cycle 12 immediately after Cycle 9 passes. For each of the six systems below, produce one ADR following the present-proposal-template with a pass criteria checklist, CRIS score, and estimate derived from Cycle 9 frame budget and zone-console tick data.</p>
<table class="caption-top table">
<colgroup>
<col style="width: 20%">
<col style="width: 21%">
<col style="width: 57%">
</colgroup>
<thead>
<tr class="header">
<th>System</th>
<th>Depends on</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Drone AI</td>
<td>Cycle 9 scene</td>
<td>Pathfinding and attack behaviour in the zone server; no prior AI baseline</td>
</tr>
<tr class="even">
<td>Combat / health</td>
<td>Cycle 9 scene</td>
<td>Damage model, respawn, HUD; no prior baseline</td>
</tr>
<tr class="odd">
<td>Core grab mechanic</td>
<td>Cycle 9 scene + interaction system</td>
<td><code>xr_controller_interaction_helper.gd</code> is solved; needs wiring to rolling cores</td>
</tr>
<tr class="even">
<td>Slot-into-terminal interaction</td>
<td>Core grab</td>
<td>Win condition trigger; same interaction system path</td>
</tr>
<tr class="odd">
<td>3-minute timer and win/lose flow</td>
<td>Slot interaction</td>
<td>Game loop state machine; triggers Cycle 11 DB write</td>
</tr>
<tr class="even">
<td>Camera modes</td>
<td>Cycle 9 scene</td>
<td>PCVR tilt-shift diorama rig; Steam Deck isometric rig; same instance, different viewports</td>
</tr>
</tbody>
</table>
<p>Art asset production (train geometry, drone models, terminal, Quantum Data-Core models, VRM avatars with MToon shaders) is a parallel track owned by the art team. Cycle 12 produces the art brief and schedule alongside the engineering ADRs; it does not estimate or gate on art completion.</p>
<p>Pass criteria:</p>
<ul class="task-list">
<li><label><input type="checkbox">One ADR per system above, with pass criteria checklist and CRIS score</label></li>
<li><label><input type="checkbox">Each ADR includes a working-days estimate with a stated basis in Cycle 9 measurements</label></li>
<li><label><input type="checkbox">Art brief delivered to art team with asset list, MToon shader targets, and poly/texture budgets for both PCVR diorama and Steam Deck isometric viewports</label></li>
<li><label><input type="checkbox">Updated project timeline incorporating all six game cycles into the Maglev Intercept sequence</label></li>
</ul>
</section>
<section id="estimate" class="level2">
<h2 class="anchored" data-anchor-id="estimate">Estimate</h2>
<p><strong>3 days</strong> (2026-06-16 → 2026-06-19). Planning cycle only; no code. Requires Cycle 9 zone-console tick data and frame budget before it can begin.</p>
</section>
<section id="cris-score" class="level2">
<h2 class="anchored" data-anchor-id="cris-score">CRIS Score</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 9%">
<col style="width: 3%">
<col style="width: 86%">
</colgroup>
<thead>
<tr class="header">
<th>Factor</th>
<th>Score</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C</strong>omplexity</td>
<td>3</td>
<td>Writing ADRs and estimates is low effort; the inputs (Cycle 9 measurements, interaction system design) are well understood by then.</td>
</tr>
<tr class="even">
<td><strong>R</strong>reach</td>
<td>10</td>
<td>All six remaining game systems are unscoped until this cycle completes.</td>
</tr>
<tr class="odd">
<td><strong>I</strong>mpediment</td>
<td>8</td>
<td>Starting game dev without scoped ADRs risks scope creep and unattributable failures in a system with no prior game-logic baseline.</td>
</tr>
<tr class="even">
<td><strong>S</strong>takeholder</td>
<td>10</td>
<td>Game Director and art team both block on this cycle for production planning.</td>
</tr>
<tr class="odd">
<td><strong>Total</strong></td>
<td>7.75</td>
<td>Build immediately after Cycle 9 passes.</td>
</tr>
</tbody>
</table>
</section>
<section id="the-downsides" class="level2">
<h2 class="anchored" data-anchor-id="the-downsides">The Downsides</h2>
<p>Cycle 12 produces plans, not working software. A week of slippage in Cycle 9 delays the planning cycle by the same amount.</p>
</section>
<section id="the-road-not-taken" class="level2">
<h2 class="anchored" data-anchor-id="the-road-not-taken">The Road Not Taken</h2>
<p>Planning the game cycles now (before Cycle 9) was considered and rejected — estimates made without a running physics scene and real frame budget data have no evidence base.</p>
</section>
<section id="status" class="level2">
<h2 class="anchored" data-anchor-id="status">Status</h2>
<p>Status: Draft</p>
</section>
<section id="decision-makers" class="level2">
<h2 class="anchored" data-anchor-id="decision-makers">Decision Makers</h2>
<ul>
<li>Lead Architect / Fabric Maintainer</li>
<li>Game Director</li>
</ul>
</section>
<section id="tags" class="level2">
<h2 class="anchored" data-anchor-id="tags">Tags</h2>
<ul>
<li>maglev-cycle-12, game-planning, vertical-slice, galls-law, 20260506-maglev-cycle-12-game-planning, present-proposal-template</li>
</ul>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<pre><code>@misc{v_sekai_2026,
  title = {V-Sekai},
  year  = {2026},
  url   = {https://v-sekai.org/}
}</code></pre>


</section>
</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-12-game-planning.html</guid>
  <pubDate>Thu, 07 May 2026 13:27:28 GMT</pubDate>
</item>
<item>
  <title></title>
  <link>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-11-db-write.html</link>
  <description><![CDATA[ 





<section id="maglev-cycle-11-cockroachdb-score-write" class="level1">
<h1>Maglev Cycle 11: CockroachDB Score Write</h1>
<section id="the-context" class="level2">
<h2 class="anchored" data-anchor-id="the-context">The Context</h2>
<p>With causal ordering confirmed in Cycle 10 and the DB connection verified in Cycle 4, Cycle 11 activates persistence: the persona zone commits the score and <code>multiplayer-fabric-uro</code> writes it to CockroachDB.</p>
</section>
<section id="the-problem-statement" class="level2">
<h2 class="anchored" data-anchor-id="the-problem-statement">The Problem Statement</h2>
<p>The cross-zone write path — persona zone commits, uro writes via Ecto over Fly’s 6PN using the <code>gateway_writer</code> role — requires end-to-end validation. With causal ordering confirmed in Cycle 10, the only remaining unknown is whether the database write path performs correctly under mission load.</p>
</section>
<section id="design" class="level2">
<h2 class="anchored" data-anchor-id="design">Design</h2>
<p>On each core-slot event the persona zone commits the score update after the <code>VClock.le</code> check passes. On mission end <code>multiplayer-fabric-uro</code> writes the committed score to CockroachDB via Ecto over Fly’s 6PN using the <code>gateway_writer</code> role. <code>RelReplica</code> entries stamped with <code>sentAt</code> are broadcast to the interest band.</p>
<p>Write path:</p>
<pre><code>spatial zone  →  QueueOp(VClock)  →  persona zone commits
              →  uro → CockroachDB (gateway_writer, Fly 6PN)
              →  RelReplica(sentAt) broadcast to interest band</code></pre>
<p>Pass criteria:</p>
<ul class="task-list">
<li><label><input type="checkbox">Committed score appears in CockroachDB within one tick of mission end</label></li>
<li><label><input type="checkbox"><code>RelReplica.stale</code> correctly reflects the write on all nodes in the interest band</label></li>
<li><label><input type="checkbox">No write occurs from any zone other than the persona authority</label></li>
</ul>
</section>
<section id="estimate" class="level2">
<h2 class="anchored" data-anchor-id="estimate">Estimate</h2>
<p><strong>5 days</strong> (2026-06-30 → 2026-07-07). The Ecto write path to CockroachDB is proven in Cycle 4; the work is the persona zone commit flow, VClock gating on the write side, and RelReplica broadcast. No prior end-to-end causal write exists in the history.</p>
</section>
<section id="cris-score" class="level2">
<h2 class="anchored" data-anchor-id="cris-score">CRIS Score</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 11%">
<col style="width: 3%">
<col style="width: 84%">
</colgroup>
<thead>
<tr class="header">
<th>Factor</th>
<th>Score</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C</strong>omplexity</td>
<td>6</td>
<td>The Ecto write path to CockroachDB over Fly’s 6PN under concurrent mission load is untested in this codebase.</td>
</tr>
<tr class="even">
<td><strong>R</strong>each</td>
<td>10</td>
<td>Persistent player progression requires this path.</td>
</tr>
<tr class="odd">
<td><strong>I</strong>mpediment</td>
<td>8</td>
<td>A broken score write does not block Cycle 10 gameplay but blocks any feature that depends on persistent state.</td>
</tr>
<tr class="even">
<td><strong>S</strong>takeholder</td>
<td>10</td>
<td>Required for the full Maglev Intercept scenario.</td>
</tr>
<tr class="odd">
<td><strong>Total</strong></td>
<td>8.0</td>
<td>Build after Cycles 10 and 9 pass.</td>
</tr>
</tbody>
</table>
</section>
<section id="the-downsides" class="level2">
<h2 class="anchored" data-anchor-id="the-downsides">The Downsides</h2>
<p>If the persona zone goes down, that player’s attributes are offline until it recovers. Replication factor ≥ 2 on the persona partition is the mitigation, deferred to a later cycle.</p>
</section>
<section id="the-road-not-taken" class="level2">
<h2 class="anchored" data-anchor-id="the-road-not-taken">The Road Not Taken</h2>
<p>Writing scores directly from the spatial zone to CockroachDB was considered. Rejected — it violates <code>DisjointRanges</code> and allows concurrent writes to the same player record.</p>
</section>
<section id="status" class="level2">
<h2 class="anchored" data-anchor-id="status">Status</h2>
<p>Status: Draft</p>
</section>
<section id="decision-makers" class="level2">
<h2 class="anchored" data-anchor-id="decision-makers">Decision Makers</h2>
<ul>
<li>Lead Architect / Fabric Maintainer</li>
</ul>
</section>
<section id="tags" class="level2">
<h2 class="anchored" data-anchor-id="tags">Tags</h2>
<ul>
<li>maglev-cycle-11, db-write, persona-zone, cockroachdb, galls-law, 20260506-maglev-cycle-11-db-write, present-proposal-template</li>
</ul>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<pre><code>@misc{v_sekai_2026,
  title = {V-Sekai},
  year  = {2026},
  url   = {https://v-sekai.org/}
}</code></pre>


</section>
</section>

 ]]></description>
  <guid>https://v-sekai-fire.github.io/manuals/decisions/20260506-maglev-cycle-11-db-write.html</guid>
  <pubDate>Thu, 07 May 2026 13:27:28 GMT</pubDate>
</item>
</channel>
</rss>
