Skip to content

fix(hooks): correct cost-tracker pricing table and filter harness noise from session summaries - #2772

Open
lojasetetoco wants to merge 1 commit into
affaan-m:mainfrom
lojasetetoco:fix/pricing-and-session-summary
Open

fix(hooks): correct cost-tracker pricing table and filter harness noise from session summaries#2772
lojasetetoco wants to merge 1 commit into
affaan-m:mainfrom
lojasetetoco:fix/pricing-and-session-summary

Conversation

@lojasetetoco

Copy link
Copy Markdown

Summary

Two fixes to runtime hooks, found while auditing a fresh 2.2.0 plugin install:

1. scripts/hooks/cost-tracker.js — stale pricing table

  • RATE_TABLE.opus was $15/$75 per MTok (Opus 3/4.0/4.1 legacy pricing). Current Opus 5 and Opus 4.5–4.8 are $5/$25, so estimated_cost_usd in ~/.claude/metrics/costs.jsonl overstated Opus sessions ~3x (verified against live rows).
  • claude-fable-5 / claude-mythos-5 matched no branch and fell through to Sonnet rates ($3/$15 instead of $10/$50), understating ~3.3x.
  • Haiku updated to 4.5 pricing ($1/$5).
  • Opus 4.0/4.1/3 keep the legacy tier via a dedicated opusLegacy branch.

2. scripts/hooks/session-end.js — harness noise in session summaries

extractSessionSummary treated local-command echoes as user asks, so the cross-session summary's Tasks list filled with <local-command-caveat>, <command-name>, <local-command-stdout> fragments — and SessionStart then re-injected that noise as context. Now filters those tags, <system-reminder>/<task-notification> blocks, tool_result carrier turns, and isMeta entries. Verified against a live transcript: Tasks now contains only real user messages.

Testing

  • node tests/hooks/cost-tracker.test.js — 10/10 pass
  • node tests/hooks/session-end.test.js — 1/1 pass

🤖 Generated with Claude Code

…e from session summaries

cost-tracker.js: RATE_TABLE priced all Opus models at the legacy $15/$75
tier and routed Fable/Mythos 5 to Sonnet rates, overstating Opus 5
sessions ~3x and understating Fable ~3.3x in costs.jsonl. Adds fable
($10/$50) and current opus ($5/$25) tiers, keeps Opus 4.0/4.1/3 on the
legacy tier, updates haiku to 4.5 pricing ($1/$5).

session-end.js: extractSessionSummary included local-command echoes
(<local-command-caveat>, <command-name>, <local-command-stdout>),
system reminders, tool_result carrier turns and isMeta entries in the
Tasks list, so SessionStart reloaded noise instead of user asks. Adds
a noise filter.

Both test suites pass (10/10 cost-tracker, 1/1 session-end).

Co-Authored-By: Claude Fable 5 <[email protected]>
@lojasetetoco
lojasetetoco requested a review from affaan-m as a code owner August 12, 2026 16:54
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Updated usage cost calculations for newly supported models and revised model rates.
    • Improved session summaries by excluding tool-generated results, system noise, metadata, and empty messages.

Walkthrough

The PR updates model pricing and matching in the cost tracker. It also filters tool results, harness noise, and metadata from session summary user messages.

Changes

Model pricing

Layer / File(s) Summary
Pricing rates and model matching
scripts/hooks/cost-tracker.js
The cost tracker adds Fable/Mythos pricing, revised Haiku and Opus rates, and a legacy Opus tier for selected Opus models.

Session summary filtering

Layer / File(s) Summary
User message filtering
scripts/hooks/session-end.js
Session summaries skip tool_result entries, harness noise, and metadata entries.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • affaan-m/ECC#2691: Updates the same cost tracker logic and also changes session-end message extraction.
  • affaan-m/ECC#2693: Overlaps with the shared model-rate and Fable/Mythos pricing changes.

