explorbot 0.2.2 → 0.2.4

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 (214) hide show
  1. package/README.md +1 -1
  2. package/bin/explorbot-cli.ts +59 -38
  3. package/boat/api-tester/src/apibot.ts +4 -2
  4. package/boat/api-tester/src/cli.ts +2 -2
  5. package/boat/api-tester/src/config.ts +43 -10
  6. package/boat/doc-collector/bin/doc-collector-cli.ts +2 -0
  7. package/boat/doc-collector/src/ai/documentarian.ts +61 -31
  8. package/boat/doc-collector/src/cli.ts +1 -0
  9. package/boat/doc-collector/src/config.ts +4 -2
  10. package/boat/doc-collector/src/docs-renderer.ts +18 -4
  11. package/boat/doc-collector/src/state-diagram.ts +61 -14
  12. package/boat/prima/bin/prima-cli.ts +5 -0
  13. package/boat/prima/package.json +16 -0
  14. package/boat/prima/src/activity-line.ts +33 -0
  15. package/boat/prima/src/cli.ts +251 -0
  16. package/boat/prima/src/envelope.ts +169 -0
  17. package/boat/prima/src/prima.ts +1124 -0
  18. package/boat/prima/src/pw-parser.ts +27 -0
  19. package/boat/prima/src/pw-registry.ts +74 -0
  20. package/boat/prima/src/session-log.ts +126 -0
  21. package/dist/bin/explorbot-cli.js +51 -32
  22. package/dist/boat/api-tester/bin/apibot-cli.js +2 -0
  23. package/dist/boat/api-tester/src/apibot.js +3 -2
  24. package/dist/boat/api-tester/src/cli.js +2 -2
  25. package/dist/boat/api-tester/src/config.js +40 -10
  26. package/dist/boat/doc-collector/bin/doc-collector-cli.js +2 -0
  27. package/dist/boat/doc-collector/src/ai/documentarian.js +44 -19
  28. package/dist/boat/doc-collector/src/cli.js +1 -0
  29. package/dist/boat/doc-collector/src/config.js +4 -2
  30. package/dist/boat/doc-collector/src/docs-renderer.js +17 -3
  31. package/dist/boat/doc-collector/src/state-diagram.js +57 -13
  32. package/dist/boat/prima/bin/prima-cli.js +4 -0
  33. package/dist/boat/prima/src/activity-line.js +30 -0
  34. package/dist/boat/prima/src/cli.js +220 -0
  35. package/dist/boat/prima/src/envelope.js +142 -0
  36. package/dist/boat/prima/src/prima.js +1031 -0
  37. package/dist/boat/prima/src/pw-parser.js +30 -0
  38. package/dist/boat/prima/src/pw-registry.js +65 -0
  39. package/dist/boat/prima/src/session-log.js +108 -0
  40. package/dist/models.json +3 -0
  41. package/dist/package.json +8 -3
  42. package/dist/rules/navigator/verification-actions.md +20 -0
  43. package/dist/src/action-result.d.ts +7 -0
  44. package/dist/src/action-result.js +4 -0
  45. package/dist/src/action.d.ts +7 -2
  46. package/dist/src/action.js +41 -6
  47. package/dist/src/ai/captain/mixin.js +3 -4
  48. package/dist/src/ai/captain/web-mode.js +7 -4
  49. package/dist/src/ai/captain.js +2 -0
  50. package/dist/src/ai/navigator.d.ts +11 -0
  51. package/dist/src/ai/navigator.js +21 -12
  52. package/dist/src/ai/pilot.d.ts +4 -0
  53. package/dist/src/ai/pilot.js +48 -2
  54. package/dist/src/ai/planner.d.ts +1 -0
  55. package/dist/src/ai/planner.js +6 -0
  56. package/dist/src/ai/provider.js +2 -2
  57. package/dist/src/ai/rerunner.js +2 -1
  58. package/dist/src/ai/researcher.js +2 -2
  59. package/dist/src/ai/rules.js +17 -10
  60. package/dist/src/ai/task-agent.js +5 -2
  61. package/dist/src/ai/tester.d.ts +1 -0
  62. package/dist/src/ai/tester.js +33 -20
  63. package/dist/src/ai/tools.d.ts +14 -0
  64. package/dist/src/ai/tools.js +113 -36
  65. package/dist/src/application-spec-contract.d.ts +8 -0
  66. package/dist/src/application-spec-contract.js +8 -0
  67. package/dist/src/application-spec.d.ts +15 -0
  68. package/dist/src/application-spec.js +71 -0
  69. package/dist/src/browser-server.d.ts +12 -6
  70. package/dist/src/browser-server.js +74 -19
  71. package/dist/src/commands/clean-command.js +2 -7
  72. package/dist/src/commands/init-command.d.ts +5 -0
  73. package/dist/src/commands/init-command.js +119 -1
  74. package/dist/src/commands/navigate-command.js +1 -1
  75. package/dist/src/commands/research-command.js +1 -1
  76. package/dist/src/commands/sites-command.d.ts +6 -0
  77. package/dist/src/commands/sites-command.js +23 -0
  78. package/dist/src/components/InitWizard.d.ts +10 -0
  79. package/dist/src/components/InitWizard.js +133 -0
  80. package/dist/src/components/InputReadline.d.ts +1 -0
  81. package/dist/src/components/InputReadline.js +7 -4
  82. package/dist/src/config.d.ts +25 -5
  83. package/dist/src/config.js +158 -40
  84. package/dist/src/execution-controller.d.ts +2 -0
  85. package/dist/src/execution-controller.js +6 -0
  86. package/dist/src/explorbot.d.ts +11 -1
  87. package/dist/src/explorbot.js +27 -6
  88. package/dist/src/explorer.d.ts +4 -1
  89. package/dist/src/explorer.js +42 -9
  90. package/dist/src/global-config.d.ts +22 -0
  91. package/dist/src/global-config.js +117 -0
  92. package/dist/src/knowledge-tracker.d.ts +5 -1
  93. package/dist/src/knowledge-tracker.js +14 -1
  94. package/dist/src/playwright-recorder.js +30 -0
  95. package/dist/src/remote.d.ts +54 -0
  96. package/dist/src/remote.js +229 -0
  97. package/dist/src/reporter.d.ts +1 -0
  98. package/dist/src/reporter.js +7 -1
  99. package/dist/src/state-manager.d.ts +2 -1
  100. package/dist/src/stats.d.ts +1 -0
  101. package/dist/src/stats.js +1 -0
  102. package/dist/src/test-plan.d.ts +2 -0
  103. package/dist/src/test-plan.js +7 -0
  104. package/dist/src/utils/aria.d.ts +2 -8
  105. package/dist/src/utils/aria.js +69 -40
  106. package/dist/src/utils/cli-name.js +6 -2
  107. package/dist/src/utils/html.js +1 -0
  108. package/dist/src/utils/logger.d.ts +6 -0
  109. package/dist/src/utils/logger.js +24 -0
  110. package/dist/src/utils/page-readiness.js +18 -1
  111. package/dist/src/utils/test-files.js +1 -2
  112. package/dist/src/utils/url-matcher.d.ts +1 -0
  113. package/dist/src/utils/url-matcher.js +12 -0
  114. package/dist/src/utils/web-element.d.ts +2 -0
  115. package/dist/src/utils/web-element.js +8 -0
  116. package/dist/src/utils/web-sandbox.d.ts +1 -1
  117. package/dist/src/utils/web-sandbox.js +2 -3
  118. package/docs/api-testing/basics.md +90 -0
  119. package/docs/api-testing/planning.md +57 -0
  120. package/docs/api-testing/running-tests.md +55 -0
  121. package/docs/assets/cloud-report.png +0 -0
  122. package/docs/assets/html-report.png +0 -0
  123. package/docs/assets/langfuse-trace.png +0 -0
  124. package/docs/assets/successful-explore-run.png +0 -0
  125. package/docs/basics/getting-started.md +140 -0
  126. package/docs/basics/prerequisites.md +63 -0
  127. package/docs/basics/providers.md +362 -0
  128. package/docs/basics/running.md +78 -0
  129. package/docs/contributing/ai-integration-tests.md +57 -0
  130. package/docs/contributing/contributing.md +90 -0
  131. package/docs/contributing/demo-videos.md +36 -0
  132. package/docs/contributing/npm-package.md +138 -0
  133. package/docs/contributing/observability.md +227 -0
  134. package/docs/contributing/regression-tests.md +103 -0
  135. package/docs/contributing/testing.md +95 -0
  136. package/docs/doc-collection/basics.md +128 -0
  137. package/docs/doc-collection/crawling.md +67 -0
  138. package/docs/doc-collection/interactive-mode.md +99 -0
  139. package/docs/index.json +86 -0
  140. package/docs/reference/commands.md +994 -0
  141. package/docs/reference/configuration.md +569 -0
  142. package/docs/reference/scripting.md +303 -0
  143. package/docs/superpowers/plans/2026-08-01-actor-boat.md +925 -0
  144. package/docs/superpowers/plans/2026-08-01-prima-boat.md +1120 -0
  145. package/docs/superpowers/reviews/2026-08-06-prima-vs-playwright-cli.md +268 -0
  146. package/docs/superpowers/specs/2026-08-01-actor-boat-design.md +204 -0
  147. package/docs/superpowers/specs/2026-08-01-prima-boat-design.md +242 -0
  148. package/docs/superpowers/specs/2026-08-03-global-config-design.md +138 -0
  149. package/docs/superpowers/specs/2026-08-07-prima-fixes-design.md +394 -0
  150. package/docs/web-testing/agents.md +158 -0
  151. package/docs/web-testing/automated-tests.md +134 -0
  152. package/docs/web-testing/basics.md +91 -0
  153. package/docs/web-testing/customization.md +131 -0
  154. package/docs/web-testing/hooks.md +238 -0
  155. package/docs/web-testing/page-interaction.md +84 -0
  156. package/docs/web-testing/planner.md +122 -0
  157. package/docs/web-testing/rerun.md +164 -0
  158. package/docs/web-testing/researcher.md +380 -0
  159. package/docs/workflow/agentic-usage.md +233 -0
  160. package/docs/workflow/application-spec.md +73 -0
  161. package/docs/workflow/ci.md +202 -0
  162. package/docs/workflow/knowledge.md +310 -0
  163. package/docs/workflow/planning-styles.md +67 -0
  164. package/docs/workflow/reporting.md +133 -0
  165. package/docs/workflow/test-plans.md +90 -0
  166. package/models.json +3 -0
  167. package/package.json +8 -3
  168. package/rules/navigator/verification-actions.md +20 -0
  169. package/src/action-result.ts +11 -0
  170. package/src/action.ts +47 -7
  171. package/src/ai/captain/mixin.ts +3 -3
  172. package/src/ai/captain/web-mode.ts +7 -4
  173. package/src/ai/captain.ts +3 -0
  174. package/src/ai/navigator.ts +26 -15
  175. package/src/ai/pilot.ts +53 -2
  176. package/src/ai/planner.ts +7 -0
  177. package/src/ai/provider.ts +2 -4
  178. package/src/ai/rerunner.ts +2 -1
  179. package/src/ai/researcher.ts +2 -2
  180. package/src/ai/rules.ts +17 -10
  181. package/src/ai/task-agent.ts +4 -2
  182. package/src/ai/tester.ts +32 -18
  183. package/src/ai/tools.ts +132 -36
  184. package/src/application-spec-contract.ts +10 -0
  185. package/src/application-spec.ts +87 -0
  186. package/src/browser-server.ts +74 -19
  187. package/src/commands/clean-command.ts +1 -6
  188. package/src/commands/init-command.ts +146 -1
  189. package/src/commands/navigate-command.ts +1 -1
  190. package/src/commands/research-command.ts +1 -1
  191. package/src/commands/sites-command.ts +27 -0
  192. package/src/components/InitWizard.tsx +166 -0
  193. package/src/components/InputReadline.tsx +8 -4
  194. package/src/config.ts +177 -43
  195. package/src/execution-controller.ts +8 -0
  196. package/src/explorbot.ts +34 -7
  197. package/src/explorer.ts +47 -9
  198. package/src/global-config.ts +148 -0
  199. package/src/knowledge-tracker.ts +17 -1
  200. package/src/playwright-recorder.ts +23 -0
  201. package/src/remote.ts +238 -0
  202. package/src/reporter.ts +7 -1
  203. package/src/state-manager.ts +2 -1
  204. package/src/stats.ts +1 -0
  205. package/src/test-plan.ts +9 -0
  206. package/src/utils/aria.ts +65 -45
  207. package/src/utils/cli-name.ts +5 -2
  208. package/src/utils/html.ts +1 -0
  209. package/src/utils/logger.ts +24 -1
  210. package/src/utils/page-readiness.ts +24 -1
  211. package/src/utils/test-files.ts +1 -2
  212. package/src/utils/url-matcher.ts +13 -0
  213. package/src/utils/web-element.ts +9 -0
  214. package/src/utils/web-sandbox.ts +3 -4
