@orkestrel/scaffold 0.0.102 → 0.0.103

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.
@@ -311,12 +311,9 @@ Build/check config alignment:
311
311
 
312
312
  - Typechecker: `vue-tsc` only where Vue SFCs are checked; `tsc` elsewhere.
313
313
  - Linter: Oxlint with `.oxlintrc.json`, independent from typechecking.
314
- - Place caller-selected local build inspection in `tools/artifacts/` or
315
- `.orkestrel/<package>/instruments/**/tools/artifacts/`, and published runtime artifact
316
- loaders in `src/server/artifacts/`. Permit computed ESM imports at those boundaries in
317
- `.js`, `.mjs`, `.ts`, and `.mts` modules, and keep ordinary implementation dependencies
318
- statically named. A source adapter admitted by a runtime loader remains a separately
319
- selected inventory; it does not widen the loader's built-package admission.
314
+ - Permit computed `import()` in every module, and refuse dynamic `require`. Name ordinary
315
+ implementation dependencies statically. In a module that imports a computed specifier,
316
+ document what selects it in the module's TSDoc.
320
317
  - Formatter: Oxfmt with `.oxfmtrc.json`.
321
318
  - Bundler: Vite.
322
319
  - Tests: Vitest; `@vitest/browser-playwright` for browser projects.
@@ -911,9 +911,8 @@ export function declarationRollup(options: DeclarationRollupOptions): Plugin {
911
911
  ])
912
912
  const entry = resolvePath(scratch, relative(scope.root, declaration))
913
913
  // A literal `import()` of the extractor reddens `tsc` in a workspace that does not
914
- // install it, and a variable specifier reddens `import/no-dynamic-require`, so the
915
- // literal `createRequire` call is the form that clears every gate in an app-only
916
- // workspace.
914
+ // install it, so the literal `createRequire` call is the form that clears the
915
+ // typecheck in an app-only workspace.
917
916
  const loaded: unknown = load('@microsoft/api-extractor')
918
917
  if (!isExtractorModule(loaded)) {
919
918
  throw new Error(
@@ -999,19 +998,8 @@ export async function environmentAssetSources(
999
998
  : specifier.type === 'TemplateLiteral' && specifier.expressions.length === 0
1000
999
  ? specifier.quasis.map((quasi) => quasi.value.cooked ?? quasi.value.raw).join('')
1001
1000
  : undefined
1002
- if (value === undefined) {
1003
- const location = workspacePath(path)
1004
- if (
1005
- location !== undefined &&
1006
- /^(?:src\/server\/artifacts\/|tools\/artifacts\/|\.orkestrel\/[^/]+\/instruments\/(?:[^/]+\/)*tools\/artifacts\/).+\.(?:js|mjs|ts|mts)$/.test(
1007
- location,
1008
- )
1009
- )
1010
- return
1011
- throw new Error(
1012
- '[orkestrel-environment-boundary] Dynamic imports must use static string values',
1013
- )
1014
- }
1001
+ // A computed specifier names no module to inspect statically.
1002
+ if (value === undefined) return
1015
1003
  const decoded = decodeAssetSource(value)
1016
1004
  if (decoded === undefined) {
1017
1005
  throw new Error('[orkestrel-environment-boundary] Module URLs must use valid URI encoding')
@@ -38,7 +38,7 @@
38
38
  ],
39
39
 
40
40
  "import/no-default-export": "error",
41
- "import/no-dynamic-require": ["error", { "esmodule": true }],
41
+ "import/no-dynamic-require": ["error", { "esmodule": false }],
42
42
  "import/extensions": "off",
43
43
  "import/no-unassigned-import": [
44
44
  "error",
@@ -70,16 +70,6 @@
70
70
  "restriction": "off"
71
71
  },
72
72
  "overrides": [
73
- {
74
- "files": [
75
- "src/server/artifacts/**/*.{js,mjs,ts,mts}",
76
- "tools/artifacts/**/*.{js,mjs,ts,mts}",
77
- ".orkestrel/*/instruments/**/tools/artifacts/**/*.{js,mjs,ts,mts}"
78
- ],
79
- "rules": {
80
- "import/no-dynamic-require": ["error", { "esmodule": false }]
81
- }
82
- },
83
73
  {
84
74
  "files": ["*.config.ts", "*.config.js"],
85
75
  "rules": {
@@ -604,7 +604,7 @@
604
604
  "storage": "claude/rules/workspace.md",
605
605
  "destination": ".claude/rules/workspace.md",
606
606
  "executable": false,
607
- "digest": "2d48495981e0fa29c5db11807c64d01e4e463cddb0e45b1345cfa96b34a7e647"
607
+ "digest": "39660cc58ad9173f2947834d2417a36937d1be69b9f87258f4b037e393a5377e"
608
608
  },
609
609
  {
610
610
  "storage": "claude/rules/writing.md",
@@ -772,7 +772,7 @@
772
772
  "storage": "configs/helpers.ts",
773
773
  "destination": "configs/helpers.ts",
774
774
  "executable": false,
775
- "digest": "a830951623b8a216dd2f62776d19b83403c7d13b5bff9a3e9baf6053169dfd7a"
775
+ "digest": "ab778a034b699137d723be586cee9cde2ca806cfec49e20cc97c71b5ca638578"
776
776
  },
777
777
  {
778
778
  "storage": "configs/policy.ts",
@@ -832,7 +832,7 @@
832
832
  "storage": "dotfiles/oxlintrc.json",
833
833
  "destination": ".oxlintrc.json",
834
834
  "executable": false,
835
- "digest": "75c465335e5f14291262b66897e9622f9320f227bcf1b41e864c17459a6d93ea"
835
+ "digest": "58ad7a7bd67ea6f66afc76e17efcc407571bf9bc07d59b09a1db6d757731d4fd"
836
836
  },
837
837
  {
838
838
  "storage": "dotfiles/prettierignore",
@@ -1186,7 +1186,7 @@
1186
1186
  "storage": "tests/config.test.ts",
1187
1187
  "destination": "tests/config.test.ts",
1188
1188
  "executable": false,
1189
- "digest": "325f8de835dd57524e44332b8dce1748d780ac083a05367a994d9190de2c4848"
1189
+ "digest": "6c896b80c309ef15cdf21d01fdf5f3d41dfca9aef800d564531463c800d3fa36"
1190
1190
  },
1191
1191
  {
1192
1192
  "storage": "tests/policy.test.ts",
@@ -1198,7 +1198,7 @@
1198
1198
  "storage": "tests/setupPolicy.ts",
1199
1199
  "destination": "tests/setupPolicy.ts",
1200
1200
  "executable": false,
1201
- "digest": "97de92603cb37f8b5f2981c7f98c2cd856f509b862f6e163a364a7950bf6d03e"
1201
+ "digest": "142d0d4681f0c6b119f99295d8b51c1c2ab4b69b9077cb94f45fb10b93b521b5"
1202
1202
  }
1203
1203
  ],
1204
1204
  "roots": [
@@ -2126,5 +2126,5 @@
2126
2126
  ]
2127
2127
  }
2128
2128
  ],
2129
- "digest": "0b8273c6d80ce1316e405dbc3275e0ce8a505717e415ba767caf791390e58bf0"
2129
+ "digest": "f8bb837441194dffdb3439fc3bd791a31c1af726b3071c8940ace7807d8e4f22"
2130
2130
  }
@@ -70,7 +70,7 @@ import configuration, { resolveWorkspacePath } from '../vite.config.js'
70
70
  import * as rootConfiguration from '../vite.config.js'
71
71
  import tsconfig from '../tsconfig.json' with { type: 'json' }
72
72
  import {
73
- ARTIFACT_IMPORT_CASES,
73
+ COMPUTED_IMPORT_PATHS,
74
74
  collectSheets,
75
75
  collectStudies,
76
76
  collectFrameworks,
@@ -2821,8 +2821,25 @@ createSomething({
2821
2821
  expect(DATA_SOURCE_FILES).not.toContain('plugins.ts')
2822
2822
  })
2823
2823
 
2824
- it('admits computed ESM imports only in artifact loaders while refusing computed require', () => {
2825
- const fixture = createPolicyScratch({ prefix: 'artifact-imports-' })
2824
+ it('pins the global dynamic-require setting to esmodule false with no override touching it', () => {
2825
+ const configured = readConfigRecord(
2826
+ JSON.parse(readFileSync(resolve(POLICY_ROOT, '.oxlintrc.json'), 'utf8')),
2827
+ )
2828
+ expect(readConfigRecord(configured.rules)['import/no-dynamic-require']).toEqual([
2829
+ 'error',
2830
+ { esmodule: false },
2831
+ ])
2832
+ if (!Array.isArray(configured.overrides)) throw new Error('Missing lint overrides')
2833
+ const touching = configured.overrides
2834
+ .map(readConfigRecord)
2835
+ .filter(
2836
+ (override) => readConfigRecord(override.rules)['import/no-dynamic-require'] !== undefined,
2837
+ )
2838
+ expect(touching).toEqual([])
2839
+ })
2840
+
2841
+ it('permits a computed import() and refuses a computed require at every module path', () => {
2842
+ const fixture = createPolicyScratch({ prefix: 'computed-imports-' })
2826
2843
  try {
2827
2844
  fixture.write(
2828
2845
  'configs/policy.ts',
@@ -2831,64 +2848,50 @@ createSomething({
2831
2848
  const configured = readConfigRecord(
2832
2849
  JSON.parse(readFileSync(resolve(POLICY_ROOT, '.oxlintrc.json'), 'utf8')),
2833
2850
  )
2851
+ const required = COMPUTED_IMPORT_PATHS.map((path) => path.replace(/\.(\w+)$/u, '.require.$1'))
2852
+ for (const path of COMPUTED_IMPORT_PATHS) {
2853
+ fixture.write(path, 'const selected = process.argv[2]\nvoid import(selected)\ndebugger\n')
2854
+ }
2855
+ for (const path of required) {
2856
+ fixture.write(path, 'const selected = process.argv[2]\nvoid require(selected)\ndebugger\n')
2857
+ }
2858
+ const paths = [...COMPUTED_IMPORT_PATHS, ...required]
2834
2859
  // Include campaign fixtures even when the workspace's default lint walk ignores them.
2835
2860
  fixture.write('.oxlintrc.json', JSON.stringify({ ...configured, ignorePatterns: [] }))
2836
- const written = ARTIFACT_IMPORT_CASES.map(([path, admitted]) => {
2837
- fixture.write(path, 'const selected = process.argv[2]\nvoid import(selected)\ndebugger\n')
2838
- const required = admitted ? path.replace(/\.(\w+)$/u, '.require.$1') : undefined
2839
- if (required !== undefined) {
2840
- fixture.write(
2841
- required,
2842
- 'const selected = process.argv[2]\nvoid require(selected)\ndebugger\n',
2843
- )
2844
- }
2845
- return { path, required }
2846
- })
2847
- const paths = written.map(({ path }) => path)
2848
- const requires = written.flatMap(({ required }) => (required === undefined ? [] : [required]))
2849
- const codes = readImportDiagnostics(fixture.path, [...paths, ...requires])
2850
- for (const [path, admitted] of ARTIFACT_IMPORT_CASES) {
2861
+ const codes = readImportDiagnostics(fixture.path, paths)
2862
+ for (const path of COMPUTED_IMPORT_PATHS) {
2851
2863
  expect({ path, refused: codes.has('import(no-dynamic-require) ' + path) }).toEqual({
2852
2864
  path,
2853
- refused: !admitted,
2865
+ refused: false,
2854
2866
  })
2855
- expect(codes.has('eslint(no-debugger) ' + path)).toBe(true)
2856
2867
  }
2857
- for (const path of requires) {
2858
- expect(codes.has('import(no-dynamic-require) ' + path)).toBe(true)
2859
- expect(codes.has('eslint(no-debugger) ' + path)).toBe(true)
2868
+ for (const path of required) {
2869
+ expect({ path, refused: codes.has('import(no-dynamic-require) ' + path) }).toEqual({
2870
+ path,
2871
+ refused: true,
2872
+ })
2860
2873
  }
2874
+ // The sentinel proves each fixture was linted, so an unlinted path cannot read as permitted.
2875
+ for (const path of paths) expect(codes.has('eslint(no-debugger) ' + path)).toBe(true)
2861
2876
 
2862
- expect(readConfigRecord(configured.rules)['import/no-dynamic-require']).toEqual([
2863
- 'error',
2864
- { esmodule: true },
2865
- ])
2866
- if (!Array.isArray(configured.overrides)) throw new Error('Missing lint overrides')
2867
- const overrides = configured.overrides.map(readConfigRecord)
2868
- const artifact = overrides.filter(
2869
- (override) => readConfigRecord(override.rules)['import/no-dynamic-require'] !== undefined,
2870
- )
2871
- expect(artifact).toEqual([
2872
- {
2873
- files: [
2874
- 'src/server/artifacts/**/*.{js,mjs,ts,mts}',
2875
- 'tools/artifacts/**/*.{js,mjs,ts,mts}',
2876
- '.orkestrel/*/instruments/**/tools/artifacts/**/*.{js,mjs,ts,mts}',
2877
- ],
2878
- rules: { 'import/no-dynamic-require': ['error', { esmodule: false }] },
2879
- },
2880
- ])
2877
+ // The control restores the ESM setting and must refuse the same computed imports.
2881
2878
  fixture.write(
2882
2879
  '.oxlintrc.json',
2883
2880
  JSON.stringify({
2884
2881
  ...configured,
2885
2882
  ignorePatterns: [],
2886
- overrides: overrides.filter((override) => !artifact.includes(override)),
2883
+ rules: {
2884
+ ...readConfigRecord(configured.rules),
2885
+ 'import/no-dynamic-require': ['error', { esmodule: true }],
2886
+ },
2887
2887
  }),
2888
2888
  )
2889
- const original = readImportDiagnostics(fixture.path, [...paths, ...requires])
2890
- for (const path of [...paths, ...requires]) {
2891
- expect(original.has('import(no-dynamic-require) ' + path)).toBe(true)
2889
+ const strict = readImportDiagnostics(fixture.path, paths)
2890
+ for (const path of paths) {
2891
+ expect({ path, refused: strict.has('import(no-dynamic-require) ' + path) }).toEqual({
2892
+ path,
2893
+ refused: true,
2894
+ })
2892
2895
  }
2893
2896
  } finally {
2894
2897
  fixture.destroy()
@@ -3930,36 +3933,22 @@ describe('configuration helpers', () => {
3930
3933
  )
3931
3934
  })
3932
3935
 
3933
- it('admits computed artifact imports through Vite while retaining literal boundary inspection', async () => {
3934
- for (const [path] of ARTIFACT_IMPORT_CASES.filter(([, admitted]) => admitted)) {
3936
+ it('admits a computed import() through Vite at every module path while collecting literal specifiers', async () => {
3937
+ for (const path of [...COMPUTED_IMPORT_PATHS, '../outside/src/server/load.ts']) {
3935
3938
  await expect(
3936
3939
  configHelpers.environmentAssetSources(
3937
3940
  'void import(process.argv[2])',
3938
3941
  resolve(POLICY_ROOT, path),
3939
3942
  ),
3940
3943
  ).resolves.toEqual([])
3941
- }
3942
- for (const [path] of ARTIFACT_IMPORT_CASES.filter(([, admitted]) => !admitted)) {
3943
3944
  await expect(
3944
3945
  configHelpers.environmentAssetSources(
3945
- 'void import(process.argv[2])',
3946
+ "void import('@src/browser')",
3946
3947
  resolve(POLICY_ROOT, path),
3947
3948
  ),
3948
- ).rejects.toThrow('Dynamic imports must use static string values')
3949
+ ).resolves.toEqual(['@src/browser'])
3949
3950
  }
3950
- await expect(
3951
- configHelpers.environmentAssetSources(
3952
- "void import('@src/browser')",
3953
- resolve(POLICY_ROOT, 'src/server/artifacts/Artifacts.ts'),
3954
- ),
3955
- ).resolves.toEqual(['@src/browser'])
3956
3951
  expect(configHelpers.environmentSourceError('src/server', '@src/browser')).toBeDefined()
3957
- await expect(
3958
- configHelpers.environmentAssetSources(
3959
- 'void import(process.argv[2])',
3960
- resolve(POLICY_ROOT, '../outside/src/server/artifacts/Artifacts.ts'),
3961
- ),
3962
- ).rejects.toThrow('Dynamic imports must use static string values')
3963
3952
  })
3964
3953
 
3965
3954
  it('drives each plugin through its real Vite hooks', async () => {
@@ -4578,35 +4578,24 @@ export function inspectSheetConfiguration(project: unknown, script?: string): re
4578
4578
  ]
4579
4579
  }
4580
4580
 
4581
- /** Lists artifact-loader paths and the computed ESM imports each boundary admits. */
4582
- export const ARTIFACT_IMPORT_CASES: ReadonlyArray<readonly [string, boolean]> = Object.freeze([
4583
- ['src/server/artifacts/Artifacts.ts', true],
4584
- ['src/server/artifacts/nested/inspect.mts', true],
4585
- ['src/server/artifacts/inspect.js', true],
4586
- ['src/server/artifacts/inspect.mjs', true],
4587
- ['src/server/artifacts-lookalike/inspect.ts', false],
4588
- ['src/browser/artifacts/inspect.ts', false],
4589
- ['src/core/artifacts/inspect.ts', false],
4590
- ['app/server/artifacts/inspect.ts', false],
4591
- ['src/server/artifacts/inspect.cts', false],
4592
- ['src/server/artifacts/inspect.cjs', false],
4593
- ['tools/artifacts/inspect.ts', true],
4594
- ['tools/artifacts/nested/inspect.mts', true],
4595
- ['tools/artifacts/inspect.js', true],
4596
- ['tools/artifacts/inspect.mjs', true],
4597
- ['.orkestrel/sample/instruments/tools/artifacts/inspect.ts', true],
4598
- ['.orkestrel/sample/instruments/harness/tools/artifacts/nested/inspect.mts', true],
4599
- ['.orkestrel/sample/instruments/harness/tools/artifacts/inspect.js', true],
4600
- ['.orkestrel/sample/instruments/harness/tools/artifacts/inspect.mjs', true],
4601
- ['src/server/inspect.ts', false],
4602
- ['src/server/tools/artifacts/inspect.ts', false],
4603
- ['configs/inspect.ts', false],
4604
- ['scripts/inspect.ts', false],
4605
- ['.orkestrel/sample/instruments/harness/inspect.ts', false],
4606
- ['tools/artifacts-lookalike/inspect.ts', false],
4607
- ['.orkestrel/sample/instruments/harness/tools/artifacts-lookalike/inspect.ts', false],
4608
- ['tools/artifacts/inspect.cts', false],
4609
- ['tools/artifacts/inspect.cjs', false],
4581
+ /** Lists source, application, test, configuration, script, and campaign paths for uniform computed-import proofs. */
4582
+ export const COMPUTED_IMPORT_PATHS: readonly string[] = Object.freeze([
4583
+ 'src/core/load.ts',
4584
+ 'src/browser/load.ts',
4585
+ 'src/server/load.ts',
4586
+ 'src/server/load.mts',
4587
+ 'src/server/load.js',
4588
+ 'src/server/load.mjs',
4589
+ 'src/server/load.cts',
4590
+ 'src/server/load.cjs',
4591
+ 'app/server/load.ts',
4592
+ 'tests/load.ts',
4593
+ 'tests/src/server/load.test.ts',
4594
+ 'configs/load.ts',
4595
+ 'scripts/load.ts',
4596
+ '.orkestrel/sample/load.ts',
4597
+ '.orkestrel/sample/instruments/harness/load.ts',
4598
+ '.orkestrel/sample/instruments/harness/load.mts',
4610
4599
  ])
4611
4600
 
4612
4601
  /**
@@ -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.102",
7
+ version: "0.0.103",
8
8
  description: "Scaffold workspaces with commands: new, audit, repair, catalog, and overwrite.",
9
9
  keywords: [
10
10
  "audit",
@@ -108,7 +108,7 @@ var package_default = {
108
108
  "@orkestrel/guide": "^0.0.24",
109
109
  "@orkestrel/html": "^0.0.12",
110
110
  "@orkestrel/probe": "^0.0.23",
111
- "@orkestrel/test": "^0.0.26",
111
+ "@orkestrel/test": "^0.0.27",
112
112
  "@types/node": "^26.6.4",
113
113
  "@vitest/browser-playwright": "^4.1.11",
114
114
  "oxfmt": "^0.72.0",