docs(6206): routes/lessons comments drop citations and the corpus measurement

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 20:39:00 -04:00
co-authored by Claude Opus 5.5
parent 0c237172e4
commit 2a5276eb0e
+11 -15
View File
@@ -7,18 +7,16 @@ contract and the `data` mirror live in one place — the same division snippets
use, and for the same reason: two doors that each compose a lesson would
compose it two ways, and the document IS what ranks.
ACL (rule #78): reads and writes of a single lesson resolve through the
ACL: reads and writes of a single lesson resolve through the
share-aware `get_lesson` / `can_write_note`, and writes are performed as the
OWNER so a shared editor isn't rejected by the owner-scoped service —
mirroring routes/snippets.py and routes/notes.py.
WHY THE TRIGGER IS A NAMED FIELD HERE TOO. The web editor could have posted a
body and let the service parse it. It doesn't, because the evidence behind
this kind (step 1) is that a trigger gets filled when a door ASKS for it by
name — the snippet corpus is at 100% on its trigger with no guard anywhere,
because a service composes the title from a parameter. A form that offered one
markdown box would be the option milestone 385 rejected, wearing a different
hat.
body and let the service parse it. It doesn't, because a trigger gets filled
when a door ASKS for it by name — a field the service composes from a named
parameter is filled every time, with no guard anywhere, and a single markdown
box is not.
"""
import logging
@@ -63,7 +61,7 @@ async def list_lessons_route():
project_id = None
limit, offset = parse_pagination(default_limit=24, max_limit=100)
# The lessons nobody has answered "which rule?" for (#4631). A listing,
# The lessons nobody has answered "which rule?" for. A listing,
# so it does not combine with a search — the MCP door says the same.
if request.args.get("unjudged") in ("1", "true"):
if q:
@@ -87,7 +85,6 @@ async def list_lessons_route():
# construction. Every row gets the key, zero-filled, so the UI renders
# "never surfaced" rather than treating a missing field as a state.
#
# Lessons were the one kind collecting this and showing it nowhere (#4196).
# The counts matter more here than on a snippet: the promotion question a
# lesson eventually raises — does this bind? — is answered by repeatedly
# surfaced AND repeatedly opened, and the far commoner reading of the same
@@ -122,8 +119,7 @@ async def lessons_taught_by_route(record_id: int):
@lessons_bp.route("/rule-candidates", methods=["GET"])
@login_required
async def lesson_rule_candidates_route():
"""The rules a lesson being written resembles, BEFORE it is saved
(milestone 440, #4658).
"""The rules a lesson being written resembles, BEFORE it is saved.
The create door offers the same list in its reply when neither answer was
given. A form needs it earlier, so the writer can name the rule in the
@@ -178,7 +174,7 @@ async def create_lesson_route():
project_id = data.get("project_id") or None
learned_from = data.get("learned_from") or []
# The rules this lesson is an instance of (milestone 440). Validated before
# The rules this lesson is an instance of. Validated before
# anything is written, as the MCP door does, so a bad id saves nothing.
no_rule = (data.get("no_rule") or "").strip()
try:
@@ -264,7 +260,7 @@ async def get_lesson_route(lesson_id: int):
await lesson_rules_svc.attach_lesson_rules(uid, [out])
# Opening the detail view IS a pull — the operator chose to look. Tagged
# apart from the MCP sources so "an agent was handed it" and "a human read
# it" stay distinguishable; they mean different things for pruning (#2085).
# it" stay distinguishable; they mean different things for pruning.
record_pulled(user_id=uid, note_id=lesson_id, source="rest_lesson")
return jsonify(out)
@@ -322,7 +318,7 @@ async def update_lesson_route(lesson_id: int):
if no_rule:
await lesson_rules_svc.set_no_rule(uid, lesson_id, no_rule)
if data.get("system_ids") is not None:
# The CALLER, not owner_uid (#4249). `set_record_systems` runs its own
# The CALLER, not owner_uid. `set_record_systems` runs its own
# `can_write_note` and links only Systems the acting user can read;
# handing it the owner makes that check trivially pass and filters by
# the owner's visibility instead. The caller's write permission is
@@ -331,7 +327,7 @@ async def update_lesson_route(lesson_id: int):
await systems_svc.set_record_systems(uid, lesson_id, data["system_ids"])
out = lessons_svc.lesson_to_dict(updated)
if no_rule:
# The same nudge the MCP door gives (#4634): this answer may complete
# The same nudge the MCP door gives: this answer may complete
# a group of no-rule lessons in one situation.
group = await lesson_rules_svc.convergence_for(uid, lesson_id)
if group: