tirtc-device-builder 0.7.3 → 0.8.1

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 (34) hide show
  1. package/.codex-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +26 -0
  3. package/README.md +61 -16
  4. package/bin/tirtc-device-builder.js +33 -1
  5. package/package.json +1 -1
  6. package/skills/tirtc-esp32-builder/SKILL.md +150 -39
  7. package/skills/tirtc-esp32-builder/USAGE.md +17 -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 +10 -2
  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 +21 -2
  22. package/skills/tirtc-esp32-builder/references/firmware-delivery.md +83 -0
  23. package/skills/tirtc-esp32-builder/references/hardware-ir.md +12 -3
  24. package/skills/tirtc-esp32-builder/references/porting-risks.md +29 -1
  25. package/skills/tirtc-esp32-builder/references/product-controls.md +76 -0
  26. package/skills/tirtc-esp32-builder/references/reporting.md +8 -4
  27. package/skills/tirtc-esp32-builder/references/runtime-contract.md +12 -2
  28. package/skills/tirtc-esp32-builder/references/tirtc-platform.md +92 -0
  29. package/skills/tirtc-esp32-builder/references/workflow.md +42 -11
  30. package/skills/tirtc-esp32-builder/scripts/audio_contract.py +2 -0
  31. package/skills/tirtc-esp32-builder/scripts/board_registry.py +677 -0
  32. package/skills/tirtc-esp32-builder/scripts/firmware_identity.py +180 -0
  33. package/skills/tirtc-esp32-builder/scripts/hardware_ir.py +147 -8
  34. package/skills/tirtc-esp32-builder/scripts/runtime_contract.py +122 -1
@@ -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.1 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.1 --version
19
+ npx --yes tirtc-device-builder@0.8.1 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.1、已安装 Skill 的 `VERSION` 为 0.8.1、所选 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,14 +59,17 @@
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
61
66
 
67
+ - Delivery mode (`development flash` or `evidence bundle`): `{{DELIVERY_MODE}}`
68
+ - Application project/version: `{{FIRMWARE_PROJECT_VERSION}}`
62
69
  - Serial port/chip: `{{SERIAL_TARGET}}`
63
70
  - Project-relative firmware artifacts: `{{FIRMWARE_ARTIFACTS}}`
64
- - Firmware SHA-256: `{{FIRMWARE_SHA256}}`
71
+ - Application-BIN SHA-256: `{{FIRMWARE_BIN_SHA256}}`
72
+ - Descriptor/full ELF SHA-256: `{{FIRMWARE_ELF_SHA256}}`
65
73
  - Flash command/result: `{{FLASH_RESULT}}`
66
74
 
67
75
  ## Artifact-bound runtime evidence
@@ -6,5 +6,18 @@
6
6
  "app_main": "main/app_main.c",
7
7
  "starter_tirtc": "components/starter_tirtc/src/starter_tirtc.c",
8
8
  "starter_runtime": "components/starter_runtime/src/starter_runtime.c"
9
+ },
10
+ "business": {
11
+ "features": [],
12
+ "protocol_revision": null,
13
+ "session_arbiter": {
14
+ "single_foreground_owner": null,
15
+ "pending_capacity": null,
16
+ "generation_guard": null,
17
+ "monotonic_deadlines": null,
18
+ "deferred_lifecycle": null,
19
+ "restore_h5_after_call": null
20
+ },
21
+ "implementation_assertions": []
9
22
  }
10
23
  }
@@ -0,0 +1,4 @@
1
+ {
2
+ "schema_version": 1,
3
+ "boards": []
4
+ }
@@ -36,6 +36,14 @@ directions are active, uses the hardware clock rate, and maps two distinct TDM
36
36
  signals. Implementation assertions must still bind the contract to the paired
37
37
  channel setup, AEC library configuration, and exact slot extraction code.
38
38
 
39
+ AEC is not optional when Hardware IR requests `ai_talk`, `device_call`, or
40
+ `wechat_voip`. For those features, `echo_cancellation.enabled=false`, missing
41
+ playback-reference wiring, or non-simultaneous capture/playback is a hard
42
+ `BLOCKED` result. Do not silently downgrade the product to push-to-talk. The
43
+ contract verifier exports structured `simultaneous_capture_playback` and
44
+ `echo_cancellation_enabled` results so the Hardware IR assessor enforces this
45
+ rule rather than trusting summary text.
46
+
39
47
  ## Mandatory gate
