diff --git a/plugin/.claude-plugin/plugin.json b/plugin/.claude-plugin/plugin.json index 6d5993e..62a9f31 100644 --- a/plugin/.claude-plugin/plugin.json +++ b/plugin/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "scribe", "description": "Scribe for Claude Code: connects the scribe MCP server, adds the hooks that deliver live project state and relevant records at the right moment, ships the shared client-neutral Scribe skills (using-scribe, writing-plans, reporting-back, systematic-debugging, verification, brainstorming, reusing-code, shape-accounting), and syncs your saved Scribe Processes as skills (/scribe:sync).", - "version": "2026.09.19.1614", + "version": "2026.09.20.0317", "author": { "name": "Bryan Van Deusen" }, diff --git a/plugin/skills/using-scribe/SKILL.md b/plugin/skills/using-scribe/SKILL.md index 96025e5..da98344 100644 --- a/plugin/skills/using-scribe/SKILL.md +++ b/plugin/skills/using-scribe/SKILL.md @@ -110,15 +110,27 @@ Two constraints on *how* that's achieved: silently, because it sometimes answers that what you are holding was never a rule — and routing an observation is not losing it. - **A preference is the one record you keep current yourself.** When the - operator corrects you, or the preference on file no longer matches how they - actually want something done, `update_preference` — that is expected, not a - liberty, and updating one mid-work is the normal case rather than an - interruption of it. It wants the task or note that taught the change. Say in the - same turn that you did it, so they can disagree while it is in front of - them. A rule waits for the operator instead: `create_rule` proposes and - asks. If what you learned is that something MUST be done a certain way, - that is a rule to propose, not a preference to harden in place. + **A preference is yours to keep current.** When the operator corrects you, + or the preference on file no longer matches how they actually want + something done, `update_preference` — that is expected, not a liberty, and + updating one mid-work is the normal case rather than an interruption of it. + It wants the task or note that taught the change. Say in the same turn that + you did it, so they can disagree while it is in front of them. A rule waits + for the operator instead: `create_rule` proposes and asks. If what you + learned is that something MUST be done a certain way, that is a rule to + propose, not a preference to harden in place. + + **A lesson grows each time it proves itself.** When one arrives and the + situation it names is the one you are actually in, you are the single + reader placed to tell whether its trigger is keyed right and whether its + claim covers what you are seeing. `update_lesson` takes what you now know: + another incident added to what taught it, the claim stated more exactly, + or — the edit worth most — a trigger re-keyed to the situation that really + fired. A lesson nobody reaches is seldom wrong; far more often it is + waiting in a situation nobody is in. One claim that has met the same + failure four times is worth more than four claims that each met it once, + so when a near-duplicate create hands back an existing id, that is the + record to grow. **Preferences shape how work is done, never what gets recorded.** They govern your conduct — how you report, how carefully you pace, which form diff --git a/src/scribe/mcp/tools/lessons.py b/src/scribe/mcp/tools/lessons.py index 05bd134..1d981ff 100644 --- a/src/scribe/mcp/tools/lessons.py +++ b/src/scribe/mcp/tools/lessons.py @@ -178,7 +178,17 @@ async def create_lesson( async def get_lesson(lesson_id: int) -> dict: - """Fetch one lesson by id, with its trigger and sources read back out.""" + """Fetch one lesson by id, with its trigger and sources read back out. + + IF THIS LESSON JUST PROVED ITSELF, IT IS WORTH MORE THAN IT SAYS. You are + reading it inside the situation it names, which makes you the one reader + who can tell whether its trigger is keyed to what actually fired and + whether its claim covers what you are seeing. `update_lesson` takes + another incident into `learned_from`, a claim stated more exactly, or a + re-keyed trigger — and the trigger is the edit that pays most, because a + lesson keyed to a situation nobody is in looks exactly like one nobody + needed. + """ uid = current_user_id() note = await lessons_svc.get_lesson(uid, lesson_id) if note is None: diff --git a/tests/test_guidance_ownership.py b/tests/test_guidance_ownership.py index bbf1f38..57f256e 100644 --- a/tests/test_guidance_ownership.py +++ b/tests/test_guidance_ownership.py @@ -118,7 +118,8 @@ TOPICS: tuple[Topic, ...] = ( "an empty session is not evidence of an empty rulebook", index=('content_type="rule"', "nothing matched")), Topic("rules bind, preferences guide and are kept current", U, ("preference", "update_preference"), - "a preference is the one record you keep current yourself", index=("preferences guide",)), + "updating one mid-work is the normal case rather than an interruption of it", + index=("preferences guide",)), Topic("kind is force: a rule binds, a preference guides, a lesson informs", U, ("lesson", "costs time", "costs consistency"), "what happens if someone doesn't do this", @@ -129,6 +130,14 @@ TOPICS: tuple[Topic, ...] = ( # mis-routing #3733 recorded happens, and the caller there has not # necessarily read the skill. shared_with=("docstrings",)), + Topic("a lesson grows each time it proves itself", U, + ("update_lesson", "re-keyed", "grows each time"), + "one claim that has met the same failure four times is worth more " + "than four claims that each met it once", + # No index marker. The index names session-START reflexes, and this + # one fires mid-work, the moment a lesson arrives in a situation it + # actually names. `lessons inform` already points at the kind. + shared_with=("docstrings",)), Topic("preferences shape how work is done, never what is recorded", U, ("never what gets recorded",), "a preference never makes a task into a note"),