feat(rulings): system_usage_events is read back — per-System counts and a telemetry block (#4769)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / integration (push) Successful in 50s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / Python tests (push) Successful in 1m44s
CI & Build / Build & push image (push) Successful in 36s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / integration (push) Successful in 50s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / Python tests (push) Successful in 1m44s
CI & Build / Build & push image (push) Successful in 36s
#4769 "Rulings are counted where someone will read them": milestone 444 step 4 wrote system_usage_events and nothing read it. - retrieval_telemetry gains a `system_usage` block: surfacings and opens by source, distinct counts, and `by_system` naming the areas most shown. There is deliberately no pull-through ratio, because rulings travel in full in the line and opens are the exception. - usage_for_systems (one GROUP BY) adds `usage` to the REST Systems list and detail, and to MCP get_system. MCP list_systems is unchanged. - The Systems UI shows a "rulings shown N×" chip. - rulings_pre_tool, rulings_write_path and mcp_get_system are now declared registry points; the registry guard covers their recorders. - The Systems store merges a PATCH reply instead of replacing the row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -380,7 +380,7 @@ async def retrieval_telemetry(
|
||||
— so `near_miss_samples=5` and opening the ids it returns is the step that
|
||||
separates a real miss from a bar doing its job.
|
||||
|
||||
Three readouts, from the three tables built for them:
|
||||
Four readouts, from the four tables built for them:
|
||||
|
||||
`sources` — per retrieval surface (`auto_inject`, `write_path`,
|
||||
`mcp_search`, …), from `retrieval_logs`: `calls`, `zero_result_calls`,
|
||||
@@ -529,6 +529,16 @@ It is an UPPER BOUND per surface: a pull records the door it came
|
||||
the zeros were missing rather than absent (#3497). Measured since, it
|
||||
declines the large majority of its calls like any other surface.
|
||||
|
||||
`system_usage` — the RULINGS arm (#4769), from `system_usage_events`: how
|
||||
often an area's rulings were shown because a command (`rulings_pre_tool`)
|
||||
or an edit (`rulings_write_path`) touched its files, how often a System
|
||||
was then opened (`mcp_get_system`), and `by_system` naming the areas, most
|
||||
shown first. A lookup, not a ranker, so it has no row in `sources` and no
|
||||
floor to tune. And NO `pull_through`, on purpose: the rulings travel in
|
||||
full in the line, so a session reads them without opening anything, and
|
||||
a ratio of opens would read near zero on an arm that is working.
|
||||
`system_usage_failed: true` means its read broke and the zeros mean nothing.
|
||||
|
||||
EVERY COUNTER BLOCK CARRIES ITS OWN COVERAGE — `complete_from` and
|
||||
`covers_window`. `complete_from` is when the number became trustworthy:
|
||||
for one source, its first recorded row; for a section that sums several,
|
||||
|
||||
@@ -18,6 +18,7 @@ from scribe.services import canonical_systems as canonical_systems_svc
|
||||
from scribe.services import milestones as milestones_svc
|
||||
from scribe.services import notes as notes_svc
|
||||
from scribe.services import systems as systems_svc
|
||||
from scribe.services import system_usage as system_usage_svc
|
||||
from scribe.services.system_usage import record_system_pulled
|
||||
|
||||
# Below this, a project is young enough that the mild "which area is this
|
||||
@@ -288,7 +289,9 @@ async def get_system(system_id: int) -> dict:
|
||||
|
||||
Returns the system, plus its associated records split into `issues`,
|
||||
`tasks` (work/plan), and `notes` — each saying what the record is and where
|
||||
it sits, not what it says (open one with get_note / get_task).
|
||||
it sits, not what it says (open one with get_note / get_task) — and
|
||||
`usage`: how many times its rulings were shown to a session because its
|
||||
files were touched (`surfaced_count`), and how many times it was opened.
|
||||
"""
|
||||
uid = current_user_id()
|
||||
system = await systems_svc.get_system(uid, system_id)
|
||||
@@ -312,6 +315,10 @@ async def get_system(system_id: int) -> dict:
|
||||
data["issues"] = issues
|
||||
data["tasks"] = tasks
|
||||
data["notes"] = notes
|
||||
# How often this area's rulings were shown to a session and the System
|
||||
# opened (#4769). Here and not on list_systems: one lookup on a read that
|
||||
# asked for the System, rather than a column on every project handshake.
|
||||
data["usage"] = (await system_usage_svc.usage_for_systems([system.id]))[system.id]
|
||||
return data
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user