Labels: context-graph, ai-gateway, reports
Systems: Plugins (context-graph / ai-gateway-graph)
Goal
Group and join AI activity by the two session-level dimensions the reports lean
on most but the graph doesn't model: gateway and user.
- "Sessions / repos / models per gateway" as a graph query, not a message scan.
- "What does user X work on" - user joined to repo, model, skill.
- Reach these by joining to what's already in the graph (repo, model, file,
skill) instead of re-deriving each side from ai_gateway_messages.
Today gateway_id is not in the graph at all, and user_id is not a node
(at best a pruned Session prop). So every per-gateway / per-user rollup in the
adoption and improvement reports falls back to a GROUP BY over the full
message table.
Queries this unlocks
With Gateway / User nodes reached by Session -served_by-> Gateway and
Session -run_by-> User (same shape as the existing via -> App):
-- repos per gateway (fleet footprint), pure graph
select g.label gateway, count(distinct sv.src_id) sessions
from edge sv join node g on g.node_id = sv.dst_id
where sv.edge_type = 'served_by'
group by g.label order by sessions desc;
-- what a user works on: their repos
select r.label repo, count(distinct i.src_id) sessions
from edge i join node r on r.node_id = i.dst_id
where i.edge_type = 'in' and r.node_type = 'Repo'
and i.src_id in (
select e.src_id from edge e join node u on u.node_id = e.dst_id
where e.edge_type = 'run_by' and u.natural_key = '<user-id>')
group by r.label order by sessions desc;
These also compose with the sibling nodes: gateway x skill, user x program,
etc., once those land.
Why it matters
The adoption/improvement reports are fundamentally "who (user), on which box
(gateway), working where (repo), with what (model/skill)." Three of those five
are already graph nodes; gateway and user are the missing two. Adding them turns
the reports' per-gateway/per-user rollups into cheap graph joins and lets fleet
questions ("which gateway drives the most repos", "which users touch which
models") be answered by traversal.
Challenges
This is the cleanest of the node additions - the values are already dedicated
columns (gateway_id, user_id), so there is no parsing or cross-client
ambiguity like skills had. The real caveats are about population and identity,
not mechanism:
user_id is almost entirely empty today. On central: 1 distinct user,
~99% of rows null. So a User node is near-empty until multi-tenant auth
(the OIDC login work) actually populates user_id. The mechanism is trivial;
its value is latent until then. Gateway, by contrast, is fully populated
(4 gateways, always present) and useful immediately.
User is not Actor. The graph already has an Actor node - but that is
a git commit author from the GitHub source, not the AI operator
(user_id). They may be the same human, keyed differently (auth id vs git
email/login). Keep them distinct nodes; bridging them is a later question, not
part of this.
- Bounded, so no cardinality risk - gateways and users are small sets, unlike
the shell-command case.
Direction (not yet a design)
Same contract pattern as the existing via -> App rule, applied to two more
session columns:
Gateway node keyed on gateway_id; edge Session -served_by-> Gateway
(always minted - gateway_id is NOT NULL).
User node keyed on user_id; edge Session -run_by-> User, minted only
when user_id is present (so it stays empty-but-correct until auth lands).
- Distinct edge names (
served_by, run_by) so they never collide with the
other new edges (ran for Skill, invoked for Program) under one edge_type
filter.
Gateway is worth doing now; User can land in the same change but should be
understood as latent until user_id is populated fleet-wide.
References
- Graph contract to extend:
hypaware-core/plugins-workspace/ai-gateway-graph/src/graph_contract.js (see the existing App node / via edge as the template)
- Projection engine:
hypaware-core/plugins-workspace/context-graph/src/project.js
- Related LLP: 0023 (contract-contribution), 0030 (session keying); OIDC/multi-tenant login work that populates
user_id
Labels:
context-graph,ai-gateway,reportsSystems: Plugins (context-graph / ai-gateway-graph)
Goal
Group and join AI activity by the two session-level dimensions the reports lean
on most but the graph doesn't model: gateway and user.
skill) instead of re-deriving each side from
ai_gateway_messages.Today
gateway_idis not in the graph at all, anduser_idis not a node(at best a pruned Session prop). So every per-gateway / per-user rollup in the
adoption and improvement reports falls back to a
GROUP BYover the fullmessage table.
Queries this unlocks
With
Gateway/Usernodes reached bySession -served_by-> GatewayandSession -run_by-> User(same shape as the existingvia -> App):These also compose with the sibling nodes: gateway x skill, user x program,
etc., once those land.
Why it matters
The adoption/improvement reports are fundamentally "who (user), on which box
(gateway), working where (repo), with what (model/skill)." Three of those five
are already graph nodes; gateway and user are the missing two. Adding them turns
the reports' per-gateway/per-user rollups into cheap graph joins and lets fleet
questions ("which gateway drives the most repos", "which users touch which
models") be answered by traversal.
Challenges
This is the cleanest of the node additions - the values are already dedicated
columns (
gateway_id,user_id), so there is no parsing or cross-clientambiguity like skills had. The real caveats are about population and identity,
not mechanism:
user_idis almost entirely empty today. On central: 1 distinct user,~99% of rows null. So a
Usernode is near-empty until multi-tenant auth(the OIDC login work) actually populates
user_id. The mechanism is trivial;its value is latent until then. Gateway, by contrast, is fully populated
(4 gateways, always present) and useful immediately.
Useris notActor. The graph already has anActornode - but that isa git commit author from the GitHub source, not the AI operator
(
user_id). They may be the same human, keyed differently (auth id vs gitemail/login). Keep them distinct nodes; bridging them is a later question, not
part of this.
the shell-command case.
Direction (not yet a design)
Same contract pattern as the existing
via -> Apprule, applied to two moresession columns:
Gatewaynode keyed ongateway_id; edgeSession -served_by-> Gateway(always minted -
gateway_idisNOT NULL).Usernode keyed onuser_id; edgeSession -run_by-> User, minted onlywhen
user_idis present (so it stays empty-but-correct until auth lands).served_by,run_by) so they never collide with theother new edges (
ranfor Skill,invokedfor Program) under oneedge_typefilter.
Gateway is worth doing now; User can land in the same change but should be
understood as latent until
user_idis populated fleet-wide.References
hypaware-core/plugins-workspace/ai-gateway-graph/src/graph_contract.js(see the existingAppnode /viaedge as the template)hypaware-core/plugins-workspace/context-graph/src/project.jsuser_id