40
48
 
41
49
  Run the gate before claiming an audio-capable build:
@@ -0,0 +1,72 @@
1
+ # Board knowledge and identity
2
+
3
+ Use this reference when identifying a board, reusing an existing adapter, or
4
+ capturing lessons after bring-up. The registry is curated, versioned input. It
5
+ does not train a model or mutate an installed Skill from conversation history.
6
+
7
+ ## Identity boundary
8
+
9
+ An ESP32 can report its SoC target, revision, Flash/PSRAM, MAC and sometimes its
10
+ module. Board firmware can probe camera PIDs, codec chip IDs and other bus
11
+ devices. These observations identify components, not necessarily the carrier
12
+ board sales model, PCB marking, hardware revision, wiring, power topology or
13
+ acoustic path. Obtain those facts from the developer and board documents.
14
+
15
+ Create a project-local identity file, merge the developer declaration with safe
16
+ read-only observations, then query the registry:
17
+
18
+ ```bash
19
+ python3 <skill-dir>/scripts/board_registry.py init-identity \
20
+ --output <project>/board-identity.json
21
+ python3 <skill-dir>/scripts/board_registry.py match \
22
+ --identity <project>/board-identity.json
23
+ ```
24
+
25
+ Use only an `exact` result with `safe_registered_reuse=true` to install a saved
26
+ adapter. `probable` can supply hypotheses while missing revision or probe facts
27
+ are resolved. `component` can supply component-level risks and driver patterns,
28
+ but never GPIO, clock, DMA or adapter values. A conflict creates a new variant.
29
+
30
+ Exact matching requires vendor, model or alias, hardware revision, SoC/resource
31
+ compatibility, and every probe marked `required_for_exact`. Marketing names are
32
+ not enough because vendors may substitute sensors or codecs without renaming a
33
+ product.
34
+
35
+ ## Knowledge scopes
36
+
37
+ - `generic`: an ESP32/TiRTC invariant. Promote only after two independent board
38
+ packages support it and a focused regression test enforces it.
39
+ - `component`: a sensor, codec, amplifier or library observation. Reuse it on a
40
+ different carrier only as a hypothesis until that board supplies evidence.
41
+ - `board`: a fact for one exact package identity. Apply it only to an exact
42
+ match.
43
+
44
+ Registry package status controls reuse:
45
+
46
+ - `knowledge_only`: lessons are usable, but the normal new-board intake remains
47
+ mandatory.
48
+ - `adapter_verified`: the Hardware IR, adapter, configuration and semantic
49
+ contracts are complete enough for the registered-board workflow.
50
+ - `hil_verified`: the reusable package also retains artifact-bound HIL evidence.
51
+
52
+ An older HIL result is provenance, not proof for a newly built artifact.
53
+
54
+ ## Learning loop
55
+
56
+ After the final assessment, create a project-local candidate:
57
+
58
+ ```bash
59
+ python3 <skill-dir>/scripts/board_registry.py candidate \
60
+ --hardware-ir <project>/hardware-ir.json \
61
+ --output <project>/board-knowledge-candidate.json
62
+ ```
63
+
64
+ Review the candidate before promotion. Add exact runtime probes, copy only
65
+ portable project-relative adapter/config/contract inputs, classify each lesson's
66
+ scope, attach the tested artifact SHA-256 for hardware or HIL claims, and add a
67
+ regression test for every generic invariant. Then commit it to a maintained
68
+ registry and publish a new Skill version. An installed Skill never edits itself
69
+ or promotes an observation automatically.
70
+
71
+ Keep credentials, MAC-derived identity, device keys, Wi-Fi secrets, tokens and
72
+ user media out of identity files, candidates and registries.
@@ -9,7 +9,16 @@ Run `hardware_ir.py assess --phase intake --strict` before generation. Hardware
9
9
  | `h5_live_audio` | Microphone path producing G.711 A-law, 8 kHz, mono for stream 10; audio controller/channel ownership and memory budget resolved |
10
10
  | `h5_live_video` | Camera plus the selected MJPEG, H.264, or H.265 profile for stream 11; refresh/key-frame control, realtime pipeline, and memory budget resolved |
11
11
  | `h5_talkback` | G.711 A-law, 8 kHz downlink decode and speaker path for stream 14; audio controller/GPIO ownership and memory budget resolved |
12
- | `ai_talk` | A-law 8 kHz microphone and speaker paths for AI stream 1, started only after `start_session`; audio ownership/channel mapping and memory budget resolved |
12
+ | `ai_talk` | A-law 8 kHz microphone and speaker paths for AI stream 1, started only after `start_session`; simultaneous capture/playback, physical reference, enabled AEC, audio ownership/channel mapping and memory budget resolved |
13
+ | `device_call` | Device-call protocol and arbiter contract plus simultaneous A-law capture/playback, physical reference and enabled AEC |
14
+ | `wechat_voip` | WeChat VoIP protocol and arbiter contract plus simultaneous A-law capture/playback, physical reference and enabled AEC |
15
+
16
+ `ai_talk`, `device_call`, and `wechat_voip` are AEC-required features. They are
17
+ `BLOCKED` when the board cannot capture a playback reference, cannot keep RX/TX
18
+ active together, or has no evidenced AEC implementation. At build time the audio
19
+ contract must explicitly report both simultaneous directions and enabled AEC;
20
+ generic full-duplex labels, a software flag without reference routing, or a
21
+ half-duplex fallback do not satisfy the gate.
13
22
 
14
23
  Hardware identity, wiring, the selected media contract, and the adapter/resource design must be at least `corroborated` to become `READY_TO_PORT`. At intake, `available=true` means a pinned source path can implement the selected profile; it does not claim that the final adapter or physical media path has run. Implementation composition, final ELF policy, runtime memory margin, browser media, and stability belong to the build or HIL phases.
15
24
 
@@ -45,6 +54,7 @@ SoftAP is one Wi-Fi option, not a universal requirement. BLE, SmartConfig, facto
45
54
  - Match the TiRTC precompiled SDK platform to the ESP-IDF target and its `manifest/build-contract.env` to the generated configuration.
46
55
  - Keep H5 stream IDs and formats stable unless the user explicitly authorizes a coordinated contract change across the server and consumers.
47
56
  - Start AI media only after the successful `start_session` response; stop and flush media before disconnecting.
57
+ - Route AI, device-call and WeChat VoIP through the same foreground-session arbiter and keep AEC active for the entire simultaneous capture/playback interval.
48
58
  - Copy SDK callback payloads into bounded queues before returning. Perform decoding, playback, HTTP, and lifecycle changes outside callbacks.
49
59
  - Use monotonic timestamps and session generation to reject stale frames and delayed callbacks.
50
60
  - Record runtime evidence with the exact BIN/ELF SHA-256. Use `assess --phase hil --artifact-sha256 <sha>`; documentation verification alone never becomes v2 `HIL_VERIFIED`.
@@ -48,15 +48,34 @@ For an explicitly selected legacy workspace, omit `--expected-kit`; otherwise re
48
48
 
49
49
  The default managed root is `<setup-root>/kits/esp32s3/<kit-version>`. The public ThingConnect workspace remains an optional legacy/development input; the doctor accepts either a Device Kit root, a repository root, or its `thing-connect/` child.
50
50
 
51
+ The managed Kit currently contains the ESP32-S3 H5/AI starter. When the requested
52
+ portfolio includes device-to-device calling or WeChat VoIP and the selected Kit
53
+ does not contain `device-sim-c`, `device-call.md`, `device-voip.md`, and the API
54
+ reference, use a full `tirtc-server-example` checkout pinned to a recorded commit
55
+ for the simulator and porting source. Cloning is an external write and requires
56
+ user authorization. Do not track a moving default branch as build evidence.
57
+
58
+ ESP32-P4 uses a separate `espressif_esp32p4` SDK archive and RISC-V toolchain.
59
+ The managed setup does not install that archive or generate a P4 starter. A P4
60
+ task therefore needs an explicit BSP/network project plus the exact P4 SDK and
61
+ `manifest/build-contract.env`; run Doctor with `--target esp32p4` and never accept
62
+ the packaged S3 archive as a compatible fallback.
63
+
51
64
  SDK resolution is independent after generation: an explicit `--sdk-dir` wins, followed by `<project>/third_party/tirtc`, then the SDK packaged in the resolved Device Kit or legacy workspace. The generated project remains diagnosable after it is moved away from the Kit.
