@orkestrel/scaffold 0.0.102 → 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 (89) 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 +35 -28
  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/helpers.ts +4 -16
  57. package/dist/host/configs/policy.ts +13 -2
  58. package/dist/host/dotfiles/editorconfig +0 -1
  59. package/dist/host/dotfiles/gitattributes +0 -1
  60. package/dist/host/dotfiles/gitignore +0 -1
  61. package/dist/host/dotfiles/oxlintrc.json +25 -11
  62. package/dist/host/guides/agent.md +1638 -598
  63. package/dist/host/guides/budget.md +89 -29
  64. package/dist/host/guides/form.md +477 -91
  65. package/dist/host/guides/mcp.md +14 -2
  66. package/dist/host/guides/ollama.md +97 -73
  67. package/dist/host/guides/probe.md +1 -1
  68. package/dist/host/guides/scaffold.md +158 -101
  69. package/dist/host/guides/study.md +2635 -0
  70. package/dist/host/guides/table.md +225 -15
  71. package/dist/host/guides/terminal.md +22 -20
  72. package/dist/host/guides/test.md +689 -255
  73. package/dist/host/manifest.json +88 -64
  74. package/dist/host/tests/config.test.ts +189 -146
  75. package/dist/host/tests/policy.test.ts +39 -1
  76. package/dist/host/tests/setupPolicy.ts +104 -57
  77. package/dist/src/core/index.cjs +1387 -611
  78. package/dist/src/core/index.cjs.map +1 -1
  79. package/dist/src/core/index.d.cts +35 -20
  80. package/dist/src/core/index.d.ts +35 -20
  81. package/dist/src/core/index.js +1385 -612
  82. package/dist/src/core/index.js.map +1 -1
  83. package/dist/src/server/index.cjs +12 -12
  84. package/dist/src/server/index.cjs.map +1 -1
  85. package/dist/src/server/index.d.cts +12 -12
  86. package/dist/src/server/index.d.ts +12 -12
  87. package/dist/src/server/index.js +12 -12
  88. package/dist/src/server/index.js.map +1 -1
  89. package/package.json +4 -4
