{"slug": "markdown-woes-looks-right-is-wrong", "title": "Markdown woes: Looks right, is wrong", "summary": "A developer has built vmark, a CLI tool that lets Markdown documents carry arithmetic rules so derived values like invoice totals are validated rather than merely rendered. The tool addresses cases where a quantity change leaves net, VAT, and gross amounts stale while the Markdown still renders correctly and passes review. It states rules such as Net = Price * Qty and asserts totals, shifting document review from manual recalculation to checking stated derivations.", "body_md": "Markdown has an unfair advantage: it looks trustworthy.\n\nA table lines up, the headings are right. The numbers have two decimal places. GitHub renders it beautifully. The pull request is green, so you merge it.\n\nAnd the invoice is wrong.\n\nNot obviously wrong: not broken-Markdown wrong. Not “the build failed” wrong. Worse: **arithmetic wrong**, and that is a different class of problem, one Markdown has never really had an answer for.\n\nMarta, a project manager at a small software consultancy. She is good at getting things out the door and the company needs people like her: smart, gets things done on an infra stack that hangs together on zip ties and duct tape. And agents, lots of AI agents.\n\nThe client has added eight hours of on-call support to an already annoying project. Marta opens the invoice in her editor, finds the quantity, changes: `12` to `20`.\n\nThe table still looks fine. She scans the diff.\n\n```\n-| On-call support | hour | 12 | 260.00 | 3120.00 | 717.60 | 3837.60 |\n+| On-call support | hour | 20 | 260.00 | 3120.00 | 717.60 | 3837.60 |\n```\n\nLooks like the intended change and Peter, the reviewer, who is a programmer does not concern himself too much with non-code.\n\n“Eight more hours. Makes sense.” Approved.\n\nMarta closes her laptop. She has a train to catch.\n\nThe invoice is wrong.\n\nThe net amount should have changed from 3,120 to 5,200. VAT should have changed. Gross should have changed. The invoice total should have changed. The payment schedule should have changed. The early-payment discount should have changed.\n\nNone of that happened. And yet **the Markdown is valid Markdown.**\n\nThis is the uncomfortable bit. Git is doing exactly what it was built to do: it tells you that one value changed. Markdown rendering is also doing exactly what it was built to do: it tells you that the document can be rendered.\n\nNeither one knows that `Net = Qty × Rate` is supposed to be true.\n\nThey see this:\n\n```\nQty:   20\nNet:   3120.00\n```\n\nA human sees it too, and a human reviewer has to stop and calculate.\n\nAt some point, this stops being code review. It becomes **rebuilding the spreadsheet in your head.** That is a terrible way to review a document.\n\nA typo is easy to catch. `52000` instead of `5200` jumps off the screen. A derived-number error doesn't. `3120` looks fine for twenty hours at that rate. `717.60` looks like normal VAT. Nothing is absurd, so nobody stops to check the relationship between the numbers. That's the whole bug.\n\nThe company that employs Marta and Peter didn't set out to build a fragile invoicing process. It started as a two-person proof of concept that happened to land a client, then a second one, then five more before anybody had a spare afternoon to fix the parts held together with hope. Peter's first job there, on his first day, was helping carry desks up three flights of stairs. Two years later he's reviewing six-figure invoices in Markdown, same instinct for getting things done, new stakes.\n\nThat's not a knock on Peter or Marta. It's how most small companies actually grow: traction arrives faster than process does, and the gap between them is where invoices like this one live.\n\nI built the first version for my own invoices, because I was tired of hand-updating the same six numbers every time a client asked for one more hour. Then I thought it might be useful to somebody other than me, so I painted it and waxed it: a real CLI, real docs, a name. I'll admit it, I fell for the thing. It brings me genuine joy to keep working on it.\n\nInstead of treating this:\n\n```\n| Item  | Price | Qty | Net   |\n|-------|------:|----:|------:|\n| pen   |  5.00 |  10 | 50.00 |\n| paper |  0.10 | 100 | 10.00 |\n```\n\nas a pile of unrelated numbers, I state the rule:\n\nvmark #order\nNet   = Price * Qty\ntotal = SUM(Net)\nassert total > 0\nNow `50.00` is no longer just a number sitting in a cell. It has a derivation: the document says, in effect:\n\n`Price × Qty`.` Net`.\nNow that changes the review model. You don't have to trust the number. **You can check the claim that produced it.**\n\nA VisiMark document is still an ordinary Markdown file. The Markdown still renders normally, the formulas live in `vmark` blocks. Numbers in prose can be connected to calculated values with invisible anchors:\n\n``` php\nOrder total: **60.00**<!--vmark=order.total-->\n```\n\nThe HTML comment doesn't clutter the rendered document. But VisiMark can now ask a much more useful question: does the number written here still agree with the formula?\n\nThat is the missing layer: Markdown handles the document, Git handles the history, VisiMark handles the arithmetic.\n\nShe changes the on-call quantity from 12 to 20. The table still renders fine. But now the repo runs a check before anything gets approved:\n\n``` bash\n$ visimark check invoice.md\nSTALE   lines.Net       · On-call support\n        3120.00 ≠ 5200.00    Qty * Rate\n\nSTALE   lines.gross_total\n        28659.00 ≠ 31217.40   SUM(Gross)\n\nSTALE   schedule.Amount · Signature\n        8597.70 ≠ 9365.22    Share * lines.gross_total\n```\n\nNot a subtle warning. Each line points at exactly what's now wrong and why. The document isn't hoping Peter notices; it's telling him, and loudly so: by breaking the build.\n\nThat's the shift. A Git diff tells you what changed. VisiMark tells you what should now be true, and whether it is. Those turn out to be different questions, and only one of them was ever being asked.\n\nWire `visimark check` into CI and the rule gets blunt: if the document disagrees with its own arithmetic, the build fails. No more hoping someone remembers to recalculate the invoice by hand.\n\nAnd since fixing stale numbers by typing them in by hand is exactly the kind of chore nobody wants, `visimark fmt` will just repair them for you. The formula is the source of truth; the numbers are just its last known output.\n\nThe client asks for eight more hours. Marta makes the edit. CI goes red before anyone has to eyeball a spreadsheet in their head. She runs the formatter in a VisiMark VS Code extension, the totals catch up on save, she checks the diff: numbers changed, formulas didn't. That's the whole review.\n\nShe sends an invoice that doesn't just look right. It's been checked against the rules that produced it, and the proof travels with the file.\n\n**Your Markdown can be perfectly rendered and completely wrong.** VisiMark doesn't fix Markdown. It just makes the numbers show their work.\n\nI wrote this article with AI. VisiMark is a MIT-licensed project with no business model or sales team behind it.", "url": "https://wpnews.pro/news/markdown-woes-looks-right-is-wrong", "canonical_source": "https://dev.to/holdmybear/markdown-woes-looks-right-is-wrong-4ep0", "published_at": "2026-09-17 17:02:07+00:00", "updated_at": "2026-09-17 17:23:13.554709+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents"], "entities": ["vmark", "GitHub", "Marta", "Peter"], "alternates": {"html": "https://wpnews.pro/news/markdown-woes-looks-right-is-wrong", "markdown": "https://wpnews.pro/news/markdown-woes-looks-right-is-wrong.md", "text": "https://wpnews.pro/news/markdown-woes-looks-right-is-wrong.txt", "jsonld": "https://wpnews.pro/news/markdown-woes-looks-right-is-wrong.jsonld"}}