diff --git a/skills/flashduty/SKILL.md b/skills/flashduty/SKILL.md index 093b655..7e7f656 100644 --- a/skills/flashduty/SKILL.md +++ b/skills/flashduty/SKILL.md @@ -15,6 +15,7 @@ hidden: true # internal-only: withheld from skills.sh public discovery (Safari - **Auth.** Set your Flashduty app key once — `export FLASHDUTY_APP_KEY=` — or pass `--app-key ` per call. Then just call the verb. - **No curl for the API.** The CLI is the only supported path to Flashduty — never hand-roll an HTTP call. - **If `fduty: command not found`** (rare — it is normally on PATH at startup): install from the Flashduty CDN into a user-writable dir (no sudo, no hang), then tell the user — don't work around it: `curl -sSL https://static.flashcat.cloud/flashduty-cli/install.sh | FLASHDUTY_INSTALL_DIR="$HOME/.local/bin" INSTALLED_NAME=fduty sh && export PATH="$HOME/.local/bin:$PATH"`. +- **If `jq` is missing** and you genuinely need JSON filtering, it is fine to install it into a user-writable dir the same way (`$HOME/.local/bin`) and continue. But first ask whether you can avoid `jq` entirely by using `--output-format toon`, `--fields`, a returned `total`, or a server-side aggregation verb (`insight`, `rule-counter-*`, etc.). ## Data model — 3 layers @@ -24,6 +25,10 @@ hidden: true # internal-only: withheld from skills.sh public discovery (Safari Append `--output-format toon` to read commands: it drops the per-row repeated keys that JSON emits, so lists cost far fewer tokens. Use `--json` only to pipe into `jq`. Bare output is a human table — don't parse it. +**Count the cheap way.** If a list response already returns `total`, trust that authoritative server count — do not page N times just to count rows. When the question is "how many by status/progress/severity", issue the narrowest server-side filter per bucket and read each response's `total`; for account-wide trends switch to aggregation verbs such as `insight *`, `rule-counter-status`, `rule-counter-node`, or `rule-counter-total`. + +**Shape the payload before you fetch it.** For ID scans, counts, or "find the matching row" tasks, prefer `--fields` projections and compact list verbs over full detail dumps. Huge raw JSON dumps are a last resort, not a default. + **Empty result = authoritative not-found.** A filter returning `[]` means no such entity in scope — report it (optionally the 1–2 closest names) and stop. Do **not** brute-force (no shifted-keyword re-queries, no widening past caps, no full-dump grep). Never infer "feature not enabled" from an empty list, and never fabricate data absent from tool output. **A result you did not fetch is "unknown", never "empty".** You may report a command's result — including "returned empty" or any count/list/finding — **only if that exact command appears in your tool-call history this turn**. If you did not run it, the honest answer is "未查询 / not queried", followed by the command to run. Writing "`incident similar` 返回空" or "无变更" for a command you never executed is fabrication, not a summary. diff --git a/skills/flashduty/reference/alert.md b/skills/flashduty/reference/alert.md index 6c63ec8..ef91058 100644 --- a/skills/flashduty/reference/alert.md +++ b/skills/flashduty/reference/alert.md @@ -130,6 +130,8 @@ View alert timeline - **All alert verbs are positional except `list` and the two-ID `merge` flag.** Every verb with `` in its `use` form takes that ID as the first bare argument — do NOT pass `--alert-id`. The single exception: `merge` takes the first alert ID positionally AND requires `--incident-id` as a flag (two different IDs, different roles). - **`alert get` vs `alert info`, `alert events` vs `alert-event list`:** both pairs exist; prefer `get`/`events` (shorter, no extra flag); `info`/`event-list` accept `--alert-id` as a flag override for scripting. - **No server-side title filter on `list`.** To search by title, use `--json` and pipe to `jq`: `fduty alert list --json | jq '.[] | select(.title | test("disk";"i"))'` +- **If `list` returns a `total`, use it.** Do not paginate page 1/2/3... just to count alerts. Ask the narrowest question (`--active`, `--recovered`, `--severity`, `--channel`, `--since`) and read the server-reported total for that bucket. +- **Use `--fields` when hunting IDs, not full rows.** If the task is "find alert IDs / titles / channels / severities", project only those fields first, then drill into one alert with `get` / `events`. Dumping every field for 100 alerts wastes tokens and hides the one row you need. - **`list` time window cap is 31 days**; `--limit` max is 100. For broader queries use `insight` domain. - **`pipeline-upsert` fully replaces** the existing pipeline — always fetch current config with `pipeline-info` first and include unchanged rules in the new body. - **Empty `list` result is authoritative** — report "no alerts match" and stop; do not widen filters or retry with alternate keywords. diff --git a/skills/flashduty/reference/incident.md b/skills/flashduty/reference/incident.md index 743794b..4063413 100644 --- a/skills/flashduty/reference/incident.md +++ b/skills/flashduty/reference/incident.md @@ -362,6 +362,8 @@ List war rooms - **24-char `incident_id` vs 6-char `num`**: positional-id verbs (`ack`, `close`, `resolve`, `detail`, `alerts`, `timeline`, `merge`, `reassign`, `comment`, `reset`, …) require the full ObjectID. Passing a 6-char num 400s. Use `incident info --num ` to resolve, or `incident list --query ` and read `incident_id`. - **`similar` only works on channel-backed incidents** (those with a real `channel_id`). Manually created incidents with no channel return HTTP 400 "Channel not found" — this is expected, not transient. Fall back to `incident list --query ""` for text search. - **`update` vs `reset`**: `update ` edits title/description/severity/custom fields. `reset ` additionally supports `--impact`, `--root-cause`, `--resolution` (the AI narrative fields). Use `reset` for post-incident write-back. +- **If `list` returns a `total`, use it instead of page-walking.** For "how many incidents are Triggered / Processing / Closed", run one filtered `incident list --progress ...` per bucket and read the returned `total`. Do not fetch page 1/2/3 just to derive counts the server already computed. +- **Use `--fields` to keep list scans compact.** When the goal is to identify matching incidents or collect IDs/numbers/titles, project only the needed columns first, then fetch one target incident with `detail` / `alerts` / `timeline`. - **`--list` window cap**: `--since`/`--until` window must be < 31 days; `--limit` max 100. Empty result is authoritative — do not widen filters or retry. - **`merge` is irreversible**: source incidents are absorbed into target permanently. Always list and confirm both IDs before running. - **`remove --force`** bypasses the interactive confirmation prompt — never pass `--force` unless the user has explicitly said so. diff --git a/skills/flashduty/reference/monit.md b/skills/flashduty/reference/monit.md index b18b785..7d59779 100644 --- a/skills/flashduty/reference/monit.md +++ b/skills/flashduty/reference/monit.md @@ -68,6 +68,19 @@ fduty monit tools-invoke --target-locator --output-format toon EOF ``` +## Hot flow — inventory all monitor alert rules without guessing folders + +```bash +# 1. get the distribution first; this is the cheap way to answer "how many rules are where / in what status" +fduty monit rule-counter-status --output-format toon + +# 2. list rules only for the concrete folder you care about +fduty monit rule-list-basic --folder-id --output-format toon + +# 3. export the exact rules you selected +fduty monit rule-export --ids ,, --output-format toon +``` + ### datasource-create @@ -327,6 +340,9 @@ Invoke target tools - **`query-rows` has no time flags.** There is no `--time-start` / `--time-end` / `--operation`. Embed all time range and bucketing inside `--expr`. Passing those flags is a silent no-op or error. - **`query-diagnose` time window via `--data`**, not flags. Pass `{"time_range":{"start":,"end":},...}`. Window wider than 6 hours is rejected server-side. Omitting `time_range` defaults to the last 15 minutes. - **`rule_configs` and nested arrays require `--data`.** The queries, thresholds, enabled_times, and labels objects cannot be expressed as flat flags — pass them as inline JSON via `--data '{"rule_configs":{...}}'`. Typed scalar flags (`--name`, `--enabled`, `--cron-pattern`, `--ds-type`) override matching `--data` keys. +- **`folder-id 0` is not a universal "all rules" sentinel.** If the API says "Folder not found", believe it. For global inventory use `rule-counter-status` / `rule-counter-node` first, then run `rule-list-basic` against real folder IDs only. +- **"全量规则 / full rules" means exported monitor alert-rule definitions.** The concrete verb is `rule-export --ids ...`, usually after `rule-list-basic` selected the IDs. It does not mean dumping incidents or alerts. +- **For rule counts, prefer the counter verbs over list pagination.** `rule-counter-status`, `rule-counter-node`, and `rule-counter-total` are the authoritative aggregation surfaces; do not infer counts by walking `rule-list-basic` pages. - **`tools-catalog` / `tools-invoke` `--target-locator` is required and not guessable.** If the user has not provided a host or IP, ask — do not invent one. Tool names in `invoke` must come from the `tools-catalog` response — never hallucinate them. - **`rule-delete-batch` and `datasource-delete` are irreversible.** Confirm IDs with `rule-list-basic` / `datasource-info` first. - **`rule-audit-detail --id` takes the audit record ID**, not the rule ID. Get audit record IDs from `rule-audits --id ` first; passing the rule ID returns HTTP 400. @@ -334,9 +350,10 @@ Invoke target tools ## Worked example — inspect a firing rule then batch-disable it ```bash -# 1. find triggered rules in folder 0 (all accessible) -fduty monit rule-list-basic --folder-id 0 --output-format toon -# look at triggered=true rows; note their ids +# 1. inspect top-level distribution, then choose a real folder id +fduty monit rule-counter-status --output-format toon +fduty monit rule-list-basic --folder-id --output-format toon +# look at the rows you actually care about; note their ids # 2. get full config of one rule fduty monit rule-info --id --output-format toon