@doxbrix/doxloop 0.1.5 → 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 +1145 -0
  2. package/README.md +422 -227
  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 +24 -5
  22. package/dist/agents.js +60 -9
  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 +3 -0
  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 +25 -0
  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 +49 -32
  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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doxbrix/doxloop",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "description": "A local-first documentation agent CLI for Codex, Claude Code, and Gemini.",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -18,13 +18,22 @@
18
18
  "files": [
19
19
  "dist",
20
20
  "assets",
21
+ "contracts",
21
22
  "docs",
23
+ "scripts/test-auto-screenshot.mjs",
22
24
  "skills/doxloop-authoring",
23
25
  "skills/doxloop-doxbrix",
24
26
  "README.md",
25
27
  "CHANGELOG.md",
26
28
  "SECURITY.md",
27
- "LICENSE"
29
+ "LICENSE",
30
+ "!dist/**/*.map",
31
+ "!assets/marketing/**",
32
+ "!assets/social/**",
33
+ "vendor/doxbrix-import/dist",
34
+ "vendor/doxbrix-import/LICENSE",
35
+ "vendor/doxbrix-import/UPSTREAM.json",
36
+ "vendor/doxbrix-import/README.md"
28
37
  ],
29
38
  "exports": {
30
39
  "./generator-api": {
@@ -42,25 +51,39 @@
42
51
  },
43
52
  "scripts": {
44
53
  "build": "pnpm run build:core && pnpm run build:generators",
45
- "build:core": "rm -rf dist && tsc -p tsconfig.json && node scripts/prepare-dist.mjs",
54
+ "build:core": "rm -rf dist && pnpm run build:importer && tsc -p tsconfig.json && vite build --config vite.ui.config.ts && node scripts/prepare-dist.mjs",
46
55
  "build:generators": "pnpm --filter './packages/*' run build",
47
- "dev": "tsx src/cli.ts",
48
- "typecheck": "tsc --noEmit && pnpm --filter './packages/*' run typecheck",
49
- "pretest": "pnpm run build",
56
+ "dev": "pnpm run build:importer && tsx src/cli.ts",
57
+ "typecheck": "pnpm run build:importer && tsc --noEmit && tsc --noEmit -p tsconfig.ui.json && pnpm --filter './packages/*' run typecheck",
58
+ "build:test": "pnpm run build:importer && tsc -p tsconfig.json && pnpm run build:generators",
59
+ "pretest": "pnpm run build:test",
50
60
  "test": "vitest run",
61
+ "test:generator": "node scripts/ci-generator-smoke.mjs",
62
+ "test:screenshot": "node scripts/test-auto-screenshot.mjs",
63
+ "test:e2e": "playwright test",
51
64
  "eval:agents": "pnpm run build && node scripts/run-authoring-evals.mjs",
52
65
  "check": "pnpm run typecheck && pnpm run test && pnpm run validate:skill && pnpm run check:boundary",
53
66
  "release:local": "node scripts/release-local.mjs",
54
67
  "validate:skill": "node scripts/validate-skills.mjs",
55
68
  "check:boundary": "node scripts/check-boundary.mjs",
56
- "prepack": "pnpm run check && pnpm run build && pnpm run check:boundary"
69
+ "prepack": "pnpm run check && pnpm run build && pnpm run check:boundary",
70
+ "test:existing-sites": "node scripts/ci-existing-sites.mjs",
71
+ "test:python-boundary": "node scripts/ci-python-sandbox.mjs",
72
+ "build:importer": "tsc -p vendor/doxbrix-import/tsconfig.json"
57
73
  },
58
74
  "dependencies": {
75
+ "@playwright/mcp": "0.0.79",
76
+ "ajv": "^8.17.1",
77
+ "ajv-formats": "^3.0.1",
78
+ "axe-core": "^4.13.0",
59
79
  "chokidar": "^4.0.3",
60
80
  "cross-spawn": "^7.0.6",
61
81
  "fflate": "^0.8.2",
62
82
  "gray-matter": "^4.0.3",
63
- "highlight.js": "^11.11.1"
83
+ "highlight.js": "^11.11.1",
84
+ "pixelmatch": "^7.1.0",
85
+ "pngjs": "^7.0.0",
86
+ "yaml": "^2.8.1"
64
87
  },
65
88
  "devDependencies": {
66
89
  "@doxbrix/doxloop-generator-docusaurus": "workspace:*",
@@ -73,20 +96,28 @@
73
96
  "@doxbrix/doxloop-generator-starlight": "workspace:*",
74
97
  "@doxbrix/doxloop-generator-static": "workspace:*",
75
98
  "@doxbrix/doxloop-generator-vitepress": "workspace:*",
99
+ "@playwright/test": "^1.62.1",
100
+ "@preact/preset-vite": "^2.10.2",
76
101
  "@types/cross-spawn": "^6.0.6",
77
102
  "@types/node": "^22.15.3",
103
+ "@types/pngjs": "^6.0.5",
104
+ "preact": "^10.27.2",
78
105
  "tsx": "^4.19.4",
79
106
  "typescript": "^5.8.3",
107
+ "vite": "^7.3.1",
80
108
  "vitest": "^3.1.2"
81
109
  },
82
110
  "engines": {
83
- "node": ">=20.12.0"
111
+ "node": ">=22.13.0"
84
112
  },
85
113
  "packageManager": "pnpm@10.33.0",
86
- "main": "index.js",
87
- "directories": {
88
- "doc": "docs"
89
- },
90
- "keywords": [],
91
- "author": ""
114
+ "keywords": [
115
+ "documentation",
116
+ "documentation-maintenance",
117
+ "cli",
118
+ "markdown",
119
+ "docusaurus",
120
+ "mkdocs"
121
+ ],
122
+ "author": "Doxbrix"
92
123
  }
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawn } from 'node:child_process'
4
+ import { mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises'
5
+ import { isAbsolute, join, resolve } from 'node:path'
6
+ import process from 'node:process'
7
+ import { agentArguments } from '../dist/author.js'
8
+ import {
9
+ checkScreenCaptureBrowser,
10
+ screenCaptureProvider,
11
+ } from '../dist/screen-capture-provider.js'
12
+
13
+ const options = parseArguments(process.argv.slice(2))
14
+ const workspace = resolve(options.output)
15
+ const captureDirectory = join(workspace, '.doxloop', 'capture-output')
16
+ const screenshot = join(workspace, 'standalone-capture.png')
17
+ const logFile = join(workspace, 'agent.log')
18
+ const resultFile = join(workspace, 'result.json')
19
+ const target = new URL(options.route, options.url).href
20
+
21
+ await mkdir(captureDirectory, { recursive: true })
22
+ await rm(screenshot, { force: true })
23
+ await rm(resultFile, { force: true })
24
+
25
+ const readiness = await checkScreenCaptureBrowser()
26
+ if (!readiness.available) fail(readiness.message)
27
+
28
+ let response
29
+ try {
30
+ response = await fetch(target, { signal: AbortSignal.timeout(10_000) })
31
+ } catch (error) {
32
+ fail(`Application is not reachable at ${target}: ${error instanceof Error ? error.message : String(error)}`)
33
+ }
34
+ if (!response.ok) fail(`Application returned HTTP ${response.status} at ${target}.`)
35
+
36
+ const provider = screenCaptureProvider(workspace, {
37
+ baseUrl: options.url,
38
+ screenshots: {
39
+ policy: 'required',
40
+ viewport: { width: options.width, height: options.height },
41
+ },
42
+ })
43
+ const prompt = `This is a standalone Doxloop screenshot smoke test.
44
+
45
+ Use only the doxloop_capture browser tools for browser work.
46
+ 1. Navigate to ${target}.
47
+ 2. Wait until the page is stable.
48
+ 3. Inspect the browser snapshot and identify the visible page heading or primary landmark.
49
+ 4. Save one PNG screenshot with browser_take_screenshot using exactly this filename: standalone-capture.png
50
+ 5. Do not modify the application and do not create any other files.
51
+ 6. In your final response, report the visible heading and confirm the screenshot filename.
52
+
53
+ The test fails unless browser_take_screenshot is called and the PNG exists.`
54
+ const args = agentArguments(options.agent, prompt, {
55
+ mode: 'create',
56
+ nonInteractive: true,
57
+ captureProvider: provider,
58
+ captureRequired: true,
59
+ })
60
+
61
+ process.stdout.write(`Testing ${options.agent} screenshot capture at ${target}\n`)
62
+ process.stdout.write(`Output: ${workspace}\n`)
63
+
64
+ const execution = await run(options.agent, args, workspace, options.timeoutMinutes)
65
+ await writeFile(logFile, execution.output, 'utf8')
66
+
67
+ if (execution.exitCode !== 0) {
68
+ await writeResult(false, `Agent exited with status ${execution.exitCode}.`)
69
+ fail(`Agent exited with status ${execution.exitCode}. See ${logFile}`)
70
+ }
71
+
72
+ let bytes
73
+ try {
74
+ bytes = await readFile(screenshot)
75
+ } catch {
76
+ await writeResult(false, 'The agent completed without producing the PNG.')
77
+ fail(`The agent completed, but no screenshot was created at ${screenshot}. See ${logFile}`)
78
+ }
79
+ const pngSignature = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])
80
+ if (bytes.length < 1_024 || !bytes.subarray(0, 8).equals(pngSignature)) {
81
+ await writeResult(false, `The output is not a valid non-empty PNG (${bytes.length} bytes).`)
82
+ fail(`Invalid screenshot output at ${screenshot}.`)
83
+ }
84
+
85
+ const details = await stat(screenshot)
86
+ await writeResult(true, `Captured a valid ${details.size}-byte PNG.`)
87
+ process.stdout.write(`PASS: captured ${details.size} bytes at ${screenshot}\n`)
88
+
89
+ async function writeResult(passed, message) {
90
+ await writeFile(resultFile, `${JSON.stringify({
91
+ passed,
92
+ agent: options.agent,
93
+ target,
94
+ screenshot: 'standalone-capture.png',
95
+ message,
96
+ }, null, 2)}\n`, 'utf8')
97
+ }
98
+
99
+ function run(command, args, cwd, timeoutMinutes) {
100
+ return new Promise((resolveRun, rejectRun) => {
101
+ const child = spawn(command, args, { cwd, env: process.env, stdio: ['ignore', 'pipe', 'pipe'] })
102
+ let output = ''
103
+ const append = (chunk, destination) => {
104
+ const text = chunk.toString()
105
+ output += text
106
+ destination.write(text)
107
+ }
108
+ child.stdout.on('data', (chunk) => append(chunk, process.stdout))
109
+ child.stderr.on('data', (chunk) => append(chunk, process.stderr))
110
+ child.once('error', rejectRun)
111
+ child.once('exit', (code, signal) => {
112
+ clearTimeout(timer)
113
+ resolveRun({ exitCode: signal ? 1 : code ?? 1, output })
114
+ })
115
+ const timer = setTimeout(() => {
116
+ child.kill('SIGTERM')
117
+ }, timeoutMinutes * 60_000)
118
+ })
119
+ }
120
+
121
+ function parseArguments(args) {
122
+ const parsed = {
123
+ agent: 'codex',
124
+ url: 'http://127.0.0.1:4317',
125
+ route: '/',
126
+ output: join('.doxloop', 'screenshot-smoke'),
127
+ width: 1440,
128
+ height: 900,
129
+ timeoutMinutes: 5,
130
+ }
131
+ for (let index = 0; index < args.length; index += 1) {
132
+ const key = args[index]
133
+ if (key === '--') continue
134
+ if (key === '--help') usage(0)
135
+ const value = args[index + 1]
136
+ if (!value || value.startsWith('--')) usage(1, `Missing value for ${key}.`)
137
+ if (key === '--agent' && (value === 'codex' || value === 'claude')) parsed.agent = value
138
+ else if (key === '--url') parsed.url = new URL(value).href
139
+ else if (key === '--route') parsed.route = value
140
+ else if (key === '--output') parsed.output = isAbsolute(value) ? value : resolve(value)
141
+ else if (key === '--width') parsed.width = positiveInteger(value, key)
142
+ else if (key === '--height') parsed.height = positiveInteger(value, key)
143
+ else if (key === '--timeout-minutes') parsed.timeoutMinutes = positiveInteger(value, key)
144
+ else usage(1, `Unknown or invalid option: ${key} ${value}`)
145
+ index += 1
146
+ }
147
+ return parsed
148
+ }
149
+
150
+ function positiveInteger(value, option) {
151
+ const number = Number(value)
152
+ if (!Number.isInteger(number) || number <= 0) usage(1, `${option} must be a positive integer.`)
153
+ return number
154
+ }
155
+
156
+ function usage(code, message) {
157
+ if (message) process.stderr.write(`${message}\n\n`)
158
+ process.stderr.write(`Usage: pnpm test:screenshot -- [options]\n\n`)
159
+ process.stderr.write(` --agent codex|claude Agent to test (default: codex)\n`)
160
+ process.stderr.write(` --url URL Application base URL\n`)
161
+ process.stderr.write(` --route PATH Route to capture (default: /)\n`)
162
+ process.stderr.write(` --output DIRECTORY Isolated test output directory\n`)
163
+ process.stderr.write(` --width PIXELS Viewport width (default: 1440)\n`)
164
+ process.stderr.write(` --height PIXELS Viewport height (default: 900)\n`)
165
+ process.stderr.write(` --timeout-minutes MINUTES Agent timeout (default: 5)\n`)
166
+ process.exit(code)
167
+ }
168
+
169
+ function fail(message) {
170
+ process.stderr.write(`FAIL: ${message}\n`)
171
+ process.exit(1)
172
+ }