T-7W0N-waypost-run-parameterised-task
State: closed/done · Impact: medium · Complexity: medium
Let a person supply a task’s arguments before it runs. Waypost finds
just deploy <env>, shows it, offers to run it, and then runs just deploy
with no environment — a command the catalog knows is incomplete. Both surfaces
have the data to do better and neither uses it.
Task keeps argv and display as separate strings on purpose: display
carries <required> / [optional] / *variadic placeholders and is not
executable, argv is executable and omits the parameters entirely. The
parameters themselves are modelled as data in Task.parameters. Nothing reads
that field to ask for values.
| Location | Role today |
|---|---|
packages/ts/detect-runners/src/model.ts | Param (name, required, variadic, default?) and Task.parameters. The field every surface has and none uses. |
packages/ts/detect-runners/src/providers/just.ts | Populates parameters from just --dump, including defaults. |
packages/ts/detect-runners/src/providers/rake.ts | Populates parameters from a rake task’s declared args. |
packages/ts/waypost/src/tui.ts | runAndExit spawns argv, then prints takes <env> [tag] — the shape is computed after the incomplete command has already run. |
packages/ts/waypost/src/web/api.ts | requestRun(id). An id and nothing else. |
packages/ts/waypost/src/serve.ts | POST /api/run looks the id up in the catalog it built itself and hands the terminal over. |
Every other provider emits parameters: [], so a change here is inert for
them — the affected surface is exactly the recipes that declare arguments.
Proposed
Section titled “Proposed”Enter on a task with parameters opens the full command in one editable field,
cursor after a trailing space, with the parameter shape shown beneath it. Type,
⏎ to run, esc to back out. A task with no parameters is untouched: ⏎ runs
it with nothing to dismiss.
One editable line rather than a field per parameter. A form would need to know how to quote, how to order variadics, and what to do when someone wants to pass a flag the recipe never declared — an editable command line has correct answers to all three for free.
TUI, where entry speed is the point, so this is a footer and not a dialog:
› deploy just ▸ ▸ ───────────────────────────────────────────────────────────────── just deploy <env> [tag] just just build just ───────────────────────────────────────────────────────────────── $ just deploy ▮ takes <env> [tag] ⏎ run esc backWeb, the same content as an inline panel rather than a modal, so dismissing it costs no click:
┌ Run ─────────────────────────────────────────────────────────────┐│ $ just deploy ▮ ││ takes <env> [tag] ││ [Cancel] [Run ⏎] │└──────────────────────────────────────────────────────────────────┘The field is seeded from argv, never from display — display holds
placeholders that a shell reads as redirections and globs, which is the reason
the two fields exist separately at all.
The server contract does not loosen
Section titled “The server contract does not loosen”POST /api/run takes an id and nothing else, deliberately: the port is
reachable by any process on the machine and any site the browser visits, so
accepting a command string would make it an arbitrary-code-execution endpoint.
That stays true. The request grows one field — a list of argument strings —
which the server appends to the argv it looked up itself. The binary, the
leading arguments and the cwd still come only from the catalog, and nothing the
client sends can replace them.
Approach
Section titled “Approach”- Web first: gate
requestRunbehind the editable line whenparameters.length > 0, and send the typed remainder as an argument list. - Server: accept and append the argument list, keeping the binary and cwd catalog-only. A test asserts a crafted body cannot change the binary.
- TUI: the same line before
runAndExit, reusing the shape string that function already builds for its after-the-fact notice. - Document the behaviour on both surfaces’ guide pages.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
packages/ts/waypost/src/web/view.ts | modify | Render the run panel. |
packages/ts/waypost/src/web/input.ts | modify | Enter opens the panel for a parameterised task; esc closes it. |
packages/ts/waypost/src/web/api.ts | modify | requestRun carries the argument list. |
packages/ts/waypost/src/serve.ts | modify | /api/run appends the list to its own argv. |
packages/ts/waypost/src/tui.ts | modify | The footer entry line before runAndExit. |
packages/ts/waypost/docs-site/src/content/docs/guide/web-view.mdx | modify | Describe running a parameterised task. |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
just deploy <env>runs with a supplied value from both surfaces, and the echoed command is the one that actually ran. - AC-2: Cancelling runs nothing and leaves the list where it was.
- AC-3: A task with no parameters still runs on a single
⏎, with no extra step. - AC-4: A test proves a request naming a different binary or cwd cannot change what is spawned — the client contributes trailing arguments only.
- AC-5: The seeded text comes from
argv; a recipe whosedisplayholds<placeholders>never puts them on the command line.
Out of scope
Section titled “Out of scope”- Remembering the last values used for a task. A history would need a per-task store and a way to clear it; nothing has asked for one yet.
- Validating a value against its
Param. The runner rejects what it does not accept, and duplicating that judgement here would be a second opinion that can be wrong.
Dependencies
Section titled “Dependencies”- none
Discovery context
Section titled “Discovery context”Found while surveying what functional work waypost had left, 2026-08-31. The
answer was that it had almost none, and this was the gap: the catalog can show
you a task it cannot help you run. runAndExit printing takes <env> [tag]
after spawning the incomplete command is the clearest symptom.