Problem
The tier chain now runs org → workspace → repo → project (hub telemetry in ~/.stella/usage.db) and, per project, session → turn → step → tool call (the observatory Sessions tab). The seam between the two halves is thin: session_id never reaches usage.db. Neither execution_rollup nor the hub telemetry table (crates/stella-store/src/usage.rs::USAGE_SCHEMA) carries it, so a hub-side 'sessions of this project' or 'org-wide session count/cost' cannot be answered from the hub — the observatory bridges by jumping into the project's own store (hub project drill lands on the project's Sessions tab).
Build
- Add
session_id TEXT to hub telemetry (schema converges via CREATE IF NOT EXISTS + column probing — see how enterprise_telemetry::initialize_store_export_schema probes columns) and to ExecutionRollupRow/execution_rollup.
- Thread it through
Store::telemetry_rows_after → UsageStore::replicate_telemetry and Store::execution_rollup → UsageStore::sync_execution.
- Content-free gate:
session_id is an opaque minted id (ses-<ms>-<pid>), but adding a hub telemetry column fails make gate until the allowlist in crates/stella-store/src/content_free.rs is edited in the same PR — that review question ('is this content?') is the point; the pid embedded in the id is a local identifier, so decide explicitly whether to hash or pass through, and record the reasoning there.
- Observatory: extend
global.rs::hub_telemetry with a per-session grouping when the column exists (degrade when absent).
Verify
Witness: register a workspace, sync a session-stamped execution, assert the hub row carries the session id — fails on main (no column). Hub prune/quarantine paths must round-trip the new column.
Constraints
Invariant 3 (zero telemetry egress by default) — this is hub-local, not egress, but the content_free allowlist is the enforcement point and must be edited deliberately, not widened casually.
Problem
The tier chain now runs org → workspace → repo → project (hub
telemetryin~/.stella/usage.db) and, per project, session → turn → step → tool call (the observatory Sessions tab). The seam between the two halves is thin:session_idnever reachesusage.db. Neitherexecution_rollupnor the hubtelemetrytable (crates/stella-store/src/usage.rs::USAGE_SCHEMA) carries it, so a hub-side 'sessions of this project' or 'org-wide session count/cost' cannot be answered from the hub — the observatory bridges by jumping into the project's own store (hub project drill lands on the project's Sessions tab).Build
session_id TEXTto hubtelemetry(schema converges via CREATE IF NOT EXISTS + column probing — see howenterprise_telemetry::initialize_store_export_schemaprobes columns) and toExecutionRollupRow/execution_rollup.Store::telemetry_rows_after→UsageStore::replicate_telemetryandStore::execution_rollup→UsageStore::sync_execution.session_idis an opaque minted id (ses-<ms>-<pid>), but adding a hub telemetry column failsmake gateuntil the allowlist incrates/stella-store/src/content_free.rsis edited in the same PR — that review question ('is this content?') is the point; the pid embedded in the id is a local identifier, so decide explicitly whether to hash or pass through, and record the reasoning there.global.rs::hub_telemetrywith a per-session grouping when the column exists (degrade when absent).Verify
Witness: register a workspace, sync a session-stamped execution, assert the hub row carries the session id — fails on main (no column). Hub prune/quarantine paths must round-trip the new column.
Constraints
Invariant 3 (zero telemetry egress by default) — this is hub-local, not egress, but the content_free allowlist is the enforcement point and must be edited deliberately, not widened casually.