@doxbrix/doxloop 0.1.4 → 0.2.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 (357) hide show
  1. package/CHANGELOG.md +1153 -0
  2. package/README.md +422 -226
  3. package/assets/doxbrix-preview.css +77 -15
  4. package/contracts/agent-events-v1.schema.json +1 -0
  5. package/contracts/coverage-v1.schema.json +59 -0
  6. package/contracts/drift-v1.schema.json +1 -0
  7. package/contracts/evaluation-v1.schema.json +62 -0
  8. package/contracts/quality-codes-v1.json +1 -0
  9. package/contracts/quality-report-v1.schema.json +1 -0
  10. package/contracts/validation-v1.schema.json +1 -0
  11. package/dist/agent-failure.d.ts +36 -0
  12. package/dist/agent-failure.js +98 -0
  13. package/dist/agent-isolation.d.ts +17 -0
  14. package/dist/agent-isolation.js +94 -0
  15. package/dist/agent-log.d.ts +197 -0
  16. package/dist/agent-log.js +1094 -0
  17. package/dist/agent-process.d.ts +63 -0
  18. package/dist/agent-process.js +128 -0
  19. package/dist/agent-reply.d.ts +47 -0
  20. package/dist/agent-reply.js +315 -0
  21. package/dist/agents.d.ts +40 -4
  22. package/dist/agents.js +115 -11
  23. package/dist/api-coverage.d.ts +11 -0
  24. package/dist/api-coverage.js +72 -0
  25. package/dist/application-probe.d.ts +28 -0
  26. package/dist/application-probe.js +93 -0
  27. package/dist/application-url.d.ts +14 -0
  28. package/dist/application-url.js +26 -0
  29. package/dist/args.js +15 -0
  30. package/dist/artifact-deploy.d.ts +9 -0
  31. package/dist/artifact-deploy.js +28 -8
  32. package/dist/assets.d.ts +72 -0
  33. package/dist/assets.js +382 -0
  34. package/dist/auth.d.ts +10 -0
  35. package/dist/auth.js +38 -9
  36. package/dist/author.d.ts +206 -4
  37. package/dist/author.js +1650 -52
  38. package/dist/authoring-batches.d.ts +190 -0
  39. package/dist/authoring-batches.js +489 -0
  40. package/dist/authoring-postpass.d.ts +79 -0
  41. package/dist/authoring-postpass.js +1289 -0
  42. package/dist/authoring-progress.d.ts +95 -0
  43. package/dist/authoring-progress.js +269 -0
  44. package/dist/autosync.d.ts +56 -0
  45. package/dist/autosync.js +442 -0
  46. package/dist/batch-artifacts.d.ts +81 -0
  47. package/dist/batch-artifacts.js +412 -0
  48. package/dist/batch-limits.d.ts +37 -0
  49. package/dist/batch-limits.js +80 -0
  50. package/dist/branding.d.ts +41 -0
  51. package/dist/branding.js +229 -0
  52. package/dist/bundle-upload.d.ts +26 -0
  53. package/dist/bundle-upload.js +99 -0
  54. package/dist/capture-auth.d.ts +95 -0
  55. package/dist/capture-auth.js +204 -0
  56. package/dist/capture.d.ts +48 -0
  57. package/dist/capture.js +20 -1
  58. package/dist/cli.js +839 -32
  59. package/dist/content-links.d.ts +10 -0
  60. package/dist/content-links.js +49 -0
  61. package/dist/contract-validation.d.ts +4 -0
  62. package/dist/contract-validation.js +25 -0
  63. package/dist/coverage-actions.d.ts +8 -0
  64. package/dist/coverage-actions.js +71 -0
  65. package/dist/coverage-resolutions.d.ts +16 -0
  66. package/dist/coverage-resolutions.js +58 -0
  67. package/dist/db.d.ts +37 -0
  68. package/dist/db.js +288 -0
  69. package/dist/demo.d.ts +12 -0
  70. package/dist/demo.js +122 -0
  71. package/dist/deploy-credentials.d.ts +7 -0
  72. package/dist/deploy-credentials.js +76 -0
  73. package/dist/deploy-targets/github-pages.d.ts +3 -0
  74. package/dist/deploy-targets/github-pages.js +100 -0
  75. package/dist/deploy-targets/index.d.ts +8 -0
  76. package/dist/deploy-targets/index.js +78 -0
  77. package/dist/deploy-targets/netlify.d.ts +3 -0
  78. package/dist/deploy-targets/netlify.js +49 -0
  79. package/dist/deploy-targets/types.d.ts +32 -0
  80. package/dist/deploy-targets/types.js +2 -0
  81. package/dist/deploy-targets/vercel.d.ts +3 -0
  82. package/dist/deploy-targets/vercel.js +95 -0
  83. package/dist/deploy.d.ts +9 -0
  84. package/dist/deploy.js +87 -13
  85. package/dist/deterministic-capture.d.ts +90 -0
  86. package/dist/deterministic-capture.js +435 -0
  87. package/dist/direct-edit.d.ts +40 -0
  88. package/dist/direct-edit.js +159 -0
  89. package/dist/docs-crawl.d.ts +86 -0
  90. package/dist/docs-crawl.js +536 -0
  91. package/dist/docs-site.d.ts +49 -0
  92. package/dist/docs-site.js +233 -0
  93. package/dist/doctor.js +8 -0
  94. package/dist/documentation-collections.d.ts +23 -0
  95. package/dist/documentation-collections.js +191 -0
  96. package/dist/documentation-plan.d.ts +253 -0
  97. package/dist/documentation-plan.js +2563 -0
  98. package/dist/doxbrix-build.d.ts +19 -0
  99. package/dist/doxbrix-build.js +167 -0
  100. package/dist/doxbrix-markdown.d.ts +9 -0
  101. package/dist/doxbrix-markdown.js +115 -14
  102. package/dist/drift.d.ts +10 -0
  103. package/dist/drift.js +164 -0
  104. package/dist/evaluation.d.ts +46 -0
  105. package/dist/evaluation.js +113 -0
  106. package/dist/evidence-pack.d.ts +47 -0
  107. package/dist/evidence-pack.js +358 -0
  108. package/dist/evidence.d.ts +25 -0
  109. package/dist/evidence.js +175 -0
  110. package/dist/fs.d.ts +8 -2
  111. package/dist/fs.js +41 -11
  112. package/dist/generator-api.d.ts +89 -0
  113. package/dist/generator-preflight.d.ts +27 -0
  114. package/dist/generator-preflight.js +105 -0
  115. package/dist/generator-runtime.d.ts +7 -0
  116. package/dist/generator-runtime.js +17 -1
  117. package/dist/generators.d.ts +24 -2
  118. package/dist/generators.js +54 -1
  119. package/dist/git-delivery.d.ts +17 -0
  120. package/dist/git-delivery.js +123 -0
  121. package/dist/globs.d.ts +16 -0
  122. package/dist/globs.js +65 -0
  123. package/dist/glossary.d.ts +26 -0
  124. package/dist/glossary.js +179 -0
  125. package/dist/history.d.ts +106 -0
  126. package/dist/history.js +600 -0
  127. package/dist/html-markdown.d.ts +46 -0
  128. package/dist/html-markdown.js +423 -0
  129. package/dist/interactive.js +16 -15
  130. package/dist/job-events.d.ts +74 -0
  131. package/dist/job-events.js +377 -0
  132. package/dist/keep-awake.d.ts +50 -0
  133. package/dist/keep-awake.js +123 -0
  134. package/dist/local-source-snapshot.d.ts +20 -0
  135. package/dist/local-source-snapshot.js +61 -0
  136. package/dist/mintlify-detect.d.ts +3 -0
  137. package/dist/mintlify-detect.js +18 -0
  138. package/dist/mintlify-import.d.ts +75 -0
  139. package/dist/mintlify-import.js +190 -0
  140. package/dist/navigation.d.ts +98 -0
  141. package/dist/navigation.js +310 -0
  142. package/dist/openapi.d.ts +60 -0
  143. package/dist/openapi.js +439 -0
  144. package/dist/page-editor-bridge.d.ts +3 -0
  145. package/dist/page-editor-bridge.js +109 -0
  146. package/dist/page-editor-preview.d.ts +10 -0
  147. package/dist/page-editor-preview.js +55 -0
  148. package/dist/page-extension.d.ts +9 -0
  149. package/dist/page-extension.js +15 -0
  150. package/dist/page-metadata.d.ts +28 -0
  151. package/dist/page-metadata.js +166 -0
  152. package/dist/page-operations.d.ts +34 -0
  153. package/dist/page-operations.js +215 -0
  154. package/dist/page-routes.d.ts +4 -0
  155. package/dist/page-routes.js +61 -0
  156. package/dist/pages.d.ts +20 -0
  157. package/dist/pages.js +184 -0
  158. package/dist/plan-generator.d.ts +3 -0
  159. package/dist/plan-generator.js +21 -0
  160. package/dist/plan-navigation.d.ts +11 -0
  161. package/dist/plan-navigation.js +30 -0
  162. package/dist/planning-captures.d.ts +20 -0
  163. package/dist/planning-captures.js +143 -0
  164. package/dist/planning-research.d.ts +135 -0
  165. package/dist/planning-research.js +472 -0
  166. package/dist/planning-triage.d.ts +23 -0
  167. package/dist/planning-triage.js +131 -0
  168. package/dist/preview.d.ts +24 -0
  169. package/dist/preview.js +280 -29
  170. package/dist/project-detect.d.ts +36 -0
  171. package/dist/project-detect.js +251 -0
  172. package/dist/project-import.d.ts +54 -0
  173. package/dist/project-import.js +157 -0
  174. package/dist/project-lock.d.ts +6 -0
  175. package/dist/project-lock.js +96 -0
  176. package/dist/project-registry.d.ts +25 -0
  177. package/dist/project-registry.js +79 -0
  178. package/dist/project.d.ts +35 -3
  179. package/dist/project.js +388 -38
  180. package/dist/prompts.d.ts +9 -0
  181. package/dist/prompts.js +33 -4
  182. package/dist/proposal-replay.d.ts +32 -0
  183. package/dist/proposal-replay.js +99 -0
  184. package/dist/quality-claims.d.ts +8 -0
  185. package/dist/quality-claims.js +168 -0
  186. package/dist/quality-config.d.ts +5 -0
  187. package/dist/quality-config.js +84 -0
  188. package/dist/quality-contract.d.ts +37 -0
  189. package/dist/quality-contract.js +46 -0
  190. package/dist/quality-examples.d.ts +4 -0
  191. package/dist/quality-examples.js +233 -0
  192. package/dist/quality-gates.d.ts +16 -0
  193. package/dist/quality-gates.js +192 -0
  194. package/dist/quality-links.d.ts +7 -0
  195. package/dist/quality-links.js +149 -0
  196. package/dist/quality-lint.d.ts +6 -0
  197. package/dist/quality-lint.js +124 -0
  198. package/dist/quality-rendered.d.ts +11 -0
  199. package/dist/quality-rendered.js +222 -0
  200. package/dist/quality-schema.d.ts +3 -0
  201. package/dist/quality-schema.js +71 -0
  202. package/dist/release-notes.d.ts +44 -0
  203. package/dist/release-notes.js +183 -0
  204. package/dist/remote-monitor.d.ts +16 -0
  205. package/dist/remote-monitor.js +74 -0
  206. package/dist/remote-source.d.ts +34 -0
  207. package/dist/remote-source.js +426 -0
  208. package/dist/review-diff.d.ts +82 -0
  209. package/dist/review-diff.js +400 -0
  210. package/dist/review-learning.d.ts +11 -0
  211. package/dist/review-learning.js +60 -0
  212. package/dist/review-render.d.ts +38 -0
  213. package/dist/review-render.js +224 -0
  214. package/dist/review-report.d.ts +9 -0
  215. package/dist/review-report.js +89 -0
  216. package/dist/review-ui.d.ts +14 -0
  217. package/dist/review-ui.js +1248 -0
  218. package/dist/schedule.d.ts +78 -0
  219. package/dist/schedule.js +480 -0
  220. package/dist/screen-capture-provider.d.ts +52 -0
  221. package/dist/screen-capture-provider.js +218 -0
  222. package/dist/screenshot-workflow.d.ts +167 -0
  223. package/dist/screenshot-workflow.js +1237 -0
  224. package/dist/settings.d.ts +1 -1
  225. package/dist/settings.js +95 -7
  226. package/dist/site-export.d.ts +18 -0
  227. package/dist/site-export.js +87 -0
  228. package/dist/source-connectors.d.ts +33 -0
  229. package/dist/source-connectors.js +268 -0
  230. package/dist/source-discovery.d.ts +132 -0
  231. package/dist/source-discovery.js +823 -0
  232. package/dist/source-intelligence.d.ts +9 -0
  233. package/dist/source-intelligence.js +306 -0
  234. package/dist/sync-review.d.ts +28 -0
  235. package/dist/sync-review.js +264 -0
  236. package/dist/sync-runs.d.ts +192 -0
  237. package/dist/sync-runs.js +2244 -0
  238. package/dist/sync.d.ts +35 -0
  239. package/dist/sync.js +298 -32
  240. package/dist/text-diff.d.ts +9 -0
  241. package/dist/text-diff.js +59 -0
  242. package/dist/types.d.ts +946 -1
  243. package/dist/ui/assets/doxloop-logo-light-De7Nx7j7.png +0 -0
  244. package/dist/ui/assets/index-BHBYU2aG.css +1 -0
  245. package/dist/ui/assets/index-Cq3RPQiC.js +33 -0
  246. package/dist/ui/index.html +18 -0
  247. package/dist/ui-server.d.ts +83 -0
  248. package/dist/ui-server.js +3532 -0
  249. package/dist/usage-budget.d.ts +28 -0
  250. package/dist/usage-budget.js +90 -0
  251. package/dist/validation.d.ts +25 -1
  252. package/dist/validation.js +312 -26
  253. package/dist/workspace-tools.d.ts +54 -0
  254. package/dist/workspace-tools.js +123 -0
  255. package/docs/agent-compatibility.md +50 -28
  256. package/docs/ci-and-automation.md +105 -66
  257. package/docs/doxbrix-http-api.md +8 -1
  258. package/docs/existing-documentation.md +80 -0
  259. package/docs/generation-performance.md +108 -0
  260. package/docs/generator-authoring.md +68 -5
  261. package/docs/generator-selection.md +50 -13
  262. package/docs/mintlify-import.md +71 -0
  263. package/docs/openapi-security.md +25 -0
  264. package/docs/project-format.md +331 -36
  265. package/docs/release-quality.md +158 -0
  266. package/docs/releasing.md +72 -0
  267. package/docs/review-workflows.md +51 -0
  268. package/docs/security-model.md +102 -39
  269. package/docs/troubleshooting.md +226 -93
  270. package/package.json +46 -15
  271. package/scripts/test-auto-screenshot.mjs +172 -0
  272. package/skills/doxloop-authoring/SKILL.md +242 -361
  273. package/skills/doxloop-authoring/references/existing-documentation.md +94 -0
  274. package/skills/doxloop-authoring/references/navigation-architecture.md +18 -7
  275. package/skills/doxloop-authoring/references/page-depth.md +169 -0
  276. package/skills/doxloop-authoring/references/project-format.md +106 -7
  277. package/skills/doxloop-authoring/references/quality.md +10 -0
  278. package/skills/doxloop-authoring/references/screenshot-manifest.md +113 -0
  279. package/skills/doxloop-authoring/references/screenshots.md +149 -235
  280. package/skills/doxloop-authoring/references/workflows.md +76 -0
  281. package/skills/doxloop-doxbrix/SKILL.md +38 -22
  282. package/skills/doxloop-doxbrix/references/api-endpoints.md +15 -14
  283. package/skills/doxloop-doxbrix/references/components.md +30 -3
  284. package/skills/doxloop-doxbrix/references/manifest.md +3 -2
  285. package/vendor/doxbrix-import/LICENSE +202 -0
  286. package/vendor/doxbrix-import/README.md +17 -0
  287. package/vendor/doxbrix-import/UPSTREAM.json +47 -0
  288. package/vendor/doxbrix-import/dist/docs/frontmatter.d.ts +13 -0
  289. package/vendor/doxbrix-import/dist/docs/frontmatter.js +83 -0
  290. package/vendor/doxbrix-import/dist/docs/import.d.ts +21 -0
  291. package/vendor/doxbrix-import/dist/docs/import.js +147 -0
  292. package/vendor/doxbrix-import/dist/docs/manifest.d.ts +163 -0
  293. package/vendor/doxbrix-import/dist/docs/manifest.js +64 -0
  294. package/vendor/doxbrix-import/dist/docs/project.d.ts +25 -0
  295. package/vendor/doxbrix-import/dist/docs/project.js +77 -0
  296. package/vendor/doxbrix-import/dist/docs/starter.d.ts +4 -0
  297. package/vendor/doxbrix-import/dist/docs/starter.js +11 -0
  298. package/vendor/doxbrix-import/dist/importer.d.ts +227 -0
  299. package/vendor/doxbrix-import/dist/importer.js +1567 -0
  300. package/vendor/doxbrix-import/dist/mintlify-openapi.d.ts +37 -0
  301. package/vendor/doxbrix-import/dist/mintlify-openapi.js +305 -0
  302. package/vendor/doxbrix-import/dist/safe-path.d.ts +9 -0
  303. package/vendor/doxbrix-import/dist/safe-path.js +47 -0
  304. package/dist/agents.d.ts.map +0 -1
  305. package/dist/agents.js.map +0 -1
  306. package/dist/args.d.ts.map +0 -1
  307. package/dist/args.js.map +0 -1
  308. package/dist/artifact-deploy.d.ts.map +0 -1
  309. package/dist/artifact-deploy.js.map +0 -1
  310. package/dist/auth.d.ts.map +0 -1
  311. package/dist/auth.js.map +0 -1
  312. package/dist/author.d.ts.map +0 -1
  313. package/dist/author.js.map +0 -1
  314. package/dist/capture.d.ts.map +0 -1
  315. package/dist/capture.js.map +0 -1
  316. package/dist/cli.d.ts.map +0 -1
  317. package/dist/cli.js.map +0 -1
  318. package/dist/deploy.d.ts.map +0 -1
  319. package/dist/deploy.js.map +0 -1
  320. package/dist/deployment-visibility.d.ts.map +0 -1
  321. package/dist/deployment-visibility.js.map +0 -1
  322. package/dist/doctor.d.ts.map +0 -1
  323. package/dist/doctor.js.map +0 -1
  324. package/dist/doxbrix-markdown.d.ts.map +0 -1
  325. package/dist/doxbrix-markdown.js.map +0 -1
  326. package/dist/errors.d.ts.map +0 -1
  327. package/dist/errors.js.map +0 -1
  328. package/dist/fs.d.ts.map +0 -1
  329. package/dist/fs.js.map +0 -1
  330. package/dist/generator-api.d.ts.map +0 -1
  331. package/dist/generator-api.js.map +0 -1
  332. package/dist/generator-manager.d.ts.map +0 -1
  333. package/dist/generator-manager.js.map +0 -1
  334. package/dist/generator-runtime.d.ts.map +0 -1
  335. package/dist/generator-runtime.js.map +0 -1
  336. package/dist/generators.d.ts.map +0 -1
  337. package/dist/generators.js.map +0 -1
  338. package/dist/interactive.d.ts.map +0 -1
  339. package/dist/interactive.js.map +0 -1
  340. package/dist/preview.d.ts.map +0 -1
  341. package/dist/preview.js.map +0 -1
  342. package/dist/progress.d.ts.map +0 -1
  343. package/dist/progress.js.map +0 -1
  344. package/dist/project.d.ts.map +0 -1
  345. package/dist/project.js.map +0 -1
  346. package/dist/prompts.d.ts.map +0 -1
  347. package/dist/prompts.js.map +0 -1
  348. package/dist/settings.d.ts.map +0 -1
  349. package/dist/settings.js.map +0 -1
  350. package/dist/sync.d.ts.map +0 -1
  351. package/dist/sync.js.map +0 -1
  352. package/dist/types.d.ts.map +0 -1
  353. package/dist/types.js.map +0 -1
  354. package/dist/validation.d.ts.map +0 -1
  355. package/dist/validation.js.map +0 -1
  356. package/dist/version.d.ts.map +0 -1
  357. package/dist/version.js.map +0 -1
