用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/jleechanorg/claude-commands --skill spend-alert-bridge命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Token-efficient second opinion slash command /advice. Extracts decision point + artifact (≤150 lines), then fans out in parallel: (1) Opus subagent reviewer with fallback chain codex→agy→cursor, (2) /research on the decision topic, (3) /secondo multi-model opinion. Use instead of advisor() which ships the full conversation uncached.
Use this skill when working in repositories managed by Agent Orchestrator or when the user asks how to use `ao` properly. Covers the default AO workflow: bootstrap with `ao start`, dispatch work with `ao spawn`, inspect progress with `ao status` or `ao session ls`, steer sessions with `ao send`, and recover or clean up sessions safely. Includes strict parameter fidelity, pre-spawn cap cleanup, quota-wall fallback, and post-spawn verification.
Generate a full agento PR status report — draft readiness, canonical /green, zero-touch rate, inline display, and Slack summary.
正在显示 SKILL.md
基于 SOC 职业分类
| name | spend-alert-bridge |
| description | Diagnose why a Spend Alert (GitHub Actions MTD/7-day breach, MCP Agent Mail relay, |
The spend-alert-daily.sh launchd script posts a Slack alert to #worldai-alerts (C0BCVG4F560) when GitHub Actions daily Δ or 7-day rolling exceeds its threshold. The user sees this alert re-routed to their session context via MCP Agent Mail (a separate relay process, com.mcp.agent.mail, PID ~1151), but nothing in the dropped-thread-watcher pipeline watches Agent Mail. Combined result: the alert appears in human-facing chat but there is no hook that pings me to reply in-thread.
Three distinct failure modes, all recurring:
The script posts correctly, the alert lands in #worldai-alerts, MCP Agent Mail relays it. But the user still gets a "why is spend $X" message because the alert numbers are real and trace to a runaway workflow. The bridge isn't broken — the cost is real.
Important nuance: the script's "MTD delta" is NOT a true daily-spend metric. GH's billing API returns monthly buckets only (date == "2026-07-01T00:00:00Z" for all of July). The script subtracts two snapshots taken 24h apart to estimate daily burn — this conflates real-time burn with billing-API lag. When the API finalizes a batch overnight, the next morning's delta will spike without any real new spend.
The first instinct: look at which workflow fired thousands of times. The 2026-07-23
incident was initially diagnosed as a comment-router.yml runaway (5,566 issue_comment
runs/32h, all conclusion=skipped). The comment-router's if: correctly skipped
each one, but the workflow_run event still registered.
This is real but usually a SYMPTOM, not the cause. The actual 5,566 comments were being posted by a different process — see Mode A.2.
The recurring shape that has actually been driving the spend spikes:
~/projects/dark-factory) posts the same 🤖 [dark-factory] Escalation required: refusing factory PR adoption comment to 1-3 PRs every ~1h as part of a feedback loopissue_comment event fires comment-router.yml once, which correctly skips at the job levelruns API balloons to thousands, polluting metrics and (in the daemon's case) triggering more downstream side effects2026-07-23 incident (bead $USER-rouf):
your-project.com#8428 (1,791 posts), #8420 (1,773), #8421 (1,770)[dark-factory] comments in 32h on these 3 PRs alone (vs ~6,000/48h for ALL of comment-router traffic)tick.rs adoption_branch_collision block posted the comment BEFORE the dedup check ran, AND the dedup key was escalation_ledger(bead_id, reason) (fresh bead_id every tick) instead of the stable branchadopted.head_ref_name AND move the dedup check before comment_external in tick.rs:1027-1053 (line numbers shift as the file is refactored — grep for adoption_branch_collision to find the current location)⚠️ 2026-07-24 INCIDENT — the documented fix was NOT actually merged. The fix commit cb2136ffedb307347175c03107670744ad496b9b ("fix(daemon): dedupe adoption_branch_collision escalation per branch ($USER-rouf)") exists on branch fix/escalation-dedupe-cooldown (dated 2026-07-23 12:08 PT) but is NOT on main (b04df6f449 is main HEAD as of this incident). git merge-base --is-ancestor cb2136ffe HEAD returns "NO — NOT on main". The daemon running via launchd therefore is still executing the buggy code. The spend spike on 2026-07-24 ($35.15 GH Actions in one day, 4× baseline) is the same A.2 pattern recurring because the fix never landed. See references/dark-factory-fix-unmerged-2026-07-24.md for the full verification sequence.
Diagnostic recipe when comment-router is the noise source:
# 1. Pull the actual comment bodies (not the workflow runs — the comments are upstream)
REPO="$GITHUB_REPOSITORY"
# NOTE: the `since` query param is ignored for `repos/<repo>/issues/comments` —
# paginate with `sort=created&direction=desc` and filter the timestamp in-process.
gh api "repos/$REPO/issues/comments?per_page=100&direction=desc&sort=updated" \
| jq -r '.[] | "\(.user.login)\t\(.author_association)\t\((.body // "")[0:80])"'
# 2. Group by author_association + author login + body prefix
# 99% of "noisy" comments will share a body prefix from one automation
gh api "repos/$REPO/issues/comments?per_page=100&direction=desc&sort=updated" \
| jq 'group_by(.author_association) | map({aa: .[0].author_association, n: length})'
# 3. Find the source — likely dark-factory daemon, GitHub Actions bot, or a cron
# Dark-factory escalation body always starts with: "🤖 **[dark-factory]** Escalation required:"
If dark-factory is the source, fix is in jleechanorg/dark-factory not $GITHUB_REPOSITORY — BUT FIRST verify the fix actually landed:
# 1. Find the dedup fix commit
cd ~/projects/dark-factory
git log --all --oneline --grep="adoption_branch_collision" | head -5
# 2. Check if it's been merged into main
FIX_SHA=$(git log --all --oneline --grep="adoption_branch_collision" | head -1 | awk '{print $1}')
git merge-base --is-ancestor "$FIX_SHA" HEAD && echo "merged" || echo "NOT MERGED"
# 3. If NOT merged, the daemon is still running buggy code. Either:
# a. Merge the branch that contains the fix (preferred), then rebuild the daemon
# binary, then `launchctl kickstart -k gui/$(id -u)/ai.dark-factory.af-tick`
# b. As a stopgap, `launchctl bootout` the daemon to suppress the comment spam
# (the daemon will still restart on its own tick interval — bootout is not a fix)
# 4. ALWAYS verify the fix is on main BEFORE telling the user "fix is shipped"
Why this matters: fixing comment-router.yml (the downstream consumer) does NOT
stop the spend alert. The fix lives at the source — the daemon that posts the comments
in the first place. The comment-router's job-level if: is already correct; it just
gets hit thousands of times because the upstream daemon is in a loop.
set -u crash in spend-alert-daily.sh (2026-07-16, RESOLVED)log_warn "$1" aborts on unbound variable when called with no arg during slack_post's stderr pipe under set -euo pipefail. The script terminates before slack_post ever fires. Fix landed — log_warn "${1:-}" (and same for log, log_error) per PR in jleechanorg/jleechanclaw. If you see this in tail -40 of the log, the fix has regressed.
| # | Mode | Cause | Fix |
|---|---|---|---|
| 1 | A.1 | comment-router.yml (PR #8354–#8355) was supposed to consolidate 4 issue_comment workflows, but its on: issue_comment trigger fires on EVERY comment, and the if: guard skips 99%+ of them. The fix only consolidated workflows; it didn't reduce trigger volume. | Add if: github.event.comment.author_association == 'OWNER' to the on: issue_comment trigger; cap concurrency (N=5). BUT verify this isn't a downstream symptom of an upstream spam loop first (see A.2). |
| 2 | A.2 | Dark-factory daemon (~/projects/dark-factory/daemon/src/tick.rs — grep for adoption_branch_collision) in an adoption_branch_collision loop posts the same 🤖 [dark-factory] Escalation required comment to 1-3 PRs every ~1h. The dedup key was escalation_ledger(bead_id, reason) (fresh bead every tick → never matches) AND the comment posted BEFORE the dedup check ran. | (a) Move escalation_dedup_should_emit BEFORE comment_external AND re-key dedup on adopted.head_ref_name (stable across colliding beads) instead of adopted.bead_id. (b) VERIFY the fix commit (cb2136ffe or successor) is on main HEAD before claiming the fix is shipped — git merge-base --is-ancestor $FIX_SHA HEAD. Branch fix/escalation-dedupe-cooldown had the fix but was NOT merged as of 2026-07-24 incident. |
| 3 | B | set -u in spend-alert-daily.sh aborts on log_warn "$1" when called with no arg | log_warn "${1:-}" everywhere, OR remove -u from the script's set line. |
The bot identity is a member of C0BCVG4F560 (verified 2026-07-23 via conversations.info returning is_member=true for the bot token fetched from ~/.bashrc HERMES_SLACK_BOT_TOKEN). The standalone bot token from HERMES_SLACK_BOT_TOKEN posts reliably; the scoped MCP identity in this session may report is_member=false because it's a different bot identity — don't conflate the two.
cat $HOME/.hermes/logs/spend-alert-daily.log | tail -40 — confirm whether the last run completed the Slack post or crashed on the set -u line. If it completed, the alert is in the channel — you're in Mode A (real cost spike), not Mode B (bridge broken).jq . $HOME/.hermes/state/spend-alert-state.json — check the rolling deltas match what the user reported. If gh_delta jumped 3x+ over baseline (e.g. $61 vs typical $15), the runway is the cause, not a billing error.curl -fsS -H "Authorization: Bearer $(bash -c 'source ~/.bashrc; echo $HERMES_SLACK_BOT_TOKEN')" "https://slack.com/api/conversations.history?channel=C0BCVG4F560&limit=5" — confirm whether the alert landed in #worldai-alerts. This is the right verification — mcp__slack__conversations_replies may falsely report not_in_channel for the scoped identity.comment-router.yml symptom + a dark-factory daemon cause — see step 7.issue_comment events have one of a small set of body prefixes (e.g. 🤖 [dark-factory] Escalation required:), the comment-router is the victim, not the cause. The fix lives in the source that posts the comments. See Mode A.2 in the failure pattern above for the dark-factory-specific recipe.git -C <repo> merge-base --is-ancestor <fix-sha> HEAD. If the result is "NOT MERGED", the daemon is still running buggy code. Either merge the branch or stop claiming the fix is shipped. (See incident 2026-07-24 — fix on fix/escalation-dedupe-cooldown was never merged, daemon still spammed comments, second spend spike identical to the first.)# Step 1: script log + state
tail -40 $HOME/.hermes/logs/spend-alert-daily.log
jq . $HOME/.hermes/state/spend-alert-state.json
# Step 2: channel membership & recent posts
TOK=$(bash -c 'source ~/.bashrc; echo $HERMES_SLACK_BOT_TOKEN')
curl -fsS -H "Authorization: Bearer $TOK" \
"https://slack.com/api/conversations.list?types=public_channel,private_channel&limit=200" \
| jq '.channels[] | select(.id=="C0BCVG4F560")'
# Step 3: identify the cost-driver repo
gh api "orgs/jleechanorg/settings/billing/usage" --paginate \
| jq '[.usageItems[]? | select(.product == "actions") | select(.date == "2026-07-01T00:00:00Z")] | sort_by(-.netAmount)'
# Step 4: identify the runaway workflow in that repo (last 32h)
# NOTE: `created=>` query param is treated as equality, not greater-than.
# Use `sort=created&direction=desc` and walk pages manually until the
# oldest run's `created_at` < SINCE.
REPO="jleechanorg/<repo>"
python3 ./scripts/gh-cost-audit.py # see scripts/ dir
scripts/spend-alert-daily.sh: change log_warn "$1" to log_warn "${1:-}" (and same for log, log_error), OR remove -u from the script's set line. Pair with scripts/tests/test_spend_alert_idempotent.py (or similar) so the crash mode is regression-tested. Status 2026-07-23: fix is in place; no crash observed today.comment-router.yml patterns — workflows that listen to high-volume issue_comment events and use a job-level if: guard. The job guard short-circuits before billable minutes, but the workflow still registers an event. Mitigations:
if: at the workflow/job level that filters by author_association, comment body prefix, and issue.pull_request BEFORE the runner is allocatedconcurrency group to a tight key (comment-router-${{ github.event.comment.id }} is already present in this file — verify it)if: contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association) guardbead_id) instead of a stable identifier (e.g. head_ref_name). Mitigations:
comment_external, gh api repos/.../issues/.../comments) — otherwise the write is never suppressed even if the dedup would have matchedcfg.escalation_refire_secs cooldown (default 3600s) so re-emission is bounded even if the dedup logic has a buggit merge-base --is-ancestor <fix-sha> <deployment-branch>. A commit on fix/escalation-dedupe-cooldown is not a fix until that branch is merged into main AND the daemon binary is rebuilt AND the running launchd job is restarted.git merge-base --is-ancestor <fix-sha> HEAD before claiming the fix is merged. The 2026-07-24 incident was caused by trusting a previous skill's stated fix location without re-verifying.created=> query param on gh api repos/<repo>/actions/runs is treated as EQUALITY, not greater-than. It returns 0 hits even when plenty of runs exist after the date. Use sort=created&direction=desc + manual pagination instead./actions/runs/{id}/timing returns billable: {} for completed runs. The billable field is reserved for in-progress / queued runs. To approximate cost, use updated_at - created_at to compute wall-clock minutes and multiply by the runner type's $/min rate. The gh-actions-cost-monitor.sh script does this with COST_PER_MINUTE=0.002 (Linux self-hosted rate).gh-api repos/<repo>/issues/comments ignores the since query parameter. The since field on the comment-schema response is also undefined. To filter comments to a time window, paginate (sort=created + direction=desc) and filter by created_at in-process.runs API sees run_duration_ms as 0/null for skipped runs even if the workflow allocated a runner. Use runs.total_count to gauge trigger volume, not minutes.run_duration_ms field — it returns null or 0 for skipped runs, even if the workflow was allocated a runner. Use updated_at - created_at to get the real wall-clock time per run.is_member=False from mcp__slack__conversations_replies is global to the bot — it's per-identity. The HERMES_SLACK_BOT_TOKEN env may resolve to a different bot identity than the one bound to the live Slack MCP server. Use with the bot token to verify, not from the scoped MCP.references/comment-router-runaway-2026-07-23.md — original 2026-07-23 incident detailreferences/dark-factory-fix-unmerged-2026-07-24.md — verification that the documented fix was never mergedscripts/gh-cost-audit.py — runs/workflow volume audit helper (32h window, per-workflow breakdown with skip counts)scripts/comment-audit.py — issue_comments audit helper (per-author, per-prefix, per-hour breakdown for time-windowed analysis)conversations.historyconversations_repliesbead_id as a dedup key. Per-tick fresh objects (new bead IDs, new session IDs) make the ledger never match. Use stable identifiers (branch name, PR number, commit SHA) for dedup keys.mcp__slack__conversations_add_message from this session context — it's the wrong identity. Use chat.postMessage with the bot token from ~/.bashrc.date == "2026-07-01T00:00:00Z" is the entire month, not a day. Don't try to slice it by day; you'll see empty results. The script's gh_delta is a 24h-difference between two MTD snapshots, NOT a true daily-spend figure.conclusion=skipped means 0 billable minutes, but the workflow_run event is registered. If a workflow fires 5,000+ times in 32h, the runs API is polluted even if no minutes are billed. Use the runs API for diagnosing trigger volume, not the billing API.comment-router.yml fires 5,000+ times/32h on issue_comment, the first instinct is to harden the workflow (add author_association guard, lower concurrency). That fixes the symptom but misses the cause: an upstream automation (most commonly the dark-factory daemon) is in a feedback loop posting the same comment to 1-3 PRs every ~1h. Pull the actual comment bodies via repos/<repo>/issues/comments?per_page=100&direction=desc&sort=updated and group by user.login + body prefix BEFORE proposing a workflow fix. If 99% of comments come from one automation with one body prefix, the fix lives at that automation, not at the comment-router. See Mode A.2 for the dark-factory-specific fix.