Two commits. CI green on dev head 6ca215d (run 3078, all six jobs).
390846a — fix(write-path): disclose cross-language prior art (#2244)
Retrieval matches on concept, and concepts are language-agnostic: a query about a
TypeScript union-find scores 0.72–0.73 against a Python snippet, over the 0.68
bar. Useful — a different-language solution gives you the shape — but the menu line
said nothing about it, so the reader either dismissed a good structural reference
or pasted Python into a .ts file.
This predates the concept-query change: raw TS code already matched the Python
snippet at 0.73, because the embedder reads identifiers and structure
semantically rather than syntactically.
plus one explanatory line, shown only when something on the menu is tagged.
Label, don't filter — a stricter bar for foreign hits would suppress exactly
the shape-borrowing this is for. Only claim a mismatch you can establish —
unknown extension or unrecorded language means no tag.
6ca215d — fix(telemetry): record a pull on get_task (#2245)
note_usage_events recorded surfaced for every auto-inject line but pulled
only from get_note / get_snippet / the REST snippet route. Auto-inject ranks
kind-blind over a corpus that is overwhelmingly tasks, so the loop was open
exactly where the volume is — measured live, "write a function to debounce a
callback in the frontend" returned three tasks and zero snippets, none of which
could record a pull.
That rate is what #1038 and #2085 gate on, so the metric would have said
"auto-inject surfaces things nobody opens" — an artifact of instrumentation
pointing at a plausible wrong conclusion.
Guarded by a rule-#33 source-inspection test, because a missing side effect is
invisible to behavioural testing.
Deploy notes
No migration. No plugin change, so no manifest bump — server-side only.
Two commits. CI green on `dev` head `6ca215d` (run 3078, all six jobs).
## `390846a` — fix(write-path): disclose cross-language prior art (#2244)
Retrieval matches on concept, and concepts are language-agnostic: a query about a
TypeScript union-find scores 0.72–0.73 against a **Python** snippet, over the 0.68
bar. Useful — a different-language solution gives you the shape — but the menu line
said nothing about it, so the reader either dismissed a good structural reference
or pasted Python into a `.ts` file.
This predates the concept-query change: raw TS code already matched the Python
snippet at 0.73, because the embedder reads identifiers and structure
semantically rather than syntactically.
> - #2222 [similar 0.72 · python] "group_pairs — Collapse ..."
plus one explanatory line, shown only when something on the menu is tagged.
**Label, don't filter** — a stricter bar for foreign hits would suppress exactly
the shape-borrowing this is for. **Only claim a mismatch you can establish** —
unknown extension or unrecorded language means no tag.
## `6ca215d` — fix(telemetry): record a pull on get_task (#2245)
`note_usage_events` recorded `surfaced` for every auto-inject line but `pulled`
only from `get_note` / `get_snippet` / the REST snippet route. Auto-inject ranks
kind-blind over a corpus that is overwhelmingly tasks, so the loop was open
exactly where the volume is — measured live, "write a function to debounce a
callback in the frontend" returned three tasks and zero snippets, none of which
could record a pull.
That rate is what #1038 and #2085 gate on, so the metric would have said
"auto-inject surfaces things nobody opens" — an artifact of instrumentation
pointing at a plausible wrong conclusion.
Guarded by a rule-#33 source-inspection test, because a missing side effect is
invisible to behavioural testing.
## Deploy notes
No migration. No plugin change, so no manifest bump — server-side only.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs
Closes#2244. Retrieval matches on concept, and concepts are language-agnostic:
asking about a TypeScript union-find scores 0.72-0.73 against a PYTHON snippet,
comfortably over the 0.68 bar. That is useful — a different-language solution
gives you the shape even when the code isn't reusable — but the menu line said
nothing about it, so the reader either dismissed a good structural reference or
pasted Python into a .ts file.
Worth noting this predates the concept-query change: raw TS code already matched
the Python snippet at 0.73, because the embedder reads identifiers and structure
semantically rather than syntactically. The fail state has been shipping quietly;
#2242 only made it an intended use rather than an accident.
- knowledge._note_to_item projects `language` from the data mirror, same shape as
the existing verification projection — a plain column read, no body parsing.
- The semantic arm carries language through on the item it builds; it is the arm
where these arise, since a snippet recorded AT the path you're editing is
almost never in another language.
- _prior_art_line folds it into the marker: [similar 0.72 · python]. Together
with the score rather than after the title, because the two jointly are the
judgement being offered.
- One explanatory line is added to the menu, and only when something on it is
actually tagged.
Two deliberate calls:
LABEL, DON'T FILTER. A stricter threshold for foreign-language hits would
suppress exactly the shape-borrowing this exists for. They were never the
problem; their being undisclosed was.
ONLY CLAIM A MISMATCH YOU CAN ESTABLISH. _foreign_language returns "" when either
side is unknown — unrecognised extension, or a snippet with no recorded language.
A wrong "· python" is worse than no tag. Same-language hits stay unlabelled, so
the common case keeps a clean line and the preamble stays off the menu entirely.
Operator-typed language names fold through an alias table first (py/python3 →
python, tsx → typescript, c++ → cpp); unrecognised names pass through lowercased,
which still makes an unknown-but-equal pair compare equal.
Trap found while building: _note() in the tests is a MagicMock, so `note.data`
auto-created a truthy mock that would have rendered its repr into a menu line.
Both test helpers now set data = None explicitly.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs
Closes#2245. note_usage_events recorded `surfaced` for every auto-inject menu
line regardless of kind, but `pulled` only from get_note, get_snippet and the
REST snippet route. get_task recorded nothing.
Auto-inject ranks kind-blind over a corpus that is overwhelmingly tasks and
issues, so tasks are most of what it surfaces. Measured live, "write a function
to debounce a callback in the frontend" returned three tasks and zero snippets —
all three written as surfaced, none able to record a pull.
surfaced and pulled only mean anything as a PAIR; the rate between them is what
#1038 and #2085 gate on. So the gap sat exactly where the volume is, and the
metric would have said "auto-inject surfaces things nobody opens" for its own
dominant kind — an artifact of the instrumentation, not a fact about the feature,
and one that pointed at a plausible-sounding wrong conclusion.
get_note already carried a comment stating this was meant to cover ANY note kind
precisely so tasks wouldn't look like dead weight. get_task is a separate tool in
a separate module and never got the call — sibling drift, invisible because a
missing side effect changes no return value.
Guarded by a rule-#33 contract test that asserts, by source inspection, that
every getter reachable from an auto-inject menu calls record_pulled. Source
inspection because no behavioural test can see a call that isn't there.
Not fixed here: the REST note/task detail routes still record nothing while the
REST snippet route records `rest_snippet`. That asymmetry is real, but a human
reading a note in a browser is arguably not the same event as an agent recalling
one, and collapsing them could skew the signal the other way. Raised as a
question for the retrieval survey instead of decided in passing.
Pre-fix rows under-count task pulls, one-sidedly by kind — treat them as unknown
rather than zero.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Two commits. CI green on
devhead6ca215d(run 3078, all six jobs).390846a— fix(write-path): disclose cross-language prior art (#2244)Retrieval matches on concept, and concepts are language-agnostic: a query about a
TypeScript union-find scores 0.72–0.73 against a Python snippet, over the 0.68
bar. Useful — a different-language solution gives you the shape — but the menu line
said nothing about it, so the reader either dismissed a good structural reference
or pasted Python into a
.tsfile.This predates the concept-query change: raw TS code already matched the Python
snippet at 0.73, because the embedder reads identifiers and structure
semantically rather than syntactically.
plus one explanatory line, shown only when something on the menu is tagged.
Label, don't filter — a stricter bar for foreign hits would suppress exactly
the shape-borrowing this is for. Only claim a mismatch you can establish —
unknown extension or unrecorded language means no tag.
6ca215d— fix(telemetry): record a pull on get_task (#2245)note_usage_eventsrecordedsurfacedfor every auto-inject line butpulledonly from
get_note/get_snippet/ the REST snippet route. Auto-inject rankskind-blind over a corpus that is overwhelmingly tasks, so the loop was open
exactly where the volume is — measured live, "write a function to debounce a
callback in the frontend" returned three tasks and zero snippets, none of which
could record a pull.
That rate is what #1038 and #2085 gate on, so the metric would have said
"auto-inject surfaces things nobody opens" — an artifact of instrumentation
pointing at a plausible wrong conclusion.
Guarded by a rule-#33 source-inspection test, because a missing side effect is
invisible to behavioural testing.
Deploy notes
No migration. No plugin change, so no manifest bump — server-side only.
🤖 Generated with Claude Code
https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs