@ultimat3/cli 27.3.0 → 27.4.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimat3/cli",
3
- "version": "27.3.0",
3
+ "version": "27.4.0",
4
4
  "description": "The `x` binary: new, dev, build, verify, generate, db, mcp, doctor, deploy",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -39,33 +39,33 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@babel/core": "^8.0.1",
42
- "@ultimat3/action": "27.3.0",
43
- "@ultimat3/admin": "27.3.0",
44
- "@ultimat3/ai": "27.3.0",
45
- "@ultimat3/auth": "27.3.0",
46
- "@ultimat3/cache": "27.3.0",
47
- "@ultimat3/core": "27.3.0",
48
- "@ultimat3/db": "27.3.0",
49
- "@ultimat3/entity": "27.3.0",
50
- "@ultimat3/flags": "27.3.0",
51
- "@ultimat3/http": "27.3.0",
52
- "@ultimat3/i18n": "27.3.0",
53
- "@ultimat3/jobs": "27.3.0",
54
- "@ultimat3/mail": "27.3.0",
55
- "@ultimat3/manifest": "27.3.0",
56
- "@ultimat3/mcp": "27.3.0",
57
- "@ultimat3/money": "27.3.0",
58
- "@ultimat3/notify": "27.3.0",
59
- "@ultimat3/policy": "27.3.0",
60
- "@ultimat3/pwa": "27.3.0",
61
- "@ultimat3/query": "27.3.0",
62
- "@ultimat3/realtime": "27.3.0",
63
- "@ultimat3/render": "27.3.0",
64
- "@ultimat3/schema": "27.3.0",
65
- "@ultimat3/seo": "27.3.0",
66
- "@ultimat3/storage": "27.3.0",
67
- "@ultimat3/testing": "27.3.0",
68
- "@ultimat3/time": "27.3.0",
42
+ "@ultimat3/action": "27.4.0",
43
+ "@ultimat3/admin": "27.4.0",
44
+ "@ultimat3/ai": "27.4.0",
45
+ "@ultimat3/auth": "27.4.0",
46
+ "@ultimat3/cache": "27.4.0",
47
+ "@ultimat3/core": "27.4.0",
48
+ "@ultimat3/db": "27.4.0",
49
+ "@ultimat3/entity": "27.4.0",
50
+ "@ultimat3/flags": "27.4.0",
51
+ "@ultimat3/http": "27.4.0",
52
+ "@ultimat3/i18n": "27.4.0",
53
+ "@ultimat3/jobs": "27.4.0",
54
+ "@ultimat3/mail": "27.4.0",
55
+ "@ultimat3/manifest": "27.4.0",
56
+ "@ultimat3/mcp": "27.4.0",
57
+ "@ultimat3/money": "27.4.0",
58
+ "@ultimat3/notify": "27.4.0",
59
+ "@ultimat3/policy": "27.4.0",
60
+ "@ultimat3/pwa": "27.4.0",
61
+ "@ultimat3/query": "27.4.0",
62
+ "@ultimat3/realtime": "27.4.0",
63
+ "@ultimat3/render": "27.4.0",
64
+ "@ultimat3/schema": "27.4.0",
65
+ "@ultimat3/seo": "27.4.0",
66
+ "@ultimat3/storage": "27.4.0",
67
+ "@ultimat3/testing": "27.4.0",
68
+ "@ultimat3/time": "27.4.0",
69
69
  "babel-preset-solid": "^1.9.15"
70
70
  }
71
71
  }