@@ -0,0 +1,10 @@
1
+ /** Literal links in Markdown/MDX, HTML and reStructuredText. Never execute components. */
2
+ export declare function contentLinks(raw: string): string[];
3
+ /**
4
+ * A link target is a URL or a path. Text that only looks like `[x](y)`
5
+ * because it is a regular expression, a JSX expression, or a template —
6
+ * `[a-z]([a-z0-9-]{0,34})`, `{props.href}`, `${base}/x` — is not one, and
7
+ * reporting it as a broken link sent a real run's page to a fix session.
8
+ */
9
+ export declare function looksLikeLinkTarget(value: string): boolean;
10
+ //# sourceMappingURL=content-links.d.ts.map
@@ -0,0 +1,49 @@
1
+ /** Literal links in Markdown/MDX, HTML and reStructuredText. Never execute components. */
2
+ export function contentLinks(raw) {
3
+ const text = raw.replace(/```[^\n]*\n[\s\S]*?```|~~~[^\n]*\n[\s\S]*?~~~/g, '').replace(/<!--[\s\S]*?-->/g, '').replace(/<(?:script|style)\b[^>]*>[\s\S]*?<\/(?:script|style)>/gi, '');
4
+ // Inline code is literal text: `[a-z]([a-z0-9-]{0,34}[a-z0-9])` is a
5
+ // pattern, not a link. The reStructuredText forms below are written with
6
+ // backticks themselves, so they read the unmasked text.
7
+ const markdown = text.replace(/(`+)(?:(?!\1)[^\n])+?\1/g, '');
8
+ const links = new Set();
9
+ const markdownPatterns = [
10
+ /!?\[[^\]]*\]\(<?([^\s)>]+)>?(?:\s+["'][^"']*["'])?\)/g,
11
+ /^\s{0,3}\[[^\]]+\]:\s*<?([^\s>]+)>?/gm,
12
+ /\b(?:href|src)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>"'=]+))/gi,
13
+ /<(https?:\/\/[^>\s]+)>/gi,
14
+ ];
15
+ const restructuredPatterns = [
16
+ /`[^`<>]*<([^<>]+)>`_?_/g,
17
+ /^\s*\.\.\s+_[^:]+:\s+(\S+)/gm,
18
+ /^\s*\.\.\s+(?:image|figure)::\s+(\S+)/gm,
19
+ /:doc:`(?:[^`<>]*<)?([^`<>]+)>?`/g,
20
+ ];
21
+ const collect = (source, patterns) => {
22
+ for (const pattern of patterns)
23
+ for (const match of source.matchAll(pattern)) {
24
+ const value = (match[1] ?? match[2] ?? match[3])?.trim().replace(/&amp;/g, '&');
25
+ if (value && looksLikeLinkTarget(value))
26
+ links.add(value);
27
+ }
28
+ };
29
+ collect(markdown, markdownPatterns);
30
+ collect(text, restructuredPatterns);
31
+ return [...links];
32
+ }
33
+ /**
34
+ * A link target is a URL or a path. Text that only looks like `[x](y)`
35
+ * because it is a regular expression, a JSX expression, or a template —
36
+ * `[a-z]([a-z0-9-]{0,34})`, `{props.href}`, `${base}/x` — is not one, and
37
+ * reporting it as a broken link sent a real run's page to a fix session.
38
+ */
39
+ export function looksLikeLinkTarget(value) {
40
+ if (value.startsWith('{'))
41
+ return false;
42
+ if (/\s/.test(value))
43
+ return false;
44
+ // Brackets, braces, pipes, backslashes, carets and backticks never appear
45
+ // unescaped in a URL a writer means as a link; they are regex or template
46
+ // syntax.
47
+ return !/[[\]{}|\\^`]/.test(value);
48
+ }
49
+ //# sourceMappingURL=content-links.js.map
@@ -0,0 +1,4 @@
1
+ export type PublicContract = 'quality-report-v1' | 'evaluation-v1' | 'coverage-v1';
2
+ /** Validate output at its public boundary so an incompatible report is never persisted. */
3
+ export declare function assertPublicContract(contract: PublicContract, value: unknown): Promise<void>;
4
+ //# sourceMappingURL=contract-validation.d.ts.map
@@ -0,0 +1,25 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { Ajv2020 } from 'ajv/dist/2020.js';
4
+ import addFormatsModule from 'ajv-formats';
5
+ import { DoxloopError } from './errors.js';
6
+ const validators = new Map();
7
+ /** Validate output at its public boundary so an incompatible report is never persisted. */
8
+ export async function assertPublicContract(contract, value) {
9
+ let validate = validators.get(contract);
10
+ if (!validate) {
11
+ const path = fileURLToPath(new URL(`../contracts/${contract}.schema.json`, import.meta.url));
12
+ const schema = JSON.parse(await readFile(path, 'utf8'));
13
+ const ajv = new Ajv2020({ allErrors: true, strict: true });
14
+ const addFormats = addFormatsModule;
15
+ addFormats(ajv);
16
+ const compiled = ajv.compile(schema);
17
+ validators.set(contract, compiled);
18
+ validate = compiled;
19
+ }
20
+ if (validate(value))
21
+ return;
22
+ const detail = validate.errors?.map((error) => `${error.instancePath || '/'} ${error.message ?? 'is invalid'}`).join('; ') ?? 'unknown schema error';
23
+ throw new DoxloopError(`Doxloop refused to write an invalid ${contract} payload: ${detail}`);
24
+ }
25
+ //# sourceMappingURL=contract-validation.js.map
@@ -0,0 +1,8 @@
1
+ export type CoverageResolutionAction = 'link' | 'exclude' | 'needs-human' | 'remove-priority' | 'reset';
2
+ export declare function resolveCoverageItem(root: string, input: {
3
+ id: string;
4
+ action: CoverageResolutionAction;
5
+ page?: string;
6
+ reason?: string;
7
+ }): Promise<void>;
8
+ //# sourceMappingURL=coverage-actions.d.ts.map
@@ -0,0 +1,71 @@
1
+ import { withProjectLock } from './project-lock.js';
2
+ import { writeCoverageResolution } from './coverage-resolutions.js';
3
+ import { DoxloopError } from './errors.js';
4
+ import { readEvidenceMap, writeEvidenceMap } from './evidence.js';
5
+ import { loadProject, saveProjectSettings } from './project.js';
6
+ import { buildSourceIntelligence } from './source-intelligence.js';
7
+ export async function resolveCoverageItem(root, input) {
8
+ return withProjectLock(root, 'write', () => resolveCoverageItemLocked(root, input));
9
+ }
10
+ async function resolveCoverageItemLocked(root, input) {
11
+ const report = await buildSourceIntelligence(root);
12
+ const item = report.coverage.metrics.flatMap((metric) => metric.items).find((candidate) => candidate.id === input.id);
13
+ if (!item)
14
+ throw new DoxloopError('The requested coverage item no longer exists. Refresh coverage and try again.');
15
+ const reason = input.reason?.trim();
16
+ if (input.action === 'reset') {
17
+ await writeCoverageResolution(root, item.id);
18
+ return;
19
+ }
20
+ if (input.action === 'needs-human') {
21
+ await writeCoverageResolution(root, item.id, { disposition: 'needs-human', ...(reason ? { reason } : {}) });
22
+ return;
23
+ }
24
+ if (input.action === 'exclude') {
25
+ if (item.surface === 'verified-pages')
26
+ throw new DoxloopError('Page verification cannot be excluded. Reverify the page or decide later.');
27
+ if (item.surface === 'reader-journeys')
28
+ throw new DoxloopError('Remove a reader journey from priority outcomes instead of excluding it as a product surface.');
29
+ if (!reason)
30
+ throw new DoxloopError('Explain why this item is not part of the supported public surface.');
31
+ await writeCoverageResolution(root, item.id, { disposition: 'excluded', reason });
32
+ return;
33
+ }
34
+ if (input.action === 'remove-priority') {
35
+ if (item.surface !== 'reader-journeys')
36
+ throw new DoxloopError('Only reader journeys can be removed from priority outcomes.');
37
+ const project = await loadProject(root);
38
+ const priorityOutcomes = (project.documentation.priorityOutcomes ?? []).filter((outcome) => outcome !== item.label);
39
+ await saveProjectSettings(root, { documentation: { ...project.documentation, priorityOutcomes } });
40
+ await writeCoverageResolution(root, item.id);
41
+ return;
42
+ }
43
+ if (input.action === 'link') {
44
+ const page = input.page?.trim();
45
+ if (!page || !report.coverage.pages.includes(page))
46
+ throw new DoxloopError('Choose an existing evidence-mapped documentation page.');
47
+ if (item.surface === 'reader-journeys') {
48
+ await writeCoverageResolution(root, item.id, { disposition: 'documented', page, ...(reason ? { reason } : {}) });
49
+ return;
50
+ }
51
+ if (!item.source)
52
+ throw new DoxloopError('This coverage item cannot be linked to source evidence.');
53
+ const map = await readEvidenceMap(root);
54
+ if (!map?.pages[page])
55
+ throw new DoxloopError('The selected documentation page is not present in the evidence map.');
56
+ const evidence = map.pages[page];
57
+ const identifier = item.kind === 'export' && item.label.startsWith('Schema ')
58
+ ? `schema:${item.label.replace(/^Schema /, '')}`
59
+ : item.label;
60
+ const existing = evidence.sources.find((entry) => entry.source === item.source);
61
+ if (existing)
62
+ existing.operations = [...new Set([...(existing.operations ?? []), identifier])];
63
+ else
64
+ evidence.sources.push({ source: item.source, operations: [identifier] });
65
+ await writeEvidenceMap(root, map);
66
+ await writeCoverageResolution(root, item.id);
67
+ return;
68
+ }
69
+ throw new DoxloopError('Unsupported coverage resolution action.');
70
+ }
71
+ //# sourceMappingURL=coverage-actions.js.map
@@ -0,0 +1,16 @@
1
+ export type CoverageResolution = {
2
+ disposition: 'documented' | 'excluded' | 'needs-human';
3
+ page?: string;
4
+ reason?: string;
5
+ updatedAt: string;
6
+ };
7
+ export type CoverageResolutions = {
8
+ schemaVersion: 1;
9
+ items: Record<string, CoverageResolution>;
10
+ };
11
+ export declare function coverageSignalId(source: string, kind: string, path: string, label: string): string;
12
+ export declare function coveragePageId(page: string): string;
13
+ export declare function coverageJourneyId(outcome: string): string;
14
+ export declare function readCoverageResolutions(root: string): Promise<CoverageResolutions>;
15
+ export declare function writeCoverageResolution(root: string, id: string, resolution?: Omit<CoverageResolution, 'updatedAt'>): Promise<void>;
16
+ //# sourceMappingURL=coverage-resolutions.d.ts.map
@@ -0,0 +1,58 @@
1
+ import { withProjectLock } from './project-lock.js';
2
+ import { createHash } from 'node:crypto';
3
+ import { mkdir, rename, writeFile } from 'node:fs/promises';
4
+ import { dirname, join } from 'node:path';
5
+ import { DoxloopError } from './errors.js';
6
+ import { pathExists, readJson } from './fs.js';
7
+ const COVERAGE_RESOLUTIONS_FILE = join('.doxloop', 'coverage-resolutions.json');
8
+ export function coverageSignalId(source, kind, path, label) {
9
+ return `signal-${createHash('sha256').update(`${source}\0${kind}\0${path}\0${label}`).digest('hex').slice(0, 16)}`;
10
+ }
11
+ export function coveragePageId(page) { return `page-${createHash('sha256').update(page).digest('hex').slice(0, 16)}`; }
12
+ export function coverageJourneyId(outcome) {
13
+ return `journey-${createHash('sha256').update(normalize(outcome)).digest('hex').slice(0, 16)}`;
14
+ }
15
+ export async function readCoverageResolutions(root) {
16
+ const path = join(root, COVERAGE_RESOLUTIONS_FILE);
17
+ if (!(await pathExists(path)))
18
+ return { schemaVersion: 1, items: {} };
19
+ const raw = await readJson(path);
20
+ if (!isCoverageResolutions(raw))
21
+ throw new DoxloopError(`${COVERAGE_RESOLUTIONS_FILE} has an unsupported format.`);
22
+ return raw;
23
+ }
24
+ export async function writeCoverageResolution(root, id, resolution) {
25
+ return withProjectLock(root, 'write', () => writeCoverageResolutionLocked(root, id, resolution));
26
+ }
27
+ async function writeCoverageResolutionLocked(root, id, resolution) {
28
+ if (!/^(signal|journey|page)-[a-f0-9]{16}$/.test(id))
29
+ throw new DoxloopError('The requested coverage item is invalid.');
30
+ const current = await readCoverageResolutions(root);
31
+ const items = { ...current.items };
32
+ if (resolution)
33
+ items[id] = { ...resolution, updatedAt: new Date().toISOString() };
34
+ else
35
+ delete items[id];
36
+ const path = join(root, COVERAGE_RESOLUTIONS_FILE);
37
+ await mkdir(dirname(path), { recursive: true });
38
+ await writeFile(`${path}.tmp`, `${JSON.stringify({ schemaVersion: 1, items }, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
39
+ await rename(`${path}.tmp`, path);
40
+ }
41
+ function isCoverageResolutions(value) {
42
+ if (!value || typeof value !== 'object' || Array.isArray(value))
43
+ return false;
44
+ const candidate = value;
45
+ if (candidate.schemaVersion !== 1 || !candidate.items || typeof candidate.items !== 'object' || Array.isArray(candidate.items))
46
+ return false;
47
+ return Object.entries(candidate.items).every(([id, item]) => {
48
+ if (!/^(signal|journey|page)-[a-f0-9]{16}$/.test(id) || !item || typeof item !== 'object' || Array.isArray(item))
49
+ return false;
50
+ const resolution = item;
51
+ return ['documented', 'excluded', 'needs-human'].includes(String(resolution.disposition)) &&
52
+ (resolution.page === undefined || typeof resolution.page === 'string') &&
53
+ (resolution.reason === undefined || typeof resolution.reason === 'string') &&
54
+ typeof resolution.updatedAt === 'string';
55
+ });
56
+ }
57
+ function normalize(value) { return value.trim().toLowerCase(); }
58
+ //# sourceMappingURL=coverage-resolutions.js.map
package/dist/db.d.ts ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Local history storage.
3
+ *
4
+ * Doxloop ships without a native database dependency: history uses `node:sqlite`
5
+ * from the required Node.js 22.13+ runtime. `DOXLOOP_NO_HISTORY=1` remains an
6
+ * explicit privacy/diagnostic opt-out. Documentation stays in git; this database
7
+ * is a derived audit index that can be deleted and rebuilt at any time.
8
+ */
9
+ export declare const DATABASE_FILE: string;
10
+ /** The subset of `node:sqlite` this module relies on. */
11
+ export interface Statement {
12
+ run(...params: unknown[]): unknown;
13
+ get(...params: unknown[]): unknown;
14
+ all(...params: unknown[]): unknown[];
15
+ }
16
+ export interface Database {
17
+ exec(sql: string): void;
18
+ prepare(sql: string): Statement;
19
+ close(): void;
20
+ }
21
+ /** The schema version a freshly migrated database reports via `PRAGMA user_version`. */
22
+ export declare const SCHEMA_VERSION: number;
23
+ /**
24
+ * Open (and migrate) the history database for a project. Returns `undefined`
25
+ * when history is unavailable, which callers must treat as "skip recording".
26
+ */
27
+ export declare function openHistory(root: string): Promise<Database | undefined>;
28
+ /** Run a write against the history database, never failing the caller. */
29
+ export declare function withHistory<T>(root: string, action: (database: Database) => T): Promise<T | undefined>;
30
+ export declare function closeHistory(root?: string): void;
31
+ /** True when the runtime can store history at all. */
32
+ export declare function historyAvailable(): Promise<boolean>;
33
+ export declare function historyRuntimeStatus(version: string): {
34
+ available: boolean;
35
+ detail: string;
36
+ };
37
+ //# sourceMappingURL=db.d.ts.map
package/dist/db.js ADDED
@@ -0,0 +1,288 @@
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ /**
4
+ * Local history storage.
5
+ *
6
+ * Doxloop ships without a native database dependency: history uses `node:sqlite`
7
+ * from the required Node.js 22.13+ runtime. `DOXLOOP_NO_HISTORY=1` remains an
8
+ * explicit privacy/diagnostic opt-out. Documentation stays in git; this database
9
+ * is a derived audit index that can be deleted and rebuilt at any time.
10
+ */
11
+ export const DATABASE_FILE = join('.doxloop', 'doxloop.db');
12
+ const SCHEMA = [
13
+ // 1 — requests, the pages they touched, the page registry, deployments, baselines.
14
+ `
15
+ CREATE TABLE requests (
16
+ id TEXT PRIMARY KEY,
17
+ created_at TEXT NOT NULL,
18
+ finished_at TEXT,
19
+ duration_ms INTEGER,
20
+ kind TEXT NOT NULL,
21
+ trigger TEXT NOT NULL,
22
+ request_text TEXT,
23
+ agent TEXT,
24
+ model TEXT,
25
+ reasoning_effort TEXT,
26
+ status TEXT NOT NULL,
27
+ pages_changed INTEGER NOT NULL DEFAULT 0,
28
+ lines_added INTEGER NOT NULL DEFAULT 0,
29
+ lines_removed INTEGER NOT NULL DEFAULT 0,
30
+ validation_pages INTEGER,
31
+ validation_errors INTEGER,
32
+ validation_warnings INTEGER,
33
+ source_summary TEXT,
34
+ stale_pages_count INTEGER NOT NULL DEFAULT 0,
35
+ error_message TEXT,
36
+ run_dir TEXT
37
+ );
38
+ CREATE INDEX requests_created_at ON requests (created_at DESC);
39
+ CREATE INDEX requests_status ON requests (status);
40
+
41
+ CREATE TABLE request_pages (
42
+ request_id TEXT NOT NULL REFERENCES requests (id) ON DELETE CASCADE,
43
+ path TEXT NOT NULL,
44
+ title TEXT,
45
+ change_kind TEXT NOT NULL,
46
+ category TEXT NOT NULL,
47
+ decision TEXT NOT NULL DEFAULT 'pending',
48
+ decided_at TEXT,
49
+ lines_added INTEGER NOT NULL DEFAULT 0,
50
+ lines_removed INTEGER NOT NULL DEFAULT 0,
51
+ PRIMARY KEY (request_id, path)
52
+ );
53
+ CREATE INDEX request_pages_path ON request_pages (path, request_id);
54
+
55
+ CREATE TABLE pages (
56
+ path TEXT PRIMARY KEY,
57
+ title TEXT,
58
+ created_at TEXT NOT NULL,
59
+ updated_at TEXT NOT NULL,
60
+ last_request_id TEXT,
61
+ content_hash TEXT,
62
+ change_count INTEGER NOT NULL DEFAULT 0,
63
+ evidence_confidence TEXT,
64
+ status TEXT NOT NULL DEFAULT 'active'
65
+ );
66
+
67
+ CREATE TABLE deployments (
68
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
69
+ started_at TEXT NOT NULL,
70
+ finished_at TEXT,
71
+ duration_ms INTEGER,
72
+ target TEXT NOT NULL,
73
+ name TEXT,
74
+ slug TEXT,
75
+ visibility TEXT,
76
+ url TEXT,
77
+ status TEXT NOT NULL,
78
+ pages_count INTEGER,
79
+ media_count INTEGER,
80
+ bytes INTEGER,
81
+ pages_created INTEGER,
82
+ pages_updated INTEGER,
83
+ pages_deleted INTEGER,
84
+ git_commit TEXT,
85
+ error_message TEXT
86
+ );
87
+ CREATE INDEX deployments_started_at ON deployments (started_at DESC);
88
+
89
+ CREATE TABLE source_syncs (
90
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
91
+ source_name TEXT NOT NULL,
92
+ -- SQLite treats NULLs as distinct in a UNIQUE constraint, so a source with
93
+ -- no fingerprint would append a duplicate row on every run. Empty strings
94
+ -- keep "already recorded" comparable.
95
+ commit_hash TEXT NOT NULL DEFAULT '',
96
+ fingerprint TEXT NOT NULL DEFAULT '',
97
+ recorded_at TEXT NOT NULL,
98
+ request_id TEXT,
99
+ UNIQUE (source_name, commit_hash, fingerprint)
100
+ );
101
+ CREATE INDEX source_syncs_name ON source_syncs (source_name, recorded_at DESC);
102
+
103
+ CREATE TABLE meta (
104
+ key TEXT PRIMARY KEY,
105
+ value TEXT NOT NULL
106
+ );
107
+ `,
108
+ // 2 — agent token usage per request. Nullable: rows from before this version
109
+ // and agents that report no usage leave them empty.
110
+ `
111
+ ALTER TABLE requests ADD COLUMN input_tokens INTEGER;
112
+ ALTER TABLE requests ADD COLUMN output_tokens INTEGER;
113
+ ALTER TABLE requests ADD COLUMN cache_read_tokens INTEGER;
114
+ ALTER TABLE requests ADD COLUMN cache_creation_tokens INTEGER;
115
+ ALTER TABLE requests ADD COLUMN cost_usd REAL;
116
+ ALTER TABLE requests ADD COLUMN agent_turns INTEGER;
117
+ ALTER TABLE requests ADD COLUMN agent_sessions INTEGER;
118
+ ALTER TABLE requests ADD COLUMN max_context_tokens INTEGER;
119
+ `,
120
+ ];
121
+ /** The schema version a freshly migrated database reports via `PRAGMA user_version`. */
122
+ export const SCHEMA_VERSION = SCHEMA.length;
123
+ let sqlite;
124
+ const connections = new Map();
125
+ /**
126
+ * Node prints an experimental warning the first time `node:sqlite` loads. The
127
+ * filter is narrow so every other warning still reaches the user, and it stays
128
+ * installed because `process.emitWarning` defers to the next tick.
129
+ */
130
+ function silenceSqliteWarning() {
131
+ const emit = process.emit.bind(process);
132
+ const filtered = (name, ...rest) => {
133
+ const warning = rest[0];
134
+ if (name === 'warning' &&
135
+ warning instanceof Error &&
136
+ warning.name === 'ExperimentalWarning' &&
137
+ warning.message.includes('SQLite')) {
138
+ return false;
139
+ }
140
+ return emit(name, ...rest);
141
+ };
142
+ process.emit = filtered;
143
+ }
144
+ async function loadSqlite() {
145
+ if (sqlite !== undefined)
146
+ return sqlite;
147
+ try {
148
+ silenceSqliteWarning();
149
+ sqlite = (await import('node:sqlite'));
150
+ }
151
+ catch {
152
+ // Node 20 and early Node 22 have no built-in SQLite. History is optional.
153
+ sqlite = null;
154
+ }
155
+ return sqlite;
156
+ }
157
+ /**
158
+ * Open (and migrate) the history database for a project. Returns `undefined`
159
+ * when history is unavailable, which callers must treat as "skip recording".
160
+ */
161
+ export async function openHistory(root) {
162
+ if (process.env.DOXLOOP_NO_HISTORY === '1')
163
+ return undefined;
164
+ const cached = connections.get(root);
165
+ if (cached !== undefined)
166
+ return cached ?? undefined;
167
+ const loaded = await loadSqlite();
168
+ if (!loaded) {
169
+ connections.set(root, null);
170
+ return undefined;
171
+ }
172
+ try {
173
+ const path = join(root, DATABASE_FILE);
174
+ mkdirSync(join(root, '.doxloop'), { recursive: true });
175
+ ensureIgnored(root);
176
+ const database = new loaded.DatabaseSync(path);
177
+ configure(database);
178
+ migrate(database);
179
+ try {
180
+ // History can contain source paths and request text. Keep it owner-only.
181
+ chmodSync(path, 0o600);
182
+ }
183
+ catch {
184
+ // Windows and some network filesystems do not support POSIX modes.
185
+ }
186
+ connections.set(root, database);
187
+ return database;
188
+ }
189
+ catch (error) {
190
+ debug('open', error);
191
+ connections.set(root, null);
192
+ return undefined;
193
+ }
194
+ }
195
+ /**
196
+ * Projects created before history existed have no ignore rule for it. The
197
+ * database is machine-local and must never reach a commit.
198
+ */
199
+ function ensureIgnored(root) {
200
+ const entries = [
201
+ '.doxloop/doxloop.db',
202
+ '.doxloop/doxloop.db-wal',
203
+ '.doxloop/doxloop.db-shm',
204
+ ];
205
+ try {
206
+ const path = join(root, '.gitignore');
207
+ const existing = existsSync(path) ? readFileSync(path, 'utf8') : '';
208
+ const lines = existing.split(/\r?\n/);
209
+ const missing = entries.filter((entry) => !lines.includes(entry));
210
+ if (missing.length === 0)
211
+ return;
212
+ const prefix = existing && !existing.endsWith('\n') ? '\n' : '';
213
+ writeFileSync(path, `${existing}${prefix}${missing.join('\n')}\n`, 'utf8');
214
+ }
215
+ catch {
216
+ // A read-only checkout still gets history; it just cannot self-ignore.
217
+ }
218
+ }
219
+ function configure(database) {
220
+ // WAL lets the UI server read while a CLI job writes; the timeout absorbs the
221
+ // brief lock contention that remains.
222
+ database.exec('PRAGMA journal_mode = WAL');
223
+ database.exec('PRAGMA busy_timeout = 5000');
224
+ database.exec('PRAGMA foreign_keys = ON');
225
+ database.exec('PRAGMA synchronous = NORMAL');
226
+ }
227
+ function migrate(database) {
228
+ const row = database.prepare('PRAGMA user_version').get();
229
+ const current = Number(row?.user_version ?? 0);
230
+ if (current >= SCHEMA.length)
231
+ return;
232
+ for (let version = current; version < SCHEMA.length; version += 1) {
233
+ database.exec('BEGIN');
234
+ try {
235
+ database.exec(SCHEMA[version]);
236
+ database.exec(`PRAGMA user_version = ${version + 1}`);
237
+ database.exec('COMMIT');
238
+ }
239
+ catch (error) {
240
+ database.exec('ROLLBACK');
241
+ throw error;
242
+ }
243
+ }
244
+ }
245
+ /** Run a write against the history database, never failing the caller. */
246
+ export async function withHistory(root, action) {
247
+ const database = await openHistory(root);
248
+ if (!database)
249
+ return undefined;
250
+ try {
251
+ return action(database);
252
+ }
253
+ catch (error) {
254
+ debug('write', error);
255
+ return undefined;
256
+ }
257
+ }
258
+ export function closeHistory(root) {
259
+ for (const [key, database] of connections) {
260
+ if (root !== undefined && key !== root)
261
+ continue;
262
+ try {
263
+ database?.close();
264
+ }
265
+ catch {
266
+ // A database closed twice is not worth reporting.
267
+ }
268
+ connections.delete(key);
269
+ }
270
+ }
271
+ /** True when the runtime can store history at all. */
272
+ export async function historyAvailable() {
273
+ return process.env.DOXLOOP_NO_HISTORY !== '1' && (await loadSqlite()) !== null;
274
+ }
275
+ export function historyRuntimeStatus(version) {
276
+ const match = /^(\d+)\.(\d+)\.(\d+)/.exec(version);
277
+ const supported = Boolean(match && (Number(match[1]) > 22 || (Number(match[1]) === 22 && (Number(match[2]) > 13 || (Number(match[2]) === 13 && Number(match[3]) >= 0)))));
278
+ return supported
279
+ ? { available: true, detail: `Node.js ${version} includes the SQLite history runtime required by Doxloop.` }
280
+ : { available: false, detail: `Node.js ${version} is too old for request history. Upgrade to Node.js 22.13 or newer before the first documentation run.` };
281
+ }
282
+ function debug(stage, error) {
283
+ if (process.env.DOXLOOP_DEBUG !== '1')
284
+ return;
285
+ const message = error instanceof Error ? error.message : String(error);
286
+ process.stderr.write(`doxloop: history ${stage} failed: ${message}\n`);
287
+ }
288
+ //# sourceMappingURL=db.js.map
package/dist/demo.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { DocumentationPlan, DocumentationReviewReport, ValidationResult } from './types.js';
2
+ export interface DemoWorkspace {
3
+ parent: string;
4
+ root: string;
5
+ plan: DocumentationPlan;
6
+ review: DocumentationReviewReport;
7
+ validation: ValidationResult;
8
+ cleanup(): Promise<void>;
9
+ }
10
+ /** Build a deterministic showcase in an isolated temporary directory. */
11
+ export declare function createDemoWorkspace(): Promise<DemoWorkspace>;
12
+ //# sourceMappingURL=demo.d.ts.map