Skip to content

--format patch/html/llm fail: the CLI looks for renderers in a directory that does not exist #46

Description

@n1ckyb

--format patch, --format html and --format llm all fail:

$ intentumdiff file a.yaml b.yaml --format patch
No renderer plugin found for format 'patch'
$ echo $?
1

--help advertises all five: "Output format: terminal (default), json, patch, html, llm".

The renderers are not missing

They ship, they load, and they report exactly the names being asked for:

wheel contains : terminal_renderer.wasm  patch_renderer.wasm
                 html_renderer.wasm      llm_renderer.wasm
entry points   : intentumdiff.renderers -> ['html', 'llm', 'patch', 'terminal']
load_plugin()  : all four LOAD
format_name    : 'html'  'llm'  'patch'  'terminal-color'
registry       : _load_renderers() returns 4 adapters

Root cause — one wrong path

src/intentumdiff/cli/_shared.py:

wasm_dir = Path(__file__).parent / "wasm"
candidates = list(wasm_dir.glob(f"{fmt.replace('-', '_')}_renderer.wasm"))

__file__ is intentumdiff/cli/_shared.py, so this resolves to intentumdiff/cli/wasm/, which does not exist. The components are at intentumdiff/wasm/ — one level up.

The glob returns nothing. The fallback loop below it iterates the same non-existent directory, so it also finds nothing. The user is then told the plugin does not exist.

terminal and json are handled inline earlier in the function and never reach this code, which is why exactly those two work — and why the gap looks like "some formats are unimplemented" rather than a path bug.

Fix is Path(__file__).parents[1] / "wasm", but see below before treating this as a one-liner.

Why this matters more than a typo

1. The error message named the wrong cause. A UAT tester concluded "three of five advertised output formats do not exist" and stopped — the correct inference from what the product said. Any user would do the same. No renderer plugin found should distinguish "no component reports this format" from "I looked in a directory that isn't there".

2. Nothing exercises these paths. Four renderer components are built, checksummed, staged and shipped; three have never been run end-to-end. INTENTUMDIFF_REQUIRE_ALL_COMPONENTS exists to stop components being silently absent, but this is the opposite failure: everything is present and the lookup never finds it. A staging gate cannot catch that; only actually rendering can.

3. It is the recurring failure mode. A confident wrong answer instead of the real one — the same family as #44 (guardrails report passed after failing to load their policy) and 0.0.1 (69 errors, exit 0). The path bug is trivial; the pattern is not.

Fix should include

  • Correct the directory, and derive it from the ONE place that already knows where components live rather than re-deriving it from __file__ in the CLI
  • An acceptance test per format: --format patch|html|llm on a real diff must exit 0 and write non-empty output. These would all have failed since the format was first advertised
  • Distinguish "no renderer reports this format" from "the component directory is missing or empty" in the message
  • Check whether anything else derives a component path from __file__ in a subpackage

Note terminal-color is the format name the terminal renderer reports, while the CLI flag is terminal. Worth confirming that mismatch is intentional while in here.

Found by UAT on 0.0.2b1; root cause and the load/declare evidence above verified directly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions