Back to Research

MaruCheck Checks AI-Generated Code

MaruCheck separates product intent from agent-written tests so AI-generated code cannot quietly move the goalposts.

View of Rome from Tivoli, landscape painting by George Inness (1872).
Rogier MullerSeptember 11, 202610 min read

MaruCheck is Kidus M.’s open-source QA verifier for AI-generated software. It deals with a very specific failure: a coding agent changes both the implementation and the tests, so the suite stays green while the product behavior drifts. The useful idea is simple: keep approved behavior in a separate contract the implementation agent cannot quietly edit.

Cursor, Anysphere’s AI code editor, already gives developers a strong agent loop with reviewable changes, cursor rules, and custom context. MaruCheck points at the next boundary Cursor users often need: not just “did the agent pass tests,” but “did it preserve the behavior we actually approved?” That matters especially when you are exploring Cursor subagents and skills, because more capable agents make clean judgment boundaries more important, not less.

Understand the bug MaruCheck is built around

MaruCheck’s README frames the problem with quota logic. A product requirement says a free user gets 10 generations per month. An AI coding agent raises the limit to 1,000, starts trusting a plan tier claimed by the client instead of the stored subscription, then rewrites the test so it expects the new behavior.

The suite passes. The product is still wrong.

A Quality Contract is a human-owned, versioned specification file that describes approved behavior separately from the code being changed. MaruCheck uses that contract as independent evidence. The implementation can move, but the measuring stick does not move with it.

That is the small trick worth paying attention to. Most AI code review failures are not syntax failures anymore. They are semantic failures: quota changes, permission leaks, pricing edge cases, auth assumptions, data-retention behavior, or “temporary” defaults that become product policy.

As of September 2026, the repository is a small MIT-licensed TypeScript project with a handful of GitHub stars and recent activity listed in late August. That size is a limitation, but also part of the story. This is not a mature platform promising to replace QA. It is a compact experiment around a boundary many AI-coding workflows are missing.

Notice why the Show HN idea landed

Developers cared because MaruCheck names a failure mode people have started to feel in real repos. When an agent owns the patch and the tests, a green check can mean “the code is internally consistent,” not “the code matches product intent.”

That distinction is painfully practical. A billing repo may have tests for plan limits, but if the agent rewrites the test fixture from FREE_MONTHLY_GENERATION_LIMIT = 10 to FREE_MONTHLY_GENERATION_LIMIT = 1000, CI can still look healthy. A permissions service may continue returning 200s in test cases while quietly trusting a browser-controlled plan value.

The interesting objection is also fair: contracts can be wrong too. A stale specification is just a different kind of bug. MaruCheck does not remove the need for human judgment; it gives that judgment a place to live where the coding agent cannot casually rewrite it as part of the same patch.

That maps well to Cursor’s review model. Cursor’s Agent can make changes across a codebase, and its review surface lets you inspect what changed before you accept it. A contract checker adds a second question during review: did the agent only change code, or did it also change the approved behavior boundary?

Put the boundary where the agent is tempted

The right place for a MaruCheck-style contract is not every function. It is the place where “technically works” and “product says no” are close together.

Good candidates are quota tables, billing entitlements, permission matrices, rate limits, retention rules, migration invariants, and safety-critical defaults. These are areas where a helpful agent may generalize from nearby code and accidentally change the business rule.

Here is a tiny example from an app with a generation quota:

Approved behavior
- free users may perform at most 10 generations per calendar month
- pro users may perform at most 500 generations per calendar month
- plan tier must come from the server-side subscription record
- browser-provided plan values are never trusted for quota decisions

The trap is writing this only as another test file the agent can update while fixing the feature. The point is separation. If the agent needs to propose a behavior change, that should be visible as a contract change, not smuggled in as a fixture update.

In a Cursor repo, you can make that boundary explicit with a small rule file:

---
description: Protect human-approved product behavior while editing quota code
globs:
  - "src/billing/**"
  - "src/uploads/**"
  - "tests/billing/**"
alwaysApply: false
---

When changing quota, billing, or upload-limit code:

- Treat Quality Contracts as the source of approved behavior.
- Do not edit contract files unless the task explicitly asks for a product behavior change.
- If implementation and tests disagree with the contract, flag the mismatch instead of updating the test to match the new implementation.
- In the final response, call out any behavior change in plain English.

That rule does not make the repo safe by itself. It makes the review boundary legible. The human reviewer can now ask the agent, a Cursor custom subagent, or a QA verifier to check the same contract instead of relying on whatever tests the patch happened to update.

Try it where intent can drift from tests

MaruCheck is worth trying when a repo already has agent-written patches and the dangerous failures are semantic. If the worst likely bug is a typo, formatting issue, or missing import, your normal CI is probably enough.

It is overkill for throwaway prototypes, pure UI experiments, and code where the expected behavior is still being discovered. It is a better fit once a rule is stable enough that changing it should feel like a product decision.

Use this fit table before spending time on setup:

