build_prompt_rule_hint, build_tool_rule_hint and build_write_path_hint
each ran the rule arm and then the via-lesson step by hand, the first two
passing the query between them through a _via_query key on the payload.
They now call one composer, _rule_moment, and the split helpers
(_prompt_rule_hint, _tool_rule_hint, _add_rules_via_lessons) and the side
channel are deleted. Output shapes are unchanged: the prompt builder
returns no checkpoint key, the tool builder always does, and
shown_rule_ids stays the direct band.
A structural test pins that only _rule_moment runs a rule arm or the
via-lesson step, and that the three builders are its only callers.
plugin_context.py: 2,418 -> 2,361 lines this step; 3,558 when the
milestone began.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On all three rule arms (prompt_rule, pre_tool_rule, write_path_rule), after
the direct match, a lesson matching the moment at the notes menu's own bar
brings the rule(s) it is CONFIRMED to be an instance of, rendered in rule
voice with "Reached through lesson #N “…”, a recorded instance of it."
- Confirmed links only (lesson_rules.confirmed_lessons /
confirmed_rules_in_scope). A suggested link carrying its rule would
manufacture the co-arrival #4637 counts and prove itself.
- Scope kept: a lesson surfaces everywhere, but the rule it brings must be
global or this project's own — milestone 414's boundary, not reopened
through a side door.
- Suppression is by RULE: anything the direct band named or the session
ledger holds is skipped, whichever lesson reached it.
- Its own slot (VIA_LESSON_LIMIT = 1), not a rule slot — a stated default,
since the plan's "decide by measurement" has nothing to measure until
links are confirmed (#4632). Its own source, rule_via_lesson: registered,
RANKED for pull-through, logged whenever it searches.
- Nothing searched at all while no lesson carries a confirmed link, which is
every install until one is judged.
- build_prompt_rule_hint / build_tool_rule_hint are now thin wrappers over
the direct arms (_prompt_rule_hint / _tool_rule_hint); the arm leaves its
query in `_via_query` only when it ran, so a disabled arm or a blank prompt
brings no rule in either, and the key never leaves the server.
- Via-lesson rules are not fed to the #4637 co-surfacing recorder: only
direct matches are evidence.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>