Specifications

The rules, written down and executed

Each area of Saybooks is governed by a written spec: the acts it must support, the invariants it must keep, and scenario files that replay real sequences of acts, refusals included, through the actual command registry. A module that claims an area must map every act and pass every scenario; the contract test fails the build otherwise. The specs speak in acts, not commands, so a competing implementation can be certified by the same files.

bridge — The Ledger Bridge · Area SpecificationThe hand-over to the accountant: map their chart once, export a period as QuickBooks Online or Xero journal lines, keep what went and when; and preliminary financials before the close.
bridge@0.3 · 6 acts · 4 scenarios · conformant
crm — Relationship Pursuit · Area SpecificationRelationship pursuit: campaigns with a goal, accounts that earned their place, contacts with sources or recorded as gaps, drafts the agent writes and a person sends, events with the page their date came from.
crm@0.5 · 26 acts · 7 scenarios · conformant
jobhunt — One Person's Search · Area SpecificationA job search as a system of record: postings, applications, interviews, recruiters, a duplicate guard, and one next action per pursuit.
jobhunt@0.1 · 18 acts · 3 scenarios · conformant
o2c — Order to Cash · Area SpecificationQuotes, orders, shipments, invoices, receivables and credit: the order-to-cash cycle of a small business, with a credit gate the agent cannot talk past.
o2c@0.2 · 26 acts · 10 scenarios · conformant
p2p — Procure to Pay · Area SpecificationProcure-to-pay, specified ahead of any implementation: purchase orders, receipts against them, supplier invoices matched three ways, payment runs.
p2p@0.1-draft · 21 acts · 0 scenarios · no run yet
Prospect stagingThe holding area in front of the CRM: bought or scraped rows the agent stages and judges, that only a person promotes.
prospect@0.1 · 6 acts · 3 scenarios · conformant
purchases — What You Buy · Area SpecificationBank and card statements and receipts the agent read: rows with provenance, accepted whole or not at all, reviewed in the person's own words; standing rules that suggest, subscriptions and spend, and bills only a person approves paying.
purchases@0.5 · 30 acts · 9 scenarios · conformant
solo — Freelancer Invoicing · Area SpecificationA freelancer's invoicing: numbered invoices with a link and a PDF, any currency, your tax scheme, payments and what is still open, and reminders for overdue ones that the person sends. Issued means issued.
solo@0.3 · 14 acts · 6 scenarios · conformant

Every invariant, in one place

120 rules across 8 areas. Each is one sentence, enforced at the one place every command passes through, and shown identically to a person and to an agent when it refuses. The area pages hold the acts, the scenarios and the last conformance run.

bridge — The Ledger Bridge · Area Specification

IdInvariant
B-1The journal is a derivation, never a posting: an export reads it and changes nothing.
B-2Money is integer minor units; every export balances, per entry and in total.
B-3One currency per hand-over; a period holding more than one is refused until a currency is named.
B-4An export is refused while an account the period uses lacks the mapping the format needs, naming it.
B-5Every hand-over records format, period, counts, control totals, a hash and the actor, and keeps the exact file.
B-6Omitting the period start continues from the last hand-over in that format.
B-7Re-exporting a period already sent is allowed and always visible, naming the earlier hand-over.
B-8The chart is theirs: codes and names come from the accountant, never invented.
B-9Every write is a logged act with an actor; refusals are logged too.
B-10Spending posts against the account it was paid from; a transfer posts nothing, so money already recorded elsewhere is never counted twice.
B-11An unreviewed row posts nothing and is reported as left out, in the preview and on the hand-over.
B-12Preliminary statements are derived on request and never stored, balance by construction from the statements' printed openings, say whether each statement account ties, and name on their face what they leave out.

crm — Relationship Pursuit · Area Specification

