Skip to content

refactor(workspace): extract private frontend core packages - #1760

Closed
beruro wants to merge 2 commits into
developfrom
junyu/audit-private-frontend-packages
Closed

beruro wants to merge 2 commits into
developfrom
junyu/audit-private-frontend-packages

Conversation

@beruro

@beruro beruro commented Sep 14, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Replay algorithms and terminal shell integration live inside the application, so their dependency boundaries and tests cannot be validated independently. Existing build, lint and test discovery assumes all frontend sources belong to the app.

Solution

Extract private source-exported replay-core and terminal-shell-integration workspace packages, migrate consumers, and teach both bundlers and quality checks to discover workspace sources. Keep the mutable shell replay cache as one application-owned instance. Configure Vitest 4 projects with isolated package tests and package build/typecheck commands. Add regression coverage for replay boundaries and terminal shell events alongside the extracted implementations.

Potential risks

Workspace resolution, bundler watching and CI discovery change; pnpm is required to install the two local links. The lockfile only adds workspace importers/links and retains upstream dependency versions. These packages are private and have no public release or persistence migration; rollback reverts the extraction and reinstalls the prior lockfile. Full application/native UI suites and packaged desktop startup were not run. The cycle checker still reports four existing app-only cycles (identical on develop) involving the icon registry, session input barrels and HoverCard; no package cycle was found. Runtime CPU/RSS was not measured and no speedup is claimed. Consumer UI changes are imports and cache ownership wiring, so screenshots would not demonstrate this change.

Verification

  • pnpm install --frozen-lockfile: passed with isolated dependencies matching the current lockfile.
  • pnpm build:packages, pnpm typecheck:packages, pnpm test:packages: passed; 64 package tests.
  • pnpm exec vitest run --config config/vitest.config.ts --project app --maxWorkers=2 src/engines/SessionCore/replay/components/ShellReplayOutput/ShellReplayOutput.test.ts: four passed.
  • pnpm exec vitest list --config config/vitest.config.ts --project '@orgii/*' --json: discovered all 64 package tests.
  • node --test scripts/quality/workspace/*.test.cjs scripts/quality/dependency-boundaries/*.test.mjs scripts/ci/select-lint-targets.test.cjs: 25 passed, including actual Webpack/Rspack build and watch behavior.
  • pnpm typecheck:fast: passed, rerun after integration with latest develop.
  • node scripts/quality/dependency-boundaries/check.mjs: zero new boundary violations; three baseline edges retained.
  • node scripts/quality/check-test-placement.mjs: passed.
  • node scripts/quality/check-circular-dependencies.mjs --json: reported four existing app-only cycles, the same set as develop; unrelated cycle cleanup is excluded.
  • Normal commit hooks passed. Final diff inspected for generated artifacts, private paths and unrelated dependency churn.

Review follow-up verification

Follow-up commit 88fed4851f addresses review findings. It uses Windows-safe package filter quoting (cmd.exe kept './packages/*' literally, so package build/typecheck/test scripts matched no project and exited 0). It extends the changed-file length gate to packages/*/src, removes the unused package dist emit from pnpm build (CI still runs build:packages), and trims unconsumed replay-core value exports. It also restores the ShellReplayOutput test docblock order, merges a duplicate import, and removes a stale engine-doc entry.

  • node --test scripts/ci/*.test.cjs: 53 passed, including new package-source cases for the file-length gate.
  • pnpm test:packages: 64 passed (35 replay-core, 29 terminal-shell-integration); pnpm test:workspace: 5 passed.
  • pnpm exec vitest run --config config/vitest.config.ts --project app src/engines/SessionCore/replay/components/ShellReplayOutput/ShellReplayOutput.test.ts: 4 passed.
  • pnpm typecheck:fast, ESLint and oxlint on the changed TypeScript files, node scripts/quality/check-test-placement.mjs, and the file-length gate on the diff: passed. Commit hooks (lint-staged, tsgo, commitlint) passed.
  • Not run: Windows cmd.exe itself (double quotes are stripped by both sh and cmd), the full app suite, and a production app build.

Audit

Architecture L1 isolated builds/tests; L2 package inventory and discovery; L3 exported types; L4 application cache ownership; L5 replay bounds and event regressions; L6 source exports and dependency direction; L7 compatibility with current Vitest APIs; L8 no wire change; L9 app and bundler consumers; L10 one implementation and one mutable cache owner. Pure import changes do not introduce action controls. Resource verdict: no new timers or subscriptions in the extraction; native lifecycle measurements remain unverified.

@FresnelR27
FresnelR27 force-pushed the junyu/audit-private-frontend-packages branch from 6575c19 to 7c0bb11 Compare September 14, 2026 16:24
@Harry19081
Harry19081 removed this pull request from stack #1783 September 14, 2026 17:14
Windows runs package scripts through cmd.exe, which keeps single quotes
literally, so --filter './packages/*' matched no workspace project and
the package build, typecheck and test scripts exited 0 without running.
Use double quotes, which both sh and cmd strip.

Also:
- judge packages/*/src TypeScript in the changed-file length gate,
  matching the lint target roots
- stop pnpm build from emitting package dist output nothing consumes;
  CI still runs build:packages
- export only the replay-core values the application imports; types
  used by public signatures stay exported
- put the jsdom docblock back at the top of ShellReplayOutput.test.ts
  and merge the component's duplicate package import
- drop the stale findIndexAtTime ownership entry from the engine docs
@Harry19081

