@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.js CHANGED
@@ -180,11 +180,15 @@ __export(index_exports, {
180
180
  AGENT_RULE_SCOPE: () => AGENT_RULE_SCOPE,
181
181
  AGENT_TIER_ROLES: () => AGENT_TIER_ROLES,
182
182
  AGENT_TIER_VALUES: () => AGENT_TIER_VALUES,
183
+ AUDIT_CATEGORY_ORDER: () => AUDIT_CATEGORY_ORDER,
183
184
  AgentConfig: () => AgentConfig,
184
185
  ApiExtractor: () => ApiExtractor,
185
186
  AstroConfig: () => AstroConfig,
186
187
  AstroOutput: () => AstroOutput,
187
188
  AstroProject: () => AstroProject,
189
+ AuditCategory: () => AuditCategory,
190
+ AuditMode: () => AuditMode,
191
+ AuditSeverity: () => AuditSeverity,
188
192
  AwsCdkProject: () => AwsCdkProject,
189
193
  AwsDeployWorkflow: () => AwsDeployWorkflow,
190
194
  AwsDeploymentConfig: () => AwsDeploymentConfig,
@@ -200,6 +204,7 @@ __export(index_exports, {
200
204
  DEFAULT_API_EXTRACTOR_ENTRY_POINT: () => DEFAULT_API_EXTRACTOR_ENTRY_POINT,
201
205
  DEFAULT_API_EXTRACTOR_REPORT_FILENAME: () => DEFAULT_API_EXTRACTOR_REPORT_FILENAME,
202
206
  DEFAULT_API_EXTRACTOR_REPORT_FOLDER: () => DEFAULT_API_EXTRACTOR_REPORT_FOLDER,
207
+ DEFAULT_AUDIT_REPORT_DIR: () => DEFAULT_AUDIT_REPORT_DIR,
203
208
  DEFAULT_DECOMPOSITION_TEMPLATE: () => DEFAULT_DECOMPOSITION_TEMPLATE,
204
209
  DEFAULT_DELEGATE_TO_PR_REVIEWER: () => DEFAULT_DELEGATE_TO_PR_REVIEWER,
205
210
  DEFAULT_DISPATCH_MODEL: () => DEFAULT_DISPATCH_MODEL,
@@ -223,6 +228,7 @@ __export(index_exports, {
223
228
  DEFAULT_PROGRESS_FILES_STATE_DIR: () => DEFAULT_PROGRESS_FILES_STATE_DIR,
224
229
  DEFAULT_REQUIRE_LINKED_ISSUE: () => DEFAULT_REQUIRE_LINKED_ISSUE,
225
230
  DEFAULT_REQUIRE_PRODUCT_CONTEXT: () => DEFAULT_REQUIRE_PRODUCT_CONTEXT,
231
+ DEFAULT_SAMPLE_COMPILER_OPTIONS: () => DEFAULT_SAMPLE_COMPILER_OPTIONS,
226
232
  DEFAULT_SCHEDULED_TASKS_ROOT: () => DEFAULT_SCHEDULED_TASKS_ROOT,
227
233
  DEFAULT_SCHEDULED_TASK_ENTRIES: () => DEFAULT_SCHEDULED_TASK_ENTRIES,
228
234
  DEFAULT_SHARED_EDITING_CONFLICT_STRATEGY: () => DEFAULT_SHARED_EDITING_CONFLICT_STRATEGY,
@@ -246,6 +252,7 @@ __export(index_exports, {
246
252
  DEFAULT_WORKFLOW_DIAGRAMS_ENABLED: () => DEFAULT_WORKFLOW_DIAGRAMS_ENABLED,
247
253
  DEFAULT_WORKFLOW_DIAGRAMS_PATH: () => DEFAULT_WORKFLOW_DIAGRAMS_PATH,
248
254
  DEFAULT_WORKFLOW_DIAGRAMS_REQUIRE_UPDATE: () => DEFAULT_WORKFLOW_DIAGRAMS_REQUIRE_UPDATE,
255
+ DOCS_SYNC_AUDIT_SCHEMA_VERSION: () => DOCS_SYNC_AUDIT_SCHEMA_VERSION,
249
256
  JsiiFaker: () => JsiiFaker,
250
257
  LAYOUT_ENFORCEMENT: () => LAYOUT_ENFORCEMENT,
251
258
  LAYOUT_ROOT_BY_PROJECT_TYPE: () => LAYOUT_ROOT_BY_PROJECT_TYPE,
@@ -268,6 +275,7 @@ __export(index_exports, {
268
275
  SCOPE_CLASS_VALUES: () => SCOPE_CLASS_VALUES,
269
276
  SHARED_EDITING_CONFLICT_STRATEGY_VALUES: () => SHARED_EDITING_CONFLICT_STRATEGY_VALUES,
270
277
  STARLIGHT_ROLE: () => STARLIGHT_ROLE,
278
+ SampleLang: () => SampleLang,
271
279
  StarlightProject: () => StarlightProject,
272
280
  TestRunner: () => TestRunner,
273
281
  TsDocCoverageKind: () => TsDocCoverageKind,
@@ -286,6 +294,7 @@ __export(index_exports, {
286
294
  addSyncLabelsWorkflow: () => addSyncLabelsWorkflow,
287
295
  agendaBundle: () => agendaBundle,
288
296
  analyzeTsDocCoverage: () => analyzeTsDocCoverage,
297
+ auditReportJsonSchema: () => auditReportJsonSchema,
289
298
  awsCdkBundle: () => awsCdkBundle,
290
299
  baseBundle: () => baseBundle,
291
300
  bcmWriterBundle: () => bcmWriterBundle,
@@ -302,6 +311,7 @@ __export(index_exports, {
302
311
  buildOrchestratorConventionsContent: () => buildOrchestratorConventionsContent,
303
312
  buildPeopleProfileBundle: () => buildPeopleProfileBundle,
304
313
  buildRegulatoryResearchBundle: () => buildRegulatoryResearchBundle,
314
+ buildReport: () => buildReport,
305
315
  buildRequirementsAnalystBundle: () => buildRequirementsAnalystBundle,
306
316
  buildRequirementsReviewerBundle: () => buildRequirementsReviewerBundle,
307
317
  buildRequirementsWriterBundle: () => buildRequirementsWriterBundle,
@@ -310,14 +320,18 @@ __export(index_exports, {
310
320
  buildStandardsResearchBundle: () => buildStandardsResearchBundle,
311
321
  buildUnblockDependentsProcedure: () => buildUnblockDependentsProcedure,
312
322
  businessModelsBundle: () => businessModelsBundle,
323
+ checkDocSamplesProcedure: () => checkDocSamplesProcedure,
313
324
  checkLinksProcedure: () => checkLinksProcedure,
314
325
  classifyIssueScope: () => classifyIssueScope,
315
326
  classifyRun: () => classifyRun,
316
327
  companyProfileBundle: () => companyProfileBundle,
328
+ compileFencedSamples: () => compileFencedSamples,
317
329
  customerProfileBundle: () => customerProfileBundle,
318
330
  docsSyncBundle: () => docsSyncBundle,
331
+ emptyCategoryBuckets: () => emptyCategoryBuckets,
319
332
  extractApiProcedure: () => extractApiProcedure,
320
333
  extractDocReferences: () => extractDocReferences,
334
+ extractFencedSamples: () => extractFencedSamples,
321
335
  formatLayoutViolation: () => formatLayoutViolation,
322
336
  formatStarlightSingletonViolation: () => formatStarlightSingletonViolation,
323
337
  getLatestEligibleVersion: () => getLatestEligibleVersion,
@@ -328,12 +342,14 @@ __export(index_exports, {
328
342
  meetingAnalysisBundle: () => meetingAnalysisBundle,
329
343
  orchestratorBundle: () => orchestratorBundle,
330
344
  peopleProfileBundle: () => peopleProfileBundle,
345
+ persistAuditReport: () => persistAuditReport,
331
346
  pnpmBundle: () => pnpmBundle,
332
347
  prReviewBundle: () => prReviewBundle,
333
348
  projenBundle: () => projenBundle,
334
349
  regulatoryResearchBundle: () => regulatoryResearchBundle,
335
350
  renderAgentTierCaseStatement: () => renderAgentTierCaseStatement,
336
351
  renderAgentTierSection: () => renderAgentTierSection,
352
+ renderCheckDocSamplesProcedure: () => renderCheckDocSamplesProcedure,
337
353
  renderCheckLinksProcedure: () => renderCheckLinksProcedure,
338
354
  renderCustomDocSectionBlock: () => renderCustomDocSectionBlock,
339
355
  renderCustomDocSections: () => renderCustomDocSections,
@@ -393,6 +409,7 @@ __export(index_exports, {
393
409
  resolveTypeScriptProjectOutdir: () => resolveTypeScriptProjectOutdir,
394
410
  resolveUnblockDependents: () => resolveUnblockDependents,
395
411
  resolveWorkflowDiagrams: () => resolveWorkflowDiagrams,
412
+ runScan: () => runScan,
396
413
  slackBundle: () => slackBundle,
397
414
  softwareProfileBundle: () => softwareProfileBundle,
398
415
  standardsResearchBundle: () => standardsResearchBundle,
@@ -8730,6 +8747,63 @@ function buildDocsSyncSubAgent(_paths) {
8730
8747
  "",
8731
8748
  "---",
8732
8749
  "",
8750
+ "## Phase 1: Scan",
8751
+ "",
8752
+ "Phase 1 walks the repo, runs every registered drift check, and",
8753
+ "writes a single combined **audit report** to disk. Phase 1 never",
8754
+ "edits documentation \u2014 only the persisted report changes between",
8755
+ "scan and fix.",
8756
+ "",
8757
+ "### Audit report",
8758
+ "",
8759
+ "The report shape is exported from `@codedrifters/configulator`",
8760
+ "as `AuditReport` (under `src/docs-sync/scan/`) so Phase 2 and",
8761
+ "any downstream consumers share one definition. Reports are",
8762
+ "persisted at:",
8763
+ "",
8764
+ "```",
8765
+ ".claude/state/docs-sync/<issue-number>-audit.json",
8766
+ "```",
8767
+ "",
8768
+ "Every report carries a `schemaVersion`, the `issueNumber`, the",
8769
+ "invocation `mode` (`pr` or `audit`), the `generatedAt` UTC",
8770
+ "timestamp, the `repoRoot`, and an optional `scope` label, plus",
8771
+ "two parallel views of the findings:",
8772
+ "",
8773
+ "- **`categories`** \u2014 findings grouped by drift-check category.",
8774
+ " Every category key is always present; empty arrays are",
8775
+ " persisted explicitly. The five categories are `apiDiff`,",
8776
+ " `tsdocCoverage`, `referenceMismatches`, `linkFailures`, and",
8777
+ " `sampleFailures`.",
8778
+ "- **`findings`** \u2014 the same records re-aggregated as a single",
8779
+ " flat array, sorted by severity (`blocking` first), then",
8780
+ " category, file, line, and subject. Provided so consumers",
8781
+ " that don't need the category grouping can iterate one array",
8782
+ " and see the merge-blocking findings at the top.",
8783
+ "",
8784
+ "Every finding carries a `category`, `severity`",
8785
+ "(`mechanical` / `advisory` / `blocking`), `location`, `subject`,",
8786
+ "`details`, and an optional `fixHint` for the Phase 2 fix agent.",
8787
+ "",
8788
+ "### Orchestrator",
8789
+ "",
8790
+ "The scan is driven by `runScan(...)` (also exported under",
8791
+ "`src/docs-sync/scan/`). The orchestrator accepts a list of",
8792
+ "`AuditCheckRunner` instances, invokes each one in registration",
8793
+ "order, merges the findings into the report, and (optionally)",
8794
+ "persists the report to disk. The default check list is empty \u2014",
8795
+ "this skeleton release runs cleanly with no checks registered",
8796
+ "and produces a schema-compliant report whose category arrays",
8797
+ "are all empty.",
8798
+ "",
8799
+ "Children of the parent docs-sync epic plug runners into the",
8800
+ "orchestrator: API/TSDoc/reference checks land first, link",
8801
+ "and fenced-sample checks land second, the fix phase reads the",
8802
+ "persisted report, and the audit-mode walker reuses the same",
8803
+ "report shape.",
8804
+ "",
8805
+ "---",
8806
+ "",
8733
8807
  "## Write Boundaries",
8734
8808
  "",
8735
8809
  "Even once the pipeline is wired, the following boundaries are",
@@ -9269,6 +9343,126 @@ var checkLinksProcedure = {
9269
9343
  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.",
9270
9344
  content: renderCheckLinksProcedure()
9271
9345
  };
9346
+ function renderCheckDocSamplesProcedure() {
9347
+ const nodeScript = [
9348
+ "(async () => {",
9349
+ " const { compileFencedSamples } = await import('@codedrifters/configulator');",
9350
+ " const docsRoot = process.argv[1];",
9351
+ " const failures = compileFencedSamples({ docsRoot });",
9352
+ " process.stdout.write(JSON.stringify(failures));",
9353
+ "})().catch((err) => {",
9354
+ " console.error('check-doc-samples.sh: ' + (err && err.stack ? err.stack : err));",
9355
+ " process.exit(3);",
9356
+ "});"
9357
+ ].join("\n");
9358
+ return [
9359
+ "#!/usr/bin/env bash",
9360
+ "# check-doc-samples.sh \u2014 Compile fenced TS/TSX samples in the Starlight docs.",
9361
+ "#",
9362
+ "# Usage:",
9363
+ "# .claude/procedures/check-doc-samples.sh <docs-root>",
9364
+ "#",
9365
+ "# Where:",
9366
+ "# <docs-root> \u2014 path to the markdown content tree",
9367
+ "# (e.g. `docs/src/content/docs`). Walked recursively",
9368
+ "# for `*.md` files.",
9369
+ "#",
9370
+ "# Wraps the `compileFencedSamples` API exported from",
9371
+ "# `@codedrifters/configulator`. For every fenced ` ```ts `,",
9372
+ "# ` ```typescript `, ` ```tsx `, or ` ```typescriptreact ` block in",
9373
+ "# the docs, the helper writes the sample to an in-memory file,",
9374
+ "# runs the TypeScript compiler against it (in-process, via the TS",
9375
+ "# compiler API), and reports any compilation diagnostics.",
9376
+ "#",
9377
+ "# Skipped samples (fence meta `skip` / `no-check`, or first line",
9378
+ "# `// @no-check`) are passed through unchecked.",
9379
+ "#",
9380
+ "# Output (stdout, single JSON array):",
9381
+ "#",
9382
+ "# [",
9383
+ "# {",
9384
+ '# "docPath": "<path relative to <docs-root>>",',
9385
+ '# "line": <1-indexed line number of the opening fence>,',
9386
+ '# "fenceIndex": <0-indexed fenced-block position within the doc>,',
9387
+ '# "lang": "ts" | "typescript" | "tsx" | "typescriptreact",',
9388
+ '# "diagnostics": [ "<TS<code>: <message>>", ... ]',
9389
+ "# },",
9390
+ "# ...",
9391
+ "# ]",
9392
+ "#",
9393
+ "# An empty array (`[]`) is emitted when every sample compiled.",
9394
+ "# Detection is **data**, not failure: this helper exits 0 when the",
9395
+ "# compilation phase ran successfully, regardless of how many",
9396
+ "# samples failed to compile. The downstream docs-sync scan phase",
9397
+ "# (#520) is responsible for treating failures as one of the two",
9398
+ "# hard-block cases per the parent epic.",
9399
+ "#",
9400
+ "# Exit codes:",
9401
+ "# 0 \u2014 compilation phase ran; failures (zero or more) are on",
9402
+ "# stdout as a JSON array.",
9403
+ "# 1 \u2014 usage error (missing args, unreadable docs root).",
9404
+ "# 2 \u2014 a required binary is not on PATH (`node` / `pnpm`).",
9405
+ "# 3 \u2014 the compilation phase threw an unhandled exception.",
9406
+ "# Stderr carries the diagnostic.",
9407
+ "#",
9408
+ "# Dependencies: expects `node` and `pnpm` on PATH and the workspace",
9409
+ "# `@codedrifters/configulator` package to be installed (the helper",
9410
+ "# resolves the API through `pnpm exec node` from the repo root).",
9411
+ "",
9412
+ "set -uo pipefail",
9413
+ "",
9414
+ "err() {",
9415
+ ' printf "check-doc-samples.sh: %s\\n" "$*" >&2',
9416
+ "}",
9417
+ "",
9418
+ 'if [ "$#" -lt 1 ]; then',
9419
+ ' err "usage: check-doc-samples.sh <docs-root>"',
9420
+ " exit 1",
9421
+ "fi",
9422
+ "",
9423
+ 'docs_root="$1"',
9424
+ "",
9425
+ 'if [ ! -d "$docs_root" ]; then',
9426
+ ' err "docs root not found: $docs_root"',
9427
+ " exit 1",
9428
+ "fi",
9429
+ "",
9430
+ "if ! command -v node >/dev/null 2>&1; then",
9431
+ ' err "node is required but not on PATH"',
9432
+ " exit 2",
9433
+ "fi",
9434
+ "",
9435
+ "if ! command -v pnpm >/dev/null 2>&1; then",
9436
+ ' err "pnpm is required but not on PATH"',
9437
+ " exit 2",
9438
+ "fi",
9439
+ "",
9440
+ "# Resolve docs_root to an absolute path so the inline node script",
9441
+ "# is independent of the cwd `pnpm exec` chooses.",
9442
+ 'docs_root_abs="$(cd "$docs_root" && pwd)"',
9443
+ "",
9444
+ "# Run the inline node script through `pnpm exec` so module",
9445
+ "# resolution finds `@codedrifters/configulator` via the workspace",
9446
+ "# even when the helper is invoked from a sub-package directory.",
9447
+ "# The `--input-type=module` flag lets us use top-level `await` and",
9448
+ "# `import()` cleanly. Diagnostics from the script flow to stderr;",
9449
+ "# stdout carries only the JSON array.",
9450
+ 'pnpm exec node --input-type=module -e "' + nodeScript.replace(/"/g, '\\"') + '" "$docs_root_abs"',
9451
+ "status=$?",
9452
+ "",
9453
+ 'if [ "$status" -ne 0 ]; then',
9454
+ ' err "compileFencedSamples exited with status $status"',
9455
+ " exit 3",
9456
+ "fi",
9457
+ "",
9458
+ "exit 0"
9459
+ ].join("\n");
9460
+ }
9461
+ var checkDocSamplesProcedure = {
9462
+ name: "check-doc-samples.sh",
9463
+ 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.",
9464
+ content: renderCheckDocSamplesProcedure()
9465
+ };
9272
9466
  function buildDocsSyncBundle(paths = DEFAULT_AGENT_PATHS) {
9273
9467
  return {
9274
9468
  name: "docs-sync",
@@ -9318,7 +9512,11 @@ function buildDocsSyncBundle(paths = DEFAULT_AGENT_PATHS) {
9318
9512
  ],
9319
9513
  skills: [buildDocsSyncPrSkill(), buildDocsSyncAuditSkill()],
9320
9514
  subAgents: [buildDocsSyncSubAgent(paths)],
9321
- procedures: [extractApiProcedure, checkLinksProcedure],
9515
+ procedures: [
9516
+ extractApiProcedure,
9517
+ checkLinksProcedure,
9518
+ checkDocSamplesProcedure
9519
+ ],
9322
9520
  labels: [
9323
9521
  {
9324
9522
  name: "type:docs-sync",
@@ -27062,8 +27260,8 @@ var FALLBACKS = {
27062
27260
  monorepoLayoutSeedBlock: ""
27063
27261
  };
27064
27262
  var TEMPLATE_RE = /\{\{(\w+(?:\.\w+)*)\}\}/g;
27065
- function getNestedValue(obj, path4) {
27066
- const parts = path4.split(".");
27263
+ function getNestedValue(obj, path7) {
27264
+ const parts = path7.split(".");
27067
27265
  let current = obj;
27068
27266
  for (const part of parts) {
27069
27267
  if (current == null || typeof current !== "object") {
@@ -27289,20 +27487,20 @@ var ClaudeRenderer = class _ClaudeRenderer {
27289
27487
  obj.excludedCommands = [...sandbox.excludedCommands];
27290
27488
  }
27291
27489
  if (sandbox.filesystem) {
27292
- const fs2 = {};
27490
+ const fs4 = {};
27293
27491
  if (sandbox.filesystem.allowRead?.length) {
27294
- fs2.allowRead = [...sandbox.filesystem.allowRead];
27492
+ fs4.allowRead = [...sandbox.filesystem.allowRead];
27295
27493
  }
27296
27494
  if (sandbox.filesystem.denyRead?.length) {
27297
- fs2.denyRead = [...sandbox.filesystem.denyRead];
27495
+ fs4.denyRead = [...sandbox.filesystem.denyRead];
27298
27496
  }
27299
27497
  if (sandbox.filesystem.allowWrite?.length) {
27300
- fs2.allowWrite = [...sandbox.filesystem.allowWrite];
27498
+ fs4.allowWrite = [...sandbox.filesystem.allowWrite];
27301
27499
  }
27302
27500
  if (sandbox.filesystem.denyWrite?.length) {
27303
- fs2.denyWrite = [...sandbox.filesystem.denyWrite];
27501
+ fs4.denyWrite = [...sandbox.filesystem.denyWrite];
27304
27502
  }
27305
- if (Object.keys(fs2).length > 0) obj.filesystem = fs2;
27503
+ if (Object.keys(fs4).length > 0) obj.filesystem = fs4;
27306
27504
  }
27307
27505
  if (sandbox.network) {
27308
27506
  const net = {};
@@ -29164,10 +29362,754 @@ function stripYamlFrontmatter(source) {
29164
29362
  return lines.join("\n");
29165
29363
  }
29166
29364
 
29167
- // src/docs-sync/tsdoc-coverage/coverage.ts
29365
+ // src/docs-sync/sample-compilation/compilation.ts
29366
+ var path4 = __toESM(require("path"));
29367
+ var ts = __toESM(require("typescript"));
29368
+
29369
+ // src/docs-sync/sample-compilation/extraction.ts
29370
+ var fs2 = __toESM(require("fs"));
29168
29371
  var path3 = __toESM(require("path"));
29372
+ var import_mdast_util_from_markdown2 = require("mdast-util-from-markdown");
29373
+ var SampleLang = {
29374
+ Ts: "ts",
29375
+ Typescript: "typescript",
29376
+ Tsx: "tsx",
29377
+ Typescriptreact: "typescriptreact"
29378
+ };
29379
+ var DEFAULT_DOCS_ROOT2 = "docs/src/content/docs";
29380
+ var PLAIN_LANGS = /* @__PURE__ */ new Set([SampleLang.Ts, SampleLang.Typescript]);
29381
+ var JSX_LANGS = /* @__PURE__ */ new Set([
29382
+ SampleLang.Tsx,
29383
+ SampleLang.Typescriptreact
29384
+ ]);
29385
+ function extractFencedSamples(options = {}) {
29386
+ const docsRoot = path3.resolve(options.docsRoot ?? DEFAULT_DOCS_ROOT2);
29387
+ const includeTsx = options.includeTsx ?? true;
29388
+ if (!fs2.existsSync(docsRoot)) {
29389
+ return [];
29390
+ }
29391
+ const records = [];
29392
+ for (const absolutePath of walkMarkdownFiles2(docsRoot)) {
29393
+ const docPath = toPosix2(path3.relative(docsRoot, absolutePath));
29394
+ const source = fs2.readFileSync(absolutePath, "utf-8");
29395
+ const tree = (0, import_mdast_util_from_markdown2.fromMarkdown)(stripYamlFrontmatter2(source));
29396
+ let fenceIndex = 0;
29397
+ collectFencedCode(tree, (node) => {
29398
+ const lang = normalizeLang(node.lang);
29399
+ if (lang === void 0) {
29400
+ return;
29401
+ }
29402
+ if (!includeTsx && JSX_LANGS.has(lang)) {
29403
+ return;
29404
+ }
29405
+ if (!PLAIN_LANGS.has(lang) && !JSX_LANGS.has(lang)) {
29406
+ return;
29407
+ }
29408
+ const start = node.position?.start;
29409
+ if (!start) {
29410
+ return;
29411
+ }
29412
+ const skip = detectSkip(node);
29413
+ records.push({
29414
+ docPath,
29415
+ line: start.line,
29416
+ fenceIndex,
29417
+ lang,
29418
+ code: node.value ?? "",
29419
+ skipped: skip.skipped,
29420
+ skipReason: skip.reason
29421
+ });
29422
+ fenceIndex += 1;
29423
+ });
29424
+ }
29425
+ records.sort((a, b) => {
29426
+ if (a.docPath !== b.docPath) {
29427
+ return a.docPath.localeCompare(b.docPath);
29428
+ }
29429
+ if (a.line !== b.line) {
29430
+ return a.line - b.line;
29431
+ }
29432
+ return a.fenceIndex - b.fenceIndex;
29433
+ });
29434
+ return records;
29435
+ }
29436
+ function walkMarkdownFiles2(root) {
29437
+ const out = [];
29438
+ const stack = [root];
29439
+ while (stack.length > 0) {
29440
+ const dir = stack.pop();
29441
+ let entries;
29442
+ try {
29443
+ entries = fs2.readdirSync(dir, { withFileTypes: true });
29444
+ } catch {
29445
+ continue;
29446
+ }
29447
+ for (const entry of entries) {
29448
+ const full = path3.join(dir, entry.name);
29449
+ if (entry.isDirectory()) {
29450
+ stack.push(full);
29451
+ } else if (entry.isFile() && full.toLowerCase().endsWith(".md")) {
29452
+ out.push(full);
29453
+ }
29454
+ }
29455
+ }
29456
+ out.sort();
29457
+ return out;
29458
+ }
29459
+ function collectFencedCode(tree, visit) {
29460
+ walk(tree);
29461
+ function walk(node) {
29462
+ if (node.type === "code") {
29463
+ visit(node);
29464
+ return;
29465
+ }
29466
+ if (node.type === "html") {
29467
+ return;
29468
+ }
29469
+ const parent = node;
29470
+ if (Array.isArray(parent.children)) {
29471
+ for (const child of parent.children) {
29472
+ walk(child);
29473
+ }
29474
+ }
29475
+ }
29476
+ }
29477
+ function normalizeLang(raw) {
29478
+ if (!raw) {
29479
+ return void 0;
29480
+ }
29481
+ const lower = raw.toLowerCase();
29482
+ switch (lower) {
29483
+ case "ts":
29484
+ return SampleLang.Ts;
29485
+ case "typescript":
29486
+ return SampleLang.Typescript;
29487
+ case "tsx":
29488
+ return SampleLang.Tsx;
29489
+ case "typescriptreact":
29490
+ return SampleLang.Typescriptreact;
29491
+ default:
29492
+ return void 0;
29493
+ }
29494
+ }
29495
+ var META_SKIP_PATTERN = /\b(skip|no-check)\b/i;
29496
+ var PRAGMA_NO_CHECK_PATTERN = /^\s*\/\/\s*@no-check\b/i;
29497
+ function detectSkip(node) {
29498
+ const meta = node.meta ?? "";
29499
+ const metaMatch = META_SKIP_PATTERN.exec(meta);
29500
+ if (metaMatch) {
29501
+ return { skipped: true, reason: `meta:${metaMatch[1].toLowerCase()}` };
29502
+ }
29503
+ const code = node.value ?? "";
29504
+ const firstLine = firstNonBlankLine(code);
29505
+ if (firstLine !== void 0 && PRAGMA_NO_CHECK_PATTERN.test(firstLine)) {
29506
+ return { skipped: true, reason: "pragma:@no-check" };
29507
+ }
29508
+ return { skipped: false, reason: "" };
29509
+ }
29510
+ function firstNonBlankLine(source) {
29511
+ for (const line of source.split("\n")) {
29512
+ if (line.trim().length > 0) {
29513
+ return line;
29514
+ }
29515
+ }
29516
+ return void 0;
29517
+ }
29518
+ function toPosix2(p) {
29519
+ return p.split(path3.sep).join("/");
29520
+ }
29521
+ function stripYamlFrontmatter2(source) {
29522
+ if (!source.startsWith("---")) {
29523
+ return source;
29524
+ }
29525
+ const lines = source.split("\n");
29526
+ if (lines[0] !== "---") {
29527
+ return source;
29528
+ }
29529
+ let endIndex = -1;
29530
+ for (let i = 1; i < lines.length; i++) {
29531
+ if (lines[i] === "---") {
29532
+ endIndex = i;
29533
+ break;
29534
+ }
29535
+ }
29536
+ if (endIndex < 0) {
29537
+ return source;
29538
+ }
29539
+ for (let i = 0; i <= endIndex; i++) {
29540
+ lines[i] = "";
29541
+ }
29542
+ return lines.join("\n");
29543
+ }
29544
+
29545
+ // src/docs-sync/sample-compilation/compilation.ts
29546
+ var DEFAULT_SAMPLE_COMPILER_OPTIONS = {
29547
+ target: ts.ScriptTarget.ES2022,
29548
+ module: ts.ModuleKind.ESNext,
29549
+ moduleResolution: ts.ModuleResolutionKind.Bundler,
29550
+ lib: ["lib.es2022.d.ts", "lib.dom.d.ts"],
29551
+ strict: true,
29552
+ noUnusedLocals: false,
29553
+ noUnusedParameters: false,
29554
+ skipLibCheck: true,
29555
+ esModuleInterop: true,
29556
+ resolveJsonModule: true,
29557
+ isolatedModules: true,
29558
+ jsx: ts.JsxEmit.Preserve,
29559
+ noEmit: true,
29560
+ allowSyntheticDefaultImports: true
29561
+ };
29562
+ var REPO_RELATIVE_MODULE_PATTERN = /^['"](?:\.\.?\/|\/)/;
29563
+ function compileFencedSamples(options = {}) {
29564
+ const samples = extractFencedSamples(options);
29565
+ const tolerateRepoRelative = options.tolerateRepoRelativeMissingModule ?? true;
29566
+ const failures = [];
29567
+ for (const sample of samples) {
29568
+ if (sample.skipped) {
29569
+ continue;
29570
+ }
29571
+ const diagnostics = compileSingleSample(
29572
+ sample,
29573
+ options.compilerOptions,
29574
+ tolerateRepoRelative
29575
+ );
29576
+ if (diagnostics.length > 0) {
29577
+ failures.push({
29578
+ docPath: sample.docPath,
29579
+ line: sample.line,
29580
+ fenceIndex: sample.fenceIndex,
29581
+ lang: sample.lang,
29582
+ diagnostics
29583
+ });
29584
+ }
29585
+ }
29586
+ return failures;
29587
+ }
29588
+ function compileSingleSample(sample, overrides, tolerateRepoRelative) {
29589
+ const filename = sampleFilename(sample);
29590
+ const compilerOptions = mergeCompilerOptions(overrides);
29591
+ const host = createSingleFileHost(filename, sample.code, compilerOptions);
29592
+ const program = ts.createProgram({
29593
+ rootNames: [filename],
29594
+ options: compilerOptions,
29595
+ host
29596
+ });
29597
+ const sourceFile = program.getSourceFile(filename);
29598
+ const collected = [];
29599
+ if (sourceFile) {
29600
+ collected.push(...program.getSyntacticDiagnostics(sourceFile));
29601
+ collected.push(...program.getSemanticDiagnostics(sourceFile));
29602
+ } else {
29603
+ collected.push(...program.getSyntacticDiagnostics());
29604
+ collected.push(...program.getSemanticDiagnostics());
29605
+ }
29606
+ const diagnostics = [];
29607
+ for (const d of collected) {
29608
+ if (tolerateRepoRelative && isRepoRelativeMissingModule(d, sample.code)) {
29609
+ continue;
29610
+ }
29611
+ diagnostics.push(formatDiagnostic(d));
29612
+ }
29613
+ return diagnostics;
29614
+ }
29615
+ function sampleFilename(sample) {
29616
+ const safeDoc = sample.docPath.replace(/[^a-zA-Z0-9]+/g, "_");
29617
+ const ext = sample.lang === SampleLang.Tsx || sample.lang === SampleLang.Typescriptreact ? "tsx" : "ts";
29618
+ return path4.posix.join("/", `${safeDoc}__${sample.fenceIndex}.${ext}`);
29619
+ }
29620
+ function mergeCompilerOptions(overrides) {
29621
+ if (!overrides) {
29622
+ return { ...DEFAULT_SAMPLE_COMPILER_OPTIONS };
29623
+ }
29624
+ const merged = { ...DEFAULT_SAMPLE_COMPILER_OPTIONS };
29625
+ for (const key of Object.keys(overrides)) {
29626
+ const value = overrides[key];
29627
+ if (value === void 0) {
29628
+ delete merged[key];
29629
+ } else {
29630
+ merged[key] = value;
29631
+ }
29632
+ }
29633
+ return merged;
29634
+ }
29635
+ function createSingleFileHost(filename, source, compilerOptions) {
29636
+ const baseHost = ts.createCompilerHost(compilerOptions, true);
29637
+ return {
29638
+ ...baseHost,
29639
+ getSourceFile(name, languageVersionOrOptions, onError, shouldCreate) {
29640
+ if (name === filename) {
29641
+ return ts.createSourceFile(
29642
+ name,
29643
+ source,
29644
+ languageVersionOrOptions,
29645
+ true
29646
+ );
29647
+ }
29648
+ return baseHost.getSourceFile(
29649
+ name,
29650
+ languageVersionOrOptions,
29651
+ onError,
29652
+ shouldCreate
29653
+ );
29654
+ },
29655
+ fileExists(name) {
29656
+ if (name === filename) {
29657
+ return true;
29658
+ }
29659
+ return baseHost.fileExists(name);
29660
+ },
29661
+ readFile(name) {
29662
+ if (name === filename) {
29663
+ return source;
29664
+ }
29665
+ return baseHost.readFile(name);
29666
+ },
29667
+ writeFile() {
29668
+ },
29669
+ getCanonicalFileName(name) {
29670
+ return baseHost.getCanonicalFileName(name);
29671
+ },
29672
+ useCaseSensitiveFileNames() {
29673
+ return baseHost.useCaseSensitiveFileNames();
29674
+ },
29675
+ getNewLine() {
29676
+ return baseHost.getNewLine();
29677
+ },
29678
+ getDefaultLibFileName(o) {
29679
+ return baseHost.getDefaultLibFileName(o);
29680
+ },
29681
+ getCurrentDirectory() {
29682
+ return baseHost.getCurrentDirectory();
29683
+ }
29684
+ };
29685
+ }
29686
+ function isRepoRelativeMissingModule(d, code) {
29687
+ if (d.code !== 2307) {
29688
+ return false;
29689
+ }
29690
+ const text = ts.flattenDiagnosticMessageText(d.messageText, "\n");
29691
+ const match = /'([^']+)'/.exec(text);
29692
+ if (!match) {
29693
+ return false;
29694
+ }
29695
+ const specifier = match[1];
29696
+ if (!specifier) {
29697
+ return false;
29698
+ }
29699
+ const inSourceSingle = `'${specifier}'`;
29700
+ const inSourceDouble = `"${specifier}"`;
29701
+ if (!code.includes(inSourceSingle) && !code.includes(inSourceDouble)) {
29702
+ return false;
29703
+ }
29704
+ return REPO_RELATIVE_MODULE_PATTERN.test(`'${specifier}'`);
29705
+ }
29706
+ function formatDiagnostic(d) {
29707
+ const text = ts.flattenDiagnosticMessageText(d.messageText, " ");
29708
+ const code = d.code === void 0 ? "" : `TS${d.code}: `;
29709
+ return `${code}${text}`.trim();
29710
+ }
29711
+
29712
+ // src/docs-sync/scan/audit-report.ts
29713
+ var AuditCategory = {
29714
+ /**
29715
+ * Findings produced by the public-API diff check that surfaces
29716
+ * added, renamed, or removed exports between the current branch
29717
+ * and the recorded baseline. Wired in by child issue #519.
29718
+ */
29719
+ ApiDiff: "apiDiff",
29720
+ /**
29721
+ * Findings produced by the TSDoc-coverage check that flags public
29722
+ * exports without a one-sentence summary. Wired in by child issue
29723
+ * #519.
29724
+ */
29725
+ TsdocCoverage: "tsdocCoverage",
29726
+ /**
29727
+ * Findings produced by the doc-reference cross-index check that
29728
+ * flags inline-code symbol mentions whose target is missing or
29729
+ * has changed. Wired in by child issue #519.
29730
+ */
29731
+ ReferenceMismatches: "referenceMismatches",
29732
+ /**
29733
+ * Findings produced by the link-integrity check (internal via
29734
+ * `astro check`, external via `lychee`). Wired in by child issue
29735
+ * #520.
29736
+ */
29737
+ LinkFailures: "linkFailures",
29738
+ /**
29739
+ * Findings produced by the fenced-sample compilation check that
29740
+ * flags ` ```ts ` / ` ```typescript ` / ` ```tsx ` blocks in the
29741
+ * docs that fail `tsc`. Wired in by child issue #520.
29742
+ */
29743
+ SampleFailures: "sampleFailures"
29744
+ };
29745
+ var AuditSeverity = {
29746
+ /**
29747
+ * The finding has a deterministic mechanical fix that the Phase 2
29748
+ * (Fix) agent will auto-apply (TSDoc stubs, dead-link updates,
29749
+ * registry sync, etc.).
29750
+ */
29751
+ Mechanical: "mechanical",
29752
+ /**
29753
+ * The finding deserves human attention but does not block the PR.
29754
+ * Surfaced as a non-blocking note on the sticky `## Docs sync`
29755
+ * comment.
29756
+ */
29757
+ Advisory: "advisory",
29758
+ /**
29759
+ * The finding blocks the PR. Per the parent epic this is reserved
29760
+ * for the two narrow cases of confirmed broken external links and
29761
+ * fenced TS samples that fail to compile.
29762
+ */
29763
+ Blocking: "blocking"
29764
+ };
29765
+ var AuditMode = {
29766
+ Pr: "pr",
29767
+ Audit: "audit"
29768
+ };
29769
+ var DOCS_SYNC_AUDIT_SCHEMA_VERSION = 1;
29770
+ function auditReportJsonSchema() {
29771
+ const locationSchema = {
29772
+ type: "object",
29773
+ additionalProperties: false,
29774
+ required: ["file", "line"],
29775
+ properties: {
29776
+ file: { type: "string" },
29777
+ line: { type: "integer", minimum: 0 }
29778
+ }
29779
+ };
29780
+ const findingBaseProperties = {
29781
+ severity: { type: "string", enum: ["mechanical", "advisory", "blocking"] },
29782
+ location: locationSchema,
29783
+ subject: { type: "string" },
29784
+ details: { type: "string" },
29785
+ fixHint: { type: "string" }
29786
+ };
29787
+ const apiDiffFindingSchema = {
29788
+ type: "object",
29789
+ required: [
29790
+ "category",
29791
+ "severity",
29792
+ "location",
29793
+ "subject",
29794
+ "details",
29795
+ "change",
29796
+ "symbol"
29797
+ ],
29798
+ properties: {
29799
+ ...findingBaseProperties,
29800
+ category: { type: "string", const: "apiDiff" },
29801
+ change: { type: "string", enum: ["added", "removed", "changed"] },
29802
+ symbol: { type: "string" }
29803
+ }
29804
+ };
29805
+ const tsdocCoverageFindingSchema = {
29806
+ type: "object",
29807
+ required: [
29808
+ "category",
29809
+ "severity",
29810
+ "location",
29811
+ "subject",
29812
+ "details",
29813
+ "shortfall",
29814
+ "symbol"
29815
+ ],
29816
+ properties: {
29817
+ ...findingBaseProperties,
29818
+ category: { type: "string", const: "tsdocCoverage" },
29819
+ shortfall: {
29820
+ type: "string",
29821
+ enum: [
29822
+ "missing-summary",
29823
+ "thin-summary",
29824
+ "missing-params",
29825
+ "missing-returns"
29826
+ ]
29827
+ },
29828
+ symbol: { type: "string" }
29829
+ }
29830
+ };
29831
+ const referenceMismatchFindingSchema = {
29832
+ type: "object",
29833
+ required: [
29834
+ "category",
29835
+ "severity",
29836
+ "location",
29837
+ "subject",
29838
+ "details",
29839
+ "mismatch",
29840
+ "symbol"
29841
+ ],
29842
+ properties: {
29843
+ ...findingBaseProperties,
29844
+ category: { type: "string", const: "referenceMismatches" },
29845
+ mismatch: {
29846
+ type: "string",
29847
+ enum: ["unknown-symbol", "signature-changed"]
29848
+ },
29849
+ symbol: { type: "string" }
29850
+ }
29851
+ };
29852
+ const linkFailureFindingSchema = {
29853
+ type: "object",
29854
+ required: [
29855
+ "category",
29856
+ "severity",
29857
+ "location",
29858
+ "subject",
29859
+ "details",
29860
+ "url",
29861
+ "kind",
29862
+ "reason"
29863
+ ],
29864
+ properties: {
29865
+ ...findingBaseProperties,
29866
+ category: { type: "string", const: "linkFailures" },
29867
+ url: { type: "string" },
29868
+ kind: { type: "string", enum: ["internal", "external"] },
29869
+ reason: { type: "string" }
29870
+ }
29871
+ };
29872
+ const sampleFailureFindingSchema = {
29873
+ type: "object",
29874
+ required: [
29875
+ "category",
29876
+ "severity",
29877
+ "location",
29878
+ "subject",
29879
+ "details",
29880
+ "fenceIndex",
29881
+ "lang",
29882
+ "diagnostics"
29883
+ ],
29884
+ properties: {
29885
+ ...findingBaseProperties,
29886
+ category: { type: "string", const: "sampleFailures" },
29887
+ fenceIndex: { type: "integer", minimum: 0 },
29888
+ lang: { type: "string" },
29889
+ diagnostics: { type: "array", items: { type: "string" } }
29890
+ }
29891
+ };
29892
+ return {
29893
+ $schema: "http://json-schema.org/draft-07/schema#",
29894
+ title: "DocsSyncAuditReport",
29895
+ type: "object",
29896
+ additionalProperties: false,
29897
+ required: [
29898
+ "schemaVersion",
29899
+ "issueNumber",
29900
+ "mode",
29901
+ "generatedAt",
29902
+ "repoRoot",
29903
+ "scope",
29904
+ "categories",
29905
+ "findings"
29906
+ ],
29907
+ properties: {
29908
+ schemaVersion: { type: "integer", const: DOCS_SYNC_AUDIT_SCHEMA_VERSION },
29909
+ issueNumber: { type: "integer", minimum: 0 },
29910
+ mode: { type: "string", enum: ["pr", "audit"] },
29911
+ generatedAt: { type: "string", format: "date-time" },
29912
+ repoRoot: { type: "string" },
29913
+ scope: { type: "string" },
29914
+ categories: {
29915
+ type: "object",
29916
+ additionalProperties: false,
29917
+ required: [
29918
+ "apiDiff",
29919
+ "tsdocCoverage",
29920
+ "referenceMismatches",
29921
+ "linkFailures",
29922
+ "sampleFailures"
29923
+ ],
29924
+ properties: {
29925
+ apiDiff: { type: "array", items: apiDiffFindingSchema },
29926
+ tsdocCoverage: { type: "array", items: tsdocCoverageFindingSchema },
29927
+ referenceMismatches: {
29928
+ type: "array",
29929
+ items: referenceMismatchFindingSchema
29930
+ },
29931
+ linkFailures: { type: "array", items: linkFailureFindingSchema },
29932
+ sampleFailures: { type: "array", items: sampleFailureFindingSchema }
29933
+ }
29934
+ },
29935
+ findings: {
29936
+ type: "array",
29937
+ items: {
29938
+ oneOf: [
29939
+ apiDiffFindingSchema,
29940
+ tsdocCoverageFindingSchema,
29941
+ referenceMismatchFindingSchema,
29942
+ linkFailureFindingSchema,
29943
+ sampleFailureFindingSchema
29944
+ ]
29945
+ }
29946
+ }
29947
+ }
29948
+ };
29949
+ }
29950
+
29951
+ // src/docs-sync/scan/run-scan.ts
29952
+ var fs3 = __toESM(require("fs"));
29953
+ var path5 = __toESM(require("path"));
29954
+ var DEFAULT_AUDIT_REPORT_DIR = ".claude/state/docs-sync";
29955
+ var SEVERITY_RANK = {
29956
+ blocking: 0,
29957
+ advisory: 1,
29958
+ mechanical: 2
29959
+ };
29960
+ var AUDIT_CATEGORY_ORDER = [
29961
+ AuditCategory.ApiDiff,
29962
+ AuditCategory.TsdocCoverage,
29963
+ AuditCategory.ReferenceMismatches,
29964
+ AuditCategory.LinkFailures,
29965
+ AuditCategory.SampleFailures
29966
+ ];
29967
+ function runScan(options) {
29968
+ const repoRoot = path5.resolve(options.repoRoot);
29969
+ const mode = options.mode;
29970
+ const scope = options.scope ?? "";
29971
+ const issueNumber = options.issueNumber;
29972
+ const checks = options.checks ?? [];
29973
+ const now = options.now ?? /* @__PURE__ */ new Date();
29974
+ const persist = options.persist ?? false;
29975
+ const reportDir = options.reportDir ?? DEFAULT_AUDIT_REPORT_DIR;
29976
+ const context = {
29977
+ repoRoot,
29978
+ mode,
29979
+ scope,
29980
+ issueNumber
29981
+ };
29982
+ const collected = [];
29983
+ for (const check of checks) {
29984
+ const result = check.run(context);
29985
+ for (const finding of result) {
29986
+ collected.push(finding);
29987
+ }
29988
+ }
29989
+ const report = buildReport({
29990
+ issueNumber,
29991
+ mode,
29992
+ scope,
29993
+ repoRoot,
29994
+ generatedAt: now,
29995
+ findings: collected
29996
+ });
29997
+ let reportPath = "";
29998
+ if (persist) {
29999
+ reportPath = persistAuditReport({
30000
+ report,
30001
+ repoRoot,
30002
+ reportDir
30003
+ });
30004
+ }
30005
+ return { report, reportPath };
30006
+ }
30007
+ function buildReport(args) {
30008
+ const buckets = emptyCategoryBuckets();
30009
+ for (const finding of args.findings) {
30010
+ pushIntoBucket(buckets, finding);
30011
+ }
30012
+ buckets.apiDiff.sort(compareFindings);
30013
+ buckets.tsdocCoverage.sort(compareFindings);
30014
+ buckets.referenceMismatches.sort(compareFindings);
30015
+ buckets.linkFailures.sort(compareFindings);
30016
+ buckets.sampleFailures.sort(compareFindings);
30017
+ const flat = [];
30018
+ for (const key of AUDIT_CATEGORY_ORDER) {
30019
+ const bucket = buckets[key];
30020
+ for (const finding of bucket) {
30021
+ flat.push(finding);
30022
+ }
30023
+ }
30024
+ flat.sort(compareFindings);
30025
+ return {
30026
+ schemaVersion: DOCS_SYNC_AUDIT_SCHEMA_VERSION,
30027
+ issueNumber: args.issueNumber,
30028
+ mode: args.mode,
30029
+ generatedAt: args.generatedAt.toISOString(),
30030
+ repoRoot: args.repoRoot,
30031
+ scope: args.scope,
30032
+ categories: {
30033
+ apiDiff: buckets.apiDiff,
30034
+ tsdocCoverage: buckets.tsdocCoverage,
30035
+ referenceMismatches: buckets.referenceMismatches,
30036
+ linkFailures: buckets.linkFailures,
30037
+ sampleFailures: buckets.sampleFailures
30038
+ },
30039
+ findings: flat
30040
+ };
30041
+ }
30042
+ function persistAuditReport(args) {
30043
+ const repoRoot = path5.resolve(args.repoRoot);
30044
+ const reportDir = args.reportDir ?? DEFAULT_AUDIT_REPORT_DIR;
30045
+ const targetDir = path5.resolve(repoRoot, reportDir);
30046
+ fs3.mkdirSync(targetDir, { recursive: true });
30047
+ const targetFile = path5.join(
30048
+ targetDir,
30049
+ `${args.report.issueNumber}-audit.json`
30050
+ );
30051
+ const tempFile = `${targetFile}.tmp-${process.pid}-${Date.now()}`;
30052
+ const serialized = `${JSON.stringify(args.report, null, 2)}
30053
+ `;
30054
+ fs3.writeFileSync(tempFile, serialized, "utf-8");
30055
+ fs3.renameSync(tempFile, targetFile);
30056
+ return targetFile;
30057
+ }
30058
+ function emptyCategoryBuckets() {
30059
+ return {
30060
+ apiDiff: [],
30061
+ tsdocCoverage: [],
30062
+ referenceMismatches: [],
30063
+ linkFailures: [],
30064
+ sampleFailures: []
30065
+ };
30066
+ }
30067
+ function pushIntoBucket(buckets, finding) {
30068
+ switch (finding.category) {
30069
+ case AuditCategory.ApiDiff:
30070
+ buckets.apiDiff.push(finding);
30071
+ return;
30072
+ case AuditCategory.TsdocCoverage:
30073
+ buckets.tsdocCoverage.push(finding);
30074
+ return;
30075
+ case AuditCategory.ReferenceMismatches:
30076
+ buckets.referenceMismatches.push(finding);
30077
+ return;
30078
+ case AuditCategory.LinkFailures:
30079
+ buckets.linkFailures.push(finding);
30080
+ return;
30081
+ case AuditCategory.SampleFailures:
30082
+ buckets.sampleFailures.push(finding);
30083
+ return;
30084
+ default: {
30085
+ const exhaustive = finding;
30086
+ throw new Error(
30087
+ `runScan: unrecognized finding category: ${JSON.stringify(exhaustive)}`
30088
+ );
30089
+ }
30090
+ }
30091
+ }
30092
+ function compareFindings(a, b) {
30093
+ const sevDelta = SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity];
30094
+ if (sevDelta !== 0) {
30095
+ return sevDelta;
30096
+ }
30097
+ if (a.category !== b.category) {
30098
+ return a.category.localeCompare(b.category);
30099
+ }
30100
+ if (a.location.file !== b.location.file) {
30101
+ return a.location.file.localeCompare(b.location.file);
30102
+ }
30103
+ if (a.location.line !== b.location.line) {
30104
+ return a.location.line - b.location.line;
30105
+ }
30106
+ return a.subject.localeCompare(b.subject);
30107
+ }
30108
+
30109
+ // src/docs-sync/tsdoc-coverage/coverage.ts
30110
+ var path6 = __toESM(require("path"));
29169
30111
  var import_tsdoc = require("@microsoft/tsdoc");
29170
- var ts = __toESM(require("typescript"));
30112
+ var ts2 = __toESM(require("typescript"));
29171
30113
  var TsDocCoverageKind = {
29172
30114
  Class: "Class",
29173
30115
  Interface: "Interface",
@@ -29183,8 +30125,8 @@ var DEFAULT_THIN_SUMMARY_WORD_THRESHOLD = 4;
29183
30125
  var DEFAULT_ENTRY_POINT = "src/index.ts";
29184
30126
  function analyzeTsDocCoverage(options) {
29185
30127
  const resolvedOptions = typeof options === "string" ? { packageRoot: options } : options;
29186
- const packageRoot = path3.resolve(resolvedOptions.packageRoot);
29187
- const entryPoint = path3.resolve(
30128
+ const packageRoot = path6.resolve(resolvedOptions.packageRoot);
30129
+ const entryPoint = path6.resolve(
29188
30130
  packageRoot,
29189
30131
  resolvedOptions.entryPoint ?? DEFAULT_ENTRY_POINT
29190
30132
  );
@@ -29193,7 +30135,7 @@ function analyzeTsDocCoverage(options) {
29193
30135
  packageRoot,
29194
30136
  resolvedOptions.tsconfigPath
29195
30137
  );
29196
- const program = ts.createProgram({
30138
+ const program = ts2.createProgram({
29197
30139
  rootNames: [entryPoint],
29198
30140
  options: compilerOptions
29199
30141
  });
@@ -29247,24 +30189,24 @@ function analyzeTsDocCoverage(options) {
29247
30189
  }
29248
30190
  function resolveCompilerOptions(packageRoot, tsconfigPath) {
29249
30191
  if (tsconfigPath) {
29250
- const absoluteTsconfig = path3.resolve(packageRoot, tsconfigPath);
29251
- const configFile = ts.readConfigFile(absoluteTsconfig, ts.sys.readFile);
30192
+ const absoluteTsconfig = path6.resolve(packageRoot, tsconfigPath);
30193
+ const configFile = ts2.readConfigFile(absoluteTsconfig, ts2.sys.readFile);
29252
30194
  if (configFile.error) {
29253
30195
  throw new Error(
29254
- `analyzeTsDocCoverage: failed to read tsconfig at ${absoluteTsconfig}: ${ts.flattenDiagnosticMessageText(configFile.error.messageText, "\n")}`
30196
+ `analyzeTsDocCoverage: failed to read tsconfig at ${absoluteTsconfig}: ${ts2.flattenDiagnosticMessageText(configFile.error.messageText, "\n")}`
29255
30197
  );
29256
30198
  }
29257
- const parsed = ts.parseJsonConfigFileContent(
30199
+ const parsed = ts2.parseJsonConfigFileContent(
29258
30200
  configFile.config,
29259
- ts.sys,
29260
- path3.dirname(absoluteTsconfig)
30201
+ ts2.sys,
30202
+ path6.dirname(absoluteTsconfig)
29261
30203
  );
29262
30204
  return { ...parsed.options, noEmit: true };
29263
30205
  }
29264
30206
  return {
29265
- target: ts.ScriptTarget.ESNext,
29266
- module: ts.ModuleKind.NodeNext,
29267
- moduleResolution: ts.ModuleResolutionKind.NodeNext,
30207
+ target: ts2.ScriptTarget.ESNext,
30208
+ module: ts2.ModuleKind.NodeNext,
30209
+ moduleResolution: ts2.ModuleResolutionKind.NodeNext,
29268
30210
  allowJs: false,
29269
30211
  declaration: false,
29270
30212
  noEmit: true,
@@ -29289,7 +30231,7 @@ function resolveAlias(symbol, checker) {
29289
30231
  return current;
29290
30232
  }
29291
30233
  function isAlias(symbol) {
29292
- return (symbol.flags & ts.SymbolFlags.Alias) !== 0;
30234
+ return (symbol.flags & ts2.SymbolFlags.Alias) !== 0;
29293
30235
  }
29294
30236
  function pickPrimaryDeclaration(symbol) {
29295
30237
  const declarations = symbol.getDeclarations();
@@ -29297,53 +30239,53 @@ function pickPrimaryDeclaration(symbol) {
29297
30239
  return void 0;
29298
30240
  }
29299
30241
  const concrete = declarations.find(
29300
- (d) => !ts.isExportSpecifier(d) && !ts.isExportAssignment(d) && !ts.isExportDeclaration(d)
30242
+ (d) => !ts2.isExportSpecifier(d) && !ts2.isExportAssignment(d) && !ts2.isExportDeclaration(d)
29301
30243
  );
29302
30244
  return concrete ?? declarations[0];
29303
30245
  }
29304
30246
  function classifyDeclaration(declaration) {
29305
- if (ts.isClassDeclaration(declaration)) {
30247
+ if (ts2.isClassDeclaration(declaration)) {
29306
30248
  return TsDocCoverageKind.Class;
29307
30249
  }
29308
- if (ts.isInterfaceDeclaration(declaration)) {
30250
+ if (ts2.isInterfaceDeclaration(declaration)) {
29309
30251
  return TsDocCoverageKind.Interface;
29310
30252
  }
29311
- if (ts.isTypeAliasDeclaration(declaration)) {
30253
+ if (ts2.isTypeAliasDeclaration(declaration)) {
29312
30254
  return TsDocCoverageKind.TypeAlias;
29313
30255
  }
29314
- if (ts.isEnumDeclaration(declaration)) {
30256
+ if (ts2.isEnumDeclaration(declaration)) {
29315
30257
  return TsDocCoverageKind.Enum;
29316
30258
  }
29317
- if (ts.isFunctionDeclaration(declaration) || ts.isMethodDeclaration(declaration)) {
30259
+ if (ts2.isFunctionDeclaration(declaration) || ts2.isMethodDeclaration(declaration)) {
29318
30260
  return TsDocCoverageKind.Function;
29319
30261
  }
29320
- if (ts.isVariableDeclaration(declaration) || ts.isVariableStatement(declaration)) {
30262
+ if (ts2.isVariableDeclaration(declaration) || ts2.isVariableStatement(declaration)) {
29321
30263
  return TsDocCoverageKind.Variable;
29322
30264
  }
29323
- if (ts.isModuleDeclaration(declaration)) {
30265
+ if (ts2.isModuleDeclaration(declaration)) {
29324
30266
  return TsDocCoverageKind.Module;
29325
30267
  }
29326
- if (ts.isExportAssignment(declaration)) {
30268
+ if (ts2.isExportAssignment(declaration)) {
29327
30269
  return TsDocCoverageKind.Default;
29328
30270
  }
29329
30271
  return TsDocCoverageKind.Other;
29330
30272
  }
29331
30273
  function resolveLocation(declaration) {
29332
- const target = ts.isVariableDeclaration(declaration) ? declaration.parent.parent ?? declaration : declaration;
30274
+ const target = ts2.isVariableDeclaration(declaration) ? declaration.parent.parent ?? declaration : declaration;
29333
30275
  const source = target.getSourceFile();
29334
30276
  const { line } = source.getLineAndCharacterOfPosition(target.getStart());
29335
30277
  return { file: source.fileName, line: line + 1 };
29336
30278
  }
29337
30279
  function parseTsDocFor(declaration, parser) {
29338
- const target = ts.isVariableDeclaration(declaration) ? declaration.parent.parent ?? declaration : declaration;
30280
+ const target = ts2.isVariableDeclaration(declaration) ? declaration.parent.parent ?? declaration : declaration;
29339
30281
  const sourceText = target.getSourceFile().getFullText();
29340
- const ranges = ts.getLeadingCommentRanges(sourceText, target.getFullStart());
30282
+ const ranges = ts2.getLeadingCommentRanges(sourceText, target.getFullStart());
29341
30283
  if (!ranges || ranges.length === 0) {
29342
30284
  return void 0;
29343
30285
  }
29344
30286
  for (let i = ranges.length - 1; i >= 0; i--) {
29345
30287
  const range = ranges[i];
29346
- if (range.kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
30288
+ if (range.kind !== ts2.SyntaxKind.MultiLineCommentTrivia) {
29347
30289
  continue;
29348
30290
  }
29349
30291
  const text = sourceText.slice(range.pos, range.end);
@@ -29566,14 +30508,14 @@ var LAYOUT_ROOT_BY_PROJECT_TYPE = {
29566
30508
  };
29567
30509
  function validateMonorepoLayout(root) {
29568
30510
  const violations = [];
29569
- const rootOutdir = toPosix2(root.outdir);
30511
+ const rootOutdir = toPosix3(root.outdir);
29570
30512
  for (const sub of root.subprojects) {
29571
30513
  const className = sub.constructor.name;
29572
30514
  const expectedRoot = expectedRootFor(sub, className);
29573
30515
  if (expectedRoot === void 0) {
29574
30516
  continue;
29575
30517
  }
29576
- const relOutdir = relativeOutdir(rootOutdir, toPosix2(sub.outdir));
30518
+ const relOutdir = relativeOutdir(rootOutdir, toPosix3(sub.outdir));
29577
30519
  if (!outdirMatchesRoot(relOutdir, expectedRoot)) {
29578
30520
  violations.push({
29579
30521
  projectName: sub.name,
@@ -29632,7 +30574,7 @@ function outdirMatchesRoot(relOutdir, expectedRoot) {
29632
30574
  }
29633
30575
  return segments.length >= 2;
29634
30576
  }
29635
- function toPosix2(p) {
30577
+ function toPosix3(p) {
29636
30578
  return p.replace(/\\/g, "/");
29637
30579
  }
29638
30580
  function relativeOutdir(rootOutdir, subOutdir) {
@@ -29712,8 +30654,8 @@ var ResetTask = class _ResetTask extends import_projen14.Component {
29712
30654
  const resetTask = this.project.tasks.addTask(this.taskName, {
29713
30655
  description: "Delete build artifacts specified by pathsToRemove option, or artifactsDirectory if pathsToRemove is empty"
29714
30656
  });
29715
- this.pathsToRemove.forEach((path4) => {
29716
- resetTask.exec(`[ -e "${path4}" ] && rm -rf ${path4} || true`);
30657
+ this.pathsToRemove.forEach((path7) => {
30658
+ resetTask.exec(`[ -e "${path7}" ] && rm -rf ${path7} || true`);
29717
30659
  });
29718
30660
  const rootHasTurbo = TurboRepo.of(this.project.root) !== void 0;
29719
30661
  const isSubproject = this.project !== this.project.root;
@@ -31652,11 +32594,15 @@ var TypeScriptConfig = class extends import_projen23.Component {
31652
32594
  AGENT_RULE_SCOPE,
31653
32595
  AGENT_TIER_ROLES,
31654
32596
  AGENT_TIER_VALUES,
32597
+ AUDIT_CATEGORY_ORDER,
31655
32598
  AgentConfig,
31656
32599
  ApiExtractor,
31657
32600
  AstroConfig,
31658
32601
  AstroOutput,
31659
32602
  AstroProject,
32603
+ AuditCategory,
32604
+ AuditMode,
32605
+ AuditSeverity,
31660
32606
  AwsCdkProject,
31661
32607
  AwsDeployWorkflow,
31662
32608
  AwsDeploymentConfig,
@@ -31672,6 +32618,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
31672
32618
  DEFAULT_API_EXTRACTOR_ENTRY_POINT,
31673
32619
  DEFAULT_API_EXTRACTOR_REPORT_FILENAME,
31674
32620
  DEFAULT_API_EXTRACTOR_REPORT_FOLDER,
32621
+ DEFAULT_AUDIT_REPORT_DIR,
31675
32622
  DEFAULT_DECOMPOSITION_TEMPLATE,
31676
32623
  DEFAULT_DELEGATE_TO_PR_REVIEWER,
31677
32624
  DEFAULT_DISPATCH_MODEL,
@@ -31695,6 +32642,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
31695
32642
  DEFAULT_PROGRESS_FILES_STATE_DIR,
31696
32643
  DEFAULT_REQUIRE_LINKED_ISSUE,
31697
32644
  DEFAULT_REQUIRE_PRODUCT_CONTEXT,
32645
+ DEFAULT_SAMPLE_COMPILER_OPTIONS,
31698
32646
  DEFAULT_SCHEDULED_TASKS_ROOT,
31699
32647
  DEFAULT_SCHEDULED_TASK_ENTRIES,
31700
32648
  DEFAULT_SHARED_EDITING_CONFLICT_STRATEGY,
@@ -31718,6 +32666,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
31718
32666
  DEFAULT_WORKFLOW_DIAGRAMS_ENABLED,
31719
32667
  DEFAULT_WORKFLOW_DIAGRAMS_PATH,
31720
32668
  DEFAULT_WORKFLOW_DIAGRAMS_REQUIRE_UPDATE,
32669
+ DOCS_SYNC_AUDIT_SCHEMA_VERSION,
31721
32670
  JsiiFaker,
31722
32671
  LAYOUT_ENFORCEMENT,
31723
32672
  LAYOUT_ROOT_BY_PROJECT_TYPE,
@@ -31740,6 +32689,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
31740
32689
  SCOPE_CLASS_VALUES,
31741
32690
  SHARED_EDITING_CONFLICT_STRATEGY_VALUES,
31742
32691
  STARLIGHT_ROLE,
32692
+ SampleLang,
31743
32693
  StarlightProject,
31744
32694
  TestRunner,
31745
32695
  TsDocCoverageKind,
@@ -31758,6 +32708,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
31758
32708
  addSyncLabelsWorkflow,
31759
32709
  agendaBundle,
31760
32710
  analyzeTsDocCoverage,
32711
+ auditReportJsonSchema,
31761
32712
  awsCdkBundle,
31762
32713
  baseBundle,
31763
32714
  bcmWriterBundle,
@@ -31774,6 +32725,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
31774
32725
  buildOrchestratorConventionsContent,
31775
32726
  buildPeopleProfileBundle,
31776
32727
  buildRegulatoryResearchBundle,
32728
+ buildReport,
31777
32729
  buildRequirementsAnalystBundle,
31778
32730
  buildRequirementsReviewerBundle,
31779
32731
  buildRequirementsWriterBundle,
@@ -31782,14 +32734,18 @@ var TypeScriptConfig = class extends import_projen23.Component {
31782
32734
  buildStandardsResearchBundle,
31783
32735
  buildUnblockDependentsProcedure,
31784
32736
  businessModelsBundle,
32737
+ checkDocSamplesProcedure,
31785
32738
  checkLinksProcedure,
31786
32739
  classifyIssueScope,
31787
32740
  classifyRun,
31788
32741
  companyProfileBundle,
32742
+ compileFencedSamples,
31789
32743
  customerProfileBundle,
31790
32744
  docsSyncBundle,
32745
+ emptyCategoryBuckets,
31791
32746
  extractApiProcedure,
31792
32747
  extractDocReferences,
32748
+ extractFencedSamples,
31793
32749
  formatLayoutViolation,
31794
32750
  formatStarlightSingletonViolation,
31795
32751
  getLatestEligibleVersion,
@@ -31800,12 +32756,14 @@ var TypeScriptConfig = class extends import_projen23.Component {
31800
32756
  meetingAnalysisBundle,
31801
32757
  orchestratorBundle,
31802
32758
  peopleProfileBundle,
32759
+ persistAuditReport,
31803
32760
  pnpmBundle,
31804
32761
  prReviewBundle,
31805
32762
  projenBundle,
31806
32763
  regulatoryResearchBundle,
31807
32764
  renderAgentTierCaseStatement,
31808
32765
  renderAgentTierSection,
32766
+ renderCheckDocSamplesProcedure,
31809
32767
  renderCheckLinksProcedure,
31810
32768
  renderCustomDocSectionBlock,
31811
32769
  renderCustomDocSections,
@@ -31865,6 +32823,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
31865
32823
  resolveTypeScriptProjectOutdir,
31866
32824
  resolveUnblockDependents,
31867
32825
  resolveWorkflowDiagrams,
32826
+ runScan,
31868
32827
  slackBundle,
31869
32828
  softwareProfileBundle,
31870
32829
  standardsResearchBundle,