@ohos-cpf/3rdloop 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -25
- package/lib/cli.js +54 -29
- package/lib/config-cmd.js +1 -1
- package/lib/config.js +32 -0
- package/lib/doctor.js +266 -48
- package/lib/mcp.js +498 -0
- package/lib/opencode.js +75 -29
- package/lib/orch.js +32 -10
- package/lib/runner.js +8 -5
- package/lib/serve.js +162 -149
- package/lib/step.js +15 -4
- package/lib/web.js +107 -265
- package/lib/workflow.js +18 -8
- package/package.json +6 -2
- package/vendor/Archive/data/.index/meta.json +7 -0
- package/vendor/Archive/data/.index/search.db +0 -0
- package/vendor/Archive/data/docs/experiences/arkts-check-tool-pitfalls-baseline-comparison.md +13 -0
- package/vendor/Archive/data/docs/experiences/arkts-deep-path-import-recognition.md +31 -0
- package/vendor/Archive/data/docs/experiences/arkts-demo-coverage-entry-file-case-mismatch.md +25 -0
- package/vendor/Archive/data/docs/experiences/arkts-demo-coverage-import-trailing-slash.md +20 -0
- package/vendor/Archive/data/docs/experiences/arkts-library-source-files-may-be-ts.md +18 -0
- package/vendor/Archive/data/docs/experiences/arkts-typedarray-buffer-interface-cast-compile-fixes.md +36 -0
- package/vendor/Archive/data/docs/experiences/arkts-xts-compile-error-clustering-fix.md +24 -0
- package/vendor/Archive/data/docs/experiences/arkts-xts-doc-expected-value-runtime-probe.md +35 -0
- package/vendor/Archive/data/docs/experiences/arkts-xts-fixture-rawfile-testability-injection.md +33 -0
- package/vendor/Archive/data/docs/experiences/code-linter-chinese-comment-false-positive.md +16 -0
- package/vendor/Archive/data/docs/experiences/esobject-new-expression-variable-tracking.md +33 -0
- package/vendor/Archive/data/docs/experiences/filesystem-case-sensitivity-module-resolution.md +31 -0
- package/vendor/Archive/data/docs/experiences/gitcode-clone-redirect-warning-normal.md +13 -0
- package/vendor/Archive/data/docs/experiences/kn_msgvq1w585ec8319.md +77 -0
- package/vendor/Archive/data/docs/experiences/kn_msovnm6rd46de72c.md +98 -0
- package/vendor/Archive/data/docs/experiences/kn_mspt8vntfe708576.md +87 -0
- package/vendor/Archive/data/docs/experiences/kn_mspu1ei77adbbb48.md +133 -0
- package/vendor/Archive/data/docs/experiences/kn_mspubgak8d30bfce.md +128 -0
- package/vendor/Archive/data/docs/experiences/kn_mspug2de3cb1f7c3.md +115 -0
- package/vendor/Archive/data/docs/experiences/kn_skill_opt_001.md +38 -0
- package/vendor/Archive/data/docs/experiences/loop-artifacts-verification-evidence-triangle.md +19 -0
- package/vendor/Archive/data/docs/experiences/macos-bash-replace-build-ps1.md +19 -0
- package/vendor/Archive/data/docs/experiences/macos-bsd-diff-q-illegal-option.md +15 -0
- package/vendor/Archive/data/docs/experiences/migrate-cjs-compatible-api-version-map-limit.md +17 -0
- package/vendor/Archive/data/docs/experiences/mp3agic-arkts-library-behavior-quirks.md +21 -0
- package/vendor/Archive/data/docs/experiences/ohos-face-detection-scan-api-mapping.md +15 -0
- package/vendor/Archive/data/docs/experiences/pr-metadata-and-diff-integrity-verification.md +12 -0
- package/vendor/Archive/data/docs/experiences/rn-coverage-index-signature-pseudo-member-false-negative.md +32 -0
- package/vendor/Archive/data/docs/experiences/rn-memory-check-severity-calibration.md +21 -0
- package/vendor/Archive/data/docs/experiences/rn-platform-specific-api-exclusion-evidence.md +24 -0
- package/vendor/Archive/data/docs/experiences/rn-upstream-version-diff-pitfalls.md +17 -0
- package/vendor/Archive/data/docs/experiences/rn-version-gap-risk-rating-rules.md +13 -0
- package/vendor/Archive/data/docs/experiences/rn-view-lib-native-contract-diff-fabric-spec.md +16 -0
- package/vendor/Archive/data/docs/experiences/rnoh-adapter-package-version-field-semantics.md +18 -0
- package/vendor/Archive/data/docs/experiences/rnoh-arkts-sqlite-rows-array-format.md +18 -0
- package/vendor/Archive/data/docs/experiences/rnoh-dependency-residue-scan-strategy.md +18 -0
- package/vendor/Archive/data/docs/experiences/rnoh-example-local-lib-dep-use-tgz.md +53 -0
- package/vendor/Archive/data/docs/experiences/rnoh-example-prereserve-rntesterlist.md +17 -0
- package/vendor/Archive/data/docs/experiences/rnoh-example-template-compatiblesdkversion-upgrade.md +29 -0
- package/vendor/Archive/data/docs/experiences/rnoh-example-turbomodule-shell-adaptation-checklist.md +41 -0
- package/vendor/Archive/data/docs/experiences/rnoh-mcp-build-project-tool-risk.md +18 -0
- package/vendor/Archive/data/docs/experiences/rnoh-npm-devdependencies-version-precheck.md +29 -0
- package/vendor/Archive/data/docs/experiences/rnoh-repo-baseline-version-verification.md +13 -0
- package/vendor/Archive/data/docs/experiences/rnoh-repo-upstream-directory-mapping.md +18 -0
- package/vendor/Archive/data/docs/experiences/rnoh-stateless-library-zero-leak-verification.md +31 -0
- package/vendor/Archive/data/docs/experiences/rnoh-template-npmrc-credential-removal.md +15 -0
- package/vendor/Archive/data/docs/experiences/rnoh-turbomodule-codegen-wiring-verification.md +19 -0
- package/vendor/Archive/data/docs/experiences/rnoh-turbomodule-cpp-methodmap-compatibility-check.md +20 -0
- package/vendor/Archive/data/docs/experiences/scenario-doc-vs-source-signature-diff-four-patterns.md +24 -0
- package/vendor/Archive/data/docs/experiences/static-analysis-grep-cross-validation.md +29 -0
- package/vendor/Archive/demo.js +489 -0
- package/vendor/Archive/index.js +43 -0
- package/vendor/Archive/package.json +16 -0
- package/vendor/Archive/src/constants.js +83 -0
- package/vendor/Archive/src/data/stopwords.txt +110 -0
- package/vendor/Archive/src/data/synonyms.json +25 -0
- package/vendor/Archive/src/data/terms.txt +59 -0
- package/vendor/Archive/src/db/sqlite-backend.js +312 -0
- package/vendor/Archive/src/db/sqlite-schema.js +64 -0
- package/vendor/Archive/src/engine.js +501 -0
- package/vendor/Archive/src/index/index-manager.js +203 -0
- package/vendor/Archive/src/index/index-state.js +94 -0
- package/vendor/Archive/src/index/search-text-builder.js +106 -0
- package/vendor/Archive/src/index.js +22 -0
- package/vendor/Archive/src/parser/api-identifiers.js +121 -0
- package/vendor/Archive/src/parser/api-suffixes.js +48 -0
- package/vendor/Archive/src/parser/heading-normalize.js +40 -0
- package/vendor/Archive/src/parser/markdown-splitter.js +215 -0
- package/vendor/Archive/src/search/catalog-routing.js +87 -0
- package/vendor/Archive/src/search/fts-search.js +289 -0
- package/vendor/Archive/src/search/query-normalizer.js +159 -0
- package/vendor/Archive/src/search/query-rewriter.js +72 -0
- package/vendor/Archive/src/search/search-engine.js +72 -0
- package/vendor/Archive/src/search/snippet.js +64 -0
- package/vendor/Archive/src/store/dir-store.js +103 -0
- package/vendor/Archive/src/store/doc-store.js +36 -0
- package/vendor/Archive/src/tokenizer/lexicon.js +151 -0
- package/vendor/Archive/src/tokenizer/tokenizer.js +167 -0
- package/vendor/Archive/src/types.js +86 -0
- package/vendor/Archive/src/utils/hash.js +16 -0
- package/vendor/Archive/src/utils/lock.js +73 -0
- package/vendor/Archive/src/utils/path-safety.js +96 -0
- package/vendor/Archive/src/utils/paths.js +39 -0
- package/vendor/BadCase/rn/INDEX.md +127 -0
- package/vendor/BadCase/rn/cases/KI-001-webview/350/247/206/351/242/221/346/227/240/346/263/225/346/250/252/345/261/217.md +52 -0
- package/vendor/BadCase/rn/cases/KI-002-fastImage/347/203/255/346/233/264/346/226/260/345/233/276/347/211/207/345/244/261/350/264/245.md +37 -0
- package/vendor/BadCase/rn/cases/KI-003-wechat/347/274/251/347/225/245/345/233/276/346/234/254/345/234/260/345/233/276/347/211/207.md +62 -0
- package/vendor/BadCase/rn/cases/KI-004-wechat/345/233/236/350/260/203/346/227/266/345/272/217.md +47 -0
- package/vendor/BadCase/rn/cases/KI-005-geolocation/345/257/274/345/205/245/350/267/257/345/276/204/345/220/216/347/274/200.md +31 -0
- package/vendor/BadCase/rn/cases/KI-006-SmartRefreshLayout/346/231/272/350/203/275/346/214/207/351/222/210/345/264/251/346/272/203.md +55 -0
- package/vendor/BadCase/rn/cases/KI-007-orientation-locker/344/274/240/346/204/237/345/231/250/345/210/235/345/247/213/345/214/226.md +58 -0
- package/vendor/BadCase/rn/cases/KI-008-orientation-locker/344/274/240/346/204/237/345/231/250/345/274/225/347/224/250/350/256/241/346/225/260.md +47 -0
- package/vendor/BadCase/rn/cases/KI-009-pager-view/345/265/214/345/245/227/346/273/221/345/212/250.md +38 -0
- package/vendor/BadCase/rn/cases/KI-010-screens/346/211/213/345/212/277/345/206/262/347/252/201.md +48 -0
- package/vendor/BadCase/rn/cases/KI-011-spring-scrollview/346/211/213/345/212/277/351/207/215/345/244/215/347/273/221/345/256/232.md +49 -0
- package/vendor/BadCase/rn/cases/KI-012-qr-camera/346/250/252/345/261/217/351/200/202/351/205/215.md +59 -0
- package/vendor/BadCase/rn/cases/KI-013-webview/346/267/261/350/211/262/346/250/241/345/274/217/350/203/214/346/231/257/350/211/262.md +37 -0
- package/vendor/BadCase/rn/cases/KI-014-amap-geolocation/345/233/236/350/260/203/347/274/272/345/244/261.md +42 -0
- package/vendor/BadCase/rn/cases/KI-015-reanimated/350/277/220/350/241/214/346/227/266/346/236/220/346/236/204/345/264/251/346/272/203.md +54 -0
- package/vendor/BadCase/rn/cases/KI-016-fs/346/226/207/344/273/266/350/257/273/345/217/226/347/274/226/347/240/201.md +58 -0
- package/vendor/BadCase/rn/cases/KI-017-blob-util/345/217/202/346/225/260/347/274/226/347/240/201/351/224/231/350/257/257.md +39 -0
- package/vendor/BadCase/rn/cases/KI-018-modal/345/274/271/347/252/227/351/227/252/347/203/201.md +53 -0
- package/vendor/BadCase/rn/cases/KI-019-code-push/351/207/215/345/220/257/351/200/273/350/276/221/345/244/261/346/225/210.md +79 -0
- package/vendor/BadCase/rn/cases/KI-020-netinfo/346/225/217/346/204/237/344/277/241/346/201/257/346/263/204/351/234/262.md +60 -0
- package/vendor/BadCase/rn/cases/KI-021-video/346/234/254/345/234/260/350/247/206/351/242/221/346/222/255/346/224/276/345/274/202/345/270/270.md +79 -0
- package/vendor/BadCase/rn/cases/KI-022-audio-recorder-player/346/236/232/344/270/276/347/274/272/345/244/261.md +38 -0
- package/vendor/BadCase/rn/cases/KI-023-svg/346/270/220/345/217/230/347/273/247/346/211/277/345/244/261/346/225/210.md +62 -0
- package/vendor/BadCase/rn/generalization-log.md +55 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-SmartRefreshLayout-32.json +328 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-SmartRefreshLayout-32.md +382 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-amap-geolocation-27.json +1351 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-amap-geolocation-27.md +1176 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-audio-recorder-player-22.json +538 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-audio-recorder-player-22.md +1488 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-blob-util-23.json +211 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-blob-util-23.md +35 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-code-push-17.json +2048 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-code-push-17.md +3866 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-fast-image-102.json +198 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-fast-image-102.md +40 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-fs-38.json +751 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-fs-38.md +883 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-geolocation-24.json +1544 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-geolocation-24.md +2598 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-modal-20.json +246 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-modal-20.md +554 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-netinfo-31.json +211 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-netinfo-31.md +54 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-orientation-locker-45.json +1626 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-orientation-locker-45.md +2213 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-orientation-locker-51.json +208 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-orientation-locker-51.md +77 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-pager-view-32.json +377 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-pager-view-32.md +174 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-qr-decode-image-camera-37.json +232 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-qr-decode-image-camera-37.md +194 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-reanimated-82.json +198 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-reanimated-82.md +67 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-screens-87.json +198 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-screens-87.md +38 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-screens-93.json +208 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-screens-93.md +34 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-spring-scrollview-38.json +222 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-spring-scrollview-38.md +56 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-svg-117.json +463 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-svg-117.md +383 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-video-66.json +464 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-video-66.md +565 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-webview-112.json +198 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-webview-112.md +47 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-webview-121.json +232 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-webview-121.md +422 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-wechat-lib-15.json +295 -0
- package/vendor/BadCase/rn/pr-info/rntpc_react-native-wechat-lib-15.md +1038 -0
- package/vendor/BadCase/rn/rules/R-01-/345/205/250/345/261/217/347/252/227/345/217/243/347/212/266/346/200/201/347/256/241/347/220/206/345/256/214/346/225/264/346/200/247.md +20 -0
- package/vendor/BadCase/rn/rules/R-02-/350/265/204/346/272/220URI/345/275/242/346/200/201/345/210/206/346/224/257/350/246/206/347/233/226.md +21 -0
- package/vendor/BadCase/rn/rules/R-03-/351/231/204/345/261/236/346/223/215/344/275/234/345/244/261/350/264/245/351/230/273/346/226/255/344/270/273/346/265/201/347/250/213.md +20 -0
- package/vendor/BadCase/rn/rules/R-04-/345/274/202/346/255/245/345/233/236/350/260/203/346/263/250/345/206/214/346/227/266/345/272/217.md +20 -0
- package/vendor/BadCase/rn/rules/R-05-/346/250/241/345/235/227/345/257/274/345/205/245/350/267/257/345/276/204/350/247/204/350/214/203.md +19 -0
- package/vendor/BadCase/rn/rules/R-06-/344/274/240/346/204/237/345/231/250/347/241/254/344/273/266/346/235/203/351/231/220/346/214/211/351/234/200/350/216/267/345/217/226.md +21 -0
- package/vendor/BadCase/rn/rules/R-07-/346/231/272/350/203/275/346/214/207/351/222/210/347/224/237/345/221/275/345/221/250/346/234/237/347/256/241/347/220/206.md +20 -0
- package/vendor/BadCase/rn/rules/R-08-/346/211/213/345/212/277/344/272/213/344/273/266/346/263/250/345/206/214/344/270/216/345/206/262/347/252/201/345/244/204/347/220/206.md +22 -0
- package/vendor/BadCase/rn/rules/R-09-/346/250/252/347/253/226/345/261/217/345/244/232/345/275/242/346/200/201/345/270/203/345/261/200/351/200/202/351/205/215.md +20 -0
- package/vendor/BadCase/rn/rules/R-10-/346/267/261/350/211/262/346/250/241/345/274/217/344/270/273/351/242/230/351/242/234/350/211/262/351/200/202/351/205/215.md +19 -0
- package/vendor/BadCase/rn/rules/R-11-/346/216/245/345/217/243/345/233/236/350/260/203/345/256/236/347/216/260/345/256/214/346/225/264/346/200/247.md +20 -0
- package/vendor/BadCase/rn/rules/R-12-/345/216/237/347/224/237/350/277/220/350/241/214/346/227/266/350/265/204/346/272/220/346/236/220/346/236/204/346/227/266/345/272/217.md +20 -0
- package/vendor/BadCase/rn/rules/R-13-/346/226/207/344/273/266/346/225/260/346/215/256/347/274/226/347/240/201/344/270/216/346/240/274/345/274/217/345/205/274/345/256/271.md +21 -0
- package/vendor/BadCase/rn/rules/R-14-/345/212/250/347/224/273/345/210/235/345/247/213/345/214/226/346/227/266/345/272/217/344/270/216/347/212/266/346/200/201/345/220/214/346/255/245.md +20 -0
- package/vendor/BadCase/rn/rules/R-15-/347/212/266/346/200/201/346/214/201/344/271/205/345/214/226/344/270/216/351/207/215/345/220/257/351/200/273/350/276/221/344/270/200/350/207/264/346/200/247.md +20 -0
- package/vendor/BadCase/rn/rules/R-16-/346/225/217/346/204/237/344/277/241/346/201/257/346/227/245/345/277/227/346/263/204/351/234/262.md +19 -0
- package/vendor/BadCase/rn/rules/R-17-/345/252/222/344/275/223/350/265/204/346/272/220/347/224/237/345/221/275/345/221/250/346/234/237/344/270/216/351/224/231/350/257/257/345/244/204/347/220/206.md +21 -0
- package/vendor/BadCase/rn/rules/R-18-/350/203/275/345/212/233/346/236/232/344/270/276/351/205/215/347/275/256/345/256/214/346/225/264/346/200/247.md +19 -0
- package/vendor/BadCase/rn/rules/R-19-/345/233/276/345/275/242/346/270/262/346/237/223/345/261/236/346/200/247/347/273/247/346/211/277/344/270/216/351/207/215/347/275/256.md +19 -0
- package/vendor/MCP/README.md +490 -0
- package/vendor/MCP/config.json +29 -0
- package/vendor/MCP/package.json +23 -0
- package/vendor/MCP/scripts/analyze-demo-coverage.cjs +1203 -0
- package/vendor/MCP/scripts/analyze-xts-coverage.cjs +1245 -0
- package/vendor/MCP/scripts/deveco_docs.js +247 -0
- package/vendor/MCP/scripts/extract-interfaces.cjs +1487 -0
- package/vendor/MCP/scripts/flutter-analyze-demo-coverage.cjs +666 -0
- package/vendor/MCP/scripts/flutter-analyze-xts-coverage.cjs +684 -0
- package/vendor/MCP/scripts/flutter-extract-interfaces.cjs +1251 -0
- package/vendor/MCP/scripts/flutter-render-spec-doc.cjs +351 -0
- package/vendor/MCP/scripts/render-spec-doc.cjs +347 -0
- package/vendor/MCP/scripts/rn-analyze-demo-coverage.cjs +645 -0
- package/vendor/MCP/scripts/rn-analyze-test-coverage.cjs +614 -0
- package/vendor/MCP/scripts/rn-extract-interfaces.cjs +1462 -0
- package/vendor/MCP/scripts/rn-render-spec-doc.cjs +327 -0
- package/vendor/MCP/scripts/rn-scan-exports.cjs +1336 -0
- package/vendor/MCP/src/client/MCPClientPool.js +220 -0
- package/vendor/MCP/src/config/ConfigLoader.js +189 -0
- package/vendor/MCP/src/executor/ScriptExecutor.js +110 -0
- package/vendor/MCP/src/gateway/Gateway.js +451 -0
- package/vendor/MCP/src/index.js +87 -0
- package/vendor/MCP/src/library/KBToolProvider.js +229 -0
- package/vendor/MCP/src/library/logger.js +60 -0
- package/vendor/MCP/src/registry/ScriptRegistry.js +238 -0
- package/vendor/MCP/src/registry/ToolRegistry.js +111 -0
- package/vendor/MCP/src/types.js +115 -0
- package/vendor/Server/CLI/cli.js +3 -3
- package/vendor/Server/Routes/server.js +3 -3
- package/vendor/Server/Skills/arkts-library-test-coverage-check/references/MCP_TOOL_USAGE.md +4 -2
- package/vendor/Server/Skills/arkts-library-xts-coverage/SKILL.md +3 -3
- package/vendor/Server/Skills/knowledge-import/SKILL.md +1 -1
- package/vendor/Server/Skills/knowledge-import/references/MCP_TOOL_USAGE.md +12 -4
- package/vendor/Server/Skills/ohos-lib-pr-push/SKILL.md +5 -4
- package/vendor/Server/Skills/rn-library-issue-generalizer/SKILL.md +2 -2
- package/vendor/Server/Skills/rn-library-known-issue-check/SKILL.md +2 -2
- package/vendor/Server/Skills/rnoh-lib-demo-coverage/SKILL.md +1 -2
- package/vendor/Server/Skills/rnoh-lib-test-align/references/port-test-demo-guide.md +1 -1
- package/vendor/Server/Skills/rnoh-lib-xts-coverage/SKILL.md +1 -2
- package/vendor/Server/package.json +5 -1
- package/vendor/VERSION +3 -3
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
## TurboModule 库(非 Fabric 组件)的测试策略差异
|
|
2
|
+
|
|
3
|
+
### 问题现象
|
|
4
|
+
NetInfo 是一个 TurboModule 库,不是 Fabric 组件库。按照 Fabric 组件库的测试策略编写 jest 单元测试时,会出现 mock 策略不匹配的问题:不需要 mock `codegenNativeComponent` 生成的 Fabric 原生组件,但需要 mock `NativeEventEmitter` 和 `NativeModules`(从 `react-native` 导入)。
|
|
5
|
+
|
|
6
|
+
### 解决方案
|
|
7
|
+
TurboModule 库的 jest mock 需求与 Fabric 组件库不同:
|
|
8
|
+
- **不需要** mock `codegenNativeComponent` 生成的 Fabric 原生组件
|
|
9
|
+
- **需要** mock `NativeEventEmitter` 和 `NativeModules`(从 `react-native` 导入)
|
|
10
|
+
- **关键**:`NativeEventEmitter.addListener` 必须返回 `{ remove: () => void }` 对象(模拟 RN 的 `NativeEventSubscription`),而非 Node EventEmitter 的默认返回值。否则 `State.tearDown()` 中的 `this._nativeEventSubscription.remove()` 会报 `TypeError: ...remove is not a function`
|
|
11
|
+
|
|
12
|
+
mock 实现示例:
|
|
13
|
+
```javascript
|
|
14
|
+
// __mocks__/react-native.js
|
|
15
|
+
const { EventEmitter } = require('events');
|
|
16
|
+
class MockNativeEventEmitter extends EventEmitter {
|
|
17
|
+
addListener(eventName, handler) {
|
|
18
|
+
const listener = super.addListener(eventName, handler);
|
|
19
|
+
return { remove: () => super.removeListener(eventName, handler) };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 结果
|
|
25
|
+
TurboModule 库测试通过。这是所有 TurboModule 库通用的 mock 需求:`NativeEventEmitter`(返回 `{remove}` 对象的 `addListener`)、`NativeModules`、`Platform`。
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 导入路径从相对路径到包名的转换
|
|
30
|
+
|
|
31
|
+
### 问题现象
|
|
32
|
+
上游 demo 使用相对路径 `'../src'` 和 `'../../src'` 引用库源码。移植到 example 工程后,这些路径会解析到错误的目录(`example/src/` 自身而非库根目录的 `src/`),导致编译错误或导入了错误的模块。
|
|
33
|
+
|
|
34
|
+
### 解决方案
|
|
35
|
+
将所有导入路径改为包名 `'@react-native-ohos/netinfo'`,让 Metro 的 resolver 正确重定向。批量定位方法:`grep -rl "'../src'" example/src/`
|
|
36
|
+
|
|
37
|
+
### 结果
|
|
38
|
+
所有导入路径正确解析到库源码,编译通过。
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## metro.config.js React 单例保护(tgz 包场景)
|
|
43
|
+
|
|
44
|
+
### 问题现象
|
|
45
|
+
即使通过 tgz 包安装(非 symlink 到库根目录),当 `watchFolders` 包含库根目录时,Metro 的 `nodeModulesPaths` 会包含库根目录的 `node_modules/react`,可能在不同导入上下文中解析到不同的 React 实例,导致 hooks 失效崩溃。
|
|
46
|
+
|
|
47
|
+
### 解决方案
|
|
48
|
+
在 `metro.config.js` 中包装 RNOH 的 `resolveRequest`:
|
|
49
|
+
1. 先获取 RNOH 的 `resolveRequest` 引用
|
|
50
|
+
2. 在包装函数中拦截裸 `react` 导入,强制解析到 example 的 `node_modules/react`
|
|
51
|
+
3. 其余导入委托给 RNOH 的 resolver
|
|
52
|
+
|
|
53
|
+
**关键约束**:不能直接设置 `resolveRequest` 覆盖 RNOH 的 harmony 解析器——这会导致 `.harmony.js` 平台文件解析全部失效。必须**包装** RNOH 的 `resolveRequest`,只拦截裸 `react` 导入。
|
|
54
|
+
|
|
55
|
+
验证方法:`grep -oE '(node_modules|\.\./node_modules)/react/index\.js' bundle.harmony.js | sort | uniq -c`,应只有 1 个路径。
|
|
56
|
+
|
|
57
|
+
### 结果
|
|
58
|
+
React 单例保证,hooks 正常工作。
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## useNetInfoInstance 的 configuration 参数无限重渲染
|
|
63
|
+
|
|
64
|
+
### 问题现象
|
|
65
|
+
在测试或 demo 中向 `useNetInfoInstance` 传入内联 configuration 对象(如 `<Comp config={{reachabilityShouldRun: () => true}} />`)时,每次渲染都会创建新对象引用,触发 `useEffect` 重新执行,调用 `setNetworkInfoManager(state)` 触发再次渲染,形成无限循环导致 Jest OOM。
|
|
66
|
+
|
|
67
|
+
### 解决方案
|
|
68
|
+
这是上游设计限制。`useNetInfoInstance` 的 `useEffect` 依赖 `[isPaused, configuration]`,内联对象引用每次都不同。测试中需避免传入内联 configuration,应使用 `useMemo` 或将配置定义为模块级常量。
|
|
69
|
+
|
|
70
|
+
### 结果
|
|
71
|
+
避免无限循环,测试正常运行。
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Jest 测试踩坑:mockReset 后 getCurrentState 返回 undefined
|
|
76
|
+
|
|
77
|
+
### 问题现象
|
|
78
|
+
`Cannot read properties of undefined (reading 'isInternetReachable')` 错误。
|
|
79
|
+
|
|
80
|
+
### 解决方案
|
|
81
|
+
`beforeEach` 中 `mockReset()` 后 `getCurrentState` 返回 `undefined`,`configure()` 创建新 State 时构造函数调用 `_fetchCurrentState()` 拿到 undefined。需在 `beforeEach` 中 `mockReset()` 后立即 `mockResolvedValue(defaultState)`。
|
|
82
|
+
|
|
83
|
+
### 结果
|
|
84
|
+
State 初始化正常,不再报 undefined 错误。
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Jest 测试踩坑:fetch() 无参数时 getCurrentState 未被调用
|
|
89
|
+
|
|
90
|
+
### 问题现象
|
|
91
|
+
测试中验证 `fetch()` 调用了 `getCurrentState`,但断言失败——`getCurrentState` 未被调用。
|
|
92
|
+
|
|
93
|
+
### 解决方案
|
|
94
|
+
`latest()` 方法有缓存时直接返回 `Promise.resolve(this._latestState)`,不调用 `getCurrentState`。测试中需要先 emit 事件设置缓存,再验证 `fetch()` 返回缓存值,而非验证 `getCurrentState` 被调用。
|
|
95
|
+
|
|
96
|
+
### 结果
|
|
97
|
+
测试断言正确反映实际行为。
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## TurboModule 库的 jest 配置模板
|
|
102
|
+
|
|
103
|
+
### 问题现象
|
|
104
|
+
TurboModule 库同时有 `src/__tests__/` 和 `example/` 目录,jest 配置需要正确处理模块解析和测试文件范围。
|
|
105
|
+
|
|
106
|
+
### 解决方案
|
|
107
|
+
`__mocks__/react-native.js` 中需要提供 `NativeEventEmitter`(返回 `{remove}` 对象的 `addListener`)、`NativeModules`、`Platform`。这是所有 TurboModule 库通用的 mock 需求。
|
|
108
|
+
|
|
109
|
+
库根目录 `jest.config.js` 模板要点:
|
|
110
|
+
- `moduleNameMapper` 统一 `react-native` → mock 和 `react` → 单一路径
|
|
111
|
+
- `testMatch` 精确限定到 `src/__tests__/*.spec.ts`,避免扫描 `example/harmony/oh_modules`
|
|
112
|
+
- `tsconfig.jest.json` 不继承 `@react-native/typescript-config`
|
|
113
|
+
|
|
114
|
+
### 结果
|
|
115
|
+
jest 配置正确,测试扫描范围精确,模块解析统一。
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 测试覆盖率扫描方法(TurboModule 库)
|
|
120
|
+
|
|
121
|
+
### 问题现象
|
|
122
|
+
对于 NetInfo 这种非组件库(TurboModule 库),覆盖率维度与 Fabric 组件库不同,需要不同的扫描方法。
|
|
123
|
+
|
|
124
|
+
### 解决方案
|
|
125
|
+
从 TurboModule Spec 文件(`*Native*.ts`)提取方法列表,从 `src/index.ts` 提取公开导出的函数/hook,然后对照测试文件搜索每个 API 的使用情况。
|
|
126
|
+
|
|
127
|
+
TurboModule 库的覆盖率维度包括:
|
|
128
|
+
- **API 覆盖**:TurboModule spec 中定义的方法
|
|
129
|
+
- **状态类型覆盖**:如网络状态 `cellular`、`wifi`、`none`、`unknown` 等各类型
|
|
130
|
+
- **配置选项覆盖**:如 `useNetInfoInstance` 的 `configuration` 参数各选项
|
|
131
|
+
|
|
132
|
+
### 结果
|
|
133
|
+
覆盖率报告全面覆盖 TurboModule 库的所有维度。
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
## HarmonyOS 签名配置与已签名 HAP 构建经验
|
|
2
|
+
|
|
3
|
+
> 来源:rntpc_react-native-netinfo (0.84) signingConfigs 配置与已签名 HAP 构建任务
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
### 问题现象一:devecocli signature generate 无法自动生成签名
|
|
8
|
+
|
|
9
|
+
执行 `devecocli signature generate --force` 时报错:
|
|
10
|
+
```
|
|
11
|
+
Failed to automatically generate signatures. Run devecocli auth login to sign in.
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
影响场景:CI/CD 环境、无华为账号的开发环境、自动化脚本。
|
|
15
|
+
|
|
16
|
+
### 解决方案
|
|
17
|
+
|
|
18
|
+
`devecocli signature generate` 需要先登录华为账号(`devecocli auth login`)。未登录时不可用。
|
|
19
|
+
|
|
20
|
+
替代方案:手动配置 `build-profile.json5` 中的 `signingConfigs`,复用本机已有的 DevEco Studio 签名材料。查找流程:
|
|
21
|
+
1. 检查 `~/.ohos/config/` 目录中是否有匹配当前 bundleName 的签名材料
|
|
22
|
+
2. 在其他成功构建的项目中查找相同 bundleName 的 build-profile.json5 配置
|
|
23
|
+
3. 直接复用该配置中的 signingConfigs
|
|
24
|
+
|
|
25
|
+
### 结果
|
|
26
|
+
|
|
27
|
+
成功通过手动复用签名材料完成签名配置,无需华为账号登录。
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
### 问题现象二:签名材料的复用约束不明确
|
|
32
|
+
|
|
33
|
+
不同项目间复用 HarmonyOS 签名材料(.p12/.cer/.p7b)时,不清楚哪些可以复用、哪些不能。
|
|
34
|
+
|
|
35
|
+
### 解决方案
|
|
36
|
+
|
|
37
|
+
签名材料复用关键约束:
|
|
38
|
+
|
|
39
|
+
| 约束维度 | 说明 |
|
|
40
|
+
|---------|------|
|
|
41
|
+
| **bundleName** | .p7b Profile 文件与 bundleName 绑定,不同 bundleName 不能复用同一 .p7b |
|
|
42
|
+
| **机器绑定** | DevEco Studio 生成的加密密码(storePassword/keyPassword)与机器绑定,同一机器不同项目可复用 |
|
|
43
|
+
| **runtimeOS** | type 必须匹配(HarmonyOS vs OpenHarmony) |
|
|
44
|
+
|
|
45
|
+
实践验证:bundleName 相同的项目可成功复用签名材料(包括加密密码),在 `SignHap` 步骤一次性通过。
|
|
46
|
+
|
|
47
|
+
### 结果
|
|
48
|
+
|
|
49
|
+
明确了签名材料复用规则,bundleName 相同的项目间可安全复用全部签名材料。
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### 问题现象三:signingConfigs 配置结构参考
|
|
54
|
+
|
|
55
|
+
需要手动填充 build-profile.json5 中空的 signingConfigs 数组。
|
|
56
|
+
|
|
57
|
+
### 解决方案
|
|
58
|
+
|
|
59
|
+
signingConfigs 配置结构:
|
|
60
|
+
|
|
61
|
+
```json5
|
|
62
|
+
signingConfigs: [
|
|
63
|
+
{
|
|
64
|
+
name: 'default', // 必须与 products[].signingConfig 一致
|
|
65
|
+
type: 'HarmonyOS', // 或 'OpenHarmony'
|
|
66
|
+
material: {
|
|
67
|
+
storeFile: '...p12', // 密钥库文件
|
|
68
|
+
storePassword: '...', // 密钥库密码(明文或DevEco加密格式)
|
|
69
|
+
keyAlias: 'debugKey', // 密钥别名
|
|
70
|
+
keyPassword: '...', // 密钥密码(明文或DevEco加密格式)
|
|
71
|
+
certpath: '...cer', // 证书文件
|
|
72
|
+
profile: '...p7b', // Profile 文件(bundleName 绑定)
|
|
73
|
+
signAlg: 'SHA256withECDSA', // 签名算法
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
加密密码格式识别:DevEco Studio 生成的加密密码以 `0000001B` 开头,十六进制格式。明文密码也可直接使用。两种格式在 build-profile.json5 中都有效。
|
|
80
|
+
|
|
81
|
+
### 结果
|
|
82
|
+
|
|
83
|
+
成功填充 signingConfigs 数组,name 与 products[].signingConfig 一致,构建时签名步骤通过。
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
### 问题现象四:如何验证已签名 HAP 构建成功
|
|
88
|
+
|
|
89
|
+
构建完成后不确定签名是否成功。
|
|
90
|
+
|
|
91
|
+
### 解决方案
|
|
92
|
+
|
|
93
|
+
已签名 HAP 位于:
|
|
94
|
+
```
|
|
95
|
+
entry/build/default/outputs/default/entry-default-signed.hap
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
与未签名的对比:
|
|
99
|
+
- `entry-default-unsigned.hap` — 打包后未签名
|
|
100
|
+
- `entry-default-signed.hap` — 签名后(比未签名大约 650KB,为签名块)
|
|
101
|
+
|
|
102
|
+
构建日志中 `SignHap` 步骤成功即表示签名完成。确认文件大小 > 0。
|
|
103
|
+
|
|
104
|
+
### 结果
|
|
105
|
+
|
|
106
|
+
通过检查 entry-default-signed.hap 文件存在且大小 > 0,确认签名构建成功。
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
### 问题现象五:MCP build_project 工具构建超时
|
|
111
|
+
|
|
112
|
+
调用 `deveco-mcp_build_project` 时超时(Request timed out),首次构建(含 clean)耗时较长超过 MCP 工具默认超时时间。
|
|
113
|
+
|
|
114
|
+
### 解决方案
|
|
115
|
+
|
|
116
|
+
改为直接使用 hvigorw 命令行构建,设置 300s 超时:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
/Applications/DevEco-Studio.app/contents/tools/node/bin/node \
|
|
120
|
+
/Applications/DevEco-Studio.app/contents/tools/hvigor/bin/hvigorw.js \
|
|
121
|
+
--mode module -p module=entry@default assembleHap -p buildMode=debug --no-daemon
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
注意:`hvigorw.js` 是 JS 文件,必须用 node 执行,不能直接作为 shell 脚本运行。
|
|
125
|
+
|
|
126
|
+
### 结果
|
|
127
|
+
|
|
128
|
+
通过 hvigorw 命令行直接构建成功绕过 MCP 工具超时限制,完成首次 clean build。对于首次 clean build 或大型项目,优先使用 hvigorw 命令行直接构建。
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# RNOH 应用部署验证与 hilog 日志分析经验
|
|
2
|
+
|
|
3
|
+
## RNOH 应用 Error 级日志噪音白名单
|
|
4
|
+
|
|
5
|
+
### 问题现象
|
|
6
|
+
RNOH (React Native OpenHarmony) 应用在正常启动运行时,会产生大量 Error 级别的 hilog 日志。仅凭 Error 级日志数量判断应用状态会导致误判,将框架层面的预期行为误读为应用崩溃。
|
|
7
|
+
|
|
8
|
+
### 解决方案
|
|
9
|
+
以下 Tag 的 Error 日志均为非致命的框架噪音,可列入白名单:
|
|
10
|
+
|
|
11
|
+
| 来源 Tag | 日志内容 | 实际含义 |
|
|
12
|
+
|---------|---------|---------|
|
|
13
|
+
| `RNOH_CPP` | `Couldn't provide turbo module "RedBox"/"SoundManager"/"IntentAndroid"/"FrameRateLogger"` | 应用未集成这些可选 TurboModule,RNOH 尝试加载已注册名称但找不到。框架设计行为,不影响功能。 |
|
|
14
|
+
| `RNOH_ARK` (DisplayMetricsManager) | `Failed to get customDensity` / `Failed to get maxFontScale` / `Failed to get window decor height` | 设备不支持该能力查询,降级处理。 |
|
|
15
|
+
| `RNOH_ARK` (DevMenu) | `Shake to open Dev Menu is disabled` + `permission.ACCELEROMETER` 缺失 | 摇一摇 DevMenu 被禁用,需在 module.json5 添加加速度计权限才能用,但不影响应用运行。 |
|
|
16
|
+
| `JSPackagerClient` / `ArkCompiler` | `Websocket connection failed` / `Decode failed, client websocket disconnect` | debug 构建尝试连接 Metro bundler 但未运行。应用使用预打包 JS 继续。 |
|
|
17
|
+
| `NETSTACK` | `lws_service stop`(重复) / `CURLcode result 7` / `epoll wait event 0 err: 111` | 对于 netinfo 等网络探测应用,这些是正常工作行为(检测网络是否可用),而非 Bug。 |
|
|
18
|
+
| `WMSDecor` | `GetDecorVisible: device not support` | 设备不支持窗口装饰功能。 |
|
|
19
|
+
| `Text` / `FontConfig` | `GetFileData: Path or realPath is nullptr` / `CheckConfigFile: Null data` | 字体配置缺失,使用默认字体。 |
|
|
20
|
+
| `PARAM_WATCHER` | `Failed to add watcher for persist.rosen.animationtrace.enabled` | 系统参数监听失败,系统级。 |
|
|
21
|
+
|
|
22
|
+
### 结果
|
|
23
|
+
在自动化部署验证流程中,将上述噪音日志 Tag 列入白名单可避免误报。NETSTACK 类日志需结合应用类型判断——网络探测类应用中这些是正常行为。
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 判断 RNOH 应用是否真正崩溃的可靠方法
|
|
28
|
+
|
|
29
|
+
### 问题现象
|
|
30
|
+
仅凭 Error 级日志数量无法准确判断应用是否真正崩溃,需要多维度综合判断。
|
|
31
|
+
|
|
32
|
+
### 解决方案
|
|
33
|
+
不要仅凭 Error 级日志数量判断应用状态,应综合以下 4 个维度:
|
|
34
|
+
|
|
35
|
+
1. **Level F (Fatal) 日志**:有无 Fatal 级日志(最可靠指标)
|
|
36
|
+
2. **faultlog 崩溃日志**:使用 `get_hilog_or_faultlog_recent` 设置 `is_crash_log=true` 查询有无崩溃记录
|
|
37
|
+
3. **UI 树验证**:使用 `get_app_ui_tree`(full 模式)获取 UI 树,grep 搜索目标组件关键词,确认应用 UI 是否正常渲染(进程存活且功能正常的最直接证据)
|
|
38
|
+
4. **进程存活**:`aa start` 返回 `start ability successfully` 后 UI 树能成功 dump,说明进程未崩溃退出
|
|
39
|
+
|
|
40
|
+
### 结果
|
|
41
|
+
当 3 个维度(无 Fatal、无 faultlog、UI 正常渲染目标组件)全部通过时,Error 日志可全部归类为框架噪音,结论为"应用正常"。此方法在实际部署验证任务中验证有效。
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## hdc snapshot_display 截图命令后缀限制
|
|
46
|
+
|
|
47
|
+
### 问题现象
|
|
48
|
+
使用 `hdc shell snapshot_display -f /data/local/tmp/xxx.png` 截图时报错:`error: fileName /data/local/tmp/xxx.png invalid, suffix must be .jpeg`。
|
|
49
|
+
|
|
50
|
+
### 解决方案
|
|
51
|
+
`snapshot_display` 命令只支持 `.jpeg` 后缀,不支持 `.png`。必须使用 `.jpeg` 扩展名:
|
|
52
|
+
```bash
|
|
53
|
+
hdc shell snapshot_display -f /data/local/tmp/screenshot.jpeg
|
|
54
|
+
hdc file recv /data/local/tmp/screenshot.jpeg ./
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 结果
|
|
58
|
+
改用 `.jpeg` 后缀后截图成功。后续截图操作统一使用 `.jpeg` 后缀,避免 `snapshot_display` 报错。
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## MCP perform_ui_action screenshot 多设备环境 hvd 参数问题
|
|
63
|
+
|
|
64
|
+
### 问题现象
|
|
65
|
+
当环境中存在多个可用设备(包括未运行的模拟器)时,MCP 工具 `perform_ui_action` 的 screenshot 操作会要求通过 `hvd` 参数指定目标设备,即使只有一个真机已连接。
|
|
66
|
+
|
|
67
|
+
### 解决方案
|
|
68
|
+
多设备环境下可改用 `hdc` 命令行直接截图作为替代方案:
|
|
69
|
+
```bash
|
|
70
|
+
hdc shell snapshot_display -f /data/local/tmp/screenshot.jpeg
|
|
71
|
+
hdc file recv /data/local/tmp/screenshot.jpeg ./
|
|
72
|
+
```
|
|
73
|
+
若必须使用 MCP 工具,则需传入 `hvd` 参数明确指定目标设备 ID。
|
|
74
|
+
|
|
75
|
+
### 结果
|
|
76
|
+
使用 hdc 命令行绕过 MCP 工具的多设备限制,成功完成截图。在多设备环境中推荐优先使用 hdc 命令行。
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## RNOH 示例项目 Bundle Name 复用的部署策略
|
|
81
|
+
|
|
82
|
+
### 问题现象
|
|
83
|
+
RNOH 示例项目(netinfo、pager-view 等)共用 bundle name `com.harmony.wechat.lib.demo`。直接部署新应用而不卸载旧应用,会导致旧应用残留,UI 树内容不匹配,无法确认是否为新部署的应用。
|
|
84
|
+
|
|
85
|
+
### 解决方案
|
|
86
|
+
部署新应用前必须先卸载旧应用:
|
|
87
|
+
```bash
|
|
88
|
+
hdc shell bm uninstall -n com.harmony.wechat.lib.demo
|
|
89
|
+
hdc install <new-hap-path>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 结果
|
|
93
|
+
先卸载再安装后,UI 树内容与新部署应用匹配,可可靠确认应用正常启动。共用 bundle name 的项目必须遵循此策略。
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## RNOH 应用部署验证标准流程
|
|
98
|
+
|
|
99
|
+
### 问题现象
|
|
100
|
+
RNOH 应用部署到设备后缺乏标准化的验证流程,容易遗漏关键检查步骤导致误判应用状态。
|
|
101
|
+
|
|
102
|
+
### 解决方案
|
|
103
|
+
推荐以下 8 步标准部署验证流程:
|
|
104
|
+
|
|
105
|
+
1. **清除残留**:`hdc shell bm uninstall -n <bundleName>`(清除旧应用残留)
|
|
106
|
+
2. **安装 HAP**:`hdc install <hap-path>`(安装新 HAP)
|
|
107
|
+
3. **清日志缓冲**:`hdc shell hilog -r`(清除历史日志干扰)
|
|
108
|
+
4. **启动应用**:`hdc shell aa start -a EntryAbility -b <bundleName>`(启动 Ability)
|
|
109
|
+
5. **等待渲染**:等待 8-10 秒(确保 UI 完成渲染)
|
|
110
|
+
6. **UI 树验证**:调用 `get_app_ui_tree`(full 模式)获取 UI 树 JSON,grep 搜索目标组件关键词(如 `netinfo/NetInfo/RNCNetInfo`),确认应用正常启动且非设备残留的其他应用
|
|
111
|
+
7. **日志检查**:调用 `get_hilog_or_faultlog_recent` 分别按 `level=F`、`is_crash_log=true`、`level=E` 过滤
|
|
112
|
+
8. **日志分析**:分类分析 Error 日志,排除噪音白名单后确认无致命错误
|
|
113
|
+
|
|
114
|
+
### 结果
|
|
115
|
+
此流程在 rntpc_react-native-netinfo (0.84) 部署验证任务中验证有效,8 步全部通过后可确认应用正常启动无崩溃。流程可复用于其他 RNOH 应用的部署验证。
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# 知识导入SKILL优化经验
|
|
2
|
+
|
|
3
|
+
## 一、SKILL修改过度推断
|
|
4
|
+
|
|
5
|
+
### 问题现象
|
|
6
|
+
知识导入过程中,AI 基于经验文档的主题关键词(如"测试""Hypium")与 SKILL description 的语义重叠,推断关联了未在经验文档中显式提及的 SKILL(TPCXTSCodeSkill、TPCXTSExecutionSkill)并进行修改。实际经验文档只记录了通用技术知识,未指出任何 SKILL 的流程缺陷。
|
|
7
|
+
|
|
8
|
+
### 解决方案
|
|
9
|
+
收紧 SKILL 类分类标准,要求两个条件同时满足才算 SKILL 类:1) 经验显式提及 SKILL 名称或步骤名;2) 内容指出该流程环节存在具体缺陷。禁止仅凭主题关键词重叠推断关联。SKILL 定位指南中删除"关键词重叠匹配"规则,改为仅支持"精确名称匹配"和"步骤名匹配"。
|
|
10
|
+
|
|
11
|
+
### 结果
|
|
12
|
+
经验文档未显式提及 SKILL 时不再误修改 SKILL,所有内容归为知识类导入知识库。默认归属原则为"宁可多导入知识库,不可误修改 SKILL"。
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 二、知识库内容未结构化整理
|
|
17
|
+
|
|
18
|
+
### 问题现象
|
|
19
|
+
导入知识库时,将原始经验文档的 Markdown 内容原封不动作为 content 参数传入 kb_add_document,未经过任何结构化整理。导致知识库中存储的是原始文档而非可高效检索复用的经验条目。
|
|
20
|
+
|
|
21
|
+
### 解决方案
|
|
22
|
+
在 SKILL.md 的 Phase 3 中增加内容结构化整理要求,强制按"问题现象/解决方案/结果"三段式重组。将原始文档中的"关键发现""踩坑记录""可复用建议"拆解为独立条目,每个条目聚焦一个问题。在 MCP_TOOL_USAGE.md 中新增"知识库内容结构化格式"章节,给出标准模板。
|
|
23
|
+
|
|
24
|
+
### 结果
|
|
25
|
+
知识库中存储的是结构化的经验条目,每个条目可独立检索,问题-方案-结果关系清晰,复用效率提升。
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 三、MCP 工具可用性未前置检查
|
|
30
|
+
|
|
31
|
+
### 问题现象
|
|
32
|
+
SKILL 直接假设 kb_add_document 工具可用,未在执行前验证 MCP Gateway 是否运行、工具是否注册。当 opencode 未配置 mcp-gateway 时,到调用阶段才发现工具不可用,导致知识类导入被迫跳过。
|
|
33
|
+
|
|
34
|
+
### 解决方案
|
|
35
|
+
在 Phase 3 新增"3.0 MCP 工具可用性检查"步骤,先调用 gateway_health 和 gateway_list_tools 确认 kb_add_document 可用。在 MCP_TOOL_USAGE.md 新增"第0章 MCP Gateway 可用性验证",包含健康检查、工具列表确认、配置方法和 opencode 重启提示。
|
|
36
|
+
|
|
37
|
+
### 结果
|
|
38
|
+
工具不可用时在最早阶段发现并跳过,避免到调用阶段才失败。用户可获知明确的配置指引,快速修复后重新执行。
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## 跨循环产物复用核验的证据三角模式与汇总指标分解
|
|
2
|
+
|
|
3
|
+
### 问题现象
|
|
4
|
+
"loop N 复用 loop N-1 产物"的核验任务中存在两类陷阱:
|
|
5
|
+
1. 仅凭前序步骤报告的"成功"结论即判定通过,报告与实物可能不一致;
|
|
6
|
+
2. 任务描述中的汇总数字(如"设备端 95/95,共 154/154")在前序报告中没有直接对应的单一数字,只对总数会漏掉口径错配。
|
|
7
|
+
|
|
8
|
+
### 解决方案
|
|
9
|
+
**证据三角模式**——关键声明必须三方交叉验证:
|
|
10
|
+
1. 报告声明:读前序步骤报告结论;
|
|
11
|
+
2. 实物产物:文件存在性 + 大小 + 时间戳(如 HAR 22MB / tgz 44MB / 签名与未签名 HAP 实体文件);
|
|
12
|
+
3. 现场 git/文件查询:如 `git merge-base br_rnoh0.84 br_rnoh0.82` 实测分支血缘、直接读依赖清单文件原文、实际列目录比对测试文件清单(jest.config.js、__mocks__/、src/__tests__/、example/src/suites/ 逐一对账)。
|
|
13
|
+
|
|
14
|
+
**汇总指标分解规则**:验收标准含汇总数字时逐项拆解到报告分项对账。示例:"95/95" = 自动套件 85/85 + Hooks 探针 10/10;"154/154" = Jest 59 + 85 + 10,分解后才确认口径一致。
|
|
15
|
+
|
|
16
|
+
**自动生成产物权威级规则**:链路中自动生成的 diff/扫描件(如 rn-scan-exports.cjs 生成的 api-diff_*.md)存在已知偏差(对 Nitro HybridObject 架构,Spec 文件为 `*.nitro.ts` 而非 `Native*.ts` 命名,扫描器规则不覆盖,导致"TurboModule Spec 变更:无"误判)。若后续人工分析报告已修正,验收一律以修正结论件为准,自动件仅作参考——否则会拿错误基线对账。
|
|
17
|
+
|
|
18
|
+
### 结果
|
|
19
|
+
react-native-mmkv loop0 产物核验 5/5 通过:分支血缘(merge-base = 预期 commit c047ada)、编译产物、依赖版本、测试产物(与报告清单一一对应)均经实物交叉验证,测试口径 59+85+10=154 分解对账一致。可复用结论:任何"loop N 复用 loop N-1 产物"的核验任务,直接套用证据三角模式与汇总指标分解规则。
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## macOS/Linux 环境替代 build.ps1 执行 devecocli build 的方法
|
|
2
|
+
|
|
3
|
+
### 问题现象
|
|
4
|
+
|
|
5
|
+
build.ps1 在 macOS 环境不可用(无 pwsh/powershell)。而构建流程强制"必须通过 build.ps1 执行"的底层原因是:直接调用 devecocli build 会导致 hvigor daemon 继承 Agent pipe 句柄不释放,造成 session 永久阻塞。
|
|
6
|
+
|
|
7
|
+
### 解决方案
|
|
8
|
+
|
|
9
|
+
等效替代方案:**bash 重定向到日志文件 + timeout 参数**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
devecocli build --modules entry > build.log 2>&1
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
原理:daemon 继承的是文件句柄而非管道句柄,同样规避了 pipe 句柄继承导致的 session 阻塞,与 build.ps1 的防护机制等价。构建错误从 build.log 日志文件中读取。
|
|
16
|
+
|
|
17
|
+
### 结果
|
|
18
|
+
|
|
19
|
+
macOS 环境下实际执行 3 轮编译均无 session 阻塞,效果与 build.ps1 等同。macOS/Linux 环境执行鸿蒙编译验证可直接采用此方案。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# macOS 下 diff -q 报 "illegal option" 的解决方法
|
|
2
|
+
|
|
3
|
+
### 问题现象
|
|
4
|
+
|
|
5
|
+
在 macOS(zsh/BSD 工具链)下执行 `diff -q` 组合用法时报 "illegal option" 错误,导致命令链中断。原因是误用了 GNU diff 的语法组合,macOS 自带的 BSD diff 不支持该用法。
|
|
6
|
+
|
|
7
|
+
### 解决方案
|
|
8
|
+
|
|
9
|
+
改用以下任一方式:
|
|
10
|
+
- 直接用 `diff` 全量比对(观察输出差异)
|
|
11
|
+
- 用 `cmp -s file1 file2` 做静默比对(通过退出码判断是否相同,适合脚本)
|
|
12
|
+
|
|
13
|
+
### 结果
|
|
14
|
+
|
|
15
|
+
命令链不再中断。macOS 环境下涉及 GNU/BSD 工具差异时,优先考虑 `cmp -s` 替代 `diff -q` 的脚本化场景用法。
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## migrate.cjs --compatible-api 版本上限陷阱与正确取值方法
|
|
2
|
+
|
|
3
|
+
### 问题现象
|
|
4
|
+
|
|
5
|
+
执行 `node migrate.cjs --compatible-api 26` 报 `未知 compatible-api 版本` 错误。根因:migrate.cjs 的 API_VERSION_MAP 存在版本上限(当前最高 24),设备 API 版本(26)超出映射表范围时直接传入即报错。而 SKILL 流程原指示"探测设备 API 版本作为 --compatible-api 传入",未考虑此上限。
|
|
6
|
+
|
|
7
|
+
### 解决方案
|
|
8
|
+
|
|
9
|
+
correct 取值流程:
|
|
10
|
+
1. `hdc shell param get const.ohos.apiversion` 获取设备 API 版本
|
|
11
|
+
2. 若设备 API 超出脚本 API_VERSION_MAP 上限,读取 `DevEco-Studio.app/Contents/sdk/default/sdk-pkg.json` 的 `apiVersion` 字段获取已安装 SDK API 版本
|
|
12
|
+
3. 取 **min(设备 API, 已安装 SDK API)** 作为 `--compatible-api`(编译面向已安装 SDK,实际以已安装 SDK API 为准)
|
|
13
|
+
4. 重跑后校验:脚本输出含 `迁移完成`,且产物 `compatibleSdkVersion ≤ 设备 API`
|
|
14
|
+
|
|
15
|
+
### 结果
|
|
16
|
+
|
|
17
|
+
以已安装 SDK API(24) 作为 compatible-api 重跑迁移成功,编译验证通过。设备 API 高于 SDK API 时必须以 SDK API 为准,不可直接传设备 API。
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## mp3agic 鸿蒙移植库源码行为缺陷与签名实测清单
|
|
2
|
+
|
|
3
|
+
### 问题现象
|
|
4
|
+
|
|
5
|
+
mp3agic 鸿蒙移植库(`.ts` 源码带 `@ts-nocheck`)存在多处与场景文档/预期不符的实际行为,按文档字面调用会运行时出错或展示错误结果。
|
|
6
|
+
|
|
7
|
+
### 解决方案(实测行为清单)
|
|
8
|
+
|
|
9
|
+
| 接口 | 实际行为(以源码为准) | Demo 处理方式 |
|
|
10
|
+
|------|----------------------|--------------|
|
|
11
|
+
| `ID3v24Tag.setGenreDescription` | 内部引用缺 `this.` 前缀(@ts-nocheck 掩盖的库缺陷),运行时抛 ReferenceError | try/catch 捕获展示 |
|
|
12
|
+
| `ID3v2ObseleteFrame.packFrame` | 无条件抛 `NotSupportedException` | try/catch 捕获展示异常名与消息,验证点标注"源码真实行为" |
|
|
13
|
+
| `unsynchroniseBuffer` | 声明返回 `number`,实际返回数组 | 按声明类型接值,`String(result)` 展示实际内容 |
|
|
14
|
+
| `BufferTools.setBit(0, 7, true)` | 返回 Int8 有符号值 `-128` 而非 `128` | 按有符号值展示 |
|
|
15
|
+
| `setChapters` / `setChapterTOC` / `getChapters` / `getChapterTOC` | 容器类型为 `JList<T>` 而非文档所写 `Array<T>` | 按 JList 构造/接值 |
|
|
16
|
+
| `BufferTools.mergeArrayBuffer` | rest 参数 `...arrays` 而非文档所写数组参数 | 调用时展开为多参数 |
|
|
17
|
+
| `ID3v2ChapterTOCFrameData` 构造函数 | 签名 `(unsynchronisation, bytes?, isRoot?, isOrdered?, id?, children?)` | 按参数序精确构造,可选参用 undefined 占位后再 setChilds |
|
|
18
|
+
|
|
19
|
+
### 结果
|
|
20
|
+
|
|
21
|
+
mp3agic Demo 生成中全部差异按源码实测行为处理,编译与功能验证通过。再次使用该库时直接对照本清单,无需重新逐接口核实。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## 鸿蒙人脸检测/取帧/码制过滤 API 对等性核查结论(RN camera-kit 适配锚点)
|
|
2
|
+
|
|
3
|
+
### 问题现象
|
|
4
|
+
RN react-native-camera-kit 18.x 新增人脸检测能力(onFaceDetected / onFaceDetectionInstallStatus 事件、faceDetectionEnabled 等 props)、码制过滤(allowedBarcodeTypes),需核查鸿蒙侧 Kit 对等性后才能下「可否适配」结论。
|
|
5
|
+
|
|
6
|
+
### 解决方案
|
|
7
|
+
新原生能力先查 Kit 对等性再下结论。本次核查锚点(devecocli docs search / 官方文档验证):
|
|
8
|
+
|
|
9
|
+
- **人脸检测** → `@kit.CoreVisionKit` `faceDetector`(API 12+):`detect(VisionInfo) → Face[]{pose{yaw,pitch,roll}, rect, points}`。约束:**仅接受 RGBA_8888 PixelMap、面向图片而非视频流、需限流**
|
|
10
|
+
- **取帧** → `image.ImageReceiver`(readLatestImage)+ 相机预览流 surface
|
|
11
|
+
- **码制过滤** → `scanCore.ScanType` 枚举(14 种,覆盖绝大部分 CodeFormat)。例外:`code-39-mod-43`(iOS-only)无对等;`interleaved-2of5` 近似映射 ITF14_CODE 需实测
|
|
12
|
+
- **通路冲突风险识别**:鸿蒙现有扫码走 `customScan(ViewControl)`(ScanKit 独占 surface),人脸检测需独立 ImageReceiver 支路 ——「扫码 + 人脸检测同时开启」的通路并存策略是适配阶段的重点验证项,分析报告应显式提示
|
|
13
|
+
|
|
14
|
+
### 结果
|
|
15
|
+
Kit 对等性核查支持「人脸检测可适配但有限制」的结论:需 RGBA_8888 像素格式转换 + 调用限流 + 独立取帧通路设计;码制过滤基本可覆盖(2 个例外项需降级或实测)。
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
## PR 元数据判读与 diff 完整性核验经验
|
|
2
|
+
|
|
3
|
+
### 问题现象
|
|
4
|
+
(1)仓库给 PR 打了「静态检查失败」标签,但 PR 元数据 API 显示 `ci_state_passed=true`,两处信息矛盾,容易误判 CI 状态;(2)单 commit PR 中 pr.patch(单次 commit patch)与累积 diff 的关系不确定,需要快速确认 diff 完整性;(3)从 diff 文本提取变更文件列表的 `sed 's/diff --git a\/.* b\/\//'` 命令在 macOS(BSD sed)上报 "unterminated substitute in regular expression",导致 changed-files.txt 生成为 **0 字节空文件**,且直至收尾才被发现,险些遗漏。
|
|
5
|
+
|
|
6
|
+
### 解决方案
|
|
7
|
+
1. CI/标签矛盾时,**以 PR 元数据 API 的 mergeable_state 为准**,标签仅作线索;静态检查结论以本地独立检查 + 基线对照为准。
|
|
8
|
+
2. 单 commit PR 快速判定:`git log --oneline` 确认 PR 分支 HEAD 的父提交即 base master tip 时,pr.patch == 累积 diff,可用于**交叉校验 diff 完整性**;但"必须生成累积 diff"的流程仍应执行,两者一致时相互印证(如 mp3agic PR #53:11 文件 +2605 行两者一致)。
|
|
9
|
+
3. macOS BSD sed 对 `a\/.* b\/` 转义组合不兼容。改用管道方案:`grep "^diff --git" pr-diff.txt | awk '{print $4}' | sed 's/^b\///'`,并在生成后 `wc -l` 校验非空。**通用教训**:所有"生成文件"类步骤都应附带非空校验,0 字节空文件在收尾前不易被察觉。
|
|
10
|
+
|
|
11
|
+
### 结果
|
|
12
|
+
在 mp3agic PR #53 检视中:以 PR 元数据为准避免了被仓库标签误导;pr.patch 与累积 diff 一致相互印证了 diff 完整性;替换命令后 changed-files.txt 正常生成,后续检视范围判断未失据。
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
## RN 覆盖率分析中索引签名伪成员假阴性的识别与 grep 对账
|
|
2
|
+
|
|
3
|
+
### 问题现象
|
|
4
|
+
|
|
5
|
+
RN 三方库用例覆盖度检视中,覆盖率脚本(rn-analyze-test-coverage.cjs / rn-analyze-demo-coverage.cjs,AST 模式)报告的未覆盖列表出现形如 `X.key` 的接口(X 为纯类型接口,key 为通用词),但人工核验发现该类型变量在测试代码中被大量使用,属于脚本假阴性。由于归零规则 6(有效覆盖率 < 100% → 评分 0 分)的放大效应,**单个此类假阴性即可翻转整个评分**(实例:rntpc_cookies 库按假阴性计算 22/23=95.65% < 100% 误触归零 → grep 对账修正后 23/23=100%,评分 0 ↔ 95)。
|
|
6
|
+
|
|
7
|
+
根因链(三层叠加):
|
|
8
|
+
1. 接口提取脚本 rn-extract-interfaces.cjs 将上游 index.d.ts 中的索引签名 `[key: string]: T` 提取为伪字段(memberName=签名参数名 key,运行时不存在名为 key 的真实属性);
|
|
9
|
+
2. 覆盖率脚本 AST 匹配器只处理 PropertyAccessExpression(属性名等值匹配)、对象字面量与 JSX 属性,**不处理 ElementAccessExpression(方括号索引访问)**,而索引签名的合法用法恰恰是 `obj["xxx"]` / `obj[变量]`;
|
|
10
|
+
3. 即使测试写点访问 `obj.xxx`,属性名是业务名而非 `key`,同样不命中 → 索引签名伪成员在属性名等值匹配体系下**必然**假阴性。
|
|
11
|
+
|
|
12
|
+
### 解决方案
|
|
13
|
+
|
|
14
|
+
**三条可疑信号**(识别未覆盖项是否为伪成员,可复用):
|
|
15
|
+
1. memberName 是"类型签名参数名"风格的通用词(`key`/`value`/`index`),而非业务命名;
|
|
16
|
+
2. 所属 className 是纯类型接口(kind=field、layer=js、type=type-decl,无运行时类),即索引签名宿主;
|
|
17
|
+
3. 测试代码中有该类型显式标注的变量(如 `const c: Cookies = {...}`),逻辑上不可能"完全没用"。
|
|
18
|
+
|
|
19
|
+
**grep 盘点对账**(验证方法):对疑似伪成员,在测试与 Demo 源码中 grep 宿主类型变量的所有访问形式:
|
|
20
|
+
- 方括号访问:`varName[`(字面量键 `varName["xxx"]`、变量键 `varName[k]`、计算键 `varName[expr]` 三种形式)
|
|
21
|
+
- 点访问:`varName.`(任意属性名,只要变量类型为该接口)
|
|
22
|
+
|
|
23
|
+
任一形式命中且语义上使用了该索引签名类型 → 判定为脚本假阴性,修正为已覆盖(来源标注 test/demo/both),并重新计算有效覆盖率。
|
|
24
|
+
|
|
25
|
+
### 结果
|
|
26
|
+
|
|
27
|
+
rntpc_cookies 实例验证:`Cookies.key` 疑似伪成员经 grep 对账命中 6+ 处(变量键+字面量键+计算键+点访问,以及对 `get()`/`getFromResponse()` 返回值的索引断言),且 `Cookie.fields` 用例通过布尔断言验证了 4 种键访问形式的正确性 → 判定已覆盖(both),有效覆盖率修正为 100%,最终评分 95 分而非 0 分。
|
|
28
|
+
|
|
29
|
+
可复用结论:
|
|
30
|
+
1. 任何"脚本未覆盖列表 → 扣分/归零"链路,评分前必须对未覆盖项**逐项 grep 交叉验证**(测试与 Demo 双来源);memberName 为通用词且所属为纯类型接口时尤其必查。
|
|
31
|
+
2. **归零边缘警觉**:排除平台特有接口后有效覆盖率恰好差 1-2 项达到 100%,是伪成员/假阴性的高发信号,此时必须逐项核验而非直接套规则。
|
|
32
|
+
3. 脚本侧根治方向:覆盖率脚本 AST 匹配器补充 ElementAccessExpression(索引访问)识别 + 变量类型映射,可从源头消除此类假阴性。
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# RN 鸿蒙内存检视严重度标定原则(destroy 豁免/死代码单例/观察项)
|
|
2
|
+
|
|
3
|
+
### 问题现象
|
|
4
|
+
|
|
5
|
+
内存泄露检视按固定扣分表执行时,两类场景容易误判:
|
|
6
|
+
1. 无状态模块未重写 `__onDestroy__`,机械执行"未释放扣 20 分"会把零泄露面的优秀库误判为 0 分或低分档。
|
|
7
|
+
2. 模块级 `export default new Logger(...)` 这类 eager 单例,若全仓库无任何 import(死代码),运行期零分配,严格意义上不是泄露,容易被高估为实际泄露风险。
|
|
8
|
+
|
|
9
|
+
### 解决方案
|
|
10
|
+
|
|
11
|
+
三条可复用标定原则:
|
|
12
|
+
|
|
13
|
+
1. **无状态模块 destroy 豁免**:`__onDestroy__` 缺失是否扣分,取决于模块是否存在可释放资源(事件监听/系统资源句柄/Map/Set 容器/回调引用/实例字段)。零字段模块不重写 destroy 属正确最小化设计,不构成泄露风险,不扣分。判定前须先用穷尽验证模式集确认"零泄露面"(rg 六组模式全 0 命中)。
|
|
14
|
+
|
|
15
|
+
2. **死代码单例两档标定**:`模块级 new 单例` 分两档——(a) 被 import → 加载即常驻,若体量固定记轻微~中等;(b) 全仓库无引用死代码 → 记轻微(0~-5),并在报告中注明"运行期零分配,非严格泄露",避免把死代码当成实际泄露高估风险。
|
|
16
|
+
|
|
17
|
+
3. **观察项(0 分)分级**:内存检视中发现的非内存问题(未接线死代码、codegen 滞后等)记入泄露风险清单但标注"观察(0 分)",说明不扣分理由(无内存影响)+ 指引归属阶段(编码质量/一致性检视)。不稀释内存评分语义,同时不丢失信息。
|
|
18
|
+
|
|
19
|
+
### 结果
|
|
20
|
+
|
|
21
|
+
rntpc_cookies 校准案例:无状态库 + 1 处死代码单例(Logger.ets 模块级 new,全仓库无 import)→ 95 分(轻微 -5);未接线死代码、codegen 滞后按观察项(0 分)记录不扣分。若死代码也不存在应为 100 分。观察项计入扣分会把优秀库误判到"良好"档,此标定原则可避免该类评分漂移。
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
## RN 平台特有接口排除判定:上游注释仅为线索,鸿蒙侧实现是决定性判据
|
|
2
|
+
|
|
3
|
+
### 问题现象
|
|
4
|
+
|
|
5
|
+
RN 三方库鸿蒙化用例覆盖度检视中,对未覆盖列表做平台特有接口排除时存在**过度排除**失真风险:上游 index.d.ts 中标注 `// Android only`、`// iOS only` 的接口,若按注释机械排除,会把鸿蒙侧真实存在的接口移出有效分母,掩盖真实覆盖缺口。
|
|
6
|
+
|
|
7
|
+
反例(rntpc_cookies 库):`removeSessionCookies`(上游标注 Android only)与 `clearByName`(上游标注 iOS only)虽被标注为单平台专属,但鸿蒙侧 TurboModule Spec **均有实现**(`clearSessionCookieSync` / 过期 Cookie 覆写删除)——不得排除。过度排除与假阴性方向相反,但同样导致有效覆盖率失真。
|
|
8
|
+
|
|
9
|
+
### 解决方案
|
|
10
|
+
|
|
11
|
+
平台特有接口排除的正确证据链(建议三条齐备才排除):
|
|
12
|
+
1. **上游平台限定标注**(`// Android only`、`// iOS only` 等)——仅为线索,不能单独作为排除依据;
|
|
13
|
+
2. **鸿蒙 JS 入口的平台门控**——如 `flush` 仅在 `Platform.OS === 'android'` 时调原生,鸿蒙为 no-op;
|
|
14
|
+
3. **鸿蒙侧 TurboModule Spec / ArkTS / C++ 转发均无实现**——决定性判据(对应检视 CHECKLIST 平台特有识别特征 4)。
|
|
15
|
+
|
|
16
|
+
判定优先级:上游 d.ts 平台注释 ≠ 排除依据;以鸿蒙侧是否有 TurboModule/ArkTS 实现为决定性判据。保守判定原则:无法确定是否平台特有时**不排除**(按正常未覆盖处理),只有证据链明确时才排除。
|
|
17
|
+
|
|
18
|
+
### 结果
|
|
19
|
+
|
|
20
|
+
rntpc_cookies 实例验证:
|
|
21
|
+
- `flush`(上游标注 Android only + 鸿蒙 JS 入口 no-op + 鸿蒙侧无实现)与 `getAll`(上游标注 iOS only + 鸿蒙侧三层均未实现、调用抛 TypeError)证据链齐备,正确排除;
|
|
22
|
+
- `removeSessionCookies` / `clearByName` 因鸿蒙侧 TurboModule 有实现而**不排除**,避免了掩盖真实覆盖状态。
|
|
23
|
+
|
|
24
|
+
可复用结论:平台特有排除判定必须核对鸿蒙侧 TurboModule Spec / ArkTS / C++ 是否有实现,不能信任上游注释;三条证据齐备才排除,防止过度排除(移出真实接口)与遗漏排除(误触归零)两类方向相反的失真。
|