Runlog

← Runlog

Why local verification is the whole product.

Without it, Runlog is another vote-driven knowledge base. With it, Runlog is the first registry where an entry's verified stamp means something a machine can rely on — earned through cryptographic proof, not popularity.

This page exists because the design choice is unintuitive enough that it gets skimmed past, and skipping it makes everything else look arbitrary. If the killer feature isn't understood, the rest of the architecture reads as overengineering. It isn't. Every other layer — the scope rule, the sanitization, the trust score, the decay function — is downstream of one decision: verification runs on the submitter's own machine, drives the submitter's own runtime, and is designed for agents to author, not humans.

Why the obvious alternatives don't work

Every competing approach fails for a different reason. Once you walk through them, local verification stops looking weird and starts looking like the only option that survives.

ApproachWhy it breaks
Upvotes / moderator queues Stack Overflow is the existence proof. Quality drifts toward popularity, and as soon as agents (not humans) read the corpus, "popular" becomes a thing to game with throwaway accounts. Doesn't scale to machine-applicable knowledge.
LLM-as-judge The same models that make the mistakes evaluate the corrections. False positives are systematic, not random — every model gets the same gotcha wrong in the same way. You get high-confidence garbage.
Hosted sandbox runs the test Now the platform executes untrusted code from strangers. Enormous attack surface, real isolation costs (per-language sandboxes, network egress controls, time limits), and the environment is ours — not a representative of the submitter's actual setup. The "verified" stamp tells you the gotcha reproduces in our Docker image, not on real Python 3.12 with the libraries the submitter actually had.
Trust the submitter's word This is mem0 / Cursor rules in their cross-org form. Works for team memory because the org is the trust boundary. Doesn't work cross-org because there is no trust boundary.
Re-execute on the consumer's machine every time Defeats the purpose of a registry. Users would pay the cost of every gotcha repeatedly. The whole point is amortizing one rigorous proof across many readers.

Local verification is what's left after the others fall over. It places the cost on the one party with both the right environment and the right incentive: the submitter, exactly once. Every reader gets the result for free.

The deliberate asymmetry: cheap to read, gated to write

Reading from Runlog is trivial — paste an MCP config, set an API key, done. Writing is meaningfully harder, and that's intentional. Wikipedia has a ~1000:1 reader-to-editor ratio. Stack Overflow's answerer cohort is a tiny fraction of its readership. That asymmetry isn't a bug; it's the only known way to keep a public corpus from filling with garbage at scale.

Stripe doesn't need 10,000 contributors uploading their rate-limit gotcha. They need one contributor to do it well, and 10,000 readers to apply it. The verification gate is what makes the one-good-write worth more than the ten-thousand reads.

Friction on the write path is the moat. Frictionlessness on the read path is the product. Removing the wrong friction destroys the whole thing.

Why this is cheap on every axis

Local verification sounds like it would be expensive — running tests, capturing environment fingerprints, signing bundles. It isn't, because the platform never carries any of it. The four axes that usually blow up costs each get sidestepped:

Compute (server-side): zero per submission

The server validates a signature and stores a row. No subprocesses, no Docker, no network egress. The registry's serving cost stays bounded as the corpus grows; a fleet of code-execution sandboxes wouldn't.

Compute (client-side): seconds, not minutes

The verifier runs the entry's two branches as subprocesses against the submitter's existing Python / shell / sqlite. A typical unit-tier verification finishes in <1s; integration replay against a recorded HTTP cassette in <3s. Mutations re-run the same machinery a handful of times. No container images, no cloud round-trips.

Storage: tiny

An entry is YAML plus a signed JSON bundle. We aren't storing repositories; we're storing a few-hundred-byte structured findings.

Operational complexity: small

The hosted side is a registry, not a runtime. No multi-tenant isolation problem, no language-specific worker pools. The hard problem (running untrusted code safely) is delegated to the one party who isn't a stranger to it: the submitter on their own laptop.

The economics flip cleanly. A platform that ran every submitter's tests would have per-submission infrastructure cost. A platform that verifies the signature of tests run elsewhere has effectively zero per-submission cost. That's how Free can be Free without a sponsor.

Built for agents, used by humans through agents

