@shoalrun/cli 0.1.0-alpha.19 → 1.0.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 (219) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/CODE-REFERENCES.md +137 -0
  3. package/README.md +19 -6
  4. package/adapters/python/requirements.txt +1 -0
  5. package/adapters/python/shoalrun_reference.py +234 -0
  6. package/agent-docs/.well-known/shoalrun/navigation/project-updates-50f26fe22670.txt +7 -3
  7. package/agent-docs/SNAPSHOT.json +5 -5
  8. package/agent-docs/about.md +3 -3
  9. package/agent-docs/api-docs/code-reference-settings.md +160 -0
  10. package/agent-docs/api-docs/code-reference-settings.sections/catalog-settings.md +50 -0
  11. package/agent-docs/api-docs/code-reference-settings.sections/complete-reference-page.md +46 -0
  12. package/agent-docs/api-docs/code-reference-settings.sections/converter-snapshot.md +58 -0
  13. package/agent-docs/api-docs/code-reference-settings.sections/descriptions-type-links-and-source-links.md +40 -0
  14. package/agent-docs/api-docs/code-reference-settings.sections/html-markdown-and-agents.md +38 -0
  15. package/agent-docs/api-docs/code-reference-settings.sections/metadata-and-selection.md +38 -0
  16. package/agent-docs/api-docs/code-reference-settings.sections/publication-sources.md +54 -0
  17. package/agent-docs/api-docs/code-reference-settings.sections/python-adapter-limits.md +38 -0
  18. package/agent-docs/api-docs/code-reference-settings.sections/related-reading.md +32 -0
  19. package/agent-docs/api-docs/code-reference-settings.sections/symbol-fields.md +56 -0
  20. package/agent-docs/api-docs/code-references.md +143 -0
  21. package/agent-docs/author/agent-overview.md +2 -2
  22. package/agent-docs/author/components/code-blocks.md +46 -1
  23. package/agent-docs/author/frontmatter-reference.md +1 -0
  24. package/agent-docs/author/frontmatter-reference.sections/categorize-connect-and-present-the-page.md +1 -0
  25. package/agent-docs/author/workspace.md +2 -2
  26. package/agent-docs/author/writing-style.md +9 -3
  27. package/agent-docs/author/writing-style.sections/adapt-this-example.md +1 -1
  28. package/agent-docs/author/writing-style.sections/choose-components-by-reader-need.md +2 -2
  29. package/agent-docs/author/writing-style.sections/evidence-and-uncertainty.md +1 -1
  30. package/agent-docs/author/writing-style.sections/example-audience-and-scope.md +1 -1
  31. package/agent-docs/author/writing-style.sections/feature-availability.md +1 -1
  32. package/agent-docs/author/writing-style.sections/ingredients-recipes-and-cookbooks.md +1 -1
  33. package/agent-docs/author/writing-style.sections/page-purpose-and-structure.md +2 -2
  34. package/agent-docs/author/writing-style.sections/procedures-and-examples.md +1 -1
  35. package/agent-docs/author/writing-style.sections/related-reading.md +1 -1
  36. package/agent-docs/author/writing-style.sections/release-notes.md +30 -0
  37. package/agent-docs/author/writing-style.sections/review-a-draft.md +1 -1
  38. package/agent-docs/author/writing-style.sections/reviewed-writing-examples.md +1 -1
  39. package/agent-docs/author/writing-style.sections/voice-and-explanations.md +1 -1
  40. package/agent-docs/changelog/2026-10-16-navigation-layouts.md +1 -1
  41. package/agent-docs/changelog/code-api-references.md +44 -0
  42. package/agent-docs/changelog/pdf-custom-languages.md +48 -0
  43. package/agent-docs/changelog.md +17 -1
  44. package/agent-docs/cli.md +11 -1
  45. package/agent-docs/cli.sections/audit-a-project-and-api-sources.md +1 -1
  46. package/agent-docs/cli.sections/author-pages.md +1 -1
  47. package/agent-docs/cli.sections/build-and-serve.md +1 -1
  48. package/agent-docs/cli.sections/inspect-config-and-operations.md +1 -1
  49. package/agent-docs/cli.sections/npm-scripts-in-this-repository.md +1 -1
  50. package/agent-docs/cli.sections/related-reading.md +1 -1
  51. package/agent-docs/cli.sections/search-and-chat.md +1 -1
  52. package/agent-docs/cli.sections/start-a-project.md +1 -1
  53. package/agent-docs/cli.sections/validate-code-reference-snapshots.md +41 -0
  54. package/agent-docs/cli.sections/working-tree-authoring-tools.md +1 -1
  55. package/agent-docs/config/apis.md +5 -1
  56. package/agent-docs/config/examples.md +3 -3
  57. package/agent-docs/config/examples.sections/feature-showcase.md +3 -3
  58. package/agent-docs/config/examples.sections/minimal-site.md +2 -2
  59. package/agent-docs/config/examples.sections/multilingual-help-center.md +2 -2
  60. package/agent-docs/config/examples.sections/parcel-api-documentation.md +2 -2
  61. package/agent-docs/config/examples.sections/related-reading.md +2 -2
  62. package/agent-docs/config/examples.sections/shared-company-preset.md +2 -2
  63. package/agent-docs/config/outputs.md +33 -12
  64. package/agent-docs/config/outputs.sections/exports.md +3 -3
  65. package/agent-docs/config/outputs.sections/metadata.md +3 -3
  66. package/agent-docs/config/outputs.sections/pdf-output.md +51 -0
  67. package/agent-docs/config/outputs.sections/related-reading.md +3 -3
  68. package/agent-docs/config.md +2 -2
  69. package/agent-docs/configuration.md +2 -2
  70. package/agent-docs/configuration.sections/build-several-sites-from-shared-content.md +1 -1
  71. package/agent-docs/configuration.sections/change-inherited-lists-deliberately.md +1 -1
  72. package/agent-docs/configuration.sections/extract-a-section-with-include.md +1 -1
  73. package/agent-docs/configuration.sections/inspect-and-validate-changes.md +1 -1
  74. package/agent-docs/configuration.sections/related-reading.md +1 -1
  75. package/agent-docs/configuration.sections/separate-config-inheritance-from-page-metadata.md +1 -1
  76. package/agent-docs/configuration.sections/share-defaults-through-extends.md +1 -1
  77. package/agent-docs/configuration.sections/start-with-one-working-file.md +2 -2
  78. package/agent-docs/configuration.sections/understand-the-three-stages.md +1 -1
  79. package/agent-docs/configuration.sections/understand-where-paths-point.md +1 -1
  80. package/agent-docs/contribute/agent-skills.md +3 -1
  81. package/agent-docs/documents.json +1009 -356
  82. package/agent-docs/features.md +6 -2
  83. package/agent-docs/index.md +2 -2
  84. package/agent-docs/provenance.json +6 -6
  85. package/agent-docs/publish/api-references.md +3 -1
  86. package/agent-docs/publish/api-references.sections/author-the-reference-page.md +3 -1
  87. package/agent-docs/publish/api-references.sections/build-and-verify-the-output.md +3 -1
  88. package/agent-docs/publish/api-references.sections/inspect-the-machine-readable-contract.md +3 -1
  89. package/agent-docs/publish/api-references.sections/next-steps.md +3 -1
  90. package/agent-docs/publish/api-references.sections/preview-a-small-api-reference.md +3 -1
  91. package/agent-docs/publish/api-references.sections/put-the-spec-in-your-project.md +3 -1
  92. package/agent-docs/publish/api-references.sections/register-the-operation.md +3 -1
  93. package/agent-docs/publish/api-references.sections/related-reading.md +3 -1
  94. package/agent-docs/publish/api-references.sections/review-imported-content-before-publishing.md +3 -1
  95. package/agent-docs/publish/api-references.sections/what-readers-get.md +3 -1
  96. package/agent-docs/publish/content-export.md +2 -0
  97. package/agent-docs/publish/content-export.sections/assets-downloads-and-notices.md +2 -0
  98. package/agent-docs/publish/content-export.sections/check-the-result.md +2 -0
  99. package/agent-docs/publish/content-export.sections/inspect-the-manifest.md +2 -0
  100. package/agent-docs/publish/content-export.sections/prerequisites.md +2 -0
  101. package/agent-docs/publish/content-export.sections/related-reading.md +2 -0
  102. package/agent-docs/publish/content-export.sections/review-exported-api-material.md +2 -0
  103. package/agent-docs/publish/content-export.sections/try-the-help-drawer-example.md +2 -0
  104. package/agent-docs/publish/content-export.sections/what-the-representations-retain.md +2 -0
  105. package/agent-docs/publish/pdf.md +184 -0
  106. package/agent-docs/publish/pdf.sections/apply-print-styling.md +65 -0
  107. package/agent-docs/publish/pdf.sections/check-the-result.md +33 -0
  108. package/agent-docs/publish/pdf.sections/export-a-page-or-publication.md +61 -0
  109. package/agent-docs/publish/pdf.sections/html-markdown-and-agents.md +31 -0
  110. package/agent-docs/publish/pdf.sections/offer-browser-page-printing.md +49 -0
  111. package/agent-docs/publish/pdf.sections/offer-direct-downloads-through-a-node-server.md +46 -0
  112. package/agent-docs/publish/pdf.sections/prerequisites.md +37 -0
  113. package/agent-docs/publish/pdf.sections/publish-an-optional-manual-download.md +39 -0
  114. package/agent-docs/publish.md +2 -0
  115. package/agent-docs/reference/agent-skills.md +7 -3
  116. package/agent-docs/search-index.json +1 -1
  117. package/agent-docs/start.md +4 -4
  118. package/agent-docs/start.sections/add-the-page-to-navigation.md +2 -2
  119. package/agent-docs/start.sections/build-and-check-both-outputs.md +2 -2
  120. package/agent-docs/start.sections/build-this-site.md +2 -2
  121. package/agent-docs/start.sections/check-writing-style.md +2 -2
  122. package/agent-docs/start.sections/create-a-page.md +2 -2
  123. package/agent-docs/start.sections/make-it-yours.md +2 -2
  124. package/agent-docs/start.sections/migrating-from-github-packages.md +2 -2
  125. package/agent-docs/start.sections/prerequisites.md +2 -2
  126. package/agent-docs/start.sections/related-reading.md +2 -2
  127. package/agent-docs/start.sections/start-your-own-project.md +4 -4
  128. package/agent-docs/status.md +9 -5
  129. package/agent-docs/styling/themes.md +7 -3
  130. package/agent-docs/what-is-shoalrun.md +2 -2
  131. package/assets/copy-markdown.js +1 -1
  132. package/assets/print-view.js +165 -0
  133. package/assets/print.js +63 -0
  134. package/dist/artifact-bundle.d.ts +2 -0
  135. package/dist/artifact-bundle.js +13 -3
  136. package/dist/authoring-snapshot.js +1 -1
  137. package/dist/browser-print-assets.d.ts +9 -0
  138. package/dist/browser-print-assets.js +45 -0
  139. package/dist/cli-discovery.d.ts +1 -1
  140. package/dist/cli-discovery.js +1 -0
  141. package/dist/cli.js +7 -0
  142. package/dist/code-reference-model.d.ts +85 -0
  143. package/dist/code-reference-model.js +73 -0
  144. package/dist/code-references.d.ts +23 -0
  145. package/dist/code-references.js +371 -0
  146. package/dist/compiler-config.d.ts +1 -0
  147. package/dist/compiler.d.ts +4 -2
  148. package/dist/compiler.js +33 -7
  149. package/dist/config.js +1 -1
  150. package/dist/content-export-command.d.ts +77 -1
  151. package/dist/content-export-command.js +5 -2
  152. package/dist/content-export-config.d.ts +4 -1
  153. package/dist/content-export-config.js +10 -5
  154. package/dist/content-export-render.d.ts +9 -3
  155. package/dist/content-export-render.js +11 -7
  156. package/dist/content-export.d.ts +126 -0
  157. package/dist/content-export.js +267 -124
  158. package/dist/content-source.d.ts +2 -0
  159. package/dist/content-workspace.d.ts +1 -0
  160. package/dist/content-workspace.js +2 -0
  161. package/dist/fonts.d.ts +9 -0
  162. package/dist/fonts.js +58 -3
  163. package/dist/frontmatter.js +5 -2
  164. package/dist/highlight-languages.d.ts +9 -0
  165. package/dist/highlight-languages.js +52 -0
  166. package/dist/highlight.d.ts +4 -1
  167. package/dist/highlight.js +20 -5
  168. package/dist/output-commit.d.ts +1 -1
  169. package/dist/output-commit.js +4 -2
  170. package/dist/page-materialization.js +3 -2
  171. package/dist/page-renderer.d.ts +1 -0
  172. package/dist/page-renderer.js +8 -1
  173. package/dist/pdf-button.d.ts +22 -0
  174. package/dist/pdf-button.js +55 -0
  175. package/dist/pdf-config.d.ts +28 -0
  176. package/dist/pdf-config.js +43 -0
  177. package/dist/pdf-http.d.ts +36 -0
  178. package/dist/pdf-http.js +132 -0
  179. package/dist/pdf-project.d.ts +6 -0
  180. package/dist/pdf-project.js +31 -0
  181. package/dist/pdf-renderer.d.ts +45 -0
  182. package/dist/pdf-renderer.js +208 -0
  183. package/dist/pdf-site.d.ts +37 -0
  184. package/dist/pdf-site.js +65 -0
  185. package/dist/pdf-stylesheet.d.ts +1 -0
  186. package/dist/pdf-stylesheet.js +57 -0
  187. package/dist/publication-render.d.ts +2 -1
  188. package/dist/publication-render.js +2 -2
  189. package/dist/representation-tree.js +5 -1
  190. package/dist/server.d.ts +2 -0
  191. package/dist/server.js +35 -8
  192. package/dist/vercel.js +6 -0
  193. package/examples/code-references/content/start.md +53 -0
  194. package/examples/code-references/docs.config.yaml +262 -0
  195. package/examples/code-references/python/orchard/__init__.py +11 -0
  196. package/examples/code-references/python/orchard/client.py +212 -0
  197. package/examples/code-references/python/orchard/errors.py +31 -0
  198. package/examples/code-references/python/orchard/models.py +69 -0
  199. package/examples/code-references/python/orchard/pagination.py +39 -0
  200. package/examples/code-references/reference.json +1244 -0
  201. package/examples/custom-language/README.md +32 -0
  202. package/examples/custom-language/content/start.mdx +28 -0
  203. package/examples/custom-language/docs.config.yaml +18 -0
  204. package/examples/custom-language/grammars/custompy.tmLanguage.json +7 -0
  205. package/examples/pdf/README.md +27 -0
  206. package/examples/pdf/content/operations.mdx +26 -0
  207. package/examples/pdf/content/start.mdx +28 -0
  208. package/examples/pdf/docs.config.yaml +29 -0
  209. package/examples/pdf/print.css +9 -0
  210. package/package.json +11 -2
  211. package/schemas/code-reference.schema.json +306 -0
  212. package/skills/shoalrun-author/SKILL.md +6 -0
  213. package/skills/shoalrun-author/references/code-api-references.md +15 -0
  214. package/skills/shoalrun-author/references/pdf-export.md +15 -0
  215. package/skills/shoalrun-brand/SKILL.md +2 -0
  216. package/skills/shoalrun-pdf/SKILL.md +49 -0
  217. package/skills/shoalrun-pdf/assets/print.css +49 -0
  218. package/skills/shoalrun-pdf/references/print-design.md +75 -0
  219. package/styles/site.css +64 -3
@@ -12,6 +12,8 @@ import { fictionalDocument, optionalDocument, resolveLlmsDiscovery } from './llm
12
12
  import { boundedDiscovery } from './compact-discovery.js';
13
13
  import { iconLicenseFile } from './icons.js';
14
14
  import { peleLicenseFile } from './diagrams.js';
15
+ import { fontMediaType } from './fonts.js';
16
+ import { createHash } from 'node:crypto';
15
17
  import { defaultShareSvg, faviconSvg, fillShareTemplate, renderPng, touchIconSvg } from './share-images.js';
16
18
  import { paletteCatalog, paletteCss, presetCatalog, resolvePalette } from './palettes.js';
17
19
  import { heading, link, list, paragraph, renderMarkdown, root, searchIndex, shareCardText, text } from './content.js';
@@ -38,6 +40,8 @@ export async function assembleArtifacts(input) {
38
40
  artifactDirectories.add(parent);
39
41
  artifacts.set(normalized, data);
40
42
  };
43
+ for (const [route, bytes] of input.extraArtifacts ?? [])
44
+ addArtifact(route, bytes);
41
45
  const addPublicArtifact = (route, data) => addArtifact(publicPath(route), data);
42
46
  const addMetadataArtifact = (route, data) => {
43
47
  for (const url of new Set([route, publicPath(route)]))
@@ -146,10 +150,16 @@ export async function assembleArtifacts(input) {
146
150
  }
147
151
  if (generatedFontsCss)
148
152
  addPublicArtifact('/assets/fonts.css', generatedFontsCss.replaceAll('url("/assets/', `url("${basePath}/assets/`));
153
+ const addFont = (route, bytes, immutable) => {
154
+ addPublicArtifact(route, bytes);
155
+ const type = fontMediaType(route);
156
+ if (type)
157
+ headers[publicPath(route)] = { 'Content-Type': type, 'Cache-Control': immutable ? 'public, max-age=31536000, immutable' : 'public, max-age=0, must-revalidate', ETag: `"${createHash('sha256').update(bytes).digest('hex')}"` };
158
+ };
149
159
  for (const file of fontFiles)
150
- addPublicArtifact(`/assets/fonts/${path.basename(file)}`, await readFile(file));
151
- for (const route of new Set(fonts.faces.map(face => face.route)))
152
- addPublicArtifact(route, await readFile(fonts.faces.find(face => face.route === route).file));
160
+ addFont(`/assets/fonts/${path.basename(file)}`, await readFile(file), false);
161
+ for (const [route, bytes] of input.projectFontAssets)
162
+ addFont(route, bytes, true);
153
163
  const shareTemplate = shareImages.template ? await readFile(shareImages.template, 'utf8') : undefined;
154
164
  for (const page of rendered) {
155
165
  const share = shareFor(page.doc);
@@ -193,7 +193,7 @@ export async function captureSnapshotInputs(configFile, options = {}) {
193
193
  for (const key of Object.keys(value))
194
194
  await visit(value[key], [...segments, key]);
195
195
  }
196
- else if (typeof value === 'string' && (['file', 'path', 'module', 'manifest', 'customCss', 'customReaderModule', 'body', 'template', 'favicon', 'logo'].includes(segments.at(-1)) || segments.at(-2) === 'files') && !/^(?:[a-z][a-z0-9+.-]*:|#)/i.test(value)) {
196
+ else if (typeof value === 'string' && (['file', 'path', 'module', 'manifest', 'customCss', 'customReaderModule', 'body', 'template', 'favicon', 'logo'].includes(segments.at(-1)) || segments.at(-2) === 'files' || (segments[0] === 'outputs' && segments[1] === 'html' && segments[2] === 'highlighting' && segments.at(-1) === 'grammar') || (segments.includes('pdf') && (segments.at(-1) === 'stylesheet' || segments.includes('fonts') && segments.at(-1) === 'source'))) && !/^(?:[a-z][a-z0-9+.-]*:|#)/i.test(value)) {
197
197
  if (path.isAbsolute(value))
198
198
  throw new SnapshotError('unsupported_dependency', `Absolute dependency at ${segments.join('.')} cannot be isolated; use a relative path.`);
199
199
  if (segments[0] === 'components' && segments.at(-1) === 'module' && !value.startsWith('.'))
@@ -0,0 +1,9 @@
1
+ /** One shared print theme for the entire build; no page content is materialized. */
2
+ export declare function browserPrintAssets(configFile: string, options: {
3
+ basePath: string;
4
+ profile?: string;
5
+ style?: string;
6
+ }): Promise<{
7
+ artifacts: Map<string, string | Buffer<ArrayBufferLike>>;
8
+ dependencies: Set<string>;
9
+ }>;
@@ -0,0 +1,45 @@
1
+ import path from 'node:path';
2
+ import { parse } from 'parse5';
3
+ import { loadConfig } from './config.js';
4
+ import { projectPdfSettings } from './pdf-project.js';
5
+ import { preparePdfDocument } from './pdf-renderer.js';
6
+ import { sitePath } from './site-path.js';
7
+ /** One shared print theme for the entire build; no page content is materialized. */
8
+ export async function browserPrintAssets(configFile, options) {
9
+ const loaded = await loadConfig(configFile, { profile: options.profile });
10
+ const { config, files } = projectPdfSettings(loaded, configFile, options.style);
11
+ const prepared = await preparePdfDocument({
12
+ documents: [{ id: 'print-theme', title: '', html: '' }], title: '', assets: new Map(), publicBase: '/',
13
+ config: { ...config, cover: false, toc: false }, configFile,
14
+ assetRoots: files.map(file => path.dirname(file))
15
+ });
16
+ let css = '';
17
+ const findStyle = (node) => { if (node.tagName === 'style')
18
+ css += (node.childNodes ?? []).map((child) => child.value ?? '').join(''); for (const child of node.childNodes ?? [])
19
+ findStyle(child); };
20
+ findStyle(parse(prepared.html));
21
+ const artifacts = new Map();
22
+ let logo;
23
+ for (const [original, asset] of prepared.assets) {
24
+ const route = sitePath(options.basePath, `/assets/print/${path.posix.basename(original)}`);
25
+ artifacts.set(route, asset.bytes);
26
+ css = css.replaceAll(original, route);
27
+ if (original.startsWith('/__pdf_logo/'))
28
+ logo = route;
29
+ }
30
+ const margins = { top: '18mm', right: '18mm', bottom: '18mm', left: '18mm', ...config.margins };
31
+ css = `@page{size:${config.size ?? 'A4'};margin:${margins.top} ${margins.right} ${margins.bottom} ${margins.left}}\n` + css;
32
+ css += '\n.pdf-print-tools{display:flex;gap:10px;align-items:center;padding:12px 0;margin-bottom:24px;font:14px Arial,sans-serif}.pdf-print-tools button{font:inherit;padding:8px 12px;border:1px solid #89998e;border-radius:4px;cursor:pointer}.pdf-print-tools .pdf-print-note{margin-left:auto;color:#53665e;font-size:12px}.pdf-chapter .page-head h1{margin-bottom:8pt}.pdf-chapter .page-head .summary{font-size:10pt;line-height:1.5;margin:0 0 8pt}.pdf-chapter .page-head .pdf-page-meta{font-size:8pt;margin:5pt 0 12pt}.pdf-page-meta{color:var(--pdf-muted);font-size:9pt;margin-bottom:14pt}.pdf-chapter .eyebrow{color:var(--pdf-muted);font-size:9pt}.pdf-chapter .page-dates{display:flex;flex-wrap:wrap;gap:4pt 10pt;font-size:9pt;color:var(--pdf-muted)}.pdf-chapter .doc-callout{border-left:3pt solid var(--pdf-accent);padding:10pt 14pt;background:#f1f4ee;margin:14pt 0}.pdf-chapter details{display:block}.pdf-reader-label{font-weight:bold;margin-top:14pt}@media screen{html{background:#dfe5de}body{max-width:210mm;margin:24px auto;padding:18mm;background:white;box-shadow:0 8px 40px #173c3520}}@media print{.pdf-print-tools{display:none!important}}';
33
+ // A manual theme may start every chapter on a new page. When no cover or
34
+ // contents precede this chapter, that break can produce a blank first sheet.
35
+ css += '\n.pdf-print-tools + .pdf-chapter{break-before:auto}';
36
+ const stylesheet = sitePath(options.basePath, '/assets/print/theme.css');
37
+ artifacts.set(stylesheet, css);
38
+ const settings = {
39
+ schemaVersion: 1, stylesheet, ...(logo ? { logo } : {}), cover: config.cover ?? false,
40
+ toc: config.toc ?? false, subtitle: config.subtitle ?? '', header: config.header ?? '', footer: config.footer ?? '',
41
+ fonts: (config.fonts ?? []).map(({ family, weight, style }) => ({ family, weight, style }))
42
+ };
43
+ artifacts.set(sitePath(options.basePath, '/assets/print/settings.json'), JSON.stringify(settings));
44
+ return { artifacts, dependencies: new Set([...loaded.dependencies, ...files]) };
45
+ }
@@ -1,4 +1,4 @@
1
1
  export declare const docsHelp = "Usage: shoalrun docs <command>\n\nRead bundled references (no project or provider key required):\n search <query> [--json]\n read <document-id> [--json]\n outline <document-id> [--json]\n section <document-id> <section-id> [--json]\n\nSearch and reads accept --site DIRECTORY, --max-tokens N, and publication\nselectors --product P --channel C --version V --language L.\n\nInspect a project:\n project [--config FILE] [--profile FILE] [--section pages|guidance|configuration|navigation|relationships|templates|findings]\n source FILE [--config FILE] [--profile FILE]\n context <document-id> [--config FILE]\n\nValidate and preview edits:\n baseline --out FILE [--config FILE] [--profile FILE]\n validate (--baseline FILE | --file FILE | --id ID) [--config FILE] [--profile FILE]\n validation-status REPORT\n review REPORT [--format json|markdown]\n preview REPORT [--port PORT]\n\nOther authoring tools: changes, plan, apply, mcp.\nDiscover packaged agent guidance with shoalrun skills list.\n";
2
2
  export declare const skillsHelp = "Usage: shoalrun skills list [--json]\n shoalrun skills read <name> [--json]\n\nList the names, descriptions and local paths of packaged skills, or read a skill.\nThese commands do not install skills or require a project or provider key.\n";
3
- export declare const cliHelp = "Usage: shoalrun <command>\n\nStart and build:\n init [directory] [--starter minimal|api-docs|showcase]\n build [config] [output] [--profile FILE]\n export [config] --out DIRECTORY [--target NAME] [--profile FILE]\n dev [config] [output] [--profile FILE] [--port PORT]\n serve <site-directory> [--host HOST] [--port PORT]\n check [config] [--json]\n audit [config]\n scaffold <template> -n <target> [--config FILE] [--product P]\n\nAgent guidance and offline documentation:\n skills list [--json]\n skills read <name> [--json]\n docs search <query> [--site DIRECTORY] [--product P] [--json]\n docs read <document-id> [--site DIRECTORY] [--product P] [--json]\n docs project [--config FILE] [--profile FILE]\n docs baseline --out FILE [--config FILE] [--profile FILE]\n docs validate (--baseline FILE | --file FILE | --id ID) [--config FILE] [--profile FILE]\n docs review REPORT [--format json|markdown]\n docs preview REPORT [--port PORT]\n\nOther commands: config, api, operation, ingredient, recipe, search, index,\nask, answers, ask-log, chat, eval, vercel.\nRun shoalrun docs --help or shoalrun skills --help for discovery commands.\n";
3
+ export declare const cliHelp = "Usage: shoalrun <command>\n\nStart and build:\n init [directory] [--starter minimal|api-docs|showcase]\n build [config] [output] [--profile FILE]\n export [config] --out DIRECTORY [--target NAME] [--profile FILE]\n dev [config] [output] [--profile FILE] [--port PORT]\n serve <site-directory> [--host HOST] [--port PORT]\n check [config] [--json]\n references check <snapshot.json>\n audit [config]\n scaffold <template> -n <target> [--config FILE] [--product P]\n\nAgent guidance and offline documentation:\n skills list [--json]\n skills read <name> [--json]\n docs search <query> [--site DIRECTORY] [--product P] [--json]\n docs read <document-id> [--site DIRECTORY] [--product P] [--json]\n docs project [--config FILE] [--profile FILE]\n docs baseline --out FILE [--config FILE] [--profile FILE]\n docs validate (--baseline FILE | --file FILE | --id ID) [--config FILE] [--profile FILE]\n docs review REPORT [--format json|markdown]\n docs preview REPORT [--port PORT]\n\nOther commands: config, api, operation, ingredient, recipe, search, index,\nask, answers, ask-log, chat, eval, vercel.\nRun shoalrun docs --help or shoalrun skills --help for discovery commands.\n";
4
4
  export declare function runSkillsCommand(args: string[]): Promise<string>;
@@ -43,6 +43,7 @@ Start and build:
43
43
  dev [config] [output] [--profile FILE] [--port PORT]
44
44
  serve <site-directory> [--host HOST] [--port PORT]
45
45
  check [config] [--json]
46
+ references check <snapshot.json>
46
47
  audit [config]
47
48
  scaffold <template> -n <target> [--config FILE] [--product P]
48
49
 
package/dist/cli.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { readCodeReference } from './code-reference-model.js';
2
3
  import { runExportCommand, exportHelp } from './content-export-command.js';
3
4
  import { cliHelp, docsHelp, skillsHelp, runSkillsCommand } from './cli-discovery.js';
4
5
  import { compareDocumentSnapshots } from './document-sync.js';
@@ -99,6 +100,12 @@ try {
99
100
  else if (command === 'skills') {
100
101
  process.stdout.write(await runSkillsCommand([subcommand, ...rest].filter((value) => value !== undefined)));
101
102
  }
103
+ else if (command === 'references') {
104
+ if (subcommand !== 'check' || rest.length !== 1)
105
+ throw new Error('Usage: shoalrun references check <snapshot.json>');
106
+ const snapshot = await readCodeReference(path.resolve(rest[0]));
107
+ process.stdout.write(JSON.stringify({ status: 'ok', programmingLanguage: snapshot.programmingLanguage, symbols: snapshot.symbols.length }) + '\n');
108
+ }
102
109
  else if (command === 'init') {
103
110
  const args = [subcommand, ...rest].filter((item) => item !== undefined);
104
111
  let directory = '.';
@@ -0,0 +1,85 @@
1
+ import { z } from 'zod';
2
+ export declare const codeReferenceSchema: z.ZodObject<{
3
+ schemaVersion: z.ZodLiteral<1>;
4
+ kind: z.ZodLiteral<"shoalrun-code-reference">;
5
+ programmingLanguage: z.ZodString;
6
+ producer: z.ZodObject<{
7
+ name: z.ZodString;
8
+ version: z.ZodString;
9
+ extractorVersion: z.ZodOptional<z.ZodString>;
10
+ }, z.core.$strict>;
11
+ sourceDigest: z.ZodOptional<z.ZodString>;
12
+ symbols: z.ZodArray<z.ZodObject<{
13
+ id: z.ZodString;
14
+ name: z.ZodString;
15
+ kind: z.ZodEnum<{
16
+ function: "function";
17
+ constructor: "constructor";
18
+ module: "module";
19
+ type: "type";
20
+ constant: "constant";
21
+ enum: "enum";
22
+ method: "method";
23
+ property: "property";
24
+ namespace: "namespace";
25
+ class: "class";
26
+ interface: "interface";
27
+ attribute: "attribute";
28
+ }>;
29
+ parent: z.ZodOptional<z.ZodString>;
30
+ visibility: z.ZodDefault<z.ZodEnum<{
31
+ public: "public";
32
+ private: "private";
33
+ }>>;
34
+ summary: z.ZodOptional<z.ZodString>;
35
+ description: z.ZodOptional<z.ZodString>;
36
+ annotation: z.ZodOptional<z.ZodString>;
37
+ default: z.ZodOptional<z.ZodString>;
38
+ required: z.ZodOptional<z.ZodBoolean>;
39
+ bases: z.ZodOptional<z.ZodArray<z.ZodString>>;
40
+ constructorSignature: z.ZodOptional<z.ZodString>;
41
+ typeReferences: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
42
+ signatures: z.ZodOptional<z.ZodArray<z.ZodString>>;
43
+ parameters: z.ZodOptional<z.ZodArray<z.ZodObject<{
44
+ name: z.ZodString;
45
+ type: z.ZodOptional<z.ZodString>;
46
+ description: z.ZodOptional<z.ZodString>;
47
+ default: z.ZodOptional<z.ZodString>;
48
+ }, z.core.$strict>>>;
49
+ returns: z.ZodOptional<z.ZodObject<{
50
+ type: z.ZodOptional<z.ZodString>;
51
+ description: z.ZodOptional<z.ZodString>;
52
+ }, z.core.$strict>>;
53
+ yields: z.ZodOptional<z.ZodObject<{
54
+ type: z.ZodOptional<z.ZodString>;
55
+ description: z.ZodOptional<z.ZodString>;
56
+ }, z.core.$strict>>;
57
+ raises: z.ZodOptional<z.ZodArray<z.ZodObject<{
58
+ name: z.ZodString;
59
+ type: z.ZodOptional<z.ZodString>;
60
+ description: z.ZodOptional<z.ZodString>;
61
+ default: z.ZodOptional<z.ZodString>;
62
+ }, z.core.$strict>>>;
63
+ examples: z.ZodOptional<z.ZodArray<z.ZodObject<{
64
+ title: z.ZodOptional<z.ZodString>;
65
+ code: z.ZodString;
66
+ }, z.core.$strict>>>;
67
+ seeAlso: z.ZodOptional<z.ZodArray<z.ZodString>>;
68
+ source: z.ZodOptional<z.ZodObject<{
69
+ path: z.ZodString;
70
+ line: z.ZodOptional<z.ZodNumber>;
71
+ }, z.core.$strict>>;
72
+ }, z.core.$strict>>;
73
+ }, z.core.$strict>;
74
+ export type CodeReferenceSnapshot = z.infer<typeof codeReferenceSchema>;
75
+ export type CodeSymbol = CodeReferenceSnapshot['symbols'][number];
76
+ export type CodeReference = {
77
+ catalog: string;
78
+ programmingLanguage: string;
79
+ symbol: CodeSymbol;
80
+ sourceUrl?: string;
81
+ layout?: 'symbols' | 'classes' | 'modules';
82
+ complete?: boolean;
83
+ };
84
+ export declare function validateCodeReference(value: unknown): CodeReferenceSnapshot;
85
+ export declare function readCodeReference(file: string, root?: string): Promise<CodeReferenceSnapshot>;
@@ -0,0 +1,73 @@
1
+ import { z } from 'zod';
2
+ import { readFile, realpath, stat } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ const text = z.string().max(100_000);
5
+ const id = z.string().min(1).max(512).regex(/^[^\s\x00-\x1f]+$/, 'Symbol IDs cannot contain whitespace or control characters');
6
+ const detail = z.object({ name: z.string().min(1).max(512), type: text.optional(), description: text.optional(), default: text.optional() }).strict();
7
+ export const codeReferenceSchema = z.object({
8
+ schemaVersion: z.literal(1),
9
+ kind: z.literal('shoalrun-code-reference'),
10
+ programmingLanguage: z.string().regex(/^[a-z][a-z0-9_-]{0,63}$/),
11
+ producer: z.object({ name: z.string().min(1).max(100), version: z.string().min(1).max(100), extractorVersion: z.string().max(100).optional() }).strict(),
12
+ sourceDigest: z.string().regex(/^[a-f0-9]{64}$/).optional(),
13
+ symbols: z.array(z.object({
14
+ id, name: z.string().min(1).max(512),
15
+ kind: z.enum(['module', 'namespace', 'class', 'interface', 'enum', 'type', 'function', 'method', 'constructor', 'property', 'attribute', 'constant']),
16
+ parent: id.optional(), visibility: z.enum(['public', 'private']).default('public'),
17
+ summary: z.string().max(1000).optional(), description: text.optional(),
18
+ annotation: text.optional(), default: text.optional(), required: z.boolean().optional(),
19
+ bases: z.array(text).max(100).optional(), constructorSignature: text.optional(),
20
+ typeReferences: z.record(z.string().min(1).max(512), id).optional(),
21
+ signatures: z.array(text).max(100).optional(),
22
+ parameters: z.array(detail).max(1000).optional(),
23
+ returns: z.object({ type: text.optional(), description: text.optional() }).strict().optional(),
24
+ yields: z.object({ type: text.optional(), description: text.optional() }).strict().optional(),
25
+ raises: z.array(detail).max(1000).optional(),
26
+ examples: z.array(z.object({ title: z.string().max(512).optional(), code: text }).strict()).max(100).optional(),
27
+ seeAlso: z.array(id).max(1000).optional(),
28
+ source: z.object({ path: z.string().min(1).max(1000).regex(/^(?!\/)(?!.*(?:^|\/)\.{1,2}(?:\/|$))[^/\\\x00:]+(?:\/[^/\\\x00:]+)*$/), line: z.number().int().positive().optional() }).strict().optional()
29
+ }).strict()).min(1).max(10_000)
30
+ }).strict();
31
+ export function validateCodeReference(value) {
32
+ const result = codeReferenceSchema.parse(value);
33
+ const symbols = new Map();
34
+ for (const symbol of result.symbols) {
35
+ if (symbols.has(symbol.id))
36
+ throw new Error(`Duplicate code symbol ${symbol.id}`);
37
+ symbols.set(symbol.id, symbol);
38
+ }
39
+ const complete = new Set();
40
+ for (const symbol of result.symbols) {
41
+ for (const target of [symbol.parent, ...symbol.seeAlso ?? [], ...Object.values(symbol.typeReferences ?? {})])
42
+ if (target && !symbols.has(target))
43
+ throw new Error(`${symbol.id}: unknown code symbol ${target}`);
44
+ const seen = new Set([symbol.id]);
45
+ let parent = symbol.parent;
46
+ while (parent && !complete.has(parent)) {
47
+ if (seen.has(parent))
48
+ throw new Error(`${symbol.id}: cyclic symbol ownership`);
49
+ seen.add(parent);
50
+ parent = symbols.get(parent)?.parent;
51
+ }
52
+ for (const id of seen)
53
+ complete.add(id);
54
+ }
55
+ return result;
56
+ }
57
+ export async function readCodeReference(file, root) {
58
+ const canonical = await realpath(file);
59
+ if (root) {
60
+ const base = await realpath(root);
61
+ if (canonical !== base && !canonical.startsWith(base + path.sep))
62
+ throw new Error('Code reference source escapes the project root');
63
+ }
64
+ if (canonical.split(path.sep).some(part => /^\.env(?:\.|$)|^\.git$|\.(?:local|override)\.md$/i.test(part)))
65
+ throw new Error('Private local files cannot be code reference sources');
66
+ const info = await stat(canonical);
67
+ if (!info.isFile() || info.size > 32 * 1024 * 1024)
68
+ throw new Error('Code reference source must be a regular JSON file at most 32 MiB');
69
+ const bytes = await readFile(canonical);
70
+ if (bytes.length > 32 * 1024 * 1024)
71
+ throw new Error('Code reference source exceeds 32 MiB');
72
+ return validateCodeReference(JSON.parse(bytes.toString('utf8')));
73
+ }
@@ -0,0 +1,23 @@
1
+ import { type CodeReference } from './code-reference-model.js';
2
+ import { type loadConfig } from './config.js';
3
+ import { type ReaderFiltersConfig, type ReaderSelection } from './reader-filters.js';
4
+ import { type Document, type Variant } from './content-source.js';
5
+ import type { AuthoredPublicationConfig, AuthoredPublicationPlan } from './publication-plan.js';
6
+ export declare function codeDocumentId(catalog: string, symbol: string): string;
7
+ export declare function materializeCodeReferences(input: {
8
+ config: AuthoredPublicationConfig & {
9
+ codeReferences?: unknown;
10
+ };
11
+ loaded: Awaited<ReturnType<typeof loadConfig>>;
12
+ plan: AuthoredPublicationPlan;
13
+ base: string;
14
+ basePath: string;
15
+ variants: Variant[];
16
+ language: string;
17
+ readerFilters?: ReaderFiltersConfig;
18
+ contentFilter?: ReaderSelection;
19
+ dependencies: Set<string>;
20
+ allowRouteCollisions?: boolean;
21
+ }): Promise<void>;
22
+ /** Imported prose is inert Markdown; it never enters MDX or project directive expansion. */
23
+ export declare function renderCodeReference(reference: CodeReference, doc: Document, documents: Map<string, Document>): any;