52
65
 
53
- Before copying a generated project to another machine, run:
66
+ For the evidence-bundle mode defined in
67
+ [firmware-delivery.md](firmware-delivery.md), run:
54
68
 
55
69
  ```bash
56
70
  python3 <skill-dir>/scripts/project_portability.py <generated-project> --export
57
71
  ```
58
72
 
59
- Copy source inputs only. Never export `build/`: CMake caches absolute source, toolchain, and Python paths from the originating machine. `managed_components/` may be regenerated from the committed `dependencies.lock`; the bundled `third_party/tirtc` SDK and its build contract must remain in the source package. CMake must invoke shell gates through `bash <script>` so the build does not depend on archive- or filesystem-specific executable bits.
73
+ Run it on a delivery copy and export source inputs only. CMake caches absolute
74
+ source, toolchain, and Python paths under `build/`; `managed_components/` may be
75
+ regenerated from the committed `dependencies.lock`. The bundled
76
+ `third_party/tirtc` SDK and its build contract must remain in the source package.
77
+ CMake must invoke shell gates through `bash <script>` so the build does not
78
+ depend on archive- or filesystem-specific executable bits.
60
79
 
61
80
  The export check also requires Hardware IR, every requested-feature semantic
62
81
  contract, `sdkconfig.defaults`, a referenced custom partition table, and each
@@ -0,0 +1,83 @@
1
+ # Firmware identity and delivery
2
+
3
+ Read this reference whenever the task builds, flashes, hands off, compares, or
4
+ retains firmware. Select the delivery mode from the user's immediate goal; do
5
+ not force a release bundle onto a quick device-test loop.
6
+
7
+ ## Choose one mode explicitly
8
+
9
+ ### Development flash
10
+
11
+ Use this mode for rapid build/flash/monitor iteration on one development
12
+ machine. Keep the normal ESP-IDF `build/` tree and use the ordinary command:
13
+
14
+ ```bash
15
+ idf.py -p <exact-port> flash monitor
16
+ ```
17
+
18
+ Do not create a new archive or make the user manually flash bootloader,
19
+ partition-table and application BIN files when `idf.py flash` can resolve the
20
+ build metadata. Before flashing, record the application version and hash of the
21
+ exact application BIN. A build assessment may bind to a project-relative file
22
+ under `build/`; that evidence remains valid only while that exact file exists.
23
+
24
+ If an experiment produces runtime evidence worth retaining, copy the unchanged
25
+ BIN and matching ELF into `artifacts/` before the next rebuild, record their
26
+ sizes and hashes, and update the report. Copying does not create a new firmware
27
+ identity; a rebuild does.
28
+
29
+ ### Evidence bundle
30
+
31
+ Use this mode for a portable handoff, release candidate, rollback image,
32
+ retained HIL result, or source export. Keep project-relative copies of the exact
33
+ application BIN and ELF, plus bootloader and partition-table files when the
34
+ recipient needs manual flashing. Record byte sizes and SHA-256 values in
35
+ Hardware IR, run strict build assessment, then run
36
+ `project_portability.py --export` on the source-only delivery tree.
37
+
38
+ When promoting a development build into an evidence bundle, copy the unchanged
39
+ files first, then replace every retained `build/...` artifact path in Hardware
40
+ IR and the report with its new `artifacts/...` path. Remove transient build
41
+ records that are not being retained; do not merely add bundle records beside
42
+ stale paths. Rerun strict build assessment against the copied application-BIN
43
+ hash so the assessor reopens the new path. The source-only export is ready only
44
+ when every `build_evidence.artifacts[]` path exists outside `build/` and the
45
+ matching report identifies the same hashes.
46
+
47
+ Only this export workflow requires removal of the machine-bound `build/` tree.
48
+ Do not delete it during active iteration, and never delete a user-owned build
49
+ tree merely to make a report look portable.
50
+
51
+ ## Make firmware self-identifying
52
+
53
+ Set an explicit, human-readable `PROJECT_VER` before `project()` in the top-level
54
+ ESP-IDF `CMakeLists.txt`. Keep it at 31 UTF-8 bytes or fewer so it fits the
55
+ `esp_app_desc_t.version` field with its terminator. Use a label that states what
56
+ the image is: for example `audio-repro.2`, `button-test.1`, `fix.3`, or a release
57
+ version. A build that deliberately preserves a known bug is a reproduction or
58
+ diagnostic image, not a fix.
59
+
60
+ At boot, log `project_name`, `version`, build date/time, IDF version, and the
61
+ full ELF SHA-256 from `esp_app_get_description()` or
62
+ `esp_app_get_elf_sha256()`. If the product has a console, expose the same fields
63
+ through `version` or `status`. This lets a tester distinguish a successful
64
+ flash of the wrong image from a runtime regression.
65
+
66
+ Verify the built application BIN before flash or handoff:
67
+
68
+ ```bash
69
+ python3 <skill-dir>/scripts/firmware_identity.py build/<app>.bin \
70
+ --elf build/<app>.elf --expect-version <expected-version>
71
+ ```
72
+
73
+ The script reads the embedded ESP-IDF application descriptor, verifies the
74
+ explicit version, and confirms that the supplied ELF's full SHA-256 matches the
75
+ descriptor. It accepts an application BIN, not a merged whole-flash image.
76
+
77
+ ## Name hashes precisely
78
+
79
+ The outer application-BIN SHA-256 and the descriptor's full ELF SHA-256 identify
80
+ different files. Record both with unambiguous labels; do not call either one
81
+ simply “firmware hash.” Bind Hardware IR artifacts and HIL observations to the
82
+ exact retained artifact SHA required by the assessor, and include the boot-log
83
+ version/full ELF hash so the physical device can be reconciled with that record.
@@ -42,16 +42,23 @@ The IR contains:
42
42
  - exact board identity, module, Flash/PSRAM, ESP-IDF, TiRTC SDK and build contract;
43
43
  - camera identity evidence plus `video_profiles[]` and `selected_video_profile`;
44
44
  - audio input/output paths;
45
- - `hardware_resources` for I2C, I2S/GPIO ownership, audio channel mapping, camera realtime policy, and memory budget;
45
+ - `hardware_resources` for I2C, I2S/GPIO ownership, audio channel mapping,
46
+ full-duplex/AEC capability, camera realtime policy, and memory budget;
46
47
  - project-relative `hardware_resources.audio_semantic_contract` for every project requesting audio;
47
48
  - project-relative `hardware_resources.video_semantic_contract` for every project requesting video;
48
- - project-relative `hardware_resources.runtime_semantic_contract` for every generated H5/AI project;
49
+ - project-relative `hardware_resources.runtime_semantic_contract` for every generated H5/AI/call/VoIP project;
49
50
  - `onboarding.wifi_credentials` with selectable SoftAP/BLE/SmartConfig/factory/development/custom methods;
50
51
  - selectable ThingConnect binding methods plus stored-binding states and reset control;
51
52
  - requested features;
52
53
  - optional `runtime_evidence[]`, each bound to a full firmware SHA-256.
53
54
  - `build_evidence.artifacts[]` containing each accepted BIN/ELF path, byte size, and full SHA-256.
54
55
 
56
+ When `ai_talk`, `device_call`, or `wechat_voip` is requested,
57
+ `hardware_resources.duplex_audio` must establish simultaneous capture/playback,
58
+ an actual playback-reference signal, and an AEC implementation. Unknown values
59
+ remain `NEEDS_CONFIRMATION`; a confirmed missing value is `BLOCKED`. Build/HIL
60
+ assessment also requires the project audio semantic gate to prove enabled AEC.
61
+
55
62
  The selected Wi-Fi method must be available and corroborated, credentials must remain outside tracked source, and reprovisioning must be defined. A board without SoftAP is valid when another selected method meets those conditions.
56
63
 
57
64
  The selected video profile controls assessment. An unselected H.264 fallback cannot make an MJPEG target pass, and missing H.264 cannot block an evidenced MJPEG target.
