grammar-inference-engine/docs/adr/0007-json-output-for-llm-prompt-injection.md
tobjend e23922a1b7
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
feat: adaptive multi-assignment clustering; add ADRs 1-10
- Multi-assignment clustering (no greedy 'used' set)
- Adaptive ngram fallback (shrink when (other) > 60%)
- Add docs/adr/ with 10 architecture decision records
- Fix ADR 1 (query modification description)
- Fix ADR 3 (multi-assignment + adaptive shrink)
- Fix ADR 5 (import sort order clarification)
- Fix ADR 6 (remove Kotlin call_suffix references)
- New ADR 9 (adaptive clustering rationale)
- New ADR 10 (universal package mapping via relpath)
2026-07-03 22:58:09 +02:00

2.1 KiB

7. JSON output for LLM prompt injection

Date: 2026-07-03

Status: Accepted

Context

The text table output is human-readable but not directly usable by an LLM. To use behavioral conventions in another agent or coding session, the output must be parsed, reformatted, and injected into a prompt — an extra friction step.

An LLM consuming conventions needs:

  • Structured data it can read directly (no parsing).
  • All metadata per convention (grammar, imports, args, files, packages).
  • Compact enough to fit in context without overflow.

Decision

Add a --json flag that outputs a structured JSON array instead of the text table.

JSON structure:

[{
  "language": ".kt",
  "conventions": [{
    "label": "assertEquals",
    "method_count": 327,
    "algorithm": "CRX",
    "grammar": "assertEquals+",
    "mdl_score": 1.0,
    "imports": ["import io.mockk.every", "..."],
    "arg_patterns": {
      "assertEquals": {
        "occurrences": 42,
        "arg_count": {"min": 2, "max": 3, "common": 2},
        "patterns": [{"count": 30, "args": 2, "types": ["lit", "var"]}]
      }
    }
  }],
  "total_methods": 1581
}]

Also accepts --format json and --format text for explicit control.

Consequences

Positive:

  • LLM consumes the JSON directly — no parsing step needed.
  • All metadata in one object per convention — imports, args, packages all together.
  • --json is a single flag — the default text output remains for human review.

Negative:

  • JSON is more verbose than text (full import list instead of truncated preview).
  • No easy way to limit output size — a large codebase produces JSON that may overflow context.
    • Mitigation: --include flag filters files before analysis, and max_clusters=20 caps cluster count.

Alternatives Considered

  • YAML output: More readable, but less universally parseable by LLMs.
  • CSV output: Too flat for nested data (arg_patterns, imports list).
  • Custom prompt template: Would need per-framework templates. JSON is framework-agnostic.
  • No structured output: User must pipe through jq or manual reformatting. Bad UX.