@bleedingdev/modern-js-create 3.2.0-ultramodern.57 → 3.2.0-ultramodern.59

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.
@@ -0,0 +1,15 @@
1
+ pre-commit:
2
+ commands:
3
+ format:
4
+ run: pnpm format
5
+ stage_fixed: true
6
+ lint:
7
+ run: pnpm lint:fix
8
+ stage_fixed: true
9
+ check:
10
+ run: pnpm check
11
+
12
+ pre-push:
13
+ commands:
14
+ check:
15
+ run: pnpm check
@@ -1,7 +1,6 @@
1
1
  packages:
2
2
  - apps/*
3
- - apps/remotes/*
4
- - services/*
3
+ - verticals/*
5
4
  - packages/*
6
5
 
7
6
  minimumReleaseAge: 0
@@ -24,7 +23,7 @@ allowBuilds:
24
23
  '@swc/core': true
25
24
  core-js: true
26
25
  esbuild: true
26
+ lefthook: true
27
27
  msgpackr-extract: true
28
28
  sharp: true
29
- simple-git-hooks: true
30
29
  workerd: true
@@ -3,9 +3,9 @@ import path from 'node:path';
3
3
 
4
4
  const root = process.cwd();
5
5
  const defaultAppDirs = [
6
- 'apps/remotes/remote-commerce',
7
- 'apps/remotes/remote-identity',
8
- 'apps/remotes/remote-design-system',
6
+ 'verticals/commerce',
7
+ 'verticals/identity',
8
+ 'verticals/design-system',
9
9
  ];
10
10
 
11
11
  const candidateDirs = process.argv.slice(2);
@@ -359,6 +359,10 @@ function main() {
359
359
  try {
360
360
  main();
361
361
  } catch (error) {
362
- console.error(`[agent-reference-repos] ${error.message}`);
363
- process.exitCode = 1;
362
+ if (required || checkOnly) {
363
+ console.error(`[agent-reference-repos] ${error.message}`);
364
+ process.exitCode = 1;
365
+ } else {
366
+ warn(error.message);
367
+ }
364
368
  }
@@ -31,25 +31,25 @@ const moduleFederationAgentSkills = ['mf'];
31
31
  const privateAgentSkills = ['plan-graph', 'dag', 'subagent-graph', 'helm', 'debugger-mode'];
32
32
  const fullStackVerticals = [
33
33
  {
34
- id: 'remote-commerce',
34
+ id: 'commerce',
35
35
  domain: 'commerce',
36
36
  stem: 'recommendations',
37
37
  group: 'recommendations',
38
- path: 'apps/remotes/remote-commerce',
39
- mfName: 'remoteCommerce',
38
+ path: 'verticals/commerce',
39
+ mfName: 'verticalCommerce',
40
40
  apiPrefix: '/commerce-api',
41
41
  },
42
42
  {
43
- id: 'remote-identity',
43
+ id: 'identity',
44
44
  domain: 'identity',
45
45
  stem: 'identity',
46
46
  group: 'identity',
47
- path: 'apps/remotes/remote-identity',
48
- mfName: 'remoteIdentity',
47
+ path: 'verticals/identity',
48
+ mfName: 'verticalIdentity',
49
49
  apiPrefix: '/identity-api',
50
50
  },
51
51
  ];
52
- const designSystemRemotePath = 'apps/remotes/remote-design-system';
52
+ const designSystemRemotePath = 'verticals/design-system';
53
53
 
54
54
  const readText = (relativePath) => fs.readFileSync(path.join(root, relativePath), 'utf-8');
55
55
  const readJson = (relativePath) => JSON.parse(readText(relativePath));
@@ -87,7 +87,7 @@ const assertNotExists = (relativePath) => {
87
87
 
88
88
  assert(
89
89
  activePnpmVersion === expectedPnpmVersion,
90
- `Generated workspace requires pnpm ${expectedPnpmVersion}; active pnpm is ${activePnpmVersion}. Run mise install, then rerun through mise exec -- pnpm ...`,
90
+ `Generated workspace requires pnpm ${expectedPnpmVersion}; active pnpm is ${activePnpmVersion}. Run mise install, then rerun pnpm from the activated shell`,
91
91
  );
92
92
 
93
93
  const requiredPaths = [
@@ -98,6 +98,8 @@ const requiredPaths = [
98
98
  'tsconfig.base.json',
99
99
  'oxlint.config.ts',
100
100
  'oxfmt.config.ts',
101
+ 'lefthook.yml',
102
+ '.codex/hooks.json',
101
103
  '.github/renovate.json',
102
104
  '.github/workflows/ultramodern-workspace-gates.yml',
103
105
  '.agents/skills-lock.json',
@@ -132,42 +134,42 @@ const requiredPaths = [
132
134
  'apps/shell-super-app/src/routes/index.css',
133
135
  'apps/shell-super-app/src/routes/layout.tsx',
134
136
  'apps/shell-super-app/src/routes/[lang]/page.tsx',
135
- 'apps/remotes/remote-commerce/package.json',
136
- 'apps/remotes/remote-commerce/modern.config.ts',
137
- 'apps/remotes/remote-commerce/module-federation.config.ts',
138
- 'apps/remotes/remote-commerce/api/effect/index.ts',
139
- 'apps/remotes/remote-commerce/shared/effect/api.ts',
140
- 'apps/remotes/remote-commerce/src/effect/recommendations-client.ts',
141
- 'apps/remotes/remote-commerce/src/modern-app-env.d.ts',
142
- 'apps/remotes/remote-commerce/src/modern.runtime.ts',
143
- 'apps/remotes/remote-commerce/locales/en/translation.json',
144
- 'apps/remotes/remote-commerce/locales/cs/translation.json',
145
- 'apps/remotes/remote-commerce/src/routes/index.css',
146
- 'apps/remotes/remote-commerce/src/routes/layout.tsx',
147
- 'apps/remotes/remote-commerce/src/routes/[lang]/page.tsx',
148
- 'apps/remotes/remote-identity/package.json',
149
- 'apps/remotes/remote-identity/modern.config.ts',
150
- 'apps/remotes/remote-identity/module-federation.config.ts',
151
- 'apps/remotes/remote-identity/api/effect/index.ts',
152
- 'apps/remotes/remote-identity/shared/effect/api.ts',
153
- 'apps/remotes/remote-identity/src/effect/identity-client.ts',
154
- 'apps/remotes/remote-identity/src/modern-app-env.d.ts',
155
- 'apps/remotes/remote-identity/src/modern.runtime.ts',
156
- 'apps/remotes/remote-identity/locales/en/translation.json',
157
- 'apps/remotes/remote-identity/locales/cs/translation.json',
158
- 'apps/remotes/remote-identity/src/routes/index.css',
159
- 'apps/remotes/remote-identity/src/routes/layout.tsx',
160
- 'apps/remotes/remote-identity/src/routes/[lang]/page.tsx',
161
- 'apps/remotes/remote-design-system/package.json',
162
- 'apps/remotes/remote-design-system/modern.config.ts',
163
- 'apps/remotes/remote-design-system/module-federation.config.ts',
164
- 'apps/remotes/remote-design-system/src/modern-app-env.d.ts',
165
- 'apps/remotes/remote-design-system/src/modern.runtime.ts',
166
- 'apps/remotes/remote-design-system/locales/en/translation.json',
167
- 'apps/remotes/remote-design-system/locales/cs/translation.json',
168
- 'apps/remotes/remote-design-system/src/routes/index.css',
169
- 'apps/remotes/remote-design-system/src/routes/layout.tsx',
170
- 'apps/remotes/remote-design-system/src/routes/[lang]/page.tsx',
137
+ 'verticals/commerce/package.json',
138
+ 'verticals/commerce/modern.config.ts',
139
+ 'verticals/commerce/module-federation.config.ts',
140
+ 'verticals/commerce/api/effect/index.ts',
141
+ 'verticals/commerce/shared/effect/api.ts',
142
+ 'verticals/commerce/src/effect/recommendations-client.ts',
143
+ 'verticals/commerce/src/modern-app-env.d.ts',
144
+ 'verticals/commerce/src/modern.runtime.ts',
145
+ 'verticals/commerce/locales/en/translation.json',
146
+ 'verticals/commerce/locales/cs/translation.json',
147
+ 'verticals/commerce/src/routes/index.css',
148
+ 'verticals/commerce/src/routes/layout.tsx',
149
+ 'verticals/commerce/src/routes/[lang]/page.tsx',
150
+ 'verticals/identity/package.json',
151
+ 'verticals/identity/modern.config.ts',
152
+ 'verticals/identity/module-federation.config.ts',
153
+ 'verticals/identity/api/effect/index.ts',
154
+ 'verticals/identity/shared/effect/api.ts',
155
+ 'verticals/identity/src/effect/identity-client.ts',
156
+ 'verticals/identity/src/modern-app-env.d.ts',
157
+ 'verticals/identity/src/modern.runtime.ts',
158
+ 'verticals/identity/locales/en/translation.json',
159
+ 'verticals/identity/locales/cs/translation.json',
160
+ 'verticals/identity/src/routes/index.css',
161
+ 'verticals/identity/src/routes/layout.tsx',
162
+ 'verticals/identity/src/routes/[lang]/page.tsx',
163
+ 'verticals/design-system/package.json',
164
+ 'verticals/design-system/modern.config.ts',
165
+ 'verticals/design-system/module-federation.config.ts',
166
+ 'verticals/design-system/src/modern-app-env.d.ts',
167
+ 'verticals/design-system/src/modern.runtime.ts',
168
+ 'verticals/design-system/locales/en/translation.json',
169
+ 'verticals/design-system/locales/cs/translation.json',
170
+ 'verticals/design-system/src/routes/index.css',
171
+ 'verticals/design-system/src/routes/layout.tsx',
172
+ 'verticals/design-system/src/routes/[lang]/page.tsx',
171
173
  'packages/shared-contracts/src/index.ts',
172
174
  'packages/shared-design-tokens/src/index.ts',
173
175
  'packages/shared-effect-api/src/index.ts',
@@ -177,12 +179,12 @@ if (tailwindEnabled) {
177
179
  requiredPaths.push(
178
180
  'apps/shell-super-app/postcss.config.mjs',
179
181
  'apps/shell-super-app/tailwind.config.ts',
180
- 'apps/remotes/remote-commerce/postcss.config.mjs',
181
- 'apps/remotes/remote-commerce/tailwind.config.ts',
182
- 'apps/remotes/remote-identity/postcss.config.mjs',
183
- 'apps/remotes/remote-identity/tailwind.config.ts',
184
- 'apps/remotes/remote-design-system/postcss.config.mjs',
185
- 'apps/remotes/remote-design-system/tailwind.config.ts',
182
+ 'verticals/commerce/postcss.config.mjs',
183
+ 'verticals/commerce/tailwind.config.ts',
184
+ 'verticals/identity/postcss.config.mjs',
185
+ 'verticals/identity/tailwind.config.ts',
186
+ 'verticals/design-system/postcss.config.mjs',
187
+ 'verticals/design-system/tailwind.config.ts',
186
188
  );
187
189
  }
188
190
 
@@ -194,9 +196,9 @@ assertNotExists('services/service-recommendations-effect');
194
196
 
195
197
  for (const appDirectory of [
196
198
  'apps/shell-super-app',
197
- 'apps/remotes/remote-commerce',
198
- 'apps/remotes/remote-identity',
199
- 'apps/remotes/remote-design-system',
199
+ 'verticals/commerce',
200
+ 'verticals/identity',
201
+ 'verticals/design-system',
200
202
  ]) {
201
203
  assert(
202
204
  !fs.existsSync(path.join(root, appDirectory, 'src/routes/page.tsx')),
@@ -236,12 +238,12 @@ assert(
236
238
  `Root must pin pnpm ${expectedPnpmVersion}`,
237
239
  );
238
240
  assert(
239
- rootPackage.engines?.pnpm === `>=${expectedPnpmVersion} <11.5.0`,
240
- `Root must require pnpm >=${expectedPnpmVersion} <11.5.0`,
241
+ rootPackage.engines?.pnpm === `>=${expectedPnpmVersion} <11.6.0`,
242
+ `Root must require pnpm >=${expectedPnpmVersion} <11.6.0`,
241
243
  );
242
244
  assert(
243
245
  JSON.stringify(readPnpmConfig('packages')) ===
244
- JSON.stringify(['apps/*', 'apps/remotes/*', 'services/*', 'packages/*']),
246
+ JSON.stringify(['apps/*', 'verticals/*', 'packages/*']),
245
247
  'pnpm-workspace.yaml must retain workspace package globs',
246
248
  );
247
249
  assert(readPnpmConfig('minimumReleaseAge') === 0, 'pnpm minimumReleaseAge must be 0');
@@ -277,9 +279,9 @@ assert(
277
279
  '@swc/core': true,
278
280
  'core-js': true,
279
281
  esbuild: true,
282
+ lefthook: true,
280
283
  'msgpackr-extract': true,
281
284
  sharp: true,
282
- 'simple-git-hooks': true,
283
285
  workerd: true,
284
286
  }),
285
287
  'pnpm allowBuilds must approve only the generated workspace build dependencies',
@@ -290,9 +292,9 @@ for (const requiredSnippet of [
290
292
  'pull_request:',
291
293
  'persist-credentials: false',
292
294
  'jdx/mise-action',
293
- 'mise exec -- pnpm install --frozen-lockfile',
294
- 'mise exec -- pnpm run ultramodern:check',
295
- 'mise exec -- pnpm build',
295
+ 'pnpm install --frozen-lockfile',
296
+ 'pnpm run ultramodern:check',
297
+ 'pnpm build',
296
298
  'MODERN_PUBLIC_SITE_URL: http://localhost:8080',
297
299
  'timeout-minutes:',
298
300
  'egress-policy: audit',
@@ -352,7 +354,7 @@ assert(
352
354
 
353
355
  const requiredRootScripts = {
354
356
  build:
355
- 'pnpm -r --filter "./apps/remotes/**" run build && pnpm --filter "./apps/shell-super-app" run build && pnpm ultramodern:assert-mf-types',
357
+ 'pnpm -r --filter "./verticals/**" run build && pnpm --filter "./apps/shell-super-app" run build && pnpm ultramodern:assert-mf-types',
356
358
  format: 'oxfmt .',
357
359
  'format:check': 'oxfmt --check .',
358
360
  lint: 'oxlint .',
@@ -360,7 +362,7 @@ const requiredRootScripts = {
360
362
  'agents:refs:check': 'node ./scripts/setup-agent-reference-repos.mjs --check',
361
363
  'agents:refs:install': 'node ./scripts/setup-agent-reference-repos.mjs',
362
364
  postinstall:
363
- 'node ./scripts/setup-agent-reference-repos.mjs && node ./scripts/bootstrap-agent-skills.mjs',
365
+ 'node ./scripts/bootstrap-agent-skills.mjs && (git rev-parse --is-inside-work-tree >/dev/null 2>&1 && lefthook install || true) && node ./scripts/setup-agent-reference-repos.mjs',
364
366
  'skills:check': 'node ./scripts/bootstrap-agent-skills.mjs --check',
365
367
  'skills:install': 'node ./scripts/bootstrap-agent-skills.mjs',
366
368
  typecheck: `pnpm -r --filter "@${packageScope}/*" typecheck`,
@@ -378,6 +380,7 @@ assert(
378
380
  for (const dependency of [
379
381
  '@effect/tsgo',
380
382
  '@typescript/native-preview',
383
+ 'lefthook',
381
384
  'oxfmt',
382
385
  'oxlint',
383
386
  'ultracite',
@@ -486,20 +489,20 @@ for (const skillName of privateAgentSkills) {
486
489
 
487
490
  const appPackagePaths = [
488
491
  'apps/shell-super-app/package.json',
489
- 'apps/remotes/remote-commerce/package.json',
490
- 'apps/remotes/remote-identity/package.json',
492
+ 'verticals/commerce/package.json',
493
+ 'verticals/identity/package.json',
491
494
  `${designSystemRemotePath}/package.json`,
492
495
  ];
493
496
 
494
497
  const expectedZephyrDependencies = {
495
- commerce: `@${packageScope}/remote-commerce@workspace:*`,
496
- identity: `@${packageScope}/remote-identity@workspace:*`,
497
- designSystem: `@${packageScope}/remote-design-system@workspace:*`,
498
+ commerce: `@${packageScope}/commerce@workspace:*`,
499
+ identity: `@${packageScope}/identity@workspace:*`,
500
+ designSystem: `@${packageScope}/design-system@workspace:*`,
498
501
  };
499
502
 
500
503
  for (const packagePath of appPackagePaths) {
501
504
  const packageJson = readJson(packagePath);
502
- const isRemote = packagePath.includes('/remotes/');
505
+ const isRemote = packagePath.includes('/verticals/');
503
506
  const fullStackVertical = fullStackVerticals.find(
504
507
  (vertical) => `${vertical.path}/package.json` === packagePath,
505
508
  );
@@ -509,7 +512,7 @@ for (const packagePath of appPackagePaths) {
509
512
  (isRemote
510
513
  ? 'modern build && node ../../../scripts/assert-mf-types.mjs'
511
514
  : 'modern build'),
512
- `${packagePath} must enforce Module Federation DTS on remote builds`,
515
+ `${packagePath} must enforce Module Federation DTS on federated builds`,
513
516
  );
514
517
  assert(packageJson.scripts?.serve === 'modern serve', `${packagePath} must use vanilla modern serve`);
515
518
  assert(
@@ -525,13 +528,13 @@ for (const packagePath of appPackagePaths) {
525
528
  if (isRemote) {
526
529
  assert(
527
530
  Object.keys(packageJson['zephyr:dependencies']).length === 0,
528
- `${packagePath} must declare an empty zephyr:dependencies map until it consumes remotes`,
531
+ `${packagePath} must declare an empty zephyr:dependencies map until it consumes verticals`,
529
532
  );
530
533
  } else {
531
534
  assert(
532
535
  JSON.stringify(packageJson['zephyr:dependencies']) ===
533
536
  JSON.stringify(expectedZephyrDependencies),
534
- `${packagePath} must map shell remote aliases to Zephyr workspace remote package dependencies`,
537
+ `${packagePath} must map shell vertical aliases to Zephyr workspace vertical package dependencies`,
535
538
  );
536
539
  }
537
540
  assert(
@@ -624,11 +627,11 @@ for (const packagePath of appPackagePaths) {
624
627
  if (packagePath === `${designSystemRemotePath}/package.json`) {
625
628
  assert(
626
629
  !packageJson.dependencies?.['@modern-js/plugin-bff'],
627
- 'Design-system remote must remain FE-only and must not depend on @modern-js/plugin-bff',
630
+ 'Design-system vertical must remain FE-only and must not depend on @modern-js/plugin-bff',
628
631
  );
629
632
  assert(
630
633
  !packageJson.exports?.['./effect/client'] && !packageJson.exports?.['./shared/effect/api'],
631
- 'Design-system remote must not expose Effect client or contract exports',
634
+ 'Design-system vertical must not expose Effect client or contract exports',
632
635
  );
633
636
  }
634
637
  if (tailwindEnabled) {
@@ -659,9 +662,9 @@ for (const packagePath of appPackagePaths) {
659
662
 
660
663
  for (const federationConfigPath of [
661
664
  'apps/shell-super-app/module-federation.config.ts',
662
- 'apps/remotes/remote-commerce/module-federation.config.ts',
663
- 'apps/remotes/remote-identity/module-federation.config.ts',
664
- 'apps/remotes/remote-design-system/module-federation.config.ts',
665
+ 'verticals/commerce/module-federation.config.ts',
666
+ 'verticals/identity/module-federation.config.ts',
667
+ 'verticals/design-system/module-federation.config.ts',
665
668
  ]) {
666
669
  const federationConfig = readText(federationConfigPath);
667
670
  assert(
@@ -675,9 +678,9 @@ for (const federationConfigPath of [
675
678
 
676
679
  for (const appDirectory of [
677
680
  'apps/shell-super-app',
678
- 'apps/remotes/remote-commerce',
679
- 'apps/remotes/remote-identity',
680
- 'apps/remotes/remote-design-system',
681
+ 'verticals/commerce',
682
+ 'verticals/identity',
683
+ 'verticals/design-system',
681
684
  ]) {
682
685
  if (tailwindEnabled) {
683
686
  assertExists(`${appDirectory}/postcss.config.mjs`);
@@ -697,9 +700,9 @@ for (const appDirectory of [
697
700
 
698
701
  for (const configPath of [
699
702
  'apps/shell-super-app/modern.config.ts',
700
- 'apps/remotes/remote-commerce/modern.config.ts',
701
- 'apps/remotes/remote-identity/modern.config.ts',
702
- 'apps/remotes/remote-design-system/modern.config.ts',
703
+ 'verticals/commerce/modern.config.ts',
704
+ 'verticals/identity/modern.config.ts',
705
+ 'verticals/design-system/modern.config.ts',
703
706
  ]) {
704
707
  const config = readText(configPath);
705
708
  assert(config.includes('presetUltramodern('), `${configPath} must use presetUltramodern`);
@@ -748,16 +751,16 @@ assert(
748
751
  'Shell MF config must share react-dom/client explicitly',
749
752
  );
750
753
  assert(
751
- shellMf.includes('remoteCommerce@http://localhost:3021/mf-manifest.json'),
752
- 'Shell must reference commerce remote',
754
+ shellMf.includes('verticalCommerce@http://localhost:3021/mf-manifest.json'),
755
+ 'Shell must reference commerce vertical',
753
756
  );
754
757
  assert(
755
- shellMf.includes('remoteIdentity@http://localhost:3022/mf-manifest.json'),
756
- 'Shell must reference identity remote',
758
+ shellMf.includes('verticalIdentity@http://localhost:3022/mf-manifest.json'),
759
+ 'Shell must reference identity vertical',
757
760
  );
758
761
  assert(
759
- shellMf.includes('remoteDesignSystem@http://localhost:3023/mf-manifest.json'),
760
- 'Shell must reference design-system remote',
762
+ shellMf.includes('verticalDesignSystem@http://localhost:3023/mf-manifest.json'),
763
+ 'Shell must reference design-system vertical',
761
764
  );
762
765
 
763
766
  const shellPackage = readJson('apps/shell-super-app/package.json');
@@ -813,14 +816,14 @@ for (const vertical of fullStackVerticals) {
813
816
  );
814
817
  }
815
818
 
816
- const designMf = readText('apps/remotes/remote-design-system/module-federation.config.ts');
817
- assert(designMf.includes("name: 'remoteDesignSystem'"), 'Design-system remote MF name is missing');
819
+ const designMf = readText('verticals/design-system/module-federation.config.ts');
820
+ assert(designMf.includes("name: 'verticalDesignSystem'"), 'Design-system federated MF name is missing');
818
821
  assert(
819
822
  designMf.includes("'react-dom/client'"),
820
- 'Design-system remote MF config must share react-dom/client explicitly',
823
+ 'Design-system federated MF config must share react-dom/client explicitly',
821
824
  );
822
- assert(designMf.includes("'./Button'"), 'Design-system remote must expose Button');
823
- assert(designMf.includes("'./tokens'"), 'Design-system remote must expose tokens');
825
+ assert(designMf.includes("'./Button'"), 'Design-system vertical must expose Button');
826
+ assert(designMf.includes("'./tokens'"), 'Design-system vertical must expose tokens');
824
827
  const sharedEffectApi = readText('packages/shared-effect-api/src/index.ts');
825
828
  assert(
826
829
  !sharedEffectApi.includes('recommendationsEffectApi') &&
@@ -832,10 +835,10 @@ assert(
832
835
  const topology = readJson('topology/reference-topology.json');
833
836
  assert(topology.preset === 'presetUltramodern', 'Topology must reference presetUltramodern');
834
837
  assert(topology.shell?.id === 'shell-super-app', 'Topology shell id is incorrect');
835
- assert(topology.shell?.remoteRefs?.length === 3, 'Topology shell must reference three remotes');
836
- assert(topology.remotes?.length === 3, 'Topology must contain three remotes');
838
+ assert(topology.shell?.verticalRefs?.length === 3, 'Topology shell must reference three verticals');
839
+ assert(topology.verticals?.length === 3, 'Topology must contain three verticals');
837
840
  for (const vertical of fullStackVerticals) {
838
- const topologyEntry = topology.remotes.find((remote) => remote.id === vertical.id);
841
+ const topologyEntry = topology.verticals.find((vertical) => vertical.id === vertical.id);
839
842
  assert(topologyEntry?.kind === 'vertical', `${vertical.id} must be a vertical topology entry`);
840
843
  assert(
841
844
  topologyEntry?.moduleFederation?.manifestUrl?.includes('/mf-manifest.json') &&
@@ -849,21 +852,21 @@ for (const vertical of fullStackVerticals) {
849
852
  );
850
853
  }
851
854
  assert(
852
- topology.remotes.some(
853
- (remote) => remote.id === 'remote-design-system' && remote.kind === 'horizontal-design-system',
855
+ topology.verticals.some(
856
+ (vertical) => vertical.id === 'design-system' && vertical.kind === 'vertical',
854
857
  ),
855
- 'Topology must contain the horizontal design-system remote',
858
+ 'Topology must contain the horizontal design-system vertical',
856
859
  );
857
860
  assert(
858
- (topology.effectServices ?? []).length === 0,
859
- 'Default vertical-owned APIs must not be generated as topology.effectServices',
861
+ !('effectServices' in topology),
862
+ 'Topology must not expose effectServices; vertical APIs are owned by vertical packages',
860
863
  );
861
864
  assert(topology.sharedPackages?.length === 3, 'Topology must contain shared package placeholders');
862
865
 
863
866
  const ownership = readJson('topology/ownership.json');
864
867
  assert(
865
868
  ownership.owners?.some(
866
- (owner) => owner.id === 'remote-commerce' && owner.ownership?.team === 'commerce-experience',
869
+ (owner) => owner.id === 'commerce' && owner.ownership?.team === 'commerce-experience',
867
870
  ),
868
871
  'Ownership metadata must retain commerce owner',
869
872
  );
@@ -917,7 +920,7 @@ assert(
917
920
  'Template manifest must list every pinned private agent skill entry',
918
921
  );
919
922
  assert(
920
- manifest.validation?.expectedCommands?.includes('mise exec -- pnpm run ultramodern:check'),
923
+ manifest.validation?.expectedCommands?.includes('pnpm run ultramodern:check'),
921
924
  'Template manifest must document the validation command',
922
925
  );
923
926
  assert(