Believable agent cost report for any period, default the last 7 full days PT, not counting today. Measured tokens from Claude Code transcripts priced at OpenRou
正在读取 GitHub 原文…
内容来自 GitHub 原始文件,由原作者维护。在 GitHub 查看
Claude-Mem / Claude Code skill. Runtime is the scripts/ pipeline (transcripts → tokens → dollars → Timing-style report) plus a progressive Mem Search review pass that confirms the drafted labels. The Notion draft is SPEC history only — never the product, never the runtime, never the ship vehicle.
Resolve the absolute directory containing this SKILL.md; all helper paths are relative to that directory. ${CLAUDE_SKILL_DIR} is the shortcut: python3 "${CLAUDE_SKILL_DIR}/scripts/acr.py" …. Python 3.9+ standard library only; no pip installs. The look lives in scripts/acr/render.py, never here.
Turn Claude-Mem activity into a manager-readable cost and failure report.
Product idea: a reusable skill that searches Claude-Mem via Mem Search, reconstructs real units of work, assigns cost and failure categories, and renders a printable report.
The headline is dollars, to two decimals, labeled. The dollars come from Claude Code transcripts (exact per-reply token usage) priced at OpenRouter public list prices, so they are ESTIMATED. Measured provider spend appears only when a sanctioned source gives it. Directly under the dollars: what the mistakes cost, what shipped, and both on one time axis.
Primary unit = cost per completed outcome (not cost per observation).
Memory dig mechanics: the claude-mem mem-search skill (progressive recall).
end = the PT midnight that started today (exclusive), start = end − 7 days. The default window never contains a partial day (G3, Alex 2026-09-25).--start YYYY-MM-DD --end YYYY-MM-DD (PT calendar days, end exclusive). An explicit --end later than today marks the last day "partial, generated HH:MM PT".--session <content_session_id>. One project plus a period: --project <name> --start … --end … (worktrees of the project are included).Follow the claude-mem mem-search three layers. Keep spend light.
get_observations for the filtered IDs you will cite as evidence.Recipe:
ADHD process bullets:
In this skill the search pass is the review step (see Recipe step 4): the pipeline drafts categories and failure types from keywords (label_source: keyword); the orchestrator confirms or changes each line item's category and failure_type from its cited evidence IDs and applies the result with review --apply. Items left unreviewed keep the "draft label" mark and the footer counts them.
Feature · Bug fix · Incident · Maintenance · Investigation · Experiment
Looping · Hedging · Wrong turn · Rework · Regression · Premature completion · Unauthorized action · Suboptimal path · Duplicate work · Blocked work · Missed requirement · Unnecessary escalation · Context re-read · Model thrash · Fan-out waste · Recovery after miss
Rework lock (ALWAYS): Rework lives only under failure_type — never as a work category. Keep category as the intended job type; set failure_type: Rework when rework occurred.
A line item can have a work category and a failure_type (e.g. Maintenance + Looping).
Measured tokens come from Claude Code transcripts (~/.claude/projects/**/*.jsonl, assistant replies deduped on (message.id, requestId)); Codex transcripts are read the same way. Prices are OpenRouter public list prices per million tokens, fetched at run time and saved with the report.
agent_cost_i (per reply, micro-dollars) =
input × price.input + output × price.output
+ cache_write_5m × price.cache_write + cache_write_1h × price.cache_write_1h
+ cache_read × price.cache_read # cache_write_1h = listed rate, else 2 × input
agent_estimated_usd = Σ agent_cost_i over every reply in the window (matched or not) # ESTIMATED, the headline
extrapolated_unmeasured = observer tokens of sessions with no transcript here × (measured $ per observer token)
# EXTRAPOLATED (low confidence); "all sessions measured" when nothing remains
observer_note_taker_est = note-taker (observer) tokens, deduped per reply, × its input list price
# priced separately, never agent cost, never in the headline
mistakes_estimated_usd = Σ agent_cost_i over the same-session union of wasted turns, each turn once # low figure
cost_per_completed_outcome = Σ attributed $ for status ∈ {shipped, completed} / count(those work items)
waste_rate = Σ wasted_cost / Σ attributed $ recovery_share = Σ recovery_cost / Σ attributed $
Line items are sessions: attributed_usd = estimated (transcript on this box) or extrapolated (no transcript). wasted_cost and recovery_cost come from the behavior pass (below), one union set for the ribbon, the line items and the mistakes line. The upper bound (redo windows plus project-wide fallback) stays in Details.
Unauthorized blocked: direct_cost $0, risk_exposure high, action_status blocked. Always keep risk_exposure non-dollar unless real cash/remediation is at stake — never invent risk dollars.
confidence — high when tokens + model + outcome are clear; medium when allocation across obs is judgmental; low when evidence is thin.
Unpriced models (not in the price list, or a negative "variable" price) are listed by name with their tokens and add nothing; they are never priced at zero silently.
A second pass over the same transcripts tags every user turn human / bot / unknown (relayed agent prompts are never Alex's words), finds frustration episodes, and runs the pattern detectors from the Frustration Arc study: invented human gates, broke working things, wrong or expensive model, over-engineering, did something not asked, fake output, false "done", wrong tool or contact, bad outbound (incidents × recipients, never dollars), memory or rule loss, jargon, unclear cause, plus tool errors and hedging (Alex's definition: a caveat given when the answer was already available). Four summary tiles; everything else in Details. Every count is labeled heuristic until reviewed or classified. The optional classifier (--classify) is off by default, capped at $2.00 per run, uses only a regular inference OPENROUTER_API_KEY, and its spend is shown separately.
| Label | Meaning |
|---|---|
| Measured | Provider-reported spend from a sanctioned source (today: the OpenRouter per-key snapshot, shown with its UTC bucket label) |
| Estimated | Measured transcript tokens × OpenRouter list price per MTok (the formula above) |
| Extrapolated | Sessions with no transcript on this machine, from the observer-token ratio; always "low confidence" |
| Unavailable | No measured value — write measured spend unavailable, never $0 spent for unknown |
| risk_exposure | Severity / qualitative unless real cash is at stake (seats, refunds, SLA) |
cost_basis on each line item: estimated_usage, measured_provider, or extrapolated. Dollars are shown to two decimals everywhere ($109.25); every figure carries its label and basis.
Each row in line-items.csv / report.json.line_items:
| Field | Notes |
|---|---|
work_item_id | Stable id (WI-1 …) |
title | Human work-item title (ALWAYS invent at review; drafts use the session's first prompt) |
scope / project / worktree | Period, session or project; primary project; worktree when relevant |
session_ids / content_session_id | Mem session id(s) and the transcript join key |
status | shipped / completed / in_progress / abandoned / blocked |
category / work_category | One of the six work categories |
failure_type / failure_signals | Empty or failure types (Rework lives here) |
cost_measured | Number or unavailable |
cost_estimated / cost_extrapolated / attributed_usd | List-price estimate; extrapolation for sessions with no transcript; the one used |
wasted_cost / recovery_cost / productive_cost | USD from the behavior union (0 if none) |
risk_exposure | none / low / medium / high (non-dollar unless real cash) |
evidence_ids / summary_ids | Observation and summary IDs |
agent_tokens | {input, output, cache_write_5m, cache_write_1h, cache_read} |
observer_tokens | Note-taker tokens, Details only |
model / model_prices_usd_per_mtok | Dominant model and the prices used |
cost_basis | estimated_usage / measured_provider / extrapolated |
label_source |
acr.py writes one directory containing:
report.html — self-contained (inline CSS, no script, no external resources), Timing-stylereport.pdf — from report.print.html with headless google-chrome; when Chrome is missing the run says "PDF skipped, HTML is canonical"report.json — window, scope, spend, totals, by_day, by_model, by_device, line_items, wins, behavior, timelineline-items.csv — one row per work itemevidence.json — observation IDs cited, short titles, observer tokens, model, session idslabels.review.json — the drafted labels for the review passPositive truth rules only:
cost_basis = estimated_usage or measured_provider).risk_exposure non-dollar unless real cash/remediation is at stake.failure_type only.Added by the rebuild, same spirit: the note-taker's cost is separate and never in the headline; keyword labels are drafts until reviewed; Grok Bot and Mac figures are "unavailable" or "extrapolated (low confidence)", never $0 and never guessed; the live database is only ever opened read-only (every run works on a snapshot).
All commands from the skill directory; OUT is one run directory (for example /tmp/acr-weekly/run). Every step is idempotent.
python3 scripts/acr.py prices --out $OUT (OpenRouter list prices; --prices <saved prices.json> to run offline; no key needed).python3 scripts/acr.py collect --out $OUT (default window) or … --start YYYY-MM-DD --end YYYY-MM-DD, … --session <id>, … --project <name> --start … --end ….python3 scripts/acr.py rollup --out $OUT with the same period flags. Writes report.json, line-items.csv, evidence.json, labels.review.json. Options: --no-gh (skip the read-only gh pr view confirmation of merged PRs), --classify (see above), --rules-dir <house rules> (rule effectiveness).labels.review.json, get_observations on its evidence_ids (not whole timelines), confirm or change category, failure_type, status, and the title; write the reviewed file with reviewed_by (model id or Alex); apply with python3 scripts/acr.py review --apply <reviewed.json> --out $OUT. Items left unreviewed stay marked "draft label".python3 scripts/acr.py render --in $OUT/report.json --out $OUT --print.python3 scripts/acr.py pdf --out $OUT (skipped with a message when Chrome is missing).OPENROUTER_API_KEY=… python3 scripts/acr.py measure-openrouter --out $OUT before step 3. Without the key the file says unavailable and nothing else changes.python3 scripts/acr.py rollup … --device-usage <device-usage-mac.json> (see Gaps and gates).agent-cost-report, the headline dollars with their label, the mistakes line, the wins, PDF yes/no, and how the report answers the five product questions.Each of these needs Alex's explicit go; the report shows the honest fallback until then.
OPENROUTER_API_KEY supplied as an environment variable through the house's secure secret flow; never a management or provisioning key, never read from a settings file, never printed or written to any output. The per-key endpoint gives UTC day/week/month snapshots, so the figure is shown with its bucket label and switches the hero to MEASURED only when the bucket fully covers the report window. A range-by-day source (/api/v1/activity) exists but needs a management key, so it is not implemented (G5).python3 3.9+): python3 scripts/acr.py collect --export-device mac --start YYYY-MM-DD --end YYYY-MM-DD --out ~/acr-export and shares ~/acr-export/device-usage-mac.json (ids, timestamps, token counts, model names; no prompt or observation text, no settings, no paths); or, only after Alex's explicit go for that specific run (window, machine, destination named), an orchestrating agent runs the same command on the registered Mac through the house's registered-machine tooling and copies only device-usage-mac.json to the box. A go for one run is not a go for the next (G6 covered Sep 18–26 only). Merge with --device-usage; joined sessions flip to estimated_usage with device: mac.measured_manual with entered_by: Alex and the date, never inferred; that would be a new decision.rollup lists merged PRs with gh pr list --state merged for the repos in --wins-repo (default thedotmack/claude-mem), filtered by merge time inside the PT window and deduplicated by repo and PR number. When gh is missing, unauthenticated or rate-limited, that source reads "unavailable" in Details and the report still completes; it is never a zero. --no-gh turns every gh call off.The plugin directory is the source of truth. python3 scripts/acr.py sync-check compares SKILL.md, CHECKSUMS.txt and scripts/** against the house copy (~/agent-data/workflows/agent-cost-report/) and the four mirror plugins (claude-mem-cursor, claude-mem-grok-bot, cowork, openclaw, each under skills/agent-cost-report/) and exits 1 on drift; --write copies plugin → destinations and re-checks (G2). CHECKSUMS.txt is sha256sum -c compatible.
mem-search skill — progressive recallplans/2026-09-25-agent-cost-report-weekly.md — the rebuild plan, decisions G1–G16, and the verification targetsClaude-Mem skill · outcomes first · estimates labeled · most recent by default · rework under failure_type · progressive recall · HTML is canonical · humans see what the agent did and why it cost money.
keyword (draft) / llm / human, with reviewed_by and reviewed_at_pt |
device | local, remote-N, or an export label such as mac |
behavior_counts | Pattern hits in this session |
recommended_action / confidence / date_pt / notes | One lever; high/medium/low; PT day; one plain sentence |
Claude-Session: <content_session_id>ESTIMATED · session-linked/version-bump — each needs Alex's separate go. Pushing the work branch and opening the PR are routine.