DEV Community

Cui Vincent
Cui Vincent

Posted on

I'm tired of cv2.imwrite: building an evidence ledger for pipeline debugging, in public

title: "I'm tired of cv2.imwrite: building an evidence ledger for pipeline debugging, in public"
published: false
tags: showdev, opensource, ai, computervision
cover_image: ""
description: "Process open source: no pip install yet. The design and the one opinionated bet behind a see -> tweak -> diff -> sign-off workbench for vision & agent pipelines."

Honest upfront: this is process open source. There's no pip install today. I'm building it in public — docs and design first, then contracts, then a runnable slice. If you want something to run this week, come back later. If you want to argue about the design before code locks it in, you're exactly who I'm writing for.

The afternoon you probably recognize
Test-set accuracy just dropped from 94% to 87%. You suspect the threshold, maybe the ROI, maybe preprocessing ate the edges.

So you scatter five cv2.imwrite calls through the code. Your folder fills with debug_003_v2_final.png and debug_003_v2_final_REAL.png. You drop a mask into a chat window; it says "probably uneven lighting" — plausible, but it can't tell you which run, which source image, which version of the params produced it.

Come back a week later and you can't answer the only question that matters: "what did I actually change, and why did it look fixed at the time?"

This isn't you not trying hard enough. The open-source vision stack has strong algorithms — OpenCV, OpenMMLab, Paddle, PCL/Open3D, COLMAP. What it's missing is the debugging tooling that expensive closed commercial vision suites baked into their IDEs years ago: click any intermediate, tweak, compare instantly. Those suites are pricey, closed, and only speak their own operator library.

The algorithms aren't weak — the tooling is
That's the whole thesis. I don't want to build another algorithm library. I want the layer above it:

see every step → tweak one param & rerun → diff this run vs. the last → human sign-off when stakes are high
▲ │
└────────────────────────────────── next round ────────────────────────────────────────┘
The first three beats are the everyday inner loop. The fourth (an explicit human Gate) only fires when a change is high-stakes. Most tools give you a fuzzy version of beat one. The goal here is to make all four first-class — and, crucially, reconciled: every run recorded, every decision attributable.

What it should feel like (target — not shipped yet)
No signup, no agent, no protocol to learn. You sprinkle a few lines into your existing pipeline:

import loopvera as lv

def detect(img):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
lv.observe("gray", gray) # one line captures the intermediate

_, mask = cv2.threshold(gray, lv.param("thresh", 130), 255, cv2.THRESH_BINARY)
lv.observe("mask", mask)                                   # lv.param makes it tweakable in the UI
return mask
Enter fullscreen mode Exit fullscreen mode

Then, in a local workbench: see every step as an image, change thresh from 130 → 160, rerun, and diff the two runs side by side with the step that changed highlighted. Library-agnostic — one observe() line, zero migration, whether your pipeline is OpenCV, MMLab, Paddle, or a custom operator.

To be clear: pip install loopvera and loopvera open are not published yet. The snippet above is the direction, not a working command.

The bet underneath: an evidence ledger, not a bigger framework
Vision debugging is the first load-bearing skin. Underneath it is a domain-neutral runtime evidence ledger — and this is where I most want your pushback.

Today's AI agents can edit code, tweak params, and batch runs. Point one at your pipeline overnight and by morning you can't say which run counts, what actually changed, or who authorized the promote — "the model said OK" and "a human approved shipping" blur into the same chat scrollback.

Agents have orchestration (a graph runs steps, a checkpointer resumes them). What they lack is evidence closure. And the tempting fix — fold everything into the graph framework, write run results and Gate decisions straight into a LangGraph checkpointer — quietly costs you later:

Split-brain: your UI reads the checkpointer, CI reads somewhere else → two answers to "did this pass."
Schema churn: the graph's persistence layer ends up doubling as your domain protocol layer; every new domain rewrites it.
Observation ≠ evidence: a trace tells you which tools ran; it doesn't tell you "did this run meet the frozen criteria, and who authorized next."
So the cut I'm making is:

Orchestration swappable. Workers swappable. Ledger not.
LangGraph stays welcome as an optional orchestration backend — it just shouldn't own the trust surface. The full argument is in the repo (Why not LangGraph / all-in-one).

What's actually in the repo today (honest inventory)
✅ Phase 1 docs — the problem, the vision, the comparison, and the opinionated architecture piece (bilingual EN / 简体中文).
⏳ Next: L0 contracts (JSON Schema + conformance tests you can clone and validate).
⏳ After that: a buildable Rust runtime skeleton, then a runnable observe → diff slice.
I'm publishing in stages so each step has standalone value and invites a different kind of contributor — and so the design gets critiqued before the code sets it in concrete. The full Roadmap is public.

What I want from you
Not stars (well — not only stars). I want pushback on two things:

Is the pain real for you? How do you manage pipeline intermediates today — imwrite? W&B? a custom viewer? And is cross-run side-by-side diff actually painful, or have you solved it?
Is "orchestration swappable, ledger not" the right cut? Or would you fold it all into the graph and move on?
If you've felt the imwrite afternoon, I'd love to hear your version in the comments or in Discussions.

Links
⭐ GitHub: https://github.com/Proofrun/LoopVera
💬 Discussions (where decisions live): https://github.com/Proofrun/LoopVera/discussions
🎮 Discord (chat & build help): https://discord.gg/7Xfz8fCmE
See every step. Diff every run. Orchestration swappable. Workers swappable. Ledger not.

I'm a solo developer building this in public, and nothing to pip install yet. At this stage I'm after feedback and design critique, not stars. Would love to hear where I'm wrong.

Top comments (0)