Repository navigation
[scanner] --no-interactive emits unfilled {{blank}} placeholders with exit 0 instead of a usage error #322
Description
Finding
With --no-interactive (or whenever stdin is not a TTY — src/cli.ts:115 turns interactive off for every piped invocation), a blank that has no flag, no autodetect value and no default is left unfilled by resolve() (src/resolver.ts:149-158 only asks when interactive is true, otherwise falls through), and expand() deliberately preserves it as {{name}} (src/parser.ts:82-85). run() in src/cli.ts:155-183 then prints that text and exits 0 — there is no check and no diagnostic between resolve() and console.log.
Reading the code at main a76385e:
$ promptargs "Review {{file}}" --no-interactive
Review {{file}}
$ echo $?
0The README's own pipelines are exactly the affected shape (README.md:486-492):
promptargs review --file=src/main.ts --no-interactive | claude -p "do this review"Drop --file= (or misspell the blank in the template) and the model receives the literal text Review {{file}} with a clean exit code, so nothing in the pipeline notices.
This contradicts the CLI's stated contract that bad input is a usage error — README.md:529 ("A flag that names no blank in the template … is also an error") and assertKnownFlags in src/flags.ts:58 already reject the inverse case (a flag with no blank). A blank with no value is the same class of mistake and is currently the only one that passes silently.
expand()'s preservation itself is intended and tested (src/parser.test.ts:99-103, :119-121) — this is about the CLI run path, not the library function.
Fix
In run() (src/cli.ts), after resolve() and before rendering, collect the template's blanks that are absent from every iteration's values (!Object.hasOwn(values, v.name); a blank with a defaultValue never gets here) and, when non-empty and !statusOnly, throw a UsageError such as:
Missing value for {{file}}: pass --file=<value> or run without --no-interactive to be asked.
(main() already turns a thrown error into the cli_error diag + process.exit(1).) --status keeps working as today so it can be used to see which blanks are still unfilled.
Tests: a cli.test.ts case that runCli(['Review {{file}}', '--no-interactive']) exits non-zero with the message, and that ['Review {{file=x}}', '--no-interactive'] and ['Review {{file}}', '--file=a', '--no-interactive'] still succeed. Add a changelog.d/fixed-<slug>.md fragment.
Decision taken by hive: a usage error (non-zero exit), not just a stderr warning — the piped-to-an-LLM case is the documented one, and a warning on stderr is invisible to the consumer that receives the broken prompt. Scope is the run path only; expand() and --status are unchanged.
— hive: agent=scanner backend=copilot model=claude-fable-5.1 copilot=1.0.88
Activity
hivecommons-hive commentedon Oct 23, 2026
🔒 Claimed by agent
scanner(agent on hive hosted-available-oke-11-placeholder-r05x). The claim lasts 2h0m0s without activity and renews while the work continues. Reply/unclaimto release, or/claimto take it over if you outrank the holder.hivecommons-hive commentedon Oct 23, 2026
Folded finding. This was filed as a separate issue, but 1 open agent-filed issue (plus 13 closed as completed in the last 14 days) already cite
src/cli.ts, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.Review backlog (intent-alignment): README --no-interactive description not updated for the new usage error
Filed from an out-of-scope finding in the Hive review of PR #323.
PR: #323 (#323)
Perspective: intent-alignment
Severity: info (P3)
Evidence:
README.md:522(promptargs/README.md
Line 522 in 803e1ff
Finding: README --no-interactive description not updated for the new usage error
README.md:522 still says
--no-interactivemeans 'Skip questions, use defaults only'. A one-line note that an unfilled blank without a default is now a usage error (exit 1) would keep docs aligned with src/cli.ts:163-170. README.md:451 describes library expand() and correctly remains unchanged.Fingerprint:
e8c3a9a50217b5cfea451ea1e065c4425d9d7fdf71ddf342c860cc70231c67bffiled by Hive review backlog
hivecommons-hive commentedon Oct 23, 2026
Additional finding (folded in — same file, possibly a different problem). Raised in the Hive review of PR #323 (#323) and folded into this issue because it cites
README.md, which this issue already covers. It may describe a different problem from this issue's own; address it together with this issue or file it separately before closing.Review backlog (intent-alignment): README --no-interactive description not updated for the new usage error
README.md:522)Perspective: intent-alignment
Severity: info (P3)
Evidence:
README.md:522(promptargs/README.md
Line 522 in 803e1ff
Finding: README --no-interactive description not updated for the new usage error
README.md:522 still says
--no-interactivemeans 'Skip questions, use defaults only'. A one-line note that an unfilled blank without a default is now a usage error (exit 1) would keep docs aligned with src/cli.ts:163-170. README.md:451 describes library expand() and correctly remains unchanged.Fingerprint:
e8c3a9a50217b5cfea451ea1e065c4425d9d7fdf71ddf342c860cc70231c67bffiled by Hive review backlog