tirtc-device-builder 0.7.3 → 0.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 (30) hide show
  1. package/.codex-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +13 -0
  3. package/README.md +44 -14
  4. package/bin/tirtc-device-builder.js +33 -1
  5. package/package.json +1 -1
  6. package/skills/tirtc-esp32-builder/SKILL.md +139 -39
  7. package/skills/tirtc-esp32-builder/USAGE.md +3 -2
  8. package/skills/tirtc-esp32-builder/VERSION +1 -1
  9. package/skills/tirtc-esp32-builder/agents/openai.yaml +1 -1
  10. package/skills/tirtc-esp32-builder/assets/board-audio-contract.example.json +3 -0
  11. package/skills/tirtc-esp32-builder/assets/board-identity.example.json +16 -0
  12. package/skills/tirtc-esp32-builder/assets/developer-intake-prompt.md +3 -3
  13. package/skills/tirtc-esp32-builder/assets/hardware-ir-v2.example.json +9 -1
  14. package/skills/tirtc-esp32-builder/assets/lckfb-szpi-esp32s3-portable-prompt.md +5 -5
  15. package/skills/tirtc-esp32-builder/assets/report-template.md +6 -1
  16. package/skills/tirtc-esp32-builder/assets/tirtc-runtime-contract.example.json +13 -0
  17. package/skills/tirtc-esp32-builder/knowledge/board-registry.json +4 -0
  18. package/skills/tirtc-esp32-builder/references/audio-contract.md +8 -0
  19. package/skills/tirtc-esp32-builder/references/board-knowledge.md +72 -0
  20. package/skills/tirtc-esp32-builder/references/capability-rules.md +11 -1
  21. package/skills/tirtc-esp32-builder/references/environment.md +13 -0
  22. package/skills/tirtc-esp32-builder/references/hardware-ir.md +12 -3
  23. package/skills/tirtc-esp32-builder/references/reporting.md +1 -1
  24. package/skills/tirtc-esp32-builder/references/runtime-contract.md +12 -2
  25. package/skills/tirtc-esp32-builder/references/tirtc-platform.md +92 -0
  26. package/skills/tirtc-esp32-builder/references/workflow.md +31 -11
  27. package/skills/tirtc-esp32-builder/scripts/audio_contract.py +2 -0
  28. package/skills/tirtc-esp32-builder/scripts/board_registry.py +677 -0
  29. package/skills/tirtc-esp32-builder/scripts/hardware_ir.py +147 -8
  30. package/skills/tirtc-esp32-builder/scripts/runtime_contract.py +122 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tirtc-device-builder",
3
- "version": "0.7.3",
3
+ "version": "0.8.0",
4
4
  "description": "Codex workflows for building and validating TiRTC device firmware across supported chip platforms.",
