From 5fbee18a949c251eec1d9425a4eae0c7ae0ef122 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sun, 14 Jun 2026 23:22:17 -0400 Subject: [PATCH] =?UTF-8?q?feat(mcp):=20S5=20=E2=80=94=20issue-kind=20guid?= =?UTF-8?q?ance=20across=20all=20instruction=20surfaces?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plan #825 (T2 — Issues task_kind) shipped S1–S4 but its S5 docs slice never landed, so every behavioral surface the plugin pushes to the agent still described the pre-kind convention ("tag `issue`" on a create_note). Result: agents fixed bugs without reaching for kind=issue and dumped the work as logs on unrelated open tasks. - _INSTRUCTIONS: rewrite the "record a problem" bullet to create_task(kind="issue") with symptom→cause→fix + arose_from_id / system_ids, and an explicit "not a work-log on an unrelated task"; add Issue + System to the hierarchy section. - skills/systematic-debugging, verification: drop "tag `issue`" / create_note-issue, point at create_task(kind="issue"). - skills/using-scribe: add issues/systems to the entity list + reflex #6. - hooks/scribe_static_context: fix → its own issue on the keyless floor. Instance-agnostic, prose-only; no schema or tool-behavior change. Pairs with always-on rule #118. Issue: #855. Co-Authored-By: Claude Opus 4.8 (1M context) --- plugin/hooks/scribe_static_context.md | 4 +++- plugin/skills/systematic-debugging/SKILL.md | 16 ++++++++++------ plugin/skills/using-scribe/SKILL.md | 15 +++++++++++---- plugin/skills/verification/SKILL.md | 5 +++-- src/scribe/mcp/server.py | 20 +++++++++++++++++--- 5 files changed, 44 insertions(+), 16 deletions(-) diff --git a/plugin/hooks/scribe_static_context.md b/plugin/hooks/scribe_static_context.md index 4f42187..cb2ed02 100644 --- a/plugin/hooks/scribe_static_context.md +++ b/plugin/hooks/scribe_static_context.md @@ -20,7 +20,9 @@ for the operator's work, and as your own working memory across sessions. `add_task_log`. Always log when you **complete a task** and when you **hit or discover a problem** — so changes of direction are captured, not just successes. Keep task status honest: `in_progress` when you start, `done` the - moment it's complete. + moment it's complete. When you **fix** something — even in passing — record it + as its own issue (`create_task(kind="issue")`), not as a work-log line on an + unrelated open task. - Do **not** keep the operator's rules, plans, or project notes in local memory / CLAUDE.md in parallel with Scribe — Scribe holds the single copy. - **Compact at clean seams** — because you record as you go, a context diff --git a/plugin/skills/systematic-debugging/SKILL.md b/plugin/skills/systematic-debugging/SKILL.md index c29c853..87cdcf4 100644 --- a/plugin/skills/systematic-debugging/SKILL.md +++ b/plugin/skills/systematic-debugging/SKILL.md @@ -10,8 +10,9 @@ guessed fix that "seems to work" often just moves the bug somewhere else. ## Recall first -Before digging in, `search` Scribe for the symptom — a prior `issue` note may -already hold the cause and the fix. Don't re-debug what's already solved. +Before digging in, `search` Scribe for the symptom — a prior issue +(`list_tasks(kind="issue")` or `search`) may already hold the cause and the fix. +Don't re-debug what's already solved. ## The loop @@ -29,7 +30,10 @@ already hold the cause and the fix. Don't re-debug what's already solved. ## Capture the issue (so it's findable) -When resolved, record it in Scribe (`create_note`, tag `issue`): **symptom → -root cause → fix → how it was verified**. Even a problem fixed in passing is -worth two lines — that's how the next person (or you) avoids re-deriving it. If -the fix was tracked as a task, log the resolution there and set it `done`. +When resolved, record it in Scribe as its own issue (`create_task(kind="issue")`): +**symptom → root cause → fix → how it was verified** in the body, optionally +linked to the task it arose from (`arose_from_id`) and the subsystem it touches +(`system_ids`). Even a problem fixed in passing is worth two lines — that's how +the next person (or you) avoids re-deriving it. Record it discretely; don't bury +it as a work-log line on an unrelated open task. If the work was already tracked +as its own task, log the resolution there and set it `done`. diff --git a/plugin/skills/using-scribe/SKILL.md b/plugin/skills/using-scribe/SKILL.md index 9485bd0..c098447 100644 --- a/plugin/skills/using-scribe/SKILL.md +++ b/plugin/skills/using-scribe/SKILL.md @@ -5,10 +5,11 @@ description: Use at the START of every session, and before answering anything ab # Using Scribe -Scribe is the operator's self-hosted second brain (notes, tasks, projects, -milestones, events, typed entities) and rulebook, reachable through the bundled -`scribe` MCP server. Its value is mostly in what it **already holds** — so make -reading it a reflex, not something you wait to be asked for. +Scribe is the operator's self-hosted second brain (notes, tasks, issues, +projects, milestones, systems, events, typed entities) and rulebook, reachable +through the bundled `scribe` MCP server. Its value is mostly in what it +**already holds** — so make reading it a reflex, not something you wait to be +asked for. ## Do this first (every session) @@ -72,6 +73,12 @@ Two constraints on *how* that's achieved: 5. **Keep state honest.** Set a task `in_progress` when you start it, `done` the moment it's complete; log progress as you go. +6. **Fixes are issues, not work-logs.** When you fix a problem — even one solved + in passing — record it as its own issue (`create_task(kind="issue")`) with + symptom → root cause → fix, optionally linked to the task it arose from + (`arose_from_id`) and the subsystem it touches (`system_ids`). Don't bury a + fix as a work-log line on whatever task happened to be open. + ## Stay inside the active project's scope Once a project is in scope — you called `enter_project`, or the working repo is diff --git a/plugin/skills/verification/SKILL.md b/plugin/skills/verification/SKILL.md index 486fe17..444d185 100644 --- a/plugin/skills/verification/SKILL.md +++ b/plugin/skills/verification/SKILL.md @@ -23,8 +23,9 @@ task `done`, confirm it against reality and record what you checked. part of the record, not a private step. - Only then set the task `done`. Never mark finished work you haven't confirmed, and never leave confirmed work sitting at `in_progress`. -- If verification surfaced a problem, capture it (tag `issue`) and keep the task - open — a found problem is a pivot to record, not something to quietly skip. +- If verification surfaced a problem, capture it as its own issue + (`create_task(kind="issue")`) and keep the task open — a found problem is a + pivot to record, not something to quietly skip. ## Honesty over optimism diff --git a/src/scribe/mcp/server.py b/src/scribe/mcp/server.py index 0d39ca0..0f9b884 100644 --- a/src/scribe/mcp/server.py +++ b/src/scribe/mcp/server.py @@ -24,6 +24,12 @@ What each part is for, and when to reach for it: todo/in_progress/done/cancelled, optional priority). A task is a note with a status — reach for one when there is something to DO. Record progress over time with work-logs (add_task_log) rather than rewriting the body. +- Issue: a task whose kind is corrective — a problem you fixed or are fixing, as + opposed to productive `work`. Create it with create_task(kind="issue"); the + body carries symptom → root cause → fix. It has the full task lifecycle, and + can link the originating task it arose from (arose_from_id) and the System(s) + it touches (system_ids). Reach for one whenever you fix something — even in + passing — instead of burying the fix in another task's work-log. - Plan: a MILESTONE acting as a plan container — HOW you'll execute a chunk of work. The design/intent lives in the milestone `body`; each step is its own child task (create_task(milestone_id=...)), tracked with status + work-logs — @@ -35,6 +41,10 @@ What each part is for, and when to reach for it: - Note: durable free-form knowledge — reference material, decisions, logs of what happened. No lifecycle, not actionable. Reach for one to CAPTURE something worth keeping. +- System: a per-project, reusable, self-describing subsystem/area. Associate any + record (note, task, issue) with it via system_ids so research, build-work, and + fixes for the same area line up, and recurring problem-spots surface. Manage + with create_system / list_systems / get_system. - Typed entities (person/place/list): structured records about people, places, and checklists. @@ -90,9 +100,13 @@ Keep task state honest — this is what makes the project a trustworthy record: that changes direction — write a short dated note on the project (create_note) capturing what happened (the pivots, not just the wins), and set the finished task to done. -- When you record a problem you solved, capture symptom → root cause → fix - (tag it `issue`) so it's findable later — even one solved in passing is worth - two lines, so it isn't diagnosed from scratch next time. +- When you fix a problem — even one solved in passing — record it as its own + issue (create_task(kind="issue")) with symptom → root cause → fix in the body, + NOT as a work-log line on whatever task happened to be open. An issue is + corrective work with its own lifecycle; recording it discretely (optionally + linked via arose_from_id to the task it came from, and system_ids to the + subsystem it touches) is what makes it findable so it isn't diagnosed from + scratch next time. Compaction hygiene — recommend compacting at clean seams. Because you record progress as you go, a context compaction is SAFE: the durable state lives in