skills/ohos-dev-arkui-v1-v2-migration/SKILL.md
Use when migrating OpenHarmony/HarmonyOS ArkUI state management from V1 (@Component, @State/@Prop/@Link/@Provide/@Consume/@Watch/@Observed) to V2 (@ComponentV2, @Local/@Param/@Event/@Provider/@Consumer/@Monitor/@ObservedV2/@Trace), or assessing migration feasibility. Trigger phrases include "迁移V1到V2", "V1V2迁移", "状态管理迁移", "将@Component改为@ComponentV2", "迁移@State/@Prop/@Link到V2", "migrate V1 to V2". Provides automated analysis (component structure, dependency tracing, API version detection, V1/V2 mixing validation), step-by-step migration guidance, and post-migration validation.
npx skillsauth add openharmonyinsight/openharmony-skills ohos-dev-arkui-v1-v2-migrationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Migrate OpenHarmony ArkUI @Component (V1) components to @ComponentV2 (V2).
Activate this skill when the user expresses any of the following intents:
@Component to @ComponentV2@State/@Prop/@Link to their V2 equivalents0. Confirm target → 1. Analyze → 2. Plan → 3. Execute → 4. Verify
Each phase is detailed below. Always proceed in this order; never skip analysis and jump straight to execution.
Before any analysis, confirm the migration target in the following order.
You must first ask the user for the project path, e.g.:
Please provide the HarmonyOS/OpenHarmony project path to migrate.
After receiving the path, proceed to Case 2. Do not assume or guess the project path.
Run the scan script:
python3 {{SKILL_DIR}}/scripts/component_analyzer.py <project-path> --scan-v1
The script outputs the list of all V1 components in the project, plus an instruction field.
You must present the V1 component list to the user and ask which component to migrate. Do not skip this step.
If the list is empty, inform the user that the project contains no V1 components and no migration is needed.
Proceed directly to Step 1 (Analysis).
python3 {{SKILL_DIR}}/scripts/api_version_checker.py <project-dir> --json
Key output fields:
mixingRules: "strict" (API < 19) or "relaxed" (API >= 19)compatibleApiVersion: the minimum compatible API versionavailableApis: list of available compatibility APIsDecision points:
strict → complex types cannot cross the V1/V2 boundary during migration; a bridge pattern may be requiredrelaxed → UIUtils.enableV2Compatibility() and UIUtils.makeV1Observed() can relax the constraintspython3 {{SKILL_DIR}}/scripts/component_analyzer.py <target-file-or-dir> --json
Output includes:
python3 {{SKILL_DIR}}/scripts/dependency_tracer.py <component-name> <project-dir> --json
Output:
mustMigrate: list of components that must be migrated together due to data interactionDecision points:
mustMigrate contains only one component → it can be migrated independentlypython3 {{SKILL_DIR}}/scripts/mixing_validator.py <project-dir> --json [--target <component-name>]
Output:
violations: mixing issues that will cause compile/runtime errorswarnings: mixing scenarios that may be riskysuggestions: available compatibility API suggestionssummary.isCompliant: whether all checks passBased on the analysis, report the migration scope and strategy to the user:
The target component has no external data interaction (hasInput: false, hasOutput: false), or all interactions use simple types.
The target component exchanges complex types with its parent/child components. All components in mustMigrate must be migrated together.
When V1 must pass an @Observed-decorated class to a V2 component:
V1Comp → V1BridgeComponent(@Component) → V2Comp(@ComponentV2)
The bridge is a pure V1 component: it destructures the @Observed class into simple-type fields and passes them to the V2 child's @Param (complex types cannot cross the V1→V2 boundary when API < 19). It must NOT hold an @ObservedV2 object via a V1 decorator. For multi-component sharing, use a standalone @ObservedV2/@Trace singleton written by V1 and read by V2. See the bridge section in references/mixing-rules.md.
Confirm the strategy with the user before proceeding to execution.
Rewrite the code item by item in the following order. Each item maps to a reference document.
@Component → @ComponentV2
If the component has @Entry, leave it unchanged (@Entry works in both V1 and V2).
If the component has @Reusable, change it to @ReusableV2.
For the full mapping table, see references/decorator-mapping.md. Quick reference:
| V1 | V2 | Key points |
|----|-----|--------|
| @State simple type | @Local | Direct replacement |
| @State complex type | @Local + @ObservedV2/@Trace on the class | V2 @Local observes only itself, not its properties |
| @State needing external init | @Param @Once | @Local forbids external initialization |
| @Prop | @Param | @Param is passed by reference (not a deep copy); @Param is read-only |
| @Link | @Param + @Event | Replace two-way binding with a callback pattern |
| @Provide/@Consume | @Provider/@Consumer | V2 requires the () syntax; the alias is the unique match key |
| @Watch | @Monitor | V2 is asynchronous; supports multiple variables; provides before/after |
| @Observed/@ObjectLink | @ObservedV2/@Trace | Deep observation; no longer needs child-component decomposition |
| $$ binding | !! binding | Direct replacement |
Change @Observed classes to @ObservedV2 and add @Trace to the properties.
// V1
@Observed
class Model {
@Track public name: string = '';
@Track public count: number = 0;
}
// V2
@ObservedV2
class Model {
@Trace public name: string = '';
@Trace public count: number = 0;
}
Note: @Observed and @ObservedV2 cannot coexist on the same class. If the class is referenced by other V1 components, resolve those dependencies first.
For detailed rules, see references/class-migration.md.
| V1 | V2 |
|----|-----|
| ForEach | Repeat(...).each(...).key(...) |
| LazyForEach + IDataSource | Repeat(...).each(...).key(...).virtualScroll() + @Local array |
In V2 the data source is a plain @Local array; modifying the array triggers updates — no need to call notifyDataAdd and friends manually.
Use .templateId() + .template() for template rendering instead of manual if checks.
For detailed rules and code examples, see references/rendering-migration.md.
| V1 | V2 |
|----|-----|
| LocalStorage | @ObservedV2/@Trace singleton |
| AppStorage | AppStorageV2.connect() |
| @StorageProp/@StorageLink | AppStorageV2.connect() + @Local + @Monitor |
| PersistentStorage | PersistenceV2.globalConnect() |
| Environment | Read directly from UIAbilityContext.config |
Important: keep V1 API calls; only add V2 API calls. During incremental migration, a single .ts file may contain V1 API calls for multiple keys. When migrating a component, add the corresponding V2 API (e.g. AppStorageV2.connect()) only for the keys that component uses, and do not remove the original V1 API calls (e.g. AppStorage.setOrCreate()), because other not-yet-migrated V1 components may still be using other keys in the same file. Only when stateApiByKey shows that all decoratorUsage for a key have been migrated to V2 may the V1 API calls for that key be removed.
For detailed rules, see references/app-state-migration.md.
ChildrenMainSize/WaterFlowSections/attributeModifier) with UIUtils.makeObserved().animateTo is incompatible with V2's asynchronous update mechanism; force a synchronous flush first with animateToImmediately (API < 22) or UIUtils.applySync() (API >= 22).For detailed rules, see references/advanced-topics.md.
After migration, consider adopting new V2 capabilities:
@Computed: derived state with automatic result cachingRepeat template rendering + virtualScroll: replaces ForEach/LazyForEachpython3 {{SKILL_DIR}}/scripts/mixing_validator.py <project-dir> --json --target <component-name>
Ensure summary.isCompliant is true and all violations are empty.
@Component → @ComponentV2@ObservedV2 + @Trace@Link two-way binding changed to @Param + @Event callback pattern$$ replaced with !!ForEach/LazyForEach replaced with RepeatanimateTo (if any) has a synchronous-flush prefix added@Observed and @ObservedV2 coexisting on the same class| File | Contents | When to consult |
|------|------|----------|
| references/decorator-mapping.md | Full decorator mapping table, migration rules for @State/@Prop/@Link/@Provide/@Watch | When rewriting state variables |
| references/class-migration.md | @Observed/@ObjectLink/@Track → @ObservedV2/@Trace, nested object observation, precise updates | When migrating data object classes |
| references/mixing-rules.md | V1/V2 mixing rules, API < 19 vs >= 19 differences, bridge pattern, enableV2Compatibility | When components coexist during migration |
| references/rendering-migration.md | ForEach/LazyForEach → Repeat, virtualScroll, template rendering, @Reusable → @ReusableV2 | When rewriting rendering logic |
| references/app-state-migration.md | LocalStorage/AppStorage/PersistentStorage/Environment → V2 alternatives | When migrating app-level state |
| references/advanced-topics.md | Built-in objects (makeObserved), animateTo migration, V1/V2 update mechanism differences | When handling special cases |
| references/architecture.md | Overall skill architecture, five-phase workflow, script responsibilities and import relationships | Maintainer reference: understanding script collaboration and data flow |
| references/migration-overview.md | Design overview, detailed JSON output fields of each script, Storage key tracing mechanism, end-to-end example walkthrough | Maintainer reference: interpreting script output and migration decisions |
| Directory | Scenario | Migration points covered |
|------|------|-----------|
| examples/simple-component/ | Simple component | @State→@Local, @Prop→@Param |
| examples/component-with-props/ | Complex parent-child interaction | @Link→@Param+@Event, @Provide→@Provider, @Watch→@Monitor, $$→!! |
| examples/observed-class/ | Data object | @Observed→@ObservedV2, @ObjectLink→@Trace, nested observation |
| examples/localstorage/ | App-level state | LocalStorage→singleton, AppStorage→AppStorageV2, PersistentStorage→PersistenceV2 |
| examples/partial-migration/ | Partial migration and coexistence | V1/V2 coexistence, bridge pattern, API version checks |
Each example directory contains before.ets (V1 code) and after.ets (V2 code) for side-by-side reference.
@Param @Once.@Monitor.@ObservedV2/@Trace can directly observe nested properties; you no longer need to decompose child components layer by layer.references/mixing-rules.md).testing
--- name: ohos-req-value-decision description: Use after review meeting to record decision and route to next step. Triggers: 评审决策纪要, 评审结论回流, value decision, 评审接纳, 评审不接纳, 评审退回, 下次重新上会. Do NOT use for feature baseline (ohos-req-feature-baseline), review gate checks (ohos-req-review-gate), or IR generation (ohos-req-feature-to-ir). metadata: author: openharmony scope: common stage: requirements capability: value-decision version: 0.3.0 status: draft tags: - sdd - requirements
development
Use when converting an OpenHarmony requirement document, spec, or design proposal into an OpenHarmony review slide deck (需求评审 / 需求变更评审 / 设计评审 PPTX) — produces the fixed OpenHarmony-branded review-deck structure (OH logo on every page) with architecture/flow diagrams and field tables. Triggers on "需求评审PPT", "需求变更评审", "把需求文档转成评审PPT", "spec转评审PPT", "requirement/spec to review deck". NOT for arbitrary or generic slide decks unrelated to OpenHarmony requirement/design review.
testing
Use when performing the Phase 0 Step 0.5 Review Ready Gate on a 04-feature.md, especially when the user says "evaluate gate", "review readiness", "feature ready?", "should we generate IR", or when the ohos-req-intake-orchestration main session needs a structured Ready / Conditional Ready / Not Ready judgment instead of doing the check inline. Reads 01-04, runs seven fixed checks plus a conditional-items check, and returns a machine-readable JSON summary plus a human-readable table that the main session can route on. Do NOT use for feature baseline generation (ohos-req-feature-baseline), value decision recording (ohos-req-value-decision), or IR generation (ohos-req-feature-to-ir).
testing
--- name: ohos-req-requirement-intake description: Use when importing an OHOS requirement into Phase 0.1, especially for 01-requirement.md, requirement intake, background, user value, scenarios, scope, FR/NFR, affected modules, or priority. Triggers: 需求导入, 01-requirement, 需求基线, RR单号. Do NOT use for feasibility analysis (ohos-req-feasibility-analysis), architecture decision (ohos-req-arch-decision), or feature baseline (ohos-req-feature-baseline). metadata: author: openharmony scope: common