Skip to content
Little Lab Rats home
Requirements engineering

What limits an AI build is the brief.

What decides whether an AI-assisted build lands is whether the work was specified well enough to hand over. Specification is a gathering problem before it is a prompting one. This page sets out how we gather, what comes out of a pass, and where we can read from today.

Artefacts per pass
9, from one run
Written for people
8 of the 9
Reviewers
2, different model families
Reading from today
Google Workspace
The one-shot argument

One prompt fails in four ways

The model is strong enough. A frontier model handed the whole meeting, the whole thread and the whole spreadsheet will return something impressively coherent. What fails is the shape of a single answer, and it fails structurally, in four distinct ways.

  1. 01

    Gaps come back as confident prose

    Ask a model to specify something the sources never settled and it will specify it anyway, fluently, in the same confident register as the parts it did know. Nothing in the output marks the join.

    This is the artefact that a one-shot prompt structurally cannot produce. A model asked to fill a gap will fill it, confidently, and you will not be told it did.

    What a pass does instead

    A requirements pass writes the gap down instead. Every unanswered thing becomes a question addressed to a named party and marked blocking or carried, so the decision to guess is yours to make in the open.

    open_questions[]
  2. 02

    Claims arrive without a source

    One prose answer carries no provenance per claim. Six months later, when somebody asks why the system behaves this way, all you have is a paragraph that cannot tell you which sentence came from the client and which the model supplied.

    What a pass does instead

    Requirements come out typed and individually identified, each with a confidence score and a link back to the document the line was extracted from. A behaviour is either traceable to a source or it is an open question.

    requirements[]
  3. 03

    One answer, and no reviewer behind it

    A single response has no reviewer standing behind it that can return block. The only check available is whether the answer reads well, which is the one test a fluent model is guaranteed to pass.

    What a pass does instead

    Two reviewer agents on different model families return pass, warn or block on everything the writing agents produced, and a block stops the package rather than filing advice for someone to weigh up later.

    review_block
  4. 04

    Each run replaces the last

    Change one input and the whole answer shifts. There is no version two to hold against version one, so nobody can review what changed. They can only read the new text and hope they notice.

    What a pass does instead

    A schema-validated artefact set keeps its shape while its contents change, which is what makes two runs comparable. You review the difference rather than re-reading the document.

    context-package.schema.json

What replaces the single prompt is a pass: 9 artefacts, the documents and data files listed below, of which 1 is written for machines and 8 are written for people.

What you get

9 artefacts from one requirements pass

Format is the boring distinction between these. Audience is the useful one: one document exists purely for a machine to consume, and the rest exist because a person has to read, argue with, and eventually sign them.

For people5For both3For agents1

Only 1 of the 9 is written for a machine: the context package, which downstream agents consume and no human ever reads for pleasure. The other 8 are the reason the pass is worth doing at all. They are what a client signs, what an argument about scope is settled against, and what somebody inherits when the original team has moved on. Choose any one of them to see real output, down to the identifiers.

Requirements register01 / 09
model: LLM
  • FR-00194%

    Operators receive a low-stock alert within 5 minutes

  • FR-00289%

    Alerts group by supplier so one order covers many parts

  • NFR-00181%

    95% of alerts under 500ms at 10k SKUs

  • CON-00177%

    Must run against the existing MySQL replica, read-only

  • OQ-00142%

    Does the threshold differ per warehouse?

What it costs to skip each one

The honest argument for a document is what goes wrong in its absence. This is that list.

Requirements register
Without it, the requirement exists only in whoever was in the room. Six months on, nobody can say whether a behaviour was asked for or assumed.
Specification
Without it, each agent re-derives the intent from the ticket title and they disagree in ways nobody notices until integration.
Work breakdown
Without it, an estimate is a guess about a whole feature. Sizing per item is what makes the total defensible, because you can argue with any one line of it.
Scope decisions
Without the reasoning, scope arguments restart every month with no memory of what was already settled or why.
Test plan
Without them, 'done' is decided after the fact by whoever wrote the code, which is the one person who cannot judge it.
Review gate
Without an explicit verdict, review is a suggestion. The gate is what makes it a decision with a consequence.
Question sheet
This is the artefact that a one-shot prompt structurally cannot produce. A model asked to fill a gap will fill it, confidently, and you will not be told it did.
Machine context package
Without a validated contract at the boundary, a malformed handoff fails three stages downstream where the cause is no longer visible.
Delivery roadmap
Everyone asks the same three questions: how long, how much, in what order. A stack of correctly sized work items is what makes them answerable, and this is where they get answered.
Where it reads from

Google Workspace today. Microsoft 365 next.

Everything else on this page is planned, and that sentence belongs at the top rather than in a footnote. A visitor who discovers the limitation after signing is a much worse outcome than one who reads it here and calls anyway.

Slack and Jira are live too, though they are where a run starts and where it reports back rather than places we read requirements from. Everything we actually read requirements from today is Google Workspace, behind a single sign-in you approve once.

Where a connector shows a monospace value, that is the source_type the pipeline records against anything it reads from there. It is also why a new family is not a weekend job: the value is pinned to a fixed list that every downstream contract validates against.

Live
Runs in production today, and its source type is on the fixed list the pipeline validates against.Google Workspace, Trigger and sink
In build
Underway. The schema revision it needs fans out through every downstream contract, which is why it is a project rather than a plugin.Microsoft 365
Planned
Wanted and scoped, not started. Listed so the gap is visible rather than implied.Microsoft 365, Wikis and trackers

Google Workspace

