autodev-cli 1.4.97 → 1.4.101
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/media/profile/00-identity.md +8 -20
- package/media/profile/01-learning.md +12 -19
- package/media/profile/02-memory-mcp.md +4 -44
- package/media/profile/03-living-docs.md +10 -13
- package/media/profile/04-skill-files.md +3 -5
- package/media/profile/05-skill-creation.md +3 -14
- package/media/profile/06-core-rules.md +10 -47
- package/media/profile/07-core-loop.md +8 -25
- package/media/profile/08-thinking.md +10 -23
- package/media/profile/09-parallel-panel.md +9 -24
- package/media/profile/10-codebase-verification.md +7 -16
- package/media/profile/11-git-debug-security.md +5 -10
- package/media/profile/12-todo-format.md +3 -16
- package/media/profile/13-workflow-principles.md +3 -7
- package/media/profile/14-contracts.md +9 -12
- package/media/profile/15-soul.md +6 -8
- package/media/profile/16-journal.md +5 -32
- package/media/profile/17-issue-tracking.md +9 -14
- package/media/profile/18-knowledgebase.md +6 -9
- package/media/profile/19-subagent-context-management.md +11 -496
- package/media/profile/20-project-graph.md +23 -49
- package/out/commands/mcpOperate.js +150 -32
- package/out/commands/mcpOperate.js.map +1 -1
- package/out/core/controlSpec.d.ts +56 -0
- package/out/core/controlSpec.js +267 -0
- package/out/core/controlSpec.js.map +1 -0
- package/out/dispatcher.js +3 -1
- package/out/dispatcher.js.map +1 -1
- package/out/graphRender.d.ts +87 -0
- package/out/graphRender.js +279 -0
- package/out/graphRender.js.map +1 -0
- package/out/graphStore.d.ts +377 -2
- package/out/graphStore.js +1240 -64
- package/out/graphStore.js.map +1 -1
- package/out/journal.d.ts +35 -0
- package/out/journal.js +167 -0
- package/out/journal.js.map +1 -0
- package/out/messageBuilder.d.ts +1 -1
- package/out/messageBuilder.js +29 -29
- package/out/messageBuilder.js.map +1 -1
- package/out/periodicActions.d.ts +18 -0
- package/out/periodicActions.js +49 -0
- package/out/periodicActions.js.map +1 -1
- package/out/profileBuilder.d.ts +1 -1
- package/out/profileBuilder.js +31 -4
- package/out/profileBuilder.js.map +1 -1
- package/out/taskLoop.d.ts +19 -0
- package/out/taskLoop.js +214 -4
- package/out/taskLoop.js.map +1 -1
- package/package.json +2 -2
package/out/graphStore.d.ts
CHANGED
|
@@ -22,6 +22,14 @@
|
|
|
22
22
|
* 3. Every `evaluation` identifies a `rubric`.
|
|
23
23
|
* 4. Superseded nodes remain addressable — supersede never deletes; it links a
|
|
24
24
|
* new version with a `supersedes` edge and flags the old one.
|
|
25
|
+
*
|
|
26
|
+
* MATERIALISATION (Tier 0). The log is append-only, so reload is incremental: we
|
|
27
|
+
* remember a byte offset and apply only the newly-appended tail on top of the
|
|
28
|
+
* live maps (apply is idempotent last-writer-wins) — a full clear+rebuild only
|
|
29
|
+
* happens when the file shrank (a rewrite). Two derived indexes are kept in step:
|
|
30
|
+
* an adjacency index (nodeId → incident edges) and an entity canonical-key index
|
|
31
|
+
* (name → entity id) so `UsageService` / `usage-service` / `usage service` all
|
|
32
|
+
* resolve to ONE entity.
|
|
25
33
|
*/
|
|
26
34
|
export type GraphNodeType = 'entity' | 'claim' | 'source' | 'artifact' | 'agent_run' | 'evaluation' | 'task' | 'commit' | 'metric' | 'note' | 'question' | 'decision';
|
|
27
35
|
export type GraphEdgeType = 'mentions' | 'supports' | 'contradicts' | 'derived_from' | 'produced' | 'evaluates' | 'revises' | 'supersedes' | 'depends_on' | 'parent_of' | 'resolved_to' | 'relates_to';
|
|
@@ -32,6 +40,14 @@ export interface GraphNode {
|
|
|
32
40
|
type: GraphNodeType;
|
|
33
41
|
name: string;
|
|
34
42
|
body?: string;
|
|
43
|
+
/**
|
|
44
|
+
* A one-line gist of the node — the navigation enabler (Tier 1, item 3).
|
|
45
|
+
* Agent-supplied at write (the writing agent already holds the context, and it
|
|
46
|
+
* rides its provenance like any write). Optional and purely additive: old log
|
|
47
|
+
* lines without `summary` replay fine. When absent on an interior/hub node, a
|
|
48
|
+
* deterministic structural rollup is synthesized on read (no LLM call).
|
|
49
|
+
*/
|
|
50
|
+
summary?: string;
|
|
35
51
|
props?: Record<string, unknown>;
|
|
36
52
|
/** Where the fact came from (a citation, url, file:line, or a source node id). */
|
|
37
53
|
source?: string;
|
|
@@ -69,6 +85,8 @@ export interface AddNodeInput {
|
|
|
69
85
|
name: string;
|
|
70
86
|
id?: string;
|
|
71
87
|
body?: string;
|
|
88
|
+
/** One-line gist (Tier 1). Stamped with a `summaryAt` prop so staleness is detectable. */
|
|
89
|
+
summary?: string;
|
|
72
90
|
props?: Record<string, unknown>;
|
|
73
91
|
source?: string;
|
|
74
92
|
inference?: boolean;
|
|
@@ -86,26 +104,227 @@ export interface AddEdgeInput {
|
|
|
86
104
|
/** A write rejected by an invariant — the caller turns this into a helpful error. */
|
|
87
105
|
export declare class GraphInvariantError extends Error {
|
|
88
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Split a label into normalised word tokens: break camelCase / PascalCase and
|
|
109
|
+
* acronym boundaries into words, lowercase, and split on any non-alphanumeric.
|
|
110
|
+
* `"UsageService"` → `["usage","service"]`, `"usage-service"` → `["usage","service"]`,
|
|
111
|
+
* `"HTTPServer v2"` → `["http","server","v2"]`.
|
|
112
|
+
*/
|
|
113
|
+
export declare function tokenize(s: string): string[];
|
|
114
|
+
/**
|
|
115
|
+
* Canonical dedup key for an entity name: a **sorted, de-duplicated token set**.
|
|
116
|
+
* This collapses camelCase, kebab-case and spaced spellings AND word order to a
|
|
117
|
+
* single key, so `UsageService`, `usage-service` and `usage service` map to one
|
|
118
|
+
* `entity:` id. Sorting means `"Service Usage"` also collapses onto the same key.
|
|
119
|
+
*/
|
|
120
|
+
export declare function canonicalKey(s: string): string;
|
|
121
|
+
/** Rough token estimate for budgeting — ~4 chars/token. */
|
|
122
|
+
export declare function estimateTokens(s: string): number;
|
|
123
|
+
/**
|
|
124
|
+
* Parse a `file:line`-style source into its cumulative path segments — the spine
|
|
125
|
+
* an auto-scaffold builds (item 1). `"src/foo/bar.ts:12"` → `["src","src/foo",
|
|
126
|
+
* "src/foo/bar.ts"]`; `"pay.ts:10"` → `["pay.ts"]`. Returns null for a URL, a
|
|
127
|
+
* source-node id (`source:ab12`), or anything that doesn't look like a path — the
|
|
128
|
+
* scaffold is deterministic and conservative, never a guess.
|
|
129
|
+
*/
|
|
130
|
+
export declare function parseSourcePath(source: string | undefined): string[] | null;
|
|
131
|
+
/** A scored query row (Tier 1) — reused by graph_query, graph_map and graph_search. */
|
|
132
|
+
export interface ScoredNode {
|
|
133
|
+
node: GraphNode;
|
|
134
|
+
score: number;
|
|
135
|
+
textScore: number;
|
|
136
|
+
matched: string[];
|
|
137
|
+
substring: boolean;
|
|
138
|
+
}
|
|
139
|
+
/** One "where do I start" map entry: a node plus its effective (authored or synthesized) summary. */
|
|
140
|
+
export interface MapEntry {
|
|
141
|
+
id: string;
|
|
142
|
+
type: GraphNodeType;
|
|
143
|
+
name: string;
|
|
144
|
+
summary?: string;
|
|
145
|
+
synthesized?: boolean;
|
|
146
|
+
stale?: boolean;
|
|
147
|
+
degree: number;
|
|
148
|
+
}
|
|
149
|
+
export interface GraphMap {
|
|
150
|
+
/** Pinned "core" tier (item 4): project invariants always prepended within budget. */
|
|
151
|
+
pinned: MapEntry[];
|
|
152
|
+
hubs: MapEntry[];
|
|
153
|
+
questions: MapEntry[];
|
|
154
|
+
decisions: MapEntry[];
|
|
155
|
+
contradictions: {
|
|
156
|
+
a: {
|
|
157
|
+
id: string;
|
|
158
|
+
name: string;
|
|
159
|
+
};
|
|
160
|
+
b: {
|
|
161
|
+
id: string;
|
|
162
|
+
name: string;
|
|
163
|
+
};
|
|
164
|
+
}[];
|
|
165
|
+
}
|
|
166
|
+
/** One node of a navigable table-of-contents (item 2). */
|
|
167
|
+
export interface TocNode {
|
|
168
|
+
id: string;
|
|
169
|
+
type: string;
|
|
170
|
+
name: string;
|
|
171
|
+
summary?: string;
|
|
172
|
+
synthesized?: boolean;
|
|
173
|
+
/** Total parent_of children (before the maxChildren cap). */
|
|
174
|
+
childCount: number;
|
|
175
|
+
children: TocNode[];
|
|
176
|
+
/** Children collapsed by the maxChildren cap or depth bound — the "+K more". */
|
|
177
|
+
moreChildren?: number;
|
|
178
|
+
}
|
|
179
|
+
export interface TocResult {
|
|
180
|
+
roots: TocNode[];
|
|
181
|
+
/** True when the spine was sparse and roots fell back to deterministic clustering. */
|
|
182
|
+
clustered?: boolean;
|
|
183
|
+
}
|
|
184
|
+
/** One row of a graph_search bundle — citable, with the edge-path from its seed. */
|
|
185
|
+
export interface SearchRow {
|
|
186
|
+
id: string;
|
|
187
|
+
type: GraphNodeType;
|
|
188
|
+
name: string;
|
|
189
|
+
score: number;
|
|
190
|
+
matched: string[];
|
|
191
|
+
summary?: string;
|
|
192
|
+
synthesized?: boolean;
|
|
193
|
+
inference?: boolean;
|
|
194
|
+
seedId: string;
|
|
195
|
+
/** The edge used to reach this node (undefined for a seed). */
|
|
196
|
+
via?: {
|
|
197
|
+
edge: GraphEdgeType;
|
|
198
|
+
fromId: string;
|
|
199
|
+
dir: 'out' | 'in';
|
|
200
|
+
};
|
|
201
|
+
/** Hop descriptors from the seed, e.g. ["supports→ claim:ab12"] — for explainability. */
|
|
202
|
+
path: string[];
|
|
203
|
+
conflicts: {
|
|
204
|
+
id: string;
|
|
205
|
+
name: string;
|
|
206
|
+
}[];
|
|
207
|
+
}
|
|
208
|
+
export interface SearchResult {
|
|
209
|
+
intent: string;
|
|
210
|
+
terms: string[];
|
|
211
|
+
budget: number;
|
|
212
|
+
hops: number;
|
|
213
|
+
rows: SearchRow[];
|
|
214
|
+
}
|
|
89
215
|
export declare class GraphStore {
|
|
90
216
|
private identity;
|
|
91
217
|
private readonly dir;
|
|
92
218
|
private readonly file;
|
|
219
|
+
/** Disposable materialised cache for cold-start (item 3). JSONL stays the sole source of truth. */
|
|
220
|
+
private readonly snapshotFile;
|
|
221
|
+
private readonly snapshotEnabled;
|
|
222
|
+
/** Byte offset the on-disk snapshot covers (0 = none loaded/written this session). */
|
|
223
|
+
private snapshotCoversBytes;
|
|
224
|
+
/** Ops applied since the last snapshot was written/loaded — the regeneration trigger. */
|
|
225
|
+
private opsSinceSnapshot;
|
|
93
226
|
private nodes;
|
|
94
227
|
private edges;
|
|
228
|
+
/** nodeId → incident edges (both directions). Rebuilt on clear, kept in step in apply(). */
|
|
229
|
+
private adjacency;
|
|
230
|
+
/** entity canonical-key → entity node id — the dedup + legacy-id resolution index. */
|
|
231
|
+
private entityIndex;
|
|
95
232
|
private lastSize;
|
|
96
233
|
private lastMtimeMs;
|
|
97
|
-
|
|
234
|
+
/** byte offset up to (and including) the last COMPLETE log line we've applied. */
|
|
235
|
+
private lastOffset;
|
|
236
|
+
/** total log ops applied since the last full rebuild (for dead-weight telemetry). */
|
|
237
|
+
private appliedOps;
|
|
238
|
+
/** complete-but-corrupt (JSON-unparseable) MIDDLE lines seen; a torn FINAL line is NOT counted. */
|
|
239
|
+
private parseFailures;
|
|
240
|
+
/** wall-clock ms of the last (incremental or full) reload. */
|
|
241
|
+
private lastReplayMs;
|
|
242
|
+
/** Monotonic node-set version bumped by apply() — the invalidation signal reload uses. */
|
|
243
|
+
private mutationSeq;
|
|
244
|
+
/** IDF over the resident node set, memoised until mutationSeq changes (item 1). */
|
|
245
|
+
private idfCache;
|
|
246
|
+
private idfCacheSeq;
|
|
247
|
+
constructor(workspaceRoot: string, identity: Identity, opts?: {
|
|
248
|
+
snapshot?: boolean;
|
|
249
|
+
});
|
|
98
250
|
/** Where the graph lives (for messages). */
|
|
99
251
|
get path(): string;
|
|
100
252
|
private ensureDir;
|
|
101
|
-
|
|
253
|
+
private clear;
|
|
254
|
+
/**
|
|
255
|
+
* Re-materialise from disk when the log changed under us (another agent wrote).
|
|
256
|
+
* INCREMENTAL: since the log is append-only we treat `lastOffset` as a byte
|
|
257
|
+
* cursor and apply only the newly-appended tail on top of the live maps (apply
|
|
258
|
+
* is idempotent). A full clear+rebuild happens only when the file shrank below
|
|
259
|
+
* our cursor (a rewrite). A torn final line is left unconsumed and picked up on
|
|
260
|
+
* a later tick once the writer finishes it. This is provably identical to a
|
|
261
|
+
* full replay because apply() is last-writer-wins and the log is append-only.
|
|
262
|
+
*/
|
|
102
263
|
reloadIfChanged(): void;
|
|
264
|
+
/**
|
|
265
|
+
* Cold-start load: if a valid snapshot covers a prefix of the current log, adopt
|
|
266
|
+
* it and tail-replay only the uncovered bytes; otherwise full-replay. The
|
|
267
|
+
* snapshot is a DISPOSABLE cache — a missing / stale / corrupt one simply falls
|
|
268
|
+
* back to full replay, and the JSONL is never touched.
|
|
269
|
+
*/
|
|
270
|
+
private loadFromScratch;
|
|
271
|
+
/** sha256 of the first min(4096, covers) bytes of the log — the cheap rewrite guard. */
|
|
272
|
+
private headSig;
|
|
273
|
+
/**
|
|
274
|
+
* Adopt the on-disk snapshot iff it is a valid prefix of the current log:
|
|
275
|
+
* `coversBytes` in (0, size] AND the head-signature still matches (guards against
|
|
276
|
+
* a rewritten/truncated log whose prefix changed). Rebuilds the derived indexes
|
|
277
|
+
* from the resident node/edge set rather than trusting serialized indexes.
|
|
278
|
+
*/
|
|
279
|
+
private tryLoadSnapshot;
|
|
280
|
+
/** Regenerate the snapshot when the uncovered tail grew past the byte/op threshold. */
|
|
281
|
+
private maybeWriteSnapshot;
|
|
282
|
+
/**
|
|
283
|
+
* Write the snapshot atomically (temp file + rename) so a partial write is never
|
|
284
|
+
* visible and concurrent multi-agent regenerations can't corrupt it — the loser
|
|
285
|
+
* of a rename race simply leaves a consistent, self-describing file behind. Snaps
|
|
286
|
+
* only the byte prefix we've fully applied (`lastOffset`), so a torn final line is
|
|
287
|
+
* never captured.
|
|
288
|
+
*/
|
|
289
|
+
private writeSnapshot;
|
|
290
|
+
/** Force a snapshot now (test hook / explicit checkpoint). No-op when snapshots are disabled. */
|
|
291
|
+
materializeSnapshot(): boolean;
|
|
292
|
+
/** Read bytes [start,end), apply every COMPLETE line, and advance lastOffset past them. */
|
|
293
|
+
private replayRange;
|
|
103
294
|
private apply;
|
|
295
|
+
private indexEntity;
|
|
296
|
+
private indexEdge;
|
|
297
|
+
private pushAdj;
|
|
298
|
+
private unindexEdge;
|
|
104
299
|
private append;
|
|
105
300
|
addNode(input: AddNodeInput): {
|
|
106
301
|
node: GraphNode;
|
|
107
302
|
created: boolean;
|
|
108
303
|
};
|
|
304
|
+
/**
|
|
305
|
+
* The write path. `scaffold:true` (the public {@link addNode}) additionally runs
|
|
306
|
+
* the deterministic parent_of auto-scaffold (item 1); the scaffold's own entity
|
|
307
|
+
* writes pass `scaffold:false` so they never recurse.
|
|
308
|
+
*/
|
|
309
|
+
private addNodeInternal;
|
|
310
|
+
/**
|
|
311
|
+
* Deterministically fill the parent_of tree from a fact's provenance — NO LLM.
|
|
312
|
+
* A `file:line` source on a claim/artifact/decision/note upserts `entity` nodes
|
|
313
|
+
* for the file and its ancestor dirs and links a `dir → file → fact` spine; a
|
|
314
|
+
* `props.area` tag upserts an area entity and parents the fact under it. Every
|
|
315
|
+
* derived node/edge carries this run's provenance and a `props.autoScaffold=true`
|
|
316
|
+
* marker, and is idempotent (deterministic ids + edge dedup) so re-adds and
|
|
317
|
+
* concurrent writers converge instead of duplicating.
|
|
318
|
+
*/
|
|
319
|
+
private scaffold;
|
|
320
|
+
private scaffoldFromSource;
|
|
321
|
+
private scaffoldFromArea;
|
|
322
|
+
/** Is there already an edge of `type` from→to? (idempotency for scaffold/rollup edges). */
|
|
323
|
+
private hasEdge;
|
|
324
|
+
/** Add a parent_of edge (marked autoScaffold) unless it already exists. */
|
|
325
|
+
private linkParentOf;
|
|
326
|
+
/** Deterministic id for a new node: entities dedupe by canonical key (+ aliases), others are fresh. */
|
|
327
|
+
private mintId;
|
|
109
328
|
addEdge(input: AddEdgeInput): GraphEdge;
|
|
110
329
|
/**
|
|
111
330
|
* Version a node: create the replacement, link it with a `supersedes` edge,
|
|
@@ -118,28 +337,172 @@ export declare class GraphStore {
|
|
|
118
337
|
edge: GraphEdge;
|
|
119
338
|
};
|
|
120
339
|
getNode(idOrName: string): GraphNode | undefined;
|
|
340
|
+
/** Incident `contradicts` edges of a node, resolved to {id,name} of the other endpoint. */
|
|
341
|
+
contradictionsFor(id: string): {
|
|
342
|
+
id: string;
|
|
343
|
+
name: string;
|
|
344
|
+
}[];
|
|
345
|
+
/** Node degree (incident edge count) — shared ranking infra for Tier 1. */
|
|
346
|
+
degree(id: string): number;
|
|
347
|
+
/** IDF over the resident node set, memoised until the node set mutates. */
|
|
348
|
+
private idf;
|
|
349
|
+
/** Exponential recency lift in [0,1]: 1 at now, decaying with age (τ≈30d). */
|
|
350
|
+
private recencyDecay;
|
|
351
|
+
/** Field-weighted TF·IDF text score for a node against a set of query terms. */
|
|
352
|
+
private scoreNode;
|
|
353
|
+
/**
|
|
354
|
+
* Relevance-ranked query (Tier 1, item 1). OR-semantics: a node is a hit if it
|
|
355
|
+
* matches ≥1 query term OR contains the intent as an exact substring (the old
|
|
356
|
+
* behaviour, kept as a guaranteed-inclusion signal → strict superset). Ranked by
|
|
357
|
+
* `textScore·(1 + wRecency·decay + wDegree·log1p(degree))`. `mode:'recent'` keeps
|
|
358
|
+
* the pure recency order; superseded nodes hidden unless includeSuperseded.
|
|
359
|
+
*/
|
|
360
|
+
scoredQuery(opts: {
|
|
361
|
+
type?: string;
|
|
362
|
+
text?: string;
|
|
363
|
+
id?: string;
|
|
364
|
+
includeSuperseded?: boolean;
|
|
365
|
+
limit?: number;
|
|
366
|
+
mode?: 'relevance' | 'recent';
|
|
367
|
+
}): ScoredNode[];
|
|
368
|
+
/**
|
|
369
|
+
* Search nodes by type and/or text. Thin wrapper over {@link scoredQuery}: with
|
|
370
|
+
* `text` it returns relevance-ranked hits (item 1); without, recency order. The
|
|
371
|
+
* old pure-substring behaviour survives as a guaranteed-inclusion subset.
|
|
372
|
+
*/
|
|
121
373
|
query(opts: {
|
|
122
374
|
type?: string;
|
|
123
375
|
text?: string;
|
|
124
376
|
id?: string;
|
|
125
377
|
includeSuperseded?: boolean;
|
|
126
378
|
limit?: number;
|
|
379
|
+
mode?: 'relevance' | 'recent';
|
|
127
380
|
}): GraphNode[];
|
|
128
381
|
/**
|
|
129
382
|
* Bounded neighbourhood around a node — the playbook's "context construction
|
|
130
383
|
* from a graph": resolve the entity, expand a hop or two over allowed edge
|
|
131
384
|
* types, and return a small, citable subgraph rather than the whole graph.
|
|
385
|
+
* Uses the adjacency index (O(visited degree), not O(E·hops)) and returns the
|
|
386
|
+
* BFS hop-distance per node so the caller can rank/token-budget the result.
|
|
387
|
+
* `includeConflicts` (default true) always follows `contradicts` edges so a
|
|
388
|
+
* conflicting claim can never be hidden by an `edgeTypes` filter.
|
|
132
389
|
*/
|
|
133
390
|
neighbors(opts: {
|
|
134
391
|
idOrName: string;
|
|
135
392
|
hops?: number;
|
|
136
393
|
edgeTypes?: string[];
|
|
137
394
|
limit?: number;
|
|
395
|
+
includeConflicts?: boolean;
|
|
138
396
|
}): {
|
|
139
397
|
center: GraphNode;
|
|
140
398
|
nodes: GraphNode[];
|
|
141
399
|
edges: GraphEdge[];
|
|
400
|
+
dist: Record<string, number>;
|
|
142
401
|
} | null;
|
|
402
|
+
/** Distinct neighbour nodes of a node (via the adjacency index). */
|
|
403
|
+
private neighborNodes;
|
|
404
|
+
/** `parent_of` children of a node (this node as the parent). */
|
|
405
|
+
private childrenOf;
|
|
406
|
+
/**
|
|
407
|
+
* DETERMINISTIC one-line rollup for an interior/hub node with NO authored
|
|
408
|
+
* summary — NO LLM call. Synthesised from structure: child (or, absent
|
|
409
|
+
* `parent_of` children, neighbour) type counts + the top child names by degree.
|
|
410
|
+
* Returns undefined for a leaf/low-degree node (nothing to summarise).
|
|
411
|
+
*/
|
|
412
|
+
rollupSummary(id: string): string | undefined;
|
|
413
|
+
/**
|
|
414
|
+
* The summary to SHOW for a node: the authored one if present, else the
|
|
415
|
+
* deterministic structural rollup (flagged synthesized), else nothing.
|
|
416
|
+
*/
|
|
417
|
+
effectiveSummary(node: GraphNode): {
|
|
418
|
+
text: string;
|
|
419
|
+
synthesized: boolean;
|
|
420
|
+
} | undefined;
|
|
421
|
+
/**
|
|
422
|
+
* An AUTHORED summary is stale when the node has been superseded, or gained a
|
|
423
|
+
* `parent_of` child AFTER the summary was written (`props.summaryAt`). Nodes
|
|
424
|
+
* with no authored summary are "unsummarized", not stale.
|
|
425
|
+
*/
|
|
426
|
+
summaryStale(node: GraphNode): boolean;
|
|
427
|
+
private mapEntry;
|
|
428
|
+
/**
|
|
429
|
+
* "Where do I start" for an agent with no id/name in hand. Ranks entities (and
|
|
430
|
+
* any node when `focusType` unset) by degree() over the adjacency index, and
|
|
431
|
+
* bundles the open `question`s, freshest `decision`s, and live `contradicts`
|
|
432
|
+
* pairs it already knows how to find. Purely read-side; render via graphRender.
|
|
433
|
+
*/
|
|
434
|
+
map(opts?: {
|
|
435
|
+
depth?: number;
|
|
436
|
+
focusType?: string;
|
|
437
|
+
maxChildren?: number;
|
|
438
|
+
}): GraphMap;
|
|
439
|
+
/** A node is pinned by `props.pinned===true` or by the reserved `props.area==='core'`. */
|
|
440
|
+
private isPinnedNode;
|
|
441
|
+
/** Live pinned nodes (project invariants) — always prepended within budget. */
|
|
442
|
+
pinnedNodes(): GraphNode[];
|
|
443
|
+
/** Set/clear the pin flag on a node (upsert; the node stays otherwise unchanged). */
|
|
444
|
+
pin(idOrName: string, pinned?: boolean): GraphNode;
|
|
445
|
+
/**
|
|
446
|
+
* Vectorless, explainable, CITABLE retrieval — the PageIndex centrepiece done
|
|
447
|
+
* without embeddings and without a server-side model (the calling agent is the
|
|
448
|
+
* reasoner). Seed with the item-1 ranked query on `intent`, then best-first
|
|
449
|
+
* expand a relevance-priority frontier: pop the best node, expand 1 hop
|
|
450
|
+
* (strong provenance edges — supports/derived_from/produced/evaluates/
|
|
451
|
+
* depends_on/parent_of — before weak relates_to/mentions), score newly-found
|
|
452
|
+
* nodes against the intent, push. Stop at node_budget. Each returned row cites
|
|
453
|
+
* `[id]` with the matched terms and the edge-path from its seed.
|
|
454
|
+
*/
|
|
455
|
+
search(opts: {
|
|
456
|
+
intent: string;
|
|
457
|
+
nodeBudget?: number;
|
|
458
|
+
hops?: number;
|
|
459
|
+
}): SearchResult;
|
|
460
|
+
private parentOfChildIds;
|
|
461
|
+
private hasParentOfParent;
|
|
462
|
+
private hasParentOfChild;
|
|
463
|
+
/** Connected components of `pool` over the given (undirected) edge types. */
|
|
464
|
+
private components;
|
|
465
|
+
/**
|
|
466
|
+
* Depth-bounded, summarized hierarchy (PageIndex-style "text-stripped overview →
|
|
467
|
+
* drill"). The spine is `parent_of` (roots = entities with no incoming parent_of);
|
|
468
|
+
* where that spine is sparse the uncovered remainder falls back to deterministic
|
|
469
|
+
* clustering (by `props.area`, else connected components over relates_to/
|
|
470
|
+
* depends_on). Each level shows the top `maxChildren` by degree and collapses the
|
|
471
|
+
* rest to `+K more`. Summaries reuse {@link effectiveSummary}. Pass `root` to
|
|
472
|
+
* expand one branch.
|
|
473
|
+
*/
|
|
474
|
+
toc(opts?: {
|
|
475
|
+
root?: string;
|
|
476
|
+
depth?: number;
|
|
477
|
+
focusType?: string;
|
|
478
|
+
maxChildren?: number;
|
|
479
|
+
}): TocResult;
|
|
480
|
+
/** Deterministic id for a cluster's rollup node, so concurrent rollups upsert not duplicate. */
|
|
481
|
+
private rollupId;
|
|
482
|
+
/** parent_of descendants of a node (transitive), excluding itself. */
|
|
483
|
+
private descendants;
|
|
484
|
+
private rollupFromMembers;
|
|
485
|
+
/** The rollup/summary node for a cluster centre, if one has been created. */
|
|
486
|
+
rollupNodeFor(idOrName: string): GraphNode | undefined;
|
|
487
|
+
/**
|
|
488
|
+
* Create or upsert a hierarchical rollup for a cluster (item 5). The cluster is a
|
|
489
|
+
* centre entity's `parent_of` descendants, or — absent a spine — its N-hop
|
|
490
|
+
* neighbourhood. The rollup is a `note` with `props.rollup=true` and a
|
|
491
|
+
* DETERMINISTIC id (`summary:<centre-key>`) so concurrent rollups of the same
|
|
492
|
+
* cluster upsert rather than duplicate; it links `derived_from → each member`
|
|
493
|
+
* (members stay fully addressable in `props.members`) and hangs under the centre
|
|
494
|
+
* via `parent_of` so it's discoverable in the TOC. Summary text is agent-supplied
|
|
495
|
+
* or the deterministic Tier-1 rollup (no LLM on the default path).
|
|
496
|
+
*/
|
|
497
|
+
rollup(opts: {
|
|
498
|
+
idOrName?: string;
|
|
499
|
+
hops?: number;
|
|
500
|
+
summary?: string;
|
|
501
|
+
}): {
|
|
502
|
+
node: GraphNode;
|
|
503
|
+
members: string[];
|
|
504
|
+
created: boolean;
|
|
505
|
+
};
|
|
143
506
|
stats(): {
|
|
144
507
|
nodeCount: number;
|
|
145
508
|
edgeCount: number;
|
|
@@ -149,5 +512,17 @@ export declare class GraphStore {
|
|
|
149
512
|
isolated: number;
|
|
150
513
|
contradictions: number;
|
|
151
514
|
openQuestions: number;
|
|
515
|
+
unsummarized: number;
|
|
516
|
+
staleSummaries: number;
|
|
517
|
+
spinelessHubs: number;
|
|
518
|
+
pinned: number;
|
|
519
|
+
fileBytes: number;
|
|
520
|
+
totalOps: number;
|
|
521
|
+
deadWeight: number;
|
|
522
|
+
deadWeightRatio: number;
|
|
523
|
+
lastReplayMs: number;
|
|
524
|
+
estTokens: number;
|
|
525
|
+
parseFailures: number;
|
|
526
|
+
tornFinalLine: boolean;
|
|
152
527
|
};
|
|
153
528
|
}
|