Let the plan name the site an explorbot test run explores - #165
Merged
Conversation
`explorbot test <planfile>` built its ExplorBot with no target, so a global installation had nothing to resolve a site from and the run died in config loading with "No site to explore" before the plan was ever read. The plan already carries the URL: the CLI now reads it before the container is built, and passes it as the run target, which serves both the global installation and the EXPLORBOT_* variables. The expression for a plan's URL — its own, else the first test's — moves onto Plan as `startUrl`, replacing the four copies of it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013W3pakMDZuDEjzm6LCFMCB
DenysKuchma
requested changes
Aug 31, 2026
| indexArg = planfile; | ||
| } | ||
|
|
||
| const planFile = [planfileArg, `${planfileArg}.md`].find((file) => fs.existsSync(file)); |
Collaborator
There was a problem hiding this comment.
This only checks the current directory, while loadPlan() also resolves names through getPlansDir(). In global mode, explorbot test saved-plan can therefore fail before loadPlan() even though the plan exists. Could both paths use the same resolver?
`explorbot test <planfile>` peeked at the plan for its URL with an existence check against the working directory alone, while `loadPlan()` resolves a name through the plans directory as well. In a global installation a saved plan named by its file name was therefore invisible to the peek, and the run died in config loading with "No site to explore" before `loadPlan()` could find it. Both paths now call one resolver, `resolvePlanPath()` in `src/utils/plan-path.ts`: a path or a name, `.md` optional, looked up in the working directory and then in the plans directory. The CLI runs before the config is loaded and has no plans directory to name, so it searches the plans directory of every registered site instead — enough to read the plan, take its URL, and let config loading resolve the site from it. `ExplorBot.resolvePlanPath()` keeps its signature and delegates. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCCFv7WWR67iCLLkSnnMnS
# Conflicts: # CHANGELOG.md
The resolver belongs with the class that already reads plan files, not in a file of its own: `Plan.resolvePath()` beside `Plan.fromMarkdown()`, with its tests in the Plan suite. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCCFv7WWR67iCLLkSnnMnS
`Plan.loadFromFile(file, plansDir?)` resolves a path or a saved-plan name and returns the plan it loaded, or null when there is none — no separate path resolver to call first. It records the file it read as `plan.filePath`, so a caller that wants the file (the `/plans` listing, the multi-suite read behind `explore --configure`) takes it from the plan instead of resolving twice. `ExplorBot.resolvePlanPath()` is gone; `loadPlan`, `loadPlans`, `PlansCommand` and both CLI plan commands go through the loader. `plan:load` resolves saved-plan names now too, as `test` does. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCCFv7WWR67iCLLkSnnMnS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Running a saved plan against a global installation was impossible: the command died in config loading before it ever opened the plan.
~/.explorbot/config.jsholds models and keys, never a site — every command names the site it runs against.testnamed none: it built itsExplorBotwithfrom: undefined, soenterGlobalModehad no target. The plan carries the URL all along, in its### Prerequisitesection, so the CLI now reads it before the container is built and passes it as the run target. The same target feeds theEXPLORBOT_*branch of config loading, so a config-free env setup gets the fix too.src/commands/test-command.tsis unchanged — the gap was in bootstrapping, not in test selection.Also here:
explorbot test <planfile>with no index runs every enabled test, as--helpand the docs already said. It used to run only the first pending one.Plan.startUrl, replacing the four copies of the expression (CLI twice, both historian writers).Verification
Smoke run against a real plan with an out-of-range index, so nothing executed past navigation:
bun teston test-plan, historian, config and global-config: 97 pass.Notes
rerun <file>has the same gap and is left alone here.🤖 Generated with Claude Code
https://claude.ai/code/session_013W3pakMDZuDEjzm6LCFMCB