design: replace sqlite3 in the eco replay with a C#-on-Linux-amenable DB (broke the deploy) #88

Open
opened 2026-07-06 17:25:43 +00:00 by coilysiren · 1 comment
Owner

Incident + direction (Kai)

Last night the eco replay deploy broke on a sqlite3 Linux compat issue. Kai's steer: "why don't we just use whatever database type is most amenable to C# on Linux? we've discovered that C# is not the answer."

This is a design brief, not an implementation ticket - investigate and post a concrete recommendation as a comment for Kai to approve. Do not migrate anything yet.

The ambiguity to resolve (flag it explicitly in your answer)

"C# is not the answer" reads two ways, and the recommendation differs sharply:

  • (i) The DB path is the dead end, stay in C# - the failure is sqlite-native-interop on the Linux image (Microsoft.Data.Sqlite / SQLitePCLRaw needs a native e_sqlite3.so that is not present or ABI-mismatched in the deploy container). Fix = pick a DB with zero native-lib dependency so it "just works" under .NET on Linux.
  • (ii) Reconsider C# for the replay entirely - if the replay is C# only to reuse Eco's game DLLs and that is itself the source of the Linux pain, the DB swap is a band-aid.

Diagnose which one Kai is actually hitting, with evidence from the code + the deploy break, and recommend accordingly.

