gsd-cc 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/install.js +91 -0
- package/hooks/gsd-boundary-guard.sh +62 -0
- package/hooks/gsd-context-monitor.sh +55 -0
- package/hooks/gsd-workflow-guard.sh +52 -0
- package/package.json +1 -1
- package/skills/gsd/discuss/SKILL.md +35 -22
- package/skills/gsd/stack/SKILL.md +18 -14
package/bin/install.js
CHANGED
|
@@ -155,9 +155,77 @@ function install(isGlobal) {
|
|
|
155
155
|
fs.chmodSync(autoLoop, 0o755);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
// 5. Install hooks
|
|
159
|
+
const hooksSrc = path.join(__dirname, '..', 'hooks');
|
|
160
|
+
const hooksDest = path.join(skillsBase, 'gsd-cc-shared', 'hooks');
|
|
161
|
+
if (fs.existsSync(hooksSrc)) {
|
|
162
|
+
copyDir(hooksSrc, hooksDest);
|
|
163
|
+
// Make hooks executable
|
|
164
|
+
const hookFiles = fs.readdirSync(hooksDest);
|
|
165
|
+
for (const f of hookFiles) {
|
|
166
|
+
fs.chmodSync(path.join(hooksDest, f), 0o755);
|
|
167
|
+
}
|
|
168
|
+
fileCount += hookFiles.length;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 6. Configure hooks in settings.json
|
|
172
|
+
installHooks(isGlobal, hooksDest);
|
|
173
|
+
|
|
158
174
|
console.log(` ${green}✓${reset} Installed ${fileCount} files to ${label}`);
|
|
159
175
|
}
|
|
160
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Install hooks into .claude/settings.json or .claude/settings.local.json
|
|
179
|
+
*/
|
|
180
|
+
function installHooks(isGlobal, hooksDir) {
|
|
181
|
+
const settingsPath = isGlobal
|
|
182
|
+
? path.join(os.homedir(), '.claude', 'settings.json')
|
|
183
|
+
: path.join(process.cwd(), '.claude', 'settings.local.json');
|
|
184
|
+
|
|
185
|
+
let settings = {};
|
|
186
|
+
if (fs.existsSync(settingsPath)) {
|
|
187
|
+
try {
|
|
188
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
189
|
+
} catch (e) {
|
|
190
|
+
settings = {};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!settings.hooks) settings.hooks = {};
|
|
195
|
+
|
|
196
|
+
const boundaryGuard = path.join(hooksDir, 'gsd-boundary-guard.sh');
|
|
197
|
+
const contextMonitor = path.join(hooksDir, 'gsd-context-monitor.sh');
|
|
198
|
+
const workflowGuard = path.join(hooksDir, 'gsd-workflow-guard.sh');
|
|
199
|
+
|
|
200
|
+
// PreToolUse: boundary guard on Edit/Write
|
|
201
|
+
if (!settings.hooks.PreToolUse) settings.hooks.PreToolUse = [];
|
|
202
|
+
// Remove existing GSD-CC hooks before adding (idempotent)
|
|
203
|
+
settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter(
|
|
204
|
+
h => !JSON.stringify(h).includes('gsd-boundary-guard')
|
|
205
|
+
);
|
|
206
|
+
settings.hooks.PreToolUse.push({
|
|
207
|
+
matcher: 'Edit|Write',
|
|
208
|
+
hooks: [{ type: 'command', command: boundaryGuard, timeout: 5000 }]
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// PostToolUse: context monitor + workflow guard
|
|
212
|
+
if (!settings.hooks.PostToolUse) settings.hooks.PostToolUse = [];
|
|
213
|
+
settings.hooks.PostToolUse = settings.hooks.PostToolUse.filter(
|
|
214
|
+
h => !JSON.stringify(h).includes('gsd-context-monitor') && !JSON.stringify(h).includes('gsd-workflow-guard')
|
|
215
|
+
);
|
|
216
|
+
settings.hooks.PostToolUse.push({
|
|
217
|
+
hooks: [{ type: 'command', command: contextMonitor, timeout: 5000 }]
|
|
218
|
+
});
|
|
219
|
+
settings.hooks.PostToolUse.push({
|
|
220
|
+
matcher: 'Edit|Write',
|
|
221
|
+
hooks: [{ type: 'command', command: workflowGuard, timeout: 5000 }]
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
|
|
225
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
226
|
+
console.log(` ${green}✓${reset} Hooks configured in ${settingsPath.replace(os.homedir(), '~').replace(process.cwd(), '.')}`);
|
|
227
|
+
}
|
|
228
|
+
|
|
161
229
|
/**
|
|
162
230
|
* Write language to CLAUDE.md
|
|
163
231
|
*/
|
|
@@ -254,9 +322,32 @@ function uninstall() {
|
|
|
254
322
|
}
|
|
255
323
|
}
|
|
256
324
|
|
|
325
|
+
// Clean up hooks from settings files
|
|
326
|
+
for (const isGlobal of [true, false]) {
|
|
327
|
+
const settingsPath = isGlobal
|
|
328
|
+
? path.join(os.homedir(), '.claude', 'settings.json')
|
|
329
|
+
: path.join(process.cwd(), '.claude', 'settings.local.json');
|
|
330
|
+
if (fs.existsSync(settingsPath)) {
|
|
331
|
+
try {
|
|
332
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
333
|
+
if (settings.hooks) {
|
|
334
|
+
for (const event of Object.keys(settings.hooks)) {
|
|
335
|
+
settings.hooks[event] = settings.hooks[event].filter(
|
|
336
|
+
h => !JSON.stringify(h).includes('gsd-')
|
|
337
|
+
);
|
|
338
|
+
if (settings.hooks[event].length === 0) delete settings.hooks[event];
|
|
339
|
+
}
|
|
340
|
+
if (Object.keys(settings.hooks).length === 0) delete settings.hooks;
|
|
341
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
342
|
+
}
|
|
343
|
+
} catch (e) { /* ignore parse errors */ }
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
257
347
|
if (!removed) {
|
|
258
348
|
console.log(` ${yellow}No GSD-CC installation found.${reset}`);
|
|
259
349
|
} else {
|
|
350
|
+
console.log(` ${green}✓${reset} Hooks removed from settings`);
|
|
260
351
|
console.log(`\n ${green}Done.${reset} GSD-CC has been removed.`);
|
|
261
352
|
}
|
|
262
353
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# GSD-CC Boundary Guard — PreToolUse hook
|
|
3
|
+
# Blocks Write/Edit operations on files listed in .gsd/STATE.md boundaries.
|
|
4
|
+
# This is a HARD enforcement — Claude cannot bypass this regardless of prompting.
|
|
5
|
+
|
|
6
|
+
INPUT=$(cat)
|
|
7
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
|
|
8
|
+
CWD=$(echo "$INPUT" | jq -r '.cwd')
|
|
9
|
+
|
|
10
|
+
# Only check Edit and Write operations
|
|
11
|
+
if [ "$TOOL_NAME" != "Edit" ] && [ "$TOOL_NAME" != "Write" ]; then
|
|
12
|
+
exit 0
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
# Get the file being edited/written
|
|
16
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
|
|
17
|
+
if [ -z "$FILE_PATH" ]; then
|
|
18
|
+
exit 0
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# Check if STATE.md exists and has boundaries
|
|
22
|
+
STATE_FILE="$CWD/.gsd/STATE.md"
|
|
23
|
+
if [ ! -f "$STATE_FILE" ]; then
|
|
24
|
+
exit 0
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Extract boundary files from STATE.md
|
|
28
|
+
# Boundaries section contains lines like: - path/to/file (reason)
|
|
29
|
+
BOUNDARIES=$(sed -n '/^## Boundaries Active/,/^##/p' "$STATE_FILE" | grep '^ *- ' | sed 's/^ *- //' | sed 's/ (.*//')
|
|
30
|
+
|
|
31
|
+
if [ -z "$BOUNDARIES" ]; then
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Normalize the target file path (make relative to CWD if absolute)
|
|
36
|
+
RELATIVE_PATH="$FILE_PATH"
|
|
37
|
+
if [[ "$FILE_PATH" == "$CWD"* ]]; then
|
|
38
|
+
RELATIVE_PATH="${FILE_PATH#$CWD/}"
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Check each boundary file
|
|
42
|
+
while IFS= read -r BOUNDARY_FILE; do
|
|
43
|
+
BOUNDARY_FILE=$(echo "$BOUNDARY_FILE" | xargs) # trim whitespace
|
|
44
|
+
if [ -z "$BOUNDARY_FILE" ]; then
|
|
45
|
+
continue
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Check exact match or path containment
|
|
49
|
+
if [ "$RELATIVE_PATH" = "$BOUNDARY_FILE" ] || [ "$FILE_PATH" = "$BOUNDARY_FILE" ]; then
|
|
50
|
+
jq -n --arg file "$BOUNDARY_FILE" '{
|
|
51
|
+
"hookSpecificOutput": {
|
|
52
|
+
"hookEventName": "PreToolUse",
|
|
53
|
+
"permissionDecision": "deny",
|
|
54
|
+
"permissionDecisionReason": ("BOUNDARY VIOLATION: " + $file + " is in the DO NOT CHANGE list for this task. This file is protected. If you need to modify it, stop and discuss with the user first.")
|
|
55
|
+
}
|
|
56
|
+
}'
|
|
57
|
+
exit 0
|
|
58
|
+
fi
|
|
59
|
+
done <<< "$BOUNDARIES"
|
|
60
|
+
|
|
61
|
+
# File not in boundaries — allow
|
|
62
|
+
exit 0
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# GSD-CC Context Monitor — PostToolUse hook
|
|
3
|
+
# Injects warnings when context usage is getting high.
|
|
4
|
+
# Uses the transcript file size as a proxy for context consumption.
|
|
5
|
+
|
|
6
|
+
INPUT=$(cat)
|
|
7
|
+
CWD=$(echo "$INPUT" | jq -r '.cwd')
|
|
8
|
+
TRANSCRIPT=$(echo "$INPUT" | jq -r '.transcript_path // empty')
|
|
9
|
+
|
|
10
|
+
# Skip if no transcript path
|
|
11
|
+
if [ -z "$TRANSCRIPT" ] || [ ! -f "$TRANSCRIPT" ]; then
|
|
12
|
+
exit 0
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
# Check if we're in a GSD-CC project
|
|
16
|
+
if [ ! -d "$CWD/.gsd" ]; then
|
|
17
|
+
exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# Use transcript line count as context proxy
|
|
21
|
+
# Typical context window: ~200K tokens ≈ ~2000 transcript lines for a heavy session
|
|
22
|
+
LINE_COUNT=$(wc -l < "$TRANSCRIPT" | xargs)
|
|
23
|
+
|
|
24
|
+
# Debounce: only warn every 20 tool calls
|
|
25
|
+
DEBOUNCE_FILE="/tmp/gsd-cc-ctx-monitor-$$"
|
|
26
|
+
if [ -f "$DEBOUNCE_FILE" ]; then
|
|
27
|
+
LAST_WARN=$(cat "$DEBOUNCE_FILE")
|
|
28
|
+
DIFF=$((LINE_COUNT - LAST_WARN))
|
|
29
|
+
if [ "$DIFF" -lt 50 ]; then
|
|
30
|
+
exit 0
|
|
31
|
+
fi
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# Warning thresholds (based on transcript lines)
|
|
35
|
+
if [ "$LINE_COUNT" -gt 1500 ]; then
|
|
36
|
+
echo "$LINE_COUNT" > "$DEBOUNCE_FILE"
|
|
37
|
+
jq -n '{
|
|
38
|
+
"hookSpecificOutput": {
|
|
39
|
+
"hookEventName": "PostToolUse",
|
|
40
|
+
"additionalContext": "⚠️ CRITICAL: Context window is very full. You MUST wrap up the current task immediately, write the summary, and instruct the user to start a fresh session. Do NOT start new work."
|
|
41
|
+
}
|
|
42
|
+
}'
|
|
43
|
+
exit 0
|
|
44
|
+
elif [ "$LINE_COUNT" -gt 1000 ]; then
|
|
45
|
+
echo "$LINE_COUNT" > "$DEBOUNCE_FILE"
|
|
46
|
+
jq -n '{
|
|
47
|
+
"hookSpecificOutput": {
|
|
48
|
+
"hookEventName": "PostToolUse",
|
|
49
|
+
"additionalContext": "⚠️ WARNING: Context window is filling up. Finish the current task soon and prepare to hand off to a fresh session."
|
|
50
|
+
}
|
|
51
|
+
}'
|
|
52
|
+
exit 0
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
exit 0
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# GSD-CC Workflow Guard — PostToolUse hook
|
|
3
|
+
# Nudges Claude back into the GSD-CC flow when it drifts.
|
|
4
|
+
# Advisory only — does not block operations.
|
|
5
|
+
|
|
6
|
+
INPUT=$(cat)
|
|
7
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
|
|
8
|
+
CWD=$(echo "$INPUT" | jq -r '.cwd')
|
|
9
|
+
|
|
10
|
+
# Only check Edit and Write on source files (not .gsd/ files)
|
|
11
|
+
if [ "$TOOL_NAME" != "Edit" ] && [ "$TOOL_NAME" != "Write" ]; then
|
|
12
|
+
exit 0
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
# Skip if not a GSD-CC project
|
|
16
|
+
STATE_FILE="$CWD/.gsd/STATE.md"
|
|
17
|
+
if [ ! -f "$STATE_FILE" ]; then
|
|
18
|
+
exit 0
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
|
|
22
|
+
if [ -z "$FILE_PATH" ]; then
|
|
23
|
+
exit 0
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# Allow writes to .gsd/ directory (that's the workflow itself)
|
|
27
|
+
if [[ "$FILE_PATH" == *".gsd/"* ]] || [[ "$FILE_PATH" == *".claude/"* ]]; then
|
|
28
|
+
exit 0
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Check if we're in an active execution phase
|
|
32
|
+
PHASE=$(grep '^phase:' "$STATE_FILE" | head -1 | sed 's/phase: *//')
|
|
33
|
+
|
|
34
|
+
case "$PHASE" in
|
|
35
|
+
"seed"|"seed-complete"|"stack-complete"|"roadmap-complete"|"plan-complete"|"discuss-complete")
|
|
36
|
+
# Not in execution — source file edits are unexpected
|
|
37
|
+
jq -n --arg phase "$PHASE" --arg file "$FILE_PATH" '{
|
|
38
|
+
"hookSpecificOutput": {
|
|
39
|
+
"hookEventName": "PostToolUse",
|
|
40
|
+
"additionalContext": ("Note: You edited " + $file + " but the current GSD-CC phase is \"" + $phase + "\" which is a planning phase, not execution. Source file changes should happen during the apply phase. If this was intentional, carry on. If not, consider running /gsd-cc to check the current state.")
|
|
41
|
+
}
|
|
42
|
+
}'
|
|
43
|
+
exit 0
|
|
44
|
+
;;
|
|
45
|
+
"applying")
|
|
46
|
+
# In execution — this is expected
|
|
47
|
+
exit 0
|
|
48
|
+
;;
|
|
49
|
+
*)
|
|
50
|
+
exit 0
|
|
51
|
+
;;
|
|
52
|
+
esac
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gsd-cc",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Get Shit Done on Claude Code — structured AI development with your Max plan",
|
|
5
5
|
"author": "Philipp Briese (https://github.com/0ui-labs)",
|
|
6
6
|
"homepage": "https://github.com/0ui-labs/GSD-CC#readme",
|
|
@@ -156,25 +156,31 @@ When running in full-auto mode (`auto_mode_scope: milestone`), Discuss is NOT sk
|
|
|
156
156
|
|
|
157
157
|
### How it works
|
|
158
158
|
|
|
159
|
-
1. Read `.gsd/PROFILE.md` — this is the user's decision-making profile
|
|
160
|
-
2. For each gray area, simulate a discussion:
|
|
161
|
-
- **
|
|
162
|
-
- **
|
|
163
|
-
|
|
164
|
-
|
|
159
|
+
1. Read `.gsd/PROFILE.md` — this is the user's decision-making profile (if it exists)
|
|
160
|
+
2. For each gray area, simulate a real discussion between two roles:
|
|
161
|
+
- **Planner:** Analyzes the technical options. Brings expertise about what works best for THIS project. Considers tradeoffs, risks, maintainability, project requirements.
|
|
162
|
+
- **Stakeholder:** Represents the user's perspective. Influenced by PROFILE.md but not controlled by it. The profile is a **nudge, not a mandate** — it shapes preferences but doesn't override what's technically best for this project.
|
|
163
|
+
3. The discussion should feel like a real debate, not a rubber stamp:
|
|
164
|
+
- Planner proposes with reasoning
|
|
165
|
+
- Stakeholder reacts based on profile + common sense
|
|
166
|
+
- If they disagree, they work it out with arguments
|
|
167
|
+
- The final decision considers BOTH technical merit AND user preferences
|
|
168
|
+
4. Write the results to `.gsd/S{nn}-DISCUSS-AUTO.md` with full transparency:
|
|
165
169
|
|
|
166
170
|
```markdown
|
|
167
|
-
# S{nn} Auto-Discuss
|
|
171
|
+
# S{nn} Auto-Discuss
|
|
168
172
|
|
|
169
|
-
> These decisions were made by auto-mode
|
|
170
|
-
>
|
|
171
|
-
>
|
|
173
|
+
> These decisions were made by auto-mode.
|
|
174
|
+
> The user's profile influenced but did not dictate decisions.
|
|
175
|
+
> Review after UNIFY. Update your profile with /gsd-cc-profile if needed.
|
|
172
176
|
|
|
173
177
|
## Decision 1: {topic}
|
|
174
178
|
**Question:** {what was ambiguous}
|
|
175
|
-
**
|
|
176
|
-
**
|
|
177
|
-
**
|
|
179
|
+
**Planner says:** {technical analysis — options, tradeoffs, recommendation}
|
|
180
|
+
**Stakeholder says:** {reaction based on profile + common sense}
|
|
181
|
+
**Profile influence:** {how the profile shaped this — or "N/A" if profile didn't cover this}
|
|
182
|
+
**Final decision:** {what was decided and why}
|
|
183
|
+
**Confidence:** {high|medium|low}
|
|
178
184
|
|
|
179
185
|
## Decision 2: {topic}
|
|
180
186
|
...
|
|
@@ -182,17 +188,24 @@ When running in full-auto mode (`auto_mode_scope: milestone`), Discuss is NOT sk
|
|
|
182
188
|
|
|
183
189
|
### Confidence levels
|
|
184
190
|
|
|
185
|
-
- **High:**
|
|
186
|
-
- **Medium:**
|
|
187
|
-
- **Low:**
|
|
191
|
+
- **High:** Clear technical winner that also aligns with the profile
|
|
192
|
+
- **Medium:** Multiple valid options — profile tipped the balance, or technical choice overrode a mild preference with good reason
|
|
193
|
+
- **Low:** Unclear technically AND the profile doesn't help — the decision is a best guess. Mark for user review.
|
|
188
194
|
|
|
189
|
-
###
|
|
195
|
+
### How the Profile Influences (NOT Controls)
|
|
190
196
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
- **
|
|
194
|
-
- **
|
|
195
|
-
- **
|
|
197
|
+
The profile is one input among several. The weight depends on the type of decision:
|
|
198
|
+
|
|
199
|
+
- **Taste decisions** (UI style, naming conventions, code style) → profile weighs heavily. There's no "right answer", so the user's preference matters most.
|
|
200
|
+
- **Technical decisions** (database choice, API design, auth strategy) → profile is a tiebreaker. If two options are technically equal, pick the one the user would prefer. But don't pick a bad option just because the profile likes it.
|
|
201
|
+
- **Red lines** → always respected. If the profile says "NEVER use X", don't use X. Period. But explain the cost if it matters.
|
|
202
|
+
|
|
203
|
+
### Rules for Auto-Discuss
|
|
204
|
+
|
|
205
|
+
- **The Planner thinks independently.** Don't just ask "what would the user want?" — first figure out what's technically best, THEN check if the profile agrees.
|
|
206
|
+
- **Disagreements are good.** If the planner thinks X is better but the profile nudges toward Y, document the tension. Don't hide it.
|
|
207
|
+
- **Use the user's language** when representing their perspective. If they said "I hate ORMs", the stakeholder says "no ORM" — not "consider avoiding object-relational mapping."
|
|
208
|
+
- **Be honest about uncertainty.** If neither technical analysis nor the profile gives a clear answer, say so.
|
|
196
209
|
|
|
197
210
|
### If no PROFILE.md exists
|
|
198
211
|
|
|
@@ -111,27 +111,31 @@ If their reasoning is sound, support it. If it's risky, explain the risk honestl
|
|
|
111
111
|
|
|
112
112
|
### For auto-discuss (synthetic stakeholder):
|
|
113
113
|
|
|
114
|
-
Read PROFILE.md
|
|
114
|
+
Read PROFILE.md (if it exists). For each stack decision, run a real discussion:
|
|
115
115
|
|
|
116
|
-
```
|
|
117
|
-
## Stack Discussion (
|
|
116
|
+
```markdown
|
|
117
|
+
## Stack Discussion (Auto)
|
|
118
118
|
|
|
119
119
|
### Language / Runtime
|
|
120
|
-
Planner
|
|
121
|
-
because {reason}.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
120
|
+
**Planner:** "For this project we need {requirement}. The best
|
|
121
|
+
options are {A} and {B}. {A} because {reason}. {B} because {reason}.
|
|
122
|
+
I'd lean toward {A}."
|
|
123
|
+
**Stakeholder:** "{Reaction — agrees, disagrees, or adds context.
|
|
124
|
+
Profile is a nudge, not a script. E.g. 'The profile says TypeScript
|
|
125
|
+
for frontend work, and that aligns here. But even without the profile
|
|
126
|
+
TypeScript would be the right call because of {project-specific reason}.'}"
|
|
127
|
+
**Decision:** {final choice}
|
|
128
|
+
**Reasoning:** {why this is right for THIS project — not just because the profile says so}
|
|
129
|
+
**Confidence:** {high|medium|low}
|
|
128
130
|
|
|
129
131
|
### Framework
|
|
130
|
-
Planner
|
|
131
|
-
Stakeholder
|
|
132
|
+
**Planner:** ...
|
|
133
|
+
**Stakeholder:** ...
|
|
132
134
|
```
|
|
133
135
|
|
|
134
|
-
**
|
|
136
|
+
**The profile influences, it doesn't dictate.** The planner should first figure out what's technically best for this specific project, THEN check if the profile agrees. If the profile says "always Next.js" but this project is a CLI tool, don't use Next.js.
|
|
137
|
+
|
|
138
|
+
**Every decision must be discussed.** Even obvious ones. The discussion creates a record of WHY each choice was made.
|
|
135
139
|
|
|
136
140
|
## Step 4: Research When Needed
|
|
137
141
|
|