DEV Community

Charlie Hu
Charlie Hu

Posted on

A Source-Locked Claim Gate for a One-Path Weekend Demo

A weekend side project should refuse to print a number it cannot point at. That is the conclusion, and the rest of this log is the cut that makes the conclusion enforceable. A longer prompt does not hold the line. A local allowlist does.

The working demo is deliberately small. It reads one markdown note, checks every detected number and link against a hand-edited allowlist, and writes a JSON receipt. If the receipt is not clean, the note does not ship. Optional static hosting comes after that check, not before it.

Why this cut, this weekend

Agent demos fail in a specific way. The prose sounds finished, then a quota, a latency figure, or a documentation link appears that nobody opened. The failure is not mystical. It is an untracked claim.

Public developer discussion has spent energy on retries, agreeable models, and the gap between model progress and ordinary software discipline. Those threads are context, not a source of figures for this log. No statistic from a third-party post is repeated here. The engineering move is local: treat unsourced numbers as build errors.

This account's recent notes already covered attempt caps, fixture locks, read-only routes, and status cards. The missing piece is the claim itself. A frozen fixture can still contain a made-up capacity line. The gate below targets that line, and nothing wider.

Scope that fits in a weekend

Four artifacts and one command define the path. The checker does not import an SDK. The hot path does not open a socket.

Files that stay

  • notes/demo.md holds the only prose the demo is allowed to show.
  • claims/allowlist.toml holds the only numbers, phrases, and URLs the prose may repeat.
  • gate_claims.py is a local checker with a boring exit code.
  • receipts/latest.json is the pass or fail record a reviewer can diff.

Work that does not get built

The skip list is part of the design, not a backlog apology.

  1. No automatic retry after a red receipt.
  2. No write tool pointed at the repository.
  3. No multi-model comparison and no named-model bake-off.
  4. No token meter and no cost chart.
  5. No account system on the optional host.
  6. No live search inside the demo process.

A side project that implements that list stops being a weekend demo. The cut keeps the path teachable, and it keeps a bad figure from hiding inside extra machinery.

Hand-write the allowlist first

Suggestions can arrive later. Authority starts in a file a human can read without a model session. The shape below is a proposal, not a verified product sheet.

# claims/allowlist.toml
# Unexecuted proposal. Rows show file shape, not measured product facts.

[[claim]]
kind = "phrase"
text = "free model access"
source = "operator-supplied availability note, re-check before publish"

[[claim]]
kind = "phrase"
text = "free server option"
source = "operator-supplied availability note, re-check before publish"

[[claim]]
kind = "url"
text = "https://dev.to/devlab_1905"
source = "this account home, open once on publish day"
Enter fullscreen mode Exit fullscreen mode

A token allotment does not belong in the example. Neither does a server size, a region, or a promise that an offer lasts. If a primary page is checked on demo day and a human adds a sourced row, the gate can allow that exact text. Until then, the prose must not invent it.

Proposed checker

The program below is a proposal. It is labeled unexecuted. It is not a benchmark, and it is not a claim that this account ran it on 2026-10-13.

#!/usr/bin/env python3
"""Fail markdown that prints numbers or links missing from an allowlist.

Proposal only. Not a recorded test run.
"""

from __future__ import annotations

import json
import re
import sys
from pathlib import Path

NUM = re.compile(r"\b\d[\d,]*(?:\.\d+)?%?\b")
URL = re.compile(r"https?://[^\s)]+")
BANNED = ("forever", "unlimited", "fastest", "guaranteed")


def load_allowlist(path: Path) -> set[str]:
    allowed: set[str] = set()
    for raw in path.read_text(encoding="utf-8").splitlines():
        line = raw.strip()
        if line.startswith("text = "):
            value = line.split("=", 1)[1].strip().strip('"')
            allowed.add(value)
    return allowed


def gate(markdown: str, allowed: set[str]) -> dict:
    failures = []
    lowered_allowed = {item.lower() for item in allowed}
    for word in BANNED:
        if word in markdown.lower() and word not in lowered_allowed:
            failures.append({"kind": "wording", "text": word})
    for match in NUM.findall(markdown):
        if match not in allowed:
            failures.append({"kind": "number", "text": match})
    for match in URL.findall(markdown):
        if match not in allowed:
            failures.append({"kind": "url", "text": match})
    return {
        "ok": not failures,
        "failure_count": len(failures),
        "failures": failures,
    }


def main() -> int:
    if len(sys.argv) != 3:
        print("usage: gate_claims.py NOTE.md ALLOWLIST.toml", file=sys.stderr)
        return 2
    note = Path(sys.argv[1]).read_text(encoding="utf-8")
    allowed = load_allowlist(Path(sys.argv[2]))
    receipt = gate(note, allowed)
    out = Path("receipts")
    out.mkdir(exist_ok=True)
    (out / "latest.json").write_text(
        json.dumps(receipt, indent=2) + "\n",
        encoding="utf-8",
    )
    print(json.dumps(receipt, indent=2))
    return 0 if receipt["ok"] else 1


if __name__ == "__main__":
    raise SystemExit(main())
Enter fullscreen mode Exit fullscreen mode

Run it from the demo root after the two input files exist.

mkdir -p receipts notes claims
python3 gate_claims.py notes/demo.md claims/allowlist.toml
echo "exit=$?"
Enter fullscreen mode Exit fullscreen mode

