feat: let exec() and shell() take a cwd - #41
Merged
Merged
Conversation
A command in a subdirectory had no way to say so: TaskContext hardcoded the
project root as cwd, even though ExecutorInterface has accepted a cwd option all
along. The workaround was shell('cd frontend && npm ci'), which puts the command
back through a shell - the thing argv execution exists to avoid.
`cwd` now joins env, tty and timeout in the options array and defaults to the
project root, so every existing call behaves exactly as before. Proven against
the binary, same argv twice:
> cat marker.txt -> No such file or directory
> cat marker.txt (cwd: .../frontend) -> ich-bin-im-frontend
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.
Follow-up to the review finding in #40, where I listed this as "additive, so not a 0.2 decision". The additive part is right; the "so leave it" part was not, and here is why it is worth doing rather than deferring.
The gap
TaskContexthardcoded the project root as the working directory, whileExecutorInterfacehas accepted acwdoption all along. So a task that needs to run something in a subdirectory had exactly one route:That puts the command back through a shell — the thing #30 removed as the default. A monorepo with a
frontend/is not an exotic case, so the safe path had a hole in it that pushed people to the unsafe one.The change
cwdjoinsenv,ttyandtimeoutin the options array and defaults to the project root, so every existing call behaves exactly as before. That is what makes it additive: no signature changes, no behaviour changes, only a key that was previously impossible to pass.Proven against the binary with the same argv twice:
Three tests: the default is the project root,
exec()honours an override,shell()takes the same option.Correcting myself on the second item
In #40 I put two findings under one label.
cwdis additive. The other one —TaskContextstill taking?OutputInterfaceand?SputnikOutputnext to theOutputChannelfrom #32 — is not additive, and my reason for deferring it does not survive a check:TaskContextisfinal, so it cannot be mocked. A user who wants to unit-test their own task has to construct a real one, with nine required arguments, two of which are final classes. There is no documentation anywhere on how to test a task. So that constructor is user-facing, and changing it is a breaking change — I called it cheap because "users never construct one", which I had not verified.That does not make it a 0.2 blocker, but it changes the reason: it is deferred because breaking changes are acceptable before 1.0, not because nobody is affected. The right time to do it is together with a documented testing story — a factory or builder so a task test does not need nine collaborators — and that is a design question, not a pre-tag cleanup.
Verified
Both this and #40 touch
docs/tasks.mdin the same region. They are independent branches offmain; if the merge of the second one conflicts, tell me and I will rebase it rather than resolving it in the web editor.🤖 Generated with Claude Code
https://claude.ai/code/session_018CTvnzcNYmFgm2HQcm821A