trajectories 0.0.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/LICENSE +201 -0
- package/README.md +288 -2
- package/dist/cli.js +30210 -0
- package/dist/convert.d.ts +31 -0
- package/dist/convert.js +431 -0
- package/dist/deepagents_checkpoint.py +362 -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 +1233 -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 +150 -0
- package/ops/install-cli.sh +63 -0
- package/ops/install-native.sh +35 -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 +21 -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,436 @@
|
|
|
1
|
+
import type { DiscoveryCheckpoint } from "./discovery.js";
|
|
2
|
+
import type {
|
|
3
|
+
AnyTrajectorySource,
|
|
4
|
+
CanonicalRecord,
|
|
5
|
+
CanonicalRecordType,
|
|
6
|
+
Diagnostic,
|
|
7
|
+
NormalizedRecord,
|
|
8
|
+
SourceIdentityKind,
|
|
9
|
+
} from "@letta-ai/trajectory";
|
|
10
|
+
|
|
11
|
+
export type SupportedSource =
|
|
12
|
+
| "claude-code"
|
|
13
|
+
| "codex"
|
|
14
|
+
| "pi"
|
|
15
|
+
| "hermes"
|
|
16
|
+
| "omp"
|
|
17
|
+
| "openclaw"
|
|
18
|
+
| "cursor"
|
|
19
|
+
| "opencode"
|
|
20
|
+
| "gemini-cli"
|
|
21
|
+
| "deepagents"
|
|
22
|
+
| "droid"
|
|
23
|
+
| "letta-code"
|
|
24
|
+
| "openhands"
|
|
25
|
+
| "copilot-cli"
|
|
26
|
+
| "grok"
|
|
27
|
+
| "kimi"
|
|
28
|
+
| "cline"
|
|
29
|
+
| "fx"
|
|
30
|
+
| "atif"
|
|
31
|
+
| string;
|
|
32
|
+
|
|
33
|
+
export interface SessionRecord {
|
|
34
|
+
id: string;
|
|
35
|
+
source: string;
|
|
36
|
+
source_path: string;
|
|
37
|
+
content_hash: string;
|
|
38
|
+
/** Version 1 is the legacy whole-session digest; version 2 is appendable. */
|
|
39
|
+
content_hash_version?: number;
|
|
40
|
+
title: string | null;
|
|
41
|
+
cwd: string | null;
|
|
42
|
+
model: string | null;
|
|
43
|
+
started_at: string | null;
|
|
44
|
+
ended_at: string | null;
|
|
45
|
+
record_count: number;
|
|
46
|
+
created_at: string;
|
|
47
|
+
updated_at: string;
|
|
48
|
+
parent_session_id?: string | null;
|
|
49
|
+
parent_tool_use_id?: string | null;
|
|
50
|
+
agent_nickname?: string | null;
|
|
51
|
+
thread_role?: string | null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface CanonicalDbRecord {
|
|
55
|
+
id: string; // record_id
|
|
56
|
+
session_id: string;
|
|
57
|
+
source_type: string;
|
|
58
|
+
/** Native lineage provenance; absent in older schemas, null when unknown. */
|
|
59
|
+
native_session_id?: string | null;
|
|
60
|
+
binding_id?: string | null;
|
|
61
|
+
record_type: CanonicalRecordType;
|
|
62
|
+
stable_source_record_id: string | null;
|
|
63
|
+
source_identity_kind: SourceIdentityKind | null;
|
|
64
|
+
source_order_id: string;
|
|
65
|
+
component_index: number;
|
|
66
|
+
record_timestamp: string | null;
|
|
67
|
+
source_timestamp: string | null;
|
|
68
|
+
content: string | null;
|
|
69
|
+
tool_call_id: string | null;
|
|
70
|
+
tool_name: string | null;
|
|
71
|
+
tool_arguments_json: string | null;
|
|
72
|
+
tool_result_json: string | null;
|
|
73
|
+
tool_result_ok: number | null; // 1 = true, 0 = false, null
|
|
74
|
+
record_json: string;
|
|
75
|
+
content_hash: string;
|
|
76
|
+
record_hash: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface NormalizedSessionResult {
|
|
80
|
+
session: SessionRecord;
|
|
81
|
+
records: CanonicalDbRecord[];
|
|
82
|
+
rawNormalizedRecords: NormalizedRecord[];
|
|
83
|
+
diagnostics: Diagnostic[];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface DiscoveredSession {
|
|
87
|
+
id: string;
|
|
88
|
+
source: string;
|
|
89
|
+
path: string;
|
|
90
|
+
updatedAt?: string;
|
|
91
|
+
title?: string;
|
|
92
|
+
sizeBytes?: number;
|
|
93
|
+
/** Native storage requiring assembly before Trajectory normalization. */
|
|
94
|
+
native?:
|
|
95
|
+
| { kind: "cursor-sqlite" | "cursor-blobstore" | "opencode-sqlite" }
|
|
96
|
+
| { kind: "opencode-storage"; root: string }
|
|
97
|
+
| { kind: "fx-directory" }
|
|
98
|
+
/** `parentSessionId` is the child's edge from the parent-side subagent registry, or absent. */
|
|
99
|
+
| { kind: "grok-updates"; parentSessionId?: string }
|
|
100
|
+
/**
|
|
101
|
+
* `parentSessionId` is the enclosing session of a `subagents/<agent>/` transcript;
|
|
102
|
+
* `parentToolUseId` is the tool call that spawned it, read from the parent's wire.
|
|
103
|
+
*/
|
|
104
|
+
| { kind: "kimi-wire"; parentSessionId?: string; parentToolUseId?: string };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface IngestCursor {
|
|
108
|
+
source: string;
|
|
109
|
+
listing_id: string;
|
|
110
|
+
source_path: string;
|
|
111
|
+
session_id: string | null;
|
|
112
|
+
mtime: string;
|
|
113
|
+
size: number;
|
|
114
|
+
bytes_ingested: number;
|
|
115
|
+
record_count: number;
|
|
116
|
+
status: "ok" | "failed" | "pending";
|
|
117
|
+
updated_at: string;
|
|
118
|
+
file_identity?: string | null;
|
|
119
|
+
prefix_hash?: string | null;
|
|
120
|
+
checkpoint_version?: number | null;
|
|
121
|
+
line_count?: number | null;
|
|
122
|
+
tail_offset?: number | null;
|
|
123
|
+
tail_hash?: string | null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface IngestQueueEntry extends DiscoveredSession {
|
|
127
|
+
attempt_count: number;
|
|
128
|
+
next_attempt_at: string | null;
|
|
129
|
+
last_attempt_at: string | null;
|
|
130
|
+
last_outcome: string | null;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* How far one user-initiated deletion went. `suppress` is the default and the
|
|
135
|
+
* one that keeps the store canonical: the session's rows stay, and every
|
|
136
|
+
* serving and admission surface treats the session as gone. `hard` is the
|
|
137
|
+
* explicit escape — the records, vectors, echo markers, titles, diagnostics and
|
|
138
|
+
* staged replacements were removed in the tombstone's own transaction, and only
|
|
139
|
+
* the axis that stops the source from re-admitting the session is left.
|
|
140
|
+
*/
|
|
141
|
+
export type TombstoneMode = "suppress" | "hard";
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* One user's deletion, as the `session_tombstones` table holds it.
|
|
145
|
+
*
|
|
146
|
+
* Every column but `mode` is one deletion event and is never rewritten: the
|
|
147
|
+
* session it names, when it happened, and why (the reason is the audit row's
|
|
148
|
+
* whole point — a tombstone with no account of itself is a hole in the record).
|
|
149
|
+
* `mode` is the exception: a `suppress` tombstone can be escalated to `hard`
|
|
150
|
+
* later, which is the same deletion carried further, not a second one.
|
|
151
|
+
*/
|
|
152
|
+
export interface TombstoneRecord {
|
|
153
|
+
/** The Ledger session id: the axis serving knows, and the row's primary key. */
|
|
154
|
+
session_id: string;
|
|
155
|
+
source: string;
|
|
156
|
+
/**
|
|
157
|
+
* The source-native id the session was committed under
|
|
158
|
+
* (`nativeId(source, session_id)`), which is the axis a re-scan can name
|
|
159
|
+
* before it reads anything. It differs from the id a *listing* carries
|
|
160
|
+
* whenever the source groups several files under one session id.
|
|
161
|
+
*/
|
|
162
|
+
native_id: string;
|
|
163
|
+
/** Where the session was ingested from, for the audit: never an admission key. */
|
|
164
|
+
source_path: string | null;
|
|
165
|
+
mode: TombstoneMode;
|
|
166
|
+
reason: string;
|
|
167
|
+
/** Records the session held when it was deleted: the deletion's own fact. */
|
|
168
|
+
record_count: number;
|
|
169
|
+
deleted_at: string;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* One session's diagnostics collapsed to one entry per code. `occurrenceCount`
|
|
174
|
+
* deliberately mixes upstream meanings: codes such as `timestamps_interpolated`
|
|
175
|
+
* report affected records, the rest report one occurrence per diagnostic. Zero
|
|
176
|
+
* is a real value upstream reports and is never inflated to one.
|
|
177
|
+
*/
|
|
178
|
+
export interface IngestDiagnosticAggregate {
|
|
179
|
+
code: string;
|
|
180
|
+
occurrenceCount: number;
|
|
181
|
+
sample: string | null;
|
|
182
|
+
/** Earliest observation of this code, carried across staged chunks. */
|
|
183
|
+
firstSeenAt?: string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** One stored diagnostics row, as the `ingest_diagnostics` table holds it. */
|
|
187
|
+
export interface IngestDiagnosticRecord {
|
|
188
|
+
session_id: string;
|
|
189
|
+
source: string;
|
|
190
|
+
code: string;
|
|
191
|
+
occurrence_count: number;
|
|
192
|
+
sample: string | null;
|
|
193
|
+
first_seen_at: string;
|
|
194
|
+
last_seen_at: string;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** Store-wide diagnostics coverage, ordered by occurrences (descending). */
|
|
198
|
+
export interface DiagnosticsSummary {
|
|
199
|
+
totalSessions: number;
|
|
200
|
+
totalOccurrences: number;
|
|
201
|
+
byCode: Array<{ code: string; sessions: number; occurrences: number }>;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* How one source's scan ended. The set is closed: upstream listers report a
|
|
206
|
+
* missing, unreadable, or file-shaped root as an empty listing, so the status
|
|
207
|
+
* is probed scanner-side before listing and must stay reconstructible.
|
|
208
|
+
*/
|
|
209
|
+
export type ScanOutcomeStatus =
|
|
210
|
+
| "listable"
|
|
211
|
+
| "missing_root"
|
|
212
|
+
| "root_wrong_shape"
|
|
213
|
+
| "unreadable_root"
|
|
214
|
+
| "listing_failed";
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* One source's scan outcome, recomputed per scan and never persisted. `status`
|
|
218
|
+
* describes the source's scan outcome; `root` names the primary (first
|
|
219
|
+
* readable) location, which for a multi-location source can be healthy even
|
|
220
|
+
* when `detail` records a failure elsewhere; `discovered` counts the sessions
|
|
221
|
+
* the source contributed to this scan. `detail` is either an error class plus
|
|
222
|
+
* the runtime's code or a native diagnostic's fixed message — both capped at
|
|
223
|
+
* `SCAN_OUTCOME_DETAIL_LIMIT` and free of store content — and is null when the
|
|
224
|
+
* status needs no explanation.
|
|
225
|
+
*/
|
|
226
|
+
export interface ScanOutcome {
|
|
227
|
+
source: string;
|
|
228
|
+
root: string;
|
|
229
|
+
status: ScanOutcomeStatus;
|
|
230
|
+
discovered: number;
|
|
231
|
+
detail?: string | null;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* One source's stored coverage: the verdict of the last lease-holding pass that
|
|
236
|
+
* scanned it (`recordSourceCoverage`). State, not history — every later pass
|
|
237
|
+
* rewrites `root`, `status`, `discovered`, `detail`, and `updated_at` in place,
|
|
238
|
+
* including a source that stops being listable, so a stored row never claims a
|
|
239
|
+
* success the newest pass did not see. `first_seen_at` is stamped once and
|
|
240
|
+
* survives while the source keeps being seen, so the row also carries coverage
|
|
241
|
+
* age; `detail` is a scan-outcome detail, and is null when the status needs no
|
|
242
|
+
* explanation. Written only by a writer holding the lease; `scan` computes the
|
|
243
|
+
* same verdicts and persists nothing.
|
|
244
|
+
*/
|
|
245
|
+
export interface SourceCoverageRow {
|
|
246
|
+
source: string;
|
|
247
|
+
root: string;
|
|
248
|
+
status: ScanOutcomeStatus;
|
|
249
|
+
discovered: number;
|
|
250
|
+
detail: string | null;
|
|
251
|
+
first_seen_at: string;
|
|
252
|
+
updated_at: string;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* What a reader sees of a stored coverage row: the same verdict without the
|
|
257
|
+
* internal `first_seen_at` stamp, which exists to make age readable inside the
|
|
258
|
+
* store rather than to widen the status contract.
|
|
259
|
+
*/
|
|
260
|
+
export type SourceCoverage = Omit<SourceCoverageRow, "first_seen_at">;
|
|
261
|
+
|
|
262
|
+
export interface ScanResult {
|
|
263
|
+
sessions: DiscoveredSession[];
|
|
264
|
+
outcomes: ScanOutcome[];
|
|
265
|
+
/** Present only for scheduled paged discovery, never fabricated by old scanners. */
|
|
266
|
+
discovery?: DiscoveryCheckpoint[];
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export interface ScanOptions {
|
|
270
|
+
/** Opt into a bounded history page plus a recent refresh, using durable checkpoints. */
|
|
271
|
+
discovery?: Record<string, DiscoveryCheckpoint>;
|
|
272
|
+
sources?: string[];
|
|
273
|
+
roots?: Record<string, string>;
|
|
274
|
+
limit?: number;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export interface BuildOptions extends ScanOptions {
|
|
278
|
+
dbPath?: string;
|
|
279
|
+
force?: boolean;
|
|
280
|
+
verbose?: boolean;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export interface BuildSummary {
|
|
284
|
+
scanned: number;
|
|
285
|
+
imported: number;
|
|
286
|
+
deduped: number;
|
|
287
|
+
failed: number;
|
|
288
|
+
/** Processed sessions with no stored vectors of any provider after this pass.
|
|
289
|
+
* Zero does not imply complete or provider-compatible semantic coverage. */
|
|
290
|
+
unembedded: number;
|
|
291
|
+
/** Sessions for which this invocation intentionally did no embedding work. */
|
|
292
|
+
embedding_skipped: number;
|
|
293
|
+
/** Sessions whose embedding attempt failed, possibly after partial progress. */
|
|
294
|
+
embedding_failed: number;
|
|
295
|
+
/** Listings the user deleted, refused at admission: not failures, and not
|
|
296
|
+
* imports — counted so the two other numbers stay what they claim to be. */
|
|
297
|
+
tombstoned: number;
|
|
298
|
+
totalRecords: number;
|
|
299
|
+
sources: Record<string, { scanned: number; imported: number; deduped: number; failed: number; tombstoned: number }>;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* What every hit names, whichever lane produced it: the session it belongs to,
|
|
304
|
+
* where that session sits in the corpus, and the snippet to show.
|
|
305
|
+
*/
|
|
306
|
+
interface SearchHitBase {
|
|
307
|
+
session_id: string;
|
|
308
|
+
source: string;
|
|
309
|
+
title: string | null;
|
|
310
|
+
cwd: string | null;
|
|
311
|
+
started_at: string | null;
|
|
312
|
+
snippet: string;
|
|
313
|
+
/**
|
|
314
|
+
* The ranking the producing lane ordered by, in that lane's own units: the
|
|
315
|
+
* lexical lanes' bm25 weighted by the recency prior (C6), the semantic lane's
|
|
316
|
+
* cosine similarity, or a fused hit's positive RRF score. Lane-relative by
|
|
317
|
+
* construction — a title hit's rank and a record hit's rank are not
|
|
318
|
+
* comparable, and the emitted order is the contract, not a re-sort by these
|
|
319
|
+
* numbers (see the robot v1 note in `docs/api-surface.md`).
|
|
320
|
+
*/
|
|
321
|
+
rank?: number;
|
|
322
|
+
parent_session_id?: string | null;
|
|
323
|
+
agent_nickname?: string | null;
|
|
324
|
+
thread_role?: string | null;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* A hit that names one canonical record: the ordinary answer of every engine.
|
|
329
|
+
*/
|
|
330
|
+
export interface RecordSearchHit extends SearchHitBase {
|
|
331
|
+
record_id: string;
|
|
332
|
+
record_type: string;
|
|
333
|
+
content: string | null;
|
|
334
|
+
tool_name: string | null;
|
|
335
|
+
tool_arguments: string | null;
|
|
336
|
+
tool_result: string | null;
|
|
337
|
+
/**
|
|
338
|
+
* How this hit matched. `implicit_wildcard` marks hits that only matched
|
|
339
|
+
* because Ledger widened a zero-hit query to prefix terms, and `semantic`
|
|
340
|
+
* marks vector hits; `lexical` is the ordinary FTS5 path.
|
|
341
|
+
*/
|
|
342
|
+
match_type: RecordMatchType;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* A hit on a session's *title*: session-level, with no record behind it.
|
|
347
|
+
*
|
|
348
|
+
* The title index answers for a session, not for a record — the title was
|
|
349
|
+
* derived from the source's own metadata or its first user message and belongs
|
|
350
|
+
* to the trajectory as a whole, so `record_id` is `null` rather than a
|
|
351
|
+
* fabricated id pointing at a record no adapter wrote, `record_type` is
|
|
352
|
+
* `"title"` rather than a record type the hit does not have, and the snippet is
|
|
353
|
+
* the title itself. `started_at` is the session's start, which is where a
|
|
354
|
+
* consumer reading the hit should look. Wake emits the same shape (`role:
|
|
355
|
+
* "title"`, `seq: 0` and never a fake `seq`,
|
|
356
|
+
* `crates/wake-core/src/db.rs#L1676-L1700`).
|
|
357
|
+
*/
|
|
358
|
+
export interface TitleSearchHit extends SearchHitBase {
|
|
359
|
+
record_id: null;
|
|
360
|
+
record_type: "title";
|
|
361
|
+
content: null;
|
|
362
|
+
tool_name: null;
|
|
363
|
+
tool_arguments: null;
|
|
364
|
+
tool_result: null;
|
|
365
|
+
/** Non-null by construction: only a session whose title the store holds is indexed. */
|
|
366
|
+
title: string;
|
|
367
|
+
match_type: "title";
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** One search hit: a canonical record, or a session matched through its title. */
|
|
371
|
+
export type SearchHit = RecordSearchHit | TitleSearchHit;
|
|
372
|
+
|
|
373
|
+
/** Which retrieval engine produced a result set. */
|
|
374
|
+
export type SearchMode = "lexical" | "semantic" | "hybrid";
|
|
375
|
+
|
|
376
|
+
/** The match provenance a hit carrying a record can have. */
|
|
377
|
+
export type RecordMatchType = "lexical" | "implicit_wildcard" | "semantic";
|
|
378
|
+
|
|
379
|
+
/** Per-hit provenance within a result set; `title` marks a session-level title hit. */
|
|
380
|
+
export type SearchMatchType = RecordMatchType | "title";
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Why prefix widening was refused on a zero-hit lexical query. Widening is only
|
|
384
|
+
* attempted when the primary query returned nothing, so a satisfied search
|
|
385
|
+
* reports `widened: null` instead of any of these.
|
|
386
|
+
*/
|
|
387
|
+
export type WideningSkipReason =
|
|
388
|
+
| "disabled"
|
|
389
|
+
| "quoted_input"
|
|
390
|
+
| "operators_present"
|
|
391
|
+
| "wildcard_present"
|
|
392
|
+
| "token_too_long"
|
|
393
|
+
| "no_widenable_tokens"
|
|
394
|
+
| "query_too_long"
|
|
395
|
+
| "corpus_over_ceiling"
|
|
396
|
+
| "no_improvement"
|
|
397
|
+
| "widened_query_failed";
|
|
398
|
+
|
|
399
|
+
export interface WideningReport {
|
|
400
|
+
applied: boolean;
|
|
401
|
+
/** Hits the un-widened query returned; always 0 when widening ran. */
|
|
402
|
+
original_hits?: number;
|
|
403
|
+
/**
|
|
404
|
+
* Hits returned by the widened pass, bounded by the requested limit (so it is
|
|
405
|
+
* a lower bound whenever it equals the limit or the limit-bounded count).
|
|
406
|
+
*/
|
|
407
|
+
widened_hits?: number;
|
|
408
|
+
/** Agent-readable reason widening was refused. */
|
|
409
|
+
skip_reason?: WideningSkipReason;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Honest accounting for one search: how exact the count is, how long the call
|
|
414
|
+
* took, which engine actually ran, and whether the zero-hit lexical path
|
|
415
|
+
* widened the query or fell back to escaped terms.
|
|
416
|
+
*/
|
|
417
|
+
export interface SearchMeta {
|
|
418
|
+
count_precision: "exact" | "lower_bound";
|
|
419
|
+
count_reason: string;
|
|
420
|
+
elapsed_ms: number;
|
|
421
|
+
search_mode: SearchMode;
|
|
422
|
+
requested_search_mode: SearchMode;
|
|
423
|
+
fallback_reason: string | null;
|
|
424
|
+
/** Null when widening was not attempted (the primary query returned hits). */
|
|
425
|
+
widened: WideningReport | null;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
export interface QueryResult {
|
|
429
|
+
query: string;
|
|
430
|
+
/** Bounded by the caller's limit; read `meta.count_precision` before
|
|
431
|
+
* presenting this as an exact corpus count. */
|
|
432
|
+
totalHits: number;
|
|
433
|
+
sessionsCount: number;
|
|
434
|
+
hits: SearchHit[];
|
|
435
|
+
meta: SearchMeta;
|
|
436
|
+
}
|