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,231 @@
|
|
|
1
|
+
# Integrated daemon observation
|
|
2
|
+
|
|
3
|
+
Status: operational retest passed at source revision `6bd64b7`; the supervised
|
|
4
|
+
daemon remains running. Failed attempts are retained. Corpus coverage and raw
|
|
5
|
+
archival retention are not complete.
|
|
6
|
+
|
|
7
|
+
## Question and acceptance
|
|
8
|
+
|
|
9
|
+
Can the integrated Ledger watcher preserve the existing index, make new native
|
|
10
|
+
records searchable under launchd, and continue bounded backfill without loading
|
|
11
|
+
an entire large JSONL transcript?
|
|
12
|
+
|
|
13
|
+
Acceptance requires a schema-6 migration with no missing existing record hashes,
|
|
14
|
+
the recovered Claude prompt slice still searchable, a supervised foreground
|
|
15
|
+
process, automatic import and append of a labeled synthetic canary, and continued
|
|
16
|
+
cursor progress. A successful process start or populated database alone is not
|
|
17
|
+
acceptance. This trial does not establish complete corpus coverage, raw archival
|
|
18
|
+
retention, exactly-once effects, or steady-state fleet capacity.
|
|
19
|
+
|
|
20
|
+
## Frozen protocol
|
|
21
|
+
|
|
22
|
+
- Target: this Mac's stable Ledger checkout at merged revision
|
|
23
|
+
`56b51e2b76d8d37f749bb114f5b73f1e40164cf9`, Bun 1.4.0,
|
|
24
|
+
installed Trajectory 0.3.0. Both PRs are merged before launch.
|
|
25
|
+
- Host: Apple Silicon macOS, 10 CPU cores, 24 GiB physical memory. Other desktop
|
|
26
|
+
work continues; this is an operational observation, not an isolated benchmark.
|
|
27
|
+
- Database: create a SQLite backup of the existing checkout index, preserving the
|
|
28
|
+
original. Migrate only the candidate, verify identity-adjusted record hashes,
|
|
29
|
+
then install the candidate at the service's dedicated data path.
|
|
30
|
+
- Workload: native-source discovery and bounded catch-up, plus a clearly labeled
|
|
31
|
+
synthetic Pi JSONL canary with three sequential append observations. No private
|
|
32
|
+
transcript bodies, titles, credentials, or environment dumps in reports.
|
|
33
|
+
- Service settings: lexical ingestion, 60-second reconciliation, 25 candidate
|
|
34
|
+
sessions per source per tick, explicit discovery limit 1,000,000 per source,
|
|
35
|
+
1 MiB target normalization chunks, adaptive individual records up to 64 MiB.
|
|
36
|
+
The record-input ceiling is not a peak-RSS guarantee.
|
|
37
|
+
- Observe the explicit process tree and read-only aggregate DB state at one-second
|
|
38
|
+
cadence for at least 180 seconds. Record baseline, sampled peak, and end RSS,
|
|
39
|
+
cumulative CPU and sampled CPU demand, wall time, query responsiveness, cursor
|
|
40
|
+
progress, failures, and supervision state. Keep unavailable I/O measurements
|
|
41
|
+
explicit rather than reporting zero. The service remains running afterward.
|
|
42
|
+
- Repetition: one operational service run, three canary appends. Do not infer
|
|
43
|
+
stable percentiles or capacity from this sample.
|
|
44
|
+
- Model/token accounting: no model or embedding generation in the daemon trial;
|
|
45
|
+
model tokens and cache counters are not applicable. Agent engineering work is
|
|
46
|
+
outside the sampled daemon process tree.
|
|
47
|
+
- Preserve private raw observation artifacts and hashes locally; publish only a
|
|
48
|
+
compact verdict and sanitized evidence. Validate the trial record with the
|
|
49
|
+
personal evaluation-engineering checker and disclose missing measurements.
|
|
50
|
+
|
|
51
|
+
## Exploratory metadata
|
|
52
|
+
|
|
53
|
+
Before installation, the original schema-v3 index contains 190 sessions and
|
|
54
|
+
68,301 canonical records: 2 Claude sessions and 188 Cursor sessions. One Claude
|
|
55
|
+
session is the separately recovered prompt-history slice. These counts do not
|
|
56
|
+
establish complete coverage.
|
|
57
|
+
|
|
58
|
+
A paginated metadata-only discovery returned 14,493 candidate sessions:
|
|
59
|
+
6,227 Claude, 3,406 Codex, 187 Pi, 1 Letta Code, 137 Droid, 2,705 Cursor,
|
|
60
|
+
and 1,830 OpenCode. Files can change while discovery runs; these are candidate
|
|
61
|
+
listings, not successfully normalized sessions or an immutable corpus manifest.
|
|
62
|
+
An earlier over-limit probe was invalid because upstream page size is capped at
|
|
63
|
+
1,000; the scanner now paginates instead of reporting those sources as empty.
|
|
64
|
+
|
|
65
|
+
Byte framing of six large files, without decoding transcript values, found a
|
|
66
|
+
roughly 750 MB Claude file and Codex files up to 419 MB. The largest observed
|
|
67
|
+
individual JSONL row was 4,184,489 bytes. This motivated separating the 1 MiB
|
|
68
|
+
batch target from the individual-record ceiling.
|
|
69
|
+
|
|
70
|
+
## Results
|
|
71
|
+
|
|
72
|
+
### Pre-observation startup attempt
|
|
73
|
+
|
|
74
|
+
The schema-6 candidate retained all 190 sessions and all 68,301 original record
|
|
75
|
+
hashes after source-prefix adjustment. The recovered prompt slice retains 78
|
|
76
|
+
records and the scoped `benchflow` query returns its historical hit. Integrity
|
|
77
|
+
and foreign-key checks pass. The original schema-3 database remains unchanged.
|
|
78
|
+
|
|
79
|
+
The first launchd attempt used the checkout below `~/Documents/Codex/`. It
|
|
80
|
+
stalled before opening SQLite: a one-second process sample remained in
|
|
81
|
+
`getcwd -> open`, and the matching macOS TCC event requested
|
|
82
|
+
`kTCCServiceSystemPolicyDocumentsFolder` for Bun. This is a failed startup, not
|
|
83
|
+
an ingestion run. The service was unloaded; no OS security policy was changed.
|
|
84
|
+
|
|
85
|
+
For the observation, the same merged revision was cloned to
|
|
86
|
+
`~/workspace/personal/ledger`, dependencies installed from the frozen lockfile,
|
|
87
|
+
and the service reinstalled from that stable checkout. The dedicated database
|
|
88
|
+
and rollback copy are outside Documents. This path correction is fixed before
|
|
89
|
+
the ingestion observation begins. Service logs were set to mode 0600; their
|
|
90
|
+
parent directory is 0700. The installer's shell umask alone does not govern
|
|
91
|
+
files created by launchd.
|
|
92
|
+
|
|
93
|
+
### Ingestion observation
|
|
94
|
+
|
|
95
|
+
The first full observation completed its 180.120-second collection window with
|
|
96
|
+
175 samples, zero collection errors, and zero query timeouts. **Ingestion
|
|
97
|
+
acceptance failed:** sessions remained 190, records 68,301, and persisted cursors
|
|
98
|
+
zero. The synthetic import returned zero hits after 90.199 seconds (90 polls,
|
|
99
|
+
zero query errors); subsequent appends were not attempted.
|
|
100
|
+
|
|
101
|
+
Attach-time RSS was 69,058,560 bytes, sampled peak 82,165,760 bytes, and end RSS
|
|
102
|
+
74,088,448 bytes. The observed process tree consumed at least 132.15 CPU-seconds;
|
|
103
|
+
peak sampled demand was 1.0015 cores. This is wasted startup work, not measured
|
|
104
|
+
ingestion throughput. Per-process I/O and post-teardown memory were not measured.
|
|
105
|
+
|
|
106
|
+
The watcher recursively subscribes to each directory and also manually walks
|
|
107
|
+
its descendants, including broad agent homes containing plugins and worktrees.
|
|
108
|
+
All of this precedes the first reconcile. A process sample during the failed
|
|
109
|
+
window shows deep repeated filesystem recursion. The process was unloaded and
|
|
110
|
+
its exit verified after collection. The original DB and failed-run artifacts
|
|
111
|
+
remain intact.
|
|
112
|
+
|
|
113
|
+
### Revised-run protocol
|
|
114
|
+
|
|
115
|
+
Retain the same migration, search, import, three-append, and cursor-progress
|
|
116
|
+
acceptance criteria. Before another run, narrow automatic subscriptions to
|
|
117
|
+
actual transcript stores, retain shallow parent watches for store creation,
|
|
118
|
+
and use manual per-directory watches only as a platform fallback. Keep all
|
|
119
|
+
sources and periodic reconciliation. Test those properties before deployment;
|
|
120
|
+
record the committed revised source SHA before launch. Repeat the 180-second
|
|
121
|
+
collection on the same dedicated DB and a new labeled canary. Preserve the
|
|
122
|
+
failed attempt rather than replacing it with the retest. This is a single
|
|
123
|
+
operational retest, not a controlled throughput or capacity comparison.
|
|
124
|
+
|
|
125
|
+
The retest's watcher change is committed at `750f7b8`, with installer changes at
|
|
126
|
+
`952f9078b3fe188d9e916915d9e772ae50fe0709`. Before deployment, the combined core
|
|
127
|
+
suite passed 182 tests and 1,087 assertions across 19 files; the observer suite
|
|
128
|
+
passed 10 tests and 79 assertions. Typecheck and whitespace checks passed.
|
|
129
|
+
|
|
130
|
+
Independent review then found quadratic ancestor lookup in the unsupported
|
|
131
|
+
recursive-watch fallback. A 512-directory fixture measured 131,842 candidate
|
|
132
|
+
visits; the recursive-only registry reduces that counter to zero. The final
|
|
133
|
+
deployment is `6bd64b717e646b0d62d31eb833f3dff0736e4456`, with 183 passing core
|
|
134
|
+
tests, 1,097 assertions across 19 files, and passing typecheck. The same 10-test
|
|
135
|
+
observer gate remains green. This final revision was captured before launch,
|
|
136
|
+
along with source-tree, runtime binary, watcher, lockfile, and protocol hashes.
|
|
137
|
+
|
|
138
|
+
### Retest results
|
|
139
|
+
|
|
140
|
+
The 180.186-second run completed with 175 process samples and 33 read-only DB
|
|
141
|
+
samples, zero collection errors, and zero query timeouts. The installed service
|
|
142
|
+
started once and remained the same supervised process throughout.
|
|
143
|
+
|
|
144
|
+
| Measurement | Observed result |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| Indexed sessions | 267 -> 752; increase 485 |
|
|
147
|
+
| Canonical records / FTS rows | 71,745 -> 123,896; increase 52,151, equal at each endpoint |
|
|
148
|
+
| Cursor bytes ingested | 32,656,746 -> 404,526,886; progress 371,870,140 bytes |
|
|
149
|
+
| Synthetic initial import | Searchable after 10.024 seconds |
|
|
150
|
+
| Three sequential appends | Searchable after 12.032, 9.021, and 3.007 seconds |
|
|
151
|
+
| Attach / sampled peak / end RSS | 249,462,784 / 347,127,808 / 289,652,736 bytes |
|
|
152
|
+
| Observed CPU-seconds / peak sampled cores | 130.26 / 1.0173 |
|
|
153
|
+
| Aggregate DB subprocess elapsed range | 89.141-566.350 ms; includes process startup |
|
|
154
|
+
| Failed cursors at window end | 61; not hidden as successful coverage |
|
|
155
|
+
|
|
156
|
+
Canary visibility is polled at one-second intervals under ongoing native
|
|
157
|
+
backfill; these are observed end-to-end latencies, not latency percentiles.
|
|
158
|
+
Cursor byte totals are logical progress, not disk-I/O counters. The two native
|
|
159
|
+
canary files are explicitly synthetic and remain labeled in the Pi store.
|
|
160
|
+
The sampled RSS peak is about 331 MiB, not a hard memory bound.
|
|
161
|
+
|
|
162
|
+
A later coherent read transaction found 1,523 sessions, 190,501 records and the
|
|
163
|
+
same number of FTS rows, zero foreign-key violations, and two staged replacement
|
|
164
|
+
sessions. All 78 recovered Claude prompts remained present; the scoped
|
|
165
|
+
`benchflow` historical query still returned its hit (5.656 ms for that probe).
|
|
166
|
+
This post-window snapshot demonstrates continued progress, not an extension of
|
|
167
|
+
the frozen measurement window or complete archival preservation.
|
|
168
|
+
|
|
169
|
+
The actual CLI was also checked after the window using `query benchflow` with
|
|
170
|
+
`--source claude-code --limit 20 --robot --json` and the dedicated DB. Its
|
|
171
|
+
structured response contained nine hits, including the recovered history slice,
|
|
172
|
+
with exit zero and no stderr. The fully checked end-to-end invocation took
|
|
173
|
+
4.645 seconds under continuing backfill; do not confuse that with the isolated
|
|
174
|
+
SQL-query duration above or infer stable latency from this probe.
|
|
175
|
+
|
|
176
|
+
The service uses the committed PR7 implementation from
|
|
177
|
+
`~/workspace/personal/ledger` and `~/.local/share/ledger/ledger.sqlite`. It remains
|
|
178
|
+
installed under user launchd label `com.archeism.ledger`. PR2 and PR6 are already
|
|
179
|
+
merged; this operational follow-up is kept as its own PR.
|
|
180
|
+
|
|
181
|
+
### Residual failures
|
|
182
|
+
|
|
183
|
+
Observed failed receipts included 33 small Cursor `/projects/` JSONL files
|
|
184
|
+
totaling 5,490 bytes, additional Cursor JSONL files, and 25 OpenCode JSON files
|
|
185
|
+
totaling 958,856 bytes. No failed-file payloads were opened for this triage.
|
|
186
|
+
Their metadata cannot establish whether they are malformed, metadata-only,
|
|
187
|
+
configuration, or unsupported transcript exports. Zero checkpoint bytes does
|
|
188
|
+
not mean zero file reads. The successful run observed ingestion from Claude,
|
|
189
|
+
Codex, Cursor, Pi, Droid, and Letta Code; it does not establish all-source recall.
|
|
190
|
+
|
|
191
|
+
Source inspection confirms two remaining issues. Custom discovery primarily
|
|
192
|
+
filters by extension, while OpenCode normalization expects a whole
|
|
193
|
+
`{info, messages}` export. Also, non-JSONL failures currently omit the cache
|
|
194
|
+
receipt fields needed to skip an unchanged failure. A newest-first budget can
|
|
195
|
+
therefore keep retrying the same 25 files before older valid exports. This is a
|
|
196
|
+
confirmed scheduling mechanism, not proof that valid older OpenCode exports
|
|
197
|
+
exist in this corpus. Cursor JSONL failures already have fingerprint-bound
|
|
198
|
+
negative caching.
|
|
199
|
+
|
|
200
|
+
Follow-up work: tighten export eligibility, retain controlled failure reasons,
|
|
201
|
+
distinguish deterministic failures from transient retries, and separate fresh
|
|
202
|
+
work from retry scheduling. A regression should place 25 newer invalid JSON
|
|
203
|
+
fixtures ahead of one older valid export, then change a failed fixture into a
|
|
204
|
+
valid export and require recovery. These changes are not claimed as implemented
|
|
205
|
+
by this PR. See `scanner.ts:194`, `ingest.ts:122`, and `watch.ts:443` at the final
|
|
206
|
+
deployment revision.
|
|
207
|
+
|
|
208
|
+
## Remaining optimization
|
|
209
|
+
|
|
210
|
+
The [bounded pagination probe](2026-09-09-discovery-pagination.md) confirms that
|
|
211
|
+
Trajectory 0.3.0 inventories a source again for every page. Two pages over 1,002
|
|
212
|
+
synthetic files caused 2,004 stat operations and four directory reads. This is
|
|
213
|
+
not evidence that pagination caused the measured startup stall. There is no
|
|
214
|
+
public single-inventory API in the installed package. Keep full discovery
|
|
215
|
+
coverage and the published normalizer; request an upstream inventory boundary
|
|
216
|
+
before replacing this with private imports or copied discovery code.
|
|
217
|
+
|
|
218
|
+
Both failed-attempt evaluation records validate structurally and remain
|
|
219
|
+
`complete: false`: per-process I/O and post-teardown memory were not collected,
|
|
220
|
+
and the TCC startup attempt lacks a full resource trace. Original artifacts and
|
|
221
|
+
checksums are private under `.local/integrate-7wV4FS/evaluation/` in the retained
|
|
222
|
+
development checkout. No private transcript contents are published here.
|
|
223
|
+
|
|
224
|
+
The third record, `evaluation/attempt-03-operational-retest/run.json`, also
|
|
225
|
+
validates with no errors and `complete: false` for the same unmeasured I/O and
|
|
226
|
+
teardown fields. Its operational rubric passes. Six negative controls reject
|
|
227
|
+
changed hashes, fabricated zero teardown memory, absent record progress, a
|
|
228
|
+
missing append, missing historical evidence, and a service restart. The frozen
|
|
229
|
+
protocol is recovered from Git revision `6bd64b7` and matches its prelaunch
|
|
230
|
+
hash; this document's subsequently appended results are not substituted for
|
|
231
|
+
the trial input. All prior archive files remain unchanged.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Discovery pagination: bounded enumeration evidence
|
|
2
|
+
|
|
3
|
+
2026-09-09. **Measured future optimization, not an implemented change.** Retain
|
|
4
|
+
published Trajectory normalization and complete discovery; do not replace its
|
|
5
|
+
discovery layer or depend on private imports to optimize pagination.
|
|
6
|
+
|
|
7
|
+
## Pin and public boundary
|
|
8
|
+
|
|
9
|
+
- Installed and [lockfile-resolved](https://github.com/archeism/ledger/blob/43081aef54c23b4bd017b6c0e11fc42a9a1cb381/packages/core/bun.lock) package:
|
|
10
|
+
`@letta-ai/trajectory@0.3.0`. Inspected upstream pin:
|
|
11
|
+
[`21ae92d10579499b183d93929c85da0b91233167`](https://github.com/letta-ai/trajectory/tree/21ae92d10579499b183d93929c85da0b91233167).
|
|
12
|
+
- The only public discovery function is `listTrajectories`. There is no
|
|
13
|
+
`listSourceSessions`, inventory snapshot API, or public adapter lister.
|
|
14
|
+
[Entrypoint](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/src/index.ts#L181-L186).
|
|
15
|
+
- Package subpaths expose only `.`, `./schema`, `./schema/canonical`, and
|
|
16
|
+
`./package.json`. Resolving `dist/listing.js` or `dist/adapters/omp/list.js`
|
|
17
|
+
through the package name returned `ERR_PACKAGE_PATH_NOT_EXPORTED` in Node.
|
|
18
|
+
An internal function's `export` declaration is not a public package contract.
|
|
19
|
+
[Export map](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/package.json#L17-L25).
|
|
20
|
+
- Every page calls the source lister again before pagination; page size is capped
|
|
21
|
+
at 1,000. The cursor retains identity/position, not an inventory snapshot.
|
|
22
|
+
[Dispatch and pagination](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/src/listing.ts#L74-L153).
|
|
23
|
+
|
|
24
|
+
## Observation and limits
|
|
25
|
+
|
|
26
|
+
Node `v24.18.1`, macOS arm64; 1,002 synthetic empty JSONL files in one temporary
|
|
27
|
+
project, separately listed as Pi and OMP. Pass-through instrumentation counts
|
|
28
|
+
filesystem API calls under the fixture root, not kernel syscalls or physical I/O.
|
|
29
|
+
|
|
30
|
+
| Source (each independently) | Cumulative items | `statSync` | `readdirSync` | `readFileSync` |
|
|
31
|
+
| --- | ---: | ---: | ---: | ---: |
|
|
32
|
+
| Pi / OMP, page 1 | 1,000 | 1,002 | 2 | 0 |
|
|
33
|
+
| Pi / OMP, pages 1 + 2 | 1,002 | 2,004 | 4 | 0 |
|
|
34
|
+
|
|
35
|
+
Thus two pages repeat inventory metadata work. There were no fixture-content
|
|
36
|
+
reads: these listers discover metadata without normalizing the empty files.
|
|
37
|
+
Bun `1.4.0` did not expose named filesystem imports to this instrumentation;
|
|
38
|
+
its zero counters were rejected, not treated as zero I/O. Counts above are from
|
|
39
|
+
Node, not a Bun timing comparison.
|
|
40
|
+
|
|
41
|
+
Ledger's audited `5d629ec3058485327a84c963f8c73997e46acbc1` scanner accumulated
|
|
42
|
+
all pages before the watcher applied its import budget. This is a source-backed
|
|
43
|
+
delay mechanism, **not a measured cause of the reported 90/130-second daemon
|
|
44
|
+
observations, nor a throughput, memory, latency, or capacity result**. No native
|
|
45
|
+
corpus, real database, model, embedding, or daemon was exercised by this probe.
|
|
46
|
+
|
|
47
|
+
## Deferred public API proposal
|
|
48
|
+
|
|
49
|
+
An upstream public full-inventory function, for example
|
|
50
|
+
`listSourceSessions({ source, root }) -> Promise<TrajectoryListing[]>`, could
|
|
51
|
+
reuse the existing listers once. This is a proposed name/contract, not an API
|
|
52
|
+
available in `0.3.0`. Ledger could then enumerate children for **all OMP parents**
|
|
53
|
+
before sorting and applying its final combined budget. No parser is copied and
|
|
54
|
+
published canonical normalization remains unchanged. Until such a supported API
|
|
55
|
+
exists, retain current complete pagination rather than lower coverage limits,
|
|
56
|
+
deep-import internals, or add a large duplicate discovery implementation.
|
|
57
|
+
No upstream issue or change has been submitted or authorized by this note.
|
|
58
|
+
|
|
59
|
+
## Reproduce
|
|
60
|
+
|
|
61
|
+
From the repository root with dependencies already installed and Node 24.18.1:
|
|
62
|
+
the command imports only public package entrypoints, creates 1,002 temporary empty
|
|
63
|
+
files, asserts counts/coverage, and removes the fixture in `finally`.
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
cd packages/core
|
|
67
|
+
node --input-type=module <<'JS'
|
|
68
|
+
import fs from "node:fs";
|
|
69
|
+
import { createRequire, syncBuiltinESMExports } from "node:module";
|
|
70
|
+
import { tmpdir } from "node:os";
|
|
71
|
+
import { join } from "node:path";
|
|
72
|
+
import assert from "node:assert/strict";
|
|
73
|
+
const require = createRequire(import.meta.url);
|
|
74
|
+
assert.equal(require("@letta-ai/trajectory/package.json").version, "0.3.0");
|
|
75
|
+
const root = fs.mkdtempSync(join(tmpdir(), "ledger-listing-count-"));
|
|
76
|
+
const project = join(root, "sessions", "project");
|
|
77
|
+
const original = { statSync: fs.statSync, readdirSync: fs.readdirSync,
|
|
78
|
+
readFileSync: fs.readFileSync };
|
|
79
|
+
let counts = [0, 0, 0]; // stat, directory enumeration, content read
|
|
80
|
+
try {
|
|
81
|
+
fs.mkdirSync(project, { recursive: true });
|
|
82
|
+
for (let i = 0; i < 1002; i++)
|
|
83
|
+
fs.writeFileSync(join(project, `session-${String(i).padStart(4, "0")}.jsonl`), "");
|
|
84
|
+
Object.keys(original).forEach((method, index) => {
|
|
85
|
+
fs[method] = function (...args) {
|
|
86
|
+
if (String(args[0]).startsWith(root + "/")) counts[index]++;
|
|
87
|
+
return Reflect.apply(original[method], fs, args);
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
syncBuiltinESMExports();
|
|
91
|
+
const api = await import("@letta-ai/trajectory");
|
|
92
|
+
assert.deepEqual(Object.keys(api).filter(k => /^list/.test(k)), ["listTrajectories"]);
|
|
93
|
+
for (const source of ["pi", "omp"]) {
|
|
94
|
+
counts = [0, 0, 0];
|
|
95
|
+
const first = await api.listTrajectories({ source, root, limit: 1000 });
|
|
96
|
+
assert.equal(first.items.length, 1000);
|
|
97
|
+
assert.ok(first.nextCursor);
|
|
98
|
+
assert.deepEqual(counts, [1002, 2, 0]);
|
|
99
|
+
console.log(JSON.stringify({ source, pages: 1, items: 1000, counts }));
|
|
100
|
+
const second = await api.listTrajectories({ source, root, limit: 1000,
|
|
101
|
+
cursor: first.nextCursor });
|
|
102
|
+
assert.equal(second.items.length, 2);
|
|
103
|
+
assert.equal(second.nextCursor, undefined);
|
|
104
|
+
assert.equal(new Set([...first.items, ...second.items].map(x => x.path)).size, 1002);
|
|
105
|
+
assert.deepEqual(counts, [2004, 4, 0]);
|
|
106
|
+
console.log(JSON.stringify({ source, pages: 2, items: 1002, counts }));
|
|
107
|
+
}
|
|
108
|
+
} finally {
|
|
109
|
+
Object.assign(fs, original);
|
|
110
|
+
syncBuiltinESMExports();
|
|
111
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
112
|
+
}
|
|
113
|
+
JS
|
|
114
|
+
```
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Trajectory discovery and AI SDK Harnesses transcript contracts
|
|
2
|
+
|
|
3
|
+
## Answer
|
|
4
|
+
|
|
5
|
+
**Trajectory parses Cursor and OpenCode exports but does not discover their local
|
|
6
|
+
stores.** This was verified against installed and latest published `0.3.0`, current
|
|
7
|
+
upstream source, and direct public-API probes below. Ledger's broad custom file
|
|
8
|
+
scanner is not functionality inherited from Trajectory.
|
|
9
|
+
|
|
10
|
+
**Vercel unifies live turn input/output and session lifecycle, not historical
|
|
11
|
+
transcript ingestion or a canonical archive.** Applications can use common AI SDK
|
|
12
|
+
messages and streams across harnesses, but each native runtime still owns its
|
|
13
|
+
conversation history. Passing old messages to `HarnessAgent` does not import that
|
|
14
|
+
history: it selects the latest user message, with separate handling for pending
|
|
15
|
+
tool continuations. [History contract](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/content/docs/03-ai-sdk-harnesses/02-harness-agent.mdx#L188-L201),
|
|
16
|
+
[implementation](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/agent/harness-agent.ts#L833-L885).
|
|
17
|
+
|
|
18
|
+
## Pins and scope
|
|
19
|
+
|
|
20
|
+
- Refreshed GitHub `main` on 2026-09-09 at 01:41 UTC:
|
|
21
|
+
[`45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563`](https://github.com/vercel/ai/commit/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563).
|
|
22
|
+
This supersedes the earlier `46cea633cf7286386eb4e70f9c04413c57723d35` research pin.
|
|
23
|
+
- Public npm metadata reported `@ai-sdk/harness` **1.0.104**, Claude Code
|
|
24
|
+
**1.0.108**, and Codex **1.0.106**. Their release tags all resolved to
|
|
25
|
+
[`db450a22f14c21fe734f0592bcde191a4515bc1c`](https://github.com/vercel/ai/commit/db450a22f14c21fe734f0592bcde191a4515bc1c).
|
|
26
|
+
The collected release-to-HEAD comparison showed no changes under those three
|
|
27
|
+
package directories. Thus the examined package contracts also exist in
|
|
28
|
+
release-tag source, not only unreleased main. Built tarballs were not audited.
|
|
29
|
+
[Harness metadata](https://registry.npmjs.org/@ai-sdk/harness/1.0.104),
|
|
30
|
+
[Claude metadata](https://registry.npmjs.org/@ai-sdk/harness-claude-code/1.0.108),
|
|
31
|
+
[Codex metadata](https://registry.npmjs.org/@ai-sdk/harness-codex/1.0.106).
|
|
32
|
+
- Official source docs still label harness packages **experimental**, despite
|
|
33
|
+
published 1.0 versions. [Status](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/content/docs/03-ai-sdk-harnesses/01-overview.mdx#L25-L36).
|
|
34
|
+
- Bounded inspection: public GitHub tree, exported core/session interfaces,
|
|
35
|
+
eleven adapter entrypoints, official source docs, and decisive Claude/Codex
|
|
36
|
+
implementation and test paths. Tests were read, not run. No local upstream
|
|
37
|
+
clone, installation, model execution, daemon, database, or personal transcript
|
|
38
|
+
access. Findings below describe these inspected surfaces, not every native
|
|
39
|
+
SDK capability or deployed documentation version.
|
|
40
|
+
|
|
41
|
+
## Trajectory: parsing is separate from discovery
|
|
42
|
+
|
|
43
|
+
On 2026-09-09, the installed package and npm's `latest` metadata both reported
|
|
44
|
+
`@letta-ai/trajectory` **0.3.0**. The registry's `gitHead` and a live GitHub `main`
|
|
45
|
+
lookup agreed on
|
|
46
|
+
[`21ae92d10579499b183d93929c85da0b91233167`](https://github.com/letta-ai/trajectory/commit/21ae92d10579499b183d93929c85da0b91233167).
|
|
47
|
+
[Published metadata](https://registry.npmjs.org/@letta-ai/trajectory/0.3.0).
|
|
48
|
+
|
|
49
|
+
| Source | Supported normalization input | Local-store listing |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| Cursor | Captured role/message content-block JSONL, documented from SWE-chat; callers supply the group identity for canonical normalization. | Intentionally unavailable: this capture is not a documented Cursor local-store format. [Adapter contract](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/src/adapters/cursor/README.md#L1-L25). |
|
|
52
|
+
| OpenCode | An assembled whole-session JSON document with `info` and `messages`, whose entries contain message metadata and parts. | Intentionally unavailable: the caller provides the assembled export. [Adapter contract](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/src/adapters/opencode/README.md#L1-L34). |
|
|
53
|
+
|
|
54
|
+
The public lister distinguishes known normalization-only sources from unknown
|
|
55
|
+
sources, returning `listing_unavailable` for both Cursor and OpenCode.
|
|
56
|
+
[Dispatch and classification](https://github.com/letta-ai/trajectory/blob/21ae92d10579499b183d93929c85da0b91233167/src/listing.ts#L56-L110).
|
|
57
|
+
|
|
58
|
+
Bounded local verification used the installed package, no private inputs, and no
|
|
59
|
+
database or model calls:
|
|
60
|
+
|
|
61
|
+
| Probe | Cursor | OpenCode |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| `listTrajectories({ source, limit: 1 })` | `NormalizationError`: `listing_unavailable` | `NormalizationError`: `listing_unavailable` |
|
|
64
|
+
| `normalizeTranscript` on a synthetic user/assistant exchange in the documented format | Three records: meta, user, assistant; one `timestamps_synthesized` diagnostic | Three records: meta, user, assistant; zero diagnostics |
|
|
65
|
+
|
|
66
|
+
Ledger therefore does need a caller-side discovery/export step for these sources.
|
|
67
|
+
The current custom scanner selects by directory, depth and filename extension,
|
|
68
|
+
not by a complete export-eligibility check. Its false candidates are a Ledger
|
|
69
|
+
discovery issue; swapping the call to `listTrajectories()` would instead make
|
|
70
|
+
both sources unavailable. [Ledger scanner](https://github.com/archeism/ledger/blob/43081aef54c23b4bd017b6c0e11fc42a9a1cb381/packages/core/src/scanner.ts).
|
|
71
|
+
No ingestion behavior or dependency was changed by this research.
|
|
72
|
+
|
|
73
|
+
## What Vercel makes common
|
|
74
|
+
|
|
75
|
+
| Surface | Actual contract |
|
|
76
|
+
| --- | --- |
|
|
77
|
+
| Application history | `UIMessage` has `id`, role, optional metadata, and typed `parts`. This is an application/UI representation, not an assertion that all native execution evidence is included. [Shape](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/content/docs/07-reference/01-ai-sdk-core/31-ui-message.mdx#L50-L75). |
|
|
78
|
+
| Turn input | AI SDK accepts `ModelMessage[]`, but the adapter receives only `string \| UserModelMessage` for a fresh turn. Prior history stays native. A regression explicitly verifies older user/assistant turns are discarded. [Adapter input](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/v1/harness-v1-prompt.ts#L1-L11), [test](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/agent/harness-agent.test.ts#L3139-L3166). |
|
|
79
|
+
| Adapter events | `HarnessV1StreamPart` standardizes text/reasoning, tool input/call/approval/result, step/turn finish, usage, errors, file changes, compaction, and a raw escape hatch. It reuses LanguageModelV4 primitives; it is not itself `UIMessage`. [Union](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/v1/harness-v1-stream-part.ts#L15-L137), [type-compatibility tests](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/v1/harness-v1-stream-part.test-d.ts#L25-L95). |
|
|
80
|
+
| Consumer output | Adapter events become AI SDK `TextStreamPart`s; `harnessMetadata` becomes `providerMetadata`. The documented UI route uses `convertToModelMessages`, `agent.stream`, then `toUIMessageStream({ stream: result.stream })`. [Translation](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/agent/internal/translate-stream-part.ts#L5-L27), [UI route](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/content/docs/03-ai-sdk-harnesses/07-ui.mdx#L153-L190). |
|
|
81
|
+
| Result messages | `responseMessages` is constructed from the current result's accumulated content as assistant/tool model messages. It is not a session-history getter. [Construction](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/agent/internal/harness-stream-text-result.ts#L397-L405), [conversion](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/agent/internal/harness-stream-text-result.ts#L472-L482). |
|
|
82
|
+
|
|
83
|
+
## Session continuity is not transcript access
|
|
84
|
+
|
|
85
|
+
`createSession({ sessionId, resumeFrom })` restores a known session;
|
|
86
|
+
`continueFrom` restores an unfinished turn. `detach()` and `stop()` return opaque
|
|
87
|
+
resume state; `destroy()` ends without resumability. The envelope identifies
|
|
88
|
+
`harnessId`, specification version, adapter-defined JSON `data`, and optional
|
|
89
|
+
continuation/tool state. That is a common lifecycle envelope, not a portable
|
|
90
|
+
cross-provider conversation. [Creation API](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/agent/harness-agent.ts#L284-L340),
|
|
91
|
+
[state types](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/v1/harness-v1-lifecycle-state.ts#L59-L119).
|
|
92
|
+
|
|
93
|
+
The complete common `HarnessV1Session` interface exposes prompt/continue,
|
|
94
|
+
compaction, suspend, detach, stop, and destroy. **It has no session listing,
|
|
95
|
+
history retrieval, transcript export, or historical import method.** The inspected
|
|
96
|
+
public adapter entrypoints likewise expose adapter factories/settings/types,
|
|
97
|
+
not a cross-harness history service. This is a scoped API finding, not a claim
|
|
98
|
+
that Claude's or Codex's own SDKs cannot inspect their native histories.
|
|
99
|
+
[Session interface](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/v1/harness-v1-session.ts#L152-L258),
|
|
100
|
+
[Claude exports](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness-claude-code/src/index.ts#L1-L15),
|
|
101
|
+
[Codex exports](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness-codex/src/index.ts#L1-L14).
|
|
102
|
+
|
|
103
|
+
Claude resumes the exact observed native conversation ID through the SDK's
|
|
104
|
+
`resume` option, falling back to cwd-based continuation only without an exact
|
|
105
|
+
ID. Codex retains a native `threadId` and calls `codex.resumeThread`.
|
|
106
|
+
Neither path enumerates old host-local transcripts and converts them into a
|
|
107
|
+
common historical dataset. [Claude resume](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness-claude-code/src/bridge/index.ts#L511-L528),
|
|
108
|
+
[Codex state](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness-codex/src/codex-harness.ts#L175-L188),
|
|
109
|
+
[Codex resume](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness-codex/src/bridge/index.ts#L205-L218).
|
|
110
|
+
|
|
111
|
+
Storage remains application-owned: the official session-store example keeps
|
|
112
|
+
opaque resume state in a map and explicitly requires durable storage in
|
|
113
|
+
production. It is not a retained-source archive or historical discovery/import
|
|
114
|
+
service. This is a stronger distinction than merely observing that bridge event
|
|
115
|
+
replay is not archival commitment. [Storage boundary](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/content/docs/03-ai-sdk-harnesses/07-ui.mdx#L97-L145).
|
|
116
|
+
|
|
117
|
+
## Fidelity limits
|
|
118
|
+
|
|
119
|
+
- **Claude:** messages with `parent_tool_use_id` are excluded from the parent
|
|
120
|
+
text/tool projection. The regression asserts no child-agent events leak into
|
|
121
|
+
that stream. A captured parent stream therefore cannot reconstruct the full
|
|
122
|
+
child execution. [Filter](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness-claude-code/src/bridge/create-emit-stream-event.ts#L213-L218),
|
|
123
|
+
[test](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness-claude-code/src/bridge/create-emit-stream-event.test.ts#L470-L522).
|
|
124
|
+
- **Codex:** completed file changes become operation/path events; MCP results
|
|
125
|
+
prefer `structured_content` over `content` rather than preserving the native
|
|
126
|
+
result envelope. This is selective normalization, not a reversible native
|
|
127
|
+
transcript encoding. [Projection](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness-codex/src/bridge/create-emit-stream-event.ts#L226-L271).
|
|
128
|
+
- **Raw is not automatic preservation:** the common union permits
|
|
129
|
+
`{ type: 'raw', rawValue }` and the translator forwards it, but the inspected
|
|
130
|
+
Claude/Codex native loops feed their selective emitters without also emitting
|
|
131
|
+
each original native event as `raw`. The escape hatch does not recover events
|
|
132
|
+
those adapters never emit. [Raw forwarding](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/agent/internal/translate-stream-part.ts#L252-L257),
|
|
133
|
+
[Claude loop](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness-claude-code/src/bridge/index.ts#L582-L600),
|
|
134
|
+
[Codex loop](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness-codex/src/bridge/index.ts#L234-L264).
|
|
135
|
+
- **SDK projection adds synthetic events:** file changes and compaction become
|
|
136
|
+
dynamic, provider-executed tool-call/result pairs with generated IDs. These
|
|
137
|
+
make UI rendering uniform; they are not original native tool calls or stable
|
|
138
|
+
source-record identities. [Translation](https://github.com/vercel/ai/blob/45f2b6a5bc06bdb40a847ea961f8d7ca7cd86563/packages/harness/src/agent/internal/translate-stream-part.ts#L165-L247).
|
|
139
|
+
|
|
140
|
+
**Ledger implication (inference):** HarnessAgent is useful as a live integration
|
|
141
|
+
boundary. Its normalized streams and opaque lifecycle state do not replace
|
|
142
|
+
historical source discovery, native-source retention, provenance/identity, or a
|
|
143
|
+
durable canonical archive. An application may persist UI messages for its own
|
|
144
|
+
chat history, but that does not establish complete cross-harness execution
|
|
145
|
+
evidence. No new implementation or adoption decision is made here.
|