@ultimat3/cli 20.2.1 → 22.0.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.
Files changed (237) hide show
  1. package/CLAUDE.md +84 -1582
  2. package/README.md +40 -2
  3. package/package.json +31 -31
  4. package/src/api-registration.ts +124 -0
  5. package/src/app-artifacts.ts +39 -0
  6. package/src/app-boundaries.ts +5 -10
  7. package/src/app-env.ts +2 -2
  8. package/src/app-load.ts +37 -5
  9. package/src/app-openapi.ts +27 -0
  10. package/src/app-permissions.ts +0 -0
  11. package/src/app-root.ts +1 -1
  12. package/src/async-pages.ts +32 -0
  13. package/src/bin.ts +7 -1
  14. package/src/boundary-findings.ts +36 -0
  15. package/src/browser-launcher-fake-html.ts +80 -0
  16. package/src/browser-launcher-fake.ts +165 -0
  17. package/src/browser-launcher-port.ts +159 -0
  18. package/src/browser-launcher.ts +26 -133
  19. package/src/budgets.ts +56 -13
  20. package/src/build-errors.ts +54 -0
  21. package/src/cdp-shot-a11y.ts +77 -0
  22. package/src/cdp-shot-clock.ts +14 -0
  23. package/src/cdp-shot-driver.ts +150 -0
  24. package/src/cdp-shot-element.ts +147 -0
  25. package/src/cdp-shot-errors.ts +62 -0
  26. package/src/cdp-shot-keys.ts +152 -0
  27. package/src/cdp-shot-page.ts +230 -0
  28. package/src/cdp-shot-watch.ts +241 -0
  29. package/src/cmd-affected-spec.ts +24 -0
  30. package/src/cmd-affected.ts +3 -19
  31. package/src/cmd-build-spec.ts +16 -0
  32. package/src/cmd-build.ts +46 -20
  33. package/src/cmd-ci-spec.ts +24 -0
  34. package/src/cmd-ci.ts +17 -21
  35. package/src/cmd-db-branch.ts +2 -2
  36. package/src/cmd-db-spec.ts +99 -0
  37. package/src/cmd-db.ts +15 -94
  38. package/src/cmd-deploy-helm.ts +136 -0
  39. package/src/cmd-deploy-spec.ts +40 -0
  40. package/src/cmd-deploy.ts +117 -42
  41. package/src/cmd-dev-spec.ts +25 -0
  42. package/src/cmd-dev.ts +78 -122
  43. package/src/cmd-docs-spec.ts +16 -0
  44. package/src/cmd-docs.ts +2 -11
  45. package/src/cmd-doctor-spec.ts +21 -0
  46. package/src/cmd-doctor.ts +4 -18
  47. package/src/cmd-env-spec.ts +18 -0
  48. package/src/cmd-env.ts +4 -13
  49. package/src/cmd-errors-spec.ts +23 -0
  50. package/src/cmd-errors.ts +3 -17
  51. package/src/cmd-fix-spec.ts +18 -0
  52. package/src/cmd-fix.ts +4 -13
  53. package/src/cmd-generate-spec.ts +31 -0
  54. package/src/cmd-generate.ts +46 -42
  55. package/src/cmd-i18n-spec.ts +16 -0
  56. package/src/cmd-i18n.ts +7 -14
  57. package/src/cmd-jobs-spec.ts +56 -0
  58. package/src/cmd-jobs.ts +3 -50
  59. package/src/cmd-manifest-spec.ts +15 -0
  60. package/src/cmd-manifest.ts +19 -20
  61. package/src/cmd-mcp-spec.ts +21 -0
  62. package/src/cmd-mcp.ts +2 -15
  63. package/src/cmd-new-spec.ts +33 -0
  64. package/src/cmd-new.ts +38 -33
  65. package/src/cmd-policy-spec.ts +13 -0
  66. package/src/cmd-policy.ts +2 -9
  67. package/src/cmd-pr-spec.ts +39 -0
  68. package/src/cmd-pr.ts +5 -65
  69. package/src/cmd-registries-spec.ts +32 -0
  70. package/src/cmd-registries.ts +4 -25
  71. package/src/cmd-routes-spec.ts +12 -0
  72. package/src/cmd-routes.ts +2 -7
  73. package/src/cmd-secrets-spec.ts +19 -0
  74. package/src/cmd-secrets.ts +22 -34
  75. package/src/cmd-shot-island.ts +12 -13
  76. package/src/cmd-shot-spec.ts +53 -0
  77. package/src/cmd-shot.ts +11 -60
  78. package/src/cmd-tasks-spec.ts +21 -0
  79. package/src/cmd-tasks.ts +2 -16
  80. package/src/cmd-test-spec.ts +54 -0
  81. package/src/cmd-test.ts +4 -49
  82. package/src/cmd-verify-spec.ts +28 -0
  83. package/src/cmd-verify.ts +3 -23
  84. package/src/db-seed.ts +4 -2
  85. package/src/dev-dashboard.ts +4 -4
  86. package/src/dev-lock.ts +18 -2
  87. package/src/dev-port.ts +21 -0
  88. package/src/dev-route-table.ts +119 -0
  89. package/src/dispatch.ts +12 -5
  90. package/src/document-styles.ts +1 -1
  91. package/src/drift.ts +4 -18
  92. package/src/error-catalog.ts +16 -9
  93. package/src/error-codes.ts +33 -28
  94. package/src/error-pages.ts +19 -7
  95. package/src/error-unthrown.ts +130 -0
  96. package/src/errors.ts +22 -29
  97. package/src/favicon.ts +2 -2
  98. package/src/fix-imports.ts +1 -1
  99. package/src/fix-scan.ts +2 -9
  100. package/src/flag-reads.ts +1 -2
  101. package/src/foreign-text.ts +36 -0
  102. package/src/framework-schema.ts +5 -6
  103. package/src/generate-feature.ts +42 -0
  104. package/src/generate-files.ts +7 -3
  105. package/src/generate-grants.ts +83 -0
  106. package/src/generate-kinds.ts +56 -4
  107. package/src/i18n-index.ts +59 -10
  108. package/src/icon-assets.ts +1 -1
  109. package/src/image-prepare.ts +14 -0
  110. package/src/import-scan.ts +63 -0
  111. package/src/index.ts +67 -334
  112. package/src/invocation-flags.ts +26 -0
  113. package/src/island-bundle.ts +38 -11
  114. package/src/island-capture.ts +6 -6
  115. package/src/island-harness-script.ts +6 -2
  116. package/src/island-realtime.ts +98 -0
  117. package/src/island-shot.ts +5 -0
  118. package/src/island-store.ts +131 -0
  119. package/src/island-verdict.ts +2 -2
  120. package/src/job-registration.ts +42 -0
  121. package/src/jobs-driver.ts +2 -2
  122. package/src/live-routes.ts +82 -42
  123. package/src/load-findings.ts +51 -0
  124. package/src/mcp-db-target.ts +1 -1
  125. package/src/mcp-errors.ts +30 -26
  126. package/src/mcp-host.ts +27 -12
  127. package/src/mcp-ui-diff.ts +27 -0
  128. package/src/mcp-ui-inspect.ts +4 -4
  129. package/src/mcp-ui-interact.ts +21 -15
  130. package/src/mcp-ui.ts +19 -15
  131. package/src/measure-database.ts +73 -0
  132. package/src/measure-paths.ts +74 -0
  133. package/src/measure-scope.ts +74 -0
  134. package/src/messages.ts +1 -3
  135. package/src/metrics-endpoint.ts +1 -1
  136. package/src/otlp-export.ts +1 -1
  137. package/src/output.ts +6 -0
  138. package/src/page-sync.ts +54 -0
  139. package/src/permission-grants.ts +86 -0
  140. package/src/prerender-out.ts +25 -0
  141. package/src/prerender.ts +121 -102
  142. package/src/pwa-artifacts.ts +3 -3
  143. package/src/realtime-browser-probe-fixture.ts +2 -2
  144. package/src/reexport-manifest.ts +2 -1
  145. package/src/registry.ts +80 -56
  146. package/src/role-realtime.ts +36 -0
  147. package/src/{dev-replicator.ts → role-replicator.ts} +1 -1
  148. package/src/{dev-roles-fixture.ts → role-start-fixture.ts} +9 -5
  149. package/src/role-start-types.ts +112 -0
  150. package/src/{dev-roles.ts → role-start.ts} +42 -115
  151. package/src/{dev-sync.ts → role-sync.ts} +23 -11
  152. package/src/root-env.ts +67 -0
  153. package/src/{dev-assets.ts → runtime-assets.ts} +7 -7
  154. package/src/{dev-services.ts → runtime-bindings.ts} +43 -17
  155. package/src/{dev-cache.ts → runtime-cache.ts} +2 -2
  156. package/src/runtime-jobs.ts +87 -0
  157. package/src/{dev-live-feed.ts → runtime-live-feed.ts} +20 -5
  158. package/src/{dev-notify-retention.ts → runtime-notify-retention.ts} +1 -1
  159. package/src/{dev-purge.ts → runtime-purge.ts} +2 -2
  160. package/src/{dev-queue.ts → runtime-queue.ts} +4 -4
  161. package/src/runtime-realtime.ts +55 -0
  162. package/src/{dev-render.ts → runtime-render.ts} +119 -20
  163. package/src/{dev-replica.ts → runtime-replica.ts} +2 -2
  164. package/src/{dev-runtime.ts → runtime-services.ts} +41 -17
  165. package/src/{dev-storage.ts → runtime-storage.ts} +4 -4
  166. package/src/scaffold-fixture.ts +28 -6
  167. package/src/scaffold-typecheck.ts +6 -3
  168. package/src/schema-drift.ts +7 -1
  169. package/src/script-csp.ts +5 -2
  170. package/src/secrets-rotation.ts +59 -0
  171. package/src/serve-boot.ts +192 -0
  172. package/src/serve-drain.ts +24 -0
  173. package/src/serve-entry.ts +6 -0
  174. package/src/serve-env.ts +116 -0
  175. package/src/serve-types.ts +55 -0
  176. package/src/serve.ts +44 -338
  177. package/src/shot-server.ts +2 -2
  178. package/src/shot-settle.ts +10 -1
  179. package/src/shot-theme.ts +3 -3
  180. package/src/shot-verdict.ts +16 -7
  181. package/src/signal-shred.ts +27 -0
  182. package/src/solid-loader.ts +26 -2
  183. package/src/static-report.ts +8 -1
  184. package/src/sw-artifacts.ts +13 -3
  185. package/src/sync-url.ts +31 -0
  186. package/src/templates/action.ts +30 -16
  187. package/src/templates/entity.ts +12 -7
  188. package/src/templates/index.ts +1 -1
  189. package/src/templates/job.ts +10 -7
  190. package/src/templates/policy.ts +20 -2
  191. package/src/templates/resource-create.ts +127 -0
  192. package/src/templates/resource-form-island.ts +76 -30
  193. package/src/templates/resource.ts +10 -4
  194. package/src/templates/route.ts +3 -0
  195. package/src/templates/scaffold-app.ts +4 -1
  196. package/src/templates/scaffold-auth.ts +3 -1
  197. package/src/templates/scaffold-container-compose.ts +184 -0
  198. package/src/templates/scaffold-container.ts +25 -145
  199. package/src/templates/scaffold-dashboard-example.ts +2 -2
  200. package/src/templates/scaffold-db-package.ts +16 -3
  201. package/src/templates/scaffold-demo-org.ts +41 -0
  202. package/src/templates/scaffold-entries.ts +1 -1
  203. package/src/templates/scaffold-env.ts +6 -0
  204. package/src/templates/scaffold-helm-templates.ts +66 -7
  205. package/src/templates/scaffold-helm.ts +27 -5
  206. package/src/templates/scaffold-i18n.ts +15 -10
  207. package/src/templates/scaffold-repo.ts +13 -10
  208. package/src/templates/scaffold-roles.ts +38 -10
  209. package/src/templates/slice-foundation.ts +1 -1
  210. package/src/templates/wrap.ts +4 -1
  211. package/src/test-passes.ts +2 -1
  212. package/src/test-workers.ts +26 -0
  213. package/src/ts-scan.ts +3 -6
  214. package/src/tsconfig-references.ts +1 -2
  215. package/src/verify-checks.ts +41 -39
  216. package/src/verify-e2e.ts +41 -0
  217. package/src/verify-run.ts +115 -50
  218. package/src/verify-step.ts +3 -3
  219. package/src/verify-tests.ts +22 -30
  220. package/src/verify-typecheck.ts +28 -0
  221. package/src/web-binding.ts +2 -2
  222. package/src/worker-bundle.ts +192 -0
  223. package/src/workspace-graph.ts +10 -33
  224. package/src/cdp-browser.ts +0 -100
  225. package/src/cdp-connection.ts +0 -211
  226. package/src/cdp-e2e-page.ts +0 -209
  227. package/src/cdp-errors.ts +0 -56
  228. package/src/cdp-launch.ts +0 -139
  229. package/src/e2e-dom-fixture.ts +0 -117
  230. package/src/e2e-driver.ts +0 -97
  231. package/src/e2e-errors.ts +0 -103
  232. package/src/e2e-evaluate.ts +0 -156
  233. package/src/e2e-locator.ts +0 -86
  234. package/src/e2e-page.ts +0 -150
  235. package/src/e2e-selection.ts +0 -182
  236. package/src/measurement-actor.ts +0 -26
  237. /package/src/{dev-hooks.ts → runtime-hooks.ts} +0 -0
