@bendyline/docblocks-cli 2.1.2 → 2.2.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.
package/dist/bin.js CHANGED
@@ -4161,258 +4161,13 @@ var init_progress = __esm({
4161
4161
  }
4162
4162
  });
4163
4163
 
4164
- // src/mcp/revision-service.ts
4165
- import { createHash as createHash7 } from "crypto";
4166
- import {
4167
- DOCBLOCKS_MCP_WIRE_VERSION as DOCBLOCKS_MCP_WIRE_VERSION5,
4168
- MCP_WIRE_LIMITS as MCP_WIRE_LIMITS7,
4169
- parseDocumentRevisionResult
4170
- } from "@bendyline/docblocks/mcp";
4171
- async function reviseDocumentArtifact(artifacts, documents, request, signal) {
4172
- throwIfAborted5(signal);
4173
- const parentArtifact = await artifacts.get(request.artifactUri, signal);
4174
- if (parentArtifact.sha256 !== request.expectedSha256) {
4175
- throw revisionError(
4176
- "conflict",
4177
- `Revision precondition failed: expected ${request.expectedSha256}, but the parent artifact is ${parentArtifact.sha256}.`,
4178
- `Use expectedSha256 "${parentArtifact.sha256}" only if this is still the intended parent artifact.`
4179
- );
4180
- }
4181
- if (parentArtifact.format !== "dbk") {
4182
- throw revisionError(
4183
- "invalid-revision-source",
4184
- `Artifact-native block revision requires a DBK parent, not ${parentArtifact.format}.`,
4185
- "Stage Markdown and assets with create_document_bundle, or convert the source to DBK first."
4186
- );
4187
- }
4188
- if (new Set(request.edits.map((edit) => edit.blockId)).size !== request.edits.length) {
4189
- throw revisionError(
4190
- "duplicate-block-edit",
4191
- "Each block id may be revised at most once per request.",
4192
- "Combine changes to the same block into one replacement fragment."
4193
- );
4194
- }
4195
- const totalReplacementCharacters = request.edits.reduce(
4196
- (sum, edit) => sum + edit.markdown.length,
4197
- 0
4198
- );
4199
- if (totalReplacementCharacters > MCP_WIRE_LIMITS7.documentCharacters) {
4200
- throw revisionError(
4201
- "revision-too-large",
4202
- "Combined replacement Markdown exceeds the MCP document character limit.",
4203
- "Use fewer or smaller block replacements."
4204
- );
4205
- }
4206
- const prepared = await documents.prepare({ kind: "artifact", uri: parentArtifact.uri }, signal);
4207
- const { flattenBlocks } = await import("@bendyline/squisq/doc");
4208
- const blocks = flattenBlocks(prepared.doc.blocks);
4209
- const ranges = await computeBlockSourceRanges(blocks, prepared.markdown.length, signal);
4210
- const blockRecords = indexEditableBlocks(blocks, ranges);
4211
- const replacements = [];
4212
- for (let index = 0; index < request.edits.length; index += 1) {
4213
- throwIfAborted5(signal);
4214
- const edit = request.edits[index];
4215
- const record = blockRecords.get(edit.blockId);
4216
- if (!record) {
4217
- throw revisionError(
4218
- "block-not-found",
4219
- `Block "${edit.blockId}" is not an editable heading block in the parent artifact.`,
4220
- "Call inspect_document on the exact parent artifact and use a returned block id with a non-null sourceRange."
4221
- );
4222
- }
4223
- const replacementMarkdown = await canonicalReplacement(
4224
- edit.markdown,
4225
- record.block,
4226
- edit.blockId
4227
- );
4228
- const before = prepared.markdown.slice(record.start, record.end);
4229
- if (replacementMarkdown === before) {
4230
- throw revisionError(
4231
- "no-op-block-edit",
4232
- `Replacement for block "${edit.blockId}" does not change its heading or body.`,
4233
- "Omit no-op block edits from the revision request."
4234
- );
4235
- }
4236
- replacements.push({
4237
- blockId: edit.blockId,
4238
- start: record.start,
4239
- end: record.end,
4240
- markdown: replacementMarkdown,
4241
- applied: {
4242
- kind: "replace_block",
4243
- blockId: edit.blockId,
4244
- beforeSha256: sha256(Buffer.from(before, "utf8")),
4245
- afterSha256: sha256(Buffer.from(replacementMarkdown, "utf8"))
4246
- }
4247
- });
4248
- if ((index + 1) % 16 === 0) await yieldForCancellation2(signal);
4249
- }
4250
- const revisedMarkdown = applyReplacements(prepared.markdown, replacements);
4251
- if (revisedMarkdown.length > MCP_WIRE_LIMITS7.documentCharacters) {
4252
- throw revisionError(
4253
- "revision-too-large",
4254
- "The revised Markdown exceeds the MCP document character limit.",
4255
- "Use smaller block replacements or split the document before revising it."
4256
- );
4257
- }
4258
- if (revisedMarkdown === prepared.markdown) {
4259
- throw revisionError(
4260
- "no-op-revision",
4261
- "The requested block replacements do not change the document.",
4262
- "Submit only replacements that change heading or body Markdown."
4263
- );
4264
- }
4265
- const [{ parseMarkdown: parseMarkdown2 }, { markdownToDoc: markdownToDoc2, flattenBlocks: flattenRevisedBlocks }] = await Promise.all([import("@bendyline/squisq/markdown"), import("@bendyline/squisq/doc")]);
4266
- const markdownDoc = parseMarkdown2(revisedMarkdown);
4267
- const doc = markdownToDoc2(markdownDoc, { defaultTemplate: "content", autoTemplates: false });
4268
- const revisedIds = new Set(
4269
- flattenRevisedBlocks(doc.blocks).map((block) => toWireIdentifier(block.id, "block"))
4270
- );
4271
- for (const replacement of replacements) {
4272
- if (!revisedIds.has(replacement.blockId)) {
4273
- throw revisionError(
4274
- "unstable-block-id",
4275
- `Replacement for block "${replacement.blockId}" did not preserve its stable id.`,
4276
- "Keep the replacement heading id unchanged and retry from the parent artifact."
4277
- );
4278
- }
4279
- }
4280
- throwIfAborted5(signal);
4281
- await prepared.container.writeDocument(revisedMarkdown);
4282
- const revisionSourceSha256 = createHash7("sha256").update("docblocks-artifact-revision-v1\0", "utf8").update(parentArtifact.sha256, "utf8").update("\0", "utf8").update(revisedMarkdown, "utf8").digest("hex");
4283
- const [conversion] = await convertPreparedDocument(
4284
- artifacts,
4285
- {
4286
- ...prepared,
4287
- markdown: revisedMarkdown,
4288
- markdownDoc,
4289
- doc,
4290
- sourceSha256: revisionSourceSha256
4291
- },
4292
- { targets: [{ format: "dbk", fidelity: "semantic" }] },
4293
- signal
4294
- );
4295
- if (!conversion) throw new Error("Document revision produced no DBK artifact");
4296
- const result = {
4297
- version: DOCBLOCKS_MCP_WIRE_VERSION5,
4298
- kind: "revision",
4299
- parentArtifact,
4300
- artifact: conversion.artifact,
4301
- edits: replacements.map((replacement) => replacement.applied),
4302
- diagnostics: conversion.diagnostics
4303
- };
4304
- const parsed = parseDocumentRevisionResult(result);
4305
- if (!parsed) throw new Error("Document revision produced an invalid MCP result");
4306
- return parsed;
4307
- }
4308
- function indexEditableBlocks(blocks, ranges) {
4309
- const indexed = /* @__PURE__ */ new Map();
4310
- const ambiguous = /* @__PURE__ */ new Set();
4311
- for (let index = 0; index < blocks.length; index += 1) {
4312
- const block = blocks[index];
4313
- const range = ranges[index];
4314
- if (!block || !range || !block.sourceHeading) continue;
4315
- const wireId = toWireIdentifier(block.id, "block");
4316
- if (indexed.has(wireId)) {
4317
- indexed.delete(wireId);
4318
- ambiguous.add(wireId);
4319
- } else if (!ambiguous.has(wireId)) {
4320
- indexed.set(wireId, { block, start: range.start, end: range.end });
4321
- }
4322
- }
4323
- return indexed;
4324
- }
4325
- async function canonicalReplacement(markdown, target, wireBlockId) {
4326
- const { parseMarkdown: parseMarkdown2, stringifyMarkdown } = await import("@bendyline/squisq/markdown");
4327
- const fragment = parseMarkdown2(markdown);
4328
- if (fragment.frontmatter && Object.keys(fragment.frontmatter).length > 0) {
4329
- throw revisionError(
4330
- "invalid-block-replacement",
4331
- `Replacement for block "${wireBlockId}" cannot contain frontmatter.`,
4332
- "Provide one heading and its direct body only."
4333
- );
4334
- }
4335
- const headings = fragment.children.filter(
4336
- (node) => node.type === "heading"
4337
- );
4338
- const heading = headings[0];
4339
- if (!heading || fragment.children[0] !== heading || headings.length !== 1) {
4340
- throw revisionError(
4341
- "invalid-block-replacement",
4342
- `Replacement for block "${wireBlockId}" must begin with exactly one heading and cannot contain nested headings.`,
4343
- "Use a complete fragment such as `# Heading {[content]}\n\nReplacement body`."
4344
- );
4345
- }
4346
- const sourceHeading = target.sourceHeading;
4347
- if (!sourceHeading) throw new Error("Editable replacement target has no source heading");
4348
- if (heading.depth !== sourceHeading.depth) {
4349
- throw revisionError(
4350
- "invalid-block-replacement",
4351
- `Replacement for block "${wireBlockId}" must keep heading depth ${sourceHeading.depth}.`,
4352
- `Begin the replacement with ${"#".repeat(sourceHeading.depth)} followed by the heading text.`
4353
- );
4354
- }
4355
- if (heading.attributes?.id && heading.attributes.id !== target.id) {
4356
- throw revisionError(
4357
- "block-id-change-not-allowed",
4358
- `Replacement for block "${wireBlockId}" cannot change its id to "${heading.attributes.id}".`,
4359
- `Omit the explicit id or keep {#${target.id}}.`
4360
- );
4361
- }
4362
- const sourceAttributes = sourceHeading.attributes;
4363
- const replacementAttributes = heading.attributes;
4364
- const attributes = {
4365
- ...sourceAttributes,
4366
- ...replacementAttributes,
4367
- id: target.id,
4368
- ...replacementAttributes?.classes === void 0 && sourceAttributes?.classes ? { classes: sourceAttributes.classes } : {},
4369
- ...replacementAttributes?.params === void 0 && sourceAttributes?.params ? { params: sourceAttributes.params } : {},
4370
- ...replacementAttributes?.blockMeta === void 0 && sourceAttributes?.blockMeta ? { blockMeta: sourceAttributes.blockMeta } : {},
4371
- ...replacementAttributes?.metadata === void 0 && sourceAttributes?.metadata ? { metadata: sourceAttributes.metadata } : {}
4372
- };
4373
- const pinnedHeading = {
4374
- ...heading,
4375
- attributes,
4376
- templateAnnotation: heading.templateAnnotation ?? sourceHeading.templateAnnotation
4377
- };
4378
- return stringifyMarkdown({
4379
- type: "document",
4380
- children: [pinnedHeading, ...fragment.children.slice(1)]
4381
- });
4382
- }
4383
- function applyReplacements(source, replacements) {
4384
- let revised = source;
4385
- const descending = [...replacements].sort((left, right) => right.start - left.start);
4386
- for (const replacement of descending) {
4387
- revised = revised.slice(0, replacement.start) + replacement.markdown + revised.slice(replacement.end);
4388
- }
4389
- return revised;
4390
- }
4391
- function revisionError(code, message, hint) {
4392
- return Object.assign(new Error(message), { code, hint, retryable: false });
4393
- }
4394
- async function yieldForCancellation2(signal) {
4395
- await new Promise((resolve4) => setImmediate(resolve4));
4396
- throwIfAborted5(signal);
4397
- }
4398
- var init_revision_service = __esm({
4399
- "src/mcp/revision-service.ts"() {
4400
- "use strict";
4401
- init_conversion_service();
4402
- init_document_service();
4403
- init_intelligence();
4404
- init_output_bounds();
4405
- }
4406
- });
4407
-
4408
4164
  // src/mcp/agentic-tools.ts
4409
4165
  import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
4410
4166
  import { z } from "zod";
4411
4167
  import {
4412
- MCP_WIRE_LIMITS as MCP_WIRE_LIMITS8,
4168
+ MCP_WIRE_LIMITS as MCP_WIRE_LIMITS7,
4413
4169
  parseComparisonResult,
4414
4170
  parseConversionResult as parseConversionResult2,
4415
- parseDocumentRevisionResult as parseDocumentRevisionResult2,
4416
4171
  parseDocumentSource,
4417
4172
  parseInspectionResult,
4418
4173
  parseMaterializationOptions,
@@ -4424,7 +4179,6 @@ import {
4424
4179
  bundleDocumentSourceSchema,
4425
4180
  DOCBLOCKS_MCP_TOOL_OUTPUT_SCHEMAS,
4426
4181
  documentSourceSchema,
4427
- documentRevisionRequestSchema,
4428
4182
  formatInputSchema,
4429
4183
  materializationOptionsSchema
4430
4184
  } from "@bendyline/docblocks/mcp/zod";
@@ -4520,7 +4274,7 @@ function registerAgenticTools(server, context) {
4520
4274
  server.registerTool(
4521
4275
  "create_document_bundle",
4522
4276
  {
4523
- description: "Stage authored Markdown and authority-scoped assets as an immutable DBK artifact. Use the returned artifact URI directly with validate_document, preview_document, and convert_document; no local Markdown file or invented root id is required.",
4277
+ description: "Optionally stage Markdown plus authority-scoped assets as a reusable immutable DBK artifact when the same bundle will feed several operations. For normal authoring, pass complete Markdown or a bundle source directly to convert_document.",
4524
4278
  inputSchema: z.object({ source: bundleDocumentSourceSchema }).strict(),
4525
4279
  outputSchema: DOCBLOCKS_MCP_TOOL_OUTPUT_SCHEMAS.create_document_bundle,
4526
4280
  annotations: ARTIFACT_CREATING
@@ -4552,38 +4306,6 @@ function registerAgenticTools(server, context) {
4552
4306
  }
4553
4307
  }
4554
4308
  );
4555
- server.registerTool(
4556
- "revise_document",
4557
- {
4558
- description: "Replace selected heading blocks in an immutable DBK artifact without resending the full document. Requires the parent artifact SHA-256, preserves block ids and child blocks, and returns a new DBK artifact without mutating the parent.",
4559
- inputSchema: documentRevisionRequestSchema,
4560
- outputSchema: DOCBLOCKS_MCP_TOOL_OUTPUT_SCHEMAS.revise_document,
4561
- annotations: ARTIFACT_CREATING
4562
- },
4563
- async (request, extra) => {
4564
- try {
4565
- return await context.runOperation(extra.signal, async (operationSignal) => {
4566
- const documents = new DocumentService(await context.authority, context.artifacts);
4567
- const result = await reviseDocumentArtifact(
4568
- context.artifacts,
4569
- documents,
4570
- request,
4571
- operationSignal
4572
- );
4573
- requireWire(parseDocumentRevisionResult2(result), "document revision");
4574
- return {
4575
- content: [
4576
- { type: "text", text: JSON.stringify(result) },
4577
- artifactLink(result.artifact)
4578
- ],
4579
- structuredContent: asStructuredContent(successResult(result))
4580
- };
4581
- });
4582
- } catch (caught) {
4583
- return errorResult(caught, "transform", "dbk", extra.signal);
4584
- }
4585
- }
4586
- );
4587
4309
  server.registerTool(
4588
4310
  "save_artifact",
4589
4311
  {
@@ -4842,15 +4564,17 @@ function registerAuthoringGuideResource(server) {
4842
4564
  import("@bendyline/squisq/transform")
4843
4565
  ]);
4844
4566
  const guide = {
4845
- version: 3,
4567
+ version: 6,
4846
4568
  workflow: [
4847
- "author complete Markdown with annotations bound to headings; ordinary headings default to content",
4848
- "keep Markdown inline or stage Markdown plus assets with create_document_bundle",
4849
- "inspect_document and validate_document before visual optimization",
4850
- "for a staged DBK, use revise_document with inspected block ids and the exact parent SHA-256 for targeted repairs",
4851
- "preview_document and inspect previewBasis before treating images as source renders, reconstructed imports, or native extraction",
4852
- "replace selected content blocks with compatible visual templates and preview again",
4853
- "convert_document to one or more immutable artifacts",
4569
+ "treat supplied facts as a closed evidence set; label calculations, assumptions, hypotheses, recommendations, and examples; do not present causal links, rhetorical performance labels, superlatives, sole causes, targets, capabilities, owners, dates, channels, or operational details as established facts unless supplied",
4570
+ "when the requested genre needs unsupplied roles, gates, timelines, channels, or procedures, add one explicit proposed operating model scope note that applies to those details, then complete the requested element",
4571
+ "author complete Squisq-compatible Markdown with annotations bound to headings; ordinary headings default to the loss-averse content template",
4572
+ "for PPTX, use exactly one level-one Markdown heading per slide and no level-two through level-six headings because every heading becomes a slide by default",
4573
+ "by default, pass the complete Markdown\u2014or a bundle source when assets are needed\u2014directly to convert_document; revise by editing the complete Markdown and converting again",
4574
+ "use create_document_bundle only when a reusable staged DBK materially avoids repeating a large Markdown-and-asset bundle across several operations",
4575
+ "use inspect_document, validate_document, and preview_document when their semantic, diagnostic, or visual evidence is useful; they are review tools rather than required phases",
4576
+ "for visual polish, replace selected content blocks with compatible visual templates while preserving required content",
4577
+ "convert_document creates one or more immutable artifacts from the authoritative complete source",
4854
4578
  "save_artifact only when a durable file is required"
4855
4579
  ],
4856
4580
  markdownAnnotation: '# Heading {[templateId key="value"]}',
@@ -4865,14 +4589,14 @@ function registerAuthoringGuideResource(server) {
4865
4589
  fidelityByFormat: MCP_FORMAT_FIDELITIES,
4866
4590
  formats: boundedFormatCapabilities(),
4867
4591
  templates,
4868
- themes: schemaModule.getThemeSummaries().slice(0, MCP_WIRE_LIMITS8.arrayEntries).map((theme) => ({
4592
+ themes: schemaModule.getThemeSummaries().slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((theme) => ({
4869
4593
  id: requireWireIdentifier(theme.id, "theme id"),
4870
- name: boundWireText(theme.name, MCP_WIRE_LIMITS8.labelCharacters, theme.id),
4594
+ name: boundWireText(theme.name, MCP_WIRE_LIMITS7.labelCharacters, theme.id),
4871
4595
  description: boundWireText(theme.description ?? "")
4872
4596
  })),
4873
- transformStyles: transformModule.getTransformStyleSummaries().slice(0, MCP_WIRE_LIMITS8.arrayEntries).map((style) => ({
4597
+ transformStyles: transformModule.getTransformStyleSummaries().slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((style) => ({
4874
4598
  id: requireWireIdentifier(style.id, "transform style id"),
4875
- name: boundWireText(style.name, MCP_WIRE_LIMITS8.labelCharacters, style.id),
4599
+ name: boundWireText(style.name, MCP_WIRE_LIMITS7.labelCharacters, style.id),
4876
4600
  description: boundWireText(style.description)
4877
4601
  }))
4878
4602
  };
@@ -4892,7 +4616,7 @@ function registerTemplateTools(server, context) {
4892
4616
  server.registerTool(
4893
4617
  "get_authoring_context",
4894
4618
  {
4895
- description: "Get the complete linked-Squisq authoring vocabulary, canonical heading syntax, content-retention behavior, workflow, and optional block recommendations in one call.",
4619
+ description: "Get a compact agent-facing authoring contract plus the complete linked-Squisq catalog in structured content, with optional block recommendations.",
4896
4620
  inputSchema: z.object({
4897
4621
  targetFormat: formatInputSchema.optional(),
4898
4622
  goal: z.enum(["content-first", "visual-polish"]).optional(),
@@ -4944,7 +4668,7 @@ function registerTemplateTools(server, context) {
4944
4668
  const recommendedTemplateIds = goal === "content-first" ? ["content", ...visual.filter((id) => id !== "content")] : visual;
4945
4669
  return {
4946
4670
  blockId: toWireIdentifier(block.id, "block"),
4947
- title: boundNullableWireText(block.title, MCP_WIRE_LIMITS8.labelCharacters),
4671
+ title: boundNullableWireText(block.title, MCP_WIRE_LIMITS7.labelCharacters),
4948
4672
  profile: {
4949
4673
  ...profile,
4950
4674
  hasAsciiDiagram: profile.hasAsciiDiagram ?? false,
@@ -4957,18 +4681,26 @@ function registerTemplateTools(server, context) {
4957
4681
  totalBlocks = blocks.length;
4958
4682
  truncated = recommendations.length < blocks.length;
4959
4683
  }
4960
- return textAndStructured({
4684
+ const payload = {
4961
4685
  goal,
4962
4686
  targetFormat: normalizedTarget,
4963
4687
  defaultTemplateId: "content",
4964
4688
  defaultFidelity: authoringDefaultFidelity(normalizedTarget, goal),
4965
4689
  workflow: [
4966
- "Author complete content with heading-bound annotations; ordinary headings default to content.",
4967
- "Keep Markdown inline or stage Markdown plus assets with create_document_bundle.",
4968
- "Validate the source and repair content-retention, accessibility, and target diagnostics.",
4969
- "For a staged DBK, use revise_document with inspected block ids and the exact parent SHA-256 for targeted repairs.",
4970
- "Preview the bounded visual items and repair overflow before changing layouts.",
4971
- "For visual polish, replace selected content blocks with compatible recommended templates and preview again.",
4690
+ "Treat supplied facts as a closed evidence set. Use temporal or correlational wording unless causality is supplied. Label calculations, assumptions, hypotheses, recommendations, and illustrative examples. Do not infer end-to-end feasibility from one supplied phase duration.",
4691
+ "Audit claims before conversion: causal links, rhetorical labels such as compounding, engine, healthy, strong, or constraint, superlatives, sole-cause claims, targets, capabilities, owners, dates, channels, and operational details must be supplied or explicitly framed as a hypothesis, recommendation, example, or proposal. Do not connect separate metrics, audiences, segments, or workflows unless the relationship is supplied. Prefer observed, coincided with, intended to, or proposed over drove, addresses, protects, or proves. Do not call choices a sequence or capacity allocation unless order, timing, or resource constraints were supplied.",
4692
+ "Complete every requested element without presenting invented policy as established fact. When a requested policy, playbook, or training guide needs unsupplied roles, gates, timelines, channels, or procedures, add one explicit proposed operating model scope note placed before the first such detail so it governs all of them.",
4693
+ "Generic option traits\u2014control, flexibility, vendor support, freed capacity, switching costs\u2014are capability claims: state one only when supplied or labeled Assumption or Judgment, even in table cells and tradeoffs.",
4694
+ "Author complete Squisq-compatible content with heading-bound annotations; ordinary headings default to the loss-averse content template.",
4695
+ normalizedTarget === "pptx" ? "Match every explicitly requested slide count exactly. Use exactly one level-one Markdown heading (#) per slide and no level-two through level-six headings because every heading becomes a slide by default. Target at most 80 words per slide, and use lists, tables, or bold labels for within-slide structure." : "Honor the requested word range and document genre. Prefer connected memo prose for executive decisions and native headings, tables, and checklists for operational documents.",
4696
+ normalizedTarget === "pptx" ? "Make slide one a supported point-of-view thesis, not a generic title or unsupported flourish. For requested choices, state a concrete opportunity cost grounded in the supplied alternatives and name one clearly labeled proposed accountable role per choice. If a tradeoff requires an unsupplied capacity or outcome assumption, label it Assumption or Potential tradeoff rather than stating it as fact." : "Tie each decision implication or comparative judgment to a supplied fact or calculation, or label it Judgment. When accountability is requested but not supplied, name one clearly labeled proposed accountable role per decision or workstream.",
4697
+ "Add decision value without inventing causes: interpret supplied comparisons to baselines, goals, targets, and rankings; use transparent calculations; label any new review cadence or measurement procedure as proposed.",
4698
+ "Before validation and conversion, run a content preflight: count slide sections or document words, verify every requested element, and rewrite or label every unsupported claim.",
4699
+ "Use the complete Markdown as the authoritative source. Pass it\u2014or a bundle source when assets are needed\u2014directly to convert_document, and revise by editing the complete Markdown and converting again.",
4700
+ "Use create_document_bundle only when reusing a large Markdown-and-asset bundle across several review or conversion operations would materially reduce retransmission.",
4701
+ "Use inspect_document or validate_document when semantic structure, content retention, accessibility, or target diagnostics need review; repair actionable findings in the authoritative Markdown.",
4702
+ "Use preview_document when visual evidence is needed, inspect previewBasis, and repair overflow or layout problems in the authoritative Markdown.",
4703
+ normalizedTarget === "pptx" ? "For visual polish, replace selected content blocks with compatible recommended templates; use patterns such as definitionCard for a definition, dataTable for a true table, comparisonBar for supported numeric comparisons, and list for concise steps when the returned catalog supports them. Preserve all required content and preview again." : "For visual polish, use native headings, tables, and checklists where they improve scanning; keep complete-body content when a visual template would discard detail, then preview again.",
4972
4704
  "Convert to immutable artifacts, inspect conversion reports, and save only final durable outputs."
4973
4705
  ],
4974
4706
  syntax: {
@@ -4978,20 +4710,21 @@ function registerTemplateTools(server, context) {
4978
4710
  },
4979
4711
  formats,
4980
4712
  templates,
4981
- themes: schemaModule.getThemeSummaries().slice(0, MCP_WIRE_LIMITS8.arrayEntries).map((theme) => ({
4713
+ themes: schemaModule.getThemeSummaries().slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((theme) => ({
4982
4714
  id: requireWireIdentifier(theme.id, "theme id"),
4983
- name: boundWireText(theme.name, MCP_WIRE_LIMITS8.labelCharacters, theme.id),
4715
+ name: boundWireText(theme.name, MCP_WIRE_LIMITS7.labelCharacters, theme.id),
4984
4716
  description: boundWireText(theme.description ?? "")
4985
4717
  })),
4986
- transformStyles: transformModule.getTransformStyleSummaries().slice(0, MCP_WIRE_LIMITS8.arrayEntries).map((style) => ({
4718
+ transformStyles: transformModule.getTransformStyleSummaries().slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((style) => ({
4987
4719
  id: requireWireIdentifier(style.id, "transform style id"),
4988
- name: boundWireText(style.name, MCP_WIRE_LIMITS8.labelCharacters, style.id),
4720
+ name: boundWireText(style.name, MCP_WIRE_LIMITS7.labelCharacters, style.id),
4989
4721
  description: boundWireText(style.description)
4990
4722
  })),
4991
4723
  recommendations,
4992
4724
  totalBlocks,
4993
4725
  truncated
4994
- });
4726
+ };
4727
+ return textAndStructured(payload, compactAuthoringContextText(payload));
4995
4728
  });
4996
4729
  } catch (caught) {
4997
4730
  return errorResult(caught, "inspect", null, extra.signal);
@@ -5081,7 +4814,7 @@ function registerTemplateTools(server, context) {
5081
4814
  const profile = recommendModule.profileBlockContents(block.contents ?? []);
5082
4815
  return {
5083
4816
  blockId: toWireIdentifier(block.id, "block"),
5084
- title: boundNullableWireText(block.title, MCP_WIRE_LIMITS8.labelCharacters),
4817
+ title: boundNullableWireText(block.title, MCP_WIRE_LIMITS7.labelCharacters),
5085
4818
  profile: {
5086
4819
  ...profile,
5087
4820
  hasAsciiDiagram: profile.hasAsciiDiagram ?? false,
@@ -5180,12 +4913,12 @@ function registerThemeTools(server, context) {
5180
4913
  layouts: (inferred.layouts ?? []).slice(0, 1e3).map((layout, index) => ({
5181
4914
  id: boundWireText(
5182
4915
  layout.name,
5183
- MCP_WIRE_LIMITS8.labelCharacters,
4916
+ MCP_WIRE_LIMITS7.labelCharacters,
5184
4917
  `layout-${index + 1}`
5185
4918
  ),
5186
4919
  name: boundWireText(
5187
4920
  layout.label,
5188
- MCP_WIRE_LIMITS8.labelCharacters,
4921
+ MCP_WIRE_LIMITS7.labelCharacters,
5189
4922
  `Layout ${index + 1}`
5190
4923
  ),
5191
4924
  description: boundWireText(layout.description ?? "")
@@ -5230,21 +4963,21 @@ function registerThemeTools(server, context) {
5230
4963
  layouts: result.layouts.slice(0, 2048).map((layout, index) => ({
5231
4964
  layoutPath: boundWireText(
5232
4965
  layout.layoutPath,
5233
- MCP_WIRE_LIMITS8.pathCharacters,
4966
+ MCP_WIRE_LIMITS7.pathCharacters,
5234
4967
  `ppt/slideLayouts/slideLayout${index + 1}.xml`
5235
4968
  ),
5236
4969
  name: boundWireText(
5237
4970
  layout.name,
5238
- MCP_WIRE_LIMITS8.labelCharacters,
4971
+ MCP_WIRE_LIMITS7.labelCharacters,
5239
4972
  `Layout ${index + 1}`
5240
4973
  ),
5241
- masterName: boundNullableWireText(layout.masterName, MCP_WIRE_LIMITS8.labelCharacters),
5242
- type: boundNullableWireText(layout.typeAttr, MCP_WIRE_LIMITS8.labelCharacters),
4974
+ masterName: boundNullableWireText(layout.masterName, MCP_WIRE_LIMITS7.labelCharacters),
4975
+ type: boundNullableWireText(layout.typeAttr, MCP_WIRE_LIMITS7.labelCharacters),
5243
4976
  slideCount: layout.slideCount,
5244
4977
  verdict: layout.verdict,
5245
4978
  templateId: boundNullableWireText(
5246
4979
  layout.builtinTemplate ?? layout.customTemplate?.name,
5247
- MCP_WIRE_LIMITS8.labelCharacters
4980
+ MCP_WIRE_LIMITS7.labelCharacters
5248
4981
  ),
5249
4982
  notes: boundWireTextArray(layout.notes ?? [], 1e3)
5250
4983
  }))
@@ -5344,7 +5077,7 @@ function registerThemeTools(server, context) {
5344
5077
  const payload = {
5345
5078
  result,
5346
5079
  theme: summarizeTheme(inferred.theme),
5347
- layoutIds: (inferred.layouts ?? []).slice(0, 1e3).map((layout) => boundWireText(layout.name, MCP_WIRE_LIMITS8.labelCharacters)),
5080
+ layoutIds: (inferred.layouts ?? []).slice(0, 1e3).map((layout) => boundWireText(layout.name, MCP_WIRE_LIMITS7.labelCharacters)),
5348
5081
  warnings: boundWireWarnings(inferred.warnings)
5349
5082
  };
5350
5083
  return {
@@ -5401,12 +5134,40 @@ function artifactLink(artifact) {
5401
5134
  async function sendProgress(extra, progress, total, message) {
5402
5135
  await reportMcpProgress(extra, progress, total, message);
5403
5136
  }
5404
- function textAndStructured(payload) {
5137
+ function textAndStructured(payload, text = JSON.stringify(payload, null, 2)) {
5405
5138
  return {
5406
- content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
5139
+ content: [{ type: "text", text }],
5407
5140
  structuredContent: asStructuredContent(successResult(payload))
5408
5141
  };
5409
5142
  }
5143
+ function compactAuthoringContextText(context) {
5144
+ const target = context.targetFormat ?? "unspecified target";
5145
+ const lines = [
5146
+ `DocBlocks authoring contract: ${target}, ${context.goal}.`,
5147
+ `Default template: ${context.defaultTemplateId}. Default fidelity: ${context.defaultFidelity ?? "select for target"}.`,
5148
+ "",
5149
+ "Required workflow:",
5150
+ ...context.workflow.map((step, index) => `${index + 1}. ${step}`),
5151
+ "",
5152
+ `Heading annotation: ${context.syntax.headingAnnotation}`,
5153
+ `Warning: ${context.syntax.standaloneWarning}`,
5154
+ `Templates (${context.templates.length}): ${context.templates.map(({ id }) => id).join(", ")}`,
5155
+ `Themes (${context.themes.length}): ${context.themes.map(({ id }) => id).join(", ")}`,
5156
+ `Transform styles (${context.transformStyles.length}): ${context.transformStyles.map(({ id }) => id).join(", ")}`
5157
+ ];
5158
+ if (context.recommendations.length > 0) {
5159
+ lines.push(
5160
+ `Recommended blocks: ${context.recommendations.map(
5161
+ ({ blockId, recommendedTemplateIds }) => `${blockId} -> ${recommendedTemplateIds.join("/")}`
5162
+ ).join("; ")}`
5163
+ );
5164
+ }
5165
+ lines.push(
5166
+ "",
5167
+ "The complete exact format, template-input, theme, transform, and recommendation catalog is in structuredContent. Use describe_template for focused follow-up when structured content is unavailable."
5168
+ );
5169
+ return lines.join("\n");
5170
+ }
5410
5171
  function asStructuredContent(payload) {
5411
5172
  return payload;
5412
5173
  }
@@ -5419,18 +5180,18 @@ function summarizeTheme(theme) {
5419
5180
  const id = requireWireIdentifier(theme.id, "theme id");
5420
5181
  return {
5421
5182
  id,
5422
- name: boundWireText(theme.name, MCP_WIRE_LIMITS8.labelCharacters, id),
5183
+ name: boundWireText(theme.name, MCP_WIRE_LIMITS7.labelCharacters, id),
5423
5184
  description: boundWireText(theme.description ?? ""),
5424
5185
  colors: {
5425
- primary: boundWireText(theme.colors.primary, MCP_WIRE_LIMITS8.labelCharacters, "#000000"),
5426
- secondary: boundWireText(theme.colors.secondary, MCP_WIRE_LIMITS8.labelCharacters, "#000000"),
5186
+ primary: boundWireText(theme.colors.primary, MCP_WIRE_LIMITS7.labelCharacters, "#000000"),
5187
+ secondary: boundWireText(theme.colors.secondary, MCP_WIRE_LIMITS7.labelCharacters, "#000000"),
5427
5188
  background: boundWireText(
5428
5189
  theme.colors.background,
5429
- MCP_WIRE_LIMITS8.labelCharacters,
5190
+ MCP_WIRE_LIMITS7.labelCharacters,
5430
5191
  "#ffffff"
5431
5192
  ),
5432
- text: boundWireText(theme.colors.text, MCP_WIRE_LIMITS8.labelCharacters, "#000000"),
5433
- highlight: boundWireText(theme.colors.highlight, MCP_WIRE_LIMITS8.labelCharacters, "#000000")
5193
+ text: boundWireText(theme.colors.text, MCP_WIRE_LIMITS7.labelCharacters, "#000000"),
5194
+ highlight: boundWireText(theme.colors.highlight, MCP_WIRE_LIMITS7.labelCharacters, "#000000")
5434
5195
  },
5435
5196
  bodyFont: boundWireText(JSON.stringify(theme.typography.bodyFont) ?? ""),
5436
5197
  titleFont: boundWireText(JSON.stringify(theme.typography.titleFont) ?? "")
@@ -5444,26 +5205,26 @@ async function authoringTemplateCatalog() {
5444
5205
  TEMPLATE_METADATA
5445
5206
  } = await import("@bendyline/squisq/doc");
5446
5207
  const authoring = TEMPLATE_AUTHORING_METADATA;
5447
- return getAvailableTemplates().slice(0, MCP_WIRE_LIMITS8.arrayEntries).map((id) => {
5208
+ return getAvailableTemplates().slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((id) => {
5448
5209
  const metadata = TEMPLATE_METADATA[id];
5449
5210
  const behavior = authoring[id];
5450
5211
  if (!behavior) throw new Error(`Template "${id}" has no authoring metadata`);
5451
- const inputs = (TEMPLATE_INPUT_DESCRIPTORS[id] ?? []).slice(0, MCP_WIRE_LIMITS8.arrayEntries).map((input) => ({
5212
+ const inputs = (TEMPLATE_INPUT_DESCRIPTORS[id] ?? []).slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((input) => ({
5452
5213
  key: requireWireIdentifier(input.key, "template input key"),
5453
5214
  description: boundWireText(input.description),
5454
- type: boundWireText(input.coerce ?? "string", MCP_WIRE_LIMITS8.labelCharacters, "string"),
5215
+ type: boundWireText(input.coerce ?? "string", MCP_WIRE_LIMITS7.labelCharacters, "string"),
5455
5216
  required: input.required ?? false,
5456
5217
  values: boundWireTextArray(
5457
5218
  input.values ?? [],
5458
- MCP_WIRE_LIMITS8.arrayEntries,
5459
- MCP_WIRE_LIMITS8.labelCharacters
5219
+ MCP_WIRE_LIMITS7.arrayEntries,
5220
+ MCP_WIRE_LIMITS7.labelCharacters
5460
5221
  ),
5461
- valueHint: boundNullableWireText(input.valueHint, MCP_WIRE_LIMITS8.labelCharacters)
5222
+ valueHint: boundNullableWireText(input.valueHint, MCP_WIRE_LIMITS7.labelCharacters)
5462
5223
  }));
5463
5224
  const required = inputs.filter((input) => input.required).map((input) => `${input.key}="\u2026"`).join(" ");
5464
5225
  return {
5465
5226
  id: requireWireIdentifier(id, "template id"),
5466
- label: boundWireText(metadata?.label ?? id, MCP_WIRE_LIMITS8.labelCharacters, id),
5227
+ label: boundWireText(metadata?.label ?? id, MCP_WIRE_LIMITS7.labelCharacters, id),
5467
5228
  description: boundWireText(metadata?.description ?? ""),
5468
5229
  inputs,
5469
5230
  ...behavior,
@@ -5485,14 +5246,14 @@ function authoringDefaultFidelity(targetFormat, goal) {
5485
5246
  function boundedFormatCapabilities() {
5486
5247
  return MCP_FORMAT_CAPABILITIES.slice(0, 64).map((format) => {
5487
5248
  const id = requireWireIdentifier(format.id, "format id");
5488
- if (id.length > MCP_WIRE_LIMITS8.formatCharacters || !MCP_OUTPUT_PATTERNS.format.test(id)) {
5249
+ if (id.length > MCP_WIRE_LIMITS7.formatCharacters || !MCP_OUTPUT_PATTERNS.format.test(id)) {
5489
5250
  throw new Error("Linked Squisq returned an invalid MCP format id");
5490
5251
  }
5491
5252
  return {
5492
5253
  id,
5493
- label: boundWireText(format.label, MCP_WIRE_LIMITS8.labelCharacters, id),
5254
+ label: boundWireText(format.label, MCP_WIRE_LIMITS7.labelCharacters, id),
5494
5255
  mimeType: format.mimeType,
5495
- extensions: boundWireTextArray(format.extensions, 64, MCP_WIRE_LIMITS8.labelCharacters),
5256
+ extensions: boundWireTextArray(format.extensions, 64, MCP_WIRE_LIMITS7.labelCharacters),
5496
5257
  import: { ...format.import },
5497
5258
  export: { ...format.export }
5498
5259
  };
@@ -5508,7 +5269,6 @@ var init_agentic_tools = __esm({
5508
5269
  init_preview_service();
5509
5270
  init_error_result();
5510
5271
  init_progress();
5511
- init_revision_service();
5512
5272
  init_output_bounds();
5513
5273
  READ_ONLY = {
5514
5274
  readOnlyHint: true,
@@ -5528,7 +5288,7 @@ var init_agentic_tools = __esm({
5528
5288
  idempotentHint: false,
5529
5289
  openWorldHint: false
5530
5290
  };
5531
- identifierSchema = z.string().min(1).max(MCP_WIRE_LIMITS8.identifierCharacters).regex(MCP_OUTPUT_PATTERNS.identifier);
5291
+ identifierSchema = z.string().min(1).max(MCP_WIRE_LIMITS7.identifierCharacters).regex(MCP_OUTPUT_PATTERNS.identifier);
5532
5292
  fidelitySchemas = {
5533
5293
  editable: z.enum(MCP_FORMAT_FIDELITIES.docx),
5534
5294
  pdf: z.enum(MCP_FORMAT_FIDELITIES.pdf),
@@ -5641,7 +5401,7 @@ var init_agentic_tools = __esm({
5641
5401
 
5642
5402
  // src/mcp/discovery-tools.ts
5643
5403
  import { z as z2 } from "zod";
5644
- import { MCP_WIRE_LIMITS as MCP_WIRE_LIMITS9 } from "@bendyline/docblocks/mcp";
5404
+ import { MCP_WIRE_LIMITS as MCP_WIRE_LIMITS8 } from "@bendyline/docblocks/mcp";
5645
5405
  import { DOCBLOCKS_MCP_TOOL_OUTPUT_SCHEMAS as DOCBLOCKS_MCP_TOOL_OUTPUT_SCHEMAS2 } from "@bendyline/docblocks/mcp/zod";
5646
5406
  function registerDiscoveryTools(server) {
5647
5407
  server.registerTool(
@@ -5676,9 +5436,9 @@ function registerDiscoveryTools(server) {
5676
5436
  try {
5677
5437
  const { getThemeSummaries } = await import("@bendyline/squisq/schemas");
5678
5438
  const result = {
5679
- themes: getThemeSummaries().slice(0, MCP_WIRE_LIMITS9.arrayEntries).map((theme) => ({
5439
+ themes: getThemeSummaries().slice(0, MCP_WIRE_LIMITS8.arrayEntries).map((theme) => ({
5680
5440
  id: requireWireIdentifier(theme.id, "theme id"),
5681
- name: boundWireText(theme.name, MCP_WIRE_LIMITS9.labelCharacters, theme.id),
5441
+ name: boundWireText(theme.name, MCP_WIRE_LIMITS8.labelCharacters, theme.id),
5682
5442
  description: boundWireText(theme.description ?? "")
5683
5443
  }))
5684
5444
  };
@@ -5703,9 +5463,9 @@ function registerDiscoveryTools(server) {
5703
5463
  try {
5704
5464
  const { getTransformStyleSummaries } = await import("@bendyline/squisq/transform");
5705
5465
  const result = {
5706
- styles: getTransformStyleSummaries().slice(0, MCP_WIRE_LIMITS9.arrayEntries).map((style) => ({
5466
+ styles: getTransformStyleSummaries().slice(0, MCP_WIRE_LIMITS8.arrayEntries).map((style) => ({
5707
5467
  id: requireWireIdentifier(style.id, "transform style id"),
5708
- name: boundWireText(style.name, MCP_WIRE_LIMITS9.labelCharacters, style.id),
5468
+ name: boundWireText(style.name, MCP_WIRE_LIMITS8.labelCharacters, style.id),
5709
5469
  description: boundWireText(style.description)
5710
5470
  }))
5711
5471
  };
@@ -5739,16 +5499,16 @@ function registerDiscoveryTools(server) {
5739
5499
  function serializableCapabilities() {
5740
5500
  return MCP_FORMAT_CAPABILITIES.slice(0, 64).map((format) => ({
5741
5501
  id: requireWireFormat(format.id),
5742
- label: boundWireText(format.label, MCP_WIRE_LIMITS9.labelCharacters, format.id),
5502
+ label: boundWireText(format.label, MCP_WIRE_LIMITS8.labelCharacters, format.id),
5743
5503
  mimeType: format.mimeType,
5744
- extensions: boundWireTextArray(format.extensions, 64, MCP_WIRE_LIMITS9.labelCharacters),
5504
+ extensions: boundWireTextArray(format.extensions, 64, MCP_WIRE_LIMITS8.labelCharacters),
5745
5505
  import: { ...format.import },
5746
5506
  export: { ...format.export }
5747
5507
  }));
5748
5508
  }
5749
5509
  function requireWireFormat(value) {
5750
5510
  requireWireIdentifier(value, "format id");
5751
- if (value.length > MCP_WIRE_LIMITS9.formatCharacters || !MCP_OUTPUT_PATTERNS.format.test(value)) {
5511
+ if (value.length > MCP_WIRE_LIMITS8.formatCharacters || !MCP_OUTPUT_PATTERNS.format.test(value)) {
5752
5512
  throw new Error("Linked Squisq returned an invalid MCP format id");
5753
5513
  }
5754
5514
  return value;
@@ -5874,12 +5634,12 @@ function presentationPrompt(topic, style, theme, template) {
5874
5634
  return `Create a presentation about: ${topic}
5875
5635
 
5876
5636
  1. Call get_authoring_context with targetFormat "pptx" and goal "content-first" for the complete linked-Squisq vocabulary and workflow in one response.
5877
- 2. Author complete Markdown sections with accessible alt text. Put annotations on headings, for example \`# Heading {[content]}\`; a standalone \`{[template]}\` creates an extra block. Prefer style "${style ?? "choose from the returned transform styles"}", theme "${theme ?? "choose from the returned themes"}", and template "${template ?? "content until visual optimization"}".
5878
- 3. Keep the draft inline or stage Markdown plus assets with create_document_bundle. Do not write a temporary local Markdown file or invent a root id.
5879
- 4. Call validate_document with targetFormat "pptx" and repair actionable diagnostics before optimizing layouts.
5880
- 5. Call preview_document and inspect every bounded slide image, especially overflow and body-retention diagnostics.
5881
- 6. If a staged DBK needs targeted repairs, call inspect_document for block IDs and revise_document with the artifact's exact SHA-256 instead of resending the full Markdown. Only after content coverage is acceptable, replace selected \`content\` blocks with more visual recommended templates and preview again.
5882
- 7. Call convert_document with a pptx target. Choose editable-native for editable Office structures, rendered-fidelity for exact Squisq visuals, or hybrid for rendered visuals plus semantic retention.
5637
+ 2. Treat the topic facts as a closed evidence set. Preserve them exactly, use temporal or correlational wording unless causality is supplied, and label calculations, assumptions, hypotheses, recommendations, and examples. Causal links, rhetorical performance labels, superlatives, sole causes, capabilities, owners, dates, channels, and operational details must be supplied or explicitly framed. Do not connect separate metrics, audiences, segments, or workflows unless the relationship is supplied. Prefer observed, coincided with, intended to, or proposed over drove, addresses, protects, or proves. Add decision value through supplied baselines, goals, targets, rankings, and transparent calculations. Do not call choices a sequence or capacity allocation unless order, timing, or resources were supplied. When the requested content needs unsupplied operating details, add one proposed operating model scope note that applies to them.
5638
+ 3. Match every explicitly requested slide count exactly. Use exactly one level-one Markdown heading (\`#\`) per slide and no level-two through level-six headings because every heading becomes a slide by default; use lists, tables, or bold labels within a slide. Target at most 80 words per slide. Make slide one a supported point-of-view thesis, not a generic title or unsupported flourish. For requested choices, state concrete opportunity costs grounded in supplied alternatives and one clearly labeled proposed accountable role per choice. Label any unsupplied capacity or outcome assumption as \`Assumption:\` or \`Potential tradeoff:\`. Author complete Markdown sections with accessible alt text. Put annotations on headings, for example \`# Heading {[content]}\`; a standalone \`{[template]}\` creates an extra block. Prefer style "${style ?? "choose from the returned transform styles"}", theme "${theme ?? "choose from the returned themes"}", and template "${template ?? "content until visual optimization"}".
5639
+ 4. Keep the complete Markdown as the authoritative draft. Pass it\u2014or a bundle source when assets are needed\u2014directly to convert_document. Use create_document_bundle only when the same materially large Markdown-and-asset bundle will feed several operations. Do not write a temporary local Markdown file or invent a root id.
5640
+ 5. Before conversion, count slide sections, verify every requested element, and rewrite or label every unsupported claim. Label any new review cadence or measurement procedure as proposed. Use validate_document when syntax, accessibility, retention, or target diagnostics need review; use preview_document when visual evidence such as overflow needs review. Repair findings in the complete Markdown.
5641
+ 6. Only after content coverage is acceptable, replace selected \`content\` blocks with compatible visual templates such as \`definitionCard\`, \`dataTable\`, \`comparisonBar\`, or \`list\` when their semantic inputs fit. Preserve required content.
5642
+ 7. Call convert_document with the complete source and a pptx target. Choose editable-native for editable Office structures, rendered-fidelity for exact Squisq visuals, or hybrid for rendered visuals plus semantic retention. Revise by editing the complete Markdown and converting again.
5883
5643
  8. Use get_conversion_report for provenance and save_artifact only when a durable file is required.`;
5884
5644
  }
5885
5645
  function videoPrompt(topic, orientation, theme, template) {
@@ -5887,20 +5647,19 @@ function videoPrompt(topic, orientation, theme, template) {
5887
5647
 
5888
5648
  1. Call get_authoring_context with targetFormat "mp4" for the complete linked-Squisq vocabulary and workflow.
5889
5649
  2. Author concise Markdown for a ${orientation ?? "landscape"} animated sequence using theme "${theme ?? "choose from the returned themes"}" and template "${template ?? "content until visual optimization"}". Bind annotations to headings.
5890
- 3. If the draft is staged, use inspect_document plus revise_document for targeted repairs instead of resending the full Markdown. Call validate_document with targetFormat "mp4" and repair actionable diagnostics.
5891
- 4. Call preview_document to review representative frames.
5892
- 5. Call convert_document with an mp4 target and orientation "${orientation ?? "landscape"}"; monitor progress and honor cancellation.
5893
- 6. Use get_conversion_report for provenance and save_artifact only when a durable file is required.`;
5650
+ 3. Keep the complete Markdown as the authoritative draft and pass it\u2014or a bundle source when assets are needed\u2014directly to convert_document. Use validate_document for uncertain target constraints and preview_document when representative-frame evidence is useful; repair findings in the complete Markdown.
5651
+ 4. Call convert_document with the complete source, an mp4 target, and orientation "${orientation ?? "landscape"}"; monitor progress and honor cancellation. Revise by editing the complete Markdown and converting again.
5652
+ 5. Use get_conversion_report for provenance and save_artifact only when a durable file is required.`;
5894
5653
  }
5895
5654
  function documentPrompt(topic, format, theme, template) {
5896
5655
  const target = format ?? "pdf";
5897
5656
  return `Create a professional document about: ${topic}
5898
5657
 
5899
5658
  1. Call get_authoring_context with targetFormat "${target}" for the complete linked-Squisq vocabulary and workflow.
5900
- 2. Author structured Markdown using theme "${theme ?? "choose from the returned themes"}" and template "${template ?? "content until visual optimization"}". Bind annotations to headings.
5901
- 3. If the draft is staged, use inspect_document plus revise_document for targeted repairs instead of resending the full Markdown. Call validate_document with targetFormat "${target}" and repair actionable diagnostics.
5902
- 4. Call convert_document with a ${target} target to create an immutable artifact.
5903
- 5. Call preview_document and review the bounded page images.
5659
+ 2. Treat the topic facts as a closed evidence set. Preserve them exactly, use temporal or correlational wording unless causality is supplied, and label calculations, assumptions, hypotheses, recommendations, and examples. Causal links, superlatives, sole causes, capabilities, owners, dates, channels, and operational details must be supplied or explicitly framed. When the requested genre needs unsupplied roles, gates, timelines, channels, or procedures, add one proposed operating model scope note that applies to those details.
5660
+ 3. Honor the requested word range and document genre. Author structured Markdown using theme "${theme ?? "choose from the returned themes"}" and template "${template ?? "content until visual optimization"}". Bind annotations to headings. Use connected memo prose for executive decisions and native headings, tables, and checklists for operational documents; retain complete-body content when a visual template would discard detail.
5661
+ 4. Before conversion, count document words, verify every requested element, and rewrite or label every unsupported claim. Keep the complete Markdown as the authoritative draft and pass it\u2014or a bundle source when assets are needed\u2014directly to convert_document. Use validate_document when syntax, accessibility, retention, or target diagnostics need review, and preview_document when page-layout evidence is useful; repair findings in the complete Markdown.
5662
+ 5. Call convert_document with the complete source and a ${target} target to create an immutable artifact. Revise by editing the complete Markdown and converting again.
5904
5663
  6. Use get_conversion_report for provenance and save_artifact only when a durable file is required.`;
5905
5664
  }
5906
5665
  function complete(values, prefix) {
@@ -5943,7 +5702,7 @@ function createMcpServer(options = {}) {
5943
5702
  const server = new McpServer(
5944
5703
  { name: "docblocks", version: getPackageVersion() },
5945
5704
  {
5946
- instructions: "Start with get_authoring_context for one-call format, theme, transform, template, syntax, and workflow guidance. Author template annotations on headings, for example `# Heading {[content]}`; standalone `{[template]}` creates an extra heading-less block. DocBlocks MCP defaults ordinary headings to the loss-averse `content` template. Keep authored work in an inline source or stage Markdown plus assets with create_document_bundle. For targeted repairs to a staged DBK, inspect its block ids and call revise_document with the artifact's exact SHA-256 instead of resending the full Markdown. Then validate, preview, convert, and only save the final artifact when durable output is required. Never invent root ids: call list_roots and use an id exactly as returned."
5705
+ instructions: "Treat provided facts as a closed evidence set: preserve them exactly; use temporal or correlational wording unless causality is supplied; label calculations, assumptions, hypotheses, recommendations, and examples. Causal links, rhetorical performance labels, superlatives, sole causes, targets, capabilities, owners, dates, channels, and operational details must be supplied or explicitly framed. Do not connect separate metrics, audiences, segments, or workflows unless the relationship is supplied. Prefer observed, coincided with, intended to, or proposed over drove, addresses, protects, or proves. Add decision value through supplied baselines, goals, targets, rankings, and transparent calculations. Do not call choices a sequence or capacity allocation unless order, timing, or resources were supplied. When a requested policy, playbook, or training guide needs unsupplied operating details, add one proposed operating model scope note, then complete every requested element. Match explicit slide/page counts and word ranges exactly; target at most 80 words per presentation section. Make slide one a supported point-of-view thesis. For requested choices, state concrete opportunity costs grounded in supplied alternatives and one proposed accountable role per choice; label unsupplied capacity, outcome, or review-cadence assumptions. Before conversion, count sections or words, verify required elements, and audit unsupported claims. Start with get_authoring_context for the compact linked-Squisq contract and structured catalog. Author complete Squisq-compatible Markdown with template annotations on headings, for example `# Heading {[content]}`; standalone `{[template]}` creates an extra heading-less block. Ordinary headings default to the loss-averse `content` template. The canonical path is complete Markdown\u2014or a bundle source when assets are needed\u2014directly into convert_document; revise by editing the complete Markdown and converting again. create_document_bundle is optional for materially large, reusable Markdown-and-asset bundles. Use inspect_document, validate_document, and preview_document when their evidence is useful rather than as required phases. Save only the final durable artifact. Never invent root ids: call list_roots and use an id exactly as returned."
5947
5706
  }
5948
5707
  );
5949
5708
  registerAgenticTools(server, {