@karmaniverous/jeeves-meta 0.1.0
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/README.md +57 -0
- package/dist/index.d.ts +825 -0
- package/dist/index.js +1394 -0
- package/package.json +111 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,825 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* List archive snapshot files in chronological order.
|
|
5
|
+
*
|
|
6
|
+
* @module archive/listArchive
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* List archive .json files sorted chronologically (oldest first).
|
|
10
|
+
*
|
|
11
|
+
* @param metaPath - Absolute path to the .meta directory.
|
|
12
|
+
* @returns Array of absolute paths to archive files, or empty if none.
|
|
13
|
+
*/
|
|
14
|
+
declare function listArchiveFiles(metaPath: string): string[];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Prune old archive snapshots beyond maxArchive.
|
|
18
|
+
*
|
|
19
|
+
* @module archive/prune
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Prune archive directory to keep at most maxArchive snapshots.
|
|
23
|
+
* Removes the oldest files.
|
|
24
|
+
*
|
|
25
|
+
* @param metaPath - Absolute path to the .meta directory.
|
|
26
|
+
* @param maxArchive - Maximum snapshots to retain.
|
|
27
|
+
* @returns Number of files pruned.
|
|
28
|
+
*/
|
|
29
|
+
declare function pruneArchive(metaPath: string, maxArchive: number): number;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Zod schema for jeeves-meta configuration.
|
|
33
|
+
*
|
|
34
|
+
* Consumers load config however they want (file, env, constructor).
|
|
35
|
+
* The library validates via this schema.
|
|
36
|
+
*
|
|
37
|
+
* @module schema/config
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/** Zod schema for jeeves-meta configuration. */
|
|
41
|
+
declare const synthConfigSchema: z.ZodObject<{
|
|
42
|
+
watchPaths: z.ZodArray<z.ZodString>;
|
|
43
|
+
watcherUrl: z.ZodURL;
|
|
44
|
+
architectEvery: z.ZodDefault<z.ZodNumber>;
|
|
45
|
+
depthWeight: z.ZodDefault<z.ZodNumber>;
|
|
46
|
+
maxArchive: z.ZodDefault<z.ZodNumber>;
|
|
47
|
+
maxLines: z.ZodDefault<z.ZodNumber>;
|
|
48
|
+
architectTimeout: z.ZodDefault<z.ZodNumber>;
|
|
49
|
+
builderTimeout: z.ZodDefault<z.ZodNumber>;
|
|
50
|
+
criticTimeout: z.ZodDefault<z.ZodNumber>;
|
|
51
|
+
defaultArchitect: z.ZodString;
|
|
52
|
+
defaultCritic: z.ZodString;
|
|
53
|
+
skipUnchanged: z.ZodDefault<z.ZodBoolean>;
|
|
54
|
+
batchSize: z.ZodDefault<z.ZodNumber>;
|
|
55
|
+
}, z.core.$strip>;
|
|
56
|
+
/** Inferred type for jeeves-meta configuration. */
|
|
57
|
+
type SynthConfig = z.infer<typeof synthConfigSchema>;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Structured error from a synthesis step failure.
|
|
61
|
+
*
|
|
62
|
+
* @module schema/error
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/** Zod schema for synthesis step errors. */
|
|
66
|
+
declare const synthErrorSchema: z.ZodObject<{
|
|
67
|
+
step: z.ZodEnum<{
|
|
68
|
+
architect: "architect";
|
|
69
|
+
builder: "builder";
|
|
70
|
+
critic: "critic";
|
|
71
|
+
}>;
|
|
72
|
+
code: z.ZodString;
|
|
73
|
+
message: z.ZodString;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
/** Inferred type for synthesis step errors. */
|
|
76
|
+
type SynthError = z.infer<typeof synthErrorSchema>;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Zod schema for .meta/meta.json files.
|
|
80
|
+
*
|
|
81
|
+
* Reserved properties are underscore-prefixed and engine-managed.
|
|
82
|
+
* All other keys are open schema (builder output).
|
|
83
|
+
*
|
|
84
|
+
* @module schema/meta
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
/** Zod schema for the reserved (underscore-prefixed) meta.json properties. */
|
|
88
|
+
declare const metaJsonSchema: z.ZodObject<{
|
|
89
|
+
_id: z.ZodUUID;
|
|
90
|
+
_steer: z.ZodOptional<z.ZodString>;
|
|
91
|
+
_architect: z.ZodOptional<z.ZodString>;
|
|
92
|
+
_builder: z.ZodOptional<z.ZodString>;
|
|
93
|
+
_critic: z.ZodOptional<z.ZodString>;
|
|
94
|
+
_generatedAt: z.ZodOptional<z.ZodISODateTime>;
|
|
95
|
+
_content: z.ZodOptional<z.ZodString>;
|
|
96
|
+
_structureHash: z.ZodOptional<z.ZodString>;
|
|
97
|
+
_synthesisCount: z.ZodOptional<z.ZodNumber>;
|
|
98
|
+
_feedback: z.ZodOptional<z.ZodString>;
|
|
99
|
+
_archived: z.ZodOptional<z.ZodBoolean>;
|
|
100
|
+
_archivedAt: z.ZodOptional<z.ZodISODateTime>;
|
|
101
|
+
_depth: z.ZodOptional<z.ZodNumber>;
|
|
102
|
+
_emphasis: z.ZodOptional<z.ZodNumber>;
|
|
103
|
+
_architectTokens: z.ZodOptional<z.ZodNumber>;
|
|
104
|
+
_builderTokens: z.ZodOptional<z.ZodNumber>;
|
|
105
|
+
_criticTokens: z.ZodOptional<z.ZodNumber>;
|
|
106
|
+
_architectTokensAvg: z.ZodOptional<z.ZodNumber>;
|
|
107
|
+
_builderTokensAvg: z.ZodOptional<z.ZodNumber>;
|
|
108
|
+
_criticTokensAvg: z.ZodOptional<z.ZodNumber>;
|
|
109
|
+
_error: z.ZodOptional<z.ZodObject<{
|
|
110
|
+
step: z.ZodEnum<{
|
|
111
|
+
architect: "architect";
|
|
112
|
+
builder: "builder";
|
|
113
|
+
critic: "critic";
|
|
114
|
+
}>;
|
|
115
|
+
code: z.ZodString;
|
|
116
|
+
message: z.ZodString;
|
|
117
|
+
}, z.core.$strip>>;
|
|
118
|
+
}, z.core.$loose>;
|
|
119
|
+
/** Inferred type for meta.json. */
|
|
120
|
+
type MetaJson = z.infer<typeof metaJsonSchema>;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Read the latest archive snapshot for steer change detection.
|
|
124
|
+
*
|
|
125
|
+
* @module archive/readLatest
|
|
126
|
+
*/
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Read the most recent archive snapshot.
|
|
130
|
+
*
|
|
131
|
+
* @param metaPath - Absolute path to the .meta directory.
|
|
132
|
+
* @returns The latest archived meta, or null if no archives exist.
|
|
133
|
+
*/
|
|
134
|
+
declare function readLatestArchive(metaPath: string): MetaJson | null;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Create archive snapshots of meta.json.
|
|
138
|
+
*
|
|
139
|
+
* Copies current meta.json to archive/\{ISO-timestamp\}.json with
|
|
140
|
+
* _archived: true and _archivedAt added.
|
|
141
|
+
*
|
|
142
|
+
* @module archive/snapshot
|
|
143
|
+
*/
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Create an archive snapshot of the current meta.json.
|
|
147
|
+
*
|
|
148
|
+
* @param metaPath - Absolute path to the .meta directory.
|
|
149
|
+
* @param meta - Current meta.json content.
|
|
150
|
+
* @returns The archive file path.
|
|
151
|
+
*/
|
|
152
|
+
declare function createSnapshot(metaPath: string, meta: MetaJson): string;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Ensure meta.json exists in each .meta/ directory.
|
|
156
|
+
*
|
|
157
|
+
* If meta.json is missing, creates it with a generated UUID.
|
|
158
|
+
*
|
|
159
|
+
* @module discovery/ensureMetaJson
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Ensure meta.json exists at the given .meta/ path.
|
|
164
|
+
*
|
|
165
|
+
* @param metaPath - Absolute path to a .meta/ directory.
|
|
166
|
+
* @returns The meta.json content (existing or newly created).
|
|
167
|
+
*/
|
|
168
|
+
declare function ensureMetaJson(metaPath: string): MetaJson;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Glob watchPaths for .meta/ directories.
|
|
172
|
+
*
|
|
173
|
+
* Walks each watchPath recursively, collecting directories named '.meta'
|
|
174
|
+
* that contain (or will contain) a meta.json file.
|
|
175
|
+
*
|
|
176
|
+
* @module discovery/globMetas
|
|
177
|
+
*/
|
|
178
|
+
/**
|
|
179
|
+
* Recursively find all .meta/ directories under the given paths.
|
|
180
|
+
*
|
|
181
|
+
* @param watchPaths - Root directories to search.
|
|
182
|
+
* @returns Array of absolute paths to .meta/ directories.
|
|
183
|
+
*/
|
|
184
|
+
declare function globMetas(watchPaths: string[]): string[];
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Types for meta discovery and ownership tree.
|
|
188
|
+
*
|
|
189
|
+
* @module discovery/types
|
|
190
|
+
*/
|
|
191
|
+
/** A discovered meta node in the ownership tree. */
|
|
192
|
+
interface MetaNode {
|
|
193
|
+
/** Absolute path to the .meta directory. */
|
|
194
|
+
metaPath: string;
|
|
195
|
+
/** Absolute path to the parent directory that this meta owns. */
|
|
196
|
+
ownerPath: string;
|
|
197
|
+
/** Depth in the ownership tree (root = 0). */
|
|
198
|
+
treeDepth: number;
|
|
199
|
+
/** Child meta nodes (subtrees with their own .meta/). */
|
|
200
|
+
children: MetaNode[];
|
|
201
|
+
/** Parent meta node, or null for roots. */
|
|
202
|
+
parent: MetaNode | null;
|
|
203
|
+
}
|
|
204
|
+
/** The full ownership tree discovered from watchPaths. */
|
|
205
|
+
interface OwnershipTree {
|
|
206
|
+
/** All discovered meta nodes, keyed by metaPath. */
|
|
207
|
+
nodes: Map<string, MetaNode>;
|
|
208
|
+
/** Root nodes (metas with no parent meta). */
|
|
209
|
+
roots: MetaNode[];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Build the ownership tree from discovered .meta/ paths.
|
|
214
|
+
*
|
|
215
|
+
* Each .meta/ directory owns its parent directory and all descendants,
|
|
216
|
+
* except subtrees that contain their own .meta/. For those subtrees,
|
|
217
|
+
* the parent meta consumes the child meta's synthesis output.
|
|
218
|
+
*
|
|
219
|
+
* @module discovery/ownershipTree
|
|
220
|
+
*/
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Build an ownership tree from an array of .meta/ directory paths.
|
|
224
|
+
*
|
|
225
|
+
* @param metaPaths - Absolute paths to .meta/ directories.
|
|
226
|
+
* @returns The ownership tree with parent/child relationships.
|
|
227
|
+
*/
|
|
228
|
+
declare function buildOwnershipTree(metaPaths: string[]): OwnershipTree;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Compute the file scope owned by a meta node.
|
|
232
|
+
*
|
|
233
|
+
* A meta owns: parent dir + all descendants, minus child .meta/ subtrees.
|
|
234
|
+
* For child subtrees, it consumes the child's .meta/meta.json as a rollup input.
|
|
235
|
+
*
|
|
236
|
+
* @module discovery/scope
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Get the scope path prefix for a meta node.
|
|
241
|
+
*
|
|
242
|
+
* This is the ownerPath — all files under this path are in scope,
|
|
243
|
+
* except subtrees owned by child metas.
|
|
244
|
+
*
|
|
245
|
+
* @param node - The meta node to compute scope for.
|
|
246
|
+
* @returns The scope path prefix.
|
|
247
|
+
*/
|
|
248
|
+
declare function getScopePrefix(node: MetaNode): string;
|
|
249
|
+
/**
|
|
250
|
+
* Get paths that should be excluded from the scope (child meta subtrees).
|
|
251
|
+
*
|
|
252
|
+
* @param node - The meta node to compute exclusions for.
|
|
253
|
+
* @returns Array of path prefixes to exclude from scope queries.
|
|
254
|
+
*/
|
|
255
|
+
declare function getScopeExclusions(node: MetaNode): string[];
|
|
256
|
+
/**
|
|
257
|
+
* Filter a list of file paths to only those in scope for a meta node.
|
|
258
|
+
*
|
|
259
|
+
* Includes files under ownerPath, excludes files under child meta ownerPaths,
|
|
260
|
+
* but includes child .meta/meta.json files as rollup inputs.
|
|
261
|
+
*
|
|
262
|
+
* @param node - The meta node.
|
|
263
|
+
* @param files - Array of file paths to filter.
|
|
264
|
+
* @returns Filtered array of in-scope file paths.
|
|
265
|
+
*/
|
|
266
|
+
declare function filterInScope(node: MetaNode, files: string[]): string[];
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Exponential moving average helper for token tracking.
|
|
270
|
+
*
|
|
271
|
+
* @module ema
|
|
272
|
+
*/
|
|
273
|
+
/**
|
|
274
|
+
* Compute exponential moving average.
|
|
275
|
+
*
|
|
276
|
+
* @param current - New observation.
|
|
277
|
+
* @param previous - Previous EMA value, or undefined for first observation.
|
|
278
|
+
* @param decay - Decay factor (0-1). Higher = more weight on new value. Default 0.3.
|
|
279
|
+
* @returns Updated EMA.
|
|
280
|
+
*/
|
|
281
|
+
declare function computeEma(current: number, previous: number | undefined, decay?: number): number;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Per-cycle context package computed by the orchestrator.
|
|
285
|
+
*
|
|
286
|
+
* Shared inputs that multiple subprocesses need are computed once
|
|
287
|
+
* and serialized into each subprocess's task prompt.
|
|
288
|
+
*
|
|
289
|
+
* @module interfaces/SynthContext
|
|
290
|
+
*/
|
|
291
|
+
/**
|
|
292
|
+
* Context package for a single synthesis cycle.
|
|
293
|
+
*
|
|
294
|
+
* The orchestrator computes this once per cycle from the meta path,
|
|
295
|
+
* ownership tree, watcher scan results, and filesystem reads.
|
|
296
|
+
*/
|
|
297
|
+
interface SynthContext {
|
|
298
|
+
/** Absolute path to the .meta directory. */
|
|
299
|
+
path: string;
|
|
300
|
+
/** All files in scope (absolute paths). */
|
|
301
|
+
scopeFiles: string[];
|
|
302
|
+
/** Files changed since _generatedAt (absolute paths). */
|
|
303
|
+
deltaFiles: string[];
|
|
304
|
+
/** Child _content outputs, keyed by relative path. */
|
|
305
|
+
childMetas: Record<string, unknown>;
|
|
306
|
+
/** _content from the last cycle, or null on first run. */
|
|
307
|
+
previousContent: string | null;
|
|
308
|
+
/** _feedback from the last cycle, or null on first run. */
|
|
309
|
+
previousFeedback: string | null;
|
|
310
|
+
/** Current _steer value, or null if unset. */
|
|
311
|
+
steer: string | null;
|
|
312
|
+
/** Archive snapshot file paths (for steer change detection, etc.). */
|
|
313
|
+
archives: string[];
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Pluggable executor interface for LLM subprocess invocation.
|
|
318
|
+
*
|
|
319
|
+
* @module interfaces/SynthExecutor
|
|
320
|
+
*/
|
|
321
|
+
/** Options for spawning a synthesis subprocess. */
|
|
322
|
+
interface SynthSpawnOptions {
|
|
323
|
+
/** Model override for this subprocess. */
|
|
324
|
+
model?: string;
|
|
325
|
+
/** Timeout in seconds. */
|
|
326
|
+
timeout?: number;
|
|
327
|
+
}
|
|
328
|
+
/** Result of a spawn call, including optional token usage. */
|
|
329
|
+
interface SynthSpawnResult {
|
|
330
|
+
/** Subprocess output text. */
|
|
331
|
+
output: string;
|
|
332
|
+
/** Token count for this call, if available from the executor. */
|
|
333
|
+
tokens?: number;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Interface for spawning synthesis subprocesses.
|
|
337
|
+
*
|
|
338
|
+
* The executor abstracts the LLM invocation mechanism. The orchestrator
|
|
339
|
+
* calls spawn() sequentially for architect, builder, and critic steps.
|
|
340
|
+
* Each call blocks until the subprocess completes and returns its result.
|
|
341
|
+
*/
|
|
342
|
+
interface SynthExecutor {
|
|
343
|
+
/**
|
|
344
|
+
* Spawn a subprocess with the given task prompt.
|
|
345
|
+
*
|
|
346
|
+
* @param task - Full task prompt for the subprocess.
|
|
347
|
+
* @param options - Optional model and timeout overrides.
|
|
348
|
+
* @returns The subprocess result with output and optional token count.
|
|
349
|
+
*/
|
|
350
|
+
spawn(task: string, options?: SynthSpawnOptions): Promise<SynthSpawnResult>;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Abstraction over the jeeves-watcher HTTP API.
|
|
355
|
+
*
|
|
356
|
+
* The orchestrator uses this for structured queries (POST /scan)
|
|
357
|
+
* and virtual rule registration. Subprocesses use watcher_search
|
|
358
|
+
* directly via tools.
|
|
359
|
+
*
|
|
360
|
+
* @module interfaces/WatcherClient
|
|
361
|
+
*/
|
|
362
|
+
/** A file returned from a scan query. */
|
|
363
|
+
interface ScanFile {
|
|
364
|
+
/** Absolute file path. */
|
|
365
|
+
file_path: string;
|
|
366
|
+
/** Last modified time as Unix seconds. */
|
|
367
|
+
modified_at: number;
|
|
368
|
+
/** SHA-256 hash of file content. */
|
|
369
|
+
content_hash: string;
|
|
370
|
+
/** Additional payload fields requested via `fields`. */
|
|
371
|
+
[key: string]: unknown;
|
|
372
|
+
}
|
|
373
|
+
/** Parameters for a scan request. */
|
|
374
|
+
interface ScanParams {
|
|
375
|
+
/** Required file path prefix to match. */
|
|
376
|
+
pathPrefix: string;
|
|
377
|
+
/** Filter files modified after this Unix timestamp (seconds). */
|
|
378
|
+
modifiedAfter?: number;
|
|
379
|
+
/** Which payload fields to return (default: all). */
|
|
380
|
+
fields?: string[];
|
|
381
|
+
/** Maximum results per page. */
|
|
382
|
+
limit?: number;
|
|
383
|
+
/** Pagination cursor from previous response. */
|
|
384
|
+
cursor?: string;
|
|
385
|
+
}
|
|
386
|
+
/** Response from a scan request. */
|
|
387
|
+
interface ScanResponse {
|
|
388
|
+
/** Deduplicated file results (one per file). */
|
|
389
|
+
files: ScanFile[];
|
|
390
|
+
/** Pagination cursor. Absent when no more results. */
|
|
391
|
+
next?: string;
|
|
392
|
+
}
|
|
393
|
+
/** An inference rule to register with the watcher. */
|
|
394
|
+
interface InferenceRuleSpec {
|
|
395
|
+
/** Rule name. */
|
|
396
|
+
name: string;
|
|
397
|
+
/** Rule description. */
|
|
398
|
+
description: string;
|
|
399
|
+
/** JSON Schema match criteria. */
|
|
400
|
+
match: Record<string, unknown>;
|
|
401
|
+
/** Schema array with set keywords. */
|
|
402
|
+
schema: unknown[];
|
|
403
|
+
/** Declarative render config. */
|
|
404
|
+
render?: Record<string, unknown>;
|
|
405
|
+
/** Handlebars template name. */
|
|
406
|
+
template?: string;
|
|
407
|
+
/** Render output format. */
|
|
408
|
+
renderAs?: string;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Interface for watcher HTTP operations.
|
|
412
|
+
*
|
|
413
|
+
* Implementations handle retry with backoff internally.
|
|
414
|
+
*/
|
|
415
|
+
interface WatcherClient {
|
|
416
|
+
/**
|
|
417
|
+
* Query indexed files by path prefix and optional filters.
|
|
418
|
+
* Qdrant has no native prefix match; the watcher handles this internally.
|
|
419
|
+
*/
|
|
420
|
+
scan(params: ScanParams): Promise<ScanResponse>;
|
|
421
|
+
/**
|
|
422
|
+
* Register virtual inference rules with the watcher.
|
|
423
|
+
*
|
|
424
|
+
* @param source - Source identifier (e.g. 'jeeves-meta').
|
|
425
|
+
* @param rules - Array of inference rules to register.
|
|
426
|
+
*/
|
|
427
|
+
registerRules(source: string, rules: InferenceRuleSpec[]): Promise<void>;
|
|
428
|
+
/**
|
|
429
|
+
* Unregister virtual inference rules by source.
|
|
430
|
+
*
|
|
431
|
+
* @param source - Source identifier to unregister.
|
|
432
|
+
*/
|
|
433
|
+
unregisterRules(source: string): Promise<void>;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Build task prompts for each synthesis step.
|
|
438
|
+
*
|
|
439
|
+
* @module orchestrator/buildTask
|
|
440
|
+
*/
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Build the architect task prompt.
|
|
444
|
+
*
|
|
445
|
+
* @param ctx - Synthesis context.
|
|
446
|
+
* @param meta - Current meta.json.
|
|
447
|
+
* @param config - Synthesis config.
|
|
448
|
+
* @returns The architect task prompt string.
|
|
449
|
+
*/
|
|
450
|
+
declare function buildArchitectTask(ctx: SynthContext, meta: MetaJson, config: SynthConfig): string;
|
|
451
|
+
/**
|
|
452
|
+
* Build the builder task prompt.
|
|
453
|
+
*
|
|
454
|
+
* @param ctx - Synthesis context.
|
|
455
|
+
* @param meta - Current meta.json.
|
|
456
|
+
* @param config - Synthesis config.
|
|
457
|
+
* @returns The builder task prompt string.
|
|
458
|
+
*/
|
|
459
|
+
declare function buildBuilderTask(ctx: SynthContext, meta: MetaJson, config: SynthConfig): string;
|
|
460
|
+
/**
|
|
461
|
+
* Build the critic task prompt.
|
|
462
|
+
*
|
|
463
|
+
* @param ctx - Synthesis context.
|
|
464
|
+
* @param meta - Current meta.json (with _content already set by builder).
|
|
465
|
+
* @param config - Synthesis config.
|
|
466
|
+
* @returns The critic task prompt string.
|
|
467
|
+
*/
|
|
468
|
+
declare function buildCriticTask(ctx: SynthContext, meta: MetaJson, config: SynthConfig): string;
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Build the SynthContext for a synthesis cycle.
|
|
472
|
+
*
|
|
473
|
+
* Computes shared inputs once: scope files, delta files, child meta outputs,
|
|
474
|
+
* previous content/feedback, steer, and archive paths.
|
|
475
|
+
*
|
|
476
|
+
* @module orchestrator/contextPackage
|
|
477
|
+
*/
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Build the context package for a synthesis cycle.
|
|
481
|
+
*
|
|
482
|
+
* @param node - The meta node being synthesized.
|
|
483
|
+
* @param meta - Current meta.json content.
|
|
484
|
+
* @param watcher - WatcherClient for scope enumeration.
|
|
485
|
+
* @returns The computed context package.
|
|
486
|
+
*/
|
|
487
|
+
declare function buildContextPackage(node: MetaNode, meta: MetaJson, watcher: WatcherClient): Promise<SynthContext>;
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Parse subprocess outputs for each synthesis step.
|
|
491
|
+
*
|
|
492
|
+
* - Architect: returns text \> _builder
|
|
493
|
+
* - Builder: returns JSON \> _content + structured fields
|
|
494
|
+
* - Critic: returns text \> _feedback
|
|
495
|
+
*
|
|
496
|
+
* @module orchestrator/parseOutput
|
|
497
|
+
*/
|
|
498
|
+
/** Parsed builder output. */
|
|
499
|
+
interface BuilderOutput {
|
|
500
|
+
/** Narrative synthesis content. */
|
|
501
|
+
content: string;
|
|
502
|
+
/** Additional structured fields (non-underscore keys). */
|
|
503
|
+
fields: Record<string, unknown>;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Parse architect output. The architect returns a task brief as text.
|
|
507
|
+
*
|
|
508
|
+
* @param output - Raw subprocess output.
|
|
509
|
+
* @returns The task brief string.
|
|
510
|
+
*/
|
|
511
|
+
declare function parseArchitectOutput(output: string): string;
|
|
512
|
+
/**
|
|
513
|
+
* Parse builder output. The builder returns JSON with _content and optional fields.
|
|
514
|
+
*
|
|
515
|
+
* Attempts JSON parse first. If that fails, treats the entire output as _content.
|
|
516
|
+
*
|
|
517
|
+
* @param output - Raw subprocess output.
|
|
518
|
+
* @returns Parsed builder output with content and structured fields.
|
|
519
|
+
*/
|
|
520
|
+
declare function parseBuilderOutput(output: string): BuilderOutput;
|
|
521
|
+
/**
|
|
522
|
+
* Parse critic output. The critic returns evaluation text.
|
|
523
|
+
*
|
|
524
|
+
* @param output - Raw subprocess output.
|
|
525
|
+
* @returns The feedback string.
|
|
526
|
+
*/
|
|
527
|
+
declare function parseCriticOutput(output: string): string;
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Merge synthesis results into meta.json.
|
|
531
|
+
*
|
|
532
|
+
* Preserves human-set fields (_id, _steer, _depth).
|
|
533
|
+
* Writes engine fields (_generatedAt, _structureHash, etc.).
|
|
534
|
+
* Validates against schema before writing.
|
|
535
|
+
*
|
|
536
|
+
* @module orchestrator/merge
|
|
537
|
+
*/
|
|
538
|
+
|
|
539
|
+
/** Options for merging synthesis results. */
|
|
540
|
+
interface MergeOptions {
|
|
541
|
+
/** Path to .meta directory. */
|
|
542
|
+
metaPath: string;
|
|
543
|
+
/** Current meta.json content. */
|
|
544
|
+
current: MetaJson;
|
|
545
|
+
/** Architect prompt used (or existing). */
|
|
546
|
+
architect: string;
|
|
547
|
+
/** Builder task brief (new or cached). */
|
|
548
|
+
builder: string;
|
|
549
|
+
/** Critic prompt used (or existing). */
|
|
550
|
+
critic: string;
|
|
551
|
+
/** Builder output (content + structured fields), or null if builder failed. */
|
|
552
|
+
builderOutput: BuilderOutput | null;
|
|
553
|
+
/** Critic feedback, or null if critic failed. */
|
|
554
|
+
feedback: string | null;
|
|
555
|
+
/** New structure hash. */
|
|
556
|
+
structureHash: string;
|
|
557
|
+
/** New synthesis count. */
|
|
558
|
+
synthesisCount: number;
|
|
559
|
+
/** Error from any step, or null on full success. */
|
|
560
|
+
error: SynthError | null;
|
|
561
|
+
/** Token count from architect step. */
|
|
562
|
+
architectTokens?: number;
|
|
563
|
+
/** Token count from builder step. */
|
|
564
|
+
builderTokens?: number;
|
|
565
|
+
/** Token count from critic step. */
|
|
566
|
+
criticTokens?: number;
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Merge results into meta.json and write atomically.
|
|
570
|
+
*
|
|
571
|
+
* @param options - Merge options.
|
|
572
|
+
* @returns The updated MetaJson.
|
|
573
|
+
* @throws If validation fails (malformed output).
|
|
574
|
+
*/
|
|
575
|
+
declare function mergeAndWrite(options: MergeOptions): MetaJson;
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Main orchestration function — the 13-step synthesis cycle.
|
|
579
|
+
*
|
|
580
|
+
* Wires together discovery, scheduling, archiving, executor calls,
|
|
581
|
+
* and merge/write-back.
|
|
582
|
+
*
|
|
583
|
+
* @module orchestrator/orchestrate
|
|
584
|
+
*/
|
|
585
|
+
|
|
586
|
+
/** Result of a single orchestration cycle. */
|
|
587
|
+
interface OrchestrateResult {
|
|
588
|
+
/** Whether a synthesis was performed. */
|
|
589
|
+
synthesized: boolean;
|
|
590
|
+
/** Path to the meta that was synthesized, if any. */
|
|
591
|
+
metaPath?: string;
|
|
592
|
+
/** Error if synthesis failed. */
|
|
593
|
+
error?: SynthError;
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Run synthesis cycles up to batchSize.
|
|
597
|
+
*
|
|
598
|
+
* Calls orchestrateOnce() in a loop, stopping when batchSize is reached
|
|
599
|
+
* or no more candidates are available.
|
|
600
|
+
*
|
|
601
|
+
* @param config - Validated synthesis config.
|
|
602
|
+
* @param executor - Pluggable LLM executor.
|
|
603
|
+
* @param watcher - Watcher HTTP client.
|
|
604
|
+
* @returns Array of results, one per cycle attempted.
|
|
605
|
+
*/
|
|
606
|
+
declare function orchestrate(config: SynthConfig, executor: SynthExecutor, watcher: WatcherClient): Promise<OrchestrateResult[]>;
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Factory for creating a bound synthesis engine.
|
|
610
|
+
*
|
|
611
|
+
* @module engine
|
|
612
|
+
*/
|
|
613
|
+
|
|
614
|
+
/** A bound synthesis engine instance. */
|
|
615
|
+
interface SynthEngine {
|
|
616
|
+
/** Run synthesis cycles up to batchSize. */
|
|
617
|
+
synthesize(): Promise<OrchestrateResult[]>;
|
|
618
|
+
/** Run synthesis targeting a specific path. */
|
|
619
|
+
synthesizePath(ownerPath: string): Promise<OrchestrateResult[]>;
|
|
620
|
+
/** The bound config. */
|
|
621
|
+
readonly config: SynthConfig;
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Create a synthesis engine with bound config, executor, and watcher client.
|
|
625
|
+
*
|
|
626
|
+
* @param config - Validated synthesis config.
|
|
627
|
+
* @param executor - Pluggable LLM executor.
|
|
628
|
+
* @param watcher - Watcher HTTP client.
|
|
629
|
+
* @returns A bound engine instance.
|
|
630
|
+
*/
|
|
631
|
+
declare function createSynthEngine(config: SynthConfig, executor: SynthExecutor, watcher: WatcherClient): SynthEngine;
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Shared error utilities.
|
|
635
|
+
*
|
|
636
|
+
* @module errors
|
|
637
|
+
*/
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Wrap an unknown caught value into a SynthError.
|
|
641
|
+
*
|
|
642
|
+
* @param step - Which synthesis step failed.
|
|
643
|
+
* @param err - The caught error value.
|
|
644
|
+
* @param code - Error classification code.
|
|
645
|
+
* @returns A structured SynthError.
|
|
646
|
+
*/
|
|
647
|
+
declare function toSynthError(step: SynthError['step'], err: unknown, code?: string): SynthError;
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* File-system lock for preventing concurrent synthesis on the same meta.
|
|
651
|
+
*
|
|
652
|
+
* Lock file: .meta/.lock containing PID + timestamp.
|
|
653
|
+
* Stale timeout: 30 minutes.
|
|
654
|
+
*
|
|
655
|
+
* @module lock
|
|
656
|
+
*/
|
|
657
|
+
/**
|
|
658
|
+
* Attempt to acquire a lock on a .meta directory.
|
|
659
|
+
*
|
|
660
|
+
* @param metaPath - Absolute path to the .meta directory.
|
|
661
|
+
* @returns True if lock was acquired, false if already locked (non-stale).
|
|
662
|
+
*/
|
|
663
|
+
declare function acquireLock(metaPath: string): boolean;
|
|
664
|
+
/**
|
|
665
|
+
* Release a lock on a .meta directory.
|
|
666
|
+
*
|
|
667
|
+
* @param metaPath - Absolute path to the .meta directory.
|
|
668
|
+
*/
|
|
669
|
+
declare function releaseLock(metaPath: string): void;
|
|
670
|
+
/**
|
|
671
|
+
* Check if a .meta directory is currently locked (non-stale).
|
|
672
|
+
*
|
|
673
|
+
* @param metaPath - Absolute path to the .meta directory.
|
|
674
|
+
* @returns True if locked and not stale.
|
|
675
|
+
*/
|
|
676
|
+
declare function isLocked(metaPath: string): boolean;
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Paginated scan helper for exhaustive scope enumeration.
|
|
680
|
+
*
|
|
681
|
+
* @module paginatedScan
|
|
682
|
+
*/
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Perform a paginated scan that follows cursor tokens until exhausted.
|
|
686
|
+
*
|
|
687
|
+
* @param watcher - WatcherClient instance.
|
|
688
|
+
* @param params - Base scan parameters (cursor is managed internally).
|
|
689
|
+
* @returns All matching files across all pages.
|
|
690
|
+
*/
|
|
691
|
+
declare function paginatedScan(watcher: WatcherClient, params: Omit<ScanParams, 'cursor'>): Promise<ScanFile[]>;
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Weighted staleness formula for candidate selection.
|
|
695
|
+
*
|
|
696
|
+
* effectiveStaleness = actualStaleness * (normalizedDepth + 1) ^ (depthWeight * emphasis)
|
|
697
|
+
*
|
|
698
|
+
* @module scheduling/weightedFormula
|
|
699
|
+
*/
|
|
700
|
+
|
|
701
|
+
/** A candidate meta with computed staleness. */
|
|
702
|
+
interface StalenessCandidate {
|
|
703
|
+
/** The meta node. */
|
|
704
|
+
node: MetaNode;
|
|
705
|
+
/** Current meta.json content. */
|
|
706
|
+
meta: MetaJson;
|
|
707
|
+
/** Actual staleness in seconds. */
|
|
708
|
+
actualStaleness: number;
|
|
709
|
+
/** Effective staleness after depth weighting. */
|
|
710
|
+
effectiveStaleness: number;
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Compute effective staleness for a set of candidates.
|
|
714
|
+
*
|
|
715
|
+
* Normalizes depths so the minimum becomes 0, then applies the formula:
|
|
716
|
+
* effectiveStaleness = actualStaleness * (normalizedDepth + 1) ^ (depthWeight * emphasis)
|
|
717
|
+
*
|
|
718
|
+
* Per-meta _emphasis (default 1) multiplies depthWeight, allowing individual
|
|
719
|
+
* metas to tune how much their tree position affects scheduling.
|
|
720
|
+
*
|
|
721
|
+
* @param candidates - Array of \{ node, meta, actualStaleness \}.
|
|
722
|
+
* @param depthWeight - Exponent for depth weighting (0 = pure staleness).
|
|
723
|
+
* @returns Same array with effectiveStaleness computed.
|
|
724
|
+
*/
|
|
725
|
+
declare function computeEffectiveStaleness(candidates: Array<{
|
|
726
|
+
node: MetaNode;
|
|
727
|
+
meta: MetaJson;
|
|
728
|
+
actualStaleness: number;
|
|
729
|
+
}>, depthWeight: number): StalenessCandidate[];
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Select the best synthesis candidate from stale metas.
|
|
733
|
+
*
|
|
734
|
+
* Picks the meta with highest effective staleness.
|
|
735
|
+
*
|
|
736
|
+
* @module scheduling/selectCandidate
|
|
737
|
+
*/
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Select the candidate with the highest effective staleness.
|
|
741
|
+
*
|
|
742
|
+
* @param candidates - Array of candidates with computed effective staleness.
|
|
743
|
+
* @returns The winning candidate, or null if no candidates.
|
|
744
|
+
*/
|
|
745
|
+
declare function selectCandidate(candidates: StalenessCandidate[]): StalenessCandidate | null;
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Staleness detection via watcher scan.
|
|
749
|
+
*
|
|
750
|
+
* A meta is stale when any file in its scope was modified after _generatedAt.
|
|
751
|
+
*
|
|
752
|
+
* @module scheduling/staleness
|
|
753
|
+
*/
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* Check if a meta is stale by querying the watcher for modified files.
|
|
757
|
+
*
|
|
758
|
+
* @param scopePrefix - Path prefix for this meta's scope.
|
|
759
|
+
* @param meta - Current meta.json content.
|
|
760
|
+
* @param watcher - WatcherClient instance.
|
|
761
|
+
* @returns True if any file in scope was modified after _generatedAt.
|
|
762
|
+
*/
|
|
763
|
+
declare function isStale(scopePrefix: string, meta: MetaJson, watcher: WatcherClient): Promise<boolean>;
|
|
764
|
+
/**
|
|
765
|
+
* Compute actual staleness in seconds (now minus _generatedAt).
|
|
766
|
+
*
|
|
767
|
+
* @param meta - Current meta.json content.
|
|
768
|
+
* @returns Staleness in seconds, or Infinity if never synthesized.
|
|
769
|
+
*/
|
|
770
|
+
declare function actualStaleness(meta: MetaJson): number;
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Compute a structure hash from a sorted file listing.
|
|
774
|
+
*
|
|
775
|
+
* Used to detect when directory structure changes, triggering
|
|
776
|
+
* an architect re-run.
|
|
777
|
+
*
|
|
778
|
+
* @module structureHash
|
|
779
|
+
*/
|
|
780
|
+
/**
|
|
781
|
+
* Compute a SHA-256 hash of a sorted file listing.
|
|
782
|
+
*
|
|
783
|
+
* @param filePaths - Array of file paths in scope.
|
|
784
|
+
* @returns Hex-encoded SHA-256 hash of the sorted, newline-joined paths.
|
|
785
|
+
*/
|
|
786
|
+
declare function computeStructureHash(filePaths: string[]): string;
|
|
787
|
+
|
|
788
|
+
/**
|
|
789
|
+
* HTTP implementation of the WatcherClient interface.
|
|
790
|
+
*
|
|
791
|
+
* Talks to jeeves-watcher's POST /scan and POST /rules endpoints
|
|
792
|
+
* with retry and exponential backoff.
|
|
793
|
+
*
|
|
794
|
+
* @module watcher-client/HttpWatcherClient
|
|
795
|
+
*/
|
|
796
|
+
|
|
797
|
+
/** Options for creating an HttpWatcherClient. */
|
|
798
|
+
interface HttpWatcherClientOptions {
|
|
799
|
+
/** Base URL for the watcher service (e.g. "http://localhost:1936"). */
|
|
800
|
+
baseUrl: string;
|
|
801
|
+
/** Maximum retry attempts for transient failures. Default: 3. */
|
|
802
|
+
maxRetries?: number;
|
|
803
|
+
/** Base delay in ms for exponential backoff. Default: 1000. */
|
|
804
|
+
backoffBaseMs?: number;
|
|
805
|
+
/** Multiplier for backoff. Default: 4 (1s, 4s, 16s). */
|
|
806
|
+
backoffFactor?: number;
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* HTTP-based WatcherClient implementation with retry.
|
|
810
|
+
*/
|
|
811
|
+
declare class HttpWatcherClient implements WatcherClient {
|
|
812
|
+
private readonly baseUrl;
|
|
813
|
+
private readonly maxRetries;
|
|
814
|
+
private readonly backoffBaseMs;
|
|
815
|
+
private readonly backoffFactor;
|
|
816
|
+
constructor(options: HttpWatcherClientOptions);
|
|
817
|
+
/** POST JSON with retry. */
|
|
818
|
+
private post;
|
|
819
|
+
scan(params: ScanParams): Promise<ScanResponse>;
|
|
820
|
+
registerRules(source: string, rules: InferenceRuleSpec[]): Promise<void>;
|
|
821
|
+
unregisterRules(source: string): Promise<void>;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
export { HttpWatcherClient, acquireLock, actualStaleness, buildArchitectTask, buildBuilderTask, buildContextPackage, buildCriticTask, buildOwnershipTree, computeEffectiveStaleness, computeEma, computeStructureHash, createSnapshot, createSynthEngine, ensureMetaJson, filterInScope, getScopeExclusions, getScopePrefix, globMetas, isLocked, isStale, listArchiveFiles, mergeAndWrite, metaJsonSchema, orchestrate, paginatedScan, parseArchitectOutput, parseBuilderOutput, parseCriticOutput, pruneArchive, readLatestArchive, releaseLock, selectCandidate, synthConfigSchema, synthErrorSchema, toSynthError };
|
|
825
|
+
export type { BuilderOutput, HttpWatcherClientOptions, InferenceRuleSpec, MergeOptions, MetaJson, MetaNode, OrchestrateResult, OwnershipTree, ScanFile, ScanParams, ScanResponse, StalenessCandidate, SynthConfig, SynthContext, SynthEngine, SynthError, SynthExecutor, SynthSpawnOptions, SynthSpawnResult, WatcherClient };
|