@@ -0,0 +1,57 @@
1
+ # AI Agent Integration Tests
2
+
3
+ We test AI agents with [`@copilotkit/aimock`](https://github.com/CopilotKit/aimock), an HTTP mock server that speaks LLM provider protocols. Unlike in-process model stubs, it runs the real `Provider` class and lets you inspect the HTTP requests through its Journal.
4
+
5
+ Reference implementation: `tests/integration/planner.test.ts`.
6
+
7
+ ## Principles
8
+
9
+ ### What we mock
10
+
11
+ - **The AI provider** — via the aimock HTTP server. Point the Vercel AI SDK at `mock.url/v1` with `createOpenAI({ compatibility: 'compatible' })` and `openai.chat('model-name')`. The `compatibility: 'compatible'` option keeps the mock on the Chat Completions API; without it, the SDK defaults to the Responses API, which aimock does not fully implement.
12
+ - **Explorer, StateManager, Researcher, ExperienceTracker** — duck-typed mocks with only the methods the agent under test calls. Each agent runs in isolation; downstream agents (such as Researcher when testing Planner) return canned output.
13
+ - **`withPage`** — resolves with a fake page object for agents that validate locators, since no browser runs in these tests.
14
+
15
+ ### What we don't mock
16
+
17
+ - The real `Provider` class, so tests exercise serialization, retry, and telemetry paths.
18
+ - Parsers, result objects, and markdown processing — the real pipeline runs.
19
+ - `ActionResult.fromState()`, which works without the filesystem when `state.html` is inline.
20
+
21
+ ### What we test
22
+
23
+ - **Output correctness**: the plan or research markdown the agent returns matches the canned AI response.
24
+ - **Prompt construction** (via Journal): `mock.getLastRequest()` returns the messages sent to the AI, so you assert on what the agent prompted, not just what it returned. This is the main reason to use aimock.
25
+ - **Control flow**: cache hits, dedup, retries, error paths, and style or feature injection. Inspect the request count and prompt content.
26
+
27
+ ### Fixture types
28
+
29
+ - Text response (for `chat()` / `invokeConversation()`): `mock.on({}, { content: 'text' })`
30
+ - Structured output (for `generateObject()`): `mock.on({}, { content: JSON.stringify(obj) })` — the SDK parses it back via `response_format: json_schema`
31
+ - Sequential responses: `mock.on({ sequenceIndex: 0 }, ...)`, `sequenceIndex: 1`, ...
32
+ - Errors: `mock.on({}, { error: {...}, status: 500 })`
33
+ - See aimock docs for matching by user message, tool name, regex, or predicate.
34
+
35
+ ### Test data
36
+
37
+ - Canned UI maps live in `test-data/ui-maps/`.
38
+ - Use fictional applications (Task Tracker, and so on). Never use real product data or user names.
39
+ - Two formats exist, depending on the agent under test:
40
+ - **Planner-input** (`task-board.md`): Element and Type columns only — what the Planner sees after its own table-column filtering.
41
+ - **Researcher-output** (`task-board-research.md`): full Element, Type, ARIA, CSS, and Coordinates columns — the raw Researcher AI output format.
42
+
43
+ ### Module-level caches
44
+
45
+ Many agents hold module-level state: plan registry, session dedup, style cache, research cache. Each module that caches across calls must export a `clearXxx()` function for use in `beforeEach`. See the existing exports:
46
+
47
+ - `src/ai/planner/subpages.ts` — `clearPlanRegistry()`
48
+ - `src/ai/planner/session-dedup.ts` — `clearSessionDedup()`
49
+ - `src/ai/planner/styles.ts` — `clearStyleCache()`
50
+ - `src/ai/researcher/cache.ts` — `clearResearchCache()`
51
+
52
+ ## Running
53
+
54
+ ```bash
55
+ bun test tests/integration/planner.test.ts
56
+ bun test tests/integration/
57
+ ```
@@ -0,0 +1,90 @@
1
+ # Contributing to Explorbot
2
+
3
+ ## Project Philosophy
4
+
5
+ Explorbot is general-purpose. It works with any web application, with no site-specific code. Keep this in mind when you contribute:
6
+
7
+ - Solutions must work across different websites.
8
+ - Don't hardcode locators or site-specific selectors.
9
+ - Prefer universal patterns: ARIA, semantic HTML, common UI conventions.
10
+ - A fix that only helps one site is probably the wrong approach.
11
+
12
+ ## Before You Start
13
+
14
+ Discuss first, code second. Open an issue to propose your idea before you send a PR. This saves wasted effort and aligns on the approach.
15
+
16
+ If Explorbot struggles on your site, try the built-in extension points first:
17
+
18
+ - Knowledge files teach Explorbot about your pages (credentials, wait conditions, hints).
19
+ - Rules add agent-specific guidance for navigation, research, and planning.
20
+ - Hooks run custom logic before and after actions.
21
+ - Configuration adjusts models, timeouts, and browser settings.
22
+
23
+ See the [knowledge](../workflow/knowledge.md), [hooks](../web-testing/hooks.md), and [configuration](../reference/configuration.md) docs.
24
+
25
+ ## Pull Requests
26
+
27
+ We accept PRs that help a variety of users. Here is what gets merged.
28
+
29
+ ### Tiny PRs get merged first
30
+
31
+ Small, focused changes are reviewed and merged quickly. Examples:
32
+
33
+ - Fix a typo in a prompt.
34
+ - Add a missing ARIA selector pattern.
35
+ - Improve an error message.
36
+ - Fix a bug with a clear reproduction.
37
+
38
+ ### PRs that change agent logic require manual testing
39
+
40
+ Changes to agents (tester, navigator, researcher, pilot, and others) affect how Explorbot interacts with every website. These PRs must be:
41
+
42
+ - Polished — clean code, no leftover debug artifacts.
43
+ - Tested by a person on real websites.
44
+ - Described clearly: what changed and why.
45
+
46
+ ### PRs that change prompts require execution traces
47
+
48
+ If you change internal AI prompts or rules, you must provide a [Langfuse](https://langfuse.com) execution trace that shows the change improved behavior. "It should work better" is not evidence. Show the before and after.
49
+
50
+ ### We accept agentic PRs
51
+
52
+ AI-generated contributions are welcome if they follow the rules above: small, focused, tested, with clear explanations.
53
+
54
+ ### What NOT to send
55
+
56
+ - PRs that reformat code differently. We use [Biome](https://biomejs.dev/) for formatting. Run `bun run format` before submitting.
57
+ - Large refactoring PRs without prior discussion.
58
+ - Site-specific fixes that only help one website.
59
+ - Changes that break existing tests.
60
+
61
+ ## Development Setup
62
+
63
+ ```bash
64
+ bun install
65
+ bunx playwright install
66
+ ```
67
+
68
+ ## Code Style
69
+
70
+ - Biome for formatting and linting. Run `bun run format` after every change.
71
+ - No comments unless explicitly needed.
72
+ - Early returns instead of nested if/else.
73
+ - KISS/YAGNI — make the smallest change possible.
74
+ - No code duplication. Check if it already exists.
75
+ - Use dedent for formatting prompts.
76
+ - No ternary operators.
77
+
78
+ See `CLAUDE.md` for the full guidelines.
79
+
80
+ ## Testing
81
+
82
+ Run `bun run format`, `bun run lint`, `bun run test:unit`, and `bun run test:node` before you submit a PR — all checks must pass. See the [testing guide](testing.md) for details, [AI integration tests](ai-integration-tests.md) for mocked-LLM agent tests, and [regression tests](regression-tests.md) for the real-AI end-to-end harness.
83
+
84
+ ## Using Claude Code
85
+
86
+ This project includes Claude Code skills to help with development. See the `.claude/skills/` directory: changelog, demo-video, explorbot-debug, explorbot-fix-session, image-processing, prompt-audit, xpath-testing.
87
+
88
+ ## Questions?
89
+
90
+ Open an issue on GitHub for questions or discussion.
@@ -0,0 +1,36 @@
1
+ # Demo Videos
2
+
3
+ Explorbot sessions can be turned into demo videos for social media and presentations. The generator composites the browser screencast of a test with a simulated terminal that replays the session's real log lines at their original pace, over an abstract background with window chrome and shadows. Everything shown is real recorded data: no more than 1.25x speedup, successful runs only.
4
+
5
+ Implementation lives in `.claude/skills/demo-video/` (`demo-video.ts` exports `analyzeDemoCandidates` and `createDemoVideo`; the Bunoshfile wraps them as commands).
6
+
7
+ ## Prerequisites
8
+
9
+ - `vhs` and `ttyd` — render the terminal simulation (`go install github.com/charmbracelet/vhs@latest`)
10
+ - `ffmpeg` and ImageMagick
11
+ - IBM Plex Mono font (optional — VHS falls back to its default mono font)
12
+ - A session recorded with screencasts: enable `ai.agents.historian.screencast` in `explorbot.config.js` so `output/screencasts/*.webm` exist alongside `output/explorbot.log`
13
+
14
+ ## Usage
15
+
16
+ ```bash
17
+ bunx bunosh demo:analyze output/explorbot.log --screencasts output/screencasts
18
+ bunx bunosh demo:video --size landscape --app-title "My App"
19
+ bunx bunosh demo:video "upload a file" --size vertical --terminal-theme light
20
+ ```
21
+
22
+ `demo:analyze` lists candidate segments ranked by how well they will read on video. `demo:video` renders the best one, or the test whose scenario name matches the first argument. Key options: `--duration` (target seconds, default 30), `--size` (`landscape`, `square`, `vertical`, or `WxH`), `--app-title` (browser window title, defaults to the tested app's host), `--terminal-theme` (`dark` or `light`), `--bg-image` (`auto` fetches a random abstract photo from Unsplash, `gradient` generates one offline, or pass a file/URL). Run `bunx bunosh demo:video --help` for the full list.
23
+
24
+ The renderer verifies its output and writes three check frames (`*-frame-first/mid/last.png`) next to the video — review them before publishing.
25
+
26
+ ## How segments are picked
27
+
28
+ Only successful tests with an existing screencast qualify. Within a test, the scorer prefers windows that:
29
+
30
+ - are dense in visible actions (click, fill, type, navigate) rather than thinking or verification steps
31
+ - have no dead air — inter-step gaps stay under 10 seconds
32
+ - show forward progress — windows dominated by repeated retry steps are rejected
33
+ - were executed live — batch-logged step bursts cannot sync with the video and are rejected
34
+ - do not end on a failure note or mid-navigation on a blank page
35
+
36
+ The log's `Saved screencast:` line joins a test to its `.webm`; video time is calibrated from that timestamp minus the video duration. If a screencast file was overwritten by a run outside the log, it is skipped.
@@ -0,0 +1,138 @@
1
+ # Building and Publishing the npm Package
2
+
3
+ Explorbot develops on Bun but ships to npm as a Node.js-compatible package. This page covers how the build works and how to publish it.
4
+
5
+ ## Prerequisites
6
+
7
+ - Bun (for development and running the build)
8
+ - Node.js >= 24 (for verifying the build output)
9
+ - npm account with publish access to `explorbot` package
10
+
11
+ ## How the Build Works
12
+
13
+ The source is TypeScript with `.ts` imports (enabled by `allowImportingTsExtensions` in `tsconfig.json`). Bun runs these natively, but Node.js needs compiled `.js` files.
14
+
15
+ The build runs the TypeScript compiler (`tsc`) with a dedicated `tsconfig.build.json`:
16
+
17
+ 1. **TypeScript compilation** - Compiles `src/`, `bin/`, and `boat/` to `dist/`, preserving the directory structure.
18
+ 2. **Import rewriting** - `rewriteRelativeImportExtensions` rewrites `.ts` imports to `.js` in the output (a TypeScript 5.7+ feature).
19
+ 3. **Type declarations** - `scripts/build-types.ts` emits `.d.ts` files for the library API (see [Type Declarations](#type-declarations)).
20
+ 4. **Asset copying** - Copies `rules/` and `assets/sample-files/` into `dist/` so runtime path resolution works.
21
+ 5. **Shebang replacement** - Replaces `#!/usr/bin/env bun` with `#!/usr/bin/env node` in every CLI entry point declared in `bin`: `dist/bin/explorbot-cli.js` and `dist/boat/prima/bin/prima-cli.js`.
22
+
23
+ ### Build Configuration
24
+
25
+ **`tsconfig.build.json`** extends the base `tsconfig.json` with:
26
+
27
+ | Option | Value | Purpose |
28
+ |--------|-------|---------|
29
+ | `noEmit` | `false` | Enable output (base config has `true`) |
30
+ | `outDir` | `dist` | Compilation output directory |
31
+ | `rewriteRelativeImportExtensions` | `true` | Rewrite `.ts` → `.js` in imports |
32
+ | `declaration` | `false` | The JS build emits no `.d.ts`; declarations are built separately (see below) |
33
+ | `sourceMap` | `false` | No source maps in the published package |
34
+ | `skipLibCheck` | `true` | Skip type checking of dependencies |
35
+
36
+ The build skips type checking (`--noCheck` flag) because Bun is more permissive than `tsc` strict mode. Bun enforces type safety during development.
37
+
38
+ ### Package Structure
39
+
40
+ After the build, the npm package contains:
41
+
42
+ ```
43
+ dist/
44
+ ├── bin/explorbot-cli.js # CLI entry point (#!/usr/bin/env node)
45
+ ├── src/ # Compiled application code (.js) + type declarations (.d.ts)
46
+ │ ├── index.js # Library entry point
47
+ │ └── index.d.ts # Library type declarations
48
+ ├── boat/ # Compiled API tester module
49
+ ├── rules/ # Agent rule files (markdown)
50
+ └── assets/sample-files/ # Sample files for testing
51
+ ```
52
+
53
+ ### Type Declarations
54
+
55
+ `declaration: true` doesn't work directly on this codebase: the Researcher agent is built from generic mixin factories (`WithDeepAnalysis(Base)` etc.) that return anonymous classes with `private` members, which TypeScript can't serialize into a `.d.ts` (`TS4094`). Rather than refactor those hot-path agents, `scripts/build-types.ts` generates declarations from a transformed copy of the source:
56
+
57
+ 1. Copies `src/` into a temporary tree, rewriting every `private`/`protected` class modifier to `public` at its exact AST position (members are preserved; only the visibility keyword changes, which removes `TS4094`).
58
+ 2. Runs `tsc --emitDeclarationOnly` over the copy into `dist/src/`.
59
+ 3. Rewrites `.ts`/`.tsx` module specifiers to `.js` in the emitted `.d.ts` so they resolve for consumers.
60
+ 4. Deletes the temporary tree.
61
+
62
+ The transform touches only the intermediate copy — the shipped `.js` keeps its real `private`/`protected` visibility. The `.d.ts` types are exact (unions, option shapes, and return types are all preserved), so Node.js/TypeScript consumers get full type-checking. Bun consumers resolve the TypeScript source directly via the `bun` export condition.
63
+
64
+ Key `package.json` fields:
65
+
66
+ ```json
67
+ {
68
+ "bin": {
69
+ "explorbot": "./dist/bin/explorbot-cli.js",
70
+ "prima": "./dist/boat/prima/bin/prima-cli.js"
71
+ },
72
+ "main": "dist/src/index.js",
73
+ "types": "dist/src/index.d.ts",
74
+ "exports": {
75
+ ".": {
76
+ "types": "./dist/src/index.d.ts",
77
+ "bun": "./src/index.ts",
78
+ "import": "./dist/src/index.js"
79
+ }
80
+ },
81
+ "files": [
82
+ "dist/",
83
+ "src/**/*.ts",
84
+ "src/**/*.tsx",
85
+ "bin/**/*.ts",
86
+ "boat/api-tester/src/**/*.ts",
87
+ "boat/doc-collector/src/**/*.ts",
88
+ "boat/doc-collector/bin/**/*.ts",
89
+ "boat/doc-collector/package.json",
90
+ "boat/prima/src/**/*.ts",
91
+ "boat/prima/bin/**/*.ts",
92
+ "boat/prima/package.json",
93
+ "rules/",
94
+ "assets/sample-files/"
95
+ ],
96
+ "engines": { "node": ">=24.0.0" }
97
+ }
98
+ ```
99
+
100
+ The package ships two commands: `explorbot`, and `prima` for the [prima boat](../reference/commands.md#prima-boat), so `npx -p explorbot prima <command>` works without a separate install.
101
+
102
+ Explorbot is both a CLI (`bin`) and a library (`exports`). The `.` entry point is `src/index.ts`, a side-effect-free barrel that re-exports the public API (`ExplorBot`, `Plan`, `Test`, and their types). The `exports` conditions are ordered so each consumer gets the right entry: `types` (the emitted `.d.ts`) for type-checking, `bun` (the TypeScript source) under Bun, and `import` (the compiled JS) under Node.js. This is why the source `src/**` files ship alongside `dist/`.
103
+
104
+ ## Building Locally
105
+
106
+ ```bash
107
+ # Build the npm package
108
+ bun run build:npm
109
+
110
+ # Verify the CLIs work on Node.js
111
+ node dist/bin/explorbot-cli.js --help
112
+ node dist/boat/prima/bin/prima-cli.js --help
113
+
114
+ # Check what would be published
115
+ npm pack --dry-run
116
+ ```
117
+
118
+ ## Publishing
119
+
120
+ GitHub Actions publishes automatically (see below), but you can also publish manually:
121
+
122
+ ```bash
123
+ # Bump version
124
+ npm version patch # or minor, major
125
+
126
+ # Build and publish (prepublishOnly runs build:npm automatically)
127
+ npm publish
128
+ ```
129
+
130
+ ## Known Limitations
131
+
132
+ - **Type declarations are transform-generated** - Declarations come from a transformed copy of the source (see [Type Declarations](#type-declarations)), not from `tsc --declaration` directly, because the mixin-based agents can't emit declarations as written. The published `.d.ts` types are exact; the workaround only concerns how they're produced.
133
+
134
+ ## CI/CD
135
+
136
+ The `test.yml` workflow verifies the npm build on every push. On Node.js 24 it runs `bun run build:npm`, then the Node smoke tests: `node --test tests/node/*.mjs`. The `publish.yml` workflow additionally checks `node dist/bin/explorbot-cli.js --help` before publishing.
137
+
138
+ The `publish.yml` workflow publishes to npm when you push a version tag (`v*` or a bare `1.2.3`-style tag). It overwrites the package version from the tag; tags containing `beta`, `alpha`, `pre`, or `rc` publish to the `beta` dist-tag instead of `latest`.
@@ -0,0 +1,227 @@
1
+ # Observability & Debugging
2
+
3
+ Explorbot integrates with [Langfuse](https://langfuse.com) for tracing. Use it to see what happened during a session: what data each agent received, which tools it called, and how it decided.
4
+
5
+ ![Langfuse Trace View](../assets/langfuse-trace.png)
6
+
7
+ ## Why Observability?
8
+
9
+ Without traces, you only see the final test result and basic logs. When Explorbot runs on its own, you need to see:
10
+
11
+ - What prompts went to the AI.
12
+ - What tools were called, and with what parameters.
13
+ - Token usage and cost per session.
14
+ - How long each operation took.
15
+ - Errors and retries.
16
+
17
+ Use this data to:
18
+
19
+ - Debug failed tests. See what the AI saw and decided.
20
+ - Create Knowledge fixes. Find the context that was missing.
21
+ - Tune prompts and agent performance.
22
+ - Understand why a test passed or failed.
23
+ - Export sessions for the `/explorbot-debug` skill.
24
+
25
+ ## Setting Up Langfuse
26
+
27
+ ### 1. Create a Langfuse Account
28
+
29
+ Sign up at [langfuse.com](https://langfuse.com) (free tier available) or self-host.
30
+
31
+ ### 2. Get Your API Keys
32
+
33
+ From your Langfuse project settings, copy:
34
+ - **Public Key**
35
+ - **Secret Key**
36
+
37
+ ### 3. Configure Explorbot
38
+
39
+ Add credentials to your `.env` file:
40
+
41
+ ```bash
42
+ LANGFUSE_PUBLIC_KEY=pk-lf-xxxxxxxx
43
+ LANGFUSE_SECRET_KEY=sk-lf-xxxxxxxx
44
+ ```
45
+
46
+ Or configure in `explorbot.config.js`:
47
+
48
+ ```javascript
49
+ export default {
50
+ ai: {
51
+ model: groq('gpt-oss-20b'),
52
+ langfuse: {
53
+ enabled: true,
54
+ publicKey: process.env.LANGFUSE_PUBLIC_KEY,
55
+ secretKey: process.env.LANGFUSE_SECRET_KEY,
56
+ baseUrl: 'https://cloud.langfuse.com', // or your self-hosted URL
57
+ },
58
+ },
59
+ };
60
+ ```
61
+
62
+ ### 4. Run Explorbot
63
+
64
+ Once configured, Explorbot traces every AI call. No code changes needed.
65
+
66
+ ## What Gets Traced
67
+
68
+ Explorbot uses the [Vercel AI SDK integration](https://langfuse.com/docs/integrations/vercel-ai-sdk) with Langfuse. Each session captures:
69
+
70
+ | Trace | Description |
71
+ |-------|-------------|
72
+ | `test: <scenario>` | Full test execution cycle |
73
+ | `researcher: <url>` | Page analysis by Researcher agent |
74
+ | `planner: <url>` | Test scenario generation |
75
+ | `driller: <url>` | Component drilling |
76
+ | `ai.generateText` | Text generation calls |
77
+ | `ai.generateObject` | Structured output calls |
78
+ | `codeceptjs.step` | Individual browser actions |
79
+
80
+ Navigator has no span of its own — its AI calls appear as `ai.*` spans under the parent trace.
81
+
82
+ ## Analyzing Sessions
83
+
84
+ ### In Langfuse Dashboard
85
+
86
+ 1. Open your Langfuse project
87
+ 2. Find the session by timestamp or name
88
+ 3. Click to see the full trace tree
89
+ 4. Inspect individual spans for:
90
+ - Input prompts
91
+ - Output responses
92
+ - Token counts
93
+ - Duration
94
+ - Errors
95
+
96
+ ## Debugging with Claude Code
97
+
98
+ Explorbot includes a Claude Code skill that analyzes failed sessions.
99
+
100
+ ### Using the Debug Skill
101
+
102
+ Find the failed `test: <scenario>` trace in Langfuse and copy its trace ID. Then, in Claude Code, run:
103
+
104
+ ```
105
+ /explorbot-debug
106
+ ```
107
+
108
+ Give it the trace ID — the skill fetches the trace with all its observations via `bun .claude/skills/explorbot-debug/langfuse-export.ts <trace-id>`. The trace holds the full context: prompts, tool calls, page states, and AI decisions. Without a trace ID, the skill analyzes `output/explorbot.log` instead.
109
+
110
+ ### What the Skill Analyzes
111
+
112
+ The skill looks for three failure patterns:
113
+
114
+ | Pattern | Symptoms | Solution |
115
+ |---------|----------|----------|
116
+ | **Missing Context** | Wrong element clicked, didn't understand UI | Add Knowledge file with disambiguation rules |
117
+ | **Wrong Prompts** | Incorrect assumptions, wrong flow | Add Knowledge with business context |
118
+ | **Wrong Tool Choice** | Used click when form needed, typing issues | Add Knowledge with CodeceptJS code examples |
119
+
120
+ ### How It Helps
121
+
122
+ 1. Extracts key data from the trace with jq:
123
+ - Failed tool calls
124
+ - URLs visited
125
+ - Prompts sent to the AI
126
+
127
+ 2. Identifies the root cause of failures.
128
+
129
+ 3. Suggests Knowledge files to fix the issue:
130
+ ```markdown
131
+ ---
132
+ url: /admin/users/*
133
+ ---
134
+
135
+ ## User Table
136
+ Each row has same buttons. Use container:
137
+ I.click('Delete', '[data-user-id="123"]')
138
+ ```
139
+
140
+ 4. Can try interactions with browser tools, if available, and record working CodeceptJS code.
141
+
142
+ ### Example Workflow
143
+
144
+ ```bash
145
+ # 1. Test fails
146
+ ./bin/explorbot-cli.ts explore /admin/users
147
+
148
+ # 2. Open Langfuse, find the failed "test: ..." trace, copy its trace ID
149
+
150
+ # 3. In Claude Code:
151
+ /explorbot-debug
152
+ # Provide the trace ID
153
+
154
+ # 4. Skill analyzes and suggests Knowledge fix
155
+ # 5. Create knowledge file
156
+ ./bin/explorbot-cli.ts learn "/admin/users/*" "Use container context for table actions"
157
+
158
+ # 6. Re-run test
159
+ ```
160
+
161
+ ## Debugging Tips
162
+
163
+ ### Enable Verbose Logging
164
+
165
+ ```bash
166
+ ./bin/explorbot-cli.ts explore /admin/users --verbose
167
+ ```
168
+
169
+ Or set the environment variable:
170
+
171
+ ```bash
172
+ DEBUG=explorbot:* ./bin/explorbot-cli.ts explore /admin/users
173
+ ```
174
+
175
+ This shows detailed logs:
176
+
177
+ - Prompts sent to the AI
178
+ - Tool calls and results
179
+ - State transitions
180
+
181
+ ### Specific Debug Namespaces
182
+
183
+ ```bash
184
+ # AI provider calls only
185
+ DEBUG=explorbot:provider ./bin/explorbot-cli.ts explore /admin/users
186
+
187
+ # Navigator agent only
188
+ DEBUG=explorbot:navigator ./bin/explorbot-cli.ts explore /admin/users
189
+
190
+ # Multiple namespaces
191
+ DEBUG=explorbot:tester,explorbot:navigator ./bin/explorbot-cli.ts explore /admin/users
192
+ ```
193
+
194
+ ### Available Namespaces
195
+
196
+ | Namespace | What it shows |
197
+ |-----------|---------------|
198
+ | `explorbot:provider` | AI API calls, responses |
199
+ | `explorbot:provider:out` | Outgoing prompts |
200
+ | `explorbot:provider:in` | Incoming responses |
201
+ | `explorbot:navigator` | Navigation decisions |
202
+ | `explorbot:researcher` | Page analysis |
203
+ | `explorbot:planner` | Test scenario generation |
204
+ | `explorbot:tester` | Test execution |
205
+ | `explorbot:historian` | Experience saving |
206
+ | `explorbot:quartermaster` | A11y analysis |
207
+
208
+ ## Cost Tracking
209
+
210
+ Langfuse tracks token usage per call. Use it to:
211
+
212
+ - Monitor cost across sessions
213
+ - Compare model efficiency
214
+ - Find expensive operations
215
+ - Tune prompts to reduce tokens
216
+
217
+ ## Self-Hosting Langfuse
218
+
219
+ For privacy or compliance, you can self-host Langfuse. Langfuse v3 requires docker compose with Postgres, ClickHouse, and Redis — follow the [self-hosting docs](https://langfuse.com/self-hosting).
220
+
221
+ Then set `baseUrl` in your config:
222
+
223
+ ```javascript
224
+ langfuse: {
225
+ baseUrl: 'http://localhost:3000',
226
+ }
227
+ ```
@@ -0,0 +1,103 @@
1
+ # Self-Regression Tests
2
+
3
+ The regression harness runs Explorbot **end-to-end with real AI models** against a controlled local fixture app, then asserts on the artifacts Explorbot produces (research, plans, test results). Unlike the integration tests in `tests/integration/` — which mock the LLM — these runs use a live provider, so they are nondeterministic and gated behind owner approval in CI.
4
+
5
+ The harness lives in `tests/regression/` and is driven by `regression:*` commands in the repo `Bunoshfile.js`.
6
+
7
+ ## Scenarios
8
+
9
+ ### Scenario A — fresh explore (`regression:basic`)
10
+
11
+ Runs `explorbot explore /issues --headless` against the Trackly fixture and asserts:
12
+
13
+ - **Login evidence** — a plan targets a post-login route (`/issues`, `/settings`) and at least one research file describes a post-login page (proves the agent applied the seeded credentials and got past the gate).
14
+ - **Research** — at least one research file with a heading, a UI-map table, and enough domain keywords.
15
+ - **Scenarios identified** — the plan holds at least `MIN_PLANNED_TESTS` tests covering at least `MIN_FEATURE_GROUPS` feature areas.
16
+ - **Tests passed** — the `Results: N passed, N failed` stdout line shows no failures and at least `MIN_PASSED` passing tests, cross-checked against the reporter markdown.
17
+
18
+ Credentials are supplied through a seeded knowledge file (`tests/regression/seeds/knowledge/login.md`) matched to `/login`, so this scenario also exercises knowledge rules.
19
+
20
+ ### Scenario B — experience reuse (`regression:experience`)
21
+
22
+ Proves Explorbot reuses prior context to pass a test it cannot pass cold. The Trackly Archive vault (`/vault`) is unlocked only by an access code that exists nowhere in the DOM — only in the server and in the seed files.
23
+
24
+ - **Control run** (always, once) — runs the seed plan with **empty** knowledge and experience dirs. It must NOT pass. A fully-passing control means the vault gate is broken and fails the harness.
25
+ - **Seeded run** (retried) — runs the same plan with the seed knowledge and experience dirs. It must pass.
26
+
27
+ The plan (`tests/regression/seeds/vault-plan.md`) describes *what* to do but never contains the code. The seeded context supplies it two ways: `seeds/knowledge/vault.md` carries the access **code** (data), and `seeds/experience/vault.md` carries the interaction **recipe** (fill field, click Unlock). Both are prior seeded context; the control has neither and fails.
28
+
29
+ > The code is carried in a knowledge file, not only experience, on purpose. Knowledge is Explorbot's prominent, deterministic channel for page-specific data — the same mechanism scenario A uses for login credentials. Empirically, cheap models followed an experience-only code recipe only occasionally, so an experience-only gate was a coin-flip; knowledge makes the gate reliable while the experience file still exercises recipe reuse.
30
+
31
+ ## The fixture app — "Trackly"
32
+
33
+ A self-contained issue tracker served in-process by `tests/regression/fixture/server.ts` (`Bun.serve`, ephemeral port, fresh in-memory store per attempt). No external network, no database.
34
+
35
+ | Route | Auth | Contents |
36
+ |-------|------|----------|
37
+ | `/login` | no | credentials form (always native HTML) |
38
+ | `/issues` | yes | issue list, search, status filter, label menu (start page) |
39
+ | `/issues/new` | yes | create form: title, description, priority, labels + assignees multiselects |
40
+ | `/issues/:id` | yes | detail, change-status menu, comment form, delete modal |
41
+ | `/settings` | yes | Profile/Preferences tabs + an activity iframe |
42
+ | `/vault` | no | scenario B access-code gate |
43
+ | `/api/*` | cookie | REST API over the same store, `+ /api/openapi.json` |
44
+
45
+ The REST API mirrors the store and is served for a future API-testing scenario; the current scenarios do not exercise it.
46
+
47
+ ### Component variants (ARIA on/off)
48
+
49
+ Every widget (button, text field, select, multiselect, dropdown menu, modal, tabs) renders in one of three variants, selectable per run:
50
+
51
+ - `native` — semantic HTML (`<button>`, `<select multiple>`, `<dialog>`, `<details>`).
52
+ - `aria` — custom `<div>` widgets with correct roles (`role="combobox"`, `aria-modal`, `role="menu"`, …).
53
+ - `plain` — bare `<div>` widgets with no roles or labels (the hostile case).
54
+ - `random` — a seeded RNG picks a variant per widget; the same `--seed` reproduces identical markup.
55
+
56
+ Pass `--variant` and `--seed` to any scenario. The login page is always native so variant runs don't fail at the door.
57
+
58
+ ## Running locally
59
+
60
+ ```bash
61
+ # No-AI sanity check: fixture routes, auth, API, vault gate, seed parsing, variant rendering
62
+ bunx bunosh regression:smoke
63
+
64
+ # Serve the fixture for manual inspection (append ?variant=plain&seed=7 to any page)
65
+ bunx bunosh regression:serve
66
+
67
+ # Real-AI runs (need a provider key)
68
+ export OPENROUTER_API_KEY=sk-...
69
+ bunx bunosh regression:experience --retries 0 # cheapest AI path
70
+ bunx bunosh regression:basic --retries 0
71
+ bunx bunosh regression:all # both scenarios, default retries
72
+ ```
73
+
74
+ Each attempt runs in an isolated throwaway directory under `tests/regression/.runs/` (gitignored). Inspect `tests/regression/.runs/<scenario>-<variant>-a<n>/output/` for the research, plans, and reporter markdown a run produced, and `tests/regression/.runs/report.md` for the summary.
75
+
76
+ ### Variant matrix
77
+
78
+ `regression:variants` runs a scenario across variants and reports the outcome per variant **without gating** — a `plain`-variant failure is data about model robustness, not a regression. Only a crashed or timed-out run fails it.
79
+
80
+ ```bash
81
+ bunx bunosh regression:variants --scenario basic --variants native,aria,plain
82
+ ```
83
+
84
+ ## CI and the approval gate
85
+
86
+ `.github/workflows/regression.yml` runs on `pull_request` and `workflow_dispatch`. The job uses the `regression` GitHub environment, which holds `OPENROUTER_API_KEY` behind a **required reviewer**. Every run — including fork PRs — pauses at the environment gate before the secret is exposed. The job runs the PR's own code, so the reviewer must read the PR diff (workflow, Bunoshfile, fixture, lib) before approving; that review is the security boundary. The workflow never uses `pull_request_target`.
87
+
88
+ The report is posted as a sticky PR comment (on `pull_request`) or a `Regression Reports` GitHub Discussion (on `workflow_dispatch`). Fork PRs get a read-only token, so comment posting may fail; the report is also written to the job step summary and uploaded as the `regression-runs` artifact.
89
+
90
+ The report also embeds the **Session Analysis** from the fresh-explore run — Explorbot's Analyst agent writes a prose summary of what works, defects, UX issues, and execution issues, which the harness reads from `output/reports/<label>.md` and appends to the comment. The Analyst is enabled in the config template (`ai.agents.analyst.enabled: true`); it adds one AI call per basic run.
91
+
92
+ ## Tuning
93
+
94
+ - **Thresholds** (`MIN_PLANNED_TESTS`, `MIN_PASSED`, `MIN_KEYWORD_HITS`, `MIN_FEATURE_GROUPS`) live at the top of `tests/regression/lib/assertions.ts`.
95
+ - **Models** live in `tests/regression/fixture/explorbot.config.js`. If cheap models are too flaky, promote a stronger model to `ai.model` or lower `MIN_PASSED`.
96
+ - **Run size** — adjust `--max-tests` in `runBasicScenario` and the per-CLI `timeout` values in `Bunoshfile.js`.
97
+
98
+ ## Owner prerequisites (one-time)
99
+
100
+ 1. Settings → Environments → create `regression`; add the repo owner as a **Required reviewer**; deployment branch policy "No restriction".
101
+ 2. Add the environment secret `OPENROUTER_API_KEY` (a dedicated key with a low spend limit).
102
+ 3. Create a Discussions category named exactly `Regression Reports`.
103
+ 4. Ensure the OpenRouter account has credit for the models in the config template.