yarramate 1.31.0 → 1.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/adapters/likec4-export.d.ts +3 -0
  2. package/dist/adapters/likec4-export.js +4 -1
  3. package/dist/adapters/likec4-project-export.d.ts +10 -1
  4. package/dist/adapters/likec4-project-export.js +8 -3
  5. package/dist/adapters/likec4-project.d.ts +3 -0
  6. package/dist/adapters/likec4-project.js +4 -3
  7. package/dist/adapters/mcp-cli.js +2 -2
  8. package/dist/branding.d.ts +86 -0
  9. package/dist/branding.js +80 -0
  10. package/dist/tools/export.js +2 -1
  11. package/dist/tools/table.d.ts +32 -3
  12. package/dist/tools/table.js +86 -32
  13. package/dist/tools/workspace.d.ts +6 -0
  14. package/dist/tools-entry.d.ts +2 -1
  15. package/dist/tools-entry.js +2 -1
  16. package/dist/visual-app/assets/{elk.bundled-JlCCXIin.js → elk.bundled-DwTh4wCo.js} +1 -1
  17. package/dist/visual-app/assets/{index-BSwETsaq.js → index-DJYV9FNm.js} +28 -28
  18. package/dist/visual-app/assets/index-DYTKTQsG.css +1 -0
  19. package/dist/visual-app/index.html +2 -2
  20. package/dist/visual-app-lib/editor.js +29863 -29803
  21. package/dist/visual-app-lib/styles.css +1 -1
  22. package/dist/visual-app-lib/types/branding.d.ts +86 -0
  23. package/dist/visual-app-lib/types/tools/workspace.d.ts +6 -0
  24. package/dist/visual-app-lib/types/visual-app/App.d.ts +4 -1
  25. package/dist/visual-app-lib/types/visual-app/mount.d.ts +10 -0
  26. package/dist/workbook-entry.d.ts +1 -0
  27. package/dist/workbook-entry.js +1 -0
  28. package/dist/workbook.d.ts +3 -2
  29. package/dist/workbook.js +19 -4
  30. package/docs/CONSUMING-YARRAMATE.md +55 -0
  31. package/package.json +1 -1
  32. package/dist/visual-app/assets/index-CZSChZa6.css +0 -1
@@ -1,4 +1,5 @@
1
1
  import { type AdapterMapping } from '../adapter-mapping.js';
2
+ import { type Branding } from '../branding.js';
2
3
  import type { StateComparison } from '../architecture-state.js';
3
4
  import type { ProjectionResult } from '../projection.js';
4
5
  import type { LikeC4KindMapping } from './likec4-kind-mapping.js';
@@ -21,6 +22,8 @@ export type LikeC4ExportResult = {
21
22
  };