Suggested reviewers: affaan-m

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes both primary fixes: pricing corrections and harness-noise filtering in runtime hooks.
Description check ✅ Passed The description directly explains the pricing corrections, session-summary filtering, and reported test results.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/hooks/cost-tracker.js`:
- Around line 73-88: Expand the cost-tracker tests with table-driven cases
covering Fable, Mythos, Haiku 4.5, current Opus, and legacy Opus pricing tiers,
asserting both selected rates and calculated costs. Include
claude-opus-4-20250514 to verify it routes to the intended legacy/current tier,
and ensure the JavaScript test coverage remains at least 80%.
- Around line 88-89: Update the model-routing logic in the cost-tracker matcher
so the canonical Opus 4.0 identifier pattern used by the integration test,
including claude-opus-4-20250514, resolves to RATE_TABLE.opusLegacy before the
generic opus branch. Preserve the existing routing for other model identifiers.

In `@scripts/hooks/session-end.js`:
- Around line 46-52: Add regression tests covering the filtering branches in the
session-end message processing: array content containing tool_result, each
harness-noise tag, and entries marked isMeta. For every filter, verify both that
matching entries are excluded and that legitimate user messages remain; assert
filtered entries do not increase totalMessages.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 36cc17ca-54a3-469f-92aa-cf37d33d0738

📥 Commits

Reviewing files that changed from the base of the PR and between 569b1d5 and db170c4.

📒 Files selected for processing (2)
  • scripts/hooks/cost-tracker.js
  • scripts/hooks/session-end.js
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (18)
**/*.{js,ts,jsx,tsx,py,java,cs,go,rb,php,scala,kt}

📄 CodeRabbit inference engine (.cursor/rules/common-coding-style.md)

**/*.{js,ts,jsx,tsx,py,java,cs,go,rb,php,scala,kt}: Always create new objects, never mutate existing ones. Use immutable patterns to prevent hidden side effects and enable safe concurrency
Organize code into many small files (200-400 lines typical, 800 lines max) organized by feature/domain rather than by type
Always handle errors explicitly at every level and never silently swallow errors
Always validate all user input before processing at system boundaries
Use schema-based validation where available
Fail fast with clear error messages when validation fails
Never trust external data (API responses, user input, file content)
Ensure code is readable and well-named
Keep functions small (less than 50 lines)
Keep files focused (less than 800 lines)
Avoid deep nesting (more than 4 levels)
Do not use hardcoded values; use constants or configuration instead

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php,swift,kt,rs,c,cpp,h,hpp}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

No hardcoded secrets (API keys, passwords, tokens) - validate before any commit

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php}: All user inputs must be validated
Enable CSRF protection on all state-changing endpoints
Verify authentication and authorization for all protected endpoints
Implement rate limiting on all endpoints to prevent abuse
Ensure error messages do not leak sensitive data in responses

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php,sql}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

Use parameterized queries to prevent SQL injection

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{js,ts,jsx,tsx,html,php,java,cs,rb,go}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

Implement XSS prevention by sanitizing HTML output

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php,swift,kt,rs,c,cpp,h,hpp,properties,yml,yaml,json,env,config}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

NEVER hardcode secrets in source code - ALWAYS use environment variables or a secret manager

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript-coding-style.md)

**/*.{ts,tsx,js,jsx}: Use spread operator for immutable updates in TypeScript/JavaScript instead of direct mutation
Use async/await with try-catch for error handling in TypeScript/JavaScript
Use Zod for schema-based input validation in TypeScript/JavaScript
No console.log statements in production code; use proper logging libraries instead

**/*.{ts,tsx,js,jsx}: Auto-format JavaScript/TypeScript files using Prettier after edit
Warn about console.log statements in edited files
Check all modified files for console.log statements before session ends

**/*.{ts,tsx,js,jsx}: Use the ApiResponse interface pattern with generic type parameter: interface ApiResponse<T> { success: boolean; data?: T; error?: string; meta?: { total: number; page: number; limit: number; } }
Implement custom React hooks following the pattern: export a named function with use prefix, generic type parameters, and proper useEffect cleanup for side effects

**/*.{ts,tsx,js,jsx}: Never hardcode secrets; always use environment variables for sensitive credentials like API keys
Throw an error when required environment variables are not configured to fail fast and ensure security prerequisites are met

Use Playwright as the E2E testing framework for critical user flows in TypeScript/JavaScript

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
{package.json,*.config.js,scripts/**/*.js}

📄 CodeRabbit inference engine (CLAUDE.md)

Package manager detection should support npm, pnpm, yarn, and bun, with configuration via CLAUDE_PACKAGE_MANAGER environment variable or project config.

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
scripts/**/*.js

📄 CodeRabbit inference engine (CLAUDE.md)

Ensure cross-platform support for Windows, macOS, and Linux via Node.js scripts in the scripts/ directory.

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,ts,jsx,tsx}: Always create new objects and never mutate in place; return new copies instead
Keep files between 200–400 lines typical, with a maximum of 800 lines
Extract helpers when a file exceeds 200 lines
Handle errors explicitly at every level; never swallow errors silently
Validate all user input before processing; use schema-based validation where available
Never trust external data (API responses, file content, query params); always validate
All user inputs must be validated and sanitized
Error messages must be scrubbed of sensitive internals
Use readable, well-named identifiers in all code
Keep functions under 50 lines
Keep files under 800 lines
Avoid nesting deeper than 4 levels
Implement comprehensive error handling in all code
Do not hardcode values; use constants or environment configuration instead
Do not use in-place mutation; always return new objects or state

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{js,ts,jsx,tsx,json,env*}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not hardcode secrets, API keys, passwords, or tokens

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{js,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,ts}: Use parameterized queries for all database writes (no string interpolation)
Auth/authz must be checked server-side for every sensitive path
Rate limiting must be applied to all public endpoints

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{jsx,tsx,js,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

HTML output must be sanitized where applicable

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{js,ts,env*}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Required environment variables must be validated at startup

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{js,jsx,ts,tsx,py,java,kt,go,rs,cpp,c,h,cs,rb,php}

📄 CodeRabbit inference engine (AGENTS.md)

Test-Driven — Write tests before implementation, 80%+ coverage required

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Security-First — Never compromise on security; validate all inputs
Immutability — Always create new objects, never mutate existing ones

  • No hardcoded secrets (API keys, passwords, tokens)
  • All user inputs validated
  • Authentication/authorization verified
  • Error messages don't leak sensitive data
    Immutability (CRITICAL): Always create new objects, never mutate. Return new copies with changes applied.
    Error handling: Handle errors at every level. Provide user-friendly messages in UI code. Log detailed context server-side. Never silently swallow errors.
    Input validation: Validate all user input at system boundaries. Use schema-based validation. Fail fast with clear messages. Never trust external data.
    Minimum coverage: 80%
    TDD workflow (mandatory):
    Commit format: <type>: <description> — Types: feat, fix, refactor, docs, test, chore, perf, ci
    API response format: Consistent envelope with success indicator, data payload, error message, and pagination metadata.

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
**/*.{sql,js,jsx,ts,tsx,py,java,kt,go,rs,php}

📄 CodeRabbit inference engine (AGENTS.md)

  • SQL injection prevention (parameterized queries)

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js
{scripts,bin}/**

⚙️ CodeRabbit configuration file

{scripts,bin}/**: Focus on command injection, unsafe subprocess usage, path traversal, SSRF, secret exposure, and missing tests for new CLI behavior.

Files:

  • scripts/hooks/session-end.js
  • scripts/hooks/cost-tracker.js

Comment on lines +73 to +88
// Current-generation list prices: Fable/Mythos 5 $10/$50, Opus 5 and
// Opus 4.5-4.8 $5/$25, Sonnet 5/4.6 $3/$15, Haiku 4.5 $1/$5. Opus 4.0/4.1
// and Opus 3 stay on the legacy $15/$75 tier.
const RATE_TABLE = {
haiku: { in: 0.80, out: 4.0, cacheWrite: 1.00, cacheRead: 0.08 },
sonnet: { in: 3.00, out: 15.0, cacheWrite: 3.75, cacheRead: 0.30 },
opus: { in: 15.00, out: 75.0, cacheWrite: 18.75, cacheRead: 1.50 }
haiku: { in: 1.00, out: 5.0, cacheWrite: 1.25, cacheRead: 0.10 },
sonnet: { in: 3.00, out: 15.0, cacheWrite: 3.75, cacheRead: 0.30 },
opus: { in: 5.00, out: 25.0, cacheWrite: 6.25, cacheRead: 0.50 },
opusLegacy: { in: 15.00, out: 75.0, cacheWrite: 18.75, cacheRead: 1.50 },
fable: { in: 10.00, out: 50.0, cacheWrite: 12.50, cacheRead: 1.00 }
};

function getRates(model) {
const m = String(model || '').toLowerCase();
if (m.includes('fable') || m.includes('mythos')) return RATE_TABLE.fable;
if (m.includes('haiku')) return RATE_TABLE.haiku;
if (m.includes('opus-4-1') || m.includes('opus-4-0') || m.includes('3-opus')) return RATE_TABLE.opusLegacy;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add regression tests for every new pricing branch.

The supplied cost-tracker test checks only that one estimate is positive. It does not assert exact rates for Fable, Mythos, Haiku 4.5, current Opus, or legacy Opus. Add table-driven cases that verify tier selection and computed cost. Include claude-opus-4-20250514 to catch the routing defect above.

As per coding guidelines, JavaScript changes require tests before implementation and at least 80% coverage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/hooks/cost-tracker.js` around lines 73 - 88, Expand the cost-tracker
tests with table-driven cases covering Fable, Mythos, Haiku 4.5, current Opus,
and legacy Opus pricing tiers, asserting both selected rates and calculated
costs. Include claude-opus-4-20250514 to verify it routes to the intended
legacy/current tier, and ensure the JavaScript test coverage remains at least
80%.

