diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..2ed2a55 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,116 @@ + + +## What and why + + + +Closes # + +## Verification + + + +- [ ] `npm test` — +- [ ] `npm run typecheck` — 0 errors (root + app) +- [ ] `npm run lint` — 0 errors +- [ ] `npm run test:electron:all` — +- [ ] New tests actually run in CI (`.github/workflows/`) +- [ ] No existing assertion was loosened +- [ ] Every capability described above was exercised end to end from the + outermost entry point (including anything shown in a screenshot) +- [ ] Re-ran the checks above on the current head, after the most recent merge + +## Deliberately out of scope + + + +--- + +
+Renderer / Electron UI — expand if you touched app/src/renderer or row rendering + +- [ ] Reader-anchor assertion added — content settling above the viewport does + not move the row the user is looking at +- [ ] Async media covered at mount, size-available, and load/error — not only the + final state +- [ ] Tested both at rest and mid-scroll (`virtual-core` skips compensation for + measured rows when scrolling backward) +- [ ] No `loading="lazy"` on virtualized rows +- [ ] No hardcoded colors or type sizes in shadow DOM (`var(--muted)` etc.) +- [ ] One visual treatment per user-visible concept +- [ ] Library calling conventions either accept both shapes or are pinned in code +- [ ] Every renderer probe has a deadline and an `error` → reject path +- [ ] No assertion with sub-pixel headroom (self-calibrate instead) + +
+ +
+Provider adapter — expand if you touched packages/core/src/providers + +- [ ] Read `claude.ts`, `codex.ts`, and `kimi.ts` in full first +- [ ] Session identity is composite (e.g. normalized cwd + header id), not the + source id alone +- [ ] A test actually calls `discover()` against each supported directory layout +- [ ] Directory layout verified against upstream source or format docs +- [ ] Canonical transcript invariant holds: direct assembly == SQLite round-trip + (ADR-0007) +- [ ] Text-less records (image-only, aborted-with-usage) still emit a row +- [ ] `indexVersionMarker` bumped if uuid format, role normalization, or any + stored-row shape changed +- [ ] "Should not be displayed" uses `visibility`, not a new meaning for + `is_sidechain` +- [ ] Cursor detects same-millisecond rewrites (mtime + ctime + size + inode) +- [ ] Unknown/newer versions are skipped and recorded, not thrown on + +
+ +
+Schema / migration — expand if you touched schema.sql or schema-migrations.ts + +- [ ] `schema.sql` hash updated in `tests/provider-schema-stability.test.mjs`, + with justification above +- [ ] Destructive DDL runs inside `runWriteTransaction` +- [ ] Completion is not inferred from the target state's own name — interrupting + at any line self-heals on the next start +- [ ] Validation rejects anything SQLite would reject, before any mutation +- [ ] Checked that no table carries its own arguments that a blanket write would + erase +- [ ] External input spliced into DDL has an allowlist and an injection test + +
+ +
+Main process / untrusted input — expand if you touched app/src/main + + + +- [ ] Transcript-derived paths do not reach `shell.openPath` unguarded; + confirmation dialogs default to Cancel +- [ ] File reads triggered by transcript content are allowlisted to known roots +- [ ] No `innerHTML` / detached `