Token导航 LogoToken导航TokenDH.com
前端设计只读github未标认证来源可访问许可证需确认审计通过

dual-edition-module-migration双版本模块迁移

Agent Skill

dual-edition-module-migration 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

282

周安装

12

GitHub Stars

4,790

下载量

99
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:dual-edition-module-migration(双版本模块迁移)
来源仓库:https://github.com/dtyq/magic
仓库路径:skills/dual-edition-module-migration
安装命令:
npx skills add https://github.com/dtyq/magic --skill dual-edition-module-migration
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/dtyq/magic --skill dual-edition-module-migration

简介

dual-edition-module-migration 处理开源与企业版代码共存时的模块迁移与覆盖机制。

  • 适用于 Codex、Claude、Cursor、Gemini CLI 中多版本产品线的代码维护场景。
  • 保持 src/opensource 为唯一源码入口,允许 enterprise 层按需覆写特定行为。
  • 迁移过程中需严格隔离商业逻辑,禁止反向依赖造成许可合规风险。
  • 适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

SKILL.md

Dual Edition Module Migration

When to apply

  • A module must exist in both open-source and enterprise editions
  • The user mentions src/opensource, enterprise/, Vite overlay, or edition-specific behavior
  • A shared module needs to stay under src/opensource/..., but enterprise behavior must override it
  • Old src/variant/... or src/opensource/variant/... facades need to be removed
  • A migration must preserve the src/opensource import boundary

Core invariants

1. src/opensource is the shared source of truth

  • Code under src/opensource/ is the default implementation
  • src/opensource/ must not import commercial code
  • If open-source needs a dependency, migrate that dependency too or degrade the feature
  • If a file under src/opensource/ or enterprise/src/opensource/ imports a module outside the opensource tree, move that dependency into the current opensource closure instead of keeping a shim
  • Do not pull private infrastructure such as keewoodClient or teamshareClient into src/opensource

