Skip to content

test(e2e): Claude Team AI metrics — per-metric specs + bronze placeholder & watermark guard (#1440) - #1491

Merged
mozhaev-dev merged 6 commits into
mainfrom
test/e2e-ai-claude-team
Jun 30, 2026
Merged

test(e2e): Claude Team AI metrics — per-metric specs + bronze placeholder & watermark guard (#1440)#1491
mozhaev-dev merged 6 commits into
mainfrom
test/e2e-ai-claude-team

Conversation

@mozhaev-dev

@mozhaev-dev mozhaev-dev commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Part of #1440 (E2E smoke: AI Adoption metrics) — the claude_team slice. Sibling of #1468 (cursor). One spec per metric.

Tests — claude_team-driven AI metrics (4)

Seeds bronze_claude_team.claude_team_code_metrics and asserts the IC Bullet AI (…0013):

  • ai_cc_lines = 40 (← total_lines_accepted)
  • ai_cc_sessions = 12 (← total_sessions)
  • ai_cc_cost = 200¢ (← total_cost "2.00", decimal-as-string → cents)
  • ai_cc_active = 1-of-3

Each value spec includes a re-sync duplicate that must dedup. New reusable schemas/bronze_claude_team.claude_team_code_metrics.yaml + templates/claude_team_usage.yaml.

cc_tool_accept / cc_tool_acceptance are not here — they need tool_use_accepted/offered, which claude_team doesn't expose (NULL by design); they belong to the claude_enterprise / admin slice.

Fixes (latent in prod, exposed by the rig)

  1. bronze_claude_team placeholder — was missing entirely; claude_team__ai_dev_usage couldn't build without Airbyte. Added DB + table mirroring the connector InlineSchemaLoader.
  2. watermark empty-table guard in claude_team__ai_dev_usage — same Date-underflow as cursor (test(e2e): AI metrics per-metric specs + bronze_cursor placeholder & watermark fixes (#1440) #1468): max(day) over an empty this is the epoch, - 3 DAY wraps to ~2149-06-04 and filters everything out. Guarded with (SELECT count() FROM this) = 0 OR … (m365 pattern). NB: this guard is copy-pasted across all 10 AI staging models — chatgpt_team next.
  3. _SESSION_START_TRUNCATE reset for the claude staging (warm-rerun safety).

Verification

./e2e.sh test -k ai_cc4 passed; warm re-run (no down) → 4 passed.

Refs #1440

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for initial placeholder setup on fresh clusters so Claude Team usage data can be prepared before the first sync.
    • Expanded end-to-end coverage for Claude Team metrics, including active usage, cost, lines, and sessions.
  • Bug Fixes

    • Prevented empty incremental loads from dropping results when the target table is newly empty.
    • Avoided duplicate metric rows from being counted during repeated runs or re-syncs.

@mozhaev-dev
mozhaev-dev requested a review from a team as a code owner June 26, 2026 05:33
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 59 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: bec0866d-44b3-4bdd-b30a-12bffe12d8a0

📥 Commits

Reviewing files that changed from the base of the PR and between 1828754 and dc01a10.

📒 Files selected for processing (6)
  • src/ingestion/connectors/ai/claude-team/dbt/claude_team__ai_overage.sql
  • src/ingestion/scripts/create-bronze-placeholders.sh
  • src/ingestion/tests/e2e/conftest.py
  • src/ingestion/tests/e2e/metrics/ai_cc_overage.test.yaml
  • src/ingestion/tests/e2e/metrics/schemas/bronze_claude_team.claude_team_overage_spend.yaml
  • src/ingestion/tests/e2e/metrics/templates/claude_team_overage.yaml
📝 Walkthrough

Walkthrough

This PR adds Claude Team bronze placeholder support, changes one incremental dbt model to skip the cutoff when the target table is empty, and adds end-to-end metric specs plus shared fixtures for cc_active, cc_cost, cc_lines, and cc_sessions.

Changes

Claude Team AI metrics support

Layer / File(s) Summary
Bronze placeholder bootstrap
src/ingestion/scripts/create-bronze-placeholders.sh, src/ingestion/tests/e2e/metrics/schemas/bronze_claude_team.claude_team_code_metrics.yaml, src/ingestion/tests/e2e/metrics/templates/claude_team_usage.yaml
The bootstrap script now creates the Claude Team bronze database and placeholder table, and the shared schema/template files define the bronze Claude Team code-metrics row shape.
Incremental guard and session reset
src/ingestion/connectors/ai/claude-team/dbt/claude_team__ai_dev_usage.sql, src/ingestion/tests/e2e/conftest.py
The incremental model skips the cutoff filter when the target table is empty, and session-start setup truncates staging.claude_team__ai_dev_usage.
Claude Team metric e2e specs
src/ingestion/tests/e2e/metrics/ai_cc_active.test.yaml, src/ingestion/tests/e2e/metrics/ai_cc_cost.test.yaml, src/ingestion/tests/e2e/metrics/ai_cc_lines.test.yaml, src/ingestion/tests/e2e/metrics/ai_cc_sessions.test.yaml
The new metric specs seed Claude Team usage data and query cc_active, cc_cost, cc_lines, and cc_sessions, asserting returned values, medians, and ranges.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • constructorfabric/insight issue 1438 — Adds AI metric e2e coverage and Claude Team usage plumbing aligned with the issue’s happy-path metric tests.
  • constructorfabric/insight issue 1440 — Extends Claude Code/Claude Team metrics coverage with cc_active, cc_cost, cc_lines, and cc_sessions.

Suggested reviewers

  • mitasovr
  • cyberantonz

Poem

A bunny hopped through bronze and glue,
With metrics bright and tests in view.
Empty targets no longer sigh,
While Alice counts hop safely by.
🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: new Claude Team AI metric e2e specs plus the bronze placeholder and watermark guard fixes.
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
  • Commit unit tests in branch test/e2e-ai-claude-team

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

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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/ingestion/scripts/create-bronze-placeholders.sh`:
- Around line 1047-1049: The placeholder schema for the bronze seed data
currently defines email as required, which conflicts with the rest of the
ingestion contract. Update the schema in create-bronze-placeholders.sh so the
placeholder table definition matches the e2e model by making email nullable
alongside the existing Nullable fields, and keep the surrounding placeholder
column definitions consistent with claude_team__ai_dev_usage expectations.

In `@src/ingestion/tests/e2e/specs/ai_cc_active.test.yaml`:
- Around line 11-21: The ai_cc_active test spec currently only seeds unique
claude_team_code_metrics rows, so it never exercises the dedup path the PR adds.
Update the ai_cc_active fixture to include a duplicate re-sync seed alongside
the existing claude_team_usage.yaml template entries for
bronze_claude_team.claude_team_code_metrics, using the same unique_key pattern
as the other ai_cc_* specs so the active-row dedup behavior is verified.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9dc29597-bd8f-4e83-967e-fc21e6a2ce8f

📥 Commits

Reviewing files that changed from the base of the PR and between 358344d and fadb3e810ee2c7076a4f2e51f6838bdfdade04ab.

📒 Files selected for processing (9)
  • src/ingestion/connectors/ai/claude-team/dbt/claude_team__ai_dev_usage.sql
  • src/ingestion/scripts/create-bronze-placeholders.sh
  • src/ingestion/tests/e2e/conftest.py
  • src/ingestion/tests/e2e/specs/ai_cc_active.test.yaml
  • src/ingestion/tests/e2e/specs/ai_cc_cost.test.yaml
  • src/ingestion/tests/e2e/specs/ai_cc_lines.test.yaml
  • src/ingestion/tests/e2e/specs/ai_cc_sessions.test.yaml
  • src/ingestion/tests/e2e/specs/schemas/bronze_claude_team.claude_team_code_metrics.yaml
  • src/ingestion/tests/e2e/specs/templates/claude_team_usage.yaml

Comment thread src/ingestion/scripts/create-bronze-placeholders.sh
Comment thread src/ingestion/tests/e2e/metrics/ai_cc_active.test.yaml
@mozhaev-dev

Copy link
Copy Markdown
Contributor Author

Thanks @coderabbitai — both addressed:

  • Placeholder nullability: tenant_id/source_id/data_source/email are now Nullable(String) in the claude_team placeholder, matching the schema's [string,"null"]; unique_key stays non-null (ORDER BY key).
  • ai_cc_active dedup: added the re-sync duplicate row so it's consistent with the other ai_cc_* specs (cc_active stays 1).

Re-ran ./e2e.sh test -k ai_cc (clean) → 4 passed.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@mozhaev-dev Looks good — thanks for addressing both points and for re-running the ai_cc E2E suite. The placeholder nullability now aligns with the schema, and the ai_cc_active duplicate re-sync assertion makes the dedup coverage consistent with the other specs.

🐇✨


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

mozhaev-dev and others added 4 commits June 27, 2026 07:29
…e guard

Two fixes the e2e rig needs (both latent in prod):
- Add the `bronze_claude_team.claude_team_code_metrics` placeholder (DB + table)
  to create-bronze-placeholders.sh, mirroring the connector InlineSchemaLoader.
  It was missing, so `claude_team__ai_dev_usage` couldn't build without Airbyte.
- Guard the incremental watermark against the empty-table Date underflow
  (`coalesce(max(day),'1970-01-01') - INTERVAL 3 DAY` wraps to ~2149 over an
  empty `this`, dropping every row). Short-circuit with `count()=0 OR …` — same
  fix as cursor (#1468); mirrors the m365__collab_* guard.

Refs #1440

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Sergei Mozhaev <mozhaev.dev@gmail.com>
Adds one spec per metric the claude_team connector drives, over a clean
claude_team_code_metrics seed: ai_cc_lines (40), ai_cc_sessions (12), ai_cc_cost
(200¢), ai_cc_active (1-of-3). All assert the IC Bullet AI (…0013) served
value/median/range; each value spec includes a re-sync duplicate that must dedup.
New reusable schema + template (claude_team_usage); cursor__/claude_team__ staging
added to _SESSION_START_TRUNCATE for warm-rerun safety.

cc_tool_accept / cc_tool_acceptance need tool_use_accepted/offered, which
claude_team doesn't expose (NULL) — they belong to the claude_enterprise / admin
slice and will be covered there.

Refs #1440

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Sergei Mozhaev <mozhaev.dev@gmail.com>
… + ai_cc_active dedup row

- create-bronze-placeholders.sh: make tenant_id/source_id/data_source/email
  Nullable in the claude_team placeholder to match the e2e schema contract
  ([string,"null"]); unique_key stays non-null (ORDER BY key). Avoids an INSERT
  mismatch for rows that legitimately omit these (the model filters email anyway).
- ai_cc_active: add the re-sync duplicate row, consistent with the other ai_cc_*
  specs — cc_active must stay 1 (an "active" metric dedups by person).

Refs #1440

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Sergei Mozhaev <mozhaev.dev@gmail.com>
…format

Rewrite the 4 cc metric specs' `description:` blocks to the canonical shape
from the metric-test skill (collab_active_days.test.yaml precedent): plain-
language bronze→silver→gold layer flow + a Team line tying seeded member values
to the asserted median/range. No behavior change — 4 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Sergei Mozhaev <mozhaev.dev@gmail.com>
@mozhaev-dev
mozhaev-dev force-pushed the test/e2e-ai-claude-team branch from d8121b4 to 1828754 Compare June 27, 2026 04:32
cc_overage ← class_ai_overage.overage_cents = max(0, used_credits − monthly
credit limit), both already in cents. Seeded via a new bronze stream
claude_team_overage_spend; alice used 300/limit 100 → 200¢, median 100,
range [50, 200] (dedup holds). 1 passed.

Supporting:
- bronze placeholder for claude_team_overage_spend (+ schema + template).
- claude_team__ai_overage: same empty-table watermark guard as the dev-usage
  models — the INTERVAL 1 MONTH window underflows the Date range over an empty
  `this` (rig resets staging between tests), so short-circuit with count()=0.
- conftest: reset staging.claude_team__ai_overage at session start (warm-rerun).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Sergei Mozhaev <mozhaev.dev@gmail.com>
@mozhaev-dev
mozhaev-dev merged commit 02864c8 into main Jun 30, 2026
23 checks passed
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.

3 participants