You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Extend override_axis_rollup_smoke with abstract/concrete Kafka producer
override; replace synthetic producers-in-overriders hint test with
describe_v2 e2e. Amend HINTS-ROAD-SIGNS Appendix A and AGENT-GUIDE for
DECLARES_PRODUCER / OVERRIDDEN_BY.DECLARES_PRODUCER parity.
Co-authored-by: Cursor <cursoragent@cursor.com>
Copy file name to clipboardExpand all lines: docs/AGENT-GUIDE.md
+4-3Lines changed: 4 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -225,12 +225,13 @@ Exact allowed values for roles, capabilities, client kinds, etc. live in `java_o
225
225
226
226
#### `describe`
227
227
228
-
- **Purpose:** Full node payload + `edge_summary`: `in` / `out` counts **per stored graph edge label** (what exists as edges in Kuzu). For **type** Symbols only (`class`, `interface`, `enum`, `record`, `annotation`), the same map may also include **describe-time composed** dot-keys — summaries of member edges, not stored labels — see the next bullets (`DECLARES.DECLARES_CLIENT`, `DECLARES.EXPOSES`); those keys are **not** valid in `neighbors(edge_types=…)`. For **method** Symbols, the map may include **override-axis virtual keys** (`OVERRIDDEN_BY`, `OVERRIDDEN_BY.DECLARES_CLIENT`, `OVERRIDDEN_BY.EXPOSES`) plus an **`OVERRIDES` row** that merges stored `[:OVERRIDES]` incident counts with the describe-time dispatch-up rollup (per direction `max`, so inbound stored overrides are preserved); see **Override-axis keys (method Symbols)** below — those virtual keys are **not** `neighbors` arguments. The **stored** relationship label **`OVERRIDES`** **is** a valid `EdgeType` for `neighbors` (same spelling as the map key; the map row is the merged view).
228
+
- **Purpose:** Full node payload + `edge_summary`: `in` / `out` counts **per stored graph edge label** (what exists as edges in Kuzu). For **type** Symbols only (`class`, `interface`, `enum`, `record`, `annotation`), the same map may also include **describe-time composed** dot-keys — summaries of member edges, not stored labels — see the next bullets (`DECLARES.DECLARES_CLIENT`, `DECLARES.DECLARES_PRODUCER`, `DECLARES.EXPOSES`); those keys are **not** valid in `neighbors(edge_types=…)`. For **method** Symbols, the map may include **override-axis virtual keys** (`OVERRIDDEN_BY`, `OVERRIDDEN_BY.DECLARES_CLIENT`, `OVERRIDDEN_BY.DECLARES_PRODUCER`, `OVERRIDDEN_BY.EXPOSES`) plus an **`OVERRIDES` row** that merges stored `[:OVERRIDES]` incident counts with the describe-time dispatch-up rollup (per direction `max`, so inbound stored overrides are preserved); see **Override-axis keys (method Symbols)** below — those virtual keys are **not** `neighbors` arguments. The **stored** relationship label **`OVERRIDES`** **is** a valid `EdgeType` for `neighbors` (same spelling as the map key; the map row is the merged view).
229
229
-**Args:**`id` (symbol, route, or client id) or **`fqn`** (exact symbol FQN when you do not have the graph id). When both are set, `id` wins. For identifier-shaped inputs and FQN collision handling, see **Identifier resolution** above.
230
230
231
-
**Composed `edge_summary` keys (type Symbols).** Keys use dot notation: `<parent_relation>.<projected_relation>`. Two are emitted today:
231
+
**Composed `edge_summary` keys (type Symbols).** Keys use dot notation: `<parent_relation>.<projected_relation>`. Three are emitted today:
232
232
233
233
-`DECLARES.DECLARES_CLIENT` — the type's methods declare brownfield HTTP clients (count is the number of `Client` rows reached through `DECLARES → DECLARES_CLIENT`). To enumerate them: `neighbors(ids=<class_id>, direction="out", edge_types=["DECLARES"])` → for each method id, `neighbors(ids=<method_id>, direction="out", edge_types=["DECLARES_CLIENT"])`.
234
+
-`DECLARES.DECLARES_PRODUCER` — the type's methods declare async producers. Same walk shape with `DECLARES_PRODUCER`.
234
235
-`DECLARES.EXPOSES` — the type's methods expose routes. Same walk shape with `EXPOSES`.
235
236
236
237
Composed keys are **read-only**: they cannot be passed to `neighbors(edge_types=…)` (the dot is not a valid `EdgeType` literal — the call fails with a Pydantic `ValidationError`). Use them as a hop affordance only.
@@ -240,7 +241,7 @@ Note on counting semantics: composed counts measure **edge rows**, not distinct
240
241
**Override-axis keys (method Symbols).** Dispatch-axis signals computed at describe-time from `IMPLEMENTS` / `EXTENDS` plus matching `Symbol.signature` (not stored as their own rel types):
241
242
242
243
-`OVERRIDDEN_BY` — on declarations reachable from implementing / extending classes in one hop: count of **distinct** concrete override methods with the same `signature` string as the described method (not counting the declaration itself).
243
-
-`OVERRIDDEN_BY.DECLARES_CLIENT` / `OVERRIDDEN_BY.EXPOSES` — same dispatch-down walk, then count outgoing `DECLARES_CLIENT` / `EXPOSES` edges from those override methods. Counts are **edge rows** on overrides (not distinct methods): one override with multiple client edges contributes the full row count. Omitted when zero.
244
+
-`OVERRIDDEN_BY.DECLARES_CLIENT` / `OVERRIDDEN_BY.DECLARES_PRODUCER` / `OVERRIDDEN_BY.EXPOSES` — same dispatch-down walk, then count outgoing `DECLARES_CLIENT` / `DECLARES_PRODUCER` / `EXPOSES` edges from those override methods. Counts are **edge rows** on overrides (not distinct methods): one override with multiple client edges contributes the full row count. Omitted when zero.
244
245
-`OVERRIDES` (map row) — merges **stored**`[:OVERRIDES]``in`/`out` (subtype→supertype edges in Kuzu) with the dispatch-up rollup (distinct upstream declarations one `IMPLEMENTS`/`EXTENDS` hop away, same `signature`). The rollup alone always reported `in: 0`; merging fixes `in` when this method is also a super declaration with incoming override edges. A class implementing two interfaces that both declare the same signature yields `out: 2` on the rollup arm (and matches stored outbound edges when materialization aligns). Prefer `neighbors(ids=<method_id>, direction="out", edge_types=["OVERRIDES"])` to list declaration ids, and `direction="in"` for overriders.
245
246
246
247
Walk recipe (manual, if you need types in the middle): `neighbors(ids=<method_id>, direction="in", edge_types=["DECLARES"])` → declaring type → `neighbors(ids=<type_id>, direction="in", edge_types=["IMPLEMENTS","EXTENDS"])` → each subtype class → `neighbors(ids=<class_id>, direction="out", edge_types=["DECLARES"])` and filter rows where `signature` matches the interface method.
results==[] and filter has identifier-shaped value → "no matches — try resolve(identifier, hint_kind='{kind}') for canonical lookup"
@@ -273,6 +278,8 @@ File placement (`mcp_hints.py`), function decomposition, integration points in `
273
278
274
279
## Appendix B — What changed (traceability)
275
280
281
+
**Amendment (2026-05-16, issue #161 / PR #164)** — five describe templates for the producer axis and override-route rollup, symmetric with the client/route rows above: `DECLARES.DECLARES_PRODUCER`, `DECLARES_PRODUCER`, `OVERRIDDEN_BY.DECLARES_PRODUCER`, `OVERRIDDEN_BY.EXPOSES`, and `kind == producer` declaring-method hint. No ontology or re-index change.
282
+
276
283
**What stayed unchanged from the first draft**
277
284
278
285
- §1 frame statement; §2 principles 1–8; §3.1 field shape; §3.2 generation contract; §5 "deliberately does NOT do" table; §8 risks table.
0 commit comments