fix(cli): reject unknown top-level commands instead of silent ask fallthrough - #27
Conversation
Adversarial review: REQUEST_CHANGESThe fix correctly stops the reported bug: However, the Confirmed regression: the quoted natural-language shorthand now fails
That whole quoted string is a single positional argument, so Reproduced with a real
So a legitimate, documented invocation now returns false failure. The new "keeps multi-word natural-language ask shorthand" test only exercises the unquoted 5-token form ( Suggested fixDiscriminate on whitespace instead of token count — a mistyped command has no spaces, a prompt does: const looksLikePrompt = positional.length > 1 || /\s/.test(positional[0] ?? '');
if (invokedAsKnowledge() && command && !COMMANDS.includes(command) && looksLikePrompt) {
command = 'ask';
commandArgOffset = 0;
}This still rejects Test suite note
|
2fd25d5 to
65496ae
Compare
…ilent ask fallthrough When invoked as the `knowledge` bin, any non-command positional was remapped to an implicit `ask`/`build` search prompt. A mistyped command like `knowledge lst` or a bogus one like `knowledge boguscmd` therefore printed a citation-context draft and exited 0, returning false success to scripts. Only remap to `ask` when the input looks like a natural-language prompt: either multiple positional words (`knowledge how do I cite sources`) or a single quoted token that contains whitespace (`knowledge "How do we cite the handbook?"`, the canonical documented form). A single bare token with no whitespace now falls through to the existing unknown-command handler, which exits non-zero with an 'Unknown command' message and a levenshtein suggestion. Rebuilt on the reconciled npm-line main (0.2.86). Tests use an isolated HOME and explicit timeouts; a regression test covers the quoted single-token prompt.
65496ae to
4cba943
Compare
Bug
knowledge boguscmd(and any unknown/typo top-level command such asknowledge lst) silently routed to theask/buildsearch flow: it printedPrepared citation context draft(or a JSON context pack under--json) and exited0, returning false success to scripts and users. Severity: high (slug: unknown-command-fallthrough).Root cause
In
src/cli.ts, when the CLI is invoked as the installedknowledgebin, the dispatcher remapped any non-command positional toask:This intentionally powers the documented natural-language shorthand
knowledge <prompt>, but it also swallowed single-token typos of real commands. The existing unknown-command handler (with a levenshtein "Did you mean" suggestion and non-zero exit) was therefore unreachable for the real bin — it only fired for non-knowledgeinvocations (e.g. tests), which is why the pre-existingunknown command includes suggestiontest passed while the shipped bin misbehaved.Fix
Gate the shorthand so it only applies to genuine multi-word natural-language prompts:
A single unknown token (
boguscmd,lst) is now treated as a mistyped command and falls through to the existing unknown-command handler → exits1withUnknown command: <x>. Did you mean '<y>'? Run 'knowledge --help' .... Multi-word prompts (knowledge how do I cite sources) still route toask, preserving the documentedknowledge <prompt>shorthand and the existingrunKnowledgeBin(['Generate','fake','answer', ...])contract test.Tests
Added to
tests/cli.test.ts(both userunKnowledgeBin, which invokes a wrapper literally namedknowledge, soinvokedAsKnowledge()is true — the condition under which the bug reproduces):knowledge bin rejects unknown single-token command instead of running ask— assertsboguscmdandlstexit1, do not printPrepared citation context draft, and emitUnknown command(plus theDid you mean 'list'suggestion forlst). Fails before the fix, passes after.knowledge bin keeps multi-word natural-language ask shorthand— assertsknowledge how do I cite sourcesstill exits0and runs the ask flow with the prompt preserved.Repro (after fix)
Verification
tests/cli.test.tsshows the same pre-existing failures on this branch as onorigin/main(all timeout/environment-related — identical set), so no regressions introduced.bin/,dist/) intentionally left to be regenerated at build/publish time.🤖 Generated with Claude Code