Skip to content

test: fault + lifecycle scenario fan-out (PR-2)#91

Merged
vreshch merged 1 commit into
masterfrom
test/e2e-scenarios
Jul 8, 2026
Merged

test: fault + lifecycle scenario fan-out (PR-2)#91
vreshch merged 1 commit into
masterfrom
test/e2e-scenarios

Conversation

@vreshch

@vreshch vreshch commented Jul 8, 2026

Copy link
Copy Markdown
Member

PR-2: fault + lifecycle scenario fan-out on the assembled-plugin harness

Builds on the PR-1 headless harness (test/fakes/* + test/integration/first-sync.test.ts, #90). Adds 14 ranked integration scenarios that boot the REAL AgentageMemoryPlugin against the fakes and assert on BOTH vault state and fake-couch state (and HTTP call shape where it matters). Couch-only plugin, no git channel. Fully deterministic - ticks are driven explicitly (tick() / a bounded macrotask drain/settle), no sleeps, no real network.

Scenarios (highest data-loss risk first)

delete-conflict.test.ts (data-loss guards)

  1. Missing-leaf pull never truncates: dropLeaf mid-pull -> round aborts, no vault write, cursor frozen at 0; restoreLeaf + a clean pull converges to the full note.
  2. Local delete -> tombstone via DELETE ?rev=; a pull-applied remote delete does NOT bounce back out as a phantom local deletion.
  3. Stale delete abandoned when content moved on: couch content-rev != our known rev -> the delete is dropped, the newer remote doc survives, the next pull restores it (edit-wins-over-stale-delete).

sync-roundtrip.test.ts
4. Local edit -> live push writes leaves (_bulk_docs) BEFORE the file doc (PUT).
5. Remote change pulls into the vault; the suppress guard + content-rev cache stop it echoing back as a redundant push.

resilience.test.ts
6. Couch 401 mid-replication -> couch-token invalidate + re-mint + retry; sync completes, pull still delivers.
7. Expired OAuth access token -> refresh_token grant + rotate before the couch JWT is minted; session stays alive.
8. Rejected live push queues, pendingCount reflects it, the next tick() flushes it.
9. Paged pull cursor (since/limit) persists across a simulated reload: rebuild from the saved couchState resumes at the cursor, no re-pull from seq 0.

lifecycle.test.ts
10. Non-couch memory -> explicit error sync state (red dot) + the server-flip message, never a silent no-op, never a write.
11. Sign-out tears the controller down -> a later tick() is inert (zero couch traffic).
12. Memory switch repoints the controller to a NEW db; the old db is never reused (proven with two independent in-memory couch stores).
13. Connect flow: discovery -> DCR -> authorize -> token exchange; dot goes green with a memory selected.

management.test.ts (lower risk)
14. Memory list maps entries -> files / folderCount -> folders / empty; createVault degrades to "not available on the server yet" on 404 / 405 / 503, then a healthy POST still creates.

Plugin lines now exercised through the assembled plugin (unit tests never reach these)

Both files are coverage-excluded (src/main.ts, src/couch/couch-sync.ts) and had NO direct test driving them end to end:

  • main.ts: syncNow channel routing (channelForVault -> couchSyncNow vs the NOT_ON_COUCH error branch), wireCouchEvents live vault handlers (modify/create/delete pushing through couchChannel), selectVault/disconnect controller lifecycle (couchChannel.for/clear), buildCouchSync wiring, refreshStatus sync-state transitions, listVaults/createVault mapping + degrade branches.
  • couch-sync.ts: syncNow/pushAll/pullOnce end to end, reassemble missing-leaf throw + cursor-freeze, tombstone conflict-abandon + DELETE ?rev path, pushFileLive/removeFile queue-on-failure + flushPending/tick drain, the 401 re-mint retry in req, and the echo suppress guard in writeVault.

Harness extensions (existing fakes + tests stay green)

  • fake-couch.ts: restoreLeaf (undo dropLeaf) + deleteRemote (a remote-origin tombstone a pull applies).
  • fake-auth-server.ts: failNextManagement(status) so /api/memories GET/POST can return a one-shot server gap.
  • router.ts + boot.ts: route couch requests by db to a per-db FakeCouch, with BootOptions.extraCouch advertising extra couch memories (backs the memory-switch test). Single-memory path unchanged.
  • test/integration/_helpers.ts: shared boot/sign-in/edit/delete/tick/drain/settle + private-field accessors (couchActive, syncStateOf, expireAccessToken).

Verify

npm run verify fully green: type-check + lint (0 errors; the 1 warning is the pre-existing settings-tab.ts obsidianmd advisory) + format:check + 125 tests (23 files) + build + check:hosts/docs/bundle.

No real plugin bug surfaced

Every fault path behaved correctly. Two sharp edges worth noting (design-correct, not bugs, not papered over):

  • A bare failNext(503) on a live push lands on the leading getDoc, which tolerates a non-200 as "doc absent" and pushes anyway - so scenario 8 faults the actual write (failLeafOnBulk) to exercise the queue. Comment in the test documents this.
  • The stale-delete abandon relies on the rev-cache entry still being present; once dropped, reconcileDeletions has no "known rev" to detect the stale delete. In the tested flow this is fine (the tombstone abandons and drops the rev, so reconcileDeletions then skips the path). Flagged here as a boundary to watch, not a reproduced fault.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

🎉 PR Validation ✅ PASSED

Commit: 4ae915781a5ddeda50bfda4dbab0ba4f2f05699d
Branch: test/e2e-scenarios

Checks:

  • ✅ Dependencies installed
  • ✅ Type check passed
  • ✅ Linting passed
  • ✅ Format check passed
  • ✅ Tests + coverage passed
  • ✅ Build successful
  • ✅ Store-compliance checks passed
  • ✅ Bundle is mobile-safe

Ready to merge!


🔗 View workflow run

@vreshch
vreshch marked this pull request as ready for review July 8, 2026 23:26
@vreshch
vreshch merged commit a9fde6a into master Jul 8, 2026
1 check passed
@vreshch
vreshch deleted the test/e2e-scenarios branch July 8, 2026 23:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant