FTS pipeline and visualization: one run and model diagram
The course has already shown fts check, fts prove, fts certify, and fts visualize
as separate commands — each has its own JSON, its own exit code, its own reason
to fail. In CI and in interaction with an agent, this is inconvenient: to understand whether
a document is ready, you have to run four processes and manually match their outputs.
This chapter is about fts pipeline, which runs the entire chain with one call
and returns one JSON, and about fts visualize, which turns a model into
a mermaid diagram — that is, into a question that can be asked of a person, not just
a compiler.
Minimal example
категория «Исполнение заказа»
объект Заказ
номер является строкой
клиент является строкой
оплачен является признаком
«склад подтвердил» является признаком
«готов к отгрузке» является состоянием «Готов к отгрузке»
морфизм «Готовый заказ можно отгрузить»
если «Готов к отгрузке»
то «Отгрузить заказ разрешено»
теорема «Заказ ЗК-7781 можно отгрузить»
дано Заказ имеет «готов к отгрузке» равное да
в данных заказы найти где номер равен «ЗК-7781»
по морфизму «Готовый заказ можно отгрузить»
следовательно «Отгрузить заказ разрешено»
This is static/fts/models/order-shipment.fts — the same model as in the chapter on
proofs and certificates. Here it is needed for a different reason: it has
both the structure, the morphism, and the theorem, which means all four
fields of PipelineResult can be demonstrated on it at once, not just a part.
What the compiler does
fts check parses the category and object, checks that the state
«Ready for shipment» is declared, and the morphism refers to an actual
existing fact. If the theorem referenced a non-existent field, the compilation would fail
here, before any data processing.
One Run Instead of Four Commands
pipeline() in src/pipeline.ts is not the fifth command, but a sequential
call of the same code that underlies check, prove, certify and visualize,
on one already compiled document:
export function pipeline(input: PipelineInput): PipelineResult {
const rawDocument = typeof input.source === "string"
? compile(input.source)
: normalizeDocument(input.document)
const document = assertValid(rawDocument)
const proof = document.proposition === null ? null : prove(document, input.context)
const certificate = document.proposition === null ? null : certify(document, input.context)
const viz = visualize(document, proof, input.viz ?? "all")
return { document, proof, certificate, viz }
}
PipelineInput takes either a string source, or already parsed
document (for those who got canonical JSON from another language — see
chapter on cross-language), plus optional context and viz.
PipelineResult is exactly { document, proof, certificate, viz }: if the
model has no theorem (document.proposition === null), proof and
certificate will be null, but document and viz will still return —
a diagram can be built without the theorem.
It is important what is missing in pipeline: it does not run fts test and does not trigger generateTypeScript. Examples testing and code generation are separate CI steps intentionally not included in this chain (one of the typical fallacies is below).
The practical difference with four separate calls is not in the number of keystrokes, but in the form of failure:
- One point of failure.
assertValidthrows an exception with the same diagnostics asfts check, and the entirepipelinestops at this stage — no need to write in CIcheck && prove && certify && visualizewith manual checking of the exit code at each stage. - One JSON for CI. The result can be saved entirely as a build artifact or parsed once in a script, instead of four files that might diverge in time if the process crashes between stages.
- One JSON for the agent. The MCP tool
fts_pipeline(src/mcp.ts) is described as: «Compile, validate, prove, and visualize FTS in one deterministic call». The agent does not need to make four sequential calls to the tool and keep four intermediate results in context — it receives the document, proof, certificate, and diagram in one round-trip and with the samedocument_digestin all parts of the response.
CLI-equivalent:
fts pipeline order-shipment.fts --context order-shipment.context.json --mode category --pretty
Category Diagram
fts visualize builds mermaid from the document, rather than drawing it manually —
the diagram is as accurate as the model is accurate. Here is the actual output
mermaidCategory for order-shipment.fts:
номер: Строка<br/>клиент: Строка<br/>оплачен: Признак<br/>склад подтвердил: Признак<br/>готов к отгрузке: Готов к отгрузке"] n_u413_u43e_u442_u43e_u432_u20_u43a_u20_u43e_u442_u433_u440_u443_u437_u43a_u435_["Готов к отгрузке"] n_u41e_u442_u433_u440_u443_u437_u438_u442_u44c_u20_u437_u430_u43a_u430_u437_u20_u440_u430_u437_u440_u435_u448_u435_u43d_u43e_["Отгрузить заказ разрешено"] n_u413_u43e_u442_u43e_u432_u20_u43a_u20_u43e_u442_u433_u440_u443_u437_u43a_u435_ -->|"morphism Готовый заказ можно отгрузить"| n_u41e_u442_u433_u440_u443_u437_u438_u442_u44c_u20_u437_u430_u43a_u430_u437_u20_u440_u430_u437_u440_u435_u448_u435_u43d_u43e_ end
The question this diagram addresses is: “how many types are in the model and what transitions between them are declared” — without reading .fts line by line. A structure node shows all fields at once, an arrow indicates the direction of the morphism from domain to codomain. mermaidCategory collects nodes by the names of structures and functors (document.structures, document.functors), so the diagram will never diverge from the model: changed a field — the node label changes on the next generation.
Morphism Diagram and Proofs
A category with one morphism is easy to read without a diagram. A diagram is needed
when there are multiple morphisms and the order of composition matters. On the model
credit-limit.fts (credit limit: scoring → risk check → limit)
mermaidFunctors draws the chain explicitly:
The question addressed by this diagram is: “in what order are the
morphisms actually applied”—in the JSON output prove the composition order is printed
left to right in the order of declaration, while the mathematical ∘ is read
right to left (this is separately discussed in the chapter on proofs). The image with
two explicit arrows removes ambiguity faster than parsing
the line A ∘ B.
mermaidProof builds the third diagram — not from the model, but from the result
prove on specific data: a chain of applied morphisms and a witness,
which closes the derivation:
The question here is different: “On the basis of which specific fact did the system approve
the limit for a particular application.” A dashed arrow to node witness — this is
the answer: a specific field of a specific object, not an abstract law.
Who and When to Show the Diagram
- Analytics — category diagram, up to code review. It is checked
visually in a minute: do the node names match the ubiquitous language from
the task, has a morphism been lost that the analyst considered obvious.
Text
.ftsis not necessarily to read for this. - A new developer in the team — category and morphism diagrams at the first acquaintance with the model. One graph replaces reading the entire file and immediately shows the boundaries: what structures exist, what transitions between them are declared, and which similar transitions in the model are simply missing.
- When analyzing an incident — a proof diagram (
mermaidProof) on the data snapshot that was at the moment of the incident. This is the only one of the three diagrams that answers not «what is generally possible», but «what exactly happened on these data»: a specific path and a specific witness, not a general model schema.
Practice in the sandbox
The “Diagram” tab invokes mermaidCategory directly in the browser — it is the same
code as in fts visualize, but without installing the CLI. Open this model and
compare the category diagram with the morphism diagram from this chapter: two nodes
«Риск-проверка разрешена» in mermaidFunctors — are the same node
of the model, just drawn twice, separately for each morphism.
Common fallacies
- Expect
pipelinetests and generation. The name sounds like the “entire model lifecycle”, butpipeline()ischeck+prove+certify+visualize, and nothing more.fts testandfts generateremain separate CI steps (see the chapter on generation and CI); including them inpipelineis meaningless to expect. - Mix up the argument positions of
visualize. The signature isvisualize(document, proof, mode), three parameters, not two. A call likevisualize(doc, "all")will substitute the string"all"instead ofproofand crash withTypeError: Cannot read properties of undefined (reading 'length')insidemermaidProof— exactly this error reproduces if checked on a vendor site build. The third argument is mandatory, the second — eithernull, or the result ofprove. - Forget about
nullinproof/certificate. For a model without a theorem (document.proposition === null)pipelinedoes not crash — it simply returnsproof: null, certificate: nullwhenvizis fully filled. Code that readsresult.proof.witnesswithout checking fornull, will crash not on a model with an error, but on a correct model without a theorem. - Consider
functorssynonymous with “no diagram”.--modehas five real values —all,category,morphisms,functors,proof(morphismsandfunctorsare synonyms in the implementation ofvisualize, both lead tomermaidFunctors); if the model has no morphisms,mermaidFunctorswill return an empty string, butvisualizein modesmorphisms/functorswill fall back tomermaid_category, not to an empty output.
Checklist
- For CI and the agent,
fts pipeline/fts_pipelineis used, not a sequence ofcheck,prove,certify,visualize. - It is known that
pipelinedoes not replacefts testandfts generate— they remain in the pipeline separately. - Before reading
result.prooforresult.certificate, it is checked that the document containsтеорема(otherwise both fields —null). - The category diagram is shown to the analyst before code review, not after.
- The proof diagram is built on a snapshot of incident data, not on an abstract model, if the question is “what happened”, not “what is possible”.