Skip to content

feat(gold): collab_person_counter_daily scaffold + Messaging counters (#1527) - #1567

Merged
mozhaev-dev merged 2 commits into
mainfrom
feat/collab-person-counter-scaffold
Jul 6, 2026
Merged

feat(gold): collab_person_counter_daily scaffold + Messaging counters (#1527)#1567
mozhaev-dev merged 2 commits into
mainfrom
feat/collab-person-counter-scaffold

Conversation

@mozhaev-dev

@mozhaev-dev mozhaev-dev commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

PR A of the #1527 split (see #1516 · release #1526) — the data-layer foundation. Establishes the shared gold view the other collab modalities (#1528#1532) extend, and delivers the Messaging modality's two counters.

Split plan: A (this) → B backend query_ref + catalog seed → C e2e YAML → D FE (insight-front).

Changes

  • New gold view insight.collab_person_counter_daily (migration 20260702000000), cloning feat: improve AI personal analytics queries #1514's ai_person_counter_daily:
    • honest-NULL UNION ALL over the per-vendor silver chat classes (M365 Teams · Slack · Zulip),
    • outer GROUP BY (person_id, metric_date) with if(countIf(x IS NOT NULL) > 0, sumIf(x, …), NULL) → a person with no source on a day is NULL, never a fake 0 (a real 0 row stays 0),
    • LEFT JOIN insight.people for org_unit_id (feeds the per-org_unit peer bands in PR B).
  • Metrics
    metric formula note
    messages_sent Σ total_chat_messages over M365 · Slack · Zulip vendor semantics differ (Slack superset incl. replies; M365 excludes group chats & replies) — chat-engagement signal, not comparable absolute
    channel_posts Σ (channel_posts + channel_replies) over M365 · Slack Slack folds replies into channel_posts already (channel_replies NULL); M365 splits → add both for comparability; Zulip has no channel split → honest-NULL
  • dbt singular test assert_collab_messaging_bounds.sql: counters ≥ 0.
  • Register the view in silver/_shared/gold_sources.yml.

Design-for-extension

The view/test are the scaffold: later modalities add columns + UNION branches (not new vendor-named rows). Honest-NULL rendering ("No data" / source tooltip) is #1517; thresholds/bands land with PR B; this PR is data-layer only.

Testing / validation

  • Static: YAML valid, migration timestamp-ordered last, no name collisions.
  • ⚠️ Not executed against a live ClickHouse locally (no cluster available). View SQL is validated end-to-end by the e2e YAML in PR C and a dev-cluster no-loss spot check (ch.sh --target dev): messages_sent == m365_teams_chats + slack_messages_sent + zulip_messages_sent per QUALITY 5: data + UX: honest-NULL and showing missing data (collaboration counters) #1517 NULL rules.

Refs #1527 · #1516

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a new daily collaboration metrics view with per-person, per-day totals for messages sent and channel posts across supported chat sources.
  • Bug Fixes
    • Improved metric handling so days with no activity remain blank (instead of showing zero), and added warning-level checks when computed totals become negative.
  • Chores
    • Updated the silver placeholder schema and added a Gold-layer catalog entry to support the new collaboration metrics, including an added channel replies field.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8bd3ad07-3908-41c4-900c-b255f08cc5d4

📥 Commits

Reviewing files that changed from the base of the PR and between f7d323a2ba6b7f421fd07cb9b1149e8dfbf0783b and 952394b.

📒 Files selected for processing (4)
  • src/ingestion/dbt/tests/gold/assert_collab_messaging_bounds.sql
  • src/ingestion/scripts/create-bronze-placeholders.sh
  • src/ingestion/scripts/migrations/20260702000000_collab-person-counter-daily.sql
  • src/ingestion/silver/_shared/gold_sources.yml
✅ Files skipped from review due to trivial changes (1)
  • src/ingestion/silver/_shared/gold_sources.yml
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/ingestion/scripts/create-bronze-placeholders.sh
  • src/ingestion/dbt/tests/gold/assert_collab_messaging_bounds.sql
  • src/ingestion/scripts/migrations/20260702000000_collab-person-counter-daily.sql

📝 Walkthrough

Walkthrough

This PR adds a new ClickHouse view insight.collab_person_counter_daily for per-person daily messaging metrics, updates the underlying placeholder schema, registers the view as a gold source, and adds a dbt bounds test for negative values.

Changes

Collab Person Counter Daily Scaffold

Layer / File(s) Summary
Bronze placeholder schema update
src/ingestion/scripts/create-bronze-placeholders.sh
Adds channel_replies (Float64) to the silver.class_collab_chat_activity placeholder table definition.
Collab person counter daily view definition
src/ingestion/scripts/migrations/20260702000000_collab-person-counter-daily.sql
Drops and recreates insight.collab_person_counter_daily, unioning M365/Slack/Zulip rows from silver.class_collab_chat_activity, aggregating messages_sent/channel_posts per person/day with honest-NULL semantics, and left-joining insight.people for org_unit_id.
Gold source registration and data quality test
src/ingestion/silver/_shared/gold_sources.yml, src/ingestion/dbt/tests/gold/assert_collab_messaging_bounds.sql
Registers collab_person_counter_daily as a gold source and adds a dbt singular test that flags non-NULL negative messages_sent/channel_posts values with warn severity and store_failures.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

Suggested reviewers: mitasovr, ktursunov, cyberantonz

🚥 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 new gold scaffold and Messaging counters added in this PR.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/collab-person-counter-scaffold

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.

🧹 Nitpick comments (1)
src/ingestion/scripts/migrations/20260702000000_collab-person-counter-daily.sql (1)

46-92: 🚀 Performance & Scalability | 🔵 Trivial | ⚖️ Poor tradeoff

Optional: collapse three FINAL scans of the same table into one pass.

The M365/Slack/Zulip branches each do a full FINAL scan of silver.class_collab_chat_activity filtered by data_source. A single scan with per-vendor CASE/multiIf projection over data_source IN (...) would avoid reading the table three times. Given this is a clone of ai_person_counter_daily, keeping the readable UNION shape is defensible — flagging only as a potential optimization if the source grows large.

🤖 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/ingestion/scripts/migrations/20260702000000_collab-person-counter-daily.sql`
around lines 46 - 92, The current UNION ALL in the raw subquery scans
silver.class_collab_chat_activity with FINAL three times for M365, Slack, and
Zulip. Consider rewriting the extraction as a single pass over data_source IN
(...) and use CASE/multiIf to derive messages_sent and channel_posts per source,
while keeping the same person_id and metric_date logic in the raw subquery.
🤖 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.

Nitpick comments:
In
`@src/ingestion/scripts/migrations/20260702000000_collab-person-counter-daily.sql`:
- Around line 46-92: The current UNION ALL in the raw subquery scans
silver.class_collab_chat_activity with FINAL three times for M365, Slack, and
Zulip. Consider rewriting the extraction as a single pass over data_source IN
(...) and use CASE/multiIf to derive messages_sent and channel_posts per source,
while keeping the same person_id and metric_date logic in the raw subquery.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 56a19a8f-be25-4461-ade5-4cfaefbf583e

📥 Commits

Reviewing files that changed from the base of the PR and between 84862c5 and f6e5a110373bfc34f87daeab98c61c51a772af09.

📒 Files selected for processing (4)
  • src/ingestion/dbt/tests/gold/assert_collab_messaging_bounds.sql
  • src/ingestion/scripts/create-bronze-placeholders.sh
  • src/ingestion/scripts/migrations/20260702000000_collab-person-counter-daily.sql
  • src/ingestion/silver/_shared/gold_sources.yml

mozhaev-dev and others added 2 commits July 6, 2026 14:59
…#1527)

PR A of the #1527 split — the data-layer foundation. Establishes the shared
gold view the other collab modalities (#1528#1532) extend, and delivers the
Messaging modality's two counters.

- New gold view `insight.collab_person_counter_daily` (migration
  20260702000000): honest-NULL UNION ALL over the per-vendor silver chat
  classes (M365 Teams · Slack · Zulip), outer GROUP BY (person_id, metric_date)
  with the `if(countIf(x IS NOT NULL) > 0, sumIf …, NULL)` wrapper so a person
  with no source on a day is NULL, never a fake 0. LEFT JOIN insight.people for
  org_unit_id. Clone of #1514's ai_person_counter_daily shape.
    · messages_sent — Σ total_chat_messages across the three vendors.
    · channel_posts — Σ (channel_posts + channel_replies) across M365 · Slack
      for vendor comparability (Slack folds replies in already; M365 splits
      them); Zulip has no channel split → honest-NULL.
- dbt singular test `assert_collab_messaging_bounds.sql`: counters ≥ 0.
- Register the view in silver/_shared/gold_sources.yml.

Designed for extension: later modalities add columns + UNION branches, not new
vendor rows. Backend query_ref + catalog seed (PR B), e2e YAML (PR C) and FE
(insight-front) follow.

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

Addresses the PR review of the #1527 gold-view scaffold.

- BLOCKER: silver.class_collab_chat_activity placeholder in
  create-bronze-placeholders.sh lacked `channel_replies`, which the M365 branch
  of collab_person_counter_daily references. ClickHouse validates columns at
  CREATE VIEW time, so on a fresh cluster / in e2e (placeholders → migrations,
  before dbt builds the real silver) the migration would fail. Add the column.
- MEDIUM: read class_collab_chat_activity (a ReplacingMergeTree) with FINAL in
  all three vendor branches so a re-synced day with >1 version per key is not
  double-summed — matches the class_collab_meeting_activity read in
  20260518000000_collab-bullet-rewrite.sql.

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 feat/collab-person-counter-scaffold branch from 333d99f to 952394b Compare July 6, 2026 11:59
@mozhaev-dev
mozhaev-dev merged commit caefa1a into main Jul 6, 2026
22 checks passed
mozhaev-dev added a commit that referenced this pull request Jul 6, 2026
…ed (#1527)

PR B of the #1527 split — the backend layer over PR A's gold view. Clones the

- Query_ref migration (m20260702_000001): `collab_messaging_counters_qr` reads
  insight.collab_person_counter_daily, re-aggregates per person with the
  honest-NULL `if(countIf(x IS NOT NULL) > 0, sumIf …, NULL)` wrapper, ARRAY
  JOIN unpivot (drops NULLs), and LEFT JOINs per-org_unit_id `quantileExact`
  bands. Stored on metrics id …0053 (next free after AI counters …0052).
- Catalog seed (m20260702_000002): product-default metric_catalog rows for
  `messages_sent` + `channel_posts`, each with an initial product-default
  metric_threshold (catalog-probe requirement) and a metric_query_catalog
  junction link to the query. source_tags carry the vendors (m365/slack/zulip).
  Thresholds are initial defaults, NOT calibrated (per-org_unit calibration is
  a post-release follow-up).
- Register both migrations in mod.rs.

Tests:
- Rust unit (feeds #1433): asserts the generated peer-counter SQL emits both
  keys with the honest-NULL wrapper + per-org_unit band join — no DB, runs in
  CI coverage.
- Extend catalog live_tests (`product_default_wins_when_no_tenant_overlay`) to
  assert both Messaging keys resolve at product-default.

Designed for extension: later modalities add keys to the ARRAY JOIN list + seed
rows. Depends on the gold view from PR A (#1567) at deploy time. Honest-NULL
rendering is #1517.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Sergei Mozhaev <mozhaev.dev@gmail.com>
cyberantonz pushed a commit to cyberantonz/insight that referenced this pull request Aug 5, 2026
…tructorfabric#1527)

PR D of the constructorfabric#1527 split — the frontend surface for the collaboration Messaging
counters (backend: gold view constructorfabric#1567 + query/seed). Mirrors the AI-adoption
peer-counters panel (constructorfabric#1514).

- metric-registry: add V2_IC_COLLAB_PEER_COUNTERS (…0053), the seeded collab
  Messaging peer-counter query.
- ic-extras: add useIcCollabPeerCounters (clone of useIcAiPeerCounters, same row
  shape + per-org_unit bands, different metric id).
- new CollabMessagingPanel: renders messages_sent + channel_posts vs the
  person's department under a "Messaging" card via the shared PeerStorySection.
  Fully catalog-driven — any counter row whose metric_key is in the catalog
  renders; unknown keys are dropped.
- mount it in the collaboration section drilldown (section-drilldown-sheet).
- catalog-snapshot mock: add the two collab_person_counter_daily.* metrics.
- vitest: renders both under "Messaging"; drops unseeded keys; renders nothing
  without person/range.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Sergey Mozhaev <Sergey.Mozhaev@constructor.tech>
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.

2 participants