From fb36599f2d5810f8a44c7ddd6e4e0416bc77130b Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Tue, 15 Sep 2026 13:45:52 -0400 Subject: [PATCH] docs(plugin): find the existing plan before making one, and file related work into it (#4080) Step 5 of milestone 415 "An existing plan is found before a new one is made". Sessions opened a second milestone beside the roadmap milestone that already covered the work, and filed related tasks loose, because no surface told them to look first. - writing-plans: a section on finding the plan that exists (enter_project's unplanned_milestones, search(content_type="milestone"), list_milestones); when an active milestone covers the work, add steps to it; a second milestone only for a separate arc; the gate's existing_milestone reply. - using-scribe: "when you plan" gains the same check and milestone_id on related tasks. - _INSTRUCTIONS PLAN line points at the milestone search (1,689 of 2,000). - test_guidance_ownership pins the topic on writing-plans. - Plugin version minted: 2026.09.15.1744. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01821k5B3Ysecp9fNYs92Kuy --- plugin/.claude-plugin/plugin.json | 2 +- plugin/skills/using-scribe/SKILL.md | 6 ++++++ plugin/skills/writing-plans/SKILL.md | 30 +++++++++++++++++++++++++++- src/scribe/mcp/server.py | 5 +++-- tests/test_guidance_ownership.py | 6 ++++++ 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/plugin/.claude-plugin/plugin.json b/plugin/.claude-plugin/plugin.json index 885fc5f..0db0f27 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.15.1626", + "version": "2026.09.15.1744", "author": { "name": "Bryan Van Deusen" }, diff --git a/plugin/skills/using-scribe/SKILL.md b/plugin/skills/using-scribe/SKILL.md index 9370e04..3ada364 100644 --- a/plugin/skills/using-scribe/SKILL.md +++ b/plugin/skills/using-scribe/SKILL.md @@ -111,6 +111,12 @@ Two constraints on *how* that's achieved: is just a task — don't wrap it in a milestone. Either way, do not write plans/specs to local `.md` files. See the **writing-plans** skill. + **Find the plan before you make one.** A project's existing milestones are + often its roadmap, and a milestone with no steps yet is still open work. + `search(content_type="milestone", project_id=...)` finds one by purpose. When + an active milestone covers the work, add steps to it rather than opening + another, and give any task you record for that work its `milestone_id`. + 5. **Keep state honest.** Set a task `in_progress` when you start it, `done` the moment it's complete; log progress as you go. Always log when you **complete** a task and when you **hit or discover a problem**, so a change diff --git a/plugin/skills/writing-plans/SKILL.md b/plugin/skills/writing-plans/SKILL.md index c2d3969..9810999 100644 --- a/plugin/skills/writing-plans/SKILL.md +++ b/plugin/skills/writing-plans/SKILL.md @@ -26,6 +26,34 @@ a complete, honest record of work that didn't need a plan. Some projects are milestone-shaped and some are a flat task list. Read the project you are in rather than imposing a shape on it. +## Then look for the plan that already exists + +Before you start a plan, find out whether the project already has one for this +work. A roadmap is often written ahead of the work as milestones with a goal +and no steps yet, and those are exactly the plans a session misses: they have +nothing in them to show up as open tasks. + +- `enter_project` lists the recent milestones and, under `unplanned_milestones`, + the active ones with no steps. +- `search(content_type="milestone", project_id=...)` finds a plan by what it is + for. `list_milestones` reads the whole roadmap. + +**When an active milestone already covers the work, the plan is that milestone.** +Read it with `get_milestone`, add your steps with +`create_records(milestone_id=, records=[…])`, and revise its body with +`update_milestone` if what you know now changes the design. Opening a new +milestone beside it splits one piece of work across two plans, and neither +shows the whole. A second milestone is right only when the work is a separate +arc: a different goal that would still make sense if the first plan were done. + +The same holds for single tasks. Work that belongs to an existing plan is +created with that milestone's `milestone_id`, not left loose beside it. + +`start_planning` and `create_milestone` check too. When an active milestone in +the project has the same title or reads as the same plan, they return it as +`existing_milestone` and create nothing. Add to that plan, or pass `force=true` +only when you have read it and this really is separate work. + ## When it does: start the plan in Scribe, not a file Call **`start_planning(project_id, title)`** before designing or implementing — @@ -59,7 +87,7 @@ record, not a file on disk. (The old `kind=plan` task is retired; `start_plannin no longer creates one.) Before designing from scratch, **recall**: `search` Scribe for a related prior -plan or decision. Often the thinking (or half of it) already exists. +decision or note. Often the thinking (or half of it) already exists. ## What a good plan contains diff --git a/src/scribe/mcp/server.py b/src/scribe/mcp/server.py index 3175676..7eb1c5a 100644 --- a/src/scribe/mcp/server.py +++ b/src/scribe/mcp/server.py @@ -49,8 +49,9 @@ client reads Agent Skills) and in each tool's description. The index: - RECALL: search before acting, scoped with the active project_id. - RECORD: create_task; a fix is kind="issue". add_task_log as you go; status in_progress on start, done on finish. Tag system_ids as you write. -- PLAN work with an arc: start_planning(steps=[...]). The plan is a milestone - and each step a task. +- PLAN work with an arc: find the existing plan first + (search(content_type="milestone")) and add steps to it; else + start_planning(steps=[...]). The plan is a milestone and each step a task. - IDS exist only once a create returns them. Records that cite each other go through create_records, writing {{ref:N}} for the Nth record. - REUSE: search snippets before building; create_snippet what you build. diff --git a/tests/test_guidance_ownership.py b/tests/test_guidance_ownership.py index 841fa2c..43140cc 100644 --- a/tests/test_guidance_ownership.py +++ b/tests/test_guidance_ownership.py @@ -147,6 +147,12 @@ TOPICS: tuple[Topic, ...] = ( # ── process arcs — owned by their skills ── Topic("plan in a milestone, steps created together", "skill:writing-plans", ("start_planning", "{{ref:"), "a milestone earns its place when the work has an arc", index=("start_planning",)), + # Milestone 415: sessions opened a second plan beside the roadmap milestone + # that already covered the work, because nothing told them to look. + Topic("find the existing plan before making one", "skill:writing-plans", + ('content_type="milestone"', "unplanned_milestones", "existing_milestone"), + "when an active milestone already covers the work, the plan is that milestone", + index=('search(content_type="milestone")',)), Topic("reuse recorded shapes; record at first build", "skill:reusing-code", ("create_snippet", "when_to_use", "first build", "second copy"), "prior art offered beside a write is not noise", index=("create_snippet",)),