Skip to content

fix(mcp): real docling_ready probe + DoclingProcessSurface attestation - #204

Merged
elasticdotventures merged 2 commits into
mainfrom
feat/60-docling-pdf-bridge
Aug 26, 2026
Merged

fix(mcp): real docling_ready probe + DoclingProcessSurface attestation#204
elasticdotventures merged 2 commits into
mainfrom
feat/60-docling-pdf-bridge

Conversation

@elasticdotventures

Copy link
Copy Markdown
Member

Closes the remaining gap in #60.

Context

#200 (already on main) implemented the real PDF-ingest path — PdfIngestOp
shells out to a reqif-opa-mcp Python sidecar via
uv run python -m reqif_ingest_cli extract and parses its output as a
docling_bridge::DoclingDocumentGraph. That's items 1–2 of #60's spec, and
they were done before this session started.

What was still missing from #60:

  • l3dg3rr_get_pipeline_status hardcoded docling_ready: true instead of
    checking anything (item 3).
  • No b00t ProcessSurface attestation existed for the sidecar dependency
    (item 4).

What this PR does

  • Adds b00t_iface::docling::DoclingProcessSurface, a ProcessSurface
    implementation attesting the sidecar's two real hard preconditions: uv
    on PATH, and a reqif-opa-mcp checkout present at the configured
    directory (default ~/promptexecution/reqif-opa-mcp, matching the
    existing convention in ledger_ops.rs's ignored real-subprocess test).
  • Wires ledgerr-mcp-server.rs's l3dg3rr_get_pipeline_status handler to
    DoclingProcessSurface::new().is_ready() instead of a literal true.
  • Removes integration_tests.rs's stale #[ignore]d
    test_ingest_statement_via_pdf_sidecar, which asserted that
    IngestStatementOp::execute() itself would do PDF ingest — that
    contradicts the PdfIngestOp-as-its-own-operation design that was
    actually shipped (IngestStatementOp now deliberately rejects .pdf
    input and points callers at PdfIngestOp). PdfIngestOp has its own
    test coverage in ledger_ops.rs, including a real (ignored)
    subprocess integration test.

Deliberate deviation from #60's literal text

#60's sketch checks which::which("docling") and a Requirement::BinaryOnPath("docling")
directly, assuming a standalone docling CLI binary on PATH. That's not
how the code that actually shipped in #200 works — there is no bare
docling binary in this architecture; the real dependency chain is uv +
a reqif-opa-mcp checkout. This PR checks the real preconditions instead
of a nonexistent binary. Flagging this explicitly in case the intent was
different from what I inferred from the shipped code — happy to adjust.

Testing

  • cargo test -p b00t-iface docling — 3/3 new tests pass
  • cargo test -p ledger-core --lib pdf_ingest — existing PdfIngestOp
    tests still pass (2 passed, 1 ignored as before — needs a real uv +
    checkout)
  • cargo test -p ledgerr-mcp --features legacy --test mcp_adapter_contract doc_02
    — the exact acceptance-criteria test from docling bridge: wire IngestStatementOp PDF branch + DoclingProcessSurface b00t attestation #60
    (doc_02_pipeline_status_shape_is_deterministic_and_concise, asserting
    blockers: ["docling_unreachable"] when docling_ready: false) passes
  • cargo build -p ledgerr-mcp --bin ledgerr-mcp-server — clean

🤖 Generated with Claude Code as part of an
unattended overnight session — flagging for human review before merge.

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

elasticdotventures and others added 2 commits August 26, 2026 22:39
#60)

PdfIngestOp and DoclingDocumentGraph (the actual PDF-ingest path, via a
uv-run reqif-opa-mcp sidecar) already existed before this change, landed
by #200. This closes the remaining gap from #60: l3dg3rr_get_pipeline_status
hardcoded docling_ready to true instead of checking anything.

Adds b00t_iface::docling::DoclingProcessSurface, a ProcessSurface
attestation checking the sidecar's two real hard preconditions (uv on
PATH, reqif-opa-mcp checkout present) — adapted from #60's literal
`which::which("docling")` sketch, which predates the uv/reqif-opa-mcp
architecture and no longer matches how PdfIngestOp actually works.

Also removes integration_tests.rs's stale #[ignore]'d
test_ingest_statement_via_pdf_sidecar, which asserted behavior
(IngestStatementOp itself doing PDF ingest) that contradicts the
PdfIngestOp design actually shipped; PdfIngestOp has its own coverage
in ledger_ops.rs, including a real ignored subprocess integration test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CI's test-and-build check failed on init_fails_when_checkout_missing:
it asserted Err(DoclingError::CheckoutMissing(_)) with a nonexistent
checkout dir, but init() checked `uv` on PATH first, and CI runners
don't have uv installed — so it returned NotOnPath instead, which the
test didn't expect. Passed locally only because uv happens to be
installed on this dev machine.

Reorders init() to check the checkout path first, so the test (and
init()'s behavior generally) no longer depends on whether uv happens
to be present on whatever machine is running it. Verified locally both
with uv on PATH and with a PATH that excludes it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant