Contributing
August 16, 2026 · View on GitHub
Thanks for considering a contribution to dsh-checkpoint-diff. This project is small on purpose — a focused read-only diff view over dsh-checkpoint-rewind checkpoints — so a few conventions keep it maintainable.
Ground rules
- Read-only by design, with one explicit exception — rollback. The plugin
must never write to snapshot storage, git, or sessions, and never fork
sessions. The single write path is user-invoked rollback
(
/rollback/POST /api/rollback/ panel Restore row): it restores snapshot file contents into the session workspace — overwrite only, never deletes, workspace-root confined,.git/.dshrefused, read-only git primitives (nogit restore). Every new write-like behavior must first extend that exception explicitly inAGENTS.md/SECURITY.md; anything else belongs in the producer (rewind) instead. - Pure functions where possible. Timeline extraction, addressing, and
output formatting live in
lib/checkpoints.mjsas pure functions; the diff engine inlib/diff/engine.mjsis dependency-free; rollback planning lives inlib/rollback.mjsas pure functions plus low-level fs helpers. Keep it that way. - Security boundaries are load-bearing. Refs are validated (git 40/64-hex,
copy UUID) and relative paths reject
..and absolute paths before any filesystem or git access; restore targets additionally refuse.git/.dshsegments and symlink escapes. Tests must cover the degradation paths (missing records, pruned snapshots, missing objects, mixed providers) and the rollback refusal paths (traversal, protected paths, absent files, method gates).
Development setup
pnpm install # zod, esbuild, jsdom + react for tests
pnpm test # unit tests (node --test, in-process isolation)
pnpm test:integration # headless integration vs. real dsh-checkpoint-rewind
pnpm build:client # rebuild the browser bundle -> lib/client.js
The integration suite assembles the real rewind plugin against the local
harness deployment ($DSH_HOME/profiles/node_modules, rc.5) because
dsh-checkpoint-rewind is not published to npm and rc.5 packages are not on the
registry either. scripts/link-profile-deps.mjs junctions those packages into
this repo's node_modules; run pnpm test:integration on a machine with the
harness installed (or with DSH_HOME pointed at one). The unit suite has no
such dependency and runs anywhere.
Sandbox notes (Windows): node --test child-process spawning and esbuild's
binary service may be blocked under restricted sandbox modes — unit tests use
--test-isolation=none, and building the client bundle may require
full-access once.
Structure
index.mjs— host plugin entry (config, domain acquisition,/diffand/rollbackincl.--project, API route)lib/— host logic:constants,domain(zod spec),workspace,checkpoints(timeline/format),project(cross-session merge/lineage),labels(snapshot intent naming),service(DiffService + HTTP handler),rollback(restore planning + fs helpers),diff/engine|git|copysrc/client/— browser half:index(slot registration),store,api,tree(collapsible directory tree),DiffTrigger,DiffPanel(incl. restore row),style(theme tokens)scripts/—build-client.mjs(esbuild),link-profile-deps.mjs(test deps)test/— unit tests, jsdom panel smoke tests,integration/diff-headless.mjsdocs/— design documents (timeline-design.md: cross-session timelines, implemented in 0.2.0)
Pull request checklist
-
pnpm testpasses -
pnpm test:integrationpasses (or is documented as environment-limited) -
pnpm build:clientand the built bundle was committed if client code changed - CHANGELOG updated (Added / Fixed sections)
- New behavior covered by a test; degradation paths included
License
By contributing you agree that your contributions are licensed under the Apache-2.0 terms of this repository.