From 467dcf669adf18afd0d00ea6e81596c1ddd2364b Mon Sep 17 00:00:00 2001 From: Implementer Date: Tue, 13 Oct 2026 07:33:39 +0200 Subject: [PATCH] The chat says which unit of the meta-model it drew The host now draws a meta-model of more types than one picture holds a unit at a time, core or one pack, and where it is asked for the whole it draws core. The chat drew that picture and described it as the schemas behind the whole model, so a visitor could not tell that the packs were left out or that one could be asked for. The note that follows a picture of the schemas now carries the unit drawn and every unit there is, and asks the answer to say which unit this is, to name the others as what can be shown next, and to say that the meta-model is drawn a unit at a time where the whole was asked for. The diagram rule sends a visitor who names core or a pack to the schema shape by unit, where the host's tool takes one. Neither field goes to the widget, which draws the picture and needs no list of units. Verified: the two new tests failed before the change; npm test, npm run typecheck, npm run build:check, conventions-check and conventions-format pass; a local chat from this branch, against a host serving companygraph/mental-model from the model server's branch, drew core for the whole meta-model in five of five asks, three in English and two in German, and the two read in full named the four packs as what can be shown next; a pack named in three wordings drew that pack each time. Process: Delivery Phase: Implement Track: Code Co-Authored-By: Claude Opus 5.5 --- lib/loop.mjs | 16 ++++++++++------ lib/prompt.mjs | 2 +- test/loop.test.mjs | 34 ++++++++++++++++++++++++++++++++++ types/lib/loop.d.mts | 5 +++++ types/lib/prompt.d.mts | 2 +- 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/lib/loop.mjs b/lib/loop.mjs index 05f5609..dfe81cd 100644 --- a/lib/loop.mjs +++ b/lib/loop.mjs @@ -58,12 +58,12 @@ import { units, ESTIMATE } from "./meter.mjs"; * A picture the host drew, as the `diagram` event and the note carry it. diagramOf checks the * source, each node's three keys, each link and each row of everyType; the shape, the title, the * count left out, a node's type and the count of edges are the host's, held by the diagram tool's - * output schema. A lifecycle's `transitions` are checked too, since a state is no node a link joins, + * output schema. A picture of the schemas' `unit` and each row of its `units` are checked as well. A lifecycle's `transitions` are checked too, since a state is no node a link joins, * and a scenario's `steps` and `extensions`, since a step is a box and no node. * @typedef {{ aggregate: string; from: string | null; to: string; command: string | null }} Transition * @typedef {{ step: string; actor: string; action: string }} Step * @typedef {{ step: string; condition: string; handling: string }} Extension - * @typedef {{ shape: string; title: string | null; mermaid: string; nodes: { node: string; id: string; title: string; type?: string }[]; omitted: number; links: { from: string; to: string; label: string }[]; everyType?: { via: string; to: string; multiplicity: string }[]; core?: string | null; transitions?: Transition[]; steps?: Step[]; extensions?: Extension[]; actor?: string; edges?: number }} Diagram + * @typedef {{ shape: string; title: string | null; mermaid: string; nodes: { node: string; id: string; title: string; type?: string }[]; omitted: number; links: { from: string; to: string; label: string }[]; everyType?: { via: string; to: string; multiplicity: string }[]; core?: string | null; unit?: string; units?: { unit: string; types: number }[]; transitions?: Transition[]; steps?: Step[]; extensions?: Extension[]; actor?: string; edges?: number }} Diagram */ // get_entity answers the entity under `entity`, fetch answers it flat with `title`, and // find_evidence answers the skill the evidence is for under `skill`. Each of the three is one @@ -165,6 +165,10 @@ export function diagramOf(name, r) { const links = Array.isArray(d.links) ? d.links.filter((/** @type {any} */ l) => l && kept.has(l.from) && kept.has(l.to) && typeof l.label === "string") : []; const everyType = Array.isArray(d.everyType) ? d.everyType.filter((/** @type {any} */ x) => x && typeof x.via === "string" && typeof x.to === "string" && typeof x.multiplicity === "string") : []; const core = typeof d.model?.core === "string" ? d.model.core : null; + // The unit of the meta-model a picture of the schemas draws, where it draws one, and every + // unit there is with how many types it declares. + const unit = typeof d.unit === "string" && d.unit ? d.unit : null; + const units = Array.isArray(d.units) ? d.units.filter((/** @type {any} */ u) => u && typeof u.unit === "string" && typeof u.types === "number") : []; /** @param {unknown} v */ const blankOr = (v) => v == null || typeof v === "string"; const transitions = Array.isArray(d.transitions) ? d.transitions.filter((/** @type {any} */ t) => t && typeof t.aggregate === "string" && typeof t.to === "string" && blankOr(t.from) && blankOr(t.command)) : []; @@ -173,7 +177,7 @@ export function diagramOf(name, r) { const steps = /** @type {Step[]} */ (Array.isArray(d.steps) ? d.steps.filter((/** @type {unknown} */ x) => allStrings(["step", "actor", "action"], x)) : []); const extensions = /** @type {Extension[]} */ (Array.isArray(d.extensions) ? d.extensions.filter((/** @type {unknown} */ x) => allStrings(["step", "condition", "handling"], x)) : []); const actor = typeof d.actor === "string" ? d.actor : ""; - return { shape: d.shape, title: d.title ?? null, mermaid: d.mermaid, nodes, omitted: d.omitted ?? 0, links, ...(d.shape === "schema" ? { everyType, core } : {}), ...(d.shape === "lifecycle" ? { transitions } : {}), ...(d.shape === "scenario" ? { steps, extensions } : {}), ...(d.shape === "usecase" ? { actor } : {}) }; + return { shape: d.shape, title: d.title ?? null, mermaid: d.mermaid, nodes, omitted: d.omitted ?? 0, links, ...(d.shape === "schema" ? { everyType, core, ...(unit ? { unit } : {}), units } : {}), ...(d.shape === "lifecycle" ? { transitions } : {}), ...(d.shape === "scenario" ? { steps, extensions } : {}), ...(d.shape === "usecase" ? { actor } : {}) }; } // What a flow's and a lifecycle's note ask of each relation: its says, said in words. @@ -308,8 +312,8 @@ export const diagramNote = (d) => { // A picture of the schemas: the types each node is, the core they are declared in, and what // every other type declares, said once, since the picture draws no arrow for it. ...(d.shape === "schema" ? { - schemas: `Each node is a type the schemas of core ${d.core ?? "(version not named)"} declare, and each relation a reference its schema declares, labeled with the field and how many one entity may hold; nested-in joins an owned type to its owner. Name the core version once. The picture is the answer: write two or three sentences, naming a few of the types and relations that carry its structure, never a list of every relation. In German core stays core, never Kern, and a schema deklariert, never erklärt.${d.everyType?.length ? " everyType lists what every other type also declares, which the picture leaves out: say it once, in a sentence of its own." : ""}`, - everyType: d.everyType ?? [], + schemas: `Each node is a type the schemas of core ${d.core ?? "(version not named)"} declare, and each relation a reference its schema declares, labeled with the field and how many one entity may hold; nested-in joins an owned type to its owner. Name the core version once. The picture is the answer: write two or three sentences, naming a few of the types and relations that carry its structure, never a list of every relation. In German core stays core, never Kern, and a schema deklariert, never erklärt.${d.everyType?.length ? " everyType lists what every other type also declares, which the picture leaves out: say it once, in a sentence of its own." : ""}${d.unit ? ` This picture draws one unit of the meta-model, ${d.unit}, ${d.unit === "core" ? "core alone" : "the pack's own types with the core types they declare to"}, because the meta-model is drawn a unit at a time; units lists every unit with how many types it declares. Say which unit this is, and name the other units as what can be shown next, a pack by its name and the word pack; where the visitor asked for the meta-model as a whole, say in one sentence that it is drawn a unit at a time.` : ""}`, + everyType: d.everyType ?? [], ...(d.unit ? { unit: d.unit, units: d.units ?? [] } : {}), } : {}), // A picture of a context map: each relation comes with the sentence that states it, so the model // repeats that sentence and never decodes a direction. @@ -501,7 +505,7 @@ export async function answer({ host, model, meter, questionCap = DEFAULT_QUESTIO } if (names.length) emit("names", { names }); if (verdict) heard(found, given); - if (picture) { const { links, everyType, core, transitions, steps, extensions, actor, ...event } = picture; emit("diagram", event); } + if (picture) { const { links, everyType, core, unit, units, transitions, steps, extensions, actor, ...event } = picture; emit("diagram", event); } results.push({ type: "tool_result", tool_use_id: call.id, content: given, is_error: r.isError }); } // The naming note follows the tool answers, so the model reads it just before it writes. diff --git a/lib/prompt.mjs b/lib/prompt.mjs index aeca0a4..e81ed86 100644 --- a/lib/prompt.mjs +++ b/lib/prompt.mjs @@ -99,7 +99,7 @@ export const KIND_RULE = "A question about the questions this model answers, whi // that hold the same, as a context is asked for as four; a system that holds nothing gets the // landscape alone and one sentence, since what is missing is rows. Which system masters a concept // is a question the pages answer in a line, and a picture of one system cannot. -export const DIAGRAM_RULE = "A visitor who asks to see how the concepts relate, how a process runs, or how something connects is shown a picture: call diagram, with shape concepts, process, neighborhood, context, aggregate, flow, lifecycle, organization, system, holds, usecase, scenario or requirements; one who asks to see the meta-model, the schemas or the types the model is written in, or what it is based on, is shown shape schema, with type where they name one, not shape concepts; the meta-model is always this model's schemas, so a question about what it is gets that answer. One who asks to see a bounded context, or the diagrams of one, is shown shape context, then aggregate, then flow, then lifecycle, all with the context's id, and the answer names what each drew; where aggregate refuses as empty, the map stands alone and the answer says only that the context holds no aggregate; otherwise, where flow or lifecycle refuses as empty, the answer says in one sentence that the model does not describe that flow or lifecycle yet. One who asks for the sequence or the lifecycle of a context or an aggregate is shown that shape alone, flow for the sequence, with its id. One who asks how the company is organized or for an org chart is shown shape organization, with a group's id where they name one, then calls get_entity on every group it drew, and the answer names each group's lead, its members and its open positions as those pages give them, never as read off the picture or its lines; where its omitted is above zero, the answer says in one sentence that the groups outside the line are drawn when one is named. One who asks who leads a group or who works in one is answered from that group's page through get_entity, in words, and shown no picture unless they ask to see one. One who asks to see a system, or the diagram of one, what it connects to, what runs on it or what it runs on, or what data it holds, is shown shape system and then shape holds, both with the system's id, never shape neighborhood, since a system's connections are its landscape, and a name that is both a surface's and a system's is read as the system's, the surface named in one sentence; the answer names what each drew; where holds refuses as empty, the landscape stands alone and the answer says in one sentence that the model names no data the system holds. One who asks which system masters a concept is answered in words from the pages through get_entity, and shown no picture unless they ask to see one. One who asks to see a use case, or the diagram of one, who wants what from it or what it is held to, is shown shape usecase and then shape requirements, both with the use case's id, and the answer names what each drew; where requirements refuses as empty, the use case stands alone and the answer says in one sentence that the model names no requirement it is held to. One who asks how a use case runs, its steps, or what happens when something goes wrong, is shown shape scenario alone, with its id. One who asks what a feature or a product is held to is shown shape requirements with that id, and one who asks about a requirement by its name is shown shape requirements with the requirement's id. Then write a sentence or two naming what it drew by title, with no table of it, stating only the relations the tool listed, or for an organization what get_entity gave for its groups, and never the picture itself, in Mermaid or any other form, because the widget draws it under the answer. Where diagram refuses for any other reason, answer in words and a table as you would without it."; +export const DIAGRAM_RULE = "A visitor who asks to see how the concepts relate, how a process runs, or how something connects is shown a picture: call diagram, with shape concepts, process, neighborhood, context, aggregate, flow, lifecycle, organization, system, holds, usecase, scenario or requirements; one who asks to see the meta-model, the schemas or the types the model is written in, or what it is based on, is shown shape schema, with type where they name one, not shape concepts; one who names core or a pack, the landscape pack, the requirements pack, is shown shape schema with unit where the tool takes one, the pack's name alone, and never with type; the meta-model is always this model's schemas, so a question about what it is gets that answer. One who asks to see a bounded context, or the diagrams of one, is shown shape context, then aggregate, then flow, then lifecycle, all with the context's id, and the answer names what each drew; where aggregate refuses as empty, the map stands alone and the answer says only that the context holds no aggregate; otherwise, where flow or lifecycle refuses as empty, the answer says in one sentence that the model does not describe that flow or lifecycle yet. One who asks for the sequence or the lifecycle of a context or an aggregate is shown that shape alone, flow for the sequence, with its id. One who asks how the company is organized or for an org chart is shown shape organization, with a group's id where they name one, then calls get_entity on every group it drew, and the answer names each group's lead, its members and its open positions as those pages give them, never as read off the picture or its lines; where its omitted is above zero, the answer says in one sentence that the groups outside the line are drawn when one is named. One who asks who leads a group or who works in one is answered from that group's page through get_entity, in words, and shown no picture unless they ask to see one. One who asks to see a system, or the diagram of one, what it connects to, what runs on it or what it runs on, or what data it holds, is shown shape system and then shape holds, both with the system's id, never shape neighborhood, since a system's connections are its landscape, and a name that is both a surface's and a system's is read as the system's, the surface named in one sentence; the answer names what each drew; where holds refuses as empty, the landscape stands alone and the answer says in one sentence that the model names no data the system holds. One who asks which system masters a concept is answered in words from the pages through get_entity, and shown no picture unless they ask to see one. One who asks to see a use case, or the diagram of one, who wants what from it or what it is held to, is shown shape usecase and then shape requirements, both with the use case's id, and the answer names what each drew; where requirements refuses as empty, the use case stands alone and the answer says in one sentence that the model names no requirement it is held to. One who asks how a use case runs, its steps, or what happens when something goes wrong, is shown shape scenario alone, with its id. One who asks what a feature or a product is held to is shown shape requirements with that id, and one who asks about a requirement by its name is shown shape requirements with the requirement's id. Then write a sentence or two naming what it drew by title, with no table of it, stating only the relations the tool listed, or for an organization what get_entity gave for its groups, and never the picture itself, in Mermaid or any other form, because the widget draws it under the answer. Where diagram refuses for any other reason, answer in words and a table as you would without it."; // The types as one sentence, so the model knows what kinds of thing the model holds before it // reaches for a tool: `feature (5)`, and an owned type with its owner, `phase (12, owned by diff --git a/test/loop.test.mjs b/test/loop.test.mjs index 5eafafc..cd5485b 100644 --- a/test/loop.test.mjs +++ b/test/loop.test.mjs @@ -1,3 +1,4 @@ +import fs from "node:fs"; import { test, before, after } from "node:test"; import assert from "node:assert/strict"; import { answer, namesIn, namesPastTheCap, NAME_CAP, foundNothing, diagramOf, diagramNote } from "../lib/loop.mjs"; @@ -587,6 +588,39 @@ test("a picture of the schemas keeps what every other type declares and the core assert.equal("everyType" in diagramOf("diagram", { isError: false, data: { ...data, shape: "concepts" } }), false, "only the schemas carry it"); }); +// A meta-model of more types than one picture holds is drawn a unit at a time, core or one pack, +// and the host says which unit it drew and which there are. The note carries both, so the answer +// says what is shown and what can be shown next, and the widget needs neither. +test("a picture of one unit of the schemas says which unit it is and names the others, in the note alone", () => { + const nodes = [{ node: "n0", id: "core/phase", title: "phase", type: "schema" }, { node: "n1", id: "core/process", title: "process", type: "schema" }]; + const data = { + shape: "schema", title: "core", mermaid: "classDiagram", nodes, edges: 1, omitted: 3, links: [{ from: "n0", to: "n1", label: "nested-in" }], everyType: [], model: { core: "0.69.0" }, + unit: "core", units: [{ unit: "core", types: 37 }, { unit: "landscape", types: 5 }, { unit: 7 }, { unit: "software" }], + }; + const picture = diagramOf("diagram", { isError: false, data }); + assert.equal(picture.unit, "core"); + assert.deepEqual(picture.units, [{ unit: "core", types: 37 }, { unit: "landscape", types: 5 }]); + const note = JSON.parse(diagramNote({ ...picture, edges: 1 })); + assert.equal(note.unit, "core"); + assert.deepEqual(note.units, [{ unit: "core", types: 37 }, { unit: "landscape", types: 5 }]); + assert.match(note.schemas, /draws one unit of the meta-model/); + assert.match(note.schemas, /shown next/); + // A picture of the whole, or of one type, names no unit and its note says nothing of one. + const whole = diagramOf("diagram", { isError: false, data: { ...data, title: null, unit: undefined } }); + assert.equal("unit" in whole, false); + const wholeNote = JSON.parse(diagramNote({ ...whole, edges: 1 })); + assert.equal("unit" in wholeNote, false); + assert.doesNotMatch(wholeNote.schemas, /one unit of the meta-model/); + assert.equal("units" in diagramOf("diagram", { isError: false, data: { ...data, shape: "concepts" } }), false, "only the schemas carry it"); + // The event the widget gets is the picture and nothing the note alone needs. + assert.match(fs.readFileSync(new URL("../lib/loop.mjs", import.meta.url), "utf8"), /const \{ links, everyType, core, unit, units, transitions, steps, extensions, actor, \.\.\.event \} = picture; emit\("diagram", event\);/); +}); + +test("the diagram rule sends core or a pack to the schema shape by unit, where the tool takes one", () => { + assert.match(DIAGRAM_RULE, /one who names core or a pack[^;]*is shown shape schema with unit where the tool takes one/); + assert.match(DIAGRAM_RULE, /never with type/); +}); + test("a type in a picture of the schemas is no name the answer links", () => { const data = { shape: "schema", nodes: [{ node: "n0", id: "core/seat", title: "seat", type: "schema" }, { node: "n1", id: "concepts/claim", title: "Claim", type: "concept" }] }; assert.deepEqual(namesIn(data), [{ id: "concepts/claim", title: "Claim" }]); diff --git a/types/lib/loop.d.mts b/types/lib/loop.d.mts index faa26d9..bbea45a 100644 --- a/types/lib/loop.d.mts +++ b/types/lib/loop.d.mts @@ -47,6 +47,11 @@ export type Diagram = { multiplicity: string; }[]; core?: string | null; + unit?: string; + units?: { + unit: string; + types: number; + }[]; transitions?: Transition[]; steps?: Step[]; extensions?: Extension[]; diff --git a/types/lib/prompt.d.mts b/types/lib/prompt.d.mts index c93bbbe..46fc20b 100644 --- a/types/lib/prompt.d.mts +++ b/types/lib/prompt.d.mts @@ -15,7 +15,7 @@ export declare const nameNote: (message: string) => string; export declare const QUESTION_RULE = "When the visitor's question asks the same thing as one of the questions this model answers, in any language or wording, get_entity that question first and answer from the entities it rests on, getting each one you draw on and naming it, not the question, as what the answer rests on; a question that rests on no entity is itself what the answer rests on, and is named. A model question is where the answer starts, not all of it: where the visitor asks more than the question does, a time such as now or lately, a period, a number or a kind, the answer gets that too, through the tools."; export declare const FACTS_RULE = "Each entity list_entities returns carries fields, the short facts its page states, such as its dates, its kind and its status. A question about now, today, currently, or what is running or ongoing is answered by list_entities with on set to today's date, which keeps the periods, start to end, that hold it, a period with no end still running; one about the latest, the last, the first or the most recent, by list_entities with by naming the date field and order newest or oldest; and one about the things of one kind, status or other value, the roles, the standing decisions, by list_entities with where naming the field and the value as fields shows them. A question about a person's role, job or position is about their experiences, kept with where on the kind that names such a period and ordered by start, and never about the type role, whose entities are the seats of this model's own processes. A list too long to read whole is narrowed with these before it is paged through. This holds even where the visitor's question also matches one of the questions this model answers, such as one about what someone does or studies now: the list on today's date is called first, and what that question rests on is added beside it, never in its place."; export declare const KIND_RULE = "A question about the questions this model answers, which there are, how they are grouped or sorted, or what they cover, including \"these questions\" where the conversation or the site offers them, is a question about this model and never about something else: it is answered by list_entities with type question-kind, then get_entity on each kind for its rank, and the answer names every kind in rank order, lowest first, with what each covers; a kind's questions come from list_references on it. It is never answered from an earlier turn's list or from your own reading of the questions."; -export declare const DIAGRAM_RULE = "A visitor who asks to see how the concepts relate, how a process runs, or how something connects is shown a picture: call diagram, with shape concepts, process, neighborhood, context, aggregate, flow, lifecycle, organization, system, holds, usecase, scenario or requirements; one who asks to see the meta-model, the schemas or the types the model is written in, or what it is based on, is shown shape schema, with type where they name one, not shape concepts; the meta-model is always this model's schemas, so a question about what it is gets that answer. One who asks to see a bounded context, or the diagrams of one, is shown shape context, then aggregate, then flow, then lifecycle, all with the context's id, and the answer names what each drew; where aggregate refuses as empty, the map stands alone and the answer says only that the context holds no aggregate; otherwise, where flow or lifecycle refuses as empty, the answer says in one sentence that the model does not describe that flow or lifecycle yet. One who asks for the sequence or the lifecycle of a context or an aggregate is shown that shape alone, flow for the sequence, with its id. One who asks how the company is organized or for an org chart is shown shape organization, with a group's id where they name one, then calls get_entity on every group it drew, and the answer names each group's lead, its members and its open positions as those pages give them, never as read off the picture or its lines; where its omitted is above zero, the answer says in one sentence that the groups outside the line are drawn when one is named. One who asks who leads a group or who works in one is answered from that group's page through get_entity, in words, and shown no picture unless they ask to see one. One who asks to see a system, or the diagram of one, what it connects to, what runs on it or what it runs on, or what data it holds, is shown shape system and then shape holds, both with the system's id, never shape neighborhood, since a system's connections are its landscape, and a name that is both a surface's and a system's is read as the system's, the surface named in one sentence; the answer names what each drew; where holds refuses as empty, the landscape stands alone and the answer says in one sentence that the model names no data the system holds. One who asks which system masters a concept is answered in words from the pages through get_entity, and shown no picture unless they ask to see one. One who asks to see a use case, or the diagram of one, who wants what from it or what it is held to, is shown shape usecase and then shape requirements, both with the use case's id, and the answer names what each drew; where requirements refuses as empty, the use case stands alone and the answer says in one sentence that the model names no requirement it is held to. One who asks how a use case runs, its steps, or what happens when something goes wrong, is shown shape scenario alone, with its id. One who asks what a feature or a product is held to is shown shape requirements with that id, and one who asks about a requirement by its name is shown shape requirements with the requirement's id. Then write a sentence or two naming what it drew by title, with no table of it, stating only the relations the tool listed, or for an organization what get_entity gave for its groups, and never the picture itself, in Mermaid or any other form, because the widget draws it under the answer. Where diagram refuses for any other reason, answer in words and a table as you would without it."; +export declare const DIAGRAM_RULE = "A visitor who asks to see how the concepts relate, how a process runs, or how something connects is shown a picture: call diagram, with shape concepts, process, neighborhood, context, aggregate, flow, lifecycle, organization, system, holds, usecase, scenario or requirements; one who asks to see the meta-model, the schemas or the types the model is written in, or what it is based on, is shown shape schema, with type where they name one, not shape concepts; one who names core or a pack, the landscape pack, the requirements pack, is shown shape schema with unit where the tool takes one, the pack's name alone, and never with type; the meta-model is always this model's schemas, so a question about what it is gets that answer. One who asks to see a bounded context, or the diagrams of one, is shown shape context, then aggregate, then flow, then lifecycle, all with the context's id, and the answer names what each drew; where aggregate refuses as empty, the map stands alone and the answer says only that the context holds no aggregate; otherwise, where flow or lifecycle refuses as empty, the answer says in one sentence that the model does not describe that flow or lifecycle yet. One who asks for the sequence or the lifecycle of a context or an aggregate is shown that shape alone, flow for the sequence, with its id. One who asks how the company is organized or for an org chart is shown shape organization, with a group's id where they name one, then calls get_entity on every group it drew, and the answer names each group's lead, its members and its open positions as those pages give them, never as read off the picture or its lines; where its omitted is above zero, the answer says in one sentence that the groups outside the line are drawn when one is named. One who asks who leads a group or who works in one is answered from that group's page through get_entity, in words, and shown no picture unless they ask to see one. One who asks to see a system, or the diagram of one, what it connects to, what runs on it or what it runs on, or what data it holds, is shown shape system and then shape holds, both with the system's id, never shape neighborhood, since a system's connections are its landscape, and a name that is both a surface's and a system's is read as the system's, the surface named in one sentence; the answer names what each drew; where holds refuses as empty, the landscape stands alone and the answer says in one sentence that the model names no data the system holds. One who asks which system masters a concept is answered in words from the pages through get_entity, and shown no picture unless they ask to see one. One who asks to see a use case, or the diagram of one, who wants what from it or what it is held to, is shown shape usecase and then shape requirements, both with the use case's id, and the answer names what each drew; where requirements refuses as empty, the use case stands alone and the answer says in one sentence that the model names no requirement it is held to. One who asks how a use case runs, its steps, or what happens when something goes wrong, is shown shape scenario alone, with its id. One who asks what a feature or a product is held to is shown shape requirements with that id, and one who asks about a requirement by its name is shown shape requirements with the requirement's id. Then write a sentence or two naming what it drew by title, with no table of it, stating only the relations the tool listed, or for an organization what get_entity gave for its groups, and never the picture itself, in Mermaid or any other form, because the widget draws it under the answer. Where diagram refuses for any other reason, answer in words and a table as you would without it."; /** @param {TypeCount[]} [types] */ export declare function typeMap(types?: TypeCount[]): string; export declare const DEFAULT_QUESTION_INDEX_CHARS = 4000;