Version. 0.1 Date. 2026-06-07 Status. Scoping note for a comprehensive API documentation effort. Records the architecture settled in conversation: a single annotated source in the Engine, generated into a concise programmatic Markdown reference and an authored, narrative, Operator-facing HTML document. Names the prerequisite bug, the writing standard, the HTML narrative structure, and the prioritized sequence. No build work; this is the brief the work proceeds from. Render-type. Scoping note. Operator-facing.
The Loomworks Engine's API will be comprehensively documented, with the descriptions living in the Engine code itself (not in separate files that drift) and generated out into two documents that serve two different readers:
Both draw on the same source: descriptions annotated onto the Engine's routes and data models. Write a description once; the Markdown takes the concise form, the HTML narrative embeds the full form. Add or change a route and regenerate — the detail stays current.
One prerequisite blocks everything: the Engine's schema does not generate at all right now (one route breaks it). That is fixed first.
The motivation traces directly from the API boundary work. The API is the boundary every driver — Companion, agent, human — crosses to reach the Engine. An inspection of that boundary found it is documented almost not at all at the field level: of 1,068 request/response fields in the schema, 4 carry a description. The thing every driver must use to talk to the Engine does not explain itself.
So this is not cosmetic documentation. It is documenting the boundary — making the contract that drivers depend on legible, and preserving the knowledge of what each endpoint and field means before that knowledge lives only in the heads of the people who wrote the routes.
The architecture decision (settled): descriptions live in the Engine code, generated out — not in standalone hand-maintained files. A separate documentation file goes stale the moment a route changes; nothing forces it back into sync. That is the same drift problem that motivated building a schema-driven console over a hand-maintained Postman collection. Putting descriptions in the code (where FastAPI already publishes them in the OpenAPI schema) makes the schema the single source, and both documents become renderings of it. Knowledge preserved in a doc that goes stale is fossilized, not preserved; knowledge in the schema, regenerated on demand, stays true.
The live /openapi.json returns HTTP 500. One route — POST /me/engagements/create-from-conversation — carries an unresolved forward reference (Optional[LLMClient]), and because FastAPI builds the schema all-or-nothing, that one route breaks the entire document. Consequences today: the console renders nothing, and /docs and /redoc are broken for everyone (their HTML shells load, but the schema they fetch 500s).
This is a real Engine defect independent of the documentation effort, and it must be fixed before any schema can be generated or annotated. The fix is narrow — resolve or model_rebuild() the LLMClient reference on that one route. Recommended to fold into the CR-2026-098 execution session, since Claude Code will be in the engine repo for that boundary work anyway; both are "make the Engine sound." May instead be a standalone fix ahead of everything if the Operator prefers it not wait on CR-2026-098.
Until this lands, the documentation work cannot begin — there is no generatable schema to annotate against or render from.
Descriptions are written where they belong:
Route suffix — "Add Engagement Route") and the descriptions are developer-facing docstrings that leak internal references (phase numbers, spec section IDs like "§6.3", migration numbers, rule IDs like "R-B20", dependency names). These are curated: real summaries written, descriptions rewritten for the intended reader.Field(..., description=...) written in the Pydantic model. The core knowledge-writing endpoint's body (AddAssertionRequest) is the worked example: grammar_element, normative_force, source_mode today show as bare name+type with no guidance on what a value should contain.The annotation carries two fullnesses natively, using slots the schema already provides:
description (routes) and Field(description=...) (fields) — the complete Operator-facing explanation. Surfaces in the HTML.summary (routes) and Field(title=...) (fields) — a short identifier. Surfaces in the Markdown.Write the full description once; the generators decide how much each output shows. The annotation effort is unchanged in scale by serving two outputs — it is the shared substrate for both.
Both documents serve the Operator: the Operator uses the testing console (Markdown), and reviews the narrative (HTML). So descriptions are written in plain English for an Operator, with full explanations. The developer-facing docstrings are translated out of codebase shorthand — phase numbers, spec section references, rule IDs, and internal function names do not appear in Operator-facing prose. This is the seed's plain-terms discipline: methodology and capability described in plain terms; codebase shorthand stays in code.
This is a translation standard, not merely a gap-fill: existing descriptions are rewritten to this standard, not just supplemented.
Fully generated from the schema. No authored prose. Carries, per endpoint: method, path, concise summary, parameters and body fields with name, type, required/optional, enum values, and the concise field title. Omits or truncates the long prose. Drift-free by construction — it is a pure rendering of the schema. This is what the API testing console reads, and what any other machine consumer uses. Because it is generated, it is always current and never maintained by hand.
A document written to be read start to finish, that teaches what the API is and how it is organized, with generated endpoint and field detail embedded into authored sections.
This document has two layers with two sources, and the distinction is load-bearing:
The HTML does not try to be exhaustive. Exhaustiveness lives in the generated Markdown and /docs, where it is drift-free. The HTML carries the understanding and the key endpoints of each area, and points into the Markdown//docs for complete per-endpoint field detail. A generated reference preserves data; a narrative preserves understanding — the HTML is the latter, and that is what "preserves knowledge" requires.
Organized as a layered narrative — the four rooms at the center, the substrate they run on placed explicitly around them:
Rules that keep the narrative from rotting:
/docs.A script in the Engine reads the built schema and emits the two documents:
Run on demand or in CI. Both outputs regenerate from the current schema; the Markdown is wholly current, the HTML's embedded detail is current while its narrative frame is curated.
This is the largest piece of work in the current arc — ~200 route descriptions to curate and ~1,000 field descriptions to write, all Operator-facing, all in the Engine code. It is not one session; it is a sustained effort, sequenced to prove the approach early and grind the bulk with the standard locked.
AddAssertionRequest as the model Claude Code follows).DUNIN7 — Done In Seven LLC — Miami, Florida Loomworks API documentation — scoping note — v0.1 — 2026-06-07