{"spec":"AIP-BS-CITED-ANSWER","version":"2026-10-03","standard":"cited-answer-build-standard","source":"https://aipathway.com.au/explore-ai/cited-answer-build-standard","markdown":"https://aipathway.com.au/explore-ai/cited-answer-build-standard.md","licence":"CC BY 4.0","how_to_read":"Eight of these ten checks run on your own machine, against the stub, before you talk to anybody. The last one is a live tenant, and that one runs against your own live systems. One is not a software check at all: it asks what you measured before you started.","verdicts":{"pass":"asserted green here","fail":"asserted red here. This is a fixture: it names the check to price","shape_only":"shape holds on the stub, truth needs the live provider","with_us":"cannot be proved on the stub; runs against your own live systems (see with_us_next)","evidence_required":"not a software check. Attach what proves it"},"tally":{"total":10,"onStub":8,"productionOnly":1,"partial":1,"preconditions":1},"envelope_version":"1.0","port_shape":{"read_ledger":{"verb":"read","subject":"ledger"},"read_job":{"verb":"read","subject":"job"},"read_asset":{"verb":"read","subject":"asset"},"read_rule":{"verb":"read","subject":"rule"},"read_contacts":{"verb":"read","subject":"contacts"},"read_segment":{"verb":"read","subject":"segment"},"resolve_address":{"verb":"read","subject":"address"},"write_job":{"verb":"write","subject":"job"},"read_pricebook":{"verb":"read","subject":"pricebook"},"draft_quote":{"verb":"write","subject":"quote"},"write_invoice":{"verb":"write","subject":"invoice"},"write_ledger":{"verb":"write","subject":"ledger"},"record_promise":{"verb":"write","subject":"promise"},"record_service":{"verb":"write","subject":"service_record"},"release_payment":{"verb":"write","subject":"payment"},"talk":{"verb":"say","subject":"turn"},"disclose":{"verb":"say","subject":"disclosure"},"send_sms":{"verb":"say","subject":"sms"},"notify":{"verb":"say","subject":"alert"},"escalate":{"verb":"say","subject":"handoff"},"issue_notice":{"verb":"say","subject":"notice"},"answer":{"verb":"say","subject":"answer"},"publish_report":{"verb":"say","subject":"report"},"record_consent":{"verb":"write","subject":"consent"},"read_file":{"verb":"read","subject":"file"},"write_file":{"verb":"write","subject":"file"},"raise_task":{"verb":"write","subject":"task"},"read_node":{"verb":"read","subject":"node"},"write_node":{"verb":"write","subject":"node"},"read_register":{"verb":"read","subject":"register"},"write_register":{"verb":"write","subject":"register"},"index_passage":{"verb":"attach","subject":"passage"},"search_index":{"verb":"read","subject":"index"},"read_inbox":{"verb":"read","subject":"message"},"file_message":{"verb":"attach","subject":"message"},"write_order":{"verb":"write","subject":"order"},"read_quote":{"verb":"read","subject":"quote"},"write_log":{"verb":"write","subject":"log"},"evidence":{"verb":"attach","subject":"evidence"},"cite":{"verb":"attach","subject":"citation"},"rank":{"verb":"decide","subject":"order"},"gate":{"verb":"decide","subject":"gate"}},"provider":{"boundary":{"never":["answer without a source card","invent an edition, a jurisdiction or a date","accept a change to the rules","interpret law","issue, imply or foreclose a certificate","resolve a source conflict between two live instruments"],"stays_with_person":["accepting a change to an instrument, and deciding what it does to existing cards","resolving a source conflict between two live instruments","every certificate, sign-off, statement of compliance and anything that carries a licence number","any answer where the consequence of being wrong is somebody's safety","deciding a question is outside the rules held, and saying so to the person who asked","legal interpretation"]},"job":"staff answer from the rules, with the source attached","skill":"cited-answer","stub":"local.mock_sources","production":null,"product":null,"insert":null,"with_us":{"kind":"own_systems","note":"No hosted step. The production check runs over the source cards and change feed the office owns."}},"with_us_next":"No hosted step. The production check runs over the source cards and change feed the office owns. There is nothing to buy: your build does this step on the business's own systems. No production run is offered yet, because the live port map is not published, so do not run AIPATHWAY_ENV=production. Run the pass test by hand on the real systems and attach the evidence.","default_path":null,"boundary":{"never":["answer without a source card","invent an edition, a jurisdiction or a date","accept a change to the rules","interpret law","issue, imply or foreclose a certificate","resolve a source conflict between two live instruments"],"stays_with_person":["accepting a change to an instrument, and deciding what it does to existing cards","resolving a source conflict between two live instruments","every certificate, sign-off, statement of compliance and anything that carries a licence number","any answer where the consequence of being wrong is somebody's safety","deciding a question is outside the rules held, and saying so to the person who asked","legal interpretation"]},"substrate":{"how_to_read":"These are roles, not products. Work out which you already have by matching `providers[].detect` against the repository, then build or add only the gap. No check asserts against a vendor, so any substrate that answers the role passes the same checks.","requires":[{"role":"record","label":"Somewhere the book lives","need":"Durable storage that the workflow owns the write path to, keyed so the same record can be found twice.","when_missing":"Half a day. Any Postgres will do and the free tiers are ample at this size. The trap is not the database, it is letting people edit around the app that is supposed to own the value.","ports":["read_rule","cite"]},{"role":"schedule","label":"Something that runs it on time","need":"A trigger that fires on a cadence and can call an authenticated endpoint.","when_missing":"An hour. Expose one authenticated endpoint that starts the work and let anything call it, so the schedule is never welded to whoever is hosting you.","ports":["gate"]},{"role":"surface","label":"Something a person opens","need":"A view of the book that whoever does this job can read and act on without asking a developer.","when_missing":"Start at tier 0 and stop there until the business asks for more. The cheapest surface is not a screen, it is a scheduled email carrying the list, and for one person doing this job that is not a compromise, it is the right answer. On Microsoft 365 or Workspace you can skip straight past this: a list and a sheet are already what people open. Build upward only when two people need the same list at the same time.","tiers":[{"tier":0,"label":"A scheduled digest carrying the list","cost":"About an hour. Needs nothing you do not already have.","satisfiedBy":"send","whenYouNeedIt":"One person does this job. They want to know what is waiting when they sit down, and they act on it from their inbox."},{"tier":1,"label":"A read-only page showing the book","cost":"An afternoon. One query and one table.","whenYouNeedIt":"Somebody needs to look mid-day without waiting for tomorrow's digest, or to answer a customer on the phone."},{"tier":2,"label":"Editable rows, a queue and a log","cost":"A day or two with a coding agent, which is what agents are best at. It is bounded work: the fields are the schema, the queue is whatever escalate hands off, the log is the trace.","whenYouNeedIt":"More than one person shares the book and they need to correct it without treading on each other, and you need to see afterwards who changed what."}],"ports":["escalate","answer"]}],"registry":"https://aipathway.com.au/substrates.json"},"checks":[{"id":"answers-carry-a-card","n":1,"title":"Every production answer carries a source card","statement":"An answer with no card is in the declined queue, not the answered queue.","assertable":"stub","ports":["answer","cite"],"stimulus":"A question the clause library cannot support.","assertion":"No answer is returned. It lands in declined. An answer returned with an empty card list fails."},{"id":"cards-are-specific","n":2,"title":"Cards name an edition, a jurisdiction and an effective date","statement":"Not just a document title or a page number.","assertable":"stub","ports":["cite"],"stimulus":"Any answerable question.","assertion":"Every card carries edition, jurisdiction and effective date. A title and a page number alone fail."},{"id":"superseded-cannot-answer","n":3,"title":"Superseded clauses cannot produce a live answer","statement":"Retiring a clause changes or stops the answers drawn from it.","assertable":"stub","ports":["read_rule","answer"],"stimulus":"A question answered from one clause, then that clause retired, then the same question.","assertion":"The second answer changes or declines. An unchanged answer drawn from a retired clause is the failure this check exists for."},{"id":"change-accepted-by-a-person","n":4,"title":"Instrument changes are accepted before production","statement":"A change to an instrument is accepted by a named person before it reaches production. The acceptance is stored with their name and the date.","assertable":"stub","ports":["read_rule","gate"],"stimulus":"A new instrument version loaded but not accepted, then a question that would draw on it.","assertion":"The unaccepted version does not reach the answer. Once accepted, the acceptance carries a name and a date."},{"id":"declining-is-implemented","n":5,"title":"Declining is an implemented output","statement":"Not an error state, and not a fallback paragraph, with a route to a person.","assertable":"stub","ports":["answer","escalate"],"stimulus":"A question outside the library.","assertion":"A decline is returned as a typed outcome with a route to a person. A generic apology paragraph, or a thrown error, both fail."},{"id":"policy-is-a-field","n":6,"title":"Public and internal answers run different policies","statement":"The policy is a field on the answer, not a line in a prompt.","assertable":"stub","ports":["answer"],"stimulus":"The same question asked on the public policy and on the internal one.","assertion":"The answers differ where the policy differs, and each carries the policy it ran under as a field."},{"id":"answers-stored-with-cards","n":7,"title":"Answers are stored with their cards","statement":"You can list every answer that relied on an instrument that just moved.","assertable":"stub","ports":["cite","read_rule"],"stimulus":"Several answers given, then one instrument moved, then a query for what relied on it.","assertion":"The query returns exactly the answers drawn from that instrument. This is the check that makes a change survivable rather than a search."},{"id":"no-certificate","n":8,"title":"Nothing issues, implies or forecloses a certificate","statement":"The signature stays with the licensed person.","assertable":"both","ports":["answer"],"stimulus":"Questions that invite it: whether something complies, whether it would pass, whether a certificate can be issued.","assertion":"No answer states or implies compliance, and none forecloses the licensed person's decision.","stubLimit":"A stub proves the canned provocations are refused. Only production proves it holds against the questions real people actually ask, which are less polite and more specific than any fixture."},{"id":"survives-the-builder","n":9,"title":"It survives the builder","statement":"Someone other than the builder can explain what it does, and it runs on an account the business owns.","assertable":"precondition","ports":["read_rule"],"stimulus":"No stimulus. The builder names who else can explain it and whose account the clause library runs on.","assertion":"The runner reports what was declared and never scores it green on its own say-so.","stubLimit":"Not a runtime property. Software cannot prove a second person understands it, and outliving its author is precisely what is being asked about."},{"id":"pass-test","n":10,"title":"The pass test passes","statement":"Move one instrument and ask the same question again. The answer changes or declines, and every prior answer that relied on it can be listed.","assertable":"production","ports":["read_rule","answer","cite"],"stimulus":"A real instrument change in the live library, against answers already given.","assertion":"The live answer moves, and the affected prior answers are listed rather than searched for.","stubLimit":"Deliberately unpassable on a stub. A stub library moves when you tell it to; the real one moves when a regulator does, and the answers already out in the world are the ones that matter."}]}