@@ -0,0 +1,14 @@
1
+ // What `x build --target docker` does before `docker build`: stamp the image with the manifest's
2
+ // build id and write the island chunks it will serve (`island-store.ts`), so a container boot
3
+ // neither re-derives the one nor rebuilds the other.
4
+
5
+ import { appManifest } from './app-manifest';
6
+ import { buildIslands } from './island-bundle';
7
+ import { writeIslandStore } from './island-store';
8
+
9
+ /** Writes `.x/islands/` and answers the build id the image is stamped with. */
10
+ export async function prepareImage(root: string): Promise<string> {
11
+ const { manifest } = await appManifest(root);
12
+ await writeIslandStore(root, await buildIslands(root));
13
+ return manifest.buildId;
14
+ }
@@ -0,0 +1,63 @@
1
+ // The one import scanner: Bun's transpiler, fed the source with type-only imports rewritten so it
2
+ // reports them too. A leaf — it imports nothing — so `scripts/boundaries.ts`, which must run with
3
+ // no `node_modules`, reads it by path. A regex scanner beside it read a nested template's
4
+ // `import … from '@ultimat3/ui'` as the generator's own import (#493); the transpiler never does.
5
+
6
+ /** A file as the scanners take it: repo-relative POSIX path and its text. */
7
+ export interface ScannedFile {
8
+ readonly path: string;
9
+ readonly source: string;
10
+ }
11
+
12
+ /** The transpiler rejects a shebang, and a `bin.ts` legitimately has one. */
13
+ export const stripShebang = (source: string): string =>
14
+ source.startsWith('#!') ? source.slice(source.indexOf('\n') + 1) : source;
15
+
16
+ /**
17
+ * `scanImports` ERASES `import type` / `export type`. Dropping the keyword before the parse makes
18
+ * the transpiler report one as an ordinary import. The lookahead keeps `export type Foo = string`
19
+ * — an alias, not an import — from becoming a syntax error.
20
+ */
21
+ const TYPE_ONLY_CLAUSE = /\b(import|export)\s+type\s+(?=[{*]|[A-Za-z_$][\w$]*\s+from\b)/g;
22
+
23
+ export const dropTypeKeyword = (source: string): string => source.replace(TYPE_ONLY_CLAUSE, '$1 ');
24
+
25
+ /**
26
+ * The inline spelling `import { type Foo } from 'x'`, whose whole list is type-only and so erased.
27
+ * The list is DELETED rather than de-`type`d — deciding which `type` is a modifier is the parser's
28
+ * job — and a side-effect import carries the one thing a scan reads, the specifier.
29
+ */
30
+ const BRACE_IMPORT =
31
+ /(^|[\s;}])(?:import|export)\s+(?:[A-Za-z_$][\w$]*\s*,\s*)?\{[^{}]*\}\s*from\s*(['"])([^'"\n]+)\2/g;
32
+
33
+ export const asSideEffectImports = (source: string): string =>
34
+ source.replace(BRACE_IMPORT, '$1import $2$3$2');
35
+
36
+ const loaderOf = (path: string): 'ts' | 'tsx' => (path.endsWith('x') ? 'tsx' : 'ts');
37
+
38
+ /** What survives type erasure: static, re-export, side-effect and dynamic imports, and `require`. */
39
+ export function scanRuntimeImports(file: ScannedFile): readonly string[] {
40
+ return new Bun.Transpiler({ loader: loaderOf(file.path) })
41
+ .scanImports(stripShebang(file.source))
42
+ .map((entry) => entry.path);
43
+ }
44
+
45
+ /**
46
+ * Every specifier the file names, type-only ones included. Throws when the file does not parse —
47
+ * a scan that answered `[]` there would read as a file importing nothing. The rewrite pass alone
48
+ * is forgiving: a rewrite the parser refuses falls back to the runtime scan.
49
+ */
50
+ export function scanAllImports(file: ScannedFile): readonly string[] {
51
+ const runtime = scanRuntimeImports(file);
52
+ let typed: readonly string[] = [];
53
+ try {
54
+ const rewritten = asSideEffectImports(dropTypeKeyword(stripShebang(file.source)));
55
+ typed = new Bun.Transpiler({ loader: loaderOf(file.path) })
56
+ .scanImports(rewritten)
57
+ .map((entry) => entry.path);
58
+ } catch {
59
+ typed = [];
60
+ }
61
+ // The rewritten pass first: it holds every import in SOURCE order, which callers report in.
62
+ return [...new Set([...typed, ...runtime])];
63
+ }
package/src/index.ts CHANGED
@@ -2,213 +2,67 @@
2
2
  // on these, and a barrel that re-exports everything would make every internal a compatibility
3
3
  // promise.
4
4
 
5
+ // The CLI's own codes and titles, registered for every process that imports this barrel — the
6
+ // gate's registry check (`scripts/verify.ts` → `registeredErrorCodes`) reads the registry, and the
7
+ // command modules that used to import `error-codes.ts` on the way load lazily since 22.0.0.
8
+ import './error-codes';
9
+
5
10
  /** The app's own API over HTTP — the one table `x dev` and a container both mount. */
6
11
  export { apiRoutes } from './api-routes';
7
- export type { BoundaryCode, SourceFile } from './app-boundaries';
12
+ export type { SourceFile } from './app-boundaries';
8
13
  export {
9
14
  appImportGraph,
10
- BOUNDARY_CODES,
11
15
  checkAppBoundaries,
12
- checkImportRules,
13
16
  readAppSources,
14
17
  resolveSpecifier,
15
18
  scanRuntimeImports,
16
19
  } from './app-boundaries';
17
- export type { LoadedApp } from './app-load';
18
- export { loadApp, resetAppLoad } from './app-load';
19
- export type { AppManifest } from './app-manifest';
20
- export { appManifest, policyFacts, readAppManifest, writeAppManifest } from './app-manifest';
21
- export { OPENAPI_FILE, openApiJson } from './app-openapi';
22
- export type { AppRoot } from './app-root';
23
- export { findAppRoot, requireAppRoot, requireBunVersion, versionAtLeast } from './app-root';
24
- export type { BoundaryCut, BoundarySplit } from './boundary-cuts';
25
- export { planBoundaryCuts } from './boundary-cuts';
26
- export type { BuildStats, RouteStats } from './budgets';
27
- export { BUILD_STATS_FILE, checkBudgets, readBuildStats } from './budgets';
28
- // The raw-CDP browser the driver above runs on. `openE2eBrowserIfAvailable()` is what an app's
29
- // test preload calls: it answers `undefined` on a machine with no Chrome, so the browser-backed
30
- // suite SKIPS rather than turning a gate red for a reason unrelated to the change.
31
- export type { E2eBrowser, OpenE2eBrowserOptions } from './cdp-browser';
32
- export {
33
- DEFAULT_CDP_TIMEOUT_MS,
34
- openE2eBrowser,
35
- openE2eBrowserIfAvailable,
36
- } from './cdp-browser';
37
- export type { CdpConnection, CdpConnectionOptions, CdpResult } from './cdp-connection';
38
- export { cdpConnect } from './cdp-connection';
39
- export type { CdpE2ePageOptions } from './cdp-e2e-page';
40
- export { cdpE2ePage } from './cdp-e2e-page';
41
- export {
42
- CdpBrowserMissingError,
43
- CdpCallFailedError,
44
- CdpLaunchFailedError,
45
- CdpTimeoutError,
46
- } from './cdp-errors';
47
- export type { LaunchedBrowser, LaunchOptions } from './cdp-launch';
48
- export {
49
- CHROME_CANDIDATES,
50
- CHROME_PATH_ENV,
51
- findChrome,
52
- launchChrome,
53
- launchFoundChrome,
54
- } from './cdp-launch';
55
- export type { BuildTarget } from './cmd-build';
56
- export {
57
- argsFor,
58
- BUILD_ENTRY,
59
- BUILD_TARGETS,
60
- buildCommand,
61
- readTarget,
62
- requireEntry,
63
- } from './cmd-build';
20
+ export { loadApp } from './app-load';
21
+ export { appManifest, writeAppManifest } from './app-manifest';
22
+ export { requireAppRoot } from './app-root';
23
+ export type { RouteStats } from './budgets';
24
+ export { checkBudgets, FRAMEWORK_INLINE_SCRIPTS, FRAMEWORK_SCRIPTS } from './budgets';
25
+ export { BUILD_ENTRY, BUILD_TARGETS, readTarget } from './cmd-build';
64
26
  export { dbCommand } from './cmd-db';
65
- export { runBranchCommand } from './cmd-db-branch';
66
- export type { DeployPlan } from './cmd-deploy';
67
- export { deployCommand, planDeploy } from './cmd-deploy';
68
- export type { DevServer, StartDevOptions } from './cmd-dev';
69
- export { devCommand, startDev } from './cmd-dev';
70
- export type { DoctorProbe, EmbeddedDatabase } from './cmd-doctor';
71
- export {
72
- doctorCommand,
73
- ENV_DEVELOPMENT,
74
- embeddedDatabaseFinding,
75
- probeFor,
76
- runDoctor,
77
- } from './cmd-doctor';
78
- export { ERRORS_SUBCOMMANDS, errorsCommand } from './cmd-errors';
79
- export { FIX_SUBCOMMANDS, fixCommand } from './cmd-fix';
27
+ export { planDeploy } from './cmd-deploy';
28
+ export { startDev } from './cmd-dev';
29
+ export type { DoctorProbe } from './cmd-doctor';
80
30
  export type { GenerateOptions, Generator } from './cmd-generate';
81
- export { GENERATORS, generate, generateCommand, writeFiles } from './cmd-generate';
82
- export { createHelpCommand, createVersionCommand, renderHelp } from './cmd-help';
83
- export { buildDrainTarget, JOBS_SUBCOMMANDS, jobsCommand } from './cmd-jobs';
84
- export { manifestCommand } from './cmd-manifest';
85
- export type { McpHttpServer } from './cmd-mcp';
86
- export { mcpCommand, startMcpHttp } from './cmd-mcp';
87
- export type { NewAppOptions, WrittenApp } from './cmd-new';
31
+ export { GENERATORS, generate, writeFiles } from './cmd-generate';
32
+ export { JOBS_SUBCOMMANDS } from './cmd-jobs';
88
33
  export { newCommand, planNewApp, writeNewApp } from './cmd-new';
89
- export type { PlannedCommand, PlannedSubcommand } from './cmd-planned';
90
- export {
91
- PLANNED_COMMANDS,
92
- PLANNED_SUBCOMMANDS,
93
- plannedCommands,
94
- plannedSubcommand,
95
- } from './cmd-planned';
34
+ export { PLANNED_COMMANDS, PLANNED_SUBCOMMANDS, plannedSubcommand } from './cmd-planned';
96
35
  // `shotCommand`, `prCommand` and `ciCommand` are deliberately NOT re-exported here. They reach
97
36
  // `x` through `registry.ts`, which is the only thing that makes a command exist — and the barrel
98
- // is the surface an APP imports. Exporting them puts `cmd-shot.ts` in the module graph of every
99
- // app that imports `@ultimat3/cli`, which then has to resolve `@ultimat3/scraping` — a browser
100
- // driver it never uses. Measured: it reds `tsc -b` on `dummy/social-media-clone` with five
101
- // TS2307s in files that app never calls. The app path does not pay for the tool path.
102
- export { actionsCommand, entitiesCommand, queriesCommand } from './cmd-registries';
103
- export { renderRouteTable, routesCommand } from './cmd-routes';
104
- export { testCommand } from './cmd-test';
37
+ // is the surface an APP imports. Exporting them would put the browser driver and the GitHub client
38
+ // in the module graph of every app that imports `@ultimat3/cli`, for tools it never calls. The app
39
+ // path does not pay for the tool path.
40
+ export { renderRouteTable } from './cmd-routes';
105
41
  export { runVerify, VERIFY_STEPS, verifyCommand, verifyStepNames } from './cmd-verify';
106
- export type { CliCommand, CommandContext } from './command';
42
+ export type { CliCommand } from './command';
107
43
  export { failed, ok } from './command';
108
- export { acceptCreatedTables, createdTables } from './db-accept-created';
109
- export type { BranchRow, BranchSubcommand } from './db-branch';
110
- export {
111
- BRANCH_SUBCOMMANDS,
112
- branchDatabaseName,
113
- branchNameOf,
114
- isBranchSubcommand,
115
- pgliteBranchName,
116
- previewUrl,
117
- } from './db-branch';
118
- export type { GeneratedFiles, GenerateMigrationOptions, GenerateOutcome } from './db-generate';
119
- export { generateAppMigration, migrationSql } from './db-generate';
120
- export type { SubscribingQuery } from './db-subscribes';
44
+ export { acceptCreatedTables } from './db-accept-created';
45
+ export type { BranchRow } from './db-branch';
46
+ export { BRANCH_SUBCOMMANDS, branchDatabaseName, branchNameOf } from './db-branch';
47
+ export type { GeneratedFiles } from './db-generate';
48
+ export { generateAppMigration } from './db-generate';
121
49
  export { QuerySubscribesUnknownError, replicaIdentityTables } from './db-subscribes';
122
- export type { AssetRoutesOptions } from './dev-assets';
123
- export {
124
- assetRoutes,
125
- MEDIA_BASE_PATH,
126
- } from './dev-assets';
127
- export type { DevDashboardInput, DevStatus } from './dev-dashboard';
128
- export { devDashboardRoutes, devPanels, devSources } from './dev-dashboard';
129
- export { devHooks } from './dev-hooks';
130
- export type { DevDbClient, RunningQueue } from './dev-queue';
131
- export { startQueue } from './dev-queue';
132
- export type { DevRenderOptions, DevRouteData } from './dev-render';
133
- export { appRoutes, routeDocument } from './dev-render';
134
- export type { RunningRoles, StartRolesOptions, WebBinding } from './dev-roles';
135
- export { DEV_BINDING, DEV_ROLES, selectRoles, startRoles } from './dev-roles';
136
- export type { RunningServices } from './dev-runtime';
137
- export { startServices } from './dev-runtime';
138
- export type { DevServices, ServiceBinding } from './dev-services';
139
- export { describeServices, resolveServices } from './dev-services';
140
- export type { DispatchOptions } from './dispatch';
141
50
  export { dispatch } from './dispatch';
142
- export type { DeclaredEntityCount, HashReconciliation } from './drift';
143
- export {
144
- checkSourceDrift,
145
- reconcileSchemaHash,
146
- recordedHashes,
147
- schemaHash,
148
- writeSchemaHash,
149
- } from './drift';
150
- // The browser-backed e2e driver. `installE2eDriver` is the ONE entry point an app's test preload
151
- // calls; everything below it is exported because the adapter's own pieces are what a driver author
152
- // re-uses, and a deep import into `src/` would make each of them a compatibility promise anyway.
153
- export type { E2eDriverOptions } from './e2e-driver';
154
- export { e2eFixtures, installE2eDriver } from './e2e-driver';
155
- export {
156
- E2eEvaluateCapturedError,
157
- E2eEvaluateThrewError,
158
- E2eEvaluateUnsupportedError,
159
- E2eLocatorAmbiguousError,
160
- E2eLocatorEmptyError,
161
- E2eServiceWorkerAbsentError,
162
- } from './e2e-errors';
163
- export type { EvaluablePage } from './e2e-evaluate';
164
- export { closureSource, evaluateClosure, evaluateExpression } from './e2e-evaluate';
165
- export type { LocatablePage } from './e2e-locator';
166
- export { e2eLocator, resetLocatorMarks } from './e2e-locator';
167
- export type { E2eBrowserPage, E2ePageOptions } from './e2e-page';
168
- export { DEFAULT_E2E_TIMEOUT_MS, DEFAULT_SERVICE_WORKER_TIMEOUT_MS, e2ePage } from './e2e-page';
169
- export type { E2eResolution, E2eSelection } from './e2e-selection';
170
- export {
171
- MARK_ATTRIBUTE,
172
- markSelector,
173
- selectionCall,
174
- selectionExpression,
175
- unmarkExpression,
176
- } from './e2e-selection';
177
- export type { ErrorCatalog } from './error-catalog';
178
- export {
179
- buildErrorCatalog,
180
- CATALOG_OPTIONAL_HOSTS,
181
- CATALOG_PACKAGES,
182
- loadErrorCatalog,
183
- registeredErrorCodes,
184
- resetErrorCatalog,
185
- } from './error-catalog';
51
+ export { checkSourceDrift, reconcileSchemaHash, writeSchemaHash } from './drift';
52
+ export { registeredErrorCodes } from './error-catalog';
186
53
  export type { CliErrorCode } from './error-codes';
187
- export { CLI_ERROR_CODES, CLI_ERROR_TITLES } from './error-codes';
188
- export type { ErrorFixReport } from './error-contract';
189
54
  export {
190
55
  BANNED_PHRASES,
191
56
  COMMAND_TOKENS,
192
57
  checkErrorCodeDocs,
193
58
  checkErrorCodeRegistry,
194
- checkErrorCodeResolution,
195
59
  checkErrorFixes,
196
- checkErrorFixReport,
197
60
  collectDeclaredCodes,
198
61
  documentedCodes,
199
62
  fixProblem,
200
- liveCodes,
201
- RESERVED_HEADING,
202
63
  staticFix,
203
64
  } from './error-contract';
204
- export type { CodeFixIndex, CodeFixScan } from './error-fixes';
205
- export {
206
- codeFixes,
207
- codeFixScan,
208
- loadCodeFixes,
209
- resetCodeFixes,
210
- scanScopeFixes,
211
- } from './error-fixes';
65
+ export { checkErrorCodesThrown } from './error-unthrown';
212
66
  export {
213
67
  BadFlagError,
214
68
  BuildEntryMissingError,
@@ -230,14 +84,7 @@ export {
230
84
  } from './errors';
231
85
  export type { ExecOptions, ExecResult, Runner } from './exec';
232
86
  export { exec, execOutput } from './exec';
233
- export {
234
- defaultFavicon,
235
- FAVICON_PATH,
236
- FAVICON_SOURCE,
237
- faviconResponse,
238
- faviconRoute,
239
- } from './favicon';
240
- export type { CitationFault, CitationRules, CommandCatalog, FixCitation } from './fix-command';
87
+ export type { CitationFault, CommandCatalog, FixCitation } from './fix-command';
241
88
  export {
242
89
  citationFault,
243
90
  citationProblem,
@@ -245,193 +92,79 @@ export {
245
92
  fixCitations,
246
93
  loadCommandCatalog,
247
94
  } from './fix-command';
248
- export type { HelperResolver } from './fix-imports';
249
- export { candidatePaths, createHelperResolver, scanImports } from './fix-imports';
250
- export {
251
- CITED_FILE_EXTENSIONS,
252
- citedPathProblem,
253
- FILE_TOKEN_PATTERN,
254
- pathCitations,
255
- } from './fix-path';
256
- export type { FixHelper, FixScan } from './fix-scan';
257
- export { scanFixes, scanFixHelpers, scanFixSites } from './fix-scan';
258
- export type { DeclaredFlag } from './flag-reads';
259
- export { checkFlagReads, declaredFlags, readsFlag } from './flag-reads';
260
- export type { FrameworkSchema, SchemaExecutor } from './framework-schema';
95
+ export { candidatePaths, scanImports } from './fix-imports';
96
+ export type { FixScan } from './fix-scan';
97
+ export { scanFixes } from './fix-scan';
98
+ export { checkFlagReads } from './flag-reads';
261
99
  // The framework's own tables, as data. Exported so `scripts/` can read the applier's list without
262
100
  // re-deriving it — the shape a ratchet over declared-but-never-applied DDL needs.
263
- export {
264
- applyFrameworkSchema,
265
- FRAMEWORK_SCHEMA,
266
- frameworkTableNames,
267
- schemaStatements,
268
- } from './framework-schema';
101
+ export { FRAMEWORK_SCHEMA } from './framework-schema';
269
102
  export type { Guard } from './guards';
270
- export { findingProblem, GUARD_DIR, guardFindings, guardPaths } from './guards';
271
- export {
272
- hasSourceIcon,
273
- ICON_BASE_PATH,
274
- ICON_SOURCE,
275
- iconPlan,
276
- iconRenderer,
277
- } from './icon-assets';
103
+ export { findingProblem, guardFindings, guardPaths } from './guards';
104
+ export { ICON_BASE_PATH, ICON_SOURCE } from './icon-assets';
278
105
  // The island bundler, and only its entry point. An island is the one module Ultimate ships to a
279
106
  // browser, so an app has to be able to build one to TEST one — `mountIsland` from
280
107
  // `@ultimat3/testing` takes this function as its `build` parameter (issue #260). `discoverIslands`,
281
108
  // `islandBundle`, `writeIslands`, `ISLAND_BASE_PATH` and `ISLAND_GLOB` stay internal: they are
282
109
  // `x build`'s and `x dev`'s wiring, and every name here is a semver promise forever.
283
- export type { IslandBundle, IslandChunk } from './island-bundle';
110
+ export type { IslandChunk } from './island-bundle';
284
111
  export { buildIslands } from './island-bundle';
285
- export type { DrainFailure, DrainOutcome, DrainSkip } from './jobs-drain';
286
- export { drainJobs } from './jobs-drain';
287
- export type { JobsListFilter, JobsListResult } from './jobs-report';
288
- export { JOB_STATES, listJobs, retryJob, showJob } from './jobs-report';
112
+ export { JOB_STATES } from './jobs-report';
289
113
  export { renderJobTable } from './jobs-table';
290
- export type { CliMcpServer, DevHostInput } from './mcp-host';
291
- export { createDevMcpServer, DEV_TOOL_SCOPES, localCaller } from './mcp-host';
292
- export { messageKeys, msg } from './messages';
293
- export type { MetricsEndpoint, MetricsEndpointOptions } from './metrics-endpoint';
114
+ export { msg } from './messages';
294
115
  export { DEFAULT_METRICS_PORT, startMetricsEndpoint } from './metrics-endpoint';
295
- export {
296
- hashFileName,
297
- MIGRATIONS_DIR,
298
- migrationName,
299
- parseMigrationSql,
300
- readMigrations,
301
- snapshotFileName,
302
- } from './migrations';
303
- export type { CommandResult, Finding, JsonValue, StepResult } from './output';
304
- export {
305
- exitCodeFor,
306
- findingFrom,
307
- isUltimateErrorShape,
308
- render,
309
- renderFinding,
310
- renderHuman,
311
- renderJson,
312
- renderUltimateError,
313
- } from './output';
116
+ export { parseMigrationSql, readMigrations } from './migrations';
117
+ export type { CommandResult, Finding, JsonValue } from './output';
118
+ export { exitCodeFor, findingFrom, render, renderFinding, renderHuman } from './output';
314
119
  export type { CommandSpec, FlagSpec, ParsedArgs } from './parse';
315
120
  export { flagBool, flagList, flagString, GLOBAL_FLAGS, nearest, parseArgs } from './parse';
316
- export type { PrerenderedPage, PrerenderOptions, PrerenderReport } from './prerender';
121
+ export type { PrerenderedPage, PrerenderReport } from './prerender';
317
122
  export { DEFAULT_ORIGIN, isPrerenderable, prerenderSite } from './prerender';
318
123
  export type { PwaArtifacts } from './pwa-artifacts';
319
- export {
320
- loadPwaArtifacts,
321
- pwaManifestRoute,
322
- WEB_MANIFEST_PATH,
323
- writePwaIcons,
324
- } from './pwa-artifacts';
325
- export { COMMANDS, cliVersion, commandFor, SPECS } from './registry';
326
- export type { SchemaDifference, SchemaDirection, SchemaPart } from './schema-diff';
327
- export { diffDeclaredSchema } from './schema-diff';
124
+ export { loadPwaArtifacts } from './pwa-artifacts';
125
+ export { COMMANDS, cliVersion, SPECS } from './registry';
126
+ export type { RunningRoles, WebBinding } from './role-start';
127
+ export { DEV_BINDING, DEV_ROLES, startRoles } from './role-start';
128
+ export { assetRoutes, MEDIA_BASE_PATH } from './runtime-assets';
129
+ export { resolveServices } from './runtime-bindings';
130
+ export { devHooks } from './runtime-hooks';
131
+ export { startQueue } from './runtime-queue';
132
+ export { appRoutes, routeDocument } from './runtime-render';
133
+ export type { RunningServices } from './runtime-services';
134
+ export { startServices } from './runtime-services';
328
135
  // The drift a hash cannot see, and the composition both the gate step and `x doctor` read.
329
- export type { DeclaredEntities } from './schema-drift';
330
136
  export { checkMigrationDrift, checkSnapshotDrift } from './schema-drift';
331
137
  export { FrameworkSchemaFailedError } from './schema-errors';
332
- export type { MigratedApp, ServedApp, ServeOptions, StartedApp } from './serve';
138
+ export type { MigratedApp, ServeOptions } from './serve';
333
139
  export {
334
140
  CONTAINER_BINDING,
335
141
  DEFAULT_PORT,
336
- metricsPortFromEnv,
337
- portFromEnv,
338
142
  roleFromEnv,
339
143
  runMigrations,
340
144
  runRole,
341
145
  serveApp,
342
146
  } from './serve';
343
147
  export { quoteArg } from './shell-quote';
344
- export {
345
- eachSourceFile,
346
- isGenerated,
347
- isTest,
348
- isVendored,
349
- SOURCE_GLOBS,
350
- } from './source-files';
351
- export type {
352
- EmittedPage,
353
- RouteFacts,
354
- SkippedRoute,
355
- SkipReason,
356
- StaticReport,
357
- UnmeasuredRoute,
358
- } from './static-report';
359
- export {
360
- parseStaticReport,
361
- readStaticReport,
362
- removeStaticReport,
363
- renderStaticReport,
364
- SKIP_REASONS,
365
- STATIC_REPORT_FILE,
366
- skippedRoute,
367
- skipReasonFor,
368
- writeStaticReport,
369
- } from './static-report';
370
- export type { StyleBundle, StyleChunk } from './style-bundle';
371
- export { STYLE_BASE_PATH, styleBundle } from './style-bundle';
372
- export type { TestCounts } from './test-counts';
373
- export { countsOf } from './test-counts';
374
- export type { TestFile } from './test-select';
375
- export { belongsToType, discoverTests, sampleFiles } from './test-select';
376
- export type { ReproduceOptions, RunShardsOptions } from './test-shards';
377
- export { filesIn, reproduceFor, runShards, testArgs } from './test-shards';
378
- export { availableCpus, defaultWorkers, WORKER_CEILING } from './test-workers';
379
- export type {
380
- CodeFixSite,
381
- CodeScan,
382
- CodeSite,
383
- FixSite,
384
- SourceSite,
385
- UnresolvedCodeSite,
386
- } from './ts-scan';
387
- export {
388
- isCodeRegistry,
389
- maskLiterals,
390
- scanBorrowedCodes,
391
- scanCodeDeclarations,
392
- scanCodeFixSites,
393
- scanCodes,
394
- stripComments,
395
- } from './ts-scan';
148
+ export { eachSourceFile, isGenerated, isTest, SOURCE_GLOBS } from './source-files';
149
+ export type { SkippedRoute, StaticReport } from './static-report';
150
+ export { parseStaticReport } from './static-report';
151
+ export { filesIn, testArgs } from './test-shards';
152
+ export { defaultWorkers } from './test-workers';
153
+ export { scanCodeDeclarations, scanCodeFixSites, scanCodes } from './ts-scan';
396
154
  // The one spelling rule for a `references` entry. Exported because the two gate scripts ask the
397
155
  // same question this package's `package-shape` step does, and three answers is a duplicate entry.
398
156
  export { normalizeReferencePath } from './tsconfig-references';
399
- export type { VerifyFloor } from './verify-floor';
400
- export {
401
- floorProblemFindings,
402
- floorRequires,
403
- parseVerifyFloor,
404
- readVerifyFloor,
405
- skippedSuiteFinding,
406
- VERIFY_FLOOR_FILE,
407
- vanishedSuiteFinding,
408
- } from './verify-floor';
409
- export type {
410
- HostCheck,
411
- StepOutcome,
412
- VerifyContext,
413
- VerifyStep,
414
- VerifyStepName,
415
- } from './verify-step';
157
+ export { readVerifyFloor, skippedSuiteFinding, VERIFY_FLOOR_FILE } from './verify-floor';
158
+ export type { HostCheck, StepOutcome, VerifyStep, VerifyStepName } from './verify-step';
416
159
  export { VERIFY_STEP_NAMES } from './verify-step';
417
160
  export type { TestType } from './verify-tests';
418
- export { TEST_STEPS, TEST_TYPES, testStepCommand, typeFiltersOf } from './verify-tests';
419
- export type { ManifestFacts, PackageShapeOptions } from './workspace-checks';
161
+ export { TEST_TYPES } from './verify-tests';
420
162
  export {
421
163
  checkFileSizes,
422
164
  checkLockstep,
423
165
  checkPackageShape,
424
- frameworkDepsOf,
425
- hasWorkspacePackages,
426
166
  LINE_CEILING,
427
167
  PACKAGE_FILES,
428
168
  SEMVER,
429
- workspacePackages,
430
169
  } from './workspace-checks';
431
- export type { WorkspaceNode, WorkspaceScan } from './workspace-graph';
432
- // The graph itself, not just the gate's verdict on it: issue #239's complaint is that a
433
- // scaffolded repo's dependency graph exists only inside `tsc`, so an app's own tooling has
434
- // nothing to read. `checkWorkspaceDependencies` stays internal — it is reached through
435
- // `x verify`, which is the one way a rule is enforced here.
436
- export { readWorkspaceGraph, scanWorkspaces } from './workspace-graph';
437
170
  export { writeErrorLine, writeLine } from './write-line';
@@ -0,0 +1,26 @@
1
+ // The flags a caller set, spelled so pasting them reproduces the same run. A `fix:` that re-runs a
2
+ // command with `--force` and loses `--feature` or `--dir` writes somewhere the caller never asked
3
+ // for — `x g`'s conflict fix wrote a second slice, `x new`'s a second app in the cwd.
4
+
5
+ import type { CommandSpec, ParsedArgs } from './parse';
6
+ import { quoteArg } from './shell-quote';
7
+
8
+ /** Never reproduced: the fix adds its own `--force`, and output flags do not change what runs. */
9
+ const NOT_REPRODUCED = new Set(['force', 'dry-run', 'json', 'help', 'verbose', 'cwd']);
10
+
11
+ /**
12
+ * Every declared flag whose value differs from its default, in the spec's order: a string as
13
+ * `--name <quoted>`, a boolean as `--name` or `--no-name`. A default is nobody's request, so it is
14
+ * left for the default to supply again.
15
+ */
16
+ export function reproducedFlags(spec: CommandSpec, args: ParsedArgs): readonly string[] {
17
+ const out: string[] = [];
18
+ for (const flag of spec.flags ?? []) {
19
+ if (NOT_REPRODUCED.has(flag.name)) continue;
20
+ const value = args.flags.get(flag.name);
21
+ if (value === undefined || value === flag.default) continue;
22
+ if (typeof value === 'string') out.push(`--${flag.name}`, quoteArg(value));
23
+ else out.push(value ? `--${flag.name}` : `--no-${flag.name}`);
24
+ }
25
+ return out;
26
+ }