trajectories 0.0.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE +201 -0
  3. package/README.md +288 -2
  4. package/dist/cli.js +30210 -0
  5. package/dist/convert.d.ts +31 -0
  6. package/dist/convert.js +431 -0
  7. package/dist/deepagents_checkpoint.py +362 -0
  8. package/dist/index.d.ts +7 -0
  9. package/dist/index.js +8402 -0
  10. package/dist/log-baseline.d.ts +26 -0
  11. package/dist/log-baseline.js +104 -0
  12. package/dist/log-content.d.ts +16 -0
  13. package/dist/log-content.js +80 -0
  14. package/dist/log-io.d.ts +10 -0
  15. package/dist/log-io.js +121 -0
  16. package/dist/log-read.d.ts +24 -0
  17. package/dist/log-read.js +117 -0
  18. package/dist/log-reconcile.d.ts +5 -0
  19. package/dist/log-reconcile.js +38 -0
  20. package/dist/log-records.d.ts +35 -0
  21. package/dist/log-records.js +85 -0
  22. package/dist/log-recovery.d.ts +18 -0
  23. package/dist/log-recovery.js +123 -0
  24. package/dist/log-stage.d.ts +14 -0
  25. package/dist/log-stage.js +138 -0
  26. package/dist/log-state.d.ts +89 -0
  27. package/dist/log-state.js +92 -0
  28. package/dist/log-switch.d.ts +3 -0
  29. package/dist/log-switch.js +98 -0
  30. package/dist/log-types.d.ts +129 -0
  31. package/dist/log-types.js +8 -0
  32. package/dist/log.d.ts +8 -0
  33. package/dist/log.js +62 -0
  34. package/dist/migrate.d.ts +29 -0
  35. package/dist/migrate.js +173 -0
  36. package/dist/normalization-runtime.d.ts +1 -0
  37. package/dist/normalization-runtime.js +3150 -0
  38. package/dist/portable.d.ts +9 -0
  39. package/dist/portable.js +26 -0
  40. package/dist/readers/canonical.d.ts +13 -0
  41. package/dist/readers/canonical.js +54 -0
  42. package/dist/readers/cline.d.ts +10 -0
  43. package/dist/readers/cline.js +107 -0
  44. package/dist/readers/cursor.d.ts +20 -0
  45. package/dist/readers/cursor.js +374 -0
  46. package/dist/readers/deepagents.d.ts +41 -0
  47. package/dist/readers/deepagents.js +163 -0
  48. package/dist/readers/fx.d.ts +11 -0
  49. package/dist/readers/fx.js +573 -0
  50. package/dist/readers/github-copilot.d.ts +8 -0
  51. package/dist/readers/github-copilot.js +216 -0
  52. package/dist/readers/grok-build.d.ts +12 -0
  53. package/dist/readers/grok-build.js +391 -0
  54. package/dist/readers/guards.d.ts +4 -0
  55. package/dist/readers/guards.js +121 -0
  56. package/dist/readers/pi-compaction.d.ts +7 -0
  57. package/dist/readers/pi-compaction.js +112 -0
  58. package/dist/readers/pi-context.d.ts +13 -0
  59. package/dist/readers/pi-context.js +64 -0
  60. package/dist/store.d.ts +25 -0
  61. package/dist/store.js +218 -0
  62. package/dist/types.d.ts +91 -0
  63. package/dist/types.js +1 -0
  64. package/dist/writers/claude-code.d.ts +5 -0
  65. package/dist/writers/claude-code.js +51 -0
  66. package/dist/writers/cline.d.ts +3 -0
  67. package/dist/writers/cline.js +77 -0
  68. package/dist/writers/codex.d.ts +3 -0
  69. package/dist/writers/codex.js +32 -0
  70. package/dist/writers/cursor.d.ts +3 -0
  71. package/dist/writers/cursor.js +197 -0
  72. package/dist/writers/deepagents.d.ts +3 -0
  73. package/dist/writers/deepagents.js +116 -0
  74. package/dist/writers/entropy.d.ts +5 -0
  75. package/dist/writers/entropy.js +33 -0
  76. package/dist/writers/fx.d.ts +3 -0
  77. package/dist/writers/fx.js +135 -0
  78. package/dist/writers/github-copilot.d.ts +3 -0
  79. package/dist/writers/github-copilot.js +71 -0
  80. package/dist/writers/grok-build.d.ts +3 -0
  81. package/dist/writers/grok-build.js +43 -0
  82. package/dist/writers/helpers.d.ts +17 -0
  83. package/dist/writers/helpers.js +75 -0
  84. package/dist/writers/omp.d.ts +3 -0
  85. package/dist/writers/omp.js +7 -0
  86. package/dist/writers/opencode.d.ts +3 -0
  87. package/dist/writers/opencode.js +65 -0
  88. package/dist/writers/pi.d.ts +3 -0
  89. package/dist/writers/pi.js +45 -0
  90. package/docs/cline-native-format.md +43 -0
  91. package/docs/copilot-native-format.md +78 -0
  92. package/docs/cursor-native-format.md +103 -0
  93. package/docs/deepagents-native-format.md +98 -0
  94. package/docs/evidence-api.md +170 -0
  95. package/docs/fx-native-format.md +87 -0
  96. package/docs/harness-parity-bootstrap.md +78 -0
  97. package/docs/harness-support-parity.md +107 -0
  98. package/docs/inspirations.md +103 -0
  99. package/docs/ledger-migration.md +141 -0
  100. package/docs/pi-compaction-context.md +75 -0
  101. package/docs/pi-provider-context.md +76 -0
  102. package/docs/research/2026-10-06-huihua-and-oar.md +176 -0
  103. package/docs/research/ledger/README.md +96 -0
  104. package/docs/research/ledger/confer/2026-09-13-round-10/README.md +61 -0
  105. package/docs/research/ledger/confer/2026-09-13-round-2/cass.md +72 -0
  106. package/docs/research/ledger/confer/2026-09-13-round-3/README.md +70 -0
  107. package/docs/research/ledger/confer/2026-09-13-round-5/README.md +61 -0
  108. package/docs/research/ledger/confer/2026-09-13-round-6/README.md +68 -0
  109. package/docs/research/ledger/confer/2026-09-13-round-7/README.md +64 -0
  110. package/docs/research/ledger/confer/2026-09-13-round-9/README.md +59 -0
  111. package/docs/research/ledger/confer/2026-09-14-wake/wake.md +146 -0
  112. package/docs/research/ledger/docs/inspirations.md +320 -0
  113. package/docs/research/ledger/docs/pr2-pr6-integration.md +53 -0
  114. package/docs/research/ledger/docs/research/2026-09-07-confer-inspirations.md +163 -0
  115. package/docs/research/ledger/docs/research/2026-09-07-letta-continuous-service.md +104 -0
  116. package/docs/research/ledger/docs/research/2026-09-08-claude-history-retrieval.md +117 -0
  117. package/docs/research/ledger/docs/research/2026-09-09-agentsview-native-discovery.md +87 -0
  118. package/docs/research/ledger/docs/research/2026-09-09-daemon-observation.md +231 -0
  119. package/docs/research/ledger/docs/research/2026-09-09-discovery-pagination.md +114 -0
  120. package/docs/research/ledger/docs/research/2026-09-09-harness-transcript-contract.md +145 -0
  121. package/docs/research/ledger/docs/research/2026-09-09-native-history-discovery.md +180 -0
  122. package/docs/research/ledger/docs/research/2026-09-09-native-history-implementation.md +137 -0
  123. package/docs/research/ledger/docs/research/2026-09-09-other-inspirations.md +279 -0
  124. package/docs/research/ledger/docs/research/2026-09-09-trajectory-and-letta-code.md +128 -0
  125. package/docs/research/ledger/docs/research/2026-09-13-diagnostics-coverage.md +116 -0
  126. package/docs/research/ledger/docs/research/2026-09-13-fts-rebuild.md +83 -0
  127. package/docs/research/ledger/docs/research/2026-09-13-read-path-split.md +74 -0
  128. package/docs/research/ledger/docs/research/2026-09-13-runtime-rollout.md +102 -0
  129. package/docs/research/ledger/docs/research/2026-09-13-scan-outcomes.md +80 -0
  130. package/docs/research/ledger/docs/research/2026-09-13-search-quality.md +105 -0
  131. package/docs/research/ledger/docs/research/2026-09-13-source-coverage.md +64 -0
  132. package/docs/research/ledger/docs/research/2026-09-13-sync-wall-budget.md +82 -0
  133. package/docs/research/ledger/docs/research/2026-09-13-typed-read-gate.md +81 -0
  134. package/docs/research/ledger/docs/research/2026-09-13-writer-lease.md +84 -0
  135. package/docs/research/ledger/docs/research/2026-09-16-c1-copy-fallback.md +227 -0
  136. package/docs/research/ledger/docs/research/2026-09-16-c10-kimi.md +414 -0
  137. package/docs/research/ledger/docs/research/2026-09-16-c2-derive-counter.md +216 -0
  138. package/docs/research/ledger/docs/research/2026-09-16-c3-echo-filter.md +305 -0
  139. package/docs/research/ledger/docs/research/2026-09-16-c4-title-index.md +349 -0
  140. package/docs/research/ledger/docs/research/2026-09-16-c5-trigram.md +268 -0
  141. package/docs/research/ledger/docs/research/2026-09-16-c6-recency-prior.md +438 -0
  142. package/docs/research/ledger/docs/research/2026-09-16-c7-tombstones.md +467 -0
  143. package/docs/research/ledger/docs/research/2026-09-16-c8-remote-truth.md +390 -0
  144. package/docs/research/ledger/docs/research/2026-09-16-c9-grok.md +380 -0
  145. package/docs/research/ledger/docs/research/2026-09-16-wake-port-program.md +38 -0
  146. package/docs/research/ledger/docs/research/2026-09-17-cursor-blobstore.md +157 -0
  147. package/docs/research/ledger/manifest.json +540 -0
  148. package/legacy/NOTICE.md +50 -0
  149. package/legacy/bin/ledger-core.ts +7 -0
  150. package/legacy/bin/ledger.ts +7 -0
  151. package/legacy/bin/traj-bridge.ts +7 -0
  152. package/legacy/scripts/import-claude-history.ts +130 -0
  153. package/legacy/scripts/native-history-smoke.ts +52 -0
  154. package/legacy/scripts/observe-daemon.ts +570 -0
  155. package/legacy/scripts/retitle-sessions.md +19 -0
  156. package/legacy/scripts/verify-runtime-rollout.ts +151 -0
  157. package/legacy/src/canonical.ts +108 -0
  158. package/legacy/src/cli.ts +1293 -0
  159. package/legacy/src/db.ts +2254 -0
  160. package/legacy/src/diagnostics.ts +87 -0
  161. package/legacy/src/discovery.ts +56 -0
  162. package/legacy/src/embeddings.ts +382 -0
  163. package/legacy/src/filter.ts +602 -0
  164. package/legacy/src/gemini_embeddings.ts +103 -0
  165. package/legacy/src/identity.ts +9 -0
  166. package/legacy/src/index.ts +10 -0
  167. package/legacy/src/ingest.ts +791 -0
  168. package/legacy/src/managed.ts +178 -0
  169. package/legacy/src/native/common.ts +68 -0
  170. package/legacy/src/native/cursor.ts +647 -0
  171. package/legacy/src/native/grok.ts +540 -0
  172. package/legacy/src/native/kimi.ts +706 -0
  173. package/legacy/src/native/opencode.ts +470 -0
  174. package/legacy/src/native/sqlite-ro.ts +281 -0
  175. package/legacy/src/native.ts +97 -0
  176. package/legacy/src/normalizer.ts +457 -0
  177. package/legacy/src/parentage.ts +562 -0
  178. package/legacy/src/pressure.ts +162 -0
  179. package/legacy/src/private-storage.ts +74 -0
  180. package/legacy/src/reader.ts +1255 -0
  181. package/legacy/src/scanner.ts +591 -0
  182. package/legacy/src/schema-gate.ts +263 -0
  183. package/legacy/src/schema.ts +829 -0
  184. package/legacy/src/semantic-top-k.ts +71 -0
  185. package/legacy/src/session-hash.ts +49 -0
  186. package/legacy/src/store-status.ts +218 -0
  187. package/legacy/src/sync-preparation.ts +45 -0
  188. package/legacy/src/sync-truth.ts +843 -0
  189. package/legacy/src/sync.ts +1233 -0
  190. package/legacy/src/types.ts +436 -0
  191. package/legacy/src/vocab.txt +30522 -0
  192. package/legacy/src/watch.ts +673 -0
  193. package/legacy/src/writer-lease.ts +310 -0
  194. package/ops/README.md +150 -0
  195. package/ops/install-cli.sh +63 -0
  196. package/ops/install-native.sh +35 -0
  197. package/ops/install-release.sh +49 -0
  198. package/ops/linux/install-systemd-user.sh +103 -0
  199. package/ops/macos/install-launchd.sh +72 -0
  200. package/ops/sync-settings.sh +37 -0
  201. package/package.json +21 -5
  202. package/skills/trajectories/SKILL.md +138 -0
  203. package/skills/trajectories/scripts/trajectories_recent.sh +26 -0
  204. package/skills/trajectories/scripts/trajectories_search.sh +26 -0
  205. package/index.js +0 -1
@@ -0,0 +1,146 @@
1
+ # iAmCorey/Wake — confer 2026-09-14 (adapters, trigram FTS, identity, SSH mirror, resume)
2
+
3
+ ## Outcome
4
+
5
+ Wake (Rust + GPUI desktop app, MIT, v0.6.5, 18 agent sources, 34.4k LOC src + 6.6k LOC tests) is the closest cousin yet — same inputs, opposite product shape. Ranked candidates; nothing here is a dependency proposal.
6
+
7
+ 1. **Copy-fallback read-only SQLite for locked/in-use stores.** Gradient: `SQLITE_OPEN_READ_ONLY` + a probe query to prove usability → copy `db` + `-wal` + `-shm` into a temp dir and read the copy → give up; never `immutable=1` (unsafe under a concurrent WAL writer), temp dir cleaned on drop. Ledger opens readonly with `busy_timeout` and emits a `read_error` diagnostic, so a store held by its own CLI costs coverage.
8
+ 2. **Self-referential echo filter on the FTS projection.** Wake excludes the agent's *own* Wake lookups (`wake_*` MCP tools; `wake-cli`/`wake-mcp` shell calls) from indexed units, and raises an `FTS_FORMAT` counter so every existing index re-derives once on upgrade. Ledger indexes the transcripts of the very agents that call `ledger search`.
9
+ 3. **Title index, ranked ahead of body hits.** Separate `titles_fts` (trigram, `key UNINDEXED`); title hits are emitted first as `role="title"`, `seq=0`, jumping to session start — never a fabricated seq. Ledger's `records_fts` has no title column, so titles are unsearchable today.
10
+ 4. **Trigram tokenization as a measured trade, not a switch.** `trigram case_sensitive 0` buys substring/code-identifier/CJK search (`useEffect(`), but *any* whitespace segment under 3 codepoints degrades the whole query to `LIKE %seg%` — exactly what `porter unicode61` does natively. An explicit decision round, not a silent swap.
11
+
12
+ Lower-value, still extractable: a derive-rule version counter separate from the schema version; tombstone double-track (path + logical key) so a delete survives re-scans; a per-agent `resume_args` + `requires_cwd` table that *withholds* the action when a source cannot honor it.
13
+
14
+ ## Reproducibility
15
+
16
+ - Pin for all citations: `iAmCorey/Wake@d9f702b6df0e85763f8ab597c09bf4ca6a168db4` (= v0.6.5, released 2026-09-14, HEAD; abbreviated `wake@d9f702b6`). Clone: `git clone --depth 100 https://github.com/iAmCorey/Wake /tmp/ledger-confer/wake` (read-only, kept outside the Ledger tree, never copied in).
17
+ - Line-verified by direct read (`sed -n`/`grep -n`) in every citation: `crates/wake-core/src/{db,scanner,remote,watcher,models}.rs`, `adapters/{mod,claude,codex,copilot,kiro,antigravity,sqlite_ro}.rs`, `services/terminal/{mod,macos}.rs`, `mcp/{mod,tools}.rs`, `tests/adapter_contracts.rs`, both `Cargo.toml`s, `CHANGELOG.md`. Ledger inspected read-only.
18
+ - Not run: no `cargo build`, no test suite, no binary, no app launch. Everything behavioural is a static read of a shallow clone; anything from a summary rather than an opened file is `[SCOUT]` or `[INFERRED]`. No Ledger tests run.
19
+ - Maturity: first release 0.1.0 on 2026-08-18, v0.6.5 today (33 releases); macOS-first, experimental Linux/Windows. The data layer reads as a rewrite of already-paid-for lessons, not a first draft.
20
+
21
+ ## Findings
22
+
23
+ ### 1. Source adapters: 18 agents, one contract, per-source sidecars
24
+
25
+ - **Coverage.** `AgentId::ALL` = claude-code, codex, grok, dsh, cursor, opencode, pi, omp, kiro, kimi, gemini, copilot, antigravity, qoder, hermes, openclaw, codebuddy, workbuddy OBSERVED `models.rs#L7-L40`. Ledger discoverable 14 + `atif` declared only OBSERVED `archeism/ledger:packages/core/src/scanner.ts#L22-L44`, `types.ts#L9-L25`.
26
+ - **Wake-only banks (8):** Kiro `~/.kiro/sessions/cli/<uuid>.{jsonl,json,history}` (`{kind:Prompt|AssistantMessage}` rows; `.json` sidecar carries cwd/title/times, `.history` ignored) OBSERVED `adapters/kiro.rs#L10-L12`; Antigravity **metadata-only** — the transcript is encrypted `.pb`, the only plaintext is `~/.gemini/antigravity-cli/conversation_summaries.db`, so its detail page is one synthetic System message saying so OBSERVED `adapters/antigravity.rs#L9-L13`; Copilot CLI as a SQLite `~/.copilot/session-store.db` (`sessions` + `turns`, dirty-detected by `updated_at` plus summed body length) OBSERVED `adapters/copilot.rs#L10-L13`; plus Grok, DSH (zstd logs decoded transparently), Kimi, Qoder, CodeBuddy, WorkBuddy.
27
+ - **Layout deltas on shared sources** (worth more than the new names): Gemini CLI read from `~/.gemini/tmp/**/chats` + `projects.json`; Codex also from `archived_sessions` OBSERVED `adapters/codex.rs#L24-L33`; OpenCode v2 from `opencode-next.db` OBSERVED `remote.rs#L93-L101`. Ledger uses `~/.gemini/sessions` and `session-state` dirs for Copilot OBSERVED `scanner.ts#L39-L44`, and has no archived/next path string anywhere in `packages/core` (grep). On this host `.copilot` holds only `ide/` and `.gemini` has neither `sessions` nor `tmp`, while `.kiro`, `.qoder`, `.grok`, `.antigravity` exist — Wake's extra banks carry data here; which shared layout is current is unproven either way, so do not "fix" Ledger from this alone.
28
+ - **Contract.** `list_session_files()` must stay cheap ("enumeration never full-parses"; SQLite sources run a metadata query, dsh a bounded first line) and degrades in place to an empty list rather than aborting the scan; `detect()` is derived from `data_roots()` and must not be overridden, so panel and scan cannot disagree OBSERVED `adapters/mod.rs#L39-L48`. `quick_meta` + per-adapter `merge_quick_meta` precedence: Codex takes a user-renamed title from `state_5.sqlite` over the first-message derivation, adopts the thread id as key, but keeps the file's `source` because it is more precise than the DB class OBSERVED `adapters/codex.rs#L739-L825`; `manages_parent_links()` distinguishes "no children now" (clear stale edges) from "unsupported" OBSERVED `adapters/mod.rs#L95-L109`.
29
+ - **Malformed data.** Per-line tolerance with explicit known-skip lists; unparseable or unknown rows increment `unknown_lines` and continue, with exact counts (including deliberate junk like `wibble-part`) pinned per source OBSERVED `adapters/claude.rs#L118-L152`, `tests/adapter_contracts.rs#L356`, `#L683`, `#L2583`. **But the signal is dropped:** `sessions.unknown_lines` is inserted as a literal `0`, omitted from the `ON CONFLICT DO UPDATE` set, and unread by the UI crate OBSERVED `db.rs#L1968-L1991` + repo-wide grep — the same loss Ledger's cycle-1 diagnostics work closed.
30
+
31
+ ### 2. Search: trigram DDL, per-segment AND, recency-multiplied bm25, honest degradation
32
+
33
+ - **DDL.** `messages_fts` is external-content (`content='messages', content_rowid='id'`) with `tokenize="trigram case_sensitive 0"`; `titles_fts` is standalone with `key UNINDEXED` OBSERVED `db.rs#L63-L67`, `#L126-L130`. SQLite is bundled (`rusqlite 0.32 features=["bundled"]`) OBSERVED `Cargo.toml#L14`, so the trigram tokenizer and its `case_sensitive` option exist.
34
+ - **Query.** Whitespace segments, each quoted as a phrase (embedded quotes doubled), joined with `AND` — substring per term, not adjacency OBSERVED `db.rs#L1587-L1591`. Any segment under 3 codepoints switches the *whole* query to `m.text LIKE '%seg%' ESCAPE '\' AND …` ordered by timestamp, with a hand-built `make_like_snippet` OBSERVED `db.rs#L1544`, `#L1632-L1650`. Degradation is *returned*, not swallowed: `search_with → (hits, degraded)` OBSERVED `#L1539`.
35
+ - **Ranking.** `ORDER BY bm25(messages_fts) * (1.0 + 1.0/(1.0 + max(0, ? - s.updated_at)/2592000000.0))` — bm25 is negative, so a ×1.0–×2.0 recency factor promotes recent sessions (today ×2, 30d ×1.5, 1y ×1.08), built from arithmetic + `max()` only (no math extension), keyed on the *session's* `updated_at` so intra-session order is untouched, and the degraded LIKE path keeps time ordering OBSERVED `db.rs#L1546-L1560`. Title hits rank above body hits through the second table, `role="title"`, `seq=0`, jump to session start, "title has no transcript row, do not fabricate a seq" OBSERVED `#L1676-L1700`; recency + title search + echo filter all shipped in 0.6.5 OBSERVED `CHANGELOG.md#L3-L13`.
36
+ - **Derive-rule versioning.** `FTS_FORMAT: &str = "2"` in `schema_meta`; a mismatch on open raises `fts_reindex`, and the next scan re-parses *every* file including mtime/size-unchanged ones, clearing the flag after a scan with no parse failures OBSERVED `db.rs#L134-L136`, `#L176-L196`, `scanner.rs#L179`, `#L440`. Newest column/table are tracked separately so read-only consumers refuse an old DB up front instead of dying mid-query OBSERVED `db.rs#L231-L233`, `#L327-L328`.
37
+ - **Freshness is disclosed, never implied.** Every MCP reply carries "Index covers activity up to {t} (local time); Wake keeps it fresh while it is running", and prints "Index freshness unknown: …" instead of omitting the line OBSERVED `mcp/tools.rs#L409-L413`.
38
+ - **Ledger gap this targets:** `records_fts` is `porter unicode61` over records with no title column OBSERVED `archeism/ledger:packages/core/src/schema.ts#L11-L21`; widening is zero-hit-only prefix-OR with typed skip reasons OBSERVED `reader.ts#L302-L314`; the residual common-prefix cost class is recorded at issue #34.
39
+
40
+ ### 3. Identity and lifecycle: file-keyed, mtime-arbitrated, tombstoned, whole-session replace
41
+
42
+ - **Key.** `session_key(agent, host, native_id)`; the host segment keeps two machines' same-UUID sessions apart. `sessions.file_path` is `UNIQUE`, and the dedup domain is that same key, which the comment argues makes "dedup domain == key segmentation" structural OBSERVED `models.rs#L616-L622`, `db.rs#L27-L48`, `scanner.rs#L232-L240`. Ledger's identity is source-scoped with an appendable v2 content hash — a different axis (provenance, not file arbitration).
43
+ - **Copy arbitration.** Same-key candidates across locations are ordered by (newest mtime, then lexicographically smallest path); the winner is queued and the losers are retained as a **parse-failure fallback order**, so a corrupt winner cannot erase the session. `write_session_guarded` repeats the comparison *inside* the write transaction, because check-then-write races a concurrent incremental scan and lets the loser land last OBSERVED `scanner.rs#L240-L263`, `#L389-L420`, `db.rs#L372-L399`.
44
+ - **Rewrite/truncate.** No generation model: the transaction deletes all messages for the key (with explicit FTS5 `'delete'` rows, required by external content), upserts the session, reinserts the units OBSERVED `db.rs#L1923-L1966`. A truncated source *replaces* the visible history under the same key and no prior generation survives — Ledger's staged replacement plus the open retention boundary is ahead, and Wake is evidence that "replace wholesale" is what you get without a retention requirement.
45
+ - **Deletion.** `tombstones(file_path PK, key, deleted_at)` written in the same transaction as the row removal; enforcement is double-track, by path *and* logical key, so another location's copy cannot resurrect a user-deleted session OBSERVED `db.rs#L76-L80`, `#L531-L570`, `#L1002-L1018`, `scanner.rs#L219-L227`. Stars/pins live in `user_data` and survive a rebuild OBSERVED `db.rs#L69-L74`.
46
+ - **Scan lifecycle.** Dirty = changed mtime/size (`known_files()`), owner-changed path, forced reindex, or full scan; "in the DB but not enumerated" → row removed (absence is not a deletion, so no tombstone); longest-root ownership resolves overlapping custom roots OBSERVED `scanner.rs#L341-L350`, `#L200-L217`, `adapters/mod.rs#L359`. Watcher: `notify`, 800 ms debounce, FSEvents loss raises `on_rescan_needed` OBSERVED `watcher.rs#L1-L20`, `scanner.rs#L21-L24`.
47
+ - **Concurrency honesty.** A process-level `SCAN_GATE` mutex serializes scans in-process and the comment states outright that it does not cover two processes, that closing the window would need a shared cross-process lock, and "for the same reason do not add `--force`"; index creation arbitrates with `hard_link` (create-if-absent) and defers to whoever won OBSERVED `scanner.rs#L55-L135`. No cross-process writer lock exists; Ledger's `writer-lease.ts` is ahead, and the value here is the named residual risk rather than an implied guarantee.
48
+ - **Dedup.** Cross-host duplicates (two remotes pointing at one machine) are deduplicated in *stats only* — `ROW_NUMBER() OVER (PARTITION BY agent_id, native_id, created_at ORDER BY updated_at DESC, host)`, with a comment on why `native_id` alone is insufficient (Hermes ids are small integers) — while both rows stay browsable OBSERVED `db.rs#L1319-L1340`. There is no cross-agent dedup at all.
49
+
50
+ ### 4. Remote hosts: probe-then-mirror rsync pull, where failure is never emptiness
51
+
52
+ - **Shape.** Not remote reads: whitelisted paths are `rsync`'d from the remote home into `<data dir>/remotes/<host>/` keeping the remote layout, and a `RemoteAdapter` decorator mounts each bank via `with_custom_root`, so adapters, parsers and FTS are remoteness-unaware OBSERVED `remote.rs#L1-L18`, `adapters/mod.rs#L134`. System `ssh`/`rsync` are shelled out rather than an SSH library, so `~/.ssh/config` aliases, ProxyJump and IdentityAgent are inherited, with `-oBatchMode=yes -oConnectTimeout=10` so a TTY-less GUI process can never hang on a passphrase OBSERVED `#L8-L12`, `#L248`.
53
+ - **Probe first, mirror second.** One `ssh host sh -c '…[ -e p ]…'` tests each whitelist path; only paths that exist go to `rsync -R --delete`, and whitelist entries missing remotely are deleted from the cache. The full whitelist must not be fed to rsync, with measured reasons: openrsync (macOS 15+) aborts the entire file list when one source's parent is missing (later sources silently untransferred, exit code only 23), and any sender-side I/O error suppresses the delete phase, so `--delete` would never fire on a host with only some agents installed OBSERVED `#L13-L22`, `#L264-L305`.
54
+ - **Failure semantics.** A probe failure fails the sync and leaves the cache untouched ("cannot treat 'cannot connect' as 'the remote is empty'"); rsync exit 24 (source vanished mid-transfer) is tolerated *only* when every error line is a missing source, matched against both GNU and openrsync dialects OBSERVED `#L328-L360`, `#L403-L431`. Per-host `last_sync_at`/`last_sync_error` are persisted and surfaced OBSERVED `db.rs#L116-L122`.
55
+ - **Cache lifecycle.** The mirror is disposable: removing a host purges its cache, because an in-flight rsync cannot be cancelled and would write the removed tree back OBSERVED `#L202-L222`. Host names are validated (no `:` — the host lands in the session key and in argv) OBSERVED `#L194-L200`; credentials are excluded by whitelist construction; remote sessions are read-only in the app and cannot be trashed.
56
+ - **For ADR-0005.** This is the *pull* sibling of the push path (tiers A instrumented / B cooperative hook / C scan-only, `archeism/ledger` PR #13, issue #14 still blocked). Wake has no push buffer, so it says nothing about tier-0's drop-vs-retry. What transfers is the truthfulness set: unreachable ≠ empty, partial ≠ complete, a cache has an explicit lifecycle and is deletable, identity carries the host, and an unprobeable transport must not be assumed.
57
+
58
+ ### 5. Resume: one capability table, cwd-conditional, no dead actions
59
+
60
+ - **One table, two shapes.** `resume_args(meta) -> Option<(Vec<String>, bool)>`: claude `--resume <id>` (requires cwd), codex `resume <id>`, qoder `--resume <id>` (cwd-bucketed history), copilot `--resume=<id>`, opencode/pi/kimi `--session <id>` (v2 switches binary via `session_bin`), omp/grok `--resume <id>`, antigravity `--conversation=<id>`, dsh `npx @deepseek-ai/dsh web` with cwd as the workspace (no per-session resume exists), hermes `--profile <profile> --resume <id>` (the profile flag must always be passed, to override the sticky active profile) OBSERVED `services/terminal/mod.rs#L104-L195`.
61
+ - **Refusal is designed in.** Kiro, Gemini CLI, OpenClaw (its TUI opens by session *key* while Wake stores the session id) and WorkBuddy (desktop only) return `None`, so `resume_targets` returns nothing and no menu item exists that would only fail when clicked OBSERVED `#L190-L195`, `#L267-L283`. macOS routes GUI hosts through deep links (`kooky://resume`, `claude://resume?session=`) rather than assuming a shell OBSERVED `services/terminal/macos.rs#L29-L45`, `#L133-L140`.
62
+ - **Remote resume** is a copied, never-executed command: `ssh -t <host> 'exec $SHELL -lic '\''cd <cwd> && <cli> <args>'\'''`. Two decisions worth keeping: the CLI is a bare name resolved against the *remote* PATH (a local absolute path is meaningless there), and the inner command runs under a login + interactive shell because sshd hands a non-interactive shell that reads no rc files, so nvm/volta-installed CLIs are `command not found` — the 0.6.5 changelog records exactly that fix OBSERVED `#L226-L256`, `CHANGELOG.md#L8`. cwd is remote, so a local `is_dir` check is deliberately skipped: non-empty → `cd`, empty → the ssh default home OBSERVED `#L236-L240`.
63
+ - INFERENCE for Ledger: resume binding is already validated on our side; the extractable piece is the *capability table with a cwd precondition and refusal*, which is what makes "resume this" honest per source. The terminal plumbing is out of scope for a headless store.
64
+
65
+ ### 6. Architecture and license
66
+
67
+ - **MIT, no rider.** Plain MIT text (Corey Chiu, 2026) and `license = "MIT"` OBSERVED `Cargo.toml#L8`. Patterns — even code — are borrowable with attribution; nothing here was copied and no dependency is proposed (Rust vs TypeScript, different products). One wrinkle: the UI crate depends on `gpui` from `zed-industries/zed` and `gpui-component` by git revision OBSERVED `crates/wake/Cargo.toml#L17-L19`; gpui upstream is GPL-3.0, so do not vendor UI code from this repo. `[INFERRED]` — transitive licenses not audited.
68
+ - **Shape.** `wake-core` is a pure data layer with no UI dependency; two read-only siblings ship beside the binary. `wake-mcp` (stdio JSON-RPC, four tools: search/list/get/projects) opens the index with `Store::open_read_only` and never rebuilds or migrates it; `wake-cli` prints the same payloads, asserted byte-for-byte apart from a trailing newline OBSERVED `mcp/mod.rs#L12`, `#L225-L228`, README. Same read-only-consumer discipline Ledger wants, plus the rule that a *stale* index is tolerated while a *foreign* one is refused up front.
69
+ - **Complementary, not competing.** Wake is a desktop browser over files the user already has: no daemon, no supervision, no canonical record model, no coverage/fidelity declaration, no raw retention, an index explicitly rebuildable at any time ("do not add `--force`"). Ledger owns durable records, parentage, cursors and retention; Wake owns the human surface and "one window over eighteen CLIs". Nothing here argues for a UI; it argues that a read-only second consumer of the index is cheap and that freshness must be printed.
70
+
71
+ ### 7. Parentage census (follow-up probe, same pin)
72
+
73
+ - **One durable single-parent edge, two producers.** `sessions.parent_key`
74
+ (`db.rs#L46`, index `idx_sessions_parent` `#L173`), added by ALTER with a
75
+ `grok_parent_backfill` flag that force-reparses Grok on old DBs (`#L156-L171`).
76
+ Recursive descendant CTE (`#L1167-L1170`), children list (`#L1125`), root/child
77
+ count filters (`#L1781-L1804`). `replace_parent_links` does a full per-agent
78
+ replace and reports whether anything changed (`#L478-L525`); it also rewrites
79
+ the child's `project_path`/`project_name` to the parent's (`#L496-L509`), and
80
+ unlinking re-parses the child to restore its fallback project
81
+ (`scanner.rs#L505-L521`).
82
+ - **Producers.** Grok: the main session dir's own subagent registry (child id →
83
+ direct parent id + parent cwd) in `grok_group.rs#L16-L38`, emitted as
84
+ `(grok:child, grok:parent)` at `#L42-L56`; subagent transcripts ARE separate
85
+ sessions and get `parent_key` (`grok.rs#L403-L447`). Hermes: DB `parent_id`,
86
+ accepted only when the parent id exists in the SAME profile DB
87
+ (`hermes.rs#L505-L521`). All other 15 adapters take the default
88
+ `false`/empty (`adapters/mod.rs#L97-L109`); `RemoteAdapter` delegates
89
+ (`remote.rs#L144-L157`). The capability bit exists so an agent whose links
90
+ change clears stale edges while an unsupported agent's rows are left alone;
91
+ the scanner keeps only edges whose parent is owned by the same winning
92
+ snapshot, then flattens each child to the transitive ROOT
93
+ (`scanner.rs#L546-L560`, caller `#L449-L523`).
94
+ - **Claude `subagents/`:** not sessions, not folded, not parented. `file_ref`
95
+ returns None for `/subagents/` and `/memory/` paths (`claude.rs#L591-L597`);
96
+ sidechain files are discovered by `list_sidechains` (`#L468+`) and attached to
97
+ the matching mainline Task call by `tool_use_id` (`tc.sidechain_ref`,
98
+ `#L556-L573`), fetched on demand via `load_sidechain` (`#L578-L588`).
99
+ `parse_session` parses with `include_sidechain=false`, so in-file sidechain
100
+ rows are skipped (`#L176`) — subagent text never enters FTS through the
101
+ parent; only the parent's Task call line is searchable. Deleting a session
102
+ trashes the whole `<id>/` sidecar dir (`#L600-L606`).
103
+ - **Cursor:** same `subagents/` dir, but no meta sidecar and the mainline Task
104
+ call carries no id — transcripts listed as sidechains with no link
105
+ (`cursor.rs#L374-L394`), not top-level sessions (`#L345-L347`); dir trashed
106
+ together (`#L354`). **CodeBuddy:** `<sessionId>/subagents/agent-*.jsonl`
107
+ explicitly "must not become top-level sessions" (`codebuddy.rs#L438`); `<id>/`
108
+ dir trashed with the session (`#L469`).
109
+ - **OMP / Pi:** no parentage at all. `PiAdapter::omp()` reuses the Pi parse
110
+ core on `~/.omp/agent/sessions` (`pi.rs#L34-L43`); recursive enumeration
111
+ makes a nested `<parent>/<child>.jsonl` its own standalone session with
112
+ native id = stem segment after the last `_` (`pi.rs#L51-L53`, `#L173-L175`;
113
+ parse_utils#L227-L260), `parent_key` empty. **Codex:** `session_meta` is read
114
+ only for cwd, originator→source and git branch (`codex.rs#L348-L363`); no
115
+ parent/spawn field is read anywhere, rollouts standalone (`#L488`).
116
+ - Sidebar: messages carry `sidechain_id` (`db.rs#L56`); search can return
117
+ sidechain hits (`#L1598`, `#L1765`) even though some user-message
118
+ aggregations exclude them (`#L1309`).
119
+
120
+ ## Ledger comparison
121
+
122
+ | Dimension | Wake @d9f702b6 | Ledger (working tree) |
123
+ | --- | --- | --- |
124
+ | Sources | 18 agents, per-source fixtures; Kiro/Grok/Kimi/Qoder/CodeBuddy/WorkBuddy/Antigravity/DSH beyond us | 14 discoverable + `atif` declared only; 8 of Wake's banks absent |
125
+ | Shared layouts | Gemini `~/.gemini/tmp/**/chats`; Copilot `session-store.db`; Codex `archived_sessions`; OpenCode `opencode-next.db` | `~/.gemini/sessions`; Copilot `session-state` dirs; no archived/next paths |
126
+ | Read discipline | readonly + probe → copy `db`/`-wal`/`-shm` → give up; never `immutable=1` | readonly + `busy_timeout`; WAL sidecars tracked, WAL store missing sidecars refused; no copy fallback |
127
+ | Malformed data | per-line counters + skip lists, exact counts in tests; column hardwired to 0, never surfaced | durable `ingest_diagnostics` per (source, session, code) — ahead |
128
+ | Search index | FTS5 `trigram case_sensitive 0`, external content, separate `titles_fts` | FTS5 `porter unicode61` over records; no title column |
129
+ | Query | segments → quoted phrase each, `AND`; any segment <3 cp degrades all to `LIKE`, reported | prefix-OR widening, zero-hit only, typed skip reasons; common-prefix floor at #34 |
130
+ | Ranking | `bm25 × recency(30d)`; titles first; snippet/highlight | `rank ASC, started_at DESC`; no recency term |
131
+ | Identity | `agent:host:native_id`, `file_path UNIQUE`, dirty = mtime+size | source-scoped identity, appendable content hash, cursors |
132
+ | Rewrite | whole-session replace in one transaction; no generation retained | staged replacement + transactional promotion; retention still open |
133
+ | Dedup | same key across locations: mtime winner + fallback order; cross-host deduped in stats only | cross-source convergence is ADR-0005 work |
134
+ | Deletion | tombstone path+key in the same transaction; system Trash | archive deletion/privacy policy still open |
135
+ | Writers | in-process mutex only; `hard_link` arbitration; "don't add `--force`" | `writer-lease.ts` (heartbeat + lock) — ahead |
136
+ | Remote | SSH rsync pull into `remotes/<host>/`, probe-then-mirror, read-only in app | none; ADR-0005 tiers proposed, #14 blocked |
137
+ | Resume | per-agent argv table + `requires_cwd`; unavailable → no action | source-bound resume validation; no launch |
138
+ | Surfaces | `wake-mcp` read-only + `wake-cli` byte-identical; freshness printed per reply | CLI + robot/semantic/hybrid; envelope work is a round-1 candidate |
139
+ | License | MIT; UI deps reach GPL-3.0 gpui upstream | n/a |
140
+
141
+ ## Boundaries
142
+
143
+ - **License verdict: MIT, clean.** No rider, no CLA-adjacent restriction in-tree: patterns and code may be adapted with attribution. This document copies nothing; if a candidate is later built, label it "adapted from an MIT reference" (or clean-room if written without the source in view). Do not vendor `gpui`/`gpui-component` — GPL-3.0 upstream `[INFERRED]`, unaudited.
144
+ - **What Ledger must not adopt:** wholesale session replacement with no retained generation; a diagnostics counter that reaches the DB as a constant zero; a metadata-only card for an encrypted source (Antigravity) contributing an index row that asserts nothing but a preview; stats-level dedup that leaves duplicate rows browsable; no cross-process writer lock (the participating-writer gap round 1 already ranked for a later cycle).
145
+ - **Non-goals this round:** Wake's GPUI/UI code and its `wake_get_session` Markdown projection; Insights/export/trash plumbing; i18n; packaging, installers and Windows/Linux desktop integration; MCP tool schemas beyond freshness. Its ssh/rsync transport is *not* a proposal for ADR-0005's deferred transport — the tiers in PR #13 stay the decision to argue with.
146
+ - **Evidence class:** no build, no test run, no binary, no app launch; static reads of a shallow clone at `d9f702b6` kept outside the Ledger tree, plus one read-only probe of local agent directories to see which banks carry data. No Ledger tests run; no Ledger file outside this one was modified.
@@ -0,0 +1,320 @@
1
+ # Inspirations
2
+
3
+ Ledger uses Letta Trajectory as its canonical normalization dependency and
4
+ combines operational and retrieval lessons from the other projects below.
5
+
6
+ See the [2026-09-07 Confer comparison](research/2026-09-07-confer-inspirations.md)
7
+ for pinned source evidence, research-agent review and implementation gates.
8
+
9
+ ## Integrated baseline
10
+
11
+ PR2 and PR6 are merged at `56b51e2b76d8d37f749bb114f5b73f1e40164cf9`.
12
+ The [integration record](pr2-pr6-integration.md) documents schema-6 migrations,
13
+ source-scoped identity and parentage, atomic records/cursor commits, staged
14
+ replacement, bounded JSONL ingestion, retryable enrichment, paginated discovery,
15
+ and startup/periodic reconciliation. Its combined gate records **152 passed,
16
+ 0 failed, 959 assertions across 17 files**, with typecheck passing. This is not
17
+ runtime acceptance. The subsequent
18
+ [daemon observation](research/2026-09-09-daemon-observation.md) passed after the
19
+ PR7 watcher/installer fixes at `6bd64b7`: automatic import and three appends,
20
+ preserved historical retrieval, and continued bounded backfill were observed.
21
+ The report retains failed attempts, resource measurements, and unresolved
22
+ Cursor/OpenCode import and retry gaps. Full corpus coverage and raw archival
23
+ retention remain unverified.
24
+
25
+ Fresh evidence: [Trajectory and Letta Code](research/2026-09-09-trajectory-and-letta-code.md)
26
+ and [Cass, AgentsView, Obelisk and AI Harnesses](research/2026-09-09-other-inspirations.md).
27
+ The [discovery and transcript-contract comparison](research/2026-09-09-harness-transcript-contract.md)
28
+ distinguishes exported-transcript parsing, local-store discovery, and Vercel's
29
+ common harness interface.
30
+ The [native-history discovery comparison](research/2026-09-09-native-history-discovery.md)
31
+ checks the next step against Cass and Obelisk: Cass reads Cursor/OpenCode native
32
+ stores, while Obelisk has no provider for either at the inspected revision.
33
+ The [AgentsView native-reader audit](research/2026-09-09-agentsview-native-discovery.md)
34
+ adds snapshot, fingerprint and watch-plan evidence. Ledger now implements native
35
+ Cursor/OpenCode discovery and assembly while retaining Trajectory normalization;
36
+ see the [implementation verification](research/2026-09-09-native-history-implementation.md)
37
+ for tested boundaries, failed attempts and deployment status.
38
+ Their earlier PR comparisons retain their historical pins; use the integration
39
+ record above for current implementation status, not their in-progress findings.
40
+
41
+ ## Letta Trajectory
42
+
43
+ Source: [letta-ai/trajectory](https://github.com/letta-ai/trajectory)
44
+
45
+ Trajectory demonstrates that heterogeneous native agent transcripts can be
46
+ normalized into a stable canonical representation. Particularly important:
47
+
48
+ - source-specific adapters;
49
+ - stable source identity and ordering;
50
+ - canonical record and content hashes;
51
+ - deduplication-oriented records;
52
+ - explicit normalization diagnostics;
53
+ - support for partial transcript fragments.
54
+
55
+ Ledger uses the published `@letta-ai/trajectory` package. Retain this dependency
56
+ for canonicalization; any replacement requires evidence and an explicit decision.
57
+ The September 9 source refresh found upstream and installed version `0.3.0`
58
+ unchanged; integration did not replace the normalizer.
59
+ Parsing support does not imply local-store discovery: Cursor and OpenCode are
60
+ explicitly normalization-only sources in this version. Both public
61
+ `listTrajectories()` probes return `listing_unavailable`; callers must locate
62
+ the expected capture or assembled session export. Ledger now supplies native
63
+ SQLite/legacy discovery and assembly for these sources, plus validated capture
64
+ and export discovery. It does not classify arbitrary JSON/JSONL files as
65
+ conversations. See the [contract comparison](research/2026-09-09-harness-transcript-contract.md).
66
+ Trajectory is primarily a normalizer; Ledger's additional concern is the
67
+ durable system that stores, relates, enriches, and serves those records.
68
+
69
+ ## Letta Code continuous service and Dream
70
+
71
+ Source: [letta-ai/letta-code](https://github.com/letta-ai/letta-code)
72
+
73
+ Letta Code is a separate implementation reference from its Trajectory dependency.
74
+ Its server command exposes remote-computer and local App Server modes; the
75
+ runtime owns scheduled work and reflection integration. Relevant patterns are:
76
+
77
+ - explicit service startup, ownership and signal-driven shutdown;
78
+ - process-scoped scheduling with persisted ownership leases and run outcomes;
79
+ - reflection evaluation after a capture attempt, with duplicate-launch guards;
80
+ - explicit client-to-Cloud reflection ownership cutover;
81
+ - memory-worktree integration before reflection completion is finalized.
82
+
83
+ See the [pinned code review](research/2026-09-07-letta-continuous-service.md).
84
+ The September 9 refresh corrects the capture-success assumption: the listener
85
+ catches append failures and can still evaluate reflection. Ordering is not a
86
+ committed-evidence gate; Ledger must own that prerequisite.
87
+ These mechanisms do not establish an always-on cross-harness transcript indexer,
88
+ exactly-once execution, or measured memory bounds. Ledger keeps its own durable
89
+ ingestion and findings/promotion boundaries; this is not a new dependency.
90
+
91
+ ## Obelisk
92
+
93
+ Source: [tommy0103/obelisk](https://github.com/tommy0103/obelisk)
94
+
95
+ Obelisk demonstrates a useful execution-memory projection over native coding
96
+ agent history. Particularly important:
97
+
98
+ - one provider adapter contract over different native stores;
99
+ - a canonical record stream before persistence;
100
+ - explicit `agent_id` and `parent_tool_use_id` linkage;
101
+ - separate subagent, workflow, and workflow-agent records;
102
+ - raw-source lookup from normalized messages;
103
+ - SQLite and CodeAct queries as a practical local interface.
104
+
105
+ Obelisk's limitation for Ledger is not source availability: it is open source
106
+ under AGPL-3.0. The limitation is dependency shape. Its `@obelisk/core` workspace
107
+ is private and unpublished, and its capture is primarily post-hoc reconstruction
108
+ of harness-native artifacts. Ledger should not copy or embed that code without an
109
+ explicit licensing decision. An eventual Obelisk adapter should consume a stable
110
+ export, database contract, CLI/service boundary, or independently implemented
111
+ projection.
112
+
113
+ ## Cass
114
+
115
+ Source: [coding_agent_session_search](https://github.com/dicklesworthstone/coding_agent_session_search)
116
+ (indexed as `dicklesworthstone/cass` in Confer).
117
+
118
+ Research targets: cross-harness lexical, semantic and hybrid retrieval; machine
119
+ output contracts; incremental indexing; index health and recovery. Adopt proven
120
+ operational patterns while preserving Letta's canonicalization contract.
121
+ The September 9 refresh records a nonstandard license rider; these observations
122
+ are not clearance to reuse Cass's implementation or import its engine.
123
+ Its current Cursor/OpenCode connectors are re-exported from the pinned
124
+ `franken-agent-detection` crate. They read source-specific SQLite layouts and
125
+ selected native files, assembling their own normalized conversations rather
126
+ than calling Trajectory. The [native-history comparison](research/2026-09-09-native-history-discovery.md)
127
+ records exact coverage, exclusions, and the distinction from Ledger's scanner.
128
+
129
+ ## AgentsView
130
+
131
+ Source: [kenn-io/agentsview](https://github.com/kenn-io/agentsview)
132
+
133
+ Research targets: a writable daemon owning SQLite, file watching with periodic
134
+ reconciliation, initial synchronization, and a web surface for session retrieval.
135
+ Integrated `watch` reconciles at startup and on an interval, persists cursors with
136
+ records, skips unchanged sources, and budgets imports. JSONL uses a 1 MiB chunk
137
+ target with adaptive individual records up to 64 MiB by default. These are input
138
+ limits, not peak-RSS guarantees; non-JSONL adapters can still read whole inputs,
139
+ and continuity/session hashing can require history-linear work. Durable backfill
140
+ fairness, coverage reporting, participating-writer ownership and a web surface
141
+ remain followups; OS supervision alone does not provide them.
142
+
143
+ The [native-reader audit](research/2026-09-09-agentsview-native-discovery.md)
144
+ informed Ledger's independently implemented read-only SQLite snapshots, WAL-aware
145
+ invalidation, selective Cursor fields and legacy OpenCode joins. Native imports
146
+ rotate oldest attempts within the discovered page to prevent active sessions
147
+ starving older candidates; this is not full-corpus pagination or per-session
148
+ database digest optimization.
149
+
150
+ ## Vercel AI SDK v7 Harnesses
151
+
152
+ Source: [vercel/ai harness packages](https://github.com/vercel/ai/tree/main/packages/harness)
153
+
154
+ AI SDK Harnesses demonstrate a live cross-harness event boundary. Particularly
155
+ important:
156
+
157
+ - one stream contract for text, reasoning, tools, usage, file changes,
158
+ compaction, errors, and raw events;
159
+ - harness lifecycle state for suspend, continue, detach, and resume;
160
+ - turn, step, and tool telemetry;
161
+ - durable workflow checkpoints;
162
+ - pluggable harness adapters.
163
+
164
+ The unified stream is an excellent live ingestion seam, but it is not a canonical
165
+ trajectory store. Child-agent fidelity also varies by adapter, so Ledger must not
166
+ assume the top-level stream contains a complete nested execution.
167
+
168
+ ## Wake
169
+
170
+ Source: [iAmCorey/Wake](https://github.com/iAmCorey/Wake)
171
+
172
+ Wake is a native desktop application (Rust + GPUI, MIT) that aggregates
173
+ coding-agent sessions read-only from eighteen harness banks into one searchable,
174
+ resumable window. It is the closest product cousin so far — same inputs,
175
+ opposite shape: no daemon, no canonical record model, no retention; the human
176
+ surface instead of the durable store. Particularly important:
177
+
178
+ - copy-fallback read-only SQLite for locked stores: a probe query first, then a
179
+ copy of `db`/`-wal`/`-shm` into a temp dir, never `immutable=1`;
180
+ - FTS5 trigram tokenization with honest degradation — any query containing a
181
+ segment too short for trigram degrades entirely to `LIKE`, and the
182
+ degradation is returned to the caller, not swallowed — plus a separate
183
+ title index ranked ahead of body hits;
184
+ - a derive-rule version counter distinct from the schema version that forces
185
+ one full index re-derivation on upgrade;
186
+ - remote mirroring failure semantics: unreachable is never treated as empty,
187
+ partial is never complete, and the mirror cache has an explicit lifecycle;
188
+ - a per-agent resume capability table with a cwd precondition and refusal,
189
+ so no resume action exists that would only fail when clicked.
190
+
191
+ Evidence: [2026-09-14 confer deep-dive](../confer/2026-09-14-wake/wake.md),
192
+ pinned at `d9f702b6` (v0.6.5). Wake's whole-session replace without retained
193
+ generations, stats-only deduplication, and in-process-only scan lock are
194
+ counter-examples Ledger is already ahead of; its breadth extends the known
195
+ source space (Kiro, Antigravity metadata-only, Copilot `session-store.db`,
196
+ Gemini `tmp/**/chats`, Codex `archived_sessions`, OpenCode `opencode-next.db`)
197
+ beyond Ledger's current banks. MIT permits pattern reuse with attribution;
198
+ its UI crate reaches [`gpui`](https://github.com/zed-industries/zed) upstream,
199
+ which is GPL-3.0 per unaudited transitive license, so no UI code may be
200
+ vendored.
201
+
202
+ ## Concrete adoption plan
203
+
204
+ Target ownership is one Ledger service. Each inspiration supplies a specific
205
+ component or a pattern we can implement within it. Only Trajectory is an adopted
206
+ dependency; resemblance to another project's feature is not proof its code was
207
+ ported. This plan does not add dependencies or claim new runtime guarantees.
208
+
209
+ | Reference | How we use or learn from it | Ledger responsibility and state |
210
+ | --- | --- | --- |
211
+ | Letta Trajectory | Call the published normalizer from our adapters. | Native group identity is separate from Ledger keys; canonical records and cursors commit together. Recovered Claude prompt slices share identity helpers and migration coverage. Raw source retention and historical record versions remain future work. |
212
+ | Cass | Adapt machine-readable search, source-bound resume validation and operational recovery patterns. | Lexical/hybrid search, robot output and integration recovery regressions exist. Evidence-bearing completeness reporting, served-index validation and vague-query coverage remain targets; no separate Cass engine is proposed. |
213
+ | AgentsView | Follow daemon/watch/reconciliation and capture-publication boundaries; study evidence-bound findings and eligibility rechecks. | Startup/periodic reconciliation, import budgets, persisted cursors and staged replacement are integrated. Fair resumable backfill, visible coverage, raw retention and continuous findings publication remain work. Staged index replacement is not staged curation. |
214
+ | Obelisk | Study explicit delegation relationships and writer/transaction boundaries, then implement Ledger's contracts independently. | Source-backed parentage is integrated. Richer relationship provenance/conflicts, workflows and participating-writer coordination remain followups. No copying, vendoring or derived code without an explicit licensing decision. |
215
+ | AI SDK Harnesses | Add an optional live-event adapter for sessions we run through that interface. | Future input path. Persist event identity and replay progress; continue native-file ingestion for sessions outside that runtime. |
216
+ | Letta Code | Adapt service ownership, scheduled-run outcomes and reflection completion rules. | Future Dream worker over committed evidence. Analysis failures must not stop capture or search; publishing findings and promoting them into memory remain separate actions. |
217
+ | Wake | Evaluate copy-fallback read-only SQLite access and trigram tokenization against our locked-store coverage loss and the issue #34 common-prefix floor; hold its remote-mirroring truthfulness set (unreachable ≠ empty, partial ≠ complete) as the reference for the ADR-0005 cooperation tiers proposed in PR #13 (tracked in issue #14); borrow the derive-rule counter and title-index patterns when the search index next changes. | Patterns only; not a dependency (Rust desktop application, MIT). MIT permits adaptation with attribution; no UI code ([`gpui`](https://github.com/zed-industries/zed) upstream is GPL-3.0 per unaudited transitive license). |
218
+
219
+ The historical pinned [Confer review](research/2026-09-07-confer-inspirations.md) and
220
+ [Letta Code review](research/2026-09-07-letta-continuous-service.md) contain the
221
+ specific implementation ranges, caveats and proposed tests. For example,
222
+ [Trajectory explicitly assigns truncation/replacement generations to its caller](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/CANONICAL.md#L47-L94);
223
+ the library cannot make our mutable source files into an archive.
224
+
225
+ ### The data path
226
+
227
+ Target archival and continuous-curation architecture. The ingestion mechanics
228
+ above are integrated; retained raw generations, historical record versions,
229
+ the human UI and Dream below remain targets:
230
+
231
+ ```text
232
+ OS supervisor (launchd/systemd)
233
+ Ledger ingestion service: backfill + watch + periodic reconciliation
234
+ native files/databases or optional live events
235
+ -> retained raw source generations + provenance
236
+ -> adapters using Trajectory -> versioned canonical records
237
+ -> rebuildable search indexes -> agent CLI / human UI
238
+
239
+ Dream worker: committed evidence -> attributed, versioned findings
240
+ ```
241
+
242
+ Raw capture still needs a retention boundary before advancing capture progress.
243
+ Normalized records and cursors now commit together; that does not retain prior
244
+ raw generations. Search should be rebuildable from retained evidence. Watch
245
+ notifications reduce delay, reconciliation catches missed work, and supervision
246
+ handles process restart; operational acceptance remains pending. Scheduled Dream
247
+ and continuous curation are separate from ingestion and require durable findings,
248
+ invalidation and separately authorized promotion.
249
+
250
+ ### Start with the failure we actually encountered
251
+
252
+ The [eval-reference recovery](https://github.com/archeism/ledger/blob/43081aef54c23b4bd017b6c0e11fc42a9a1cb381/docs/case-studies/2026-09-09-recovering-the-eval-reference.md)
253
+ exposed both a missing source and a missing preservation guarantee. At the
254
+ research baseline `571c144`, `saveSession` replaced previous session records when
255
+ content changed. The merged integration now keeps existing sessions searchable
256
+ while a replacement is staged and promotes it transactionally, including after
257
+ restart. This improves snapshot-index recovery; it does not retain every source
258
+ generation after publication or establish the archival boundary above.
259
+
260
+ The smallest next implementation should preserve a captured source generation
261
+ before indexing it, track subsequent truncation/replacement explicitly, and prove
262
+ that the original reference survives source repair and a search-index rebuild.
263
+ Use a small synthetic fixture for the archival failure test; keep the private
264
+ recovery case as a separately scoped retrieval regression. Archival crash/restart,
265
+ duplicate-import and rebuild-from-retained-evidence gates are additional to the
266
+ integrated records/cursor and replacement-staging tests.
267
+
268
+ Recovered prompt-history slices now remain idempotent after migration. Complete
269
+ automatic coverage and fair, restart-resumable enumeration are not established
270
+ by the integrated reconciliation loop.
271
+ Coordinate CLI and daemon writers, expose unsupported/failed/pending sources, and
272
+ improve retrieval against the preserved failed queries. Extend relationship
273
+ provenance and workflows beyond current parentage; live capture, UI and Dream
274
+ remain later work. Explicit archive deletion and privacy exclusions need their
275
+ own policy; source truncation is not authorization to erase captured evidence.
276
+
277
+ ### How a borrowed pattern becomes a Ledger change
278
+
279
+ For each change: name the observed failure, cite the pinned upstream mechanism,
280
+ check the license and installed API, write a Ledger-owned failing test, implement
281
+ the smallest fix, and rerun the gate. Record whether we adopted a dependency,
282
+ adapted an algorithm or independently implemented behavior. Do not label code
283
+ clean-room merely because it was rewritten in another language.
284
+
285
+ No upstream code was copied for this plan. Ledger must establish its own storage,
286
+ progress, privacy and recovery guarantees through implementation and tests.
287
+
288
+ ## Session parentage coverage
289
+
290
+ Trajectory remains the record SoT. It does not store a parent/child session
291
+ edge (`source_group_id` is this transcript's own id; `MetaRecord` is cwd,
292
+ branch, and model). Ledger folds source-proved parentage beside those records.
293
+ Do not copy AGPL Obelisk code.
294
+
295
+ The upstream inventory below preserves the historical PR6 parentage comparison;
296
+ it is not a new census of current upstream support. The integration record and
297
+ September 9 research above distinguish merged behavior from remaining gaps.
298
+
299
+ | Inspiration | What it actually does with subagents |
300
+ |---|---|
301
+ | Trajectory | Lists Claude parent and standalone `subagents/` files as separate groups; drops sidechain rows inside a parent file; does **not** list OMP nested `<parent>/<child>.jsonl`; ATIF embedded `subagent_trajectories` are dropped. No parent field. |
302
+ | Obelisk | Five providers only: Claude (path + `.meta.json`, child folded into parent), Codex (`session_meta` / spawn, folded), Pi (`parentSession`), DeepSeek (`parentSession` + file tree), Kimi (`parent_tool_use_id`). DeepSeek and Kimi are not Ledger sources. |
303
+ | Cass | 26 connectors. Indexes Claude `subagents/` files as conversations, then **skips** them by default (`**/subagents/*.jsonl`). No parentage graph. |
304
+ | AgentsView | Broadest parentage map. Ledger overlap: Claude path/sessionId/meta, Codex `session_meta`, Pi `branchedFrom`, OMP `parentSession` + nested sibling, Hermes `parent_session_id`, OpenCode `parentID` / `parent_id`. Its OpenClaw parser ignores header parent fields. Cursor has a `subagents/` path in tests, not a parent field. Gemini CLI, OpenHands, and Copilot CLI have no session-parent field. Many AgentsView-only harnesses (Zed, Roo, Qoder, …) are out of Ledger scope. |
305
+ | AI SDK Harnesses | Live stream. Child-agent fidelity varies by adapter; not a transcript parentage SoT. |
306
+ | Letta Code service | Scheduling and Dream. Not parentage. |
307
+ | Wake (censused 2026-09-14 at `d9f702b6`, census persisted in the [confer file](../confer/2026-09-14-wake/wake.md) §7) | One durable single-parent edge (`sessions.parent_key`), produced only by Grok (its own subagent registry) and Hermes (same-profile `parent_id`); children flatten to the transitive root and inherit the parent's project. Claude `subagents/` files are discovered but hidden — attached to the mainline Task call by `tool_use_id`; their text is never indexed, so only the parent's Task call line is searchable. Cursor/CodeBuddy child dirs are hidden and unlinked; OMP/Pi nested files are standalone sessions; Codex `session_meta` is read for cwd/branch only, no parent. |
308
+
309
+ Integrated parentage sources (source-backed, independently implemented):
310
+ `claude-code`, `codex`, `pi`, `openclaw` (same SessionManager header), `omp`
311
+ (header plus nested sibling), `hermes`, `opencode` (`parentID` / SQLite
312
+ `parent_id`), `cursor` (`subagents/` path when present), `grok`
313
+ (`subagents/<child>/meta.json` registry under the parent, read at scan time) and
314
+ `kimi` (`<parent>/subagents/<agent>/` path under the parent's session directory,
315
+ plus the parent wire's `parent_tool_call_id` binding to the spawning call).
316
+
317
+ Left unimplemented until a source field or path proves the edge:
318
+ `gemini-cli`, `copilot-cli`, `letta-code`, `openhands`, `deepagents`, `droid`,
319
+ `atif`. OpenCode SQLite discovery and session/message/part assembly now exist;
320
+ the earlier extra-scanner discovery gap is superseded by the native readers.
@@ -0,0 +1,53 @@
1
+ # PR2 and PR6 integration
2
+
3
+ Integration commit: `9f52f8a`. PR2's identity, provider-aware enrichment, failure
4
+ isolation and reconciliation are retained alongside PR6's parentage, persisted
5
+ cursors, unchanged-source fast path, lexical-default watch and import budget.
6
+ No upstream normalization dependency was replaced.
7
+
8
+ ## Contracts verified
9
+
10
+ - Schema 6 distinguishes the experimental layouts by shape: main v3, PR2
11
+ identity v4, and PR6 parentage v4/cursor v5. Migration preserves source-scoped
12
+ sessions, records, FTS, embeddings and parent links without double-prefixing.
13
+ - Native group identities are passed to Trajectory; Ledger primary keys and
14
+ parent references are source-scoped. Recovered Claude prompt-history slices
15
+ use the same identity helpers and remain idempotent after migration.
16
+ - Records and cursors commit together. Existing sessions remain searchable while
17
+ a replacement is staged, including after restart; completed promotion is
18
+ transactional and streams staged records in bounded batches.
19
+ - JSONL reads use 1 MiB target chunks and adaptive individual records up to
20
+ 64 MiB by default. Prefix hashes and precise file identity validate continuity.
21
+ Incomplete lines do not advance progress; oversized rows warn without being
22
+ consumed. Raising the configured ceiling or ingestion version retries cached
23
+ failures. These input limits are not peak-RSS guarantees.
24
+ - Claude parent/standalone classification is bound to the source snapshot,
25
+ including a sidechain-only first chunk. Source-backed parent corrections,
26
+ whitespace rejection, native OMP header identities and diagnostic routing have
27
+ regressions. Cursor/Copilot line ordering uses the verified prefix line count;
28
+ canonical record identities and byte anchors remain unchanged.
29
+ - Watch startup and periodic reconciliation, missed-root discovery, import
30
+ budgets, append events, enrichment warnings and async shutdown drain are
31
+ covered. Source discovery paginates upstream's 1,000-item pages.
32
+
33
+ ## Verification
34
+
35
+ `bun test`: 152 passed, 0 failed, 959 assertions across 17 files.
36
+ `bun run typecheck` passed. Tests use bounded synthetic stores, not a broad
37
+ normalization of personal history. Fault cases were reproduced before fixes.
38
+
39
+ The daemon installers use `$XDG_DATA_HOME/ledger` or
40
+ `~/.local/share/ledger`, private creation permissions, all supported default
41
+ sources and an explicit large discovery limit. Runtime installation and
42
+ observation are separate from this test result.
43
+
44
+ ## Remaining boundaries
45
+
46
+ This remains a mutable-source snapshot index, not a raw-source archive.
47
+ Staging protects recall during rebuilding; it does not retain every historical
48
+ source generation after publication. First-chunk metadata and synthesized
49
+ timestamps are not universally identical to whole-file normalization.
50
+ Non-JSONL adapters can still read whole inputs. Changed-source prefix verification
51
+ and session-hash calculation require history-linear work; a source limit and
52
+ per-tick budget are not a durable fairness frontier. These remain explicit
53
+ targets for the follow-up observation and inspiration review.