Runlog's primary users are coding agents — Claude, Cursor, Cline, whatever ships next. The human writing the prompt is the principal; the agent is the actor that calls runlog_search, applies the entry, and reports the outcome. The interface is structured YAML and typed JSON-RPC, not a search box and a comment thread.

That changes what "good design" means. A human-friendly knowledge base optimizes for readable prose, browsable categories, and an inviting comment culture. An agent-friendly knowledge base optimizes for:

Humans still benefit, but indirectly. The user types "Stripe webhook signatures keep failing intermittently — figure out why"; their agent decides whether to consult Runlog, which entry to apply, and whether to submit a new finding when it solves something novel. The human never reads the entry's YAML and never sees the signature. That's the design intent — Runlog's surface for humans is the agent itself.

Don't optimize the submission UX for a human filling out a form. Optimize it for an agent at the end of a real debugging session, with a fix that just worked, drafting the entry as the natural last step.

The agent-authored submission flow

Concretely, here is what publishing a finding looks like when the system is doing its job. The boxes are roles — who does what — not chronological waiting:

  1. human Hits a third-party-system gotcha while coding with their agent. PyYAML's yaml.load parses permissions: 022 as the integer 18, their script breaks, the agent debugs it with them, the fix lands.
  2. agent Notices the fix concerns a public library, isn't already in team memory, and isn't already in Runlog. Asks the human one short question: "Worth publishing this as a Runlog entry?"
  3. agent Drafts the entry from the conversation it just participated in. Two branches (failed approach + working approach), inputs as placeholders, declared mutations that should break the working branch.
  4. agent Runs runlog-verifier verify locally. The verifier executes both branches against the submitter's Python, applies the mutations, captures the environment fingerprint. If anything fails — tautological test, mutation that doesn't discriminate, missing matcher — the agent reads the typed rejection reason and fixes the draft. Loops until the verifier signs.
  5. agent Submits the signed bundle via runlog_submit. The server checks the signature and the scope rule, sanitizes against the allow-list, stores the entry.
  6. human Sees a one-line confirmation. Goes back to coding.

The human's part is two prompts: the original bug report, and "yes, publish." The cryptographic verification, mutation testing, environment capture, and rejection-loop debugging happen entirely on the agent's side, on the human's existing machine, using runtimes that are already installed because they were already needed to fix the bug.

This flow is the spec for the runlog-author skill, the agent-side authoring tool that compresses submission to those two prompts. It ships in runlog-skills/runlog-author/SKILL.md (Claude Code, Cursor, Cline, Continue, Aider, Copilot, JetBrains, Windsurf, Zed adapters) and drives the Ed25519-signed verifier locally to produce the signed bundle.
Every v0.1 submission lands at status: unverified, signed bundle included. The signed verifier is still the submit-time gate: differential branch execution and mutation testing run locally inside the binary, and the server rejects invalid bundles with typed errors. The engine that promotes entries to verified ships in milestone M05 — weighted usage telemetry plus dependency-manifest correlation. Unsigned submissions land today; once M05 ships, only verifier-signed entries become candidates for promotion. The architecture is end-to-end; the trust-score loop is staged.

What it costs to read vs. to write — honestly

To read (consume verified entries)

That's the entire setup. Total time: under five minutes. Zero local toolchain, zero keys to manage, zero per-query cost.

To write (submit verified findings)

Today this is a real toolchain that a determined contributor can manage; the runlog-author skill collapses it into two prompts and a keypair the skill manages on first use. The verification requirement itself never relaxes — that is the entire product.

The invariant we will not break

Several of the decisions on this page look like they could be loosened "just a little" to make adoption easier. They cannot, and the reason is the same in every case: weakening them turns Runlog into a competitor to team memory, where it would lose. The differentiation is the rigor.

Loosening any one of these to "make submission easier" is a phantom optimization — the easier path leads to a product that isn't worth using. The path forward is to compress the incidental friction (toolchain ergonomics, agent-driven authoring, release artifacts) without touching the structural friction (the verifier itself).

Back to the basics

If you came here from the homepage, the rest of the picture lives there: the complementarity to team memory, the three-tier trust stack, and the MCP surface. This page is just the deeper why for the one piece that matters most.

← Back to the homepage · Register an API key

Notes by Volker Otto. Comments and corrections welcome at runlog@volkerotto.net.