@@ -77,7 +84,9 @@ python3 <skill-dir>/scripts/hardware_ir.py assess hardware-ir.json \
77
84
  --phase hil --artifact-sha256 <64-character-sha256> --strict
78
85
  ```
79
86
 
80
- H5 features require matching L5 evidence; AI requires matching L6 evidence. Evidence from an older firmware remains provenance but does not verify the current artifact.
87
+ H5 features require matching L5 evidence; AI, device-call and WeChat VoIP
88
+ require matching L6 evidence. Evidence from an older firmware remains
89
+ provenance but does not verify the current artifact.
81
90
 
82
91
  ## Intake quality
83
92
 
@@ -62,9 +62,37 @@ Disable Wi-Fi power saving for the realtime baseline unless the product contract
62
62
 
63
63
  Confirm SDK send return semantics and callback payload lifetimes from the selected SDK version. Keep SDK callbacks bounded and copy payloads before returning.
64
64
 
65
+ ## Repeated or duplicated downlink audio
66
+
67
+ Do not label a build as a fix merely because it adds logs or makes the symptom
68
+ less frequent. First produce a self-identifying reproduction build, then count
69
+ the same frame across four boundaries: TiRTC receive callback, accepted queue
70
+ item, playback dequeue, and codec/I2S write. Include mode and connection
71
+ generation, stream/media type, payload length, bounded queue depth/drop counters,
72
+ and an available transport sequence or timestamp. Sample payload hashes only as
73
+ diagnostic evidence; do not blindly discard equal hashes because silence or
74
+ legitimately repeated encoded frames may be identical.
75
+
76
+ Carry one local trace ID from the accepted callback through queue and playback,
77
+ and record write offset, requested bytes, returned bytes, and cumulative bytes.
78
+ Multiple codec/I2S writes are valid when a frame is deliberately chunked or a
79
+ partial write advances the offset; a local duplication exists only when the
80
+ same byte/sample range is committed more than once or cumulative output exceeds
81
+ the frame's decoded contract. Repeated callbacks with the same available
82
+ transport identity point upstream or into SDK delivery. Unique downlink frames
83
+ heard repeatedly require checking resampling, DMA/I2S replay and acoustic
84
+ feedback separately. On stop/reconnect, reject stale generations and drain or
85
+ invalidate queued audio. Verify the correction with repeated AI sessions, rapid
86
+ stop/start, delayed callbacks and H5 recovery against the exact reproduction and
87
+ candidate-fix firmware identities.
88
+
65
89
  ## Artifact discipline
66
90
 
67
- Record BIN/ELF SHA-256 for every build used in HIL. Runtime evidence applies only to the exact artifact. Diagnose one failing invariant, make the smallest correction, rerun that layer, and preserve the comparison in the report.
91
+ Follow [firmware-delivery.md](firmware-delivery.md). Record the explicit firmware
92
+ version, application-BIN SHA-256 and descriptor/full ELF SHA-256 for every build
93
+ used in HIL. Runtime evidence applies only to the exact artifact. Diagnose one
94
+ failing invariant, make the smallest correction, rerun that layer, and preserve
95
+ the comparison in the report.
68
96
 
69
97
  Local intermediate snapshots may be ignored, but the Hardware IR, semantic
70
98
  contracts, `dependencies.lock`, custom partition input, and the artifact named
@@ -0,0 +1,76 @@
1
+ # Product controls, reset, and power
2
+
3
+ Read this reference when the product has buttons, touch inputs, reset controls,
4
+ power keys, wake sources, or enclosure labels. Concrete pins and electrical
5
+ behavior belong in the exact board/carrier evidence and adapter, never in this
6
+ Skill.
7
+
8
+ ## Identify the physical product, not just the baseboard
9
+
10
+ A retail or battery-powered device may combine a compute board with a carrier,
11
+ PMIC, latch circuit, flex PCB, or enclosure controls that are absent from the
12
+ baseboard schematic. When a user's physical observation conflicts with the
13
+ available schematic, treat it as evidence of a missing or different variant.
14
+ Do not declare a working control nonexistent. Request or inspect the exact
15
+ carrier schematic, PCB markings, photographs, BSP definitions, or safe probe
16
+ results and keep the unresolved mapping explicit.
17
+
18
+ Classify each physical label before assigning software behavior:
19
+
20
+ - MCU-readable GPIO button or touch input;
21
+ - boot-strapping input;
22
+ - reset/enable line;
23
+ - PMIC or hardware power-latch control;
24
+ - I/O-expander input;
25
+ - indicator with no input function;
26
+ - unknown control on a missing board layer.
27
+
28
+ For an MCU-readable input, record the SoC GPIO, active level, external pull,
29
+ debounce requirement, shared owner, wake capability, and any strapping role.
30
+ Holding a strapping pin during reset can select a boot mode. A reset/enable line
31
+ normally resets the MCU and cannot also be treated as an application button.
32
+ A PMIC/latch power key and an MCU “enter deep sleep” action are different
33
+ product contracts; do not substitute one for the other without circuit evidence.
34
+
35
+ ## Keep controls behind a narrow adapter
36
+
37
+ Use a board/product-controls component to own GPIO setup, polling or ISR work,
38
+ debounce, gestures, and boot-held suppression. It emits bounded product intents
39
+ such as `AI_TOGGLE_REQUESTED`; it does not call TiRTC, HTTP, MQTT, media, or
40
+ session lifecycle APIs from an ISR or polling callback.
41
+
42
+ Prefer one `AI_TOGGLE_REQUESTED` event whose start/stop decision is serialized by
43
+ the state-owning runtime. If the existing runtime exposes only separate start
44
+ and stop intents, the adapter may map a public state snapshot to one of them,
45
+ but the runtime must validate the intent again against its authoritative state.
46
+ Define whether rapid gestures are queued, coalesced, or rejected so two reads of
47
+ the same stale snapshot cannot silently violate the product behavior.
48
+
49
+ The runtime remains responsible for session generation, callback ordering,
50
+ media ownership, timeouts, cleanup, and late-event rejection. A toggle must
51
+ define behavior for waiting, connecting, active, stopping, H5-owned, and
52
+ error/recovery states instead of maintaining a second Boolean inside the button
53
+ driver.
54
+
55
+ ## Deterministic button behavior
56
+
57
+ For a mechanical active-low or active-high input, require all of the following:
58
+
59
+ - a stable active interval before one press event;
60
+ - no repeat event until a stable release;
61
+ - a button already held during boot must be released before it can trigger;
62
+ - short/long-press thresholds have an explicit product meaning;
63
+ - queue overflow or rejected intents are logged and recover safely;
64
+ - polling tasks and ISRs stay bounded and never block on network/session work.
65
+
66
+ Test boot-held, bounce, rapid repeated presses, press during connection, press
67
+ during active audio, press during stop, delayed SDK callbacks, and recovery to
68
+ H5 or waiting state. For a battery product, separately test cold power-on,
69
+ software shutdown/deep sleep, wake, charging/USB behavior, and reset; a passing
70
+ AI toggle does not prove the power path.
71
+
72
+ Keep debounce and gesture state transitions separable from GPIO/RTOS plumbing
73
+ so host tests can prove boot-held suppression, one event per stable press,
74
+ release re-arming, and the selected rapid-gesture policy. Add a focused runtime
75
+ test for stale or duplicate control intents whenever the runtime performs the
76
+ authoritative state validation.
@@ -13,16 +13,20 @@ Use [the report template](../assets/report-template.md) and preserve separate `P
13
13
  | L3 Online | Wi-Fi provisioning, binding, MQTT, and TiRTC reach ready state |
14
14
  | L4 Media | Camera/microphone/speaker local paths work and counters/measurements are captured |
15
15
  | L5 H5 | Browser receives the declared video/audio and talkback reaches the device |
16
- | L6 AI | Token, WHIP, `start_session`, bidirectional audio, stop, and H5 recovery work |
16
+ | L6 Sessions | AI, device-call and WeChat VoIP requested flows work; simultaneous capture/playback, AEC/double-talk, stop, timeout and H5 recovery are observed separately |
17
17
  | L7 Stability | Requested weak-network, repeated-session, resource, and soak criteria pass |
18
18
 
19
- Run and record the intake assessment before L0, the build assessment with `--project` and the exact artifact SHA-256 at L1, and the HIL assessment only when matching runtime evidence exists. Before assessment, copy final deliverable BIN/ELF files to project-relative `artifacts/` paths and record their actual byte size and SHA-256 in `build_evidence.artifacts[]`; the assessor reopens the file and rejects stale metadata. Missing serial or browser access is a `SKIP` for the affected L2-L7 levels, not an L0/L1 failure.
19
+ Run and record the intake assessment before L0, the build assessment with `--project` and the exact artifact SHA-256 at L1, and the HIL assessment only when matching runtime evidence exists. Follow [firmware-delivery.md](firmware-delivery.md) for artifact location, retention, and mode-transition rules. Record actual byte size and SHA-256 in `build_evidence.artifacts[]`; the assessor reopens the file and rejects stale metadata. Missing serial or browser access is a `SKIP` for the affected L2-L7 levels, not an L0/L1 failure.
20
20
 
21
- Keep `COMPILE_PASS` separate from `BUILD_VERIFIED`. When the compiler succeeds but a required runtime, audio, or video semantic gate fails or is missing, record the compiler result and report the feature and project as blocked. After build assessment, remove `build/` without rebuilding and run `project_portability.py --export`; the source deliverable may retain verified `artifacts/` copies but not a machine-bound build tree. H5 image display is L5 evidence, never an inference from L1.
21
+ Keep `COMPILE_PASS` separate from `BUILD_VERIFIED`. When the compiler succeeds but a required runtime, audio, or video semantic gate fails or is missing, record the compiler result and report the feature and project as blocked. H5 image display is L5 evidence, never an inference from L1.
22
22
 
23
23
  ## Evidence
24
24
 
25
- Record exact board revision, selected media, Wi-Fi, and binding profiles, toolchain and SDK versions, source/adapter revisions, commands, return codes, firmware size and SHA-256, serial port/chip, sanitized log paths, browser or platform observations, and every unavailable dependency.
25
+ Record exact board revision, selected media, Wi-Fi, and binding profiles,
26
+ toolchain and SDK versions, source/adapter revisions, commands, return codes,
27
+ firmware version, application-BIN SHA-256, descriptor/full ELF SHA-256, serial
28
+ port/chip, sanitized log paths, browser or platform observations, and every
29
+ unavailable dependency. Never conflate the BIN and ELF hashes.
26
30
 
27
31
  Runtime evidence belongs to one artifact. Label superseded artifacts and keep their observations as history; do not promote them to the current BIN/ELF. For HIL assessment, add the full SHA-256 to `runtime_evidence` and run `hardware_ir.py assess --phase hil --artifact-sha256 <sha> --strict`.
28
32
 
@@ -1,6 +1,6 @@
1
1
  # TiRTC runtime protocol contract
2
2
 
3
- Use this gate for every generated H5/AI project. It verifies protocol behavior that is
3
+ Use this gate for every generated H5/AI/call/VoIP project. It verifies protocol behavior that is
4
4
  neither a board clock fact nor a camera fact: service discovery wiring, SDK callback
5
5
  lifecycle, stream/media metadata, and AI session negotiation.
6
6
 
@@ -30,5 +30,15 @@ The gate requires all of the following:
30
30
  - AI media starts only after a matching response provides a non-empty session ID and
31
31
  authoritative input/output audio formats matching the implemented codec;
32
32
  - remote `end_session` converges through the runtime control task.
33
+ - requested device-call/WeChat VoIP endpoints, MQTT event names, `call`/`wxcall`
34
+ commands and their pinned `tirtc-server-example` protocol revision are present
35
+ in implementation files;
36
+ - one foreground-session arbiter owns STREAM/AI/CALL/VOIP state, allows one
37
+ pending request, rejects stale generations, uses monotonic deadlines, defers
38
+ lifecycle work outside callbacks and restores H5 after foreground calls.
33
39
 
34
- Compilation without this gate is not an H5/AI `BUILD_VERIFIED` result.
40
+ For device-call or WeChat VoIP, populate the example contract's `business`
41
+ section. An empty `business.features` list remains valid for H5/AI-only projects,
42
+ but cannot satisfy Hardware IR that requests `device_call` or `wechat_voip`.
43
+
44
+ Compilation without this gate is not an H5/AI/call/VoIP `BUILD_VERIFIED` result.