Notation vocabulary
This doc holds the notation-system vocabulary — what the markdown templates produce, how they're filled in, and the
rules that validate them. It is kept in teaching order rather than alphabetically, because Template precedes Notation by
design: you read what a Template declares before you read what a Notation runs. The rest of the workspace vocabulary
lives in glossary.md.
Template
A static blueprint. A markdown file with a YAML frontmatter block — title, code, respondent_type, and the
questionnaire: and workflow: specs — plus a body of legal prose with {{question_code}} placeholders.
A Template declares: which Questions to ask, in what order, what workflow advances the resulting document, who the respondent is, what the document is titled. It asks nothing on its own. Until a respondent is bound to it (see Notation), it is inert — a file on disk, useful for linting and preview, but no questions have been asked and no workflow has run.
Identified by a stable code like llc-california or onboarding-retainer.
- Schema:
store::entity::template - Files:
notation_templates/—category/snake_case_name.md, e.g.notation_templates/trust/nevada.md.
Storage. The markdown body lives in
cloud::StorageServicelike every other artifact: thetemplates.bodyTEXT column is gone;templates.blob_idreferences a Blob holding the bytes. Read the body viastore::templates::body; the seed andnavigator importpaths ingest it (sha-dedup). The Project's archive folder plays no role — Templates are workspace-scoped code-like assets governed by git, not by the per-Project archive.Workspace-shared vs project-scoped. A Template is workspace-shared (
templates.project_id IS NULL, the public catalog default) or scoped to a single Project. Project-scoped rows are hidden from the public Template list (clilist, the admin surface) and resolved only under that Project;store::templates::resolveprefers the caller's Project, falling back to the shared row. Two partial unique indexes oncodeenforce the rule —UNIQUE (code) WHERE project_id IS NULLkeeps workspace-shared codes globally unique (llc__california,onboarding__retainer);UNIQUE (project_id, code) WHERE project_id IS NOT NULLlets each Project reuse short codes (amendment,consent) without colliding with another Project's.
Notation
A Template come to life. One running instance of a Template, bound to a specific Person — the
respondent — a Project, and optionally an Entity, carrying a workflow
state such as draft, staff_review, or signed.
Client English. A Notation in the context of its Project is what clients call an Engagement (or a Retainer, when the bound Template is the onboarding retainer). The schema noun is
Notation; the marketing noun is Engagement.
The Questions the Template declared are asked here; the Answers the respondent gives are stored against this Notation; the workflow runs against this Notation. Where a Template is static, a Notation has a lifetime — born when a matter opens, closed when its workflow terminates. In our legal practice, the unit of work is a Notation: opening a new matter creates one; walking a client through engagement, intake, and signing advances it through its states.
- Schema:
store::entity::notation - Lives in:
notationstable
Note — two meanings. "Notation" is also the umbrella name for Navigator's markdown notation format (the file format Templates are written in). Templates are notations in that sense; each row in the
notationstable is one running instance of one. The format name is older than the schema; both meanings stuck. Disambiguate by context: capitalized and referring to a row or a matter, it's the runtime instance; referring to the file format, it's the lowercase "markdown notation."
Questionnaire
The ordered list of Questions a Template declares it will ask. Lives entirely in the template's
frontmatter under questionnaire:. Not a separate table — the questionnaire is what you get when you read a Template's
frontmatter and resolve each entry against the questions table.
When a Notation runs, those are the prompts the respondent sees and the Answers get attached to. The Template declares the questionnaire; the Notation asks it.
Status — declared and walked. The questionnaire state machine is structurally validated by the
N104rule implementation and executed step-by-step byweb::retainer_walk: one question per request, one Answer per advance, one Notation Event per transition. The walker shares its runtime surface with the Workflow Runtime — both implementworkflows::StateMachineRuntime, keyed by(MachineKind, notation_id)— so a single Restate virtual object per Notation hosts both timelines on one logical journal. Seedocs/retainer_intake.mdfor the end-to-end walkthrough.
Conversational notation (MCP)
The same questionnaire state machine is also driven from outside the HTML form via two MCP tools: aida_create_notation
(start the Notation, get the first question) and aida_answer_notation (submit one answer, get the next question or
"complete"). The LLM client is the UI; the server owns the state. Both the form and the MCP tools call the same
workflows::notation_session service, so changes to the walking logic touch
exactly one codepath. See mcp/README.md for the client-side loop.
Language access
Each Person carries a preferred_language (BCP-47, default en). notation_session::load_question renders each prompt
in that language from the question_translations table — attorney-reviewed localized copy keyed by (question_id, locale) — falling back to the English base prompt when no translation exists. Because both the HTML form and the MCP /
A2A tools resolve the prompt through that one service, intake is multilingual on every surface at once. Translation is
reviewed copy, not runtime machine translation: the staff_review gate and all legal copy stay attorney-reviewed in
each language. Spanish (es) ships seeded for the retainer questions.
Question
One prompt presented to a respondent during Template traversal. Identified by a stable code (e.g. client_name,
organizer_state). Has an answer_type — string, int, bool, choice, etc. — that the form layer uses to render
the right input.
- Schema:
store::entity::question - Lives in:
questionstable - Seed:
store/seeds/Question.yaml
Answer
One respondent's answer to one Question. Deduplicated by (question, person, value), so re-submitting the same value is
a no-op.
- Schema:
store::entity::answer - Lives in:
answerstable
Rule
A validation check applied to markdown notations by the rules crate. Three families:
- M-family — generic Markdown hygiene (headings, list spacing, code-fence languages, link targets).
- N-family — Navigator notation template shape (required keys, question-code resolution, template/workflow well-formedness).
- S101 — the 120-character line-length limit. Applies to every
.mdfile in the workspace.
The cli validate subcommand runs the relevant subset per file.