@orkestrel/scaffold 0.0.70 → 0.0.72

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 (67) hide show
  1. package/dist/bin/main.js +8 -8
  2. package/dist/bin/main.js.map +1 -1
  3. package/dist/host/CLAUDE.md +3 -3
  4. package/dist/host/agents/orchestration.md +66 -32
  5. package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +36 -6
  6. package/dist/host/agents/skills/enterprise-bootstrap/references/color-modes.md +3 -2
  7. package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +1 -1
  8. package/dist/host/agents/skills/orkestrel-build-application/SKILL.md +18 -1
  9. package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +1 -1
  10. package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +2 -4
  11. package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +12 -9
  12. package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +16 -8
  13. package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +2 -2
  14. package/dist/host/agents/skills/orkestrel-harden-package/SKILL.md +1 -1
  15. package/dist/host/agents/skills/orkestrel-polish-surface/SKILL.md +2 -1
  16. package/dist/host/agents/skills/orkestrel-prove-journey/SKILL.md +19 -8
  17. package/dist/host/agents/skills/orkestrel-prove-journey/references/layer.md +16 -15
  18. package/dist/host/agents/skills/orkestrel-prove-journey/references/statechart.md +5 -2
  19. package/dist/host/agents/skills/orkestrel-prove-journey/references/styles.md +5 -1
  20. package/dist/host/agents/templates/brief.md +4 -3
  21. package/dist/host/agents/transports/claude.md +13 -6
  22. package/dist/host/agents/transports/codex.md +2 -2
  23. package/dist/host/agents/transports/cursor.md +85 -0
  24. package/dist/host/claude/agents/application.md +5 -6
  25. package/dist/host/claude/agents/builder.md +3 -13
  26. package/dist/host/claude/agents/checker.md +9 -2
  27. package/dist/host/claude/agents/distiller.md +37 -0
  28. package/dist/host/claude/agents/grok.md +9 -56
  29. package/dist/host/claude/agents/{implementer.md → opus.md} +8 -9
  30. package/dist/host/claude/agents/orkestrel.md +14 -7
  31. package/dist/host/claude/agents/planner.md +12 -5
  32. package/dist/host/claude/agents/researcher.md +7 -0
  33. package/dist/host/claude/agents/reviewer.md +14 -7
  34. package/dist/host/claude/agents/scout.md +8 -1
  35. package/dist/host/claude/agents/sol.md +5 -5
  36. package/dist/host/claude/rules/documentation.md +1 -0
  37. package/dist/host/claude/rules/writing.md +27 -24
  38. package/dist/host/claude/skills/orkestrel-build-application/SKILL.md +1 -1
  39. package/dist/host/codex/agents/analyst.toml +10 -4
  40. package/dist/host/codex/agents/application.toml +5 -6
  41. package/dist/host/codex/agents/builder.toml +5 -5
  42. package/dist/host/codex/agents/checker.toml +4 -0
  43. package/dist/host/codex/agents/distiller.toml +28 -0
  44. package/dist/host/codex/agents/grok.toml +27 -19
  45. package/dist/host/codex/agents/opus.toml +5 -4
  46. package/dist/host/codex/agents/orkestrel.toml +5 -0
  47. package/dist/host/codex/agents/planner.toml +10 -0
  48. package/dist/host/codex/agents/researcher.toml +4 -0
  49. package/dist/host/codex/agents/reviewer.toml +12 -2
  50. package/dist/host/codex/agents/scout.toml +5 -2
  51. package/dist/host/codex/agents/{implementer.toml → sol.toml} +5 -6
  52. package/dist/host/codex/agents/verifier.toml +3 -0
  53. package/dist/host/codex/config.toml +2 -2
  54. package/dist/host/configs/policy.ts +5 -2
  55. package/dist/host/guides/scaffold.md +19 -8
  56. package/dist/host/manifest.json +75 -57
  57. package/dist/src/core/index.cjs +456 -357
  58. package/dist/src/core/index.cjs.map +1 -1
  59. package/dist/src/core/index.d.cts +22 -21
  60. package/dist/src/core/index.d.ts +22 -21
  61. package/dist/src/core/index.js +457 -358
  62. package/dist/src/core/index.js.map +1 -1
  63. package/dist/src/server/index.cjs +4 -4
  64. package/dist/src/server/index.cjs.map +1 -1
  65. package/dist/src/server/index.js +5 -5
  66. package/dist/src/server/index.js.map +1 -1
  67. package/package.json +9 -9
@@ -1,9 +1,9 @@
1
- import { andOf, arrayOf, attempt, canonicalStringify, cloneJSONValue, compareValues, enumerableKeys, holds, isArray, isBoolean, isFunction, isRecord, isString, limitEntries, literalOf, parseJSON, recordOf, sortValues, stringOf, unionOf } from "@orkestrel/contract";
1
+ import { andOf, arrayOf, attempt, canonicalStringify, cloneJSONValue, compareValues, enumerableKeys, holds, isArray, isBoolean, isFunction, isInstance, isRecord, isString, limitEntries, literalOf, parseJSON, recordOf, sortValues, stringOf, unionOf } from "@orkestrel/contract";
2
2
  import { fillTemplate } from "@orkestrel/template";
3
3
  import { Emitter } from "@orkestrel/emitter";
