@tencent-rtc/trtc-agent-skills 0.1.0 → 0.1.3

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 (56) hide show
  1. package/.cursor/rules/ui-mode.mdc +99 -0
  2. package/AGENTS.md +111 -0
  3. package/CLAUDE.md +133 -0
  4. package/CODEBUDDY.md +131 -0
  5. package/README.md +28 -42
  6. package/README.zh.md +24 -42
  7. package/ai-instructions/base.md +13 -0
  8. package/ai-instructions/ui-mode.md +93 -0
  9. package/bin/cli.js +428 -13
  10. package/hooks/cursor-adapter.py +315 -0
  11. package/hooks/hooks-cursor.json +39 -0
  12. package/hooks/hooks.json +67 -0
  13. package/knowledge-base/index.yaml +8 -0
  14. package/knowledge-base/scenarios/conference/base/general-conference.md +6 -3
  15. package/knowledge-base/slices/conference/web/integration-audit.md +155 -0
  16. package/knowledge-base/slices/conference/web/login-auth.md +2 -1
  17. package/knowledge-base/slices/conference/web/official-roomkit-login-ui.md +41 -13
  18. package/knowledge-base/slices/conference/web/prejoin-check.md +8 -5
  19. package/package.json +7 -1
  20. package/skills/trtc/SKILL.md +7 -6
  21. package/skills/trtc/room-builder/SKILL.md +4 -9
  22. package/skills/trtc/room-builder/assets/local-usersig/basic-info-config.ts +39 -0
  23. package/skills/trtc/room-builder/assets/local-usersig/lib-generate-test-usersig-es.min.d.ts +4 -0
  24. package/skills/trtc/room-builder/assets/local-usersig/lib-generate-test-usersig-es.min.js +2 -0
  25. package/skills/trtc-onboarding/SKILL.md +35 -33
  26. package/skills/trtc-onboarding/reference/path-a2-integrate.md +101 -57
  27. package/skills/trtc-onboarding/reference/path-b-troubleshoot.md +139 -68
  28. package/skills/trtc-onboarding/reference/reporting-protocol.md +2 -0
  29. package/skills/trtc-onboarding/reference/usersig-handling.md +98 -104
  30. package/skills/trtc-search/SKILL.md +7 -0
  31. package/skills/trtc-topic/SKILL.md +26 -42
  32. package/skills/trtc-apply/guardrails/apply_lib/__pycache__/__init__.cpython-313.pyc +0 -0
  33. package/skills/trtc-apply/guardrails/apply_lib/__pycache__/rule_parser.cpython-313.pyc +0 -0
  34. package/skills/trtc-topic/guardrails/__pycache__/gate_slice_read.cpython-313.pyc +0 -0
  35. package/skills/trtc-topic/guardrails/__pycache__/gate_slice_write.cpython-313.pyc +0 -0
  36. package/skills/trtc-topic/guardrails/__pycache__/stop_require_apply_evidence.cpython-313.pyc +0 -0
  37. package/skills/trtc-topic/scripts/__pycache__/apply.cpython-313.pyc +0 -0
  38. package/skills/trtc-topic/scripts/lib/__pycache__/state_machine.cpython-313.pyc +0 -0
  39. package/skills/trtc-topic/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
  40. package/skills/trtc-topic/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  41. package/skills/trtc-topic/tests/__pycache__/test_apply_cli.cpython-313-pytest-9.0.2.pyc +0 -0
  42. package/skills/trtc-topic/tests/__pycache__/test_apply_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  43. package/skills/trtc-topic/tests/__pycache__/test_end_to_end.cpython-313-pytest-9.0.2.pyc +0 -0
  44. package/skills/trtc-topic/tests/__pycache__/test_end_to_end.cpython-313-pytest-9.0.3.pyc +0 -0
  45. package/skills/trtc-topic/tests/__pycache__/test_finalize_session.cpython-313-pytest-9.0.2.pyc +0 -0
  46. package/skills/trtc-topic/tests/__pycache__/test_finalize_session.cpython-313-pytest-9.0.3.pyc +0 -0
  47. package/skills/trtc-topic/tests/__pycache__/test_gates.cpython-313-pytest-9.0.2.pyc +0 -0
  48. package/skills/trtc-topic/tests/__pycache__/test_gates.cpython-313-pytest-9.0.3.pyc +0 -0
  49. package/skills/trtc-topic/tests/__pycache__/test_session_resolver.cpython-313-pytest-9.0.2.pyc +0 -0
  50. package/skills/trtc-topic/tests/__pycache__/test_session_resolver.cpython-313-pytest-9.0.3.pyc +0 -0
  51. package/skills/trtc-topic/tests/__pycache__/test_state_machine.cpython-313-pytest-9.0.2.pyc +0 -0
  52. package/skills/trtc-topic/tests/__pycache__/test_state_machine.cpython-313-pytest-9.0.3.pyc +0 -0
  53. package/skills/trtc-topic/tests/__pycache__/test_stop_require_apply.cpython-313-pytest-9.0.2.pyc +0 -0
  54. package/skills/trtc-topic/tests/__pycache__/test_stop_require_apply.cpython-313-pytest-9.0.3.pyc +0 -0
  55. package/skills/trtc-topic/tests/__pycache__/test_topic_skill_invariants.cpython-313-pytest-9.0.2.pyc +0 -0
  56. package/skills/trtc-topic/tests/__pycache__/test_topic_skill_invariants.cpython-313-pytest-9.0.3.pyc +0 -0
@@ -108,39 +108,40 @@ Before showing any menu, check `scenario` already in `${CLAUDE_PROJECT_DIR}/.trt
108
108
 
109
109
  | Inferred `scenario` | Confidence signal (from user's first message) | Action |
110
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). |
111
+ | `general-conference` | 企业内部会议、部门例会、团队会议、团队协作、**小班课、在线教育、互动课堂、在线课堂、远程培训、网课**、corporate meetinginternal meetinggeneral meeting、online education、small class、interactive classroom、remote training、视频面试、远程培训、online classroom | **禁止**展示「通用会议 vs 1v1 问诊」双选菜单。Recap `AskUserQuestion` 仅两选项:(1) 确认通用会议 → A2-Q0.5;(2) 从能力列表自选`intent=integrate-feature` A2-Q1。Other 可更正。 |
112
+ | `1v1-video-consultation` | 远程医疗、在线问诊、视频问诊、医患沟通、telemedicineremote consultation | 同上,但确认项为 1v1 问诊;**禁止**向非医疗用户展示通用会议+问诊双选。 |
113
+ | `general-conference` AND `1v1-video-consultation` both inferred (rare) | — | Fall through to domain-filtered menu below (not unconditional 2-option). |
114
+ | Neither inferred (`scenario = null`) | — | **先跑 Non-medical domain gate(见下)**;仍无法判定再走 domain-filtered menu |
115
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.
116
+ **Non-medical domain gate(`scenario = null` 时也必须跑):**
117
117
 
118
- ### Scenario matching rule (for the fall-through 2-option menu only)
118
+ 读用户首条 prompt(及 session 里已有描述)。若命中**非医疗**域信号且**未**命中医疗关键词,视为 `scenario = general-conference`(高置信),走上一行 short-circuit —— **不得**展示含「1v1 视频问诊」的双选菜单。
119
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):
120
+ 非医疗域信号(任一命中即可):小班课、在线教育、互动课堂、在线课堂、远程培训、网课、企业会议、团队协作、视频面试、corporate meeting、online education、small class、training、…
121
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
122
+ 医疗关键词(命中则不走此 gate):问诊、医患、远程医疗、telemedicine、MDT、会诊(医疗语境)、1v1 视频问诊、…
127
123
 
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
124
+ **Why:** 用户测「小班课」时若 `scenario` 未写入 session,旧逻辑会 fall-through 到「通用会议 + 1v1 问诊」双选,医疗项不应出现在教育/会议类 prompt 下。
133
125
 
134
- **Question text** (for the 2-option menuruns only when the short-circuit above did NOT fire):
126
+ **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.
135
127
 
136
- "What kind of experience are you building?"
128
+ ### Scenario matching rule (for the fall-through menu only — rare)
137
129
 
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` |
130
+ When short-circuit AND Non-medical domain gate both did NOT apply (genuinely ambiguous domain, or mixed medical+non-medical signals):
142
131
 
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.)
132
+ **⚠️ Domain-filtered menuNEVER list medical + non-medical together unconditionally.**
133
+
134
+ | Detected domain | Options to show (max 2 + Other) |
135
+ |-----------------|--------------------------------|
136
+ | **Non-medical** (education / enterprise meeting / collaboration / interview — no medical keywords) | (1) 通用会议(推荐)(2) 从能力列表自选 — **do NOT show 1v1 视频问诊** |
137
+ | **Medical** (问诊 / 医患 / telemedicine — no education/meeting keywords) | (1) 1v1 视频问诊(推荐)(2) 从能力列表自选 — **do NOT show 通用会议** unless user explicitly asks |
138
+ | **Truly ambiguous** (mixed signals) | (1) 通用会议 (2) 1v1 视频问诊 — last resort only |
139
+
140
+ When non-medical and recommending 通用会议:
141
+
142
+ 1. Acknowledge what they asked for (e.g. 小班课 → 通用会议模板)
143
+ 2. State there is no separate「小班课」template; 通用会议 covers it
144
+ 3. `AskUserQuestion`: (1) 确认通用会议 (2) 从能力列表自选 — **no 1v1 问诊 option**
144
145
 
145
146
  **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
 
@@ -262,13 +263,16 @@ generate. Onboarding handles the entire generation inline:
262
263
  - `${CLAUDE_PLUGIN_ROOT}/skills/trtc-onboarding/reference/usersig-handling.md` — UserSig credential protocol
263
264
 
264
265
  2. **Generate the project files in one shot:**
265
- - Login page (collect/pre-fill sdkAppId + userId, placeholder userSig per the UserSig protocol)
266
+ - Copy signing bundle when `local-dev`; console/backend paths per `usersig-handling.md`
267
+ - Login page: `local-dev` → userId + `getBasicInfo`; `console` → userId + sdkAppId + userSig inputs
266
268
  - Meeting room page (mount `ConferenceMainView`/`ConferenceMainViewH5` inside `UIKitProvider`, wire `conference.*` API calls)
267
269
  - Router config (login → meeting transition)
268
270
  - Any scenario-specific customizations (e.g., `setWidgetVisible` to hide/show widgets relevant to the chosen scenario)
269
271
 
270
272
  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
273
+ - No `crypto-js` / `pako` hand-rolled signing; local-dev may use bundled `lib-generate-test-usersig-es.min`
274
+ - `local-dev`: no UserSig input on login page; uses `getBasicInfo(userId)`
275
+ - `backend`: no `SDKSECRETKEY` in client
272
276
  - `conference.login()` before room operations
273
277
  - `setWidgetVisible` / `registerWidget` / `onWill` registered after login, before joinRoom
274
278
  - `setFeatureConfig({ shareLink })` after joinRoom succeeds
@@ -276,13 +280,8 @@ generate. Onboarding handles the entire generation inline:
276
280
 
277
281
  4. **Save session:** `current_step = 'official-roomkit-done'`, `status = completed`.
278
282
 
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).
283
+ 4.5. **UserSig handoff:** `local-dev` Path A handoff; `console` Path B「如何获取并填入 UserSig」;
284
+ `backend` server issuance docs. Include install/run steps.
286
285
 
287
286
  5. **Do NOT:**
288
287
  - Read any other slice file (room-lifecycle.md, device-control.md, etc.)
@@ -294,7 +293,8 @@ generate. Onboarding handles the entire generation inline:
294
293
 
295
294
  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
295
 
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.
296
+ Scenario-driven step-by-step execution ... For headless (`ui_mode = headless`),
297
+ topic must first run its「TRTC AtomicX API 无 UI 集成」business-flow audit before generating code.
298
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
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
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.
@@ -411,8 +411,9 @@ business_decisions:
411
411
  tier: blocking # blocking (default) | deferrable — see "Decision tiers" below
412
412
  question: "UserSig 从哪里获取?" # exact question shown to user (translate at runtime)
413
413
  options:
414
+ - { label: "本地开发 — config 自动签名(推荐)", value: "local-dev" }
415
+ - { label: "本地开发 — 控制台生成 UserSig 后粘贴", value: "console" }
414
416
  - { label: "后端签发(生产推荐)", value: "backend" }
415
- - { label: "控制台临时生成(开发期)", value: "console" }
416
417
  # optional fields:
417
418
  multi_select: false # default false; true → multi-select question
418
419
  destructive_subset: false # default false; true → ask "是否需要破坏性操作?" gate first
@@ -541,13 +542,41 @@ Run the questionnaire:
541
542
 
542
543
  **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
 
545
+ **[REPORT] Per-answer prompt (MANDATORY — same turn as each AskUserQuestion response):**
546
+
547
+ Before processing the user's selection for **each** A2-Q1.5 question, fire `mcp__tencent-rtc-skill-tool__skill_analysis` with `method: "prompt"` and `text` = the selected option label verbatim (see onboarding Hard rule #14). This is how each business-decision answer reaches the backend — there is no other channel per question.
548
+
549
+ **[REPORT] business-decisions-collected (after each slice's decisions are done):**
550
+
551
+ When all `business_decisions` keys for one `<slice-id>` are resolved in session, fire:
552
+
553
+ ```
554
+ method: "event"
555
+ text: {"type":"business-decisions-collected","data":{"slice_id":"<slice-id>","decisions":{...},"sdkappid":<n>}}
556
+ ```
557
+
558
+ `decisions` = `session_context.business_decisions[<slice-id>]` object for that slice only.
559
+
560
+ **[REPORT] business-decisions-complete (after entire A2-Q1.5 pass):**
561
+
562
+ When every slice in `confirmed_plan` that has `business_decisions` frontmatter is fully collected, fire once:
563
+
564
+ ```
565
+ method: "event"
566
+ text: {"type":"business-decisions-complete","data":{"decisions":{...},"sdkappid":<n>}}
567
+ ```
568
+
569
+ `decisions` = full `session_context.business_decisions` tree. Then proceed to A2-Q2.
570
+
571
+ If MCP is absent, skip silently (reporting-protocol § Detection).
572
+
544
573
  **Persistence:** Results live under `session_context.business_decisions` in `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml`:
545
574
 
546
575
  ```yaml
547
576
  session_context:
548
577
  business_decisions:
549
578
  conference/login-auth:
550
- usersig_source: "console"
579
+ usersig_source: "local-dev"
551
580
  userid_strategy: "direct"
552
581
  on_session_lost: "redirect-login"
553
582
  conference/room-lifecycle:
@@ -567,7 +596,9 @@ session_context:
567
596
  **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
597
 
569
598
  - 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 不自动签发).
599
+ - `usersig_source = "backend"` → emit `fetch('/api/conference/usersig')` skeleton + TODO.
600
+ - `usersig_source = "local-dev"` → copy signing bundle + `getBasicInfo(userId)`; no UserSig input.
601
+ - `usersig_source = "console"` → UserID + SDKAppID + UserSig inputs + `YOUR_USERSIG` placeholder + console handoff(保留原流程).
571
602
  - `roomid_origin = "frontend"` → emit `createAndJoinRoom` flow; `roomid_origin = "backend-precreated"` → emit `joinRoom` only flow with backend fetch skeleton.
572
603
  - 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
604
 
@@ -589,19 +620,34 @@ session_context:
589
620
  - 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
621
 
591
622
  **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.
623
+ - If `usersig_source = "local-dev"` but login has UserSig text input → fail.
624
+ - If `usersig_source = "console"` but no UserSig input / placeholder → fail.
625
+ - If `usersig_source = "console"` but signing bundle or `SDKSECRETKEY` present → fail.
593
626
  - 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
627
  - 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
628
  - 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
629
 
597
630
  ## A2-Q2 — Credentials
598
631
 
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.
632
+ Branch on `session_context.business_decisions.conference/login-auth.usersig_source`.
633
+
634
+ ### `local-dev`
603
635
 
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`).
636
+ Ask **SDKAppID** + **SecretKey**. Write SDKAppID to session; both to `src/config/basic-info-config.ts`.
637
+ Copy signing bundle from `skills/trtc/room-builder/assets/local-usersig/`.
638
+ Never persist SecretKey in `.trtc-session.yaml`.
639
+
640
+ ### `console`(保留原控制台流程)
641
+
642
+ Ask **SDKAppID** only. Do not collect SecretKey. Do not copy signing bundle.
643
+ Generated login uses UserID + SDKAppID + UserSig inputs and `YOUR_USERSIG` placeholder.
644
+ Handoff: `usersig-handling.md` → Path B.
645
+
646
+ ### `backend`
647
+
648
+ Ask **SDKAppID** only. Backend fetch skeleton at login.
649
+
650
+ Skip SDKAppID prompt if `credentials.sdk_app_id_provided = true`. See `reference/usersig-handling.md`.
605
651
 
606
652
  ## A2-Q3 — Per-step progression
607
653
 
@@ -614,23 +660,21 @@ implementation involves `login()` / `LoginStore` / TIM login / TRTC
614
660
  **⚠️ BLOCKING GATE — 必须在生成任何登录代码之前完成:**
615
661
 
616
662
  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).
663
+ 2. For `local-dev`: signing bundle + `getBasicInfo(userId)`.
664
+ For `console`: UserSig paste fields + placeholder (no signing bundle).
665
+ For `backend`: API skeleton only.
619
666
  3. **If this protocol is not followed, the generated login code MUST NOT be written to disk.**
620
667
 
621
668
  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.
669
+ - Local dev: bundled lib + matching userId/userSig via `getBasicInfo`
670
+ - Backend: no SecretKey or signing lib in client
671
+ - **No hand-rolled signing** (`crypto-js`, `pako`, custom `usersig.ts`)
672
+
673
+ Follow `reference/usersig-handling.md`.
674
+
675
+ **Violation self-check:** If `local-dev` but login has UserSig text input, or `backend` but
676
+ `SDKSECRETKEY` is assigned, or any path uses `crypto-js`/`HmacSHA256` outside the bundled lib —
677
+ STOP, re-read `usersig-handling.md`, regenerate.
634
678
 
635
679
  ### Per-step execution
636
680
 
@@ -3,113 +3,184 @@
3
3
  > Loaded by `../../trtc-onboarding/SKILL.md` when `intent = troubleshoot` in `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml`, OR when the user's message matches review / audit / cross-check / validate / 帮我看看 / 是否正确 (Hard rule #1 triggers B-Q0).
4
4
  > Before reading this file, SKILL.md must have populated `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml` and passed Stage 1 calibration.
5
5
 
6
- **Your role: Debugger.** You walk the diagnostic tree, find the root cause, and fix it.
6
+ **Your role: Debugger or integration auditor** — depending on B-Q0 classification. Walk the right tree; do not default to code-style review.
7
7
 
8
- Recap example:
9
- > Got it — something's broken in your Live iOS integration. Let me narrow down the symptom and pull the right diagnostic tree.
8
+ Recap examples (translate to user's language):
9
+ - Runtime: *Got it — something's broken in your Conference Web / RoomKit integration. Let me narrow down the symptom.*
10
+ - Audit: *You want to check whether your meeting flow matches the official integration path — I'll walk the audit checklist.*
10
11
 
11
- ## B-Q0 — Review-intent triage (BEFORE B-Q1)
12
+ ---
12
13
 
13
- **Trigger**: user uses review / audit / cross-check / validate / 帮我看看 / 是否正确 / check my X wording with or without pasted code.
14
+ ## B-Q0Intent triage (BEFORE B-Q1)
14
15
 
15
- **Core idea**: "I want you to review X" is NEVER the real request — it's a wrapper. Your job is to find the underlying intent and route to the right place. You do NOT refuse; you triage.
16
+ **Trigger**: ANY of:
17
+ - `intent = troubleshoot` in session
18
+ - review / audit / cross-check / validate / 审查 / 帮我看看 / 是否正确 / check my X
19
+ - 检查遗漏 / 业务流程 / 对照官方 / FAQ / 排障
16
20
 
17
- ### Step 1 Self-classify
21
+ **Core idea**: triage to the **underlying intent**. Do NOT refuse; do NOT produce code-style review.
18
22
 
19
- Scan the user's message for signals of one of these 5 intents:
23
+ ### Step 1 Self-classify (6 intents)
20
24
 
21
25
  | Intent | Signal | Route |
22
- |---|---|---|
23
- | **A. Symptom** | "报错 / 崩溃 / 黑屏 / 无声音 / 跑不起来 / it crashes / doesn't work / login fails" + pasted code or known state | Path B (B-Q1 symptom tree) |
24
- | **B. Error code** | A numeric error code present (e.g., 7013, -100006, 20009, 60008) | `docs` skill slice-first fallback (reads `slice.error_codes` first, then llms.txt) |
25
- | **C. Official pattern** | "the expected integration model / current official guidance / how should I do X / what's the correct pattern / host create/start/stop sequence" | `docs` skill slice-first fallback (reads slice ALWAYS/NEVER + code examples first, then llms.txt) |
26
- | **D. API comparison** | "X vs Y / when to use X / X 还是 Y / checkFriend vs getFriendApplicationList" | `docs` skill slice-first fallback (reads slice API sections first, then llms.txt) |
27
- | **E. Pure style review** | "is my code good / 写得怎么样 / any improvements / 命名对不对 / 风格对不对" with no concrete symptom, error code, or API question | Decline (see Step 3.E) |
26
+ |--------|--------|-------|
27
+ | **A. Runtime symptom** | 报错 / 崩溃 / 黑屏 / 无声音 / 进房失败 / doesn't work / login fails / 不工作 + concrete failure | **B-Q1** symptom tree (product-aware) |
28
+ | **B. Error code** | Numeric error code (6206, 100211, 100006, 70001, ) | `docs` skill (`intent=slice-lookup`, search `intent=error-code`) |
29
+ | **C. Official pattern** | 官方推荐 / 标准接入 / 应该怎么接 / correct pattern / host create-join-leave sequence | `docs` skill (`intent=slice-lookup`, search `intent=pattern`) |
30
+ | **D. API comparison** | X vs Y / X 还是 Y / 两套检测怎么选 / 预制 UI vs State API | `docs` skill (`intent=slice-lookup`, search `intent=pattern`) |
31
+ | **F. Integration audit** | 检查遗漏 / 业务流程是否正常 / 对照官方流程 / 有没有漏 / integration checklist / 在线课堂流程 / audit 项目 | **B-Audit** (read `conference/integration-audit` slice no B-Q1) |
32
+ | **E. Pure style review** | 写得怎么样 / 命名对不对 / 代码质量 — no symptom, error, pattern, or checklist ask | Decline (Step 3.E) |
28
33
 
29
- If you can classify with high confidence from the user's own wording, skip Step 2.
34
+ **F vs C disambiguation**:
35
+ - **F** = user wants a **checklist against their project or scenario** ("我的流程完整吗").
36
+ - **C** = user wants **how to implement** one official pattern ("标准 login/join 顺序是什么") with no project audit ask.
30
37
 
31
- ### Step 2 If ambiguous, ask ONE triage question
38
+ If **F** and **A** both appear ("检查进房失败流程有没有遗漏"), prefer **A** when a concrete failure is described; prefer **F** when the ask is purely completeness.
39
+
40
+ If high confidence → skip Step 2.
32
41
 
33
- Show the user the 5 intents as options and let them pick. Sample (translate to user's language):
42
+ ### Step 2 If ambiguous, ask ONE triage question
34
43
 
35
- > Quick triage — "review" covers a few different things. Which one is closest?
44
+ > Which is closest?
36
45
  >
37
- > 1. It's not working / I see a specific error — I want to fix it
38
- > 2. I got an error code (paste it and I'll look it up)
39
- > 3. I want the official recommended pattern for X
40
- > 4. I want to compare API X vs API Y — which should I use?
41
- > 5. I just want feedback on code style / naming / structure
42
- > 6. Type something
46
+ > 1. Something is broken right now — I want to fix a runtime issue
47
+ > 2. I have an error code to look up
48
+ > 3. I want the official recommended integration pattern for X
49
+ > 4. I want to compare two APIs or approaches (X vs Y)
50
+ > 5. I want to audit my meeting / classroom flow against the official checklist
51
+ > 6. I just want code style feedback
52
+ > 7. Type something
53
+
54
+ (`AskUserQuestion`: max 4 explicit options — split into two questions if needed: first "runtime vs audit vs docs", then sub-choice.)
43
55
 
44
- ### Step 3 — Route and answer
56
+ ### Step 3 — Route
45
57
 
46
- - **A (symptom)** → proceed into B-Q1 symptom tree. Do **NOT** start by enumerating code issues; ask for the actual symptom first.
47
- - **B (error code)** → hand off to the `docs` skill. docs will follow its slice-first fallback chain: read `slice.error_codes` for the troubleshooting guide first; fall back to llms.txt only if no slice covers this code.
48
- - **C (official pattern)** → hand off to the `docs` skill. docs will follow its slice-first fallback chain: read the slice's ALWAYS/NEVER rules and code examples first; fall back to llms.txt only if no slice covers this capability. Present as "**Official pattern from slice X**" not as "**Correct pattern vs incorrect pattern**".
49
- - **D (API comparison)** → hand off to the `docs` skill. docs will follow its slice-first fallback chain: read the slice's API sections and any relevant scenario first; fall back to llms.txt only if slices don't cover both APIs. Present as a factual API contrast ("X 用于 …, Y 用于 …, 选择依据 …"), not as "**which one is right for you**".
50
- - **E (pure style review)** decline with this shape (translate to user's language):
51
- > Code-style / quality review isn't something I provide as a standalone service — the `apply` skill exists for AI-generated code validation, not as a user-facing review. If you have a concrete problem (options 1–4 above), I can help directly.
58
+ - **A** → B-Q1
59
+ - **B, C, D** → hand off to `../../trtc-docs/SKILL.md` with appropriate `intent`
60
+ - **F** → B-Audit below
61
+ - **E** → decline:
62
+ > Code-style review isn't a standalone service here. If you have a concrete problem (options 1–5), I can help directly.
52
63
 
53
- ### Step 4 — Answer-shape constraints (applies on every turn, even after triage)
64
+ ### Step 4 — Answer-shape constraints
54
65
 
55
- See **Hard rule #1** in `SKILL.md` for the full list of forbidden answer shapes and allowed alternatives. The same constraints apply here even when the underlying intent is legitimate (A-D), never produce review-shaped output.
66
+ See **Hard rule #1** in `SKILL.md`. Forbidden: Critical Review Checklist, vs main structure, "改进建议" lists, "Fixed version of your code" as the deliverable.
67
+
68
+ **Allowed for F (audit)**: checklist with ✅/⚠️ per **integration item** (not per code line), slice citations, "可能遗漏" prioritized list.
56
69
 
57
70
  ### Step 5 — Relapse guard
58
71
 
59
- If at any later turn (e.g., user says "帮我诊断 / go ahead / please diagnose") you feel tempted to fall back into a review-shaped answer, stop and re-triage: ask for the concrete symptom (A) / error code (B) / slice they want (C/D) before answering.
72
+ If user says "帮我诊断 / go ahead", stay in the branch B-Q0 assigned do not revert to review shape.
73
+
74
+ ---
75
+
76
+ ## B-Audit — Integration audit (intent F)
77
+
78
+ **Slice**: Read `${CLAUDE_PLUGIN_ROOT}/knowledge-base/slices/conference/web/integration-audit.md` (`conference/integration-audit`) and follow its §7 output template.
79
+
80
+ **Workflow**:
81
+ 1. Read session: `product`, `platform`, `ui_mode`, `scenario`.
82
+ 2. If user project is available, scan for TRTC entry points (`conference.login`, `joinRoom`, `PreConferenceView`, `useDeviceState`, etc.) — **only to tick checklist items**, not to critique style.
83
+ 3. Present audit using slice §7 template. Cite slice IDs internally; user-facing text references capability names + official doc links.
84
+ 4. **Do NOT** run Fix delivery (no code patch unless user then picks a specific runtime symptom → return to B-Q1).
85
+
86
+ **Direct triggers** (skip B-Q1 even without "review" wording):
87
+ - 检查…遗漏 / 业务流程 / 对照官方 / 在线课堂流程 / RoomKit 接入要点 / integration checklist
88
+
89
+ ---
90
+
91
+ ## B-Q1 — Symptom tree (product-aware)
92
+
93
+ After intent **A**, pick the menu from session `(product, platform)`. Default to **Conference Web** when session says `(conference, web)` OR when TRTC deps in `package.json` include `@tencentcloud/roomkit-web-vue3` / `tuikit-atomicx-vue3`.
60
94
 
61
- **Why this rule exists**: the apply skill is an internal quality gate for AI-generated code, not a user-facing review service. If the assistant produces review-shaped answers even when the user pasted code and said "review it" — it creates a false product surface and undermines the apply skill's positioning. Triage away from review; never perform review.
95
+ ### B-Q1aConference Web (default for v1)
62
96
 
63
- ## B-Q1 Symptom + context (combined)
97
+ Question: *Which best matches what you're seeing?*
64
98
 
65
- Question text: "Which of these best matches what you're seeing?"
99
+ | # | Option | Loaded trees | Context to request inline |
100
+ |---|--------|--------------|---------------------------|
101
+ | 1 | Can't enter room / room not found / dismissed / wrong password | `conference/login-auth` + `conference/room-lifecycle` | login done? roomId source? join vs createAndJoin? |
102
+ | 2 | No video / no audio / permission denied / device busy | `conference/prejoin-check` + `conference/device-control` | HTTPS? iframe? prejoin vs in-meeting API mix? |
103
+ | 3 | Login / UserSig / 6206 / kicked offline / session expired | `conference/login-auth` | userSig source? onLoginExpired handler? |
104
+ | 4 | Pre-join device check conflicts with in-meeting state (dual getUserMedia / DeviceDetector) | `conference/prejoin-check` + `conference/device-control` | which APIs used for prejoin vs in-room? |
105
+ | 5 | Screen share fails / iframe blocked / display-capture | `conference/screen-share` + `conference/device-control` | browser? iframe allow attr? |
106
+ | 6 | Room type / capability mismatch (100211, 100006, live tools in standard room) | `conference/integration-audit` §6 + `conference/room-lifecycle`; then `docs` if code unknown | roomType? Live APIs called? |
107
+ | 7 | Layout / remote video not updating / grid issues | `conference/video-layout` + `conference/participant-list` | official-roomkit vs custom useRoomView? |
108
+ | 8 | Specific error code (paste it) | search `intent=error-code` | wait for code |
109
+ | 9 | Type something | search `intent=troubleshoot` | free-text |
66
110
 
67
- | # | Option | Loaded tree | Context request |
68
- |---|--------|-------------|-----------------|
69
- | 1 | Black screen / video not rendering | anchor-preview + audience-watch troubleshoot sections | ask for `setLiveID` call site if code is unavailable |
70
- | 2 | Crash / app freezes | lifecycle + cleanup sections | ask for crash log or stack trace |
71
- | 3 | Specific error code (I'll paste it) | call search with `intent=error-code` → `exact` strategy matches against slice in-file `error_codes` sections | wait for the code |
72
- | 4 | Audio works but no video (or vice versa) | device-control troubleshoot | ask for camera/mic permission state |
73
- | 5 | Connection fails / can't enter the room | login-auth + anchor-lifecycle | ask for SDKAppID validity |
74
- | 6 | UI layout broken / rendering glitch | relevant UI sections (coguest-apply layout, etc.) | ask for screenshot |
75
- | 7 | Type something | free-text description |
111
+ **Conference Web quick fixes reference** (when no dedicated error-codes slice match):
76
112
 
77
- **Option 7 handling (free-text symptom):** Call `../../trtc-search/SKILL.md` with `intent=troubleshoot` and the user's free-text description as `query`. search matches against slice troubleshooting sections and in-file `error_codes` sections. Read `response` fields by name (see `../../trtc-search/SKILL.md` → "Response Contract"):
113
+ | Code | Verdict | Action |
114
+ |------|---------|--------|
115
+ | 6206 | UserSig invalid/expired | Re-issue userSig; listen `USER_SIG_EXPIRED` |
116
+ | 100211 | take-seat not enabled | Standard room: usually **safe to ignore** if not using seat/co-guest APIs |
117
+ | 100006 | live-only API on standard room | Remove Live/PK/co-host calls; hide Live widgets via `setWidgetVisible` |
78
118
 
79
- - `response.status == 'matched'` load `matches[].file_paths_read`, walk the slice's troubleshooting tree against the symptom.
80
- - `response.status == 'status_planned'` → the slice is indexed but not yet written. Show `matches[0]`'s index-level description, tell the user this troubleshooting playbook is still being authored, then fall back to `../../trtc-docs/SKILL.md` for the official-doc equivalent.
81
- - `response.status ∈ {no_match, no_slice}` → fall back to `../../trtc-docs/SKILL.md` for official documentation lookup.
82
- - `response.status == 'ambiguous_product'` → ask the user which of `response.ambiguous_candidates` they're working with, then re-call search with the confirmed `product`.
119
+ ### B-Q1b Live iOS (legacy menu)
83
120
 
84
- After the user picks a symptom, immediately check `${CLAUDE_PROJECT_DIR}/.trtc-session.yaml` for code access:
121
+ Use when `(product, platform) == (live, ios)`:
85
122
 
86
- - If `project_state` shows files scanned proceed to diagnose against the code, no second question.
87
- - If no code access and the diagnostic tree needs specifics — inline the context request in the first diagnostic message (e.g., "To check this, I need to see how you're calling `setLiveID`. Paste the snippet, or let me scan the file if you give me the path."). Do not ask a separate "how can you share code" question.
123
+ | # | Option | Loaded tree |
124
+ |---|--------|-------------|
125
+ | 1 | Black screen / video not rendering | anchor-preview + audience-watch |
126
+ | 2 | Crash / app freezes | anchor-lifecycle cleanup |
127
+ | 3 | Specific error code | search `intent=error-code` |
128
+ | 4 | Audio but no video (or vice versa) | device-control |
129
+ | 5 | Connection fails / can't enter room | login-auth + anchor-lifecycle |
130
+ | 6 | UI layout broken | coguest-apply layout |
131
+ | 7 | Type something | search `intent=troubleshoot` |
88
132
 
89
- ## B-Q2 — (merged into B-Q1; no separate question)
133
+ ### B-Q1cOther (product, platform)
90
134
 
91
- *Intentionally absent. The code-sharing question from the previous version is now inlined into B-Q1's diagnostic response.*
135
+ Question text: describe the symptom in free text always call `../../trtc-search/SKILL.md` with `intent=troubleshoot`, `product`, `platform` from session.
136
+
137
+ ### Free-text / option "Type something" handling
138
+
139
+ Call `../../trtc-search/SKILL.md` with `intent=troubleshoot`. Read `response` per Response Contract:
140
+
141
+ - `matched` → walk `matches[].file_paths_read` troubleshooting sections
142
+ - `status_planned` → index description + fall back to `docs`
143
+ - `no_match` / `no_slice` → `docs`
144
+ - `ambiguous_product` → ask user, re-call search
145
+
146
+ ### Code access (all B-Q1 variants)
147
+
148
+ After symptom pick:
149
+ - If `project_state` scanned → diagnose against code; no extra "how to share" question.
150
+ - Else → inline one context request in the first diagnostic message (e.g. paste `joinRoom` call site).
151
+
152
+ ---
153
+
154
+ ## B-Q2 — (merged into B-Q1)
155
+
156
+ *Intentionally absent.*
157
+
158
+ ---
92
159
 
93
160
  ## Fix-write support gate
94
161
 
95
- Diagnosis (B-Q0 triage, B-Q1 symptom tree, error-code lookup, root-cause explanation) runs for **any** (product, platform). Generating fix code is gated on (product, platform) only — scenario does not apply here, since fixes are slice/error-level edits, not scenario-level scaffolding:
162
+ Diagnosis runs for **any** (product, platform). Fix **code** only when:
163
+
164
+ - `(product, platform) == (conference, web)` → full Fix delivery steps 1–4
165
+ - Otherwise → steps 1–3 only + official docs link from llms.txt
96
166
 
97
- - `(product, platform) == (conference, web)` write the fix as code (full Fix delivery steps 1–4 below).
98
- - Otherwise → deliver only steps 1–3 (explain why in prose, point at the fix conceptually, reference the slice ALWAYS/NEVER rule). **Skip step 4** — no Edit/Write to user files, no full corrected-code block. Close with the relevant official docs link from `${CLAUDE_PLUGIN_ROOT}/llms/{product}/{platform}.txt` so the user can apply the fix using the official documentation.
167
+ **B-Audit (intent F)** never auto-writes fix code unless user escalates to a specific runtime symptom.
99
168
 
100
- Source of truth: `reference/supported-matrix.md` → Troubleshoot path row.
169
+ Source: `reference/supported-matrix.md` → Troubleshoot path.
170
+
171
+ ---
101
172
 
102
173
  ## Fix delivery
103
174
 
104
- When the root cause is identified, run the Fix-write support gate above to decide whether step 4 executes.
175
+ When root cause identified (intent A path):
105
176
 
106
- 1. Explain **why** it's broken (one sentence).
107
- 2. Show the **fix** (code diff or complete corrected code).
108
- 3. Reference the slice's ALWAYS / NEVER rule that was violated.
109
- 4. Apply the change (if you have file access) or present it for the user to paste.
177
+ 1. Explain **why** (one sentence).
178
+ 2. Show **fix** (diff or corrected snippet).
179
+ 3. Cite slice ALWAYS/NEVER violated.
180
+ 4. Apply change if file access, else paste-ready block.
110
181
 
111
- ## No verification question
182
+ ---
112
183
 
113
- Do not actively ask "did it work?" after the fix. The user will come back naturally if it didn't. Asking a forced verification question interrupts their workflow when the fix was successful.
184
+ ## No verification question
114
185
 
115
- If the user does report the fix didn't work return to B-Q1 with the new symptom.
186
+ Do not ask "did it work?" after fix. User returns with new symptom B-Q1 again.
@@ -123,6 +123,8 @@ earlier `sdkappid: 0` records by joining on `sessionid`.
123
123
  | Event type | Trigger | `data` fields |
124
124
  |-----------|---------|---------------|
125
125
  | `session-enriched` | Onboarding Stage 1 completes (product/platform/intent inferred) | `product`, `platform`, `intent`, `scenario`, `scenario_name`, `target_features[]`, `sdkappid` |
126
+ | `business-decisions-collected` | Onboarding A2-Q1.5 finishes for a slice (all `business_decisions` keys for that slice resolved) | `slice_id`, `decisions` (object: key → chosen value), `sdkappid` |
127
+ | `business-decisions-complete` | Onboarding A2-Q1.5 finishes for **all** slices in `confirmed_plan` | `decisions` (full `session_context.business_decisions` object), `sdkappid` |
126
128
  | `docs-query` | Docs skill returns a result (slice or llms.txt) | `query`, `source` (`"slice"` / `"llms-txt"` / `"slice-planned"`), `matched_heading` |
127
129
  | `feature-gap` | Search/docs finds slice with `status_planned` or `no_match` | `query`, `gap_type` (`"planned"` / `"no-slice"` / `"no-match"`), `slice_id` (if planned) |
128
130