Investigate

  1. Locate the eco replay - which component/service it is (likely within coilyco-gaming/eco-app; confirm, and say so if it lives elsewhere), and its deploy path (the services/eco-app/** bundle in coilyco-bridge/deploy, or a sibling).
  2. Root-cause the sqlite3 Linux break - is it a missing/mismatched native SQLite lib in the container image, a build-arch issue, a file-locking/:memory: path issue, or a driver version? Pin the actual failure, not a guess.
  3. Weigh the DB options for C#-on-Linux with the no-native-lib lens:
    • PostgreSQL via Npgsql - fully managed driver, no native lib, first-class on Linux, already in the homelab (external-secrets + k8s). Strong default if the replay needs a real relational store.
    • LiteDB / a pure-C# embedded store - no native lib, single-file, closest drop-in to an embedded sqlite if the replay just needs local persistence.
    • Fix sqlite in place - SQLitePCLRaw.bundle_e_sqlite3 ships the Linux native; sometimes the break is just a missing bundle package. Cheapest if the replay is otherwise fine.
    • Note how Kai's parallel "most pages are just data, only world/region is visual" simplification (sibling eco-app issue) affects the replay's data needs - if replay data is being de-emphasized, the store may shrink or disappear.

Deliverable

A comment with: the pinned root cause, the resolved read on the C# ambiguity, a recommended persistence choice (+ a short migration sketch and blast radius), and the follow-up implementation issue(s) to file. If the answer is "just add the SQLitePCLRaw bundle," say so plainly - the cheapest correct fix wins.

## Incident + direction (Kai) Last night the **eco replay deploy broke on a sqlite3 Linux compat issue**. Kai's steer: *"why don't we just use whatever database type is most amenable to C# on Linux? we've discovered that C# is not the answer."* This is a **design brief, not an implementation ticket** - investigate and post a concrete recommendation as a comment for Kai to approve. **Do not migrate anything yet.** ## The ambiguity to resolve (flag it explicitly in your answer) "C# is not the answer" reads two ways, and the recommendation differs sharply: - **(i) The DB path is the dead end, stay in C#** - the failure is sqlite-native-interop on the Linux image (Microsoft.Data.Sqlite / SQLitePCLRaw needs a native `e_sqlite3.so` that is not present or ABI-mismatched in the deploy container). Fix = pick a DB with **zero native-lib dependency** so it "just works" under .NET on Linux. - **(ii) Reconsider C# for the replay entirely** - if the replay is C# only to reuse Eco's game DLLs and that is itself the source of the Linux pain, the DB swap is a band-aid. Diagnose which one Kai is actually hitting, with evidence from the code + the deploy break, and recommend accordingly. ## Investigate 1. **Locate the eco replay** - which component/service it is (likely within [coilyco-gaming/eco-app](https://forgejo.coilysiren.me/coilyco-gaming/eco-app); confirm, and say so if it lives elsewhere), and its deploy path (the `services/eco-app/**` bundle in coilyco-bridge/deploy, or a sibling). 2. **Root-cause the sqlite3 Linux break** - is it a missing/mismatched native SQLite lib in the container image, a build-arch issue, a file-locking/`:memory:` path issue, or a driver version? Pin the actual failure, not a guess. 3. **Weigh the DB options for C#-on-Linux** with the no-native-lib lens: - **PostgreSQL via Npgsql** - fully managed driver, no native lib, first-class on Linux, already in the homelab (external-secrets + k8s). Strong default if the replay needs a real relational store. - **LiteDB / a pure-C# embedded store** - no native lib, single-file, closest drop-in to an embedded sqlite if the replay just needs local persistence. - **Fix sqlite in place** - `SQLitePCLRaw.bundle_e_sqlite3` ships the Linux native; sometimes the break is just a missing bundle package. Cheapest if the replay is otherwise fine. - Note how Kai's parallel **"most pages are just data, only world/region is visual"** simplification (sibling eco-app issue) affects the replay's data needs - if replay data is being de-emphasized, the store may shrink or disappear. ## Deliverable A comment with: the pinned root cause, the resolved read on the C# ambiguity, a recommended persistence choice (+ a short migration sketch and blast radius), and the follow-up implementation issue(s) to file. If the answer is "just add the SQLitePCLRaw bundle," say so plainly - the cheapest correct fix wins.
Member

🔎 ward agent advisor

ward agent advisor --driver claude ran a one-shot standard research pass on this question:

Diagnose the eco replay sqlite3 Linux compat break and recommend a C#-on-Linux-amenable persistence layer. Resolve the 'C# is not the answer' ambiguity with evidence: is this sqlite native-interop on the Linux image (fix = no-native-lib DB, stay C#) or a reason to reconsider C# for the replay? Pin the actual root cause, weigh Postgres/Npgsql vs a pure-C# embedded store vs just adding the SQLitePCLRaw native bundle, and post a concrete recommendation + follow-up implementation issues as a comment. Design only, do not migrate.


Diagnosis: this is native-SQLite interop on the Linux Eco server, not a reason to leave C#

Where the eco replay actually lives

The replay is two pieces in this repo (coilyco-gaming/eco-app), confirmed in docs/replay/README.md:

  1. The C# Eco mod (mods/replay/src/) — EcoReplayPlugin implements IGameActionAware, receives every GameAction, and appends to SQLite via Microsoft.Data.Sqlite (EventStore.cs). It runs in-process inside the live Eco game server and is shipped out of band — it is explicitly not in the eco-app Docker image (.forgejo/workflows/build-publish.yml mods: job comment: "shipped to the game server OUT OF BAND … NOT in the eco-app image").
  2. The Python reader (src/eco_replay/main.py) — a thin FastAPI re-server mounted at /replay/api in the fused service. It reads the mod's data one of three ways: the SQLite file directly via stdlib sqlite3 (ECO_REPLAY_DB), the mod's HTTP endpoint (UPSTREAM_URL), or mock data.

The break is on the C# side. The eco-app container is python:3.13 (Dockerfile) — stdlib sqlite3 there is statically linked, has no native-lib gap, and did not break. The thing that "broke the deploy" is the mod loading libe_sqlite3.so inside the Eco server.

Pinned root cause

This is a recurrence of eco-app#71, not a new class of bug. The evidence chain:

  • Microsoft.Data.SqliteSQLitePCLRaw.bundle_e_sqlite3 needs a native libe_sqlite3.so dlopen'd at first use (Batteries_V2.Init).
  • Eco loads mods via AssemblyLoadContext.Default.LoadFromStream, and the Eco server ships as a single-file .NET bundle, so the default native resolver searches only the bundle extraction dir (~/.net/EcoServer/<hash>/), never the mod folder or its runtimes/linux-x64/native/. #71's fix was an elaborate DllImportResolver registered on the provider assembly (SQLite3Provider_e_sqlite3) that probes modDir and modDir/runtimes/linux-x64/native/ for the .so (see EcoReplayPlugin.InstallNativeLibraryResolver, and the #71 commit c2bef47).
  • That resolver only works if the .so is physically present in one of those probed paths. The most likely #88 trigger: the out-of-band ship copied EcoReplay.dll (and its managed deps) but not the runtimes/linux-x64/native/libe_sqlite3.so sibling that dotnet build emits under bin/Release/net10.0/. With the file absent, every File.Exists candidate misses, the resolver returns IntPtr.Zero, default resolution runs, dlopen fails → DllNotFoundExceptioncrash-loop on server start (exactly the #71 failure mode). A secondary candidate is an Eco server runtime bump changing the bundle extraction layout and re-defeating the resolver — same root class either way.

This is a moving target. #71 already patched the interop once; #88 is the second break. Chasing a native .so staged into a mod folder that gets reloaded through LoadFromStream into a single-file bundle is fundamentally fragile, and every Eco server update can re-break it. That is the real signal in Kai's steer.

Resolving the "C# is not the answer" ambiguity → it's reading (i)

Interpretation (ii) — "reconsider C# for the replay entirely" — is not on the table for the recorder. The recorder must be a C# Eco plugin: it implements IGameActionAware and receives GameAction objects in-process inside the game server. No other language can subscribe to that firehose — there is no non-C# way to write this half. The Python half already is the non-C# piece, and it's fine.

So Kai is hitting (i): the native-DB path is the dead end, the mod stays C#. "C# is not the answer" means don't make a C# mod drive a native-code SQLite inside the Eco bundle — not rewrite the recorder. The fix is to pick a persistence layer with zero native dependency.

Weighing the options (no-native-lib lens)

  • Re-add / re-stage the SQLitePCLRaw native bundle (fix in place). This is the cheapest mechanical fix and #71 already shipped the resolver + bundle_e_sqlite3. If the only defect is that the ship step drops runtimes/linux-x64/native/libe_sqlite3.so, fixing the ship manifest unblocks the deploy today. But it is the exact band-aid Kai just rejected: it keeps the native dependency and the second break proves it's not durable. Use only as an emergency hotfix, not the strategy.
  • PostgreSQL via Npgsql. Npgsql is 100% managed, no native lib, first-class on Linux, and Postgres is already in the homelab (external-secrets + k8s). It cleanly serves both sides: the mod writes over the network, the Python reader reads over the network — which also eliminates the current file-sharing coupling (today ECO_REPLAY_DB needs the app container to see the game server's filesystem). It keeps indexed queries (filter by citizen/type/since, ORDER BY id DESC LIMIT ≤1000) at any volume. Cost: the game server now needs network + a credential to Postgres, a Postgres outage becomes a write path failure (the store already tolerates + drops write errors, so this degrades gracefully), and it needs a matching change in coilyco-bridge/deploy (a DB + ExternalSecret). Strong default if replay stays a real feature.
  • LiteDB / pure-C# embedded store. Zero native lib, single file, keeps the "rides Eco's Storage/ backup loop for free" property. But it breaks the Python direct-file read contract (src/eco_replay/main.py opens the file with stdlib sqlite3; LiteDB's BSON format is unreadable by sqlite3, and there's no solid Python LiteDB reader). Choosing LiteDB forces the Python side onto the UPSTREAM_URL HTTP path only. Workable, but it trades one interop headache for a read-contract rewrite with less upside than Postgres.
  • Append-only JSONL (pure managed, no DB at all). The mod already references Newtonsoft.Json; writing newline-delimited JSON to Storage/EcoReplay.jsonl is zero-dependency, keeps the single-file-rides-backup property, and is trivially readable by both the mod's own HTTP endpoint and the Python reader (swap sqlite3 for line reads). The truest expression of "pick whatever is most amenable to C#-on-Linux" — the most amenable DB is no native DB. Cost: no indexes, so a query is a reverse file scan; fine at homelab volume with LIMIT ≤1000, but degrades if the event log grows large.

The "most pages are just data, only world/region is visual" simplification matters here

That sibling steer de-emphasizes replay data and argues against standing up dedicated Postgres infra for it. If replay is shrinking toward a low-traffic, possibly-optional surface, the JSONL path is the proportionate answer; if replay stays a first-class queryable feature, Postgres is worth the deploy wiring.

Recommendation

Drop Microsoft.Data.Sqlite from the mod. Pick by whether replay stays a real feature:

  • Default (replay stays first-class): PostgreSQL via Npgsql. Pure-managed, no native lib, already in the homelab, decouples the game host from the app container's filesystem, keeps indexed queries. This is the durable end of the recurring native-interop pain.
  • If replay is being de-emphasized per the sibling simplification: append-only JSONL. Pure-managed, zero dependency, cross-readable by C# and Python, smallest blast radius.
  • Reject LiteDB (breaks the Python sqlite3 read contract for no net gain over the two above) and reject "just re-add the bundle" as the strategy (it's the band-aid #71 already tried; offer it only as a same-day hotfix if the deploy must be unblocked before the swap lands).

Kai's call to make: first-class replay (→ Postgres) vs de-emphasized replay (→ JSONL). I lean JSONL given the "most pages are just data" steer plus the fact that the recorder's needs are genuinely just append + bounded filtered reads — but Postgres is the right answer the moment replay wants real query scale.

Migration sketch + blast radius

Both options are contained to coilyco-gaming/eco-app (the mod and its Python reader live in the same repo), plus a deploy-repo change only if Postgres is chosen.

  • JSONL path: rewrite EventStore.cs to append serialized rows to Storage/EcoReplay.jsonl (keep the existing bounded-channel + background-writer design — it maps cleanly to batched line appends; keep Query() as a bounded reverse scan). Update src/eco_replay/main.py _fetch_from_db/_stats_from_db to read the JSONL file instead of sqlite3. Drop the Microsoft.Data.Sqlite PackageReference and the entire InstallNativeLibraryResolver block. No deploy-repo change (no new infra). Update docs/replay/README.md and docs/FEATURES.md.
  • Postgres path: rewrite EventStore.cs to Npgsql (schema is the same events table; the batched-transaction writer ports directly), take a connection string from mod config/env. Point src/eco_replay/main.py at Postgres (swap sqlite3 for psycopg, or read exclusively via UPSTREAM_URL). Matching change in coilyco-bridge/deploy (services/eco-app/**): a Postgres instance/DB + an ExternalSecret for the credential, per the AGENTS.md cross-repo contract. Update the docs.

Follow-up implementation issues to file (after Kai approves a direction — do NOT migrate yet)

All are in coilyco-gaming/eco-app unless noted; I'm holding them until Kai picks JSONL vs Postgres so we don't file work for the rejected branch:

  1. coilyco-gaming/eco-app: swap the replay mod off native SQLite to . Rewrite EventStore.cs, drop Microsoft.Data.Sqlite + the native resolver, keep the bounded-channel writer. Depends on Kai's direction; unblocks #2 and #3.
  2. coilyco-gaming/eco-app: point the Python reader (src/eco_replay/main.py) at the new store. Depends on #1's storage format being locked.
  3. (Postgres branch only) coilyco-bridge/deploy: provision Postgres + ExternalSecret for eco-app replay under services/eco-app/**. Depends on #1 defining the connection contract; can proceed in parallel once the schema/DSN shape is fixed.
  4. (Optional, orthogonal) coilyco-gaming/eco-app: harden the out-of-band mod ship step so a mod's runtimes/** natives can't be silently dropped — captures the immediate #88 trigger regardless of which store wins, and de-risks any future native dep.

If the deploy must be unblocked today before the swap lands, the emergency hotfix is: ensure runtimes/linux-x64/native/libe_sqlite3.so is actually staged next to EcoReplay.dll on the game server (the path #71's resolver probes). That is the cheapest correct stopgap — but it is a stopgap, and the durable answer is dropping the native dependency.


Researched and posted automatically by ward agent advisor --driver claude (ward#179). This is one-shot research, not a carried change - verify before acting on it.

— Claude (she/her), via ward agent

### 🔎 ward agent advisor `ward agent advisor --driver claude` ran a one-shot **standard** research pass on this question: > Diagnose the eco replay sqlite3 Linux compat break and recommend a C#-on-Linux-amenable persistence layer. Resolve the 'C# is not the answer' ambiguity with evidence: is this sqlite native-interop on the Linux image (fix = no-native-lib DB, stay C#) or a reason to reconsider C# for the replay? Pin the actual root cause, weigh Postgres/Npgsql vs a pure-C# embedded store vs just adding the SQLitePCLRaw native bundle, and post a concrete recommendation + follow-up implementation issues as a comment. Design only, do not migrate. --- ## Diagnosis: this is native-SQLite interop on the Linux Eco server, not a reason to leave C# ### Where the eco replay actually lives The replay is **two pieces in this repo** (`coilyco-gaming/eco-app`), confirmed in `docs/replay/README.md`: 1. **The C# Eco mod** (`mods/replay/src/`) — `EcoReplayPlugin` implements `IGameActionAware`, receives every `GameAction`, and appends to SQLite via `Microsoft.Data.Sqlite` (`EventStore.cs`). It runs **in-process inside the live Eco game server** and is shipped **out of band** — it is explicitly *not* in the eco-app Docker image (`.forgejo/workflows/build-publish.yml` `mods:` job comment: "shipped to the game server OUT OF BAND … NOT in the eco-app image"). 2. **The Python reader** (`src/eco_replay/main.py`) — a thin FastAPI re-server mounted at `/replay/api` in the fused service. It reads the mod's data one of three ways: the SQLite file directly via stdlib `sqlite3` (`ECO_REPLAY_DB`), the mod's HTTP endpoint (`UPSTREAM_URL`), or mock data. **The break is on the C# side.** The eco-app container is `python:3.13` (Dockerfile) — stdlib `sqlite3` there is statically linked, has no native-lib gap, and did not break. The thing that "broke the deploy" is the mod loading `libe_sqlite3.so` inside the Eco server. ### Pinned root cause This is a **recurrence of eco-app#71**, not a new class of bug. The evidence chain: - `Microsoft.Data.Sqlite` → `SQLitePCLRaw.bundle_e_sqlite3` needs a native `libe_sqlite3.so` dlopen'd at first use (`Batteries_V2.Init`). - Eco loads mods via `AssemblyLoadContext.Default.LoadFromStream`, and the Eco server ships as a **single-file .NET bundle**, so the default native resolver searches only the bundle extraction dir (`~/.net/EcoServer/<hash>/`), never the mod folder or its `runtimes/linux-x64/native/`. #71's fix was an elaborate `DllImportResolver` registered on the provider assembly (`SQLite3Provider_e_sqlite3`) that probes `modDir` and `modDir/runtimes/linux-x64/native/` for the `.so` (see `EcoReplayPlugin.InstallNativeLibraryResolver`, and the #71 commit `c2bef47`). - That resolver only works **if the `.so` is physically present in one of those probed paths**. The most likely #88 trigger: the out-of-band ship copied `EcoReplay.dll` (and its managed deps) but **not the `runtimes/linux-x64/native/libe_sqlite3.so` sibling** that `dotnet build` emits under `bin/Release/net10.0/`. With the file absent, every `File.Exists` candidate misses, the resolver returns `IntPtr.Zero`, default resolution runs, `dlopen` fails → `DllNotFoundException` → **crash-loop on server start** (exactly the #71 failure mode). A secondary candidate is an Eco server runtime bump changing the bundle extraction layout and re-defeating the resolver — same root class either way. **This is a moving target.** #71 already patched the interop once; #88 is the second break. Chasing a native `.so` staged into a mod folder that gets reloaded through `LoadFromStream` into a single-file bundle is fundamentally fragile, and every Eco server update can re-break it. That is the real signal in Kai's steer. ### Resolving the "C# is not the answer" ambiguity → it's reading (i) Interpretation **(ii) — "reconsider C# for the replay entirely" — is not on the table for the recorder.** The recorder *must* be a C# Eco plugin: it implements `IGameActionAware` and receives `GameAction` objects in-process inside the game server. No other language can subscribe to that firehose — there is no non-C# way to write this half. The Python half already is the non-C# piece, and it's fine. So Kai is hitting **(i): the native-DB path is the dead end, the mod stays C#.** "C# is not the answer" means *don't make a C# mod drive a native-code SQLite inside the Eco bundle* — not *rewrite the recorder*. The fix is to pick a persistence layer with **zero native dependency**. ### Weighing the options (no-native-lib lens) - **Re-add / re-stage the SQLitePCLRaw native bundle (fix in place).** This is the cheapest *mechanical* fix and #71 already shipped the resolver + `bundle_e_sqlite3`. If the only defect is that the ship step drops `runtimes/linux-x64/native/libe_sqlite3.so`, fixing the ship manifest unblocks the deploy today. **But** it is the exact band-aid Kai just rejected: it keeps the native dependency and the second break proves it's not durable. **Use only as an emergency hotfix, not the strategy.** - **PostgreSQL via Npgsql.** Npgsql is 100% managed, no native lib, first-class on Linux, and Postgres is already in the homelab (external-secrets + k8s). It cleanly serves **both** sides: the mod writes over the network, the Python reader reads over the network — which also **eliminates the current file-sharing coupling** (today `ECO_REPLAY_DB` needs the app container to see the game server's filesystem). It keeps indexed queries (filter by citizen/type/since, `ORDER BY id DESC LIMIT ≤1000`) at any volume. Cost: the game server now needs network + a credential to Postgres, a Postgres outage becomes a write path failure (the store already tolerates + drops write errors, so this degrades gracefully), and it needs a matching change in `coilyco-bridge/deploy` (a DB + ExternalSecret). **Strong default if replay stays a real feature.** - **LiteDB / pure-C# embedded store.** Zero native lib, single file, keeps the "rides Eco's `Storage/` backup loop for free" property. **But it breaks the Python direct-file read contract** (`src/eco_replay/main.py` opens the file with stdlib `sqlite3`; LiteDB's BSON format is unreadable by `sqlite3`, and there's no solid Python LiteDB reader). Choosing LiteDB forces the Python side onto the `UPSTREAM_URL` HTTP path only. Workable, but it trades one interop headache for a read-contract rewrite with less upside than Postgres. - **Append-only JSONL (pure managed, no DB at all).** The mod already references `Newtonsoft.Json`; writing newline-delimited JSON to `Storage/EcoReplay.jsonl` is zero-dependency, keeps the single-file-rides-backup property, and is trivially readable by *both* the mod's own HTTP endpoint and the Python reader (swap `sqlite3` for line reads). The truest expression of "pick whatever is most amenable to C#-on-Linux" — the most amenable DB is no native DB. Cost: no indexes, so a query is a reverse file scan; fine at homelab volume with `LIMIT ≤1000`, but degrades if the event log grows large. ### The "most pages are just data, only world/region is visual" simplification matters here That sibling steer **de-emphasizes replay data** and argues *against* standing up dedicated Postgres infra for it. If replay is shrinking toward a low-traffic, possibly-optional surface, the JSONL path is the proportionate answer; if replay stays a first-class queryable feature, Postgres is worth the deploy wiring. ### Recommendation **Drop `Microsoft.Data.Sqlite` from the mod. Pick by whether replay stays a real feature:** - **Default (replay stays first-class): PostgreSQL via Npgsql.** Pure-managed, no native lib, already in the homelab, decouples the game host from the app container's filesystem, keeps indexed queries. This is the durable end of the recurring native-interop pain. - **If replay is being de-emphasized per the sibling simplification: append-only JSONL.** Pure-managed, zero dependency, cross-readable by C# and Python, smallest blast radius. - **Reject** LiteDB (breaks the Python `sqlite3` read contract for no net gain over the two above) and reject "just re-add the bundle" as the *strategy* (it's the band-aid #71 already tried; offer it only as a same-day hotfix if the deploy must be unblocked before the swap lands). **Kai's call to make:** first-class replay (→ Postgres) vs de-emphasized replay (→ JSONL). I lean **JSONL** given the "most pages are just data" steer plus the fact that the recorder's needs are genuinely just append + bounded filtered reads — but Postgres is the right answer the moment replay wants real query scale. ### Migration sketch + blast radius Both options are **contained to `coilyco-gaming/eco-app`** (the mod and its Python reader live in the same repo), plus a deploy-repo change **only if Postgres is chosen**. - **JSONL path:** rewrite `EventStore.cs` to append serialized rows to `Storage/EcoReplay.jsonl` (keep the existing bounded-channel + background-writer design — it maps cleanly to batched line appends; keep `Query()` as a bounded reverse scan). Update `src/eco_replay/main.py` `_fetch_from_db`/`_stats_from_db` to read the JSONL file instead of `sqlite3`. Drop the `Microsoft.Data.Sqlite` PackageReference and the entire `InstallNativeLibraryResolver` block. No deploy-repo change (no new infra). Update `docs/replay/README.md` and `docs/FEATURES.md`. - **Postgres path:** rewrite `EventStore.cs` to `Npgsql` (schema is the same `events` table; the batched-transaction writer ports directly), take a connection string from mod config/env. Point `src/eco_replay/main.py` at Postgres (swap `sqlite3` for `psycopg`, or read exclusively via `UPSTREAM_URL`). **Matching change in `coilyco-bridge/deploy` (`services/eco-app/**`): a Postgres instance/DB + an ExternalSecret for the credential**, per the AGENTS.md cross-repo contract. Update the docs. ### Follow-up implementation issues to file (after Kai approves a direction — do NOT migrate yet) All are in `coilyco-gaming/eco-app` unless noted; I'm holding them until Kai picks JSONL vs Postgres so we don't file work for the rejected branch: 1. **`coilyco-gaming/eco-app`: swap the replay mod off native SQLite to <chosen store>.** Rewrite `EventStore.cs`, drop `Microsoft.Data.Sqlite` + the native resolver, keep the bounded-channel writer. Depends on Kai's direction; unblocks #2 and #3. 2. **`coilyco-gaming/eco-app`: point the Python reader (`src/eco_replay/main.py`) at the new store.** Depends on #1's storage format being locked. 3. **(Postgres branch only) `coilyco-bridge/deploy`: provision Postgres + ExternalSecret for eco-app replay under `services/eco-app/**`.** Depends on #1 defining the connection contract; can proceed in parallel once the schema/DSN shape is fixed. 4. **(Optional, orthogonal) `coilyco-gaming/eco-app`: harden the out-of-band mod ship step** so a mod's `runtimes/**` natives can't be silently dropped — captures the immediate #88 trigger regardless of which store wins, and de-risks any future native dep. If the deploy must be unblocked **today** before the swap lands, the emergency hotfix is: ensure `runtimes/linux-x64/native/libe_sqlite3.so` is actually staged next to `EcoReplay.dll` on the game server (the path #71's resolver probes). That is the cheapest correct stopgap — but it is a stopgap, and the durable answer is dropping the native dependency. --- Researched and posted automatically by `ward agent advisor --driver claude` (ward#179). This is one-shot research, not a carried change - verify before acting on it. <!-- ward-agent-reply --> <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
coilyco-ops added
P3
and removed
P2
labels 2026-07-10 09:00:48 +00:00
Sign in to join this conversation.
No description provided.