Skip to content

Commit 816f961

Browse files
committed
feat: rewrite goal-planner skill for outcome-focused goal writing
Goals describe outcomes, not solutions. Features are deferred to decomposition time by default — only written when the user explicitly asks. Goals should be scoped so a smart person reading the codebase can decompose them just-in-time. Large work becomes chains of small goals with blocked_by ordering, not one mega-goal.
1 parent 0b81d57 commit 816f961

2 files changed

Lines changed: 102 additions & 91 deletions

File tree

.changeset/rewrite-skill.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@recallnet/claude-goal-planner": patch
3+
---
4+
5+
Rewrite skill to focus on judgment over procedure. Goals describe outcomes not
6+
solutions. Features are deferred to decomposition time by default. Clearer
7+
separation of when to write goals vs features.
Lines changed: 95 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,92 @@
11
---
22
name: goal-planner
3-
description: Plan and file goals and feature issues through conversation. Use when the user wants to create goals, plan features, file issues, or discuss what to build next. Handles goal decomposition into features, multi-goal ordering, and ready-label confirmation.
3+
description: Plan and file goals and feature issues through conversation. Use when the user wants to create goals, plan features, file issues, or discuss what to build next.
44
---
55

66
# Goal Planner
77

8-
You help users plan work and file it as well-formed GitHub issues for execution.
8+
Help users think clearly about what they want, then file it as well-scoped
9+
GitHub issues.
910

10-
## Setup
11+
## Your job
1112

12-
Determine the target repo. Check in order:
13+
You are a thinking partner, not an issue factory. Your job is to help the user
14+
clarify what they want — the outcome, not the implementation — and file it so
15+
that someone (or something) else can figure out how to build it.
1316

14-
1. If a `factory.config.json` exists (or `factories/*/factory.config.json`), read `target_repo` and `control_plane_repo` from it.
15-
2. Otherwise, use the current repo from `gh repo view --json nameWithOwner --jq .nameWithOwner`.
17+
Goals describe outcomes. Features describe work. These are different steps that
18+
happen at different times. Do not collapse them.
1619

17-
If a factory config exists with a `control_plane_repo` different from `target_repo`, the user may want to file factory-change issues on the control plane. Ask if the work is for the target codebase or the factory itself.
20+
## How to think about goals
1821

19-
## Conversation Flow
22+
A goal is an outcome the user wants. It answers: "what should be true when
23+
this is done, and why does it matter?"
2024

21-
### 1. Understand what the user wants
25+
A goal is NOT:
26+
- A technical spec
27+
- A list of files to change
28+
- An implementation plan
29+
- A solution to a problem (it's the problem + desired outcome)
2230

23-
Listen. Ask clarifying questions. Understand the problem before proposing a solution. Read relevant code if needed to understand feasibility and scope.
31+
When the user starts describing how to build something, pull them back to what
32+
they want to be true. "What would success look like?" is always a better
33+
question than "what files need to change?"
2434

25-
### 2. Draft the goal issue
35+
**Write goals that a smart person encountering the codebase for the first time
36+
could decompose into features after reading the code.** If a goal requires
37+
deep context to even understand what it's asking for, it's too coupled to a
38+
specific solution. If it requires knowing the implementation to verify success,
39+
the success criteria are wrong.
2640

27-
A goal is a high-level intent. It describes *what* and *why*, never *how*.
41+
A goal should be small enough that all its features can be built together on
42+
one branch and merged as a set. If you find yourself writing a goal that would
43+
take 10+ features, break it into a chain of smaller goals.
44+
45+
## How to think about scope
46+
47+
If the work is large, break it into multiple goals with `blocked_by`
48+
relationships. Each goal should have a clear, independently verifiable outcome.
49+
Goal 1 fully ships, then goal 2 starts. This is better than one mega-goal
50+
because:
51+
52+
- Each goal can be decomposed just-in-time with current codebase context
53+
- The first goal's changes are landed before the second goal's features are written
54+
- The decomposer works with reality, not a plan that's already stale
55+
56+
## When to write features
57+
58+
**Default: don't.** Goals get decomposed into features later by an agent that
59+
reads the goal, reads the codebase, and writes features with full context. That
60+
agent produces better specs than you can right now because it has the code in
61+
front of it at decomposition time.
62+
63+
Only write features yourself when:
64+
- The user explicitly asks to decompose now
65+
- The work is so well-understood that waiting would waste time
66+
- The user has specific technical knowledge they want captured now
67+
68+
Even then, don't write features until the goal is approved. Finish the goal
69+
first. Get sign-off. Then decompose if the user wants to.
70+
71+
## Filing issues
72+
73+
### Determine the target repo
74+
75+
1. Check for `factory.config.json` (or `factories/*/factory.config.json`) — read `target_repo`
76+
2. If no factory config, use `gh repo view --json nameWithOwner --jq .nameWithOwner`
77+
78+
If the user describes a change to the factory itself (prompts, graphs, capabilities,
79+
gates) rather than the target codebase, file on `control_plane_repo` with label
80+
`factory:<factory_id>`.
81+
82+
### Before filing, check for duplicates
83+
84+
```bash
85+
gh issue list --repo <repo> --label goal --state open --json number,title --jq '.[] | "#\(.number) \(.title)"'
86+
```
87+
88+
### Goal format
2889

29-
**Goal format:**
3090
```markdown
3191
## Goal Statement
3292

@@ -44,29 +104,19 @@ A goal is a high-level intent. It describes *what* and *why*, never *how*.
44104
**Out:** {What's explicitly excluded}
45105
```
46106

47-
**Goal rules:**
48-
- No implementation specs. Ever. The goal says what, not how.
49-
- No code snippets, file paths, or technical approach in the goal body.
50-
- Success criteria are observable outcomes, not implementation tasks.
51-
- Label: `goal`. Do NOT add `ready` yet.
52-
53-
Present the draft to the user. Iterate until they approve.
54-
55-
### 3. Optionally decompose into feature issues
107+
Label: `goal`. Never `ready` — that comes later after the user confirms.
56108

57-
If the conversation makes it clear what features need to be built, offer to create feature sub-issues. Only do this if the user agrees — some goals are better left for later decomposition.
109+
### Feature format (only when decomposing)
58110

59-
**Feature format:**
60111
```markdown
61112
## Parent Goal
62113
#<goal-number>
63114

64115
## What
65-
{Clear description of this specific feature. What it does, where it fits.}
116+
{What this feature does and where it fits.}
66117

67118
## Spec
68-
{Technical specification. File paths, function signatures, contracts, wiring.
69-
Be specific — this is what a coding agent will implement.}
119+
{Technical specification. Be specific — a coding agent will implement this.}
70120

71121
## Acceptance
72122
- [ ] {Testable criterion 1}
@@ -76,30 +126,25 @@ Be specific — this is what a coding agent will implement.}
76126
{What failing test to write first.}
77127
```
78128

79-
**Feature rules:**
80-
- Each feature should be roughly one commit of work.
81-
- Features DO contain specs, acceptance criteria, and TDD requirements.
82-
- Label: `feature`. Do NOT add `ready` yet.
83-
- All features in a goal will be built together on one worktree, then merged as a set.
84-
- After creating each feature issue, add it as a sub-issue of the goal using the REST API:
85-
```bash
86-
# Get the feature's numeric ID (not node_id)
87-
child_id=$(gh api repos/<repo>/issues/<feature_number> --jq '.id')
88-
# Add as sub-issue of the goal
89-
gh api -X POST repos/<repo>/issues/<goal_number>/sub_issues -F sub_issue_id=$child_id
90-
```
91-
This is the REST sub-issues API. The `sub_issue_id` field requires the issue's numeric `.id` from the REST API (not `.node_id`).
129+
Label: `feature`. Each feature is roughly one commit of work.
130+
131+
### Linking sub-issues to goals
132+
133+
After creating each feature, link it as a sub-issue of the goal:
92134

93-
### 4. Handle multi-goal ordering
135+
```bash
136+
child_id=$(gh api repos/<repo>/issues/<feature_number> --jq '.id')
137+
gh api -X POST repos/<repo>/issues/<goal_number>/sub_issues -F sub_issue_id=$child_id
138+
```
139+
140+
The `sub_issue_id` requires the numeric `.id` from the REST API, not `.node_id`.
94141

95-
If the work is too large for one goal, break it into multiple goals. Use the GraphQL `addBlockedBy` mutation to enforce ordering:
142+
### Ordering goals with blocked-by
96143

97144
```bash
98-
# Get node IDs for both goals
99145
goal1_node_id=$(gh api repos/<repo>/issues/<goal1_number> --jq '.node_id')
100146
goal2_node_id=$(gh api repos/<repo>/issues/<goal2_number> --jq '.node_id')
101147

102-
# Make goal 2 blocked by goal 1
103148
gh api graphql -f query='
104149
mutation($issueId: ID!, $blockingIssueId: ID!) {
105150
addBlockedBy(input: {issueId: $issueId, blockingIssueId: $blockingIssueId}) {
@@ -108,57 +153,16 @@ gh api graphql -f query='
108153
}' -f issueId="$goal2_node_id" -f blockingIssueId="$goal1_node_id"
109154
```
110155

111-
This uses `addBlockedBy` (not `addIssueDependency` which does not exist). The `issueId` is the issue that IS blocked, `blockingIssueId` is the issue that blocks it. Both must be GraphQL node IDs (`.node_id`), not numeric IDs.
156+
`issueId` = the blocked issue. `blockingIssueId` = the blocker. Both are `.node_id`.
112157

113-
Tell the user: "Goal 1 will fully complete before Goal 2 starts."
158+
### Ready gate
114159

115-
### 5. Confirm and label ready
116-
117-
After all issues are created, present the full plan:
118-
119-
```
120-
Here's what I've created:
160+
After all issues are created, show the user what you filed. Nothing builds
161+
until the user explicitly confirms. When they say "ready", "go", "ship it",
162+
or equivalent:
121163

122-
Goal: #<number> — <title>
123-
Feature: #<number> — <title>
124-
Feature: #<number> — <title>
125-
Feature: #<number> — <title>
126-
127-
Nothing will build until you confirm. Say "ready" to label everything
128-
and start execution, or tell me what to change.
129-
```
130-
131-
**Only label `ready` after explicit user confirmation.** The user must say "ready", "go", "ship it", "looks good, do it", or something unambiguously affirmative.
132-
133-
When confirmed:
134164
```bash
135165
gh issue edit <number> --repo <repo> --add-label "ready"
136166
```
137167

138-
Apply to the goal and all its features at once.
139-
140-
### 6. Check for duplicates first
141-
142-
Before creating any goal, check existing open goals:
143-
```bash
144-
gh issue list --repo <repo> --label goal --state open --json number,title --jq '.[] | "#\(.number) \(.title)"'
145-
```
146-
147-
## What NOT to do
148-
149-
- Do not label `ready` without explicit user confirmation.
150-
- Do not put implementation details in goal issues.
151-
- Do not create features without user agreement to decompose.
152-
- Do not guess the target repo — detect it from config or git remote.
153-
- Do not create circular blocked-by relationships.
154-
- Do not file duplicate goals.
155-
156-
## Factory-aware routing
157-
158-
When a factory config exists with `control_plane_repo` different from `target_repo`, and the user describes a factory problem (bad prompts, missing capabilities, broken gates):
159-
160-
- File on `control_plane_repo` instead of `target_repo`
161-
- Add label `factory:<factory_id>` alongside `goal`
162-
- The goal statement should describe the factory behavior change
163-
164-
This routing only activates when the factory config is present. In a plain repo, everything files on the current repo.
168+
Label the goal and all its features at once.

0 commit comments

Comments
 (0)