docspack 0.4.0 → 1.1.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 (91) hide show
  1. package/README.md +31 -0
  2. package/dist/agent.d.ts +48 -0
  3. package/dist/agent.d.ts.map +1 -0
  4. package/dist/agent.js +243 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/artifact.d.ts +32 -0
  7. package/dist/artifact.d.ts.map +1 -0
  8. package/dist/artifact.js +78 -0
  9. package/dist/artifact.js.map +1 -0
  10. package/dist/build.d.ts +23 -0
  11. package/dist/build.d.ts.map +1 -1
  12. package/dist/build.js +201 -96
  13. package/dist/build.js.map +1 -1
  14. package/dist/changed.d.ts +31 -0
  15. package/dist/changed.d.ts.map +1 -0
  16. package/dist/changed.js +71 -0
  17. package/dist/changed.js.map +1 -0
  18. package/dist/cli.js +222 -12
  19. package/dist/cli.js.map +1 -1
  20. package/dist/coverage.d.ts +35 -0
  21. package/dist/coverage.d.ts.map +1 -0
  22. package/dist/coverage.js +64 -0
  23. package/dist/coverage.js.map +1 -0
  24. package/dist/db.d.ts +75 -2
  25. package/dist/db.d.ts.map +1 -1
  26. package/dist/db.js +168 -6
  27. package/dist/db.js.map +1 -1
  28. package/dist/discovery.d.ts +14 -0
  29. package/dist/discovery.d.ts.map +1 -1
  30. package/dist/discovery.js +31 -6
  31. package/dist/discovery.js.map +1 -1
  32. package/dist/doctor.d.ts.map +1 -1
  33. package/dist/doctor.js +60 -9
  34. package/dist/doctor.js.map +1 -1
  35. package/dist/endpoints.d.ts +45 -0
  36. package/dist/endpoints.d.ts.map +1 -0
  37. package/dist/endpoints.js +155 -0
  38. package/dist/endpoints.js.map +1 -0
  39. package/dist/help.d.ts.map +1 -1
  40. package/dist/help.js +120 -5
  41. package/dist/help.js.map +1 -1
  42. package/dist/index.d.ts +10 -4
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +10 -4
  45. package/dist/index.js.map +1 -1
  46. package/dist/local.d.ts +67 -0
  47. package/dist/local.d.ts.map +1 -0
  48. package/dist/local.js +242 -0
  49. package/dist/local.js.map +1 -0
  50. package/dist/mcp.d.ts.map +1 -1
  51. package/dist/mcp.js +3 -0
  52. package/dist/mcp.js.map +1 -1
  53. package/dist/preview.d.ts.map +1 -1
  54. package/dist/preview.js +26 -7
  55. package/dist/preview.js.map +1 -1
  56. package/dist/search.d.ts +22 -1
  57. package/dist/search.d.ts.map +1 -1
  58. package/dist/search.js +147 -22
  59. package/dist/search.js.map +1 -1
  60. package/dist/surface.d.ts +45 -0
  61. package/dist/surface.d.ts.map +1 -0
  62. package/dist/surface.js +208 -0
  63. package/dist/surface.js.map +1 -0
  64. package/dist/sync.d.ts +8 -1
  65. package/dist/sync.d.ts.map +1 -1
  66. package/dist/sync.js +50 -1
  67. package/dist/sync.js.map +1 -1
  68. package/dist/verify.d.ts +9 -0
  69. package/dist/verify.d.ts.map +1 -1
  70. package/dist/verify.js +1 -1
  71. package/dist/verify.js.map +1 -1
  72. package/package.json +7 -5
  73. package/src/agent.ts +308 -0
  74. package/src/artifact.ts +110 -0
  75. package/src/build.ts +240 -111
  76. package/src/changed.ts +99 -0
  77. package/src/cli.ts +263 -12
  78. package/src/coverage.ts +96 -0
  79. package/src/db.ts +250 -7
  80. package/src/discovery.ts +40 -5
  81. package/src/doctor.ts +68 -8
  82. package/src/endpoints.ts +184 -0
  83. package/src/help.ts +120 -5
  84. package/src/index.ts +52 -1
  85. package/src/local.ts +335 -0
  86. package/src/mcp.ts +3 -0
  87. package/src/preview.ts +38 -13
  88. package/src/search.ts +203 -23
  89. package/src/surface.ts +265 -0
  90. package/src/sync.ts +66 -2
  91. package/src/verify.ts +1 -1
@@ -0,0 +1,184 @@
1
+ import { HTTP_METHODS } from "@docspack/openapi";
2
+
3
+ /**
4
+ * Answering a question that names an HTTP request, by address rather than by ranking.
5
+ *
6
+ * This is the same argument `search.ts` makes for exported symbols, applied to endpoints. A query
7
+ * like `POST /v1/charges` is not a phrase, it is a key: ranked as prose it matches every chunk that
8
+ * mentions charges, and the overview page — which says "charges" six times — outranks the one chunk
9
+ * that describes the operation. `/v1` and `charges` are also the two worst possible search terms in
10
+ * a document where every path starts with `/v1`.
11
+ *
12
+ * So an endpoint an operation chunk declares is looked up exactly, and the matching chunk is pinned
13
+ * ahead of anything the ranker found. `docspack build --openapi` records both spellings of every
14
+ * operation in its chunk's `entities` — `POST /v1/charges` and `createCharge` — and the second one
15
+ * already worked, because an operation id is identifier-shaped and the symbol path handles it. The
16
+ * first one could not match anything at all.
17
+ */
18
+
19
+ /** An operation a chunk declares. */
20
+ export interface EndpointEntry {
21
+ readonly chunkId: string;
22
+ readonly method: string;
23
+ /** Template path as the document wrote it, braces included. */
24
+ readonly path: string;
25
+ }
26
+
27
+ /**
28
+ * How many endpoints one answer may pin.
29
+ *
30
+ * Two, matching `MAX_DECLARATIONS`. A question names one request, occasionally two — "how do I
31
+ * create a charge and then refund it". More than that and the addresses are incidental, and pinning
32
+ * them spends the budget on operations nobody asked about.
33
+ */
34
+ export const MAX_ENDPOINTS = 2;
35
+
36
+ const METHODS = new Set<string>(HTTP_METHODS);
37
+
38
+ /**
39
+ * An endpoint reference in a query.
40
+ *
41
+ * The path is required to contain a `/`, which is what keeps `GET the newest invoice` from being
42
+ * read as a request for a path called `the`. A full URL is accepted and reduced to its path, because
43
+ * that is what an agent has in front of it when it is reading a log line or a network tab.
44
+ */
45
+ const REFERENCE = /\b([A-Za-z]+)\s+(\S*\/\S*)/g;
46
+
47
+ /** A bare path, for a question that names an endpoint without naming a method. */
48
+ const BARE_PATH = /(?:^|\s)(\/[A-Za-z0-9{}._~%\-/]*)/g;
49
+
50
+ /** Collects the endpoints a set of chunks declares, from their manifest entities. */
51
+ export function endpointIndex(
52
+ chunks: Iterable<{ readonly chunkId: string; readonly entities: readonly string[] }>,
53
+ ): EndpointEntry[] {
54
+ const entries: EndpointEntry[] = [];
55
+ for (const chunk of chunks) {
56
+ for (const entity of chunk.entities) {
57
+ const parsed = parseEndpoint(entity);
58
+ if (parsed !== undefined) entries.push({ chunkId: chunk.chunkId, ...parsed });
59
+ }
60
+ }
61
+ return entries;
62
+ }
63
+
64
+ /** Reads `POST /v1/charges` as a method and a path. */
65
+ function parseEndpoint(entity: string): { method: string; path: string } | undefined {
66
+ const match = /^([A-Z]+) (\/\S*)$/.exec(entity);
67
+ const method = match?.[1];
68
+ const path = match?.[2];
69
+ if (method === undefined || path === undefined || !METHODS.has(method)) return undefined;
70
+ return { method, path };
71
+ }
72
+
73
+ /**
74
+ * The operations a query addresses, in the order the query named them.
75
+ *
76
+ * An exact match wins. Failing that, the path is matched against the template a document declared,
77
+ * so an agent holding a real URL — `GET /v1/charges/ch_3Ox7`, copied out of a log — still reaches
78
+ * `GET /v1/charges/{charge}`. That is the case this exists for: a concrete request is what somebody
79
+ * actually has, and a template is what the document contains.
80
+ */
81
+ export function matchEndpoints(
82
+ query: string,
83
+ index: readonly EndpointEntry[],
84
+ limit = MAX_ENDPOINTS,
85
+ ): EndpointEntry[] {
86
+ if (index.length === 0) return [];
87
+
88
+ const found: EndpointEntry[] = [];
89
+ const seen = new Set<string>();
90
+ const take = (entry: EndpointEntry): void => {
91
+ if (seen.has(entry.chunkId) || found.length >= limit) return;
92
+ seen.add(entry.chunkId);
93
+ found.push(entry);
94
+ };
95
+
96
+ for (const reference of references(query)) {
97
+ if (found.length >= limit) break;
98
+ const exact = index.filter(
99
+ (entry) => entry.method === reference.method && entry.path === reference.path,
100
+ );
101
+ if (exact.length > 0) {
102
+ for (const entry of exact) take(entry);
103
+ continue;
104
+ }
105
+ for (const entry of index) {
106
+ if (entry.method !== reference.method) continue;
107
+ if (templateMatches(entry.path, reference.path)) take(entry);
108
+ }
109
+ }
110
+
111
+ // Only when no method was named anywhere: otherwise a question that spells out `POST /charges`
112
+ // would also pin the `GET` on the same path, which is not what it asked for.
113
+ if (found.length === 0) {
114
+ for (const path of barePaths(query)) {
115
+ for (const entry of index) {
116
+ if (entry.path === path || templateMatches(entry.path, path)) take(entry);
117
+ }
118
+ }
119
+ }
120
+
121
+ return found;
122
+ }
123
+
124
+ /** Method-and-path references in a query, normalized. */
125
+ function references(query: string): { method: string; path: string }[] {
126
+ const found: { method: string; path: string }[] = [];
127
+ for (const match of query.matchAll(REFERENCE)) {
128
+ const method = match[1]?.toUpperCase();
129
+ const raw = match[2];
130
+ if (method === undefined || raw === undefined || !METHODS.has(method)) continue;
131
+ const path = toPath(raw);
132
+ if (path !== undefined) found.push({ method, path });
133
+ }
134
+ return found;
135
+ }
136
+
137
+ function barePaths(query: string): string[] {
138
+ const found: string[] = [];
139
+ for (const match of query.matchAll(BARE_PATH)) {
140
+ const path = match[1] === undefined ? undefined : toPath(match[1]);
141
+ // A lone `/` addresses nothing, and every sentence with a slash in it would otherwise be read
142
+ // as naming the document's root.
143
+ if (path !== undefined && path.length > 1) found.push(path);
144
+ }
145
+ return found;
146
+ }
147
+
148
+ /**
149
+ * Reduces what someone wrote to a path.
150
+ *
151
+ * A full URL keeps only its path. A query string and trailing sentence punctuation are dropped: the
152
+ * query string is values rather than address, and a question mark at the end of `GET /charges?` is
153
+ * almost never an empty query string.
154
+ */
155
+ function toPath(raw: string): string | undefined {
156
+ let value = raw.replace(/[),.;:'"`]+$/, "");
157
+ const scheme = /^[a-z][a-z0-9+.-]*:\/\//i.exec(value);
158
+ if (scheme !== null) {
159
+ try {
160
+ value = new URL(value).pathname;
161
+ } catch {
162
+ return undefined;
163
+ }
164
+ }
165
+ const queryAt = value.indexOf("?");
166
+ if (queryAt >= 0) value = value.slice(0, queryAt);
167
+ if (!value.startsWith("/")) return undefined;
168
+ // Repeated and trailing slashes are noise a URL bar forgives, and a path whose segment count is
169
+ // off by a stray slash matches no template at all — which reads as "the endpoint is undocumented".
170
+ return value.replace(/\/{2,}/g, "/").replace(/\/+$/, "") || "/";
171
+ }
172
+
173
+ /** Whether a concrete path fills in a template: `/v1/charges/{charge}` against `/v1/charges/ch_3`. */
174
+ function templateMatches(template: string, concrete: string): boolean {
175
+ const left = template.split("/");
176
+ const right = concrete.split("/");
177
+ if (left.length !== right.length) return false;
178
+ return left.every((segment, index) => {
179
+ // A template segment matches any one segment, but not an empty one: `/charges/` is not a
180
+ // request for a charge.
181
+ if (segment.startsWith("{") && segment.endsWith("}")) return (right[index] ?? "").length > 0;
182
+ return segment === right[index];
183
+ });
184
+ }
package/src/help.ts CHANGED
@@ -37,12 +37,21 @@ export const COMMANDS: readonly CommandHelp[] = [
37
37
  summary: "Index the docs packages this project depends on",
38
38
  group: "core",
39
39
  usage: "docspack sync [options]",
40
- options: [["--force", "re-index packages already in the store"]],
40
+ options: [
41
+ ["--force", "re-index packages already in the store"],
42
+ ["--no-artifacts", "skip the declarations derived from installed libraries"],
43
+ ],
41
44
  detail: [
42
45
  "Reads node_modules and indexes every @vendor/docspack and @docspack-community/<name>",
43
46
  "package this project declares. Makes no network requests.",
47
+ "",
48
+ "It also reads each installed library's own type declarations and indexes one entry per",
49
+ "exported name. Half of a well-documented library's exports are mentioned in no",
50
+ "documentation anyone published, and those declarations are the only local answer for",
51
+ "them. They are looked up by name, never ranked against prose, so they cannot crowd out",
52
+ "the documentation that does exist.",
44
53
  ],
45
- examples: ["docspack sync", "docspack sync --force"],
54
+ examples: ["docspack sync", "docspack sync --force", "docspack sync --no-artifacts"],
46
55
  },
47
56
  {
48
57
  name: "ask",
@@ -54,12 +63,64 @@ export const COMMANDS: readonly CommandHelp[] = [
54
63
  "Answers from the installed versions, in the Markdown an agent should read. Exits 0 when",
55
64
  "chunks were returned, 3 when a docs package is installed but not indexed, and 4 when",
56
65
  "everything installed is indexed and nothing matched.",
66
+ "",
67
+ "When the question names something an installed library exports and no documentation",
68
+ "mentions, the answer leads with that name's declaration from the installed build and says",
69
+ "the documentation does not cover it. Ranking alone cannot tell that apart from a match.",
57
70
  ],
58
71
  examples: [
59
72
  'docspack ask "how do I verify a webhook signature"',
60
73
  'docspack ask "webhook signature" --package stripe --limit 5',
61
74
  ],
62
75
  },
76
+ {
77
+ name: "index",
78
+ summary: "Index this project's own sources, so an agent can ask them instead of reading them",
79
+ group: "core",
80
+ usage: "docspack index [--from <dir>] [--from-json <file|->]",
81
+ options: [
82
+ ["--from <dir>", "directory of Markdown to index"],
83
+ ["--from-json <f>", "JSON records to index, or `-` for standard input"],
84
+ ["--name <s>", "name for the corpus (default: derived from the source)"],
85
+ ["--force", "re-index even when no source has changed"],
86
+ ],
87
+ detail: [
88
+ "For a corpus this project already has rather than one somebody published: notes, an",
89
+ "export, rows out of a query. The payload is built in a temporary directory and thrown",
90
+ "away; what is kept is the index, in `.docspack/local.db`, which is a plaintext copy of",
91
+ "whatever was indexed and is gitignored on the tool's behalf.",
92
+ "",
93
+ "Records arrive as JSON so no database driver is needed: `sqlite3 -json … | docspack index",
94
+ "--from-json -`. A record with an `id` becomes one chunk under that id, because a row's",
95
+ "identity is its key.",
96
+ "",
97
+ "What was indexed is recorded with each source's size, mtime and hash, so a re-run does",
98
+ "nothing when nothing has changed and `recall` can say when an answer may be superseded.",
99
+ ],
100
+ examples: [
101
+ "docspack index --from ./notes",
102
+ "sqlite3 -json shop.db 'select id, title, body as text from posts' | docspack index --from-json -",
103
+ ],
104
+ },
105
+ {
106
+ name: "recall",
107
+ summary: "Answer from this project's indexed corpus, not from its dependencies",
108
+ group: "core",
109
+ usage: 'docspack recall "<question>"',
110
+ options: [
111
+ ["--limit <n>", `maximum chunks to return (default ${LIMIT})`],
112
+ ["--max-tokens <n>", `token ceiling for the result set (default ${MAX_TOKENS})`],
113
+ ],
114
+ detail: [
115
+ "Separate from `ask` on purpose. `ask` answers from the versions this project installed,",
116
+ "and a working corpus is never one of them — so a corpus cannot reach an answer about a",
117
+ "dependency, and a dependency cannot reach an answer about your notes.",
118
+ "",
119
+ "An answer leads with a warning when a source has changed since it was indexed. Exits 1",
120
+ "when nothing matched.",
121
+ ],
122
+ examples: ['docspack recall "what did we decide about retries"'],
123
+ },
63
124
  {
64
125
  name: "search",
65
126
  summary: "Same index, formatted for a human reading the terminal",
@@ -73,9 +134,57 @@ export const COMMANDS: readonly CommandHelp[] = [
73
134
  name: "list",
74
135
  summary: "Show this project's docs packages and their index state",
75
136
  group: "core",
76
- usage: "docspack list",
137
+ usage: "docspack list [options]",
138
+ options: [["--coverage", "how much of each documented library's exports the prose mentions"]],
139
+ detail: [
140
+ "Coverage is mechanical: the exported names a library declares, against the names its",
141
+ "documentation mentions anywhere. It is reported, never gated on — a page listing every",
142
+ "export and explaining none would score full marks.",
143
+ ],
144
+ examples: ["docspack list", "docspack list --coverage", "docspack list --json"],
145
+ },
146
+ {
147
+ name: "agent",
148
+ summary: "Wire docspack into the agent tooling this project already uses",
149
+ group: "core",
150
+ usage: "docspack agent <install|check> [options]",
151
+ options: [
152
+ ["--feedback", "also include recording documentation problems"],
153
+ ["--hooks", "add a SessionStart hook that keeps the index in step"],
154
+ ["--mcp", "add the MCP server to .mcp.json"],
155
+ ["--dry-run", "print what would be written and write nothing"],
156
+ ],
157
+ detail: [
158
+ "`install` writes a marked block into AGENTS.md or CLAUDE.md — whichever the project",
159
+ "already has — and a skill into .claude/skills/docspack/ when the project uses Claude",
160
+ "Code. Everything outside the markers is left alone, and re-running rewrites the block",
161
+ "rather than appending a second copy.",
162
+ "",
163
+ "`check` writes nothing and exits non-zero when the wiring is missing or out of date, so",
164
+ "CI notices a pasted instruction that has drifted from what the tool now does.",
165
+ ],
166
+ examples: [
167
+ "docspack agent install",
168
+ "docspack agent install --feedback --hooks",
169
+ "docspack agent check",
170
+ ],
171
+ },
172
+ {
173
+ name: "changed",
174
+ summary: "What a library's exports gained and lost between two versions",
175
+ group: "core",
176
+ usage: "docspack changed <library>[@version]",
77
177
  options: [],
78
- examples: ["docspack list", "docspack list --json"],
178
+ detail: [
179
+ "Compares two versions already in the global store, which is shared by every project on",
180
+ "this machine, so nothing is fetched. Without a version it compares what is installed here",
181
+ "against the most recently indexed other version.",
182
+ "",
183
+ "Upgrades are overwhelmingly additive: the useful answer is what exists now that an older",
184
+ "release did not have, and which of those names no documentation here mentions — the ones",
185
+ "a model can know from neither its training data nor the vendor's pages.",
186
+ ],
187
+ examples: ["docspack changed hono", "docspack changed hono@4.0.0"],
79
188
  },
80
189
  {
81
190
  name: "verify",
@@ -180,7 +289,7 @@ export const COMMANDS: readonly CommandHelp[] = [
180
289
  usage: "docspack build [source] [options]",
181
290
  options: [
182
291
  ["--from <dir>", "directory of Markdown to package"],
183
- ["--openapi <file>", "OpenAPI JSON to package, one chunk per operation"],
292
+ ["--openapi <file>", "OpenAPI 3 document (JSON or YAML), one chunk per operation"],
184
293
  ["--name <name>", "package name, e.g. @acme/docspack"],
185
294
  ["--pkg-version <v>", "package version"],
186
295
  ["--out <dir>", "output directory (default: the current directory)"],
@@ -195,6 +304,11 @@ export const COMMANDS: readonly CommandHelp[] = [
195
304
  "the budget: use it for generated reference, where a heading is a field name and one chunk",
196
305
  "per heading is hundreds of chunks too small to answer anything.",
197
306
  "",
307
+ "--openapi writes one chunk per operation: the base URL, the credential, the inputs with",
308
+ "their types, the response, the failures and a runnable curl call, in LAPIS notation. Each",
309
+ "chunk answers to both `POST /v1/charges` and the operationId, so `docspack ask` can be",
310
+ "given either. Combine it with --from to publish prose and an API in one package.",
311
+ "",
198
312
  "With no flags, settings are read from the docspack key of the package.json in --out.",
199
313
  ],
200
314
  examples: [
@@ -202,6 +316,7 @@ export const COMMANDS: readonly CommandHelp[] = [
202
316
  "docspack build --from ./docs --name @acme/docspack --pkg-version 1.4.0",
203
317
  "docspack build --from ./reference --min-chunk-tokens 400 --max-chunk-tokens 900",
204
318
  "docspack build --openapi ./openapi.json",
319
+ "docspack build --from ./docs --openapi ./openapi.json",
205
320
  ],
206
321
  },
207
322
  {
package/src/index.ts CHANGED
@@ -1,4 +1,21 @@
1
- export { type BuildOptions, type BuildResult, buildPackage } from "./build.js";
1
+ export {
2
+ type AgentFile,
3
+ type AgentOptions,
4
+ type AgentPlan,
5
+ applyAgentSetup,
6
+ planAgentSetup,
7
+ type SurfaceKind,
8
+ withBlock,
9
+ } from "./agent.js";
10
+ export { type ArtifactPackage, readArtifact } from "./artifact.js";
11
+ export {
12
+ type BuildOptions,
13
+ type BuildResult,
14
+ buildPackage,
15
+ LOCAL_VERSION,
16
+ localPackageName,
17
+ } from "./build.js";
18
+ export { type ChangedOptions, changedSurface, type SurfaceChange } from "./changed.js";
2
19
  export {
3
20
  type BuildConfig,
4
21
  CONFIG_KEY,
@@ -7,19 +24,34 @@ export {
7
24
  parseFeedbackChannel,
8
25
  readBuildConfig,
9
26
  } from "./config.js";
27
+ export {
28
+ type CoverageOptions,
29
+ type CoverageReport,
30
+ identifiers,
31
+ type LibraryCoverage,
32
+ measureCoverage,
33
+ } from "./coverage.js";
10
34
  export {
11
35
  defaultStorePath,
12
36
  type IndexedChunk,
13
37
  type IndexedPackage,
38
+ type IndexedSource,
39
+ LOCAL_STORE_DIR,
40
+ localStorePath,
41
+ type PackageKind,
14
42
  type SearchHit,
15
43
  type SearchOptions,
16
44
  Store,
45
+ type SymbolHit,
17
46
  silenceSqliteWarning,
18
47
  toFtsQuery,
48
+ toPackageKind,
19
49
  } from "./db.js";
20
50
  export {
51
+ type DiscoveredLibrary,
21
52
  type DiscoveredPackage,
22
53
  type Discovery,
54
+ discoverLibraries,
23
55
  discoverPackages,
24
56
  projectPackageIds,
25
57
  resolvePackageDir,
@@ -90,6 +122,17 @@ export {
90
122
  type LlmsTxtSection,
91
123
  parseLlmsTxt,
92
124
  } from "./llms-txt.js";
125
+ export {
126
+ type IndexLocalOptions,
127
+ type IndexLocalResult,
128
+ indexLocal,
129
+ type RecallHit,
130
+ type RecallOptions,
131
+ type RecallResult,
132
+ recallLocal,
133
+ renderRecall,
134
+ type StaleSource,
135
+ } from "./local.js";
93
136
  export { createMcpServer, type McpOptions, startMcpServer } from "./mcp.js";
94
137
  export { type PreviewOptions, type PreviewResult, previewPackage } from "./preview.js";
95
138
  export { type Choice, defaultStreams, Prompter, type PromptStreams } from "./prompt.js";
@@ -136,6 +179,13 @@ export {
136
179
  type SubmitOptions,
137
180
  type SubmitReport,
138
181
  } from "./submit.js";
182
+ export {
183
+ declarationOf,
184
+ type ExportedSymbol,
185
+ hasJsdoc,
186
+ type PublicSurface,
187
+ readPublicSurface,
188
+ } from "./surface.js";
139
189
  export {
140
190
  type SyncedPackage,
141
191
  type SyncOptions,
@@ -145,6 +195,7 @@ export {
145
195
  } from "./sync.js";
146
196
  export {
147
197
  type DriftFinding,
198
+ documentedLibraries,
148
199
  type VerifiedPackage,
149
200
  type VerifyOptions,
150
201
  type VerifyReport,