import type { ToolDefinition } from "./types.js"; /** * `specguard-lint --json` (Ruby) or `specguard lint --json` (JS/TS) as a tool — * the `@intent` linter, shipped in `specguard-ruby` (`bin/specguard-lint`, * SPGD-12 §1) and in `@yatfa/specguard` (`specguard lint`). Which one runs is * decided by `SPECGUARD_LINT_COMMAND` alone; this file does not detect it. * * == Why this wraps the JSON renderer and not the human one * * The gem grew `--json` in SPGD-305 precisely so a consumer gets *which file, * which line, which rule* as data instead of a prose format to regex. An agent * is that consumer. Passing `--json` unconditionally is what makes this a thin * client rather than a parser: the document goes back as the linter emitted it, * key for key, and this file contains no knowledge of the OpenTestIntent schema, * no finding shape, and no rule about what makes an annotation valid. * * == The exit code is a verdict, not an error * * The linter's contract is three-valued and the mapping is the one decision * this tool actually makes: * * 0 — every annotation checked was valid (including "there were none"). * 1 — at least one annotation is malformed. A SUCCESSFUL tool call with * findings in it. Reporting exit 1 as a tool error would tell the agent * the linter broke, when what happened is the linter worked and the code * is wrong — and an agent that reads "tool failed" retries the tool * instead of fixing the annotation. * 2 — the linter could not do its job. A tool error, and the only one. The * gem deliberately emits NO document on this path (a `{"ok": false, * "findings": []}` for a run that checked nothing is how a gate that * checked nothing gets mistaken for one that found nothing), so the prose * it wrote to stderr is the entire diagnosis and is passed through. * * `ok` is read off the document rather than re-derived from the exit code, and * the exit code is reported beside it, so an agent can see the two agree. * * == What is deliberately not validated here * * `--changed` together with explicit paths is misuse, and the linter exits 2 * saying so. This tool does not pre-empt that. Re-implementing the rule would * put a second copy of the linter's argument grammar in a different language, * free to drift the day the gem adds a flag — and the tool would then be * enforcing a contract it does not own. The schema documents the conflict; the * linter adjudicates it. */ declare const lintIntentAnnotations: ToolDefinition; export default lintIntentAnnotations;