@orkestrel/scaffold 0.0.13 → 0.0.15

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.
@@ -707,7 +707,6 @@ export declare function coreTsconfig(): string;
707
707
  * `configs/src/vite.core.config.ts` — inlines its own `build.lib` /
708
708
  * `rolldownOptions` (core's `srcCore` root export carries no build.lib).
709
709
  *
710
- * @param browser - Whether a declared browser environment enables the shared CSS pipeline.
711
710
  * @returns The core environment `vite.config.ts` file content, newline-terminated.
712
711
  *
713
712
  * @example
@@ -715,7 +714,7 @@ export declare function coreTsconfig(): string;
715
714
  * coreViteConfig().includes('srcCore(') // true
716
715
  * ```
717
716
  */
718
- export declare function coreViteConfig(browser?: boolean): string;
717
+ export declare function coreViteConfig(): string;
719
718
 
720
719
  /**
721
720
  * Validate and return a `Blueprint` from plain data.
@@ -2276,7 +2275,7 @@ export declare function coreViteConfig(browser?: boolean): string;
2276
2275
  export declare function rootViteConfig(src: readonly Environment[], facts?: ViteFacts): string;
2277
2276
 
2278
2277
  /** The devDependency range generated packages pin `@orkestrel/scaffold` at. */
2279
- export declare const SCAFFOLD_RANGE = "^0.0.12";
2278
+ export declare const SCAFFOLD_RANGE = "^0.0.15";
2280
2279
 
2281
2280
  /**
2282
2281
  * Carries a `ScaffoldErrorCode` + optional `context` (AGENTS §12).
@@ -2788,11 +2787,14 @@ export declare function coreViteConfig(browser?: boolean): string;
2788
2787
  * configuration emits the environment-boundary plugin, its module-graph AST
2789
2788
  * audit, and stylesheet rejection, because those enforce owner-independent
2790
2789
  * laws. Only the host-specific pipelines below are selected by the declared
2791
- * environments. `browser` covers everything a declared browser environment
2792
- * needs the CSS pipeline and the Playwright-backed browser test project;
2793
- * `vue` adds the single-file-component, HTML, and development-server
2794
- * machinery an application browser environment needs; `output` adds build
2795
- * output containment, which an application of `core` alone never builds.
2790
+ * environments. `browser` selects the shared root machinery a declared
2791
+ * browser environment needs: CSS analysis and the Playwright-backed browser
2792
+ * test project. Individual `css` configuration belongs only to the
2793
+ * `srcBrowser` and `appBrowser` factories; core and server factories never
2794
+ * inherit it. `vue` adds the single-file-component, HTML, and
2795
+ * development-server machinery an application browser environment needs;
2796
+ * `output` adds build output containment, which an application of `core`
2797
+ * alone never builds.
2796
2798
  */
2797
2799
  export declare interface ViteMachinery {
2798
2800
  readonly browser: boolean;
@@ -707,7 +707,6 @@ export declare function coreTsconfig(): string;
707
707
  * `configs/src/vite.core.config.ts` — inlines its own `build.lib` /
708
708
  * `rolldownOptions` (core's `srcCore` root export carries no build.lib).
709
709
  *
710
- * @param browser - Whether a declared browser environment enables the shared CSS pipeline.
711
710
  * @returns The core environment `vite.config.ts` file content, newline-terminated.
712
711
  *
713
712
  * @example
@@ -715,7 +714,7 @@ export declare function coreTsconfig(): string;
715
714
  * coreViteConfig().includes('srcCore(') // true
716
715
  * ```
717
716
  */
718
- export declare function coreViteConfig(browser?: boolean): string;
717
+ export declare function coreViteConfig(): string;
719
718
 
720
719
  /**
721
720
  * Validate and return a `Blueprint` from plain data.
@@ -2276,7 +2275,7 @@ export declare function coreViteConfig(browser?: boolean): string;
2276
2275
  export declare function rootViteConfig(src: readonly Environment[], facts?: ViteFacts): string;
2277
2276
 
2278
2277
  /** The devDependency range generated packages pin `@orkestrel/scaffold` at. */
2279
- export declare const SCAFFOLD_RANGE = "^0.0.12";
2278
+ export declare const SCAFFOLD_RANGE = "^0.0.15";
2280
2279
 
2281
2280
  /**
2282
2281
  * Carries a `ScaffoldErrorCode` + optional `context` (AGENTS §12).
@@ -2788,11 +2787,14 @@ export declare function coreViteConfig(browser?: boolean): string;
2788
2787
  * configuration emits the environment-boundary plugin, its module-graph AST
2789
2788
  * audit, and stylesheet rejection, because those enforce owner-independent
2790
2789
  * laws. Only the host-specific pipelines below are selected by the declared
2791
- * environments. `browser` covers everything a declared browser environment
2792
- * needs the CSS pipeline and the Playwright-backed browser test project;
2793
- * `vue` adds the single-file-component, HTML, and development-server
2794
- * machinery an application browser environment needs; `output` adds build
2795
- * output containment, which an application of `core` alone never builds.
2790
+ * environments. `browser` selects the shared root machinery a declared
2791
+ * browser environment needs: CSS analysis and the Playwright-backed browser
2792
+ * test project. Individual `css` configuration belongs only to the
2793
+ * `srcBrowser` and `appBrowser` factories; core and server factories never
2794
+ * inherit it. `vue` adds the single-file-component, HTML, and
2795
+ * development-server machinery an application browser environment needs;
2796
+ * `output` adds build output containment, which an application of `core`
2797
+ * alone never builds.
2796
2798
  */
2797
2799
  export declare interface ViteMachinery {
2798
2800
  readonly browser: boolean;
@@ -226,7 +226,7 @@ var DEFAULT_VERSION = "0.0.1";
226
226
  /** The `engines.node` range the `blueprint` builder fills. */
227
227
  var DEFAULT_ENGINES = `>=${MINIMUM_NODE_VERSION}`;
228
228
  /** The devDependency range generated packages pin `@orkestrel/scaffold` at. */
229
- var SCAFFOLD_RANGE = "^0.0.12";
229
+ var SCAFFOLD_RANGE = "^0.0.15";
230
230
  /** Tooling versions shared by scaffold and every generated workspace. */
231
231
  var BASE_DEV_DEPENDENCIES = Object.freeze({
232
232
  "@microsoft/api-extractor": "^7.58.12",
@@ -236,14 +236,14 @@ var BASE_DEV_DEPENDENCIES = Object.freeze({
236
236
  oxfmt: "^0.61.0",
237
237
  oxlint: "^1.76.0",
238
238
  typescript: "^6.0.3",
239
- vite: "^8.1.5",
239
+ vite: "~8.2.0",
240
240
  "vite-plugin-dts": "^5.0.3",
241
241
  vitest: "^4.1.10"
242
242
  });
243
243
  /** Additional development dependency required by a published browser source environment. */
244
244
  var SOURCE_BROWSER_DEV_DEPENDENCIES = Object.freeze({
245
245
  "@vitest/browser-playwright": "^4.1.10",
246
- playwright: "^1.62.0"
246
+ playwright: "^1.62.1"
247
247
  });
248
248
  /** Additional development dependencies required by a private Vue browser application. */
249
249
  var APP_BROWSER_DEV_DEPENDENCIES = Object.freeze({
@@ -5936,7 +5936,7 @@ import { parse as parseVue } from 'vue/compiler-sfc'
5936
5936
  if (isCSSRequest(id)) {
5937
5937
  const config = resolvedConfig
5938
5938
  if (config === undefined) {
5939
- this.error('Environment boundary requires resolved Vite configuration')
5939
+ return this.error('Environment boundary requires resolved Vite configuration')
5940
5940
  }
5941
5941
  const stylesheet = await preprocessCSS(restored, id, config)
5942
5942
  for (const dependency of stylesheet.deps ?? []) {
@@ -5982,7 +5982,9 @@ import { parse as parseVue } from 'vue/compiler-sfc'
5982
5982
  ? undefined
5983
5983
  : packageRootOf(packageName, physicalSource)
5984
5984
  if (packageRoot === undefined || !containedPath(packageRoot, physicalSource)) {
5985
- this.error('Resolved dependencies must remain inside their physical package root')
5985
+ return this.error(
5986
+ 'Resolved dependencies must remain inside their physical package root',
5987
+ )
5986
5988
  }
5987
5989
  trustedPackageRoots.add(packageRoot)
5988
5990
  }
@@ -5990,7 +5992,7 @@ import { parse as parseVue } from 'vue/compiler-sfc'
5990
5992
  }
5991
5993
  const resolvedSource = workspacePath(physicalSource)
5992
5994
  if (resolvedSource === undefined) {
5993
- this.error('Environment modules cannot import files outside the workspace')
5995
+ return this.error('Environment modules cannot import files outside the workspace')
5994
5996
  }
5995
5997
  const assetError = environmentPathError(owner, resolvedSource)
5996
5998
  if (assetError !== undefined) this.error(assetError)
@@ -6019,7 +6021,7 @@ import { parse as parseVue } from 'vue/compiler-sfc'
6019
6021
  )
6020
6022
  const resolvedSource = workspacePath(resolution?.id ?? fallbackSource)
6021
6023
  if (resolvedSource === undefined) {
6022
- this.error('Environment modules cannot import files outside the workspace')
6024
+ return this.error('Environment modules cannot import files outside the workspace')
6023
6025
  }
6024
6026
  const pathError = environmentPathError('app/browser', resolvedSource)
6025
6027
  if (pathError !== undefined) this.error(pathError)
@@ -6037,7 +6039,7 @@ import { parse as parseVue } from 'vue/compiler-sfc'
6037
6039
  if (source === undefined) continue
6038
6040
  const decodedSource = decodeAssetSource(source)
6039
6041
  if (decodedSource === undefined) {
6040
- this.error('Vue block URLs must use valid URI encoding')
6042
+ return this.error('Vue block URLs must use valid URI encoding')
6041
6043
  }
6042
6044
  const normalizedSource = decodedSource.replaceAll('\\\\', '/')
6043
6045
  const sourceError = environmentSourceError('app/browser', normalizedSource)
@@ -6095,7 +6097,7 @@ import { parse as parseVue } from 'vue/compiler-sfc'
6095
6097
  if (isCSSRequest(id)) {
6096
6098
  const config = resolvedConfig
6097
6099
  if (config === undefined) {
6098
- this.error('Environment boundary requires resolved Vite configuration')
6100
+ return this.error('Environment boundary requires resolved Vite configuration')
6099
6101
  }
6100
6102
  const stylesheet = await preprocessCSS(code, id, config)
6101
6103
  for (const dependency of stylesheet.deps ?? []) {
@@ -6141,7 +6143,9 @@ import { parse as parseVue } from 'vue/compiler-sfc'
6141
6143
  ? undefined
6142
6144
  : packageRootOf(packageName, physicalSource)
6143
6145
  if (packageRoot === undefined || !containedPath(packageRoot, physicalSource)) {
6144
- this.error('Resolved dependencies must remain inside their physical package root')
6146
+ return this.error(
6147
+ 'Resolved dependencies must remain inside their physical package root',
6148
+ )
6145
6149
  }
6146
6150
  trustedPackageRoots.add(packageRoot)
6147
6151
  }
@@ -6149,7 +6153,7 @@ import { parse as parseVue } from 'vue/compiler-sfc'
6149
6153
  }
6150
6154
  const resolvedSource = workspacePath(physicalSource)
6151
6155
  if (resolvedSource === undefined) {
6152
- this.error('Environment modules cannot import files outside the workspace')
6156
+ return this.error('Environment modules cannot import files outside the workspace')
6153
6157
  }
6154
6158
  const assetError = environmentPathError(owner, resolvedSource)
6155
6159
  if (assetError !== undefined) this.error(assetError)
@@ -6708,7 +6712,11 @@ ${EXPORT_KEYWORD} function outputBoundary(output: string): Plugin {
6708
6712
  '[orkestrel-output-boundary] Public directories are disabled; every output must come from the audited graph',
6709
6713
  )
6710
6714
  }
6711
- if (output.endsWith('/browser') && config.build.assetsInlineLimit !== 0) {
6715
+ if (
6716
+ output.endsWith('/browser') &&
6717
+ config.build.lib === false &&
6718
+ config.build.assetsInlineLimit !== 0
6719
+ ) {
6712
6720
  throw new Error(
6713
6721
  '[orkestrel-output-boundary] Browser assets must remain external for output auditing',
6714
6722
  )
@@ -7111,7 +7119,7 @@ ${needsVue ? ` configureServer(server) {
7111
7119
  ? packageRootForResolved(physicalResolution)
7112
7120
  : undefined
7113
7121
  if (mappedPackageRoot === undefined) {
7114
- this.error(
7122
+ return this.error(
7115
7123
  'Dependency package imports must resolve inside an exact physical package root',
7116
7124
  )
7117
7125
  }
@@ -7130,7 +7138,7 @@ ${needsVue ? ` configureServer(server) {
7130
7138
  const packageRoot =
7131
7139
  packageName === undefined ? undefined : packageRootOf(packageName, physicalResolution)
7132
7140
  if (packageRoot === undefined || !containedPath(packageRoot, physicalResolution)) {
7133
- this.error('Resolved dependencies must remain inside their physical package root')
7141
+ return this.error('Resolved dependencies must remain inside their physical package root')
7134
7142
  }
7135
7143
  trustedPackageRoots.add(packageRoot)
7136
7144
  }
@@ -7161,7 +7169,7 @@ ${needsVue ? ` configureServer(server) {
7161
7169
  }
7162
7170
  const code = readBoundedFile(physicalImporter, ENVIRONMENT_MODULE_BYTES)
7163
7171
  if (code === undefined) {
7164
- this.error('Dependency module source must be a bounded regular file')
7172
+ return this.error('Dependency module source must be a bounded regular file')
7165
7173
  }
7166
7174
  for (const source of await environmentAssetSources(code, id)) {
7167
7175
  const normalizedSource = source.replaceAll('\\\\', '/')
@@ -7398,7 +7406,7 @@ ${EXPORT_KEYWORD} ${CONST_KEYWORD} ENVIRONMENT_CSS = Object.freeze({
7398
7406
  'value' in rule && rule.value !== null && 'loc' in rule.value
7399
7407
  ? sources[rule.value.loc.source_index]
7400
7408
  : undefined
7401
- if (rule.type !== 'import') return
7409
+ if (rule.type !== 'import' || rule.value === null) return
7402
7410
  const error = stylesheetAssetError(source, rule.value.url)
7403
7411
  if (error !== undefined) {
7404
7412
  throw new Error(\`[orkestrel-environment-boundary] \${error}\`)
@@ -7619,7 +7627,6 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7619
7627
  publicDir: false,
7620
7628
  plugins: [outputBoundary('dist/src/browser'), environmentBoundary('src/browser')],
7621
7629
  build: {
7622
- assetsInlineLimit: 0,
7623
7630
  emptyOutDir: true,
7624
7631
  sourcemap: true,
7625
7632
  minify: false,
@@ -7670,7 +7677,7 @@ ${renderedTest}
7670
7677
  ${EXPORT_KEYWORD} const srcServer = (config?: UserConfig): UserConfig =>
7671
7678
  mergeConfig(
7672
7679
  {
7673
- resolve,${machinery.browser ? "\n css: ENVIRONMENT_CSS," : ""}
7680
+ resolve,
7674
7681
  publicDir: false,
7675
7682
  plugins: [outputBoundary('dist/src/server'), environmentBoundary('src/server')],
7676
7683
  build: {
@@ -7753,7 +7760,6 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7753
7760
  publicDir: false,
7754
7761
  plugins: [outputBoundary('dist/src/browser'), environmentBoundary('src/browser')],
7755
7762
  build: {
7756
- assetsInlineLimit: 0,
7757
7763
  lib: {
7758
7764
  entry: resolveWorkspacePath('src/browser/index.ts'),
7759
7765
  formats: ['es'],
@@ -7798,7 +7804,7 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7798
7804
  ${EXPORT_KEYWORD} const srcServer = (config?: UserConfig): UserConfig =>
7799
7805
  srcCore(
7800
7806
  mergeConfig(
7801
- {${machinery.browser ? "\n css: ENVIRONMENT_CSS," : ""}
7807
+ {
7802
7808
  publicDir: false,
7803
7809
  plugins: [outputBoundary('dist/src/server'), environmentBoundary('src/server')],
7804
7810
  build: {
@@ -7890,7 +7896,7 @@ function applicationViteConfig(src, app, facts = {}) {
7890
7896
  ${EXPORT_KEYWORD} const srcCore = (config?: UserConfig): UserConfig =>
7891
7897
  mergeConfig(
7892
7898
  {
7893
- resolve,${machinery.browser ? "\n css: ENVIRONMENT_CSS," : ""}
7899
+ resolve,
7894
7900
  publicDir: false,
7895
7901
  plugins: [environmentBoundary('src/core')],
7896
7902
  build: { emptyOutDir: true, sourcemap: true, minify: false },
@@ -7918,7 +7924,6 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7918
7924
  publicDir: false,
7919
7925
  plugins: [outputBoundary('dist/src/browser'), environmentBoundary('src/browser')],
7920
7926
  build: {
7921
- assetsInlineLimit: 0,
7922
7927
  emptyOutDir: true,
7923
7928
  sourcemap: true,
7924
7929
  minify: false,
@@ -7980,7 +7985,7 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7980
7985
  ${EXPORT_KEYWORD} const srcServer = (config?: UserConfig): UserConfig =>
7981
7986
  mergeConfig(
7982
7987
  {
7983
- resolve,${machinery.browser ? "\n css: ENVIRONMENT_CSS," : ""}
7988
+ resolve,
7984
7989
  publicDir: false,
7985
7990
  plugins: [outputBoundary('dist/src/server'), environmentBoundary('src/server')],
7986
7991
  build: {
@@ -8014,7 +8019,7 @@ ${EXPORT_KEYWORD} const srcServer = (config?: UserConfig): UserConfig =>
8014
8019
  ${EXPORT_KEYWORD} const appCore = (config?: UserConfig): UserConfig =>
8015
8020
  mergeConfig(
8016
8021
  {
8017
- resolve,${machinery.browser ? "\n css: ENVIRONMENT_CSS," : ""}
8022
+ resolve,
8018
8023
  publicDir: false,
8019
8024
  plugins: [environmentBoundary('app/core')],
8020
8025
  test: {
@@ -8091,7 +8096,7 @@ ${EXPORT_KEYWORD} function appBrowser(...config: readonly never[]): UserConfig {
8091
8096
  ${EXPORT_KEYWORD} const appServer = (config?: UserConfig): UserConfig =>
8092
8097
  mergeConfig(
8093
8098
  {
8094
- resolve,${machinery.browser ? "\n css: ENVIRONMENT_CSS," : ""}
8099
+ resolve,
8095
8100
  publicDir: false,
8096
8101
  plugins: [outputBoundary('dist/app/server'), environmentBoundary('app/server')],
8097
8102
  build: {
@@ -8157,7 +8162,6 @@ function coreTsconfig() {
8157
8162
  * `configs/src/vite.core.config.ts` — inlines its own `build.lib` /
8158
8163
  * `rolldownOptions` (core's `srcCore` root export carries no build.lib).
8159
8164
  *
8160
- * @param browser - Whether a declared browser environment enables the shared CSS pipeline.
8161
8165
  * @returns The core environment `vite.config.ts` file content, newline-terminated.
8162
8166
  *
8163
8167
  * @example
@@ -8165,11 +8169,11 @@ function coreTsconfig() {
8165
8169
  * coreViteConfig().includes('srcCore(') // true
8166
8170
  * ```
8167
8171
  */
8168
- function coreViteConfig(browser = true) {
8172
+ function coreViteConfig() {
8169
8173
  return `import { defineConfig } from 'vite'
8170
8174
  import dts from 'vite-plugin-dts'
8171
8175
  import {
8172
- ${browser ? " ENVIRONMENT_CSS,\n" : ""} environmentBoundary,
8176
+ environmentBoundary,
8173
8177
  outputBoundary,
8174
8178
  srcCore,
8175
8179
  resolveWorkspacePath,
@@ -8177,7 +8181,7 @@ ${browser ? " ENVIRONMENT_CSS,\n" : ""} environmentBoundary,
8177
8181
 
8178
8182
  export default defineConfig(
8179
8183
  srcCore({
8180
- ${browser ? " css: ENVIRONMENT_CSS,\n" : ""} publicDir: false,
8184
+ publicDir: false,
8181
8185
  plugins: [
8182
8186
  outputBoundary('dist/src/core'),
8183
8187
  environmentBoundary('src/core'),
@@ -8466,7 +8470,6 @@ ${browser}
8466
8470
  * ```
8467
8471
  */
8468
8472
  function configArtifacts(spec) {
8469
- const machinery = viteMachinery(spec.src, spec.app, spec.bin);
8470
8473
  const artifacts = [{
8471
8474
  path: "tsconfig.json",
8472
8475
  group: "configs",
@@ -8482,7 +8485,7 @@ function configArtifacts(spec) {
8482
8485
  const row = SRC_MATRIX[environment];
8483
8486
  for (const path of row.configs) {
8484
8487
  const isTsconfig = path.endsWith(".json");
8485
- const content = environment === "core" ? isTsconfig ? coreTsconfig() : coreViteConfig(machinery.browser) : isTsconfig ? srcTsconfig(environment) : srcViteConfig(environment);
8488
+ const content = environment === "core" ? isTsconfig ? coreTsconfig() : coreViteConfig() : isTsconfig ? srcTsconfig(environment) : srcViteConfig(environment);
8486
8489
  artifacts.push({
8487
8490
  path,
8488
8491
  group: "configs",
@@ -8614,24 +8617,20 @@ function paritySpecifiers(spec) {
8614
8617
  for (const environment of spec.app) modules[`@app/${environment}`] = `app/${environment}`;
8615
8618
  const specifierItems = selfSpecifiers.map((specifier) => `'${specifier}'`);
8616
8619
  const inlineSpecifierList = `[${specifierItems.join(", ")}]`;
8617
- return `${EXPORT_KEYWORD} ${CONST_KEYWORD} SELF_SPECIFIERS = ${fitsPrintWidth(`const SELF_SPECIFIERS = ${inlineSpecifierList}`) ? inlineSpecifierList : `[
8618
- ${specifierItems.map((specifier) => `\t${specifier},`).join("\n")}
8619
- ]`}
8620
-
8621
- ${EXPORT_KEYWORD} ${CONST_KEYWORD} SPECIFIER_MODULES: Readonly<Record<string, string>> = {
8622
- ${Object.entries(modules).map(([specifier, module]) => `\t'${specifier}': '${module}',`).join("\n")}
8623
- }
8624
- ${EXPORT_KEYWORD} ${CONST_KEYWORD} SPECIFIER_SOURCES = new Map<string, ReturnType<typeof createSource>>()
8625
- ${EXPORT_KEYWORD} ${FUNCTION_KEYWORD} exportsFor(specifier: string): readonly string[] {
8626
- const module = SPECIFIER_MODULES[specifier]
8627
- if (module === undefined) return []
8628
- let source = SPECIFIER_SOURCES.get(module)
8629
- if (source === undefined) {
8630
- source = createSource({ files: GUIDE_FILES, module })
8631
- SPECIFIER_SOURCES.set(module, source)
8632
- }
8633
- return source.exports().map((symbol) => symbol.name)
8634
- }`;
8620
+ const lines = fitsPrintWidth(`const SELF_SPECIFIERS = ${inlineSpecifierList}`) ? [`${EXPORT_KEYWORD} ${CONST_KEYWORD} SELF_SPECIFIERS = ${inlineSpecifierList}`] : [
8621
+ `${EXPORT_KEYWORD} ${CONST_KEYWORD} SELF_SPECIFIERS = [`,
8622
+ ...specifierItems.map((specifier) => `\t${specifier},`),
8623
+ "]"
8624
+ ];
8625
+ lines.push("", [
8626
+ EXPORT_KEYWORD,
8627
+ CONST_KEYWORD,
8628
+ "SPECIFIER_MODULES:",
8629
+ "Readonly<Record<string, string>>",
8630
+ "=",
8631
+ "{"
8632
+ ].join(" "), ...Object.entries(modules).map(([specifier, module]) => `\t'${specifier}': '${module}',`), "}", `${EXPORT_KEYWORD} ${CONST_KEYWORD} SPECIFIER_SOURCES = new Map<string, ReturnType<typeof createSource>>()`, `${EXPORT_KEYWORD} ${FUNCTION_KEYWORD} exportsFor(specifier: string): readonly string[] {`, " const module = SPECIFIER_MODULES[specifier]", " if (module === undefined) return []", " let source = SPECIFIER_SOURCES.get(module)", " if (source === undefined) {", " source = createSource({ files: GUIDE_FILES, module })", " SPECIFIER_SOURCES.set(module, source)", " }", " return source.exports().map((symbol) => symbol.name)", "}");
8633
+ return lines.join("\n");
8635
8634
  }
8636
8635
  /**
8637
8636
  * Draft the `tests` group's `template` artifacts — the shared recorder
@@ -8652,8 +8651,8 @@ ${EXPORT_KEYWORD} ${FUNCTION_KEYWORD} exportsFor(specifier: string): readonly st
8652
8651
  function testArtifacts(spec, pascal) {
8653
8652
  const hasBrowser = spec.src.includes("browser") || spec.app.includes("browser");
8654
8653
  const hasVue = spec.app.includes("browser");
8655
- const browserPolicySpecifier = hasBrowser ? ", existsSync" : "";
8656
- const browserPolicyImport = hasBrowser ? "import { chromium } from 'playwright'" : "";
8654
+ const browserPolicySpecifier = hasBrowser ? ", accessSync, constants as FS_CONSTANTS, statSync" : "";
8655
+ const browserPolicyImport = hasBrowser ? "import { chromium } from 'playwright'\nimport { resolveChromium } from '../vite.config.js'" : "";
8657
8656
  const vuePolicyImport = hasVue ? "import { parse as parseVue } from 'vue/compiler-sfc'" : "";
8658
8657
  const workspacePolicyAssertion = hasVue ? `expect(
8659
8658
  inspectCodingWorkspace(process.cwd(), (path, content) => {
@@ -8665,12 +8664,13 @@ function testArtifacts(spec, pascal) {
8665
8664
  }),
8666
8665
  ).toEqual([])` : "expect(inspectCodingWorkspace(process.cwd())).toEqual([])";
8667
8666
  const browserPolicyTest = hasBrowser ? `
8668
- it.skipIf(!existsSync(chromium.executablePath()))(
8669
- 'runs browser suites only when the real Chromium executable is installed',
8670
- () => {
8671
- expect(existsSync(chromium.executablePath())).toBe(true)
8672
- },
8673
- )` : "";
8667
+ it('resolves Chromium only to a real executable file', () => {
8668
+ const chromiumPath = resolveChromium(chromium.executablePath())
8669
+ if (chromiumPath === undefined) return
8670
+
8671
+ expect(statSync(chromiumPath).isFile()).toBe(true)
8672
+ expect(() => accessSync(chromiumPath, FS_CONSTANTS.X_OK)).not.toThrow()
8673
+ })` : "";
8674
8674
  const artifacts = [fillArtifact("tests/setup.ts", "tests", "setup", {}), fillArtifact("tests/policy.test.ts", "tests", "policyTest", {
8675
8675
  browserPolicySpecifier,
8676
8676
  browserPolicyImport,