2. enterprise/ is an overlay, not a second app

  • Keep the same relative path under enterprise/ as the shared file under src/
  • Runtime resolution priority is enterprise/** first, then src/**
  • Enterprise files should be as thin as possible
  • Prefer a re-export shim in enterprise/... when it preserves behavior without duplication
  • Do not use re-export shims when the stable caller path is already @/opensource/... and the shim would import from outside the opensource tree
  • If a dependency chain is truly enterprise-only, keep the whole chain in enterprise/...
  • Do not leave enterprise-only stores or services in src just because enterprise files import them
  • Do not create an enterprise overlay file that re-imports the same logical @/opensource/... path it overrides
  • If the stable caller path is @/opensource/..., the enterprise implementation must live under enterprise/src/opensource/...
  • Do not move a dual-edition module into enterprise/components/... or another non-mirrored path unless the user explicitly wants a commercial-only module

3. Open-source callers should import the real shared path

  • Files under src/opensource/ should import @/opensource/... directly
  • Do not keep @/variant/... in open-source code
  • If enterprise needs different behavior for that shared path, add an overlay file under enterprise/src/opensource/...

4. Choose extension point by artifact type

Use this rule first:

ArtifactPreferred mechanism
React view/component rendered through factoryComponentFactory default in src/opensource plus enterprise or premium override where still needed
Hook / service / preload helper imported from open-source codeDirect @/opensource/... import plus enterprise/src/opensource/... overlay when behavior differs
Shared implementation used by both editionsMove to src/opensource/...; if callers already target @/opensource/..., migrate the real code and delete the old file instead of leaving a compatibility shim
Legacy src/components/... module becoming dual-editionMigrate to src/opensource/... plus mirrored enterprise/src/opensource/...; then switch callers to @/opensource/...
Runtime-only indirectionsrc/runtime/<domain>/ only when direct imports and overlay cannot express the binding

Architecture patterns

Pattern A: Shared baseline plus enterprise overlay

Use this for hooks, services, helpers, and other non-visual modules.

  1. Keep the default implementation in src/opensource/...
  2. Update callers to import that @/opensource/... path directly
  3. If enterprise behavior differs, add the same path under enterprise/src/opensource/...
  4. Let Vite resolve the enterprise file first at runtime
  5. Remove the old variant facade after callers are switched

Minimal example:

// src/opensource/components/business/RecordingSummary/hooks/useCancelRecord.tsx
export default function useCancelRecord() {
	// shared implementation
}
// enterprise/src/opensource/components/business/RecordingSummary/hooks/useCancelRecord.tsx
export default function useCancelRecord() {
	// enterprise implementation
}
import useCancelRecord from "@/opensource/components/business/RecordingSummary/hooks/useCancelRecord"

Pattern B: Component override

Use this when a UI component needs edition-specific rendering.

  1. Keep the default implementation in src/opensource/...
  2. Register it in src/opensource/components/ComponentRender/config/defaultComponents.tsx
  3. Keep commercial-only UI in src/... only when it owns real delta
  4. Register premium overrides only where the factory still needs explicit component replacement
  5. For helper imports such as preload code, prefer direct @/opensource/... imports plus enterprise overlay

This keeps render-time switching and non-render imports aligned.

Pattern B.5: Shared facade plus enterprise child override

Use this when the only edition difference is a small injected block inside a much larger shared page or layout.

Rules:

  1. Extract the changing block into the smallest possible shared child component or hook under src/opensource/...
  2. Keep the shared baseline minimal: null, false, no-op callback, or another tiny safe fallback
  3. Mirror only that child component or hook under enterprise/src/opensource/...
  4. Update the large shared page or layout to import the stable @/opensource/... facade instead of importing commercial modules directly
  5. Do not override the whole page or layout when a banner, modal, slogan, model tag, or hook is the real variability point

Why:

  • It minimizes duplicated page code
  • It prevents accidental divergence between editions
  • It makes review easier because the commercial delta is isolated to one extension point

Example use cases:

  • Activity banner slot in EmptyWorkspacePanel
  • Activity modal slot in MainLayout
  • Login slogan slot in SSOLayout
  • Enterprise-only hook such as useFreePointsTrigger

Pattern C: Temporary enterprise shim over existing commercial file

Use this only as a short-lived transition when a large enterprise implementation already exists under src/... and the user has not required a hard opensource-only closure.

  1. Add enterprise/src/opensource/<same-path>.ts(x)
  2. Re-export from the existing commercial file under src/...
  3. Switch all shared callers to @/opensource/...
  4. Remove variant files
  5. Later, inline or fold the shim if the codebase is cleaned up further

Do not use this pattern when the user requires src/opensource/... and enterprise/src/opensource/... to avoid importing any dependency outside the opensource tree.

Pattern D: Enterprise-only dependency closure

Use this when a module and its dependencies only exist for enterprise or App-native behavior.

Rules:

  1. Move the whole closure into enterprise/src/opensource/...
  2. Do not add src/opensource stubs for enterprise-only stores or services unless the user explicitly wants a temporary bridge
  3. Update enterprise callers to use the stable @/opensource/... path, so overlay resolves the real file
  4. Delete the old src/... files once imports are switched

Example closure:

  • stores/recordingSummary/appNative.ts
  • services/recordSummaryAppNativeService/**
  • services/AppAIRecordingService/**

Why:

  • Leaving half the chain in src recreates the old boundary violation
  • Enterprise-only dependencies should not look shared just because shared callers reference the logical path

Pattern E: Enterprise-only module with open-source stub

Use when a hook or component is moved entirely to enterprise/src/opensource/..., but src/opensource callers still import it (e.g. overlay disabled, or callers exist in both editions).

Rules:

  1. Keep a stub in src/opensource/... at the same logical path
  2. Stub returns no-op values: empty array for lists, false for flags, () => {} for callbacks, null for ReactNode
  3. Stub must match the enterprise interface exactly so all callers work without changes
  4. Enterprise overlay provides the full implementation when overlay is enabled

Stub minimization rules:

  1. Keep only the smallest surface that current open-source callers actually import
  2. Do not copy enterprise-only helper files, upload types, or private dependency adapters into src/opensource/... if the stub does not use them
  3. Prefer flattening a stub to one file when the open-source side only needs a no-op export plus one or two lightweight enums or helpers
  4. If a helper already exists globally, reuse it instead of creating a module-local duplicate in the stub

Example:

// src/opensource/.../useCollaboratorUpdatePanel.tsx (stub)
function useCollaboratorUpdatePanel({ selectedProject: _sp, onClose: _onClose }) {
	return {
		collaborators: [],
		collaborationInfo: { is_collaboration_enabled: false, default_join_permission: "viewer" },
		openManageModal: () => {},
		CollaboratorUpdatePanel: null,
	}
}
// enterprise/src/opensource/.../useCollaboratorUpdatePanel.tsx (full impl)
// Full implementation with CollaborationManageModal, useCollaborationManageData, etc.

Pattern F: Optional runtime facade

Use only when direct imports plus overlay are still not enough.

Rules:

  1. Create src/runtime/<domain>/
  2. Export a stable runtime API from that layer
  3. Keep src/opensource/ off that runtime facade unless the user explicitly wants the extra indirection
  4. Justify the runtime layer with a real binding problem, not habit

Enterprise overlay import resolution

When creating an enterprise overlay file (e.g. enterprise/src/opensource/.../ProjectCardContainer), relative imports like ../ProjectCard may fail TypeScript resolution if the target has no enterprise overlay (only partial overlay like ProjectCardShareSection).

Rule: use @/opensource/... absolute paths for modules that exist only in src or have no full enterprise overlay, so resolution falls through to src correctly.

Migration workflow

0. Find all importers before migration

Before moving or stubbing a module, run rg "ModuleName|useModuleName" (or equivalent) to find every caller.

Rule: each importer must either (a) get the stub when overlay is disabled, or (b) be updated to conditionally use the feature. Missing an importer causes build failures such as EISDIR or "module not found".

0.5. Choose the final logical path first

Before creating files, decide which import path should survive after migration.

Ask:

  • Should callers end up on @/opensource/...?
  • Is this actually a commercial-only module that should stay under @/components/...?
  • Does the enterprise implementation need to mirror src/opensource/... under enterprise/src/opensource/...?

Rule: do not start by copying code into enterprise/components/... when the long-term target is a dual-edition @/opensource/... path.

0.6. Choose the smallest override surface

Before creating any overlay file, ask:

  • Is the real delta a whole page, or only one injected child block?
  • Can the shared page keep working if that child becomes a null or no-op facade?
  • Would extracting a shared banner/modal/slogan/tag/hook avoid duplicating the page?

Rule: if the delta is only a small block inside a large shared file, first extract that block into a shared src/opensource/... facade and override only that facade in enterprise/src/opensource/....

1. Classify the target from first principles

Split the target into:

  • Shared baseline
  • Enterprise-only delta
  • Open-source forbidden dependencies
  • UI override points
  • Helper or preload entrypoints
  • Old variant facades that can be removed
  • Enterprise-only dependency closures such as native stores and native services

Ask:

  • What must exist in both editions?
  • What is truly enterprise-only?
  • Which imports inside src/opensource still point at indirection instead of the real shared file?
  • Can Vite overlay solve this directly with a mirrored enterprise path?
  • Are there forbidden clients or App-only branches that must stay out of src/opensource?

2. Keep the baseline in src/opensource

  • Move or keep the shared implementation in src/opensource/...
  • Rewrite internal imports to @/opensource/...
  • If an internal import still points outside opensource, migrate that dependency into the same closure or inline the needed code before proceeding
  • Remove App-only or enterprise-only branches from the shared copy
  • Add safe stubs or degrade behavior instead of importing private clients

3. Preserve enterprise deltas with mirrored paths

  • Add enterprise/src/opensource/... only for real behavior differences
  • Prefer thin enterprise shims only when they do not violate the opensource boundary
  • If the enterprise implementation already lives in src/... but callers must stay inside opensource, migrate the real implementation or the required subset into the mirrored enterprise/src/opensource/... path
  • If a dependency chain is enterprise-only, move the full chain instead of splitting it across src and enterprise

4. Remove variant

When old code uses @/variant/...:

  1. Replace each caller with the corresponding @/opensource/... import
  2. Create enterprise/src/opensource/... overlays for any enterprise-only behavior
  3. Delete src/variant/...
  4. Delete src/opensource/variant/...

5. Verify boundaries

For the migrated domain, check:

  • src/opensource/... only imports shared-safe dependencies
  • No src/opensource file imports @/variant/...
  • Enterprise overrides mirror the shared path under enterprise/src/opensource/...
  • src/opensource still avoids private clients and private infrastructure
  • Preload helpers import the same @/opensource/... path that runtime code conceptually depends on
  • Enterprise-only stores and services do not remain in src
  • If a shared initializer still needs enterprise-only restore logic, split the initializer: shared file keeps shared logic, enterprise overlay re-adds the enterprise branch

6. Verify compatibility

  • Shared imports still work in open-source mode
  • Enterprise runtime resolves overlay files as expected
  • Existing explicit component overrides still work if they remain in use
  • No leftover imports reference deleted variant paths

Boundary checklist

  • src/opensource does not import commercial modules directly
  • src/opensource does not import @/variant/...
  • Shared dependencies needed by the migrated module are available under src/opensource
  • Enterprise-only behavior is mirrored under enterprise/src/opensource/...
  • Enterprise-only stores/services are not left behind in src
  • Runtime-only facades are used only when direct imports plus overlay are insufficient
  • Private clients such as keewoodClient and teamshareClient are not introduced into src/opensource
  • Files under src/opensource and enterprise/src/opensource do not import modules outside the opensource tree unless the user explicitly approves a temporary exception

Verification checklist

  • Find all importers of the target module with rg before migration
  • Run targeted lint checks for touched files
  • Run focused tests for changed logic when available
  • Run build verification and fix missing mirrored dependencies iteratively
  • Search for leftover @/variant/... imports
  • Confirm enterprise overlay paths match the shared path exactly
  • Search for leftover imports to deleted enterprise-only source paths under src
  • Check initializers and lazy imports for unresolved paths after moving enterprise-only modules
  • If overlay is disabled: ensure open-source stubs exist and match the enterprise interface
  • Search for leftover imports to the pre-migration commercial path such as @/components/business/<module>

Common pitfalls

Pitfall 1: Keeping variant after the overlay exists

This preserves dead indirection and makes the import graph harder to reason about.

Rule: if direct @/opensource/... plus mirrored enterprise/... works, delete variant.

Pitfall 2: Letting src/opensource import commercial code

This breaks the hard boundary.

Rule: only enterprise/... may point back to commercial implementations as migration shims.

Pitfall 3: Forgetting helper imports

Render-time code may be correct while preload or utility code still points at old facades.

Rule: migrate preload helpers and utility imports together with the main implementation.

Pitfall 4: Copying enterprise code blindly

Large duplicate files increase drift immediately.

Rule: prefer a thin enterprise re-export shim first, then refactor if needed.

Pitfall 4.5: Leaving old commercial files behind after callers switch

This invites regressions because new code can accidentally import the pre-migration path again.

Rule: once callers are updated to @/opensource/..., delete the old src/components/... source files for that migrated closure.

Pitfall 5: Smuggling private clients into open-source

If a feature depends on private infrastructure, the shared layer should not import it.

Rule: degrade or stub the open-source path instead of copying the client.

Pitfall 6: Keeping enterprise-only stores or services in src

This makes the import graph look shared when the implementation is not actually shared.

Rule: if the module only exists for enterprise/App-native behavior, move the full chain into enterprise/src/opensource/....

Pitfall 7: Forgetting initializer split after moving enterprise-only services

A shared initializer may still dynamically import files that were intentionally removed from src.

Rule: keep the shared initializer web-safe, and add an enterprise overlay initializer when native restore logic must remain.

Pitfall 8: Making an overlay file import itself logically

If enterprise/src/opensource/foo.ts re-exports from @/opensource/foo, overlay resolution points back to the same enterprise file.

Rule: put the real enterprise implementation in the overlay file, or use a temporary non-overlay source path only during an explicit short-lived migration step.

Pitfall 9: Overlay disabled but modules moved to enterprise only

vitePluginEnterpriseOverlay may be commented out; the build then uses only src. Enterprise overlay files are never loaded.

Rule: when moving hooks/components to enterprise/src/opensource/... only, keep open-source stubs in src/opensource/... that satisfy all imports. Otherwise the build fails (e.g. EISDIR: illegal operation on a directory when importing a deleted module).

Pitfall 10: Stub interface mismatch

Open-source stubs must return the exact same interface as the enterprise implementation.

Rule: hooks must return the same shape (e.g. collaborators: [], collaborationInfo: {...}, openManageModal: () => {}, CollaboratorUpdatePanel: null). Components must export the same default and accept the same props.

Pitfall 11: Putting the enterprise file under the wrong root

If callers are meant to import @/opensource/..., placing the real file under enterprise/components/... breaks the mirrored overlay model and leaves the import graph inconsistent.

Rule: dual-edition overlays for shared modules belong under enterprise/src/opensource/....

Pitfall 12: Overbuilding the open-source stub

Copying all enterprise files, types, and helpers into src/opensource/... increases drift and makes the stub look like a real shared implementation when it is not.

Rule: keep the stub minimal. Export only what open-source callers need right now.

Pitfall 13: Duplicating generic helpers inside the migrated module

A local helper such as utils/env.ts may duplicate an existing global utility and create extra cleanup work during migration.

Rule: prefer shared utilities like @/opensource/utils/env when they already express the same behavior.

Pitfall 14: Putting the real implementation into src/opensource by mistake

This usually happens when the user says "enterprise only" or "open-source should not include this", but the migration starts from caller paths instead of feature ownership.

Rule:

  1. src/opensource/... may contain only the shared facade or no-op stub for that feature
  2. The real enterprise implementation must live under the mirrored enterprise/src/opensource/... path
  3. If the user explicitly says the open-source edition must not include the feature, do not put visible runtime behavior into src/opensource/...

Pitfall 15: Overriding a whole page for one small delta

Copying an entire page or layout just to swap one banner or modal creates unnecessary drift immediately.

Rule: extract the variable block into a dedicated shared child component or hook first, then override only that child in enterprise/src/opensource/....

RecordingSummary reference

Use RecordingSummary as the reference implementation:

  • src/opensource/... is the shared baseline
  • Open-source callers import @/opensource/... directly
  • Enterprise-only useCancelRecord and useIsCurrentRecording behavior is exposed through enterprise/src/opensource/...
  • App-native store and native recording services live only under enterprise/src/opensource/...
  • initRecordSummaryService is split so shared code keeps only web restore logic and enterprise overlay restores native logic
  • preloadRecordSummaryEditorPanel no longer needs a variant facade
  • Old src/variant/... and src/opensource/variant/... files are deleted after migration

Output expectations

When using this skill, produce:

  1. A short architecture decision: direct shared import vs enterprise overlay vs component override vs runtime facade
  2. A migration plan grouped by shared baseline, enterprise deltas, and forbidden dependencies
  3. The concrete file changes
  4. Verification status for lint, tests, and build

Keep it minimal

  • Prefer the smallest boundary-preserving change
  • Prefer enterprise shims over duplicated enterprise copies
  • Prefer direct @/opensource/... imports over extra facades
  • Do not migrate unrelated historical boundary violations unless the user expands scope

Additional resources

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

34.36%
按下载量换算34

Claude

28.33%
按下载量换算28

Cursor

20.46%
按下载量换算20

Gemini CLI

9.56%
按下载量换算9

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

只读

该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills