@codedrifters/configulator 0.0.273 → 0.0.275

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/lib/index.mjs CHANGED
@@ -8487,6 +8487,63 @@ function buildDocsSyncSubAgent(_paths) {
8487
8487
  "",
8488
8488
  "---",
8489
8489
  "",
8490
+ "## Phase 1: Scan",
8491
+ "",
8492
+ "Phase 1 walks the repo, runs every registered drift check, and",
8493
+ "writes a single combined **audit report** to disk. Phase 1 never",
8494
+ "edits documentation \u2014 only the persisted report changes between",
8495
+ "scan and fix.",
8496
+ "",
8497
+ "### Audit report",
8498
+ "",
8499
+ "The report shape is exported from `@codedrifters/configulator`",
8500
+ "as `AuditReport` (under `src/docs-sync/scan/`) so Phase 2 and",
8501
+ "any downstream consumers share one definition. Reports are",
8502
+ "persisted at:",
8503
+ "",
8504
+ "```",
8505
+ ".claude/state/docs-sync/<issue-number>-audit.json",
8506
+ "```",
8507
+ "",
8508
+ "Every report carries a `schemaVersion`, the `issueNumber`, the",
8509
+ "invocation `mode` (`pr` or `audit`), the `generatedAt` UTC",
8510
+ "timestamp, the `repoRoot`, and an optional `scope` label, plus",
8511
+ "two parallel views of the findings:",
8512
+ "",
8513
+ "- **`categories`** \u2014 findings grouped by drift-check category.",
8514
+ " Every category key is always present; empty arrays are",
8515
+ " persisted explicitly. The five categories are `apiDiff`,",
8516
+ " `tsdocCoverage`, `referenceMismatches`, `linkFailures`, and",
8517
+ " `sampleFailures`.",
8518
+ "- **`findings`** \u2014 the same records re-aggregated as a single",
8519
+ " flat array, sorted by severity (`blocking` first), then",
8520
+ " category, file, line, and subject. Provided so consumers",
8521
+ " that don't need the category grouping can iterate one array",
8522
+ " and see the merge-blocking findings at the top.",
8523
+ "",
8524
+ "Every finding carries a `category`, `severity`",
8525
+ "(`mechanical` / `advisory` / `blocking`), `location`, `subject`,",
8526
+ "`details`, and an optional `fixHint` for the Phase 2 fix agent.",
8527
+ "",
8528
+ "### Orchestrator",
8529
+ "",
8530
+ "The scan is driven by `runScan(...)` (also exported under",
8531
+ "`src/docs-sync/scan/`). The orchestrator accepts a list of",
8532
+ "`AuditCheckRunner` instances, invokes each one in registration",
8533
+ "order, merges the findings into the report, and (optionally)",
8534
+ "persists the report to disk. The default check list is empty \u2014",
8535
+ "this skeleton release runs cleanly with no checks registered",
8536
+ "and produces a schema-compliant report whose category arrays",
8537
+ "are all empty.",
8538
+ "",
8539
+ "Children of the parent docs-sync epic plug runners into the",
8540
+ "orchestrator: API/TSDoc/reference checks land first, link",
8541
+ "and fenced-sample checks land second, the fix phase reads the",
8542
+ "persisted report, and the audit-mode walker reuses the same",
8543
+ "report shape.",
8544
+ "",
8545
+ "---",
8546
+ "",
8490
8547
  "## Write Boundaries",
8491
8548
  "",
8492
8549
  "Even once the pipeline is wired, the following boundaries are",
@@ -9026,6 +9083,126 @@ var checkLinksProcedure = {
9026
9083
  description: "Link integrity checker that wraps `astro check` (internal links) and `lychee` (external URLs) and normalizes their output into a single JSON-array stream of { url, docPath, line, kind, reason } records. Detection is data: the helper exits 0 when a tool ran successfully regardless of how many broken links it reported. Non-zero exits are reserved for tool-level failures.",
9027
9084
  content: renderCheckLinksProcedure()
9028
9085
  };
9086
+ function renderCheckDocSamplesProcedure() {
9087
+ const nodeScript = [
9088
+ "(async () => {",
9089
+ " const { compileFencedSamples } = await import('@codedrifters/configulator');",
9090
+ " const docsRoot = process.argv[1];",
9091
+ " const failures = compileFencedSamples({ docsRoot });",
9092
+ " process.stdout.write(JSON.stringify(failures));",
9093
+ "})().catch((err) => {",
9094
+ " console.error('check-doc-samples.sh: ' + (err && err.stack ? err.stack : err));",
9095
+ " process.exit(3);",
9096
+ "});"
9097
+ ].join("\n");
9098
+ return [
9099
+ "#!/usr/bin/env bash",
9100
+ "# check-doc-samples.sh \u2014 Compile fenced TS/TSX samples in the Starlight docs.",
9101
+ "#",
9102
+ "# Usage:",
9103
+ "# .claude/procedures/check-doc-samples.sh <docs-root>",
9104
+ "#",
9105
+ "# Where:",
9106
+ "# <docs-root> \u2014 path to the markdown content tree",
9107
+ "# (e.g. `docs/src/content/docs`). Walked recursively",
9108
+ "# for `*.md` files.",
9109
+ "#",
9110
+ "# Wraps the `compileFencedSamples` API exported from",
9111
+ "# `@codedrifters/configulator`. For every fenced ` ```ts `,",
9112
+ "# ` ```typescript `, ` ```tsx `, or ` ```typescriptreact ` block in",
9113
+ "# the docs, the helper writes the sample to an in-memory file,",
9114
+ "# runs the TypeScript compiler against it (in-process, via the TS",
9115
+ "# compiler API), and reports any compilation diagnostics.",
9116
+ "#",
9117
+ "# Skipped samples (fence meta `skip` / `no-check`, or first line",
9118
+ "# `// @no-check`) are passed through unchecked.",
9119
+ "#",
9120
+ "# Output (stdout, single JSON array):",
9121
+ "#",
9122
+ "# [",
9123
+ "# {",
9124
+ '# "docPath": "<path relative to <docs-root>>",',
9125
+ '# "line": <1-indexed line number of the opening fence>,',
9126
+ '# "fenceIndex": <0-indexed fenced-block position within the doc>,',
9127
+ '# "lang": "ts" | "typescript" | "tsx" | "typescriptreact",',
9128
+ '# "diagnostics": [ "<TS<code>: <message>>", ... ]',
9129
+ "# },",
9130
+ "# ...",
9131
+ "# ]",
9132
+ "#",
9133
+ "# An empty array (`[]`) is emitted when every sample compiled.",
9134
+ "# Detection is **data**, not failure: this helper exits 0 when the",
9135
+ "# compilation phase ran successfully, regardless of how many",
9136
+ "# samples failed to compile. The downstream docs-sync scan phase",
9137
+ "# (#520) is responsible for treating failures as one of the two",
9138
+ "# hard-block cases per the parent epic.",
9139
+ "#",
9140
+ "# Exit codes:",
9141
+ "# 0 \u2014 compilation phase ran; failures (zero or more) are on",
9142
+ "# stdout as a JSON array.",
9143
+ "# 1 \u2014 usage error (missing args, unreadable docs root).",
9144
+ "# 2 \u2014 a required binary is not on PATH (`node` / `pnpm`).",
9145
+ "# 3 \u2014 the compilation phase threw an unhandled exception.",
9146
+ "# Stderr carries the diagnostic.",
9147
+ "#",
9148
+ "# Dependencies: expects `node` and `pnpm` on PATH and the workspace",
9149
+ "# `@codedrifters/configulator` package to be installed (the helper",
9150
+ "# resolves the API through `pnpm exec node` from the repo root).",
9151
+ "",
9152
+ "set -uo pipefail",
9153
+ "",
9154
+ "err() {",
9155
+ ' printf "check-doc-samples.sh: %s\\n" "$*" >&2',
9156
+ "}",
9157
+ "",
9158
+ 'if [ "$#" -lt 1 ]; then',
9159
+ ' err "usage: check-doc-samples.sh <docs-root>"',
9160
+ " exit 1",
9161
+ "fi",
9162
+ "",
9163
+ 'docs_root="$1"',
9164
+ "",
9165
+ 'if [ ! -d "$docs_root" ]; then',
9166
+ ' err "docs root not found: $docs_root"',
9167
+ " exit 1",
9168
+ "fi",
9169
+ "",
9170
+ "if ! command -v node >/dev/null 2>&1; then",
9171
+ ' err "node is required but not on PATH"',
9172
+ " exit 2",
9173
+ "fi",
9174
+ "",
9175
+ "if ! command -v pnpm >/dev/null 2>&1; then",
9176
+ ' err "pnpm is required but not on PATH"',
9177
+ " exit 2",
9178
+ "fi",
9179
+ "",
9180
+ "# Resolve docs_root to an absolute path so the inline node script",
9181
+ "# is independent of the cwd `pnpm exec` chooses.",
9182
+ 'docs_root_abs="$(cd "$docs_root" && pwd)"',
9183
+ "",
9184
+ "# Run the inline node script through `pnpm exec` so module",
9185
+ "# resolution finds `@codedrifters/configulator` via the workspace",
9186
+ "# even when the helper is invoked from a sub-package directory.",
9187
+ "# The `--input-type=module` flag lets us use top-level `await` and",
9188
+ "# `import()` cleanly. Diagnostics from the script flow to stderr;",
9189
+ "# stdout carries only the JSON array.",
9190
+ 'pnpm exec node --input-type=module -e "' + nodeScript.replace(/"/g, '\\"') + '" "$docs_root_abs"',
9191
+ "status=$?",
9192
+ "",
9193
+ 'if [ "$status" -ne 0 ]; then',
9194
+ ' err "compileFencedSamples exited with status $status"',
9195
+ " exit 3",
9196
+ "fi",
9197
+ "",
9198
+ "exit 0"
9199
+ ].join("\n");
9200
+ }
9201
+ var checkDocSamplesProcedure = {
9202
+ name: "check-doc-samples.sh",
9203
+ description: "Fenced-sample compilation checker that wraps the `compileFencedSamples` API and emits a JSON-array stream of { docPath, line, fenceIndex, lang, diagnostics } failure records. Skipped samples (meta `skip`/`no-check`, or first-line `// @no-check`) are passed through unchecked. Detection is data: the helper exits 0 whenever compilation ran successfully regardless of failure count.",
9204
+ content: renderCheckDocSamplesProcedure()
9205
+ };
9029
9206
  function buildDocsSyncBundle(paths = DEFAULT_AGENT_PATHS) {
9030
9207
  return {
9031
9208
  name: "docs-sync",
@@ -9075,7 +9252,11 @@ function buildDocsSyncBundle(paths = DEFAULT_AGENT_PATHS) {
9075
9252
  ],
9076
9253
  skills: [buildDocsSyncPrSkill(), buildDocsSyncAuditSkill()],
9077
9254
  subAgents: [buildDocsSyncSubAgent(paths)],
9078
- procedures: [extractApiProcedure, checkLinksProcedure],
9255
+ procedures: [
9256
+ extractApiProcedure,
9257
+ checkLinksProcedure,
9258
+ checkDocSamplesProcedure
9259
+ ],
9079
9260
  labels: [
9080
9261
  {
9081
9262
  name: "type:docs-sync",
@@ -26819,8 +27000,8 @@ var FALLBACKS = {
26819
27000
  monorepoLayoutSeedBlock: ""
26820
27001
  };
26821
27002
  var TEMPLATE_RE = /\{\{(\w+(?:\.\w+)*)\}\}/g;
26822
- function getNestedValue(obj, path4) {
26823
- const parts = path4.split(".");
27003
+ function getNestedValue(obj, path7) {
27004
+ const parts = path7.split(".");
26824
27005
  let current = obj;
26825
27006
  for (const part of parts) {
26826
27007
  if (current == null || typeof current !== "object") {
@@ -27046,20 +27227,20 @@ var ClaudeRenderer = class _ClaudeRenderer {
27046
27227
  obj.excludedCommands = [...sandbox.excludedCommands];
27047
27228
  }
27048
27229
  if (sandbox.filesystem) {
27049
- const fs2 = {};
27230
+ const fs4 = {};
27050
27231
  if (sandbox.filesystem.allowRead?.length) {
27051
- fs2.allowRead = [...sandbox.filesystem.allowRead];
27232
+ fs4.allowRead = [...sandbox.filesystem.allowRead];
27052
27233
  }
27053
27234
  if (sandbox.filesystem.denyRead?.length) {
27054
- fs2.denyRead = [...sandbox.filesystem.denyRead];
27235
+ fs4.denyRead = [...sandbox.filesystem.denyRead];
27055
27236
  }
27056
27237
  if (sandbox.filesystem.allowWrite?.length) {
27057
- fs2.allowWrite = [...sandbox.filesystem.allowWrite];
27238
+ fs4.allowWrite = [...sandbox.filesystem.allowWrite];
27058
27239
  }
27059
27240
  if (sandbox.filesystem.denyWrite?.length) {
27060
- fs2.denyWrite = [...sandbox.filesystem.denyWrite];
27241
+ fs4.denyWrite = [...sandbox.filesystem.denyWrite];
27061
27242
  }
27062
- if (Object.keys(fs2).length > 0) obj.filesystem = fs2;
27243
+ if (Object.keys(fs4).length > 0) obj.filesystem = fs4;
27063
27244
  }
27064
27245
  if (sandbox.network) {
27065
27246
  const net = {};
@@ -28921,10 +29102,754 @@ function stripYamlFrontmatter(source) {
28921
29102
  return lines.join("\n");
28922
29103
  }
28923
29104
 
28924
- // src/docs-sync/tsdoc-coverage/coverage.ts
29105
+ // src/docs-sync/sample-compilation/compilation.ts
29106
+ import * as path4 from "path";
29107
+ import * as ts from "typescript";
29108
+
29109
+ // src/docs-sync/sample-compilation/extraction.ts
29110
+ import * as fs2 from "fs";
28925
29111
  import * as path3 from "path";
29112
+ import { fromMarkdown as fromMarkdown2 } from "mdast-util-from-markdown";
29113
+ var SampleLang = {
29114
+ Ts: "ts",
29115
+ Typescript: "typescript",
29116
+ Tsx: "tsx",
29117
+ Typescriptreact: "typescriptreact"
29118
+ };
29119
+ var DEFAULT_DOCS_ROOT2 = "docs/src/content/docs";
29120
+ var PLAIN_LANGS = /* @__PURE__ */ new Set([SampleLang.Ts, SampleLang.Typescript]);
29121
+ var JSX_LANGS = /* @__PURE__ */ new Set([
29122
+ SampleLang.Tsx,
29123
+ SampleLang.Typescriptreact
29124
+ ]);
29125
+ function extractFencedSamples(options = {}) {
29126
+ const docsRoot = path3.resolve(options.docsRoot ?? DEFAULT_DOCS_ROOT2);
29127
+ const includeTsx = options.includeTsx ?? true;
29128
+ if (!fs2.existsSync(docsRoot)) {
29129
+ return [];
29130
+ }
29131
+ const records = [];
29132
+ for (const absolutePath of walkMarkdownFiles2(docsRoot)) {
29133
+ const docPath = toPosix2(path3.relative(docsRoot, absolutePath));
29134
+ const source = fs2.readFileSync(absolutePath, "utf-8");
29135
+ const tree = fromMarkdown2(stripYamlFrontmatter2(source));
29136
+ let fenceIndex = 0;
29137
+ collectFencedCode(tree, (node) => {
29138
+ const lang = normalizeLang(node.lang);
29139
+ if (lang === void 0) {
29140
+ return;
29141
+ }
29142
+ if (!includeTsx && JSX_LANGS.has(lang)) {
29143
+ return;
29144
+ }
29145
+ if (!PLAIN_LANGS.has(lang) && !JSX_LANGS.has(lang)) {
29146
+ return;
29147
+ }
29148
+ const start = node.position?.start;
29149
+ if (!start) {
29150
+ return;
29151
+ }
29152
+ const skip = detectSkip(node);
29153
+ records.push({
29154
+ docPath,
29155
+ line: start.line,
29156
+ fenceIndex,
29157
+ lang,
29158
+ code: node.value ?? "",
29159
+ skipped: skip.skipped,
29160
+ skipReason: skip.reason
29161
+ });
29162
+ fenceIndex += 1;
29163
+ });
29164
+ }
29165
+ records.sort((a, b) => {
29166
+ if (a.docPath !== b.docPath) {
29167
+ return a.docPath.localeCompare(b.docPath);
29168
+ }
29169
+ if (a.line !== b.line) {
29170
+ return a.line - b.line;
29171
+ }
29172
+ return a.fenceIndex - b.fenceIndex;
29173
+ });
29174
+ return records;
29175
+ }
29176
+ function walkMarkdownFiles2(root) {
29177
+ const out = [];
29178
+ const stack = [root];
29179
+ while (stack.length > 0) {
29180
+ const dir = stack.pop();
29181
+ let entries;
29182
+ try {
29183
+ entries = fs2.readdirSync(dir, { withFileTypes: true });
29184
+ } catch {
29185
+ continue;
29186
+ }
29187
+ for (const entry of entries) {
29188
+ const full = path3.join(dir, entry.name);
29189
+ if (entry.isDirectory()) {
29190
+ stack.push(full);
29191
+ } else if (entry.isFile() && full.toLowerCase().endsWith(".md")) {
29192
+ out.push(full);
29193
+ }
29194
+ }
29195
+ }
29196
+ out.sort();
29197
+ return out;
29198
+ }
29199
+ function collectFencedCode(tree, visit) {
29200
+ walk(tree);
29201
+ function walk(node) {
29202
+ if (node.type === "code") {
29203
+ visit(node);
29204
+ return;
29205
+ }
29206
+ if (node.type === "html") {
29207
+ return;
29208
+ }
29209
+ const parent = node;
29210
+ if (Array.isArray(parent.children)) {
29211
+ for (const child of parent.children) {
29212
+ walk(child);
29213
+ }
29214
+ }
29215
+ }
29216
+ }
29217
+ function normalizeLang(raw) {
29218
+ if (!raw) {
29219
+ return void 0;
29220
+ }
29221
+ const lower = raw.toLowerCase();
29222
+ switch (lower) {
29223
+ case "ts":
29224
+ return SampleLang.Ts;
29225
+ case "typescript":
29226
+ return SampleLang.Typescript;
29227
+ case "tsx":
29228
+ return SampleLang.Tsx;
29229
+ case "typescriptreact":
29230
+ return SampleLang.Typescriptreact;
29231
+ default:
29232
+ return void 0;
29233
+ }
29234
+ }
29235
+ var META_SKIP_PATTERN = /\b(skip|no-check)\b/i;
29236
+ var PRAGMA_NO_CHECK_PATTERN = /^\s*\/\/\s*@no-check\b/i;
29237
+ function detectSkip(node) {
29238
+ const meta = node.meta ?? "";
29239
+ const metaMatch = META_SKIP_PATTERN.exec(meta);
29240
+ if (metaMatch) {
29241
+ return { skipped: true, reason: `meta:${metaMatch[1].toLowerCase()}` };
29242
+ }
29243
+ const code = node.value ?? "";
29244
+ const firstLine = firstNonBlankLine(code);
29245
+ if (firstLine !== void 0 && PRAGMA_NO_CHECK_PATTERN.test(firstLine)) {
29246
+ return { skipped: true, reason: "pragma:@no-check" };
29247
+ }
29248
+ return { skipped: false, reason: "" };
29249
+ }
29250
+ function firstNonBlankLine(source) {
29251
+ for (const line of source.split("\n")) {
29252
+ if (line.trim().length > 0) {
29253
+ return line;
29254
+ }
29255
+ }
29256
+ return void 0;
29257
+ }
29258
+ function toPosix2(p) {
29259
+ return p.split(path3.sep).join("/");
29260
+ }
29261
+ function stripYamlFrontmatter2(source) {
29262
+ if (!source.startsWith("---")) {
29263
+ return source;
29264
+ }
29265
+ const lines = source.split("\n");
29266
+ if (lines[0] !== "---") {
29267
+ return source;
29268
+ }
29269
+ let endIndex = -1;
29270
+ for (let i = 1; i < lines.length; i++) {
29271
+ if (lines[i] === "---") {
29272
+ endIndex = i;
29273
+ break;
29274
+ }
29275
+ }
29276
+ if (endIndex < 0) {
29277
+ return source;
29278
+ }
29279
+ for (let i = 0; i <= endIndex; i++) {
29280
+ lines[i] = "";
29281
+ }
29282
+ return lines.join("\n");
29283
+ }
29284
+
29285
+ // src/docs-sync/sample-compilation/compilation.ts
29286
+ var DEFAULT_SAMPLE_COMPILER_OPTIONS = {
29287
+ target: ts.ScriptTarget.ES2022,
29288
+ module: ts.ModuleKind.ESNext,
29289
+ moduleResolution: ts.ModuleResolutionKind.Bundler,
29290
+ lib: ["lib.es2022.d.ts", "lib.dom.d.ts"],
29291
+ strict: true,
29292
+ noUnusedLocals: false,
29293
+ noUnusedParameters: false,
29294
+ skipLibCheck: true,
29295
+ esModuleInterop: true,
29296
+ resolveJsonModule: true,
29297
+ isolatedModules: true,
29298
+ jsx: ts.JsxEmit.Preserve,
29299
+ noEmit: true,
29300
+ allowSyntheticDefaultImports: true
29301
+ };
29302
+ var REPO_RELATIVE_MODULE_PATTERN = /^['"](?:\.\.?\/|\/)/;
29303
+ function compileFencedSamples(options = {}) {
29304
+ const samples = extractFencedSamples(options);
29305
+ const tolerateRepoRelative = options.tolerateRepoRelativeMissingModule ?? true;
29306
+ const failures = [];
29307
+ for (const sample of samples) {
29308
+ if (sample.skipped) {
29309
+ continue;
29310
+ }
29311
+ const diagnostics = compileSingleSample(
29312
+ sample,
29313
+ options.compilerOptions,
29314
+ tolerateRepoRelative
29315
+ );
29316
+ if (diagnostics.length > 0) {
29317
+ failures.push({
29318
+ docPath: sample.docPath,
29319
+ line: sample.line,
29320
+ fenceIndex: sample.fenceIndex,
29321
+ lang: sample.lang,
29322
+ diagnostics
29323
+ });
29324
+ }
29325
+ }
29326
+ return failures;
29327
+ }
29328
+ function compileSingleSample(sample, overrides, tolerateRepoRelative) {
29329
+ const filename = sampleFilename(sample);
29330
+ const compilerOptions = mergeCompilerOptions(overrides);
29331
+ const host = createSingleFileHost(filename, sample.code, compilerOptions);
29332
+ const program = ts.createProgram({
29333
+ rootNames: [filename],
29334
+ options: compilerOptions,
29335
+ host
29336
+ });
29337
+ const sourceFile = program.getSourceFile(filename);
29338
+ const collected = [];
29339
+ if (sourceFile) {
29340
+ collected.push(...program.getSyntacticDiagnostics(sourceFile));
29341
+ collected.push(...program.getSemanticDiagnostics(sourceFile));
29342
+ } else {
29343
+ collected.push(...program.getSyntacticDiagnostics());
29344
+ collected.push(...program.getSemanticDiagnostics());
29345
+ }
29346
+ const diagnostics = [];
29347
+ for (const d of collected) {
29348
+ if (tolerateRepoRelative && isRepoRelativeMissingModule(d, sample.code)) {
29349
+ continue;
29350
+ }
29351
+ diagnostics.push(formatDiagnostic(d));
29352
+ }
29353
+ return diagnostics;
29354
+ }
29355
+ function sampleFilename(sample) {
29356
+ const safeDoc = sample.docPath.replace(/[^a-zA-Z0-9]+/g, "_");
29357
+ const ext = sample.lang === SampleLang.Tsx || sample.lang === SampleLang.Typescriptreact ? "tsx" : "ts";
29358
+ return path4.posix.join("/", `${safeDoc}__${sample.fenceIndex}.${ext}`);
29359
+ }
29360
+ function mergeCompilerOptions(overrides) {
29361
+ if (!overrides) {
29362
+ return { ...DEFAULT_SAMPLE_COMPILER_OPTIONS };
29363
+ }
29364
+ const merged = { ...DEFAULT_SAMPLE_COMPILER_OPTIONS };
29365
+ for (const key of Object.keys(overrides)) {
29366
+ const value = overrides[key];
29367
+ if (value === void 0) {
29368
+ delete merged[key];
29369
+ } else {
29370
+ merged[key] = value;
29371
+ }
29372
+ }
29373
+ return merged;
29374
+ }
29375
+ function createSingleFileHost(filename, source, compilerOptions) {
29376
+ const baseHost = ts.createCompilerHost(compilerOptions, true);
29377
+ return {
29378
+ ...baseHost,
29379
+ getSourceFile(name, languageVersionOrOptions, onError, shouldCreate) {
29380
+ if (name === filename) {
29381
+ return ts.createSourceFile(
29382
+ name,
29383
+ source,
29384
+ languageVersionOrOptions,
29385
+ true
29386
+ );
29387
+ }
29388
+ return baseHost.getSourceFile(
29389
+ name,
29390
+ languageVersionOrOptions,
29391
+ onError,
29392
+ shouldCreate
29393
+ );
29394
+ },
29395
+ fileExists(name) {
29396
+ if (name === filename) {
29397
+ return true;
29398
+ }
29399
+ return baseHost.fileExists(name);
29400
+ },
29401
+ readFile(name) {
29402
+ if (name === filename) {
29403
+ return source;
29404
+ }
29405
+ return baseHost.readFile(name);
29406
+ },
29407
+ writeFile() {
29408
+ },
29409
+ getCanonicalFileName(name) {
29410
+ return baseHost.getCanonicalFileName(name);
29411
+ },
29412
+ useCaseSensitiveFileNames() {
29413
+ return baseHost.useCaseSensitiveFileNames();
29414
+ },
29415
+ getNewLine() {
29416
+ return baseHost.getNewLine();
29417
+ },
29418
+ getDefaultLibFileName(o) {
29419
+ return baseHost.getDefaultLibFileName(o);
29420
+ },
29421
+ getCurrentDirectory() {
29422
+ return baseHost.getCurrentDirectory();
29423
+ }
29424
+ };
29425
+ }
29426
+ function isRepoRelativeMissingModule(d, code) {
29427
+ if (d.code !== 2307) {
29428
+ return false;
29429
+ }
29430
+ const text = ts.flattenDiagnosticMessageText(d.messageText, "\n");
29431
+ const match = /'([^']+)'/.exec(text);
29432
+ if (!match) {
29433
+ return false;
29434
+ }
29435
+ const specifier = match[1];
29436
+ if (!specifier) {
29437
+ return false;
29438
+ }
29439
+ const inSourceSingle = `'${specifier}'`;
29440
+ const inSourceDouble = `"${specifier}"`;
29441
+ if (!code.includes(inSourceSingle) && !code.includes(inSourceDouble)) {
29442
+ return false;
29443
+ }
29444
+ return REPO_RELATIVE_MODULE_PATTERN.test(`'${specifier}'`);
29445
+ }
29446
+ function formatDiagnostic(d) {
29447
+ const text = ts.flattenDiagnosticMessageText(d.messageText, " ");
29448
+ const code = d.code === void 0 ? "" : `TS${d.code}: `;
29449
+ return `${code}${text}`.trim();
29450
+ }
29451
+
29452
+ // src/docs-sync/scan/audit-report.ts
29453
+ var AuditCategory = {
29454
+ /**
29455
+ * Findings produced by the public-API diff check that surfaces
29456
+ * added, renamed, or removed exports between the current branch
29457
+ * and the recorded baseline. Wired in by child issue #519.
29458
+ */
29459
+ ApiDiff: "apiDiff",
29460
+ /**
29461
+ * Findings produced by the TSDoc-coverage check that flags public
29462
+ * exports without a one-sentence summary. Wired in by child issue
29463
+ * #519.
29464
+ */
29465
+ TsdocCoverage: "tsdocCoverage",
29466
+ /**
29467
+ * Findings produced by the doc-reference cross-index check that
29468
+ * flags inline-code symbol mentions whose target is missing or
29469
+ * has changed. Wired in by child issue #519.
29470
+ */
29471
+ ReferenceMismatches: "referenceMismatches",
29472
+ /**
29473
+ * Findings produced by the link-integrity check (internal via
29474
+ * `astro check`, external via `lychee`). Wired in by child issue
29475
+ * #520.
29476
+ */
29477
+ LinkFailures: "linkFailures",
29478
+ /**
29479
+ * Findings produced by the fenced-sample compilation check that
29480
+ * flags ` ```ts ` / ` ```typescript ` / ` ```tsx ` blocks in the
29481
+ * docs that fail `tsc`. Wired in by child issue #520.
29482
+ */
29483
+ SampleFailures: "sampleFailures"
29484
+ };
29485
+ var AuditSeverity = {
29486
+ /**
29487
+ * The finding has a deterministic mechanical fix that the Phase 2
29488
+ * (Fix) agent will auto-apply (TSDoc stubs, dead-link updates,
29489
+ * registry sync, etc.).
29490
+ */
29491
+ Mechanical: "mechanical",
29492
+ /**
29493
+ * The finding deserves human attention but does not block the PR.
29494
+ * Surfaced as a non-blocking note on the sticky `## Docs sync`
29495
+ * comment.
29496
+ */
29497
+ Advisory: "advisory",
29498
+ /**
29499
+ * The finding blocks the PR. Per the parent epic this is reserved
29500
+ * for the two narrow cases of confirmed broken external links and
29501
+ * fenced TS samples that fail to compile.
29502
+ */
29503
+ Blocking: "blocking"
29504
+ };
29505
+ var AuditMode = {
29506
+ Pr: "pr",
29507
+ Audit: "audit"
29508
+ };
29509
+ var DOCS_SYNC_AUDIT_SCHEMA_VERSION = 1;
29510
+ function auditReportJsonSchema() {
29511
+ const locationSchema = {
29512
+ type: "object",
29513
+ additionalProperties: false,
29514
+ required: ["file", "line"],
29515
+ properties: {
29516
+ file: { type: "string" },
29517
+ line: { type: "integer", minimum: 0 }
29518
+ }
29519
+ };
29520
+ const findingBaseProperties = {
29521
+ severity: { type: "string", enum: ["mechanical", "advisory", "blocking"] },
29522
+ location: locationSchema,
29523
+ subject: { type: "string" },
29524
+ details: { type: "string" },
29525
+ fixHint: { type: "string" }
29526
+ };
29527
+ const apiDiffFindingSchema = {
29528
+ type: "object",
29529
+ required: [
29530
+ "category",
29531
+ "severity",
29532
+ "location",
29533
+ "subject",
29534
+ "details",
29535
+ "change",
29536
+ "symbol"
29537
+ ],
29538
+ properties: {
29539
+ ...findingBaseProperties,
29540
+ category: { type: "string", const: "apiDiff" },
29541
+ change: { type: "string", enum: ["added", "removed", "changed"] },
29542
+ symbol: { type: "string" }
29543
+ }
29544
+ };
29545
+ const tsdocCoverageFindingSchema = {
29546
+ type: "object",
29547
+ required: [
29548
+ "category",
29549
+ "severity",
29550
+ "location",
29551
+ "subject",
29552
+ "details",
29553
+ "shortfall",
29554
+ "symbol"
29555
+ ],
29556
+ properties: {
29557
+ ...findingBaseProperties,
29558
+ category: { type: "string", const: "tsdocCoverage" },
29559
+ shortfall: {
29560
+ type: "string",
29561
+ enum: [
29562
+ "missing-summary",
29563
+ "thin-summary",
29564
+ "missing-params",
29565
+ "missing-returns"
29566
+ ]
29567
+ },
29568
+ symbol: { type: "string" }
29569
+ }
29570
+ };
29571
+ const referenceMismatchFindingSchema = {
29572
+ type: "object",
29573
+ required: [
29574
+ "category",
29575
+ "severity",
29576
+ "location",
29577
+ "subject",
29578
+ "details",
29579
+ "mismatch",
29580
+ "symbol"
29581
+ ],
29582
+ properties: {
29583
+ ...findingBaseProperties,
29584
+ category: { type: "string", const: "referenceMismatches" },
29585
+ mismatch: {
29586
+ type: "string",
29587
+ enum: ["unknown-symbol", "signature-changed"]
29588
+ },
29589
+ symbol: { type: "string" }
29590
+ }
29591
+ };
29592
+ const linkFailureFindingSchema = {
29593
+ type: "object",
29594
+ required: [
29595
+ "category",
29596
+ "severity",
29597
+ "location",
29598
+ "subject",
29599
+ "details",
29600
+ "url",
29601
+ "kind",
29602
+ "reason"
29603
+ ],
29604
+ properties: {
29605
+ ...findingBaseProperties,
29606
+ category: { type: "string", const: "linkFailures" },
29607
+ url: { type: "string" },
29608
+ kind: { type: "string", enum: ["internal", "external"] },
29609
+ reason: { type: "string" }
29610
+ }
29611
+ };
29612
+ const sampleFailureFindingSchema = {
29613
+ type: "object",
29614
+ required: [
29615
+ "category",
29616
+ "severity",
29617
+ "location",
29618
+ "subject",
29619
+ "details",
29620
+ "fenceIndex",
29621
+ "lang",
29622
+ "diagnostics"
29623
+ ],
29624
+ properties: {
29625
+ ...findingBaseProperties,
29626
+ category: { type: "string", const: "sampleFailures" },
29627
+ fenceIndex: { type: "integer", minimum: 0 },
29628
+ lang: { type: "string" },
29629
+ diagnostics: { type: "array", items: { type: "string" } }
29630
+ }
29631
+ };
29632
+ return {
29633
+ $schema: "http://json-schema.org/draft-07/schema#",
29634
+ title: "DocsSyncAuditReport",
29635
+ type: "object",
29636
+ additionalProperties: false,
29637
+ required: [
29638
+ "schemaVersion",
29639
+ "issueNumber",
29640
+ "mode",
29641
+ "generatedAt",
29642
+ "repoRoot",
29643
+ "scope",
29644
+ "categories",
29645
+ "findings"
29646
+ ],
29647
+ properties: {
29648
+ schemaVersion: { type: "integer", const: DOCS_SYNC_AUDIT_SCHEMA_VERSION },
29649
+ issueNumber: { type: "integer", minimum: 0 },
29650
+ mode: { type: "string", enum: ["pr", "audit"] },
29651
+ generatedAt: { type: "string", format: "date-time" },
29652
+ repoRoot: { type: "string" },
29653
+ scope: { type: "string" },
29654
+ categories: {
29655
+ type: "object",
29656
+ additionalProperties: false,
29657
+ required: [
29658
+ "apiDiff",
29659
+ "tsdocCoverage",
29660
+ "referenceMismatches",
29661
+ "linkFailures",
29662
+ "sampleFailures"
29663
+ ],
29664
+ properties: {
29665
+ apiDiff: { type: "array", items: apiDiffFindingSchema },
29666
+ tsdocCoverage: { type: "array", items: tsdocCoverageFindingSchema },
29667
+ referenceMismatches: {
29668
+ type: "array",
29669
+ items: referenceMismatchFindingSchema
29670
+ },
29671
+ linkFailures: { type: "array", items: linkFailureFindingSchema },
29672
+ sampleFailures: { type: "array", items: sampleFailureFindingSchema }
29673
+ }
29674
+ },
29675
+ findings: {
29676
+ type: "array",
29677
+ items: {
29678
+ oneOf: [
29679
+ apiDiffFindingSchema,
29680
+ tsdocCoverageFindingSchema,
29681
+ referenceMismatchFindingSchema,
29682
+ linkFailureFindingSchema,
29683
+ sampleFailureFindingSchema
29684
+ ]
29685
+ }
29686
+ }
29687
+ }
29688
+ };
29689
+ }
29690
+
29691
+ // src/docs-sync/scan/run-scan.ts
29692
+ import * as fs3 from "fs";
29693
+ import * as path5 from "path";
29694
+ var DEFAULT_AUDIT_REPORT_DIR = ".claude/state/docs-sync";
29695
+ var SEVERITY_RANK = {
29696
+ blocking: 0,
29697
+ advisory: 1,
29698
+ mechanical: 2
29699
+ };
29700
+ var AUDIT_CATEGORY_ORDER = [
29701
+ AuditCategory.ApiDiff,
29702
+ AuditCategory.TsdocCoverage,
29703
+ AuditCategory.ReferenceMismatches,
29704
+ AuditCategory.LinkFailures,
29705
+ AuditCategory.SampleFailures
29706
+ ];
29707
+ function runScan(options) {
29708
+ const repoRoot = path5.resolve(options.repoRoot);
29709
+ const mode = options.mode;
29710
+ const scope = options.scope ?? "";
29711
+ const issueNumber = options.issueNumber;
29712
+ const checks = options.checks ?? [];
29713
+ const now = options.now ?? /* @__PURE__ */ new Date();
29714
+ const persist = options.persist ?? false;
29715
+ const reportDir = options.reportDir ?? DEFAULT_AUDIT_REPORT_DIR;
29716
+ const context = {
29717
+ repoRoot,
29718
+ mode,
29719
+ scope,
29720
+ issueNumber
29721
+ };
29722
+ const collected = [];
29723
+ for (const check of checks) {
29724
+ const result = check.run(context);
29725
+ for (const finding of result) {
29726
+ collected.push(finding);
29727
+ }
29728
+ }
29729
+ const report = buildReport({
29730
+ issueNumber,
29731
+ mode,
29732
+ scope,
29733
+ repoRoot,
29734
+ generatedAt: now,
29735
+ findings: collected
29736
+ });
29737
+ let reportPath = "";
29738
+ if (persist) {
29739
+ reportPath = persistAuditReport({
29740
+ report,
29741
+ repoRoot,
29742
+ reportDir
29743
+ });
29744
+ }
29745
+ return { report, reportPath };
29746
+ }
29747
+ function buildReport(args) {
29748
+ const buckets = emptyCategoryBuckets();
29749
+ for (const finding of args.findings) {
29750
+ pushIntoBucket(buckets, finding);
29751
+ }
29752
+ buckets.apiDiff.sort(compareFindings);
29753
+ buckets.tsdocCoverage.sort(compareFindings);
29754
+ buckets.referenceMismatches.sort(compareFindings);
29755
+ buckets.linkFailures.sort(compareFindings);
29756
+ buckets.sampleFailures.sort(compareFindings);
29757
+ const flat = [];
29758
+ for (const key of AUDIT_CATEGORY_ORDER) {
29759
+ const bucket = buckets[key];
29760
+ for (const finding of bucket) {
29761
+ flat.push(finding);
29762
+ }
29763
+ }
29764
+ flat.sort(compareFindings);
29765
+ return {
29766
+ schemaVersion: DOCS_SYNC_AUDIT_SCHEMA_VERSION,
29767
+ issueNumber: args.issueNumber,
29768
+ mode: args.mode,
29769
+ generatedAt: args.generatedAt.toISOString(),
29770
+ repoRoot: args.repoRoot,
29771
+ scope: args.scope,
29772
+ categories: {
29773
+ apiDiff: buckets.apiDiff,
29774
+ tsdocCoverage: buckets.tsdocCoverage,
29775
+ referenceMismatches: buckets.referenceMismatches,
29776
+ linkFailures: buckets.linkFailures,
29777
+ sampleFailures: buckets.sampleFailures
29778
+ },
29779
+ findings: flat
29780
+ };
29781
+ }
29782
+ function persistAuditReport(args) {
29783
+ const repoRoot = path5.resolve(args.repoRoot);
29784
+ const reportDir = args.reportDir ?? DEFAULT_AUDIT_REPORT_DIR;
29785
+ const targetDir = path5.resolve(repoRoot, reportDir);
29786
+ fs3.mkdirSync(targetDir, { recursive: true });
29787
+ const targetFile = path5.join(
29788
+ targetDir,
29789
+ `${args.report.issueNumber}-audit.json`
29790
+ );
29791
+ const tempFile = `${targetFile}.tmp-${process.pid}-${Date.now()}`;
29792
+ const serialized = `${JSON.stringify(args.report, null, 2)}
29793
+ `;
29794
+ fs3.writeFileSync(tempFile, serialized, "utf-8");
29795
+ fs3.renameSync(tempFile, targetFile);
29796
+ return targetFile;
29797
+ }
29798
+ function emptyCategoryBuckets() {
29799
+ return {
29800
+ apiDiff: [],
29801
+ tsdocCoverage: [],
29802
+ referenceMismatches: [],
29803
+ linkFailures: [],
29804
+ sampleFailures: []
29805
+ };
29806
+ }
29807
+ function pushIntoBucket(buckets, finding) {
29808
+ switch (finding.category) {
29809
+ case AuditCategory.ApiDiff:
29810
+ buckets.apiDiff.push(finding);
29811
+ return;
29812
+ case AuditCategory.TsdocCoverage:
29813
+ buckets.tsdocCoverage.push(finding);
29814
+ return;
29815
+ case AuditCategory.ReferenceMismatches:
29816
+ buckets.referenceMismatches.push(finding);
29817
+ return;
29818
+ case AuditCategory.LinkFailures:
29819
+ buckets.linkFailures.push(finding);
29820
+ return;
29821
+ case AuditCategory.SampleFailures:
29822
+ buckets.sampleFailures.push(finding);
29823
+ return;
29824
+ default: {
29825
+ const exhaustive = finding;
29826
+ throw new Error(
29827
+ `runScan: unrecognized finding category: ${JSON.stringify(exhaustive)}`
29828
+ );
29829
+ }
29830
+ }
29831
+ }
29832
+ function compareFindings(a, b) {
29833
+ const sevDelta = SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity];
29834
+ if (sevDelta !== 0) {
29835
+ return sevDelta;
29836
+ }
29837
+ if (a.category !== b.category) {
29838
+ return a.category.localeCompare(b.category);
29839
+ }
29840
+ if (a.location.file !== b.location.file) {
29841
+ return a.location.file.localeCompare(b.location.file);
29842
+ }
29843
+ if (a.location.line !== b.location.line) {
29844
+ return a.location.line - b.location.line;
29845
+ }
29846
+ return a.subject.localeCompare(b.subject);
29847
+ }
29848
+
29849
+ // src/docs-sync/tsdoc-coverage/coverage.ts
29850
+ import * as path6 from "path";
28926
29851
  import { TSDocParser } from "@microsoft/tsdoc";
28927
- import * as ts from "typescript";
29852
+ import * as ts2 from "typescript";
28928
29853
  var TsDocCoverageKind = {
28929
29854
  Class: "Class",
28930
29855
  Interface: "Interface",
@@ -28940,8 +29865,8 @@ var DEFAULT_THIN_SUMMARY_WORD_THRESHOLD = 4;
28940
29865
  var DEFAULT_ENTRY_POINT = "src/index.ts";
28941
29866
  function analyzeTsDocCoverage(options) {
28942
29867
  const resolvedOptions = typeof options === "string" ? { packageRoot: options } : options;
28943
- const packageRoot = path3.resolve(resolvedOptions.packageRoot);
28944
- const entryPoint = path3.resolve(
29868
+ const packageRoot = path6.resolve(resolvedOptions.packageRoot);
29869
+ const entryPoint = path6.resolve(
28945
29870
  packageRoot,
28946
29871
  resolvedOptions.entryPoint ?? DEFAULT_ENTRY_POINT
28947
29872
  );
@@ -28950,7 +29875,7 @@ function analyzeTsDocCoverage(options) {
28950
29875
  packageRoot,
28951
29876
  resolvedOptions.tsconfigPath
28952
29877
  );
28953
- const program = ts.createProgram({
29878
+ const program = ts2.createProgram({
28954
29879
  rootNames: [entryPoint],
28955
29880
  options: compilerOptions
28956
29881
  });
@@ -29004,24 +29929,24 @@ function analyzeTsDocCoverage(options) {
29004
29929
  }
29005
29930
  function resolveCompilerOptions(packageRoot, tsconfigPath) {
29006
29931
  if (tsconfigPath) {
29007
- const absoluteTsconfig = path3.resolve(packageRoot, tsconfigPath);
29008
- const configFile = ts.readConfigFile(absoluteTsconfig, ts.sys.readFile);
29932
+ const absoluteTsconfig = path6.resolve(packageRoot, tsconfigPath);
29933
+ const configFile = ts2.readConfigFile(absoluteTsconfig, ts2.sys.readFile);
29009
29934
  if (configFile.error) {
29010
29935
  throw new Error(
29011
- `analyzeTsDocCoverage: failed to read tsconfig at ${absoluteTsconfig}: ${ts.flattenDiagnosticMessageText(configFile.error.messageText, "\n")}`
29936
+ `analyzeTsDocCoverage: failed to read tsconfig at ${absoluteTsconfig}: ${ts2.flattenDiagnosticMessageText(configFile.error.messageText, "\n")}`
29012
29937
  );
29013
29938
  }
29014
- const parsed = ts.parseJsonConfigFileContent(
29939
+ const parsed = ts2.parseJsonConfigFileContent(
29015
29940
  configFile.config,
29016
- ts.sys,
29017
- path3.dirname(absoluteTsconfig)
29941
+ ts2.sys,
29942
+ path6.dirname(absoluteTsconfig)
29018
29943
  );
29019
29944
  return { ...parsed.options, noEmit: true };
29020
29945
  }
29021
29946
  return {
29022
- target: ts.ScriptTarget.ESNext,
29023
- module: ts.ModuleKind.NodeNext,
29024
- moduleResolution: ts.ModuleResolutionKind.NodeNext,
29947
+ target: ts2.ScriptTarget.ESNext,
29948
+ module: ts2.ModuleKind.NodeNext,
29949
+ moduleResolution: ts2.ModuleResolutionKind.NodeNext,
29025
29950
  allowJs: false,
29026
29951
  declaration: false,
29027
29952
  noEmit: true,
@@ -29046,7 +29971,7 @@ function resolveAlias(symbol, checker) {
29046
29971
  return current;
29047
29972
  }
29048
29973
  function isAlias(symbol) {
29049
- return (symbol.flags & ts.SymbolFlags.Alias) !== 0;
29974
+ return (symbol.flags & ts2.SymbolFlags.Alias) !== 0;
29050
29975
  }
29051
29976
  function pickPrimaryDeclaration(symbol) {
29052
29977
  const declarations = symbol.getDeclarations();
@@ -29054,53 +29979,53 @@ function pickPrimaryDeclaration(symbol) {
29054
29979
  return void 0;
29055
29980
  }
29056
29981
  const concrete = declarations.find(
29057
- (d) => !ts.isExportSpecifier(d) && !ts.isExportAssignment(d) && !ts.isExportDeclaration(d)
29982
+ (d) => !ts2.isExportSpecifier(d) && !ts2.isExportAssignment(d) && !ts2.isExportDeclaration(d)
29058
29983
  );
29059
29984
  return concrete ?? declarations[0];
29060
29985
  }
29061
29986
  function classifyDeclaration(declaration) {
29062
- if (ts.isClassDeclaration(declaration)) {
29987
+ if (ts2.isClassDeclaration(declaration)) {
29063
29988
  return TsDocCoverageKind.Class;
29064
29989
  }
29065
- if (ts.isInterfaceDeclaration(declaration)) {
29990
+ if (ts2.isInterfaceDeclaration(declaration)) {
29066
29991
  return TsDocCoverageKind.Interface;
29067
29992
  }
29068
- if (ts.isTypeAliasDeclaration(declaration)) {
29993
+ if (ts2.isTypeAliasDeclaration(declaration)) {
29069
29994
  return TsDocCoverageKind.TypeAlias;
29070
29995
  }
29071
- if (ts.isEnumDeclaration(declaration)) {
29996
+ if (ts2.isEnumDeclaration(declaration)) {
29072
29997
  return TsDocCoverageKind.Enum;
29073
29998
  }
29074
- if (ts.isFunctionDeclaration(declaration) || ts.isMethodDeclaration(declaration)) {
29999
+ if (ts2.isFunctionDeclaration(declaration) || ts2.isMethodDeclaration(declaration)) {
29075
30000
  return TsDocCoverageKind.Function;
29076
30001
  }
29077
- if (ts.isVariableDeclaration(declaration) || ts.isVariableStatement(declaration)) {
30002
+ if (ts2.isVariableDeclaration(declaration) || ts2.isVariableStatement(declaration)) {
29078
30003
  return TsDocCoverageKind.Variable;
29079
30004
  }
29080
- if (ts.isModuleDeclaration(declaration)) {
30005
+ if (ts2.isModuleDeclaration(declaration)) {
29081
30006
  return TsDocCoverageKind.Module;
29082
30007
  }
29083
- if (ts.isExportAssignment(declaration)) {
30008
+ if (ts2.isExportAssignment(declaration)) {
29084
30009
  return TsDocCoverageKind.Default;
29085
30010
  }
29086
30011
  return TsDocCoverageKind.Other;
29087
30012
  }
29088
30013
  function resolveLocation(declaration) {
29089
- const target = ts.isVariableDeclaration(declaration) ? declaration.parent.parent ?? declaration : declaration;
30014
+ const target = ts2.isVariableDeclaration(declaration) ? declaration.parent.parent ?? declaration : declaration;
29090
30015
  const source = target.getSourceFile();
29091
30016
  const { line } = source.getLineAndCharacterOfPosition(target.getStart());
29092
30017
  return { file: source.fileName, line: line + 1 };
29093
30018
  }
29094
30019
  function parseTsDocFor(declaration, parser) {
29095
- const target = ts.isVariableDeclaration(declaration) ? declaration.parent.parent ?? declaration : declaration;
30020
+ const target = ts2.isVariableDeclaration(declaration) ? declaration.parent.parent ?? declaration : declaration;
29096
30021
  const sourceText = target.getSourceFile().getFullText();
29097
- const ranges = ts.getLeadingCommentRanges(sourceText, target.getFullStart());
30022
+ const ranges = ts2.getLeadingCommentRanges(sourceText, target.getFullStart());
29098
30023
  if (!ranges || ranges.length === 0) {
29099
30024
  return void 0;
29100
30025
  }
29101
30026
  for (let i = ranges.length - 1; i >= 0; i--) {
29102
30027
  const range = ranges[i];
29103
- if (range.kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
30028
+ if (range.kind !== ts2.SyntaxKind.MultiLineCommentTrivia) {
29104
30029
  continue;
29105
30030
  }
29106
30031
  const text = sourceText.slice(range.pos, range.end);
@@ -29323,14 +30248,14 @@ var LAYOUT_ROOT_BY_PROJECT_TYPE = {
29323
30248
  };
29324
30249
  function validateMonorepoLayout(root) {
29325
30250
  const violations = [];
29326
- const rootOutdir = toPosix2(root.outdir);
30251
+ const rootOutdir = toPosix3(root.outdir);
29327
30252
  for (const sub of root.subprojects) {
29328
30253
  const className = sub.constructor.name;
29329
30254
  const expectedRoot = expectedRootFor(sub, className);
29330
30255
  if (expectedRoot === void 0) {
29331
30256
  continue;
29332
30257
  }
29333
- const relOutdir = relativeOutdir(rootOutdir, toPosix2(sub.outdir));
30258
+ const relOutdir = relativeOutdir(rootOutdir, toPosix3(sub.outdir));
29334
30259
  if (!outdirMatchesRoot(relOutdir, expectedRoot)) {
29335
30260
  violations.push({
29336
30261
  projectName: sub.name,
@@ -29389,7 +30314,7 @@ function outdirMatchesRoot(relOutdir, expectedRoot) {
29389
30314
  }
29390
30315
  return segments.length >= 2;
29391
30316
  }
29392
- function toPosix2(p) {
30317
+ function toPosix3(p) {
29393
30318
  return p.replace(/\\/g, "/");
29394
30319
  }
29395
30320
  function relativeOutdir(rootOutdir, subOutdir) {
@@ -29478,8 +30403,8 @@ var ResetTask = class _ResetTask extends Component14 {
29478
30403
  const resetTask = this.project.tasks.addTask(this.taskName, {
29479
30404
  description: "Delete build artifacts specified by pathsToRemove option, or artifactsDirectory if pathsToRemove is empty"
29480
30405
  });
29481
- this.pathsToRemove.forEach((path4) => {
29482
- resetTask.exec(`[ -e "${path4}" ] && rm -rf ${path4} || true`);
30406
+ this.pathsToRemove.forEach((path7) => {
30407
+ resetTask.exec(`[ -e "${path7}" ] && rm -rf ${path7} || true`);
29483
30408
  });
29484
30409
  const rootHasTurbo = TurboRepo.of(this.project.root) !== void 0;
29485
30410
  const isSubproject = this.project !== this.project.root;
@@ -31387,7 +32312,7 @@ export const collections = {
31387
32312
  `;
31388
32313
 
31389
32314
  // src/typescript/typescript-config.ts
31390
- import { relative as relative5 } from "path";
32315
+ import { relative as relative6 } from "path";
31391
32316
  import { Component as Component19 } from "projen";
31392
32317
  import { ensureRelativePathStartsWithDot } from "projen/lib/util/path";
31393
32318
  var TypeScriptConfig = class extends Component19 {
@@ -31406,7 +32331,7 @@ var TypeScriptConfig = class extends Component19 {
31406
32331
  ...tsPaths,
31407
32332
  [dep.name]: [
31408
32333
  ensureRelativePathStartsWithDot(
31409
- relative5(project.outdir, subproject.outdir)
32334
+ relative6(project.outdir, subproject.outdir)
31410
32335
  )
31411
32336
  ]
31412
32337
  };
@@ -31421,11 +32346,15 @@ export {
31421
32346
  AGENT_RULE_SCOPE,
31422
32347
  AGENT_TIER_ROLES,
31423
32348
  AGENT_TIER_VALUES,
32349
+ AUDIT_CATEGORY_ORDER,
31424
32350
  AgentConfig,
31425
32351
  ApiExtractor,
31426
32352
  AstroConfig,
31427
32353
  AstroOutput,
31428
32354
  AstroProject,
32355
+ AuditCategory,
32356
+ AuditMode,
32357
+ AuditSeverity,
31429
32358
  AwsCdkProject,
31430
32359
  AwsDeployWorkflow,
31431
32360
  AwsDeploymentConfig,
@@ -31441,6 +32370,7 @@ export {
31441
32370
  DEFAULT_API_EXTRACTOR_ENTRY_POINT,
31442
32371
  DEFAULT_API_EXTRACTOR_REPORT_FILENAME,
31443
32372
  DEFAULT_API_EXTRACTOR_REPORT_FOLDER,
32373
+ DEFAULT_AUDIT_REPORT_DIR,
31444
32374
  DEFAULT_DECOMPOSITION_TEMPLATE,
31445
32375
  DEFAULT_DELEGATE_TO_PR_REVIEWER,
31446
32376
  DEFAULT_DISPATCH_MODEL,
@@ -31464,6 +32394,7 @@ export {
31464
32394
  DEFAULT_PROGRESS_FILES_STATE_DIR,
31465
32395
  DEFAULT_REQUIRE_LINKED_ISSUE,
31466
32396
  DEFAULT_REQUIRE_PRODUCT_CONTEXT,
32397
+ DEFAULT_SAMPLE_COMPILER_OPTIONS,
31467
32398
  DEFAULT_SCHEDULED_TASKS_ROOT,
31468
32399
  DEFAULT_SCHEDULED_TASK_ENTRIES,
31469
32400
  DEFAULT_SHARED_EDITING_CONFLICT_STRATEGY,
@@ -31487,6 +32418,7 @@ export {
31487
32418
  DEFAULT_WORKFLOW_DIAGRAMS_ENABLED,
31488
32419
  DEFAULT_WORKFLOW_DIAGRAMS_PATH,
31489
32420
  DEFAULT_WORKFLOW_DIAGRAMS_REQUIRE_UPDATE,
32421
+ DOCS_SYNC_AUDIT_SCHEMA_VERSION,
31490
32422
  JsiiFaker,
31491
32423
  LAYOUT_ENFORCEMENT,
31492
32424
  LAYOUT_ROOT_BY_PROJECT_TYPE,
@@ -31509,6 +32441,7 @@ export {
31509
32441
  SCOPE_CLASS_VALUES,
31510
32442
  SHARED_EDITING_CONFLICT_STRATEGY_VALUES,
31511
32443
  STARLIGHT_ROLE,
32444
+ SampleLang,
31512
32445
  StarlightProject,
31513
32446
  TestRunner,
31514
32447
  TsDocCoverageKind,
@@ -31527,6 +32460,7 @@ export {
31527
32460
  addSyncLabelsWorkflow,
31528
32461
  agendaBundle,
31529
32462
  analyzeTsDocCoverage,
32463
+ auditReportJsonSchema,
31530
32464
  awsCdkBundle,
31531
32465
  baseBundle,
31532
32466
  bcmWriterBundle,
@@ -31543,6 +32477,7 @@ export {
31543
32477
  buildOrchestratorConventionsContent,
31544
32478
  buildPeopleProfileBundle,
31545
32479
  buildRegulatoryResearchBundle,
32480
+ buildReport,
31546
32481
  buildRequirementsAnalystBundle,
31547
32482
  buildRequirementsReviewerBundle,
31548
32483
  buildRequirementsWriterBundle,
@@ -31551,14 +32486,18 @@ export {
31551
32486
  buildStandardsResearchBundle,
31552
32487
  buildUnblockDependentsProcedure,
31553
32488
  businessModelsBundle,
32489
+ checkDocSamplesProcedure,
31554
32490
  checkLinksProcedure,
31555
32491
  classifyIssueScope,
31556
32492
  classifyRun,
31557
32493
  companyProfileBundle,
32494
+ compileFencedSamples,
31558
32495
  customerProfileBundle,
31559
32496
  docsSyncBundle,
32497
+ emptyCategoryBuckets,
31560
32498
  extractApiProcedure,
31561
32499
  extractDocReferences,
32500
+ extractFencedSamples,
31562
32501
  formatLayoutViolation,
31563
32502
  formatStarlightSingletonViolation,
31564
32503
  getLatestEligibleVersion,
@@ -31569,12 +32508,14 @@ export {
31569
32508
  meetingAnalysisBundle,
31570
32509
  orchestratorBundle,
31571
32510
  peopleProfileBundle,
32511
+ persistAuditReport,
31572
32512
  pnpmBundle,
31573
32513
  prReviewBundle,
31574
32514
  projenBundle,
31575
32515
  regulatoryResearchBundle,
31576
32516
  renderAgentTierCaseStatement,
31577
32517
  renderAgentTierSection,
32518
+ renderCheckDocSamplesProcedure,
31578
32519
  renderCheckLinksProcedure,
31579
32520
  renderCustomDocSectionBlock,
31580
32521
  renderCustomDocSections,
@@ -31634,6 +32575,7 @@ export {
31634
32575
  resolveTypeScriptProjectOutdir,
31635
32576
  resolveUnblockDependents,
31636
32577
  resolveWorkflowDiagrams,
32578
+ runScan,
31637
32579
  slackBundle,
31638
32580
  softwareProfileBundle,
31639
32581
  standardsResearchBundle,