@@ -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,
@@ -323,16 +323,27 @@ describe('selected faces', () => {
323
323
  }
324
324
  const script =
325
325
  'vite build --config configs/src/vite.styles.config.ts && vite build --config configs/src/vite.themes.config.ts'
326
- expect(inspectSheetConfiguration(project, script)).toEqual([])
327
- expect(
328
- inspectSheetConfiguration(
329
- { test: { ...project.test, setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'] } },
330
- script,
331
- ),
332
- ).toContain('./tests/setupStyles.ts')
333
- expect(
334
- inspectSheetConfiguration(project, script.split(' && ').reverse().join(' && ')),
335
- ).toContain('themes order')
326
+ const scratch = createPolicyScratch({ prefix: 'config-sheet-setup-' })
327
+ const withoutStyles = {
328
+ test: { ...project.test, setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'] },
329
+ }
330
+ try {
331
+ expect(inspectSheetConfiguration(withoutStyles, script, scratch.path)).toEqual([])
332
+ scratch.write('tests/setupStyles.ts', 'export {}\n')
333
+ expect(inspectSheetConfiguration(project, script, scratch.path)).toEqual([])
334
+ expect(inspectSheetConfiguration(withoutStyles, script, scratch.path)).toContain(
335
+ './tests/setupStyles.ts',
336
+ )
337
+ expect(
338
+ inspectSheetConfiguration(
339
+ project,
340
+ script.split(' && ').reverse().join(' && '),
341
+ scratch.path,
342
+ ),
343
+ ).toContain('themes order')
344
+ } finally {
345
+ scratch.destroy()
346
+ }
336
347
  })
337
348
 
338
349
  it('resolves showcase and journey modes for every occupied application', async () => {
@@ -707,19 +718,24 @@ describe('root configuration', () => {
707
718
  )
708
719
  .filter(([, path]) => existsSync(resolve(POLICY_ROOT, path)))
709
720
  .map(([label, , include, setup]): [string, PolicyProject] => [label, { include, setup }]),
710
- ...['policy', 'config', 'guides', 'conformance', 'distribution', 'integration']
711
- .filter((label) => existsSync(resolve(POLICY_ROOT, `tests/${label}.test.ts`)))
721
+ ...['policy', 'config', 'guides', 'conformance', 'tree', 'distribution', 'integration']
722
+ .filter((label) => readdirSync(resolve(POLICY_ROOT, 'tests')).includes(`${label}.test.ts`))
712
723
  .map((label): [string, PolicyProject] => [
713
724
  label,
714
725
  {
715
726
  include: `tests/${label}.test.ts`,
716
727
  setup: [
717
728
  './tests/setup.ts',
718
- ...(label === 'conformance' ? ['./tests/setupServer.ts'] : []),
729
+ ...(label === 'conformance' || label === 'tree' ? ['./tests/setupServer.ts'] : []),
719
730
  ...(label === 'integration' &&
720
731
  (collectSheets(POLICY_ROOT).length > 0 ||
721
732
  existsSync(resolve(POLICY_ROOT, 'src/styles/themes/index.scss')))
722
- ? ['./tests/setupBrowser.ts', './tests/setupStyles.ts']
733
+ ? [
734
+ './tests/setupBrowser.ts',
735
+ ...(existsSync(resolve(POLICY_ROOT, 'tests/setupStyles.ts'))
736
+ ? ['./tests/setupStyles.ts']
737
+ : []),
738
+ ]
723
739
  : []),
724
740
  ],
725
741
  },
@@ -910,8 +926,8 @@ describe('root configuration', () => {
910
926
  // before its result is read. Extra factories are ignored without validating their result shape.
911
927
  expect(extraLoads).toStrictEqual([])
912
928
  for (const [label, project] of expected) expect(configured.get(label)).toStrictEqual(project)
913
- for (const label of ['setup', 'setup:browser']) {
914
- const name = label === 'setup' ? 'setup' : 'setupBrowser'
929
+ for (const label of ['setup', 'setup:browser', 'tree']) {
930
+ const name = label === 'setup:browser' ? 'setupBrowser' : label
915
931
  expect(projects.some((entry) => typeof entry === 'function' && entry.name === name)).toBe(
916
932
  expected.has(label),
917
933
  )
@@ -1281,6 +1297,7 @@ describe('root configuration', () => {
1281
1297
  const distribution = Object.getOwnPropertyDescriptor(scripts, 'test:distribution')?.value
1282
1298
  const integration = Object.getOwnPropertyDescriptor(scripts, 'test:integration')?.value
1283
1299
  const conformance = Object.getOwnPropertyDescriptor(scripts, 'test:conformance')?.value
1300
+ const tree = Object.getOwnPropertyDescriptor(scripts, 'test:tree')?.value
1284
1301
  const service = Object.getOwnPropertyDescriptor(scripts, 'test:service')?.value
1285
1302
  const studies = Object.getOwnPropertyDescriptor(scripts, 'test:studies')?.value
1286
1303
  const publish = Object.getOwnPropertyDescriptor(scripts, 'prepublishOnly')?.value
@@ -1307,6 +1324,7 @@ describe('root configuration', () => {
1307
1324
  expect(registered.has('config')).toBe(true)
1308
1325
  expect(registered.has('control')).toBe(false)
1309
1326
  const hasConformance = registered.has('conformance')
1327
+ const hasTree = registered.has('tree')
1310
1328
  const hasDistribution = registered.has('distribution')
1311
1329
  const hasService = registered.has('service')
1312
1330
  const hasStudies = registered.has('studies')
@@ -1349,6 +1367,13 @@ describe('root configuration', () => {
1349
1367
  expect(typeof test === 'string' && test.includes('npm run test:conformance')).toBe(
1350
1368
  hasConformance,
1351
1369
  )
1370
+ expect(tree).toBe(
1371
+ hasTree
1372
+ ? 'vitest run --config vite.config.ts --no-cache --reporter=dot --project tree'
1373
+ : undefined,
1374
+ )
1375
+ expect(typeof test === 'string' && test.includes('npm run test:tree')).toBe(hasTree)
1376
+ expect(typeof publish === 'string' && publish.includes('npm run test:tree')).toBe(false)
1352
1377
  expect(service).toBe(
1353
1378
  hasService
1354
1379
  ? 'vitest run --config vite.config.ts --no-cache --reporter=dot --project service'
@@ -2821,8 +2846,25 @@ createSomething({
2821
2846
  expect(DATA_SOURCE_FILES).not.toContain('plugins.ts')
2822
2847
  })
2823
2848
 
2824
- it('admits computed ESM imports only in artifact loaders while refusing computed require', () => {
2825
- const fixture = createPolicyScratch({ prefix: 'artifact-imports-' })
2849
+ it('pins the global dynamic-require setting to esmodule false with no override touching it', () => {
2850
+ const configured = readConfigRecord(
2851
+ JSON.parse(readFileSync(resolve(POLICY_ROOT, '.oxlintrc.json'), 'utf8')),
2852
+ )
2853
+ expect(readConfigRecord(configured.rules)['import/no-dynamic-require']).toEqual([
2854
+ 'error',
2855
+ { esmodule: false },
2856
+ ])
2857
+ if (!Array.isArray(configured.overrides)) throw new Error('Missing lint overrides')
2858
+ const touching = configured.overrides
2859
+ .map(readConfigRecord)
2860
+ .filter(
2861
+ (override) => readConfigRecord(override.rules)['import/no-dynamic-require'] !== undefined,
2862
+ )
2863
+ expect(touching).toEqual([])
2864
+ })
2865
+
2866
+ it('permits a computed import() and refuses a computed require at every module path', () => {
2867
+ const fixture = createPolicyScratch({ prefix: 'computed-imports-' })
2826
2868
  try {
2827
2869
  fixture.write(
2828
2870
  'configs/policy.ts',
@@ -2831,64 +2873,50 @@ createSomething({
2831
2873
  const configured = readConfigRecord(
2832
2874
  JSON.parse(readFileSync(resolve(POLICY_ROOT, '.oxlintrc.json'), 'utf8')),
2833
2875
  )
2876
+ const required = COMPUTED_IMPORT_PATHS.map((path) => path.replace(/\.(\w+)$/u, '.require.$1'))
2877
+ for (const path of COMPUTED_IMPORT_PATHS) {
2878
+ fixture.write(path, 'const selected = process.argv[2]\nvoid import(selected)\ndebugger\n')
2879
+ }
2880
+ for (const path of required) {
2881
+ fixture.write(path, 'const selected = process.argv[2]\nvoid require(selected)\ndebugger\n')
2882
+ }
2883
+ const paths = [...COMPUTED_IMPORT_PATHS, ...required]
2834
2884
  // Include campaign fixtures even when the workspace's default lint walk ignores them.
2835
2885
  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) {
2886
+ const codes = readImportDiagnostics(fixture.path, paths)
2887
+ for (const path of COMPUTED_IMPORT_PATHS) {
2851
2888
  expect({ path, refused: codes.has('import(no-dynamic-require) ' + path) }).toEqual({
2852
2889
  path,
2853
- refused: !admitted,
2890
+ refused: false,
2854
2891
  })
2855
- expect(codes.has('eslint(no-debugger) ' + path)).toBe(true)
2856
2892
  }
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)
2893
+ for (const path of required) {
2894
+ expect({ path, refused: codes.has('import(no-dynamic-require) ' + path) }).toEqual({
2895
+ path,
2896
+ refused: true,
2897
+ })
2860
2898
  }
2899
+ // The sentinel proves each fixture was linted, so an unlinted path cannot read as permitted.
2900
+ for (const path of paths) expect(codes.has('eslint(no-debugger) ' + path)).toBe(true)
2861
2901
 
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
- ])
2902
+ // The control restores the ESM setting and must refuse the same computed imports.
2881
2903
  fixture.write(
2882
2904
  '.oxlintrc.json',
2883
2905
  JSON.stringify({
2884
2906
  ...configured,
2885
2907
  ignorePatterns: [],
2886
- overrides: overrides.filter((override) => !artifact.includes(override)),
2908
+ rules: {
2909
+ ...readConfigRecord(configured.rules),
2910
+ 'import/no-dynamic-require': ['error', { esmodule: true }],
2911
+ },
2887
2912
  }),
2888
2913
  )
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)
2914
+ const strict = readImportDiagnostics(fixture.path, paths)
2915
+ for (const path of paths) {
2916
+ expect({ path, refused: strict.has('import(no-dynamic-require) ' + path) }).toEqual({
2917
+ path,
2918
+ refused: true,
2919
+ })
2892
2920
  }
2893
2921
  } finally {
2894
2922
  fixture.destroy()
@@ -2913,72 +2941,89 @@ createSomething({
2913
2941
  const pattern = readConfigRecord(patternValue)
2914
2942
  const message = pattern.message
2915
2943
  if (typeof message !== 'string') throw new Error('Missing pattern message')
2916
- const listed: ReadonlyArray<readonly [string, boolean]> = message.includes('URL schemes')
2917
- ? [
2918
- ['https://host/x', true],
2919
- ['data:text/plain,x', true],
2920
- ['node:fs', false],
2921
- ['n:entry', true],
2922
- ['no:entry', true],
2923
- ['nod:entry', true],
2924
- ['nodea:entry', true],
2925
- ['1bad:entry', false],
2926
- ['./data:entry', false],
2927
- ]
2928
- : message.includes('noncanonical dot')
2944
+ const alias = /@src\/(core|browser|server) alias/u.exec(message)?.[1]
2945
+ const listed: ReadonlyArray<readonly [string, boolean]> =
2946
+ alias !== undefined
2929
2947
  ? [
2930
- ['../core/../server/index.js', true],
2931
- ['../core/./index.js', true],
2932
- ['../core/index.js', false],
2933
- ['./index.js', false],
2934
- ['../../core/index.js', false],
2935
- ['.../../index.js', true],
2936
- ['.name/../index.js', true],
2948
+ [`../${alias}/index.js`, true],
2949
+ [`../../${alias}/types.js`, true],
2950
+ [`../../src/${alias}/index.js`, true],
2951
+ [`../${alias}`, true],
2952
+ [`../${alias}/`, true],
2953
+ [`../${alias}?raw`, true],
2954
+ [`../${alias}#fragment`, true],
2955
+ [`@src/${alias}`, false],
2956
+ [`./${alias}/index.js`, false],
2957
+ [`../${alias}x/index.js`, false],
2958
+ [`../${alias}.ext/index.js`, false],
2937
2959
  ]
2938
- : message.includes('sibling sheet')
2960
+ : message.includes('URL schemes')
2939
2961
  ? [
2940
- ['@src/print', true],
2941
- ['../print/index.js', true],
2942
- ['@src/core', false],
2943
- ['@src/browser', false],
2944
- ['@src/vue', false],
2945
- ['@app/core', false],
2946
- ['@app/browser', false],
2947
- ['@src/corex', true],
2948
- ['@src/', true],
2949
- ['../src/print/index.js', true],
2950
- ['../browser?x', true],
2951
- ['../print.ext/index.js', false],
2952
- ...(Array.isArray(block.files) &&
2953
- block.files.some(
2954
- (file: unknown) => typeof file === 'string' && file.startsWith('app/vue/'),
2955
- )
2956
- ? [['@app/print', true] as const]
2957
- : []),
2958
- ]
2959
- : [
2960
- [
2961
- message.includes('absolute paths')
2962
- ? '/machine/module.js'
2963
- : message.includes('normalized traversal')
2964
- ? './../core/index.js'
2965
- : message.includes('forward slashes')
2966
- ? '..\\core\\index.js'
2967
- : message.includes('compiler API')
2968
- ? 'typescript'
2969
- : message.includes('private app')
2970
- ? '@app/core'
2971
- : message.includes('stylesheets')
2972
- ? './index.css'
2973
- : message.includes('host-independent') ||
2974
- message.includes('Node or server')
2975
- ? 'node:fs'
2976
- : message.includes('Vue extension')
2977
- ? '@src/vue'
2978
- : '@src/browser',
2979
- true,
2980
- ],
2962
+ ['https://host/x', true],
2963
+ ['data:text/plain,x', true],
2964
+ ['node:fs', false],
2965
+ ['n:entry', true],
2966
+ ['no:entry', true],
2967
+ ['nod:entry', true],
2968
+ ['nodea:entry', true],
2969
+ ['1bad:entry', false],
2970
+ ['./data:entry', false],
2981
2971
  ]
2972
+ : message.includes('noncanonical dot')
2973
+ ? [
2974
+ ['../core/../server/index.js', true],
2975
+ ['../core/./index.js', true],
2976
+ ['../core/index.js', false],
2977
+ ['./index.js', false],
2978
+ ['../../core/index.js', false],
2979
+ ['.../../index.js', true],
2980
+ ['.name/../index.js', true],
2981
+ ]
2982
+ : message.includes('sibling sheet')
2983
+ ? [
2984
+ ['@src/print', true],
2985
+ ['../print/index.js', true],
2986
+ ['@src/core', false],
2987
+ ['@src/browser', false],
2988
+ ['@src/vue', false],
2989
+ ['@app/core', false],
2990
+ ['@app/browser', false],
2991
+ ['@src/corex', true],
2992
+ ['@src/', true],
2993
+ ['../src/print/index.js', true],
2994
+ ['../browser?x', true],
2995
+ ['../print.ext/index.js', false],
2996
+ ...(Array.isArray(block.files) &&
2997
+ block.files.some(
2998
+ (file: unknown) =>
2999
+ typeof file === 'string' && file.startsWith('app/vue/'),
3000
+ )
3001
+ ? [['@app/print', true] as const]
3002
+ : []),
3003
+ ]
3004
+ : [
3005
+ [
3006
+ message.includes('absolute paths')
3007
+ ? '/machine/module.js'
3008
+ : message.includes('normalized traversal')
3009
+ ? './../core/index.js'
3010
+ : message.includes('forward slashes')
3011
+ ? '..\\core\\index.js'
3012
+ : message.includes('compiler API')
3013
+ ? 'typescript'
3014
+ : message.includes('private app')
3015
+ ? '@app/core'
3016
+ : message.includes('stylesheets')
3017
+ ? './index.css'
3018
+ : message.includes('host-independent') ||
3019
+ message.includes('Node or server')
3020
+ ? 'node:fs'
3021
+ : message.includes('Vue extension')
3022
+ ? '@src/vue'
3023
+ : '@src/browser',
3024
+ true,
3025
+ ],
3026
+ ]
2982
3027
  const face =
2983
3028
  message.includes('another styles face') && typeof pattern.regex === 'string'
2984
3029
  ? /@src\/(bootstrap|tailwindcss|styles)\(/u.exec(pattern.regex)?.[1]
@@ -3132,21 +3177,34 @@ createSomething({
3132
3177
  ]),
3133
3178
  ]
3134
3179
  : []),
3180
+ ...(['src/browser', 'src/server', 'src/vue', 'src/bin'].includes(owner)
3181
+ ? ['../core/index.js', '../../src/core/index.js']
3182
+ : []),
3183
+ ...(owner === 'src/vue' ? ['../browser/index.js', '../../src/browser/index.js'] : []),
3184
+ ...(owner === 'src/bin' ? ['../server/index.js', '../../src/server/index.js'] : []),
3135
3185
  ]
3136
3186
  const admitted = [
3137
3187
  ...(owner.endsWith('/vue')
3138
3188
  ? [
3139
3189
  '@src/core',
3140
3190
  '@src/browser',
3141
- '../core/index.js',
3142
- '../browser/index.js',
3143
3191
  'vue',
3144
3192
  '@vue/runtime-core',
3145
3193
  ...(owner.startsWith('app/')
3146
- ? ['@app/core', '@app/browser', '@src/vue', '../../src/vue/index.js']
3194
+ ? [
3195
+ '@app/core',
3196
+ '@app/browser',
3197
+ '@src/vue',
3198
+ '../../src/vue/index.js',
3199
+ '../browser/index.js',
3200
+ ]
3147
3201
  : []),
3148
3202
  ]
3149
3203
  : ['@src/core']),
3204
+ ...(['src/browser', 'src/server', 'src/vue', 'src/bin'].includes(owner)
3205
+ ? []
3206
+ : ['../core/index.js']),
3207
+ ...(owner === 'src/bin' ? ['@src/server'] : []),
3150
3208
  ...(sheet
3151
3209
  ? [
3152
3210
  ...faces
@@ -3174,7 +3232,6 @@ createSomething({
3174
3232
  [
3175
3233
  ...admitted,
3176
3234
  './index.js',
3177
- '../core/index.js',
3178
3235
  ...(owner.endsWith('/server') || owner === 'src/bin' ? ['node:fs'] : []),
3179
3236
  ],
3180
3237
  false,
@@ -3930,36 +3987,22 @@ describe('configuration helpers', () => {
3930
3987
  )
3931
3988
  })
3932
3989
 
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)) {
3990
+ it('admits a computed import() through Vite at every module path while collecting literal specifiers', async () => {
3991
+ for (const path of [...COMPUTED_IMPORT_PATHS, '../outside/src/server/load.ts']) {
3935
3992
  await expect(
3936
3993
  configHelpers.environmentAssetSources(
3937
3994
  'void import(process.argv[2])',
3938
3995
  resolve(POLICY_ROOT, path),
3939
3996
  ),
3940
3997
  ).resolves.toEqual([])
3941
- }
3942
- for (const [path] of ARTIFACT_IMPORT_CASES.filter(([, admitted]) => !admitted)) {
3943
3998
  await expect(
3944
3999
  configHelpers.environmentAssetSources(
3945
- 'void import(process.argv[2])',
4000
+ "void import('@src/browser')",
3946
4001
  resolve(POLICY_ROOT, path),
3947
4002
  ),
3948
- ).rejects.toThrow('Dynamic imports must use static string values')
4003
+ ).resolves.toEqual(['@src/browser'])
3949
4004
  }
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
4005
  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
4006
  })
3964
4007
 
3965
4008
  it('drives each plugin through its real Vite hooks', async () => {
@@ -88,10 +88,23 @@ describe('surface policy controls', () => {
88
88
  }
89
89
  })
90
90
 
91
- it('refuses a target catalog row absent from the installed guides', () => {
91
+ it('ignores a target catalog row the installed scaffold does not stage', () => {
92
92
  const scratch = createPolicySurfaceFixture()
93
93
  try {
94
94
  scratch.write(POLICY_CATALOG_FILE, createPolicyCatalog(['other', 'sample', 'uncovered']))
95
+ expect(inspectPolicyWorkspace(scratch.path)).toEqual([])
96
+ } finally {
97
+ scratch.destroy()
98
+ }
99
+ })
100
+
101
+ it('refuses a staged catalog row absent from the installed guides', () => {
102
+ const scratch = createPolicySurfaceFixture()
103
+ try {
104
+ scratch.write(
105
+ `${POLICY_SURFACE_HOST}/${POLICY_SURFACE_CATALOG}`,
106
+ createPolicyCatalog(['other', 'sample', 'uncovered']),
107
+ )
95
108
  expect(inspectPolicyWorkspace(scratch.path)).toEqual([
96
109
  {
97
110
  rule: 'surface',
@@ -212,6 +225,31 @@ describe('surface policy controls', () => {
212
225
  }
213
226
  })
214
227
 
228
+ it('excludes the distribution harness in an adopter while reporting target-owned collisions', () => {
229
+ const scratch = createPolicySurfaceFixture()
230
+ try {
231
+ scratch.write('tests/setupDistribution.ts', 'export function readShared() {}\n')
232
+ expect(inspectPolicyWorkspace(scratch.path)).toEqual([])
233
+ scratch.write('tests/setupExtra.ts', 'export function readShared() {}\n')
234
+ expect(inspectPolicyWorkspace(scratch.path)).toEqual([
235
+ {
236
+ rule: 'mirror',
237
+ path: 'tests/setupExtra.ts',
238
+ message:
239
+ 'exporting setup module requires its sibling proof or an import from tests/setup.test.ts',
240
+ },
241
+ {
242
+ rule: 'surface',
243
+ path: 'tests/setupExtra.ts',
244
+ line: 1,
245
+ message: 'surface name belongs to one package: readShared (other)',
246
+ },
247
+ ])
248
+ } finally {
249
+ scratch.destroy()
250
+ }
251
+ })
252
+
215
253
  it('refuses a barrel statement outside the relative star-export population', () => {
216
254
  const scratch = createPolicySurfaceFixture()
217
255
  try {