@@ -0,0 +1,46 @@
1
+ // The one feature layout, made a build error: a primitive module `actions.ts` (or `live`,
2
+ // `queries`, `jobs`, `tasks`) beside the directory of the same name is refused. `x g` writes the
3
+ // directory form — `<slice>/actions/<name>.ts`, one primitive per file — and an app that also keeps
4
+ // `actions.ts` has two homes for one kind of thing, where `./actions` resolves to the file and never
5
+ // the directory. A component module beside its folder (`ui.tsx` + `ui/`) is not a primitive's home,
6
+ // and `x g resource` writes exactly that pair.
7
+
8
+ import { ERROR_DOCS_URL } from '@ultimat3/core';
9
+ import type { SourceFile } from './app-boundaries';
10
+ import type { Finding } from './output';
11
+
12
+ /** The directories `x g` writes primitives into — the only names the refusal reads. */
13
+ export const PRIMITIVE_DIRS: ReadonlySet<string> = new Set([
14
+ 'actions',
15
+ 'live',
16
+ 'queries',
17
+ 'jobs',
18
+ 'tasks',
19
+ ]);
20
+
21
+ const MODULE = /^(?<stem>.+)\.(?:ts|tsx)$/;
22
+
23
+ /** Every primitive module `X.ts` among `files` beside a directory `X/` holding another of them. */
24
+ export function siblingModuleFindings(files: readonly SourceFile[]): readonly Finding[] {
25
+ const directories = new Set<string>();
26
+ for (const { path } of files) {
27
+ const parts = path.split('/');
28
+ for (let depth = 1; depth < parts.length; depth += 1) {
29
+ directories.add(parts.slice(0, depth).join('/'));
30
+ }
31
+ }
32
+ return files.flatMap(({ path }): Finding[] => {
33
+ const stem = MODULE.exec(path)?.groups?.['stem'];
34
+ const name = stem?.split('/').at(-1) ?? '';
35
+ if (stem === undefined || !PRIMITIVE_DIRS.has(name) || !directories.has(stem)) return [];
36
+ return [
37
+ {
38
+ code: 'X_LAYOUT_SIBLING_MODULE',
39
+ cause: `${path} sits beside the directory ${stem}/ — \`./${name}\` resolves to the file, and the directory form is the one layout`,
40
+ fix: `x verify --only boundaries --json # move each declaration in ${path} to ${stem}/<its-export-in-kebab-case>.ts, then delete ${path}`,
41
+ docs: ERROR_DOCS_URL,
42
+ at: path,
43
+ },
44
+ ];
45
+ });
46
+ }
@@ -5,6 +5,7 @@
5
5
 
6
6
  import type { SourceFile } from './app-boundaries';
7
7
  import { appImportGraph, checkImportRules, readAppSources } from './app-boundaries';
8
+ import { siblingModuleFindings } from './app-layout';
8
9
  import { appTransportFindings } from './app-transport';
9
10
  import { planBoundaryCuts } from './boundary-cuts';
10
11
  import type { Finding } from './output';
@@ -44,5 +45,6 @@ export async function appBoundaryFindings(
44
45
  return [
45
46
  ...withCutEdits(checkImportRules(files), appImportGraph(files)),
46
47
  ...(await appTransportFindings(root, files)),
48
+ ...siblingModuleFindings(files),
47
49
  ];
48
50
  }
@@ -232,6 +232,7 @@ export const CLI_OWNED_ERROR_CODES = [
232
232
  'X_PACKAGE_TEST_ONLY_SHIPPED',
233
233
  'X_ISLAND_MODULE_DUPLICATED',
234
234
  'X_BACKFILL_SLICE_ENTITY',
235
+ 'X_LAYOUT_SIBLING_MODULE',
235
236
  ] as const;
236
237
 
237
238
  /**
@@ -420,6 +421,7 @@ export const CLI_ERROR_TITLES: Readonly<Record<CliOwnedErrorCode, string>> = {
420
421
  X_PACKAGE_TEST_ONLY_SHIPPED: 'a test-only module ships in the tarball',
421
422
  X_ISLAND_MODULE_DUPLICATED: 'An island chunk bundles one module more than once',
422
423
  X_BACKFILL_SLICE_ENTITY: 'the slice holds no entity a generated backfill can sweep',
424
+ X_LAYOUT_SIBLING_MODULE: 'a primitive module beside its directory',
423
425
  };
424
426
 
425
427
  // One unconditional call, so a second package claiming one of the CLI's codes throws
package/src/mcp-errors.ts CHANGED
@@ -302,6 +302,8 @@ const CLI_FIXES: Readonly<Record<CliErrorCode, string>> = {
302
302
  'gh issue create --repo developerz-ai/ultimate --title "X_ISLAND_MODULE_DUPLICATED" # paste this error\'s --json as the body: the framework bundled one of its own modules twice',
303
303
  X_BACKFILL_SLICE_ENTITY:
304
304
  'x errors explain X_BACKFILL_SLICE_ENTITY --json # the refusal itself names the x g job line for this slice',
305
+ X_LAYOUT_SIBLING_MODULE:
306
+ 'x verify --only boundaries --json # then move each declaration in X.ts to X/<name>.ts, one primitive per file',
305
307
  };
306
308
 
307
309
  const isCliCode = (code: string): code is CliErrorCode =>