wiki-graph 0.5.0 → 0.6.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/dist/index.js CHANGED
@@ -12,6 +12,578 @@ var __export = (target, all) => {
12
12
  __defProp(target, name, { get: all[name], enumerable: true });
13
13
  };
14
14
 
15
+ // ../core/src/runtime/platform/files.ts
16
+ var init_files = __esm({
17
+ "../core/src/runtime/platform/files.ts"() {
18
+ "use strict";
19
+ }
20
+ });
21
+
22
+ // ../core/src/runtime/platform/index.ts
23
+ async function withWikiGraphStorage(storage, operation) {
24
+ if (storage === void 0) {
25
+ return await operation();
26
+ }
27
+ return await storageContext.run(storage, operation);
28
+ }
29
+ var installedPlatform, DeferredHostAsyncContext, storageContext;
30
+ var init_platform = __esm({
31
+ "../core/src/runtime/platform/index.ts"() {
32
+ "use strict";
33
+ init_files();
34
+ DeferredHostAsyncContext = class {
35
+ #impl;
36
+ #fallbackStore;
37
+ run(store, callback) {
38
+ const implementation = this.#implementation();
39
+ if (implementation !== void 0) {
40
+ return implementation.run(store, callback);
41
+ }
42
+ const previous = this.#fallbackStore;
43
+ this.#fallbackStore = store;
44
+ try {
45
+ return callback();
46
+ } finally {
47
+ this.#fallbackStore = previous;
48
+ }
49
+ }
50
+ enterWith(store) {
51
+ const implementation = this.#implementation();
52
+ if (implementation !== void 0) {
53
+ implementation.enterWith(store);
54
+ } else {
55
+ this.#fallbackStore = store;
56
+ }
57
+ }
58
+ getStore() {
59
+ return this.#implementation()?.getStore() ?? this.#fallbackStore;
60
+ }
61
+ #implementation() {
62
+ if (this.#impl !== void 0) {
63
+ return this.#impl;
64
+ }
65
+ if (installedPlatform === void 0) {
66
+ return void 0;
67
+ }
68
+ this.#impl = installedPlatform.asyncContext.create();
69
+ if (this.#fallbackStore !== void 0) {
70
+ this.#impl.enterWith(this.#fallbackStore);
71
+ this.#fallbackStore = void 0;
72
+ }
73
+ return this.#impl;
74
+ }
75
+ };
76
+ storageContext = new DeferredHostAsyncContext();
77
+ }
78
+ });
79
+
80
+ // ../core/src/runtime/common/template.ts
81
+ function normalizeTemplateName(templateName) {
82
+ if (LEADING_DOT_SEGMENT_PATTERN.test(templateName)) {
83
+ throw new Error(`invalid template name ${templateName}`);
84
+ }
85
+ const withoutLeadingSlash = templateName.replace(LEADING_SLASH_PATTERN, "");
86
+ const withoutExtension = withoutLeadingSlash.replace(
87
+ JINJA_EXTENSION_PATTERN,
88
+ ""
89
+ );
90
+ if (withoutExtension.split("/").includes("..")) {
91
+ throw new Error(`invalid template name ${templateName}`);
92
+ }
93
+ return `${withoutExtension}.jinja`;
94
+ }
95
+ var JINJA_EXTENSION_PATTERN, LEADING_DOT_SEGMENT_PATTERN, LEADING_SLASH_PATTERN;
96
+ var init_template = __esm({
97
+ "../core/src/runtime/common/template.ts"() {
98
+ "use strict";
99
+ init_platform();
100
+ JINJA_EXTENSION_PATTERN = /\.jinja$/iu;
101
+ LEADING_DOT_SEGMENT_PATTERN = /^\.+\//u;
102
+ LEADING_SLASH_PATTERN = /^\/+/u;
103
+ }
104
+ });
105
+
106
+ // src/runtime/node-platform.ts
107
+ import * as asyncHooks from "async_hooks";
108
+ import * as crypto from "crypto";
109
+ import * as fs from "fs";
110
+ import * as fsPromises from "fs/promises";
111
+ import * as os from "os";
112
+ import * as pathModule from "path";
113
+ import * as process2 from "process";
114
+ import { Writable } from "stream";
115
+ import { pipeline } from "stream/promises";
116
+ import * as sqlite3 from "sqlite3";
117
+ import * as yauzl from "yauzl";
118
+ import * as yazl from "yazl";
119
+ import { Environment, Loader } from "nunjucks";
120
+ function encodeNodeResourceIdentity(kind, path) {
121
+ return `node-${kind}:${Buffer.from(pathModule.resolve(path), "utf8").toString("base64url")}`;
122
+ }
123
+ function decodeNodeResourceIdentity(identity, kind) {
124
+ const prefix = `node-${kind}:`;
125
+ if (!identity.startsWith(prefix)) {
126
+ return pathModule.isAbsolute(identity) ? identity : void 0;
127
+ }
128
+ try {
129
+ return Buffer.from(identity.slice(prefix.length), "base64url").toString(
130
+ "utf8"
131
+ );
132
+ } catch {
133
+ return void 0;
134
+ }
135
+ }
136
+ function getNodeResourcePath(resource) {
137
+ if (resource instanceof NodeFile || resource instanceof NodeDirectory) {
138
+ return resource.path;
139
+ }
140
+ if (typeof resource === "object" && resource !== null && "path" in resource && typeof resource.path === "string") {
141
+ return resource.path;
142
+ }
143
+ throw new TypeError("Expected a Node File or Directory resource");
144
+ }
145
+ function assertChildName(name) {
146
+ if (name.length === 0 || name === "." || name === ".." || pathModule.isAbsolute(name) || name.includes("/") || name.includes("\\")) {
147
+ throw new TypeError(`Directory child must be a relative name: ${name}`);
148
+ }
149
+ }
150
+ async function openNodeDatabase(file, options = {}) {
151
+ const flags = (options.readonly === true ? nodeSqlite3.OPEN_READONLY : nodeSqlite3.OPEN_READWRITE | nodeSqlite3.OPEN_CREATE) | nodeSqlite3.OPEN_FULLMUTEX;
152
+ return new NodeDatabaseConnection(await openNativeNodeDatabase(file, flags));
153
+ }
154
+ async function openNativeNodeDatabase(file, flags) {
155
+ if (!(file instanceof NodeFile)) {
156
+ throw new TypeError("The Node database adapter requires a NodeFile");
157
+ }
158
+ return await new Promise((resolve9, reject) => {
159
+ const database = new nodeSqlite3.Database(file.path, flags, (error) => {
160
+ if (error) reject(error);
161
+ else resolve9(database);
162
+ });
163
+ });
164
+ }
165
+ async function openNodeZip(file) {
166
+ if (!(file instanceof NodeFile)) {
167
+ throw new TypeError("The Node ZIP adapter requires a NodeFile");
168
+ }
169
+ const zipFile = await new Promise((resolve9, reject) => {
170
+ yauzl.open(
171
+ file.path,
172
+ { autoClose: false, lazyEntries: true },
173
+ (error, opened) => {
174
+ if (error || opened === void 0)
175
+ reject(error ?? new Error("Cannot open ZIP"));
176
+ else resolve9(opened);
177
+ }
178
+ );
179
+ });
180
+ const entries = await new Promise(
181
+ (resolve9, reject) => {
182
+ const discovered = /* @__PURE__ */ new Map();
183
+ const rejectAndClose = (error) => {
184
+ zipFile.close();
185
+ reject(
186
+ error instanceof Error ? error : new Error("Cannot scan ZIP central directory")
187
+ );
188
+ };
189
+ const resolveEntries = () => {
190
+ zipFile.off("error", rejectAndClose);
191
+ resolve9(discovered);
192
+ };
193
+ zipFile.on("entry", (entry) => {
194
+ if (!entry.fileName.endsWith("/")) {
195
+ discovered.set(entry.fileName, entry);
196
+ }
197
+ zipFile.readEntry();
198
+ });
199
+ zipFile.once("error", rejectAndClose);
200
+ zipFile.once("end", resolveEntries);
201
+ zipFile.readEntry();
202
+ }
203
+ );
204
+ let closed = false;
205
+ return {
206
+ close: () => {
207
+ if (!closed) zipFile.close();
208
+ closed = true;
209
+ return Promise.resolve();
210
+ },
211
+ listEntries: () => Promise.resolve([...entries.keys()]),
212
+ readEntry: async (name) => {
213
+ if (closed) throw new Error("Cannot read a closed ZIP archive");
214
+ const entry = entries.get(name);
215
+ if (entry === void 0) return void 0;
216
+ return await readNodeZipEntry(zipFile, entry);
217
+ }
218
+ };
219
+ }
220
+ async function readNodeZipEntry(zipFile, entry) {
221
+ const stream = await new Promise((resolve9, reject) => {
222
+ zipFile.openReadStream(entry, (error, opened) => {
223
+ if (error || opened === void 0) {
224
+ reject(error ?? new Error(`Cannot read ZIP entry: ${entry.fileName}`));
225
+ } else {
226
+ resolve9(opened);
227
+ }
228
+ });
229
+ });
230
+ return await collectNodeStream(stream);
231
+ }
232
+ async function writeNodeZip(file, entries) {
233
+ const zipFile = new yazl.ZipFile();
234
+ const writer = await file.openWriter();
235
+ const outputStream = zipFile.outputStream;
236
+ const outputDone = writeNodeStream(outputStream, writer);
237
+ const entryState = { cancelled: false, complete: false };
238
+ let iterator;
239
+ try {
240
+ iterator = getNodeZipEntryIterator(entries);
241
+ const entriesDone = addNodeZipEntries(zipFile, iterator, entryState);
242
+ await Promise.race([entriesDone, outputDone]);
243
+ if (!entryState.complete) {
244
+ throw new Error("ZIP output ended before entry production completed");
245
+ }
246
+ zipFile.end();
247
+ await outputDone;
248
+ await writer.commit();
249
+ } catch (error) {
250
+ entryState.cancelled = true;
251
+ if (!entryState.complete && iterator !== void 0) {
252
+ closeNodeZipEntryIterator(iterator);
253
+ }
254
+ if (!outputStream.destroyed) {
255
+ outputStream.destroy(
256
+ error instanceof Error ? error : new Error("Cannot write ZIP archive")
257
+ );
258
+ }
259
+ await outputDone.catch(() => void 0);
260
+ await writer.abort().catch(() => void 0);
261
+ throw error;
262
+ }
263
+ }
264
+ async function addNodeZipEntries(zipFile, iterator, state) {
265
+ while (!state.cancelled) {
266
+ const result = await iterator.next();
267
+ if (state.cancelled) return;
268
+ if (result.done) {
269
+ state.complete = true;
270
+ return;
271
+ }
272
+ zipFile.addBuffer(Buffer.from(result.value.data), result.value.name, {
273
+ compress: false
274
+ });
275
+ }
276
+ }
277
+ function getNodeZipEntryIterator(entries) {
278
+ const asyncIterator = entries[Symbol.asyncIterator];
279
+ return asyncIterator === void 0 ? entries[Symbol.iterator]() : asyncIterator.call(entries);
280
+ }
281
+ function closeNodeZipEntryIterator(iterator) {
282
+ if (iterator.return === void 0) return;
283
+ try {
284
+ void Promise.resolve(iterator.return()).catch(() => void 0);
285
+ } catch {
286
+ }
287
+ }
288
+ async function writeNodeStream(input, writer) {
289
+ await pipeline(
290
+ input,
291
+ new Writable({
292
+ write: (chunk, _encoding, callback) => {
293
+ void writer.write(chunk).then(
294
+ () => callback(),
295
+ (error) => callback(
296
+ error instanceof Error ? error : new Error("Cannot stream ZIP archive")
297
+ )
298
+ );
299
+ }
300
+ })
301
+ );
302
+ }
303
+ async function collectNodeStream(input) {
304
+ return await new Promise((resolve9, reject) => {
305
+ const chunks = [];
306
+ input.on("data", (chunk) => chunks.push(chunk));
307
+ input.once("error", reject);
308
+ input.once("end", () => resolve9(Buffer.concat(chunks)));
309
+ });
310
+ }
311
+ function resolveNodeDataDirectory() {
312
+ const injected = globalThis.__WIKIGRAPH_DATA_DIR__;
313
+ if (typeof injected === "string" && injected !== "") return injected;
314
+ let directory = nodeProcess.cwd();
315
+ while (true) {
316
+ for (const candidate of [
317
+ pathModule.join(directory, "data"),
318
+ pathModule.join(directory, "packages", "core", "data")
319
+ ]) {
320
+ try {
321
+ if (fs.statSync(candidate).isDirectory()) return candidate;
322
+ } catch {
323
+ }
324
+ }
325
+ const parent = pathModule.dirname(directory);
326
+ if (parent === directory)
327
+ throw new Error("Could not locate data directory");
328
+ directory = parent;
329
+ }
330
+ }
331
+ function createNodeWikiGraphStorage(stateRoot = pathModule.join(os.homedir(), ".wikigraph")) {
332
+ return {
333
+ library: new NodeDirectory(stateRoot),
334
+ documentStore: new NodeDirectory(pathModule.join(stateRoot, "documents"))
335
+ };
336
+ }
337
+ async function withNodeWikiGraphStorage(stateRoot, operation) {
338
+ return await withWikiGraphStorage(
339
+ stateRoot === void 0 ? void 0 : createNodeWikiGraphStorage(stateRoot),
340
+ operation
341
+ );
342
+ }
343
+ var nodeProcess, nodeSqlite3, NodeFile, NodeDirectory, NodeDatabaseConnection, nodeWikiGraphPlatform, NodeTemplateLoader;
344
+ var init_node_platform = __esm({
345
+ "src/runtime/node-platform.ts"() {
346
+ "use strict";
347
+ init_platform();
348
+ init_template();
349
+ nodeProcess = process2.default ?? process2;
350
+ nodeSqlite3 = sqlite3.default ?? sqlite3;
351
+ NodeFile = class {
352
+ constructor(path, name = pathModule.basename(path)) {
353
+ this.path = path;
354
+ this.identity = encodeNodeResourceIdentity("file", path);
355
+ this.name = name;
356
+ }
357
+ path;
358
+ identity;
359
+ name;
360
+ async read(options) {
361
+ return await fsPromises.readFile(
362
+ this.path,
363
+ options?.encoding === void 0 ? void 0 : { encoding: options.encoding }
364
+ );
365
+ }
366
+ async getSize() {
367
+ try {
368
+ return (await fsPromises.stat(this.path)).size;
369
+ } catch (error) {
370
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
371
+ return 0;
372
+ }
373
+ throw error;
374
+ }
375
+ }
376
+ async getLastModified() {
377
+ try {
378
+ return (await fsPromises.stat(this.path)).mtimeMs;
379
+ } catch (error) {
380
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
381
+ return void 0;
382
+ }
383
+ throw error;
384
+ }
385
+ }
386
+ async openWriter() {
387
+ await fsPromises.mkdir(pathModule.dirname(this.path), { recursive: true });
388
+ const temporary = `${this.path}.tmp-${crypto.randomUUID()}`;
389
+ const handle = await fsPromises.open(temporary, "wx");
390
+ let closed = false;
391
+ return {
392
+ write: async (data) => {
393
+ if (closed) throw new Error("Cannot write to a closed FileWriter");
394
+ if (typeof data === "string") await handle.write(data);
395
+ else await handle.write(Buffer.from(data));
396
+ },
397
+ commit: async () => {
398
+ if (!closed) {
399
+ await handle.close();
400
+ await fsPromises.rename(temporary, this.path);
401
+ }
402
+ closed = true;
403
+ },
404
+ abort: async () => {
405
+ if (!closed) {
406
+ await handle.close();
407
+ await fsPromises.rm(temporary, { force: true });
408
+ }
409
+ closed = true;
410
+ }
411
+ };
412
+ }
413
+ };
414
+ NodeDirectory = class _NodeDirectory {
415
+ constructor(path) {
416
+ this.path = path;
417
+ this.identity = encodeNodeResourceIdentity("directory", path);
418
+ this.name = pathModule.basename(path);
419
+ }
420
+ path;
421
+ identity;
422
+ name;
423
+ async getFile(name) {
424
+ assertChildName(name);
425
+ const file = new NodeFile(pathModule.join(this.path, name));
426
+ try {
427
+ return (await fsPromises.stat(file.path)).isFile() ? file : void 0;
428
+ } catch {
429
+ return void 0;
430
+ }
431
+ }
432
+ async getLastModified() {
433
+ try {
434
+ return (await fsPromises.stat(this.path)).mtimeMs;
435
+ } catch (error) {
436
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
437
+ return void 0;
438
+ }
439
+ throw error;
440
+ }
441
+ }
442
+ async getDirectory(name) {
443
+ assertChildName(name);
444
+ const directory = new _NodeDirectory(pathModule.join(this.path, name));
445
+ try {
446
+ return (await fsPromises.stat(directory.path)).isDirectory() ? directory : void 0;
447
+ } catch {
448
+ return void 0;
449
+ }
450
+ }
451
+ async list() {
452
+ const entries = await fsPromises.readdir(this.path, {
453
+ withFileTypes: true
454
+ });
455
+ return entries.map(
456
+ (entry) => entry.isDirectory() ? new _NodeDirectory(pathModule.join(this.path, entry.name)) : new NodeFile(pathModule.join(this.path, entry.name), entry.name)
457
+ );
458
+ }
459
+ async createFile(name) {
460
+ assertChildName(name);
461
+ await fsPromises.mkdir(this.path, { recursive: true });
462
+ const file = new NodeFile(pathModule.join(this.path, name));
463
+ await fsPromises.writeFile(file.path, "", { flag: "wx" });
464
+ return file;
465
+ }
466
+ async createDirectory(name) {
467
+ assertChildName(name);
468
+ await fsPromises.mkdir(this.path, { recursive: true });
469
+ const directory = new _NodeDirectory(pathModule.join(this.path, name));
470
+ await fsPromises.mkdir(directory.path);
471
+ return directory;
472
+ }
473
+ async remove(name, options) {
474
+ assertChildName(name);
475
+ await fsPromises.rm(pathModule.join(this.path, name), {
476
+ force: true,
477
+ recursive: options?.recursive === true
478
+ });
479
+ }
480
+ };
481
+ NodeDatabaseConnection = class {
482
+ constructor(database) {
483
+ this.database = database;
484
+ }
485
+ database;
486
+ async close() {
487
+ await new Promise((resolve9, reject) => {
488
+ this.database.close((error) => {
489
+ if (error) reject(error);
490
+ else resolve9();
491
+ });
492
+ });
493
+ }
494
+ async execute(sql) {
495
+ await new Promise((resolve9, reject) => {
496
+ this.database.exec(sql, (error) => {
497
+ if (error) reject(error);
498
+ else resolve9();
499
+ });
500
+ });
501
+ }
502
+ async queryAll(sql, params = []) {
503
+ return await new Promise((resolve9, reject) => {
504
+ this.database.all(sql, [...params], (error, rows) => {
505
+ if (error) reject(error);
506
+ else resolve9(rows);
507
+ });
508
+ });
509
+ }
510
+ async queryOne(sql, params = []) {
511
+ return await new Promise((resolve9, reject) => {
512
+ this.database.get(sql, [...params], (error, row) => {
513
+ if (error) reject(error);
514
+ else resolve9(row);
515
+ });
516
+ });
517
+ }
518
+ async run(sql, params = []) {
519
+ await new Promise((resolve9, reject) => {
520
+ this.database.run(sql, [...params], (error) => {
521
+ if (error) reject(error);
522
+ else resolve9();
523
+ });
524
+ });
525
+ }
526
+ };
527
+ nodeWikiGraphPlatform = {
528
+ asyncContext: {
529
+ create: () => new asyncHooks.AsyncLocalStorage()
530
+ },
531
+ database: { open: openNodeDatabase },
532
+ lifecycle: {
533
+ instanceId: `node-process:${nodeProcess.pid}`,
534
+ isInstanceAlive: (instanceId) => {
535
+ const match = /^node-process:(\d+)$/u.exec(instanceId);
536
+ if (match === null) return Promise.resolve(void 0);
537
+ try {
538
+ nodeProcess.kill(Number(match[1]), 0);
539
+ return Promise.resolve(true);
540
+ } catch (error) {
541
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ESRCH") {
542
+ return Promise.resolve(false);
543
+ }
544
+ return Promise.resolve(true);
545
+ }
546
+ }
547
+ },
548
+ resources: {
549
+ getDirectory: (identity) => {
550
+ const path = decodeNodeResourceIdentity(identity, "directory");
551
+ return Promise.resolve(
552
+ path === void 0 ? void 0 : new NodeDirectory(path)
553
+ );
554
+ },
555
+ getFile: (identity) => {
556
+ const path = decodeNodeResourceIdentity(identity, "file");
557
+ return Promise.resolve(
558
+ path === void 0 ? void 0 : new NodeFile(path)
559
+ );
560
+ },
561
+ resolveLegacyDirectory: (reference) => {
562
+ const path = decodeNodeResourceIdentity(reference, "directory");
563
+ return Promise.resolve(
564
+ path === void 0 ? void 0 : new NodeDirectory(path)
565
+ );
566
+ }
567
+ },
568
+ templates: {
569
+ createEnvironment: (options) => new Environment(new NodeTemplateLoader(), options)
570
+ },
571
+ zip: { open: openNodeZip, write: writeNodeZip }
572
+ };
573
+ NodeTemplateLoader = class extends Loader {
574
+ getSource(templateName) {
575
+ const name = normalizeTemplateName(templateName);
576
+ const filePath = pathModule.join(resolveNodeDataDirectory(), name);
577
+ return {
578
+ noCache: false,
579
+ path: name,
580
+ src: fs.readFileSync(filePath, "utf8")
581
+ };
582
+ }
583
+ };
584
+ }
585
+ });
586
+
15
587
  // src/support/errors.ts
16
588
  import { CLI_PRIMARY_COMMAND } from "wiki-graph-core";
17
589
  function withHelpRoute(message, route) {
@@ -79,7 +651,7 @@ var init_formats = __esm({
79
651
  });
80
652
 
81
653
  // src/runtime/context.ts
82
- import { AsyncLocalStorage } from "async_hooks";
654
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
83
655
  async function withWikiGraphCLIRuntimeContext(context, operation) {
84
656
  return await cliRuntimeContext.run(context, operation);
85
657
  }
@@ -89,6 +661,9 @@ function getCLICwd() {
89
661
  function getCLIEnv() {
90
662
  return cliRuntimeContext.getStore()?.env ?? process.env;
91
663
  }
664
+ function getCLIEnvValue(name) {
665
+ return getCLIEnv()[name];
666
+ }
92
667
  function getCLIDevProjectRoot() {
93
668
  return cliRuntimeContext.getStore()?.devProjectRoot;
94
669
  }
@@ -126,15 +701,15 @@ var cliRuntimeContext, queueAutostartForTesting;
126
701
  var init_context = __esm({
127
702
  "src/runtime/context.ts"() {
128
703
  "use strict";
129
- cliRuntimeContext = new AsyncLocalStorage();
704
+ cliRuntimeContext = new AsyncLocalStorage2();
130
705
  }
131
706
  });
132
707
 
133
708
  // src/support/io.ts
134
709
  import { createReadStream } from "fs";
135
- import { rm } from "fs/promises";
136
- import { join } from "path";
137
- import { createWikiGraphTempDirectory } from "wiki-graph-core";
710
+ import { mkdtemp, rm as rm2 } from "fs/promises";
711
+ import { join as join2 } from "path";
712
+ import { tmpdir } from "os";
138
713
  function readTextStreamFromStdin() {
139
714
  const stdin = getCLIStdin();
140
715
  stdin.setEncoding("utf8");
@@ -149,10 +724,10 @@ async function writeTextToStdout(text) {
149
724
  await writeChunkToStdout(text);
150
725
  }
151
726
  async function writeTextToStderr(text) {
152
- await new Promise((resolve4, reject) => {
727
+ await new Promise((resolve9, reject) => {
153
728
  getCLIStderr().write(text, (error) => {
154
729
  if (error === void 0 || error === null) {
155
- resolve4();
730
+ resolve9();
156
731
  return;
157
732
  }
158
733
  reject(error);
@@ -163,15 +738,15 @@ async function writeBinaryToStdout(data) {
163
738
  await writeChunkToStdout(data);
164
739
  }
165
740
  async function writeChunkToStdout(chunk) {
166
- await new Promise((resolve4, reject) => {
741
+ await new Promise((resolve9, reject) => {
167
742
  getCLIStdout().write(chunk, (error) => {
168
743
  if (error === void 0 || error === null) {
169
- resolve4();
744
+ resolve9();
170
745
  return;
171
746
  }
172
747
  if (isBrokenPipeError(error)) {
173
748
  setCLIExitCode(0);
174
- resolve4();
749
+ resolve9();
175
750
  return;
176
751
  }
177
752
  reject(error);
@@ -183,14 +758,14 @@ function isBrokenPipeError(error) {
183
758
  }
184
759
  async function createTemporaryOutputPath(prefix, extension) {
185
760
  void prefix;
186
- const directoryPath = await createWikiGraphTempDirectory("cli-output");
761
+ const directoryPath = await mkdtemp(join2(tmpdir(), "wikigraph-cli-output-"));
187
762
  return {
188
763
  directoryPath,
189
- filePath: join(directoryPath, `output${extension}`)
764
+ filePath: join2(directoryPath, `output${extension}`)
190
765
  };
191
766
  }
192
767
  async function removeTemporaryDirectory(directoryPath) {
193
- await rm(directoryPath, { force: true, recursive: true });
768
+ await rm2(directoryPath, { force: true, recursive: true });
194
769
  }
195
770
  var init_io = __esm({
196
771
  "src/support/io.ts"() {
@@ -388,11 +963,74 @@ var init_tree = __esm({
388
963
  }
389
964
  });
390
965
 
966
+ // src/support/uri.ts
967
+ import { homedir as homedir2 } from "os";
968
+ import { isAbsolute as isAbsolute2, relative, resolve as resolve2 } from "path";
969
+ import {
970
+ formatWikiGraphCommandUri as formatPortableWikiGraphCommandUri,
971
+ parseLocatedWikiGraphUri as parsePortableLocatedWikiGraphUri
972
+ } from "wiki-graph-core";
973
+ function parseLocatedWikiGraphUri(uri) {
974
+ const parsed = parsePortableLocatedWikiGraphUri(uri);
975
+ if (parsed.archivePath === void 0 || parsed.archivePath.startsWith("wikg://lib/")) {
976
+ return parsed;
977
+ }
978
+ return {
979
+ ...parsed,
980
+ archivePath: resolveCLIArchivePath(parsed.archivePath)
981
+ };
982
+ }
983
+ function formatWikiGraphCommandUri(archivePath, objectUri, cwd = getCLICwd()) {
984
+ let locator = archivePath;
985
+ if (isAbsolute2(archivePath)) {
986
+ const candidate = relative(cwd, archivePath);
987
+ if (candidate !== "" && !candidate.startsWith("..") && !isAbsolute2(candidate)) {
988
+ locator = candidate;
989
+ }
990
+ }
991
+ return formatPortableWikiGraphCommandUri(locator, objectUri);
992
+ }
993
+ function getRelativeArchiveUriResolution(uri) {
994
+ let parsed;
995
+ try {
996
+ parsed = parsePortableLocatedWikiGraphUri(uri);
997
+ } catch {
998
+ return void 0;
999
+ }
1000
+ const locator = parsed.archivePath;
1001
+ if (locator === void 0 || locator === "~" || locator.startsWith("~/") || locator.startsWith("wikg://lib/") || isAbsolute2(locator)) {
1002
+ return void 0;
1003
+ }
1004
+ const workingDirectory = getCLICwd();
1005
+ return {
1006
+ inputUri: uri,
1007
+ resolvedArchivePath: resolve2(workingDirectory, locator),
1008
+ workingDirectory
1009
+ };
1010
+ }
1011
+ function resolveCLIArchivePath(locator) {
1012
+ if (locator === "~") return getCLIHomeDirectory();
1013
+ if (locator.startsWith("~/")) {
1014
+ return resolve2(getCLIHomeDirectory(), locator.slice(2));
1015
+ }
1016
+ return resolve2(getCLICwd(), locator);
1017
+ }
1018
+ function getCLIHomeDirectory() {
1019
+ const environmentHome = getCLIEnvValue("HOME")?.trim();
1020
+ return environmentHome === void 0 || environmentHome === "" ? homedir2() : environmentHome;
1021
+ }
1022
+ var init_uri = __esm({
1023
+ "src/support/uri.ts"() {
1024
+ "use strict";
1025
+ init_context();
1026
+ }
1027
+ });
1028
+
391
1029
  // src/support/version.ts
392
- import { existsSync, readFileSync } from "fs";
393
- import { dirname, join as join2, parse, resolve } from "path";
1030
+ import { existsSync, readFileSync as readFileSync2 } from "fs";
1031
+ import { dirname as dirname2, join as join3, parse, resolve as resolve3 } from "path";
394
1032
  function isCLIPackageJSON(path) {
395
- const parsed = JSON.parse(readFileSync(path, "utf8"));
1033
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
396
1034
  return typeof parsed === "object" && parsed !== null && "name" in parsed && parsed.name === "wiki-graph";
397
1035
  }
398
1036
  function findPackageJSONPathFromWorkingDirectory() {
@@ -400,8 +1038,8 @@ function findPackageJSONPathFromWorkingDirectory() {
400
1038
  const rootDirectoryPath = parse(currentDirectoryPath).root;
401
1039
  while (true) {
402
1040
  for (const candidatePath of [
403
- join2(currentDirectoryPath, "package.json"),
404
- join2(currentDirectoryPath, "packages", "cli", "package.json")
1041
+ join3(currentDirectoryPath, "package.json"),
1042
+ join3(currentDirectoryPath, "packages", "cli", "package.json")
405
1043
  ]) {
406
1044
  if (existsSync(candidatePath) && isCLIPackageJSON(candidatePath)) {
407
1045
  return candidatePath;
@@ -410,13 +1048,13 @@ function findPackageJSONPathFromWorkingDirectory() {
410
1048
  if (currentDirectoryPath === rootDirectoryPath) {
411
1049
  return void 0;
412
1050
  }
413
- currentDirectoryPath = dirname(currentDirectoryPath);
1051
+ currentDirectoryPath = dirname2(currentDirectoryPath);
414
1052
  }
415
1053
  }
416
1054
  function resolvePackageJSONPath() {
417
1055
  const injectedCLIDistDirectoryPath = globalThis.__WIKIGRAPH_CLI_DIST_DIR__;
418
1056
  const candidatePaths = [
419
- typeof injectedCLIDistDirectoryPath === "string" ? resolve(injectedCLIDistDirectoryPath, "../package.json") : void 0,
1057
+ typeof injectedCLIDistDirectoryPath === "string" ? resolve3(injectedCLIDistDirectoryPath, "../package.json") : void 0,
420
1058
  findPackageJSONPathFromWorkingDirectory()
421
1059
  ];
422
1060
  for (const candidatePath of candidatePaths) {
@@ -428,7 +1066,7 @@ function resolvePackageJSONPath() {
428
1066
  }
429
1067
  function readCLIVersion() {
430
1068
  const packageJSONPath = resolvePackageJSONPath();
431
- const parsed = JSON.parse(readFileSync(packageJSONPath, "utf8"));
1069
+ const parsed = JSON.parse(readFileSync2(packageJSONPath, "utf8"));
432
1070
  if (typeof parsed === "object" && parsed !== null && "version" in parsed && typeof parsed.version === "string") {
433
1071
  return parsed.version;
434
1072
  }
@@ -451,13 +1089,15 @@ var init_support = __esm({
451
1089
  init_json();
452
1090
  init_shell();
453
1091
  init_tree();
1092
+ init_uri();
454
1093
  init_version();
455
1094
  }
456
1095
  });
457
1096
 
458
1097
  // src/runtime/local-config.ts
459
- import { resolveWikiGraphCoreDatabasePath } from "wiki-graph-core";
460
1098
  import { openSharedStateDatabase } from "wiki-graph-core";
1099
+ import { join as join4 } from "path";
1100
+ import { homedir as homedir3 } from "os";
461
1101
  async function readLocalConfigSection(section) {
462
1102
  return await withLocalConfigDatabase(async (database) => {
463
1103
  return await readLocalConfigSectionInDatabase(database, section);
@@ -540,7 +1180,9 @@ function validateLocalConfigSection(section, value) {
540
1180
  }
541
1181
  async function withLocalConfigDatabase(operation) {
542
1182
  const database = await openSharedStateDatabase(
543
- resolveWikiGraphCoreDatabasePath(),
1183
+ new NodeFile(
1184
+ join4(getCLIStateDir() ?? join4(homedir3(), ".wikigraph"), "core.sqlite")
1185
+ ),
544
1186
  LOCAL_CONFIG_SCHEMA_SQL
545
1187
  );
546
1188
  try {
@@ -690,6 +1332,8 @@ var LOCAL_CONFIG_SECTIONS, LOCAL_CONFIG_SCHEMA_SQL;
690
1332
  var init_local_config = __esm({
691
1333
  "src/runtime/local-config.ts"() {
692
1334
  "use strict";
1335
+ init_context();
1336
+ init_node_platform();
693
1337
  LOCAL_CONFIG_SECTIONS = [
694
1338
  "concurrent",
695
1339
  "embeddings",
@@ -1219,12 +1863,12 @@ function planGenerationTask(task, words, chapters, concurrent, model) {
1219
1863
  };
1220
1864
  }
1221
1865
  function createGenerationPerformanceHints(input) {
1222
- if (!input.hasGenerationWork) {
1866
+ if (!input.hasJobWork) {
1223
1867
  return [];
1224
1868
  }
1225
1869
  const hints = [];
1226
1870
  const recommendedRequest = input.concurrent.request < 4 ? DEFAULT_GENERATION_REQUEST_CONCURRENCY : input.concurrent.request < 8 ? 8 : void 0;
1227
- if (recommendedRequest !== void 0) {
1871
+ if (input.hasRequestWork && recommendedRequest !== void 0) {
1228
1872
  hints.push({
1229
1873
  command: `wg wikg://local/config/concurrent put request ${recommendedRequest}`,
1230
1874
  current: input.concurrent.request,
@@ -1238,7 +1882,7 @@ function createGenerationPerformanceHints(input) {
1238
1882
  command: "wg wikg://local/config/concurrent put job 4",
1239
1883
  current: input.concurrent.job,
1240
1884
  kind: "job",
1241
- message: "Multiple chapters need generation and job concurrency is below 4. Raising it lets chapter jobs run in parallel.",
1885
+ message: "Multiple chapters need work and job concurrency is below 4. Raising it lets chapter jobs run in parallel.",
1242
1886
  recommended: 4
1243
1887
  });
1244
1888
  }
@@ -1690,7 +2334,6 @@ var init_progress_output = __esm({
1690
2334
  });
1691
2335
 
1692
2336
  // src/runtime/stage.ts
1693
- import { resolveDataDirPath as resolveDataDirPath2 } from "wiki-graph-core";
1694
2337
  import {
1695
2338
  DEFAULT_EXTRACTION_PROMPT,
1696
2339
  DEFAULT_KNOWLEDGE_GRAPH_RECALL_PROMPT,
@@ -1702,14 +2345,13 @@ import { LLM } from "wiki-graph-core";
1702
2345
  function createStageLLM(config, options) {
1703
2346
  const llmOptions = buildLLMOptions(config);
1704
2347
  return new LLM({
1705
- dataDirPath: resolveDataDirPath2(),
1706
2348
  sampling: createDefaultWikiGraphSampling({
1707
2349
  ...llmOptions.temperature === void 0 ? {} : { temperature: llmOptions.temperature },
1708
2350
  ...llmOptions.topP === void 0 ? {} : { topP: llmOptions.topP }
1709
2351
  }),
1710
2352
  ...llmOptions,
1711
- ...options?.cacheDirPath === void 0 ? {} : { cacheDirPath: options.cacheDirPath },
1712
- ...options?.logDirPath === void 0 ? {} : { logDirPath: options.logDirPath },
2353
+ ...options?.cacheDirectory === void 0 ? {} : { cacheDirectory: options.cacheDirectory },
2354
+ ...options?.logDirectory === void 0 ? {} : { logDirectory: options.logDirectory },
1713
2355
  ...options?.onStreamProgress === void 0 ? {} : { onStreamProgress: options.onStreamProgress },
1714
2356
  ...options?.onTokenUsage === void 0 ? {} : { onTokenUsage: options.onTokenUsage }
1715
2357
  });
@@ -1737,6 +2379,52 @@ var init_stage = __esm({
1737
2379
  }
1738
2380
  });
1739
2381
 
2382
+ // src/runtime/wikispine.ts
2383
+ import { spawn } from "child_process";
2384
+ var nodeWikispineCommandRunner;
2385
+ var init_wikispine = __esm({
2386
+ "src/runtime/wikispine.ts"() {
2387
+ "use strict";
2388
+ nodeWikispineCommandRunner = {
2389
+ run: async ({ args, command, input, onStdout }) => await new Promise((resolve9, reject) => {
2390
+ const child = spawn(command, [...args], {
2391
+ stdio: ["pipe", "pipe", "pipe"]
2392
+ });
2393
+ const stderr = [];
2394
+ let settled = false;
2395
+ child.stdout.setEncoding("utf8");
2396
+ child.stdout.on("data", (chunk) => {
2397
+ if (settled) return;
2398
+ try {
2399
+ onStdout(chunk);
2400
+ } catch (error) {
2401
+ settled = true;
2402
+ child.kill();
2403
+ reject(error instanceof Error ? error : new Error(String(error)));
2404
+ }
2405
+ });
2406
+ child.stderr.on("data", (chunk) => stderr.push(chunk));
2407
+ child.on("error", (error) => {
2408
+ if (settled) return;
2409
+ settled = true;
2410
+ reject(
2411
+ new Error(`Failed to start wikispine command: ${error.message}`)
2412
+ );
2413
+ });
2414
+ child.on("close", (exitCode) => {
2415
+ if (settled) return;
2416
+ settled = true;
2417
+ resolve9({
2418
+ exitCode,
2419
+ stderr: Buffer.concat(stderr).toString("utf8")
2420
+ });
2421
+ });
2422
+ child.stdin.end(input);
2423
+ })
2424
+ };
2425
+ }
2426
+ });
2427
+
1740
2428
  // src/runtime/index.ts
1741
2429
  var init_runtime = __esm({
1742
2430
  "src/runtime/index.ts"() {
@@ -1748,6 +2436,7 @@ var init_runtime = __esm({
1748
2436
  init_progress();
1749
2437
  init_progress_output();
1750
2438
  init_stage();
2439
+ init_wikispine();
1751
2440
  }
1752
2441
  });
1753
2442
 
@@ -1756,8 +2445,8 @@ var convert_exports = {};
1756
2445
  __export(convert_exports, {
1757
2446
  runConvertCommand: () => runConvertCommand
1758
2447
  });
1759
- import { rm as rm2 } from "fs/promises";
1760
- import { resolve as resolve2 } from "path";
2448
+ import { rm as rm3 } from "fs/promises";
2449
+ import { resolve as resolve4 } from "path";
1761
2450
  import { WikiGraph } from "wiki-graph-core";
1762
2451
  async function runConvertCommand(args) {
1763
2452
  const input = resolveInputEndpoint(args);
@@ -1801,7 +2490,7 @@ async function runConvertCommand(args) {
1801
2490
  throw new Error("Internal error: wikg input requires a file path.");
1802
2491
  }
1803
2492
  try {
1804
- await app.openSession(input.path, async (digest) => {
2493
+ await app.openSession(new NodeFile(input.path), async (digest) => {
1805
2494
  await writeDigestOutput(digest, output);
1806
2495
  });
1807
2496
  return;
@@ -1822,7 +2511,7 @@ async function runConvertCommand(args) {
1822
2511
  }
1823
2512
  await app.digestTextStreamSession(
1824
2513
  {
1825
- ...digestDirPath === void 0 ? {} : { documentDirPath: digestDirPath },
2514
+ ...digestDirPath === void 0 ? {} : { documentDirectory: new NodeDirectory(digestDirPath) },
1826
2515
  ...progressRenderer.onProgress === void 0 ? {} : { onProgress: progressRenderer.onProgress },
1827
2516
  sourceFormat: input.format,
1828
2517
  stream: readTextStreamFromStdin(),
@@ -1839,9 +2528,9 @@ async function runConvertCommand(args) {
1839
2528
  case "epub":
1840
2529
  await app.digestEpubSession(
1841
2530
  {
1842
- ...digestDirPath === void 0 ? {} : { documentDirPath: digestDirPath },
2531
+ ...digestDirPath === void 0 ? {} : { documentDirectory: new NodeDirectory(digestDirPath) },
1843
2532
  ...progressRenderer.onProgress === void 0 ? {} : { onProgress: progressRenderer.onProgress },
1844
- path: input.path,
2533
+ file: new NodeFile(input.path),
1845
2534
  ...extractionPrompt === void 0 ? {} : { extractionPrompt },
1846
2535
  targetStage
1847
2536
  },
@@ -1853,9 +2542,9 @@ async function runConvertCommand(args) {
1853
2542
  case "markdown":
1854
2543
  await app.digestMarkdownSession(
1855
2544
  {
1856
- ...digestDirPath === void 0 ? {} : { documentDirPath: digestDirPath },
2545
+ ...digestDirPath === void 0 ? {} : { documentDirectory: new NodeDirectory(digestDirPath) },
1857
2546
  ...progressRenderer.onProgress === void 0 ? {} : { onProgress: progressRenderer.onProgress },
1858
- path: input.path,
2547
+ file: new NodeFile(input.path),
1859
2548
  ...extractionPrompt === void 0 ? {} : { extractionPrompt },
1860
2549
  targetStage
1861
2550
  },
@@ -1867,9 +2556,9 @@ async function runConvertCommand(args) {
1867
2556
  case "txt":
1868
2557
  await app.digestTxtSession(
1869
2558
  {
1870
- ...digestDirPath === void 0 ? {} : { documentDirPath: digestDirPath },
2559
+ ...digestDirPath === void 0 ? {} : { documentDirectory: new NodeDirectory(digestDirPath) },
1871
2560
  ...progressRenderer.onProgress === void 0 ? {} : { onProgress: progressRenderer.onProgress },
1872
- path: input.path,
2561
+ file: new NodeFile(input.path),
1873
2562
  ...extractionPrompt === void 0 ? {} : { extractionPrompt },
1874
2563
  targetStage
1875
2564
  },
@@ -1888,8 +2577,8 @@ async function prepareDigestDirPath(args, requiresDigest) {
1888
2577
  if (normalizedPath === void 0 || !requiresDigest) {
1889
2578
  return void 0;
1890
2579
  }
1891
- const resolvedPath = resolve2(normalizedPath);
1892
- await rm2(resolvedPath, { force: true, recursive: true });
2580
+ const resolvedPath = resolve4(normalizedPath);
2581
+ await rm3(resolvedPath, { force: true, recursive: true });
1893
2582
  return resolvedPath;
1894
2583
  }
1895
2584
  async function loadRequiredConfig(args, requiresDigest) {
@@ -1938,14 +2627,14 @@ async function writeDigestOutput(digest, output) {
1938
2627
  async function writeDigestToFile(digest, path, format) {
1939
2628
  switch (format) {
1940
2629
  case "epub":
1941
- await digest.exportEpub(path);
2630
+ await digest.exportEpub(new NodeFile(path));
1942
2631
  return;
1943
2632
  case "markdown":
1944
2633
  case "txt":
1945
- await digest.exportText(path);
2634
+ await digest.exportText(new NodeFile(path));
1946
2635
  return;
1947
2636
  case "wikg":
1948
- await digest.saveAs(path);
2637
+ await digest.saveAs(new NodeFile(path));
1949
2638
  return;
1950
2639
  }
1951
2640
  }
@@ -2040,17 +2729,17 @@ var init_convert = __esm({
2040
2729
  init_llm();
2041
2730
  init_support();
2042
2731
  init_runtime();
2732
+ init_node_platform();
2043
2733
  }
2044
2734
  });
2045
2735
 
2046
2736
  // src/commands/archive-command/create.ts
2047
- import { rename, rm as rm3, stat } from "fs/promises";
2048
- import { basename, dirname as dirname2, join as join3 } from "path";
2737
+ import { mkdtemp as mkdtemp2, rename as rename2, rm as rm4, stat as stat2 } from "fs/promises";
2738
+ import { basename as basename2, dirname as dirname3, join as join5 } from "path";
2739
+ import { tmpdir as tmpdir2 } from "os";
2049
2740
  import {
2050
- createWikiGraphTempDirectory as createWikiGraphTempDirectory2,
2051
2741
  DirectoryDocument,
2052
2742
  formatLocatedWikiGraphUri,
2053
- formatWikiGraphCommandUri,
2054
2743
  TOC_FILE_VERSION,
2055
2744
  writeWikgArchive
2056
2745
  } from "wiki-graph-core";
@@ -2061,7 +2750,7 @@ async function createArchive(args) {
2061
2750
  await finalizeCreatedArchiveFile(args, outputPath);
2062
2751
  } finally {
2063
2752
  if (outputPath !== args.archivePath) {
2064
- await rm3(outputPath, { force: true, recursive: true });
2753
+ await rm4(outputPath, { force: true, recursive: true });
2065
2754
  }
2066
2755
  }
2067
2756
  await writeCreatedArchive(args);
@@ -2081,8 +2770,11 @@ async function writeCreatedArchiveFile(args, outputPath) {
2081
2770
  });
2082
2771
  }
2083
2772
  async function createEmptyArchive(outputPath) {
2084
- const directoryPath = await createWikiGraphTempDirectory2("archive-write");
2085
- const document = await DirectoryDocument.open(directoryPath);
2773
+ const directoryPath = await mkdtemp2(
2774
+ join5(tmpdir2(), "wikigraph-archive-write-")
2775
+ );
2776
+ const directory = new NodeDirectory(directoryPath);
2777
+ const document = await DirectoryDocument.open(directory);
2086
2778
  try {
2087
2779
  try {
2088
2780
  await document.openSession(async (openedDocument) => {
@@ -2094,9 +2786,9 @@ async function createEmptyArchive(outputPath) {
2094
2786
  } finally {
2095
2787
  await document.release();
2096
2788
  }
2097
- await writeWikgArchive(directoryPath, outputPath);
2789
+ await writeWikgArchive(directory, new NodeFile(outputPath));
2098
2790
  } finally {
2099
- await rm3(directoryPath, { force: true, recursive: true });
2791
+ await rm4(directoryPath, { force: true, recursive: true });
2100
2792
  }
2101
2793
  }
2102
2794
  async function prepareCreateArchiveOutputPath(args) {
@@ -2106,20 +2798,20 @@ async function prepareCreateArchiveOutputPath(args) {
2106
2798
  if (args.replace !== true) {
2107
2799
  return args.archivePath;
2108
2800
  }
2109
- return join3(
2110
- dirname2(args.archivePath),
2111
- `.${basename(args.archivePath)}.${process.pid}.${Date.now()}.tmp.wikg`
2801
+ return join5(
2802
+ dirname3(args.archivePath),
2803
+ `.${basename2(args.archivePath)}.${process.pid}.${Date.now()}.tmp.wikg`
2112
2804
  );
2113
2805
  }
2114
2806
  async function finalizeCreatedArchiveFile(args, outputPath) {
2115
2807
  if (outputPath === args.archivePath) {
2116
2808
  return;
2117
2809
  }
2118
- await rename(outputPath, args.archivePath);
2810
+ await rename2(outputPath, args.archivePath);
2119
2811
  }
2120
2812
  async function fileExists(path) {
2121
2813
  try {
2122
- await stat(path);
2814
+ await stat2(path);
2123
2815
  return true;
2124
2816
  } catch (error) {
2125
2817
  if (isNodeENOENTError(error)) {
@@ -2150,6 +2842,7 @@ async function writeCreatedArchive(args) {
2150
2842
  var init_create = __esm({
2151
2843
  "src/commands/archive-command/create.ts"() {
2152
2844
  "use strict";
2845
+ init_node_platform();
2153
2846
  init_convert();
2154
2847
  init_support();
2155
2848
  }
@@ -2157,7 +2850,6 @@ var init_create = __esm({
2157
2850
 
2158
2851
  // src/commands/archive-command/inspect.ts
2159
2852
  import {
2160
- formatWikiGraphCommandUri as formatWikiGraphCommandUri2,
2161
2853
  isArchiveSearchIndexCurrent,
2162
2854
  listChapters
2163
2855
  } from "wiki-graph-core";
@@ -2171,11 +2863,10 @@ async function writeArchiveInspectReport(document, args) {
2171
2863
  }
2172
2864
  async function createArchiveInspectReport(document, args) {
2173
2865
  const archiveUri = formatArchiveInspectCommandUri(args.archivePath);
2174
- const scopeUri = args.chapterId === void 0 ? archiveUri : `${archiveUri}/chapter/${args.chapterId}`;
2175
2866
  const [
2176
2867
  chapters,
2177
2868
  summaryWords,
2178
- ftsCurrent,
2869
+ indexCacheCurrent,
2179
2870
  config,
2180
2871
  ftsArtifactCoverage,
2181
2872
  sourceEmbeddingArtifactCoverage,
@@ -2189,6 +2880,8 @@ async function createArchiveInspectReport(document, args) {
2189
2880
  readIndexArtifactCoverage(document, "embedding-source", args.chapterId),
2190
2881
  readIndexArtifactCoverage(document, "embedding-summary", args.chapterId)
2191
2882
  ]);
2883
+ const selectedChapter = args.chapterId === void 0 ? void 0 : chapters[0];
2884
+ const scopeUri = selectedChapter === void 0 ? archiveUri : formatInspectLocatedChapterUri(archiveUri, selectedChapter);
2192
2885
  const concurrent = {
2193
2886
  job: config.concurrent?.job ?? DEFAULT_GENERATION_JOB_CONCURRENCY,
2194
2887
  request: config.concurrent?.request ?? DEFAULT_GENERATION_REQUEST_CONCURRENCY
@@ -2219,15 +2912,28 @@ async function createArchiveInspectReport(document, args) {
2219
2912
  contentChapters,
2220
2913
  summaryEmbeddingArtifactCoverage
2221
2914
  );
2222
- const queryBlockedChapters = contentChapters.filter(
2915
+ const queryBlockedContentChapters = contentChapters.filter(
2223
2916
  (chapter) => !ftsArtifactCovered.includes(chapter) && !sourceEmbeddingArtifactCovered.includes(chapter)
2224
- ).map((chapter) => chapter.chapterId);
2917
+ );
2918
+ const queryBlockedChapters = queryBlockedContentChapters.map(
2919
+ (chapter) => createInspectChapterReference(archiveUri, chapter)
2920
+ );
2921
+ const queryReady = queryBlockedChapters.length === 0;
2922
+ const buildFtsCommand = formatCliCommand([
2923
+ "wikg://local/job",
2924
+ "add",
2925
+ "--input",
2926
+ scopeUri,
2927
+ "--task",
2928
+ "index-fts"
2929
+ ]);
2225
2930
  const improvements = createInspectImprovements({
2226
2931
  archiveUri,
2227
2932
  concurrent,
2228
2933
  contentChapters,
2229
- ftsCurrent,
2934
+ indexCacheCurrent,
2230
2935
  planningModel,
2936
+ queryBlockedChapters: queryBlockedContentChapters,
2231
2937
  scopeUri,
2232
2938
  summaryCovered,
2233
2939
  knowledgeGraphCovered,
@@ -2239,7 +2945,10 @@ async function createArchiveInspectReport(document, args) {
2239
2945
  ...improvements.map((improvement) => improvement.missingChapters ?? 0)
2240
2946
  ),
2241
2947
  concurrent,
2242
- hasGenerationWork: improvements.some(
2948
+ hasJobWork: improvements.some(
2949
+ (improvement) => improvement.planning !== void 0
2950
+ ),
2951
+ hasRequestWork: improvements.some(
2243
2952
  (improvement) => improvement.planning !== void 0
2244
2953
  )
2245
2954
  });
@@ -2255,15 +2964,18 @@ async function createArchiveInspectReport(document, args) {
2255
2964
  sourceWords,
2256
2965
  summaryWords
2257
2966
  },
2258
- index: {
2259
- current: ftsCurrent,
2260
- ...ftsCurrent ? {} : {
2967
+ localIndexCache: {
2968
+ current: indexCacheCurrent,
2969
+ ...!queryReady ? {
2970
+ blockedBy: "missing-search-artifacts",
2971
+ impact: "The cache cannot be built until every content chapter has a current FTS or source embedding artifact."
2972
+ } : indexCacheCurrent ? {} : {
2261
2973
  fixCommand: formatCliCommand([`${archiveUri}/index`, "sync"]),
2262
2974
  impact: "The next archive query may need to sync index cache first.",
2263
2975
  resource: "local CPU/disk time only; no provider calls."
2264
2976
  },
2265
- querySupport: queryBlockedChapters.length === 0,
2266
- status: ftsCurrent ? "current" : "missing-or-outdated"
2977
+ status: !queryReady ? "blocked" : indexCacheCurrent ? "current" : "missing-or-outdated",
2978
+ syncAvailable: queryReady && !indexCacheCurrent
2267
2979
  },
2268
2980
  coverage: {
2269
2981
  ftsIndexArtifact: createInspectCoverage(
@@ -2285,12 +2997,25 @@ async function createArchiveInspectReport(document, args) {
2285
2997
  contentChapters
2286
2998
  )
2287
2999
  },
2288
- queryBlockedChapters,
3000
+ query: {
3001
+ ready: queryReady
3002
+ },
3003
+ searchArtifacts: {
3004
+ blockedChapters: queryBlockedChapters,
3005
+ ...!queryReady ? {
3006
+ fixCommand: buildFtsCommand,
3007
+ resource: "local CPU/disk time only; no provider calls."
3008
+ } : {},
3009
+ helpCommand: "wg help readiness",
3010
+ ready: queryReady,
3011
+ status: queryReady ? "ready" : "incomplete"
3012
+ },
2289
3013
  retrievalGuidance: formatRetrievalGuidance({
2290
- ftsCurrent,
3014
+ indexCacheCurrent,
2291
3015
  knowledgeGraphCovered,
2292
3016
  readingGraphCovered,
2293
3017
  contentChapters,
3018
+ queryReady,
2294
3019
  sourceWords
2295
3020
  }),
2296
3021
  improvements,
@@ -2305,13 +3030,13 @@ function formatArchiveInspectCommandUri(archivePath) {
2305
3030
  if (archivePath.startsWith("wikg://lib/")) {
2306
3031
  return archivePath;
2307
3032
  }
2308
- return formatWikiGraphCommandUri2(archivePath);
3033
+ return formatWikiGraphCommandUri(archivePath);
2309
3034
  }
2310
3035
  function formatArchiveInspectText(report) {
2311
3036
  return [
2312
3037
  "Archive Inspect",
2313
3038
  `URI: ${report.uri}`,
2314
- `Scope: ${report.scope.type === "archive" ? "archive" : `chapter ${report.scope.chapterId}`}`,
3039
+ `Scope: ${report.scope.type === "archive" ? "archive" : report.uri}`,
2315
3040
  "",
2316
3041
  "Content",
2317
3042
  `Chapters: ${report.content.chapters.content} content / ${report.content.chapters.total} total`,
@@ -2319,13 +3044,21 @@ function formatArchiveInspectText(report) {
2319
3044
  `Source words: ${report.content.sourceWords}`,
2320
3045
  `Summary words: ${report.content.summaryWords}`,
2321
3046
  "",
3047
+ "Query Readiness",
3048
+ `Status: ${report.query.ready ? "available" : "unavailable"}`,
3049
+ `Search artifacts: ${report.searchArtifacts.status}`,
3050
+ ...report.searchArtifacts.ready ? [] : [
3051
+ `Fix: ${report.searchArtifacts.fixCommand}`,
3052
+ `Resource: ${report.searchArtifacts.resource}`,
3053
+ `Help: ${report.searchArtifacts.helpCommand}`
3054
+ ],
3055
+ "",
2322
3056
  "Index Cache",
2323
- `Status: ${report.index.current ? "current" : "missing or outdated"}`,
2324
- `Query support: ${report.index.querySupport ? "available" : "unavailable"}`,
2325
- ...report.index.current ? [] : [
2326
- `Impact: ${report.index.impact}`,
2327
- `Fix: ${report.index.fixCommand}`,
2328
- `Resource: ${report.index.resource}`
3057
+ `Status: ${report.localIndexCache.status === "missing-or-outdated" ? "missing or outdated" : report.localIndexCache.status}`,
3058
+ ...report.localIndexCache.current ? [] : [
3059
+ `Impact: ${report.localIndexCache.impact}`,
3060
+ ...report.localIndexCache.fixCommand === void 0 ? [] : [`Fix: ${report.localIndexCache.fixCommand}`],
3061
+ ...report.localIndexCache.resource === void 0 ? [] : [`Resource: ${report.localIndexCache.resource}`]
2329
3062
  ],
2330
3063
  "",
2331
3064
  "Coverage",
@@ -2345,8 +3078,11 @@ function formatArchiveInspectText(report) {
2345
3078
  formatCoverageLine("Knowledge Graph", report.coverage.knowledgeGraph),
2346
3079
  formatCoverageLine("Summary Artifact", report.coverage.summary),
2347
3080
  `Summary note: ${report.help.summaryCoverage}`,
2348
- ...report.queryBlockedChapters.length === 0 ? [] : [
2349
- `Query blockers: chapters ${report.queryBlockedChapters.join(", ")} have neither FTS nor source embedding index artifacts.`
3081
+ ...report.searchArtifacts.blockedChapters.length === 0 ? [] : [
3082
+ "Query blockers: these chapters have neither FTS nor source embedding index artifacts:",
3083
+ ...report.searchArtifacts.blockedChapters.map(
3084
+ (chapter) => `- ${chapter.title === null ? "[untitled]" : chapter.title}: ${chapter.locatedUri}`
3085
+ )
2350
3086
  ],
2351
3087
  "",
2352
3088
  "Retrieval Guidance",
@@ -2362,6 +3098,17 @@ function formatArchiveInspectText(report) {
2362
3098
  ]
2363
3099
  ].join("\n") + "\n";
2364
3100
  }
3101
+ function createInspectChapterReference(archiveUri, chapter) {
3102
+ return {
3103
+ chapterId: chapter.chapterId,
3104
+ locatedUri: formatInspectLocatedChapterUri(archiveUri, chapter),
3105
+ title: chapter.title,
3106
+ uri: chapter.uri
3107
+ };
3108
+ }
3109
+ function formatInspectLocatedChapterUri(archiveUri, chapter) {
3110
+ return `${archiveUri.replace(/\/+$/u, "")}/${chapter.uri.replace(/^wikg:\/\//u, "")}`;
3111
+ }
2365
3112
  async function readInspectChapters(document, chapterId) {
2366
3113
  const chapters = chapterId === void 0 ? await listChapters(document) : (await listChapters(document)).filter(
2367
3114
  (chapter) => chapter.chapterId === chapterId
@@ -2430,7 +3177,7 @@ function formatRetrievalGuidance(input) {
2430
3177
  ];
2431
3178
  }
2432
3179
  const lines = [
2433
- `Query cache: ${input.ftsCurrent ? "current" : "missing or outdated; archive query can sync it from artifacts"}.`
3180
+ input.queryReady ? `Query: available; local index cache is ${input.indexCacheCurrent ? "current" : "missing or outdated and can be synced from artifacts"}.` : "Query: unavailable until every content chapter has a current FTS or source embedding artifact."
2434
3181
  ];
2435
3182
  lines.push(
2436
3183
  formatObjectSearchGuidance(
@@ -2466,13 +3213,6 @@ function formatObjectSearchGuidance(label, covered, total) {
2466
3213
  }
2467
3214
  function createInspectImprovements(input) {
2468
3215
  const improvements = [];
2469
- if (!input.ftsCurrent) {
2470
- improvements.push({
2471
- command: formatCliCommand([`${input.archiveUri}/index`, "sync"]),
2472
- recommendation: "Sync the index cache from chapter index artifacts so query starts without a lazy cache rebuild.",
2473
- title: "Sync index cache"
2474
- });
2475
- }
2476
3216
  if (input.contentChapters.length === 0) {
2477
3217
  improvements.push({
2478
3218
  command: formatCliCommand([
@@ -2486,6 +3226,28 @@ function createInspectImprovements(input) {
2486
3226
  });
2487
3227
  return improvements;
2488
3228
  }
3229
+ if (input.queryBlockedChapters.length > 0) {
3230
+ improvements.push({
3231
+ command: formatCliCommand([
3232
+ "wikg://local/job",
3233
+ "add",
3234
+ "--input",
3235
+ input.scopeUri,
3236
+ "--task",
3237
+ "index-fts"
3238
+ ]),
3239
+ missingChapters: input.queryBlockedChapters.length,
3240
+ missingWords: sumWords(input.queryBlockedChapters),
3241
+ recommendation: "Build local FTS artifacts to make this scope queryable. This does not call a provider.",
3242
+ title: "Enable query with local FTS"
3243
+ });
3244
+ } else if (!input.indexCacheCurrent) {
3245
+ improvements.push({
3246
+ command: formatCliCommand([`${input.archiveUri}/index`, "sync"]),
3247
+ recommendation: "Sync the index cache from chapter index artifacts so query starts without a lazy cache rebuild.",
3248
+ title: "Sync index cache"
3249
+ });
3250
+ }
2489
3251
  improvements.push(
2490
3252
  ...createGraphImprovement({
2491
3253
  concurrent: input.concurrent,
@@ -2612,6 +3374,7 @@ function formatPercent(numerator, denominator) {
2612
3374
  var init_inspect = __esm({
2613
3375
  "src/commands/archive-command/inspect.ts"() {
2614
3376
  "use strict";
3377
+ init_support();
2615
3378
  init_config();
2616
3379
  init_runtime();
2617
3380
  init_support();
@@ -2627,7 +3390,20 @@ async function createOutputContinuationCursor(context, cursor) {
2627
3390
  return null;
2628
3391
  }
2629
3392
  let input;
2630
- if (context.continuationKind === "evidence") {
3393
+ if (context.continuationKind === "source-locators") {
3394
+ if (context.targetUri === void 0) {
3395
+ throw new Error("Source locator cursors require a target URI.");
3396
+ }
3397
+ input = {
3398
+ archiveKey: context.archiveKey,
3399
+ archivePath: context.archivePath,
3400
+ cursor,
3401
+ format: context.format,
3402
+ indexScope: context.indexScope,
3403
+ kind: "source-locators",
3404
+ targetUri: context.targetUri
3405
+ };
3406
+ } else if (context.continuationKind === "evidence") {
2631
3407
  if (context.targetUri === void 0) {
2632
3408
  throw new Error("Evidence continuation cursors require a target URI.");
2633
3409
  }
@@ -2724,25 +3500,13 @@ function formatSourceCitationBlock(uri, text) {
2724
3500
  return [`@@ ${uri} @@`, normalizeSourceText(text)].join("\n");
2725
3501
  }
2726
3502
  function normalizeSourceText(text) {
2727
- const lines = text.replace(/\r\n?/g, "\n").split("\n");
2728
- while (lines.length > 0 && lines[0]?.trim() === "") {
2729
- lines.shift();
2730
- }
2731
- while (lines.length > 0 && lines.at(-1)?.trim() === "") {
2732
- lines.pop();
2733
- }
3503
+ const lines = text.replace(/\r\n?/gu, "\n").split("\n");
3504
+ while (lines.length > 0 && lines[0]?.trim() === "") lines.shift();
3505
+ while (lines.length > 0 && lines.at(-1)?.trim() === "") lines.pop();
2734
3506
  const normalizedLines = [];
2735
- let previousLineWasBlank = false;
2736
3507
  for (const line of lines) {
2737
- if (line.trim() === "") {
2738
- if (!previousLineWasBlank) {
2739
- normalizedLines.push("");
2740
- }
2741
- previousLineWasBlank = true;
2742
- continue;
2743
- }
2744
- normalizedLines.push(line);
2745
- previousLineWasBlank = false;
3508
+ if (line.trim() === "" && normalizedLines.at(-1) === "") continue;
3509
+ normalizedLines.push(line.trim() === "" ? "" : line);
2746
3510
  }
2747
3511
  return normalizedLines.join("\n");
2748
3512
  }
@@ -2864,7 +3628,7 @@ function toWikiGraphUri(id) {
2864
3628
  return id;
2865
3629
  }
2866
3630
  }
2867
- var init_uri = __esm({
3631
+ var init_uri2 = __esm({
2868
3632
  "src/commands/archive-output/object/uri.ts"() {
2869
3633
  "use strict";
2870
3634
  }
@@ -2878,6 +3642,11 @@ var init_types = __esm({
2878
3642
  DEFAULT_GET_EVIDENCE_LIMIT = 3;
2879
3643
  PLAIN_OBJECT_KEY_PRIORITY = [
2880
3644
  "uri",
3645
+ "digest",
3646
+ "mediaType",
3647
+ "name",
3648
+ "identifier",
3649
+ "locator",
2881
3650
  "title",
2882
3651
  "label",
2883
3652
  "labels",
@@ -2954,10 +3723,6 @@ var init_plain = __esm({
2954
3723
  });
2955
3724
 
2956
3725
  // src/commands/archive-output/text/object.ts
2957
- import {
2958
- formatWikiGraphCommandUri as formatWikiGraphCommandUri3,
2959
- parseLocatedWikiGraphUri as parseLocatedWikiGraphUri7
2960
- } from "wiki-graph-core";
2961
3726
  function formatFindObject(object) {
2962
3727
  const lines = formatScoredLines(
2963
3728
  object.score,
@@ -3000,10 +3765,10 @@ function formatOpenShortUriCommand(locator, objectUri) {
3000
3765
  if (locator.startsWith("wikg://lib/")) {
3001
3766
  return `${locator.replace(/\/+$/u, "")}/${objectUri.slice("wikg://".length)}`;
3002
3767
  }
3003
- return formatWikiGraphCommandUri3(locator, objectUri);
3768
+ return formatWikiGraphCommandUri(locator, objectUri);
3004
3769
  }
3005
3770
  function isShortOutputUri(uri) {
3006
- return uri.startsWith("wikg://") && parseLocatedWikiGraphUri7(uri).archivePath === void 0;
3771
+ return uri.startsWith("wikg://") && parseLocatedWikiGraphUri(uri).archivePath === void 0;
3007
3772
  }
3008
3773
  function formatBacklinkLines(backlinks) {
3009
3774
  const lines = [
@@ -3093,7 +3858,8 @@ var init_object = __esm({
3093
3858
  "src/commands/archive-output/text/object.ts"() {
3094
3859
  "use strict";
3095
3860
  init_support();
3096
- init_uri();
3861
+ init_support();
3862
+ init_uri2();
3097
3863
  init_evidence();
3098
3864
  init_lines();
3099
3865
  init_plain();
@@ -3248,6 +4014,10 @@ async function createBacklinkBucketObject(bucket, context) {
3248
4014
  async function createPageObject(page, context) {
3249
4015
  const librarySource = createLibrarySourceObject(page);
3250
4016
  switch (page.type) {
4017
+ case "artifact": {
4018
+ const { id: _id, type: _type, ...rest } = page;
4019
+ return { ...librarySource, ...rest, uri: page.id };
4020
+ }
3251
4021
  case "entity-wikipage":
3252
4022
  return {
3253
4023
  ...librarySource,
@@ -3379,14 +4149,11 @@ var init_objects = __esm({
3379
4149
  "src/commands/archive-output/object/objects.ts"() {
3380
4150
  "use strict";
3381
4151
  init_cursor();
3382
- init_uri();
4152
+ init_uri2();
3383
4153
  }
3384
4154
  });
3385
4155
 
3386
4156
  // src/commands/archive-output/text/page.ts
3387
- import {
3388
- formatWikiGraphCommandUri as formatWikiGraphCommandUri4
3389
- } from "wiki-graph-core";
3390
4157
  async function formatEvidenceBackedPageText(uri, label, evidence, context) {
3391
4158
  if (context.evidenceLimit === void 0) {
3392
4159
  return [`${uri}`, label].join("\n");
@@ -3409,7 +4176,7 @@ function appendEntityNextSteps(text, uri, archivePath) {
3409
4176
  if (!isEntityOutputUri(uri)) {
3410
4177
  return text;
3411
4178
  }
3412
- const entityUri = formatWikiGraphCommandUri4(
4179
+ const entityUri = formatWikiGraphCommandUri(
3413
4180
  archivePath,
3414
4181
  uri.replace(/\/$/u, "")
3415
4182
  );
@@ -3480,6 +4247,8 @@ function formatPosition(position) {
3480
4247
  }
3481
4248
  async function formatPackAnchor(anchor, context) {
3482
4249
  switch (anchor.type) {
4250
+ case "artifact":
4251
+ return formatPlainObject(await createPageObject(anchor, context));
3483
4252
  case "chapter-title":
3484
4253
  case "chapter":
3485
4254
  return formatPlainObject(await createPageObject(anchor, context));
@@ -3536,7 +4305,7 @@ var init_page = __esm({
3536
4305
  "use strict";
3537
4306
  init_support();
3538
4307
  init_objects();
3539
- init_uri();
4308
+ init_uri2();
3540
4309
  init_evidence();
3541
4310
  init_plain();
3542
4311
  }
@@ -4008,6 +4777,12 @@ async function writePage(page, context, format) {
4008
4777
  return;
4009
4778
  }
4010
4779
  switch (page.type) {
4780
+ case "artifact":
4781
+ await writeTextToStdout(
4782
+ `${formatPlainObject(await createPageObject(page, context))}
4783
+ `
4784
+ );
4785
+ return;
4011
4786
  case "chapter-title":
4012
4787
  await writeTextToStdout(
4013
4788
  `${formatPlainObject(await createPageObject(page, context))}
@@ -4122,13 +4897,77 @@ ${page.content}
4122
4897
  return;
4123
4898
  }
4124
4899
  }
4125
- var init_page2 = __esm({
4126
- "src/commands/archive-output/write/page.ts"() {
4900
+ var init_page2 = __esm({
4901
+ "src/commands/archive-output/write/page.ts"() {
4902
+ "use strict";
4903
+ init_support();
4904
+ init_text();
4905
+ init_jsonl();
4906
+ init_objects();
4907
+ }
4908
+ });
4909
+
4910
+ // src/commands/archive-output/write/source-locators.ts
4911
+ async function writeSourceLocators(result, context, format) {
4912
+ const nextCursor = await createOutputContinuationCursor(
4913
+ context,
4914
+ result.nextCursor
4915
+ );
4916
+ if (format === "json") {
4917
+ await writeTextToStdout(
4918
+ formatCLIJSON({
4919
+ limit: result.limit,
4920
+ nextCursor,
4921
+ objects: result.items
4922
+ })
4923
+ );
4924
+ return;
4925
+ }
4926
+ if (format === "jsonl") {
4927
+ await writeJSONL([...result.items, createPageCursorObject(nextCursor)]);
4928
+ return;
4929
+ }
4930
+ if (result.items.length === 0) {
4931
+ await writeTextToStdout("No source locators.\n");
4932
+ return;
4933
+ }
4934
+ await writeTextToStdout(
4935
+ `${result.items.map(formatSourceLocator).join("\n")}${formatNextCursor(nextCursor)}
4936
+ `
4937
+ );
4938
+ }
4939
+ async function writeAllSourceLocators(readPage, initialCursor, context, format) {
4940
+ const pages = [];
4941
+ let cursor = initialCursor;
4942
+ while (true) {
4943
+ const page = await readPage(cursor);
4944
+ if (format === "jsonl") {
4945
+ await writeJSONL(page.items);
4946
+ } else {
4947
+ pages.push(page);
4948
+ }
4949
+ if (page.nextCursor === null) break;
4950
+ cursor = page.nextCursor;
4951
+ }
4952
+ if (format === "jsonl") return;
4953
+ const items = pages.flatMap((page) => page.items);
4954
+ await writeSourceLocators(
4955
+ { items, limit: items.length, nextCursor: null },
4956
+ context,
4957
+ format
4958
+ );
4959
+ }
4960
+ function formatSourceLocator(locator) {
4961
+ return `${locator.range[0]}..${locator.range[1]} -> ${locator.uri}`;
4962
+ }
4963
+ var init_source_locators = __esm({
4964
+ "src/commands/archive-output/write/source-locators.ts"() {
4127
4965
  "use strict";
4128
4966
  init_support();
4967
+ init_cursor();
4968
+ init_page_cursor();
4129
4969
  init_text();
4130
4970
  init_jsonl();
4131
- init_objects();
4132
4971
  }
4133
4972
  });
4134
4973
 
@@ -4141,6 +4980,7 @@ var init_write = __esm({
4141
4980
  init_list();
4142
4981
  init_pack();
4143
4982
  init_page2();
4983
+ init_source_locators();
4144
4984
  }
4145
4985
  });
4146
4986
 
@@ -4156,13 +4996,12 @@ var init_archive_output = __esm({
4156
4996
  import {
4157
4997
  formatLocatedWikiGraphUri as formatLocatedWikiGraphUri2,
4158
4998
  parseWikiGraphLibraryUri as parseWikiGraphLibraryUri4,
4159
- parseLocatedWikiGraphUri as parseLocatedWikiGraphUri8,
4160
- requireLocatedObjectOrArchiveUri,
4161
- resolveWikiGraphLibraryArchivePath
4999
+ resolveWikiGraphLibraryArchiveFile
4162
5000
  } from "wiki-graph-core";
4163
5001
  async function resolveArchiveRuntimeLocation(uriOrPath) {
4164
5002
  if (!uriOrPath.startsWith("wikg://")) {
4165
5003
  return {
5004
+ archiveFile: new NodeFile(uriOrPath),
4166
5005
  archiveKey: uriOrPath,
4167
5006
  archivePath: uriOrPath,
4168
5007
  indexScope: {
@@ -4173,11 +5012,13 @@ async function resolveArchiveRuntimeLocation(uriOrPath) {
4173
5012
  locatedUri: formatLocatedWikiGraphUri2(uriOrPath)
4174
5013
  };
4175
5014
  }
4176
- const parsed = parseLocatedWikiGraphUri8(uriOrPath);
5015
+ const parsed = parseLocatedWikiGraphUri(uriOrPath);
4177
5016
  const archiveLocator = parsed.archivePath ?? uriOrPath;
4178
5017
  const libraryArchiveTarget = archiveLocator.startsWith("wikg://lib/") ? parseWikiGraphLibraryUri4(archiveLocator) : void 0;
4179
- const archivePath = libraryArchiveTarget?.kind === "archive" ? await resolveWikiGraphLibraryArchivePath(archiveLocator) : archiveLocator;
5018
+ const archiveFile = libraryArchiveTarget?.kind === "archive" ? await resolveWikiGraphLibraryArchiveFile(archiveLocator) : new NodeFile(archiveLocator);
5019
+ const archivePath = getNodeResourcePath(archiveFile);
4180
5020
  return {
5021
+ archiveFile,
4181
5022
  archiveKey: archivePath,
4182
5023
  archivePath,
4183
5024
  indexScope: { archiveKey: archivePath, archivePath, kind: "archive-index" },
@@ -4210,7 +5051,11 @@ function getArchivePath(uri) {
4210
5051
  if (parseWikiGraphLibraryUri4(uri)?.kind === "scope") {
4211
5052
  return uri;
4212
5053
  }
4213
- return requireLocatedObjectOrArchiveUri(uri).archivePath;
5054
+ const archivePath = parseLocatedWikiGraphUri(uri).archivePath;
5055
+ if (archivePath === void 0) {
5056
+ throw new Error(`Missing archive locator in URI: ${uri}`);
5057
+ }
5058
+ return archivePath;
4214
5059
  }
4215
5060
  function getArchiveIndexScope(uri) {
4216
5061
  if (parseWikiGraphLibraryUri4(uri)?.kind === "scope") {
@@ -4224,19 +5069,21 @@ function getObjectUri(uri) {
4224
5069
  if (libraryTarget?.kind === "scope" && libraryTarget.objectUri !== void 0) {
4225
5070
  return libraryTarget.objectUri;
4226
5071
  }
4227
- const parsed = requireLocatedObjectOrArchiveUri(uri);
5072
+ const parsed = parseLocatedWikiGraphUri(uri);
4228
5073
  return parsed.objectUri ?? "wikg://";
4229
5074
  }
4230
5075
  function isArchiveRootGet(args) {
4231
- return args.objectId !== void 0 && requireLocatedObjectOrArchiveUri(args.objectId).objectUri === void 0;
5076
+ return args.objectId !== void 0 && parseLocatedWikiGraphUri(args.objectId).objectUri === void 0;
4232
5077
  }
4233
5078
  function parseChapterScope(uri) {
4234
5079
  const match = /^wikg:\/\/chapter\/([1-9][0-9]*)(?:\/|$)/u.exec(uri);
4235
5080
  return match?.[1] === void 0 ? void 0 : Number(match[1]);
4236
5081
  }
4237
- var init_uri2 = __esm({
5082
+ var init_uri3 = __esm({
4238
5083
  "src/commands/archive-command/run/uri.ts"() {
4239
5084
  "use strict";
5085
+ init_support();
5086
+ init_node_platform();
4240
5087
  }
4241
5088
  });
4242
5089
 
@@ -4249,13 +5096,13 @@ import {
4249
5096
  } from "wiki-graph-core";
4250
5097
  async function readArchiveDocument(path, operation) {
4251
5098
  const location = await resolveArchiveRuntimeLocation(path);
4252
- return await new WikiGraphArchiveFile(location.archivePath).readDocument(
5099
+ return await new WikiGraphArchiveFile(location.archiveFile).readDocument(
4253
5100
  operation
4254
5101
  );
4255
5102
  }
4256
5103
  async function writeArchiveDocument(path, operation, options = {}) {
4257
5104
  const location = await resolveArchiveRuntimeLocation(path);
4258
- const result = await new WikiGraphArchiveFile(location.archivePath).write(
5105
+ const result = await new WikiGraphArchiveFile(location.archiveFile).write(
4259
5106
  operation,
4260
5107
  options
4261
5108
  );
@@ -4291,7 +5138,7 @@ function reportLibraryIndexSyncFailure(error) {
4291
5138
  var init_document = __esm({
4292
5139
  "src/commands/archive-command/run/document.ts"() {
4293
5140
  "use strict";
4294
- init_uri2();
5141
+ init_uri3();
4295
5142
  }
4296
5143
  });
4297
5144
 
@@ -4308,7 +5155,7 @@ var init_types2 = __esm({
4308
5155
 
4309
5156
  // src/commands/archive-command/run/options.ts
4310
5157
  import {
4311
- parseLocatedWikiGraphUri as parseLocatedWikiGraphUri9
5158
+ parseLocatedWikiGraphUri as parseLocatedWikiGraphUri2
4312
5159
  } from "wiki-graph-core";
4313
5160
  function createFindOptions(args) {
4314
5161
  const types = args.kinds?.map((kind) => {
@@ -4420,7 +5267,7 @@ function createScopeOptions(args) {
4420
5267
  if (args.chapters !== void 0) {
4421
5268
  return { chapters: args.chapters };
4422
5269
  }
4423
- const objectUri = parseLocatedWikiGraphUri9(args.archivePath).objectUri;
5270
+ const objectUri = parseLocatedWikiGraphUri2(args.archivePath).objectUri;
4424
5271
  if (objectUri === void 0) {
4425
5272
  return {};
4426
5273
  }
@@ -4467,7 +5314,7 @@ var init_options = __esm({
4467
5314
  "src/commands/archive-command/run/options.ts"() {
4468
5315
  "use strict";
4469
5316
  init_types2();
4470
- init_uri2();
5317
+ init_uri3();
4471
5318
  }
4472
5319
  });
4473
5320
 
@@ -4478,6 +5325,7 @@ import {
4478
5325
  findWikiGraphLibraryObjects,
4479
5326
  listArchiveCollection,
4480
5327
  listArchiveEvidence,
5328
+ listArchiveSourceLocators,
4481
5329
  listWikiGraphLibraryArchiveMembers,
4482
5330
  listRelatedWikiGraphLibraryObjects,
4483
5331
  listWikiGraphLibraryEvidence,
@@ -4500,6 +5348,33 @@ async function runNextArchivePage(args) {
4500
5348
  );
4501
5349
  }
4502
5350
  }
5351
+ if (cursor.kind === "source-locators") {
5352
+ await readArchiveDocument(
5353
+ getCursorArchivePath(cursor),
5354
+ async (document) => {
5355
+ const format = args.format ?? cursor.format;
5356
+ const limit = args.limit ?? DEFAULT_OUTPUT_LIMIT;
5357
+ await writeSourceLocators(
5358
+ await listArchiveSourceLocators(document, cursor.targetUri, {
5359
+ cursor: cursor.cursor,
5360
+ limit
5361
+ }),
5362
+ {
5363
+ archiveKey: cursor.archiveKey,
5364
+ archivePath: cursor.archivePath,
5365
+ continuationKind: "source-locators",
5366
+ format,
5367
+ indexScope: cursor.indexScope,
5368
+ limit,
5369
+ targetUri: cursor.targetUri,
5370
+ types: null
5371
+ },
5372
+ format
5373
+ );
5374
+ }
5375
+ );
5376
+ return;
5377
+ }
4503
5378
  if (cursor.indexScope?.kind === "library-index") {
4504
5379
  await runNextLibraryIndexPage(args, cursor);
4505
5380
  return;
@@ -4658,6 +5533,10 @@ async function runNextLibraryIndexPage(args, cursor) {
4658
5533
  const format = args.format ?? cursor.format;
4659
5534
  const limit = args.limit ?? DEFAULT_OUTPUT_LIMIT;
4660
5535
  switch (cursor.kind) {
5536
+ case "source-locators":
5537
+ throw new Error(
5538
+ "Source locator cursors do not use the aggregate library index."
5539
+ );
4661
5540
  case "collection": {
4662
5541
  const collectionOptions = {
4663
5542
  ...cursor.backlinks === void 0 ? {} : { backlinks: cursor.backlinks },
@@ -4809,7 +5688,7 @@ function createCursorOutputContext(cursor, format, limit) {
4809
5688
  format,
4810
5689
  indexScope: cursor.indexScope,
4811
5690
  limit,
4812
- types: cursor.kind === "evidence" || cursor.kind === "related" ? null : cursor.types,
5691
+ types: cursor.kind === "evidence" || cursor.kind === "related" || cursor.kind === "source-locators" ? null : cursor.types,
4813
5692
  ...cursor.kind === "search" || cursor.kind === "collection" ? cursor.backlinks === void 0 ? {} : { backlinks: cursor.backlinks } : {},
4814
5693
  ...cursor.kind === "search" || cursor.kind === "collection" ? cursor.evidenceLimit === void 0 ? {} : { evidenceLimit: cursor.evidenceLimit } : {},
4815
5694
  ...cursor.kind === "search" || cursor.kind === "collection" ? cursor.sourceContext === void 0 ? {} : { sourceContext: cursor.sourceContext } : {},
@@ -4835,7 +5714,7 @@ var init_next = __esm({
4835
5714
  init_document();
4836
5715
  init_options();
4837
5716
  init_types2();
4838
- init_uri2();
5717
+ init_uri3();
4839
5718
  }
4840
5719
  });
4841
5720
 
@@ -4855,7 +5734,7 @@ var init_root = __esm({
4855
5734
  "src/commands/archive-command/run/root.ts"() {
4856
5735
  "use strict";
4857
5736
  init_support();
4858
- init_uri2();
5737
+ init_uri3();
4859
5738
  }
4860
5739
  });
4861
5740
 
@@ -4868,18 +5747,18 @@ var init_run = __esm({
4868
5747
  init_options();
4869
5748
  init_root();
4870
5749
  init_types2();
4871
- init_uri2();
5750
+ init_uri3();
4872
5751
  }
4873
5752
  });
4874
5753
 
4875
5754
  // src/commands/archive-command/run/scope.ts
4876
5755
  import {
4877
5756
  listChapters as listChapters2,
4878
- parseLocatedWikiGraphUri as parseLocatedWikiGraphUri10,
5757
+ parseLocatedWikiGraphUri as parseLocatedWikiGraphUri3,
4879
5758
  resolveChapterPathReadonly
4880
5759
  } from "wiki-graph-core";
4881
5760
  async function resolveArchiveChapterScope(document, args) {
4882
- const objectUri = parseLocatedWikiGraphUri10(args.archivePath).objectUri;
5761
+ const objectUri = parseLocatedWikiGraphUri3(args.archivePath).objectUri;
4883
5762
  if (objectUri === void 0) {
4884
5763
  return void 0;
4885
5764
  }
@@ -4959,6 +5838,8 @@ import {
4959
5838
  resolveWikiGraphLibrary,
4960
5839
  findArchiveObjects as findArchiveObjects2,
4961
5840
  listArchiveQueryableChapterIds,
5841
+ listArchiveSourceLocators as listArchiveSourceLocators2,
5842
+ isSourceLocatorScopeUri,
4962
5843
  rebuildArchiveSearchIndex,
4963
5844
  WikiGraphArchiveFile as WikiGraphArchiveFile2
4964
5845
  } from "wiki-graph-core";
@@ -5028,6 +5909,32 @@ async function runArchiveCommand(args) {
5028
5909
  await readArchiveDocument(
5029
5910
  getArchivePath(args.archivePath),
5030
5911
  async (document) => {
5912
+ const objectUri = getObjectUri(args.archivePath);
5913
+ if (isSourceLocatorScopeUri(objectUri)) {
5914
+ const context2 = createArchiveOutputContext(args, {
5915
+ continuationKind: "source-locators",
5916
+ targetUri: objectUri
5917
+ });
5918
+ const readPage = async (cursor) => await listArchiveSourceLocators2(document, objectUri, {
5919
+ ...cursor === void 0 ? {} : { cursor },
5920
+ ...args.limit === void 0 ? {} : { limit: args.limit }
5921
+ });
5922
+ if (args.all === true) {
5923
+ await writeAllSourceLocators(
5924
+ readPage,
5925
+ args.cursor,
5926
+ context2,
5927
+ args.format ?? "text"
5928
+ );
5929
+ return;
5930
+ }
5931
+ await writeSourceLocators(
5932
+ await readPage(args.cursor),
5933
+ context2,
5934
+ args.format ?? "text"
5935
+ );
5936
+ return;
5937
+ }
5031
5938
  const scope = await resolveArchiveChapterScope(document, args);
5032
5939
  const scopedArgs = scope === void 0 ? args : { ...args, chapters: scope.chapterIds };
5033
5940
  const context = createArchiveOutputContext(scopedArgs, {
@@ -5207,14 +6114,21 @@ async function runArchiveCommand(args) {
5207
6114
  }
5208
6115
  async function ensureArchiveQueryIndexCache(args) {
5209
6116
  const location = await resolveArchiveRuntimeLocation(args.archivePath);
5210
- await new WikiGraphArchiveFile2(location.archivePath).write(
6117
+ await new WikiGraphArchiveFile2(location.archiveFile).write(
5211
6118
  async (document) => {
5212
6119
  const scopedArgs = await createScopedQueryArgs(document, args);
5213
6120
  const options = scopedArgs.chapters === void 0 ? {} : { chapters: scopedArgs.chapters };
5214
6121
  if (await isArchiveSearchIndexCurrent2(document, options)) {
5215
6122
  return;
5216
6123
  }
5217
- await rebuildArchiveSearchIndex(document, void 0, options);
6124
+ try {
6125
+ await rebuildArchiveSearchIndex(document, void 0, options);
6126
+ } catch (error) {
6127
+ if (isArchiveQueryNotReadyError(error)) {
6128
+ throw createArchiveQueryNotReadyError(args, error.message);
6129
+ }
6130
+ throw error;
6131
+ }
5218
6132
  },
5219
6133
  { searchIndexWritebackPolicy: "cache" }
5220
6134
  );
@@ -5228,12 +6142,37 @@ async function createScopedQueryArgs(document, args) {
5228
6142
  ...scope === void 0 ? {} : { chapters: scope.chapterIds }
5229
6143
  });
5230
6144
  if (queryableChapters.length === 0) {
5231
- throw new Error(
6145
+ throw createArchiveQueryNotReadyError(
6146
+ args,
5232
6147
  "Wiki Graph query is not ready. No chapters in this scope have a current FTS artifact or source embedding artifact."
5233
6148
  );
5234
6149
  }
5235
6150
  return { ...args, chapters: queryableChapters };
5236
6151
  }
6152
+ function createArchiveQueryNotReadyError(args, reason) {
6153
+ const buildCommand = formatCliCommand([
6154
+ "wikg://local/job",
6155
+ "add",
6156
+ "--input",
6157
+ args.archivePath,
6158
+ "--task",
6159
+ "index-fts"
6160
+ ]);
6161
+ return new Error(
6162
+ [
6163
+ reason,
6164
+ "",
6165
+ "Build local FTS artifacts without provider calls:",
6166
+ ` ${buildCommand}`,
6167
+ "",
6168
+ "Help:",
6169
+ " wg help readiness"
6170
+ ].join("\n")
6171
+ );
6172
+ }
6173
+ function isArchiveQueryNotReadyError(error) {
6174
+ return error instanceof Error && error.name === "ArchiveQueryNotReadyError";
6175
+ }
5237
6176
  function applyChapterScope(args, scope) {
5238
6177
  return scope === void 0 ? args : { ...args, chapters: scope.chapterIds };
5239
6178
  }
@@ -5517,6 +6456,7 @@ var init_archive_command = __esm({
5517
6456
  "use strict";
5518
6457
  init_config();
5519
6458
  init_embedding();
6459
+ init_support();
5520
6460
  init_convert();
5521
6461
  init_create();
5522
6462
  init_inspect();
@@ -5593,12 +6533,12 @@ var init_entry_context = __esm({
5593
6533
  });
5594
6534
 
5595
6535
  // src/runtime/internal-child.ts
5596
- import { spawn } from "child_process";
6536
+ import { spawn as spawn2 } from "child_process";
5597
6537
  import { existsSync as existsSync2 } from "fs";
5598
- import { join as join4, resolve as resolve3 } from "path";
6538
+ import { join as join6, resolve as resolve5 } from "path";
5599
6539
  function spawnInternalChild(kind, options = {}) {
5600
6540
  const command = createInternalChildCommand(kind, options.args ?? []);
5601
- return spawn(command.command, command.args, {
6541
+ return spawn2(command.command, command.args, {
5602
6542
  cwd: getCLICwd(),
5603
6543
  detached: options.detached === true,
5604
6544
  env: createInternalChildEnvironment(),
@@ -5639,8 +6579,8 @@ function createInternalChildCommand(kind, args) {
5639
6579
  if (devProjectRoot !== void 0 && stateDir !== void 0) {
5640
6580
  return {
5641
6581
  args: [
5642
- join4(devProjectRoot, "node_modules", "tsx", "dist", "cli.mjs"),
5643
- join4(devProjectRoot, "packages", "cli", "src", "bin", `${kind}.ts`),
6582
+ join6(devProjectRoot, "node_modules", "tsx", "dist", "cli.mjs"),
6583
+ join6(devProjectRoot, "packages", "cli", "src", "bin", `${kind}.ts`),
5644
6584
  "--wikigraph-internal-child",
5645
6585
  kind,
5646
6586
  "--wikigraph-state-dir",
@@ -5670,8 +6610,8 @@ function createInternalChildEnvironment() {
5670
6610
  }
5671
6611
  function resolveProductionEntryPath(kind) {
5672
6612
  const filename = `${kind}.js`;
5673
- const distDirPath = globalThis.__WIKIGRAPH_CLI_DIST_DIR__ ?? resolve3(getCLICwd(), "packages", "cli", "dist");
5674
- const adjacent = join4(distDirPath, filename);
6613
+ const distDirPath = globalThis.__WIKIGRAPH_CLI_DIST_DIR__ ?? resolve5(getCLICwd(), "packages", "cli", "dist");
6614
+ const adjacent = join6(distDirPath, filename);
5675
6615
  if (existsSync2(adjacent)) {
5676
6616
  return adjacent;
5677
6617
  }
@@ -5703,6 +6643,7 @@ function createQueueAddEstimate(input) {
5703
6643
  target: input.target
5704
6644
  });
5705
6645
  const workChapters = Math.max(0, ...steps.map((step) => step.chapters));
6646
+ const usesProvider = steps.some((step) => step.task !== "index-fts");
5706
6647
  return {
5707
6648
  chapters: input.chapters.length,
5708
6649
  concurrent,
@@ -5710,11 +6651,13 @@ function createQueueAddEstimate(input) {
5710
6651
  performanceHints: createGenerationPerformanceHints({
5711
6652
  chapters: workChapters,
5712
6653
  concurrent,
5713
- hasGenerationWork: steps.length > 0
6654
+ hasJobWork: steps.length > 0,
6655
+ hasRequestWork: usesProvider
5714
6656
  }),
5715
6657
  planning: sumGenerationPlanningCosts(model, steps),
5716
6658
  steps,
5717
6659
  target: input.target,
6660
+ usesProvider,
5718
6661
  words
5719
6662
  };
5720
6663
  }
@@ -5847,7 +6790,7 @@ function sumGenerationPlanningCosts(model, steps) {
5847
6790
  function formatQueueAddEstimateJSON(estimate) {
5848
6791
  return {
5849
6792
  chapters: estimate.chapters,
5850
- concurrent: estimate.concurrent,
6793
+ concurrent: estimate.usesProvider ? estimate.concurrent : { job: estimate.concurrent.job },
5851
6794
  includesPrerequisites: estimate.includesPrerequisites,
5852
6795
  performanceHints: estimate.performanceHints,
5853
6796
  steps: estimate.steps.map((step) => ({
@@ -5862,7 +6805,7 @@ function formatQueueAddEstimateJSON(estimate) {
5862
6805
  tokens: estimate.planning.tokens,
5863
6806
  waitSeconds: estimate.planning.timeSeconds,
5864
6807
  words: estimate.words,
5865
- model: estimate.planning.model
6808
+ ...estimate.usesProvider ? { model: estimate.planning.model } : {}
5866
6809
  };
5867
6810
  }
5868
6811
  function formatQueueAddEstimateLines(estimate) {
@@ -5870,10 +6813,10 @@ function formatQueueAddEstimateLines(estimate) {
5870
6813
  "Estimate:",
5871
6814
  ` Work: ${estimate.target} over ${estimate.chapters} chapter${estimate.chapters === 1 ? "" : "s"} / ${estimate.words} words`,
5872
6815
  ...estimate.includesPrerequisites ? [" Includes prerequisite Reading Graph work where missing."] : [],
5873
- ` Model: ${estimate.planning.model}`,
6816
+ ...estimate.usesProvider ? [` Model: ${estimate.planning.model}`] : [],
5874
6817
  ` Tokens: ${estimate.planning.tokens.input} input / ${estimate.planning.tokens.cacheableInput} cacheable input / ${estimate.planning.tokens.output} output`,
5875
6818
  ` Wait: ${formatGenerationPlanningDuration(estimate.planning.timeSeconds.min)}-${formatGenerationPlanningDuration(estimate.planning.timeSeconds.max)}`,
5876
- ` Current concurrency: job=${estimate.concurrent.job} request=${estimate.concurrent.request}`,
6819
+ ` Current concurrency: job=${estimate.concurrent.job}${estimate.usesProvider ? ` request=${estimate.concurrent.request}` : ""}`,
5877
6820
  ...formatQueuePerformanceHintLines(estimate.performanceHints)
5878
6821
  ];
5879
6822
  }
@@ -5897,9 +6840,19 @@ var init_estimate = __esm({
5897
6840
  });
5898
6841
 
5899
6842
  // src/commands/queue/output.ts
6843
+ import {
6844
+ formatLocatedChapterUri as formatLocatedChapterUri2,
6845
+ listChapters as listChapters3,
6846
+ WikiGraphArchiveFile as WikiGraphArchiveFile3
6847
+ } from "wiki-graph-core";
5900
6848
  async function writeJobList(jobs, options) {
6849
+ const chapters = await resolveJobChapters(jobs);
5901
6850
  if (options.json) {
5902
- await writeTextToStdout(formatCLIJSON({ items: jobs.map(formatJobJSON) }));
6851
+ await writeTextToStdout(
6852
+ formatCLIJSON({
6853
+ items: jobs.map((job) => formatJobJSON(job, chapters.get(job.jobId)))
6854
+ })
6855
+ );
5903
6856
  return;
5904
6857
  }
5905
6858
  if (jobs.length === 0) {
@@ -5909,57 +6862,65 @@ async function writeJobList(jobs, options) {
5909
6862
  await writeTextToStdout(
5910
6863
  `${formatJobListHeader()}
5911
6864
  ${jobs.map(
5912
- (job) => `${job.jobId.slice(0, 8).padEnd(8)} ${job.state.padEnd(9)} ${(job.currentStep ?? "-").padEnd(7)} ${job.target.padEnd(7)} ${job.chapterId.toString().padStart(7)} ${formatArchiveName(job.archivePath)}`
6865
+ (job) => `${job.jobId.slice(0, 8).padEnd(8)} ${job.state.padEnd(9)} ${(job.currentStep ?? "-").padEnd(7)} ${job.target.padEnd(7)} ${formatJobChapterListLabel(job, chapters.get(job.jobId))}`
5913
6866
  ).join("\n")}
5914
6867
  `
5915
6868
  );
5916
6869
  }
5917
6870
  function formatJobListHeader() {
5918
- return `${"JOB".padEnd(8)} ${"STATE".padEnd(9)} ${"STEP".padEnd(7)} ${"TARGET".padEnd(7)} ${"CHAPTER".padStart(7)} ARCHIVE`;
6871
+ return `${"JOB".padEnd(8)} ${"STATE".padEnd(9)} ${"STEP".padEnd(7)} ${"TARGET".padEnd(7)} CHAPTER`;
5919
6872
  }
5920
6873
  async function writeJobStatus(job, options) {
6874
+ const chapter = await resolveJobChapter(job);
5921
6875
  if (options.json) {
5922
- await writeTextToStdout(formatCLIJSON(formatJobJSON(job)));
6876
+ await writeTextToStdout(formatCLIJSON(formatJobJSON(job, chapter)));
5923
6877
  return;
5924
6878
  }
5925
6879
  await writeTextToStdout(
5926
6880
  [
5927
6881
  `Job: ${job.jobId}`,
5928
6882
  `State: ${job.state}`,
5929
- `Archive: ${job.archivePath}`,
5930
- `Chapter: ${job.chapterId}`,
6883
+ `Archive: ${requireJobResourcePath(job, "archive", "archivePath")}`,
6884
+ `Chapter: ${formatJobChapterLabel(job, chapter)}`,
6885
+ ...chapter === void 0 ? [] : [`Chapter URI: ${chapter.locatedUri}`],
5931
6886
  `Target: ${job.target}`,
5932
6887
  `Step: ${job.currentStep ?? "-"}`,
5933
- `Workspace: ${job.workspacePath}`,
5934
- `Cache: ${job.cachePath}`,
5935
- `Logs: ${job.logPath}`,
6888
+ `Workspace: ${getJobResourcePath(job, "workspace", "workspacePath") ?? "-"}`,
6889
+ `Cache: ${getJobResourcePath(job, "cache", "cachePath") ?? "-"}`,
6890
+ `Logs: ${getJobResourcePath(job, "log", "logPath") ?? "-"}`,
5936
6891
  ...job.errorJSON === void 0 ? [] : [`Error: ${job.errorJSON}`]
5937
6892
  ].join("\n") + "\n"
5938
6893
  );
5939
6894
  }
5940
- function formatJobJSON(job) {
6895
+ function formatJobJSON(job, chapter) {
5941
6896
  return {
5942
6897
  archiveKey: job.archiveKey,
5943
- archivePath: job.archivePath,
5944
- cachePath: job.cachePath,
6898
+ archivePath: getJobResourcePath(job, "archive", "archivePath"),
6899
+ cachePath: getJobResourcePath(job, "cache", "cachePath"),
5945
6900
  chapterId: job.chapterId,
6901
+ ...chapter === void 0 ? {} : {
6902
+ chapter: {
6903
+ locatedUri: chapter.locatedUri,
6904
+ title: chapter.title,
6905
+ uri: chapter.uri
6906
+ }
6907
+ },
5946
6908
  createdAt: job.createdAt,
5947
6909
  ...job.currentStep === void 0 ? {} : { currentStep: job.currentStep },
5948
6910
  ...job.errorJSON === void 0 ? {} : { errorJSON: job.errorJSON },
5949
- eventsPath: job.eventsPath,
6911
+ eventsPath: getJobResourcePath(job, "events", "eventsPath"),
5950
6912
  ...job.finishedAt === void 0 ? {} : { finishedAt: job.finishedAt },
5951
6913
  jobId: job.jobId,
5952
- logPath: job.logPath,
6914
+ logPath: getJobResourcePath(job, "log", "logPath"),
5953
6915
  ...job.llmJSON === void 0 ? {} : { llm: formatJobLLMJSON(job.llmJSON) },
5954
6916
  ...job.ownerId === void 0 ? {} : { ownerId: job.ownerId },
5955
- ...job.ownerPid === void 0 ? {} : { ownerPid: job.ownerPid },
5956
6917
  ...job.prompt === void 0 ? {} : { prompt: job.prompt },
5957
6918
  queueRank: job.queueRank,
5958
6919
  state: job.state,
5959
6920
  ...job.readingSummaryStartedAt === void 0 ? {} : { readingSummaryStartedAt: job.readingSummaryStartedAt },
5960
6921
  target: job.target,
5961
6922
  updatedAt: job.updatedAt,
5962
- workspacePath: job.workspacePath
6923
+ workspacePath: getJobResourcePath(job, "workspace", "workspacePath")
5963
6924
  };
5964
6925
  }
5965
6926
  function formatJobQueuedNotice(job) {
@@ -6003,10 +6964,11 @@ function isRecord(value) {
6003
6964
  return value !== null && typeof value === "object" && !Array.isArray(value);
6004
6965
  }
6005
6966
  async function writeJobSummary(job, options = { json: false }) {
6967
+ const chapter = options.chapter === void 0 ? await resolveJobChapter(job) : createJobChapterReference(job, options.chapter);
6006
6968
  if (options.json) {
6007
6969
  await writeTextToStdout(
6008
6970
  formatCLIJSON({
6009
- ...formatJobJSON(job),
6971
+ ...formatJobJSON(job, chapter),
6010
6972
  ...formatJobQueuedNotice(job) === void 0 ? {} : { notice: formatJobQueuedNotice(job) },
6011
6973
  ...options.estimate === void 0 ? {} : { estimate: formatQueueAddEstimateJSON(options.estimate) },
6012
6974
  ...options.watch === true ? {
@@ -6021,7 +6983,8 @@ async function writeJobSummary(job, options = { json: false }) {
6021
6983
  }
6022
6984
  await writeTextToStdout(
6023
6985
  [
6024
- `Job ${job.jobId} ${job.state} ${job.target} chapter ${job.chapterId} ${job.archivePath}`,
6986
+ `Job ${job.jobId} ${job.state} ${job.target} chapter ${formatJobChapterLabel(job, chapter)}`,
6987
+ ...chapter === void 0 ? [] : [`Chapter URI: ${chapter.locatedUri}`],
6025
6988
  ...formatJobQueuedNotice(job) === void 0 ? [] : [formatJobQueuedNotice(job)],
6026
6989
  ...options.watch === true ? [
6027
6990
  `Watch: ${formatCliCommand([
@@ -6035,12 +6998,29 @@ async function writeJobSummary(job, options = { json: false }) {
6035
6998
  );
6036
6999
  }
6037
7000
  async function writeArchiveAddSummary(input) {
7001
+ const jobsCommand = formatCliCommand(["wikg://local/job", "--json"]);
7002
+ const verifyCommand = formatCliCommand([
7003
+ formatWikiGraphCommandUri(input.archivePath),
7004
+ "inspect"
7005
+ ]);
6038
7006
  if (input.json) {
6039
7007
  await writeTextToStdout(
6040
7008
  formatCLIJSON({
6041
- created: input.created.map((item) => formatJobJSON(item.job)),
7009
+ created: input.created.map(
7010
+ (item) => formatJobJSON(
7011
+ item.job,
7012
+ createJobChapterReference(item.job, item.chapter)
7013
+ )
7014
+ ),
6042
7015
  ...input.estimate === void 0 ? {} : { estimate: formatQueueAddEstimateJSON(input.estimate) },
6043
- skipped: input.skipped
7016
+ ...input.created.length === 0 ? {} : { jobsCommand, verifyCommand },
7017
+ skipped: input.skipped.map((item) => ({
7018
+ chapterId: item.chapter.chapterId,
7019
+ chapter: formatChapterJSON(
7020
+ createJobChapterReferenceFromPath(input.archivePath, item.chapter)
7021
+ ),
7022
+ reason: item.reason
7023
+ }))
6044
7024
  })
6045
7025
  );
6046
7026
  return;
@@ -6051,38 +7031,129 @@ async function writeArchiveAddSummary(input) {
6051
7031
  ];
6052
7032
  for (const job of input.created) {
6053
7033
  lines.push(
6054
- `Job ${job.job.jobId} ${job.job.state} ${job.job.target} chapter ${job.job.chapterId}`
7034
+ `Job ${job.job.jobId} ${job.job.state} ${job.job.target} chapter ${formatChapterLabel(job.chapter)}`,
7035
+ `Chapter URI: ${createJobChapterReference(job.job, job.chapter).locatedUri}`
6055
7036
  );
6056
7037
  }
6057
7038
  for (const skipped of input.skipped) {
6058
- lines.push(`Skipped chapter ${skipped.chapterId}: ${skipped.reason}`);
7039
+ lines.push(
7040
+ `Skipped chapter ${formatChapterLabel(skipped.chapter)}: ${skipped.reason}`
7041
+ );
6059
7042
  }
6060
7043
  if (input.estimate !== void 0) {
6061
7044
  lines.push("", ...formatQueueAddEstimateLines(input.estimate));
6062
7045
  }
7046
+ if (input.created.length > 0) {
7047
+ lines.push(
7048
+ "",
7049
+ `Jobs: ${jobsCommand}`,
7050
+ `Verify after the jobs finish: ${verifyCommand}`
7051
+ );
7052
+ }
6063
7053
  await writeTextToStdout(`${lines.join("\n")}
6064
7054
  `);
6065
7055
  }
6066
- function formatArchiveName(path) {
6067
- return path.split(/[\\/]/u).at(-1) ?? path;
7056
+ function formatJobChapterLabel(job, chapter) {
7057
+ return chapter === void 0 ? `[unavailable; internal id ${job.chapterId}]` : formatChapterLabel(chapter);
7058
+ }
7059
+ function formatJobChapterListLabel(job, chapter) {
7060
+ return chapter === void 0 ? `[unavailable; internal id ${job.chapterId}]` : `${chapter.title ?? "[untitled]"} ${chapter.locatedUri}`;
7061
+ }
7062
+ function formatChapterLabel(chapter) {
7063
+ return chapter.title === null || chapter.title === void 0 ? chapter.uri : `${JSON.stringify(chapter.title)} (${chapter.uri})`;
7064
+ }
7065
+ function formatChapterJSON(chapter) {
7066
+ return {
7067
+ locatedUri: chapter.locatedUri,
7068
+ title: chapter.title,
7069
+ uri: chapter.uri
7070
+ };
7071
+ }
7072
+ function createJobChapterReference(job, chapter) {
7073
+ return createJobChapterReferenceFromPath(
7074
+ requireJobResourcePath(job, "archive", "archivePath"),
7075
+ chapter
7076
+ );
7077
+ }
7078
+ function createJobChapterReferenceFromPath(archivePath, chapter) {
7079
+ return {
7080
+ locatedUri: formatLocatedChapterUri2(archivePath, chapter.path),
7081
+ title: chapter.title,
7082
+ uri: chapter.uri
7083
+ };
7084
+ }
7085
+ async function resolveJobChapters(jobs) {
7086
+ const jobsByArchive = /* @__PURE__ */ new Map();
7087
+ for (const job of jobs) {
7088
+ const archivePath = requireJobResourcePath(job, "archive", "archivePath");
7089
+ const grouped = jobsByArchive.get(archivePath) ?? [];
7090
+ grouped.push(job);
7091
+ jobsByArchive.set(archivePath, grouped);
7092
+ }
7093
+ const entries = (await Promise.all(
7094
+ [...jobsByArchive].map(async ([archivePath, archiveJobs]) => {
7095
+ try {
7096
+ let chapters = [];
7097
+ await new WikiGraphArchiveFile3(
7098
+ new NodeFile(archivePath)
7099
+ ).readDocument(async (document) => {
7100
+ chapters = await listChapters3(document);
7101
+ });
7102
+ const chaptersById = new Map(
7103
+ chapters.map((chapter) => [chapter.chapterId, chapter])
7104
+ );
7105
+ return archiveJobs.flatMap((job) => {
7106
+ const chapter = chaptersById.get(job.chapterId);
7107
+ return chapter === void 0 ? [] : [
7108
+ [
7109
+ job.jobId,
7110
+ createJobChapterReferenceFromPath(archivePath, chapter)
7111
+ ]
7112
+ ];
7113
+ });
7114
+ } catch {
7115
+ return [];
7116
+ }
7117
+ })
7118
+ )).flat();
7119
+ return new Map(entries);
7120
+ }
7121
+ async function resolveJobChapter(job) {
7122
+ return (await resolveJobChapters([job])).get(job.jobId);
7123
+ }
7124
+ function getJobResourcePath(job, resourceKey, legacyKey) {
7125
+ const record = job;
7126
+ const resource = record[resourceKey];
7127
+ if (resource !== void 0) {
7128
+ return getNodeResourcePath(resource);
7129
+ }
7130
+ const legacyPath = record[legacyKey];
7131
+ if (typeof legacyPath === "string") return legacyPath;
7132
+ return void 0;
7133
+ }
7134
+ function requireJobResourcePath(job, resourceKey, legacyKey) {
7135
+ const path = getJobResourcePath(job, resourceKey, legacyKey);
7136
+ if (path !== void 0) return path;
7137
+ throw new TypeError(`Build job is missing ${resourceKey}`);
6068
7138
  }
6069
7139
  var init_output = __esm({
6070
7140
  "src/commands/queue/output.ts"() {
6071
7141
  "use strict";
6072
7142
  init_support();
6073
7143
  init_estimate();
7144
+ init_node_platform();
6074
7145
  }
6075
7146
  });
6076
7147
 
6077
7148
  // src/commands/queue/add.ts
6078
7149
  import {
6079
7150
  addBuildJob,
6080
- listChapters as listChapters3
7151
+ listChapters as listChapters4
6081
7152
  } from "wiki-graph-core";
6082
- import { WikiGraphArchiveFile as WikiGraphArchiveFile3 } from "wiki-graph-core";
7153
+ import { WikiGraphArchiveFile as WikiGraphArchiveFile4 } from "wiki-graph-core";
6083
7154
  async function addChapterJob(args, chapterId) {
6084
7155
  return await addBuildJob({
6085
- archivePath: args.archivePath,
7156
+ archive: new NodeFile(args.archivePath),
6086
7157
  boost: args.boost ?? false,
6087
7158
  chapterId,
6088
7159
  ...args.llmJSON === void 0 ? {} : { llmJSON: args.llmJSON },
@@ -6093,16 +7164,16 @@ async function addChapterJob(args, chapterId) {
6093
7164
  async function addArchiveJobs(args, config) {
6094
7165
  const created = [];
6095
7166
  const skipped = [];
6096
- await new WikiGraphArchiveFile3(args.archivePath).readDocument(
7167
+ await new WikiGraphArchiveFile4(new NodeFile(args.archivePath)).readDocument(
6097
7168
  async (document) => {
6098
7169
  const chapterIdSet = args.chapterIds === void 0 ? void 0 : new Set(args.chapterIds);
6099
- for (const chapter of await listChapters3(document)) {
7170
+ for (const chapter of await listChapters4(document)) {
6100
7171
  if (chapterIdSet !== void 0 && !chapterIdSet.has(chapter.chapterId)) {
6101
7172
  continue;
6102
7173
  }
6103
7174
  if (chapter.stage === "planned") {
6104
7175
  skipped.push({
6105
- chapterId: chapter.chapterId,
7176
+ chapter,
6106
7177
  reason: "planned"
6107
7178
  });
6108
7179
  continue;
@@ -6112,7 +7183,7 @@ async function addArchiveJobs(args, config) {
6112
7183
  const summary = await document.readSummary(chapter.chapterId);
6113
7184
  if (summary === void 0 || summary.trim() === "") {
6114
7185
  skipped.push({
6115
- chapterId: chapter.chapterId,
7186
+ chapter,
6116
7187
  reason: "missing summary"
6117
7188
  });
6118
7189
  continue;
@@ -6128,7 +7199,7 @@ async function addArchiveJobs(args, config) {
6128
7199
  );
6129
7200
  if (artifact?.sourceRevision !== revision) {
6130
7201
  skipped.push({
6131
- chapterId: chapter.chapterId,
7202
+ chapter,
6132
7203
  reason: "missing current FTS index artifact"
6133
7204
  });
6134
7205
  continue;
@@ -6141,7 +7212,7 @@ async function addArchiveJobs(args, config) {
6141
7212
  });
6142
7213
  } catch (error) {
6143
7214
  skipped.push({
6144
- chapterId: chapter.chapterId,
7215
+ chapter,
6145
7216
  reason: error instanceof Error ? error.message : String(error)
6146
7217
  });
6147
7218
  }
@@ -6149,6 +7220,7 @@ async function addArchiveJobs(args, config) {
6149
7220
  }
6150
7221
  );
6151
7222
  await writeArchiveAddSummary({
7223
+ archivePath: args.archivePath,
6152
7224
  created,
6153
7225
  ...created.length === 0 ? {} : {
6154
7226
  estimate: createQueueAddEstimate({
@@ -6163,9 +7235,9 @@ async function addArchiveJobs(args, config) {
6163
7235
  }
6164
7236
  async function assertQueueAddReady(args, chapterId) {
6165
7237
  let chapter;
6166
- await new WikiGraphArchiveFile3(args.archivePath).readDocument(
7238
+ await new WikiGraphArchiveFile4(new NodeFile(args.archivePath)).readDocument(
6167
7239
  async (document) => {
6168
- chapter = (await listChapters3(document)).find(
7240
+ chapter = (await listChapters4(document)).find(
6169
7241
  (entry) => entry.chapterId === chapterId
6170
7242
  );
6171
7243
  }
@@ -6173,18 +7245,20 @@ async function assertQueueAddReady(args, chapterId) {
6173
7245
  if (chapter === void 0) {
6174
7246
  throw new Error(`Chapter ${chapterId} does not exist.`);
6175
7247
  }
6176
- await new WikiGraphArchiveFile3(args.archivePath).read(async (digest) => {
6177
- if (await digest.readChapterStage(chapterId) === "planned") {
6178
- throw new Error(
6179
- `Chapter ${chapter.uri} is planned. Set source before queueing a build job.`
6180
- );
7248
+ await new WikiGraphArchiveFile4(new NodeFile(args.archivePath)).read(
7249
+ async (digest) => {
7250
+ if (await digest.readChapterStage(chapterId) === "planned") {
7251
+ throw new Error(
7252
+ `Chapter ${chapter.uri} is planned. Set source before queueing a build job.`
7253
+ );
7254
+ }
6181
7255
  }
6182
- });
7256
+ );
6183
7257
  const target = args.target ?? "reading-summary";
6184
7258
  if (target !== "index-embedding-summary" && target !== "knowledge-graph" && target !== "reading-graph") {
6185
7259
  return;
6186
7260
  }
6187
- await new WikiGraphArchiveFile3(args.archivePath).readDocument(
7261
+ await new WikiGraphArchiveFile4(new NodeFile(args.archivePath)).readDocument(
6188
7262
  async (document) => {
6189
7263
  if (target === "index-embedding-summary") {
6190
7264
  const summary = await document.readSummary(chapterId);
@@ -6208,9 +7282,9 @@ async function assertQueueAddReady(args, chapterId) {
6208
7282
  }
6209
7283
  async function readQueueAddChapter(args, chapterId) {
6210
7284
  let matched;
6211
- await new WikiGraphArchiveFile3(args.archivePath).readDocument(
7285
+ await new WikiGraphArchiveFile4(new NodeFile(args.archivePath)).readDocument(
6212
7286
  async (document) => {
6213
- matched = (await listChapters3(document)).find(
7287
+ matched = (await listChapters4(document)).find(
6214
7288
  (chapter) => chapter.chapterId === chapterId
6215
7289
  );
6216
7290
  }
@@ -6244,6 +7318,7 @@ var init_add = __esm({
6244
7318
  init_internal_child();
6245
7319
  init_estimate();
6246
7320
  init_output();
7321
+ init_node_platform();
6247
7322
  }
6248
7323
  });
6249
7324
 
@@ -6252,7 +7327,7 @@ var chapter_exports = {};
6252
7327
  __export(chapter_exports, {
6253
7328
  runArchiveChapterCommand: () => runArchiveChapterCommand
6254
7329
  });
6255
- import { readFile } from "fs/promises";
7330
+ import { readFile as readFile2 } from "fs/promises";
6256
7331
  import { Readable } from "stream";
6257
7332
  import {
6258
7333
  addBuildJob as addBuildJob2,
@@ -6260,8 +7335,9 @@ import {
6260
7335
  applyChapterTree,
6261
7336
  assertNoActiveBuildJobConflicts,
6262
7337
  assertNoActiveBuildJobs,
7338
+ formatLocatedChapterUri as formatLocatedChapterUri3,
6263
7339
  getChapterTree,
6264
- listChapters as listChapters4,
7340
+ listChapters as listChapters5,
6265
7341
  moveChapter,
6266
7342
  parseChapterTreeInput,
6267
7343
  removeChapter,
@@ -6269,9 +7345,10 @@ import {
6269
7345
  resolveChapterPathReadonly as resolveChapterPathReadonly2,
6270
7346
  setChapterSource,
6271
7347
  setChapterSummary,
6272
- setChapterTitle
7348
+ setChapterTitle,
7349
+ parseSourceTextJsonl,
7350
+ WikiGraphArchiveFile as WikiGraphArchiveFile5
6273
7351
  } from "wiki-graph-core";
6274
- import { WikiGraphArchiveFile as WikiGraphArchiveFile4 } from "wiki-graph-core";
6275
7352
  async function runArchiveChapterCommand(args) {
6276
7353
  switch (args.action) {
6277
7354
  case "add":
@@ -6281,7 +7358,7 @@ async function runArchiveChapterCommand(args) {
6281
7358
  args.parentChapterPath
6282
7359
  );
6283
7360
  await assertNoActiveBuildJobConflicts({
6284
- archivePath: args.path,
7361
+ archive: new NodeFile(args.path),
6285
7362
  operation: "Adding chapter",
6286
7363
  scope: { kind: "archive" }
6287
7364
  });
@@ -6296,13 +7373,15 @@ async function runArchiveChapterCommand(args) {
6296
7373
  Readable.from([await readRequiredSourceText(args)])
6297
7374
  );
6298
7375
  }
6299
- await writeChapterDetails(details, args.json ?? false);
7376
+ await writeChapterDetails(details, args.json ?? false, {
7377
+ locatedUri: formatChapterCommandUri(args.path, details.path)
7378
+ });
6300
7379
  });
6301
7380
  return;
6302
7381
  case "list":
6303
7382
  await readArchiveDocument(args.path, async (document) => {
6304
7383
  await writeChapterList(
6305
- await listChapters4(document),
7384
+ await listChapters5(document),
6306
7385
  args.json ?? false
6307
7386
  );
6308
7387
  });
@@ -6322,17 +7401,30 @@ async function runArchiveChapterCommand(args) {
6322
7401
  });
6323
7402
  return;
6324
7403
  case "build-index-artifact": {
6325
- const chapterId = await readArchiveDocument(
6326
- args.path,
6327
- async (document) => await resolveRequiredChapterPath(document, args.chapterPath)
6328
- );
7404
+ const chapter = await readArchiveDocument(args.path, async (document) => {
7405
+ const chapterId = await resolveRequiredChapterPath(
7406
+ document,
7407
+ args.chapterPath
7408
+ );
7409
+ const matched = (await listChapters5(document)).find(
7410
+ (entry) => entry.chapterId === chapterId
7411
+ );
7412
+ if (matched === void 0) {
7413
+ throw new Error(`Chapter internal id ${chapterId} does not exist.`);
7414
+ }
7415
+ return matched;
7416
+ });
6329
7417
  const job = await addBuildJob2({
6330
- archivePath: args.path,
6331
- chapterId,
7418
+ archive: new NodeFile(args.path),
7419
+ chapterId: chapter.chapterId,
6332
7420
  target: requireIndexArtifactTarget(args.indexArtifactTarget)
6333
7421
  });
6334
7422
  tryStartQueueWorker();
6335
- await writeJobSummary(job, { json: args.json ?? false, watch: true });
7423
+ await writeJobSummary(job, {
7424
+ chapter,
7425
+ json: args.json ?? false,
7426
+ watch: true
7427
+ });
6336
7428
  return;
6337
7429
  }
6338
7430
  case "delete-index-artifact":
@@ -6378,7 +7470,7 @@ async function runArchiveChapterCommand(args) {
6378
7470
  args.parentChapterPath
6379
7471
  );
6380
7472
  await assertNoActiveBuildJobConflicts({
6381
- archivePath: args.path,
7473
+ archive: new NodeFile(args.path),
6382
7474
  operation: "Moving chapter",
6383
7475
  scope: { kind: "archive" }
6384
7476
  });
@@ -6400,7 +7492,7 @@ async function runArchiveChapterCommand(args) {
6400
7492
  args.chapterPath
6401
7493
  );
6402
7494
  await assertNoActiveBuildJobConflicts({
6403
- archivePath: args.path,
7495
+ archive: new NodeFile(args.path),
6404
7496
  operation: "Removing chapter",
6405
7497
  scope: { kind: "archive" }
6406
7498
  });
@@ -6444,14 +7536,17 @@ async function runArchiveChapterCommand(args) {
6444
7536
  args.chapterPath
6445
7537
  );
6446
7538
  await assertNoActiveBuildJobs({
6447
- archivePath: args.path,
7539
+ archive: new NodeFile(args.path),
6448
7540
  chapterIds: [chapterId],
6449
7541
  operation: "Setting chapter source"
6450
7542
  });
7543
+ const sourceText = await readRequiredSourceText(args);
7544
+ const parsed = args.inputFormat === "jsonl" ? parseSourceTextJsonl(sourceText) : void 0;
6451
7545
  const details = await setChapterSource(
6452
7546
  document,
6453
7547
  chapterId,
6454
- Readable.from([await readRequiredSourceText(args)])
7548
+ Readable.from([parsed?.text ?? sourceText]),
7549
+ parsed === void 0 ? {} : { provenance: parsed.provenance }
6455
7550
  );
6456
7551
  await writeChapterDetails(details, args.json ?? false);
6457
7552
  });
@@ -6463,7 +7558,7 @@ async function runArchiveChapterCommand(args) {
6463
7558
  args.chapterPath
6464
7559
  );
6465
7560
  await assertNoActiveBuildJobs({
6466
- archivePath: args.path,
7561
+ archive: new NodeFile(args.path),
6467
7562
  chapterIds: [chapterId],
6468
7563
  operation: "Setting chapter summary",
6469
7564
  requiresTarget: "reading-summary"
@@ -6483,7 +7578,7 @@ async function runArchiveChapterCommand(args) {
6483
7578
  args.chapterPath
6484
7579
  );
6485
7580
  await assertNoActiveBuildJobs({
6486
- archivePath: args.path,
7581
+ archive: new NodeFile(args.path),
6487
7582
  chapterIds: [chapterId],
6488
7583
  operation: "Setting chapter title"
6489
7584
  });
@@ -6502,7 +7597,7 @@ async function runArchiveChapterCommand(args) {
6502
7597
  async (document) => {
6503
7598
  if (args.dryRun !== true) {
6504
7599
  await assertNoActiveBuildJobConflicts({
6505
- archivePath: args.path,
7600
+ archive: new NodeFile(args.path),
6506
7601
  operation: "Changing chapter tree",
6507
7602
  scope: { kind: "archive" }
6508
7603
  });
@@ -6599,7 +7694,7 @@ function formatIndexArtifactKind(kind) {
6599
7694
  async function runEditableCommand(path, operation, options = {}) {
6600
7695
  if (options.markLibraryDirty === false) {
6601
7696
  const location = await resolveArchiveRuntimeLocation(path);
6602
- await new WikiGraphArchiveFile4(location.archivePath).write(operation);
7697
+ await new WikiGraphArchiveFile5(location.archiveFile).write(operation);
6603
7698
  return;
6604
7699
  }
6605
7700
  await writeArchiveDocument(path, operation);
@@ -6619,7 +7714,7 @@ async function readContentText(args) {
6619
7714
  return content;
6620
7715
  }
6621
7716
  if (args.inputPath !== void 0) {
6622
- return await readFile(args.inputPath, "utf8");
7717
+ return await readFile2(args.inputPath, "utf8");
6623
7718
  }
6624
7719
  throw new Error(
6625
7720
  "Missing input. Pass a positional value, use --input <path>, or use --input - for stdin."
@@ -6629,18 +7724,19 @@ async function readRequiredSourceText(args) {
6629
7724
  const content = await readContentText(args);
6630
7725
  if (content.trim() === "") {
6631
7726
  throw new Error(
6632
- "Source input is empty. Pass non-empty text with --input <path> or --input -."
7727
+ "Source input is empty. Pass non-empty positional text, use --input <path>, or use --input - for stdin."
6633
7728
  );
6634
7729
  }
6635
7730
  return content;
6636
7731
  }
6637
- async function writeChapterDetails(details, json) {
7732
+ async function writeChapterDetails(details, json, options = {}) {
6638
7733
  if (json) {
6639
7734
  await writeTextToStdout(
6640
7735
  formatCLIJSON({
6641
7736
  childCount: details.childCount,
6642
7737
  graphReady: details.graphReady,
6643
7738
  hasSummary: details.hasSummary,
7739
+ ...options.locatedUri === void 0 ? {} : { locatedUri: options.locatedUri },
6644
7740
  sourceUnits: details.fragmentCount,
6645
7741
  stage: formatStage(details.stage),
6646
7742
  title: details.title,
@@ -6651,6 +7747,7 @@ async function writeChapterDetails(details, json) {
6651
7747
  }
6652
7748
  const lines = [
6653
7749
  `Chapter: ${details.uri}`,
7750
+ ...options.locatedUri === void 0 ? [] : [`Located URI: ${options.locatedUri}`],
6654
7751
  `Title: ${details.title ?? "[untitled]"}`,
6655
7752
  `Stage: ${formatStage(details.stage)}`,
6656
7753
  `Source Units: ${details.fragmentCount}`,
@@ -6661,6 +7758,18 @@ async function writeChapterDetails(details, json) {
6661
7758
  await writeTextToStdout(`${lines.join("\n")}
6662
7759
  `);
6663
7760
  }
7761
+ function formatChapterCommandUri(archiveLocator, chapterPath) {
7762
+ if (archiveLocator.startsWith("wikg://lib/")) {
7763
+ return `${archiveLocator.replace(/\/+$/u, "")}/chapter/${chapterPath}`;
7764
+ }
7765
+ if (archiveLocator.startsWith("wikg://")) {
7766
+ const parsed = parseLocatedWikiGraphUri(archiveLocator);
7767
+ if (parsed.archivePath !== void 0) {
7768
+ return formatLocatedChapterUri3(parsed.archivePath, chapterPath);
7769
+ }
7770
+ }
7771
+ return formatLocatedChapterUri3(archiveLocator, chapterPath);
7772
+ }
6664
7773
  async function writeChapterList(entries, json) {
6665
7774
  if (json) {
6666
7775
  await writeTextToStdout(
@@ -6723,9 +7832,9 @@ async function writeChapterTreeApplyResult(result, dryRun) {
6723
7832
  `Move ${move.oldUri} [index ${move.oldIndex}] -> ${move.newUri} [index ${move.newIndex}]`
6724
7833
  );
6725
7834
  }
6726
- for (const rename2 of result.renamed) {
7835
+ for (const rename3 of result.renamed) {
6727
7836
  lines.push(
6728
- `Rename ${rename2.uri}: ${formatTitle(rename2.oldTitle)} -> ${formatTitle(rename2.newTitle)}`
7837
+ `Rename ${rename3.uri}: ${formatTitle(rename3.oldTitle)} -> ${formatTitle(rename3.newTitle)}`
6729
7838
  );
6730
7839
  }
6731
7840
  await writeTextToStdout(`${lines.join("\n")}
@@ -6750,20 +7859,20 @@ async function assertResetAllowed(archivePath, chapterId, stage) {
6750
7859
  switch (stage) {
6751
7860
  case "planned":
6752
7861
  await assertNoActiveBuildJobs({
6753
- archivePath,
7862
+ archive: new NodeFile(archivePath),
6754
7863
  chapterIds: [chapterId],
6755
7864
  operation: "Resetting chapter to planned"
6756
7865
  });
6757
7866
  return;
6758
7867
  case "sourced":
6759
7868
  await assertNoActiveBuildJobs({
6760
- archivePath,
7869
+ archive: new NodeFile(archivePath),
6761
7870
  chapterIds: [chapterId],
6762
7871
  operation: "Resetting chapter graph",
6763
7872
  requiresTarget: "reading-graph"
6764
7873
  });
6765
7874
  await assertNoActiveBuildJobs({
6766
- archivePath,
7875
+ archive: new NodeFile(archivePath),
6767
7876
  chapterIds: [chapterId],
6768
7877
  operation: "Resetting chapter summary",
6769
7878
  requiresTarget: "reading-summary"
@@ -6771,7 +7880,7 @@ async function assertResetAllowed(archivePath, chapterId, stage) {
6771
7880
  return;
6772
7881
  case "graphed":
6773
7882
  await assertNoActiveBuildJobs({
6774
- archivePath,
7883
+ archive: new NodeFile(archivePath),
6775
7884
  chapterIds: [chapterId],
6776
7885
  operation: "Resetting chapter summary",
6777
7886
  requiresTarget: "reading-summary"
@@ -6782,12 +7891,13 @@ async function assertResetAllowed(archivePath, chapterId, stage) {
6782
7891
  var init_chapter = __esm({
6783
7892
  "src/commands/archive-command/chapter.ts"() {
6784
7893
  "use strict";
7894
+ init_node_platform();
6785
7895
  init_support();
6786
7896
  init_support();
6787
7897
  init_add();
6788
7898
  init_output();
6789
7899
  init_document();
6790
- init_uri2();
7900
+ init_uri3();
6791
7901
  }
6792
7902
  });
6793
7903
 
@@ -6802,7 +7912,7 @@ import {
6802
7912
  listArchiveQueryableChapterIds as listArchiveQueryableChapterIds2,
6803
7913
  readSearchIndexCapabilityStatus,
6804
7914
  rebuildArchiveSearchIndex as rebuildArchiveSearchIndex2,
6805
- WikiGraphArchiveFile as WikiGraphArchiveFile5
7915
+ WikiGraphArchiveFile as WikiGraphArchiveFile6
6806
7916
  } from "wiki-graph-core";
6807
7917
  async function runArchiveIndexCommand(args) {
6808
7918
  switch (args.action) {
@@ -6819,7 +7929,7 @@ async function runArchiveIndexCommand(args) {
6819
7929
  }
6820
7930
  async function readIndexCache(args) {
6821
7931
  const location = await resolveArchiveRuntimeLocation(args.archivePath);
6822
- await new WikiGraphArchiveFile5(location.archivePath).readDocument(
7932
+ await new WikiGraphArchiveFile6(location.archiveFile).readDocument(
6823
7933
  async (document) => {
6824
7934
  await writeIndexOutput(args, {
6825
7935
  capabilities: await readSearchIndexCapabilityStatus(document),
@@ -6834,7 +7944,7 @@ async function syncIndexCache(args) {
6834
7944
  jsonl: args.jsonl ?? false,
6835
7945
  throttleMs: INDEX_PROGRESS_OUTPUT_INTERVAL_MS
6836
7946
  });
6837
- await new WikiGraphArchiveFile5(location.archivePath).write(
7947
+ await new WikiGraphArchiveFile6(location.archiveFile).write(
6838
7948
  async (document) => {
6839
7949
  await writer.write({
6840
7950
  json: { type: "started" },
@@ -6893,7 +8003,7 @@ async function syncIndexCache(args) {
6893
8003
  }
6894
8004
  async function cleanIndexCache(args) {
6895
8005
  const location = await resolveArchiveRuntimeLocation(args.archivePath);
6896
- await new WikiGraphArchiveFile5(location.archivePath).write(
8006
+ await new WikiGraphArchiveFile6(location.archiveFile).write(
6897
8007
  async (document) => {
6898
8008
  await document.deleteSearchIndexDatabase();
6899
8009
  await writeIndexOutput(args, {
@@ -6973,7 +8083,7 @@ var init_search_index = __esm({
6973
8083
  init_support();
6974
8084
  init_support();
6975
8085
  init_runtime();
6976
- init_uri2();
8086
+ init_uri3();
6977
8087
  INDEX_PROGRESS_OUTPUT_INTERVAL_MS = 6e3;
6978
8088
  }
6979
8089
  });
@@ -6992,7 +8102,7 @@ async function runArchiveMetaCommand(args) {
6992
8102
  }
6993
8103
  const app = new WikiGraph2({});
6994
8104
  const location = await resolveArchiveRuntimeLocation(args.inputPath);
6995
- await app.openSession(location.archivePath, async (digest) => {
8105
+ await app.openSession(new NodeFile(location.archivePath), async (digest) => {
6996
8106
  await writeArchiveMeta(await digest.readMeta(), {
6997
8107
  json: args.json ?? false
6998
8108
  });
@@ -7001,7 +8111,7 @@ async function runArchiveMetaCommand(args) {
7001
8111
  async function runArchiveCoverCommand(args) {
7002
8112
  const app = new WikiGraph2({});
7003
8113
  const location = await resolveArchiveRuntimeLocation(args.inputPath);
7004
- await app.openSession(location.archivePath, async (digest) => {
8114
+ await app.openSession(new NodeFile(location.archivePath), async (digest) => {
7005
8115
  if (process.stdout.isTTY === true) {
7006
8116
  throw new Error(
7007
8117
  "Refusing to write binary cover data to an interactive terminal. Redirect stdout or pipe it."
@@ -7081,7 +8191,8 @@ var init_maintenance = __esm({
7081
8191
  init_support();
7082
8192
  init_support();
7083
8193
  init_document();
7084
- init_uri2();
8194
+ init_uri3();
8195
+ init_node_platform();
7085
8196
  }
7086
8197
  });
7087
8198
 
@@ -7144,28 +8255,51 @@ var legacy_exports = {};
7144
8255
  __export(legacy_exports, {
7145
8256
  runLegacyCommand: () => runLegacyCommand
7146
8257
  });
7147
- import { upgradeWikiGraphMaintenanceTarget } from "wiki-graph-core";
8258
+ import { migrateLegacySdpubToWikg } from "wiki-graph-core";
8259
+ import { resolve as resolve6 } from "path";
7148
8260
  async function runLegacyCommand(args) {
7149
8261
  switch (args.action) {
7150
8262
  case "migrate": {
7151
8263
  process.stderr.write(
7152
8264
  "`wg legacy migrate` is deprecated. Use `wg maintenance upgrade <sdpub-path>`.\n"
7153
8265
  );
7154
- const result = await upgradeWikiGraphMaintenanceTarget(args.inputPath, {
7155
- ...args.outputPath === void 0 ? {} : { outputPath: args.outputPath }
7156
- });
7157
- if (result.kind !== "sdpub") {
7158
- throw new Error("Legacy migrate only supports sdpub inputs.");
7159
- }
7160
- process.stdout.write(`Wrote ${result.outputPath}
8266
+ const outputPath = resolve6(
8267
+ args.outputPath ?? defaultWikgOutputPath(args.inputPath)
8268
+ );
8269
+ await migrateLegacySdpubToWikg(
8270
+ new NodeFile(resolve6(args.inputPath)),
8271
+ new NodeFile(outputPath)
8272
+ );
8273
+ process.stdout.write(`Wrote ${outputPath}
7161
8274
  `);
7162
8275
  return;
7163
8276
  }
7164
8277
  }
7165
8278
  }
8279
+ function defaultWikgOutputPath(inputPath) {
8280
+ return inputPath.toLowerCase().endsWith(".sdpub") ? `${inputPath.slice(0, -".sdpub".length)}.wikg` : `${inputPath}.wikg`;
8281
+ }
7166
8282
  var init_legacy = __esm({
7167
8283
  "src/commands/legacy.ts"() {
7168
8284
  "use strict";
8285
+ init_node_platform();
8286
+ }
8287
+ });
8288
+
8289
+ // src/runtime/home-target.ts
8290
+ import { homedir as homedir4 } from "os";
8291
+ import { join as join7, resolve as resolve7 } from "path";
8292
+ function isWikiGraphHomeTarget(target) {
8293
+ if (target === "home" || target === "~/.wikigraph") return true;
8294
+ const configuredHome = resolve7(
8295
+ getCLIStateDir() ?? join7(homedir4(), ".wikigraph")
8296
+ );
8297
+ return resolve7(getCLICwd(), target) === configuredHome;
8298
+ }
8299
+ var init_home_target = __esm({
8300
+ "src/runtime/home-target.ts"() {
8301
+ "use strict";
8302
+ init_context();
7169
8303
  }
7170
8304
  });
7171
8305
 
@@ -7175,14 +8309,21 @@ __export(maintenance_exports2, {
7175
8309
  runMaintenanceCommand: () => runMaintenanceCommand
7176
8310
  });
7177
8311
  import {
7178
- upgradeWikiGraphMaintenanceTarget as upgradeWikiGraphMaintenanceTarget2
8312
+ parseWikiGraphLibraryUri as parseWikiGraphLibraryUri7,
8313
+ upgradeWikiGraphMaintenanceTarget
7179
8314
  } from "wiki-graph-core";
8315
+ import { resolve as resolve8 } from "path";
7180
8316
  async function runMaintenanceCommand(args) {
7181
8317
  switch (args.action) {
7182
8318
  case "upgrade": {
7183
- const result = await upgradeWikiGraphMaintenanceTarget2(args.target, {
7184
- ...args.outputPath === void 0 ? {} : { outputPath: args.outputPath }
7185
- });
8319
+ if (args.outputPath !== void 0 || args.target.endsWith(".sdpub")) {
8320
+ throw new Error(
8321
+ "Legacy sdpub migration is available through `wg legacy migrate`."
8322
+ );
8323
+ }
8324
+ const result = await upgradeWikiGraphMaintenanceTarget(
8325
+ parseMaintenanceTarget(args.target)
8326
+ );
7186
8327
  await writeTextToStdout(
7187
8328
  args.json === true ? formatCLIJSON(result) : formatMaintenanceUpgradeResult(result)
7188
8329
  );
@@ -7193,13 +8334,10 @@ async function runMaintenanceCommand(args) {
7193
8334
  function formatMaintenanceUpgradeResult(result) {
7194
8335
  switch (result.kind) {
7195
8336
  case "home":
7196
- return `Home ${result.status}: ${result.path} (schema v${result.schemaVersionBefore} -> v${result.schemaVersionAfter})
8337
+ return `Home ${result.status} (schema v${result.schemaVersionBefore} -> v${result.schemaVersionAfter})
7197
8338
  `;
7198
8339
  case "archive":
7199
- return `Archive ${result.status}: ${result.path} (schema v${result.schemaVersionBefore} -> v${result.schemaVersionAfter})
7200
- `;
7201
- case "sdpub":
7202
- return `Wrote ${result.outputPath}
8340
+ return `Archive ${result.status}: ${result.fileName} (schema v${result.schemaVersionBefore} -> v${result.schemaVersionAfter})
7203
8341
  `;
7204
8342
  case "lib": {
7205
8343
  const lines = [
@@ -7215,10 +8353,28 @@ function formatMaintenanceUpgradeResult(result) {
7215
8353
  }
7216
8354
  }
7217
8355
  }
8356
+ function parseMaintenanceTarget(target) {
8357
+ if (isWikiGraphHomeTarget(target)) {
8358
+ return { kind: "home" };
8359
+ }
8360
+ if (target.startsWith("wikg://lib")) {
8361
+ const parsed = parseWikiGraphLibraryUri7(target);
8362
+ if (parsed === void 0 || parsed.kind === "archive") {
8363
+ throw new Error(`Invalid Wiki Graph library upgrade target: ${target}`);
8364
+ }
8365
+ return { kind: "library", target: parsed };
8366
+ }
8367
+ if (!target.endsWith(".wikg")) {
8368
+ throw new Error(`Unsupported maintenance upgrade target: ${target}`);
8369
+ }
8370
+ return { file: new NodeFile(resolve8(target)), kind: "archive" };
8371
+ }
7218
8372
  var init_maintenance2 = __esm({
7219
8373
  "src/commands/maintenance.ts"() {
7220
8374
  "use strict";
8375
+ init_home_target();
7221
8376
  init_support();
8377
+ init_node_platform();
7222
8378
  }
7223
8379
  });
7224
8380
 
@@ -7228,7 +8384,7 @@ __export(local_config_exports, {
7228
8384
  mergeMaskedSecretsForSet: () => mergeMaskedSecretsForSet,
7229
8385
  runLocalConfigCommand: () => runLocalConfigCommand
7230
8386
  });
7231
- import { Writable } from "stream";
8387
+ import { Writable as Writable2 } from "stream";
7232
8388
  import { createInterface } from "readline/promises";
7233
8389
  import { generateText } from "ai";
7234
8390
  import {
@@ -7418,7 +8574,8 @@ async function runWikispineConfigTest(args) {
7418
8574
  try {
7419
8575
  const provider = parseWikispineProvider(wikispine.provider);
7420
8576
  const result = await testWikispineRuntime({
7421
- provider
8577
+ provider,
8578
+ ...provider === "cli" ? { commandRunner: nodeWikispineCommandRunner } : {}
7422
8579
  });
7423
8580
  const output = {
7424
8581
  durationMs: result.durationMs,
@@ -7552,7 +8709,7 @@ async function readSecretValue(key) {
7552
8709
  if (process.stdin.isTTY !== true) {
7553
8710
  throw new Error(`${key} requires an interactive terminal.`);
7554
8711
  }
7555
- const mutedOutput = new Writable({
8712
+ const mutedOutput = new Writable2({
7556
8713
  write(_chunk, _encoding, callback) {
7557
8714
  callback();
7558
8715
  }
@@ -7578,6 +8735,7 @@ var init_local_config2 = __esm({
7578
8735
  "src/commands/local-config.ts"() {
7579
8736
  "use strict";
7580
8737
  init_llm();
8738
+ init_wikispine();
7581
8739
  init_embedding();
7582
8740
  init_context();
7583
8741
  init_support();
@@ -7591,7 +8749,7 @@ var library_exports = {};
7591
8749
  __export(library_exports, {
7592
8750
  runLibraryCommand: () => runLibraryCommand
7593
8751
  });
7594
- import { readFile as readFile2 } from "fs/promises";
8752
+ import { mkdir as mkdir2, readFile as readFile3 } from "fs/promises";
7595
8753
  import {
7596
8754
  addWikiGraphLibraryArchive,
7597
8755
  assertWikiGraphLibrarySchemaCurrent,
@@ -7627,7 +8785,7 @@ async function runLibraryCommand(args) {
7627
8785
  }
7628
8786
  await writeLibraryArchive(
7629
8787
  await addWikiGraphLibraryArchive({
7630
- inputPath: args.inputPath,
8788
+ inputFile: new NodeFile(args.inputPath),
7631
8789
  target: args.target,
7632
8790
  ...args.to === void 0 ? {} : { to: args.to }
7633
8791
  }),
@@ -7639,7 +8797,10 @@ async function runLibraryCommand(args) {
7639
8797
  if (args.path === void 0) {
7640
8798
  throw new Error("Missing --path <folder> for library create.");
7641
8799
  }
7642
- const library = await createWikiGraphLibrary({ folderPath: args.path });
8800
+ await mkdir2(args.path);
8801
+ const library = await createWikiGraphLibrary({
8802
+ folder: new NodeDirectory(args.path)
8803
+ });
7643
8804
  await writeLibrary(library, args.json ?? false);
7644
8805
  return;
7645
8806
  }
@@ -7678,7 +8839,7 @@ async function runLibraryCommand(args) {
7678
8839
  await writeScanResult(
7679
8840
  "path set",
7680
8841
  async () => await rebindWikiGraphLibrary({
7681
- folderPath,
8842
+ folder: new NodeDirectory(folderPath),
7682
8843
  target: args.target
7683
8844
  }),
7684
8845
  args.json ?? false,
@@ -7865,9 +9026,9 @@ async function writeLibrary(library, json) {
7865
9026
  formatCLIJSON({
7866
9027
  uri: library.uri,
7867
9028
  id: library.publicId,
7868
- folderPath: library.folderPath,
9029
+ folderPath: getNodeResourcePath(library.folder),
7869
9030
  isDefault: library.isDefault,
7870
- stagingPath: library.stagingPath,
9031
+ stagingPath: getNodeResourcePath(library.staging),
7871
9032
  createdAt: library.createdAt,
7872
9033
  updatedAt: library.updatedAt
7873
9034
  })
@@ -7884,7 +9045,7 @@ async function writeLibraries(libraries, json) {
7884
9045
  items: libraries.map((library) => ({
7885
9046
  uri: library.uri,
7886
9047
  id: library.publicId,
7887
- path: library.folderPath,
9048
+ path: getNodeResourcePath(library.folder),
7888
9049
  isDefault: library.isDefault
7889
9050
  }))
7890
9051
  })
@@ -7896,7 +9057,7 @@ async function writeLibraries(libraries, json) {
7896
9057
  (library) => [
7897
9058
  library.uri,
7898
9059
  library.publicId,
7899
- library.folderPath,
9060
+ getNodeResourcePath(library.folder),
7900
9061
  library.isDefault ? "default" : ""
7901
9062
  ].join(" ")
7902
9063
  ).join("\n") + (libraries.length === 0 ? "" : "\n")
@@ -7905,11 +9066,14 @@ async function writeLibraries(libraries, json) {
7905
9066
  async function writeLibraryPath(library, json) {
7906
9067
  if (json) {
7907
9068
  await writeTextToStdout(
7908
- formatCLIJSON({ uri: `${library.uri}/path`, path: library.folderPath })
9069
+ formatCLIJSON({
9070
+ uri: `${library.uri}/path`,
9071
+ path: getNodeResourcePath(library.folder)
9072
+ })
7909
9073
  );
7910
9074
  return;
7911
9075
  }
7912
- await writeTextToStdout(`${library.folderPath}
9076
+ await writeTextToStdout(`${getNodeResourcePath(library.folder)}
7913
9077
  `);
7914
9078
  }
7915
9079
  async function writeLibraryArchivePath(archive, json) {
@@ -8019,7 +9183,7 @@ async function writeLibraryArchivePage(archive, json) {
8019
9183
  `Entity: ${archive.uri}/entity`,
8020
9184
  `Triple: ${archive.uri}/triple`,
8021
9185
  `Inspect: ${archive.uri} inspect`,
8022
- `Metadata path: ${archive.path}`,
9186
+ `Metadata path: ${formatArchiveHostPath(archive)}`,
8023
9187
  ""
8024
9188
  ].join("\n")
8025
9189
  );
@@ -8030,7 +9194,7 @@ function formatLibraryArchiveJSON(archive) {
8030
9194
  id: archive.publicId,
8031
9195
  libraryUri: archive.libraryUri,
8032
9196
  relativePath: archive.relativePath,
8033
- path: archive.path,
9197
+ path: formatArchiveHostPath(archive),
8034
9198
  exists: archive.exists,
8035
9199
  status: archive.status,
8036
9200
  lastSeenMutationToken: archive.lastSeenMutationToken,
@@ -8056,7 +9220,7 @@ function formatLibraryArchivePageJSON(archive) {
8056
9220
  inspect: `${archive.uri} inspect`
8057
9221
  },
8058
9222
  metadata: {
8059
- path: archive.path,
9223
+ path: formatArchiveHostPath(archive),
8060
9224
  exists: archive.exists,
8061
9225
  lastSeenMutationToken: archive.lastSeenMutationToken,
8062
9226
  lastSeenSize: archive.lastSeenSize,
@@ -8195,7 +9359,7 @@ async function readRawInput(args) {
8195
9359
  return content;
8196
9360
  }
8197
9361
  if (args.inputPath !== void 0) {
8198
- return await readFile2(args.inputPath, "utf8");
9362
+ return await readFile3(args.inputPath, "utf8");
8199
9363
  }
8200
9364
  throw new Error(
8201
9365
  "Missing input. Pass a value, use --input <path>, or use --input - for stdin."
@@ -8242,12 +9406,16 @@ function formatMetadataTextValue(value) {
8242
9406
  }
8243
9407
  return String(value);
8244
9408
  }
9409
+ function formatArchiveHostPath(archive) {
9410
+ return archive.file === void 0 ? archive.relativePath : getNodeResourcePath(archive.file);
9411
+ }
8245
9412
  var INDEX_PROGRESS_OUTPUT_INTERVAL_MS2;
8246
9413
  var init_library = __esm({
8247
9414
  "src/commands/library.ts"() {
8248
9415
  "use strict";
8249
9416
  init_support();
8250
9417
  init_run();
9418
+ init_node_platform();
8251
9419
  init_archive_output();
8252
9420
  init_runtime();
8253
9421
  INDEX_PROGRESS_OUTPUT_INTERVAL_MS2 = 6e3;
@@ -8259,15 +9427,15 @@ var object_metadata_exports = {};
8259
9427
  __export(object_metadata_exports, {
8260
9428
  runObjectMetadataCommand: () => runObjectMetadataCommand
8261
9429
  });
8262
- import { readFile as readFile3 } from "fs/promises";
9430
+ import { readFile as readFile4 } from "fs/promises";
8263
9431
  import { ObjectMetadataKind } from "wiki-graph-core";
8264
- import { WikiGraphArchiveFile as WikiGraphArchiveFile6 } from "wiki-graph-core";
9432
+ import { WikiGraphArchiveFile as WikiGraphArchiveFile7 } from "wiki-graph-core";
8265
9433
  async function runObjectMetadataCommand(args) {
8266
9434
  const target = parseObjectMetadataTarget(args.objectPath);
8267
9435
  switch (args.action) {
8268
9436
  case "get": {
8269
9437
  const location = await resolveArchiveRuntimeLocation(args.archivePath);
8270
- await new WikiGraphArchiveFile6(location.archivePath).readDocument(
9438
+ await new WikiGraphArchiveFile7(location.archiveFile).readDocument(
8271
9439
  async (document) => {
8272
9440
  await writeMetadataMap2(
8273
9441
  await document.metadata.getMap(args.objectPath),
@@ -8354,7 +9522,7 @@ async function readRawInput2(args) {
8354
9522
  return content;
8355
9523
  }
8356
9524
  if (args.inputPath !== void 0) {
8357
- return await readFile3(args.inputPath, "utf8");
9525
+ return await readFile4(args.inputPath, "utf8");
8358
9526
  }
8359
9527
  throw new Error(
8360
9528
  "Missing input. Pass a value, use --input <path>, or use --input - for stdin."
@@ -8453,7 +9621,7 @@ var init_object_metadata = __esm({
8453
9621
  "src/commands/object-metadata.ts"() {
8454
9622
  "use strict";
8455
9623
  init_document();
8456
- init_uri2();
9624
+ init_uri3();
8457
9625
  init_support();
8458
9626
  init_support();
8459
9627
  }
@@ -8644,23 +9812,33 @@ import {
8644
9812
  runBuildJobWorker,
8645
9813
  snapshotChapterKnowledgeGraphInput,
8646
9814
  snapshotChapterSummaryInput,
8647
- writeIndexArtifactOutput
9815
+ writeIndexArtifactOutput,
9816
+ ensureRelativeFile
8648
9817
  } from "wiki-graph-core";
8649
- import { WikiGraphArchiveFile as WikiGraphArchiveFile7 } from "wiki-graph-core";
8650
- import { join as join5 } from "path";
9818
+ import { WikiGraphArchiveFile as WikiGraphArchiveFile8 } from "wiki-graph-core";
8651
9819
  async function runQueueWorker() {
8652
9820
  const config = await loadCLIConfig();
8653
- await runBuildJobWorker({
8654
- concurrency: config.concurrent?.job ?? DEFAULT_GENERATION_JOB_CONCURRENCY,
8655
- executeJob: async (job, reporter, context) => {
8656
- await executeBuildJob(job, reporter, context);
8657
- }
8658
- });
9821
+ const controller = new AbortController();
9822
+ const stop = () => controller.abort();
9823
+ process.once("SIGINT", stop);
9824
+ process.once("SIGTERM", stop);
9825
+ try {
9826
+ await runBuildJobWorker({
9827
+ concurrency: config.concurrent?.job ?? DEFAULT_GENERATION_JOB_CONCURRENCY,
9828
+ executeJob: async (job, reporter, context) => {
9829
+ await executeBuildJob(job, reporter, context);
9830
+ },
9831
+ signal: controller.signal
9832
+ });
9833
+ } finally {
9834
+ process.removeListener("SIGINT", stop);
9835
+ process.removeListener("SIGTERM", stop);
9836
+ }
8659
9837
  }
8660
9838
  async function executeBuildJob(job, reporter, context) {
8661
9839
  await withLoggingContext(
8662
9840
  {
8663
- logDirPath: job.logPath,
9841
+ logDirectory: job.log,
8664
9842
  operation: "build-job"
8665
9843
  },
8666
9844
  async () => {
@@ -8680,8 +9858,8 @@ async function executeGenerationBuildJob(job, reporter, context) {
8680
9858
  ...job.llmJSON === void 0 ? {} : { llmJSON: job.llmJSON }
8681
9859
  });
8682
9860
  const llm = createStageLLM(config, {
8683
- cacheDirPath: job.cachePath,
8684
- logDirPath: job.logPath,
9861
+ cacheDirectory: job.cache,
9862
+ logDirectory: job.log,
8685
9863
  onStreamProgress: async (event) => {
8686
9864
  await reporter.addOutputCharacters(event.outputCharacters);
8687
9865
  },
@@ -8703,9 +9881,7 @@ async function executeGenerationBuildJob(job, reporter, context) {
8703
9881
  signal: context.signal
8704
9882
  });
8705
9883
  request.lazy = async (operation) => await llm.request(async () => await operation(request));
8706
- const buildInput = await new WikiGraphArchiveFile7(
8707
- job.archivePath
8708
- ).readDocument(
9884
+ const buildInput = await new WikiGraphArchiveFile8(job.archive).readDocument(
8709
9885
  async (document) => await readChapterBuildInput(document, job.chapterId)
8710
9886
  );
8711
9887
  let { details } = buildInput;
@@ -8725,7 +9901,7 @@ async function executeGenerationBuildJob(job, reporter, context) {
8725
9901
  );
8726
9902
  }
8727
9903
  if (job.target === "knowledge-graph" || job.target === "reading-graph") {
8728
- await new WikiGraphArchiveFile7(job.archivePath).readDocument(
9904
+ await new WikiGraphArchiveFile8(job.archive).readDocument(
8729
9905
  async (document) => {
8730
9906
  const artifact = await document.indexArtifacts.get(
8731
9907
  job.chapterId,
@@ -8742,8 +9918,8 @@ async function executeGenerationBuildJob(job, reporter, context) {
8742
9918
  if (job.target === "knowledge-graph") {
8743
9919
  const wikispine = requireKnowledgeGraphWikispineConfig(config);
8744
9920
  await reporter.stepStarted("knowledge-graph");
8745
- const knowledgeGraphInput = await new WikiGraphArchiveFile7(
8746
- job.archivePath
9921
+ const knowledgeGraphInput = await new WikiGraphArchiveFile8(
9922
+ job.archive
8747
9923
  ).readDocument(async (document) => {
8748
9924
  await assertCurrentBuildInputRevision(job, document);
8749
9925
  return await snapshotChapterKnowledgeGraphInput(document, job.chapterId);
@@ -8756,11 +9932,14 @@ async function executeGenerationBuildJob(job, reporter, context) {
8756
9932
  progressTracker: reporter,
8757
9933
  request,
8758
9934
  resolverOptions: {
8759
- logDirPath: job.logPath,
9935
+ logDirectory: job.log,
8760
9936
  normalizer: createDisambiguationProfileNormalizer({ request })
8761
9937
  },
8762
- wikispine,
8763
- workspacePath: job.workspacePath
9938
+ wikispine: {
9939
+ ...wikispine,
9940
+ ...wikispine.provider === "cli" ? { commandRunner: nodeWikispineCommandRunner } : {}
9941
+ },
9942
+ workspace: job.workspace
8764
9943
  }
8765
9944
  );
8766
9945
  await reporter.updatePhase({
@@ -8769,7 +9948,7 @@ async function executeGenerationBuildJob(job, reporter, context) {
8769
9948
  total: 1,
8770
9949
  unit: "item"
8771
9950
  });
8772
- await new WikiGraphArchiveFile7(job.archivePath).write(async (document) => {
9951
+ await new WikiGraphArchiveFile8(job.archive).write(async (document) => {
8773
9952
  assertJobStillRunning(await getBuildJob2(job.jobId));
8774
9953
  await assertCurrentBuildInputRevision(job, document);
8775
9954
  await commitChapterKnowledgeGraphArtifact(document, artifact);
@@ -8791,7 +9970,7 @@ async function executeGenerationBuildJob(job, reporter, context) {
8791
9970
  extractionPrompt,
8792
9971
  llm,
8793
9972
  sourceText,
8794
- workspacePath: job.workspacePath,
9973
+ workspace: job.workspace,
8795
9974
  progressTracker: {
8796
9975
  async advance(wordsCount) {
8797
9976
  graphWords += wordsCount;
@@ -8810,7 +9989,7 @@ async function executeGenerationBuildJob(job, reporter, context) {
8810
9989
  total: 1,
8811
9990
  unit: "item"
8812
9991
  });
8813
- details = await new WikiGraphArchiveFile7(job.archivePath).write(
9992
+ details = await new WikiGraphArchiveFile8(job.archive).write(
8814
9993
  async (document) => {
8815
9994
  assertJobStillRunning(await getBuildJob2(job.jobId));
8816
9995
  await assertCurrentBuildInputRevision(job, document);
@@ -8823,8 +10002,8 @@ async function executeGenerationBuildJob(job, reporter, context) {
8823
10002
  total: 1,
8824
10003
  unit: "item"
8825
10004
  });
8826
- const nextBuildInput = await new WikiGraphArchiveFile7(
8827
- job.archivePath
10005
+ const nextBuildInput = await new WikiGraphArchiveFile8(
10006
+ job.archive
8828
10007
  ).readDocument(
8829
10008
  async (document) => await readChapterBuildInput(document, job.chapterId)
8830
10009
  );
@@ -8843,7 +10022,7 @@ async function executeGenerationBuildJob(job, reporter, context) {
8843
10022
  return;
8844
10023
  }
8845
10024
  if (details.stage !== "graphed") {
8846
- ({ details } = await new WikiGraphArchiveFile7(job.archivePath).readDocument(
10025
+ ({ details } = await new WikiGraphArchiveFile8(job.archive).readDocument(
8847
10026
  async (document) => await readChapterBuildInput(document, job.chapterId)
8848
10027
  ));
8849
10028
  }
@@ -8853,20 +10032,20 @@ async function executeGenerationBuildJob(job, reporter, context) {
8853
10032
  );
8854
10033
  }
8855
10034
  await reporter.stepStarted("reading-summary");
8856
- const summaryInput = await new WikiGraphArchiveFile7(
8857
- job.archivePath
8858
- ).readDocument(async (document) => {
8859
- await assertCurrentBuildInputRevision(job, document);
8860
- return await snapshotChapterSummaryInput(
8861
- document,
8862
- job.chapterId,
8863
- job.workspacePath
8864
- );
8865
- });
10035
+ const summaryInput = await new WikiGraphArchiveFile8(job.archive).readDocument(
10036
+ async (document) => {
10037
+ await assertCurrentBuildInputRevision(job, document);
10038
+ return await snapshotChapterSummaryInput(
10039
+ document,
10040
+ job.chapterId,
10041
+ job.workspace
10042
+ );
10043
+ }
10044
+ );
8866
10045
  const summary = await buildChapterSummaryArtifactFromSnapshot(job.chapterId, {
8867
10046
  llm,
8868
- snapshotPath: summaryInput.filePath,
8869
- workspacePath: job.workspacePath
10047
+ snapshotFile: summaryInput.file,
10048
+ workspace: job.workspace
8870
10049
  });
8871
10050
  await reporter.updatePhase({
8872
10051
  done: 0,
@@ -8874,7 +10053,7 @@ async function executeGenerationBuildJob(job, reporter, context) {
8874
10053
  total: 1,
8875
10054
  unit: "item"
8876
10055
  });
8877
- details = await new WikiGraphArchiveFile7(job.archivePath).write(
10056
+ details = await new WikiGraphArchiveFile8(job.archive).write(
8878
10057
  async (document) => {
8879
10058
  assertJobStillRunning(await getBuildJob2(job.jobId));
8880
10059
  await assertCurrentBuildInputRevision(job, document);
@@ -8910,9 +10089,9 @@ async function executeIndexArtifactBuildJob(job, reporter, context) {
8910
10089
  unit: "item"
8911
10090
  });
8912
10091
  if (job.target === "index-fts") {
8913
- const outputPath2 = resolveIndexArtifactOutputPath(job);
10092
+ const outputFile2 = await resolveIndexArtifactOutputFile(job);
8914
10093
  await writeIndexArtifactOutput(
8915
- outputPath2,
10094
+ outputFile2,
8916
10095
  createFtsIndexArtifactInput({
8917
10096
  chapterTitles: snapshot.chapterTitles,
8918
10097
  chunks: snapshot.chunks,
@@ -8923,12 +10102,12 @@ async function executeIndexArtifactBuildJob(job, reporter, context) {
8923
10102
  summarySentences: snapshot.summarySentences
8924
10103
  })
8925
10104
  );
8926
- const artifact2 = await readIndexArtifactOutput(outputPath2);
10105
+ const artifact2 = await readIndexArtifactOutput(outputFile2);
8927
10106
  assertIndexArtifactOutputMatchesJob(job, snapshot.revision, artifact2);
8928
10107
  if (!("lexicalRows" in artifact2)) {
8929
10108
  throw new Error("Index artifact output is not an FTS artifact.");
8930
10109
  }
8931
- await new WikiGraphArchiveFile7(job.archivePath).write(async (document) => {
10110
+ await new WikiGraphArchiveFile8(job.archive).write(async (document) => {
8932
10111
  assertJobStillRunning(await getBuildJob2(job.jobId));
8933
10112
  await assertJobChapterExists(document, job.chapterId);
8934
10113
  await assertCurrentBuildInputRevision(job, document);
@@ -8946,7 +10125,7 @@ async function executeIndexArtifactBuildJob(job, reporter, context) {
8946
10125
  )
8947
10126
  );
8948
10127
  }
8949
- const outputPath = resolveIndexArtifactOutputPath(job);
10128
+ const outputFile = await resolveIndexArtifactOutputFile(job);
8950
10129
  const artifact = await createEmbeddingIndexArtifactInput({
8951
10130
  embeddingProvider: buildSearchIndexEmbeddingProvider(config.embedding),
8952
10131
  kind: job.target === "index-embedding-source" ? "embedding-source" : "embedding-summary",
@@ -8955,13 +10134,13 @@ async function executeIndexArtifactBuildJob(job, reporter, context) {
8955
10134
  signal: context.signal,
8956
10135
  sourceRevision: snapshot.revision
8957
10136
  });
8958
- await writeIndexArtifactOutput(outputPath, artifact);
8959
- const output = await readIndexArtifactOutput(outputPath);
10137
+ await writeIndexArtifactOutput(outputFile, artifact);
10138
+ const output = await readIndexArtifactOutput(outputFile);
8960
10139
  assertIndexArtifactOutputMatchesJob(job, snapshot.revision, output);
8961
10140
  if ("lexicalRows" in output) {
8962
10141
  throw new Error("Index artifact output is not an embedding artifact.");
8963
10142
  }
8964
- await new WikiGraphArchiveFile7(job.archivePath).write(async (document) => {
10143
+ await new WikiGraphArchiveFile8(job.archive).write(async (document) => {
8965
10144
  assertJobStillRunning(await getBuildJob2(job.jobId));
8966
10145
  await assertJobChapterExists(document, job.chapterId);
8967
10146
  await assertCurrentBuildInputRevision(job, document);
@@ -8980,7 +10159,7 @@ async function completeIndexArtifactStep(job, reporter) {
8980
10159
  assertJobStillRunning(await getBuildJob2(job.jobId));
8981
10160
  }
8982
10161
  async function readIndexArtifactJobSnapshot(job) {
8983
- return await new WikiGraphArchiveFile7(job.archivePath).readDocument(
10162
+ return await new WikiGraphArchiveFile8(job.archive).readDocument(
8984
10163
  async (document) => {
8985
10164
  await assertJobChapterExists(document, job.chapterId);
8986
10165
  const revision = await document.serials.getRevision(job.chapterId);
@@ -9043,8 +10222,8 @@ async function readChapterTitles(document, serialId) {
9043
10222
  function collectTocItems(items) {
9044
10223
  return items.flatMap((item) => [item, ...collectTocItems(item.children)]);
9045
10224
  }
9046
- function resolveIndexArtifactOutputPath(job) {
9047
- return join5(job.workspacePath, "index-artifact-output.jsonl");
10225
+ async function resolveIndexArtifactOutputFile(job) {
10226
+ return await ensureRelativeFile(job.workspace, "index-artifact-output.jsonl");
9048
10227
  }
9049
10228
  function assertIndexArtifactOutputMatchesJob(job, inputRevision, artifact) {
9050
10229
  if (artifact.serialId !== job.chapterId) {
@@ -9124,6 +10303,7 @@ var init_worker = __esm({
9124
10303
  init_runtime();
9125
10304
  init_embedding();
9126
10305
  init_support();
10306
+ init_wikispine();
9127
10307
  }
9128
10308
  });
9129
10309
 
@@ -9137,7 +10317,7 @@ import {
9137
10317
  boostBuildJob,
9138
10318
  cancelBuildJob,
9139
10319
  cleanBuildJobs,
9140
- formatLocatedChapterUri as formatLocatedChapterUri2,
10320
+ formatLocatedChapterUri as formatLocatedChapterUri4,
9141
10321
  formatLocatedWikiGraphUri as formatLocatedWikiGraphUri4,
9142
10322
  getBuildJob as getBuildJob3,
9143
10323
  listBuildJobs,
@@ -9146,7 +10326,7 @@ import {
9146
10326
  resolveBuildJobId,
9147
10327
  resumeBuildJob,
9148
10328
  updateBuildJobTarget,
9149
- WikiGraphArchiveFile as WikiGraphArchiveFile8
10329
+ WikiGraphArchiveFile as WikiGraphArchiveFile9
9150
10330
  } from "wiki-graph-core";
9151
10331
  async function runQueueCommand(args) {
9152
10332
  switch (args.action) {
@@ -9184,6 +10364,7 @@ async function runQueueCommand(args) {
9184
10364
  target: args.target ?? "reading-summary"
9185
10365
  });
9186
10366
  await writeJobSummary(await addChapterJob(args, chapterId), {
10367
+ chapter,
9187
10368
  estimate,
9188
10369
  json: args.json ?? false,
9189
10370
  watch: true
@@ -9199,7 +10380,7 @@ async function runQueueCommand(args) {
9199
10380
  await listBuildJobs({
9200
10381
  ...args.activeOnly === void 0 ? {} : { activeOnly: args.activeOnly },
9201
10382
  ...args.all === void 0 ? {} : { all: args.all },
9202
- ...args.archivePath === void 0 ? {} : { archivePath: args.archivePath }
10383
+ ...args.archivePath === void 0 ? {} : { archive: new NodeFile(args.archivePath) }
9203
10384
  }),
9204
10385
  { json: args.json ?? false }
9205
10386
  );
@@ -9262,7 +10443,7 @@ async function resolveQueueChapterIds(args) {
9262
10443
  return void 0;
9263
10444
  }
9264
10445
  let chapterIds;
9265
- await new WikiGraphArchiveFile8(args.archivePath).readDocument(
10446
+ await new WikiGraphArchiveFile9(new NodeFile(args.archivePath)).readDocument(
9266
10447
  async (document) => {
9267
10448
  if (args.chapterPath === void 0) {
9268
10449
  chapterIds = (await resolveArchiveChapterScope(document, {
@@ -9275,7 +10456,7 @@ async function resolveQueueChapterIds(args) {
9275
10456
  return;
9276
10457
  }
9277
10458
  chapterIds = (await resolveArchiveChapterScope(document, {
9278
- archivePath: formatLocatedChapterUri2(
10459
+ archivePath: formatLocatedChapterUri4(
9279
10460
  args.archivePath,
9280
10461
  args.chapterPath
9281
10462
  ),
@@ -9299,6 +10480,7 @@ var init_queue = __esm({
9299
10480
  init_watch();
9300
10481
  init_worker();
9301
10482
  init_scope();
10483
+ init_node_platform();
9302
10484
  init_worker();
9303
10485
  }
9304
10486
  });
@@ -9307,8 +10489,8 @@ var init_queue = __esm({
9307
10489
  export * from "wiki-graph-core";
9308
10490
 
9309
10491
  // src/app/runner.ts
9310
- import { Readable as Readable2, Writable as Writable2 } from "stream";
9311
- import { withWikiGraphRuntimeStateDirectoryPath } from "wiki-graph-core";
10492
+ init_node_platform();
10493
+ import { Readable as Readable2, Writable as Writable3 } from "stream";
9312
10494
 
9313
10495
  // src/args/help.ts
9314
10496
  init_support();
@@ -9316,7 +10498,6 @@ init_support();
9316
10498
  init_support();
9317
10499
  import {
9318
10500
  formatWikiGraphLibraryUri,
9319
- parseLocatedWikiGraphUri,
9320
10501
  parseWikiGraphLibraryUri,
9321
10502
  resolveDataDirPath
9322
10503
  } from "wiki-graph-core";
@@ -9435,6 +10616,9 @@ function parseChapterTarget(objectUri) {
9435
10616
  kind: "chapter-index-artifact"
9436
10617
  };
9437
10618
  }
10619
+ if (suffix === "source/locators") {
10620
+ return { chapterPath, kind: "source-locator-scope" };
10621
+ }
9438
10622
  const resource = parseChapterResourceSuffix(suffix);
9439
10623
  if (suffix !== void 0 && resource === void 0) {
9440
10624
  return void 0;
@@ -9524,6 +10708,8 @@ function parseChapterResourceSuffix(suffix) {
9524
10708
  // src/args/help.ts
9525
10709
  var HELP_TOPICS = [
9526
10710
  "format",
10711
+ "file-import",
10712
+ "source-locators",
9527
10713
  "config",
9528
10714
  "runtime",
9529
10715
  "uri",
@@ -9536,6 +10722,7 @@ var URI_HELP_TARGETS = [
9536
10722
  name: "archive-scope",
9537
10723
  predicates: ["create", "export", "inspect"]
9538
10724
  },
10725
+ { name: "artifact-object", predicates: [] },
9539
10726
  {
9540
10727
  name: "chapter-collection-scope",
9541
10728
  predicates: ["add"]
@@ -9545,6 +10732,7 @@ var URI_HELP_TARGETS = [
9545
10732
  predicates: ["move", "remove", "reset"]
9546
10733
  },
9547
10734
  { name: "chapter-source-range-object", predicates: [] },
10735
+ { name: "chapter-source-locator-scope", predicates: [] },
9548
10736
  { name: "chapter-source-object", predicates: ["set"] },
9549
10737
  { name: "chapter-summary-range-object", predicates: [] },
9550
10738
  { name: "chapter-summary-object", predicates: ["set"] },
@@ -9598,6 +10786,16 @@ var HELP_TOPIC_METADATA = [
9598
10786
  name: "format",
9599
10787
  summary: "Supported formats, inference rules, and IO constraints."
9600
10788
  },
10789
+ {
10790
+ name: "file-import",
10791
+ rootVisible: false,
10792
+ summary: "Advanced source-file import and source-text provenance behavior."
10793
+ },
10794
+ {
10795
+ name: "source-locators",
10796
+ rootVisible: false,
10797
+ summary: "Source artifact URIs and source-text locator mappings."
10798
+ },
9601
10799
  {
9602
10800
  name: "config",
9603
10801
  summary: "Configuration overview, precedence, and when each layer applies."
@@ -9639,6 +10837,8 @@ var ARCHIVE_MAINTENANCE_COMMAND_METADATA = [
9639
10837
  ];
9640
10838
  var HELP_TOPIC_TEMPLATE_NAMES = {
9641
10839
  format: "help/topics/format",
10840
+ "file-import": "help/topics/file-import",
10841
+ "source-locators": "help/topics/source-locators",
9642
10842
  config: "help/topics/config",
9643
10843
  runtime: "help/topics/runtime",
9644
10844
  uri: "help/topics/uri",
@@ -9674,10 +10874,11 @@ function renderHelpTopicText(topic) {
9674
10874
  }
9675
10875
  function renderUriHelpText(targetName, uri) {
9676
10876
  return renderHelpTemplate("help/commands/uri", {
10877
+ displayUri: uri,
9677
10878
  libraryContext: getLibraryHelpContext(uri),
9678
10879
  target: requireUriHelpTarget(targetName),
9679
10880
  uriContext: getUriHelpContext(uri),
9680
- uri
10881
+ uri: formatHelpCommandUri(uri)
9681
10882
  });
9682
10883
  }
9683
10884
  function renderUriPredicateHelpText(targetName, predicate, uri) {
@@ -9691,26 +10892,33 @@ function renderUriPredicateHelpText(targetName, predicate, uri) {
9691
10892
  );
9692
10893
  }
9693
10894
  return renderHelpTemplate("help/commands/predicate", {
10895
+ displayUri: uri,
9694
10896
  libraryContext: getLibraryHelpContext(uri),
9695
10897
  predicate,
9696
10898
  target,
9697
10899
  uriContext: getUriHelpContext(uri),
9698
- uri
10900
+ uri: formatHelpCommandUri(uri)
9699
10901
  });
9700
10902
  }
9701
10903
  function renderLibraryUriHelpText(uri, target) {
10904
+ const helpUri = formatLibraryHelpUri(uri, target);
9702
10905
  return renderHelpTemplate("help/commands/library", {
9703
10906
  target,
9704
- uri: formatLibraryHelpUri(uri, target)
10907
+ uri: formatHelpCommandUri(helpUri)
9705
10908
  });
9706
10909
  }
9707
10910
  function renderLibraryPredicateHelpText(uri, target, predicate) {
10911
+ const helpUri = formatLibraryHelpUri(uri, target);
9708
10912
  return renderHelpTemplate("help/commands/library-predicate", {
10913
+ displayUri: helpUri,
9709
10914
  predicate,
9710
10915
  target,
9711
- uri: formatLibraryHelpUri(uri, target)
10916
+ uri: formatHelpCommandUri(helpUri)
9712
10917
  });
9713
10918
  }
10919
+ function formatHelpCommandUri(uri) {
10920
+ return formatShellArgument(uri);
10921
+ }
9714
10922
  function formatLibraryHelpUri(fallbackUri, target) {
9715
10923
  const scopeUri = formatWikiGraphLibraryUri(target.publicId);
9716
10924
  switch (target.kind) {
@@ -9844,10 +11052,7 @@ function getHelpTemplateEnvironment() {
9844
11052
 
9845
11053
  // src/args/archive.ts
9846
11054
  init_support();
9847
- init_support();
9848
- import {
9849
- parseLocatedWikiGraphUri as parseLocatedWikiGraphUri4
9850
- } from "wiki-graph-core";
11055
+ import "wiki-graph-core";
9851
11056
 
9852
11057
  // src/args/helper/actions.ts
9853
11058
  init_support();
@@ -9862,17 +11067,12 @@ function isArchiveMaintenanceCommand(value) {
9862
11067
 
9863
11068
  // src/args/helper/chapter/ids.ts
9864
11069
  init_support();
9865
- import {
9866
- parseChapterPath as parseChapterPath2,
9867
- parseChapterUriPath,
9868
- parseLocatedWikiGraphUri as parseLocatedWikiGraphUri3
9869
- } from "wiki-graph-core";
11070
+ import { parseChapterPath as parseChapterPath2, parseChapterUriPath } from "wiki-graph-core";
9870
11071
 
9871
11072
  // src/args/helper/uri.ts
9872
11073
  init_support();
9873
11074
  init_local_config();
9874
11075
  import {
9875
- parseLocatedWikiGraphUri as parseLocatedWikiGraphUri2,
9876
11076
  parseWikiGraphUriSyntax,
9877
11077
  WIKI_GRAPH_URI_PREFIX
9878
11078
  } from "wiki-graph-core";
@@ -9881,7 +11081,7 @@ function validateArchiveCommandUriInput(action, value) {
9881
11081
  return;
9882
11082
  }
9883
11083
  if (isWikiGraphUri(value)) {
9884
- if (parseLocatedWikiGraphUri2(value).archivePath === void 0) {
11084
+ if (parseLocatedWikiGraphUri(value).archivePath === void 0) {
9885
11085
  throw new Error(formatMissingArchiveLocatorMessage(value));
9886
11086
  }
9887
11087
  return;
@@ -9895,12 +11095,12 @@ function parseArchiveInspectChapterId(uri) {
9895
11095
  if (uri === void 0 || !isWikiGraphUri(uri)) {
9896
11096
  return void 0;
9897
11097
  }
9898
- const objectUri = parseLocatedWikiGraphUri2(uri).objectUri;
11098
+ const objectUri = parseLocatedWikiGraphUri(uri).objectUri;
9899
11099
  const match = objectUri === void 0 ? void 0 : /^wikg:\/\/chapter\/([1-9][0-9]*)$/u.exec(objectUri);
9900
11100
  return match?.[1] === void 0 ? void 0 : Number(match[1]);
9901
11101
  }
9902
11102
  function validatePackTargetUri(uri, helpRoute) {
9903
- const parsed = parseLocatedWikiGraphUri2(uri);
11103
+ const parsed = parseLocatedWikiGraphUri(uri);
9904
11104
  if (parsed.archivePath === void 0) {
9905
11105
  throw new Error(
9906
11106
  withHelpRoute(formatMissingArchiveLocatorMessage(uri), helpRoute)
@@ -9918,7 +11118,7 @@ function validatePackTargetUri(uri, helpRoute) {
9918
11118
  }
9919
11119
  }
9920
11120
  function validateRelatedTargetUri(uri, helpRoute) {
9921
- const parsed = parseLocatedWikiGraphUri2(uri);
11121
+ const parsed = parseLocatedWikiGraphUri(uri);
9922
11122
  if (parsed.archivePath === void 0) {
9923
11123
  throw new Error(
9924
11124
  withHelpRoute(formatMissingArchiveLocatorMessage(uri), helpRoute)
@@ -9944,7 +11144,7 @@ function validateRelatedTargetUri(uri, helpRoute) {
9944
11144
  return targetType;
9945
11145
  }
9946
11146
  function validateEvidenceTargetUri(uri, helpRoute) {
9947
- const parsed = parseLocatedWikiGraphUri2(uri);
11147
+ const parsed = parseLocatedWikiGraphUri(uri);
9948
11148
  if (parsed.archivePath === void 0) {
9949
11149
  throw new Error(
9950
11150
  withHelpRoute(formatMissingArchiveLocatorMessage(uri), helpRoute)
@@ -10142,7 +11342,7 @@ function parseWikiGraphPath(value) {
10142
11342
  }
10143
11343
  }
10144
11344
  function requireArchiveUriPath(uri, helpRoute) {
10145
- const parsed = parseLocatedWikiGraphUri2(uri);
11345
+ const parsed = parseLocatedWikiGraphUri(uri);
10146
11346
  if (parsed.archivePath === void 0 || parsed.objectUri !== void 0) {
10147
11347
  throw new Error(
10148
11348
  withHelpRoute(`Expected an archive Wiki Graph URI: ${uri}`, helpRoute)
@@ -10158,7 +11358,7 @@ function parseChapterPathRef(value, flag, archivePath, helpRoute) {
10158
11358
  if (!isWikiGraphUri(normalized)) {
10159
11359
  return parseChapterPath2(normalized, flag);
10160
11360
  }
10161
- const parsed = parseLocatedWikiGraphUri3(normalized);
11361
+ const parsed = parseLocatedWikiGraphUri(normalized);
10162
11362
  if (parsed.archivePath !== void 0 && parsed.archivePath !== archivePath) {
10163
11363
  throw new Error(
10164
11364
  `Invalid ${flag}: ${value}. Chapter URI belongs to a different archive.`
@@ -10522,12 +11722,14 @@ function normalizeArchiveChapterArguments(action, path, values, helpRoute, treeA
10522
11722
  rejectActionFlag(values.after, "--after", action, helpRoute);
10523
11723
  rejectActionFlag(values.before, "--before", action, helpRoute);
10524
11724
  rejectActionFlag(values.import, "--import", action, helpRoute);
10525
- rejectActionFlag(
10526
- values["input-format"],
10527
- "--input-format",
10528
- action,
10529
- helpRoute
10530
- );
11725
+ if (values["input-format"] !== void 0 && values["input-format"] !== "jsonl") {
11726
+ throw new Error(
11727
+ withHelpRoute(
11728
+ "`--input-format` for chapter source set only accepts `jsonl`.",
11729
+ helpRoute
11730
+ )
11731
+ );
11732
+ }
10531
11733
  rejectActionFlag(values.parent, "--parent", action, helpRoute);
10532
11734
  rejectActionFlag(values.prompt, "--prompt", action, helpRoute);
10533
11735
  rejectActionFlag(values.title, "--title", action, helpRoute);
@@ -10555,6 +11757,7 @@ function normalizeArchiveChapterArguments(action, path, values, helpRoute, treeA
10555
11757
  ...values.json === void 0 ? {} : { json: values.json },
10556
11758
  path,
10557
11759
  ...values.input === void 0 ? {} : { inputPath: values.input },
11760
+ ...values["input-format"] === void 0 ? {} : { inputFormat: "jsonl" },
10558
11761
  ...values.llm === void 0 ? {} : { llmJSON: values.llm }
10559
11762
  };
10560
11763
  case "set-summary":
@@ -11392,7 +12595,7 @@ function parseArchiveArguments(action, positionals, values, helpRoute = `wg ${ac
11392
12595
  };
11393
12596
  case "inspect": {
11394
12597
  const chapterId = parseArchiveInspectChapterId(positionals[0]);
11395
- const parsedArchivePath = parseLocatedWikiGraphUri4(archivePath).archivePath ?? archivePath;
12598
+ const parsedArchivePath = parseLocatedWikiGraphUri(archivePath).archivePath ?? archivePath;
11396
12599
  rejectArchiveExtraPositionals(action, positionals, 1, helpRoute);
11397
12600
  rejectArchiveNonReadFlags(action, values, helpRoute);
11398
12601
  rejectArchiveFlag(action, "--budget", values.budget, helpRoute);
@@ -11711,7 +12914,7 @@ function rejectNonChapterDepthFlag(action, archivePath, depth, helpRoute) {
11711
12914
  if (depth === void 0) {
11712
12915
  return;
11713
12916
  }
11714
- const objectUri = parseLocatedWikiGraphUri4(archivePath).objectUri;
12917
+ const objectUri = parseLocatedWikiGraphUri(archivePath).objectUri;
11715
12918
  if (objectUri === "wikg://chapter" || objectUri?.startsWith("wikg://chapter/") === true) {
11716
12919
  return;
11717
12920
  }
@@ -11739,7 +12942,6 @@ init_support();
11739
12942
 
11740
12943
  // src/args/queue.ts
11741
12944
  init_support();
11742
- import { parseLocatedWikiGraphUri as parseLocatedWikiGraphUri6 } from "wiki-graph-core";
11743
12945
 
11744
12946
  // src/args/uri/chapter/routing.ts
11745
12947
  import {
@@ -11844,7 +13046,36 @@ function parseArchiveChapterUriArguments(uri, archivePath, target, action, tail,
11844
13046
  values,
11845
13047
  helpRoute
11846
13048
  );
13049
+ case "source-locator-scope":
13050
+ return parseSourceLocatorScopeUriArguments(
13051
+ uri,
13052
+ action,
13053
+ tail,
13054
+ values,
13055
+ helpRoute
13056
+ );
13057
+ }
13058
+ }
13059
+ function parseSourceLocatorScopeUriArguments(uri, action, tail, values, helpRoute) {
13060
+ if (action !== "list") {
13061
+ throw new Error(
13062
+ withHelpRoute(
13063
+ "The source locator scope is read-only. Read it directly to enumerate locator mappings.",
13064
+ "wg <chapter-uri>/source/locators --help"
13065
+ )
13066
+ );
11847
13067
  }
13068
+ rejectArchiveChapterFlag("backlinks", values.backlinks, helpRoute);
13069
+ rejectArchiveChapterFlag("context", values.context, helpRoute);
13070
+ rejectArchiveChapterFlag("depth", values.depth, helpRoute);
13071
+ rejectArchiveChapterFlag("evidence", values.evidence, helpRoute);
13072
+ rejectArchiveChapterFlag("reverse", values.reverse, helpRoute);
13073
+ rejectArchiveChapterFlag(
13074
+ "skip-unindexed",
13075
+ values["skip-unindexed"],
13076
+ helpRoute
13077
+ );
13078
+ return parseArchiveArguments("list", [uri, ...tail], values, helpRoute);
11848
13079
  }
11849
13080
  function parseChapterIndexArtifactUriArguments(archivePath, chapterPath, indexArtifactKind, action, tail, values, helpRoute) {
11850
13081
  rejectArchiveChapterMetaFlags(values, helpRoute);
@@ -12205,8 +13436,7 @@ function parseArchiveChapterLikeArguments(action, archivePath, tail, values, hel
12205
13436
 
12206
13437
  // src/args/uri/entry.ts
12207
13438
  import {
12208
- parseWikiGraphLibraryUri as parseWikiGraphLibraryUri2,
12209
- parseLocatedWikiGraphUri as parseLocatedWikiGraphUri5
13439
+ parseWikiGraphLibraryUri as parseWikiGraphLibraryUri2
12210
13440
  } from "wiki-graph-core";
12211
13441
  init_support();
12212
13442
 
@@ -12525,14 +13755,14 @@ function normalizeArchiveUriAction(uri, action) {
12525
13755
  if (action !== "apply") {
12526
13756
  return action;
12527
13757
  }
12528
- const parsed = parseLocatedWikiGraphUri5(uri);
13758
+ const parsed = parseLocatedWikiGraphUri(uri);
12529
13759
  if (parsed.objectUri === "wikg://chapter/tree") {
12530
13760
  return "set";
12531
13761
  }
12532
13762
  return action;
12533
13763
  }
12534
13764
  function resolveImplicitArchiveUriAction(uri, query) {
12535
- const parsed = parseLocatedWikiGraphUri5(uri);
13765
+ const parsed = parseLocatedWikiGraphUri(uri);
12536
13766
  if (parsed.archivePath === void 0) {
12537
13767
  throw new Error(formatMissingArchiveLocatorMessage(uri));
12538
13768
  }
@@ -12564,6 +13794,7 @@ function classifyArchiveUri(objectUri) {
12564
13794
  case "triple-pattern-lens":
12565
13795
  case "chapter-lens":
12566
13796
  case "chapter-triple-pattern-lens":
13797
+ case "source-locator-scope":
12567
13798
  return "scope";
12568
13799
  case "tree":
12569
13800
  case "chapter-resource":
@@ -12580,7 +13811,7 @@ function classifyArchiveUri(objectUri) {
12580
13811
  return "object";
12581
13812
  }
12582
13813
  function classifyArchiveUriHelpTarget(uri) {
12583
- const parsed = parseLocatedWikiGraphUri5(uri);
13814
+ const parsed = parseLocatedWikiGraphUri(uri);
12584
13815
  const objectUri = parsed.objectUri;
12585
13816
  if (objectUri === void 0) {
12586
13817
  return "archive-scope";
@@ -12596,6 +13827,9 @@ function classifyArchiveUriHelpTarget(uri) {
12596
13827
  if (path === "index") {
12597
13828
  return "index-object";
12598
13829
  }
13830
+ if (/^artifact\/[0-9a-f]{12,64}(?:#.+)?$/iu.test(path)) {
13831
+ return "artifact-object";
13832
+ }
12599
13833
  const chapterTarget = parseChapterTarget(objectUri);
12600
13834
  if (chapterTarget !== void 0) {
12601
13835
  switch (chapterTarget.kind) {
@@ -12609,6 +13843,8 @@ function classifyArchiveUriHelpTarget(uri) {
12609
13843
  return "chapter-state-object";
12610
13844
  case "chapter-index-artifact":
12611
13845
  return "chapter-index-artifact";
13846
+ case "source-locator-scope":
13847
+ return "chapter-source-locator-scope";
12612
13848
  case "chapter-resource":
12613
13849
  switch (chapterTarget.resource) {
12614
13850
  case "source":
@@ -12707,7 +13943,7 @@ function hasUriFragment(uri) {
12707
13943
  return uri.includes("#");
12708
13944
  }
12709
13945
  function parseArchiveUriTargetArguments(uri, action, tail, values) {
12710
- const parsed = parseLocatedWikiGraphUri5(uri);
13946
+ const parsed = parseLocatedWikiGraphUri(uri);
12711
13947
  const libraryArchiveObjectTarget = parseLibraryArchiveObjectTarget(uri);
12712
13948
  const archivePath = libraryArchiveObjectTarget === void 0 ? parsed.archivePath : formatLibraryArchiveLocator(libraryArchiveObjectTarget);
12713
13949
  const objectUri = libraryArchiveObjectTarget?.objectUri ?? parsed.objectUri;
@@ -13014,7 +14250,7 @@ function parseQueueAddArguments(tail, values, helpRoute) {
13014
14250
  };
13015
14251
  }
13016
14252
  function parseQueueAddInput(uri, helpRoute) {
13017
- const parsed = parseLocatedWikiGraphUri6(uri);
14253
+ const parsed = parseLocatedWikiGraphUri(uri);
13018
14254
  if (parsed.archivePath === void 0) {
13019
14255
  throw new Error(
13020
14256
  withHelpRoute(
@@ -15046,6 +16282,7 @@ async function runQueueCommand2(args) {
15046
16282
  // src/app/dispatch.ts
15047
16283
  init_support();
15048
16284
  init_support();
16285
+ init_home_target();
15049
16286
  import {
15050
16287
  ensureWikiGraphHomeSchemaCurrent,
15051
16288
  formatError as formatError3,
@@ -15070,7 +16307,9 @@ async function dispatchWikiGraphCLI(input) {
15070
16307
  `);
15071
16308
  return { exitCode: 0 };
15072
16309
  }
15073
- await ensureWikiGraphHomeSchemaCurrent();
16310
+ if (parsed.kind !== "maintenance-command" || !isWikiGraphHomeTarget(parsed.args.target)) {
16311
+ await ensureWikiGraphHomeSchemaCurrent();
16312
+ }
15074
16313
  switch (parsed.kind) {
15075
16314
  case "convert":
15076
16315
  await runConvertCommand2(parsed.args);
@@ -15114,14 +16353,18 @@ async function dispatchWikiGraphCLI(input) {
15114
16353
  }
15115
16354
  } catch (error) {
15116
16355
  if (shouldWriteJSONError(input.argv)) {
15117
- input.stdout.write(formatCLIJSON(createCLIErrorObject(error)));
16356
+ input.stdout.write(
16357
+ formatCLIJSON(createCLIErrorObject(error, input.argv))
16358
+ );
15118
16359
  return { exitCode: 1 };
15119
16360
  }
15120
16361
  if (shouldWriteJSONLError(input.argv)) {
15121
- input.stdout.write(formatCLIJSONLine(createCLIErrorObject(error)));
16362
+ input.stdout.write(
16363
+ formatCLIJSONLine(createCLIErrorObject(error, input.argv))
16364
+ );
15122
16365
  return { exitCode: 1 };
15123
16366
  }
15124
- input.stderr.write(`${formatCLIError(error)}
16367
+ input.stderr.write(`${formatCLIError(error, input.argv)}
15125
16368
  `);
15126
16369
  return { exitCode: 1 };
15127
16370
  }
@@ -15129,20 +16372,42 @@ async function dispatchWikiGraphCLI(input) {
15129
16372
  function shouldPrintDefaultHelp(argv, stdinIsTTY) {
15130
16373
  return argv.length === 0 && stdinIsTTY === true;
15131
16374
  }
15132
- function formatCLIError(error) {
16375
+ function formatCLIError(error, argv) {
15133
16376
  if (error instanceof LLMPaymentRequiredError) {
15134
16377
  return "LLM payment required. Check your provider billing status or account balance.";
15135
16378
  }
15136
- return formatError3(error);
16379
+ const message = formatError3(error);
16380
+ const relativeResolution = hasErrorCode(error, "ENOENT") ? getRelativeArchiveUriResolution(argv[0] ?? "") : void 0;
16381
+ if (relativeResolution === void 0) {
16382
+ return message;
16383
+ }
16384
+ return `${message}
16385
+ Archive URI \`${relativeResolution.inputUri}\` is relative to the current working directory:
16386
+ ${relativeResolution.workingDirectory}
16387
+ Resolved archive path:
16388
+ ${relativeResolution.resolvedArchivePath}
16389
+ See: wg help uri`;
15137
16390
  }
15138
- function createCLIErrorObject(error) {
16391
+ function createCLIErrorObject(error, argv) {
15139
16392
  return {
15140
16393
  error: {
15141
- message: formatCLIError(error),
16394
+ message: formatCLIError(error, argv),
15142
16395
  type: error instanceof LLMPaymentRequiredError ? "llm_payment_required" : "error"
15143
16396
  }
15144
16397
  };
15145
16398
  }
16399
+ function hasErrorCode(error, code) {
16400
+ const visited = /* @__PURE__ */ new Set();
16401
+ let current = error;
16402
+ while (current !== void 0 && !visited.has(current)) {
16403
+ visited.add(current);
16404
+ if (current instanceof Error && "code" in current && current.code === code) {
16405
+ return true;
16406
+ }
16407
+ current = current instanceof Error ? current.cause : void 0;
16408
+ }
16409
+ return false;
16410
+ }
15146
16411
  function shouldWriteJSONError(argv) {
15147
16412
  return argv.some((item) => item === "--json" || item.startsWith("--json="));
15148
16413
  }
@@ -15194,7 +16459,7 @@ async function runWikiGraphCLIWithEntryPolicy(input = {}, envPolicy) {
15194
16459
  stdout,
15195
16460
  stdoutIsTTY: input.stdoutIsTTY
15196
16461
  };
15197
- return await withWikiGraphRuntimeStateDirectoryPath(
16462
+ return await withNodeWikiGraphStorage(
15198
16463
  entryContext.stateDir,
15199
16464
  async () => withWikiGraphCLIRuntimeContext(context, async () => {
15200
16465
  const result = await dispatchWikiGraphCLI({
@@ -15259,7 +16524,7 @@ function throwIfAborted(signal) {
15259
16524
  }
15260
16525
  throw signal.reason instanceof Error ? signal.reason : new Error("The Wiki Graph CLI run was aborted.");
15261
16526
  }
15262
- var CaptureWritable = class extends Writable2 {
16527
+ var CaptureWritable = class extends Writable3 {
15263
16528
  #chunks = [];
15264
16529
  constructor(isTTY) {
15265
16530
  super();
@@ -15284,6 +16549,9 @@ var CaptureWritable = class extends Writable2 {
15284
16549
  callback();
15285
16550
  }
15286
16551
  };
16552
+
16553
+ // src/app/main.ts
16554
+ init_node_platform();
15287
16555
  export {
15288
16556
  createWikiGraphCLI,
15289
16557
  runWikiGraphCLI,