Skip to content

Centralize runtime env aliases and startup thread selection#1481

Closed
raulferrodrigues wants to merge 2 commits intopingdotgg:mainfrom
raulferrodrigues:feature/runtime-aliases-startup-thread
Closed

Centralize runtime env aliases and startup thread selection#1481
raulferrodrigues wants to merge 2 commits intopingdotgg:mainfrom
raulferrodrigues:feature/runtime-aliases-startup-thread

Conversation

@raulferrodrigues
Copy link
Copy Markdown

@raulferrodrigues raulferrodrigues commented Mar 28, 2026

Summary

  • stabilize local runtime isolation so local desktop and web/dev runs stop colliding with installed-app state
  • centralize runtime env alias and default-home handling in shared code and make local desktop backend startup explicit
  • move startup thread selection into the server welcome contract and harden/test the workspace-link sync path

Validation

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test

Note

Medium Risk
Medium risk because it changes runtime defaults (env var names, home-dir selection, desktop backend spawning, and server.welcome payload fields), which can affect startup behavior and persisted state locations across installs/dev.

Overview
Renames project/package scope and runtime identifiers from @t3tools/*/t3/T3CODE_* to @tero/*/tero/TERO_* across docs, build/release config, and the desktop/server/web code paths.

Centralizes runtime env aliasing and default home-dir selection via @tero/shared/runtime, defaults dev runs to ~/.tero-dev, and makes desktop backend spawning explicit (requires TERO_DESKTOP_SERVER_EXECUTABLE, passes --mode desktop --no-browser --home-dir ... --auth-token ...) to avoid Electron/Node confusion and state collisions.

Updates the WebSocket server.welcome contract to provide startupProjectId/startupThreadId (selected from cwd when auto-bootstrap is enabled, otherwise latest non-deleted thread) and adjusts tests accordingly.