Copy link
Copy Markdown
Member

Review of 7c0bb11942. Follow-up fixes pushed as 88fed4851f.

The extraction itself holds up: moved code, bundler resolution, Vitest projects and the boundary checks all worked in local runs. Findings, all fixed in 88fed4851f:

  1. Package scripts did nothing on Windows. build:packages, typecheck:packages and test:packages quoted the filter as './packages/*'. On Windows pnpm runs scripts through cmd.exe, which keeps single quotes as part of the argument. Passing the quotes through literally reproduces No projects matched the filters with exit code 0. The scripts now use double quotes, which both sh and cmd strip.
  2. The changed-file length gate skipped package source. scripts/ci/check-changed-file-length.cjs only judged src/, while lint targets, test placement, boundaries, cycles and typed lint all cover packages/*/src. It now uses the same source roots as select-lint-targets.cjs, with tests.
  3. pnpm build emitted package dist output that nothing reads, since the app compiles the source exports. I removed it from build; CI still runs build:packages.
  4. The entry points exported 9 values that nothing outside the package tests used: SHELL_REPLAY_CACHE_MAX_BYTES, replayFramesMemoryBytes, buildShellReplayVisualRows, shellReplayRangeCacheKey, REPLAY_TURN_SEGMENT_COLOR_COUNT, REPLAY_TURN_MIN_SEGMENT_SPAN, isReplayTurnStartPreview, indexToReplaySliderValue, applyReplayTurnSegmentLayout. They are removed from /shell and /timeline. Package tests import the implementation files directly, and types used in exported signatures stay exported.
  5. Small cleanups:
    • The jsdom docblock is back at the top of ShellReplayOutput.test.ts. It still worked before, because Vitest scans the whole file.
    • The component's two imports from @orgii/replay-core/shell are merged.
    • docs/architecture/frontend-engines.md no longer lists utils/findIndexAtTime.ts under Simulator.

The description said the cycle checker reports three existing cycles. It reports four, identical on develop and this branch (the fourth is src/icons.ts ↔ src/assets/icons/StopCircleIcon.ts), so there is no regression. The description is updated.

Verification

  • Passed: node --test scripts/ci/*.test.cjs (53), pnpm test:packages (64), pnpm test:workspace (5), the ShellReplayOutput suite (4), pnpm typecheck:fast, ESLint and oxlint on the changed files, test placement, the file-length gate, and the commit hooks.
  • Not run: Windows cmd.exe itself, the full app suite, a production build.

#1762 no longer depends on this PR: stack #1783 was dissolved and #1762 now targets develop directly.

@Harry19081 Harry19081 added refactor Code restructuring without an intended behavior change frontend-ui Frontend UI, design system, accessibility, layout, or theming labels Sep 15, 2026
@Harry19081

Copy link
Copy Markdown
Member

Closing this one — not because the work is wrong, but because the cost/benefit doesn't hold up. The extraction itself is clean and my earlier review confirmed that; this is a scope judgment, not a quality one.

What the diff delivers: 7 source files moved into two private, never-published packages, and 7 genuinely new test cases (shellReplayRange 10 → 13, ShellIntegrationAddon 25 → 29; findIndexAtTime and replayTurnSegments are unchanged at 9 and 8). The rest of the +1,770 lines is the apparatus needed to make a workspace layout exist: workspace-sources.mjs, a 396-line bundler test, a 203-line workspace boundary test, plus dependency-cruiser, the circular-dependency checker, lint-target selection, the file-length gate, the CI workflow, both bundler configs, Vitest projects and the root scripts.

Why the premise doesn't survive contact with the files. The stated problem is that these algorithms' dependency boundaries can't be validated independently. But the extracted files are already dependency-free: findIndexAtTime.ts and ShellIntegrationAddon.ts have no imports at all, shellReplayRequestGuard.ts has one local type import, and replayTurnSegments.ts and shellReplayRange.ts have one type-only import each. There is nothing to un-import. We already run dependency-cruiser behind a baseline-driven checker in scripts/quality/dependency-boundaries/check.mjs — a rule there pins the same invariant in roughly ten lines of config rather than a thousand lines of build infrastructure.

shellReplayCache.ts isn't an independent improvement either: it exists only because a module-level singleton can't live inside the extracted package.

Why the cost is real rather than theoretical. There's no packages/ directory on develop, no monorepo plan in docs/, and pnpm-workspace.yaml is still ["."] — so this would be the sole inhabitant of a new layout, and the layout's upkeep lands on the repo's most frequently edited infrastructure files. The branch shows what that means in practice: 786 commits of drift in seven days produced conflicts in package.json, the file-length gate and the engine doc. It has also gone stale in a way the green checks don't reveal — develop moved oxlint's config to src/.oxlintrc.json, but this branch's lint:fast and its added lint-staged entry still point at the removed root .oxlintrc.json. The lint-staged entry sits in a non-conflicting hunk, so a routine conflict resolution would merge it green and break commits on package files later. The passing checks above are real, but they ran against a 786-commit-old base.

The part worth keeping. The 7 new test cases need none of the extraction. Happy to port them onto develop against today's paths as a small test(replay) PR, or leave that to you if you'd rather carry it — just say which.

Sorry to land this after the follow-up round you did; the boundary question is worth raising separately if you think the invariant needs stronger enforcement than a cruiser rule.

@Harry19081 Harry19081 closed this Sep 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend-ui Frontend UI, design system, accessibility, layout, or theming refactor Code restructuring without an intended behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants