ubume 0.1.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 (182) hide show
  1. package/README.md +88 -0
  2. package/bin/codexa-local-harness-bridge.js +3 -0
  3. package/bin/codexa.js +28 -0
  4. package/bin/ubume-local-harness-bridge.js +325 -0
  5. package/bin/ubume.js +398 -0
  6. package/package.json +66 -0
  7. package/src/app.tsx +5759 -0
  8. package/src/commands/handler.ts +889 -0
  9. package/src/config/appVersion.ts +69 -0
  10. package/src/config/buildInfo.ts +3 -0
  11. package/src/config/launchArgs.ts +196 -0
  12. package/src/config/layeredConfig.ts +853 -0
  13. package/src/config/legacyEnv.ts +16 -0
  14. package/src/config/persistence.ts +377 -0
  15. package/src/config/runtimeConfig.ts +558 -0
  16. package/src/config/settings.ts +405 -0
  17. package/src/config/toml-serialize.ts +109 -0
  18. package/src/config/trustStore.ts +84 -0
  19. package/src/config/updateCheckCache.ts +85 -0
  20. package/src/core/README.md +55 -0
  21. package/src/core/agent/loop.ts +464 -0
  22. package/src/core/agent/protocol.ts +345 -0
  23. package/src/core/agent/tools.ts +423 -0
  24. package/src/core/auth/codexAuth.ts +359 -0
  25. package/src/core/codex/codexExecArgs.ts +166 -0
  26. package/src/core/codex/codexLaunch.ts +163 -0
  27. package/src/core/codex/codexPrompt.ts +429 -0
  28. package/src/core/debug/inputDebug.ts +51 -0
  29. package/src/core/debug/localStreamDebug.ts +50 -0
  30. package/src/core/debug/modelStateDebug.ts +35 -0
  31. package/src/core/executables/antigravityExecutable.ts +48 -0
  32. package/src/core/executables/claudeExecutable.ts +63 -0
  33. package/src/core/executables/codexExecutable.ts +160 -0
  34. package/src/core/executables/executableResolver.ts +164 -0
  35. package/src/core/executables/geminiExecutable.ts +78 -0
  36. package/src/core/models/codexCapabilities.ts +97 -0
  37. package/src/core/models/codexModelCapabilities.ts +624 -0
  38. package/src/core/models/codexModelsCacheSeed.ts +153 -0
  39. package/src/core/models/modelSpecs.ts +303 -0
  40. package/src/core/models/providerModelCache.ts +94 -0
  41. package/src/core/perf/profiler.ts +125 -0
  42. package/src/core/perf/renderDebug.ts +398 -0
  43. package/src/core/process/CommandRunner.ts +280 -0
  44. package/src/core/process/processValidation.ts +111 -0
  45. package/src/core/providerLauncher/launcher.ts +220 -0
  46. package/src/core/providerLauncher/registry.ts +354 -0
  47. package/src/core/providerLauncher/types.ts +95 -0
  48. package/src/core/providerLauncher/workspaceConfig.ts +487 -0
  49. package/src/core/providerRuntime/anthropic.ts +580 -0
  50. package/src/core/providerRuntime/antigravity.ts +500 -0
  51. package/src/core/providerRuntime/capabilityProfile.ts +383 -0
  52. package/src/core/providerRuntime/claudeCodeDiscovery.ts +724 -0
  53. package/src/core/providerRuntime/claudeCodeDiscoveryDebug.ts +55 -0
  54. package/src/core/providerRuntime/codexaCupy.ts +97 -0
  55. package/src/core/providerRuntime/codexaNative.ts +425 -0
  56. package/src/core/providerRuntime/contextMetadata.ts +397 -0
  57. package/src/core/providerRuntime/gemini.ts +789 -0
  58. package/src/core/providerRuntime/lmstudio.ts +118 -0
  59. package/src/core/providerRuntime/local.ts +770 -0
  60. package/src/core/providerRuntime/localHarness/runtime.ts +1090 -0
  61. package/src/core/providerRuntime/localOutputBudget.ts +17 -0
  62. package/src/core/providerRuntime/mistralVibe.ts +667 -0
  63. package/src/core/providerRuntime/models.ts +175 -0
  64. package/src/core/providerRuntime/reasoning.ts +20 -0
  65. package/src/core/providerRuntime/registry.ts +286 -0
  66. package/src/core/providerRuntime/types.ts +142 -0
  67. package/src/core/providerRuntime/unsloth.ts +216 -0
  68. package/src/core/providers/codexJsonStream.ts +305 -0
  69. package/src/core/providers/codexSubprocess.ts +378 -0
  70. package/src/core/providers/codexTranscript.ts +695 -0
  71. package/src/core/providers/openaiNative.ts +13 -0
  72. package/src/core/providers/registry.ts +21 -0
  73. package/src/core/providers/types.ts +91 -0
  74. package/src/core/shared/attachments.ts +101 -0
  75. package/src/core/shared/cleanupFastFail.ts +67 -0
  76. package/src/core/shared/clipboard.ts +24 -0
  77. package/src/core/shared/clipboardImage.ts +111 -0
  78. package/src/core/shared/githubDiagnostics.ts +222 -0
  79. package/src/core/shared/hollowResponseFormat.ts +39 -0
  80. package/src/core/terminal/clearFrameBoundary.ts +852 -0
  81. package/src/core/terminal/frameLock.ts +110 -0
  82. package/src/core/terminal/inkRenderReset.ts +123 -0
  83. package/src/core/terminal/startupClear.ts +20 -0
  84. package/src/core/terminal/terminalCapabilities.ts +100 -0
  85. package/src/core/terminal/terminalControl.ts +169 -0
  86. package/src/core/terminal/terminalSanitize.ts +147 -0
  87. package/src/core/terminal/terminalTitle.ts +400 -0
  88. package/src/core/version/channel.ts +27 -0
  89. package/src/core/version/packageManager.ts +119 -0
  90. package/src/core/version/updateCheck.ts +203 -0
  91. package/src/core/workspace/appData.ts +107 -0
  92. package/src/core/workspace/conversationStore.ts +335 -0
  93. package/src/core/workspace/launchContext.ts +259 -0
  94. package/src/core/workspace/planStorage.ts +135 -0
  95. package/src/core/workspace/projectInstructions.ts +54 -0
  96. package/src/core/workspace/scratchDir.ts +64 -0
  97. package/src/core/workspace/workspaceActivity.ts +384 -0
  98. package/src/core/workspace/workspaceGuard.ts +377 -0
  99. package/src/core/workspace/workspaceRoot.ts +47 -0
  100. package/src/exec.ts +73 -0
  101. package/src/headless/execArgs.ts +296 -0
  102. package/src/headless/execRunner.ts +304 -0
  103. package/src/index.tsx +270 -0
  104. package/src/legacyEnvBootstrap.ts +5 -0
  105. package/src/session/appSession.ts +771 -0
  106. package/src/session/chatLifecycle.ts +994 -0
  107. package/src/session/conversation.ts +107 -0
  108. package/src/session/liveRenderScheduler.ts +214 -0
  109. package/src/session/persistedResponse.ts +93 -0
  110. package/src/session/planFlow.ts +159 -0
  111. package/src/session/planTranscript.ts +19 -0
  112. package/src/session/promptRunSchedule.ts +26 -0
  113. package/src/session/types.ts +234 -0
  114. package/src/test/runtimeTestUtils.ts +14 -0
  115. package/src/types/react-dom.d.ts +3 -0
  116. package/src/ui/chrome/ActivityBars.tsx +68 -0
  117. package/src/ui/chrome/ActivityIndicator.tsx +58 -0
  118. package/src/ui/chrome/AnimatedStatusText.tsx +69 -0
  119. package/src/ui/chrome/AppShell.tsx +474 -0
  120. package/src/ui/chrome/BottomComposer.tsx +1135 -0
  121. package/src/ui/chrome/DashCard.tsx +82 -0
  122. package/src/ui/chrome/RunFooter.tsx +65 -0
  123. package/src/ui/chrome/RuntimeStatusBar.tsx +108 -0
  124. package/src/ui/chrome/Spinner.tsx +25 -0
  125. package/src/ui/chrome/TopHeader.tsx +439 -0
  126. package/src/ui/chrome/UpdateAvailableCard.tsx +42 -0
  127. package/src/ui/chrome/busyStatusAnimation.ts +11 -0
  128. package/src/ui/input/commandNormalize.ts +66 -0
  129. package/src/ui/input/focus.ts +73 -0
  130. package/src/ui/input/imageAttachments.ts +18 -0
  131. package/src/ui/input/inputBuffer.ts +203 -0
  132. package/src/ui/input/pastedContent.ts +75 -0
  133. package/src/ui/input/rawArrowKeys.ts +28 -0
  134. package/src/ui/input/slashCommands.ts +43 -0
  135. package/src/ui/input/useStdinRawModeLease.ts +23 -0
  136. package/src/ui/layout.ts +560 -0
  137. package/src/ui/panels/AttachmentImportPanel.tsx +131 -0
  138. package/src/ui/panels/AuthPanel.tsx +149 -0
  139. package/src/ui/panels/BackendPicker.tsx +28 -0
  140. package/src/ui/panels/ModePicker.tsx +31 -0
  141. package/src/ui/panels/ModelPicker.tsx +31 -0
  142. package/src/ui/panels/ModelPickerScreen.tsx +761 -0
  143. package/src/ui/panels/ModelReasoningPicker.tsx +458 -0
  144. package/src/ui/panels/Panel.tsx +51 -0
  145. package/src/ui/panels/PermissionsPanel.tsx +78 -0
  146. package/src/ui/panels/PlanActionPicker.tsx +187 -0
  147. package/src/ui/panels/ProviderPicker.tsx +753 -0
  148. package/src/ui/panels/ProviderSetupPrompt.tsx +52 -0
  149. package/src/ui/panels/ReasoningPicker.tsx +46 -0
  150. package/src/ui/panels/ResumePicker.tsx +90 -0
  151. package/src/ui/panels/SelectionPanel.tsx +138 -0
  152. package/src/ui/panels/SettingsPanel.tsx +156 -0
  153. package/src/ui/panels/TextEntryPanel.tsx +139 -0
  154. package/src/ui/panels/ThemePicker.tsx +32 -0
  155. package/src/ui/panels/ToolApprovalPanel.tsx +46 -0
  156. package/src/ui/panels/UpdatePromptPanel.tsx +236 -0
  157. package/src/ui/panels/responsivePickerViewport.ts +64 -0
  158. package/src/ui/render/Markdown.tsx +331 -0
  159. package/src/ui/render/diffRenderer.ts +116 -0
  160. package/src/ui/render/logoVariants.ts +113 -0
  161. package/src/ui/render/modeDisplay.ts +52 -0
  162. package/src/ui/render/outputPipeline.ts +64 -0
  163. package/src/ui/render/runtimeDisplay.ts +128 -0
  164. package/src/ui/render/terminalAnswerFormat.ts +128 -0
  165. package/src/ui/render/textLayout.ts +392 -0
  166. package/src/ui/theme.tsx +274 -0
  167. package/src/ui/themeFlow.ts +41 -0
  168. package/src/ui/timeline/ActionRequiredBlock.tsx +38 -0
  169. package/src/ui/timeline/AgentBlock.tsx +130 -0
  170. package/src/ui/timeline/StaticIntroItem.tsx +54 -0
  171. package/src/ui/timeline/ThinkingBlock.tsx +100 -0
  172. package/src/ui/timeline/Timeline.tsx +1410 -0
  173. package/src/ui/timeline/TranscriptShell.tsx +302 -0
  174. package/src/ui/timeline/TurnGroup.tsx +673 -0
  175. package/src/ui/timeline/layoutListWindow.ts +145 -0
  176. package/src/ui/timeline/liveViewportWindow.ts +68 -0
  177. package/src/ui/timeline/progressEntries.ts +156 -0
  178. package/src/ui/timeline/runActivityView.ts +37 -0
  179. package/src/ui/timeline/staticTranscriptCache.ts +174 -0
  180. package/src/ui/timeline/streamCoalesce.ts +53 -0
  181. package/src/ui/timeline/timelineMeasure.ts +3273 -0
  182. package/src/ui/useThrottledValue.ts +31 -0
package/src/index.tsx ADDED
@@ -0,0 +1,270 @@
1
+ import "./legacyEnvBootstrap.js";
2
+ import React from "react";
3
+ import { render, type Instance, type RenderOptions } from "ink";
4
+ import { App } from "./app.js";
5
+ import { parseLaunchArgs, type LaunchArgs } from "./config/launchArgs.js";
6
+ import { loadSettings } from "./config/persistence.js";
7
+ import { APP_NAME, formatTerminalTitlePath } from "./config/settings.js";
8
+ import { getTerminalCapability } from "./core/terminal/terminalCapabilities.js";
9
+ import * as renderDebug from "./core/perf/renderDebug.js";
10
+ import { MIN_VIEWPORT_COLS, MIN_VIEWPORT_ROWS } from "./ui/layout.js";
11
+ import {
12
+ setIntendedTerminalTitle,
13
+ } from "./core/terminal/terminalTitle.js";
14
+ import { resolveWorkspaceRoot } from "./core/workspace/workspaceRoot.js";
15
+ import {
16
+ createTerminalModeController,
17
+ writeTerminalControl,
18
+ } from "./core/terminal/terminalControl.js";
19
+ import { resolveInkRenderInstance, type InkRenderInstance } from "./core/terminal/inkRenderReset.js";
20
+ import { resetFrameLockForResize, wrapStdoutWithFrameLock } from "./core/terminal/frameLock.js";
21
+
22
+ type RenderHandle = Pick<Instance, "clear" | "cleanup" | "waitUntilExit">;
23
+
24
+ export function resolveKittyKeyboardOptions(
25
+ env: Record<string, string | undefined>,
26
+ ): RenderOptions["kittyKeyboard"] | undefined {
27
+ // Ink's auto mode probes with CSI ? u. Kitty's response can race Ink's
28
+ // regular input listeners and leak into both the first frame and composer.
29
+ // A direct Kitty session is already known to support the protocol, so enable
30
+ // it without probing. Avoid protocol negotiation in all other terminals.
31
+ if ((env.TERM ?? "").toLowerCase() !== "xterm-kitty") {
32
+ return undefined;
33
+ }
34
+
35
+ return {
36
+ mode: "enabled",
37
+ flags: ["disambiguateEscapeCodes"],
38
+ };
39
+ }
40
+
41
+ export interface AppStdout {
42
+ isTTY: boolean;
43
+ write: (chunk: string) => boolean;
44
+ on: (event: "resize" | string, listener: (...args: unknown[]) => void) => void;
45
+ off: (event: "resize" | string, listener: (...args: unknown[]) => void) => void;
46
+ columns?: number;
47
+ rows?: number;
48
+ }
49
+
50
+ export interface StartAppDependencies {
51
+ stdin: Pick<NodeJS.ReadStream, "isTTY">;
52
+ stdout: AppStdout;
53
+ stderr: Pick<NodeJS.WriteStream, "write"> & Partial<Pick<NodeJS.WriteStream, "isTTY">>;
54
+ env: Record<string, string | undefined>;
55
+ platform: NodeJS.Platform;
56
+ argv: string[];
57
+ renderApp: (node: React.ReactElement, options?: RenderOptions) => RenderHandle;
58
+ resolveInkInstanceForStdout: (stdout: AppStdout) => InkRenderInstance | null;
59
+ registerExitHandler: (handler: () => void) => void;
60
+ }
61
+
62
+ export interface StartAppResult {
63
+ started: boolean;
64
+ exitCode: number;
65
+ }
66
+
67
+ interface ActiveRootState {
68
+ cleanup: () => void;
69
+ }
70
+
71
+ let activeRoot: ActiveRootState | null = null;
72
+
73
+ function debugLaunch(env: Record<string, string | undefined>, write: (chunk: string, source: string) => boolean, fields: Record<string, unknown>): void {
74
+ if (env.UBUME_DEBUG_LAUNCH !== "1" && env.CODEXA_DEBUG_LAUNCH !== "1") {
75
+ return;
76
+ }
77
+
78
+ write(`[ubume:launch] ${JSON.stringify(fields)}\n`, "src/index.tsx:launchDebug");
79
+ }
80
+
81
+ function hasInvalidRestoreDimensions(stdout: Pick<AppStdout, "columns" | "rows">): boolean {
82
+ const cols = stdout.columns;
83
+ const rows = stdout.rows;
84
+ return !Number.isFinite(cols) || !Number.isFinite(rows)
85
+ || (cols ?? 0) < MIN_VIEWPORT_COLS || (rows ?? 0) < MIN_VIEWPORT_ROWS;
86
+ }
87
+
88
+ export function startApp({
89
+ stdin = process.stdin,
90
+ stdout = process.stdout,
91
+ stderr = process.stderr,
92
+ env = process.env,
93
+ platform = process.platform,
94
+ argv = process.argv.slice(2),
95
+ renderApp = render,
96
+ resolveInkInstanceForStdout = resolveInkRenderInstance,
97
+ registerExitHandler = (handler) => {
98
+ process.on("exit", handler);
99
+ },
100
+ }: Partial<StartAppDependencies> = {}): StartAppResult {
101
+ renderDebug.configureRenderDebug(env);
102
+
103
+ if (activeRoot) {
104
+ return { started: true, exitCode: 0 };
105
+ }
106
+
107
+ // Wrap stdout to implement frame locking, deduplication, and width-safe row
108
+ // padding via \x1b[K injection across the entire TUI.
109
+ const wrappedStdout = wrapStdoutWithFrameLock({ stdout, env });
110
+
111
+ const terminal = createTerminalModeController((chunk) => wrappedStdout.write(chunk));
112
+ const writeStdout = (chunk: string, source: string): boolean => terminal.write(chunk, source);
113
+
114
+ const writeStderr = (chunk: string, source: string): boolean => {
115
+ return writeTerminalControl((value) => stderr.write(value), "stderr", source, chunk);
116
+ };
117
+
118
+ debugLaunch(env, writeStderr, {
119
+ phase: "startApp",
120
+ resolvedLaunchMode: "interactive-ui",
121
+ stdinIsTTY: Boolean(stdin.isTTY),
122
+ stdoutIsTTY: Boolean(stdout.isTTY),
123
+ stderrIsTTY: Boolean(stderr.isTTY),
124
+ TERM: env.TERM,
125
+ WT_SESSION: env.WT_SESSION,
126
+ TERM_PROGRAM: env.TERM_PROGRAM,
127
+ argv,
128
+ });
129
+
130
+ const capability = getTerminalCapability({
131
+ stdinIsTTY: Boolean(stdin.isTTY),
132
+ stdoutIsTTY: Boolean(stdout.isTTY),
133
+ platform,
134
+ env,
135
+ });
136
+
137
+ if (!capability.supported) {
138
+ writeStderr(`${capability.message}\n`, "src/index.tsx:unsupportedTerminal");
139
+ return { started: false, exitCode: 1 };
140
+ }
141
+ if (capability.warning) {
142
+ writeStderr(`${capability.warning}\n`, "src/index.tsx:terminalCapabilityWarning");
143
+ }
144
+
145
+ const parsedLaunchArgs = parseLaunchArgs(argv);
146
+ if (!parsedLaunchArgs.ok) {
147
+ writeStderr(`${parsedLaunchArgs.error}\n`, "src/index.tsx:launchArgs");
148
+ return { started: false, exitCode: 1 };
149
+ }
150
+ const launchArgs: LaunchArgs = parsedLaunchArgs.value;
151
+ // Main chat starts in the normal screen buffer so the startup frame and later
152
+ // transcript rows are owned by native terminal scrollback. Overlay screens
153
+ // enter alternate-screen mode from app.tsx only while an overlay is active.
154
+ const startupWorkspaceRoot = resolveWorkspaceRoot();
155
+ const startupSettings = loadSettings();
156
+ const startupTitle =
157
+ formatTerminalTitlePath(startupWorkspaceRoot, startupSettings.ui.terminalTitleMode) || APP_NAME;
158
+ setIntendedTerminalTitle(startupTitle, {
159
+ force: true,
160
+ reason: "startup-title",
161
+ write: (chunk) => writeStdout(chunk, "src/index.tsx:startup.title"),
162
+ });
163
+ terminal.setMouseReporting(false, "src/index.tsx:startup.nativeScroll");
164
+ terminal.setBracketedPaste(true, "src/index.tsx:startup.bracketedPaste");
165
+
166
+ let cleanupDone = false;
167
+ let repaintArmed = false;
168
+ let renderHandle: RenderHandle | null = null;
169
+ let inkInstance: InkRenderInstance | null = null;
170
+ let previousResizeCols = stdout.columns;
171
+ let previousResizeRows = stdout.rows;
172
+
173
+ const onResize = () => {
174
+ resetFrameLockForResize(wrappedStdout);
175
+ renderDebug.traceEvent("terminal", "resize", {
176
+ previousCols: previousResizeCols,
177
+ previousRows: previousResizeRows,
178
+ cols: stdout.columns,
179
+ rows: stdout.rows,
180
+ invalid: hasInvalidRestoreDimensions(stdout),
181
+ });
182
+ previousResizeCols = stdout.columns;
183
+ previousResizeRows = stdout.rows;
184
+
185
+ if (hasInvalidRestoreDimensions(stdout)) {
186
+ // Transient invalid dimensions (e.g. during maximize/restore on
187
+ // Windows). Keep the previous frame visible and let useTerminalViewport
188
+ // preserve the last renderable layout until valid dimensions return.
189
+ repaintArmed = true;
190
+ return;
191
+ }
192
+
193
+ if (repaintArmed) {
194
+ repaintArmed = false;
195
+ }
196
+
197
+ // useTerminalViewport owns resize-driven React state. Do not clear the
198
+ // terminal, reset Ink output caches, or force Ink renders here; those
199
+ // imperative paths can produce a transient empty frame during streaming.
200
+ };
201
+
202
+ const cleanup = () => {
203
+ if (cleanupDone) return;
204
+ cleanupDone = true;
205
+ stdout.off("resize", onResize);
206
+ renderHandle?.cleanup();
207
+ // Restore terminal state: disable mouse reporting and bracketed paste.
208
+ terminal.setMouseReporting(false, "src/index.tsx:cleanup.mouse");
209
+ terminal.setBracketedPaste(false, "src/index.tsx:cleanup.bracketedPaste");
210
+ terminal.setAlternateScreen(false, "src/index.tsx:cleanup.alternateScreen");
211
+ terminal.resetModes();
212
+ activeRoot = null;
213
+ };
214
+
215
+ const handleFatal = (error: unknown) => {
216
+ cleanup();
217
+ if (error instanceof Error) {
218
+ writeStderr(`${error.stack || error.message}\n`, "src/index.tsx:fatalError");
219
+ } else if (error) {
220
+ writeStderr(`${String(error)}\n`, "src/index.tsx:fatalUnknown");
221
+ }
222
+ process.exit(1);
223
+ };
224
+
225
+ const handleSignal = () => {
226
+ cleanup();
227
+ process.exit(0);
228
+ };
229
+
230
+ stdout.on("resize", onResize);
231
+ registerExitHandler(cleanup);
232
+
233
+ // Ensure clean teardown on signals and unhandled failures to prevent
234
+ // leaving the terminal in mouse-reporting mode.
235
+ process.on("SIGINT", handleSignal);
236
+ process.on("SIGTERM", handleSignal);
237
+ process.on("uncaughtException", handleFatal);
238
+ process.on("unhandledRejection", handleFatal);
239
+
240
+ const kittyKeyboard = resolveKittyKeyboardOptions(env);
241
+ renderHandle = renderApp(<App launchArgs={launchArgs} />, {
242
+ ...(kittyKeyboard ? { kittyKeyboard } : {}),
243
+ stdout: wrappedStdout as any,
244
+ });
245
+
246
+ // Resolve the real Ink class instance to get access to lastOutput,
247
+ // onRender, calculateLayout, etc. Gracefully degrades to null in tests.
248
+ inkInstance = resolveInkInstanceForStdout(wrappedStdout);
249
+
250
+ // Remove Ink's own resize handler so the app is the sole resize handler.
251
+ // This eliminates the race where Ink's resized() fires alongside our
252
+ // onResize, causing interleaved renders that desync logUpdate.
253
+ if (inkInstance?.unsubscribeResize) {
254
+ inkInstance.unsubscribeResize();
255
+ }
256
+
257
+ void renderHandle.waitUntilExit().finally(cleanup);
258
+
259
+ activeRoot = { cleanup };
260
+ return { started: true, exitCode: 0 };
261
+ }
262
+
263
+ const isMainModule = Boolean((import.meta as ImportMeta & { main?: boolean }).main);
264
+
265
+ if (isMainModule) {
266
+ const result = startApp();
267
+ if (!result.started) {
268
+ process.exitCode = result.exitCode;
269
+ }
270
+ }
@@ -0,0 +1,5 @@
1
+ // Side-effect module: entry points import this first so legacy CODEXA_* variables are
2
+ // aliased before any other module reads process.env at load time.
3
+ import { applyLegacyEnvAliases } from "./config/legacyEnv.js";
4
+
5
+ applyLegacyEnvAliases();