One sign-in approval covers the whole family. This is what runs in production today.

  • Google DocsLive
    google_doc

    Specs, notes, and memos, including comment threads.

  • GmailLive
    gmail_thread

    Whole threads, so a decision keeps the argument that produced it.

  • Google MeetLive
    google_meet

    Meeting transcripts, attributed per speaker.

  • Google DriveLive
    drive_file

    Attachments and files that are not native Google documents.

  • Google SheetsLive
    google_sheet

    Requirement registers and trackers kept as spreadsheets.

  • Google SlidesLive
    google_slide

    Decks, where the scope decision is often the only written record.

Trigger and sink

Not requirement sources. This is where a run starts and where it reports back.

  • SlackLive

    The one command that starts a run, and the channel it answers in.

  • JiraLive

    Ticket created on handoff, transitioned on deploy.

Microsoft 365

Next, and the largest single gap. Requires a schema revision that fans out across every downstream contract, which is why it is a project rather than a plugin.

  • SharePoint & OneDriveIn build

    Document libraries, the usual home of the real specification.

  • OutlookIn build

    Mail threads, matching the Gmail behaviour.

  • TeamsPlanned

    Channel history and meeting transcripts.

Wikis and trackers

Wanted, scoped, not started. Listed here so the gap is visible rather than implied.

  • ConfluencePlanned

    Space and page trees.

  • NotionPlanned

    Databases and pages.

  • Azure DevOps & GitHub IssuesPlanned

    Existing backlogs, read as prior art rather than as requirements.

  • S3 & Azure BlobPlanned

    Document dumps from a system that no longer has an owner.

Evidence and confidence

Every requirement arrives with its own evidence

Extraction returns rows rather than a paragraph: each one typed, each one scored, each one pointing back at the document it came from.

FR
Functional requirement

Something the system has to do.

NFR
Non-functional requirement

How well it has to do it, stated as a number where one exists.

CON
Constraint

Something the solution is not free to choose.

OQ
Open question

Not a requirement at all, but the recorded absence of one.

The score beside each row is the extractor reporting its own certainty, not a rating of how good the requirement is. It earns its place by making one thing possible: a row the model is unsure about becomes an open question addressed to whoever can settle it, rather than a confident requirement. In the register here, the lowest-scoring row is exactly that: OQ-001, which asks rather than asserts.

Each row also carries a link back to the source document. That link is what makes a requirement arguable a year later: you can go and read the sentence it was drawn from, and decide whether the reading was fair.

Requirements registerrequirements[]
model: LLM
  • FR-00194%

    Operators receive a low-stock alert within 5 minutes

  • FR-00289%

    Alerts group by supplier so one order covers many parts

  • NFR-00181%

    95% of alerts under 500ms at 10k SKUs

  • CON-00177%

    Must run against the existing MySQL replica, read-only

  • OQ-00142%

    Does the threshold differ per warehouse?

Two readers, one row

The same requirement, read two ways

A requirement has to survive two readers who want opposite things from it. The engineer needs it unambiguous enough to implement and to test. The person approving the spend needs to know what it costs, when it lands, and what happens if it does not. Most documents serve one of them and irritate the other.

The developer’s reading

Tokenise card details at the edge

Swap the raw PAN for a provider token before the request reaches application code.

given
a checkout request carrying a raw card number
when
the request passes the edge tokeniser
then
application code receives a token and never the number

That triple is the executable test case, written before any implementation exists to bias it. It is also the whole specification: there is nothing else to interpret.

The business reading
mustpriority: critical

Handling a raw PAN anywhere in our estate would put the whole platform in PCI scope.

Effort
4.0 h
Scheduled
2026-09
In plans
All three

Every plan includes this one, and the sentence above is why. Its trace back to the meeting is act-card-001.

Both readers are looking at the same row, projected two ways and generated in the same pass, which is what stops them drifting apart the way a specification and the slide summarising it always do.

The right-hand panel is also the part that is usually missing. A justification written at extraction time is worth more than one reconstructed in a budget meeting six weeks later, because at extraction time somebody still remembers why the sentence was said. Here the reason survives in the words of the person who gave it: a raw card number anywhere in the estate would drag the whole platform into payment-card compliance.

The review gate

A verdict that can stop the work

Four agents write. Two only review, on different model families, and they return pass, warn or block. A block stops the package rather than filing advice for somebody to weigh up later.

pass moves on. warn moves on and takes its findings with it, so the next reader sees what the reviewer was unhappy about. block withholds the handoff. That third state is the whole point: without a verdict that has a consequence, review is a suggestion.

The reviewers run on different model families, and that is a design decision rather than a procurement accident. Two instances of the same model share the same training and the same failure modes, so when they agree, the agreement carries almost no information: the second run is likely to have missed whatever the first one missed. Reviewers from different families disagree in useful places, and the disagreement is the signal worth paying for.

In the run shown here the verdict is warn: two findings, neither of them blocking, both travelling with the package rather than being filed away. The package proceeds, and the next person to open it knows exactly what was flagged.

Review gatereview_block
  • warnA5 spec reviewer2 findings, none blocking
  • passA6 independent reviewerdeterminism check clean
  • passSchema validationcontext-package.schema.json
  • warnGate verdictwarn: proceeds, findings carried

This is document one of three.

The package that settles what to build is the same package a roadmap is scheduled from and a proposal is priced from. Work sized one item at a time becomes hours, hours against capacity become months, and months against a rate card become a figure somebody can sign. Change an input and all three move together.

Or send us one real requirement and we will run it: hello@littlelabrats.com