Adds a postinstall workspace-link sync script (scripts/sync-workspace-links.mjs) to ensure node_modules/@tero/* symlinks exist for local Node/Electron entrypoints.

Written by Cursor Bugbot for commit 1682216. This will update automatically on new commits. Configure here.

Note

Rename all @t3tools/T3CODE_*/t3 identifiers to @tero/TERO_*/tero across the monorepo

  • Renames all package scopes from @t3tools/* to @tero/* and updates the CLI binary from t3 to tero, including package.json files, imports, and turbo/build configs throughout the monorepo.
  • Centralizes environment variable alias normalization via a new normalizeEnvAliases function in @tero/shared/runtime, called at startup in the server, desktop, and dev runner to warn on conflicts and backfill TERO_* keys from legacy T3CODE_* values.
  • Renames all T3CODE_* runtime env vars to TERO_* (e.g. TERO_PORT, TERO_HOME, TERO_AUTH_TOKEN) in the server CLI, desktop main process, and build scripts.
  • Renames WebSocket welcome payload fields from bootstrapProjectId/bootstrapThreadId to startupProjectId/startupThreadId, and updates selection logic to use the current read-model snapshot rather than only recent bootstrap operations.
  • Renames localStorage/storage keys from t3code:* to tero:* (e.g. tero:app-settings:v1, tero:renderer-state:v8) and adds a LEGACY_PERSISTED_STATE_KEYS array for migration.
  • Adds scripts/lib/workspace-links.mjs with syncWorkspaceLinks and a postinstall hook to maintain node_modules symlinks for workspace packages.
  • Risk: All TERO_* storage keys, env vars, git refs (refs/tero/checkpoints), checkpoint commit prefixes, and service tag identifiers are changed; existing persisted state under old keys will not be read unless explicitly migrated.
📊 Macroscope summarized 1682216. 86 files reviewed, 5 issues evaluated, 1 issue filtered, 3 comments posted

🗂️ Filtered Issues

apps/web/src/appSettings.ts — 0 comments posted, 1 evaluated, 1 filtered
  • line 17: Changing APP_SETTINGS_STORAGE_KEY from "t3code:app-settings:v1" to "tero:app-settings:v1" will cause existing users to lose all their saved settings. The useAppSettings hook uses this key with useLocalStorage, so any settings previously stored under the old key will be orphaned and the app will fall back to DEFAULT_APP_SETTINGS. If preserving user settings during the rebrand is intended, a migration from the old key to the new key should be implemented. [ Cross-file consolidated ]

- Move shared env alias and home-path logic into `@tero/shared/runtime`
- Rename welcome payload ids to `startup*` and use latest thread fallback
- Tighten desktop backend resolution for local dev runtime
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: bc9559ba-7a6f-4c5a-bf32-d98686b51ccb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 28, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

- any place where legacy `t3code` and new `tero` paths/keys may be mixed
- Avoid launching the app/dev stack casually while collecting evidence; prefer static inspection first.
- Only after the startup/persistence risk is understood should the rename resume.
- Update this file as findings and changes accumulate.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigation log with personal paths accidentally committed

Medium Severity

CURRENT-TASK.md is a 448-line forensic investigation log containing absolute local filesystem paths (e.g. /Users/raulrodrigues/workspace/personal/t3code-ero/...), detailed debugging session notes, incident timelines, and working hypotheses. This is a temporary task-tracking document that exposes developer-specific environment details and doesn't belong in the repository.

Fix in Cursor Fix in Web

TurnId,
type OrchestrationEvent,
} from "@t3tools/contracts";
} from "@tero/contracts";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test fixtures use stale checkpoint ref prefix

Low Severity

CHECKPOINT_REFS_PREFIX was renamed from refs/t3/checkpoints to refs/tero/checkpoints in Utils.ts, but several test files still hardcode the old refs/t3/checkpoints prefix in fixture data. While these tests are internally consistent and still pass, they no longer test the actual production ref format, reducing their value as regression guards for the checkpoint path.

Additional Locations (1)
Fix in Cursor Fix in Web

};
// Send welcome before adding to broadcast set so publishAll calls
// cannot reach this client before the welcome arrives.
void runPromise(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High src/wsServer.ts:1013

Line 1015 calls projectionReadModelQuery.getSnapshot() inside void runPromise(...) with no error handling. If the snapshot query fails (e.g., database error), the rejected promise becomes an unhandled rejection that can crash the Node.js process depending on its --unhandled-rejections mode. Consider adding .catch() or Effect.ignoreCause to the pipeline so failures don't propagate as unhandled rejections.

🤖 Copy this AI Prompt to have your agent fix this:
In file apps/server/src/wsServer.ts around line 1013:

Line 1015 calls `projectionReadModelQuery.getSnapshot()` inside `void runPromise(...)` with no error handling. If the snapshot query fails (e.g., database error), the rejected promise becomes an unhandled rejection that can crash the Node.js process depending on its `--unhandled-rejections` mode. Consider adding `.catch()` or `Effect.ignoreCause` to the pipeline so failures don't propagate as unhandled rejections.

Evidence trail:
apps/server/src/wsServer.ts lines 1013-1040 (REVIEWED_COMMIT): `void runPromise(...)` pipeline with no error handling. Line 736: `const runPromise = Effect.runPromiseWith(runtimeServices);`. Line 1043: contrast shows `Effect.ignoreCause({ log: true })` being used for error handling in similar pattern.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium

if (typeof window === "undefined") return initialState;

Changing PERSISTED_STATE_KEY to "tero:renderer-state:v8" without updating readPersistedState() causes silent data loss for existing users. When an existing user loads the app, readPersistedState() reads only from the new key (line 48), finds nothing, and returns initialState. The user's persisted expanded project states and project order are lost. The old key is then deleted by persistState() (lines 86-90) before its data is ever read. Consider updating readPersistedState() to attempt reading from LEGACY_PERSISTED_STATE_KEYS as a fallback before returning initialState.

Also found in 1 other location(s)

apps/web/src/appSettings.ts:17

Changing APP_SETTINGS_STORAGE_KEY from "t3code:app-settings:v1" to "tero:app-settings:v1" will cause existing users to lose all their saved settings. The useAppSettings hook uses this key with useLocalStorage, so any settings previously stored under the old key will be orphaned and the app will fall back to DEFAULT_APP_SETTINGS. If preserving user settings during the rebrand is intended, a migration from the old key to the new key should be implemented.

🤖 Copy this AI Prompt to have your agent fix this:
In file apps/web/src/store.ts around line 46:

Changing `PERSISTED_STATE_KEY` to `"tero:renderer-state:v8"` without updating `readPersistedState()` causes silent data loss for existing users. When an existing user loads the app, `readPersistedState()` reads only from the new key (line 48), finds nothing, and returns `initialState`. The user's persisted expanded project states and project order are lost. The old key is then deleted by `persistState()` (lines 86-90) before its data is ever read. Consider updating `readPersistedState()` to attempt reading from `LEGACY_PERSISTED_STATE_KEYS` as a fallback before returning `initialState`.

Evidence trail:
apps/web/src/store.ts lines 20-31 (PERSISTED_STATE_KEY and LEGACY_PERSISTED_STATE_KEYS definitions), lines 44-66 (readPersistedState function - only reads from new key at line 47, returns initialState at line 48 if not found, no fallback to legacy keys), lines 70-91 (persistState function - deletes all legacy keys at lines 86-90). Commit: REVIEWED_COMMIT.

Also found in 1 other location(s):
- apps/web/src/appSettings.ts:17 -- Changing `APP_SETTINGS_STORAGE_KEY` from `"t3code:app-settings:v1"` to `"tero:app-settings:v1"` will cause existing users to lose all their saved settings. The `useAppSettings` hook uses this key with `useLocalStorage`, so any settings previously stored under the old key will be orphaned and the app will fall back to `DEFAULT_APP_SETTINGS`. If preserving user settings during the rebrand is intended, a migration from the old key to the new key should be implemented.

export async function collectWorkspacePackages(repoRoot) {
const rootPackageJsonPath = join(repoRoot, "package.json");
const rootPackageJson = await readJson(rootPackageJsonPath);
const packagePatterns = rootPackageJson.workspaces?.packages ?? [];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low lib/workspace-links.mjs:71

When workspaces is specified as a plain array like {"workspaces": ["packages/*"]}, rootPackageJson.workspaces?.packages evaluates to undefined, so packagePatterns becomes [] and the function silently returns zero packages. Should handle both the shorthand array format and the { packages: [...] } object format.

-  const packagePatterns = rootPackageJson.workspaces?.packages ?? [];
+  const packagePatterns = Array.isArray(rootPackageJson.workspaces)
+    ? rootPackageJson.workspaces
+    : rootPackageJson.workspaces?.packages ?? [];
🤖 Copy this AI Prompt to have your agent fix this:
In file scripts/lib/workspace-links.mjs around line 71:

When `workspaces` is specified as a plain array like `{"workspaces": ["packages/*"]}`, `rootPackageJson.workspaces?.packages` evaluates to `undefined`, so `packagePatterns` becomes `[]` and the function silently returns zero packages. Should handle both the shorthand array format and the `{ packages: [...] }` object format.

Evidence trail:
scripts/lib/workspace-links.mjs lines 65-85 at REVIEWED_COMMIT (line 71 shows `rootPackageJson.workspaces?.packages ?? []`). npm documentation at https://docs.npmjs.com/cli/v11/configuring-npm/package-json/ and https://docs.npmjs.com/cli/v10/using-npm/workspaces/ confirms npm workspaces use array format `"workspaces": ["packages/a"]`, not object format with `packages` property.

@raulferrodrigues raulferrodrigues deleted the feature/runtime-aliases-startup-thread branch March 28, 2026 07:24
@raulferrodrigues
Copy link
Copy Markdown
Author

sorry idk why this went to this repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant