VenueCompliant

Documents that have to survive being questioned

The paid product generates the four written procedures Martyn’s Law requires. Those documents are a venue’s evidence that it did what the Act asks, so the problem was never producing good prose — it was producing prose that can be traced, reproduced and recalled. That decided nearly every architectural choice, including a refusal to put a language model anywhere near it.

  • TypeScript
  • Next.js
  • Postgres
  • PDF & DOCX generation
01

The output is evidence, not content

A standard-tier premises has to put four procedures in writing — evacuation, invacuation, lockdown and communication — and make sure its staff can actually carry them out. The person who signs them is the responsible person under the Act, and it is their name on it, not ours. If anyone ever asks why their lockdown procedure says what it says, “the tool generated it” is not an answer they can give.

So every block in the library carries the source it came from, and a block without one fails to load rather than logging a warning. The citation travels with the sentence instead of sitting in a bibliography that somebody has to reconcile against the text later.

id: EVAC-OVERNIGHT-01
applies_when:
  all: [overnight_accommodation]
requires_vars: [assembly_point]
source: "Terrorism (Protection of Premises) Act 2025, s.5(3)(a); …"
version: 1
02

Fifteen venue types is not fifteen libraries

The checker recognises fifteen kinds of venue, from nightclubs to village halls to places of worship. The obvious way to generate their documents is to write fifteen sets of procedures — which is fifteen libraries to keep in step every time the guidance moves, and it encodes the wrong idea about what separates them in the first place.

Notchurch-ness or hotel-ness — the visible axis, and the wrong one
Butovernight_accommodation · volunteer_staff · limited_mobility_occupants
What actually differs between a church’s evacuation procedure and a hotel’s

Blocks declare the attributes they apply under and a venue receives the ones that match its profile. Ten attribute keys cover all fifteen types, and venue type survives only as a default profile the customer can correct — because a church hall that hosts a sleepover genuinely needs the overnight block, and no amount of routing by venue type would ever have handed it one.

The questionnaire then falls out of the same declarations. Each block names the variables its text needs, and the questions asked are the union of those across the blocks that actually apply. It is not possible to ask a venue for an assembly point it will never be shown, or to render a document around a variable nobody was asked for.

The safety net is a snapshot of the composed output for each of the fifteen types. Editing one block shows exactly which venue types it moved — including the ones that were not being thought about, which is the entire reason a shared library is safe to have.

03

No model in the part where one would be most impressive

Generation is deterministic: the same answers produce identical output. Nothing in the engine reads the clock — the generation timestamp is a parameter — nothing is random, and nothing depends on object key order.

Two things follow from that. A trust running twenty-five schools gets twenty-five consistent documents rather than twenty-five subtly different ones. And any customer’s exact document can be reproduced from their stored answers months after it was issued, which is what makes it evidence rather than a file they happen to hold.

Which rules out generating the prose with a language model — the one part of this product where reaching for one would be most tempting, and would demo best. These documents tell people what to do during a terrorist attack. Every sentence that reaches a customer has been written and reviewed by a human, because output nobody can reproduce is output nobody can stand behind when asked where a particular instruction came from.

There is a language model in the product — it drafts replies to inbound enquiries, internally, for a person to read before anything is sent. The question was never whether to use one. It was where the boundary goes, and on which side of it a human sits.

04

Which is what makes a recall possible

Every generated document stores a manifest of the blocks that produced it and the version each one was at. A daily sweep compares those manifests against the current library and flags any organisation holding a document that has fallen behind.

It was built for the ordinary case — guidance moves, a block is rewritten, its version is bumped. It is also what stands behind the promise to reissue documents free of charge when that happens. Nobody has to remember who bought what, because the documents remember what they were made of.

A recall mechanism that has never fired is a belief rather than a capability, so the test is to bump a block version in a test environment and watch the right organisation get flagged. Reading the sweep and finding it convincing is a different act from seeing it name somebody.

05

What holds regardless

  • Work out what the output has to survive before choosing how to produce it. Here it had to survive being questioned years later, which disqualified the fastest way to build almost every part of it.
  • Find the axis the variation genuinely runs along. Fifteen venue types was the visible dimension; ten attributes covered the same ground in a library small enough to keep correct.
  • Derive rather than maintain alongside. The questions asked, the contents of a document and the list of customers affected by a change are all computed from the blocks — none of them is a second list somebody has to remember to update.
  • Decide where a model’s output is allowed to reach a person unreviewed. That is a boundary you draw once, deliberately, not a question you answer per feature.