Add PyPI metadata: readme, classifiers, project URLs - #3
Merged
Conversation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
anshss
added a commit
that referenced
this pull request
Apr 12, 2026
…dex migration - Use cursor-local .description instead of connection-level to avoid race conditions with concurrent queries - Fix get_traces() GROUP BY to aggregate per trace_id only; use subquery for name and error-aware CASE expression for status_code - Add migration #3 to recreate missing performance indexes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2 tasks
anilmurty
added a commit
that referenced
this pull request
Jun 19, 2026
…#10,#13) Smoke-test playbook (tests/manual-new-release-tests.md): - #3 (and #8/#9/#11/#12/#14/#16 — same root cause): code blocks are now command-only; the inline "# comments" and "# [ ]" checklists that the markdown copy button was pulling into copied commands moved to prose / "- [ ]" lists around each block. Added a note explaining the convention. - #10: corrected the Section 4 trim expectation — with [capture] prompts=false (default), trim checks the capture prereq first and prints the capture hint, NOT the tokenjam[bloat] install hint (only reachable once capture is on). - #13: export file is "claude-code-<date>.jsonc", not ".json". Doc-only; no code changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
anilmurty
added a commit
that referenced
this pull request
Jun 23, 2026
, #213) (#218) * Add Lens cost charts: stacked by-model/agent + cache-savings time-series Wave 1 of the Lens Visualizations milestone (#3). Two new cost charts on the Cost screen, both server-shaped (the UI consumes the response + the framing block, never re-deriving plan-tier rules). #213 — Stacked cost-by-model / -by-agent over time. The /cost `series` already grouped by (bucket, agent, model); it now also carries `provider` + the full token-component split (cache read/write) so it's the reusable group-by shape the future analytics explorer (#210) can pivot too. A new StackedBarChart renders cumulative back-to-front uPlot bars (cheap, offline) for the model/agent toggle; `total` keeps the line view. Plan-tier framing respected — subscription/local stack token volume, not raw spend. #212 — Cache-savings time-series. New GET /api/v1/cost/cache returns per-bucket cache hit-rate (cache_read / (cache_read + input)) and the dollars already *captured* by real cache reads, priced per (provider, model) as cache_read_tokens × (input_rate − cache_read_rate) — a measured figure. The window-level *estimated recoverable* comes from the cache analyzer's #111 contract. A new CacheSavingsChart draws cumulative captured (left axis) + hit- rate (right axis) + a dashed "achievable" envelope (captured + recoverable). Honesty discipline (Critical Rule 14): "captured" is measured; the gap is "estimated recoverable", never "saved" — the caption says so verbatim, and the recoverable dollar routes through the framing block (tokens for subscription). Both /cost and /cost/cache share a single `_framing_block` helper (window- independent plan mix, #177) so neither re-derives the suppression rules. Tests: endpoint tests (httpx + InMemoryBackend) pin the reusable series shape, the hit-rate/captured math, the recoverable passthrough, and subscription framing; static-grep UI regressions assert the stacked + cache charts/helpers and the honesty caption are present; test_ui_offline stays green; the extracted app module passes `node --check`. Closes #213 Closes #212 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(lens): add Wave 1 cost-chart review screenshots Review aids for the #212/#213 PR — the stacked cost-by-model/agent chart and the cache-savings time-series (captured vs estimated-recoverable). Kept under docs/lens/wave1/; drop in review if binaries on main are undesired. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: drop committed Lens screenshots from the diff Keep main binary-free — review screenshots belong in the PR description, not in git history. The captures are preserved out-of-repo for review/docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
anilmurty
added a commit
that referenced
this pull request
Jun 23, 2026
…een (#224) The differentiated Lens viz (#211, milestone #3): split the window's spend into the four token components and overlay each optimize analyzer's attributed recoverable waste — the cost-WASTE view a generic activity dashboard can't show because it depends on our analyzers' attributed estimates. New GET /api/v1/cost/components computes, server-side: - the component cost split (input / output / cache-read / cache-write), priced per (provider, model) via the pricing table so it's exact, not apportioned from the aggregate cost_usd; and - a registry-driven per-analyzer recoverable list — it iterates the typed downgrade slot plus every wave-2 finding carrying the #111 recoverable contract field, so a new analyzer appears automatically with no code change. Each entry keeps the analyzer's own caveat + estimate_basis verbatim and the component its savings act on ("call" = whole-call model swap / call elimination, for analyzers that can't be honestly pinned to one component). The UI adds a ComponentWasteChart (vendored uPlot stacked bars, offline intact): two columns — measured "Cost" stacked by component and "Recoverable (est.)" stacked by analyzer. They are SEPARATE bars; recoverable is never subtracted from cost and never called "saved" (Critical Rule 14) — the caption reads "a heuristic estimate to review before acting, not a realized cost reduction". A per-analyzer list under the chart surfaces each estimate behind the "estimated recoverable" tag with its caveat. Every figure routes through the framing block (fmtFramedSavings / fmtFramedDollar) so subscription/local users see token-share, not raw dollars, and the bars themselves switch to token volume. The endpoint fetch is best-effort — a failure never blanks Optimize. Tests: endpoint tests (httpx + InMemoryBackend) pin the per-component pricing, the registry-driven recoverable (reuse appears from the findings dict), the downsize caveat verbatim, "saved" absent from the payload, and subscription framing; static-grep UI regressions assert the chart/helpers, the registry- driven build (no hard-coded analyzer list), the honesty caption + "saved" absent from the surface, and the framing routing; test_ui_offline stays green and the app module passes node --check. Closes #211 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
anilmurty
pushed a commit
that referenced
this pull request
Jul 2, 2026
#4) Claude Code's built-ins leave a real, documented gap: /compact is reactive, lossy and single-session; /context shows current-session totals only. Neither attributes WHAT is burning quota across sessions nor suggests a structural fix. A whole DIY ecosystem (ccusage, codeburn, context-analyzer, session-recall, ...) has sprung up to fill it — the strongest revealed-demand signal. Proof point: anthropics/claude-code#24147, where a dev hand-parsed 30 days of JSONL to find CLAUDE.md re-reads consumed 99.93% of their quota. `tj context` runs a local diagnostic over Claude Code sessions and reports: 1. Per-turn context composition — what share of each turn went to RE-READING prior context (cache-read tokens: conversation history, CLAUDE.md, accrued tool output) vs. NET-NEW WORK (uncached input + output), with the re-read overhead named. 2. Recurring inclusions — the same file re-read across many sessions, frequency-counted, each with a concrete `@file` / CLAUDE.md structural fix (capture-gated on `[capture] tool_inputs`). 3. Compact candidates — sessions whose accumulated re-reading makes a mid-session /compact reclaim the most quota. Framing is quota-native (the subscription majority): headline numbers render as token-share / "% of cycle tokens" via core/framing.py — the single source of truth for plan-tier-aware rendering — for Pro/Max users. Dollars are a SECONDARY calibration signal for API users, never the headline. Output is a screenshottable terminal card; `--json` for machine-readable output. Honesty discipline (CLAUDE.md Rule 14): every figure is a measured token share or a structural candidate flag, never a guaranteed saving; re-read tokens are cache reads (billed at a reduced rate, not free) — real quota, stated as such. Needs a direct DuckDB connection (reads the raw `attributes` column, which the API shim doesn't expose) — fails gracefully with a `tj stop` hint when the daemon holds the lock, mirroring `tj report --trim`. Scoped OUT of v1 (named, not faked): MCP schema-injection attribution and prompt-cache-miss attribution aren't derivable from current backfill data; recurring-inclusion detection covers file Reads only. Per the #3 handoff, content lands only on freshly-ingested spans after enabling `[capture]` — the command surfaces that nudge rather than silently showing empty recurring data. Covered by tests/unit/test_context_diagnostic.py over a synthetic multi-session fixture: per-turn re-read-vs-work composition, cross-session recurring-inclusion detection with structural fix, compact-candidate detection, the capture-off nudge, and end-to-end CLI rendering of quota-share for a Max plan. Co-Authored-By: Claude <noreply@anthropic.com>
anilmurty
pushed a commit
that referenced
this pull request
Jul 2, 2026
The Claude Code backfill ran one existence-check SELECT plus one INSERT per span in `_insert_session_idempotent` — ~2 DuckDB round-trips per span, so a large history (~120k spans) paid ~240k statements (~100s). #13 bounded only the quickstart first-run path; the full `tj backfill claude-code` / daemon path still paid the full per-span cost. Replace the per-span loop with a bulk path that processes a whole session in a BOUNDED number of statements regardless of span count: - Partition new-vs-existing span_ids in ONE chunked `WHERE span_id IN (...)` query (`_existing_span_ids`) instead of N existence SELECTs. - Bulk-insert the new spans in a single `executemany` (`_SPAN_INSERT_SQL` + `_span_insert_params`, kept in lock-step with `DuckDBBackend.insert_span`). - On `--reingest`, batch-load the existing rows' attributes in ONE chunked query (`_load_attrs_bulk`), compute the per-key attribute merge in Python, then apply the updates in a single `executemany`. The #10 idempotency + reingest contract is preserved exactly: new spans insert; existing spans without `--reingest` are skipped untouched; existing spans with `--reingest` get `sub_agent_id` updated and `attributes` per-key merged (overlay `{**stored, **parsed}`, parsed wins, never wipes a stored key). The no-`conn` fallback path is unchanged. Drops the now-unused single-span `_load_attrs` helper. Tests: all existing #3/#10/#13 backfill tests pass unchanged. Adds four #15 tests — bulk insert lands every new span; existing spans are skipped without `--reingest`; `--reingest` still merges attributes (overlay, no wipe) + updates sub_agent_id; and a counting-connection test asserting a 400-span session inserts in a BOUNDED number of statements (well under N execute() calls, via executemany) rather than ~2 per span. Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit 6f94fe0)
anilmurty
pushed a commit
that referenced
this pull request
Jul 2, 2026
… flags (#3) The Claude Code JSONL backfill parser recomputed cost from token/model metadata but never extracted per-message content or tool-input from the transcript — even though that data is present and core/transcript.py already reads it. Because backfill bypasses IngestPipeline/strip_captured_content, the [capture] toggles were a no-op on the CC path: flipping capture.prompts changed nothing. This blocked the context-cost diagnostic (#4), which needs per-message content + inclusion args to attribute tokens. parse_claude_code_session now accepts a CaptureConfig and, gated per toggle, populates the assistant LLM span with gen_ai.prompt.content (the triggering human prompt) and gen_ai.completion.content (the agent narration), and each tool span with gen_ai.tool.input (the raw args). The keys match GenAIAttributes so downstream consumers and alert content-stripping treat backfilled content identically to live content. ingest_claude_code reads config.capture and forwards it; iter_claude_code_sessions threads it through. Extraction is strictly opt-in: the None default and the all-False CaptureConfig default leave every span's attributes byte-for-byte unchanged ({"source": ...}), so a default backfill is unchanged and stays 100% local. Reuses _block_text from core/transcript.py for the record-walking. Co-Authored-By: Claude <noreply@anthropic.com>
This was referenced Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
readme = "README.md"so PyPI renders the project descriptionauthors,classifiers, and[project.urls](Homepage, Repository, Issues)PyPI will pick up these changes on the next release.
Test plan
python -m buildsucceeds🤖 Generated with Claude Code