From b37dd2cacf65d736f476f2b5596545e7228c7002 Mon Sep 17 00:00:00 2001 From: jonahgabriel Date: Wed, 29 Apr 2026 13:53:14 -0400 Subject: [PATCH] feat(OMN-10299): add cost.by_repo.v1 topic to TOPICS constant Adds costByRepo key to the TOPICS constant in shared/types/topics.ts and ships a companion test file covering the value, TypeScript union membership, uniqueness, and naming convention invariants. Upstream-blocked: repo_name column absent from llm_cost_aggregates (omnibase_infra migration 031:142 uses generic aggregation_key only). Follow-up required in omnibase_infra before consumers can receive data. --- shared/types/topics.test.ts | 9 +++++++++ shared/types/topics.ts | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/shared/types/topics.test.ts b/shared/types/topics.test.ts index 7b263fe8..d2f3d9b7 100644 --- a/shared/types/topics.test.ts +++ b/shared/types/topics.test.ts @@ -12,6 +12,15 @@ describe('TOPICS constant', () => { expect(topic).toBeDefined(); }); + it('costByRepo key resolves to the correct topic string', () => { + expect(TOPICS.costByRepo).toBe('onex.snapshot.projection.cost.by_repo.v1'); + }); + + it('TopicSymbol union includes costByRepo value (compile-time assertion)', () => { + const _: TopicSymbol = TOPICS.costByRepo; + expect(_).toBe(TOPICS.costByRepo); + }); + it('all topic values follow the onex.snapshot.projection naming convention', () => { for (const [key, value] of Object.entries(TOPICS)) { expect(value, `TOPICS.${key} must start with onex.snapshot.projection.`).toMatch( diff --git a/shared/types/topics.ts b/shared/types/topics.ts index da627fae..9a2fc80d 100644 --- a/shared/types/topics.ts +++ b/shared/types/topics.ts @@ -37,6 +37,23 @@ export const TOPICS = { * but the aggregation/snapshot emitter path is not yet wired. */ costTokenUsage: 'onex.snapshot.projection.cost.token_usage.v1', + /** + * Cost aggregated by repository. Topic registration leads consumer. + * + * Consumer: ships in OMN-10302 (T19 in epic OMN-10282 plan), which adds the + * IBarChartAdapter manifest entry once OMN-10286 (T4, BarChart primitive) + * lands. Sequenced this way because the manifest entry depends on the + * primitive type, which depends on the chart-config schema (OMN-10284, merged). + * + * Upstream blocker: `repo_name` column is absent from `llm_cost_aggregates` + * (omnibase_infra migration 031:142 has only generic `aggregation_key`). + * Resolution: either new migration adding `repo_name` OR standardize on + * `aggregation_key` encoding `repo:`. Decision pending — tracked in + * the OMN-10302 ticket body and the omnimarket emitter ticket (TBD). + * + * @see {@link https://linear.app/omninode/issue/OMN-10302} + */ + costByRepo: 'onex.snapshot.projection.cost.by_repo.v1', } as const; export type TopicSymbol = (typeof TOPICS)[keyof typeof TOPICS];