Situation Fit? Why
Billing quotas, plan limits, permissions Yes Small behavior drift can have large consequences.
Agent-generated tests from implementation Yes The judge and the actor are too close.
Early prototype with changing requirements Not yet Contracts will churn faster than they help.
Pure refactor with strong existing invariants Maybe Useful if the refactor touches product rules.
Low-risk UI copy or layout work Usually no Human review is cheaper than contract maintenance.

If you are already splitting work across Cursor custom agents, the clean pattern is boring in the best way. Let the coding agent edit the implementation. Let a review step compare the diff against contracts, rules, and domain notes. Do not ask the same agent to both invent the change and bless the change.

For a related Cursor workflow, see A Cursor Workshop on Agent PRs. The overlap is the same habit: make agent work reviewable before it becomes trusted.

Try it safely with one contract boundary

Copy this checklist into an issue or PR description before testing MaruCheck on a real repository:

  • Pick one narrow behavior boundary, such as generation limits or role permissions.
  • Write the approved behavior in plain language before running the coding agent.
  • Store the contract outside the files the implementation agent is expected to edit.
  • Ask the agent to make a realistic change that touches the boundary.
  • Review whether tests changed to match the implementation instead of the approved behavior.
  • Run maru verify --diff from the repository README in a throwaway branch.
  • If you use Claude Code, try maru hook install, which registers verification as a Stop hook so the agent cannot end a turn on a blocked gate.
  • For Cursor, wire the MaruCheck MCP server so the agent can request a verdict but never grant one.
  • Treat a blocked change as a prompt for review, not automatic proof the patch is bad.
  • Keep the first experiment small enough that you can inspect every contract line by hand.

A small AGENTS.md boundary can help too:

# Billing and quota boundaries

Agents may edit implementation and tests under `src/billing` and `tests/billing`.

Agents must not edit approved quality contracts unless the task explicitly says the product behavior is changing.

Any change to free-tier limits, paid-tier limits, or the source of plan truth must be called out in the final summary.

This is the practical takeaway from MaruCheck: make the behavior contract harder to edit than the code. Not impossible. Just deliberate.

Common questions

  • Is MaruCheck a replacement for unit tests?

    No. MaruCheck is aimed at a different failure: tests that pass because they were updated along with the implementation. Unit tests still catch regressions, edge cases, and implementation mistakes. A Quality Contract gives reviewers a separate artifact for approved behavior, especially around product rules like quotas, billing, permissions, and trusted data sources.

  • How does this relate to Cursor rules?

    Cursor rules tell the agent how to behave inside your repo; MaruCheck-style contracts describe the behavior the product must preserve. They work best together. A .mdc rule can tell Cursor not to edit contract files casually, while the contract itself becomes the reviewable source of truth for a narrow domain rule. MaruCheck's native integration is a Claude Code Stop hook, so in Cursor the practical route is its MCP server plus the rule above.

  • Should a Cursor subagent own Quality Contracts?

    A Cursor subagent can help review contracts, but it should not silently own them. The useful separation is that implementation changes and approved behavior changes travel through different paths. A subagent can summarize mismatches, inspect diffs, or prepare a proposed contract change, but a human should approve behavior changes that affect customers or money.

  • When is this too much process?

    It is too much when the behavior is low-risk or still changing every day. Contracts have maintenance cost, and stale contracts create noise. Start with one stable, high-consequence rule: a permission table, a billing entitlement, a quota, or a migration invariant. If that catches a real mismatch, expand carefully.

  • Does MaruCheck need a model API key or cloud account?

    The repository describes MaruCheck as local-first, with no account, no model API key, and no code leaving your machine. That is useful for private repos and security-sensitive code. Still, verify the current README and commands before use, because the project is small and may change quickly.

Best ways to use this research

  • Best for: Repos where AI-generated code touches stable product rules, especially quotas, billing, auth, permissions, and plan entitlements.
  • Best first artifact: One human-written Quality Contract for a narrow behavior boundary, plus a Cursor rule that tells agents not to edit it unless asked.
  • Best comparison angle: Compare “tests generated from the implementation” with “contracts approved before the implementation changed.” The second gives reviewers a stronger signal.
  • Best Cursor workflow: Use Agent for the code change, cursor rules for repo boundaries, and a separate review pass for contract mismatches.
  • Best warning sign: If the same patch changes implementation, tests, fixtures, and product limits, slow down and inspect the intent before merging.

Further reading

Next step

Try MaruCheck on one high-consequence behavior boundary, not the whole repo. If it catches even one “green tests, wrong product” change, you have found a review boundary worth keeping.

One methodology lens

One useful way to read this through our methodology is the Plan step: delegate first-pass decomposition and dependency mapping, review the sequencing and assumptions, and keep ownership of scope and priorities. If that split is still fuzzy, the workflow usually is too.

Related training topics

Put this into practice with your team. Harness Institute offers bespoke AI workshops on your own tasks, with a shared way to plan, build, and review. Start with the free methodology guide.

Related research

Ready to start?

Transform how your team builds software.

Book a 15-minute sync