Seven layers, one direction of flow, and a record of everything.
This page describes how EveryShall is built: the data model, the execution model for agents, how requirements are extracted, how citations are verified, and what the Ledger actually contains. It is written for technical evaluators and for proposal managers who want to know what "auditable" means in practice.
System layers
Data moves downward through the stack. No layer writes to the one above it. Every layer emits Ledger events.
| # | Layer | Responsibility | Key invariants |
|---|---|---|---|
| 1 | Ingestion | Polls configured sources on a schedule using a posted-date cursor per source. Downloads notices and every attachment. Computes SHA-256 of each file. | Idempotent by (source, notice_id, attachment_sha256). Respects each source's published rate limits. Never writes back to a source. |
| 2 | Normalization | Converts PDF, Word, and scanned documents into a page-anchored text model with layout blocks and tables. OCR is applied only to image-only pages and marked as such. | Every text span retains (doc_sha256, page, char_start, char_end). Original files are kept unchanged. |
| 3 | Retrieval index | Chunks firm documents and solicitation text into overlapping passages, embeds them, and stores vectors plus a lexical index per firm. | Indexes are partitioned by firm. A query from one firm's pipeline is physically unable to hit another firm's partition. |
| 4 | Rules engine | Evaluates a firm's go/no-go rules deterministically: NAICS match, set-aside eligibility, value thresholds, geography, excluded terms, required certifications. | Pure function of (rules, opportunity). Same input, same output, no model involved. Hard rules short-circuit before any model call. |
| 5 | Agent runtime | Runs Scout, Fit, Compliance, Drafter, and Reviewer as typed steps in a workflow with per-step retries, timeouts, and schema validation of model output. | A step's output is rejected and retried if it fails its JSON schema. Prompts are versioned and referenced by version in every record. |
| 6 | Ledger | Append-only, hash-chained log of every event per bid: ingestion, rule results, model calls, extracted requirements, sentences, verifications, human edits, exports. | Entries are never updated or deleted. Each entry stores the hash of the previous one. Redaction on deletion replaces payloads, not entries. |
| 7 | Export | Renders the draft to .docx or .pdf with the compliance matrix as an appendix, stamped with the matrix version hash and Ledger sequence number. | An exported file can be matched back to the exact Ledger state that produced it. |
Agents are typed steps, not free-running loops.
Typed input and output
Each agent is a function with a declared input schema and output schema. Model responses are parsed and validated against the output schema before anything downstream sees them. A response that does not validate is discarded and the step retries with the validation error appended to the prompt, up to a fixed limit, then fails loudly.
Deterministic tools
Tools available to an agent are ordinary functions: fetch a document, look up a rule, retrieve passages, write a record. A tool call is logged with its arguments and result hash. Agents cannot call tools outside their declared set, and no agent has a tool that submits anything anywhere.
Versioned prompts and models
Every prompt is a versioned artifact. Every model call records model identifier, prompt version, input token count, output token count, and latency. Changing a prompt creates a new version; old records keep pointing at the version that produced them.
Idempotency and retries
Every step has an idempotency key derived from its inputs. Re-running a workflow after a failure resumes from the last completed step and does not duplicate Ledger entries or model calls.
Isolation
A workflow runs in the context of exactly one firm. Its retrieval queries, rule lookups, and writes are scoped to that firm's partition by construction, not by filtering after the fact.
Budgets
Each step declares a maximum token budget and a maximum wall-clock time. Exceeding either fails the step. Per-firm daily budgets cap total model spend so a malformed solicitation cannot consume the account.
How a 120-page package becomes a matrix
Segmentation
The normalized text is split into sections using the solicitation's own structure where present (uniform contract format sections A through M, or the numbered headings of a state RFP) and heading detection where not. Each section keeps its page range.
Candidate detection
Sentences containing obligation language are selected deterministically: modal verbs (shall, must, will, is required to, are required to), imperative constructions, and enumerated submission instructions. Detection is lexical and rule-based, so it is exhaustive rather than sampled; the model never decides which sentences to look at.
Classification and structuring
Each candidate is passed to the large model with its surrounding context and returned as a structured requirement record: verbatim text, modal, category (format, deadline, form, staffing, past performance, technical, evaluation, pricing, other), due kind, and the source span. The verbatim text is checked byte-for-byte against the source span; a mismatch rejects the record.
Deduplication and linking
Requirements repeated across sections (common between instructions and evaluation criteria) are linked, not merged, so the matrix shows both locations. Cross-references ("see Section L.4") are resolved to requirement IDs where the target can be found.
Matrix versioning
The set of requirement records for a bid is hashed to produce a matrix version. Any change (a human adding a missed requirement, an amendment to the solicitation) produces a new version. Drafts and exports reference the version they were checked against.
Requirement record, abbreviated
{
"id": "req_01J9K3...",
"opportunity_id": "opp_01J9K2...",
"ref": "L-1",
"text": "Offeror shall submit a technical volume not exceeding 15 pages, 12-point font, single-spaced.",
"modal": "shall",
"category": "format",
"source": { "doc_sha256": "3f9a...c1", "page": 42, "char_start": 1180, "char_end": 1274 },
"due": { "kind": "with_proposal" },
"extracted_by": { "model": "large-v?", "prompt_version": "extract@2026-09-08", "run_id": "run_01J9K4..." },
"status": "open"
}A sentence is either supported, or it is flagged.
Retrieval-grounded drafting
For each requirement or section, Drafter retrieves candidate passages from the firm's documents (hybrid lexical and vector search, re-ranked) and the solicitation. The model is instructed to write only from the supplied passages and to attach, per sentence, the passage identifiers it used.
Span-level citations
A citation is not "document X". It is (document hash, page, character range). The cited span is stored with the sentence, so the reader can open the exact text the sentence rests on.
Independent verification pass
Reviewer re-checks every sentence in a separate model call that sees only the sentence and its cited spans, and returns supported, partially supported, or unsupported. The drafting model's own citations are treated as claims, not facts.
Flags are visible, not silent
Unsupported and partially supported sentences are rendered with a visible flag in the editor and listed in the review report. They are never removed automatically, because the human may have the missing source. They cannot be exported without an explicit per-sentence acknowledgement.
Requirement coverage
Each sentence declares which requirement IDs it addresses. Reviewer computes coverage: requirements with no addressing sentence are listed as gaps; sections exceeding declared page limits are listed as violations, using the export renderer's own page count.
Numbers and names
Numeric values, dates, names, and contract identifiers in a sentence are cross-checked against the cited span with exact-match rules before the model-based verification runs. A number that does not appear in its cited source is an automatic flag.
Sentence record, abbreviated
{
"id": "sen_01J9K7...",
"section_id": "sec_2_1_past_performance",
"text": "For the State Department of Labor we designed and ran a twelve-module supervisor curriculum for 340 staff across six sites.",
"citations": [
{ "doc_id": "doc_pp_2024_03", "doc_sha256": "a71e...9d", "page": 1, "char_start": 210, "char_end": 402 }
],
"verification": { "verdict": "supported", "method": "span_entailment", "model": "large-v?", "prompt_version": "verify@2026-09-08" },
"addresses": ["req_L-2"],
"human_edits": 0
}Hard rules first, then a scored explanation.
Rule language
Go/no-go rules are stored as structured conditions over opportunity fields: NAICS in set, set-aside in set, estimated value within range, place of performance in set, required certifications subset of held certifications, excluded keywords absent. Rules are evaluated by the rules engine without a model.
Soft scoring
Opportunities that pass hard rules are scored by the small model against the firm's capability statement and past performance passages, on fixed dimensions: scope similarity, past-performance match, staffing feasibility, and effort. Each dimension returns a score and a two-sentence reason citing the passages used.
Explanations are records
The score and reasons are stored as a record and shown in full. The owner's go or no-go decision is stored alongside, so the system accumulates labeled outcomes for later calibration.
What it does not do
Fit does not predict win probability. There is no historical win data to train on yet, and we will not display a number we cannot back.
Append-only, hash-chained, exportable.
Structure
One Ledger per bid. Entries are sequenced, timestamped, attributed to an actor (agent with version, or a named human), typed by event, and carry a payload. Each entry stores the hash of the previous entry and its own hash over (seq, at, actor, event, payload, prev_hash).
Tamper evidence
Because each hash covers the previous one, altering or removing any entry breaks the chain from that point forward. The chain can be re-verified on demand, and the head hash is included in every export stamp.
Event types
source.polled, attachment.fetched, document.normalized, rule.evaluated, fit.scored, decision.recorded, requirement.extracted, matrix.versioned, passage.retrieved, sentence.drafted, sentence.verified, sentence.flagged, sentence.edited, coverage.computed, export.rendered.
Export and deletion
A firm can export any bid's Ledger as JSON. On deletion requests, payloads that contain firm content are replaced with a redaction marker and the entry is re-hashed into a documented redaction chain, so the sequence and structure of events survive while the content does not.
Ledger entry, abbreviated
{
"seq": 148,
"bid_id": "bid_01J9K1...",
"at": "2026-09-08T14:03:11.402Z",
"actor": { "type": "agent", "name": "reviewer", "version": "0.4.1" },
"event": "sentence.flagged",
"payload": { "sentence_id": "sen_01J9K8...", "reason": "no_supporting_span" },
"prev_hash": "5d2c...e0",
"hash": "9b0f...47"
}Core entities
| Entity | Key fields | Notes |
|---|---|---|
| Firm | id, legal name, identifiers (UEI, CAGE, state vendor IDs), NAICS set, set-aside statuses, certifications, territories | Partition root for all other entities. |
| Rule | id, firm_id, condition tree, action (go, no-go, review), version | Evaluated deterministically. Versioned; old evaluations keep their rule version. |
| Firm document | id, firm_id, sha256, type (capability, past performance, resume, certification, prior proposal), pages, normalized text | Original bytes kept immutable; text model derived. |
| Opportunity | id, source, notice_id, posted_at, response_due_at, agency, NAICS, set-aside, value estimate, attachments[] | Deduplicated across sources by (source, notice_id). |
| Bid | id, firm_id, opportunity_id, decision, matrix_version, ledger_head | Created on a go decision. |
| Requirement | id, bid_id, ref, verbatim text, modal, category, source span, due, status, links[] | Verbatim text validated against source span. |
| Section / Sentence | id, bid_id, order, text, citations[], verification, addresses[], edit history | Sentence is the unit of citation and verification. |
| Ledger entry | seq, bid_id, at, actor, event, payload, prev_hash, hash | Append-only. |
| Export | id, bid_id, format, matrix_version, ledger_seq, ledger_head, file sha256 | Stamp embedded in the document footer and metadata. |
Sources and cadence
Polling
Each source connector keeps a cursor on the source's own posted or modified timestamp and requests only records newer than the cursor. Poll frequency is set per source to stay inside its published rate limit with headroom. Attachments are fetched once and deduplicated by hash.
Amendments
When a source publishes an amendment, the opportunity record is versioned, changed attachments are re-normalized, and any open bid on that opportunity gets a new matrix version with a diff of added, removed, and changed requirements.
Connector policy
Connectors use published APIs or feeds where they exist. Sources whose terms prohibit automated access are not connected. Each connector is listed on the Platform page only after it has run against live postings.
Document formats
PDF (text and image-only), Word, and plain text. Spreadsheets in attachments are extracted as tables. Image-only pages are OCR'd and flagged so that citations to them carry an OCR marker.
Ask the hard questions on the first call.
Bring a live solicitation and a technical reviewer. We will walk through the matrix, the citations, and the Ledger for it.