Renderer windows set their logger source inline via initWindowSource() in
entryPoint.tsx, which had to execute before any import-time log or the source
fell back to 'UNKNOWN'. ESM hoists imports above statements, so this ordering
was fragile and applied inconsistently across windows.
LoggerService now derives the source at construction from a
<meta name="logger-window-source"> tag in each window's index.html. The meta
is parsed before any module script runs, so the source is set before any
import-time log -- no ordering rules in entryPoint.tsx. initWindowSource() is
kept as an explicit override for documentless contexts (workers, tests) and
takes precedence over the derived value.
- Add resolveWindowSourceFromMeta() and derivedWindow with
explicit > derived > UNKNOWN precedence; export the LoggerService class
- Declare the meta in all 7 window index.html files (source strings unchanged)
- Drop the 7 inline initWindowSource() calls and the subWindow initLogger.ts
module; keep the worker's explicit initWindowSource('Worker')
- Update windows/README.md and docs/guides/logging.md
- Add LoggerService unit tests
> ### 🚨 Branch strategy — read before opening this PR
>
> The v2 refactor has merged into `main`, so **`main` is the default
branch for active development** (v1 and v2 code currently coexist there
— expect large, breaking changes).
>
> - **Active development** (features, refactors, optimizations, fixes
for the current codebase) → target **`main`** (the default base).
> - **v1 maintenance** (hotfixes and subsequent v1 releases) → branch
from and target **`v1`**, _not_ `main`.
>
> A v1 fix does **not** auto-carry to `main`: if the same bug exists on
`main`, open a separate forward-port PR targeting `main`. Before
touching subsystems being replaced, read `docs/references/data/` and
watch for `@deprecated` markers — they flag code being deleted.
### What this PR does
Before this PR:
Development builds always used the fixed `Dev` suffix for Electron's
default `userData` path, so parallel dev instances shared the same app
data path and single-instance lock.
After this PR:
Development builds can set `CS_DEV_USER_DATA_SUFFIX` to use a unique
`userData` suffix per dev instance. Blank values fall back to `Dev`. The
development guide, preboot reference, and `.env.example` document both
`.env` and inline command usage. `pnpm debug` also loads `.env` through
`dotenv`, matching `pnpm dev` while preserving Electron argument
passthrough with `dotenv -- electron-vite -- ...`.
<!-- (optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)`
format, will close the issue(s) when PR gets merged)*: -->
Fixes # N/A
### Why we need it and why it was done in this way
The following tradeoffs were made:
This keeps the change scoped to the existing preboot dev `userData`
suffix path instead of introducing a new config system. The suffix is
trimmed and empty values fall back to the current default to avoid
accidentally running dev against the unsuffixed packaged data path.
The following alternatives were considered:
Adding a dedicated package script for each development instance was not
chosen because instance names are local developer concerns. A single
environment variable is enough and works from either `.env` or one-off
shell commands.
Links to places where the discussion took place: N/A
### Breaking changes
N/A
### Special notes for your reviewer
This is dev-only behavior. Packaged builds still use the existing
BootConfig-driven userData resolution path.
### Checklist
This checklist is not enforcing, but it's a reminder of items that could
be relevant to every PR.
Approvers are expected to review this list.
- [x] Branch: This PR targets the correct branch — `main` for active
development, `v1` for v1 maintenance fixes
- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: [Write code that humans can
understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans)
and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle)
- [ ] Refactor: You have [left the code cleaner than you found it (Boy
Scout
Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html)
- [x] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [ ] Documentation: A [user-guide update](https://docs.cherry-ai.com)
was considered and is present (link) or not required. Check this only
when the PR introduces or changes a user-facing feature or behavior.
- [x] Self-review: I have reviewed my own code (e.g., via
[`/gh-pr-review`](/.claude/skills/gh-pr-review/SKILL.md), `gh pr diff`,
or GitHub UI) before requesting review from others
### Release note
<!-- Write your release note:
1. Enter your extended release note in the below block. If the PR
requires additional action from users switching to the new release,
include the string "action required".
2. If no release note is required, just write "NONE".
3. Only include user-facing changes (new features, bug fixes visible to
users, UI changes, behavior changes). For CI, maintenance, internal
refactoring, build tooling, or other non-user-facing work, write "NONE".
-->
```release-note
NONE
```
---------
Signed-off-by: kangfenmao <kangfenmao@qq.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Previously the CSLOGGER_* console overrides and the verbose (silly) file level were gated behind isDev, so a packaged build could not raise its log level for troubleshooting. Replace the isDev gates in both the main and renderer LoggerService with isDev || DIAGNOSTICS_ENABLED, so setting CS_DIAGNOSTICS makes the logger behave exactly as in dev: verbose file level, console output, and the CSLOGGER_* filters all turn on together. Idempotent in dev.
Reuses the existing DIAGNOSTICS_ENABLED flag as the single source of truth; the renderer reads CS_DIAGNOSTICS via the preload-exposed process.env. Document the behavior in the diagnostics and logging guides.
Promote the temporary boot profiler into a permanent, opt-in diagnostics facility gated by CS_DIAGNOSTICS (off by default, zero overhead when unset). Move it to src/main/core/diagnostics.ts so the db and lifecycle layers no longer cross-import a lifecycle-internal file.
Probes, all gated by the same flag: per-service init timing, phase service spans, event-loop lag, and a whenReady V8 CPU profile (carried over); slow DB queries, now covering interactive-transaction interiors and batches (not just client.execute); slow IPC handlers (BaseService.ipcHandle); window construction + ready-to-show latency (WindowManager); and slow DataApi requests (ApiServer).
DataApi request duration is consolidated to a single monotonic performance.now() measurement in handleRequest, computed only when enabled; the redundant Date.now() duration in MiddlewareEngine is removed and metadata.duration is now optional.
Packaged-build safe: the CPU profile is written to the app logs directory (not process.cwd()) and a failed write can never break boot. Thresholds live in SLOW_THRESHOLD_MS; usage in docs/guides/diagnostics.md.
Also demote per-service stop/destroy logs to debug to quiet shutdown output.
Apply the naming-conventions §6.1 acronym-casing rule (MCP -> Mcp) to the
MCP* PascalCase identifier family across the codebase (McpServer, McpTool,
McpToolResponse, BuiltinMcpServerNames, McpService, etc.) plus the local
identifiers boundMcp/enableMcp/disableMcp and the didiMcp registry key.
Regenerate the OpenAPI spec from the renamed schemas.
Deliberately left unchanged (not naming-convention identifiers): persisted
field keys read by migrators (enabledMCPs), v1 Redux selectors (selectMCP),
string values (ExaMCP, logger labels), and UPPER_SNAKE constants (MCP_*).
Also fix naming issues in the data reference docs that prompted this:
- JSONStreamReader -> JsonStreamReader (match the real class name)
- rowToMCPServer -> rowToMcpServer (match the real function name)
- replace the TopicService getInstance() skeleton with a direct singleton
- sync stale MCPServer/MCPTool/McpService references in affected docs
The former v2 branch has merged into main, making the old "main is frozen,
submit to v2" guidance backwards. Update all contributor-facing entry points
to the current model: main is the active v2 development line; v1 maintenance
fixes target the v1 branch.
- CLAUDE.md: add a v2 "Current state" callout and a branch-targeting
Operational Rule (the AI-facing context).
- gh-create-pr skill: route v1 maintenance PRs to base v1.
- PR template: replace the stale hidden comment with a visible branch
callout and add a branch checklist item.
- CONTRIBUTING.md / docs/guides/contributing.md: rewrite the branch strategy
section to the new model.
- docs/guides/branching-strategy.md: add a current-model note and fix the PR
target guideline.
Move all renderer source from src/renderer/src/* up one level to
src/renderer/*, removing the redundant nested src directory.
- Update path aliases (@renderer, @types, @logger, @data) and TanStack
Router paths in electron.vite.config.ts; update tsconfig.{json,web,node}
path mappings and include globs.
- Fix Vite root-relative script paths in the 8 renderer HTML entries.
- Update cross-process relative imports in main/preload (language,
apiServer models, preload index) to drop the /src segment.
- Switch renderer test imports of the logger mock to the @test-mocks alias.
- Update hardcoded renderer paths in scripts and their fixtures, lint
configs (eslint/oxlint/biome), CODEOWNERS, docs, and the data-classify tool.
- Convert deep (../../+) relative imports within the renderer to the
@renderer alias (69 files, 108 imports); keep single-level relatives.
- Fix doc links broken by the move and correct one pre-existing broken
link in naming-conventions.md.