@lorepack/cli 0.0.0-stage → 0.1.0-alpha.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.
Files changed (229) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/commands/activate.d.ts +20 -0
  3. package/dist/commands/activate.d.ts.map +1 -0
  4. package/dist/commands/activate.js +171 -0
  5. package/dist/commands/activate.js.map +1 -0
  6. package/dist/commands/build.d.ts +3 -0
  7. package/dist/commands/build.d.ts.map +1 -0
  8. package/dist/commands/build.js +53 -0
  9. package/dist/commands/build.js.map +1 -0
  10. package/dist/commands/config.d.ts +14 -0
  11. package/dist/commands/config.d.ts.map +1 -0
  12. package/dist/commands/config.js +109 -0
  13. package/dist/commands/config.js.map +1 -0
  14. package/dist/commands/connect.d.ts +5 -0
  15. package/dist/commands/connect.d.ts.map +1 -0
  16. package/dist/commands/connect.js +196 -0
  17. package/dist/commands/connect.js.map +1 -0
  18. package/dist/commands/deploy.d.ts +14 -0
  19. package/dist/commands/deploy.d.ts.map +1 -0
  20. package/dist/commands/deploy.js +248 -0
  21. package/dist/commands/deploy.js.map +1 -0
  22. package/dist/commands/dev.d.ts +25 -0
  23. package/dist/commands/dev.d.ts.map +1 -0
  24. package/dist/commands/dev.js +227 -0
  25. package/dist/commands/dev.js.map +1 -0
  26. package/dist/commands/diff.d.ts +3 -0
  27. package/dist/commands/diff.d.ts.map +1 -0
  28. package/dist/commands/diff.js +75 -0
  29. package/dist/commands/diff.js.map +1 -0
  30. package/dist/commands/doctor.d.ts +14 -0
  31. package/dist/commands/doctor.d.ts.map +1 -0
  32. package/dist/commands/doctor.js +96 -0
  33. package/dist/commands/doctor.js.map +1 -0
  34. package/dist/commands/export.d.ts +3 -0
  35. package/dist/commands/export.d.ts.map +1 -0
  36. package/dist/commands/export.js +126 -0
  37. package/dist/commands/export.js.map +1 -0
  38. package/dist/commands/index.d.ts +8 -0
  39. package/dist/commands/index.d.ts.map +1 -0
  40. package/dist/commands/index.js +51 -0
  41. package/dist/commands/index.js.map +1 -0
  42. package/dist/commands/init.d.ts +3 -0
  43. package/dist/commands/init.d.ts.map +1 -0
  44. package/dist/commands/init.js +95 -0
  45. package/dist/commands/init.js.map +1 -0
  46. package/dist/commands/inspect.d.ts +15 -0
  47. package/dist/commands/inspect.d.ts.map +1 -0
  48. package/dist/commands/inspect.js +527 -0
  49. package/dist/commands/inspect.js.map +1 -0
  50. package/dist/commands/mcp.d.ts +12 -0
  51. package/dist/commands/mcp.d.ts.map +1 -0
  52. package/dist/commands/mcp.js +219 -0
  53. package/dist/commands/mcp.js.map +1 -0
  54. package/dist/commands/pack.d.ts +9 -0
  55. package/dist/commands/pack.d.ts.map +1 -0
  56. package/dist/commands/pack.js +57 -0
  57. package/dist/commands/pack.js.map +1 -0
  58. package/dist/commands/plan.d.ts +3 -0
  59. package/dist/commands/plan.d.ts.map +1 -0
  60. package/dist/commands/plan.js +44 -0
  61. package/dist/commands/plan.js.map +1 -0
  62. package/dist/commands/prune.d.ts +7 -0
  63. package/dist/commands/prune.d.ts.map +1 -0
  64. package/dist/commands/prune.js +341 -0
  65. package/dist/commands/prune.js.map +1 -0
  66. package/dist/commands/search.d.ts +3 -0
  67. package/dist/commands/search.d.ts.map +1 -0
  68. package/dist/commands/search.js +84 -0
  69. package/dist/commands/search.js.map +1 -0
  70. package/dist/commands/serve.d.ts +20 -0
  71. package/dist/commands/serve.d.ts.map +1 -0
  72. package/dist/commands/serve.js +66 -0
  73. package/dist/commands/serve.js.map +1 -0
  74. package/dist/commands/status.d.ts +3 -0
  75. package/dist/commands/status.d.ts.map +1 -0
  76. package/dist/commands/status.js +27 -0
  77. package/dist/commands/status.js.map +1 -0
  78. package/dist/commands/target.d.ts +71 -0
  79. package/dist/commands/target.d.ts.map +1 -0
  80. package/dist/commands/target.js +945 -0
  81. package/dist/commands/target.js.map +1 -0
  82. package/dist/entry.d.ts +3 -0
  83. package/dist/entry.d.ts.map +1 -0
  84. package/dist/entry.js +19 -0
  85. package/dist/entry.js.map +1 -0
  86. package/dist/framework/context.d.ts +49 -0
  87. package/dist/framework/context.d.ts.map +1 -0
  88. package/dist/framework/context.js +47 -0
  89. package/dist/framework/context.js.map +1 -0
  90. package/dist/framework/exit.d.ts +36 -0
  91. package/dist/framework/exit.d.ts.map +1 -0
  92. package/dist/framework/exit.js +57 -0
  93. package/dist/framework/exit.js.map +1 -0
  94. package/dist/framework/metadata.d.ts +38 -0
  95. package/dist/framework/metadata.d.ts.map +1 -0
  96. package/dist/framework/metadata.js +47 -0
  97. package/dist/framework/metadata.js.map +1 -0
  98. package/dist/framework/program.d.ts +47 -0
  99. package/dist/framework/program.d.ts.map +1 -0
  100. package/dist/framework/program.js +189 -0
  101. package/dist/framework/program.js.map +1 -0
  102. package/dist/index.d.ts +7 -0
  103. package/dist/index.d.ts.map +1 -0
  104. package/dist/index.js +7 -0
  105. package/dist/index.js.map +1 -0
  106. package/dist/migrations/README.md +7 -0
  107. package/dist/migrations/build/0001_catalog.sql +85 -0
  108. package/dist/migrations/build/0002_tables.sql +43 -0
  109. package/dist/migrations/build/0003_table-cell-range.sql +13 -0
  110. package/dist/migrations/build/0004_chunk-page.sql +11 -0
  111. package/dist/migrations/state/0001_state.sql +40 -0
  112. package/dist/public-entry.js +38563 -0
  113. package/dist/public-entry.js.map +7 -0
  114. package/dist/public-index.js +36428 -0
  115. package/dist/public-index.js.map +7 -0
  116. package/dist/services/build.d.ts +48 -0
  117. package/dist/services/build.d.ts.map +1 -0
  118. package/dist/services/build.js +499 -0
  119. package/dist/services/build.js.map +1 -0
  120. package/dist/services/builds.d.ts +40 -0
  121. package/dist/services/builds.d.ts.map +1 -0
  122. package/dist/services/builds.js +184 -0
  123. package/dist/services/builds.js.map +1 -0
  124. package/dist/services/cancellation.d.ts +27 -0
  125. package/dist/services/cancellation.d.ts.map +1 -0
  126. package/dist/services/cancellation.js +41 -0
  127. package/dist/services/cancellation.js.map +1 -0
  128. package/dist/services/cloudflare-target.d.ts +38 -0
  129. package/dist/services/cloudflare-target.d.ts.map +1 -0
  130. package/dist/services/cloudflare-target.js +471 -0
  131. package/dist/services/cloudflare-target.js.map +1 -0
  132. package/dist/services/comparer.d.ts +15 -0
  133. package/dist/services/comparer.d.ts.map +1 -0
  134. package/dist/services/comparer.js +43 -0
  135. package/dist/services/comparer.js.map +1 -0
  136. package/dist/services/config-resolve.d.ts +60 -0
  137. package/dist/services/config-resolve.d.ts.map +1 -0
  138. package/dist/services/config-resolve.js +178 -0
  139. package/dist/services/config-resolve.js.map +1 -0
  140. package/dist/services/deploy.d.ts +70 -0
  141. package/dist/services/deploy.d.ts.map +1 -0
  142. package/dist/services/deploy.js +260 -0
  143. package/dist/services/deploy.js.map +1 -0
  144. package/dist/services/dev-session.d.ts +52 -0
  145. package/dist/services/dev-session.d.ts.map +1 -0
  146. package/dist/services/dev-session.js +102 -0
  147. package/dist/services/dev-session.js.map +1 -0
  148. package/dist/services/doctor.d.ts +35 -0
  149. package/dist/services/doctor.d.ts.map +1 -0
  150. package/dist/services/doctor.js +389 -0
  151. package/dist/services/doctor.js.map +1 -0
  152. package/dist/services/export.d.ts +20 -0
  153. package/dist/services/export.d.ts.map +1 -0
  154. package/dist/services/export.js +129 -0
  155. package/dist/services/export.js.map +1 -0
  156. package/dist/services/init.d.ts +46 -0
  157. package/dist/services/init.d.ts.map +1 -0
  158. package/dist/services/init.js +231 -0
  159. package/dist/services/init.js.map +1 -0
  160. package/dist/services/packing.d.ts +25 -0
  161. package/dist/services/packing.d.ts.map +1 -0
  162. package/dist/services/packing.js +69 -0
  163. package/dist/services/packing.js.map +1 -0
  164. package/dist/services/parse-cache.d.ts +47 -0
  165. package/dist/services/parse-cache.d.ts.map +1 -0
  166. package/dist/services/parse-cache.js +65 -0
  167. package/dist/services/parse-cache.js.map +1 -0
  168. package/dist/services/project.d.ts +49 -0
  169. package/dist/services/project.d.ts.map +1 -0
  170. package/dist/services/project.js +119 -0
  171. package/dist/services/project.js.map +1 -0
  172. package/dist/services/remote-prune.d.ts +7 -0
  173. package/dist/services/remote-prune.d.ts.map +1 -0
  174. package/dist/services/remote-prune.js +34 -0
  175. package/dist/services/remote-prune.js.map +1 -0
  176. package/dist/services/retention.d.ts +20 -0
  177. package/dist/services/retention.d.ts.map +1 -0
  178. package/dist/services/retention.js +106 -0
  179. package/dist/services/retention.js.map +1 -0
  180. package/dist/services/revalidate.d.ts +36 -0
  181. package/dist/services/revalidate.d.ts.map +1 -0
  182. package/dist/services/revalidate.js +73 -0
  183. package/dist/services/revalidate.js.map +1 -0
  184. package/dist/services/search.d.ts +25 -0
  185. package/dist/services/search.d.ts.map +1 -0
  186. package/dist/services/search.js +88 -0
  187. package/dist/services/search.js.map +1 -0
  188. package/dist/services/serving.d.ts +70 -0
  189. package/dist/services/serving.d.ts.map +1 -0
  190. package/dist/services/serving.js +240 -0
  191. package/dist/services/serving.js.map +1 -0
  192. package/dist/services/status.d.ts +54 -0
  193. package/dist/services/status.d.ts.map +1 -0
  194. package/dist/services/status.js +203 -0
  195. package/dist/services/status.js.map +1 -0
  196. package/dist/services/studio-assets.d.ts +13 -0
  197. package/dist/services/studio-assets.d.ts.map +1 -0
  198. package/dist/services/studio-assets.js +94 -0
  199. package/dist/services/studio-assets.js.map +1 -0
  200. package/dist/services/studio-diagnostics.d.ts +28 -0
  201. package/dist/services/studio-diagnostics.d.ts.map +1 -0
  202. package/dist/services/studio-diagnostics.js +88 -0
  203. package/dist/services/studio-diagnostics.js.map +1 -0
  204. package/dist/services/studio-endpoints.d.ts +61 -0
  205. package/dist/services/studio-endpoints.d.ts.map +1 -0
  206. package/dist/services/studio-endpoints.js +88 -0
  207. package/dist/services/studio-endpoints.js.map +1 -0
  208. package/dist/services/studio-mutations.d.ts +32 -0
  209. package/dist/services/studio-mutations.d.ts.map +1 -0
  210. package/dist/services/studio-mutations.js +149 -0
  211. package/dist/services/studio-mutations.js.map +1 -0
  212. package/dist/services/versions.d.ts +38 -0
  213. package/dist/services/versions.d.ts.map +1 -0
  214. package/dist/services/versions.js +46 -0
  215. package/dist/services/versions.js.map +1 -0
  216. package/dist/services/watch.d.ts +103 -0
  217. package/dist/services/watch.d.ts.map +1 -0
  218. package/dist/services/watch.js +420 -0
  219. package/dist/services/watch.js.map +1 -0
  220. package/package.json +73 -4
  221. package/studio-dist/assets/ibm-plex-mono-latin-400-normal-Dm_PoFIZ.woff2 +0 -0
  222. package/studio-dist/assets/ibm-plex-mono-latin-500-normal-C_OblDzq.woff2 +0 -0
  223. package/studio-dist/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  224. package/studio-dist/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  225. package/studio-dist/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  226. package/studio-dist/assets/index-BuAYbQVX.js +66 -0
  227. package/studio-dist/assets/index-C_3XEUt4.css +1 -0
  228. package/studio-dist/index.html +30 -0
  229. package/README.md +0 -3
@@ -0,0 +1,88 @@
1
+ import { createLocalRuntimeBackend } from '@lorepack/backend-local';
2
+ import { count, LoreError, } from '@lorepack/core';
3
+ import { createRuntime } from '@lorepack/runtime';
4
+ export async function runSearch(options) {
5
+ const backend = createLocalRuntimeBackend({
6
+ projectRoot: options.config.projectRoot,
7
+ // The CLI has already established freshness for its own header, so the runtime is
8
+ // handed the answer rather than made to work it out again.
9
+ freshness: async () => options.sourceState,
10
+ });
11
+ try {
12
+ if ((await backend.provider.current()) === null) {
13
+ throw new LoreError('LORE_E_BUILD_NOT_FOUND', 'This project has no active build to search.', {
14
+ remediation: 'Run `lorepack build` first.',
15
+ });
16
+ }
17
+ return await createRuntime(backend).search({
18
+ query: options.query,
19
+ limit: options.limit ?? 10,
20
+ includeArchived: options.includeArchived ?? false,
21
+ debug: options.debug ?? false,
22
+ ...(options.pathGlob === undefined ? {} : { pathGlob: options.pathGlob }),
23
+ ...(options.type === undefined ? {} : { fileType: options.type }),
24
+ ...(options.artifactId === undefined ? {} : { artifactId: options.artifactId }),
25
+ });
26
+ }
27
+ finally {
28
+ backend.close();
29
+ }
30
+ }
31
+ export function renderSearch(result, query, verbose = false) {
32
+ const lines = [
33
+ `Build ${result.buildId.slice(0, 17)} (sources ${result.sourceState}), ${count(result.totalIndexedChunks, 'chunk')} indexed`,
34
+ '',
35
+ ];
36
+ if (result.hits.length === 0) {
37
+ lines.push(`No matches for "${query}".`);
38
+ lines.push('');
39
+ lines.push(result.totalIndexedChunks === 0
40
+ ? 'This build indexed nothing. Run `lorepack inspect warnings` to see what was skipped.'
41
+ : `Searched ${count(result.totalIndexedChunks, 'chunk')}. Try fewer or more general terms.`);
42
+ return lines.join('\n');
43
+ }
44
+ let rank = 0;
45
+ for (const hit of result.hits) {
46
+ rank += 1;
47
+ const where = hit.locator.lineStart === undefined
48
+ ? hit.locator.relativePath
49
+ : `${hit.locator.relativePath}:${hit.locator.lineStart}`;
50
+ // The rank is the claim, and the score is shown only when asked for. It is a
51
+ // relevance heuristic: how well the words match, not how likely the content is to be
52
+ // right. Printing it beside every result would invite reading it as confidence.
53
+ lines.push(`${String(rank).padStart(2)}. ${where}${verbose ? ` (relevance ${hit.score.toFixed(2)})` : ''}`);
54
+ if (hit.headingPath.length > 0)
55
+ lines.push(` ${hit.headingPath.join(' > ')}`);
56
+ if (hit.labels.length > 0)
57
+ lines.push(` [${hit.labels.join(', ')}]`);
58
+ lines.push(` ${hit.excerpt.replace(/\s+/g, ' ').trim()}`);
59
+ if (hit.scoreComponents !== undefined) {
60
+ lines.push(` why: ${renderComponents(hit.scoreComponents)}`);
61
+ }
62
+ lines.push('');
63
+ }
64
+ if (result.hits.some((hit) => hit.scoreComponents !== undefined)) {
65
+ lines.push('Relevance is a heuristic about matching words. It is not a confidence, and');
66
+ lines.push('it is not evidence that a document is correct.');
67
+ }
68
+ return lines.join('\n').trimEnd();
69
+ }
70
+ /** The components in the order they are applied, so the line reads like the calculation. */
71
+ function renderComponents(components) {
72
+ const order = [
73
+ 'lexical',
74
+ 'pathExact',
75
+ 'titleExact',
76
+ 'headingExact',
77
+ 'allTerms',
78
+ 'statusFactor',
79
+ 'authorityFactor',
80
+ 'supersededFactor',
81
+ 'total',
82
+ ];
83
+ return order
84
+ .filter((name) => components[name] !== undefined)
85
+ .map((name) => `${name} ${components[name].toFixed(2)}`)
86
+ .join(', ');
87
+ }
88
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/services/search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import { createLocalRuntimeBackend } from '@lorepack/backend-local';
2
+ import { type BuildId, type LoadedConfig } from '@lorepack/core';
3
+ /** Exported for the tests, which assert the wording rather than reproducing it. */
4
+ export declare const SERVE_DEFAULTS: {
5
+ readonly port: 4321;
6
+ readonly attempts: 20;
7
+ };
8
+ export interface ServingOptions {
9
+ readonly config: LoadedConfig;
10
+ readonly host: string;
11
+ readonly port: number;
12
+ readonly warn: (text: string) => void;
13
+ /**
14
+ * How the server decides whether the sources have moved on.
15
+ *
16
+ * Omitted, it polls with a metadata prescreen on `revalidateIntervalMs`. `lorepack dev` passes
17
+ * its watcher's answer instead, which is the hook #112 named and the Phase 3 audit expects
18
+ * #53 and #55 to use.
19
+ */
20
+ readonly freshness?: () => Promise<import('@lorepack/core').SourceState>;
21
+ readonly revalidateIntervalMs?: number;
22
+ /**
23
+ * Serve Studio at the root.
24
+ *
25
+ * `lorepack dev` does; `lorepack serve` does not, because Studio can activate and roll back and
26
+ * `lorepack serve` promises to be read-only and never to rebuild. Two commands with different
27
+ * promises should not quietly offer the same surface.
28
+ */
29
+ readonly studio?: boolean;
30
+ /**
31
+ * The watcher's live state, when there is a watcher.
32
+ *
33
+ * Supplied by `lorepack dev` for Studio's Diagnostics route. `lorepack serve` has no watcher and
34
+ * supplies nothing, and the route says so rather than inventing a state for it.
35
+ */
36
+ readonly watchStatus?: () => import('./watch.js').WatchStatus;
37
+ }
38
+ export interface RunningServer {
39
+ readonly url: string;
40
+ readonly port: number;
41
+ readonly buildId: BuildId;
42
+ /** Whether Studio's assets were found and mounted, so the caller knows what to print. */
43
+ readonly studio: boolean;
44
+ /** Drains in-flight requests, then releases the databases. Idempotent. */
45
+ readonly close: () => Promise<void>;
46
+ }
47
+ export interface ServingDependencies {
48
+ readonly createBackend?: typeof createLocalRuntimeBackend;
49
+ readonly listen?: typeof listen;
50
+ }
51
+ export declare function startServing(options: ServingOptions, dependencies?: ServingDependencies): Promise<RunningServer>;
52
+ interface Listening {
53
+ readonly port: number;
54
+ readonly close: () => Promise<void>;
55
+ }
56
+ /**
57
+ * Binds, stepping to the next port when one is taken.
58
+ *
59
+ * Architecture 6.9 asks for exactly this: an occupied port is an ordinary condition of a
60
+ * developer machine, not a failure, so the server moves and says where it went.
61
+ */
62
+ declare function listen(fetch: (request: Request) => Response | Promise<Response>, hostname: string, first: number, warn: (text: string) => void): Promise<Listening>;
63
+ /** Resolves on the first interrupt, so a caller can drain in its own order. */
64
+ export declare function untilInterrupted(warn: (text: string) => void): Promise<void>;
65
+ export declare function isLoopback(host: string): boolean;
66
+ /** Milliseconds, or 0 for every request. `off` belongs to `lorepack mcp`, which can pin. */
67
+ export declare function parseInterval(raw: unknown): number;
68
+ export declare function parsePort(raw: unknown): number;
69
+ export {};
70
+ //# sourceMappingURL=serving.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serving.d.ts","sourceRoot":"","sources":["../../src/services/serving.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAa,MAAM,gBAAgB,CAAC;AAkC5E,mFAAmF;AACnF,eAAO,MAAM,cAAc;aAAK,IAAI;aAAgB,QAAQ;CAA0B,CAAC;AAEvF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,gBAAgB,EAAE,WAAW,CAAC,CAAC;IACzE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,OAAO,YAAY,EAAE,WAAW,CAAC;CAC/D;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,yFAAyF;IACzF,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,yBAAyB,CAAC;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,MAAM,CAAC;CACjC;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,YAAY,GAAE,mBAAwB,GACrC,OAAO,CAAC,aAAa,CAAC,CAuJxB;AAED,UAAU,SAAS;IACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED;;;;;GAKG;AACH,iBAAe,MAAM,CACnB,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,EACzD,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC3B,OAAO,CAAC,SAAS,CAAC,CA2BpB;AAED,+EAA+E;AAC/E,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CASlF;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAclD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAS9C"}
@@ -0,0 +1,240 @@
1
+ import { serve } from '@hono/node-server';
2
+ import { createLocalRuntimeBackend } from '@lorepack/backend-local';
3
+ import { LoreError } from '@lorepack/core';
4
+ import { createMcpHttpHandler } from '@lorepack/mcp';
5
+ import { createApiApp, createRuntime } from '@lorepack/runtime';
6
+ import { createLocalComparer } from './comparer.js';
7
+ import { renderBundleMarkdown } from './export.js';
8
+ import { packBuild } from './packing.js';
9
+ import { createRevalidator, DEFAULT_REVALIDATE_INTERVAL_MS } from './revalidate.js';
10
+ import { createStudioAssets, studioIsBuilt } from './studio-assets.js';
11
+ import { createDiagnosticsEndpoint } from './studio-diagnostics.js';
12
+ import { createPlanEndpoint, createWarningsEndpoint } from './studio-endpoints.js';
13
+ import { createActivateEndpoint, createBuildsEndpoint, createRollbackEndpoint, } from './studio-mutations.js';
14
+ /**
15
+ * Serving an active build over HTTP and MCP, in one place, for the two commands that do it.
16
+ *
17
+ * `lorepack serve` and `lorepack dev` differ in what they are willing to do to a project: one never
18
+ * builds, the other builds and watches. They do not differ in how a build is served, and the
19
+ * Phase 3 audit on #4 is explicit that `lorepack dev` should supervise the existing server rather
20
+ * than grow a second one. Two servers would mean two port policies, two binding warnings and
21
+ * two ways to drain, and the difference between them would be discovered by a user.
22
+ *
23
+ * The freshness revalidator is injectable for the same reason. `lorepack serve` has no better
24
+ * information than an interval and a metadata prescreen, but a supervisor that is already
25
+ * watching the filesystem does, and supplying it is an injection rather than a rewrite.
26
+ */
27
+ const DEFAULT_PORT = 4321;
28
+ /** How many ports to try before giving up. Enough for several servers, few enough to fail. */
29
+ const PORT_ATTEMPTS = 20;
30
+ /** Exported for the tests, which assert the wording rather than reproducing it. */
31
+ export const SERVE_DEFAULTS = { port: DEFAULT_PORT, attempts: PORT_ATTEMPTS };
32
+ export async function startServing(options, dependencies = {}) {
33
+ const revalidator = createRevalidator({
34
+ config: options.config,
35
+ intervalMs: options.revalidateIntervalMs ?? DEFAULT_REVALIDATE_INTERVAL_MS,
36
+ });
37
+ const freshness = options.freshness ?? (() => revalidator.freshness());
38
+ const backend = (dependencies.createBackend ?? createLocalRuntimeBackend)({
39
+ projectRoot: options.config.projectRoot,
40
+ // Freshness is an annotation and never fails a read: a server that refused to answer
41
+ // because the source tree moved would be useless (#147).
42
+ freshness,
43
+ });
44
+ try {
45
+ const active = await backend.provider.current();
46
+ if (active === null) {
47
+ throw new LoreError('LORE_E_BUILD_NOT_FOUND', 'This project has no build to serve.', {
48
+ remediation: 'Run `lorepack build` first.',
49
+ });
50
+ }
51
+ const runtime = createRuntime(backend);
52
+ // One handler for the process, built once: it constructs a fresh server per request
53
+ // internally, which is what the stateless model asks for, and holds the machinery that
54
+ // would otherwise be rebuilt on every call.
55
+ const startedAt = new Date().toISOString();
56
+ // Filled in by `listen` below, which is where the port stops being a request and becomes
57
+ // a fact. Diagnostics reads it through a closure rather than being constructed twice.
58
+ let boundPort = options.port;
59
+ const comparer = createLocalComparer(options.config.projectRoot);
60
+ const mcp = createMcpHttpHandler(runtime, comparer);
61
+ // Absent when the package was installed without built assets, which is a broken install
62
+ // rather than a mode: saying nothing about Studio is better than printing a URL that 404s.
63
+ const serveStudio = options.studio === true && studioIsBuilt();
64
+ const app = createApiApp({
65
+ runtime,
66
+ currentBuild: () => backend.provider.current(),
67
+ freshness,
68
+ mcpHandler: (request) => mcp.fetch(request),
69
+ // Reads of the **active build**, so any server can answer them: they change nothing and
70
+ // they touch no source file. `lorepack serve` offering them is the same promise it already
71
+ // makes about `/v1/search`.
72
+ exportBundle: async (request) => {
73
+ const bundle = await runtime.contextForTask(request);
74
+ // The same renderer `lorepack export` uses, so "copy as export" is byte-identical rather
75
+ // than merely similar. A parity test asserts it.
76
+ return renderBundleMarkdown(bundle, {
77
+ projectName: options.config.config.name,
78
+ moreCommand: `lorepack export --task ${JSON.stringify(bundle.task)} --profile deep`,
79
+ sourceState: bundle.sourceState,
80
+ });
81
+ },
82
+ sources: async () => {
83
+ const handle = await backend.provider.acquire();
84
+ try {
85
+ const scope = await backend.open(handle);
86
+ return { buildId: handle.buildId, artifacts: await scope.catalog.artifacts() };
87
+ }
88
+ finally {
89
+ handle.release();
90
+ }
91
+ },
92
+ warnings: createWarningsEndpoint(async () => {
93
+ // Acquired and released like any other read, so a warnings request cannot pin a build
94
+ // open after it stops being active.
95
+ const handle = await backend.provider.acquire();
96
+ try {
97
+ const scope = await backend.open(handle);
98
+ const manifest = await scope.catalog.manifest();
99
+ return {
100
+ buildId: manifest.buildId,
101
+ warnings: manifest.warnings,
102
+ ...(manifest.exclusions === undefined ? {} : { exclusions: manifest.exclusions }),
103
+ };
104
+ }
105
+ finally {
106
+ handle.release();
107
+ }
108
+ }),
109
+ ...(serveStudio
110
+ ? {
111
+ assets: createStudioAssets(),
112
+ allowLoopbackOrigin: true,
113
+ // The one Studio read that is **not** a read of the build: planning walks the
114
+ // source tree. `lorepack serve` promises never to rebuild and has no business reading
115
+ // sources, so this belongs to `lorepack dev` alone.
116
+ plan: createPlanEndpoint(options.config),
117
+ // Reads the machine rather than the build: SQLite controls, the watcher, the
118
+ // process serving this request. The port is passed as a function because it is
119
+ // chosen by binding, which has not happened yet at this line.
120
+ diagnostics: createDiagnosticsEndpoint({
121
+ config: options.config,
122
+ host: options.host,
123
+ port: () => boundPort,
124
+ startedAt,
125
+ ...(options.watchStatus === undefined ? {} : { watchStatus: options.watchStatus }),
126
+ }),
127
+ // The only writes in this API, and they exist only here. `lorepack serve` promises to
128
+ // be read-only, so it passes no actions and simply does not have these routes.
129
+ localActions: {
130
+ builds: createBuildsEndpoint(options.config),
131
+ diff: (from, to) => comparer.compare(from, to),
132
+ activate: createActivateEndpoint(options.config),
133
+ rollback: createRollbackEndpoint(options.config),
134
+ pack: async (request) => {
135
+ const asked = request;
136
+ return packBuild(options.config, { build: asked.build, out: asked.out });
137
+ },
138
+ },
139
+ }
140
+ : {}),
141
+ });
142
+ if (!isLoopback(options.host)) {
143
+ // Architecture 15.3: binding beyond loopback is possible and never accidental.
144
+ options.warn(`Warning: binding to ${options.host} exposes this build to your network. It is read-only, and it is still your documents.\n`);
145
+ }
146
+ const server = await (dependencies.listen ?? listen)(app.fetch, options.host, options.port, options.warn);
147
+ boundPort = server.port;
148
+ let closed = false;
149
+ return {
150
+ url: `http://${options.host}:${server.port}`,
151
+ port: server.port,
152
+ buildId: active.buildId,
153
+ studio: serveStudio,
154
+ close: async () => {
155
+ if (closed)
156
+ return;
157
+ closed = true;
158
+ // Order matters: `close()` stops new connections and waits for in-flight requests,
159
+ // and only then are the databases released. Releasing first would let a request in
160
+ // flight read a closed handle.
161
+ await server.close();
162
+ await mcp.close();
163
+ backend.close();
164
+ },
165
+ };
166
+ }
167
+ catch (error) {
168
+ backend.close();
169
+ throw error;
170
+ }
171
+ }
172
+ /**
173
+ * Binds, stepping to the next port when one is taken.
174
+ *
175
+ * Architecture 6.9 asks for exactly this: an occupied port is an ordinary condition of a
176
+ * developer machine, not a failure, so the server moves and says where it went.
177
+ */
178
+ async function listen(fetch, hostname, first, warn) {
179
+ for (let attempt = 0; attempt < PORT_ATTEMPTS; attempt += 1) {
180
+ const port = first + attempt;
181
+ try {
182
+ const server = await new Promise((resolve, reject) => {
183
+ const started = serve({ fetch, hostname, port }, () => resolve(started));
184
+ started.on('error', reject);
185
+ });
186
+ if (attempt > 0)
187
+ warn(`Port ${first} was busy, using ${port}.\n`);
188
+ return {
189
+ port,
190
+ close: () => new Promise((resolve) => {
191
+ server.close(() => resolve());
192
+ }),
193
+ };
194
+ }
195
+ catch (error) {
196
+ const code = error.code;
197
+ if (code !== 'EADDRINUSE')
198
+ throw error;
199
+ }
200
+ }
201
+ throw new LoreError('LORE_E_INVALID_ARGUMENT', `No free port between ${first} and ${first + PORT_ATTEMPTS - 1}.`, { remediation: 'Pass a different --port, or stop whatever is using this range.' });
202
+ }
203
+ /** Resolves on the first interrupt, so a caller can drain in its own order. */
204
+ export async function untilInterrupted(warn) {
205
+ await new Promise((resolve) => {
206
+ const stop = (signal) => {
207
+ warn(`\nStopping on ${signal}. Draining requests.\n`);
208
+ resolve();
209
+ };
210
+ process.once('SIGINT', () => stop('SIGINT'));
211
+ process.once('SIGTERM', () => stop('SIGTERM'));
212
+ });
213
+ }
214
+ export function isLoopback(host) {
215
+ return host === '127.0.0.1' || host === 'localhost' || host === '::1';
216
+ }
217
+ /** Milliseconds, or 0 for every request. `off` belongs to `lorepack mcp`, which can pin. */
218
+ export function parseInterval(raw) {
219
+ // `Number('')` is 0, and 0 is the most expensive setting there is: it content-hashes the
220
+ // corpus on every request. Reaching it by writing nothing, which is what a shell does
221
+ // with an unset variable, is not a choice anyone made (#195).
222
+ const blank = typeof raw === 'string' && raw.trim() === '';
223
+ const value = blank ? Number.NaN : Number(raw);
224
+ if (!Number.isFinite(value) || value < 0) {
225
+ throw new LoreError('LORE_E_INVALID_ARGUMENT', `--revalidate-interval must be a number of milliseconds, got ${raw}.`, { remediation: 'Pass milliseconds, or 0 to recheck on every request.' });
226
+ }
227
+ return value;
228
+ }
229
+ export function parsePort(raw) {
230
+ if (raw === undefined)
231
+ return DEFAULT_PORT;
232
+ const value = Number(raw);
233
+ if (!Number.isInteger(value) || value < 1 || value > 65_535) {
234
+ throw new LoreError('LORE_E_INVALID_ARGUMENT', `--port must be a port number, got ${raw}.`, {
235
+ remediation: `Pass a number between 1 and 65535, for example --port ${DEFAULT_PORT}.`,
236
+ });
237
+ }
238
+ return value;
239
+ }
240
+ //# sourceMappingURL=serving.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serving.js","sourceRoot":"","sources":["../../src/services/serving.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAmC,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAE/B;;;;;;;;;;;;GAYG;AAEH,MAAM,YAAY,GAAG,IAAI,CAAC;AAC1B,8FAA8F;AAC9F,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB,mFAAmF;AACnF,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAW,CAAC;AAgDvF,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAuB,EACvB,YAAY,GAAwB,EAAE;IAEtC,MAAM,WAAW,GAAG,iBAAiB,CAAC;QACpC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,UAAU,EAAE,OAAO,CAAC,oBAAoB,IAAI,8BAA8B;KAC3E,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC;IAEvE,MAAM,OAAO,GAAG,CAAC,YAAY,CAAC,aAAa,IAAI,yBAAyB,CAAC,CAAC;QACxE,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW;QACvC,qFAAqF;QACrF,yDAAyD;QACzD,SAAS;KACV,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QAChD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,MAAM,IAAI,SAAS,CAAC,wBAAwB,EAAE,qCAAqC,EAAE;gBACnF,WAAW,EAAE,6BAA6B;aAC3C,CAAC,CAAC;QACL,CAAC;QAED,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACvC,oFAAoF;QACpF,uFAAuF;QACvF,4CAA4C;QAC5C,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,yFAAyF;QACzF,sFAAsF;QACtF,IAAI,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;QAE7B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,oBAAoB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACpD,wFAAwF;QACxF,2FAA2F;QAC3F,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,KAAK,IAAI,IAAI,aAAa,EAAE,CAAC;QAC/D,MAAM,GAAG,GAAG,YAAY,CAAC;YACvB,OAAO;YACP,YAAY,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE;YAC9C,SAAS;YACT,UAAU,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;YAC3C,wFAAwF;YACxF,2FAA2F;YAC3F,4BAA4B;YAC5B,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC9B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,cAAc,CACzC,OAAuD,CACxD,CAAC;gBACF,yFAAyF;gBACzF,iDAAiD;gBACjD,OAAO,oBAAoB,CAAC,MAAM,EAAE;oBAClC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI;oBACvC,WAAW,EAAE,0BAA0B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB;oBACnF,WAAW,EAAE,MAAM,CAAC,WAAW;iBAChC,CAAC,CAAC;YACL,CAAC;YACD,OAAO,EAAE,KAAK,IAAI,EAAE;gBAClB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;gBAChD,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBACzC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;gBACjF,CAAC;wBAAS,CAAC;oBACT,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,CAAC;YACH,CAAC;YACD,QAAQ,EAAE,sBAAsB,CAAC,KAAK,IAAI,EAAE;gBAC1C,sFAAsF;gBACtF,oCAAoC;gBACpC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;gBAChD,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBACzC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;oBAChD,OAAO;wBACL,OAAO,EAAE,QAAQ,CAAC,OAAO;wBACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;wBAC3B,GAAG,CAAC,QAAQ,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC;qBAClF,CAAC;gBACJ,CAAC;wBAAS,CAAC;oBACT,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,CAAC;YACH,CAAC,CAAC;YACF,GAAG,CAAC,WAAW;gBACb,CAAC,CAAC;oBACE,MAAM,EAAE,kBAAkB,EAAE;oBAC5B,mBAAmB,EAAE,IAAI;oBACzB,8EAA8E;oBAC9E,sFAAsF;oBACtF,oDAAoD;oBACpD,IAAI,EAAE,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC;oBACxC,6EAA6E;oBAC7E,+EAA+E;oBAC/E,8DAA8D;oBAC9D,WAAW,EAAE,yBAAyB,CAAC;wBACrC,MAAM,EAAE,OAAO,CAAC,MAAM;wBACtB,IAAI,EAAE,OAAO,CAAC,IAAI;wBAClB,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;wBACrB,SAAS;wBACT,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;qBACnF,CAAC;oBACF,sFAAsF;oBACtF,+EAA+E;oBAC/E,YAAY,EAAE;wBACZ,MAAM,EAAE,oBAAoB,CAAC,OAAO,CAAC,MAAM,CAAC;wBAC5C,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;wBAC9C,QAAQ,EAAE,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC;wBAChD,QAAQ,EAAE,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC;wBAChD,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;4BACtB,MAAM,KAAK,GAAG,OAA2C,CAAC;4BAC1D,OAAO,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;wBAC3E,CAAC;qBACF;iBACF;gBACH,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,+EAA+E;YAC/E,OAAO,CAAC,IAAI,CACV,uBAAuB,OAAO,CAAC,IAAI,yFAAyF,CAC7H,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,IAAI,MAAM,CAAC,CAClD,GAAG,CAAC,KAAK,EACT,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,IAAI,CACb,CAAC;QACF,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC;QAExB,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,OAAO;YACL,GAAG,EAAE,UAAU,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE;YAC5C,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,KAAK,IAAI,EAAE;gBAChB,IAAI,MAAM;oBAAE,OAAO;gBACnB,MAAM,GAAG,IAAI,CAAC;gBACd,mFAAmF;gBACnF,mFAAmF;gBACnF,+BAA+B;gBAC/B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;gBACrB,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;gBAClB,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,CAAC;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAOD;;;;;GAKG;AACH,KAAK,UAAU,MAAM,CACnB,KAAyD,EACzD,QAAgB,EAChB,KAAa,EACb,IAA4B;IAE5B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,aAAa,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,GAAG,KAAK,GAAG,OAAO,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC7E,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;gBACzE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;YACH,IAAI,OAAO,GAAG,CAAC;gBAAE,IAAI,CAAC,QAAQ,KAAK,oBAAoB,IAAI,KAAK,CAAC,CAAC;YAClE,OAAO;gBACL,IAAI;gBACJ,KAAK,EAAE,GAAG,EAAE,CACV,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;oBAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;gBAChC,CAAC,CAAC;aACL,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,GAAI,KAA2B,CAAC,IAAI,CAAC;YAC/C,IAAI,IAAI,KAAK,YAAY;gBAAE,MAAM,KAAK,CAAC;QACzC,CAAC;IACH,CAAC;IAED,MAAM,IAAI,SAAS,CACjB,yBAAyB,EACzB,wBAAwB,KAAK,QAAQ,KAAK,GAAG,aAAa,GAAG,CAAC,GAAG,EACjE,EAAE,WAAW,EAAE,gEAAgE,EAAE,CAClF,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAA4B;IACjE,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,CAAC,MAAc,EAAQ,EAAE;YACpC,IAAI,CAAC,iBAAiB,MAAM,wBAAwB,CAAC,CAAC;YACtD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,KAAK,CAAC;AACxE,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,yFAAyF;IACzF,sFAAsF;IACtF,8DAA8D;IAC9D,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;IAC3D,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,SAAS,CACjB,yBAAyB,EACzB,+DAA+D,GAAG,GAAG,EACrE,EAAE,WAAW,EAAE,sDAAsD,EAAE,CACxE,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAY;IACpC,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,YAAY,CAAC;IAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,MAAM,EAAE,CAAC;QAC5D,MAAM,IAAI,SAAS,CAAC,yBAAyB,EAAE,qCAAqC,GAAG,GAAG,EAAE;YAC1F,WAAW,EAAE,yDAAyD,YAAY,GAAG;SACtF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { type LoadedConfig, type ProgressBus, type SourceState, type Status } from '@lorepack/core';
2
+ /**
3
+ * `lorepack status` answers one question: is the context my AI reads current?
4
+ *
5
+ * It never writes, not even a migration or a cache entry. Status is run constantly, often
6
+ * in a prompt, and a command that mutated a project as a side effect of being asked about
7
+ * it would be a trap.
8
+ */
9
+ export interface StatusOptions {
10
+ readonly config: LoadedConfig;
11
+ readonly progress?: ProgressBus;
12
+ readonly allowLargeProject?: boolean;
13
+ readonly now?: () => Date;
14
+ }
15
+ export declare function readStatus(options: StatusOptions): Promise<Status>;
16
+ export interface Freshness {
17
+ readonly sourceState: SourceState;
18
+ /** Why freshness could not be established, for the human rendering. Null when it was. */
19
+ readonly reason: string | null;
20
+ }
21
+ /**
22
+ * Freshness for a read-only command: an annotation on the answer, never a precondition
23
+ * for it.
24
+ *
25
+ * Section 4.10 says freshness travels with the result, and it is tempting to read that as
26
+ * "establish it or fail". That reading cost `lorepack search` its usefulness on any project
27
+ * above the file envelope: the build existed and was perfectly queryable, and the query was
28
+ * refused because a guard about the cost of *building* had been consulted first (#147). A
29
+ * read of a sealed build is not entitled to have an opinion about the source tree.
30
+ *
31
+ * So two things differ from `readStatus`:
32
+ *
33
+ * - **The envelope does not apply.** It bounds what Lorepack promises about build
34
+ * performance, not what it will answer from a build it already made.
35
+ * - **Nothing here can fail the command.** A source tree that is enormous, unreadable or
36
+ * gone leaves freshness `unknown`, which is precisely what the contract's third state
37
+ * means, and the caller still gets the build's answer.
38
+ *
39
+ * Invariant 6 applies to the degraded case too: `unknown` says Lorepack does not know, and
40
+ * never that the sources are clean.
41
+ */
42
+ export declare function readFreshness(options: StatusOptions): Promise<Freshness>;
43
+ /**
44
+ * Which failures are allowed to become `unknown`, and which must still be raised.
45
+ *
46
+ * An allowlist rather than a bare `catch`. Swallowing everything would turn a corrupt
47
+ * state database into the cheerful and false statement "freshness unknown", which is the
48
+ * kind of helpfulness that hides a real defect for a phase or two. These three all mean
49
+ * "something about the source tree stopped us looking", and none of them says anything
50
+ * about whether the build being read is sound.
51
+ */
52
+ export declare function degradedFreshness(error: unknown): Freshness | null;
53
+ export declare function renderStatus(status: Status, verbose: boolean): string;
54
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/services/status.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,YAAY,EAEjB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,MAAM,EACZ,MAAM,gBAAgB,CAAC;AAGxB;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC;IAChC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAiExE;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,yFAAyF;IACzF,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAY9E;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CASlE;AAsCD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CA0CrE"}