expo-harmony-toolkit 1.7.2 → 1.8.0

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.
Files changed (69) hide show
  1. package/README.en.md +25 -11
  2. package/README.md +27 -13
  3. package/build/core/autolinking.d.ts +10 -0
  4. package/build/core/autolinking.js +421 -0
  5. package/build/core/build/commands.d.ts +19 -0
  6. package/build/core/build/commands.js +61 -0
  7. package/build/core/build/compatibilityShims.d.ts +1 -0
  8. package/build/core/build/compatibilityShims.js +272 -0
  9. package/build/core/build/localHar.d.ts +13 -0
  10. package/build/core/build/localHar.js +337 -0
  11. package/build/core/build/reporting.d.ts +19 -0
  12. package/build/core/build/reporting.js +67 -0
  13. package/build/core/build/rnohCompatibility.d.ts +1 -0
  14. package/build/core/build/rnohCompatibility.js +38 -0
  15. package/build/core/build.d.ts +4 -12
  16. package/build/core/build.js +70 -762
  17. package/build/core/constants.d.ts +2 -1
  18. package/build/core/constants.js +3 -2
  19. package/build/core/dependencyInspection.d.ts +2 -0
  20. package/build/core/dependencyInspection.js +130 -0
  21. package/build/core/env.js +1 -1
  22. package/build/core/report.js +162 -10
  23. package/build/core/signing.d.ts +2 -0
  24. package/build/core/signing.js +30 -0
  25. package/build/core/template/capabilityRegistry.d.ts +9 -0
  26. package/build/core/template/capabilityRegistry.js +84 -0
  27. package/build/core/template/expoModulesCoreShim.d.ts +2 -0
  28. package/build/core/template/expoModulesCoreShim.js +279 -0
  29. package/build/core/template/metro.d.ts +2 -0
  30. package/build/core/template/metro.js +213 -0
  31. package/build/core/template/nativeFiles.d.ts +8 -0
  32. package/build/core/template/nativeFiles.js +333 -0
  33. package/build/core/template/renderers/camera.d.ts +4 -0
  34. package/build/core/template/renderers/camera.js +612 -0
  35. package/build/core/template/renderers/fileSystem.d.ts +4 -0
  36. package/build/core/template/renderers/fileSystem.js +814 -0
  37. package/build/core/template/renderers/imagePicker.d.ts +4 -0
  38. package/build/core/template/renderers/imagePicker.js +753 -0
  39. package/build/core/template/renderers/location.d.ts +4 -0
  40. package/build/core/template/renderers/location.js +836 -0
  41. package/build/core/template/runtimeShims.d.ts +2 -0
  42. package/build/core/template/runtimeShims.js +192 -0
  43. package/build/core/template/support.d.ts +11 -0
  44. package/build/core/template/support.js +108 -0
  45. package/build/core/template.d.ts +3 -6
  46. package/build/core/template.js +49 -4457
  47. package/build/data/capabilities.js +21 -4
  48. package/build/data/dependencyCatalog.js +10 -0
  49. package/build/data/publicDocs.d.ts +11 -0
  50. package/build/data/publicDocs.js +28 -0
  51. package/build/data/validatedMatrices.js +9 -1
  52. package/build/docs/render.d.ts +9 -0
  53. package/build/docs/render.js +250 -0
  54. package/build/types.d.ts +19 -0
  55. package/docs/cli-build.md +1 -1
  56. package/docs/npm-release.md +1 -0
  57. package/docs/official-app-shell-sample.md +2 -1
  58. package/docs/official-minimal-sample.md +2 -1
  59. package/docs/official-native-capabilities-sample.md +12 -2
  60. package/docs/official-ui-stack-sample.md +2 -1
  61. package/docs/roadmap.md +146 -51
  62. package/docs/signing-and-release.md +3 -0
  63. package/docs/support-matrix.md +59 -13
  64. package/package.json +13 -5
  65. package/docs/v1.5.1-acceptance.md +0 -385
  66. package/docs/v1.6.0-acceptance.md +0 -193
  67. package/docs/v1.7.0-acceptance.md +0 -111
  68. package/docs/v1.7.1-acceptance.md +0 -111
  69. package/docs/v1.7.2-acceptance.md +0 -37
@@ -12,12 +12,24 @@ const PREVIEW_BASELINE_EVIDENCE = {
12
12
  device: true,
13
13
  release: false,
14
14
  };
15
+ const PREVIEW_BASELINE_EVIDENCE_SOURCE = {
16
+ bundle: 'automated',
17
+ debugBuild: 'automated',
18
+ device: 'manual-doc',
19
+ release: 'none',
20
+ };
15
21
  const EXPLORATORY_EVIDENCE = {
16
22
  bundle: false,
17
23
  debugBuild: false,
18
24
  device: false,
19
25
  release: false,
20
26
  };
27
+ const EXPLORATORY_EVIDENCE_SOURCE = {
28
+ bundle: 'none',
29
+ debugBuild: 'none',
30
+ device: 'none',
31
+ release: 'none',
32
+ };
21
33
  exports.CAPABILITY_DEFINITIONS = [
22
34
  {
23
35
  id: 'expo-file-system',
@@ -26,7 +38,8 @@ exports.CAPABILITY_DEFINITIONS = [
26
38
  supportTier: 'preview',
27
39
  runtimeMode: 'adapter',
28
40
  evidence: PREVIEW_BASELINE_EVIDENCE,
29
- note: 'Toolkit-managed Harmony native file-system adapters cover the v1.7.2 preview subset: UTF-8/base64 sandbox I/O, append and partial reads, md5 metadata, and direct downloads into the app sandbox.',
41
+ evidenceSource: PREVIEW_BASELINE_EVIDENCE_SOURCE,
42
+ note: 'Toolkit-managed Harmony native file-system adapters cover the v1.8.0 preview subset: UTF-8/base64 sandbox I/O, append and partial reads, md5 metadata, and direct downloads into the app sandbox.',
30
43
  docsUrl: 'https://github.com/react-native-oh-library/usage-docs/blob/master/en/react-native-fs.md',
31
44
  nativePackageNames: ['react-native-fs'],
32
45
  harmonyPermissions: [],
@@ -44,7 +57,8 @@ exports.CAPABILITY_DEFINITIONS = [
44
57
  supportTier: 'preview',
45
58
  runtimeMode: 'adapter',
46
59
  evidence: PREVIEW_BASELINE_EVIDENCE,
47
- note: 'Toolkit-managed Harmony adapters cover the v1.7.2 preview subset: media and camera permissions, single/multi-select library flows, system photo/video capture, pending-result restore, and richer video asset metadata.',
60
+ evidenceSource: PREVIEW_BASELINE_EVIDENCE_SOURCE,
61
+ note: 'Toolkit-managed Harmony adapters cover the v1.8.0 preview subset: media and camera permissions, single/multi-select library flows, system photo/video capture, pending-result restore, and richer video asset metadata.',
48
62
  docsUrl: 'https://github.com/react-native-oh-library/usage-docs/blob/master/en/react-native-image-picker.md',
49
63
  nativePackageNames: ['react-native-image-picker', 'react-native-permissions'],
50
64
  harmonyPermissions: [
@@ -66,7 +80,8 @@ exports.CAPABILITY_DEFINITIONS = [
66
80
  supportTier: 'preview',
67
81
  runtimeMode: 'adapter',
68
82
  evidence: PREVIEW_BASELINE_EVIDENCE,
69
- note: 'Toolkit-managed Harmony adapters cover the v1.7.2 preview subset: foreground/background permission flows, current and last-known fixes, geocoding, continuous watch subscriptions, and sensor-backed heading updates.',
83
+ evidenceSource: PREVIEW_BASELINE_EVIDENCE_SOURCE,
84
+ note: 'Toolkit-managed Harmony adapters cover the v1.8.0 preview subset: foreground/background permission flows, current and last-known fixes, geocoding, continuous watch subscriptions, and sensor-backed heading updates.',
70
85
  docsUrl: 'https://github.com/react-native-oh-library/usage-docs/blob/master/en/%40react-native-community-geolocation.md',
71
86
  nativePackageNames: ['@react-native-community/geolocation', 'react-native-permissions'],
72
87
  harmonyPermissions: [
@@ -89,7 +104,8 @@ exports.CAPABILITY_DEFINITIONS = [
89
104
  supportTier: 'preview',
90
105
  runtimeMode: 'adapter',
91
106
  evidence: PREVIEW_BASELINE_EVIDENCE,
92
- note: 'Toolkit-managed Harmony adapters cover the v1.7.2 preview subset: embedded camera preview, still capture, preview pause/resume, microphone permission, and in-session video recording controls.',
107
+ evidenceSource: PREVIEW_BASELINE_EVIDENCE_SOURCE,
108
+ note: 'Toolkit-managed Harmony adapters cover the v1.8.0 preview subset: embedded camera preview, still capture, preview pause/resume, microphone permission, and in-session video recording controls.',
93
109
  docsUrl: 'https://github.com/react-native-oh-library/usage-docs/blob/master/en/react-native-camera-kit.md',
94
110
  nativePackageNames: ['react-native-camera-kit', 'react-native-permissions'],
95
111
  harmonyPermissions: ['ohos.permission.CAMERA', 'ohos.permission.MICROPHONE'],
@@ -107,6 +123,7 @@ exports.CAPABILITY_DEFINITIONS = [
107
123
  supportTier: 'experimental',
108
124
  runtimeMode: 'shim',
109
125
  evidence: EXPLORATORY_EVIDENCE,
126
+ evidenceSource: EXPLORATORY_EVIDENCE_SOURCE,
110
127
  note: 'Notifications stay below the public promise until a complete Harmony delivery story is validated end to end.',
111
128
  docsUrl: 'https://github.com/react-native-oh-library',
112
129
  nativePackageNames: [],
@@ -37,6 +37,11 @@ exports.DEPENDENCY_CATALOG = {
37
37
  supportTier: 'verified',
38
38
  note: 'Toolkit can parse Expo config and scaffold Harmony sidecar files for managed/CNG projects.',
39
39
  },
40
+ '@expo/metro-runtime': {
41
+ status: 'supported',
42
+ supportTier: 'verified',
43
+ note: 'Metro runtime is part of the validated managed Expo routing/bundling chain and keeps Expo workspace peers aligned.',
44
+ },
40
45
  '@babel/runtime': {
41
46
  status: 'supported',
42
47
  supportTier: 'verified',
@@ -62,6 +67,11 @@ exports.DEPENDENCY_CATALOG = {
62
67
  supportTier: 'verified',
63
68
  note: 'React is treated as a baseline JavaScript dependency.',
64
69
  },
70
+ 'react-dom': {
71
+ status: 'supported',
72
+ supportTier: 'verified',
73
+ note: 'React DOM is treated as a workspace peer for Expo Router and web-capable managed Expo projects inside the validated matrix.',
74
+ },
65
75
  'react-native': {
66
76
  status: 'supported',
67
77
  supportTier: 'verified',
@@ -0,0 +1,11 @@
1
+ export declare const PUBLIC_RELEASE_TRACKS: {
2
+ readonly latest: "fully accepted verified only";
3
+ readonly next: "preview fast track";
4
+ };
5
+ export declare const PRIMARY_SAMPLE_PATH = "examples/official-ui-stack-sample";
6
+ export declare const PREVIEW_SAMPLE_PATH = "examples/official-native-capabilities-sample";
7
+ export declare const SUPPORTING_SAMPLE_PATHS: readonly ["examples/official-app-shell-sample", "examples/official-minimal-sample"];
8
+ export declare const VERIFIED_JS_UI_CAPABILITY_NAMES: readonly ["expo-router", "expo-linking", "expo-constants", ...("react-native-reanimated" | "react-native-svg")[]];
9
+ export declare const PREVIEW_CAPABILITY_DEFINITIONS: import("..").CapabilityDefinition[];
10
+ export declare const EXPERIMENTAL_CAPABILITY_NAMES: readonly [...string[], "react-native-gesture-handler"];
11
+ export declare const PUBLIC_CURRENT_VERSION = "1.8.0";
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PUBLIC_CURRENT_VERSION = exports.EXPERIMENTAL_CAPABILITY_NAMES = exports.PREVIEW_CAPABILITY_DEFINITIONS = exports.VERIFIED_JS_UI_CAPABILITY_NAMES = exports.SUPPORTING_SAMPLE_PATHS = exports.PREVIEW_SAMPLE_PATH = exports.PRIMARY_SAMPLE_PATH = exports.PUBLIC_RELEASE_TRACKS = void 0;
4
+ const constants_1 = require("../core/constants");
5
+ const capabilities_1 = require("./capabilities");
6
+ const uiStack_1 = require("./uiStack");
7
+ exports.PUBLIC_RELEASE_TRACKS = {
8
+ latest: 'fully accepted verified only',
9
+ next: 'preview fast track',
10
+ };
11
+ exports.PRIMARY_SAMPLE_PATH = 'examples/official-ui-stack-sample';
12
+ exports.PREVIEW_SAMPLE_PATH = 'examples/official-native-capabilities-sample';
13
+ exports.SUPPORTING_SAMPLE_PATHS = [
14
+ 'examples/official-app-shell-sample',
15
+ 'examples/official-minimal-sample',
16
+ ];
17
+ exports.VERIFIED_JS_UI_CAPABILITY_NAMES = [
18
+ 'expo-router',
19
+ 'expo-linking',
20
+ 'expo-constants',
21
+ ...uiStack_1.UI_STACK_VALIDATED_ADAPTERS.map((adapter) => adapter.canonicalPackageName),
22
+ ];
23
+ exports.PREVIEW_CAPABILITY_DEFINITIONS = capabilities_1.CAPABILITY_DEFINITIONS.filter((definition) => definition.supportTier === 'preview');
24
+ exports.EXPERIMENTAL_CAPABILITY_NAMES = [
25
+ ...capabilities_1.CAPABILITY_DEFINITIONS.filter((definition) => definition.supportTier === 'experimental').map((definition) => definition.packageName),
26
+ 'react-native-gesture-handler',
27
+ ];
28
+ exports.PUBLIC_CURRENT_VERSION = constants_1.TOOLKIT_VERSION;
@@ -6,10 +6,12 @@ const uiStack_1 = require("./uiStack");
6
6
  exports.DEFAULT_VALIDATED_MATRIX_ID = 'expo55-rnoh082-ui-stack';
7
7
  const BASE_ALLOWED_DEPENDENCIES = [
8
8
  'expo',
9
+ '@expo/metro-runtime',
9
10
  'expo-constants',
10
11
  'expo-linking',
11
12
  'expo-router',
12
13
  'react',
14
+ 'react-dom',
13
15
  'react-native',
14
16
  'expo-status-bar',
15
17
  '@babel/runtime',
@@ -36,6 +38,9 @@ exports.VALIDATED_RELEASE_MATRICES = {
36
38
  required: true,
37
39
  version: '>=55.0.0 <56.0.0',
38
40
  },
41
+ '@expo/metro-runtime': {
42
+ version: '>=55.0.0 <56.0.0',
43
+ },
39
44
  'expo-constants': {
40
45
  version: '>=55.0.0 <56.0.0',
41
46
  },
@@ -43,12 +48,15 @@ exports.VALIDATED_RELEASE_MATRICES = {
43
48
  version: '>=55.0.0 <56.0.0',
44
49
  },
45
50
  'expo-router': {
46
- version: '>=6.0.0 <7.0.0',
51
+ version: '>=55.0.0 <56.0.0',
47
52
  },
48
53
  react: {
49
54
  required: true,
50
55
  version: '19.1.1',
51
56
  },
57
+ 'react-dom': {
58
+ version: '19.1.1',
59
+ },
52
60
  'react-native': {
53
61
  required: true,
54
62
  version: '0.82.1',
@@ -0,0 +1,9 @@
1
+ export type DocsLocale = 'zh' | 'en';
2
+ export declare function renderReadmeCurrentStatus(locale: DocsLocale): string;
3
+ export declare function renderReadmeSupportMatrixSection(locale: DocsLocale): string;
4
+ export declare function renderSupportMatrixVerifiedMatrix(locale: DocsLocale): string;
5
+ export declare function renderSupportMatrixVerifiedAllowlist(): string;
6
+ export declare function renderSupportMatrixCapabilityTelemetry(locale: DocsLocale): string;
7
+ export declare function renderSupportMatrixPreviewCapabilities(locale: DocsLocale): string;
8
+ export declare function renderSupportMatrixUiStackRules(locale: DocsLocale): string;
9
+ export declare function renderSupportMatrixReleaseTracks(locale: DocsLocale): string;
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderReadmeCurrentStatus = renderReadmeCurrentStatus;
4
+ exports.renderReadmeSupportMatrixSection = renderReadmeSupportMatrixSection;
5
+ exports.renderSupportMatrixVerifiedMatrix = renderSupportMatrixVerifiedMatrix;
6
+ exports.renderSupportMatrixVerifiedAllowlist = renderSupportMatrixVerifiedAllowlist;
7
+ exports.renderSupportMatrixCapabilityTelemetry = renderSupportMatrixCapabilityTelemetry;
8
+ exports.renderSupportMatrixPreviewCapabilities = renderSupportMatrixPreviewCapabilities;
9
+ exports.renderSupportMatrixUiStackRules = renderSupportMatrixUiStackRules;
10
+ exports.renderSupportMatrixReleaseTracks = renderSupportMatrixReleaseTracks;
11
+ const publicDocs_1 = require("../data/publicDocs");
12
+ const validatedMatrices_1 = require("../data/validatedMatrices");
13
+ const uiStack_1 = require("../data/uiStack");
14
+ const matrix = validatedMatrices_1.VALIDATED_RELEASE_MATRICES[validatedMatrices_1.DEFAULT_VALIDATED_MATRIX_ID];
15
+ function renderReadmeCurrentStatus(locale) {
16
+ const headers = locale === 'zh'
17
+ ? ['项目', '说明']
18
+ : ['Item', 'Status'];
19
+ const versionLabel = locale === 'zh' ? '当前版本' : 'Current version';
20
+ const supportModelLabel = locale === 'zh' ? '支持模型' : 'Support model';
21
+ const verifiedMatrixLabel = locale === 'zh' ? '唯一 `verified` 公开矩阵' : 'Public `verified` matrix';
22
+ const inputLabel = locale === 'zh' ? '输入范围' : 'Supported input';
23
+ const verifiedCapabilitiesLabel = locale === 'zh' ? '`verified` JS/UI 能力' : '`verified` JS/UI capabilities';
24
+ const previewLabel = locale === 'zh' ? '`preview` 原生能力' : '`preview` native capabilities';
25
+ const experimentalLabel = locale === 'zh' ? '`experimental` 能力' : '`experimental` capabilities';
26
+ const releaseTracksLabel = locale === 'zh' ? '发布轨' : 'Release tracks';
27
+ const telemetryLabel = locale === 'zh' ? 'capability 遥测' : 'Capability telemetry';
28
+ const buildPathLabel = locale === 'zh' ? '构建链' : 'Build path';
29
+ const primarySampleLabel = locale === 'zh' ? '主 sample' : 'Primary sample';
30
+ const previewSampleLabel = locale === 'zh' ? 'preview sample' : 'Preview sample';
31
+ const supportingSamplesLabel = locale === 'zh' ? '辅助 onboarding samples' : 'Supporting onboarding samples';
32
+ const releaseTracksValue = locale === 'zh'
33
+ ? `\`latest\` = ${publicDocs_1.PUBLIC_RELEASE_TRACKS.latest};\`next\` = ${publicDocs_1.PUBLIC_RELEASE_TRACKS.next}`
34
+ : `\`latest\` = fully accepted \`verified\` only; \`next\` = ${publicDocs_1.PUBLIC_RELEASE_TRACKS.next}`;
35
+ const inputValue = locale === 'zh' ? 'Managed/CNG Expo 项目' : 'Managed/CNG Expo projects';
36
+ const listJoiner = locale === 'zh' ? '、' : ', ';
37
+ return [
38
+ `| ${headers[0]} | ${headers[1]} |`,
39
+ '| --- | --- |',
40
+ `| ${versionLabel} | \`v${publicDocs_1.PUBLIC_CURRENT_VERSION}\` |`,
41
+ `| ${supportModelLabel} | \`verified + preview + experimental\` |`,
42
+ `| ${verifiedMatrixLabel} | \`${validatedMatrices_1.DEFAULT_VALIDATED_MATRIX_ID}\` |`,
43
+ `| ${inputLabel} | ${inputValue} |`,
44
+ `| ${verifiedCapabilitiesLabel} | ${joinInlineCode(publicDocs_1.VERIFIED_JS_UI_CAPABILITY_NAMES, listJoiner)} |`,
45
+ `| ${previewLabel} | ${joinInlineCode(publicDocs_1.PREVIEW_CAPABILITY_DEFINITIONS.map((definition) => definition.packageName), listJoiner)} |`,
46
+ `| ${experimentalLabel} | ${joinInlineCode(publicDocs_1.EXPERIMENTAL_CAPABILITY_NAMES, listJoiner)} |`,
47
+ `| ${releaseTracksLabel} | ${releaseTracksValue} |`,
48
+ `| ${telemetryLabel} | \`runtimeMode\` + \`evidence(...)\` + \`evidenceSource(...)\` + \`coverageProfile\` + \`nextActions\` |`,
49
+ `| ${buildPathLabel} | \`doctor -> init -> bundle -> build-hap\` |`,
50
+ `| ${primarySampleLabel} | \`${publicDocs_1.PRIMARY_SAMPLE_PATH}\` |`,
51
+ `| ${previewSampleLabel} | \`${publicDocs_1.PREVIEW_SAMPLE_PATH}\` |`,
52
+ `| ${supportingSamplesLabel} | ${publicDocs_1.SUPPORTING_SAMPLE_PATHS.map((samplePath) => `\`${samplePath}\``).join(locale === 'zh' ? '、' : ', ')} |`,
53
+ ].join('\n');
54
+ }
55
+ function renderReadmeSupportMatrixSection(locale) {
56
+ const verifiedLine = locale === 'zh'
57
+ ? `- \`verified\`:唯一公开矩阵仍是 \`${validatedMatrices_1.DEFAULT_VALIDATED_MATRIX_ID}\``
58
+ : `- \`verified\`: the only public matrix remains \`${validatedMatrices_1.DEFAULT_VALIDATED_MATRIX_ID}\``;
59
+ const previewLine = locale === 'zh'
60
+ ? `- \`preview\`:${joinInlineCode(publicDocs_1.PREVIEW_CAPABILITY_DEFINITIONS.map((definition) => definition.packageName))}`
61
+ : `- \`preview\`: ${joinInlineCode(publicDocs_1.PREVIEW_CAPABILITY_DEFINITIONS.map((definition) => definition.packageName))}`;
62
+ const experimentalLine = locale === 'zh'
63
+ ? `- \`experimental\`:${joinInlineCode(publicDocs_1.EXPERIMENTAL_CAPABILITY_NAMES)}`
64
+ : `- \`experimental\`: ${joinInlineCode(publicDocs_1.EXPERIMENTAL_CAPABILITY_NAMES)}`;
65
+ const strictLine = locale === 'zh'
66
+ ? '`doctor --strict` 继续只代表 `verified`。`doctor --target-tier preview` 会在同一 runtime matrix 下额外放行 preview 能力,但这不等于它们已经进入正式承诺。'
67
+ : '`doctor --strict` still means `verified` only. `doctor --target-tier preview` allows the same runtime matrix plus preview-tier capabilities, but that does not promote them into the formal public promise.';
68
+ const telemetryLines = locale === 'zh'
69
+ ? [
70
+ '- `doctor-report.json` 的 `capabilities[]` 会带出 `runtimeMode`',
71
+ '- `doctor-report.json` 与 `toolkit-config.json` 会带出 `evidence.bundle`、`evidence.debugBuild`、`evidence.device`、`evidence.release`',
72
+ '- `doctor-report.json` 与 `toolkit-config.json` 会带出 `evidenceSource.bundle`、`evidenceSource.debugBuild`、`evidenceSource.device`、`evidenceSource.release`',
73
+ '- `doctor-report.json` 与 `toolkit-config.json` 也会带出 `coverageProfile` 与按顺序排列的 `nextActions`',
74
+ '- `runtimeMode=shim` 说明当前仍未进入 verified runtime path,即使 bundle / debug build 已经可走通',
75
+ '- `evidenceSource.device=manual-doc` 表示当前只有人工设备验收记录,不代表机器自动验证',
76
+ ]
77
+ : [
78
+ '- `doctor-report.json` exposes `capabilities[].runtimeMode`',
79
+ '- `doctor-report.json` and `toolkit-config.json` expose `evidence.bundle`, `evidence.debugBuild`, `evidence.device`, and `evidence.release`',
80
+ '- `doctor-report.json` and `toolkit-config.json` expose `evidenceSource.bundle`, `evidenceSource.debugBuild`, `evidenceSource.device`, and `evidenceSource.release`',
81
+ '- `doctor-report.json` and `toolkit-config.json` also expose `coverageProfile` plus ordered `nextActions`',
82
+ '- `runtimeMode=shim` means the capability still has not reached a verified runtime path even if bundling and debug-build scaffolding already exist',
83
+ '- `evidenceSource.device=manual-doc` means the current device signal comes from manual acceptance records, not automated verification',
84
+ ];
85
+ return [verifiedLine, previewLine, experimentalLine, '', strictLine, '', ...telemetryLines].join('\n');
86
+ }
87
+ function renderSupportMatrixVerifiedMatrix(locale) {
88
+ const appShellValue = locale === 'zh'
89
+ ? '`expo-router` `55.x`、`expo-linking` `55.x`、`expo-constants` `55.x`、`@expo/metro-runtime` `55.x`、`react-dom` `19.1.1`'
90
+ : '`expo-router` `55.x`, `expo-linking` `55.x`, `expo-constants` `55.x`, `@expo/metro-runtime` `55.x`, `react-dom` `19.1.1`';
91
+ const uiStackValue = locale === 'zh'
92
+ ? '`react-native-reanimated` `3.6.0`、`react-native-svg` `15.0.0`'
93
+ : '`react-native-reanimated` `3.6.0`, `react-native-svg` `15.0.0`';
94
+ return [
95
+ '| 项目 | 要求 |',
96
+ '| --- | --- |',
97
+ `| Expo SDK | \`${matrix.expoSdkVersion}\` |`,
98
+ `| React | \`${matrix.dependencyRules.react?.version}\` |`,
99
+ `| React Native | \`${matrix.dependencyRules['react-native']?.version}\` |`,
100
+ `| \`@react-native-oh/react-native-harmony\` | \`${matrix.dependencyRules['@react-native-oh/react-native-harmony']?.version}\` |`,
101
+ `| \`@react-native-oh/react-native-harmony-cli\` | \`${matrix.dependencyRules['@react-native-oh/react-native-harmony-cli']?.version}\` |`,
102
+ '| `@react-native-community/cli` | `20.x` |',
103
+ '| `metro` | `0.83.x` |',
104
+ `| App Shell 依赖 | ${appShellValue} |`,
105
+ `| UI stack 依赖 | ${uiStackValue} |`,
106
+ '| 原生标识 | 至少设置 `android.package` 或 `ios.bundleIdentifier` |',
107
+ ].join('\n');
108
+ }
109
+ function renderSupportMatrixVerifiedAllowlist() {
110
+ return matrix.allowedDependencies.map((dependencyName) => `- \`${dependencyName}\``).join('\n');
111
+ }
112
+ function renderSupportMatrixCapabilityTelemetry(locale) {
113
+ const lines = locale === 'zh'
114
+ ? [
115
+ '所有 capability 从现在开始都同时公开:',
116
+ '',
117
+ '- `supportTier`',
118
+ '- `runtimeMode`',
119
+ '- `evidence.bundle`',
120
+ '- `evidence.debugBuild`',
121
+ '- `evidence.device`',
122
+ '- `evidence.release`',
123
+ '- `evidenceSource.bundle`',
124
+ '- `evidenceSource.debugBuild`',
125
+ '- `evidenceSource.device`',
126
+ '- `evidenceSource.release`',
127
+ '',
128
+ '判读规则:',
129
+ '',
130
+ '- `runtimeMode=shim`:说明当前还在桥接或占位阶段,即使 bundle / debug build 已完成,也不应宣称 verified',
131
+ '- `runtimeMode=adapter`:说明已经进入真实适配路径,但仍缺少某些验收证据',
132
+ '- `runtimeMode=verified`:说明能力已进入正式承诺,且证据闭环完成',
133
+ ]
134
+ : [
135
+ 'All capabilities now publish the following fields together:',
136
+ '',
137
+ '- `supportTier`',
138
+ '- `runtimeMode`',
139
+ '- `evidence.bundle`',
140
+ '- `evidence.debugBuild`',
141
+ '- `evidence.device`',
142
+ '- `evidence.release`',
143
+ '- `evidenceSource.bundle`',
144
+ '- `evidenceSource.debugBuild`',
145
+ '- `evidenceSource.device`',
146
+ '- `evidenceSource.release`',
147
+ '',
148
+ 'Reading rules:',
149
+ '',
150
+ '- `runtimeMode=shim`: the capability is still on a bridge or placeholder path and must not be described as verified',
151
+ '- `runtimeMode=adapter`: the capability is on a real adapter path but still lacks part of the evidence needed for verified promotion',
152
+ '- `runtimeMode=verified`: the capability has entered the formal public promise and closed the evidence loop',
153
+ ];
154
+ return lines.join('\n');
155
+ }
156
+ function renderSupportMatrixPreviewCapabilities(locale) {
157
+ const headers = locale === 'zh'
158
+ ? ['Expo 能力', '当前层级', 'runtimeMode', 'evidence', 'Harmony 依赖方向', '受管权限', '官方 sample route']
159
+ : ['Expo capability', 'Support tier', 'runtimeMode', 'evidence', 'Harmony dependency direction', 'Managed permissions', 'Official sample route'];
160
+ return [
161
+ `| ${headers.join(' | ')} |`,
162
+ `| ${headers.map(() => '---').join(' | ')} |`,
163
+ ...publicDocs_1.PREVIEW_CAPABILITY_DEFINITIONS.map((definition) => {
164
+ const dependencyDirection = definition.nativePackageNames.length > 0
165
+ ? definition.nativePackageNames.join(', ')
166
+ : 'toolkit-managed bridge';
167
+ const permissions = definition.harmonyPermissions.length > 0
168
+ ? definition.harmonyPermissions.join(locale === 'zh' ? '、' : ', ')
169
+ : locale === 'zh'
170
+ ? '无新增必需权限'
171
+ : 'no additional required permissions';
172
+ return [
173
+ `\`${definition.packageName}\``,
174
+ `\`${definition.supportTier}\``,
175
+ `\`${definition.runtimeMode}\``,
176
+ `\`${renderEvidence(definition)}\``,
177
+ dependencyDirection,
178
+ permissions,
179
+ `\`${definition.sampleRoute}\``,
180
+ ].join(' | ');
181
+ }).map((row) => `| ${row} |`),
182
+ ].join('\n');
183
+ }
184
+ function renderSupportMatrixUiStackRules(locale) {
185
+ const intro = locale === 'zh'
186
+ ? 'canonical 包与 Harmony adapter 包固定为双向强制:'
187
+ : 'Canonical packages and Harmony adapters stay strictly paired in both directions:';
188
+ const rules = locale === 'zh'
189
+ ? [
190
+ '规则固定为:',
191
+ '',
192
+ '- 出现 canonical 包,必须同时出现对应 `@react-native-oh-tpl/*`',
193
+ '- 出现 `@react-native-oh-tpl/*`,也必须同时出现对应 canonical 包',
194
+ '- canonical 包按 semver 校验',
195
+ '- `@react-native-oh-tpl/*` 按 exact dependency specifier 校验',
196
+ '',
197
+ '当前固定 exact specifier:',
198
+ ]
199
+ : [
200
+ 'The enforced rules are:',
201
+ '',
202
+ '- canonical packages require their matching `@react-native-oh-tpl/*` adapters',
203
+ '- adapter packages also require their canonical counterparts',
204
+ '- canonical packages are validated with semver ranges',
205
+ '- `@react-native-oh-tpl/*` adapters are validated against exact dependency specifiers',
206
+ '',
207
+ 'Pinned exact specifiers:',
208
+ ];
209
+ return [
210
+ intro,
211
+ '',
212
+ ...uiStack_1.UI_STACK_VALIDATED_ADAPTERS.map((adapter) => `- \`${adapter.canonicalPackageName}\` ↔ \`${adapter.adapterPackageName}\``),
213
+ '',
214
+ ...rules,
215
+ '',
216
+ ...uiStack_1.UI_STACK_VALIDATED_ADAPTERS.map((adapter) => `- \`${adapter.adapterPackageName}\`: \`${(0, uiStack_1.getUiStackAdapterSpecifier)(adapter)}\``),
217
+ ].join('\n');
218
+ }
219
+ function renderSupportMatrixReleaseTracks(locale) {
220
+ return locale === 'zh'
221
+ ? [
222
+ '- `latest`',
223
+ ' - 只承接完整验收的 `verified` 能力',
224
+ ' - 只允许 verified sample / gate 作为发布依据',
225
+ '- `next`',
226
+ ' - 承接 preview fast track',
227
+ ' - 必须至少通过 preview sample、bundle、debug build gate',
228
+ ' - 不得被描述为 verified 或 release-ready',
229
+ ].join('\n')
230
+ : [
231
+ '- `latest`',
232
+ ' - only carries fully accepted `verified` capabilities',
233
+ ' - only verified samples and gates may justify a release',
234
+ '- `next`',
235
+ ' - carries preview fast-track work',
236
+ ' - must at least pass the preview sample, bundle, and debug-build gates',
237
+ ' - must not be described as verified or release-ready',
238
+ ].join('\n');
239
+ }
240
+ function joinInlineCode(entries, joiner = ', ') {
241
+ return entries.map((entry) => `\`${entry}\``).join(joiner);
242
+ }
243
+ function renderEvidence(definition) {
244
+ return [
245
+ `bundle=${definition.evidence.bundle ? 'yes' : 'no'}[${definition.evidenceSource.bundle}]`,
246
+ `debugBuild=${definition.evidence.debugBuild ? 'yes' : 'no'}[${definition.evidenceSource.debugBuild}]`,
247
+ `device=${definition.evidence.device ? 'yes' : 'no'}[${definition.evidenceSource.device}]`,
248
+ `release=${definition.evidence.release ? 'yes' : 'no'}[${definition.evidenceSource.release}]`,
249
+ ].join(', ');
250
+ }
package/build/types.d.ts CHANGED
@@ -3,6 +3,10 @@ export type EligibilityStatus = 'eligible' | 'ineligible';
3
3
  export type SupportTier = 'verified' | 'preview' | 'experimental' | 'unsupported';
4
4
  export type DoctorTargetTier = Exclude<SupportTier, 'unsupported'>;
5
5
  export type CapabilityRuntimeMode = 'shim' | 'adapter' | 'verified';
6
+ export type CapabilityEvidenceSource = 'automated' | 'manual-doc' | 'none';
7
+ export type DependencyBuildabilityRisk = 'known' | 'js-only-unknown' | 'native-risk' | 'unresolved';
8
+ export type CoverageProfile = 'managed-core' | 'managed-native-heavy' | 'bare' | 'third-party-native-heavy';
9
+ export type GapCategory = 'matrix-drift' | 'official-module-gap' | 'third-party-native-gap' | 'bare-workflow-gap';
6
10
  export type DependencySource = 'dependency' | 'devDependency' | 'peerDependency' | 'expo-plugin';
7
11
  export interface ExpoHarmonyPluginProps {
8
12
  bundleName?: string;
@@ -66,6 +70,8 @@ export interface DetectedDependency {
66
70
  source: DependencySource;
67
71
  status: CompatibilityStatus;
68
72
  supportTier: SupportTier;
73
+ buildabilityRisk: DependencyBuildabilityRisk;
74
+ gapCategory: GapCategory;
69
75
  blocking: boolean;
70
76
  note: string;
71
77
  replacement?: string;
@@ -89,6 +95,12 @@ export interface CapabilityEvidence {
89
95
  device: boolean;
90
96
  release: boolean;
91
97
  }
98
+ export interface CapabilityEvidenceSourceMap {
99
+ bundle: CapabilityEvidenceSource;
100
+ debugBuild: CapabilityEvidenceSource;
101
+ device: CapabilityEvidenceSource;
102
+ release: CapabilityEvidenceSource;
103
+ }
92
104
  export interface CapabilityDefinition {
93
105
  id: string;
94
106
  packageName: string;
@@ -96,6 +108,7 @@ export interface CapabilityDefinition {
96
108
  supportTier: DoctorTargetTier;
97
109
  runtimeMode: CapabilityRuntimeMode;
98
110
  evidence: CapabilityEvidence;
111
+ evidenceSource: CapabilityEvidenceSourceMap;
99
112
  note: string;
100
113
  docsUrl?: string;
101
114
  nativePackageNames: string[];
@@ -110,6 +123,7 @@ export interface ProjectCapabilityReport {
110
123
  supportTier: DoctorTargetTier;
111
124
  runtimeMode: CapabilityRuntimeMode;
112
125
  evidence: CapabilityEvidence;
126
+ evidenceSource: CapabilityEvidenceSourceMap;
113
127
  note: string;
114
128
  docsUrl?: string;
115
129
  nativePackageNames: string[];
@@ -123,6 +137,7 @@ export interface ManagedCapabilityRecord {
123
137
  supportTier: DoctorTargetTier;
124
138
  runtimeMode: CapabilityRuntimeMode;
125
139
  evidence: CapabilityEvidence;
140
+ evidenceSource: CapabilityEvidenceSourceMap;
126
141
  }
127
142
  export interface DoctorReport {
128
143
  generatedAt: string;
@@ -136,6 +151,7 @@ export interface DoctorReport {
136
151
  rnohCliVersion: string;
137
152
  expoSdkVersion: number | null;
138
153
  targetTier: DoctorTargetTier;
154
+ coverageProfile: CoverageProfile;
139
155
  expoConfig: {
140
156
  name: string | null;
141
157
  slug: string | null;
@@ -150,6 +166,7 @@ export interface DoctorReport {
150
166
  supportSummary: SupportTierSummary;
151
167
  capabilities: ProjectCapabilityReport[];
152
168
  blockingIssues: BlockingIssue[];
169
+ nextActions: string[];
153
170
  advisories: string[];
154
171
  warnings: string[];
155
172
  }
@@ -218,8 +235,10 @@ export interface ToolkitConfig {
218
235
  rnohCliVersion: string;
219
236
  bundleName: string;
220
237
  entryModuleName: string;
238
+ coverageProfile: CoverageProfile;
221
239
  capabilities: ManagedCapabilityRecord[];
222
240
  requestedHarmonyPermissions: string[];
241
+ nextActions: string[];
223
242
  project: {
224
243
  name: string;
225
244
  slug: string;
package/docs/cli-build.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # CLI 构建指南
2
2
 
3
- `v1.7.2` 延续 `verified + preview + experimental` 支持分层,并把四项 preview capability 的现有 `🟠` 缺口收口到明确 `🟡` 子集,其中 `expo55-rnoh082-ui-stack` 仍是唯一 verified 矩阵。
3
+ `v1.8.0` 延续 `verified + preview + experimental` 支持分层,并把四项 preview capability 的现有 `🟠` 缺口收口到明确 `🟡` 子集,其中 `expo55-rnoh082-ui-stack` 仍是唯一 verified 矩阵。
4
4
 
5
5
  CLI 命令集合不变:
6
6
 
@@ -60,6 +60,7 @@ pnpm release:check
60
60
 
61
61
  - hosted CI 默认仍可通过 `EXPO_HARMONY_RELEASE_SKIP_HAP=1` 跳过真实 DevEco HAP 构建
62
62
  - debug / release HAP gate 继续由 capability acceptance、带工具链环境的 CI 或本地验收补齐
63
+ - preview capability 若在报告里显示 `device=yes`,必须同时以 `evidenceSource.device=manual-doc` 对外说明其来源,不得表述成 CI 自动设备验证
63
64
 
64
65
  ## 手动发布
65
66
 
@@ -38,7 +38,7 @@ pnpm run harmony:build:debug
38
38
  如果要继续验证 release 构建,先准备本地签名覆盖文件:
39
39
 
40
40
  ```bash
41
- mkdir -p .expo-harmony
41
+ cp .expo-harmony/signing.local.example.json .expo-harmony/signing.local.json
42
42
  $EDITOR .expo-harmony/signing.local.json
43
43
  pnpm run harmony:env
44
44
  pnpm run harmony:build:release
@@ -46,6 +46,7 @@ pnpm run harmony:build:release
46
46
 
47
47
  说明:
48
48
 
49
+ - `.expo-harmony/signing.local.example.json` 是可直接复制的本地 signing 範本
49
50
  - `.expo-harmony/signing.local.json` 是本地 signing 入口
50
51
  - signing 缺失时,`harmony:env` 和 `harmony:build:release` 会明确提示,不会静默跳过
51
52
 
@@ -35,7 +35,7 @@ pnpm run harmony:build:debug
35
35
  如果要继续验证 release 构建,先准备本地签名覆盖文件:
36
36
 
37
37
  ```bash
38
- mkdir -p .expo-harmony
38
+ cp .expo-harmony/signing.local.example.json .expo-harmony/signing.local.json
39
39
  $EDITOR .expo-harmony/signing.local.json
40
40
  pnpm run harmony:env
41
41
  pnpm run harmony:build:release
@@ -43,6 +43,7 @@ pnpm run harmony:build:release
43
43
 
44
44
  说明:
45
45
 
46
+ - `.expo-harmony/signing.local.example.json` 是可直接复制的本地 signing 範本
46
47
  - `.expo-harmony/signing.local.json` 是本地 signing 入口
47
48
  - toolkit 会把本地 signing 合并进 `harmony/build-profile.json5`
48
49
  - 如果 signing 没配置,`harmony:env` 会明确报缺失;这属于预期阻断
@@ -2,7 +2,12 @@
2
2
 
3
3
  路径:`examples/official-native-capabilities-sample`
4
4
 
5
- 这个 sample 是 `v1.7.2` 的官方 preview native-capability walkthrough。它的目标不是把 preview 能力包装成 `verified`,而是把四项能力当前真实可承诺的 `🟡` 子集集中演示出来,并把 preview 边界收敛到真机 / release 证据,而不是接口缺口。
5
+ 这个 sample 是 `v1.8.0` 的官方 preview native-capability walkthrough。它的目标不是把 preview 能力包装成 `verified`,而是把四项能力当前真实可承诺的 `🟡` 子集集中演示出来,并把 preview 边界收敛到真机 / release 证据,而不是接口缺口。
6
+
7
+ 从 `v1.8.x` 开始,这个 sample 的角色会固定成两层:
8
+
9
+ - combined smoke:负责四项 preview capability 的总回归
10
+ - per-capability acceptance:每条 route 继续单独维护 device / release 记录,不再让 combined smoke 代替单项证据
6
11
 
7
12
  标记说明:
8
13
 
@@ -22,6 +27,10 @@
22
27
  - `/location`
23
28
  - `/camera`
24
29
 
30
+ 对应的逐 capability 追踪板见:
31
+
32
+ - [v1.8.x capability board](../acceptance/v1.8.x-capability-board.md)
33
+
25
34
  ## 每条 route 的真实范围
26
35
 
27
36
  ### `/file-system`
@@ -108,7 +117,7 @@ pnpm run harmony:doctor:strict
108
117
  如果要继续验证 release 构建,先准备本地签名覆盖文件:
109
118
 
110
119
  ```bash
111
- mkdir -p .expo-harmony
120
+ cp .expo-harmony/signing.local.example.json .expo-harmony/signing.local.json
112
121
  $EDITOR .expo-harmony/signing.local.json
113
122
  pnpm run harmony:env
114
123
  pnpm run harmony:build:release
@@ -116,6 +125,7 @@ pnpm run harmony:build:release
116
125
 
117
126
  说明:
118
127
 
128
+ - `.expo-harmony/signing.local.example.json` 是可直接复制的本地 signing 範本
119
129
  - `.expo-harmony/signing.local.json` 是本地 signing 入口
120
130
  - toolkit 会把本地 signing 合并进 `harmony/build-profile.json5`
121
131
  - 即使 release 构建可走通,在没有真机前,这四项能力也仍保持 `preview`
@@ -47,7 +47,7 @@ pnpm run harmony:build:debug
47
47
  如果要继续验证 release 构建,先准备本地签名覆盖文件:
48
48
 
49
49
  ```bash
50
- mkdir -p .expo-harmony
50
+ cp .expo-harmony/signing.local.example.json .expo-harmony/signing.local.json
51
51
  $EDITOR .expo-harmony/signing.local.json
52
52
  pnpm run harmony:env
53
53
  pnpm run harmony:build:release
@@ -55,6 +55,7 @@ pnpm run harmony:build:release
55
55
 
56
56
  说明:
57
57
 
58
+ - `.expo-harmony/signing.local.example.json` 是可直接复制的本地 signing 範本
58
59
  - `.expo-harmony/signing.local.json` 是本地 signing 入口
59
60
  - signing 缺失时,release 构建应明确失败,而不是假成功
60
61