Skip to content

feat(traces): record model, reasoning effort, and token usage per session event#320

Open
efenocchi wants to merge 13 commits into
mainfrom
feat/trace-model-tokens
Open

feat(traces): record model, reasoning effort, and token usage per session event#320
efenocchi wants to merge 13 commits into
mainfrom
feat/trace-model-tokens

Conversation

@efenocchi

@efenocchi efenocchi commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator

What

Records model, reasoning effort, and token consumption on captured session traces, so per-model token usage is a simple query over the sessions table. Covers every code assistant the plugin captures.

Neither Claude Code nor Codex passes this in the hook payload, but both write it to the on-disk transcript the capture hooks already receive a path to. Pi and OpenClaw expose model+usage on the in-process SDK message. A shared module reads/normalizes it and the capture paths enrich the JSONB message column — no schema migration.

Coverage (verified end-to-end against real transcripts)

Agent model reasoning effort token usage source
Claude Code n/a (no per-message field) ✅ input/output/cache transcript last assistant turn
Codex ✅ input/output/cache/reasoning + cumulative rollout turn_context + token_count
Pi n/a ✅ input/output/cache SDK message_end
OpenClaw n/a ✅ input/output/cache SDK agent_end
Cursor ✅ (already) n/a none exists in its transcript payload
Hermes none in payload

Stored shape (JSONB message)

{ "model": "claude-opus-4-8", "reasoning_effort": null,
  "token_usage": { "input_tokens": 131, "output_tokens": 403,
                   "cache_read_tokens": 357059, "cache_creation_tokens": 2102 } }

Codex rows additionally carry reasoning_effort and token_usage_total (whole-session cumulative).

How

  • New src/notifications/model-usage.ts: parseClaudeTurnMeta, parseCodexTurnMeta, and normalizeSdkUsage/sdkTurnMeta (Pi/OpenClaw). Normalized keys across agents; absent fields stay absent; non-negative-safe-integer filtering; best-effort (null on any failure).
  • Wiring: src/hooks/capture.ts (Claude), src/hooks/codex/capture.ts (Codex), harnesses/openclaw/src/index.ts (import), harnesses/pi/extension-source/hivemind.ts (inlined — pi ships raw .ts).
  • src/hooks/shared/redact.ts: guard so the entropy backstop doesn't shred provider model ids now stored in every row (would break per-model rollups) — narrow enough that a secret wearing a model prefix is still masked.

Testing

  • scripts/trace-model-usage-e2e.mjs drives the real capture hooks (Claude/Codex/Cursor/Hermes) across every model in the local transcripts, writes to a throwaway table, reads back, and asserts each agent's rows landed with token_usage for the token-bearing agents. Pi/OpenClaw capture in-process, so it proves their enriched entry from a real transcript message. Passes.
    • Verified models incl. claude-opus-4-8 / sonnet-4-6 / haiku-4-5, gpt-5.6-sol / gpt-5.5 (+ reasoning + cumulative), pi gpt-5.5, openclaw anthropic/claude-sonnet-4.
    • The sessions table drops/lags rapid same-table bursts (200 OK, rows=0); the harness paces + retries and reports invoked-vs-visible honestly. This is a backend characteristic, not a feature defect.
  • Unit tests: tests/shared/notifications-model-usage.test.ts, redaction guard tests in tests/shared/redact.test.ts. tsc clean; full suite green except one pre-existing, unrelated cli-bundle-runtime tree-sitter test (environmental; my diff touches no graph/CLI code).

Review

codex review run twice (initial + expanded scope); all findings fixed — SubagentStop transcript, Codex turn-boundary scoping, cumulative-vs-per-model semantics, non-object JSONL guard, redaction guard tightening, and e2e capture-verification. CodeRabbit findings (invalid token counts, per-turn effort reset) also fixed.

Summary by CodeRabbit

  • New Features
    • Captured assistant messages now include model identifiers, reasoning effort, and token usage when available.
    • Added support for usage metadata across Claude, Codex, Pi, and OpenClaw sessions.
  • Bug Fixes
    • Provider model identifiers are no longer incorrectly redacted as secrets.
    • Metadata extraction gracefully handles missing, malformed, or incomplete transcripts.
  • Tests
    • Added coverage for usage normalization, transcript parsing, metadata capture, and secret redaction.

New shared module src/notifications/model-usage.ts with two best-effort
parsers that read the on-disk transcript the capture hooks already receive
a path to:

- parseClaudeTurnMeta: last assistant turn's model + usage from a Claude
  Code transcript. Reasoning effort left null (no per-message field).
- parseCodexTurnMeta: model + reasoning_effort (turn_context) + per-turn
  and cumulative token usage (token_count) from a Codex rollout.

Both normalize onto a shared NormalizedUsage shape (cache_read_tokens,
cache_creation_tokens, reasoning_output_tokens, total_tokens) so a
per-model rollup is a single GROUP BY over the sessions table. Absent
fields stay absent; any read/parse failure returns null.

Covered by tests/shared/notifications-model-usage.test.ts (real transcript
shapes: reverse-scan, omitted fields, malformed lines, model fallback,
last-vs-total usage).
Enrich the assistant_message trace row (Stop event) with model,
reasoning_effort (null for Claude) and per-turn token_usage, read from the
transcript's last assistant turn via parseClaudeTurnMeta. Best-effort: the
row is written unchanged when the transcript is unreadable.
Enrich the Codex trace meta with reasoning_effort, per-turn token_usage
and cumulative token_usage_total from the rollout (parseCodexTurnMeta).
Codex emits no assistant event, so the enrichment rides on every
user/tool row; the running total rolls up per model with MAX, not SUM.
The turn_context model refines the payload model when present.
Four correctness fixes from the codex review of this branch:

- SubagentStop: parse agent_transcript_path when present. transcript_path
  points at the parent session, so the subagent's assistant event was
  recording the parent model/usage (capture.ts).
- Codex per-turn usage: clear it on each turn_context so a new turn's model
  never inherits the previous turn's tokens. total stays cumulative.
- token_usage_total: documented as whole-session cumulative (across all
  models), not per-model; per-model totals sum per-turn usage deduped by
  turn_id. Fixed the misleading MAX-per-model note.
- Best-effort contract: skip non-object JSONL roots (a bare `null` line)
  before dereferencing, in both parsers.

Tests extended: turn-boundary model change omits stale usage; bare-null
line survives in both parsers.
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@efenocchi, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: eaebb857-aa69-4b0a-bd8d-c42b9bf8ad52

📥 Commits

Reviewing files that changed from the base of the PR and between 603bd04 and 551912a.

📒 Files selected for processing (3)
  • scripts/trace-model-usage-e2e.mjs
  • src/hooks/shared/redact.ts
  • tests/shared/redact.test.ts
📝 Walkthrough

Walkthrough

Adds best-effort model and token-usage extraction for Claude, Codex, Pi, and OpenClaw captures, validates the metadata through unit and E2E tests, and prevents recognized provider model identifiers from being redacted as secrets.

Changes

Transcript metadata enrichment

Layer / File(s) Summary
Metadata contracts and parsing helpers
src/notifications/model-usage.ts
Defines normalized usage metadata and parses Claude and Codex JSONL transcripts with fallback and validation behavior.
Capture hook metadata integration
src/hooks/capture.ts, src/hooks/codex/capture.ts
Merges parsed metadata into Claude assistant and Codex user-message/tool-call entries.
Transcript parser test coverage
tests/shared/notifications-model-usage.test.ts
Tests normalization, fallback, turn boundaries, malformed input, and missing metadata.
Pi and OpenClaw entry enrichment
harnesses/pi/extension-source/hivemind.ts, harnesses/openclaw/src/index.ts
Adds model and token-usage metadata to assistant rows captured from SDK payloads.

