Files
zhaoleibd e525beb8d6 feat(skills): unify meeting related skills (#2387)
* feat(skills): unify meeting guidance

* fix(meeting): restore domain boundary guidance

* docs(meeting): remove agent rollout qualification guidance

* docs(meeting): front-load skill routing description

* docs(meeting): refine identity and command guidance

* docs(meeting): clarify identity and pagination guidance

* docs(meeting): fix minutes todo detail command

* fix(meeting): clarify artifact query routing

* fix(meeting): improve live meeting skill recall

* fix(qualitygate): generate valid minute token placeholders

* fix(meeting): address unified skill review findings

* docs(meeting): add minutes permission guidance

* docs(lark-meeting): 更新SKILL.md并新增会议问答引导脚本

1. 优化SKILL.md表格排版与快速行动章节内容,新增批量获取当日会议脚本的使用说明
2. 新增meeting_qa_bootstrap.py脚本,实现一站式采集当日进行中、已结束会议及未来日程,生成可直接执行的命令引导

* docs(calendar): clarify today's meeting lookup

* revert(meeting): remove meeting Q&A bootstrap guidance

* fix(skills): register lark-meeting suite keywords

---------

Co-authored-by: maozhixiang <maozhixiang@bytedance.com>
2026-08-21 10:49:46 +08:00

102 lines
3.6 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
//
// Capability source test: pins the identity (user/bot) claims made in
// skills/lark-note against the AuthTypes actually declared on the
// shortcuts, and pins the bot+unified stop-path guidance PR #2278's review
// found missing: NoteTranscript stays user-only, so any doc reachable from a
// `+detail --as bot` -> unified routing decision must say so explicitly
// instead of silently falling back to --as user.
package note
import (
"os"
"strings"
"testing"
)
func hasAuthType(authTypes []string, want string) bool {
for _, a := range authTypes {
if a == want {
return true
}
}
return false
}
func readSkillDoc(t *testing.T, relPath string) string {
t.Helper()
data, err := os.ReadFile("../../" + relPath)
if err != nil {
t.Fatalf("read %s: %v", relPath, err)
}
return string(data)
}
func TestNoteIdentityDocsMatchAuthTypes(t *testing.T) {
if !hasAuthType(NoteDetail.AuthTypes, "bot") {
t.Fatalf("NoteDetail.AuthTypes = %v, want bot included (this PR's contract)", NoteDetail.AuthTypes)
}
if hasAuthType(NoteTranscript.AuthTypes, "bot") {
t.Fatalf("NoteTranscript.AuthTypes = %v now includes bot; update the bot+unified stop-path guidance below (and this test) instead of leaving it stale", NoteTranscript.AuthTypes)
}
scene := readSkillDoc(t, "skills/lark-meeting/scenes/query-note-and-artifacts.md")
if !strings.Contains(scene, "`note +detail` 支持 `--as user` / `--as bot`") {
t.Error("query-note-and-artifacts.md must state that note +detail supports both user and bot")
}
if !strings.Contains(scene, "`note +transcript` 仅支持 `--as user`") {
t.Error("query-note-and-artifacts.md must state that note +transcript is user-only (matches NoteTranscript.AuthTypes)")
}
}
// TestNoteUnifiedBotStopPathIsDocumented pins that every doc reachable from a
// `note +detail` -> `note_display_type=unified` routing decision explicitly
// calls out that `+transcript` can't continue under --as bot, rather than
// letting an agent silently drop --as and switch identity.
func TestNoteUnifiedBotStopPathIsDocumented(t *testing.T) {
for _, path := range []string{
"skills/lark-meeting/scenes/query-note-and-artifacts.md",
"skills/lark-meeting/references/lark-note-detail.md",
"skills/lark-meeting/references/lark-note-transcript.md",
} {
content := readSkillDoc(t, path)
if !strings.Contains(content, "bot") || !strings.Contains(content, "user") {
t.Errorf("%s must document the bot+unified boundary for note +transcript (mention both user and bot)", path)
}
}
}
func TestLegacyNoteSkillRoutesToMeetingSkill(t *testing.T) {
skill := readSkillDoc(t, "skills/lark-note/SKILL.md")
for _, must := range []string{
"本技能只用于兼容旧名称,不直接处理业务。",
"../lark-meeting/SKILL.md",
} {
if !strings.Contains(skill, must) {
t.Errorf("skills/lark-note/SKILL.md must preserve compatibility routing %q", must)
}
}
}
func TestMeetingNoteCoverHandlingIsReachable(t *testing.T) {
noteScene := readSkillDoc(t, "skills/lark-meeting/scenes/query-note-and-artifacts.md")
for _, must := range []string{
"第一个 `<whiteboard",
"docs +media-download",
"--type whiteboard",
"./notes/<note_id>/cover",
"--as <source_identity>",
} {
if !strings.Contains(noteScene, must) {
t.Errorf("query-note-and-artifacts.md must preserve note cover handling %q", must)
}
}
meetingScene := readSkillDoc(t, "skills/lark-meeting/scenes/query-meeting-and-artifacts.md")
if !strings.Contains(meetingScene, "query-note-and-artifacts.md") {
t.Error("query-meeting-and-artifacts.md must route intelligent-note body handling to the owning Note scene")
}
}