4
4
  var package_default = {
5
5
  name: "@orkestrel/scaffold",
6
- version: "0.0.70",
6
+ version: "0.0.72",
7
7
  description: "Scaffold workspaces with commands: new, audit, repair, catalog, and overwrite.",
8
8
  keywords: [
9
9
  "audit",
@@ -89,19 +89,19 @@ var package_default = {
89
89
  "prepublishOnly": "npm run format:check && npm run lint:check && npm run check && npm run build && npm test && npm run test:distribution -- --mode release"
90
90
  },
91
91
  dependencies: {
92
- "@orkestrel/console": "^0.0.13",
92
+ "@orkestrel/console": "^0.0.14",
93
93
  "@orkestrel/contract": "^0.0.17",
94
94
  "@orkestrel/emitter": "^0.0.10",
95
- "@orkestrel/markdown": "^0.0.14",
96
- "@orkestrel/process": "^0.0.12",
97
- "@orkestrel/template": "^0.0.7"
95
+ "@orkestrel/markdown": "^0.0.15",
96
+ "@orkestrel/process": "^0.0.13",
97
+ "@orkestrel/template": "^0.0.8"
98
98
  },
99
99
  devDependencies: {
100
100
  "@microsoft/api-extractor": "^7.59.1",
101
- "@orkestrel/guide": "^0.0.19",
102
- "@orkestrel/html": "^0.0.9",
103
- "@orkestrel/probe": "^0.0.14",
104
- "@orkestrel/test": "^0.0.14",
101
+ "@orkestrel/guide": "^0.0.20",
102
+ "@orkestrel/html": "^0.0.10",
103
+ "@orkestrel/probe": "^0.0.16",
104
+ "@orkestrel/test": "^0.0.16",
105
105
  "@types/node": "^26.5.1",
106
106
  "@vitest/browser-playwright": "^4.1.11",
107
107
  "oxfmt": "^0.68.0",
@@ -670,7 +670,8 @@ var CONFIG_TEMPLATES = Object.freeze({
670
670
  "exclude": ["node_modules", "dist", "tmp"]
671
671
  }
672
672
  `,
673
- vite: `import type { {{viteTypes}} } from 'vite'
673
+ vite: `import type { PluginOption, UserConfig } from 'vite'
674
+ import { mergeConfig } from 'vite'
674
675
  {{imports}}import { defineConfig } from 'vitest/config'
675
676
  import manifest from './package.json' with { type: 'json' }
676
677
  import tsconfig from './tsconfig.json' with { type: 'json' }
@@ -700,6 +701,68 @@ const resolve = {
700
701
  }, {}),
701
702
  }
702
703
 
704
+ // Merges a caller's override onto the configuration a factory declares, so a
705
+ // package's own configuration reaches the factory through its parameter instead of
706
+ // wrapping the call from outside.
707
+ //
708
+ // Vitest calls every registered project factory with its own invocation record —
709
+ // \`command\`, \`mode\`, \`isSsrBuild\`, \`isPreview\` — so a factory that also takes an
710
+ // override receives that record in the same position. A \`UserConfig\` declares \`mode\`
711
+ // but not \`command\`, and the invocation record always carries both, so a value
712
+ // carrying the pair is that record rather than an override. The merge returns the
713
+ // base unchanged and reports nothing. The \`tests/config.test.ts\` file drives every
714
+ // registered factory through it.
715
+ //
716
+ // \`mergeConfig\` concatenates arrays, so an override carrying \`plugins\` would otherwise
717
+ // add a second copy of a plugin the base already declares. Only named top-level
718
+ // objects replace a base plugin of the same name, in the base's position, and one
719
+ // override entry is taken at most once. An entry no base position took appends in its
720
+ // written order; the caller's own entries never merge with each other. Nested arrays,
721
+ // promises, falsy entries, and anonymous objects pass through unchanged. An override
722
+ // cannot remove a base plugin. Every key other than \`plugins\` merges as \`mergeConfig\`
723
+ // merges it, so an override's arrays elsewhere concatenate with the base's rather than
724
+ // replacing them.
725
+ export function mergeOverride(base: UserConfig, override?: UserConfig): UserConfig {
726
+ if (override === undefined || ('command' in override && 'mode' in override)) return base
727
+ const merged: UserConfig = mergeConfig(base, override)
728
+ if (merged.plugins === undefined) return merged
729
+ const candidates = override.plugins ?? []
730
+ const taken = new Set<number>()
731
+ const selected: PluginOption[] = []
732
+ for (const plugin of base.plugins ?? []) {
733
+ if (!isNamedPlugin(plugin)) {
734
+ selected.push(plugin)
735
+ continue
736
+ }
737
+ const index = candidates.findIndex(
738
+ (candidate, position) =>
739
+ !taken.has(position) && isNamedPlugin(candidate) && candidate.name === plugin.name,
740
+ )
741
+ const replacement = candidates[index]
742
+ if (replacement === undefined) {
743
+ selected.push(plugin)
744
+ } else {
745
+ selected.push(replacement)
746
+ taken.add(index)
747
+ }
748
+ }
749
+ for (const [index, plugin] of candidates.entries()) {
750
+ if (!taken.has(index)) selected.push(plugin)
751
+ }
752
+ return { ...merged, plugins: selected }
753
+ }
754
+
755
+ function isNamedPlugin(plugin: PluginOption): plugin is { name: string } {
756
+ return (
757
+ typeof plugin === 'object' &&
758
+ plugin !== null &&
759
+ !Array.isArray(plugin) &&
760
+ !('then' in plugin && typeof plugin.then === 'function') &&
761
+ 'name' in plugin &&
762
+ typeof plugin.name === 'string'
763
+ )
764
+ }
765
+
703
766
  {{factories}}export default defineConfig({
704
767
  resolve,
705
768
  test: {
@@ -710,149 +773,166 @@ const resolve = {
710
773
  }),
711
774
  factories: Object.freeze({
712
775
  src: Object.freeze({
713
- core: `export const srcCore = (): UserConfig => ({
714
- resolve,
715
- publicDir: false,
716
- build: {
717
- emptyOutDir: true,
718
- sourcemap: true,
719
- minify: false,
720
- rolldownOptions: { onLog: enforceBuildLog },
721
- },
722
- test: {
723
- name: { label: 'src:core', color: 'magenta' },
724
- include: ['tests/src/core/**/*.test.ts'],
725
- setupFiles: ['./tests/setup.ts'],
726
- environment: 'node',
727
- browser: { enabled: false },
728
- },
729
- })
730
- `,
731
- browser: `export const srcBrowser = (): UserConfig => ({
732
- resolve,
733
- publicDir: false,
734
- plugins: [outputBoundary('dist/src/browser'), environmentBoundary('src/browser')],
735
- build: {
736
- emptyOutDir: true,
737
- sourcemap: true,
738
- minify: false,
739
- lib: {
740
- entry: resolveWorkspacePath('src/browser/index.ts'),
741
- formats: ['es'],
742
- fileName: () => 'index.js',
776
+ core: `export function srcCore(override?: UserConfig): UserConfig {
777
+ const project: UserConfig = {
778
+ resolve,
779
+ publicDir: false,
780
+ build: {
781
+ emptyOutDir: true,
782
+ sourcemap: true,
783
+ minify: false,
784
+ rolldownOptions: { onLog: enforceBuildLog },
785
+ },
786
+ test: {
787
+ name: { label: 'src:core', color: 'magenta' },
788
+ include: ['tests/src/core/**/*.test.ts'],
789
+ setupFiles: ['./tests/setup.ts'],
790
+ environment: 'node',
791
+ browser: { enabled: false },
743
792
  },
744
- outDir: 'dist/src/browser',
745
- rolldownOptions: {
746
- onLog: enforceBuildLog,
747
- {{external}}
793
+ }
794
+ return mergeOverride(project, override)
795
+ }
796
+ `,
797
+ browser: `export function srcBrowser(override?: UserConfig): UserConfig {
798
+ const project: UserConfig = {
799
+ resolve,
800
+ publicDir: false,
801
+ plugins: [outputBoundary('dist/src/browser'), environmentBoundary('src/browser')],
802
+ build: {
803
+ emptyOutDir: true,
804
+ sourcemap: true,
805
+ minify: false,
806
+ lib: {
807
+ entry: resolveWorkspacePath('src/browser/index.ts'),
808
+ formats: ['es'],
809
+ fileName: () => 'index.js',
810
+ },
811
+ outDir: 'dist/src/browser',
812
+ rolldownOptions: {
813
+ onLog: enforceBuildLog,
814
+ {{external}}
748
815
  {{output}}
816
+ },
749
817
  },
750
- },
751
- test: {
752
- name: { label: 'src:browser', color: 'yellow' },
753
- include: ['tests/src/browser/**/*.test.ts'],
754
- {{exclude}} setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
818
+ test: {
819
+ name: { label: 'src:browser', color: 'yellow' },
820
+ include: ['tests/src/browser/**/*.test.ts'],
821
+ {{exclude}} setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
755
822
  {{global}}
756
- browser: {
757
- enabled: true,
758
- provider: playwright(browserOptions),
759
- instances: [{ browser: 'chromium', headless: true }],
823
+ browser: {
824
+ enabled: true,
825
+ provider: playwright(browserOptions),
826
+ instances: [{ browser: 'chromium', headless: true }],
827
+ },
828
+ fileParallelism: false,
760
829
  },
761
- fileParallelism: false,
762
- },
763
- })
830
+ }
831
+ return mergeOverride(project, override)
832
+ }
764
833
  `,
765
- server: `export const srcServer = (): UserConfig => ({
766
- resolve,
767
- publicDir: false,
768
- plugins: [outputBoundary('dist/src/server'), environmentBoundary('src/server')],
769
- build: {
770
- emptyOutDir: true,
771
- sourcemap: true,
772
- minify: false,
773
- lib: {
774
- entry: resolveWorkspacePath('src/server/index.ts'),
775
- formats: ['es', 'cjs'],
776
- fileName: (format: string) => (format === 'es' ? 'index.js' : 'index.cjs'),
777
- },
778
- outDir: 'dist/src/server',
779
- target: 'node22',
780
- rolldownOptions: {
781
- onLog: enforceBuildLog,
782
- platform: 'node',
783
- {{external}}
834
+ server: `export function srcServer(override?: UserConfig): UserConfig {
835
+ const project: UserConfig = {
836
+ resolve,
837
+ publicDir: false,
838
+ plugins: [outputBoundary('dist/src/server'), environmentBoundary('src/server')],
839
+ build: {
840
+ emptyOutDir: true,
841
+ sourcemap: true,
842
+ minify: false,
843
+ lib: {
844
+ entry: resolveWorkspacePath('src/server/index.ts'),
845
+ formats: ['es', 'cjs'],
846
+ fileName: (format: string) => (format === 'es' ? 'index.js' : 'index.cjs'),
847
+ },
848
+ outDir: 'dist/src/server',
849
+ target: 'node22',
850
+ rolldownOptions: {
851
+ onLog: enforceBuildLog,
852
+ platform: 'node',
853
+ {{external}}
784
854
  {{output}}
855
+ },
785
856
  },
786
- },
787
- test: {
788
- name: { label: 'src:server', color: 'red' },
789
- include: ['tests/src/server/**/*.test.ts'],
790
- {{exclude}} setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
791
- environment: 'node',
792
- browser: { enabled: false },
793
- },
794
- })
857
+ test: {
858
+ name: { label: 'src:server', color: 'red' },
859
+ include: ['tests/src/server/**/*.test.ts'],
860
+ {{exclude}} setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
861
+ environment: 'node',
862
+ browser: { enabled: false },
863
+ },
864
+ }
865
+ return mergeOverride(project, override)
866
+ }
795
867
  `,
796
- bin: `export const srcBin = (): UserConfig => ({
797
- resolve,
798
- publicDir: false,
799
- plugins: [outputBoundary('dist/bin')],
800
- build: {
801
- emptyOutDir: true,
802
- sourcemap: true,
803
- minify: false,
804
- lib: {
805
- entry: resolveWorkspacePath('${BIN_ENTRY_PATH}'),
806
- formats: ['es'],
807
- fileName: () => 'main.js',
868
+ bin: `export function srcBin(override?: UserConfig): UserConfig {
869
+ const project: UserConfig = {
870
+ resolve,
871
+ publicDir: false,
872
+ plugins: [outputBoundary('dist/bin')],
873
+ build: {
874
+ emptyOutDir: true,
875
+ sourcemap: true,
876
+ minify: false,
877
+ lib: {
878
+ entry: resolveWorkspacePath('${BIN_ENTRY_PATH}'),
879
+ formats: ['es'],
880
+ fileName: () => 'main.js',
881
+ },
882
+ outDir: 'dist/bin',
883
+ target: 'node22',
884
+ rolldownOptions: {
885
+ onLog: enforceBuildLog,
886
+ external: (id: string) =>
887
+ id.startsWith('node:') ||
888
+ id.startsWith('@orkestrel/') ||
889
+ id.startsWith('@src/') ||
890
+ peers.some((peer) => id === peer || id.startsWith(peer + '/')),
891
+ },
808
892
  },
809
- outDir: 'dist/bin',
810
- target: 'node22',
811
- rolldownOptions: {
812
- onLog: enforceBuildLog,
813
- external: (id: string) =>
814
- id.startsWith('node:') ||
815
- id.startsWith('@orkestrel/') ||
816
- id.startsWith('@src/') ||
817
- peers.some((peer) => id === peer || id.startsWith(peer + '/')),
893
+ test: {
894
+ name: { label: 'src:bin', color: 'yellow' },
895
+ include: ['tests/src/bin/**/*.test.ts'],
896
+ setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
897
+ environment: 'node',
898
+ browser: { enabled: false },
899
+ // A bin test drives the real executable over a real temporary repository, so it
900
+ // spends seconds in process startup and filesystem work rather than milliseconds.
901
+ // Vitest's five-second default clears one alone and times out under a full suite.
902
+ testTimeout: 15_000,
818
903
  },
819
- },
820
- test: {
821
- name: { label: 'src:bin', color: 'yellow' },
822
- include: ['tests/src/bin/**/*.test.ts'],
823
- setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
824
- environment: 'node',
825
- browser: { enabled: false },
826
- // A bin test drives the real executable over a real temporary repository, so it
827
- // spends seconds in process startup and filesystem work rather than milliseconds.
828
- // Vitest's five-second default clears one alone and times out under a full suite.
829
- testTimeout: 15_000,
830
- },
831
- })
904
+ }
905
+ return mergeOverride(project, override)
906
+ }
832
907
  `
833
908
  }),
834
909
  app: Object.freeze({
835
- core: `export const appCore = (): UserConfig => ({
836
- resolve,
837
- publicDir: false,
838
- plugins: [environmentBoundary('app/core')],
839
- test: {
840
- name: { label: 'app:core', color: 'cyan' },
841
- include: ['tests/app/core/**/*.test.ts'],
842
- setupFiles: ['./tests/setup.ts'],
843
- environment: 'node',
844
- browser: { enabled: false },
845
- },
846
- })
910
+ core: `export function appCore(override?: UserConfig): UserConfig {
911
+ const project: UserConfig = {
912
+ resolve,
913
+ publicDir: false,
914
+ plugins: [environmentBoundary('app/core')],
915
+ test: {
916
+ name: { label: 'app:core', color: 'cyan' },
917
+ include: ['tests/app/core/**/*.test.ts'],
918
+ setupFiles: ['./tests/setup.ts'],
919
+ environment: 'node',
920
+ browser: { enabled: false },
921
+ },
922
+ }
923
+ return mergeOverride(project, override)
924
+ }
847
925
  `,
848
- browser: `function applicationBrowser(showcase: boolean): UserConfig {
849
- const output = showcase ? 'dist/showcase' : 'dist/app/browser'
850
- {{showcasePlugins}} return {
926
+ browser: `export function appBrowser(override?: UserConfig): UserConfig {
927
+ const output = 'dist/app/browser'
928
+ const project: UserConfig = {
851
929
  resolve,
852
- {{plugins}} root: resolveWorkspacePath('app/browser'),
930
+ plugins: [outputBoundary(output), environmentBoundary('app/browser'), vue()],
931
+ root: resolveWorkspacePath('app/browser'),
853
932
  publicDir: false,
854
933
  build: {
855
- {{showcaseBuild}} emptyOutDir: true,
934
+ assetsInlineLimit: 0,
935
+ emptyOutDir: true,
856
936
  outDir: resolveWorkspacePath(output),
857
937
  rolldownOptions: {
858
938
  onLog: enforceBuildLog,
@@ -873,160 +953,229 @@ const resolve = {
873
953
  fileParallelism: false,
874
954
  },
875
955
  }
876
- }
877
-
878
- export function appBrowser(): UserConfig {
879
- return applicationBrowser(false)
956
+ return mergeOverride(project, override)
880
957
  }
881
958
  {{showcaseFactory}}`,
882
- server: `export const appServer = (): UserConfig => ({
883
- resolve,
884
- publicDir: false,
885
- plugins: [outputBoundary('dist/app/server'), environmentBoundary('app/server')],
886
- build: {
887
- emptyOutDir: true,
888
- lib: {
889
- entry: resolveWorkspacePath('app/server/main.ts'),
890
- formats: ['cjs'],
891
- fileName: () => 'main.cjs',
959
+ showcase: `
960
+ export function appShowcase(override?: UserConfig): UserConfig {
961
+ const output = 'dist/showcase'
962
+ const showcase: UserConfig = {
963
+ plugins: [
964
+ outputBoundary(output),
965
+ viteSingleFile({
966
+ removeViteModuleLoader: true,
967
+ useRecommendedBuildConfig: true,
968
+ }),
969
+ {
970
+ name: 'orkestrel-showcase-html',
971
+ transformIndexHtml: {
972
+ order: 'post',
973
+ handler(html) {
974
+ const stamp = new Date().toISOString()
975
+ return html.replace(
976
+ '</head>',
977
+ '\t\t<meta name="build-id" content="' + stamp + '" />\\n\t</head>',
978
+ )
979
+ },
980
+ },
981
+ },
982
+ ],
983
+ build: {
984
+ // The \`appBrowser\` factory sets \`assetsInlineLimit\` to 0, so every asset becomes
985
+ // its own file, and 4096 is Vite's own default put back. The \`viteSingleFile\`
986
+ // plugin overwrites the value while the \`useRecommendedBuildConfig\` option stays
987
+ // true, so this line takes effect only in a workspace that turns that option off.
988
+ assetsInlineLimit: 4096,
989
+ cssMinify: 'lightningcss',
990
+ minify: 'oxc',
991
+ modulePreload: false,
992
+ outDir: resolveWorkspacePath(output),
993
+ reportCompressedSize: false,
994
+ sourcemap: false,
995
+ target: 'esnext',
892
996
  },
893
- outDir: resolveWorkspacePath('dist/app/server'),
894
- target: 'node22',
895
- rolldownOptions: {
896
- onLog: enforceBuildLog,
897
- external: (id: string) => id.startsWith('node:'),
997
+ }
998
+ return appBrowser(mergeOverride(showcase, override))
999
+ }
1000
+ `,
1001
+ server: `export function appServer(override?: UserConfig): UserConfig {
1002
+ const project: UserConfig = {
1003
+ resolve,
1004
+ publicDir: false,
1005
+ plugins: [outputBoundary('dist/app/server'), environmentBoundary('app/server')],
1006
+ build: {
1007
+ emptyOutDir: true,
1008
+ lib: {
1009
+ entry: resolveWorkspacePath('app/server/main.ts'),
1010
+ formats: ['cjs'],
1011
+ fileName: () => 'main.cjs',
1012
+ },
1013
+ outDir: resolveWorkspacePath('dist/app/server'),
1014
+ target: 'node22',
1015
+ rolldownOptions: {
1016
+ onLog: enforceBuildLog,
1017
+ external: (id: string) => id.startsWith('node:'),
1018
+ },
898
1019
  },
899
- },
900
- test: {
901
- name: { label: 'app:server', color: 'green' },
902
- include: ['tests/app/server/**/*.test.ts'],
903
- setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
904
- environment: 'node',
905
- browser: { enabled: false },
906
- },
907
- })
1020
+ test: {
1021
+ name: { label: 'app:server', color: 'green' },
1022
+ include: ['tests/app/server/**/*.test.ts'],
1023
+ setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
1024
+ environment: 'node',
1025
+ browser: { enabled: false },
1026
+ },
1027
+ }
1028
+ return mergeOverride(project, override)
1029
+ }
908
1030
  `
909
1031
  }),
910
- policy: `export const policy = (): UserConfig => ({
911
- resolve,
912
- test: {
913
- name: { label: 'policy', color: 'white' },
914
- include: ['tests/policy.test.ts'],
915
- setupFiles: ['./tests/setup.ts'],
916
- environment: 'node',
917
- browser: { enabled: false },
918
- },
919
- })
1032
+ policy: `export function policy(override?: UserConfig): UserConfig {
1033
+ const project: UserConfig = {
1034
+ resolve,
1035
+ test: {
1036
+ name: { label: 'policy', color: 'white' },
1037
+ include: ['tests/policy.test.ts'],
1038
+ setupFiles: ['./tests/setup.ts'],
1039
+ environment: 'node',
1040
+ browser: { enabled: false },
1041
+ },
1042
+ }
1043
+ return mergeOverride(project, override)
1044
+ }
920
1045
  `,
921
- config: `export const config = (): UserConfig => ({
922
- resolve,
923
- test: {
924
- name: { label: 'config', color: 'yellow' },
925
- include: ['tests/config.test.ts'],
926
- setupFiles: ['./tests/setup.ts'],
927
- environment: 'node',
928
- browser: { enabled: false },
929
- // A config test validates every target wrapper, spawns the real linter twice under
930
- // 15-second child caps, and rolls one face up through the compiler and the extractor it
931
- // spawns, so this budget clears the capped pair with room for a contended host.
932
- testTimeout: 60_000,
933
- },
934
- })
1046
+ config: `export function config(override?: UserConfig): UserConfig {
1047
+ const project: UserConfig = {
1048
+ resolve,
1049
+ test: {
1050
+ name: { label: 'config', color: 'yellow' },
1051
+ include: ['tests/config.test.ts'],
1052
+ setupFiles: ['./tests/setup.ts'],
1053
+ environment: 'node',
1054
+ browser: { enabled: false },
1055
+ // A config test validates every target wrapper, spawns the real linter twice under
1056
+ // 15-second child caps, and rolls one face up through the compiler and the extractor it
1057
+ // spawns, so this budget clears the capped pair with room for a contended host.
1058
+ testTimeout: 60_000,
1059
+ },
1060
+ }
1061
+ return mergeOverride(project, override)
1062
+ }
935
1063
  `,
936
- setup: `export const setup = (): UserConfig => ({
937
- resolve,
938
- test: {
939
- name: { label: 'setup', color: 'white' },
940
- include: ['tests/setup*.test.ts'],
941
- setupFiles: ['./tests/setup.ts'],
942
- environment: 'node',
943
- browser: { enabled: false },
944
- },
945
- })
1064
+ setup: `export function setup(override?: UserConfig): UserConfig {
1065
+ const project: UserConfig = {
1066
+ resolve,
1067
+ test: {
1068
+ name: { label: 'setup', color: 'white' },
1069
+ include: ['tests/setup*.test.ts'],
1070
+ setupFiles: ['./tests/setup.ts'],
1071
+ environment: 'node',
1072
+ browser: { enabled: false },
1073
+ },
1074
+ }
1075
+ return mergeOverride(project, override)
1076
+ }
946
1077
  `,
947
- guides: `export const guides = (): UserConfig => ({
948
- resolve,
949
- test: {
950
- name: { label: 'guides', color: 'green' },
951
- include: ['${GUIDES_TEST_PATH}'],
952
- exclude: ['tests/src/**/*.test.ts', 'tests/app/**/*.test.ts', 'tests/setup.test.ts'],
953
- setupFiles: ['./tests/setup.ts'],
954
- environment: 'node',
955
- browser: { enabled: false },
956
- },
957
- })
1078
+ guides: `export function guides(override?: UserConfig): UserConfig {
1079
+ const project: UserConfig = {
1080
+ resolve,
1081
+ test: {
1082
+ name: { label: 'guides', color: 'green' },
1083
+ include: ['${GUIDES_TEST_PATH}'],
1084
+ exclude: ['tests/src/**/*.test.ts', 'tests/app/**/*.test.ts', 'tests/setup.test.ts'],
1085
+ setupFiles: ['./tests/setup.ts'],
1086
+ environment: 'node',
1087
+ browser: { enabled: false },
1088
+ },
1089
+ }
1090
+ return mergeOverride(project, override)
1091
+ }
958
1092
  `,
959
1093
  conformance: `// Where this package drifts from the official tooling it stays compatible with.
960
1094
  // The subject is this package, so the proof is hermetic and stays in \`npm test\`.
961
- export const conformance = (): UserConfig => ({
962
- resolve,
963
- test: {
964
- name: { label: 'conformance', color: 'magenta' },
965
- include: ['${CONFORMANCE_TEST_PATH}'],
966
- setupFiles: ['./tests/setup.ts'],
967
- environment: 'node',
968
- browser: { enabled: false },
969
- },
970
- })
1095
+ export function conformance(override?: UserConfig): UserConfig {
1096
+ const project: UserConfig = {
1097
+ resolve,
1098
+ test: {
1099
+ name: { label: 'conformance', color: 'magenta' },
1100
+ include: ['${CONFORMANCE_TEST_PATH}'],
1101
+ setupFiles: ['./tests/setup.ts'],
1102
+ environment: 'node',
1103
+ browser: { enabled: false },
1104
+ },
1105
+ }
1106
+ return mergeOverride(project, override)
1107
+ }
971
1108
  `,
972
1109
  service: `// The caller prepares the live external services before this project.
973
1110
  // \`tests/setupService.ts\` verifies readiness, and the project stays out of \`npm test\`
974
1111
  // because a real service answers it.
975
- export const service = (): UserConfig => ({
976
- resolve,
977
- test: {
978
- name: { label: 'service', color: 'red' },
979
- include: ['${SERVICE_TEST_INCLUDE}'],
980
- setupFiles: ['./tests/setup.ts', './tests/setupService.ts'],
981
- environment: 'node',
982
- browser: { enabled: false },
983
- testTimeout: 120_000,
984
- hookTimeout: 120_000,
985
- fileParallelism: false,
986
- },
987
- })
1112
+ export function service(override?: UserConfig): UserConfig {
1113
+ const project: UserConfig = {
1114
+ resolve,
1115
+ test: {
1116
+ name: { label: 'service', color: 'red' },
1117
+ include: ['${SERVICE_TEST_INCLUDE}'],
1118
+ setupFiles: ['./tests/setup.ts', './tests/setupService.ts'],
1119
+ environment: 'node',
1120
+ browser: { enabled: false },
1121
+ testTimeout: 120_000,
1122
+ hookTimeout: 120_000,
1123
+ fileParallelism: false,
1124
+ },
1125
+ }
1126
+ return mergeOverride(project, override)
1127
+ }
988
1128
  `,
989
- distribution: `export const distribution = (): UserConfig => ({
990
- resolve,
991
- test: {
992
- name: { label: 'distribution', color: 'cyan' },
993
- include: ['${DISTRIBUTION_TEST_PATH}'],
994
- setupFiles: ['./tests/setup.ts'],
995
- environment: 'node',
996
- testTimeout: 120_000,
997
- hookTimeout: 120_000,
998
- fileParallelism: false,
999
- },
1000
- })
1129
+ distribution: `export function distribution(override?: UserConfig): UserConfig {
1130
+ const project: UserConfig = {
1131
+ resolve,
1132
+ test: {
1133
+ name: { label: 'distribution', color: 'cyan' },
1134
+ include: ['${DISTRIBUTION_TEST_PATH}'],
1135
+ setupFiles: ['./tests/setup.ts'],
1136
+ environment: 'node',
1137
+ testTimeout: 120_000,
1138
+ hookTimeout: 120_000,
1139
+ fileParallelism: false,
1140
+ },
1141
+ }
1142
+ return mergeOverride(project, override)
1143
+ }
1001
1144
  `,
1002
1145
  probe: `// A workbench, not a proof. No gate selects this project. Run in test mode by the
1003
1146
  // \`test:probe\` script, it collects \`tmp/probe/**/*.test.ts\`. Run in benchmark mode by the
1004
1147
  // \`test:bench\` script, the same workbench also collects \`tests/**/*.test.ts\` for a \`bench\` block,
1005
1148
  // so a suite may carry a bench beside its ordinary tests without a second project. The mode
1006
1149
  // guard around each \`bench\` call keeps it out of test mode, so it never executes there.
1007
- export const probe = (): UserConfig => ({
1008
- resolve,
1009
- test: {
1010
- name: { label: 'probe', color: 'black' },
1011
- include: ['tmp/probe/**/*.test.ts'],
1012
- setupFiles: ['./tests/setup.ts'],
1013
- environment: 'node',
1014
- browser: { enabled: false },
1015
- fileParallelism: false,
1016
- pool: 'threads',
1017
- benchmark: { include: ['tmp/probe/**/*.test.ts', 'tests/**/*.test.ts'] },
1018
- },
1019
- })
1150
+ export function probe(override?: UserConfig): UserConfig {
1151
+ const project: UserConfig = {
1152
+ resolve,
1153
+ test: {
1154
+ name: { label: 'probe', color: 'black' },
1155
+ include: ['tmp/probe/**/*.test.ts'],
1156
+ setupFiles: ['./tests/setup.ts'],
1157
+ environment: 'node',
1158
+ browser: { enabled: false },
1159
+ fileParallelism: false,
1160
+ pool: 'threads',
1161
+ benchmark: { include: ['tmp/probe/**/*.test.ts', 'tests/**/*.test.ts'] },
1162
+ },
1163
+ }
1164
+ return mergeOverride(project, override)
1165
+ }
1020
1166
  `,
1021
- integration: `export const integration = (): UserConfig => ({
1022
- resolve,
1023
- test: {
1024
- name: { label: 'integration', color: 'blue' },
1025
- include: ['${INTEGRATION_TEST_PATH}'],
1026
- setupFiles: ['./tests/setup.ts'],
1027
- {{global}} environment: 'node',
1028
- },
1029
- })
1167
+ integration: `export function integration(override?: UserConfig): UserConfig {
1168
+ const project: UserConfig = {
1169
+ resolve,
1170
+ test: {
1171
+ name: { label: 'integration', color: 'blue' },
1172
+ include: ['${INTEGRATION_TEST_PATH}'],
1173
+ setupFiles: ['./tests/setup.ts'],
1174
+ {{global}} environment: 'node',
1175
+ },
1176
+ }
1177
+ return mergeOverride(project, override)
1178
+ }
1030
1179
  `
1031
1180
  }),
1032
1181
  tsconfigs: Object.freeze({
@@ -1154,12 +1303,12 @@ export const probe = (): UserConfig => ({
1154
1303
  }),
1155
1304
  vites: Object.freeze({
1156
1305
  src: Object.freeze({
1157
- core: `import { defineConfig, mergeConfig } from 'vite'
1306
+ core: `import { defineConfig } from 'vite'
1158
1307
  import { declarationRollup, environmentBoundary, outputBoundary } from '../helpers.js'
1159
1308
  import { peers, srcCore, resolveWorkspacePath } from '../../vite.config.ts'
1160
1309
 
1161
1310
  export default defineConfig(
1162
- mergeConfig(srcCore(), {
1311
+ srcCore({
1163
1312
  publicDir: false,
1164
1313
  plugins: [
1165
1314
  outputBoundary('dist/src/core'),
@@ -1186,14 +1335,14 @@ export default defineConfig(
1186
1335
  }),
1187
1336
  )
1188
1337
  `,
1189
- browser: `import { defineConfig, mergeConfig } from 'vite'
1338
+ browser: `import { defineConfig } from 'vite'
1190
1339
  import { declarationRollup, rewriteCoreSpecifier } from '../helpers.js'
1191
1340
  import { srcBrowser, resolveWorkspacePath } from '../../vite.config.ts'
1192
1341
 
1193
1342
  // The roll-up reaches src/core through a specifier the tarball does not carry, so the rewrite
1194
1343
  // externalizes core through the package's own published root export, on the final roll-up alone.
1195
1344
  export default defineConfig(
1196
- mergeConfig(srcBrowser(), {
1345
+ srcBrowser({
1197
1346
  plugins: [
1198
1347
  declarationRollup({
1199
1348
  project: resolveWorkspacePath('configs/src/tsconfig.browser.json'),
@@ -1203,14 +1352,14 @@ export default defineConfig(
1203
1352
  }),
1204
1353
  )
1205
1354
  `,
1206
- server: `import { defineConfig, mergeConfig } from 'vite'
1355
+ server: `import { defineConfig } from 'vite'
1207
1356
  import { declarationRollup, rewriteCoreSpecifier } from '../helpers.js'
1208
1357
  import { srcServer, resolveWorkspacePath } from '../../vite.config.ts'
1209
1358
 
1210
1359
  // The roll-up reaches src/core through a specifier the tarball does not carry, so the rewrite
1211
1360
  // externalizes core through the package's own published root export, on the final roll-up alone.
1212
1361
  export default defineConfig(
1213
- mergeConfig(srcServer(), {
1362
+ srcServer({
1214
1363
  plugins: [
1215
1364
  declarationRollup({
1216
1365
  project: resolveWorkspacePath('configs/src/tsconfig.server.json'),
@@ -1221,7 +1370,7 @@ export default defineConfig(
1221
1370
  )
1222
1371
  `
1223
1372
  }),
1224
- bin: `import { defineConfig, mergeConfig } from 'vite'
1373
+ bin: `import { defineConfig } from 'vite'
1225
1374
  import { srcBin } from '../../vite.config.ts'
1226
1375
 
1227
1376
  // The \`scaffold\` executable build — a single ESM lib file, no declarations (an
@@ -1230,7 +1379,7 @@ import { srcBin } from '../../vite.config.ts'
1230
1379
  // \`output.paths\` rewriting the externalized \`@src/*\` specifiers to the built sibling
1231
1380
  // src environments (relative to \`dist/bin/\`), so the emitted bin resolves at runtime.
1232
1381
  export default defineConfig(
1233
- mergeConfig(srcBin(), {
1382
+ srcBin({
1234
1383
  build: {
1235
1384
  rolldownOptions: {
1236
1385
  output: {
@@ -2850,7 +2999,7 @@ var ScaffoldError = class extends Error {
2850
2999
  * ```
2851
3000
  */
2852
3001
  function isScaffoldError(value) {
2853
- return value instanceof ScaffoldError;
3002
+ return isInstance(value, ScaffoldError);
2854
3003
  }
2855
3004
  //#endregion
2856
3005
  //#region src/core/validators.ts
@@ -4998,14 +5147,14 @@ function blueprintToRootVite(blueprint) {
4998
5147
  const core = blueprint.src.includes("core");
4999
5148
  factories.push(fillTemplate(CONFIG_TEMPLATES.factories.src.browser, {
5000
5149
  external: core ? `external: (id: string) =>
5001
- id === '@src/core' ||
5002
- id.startsWith('@orkestrel/') ||
5003
- peers.some((peer) => id === peer || id.startsWith(peer + '/')),` : `external: (id: string) =>
5004
- id.startsWith('@orkestrel/') ||
5005
- peers.some((peer) => id === peer || id.startsWith(peer + '/')),`,
5006
- output: core ? " output: { paths: { '@src/core': '../core/index.js' } }," : " output: {},",
5007
- exclude: core ? " exclude: ['tests/src/core/**/*.test.ts'],\n" : "",
5008
- global: blueprint.global ? " globalSetup: ['./tests/setupGlobal.ts'],\n" : ""
5150
+ id === '@src/core' ||
5151
+ id.startsWith('@orkestrel/') ||
5152
+ peers.some((peer) => id === peer || id.startsWith(peer + '/')),` : `external: (id: string) =>
5153
+ id.startsWith('@orkestrel/') ||
5154
+ peers.some((peer) => id === peer || id.startsWith(peer + '/')),`,
5155
+ output: core ? " output: { paths: { '@src/core': '../core/index.js' } }," : " output: {},",
5156
+ exclude: core ? " exclude: ['tests/src/core/**/*.test.ts'],\n" : "",
5157
+ global: blueprint.global ? " globalSetup: ['./tests/setupGlobal.ts'],\n" : ""
5009
5158
  }));
5010
5159
  projects.push("srcBrowser");
5011
5160
  }
@@ -5013,26 +5162,26 @@ function blueprintToRootVite(blueprint) {
5013
5162
  const core = blueprint.src.includes("core");
5014
5163
  factories.push(fillTemplate(CONFIG_TEMPLATES.factories.src.server, {
5015
5164
  external: core ? `external: (id: string) =>
5016
- id === '@src/core' ||
5017
- id.startsWith('node:') ||
5018
- id.startsWith('@orkestrel/') ||
5019
- peers.some((peer) => id === peer || id.startsWith(peer + '/')),` : `external: (id: string) =>
5020
- id.startsWith('node:') ||
5021
- id.startsWith('@orkestrel/') ||
5022
- peers.some((peer) => id === peer || id.startsWith(peer + '/')),`,
5023
- output: core ? `\t\t\toutput: [
5024
- {
5025
- format: 'es',
5026
- entryFileNames: 'index.js',
5027
- paths: { '@src/core': '../core/index.js' },
5028
- },
5029
- {
5030
- format: 'cjs',
5031
- entryFileNames: 'index.cjs',
5032
- paths: { '@src/core': '../core/index.cjs' },
5033
- },
5034
- ],` : " output: {},",
5035
- exclude: core ? " exclude: ['tests/src/core/**/*.test.ts'],\n" : ""
5165
+ id === '@src/core' ||
5166
+ id.startsWith('node:') ||
5167
+ id.startsWith('@orkestrel/') ||
5168
+ peers.some((peer) => id === peer || id.startsWith(peer + '/')),` : `external: (id: string) =>
5169
+ id.startsWith('node:') ||
5170
+ id.startsWith('@orkestrel/') ||
5171
+ peers.some((peer) => id === peer || id.startsWith(peer + '/')),`,
5172
+ output: core ? `\t\t\t\toutput: [
5173
+ {
5174
+ format: 'es',
5175
+ entryFileNames: 'index.js',
5176
+ paths: { '@src/core': '../core/index.js' },
5177
+ },
5178
+ {
5179
+ format: 'cjs',
5180
+ entryFileNames: 'index.cjs',
5181
+ paths: { '@src/core': '../core/index.cjs' },
5182
+ },
5183
+ ],` : " output: {},",
5184
+ exclude: core ? " exclude: ['tests/src/core/**/*.test.ts'],\n" : ""
5036
5185
  }));
5037
5186
  projects.push("srcServer");
5038
5187
  }
@@ -5045,57 +5194,8 @@ function blueprintToRootVite(blueprint) {
5045
5194
  projects.push("appCore");
5046
5195
  }
5047
5196
  if (blueprint.app.includes("browser")) {
5048
- const showcasePlugins = machinery.showcase ? ` const showcasePlugins: PluginOption[] = showcase
5049
- ? [
5050
- viteSingleFile({
5051
- removeViteModuleLoader: true,
5052
- useRecommendedBuildConfig: true,
5053
- }),
5054
- {
5055
- name: 'orkestrel-showcase-html',
5056
- transformIndexHtml: {
5057
- order: 'post',
5058
- handler(html) {
5059
- const stamp = new Date().toISOString()
5060
- return html.replace(
5061
- '</head>',
5062
- '\t\t<meta name="build-id" content="' + stamp + '" />\\n\t</head>',
5063
- )
5064
- },
5065
- },
5066
- },
5067
- ]
5068
- : []
5069
- ` : "";
5070
- const plugins = machinery.showcase ? `\t\tplugins: [
5071
- outputBoundary(output),
5072
- environmentBoundary('app/browser'),
5073
- vue(),
5074
- ...showcasePlugins,
5075
- ],
5076
- ` : " plugins: [outputBoundary(output), environmentBoundary('app/browser'), vue()],\n";
5077
- const showcaseBuild = machinery.showcase ? `\t\t\t...(showcase
5078
- ? {
5079
- cssMinify: 'lightningcss',
5080
- minify: 'oxc',
5081
- modulePreload: false,
5082
- reportCompressedSize: false,
5083
- sourcemap: false,
5084
- target: 'esnext',
5085
- }
5086
- : { assetsInlineLimit: 0 }),
5087
- ` : " assetsInlineLimit: 0,\n";
5088
- const showcaseFactory = machinery.showcase ? `
5089
- export function appShowcase(): UserConfig {
5090
- return applicationBrowser(true)
5091
- }
5092
- ` : "";
5093
- factories.push(fillTemplate(CONFIG_TEMPLATES.factories.app.browser, {
5094
- plugins,
5095
- showcasePlugins,
5096
- showcaseBuild,
5097
- showcaseFactory
5098
- }));
5197
+ const showcaseFactory = machinery.showcase ? CONFIG_TEMPLATES.factories.app.showcase : "";
5198
+ factories.push(fillTemplate(CONFIG_TEMPLATES.factories.app.browser, { showcaseFactory }));
5099
5199
  projects.push("appBrowser");
5100
5200
  }
5101
5201
  if (blueprint.app.includes("server")) {
@@ -5127,7 +5227,7 @@ export function appShowcase(): UserConfig {
5127
5227
  projects.push("distribution");
5128
5228
  }
5129
5229
  if (blueprint.integration) {
5130
- factories.push(fillTemplate(CONFIG_TEMPLATES.factories.integration, { global: blueprint.global ? " globalSetup: ['./tests/setupGlobal.ts'],\n" : "" }));
5230
+ factories.push(fillTemplate(CONFIG_TEMPLATES.factories.integration, { global: blueprint.global ? " globalSetup: ['./tests/setupGlobal.ts'],\n" : "" }));
5131
5231
  projects.push("integration");
5132
5232
  }
5133
5233
  factories.push(CONFIG_TEMPLATES.factories.probe);
@@ -5143,7 +5243,6 @@ ${projects.map((project) => `\t\t\t${project},`).join("\n")}
5143
5243
  "outputBoundary"
5144
5244
  ].filter((helper) => body.includes(helper));
5145
5245
  return fillTemplate(CONFIG_TEMPLATES.root.vite, {
5146
- viteTypes: machinery.showcase ? "PluginOption, UserConfig" : "UserConfig",
5147
5246
  imports: imports.length === 0 ? "" : `${imports.join("\n")}\n`,
5148
5247
  helpers: helpers.length === 0 ? "" : `import { ${helpers.join(", ")} } from './configs/helpers.js'\n`,
5149
5248
  browsers: machinery.browser ? "import { resolveBrowser, resolvePinnedBrowser } from './configs/browsers.js'\n" : "",
@@ -5790,7 +5889,7 @@ function replaceManifestRanges(manifest, pins) {
5790
5889
  if (manifest.charAt(value) === ":") {
5791
5890
  value += 1;
5792
5891
  while (value < manifest.length && /\s/u.test(manifest.charAt(value))) value += 1;
5793
- if (typeof key === "string" && sectionNames.has(key) && manifest.charAt(value) === "{") {
5892
+ if (isString(key) && sectionNames.has(key) && manifest.charAt(value) === "{") {
5794
5893
  let sectionDepth = 0;
5795
5894
  let sectionCursor = value;
5796
5895
  while (sectionCursor < manifest.length) {
@@ -5872,7 +5971,7 @@ function replaceManifestRanges(manifest, pins) {
5872
5971
  }
5873
5972
  valueStart += 1;
5874
5973
  while (valueStart < section.length && /\s/u.test(section.charAt(valueStart))) valueStart += 1;
5875
- if (typeof key !== "string" || section.charAt(valueStart) !== "\"") {
5974
+ if (!isString(key) || section.charAt(valueStart) !== "\"") {
5876
5975
  sectionCursor = keyEnd;
5877
5976
  continue;
5878
5977
  }