22
23
  export interface LikeC4ExportOptions {
23
24
  readonly comparison?: StateComparison;
25
+ /** The banner names the host's product (#546, ADR 0158); absent, the engine. */
26
+ readonly branding?: Branding;
24
27
  /** Git-derived review overlay (ADR 0066): subjects new or changed in a
25
28
  * ref range carry metadata and view styling; nothing is authored. */
26
29
  readonly gitChange?: GitChangeOverlay;
@@ -1,4 +1,5 @@
1
1
  import { adapterMappingEntryLocation, adapterMappingLocation, } from '../adapter-mapping.js';
2
+ import { resolveBranding } from '../branding.js';
2
3
  import { diagnosticOrder } from '../source-document.js';
3
4
  const identifier = /^[A-Za-z_][A-Za-z0-9_-]*$/;
4
5
  const valueFor = (claims, subject, predicate) => {
@@ -114,8 +115,10 @@ export function exportLikeC4(projection, mapping, kindMapping, options = {}) {
114
115
  diagnostics: diagnostics.sort(diagnosticOrder),
115
116
  };
116
117
  }
118
+ const brand = resolveBranding(options.branding);
117
119
  const lines = [
118
- '// Generated by YarraMate. Edit the native documents, not this file.',
120
+ `// Generated by ${brand.productName}. Edit the native documents, not this file.`,
121
+ ...(brand.vendorLine === null ? [] : [`// ${brand.vendorLine}`]),
119
122
  'model {',
120
123
  ];
121
124
  for (const concept of concepts) {
@@ -1,4 +1,5 @@
1
1
  import type { WorkspaceSource } from '../compiler.js';
2
+ import { type Branding } from '../branding.js';
2
3
  import { type LikeC4PreparationDiagnostic } from './likec4-prepare.js';
3
4
  import type { GitChangeOverlay } from './likec4-export.js';
4
5
  import { type LikeC4ProjectDefinition, type PreparedLikeC4ProjectView } from './likec4-project.js';
@@ -26,6 +27,12 @@ export interface LikeC4ProjectExportInput {
26
27
  readonly requireMappedRelationships: boolean;
27
28
  /** The git-derived review overlay, when the CLI derived one. */
28
29
  readonly gitChange?: GitChangeOverlay;
30
+ /**
31
+ * The host's branding (#546, ADR 0158): the model banner and the project
32
+ * name in `likec4.config.json`. The marker file and its digests are
33
+ * machinery and keep their names.
34
+ */
35
+ readonly branding?: Branding;
29
36
  }
30
37
  export interface LikeC4ProjectExported {
31
38
  readonly ok: true;
@@ -38,6 +45,8 @@ export interface LikeC4ProjectExported {
38
45
  readonly kindMappingIdentity?: string;
39
46
  /** Every source that fed the export, for the marker's input digests. */
40
47
  readonly inputs: readonly WorkspaceSource[];
48
+ /** Echoed from the input so `generatedProjectFiles` names the project for it. */
49
+ readonly branding?: Branding;
41
50
  }
42
51
  export type LikeC4ProjectExportResult = LikeC4ProjectExported | {
43
52
  readonly ok: false;
@@ -62,7 +71,7 @@ export interface GeneratedProjectOwnership {
62
71
  }
63
72
  export declare const ownershipOf: (exported: LikeC4ProjectExported) => GeneratedProjectOwnership;
64
73
  export declare const inputDigestsOf: (inputs: readonly WorkspaceSource[]) => Readonly<Record<string, string>>;
65
- export declare const projectNameOf: (projectIdentity: string) => string;
74
+ export declare const projectNameOf: (projectIdentity: string, branding?: Branding) => string;
66
75
  /**
67
76
  * The four files a generated project holds, exactly as the CLI writes them
68
77
  * under its output directory: the config, the model, the specification the
@@ -1,4 +1,5 @@
1
1
  import { parseDocument } from 'yaml';
2
+ import { brandSlug, resolveBranding } from '../branding.js';
2
3
  import { sha256Hex } from '../digest.js';
3
4
  import { LIKEC4_SPECIFICATION_SOURCE } from '../likec4-specification.generated.js';
4
5
  import { locateSourcePath } from '../source-document.js';
@@ -165,7 +166,10 @@ export const exportLikeC4ProjectFromSources = (input) => {
165
166
  }
166
167
  renderedViewIds.add(renderedId);
167
168
  }
168
- const exported = exportLikeC4Project(definition, successfulViews, input.gitChange === undefined ? {} : { gitChange: input.gitChange });
169
+ const exported = exportLikeC4Project(definition, successfulViews, {
170
+ ...(input.gitChange === undefined ? {} : { gitChange: input.gitChange }),
171
+ ...(input.branding === undefined ? {} : { branding: input.branding }),
172
+ });
169
173
  if (!exported.ok)
170
174
  return { ok: false, diagnostics: exported.diagnostics };
171
175
  const first = successfulViews[0];
@@ -182,6 +186,7 @@ export const exportLikeC4ProjectFromSources = (input) => {
182
186
  kindMappingIdentity: `${first.prepared.kindMapping.id}@${first.prepared.kindMapping.version}`,
183
187
  }),
184
188
  inputs: [projectSource, ...sources, ...referencedSources.values()],
189
+ ...(input.branding === undefined ? {} : { branding: input.branding }),
185
190
  };
186
191
  };
187
192
  // ---------------------------------------------------------------------------
@@ -208,7 +213,7 @@ export const ownershipOf = (exported) => ({
208
213
  export const inputDigestsOf = (inputs) => Object.fromEntries(inputs
209
214
  .map(({ path, source }) => [path, sha256Hex(source)])
210
215
  .sort(([left], [right]) => left.localeCompare(right)));
211
- export const projectNameOf = (projectIdentity) => `yarramate-${projectIdentity}`.replaceAll(/[^A-Za-z0-9_-]/g, '-');
216
+ export const projectNameOf = (projectIdentity, branding) => `${brandSlug(resolveBranding(branding))}-${projectIdentity}`.replaceAll(/[^A-Za-z0-9_-]/g, '-');
212
217
  /**
213
218
  * The four files a generated project holds, exactly as the CLI writes them
214
219
  * under its output directory: the config, the model, the specification the
@@ -218,7 +223,7 @@ export const projectNameOf = (projectIdentity) => `yarramate-${projectIdentity}`
218
223
  export const generatedProjectFiles = (exported) => {
219
224
  const configSource = `${JSON.stringify({
220
225
  $schema: 'https://likec4.dev/schemas/config.json',
221
- name: projectNameOf(exported.projectIdentity),
226
+ name: projectNameOf(exported.projectIdentity, exported.branding),
222
227
  title: exported.project.title,
223
228
  }, null, 2)}\n`;
224
229
  const markerSource = `${JSON.stringify({
@@ -1,3 +1,4 @@
1
+ import type { Branding } from '../branding.js';
1
2
  import type { WorkspaceSource } from '../compiler.js';
2
3
  import type { LikeC4PreparationResult } from './likec4-prepare.js';
3
4
  import { type GitChangeOverlay, type LikeC4ExportResult } from './likec4-export.js';
@@ -59,5 +60,7 @@ export interface PreparedLikeC4ProjectView {
59
60
  }
60
61
  export interface LikeC4ProjectExportOptions {
61
62
  readonly gitChange?: GitChangeOverlay;
63
+ /** Names the product in the model banner (#546, ADR 0158). */
64
+ readonly branding?: Branding;
62
65
  }
63
66
  export declare function exportLikeC4Project(project: LikeC4ProjectDefinition, views: readonly PreparedLikeC4ProjectView[], options?: LikeC4ProjectExportOptions): LikeC4ExportResult;
@@ -236,9 +236,10 @@ export function exportLikeC4Project(project, views, options = {}) {
236
236
  if (first === undefined) {
237
237
  throw new Error('LikeC4 project requires at least one view');
238
238
  }
239
- const model = exportLikeC4(unionProjection(project, views), first.prepared.subjectMapping, first.prepared.kindMapping, options.gitChange === undefined
240
- ? {}
241
- : { gitChange: options.gitChange });
239
+ const model = exportLikeC4(unionProjection(project, views), first.prepared.subjectMapping, first.prepared.kindMapping, {
240
+ ...(options.gitChange === undefined ? {} : { gitChange: options.gitChange }),
241
+ ...(options.branding === undefined ? {} : { branding: options.branding }),
242
+ });
242
243
  if (!model.ok)
243
244
  return model;
244
245
  const startToken = '\nviews {\n';
@@ -7,7 +7,7 @@ import { isMainModule, packageVersion, versionResult, } from '../cli-support.js'
7
7
  import { runCli } from '../cli.js';
8
8
  import { createFileSystemStore } from '../source-store.js';
9
9
  import { loadWorkspaceManifest } from '../workspace.js';
10
- import { LOOP, STDIO_PROPERTIES, TOOL_CATALOGUE, runTool, } from '../tools/table.js';
10
+ import { STDIO_PROPERTIES, TOOL_CATALOGUE, instructionsFor, runTool, } from '../tools/table.js';
11
11
  /** The sentence the stdio rows add, because only here is there a `workspace` to name. */
12
12
  const WORKSPACE_SENTENCE = 'Every tool takes the same optional `workspace`; omit it to use the workspace this server was started with, or .yarramate/workspace.yaml under its working directory.';
13
13
  const CONVENTIONAL_WORKSPACE = join('.yarramate', 'workspace.yaml');
@@ -236,7 +236,7 @@ export const handleRequest = (request, context = { cwd: process.cwd(), workspace
236
236
  protocolVersion: '2025-06-18',
237
237
  capabilities: { tools: {} },
238
238
  serverInfo: { name: 'yarramate', version: packageVersion },
239
- instructions: `The architecture record of a YarraMate workspace. The native documents in the repository are canonical; every read renders them, and yarramate_apply is the one write, the same atomic batch the CLI lands. ${LOOP} ${WORKSPACE_SENTENCE}`,
239
+ instructions: `${instructionsFor()} ${WORKSPACE_SENTENCE}`,
240
240
  });
241
241
  return;
242
242
  }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * White-labelling (#546, ADR 0158): one value, set once by a host, that
3
+ * names the product on every surface a consumer's users see - the editor
4
+ * shell, the tool list an agent reads, the workbook's cover sheet and the
5
+ * LikeC4 banner. Nothing else changes: record formats, diagnostic codes and
6
+ * the wire protocol are contracts, not branding, and stay `yarramate/...`
7
+ * and `YM...`. Absent, every surface reads exactly as it always has.
8
+ *
9
+ * Pure: no imports, so it sits under every entry (`yarramate/tools`,
10
+ * `yarramate/workbook`, `yarramate/visual-app`) without weight.
11
+ */
12
+ export type BrandingLogo =
13
+ /** Inline markup the host wrote; rendered as the host's own SVG. */
14
+ {
15
+ readonly svg: string;
16
+ }
17
+ /** An address the page fetches; rendered as an image. */
18
+ | {
19
+ readonly url: string;
20
+ };
21
+ export interface Branding {
22
+ /** "ApertureX", "Halcyon Architecture". Required: a brand without a name is not one. */
23
+ readonly productName: string;
24
+ /**
25
+ * For tight chrome: beside the logo in the brand mark, and in the
26
+ * authority line ("Checked Halcyon model"). Defaults to `productName`.
27
+ * `null` draws the logo alone, for a wordmark that already says the name.
28
+ */
29
+ readonly shortName?: string | null;
30
+ /** Beside the title in the editor shell. Nothing is drawn without one. */
31
+ readonly logo?: BrandingLogo;
32
+ /**
33
+ * One CSS colour for the chrome - the authority mark, the notices, the
34
+ * changeset controls - never the notation: what a node or an edge looks
35
+ * like is the style preset's, and a comparison's added/removed marks keep
36
+ * their own tokens.
37
+ */
38
+ readonly accent?: string;
39
+ /** Where the brand mark links. Without it the mark is text, not a link. */
40
+ readonly docsUrl?: string;
41
+ /**
42
+ * The line under the product name, on the editor strip, the workbook's
43
+ * cover sheet and the LikeC4 banner. Unset: "Powered by yarramate". A
44
+ * string replaces it; `null` removes it, and with it every other mention
45
+ * of the engine those surfaces make.
46
+ */
47
+ readonly vendorLine?: string | null;
48
+ /**
49
+ * The prefix of the tool names an agent reads: `acme` publishes
50
+ * `acme_design`, `acme_apply`, ... Default `yarramate`. An instruction
51
+ * written for `yarramate_design` will not find `acme_design`, so a host
52
+ * that re-prefixes owns its own agent instructions.
53
+ */
54
+ readonly toolPrefix?: string;
55
+ }
56
+ /** `Branding` with every default applied, which is what the surfaces read. */
57
+ export interface ResolvedBranding {
58
+ readonly productName: string;
59
+ /** `null` when the mark is the logo alone; the authority line then says `productName`. */
60
+ readonly shortName: string | null;
61
+ readonly logo?: BrandingLogo;
62
+ readonly accent?: string;
63
+ readonly docsUrl?: string;
64
+ /** `null` when there is none to show. */
65
+ readonly vendorLine: string | null;
66
+ readonly toolPrefix: string;
67
+ /** False is the unbranded product: every surface as it was before #546. */
68
+ readonly branded: boolean;
69
+ }
70
+ export declare const YARRAMATE_PRODUCT_NAME = "YarraMate";
71
+ export declare const YARRAMATE_TOOL_PREFIX = "yarramate";
72
+ export declare const DEFAULT_VENDOR_LINE = "Powered by yarramate";
73
+ /**
74
+ * Applies the defaults. `undefined` is the unbranded product. A value with
75
+ * a blank `productName` or a `toolPrefix` no MCP client could publish is a
76
+ * host's configuration error and throws, at mount or serve time, rather
77
+ * than reaching a person as a blank name or an agent as a broken tool list.
78
+ */
79
+ export declare const resolveBranding: (branding?: Branding) => ResolvedBranding;
80
+ /**
81
+ * The product name as an identifier segment: the LikeC4 project name is
82
+ * `<slug>-<project id>`, `yarramate-…` unbranded. Lower-case letters,
83
+ * digits and single hyphens; a name with nothing usable in it falls back
84
+ * to the engine's own slug rather than producing an empty segment.
85
+ */
86
+ export declare const brandSlug: (branding: ResolvedBranding) => string;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * White-labelling (#546, ADR 0158): one value, set once by a host, that
3
+ * names the product on every surface a consumer's users see - the editor
4
+ * shell, the tool list an agent reads, the workbook's cover sheet and the
5
+ * LikeC4 banner. Nothing else changes: record formats, diagnostic codes and
6
+ * the wire protocol are contracts, not branding, and stay `yarramate/...`
7
+ * and `YM...`. Absent, every surface reads exactly as it always has.
8
+ *
9
+ * Pure: no imports, so it sits under every entry (`yarramate/tools`,
10
+ * `yarramate/workbook`, `yarramate/visual-app`) without weight.
11
+ */
12
+ export const YARRAMATE_PRODUCT_NAME = 'YarraMate';
13
+ export const YARRAMATE_TOOL_PREFIX = 'yarramate';
14
+ export const DEFAULT_VENDOR_LINE = 'Powered by yarramate';
15
+ /** What an MCP client accepts in a tool name, applied to the prefix alone. */
16
+ const TOOL_PREFIX = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
17
+ const UNBRANDED = {
18
+ productName: YARRAMATE_PRODUCT_NAME,
19
+ shortName: YARRAMATE_PRODUCT_NAME,
20
+ vendorLine: null,
21
+ toolPrefix: YARRAMATE_TOOL_PREFIX,
22
+ branded: false,
23
+ };
24
+ /**
25
+ * Applies the defaults. `undefined` is the unbranded product. A value with
26
+ * a blank `productName` or a `toolPrefix` no MCP client could publish is a
27
+ * host's configuration error and throws, at mount or serve time, rather
28
+ * than reaching a person as a blank name or an agent as a broken tool list.
29
+ */
30
+ export const resolveBranding = (branding) => {
31
+ if (branding === undefined)
32
+ return UNBRANDED;
33
+ const productName = branding.productName.trim();
34
+ if (productName === '') {
35
+ throw new TypeError('branding.productName must not be blank');
36
+ }
37
+ const toolPrefix = branding.toolPrefix ?? YARRAMATE_TOOL_PREFIX;
38
+ if (!TOOL_PREFIX.test(toolPrefix)) {
39
+ throw new TypeError(`branding.toolPrefix "${toolPrefix}" must be letters, digits and hyphens, starting with a letter or digit`);
40
+ }
41
+ const shortName = branding.shortName === null ? null : branding.shortName?.trim();
42
+ const vendorLine = branding.vendorLine === undefined
43
+ ? DEFAULT_VENDOR_LINE
44
+ : branding.vendorLine === null || branding.vendorLine.trim() === ''
45
+ ? null
46
+ : branding.vendorLine.trim();
47
+ return {
48
+ productName,
49
+ shortName: shortName === null
50
+ ? null
51
+ : shortName === undefined || shortName === ''
52
+ ? productName
53
+ : shortName,
54
+ ...(branding.logo === undefined ? {} : { logo: branding.logo }),
55
+ ...(branding.accent === undefined ? {} : { accent: branding.accent }),
56
+ ...(branding.docsUrl === undefined ? {} : { docsUrl: branding.docsUrl }),
57
+ vendorLine,
58
+ toolPrefix,
59
+ branded: true,
60
+ };
61
+ };
62
+ /**
63
+ * The product name as an identifier segment: the LikeC4 project name is
64
+ * `<slug>-<project id>`, `yarramate-…` unbranded. Lower-case letters,
65
+ * digits and single hyphens; a name with nothing usable in it falls back
66
+ * to the engine's own slug rather than producing an empty segment.
67
+ */
68
+ export const brandSlug = (branding) => {
69
+ if (!branding.branded)
70
+ return YARRAMATE_TOOL_PREFIX;
71
+ // Split on the runs and join what is left: linear, where a trim by
72
+ // `^-+|-+$` is polynomial on a name that is mostly hyphens (CodeQL
73
+ // js/polynomial-redos, the rule that bit #547's walker too).
74
+ const slug = (branding.shortName ?? branding.productName)
75
+ .toLowerCase()
76
+ .split(/[^a-z0-9]+/)
77
+ .filter((part) => part !== '')
78
+ .join('-');
79
+ return slug === '' ? YARRAMATE_TOOL_PREFIX : slug;
80
+ };
@@ -157,6 +157,7 @@ export const exportLikeC4 = (workspace, project) => guarded(() => {
157
157
  return held === undefined ? undefined : { path, source: held.source };
158
158
  },
159
159
  requireMappedRelationships: false,
160
+ ...(workspace.branding === undefined ? {} : { branding: workspace.branding }),
160
161
  });
161
162
  if (!exported.ok)
162
163
  return failed(exported.diagnostics);
@@ -185,7 +186,7 @@ export const exportWorkbook = (workspace, projection) => guarded(() => {
185
186
  ...compiled.profileContext.relationshipKindLineages.keys(),
186
187
  ].sort(),
187
188
  statuses: ['planned', 'current', 'retired'],
188
- });
189
+ }, workspace.branding);
189
190
  const stem = evaluated.result.projection.split('@')[0] ?? 'workbook';
190
191
  return {
191
192
  ok: true,
@@ -1,5 +1,6 @@
1
1
  import type { WorkspaceSource } from '../compiler.js';
2
2
  import type { ToolWorkspace } from './workspace.js';
3
+ import { type Branding } from '../branding.js';
3
4
  /**
4
5
  * The tool surface, once (ADR 0156). The stdio adapter and a hosted server
5
6
  * publish these rows; `runTool` answers a call over a store, and both
@@ -7,7 +8,18 @@ import type { ToolWorkspace } from './workspace.js';
7
8
  * the network read the same names, the same schemas, the same sentences,
8
9
  * and get the same text back.
9
10
  */
10
- export type ToolName = 'yarramate_ask' | 'yarramate_design' | 'yarramate_apply' | 'yarramate_check' | 'yarramate_reconcile' | 'yarramate_export';
11
+ export declare const TOOL_VERBS: readonly ['ask', 'design', 'apply', 'check', 'reconcile', 'export'];
12
+ export type ToolVerb = (typeof TOOL_VERBS)[number];
13
+ /**
14
+ * A published name: the prefix a host chose, an underscore, the verb. The
15
+ * prefix is branding (#546, ADR 0158); the verb is the contract, and
16
+ * `runTool` dispatches on it alone.
17
+ */
18
+ export type ToolNameFor<P extends string> = `${P}_${ToolVerb}`;
19
+ export type ToolName = ToolNameFor<typeof YARRAMATE_PREFIX>;
20
+ declare const YARRAMATE_PREFIX = "yarramate";
21
+ /** The verb behind a name of any prefix; `undefined` for a name that is not a tool's. */
22
+ export declare const toolVerbOf: (name: string) => ToolVerb | undefined;
11
23
  /**
12
24
  * One row per tool. Generic over the name so a host that adds tools of its
13
25
  * own builds `[...TOOL_CATALOGUE, own]` as `ToolDefinition<string>[]` with
@@ -33,7 +45,13 @@ export interface ToolDefinition<N extends string = ToolName> {
33
45
  * for the first time has never seen the skill file; the tool list is the
34
46
  * only place it learns that design asks, apply lands, and design asks again.
35
47
  */
36
- export declare const LOOP = "The loop: call yarramate_design for the top open question, answer it with the person, land the answer with yarramate_apply, then call yarramate_design again.";
48
+ export declare const loopFor: (branding?: Branding) => string;
49
+ export declare const LOOP: string;
50
+ /**
51
+ * The `initialize` instructions a server publishes, without the stdio
52
+ * adapter's sentence about `workspace`: the record, the one write, the loop.
53
+ */
54
+ export declare const instructionsFor: (branding?: Branding) => string;
37
55
  /**
38
56
  * The two argument properties that exist only where a filesystem does:
39
57
  * `workspace` (which manifest) and `out` (where export writes). The stdio
@@ -42,6 +60,12 @@ export declare const LOOP = "The loop: call yarramate_design for the top open qu
42
60
  * words.
43
61
  */
44
62
  export declare const STDIO_PROPERTIES: Readonly<Record<'workspace' | 'out', Record<string, unknown>>>;
63
+ /**
64
+ * The rows for a host's branding: the prefix in every name, in the loop
65
+ * sentence and wherever a description names a sibling tool. Unbranded, or
66
+ * branded without a `toolPrefix`, this is `TOOL_CATALOGUE` row for row.
67
+ */
68
+ export declare const toolCatalogueFor: (branding?: Branding) => readonly ToolDefinition<string>[];
45
69
  export declare const TOOL_CATALOGUE: readonly ToolDefinition<ToolName>[];
46
70
  export interface ToolFile {
47
71
  /** Relative, `/`-separated, as the CLI would write it under `out`. */
@@ -78,8 +102,13 @@ export type ToolOutcome = {
78
102
  * the function the row names, renders exactly the text the stdio adapter
79
103
  * returns for the same call. `yarramate_reconcile` answers `ok: false`
80
104
  * with the row's `unavailable` line.
105
+ *
106
+ * `name` may carry any prefix (#546): the verb after the last underscore is
107
+ * what dispatches, and a refusal names the tool by the name it was called
108
+ * by, so an agent reading `acme_export` in its tool list reads `acme_export`
109
+ * in the refusal. A name with no tool verb is refused, never thrown.
81
110
  */
82
- export declare const runTool: (name: ToolName, input: Record<string, unknown>, workspace: ToolWorkspace) => ToolOutcome;
111
+ export declare const runTool: (name: string, input: Record<string, unknown>, workspace: ToolWorkspace) => ToolOutcome;
83
112
  /** The files a text kind would write under `out`, for a caller with a filesystem. */
84
113
  export declare const filesOf: (outcome: ToolOutcome) => readonly ToolFile[];
85
114
  export type { WorkspaceSource };