IdInvariant
CRM-1Never invent a person: named contacts require a source; facts come only from sources.
CRM-2A gap is a finding: recorded with a note, listed in the worklist, resolved only with provenance.
CRM-3Every account earned its place: why_them and source_url are mandatory.
CRM-4Relationship-graph fields are human-only: refused to agents regardless of role.
CRM-5Activities record when it happened, not when it was typed.
CRM-6Nothing is deleted: exclusion and closure are reasoned statuses.
CRM-7Parking or killing an account requires a reason.
CRM-8Promotion is a bridge act: won → core customer via the owner's API, at most once.
CRM-9Provenance survives updates: correctable, never removable.
CRM-10Interpretation is free; facts are sourced.
CRM-11Every write is a logged command with an actor; refusals are logged; reads are not.
CRM-12Every account pursues a campaign; pursuit state is campaign-relative.
CRM-13No campaign without a goal — the goal is the brief agents read before filling the list.
CRM-14There is no outbound channel: a draft is written and held; only a person sends it.
CRM-15A sent draft is immutable and its exact words are copied onto the activity trail; a discarded draft is never revived.
CRM-16Every draft carries a rationale for its reviewer, and the rationale is never part of what is sent.
CRM-17What a campaign may claim is written by a person; refused words are checked against every draft and edit alike.
CRM-18Parking is a fact about what happened and is orthogonal to status; it needs a reason and is reversible.
CRM-19Account state is derived on read, never stored: an approach already made is never reported as an untouched door.
CRM-20An event carries the source its date came from; a date not on the source is not a date.
CRM-21Events are never deleted or reopened: done takes an outcome, cancelled takes a reason.
CRM-22Attendance is the person's stance and a separate axis from the event's status; it is recorded only on their word.

jobhunt — One Person's Search · Area Specification

IdInvariant
JH-1Record of reality: facts only from the JD or correspondence; unknown beats guessed.
JH-2Every contact has a source.
JH-3Duplicate warnings are surfaced, never auto-resolved — a person decides.
JH-4One application per posting.
JH-5The end client is first-class; a missing one is visible work.
JH-6One open next action per posting; supersede history kept.
JH-7Suggestions, never actions: the area never sends, submits or clicks.
JH-8Skips are reasoned pattern memory.
JH-9Ghosted is a status, not a deletion.
JH-10Applications record the resume version actually sent.
JH-11Comp is annualized with caveats in prose.
JH-12Interview rounds close with outcomes; outcomes are touches.
JH-13Thresholds are reference data, not code.
JH-14Every write is a logged command with an actor; refusals kept; reads unlogged.

o2c — Order to Cash · Area Specification

IdInvariant
INV-1Money is integer minor units, everywhere.
INV-2Both prices survive: list price and charged price on every line.
INV-3Documents don't mutate past draft except through defined acts.
INV-4Bill what was fulfilled, never what was ordered.
INV-5One credit gate, at confirmation; exposure counts open AR plus committed.
INV-6Stock never goes negative; only the stock owner's API changes it.
INV-7Short fulfilment leaves the remainder open; only close_short extinguishes it.
INV-8Recording cash is not applying cash; unapplied cash is a valid state.
INV-9Document numbers are sequential and never reused.
INV-10Void only when untouched; anything applied-against is corrected by credit note.
INV-11The credit note is the only downward correction past draft.
INV-12Restock only what physically returns sellable.
INV-13Cash is not transferable between customers.
INV-14Tax is frozen at issuance.
INV-15Due dates derive from terms at issuance.
INV-16Write-offs are reasoned, visible credit acts.
INV-17Refusals name the numbers.
INV-18One sentence per rule, on every surface.
INV-19Prices freeze when a document is raised from another.
INV-20Closure is derived, not declared.
INV-21Every write is a logged command with an actor; reads are never logged.
INV-22The books produce documents; they never send them.
INV-23Every journal entry balances — debits equal credits, derived from the books, never entered.

p2p — Procure to Pay · Area Specification

IdInvariant
P2P-1Money is integer cents, everywhere.
P2P-2Nothing is paid without an approved bill; nothing approves without a match on the record.
P2P-3The 3-way match names its numbers; tolerance is config, breach is a refusal.
P2P-4Stock enters only through a receipt; receipts are immutable facts.
P2P-5Item cost is derived from receipts, never entered.
P2P-6Vendor bank details are human-only; an agent can record a bill, never redirect money.
P2P-7A disputed bill cannot be paid; dispute and resolution carry reasons.
P2P-8PO prices freeze at issue; variances are shown, never averaged away.
P2P-9Payments are recorded, never executed — no outbound rails.
P2P-10The duplicate-bill guard surfaces warnings; it never auto-resolves them.
P2P-11Over-receipt and over-billing are refusals naming the quantities.
P2P-12Every write is a logged command with an actor; refusals are logged too.
P2P-13Journal entries derive balanced: receipt to GRNI, approval to AP, payment to cash; COGS arrives with cost.
P2P-14Goods received not invoiced is always visible — a real liability, not a residue.

Prospect staging

IdInvariant
PRO-1The same pull never lands twice: a repeated hash is refused, naming the pull that holds it.
PRO-2Every pull records the brief it was made under, and it is mandatory at the door.
PRO-3A verdict carries a reason a person can overrule, or it is refused.
PRO-4An unjudged row is a distinct state from any verdict, and is queryable as such.
PRO-5Only a person promotes. The act is refused to agents whatever their role.
PRO-6A promoted row records what it became; a promoted row is never re-judged or re-promoted.
PRO-7A staged row is counted in no pipeline, coverage or campaign statistic.
PRO-8Rows are never edited: a wrong pull is discarded and staged again from a fresh read.
PRO-9A discard keeps rows that already became accounts, so those accounts keep their provenance.
PRO-10A promoted account is held to the curated list's own gate: why_them and source_url, from the verdict.
PRO-11Every write is a logged act with an actor; refusals are logged; reads are not.

purchases — What You Buy · Area Specification

IdInvariant
P-1Money is integer minor units, signed; every source and transaction carries a currency; sums are per currency and never cross.
P-2Every transaction traces to a source: source id, row index, and the raw line as read.
P-3A statement is accepted whole or not at all: the rows must reconcile to the printed opening and closing balance, and to the printed row count when the statement prints one, or the batch is refused with the gap named.
P-4The same source hash is refused a second time; rows already present are skipped and listed, never silently merged or duplicated.
P-5Nothing is invented: category, vendor and status are empty or unreviewed until an act with a reason sets them.
P-6A subscription is declared, then confirmed by the record: a period with no matching charge is missed, two make it lapsed; a charge is never assumed.
P-7A receipt matches at most one transaction and vice versa; matching is a reasoned act, refused when the total or date does not fit unless overridden with a reason.
P-8Every write is a logged act with an actor; refusals are logged too.
P-9Files never live here: a source or a receipt is its hash, its metadata and what was read.
P-11A standing rule suggests and never books: matching rows stay unreviewed with the suggestion until a reasoned review confirms them; ending a rule removes its suggestions and changes no reviewed row.
P-12A bill is a record, never a payment: only a person approves paying it, a payment is recorded after it happened and by an agent only for an approved bill, a linked statement row must match it, and the same bill is refused twice.

solo — Freelancer Invoicing · Area Specification

IdInvariant
S-1Money is integer cents, everywhere.
S-2An issued invoice is immutable — mistakes are void-and-reissue, on the record.
S-3The seller and bill-to blocks freeze at issuance; issuing without a profile or a client address is refused with the guide sentence.
S-4Numbers are sequential and never reused; a voided number stays burned.
S-5Invoice timing is the freelancer's agreement — the system records, never gatekeeps terms.
S-6No invented facts: amounts, dates and names come from the person or stay empty.
S-7Documents are produced, never sent; the doc link views one document (DRAFT-stamped until issued) and nothing more.
S-8Every write is a logged act with an actor; refusals are logged too.
S-9Journal derivation balances: issue to AR/Revenue, receipt to Cash/Deposits, application to Deposits/AR.
S-10An invoice carries exactly one currency from the company's set, a payment too; cash never crosses currencies; sums are per currency.
S-11Tax follows the company's scheme, frozen at issue: unregistered lines cannot carry tax; registered lines default to the rate and the document prints TAX INVOICE.
S-12Numbers follow the company's format (sequence token, optional year token) and stay sequential and never reused within it.
S-13A reminder is a draft a person sends: only for an overdue invoice with money open, one waiting at a time, its figures the invoice's own, a send recorded only with the day it went, another within seven days only with a reason.

These pages are generated from the files in specs/ in the repository; scenarios are executed by src/conformance.js on every build. Written and maintained by Peter Varga, who also runs Portland AI Works. github.com/alviso/saybooks, AGPL-3.0.