Exit code 0 means the detected claims were already allowlisted. Exit code 1 means the note stays unpublished. Exit code 2 means the command was called wrong. The receipt file is the review object. A model transcript is not.

Two notes, two expected receipts

These fixtures are specifications for a later run. They are not recorded outputs.

Passing note

This demo reads one local note and writes a receipt.
It may mention free model access only as an operator-supplied option.
Enter fullscreen mode Exit fullscreen mode

That note has no bare number and no URL. The checker should return ok: true when the phrase row exists and the banned-word list stays quiet. The sample script does not yet prove that an allowlisted phrase occurs in the note. That gap is intentional. A weekend can ship the failure mode first, then add a presence check only if a real run shows a need.

Failing note

The free tier includes 8192 tokens and stays unlimited.
Docs live at https://example.com/pricing.
Enter fullscreen mode Exit fullscreen mode

Expected failures include the number 8192, the word unlimited, and the unlisted URL. The demo stops. Nobody repairs it by asking for another draft. The human deletes the sentences, or replaces them with sourced rows after opening a primary page on the same day.

Decision table

Signal in the note Result Next edit
Number absent from text rows Fail Remove it, or add a row whose source was opened that day
URL absent from text rows Fail Drop the link
Banned wording such as unlimited Fail Use a dated check instead of a permanence claim
Allowlisted operator phrase, no new number Pass Keep a single plain mention
Step index such as a digit in a list Often fail Spell the step, or allowlist the digit as a structural index
Image-only claim Not detected Do not use images for figures in this demo

The last two rows are why the gate is a lock for a side project, not a general truth machine. Lists that need digits should be rewritten, or the digits should be added as explicit rows with source structural index, not a product fact.

One model pass, after the file exists

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

MonkeyCode is relevant only after claims/allowlist.toml exists. The operator describes it as an open-source project and states that free model access and a free server option are available. This log does not add model names, quotas, hardware, regions, or a duration. Those details were not verified against a primary source for 2026-10-13, and an unverified figure would fail the gate this article is arguing for.

Use free model access for one classification pass on the note. Ask for labels only: plain, numeric, or needs-source. Paste the labels beside the note in a scratch file. Merge nothing automatically. If the labels are wrong, shrink the note. A second call is a skip, not a remedy.

Use the free server option, if it is still offered when the receipt is green, as a static file host for receipts/latest.json and a single HTML page. The page may print ok and failure_count. It gets no form, no upload, and no proxy to a model endpoint. If that option is down, or the terms differ from what was assumed, skip hosting. The local command remains the demo either way.

Readers comparing this cut with their own side project can confirm the repository license and the current free-access terms, then run the checker against one note they already trust. A local red receipt is a better introduction than a hosted tour.

Static page, still optional

A few lines of HTML are enough for a reviewer who wants the receipt visible. They load JSON only when both files sit on the same origin. This snippet is also a proposal, not a deployed site.

<pre id="out">receipt not loaded</pre>
<script>
fetch("./latest.json")
  .then((res) => res.json())
  .then((data) => {
    document.getElementById("out").textContent = JSON.stringify(data, null, 2);
  })
  .catch(() => {
    document.getElementById("out").textContent = "local receipt missing";
  });
</script>
Enter fullscreen mode Exit fullscreen mode

That page teaches the receipt shape. It does not teach product capacity. Leaving it offline is a valid weekend outcome, and it should be the default if the host terms were not re-read that day.

Test plan before anyone treats the script as done

No run is claimed here. A reviewer would still want a fixed sequence before trusting the exit code.

Sequence

  1. Empty-claim note. Expect ok: true and failure_count: 0.
  2. Note containing 8192. Expect a number failure and exit 1.
  3. Note containing an unlisted URL. Expect a URL failure.
  4. Note containing guaranteed. Expect a wording failure.
  5. Note whose only URL is copied exactly from an allowlist row. Expect that URL not to fail.
  6. Run the same command with the network interface disabled. Expect an identical receipt, because the checker should not dial out.
  7. Point the command at a missing file. Expect a traceback or a usage error, then decide whether a cleaner message is worth a later weekend. It is not required for this cut.

Record the seven results in the receipt directory only after a real run. Until then, the plan and the script stay labeled as proposals. A green reading invented in the write-up would be the same class of defect the gate exists to catch.

Who should walk away

The regex misses spelled-out numbers and claims split across markup. A determined draft can smuggle a figure in an image or in HTML entities. The sample loader is a line scan, not a TOML parser, so a wrapped string can fool it. Those are reasons to keep the input small, not reasons to trust the script on a large corpus.

Do not use this path for pricing pages, incident reports, security advisories, medical text, or legal text. Do not use it as evidence in a launch review. Do not point a write-capable agent at the allowlist and call the result independent.

People who need signed provenance, citation graphs, or policy approval need a different system. People who want a model to retry until the exit code turns green are outside the cut. The red receipt is the feature that retry loop would automate away.

What shipped, on paper

The weekend artifact is a scope decision plus a proposed command. One note in. One allowlist. One receipt out. Hosting is a trailing option tied to a free server offer that must be re-read before use. Free model access, if still available, may label sentences once. It does not get to mint numbers.

That is a build log, not a product announcement. The demo is finished when an unsourced figure cannot pass, even if the optional page never goes up.

Top comments (0)