trajectories 0.0.0 → 0.1.1
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.
- package/CHANGELOG.md +23 -0
- package/LICENSE +201 -0
- package/README.md +274 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +8542 -0
- package/dist/convert.d.ts +31 -0
- package/dist/convert.js +431 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8402 -0
- package/dist/log-baseline.d.ts +26 -0
- package/dist/log-baseline.js +104 -0
- package/dist/log-content.d.ts +16 -0
- package/dist/log-content.js +80 -0
- package/dist/log-io.d.ts +10 -0
- package/dist/log-io.js +121 -0
- package/dist/log-read.d.ts +24 -0
- package/dist/log-read.js +117 -0
- package/dist/log-reconcile.d.ts +5 -0
- package/dist/log-reconcile.js +38 -0
- package/dist/log-records.d.ts +35 -0
- package/dist/log-records.js +85 -0
- package/dist/log-recovery.d.ts +18 -0
- package/dist/log-recovery.js +123 -0
- package/dist/log-stage.d.ts +14 -0
- package/dist/log-stage.js +138 -0
- package/dist/log-state.d.ts +89 -0
- package/dist/log-state.js +92 -0
- package/dist/log-switch.d.ts +3 -0
- package/dist/log-switch.js +98 -0
- package/dist/log-types.d.ts +129 -0
- package/dist/log-types.js +8 -0
- package/dist/log.d.ts +8 -0
- package/dist/log.js +62 -0
- package/dist/migrate.d.ts +29 -0
- package/dist/migrate.js +173 -0
- package/dist/normalization-runtime.d.ts +1 -0
- package/dist/normalization-runtime.js +3150 -0
- package/dist/portable.d.ts +9 -0
- package/dist/portable.js +26 -0
- package/dist/readers/canonical.d.ts +13 -0
- package/dist/readers/canonical.js +54 -0
- package/dist/readers/cline.d.ts +10 -0
- package/dist/readers/cline.js +107 -0
- package/dist/readers/cursor.d.ts +20 -0
- package/dist/readers/cursor.js +374 -0
- package/dist/readers/deepagents.d.ts +41 -0
- package/dist/readers/deepagents.js +163 -0
- package/dist/readers/fx.d.ts +11 -0
- package/dist/readers/fx.js +573 -0
- package/dist/readers/github-copilot.d.ts +8 -0
- package/dist/readers/github-copilot.js +216 -0
- package/dist/readers/grok-build.d.ts +12 -0
- package/dist/readers/grok-build.js +391 -0
- package/dist/readers/guards.d.ts +4 -0
- package/dist/readers/guards.js +121 -0
- package/dist/readers/pi-compaction.d.ts +7 -0
- package/dist/readers/pi-compaction.js +112 -0
- package/dist/readers/pi-context.d.ts +13 -0
- package/dist/readers/pi-context.js +64 -0
- package/dist/store.d.ts +25 -0
- package/dist/store.js +218 -0
- package/dist/types.d.ts +91 -0
- package/dist/types.js +1 -0
- package/dist/writers/claude-code.d.ts +5 -0
- package/dist/writers/claude-code.js +51 -0
- package/dist/writers/cline.d.ts +3 -0
- package/dist/writers/cline.js +77 -0
- package/dist/writers/codex.d.ts +3 -0
- package/dist/writers/codex.js +32 -0
- package/dist/writers/cursor.d.ts +3 -0
- package/dist/writers/cursor.js +197 -0
- package/dist/writers/deepagents.d.ts +3 -0
- package/dist/writers/deepagents.js +116 -0
- package/dist/writers/entropy.d.ts +5 -0
- package/dist/writers/entropy.js +33 -0
- package/dist/writers/fx.d.ts +3 -0
- package/dist/writers/fx.js +135 -0
- package/dist/writers/github-copilot.d.ts +3 -0
- package/dist/writers/github-copilot.js +71 -0
- package/dist/writers/grok-build.d.ts +3 -0
- package/dist/writers/grok-build.js +43 -0
- package/dist/writers/helpers.d.ts +17 -0
- package/dist/writers/helpers.js +75 -0
- package/dist/writers/omp.d.ts +3 -0
- package/dist/writers/omp.js +7 -0
- package/dist/writers/opencode.d.ts +3 -0
- package/dist/writers/opencode.js +65 -0
- package/dist/writers/pi.d.ts +3 -0
- package/dist/writers/pi.js +45 -0
- package/docs/cline-native-format.md +43 -0
- package/docs/copilot-native-format.md +78 -0
- package/docs/cursor-native-format.md +103 -0
- package/docs/deepagents-native-format.md +98 -0
- package/docs/evidence-api.md +170 -0
- package/docs/fx-native-format.md +87 -0
- package/docs/harness-parity-bootstrap.md +78 -0
- package/docs/harness-support-parity.md +107 -0
- package/docs/inspirations.md +103 -0
- package/docs/ledger-migration.md +141 -0
- package/docs/pi-compaction-context.md +75 -0
- package/docs/pi-provider-context.md +76 -0
- package/docs/research/2026-10-06-huihua-and-oar.md +176 -0
- package/docs/research/ledger/README.md +96 -0
- package/docs/research/ledger/confer/2026-09-13-round-10/README.md +61 -0
- package/docs/research/ledger/confer/2026-09-13-round-2/cass.md +72 -0
- package/docs/research/ledger/confer/2026-09-13-round-3/README.md +70 -0
- package/docs/research/ledger/confer/2026-09-13-round-5/README.md +61 -0
- package/docs/research/ledger/confer/2026-09-13-round-6/README.md +68 -0
- package/docs/research/ledger/confer/2026-09-13-round-7/README.md +64 -0
- package/docs/research/ledger/confer/2026-09-13-round-9/README.md +59 -0
- package/docs/research/ledger/confer/2026-09-14-wake/wake.md +146 -0
- package/docs/research/ledger/docs/inspirations.md +320 -0
- package/docs/research/ledger/docs/pr2-pr6-integration.md +53 -0
- package/docs/research/ledger/docs/research/2026-09-07-confer-inspirations.md +163 -0
- package/docs/research/ledger/docs/research/2026-09-07-letta-continuous-service.md +104 -0
- package/docs/research/ledger/docs/research/2026-09-08-claude-history-retrieval.md +117 -0
- package/docs/research/ledger/docs/research/2026-09-09-agentsview-native-discovery.md +87 -0
- package/docs/research/ledger/docs/research/2026-09-09-daemon-observation.md +231 -0
- package/docs/research/ledger/docs/research/2026-09-09-discovery-pagination.md +114 -0
- package/docs/research/ledger/docs/research/2026-09-09-harness-transcript-contract.md +145 -0
- package/docs/research/ledger/docs/research/2026-09-09-native-history-discovery.md +180 -0
- package/docs/research/ledger/docs/research/2026-09-09-native-history-implementation.md +137 -0
- package/docs/research/ledger/docs/research/2026-09-09-other-inspirations.md +279 -0
- package/docs/research/ledger/docs/research/2026-09-09-trajectory-and-letta-code.md +128 -0
- package/docs/research/ledger/docs/research/2026-09-13-diagnostics-coverage.md +116 -0
- package/docs/research/ledger/docs/research/2026-09-13-fts-rebuild.md +83 -0
- package/docs/research/ledger/docs/research/2026-09-13-read-path-split.md +74 -0
- package/docs/research/ledger/docs/research/2026-09-13-runtime-rollout.md +102 -0
- package/docs/research/ledger/docs/research/2026-09-13-scan-outcomes.md +80 -0
- package/docs/research/ledger/docs/research/2026-09-13-search-quality.md +105 -0
- package/docs/research/ledger/docs/research/2026-09-13-source-coverage.md +64 -0
- package/docs/research/ledger/docs/research/2026-09-13-sync-wall-budget.md +82 -0
- package/docs/research/ledger/docs/research/2026-09-13-typed-read-gate.md +81 -0
- package/docs/research/ledger/docs/research/2026-09-13-writer-lease.md +84 -0
- package/docs/research/ledger/docs/research/2026-09-16-c1-copy-fallback.md +227 -0
- package/docs/research/ledger/docs/research/2026-09-16-c10-kimi.md +414 -0
- package/docs/research/ledger/docs/research/2026-09-16-c2-derive-counter.md +216 -0
- package/docs/research/ledger/docs/research/2026-09-16-c3-echo-filter.md +305 -0
- package/docs/research/ledger/docs/research/2026-09-16-c4-title-index.md +349 -0
- package/docs/research/ledger/docs/research/2026-09-16-c5-trigram.md +268 -0
- package/docs/research/ledger/docs/research/2026-09-16-c6-recency-prior.md +438 -0
- package/docs/research/ledger/docs/research/2026-09-16-c7-tombstones.md +467 -0
- package/docs/research/ledger/docs/research/2026-09-16-c8-remote-truth.md +390 -0
- package/docs/research/ledger/docs/research/2026-09-16-c9-grok.md +380 -0
- package/docs/research/ledger/docs/research/2026-09-16-wake-port-program.md +38 -0
- package/docs/research/ledger/docs/research/2026-09-17-cursor-blobstore.md +157 -0
- package/docs/research/ledger/manifest.json +540 -0
- package/legacy/NOTICE.md +50 -0
- package/legacy/bin/ledger-core.ts +7 -0
- package/legacy/bin/ledger.ts +7 -0
- package/legacy/bin/traj-bridge.ts +7 -0
- package/legacy/scripts/import-claude-history.ts +130 -0
- package/legacy/scripts/native-history-smoke.ts +52 -0
- package/legacy/scripts/observe-daemon.ts +570 -0
- package/legacy/scripts/retitle-sessions.md +19 -0
- package/legacy/scripts/verify-runtime-rollout.ts +151 -0
- package/legacy/src/canonical.ts +108 -0
- package/legacy/src/cli.ts +1293 -0
- package/legacy/src/db.ts +2254 -0
- package/legacy/src/diagnostics.ts +87 -0
- package/legacy/src/discovery.ts +56 -0
- package/legacy/src/embeddings.ts +382 -0
- package/legacy/src/filter.ts +602 -0
- package/legacy/src/gemini_embeddings.ts +103 -0
- package/legacy/src/identity.ts +9 -0
- package/legacy/src/index.ts +10 -0
- package/legacy/src/ingest.ts +791 -0
- package/legacy/src/managed.ts +178 -0
- package/legacy/src/native/common.ts +68 -0
- package/legacy/src/native/cursor.ts +647 -0
- package/legacy/src/native/grok.ts +540 -0
- package/legacy/src/native/kimi.ts +706 -0
- package/legacy/src/native/opencode.ts +470 -0
- package/legacy/src/native/sqlite-ro.ts +281 -0
- package/legacy/src/native.ts +97 -0
- package/legacy/src/normalizer.ts +457 -0
- package/legacy/src/parentage.ts +562 -0
- package/legacy/src/pressure.ts +162 -0
- package/legacy/src/private-storage.ts +74 -0
- package/legacy/src/reader.ts +1255 -0
- package/legacy/src/scanner.ts +591 -0
- package/legacy/src/schema-gate.ts +263 -0
- package/legacy/src/schema.ts +829 -0
- package/legacy/src/semantic-top-k.ts +71 -0
- package/legacy/src/session-hash.ts +49 -0
- package/legacy/src/store-status.ts +218 -0
- package/legacy/src/sync-preparation.ts +45 -0
- package/legacy/src/sync-truth.ts +843 -0
- package/legacy/src/sync.ts +1219 -0
- package/legacy/src/types.ts +436 -0
- package/legacy/src/vocab.txt +30522 -0
- package/legacy/src/watch.ts +673 -0
- package/legacy/src/writer-lease.ts +310 -0
- package/ops/README.md +120 -0
- package/ops/install-cli.sh +63 -0
- package/ops/install-release.sh +49 -0
- package/ops/linux/install-systemd-user.sh +103 -0
- package/ops/macos/install-launchd.sh +72 -0
- package/ops/sync-settings.sh +37 -0
- package/package.json +19 -5
- package/skills/trajectories/SKILL.md +138 -0
- package/skills/trajectories/scripts/trajectories_recent.sh +26 -0
- package/skills/trajectories/scripts/trajectories_search.sh +26 -0
- package/index.js +0 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Trajectory and Letta Code: integration evidence
|
|
2
|
+
|
|
3
|
+
Source refresh: 2026-09-09. Retain published `@letta-ai/trajectory` for canonical
|
|
4
|
+
normalization; adapt selected Letta Code lifecycle contracts independently. Letta
|
|
5
|
+
Code is not an adopted dependency or a replacement for Ledger's durable store.
|
|
6
|
+
This addendum supplements the [prior comparison](2026-09-07-confer-inspirations.md)
|
|
7
|
+
and [service review](2026-09-07-letta-continuous-service.md), without repeating them.
|
|
8
|
+
|
|
9
|
+
## Pins and scope
|
|
10
|
+
|
|
11
|
+
| Inspected source | Exact commit | Version / boundary |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| letta-ai/trajectory | `21ae92d10579499b183d93929c85da0b91233167` | GitHub HEAD and npm latest were still `0.3.0`, unchanged from the prior research; installed package agreed. `NORMALIZER_VERSION=0.3.0`, `CANONICAL_SCHEMA_VERSION=3`. [Constants](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/src/version.ts#L1-L16) |
|
|
14
|
+
| letta-ai/letta-code | `170a6d190eb70b65ebf0d4e1683f971e18633997` | Package `0.31.14`; pins Trajectory **`0.2.0`**, not `0.3.0`. [Package](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/package.json#L1-L3), [dependency](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/package.json#L123-L135) |
|
|
15
|
+
| Ledger research baseline | `571c14498acad05c89d2fefc14b8ee3ae775fd11` | Original `main` inspected during the source refresh. |
|
|
16
|
+
| Ledger PR2 research head | `94f70c5fa46fcc8f5ccbdf477d67c0cd2c4a32cc` | Historical comparison point, not the final merged PR2 head. |
|
|
17
|
+
| Ledger PR6 research head | `1efa46d9ac7164f2c32b2a47957b6ea732322f8d` | Historical comparison point, before current integration repairs. |
|
|
18
|
+
|
|
19
|
+
At preservation time, this worktree starts at PR2's merge commit
|
|
20
|
+
`7fe199ce9d62e4a9e966aff18b7c33eda917ac40`. The coordinator reports PR6 integration
|
|
21
|
+
underway with Ledger DB schema 6, atomic cursor commits, and bounded chunks. Those
|
|
22
|
+
changes were not evaluated by this source pass: the old PR findings below must
|
|
23
|
+
not be presented as current-main failures or as verified repairs.
|
|
24
|
+
|
|
25
|
+
Evidence came from fresh primary GitHub source/API reads, with both upstream HEADs
|
|
26
|
+
rechecked during the pass. Confer's direct shell was unavailable; registrar and
|
|
27
|
+
doctor checks found a usable queue, but job
|
|
28
|
+
`499e3ea4-cc67-4619-b200-c895c4231a14` failed because Letta Code was absent from its
|
|
29
|
+
catalog. That job supplies no findings. Upstream test source was inspected, not
|
|
30
|
+
run. No daemon/runtime verification is claimed here; main owns that observation.
|
|
31
|
+
No upstream clones, native transcript inspection, or secret values are included.
|
|
32
|
+
|
|
33
|
+
## Canonical contract already available in 0.3.0
|
|
34
|
+
|
|
35
|
+
- **Identity and versions are separate.** `record_id` hashes native group,
|
|
36
|
+
source-record identity, and semantic component key, without source type.
|
|
37
|
+
Native/location identities support conflict detection; content fallback only
|
|
38
|
+
supports exact dedup. `content_hash` covers normalized semantic content;
|
|
39
|
+
`record_hash` covers the full normalized record, including timestamps.
|
|
40
|
+
Ledger supplies source scope, content versions, and durable ingestion order.
|
|
41
|
+
[Implementation](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/src/canonical.ts#L43-L153)
|
|
42
|
+
- **Partial is not arbitrary streaming.** Explicit `partial:true` permits an
|
|
43
|
+
initial single-role fragment; a positive `baseByteOffset` implies partial mode.
|
|
44
|
+
Canonical meta appears only at offset zero, and cross-chunk tool results retain
|
|
45
|
+
their call IDs. Byte offsets affect byte anchors, not ordinals: id-less Letta
|
|
46
|
+
Code rows are ordinal-anchored. Preserve native group context and test each
|
|
47
|
+
adapter's chunk equivalence rather than generalizing from JSONL syntax.
|
|
48
|
+
[API](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/src/index.ts#L94-L172),
|
|
49
|
+
[tests](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/test/canonical.test.ts#L468-L584),
|
|
50
|
+
[Letta ordinal fallback](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/src/adapters/letta-code/index.ts#L60-L69)
|
|
51
|
+
- **Normalization is neither raw retention nor an ingestion engine.** The API
|
|
52
|
+
accepts a complete string; JSONL parsing builds arrays and skips malformed rows
|
|
53
|
+
with diagnostics. Tool argument/result bounds cap fields, not peak memory.
|
|
54
|
+
Canonical JSON preserves emitted normalized records, not original source bytes.
|
|
55
|
+
Persist diagnostics and the returned normalizer/schema/effective configuration.
|
|
56
|
+
[Parser](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/src/adapters/shared.ts#L10-L45),
|
|
57
|
+
[bounds](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/src/bounds.ts#L17-L24),
|
|
58
|
+
[result envelope](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/src/canonical.ts#L338-L349)
|
|
59
|
+
|
|
60
|
+
## Letta Code's actual use, not inferred infrastructure
|
|
61
|
+
|
|
62
|
+
- **Historical export:** discovery feeds whole-input `normalizeTranscript` calls,
|
|
63
|
+
JSON files, and a manifest, defaulting to `/tmp/letta-trajectories`. Re-export
|
|
64
|
+
removes previous export contents. Search scans user/assistant prose for a
|
|
65
|
+
case-insensitive substring. This path is a replaceable export, not canonical
|
|
66
|
+
persistence, incremental sync, or a continuously maintained search index.
|
|
67
|
+
[CLI](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/cli/subcommands/trajectories.ts#L23-L62),
|
|
68
|
+
[export implementation](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/cli/subcommands/trajectories/export.ts#L150-L334),
|
|
69
|
+
[query implementation](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/cli/subcommands/trajectories/review.ts#L167-L200)
|
|
70
|
+
- **Own-turn capture and correction to the prior review:** native rows append to
|
|
71
|
+
`$LETTA_TRANSCRIPT_ROOT` or `~/.letta/transcripts/<agent>/<conversation>/transcript.jsonl`,
|
|
72
|
+
with a separate `state.json`. Reflection later calls `normalizeTranscript` with
|
|
73
|
+
`partial:true`, not `normalizeToCanonical`. The listener attempts capture before
|
|
74
|
+
reflection, but **catches append failure and still evaluates reflection**.
|
|
75
|
+
Therefore the prior capture-before-trigger observation is ordering, not a
|
|
76
|
+
capture-success gate. Ledger must define its own committed-evidence prerequisite.
|
|
77
|
+
[Root](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/utils/transcript-paths.ts#L4-L21),
|
|
78
|
+
[capture](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/cli/helpers/reflection-transcript.ts#L914-L952),
|
|
79
|
+
[normalization](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/cli/helpers/reflection-transcript.ts#L630-L641),
|
|
80
|
+
[decisive caller](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/websocket/listener/turn-completion.ts#L67-L105)
|
|
81
|
+
- **Sync, watch, and query boundaries:** completion sync sends Cloud a
|
|
82
|
+
`reflected_through_message_id`; the inspected filesystem watcher watches new
|
|
83
|
+
worktrees, not harness history. Separate local-backend search treats vector and
|
|
84
|
+
hybrid requests as FTS-lite without a vector index. None proves fleet transcript
|
|
85
|
+
synchronization or continuous cross-harness indexing.
|
|
86
|
+
[Completion sync](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/cli/helpers/reflection-completion.ts#L40-L130),
|
|
87
|
+
[watcher](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/websocket/listener/worktree-watcher.ts#L120-L158),
|
|
88
|
+
[local query](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/backend/local/transcript-search.ts#L409-L460)
|
|
89
|
+
- **Useful later Dream contracts:** reflection completion is gated on memory
|
|
90
|
+
integration, not merely subagent success. Cron has persisted PID/token ownership
|
|
91
|
+
and run outcomes, but per-minute dedup remains in memory. Adapt explicit
|
|
92
|
+
ownership and completion semantics; do not inherit an exactly-once claim.
|
|
93
|
+
[Integration gate](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/cli/helpers/reflection-launcher.ts#L628-L634),
|
|
94
|
+
[completion caller](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/cli/helpers/reflection-launcher.ts#L868-L906),
|
|
95
|
+
[lease](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/cron/cron-file.ts#L646-L682),
|
|
96
|
+
[dispatch](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/src/cron/scheduler.ts#L498-L594)
|
|
97
|
+
|
|
98
|
+
## Historical PR findings versus remaining architecture
|
|
99
|
+
|
|
100
|
+
| Pinned observation before integration | Disposition / minimal Ledger-owned contract |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| PR2 scopes Ledger IDs; PR6 passes stored session IDs as native `groupId`. The branches also assigned incompatible meanings to DB migration v4. [PR2 identity](https://github.com/archeism/ledger/blob/94f70c5fa46fcc8f5ccbdf477d67c0cd2c4a32cc/packages/core/src/normalizer.ts#L102-L106), [PR6 handoff](https://github.com/archeism/ledger/blob/1efa46d9ac7164f2c32b2a47957b6ea732322f8d/packages/core/src/ingest.ts#L196-L217), [PR2 migration](https://github.com/archeism/ledger/blob/94f70c5fa46fcc8f5ccbdf477d67c0cd2c4a32cc/packages/core/src/schema.ts#L76-L107), [PR6 migration](https://github.com/archeism/ledger/blob/1efa46d9ac7164f2c32b2a47957b6ea732322f8d/packages/core/src/schema.ts#L117-L145) | Integration concern, not a newly asserted main defect. Schema-6 work is underway. Keep Ledger-scoped keys distinct from native group identity, including append paths and relationships; cover both historical DB shapes. |
|
|
103
|
+
| PR6 commits records, optionally awaits embeddings, then writes its cursor separately. [Sequencing](https://github.com/archeism/ledger/blob/1efa46d9ac7164f2c32b2a47957b6ea732322f8d/packages/core/src/ingest.ts#L132-L144) | Atomic-cursor integration is underway. Commit canonical records and normalization progress together; keep embeddings retryable enrichment outside that boundary. |
|
|
104
|
+
| PR6 assumes growth means append continuity, initializes progress from full file size, and allocates the entire suffix. A skipped incomplete initial row can be lost if its later suffix contains other valid rows. [Initial cursor/growth](https://github.com/archeism/ledger/blob/1efa46d9ac7164f2c32b2a47957b6ea732322f8d/packages/core/src/ingest.ts#L119-L168), [suffix read](https://github.com/archeism/ledger/blob/1efa46d9ac7164f2c32b2a47957b6ea732322f8d/packages/core/src/ingest.ts#L225-L241) | Bounded-chunk integration is underway. Complete-byte cursors, UTF-8/partial-line handling, and adapter-specific replay equivalence are the contracts to validate, not claims established here. |
|
|
105
|
+
| PR6 skips existing record IDs without comparing semantic hashes; changed full sessions still replace prior records. [Append dedup](https://github.com/archeism/ledger/blob/1efa46d9ac7164f2c32b2a47957b6ea732322f8d/packages/core/src/db.ts#L385-L418), [replacement](https://github.com/archeism/ledger/blob/1efa46d9ac7164f2c32b2a47957b6ea732322f8d/packages/core/src/db.ts#L306-L349) | Separate archival/versioning followup. Atomic cursors and bounded chunks alone do not establish retained source generations, content-conflict handling, or rebuildable evidence. |
|
|
106
|
+
|
|
107
|
+
Remaining architecture: retain raw source generations/range digests before
|
|
108
|
+
advancing capture progress; bind normalization to normalizer/schema/config
|
|
109
|
+
versions and diagnostics; version or quarantine same-identity semantic conflicts.
|
|
110
|
+
Keep source timestamps descriptive, not ingestion cursors. Dream needs durable
|
|
111
|
+
jobs, evidence-bound publication/invalidation, and separate promotion authority;
|
|
112
|
+
fleet/live capture needs explicit identity and privacy contracts. These are
|
|
113
|
+
separately scoped Ledger-owned followups, not supplied upstream features. This
|
|
114
|
+
source note does not certify implementation status or merge readiness.
|
|
115
|
+
|
|
116
|
+
## Adoption and licensing
|
|
117
|
+
|
|
118
|
+
Adopt the published Trajectory API; independently implement Ledger's storage and
|
|
119
|
+
progress contracts. Learn from Letta Code's explicit ownership and integration
|
|
120
|
+
completion gate, not its replaceable export directory, in-memory cron dedup, or
|
|
121
|
+
best-effort capture ordering. No upstream implementation was copied or vendored.
|
|
122
|
+
|
|
123
|
+
Both inspected upstream repositories declare Apache-2.0; applicable licenses and
|
|
124
|
+
notices still apply. [Trajectory license](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/LICENSE),
|
|
125
|
+
[Letta Code license](https://github.com/letta-ai/letta-code/blob/170a6d190eb70b65ebf0d4e1683f971e18633997/LICENSE).
|
|
126
|
+
Ledger's [repository guidance](https://github.com/archeism/ledger/blob/43081aef54c23b4bd017b6c0e11fc42a9a1cb381/AGENTS.md#licensing) still records no selected
|
|
127
|
+
project license and prohibits copying/vendoring/deriving Obelisk code without an
|
|
128
|
+
explicit licensing decision. No new dependency or licensing decision is made here.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Durable normalization diagnostics as coverage records, 2026-09-13
|
|
2
|
+
|
|
3
|
+
## Outcome
|
|
4
|
+
|
|
5
|
+
Ledger now persists the normalization diagnostics of `@letta-ai/trajectory`
|
|
6
|
+
as durable, attributable coverage records (schema v9 `ingest_diagnostics`)
|
|
7
|
+
and surfaces them through `ledger status`. Before this change the diagnostics
|
|
8
|
+
were collected by the normalizer and dropped by `ingest.ts`; the only honest
|
|
9
|
+
signal of lossiness (for example `tool_result_truncated` under the default
|
|
10
|
+
2,500-code-point tool-result bound) was invisible in the store, the CLI, and
|
|
11
|
+
the robot contract.
|
|
12
|
+
|
|
13
|
+
The increment is stacked on PR16's `codex/ledger-cli-evaluation` head because
|
|
14
|
+
the status surface and `store-status.ts` live there. PR8-owned behavior is
|
|
15
|
+
untouched; the one PR8-file edit (`normalizer.ts`) is an additive export.
|
|
16
|
+
|
|
17
|
+
## Evidence chain
|
|
18
|
+
|
|
19
|
+
- Round-1 Confer research pinned the upstream contract:
|
|
20
|
+
diagnostic codes are additive and never repurposed, and diagnostic text
|
|
21
|
+
never contains raw transcript content
|
|
22
|
+
(`letta-ai/trajectory@21ae92d10579499b183d93929c85da0b91233167:CANONICAL.md#L204-L209`,
|
|
23
|
+
`src/types.ts#L96-L118`), which makes the messages safe to persist verbatim.
|
|
24
|
+
- The dropped-plumbing defect was verified locally at base `988f52e`:
|
|
25
|
+
`packages/core/src/normalizer.ts#L98` returns
|
|
26
|
+
`NormalizedSessionResult.diagnostics`; `ingest.ts` never read the field.
|
|
27
|
+
- The installed `Diagnostic` shape (`dist/types.d.ts#L67-L73`) is
|
|
28
|
+
`{ code, message, inputLine?, recordIndex?, count? }` — there is no severity
|
|
29
|
+
field anywhere in the package, so the design's severity column was dropped
|
|
30
|
+
rather than stored permanently NULL. `count` is pre-aggregated by upstream
|
|
31
|
+
for `timestamps_interpolated`/`timestamps_synthesized` and summed honestly.
|
|
32
|
+
- Gap alignment: `docs/inspirations.md` names "expose unsupported/failed/
|
|
33
|
+
pending sources" and evidence-bearing completeness reporting as remaining
|
|
34
|
+
work; AgentsView's doctor is the per-root ok/missing/error pattern and Cass
|
|
35
|
+
carries a `_meta.search_completeness` field for the same reason. This is
|
|
36
|
+
Ledger's first durable piece of that surface.
|
|
37
|
+
|
|
38
|
+
## Design
|
|
39
|
+
|
|
40
|
+
- `ingest_diagnostics` is keyed `(session_id, code)`; `source` is stored for
|
|
41
|
+
filtering. Rows carry `occurrence_count`, a bounded code-point-safe
|
|
42
|
+
`sample` (last message, ≤200 code points), and `first_seen_at` /
|
|
43
|
+
`last_seen_at`. Sessions are globally unique by id, so replacement and
|
|
44
|
+
deletion key on `session_id` alone.
|
|
45
|
+
- Replacement semantics, not accumulation: each successful whole-file
|
|
46
|
+
normalization replaces the session's rows inside the same transaction as
|
|
47
|
+
records and cursor. Identical re-imports are idempotent; counts never
|
|
48
|
+
double; a session that normalizes cleanly loses its old rows.
|
|
49
|
+
- Chunked honesty: a pass publishes live coverage only when it normalized the
|
|
50
|
+
whole file itself (`!append && complete`). Multi-chunk rebuilds merge each
|
|
51
|
+
chunk's aggregate into the stage (`ingest_staged_sessions.diagnostics_json`,
|
|
52
|
+
durable across restarts) and publish the union at promotion. A promotion
|
|
53
|
+
with no aggregate clears rows instead of keeping the predecessor's —
|
|
54
|
+
unknown beats wrong. Live append continuations keep the last whole-file
|
|
55
|
+
coverage and are documented as not re-counting appended content.
|
|
56
|
+
- `ledger build` (the `saveSession` path) publishes the same coverage so a
|
|
57
|
+
build-populated store cannot silently report zero findings.
|
|
58
|
+
- Status surface: robot/JSON gains an additive `diagnostics` object
|
|
59
|
+
(`{ totalSessions, totalOccurrences, byCode[] }`), `null` on stores that
|
|
60
|
+
predate the table (read-only `sqlite_master` probe — `status` still never
|
|
61
|
+
migrates); human output distinguishes `unknown (store predates diagnostics
|
|
62
|
+
schema)`, `none`, and the findings block (top codes by occurrences).
|
|
63
|
+
- Invariant hardening: an `AFTER DELETE ON sessions` trigger removes a
|
|
64
|
+
session's diagnostics rows even when a raw connection has
|
|
65
|
+
`foreign_keys=OFF`; promotion also deletes explicitly.
|
|
66
|
+
- `commitIngest`/`commitStagedIngest` take an options object for the new
|
|
67
|
+
payload (`{ diagnostics? }`) so later extensions (PR8 adds
|
|
68
|
+
`allowPathReplacement` positionally) cannot hit parameter-order traps.
|
|
69
|
+
|
|
70
|
+
## Verification
|
|
71
|
+
|
|
72
|
+
Independent verifier round (scripts under `/tmp/dx-verify`, base worktree at
|
|
73
|
+
`988f52e`, changed tree uncommitted; every number below is from that round):
|
|
74
|
+
|
|
75
|
+
- Stability: full suite 289 pass / 0 fail / 1846 assertions across 26 files,
|
|
76
|
+
three consecutive runs (25.9s, 25.5s, 25.3s). Base tree: 269 / 0 / 1670
|
|
77
|
+
across 25 files, three runs. Typecheck and build clean.
|
|
78
|
+
- Transient-failure chase: one new e2e test initially re-downloaded a 22 MB
|
|
79
|
+
ONNX model per run under an isolated HOME (35.5 s wall, bun 5 s timeout,
|
|
80
|
+
5/5 individual timeouts); root-caused and fixed to inherit HOME like the
|
|
81
|
+
sibling subprocess tests (0.49 s with the shared model cache).
|
|
82
|
+
- Capability: 16/16 assertions on a fresh mixed corpus via the canonical CLI
|
|
83
|
+
(`build` + `status --robot`): 3 truncation occurrences attributed to exactly
|
|
84
|
+
the loud session; clean corpus reports `none`; rewriting the source clean
|
|
85
|
+
makes findings disappear (no accumulation). Negative control on the base
|
|
86
|
+
tree scores 2/16 — the base payload has no diagnostics key at all.
|
|
87
|
+
- Atomicity probe: a poisoned aggregate (null code) throws inside
|
|
88
|
+
`commitIngest`; sessions, records, cursor, and diagnostics all roll back
|
|
89
|
+
together (7/7). Staged-union probe: a rebuild consumed across five chunk
|
|
90
|
+
passes published exactly the whole-file ground truth at promotion (5/5).
|
|
91
|
+
- Overhead (N=30 passes, 12-session corpus, embeddings disabled, same script
|
|
92
|
+
bytes on both trees): ingest median 44.1 ms base vs 44.4 ms changed
|
|
93
|
+
(+0.8%, ranges overlap); records/pass and sessions/pass identical
|
|
94
|
+
(236/12). In-process `readStoreStatus` gains ~50 µs; CLI `status --robot`
|
|
95
|
+
wall time is indistinguishable (bun startup dominates).
|
|
96
|
+
- Migration: 19/19 assertions. A v8 store stays v8 under read-only status
|
|
97
|
+
(`diagnostics: null`, human `unknown`), upgrades on the next writer open
|
|
98
|
+
with zero fabricated rows, and a raw `DELETE FROM sessions` under
|
|
99
|
+
`foreign_keys=OFF` still removes the session's diagnostics rows (trigger).
|
|
100
|
+
|
|
101
|
+
## Boundaries
|
|
102
|
+
|
|
103
|
+
- Occurrence units are per-code heterogeneous (records-affected for
|
|
104
|
+
`timestamps_*`, diagnostic counts elsewhere) — documented on the type, not
|
|
105
|
+
normalized away.
|
|
106
|
+
- Ledger's own `warning()` strings (paths, budgets) remain transient ingest
|
|
107
|
+
results by scope decision; persisting them is follow-up work with a
|
|
108
|
+
privacy decision attached.
|
|
109
|
+
- Brand-new multi-chunk listings publish no coverage until a whole-file
|
|
110
|
+
normalization happens (documented residual; closing it requires staging
|
|
111
|
+
cold partial passes, which the existing ingest-staging contract pins
|
|
112
|
+
against). Zero rows therefore render as `none`, indistinguishable from an
|
|
113
|
+
observed-clean pass for such sessions.
|
|
114
|
+
- No raw source retention: this records the normalizer's observations, not
|
|
115
|
+
source bytes. The archival boundary remains open with its own policy.
|
|
116
|
+
- No upstream code copied; Trajectory remains the only adopted dependency.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# FTS rebuild migration (schema v11) and the measured rejection of the prefix index, 2026-09-13
|
|
2
|
+
|
|
3
|
+
## Outcome
|
|
4
|
+
|
|
5
|
+
Cycle 2's query widening is inert on the production store: 156,801
|
|
6
|
+
records always exceeded `LEDGER_WIDEN_MAX_RECORDS` (10,000), and widened
|
|
7
|
+
queries measured 0.14–1.5 s there. This cycle set out to add an FTS5
|
|
8
|
+
`prefix=` index and **measurement rejected it**: on a byte-consistent
|
|
9
|
+
copy of the live store, prefix options ('2 3', '2 3 4') added
|
|
10
|
+
+106–151 MB (+13–19% store) and ~+35% ingest write cost with **no
|
|
11
|
+
measurable latency benefit** — the residual cost for common short
|
|
12
|
+
prefixes is match-set/bm25 evaluation, not the index seek. The shipped
|
|
13
|
+
increment is what the measurement actually validated: a one-time
|
|
14
|
+
**rebuild of `records_fts`** (schema v11), which made widened queries
|
|
15
|
+
5–10× faster and exact-term queries 8–80× faster at near-zero size cost,
|
|
16
|
+
plus a measured-basis raise of the widening ceiling to 250,000 records.
|
|
17
|
+
Closes #21.
|
|
18
|
+
|
|
19
|
+
## Design
|
|
20
|
+
|
|
21
|
+
- FTS5 virtual tables cannot be `ALTER`ed; the migration (inside the
|
|
22
|
+
existing crash-atomic `migrate()` transaction, under the writer lease)
|
|
23
|
+
drops and recreates `records_fts` with the **unchanged** DDL and
|
|
24
|
+
repopulates from `records` via a projection mirroring
|
|
25
|
+
`insertRecordsInternal` value-for-value (single DDL constant shared by
|
|
26
|
+
fresh stores and the rebuild so they cannot drift). Post-copy gates
|
|
27
|
+
inside the transaction: row parity (`records` vs `records_fts` counts)
|
|
28
|
+
and the FTS5 `integrity-check` command — a failure aborts and leaves
|
|
29
|
+
v10 authoritative. `user_version = 11` is the marker. The gates also
|
|
30
|
+
heal drift (lost/orphan FTS rows).
|
|
31
|
+
- Widening ceiling `DEFAULT_WIDEN_MAX_RECORDS` 10,000 → 250,000, on the
|
|
32
|
+
measured basis below; `LEDGER_WIDEN_MAX_RECORDS` semantics unchanged.
|
|
33
|
+
|
|
34
|
+
## Verification (two independent measurement rounds + adversarial audit)
|
|
35
|
+
|
|
36
|
+
All numbers from byte-consistent copies of the live store
|
|
37
|
+
(156,801 records / 811 MB):
|
|
38
|
+
|
|
39
|
+
- **Rebuild cost**: wall 11.5 s idle / 35.6–38.1 s under host load; WAL
|
|
40
|
+
peak 274 MiB (~2.8% of volume headroom), truncated after commit; net
|
|
41
|
+
store +1.8 MB; parity and integrity-check pass inside the migration.
|
|
42
|
+
Concurrent writers refuse fast via the cycle-3 lease (250 ms → typed
|
|
43
|
+
`WRITER_BUSY`) instead of blocking behind the ~27 s write-lock hold;
|
|
44
|
+
readers unaffected (WAL).
|
|
45
|
+
- **Latency (engine ms, old → rebuilt)**: widened zero-hit probes
|
|
46
|
+
'records sqlite' 890 → 85/60; 'daemon watchdog' 178 → 19/37;
|
|
47
|
+
'canonical trajectory' 219 → 106/130 (idle round) and 840 → 474 first /
|
|
48
|
+
42 → 40 warm, 3456 → 1731 widened (loaded round — magnitudes are
|
|
49
|
+
load-dependent; direction unanimous). Exact-term probes 88 → 5.6,
|
|
50
|
+
82 → 10.8, 55 → 0.8, 34 → 1.0, 78 → 9.9 ms. Common short prefixes
|
|
51
|
+
('the*', 'run*') remain ~0.46–0.69 s in every shape — match-set-bound,
|
|
52
|
+
documented as the residual cost class.
|
|
53
|
+
- **Result equality**: 10/10 and 8/8 probe queries (widened and exact)
|
|
54
|
+
byte-identical hits, order, ranks, snippets across the rebuild.
|
|
55
|
+
FTS rowids are remapped; no consumer depends on them (verified).
|
|
56
|
+
- **Prefix option (rejected)**: rebuild-without-prefix vs
|
|
57
|
+
'2 3 4' on identical content — widened queries within noise;
|
|
58
|
+
+151 MB size, 10,772 → 32,129 idx rows; 5,000-record ingest
|
|
59
|
+
1,919 → 2,595 ms (+35%), WAL 65.5 → 87.9 MB.
|
|
60
|
+
- **Rollback atomicity**: killed mid-migration → `user_version` stays
|
|
61
|
+
10, index DDL and rows byte-identical, next open migrates cleanly.
|
|
62
|
+
- **Audit fixes before shipping**: both post-copy gates now pinned by
|
|
63
|
+
real-mismatch tests (mutations that neutralize either gate fail the
|
|
64
|
+
suite); the fresh-segments rationale was itself falsified by
|
|
65
|
+
measurement (the rebuilt index has *more* segments on the maintained
|
|
66
|
+
store — the win is empirical, mechanism-neutral); binary-skew and
|
|
67
|
+
marker-only-revert documented; tool-result fallback pinned by column
|
|
68
|
+
value.
|
|
69
|
+
- **Suite**: 522+ pass / 0 fail across 35 files (post-fix count per the
|
|
70
|
+
final round); typecheck/build clean.
|
|
71
|
+
|
|
72
|
+
## Boundaries
|
|
73
|
+
|
|
74
|
+
- The daemon's first post-merge writer open performs the one-time
|
|
75
|
+
migration on the live store (~30–40 s on this volume, under the
|
|
76
|
+
lease); pre-change binaries refuse a v11 store with the standard
|
|
77
|
+
too-new error — rollback is the `user_version` marker alone (the DDL
|
|
78
|
+
is unchanged).
|
|
79
|
+
- Common-prefix widened queries remain ~0.5 s at this corpus size — a
|
|
80
|
+
ranking/candidate-cap question, not an index question; recorded.
|
|
81
|
+
- Rebuild cadence: the v11 rebuild is one-time; periodic re-defragment
|
|
82
|
+
(Cass-style reconciler) is not included — `automerge=4` plus the
|
|
83
|
+
existing maintenance merge remain the steady-state discipline.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Read-path connection split, 2026-09-13
|
|
2
|
+
|
|
3
|
+
## Outcome
|
|
4
|
+
|
|
5
|
+
Read verbs (`search`, `recent`, `emit-pi`) opened the write-bearing
|
|
6
|
+
`TrajectoryDb`, whose constructor always writes (WAL pragma,
|
|
7
|
+
`CREATE_TABLES_SQL`, trigger repair; migrations on old schemas) — so a
|
|
8
|
+
search could create or upgrade a store outside the writer lease, and a
|
|
9
|
+
`--semantic` query backfilled embeddings mid-read. This cycle introduces
|
|
10
|
+
`TrajectoryReader`: a strictly read-only connection (`readonly: true` open
|
|
11
|
+
flag — engine-enforced, irreversible; never `query_only`) with typed
|
|
12
|
+
refusals (`STORE_NOT_INITIALIZED`, `SCHEMA_MISMATCH`, `STORE_UNREADABLE`),
|
|
13
|
+
no DDL/migration/repair, and no embedding writes. Semantic/hybrid without
|
|
14
|
+
usable embeddings answers lexically and says so via the cycle-2 envelope
|
|
15
|
+
trio (`search_mode: "lexical"`, `requested_search_mode` as requested,
|
|
16
|
+
`fallback_reason: "embeddings_unavailable"`) — the designed first use of
|
|
17
|
+
that field pair. Closes issue #23's read-side; the lease boundary from
|
|
18
|
+
cycle 3 is now complete.
|
|
19
|
+
|
|
20
|
+
Query internals were extracted and shared between the writer and reader
|
|
21
|
+
handles, so widening, envelope, provenance, and fusion cannot drift; the
|
|
22
|
+
cycle-2 suite passes unchanged against the reader path. The writer handle
|
|
23
|
+
keeps its pre-query backfill (`ensureQueryEmbeddings`) and its documented
|
|
24
|
+
provider-failure asymmetry.
|
|
25
|
+
|
|
26
|
+
## Evidence chain
|
|
27
|
+
|
|
28
|
+
[Confer round 5](../../confer/2026-09-13-round-5/README.md) pinned the
|
|
29
|
+
read-connection discipline from all six inspirations: Obelisk's
|
|
30
|
+
`readOnly:true` recipe and typed schema refusals (AGPL — patterns only),
|
|
31
|
+
AgentsView's reader-pool/DSN discipline and the stranded-reader-on-swap
|
|
32
|
+
hazard avoided by per-invocation readers, Cass's "a strict read never
|
|
33
|
+
repairs" rule and byte-invariance test (rider — patterns only),
|
|
34
|
+
Trajectory's `openWithWalFallback` writable-retry identified as the
|
|
35
|
+
anti-pattern behind the round-4 stale-`-shm` failure, letta-code's
|
|
36
|
+
manifest refusal with remedy in the message.
|
|
37
|
+
|
|
38
|
+
## Verification (combined adversarial + independent rounds)
|
|
39
|
+
|
|
40
|
+
- Write-freedom confirmed: db and `-wal` byte-identical after every read
|
|
41
|
+
verb across WAL/non-WAL shapes, refusal paths, and a live writer with an
|
|
42
|
+
open transaction; no sidecar or lock file ever created; `user_version`
|
|
43
|
+
never bumped. (`-shm` is shared wal-index bookkeeping SQLite may refresh
|
|
44
|
+
once on first open of a dirty WAL — documented, excluded from the
|
|
45
|
+
data-hash contract.) Engine-level test proves the handle rejects writes
|
|
46
|
+
(SQLITE_READONLY) — mutation-verified (removing the readonly flag fails
|
|
47
|
+
two tests).
|
|
48
|
+
- Behavioral drift: none — 14 lexical query shapes plus the full envelope
|
|
49
|
+
identical to baseline `a19916b`; semantic/hybrid with embeddings
|
|
50
|
+
byte-identical between handles. Intended changes only: read path never
|
|
51
|
+
backfills; provider failure with vectors present now answers lexically
|
|
52
|
+
(documented) instead of throwing on the writer handle too.
|
|
53
|
+
- Concurrency: reads serve the last committed snapshot during a held
|
|
54
|
+
`BEGIN IMMEDIATE`; 120 concurrent read verbs against a write burst with
|
|
55
|
+
periodic checkpoints all succeeded; the live 820 MB store read correctly
|
|
56
|
+
while a real `ledger sync` held the lease.
|
|
57
|
+
- Suite: 454 pass / 1 fail of 455 across 35 files — the failure is the
|
|
58
|
+
pre-existing native-cursor classification (#18, reproduced identically
|
|
59
|
+
on baseline). Typecheck and build clean. Reader suite: 22 tests / 181
|
|
60
|
+
assertions; cycle-2 and cycle-4 suites pass unchanged.
|
|
61
|
+
- Human-mode note branches on reason (FTS wording pinned; other reasons
|
|
62
|
+
print `answered lexically (<reason>)`); empty stores report plain
|
|
63
|
+
zero-hit results; dimension-mismatched provider vectors fall back rather
|
|
64
|
+
than rank zeros.
|
|
65
|
+
|
|
66
|
+
## Boundaries
|
|
67
|
+
|
|
68
|
+
- The "initialized store" gate recognizes a `sessions` table (consistent
|
|
69
|
+
with `store-status`); a foreign file with only that table fails per-verb
|
|
70
|
+
with a raw SQLite error — a shared weakness with status, recorded as
|
|
71
|
+
follow-up (AgentsView's required-schema diff is the known shape).
|
|
72
|
+
- `-shm` refresh on first open of a dirty WAL is SQLite's own wal-index
|
|
73
|
+
bookkeeping, not a Ledger write.
|
|
74
|
+
- Writers unchanged: `TrajectoryDb` + lease + backfill-first semantics.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Verified Mac CLI and service rollout
|
|
2
|
+
|
|
3
|
+
The Mac service now uses `main` at
|
|
4
|
+
`51a071ee5af3b722955260edbc669998eb025d6e` and the existing XDG database.
|
|
5
|
+
[PR31](https://github.com/archeism/ledger/pull/31) preserves robot output
|
|
6
|
+
compatibility and fixes Cursor schema classification, closing issue 18.
|
|
7
|
+
Its merge tree exactly matched the tested `3a610b5` tree.
|
|
8
|
+
The service checkout subsequently received documentation-only commit `0680cb5`.
|
|
9
|
+
Upstream PR30 landed during report publication and was preserved in the report's
|
|
10
|
+
merge, but was not deployed; the test and rollout claims here apply to the pinned
|
|
11
|
+
source revision above, not that newer scan-outcomes change.
|
|
12
|
+
|
|
13
|
+
## Changes and checks
|
|
14
|
+
|
|
15
|
+
- Default robot search remains legacy hits-only JSONL or a JSON array. New agents
|
|
16
|
+
explicitly select `--output-version 2` for metadata and match provenance.
|
|
17
|
+
- Cursor checks required SQLite columns before projection. Invalid schema errors
|
|
18
|
+
no longer depend on runtime-specific error metadata; transient errors retain
|
|
19
|
+
their classification. The original test passed on this Mac, but four
|
|
20
|
+
metadata-stripped regressions failed before the fix and passed afterward.
|
|
21
|
+
- Full core suite: **494 passed, zero failed**, 3,393 assertions, 53.03 seconds.
|
|
22
|
+
Build, package typecheck, helper typecheck, and diff checks passed. The separate
|
|
23
|
+
observer suite passed 12 tests.
|
|
24
|
+
- Independent review found embedded personal fixtures and omitted cursor/staging
|
|
25
|
+
comparison fields in the first helper. Both were corrected before publication;
|
|
26
|
+
the supplemental comparison covered the omitted fields without repeating the
|
|
27
|
+
expensive full archive scan.
|
|
28
|
+
|
|
29
|
+
## Preservation and retrieval
|
|
30
|
+
|
|
31
|
+
An online SQLite backup was rehearsed separately from the live store. The v6-to-v10
|
|
32
|
+
migration took 23.4 seconds on that copy. Full row digests matched for 1,333,616
|
|
33
|
+
records, 12,880 sessions, 14,874 embeddings, and 12,992 cursors. Old cursor identity
|
|
34
|
+
and prefix hashes and staged-session metadata also matched. Before/after SQLite
|
|
35
|
+
quick checks passed, with no foreign-key violations.
|
|
36
|
+
|
|
37
|
+
Eleven frozen checks passed both before and after migration: original ACTI eval
|
|
38
|
+
and Cursor Git-notes retrieval, the broad evaluation-repository keyword, one
|
|
39
|
+
original session from each of seven populated harnesses, and a negative control.
|
|
40
|
+
All positive target sessions ranked first within source-filtered top-50 results.
|
|
41
|
+
Database, WAL, and writer-lock hashes were unchanged by the query batches.
|
|
42
|
+
|
|
43
|
+
After stopping the old watcher, a fresh quiescent backup held 1,334,038 records
|
|
44
|
+
and 12,884 sessions. The live migration preserved those counts exactly. All 11
|
|
45
|
+
live checks then passed with unchanged database/WAL/lock hashes while the service
|
|
46
|
+
was idle. The live negative was generated privately before querying: an earlier
|
|
47
|
+
visible control literal could itself enter the archive through this agent's
|
|
48
|
+
transcript. Positive cases and limits were unchanged, and both fixtures remain
|
|
49
|
+
available in the private evidence bundle.
|
|
50
|
+
|
|
51
|
+
These checks establish preservation and sampled retrieval, not full historical
|
|
52
|
+
coverage or general ranking quality. Widening retains its 10,000-record ceiling;
|
|
53
|
+
this archive is larger, so it does not automatically receive that fallback.
|
|
54
|
+
|
|
55
|
+
## Installed operation
|
|
56
|
+
|
|
57
|
+
`~/.local/bin/ledger` now invokes the stable workspace checkout. The launchd job
|
|
58
|
+
`com.archeism.ledger` retains the existing database, all 14 configured sources,
|
|
59
|
+
and discovery limit of 1,000,000 per source. It runs bounded `sync` every 900
|
|
60
|
+
seconds, with one worker, 25 admitted sessions, 64 MiB source budget, 120-second
|
|
61
|
+
pass budget, and 30-second worker deadlines; the old always-on watcher is stopped.
|
|
62
|
+
|
|
63
|
+
Two real passes exited zero and their process trees terminated:
|
|
64
|
+
|
|
65
|
+
| Pass | Duration | Published | Staged Records After | Worker Timeouts |
|
|
66
|
+
| --- | --- | --- | --- | --- |
|
|
67
|
+
| Initial scheduled pass | 115.1 s | No completed sessions | 1,593 | 3 |
|
|
68
|
+
| Explicit resumability check | 111.6 s | 1 session / 31 records | 2,868 | 3 |
|
|
69
|
+
|
|
70
|
+
Final observed totals were 1,334,069 records and 12,885 sessions. Backfill is
|
|
71
|
+
**not complete**: 14,785 queue entries remained, including six timed-out items
|
|
72
|
+
scheduled for retry. Existing failed source artifacts were not silently cleared.
|
|
73
|
+
The service is expected to be idle between passes, with last exit code zero.
|
|
74
|
+
|
|
75
|
+
## Resource and Evidence Limits
|
|
76
|
+
|
|
77
|
+
The first observer had five database-aggregate timeouts on the large store;
|
|
78
|
+
its incomplete result is retained. A second process-only observation reused
|
|
79
|
+
the repository's PID/start-time tracking, sampled every second without database
|
|
80
|
+
aggregation, and had no collection errors. It attached after startup: its
|
|
81
|
+
330,727,424-byte sampled peak RSS and 29.67 observed CPU-seconds are lower bounds,
|
|
82
|
+
not whole-pass maxima or a capacity guarantee. No descendants remained at exit.
|
|
83
|
+
|
|
84
|
+
No model was called by the measured operations. Early Bun `resourceUsage()`
|
|
85
|
+
objects serialized as `{}`; they are unavailable measurements, not zeros.
|
|
86
|
+
A replay explicitly materialized their non-enumerable getters and CPU bigint
|
|
87
|
+
counters. Physical process I/O bytes remain unavailable on this Mac. The evidence
|
|
88
|
+
validator reports **valid, incomplete**, with only those two I/O dimensions
|
|
89
|
+
unavailable; no percentile or throughput claim follows from these probes.
|
|
90
|
+
|
|
91
|
+
Private artifacts are under the rollout worktree's
|
|
92
|
+
`.local/runtime-upgrade-20260913/`: frozen fixtures, before/after digests,
|
|
93
|
+
supplemental preservation checks, query attempts, full test log, both observations,
|
|
94
|
+
service summaries, and checksummed `run.json`. They are excluded from Git.
|
|
95
|
+
See [the replay protocol](https://github.com/archeism/ledger/blob/43081aef54c23b4bd017b6c0e11fc42a9a1cb381/lab/runtime-rollout/README.md).
|
|
96
|
+
|
|
97
|
+
Paired rollback files are under
|
|
98
|
+
`~/.local/share/ledger/backups/20260913-runtime-upgrade/`, including
|
|
99
|
+
`quiescent-pre-upgrade.sqlite`, `pre-upgrade.plist`, and `rollout-state.json`.
|
|
100
|
+
Stop the new job first, retain the latest database and sidecars, then restore the
|
|
101
|
+
old backup with code `6a33ca80e921040981114bf3a94e9995566a0f15` and its plist.
|
|
102
|
+
Never run an old writer on the migrated database or discard post-upgrade data.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Per-source scan outcomes, 2026-09-13
|
|
2
|
+
|
|
3
|
+
## Outcome
|
|
4
|
+
|
|
5
|
+
`scanSessions` collapsed every listing failure into one `read_error`
|
|
6
|
+
diagnostic delivered to an `onDiagnostic` callback that no caller passed —
|
|
7
|
+
sources failed silently and reported 0 sessions; the extended directory
|
|
8
|
+
branch swallowed filesystem errors with no diagnostic at all; and the
|
|
9
|
+
installed Trajectory 0.3.0 cannot fix this from below: a verified probe
|
|
10
|
+
of the package under Bun shows 8 of 10 file listers return silent
|
|
11
|
+
`items=0` for missing, empty, and unreadable roots alike, and the SQLite
|
|
12
|
+
listers' most common real failures escape as raw `SQLiteError` with no
|
|
13
|
+
code. This cycle computes scan outcomes scanner-side and reports one row
|
|
14
|
+
per source.
|
|
15
|
+
|
|
16
|
+
- `scanSessions` returns `{sessions, outcomes}` (clean cutover; every
|
|
17
|
+
caller migrated). Each `ScanOutcome` row carries `source`, `root`,
|
|
18
|
+
a closed status (`listable`, `missing_root`, `root_not_directory`,
|
|
19
|
+
`unreadable_root`, `listing_failed`), `discovered`, and a capped
|
|
20
|
+
content-free `detail` (error class + code only; the only path in a row
|
|
21
|
+
is the root itself). Rows are sorted by source; a zero row is a signal,
|
|
22
|
+
not absence.
|
|
23
|
+
- Ledger probes each resolved root itself (stat: ENOENT vs non-directory
|
|
24
|
+
vs access error) before listing, mirroring exactly what each lister
|
|
25
|
+
reads — verified against the installed adapters for all 10 library
|
|
26
|
+
sources, both native roots, and the extended locations.
|
|
27
|
+
- Native sources funnel their existing diagnostics into the rows:
|
|
28
|
+
a diagnostic alongside discovered sessions keeps `listable` with the
|
|
29
|
+
message in `detail`; `listing_failed` fires only when the scan threw or
|
|
30
|
+
discovered nothing. Extended sources replaced silent skips with rows.
|
|
31
|
+
- `scan --robot` JSONL emits a leading `{"type":"scan_outcomes",...}`
|
|
32
|
+
line (the `search_meta` precedent); `--json` gains `outcomes`; human
|
|
33
|
+
output is byte-identical to baseline when every source is listable and
|
|
34
|
+
otherwise prints one stderr note per anomalous source — `missing_root`
|
|
35
|
+
rows stay silent (absent defaults are normal; robots get every row).
|
|
36
|
+
|
|
37
|
+
## Evidence chain
|
|
38
|
+
|
|
39
|
+
[Confer round 7](../../confer/2026-09-13-round-7/README.md): the installed-
|
|
40
|
+
package behavior matrix (trajectory), Obelisk's errno split and
|
|
41
|
+
provenance analysis (AGPL — patterns only), AgentsView's typed
|
|
42
|
+
per-source status shape over doctor's three-way text ladder, Cass's
|
|
43
|
+
all-count-keys and sorted/deduped diagnostics discipline with a curated
|
|
44
|
+
typed channel only (rider — patterns only), and letta-code recorded as
|
|
45
|
+
the deliberate counterexample (listing hides unusable sources).
|
|
46
|
+
|
|
47
|
+
## Verification (combined adversarial + independent rounds)
|
|
48
|
+
|
|
49
|
+
- Root resolution: 14/14 default roots mirror the actual listers
|
|
50
|
+
(compared against installed adapter code); a fake HOME with real-shaped
|
|
51
|
+
stores for all fourteen sources yields 14/14 `listable` with discovered
|
|
52
|
+
counts equal to the library's; the real HOME yields 8 `listable`
|
|
53
|
+
(claude-code 113, codex 833, cursor 640, hermes 124, omp 77, opencode
|
|
54
|
+
932, pi 873, droid 68) and 6 `missing_root`, each verified genuinely
|
|
55
|
+
absent — no false verdicts.
|
|
56
|
+
- Invariance: human stdout byte-identical to baseline `cb673ea` across
|
|
57
|
+
three HOME shapes (all-listable, partial, real); robot JSONL delta is
|
|
58
|
+
exactly the leading outcomes line; `--json` strictly additive.
|
|
59
|
+
- Mutations: removing the probe or the sort each fails multiple tests;
|
|
60
|
+
the native partial-evidence edge (diagnostic + sessions → `listable`
|
|
61
|
+
with detail) is pinned.
|
|
62
|
+
- Suite: 486 pass / 1 fail of 487 — the pre-existing native-cursor #18.
|
|
63
|
+
Typecheck/build clean. The audit's findings were fixed before shipping:
|
|
64
|
+
native partial-evidence no longer mislabels working Cursor installs
|
|
65
|
+
(640 sessions reported with a diagnostic), lab controller probes
|
|
66
|
+
destructure the new shape (their deeper fixture rejection is
|
|
67
|
+
pre-existing and out of scope), the root/status doc widened, default-
|
|
68
|
+
scan note noise suppressed, sort made code-unit stable.
|
|
69
|
+
|
|
70
|
+
## Boundaries
|
|
71
|
+
|
|
72
|
+
- Outcomes are recomputed per scan and never persisted; durable per-source
|
|
73
|
+
coverage state (a natural fit for `ingest_queue.last_outcome`) is a
|
|
74
|
+
later cycle.
|
|
75
|
+
- `status` describes the source's scan; `root` names the primary
|
|
76
|
+
location — a multi-location source can be `listable` while `detail`
|
|
77
|
+
records a failure elsewhere (documented).
|
|
78
|
+
- Two historical lab controllers were migrated to the new shape but
|
|
79
|
+
remain non-runnable on their original fixtures for a pre-existing
|
|
80
|
+
OpenCode validator reason (identical before this change; recorded).
|