Skip to content

mig: fold openclaw into the summary MV usage predicates - #5932

Merged
bradcypert merged 1 commit into
mainfrom
brad/dno-959-openclaw-mv-migration
Sep 2, 2026
Merged

mig: fold openclaw into the summary MV usage predicates#5932
bradcypert merged 1 commit into
mainfrom
brad/dno-959-openclaw-mv-migration

Conversation

@bradcypert

@bradcypert bradcypert commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Part of DNO-959. Split from #5929 so the schema change rolls forward and back on its own.

Why

Both summary materialized views gate counting on a hook-source allowlist that named Codex, Cursor and OpenCode but not OpenClaw. OpenClaw rows were ingested and then silently skipped by every token, cost and tool-call aggregate — no error, nothing in the logs, just sessions that showed up with nothing behind them.

The bit worth reviewing

Atlas generated DROP VIEW + CREATE MATERIALIZED VIEW for both MVs. Shipping that would open a window where telemetry_logs inserts bypass the aggregates and are lost from the summaries permanently.

Hand-edited to ALTER … MODIFY QUERY in both flavors, mirroring 20260727130626_opencode-usage-rows and 20260803192750_litellm-usage-in-summaries, which carry the same note for the same reason.

is_opencode_usage_row is renamed to is_hook_turn_usage_row, since the predicate now covers two adapters.

Why repo-layer Go is in a migration PR

server/internal/telemetry/repo/sessions.go mirrors these predicates for the raw ListSessions path, and sessions_schema_sync_test.go pins the two copies against schema.sql in both directions. Splitting them from the MV definition fails the test on both sides, so they have to move together. The migration-mixing check allows this: its filter excludes server/internal/**/repo/**.

I also added the per-turn usage fragment to that test's pinned list, which was previously unpinned.

Verification

Against the ClickHouse image CI pins (26.2.19.43, same digest):

  • full golang-migrate chain replays clean through 20260831204729/u openclaw-usage-rows
  • both live MVs come back carrying openclaw
  • down 1 cleanly restores the previous definitions
  • a follow-up clickhouse:diff reports the migration directory synced with schema.sql
  • the schema-sync test passes with this branch standing alone

Reviewer notes

  • Forward-only, and deliberately so. The MVs admit OpenClaw rows from deploy onward; existing sessions are not retroactively aggregated. Reviewed and decided against a backfill: there is almost no OpenClaw data in production to recover, so it would be cost without benefit. Matches the opencode precedent.
  • The two ALTERs are not atomic as a pair. A row inserted between them is counted by the new predicate in one MV and the old one in the other. The window is sub-second metadata-only DDL, every prior migration of this shape has it, and with near-zero OpenClaw volume nothing is expected to land in it. Accepted rather than fenced.
  • Cost will read $0. OpenClaw reports tokens but no dollar figure on the hook we decode, and Gram has no token→price fallback. So OpenClaw will show real token volume next to zero dollars, which reads as "free" rather than "unknown". Written up with payload evidence in DNO-1020; not addressed here.

Related PRs

Independent — all three branch from main, no stacking:

🤖 Generated with Claude Code

https://claude.ai/code/session_01TiJy9DrFpsmnD2vEkDHKNv


Summary by cubic

Implements DNO-959 by updating both summary materialized views to count OpenClaw per-turn usage and completed tool calls. OpenClaw rows were previously ingested but excluded by hook-source allowlists; they now contribute from deployment onward, without backfilling existing rows, and cost remains $0 because the payload has no dollar value.

Migration

  • Uses ALTER ... MODIFY QUERY to avoid dropping either materialized view during deployment.
  • Applies the two updates sequentially, so inserts during the window can briefly skew the summaries.
  • Renames the shared predicate to is_hook_turn_usage_row and keeps the Go session path and schema-sync test aligned.
  • Documents the no-backfill and non-atomic update decisions in the migration.

Written for commit 27501ef. Summary will update on new commits.

Review in cubic

@bradcypert
bradcypert requested a review from a team as a code owner September 1, 2026 14:10
@linear-code

linear-code Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

DNO-959

@changeset-bot

changeset-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 27501ef

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
server Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Running ultrareview automatically — This migration rewires both usage materialized views and the matching Go predicates to include OpenClaw rows — any predicate mismatch risks silently dropping or double-counting usage data across summaries, so a deep multi-pass review is warranted.. I'll post findings when complete.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

atlas migrate lint on server/migrations

Status Step Result
No migration files detected  
ERD and visual diff generated View Visualization
No issues found View Report
Read the full linting report on Atlas Cloud

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

atlas migrate lint on server/clickhouse/migrations

Status Step Result
1 new migration file detected 20260902193935_openclaw-usage-rows.sql
ERD and visual diff generated View Visualization
No issues found View Report
Read the full linting report on Atlas Cloud

@blacksmith-sh

This comment has been minimized.

@cubic-dev-ai cubic-dev-ai 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.

Ultrareview completed in 7m 9s

All reported issues were addressed across 9 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread server/clickhouse/migrations/20260902193935_openclaw-usage-rows.sql
Comment thread server/clickhouse/migrations/20260902193935_openclaw-usage-rows.sql
Comment thread server/clickhouse/local/golang_migrate/20260831204729_openclaw-usage-rows.up.sql Outdated
Thegreatsura pushed a commit to Thegreatsura/gram that referenced this pull request Sep 2, 2026
…peakeasy-api#5933)

Closes DNO-960. Split from speakeasy-api#5929 so nothing here shares a rollback fate
with the schema change.

## Why

We ship an OpenClaw observability package but never told anyone how to
install it. The generated ZIP README had sections for Claude Code,
Cursor, Codex and OpenCode, and nothing for OpenClaw.

There was also no runbook for the two things that silently break an
OpenClaw install — both of which produce a *partly* working state rather
than an obvious failure, which is the worst kind.

## What changed

- **Generated package README**: an OpenClaw install section — the
directory install, `--force` when replacing, the required
`allowConversationAccess` block, the Gateway restart, and the coverage
caveat
- **`docs/runbooks/openclaw-install.md`**: laptop and server/CI install
paths, verification, enforcement semantics, version-pin policy, and the
operational gotchas from the DNO-950 spike
- **`docs/plugins/overview.md`**: OpenClaw listed alongside the other
observability packages and in the `downloadObservabilityPlugin` enum

## The two traps the runbook exists for

1. **`allowConversationAccess`.** Without it the conversation hooks
silently never fire — no prompts, no assistant responses, no usage —
while tool hooks keep working. A half-configured install looks partly
fine.
2. **The harness split.** When a model routes through the Claude CLI
harness (`agentRuntime: claude-cli`, which `openclaw models auth login`
writes *by default* when a claude-cli profile exists), OpenClaw
delegates the model and tool loop out-of-process and its tool/LLM hooks
never fire. Those sessions are still covered — by our Claude Code hooks
— so this is complementary coverage rather than a hole, but a customer
in that mode will otherwise think the integration is broken.

## Notes

- `generate.go` is a server implementation file, but the change is
purely the customer-facing install text, so it belongs with the runbook
rather than the feature PR.
- No `hooksGeneratorVersion` bump needed: the README is not part of the
rendered hook-plugin subtree that `check-generator-versions` diffs.
Confirmed by rendering `export-hook-plugin -published` and checking the
file list.
- The runbook records that our fixtures were captured from OpenClaw
2026.6.34 while 2026.7.1-2 is what installs today, and documents the
qualification procedure for that gap. The fixture-side half is
speakeasy-api/agenthooks#24.
- Deliberately no nightly canary against OpenClaw `latest`: it would
page on OpenClaw's release cadence and registry flakes without telling
us what we actually support — the same reasoning that keeps the LiteLLM
real-proxy suite on `workflow_dispatch`.

## Related PRs

Independent — all three branch from `main`, no stacking:

- speakeasy-api#5929 — `feat:` source alias and turn correlation
- speakeasy-api#5932 — `mig:` the materialized-view change

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01TiJy9DrFpsmnD2vEkDHKNv

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds OpenClaw install docs for the observability plugin — the generated
ZIP README now has an OpenClaw section, and a new runbook covers laptop
and server/CI installs. Two configuration states silently break coverage
without any error, and both are now documented.

- The README's OpenClaw section is generated only when a hooks API key
exists, so it never describes files that aren't in the ZIP.
- The runbook details the two traps: missing `allowConversationAccess`
drops prompt and usage capture while tool hooks keep working, and the
Claude CLI harness routes sessions through Claude Code hooks, which
capture them only if those hooks are also deployed on the machine.
- Documents how coverage depends on model-auth mode, the enforcement
timeout budgets, the version-pin qualification procedure, and that the
hooks binary is fetched from the org's Gram server rather than GitHub.
- Adds an OpenClaw package-format section in
`docs/plugins/package-format.md`, and lists OpenClaw in
`docs/plugins/overview.md`, the `downloadObservabilityPlugin` enum, and
the observability slug table in `docs/plugins/publishing.md`.
- Closes DNO-960.

<sup>Written for commit 024520e.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/speakeasy-api/gram/pull/5933?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@bradcypert
bradcypert force-pushed the brad/dno-959-openclaw-mv-migration branch from c96aec3 to f28d669 Compare September 2, 2026 18:49
Both summary MVs gate counting on a hook-source allowlist that named
Codex, Cursor and OpenCode but not OpenClaw, so OpenClaw rows were
ingested and then skipped by every token, cost and tool-call aggregate.

Atlas generates DROP VIEW + CREATE for an MV SELECT change, which leaves
a window where telemetry_logs inserts bypass the aggregates and are lost
from the summaries permanently. Hand-edited to ALTER ... MODIFY QUERY in
both flavors, mirroring 20260727130626_opencode-usage-rows and
20260803192750_litellm-usage-in-summaries. The file header records the
two decisions review kept re-raising: no backfill, and the pair not
being atomic.

The repo-layer session predicates move with the schema: the schema-sync
test pins them against schema.sql in both directions, so they cannot be
split from the MV definition without failing on both sides.

Regenerated on top of main rather than rebased: 20260902165930
meta-mcp-attribution landed with a later timestamp than the previous
migration, so a rebase would have left this one out of order. Its
telemetry_logs and trace_summaries changes are untouched here, and the
MV SELECTs were re-derived from main's current schema.sql rather than
carried over, so the meta_mcp_server_id work is preserved.

Verified against the ClickHouse image CI pins: the chain replays clean
with meta-mcp-attribution applying first, both MVs come back carrying
openclaw, meta_mcp_server_id survives, and a follow-up diff reports the
directory synced with schema.sql.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TiJy9DrFpsmnD2vEkDHKNv
@bradcypert
bradcypert force-pushed the brad/dno-959-openclaw-mv-migration branch from f28d669 to 27501ef Compare September 2, 2026 19:41
@bradcypert
bradcypert enabled auto-merge September 2, 2026 19:50
@bradcypert
bradcypert added this pull request to the merge queue Sep 2, 2026
Merged via the queue into main with commit ddbb145 Sep 2, 2026
45 checks passed
@bradcypert
bradcypert deleted the brad/dno-959-openclaw-mv-migration branch September 2, 2026 19:58
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 2, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants