@orkestrel/scaffold 0.0.103 → 0.0.104

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/agents/skills/orkestrel-dispatch/scripts/helpers.js +84 -1
  2. package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +21 -6
  3. package/dist/agents/skills/orkestrel-harden/scripts/titles.js +338 -0
  4. package/dist/agents/skills/orkestrel-publish/scripts/swap.js +3 -39
  5. package/dist/agents/skills/orkestrel-publish/scripts/wave.js +433 -47
  6. package/dist/agents/skills/orkestrel-publish/scripts/window.js +2 -1
  7. package/dist/bin/main.js +16 -9
  8. package/dist/bin/main.js.map +1 -1
  9. package/dist/host/agents/orchestration.md +3 -3
  10. package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +2 -2
  11. package/dist/host/agents/skills/enterprise-bootstrap/references/inspection.md +1 -1
  12. package/dist/host/agents/skills/orkestrel-build/SKILL.md +2 -2
  13. package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +2 -2
  14. package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +1 -1
  15. package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +3 -3
  16. package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +10 -10
  17. package/dist/host/agents/skills/orkestrel-dispatch/references/launch.md +1 -0
  18. package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +100 -1
  19. package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +27 -6
  20. package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +4 -4
  21. package/dist/host/agents/skills/orkestrel-falsify/agents/openai.yaml +1 -1
  22. package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +8 -7
  23. package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +6 -6
  24. package/dist/host/agents/skills/orkestrel-harden/SKILL.md +6 -1
  25. package/dist/host/agents/skills/orkestrel-harden/references/bindings.md +1700 -0
  26. package/dist/host/agents/skills/orkestrel-harden/references/contract.md +2 -2
  27. package/dist/host/agents/skills/orkestrel-harden/references/equivalence.md +48 -0
  28. package/dist/host/agents/skills/orkestrel-harden/references/hardening.md +4 -2
  29. package/dist/host/agents/skills/orkestrel-harden/scripts/titles.ts +425 -0
  30. package/dist/host/agents/skills/orkestrel-journey/SKILL.md +2 -2
  31. package/dist/host/agents/skills/orkestrel-journey/references/captures.md +9 -8
  32. package/dist/host/agents/skills/orkestrel-polish/SKILL.md +3 -3
  33. package/dist/host/agents/skills/orkestrel-publish/SKILL.md +2 -2
  34. package/dist/host/agents/skills/orkestrel-publish/references/release.md +1 -0
  35. package/dist/host/agents/skills/orkestrel-publish/references/wave.md +56 -13
  36. package/dist/host/agents/skills/orkestrel-publish/references/window.md +6 -6
  37. package/dist/host/agents/skills/orkestrel-publish/scripts/swap.ts +5 -49
  38. package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +646 -49
  39. package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +2 -1
  40. package/dist/host/agents/transports/codex.md +1 -1
  41. package/dist/host/claude/agents/orkestrel.md +54 -53
  42. package/dist/host/claude/agents/reviewer.md +4 -4
  43. package/dist/host/claude/rules/documentation.md +2 -1
  44. package/dist/host/claude/rules/patterns.md +1 -1
  45. package/dist/host/claude/rules/quality.md +2 -2
  46. package/dist/host/claude/rules/styles.md +1 -1
  47. package/dist/host/claude/rules/tests.md +34 -8
  48. package/dist/host/claude/rules/typescript.md +29 -0
  49. package/dist/host/claude/rules/workspace.md +32 -22
  50. package/dist/host/claude/rules/writing.md +34 -26
  51. package/dist/host/claude/settings.json +2 -0
  52. package/dist/host/claude/skills/orkestrel-debrief/SKILL.md +1 -1
  53. package/dist/host/claude/skills/orkestrel-falsify/SKILL.md +1 -1
  54. package/dist/host/codex/agents/analyst.toml +3 -3
  55. package/dist/host/codex/agents/reviewer.toml +4 -4
  56. package/dist/host/configs/policy.ts +13 -2
  57. package/dist/host/dotfiles/editorconfig +0 -1
  58. package/dist/host/dotfiles/gitattributes +0 -1
  59. package/dist/host/dotfiles/gitignore +0 -1
  60. package/dist/host/dotfiles/oxlintrc.json +24 -0
  61. package/dist/host/guides/agent.md +1638 -598
  62. package/dist/host/guides/budget.md +89 -29
  63. package/dist/host/guides/form.md +477 -91
  64. package/dist/host/guides/mcp.md +14 -2
  65. package/dist/host/guides/ollama.md +97 -73
  66. package/dist/host/guides/probe.md +1 -1
  67. package/dist/host/guides/scaffold.md +158 -101
  68. package/dist/host/guides/study.md +2635 -0
  69. package/dist/host/guides/table.md +225 -15
  70. package/dist/host/guides/terminal.md +22 -20
  71. package/dist/host/guides/test.md +689 -255
  72. package/dist/host/manifest.json +87 -63
  73. package/dist/host/tests/config.test.ts +136 -82
  74. package/dist/host/tests/policy.test.ts +39 -1
  75. package/dist/host/tests/setupPolicy.ts +86 -28
  76. package/dist/src/core/index.cjs +1387 -611
  77. package/dist/src/core/index.cjs.map +1 -1
  78. package/dist/src/core/index.d.cts +35 -20
  79. package/dist/src/core/index.d.ts +35 -20
  80. package/dist/src/core/index.js +1385 -612
  81. package/dist/src/core/index.js.map +1 -1
  82. package/dist/src/server/index.cjs +12 -12
  83. package/dist/src/server/index.cjs.map +1 -1
  84. package/dist/src/server/index.d.cts +12 -12
  85. package/dist/src/server/index.d.ts +12 -12
  86. package/dist/src/server/index.js +12 -12
  87. package/dist/src/server/index.js.map +1 -1
  88. package/package.json +4 -4
@@ -4,7 +4,7 @@ let _orkestrel_template = require("@orkestrel/template");
4
4
  let _orkestrel_emitter = require("@orkestrel/emitter");
5
5
  var package_default = {
6
6
  name: "@orkestrel/scaffold",
7
- version: "0.0.103",
7
+ version: "0.0.104",
8
8
  description: "Scaffold workspaces with commands: new, audit, repair, catalog, and overwrite.",
9
9
  keywords: [
10
10
  "audit",
@@ -104,11 +104,11 @@ var package_default = {
104
104
  },
105
105
  devDependencies: {
106
106
  "@microsoft/api-extractor": "^7.59.4",
107
- "@orkestrel/browser": "^0.0.28",
107
+ "@orkestrel/browser": "^0.0.29",
108
108
  "@orkestrel/guide": "^0.0.24",
109
109
  "@orkestrel/html": "^0.0.12",
110
- "@orkestrel/probe": "^0.0.23",
111
- "@orkestrel/test": "^0.0.27",
110
+ "@orkestrel/probe": "^0.0.24",
111
+ "@orkestrel/test": "^0.0.28",
112
112
  "@types/node": "^26.6.4",
113
113
  "@vitest/browser-playwright": "^4.1.11",
114
114
  "oxfmt": "^0.72.0",
@@ -250,6 +250,8 @@ var APP_MATRIX = Object.freeze({
250
250
  var BIN_CONFIGS = Object.freeze(["configs/src/vite.bin.config.ts", "configs/src/tsconfig.bin.json"]);
251
251
  /** Names the executable entry whose presence makes a workspace `bin`. */
252
252
  var BIN_ENTRY_PATH = "src/bin/main.ts";
253
+ /** Names the built executable a bin workspace's manifest command runs. */
254
+ var BIN_OUTPUT_PATH = "dist/bin/main.js";
253
255
  /**
254
256
  * Lists the paths a target receives from the vendored data root, frozen.
255
257
  *
@@ -478,6 +480,8 @@ var GLOBAL_SETUP_PATH = "tests/setupGlobal.ts";
478
480
  var GUIDES_TEST_PATH = "tests/guides.test.ts";
479
481
  /** Names the generated packed-package proof every publishing workspace is planned at. */
480
482
  var DISTRIBUTION_TEST_PATH = "tests/distribution.test.ts";
483
+ /** Names the content-owned harness imported by the generated distribution proof. */
484
+ var DISTRIBUTION_SETUP_PATH = "tests/setupDistribution.ts";
481
485
  /**
482
486
  * Names the `prepublishOnly` row that runs the packed-package proof against a real registry.
483
487
  *
@@ -496,6 +500,8 @@ var INTEGRATION_TEST_PATH = "tests/integration.test.ts";
496
500
  var MANIFEST_PATH = "package.json";
497
501
  /** Names the official-tooling drift proof whose presence makes a workspace `conformance`. */
498
502
  var CONFORMANCE_TEST_PATH = "tests/conformance.test.ts";
503
+ /** Names the real-tree proof whose presence makes a workspace `tree`. */
504
+ var TREE_TEST_PATH = "tests/tree.test.ts";
499
505
  /** Names the live-service readiness module whose presence makes a workspace `service`. */
500
506
  var SERVICE_SETUP_PATH = "tests/setupService.ts";
501
507
  /**
@@ -527,8 +533,8 @@ var NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
527
533
  * @remarks
528
534
  * A dependency name reaches a path, because a workspace's guide mirror is
529
535
  * derived from it. Fixing the scope and forbidding everything but the bare name
530
- * after it is what stops a hand-built name from escaping the directory the
531
- * mirror belongs in.
536
+ * after it is what stops a hand-built name from resolving outside the directory
537
+ * the mirror belongs in.
532
538
  */
533
539
  var DEPENDENCY_NAME_PATTERN = /^@orkestrel\/[a-z][a-z0-9-]*$/;
534
540
  /**
@@ -942,7 +948,13 @@ function isNamedPlugin(plugin: PluginOption): plugin is { name: string } {
942
948
  name: { label: name, color: 'magenta' },
943
949
  root: resolveWorkspacePath('.'),
944
950
  isolate: false,
945
- setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts', './tests/setupStyles.ts'],
951
+ setupFiles: [
952
+ './tests/setup.ts',
953
+ './tests/setupBrowser.ts',
954
+ ...(existsSync(resolveWorkspacePath('tests/setupStyles.ts'))
955
+ ? ['./tests/setupStyles.ts']
956
+ : []),
957
+ ],
946
958
  browser: {
947
959
  enabled: true,
948
960
  provider: playwright(browserOptions),
@@ -1462,6 +1474,24 @@ export function skills(override?: UserConfig): UserConfig {
1462
1474
  }
1463
1475
  return mergeOverride(project, override)
1464
1476
  }
1477
+ `,
1478
+ tree: `// The laws this package states about its own real tree.
1479
+ // Standalone Node proof; reads the tree without a build, install, or service.
1480
+ export function tree(override?: UserConfig): UserConfig {
1481
+ const project: UserConfig = {
1482
+ resolve,
1483
+ test: {
1484
+ name: { label: 'tree', color: 'magenta' },
1485
+ include: ['${TREE_TEST_PATH}'],
1486
+ setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
1487
+ pool: 'threads',
1488
+ isolate: false,
1489
+ environment: 'node',
1490
+ browser: { enabled: false },
1491
+ },
1492
+ }
1493
+ return mergeOverride(project, override)
1494
+ }
1465
1495
  `,
1466
1496
  conformance: `// Where this package drifts from the official tooling it stays compatible with.
1467
1497
  // The subject is this package, so the proof is hermetic and stays in \`npm test\`.
@@ -2226,11 +2256,11 @@ export function resolveSystemBrowser(
2226
2256
  * verified system channel, then the platform default channel. An operator override outranks
2227
2257
  * discovery and is returned exactly as given: none of those environment values is checked
2228
2258
  * against the filesystem, because verifying an override would defeat the override. The pinned
2229
- * managed revision outranks anything found on the host because it is deterministic. The installed
2230
- * pinned revision returns empty options unless \`PLAYWRIGHT_SCROLLBARS=classic\` is set. Only a
2231
- * discovered system channel is verified before it is named. The platform default is unverified
2232
- * as well and exists only as a last resort: Windows takes \`msedge\`, which ships with the OS and
2233
- * never collides with a foreground Chrome.
2259
+ * managed revision outranks anything found on the host because it is deterministic. Every resolved
2260
+ * managed path names the full Chromium executable so headless launches retain browser permissions.
2261
+ * Only a discovered system channel is verified before it is named. The platform default is
2262
+ * unverified as well and exists only as a last resort: Windows takes \`msedge\`, which ships with the
2263
+ * OS and never collides with a foreground Chrome.
2234
2264
  *
2235
2265
  * Set \`PLAYWRIGHT_SCROLLBARS=classic\` only for runs that measure scrollbar compensation, never
2236
2266
  * for a standing gate. Every Chromium launch in that run omits Playwright's \`--hide-scrollbars\`
@@ -2277,7 +2307,6 @@ export function resolveBrowser(
2277
2307
  }
2278
2308
  const managed = pinned === undefined ? undefined : resolveManagedBrowser(pinned)
2279
2309
  if (managed !== undefined) {
2280
- if (managed === pinned) return scrollbars === 'classic' ? { launchOptions: launch } : {}
2281
2310
  return { launchOptions: { executablePath: managed, ...launch } }
2282
2311
  }
2283
2312
  const bundled = resolveBundledBrowser(platform, root)
@@ -2451,8 +2480,8 @@ declare module 'vitest' {
2451
2480
  }
2452
2481
  `,
2453
2482
  sheet: `import sheet from '{{root}}dist/src/{{name}}/index.css?raw'
2483
+ import { adoptSheet, readLayerNames } from '@orkestrel/test/browser'
2454
2484
  import { describe, expect, it } from 'vitest'
2455
- import { adoptSheet, readLayerNames } from '{{setup}}'
2456
2485
 
2457
2486
  describe('{{name}} entry', () => {
2458
2487
  it('opens with the declared cascade order', () => {
@@ -2476,120 +2505,8 @@ describe('{{name}} entry', () => {
2476
2505
  })
2477
2506
  `,
2478
2507
  styles: Object.freeze({
2479
- module: `/** Describes an adopted stylesheet and its idempotent release operation. */
2480
- export interface SheetAdoption {
2481
- readonly sheet: CSSStyleSheet
2482
- release(): void
2483
- }
2484
-
2485
- /**
2486
- * Adopts CSS text into the document with an idempotent release operation.
2487
- * @param text - The compiled sheet text.
2488
- * @returns The adopted sheet and its release operation.
2489
- * @example
2490
- * \`\`\`ts
2491
- * const adopted = adoptSheet('.sample { color: red }')
2492
- * adopted.release()
2493
- * \`\`\`
2494
- */
2495
- export function adoptSheet(text: string): SheetAdoption {
2496
- const sheet = new CSSStyleSheet()
2497
- sheet.replaceSync(text)
2498
- document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]
2499
- return {
2500
- sheet,
2501
- release: () => {
2502
- document.adoptedStyleSheets = document.adoptedStyleSheets.filter(
2503
- (candidate) => candidate !== sheet,
2504
- )
2505
- },
2506
- }
2507
- }
2508
-
2509
- /**
2510
- * Reads layer statements and blocks in declaration order, including repeated names.
2511
- * @param source - The parsed sheet, or a grouping rule inside it.
2512
- * @param layer - The qualified name of the layer that encloses \`source\`, when one does.
2513
- * @returns Qualified layer names, with an empty name for an anonymous layer.
2514
- * @example
2515
- * \`\`\`ts
2516
- * readLayerNames(new CSSStyleSheet()) // []
2517
- * \`\`\`
2518
- */
2519
- export function readLayerNames(
2520
- source: CSSStyleSheet | CSSGroupingRule,
2521
- layer?: string,
2522
- ): readonly string[] {
2523
- return Array.from(source.cssRules).flatMap((rule) => [
2524
- ...(rule instanceof CSSLayerStatementRule
2525
- ? rule.nameList
2526
- : rule instanceof CSSLayerBlockRule
2527
- ? [rule.name]
2528
- : []
2529
- ).map((name) => (layer === undefined ? name : layer + '.' + name)),
2530
- ...(rule instanceof CSSGroupingRule
2531
- ? readLayerNames(
2532
- rule,
2533
- rule instanceof CSSLayerBlockRule
2534
- ? layer === undefined
2535
- ? rule.name
2536
- : layer + '.' + rule.name
2537
- : layer,
2538
- )
2539
- : []),
2540
- ])
2541
- }
2542
- `,
2543
- proof: `import type { SheetAdoption } from './setupStyles.js'
2544
- import { describe, expect, it } from 'vitest'
2545
- import { adoptSheet, readLayerNames } from './setupStyles.js'
2546
-
2547
- describe('CSSOM instruments', () => {
2548
- it('adopts and releases only its own sheet, including repeated release', () => {
2549
- const previous = [...document.adoptedStyleSheets]
2550
- const first: SheetAdoption = adoptSheet('.sample { color: red }')
2551
- try {
2552
- const second = adoptSheet('.other { display: block }')
2553
- try {
2554
- expect(document.adoptedStyleSheets).toEqual([...previous, first.sheet, second.sheet])
2555
- expect(first.sheet.cssRules.length).toBe(1)
2556
- first.release()
2557
- first.release()
2558
- expect(document.adoptedStyleSheets).toEqual([...previous, second.sheet])
2559
- } finally {
2560
- second.release()
2561
- }
2562
- } finally {
2563
- first.release()
2564
- }
2565
- expect(document.adoptedStyleSheets).toEqual(previous)
2566
- })
2567
-
2568
- it('reads statements, blocks, nested conditions, and anonymous layers in order', () => {
2569
- const adopted = adoptSheet(
2570
- '@layer first, second; @layer first { @media all { @layer nested {} } } @layer {}',
2571
- )
2572
- try {
2573
- expect(readLayerNames(adopted.sheet)).toEqual([
2574
- 'first',
2575
- 'second',
2576
- 'first',
2577
- 'first.nested',
2578
- '',
2579
- ])
2580
- } finally {
2581
- adopted.release()
2582
- }
2583
- })
2584
-
2585
- it('returns no layer names for an empty sheet or an unlayered rule', () => {
2586
- const sheet = new CSSStyleSheet()
2587
- expect(readLayerNames(sheet)).toEqual([])
2588
- sheet.replaceSync('.sample { color: red }')
2589
- expect(readLayerNames(sheet)).toEqual([])
2590
- })
2591
- })
2592
- `
2508
+ module: "",
2509
+ proof: ""
2593
2510
  }),
2594
2511
  setup: "",
2595
2512
  global: Object.freeze({
@@ -2625,13 +2542,7 @@ describe('bin entry', () => {
2625
2542
  })
2626
2543
  `,
2627
2544
  distribution: Object.freeze({
2628
- proof: `// The artifact a consumer installs, measured rather than described. This workspace
2629
- // is packed and installed into a throwaway consumer, and every following claim is read
2630
- // off that installed tree: the exports map it publishes, the declarations it ships,
2631
- // and the module objects a real runtime hands a consumer. Nothing here names this
2632
- // package, one of its exports, or how many there are, so the proof stays true as
2633
- // the published surface moves.
2634
- {{types}}import type { SpawnSyncReturns } from 'node:child_process'
2545
+ module: `{{types}}import type { SpawnSyncReturns } from 'node:child_process'
2635
2546
  import type { TestContext } from 'vitest'
2636
2547
  import { spawnSync } from 'node:child_process'
2637
2548
  import {
@@ -2646,67 +2557,126 @@ import {
2646
2557
  } from 'node:fs'
2647
2558
  {{transport}}import { createRequire } from 'node:module'
2648
2559
  import { tmpdir } from 'node:os'
2649
- import { dirname, join, resolve } from 'node:path'
2650
- import { fileURLToPath } from 'node:url'
2651
- {{launcher}}import { afterAll, beforeAll, describe, expect, it } from 'vitest'
2560
+ import { dirname, join, relative as relativePath, resolve, sep } from 'node:path'
2561
+ import { fileURLToPath, pathToFileURL } from 'node:url'
2562
+ import { isDeepStrictEqual } from 'node:util'
2563
+ import { parseSync } from 'vite'
2564
+ {{launcher}}
2565
+ /** Defines the lifecycle and installed consumer read by a distribution proof. */
2566
+ export interface DistributionSuiteInterface {
2567
+ readonly scratch: string
2568
+ start(): void
2569
+ read(context: TestContext): DistributionStage
2570
+ destroy(): void
2571
+ }
2652
2572
 
2653
- const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
2654
- const NPM = process.platform === 'win32' ? 'npm.cmd' : 'npm'
2573
+ /** Holds the observed and required values for one distribution assertion. */
2574
+ export interface DistributionObservation {
2575
+ readonly actual: unknown
2576
+ readonly expected: unknown
2577
+ }
2578
+
2579
+ /** Defines one independently registered distribution observation. */
2580
+ export interface DistributionCase {
2581
+ readonly label: string
2582
+ readonly observe: (
2583
+ context: TestContext,
2584
+ ) => DistributionObservation | Promise<DistributionObservation>
2585
+ }
2586
+
2587
+ /** Holds the installed export map's classified publications. */
2588
+ export interface DistributionClassification {
2589
+ readonly entries: readonly DistributionEntry[]
2590
+ readonly subpaths: readonly string[]
2591
+ readonly undeclared: readonly string[]
2592
+ readonly excluded: readonly string[]
2593
+ readonly targets: readonly string[]
2594
+ }
2595
+
2596
+ /** Names the workspace whose packed artifact the proof consumes. */
2597
+ export const DISTRIBUTION_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
2598
+ /** Names the npm executable on the running host. */
2599
+ export const DISTRIBUTION_NPM = process.platform === 'win32' ? 'npm.cmd' : 'npm'
2655
2600
  // The compiler this workspace installs, run as a command rather than called in
2656
2601
  // process: the command and its plain-text diagnostics are the same across the
2657
2602
  // compiler majors this toolchain supports, and its in-process API is not. It is
2658
2603
  // resolved from the workspace under proof, so a consumer of the packed artifact is
2659
2604
  // checked by the same compiler that workspace's own \`check\` script runs.
2660
- const TSC = createRequire(join(ROOT, 'package.json')).resolve('typescript/bin/tsc')
2605
+ /** Names the compiler installed by the workspace under proof. */
2606
+ export const DISTRIBUTION_COMPILER = createRequire(join(DISTRIBUTION_ROOT, 'package.json')).resolve(
2607
+ 'typescript/bin/tsc',
2608
+ )
2661
2609
  // Windows needs a shell to launch a \`.cmd\`: Node refuses one directly since the
2662
2610
  // batch-argument hardening, and \`spawnSync\` returns \`EINVAL\` with a null status
2663
2611
  // rather than an exit code a caller can read. Every following argument is a literal or
2664
2612
  // a path this file built, so the shell has nothing to escape.
2665
- const SHELL = process.platform === 'win32'
2613
+ /** Selects the Windows command-shell route required by the npm shim. */
2614
+ export const DISTRIBUTION_SHELL = process.platform === 'win32'
2666
2615
  // \`prepublishOnly\` runs this proof as \`npm run test:distribution -- --mode release\`,
2667
2616
  // and the root configuration's project factories carry that mode into this project.
2668
2617
  // Release is the publish gate, so evidence it cannot obtain fails there and skips
2669
2618
  // everywhere else: a gate that passes on missing evidence proves nothing.
2670
- const RELEASE = import.meta.env.MODE === 'release'
2619
+ /** Indicates whether missing prerequisites must fail the publish gate. */
2620
+ export const DISTRIBUTION_RELEASE = import.meta.env?.MODE === 'release'
2671
2621
  // The built output directory convention a browser face may publish from. Every
2672
2622
  // selection reads this prefix off the export target and never off the subpath name. A
2673
2623
  // workspace whose only published face is the browser one publishes that face at the
2674
2624
  // root subpath, so a rule keyed on the subpath name drives a browser bundle through
2675
2625
  // Node and the miss is silent.
2676
- const BROWSER_OUTPUT = './dist/src/browser/'
2677
- const ABSENT_SUBPATH = '/no-subpath-is-published-under-this-name'
2626
+ /** Names the conventional output prefix for a browser publication. */
2627
+ export const DISTRIBUTION_BROWSER_OUTPUT = './dist/src/browser/'
2628
+ /** Names the unpublished subpath used as a resolution control. */
2629
+ export const DISTRIBUTION_ABSENT_SUBPATH = '/no-subpath-is-published-under-this-name'
2678
2630
  // A compiler diagnostic that says where it is: the path relative to the directory
2679
2631
  // the compiler ran in, the 1-based line and column, the code, and the message. The
2680
2632
  // diagnostics are the verdict rather than the exit code, which differs between the
2681
2633
  // compiler majors this toolchain supports, so a reported line matching nothing here
2682
2634
  // came from something other than a check of a consumer module.
2683
- const DIAGNOSTIC_PATTERN = /^(.+?)\\(\\d+,\\d+\\): error TS\\d+: /u
2684
- const PING = ['ping', '--fetch-retries=0', '--fetch-timeout=5000', '--loglevel=silent']
2685
- const ESM_DRIVER = 'drive.mjs'
2686
- const CJS_DRIVER = 'drive.cjs'
2687
- const CONSUMER_MANIFEST = \`{ "name": "distribution-consumer", "private": true, "type": "module" }\\n\`
2688
- const ESM_DRIVER_SOURCE = \`const entry = await import(process.argv[2])
2635
+ /** Matches the location prefix of a consumer compiler diagnostic. */
2636
+ export const DISTRIBUTION_DIAGNOSTIC_PATTERN = /^(.+?)\\(\\d+,\\d+\\): error TS\\d+: /u
2637
+ /** Lists the bounded registry-readiness command arguments. */
2638
+ export const DISTRIBUTION_PING = Object.freeze([
2639
+ 'ping',
2640
+ '--fetch-retries=0',
2641
+ '--fetch-timeout=5000',
2642
+ '--loglevel=silent',
2643
+ ])
2644
+ /** Names the consumer entry that imports an installed module. */
2645
+ export const DISTRIBUTION_ESM_DRIVER = 'drive.mjs'
2646
+ /** Names the consumer entry that requires an installed module. */
2647
+ export const DISTRIBUTION_CJS_DRIVER = 'drive.cjs'
2648
+ /** Defines the isolated consumer package manifest. */
2649
+ export const DISTRIBUTION_CONSUMER_MANIFEST =
2650
+ '{ "name": "distribution-consumer", "private": true, "type": "module" }\\n'
2651
+ /** Reads the names exported by an installed ESM entry. */
2652
+ export const DISTRIBUTION_ESM_DRIVER_SOURCE = \`const entry = await import(process.argv[2])
2689
2653
  process.stdout.write(JSON.stringify(Object.keys(entry).sort()))
2690
2654
  \`
2691
- const CJS_DRIVER_SOURCE = \`const entry = require(process.argv[2])
2655
+ /** Reads the names exported by an installed CommonJS entry. */
2656
+ export const DISTRIBUTION_CJS_DRIVER_SOURCE = \`const entry = require(process.argv[2])
2692
2657
  process.stdout.write(JSON.stringify(Object.keys(entry).sort()))
2693
2658
  \`
2694
2659
 
2695
2660
  // The extensions a JavaScript handler loads as modules. Node loads a native addon
2696
2661
  // through its addon handler instead, so that extension is named separately.
2697
- const MODULE_EXTENSIONS = ['.js', '.mjs', '.cjs']
2698
- const ADDON_EXTENSION = '.node'
2662
+ /** Lists extensions loaded as JavaScript modules. */
2663
+ export const DISTRIBUTION_MODULE_EXTENSIONS = Object.freeze(['.js', '.mjs', '.cjs'])
2664
+ /** Names the extension loaded by the native-addon handler. */
2665
+ export const DISTRIBUTION_ADDON_EXTENSION = '.node'
2699
2666
  // The extensions a declaration file carries. A \`require\` condition declares
2700
2667
  // \`.d.cts\` and an ESM-only one \`.d.mts\`, so the \`.d.ts\` spelling alone does not
2701
2668
  // name them.
2702
- const DECLARATION_EXTENSIONS = ['.d.ts', '.d.cts', '.d.mts']
2703
- type Format = 'module' | 'commonjs'
2669
+ /** Lists the supported TypeScript declaration extensions. */
2670
+ export const DISTRIBUTION_DECLARATION_EXTENSIONS = Object.freeze(['.d.ts', '.d.cts', '.d.mts'])
2671
+ /** Names the module format of a typed consumer. */
2672
+ export type DistributionFormat = 'module' | 'commonjs'
2704
2673
 
2705
2674
  // The Node import target is resolved with the conditions that driver supplies. The
2706
2675
  // CommonJS compile probe is selected from its declaration's format, and its runtime
2707
2676
  // drive loads the same subpath through Node's require resolver. Vite's production
2708
2677
  // client build enables its module and browser conditions.
2709
- const RUNTIME_CONDITIONS = Object.freeze({
2678
+ /** Defines the conditions each runtime uses to resolve an entry. */
2679
+ export const DISTRIBUTION_RUNTIME_CONDITIONS = Object.freeze({
2710
2680
  module: Object.freeze(['node-addons', 'node', 'import', 'module-sync']),
2711
2681
  commonjs: Object.freeze(['node-addons', 'node', 'require', 'module-sync']),
2712
2682
  browser: Object.freeze(['module', 'browser', 'production', 'import']),
@@ -2714,24 +2684,28 @@ const RUNTIME_CONDITIONS = Object.freeze({
2714
2684
  // TypeScript's Node resolutions add \`node\` to the format condition. Its bundler
2715
2685
  // resolution does not, so a browser drive compares against the declaration a bundler
2716
2686
  // consumer reads rather than borrowing the Node declaration.
2717
- const BUNDLER_CONDITIONS = Object.freeze({
2718
- module: ['types', 'import'],
2719
- commonjs: ['types', 'require'],
2687
+ /** Defines the declaration conditions used by bundler consumers. */
2688
+ export const DISTRIBUTION_BUNDLER_CONDITIONS = Object.freeze({
2689
+ module: Object.freeze(['types', 'import']),
2690
+ commonjs: Object.freeze(['types', 'require']),
2720
2691
  })
2721
- const DECLARATION_CONDITIONS = Object.freeze({
2722
- module: ['types', 'node', 'import'],
2723
- commonjs: ['types', 'node', 'require'],
2724
- browser: BUNDLER_CONDITIONS.module,
2692
+ /** Defines the declaration conditions paired with each runtime. */
2693
+ export const DISTRIBUTION_DECLARATION_CONDITIONS = Object.freeze({
2694
+ module: Object.freeze(['types', 'node', 'import']),
2695
+ commonjs: Object.freeze(['types', 'node', 'require']),
2696
+ browser: DISTRIBUTION_BUNDLER_CONDITIONS.module,
2725
2697
  })
2726
2698
 
2727
- interface Resolution {
2699
+ /** Describes the compiler options and conditions for one consumer resolution. */
2700
+ export interface DistributionResolution {
2728
2701
  readonly label: string
2729
2702
  readonly resolution: string
2730
2703
  readonly module: string
2731
- readonly conditions: Readonly<Record<Format, readonly string[]>>
2704
+ readonly conditions: Readonly<Record<DistributionFormat, readonly string[]>>
2732
2705
  }
2733
2706
 
2734
- interface TargetResolution {
2707
+ /** Holds the target selected by package condition resolution. */
2708
+ export interface DistributionTargetResult {
2735
2709
  readonly target: string
2736
2710
  }
2737
2711
 
@@ -2740,44 +2714,53 @@ interface TargetResolution {
2740
2714
  // \`require\`-only subpath therefore stays in each CommonJS probe that can resolve it.
2741
2715
  // The option values are the spellings the project file takes, so nothing here needs
2742
2716
  // the compiler's own API to name them.
2743
- const RESOLUTIONS: readonly Resolution[] = [
2717
+ /** Lists the compiler resolutions driven against installed declarations. */
2718
+ export const DISTRIBUTION_RESOLUTIONS: readonly DistributionResolution[] = Object.freeze([
2744
2719
  {
2745
2720
  label: 'node16',
2746
2721
  resolution: 'node16',
2747
2722
  module: 'node16',
2748
- conditions: DECLARATION_CONDITIONS,
2723
+ conditions: DISTRIBUTION_DECLARATION_CONDITIONS,
2749
2724
  },
2750
2725
  {
2751
2726
  label: 'nodenext',
2752
2727
  resolution: 'nodenext',
2753
2728
  module: 'nodenext',
2754
- conditions: DECLARATION_CONDITIONS,
2729
+ conditions: DISTRIBUTION_DECLARATION_CONDITIONS,
2755
2730
  },
2756
2731
  {
2757
2732
  label: 'bundler',
2758
2733
  resolution: 'bundler',
2759
2734
  module: 'esnext',
2760
- conditions: BUNDLER_CONDITIONS,
2735
+ conditions: DISTRIBUTION_BUNDLER_CONDITIONS,
2761
2736
  },
2762
- ]
2737
+ ])
2763
2738
 
2764
2739
  // The driver a bundled consumer reads declarations under. A browser application
2765
2740
  // compiles through a bundler, so the browser drive answers under this one alone,
2766
2741
  // and naming it here is what keeps that selection tied to the driver it selects.
2767
- const BROWSER_DRIVER = RESOLUTIONS.find((candidate) => candidate.label === 'bundler')
2768
- if (BROWSER_DRIVER === undefined) throw new Error("RESOLUTIONS carries no 'bundler' row")
2742
+ /** Selects the compiler resolution used by a browser consumer. */
2743
+ export const DISTRIBUTION_BROWSER_RESOLUTION = DISTRIBUTION_RESOLUTIONS.find(
2744
+ (candidate) => candidate.label === 'bundler',
2745
+ )
2746
+ if (DISTRIBUTION_BROWSER_RESOLUTION === undefined)
2747
+ throw new Error("DISTRIBUTION_RESOLUTIONS carries no 'bundler' row")
2769
2748
 
2770
- const FORMATS: ReadonlyArray<readonly [extension: string, format: Format]> = [
2749
+ /** Pairs consumer source extensions with their module formats. */
2750
+ export const DISTRIBUTION_FORMATS: ReadonlyArray<
2751
+ readonly [extension: string, format: DistributionFormat]
2752
+ > = Object.freeze([
2771
2753
  ['ts', 'module'],
2772
2754
  ['cts', 'commonjs'],
2773
- ]
2755
+ ])
2774
2756
 
2775
2757
  // One published subpath, resolved to what this proof can drive: the specifier a
2776
2758
  // consumer writes, whether the declarations its consumer formats resolve at all,
2777
2759
  // whether the exports map answers the browser condition with a target of its own,
2778
2760
  // whether it answers \`import\` and \`require\` at all, and whether the target that
2779
2761
  // \`require\` answers with is one that a CommonJS consumer loads.
2780
- interface Entry {
2762
+ /** Describes one published subpath and its runtime and declaration capabilities. */
2763
+ export interface DistributionEntry {
2781
2764
  readonly subpath: string
2782
2765
  readonly specifier: string
2783
2766
  readonly mapping: unknown
@@ -2795,29 +2778,48 @@ interface Entry {
2795
2778
  // The installed tree every claim is read from. Every subpath the exports map names
2796
2779
  // lands in exactly one of \`entries\`, \`undeclared\`, and \`excluded\`, so a subpath this
2797
2780
  // proof cannot drive is reported rather than dropped.
2798
- interface Stage {
2781
+ /** Holds the installed consumer and the partition of its published subpaths. */
2782
+ export interface DistributionStage {
2799
2783
  readonly consumer: string
2800
2784
  readonly installed: string
2801
2785
  readonly archives: readonly string[]
2802
- readonly entries: readonly Entry[]
2786
+ readonly entries: readonly DistributionEntry[]
2803
2787
  readonly subpaths: readonly string[]
2804
2788
  readonly undeclared: readonly string[]
2805
2789
  readonly excluded: readonly string[]
2806
2790
  readonly targets: readonly string[]
2807
2791
  }
2808
2792
 
2809
- function isRecord(value: unknown): value is Readonly<Record<string, unknown>> {
2793
+ /**
2794
+ * Checks whether a value is a non-null object other than an array.
2795
+ *
2796
+ * @param value - The value to inspect.
2797
+ * @returns True if the value is a record; false otherwise.
2798
+ */
2799
+ export function isDistributionRecord(value: unknown): value is Readonly<Record<string, unknown>> {
2810
2800
  return typeof value === 'object' && value !== null && !Array.isArray(value)
2811
2801
  }
2812
2802
 
2813
- function isNames(value: unknown): value is readonly string[] {
2803
+ /**
2804
+ * Checks whether a value is an array of strings.
2805
+ *
2806
+ * @param value - The value to inspect.
2807
+ * @returns True if every array member is a string; false otherwise.
2808
+ */
2809
+ export function isDistributionNames(value: unknown): value is readonly string[] {
2814
2810
  return Array.isArray(value) && value.every((name) => typeof name === 'string')
2815
2811
  }
2816
2812
 
2817
2813
  // A fallback list, which is what Node reads an array in an exports entry as. The
2818
2814
  // narrowing is what the following walkers need: \`Array.isArray\` widens an \`unknown\`
2819
2815
  // member to \`any\`, and an entry read that way is not read at all.
2820
- function isList(value: unknown): value is readonly unknown[] {
2816
+ /**
2817
+ * Checks whether a value is a fallback array.
2818
+ *
2819
+ * @param value - The value to inspect.
2820
+ * @returns True if the value is an array; false otherwise.
2821
+ */
2822
+ export function isDistributionList(value: unknown): value is readonly unknown[] {
2821
2823
  return Array.isArray(value)
2822
2824
  }
2823
2825
 
@@ -2825,7 +2827,13 @@ function isList(value: unknown): value is readonly unknown[] {
2825
2827
  // package and a target containing a dot, parent, or node_modules segment during
2826
2828
  // package-target resolution. A later module-resolution failure is not the same
2827
2829
  // thing: an array falls through the former and keeps the latter.
2828
- function isPackageTarget(target: string): boolean {
2830
+ /**
2831
+ * Checks whether a relative package target contains only admitted segments.
2832
+ *
2833
+ * @param target - The package-relative target.
2834
+ * @returns True if the target passes package-target validation; false otherwise.
2835
+ */
2836
+ export function matchesDistributionPackageTarget(target: string): boolean {
2829
2837
  if (!target.startsWith('./')) return false
2830
2838
  const refused = ['.', '..', 'node_modules']
2831
2839
  return target
@@ -2840,59 +2848,113 @@ function isPackageTarget(target: string): boolean {
2840
2848
  })
2841
2849
  }
2842
2850
 
2843
- function readJson(path: string): unknown {
2851
+ /**
2852
+ * Reads and parses a JSON file.
2853
+ *
2854
+ * @param path - The file to read.
2855
+ * @returns The parsed value. Throws when reading or parsing fails.
2856
+ */
2857
+ export function readDistributionJSON(path: string): unknown {
2844
2858
  const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'))
2845
2859
  return parsed
2846
2860
  }
2847
2861
 
2848
- function readManifestName(path: string): string {
2849
- const manifest = readJson(path)
2850
- if (!isRecord(manifest) || typeof manifest.name !== 'string') {
2862
+ /**
2863
+ * Reads the package name from a manifest.
2864
+ *
2865
+ * @param path - The manifest to read.
2866
+ * @returns The package name. Throws when the manifest has no string name.
2867
+ */
2868
+ export function readDistributionManifestName(path: string): string {
2869
+ const manifest = readDistributionJSON(path)
2870
+ if (!isDistributionRecord(manifest) || typeof manifest.name !== 'string') {
2851
2871
  throw new Error(\`The manifest at \${path} declares no package name\`)
2852
2872
  }
2853
2873
  return manifest.name
2854
2874
  }
2855
2875
 
2856
- function writeFile(path: string, content: string): void {
2876
+ /**
2877
+ * Writes a consumer file after creating its parent directory.
2878
+ *
2879
+ * @param path - The file to write.
2880
+ * @param content - The text to write.
2881
+ */
2882
+ export function writeDistributionFile(path: string, content: string): void {
2857
2883
  mkdirSync(dirname(path), { recursive: true })
2858
2884
  writeFileSync(path, content)
2859
2885
  }
2860
2886
 
2861
- function readOutput(result: SpawnSyncReturns<string>): string {
2887
+ /**
2888
+ * Combines the output streams of a completed command.
2889
+ *
2890
+ * @param result - The completed command.
2891
+ * @returns The trimmed diagnostic text.
2892
+ */
2893
+ export function readDistributionOutput(result: SpawnSyncReturns<string>): string {
2862
2894
  return \`\${result.stdout ?? ''}\${result.stderr ?? ''}\`.trim()
2863
2895
  }
2864
2896
 
2865
- function runNpm(args: readonly string[], cwd: string, scratch: string): SpawnSyncReturns<string> {
2866
- return spawnSync(NPM, [...args], {
2897
+ /**
2898
+ * Runs npm with a cache inside the owned scratch directory.
2899
+ *
2900
+ * @param args - The npm arguments.
2901
+ * @param cwd - The working directory.
2902
+ * @param scratch - The owned scratch root.
2903
+ * @returns The command status and captured streams.
2904
+ */
2905
+ export function runDistributionNpm(
2906
+ args: readonly string[],
2907
+ cwd: string,
2908
+ scratch: string,
2909
+ ): SpawnSyncReturns<string> {
2910
+ return spawnSync(DISTRIBUTION_NPM, [...args], {
2867
2911
  cwd,
2868
2912
  encoding: 'utf8',
2869
2913
  env: { ...process.env, npm_config_cache: join(scratch, 'cache') },
2870
- shell: SHELL,
2914
+ shell: DISTRIBUTION_SHELL,
2871
2915
  windowsHide: true,
2872
2916
  })
2873
2917
  }
2874
2918
 
2875
- function runNode(args: readonly string[], cwd: string): SpawnSyncReturns<string> {
2919
+ /**
2920
+ * Runs a JavaScript entry with the running Node executable.
2921
+ *
2922
+ * @param args - The Node arguments.
2923
+ * @param cwd - The working directory.
2924
+ * @returns The command status and captured streams.
2925
+ */
2926
+ export function runDistributionNode(
2927
+ args: readonly string[],
2928
+ cwd: string,
2929
+ ): SpawnSyncReturns<string> {
2876
2930
  return spawnSync(process.execPath, [...args], { cwd, encoding: 'utf8', windowsHide: true })
2877
2931
  }
2878
2932
 
2879
2933
  // Node's own condition matching, read in declaration order.
2880
- function resolvePackageTarget(
2934
+ /**
2935
+ * Resolves a package target through conditions and fallback arrays.
2936
+ *
2937
+ * @param entry - The exports-map entry.
2938
+ * @param conditions - The active resolution conditions.
2939
+ * @returns The selected target, or undefined when no branch resolves.
2940
+ */
2941
+ export function resolveDistributionPackageTarget(
2881
2942
  entry: unknown,
2882
2943
  conditions: readonly string[],
2883
- ): TargetResolution | undefined {
2944
+ ): DistributionTargetResult | undefined {
2884
2945
  if (typeof entry === 'string') return { target: entry }
2885
- if (isList(entry)) {
2946
+ if (isDistributionList(entry)) {
2886
2947
  for (const member of entry) {
2887
- const resolved = resolvePackageTarget(member, conditions)
2888
- if (resolved !== undefined && isPackageTarget(resolved.target)) return resolved
2948
+ const resolved = resolveDistributionPackageTarget(member, conditions)
2949
+ if (resolved !== undefined && matchesDistributionPackageTarget(resolved.target))
2950
+ return resolved
2889
2951
  }
2890
2952
  return undefined
2891
2953
  }
2892
- if (!isRecord(entry)) return undefined
2954
+ if (!isDistributionRecord(entry)) return undefined
2893
2955
  for (const [condition, nested] of Object.entries(entry)) {
2894
2956
  if (condition !== 'default' && !conditions.includes(condition)) continue
2895
- const resolved = resolvePackageTarget(nested, conditions)
2957
+ const resolved = resolveDistributionPackageTarget(nested, conditions)
2896
2958
  if (resolved !== undefined) return resolved
2897
2959
  }
2898
2960
  return undefined
@@ -2902,13 +2964,29 @@ function resolvePackageTarget(
2902
2964
  // one walker. An entry may declare \`types\` beside \`default\` at its top level
2903
2965
  // rather than inside \`import\`, so a fixed \`entry.import.types\` lookup is not
2904
2966
  // equivalent to condition resolution.
2905
- function resolveTarget(entry: unknown, conditions: readonly string[]): string | undefined {
2906
- return resolvePackageTarget(entry, conditions)?.target
2967
+ /**
2968
+ * Resolves the path selected by an exports-map entry.
2969
+ *
2970
+ * @param entry - The exports-map entry.
2971
+ * @param conditions - The active resolution conditions.
2972
+ * @returns The selected path, or undefined when no branch resolves.
2973
+ */
2974
+ export function resolveDistributionTarget(
2975
+ entry: unknown,
2976
+ conditions: readonly string[],
2977
+ ): string | undefined {
2978
+ return resolveDistributionPackageTarget(entry, conditions)?.target
2907
2979
  }
2908
2980
 
2909
2981
  // Whether a path is a physical file. TypeScript's file-existence check refuses a
2910
2982
  // directory at the same spelling and continues to the outer package scope.
2911
- function matchesFile(path: string): boolean {
2983
+ /**
2984
+ * Checks whether a path names a physical file.
2985
+ *
2986
+ * @param path - The filesystem path.
2987
+ * @returns True if the path names a file; false otherwise.
2988
+ */
2989
+ export function matchesDistributionFile(path: string): boolean {
2912
2990
  try {
2913
2991
  return statSync(path).isFile()
2914
2992
  } catch {
@@ -2919,8 +2997,18 @@ function matchesFile(path: string): boolean {
2919
2997
  // TypeScript resolves a declaration target by accepting an existing declaration
2920
2998
  // directly or by substituting beside a JavaScript target. A missing target leaves
2921
2999
  // the containing condition or fallback list unresolved, so the walk continues.
2922
- function targetToDeclaration(target: string, installed: string): string | undefined {
2923
- if (!isPackageTarget(target)) return undefined
3000
+ /**
3001
+ * Resolves an existing declaration beside a package target.
3002
+ *
3003
+ * @param target - The package-relative target.
3004
+ * @param installed - The installed package root.
3005
+ * @returns The declaration target, or undefined when no declaration exists.
3006
+ */
3007
+ export function targetToDistributionDeclaration(
3008
+ target: string,
3009
+ installed: string,
3010
+ ): string | undefined {
3011
+ if (!matchesDistributionPackageTarget(target)) return undefined
2924
3012
  const declaration = target.endsWith('.cjs')
2925
3013
  ? \`\${target.slice(0, -4)}.d.cts\`
2926
3014
  : target.endsWith('.mjs')
@@ -2928,29 +3016,37 @@ function targetToDeclaration(target: string, installed: string): string | undefi
2928
3016
  : target.endsWith('.js')
2929
3017
  ? \`\${target.slice(0, -3)}.d.ts\`
2930
3018
  : target
2931
- if (declaration === target && !isDeclaration(target)) return undefined
2932
- return matchesFile(join(installed, declaration)) ? declaration : undefined
3019
+ if (declaration === target && !matchesDistributionDeclaration(target)) return undefined
3020
+ return matchesDistributionFile(join(installed, declaration)) ? declaration : undefined
2933
3021
  }
2934
3022
 
2935
3023
  // The declaration TypeScript resolves through one importing format's conditions.
2936
3024
  // Condition objects keep manifest order, and arrays keep fallback order.
2937
- function resolveDeclaration(
3025
+ /**
3026
+ * Resolves an existing declaration through consumer conditions.
3027
+ *
3028
+ * @param entry - The exports-map entry.
3029
+ * @param conditions - The active declaration conditions.
3030
+ * @param installed - The installed package root.
3031
+ * @returns The declaration target, or undefined when no branch resolves.
3032
+ */
3033
+ export function resolveDistributionDeclaration(
2938
3034
  entry: unknown,
2939
3035
  conditions: readonly string[],
2940
3036
  installed: string,
2941
3037
  ): string | undefined {
2942
- if (typeof entry === 'string') return targetToDeclaration(entry, installed)
2943
- if (isList(entry)) {
3038
+ if (typeof entry === 'string') return targetToDistributionDeclaration(entry, installed)
3039
+ if (isDistributionList(entry)) {
2944
3040
  for (const member of entry) {
2945
- const resolved = resolveDeclaration(member, conditions, installed)
3041
+ const resolved = resolveDistributionDeclaration(member, conditions, installed)
2946
3042
  if (resolved !== undefined) return resolved
2947
3043
  }
2948
3044
  return undefined
2949
3045
  }
2950
- if (!isRecord(entry)) return undefined
3046
+ if (!isDistributionRecord(entry)) return undefined
2951
3047
  for (const [condition, nested] of Object.entries(entry)) {
2952
3048
  if (condition !== 'default' && !conditions.includes(condition)) continue
2953
- const resolved = resolveDeclaration(nested, conditions, installed)
3049
+ const resolved = resolveDistributionDeclaration(nested, conditions, installed)
2954
3050
  if (resolved !== undefined) return resolved
2955
3051
  }
2956
3052
  return undefined
@@ -2959,7 +3055,14 @@ function resolveDeclaration(
2959
3055
  // The nearest package scope that decides a \`.d.ts\` declaration's module format. A
2960
3056
  // physical nested manifest starts a scope even when it omits \`type\` or cannot be
2961
3057
  // parsed. A directory at that spelling is not a manifest, so the walk continues.
2962
- function readPackageType(installed: string, target: string): unknown {
3058
+ /**
3059
+ * Reads the nearest package scope for a target inside an installed package.
3060
+ *
3061
+ * @param installed - The installed package root.
3062
+ * @param target - The package-relative target.
3063
+ * @returns The manifest type, or undefined when the nearest scope omits it or cannot be read.
3064
+ */
3065
+ export function readDistributionPackageType(installed: string, target: string): unknown {
2963
3066
  // One \`dirname\` per path segment reaches the root from any path. The walk ends at the
2964
3067
  // installed package, so no scope above it is consulted.
2965
3068
  const start = dirname(join(installed, target))
@@ -2969,57 +3072,91 @@ function readPackageType(installed: string, target: string): unknown {
2969
3072
  const end = chain.indexOf(installed)
2970
3073
  const scope = chain
2971
3074
  .slice(0, end === -1 ? chain.length : end + 1)
2972
- .find((directory) => matchesFile(join(directory, 'package.json')))
3075
+ .find((directory) => matchesDistributionFile(join(directory, 'package.json')))
2973
3076
  if (scope === undefined) return undefined
2974
3077
  try {
2975
- const manifest = readJson(join(scope, 'package.json'))
2976
- return isRecord(manifest) ? manifest.type : undefined
3078
+ const manifest = readDistributionJSON(join(scope, 'package.json'))
3079
+ return isDistributionRecord(manifest) ? manifest.type : undefined
2977
3080
  } catch {
2978
3081
  return undefined
2979
3082
  }
2980
3083
  }
2981
3084
 
2982
- function resolvesBrowser(entry: unknown): boolean {
2983
- const module = resolveTarget(entry, RUNTIME_CONDITIONS.browser)
2984
- if (module !== undefined && module.startsWith(BROWSER_OUTPUT)) return true
3085
+ /**
3086
+ * Checks whether an entry publishes a distinct or conventional browser target.
3087
+ *
3088
+ * @param entry - The exports-map entry.
3089
+ * @returns True if the entry requires a browser drive; false otherwise.
3090
+ */
3091
+ export function resolvesDistributionBrowser(entry: unknown): boolean {
3092
+ const module = resolveDistributionTarget(entry, DISTRIBUTION_RUNTIME_CONDITIONS.browser)
3093
+ if (module !== undefined && module.startsWith(DISTRIBUTION_BROWSER_OUTPUT)) return true
2985
3094
  if (module === undefined) return false
2986
- const imported = resolveTarget(entry, RUNTIME_CONDITIONS.module)
2987
- const required = resolveTarget(entry, RUNTIME_CONDITIONS.commonjs)
3095
+ const imported = resolveDistributionTarget(entry, DISTRIBUTION_RUNTIME_CONDITIONS.module)
3096
+ const required = resolveDistributionTarget(entry, DISTRIBUTION_RUNTIME_CONDITIONS.commonjs)
2988
3097
  return module !== imported && module !== required
2989
3098
  }
2990
3099
 
2991
3100
  // Whether the target selected by Node's CommonJS conditions is a module require can
2992
3101
  // load. A JavaScript target takes its own nearest package scope. Native addons and
2993
3102
  // extensionless targets have their own CommonJS handlers.
2994
- function resolvesCommonJS(entry: unknown, installed: string): boolean {
2995
- const target = resolveTarget(entry, RUNTIME_CONDITIONS.commonjs)
3103
+ /**
3104
+ * Checks whether Node require can load an entry selected by its conditions.
3105
+ *
3106
+ * @param entry - The exports-map entry.
3107
+ * @param installed - The installed package root.
3108
+ * @returns True if the target has a CommonJS-compatible format; false otherwise.
3109
+ */
3110
+ export function resolvesDistributionCommonJS(entry: unknown, installed: string): boolean {
3111
+ const target = resolveDistributionTarget(entry, DISTRIBUTION_RUNTIME_CONDITIONS.commonjs)
2996
3112
  if (target === undefined) return false
2997
3113
  const name = target.slice(target.lastIndexOf('/') + 1)
2998
3114
  if (name.endsWith('.cjs')) return true
2999
3115
  if (name.endsWith('.mjs')) return false
3000
3116
  if (name.endsWith('.node')) return true
3001
3117
  if (!name.includes('.')) return true
3002
- return name.endsWith('.js') && readPackageType(installed, target) !== 'module'
3118
+ return name.endsWith('.js') && readDistributionPackageType(installed, target) !== 'module'
3003
3119
  }
3004
3120
 
3005
3121
  // Whether the declaration selected by a typed CommonJS consumer admits that entry.
3006
3122
  // A \`.d.cts\` declaration admits and a \`.d.mts\` declaration refuses. A \`.d.ts\`
3007
3123
  // declaration takes its own nearest package scope.
3008
- function declaresCommonJS(entry: unknown, installed: string): boolean {
3009
- const declaration = resolveDeclaration(entry, DECLARATION_CONDITIONS.commonjs, installed)
3124
+ /**
3125
+ * Checks whether an entry resolves a CommonJS-compatible declaration.
3126
+ *
3127
+ * @param entry - The exports-map entry.
3128
+ * @param installed - The installed package root.
3129
+ * @returns True if the selected declaration admits CommonJS consumption; false otherwise.
3130
+ */
3131
+ export function declaresDistributionCommonJS(entry: unknown, installed: string): boolean {
3132
+ const declaration = resolveDistributionDeclaration(
3133
+ entry,
3134
+ DISTRIBUTION_DECLARATION_CONDITIONS.commonjs,
3135
+ installed,
3136
+ )
3010
3137
  if (declaration === undefined) return false
3011
3138
  if (declaration.endsWith('.d.cts')) return true
3012
3139
  if (declaration.endsWith('.d.mts')) return false
3013
- return declaration.endsWith('.d.ts') && readPackageType(installed, declaration) !== 'module'
3140
+ return (
3141
+ declaration.endsWith('.d.ts') &&
3142
+ readDistributionPackageType(installed, declaration) !== 'module'
3143
+ )
3014
3144
  }
3015
3145
 
3016
3146
  // Every target an entry names under any condition. A fallback list omits members
3017
3147
  // Node rejects during package-target validation, because no reader can take them.
3018
- function collectTargets(entry: unknown): readonly string[] {
3148
+ /**
3149
+ * Collects the targets an entry publishes under every condition.
3150
+ *
3151
+ * @param entry - The exports-map entry.
3152
+ * @returns The targets, excluding invalid members of fallback arrays.
3153
+ */
3154
+ export function collectDistributionTargets(entry: unknown): readonly string[] {
3019
3155
  if (typeof entry === 'string') return [entry]
3020
- if (isList(entry)) return entry.flatMap(collectTargets).filter(isPackageTarget)
3021
- if (!isRecord(entry)) return []
3022
- return Object.values(entry).flatMap((nested) => collectTargets(nested))
3156
+ if (isDistributionList(entry))
3157
+ return entry.flatMap(collectDistributionTargets).filter(matchesDistributionPackageTarget)
3158
+ if (!isDistributionRecord(entry)) return []
3159
+ return Object.values(entry).flatMap((nested) => collectDistributionTargets(nested))
3023
3160
  }
3024
3161
 
3025
3162
  // Whether a target is a file a runtime loads for its names, which is what a
@@ -3031,24 +3168,43 @@ function collectTargets(entry: unknown): readonly string[] {
3031
3168
  // \`"./package.json"\` manifest pointer, and a declaration alike.
3032
3169
  // The cost is an extensionless file published for a reader, such as a \`LICENSE\`:
3033
3170
  // that target reports undeclared until it is given an extension or a declaration.
3034
- function isModule(target: string): boolean {
3171
+ /**
3172
+ * Checks whether a target names a runtime module rather than an asset.
3173
+ *
3174
+ * @param target - The package-relative target.
3175
+ * @returns True if the target has a module extension or no extension; false otherwise.
3176
+ */
3177
+ export function matchesDistributionModule(target: string): boolean {
3035
3178
  const name = target.slice(target.lastIndexOf('/') + 1)
3036
3179
  const dot = name.lastIndexOf('.')
3037
- if (name.endsWith(ADDON_EXTENSION)) return true
3038
- return dot === -1 || MODULE_EXTENSIONS.includes(name.slice(dot))
3180
+ if (name.endsWith(DISTRIBUTION_ADDON_EXTENSION)) return true
3181
+ return dot === -1 || DISTRIBUTION_MODULE_EXTENSIONS.includes(name.slice(dot))
3039
3182
  }
3040
3183
 
3041
3184
  // Whether a resolved target is a declaration rather than the JavaScript a
3042
3185
  // \`default\` branch answers with when the entry declares no \`types\` condition.
3043
- function isDeclaration(target: string): boolean {
3044
- return DECLARATION_EXTENSIONS.some((extension) => target.endsWith(extension))
3186
+ /**
3187
+ * Checks whether a target names a TypeScript declaration.
3188
+ *
3189
+ * @param target - The package-relative target.
3190
+ * @returns True if the target has a declaration extension; false otherwise.
3191
+ */
3192
+ export function matchesDistributionDeclaration(target: string): boolean {
3193
+ return DISTRIBUTION_DECLARATION_EXTENSIONS.some((extension) => target.endsWith(extension))
3045
3194
  }
3046
3195
 
3047
3196
  // The declarations the Node module, Node CommonJS, and browser drives compare
3048
3197
  // against. Each field uses the conditions of the TypeScript consumer paired with
3049
3198
  // that runtime. A JavaScript target resolves through TypeScript's adjacent
3050
3199
  // declaration substitution rather than standing in for the declaration itself.
3051
- function readDeclaration(
3200
+ /**
3201
+ * Reads the declarations paired with Node and browser consumers.
3202
+ *
3203
+ * @param entry - The exports-map entry.
3204
+ * @param installed - The installed package root.
3205
+ * @returns The declaration selected by each consumer format.
3206
+ */
3207
+ export function readDistributionDeclaration(
3052
3208
  entry: unknown,
3053
3209
  installed: string,
3054
3210
  ): {
@@ -3057,17 +3213,39 @@ function readDeclaration(
3057
3213
  readonly browser: string | undefined
3058
3214
  } {
3059
3215
  return {
3060
- module: resolveDeclaration(entry, DECLARATION_CONDITIONS.module, installed),
3061
- commonjs: resolveDeclaration(entry, DECLARATION_CONDITIONS.commonjs, installed),
3062
- browser: resolveDeclaration(entry, DECLARATION_CONDITIONS.browser, installed),
3216
+ module: resolveDistributionDeclaration(
3217
+ entry,
3218
+ DISTRIBUTION_DECLARATION_CONDITIONS.module,
3219
+ installed,
3220
+ ),
3221
+ commonjs: resolveDistributionDeclaration(
3222
+ entry,
3223
+ DISTRIBUTION_DECLARATION_CONDITIONS.commonjs,
3224
+ installed,
3225
+ ),
3226
+ browser: resolveDistributionDeclaration(
3227
+ entry,
3228
+ DISTRIBUTION_DECLARATION_CONDITIONS.browser,
3229
+ installed,
3230
+ ),
3063
3231
  }
3064
3232
  }
3065
3233
 
3066
3234
  // The entries one compile driver can resolve under its own conditions.
3067
- function selectEntries(entries: readonly Entry[], conditions: readonly string[]): readonly Entry[] {
3235
+ /**
3236
+ * Filters entries to those a consumer can resolve.
3237
+ *
3238
+ * @param entries - The installed entries.
3239
+ * @param conditions - The active consumer conditions.
3240
+ * @returns The matching entries in their original order.
3241
+ */
3242
+ export function filterDistributionEntries(
3243
+ entries: readonly DistributionEntry[],
3244
+ conditions: readonly string[],
3245
+ ): readonly DistributionEntry[] {
3068
3246
  return entries.filter(
3069
3247
  (entry) =>
3070
- resolveTarget(entry.mapping, conditions) !== undefined &&
3248
+ resolveDistributionTarget(entry.mapping, conditions) !== undefined &&
3071
3249
  (!conditions.includes('require') || entry.loadable),
3072
3250
  )
3073
3251
  }
@@ -3075,22 +3253,42 @@ function selectEntries(entries: readonly Entry[], conditions: readonly string[])
3075
3253
  // The compile drivers whose conditions reach one entry under one importing format.
3076
3254
  // A driver that resolves no target for that entry compiles nothing, so a consumer
3077
3255
  // written under it would report a resolution failure this package never made.
3078
- function selectDrivers(entry: Entry, format: Format): readonly Resolution[] {
3079
- return RESOLUTIONS.filter(
3080
- (driver) => selectEntries([entry], driver.conditions[format]).length > 0,
3256
+ /**
3257
+ * Filters compiler resolutions to those that can read an entry.
3258
+ *
3259
+ * @param entry - The installed entry.
3260
+ * @param format - The consumer module format.
3261
+ * @returns The matching compiler resolutions.
3262
+ */
3263
+ export function filterDistributionResolutions(
3264
+ entry: DistributionEntry,
3265
+ format: DistributionFormat,
3266
+ ): readonly DistributionResolution[] {
3267
+ return DISTRIBUTION_RESOLUTIONS.filter(
3268
+ (driver) => filterDistributionEntries([entry], driver.conditions[format]).length > 0,
3081
3269
  )
3082
3270
  }
3083
3271
 
3084
3272
  // Requirable entries that declare CommonJS support but a typed CommonJS consumer
3085
3273
  // cannot compile against. A default branch resolving under the require condition
3086
3274
  // set makes no CommonJS claim.
3087
- function selectUntypable(entries: readonly Entry[], installed: string): readonly Entry[] {
3275
+ /**
3276
+ * Filters entries whose require target lacks a compatible declaration.
3277
+ *
3278
+ * @param entries - The installed entries.
3279
+ * @param installed - The installed package root.
3280
+ * @returns The entries a CommonJS consumer cannot typecheck.
3281
+ */
3282
+ export function filterDistributionUntypable(
3283
+ entries: readonly DistributionEntry[],
3284
+ installed: string,
3285
+ ): readonly DistributionEntry[] {
3088
3286
  return entries.filter(
3089
3287
  (entry) =>
3090
3288
  entry.requirable &&
3091
- isRecord(entry.mapping) &&
3289
+ isDistributionRecord(entry.mapping) &&
3092
3290
  Object.hasOwn(entry.mapping, 'require') &&
3093
- !declaresCommonJS(entry.mapping, installed),
3291
+ !declaresDistributionCommonJS(entry.mapping, installed),
3094
3292
  )
3095
3293
  }
3096
3294
 
@@ -3098,20 +3296,30 @@ function selectUntypable(entries: readonly Entry[], installed: string): readonly
3098
3296
  // installed entry that consumer imports, the file extension fixing its importing
3099
3297
  // format, the names a real runtime published off it, and the driver whose scratch
3100
3298
  // project compiles it.
3101
- interface Surface {
3102
- readonly entry: Entry
3299
+ /** Describes the runtime names and declaration resolution compared for one entry. */
3300
+ export interface DistributionSurface {
3301
+ readonly entry: DistributionEntry
3103
3302
  readonly extension: string
3104
3303
  readonly published: readonly string[]
3105
- readonly driver: Resolution
3304
+ readonly driver: DistributionResolution
3106
3305
  }
3107
3306
 
3108
3307
  // A scratch project over named consumer modules, written beside them so their own
3109
3308
  // resolution reaches the installed package. Nothing is emitted and no ambient types
3110
3309
  // are pulled in, so what the check reads is the installed declarations alone.
3111
- function writeProject(
3112
- stage: Stage,
3310
+ /**
3311
+ * Writes a compiler project for a consumer probe.
3312
+ *
3313
+ * @param stage - The installed consumer.
3314
+ * @param name - The project filename suffix.
3315
+ * @param driver - The compiler resolution.
3316
+ * @param files - The consumer source files.
3317
+ * @returns The absolute project path.
3318
+ */
3319
+ export function writeDistributionProject(
3320
+ stage: DistributionStage,
3113
3321
  name: string,
3114
- driver: Resolution,
3322
+ driver: DistributionResolution,
3115
3323
  files: readonly string[],
3116
3324
  ): string {
3117
3325
  const path = join(stage.consumer, \`tsconfig.\${name}.json\`)
@@ -3127,7 +3335,7 @@ function writeProject(
3127
3335
  },
3128
3336
  files: [...files],
3129
3337
  }
3130
- writeFile(path, \`\${JSON.stringify(project, undefined, '\\t')}\\n\`)
3338
+ writeDistributionFile(path, \`\${JSON.stringify(project, undefined, '\\t')}\\n\`)
3131
3339
  return path
3132
3340
  }
3133
3341
 
@@ -3138,8 +3346,21 @@ function writeProject(
3138
3346
  // naming the scratch project rather than a consumer module, and anything at all on
3139
3347
  // the error stream are faults of this proof rather than of the package under proof,
3140
3348
  // so each is raised where it happens instead of counted against the package.
3141
- function checkProject(stage: Stage, project: string): readonly string[] {
3142
- const result = runNode([TSC, '--noEmit', '--pretty', 'false', '-p', project], stage.consumer)
3349
+ /**
3350
+ * Checks a consumer project with the installed TypeScript compiler.
3351
+ *
3352
+ * @param stage - The installed consumer.
3353
+ * @param project - The compiler project path.
3354
+ * @returns The located compiler diagnostics. Throws on a tool or project failure.
3355
+ */
3356
+ export function checkDistributionProject(
3357
+ stage: DistributionStage,
3358
+ project: string,
3359
+ ): readonly string[] {
3360
+ const result = runDistributionNode(
3361
+ [DISTRIBUTION_COMPILER, '--noEmit', '--pretty', 'false', '-p', project],
3362
+ stage.consumer,
3363
+ )
3143
3364
  const refused = \`\${result.stderr ?? ''}\`.trim()
3144
3365
  if (refused.length > 0) {
3145
3366
  throw new Error(\`The consumer compiler wrote \${refused} to its error stream\`)
@@ -3151,7 +3372,7 @@ function checkProject(stage: Stage, project: string): readonly string[] {
3151
3372
  const heads = lines.flatMap((line, index) => (index === 0 || !/^\\s/u.test(line) ? [index] : []))
3152
3373
  const reported = heads.map((head, position) => {
3153
3374
  const line = lines[head] ?? ''
3154
- const located = DIAGNOSTIC_PATTERN.exec(line)?.[1]
3375
+ const located = DISTRIBUTION_DIAGNOSTIC_PATTERN.exec(line)?.[1]
3155
3376
  if (located === undefined) {
3156
3377
  throw new Error(\`The consumer compiler reported \${line}, which names no location\`)
3157
3378
  }
@@ -3164,7 +3385,7 @@ function checkProject(stage: Stage, project: string): readonly string[] {
3164
3385
  ].join(' ')
3165
3386
  })
3166
3387
  if (reported.length === 0 && result.status !== 0) {
3167
- throw new Error(\`The consumer compiler refused the project: \${readOutput(result)}\`)
3388
+ throw new Error(\`The consumer compiler refused the project: \${readDistributionOutput(result)}\`)
3168
3389
  }
3169
3390
  return reported
3170
3391
  }
@@ -3179,26 +3400,47 @@ function checkProject(stage: Stage, project: string): readonly string[] {
3179
3400
  // as a type alone, land on \`surfaced\`: a variable widens into the type
3180
3401
  // \`declared\` annotates, and only \`surfaced\` reads the literal's own keys back.
3181
3402
  // Each names the member it is about, so the failure says which export moved.
3182
- function checkSurface(stage: Stage, surface: Surface): readonly string[] {
3403
+ /**
3404
+ * Checks runtime export names against their installed declarations.
3405
+ *
3406
+ * @param stage - The installed consumer.
3407
+ * @param surface - The publication and declaration pair.
3408
+ * @returns The diagnostics labelled by compiler resolution.
3409
+ */
3410
+ export function checkDistributionSurface(
3411
+ stage: DistributionStage,
3412
+ surface: DistributionSurface,
3413
+ ): readonly string[] {
3183
3414
  const slug = surface.entry.subpath.replaceAll(/[^\\w]+/gu, '-')
3184
3415
  const name = \`surface.\${surface.driver.label}\${slug}.\${surface.extension}\`
3185
3416
  const module = \`\${name}\`
3186
3417
  const keys = surface.published.map((key) => \`\${JSON.stringify(key)}: true\`).join(', ')
3187
- writeFile(
3418
+ writeDistributionFile(
3188
3419
  join(stage.consumer, module),
3189
3420
  \`import * as entry from \${JSON.stringify(surface.entry.specifier)}
3190
- const published = {\${keys.length === 0 ? '' : \` \${keys} \`}} as const
3191
- const declared: Record<keyof typeof entry, true> = published
3192
- const surfaced: Record<keyof typeof published, true> = declared
3421
+ export const published = {\${keys.length === 0 ? '' : \` \${keys} \`}} as const
3422
+ export const declared: Record<keyof typeof entry, true> = published
3423
+ export const surfaced: Record<keyof typeof published, true> = declared
3193
3424
  \`,
3194
3425
  )
3195
- const project = writeProject(stage, name, surface.driver, [\`./\${module}\`])
3196
- return checkProject(stage, project).map((line) => \`\${surface.driver.label}: \${line}\`)
3426
+ const project = writeDistributionProject(stage, name, surface.driver, [\`./\${module}\`])
3427
+ return checkDistributionProject(stage, project).map((line) => \`\${surface.driver.label}: \${line}\`)
3197
3428
  }
3198
3429
 
3199
3430
  // One consumer module importing every installed entry, written where its own
3200
3431
  // resolution finds the installed package.
3201
- function writeConsumerProbe(stage: Stage, path: string, specifiers: readonly string[]): void {
3432
+ /**
3433
+ * Writes a consumer importing the requested public specifiers.
3434
+ *
3435
+ * @param stage - The installed consumer.
3436
+ * @param path - The consumer-relative source path.
3437
+ * @param specifiers - The public imports to resolve.
3438
+ */
3439
+ export function writeDistributionConsumerProbe(
3440
+ stage: DistributionStage,
3441
+ path: string,
3442
+ specifiers: readonly string[],
3443
+ ): void {
3202
3444
  const modules = specifiers.map((specifier, index) => ({
3203
3445
  binding: \`entry\${String(index)}\`,
3204
3446
  specifier,
@@ -3208,112 +3450,94 @@ function writeConsumerProbe(stage: Stage, path: string, specifiers: readonly str
3208
3450
  )
3209
3451
  const names = modules.map(({ binding }) => binding)
3210
3452
  const source = \`\${bindings.join('\\n')}\\nexport const surface = [\${names.join(', ')}]\\n\`
3211
- writeFile(join(stage.consumer, path), source)
3453
+ writeDistributionFile(join(stage.consumer, path), source)
3212
3454
  }
3213
3455
 
3214
3456
  // The runtime key set a real process reads off one installed entry under one
3215
3457
  // condition. The driver is a file rather than an \`--eval\` string, so the specifier
3216
3458
  // travels as an argument and nothing needs escaping.
3217
- function driveRuntime(stage: Stage, specifier: string, driver: string): readonly string[] {
3218
- const result = runNode([join(stage.consumer, driver), specifier], stage.consumer)
3459
+ /**
3460
+ * Reads the names a real Node process loads from an installed entry.
3461
+ *
3462
+ * @param stage - The installed consumer.
3463
+ * @param specifier - The public package specifier.
3464
+ * @param driver - The consumer driver filename.
3465
+ * @returns The exported names. Throws when loading or decoding fails.
3466
+ */
3467
+ export function driveDistributionRuntime(
3468
+ stage: DistributionStage,
3469
+ specifier: string,
3470
+ driver: string,
3471
+ ): readonly string[] {
3472
+ const result = runDistributionNode([join(stage.consumer, driver), specifier], stage.consumer)
3219
3473
  if (result.status !== 0) {
3220
- throw new Error(\`Loading \${specifier} from the consumer failed: \${readOutput(result)}\`)
3474
+ throw new Error(
3475
+ \`Loading \${specifier} from the consumer failed: \${readDistributionOutput(result)}\`,
3476
+ )
3221
3477
  }
3222
3478
  const published: unknown = JSON.parse(result.stdout)
3223
- if (!isNames(published)) throw new Error(\`The driver printed no name list for \${specifier}\`)
3479
+ if (!isDistributionNames(published))
3480
+ throw new Error(\`The driver printed no name list for \${specifier}\`)
3224
3481
  return published
3225
3482
  }
3226
3483
  {{helpers}}
3227
3484
  // Pack this workspace, install the archive into an isolated consumer, and read the
3228
3485
  // published surface back off the installed tree. Every later claim reads this
3229
3486
  // result, so a failure here is raised where it happens rather than once per entry.
3230
- function buildStage(scratch: string): Stage {
3487
+ /**
3488
+ * Packs the workspace and installs its archive into an isolated consumer.
3489
+ *
3490
+ * @param scratch - The owned scratch root.
3491
+ * @returns The installed consumer and classified exports.
3492
+ * @throws Thrown when packing or installation fails.
3493
+ */
3494
+ export function buildDistributionStage(scratch: string): DistributionStage {
3231
3495
  const packed = join(scratch, 'packed')
3232
3496
  const consumer = join(scratch, 'consumer')
3233
3497
  mkdirSync(packed, { recursive: true })
3234
- const pack = runNpm(['pack', '--ignore-scripts', '--pack-destination', packed], ROOT, scratch)
3235
- if (pack.status !== 0) throw new Error(\`npm pack refused this workspace: \${readOutput(pack)}\`)
3498
+ const pack = runDistributionNpm(
3499
+ ['pack', '--ignore-scripts', '--pack-destination', packed],
3500
+ DISTRIBUTION_ROOT,
3501
+ scratch,
3502
+ )
3503
+ if (pack.status !== 0)
3504
+ throw new Error(\`npm pack refused this workspace: \${readDistributionOutput(pack)}\`)
3236
3505
  const archives = readdirSync(packed).filter((name) => name.endsWith('.tgz'))
3237
3506
  const archive = archives[0]
3238
3507
  if (archives.length !== 1 || archive === undefined) {
3239
3508
  throw new Error(\`npm pack wrote no single archive: \${archives.join(', ')}\`)
3240
3509
  }
3241
- writeFile(join(consumer, 'package.json'), CONSUMER_MANIFEST)
3242
- writeFile(join(consumer, ESM_DRIVER), ESM_DRIVER_SOURCE)
3243
- writeFile(join(consumer, CJS_DRIVER), CJS_DRIVER_SOURCE)
3244
- const install = runNpm(
3510
+ writeDistributionFile(join(consumer, 'package.json'), DISTRIBUTION_CONSUMER_MANIFEST)
3511
+ writeDistributionFile(join(consumer, DISTRIBUTION_ESM_DRIVER), DISTRIBUTION_ESM_DRIVER_SOURCE)
3512
+ writeDistributionFile(join(consumer, DISTRIBUTION_CJS_DRIVER), DISTRIBUTION_CJS_DRIVER_SOURCE)
3513
+ const install = runDistributionNpm(
3245
3514
  ['install', '--ignore-scripts', '--no-audit', '--no-fund', join(packed, archive)],
3246
3515
  consumer,
3247
3516
  scratch,
3248
3517
  )
3249
3518
  if (install.status !== 0) {
3250
- throw new Error(\`Installing the packed archive failed: \${readOutput(install)}\`)
3519
+ throw new Error(\`Installing the packed archive failed: \${readDistributionOutput(install)}\`)
3251
3520
  }
3252
- const name = readManifestName(join(ROOT, 'package.json'))
3521
+ const name = readDistributionManifestName(join(DISTRIBUTION_ROOT, 'package.json'))
3253
3522
  const installed = join(consumer, 'node_modules', ...name.split('/'))
3254
- const manifest = readJson(join(installed, 'package.json'))
3255
- if (!isRecord(manifest) || !isRecord(manifest.exports)) {
3523
+ const manifest = readDistributionJSON(join(installed, 'package.json'))
3524
+ if (!isDistributionRecord(manifest) || !isDistributionRecord(manifest.exports)) {
3256
3525
  throw new Error('The installed manifest publishes no exports map')
3257
3526
  }
3258
- const readings = Object.entries(manifest.exports).map(([subpath, mapping]) => {
3259
- const files = collectTargets(mapping)
3260
- const declaration = readDeclaration(mapping, installed)
3261
- // A subpath resolving no declaration is partitioned rather than dropped. It is a
3262
- // defect when a runtime loads one of its targets for names, because a consumer
3263
- // importing it compiles against nothing under \`node16\`. It is an excluded
3264
- // publication otherwise: the \`"./package.json"\` manifest pointer and a stylesheet
3265
- // are published for a reader rather than an importer.
3266
- if (
3267
- declaration.module === undefined &&
3268
- declaration.commonjs === undefined &&
3269
- declaration.browser === undefined
3270
- ) {
3271
- return { subpath, files, entry: undefined }
3272
- }
3273
- const importTarget = resolveTarget(mapping, RUNTIME_CONDITIONS.module)
3274
- const requireTarget = resolveTarget(mapping, RUNTIME_CONDITIONS.commonjs)
3275
- const browserTarget = resolveTarget(mapping, RUNTIME_CONDITIONS.browser)
3276
- const browsable = resolvesBrowser(mapping)
3277
- const shadowed = browsable && requireTarget === browserTarget
3278
- const requirable = requireTarget !== undefined && !shadowed
3279
- const loadable = requirable && resolvesCommonJS(mapping, installed)
3280
- const entry: Entry = {
3281
- subpath,
3282
- specifier: subpath === '.' ? name : \`\${name}\${subpath.slice(1)}\`,
3283
- mapping,
3284
- declaration: {
3285
- importable: declaration.module !== undefined,
3286
- requirable: declaration.commonjs !== undefined,
3287
- browsable: declaration.browser !== undefined,
3288
- },
3289
- browsable,
3290
- importable: importTarget !== undefined && !(browsable && importTarget === browserTarget),
3291
- requirable,
3292
- loadable,
3293
- }
3294
- return { subpath, files, entry }
3295
- })
3296
- const entries = readings.flatMap(({ entry }) => (entry === undefined ? [] : [entry]))
3297
- const targets = readings.flatMap(({ files }) => files)
3298
- const subpaths = readings.map(({ subpath }) => subpath)
3299
- const undeclared = readings
3300
- .filter(({ entry, files }) => entry === undefined && files.some(isModule))
3301
- .map(({ subpath }) => subpath)
3302
- const excluded = readings
3303
- .filter(({ entry, files }) => entry === undefined && !files.some(isModule))
3304
- .map(({ subpath }) => subpath)
3305
- return { consumer, installed, archives, entries, subpaths, undeclared, excluded, targets }
3527
+ return { consumer, installed, archives, ...classifyDistributionStage(manifest, installed, name) }
3306
3528
  }
3307
3529
 
3308
3530
  // One file's run: the scratch directory and the staged consumer, which is absent when the
3309
3531
  // registry could not be reached.
3310
- interface DistributionRun {
3532
+ /** Binds an owned scratch directory to its optional installed consumer. */
3533
+ export interface DistributionRun {
3311
3534
  readonly scratch: string
3312
- readonly stage: Stage | undefined
3535
+ readonly stage: DistributionStage | undefined
3313
3536
  }
3314
3537
 
3315
3538
  // The run the start hook binds once for this file and the stop hook releases.
3316
- class DistributionSuite {
3539
+ /** Owns the staged consumer shared by one distribution proof. */
3540
+ export class DistributionSuite implements DistributionSuiteInterface {
3317
3541
  #run: DistributionRun | undefined
3318
3542
 
3319
3543
  get scratch(): string {
@@ -3323,8 +3547,12 @@ class DistributionSuite {
3323
3547
  return this.#run.scratch
3324
3548
  }
3325
3549
 
3326
- get stage(): Stage | undefined {
3327
- return this.#run?.stage
3550
+ read(context: TestContext): DistributionStage {
3551
+ const stage = this.#run?.stage
3552
+ if (stage === undefined) {
3553
+ return context.skip('\`npm ping\` did not answer, so nothing was packed or installed')
3554
+ }
3555
+ return stage
3328
3556
  }
3329
3557
 
3330
3558
  start(): void {
@@ -3332,7 +3560,7 @@ class DistributionSuite {
3332
3560
  throw new Error('The distribution setup has already allocated its scratch directory')
3333
3561
  }
3334
3562
  const scratch = mkdtempSync(join(tmpdir(), 'distribution-'))
3335
- this.#run = { scratch, stage: openStage(scratch) }
3563
+ this.#run = { scratch, stage: openDistributionStage(scratch) }
3336
3564
  }
3337
3565
 
3338
3566
  destroy(): void {
@@ -3343,25 +3571,26 @@ class DistributionSuite {
3343
3571
  }
3344
3572
  }
3345
3573
 
3346
- const DISTRIBUTION_SUITE = new DistributionSuite()
3347
-
3348
- beforeAll(() => DISTRIBUTION_SUITE.start())
3349
-
3350
- afterAll(() => DISTRIBUTION_SUITE.destroy())
3351
-
3352
3574
  // Installing the packed archive resolves its own runtime dependencies, so an
3353
3575
  // unreachable registry leaves nothing to measure. Under release that is the gate
3354
3576
  // failing; anywhere else the suite skips and names the mechanism it wanted.
3355
- function openStage(scratch: string): Stage | undefined {
3577
+ /**
3578
+ * Opens an installed consumer after checking registry readiness.
3579
+ *
3580
+ * @param scratch - The owned scratch root.
3581
+ * @returns The installed consumer, or undefined when an ordinary run cannot reach the registry.
3582
+ * @throws Thrown in release mode or when staging fails, after removing scratch.
3583
+ */
3584
+ export function openDistributionStage(scratch: string): DistributionStage | undefined {
3356
3585
  try {
3357
3586
  mkdirSync(join(scratch, 'cache'), { recursive: true })
3358
- if (runNpm(PING, ROOT, scratch).status !== 0) {
3359
- if (!RELEASE) return undefined
3587
+ if (runDistributionNpm(DISTRIBUTION_PING, DISTRIBUTION_ROOT, scratch).status !== 0) {
3588
+ if (!DISTRIBUTION_RELEASE) return undefined
3360
3589
  throw new Error(
3361
3590
  'The release gate requires a reachable npm registry, and npm ping did not answer',
3362
3591
  )
3363
3592
  }
3364
- return buildStage(scratch)
3593
+ return buildDistributionStage(scratch)
3365
3594
  } catch (error) {
3366
3595
  rmSync(scratch, {
3367
3596
  force: true,
@@ -3373,200 +3602,690 @@ function openStage(scratch: string): Stage | undefined {
3373
3602
  }
3374
3603
  }
3375
3604
 
3376
- describe('distribution classifiers', () => {
3377
- it('classifies synthetic export mappings without a registry stage', () => {
3378
- const root = join(DISTRIBUTION_SUITE.scratch, 'classifiers')
3379
- writeFile(
3380
- join(root, 'package.json'),
3381
- JSON.stringify({
3382
- type: 'commonjs',
3383
- exports: {
3384
- condition: { browser: './b.js', default: './n.js' },
3385
- convention: { default: './dist/src/browser/index.js' },
3386
- universal: { default: './shared.js' },
3387
- 'import-shared': {
3388
- browser: './shared.mjs',
3389
- import: './shared.mjs',
3390
- default: './node.js',
3391
- },
3392
- 'require-shared': {
3393
- browser: './shared.cjs',
3394
- require: './shared.cjs',
3395
- default: './node.js',
3396
- },
3397
- node: { node: './node.js', default: './node.js' },
3398
- silent: { 'module-sync': './x.cjs', import: './x.mjs' },
3399
- module: { require: './x.mjs' },
3400
- 'nested-module': { require: './module/x.js' },
3401
- 'nested-commonjs': { require: './commonjs/x.js' },
3402
- esm: { import: './x.mjs' },
3403
- },
3404
- }),
3605
+ /**
3606
+ * Partitions an installed exports map into driven, undeclared, and excluded subpaths.
3607
+ *
3608
+ * @param manifest - The installed package manifest.
3609
+ * @param installed - The installed package root.
3610
+ * @param name - The published package name.
3611
+ * @returns The classified entries and complete target population.
3612
+ * @throws Thrown when the exports map is absent.
3613
+ */
3614
+ export function classifyDistributionStage(
3615
+ manifest: Readonly<Record<string, unknown>>,
3616
+ installed: string,
3617
+ name: string,
3618
+ ): DistributionClassification {
3619
+ if (!isDistributionRecord(manifest.exports))
3620
+ throw new Error('The installed manifest publishes no exports map')
3621
+ const readings = Object.entries(manifest.exports).map(([subpath, mapping]) => {
3622
+ const files = collectDistributionTargets(mapping)
3623
+ const declaration = readDistributionDeclaration(mapping, installed)
3624
+ // A subpath resolving no declaration is partitioned rather than dropped. It is a
3625
+ // defect when a runtime loads one of its targets for names, because a consumer
3626
+ // importing it compiles against nothing under \`node16\`. It is an excluded
3627
+ // publication otherwise: the \`"./package.json"\` manifest pointer and a stylesheet
3628
+ // are published for a reader rather than an importer.
3629
+ if (
3630
+ declaration.module === undefined &&
3631
+ declaration.commonjs === undefined &&
3632
+ declaration.browser === undefined
3633
+ ) {
3634
+ return { subpath, files, entry: undefined }
3635
+ }
3636
+ const importTarget = resolveDistributionTarget(mapping, DISTRIBUTION_RUNTIME_CONDITIONS.module)
3637
+ const requireTarget = resolveDistributionTarget(
3638
+ mapping,
3639
+ DISTRIBUTION_RUNTIME_CONDITIONS.commonjs,
3405
3640
  )
3406
- writeFile(join(root, 'module/package.json'), '{ "type": "module" }\\n')
3407
- writeFile(join(root, 'commonjs/package.json'), '{ "type": "commonjs" }\\n')
3408
- const manifest = readJson(join(root, 'package.json'))
3409
- if (!isRecord(manifest) || !isRecord(manifest.exports)) {
3410
- throw new Error('The classifier fixture declares no exports map')
3641
+ const browserTarget = resolveDistributionTarget(
3642
+ mapping,
3643
+ DISTRIBUTION_RUNTIME_CONDITIONS.browser,
3644
+ )
3645
+ const browsable = resolvesDistributionBrowser(mapping)
3646
+ const shadowed = browsable && requireTarget === browserTarget
3647
+ const requirable = requireTarget !== undefined && !shadowed
3648
+ const loadable = requirable && resolvesDistributionCommonJS(mapping, installed)
3649
+ const entry: DistributionEntry = {
3650
+ subpath,
3651
+ specifier: subpath === '.' ? name : \`\${name}\${subpath.slice(1)}\`,
3652
+ mapping,
3653
+ declaration: {
3654
+ importable: declaration.module !== undefined,
3655
+ requirable: declaration.commonjs !== undefined,
3656
+ browsable: declaration.browser !== undefined,
3657
+ },
3658
+ browsable,
3659
+ importable: importTarget !== undefined && !(browsable && importTarget === browserTarget),
3660
+ requirable,
3661
+ loadable,
3411
3662
  }
3412
- const mappings = manifest.exports
3413
- expect({
3414
- condition: resolvesBrowser(mappings.condition),
3415
- convention: resolvesBrowser(mappings.convention),
3416
- universal: resolvesBrowser(mappings.universal),
3417
- import: resolvesBrowser(mappings['import-shared']),
3418
- require: resolvesBrowser(mappings['require-shared']),
3419
- node: resolvesBrowser(mappings.node),
3420
- }).toStrictEqual({
3421
- condition: true,
3422
- convention: true,
3423
- universal: false,
3424
- import: false,
3425
- require: false,
3426
- node: false,
3427
- })
3428
- expect({
3429
- silent: resolvesCommonJS(mappings.silent, root),
3430
- module: resolvesCommonJS(mappings.module, root),
3431
- nestedModule: resolvesCommonJS(mappings['nested-module'], root),
3432
- nestedCommonJS: resolvesCommonJS(mappings['nested-commonjs'], root),
3433
- esm: resolvesCommonJS(mappings.esm, root),
3434
- }).toStrictEqual({
3435
- silent: true,
3436
- module: false,
3437
- nestedModule: false,
3438
- nestedCommonJS: true,
3439
- esm: false,
3440
- })
3663
+ return { subpath, files, entry }
3441
3664
  })
3442
- })
3665
+ const entries = readings.flatMap(({ entry }) => (entry === undefined ? [] : [entry]))
3666
+ const targets = readings.flatMap(({ files }) => files)
3667
+ const subpaths = readings.map(({ subpath }) => subpath)
3668
+ const undeclared = readings
3669
+ .filter(({ entry, files }) => entry === undefined && files.some(matchesDistributionModule))
3670
+ .map(({ subpath }) => subpath)
3671
+ const excluded = readings
3672
+ .filter(({ entry, files }) => entry === undefined && !files.some(matchesDistributionModule))
3673
+ .map(({ subpath }) => subpath)
3674
+ return { entries, subpaths, undeclared, excluded, targets }
3675
+ }
3443
3676
 
3444
- // The staged consumer, or a skip naming what the run could not reach. \`it.skipIf\`
3445
- // carries no reason, so the gate sits here where the test context can state one.
3446
- function requireStage(context: TestContext): Stage {
3447
- const staged = DISTRIBUTION_SUITE.stage
3448
- if (staged === undefined) {
3449
- return context.skip('\`npm ping\` did not answer, so nothing was packed or installed')
3450
- }
3451
- return staged
3677
+ /**
3678
+ * Creates the lifecycle boundary used by generated distribution proofs.
3679
+ * @returns The suite interface backed by an owned run.
3680
+ */
3681
+ export function createDistributionSuite(): DistributionSuiteInterface {
3682
+ return new DistributionSuite()
3452
3683
  }
3453
3684
 
3454
- describe('installed package consumer', () => {
3455
- it('packs one archive and installs it in isolation [requires the registry]', (context) => {
3456
- const stage = requireStage(context)
3457
- expect(stage.archives).toHaveLength(1)
3458
- expect(existsSync(join(stage.installed, 'package.json'))).toBe(true)
3459
- expect(stage.entries.length).toBeGreaterThan(0)
3685
+ /**
3686
+ * Collects physical files beneath an installed output directory.
3687
+ * @param directory - The output directory to walk.
3688
+ * @returns The installed files, or an empty list when the directory is absent.
3689
+ */
3690
+ export function collectDistributionFiles(directory: string): readonly string[] {
3691
+ if (!existsSync(directory)) return []
3692
+ return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {
3693
+ const path = join(directory, entry.name)
3694
+ return entry.isDirectory() ? collectDistributionFiles(path) : entry.isFile() ? [path] : []
3460
3695
  })
3696
+ }
3461
3697
 
3462
- it('ships every relative target its exports map names [requires the registry]', (context) => {
3463
- const stage = requireStage(context)
3464
- const relative = stage.targets.filter((target) => target.startsWith('./'))
3465
- expect(relative).not.toStrictEqual([])
3466
- expect(relative.filter((target) => !existsSync(join(stage.installed, target)))).toStrictEqual(
3467
- [],
3468
- )
3698
+ /**
3699
+ * Reads the source environment owning an installed output path.
3700
+ * @param installed - The installed package root.
3701
+ * @param path - The output file.
3702
+ * @returns The source environment, or undefined outside a JavaScript face.
3703
+ */
3704
+ export function readDistributionFace(installed: string, path: string): string | undefined {
3705
+ const [output, axis, face] = relativePath(installed, path).split(sep)
3706
+ return output === 'dist'
3707
+ ? axis === 'src'
3708
+ ? face
3709
+ : axis === 'bin'
3710
+ ? 'bin'
3711
+ : undefined
3712
+ : undefined
3713
+ }
3714
+
3715
+ /**
3716
+ * Scans installed JavaScript maps for sources copied from another environment.
3717
+ * @param installed - The installed package root.
3718
+ * @returns The copied sources and unreadable maps.
3719
+ * @throws Thrown when a code-bearing output has no readable map of its own.
3720
+ */
3721
+ export function scanDistributionSourceMaps(installed: string): readonly string[] {
3722
+ const files = collectDistributionFiles(join(installed, 'dist')).filter(
3723
+ (path) => readDistributionFace(installed, path) !== undefined,
3724
+ )
3725
+ const outputs = files
3726
+ .filter((path) => /\\.(?:js|cjs|mjs)$/u.test(path))
3727
+ .map((path) => {
3728
+ const parsed = parseSync(path, readFileSync(path, 'utf8'))
3729
+ const code = parsed.program.body.some(
3730
+ (statement) =>
3731
+ statement.type !== 'EmptyStatement' &&
3732
+ !(
3733
+ statement.type === 'ExportNamedDeclaration' &&
3734
+ statement.declaration === null &&
3735
+ statement.specifiers.length === 0 &&
3736
+ statement.source === null
3737
+ ),
3738
+ )
3739
+ const reference = parsed.comments
3740
+ .flatMap((comment) => {
3741
+ const match = /^[@#]\\s*sourceMappingURL=(\\S+)\\s*$/u.exec(comment.value)
3742
+ return match?.[1] === undefined ? [] : [match[1]]
3743
+ })
3744
+ .at(-1)
3745
+ try {
3746
+ const inline = reference?.startsWith('data:') === true
3747
+ const target = inline
3748
+ ? path
3749
+ : reference === undefined
3750
+ ? \`\${path}.map\`
3751
+ : fileURLToPath(new URL(reference.replaceAll('\\\\', '/'), pathToFileURL(path)))
3752
+ return {
3753
+ path: target,
3754
+ face: readDistributionFace(installed, path),
3755
+ code,
3756
+ reference: inline ? reference : undefined,
3757
+ }
3758
+ } catch {
3759
+ throw new Error(\`Unreadable source maps for \${path}\`)
3760
+ }
3761
+ })
3762
+ const maps = [
3763
+ ...outputs.filter(
3764
+ ({ path, code, reference }) => code || reference !== undefined || existsSync(path),
3765
+ ),
3766
+ ...files
3767
+ .filter(
3768
+ (path) =>
3769
+ /\\.(?:js|cjs|mjs)\\.map$/u.test(path) && !outputs.some((output) => output.path === path),
3770
+ )
3771
+ .map((path) => ({
3772
+ path,
3773
+ face: readDistributionFace(installed, path),
3774
+ code: false,
3775
+ reference: undefined,
3776
+ })),
3777
+ ]
3778
+ if (maps.length === 0)
3779
+ console.info('No built JavaScript face holds code, so no source map is required')
3780
+ return maps.flatMap(({ path, face, code, reference }) => {
3781
+ const label = relativePath(installed, path).split(sep).join('/')
3782
+ try {
3783
+ const payload =
3784
+ reference === undefined
3785
+ ? undefined
3786
+ : /^data:application\\/json(?:;charset=[^;,]+)?(;base64)?,(.*)$/iu.exec(reference)
3787
+ const map: unknown =
3788
+ reference === undefined
3789
+ ? readDistributionJSON(path)
3790
+ : payload?.[2] === undefined
3791
+ ? undefined
3792
+ : JSON.parse(
3793
+ payload[1] === undefined
3794
+ ? decodeURIComponent(payload[2])
3795
+ : Buffer.from(payload[2], 'base64').toString('utf8'),
3796
+ )
3797
+ if (
3798
+ !isDistributionRecord(map) ||
3799
+ !isDistributionNames(map.sources) ||
3800
+ (map.sourceRoot !== undefined && typeof map.sourceRoot !== 'string')
3801
+ ) {
3802
+ throw new Error('Unreadable source map')
3803
+ }
3804
+ const root = typeof map.sourceRoot === 'string' ? map.sourceRoot : ''
3805
+ const directory = root.startsWith('file:')
3806
+ ? fileURLToPath(new URL(root))
3807
+ : resolve(dirname(path), root.replaceAll('\\\\', '/'))
3808
+ const sources = map.sources.map((source) =>
3809
+ relativePath(
3810
+ resolve(installed),
3811
+ source.startsWith('file:')
3812
+ ? fileURLToPath(new URL(source))
3813
+ : resolve(directory, source.replaceAll('\\\\', '/')),
3814
+ )
3815
+ .split(sep)
3816
+ .join('/'),
3817
+ )
3818
+ const copied = sources.filter(
3819
+ (source) => source.startsWith('src/') && !source.startsWith(\`src/\${face}/\`),
3820
+ )
3821
+ return [
3822
+ ...copied.map((source) => \`\${label}: \${source}\`),
3823
+ ...(sources.some((source) => source.startsWith(\`src/\${face}/\`))
3824
+ ? []
3825
+ : [\`\${label}: unreadable source map (no src/\${face}/ source)\`]),
3826
+ ]
3827
+ } catch {
3828
+ if (code) throw new Error(\`Unreadable source maps for \${path}\`)
3829
+ return [\`\${label}: unreadable source map\`]
3830
+ }
3469
3831
  })
3832
+ }
3470
3833
 
3471
- // Every published subpath is driven, excluded by name, or reported here. A dropped
3472
- // one leaves no trace: no runtime test, no declaration comparison, and no place in
3473
- // the resolution compile, so the run reports success for a subpath it never
3474
- // measured.
3475
- it('declares types for every module it publishes [requires the registry]', (context) => {
3476
- const stage = requireStage(context)
3477
- const partitioned = [
3478
- ...stage.entries.map((entry) => entry.subpath),
3479
- ...stage.undeclared,
3480
- ...stage.excluded,
3481
- ]
3482
- expect(stage.undeclared).toStrictEqual([])
3483
- expect(partitioned.sort()).toStrictEqual([...stage.subpaths].sort())
3484
- // A driven subpath answers a runtime condition. One resolving a declaration and
3485
- // no Node or browser target compiles for a consumer and throws when that consumer
3486
- // loads it. Each later drive retires itself for that entry, so this assertion names
3487
- // the subpath rather than counting it as driven.
3488
- const unreachable = stage.entries.filter(
3489
- (entry) => !entry.importable && !entry.requirable && !entry.browsable,
3490
- )
3491
- expect(unreachable.map((entry) => entry.subpath)).toStrictEqual([])
3492
- const untypable = selectUntypable(stage.entries, stage.installed)
3493
- expect(untypable.map((entry) => entry.subpath)).toStrictEqual([])
3834
+ /**
3835
+ * Reads top-level names declared by a roll-up, including unexported declarations.
3836
+ * @param path - The installed declaration file.
3837
+ * @returns The declared names. Refuses syntax errors and unreadable binding patterns.
3838
+ */
3839
+ export function readDistributionNames(path: string): readonly string[] {
3840
+ const source = parseSync(path, readFileSync(path, 'utf8'))
3841
+ if (source.errors.length > 0) throw new Error(\`Unreadable declarations at \${path}\`)
3842
+ return source.program.body.flatMap((statement) => {
3843
+ const declaration =
3844
+ statement.type === 'ExportNamedDeclaration' || statement.type === 'ExportDefaultDeclaration'
3845
+ ? statement.declaration
3846
+ : statement
3847
+ if (declaration === null) return []
3848
+ if (declaration.type === 'VariableDeclaration') {
3849
+ return declaration.declarations.map((binding) => {
3850
+ if (binding.id.type !== 'Identifier')
3851
+ throw new Error(\`Unreadable declaration binding at \${path}\`)
3852
+ return binding.id.name
3853
+ })
3854
+ }
3855
+ if (
3856
+ declaration.type === 'ClassDeclaration' ||
3857
+ declaration.type === 'FunctionDeclaration' ||
3858
+ declaration.type === 'TSDeclareFunction' ||
3859
+ declaration.type === 'TSInterfaceDeclaration' ||
3860
+ declaration.type === 'TSTypeAliasDeclaration' ||
3861
+ declaration.type === 'TSEnumDeclaration' ||
3862
+ declaration.type === 'TSModuleDeclaration'
3863
+ ) {
3864
+ return declaration.id?.type === 'Identifier' ? [declaration.id.name] : []
3865
+ }
3866
+ return []
3494
3867
  })
3868
+ }
3495
3869
 
3496
- it('refuses a subpath its exports map does not name [requires the registry]', (context) => {
3497
- const stage = requireStage(context)
3498
- const name = readManifestName(join(stage.installed, 'package.json'))
3499
- const driver = join(stage.consumer, ESM_DRIVER)
3500
- const result = runNode([driver, \`\${name}\${ABSENT_SUBPATH}\`], stage.consumer)
3501
- expect(result.status).not.toBe(0)
3502
- expect(readOutput(result)).toContain('ERR_PACKAGE_PATH_NOT_EXPORTED')
3870
+ /**
3871
+ * Checks whether a source entry exports names, following local star exports.
3872
+ * @param path - The source entry to inspect.
3873
+ * @param ancestors - The entries already visited on this export path.
3874
+ * @returns True if the entry exports a name; false otherwise.
3875
+ */
3876
+ export function matchesDistributionSourceExports(
3877
+ path: string,
3878
+ ancestors: readonly string[] = [],
3879
+ ): boolean {
3880
+ if (ancestors.includes(path)) return false
3881
+ const source = parseSync(path, readFileSync(path, 'utf8'))
3882
+ if (source.errors.length > 0) throw new Error(\`Unreadable source exports at \${path}\`)
3883
+ return source.program.body.some((statement) => {
3884
+ if (statement.type === 'ExportDefaultDeclaration') return ancestors.length === 0
3885
+ if (statement.type === 'ExportNamedDeclaration')
3886
+ return (
3887
+ statement.declaration !== null ||
3888
+ statement.specifiers.some((specifier) => {
3889
+ const name =
3890
+ specifier.exported.type === 'Identifier'
3891
+ ? specifier.exported.name
3892
+ : specifier.exported.value
3893
+ return ancestors.length === 0 || name !== 'default'
3894
+ })
3895
+ )
3896
+ if (statement.type !== 'ExportAllDeclaration') return false
3897
+ if (statement.exported !== null || !statement.source.value.startsWith('.')) return true
3898
+ const target = resolve(dirname(path), statement.source.value.replace(/\\.js$/u, '.ts'))
3899
+ return matchesDistributionSourceExports(target, [...ancestors, path])
3503
3900
  })
3901
+ }
3504
3902
 
3505
- // The absent subpath is the firing control: a resolution that reports nothing
3506
- // for every published entry has not been shown to resolve anything at all. Each
3507
- // module format carries its own control, because a format that resolves nothing
3508
- // is silent for the same reason a resolution that resolves nothing is.
3509
- it('compiles a consumer under every module resolution [requires the registry]', (context) => {
3510
- const stage = requireStage(context)
3511
- const name = readManifestName(join(stage.installed, 'package.json'))
3512
- const readings = RESOLUTIONS.flatMap((driver) =>
3513
- FORMATS.flatMap(([extension, format]) => {
3514
- const written = selectEntries(stage.entries, driver.conditions[format])
3515
- if (written.length === 0) return []
3516
- const label = \`\${driver.label}.\${extension}\`
3517
- const probe = \`probe.\${label}\`
3518
- const specifiers = written.map((entry) => entry.specifier)
3519
- writeConsumerProbe(stage, probe, specifiers)
3520
- const project = writeProject(stage, probe, driver, [\`./\${probe}\`])
3521
- const messages = checkProject(stage, project).map((message) => \`\${label}: \${message}\`)
3522
- const control = \`control.\${label}\`
3523
- writeConsumerProbe(stage, control, [\`\${name}\${ABSENT_SUBPATH}\`])
3524
- const refused = writeProject(stage, control, driver, [\`./\${control}\`])
3525
- return [{ messages, silent: checkProject(stage, refused).length === 0 ? [label] : [] }]
3526
- }),
3527
- )
3528
- expect(readings.flatMap(({ messages }) => messages)).toStrictEqual([])
3529
- expect(readings.flatMap(({ silent }) => silent)).toStrictEqual([])
3903
+ /**
3904
+ * Scans installed declaration faces for names declared by multiple environments.
3905
+ * @param installed - The installed package root.
3906
+ * @param source - The workspace holding the source entries being published.
3907
+ * @returns The repeated names with their declaring faces.
3908
+ * @throws Thrown when a source entry exports names but its roll-up declares none.
3909
+ */
3910
+ export function scanDistributionDeclarations(
3911
+ installed: string,
3912
+ source: string = DISTRIBUTION_ROOT,
3913
+ ): readonly string[] {
3914
+ const declarations = collectDistributionFiles(join(installed, 'dist'))
3915
+ .filter(matchesDistributionDeclaration)
3916
+ .map((path) => ({
3917
+ path,
3918
+ face: readDistributionFace(installed, path),
3919
+ names: readDistributionNames(path),
3920
+ }))
3921
+ const entries = collectDistributionFiles(join(source, 'src')).filter((path) => {
3922
+ const parts = relativePath(source, path).split(sep)
3923
+ return parts.length === 3 && parts[2] === 'index.ts'
3530
3924
  })
3531
- {{guard}}})
3532
-
3533
- describe('installed entries', () => {
3534
- it('publishes what it declares to a Node import, and no more', (context) => {
3535
- const stage = requireStage(context)
3536
- const entries = stage.entries.filter((entry) => entry.importable)
3537
- if (entries.length === 0) return context.skip('No installed entry supports Node import')
3538
- for (const entry of entries) {
3539
- if (!entry.declaration.importable) {
3540
- throw new Error(\`\${entry.subpath} publishes no import declaration\`)
3541
- }
3542
- const published = driveRuntime(stage, entry.specifier, ESM_DRIVER)
3543
- const drivers = selectDrivers(entry, 'module')
3544
- expect(drivers).not.toStrictEqual([])
3545
- const reported = drivers.flatMap((driver) =>
3546
- checkSurface(stage, { entry, extension: 'ts', published, driver }),
3925
+ const published = entries.filter((path) => matchesDistributionSourceExports(path))
3926
+ for (const path of published) {
3927
+ const face = relativePath(source, path).split(sep)[1]
3928
+ if (!declarations.some((entry) => entry.face === face && entry.names.length > 0))
3929
+ throw new Error(
3930
+ \`The \${face} source entry exports names but its declaration roll-up declares none\`,
3547
3931
  )
3548
- expect(reported).toStrictEqual([])
3549
- }
3932
+ }
3933
+ if (published.length === 0)
3934
+ console.info('No source entry exports names, so no declaration names are required')
3935
+ const names = [...new Set(declarations.flatMap((entry) => entry.names))].sort()
3936
+ return names.flatMap((name) => {
3937
+ const faces = [
3938
+ ...new Set(
3939
+ declarations
3940
+ .filter((entry) => entry.names.includes(name))
3941
+ .map((entry) => entry.face)
3942
+ .filter((face) => face !== undefined),
3943
+ ),
3944
+ ].sort()
3945
+ return faces.length > 1 ? [\`\${name}: \${faces.join(', ')}\`] : []
3550
3946
  })
3947
+ }
3551
3948
 
3552
- it('publishes what it declares to a Node require, and no more', (context) => {
3553
- const stage = requireStage(context)
3554
- const entries = stage.entries.filter((entry) => entry.requirable)
3555
- if (entries.length === 0) return context.skip('No installed entry supports Node require')
3556
- for (const entry of entries) {
3557
- if (!entry.declaration.requirable) {
3558
- throw new Error(\`\${entry.subpath} publishes no require declaration\`)
3559
- }
3560
- const published = driveRuntime(stage, entry.specifier, CJS_DRIVER)
3561
- const drivers = selectDrivers(entry, 'commonjs')
3562
- expect(drivers).not.toStrictEqual([])
3563
- const reported = drivers.flatMap((driver) =>
3564
- checkSurface(stage, { entry, extension: 'cts', published, driver }),
3565
- )
3566
- expect(reported).toStrictEqual([])
3567
- }
3568
- })
3569
- {{drive}}})
3949
+ /**
3950
+ * Checks the installed manifest against npm's normalization in an owned scratch copy.
3951
+ * @param installed - The installed package root, read only.
3952
+ * @param scratch - The suite's owned scratch root and npm cache parent.
3953
+ * @returns The top-level keys changed by npm. Refuses an unsuccessful npm command.
3954
+ */
3955
+ export function checkDistributionManifest(installed: string, scratch: string): readonly string[] {
3956
+ const directory = mkdtempSync(join(scratch, 'manifest-'))
3957
+ try {
3958
+ const path = join(directory, 'package.json')
3959
+ writeFileSync(path, readFileSync(join(installed, 'package.json')))
3960
+ const before = readDistributionJSON(path)
3961
+ const result = runDistributionNpm(['pkg', 'fix'], directory, scratch)
3962
+ if (result.status !== 0)
3963
+ throw new Error(\`npm pkg fix failed: \${readDistributionOutput(result)}\`)
3964
+ const after = readDistributionJSON(path)
3965
+ if (!isDistributionRecord(before) || !isDistributionRecord(after))
3966
+ throw new Error('Unreadable manifest')
3967
+ return [...new Set([...Object.keys(before), ...Object.keys(after)])]
3968
+ .filter((key) => !isDeepStrictEqual(before[key], after[key]))
3969
+ .sort()
3970
+ } finally {
3971
+ rmSync(directory, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })
3972
+ }
3973
+ }
3974
+
3975
+ /**
3976
+ * Builds independently registered observations over the suite's installed consumer.
3977
+ * @param suite - The lifecycle shared by the proof's hooks and observations.
3978
+ * @returns The case rows whose observations each require one assertion.
3979
+ */
3980
+ export function buildDistributionCases(
3981
+ suite: DistributionSuiteInterface,
3982
+ ): readonly DistributionCase[] {
3983
+ return [
3984
+ {
3985
+ label: 'classifies synthetic export mappings without a registry stage',
3986
+ observe: () => {
3987
+ const root = join(suite.scratch, 'classifiers')
3988
+ writeDistributionFile(
3989
+ join(root, 'package.json'),
3990
+ JSON.stringify({
3991
+ type: 'commonjs',
3992
+ exports: {
3993
+ condition: { browser: './b.js', default: './n.js' },
3994
+ convention: { default: './dist/src/browser/index.js' },
3995
+ universal: { default: './shared.js' },
3996
+ 'import-shared': {
3997
+ browser: './shared.mjs',
3998
+ import: './shared.mjs',
3999
+ default: './node.js',
4000
+ },
4001
+ 'require-shared': {
4002
+ browser: './shared.cjs',
4003
+ require: './shared.cjs',
4004
+ default: './node.js',
4005
+ },
4006
+ node: { node: './node.js', default: './node.js' },
4007
+ silent: { 'module-sync': './x.cjs', import: './x.mjs' },
4008
+ module: { require: './x.mjs' },
4009
+ 'nested-module': { require: './module/x.js' },
4010
+ 'nested-commonjs': { require: './commonjs/x.js' },
4011
+ esm: { import: './x.mjs' },
4012
+ },
4013
+ }),
4014
+ )
4015
+ writeDistributionFile(join(root, 'module/package.json'), '{ "type": "module" }\\n')
4016
+ writeDistributionFile(join(root, 'commonjs/package.json'), '{ "type": "commonjs" }\\n')
4017
+ const manifest = readDistributionJSON(join(root, 'package.json'))
4018
+ if (!isDistributionRecord(manifest) || !isDistributionRecord(manifest.exports)) {
4019
+ throw new Error('The classifier fixture declares no exports map')
4020
+ }
4021
+ const mappings = manifest.exports
4022
+
4023
+ return {
4024
+ actual: {
4025
+ browser: {
4026
+ condition: resolvesDistributionBrowser(mappings.condition),
4027
+ convention: resolvesDistributionBrowser(mappings.convention),
4028
+ universal: resolvesDistributionBrowser(mappings.universal),
4029
+ import: resolvesDistributionBrowser(mappings['import-shared']),
4030
+ require: resolvesDistributionBrowser(mappings['require-shared']),
4031
+ node: resolvesDistributionBrowser(mappings.node),
4032
+ },
4033
+ commonjs: {
4034
+ silent: resolvesDistributionCommonJS(mappings.silent, root),
4035
+ module: resolvesDistributionCommonJS(mappings.module, root),
4036
+ nestedModule: resolvesDistributionCommonJS(mappings['nested-module'], root),
4037
+ nestedCommonJS: resolvesDistributionCommonJS(mappings['nested-commonjs'], root),
4038
+ esm: resolvesDistributionCommonJS(mappings.esm, root),
4039
+ },
4040
+ },
4041
+ expected: {
4042
+ browser: {
4043
+ condition: true,
4044
+ convention: true,
4045
+ universal: false,
4046
+ import: false,
4047
+ require: false,
4048
+ node: false,
4049
+ },
4050
+ commonjs: {
4051
+ silent: true,
4052
+ module: false,
4053
+ nestedModule: false,
4054
+ nestedCommonJS: true,
4055
+ esm: false,
4056
+ },
4057
+ },
4058
+ }
4059
+ },
4060
+ },
4061
+ {
4062
+ label: 'keeps installed JavaScript sources in their own environment [requires the registry]',
4063
+ observe: (context) => {
4064
+ const stage = suite.read(context)
4065
+ return { actual: scanDistributionSourceMaps(stage.installed), expected: [] }
4066
+ },
4067
+ },
4068
+ {
4069
+ label: 'declares each installed name in one environment [requires the registry]',
4070
+ observe: (context) => {
4071
+ const stage = suite.read(context)
4072
+ const faces = new Set(
4073
+ collectDistributionFiles(join(stage.installed, 'dist'))
4074
+ .filter(matchesDistributionDeclaration)
4075
+ .map((path) => readDistributionFace(stage.installed, path))
4076
+ .filter((face) => face !== undefined),
4077
+ )
4078
+ const findings = scanDistributionDeclarations(stage.installed)
4079
+ if (faces.size <= 1)
4080
+ console.info(
4081
+ 'Fewer than two declaration faces are installed, so no cross-face copy exists',
4082
+ )
4083
+ return { actual: findings, expected: [] }
4084
+ },
4085
+ },
4086
+ {
4087
+ label: 'keeps the installed manifest fixed under npm pkg fix [requires the registry]',
4088
+ observe: (context) => ({
4089
+ actual: checkDistributionManifest(suite.read(context).installed, suite.scratch),
4090
+ expected: [],
4091
+ }),
4092
+ },
4093
+ {
4094
+ label: 'packs one archive and installs it in isolation [requires the registry]',
4095
+ observe: (context) => {
4096
+ const stage = suite.read(context)
4097
+ return {
4098
+ actual: {
4099
+ archives: stage.archives.length,
4100
+ installed: existsSync(join(stage.installed, 'package.json')),
4101
+ entries: stage.entries.length > 0,
4102
+ },
4103
+ expected: { archives: 1, installed: true, entries: true },
4104
+ }
4105
+ },
4106
+ },
4107
+ {
4108
+ label: 'ships every relative target its exports map names [requires the registry]',
4109
+ observe: (context) => {
4110
+ const stage = suite.read(context)
4111
+ const relative = stage.targets.filter((target) => target.startsWith('./'))
4112
+ return {
4113
+ actual: {
4114
+ populated: relative.length > 0,
4115
+ missing: relative.filter((target) => !existsSync(join(stage.installed, target))),
4116
+ },
4117
+ expected: { populated: true, missing: [] },
4118
+ }
4119
+ },
4120
+ },
4121
+ {
4122
+ label: 'declares types for every module it publishes [requires the registry]',
4123
+ observe: (context) => {
4124
+ const stage = suite.read(context)
4125
+ const partitioned = [
4126
+ ...stage.entries.map((entry) => entry.subpath),
4127
+ ...stage.undeclared,
4128
+ ...stage.excluded,
4129
+ ]
4130
+ return {
4131
+ actual: {
4132
+ undeclared: stage.undeclared,
4133
+ partitioned: partitioned.sort(),
4134
+ unreachable: stage.entries
4135
+ .filter((entry) => !entry.importable && !entry.requirable && !entry.browsable)
4136
+ .map((entry) => entry.subpath),
4137
+ untypable: filterDistributionUntypable(stage.entries, stage.installed).map(
4138
+ (entry) => entry.subpath,
4139
+ ),
4140
+ },
4141
+ expected: {
4142
+ undeclared: [],
4143
+ partitioned: [...stage.subpaths].sort(),
4144
+ unreachable: [],
4145
+ untypable: [],
4146
+ },
4147
+ }
4148
+ },
4149
+ },
4150
+ {
4151
+ label: 'refuses a subpath its exports map does not name [requires the registry]',
4152
+ observe: (context) => {
4153
+ const stage = suite.read(context)
4154
+ const name = readDistributionManifestName(join(stage.installed, 'package.json'))
4155
+ const result = runDistributionNode(
4156
+ [join(stage.consumer, DISTRIBUTION_ESM_DRIVER), \`\${name}\${DISTRIBUTION_ABSENT_SUBPATH}\`],
4157
+ stage.consumer,
4158
+ )
4159
+ return {
4160
+ actual: {
4161
+ refused: result.status !== 0,
4162
+ coded: readDistributionOutput(result).includes('ERR_PACKAGE_PATH_NOT_EXPORTED'),
4163
+ },
4164
+ expected: { refused: true, coded: true },
4165
+ }
4166
+ },
4167
+ },
4168
+ {
4169
+ label: 'compiles a consumer under every module resolution [requires the registry]',
4170
+ observe: (context) => {
4171
+ const stage = suite.read(context)
4172
+ const name = readDistributionManifestName(join(stage.installed, 'package.json'))
4173
+ const readings = DISTRIBUTION_RESOLUTIONS.flatMap((driver) =>
4174
+ DISTRIBUTION_FORMATS.flatMap(([extension, format]) => {
4175
+ const written = filterDistributionEntries(stage.entries, driver.conditions[format])
4176
+ if (written.length === 0) return []
4177
+ const label = \`\${driver.label}.\${extension}\`
4178
+ const probe = \`probe.\${label}\`
4179
+ const specifiers = written.map((entry) => entry.specifier)
4180
+ writeDistributionConsumerProbe(stage, probe, specifiers)
4181
+ const project = writeDistributionProject(stage, probe, driver, [\`./\${probe}\`])
4182
+ const messages = checkDistributionProject(stage, project).map(
4183
+ (message) => \`\${label}: \${message}\`,
4184
+ )
4185
+ const control = \`control.\${label}\`
4186
+ writeDistributionConsumerProbe(stage, control, [
4187
+ \`\${name}\${DISTRIBUTION_ABSENT_SUBPATH}\`,
4188
+ ])
4189
+ const refused = writeDistributionProject(stage, control, driver, [\`./\${control}\`])
4190
+ return [
4191
+ {
4192
+ messages,
4193
+ silent: checkDistributionProject(stage, refused).length === 0 ? [label] : [],
4194
+ },
4195
+ ]
4196
+ }),
4197
+ )
4198
+ return {
4199
+ actual: {
4200
+ messages: readings.flatMap(({ messages }) => messages),
4201
+ silent: readings.flatMap(({ silent }) => silent),
4202
+ },
4203
+ expected: { messages: [], silent: [] },
4204
+ }
4205
+ },
4206
+ },
4207
+ {
4208
+ label: 'publishes what it declares to a Node import, and no more',
4209
+ observe: (context) => {
4210
+ const stage = suite.read(context)
4211
+ const entries = stage.entries.filter((entry) => entry.importable)
4212
+ if (entries.length === 0) return context.skip('No installed entry supports Node import')
4213
+ const readings = entries.map((entry) => {
4214
+ if (!entry.declaration.importable)
4215
+ throw new Error(\`\${entry.subpath} publishes no import declaration\`)
4216
+ const published = driveDistributionRuntime(
4217
+ stage,
4218
+ entry.specifier,
4219
+ DISTRIBUTION_ESM_DRIVER,
4220
+ )
4221
+ const drivers = filterDistributionResolutions(entry, 'module')
4222
+ return {
4223
+ entry: entry.subpath,
4224
+ driven: drivers.length > 0,
4225
+ reported: drivers.flatMap((driver) =>
4226
+ checkDistributionSurface(stage, { entry, extension: 'ts', published, driver }),
4227
+ ),
4228
+ }
4229
+ })
4230
+ return {
4231
+ actual: readings,
4232
+ expected: entries.map((entry) => ({ entry: entry.subpath, driven: true, reported: [] })),
4233
+ }
4234
+ },
4235
+ },
4236
+ {
4237
+ label: 'publishes what it declares to a Node require, and no more',
4238
+ observe: (context) => {
4239
+ const stage = suite.read(context)
4240
+ const entries = stage.entries.filter((entry) => entry.requirable)
4241
+ if (entries.length === 0) return context.skip('No installed entry supports Node require')
4242
+ const readings = entries.map((entry) => {
4243
+ if (!entry.declaration.requirable)
4244
+ throw new Error(\`\${entry.subpath} publishes no require declaration\`)
4245
+ const published = driveDistributionRuntime(
4246
+ stage,
4247
+ entry.specifier,
4248
+ DISTRIBUTION_CJS_DRIVER,
4249
+ )
4250
+ const drivers = filterDistributionResolutions(entry, 'commonjs')
4251
+ return {
4252
+ entry: entry.subpath,
4253
+ driven: drivers.length > 0,
4254
+ reported: drivers.flatMap((driver) =>
4255
+ checkDistributionSurface(stage, { entry, extension: 'cts', published, driver }),
4256
+ ),
4257
+ }
4258
+ })
4259
+ return {
4260
+ actual: readings,
4261
+ expected: entries.map((entry) => ({ entry: entry.subpath, driven: true, reported: [] })),
4262
+ }
4263
+ },
4264
+ },
4265
+ ]
4266
+ }
4267
+ `,
4268
+ proof: `import {
4269
+ // These exports remain available to proofs emitted by earlier scaffold releases.
4270
+ buildDistributionCases,
4271
+ {{import}}createDistributionSuite,
4272
+ } from './setupDistribution.js'
4273
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest'
4274
+
4275
+ const DISTRIBUTION_SUITE = createDistributionSuite()
4276
+
4277
+ beforeAll(() => DISTRIBUTION_SUITE.start())
4278
+
4279
+ afterAll(() => DISTRIBUTION_SUITE.destroy())
4280
+
4281
+ describe('installed package consumer', () => {
4282
+ for (const row of buildDistributionCases(DISTRIBUTION_SUITE)) {
4283
+ it(\`\${row.label}\`, async (context) => {
4284
+ const observation = await row.observe(context)
4285
+ expect(observation.actual).toStrictEqual(observation.expected)
4286
+ })
4287
+ }
4288
+ {{guard}}{{drive}}})
3570
4289
  `,
3571
4290
  transport: `import { createServer } from 'node:http'
3572
4291
  `,
@@ -3577,8 +4296,9 @@ import type { Browser } from 'playwright'
3577
4296
  import { build } from 'vite'
3578
4297
  import { resolveBrowser, resolvePinnedBrowser } from '../configs/browsers.js'
3579
4298
  `,
3580
- helpers: `
3581
- const BROWSER_PAGE = \`<!doctype html>
4299
+ import: "checkDistributionBrowser,\n ",
4300
+ helpers: `/** Defines the page that loads a bundled browser consumer. */
4301
+ export const DISTRIBUTION_BROWSER_PAGE = \`<!doctype html>
3582
4302
  <html lang="en">
3583
4303
  <head>
3584
4304
  <meta charset="UTF-8" />
@@ -3590,7 +4310,13 @@ const BROWSER_PAGE = \`<!doctype html>
3590
4310
  </html>
3591
4311
  \`
3592
4312
 
3593
- function readContentType(path: string): string {
4313
+ /**
4314
+ * Infers the response media type from a bundle filename.
4315
+ *
4316
+ * @param path - The requested bundle path.
4317
+ * @returns The media type, defaulting to application/octet-stream.
4318
+ */
4319
+ export function inferDistributionContentType(path: string): string {
3594
4320
  if (path.endsWith('.html')) return 'text/html'
3595
4321
  if (path.endsWith('.js')) return 'text/javascript'
3596
4322
  if (path.endsWith('.css')) return 'text/css'
@@ -3601,7 +4327,13 @@ function readContentType(path: string): string {
3601
4327
  // \`resolveBrowser\` answers with provider options and never reports absence: its
3602
4328
  // last resort is a channel nothing verified. So the launch is attempted and its
3603
4329
  // rejection classified, rather than probed for and ruled on.
3604
- function describeBrowser(options: PlaywrightProviderOptions): string {
4330
+ /**
4331
+ * Renders the browser endpoint selected by provider options.
4332
+ *
4333
+ * @param options - The browser provider options.
4334
+ * @returns The endpoint, executable, channel, or bundled-browser description.
4335
+ */
4336
+ export function renderDistributionBrowser(options: PlaywrightProviderOptions): string {
3605
4337
  const endpoint = options.connectOptions?.wsEndpoint
3606
4338
  if (endpoint !== undefined) return \`the browser server at \${endpoint}\`
3607
4339
  const executable = options.launchOptions?.executablePath
@@ -3611,7 +4343,15 @@ function describeBrowser(options: PlaywrightProviderOptions): string {
3611
4343
  return 'the Chromium Playwright installed for itself'
3612
4344
  }
3613
4345
 
3614
- async function launchBrowser(options: PlaywrightProviderOptions): Promise<Browser> {
4346
+ /**
4347
+ * Launches or connects to the selected Chromium browser.
4348
+ *
4349
+ * @param options - The browser provider options.
4350
+ * @returns The real browser. Rejects when the selected browser is unavailable.
4351
+ */
4352
+ export async function launchDistributionBrowser(
4353
+ options: PlaywrightProviderOptions,
4354
+ ): Promise<Browser> {
3615
4355
  const endpoint = options.connectOptions?.wsEndpoint
3616
4356
  if (endpoint !== undefined) return chromium.connect(endpoint)
3617
4357
  return chromium.launch({ ...options.launchOptions, headless: true })
@@ -3620,11 +4360,21 @@ async function launchBrowser(options: PlaywrightProviderOptions): Promise<Browse
3620
4360
  // A consumer of one installed browser entry, bundled by the Vite toolchain this
3621
4361
  // workspace already declares. Nothing is stubbed: the bundle resolves the installed
3622
4362
  // package and its whole transitive graph as an application consuming it would.
3623
- async function bundleEntry(stage: Stage, entry: Entry): Promise<string> {
4363
+ /**
4364
+ * Bundles a browser consumer against an installed public entry.
4365
+ *
4366
+ * @param stage - The installed consumer.
4367
+ * @param entry - The browser publication.
4368
+ * @returns The bundle directory. Rejects when Vite cannot build the consumer.
4369
+ */
4370
+ export async function bundleDistributionEntry(
4371
+ stage: DistributionStage,
4372
+ entry: DistributionEntry,
4373
+ ): Promise<string> {
3624
4374
  const page = join(stage.consumer, 'pages', entry.subpath.replaceAll(/[^\\w]+/gu, '-'))
3625
4375
  const specifier = JSON.stringify(entry.specifier)
3626
- writeFile(join(page, 'index.html'), BROWSER_PAGE)
3627
- writeFile(
4376
+ writeDistributionFile(join(page, 'index.html'), DISTRIBUTION_BROWSER_PAGE)
4377
+ writeDistributionFile(
3628
4378
  join(page, 'main.js'),
3629
4379
  \`import * as entry from \${specifier}\\nglobalThis.subject = Object.keys(entry).sort()\\n\`,
3630
4380
  )
@@ -3641,7 +4391,17 @@ async function bundleEntry(stage: Stage, entry: Entry): Promise<string> {
3641
4391
  // The key set the bundled module publishes in a real browser, read off the page
3642
4392
  // once it has loaded over a loopback server. A module that never evaluated
3643
4393
  // publishes nothing, and a page error is raised rather than compared away.
3644
- async function readBrowserExports(browser: Browser, bundle: string): Promise<readonly string[]> {
4394
+ /**
4395
+ * Reads the names a real browser publishes from a served bundle.
4396
+ *
4397
+ * @param browser - The browser to drive.
4398
+ * @param bundle - The built consumer directory.
4399
+ * @returns The exported names. Rejects on a page error or an invalid name list.
4400
+ */
4401
+ export async function readDistributionBrowserExports(
4402
+ browser: Browser,
4403
+ bundle: string,
4404
+ ): Promise<readonly string[]> {
3645
4405
  const server = createServer((request, response) => {
3646
4406
  const asked = request.url === undefined || request.url === '/' ? '/index.html' : request.url
3647
4407
  const path = join(bundle, decodeURIComponent(asked))
@@ -3650,7 +4410,7 @@ async function readBrowserExports(browser: Browser, bundle: string): Promise<rea
3650
4410
  response.end()
3651
4411
  return
3652
4412
  }
3653
- response.writeHead(200, { 'content-type': readContentType(path) })
4413
+ response.writeHead(200, { 'content-type': inferDistributionContentType(path) })
3654
4414
  response.end(readFileSync(path))
3655
4415
  })
3656
4416
  try {
@@ -3667,63 +4427,65 @@ async function readBrowserExports(browser: Browser, bundle: string): Promise<rea
3667
4427
  await page.goto(\`http://127.0.0.1:\${String(address.port)}/\`, { waitUntil: 'load' })
3668
4428
  const published: unknown = await page.evaluate('globalThis.subject')
3669
4429
  if (failures.length > 0) throw new Error(\`The bundle raised \${failures.join(' | ')}\`)
3670
- if (!isNames(published)) throw new Error('The bundled module published no name list')
4430
+ if (!isDistributionNames(published))
4431
+ throw new Error('The bundled module published no name list')
3671
4432
  return published
3672
4433
  } finally {
3673
4434
  server.close()
3674
4435
  }
3675
4436
  }
3676
- `,
3677
- drive: `
3678
- it('publishes what it declares to a real browser [requires a browser]', async (context) => {
3679
- const stage = requireStage(context)
3680
- const entries = stage.entries.filter((entry) => entry.browsable)
3681
- if (entries.length === 0) return context.skip('No installed entry supports a browser')
3682
- for (const entry of entries) {
3683
- if (!entry.declaration.browsable) {
3684
- throw new Error(\`\${entry.subpath} publishes no browser declaration\`)
3685
- }
3686
- const options = resolveBrowser(resolvePinnedBrowser(), process.platform, process.env)
3687
- const browser = await launchBrowser(options).catch((error: unknown) => {
3688
- const cause = \`\${describeBrowser(options)} was rejected: \${String(error)}\`
3689
- if (RELEASE) throw new Error(\`The release gate requires a browser, and \${cause}\`)
3690
- return context.skip(\`No browser launched. \${cause}\`)
4437
+ /**
4438
+ * Checks each browser publication against its installed declarations in a real browser.
4439
+ * @param stage - The installed consumer to drive.
4440
+ * @param context - The proof context that reports unavailable browser prerequisites.
4441
+ * @returns The compiler diagnostics each browser publication reports.
4442
+ */
4443
+ export async function checkDistributionBrowser(
4444
+ stage: DistributionStage,
4445
+ context: TestContext,
4446
+ ): Promise<readonly string[]> {
4447
+ const driver = DISTRIBUTION_BROWSER_RESOLUTION
4448
+ if (driver === undefined) throw new Error("DISTRIBUTION_RESOLUTIONS carries no 'bundler' row")
4449
+ const entries = stage.entries.filter((entry) => entry.browsable)
4450
+ if (entries.length === 0) return context.skip('No installed entry supports a browser')
4451
+ const readings: Array<readonly string[]> = []
4452
+ for (const entry of entries) {
4453
+ if (!entry.declaration.browsable) {
4454
+ throw new Error(\`\${entry.subpath} publishes no browser declaration\`)
4455
+ }
4456
+ const options = resolveBrowser(resolvePinnedBrowser(), process.platform, process.env)
4457
+ const browser = await launchDistributionBrowser(options).catch((error: unknown) => {
4458
+ const cause = \`\${renderDistributionBrowser(options)} was rejected: \${String(error)}\`
4459
+ if (DISTRIBUTION_RELEASE) throw new Error(\`The release gate requires a browser, and \${cause}\`)
4460
+ return context.skip(\`No browser launched. \${cause}\`)
4461
+ })
4462
+ try {
4463
+ const bundle = await bundleDistributionEntry(stage, entry)
4464
+ const published = await readDistributionBrowserExports(browser, bundle)
4465
+ // A browser consumer reads the installed declarations through a bundler, so
4466
+ // that is the one driver this face answers under.
4467
+ const reported = checkDistributionSurface(stage, {
4468
+ entry,
4469
+ extension: 'ts',
4470
+ published,
4471
+ driver,
3691
4472
  })
3692
- try {
3693
- const bundle = await bundleEntry(stage, entry)
3694
- const published = await readBrowserExports(browser, bundle)
3695
- // A browser consumer reads the installed declarations through a bundler, so
3696
- // that is the one driver this face answers under.
3697
- const reported = checkSurface(stage, {
3698
- entry,
3699
- extension: 'ts',
3700
- published,
3701
- driver: BROWSER_DRIVER,
3702
- })
3703
- expect(reported).toStrictEqual([])
3704
- } finally {
3705
- await browser.close()
3706
- }
4473
+ readings.push(reported)
4474
+ } finally {
4475
+ await browser.close()
3707
4476
  }
4477
+ }
4478
+ return readings.flat()
4479
+ }
4480
+ `,
4481
+ drive: ` it('publishes what it declares to a real browser [requires a browser]', async (context) => {
4482
+ expect(await checkDistributionBrowser(DISTRIBUTION_SUITE.read(context), context)).toStrictEqual(
4483
+ [],
4484
+ )
3708
4485
  })
3709
4486
  `,
3710
- guard: `
3711
- // This proof drives a Node import and a Node require and carries no browser
3712
- // branch: the workspace published no browser face when it was written, and the
3713
- // browser drive measures the packed artifact, so only a published face is owed
3714
- // one. A private browser application does not select this branch. It declares the
3715
- // browser launcher and its Vitest browser provider and gets the generated browser
3716
- // configuration module beside it, but installed browser tooling does not stand for
3717
- // a published browser face. \`vite\` selects nothing either, though the branch
3718
- // imports it: scaffold puts \`vite\` in every workspace's base development
3719
- // dependencies, whatever that workspace publishes. The later Node
3720
- // entry filters retire each matching Node drive for a face published
3721
- // later, which leaves nothing measuring it. So it reddens here and names the
3722
- // subpath a browser branch is owed for. A workspace that gains one deletes this
3723
- // file and runs the \`repair\` verb, which writes the variant carrying that branch.
3724
- it('publishes no browser face this proof cannot drive [requires the registry]', (context) => {
3725
- const stage = requireStage(context)
3726
- const faces = stage.entries.filter((entry) => entry.browsable)
4487
+ guard: ` it('publishes no browser face this proof cannot drive [requires the registry]', (context) => {
4488
+ const faces = DISTRIBUTION_SUITE.read(context).entries.filter((entry) => entry.browsable)
3727
4489
  expect(faces.map((entry) => entry.subpath)).toStrictEqual([])
3728
4490
  })
3729
4491
  `
@@ -3973,7 +4735,7 @@ var isContent = (0, _orkestrel_contract.stringOf)({ max: MAX_ARTIFACT_BYTES });
3973
4735
  *
3974
4736
  * @remarks
3975
4737
  * Compose this ahead of an element guard so the item count is settled before
3976
- * anything walks the items. A hostile `length` accessor answers `false` here
4738
+ * anything walks the items. A throwing `length` accessor answers `false` here
3977
4739
  * rather than escaping as a thrown error.
3978
4740
  *
3979
4741
  * @example
@@ -4224,6 +4986,7 @@ var isBlueprint = (0, _orkestrel_contract.recordOf)({
4224
4986
  guides: _orkestrel_contract.isBoolean,
4225
4987
  integration: _orkestrel_contract.isBoolean,
4226
4988
  conformance: _orkestrel_contract.isBoolean,
4989
+ tree: _orkestrel_contract.isBoolean,
4227
4990
  service: _orkestrel_contract.isBoolean,
4228
4991
  vendors: (0, _orkestrel_contract.andOf)(isCollection, (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)),
4229
4992
  studies: _orkestrel_contract.isBoolean,
@@ -4405,7 +5168,7 @@ var isCatalogEntry = (0, _orkestrel_contract.unionOf)((0, _orkestrel_contract.re
4405
5168
  * whose every value is exact lowercase hexadecimal bytes; false otherwise.
4406
5169
  *
4407
5170
  * @remarks
4408
- * Read through the shared total key lens, so a hostile `ownKeys` trap and a
5171
+ * Read through the shared total key lens, so an `ownKeys` trap that throws and a
4409
5172
  * throwing accessor both answer `false` rather than escaping. There is no
4410
5173
  * dictionary combinator upstream to compose this from: the key law and the
4411
5174
  * value law are both this package's own.
@@ -6126,10 +6889,11 @@ function blueprintToScripts(blueprint) {
6126
6889
  "npm run test:policy",
6127
6890
  "npm run test:config",
6128
6891
  ...blueprint.setup.includes("node") || blueprint.global ? ["npm run test:setup"] : [],
6129
- ...blueprint.setup.includes("browser") || targets.length > 0 ? ["npm run test:setup:browser"] : [],
6892
+ ...blueprint.setup.includes("browser") ? ["npm run test:setup:browser"] : [],
6130
6893
  ...blueprint.skills ? ["npm run test:skills"] : [],
6131
6894
  ...blueprint.guides ? ["npm run test:guides"] : [],
6132
6895
  ...blueprint.conformance ? ["npm run test:conformance"] : [],
6896
+ ...blueprint.tree ? ["npm run test:tree"] : [],
6133
6897
  ...integrates ? ["npm run test:integration"] : [],
6134
6898
  ...!publishes && blueprint.studies ? ["npm run test:studies"] : [],
6135
6899
  ...!publishes && blueprint.service ? ["npm run test:service"] : []
@@ -6158,7 +6922,7 @@ function blueprintToScripts(blueprint) {
6158
6922
  "test:policy": `${vitest} --project policy`,
6159
6923
  "test:config": `${vitest} --project config`,
6160
6924
  ...blueprint.setup.includes("node") || blueprint.global ? { "test:setup": `${vitest} --project setup` } : {},
6161
- ...blueprint.setup.includes("browser") || targets.length > 0 ? { "test:setup:browser": `${vitest} --project setup:browser` } : {},
6925
+ ...blueprint.setup.includes("browser") ? { "test:setup:browser": `${vitest} --project setup:browser` } : {},
6162
6926
  ...blueprint.journey && blueprint.app.includes("browser") ? {
6163
6927
  "test:journey": journey,
6164
6928
  ...Object.fromEntries(application.map((name) => [`test:journey:${name}`, `${journey} --mode ${name}`]))
@@ -6166,6 +6930,7 @@ function blueprintToScripts(blueprint) {
6166
6930
  ...blueprint.skills ? { "test:skills": `${vitest} --project skills` } : {},
6167
6931
  ...blueprint.guides ? { "test:guides": `node --experimental-strip-types ${GUIDES_TEST_PATH}` } : {},
6168
6932
  ...blueprint.conformance ? { "test:conformance": `${vitest} --project conformance` } : {},
6933
+ ...blueprint.tree ? { "test:tree": `${vitest} --project tree` } : {},
6169
6934
  "test:probe": "vitest run --config vite.config.ts --no-cache --reporter=verbose --project probe",
6170
6935
  "test:bench": "vitest bench --config vite.config.ts --no-cache --project probe",
6171
6936
  ...publishes ? { "test:distribution": `${vitest} --project distribution` } : {},
@@ -6351,7 +7116,7 @@ function blueprintToManifest(blueprint) {
6351
7116
  type: "git",
6352
7117
  url: `git+https://github.com/orkestrel/${blueprint.name}.git`
6353
7118
  } } : {},
6354
- ...blueprint.bin ? { bin: { [blueprint.name]: "./dist/bin/main.js" } } : {},
7119
+ ...blueprint.bin ? { bin: { [blueprint.name]: BIN_OUTPUT_PATH } } : {},
6355
7120
  files: [
6356
7121
  blueprint.bin || publishes ? "dist/src" : "dist/app",
6357
7122
  ...blueprint.bin ? ["dist/bin"] : [],
@@ -6362,7 +7127,7 @@ function blueprintToManifest(blueprint) {
6362
7127
  ],
6363
7128
  type: "module",
6364
7129
  ...publishes ? {
6365
- sideEffects: targets.length > 0 || blueprint.bin ? [...targets.length > 0 ? ["**/*.css", "**/*.scss"] : [], ...blueprint.bin ? [`./${BIN_ENTRY_PATH}`, "./dist/bin/main.js"] : []] : false,
7130
+ sideEffects: targets.length > 0 || blueprint.bin ? [...targets.length > 0 ? ["**/*.css", "**/*.scss"] : [], ...blueprint.bin ? [`./${BIN_ENTRY_PATH}`, `./${BIN_OUTPUT_PATH}`] : []] : false,
6366
7131
  ...blueprint.src.length > 0 ? entry : {},
6367
7132
  exports: blueprintToExports(blueprint),
6368
7133
  publishConfig: { access: "public" }
@@ -6513,10 +7278,11 @@ function blueprintToProjects(blueprint) {
6513
7278
  "policy",
6514
7279
  "config",
6515
7280
  ...blueprint.setup.includes("node") || blueprint.global ? ["setup"] : [],
6516
- ...blueprint.setup.includes("browser") || styled ? ["setup:browser"] : [],
7281
+ ...blueprint.setup.includes("browser") ? ["setup:browser"] : [],
6517
7282
  ...blueprint.guides ? ["guides"] : [],
6518
7283
  ...blueprint.skills ? ["skills"] : [],
6519
7284
  ...blueprint.conformance ? ["conformance"] : [],
7285
+ ...blueprint.tree ? ["tree"] : [],
6520
7286
  ...blueprint.service ? ["service"] : [],
6521
7287
  ...blueprint.studies ? ["studies"] : [],
6522
7288
  ...blueprint.src.length > 0 || styled ? ["distribution"] : [],
@@ -6582,13 +7348,10 @@ function blueprintToRootVite(blueprint) {
6582
7348
  const styled = sheets.length > 0 || blueprint.themes;
6583
7349
  const global = blueprint.global ? " globalSetup: ['./tests/setupGlobal.ts'],\n" : "";
6584
7350
  const imports = [
7351
+ ...styled || machinery.showcase ? [`import { ${[...styled ? ["existsSync"] : [], ...machinery.showcase ? ["renameSync"] : []].join(", ")} } from 'node:fs'`] : [],
6585
7352
  ...machinery.browser ? ["import { playwright } from '@vitest/browser-playwright'"] : [],
6586
7353
  ...machinery.frameworks.includes("vue") ? ["import vue from '@vitejs/plugin-vue'"] : [],
6587
- ...machinery.showcase ? [
6588
- "import { viteSingleFile } from 'vite-plugin-singlefile'",
6589
- "import { renameSync } from 'node:fs'",
6590
- "import { resolve as resolvePath } from 'node:path'"
6591
- ] : []
7354
+ ...machinery.showcase ? ["import { viteSingleFile } from 'vite-plugin-singlefile'", "import { resolve as resolvePath } from 'node:path'"] : []
6592
7355
  ];
6593
7356
  const external = "external: resolveSourceExternal,";
6594
7357
  const factories = [
@@ -6651,6 +7414,7 @@ function blueprintToRootVite(blueprint) {
6651
7414
  ...planned.has("guides") ? [CONFIG_TEMPLATES.factories.guides] : [],
6652
7415
  ...planned.has("skills") ? [CONFIG_TEMPLATES.factories.skills] : [],
6653
7416
  ...planned.has("conformance") ? [CONFIG_TEMPLATES.factories.conformance] : [],
7417
+ ...planned.has("tree") ? [CONFIG_TEMPLATES.factories.tree] : [],
6654
7418
  ...planned.has("service") ? [CONFIG_TEMPLATES.factories.service] : [],
6655
7419
  ...planned.has("studies") ? [CONFIG_TEMPLATES.factories.studies] : [],
6656
7420
  ...planned.has("distribution") ? [CONFIG_TEMPLATES.factories.distribution] : [],
@@ -6675,6 +7439,7 @@ function blueprintToRootVite(blueprint) {
6675
7439
  ...planned.has("guides") ? ["guides"] : [],
6676
7440
  ...planned.has("skills") ? ["skills"] : [],
6677
7441
  ...planned.has("conformance") ? ["conformance"] : [],
7442
+ ...planned.has("tree") ? ["tree"] : [],
6678
7443
  ...planned.has("service") ? ["service"] : [],
6679
7444
  ...planned.has("studies") ? ["studies"] : [],
6680
7445
  ...planned.has("distribution") ? ["distribution"] : [],
@@ -7040,12 +7805,12 @@ function blueprintToSourceArtifacts(blueprint) {
7040
7805
  * path. `studies` emits nothing: the root configuration names no study harness,
7041
7806
  * so `tests/setupStudy.ts` is the package's own module.
7042
7807
  *
7043
- * The distribution proof is emitted, and the same test separates it from those
7044
- * two: its subject is the packed tarball rather than anything only the package
7045
- * knows, so every assertion derives from the installed tree at run time and
7046
- * nothing has to be named. It follows the published source it packs, and it is
7047
- * the one artifact here claimed by presence: a target lacking it reports as
7048
- * drift, and a package that replaced it with a better proof keeps that proof.
7808
+ * The content-owned distribution harness `tests/setupDistribution.ts` and the presence-owned
7809
+ * proof `tests/distribution.test.ts` are emitted because the proof measures the packed tarball
7810
+ * rather than anything only the package knows. Every assertion derives from the installed tree
7811
+ * at run time, so nothing has to be named. The proof follows the published source it packs and
7812
+ * alone is claimed by presence: a target lacking the proof reports as drift, and a package that
7813
+ * replaced the proof with a better one keeps that proof.
7049
7814
  *
7050
7815
  * @example
7051
7816
  * ```ts
@@ -7091,8 +7856,7 @@ function blueprintToTestArtifacts(blueprint) {
7091
7856
  origin: "template",
7092
7857
  content: (0, _orkestrel_template.fillTemplate)(ARTIFACT_TEMPLATES.tests.sheet, {
7093
7858
  name,
7094
- root: `${tests}../`,
7095
- setup: `${tests}setupStyles.js`
7859
+ root: `${tests}../`
7096
7860
  })
7097
7861
  };
7098
7862
  });
@@ -7104,7 +7868,7 @@ function blueprintToTestArtifacts(blueprint) {
7104
7868
  environment: "browser",
7105
7869
  content: blueprint.journey ? ARTIFACT_TEMPLATES.tests.browser : ARTIFACT_TEMPLATES.tests.setup
7106
7870
  }] : [];
7107
- const servers = blueprint.src.includes("server") || blueprint.app.includes("server") || blueprint.bin || blueprint.conformance ? [{
7871
+ const servers = blueprint.src.includes("server") || blueprint.app.includes("server") || blueprint.bin || blueprint.conformance || blueprint.tree ? [{
7108
7872
  path: "tests/setupServer.ts",
7109
7873
  group: "tests",
7110
7874
  ownership: "birth",
@@ -7179,20 +7943,28 @@ function blueprintToTestArtifacts(blueprint) {
7179
7943
  })
7180
7944
  })).toArray();
7181
7945
  const distribution = ARTIFACT_TEMPLATES.tests.distribution;
7182
- const distributions = blueprint.src.length > 0 || blueprintToSheets(blueprint).length > 0 || blueprint.themes ? [blueprint.src.includes("browser")].map((browser) => ({
7183
- path: DISTRIBUTION_TEST_PATH,
7946
+ const distributions = blueprint.src.length > 0 || blueprintToSheets(blueprint).length > 0 || blueprint.themes ? [blueprint.src.includes("browser")].flatMap((browser) => [{
7947
+ path: DISTRIBUTION_SETUP_PATH,
7184
7948
  group: "tests",
7185
- ownership: "presence",
7949
+ ownership: "content",
7186
7950
  origin: "template",
7187
- content: (0, _orkestrel_template.fillTemplate)(distribution.proof, {
7951
+ content: (0, _orkestrel_template.fillTemplate)(distribution.module, {
7188
7952
  types: browser ? distribution.types : "",
7189
7953
  transport: browser ? distribution.transport : "",
7190
7954
  launcher: browser ? distribution.launcher : "",
7191
- helpers: browser ? distribution.helpers : "",
7955
+ helpers: browser ? distribution.helpers : ""
7956
+ })
7957
+ }, {
7958
+ path: DISTRIBUTION_TEST_PATH,
7959
+ group: "tests",
7960
+ ownership: "presence",
7961
+ origin: "template",
7962
+ content: (0, _orkestrel_template.fillTemplate)(distribution.proof, {
7963
+ import: browser ? distribution.import : "",
7192
7964
  drive: browser ? distribution.drive : "",
7193
7965
  guard: browser ? "" : distribution.guard
7194
7966
  })
7195
- })) : [];
7967
+ }]) : [];
7196
7968
  const integrations = blueprint.integration ? [[...Iterator.from(blueprint.src).map((environment) => ({
7197
7969
  entry: environment === "core" ? "srcCore" : environment === "browser" ? "srcBrowser" : "srcServer",
7198
7970
  specifier: `@src/${environment}`
@@ -7227,7 +7999,7 @@ function blueprintToTestArtifacts(blueprint) {
7227
7999
  content: ARTIFACT_TEMPLATES.tests.setup
7228
8000
  },
7229
8001
  ...faces,
7230
- ...styles,
8002
+ ...styles.filter(({ content }) => content.length > 0),
7231
8003
  ...sheetTests,
7232
8004
  ...browsers,
7233
8005
  ...servers,
@@ -8385,13 +9157,14 @@ function createBlueprint(name, input) {
8385
9157
  peers: input?.peers ?? [],
8386
9158
  extras: input?.extras ?? [],
8387
9159
  version: input?.version ?? "0.0.1",
8388
- engines: input?.engines ?? DEFAULT_ENGINES,
9160
+ engines: input?.engines ?? ">=22.18.0",
8389
9161
  overrides: input?.overrides ?? [],
8390
9162
  bin: input?.bin ?? false,
8391
9163
  setup: input?.setup ?? [],
8392
9164
  guides: input?.guides ?? false,
8393
9165
  integration: input?.integration ?? false,
8394
9166
  conformance: input?.conformance ?? false,
9167
+ tree: input?.tree ?? false,
8395
9168
  service: input?.service ?? false,
8396
9169
  vendors: input?.vendors ?? [],
8397
9170
  studies: input?.studies ?? false,
@@ -8714,6 +9487,7 @@ exports.AXES = AXES;
8714
9487
  exports.BASE_DEV_DEPENDENCIES = BASE_DEV_DEPENDENCIES;
8715
9488
  exports.BIN_CONFIGS = BIN_CONFIGS;
8716
9489
  exports.BIN_ENTRY_PATH = BIN_ENTRY_PATH;
9490
+ exports.BIN_OUTPUT_PATH = BIN_OUTPUT_PATH;
8717
9491
  exports.BROWSE_DEV_DEPENDENCIES = BROWSE_DEV_DEPENDENCIES;
8718
9492
  exports.BROWSE_UPSTREAM = BROWSE_UPSTREAM;
8719
9493
  exports.CANON_PATHS = CANON_PATHS;
@@ -8728,6 +9502,7 @@ exports.DECLARATION_DEV_DEPENDENCIES = DECLARATION_DEV_DEPENDENCIES;
8728
9502
  exports.DEFAULT_ENGINES = DEFAULT_ENGINES;
8729
9503
  exports.DEFAULT_VERSION = DEFAULT_VERSION;
8730
9504
  exports.DEPENDENCY_NAME_PATTERN = DEPENDENCY_NAME_PATTERN;
9505
+ exports.DISTRIBUTION_SETUP_PATH = DISTRIBUTION_SETUP_PATH;
8731
9506
  exports.DISTRIBUTION_TEST_PATH = DISTRIBUTION_TEST_PATH;
8732
9507
  exports.ENGINES_PATTERN = ENGINES_PATTERN;
8733
9508
  exports.ENVIRONMENTS = ENVIRONMENTS;
@@ -8791,6 +9566,7 @@ exports.TAB_WIDTH = TAB_WIDTH;
8791
9566
  exports.TARGET_SKILL_NAMES = TARGET_SKILL_NAMES;
8792
9567
  exports.THEMES_BARREL_PATH = THEMES_BARREL_PATH;
8793
9568
  exports.THEMES_ENTRY_PATH = THEMES_ENTRY_PATH;
9569
+ exports.TREE_TEST_PATH = TREE_TEST_PATH;
8794
9570
  exports.VERSION_PATTERN = VERSION_PATTERN;
8795
9571
  exports.WORKSPACE_DEV_ENGINES = WORKSPACE_DEV_ENGINES;
8796
9572
  exports.WORKSPACE_OWNED_PATHS = WORKSPACE_OWNED_PATHS;