You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat: stabilize shared-project types across products - #8
Keep shared-project declarations stable across full/selected preparation and single-product dev/build, while preserving legitimate field removal and active-product runtime isolation.
主要变化 / Changes
Collect all associated products/variants for affected project ownership groups in the current environment, resolving canonical development and production host contexts.
Coordinate standard dev/build generation once per affected project and validate a private type-contract handshake before plugins can overwrite declarations.
Mark inferred product/context-specific fields optional; preserve explicit schema semantics and public-prefix/scope boundaries.
Reject ambiguous host-root/output ownership before writing. Resolve symlinked and future output paths consistently.
Serialize collection/publication, recover verified dead lock owners conservatively, and abort/drain preparation when dependencies fail.
Add deterministic concurrency/cancellation, actual CLI dev, shared Electron main/preload/renderer, deletion, ownership, and mixed-host regressions. Preserve hostless/non-Vite behavior.
Update English/Chinese documentation and migration guidance.
验证情况 / Verification
Current head: 2646a7ba3f6e2bf07575e3956685a17203d264d4.
Latest test-only cleanup: 15 affected tests, ESLint and TypeScript passed locally; no cases were removed. Production code is unchanged from e8ee058, whose full local 701-test suite, package build and publint passed.
Independent review completed for the four initial findings, portable lock recovery, and the follow-up shared-owner cache issue.
Project preparation invalidates all cached contracts conservatively; a real A → B → A shared-root regression verifies fresh handshakes, while ordinary targets retain cache reuse.
Fixed deferred preparation cache invalidation, global raw-env optionality across owned scopes/aliases, non-Vite adapter isolation, and schema-declared handshake keys.
Lock recovery uses an exclusive per-owner directory claim; regressions cover contention, late recoverers, abandoned claims, and killed-process recovery. Twenty coordination-suite repetitions passed during development.
Simplified canonical context collection and removed a redundant stateless test assertion; retained compiler and real CLI regression coverage.
CI: 11/11 jobs passed for this exact head, including Linux/macOS/Windows on Node 22.18.0 and 24.x, packaged compatibility, and all three Electron acceptance jobs.
Packaged profiles: full on Linux/Node 24, daily on Linux/Node 22, platform on macOS and Windows.
Both findings from Copilot re-review were reproduced and fixed: config paths resolve from the configured project path before canonicalization; generic owners contribute to raw-key reconciliation without automatic publication. Regression coverage includes symlink misselection, hostless and no-Matrix-plugin ancestors, stable declarations, absent-output preservation, and strict TypeScript compilation.
Independent review found no blockers or further worthwhile simplifications. The final local suite passed with two workers after a default-concurrency run timed out in an existing CLI test; default-concurrency CI passed all six OS/Node combinations without that failure.
Fixed and verified the subsequent fallback schema finding: generic and worker declarations share normalized metadata while original schema defaults remain available at runtime. A shared-output prepare/build regression covers required, optional, and defaulted fields. The review discussion is resolved.
Final cleanup removes unused unlink-mock error plumbing and four redundant assertions (net −12 lines), without changing production behavior. No further Copilot review cycle is planned for this scope.
风险 / Risks
Deferred compatibility edge case: standalone Vite with a symlinked root and a parent-relative custom declaration output can resolve the output against the physical parent (Vite 7, or Vite 8 with resolve.preserveSymlinks: true). The proposed path patch is excluded from this PR by scope choice; the finding remains unresolved.
Approved compatibility constraint: coordinated declarations require the resolved host root and output to stay within project.root. Align project.root with the actual shared project directory and use project.configFile for configurations stored elsewhere. Unsupported ownership fails before writes instead of silently narrowing a shared declaration.
Host-aware automatic coordination covers discoverable Vite/electron-vite configurations for standard dev/build. Custom targets and non-Vite hosts retain their existing generation behavior.
Host configuration code executes for both canonical lifecycles; this adds startup work and is not a side-effect-free static scan. Uncollected contract changes fail explicitly.
Dev/build preparation remains per-project to preserve existing just-in-time preparation order; this is not a multi-file transaction.
Live or uncertain lock owners are never reclaimed by age. A process interrupted while holding a recovery claim fails closed; the timeout identifies the lock and sibling claim directories for manual cleanup only after confirming no preparation or recovery is running.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Deferred preparation can leave another shared owner's cached handshake stale, causing subsequent valid builds to fail.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Invalidate shared ownership caches after deferred preparation
src/cli/index.ts:126
Invalidate cached contracts for all projects sharing the affected ownership group. With projects A/B sharing a physical root, an A → B → A build sequence fails if B's deferred preparation adds a public field: B publishes the updated declaration, but the final A build reuses its old handshake and rejects the field as uncollected. Clearing the cache after preparation is a conservative fix, though it may recollect unrelated projects; group-aware invalidation would avoid that extra work. Add an interleaved two-project regression.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Cross-process recovery and cross-host coordination need human review, with unresolved correctness issues requiring fixes.
No open issues 🎉
2 previously missed issues
In code that hasn't changed since last review
Resolve configFile relative to the configured project path
src/typegen/project.ts:110
Resolving configFile against the canonical root changes relative paths when project.root is a symlink. For example, if links/app points to packages/app and configFile is ../configs/vite.config.mjs, the automatic precheck selects links/configs/vite.config.mjs, but this call looks under packages/configs. Preparation can then fail or load a different configuration. Resolve the config against the configured project path first; keep canonicalizing the selected file and worker directory separately.
Retain hostless owners for consistent raw-key optionality
src/typegen/project.ts:112
Skipping hostless owners makes prepare and dev/build disagree about global raw-key optionality. Suppose an ancestor project belongs to alpha (VITE_X present) and gamma (VITE_X absent), and a nested Vite project belongs to beta (VITE_X present). Full prepare makes ImportMetaEnv.VITE_X optional in both outputs. Building beta skips the ancestor here and rewrites the nested property as required, leaving conflicting interface declarations when both files are included. Retain generic owners as inputs to raw-key reconciliation without automatically publishing their outputs. Add a full-prepare → nested-build regression that compiles both declarations.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
改动目的 / Purpose
Closes #7.
Keep shared-project declarations stable across full/selected preparation and single-product dev/build, while preserving legitimate field removal and active-product runtime isolation.
主要变化 / Changes
验证情况 / Verification
Current head:
2646a7ba3f6e2bf07575e3956685a17203d264d4.Latest test-only cleanup: 15 affected tests, ESLint and TypeScript passed locally; no cases were removed. Production code is unchanged from e8ee058, whose full local 701-test suite, package build and publint passed.
Independent review completed for the four initial findings, portable lock recovery, and the follow-up shared-owner cache issue.
Project preparation invalidates all cached contracts conservatively; a real A → B → A shared-root regression verifies fresh handshakes, while ordinary targets retain cache reuse.
Fixed deferred preparation cache invalidation, global raw-env optionality across owned scopes/aliases, non-Vite adapter isolation, and schema-declared handshake keys.
Lock recovery uses an exclusive per-owner directory claim; regressions cover contention, late recoverers, abandoned claims, and killed-process recovery. Twenty coordination-suite repetitions passed during development.
Simplified canonical context collection and removed a redundant stateless test assertion; retained compiler and real CLI regression coverage.
CI: 11/11 jobs passed for this exact head, including Linux/macOS/Windows on Node 22.18.0 and 24.x, packaged compatibility, and all three Electron acceptance jobs.
Packaged profiles: full on Linux/Node 24, daily on Linux/Node 22, platform on macOS and Windows.
Documentation checks: passed.
Both findings from Copilot re-review were reproduced and fixed: config paths resolve from the configured project path before canonicalization; generic owners contribute to raw-key reconciliation without automatic publication. Regression coverage includes symlink misselection, hostless and no-Matrix-plugin ancestors, stable declarations, absent-output preservation, and strict TypeScript compilation.
Independent review found no blockers or further worthwhile simplifications. The final local suite passed with two workers after a default-concurrency run timed out in an existing CLI test; default-concurrency CI passed all six OS/Node combinations without that failure.
Fixed and verified the subsequent fallback schema finding: generic and worker declarations share normalized metadata while original schema defaults remain available at runtime. A shared-output prepare/build regression covers required, optional, and defaulted fields. The review discussion is resolved.
Final cleanup removes unused unlink-mock error plumbing and four redundant assertions (net −12 lines), without changing production behavior. No further Copilot review cycle is planned for this scope.
风险 / Risks
Deferred compatibility edge case: standalone Vite with a symlinked root and a parent-relative custom declaration output can resolve the output against the physical parent (Vite 7, or Vite 8 with
resolve.preserveSymlinks: true). The proposed path patch is excluded from this PR by scope choice; the finding remains unresolved.Approved compatibility constraint: coordinated declarations require the resolved host root and output to stay within
project.root. Alignproject.rootwith the actual shared project directory and useproject.configFilefor configurations stored elsewhere. Unsupported ownership fails before writes instead of silently narrowing a shared declaration.Host-aware automatic coordination covers discoverable Vite/electron-vite configurations for standard dev/build. Custom targets and non-Vite hosts retain their existing generation behavior.
Host configuration code executes for both canonical lifecycles; this adds startup work and is not a side-effect-free static scan. Uncollected contract changes fail explicitly.
Dev/build preparation remains per-project to preserve existing just-in-time preparation order; this is not a multi-file transaction.
Live or uncertain lock owners are never reclaimed by age. A process interrupted while holding a recovery claim fails closed; the timeout identifies the lock and sibling claim directories for manual cleanup only after confirming no preparation or recovery is running.