The query tool description tells agents to compute fromLine = line - 20
for context around a hit. For hits in lines 1 through 20 that yields a
negative fromLine, which propagated unchanged through:
MCP get handler -> store.getDocumentBody -> Array.prototype.slice
A negative slice start offsets from the end of the array rather than
clamping to the beginning, so a top-of-file hit on a long document
returned an empty string and on a short document returned content from
the wrong region (e.g. lines 11-30 of a 30-line file in response to a
request for the head of the document). The lineNumbers branch was the
same shape: addLineNumbers(text, -19) emitted "-19:", "-18:" prefixes.
Same buggy slice lived in the CLI getDocument path independently.
Fix in three layers, plus the docstring:
- src/mcp/server.ts: clamp parsedFromLine to >= 1 after parsing input
args and the :line suffix, before it reaches getDocumentBody and
addLineNumbers. Also tighten the query tool's recommendation to
`fromLine = max(1, line - 20)` so following the docstring literally
produces a valid value.
- src/cli/qmd.ts: same clamp on the CLI getDocument fromLine after
the colon-suffix parse.
- src/store.ts: defensive Math.max(0, ...) on the slice start in
getDocumentBody so SDK callers and any future entry points are
protected without relying on every caller remembering to clamp.
- test/store.test.ts: regression test on getDocumentBody with
fromLine = -19 returns the head of the document, not the tail.
- test/cli.test.ts: regression test on `qmd get --from -19` matches
the no-flag baseline (head of document).