Source: Coding guidelines

Comment on lines +88 to 89
if (m.includes('opus-4-1') || m.includes('opus-4-0') || m.includes('3-opus')) return RATE_TABLE.opusLegacy;
if (m.includes('opus')) return RATE_TABLE.opus;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Route the canonical Opus 4.0 identifier to the legacy tier.

The supplied integration test uses claude-opus-4-20250514 in tests/hooks/cost-tracker.test.js Lines 75-130. Line 88 does not match this identifier, so Line 89 applies RATE_TABLE.opus at $5/$25 instead of RATE_TABLE.opusLegacy at $15/$75. Match the canonical Opus 4.0 form or parse the model version explicitly.

Suggested matcher fix
-  if (m.includes('opus-4-1') || m.includes('opus-4-0') || m.includes('3-opus')) return RATE_TABLE.opusLegacy;
+  const isLegacyOpus4 =
+    m.includes('opus-4-0') ||
+    m.includes('opus-4-1') ||
+    /(?:^|-)opus-4-\d{8}(?:-|$)/.test(m);
+  if (m.includes('3-opus') || isLegacyOpus4) return RATE_TABLE.opusLegacy;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (m.includes('opus-4-1') || m.includes('opus-4-0') || m.includes('3-opus')) return RATE_TABLE.opusLegacy;
if (m.includes('opus')) return RATE_TABLE.opus;
const isLegacyOpus4 =
m.includes('opus-4-0') ||
m.includes('opus-4-1') ||
/(?:^|-)opus-4-\d{8}(?:-|$)/.test(m);
if (m.includes('3-opus') || isLegacyOpus4) return RATE_TABLE.opusLegacy;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/hooks/cost-tracker.js` around lines 88 - 89, Update the model-routing
logic in the cost-tracker matcher so the canonical Opus 4.0 identifier pattern
used by the integration test, including claude-opus-4-20250514, resolves to
RATE_TABLE.opusLegacy before the generic opus branch. Preserve the existing
routing for other model identifiers.

Comment on lines +46 to +52
// Skip tool_result carrier turns — they are not user asks.
const isToolResult = Array.isArray(rawContent) && rawContent.some(c => c && c.type === 'tool_result');
const text = typeof rawContent === 'string' ? rawContent : Array.isArray(rawContent) ? rawContent.map(c => (c && c.text) || '').join(' ') : '';
const cleaned = stripAnsi(text).trim();
if (cleaned) {
// Skip harness noise: local command echoes, caveats, system reminders.
const isNoise = /^<(local-command-caveat|local-command-stdout|command-name|command-message|command-args|system-reminder|task-notification)/i.test(cleaned);
if (cleaned && !isToolResult && !isNoise && !entry.isMeta) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add regression tests for every new filter.

The supplied test covers array content parsing, but it does not cover tool_result, each harness tag, or isMeta. Add positive and negative cases for these branches. Verify that legitimate user messages remain and that filtered entries do not increase totalMessages.

As per coding guidelines, “Test-Driven — Write tests before implementation, 80%+ coverage required.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/hooks/session-end.js` around lines 46 - 52, Add regression tests
covering the filtering branches in the session-end message processing: array
content containing tool_result, each harness-noise tag, and entries marked
isMeta. For every filter, verify both that matching entries are excluded and
that legitimate user messages remain; assert filtered entries do not increase
totalMessages.

Source: Coding guidelines

@greptile-apps

greptile-apps Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This change updates model-cost classifications and removes harness-generated transcript noise from cross-session summaries.

Two data-quality failures remain. scripts/hooks/cost-tracker.js assigns the dated Opus 4.0 identifier to the lower current Opus pricing tier when no fresh authoritative cache is available, understating recorded fallback costs. scripts/hooks/session-end.js drops genuine user text when it shares a content array with a tool_result, so follow-up requests can disappear from persisted session Tasks.

T-Rex validation blocked

The exact hook paths were executed and their output was captured, but the required evidence could not be uploaded because the artifact-upload tool or endpoint was unavailable. Local evidence paths cannot be presented as uploaded artifacts.

Confidence Score: 3/5

The change is not ready to merge because fallback cost records can be materially understated and genuine follow-up requests can be omitted from session continuity data.

Two independent user-visible logic failures were exercised through the real hook entry points: the dated Opus 4.0 fallback recorded $30 instead of $90 for the tested token usage, and a mixed text/tool-result turn lost text that persisted in the text-only baseline.

Files Needing Attention: scripts/hooks/cost-tracker.js needs dated Opus 4.0 legacy-rate handling and regression coverage. scripts/hooks/session-end.js needs block-level tool-result filtering so non-tool text is retained. Focused tests should cover both behaviors.

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex attempted reproductions of the cost-tracker and session-end flow, captured the resulting outputs, but the Greptile artifact-upload tool remained unavailable, preventing verification proofs from being uploaded.
  • T-Rex produced a proof for a posted P1 finding; a review comment provides the details.
  • T-Rex produced a second P1 finding proof, described in another review comment.
  • T-Rex notes that no artifact-upload mechanism exists to return IDs or URLs, and local artifact references are present for the session-end mixed-tool repro.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (2)

  1. General comment

    P1 Opus 4.0 dated model identifier falls through to current Opus rates

    • Bug
      • With no fresh harness-cost cache, claude-opus-4-20250514 was estimated at $30 for 1M input plus 1M output tokens, rather than the $90 legacy Opus 4.0 estimate.
    • Cause
      • The legacy checks accept opus-4-1 and opus-4-0, but not the dated identifier opus-4-20250514, which subsequently matches generic opus.
    • Fix
      • Classify dated Opus 4.0 identifiers as legacy before the generic Opus branch and add a regression test.

    T-Rex Ran code and verified through T-Rex

  2. General comment

    P1 Mixed user content arrays lose genuine task text when any block is a tool_result

    • Bug
      • A user transcript entry containing both text and a tool_result block omits the genuine text from the persisted Tasks summary.
    • Cause
      • The hook treats any tool_result in the content array as grounds to reject the entire turn.
    • Fix
      • Retain meaningful non-tool-result text while excluding only tool-result blocks.

    T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "fix(hooks): update cost-tracker pricing ..." | Re-trigger Greptile

const m = String(model || '').toLowerCase();
if (m.includes('fable') || m.includes('mythos')) return RATE_TABLE.fable;
if (m.includes('haiku')) return RATE_TABLE.haiku;
if (m.includes('opus-4-1') || m.includes('opus-4-0') || m.includes('3-opus')) return RATE_TABLE.opusLegacy;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Dated Opus 4.0 model uses current rates

When the authoritative harness-cost cache is absent or stale, claude-opus-4-20250514 does not match the legacy predicates and falls through to the generic Opus rate. The transcript fallback therefore records $30 for 1M input plus 1M output tokens instead of the $90 legacy Opus 4.0 estimate. Classify this dated Opus 4.0 identifier as opusLegacy before the generic opus branch and add a regression case for the fallback path.

Comment on lines +46 to +52
// Skip tool_result carrier turns — they are not user asks.
const isToolResult = Array.isArray(rawContent) && rawContent.some(c => c && c.type === 'tool_result');
const text = typeof rawContent === 'string' ? rawContent : Array.isArray(rawContent) ? rawContent.map(c => (c && c.text) || '').join(' ') : '';
const cleaned = stripAnsi(text).trim();
if (cleaned) {
// Skip harness noise: local command echoes, caveats, system reminders.
const isNoise = /^<(local-command-caveat|local-command-stdout|command-name|command-message|command-args|system-reminder|task-notification)/i.test(cleaned);
if (cleaned && !isToolResult && !isNoise && !entry.isMeta) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Mixed user turns discard genuine task text

A user content array containing both a text block and a tool_result block is rejected wholesale because isToolResult is true when any block is a tool result. The same text persists as a Task in a text-only turn but disappears in the mixed-block case, so legitimate follow-up requests are lost from cross-session context. Exclude only tool_result blocks when extracting text instead of skipping the whole turn.

Comment on lines +86 to 87
if (m.includes('fable') || m.includes('mythos')) return RATE_TABLE.fable;
if (m.includes('haiku')) return RATE_TABLE.haiku;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 New classifications lack regression coverage

The changed rate mappings and transcript exclusions lack assertions for exact legacy Opus costs and mixed tool-result, noise, and meta content, allowing these classifications to regress without failing the test suite.

Rule Used: Treat CLI inputs, URLs, file paths, and subprocess... (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant