scan agreed — present: 0 games. Nothing in this repo was wrong. The parsing, the ids and the launch recipes were right all along.
The kit's openReadOnly built a file:<path>?immutable=1 URI — correct intent, since immutable=1 is what stops a scan locking a running Lutris's pga.db — but opened it with { readonly: true }, which does not enable SQLite's URI filename parsing. On Linux (Bun's bundled SQLite, unlike macOS's system build) that open always threw SQLiteError: unable to open database file. Every layer then degrades an open failure to "this launcher isn't installed", so the failure was invisible: withReadOnlyDb(...) ?? [] returned an empty library, while detect cheerfully reported present because it only stats the file.
Fixed in punktfunk#78, published as plugin-kit 0.3.1.
Why a lockfile change is needed
package.json already ranged ^0.3.0, so the published plugin would have resolved 0.3.1 on an operator's install anyway — but bun.lock pinned 0.3.0 exactly, so CI kept testing against the broken reader.
Parity, with the published kit
Re-run on .21 against a live host using the published 0.3.1 (a clean install, not the patched copy used while debugging), with this plugin still unregistered so the host was on its built-in scanner:
The parity sample is n=1 — .21 has exactly one Lutris game (Ubisoft Connect, wine runner). It proves the reader works and the id/title/launch/role/meta shapes match, but it is one title, not a library.
Art is compared by presence, not value (a data: URL legitimately becomes a file:// path), so the covers still want one spot-check by eye.
After merge
Tag v0.1.0 to publish — this plugin has never been released, so the version already in package.json is the first one, and ci.yml's publish job is gated on refs/tags/v*.
## This plugin has never returned a game
Running this repo's own release gate against a live host on `.21` (Lutris 0.5.22, one game):
```
parity FAILED — 0 identical, 1 missing, 0 unexpected, 0 changed
missing: lutris:1 Ubisoft Connect
```
`scan` agreed — `present: 0 games`. **Nothing in this repo was wrong.** The parsing, the ids and the launch recipes were right all along.
The kit's `openReadOnly` built a `file:<path>?immutable=1` URI — correct intent, since `immutable=1` is what stops a scan locking a running Lutris's `pga.db` — but opened it with `{ readonly: true }`, which does **not** enable SQLite's URI filename parsing. On Linux (Bun's bundled SQLite, unlike macOS's system build) that open always threw `SQLiteError: unable to open database file`. Every layer then degrades an open failure to "this launcher isn't installed", so the failure was invisible: `withReadOnlyDb(...) ?? []` returned an empty library, while `detect` cheerfully reported `present` because it only stats the file.
Fixed in [punktfunk#78](https://git.unom.io/unom/punktfunk/pulls/78), published as **plugin-kit 0.3.1**.
## Why a lockfile change is needed
`package.json` already ranged `^0.3.0`, so the *published* plugin would have resolved 0.3.1 on an operator's install anyway — but `bun.lock` pinned `0.3.0` exactly, so CI kept testing against the broken reader.
## Parity, with the published kit
Re-run on `.21` against a live host using the **published** 0.3.1 (a clean install, not the patched copy used while debugging), with this plugin still unregistered so the host was on its built-in scanner:
| | before | after |
|---|---|---|
| `scan` | `present: 0 games` | **`present: 1 games, 1 launcher entries`** |
| `parity --compare` | `FAILED — 1 missing` | **`OK — 1 entries identical`** |
| exit code | 0 (the gate could not fail — also fixed in #78) | 0, correctly |
Gates: biome clean, `tsc --noEmit` clean, 5/5 tests, bundle builds.
## Honest limits
- The parity sample is **n=1** — `.21` has exactly one Lutris game (Ubisoft Connect, wine runner). It proves the reader works and the id/title/launch/role/meta shapes match, but it is one title, not a library.
- Art is compared by presence, not value (a `data:` URL legitimately becomes a `file://` path), so the covers still want one spot-check by eye.
## After merge
Tag **`v0.1.0`** to publish — this plugin has never been released, so the version already in `package.json` is the first one, and `ci.yml`'s `publish` job is gated on `refs/tags/v*`.
The kit's `openReadOnly` built a `file:<path>?immutable=1` URI but opened it with
`{ readonly: true }`, which does not enable SQLite's URI filename parsing. On
Linux — Bun's bundled SQLite, unlike macOS's system one — that open always threw,
and every layer degrades an open failure to "this launcher isn't installed". So
this plugin reported 0 games on every box it has ever run on, while `detect`
happily said "present" (it only stats the file).
Nothing here was wrong; the parsing and the ids were right all along. Fixed in
punktfunk#78, published as plugin-kit 0.3.1.
The caret range already allowed it, but bun.lock pinned 0.3.0 exactly, so CI kept
testing against the broken reader.
Parity, run on .21 against a live host with the PUBLISHED 0.3.1 (not a patched
copy) — the gate that caught this in the first place:
scan: present: 1 games, 1 launcher entries (was 0 games)
parity: OK — 1 entries identical (was: FAILED — 1 missing)
Gates: biome clean, tsc clean, 5/5 tests, bundle builds.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
This plugin has never returned a game
Running this repo's own release gate against a live host on
.21(Lutris 0.5.22, one game):scanagreed —present: 0 games. Nothing in this repo was wrong. The parsing, the ids and the launch recipes were right all along.The kit's
openReadOnlybuilt afile:<path>?immutable=1URI — correct intent, sinceimmutable=1is what stops a scan locking a running Lutris'spga.db— but opened it with{ readonly: true }, which does not enable SQLite's URI filename parsing. On Linux (Bun's bundled SQLite, unlike macOS's system build) that open always threwSQLiteError: unable to open database file. Every layer then degrades an open failure to "this launcher isn't installed", so the failure was invisible:withReadOnlyDb(...) ?? []returned an empty library, whiledetectcheerfully reportedpresentbecause it only stats the file.Fixed in punktfunk#78, published as plugin-kit 0.3.1.
Why a lockfile change is needed
package.jsonalready ranged^0.3.0, so the published plugin would have resolved 0.3.1 on an operator's install anyway — butbun.lockpinned0.3.0exactly, so CI kept testing against the broken reader.Parity, with the published kit
Re-run on
.21against a live host using the published 0.3.1 (a clean install, not the patched copy used while debugging), with this plugin still unregistered so the host was on its built-in scanner:scanpresent: 0 gamespresent: 1 games, 1 launcher entriesparity --compareFAILED — 1 missingOK — 1 entries identicalGates: biome clean,
tsc --noEmitclean, 5/5 tests, bundle builds.Honest limits
.21has exactly one Lutris game (Ubisoft Connect, wine runner). It proves the reader works and the id/title/launch/role/meta shapes match, but it is one title, not a library.data:URL legitimately becomes afile://path), so the covers still want one spot-check by eye.After merge
Tag
v0.1.0to publish — this plugin has never been released, so the version already inpackage.jsonis the first one, andci.yml'spublishjob is gated onrefs/tags/v*.The kit's `openReadOnly` built a `file:<path>?immutable=1` URI but opened it with `{ readonly: true }`, which does not enable SQLite's URI filename parsing. On Linux — Bun's bundled SQLite, unlike macOS's system one — that open always threw, and every layer degrades an open failure to "this launcher isn't installed". So this plugin reported 0 games on every box it has ever run on, while `detect` happily said "present" (it only stats the file). Nothing here was wrong; the parsing and the ids were right all along. Fixed in punktfunk#78, published as plugin-kit 0.3.1. The caret range already allowed it, but bun.lock pinned 0.3.0 exactly, so CI kept testing against the broken reader. Parity, run on .21 against a live host with the PUBLISHED 0.3.1 (not a patched copy) — the gate that caught this in the first place: scan: present: 1 games, 1 launcher entries (was 0 games) parity: OK — 1 entries identical (was: FAILED — 1 missing) Gates: biome clean, tsc clean, 5/5 tests, bundle builds.