People approve snapshots; agents keep recomputing. Pursuit Permit lets recommendations update without letting permission drift.

The £900k bid now qualifies. The active £750k / 32-hour permit does not change. active_permit_conflict. Zero hours moved.

Inspiration

A browser agent can discover new evidence in the same page where it can propose spending a scarce bid-team slot. The dangerous ambiguity is not ranking. It appears later: does yesterday's approval follow today's newly correct recommendation?

Most approval demos end when approval is granted. Pursuit Permit starts where that becomes dangerous: after the facts change. It is a fixed, synthetic procurement replay of one narrow protocol—recommend, approve an exact revision, issue a bounded permit, and later re-prove the decision without inheriting yesterday's authority.

What it does

The demo gives every judge the same reproducible two-act decision:

  1. Five page-owned WebMCP tools search, compare, shortlist, issue, and retest. The apparent £900,000 winner fails two mandatory gates, so the eligible £750,000 alternative is proposed for the team's only 32-hour bid slot.
  2. issue_pursuit_permit returns structured approval_required. It creates no permit and commits no capacity. The registered tool surface intentionally exposes no approval endpoint.
  3. A visibly separate page checkpoint, labeled NOT AN AGENT TOOL, records an unverified reviewer label against the exact bid, allocation, evidence revision, and decision revision. Approval still commits zero hours.
  4. Only a matching WebMCP retry issues one idempotent, revision-bound permit and changes 32 hours from proposed to committed.
  5. A second page-only demo action revises the synthetic bidder evidence. Both reopening conditions stored in the historical receipt now pass, so the £900,000 bid becomes the better recommendation.
  6. retest_pursuit_permit(receiptId) re-proves the old receipt against the new facts and names the still-active permit the candidate would displace. It creates no new authority.
  7. A forced shortlist fails closed with active_permit_conflict. The original £750,000 permit survives. Zero hours move.

The values, opportunities, evidence, and staffing hours are deterministic demo fixtures—not live procurement data, measured savings, staffing advice, verified identity, or production authorization.

Why WebMCP

This proof cannot live only in chat. The five imperative WebMCP tools and the React interface share one client-side controller. Every call changes the same opportunity rows, evidence panel, shortlist, capacity rail, checkpoint, receipt, and chain-of-custody ledger the reviewer sees.

The built-in proof console exposes all five registered tools, the chronological invocation count, and selected request/response evidence. WebMCP therefore makes the state machine inspectable: an agent can re-evaluate and propose, encounter a machine-readable stop, retry after a visible checkpoint, and later discover that a better recommendation still lacks authority to displace an active permit.

How we built it

Pursuit Permit uses React 19, TypeScript, Vite, strict Zod schemas, and the official webmcp-types package. Motion provides causal rank transitions and checkpoint-to-receipt continuity; NumberFlow handles the changing leader value; Rough Notation marks the defeated pursuit and failed clauses. Locally bundled IBM Plex fonts keep the interface self-contained.

The controller validates every tool boundary and produces immutable state shared by UI and WebMCP. Approval binds the shortlist, allocation, exact evidence content, opportunity details, bidder profile, evidence revision, and decision revision. Idempotency keys cannot replay across revisions, one approval fingerprint can create only one receipt, and relevant state changes invalidate approval. The active permit is stored separately from the new working proposal, so reopened evidence cannot erase or silently replace it.

Challenges we ran into

The first challenge was separating planned, proposed, approved, and committed. Comparison may calculate a 32-hour move; shortlist may propose it; the page checkpoint may record approval. Only permit issuance can change committed capacity.

The second was making retest useful without making it dangerous. New evidence must be allowed to prove that the recommendation changed, but it must not rewrite history or let a reopened tender steal an already committed slot.

The third was visual: the safety property had to be visible in seconds. We used an evidence thread, physical rank reversal, NO-BID stamp, capacity rail, distinct reviewer checkpoint, permit seal, green reopening thread, and a proof-mode flight recorder so the product demonstrates the boundary instead of merely claiming it.

Accomplishments that we're proud of

  • Five discoverable, page-owned WebMCP tools operating on the same state the judge sees.
  • A structured approval_required stop with 0h committed and no exposed approval tool.
  • One exact approved retry that issues a proof-carrying permit and commits 32 demo hours.
  • A historical-receipt retest followed by active_permit_conflict, preserving the active permit and moving 0h.
  • Keyboard-only operation, reduced motion, forced-colors support, focus-managed modal inspection, and 320px reflow.
  • A verified release gate: 129 unit/integration checks, 42 applicable browser checks, 87.55% statement coverage, 80.56% branch coverage, production build, lint, typecheck, and zero dependency-audit vulnerabilities.

What we learned

An agent becomes more useful when its state transitions are narrower than its recommendations. ‘Approved’ and ‘committed’ are not synonyms, and a receipt is most valuable when it can be re-tested without becoming a blank cheque.

What's next

A production version would ingest licensed procurement data, use a permissioned company evidence library, attach source-level provenance, authenticate reviewers, integrate with real staffing systems, and define explicit revocation and supersession rules. Those are roadmap items, not capabilities claimed by this challenge build.

Built With

Share this project:

Updates

Submission history