Skip to content

fix(run): accept and forward --payable-now; JSON refusal for no-runnable-command - #200

Merged
SELAT-DEV merged 2 commits into
mainfrom
claude/eloquent-thompson-rsqc1t
Sep 24, 2026
Merged

SELAT-DEV merged 2 commits into
mainfrom
claude/eloquent-thompson-rsqc1t

Conversation

@SELAT-DEV

Copy link
Copy Markdown
Contributor

Summary

selat run's "no runnable selat-pay command in pick output" error told the user to "Try --payable-now", but run rejected that flag as unknown (it was not in KNOWN_RUN_FLAGS) and never forwarded it to the rank.mjs spawn, so following the advice dead-ended in an unknown-flag error.

rank.mjs already parses --payable-now on its own (a boolean applied to the catalog before the pick / pin step, independent of selat search), so the flag now works end to end.

Changes

lib/commands/run.mjs

  • --payable-now joins KNOWN_RUN_FLAGS, the usage line, and run --help.
  • parseRunArgs sets payableNow; rankPickArgv forwards it via a new payableNowArgs seam. Omitted when absent, so default ranking argv is unchanged.
  • The hint is now noRunnableHintLine(): it recommends --payable-now, and when the caller already passed it, points at the live 402 instead of repeating advice they already followed.
  • The no-runnable-command refusal now goes through emitRunError. Under --json it is {ok:false, error, reason:"no-runnable-command", detail, hint, payableNow, note?} on stdout instead of prose on stderr with an empty stdout (which JSON.parse("") crashed at machine callers). Human output is unchanged. Nothing is charged on this path either way.

README.md: one sentence on the flag in the selat run row.

Tests

New test/run-payable-now.test.mjs (10 tests): parse/argv seam pins, help text, a guard that every --flag the hint names is one the parser accepts, and hermetic end-to-end runs through bin/selat.mjs against a fake rank.mjs that records its argv. The end-to-end cases reproduce the original loop: the first run hits the refusal with the hint, the retry with --payable-now reaches the ranker carrying the flag and never sees "unknown flag". A --json case checks the stdout contract. Nothing is paid (--dry-run, fake selat-pay, no session budget).

Full suite: 592 pass, 0 fail. npm run check clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BxtLkUJD5kZfi4ggn4YBJE


Generated by Claude Code

The "no runnable selat-pay command in pick output" error told the user to
"Try --payable-now", but `selat run` rejected that flag as unknown and never
forwarded it to the rank.mjs spawn, so following the advice dead-ended in an
unknown-flag error.

rank.mjs already parses --payable-now on its own (a boolean applied to the
catalog before the pick / pin step, independent of `selat search`), so the
flag now works end to end:

- --payable-now joins KNOWN_RUN_FLAGS, the usage line, and `run --help`
- parseRunArgs sets `payableNow`; rankPickArgv forwards it via a new
  payableNowArgs seam, omitted when absent so default ranking is unchanged
- the hint is now noRunnableHintLine(): it recommends --payable-now, and
  when the caller already passed it, points at the live 402 instead of
  repeating advice they already followed

Adds test/run-payable-now.test.mjs: parse/argv seam pins, help text, a
guard that every flag the hint names is one the parser accepts, and a
hermetic end-to-end run against a fake rank.mjs that records its argv
(--dry-run, fake selat-pay, no session budget — nothing is paid).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BxtLkUJD5kZfi4ggn4YBJE
The "no runnable selat-pay command in pick output" path wrote prose to
stderr and returned 1 even under --json, leaving stdout empty — which
JSON.parse("") turns into a crash at a machine caller. Every other run
failure goes through emitRunError; this one now does too.

Under --json the refusal is {ok:false, error, reason:"no-runnable-command",
detail, hint, payableNow, note?} on stdout, with the retry advice carried
as data (`hint`) and `payableNow` telling the caller whether that retry has
already been tried. Human output is unchanged. Nothing is charged on this
path either way.

Adds a --json case to test/run-payable-now.test.mjs covering the first
refusal and the --payable-now retry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BxtLkUJD5kZfi4ggn4YBJE
@SELAT-DEV
SELAT-DEV marked this pull request as ready for review September 24, 2026 18:36
@SELAT-DEV
SELAT-DEV merged commit 209bbc8 into main Sep 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants