@tencent-rtc/trtc-agent-skills 0.1.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 (205) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +172 -0
  3. package/README.zh.md +173 -0
  4. package/bin/cli.js +434 -0
  5. package/knowledge-base/index.yaml +454 -0
  6. package/knowledge-base/platform-slice-template.md +233 -0
  7. package/knowledge-base/scenario-spec.md +350 -0
  8. package/knowledge-base/scenarios/conference/base/general-conference.md +365 -0
  9. package/knowledge-base/scenarios/conference/base/webinar-conference.md +130 -0
  10. package/knowledge-base/scenarios/conference/medical/1v1-video-consultation.md +145 -0
  11. package/knowledge-base/scenarios/conference/medical/medical-multidoctor-consultation.md +113 -0
  12. package/knowledge-base/scenarios/live/entertainment-live-room.md +118 -0
  13. package/knowledge-base/slice-spec.md +546 -0
  14. package/knowledge-base/slices/conference/web/ai-tools.md +225 -0
  15. package/knowledge-base/slices/conference/web/beauty-effects.md +188 -0
  16. package/knowledge-base/slices/conference/web/device-control.md +338 -0
  17. package/knowledge-base/slices/conference/web/login-auth.md +261 -0
  18. package/knowledge-base/slices/conference/web/network-quality.md +190 -0
  19. package/knowledge-base/slices/conference/web/official-roomkit-api.md +298 -0
  20. package/knowledge-base/slices/conference/web/official-roomkit-login-ui.md +246 -0
  21. package/knowledge-base/slices/conference/web/participant-list.md +238 -0
  22. package/knowledge-base/slices/conference/web/participant-management.md +718 -0
  23. package/knowledge-base/slices/conference/web/prejoin-check.md +293 -0
  24. package/knowledge-base/slices/conference/web/room-call.md +213 -0
  25. package/knowledge-base/slices/conference/web/room-chat.md +426 -0
  26. package/knowledge-base/slices/conference/web/room-lifecycle.md +534 -0
  27. package/knowledge-base/slices/conference/web/room-schedule.md +281 -0
  28. package/knowledge-base/slices/conference/web/screen-share.md +211 -0
  29. package/knowledge-base/slices/conference/web/video-layout.md +675 -0
  30. package/knowledge-base/slices/conference/web/virtual-background.md +197 -0
  31. package/knowledge-base/slices/conference/web/webinar-interaction.md +206 -0
  32. package/knowledge-base/slices/live/anchor-lifecycle.md +122 -0
  33. package/knowledge-base/slices/live/anchor-preview.md +90 -0
  34. package/knowledge-base/slices/live/anchor-room-config.md +104 -0
  35. package/knowledge-base/slices/live/audience-list.md +86 -0
  36. package/knowledge-base/slices/live/audience-manage.md +92 -0
  37. package/knowledge-base/slices/live/audience-watch.md +85 -0
  38. package/knowledge-base/slices/live/audio.md +116 -0
  39. package/knowledge-base/slices/live/barrage.md +88 -0
  40. package/knowledge-base/slices/live/beauty.md +99 -0
  41. package/knowledge-base/slices/live/coguest-apply.md +105 -0
  42. package/knowledge-base/slices/live/device-control.md +91 -0
  43. package/knowledge-base/slices/live/error-codes.md +167 -0
  44. package/knowledge-base/slices/live/gift.md +84 -0
  45. package/knowledge-base/slices/live/ios/.gitkeep +0 -0
  46. package/knowledge-base/slices/live/ios/anchor-lifecycle.md +313 -0
  47. package/knowledge-base/slices/live/ios/anchor-preview.md +228 -0
  48. package/knowledge-base/slices/live/ios/anchor-room-config.md +257 -0
  49. package/knowledge-base/slices/live/ios/audience-list.md +353 -0
  50. package/knowledge-base/slices/live/ios/audience-manage.md +381 -0
  51. package/knowledge-base/slices/live/ios/audience-watch.md +286 -0
  52. package/knowledge-base/slices/live/ios/audio.md +373 -0
  53. package/knowledge-base/slices/live/ios/barrage.md +285 -0
  54. package/knowledge-base/slices/live/ios/beauty.md +323 -0
  55. package/knowledge-base/slices/live/ios/coguest-apply.md +506 -0
  56. package/knowledge-base/slices/live/ios/device-control.md +286 -0
  57. package/knowledge-base/slices/live/ios/error-codes.md +270 -0
  58. package/knowledge-base/slices/live/ios/gift.md +315 -0
  59. package/knowledge-base/slices/live/ios/live-list.md +269 -0
  60. package/knowledge-base/slices/live/ios/login-auth.md +247 -0
  61. package/knowledge-base/slices/live/live-list.md +82 -0
  62. package/knowledge-base/slices/live/login-auth.md +78 -0
  63. package/package.json +34 -0
  64. package/skills/trtc/SKILL.md +326 -0
  65. package/skills/trtc/room-builder/SKILL.md +138 -0
  66. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/README.md +108 -0
  67. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/backend-contract.zh-CN.md +162 -0
  68. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/integration.zh-CN.md +154 -0
  69. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/theme.zh-CN.md +78 -0
  70. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/index.html +12 -0
  71. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/package.json +28 -0
  72. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/postcss.config.js +5 -0
  73. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/App.vue +25 -0
  74. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/ConsultationManagePanel.vue +838 -0
  75. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/LanguageSwitch.vue +102 -0
  76. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/LoadingSpinner.vue +6 -0
  77. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalAlert.vue +34 -0
  78. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalBusinessPanel.vue +148 -0
  79. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalButton.vue +49 -0
  80. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalConfirmDialog.vue +68 -0
  81. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalDataPanel.vue +196 -0
  82. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalRecordPanel.vue +270 -0
  83. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/PrescriptionPanel.vue +363 -0
  84. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/basic-info-config.ts +29 -0
  85. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/lib-generate-test-usersig-es.min.d.ts +4 -0
  86. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/lib-generate-test-usersig-es.min.js +2 -0
  87. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/runtime-config.ts +12 -0
  88. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/env.d.ts +32 -0
  89. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationChatPanel.vue +123 -0
  90. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationMembersPanel.vue +230 -0
  91. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationTranscriptionPanel.vue +135 -0
  92. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationVideoStage.vue +113 -0
  93. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/InviteDoctorDialog.vue +132 -0
  94. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/KickMemberConfirmDialog.vue +50 -0
  95. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/types.ts +77 -0
  96. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationChat.ts +97 -0
  97. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationDevices.ts +48 -0
  98. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationParticipants.ts +121 -0
  99. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationPermissions.ts +25 -0
  100. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/utils.ts +70 -0
  101. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/en-US/index.ts +553 -0
  102. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/index.ts +25 -0
  103. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/medicalTranslate.ts +85 -0
  104. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/state.ts +49 -0
  105. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/zh-CN/index.ts +463 -0
  106. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/main.ts +12 -0
  107. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/mock/appointments.ts +96 -0
  108. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/mock/users.ts +79 -0
  109. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/router/index.ts +63 -0
  110. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/index.ts +25 -0
  111. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/appointmentService.ts +77 -0
  112. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/authService.ts +38 -0
  113. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/launchContext.ts +31 -0
  114. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/userService.ts +35 -0
  115. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/appointmentService.ts +43 -0
  116. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/authService.ts +33 -0
  117. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/userService.ts +43 -0
  118. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/types.ts +135 -0
  119. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/shared/icons.ts +53 -0
  120. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/index.css +106 -0
  121. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/tailwind.css +3 -0
  122. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/theme.css +209 -0
  123. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/auth.ts +50 -0
  124. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/format.ts +24 -0
  125. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/navigation.ts +12 -0
  126. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/session.ts +28 -0
  127. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/DoctorConsultationView.vue +777 -0
  128. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/DoctorDashboardView.vue +678 -0
  129. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/LoginView.vue +441 -0
  130. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientConsultationFinishedView.vue +185 -0
  131. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientConsultationView.vue +1003 -0
  132. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientSelectDoctorView.vue +317 -0
  133. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientWaitingView.vue +454 -0
  134. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/tsconfig.json +21 -0
  135. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/tsconfig.node.json +8 -0
  136. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/vite.config.ts +17 -0
  137. package/skills/trtc/room-builder/templates/scenarios/medical-consultation//346/216/245/345/205/245/350/257/264/346/230/216.md +6 -0
  138. package/skills/trtc/room-builder/tools/render_ai_instructions.py +226 -0
  139. package/skills/trtc-apply/SKILL.md +97 -0
  140. package/skills/trtc-apply/guardrails/apply_lib/__init__.py +0 -0
  141. package/skills/trtc-apply/guardrails/apply_lib/__pycache__/__init__.cpython-313.pyc +0 -0
  142. package/skills/trtc-apply/guardrails/apply_lib/__pycache__/rule_parser.cpython-313.pyc +0 -0
  143. package/skills/trtc-apply/guardrails/apply_lib/rule_parser.py +268 -0
  144. package/skills/trtc-docs/SKILL.md +207 -0
  145. package/skills/trtc-onboarding/SKILL.md +839 -0
  146. package/skills/trtc-onboarding/reference/path-a1-demo.md +103 -0
  147. package/skills/trtc-onboarding/reference/path-a2-integrate.md +693 -0
  148. package/skills/trtc-onboarding/reference/path-b-troubleshoot.md +115 -0
  149. package/skills/trtc-onboarding/reference/path-c-expand.md +43 -0
  150. package/skills/trtc-onboarding/reference/reporting-protocol.md +174 -0
  151. package/skills/trtc-onboarding/reference/supported-matrix.md +100 -0
  152. package/skills/trtc-onboarding/reference/usersig-handling.md +140 -0
  153. package/skills/trtc-search/SKILL.md +221 -0
  154. package/skills/trtc-topic/SKILL.md +638 -0
  155. package/skills/trtc-topic/guardrails/__pycache__/gate_slice_read.cpython-313.pyc +0 -0
  156. package/skills/trtc-topic/guardrails/__pycache__/gate_slice_write.cpython-313.pyc +0 -0
  157. package/skills/trtc-topic/guardrails/__pycache__/stop_require_apply_evidence.cpython-313.pyc +0 -0
  158. package/skills/trtc-topic/guardrails/gate_slice_read.py +133 -0
  159. package/skills/trtc-topic/guardrails/gate_slice_write.py +169 -0
  160. package/skills/trtc-topic/guardrails/stop_require_apply_evidence.py +97 -0
  161. package/skills/trtc-topic/references/execution-units.yaml +58 -0
  162. package/skills/trtc-topic/runtime/README.md +50 -0
  163. package/skills/trtc-topic/runtime/RUNTIME.md +128 -0
  164. package/skills/trtc-topic/runtime/lib/__init__.py +0 -0
  165. package/skills/trtc-topic/runtime/lib/platforms.py +194 -0
  166. package/skills/trtc-topic/runtime/package-lock.json +1211 -0
  167. package/skills/trtc-topic/runtime/package.json +13 -0
  168. package/skills/trtc-topic/runtime/telemetry-bridge.mjs +339 -0
  169. package/skills/trtc-topic/runtime/telemetry_collector.py +293 -0
  170. package/skills/trtc-topic/scripts/STATE-MACHINE-GUIDE.md +186 -0
  171. package/skills/trtc-topic/scripts/__pycache__/apply.cpython-313.pyc +0 -0
  172. package/skills/trtc-topic/scripts/apply.py +581 -0
  173. package/skills/trtc-topic/scripts/finalize_session.py +113 -0
  174. package/skills/trtc-topic/scripts/init_slice_queue.py +96 -0
  175. package/skills/trtc-topic/scripts/lib/__pycache__/state_machine.cpython-313.pyc +0 -0
  176. package/skills/trtc-topic/scripts/lib/state_machine.py +328 -0
  177. package/skills/trtc-topic/scripts/next_slice.py +137 -0
  178. package/skills/trtc-topic/tests/README.md +70 -0
  179. package/skills/trtc-topic/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
  180. package/skills/trtc-topic/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  181. package/skills/trtc-topic/tests/__pycache__/test_apply_cli.cpython-313-pytest-9.0.2.pyc +0 -0
  182. package/skills/trtc-topic/tests/__pycache__/test_apply_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  183. package/skills/trtc-topic/tests/__pycache__/test_end_to_end.cpython-313-pytest-9.0.2.pyc +0 -0
  184. package/skills/trtc-topic/tests/__pycache__/test_end_to_end.cpython-313-pytest-9.0.3.pyc +0 -0
  185. package/skills/trtc-topic/tests/__pycache__/test_finalize_session.cpython-313-pytest-9.0.2.pyc +0 -0
  186. package/skills/trtc-topic/tests/__pycache__/test_finalize_session.cpython-313-pytest-9.0.3.pyc +0 -0
  187. package/skills/trtc-topic/tests/__pycache__/test_gates.cpython-313-pytest-9.0.2.pyc +0 -0
  188. package/skills/trtc-topic/tests/__pycache__/test_gates.cpython-313-pytest-9.0.3.pyc +0 -0
  189. package/skills/trtc-topic/tests/__pycache__/test_session_resolver.cpython-313-pytest-9.0.2.pyc +0 -0
  190. package/skills/trtc-topic/tests/__pycache__/test_session_resolver.cpython-313-pytest-9.0.3.pyc +0 -0
  191. package/skills/trtc-topic/tests/__pycache__/test_state_machine.cpython-313-pytest-9.0.2.pyc +0 -0
  192. package/skills/trtc-topic/tests/__pycache__/test_state_machine.cpython-313-pytest-9.0.3.pyc +0 -0
  193. package/skills/trtc-topic/tests/__pycache__/test_stop_require_apply.cpython-313-pytest-9.0.2.pyc +0 -0
  194. package/skills/trtc-topic/tests/__pycache__/test_stop_require_apply.cpython-313-pytest-9.0.3.pyc +0 -0
  195. package/skills/trtc-topic/tests/__pycache__/test_topic_skill_invariants.cpython-313-pytest-9.0.2.pyc +0 -0
  196. package/skills/trtc-topic/tests/__pycache__/test_topic_skill_invariants.cpython-313-pytest-9.0.3.pyc +0 -0
  197. package/skills/trtc-topic/tests/conftest.py +72 -0
  198. package/skills/trtc-topic/tests/test_apply_cli.py +480 -0
  199. package/skills/trtc-topic/tests/test_end_to_end.py +305 -0
  200. package/skills/trtc-topic/tests/test_finalize_session.py +51 -0
  201. package/skills/trtc-topic/tests/test_gates.py +316 -0
  202. package/skills/trtc-topic/tests/test_session_resolver.py +260 -0
  203. package/skills/trtc-topic/tests/test_state_machine.py +414 -0
  204. package/skills/trtc-topic/tests/test_stop_require_apply.py +99 -0
  205. package/skills/trtc-topic/tests/test_topic_skill_invariants.py +130 -0
@@ -0,0 +1,693 @@
1
+ # Path A2 — Direct Integration
2
+
3
+ > Loaded by `../../trtc-onboarding/SKILL.md` when `intent ∈ {integrate-scenario, integrate-feature}` in `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml`.
4
+ > Before reading this file, SKILL.md must have populated `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml` and passed Stage 1 calibration (including Stage 1.0 conflict resolution if applicable).
5
+
6
+ **Your role: Co-developer.** You scan the project and write code that follows slice-defined best practices. Code-writing runs inside the topic slice loop, where a silent internal structural gate (`apply.py`) runs before each step is declared done — the user never opts into it, and it is never surfaced as a user-facing service. See **"About apply"** below.
7
+
8
+ ## About apply (internal structural gate)
9
+
10
+ A2 does **not** call apply directly. Code-writing happens inside the topic slice loop (A2 hands off to `../../trtc-topic/SKILL.md`), and topic runs `apply.py` as a per-step **structural gate** during that loop. You do not construct any apply request here.
11
+
12
+ What the gate is (and isn't): it is a state-machine forcing function + a lightweight check that code exists and each slice's entry symbol is wired up — it stops the AI from declaring a step done without running a deterministic check. It does **not** verify types, compilation, or runtime correctness. See `../../trtc-apply/SKILL.md` for the exact behavior. Correctness comes from copying slices verbatim and the user confirming in their real project.
13
+
14
+ **Never:**
15
+ - Never tell the user "I'm calling apply" or "apply said X". apply is silent infrastructure.
16
+ - Never declare a step done while topic's state machine is at `apply_failed` — the Stop hook blocks end-of-turn until apply passes.
17
+
18
+ > **Slice discovery vs. slice loading in this path:**
19
+ >
20
+ > - **When the slice ID is already known** (user picked from A2-Q1 menu, or scenario file lists the slice sequence): read `${CLAUDE_PLUGIN_ROOT}/${CLAUDE_PLUGIN_ROOT}/knowledge-base/{slice.file}` and the platform-specific file at `${CLAUDE_PLUGIN_ROOT}/knowledge-base/slices/{product}/{platform}/{ability}.md` directly. Do NOT call search.
21
+ > - **When the slice ID is unknown** (user described a feature in free text, or Stage 0 inferred `target_features` from natural language): call `../../trtc-search/SKILL.md` with `intent=feature` to discover the matching slice ID. Read `response` fields by name — see `../../trtc-search/SKILL.md` → "Response Contract" for the schema.
22
+ > - **When `response.status == 'matched'` and `matches.length == 1`** (and `content_loaded: full`): the slice is found — load the file directly from `matches[0].file_paths_read` and proceed.
23
+ > - **When `response.status == 'matched'` and `matches.length > 1`** (typically with `content_loaded: summary` set per match): present the slice summaries to the user and let them pick which to integrate. Use `AskUserQuestion` with each summary as an option.
24
+ > - **When `response.status == 'no_match'` or `'no_slice'`**: the feature is not covered in the knowledge base. Fall back to `../../trtc-docs/SKILL.md` (which will use llms.txt to find official documentation). Inform the user in their language that the KB doesn't have a detailed integration guide for this feature, and present the official docs instead.
25
+ > - **When `response.status == 'status_planned'`**: the slice is indexed but not yet written. Show the user `matches[0]`'s index-level description, tell them this feature's detailed playbook is still being authored, and offer to fall back to `../../trtc-docs/SKILL.md` for the official-doc equivalent.
26
+ > - **When `response.status == 'ambiguous_product'`**: the user's description plausibly matches multiple products (`response.ambiguous_candidates`). Ask the user to confirm which product, then re-call search with the confirmed `product` set. Do NOT pick silently.
27
+ >
28
+ > Users never see that search was involved — you compose the final answer with the slice content.
29
+
30
+ Recap example:
31
+ > Alright — Live on iOS, adding gift function to your existing project. I see your Podfile already has AtomicXCore and LoginStore is set up, so we'll start at the gift module directly.
32
+
33
+ ## A2-Qpre — Capability overview (Conference only)
34
+
35
+ **Trigger**: `product = conference` AND `intent ∈ {integrate-scenario, integrate-feature}` AND `capability_overview_shown != true` in `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml`.
36
+
37
+ Skip for all other products. Skip whenever `capability_overview_shown = true` (already shown earlier this session, including session reloads and A2-Q4 "Add another feature" loop-backs).
38
+
39
+ **Purpose**: Conference has 16+ capability slices spanning 7 functional groups. Users who are new to the product cannot make informed scenario or feature choices without first understanding what Conference can do. This step provides a structured capability overview before any selection question, replacing the "blind choice" problem with "informed choice."
40
+
41
+ **Execution**:
42
+
43
+ 1. Read `${CLAUDE_PLUGIN_ROOT}/skills/trtc-topic/references/execution-units.yaml` → `scenarios.general-conference.delivery_units` for the authoritative grouping.
44
+ 2. Read `${CLAUDE_PLUGIN_ROOT}/knowledge-base/index.yaml` → `slices` for each slice's `name` and `description` (filter by `id` starting with `conference/`).
45
+ 3. Render the capability overview in the user's language, using this format:
46
+
47
+ ```
48
+ Conference 可以帮你搭建视频会议应用,以下是可集成的全部能力:
49
+
50
+ [会议基础链路]
51
+ 登录与鉴权 — 统一登录态、SDKAppID/UserID/UserSig 鉴权、登录失效/多端顶替处理
52
+ 房间创建、加入、离开与结束 — 会议从创建到结束的主链路
53
+
54
+ [会前准备]
55
+ 入会前设备检查 — 摄像头/麦克风/扬声器的会前检测与本地预览
56
+ 设备控制 — 会中摄像头/麦克风/扬声器的开关、切换、权限处理
57
+
58
+ [音视频与布局]
59
+ 参会人列表与状态 — 参会人列表、角色、发言态、音视频状态
60
+ 视频布局 — 视频区域渲染、布局模板切换、共享突出展示
61
+ 网络质量 — 会中网络状态感知、弱网提示、重连状态
62
+
63
+ [会中协作]
64
+ 屏幕分享 — 桌面端共享屏幕、共享系统音频、共享状态监听
65
+ 会中聊天 — 会议与群组会话绑定、消息收发、历史分页
66
+
67
+ [成员与会控]
68
+ 参会人管理与角色治理 — 角色治理、全员/单成员会控、设备申请审批
69
+ 会中呼叫 — 会议进行中向房外用户发起实时呼叫
70
+
71
+ [预约会议]
72
+ 预约会议 — 未来会议的创建、更新、取消、列表查询与到点提醒
73
+
74
+ [视频增强]
75
+ 美颜效果 — 磨皮/美白/红润等基础美颜
76
+ 虚拟背景 — 背景虚化/替换、模型资源配置、浏览器支持性检测
77
+ ```
78
+
79
+ 4. After the overview, do NOT ask a separate "Did you read this?" question. Proceed directly to A2-Q0 (scenario selection) or A2-Q1 (module selection), depending on `intent`.
80
+ 5. **Persist `capability_overview_shown = true`** to `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml`. Piggyback on the next session write (the Stage 1 confirmed write, or the first Checkpoint write) — do NOT trigger an extra Write just for this field.
81
+
82
+ **Key rules**:
83
+ - The overview is **informational only** — no selection, no `AskUserQuestion`. It exists to give the user mental context for the choices that follow.
84
+ - Group titles come from `execution-units.yaml` `delivery_units[].title`. Slice descriptions come from `index.yaml` `slices[].description`. Do NOT hardcode either — read them at runtime so the overview stays in sync when slices are added/removed.
85
+ - Keep descriptions to one line each. This is a menu card, not a tutorial.
86
+ - If `execution-units.yaml` is missing or has no entry for `general-conference`, fall back to listing all `conference/*` slices from `index.yaml` in declaration order without grouping.
87
+ - This step runs **once per session**, gated by `capability_overview_shown`. On subsequent returns (e.g. A2-Q4 "Add another feature" → loop back to A2-Q1), skip A2-Qpre — the user has already seen the overview.
88
+
89
+ ## A2-Q0 — Scenario vs single-feature branching
90
+
91
+ Skip if `intent = integrate-feature` was already explicitly set (user said "add gift" — no need to ask about scenarios).
92
+
93
+ Ask when `intent = integrate-scenario`, or when the user finished Path A1 of a product that supports scenario-based UI (Conference / Live), or when `target_features` is empty.
94
+
95
+ **If `product = conference`:** A2-Qpre has already been shown (or skipped on reload). The user now has context about what Conference can do. Proceed with scenario selection.
96
+
97
+ Question text: "What kind of experience are you building?"
98
+
99
+ The supported scenarios for v1 are `general-conference` and `1v1-video-consultation`. Do NOT read `index.yaml` to construct this list — these two are aligned with `reference/supported-matrix.md`.
100
+
101
+ These two scenarios are NOT interchangeable: `1v1-video-consultation` is a **medical-only terminal path** that copies a complete healthcare project (see CLAUDE.md → Medical new-project shortcut). It must NEVER be presented as a generic option to non-medical users.
102
+
103
+ ### A2-Q0 high-confidence short-circuit (run FIRST)
104
+
105
+ **Precondition**: A2-Qpre has already been shown (or skipped per its trigger rules). The user has seen the capability overview and now has context for what Conference can do.
106
+
107
+ Before showing any menu, check `scenario` already in `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml` (populated by Stage 0 business-keyword inference, see `SKILL.md` → Business-scenario → product mapping table):
108
+
109
+ | Inferred `scenario` | Confidence signal (from user's first message) | Action |
110
+ |---|---|---|
111
+ | `general-conference` | "企业内部会议", "部门例会", "团队会议", "团队协作", "corporate meeting", "internal meeting", "general meeting", "视频面试", "远程培训", "online classroom" — any non-medical multi-party scenario keyword | Skip the 2-option menu. Show a single confirmation step: recap the scenario fit ("企业内部会议属于通用会议场景,覆盖多人视频会议、屏幕共享、会控、成员管理"), then `AskUserQuestion` with ONE option "Confirm general-conference" (the auto Other lets the user disagree if needed). On confirm → A2-Q0.5. On Other → re-run Stage 0 inference on the free text. |
112
+ | `1v1-video-consultation` | "远程医疗", "在线问诊", "视频问诊", "医患沟通", "telemedicine", "remote consultation" — any medical-domain keyword | Skip the 2-option menu. Show a single confirmation: recap "1v1 视频问诊场景将创建一个完整的问诊项目模板", `AskUserQuestion` with ONE option "Confirm 1v1-video-consultation". On confirm → A2-Q0.5 (medical new-project condition). On Other → re-run Stage 0 inference. |
113
+ | `general-conference` AND `1v1-video-consultation` both inferred (rare, only when first message mixes both domains) | — | Fall through to the 2-option menu below. |
114
+ | Neither inferred (`scenario = null`) or scenario is one not in v1 (e.g. webinar) | — | Fall through to the 2-option menu below (or trigger Integration scenario gate for hidden scenarios). |
115
+
116
+ **Why short-circuit exists**: the two scenarios are domain-segregated. Forcing a non-medical user (e.g. "企业内部会议") to look at "1v1 视频问诊 — copies a medical project" alongside their actual choice creates confusion and erodes trust. When the inference is unambiguous, skip the menu.
117
+
118
+ ### Scenario matching rule (for the fall-through 2-option menu only)
119
+
120
+ When the short-circuit does NOT trigger (i.e. `scenario` is null, or the user described a use case that doesn't cleanly map to either v1 scenario):
121
+
122
+ 1. Acknowledge what they asked for
123
+ 2. State that this specific use case does not have a dedicated scenario template
124
+ 3. Show the supported scenarios with their scope description (from the option table below)
125
+ 4. Recommend the best fit — state which one and why it's the closest match
126
+ 5. Let the user confirm
127
+
128
+ **The key rules:**
129
+ - NEVER silently map an unsupported scenario name to a supported one without explaining
130
+ - NEVER present the medical template as suitable for non-medical use cases (it copies a complete medical-specific project) — the short-circuit above handles unambiguous non-medical inputs; the 2-option menu only runs when intent is genuinely ambiguous
131
+ - When the 2-option menu DOES run (genuine ambiguity), show both options with their scope description so the user can make an informed choice
132
+ - Do NOT invent features or promise capabilities that are not in the scenario — only describe what the scenario actually provides
133
+
134
+ **Question text** (for the 2-option menu — runs only when the short-circuit above did NOT fire):
135
+
136
+ "What kind of experience are you building?"
137
+
138
+ | # | Option | Fills |
139
+ |---|--------|-------|
140
+ | 1 | General meeting / 通用会议 (multi-party video meeting — fits most use cases including online education, remote training, team collaboration) | `scenario = general-conference` |
141
+ | 2 | Telemedicine / 1v1 视频问诊 (medical consultation template — ONLY for healthcare scenarios, copies a complete medical project) | `scenario = 1v1-video-consultation` |
142
+
143
+ (2 options only. "Type something" is auto-provided by AskUserQuestion's Other — do NOT add it as an explicit option. If free-text input maps to an unsupported scenario, trigger Integration scenario gate.)
144
+
145
+ **Free-text handling**: if the user's free text maps to a hidden scenario (e.g. "webinar", "研讨会", "multidoctor", "会诊"), trigger the Integration scenario gate recap from `onboarding/SKILL.md` → `### Integration scenario gate` instead of falling through to A2-Q1.
146
+
147
+ **After user selects a conference scenario** → proceed immediately to A2-Q0.5 (Conference integration mode). Do NOT skip A2-Q0.5.
148
+
149
+ **If `product = live`:**
150
+
151
+ | # | Option | Fills |
152
+ |---|--------|-------|
153
+ | 1 | Entertainment live room (gifts, barrage, co-guest) | `scenario = entertainment-live-room` |
154
+ | 2 | E-commerce live streaming | `scenario = ecommerce-live` |
155
+ | 3 | I want to pick individual features myself | fall through to A2-Q1 |
156
+ | 4 | Type something | free-text |
157
+
158
+ ## A2-Q0.5 — Conference integration mode (conference scenarios only)
159
+
160
+ **Trigger**: the user picked one of the conference scenarios in A2-Q0
161
+ (`general-conference` / `webinar-conference` / `1v1-video-consultation` / `medical-multidoctor-consultation`).
162
+ Skip for all other products and for the A2-Q1 fall-through branch.
163
+
164
+ **Purpose**: decide how topic will integrate the conference UI — as the
165
+ official RoomKit UI, or as headless composables where the user supplies their
166
+ own UI. Ask BEFORE handing off to topic, so topic reads `ui_mode` from the
167
+ session file at skill entry.
168
+
169
+ **User-facing wording rule**: Do not expose implementation labels such as
170
+ `A2-Q0.5`, `ui_mode`, "CLAUDE.md", "shortcut", "bypass", "theme workflow",
171
+ "normal UI mode selection", or "topic handoff" in chat. Present this as a
172
+ product choice the customer is making, not as internal routing.
173
+
174
+ ### Medical new-project condition
175
+
176
+ When ALL of the following are true, use the **medical-specific 3-option menu** below instead of the default 3-option menu:
177
+
178
+ - `scenario = 1v1-video-consultation`
179
+ - `project_state.has_trtc_dep = false` (no existing TRTC project detected — indicates a brand-new project)
180
+
181
+ For new medical consultation projects, the recommended path is copying the
182
+ bundled template project directly. This is an internal routing rule; do not
183
+ mention the shortcut or CLAUDE.md to the user.
184
+
185
+ **Question text (medical new-project)** (translate to user's language at runtime):
186
+
187
+ > How would you like to start the 1v1 video consultation project?
188
+
189
+ | # | Option | Fills | Next |
190
+ |---|--------|-------|------|
191
+ | 1 | Create a complete runnable consultation project (recommended: includes the full consultation UI, mock data, and config; start with `pnpm install` and `pnpm dev`) | `ui_mode = medical-template` | execute Medical template copy flow (below) |
192
+ | 2 | Add business logic only (composables / stores / types; customer provides UI) | `ui_mode = headless` | hand off to `../../trtc-topic/SKILL.md` (Read) with headless spec |
193
+
194
+ (2 options; "Type something" is auto-provided by AskUserQuestion's Other — do NOT add it as an explicit option per Global rule #2.)
195
+
196
+ **Medical template copy flow (option 1 selected):**
197
+
198
+ 1. Ask the user for the target project directory (or default to a sibling directory like `../medical-consultation/`).
199
+ 2. Copy `${CLAUDE_PLUGIN_ROOT}/skills/trtc/room-builder/templates/scenarios/medical-consultation/` to the target directory, preserving structure exactly as packaged.
200
+ 3. Do NOT read `../../trtc-topic/SKILL.md`, do NOT show scenario capabilities or a slice/module overview, and do NOT run A2-Q0.6. The template path is terminal and does not enter the slice state machine.
201
+ 4. Do NOT generate Vue SFCs, do NOT run any UI/medical verifiers.
202
+ 5. Tell the user to use `pnpm install` for dependencies and `pnpm dev` for local development. Do NOT recommend `npm install` / `npm run dev` (this template starts much slower with npm and can show a blank first screen for a while).
203
+ 6. Set `ui_mode = 'medical-template'`, `current_step = 'template-copied'`, and `status = completed` in `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml`. Write session.
204
+ 7. Do NOT hand off to topic — the template is a complete, self-contained project; no step-by-step slice execution needed.
205
+
206
+ **Medical template user-facing recap**: When option 1 is selected, say something
207
+ like: "好的,我会创建一个完整的 1v1 视频问诊项目,里面已经包含问诊 UI、模拟数据和基础配置。创建完成后用 `pnpm install` 和 `pnpm dev` 启动。" Do not say the user "hit" or "matched" an internal rule.
208
+
209
+ **Medical template default / recommendation rule**: When `scenario = 1v1-video-consultation` AND `project_state.has_trtc_dep = false`, map short confirmations ("推荐", "默认", "1", "模板", "快速", "直接复制") to option 1 (template copy). Only proceed to options 2–3 when the user explicitly asks for a different integration approach.
210
+
211
+ **Medical template resume rule**: If a later turn resumes a session with
212
+ `ui_mode = medical-template`, `current_step = template-copied`, or
213
+ `status = completed`, do not resume topic and do not re-open the slice sequence.
214
+ Summarize that the complete 1v1 consultation project has already been created
215
+ and repeat only the next commands (`pnpm install`, `pnpm dev`) if useful.
216
+
217
+ ---
218
+
219
+ ### Default 2-option menu (non-medical or existing project)
220
+
221
+ When the medical condition above is NOT met (i.e. `scenario != 1v1-video-consultation` OR `project_state.has_trtc_dep = true`), use the standard menu:
222
+
223
+ **Question text** (translate to user's language at runtime):
224
+
225
+ > How do you want to integrate the conference UI?
226
+
227
+ | # | Option | Fills | Next |
228
+ |---|--------|-------|------|
229
+ | 1 | 用官方现成会议界面(推荐,最快)— 直接用官方会议组件,开箱即有完整界面(视频、工具栏、成员列表、聊天等),按钮/挂件/拦截/分享链接/布局通过官方 API 调整 | `ui_mode = official-roomkit` | execute official-roomkit fast path (no topic handoff) |
230
+ | 2 | 只要业务逻辑代码,界面我自己写 — 生成可嵌入的 composables / stores / 类型,**不含任何会议界面**;适合已有设计系统或想完全自己掌控 UI 的项目 | `ui_mode = headless` | hand off to `../../trtc-topic/SKILL.md` (Read) with headless spec |
231
+
232
+ (2 options; "Type something" is auto-provided by AskUserQuestion's Other — do NOT add it as an explicit option per Global rule #2.)
233
+
234
+ Persist `ui_mode` to `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml`. Piggyback on the Stage 1 confirmed
235
+ write — do NOT trigger an extra Write just for this field.
236
+
237
+ **Default / recommendation rule (non-medical)**: If the user says "集成会议", "接入会议",
238
+ "快速接入", "官方 UI", "RoomKit", "TUIRoomKit", or asks for UI tweaks on top of
239
+ the official meeting UI, recommend option 1 and map short confirmations
240
+ ("推荐", "默认", "1", "官方") to `ui_mode = official-roomkit`.
241
+
242
+ **Telemedicine default**: maps to room-builder's `one-on-one` scene. Multi-party
243
+ consultation is out of scope for this release (see pending_todos).
244
+
245
+ When a scenario is chosen:
246
+
247
+ 0. **Terminal medical-template guard.** If `scenario = 1v1-video-consultation`
248
+ and `ui_mode = medical-template`, STOP here and execute the Medical template
249
+ copy flow above. Do not run the following topic handoff steps.
250
+
251
+ **Branch by `ui_mode`:**
252
+
253
+ ### If `ui_mode = official-roomkit` (fast path — no topic, no state machine)
254
+
255
+ Official RoomKit mode does NOT hand off to topic. The official component
256
+ packages all 16 capabilities internally — there is no per-slice code to
257
+ generate. Onboarding handles the entire generation inline:
258
+
259
+ 1. **Read these files (and only these):**
260
+ - `${CLAUDE_PLUGIN_ROOT}/knowledge-base/slices/conference/web/official-roomkit-api.md` — complete API signatures, calling sequence, code example, MUST/MUST NOT
261
+ - `${CLAUDE_PLUGIN_ROOT}/knowledge-base/slices/conference/web/official-roomkit-login-ui.md` — login page UI structure and styling constraints
262
+ - `${CLAUDE_PLUGIN_ROOT}/skills/trtc-onboarding/reference/usersig-handling.md` — UserSig credential protocol
263
+
264
+ 2. **Generate the project files in one shot:**
265
+ - Login page (collect/pre-fill sdkAppId + userId, placeholder userSig per the UserSig protocol)
266
+ - Meeting room page (mount `ConferenceMainView`/`ConferenceMainViewH5` inside `UIKitProvider`, wire `conference.*` API calls)
267
+ - Router config (login → meeting transition)
268
+ - Any scenario-specific customizations (e.g., `setWidgetVisible` to hide/show widgets relevant to the chosen scenario)
269
+
270
+ 3. **Run one compliance check** against `official-roomkit-api.md`'s MUST/MUST NOT rules. No need for the full apply pipeline — just verify:
271
+ - No `SecretKey` / `crypto-js` / `pako` in client code
272
+ - `conference.login()` before room operations
273
+ - `setWidgetVisible` / `registerWidget` / `onWill` registered after login, before joinRoom
274
+ - `setFeatureConfig({ shareLink })` after joinRoom succeeds
275
+ - Cleanup functions collected and called on ROOM_LEAVE + ROOM_DISMISS
276
+
277
+ 4. **Save session:** `current_step = 'official-roomkit-done'`, `status = completed`.
278
+
279
+ 4.5. **UserSig fill guidance + run steps (MUST surface to user):** the login
280
+ code always uses a placeholder userSig (the skill never auto-generates one).
281
+ Include the **"如何获取并填入 UserSig"** handoff block from
282
+ `reference/usersig-handling.md` → "Completion handoff", with the real
283
+ file path / variable filled in. Direct the user to the TRTC console to
284
+ generate a test userSig. Also tell the user to install dependencies before
285
+ `dev` (`pnpm install` → `pnpm dev`, or the project's package manager).
286
+
287
+ 5. **Do NOT:**
288
+ - Read any other slice file (room-lifecycle.md, device-control.md, etc.)
289
+ - Hand off to `../../trtc-topic/SKILL.md`
290
+ - Run the state machine (init_slice_queue, next_slice, etc.)
291
+ - Ask A2-Q0.6 (auto-advance policy) — irrelevant without a slice loop
292
+
293
+ ### If `ui_mode = headless` (topic path — state machine)
294
+
295
+ 1. **Handoff to `../../trtc-topic/SKILL.md` via Read.** Read `${CLAUDE_PLUGIN_ROOT}/skills/trtc-topic/SKILL.md` and execute its flow. (Plain Read is the current handoff convention — the §3.5 cross-skill `Skill()` tool handoff was walked back. The real constraints that prevent topic from being silently bypassed live in PreToolUse / Stop hooks and the on-disk state machine, not in how SKILL.md is loaded — so plain Read is sufficient.)
296
+
297
+ Scenario-driven step-by-step execution (reading the scenario file, walking the ordered slice list, loading per-step slices, pausing between steps, verification checklist) is topic's responsibility, not onboarding's. For Vue3 Web no-UI Atomicx/API-direct requests, topic must first run its headless business-flow audit before generating code. Onboarding A2 owns intent identification and scenario selection; once a scenario is picked, topic owns the drive.
298
+ Do not mark `session_context.headless_business_flow_confirmed = true` in onboarding. Topic owns that confirmation after it asks the Atomicx no-UI business-flow questions and records the user's answers.
299
+ 2. Pass the scenario id and the current `session_context` (product, platform, credentials if collected, `target_features`, `project_state`) to topic as inputs. Topic will read `${CLAUDE_PLUGIN_ROOT}/${CLAUDE_PLUGIN_ROOT}/knowledge-base/{scenario.file}` itself.
300
+ 3. Save `session_context.current_step = 'topic-handoff'` and `session_context.scenario = <chosen-id>` so if the user later returns mid-flow, routing can resume topic from where it paused.
301
+ 4. Do NOT run A2-Q1 (module selection) or A2-Q3 (per-step execution) for scenario-driven flows — those paths are for `intent = integrate-feature` only.
302
+
303
+ Scenario-driven UI presets, default layouts, and scenario-specific A2-Q4 tweaks are not onboarding's concern after handoff — topic handles them (or defers UI adjustments back to the user as a follow-up).
304
+
305
+ If the chosen scenario has `status: planned` in the index: tell the user (in their own language) that the detailed playbook for this scenario is still being written, and offer two options — (a) fall through to A2-Q1 for manual module selection, or (b) let onboarding/topic compose the flow on-the-fly from the available slices. Do NOT silently Read `../../trtc-topic/SKILL.md` in this case; topic needs a concrete scenario file to drive its walk-through.
306
+
307
+ ## A2-Q0.6 — Auto-advance policy (scenario-driven flows only)
308
+
309
+ **Trigger**: the user picked any scenario in A2-Q0 (i.e. `intent = integrate-scenario`).
310
+ Skip for `integrate-feature` flows.
311
+
312
+ **MUST ask — do NOT silently default.** This question must be explicitly asked
313
+ before topic starts the slice loop. The "unset → treated as `pause_each`" rule
314
+ below is a **fail-closed safety net for legacy/interrupted sessions only**, NOT
315
+ a license to skip the question on a fresh scenario flow. Topic re-checks this at
316
+ its Step 3 gate: if `intent = integrate-scenario` and `auto_advance_policy` is
317
+ unset when the loop is about to start, topic bounces back here. (Skip only when
318
+ `ui_mode = official-roomkit` or `medical-template`, which have no slice loop.)
319
+
320
+ **Purpose**: decide how topic paces the slice loop after `apply.py` passes —
321
+ either pause and ask the user 继续? after each slice, or let `apply.py`
322
+ auto-advance the cursor when its checks succeed. Pausing on apply
323
+ **failure** is unconditional regardless of policy — the user always sees a
324
+ break when the code didn't pass the gate.
325
+
326
+ Ask AFTER A2-Q0.5 (so topic reads both `ui_mode` and `auto_advance_policy`
327
+ from the session at skill entry). Piggyback the Stage 1 confirmed write —
328
+ no extra Write just for these fields.
329
+
330
+ **Question text** (translate to user's language at runtime):
331
+
332
+ > Between each step, do you want me to pause and check in with you, or keep going automatically when things look good?
333
+
334
+ | # | Option | Fills | Notes |
335
+ |---|--------|-------|------|
336
+ | 1 | Keep going automatically — only pause if something looks wrong (recommended — fastest, still safe) | `auto_advance_policy = "pause_on_failure"` | Default. apply.py auto-advances cursor on pass |
337
+ | 2 | Pause after every step so I can review what changed (slower but maximum control) | `auto_advance_policy = "pause_each"` | Original behaviour |
338
+ | 3 | Type something | free-text | re-infer |
339
+
340
+ Persist `auto_advance_policy` (root-level field) to `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml`. Unset / unknown
341
+ values are treated as `pause_each` by topic — fail closed.
342
+
343
+ ## A2-Q1 — Module selection (single-feature mode)
344
+
345
+ Trigger: `intent = integrate-feature`, or the user chose "pick individual features" in A2-Q0, or A2-Q0 was skipped.
346
+
347
+ **If `product = conference`:** A2-Qpre has already shown the capability overview. Now present a grouped module selection that mirrors the delivery-unit structure the user just saw. This ensures the selection interaction is visually consistent with the overview — users pick from the same categories they just read about.
348
+
349
+ Question text: "Which capability groups do you want to integrate? (multi-select; [会议基础链路] is required as the foundation)"
350
+
351
+ Use `AskUserQuestion` with `multiSelect: true`. Group options by delivery units from `${CLAUDE_PLUGIN_ROOT}/skills/trtc-topic/references/execution-units.yaml` → `scenarios.general-conference.delivery_units`. Map each delivery unit to one option; the option label is the unit title, the option description lists the included slices by name. Example:
352
+
353
+ | # | Option | Description (auto-generated from unit title + slice names) | Slices |
354
+ |---|--------|-------|--------|
355
+ | 1 | 会议基础链路(必选) | 登录与鉴权 + 房间创建、加入、离开与结束 | conference/login-auth, conference/room-lifecycle |
356
+ | 2 | 会前准备 | 入会前设备检查 + 设备控制 | conference/prejoin-check, conference/device-control |
357
+ | 3 | 音视频与布局 | 参会人列表与状态 + 视频布局 + 网络质量 | conference/participant-list, conference/video-layout, conference/network-quality |
358
+ | 4 | 会中协作 | 屏幕分享 + 会中聊天 | conference/screen-share, conference/room-chat |
359
+ | 5 | 成员与会控 | 参会人管理与角色治理 + 会中呼叫 | conference/participant-management, conference/room-call |
360
+ | 6 | 预约会议 | 预约会议 | conference/room-schedule |
361
+ | 7 | 视频增强 | 美颜效果 + 虚拟背景 | conference/beauty-effects, conference/virtual-background |
362
+
363
+ > **Note**: This table shows 7 options which exceeds `AskUserQuestion`'s 4-option cap. Apply the **A2-Q1 conference grouping merge** below to reduce to 4 options.
364
+
365
+ ### A2-Q1 conference grouping merge
366
+
367
+ When `product = conference`, the 7 delivery units must be merged into 4 options to fit `AskUserQuestion`'s cap. Use this fixed merge:
368
+
369
+ | # | Option | Merged delivery units | Slices |
370
+ |---|--------|----------------------|--------|
371
+ | 1 | 会议基础 + 会前准备(必选) | foundation + prejoin | conference/login-auth, conference/room-lifecycle, conference/prejoin-check, conference/device-control |
372
+ | 2 | 音视频 + 协作 + 会控 | media + collaboration + moderation | conference/participant-list, conference/video-layout, conference/network-quality, conference/screen-share, conference/room-chat, conference/participant-management, conference/room-call |
373
+ | 3 | 预约会议 | schedule | conference/room-schedule |
374
+ | 4 | 视频增强(美颜 + 虚拟背景) | effects | conference/beauty-effects, conference/virtual-background |
375
+
376
+ Option 1 is always selected (required foundation). Options 2–4 are multi-select.
377
+
378
+ **If `product = live`** (or any non-conference product): use the existing flat option list. Pull from `${CLAUDE_PLUGIN_ROOT}/knowledge-base/index.yaml` slices filtered by product. Example for `product = live`:
379
+
380
+ | # | Option | Slice |
381
+ |---|--------|-------|
382
+ | 1 | Login & authentication (required) | live/login-auth |
383
+ | 2 | Anchor broadcast + device control | live/anchor-preview + device-control + anchor-lifecycle |
384
+ | 3 | Audience watch + live list | live/audience-watch + live-list |
385
+ | 4 | Barrage (live comments) | live/barrage |
386
+ | 5 | Gift | live/gift |
387
+ | 6 | Co-guest (audience goes on mic) | live/coguest-apply |
388
+ | 7 | Beauty filters | live/beauty |
389
+ | 8 | Audio effects | live/audio |
390
+ | 9 | Audience management (mute, kick, admin) | live/audience-manage |
391
+ | 10 | Type something | free-text |
392
+
393
+ Use `AskUserQuestion` with `multiSelect: true`.
394
+
395
+ ### A2-Q1.5 — Business decisions collection (per-slice)
396
+
397
+ After A2-Q1 multi-select completes, before advancing to A2-Q2: for each slice in the chosen list, run a **business-decisions collection** pass to fill in the open variables that code generation needs. This step is governed by Hard rule #13 in `../SKILL.md`.
398
+
399
+ **Why this exists:** A slice describes **which APIs** to call. But generating concrete code requires answering business-side questions that are independent of the API surface — e.g. for `conference/login-auth` the slice tells you to call `login(sdkAppId, userId, userSig)`, but it doesn't tell you where `userSig` comes from, what `userId` is mapped from, or where to navigate when the session is lost. Guessing these defaults produces code the user has to rip out. Asking takes one extra `AskUserQuestion` per decision and saves the rewrite.
400
+
401
+ **The decision list comes from each slice's frontmatter, NOT from a hardcoded table here.** Onboarding reads `business_decisions:` in the slice's frontmatter and asks one `AskUserQuestion` per entry. When a slice author adds / removes / changes decisions, the rule follows automatically — no edit needed in this skill.
402
+
403
+ **Slice frontmatter contract:**
404
+
405
+ ```yaml
406
+ ---
407
+ id: conference/login-auth
408
+ platform: web
409
+ business_decisions:
410
+ - key: usersig_source # YAML key — used as session_context lookup
411
+ tier: blocking # blocking (default) | deferrable — see "Decision tiers" below
412
+ question: "UserSig 从哪里获取?" # exact question shown to user (translate at runtime)
413
+ options:
414
+ - { label: "后端签发(生产推荐)", value: "backend" }
415
+ - { label: "控制台临时生成(开发期)", value: "console" }
416
+ # optional fields:
417
+ multi_select: false # default false; true → multi-select question
418
+ destructive_subset: false # default false; true → ask "是否需要破坏性操作?" gate first
419
+ depends_on: # only ask this decision if another decision matches
420
+ key: creation_pattern # ex: "scheduled_features" only asked if "creation_pattern includes scheduled"
421
+ value: ["scheduled", "both"]
422
+ - key: on_session_lost
423
+ tier: deferrable #异常/边界路径 → 不阻塞主流程
424
+ default: redirect-login # deferrable 项 MUST 提供推荐默认值
425
+ question: "登录态失效后页面如何处理?"
426
+ options:
427
+ - { label: "跳回登录页(推荐默认)", value: "redirect-login" }
428
+ - { label: "后台静默重连", value: "auto-refresh" }
429
+ - { label: "弹窗让用户决定", value: "prompt-user" }
430
+ - key: management_features # multi-select example with a baseline
431
+ tier: blocking
432
+ multi_select: true
433
+ baseline: ["list"] # always-generated values, NOT shown as options
434
+ question: "主持人需要哪些会控权限?(参会人列表默认展示)"
435
+ options: # only the user-selectable extras appear here
436
+ - { label: "管控单个成员", value: "single-control" }
437
+ - { label: "全场管控", value: "all-room" }
438
+ - { label: "成员身份管理", value: "role-and-kick" }
439
+ ---
440
+ ```
441
+
442
+ **Baseline values (`baseline` field, multi-select only):**
443
+
444
+ 某些多选决策里存在"基础项"——它是该能力的前提,几乎总要生成(如 `participant-management` 的成员列表 `list`)。把基础项和真正的可选项放进同一个多选框,会造成颗粒度不一致(用户在"前提"和"权限"之间纠结)。
445
+
446
+ 解决办法:用 `baseline: [...]` 声明这些始终生成的值。规则:
447
+ - `baseline` 里的值 **不作为 `options` 展示**,A2-Q1.5 不会让用户勾选它们。
448
+ - 采集时,`session_context.business_decisions[<slice-id>][<key>]` 的最终值 = `baseline` ∪ 用户在 `options` 里勾选的值。
449
+ - 即使用户一个 option 都没勾,baseline 值依然写入(保证基础能力被生成)。
450
+ - 仅对 `multi_select: true` 的决策有效;单选决策忽略此字段。
451
+ - 问题文案应点明基础项已默认提供(如"参会人列表默认展示"),避免用户以为漏选。
452
+
453
+ **Decision tiers (`tier` field):**
454
+
455
+ 每个 `business_decisions` 项可声明一个 `tier`,决定"用户没回答时怎么办":
456
+
457
+ | tier | 含义 | 未回答时的行为 |
458
+ |------|------|---------------|
459
+ | `blocking`(默认,可省略) | 决定主流程走哪条代码分支(如 `usersig_source`、`userid_strategy`、`roomid_origin`)。不答就无法正确生成主流程。 | **维持铁律:缺值则 topic STOP,回 A2-Q1.5 问完再继续。** |
460
+ | `deferrable` | 只影响异常/边界路径(如 `on_session_lost`、`passive_exit_target`),不影响登录→建房→进会主链路能否跑通。 | **用 `default` 值先生成 + 注入 `// TODO: 确认<决策项>策略,当前用推荐默认值 <default>` 注释**,主流程跑起来后作为 next step 回填。 |
461
+
462
+ **`deferrable` 契约(slice 作者必须遵守):**
463
+ - 声明 `tier: deferrable` 的项 **MUST 同时提供 `default`**(取 `options` 里的某个 `value`,通常是标注"推荐"的那个)。缺 `default` 的 deferrable 项视为契约错误,apply gate 抛错给 slice 作者。
464
+ - `deferrable` 只能用于异常/边界决策。任何会改变主流程分支结构的决策(建不建房、UserSig 来源、是否匿名)必须是 `blocking`。
465
+ - `default` **不是"AI 猜的值"**,而是 slice 作者显式声明、且会通过 TODO 注释告知用户的推荐值——这与"先生成默认代码、等用户报错再改"的反模式有本质区别(后者是无声的、错了用户才发现)。
466
+
467
+ A2-Q1.5 采集时,`deferrable` 项**仍然会问**(顺序上建议放在该 slice 所有 `blocking` 项之后);只有当用户**显式跳过 / 未答**时才回退到 `default`。也就是说:能问到就用用户的答案,问不到才用 default 兜底跑通主流程。
468
+
469
+ **A2-Q1.5 execution algorithm:**
470
+
471
+ The algorithm groups questions by **delivery unit** (from `${CLAUDE_PLUGIN_ROOT}/skills/trtc-topic/references/execution-units.yaml`) for visual coherence — users see "成员与会控" as a section heading covering 3 slices, not 8 disconnected questions. Storage stays per-slice in `session_context.business_decisions[<slice-id>]`; only the question-asking order is grouped.
472
+
473
+ ```
474
+ Build the question plan:
475
+ units = execution-units.yaml[scenario].delivery_units
476
+ ordered_groups = []
477
+ consumed_slices = set()
478
+
479
+ For each unit in units (in declared order):
480
+ group_slices = [s for s in unit.slices if s in confirmed_plan]
481
+ If group_slices is empty: skip this unit (none of its slices selected).
482
+ ordered_groups.append({ title: unit.title, slices: group_slices })
483
+ consumed_slices.update(group_slices)
484
+
485
+ orphan_slices = [s for s in confirmed_plan if s not in consumed_slices]
486
+ If orphan_slices: ordered_groups.append({ title: "其他", slices: orphan_slices })
487
+
488
+ Run the questionnaire:
489
+ For each group in ordered_groups:
490
+ Show group.title as a section heading to the user (one short line, e.g. "—— 成员与会控 ——").
491
+ For each slice in group.slices:
492
+ Read slice frontmatter business_decisions[]
493
+ If empty / absent: skip this slice (no decisions needed).
494
+ Sort: ask all tier=blocking decisions first, then tier=deferrable ones.
495
+ For each decision in business_decisions[]:
496
+ If session_context.business_decisions[<slice-id>][<key>] already set:
497
+ skip (already answered in earlier turn — never re-ask)
498
+ continue
499
+ If decision.depends_on is set:
500
+ check: does session_context.business_decisions[<slice-id>][<dep.key>]
501
+ match dep.value?
502
+ no → skip this decision
503
+ If decision.destructive_subset = true:
504
+ first ask "是否需要破坏性操作({decision label})?" with 是/否
505
+ no → set value = []
506
+ continue
507
+ yes → fall through to options multi-select
508
+ AskUserQuestion(decision.question, decision.options, multi_select)
509
+ If user answered → persist pick to session_context.business_decisions[<slice-id>][<key>]
510
+ If decision.multi_select AND decision.baseline is set:
511
+ final_value = decision.baseline ∪ user_picks # baseline always included
512
+ persist final_value (even if user_picks is empty)
513
+ If user explicitly skipped / deferred AND decision.tier == "deferrable":
514
+ do NOT persist a value (leave the key unset)
515
+ → topic will fall back to decision.default at generation time + inject a TODO
516
+ If user skipped AND decision.tier == "blocking":
517
+ # baseline-only multi-select: if a baseline exists, skipping = baseline alone (valid)
518
+ If decision.multi_select AND decision.baseline is set:
519
+ persist decision.baseline as the value
520
+ continue
521
+ Else:
522
+ cannot proceed — re-ask (blocking decisions must be answered)
523
+ ```
524
+
525
+ **Tier-aware skipping:** `blocking` 决策必须答(用户跳过就重问);`deferrable` 决策允许用户跳过——跳过时不写入 session,由 topic 在生成代码时回退到 frontmatter 的 `default` 并注入 TODO 注释。这让"主流程先跑通、异常处理后补"成为可能,同时不违反"不无声猜值"的铁律(default 是显式声明 + TODO 可见)。
526
+
527
+ **Baseline merge:** 对带 `baseline` 的多选决策,存入 session 的最终值始终是 `baseline ∪ 用户勾选`。`baseline` 里的值不在 `options` 出现、用户无法取消,保证基础能力(如成员列表)总被生成。即使用户一个额外项都没选,session 里也会写入 baseline 值(而非空数组)。
528
+
529
+ **`decision_constraints`(跨 key 组合约束):** 部分 slice 在 frontmatter 里除 `business_decisions` 外还声明 `decision_constraints:`,描述同一 slice 内**多个决策值之间**的组合规则。每条含 `when`(触发条件)+ 下列之一:
530
+
531
+ | 字段 | 含义 | A2-Q1.5 消费方式 |
532
+ |------|------|-----------------|
533
+ | `forbid: {key: value}` | `when` 成立时禁止的组合 | 用户答出该组合时,**不持久化**,提示冲突原因(取 `reason`)并**重问**冲突的那个 key,引导改选 |
534
+ | `adjust: {key: {disable_option, prefer}}` | `when` 成立时调整另一 key 的选项 | 提问该 key **之前**先检查:若 `when` 已成立,从 `options` 中灰掉 `disable_option`,并把 `prefer` 列表的首项作为推荐默认 |
535
+
536
+ 例(`conference/room-lifecycle`):`roomid_origin = join-only` 时,① 禁止 `creation_pattern = both`(选到则重问 creation_pattern);② 提问 `passive_exit_target` 前灰掉 `lobby` 选项、默认推 `login`。约束校验在 `AskUserQuestion` 持久化之后、进入下一 key 之前执行;`adjust` 在目标 key 提问之前执行。topic 生成代码与 apply gate 也共享这些约束。
537
+
538
+ **Section heading display:** keep it minimal — one short line above the next AskUserQuestion call, in the user's language. Examples: `—— 会议基础链路 ——`, `—— 成员与会控 ——`, `—— 视频增强 ——`. Do NOT show a full progress bar or "step N of M" — the questions themselves are the progress.
539
+
540
+ **Scenario absence fallback:** if the session's scenario is not present in `execution-units.yaml`, OR `intent = integrate-feature` (single-feature mode, no scenario), skip the grouping pass entirely and ask in `confirmed_plan` order without section headings. The grouping is purely UX sugar — its absence does not change which questions get asked.
541
+
542
+ **4-option cap handling:** If `decision.options` has more than 4 entries, slice authors should split them into multiple `business_decisions` entries (group by impact tier or sub-domain) rather than one mega-question. Onboarding never silently truncates options.
543
+
544
+ **Persistence:** Results live under `session_context.business_decisions` in `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml`:
545
+
546
+ ```yaml
547
+ session_context:
548
+ business_decisions:
549
+ conference/login-auth:
550
+ usersig_source: "console"
551
+ userid_strategy: "direct"
552
+ on_session_lost: "redirect-login"
553
+ conference/room-lifecycle:
554
+ roomid_origin: "frontend"
555
+ creation_pattern: "instant"
556
+ passive_exit_target: "lobby"
557
+ conference/participant-management:
558
+ management_features: ["list", "single-control", "all-room"]
559
+ # "list" is baseline (always present, not a user option); "single-control"/"all-room" were picked.
560
+ # "role-and-kick" NOT in array → topic skips setAdmin/revokeAdmin/transferOwner/kickParticipant entirely
561
+ conference/room-schedule:
562
+ schedule_features: ["list", "modify", "events"]
563
+ # "list" is baseline (always present, not a user option); "modify"/"events" were picked.
564
+ # "password" NOT in array → 密码字段/校验不生成
565
+ ```
566
+
567
+ **Topic-side contract (Step 3, governed by topic G8):** when generating code for a slice, topic MUST consult `session_context.business_decisions[<slice-id>]` and tailor the output:
568
+
569
+ - For decisions with `value: "X"` (single-select): generate code matching that branch.
570
+ - `usersig_source = "backend"` → emit `fetch('/api/conference/usersig')` skeleton + TODO; `usersig_source = "console"` → emit placeholder `'YOUR_USERSIG'` + console-link comment(用户需自行到 TRTC 控制台生成测试 UserSig 并填入,skill 不自动签发).
571
+ - `roomid_origin = "frontend"` → emit `createAndJoinRoom` flow; `roomid_origin = "backend-precreated"` → emit `joinRoom` only flow with backend fetch skeleton.
572
+ - For decisions with `value: [...]` (multi-select / multi_select=true): generate ONLY APIs whose ids appear in the array. APIs absent MUST NOT be exported, imported, or rendered as UI entry points.
573
+
574
+ **If a slice has `business_decisions:` but `session_context.business_decisions[<slice-id>]` is missing or partial:** behavior depends on the missing decision's `tier`:
575
+ - **`blocking` 缺值** → topic MUST stop code generation and bounce back to A2-Q1.5 to fill the gap. Do not "default to safe values" — silent defaults are exactly the failure mode this rule prevents.
576
+ - **`deferrable` 缺值** → topic does NOT stop. Use the frontmatter `default` value to generate the branch, and inject a `// TODO: 确认<decision-key>策略(当前用推荐默认值 <default>,主流程跑通后可调整)` comment at the relevant code site. This keeps the main flow runnable while flagging the deferred decision visibly.
577
+
578
+ **MUST NOT:**
579
+ - Do NOT bundle multiple decisions into a single `AskUserQuestion` (option semantics get muddled, hits the 4-option cap).
580
+ - Do NOT skip A2-Q1.5 because "the user seems experienced" or "the slice looks simple" — every slice with `business_decisions` MUST be asked.
581
+ - Do NOT generate UI containers (e.g. a panel that conditionally renders every governance API based on a runtime flag) — unselected APIs MUST be absent from source, not hidden behind v-if.
582
+ - Do NOT hardcode the decision list inside `onboarding` — the registry of "what to ask" is each slice's frontmatter, not a table here.
583
+
584
+ **Slice author checklist** (when authoring or editing a slice):
585
+ - Identify every variable in the generated code that depends on business choice (where does X come from / which subset of APIs / how to handle Y when it fails).
586
+ - Add one `business_decisions` entry per variable.
587
+ - **Assign a `tier`**: if the decision changes the main-flow code structure (credential source, build-room-or-not, anonymous-or-not) → `blocking` (default). If it only affects error/edge handling that doesn't block the main flow from running (session-lost handler, passive-exit target) → `deferrable`, and you MUST also provide a `default` value.
588
+ - Group destructive operations behind `destructive_subset: true` so they get a yes/no gate before the option list.
589
+ - Use `depends_on` when one decision is only meaningful in the context of another (e.g. `schedule_features` only matters when `creation_pattern` includes scheduled rooms).
590
+
591
+ **Apply gate cross-check:** apply skill verifies generated code consistency with `session_context.business_decisions`. Concrete checks (non-exhaustive):
592
+ - If generated code contains `userSig: 'YOUR_USERSIG'` but slice has `business_decisions: usersig_source` → user must have picked `"console"`; if they picked `"backend"` → fail with mismatch error.
593
+ - If generated code calls `kickParticipant`/`setAdmin`/`transferOwner` but `business_decisions.management_features` array doesn't contain `"role-and-kick"` → fail. (Same pattern for `single-control` / `all-room` archetypes.)
594
+ - If a slice's frontmatter has no `business_decisions` field but generated code contains placeholders that imply a business choice (e.g. hardcoded `'YOUR_USERSIG'`, hardcoded `roomId`) → emit a warning suggesting the slice author add a `business_decisions` entry.
595
+ - If a `business_decisions` entry declares `tier: deferrable` but has no `default` field → fail with a slice-author contract error (deferrable decisions MUST carry a default).
596
+
597
+ ## A2-Q2 — Credentials
598
+
599
+ Ask the user for their **SDKAppID** only — the skill does NOT sign UserSig, so do
600
+ NOT ask for the SecretKey, and there is no MCP auto-detection of credentials.
601
+ Reuse the A1-Q1 SDKAppID prompt (see `reference/path-a1-demo.md`). Skip entirely
602
+ if `credentials.sdk_app_id_provided` is `true` in the session file.
603
+
604
+ **Important**: SDKAppID is not a secret — after the user provides it, write the numeric value to `credentials.sdkappid` in the session file at the next Checkpoint, and set `credentials.sdk_app_id_provided` to `true` (do not trigger an extra Write just for credentials). The test UserSig itself is obtained by the user from the TRTC console at integration time (see `reference/usersig-handling.md`).
605
+
606
+ ## A2-Q3 — Per-step progression
607
+
608
+ ### Login step enhancement
609
+
610
+ When the current step's slice is `{product}/login-auth` (or any slice whose
611
+ implementation involves `login()` / `LoginStore` / TIM login / TRTC
612
+ `enterRoom` authentication):
613
+
614
+ **⚠️ BLOCKING GATE — 必须在生成任何登录代码之前完成:**
615
+
616
+ 1. Read `reference/usersig-handling.md` and follow its Generation Protocol.
617
+ 2. Emit a placeholder userSig + console-handoff instructions. The skill does NOT
618
+ auto-generate UserSig (no MCP, no client-side signing).
619
+ 3. **If this protocol is not followed, the generated login code MUST NOT be written to disk.**
620
+
621
+ This gate ensures:
622
+ - A placeholder userSig with clear console-fill instructions is emitted
623
+ - Input fields remain available for custom userID/userSig at runtime
624
+ - **No client-side signing code is ever generated** (no `crypto-js`, no `pako`, no `SecretKey` in source)
625
+
626
+ Follow the Generation Protocol in `usersig-handling.md` (placeholders +
627
+ console-handoff instruction comments).
628
+
629
+ **Violation self-check (same weight as apply gate):** If your about-to-write login
630
+ code contains `HmacSHA256`, `crypto-js`, `pako`, `SecretKey` in a non-comment
631
+ assignment, `generateUserSig`, or creates a file matching `**/usersig.*` — you
632
+ are violating this gate. STOP, discard, re-read `reference/usersig-handling.md`,
633
+ and regenerate.
634
+
635
+ ### Per-step execution
636
+
637
+ After writing code for each step, topic runs `apply.py` (the structural gate, see **"About apply"** above). Only report the step done after apply passes (state → `apply_passed`). Summarize the outcome to the user using this template:
638
+
639
+ ```
640
+ Step {n} ({slice name}) done.
641
+ Changes: {N files added, M files modified}. Did not touch {AppDelegate.swift / main.ts / etc.}.
642
+ Structural gate: passed ({K} slice entries wired up). Verify in your project by running it.
643
+ ```
644
+
645
+ **Persist session state** (see `SKILL.md` § Session context → Checkpoints). After a step passes apply:
646
+ - Set `current_step` to the next step's id (e.g. from `A2.3` to `A2.4`)
647
+ - Append the just-completed slice id to `completed_steps`
648
+ - Update `updated_at` timestamp
649
+ - Write to `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml`
650
+
651
+ **First Write of the session** (i.e. right after Stage 1 calibration confirmed, before this step executes): create the file with `status: active`, all inferred fields filled, and trigger the `.gitignore` auto-update flow described in `SKILL.md` § Session context.
652
+
653
+ If apply fails (state → `apply_failed`), do NOT write this summary **and do NOT advance `current_step` in the session file**. Re-read the slice, regenerate / patch the code based on the failed rule text in the evidence JSON, and re-run apply. The Stop hook keeps the loop alive until apply passes. If you genuinely can't get it to pass, surface a message framed as "I hit a snag on step {n}" — never "apply skill said X" — and list what was tried.
654
+
655
+ ### Auto-advance rules (default behavior)
656
+
657
+ | apply result | Action |
658
+ |---|---|
659
+ | `pass` | **Auto-advance.** Do NOT pause or show a question menu. Immediately proceed to the next slice. Output a one-line step summary and continue generating the next step in the same response. |
660
+ | `partial` (only `warning`/`info`) | **Auto-advance with note.** Same as `pass`, but append a collapsed line noting warnings. Continue. |
661
+ | `partial` (any `critical`) | **Pause.** Show the critical warnings and ask the user how to proceed. |
662
+ | `fail` (after retry exhausted / give-up) | **Pause.** Inform the user and offer options (skip / pause / provide context). |
663
+
664
+ **Batch output:** When consecutive steps all pass, combine their summaries into a single response. The user sees progress flowing without interruption.
665
+
666
+ **Completion:** After all planned steps pass, present a final summary table. Do NOT show the per-step question menu below — it only activates when the user explicitly requests step-by-step mode.
667
+
668
+ **Step-by-step override:** If the user explicitly says "一步一步来" / "pause between steps" / "let me review each step", switch to per-step confirmation mode and show the question menu below after each step. Otherwise, auto-advance is the default.
669
+
670
+ ### Per-step question menu (only when step-by-step mode is active)
671
+
672
+ Question text: "What would you like to do next?"
673
+
674
+ | # | Option | Action |
675
+ |---|--------|--------|
676
+ | 1 | Continue to the next step | advance `current_step`, load next slice |
677
+ | 2 | Walk me through why this code is structured this way | expand the slice's ALWAYS/NEVER rationale (no session write) |
678
+ | 3 | I want to adjust this step's code | collect diff request; after adjusted code passes apply again, re-write session as in the normal Step passes-apply flow |
679
+ | 4 | Pause here | set `status: paused`, keep `current_step` unchanged, Write session; exit the loop |
680
+ | 5 | Type something | free-text |
681
+
682
+ ## A2-Q4 — Completion
683
+
684
+ After all planned steps are done.
685
+
686
+ Question text: "Integration finished. What's next?"
687
+
688
+ | # | Option | Action |
689
+ |---|--------|--------|
690
+ | 1 | Add another feature | loop back to A2-Q1 (as single-feature mode); session `status` stays `active` |
691
+ | 2 | I'm good for now | set `status: completed`, Write session, end onboarding cleanly |
692
+ | 3 | Type something | free-text |
693
+