5
5
  "author": {
6
6
  "name": "TangeAI",
package/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  This project follows Semantic Versioning.
4
4
 
5
+ ## 0.8.0
6
+
7
+ - Add an evidence-backed board identity and curated registry workflow with exact,
8
+ probable and component-only matching plus reviewable knowledge candidates.
9
+ - Extend Hardware IR and runtime contracts to model device-to-device calls and
10
+ WeChat VoIP against a pinned business-protocol revision and unified session
11
+ arbiter.
12
+ - Make simultaneous capture/playback, a physical playback reference and enabled
13
+ AEC mandatory for AI intercom, device calls and WeChat VoIP at intake, build
14
+ and artifact-bound HIL assessment.
15
+ - Add conditional ESP32-P4 target/SDK matching while retaining ESP32-S3 as the
16
+ managed generator path, and document simulator-first four-feature porting.
17
+
5
18
  ## 0.7.3
6
19
 
7
20
  - Make source export reject missing or Git-ignored Hardware IR, requested-feature
package/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  # TiRTC Device Builder
2
2
 
3
- TiRTC Device Builder 用于把 ESP32-S3 开发板接入 TiRTC。输入可以只有开发板型号,也可以包含原理图、BSP、引脚表和外设示例。安装后的 Codex Skill 会先检查环境、整理有依据的硬件事实,再生成独立的 ESP-IDF 工程并完成板级移植和编译。烧录和实机验证只有在开发者明确给出目标串口并授权后才会执行。
3
+ TiRTC Device Builder 用于把 ESP32-S3/ESP32-P4 开发板接入 TiRTC。输入可以只有开发板型号,也可以包含原理图、BSP、引脚表和外设示例。安装后的 Codex Skill 会先检查环境、整理有依据的硬件事实,再生成或移植独立的 ESP-IDF 工程并完成板级适配和编译。烧录和实机验证只有在开发者明确给出目标串口并授权后才会执行。
4
4
 
5
5
  当前仓库提供一个 Skill:
6
6
 
7
7
  | Skill | 平台 | 主要用途 |
8
8
  |---|---|---|
9
- | `tirtc-esp32-builder` | ESP32-S3、ESP-IDF 5.5.x | 环境检查、Hardware IR、工程生成、板级媒体移植、编译、烧录和分层验收 |
9
+ | `tirtc-esp32-builder` | ESP32-S3 / ESP32-P4、ESP-IDF 5.5.x | 板型识别、Hardware IR、工程生成/移植、H5/AI/设备互呼/微信 VoIP、AEC 门禁、编译烧录和分层验收 |
10
10
 
11
- 开发者不需要克隆 `tirtc-server-example`,也不用登录 npm。工程模板、协议文档和 TiRTC SDK 已打包在独立的 ESP32 Device Kit 中,安装命令会自动下载并校验。
11
+ H5/AI 的 ESP32-S3 托管模板、协议文档和 TiRTC SDK 已打包在独立的 ESP32 Device Kit 中,安装时会自动下载并校验。设备互呼或微信 VoIP 的模拟/移植若超出当前 Kit 内容,则需要在用户授权后使用固定 commit 的 `tirtc-server-example` 完整仓库。ESP32-P4 必须使用匹配的 P4 SDK、BSP 与网络方案,不能复用 S3 预编译库。
12
12
 
13
13
  - npm 包:[tirtc-device-builder](https://www.npmjs.com/package/tirtc-device-builder)
14
14
  - GitHub 仓库:[tangeai/tirtc-device-builder](https://github.com/tangeai/tirtc-device-builder)
@@ -85,11 +85,12 @@ Skill 在 Codex 会话启动时被发现。安装完成后,关闭当前 Codex
85
85
  - <原理图、BSP/厂商示例、数据手册或产品页;一行一个>
86
86
 
87
87
  目标:
88
- - 功能:<例如 H5 实时音视频、H5 对讲、AI 双向语音>
88
+ - 功能:<例如 H5 实时音视频/对讲、AI 对讲、设备呼设备、微信 VoIP>
89
89
  - 平台/Web 视频:MJPEG、H264、H265
90
90
  - 板级视频选择:<MJPEG/H264/H265/根据硬件证据选择一种>
91
91
  - Wi-Fi:<指定方案/根据 BSP 选择>
92
92
  - 设备绑定:<指定方案/根据平台合同选择>
93
+ - AEC:AI 对讲、设备呼设备、微信 VoIP 必须全双工并启用 AEC
93
94
 
94
95
  工程:<输出目录或现有工程的工作区相对路径>
95
96
 
@@ -110,6 +111,35 @@ H5 对讲和 AI 双向对讲。
110
111
 
111
112
  只有型号时,Skill 会先调查公开资料并列出缺口,不会猜测 GPIO、器件或媒体能力。要进入代码移植,通常还需要准确的板卡版本、原理图,以及能在实物上运行的 BSP 或外设示例。
112
113
 
114
+ ### 示例对话
115
+
116
+ 新板卡、先做资料评审:
117
+
118
+ ```text
119
+ 用户:$tirtc-esp32-builder
120
+ 这是 XX 厂商 ESP32-S3 Camera Board Rev.B,资料在 boards/xx-revb/。
121
+ 目标是 H5 音视频、AI 对讲、设备互呼和微信 VoIP;后三项必须 AEC。
122
+ 先识别板型、生成 Hardware IR 并告诉我还缺什么,不烧录。
123
+
124
+ Codex:我会先运行 Doctor,读取原理图/BSP/数据手册,生成 board identity,
125
+ 查询已验证板型注册表;无法从 SoC 判断的 PCB 引脚仍保持未知。
126
+ 随后分别评估四类业务能力,并对 AI/CALL/VOIP 强制检查全双工、
127
+ 回采参考和 AEC,不满足时返回 BLOCKED,不自动降级半双工。
128
+ ```
129
+
130
+ 同板型复用并完成真机验证:
131
+
132
+ ```text
133
+ 用户:$tirtc-esp32-builder
134
+ 使用 boards/identity.json 匹配已验证板型,工程输出到 ports/xx-revb。
135
+ 允许构建和烧录 /dev/ttyACM0,验证 call 另一台设备和 wxcall。
136
+
137
+ Codex:只有 exact identity 且 safe_registered_reuse=true 才复用板级包。
138
+ 我会重新运行 runtime/audio/video 门禁、构建并绑定新 artifact SHA,
139
+ 然后在该串口验证 AI、设备互呼、微信 VoIP 的 AEC/double-talk、
140
+ 会话切换和重连;旧固件的 HIL 结果不会继承给新固件。
141
+ ```
142
+
113
143
  ## 工作范围
114
144
 
115
145
  整个流程从板卡资料核对开始,以分层验收报告结束:
@@ -121,7 +151,7 @@ H5 对讲和 AI 双向对讲。
121
151
  Hardware IR:硬件事实、来源和未知项
122
152
 
123
153
 
124
- 能力门禁:能否支持 H5 / AI
154
+ 能力门禁:H5 / AI / CALL / VOIP / AEC
125
155
 
126
156
 
127
157
  独立 ESP-IDF 工程与板级媒体适配
@@ -138,13 +168,13 @@ Skill 负责:
138
168
  - 检查 Node.js 之外的 ESP-IDF、编译器、TiRTC SDK、工程配置和串口;
139
169
  - 从原理图、BSP、数据手册和实测示例中提取有来源的硬件事实;
140
170
  - 生成并校验 `hardware-ir.json`,把冲突和未知项留在报告里;
141
- - 判断视频、上行音频、下行播放和 AI 会话是否具备移植条件;
171
+ - 判断视频、上行音频、下行播放、AI、设备互呼、微信 VoIP 与 AEC 是否具备移植条件;
142
172
  - 生成带 TiRTC SDK 的独立 ESP-IDF 工程;
143
173
  - 核验发现地址、SDK callback 生命周期、下行格式过滤和 AI 会话响应等运行协议不变量;
144
174
  - 把摄像头、所选 MJPEG/H.264/H.265 路径、麦克风、Codec、I2S、功放和按键接到板级 adapter;
145
175
  - 运行测试和 `idf.py build`,记录固件路径、版本和 SHA-256;
146
176
  - 在用户明确给出芯片、工程和串口后烧录;
147
- - 分别验证启动、上线、本地媒体、H5、AI 和稳定性;
177
+ - 分别验证启动、上线、本地媒体、H5、AI、设备互呼、微信 VoIP、AEC/double-talk 和稳定性;
148
178
  - 输出 `TIRTC_PORTING_REPORT.md`,每一层都标成 `PASS`、`FAIL` 或 `SKIP`。
149
179
 
150
180
  ### Skill 不猜硬件
@@ -252,7 +282,7 @@ board-materials/
252
282
  | 支持自动安装的系统 | Linux、WSL、macOS |
253
283
  | 原生 Windows | 使用 Espressif 官方安装器准备 ESP-IDF,再重新运行检查 |
254
284
 
255
- 当前生成器只支持 ESP32-S3。Flash PSRAM 不是 16 MB / 8 MB 时,需要重新评估 `sdkconfig.defaults`、分区表、DMA 和媒体缓存预算。名称相近的芯片不会被自动当作 ESP32-S3 处理。
285
+ 当前托管自动生成器只提供 ESP32-S3 模板。ESP32-P4 可由 Skill 在已有、证据完整的 P4 BSP/工程上移植,但必须使用 `espressif-esp32p4` SDK、匹配的构建合同和明确的 ESP-Hosted 或以太网方案。Flash 或 PSRAM 容量变化时,需要重新评估 `sdkconfig.defaults`、分区表、DMA 和媒体缓存预算。
256
286
 
257
287
  ### 本机软件
258
288
 
@@ -288,7 +318,7 @@ H5 和 AI 的端到端验收还需要可访问的 ThingConnect 服务、可用
288
318
 
289
319
  ThingConnect 平台和 Web 播放端支持 MJPEG、H.264、H.265;具体开发板必须根据其有证据的媒体路径只选择一种输出 profile。MJPEG 提交完整 JPEG 帧;H.264/H.265 按合同提交 Annex-B access unit、参数集,并实现刷新或关键帧控制。某块板只能输出 MJPEG 不代表平台只支持 MJPEG。板上有摄像头 Sensor,只能证明图像有来源,不能证明浏览器一定能持续出图。
290
320
 
291
- 当前音频基线使用 G.711 A-law、8 kHz、单声道。对讲还要有可靠的下行队列、A-law 解码、Codec/I2S/功放播放和会话停止清理。没有可用的全双工和 AEC 证据时,应按半双工设计 AI 对讲。
321
+ 当前音频基线使用 G.711 A-law、8 kHz、单声道。对讲还要有可靠的下行队列、A-law 解码、Codec/I2S/功放播放和会话停止清理。AI 对讲、设备互呼和微信 VoIP 强制要求全双工、真实播放参考和 AEC;没有证据时必须标记为 `BLOCKED`,不能自动降级为半双工。只有单独请求的 H5 talkback 可在产品合同明确允许时采用半双工。
292
322
 
293
323
  ## 安装方式和目录
294
324
 
@@ -621,7 +651,7 @@ Wi-Fi 配网和 ThingConnect 设备绑定是两套独立流程。绑定可以选
621
651
  | L3 Online | 所选 Wi-Fi 凭证和设备绑定流程、MQTT 与 TiRTC 就绪 |
622
652
  | L4 Media | 摄像头、麦克风、扬声器的本地路径和计数正常 |
623
653
  | L5 H5 | 浏览器持续收到声明的音视频,下行对讲到达实体扬声器 |
624
- | L6 AI | token、WHIP、`start_session`、双向音频、停止和 H5 恢复正常 |
654
+ | L6 AI/CALL/VOIP/AEC | AI、设备互呼、微信 VoIP 的双向音频、AEC/double-talk、停止/超时和 H5 恢复分别通过 |
625
655
  | L7 Stability | 按需求完成反复会话、弱网、资源和长稳测试 |
626
656
 
627
657
  一份完整交付通常包含:
@@ -782,7 +812,7 @@ WSL 默认不一定能看到 USB 设备。按 [Microsoft WSL USB 连接说明](h
782
812
  - 上行:麦克风、采样率、声道、G.711 A-law 编码、发送时机;
783
813
  - 下行:stream 14、队列边界、A-law 解码、I2S/Codec、功放使能、扬声器;
784
814
  - AI:`start_session` 成功后才发送音频,停止时清理旧 generation 数据;
785
- - 全双工:没有 AEC 和硬件证据时先验证半双工。
815
+ - 全双工:AI、设备互呼和微信 VoIP 缺少回采参考或 AEC 证据时直接阻塞;仅 H5 talkback 可按明确的产品合同验证半双工。
786
816
 
787
817
  ### 原生 Windows 无法自动安装 ESP-IDF
788
818
 
@@ -822,7 +852,7 @@ Skill、Device Kit 和 ESP-IDF 会写到 npm 包目录之外,也可能占用
822
852
 
823
853
  ### 能支持 ESP32 之外的芯片吗?
824
854
 
825
- 仓库允许每个平台使用独立 Skill,但当前公开版本只实现 ESP32-S3。泰芯或其他平台需要新增 `skills/<platform-skill>/`,并分别维护 SDK、工具链、板级 adapter 和验收约束。
855
+ 仓库允许每个平台使用独立 Skill。当前公开 Skill 覆盖 ESP32-S3,并支持在证据完整的已有工程上移植 ESP32-P4;托管一键生成仍是 S3。泰芯或其他平台需要新增 `skills/<platform-skill>/`,并分别维护 SDK、工具链、板级 adapter 和验收约束。
826
856
 
827
857
  ## 给仓库维护者
828
858
 
@@ -881,8 +911,8 @@ metadata 中的版本、标签、上游 commit 和期望 SHA-256 必须与本地
881
911
 
882
912
  ```bash
883
913
  npm test
884
- git tag -a v0.7.3 -m "v0.7.3"
885
- git push origin v0.7.3
914
+ git tag -a v0.8.0 -m "v0.8.0"
915
+ git push origin v0.8.0
886
916
  ```
887
917
 
888
918
  不要重复发布已经存在的 npm 版本。版本变化同步更新 `package.json`、`.codex-plugin/plugin.json` 和发布说明。
@@ -38,6 +38,7 @@ Usage:
38
38
  tirtc-device-builder install <platform> [--skills-dir <path>] [--force]
39
39
  tirtc-device-builder setup <platform> [setup options]
40
40
  tirtc-device-builder doctor <platform> [doctor options]
41
+ tirtc-device-builder boards <platform> <list|validate|match|init-identity|candidate> [options]
41
42
  tirtc-device-builder --version
42
43
 
43
44
  Platforms:
@@ -49,6 +50,7 @@ Examples:
49
50
  npx tirtc-device-builder setup esp32 --install
50
51
  npx tirtc-device-builder install esp32 --skills-dir /absolute/path/skills
51
52
  npx tirtc-device-builder doctor esp32 --project /absolute/path/project
53
+ npx tirtc-device-builder boards esp32 match --identity ./board-identity.json
52
54
 
53
55
  Install defaults to ${"$"}{CODEX_HOME:-~/.codex}/skills. Existing skills are
54
56
  preserved unless --force is explicitly supplied. Setup checks are read-only;
@@ -175,6 +177,28 @@ function runDoctor(platform, args) {
175
177
  return Number.isInteger(result.status) ? result.status : 1;
176
178
  }
177
179
 
180
+ function runBoardRegistry(platform, args) {
181
+ const script = join(
182
+ PACKAGE_ROOT,
183
+ "skills",
184
+ platform.skill,
185
+ "scripts",
186
+ "board_registry.py",
187
+ );
188
+ if (!existsSync(script)) {
189
+ return fail(`package is missing board registry script for ${platform.name}`);
190
+ }
191
+
192
+ const python = process.env.PYTHON || "python3";
193
+ const result = spawnSync(python, [script, ...args], {
194
+ stdio: "inherit",
195
+ });
196
+ if (result.error) {
197
+ return fail(`could not run ${python}: ${result.error.message}`);
198
+ }
199
+ return Number.isInteger(result.status) ? result.status : 1;
200
+ }
201
+
178
202
  function main(args) {
179
203
  if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
180
204
  printHelp();
@@ -192,7 +216,12 @@ function main(args) {
192
216
  }
193
217
 
194
218
  const [command, identifier, ...rest] = args;
195
- if (command !== "install" && command !== "doctor" && command !== "setup") {
219
+ if (
220
+ command !== "install" &&
221
+ command !== "doctor" &&
222
+ command !== "setup" &&
223
+ command !== "boards"
224
+ ) {
196
225
  return fail(`unknown command: ${command}; run with --help`);
197
226
  }
198
227
  if (!identifier) {
@@ -206,6 +235,9 @@ function main(args) {
206
235
  if (command === "doctor") {
207
236
  return runDoctor(platform, rest);
208
237
  }
238
+ if (command === "boards") {
239
+ return runBoardRegistry(platform, rest);
240
+ }
209
241
  if (command === "setup") {
210
242
  if (platform.name !== "esp32") {
211
243
  return fail(`setup is not available for platform: ${platform.name}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tirtc-device-builder",
3
- "version": "0.7.3",
3
+ "version": "0.8.0",
4
4
  "description": "Install and run TiRTC device-development skills for Codex.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -1,43 +1,143 @@
1
1
  ---
2
2
  name: tirtc-esp32-builder
3
- description: Check or set up ESP-IDF, then generate, port, build, flash, and validate ThingConnect TiRTC ESP32 projects from a board model, schematic, BSP, pin map, or peripheral examples when H5 live view/talkback or AI intercom is requested. Use for environment diagnosis, supported-board generation, and new-board hardware intake; exclude Linux device-sim-c and server-only work.
3
+ description: Identify, generate, port, build, flash, validate, and capture reusable knowledge for TiRTC ESP32-S3 or ESP32-P4 boards from a model, schematic, BSP, pin map, peripheral examples, or an existing ESP-IDF project. Use for H5 live view/talkback, AI intercom, device-to-device calls, WeChat VoIP, board detection, memory/AEC bring-up, or reusable board registration; exclude server-only work and unrelated embedded projects.
4
4
  ---
5
5
 
6
- # TiRTC Embedded Builder
7
-
8
- Turn board evidence into an evidence-backed ESP-IDF project. Treat the Hardware IR as the single handoff between probabilistic document extraction and deterministic capability, generation, build, and verification steps.
9
-
10
- ## Start
11
-
12
- 1. Read this Skill's `VERSION` file and [environment.md](references/environment.md). Record the `VERSION` value as the installed Skill version; never infer it from the prompt or an npm command run elsewhere. For a first-time setup or a request to check/install prerequisites, prefer `npx tirtc-device-builder@latest setup esp32`. Run its `--install` mode only when the user explicitly authorizes installation at the displayed destinations. The installer may create user-space files but never grants permission for `sudo` or persistent shell-profile edits.
13
- 2. Locate the versioned ESP32 Device Kit root containing `device-sim/` using the explicit input, `TIRTC_THING_CONNECT_ROOT`, the managed setup configuration, or workspace discovery. For a managed Kit, read `manifest.json`, require its exact expected `kit_version`, and treat its manifest and packaged protocol documents as generation facts. An older but structurally complete Kit is not compatible. If the user explicitly supplies an unversioned full ThingConnect source workspace, treat it as legacy input and also read its applicable `AGENTS.md`.
14
- 3. Run the Doctor through the managed environment helper when one exists; otherwise run `python3 <skill-dir>/scripts/doctor.py --expected-idf 5.5 --target esp32s3`. Add `--expected-kit <kit-version> --require-workspace` for managed-Kit generation; a self-contained generated project can instead resolve its bundled SDK through `--project`. Resolve every required failure before claiming build readiness.
15
- 4. Read [workflow.md](references/workflow.md). Select the registered-board, new-board intake, or existing-project branch. The branch is selected when every supplied artifact has been accounted for and the exact board revision is known or explicitly unresolved.
16
- 5. Read [hardware-ir.md](references/hardware-ir.md) when a Hardware IR must be created or updated. New intake uses schema v2; schema v1 remains readable for existing H.264 projects. Record a source and verification level for every hardware fact that affects a requested feature.
17
- 6. Run `python3 <skill-dir>/scripts/hardware_ir.py validate <hardware-ir.json>` and then `assess --phase intake --strict`. `READY_TO_PORT` means the evidence is sufficient to design the adapter without guessing wiring or changing an unapproved public contract; it does not require a final ELF or runtime measurements.
18
-
19
- Before stopping on `NEEDS_CONFIRMATION`, classify every unresolved fact as `source_resolvable`, `implementation_resolvable`, `build_resolvable`, `hil_resolvable`, or `user_blocked`. Resolve source facts by inspection. For implementation/build facts, record the evidenced design plan at `corroborated`, generate a compile-safe adapter, and verify it at L1. Defer HIL-only measurements to L2-L7 when hardware access is unavailable. Stop before implementation only for `user_blocked` facts such as unknown wiring or identity, a missing product choice, an unavailable SDK, or a required public-contract change.
20
-
21
- ## Build the project
22
-
23
- Run `<device-kit-root>/device-sim/scripts/create_esp32_project.py` for the current ESP32-S3 H5/AI starter. Keep ThingConnect onboarding, H5, AI, TiRTC lifecycle, callback, stream, and generation behavior in the existing deep modules. Put board-specific camera, microphone, encoder, codec, amplifier, GPIO, DMA, and task behavior behind the `starter_media` seam or a board media adapter owned by it.
24
-
25
- Before changing media code, read [capability-rules.md](references/capability-rules.md) and [porting-risks.md](references/porting-risks.md), then read the repository documents they route to. For requested audio, read [audio-contract.md](references/audio-contract.md); for requested video, read [video-contract.md](references/video-contract.md); for any H5 or AI project, read [runtime-contract.md](references/runtime-contract.md). Complete every applicable project-local semantic gate. Treat platform/Web codec support and board codec selection as separate facts: the current platform contract accepts MJPEG, H.264, and H.265, while each board contract selects exactly one evidenced output profile. A camera sensor alone does not establish H5 video support. Choose half duplex for AI when the supplied hardware and BSP do not establish a usable full-duplex/AEC path.
26
-
27
- Keep the Skill board-agnostic. The prompt supplies product intent and artifact locations; Hardware IR stores evidence; the generated board adapter owns concrete sensors, codecs, pins, clocks, slots, DMA, and task allocation. Never add one board's values to Skill defaults to make an assessment pass.
28
-
29
- Run focused tests before ESP-IDF build. Resolve the TiRTC SDK target and `manifest/build-contract.env` against the generated `sdkconfig`; a mismatched precompiled SDK is a blocked build, not a code-generation problem. Resolve managed components with `idf.py reconfigure`, then validate and install every applicable audio, video, and runtime contract gate. The runtime gate is mandatory for generated H5/AI projects and must prove service-endpoint wiring, deferred lifecycle operations, exact stream/media filtering, AI response validation, and remote `end_session` handling. A value copied from a “typical” header comment or a different sample rate is not clock evidence. A self-declared camera realtime or memory boolean is not video evidence.
30
-
31
- After a successful build, promote only facts actually established by source, compile, semantic, or post-link gates to `build_verified`. Copy the final BIN/ELF needed for delivery into a project-relative `artifacts/` directory, record the actual file path, byte size, and SHA-256 under `build_evidence.artifacts[]`, and run `hardware_ir.py assess --phase build --project <project> --artifact-sha256 <sha256> --strict`. The assessment reopens the recorded file and rejects a missing, stale, size-mismatched, or hash-mismatched artifact. A design plan at `corroborated` can pass intake but cannot pass the build phase. Report a successful compiler invocation as `COMPILE_PASS` when any requested feature gate is blocked; project-wide `BUILD_VERIFIED` requires every requested feature to pass.
32
-
33
- ## Flash and verify
34
-
35
- Flash only when the user requested hardware mutation and the exact serial port and chip have been resolved. When more than one candidate device exists, obtain the target choice before writing. Keep credentials outside generated files and redact device keys, Wi-Fi passwords, MQTT/WHIP tokens, and user media from logs and reports.
36
-
37
- Read [reporting.md](references/reporting.md) before end-to-end verification. Report every acceptance level as `PASS`, `FAIL`, or `SKIP`, with commands and evidence. Bind HIL observations to the exact firmware SHA-256 with `assess --phase hil --artifact-sha256`; an older artifact cannot verify a newer build. A build-only result is not H5 or AI completion; missing hardware, browser, account, service, or network evidence remains an explicit `SKIP` or blocker.
38
-
39
- For HIL assessment, run `hardware_ir.py assess --phase hil --artifact-sha256 <sha256> --strict`. The HIL phase first requires build-verified paths, then promotes only features whose L5/L6 runtime evidence matches that exact artifact.
40
-
41
- ## Finish
42
-
43
- After the final assessment, remove the machine-bound `build/` tree without rebuilding, then run `project_portability.py <project> --export` against the source plus the project-relative `artifacts/` copies. Resolve every missing or Git-ignored required input reported by that check; local intermediate artifacts may remain ignored, but retained build evidence must survive export. Return the generated project path, Hardware IR, capability assessment, build artifacts, flash record when applicable, and `TIRTC_PORTING_REPORT.md`. The task is complete only when every requested feature is either verified at the requested level or named as a blocker with the smallest next action that can resolve it.
6
+ # TiRTC ESP32 Builder
7
+
8
+ Turn board evidence into a verified ESP-IDF product port. Hardware IR is the
9
+ handoff from probabilistic document extraction to deterministic generation and
10
+ gates. The curated board registry preserves reusable results without treating a
11
+ past build as proof for a new artifact.
12
+
13
+ ## 1. Establish the platform and inputs
14
+
15
+ 1. Read this Skill's `VERSION`, then read [environment.md](references/environment.md),
16
+ [workflow.md](references/workflow.md), and
17
+ [TiRTC platform contract](references/tirtc-platform.md). Record the installed
18
+ Skill version rather than inferring it from a prompt or npm output.
19
+ 2. Freeze the requested product features independently: H5 live audio/video and
20
+ talkback, AI intercom, device-to-device calling, and WeChat VoIP. Do not
21
+ silently remove a requested feature because the current starter lacks it.
22
+ 3. Resolve a versioned source of truth. The managed ESP32-S3 Device Kit is the
23
+ default for its packaged capabilities. Device-call/WeChat simulation or
24
+ protocol porting requires a pinned full `tirtc-server-example` checkout when
25
+ those sources are absent from the selected Kit. Clone or download it only
26
+ when the user authorizes that external write. Read applicable repository
27
+ instructions and the exact business documents routed by `workflow.md`.
28
+ 4. Run Doctor for the exact target and SDK package. Managed generation currently
29
+ automates ESP32-S3. ESP32-P4 is valid only with an evidenced P4 BSP/network
30
+ path and the matching `espressif_esp32p4` SDK/build contract; never link the
31
+ S3 archive into a P4 image.
32
+
33
+ ## 2. Identify the board and query knowledge
34
+
35
+ Read [board-knowledge.md](references/board-knowledge.md). Combine developer-
36
+ declared vendor/model/PCB revision with safe observations such as SoC, module,
37
+ Flash/PSRAM, camera PID and codec IDs. The SoC cannot determine carrier-board
38
+ wiring or PCB revision by itself.
39
+
40
+ Run `board_registry.py match` before selecting a workflow branch. Only an exact
41
+ identity with `safe_registered_reuse=true` selects the registered-board branch.
42
+ A probable match supplies hypotheses; a component match supplies only component
43
+ lessons. Any identity conflict creates a new variant and keeps concrete GPIO,
44
+ clock, DMA and task values unresolved.
45
+
46
+ ## 3. Prove the business flows before board porting
47
+
48
+ When device-call or WeChat VoIP is requested, first build and run the pinned
49
+ Linux C simulator with file-backed media. Verify the requested H5, AI, `call
50
+ <device_id> [video|audio]`, and `wxcall [N] [video|audio]` paths plus accept,
51
+ reject, cancel, hangup, timeout and recovery behavior. This establishes the
52
+ business protocol and state model; it does not verify ESP32 hardware.
53
+
54
+ Preserve one process-wide TiRTC lifecycle and one unified Router → Arbiter →
55
+ Coordinator path. STREAM is the H5 baseline; VOIP, AI and CALL are foreground
56
+ owners unless the product contract explicitly proves parallel resources.
57
+ Callbacks enqueue bounded events. A single state-owning task handles HTTP,
58
+ MQTT, connection lifecycle, generation checks and monotonic deadlines.
59
+
60
+ ## 4. Create and assess Hardware IR
61
+
62
+ For a new or changed board, read [hardware-ir.md](references/hardware-ir.md),
63
+ create schema v2, validate it, and run strict intake assessment. Record a source
64
+ and verification level for every identity, pin, clock, slot, media, memory,
65
+ onboarding and business fact. Keep contradictions and unknowns explicit.
66
+
67
+ Classify unresolved facts as `source_resolvable`, `implementation_resolvable`,
68
+ `build_resolvable`, `hil_resolvable`, or `user_blocked`. Resolve all safe source,
69
+ implementation and build facts. Stop before code only for a genuine user choice,
70
+ unknown wiring/identity, unavailable matching SDK, or required public-contract
71
+ change.
72
+
73
+ ## 5. Generate and port
74
+
75
+ Generate a new project without overwriting an existing path. Keep platform
76
+ onboarding, MQTT, TiRTC lifecycle, session routing/arbitration and stream
77
+ contracts in stable modules. Put camera, microphone, encoder, codec, amplifier,
78
+ GPIO, DMA, AEC and realtime task behavior behind `starter_media` or its board
79
+ adapter.
80
+
81
+ Treat AEC as mandatory for `ai_talk`, `device_call`, and `wechat_voip`. Do not
82
+ certify those features through a half-duplex fallback. Hardware IR must prove
83
+ simultaneous capture/playback, a physical playback-reference path, and an
84
+ available AEC implementation. The build gate must additionally prove
85
+ `shared_clock.directions_simultaneous=true` and
86
+ `echo_cancellation.enabled=true`; otherwise the affected feature is `BLOCKED`.
87
+ H5 talkback alone may remain half-duplex only when the requested product
88
+ contract explicitly permits it.
89
+
90
+ Follow the lifecycle from the locked C header: configure pre-init-only options
91
+ such as `TIRTC_OPT_MAX_SEND_BUFFER`, call `TiRtcInit()`, set the device secret and
92
+ client ID from an untracked runtime source, call `TiRtcStart()`, and wait for
93
+ `TIRTC_EVENT_SYS_STARTED`. `TiRtcStart()` returning zero is not readiness.
94
+
95
+ Before media work, read [capability-rules.md](references/capability-rules.md) and
96
+ [porting-risks.md](references/porting-risks.md). For requested audio, video or
97
+ H5/AI/call runtime behavior, read and install the applicable semantic contracts.
98
+ Keep concrete board values in Hardware IR, contracts and adapter files rather
99
+ than Skill defaults.
100
+
101
+ ## 6. Build and assess
102
+
103
+ Run focused tests, resolve managed components, validate the exact SDK
104
+ `manifest/build-contract.env`, install every applicable semantic gate, then run
105
+ the ordinary ESP-IDF build. Requested call/VoIP features must be represented by
106
+ the runtime/business contract and the unified arbiter implementation; an H5/AI-
107
+ only starter cannot reach `BUILD_VERIFIED` for those features.
108
+
109
+ Copy final BIN/ELF deliverables into project-relative `artifacts/`, record actual
110
+ size and SHA-256 in Hardware IR, then run strict build assessment with `--project`
111
+ and that exact hash. Compiler success with a missing feature gate is
112
+ `COMPILE_PASS`, not product completion.
113
+
114
+ ## 7. Flash, verify, and learn
115
+
116
+ Flash only with explicit authorization and an exact serial target. Read
117
+ [reporting.md](references/reporting.md). Record every level as PASS, FAIL or SKIP
118
+ and bind HIL observations to the exact artifact SHA-256. Verify local media,
119
+ H5, AI, device-call, WeChat VoIP, AEC/double-talk when requested, recovery,
120
+ weak-network behavior and stability separately.
121
+
122
+ For every AEC-required flow, run speaker-active near-end speech, far-end-only,
123
+ double-talk, rapid session switching and reconnect cases. Watchdog survival or
124
+ clean audio in one mode cannot substitute for these per-mode observations.
125
+
126
+ After assessment, generate a project-local board-knowledge candidate. Promotion
127
+ is a reviewed repository change: classify lessons as generic, component or exact
128
+ board; attach artifact evidence; add regression tests for generic invariants;
129
+ then publish a new Skill/registry version. Never let an installed Skill mutate
130
+ itself from conversation history.
131
+
132
+ Remove machine-bound `build/` after the final assessment, retain verified
133
+ project-relative artifacts, run `project_portability.py --export`, and return the
134
+ project, Hardware IR, identity match, capability result, artifacts and report.
135
+
136
+ ## Security boundary
137
+
138
+ Keep AccessKey, SecretKey, device keys, Wi-Fi passwords, MQTT/WHIP tokens,
139
+ certificates, MAC-derived identifiers and user media outside source, prompts,
140
+ registries and reports. Inject secrets through an untracked configuration,
141
+ provisioning store, secure NVS or a product keystore. Redact logs. Installation,
142
+ cloning, flashing, erasing NVS, browser/account use and registry promotion each
143
+ retain their own authorization boundary.
@@ -20,7 +20,8 @@ $tirtc-esp32-builder
20
20
  资料:
21
21
  - <原理图、BSP/厂商示例、数据手册和产品页;一行一个>
22
22
 
23
- 目标:<H5 实时音视频、H5 对讲、AI 双向语音等>
23
+ 目标:<H5 实时音视频/对讲、AI 对讲、设备互呼、微信 VoIP>
24
+ AEC:AI、设备互呼、微信 VoIP 必须全双工并启用 AEC
24
25
  视频:<MJPEG/H264/H265/根据证据选择>
25
26
  Wi-Fi 与设备绑定:<指定方案/根据 BSP 和平台合同选择>
26
27
  工程:<输出目录或现有工程的绝对路径>
@@ -53,7 +54,7 @@ $tirtc-esp32-builder 分析 <厂商> <型号> <硬件版本>,目标是 H5 实
53
54
  提供本地资料:
54
55
 
55
56
  ```text
56
- $tirtc-esp32-builder 使用原理图 /path/board.pdf、BSP /path/vendor-project 和一键安装的 Device Kit,为该板生成 TiRTC H5/AI ESP-IDF 工程并编译。
57
+ $tirtc-esp32-builder 使用原理图 /path/board.pdf、BSP /path/vendor-project 和一键安装的 Device Kit,为该板生成 TiRTC H5/AI/CALL/VOIP ESP-IDF 工程并编译;AI/CALL/VOIP 必须通过 AEC 门禁。
57
58
  ```
58
59
 
59
60
  完整实机流程:
@@ -1 +1 @@
1
- 0.7.3
1
+ 0.8.0
@@ -1,4 +1,4 @@
1
1
  interface:
2
2
  display_name: "TiRTC ESP32 Builder"
3
3
  short_description: "从开发板资料生成并验证 TiRTC ESP32 固件"
4
- default_prompt: "Use $tirtc-esp32-builder to analyze my ESP32 board materials and build a TiRTC H5 live-view and AI intercom project."
4
+ default_prompt: "Use $tirtc-esp32-builder to identify my ESP32 board and build an evidence-backed TiRTC H5, AI, device-call, or WeChat VoIP project with mandatory AEC for duplex sessions."
@@ -43,6 +43,9 @@
43
43
  "paired_channels": false,
44
44
  "handoff": "release_before_claim"
45
45
  },
46
+ "echo_cancellation": {
47
+ "enabled": false
48
+ },
46
49
  "implementation_assertions": [
47
50
  {
48
51
  "file": "components/starter_media/src/starter_media.c",
@@ -0,0 +1,16 @@
1
+ {
2
+ "schema_version": 1,
3
+ "declared": {
4
+ "vendor": null,
5
+ "model": null,
6
+ "hardware_revision": null
7
+ },
8
+ "observed": {
9
+ "target": null,
10
+ "module": null,
11
+ "flash_mb": null,
12
+ "psram_mb": null,
13
+ "components": [],
14
+ "probes": []
15
+ }
16
+ }
@@ -20,10 +20,10 @@ $tirtc-esp32-builder
20
20
  - <原理图、BSP/厂商示例、数据手册、产品页等工作区相对路径或固定链接;一行一个>
21
21
 
22
22
  目标:
23
- - <例如:H5 实时视频和声音、H5 语音对讲、AI 双向语音对讲>
23
+ - <例如:H5 实时音视频/对讲、AI 对讲、设备呼设备、微信 VoIP>
24
24
  - 平台/Web 视频能力:<例如 MJPEG、H264、H265;按平台合同填写>
25
25
  - 板级视频选择:<MJPEG/H264/H265/根据硬件证据选择一种>
26
- - 双工或 AEC 的硬要求:<无,初版可半双工/必须全双工或 AEC/未知>
26
+ - 双工或 AEC 的硬要求:AI 对讲、设备呼设备、微信 VoIP 必须全双工并启用 AEC;仅 H5 对讲是否允许半双工:<是/否>
27
27
 
28
28
  接入方式:
29
29
  - Wi-Fi:<选择一种,或写“根据 BSP 选择”>
@@ -37,7 +37,7 @@ $tirtc-esp32-builder
37
37
  2. 把每个未知项标为 source_resolvable、implementation_resolvable、build_resolvable、hil_resolvable 或 user_blocked。先通过资料和固定版本源码解决 source_resolvable;只有 user_blocked 会阻止开始 adapter 开发。
38
38
  3. READY_TO_PORT 表示硬件身份、连接、媒体合同和资源设计已经有证据,足以开始实现;它不要求最终 ELF 或实机数据。可通过实现或构建解决的项目必须继续生成 compile-safe adapter、锁定依赖、运行门禁并编译。
39
39
  4. 移植前核对平台媒体合同、板级选择、板级资源、静态内存预算、配网和绑定状态。音频工程必须生成项目内 `board-audio-contract.json`,在依赖解析后核验每个 codec 的 `(MCLK, sample rate)` 表、I2S mode/controller、TDM slot/物理信号和共享 GPIO handoff;视频工程必须生成项目内 `board-video-contract.json` 并引用 `platform-media-contract.json`,分别证明平台可接受的 profiles 与该板选中的唯一 profile,再核验锁定 camera 组件、传感器白名单、Wi-Fi/camera CPU 隔离、完整帧边界、frame buffers、TiRTC send buffer 和 backpressure。
40
- 5. 所有 H5/AI 工程必须生成 `tirtc-runtime-contract.json`,核验服务发现 endpoint 确实传给 SDK、callback 内不直接调用生命周期 API、下行 stream/media 精确过滤、AI 响应格式和远端 `end_session`。runtime、audio、video 三类适用门禁都要接入普通 `idf.py build`。`resolved=true`、`pipeline_safe=true` 或编译成功不能替代门禁。
40
+ 5. 所有 H5/AI/设备呼叫/微信 VoIP 工程必须生成 `tirtc-runtime-contract.json`,核验服务发现 endpoint 确实传给 SDK、callback 内不直接调用生命周期 API、下行 stream/media 精确过滤、AI 响应格式、远端 `end_session` 和统一会话仲裁。设备呼叫/微信 VoIP 还要固定业务协议 revision 并校验 endpoint、MQTT 事件和 `call`/`wxcall` 命令。AI、设备呼叫和微信 VoIP 必须在 Hardware IR 中证明同时采集播放、真实回采参考与可用 AEC,并由 `board-audio-contract.json` 证明 `directions_simultaneous=true`、`echo_cancellation.enabled=true`;缺任一项直接 BLOCKED,不得自动降级半双工。runtime、audio、video 三类适用门禁都要接入普通 `idf.py build`。`resolved=true`、`pipeline_safe=true` 或编译成功不能替代门禁。
41
41
  6. 将最终 BIN/ELF 复制到项目内 `artifacts/`,记录真实相对路径、大小和 SHA-256,将所评估的 SHA 写入 Hardware IR 的 `build_evidence.artifacts[]`,再使用 `--project` 运行 build 阶段评估并输出 TIRTC_PORTING_REPORT.md。评估后移除机器绑定的 `build/`,运行 `project_portability.py --export`,不得再次构建。区分 `COMPILE_PASS`、请求能力 `BUILD_VERIFIED` 和 L2-L7 实机验收。
42
42
  7. 本轮不访问串口、不烧录、不擦除 NVS;因此缺少启动、浏览器、实体声音和运行时资源数据时,把相应 L2-L7 标为 SKIP,不得阻止 L0/L1。
43
43
  8. Wi-Fi 密码、设备密钥、token、私钥和用户音视频不能写入工程或报告。
@@ -83,6 +83,12 @@
83
83
  "resolved": null,
84
84
  "verification": "extracted"
85
85
  },
86
+ "duplex_audio": {
87
+ "simultaneous_capture_playback": null,
88
+ "playback_reference_available": null,
89
+ "aec_implementation_available": null,
90
+ "verification": "extracted"
91
+ },
86
92
  "camera_realtime": {
87
93
  "pipeline_safe": null,
88
94
  "verification": "extracted"
@@ -122,7 +128,9 @@
122
128
  "h5_live_audio",
123
129
  "h5_live_video",
124
130
  "h5_talkback",
125
- "ai_talk"
131
+ "ai_talk",
132
+ "device_call",
133
+ "wechat_voip"
126
134
  ]
127
135
  }
128
136
  }
@@ -7,7 +7,7 @@ $tirtc-esp32-builder
7
7
  前置条件(必须由开发者在启动本次 Codex 会话前完成,不属于本提示词内的操作):
8
8
 
9
9
  ```bash
10
- npx --yes tirtc-device-builder@0.7.3 setup esp32 --install --force-skill
10
+ npx --yes tirtc-device-builder@0.8.0 setup esp32 --install --force-skill
11
11
  ```
12
12
 
13
13
  该命令只允许在当前用户目录安装固定版本的 Skill、managed ESP32 Device Kit、ESP-IDF 和工具链;禁止 sudo、系统级包变更和修改 shell profile。安装完成后,开发者必须关闭原 Codex 会话,再从本 clean-room 工作区启动一个新会话,然后粘贴本提示词。
@@ -15,11 +15,11 @@ npx --yes tirtc-device-builder@0.7.3 setup esp32 --install --force-skill
15
15
  本轮第一步先只读运行:
16
16
 
17
17
  ```bash
18
- npx --yes tirtc-device-builder@0.7.3 --version
19
- npx --yes tirtc-device-builder@0.7.3 setup esp32
18
+ npx --yes tirtc-device-builder@0.8.0 --version
19
+ npx --yes tirtc-device-builder@0.8.0 setup esp32
20
20
  ```
21
21
 
22
- 必须根据命令的实际输出和本机文件确认:npm 包为 0.7.3、已安装 Skill 的 `VERSION` 为 0.7.3、所选 Device Kit 的 `manifest.json` 中 `kit_version` 为 1.1.1,并且 Doctor 对 `--expected-kit 1.1.1` 输出 `OVERALL: PASS`。Plugin manifest 不属于这种 npm 安装方式的运行时前置条件,不得把不可访问的 Plugin 版本当作阻塞项。如果版本不一致、Skill 是在当前会话启动后才安装,或环境检查未通过,停止并报告前置条件不成立;不要在当前会话中替换 Skill 后继续生成工程。
22
+ 必须根据命令的实际输出和本机文件确认:npm 包为 0.8.0、已安装 Skill 的 `VERSION` 为 0.8.0、所选 Device Kit 的 `manifest.json` 中 `kit_version` 为 1.1.1,并且 Doctor 对 `--expected-kit 1.1.1` 输出 `OVERALL: PASS`。Plugin manifest 不属于这种 npm 安装方式的运行时前置条件,不得把不可访问的 Plugin 版本当作阻塞项。如果版本不一致、Skill 是在当前会话启动后才安装,或环境检查未通过,停止并报告前置条件不成立;不要在当前会话中替换 Skill 后继续生成工程。
23
23
 
24
24
  工作区与 clean-room 边界:
25
25
  - 将启动 Codex 时的当前目录定义为 `WORKSPACE_ROOT`。
@@ -55,7 +55,7 @@ npx --yes tirtc-device-builder@0.7.3 setup esp32
55
55
  - 每次视频调用必须发送一张完整 JPEG,禁止截断帧或裸分片。
56
56
  - 音频 G.711 A-law、8 kHz、mono。
57
57
  - stream:H5 上行 10、视频 11、H5 下行 14、AI 1。
58
- - 初版允许半双工;不得声明未经实机验证的全双工或 AEC
58
+ - AI 对讲必须实现全双工和 AEC;构建阶段必须证明同时采集播放、真实播放参考与 `echo_cancellation.enabled=true`,实机结果仍只能在 L2-L7 验证后声明。
59
59
 
60
60
  接入要求:
61
61
  - SoftAP 配网,凭证保存 NVS。
@@ -27,6 +27,9 @@
27
27
  | H5 live video | | |
28
28
  | H5 talkback | | |
29
29
  | AI intercom | | |
30
+ | Device-to-device call | | |
31
+ | WeChat VoIP | | |
32
+ | Full-duplex AEC/reference path | | |
30
33
 
31
34
  ## Semantic build gates
32
35
 
@@ -37,6 +40,8 @@
37
40
  - Audio contract path/SHA-256: `{{AUDIO_CONTRACT}}`
38
41
  - Codec clock-table result: `{{AUDIO_CLOCK_GATE}}`
39
42
  - I2S mode/controller/slot/handoff result: `{{AUDIO_TOPOLOGY_GATE}}`
43
+ - Simultaneous capture/playback and AEC result: `{{AEC_GATE}}`
44
+ - Device-call/WeChat protocol and arbiter result: `{{BUSINESS_RUNTIME_GATE}}`
40
45
  - Video contract path/SHA-256: `{{VIDEO_CONTRACT}}`
41
46
  - Camera lock/PID/CPU/frame/backpressure result: `{{VIDEO_GATE}}`
42
47
  - Final ELF I2C driver-family result: `{{I2C_ELF_GATE}}`
@@ -54,7 +59,7 @@
54
59
  | L3 Online | | |
55
60
  | L4 Media | | |
56
61
  | L5 H5 | | |
57
- | L6 AI | | |
62
+ | L6 AI/CALL/VOIP/AEC | | |
58
63
  | L7 Stability | | |
59
64
 
60
65
  ## Firmware and flash record