End-to-end usage verification

Layer / File(s) Summary
Usage tracing and verification workflow
scripts/trace-model-usage-e2e.mjs
Discovers real transcripts, invokes compiled hooks, polls stored rows, checks metadata invariants, and cleans up test data.

Model identifier redaction handling

Layer / File(s) Summary
Provider model identifier preservation
src/hooks/shared/redact.ts, tests/shared/redact.test.ts
Exempts recognized provider model slugs from entropy masking while continuing to redact high-entropy secrets with similar prefixes.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CaptureHooks
  participant ModelUsageParsers
  participant TranscriptFiles
  participant SessionsTable
  CaptureHooks->>ModelUsageParsers: Parse transcript or SDK usage metadata
  ModelUsageParsers->>TranscriptFiles: Read JSONL transcript when needed
  TranscriptFiles-->>ModelUsageParsers: Return transcript events
  ModelUsageParsers-->>CaptureHooks: Return normalized model metadata
  CaptureHooks->>SessionsTable: Insert enriched capture rows
  SessionsTable-->>CaptureHooks: Return stored entries
Loading

Possibly related PRs

  • activeloopai/hivemind#307: Updates the shared redaction implementation and tests that this change extends for provider model identifiers.

Suggested reviewers: khustup2

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 61.54% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description covers the change, but it does not follow the required template and omits Version Bump and Test plan sections. Rewrite it using the repo template with Summary, Version Bump, and Test plan sections, including whether package.json was bumped.
✅ Passed checks (3 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly summarizes the main change: recording model, reasoning effort, and token usage in trace events.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/trace-model-tokens

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.

@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Scope: files changed in this PR. Enforced threshold: 90% per metric (per file via vitest.config.ts).

Status Category Percentage Covered / Total
🟢 Lines 97.97% (🎯 90%) 241 / 246
🟢 Statements 94.92% (🎯 90%) 280 / 295
🟢 Functions 100.00% (🎯 90%) 27 / 27
🔴 Branches 86.19% (🎯 90%) 181 / 210
File Coverage — 4 files changed
File Stmts Branches Functions Lines
src/hooks/capture.ts 🟢 95.3% 🔴 83.9% 🟢 100.0% 🟢 100.0%
src/hooks/codex/capture.ts 🟢 97.2% 🔴 82.5% 🟢 100.0% 🟢 100.0%
src/hooks/shared/redact.ts 🟢 97.2% 🟢 92.8% 🟢 100.0% 🟢 100.0%
src/notifications/model-usage.ts 🟢 92.2% 🔴 87.2% 🟢 100.0% 🟢 93.8%

Generated for commit 675a7c4.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@src/notifications/model-usage.ts`:
- Around line 72-78: Update readLines to avoid synchronously rereading and
splitting the entire transcript on every event. Maintain a per-transcript
cursor/cache or otherwise read only bytes appended since the previous call,
while preserving the missing-transcript handling and returning the newly
available lines needed by callers.
- Around line 62-64: Update toNum in model-usage.ts to return a value only when
v is a finite, non-negative safe integer; return undefined for negative,
fractional, unsafe, or otherwise invalid inputs before they reach usage
aggregation persistence.
- Around line 204-211: Update the turn_context handling in the model-usage
parser to reset model and reasoningEffort for every new turn, using the current
hook model only as the fallback when the new context’s model is missing or
malformed and clearing invalid or absent effort instead of retaining the
previous value. Preserve last/total behavior, and add a regression test covering
a valid first context followed by a context with missing or malformed
model/effort.
🪄 Autofix (Beta)

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: CHILL

Plan: Pro Plus

Run ID: 7de3d604-2726-4324-b4f3-4cebcf231d7a

📥 Commits

Reviewing files that changed from the base of the PR and between c4f1ef6 and b9fc044.

📒 Files selected for processing (4)
  • src/hooks/capture.ts
  • src/hooks/codex/capture.ts
  • src/notifications/model-usage.ts
  • tests/shared/notifications-model-usage.test.ts

Comment thread src/notifications/model-usage.ts
Comment on lines +72 to +78
function readLines(path: string): string[] | null {
if (!path || !existsSync(path)) {
log(`transcript missing: ${path}`);
return null;
}
try {
return readFileSync(path, "utf-8").split("\n");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

Avoid synchronously rereading the entire transcript for every event.

Codex calls this on every user/tool row, making transcript processing cumulative O(n²) and blocking the hook as sessions grow. Read only the tail/new bytes, or maintain a per-transcript cursor/cache.

🤖 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 `@src/notifications/model-usage.ts` around lines 72 - 78, Update readLines to
avoid synchronously rereading and splitting the entire transcript on every
event. Maintain a per-transcript cursor/cache or otherwise read only bytes
appended since the previous call, while preserving the missing-transcript
handling and returning the newly available lines needed by callers.

Comment thread src/notifications/model-usage.ts
…effort per turn

- toNum: accept only non-negative safe integers, so negative / fractional /
  unsafe values never enter token aggregates.
- turn_context: reset both model and reasoning effort per turn (hook model as
  fallback) so a later turn that omits effort no longer inherits the previous
  turn's effort — same scoping fix already applied to per-turn usage.

Tests: per-turn model/effort reset with hook-model fallback; negative and
fractional token counts dropped.
@efenocchi

Copy link
Copy Markdown
Collaborator Author

CodeRabbit triage:

  • toNum (invalid token counts) — fixed in 52910dc: only non-negative safe integers pass.
  • turn_context effort scoping — fixed in 52910dc: model and effort reset per turn (hook model as fallback), matching the per-turn usage scoping.
  • readLines O(n²) full re-read — acknowledged, deferring to a follow-up. Rationale: the capture hooks run async:true, each read is a few ms on transcripts of realistic size, and this mirrors the existing transcript-parser.ts which also reads the whole transcript. A per-transcript cursor/cache (handling truncation/rotation) is a self-contained optimization better done separately rather than bundled into this behavioral change. Tracking it as a follow-up.

normalizeSdkUsage maps the pi/openclaw usage shape
{input, output, cacheRead, cacheWrite, totalTokens} onto the shared
NormalizedUsage keys; sdkTurnMeta builds the {model, token_usage} enrichment
from an in-process SDK message (these runtimes expose no reasoning effort).
Same non-negative-safe-integer filtering as the transcript parsers.

Tests cover the real Pi and OpenClaw usage shapes (incl. cacheWrite ->
cache_creation_tokens) and the model-only / empty cases.
Storing the model on every trace row exposed a latent false positive: the
high-entropy backstop masked long dated slugs like
`claude-haiku-4-5-20251001` -> `********`, which would silently break
per-model token rollups. Add a model-identifier guard to looksLikeSecret
(claude/gpt/o*/gemini/... optionally provider-prefixed) so these survive
redaction. Regression test asserts common ids are preserved.
The agent_end auto-capture loop now enriches assistant rows with model and
normalized token_usage from the SDK message (via the shared sdkTurnMeta).
User rows are unchanged.
message_end now enriches the assistant row with model and normalized
token_usage from the SDK message. Pi ships as raw .ts with no shared-module
imports, so the normalizer is inlined in lockstep with
src/notifications/model-usage.ts (same pattern as the inlined JWT helpers).
scripts/trace-model-usage-e2e.mjs drives the real capture hooks (Claude
Code, Codex, Cursor, Hermes) against every model found in the local
transcripts, writing to a throwaway table and reading the rows back to show
what landed in the JSONB message column. Pi and OpenClaw capture in-process
(not via stdin hooks), so it proves their enriched entry from a real
transcript message via the shared sdkTurnMeta. Suppresses side effects
(HIVEMIND_WIKI_WORKER=1), disables embeddings, and cleans up its rows.
Address codex review [P1]: the earlier exemption used a case-insensitive
prefix match with an open charset, so a random key wearing a model prefix
(`gpt-AbCd…30chars`) would be exempted and stored unmasked. Narrow it to
lowercase-only ids with each dot/dash segment capped at 12 chars, so no 24+
high-entropy run (mixed-case or long) can satisfy it. Added a negative test
asserting prefixed high-entropy secrets are still masked.
… agent

Address codex review [P2] plus the sessions-table write behaviour observed
while running it:
- The hooks swallow insert errors and exit 0, so exit code is not proof.
  Read the rows back and assert each agent's capture path landed rows, with
  token_usage present for the token-bearing agents (claude_code, codex).
- The table drops rapid same-table bursts (200 OK, rows=0, row never lands)
  and is read-after-write lagged. Pace inserts (SLEEP_MS), poll the read-back,
  and retry stragglers; report invoked-vs-visible per agent instead of
  silently treating a hidden tail as success.
- Derive the agent from the session_id prefix (the SQL `agent` column reads
  back unreliably here).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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/trace-model-usage-e2e.mjs`:
- Around line 290-301: Strengthen scripts/trace-model-usage-e2e.mjs at lines
290-301 by retaining expected parser metadata per session and comparing every
stored model, reasoning-effort, usage, and cumulative-usage field for each
capture path, rather than checking only row presence; update lines 312-318 to
exercise Pi’s inline normalizer and both integrations’ real entry/write paths
with assertions, ensuring logging or missing transcripts cannot count as
success.
- Around line 297-301: Update the validation loops in the trace-model usage
check to require rows only for agents recorded in invokedByAgent. Gate both
modelsByAgent and tokenRowsByAgent checks on whether each agent was actually
invoked, while preserving the existing missing-row problems for invoked agents.

In `@src/hooks/shared/redact.ts`:
- Around line 70-74: Update the model-identifier whitelist regex in the
redaction logic to recognize un-hyphenated version digits for the affected
families, such as optional single digits after llama and qwen, while preserving
existing matching behavior. Extend the accepted prefix alternatives to include
common Bedrock/provider prefixes—anthropic, amazon, cohere, meta, us, and eu—so
provider-qualified identifiers remain unredacted after colon splitting.

In `@tests/shared/redact.test.ts`:
- Around line 223-251: Replace the generic toContain assertions in the
provider-model and prefixed-secret tests with exact toBe assertions against the
complete expected redacted or unchanged payload. Keep redactSecrets and MASK
behavior unchanged, and ensure each assertion verifies the entire JSON or token
string rather than only a substring.
🪄 Autofix (Beta)

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: CHILL

Plan: Pro Plus

Run ID: 0aba9947-0d09-4f5b-a85f-cf481a1a56e1

📥 Commits

Reviewing files that changed from the base of the PR and between 52910dc and 603bd04.

📒 Files selected for processing (7)
  • harnesses/openclaw/src/index.ts
  • harnesses/pi/extension-source/hivemind.ts
  • scripts/trace-model-usage-e2e.mjs
  • src/hooks/shared/redact.ts
  • src/notifications/model-usage.ts
  • tests/shared/notifications-model-usage.test.ts
  • tests/shared/redact.test.ts

Comment thread scripts/trace-model-usage-e2e.mjs Outdated
Comment on lines +290 to +301
// Guard: exit code 0 from a capture hook is not proof — verify each agent's
// capture path actually wrote correct rows. We assert per-agent presence
// (and token_usage for the token-bearing agents) rather than requiring every
// one of a 20-model burst to be visible, which the backend's read-lag won't
// reliably surface. A genuinely broken hook lands zero rows for its agent.
const problems = [];
if (rows.length === 0) problems.push("no rows landed at all");
for (const agent of ["claude_code", "codex", "cursor"]) {
if (!(modelsByAgent.get(agent)?.size)) problems.push(`no ${agent} rows landed`);
}
for (const agent of ["claude_code", "codex"]) {
if (!tokenRowsByAgent.get(agent)) problems.push(`no ${agent} row carried token_usage`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Make the harness validate actual metadata across every capture path.

The current checks establish partial presence, not correctness or Pi/OpenClaw integration behavior.

  • scripts/trace-model-usage-e2e.mjs#L290-L301: retain expected parser metadata per session and compare every stored model, reasoning-effort, usage, and cumulative-usage field.
  • scripts/trace-model-usage-e2e.mjs#L312-L318: exercise Pi’s inline normalizer and both integrations’ real entry/write paths with assertions; do not treat logging or absent transcripts as success.
📍 Affects 1 file
  • scripts/trace-model-usage-e2e.mjs#L290-L301 (this comment)
  • scripts/trace-model-usage-e2e.mjs#L312-L318
🤖 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/trace-model-usage-e2e.mjs` around lines 290 - 301, Strengthen
scripts/trace-model-usage-e2e.mjs at lines 290-301 by retaining expected parser
metadata per session and comparing every stored model, reasoning-effort, usage,
and cumulative-usage field for each capture path, rather than checking only row
presence; update lines 312-318 to exercise Pi’s inline normalizer and both
integrations’ real entry/write paths with assertions, ensuring logging or
missing transcripts cannot count as success.

Comment thread scripts/trace-model-usage-e2e.mjs Outdated
Comment thread src/hooks/shared/redact.ts
Comment thread tests/shared/redact.test.ts
- redact: broaden the model-id guard to cover cloud/region-prefixed slugs
  (us.anthropic.claude-3-5-sonnet-20241022-v2) and digit-fused families
  (qwen2.5-coder-32b-instruct, llama3.1-405b-instruct) so they aren't
  over-redacted, while keeping the lowercase + <=12-char-segment invariants
  that stop a secret from slipping through. Tests use exact assertions.
- e2e: require only agents that were actually invoked (a CI box may lack a
  given agent's transcripts); assert token-bearing rows carry positive
  integer input+output tokens (correctness, not mere presence); and assert
  the Pi/OpenClaw sdkTurnMeta proof yields valid positive token_usage.
@efenocchi

Copy link
Copy Markdown
Collaborator Author

CodeRabbit round-2 triage (all in 551912ae):

  • redact — Bedrock / un-hyphenated families ✅ Broadened the guard to allow cloud/region prefixes (us.anthropic.claude-3-5-sonnet-20241022-v2) and a digit fused to the family (qwen2.5-coder-32b-instruct, llama3.1-405b-instruct), while keeping the two safety invariants (lowercase-only + every segment ≤12 chars) so a high-entropy secret still cannot match.
  • e2e — only require invoked agents ✅ Required agents are now derived from the jobs actually created, not hardcoded — a box without a given agent's transcripts no longer fails spuriously.
  • e2e — validate actual metadata ✅ Token-bearing rows must now carry positive integer input+output tokens (not mere presence), and the Pi/OpenClaw sdkTurnMeta proof asserts valid positive token_usage.
  • tests — exact assertions ✅ Redaction tests now assert exact input/output.
  • toNum / reset model+effort at turn boundary — already in the current code (the reset landed in 52910dcd/b9fc044c; your proposed diff matches it verbatim). No change needed.
  • readLines re-reads the whole transcript (O(n²)) — deferring. The capture hooks run async:true, each read is a few ms on realistic transcripts, and this mirrors the existing transcript-parser.ts which also reads the whole file. A per-transcript cursor/cache (handling truncation/rotation) is a self-contained optimization better landed separately than bundled into this behavioral change. Tracking as a follow-up.

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