diff --git a/internal/skilldoc/source_cards_test.go b/internal/skilldoc/source_cards_test.go new file mode 100644 index 0000000..2f76def --- /dev/null +++ b/internal/skilldoc/source_cards_test.go @@ -0,0 +1,26 @@ +package skilldoc + +import ( + "os" + "strings" + "testing" +) + +func TestChannelCardDisambiguatesFlashcatWorkspace(t *testing.T) { + body, err := os.ReadFile("../../skills/flashduty/reference/channel.md") + if err != nil { + t.Fatal(err) + } + text := string(body) + for _, want := range []string{ + "协作空间", + "Flashcat workspace", + "灭火图", + "firemap", + "do not silently switch", + } { + if !strings.Contains(text, want) { + t.Errorf("channel card must disambiguate Flashduty channel vs Flashcat workspace; missing %q", want) + } + } +} diff --git a/skills/flashduty/reference/channel.md b/skills/flashduty/reference/channel.md index 6b6f5b1..025bdc6 100644 --- a/skills/flashduty/reference/channel.md +++ b/skills/flashduty/reference/channel.md @@ -6,6 +6,8 @@ Prereq: `SKILL.md` read. **SKILL.md + this card = full competence on channels "协作空间 / 频道 / 渠道 / 告警分组 / 降噪 / 静默 / 抑制 / 丢弃 / 升级策略 / 告警收敛 / channel / collaboration space / escalation rule / silence / inhibit / drop rule" → **channel**, NOT `incident` (incidents live _inside_ a channel) or `alert` (alerts are routed _into_ a channel). **`协作空间` (collaboration space) IS the `channel` API noun** — a naive translation would be "频道", but Flashduty's product surfaces it as 协作空间. Key IDs: **`channel-id` (int)** from `channel list`; **`rule-id` (MongoDB ObjectID string)** from `escalate-rule-list`, `inhibit-rule-list`, `silence-rule-list`, `unsubscribe-rule-list`. +**Flashcat workspace exception.** When the user asks whether a "空间" is healthy, red/green, or specifically mentions **灭火图 / firemap**, do not assume they mean a Flashduty channel. In that context, "空间" may be a **Flashcat workspace**, and the answer must come from the Flashcat/firemap surface rather than channel incident stats. If you first resolved a name as a Flashduty `channel-id` and later resolve the same visible name as a Flashcat `workspace-id`, **do not silently switch** — tell the user these are different objects and state which ID/surface each conclusion uses. + ## Intent → verb | want | verb | @@ -38,6 +40,7 @@ fduty channel create --channel-name "production-api" --team-id \ # → returns channel_id; use it below # 3. add an escalation rule (all flags; layers is required via --data) +# API field `person_ids` expects member IDs from `fduty member list`. fduty channel escalate-rule-create \ --channel-id --rule-name "P1 on-call" --template-id \ --data '{"layers":[{"target":{"person_ids":[],"by":{"critical":["voice","sms"],"warning":["feishu"]}},"notify_step":5,"max_times":3,"escalate_window":30}]}'