Repository navigation
Description
Summary
t3code-seed-providers' seed script (pkgs/t3code-seed-providers/seed.sh, embedded Python) only guards against unparseable settings.json — a parseable-but-wrong-shaped document crashes it with a raw traceback, and because the script is set -euo pipefail and runs as the t3code-seed-providers oneshot user unit (home/common/default.nix:528, Before=t3code.service), one bad shape silently disables all seeding on every boot — including the OpenCode-1.x safety disable, which is the one part that exists to protect the shared 2.x session DB.
Hand-editing settings.json is explicitly supported upstream (the file's own header says so), so wrong shapes are a realistic input, not a theoretical one.
Evidence (main fa52fcb3, pkgs/t3code-seed-providers/seed.sh)
- The only shape guard is the
tryaroundjson.loadsat :46-48: unparseable →sys.exit(0)("don't clobber something we can't parse"). Nothing validates what the parsed value is. doc.setdefault("providerInstances", {})(:143) assumesdocis a dict.- The add loop assumes
providerInstancesis a dict (instances[k] = desired[k]). - The refresh-on-seed loop (:155-162) calls
instances[k].setdefault("config", {})andconfig.get(...)with no isinstance checks — unlike the safety loop right below it (:173), which does guardisinstance(inst, dict). A crash in refresh also means the safety loop never runs. - The unit always sets all four binary env vars (
home/common/default.nix:544-549: OPENCODE_V2_BIN, ANTIGRAVITY_ACP_BIN, MUSE_BIN, PI_BIN), so the refresh loop is always armed for the fleet-owned ids.
Verified this run with the real script (md5-matched copy of main's seed.sh; probe on the laptop at ~/git/fleet/probe-2026-10-30-laneB-t3seed/, env mirroring the unit):
- control
{}→ rc 0, all instances added (OK) - unparseable
{not json→ rc 0, file untouched (the designed path) []→ rc 1,AttributeError: 'list' object has no attribute 'setdefault'null→ rc 1,AttributeError: 'NoneType' object has no attribute 'setdefault'{"providerInstances": []}→ rc 1,TypeError: list indices must be integers{"providerInstances": null}→ rc 1,TypeError: argument of type 'NoneType' is not a container{"providerInstances": {"muse": "oops"}}→ rc 1,AttributeError: 'str' object has no attribute 'setdefault'(refresh loop){"providerInstances": {"opencode-v2": {"driver": "opencode", "config": null}}}→ rc 1,AttributeError: 'NoneType' object has no attribute 'get'config: "oops"→ rc 1, same site
In every crash case nothing is written and no seeding happens at all — the adds computed before the crash are discarded with the process.
Why it matters
The seed runs before t3code starts, every boot. A single malformed entry — from a hand edit, a t3 version writing a new shape, or a partially migrated file — turns the unit into a permanent failure whose only trace is a Python traceback in the journal, and the fleet loses three things at once: new-instance seeding, binaryPath refresh (the fix for stranded store paths), and the 1.x safety disable that keeps a V1 binary away from the shared 2.x session DB. The script's own contract for input it cannot handle is "exit quietly and don't clobber" — wrong shapes should get the same treatment as unparseable bytes, or be repaired per-instance, not abort the whole run.
Acceptance criteria
- A settings.json whose top level is not a JSON object, or whose
providerInstancesis not an object, no longer crashes the script: it exits without modifying the file and logs a legible reason (stderr), matching the unparseable path's don't-clobber contract. - A fleet-owned instance whose stored value (or its
config) is not an object does not abort the run: the remaining instances still seed/refresh, and the OpenCode-1.x safety disable still executes; the malformed entry is left untouched and named in the log line. - Regression tests (or a scripted fixture run) cover:
[],null,providerInstances: []/null, a fleet instance as a string,config: null/"oops", plus the{}control and the unparseable control. - Well-formed files behave exactly as today (adds, refresh, disable, single stderr summary line).
Dedup
- Searched open + closed issues for t3code seed / settings.json shape handling this run: no match. The seed script and its refresh/safety behaviour have no prior filing.
Activity
dezren39 commentedon Oct 30, 2026
🤖 Agent note · filed
24 remaining items
dezren39 commentedon Oct 31, 2026
🤖 Agent note · parked
dezren39 commentedon Oct 31, 2026
🤖 Agent note · picked up
queue/4410-2738-seed-shapesdezren39 commentedon Oct 31, 2026
🤖 Agent note · done