feat(rules): a rule surfaces through the lessons confirmed as its instances (milestone 440 step 4, #4633)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 18s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / integration (push) Successful in 55s
CI & Build / Python tests (push) Failing after 1m16s
CI & Build / Build & push image (push) Skipped
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 18s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / integration (push) Successful in 55s
CI & Build / Python tests (push) Failing after 1m16s
CI & Build / Build & push image (push) Skipped
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>
This commit is contained in:
@@ -314,3 +314,36 @@ async def test_confirming_a_suggestion_keeps_what_it_rested_on(world):
|
||||
out = await links_svc.judge_link(world["owner"], world["lesson"], world["r1"], "confirm", "same failure class")
|
||||
assert out["state"] == "confirmed"
|
||||
assert len(out["evidence"]["situations"]) == 3
|
||||
|
||||
|
||||
# ── #4633: which links can carry a rule ─────────────────────────────────────
|
||||
|
||||
|
||||
async def test_only_a_confirmed_link_can_carry_its_rule(world):
|
||||
"""A suggested link never expands: it would manufacture the co-arrival
|
||||
that #4637 counts, and prove itself. A rejected one obviously not."""
|
||||
owner, lesson = world["owner"], world["lesson"]
|
||||
await links_svc.co_surfaced(owner, [lesson], [world["r1"]], arm="p", situation="one ask here")
|
||||
await links_svc.judge_link(owner, lesson, world["r2"], "reject", "not this")
|
||||
assert await links_svc.confirmed_lessons(owner) == set()
|
||||
assert await links_svc.confirmed_rules_in_scope(owner, [lesson], world["mine"]) == {}
|
||||
|
||||
await links_svc.judge_link(owner, lesson, world["r1"], "confirm", "same failure class")
|
||||
assert lesson in await links_svc.confirmed_lessons(owner)
|
||||
rules = await links_svc.confirmed_rules_in_scope(owner, [lesson], world["mine"])
|
||||
assert [r.id for r in rules[lesson]] == [world["r1"]]
|
||||
|
||||
|
||||
async def test_a_project_rule_stays_in_its_project_even_through_a_lesson(world):
|
||||
"""Milestone 414's scope, kept on the side door: the lesson surfaces
|
||||
everywhere, its project rule only in its project."""
|
||||
owner, lesson = world["owner"], world["lesson"]
|
||||
await links_svc.set_lesson_rules(owner, lesson, [world["r1"]])
|
||||
assert await links_svc.confirmed_rules_in_scope(owner, [lesson], world["mine"])
|
||||
assert await links_svc.confirmed_rules_in_scope(owner, [lesson], world["theirs"]) == {}
|
||||
assert await links_svc.confirmed_rules_in_scope(owner, [lesson], None) == {}
|
||||
|
||||
|
||||
async def test_a_stranger_reaches_no_rule_through_someone_elses_link(world):
|
||||
await links_svc.set_lesson_rules(world["owner"], world["lesson"], [world["r1"]])
|
||||
assert await links_svc.confirmed_lessons(world["stranger"]) == set()
|
||||
|
||||
Reference in New Issue
Block a user