gsd-pi 0.3.0 → 0.3.3
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/README.md +3 -1
- package/dist/cli.js +112 -5
- package/dist/loader.js +0 -0
- package/dist/resource-loader.d.ts +3 -3
- package/dist/resource-loader.js +10 -4
- package/dist/tool-bootstrap.d.ts +4 -0
- package/dist/tool-bootstrap.js +74 -0
- package/dist/wizard.js +15 -5
- package/package.json +6 -2
- package/patches/@mariozechner+pi-coding-agent+0.57.1.patch +48 -0
- package/patches/@mariozechner+pi-tui+0.57.1.patch +47 -0
- package/scripts/postinstall.js +8 -0
- package/src/resources/extensions/bg-shell/index.ts +57 -8
- package/src/resources/extensions/browser-tools/index.ts +80 -7
- package/src/resources/extensions/github/gh-api.ts +46 -30
- package/src/resources/extensions/gsd/auto.ts +188 -10
- package/src/resources/extensions/gsd/commands.ts +13 -6
- package/src/resources/extensions/gsd/doctor.ts +7 -0
- package/src/resources/extensions/gsd/guided-flow.ts +9 -6
- package/src/resources/extensions/gsd/index.ts +32 -2
- package/src/resources/extensions/gsd/prompts/discuss.md +73 -27
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/prompts/worktree-merge.md +51 -17
- package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +38 -0
- package/src/resources/extensions/gsd/worktree-command.ts +219 -49
- package/src/resources/extensions/gsd/worktree-manager.ts +106 -16
- package/src/resources/extensions/mcporter/index.ts +410 -0
- package/src/resources/extensions/slash-commands/clear.ts +10 -0
- package/src/resources/extensions/slash-commands/index.ts +2 -2
- package/src/resources/extensions/voice/index.ts +176 -0
- package/src/resources/extensions/voice/speech-recognizer +0 -0
- package/src/resources/extensions/voice/speech-recognizer.swift +76 -0
- package/dist/modes/interactive/theme/dark.json +0 -85
- package/dist/modes/interactive/theme/light.json +0 -84
- package/dist/modes/interactive/theme/theme-schema.json +0 -335
- package/dist/modes/interactive/theme/theme.d.ts +0 -78
- package/dist/modes/interactive/theme/theme.d.ts.map +0 -1
- package/dist/modes/interactive/theme/theme.js +0 -949
- package/dist/modes/interactive/theme/theme.js.map +0 -1
- package/src/resources/extensions/slash-commands/gsd-run.ts +0 -34
|
@@ -31,13 +31,14 @@ let pendingAutoStart: {
|
|
|
31
31
|
pi: ExtensionAPI;
|
|
32
32
|
basePath: string;
|
|
33
33
|
milestoneId: string; // the milestone being discussed
|
|
34
|
+
step?: boolean; // preserve step mode through discuss → auto transition
|
|
34
35
|
} | null = null;
|
|
35
36
|
|
|
36
37
|
/** Called from agent_end to check if auto-mode should start after discuss */
|
|
37
38
|
export function checkAutoStartAfterDiscuss(): boolean {
|
|
38
39
|
if (!pendingAutoStart) return false;
|
|
39
40
|
|
|
40
|
-
const { ctx, pi, basePath, milestoneId } = pendingAutoStart;
|
|
41
|
+
const { ctx, pi, basePath, milestoneId, step } = pendingAutoStart;
|
|
41
42
|
|
|
42
43
|
// Don't fire until the discuss phase has actually produced a context file
|
|
43
44
|
// for the milestone being discussed. agent_end fires after every LLM turn,
|
|
@@ -47,7 +48,7 @@ export function checkAutoStartAfterDiscuss(): boolean {
|
|
|
47
48
|
if (!contextFile) return false; // no context yet — keep waiting
|
|
48
49
|
|
|
49
50
|
pendingAutoStart = null;
|
|
50
|
-
startAuto(ctx, pi, basePath, false).catch(() => {});
|
|
51
|
+
startAuto(ctx, pi, basePath, false, { step }).catch(() => {});
|
|
51
52
|
return true;
|
|
52
53
|
}
|
|
53
54
|
|
|
@@ -435,7 +436,9 @@ export async function showSmartEntry(
|
|
|
435
436
|
ctx: ExtensionCommandContext,
|
|
436
437
|
pi: ExtensionAPI,
|
|
437
438
|
basePath: string,
|
|
439
|
+
options?: { step?: boolean },
|
|
438
440
|
): Promise<void> {
|
|
441
|
+
const stepMode = options?.step;
|
|
439
442
|
|
|
440
443
|
// ── Ensure git repo exists — GSD needs it for branch-per-slice ──────
|
|
441
444
|
try {
|
|
@@ -501,14 +504,14 @@ export async function showSmartEntry(
|
|
|
501
504
|
|
|
502
505
|
if (isFirst) {
|
|
503
506
|
// First ever — skip wizard, just ask directly
|
|
504
|
-
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId };
|
|
507
|
+
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId, step: stepMode };
|
|
505
508
|
dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
506
509
|
`New project, milestone ${nextId}. Do NOT read or explore .gsd/ — it's empty scaffolding.`,
|
|
507
510
|
basePath
|
|
508
511
|
));
|
|
509
512
|
} else {
|
|
510
513
|
const choice = await showNextAction(ctx as any, {
|
|
511
|
-
title: "GSD — Get
|
|
514
|
+
title: "GSD — Get Shit Done",
|
|
512
515
|
summary: ["No active milestone."],
|
|
513
516
|
actions: [
|
|
514
517
|
{
|
|
@@ -522,7 +525,7 @@ export async function showSmartEntry(
|
|
|
522
525
|
});
|
|
523
526
|
|
|
524
527
|
if (choice === "new_milestone") {
|
|
525
|
-
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId };
|
|
528
|
+
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId, step: stepMode };
|
|
526
529
|
dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
527
530
|
`New milestone ${nextId}.`,
|
|
528
531
|
basePath
|
|
@@ -560,7 +563,7 @@ export async function showSmartEntry(
|
|
|
560
563
|
const milestoneIds = findMilestoneIds(basePath);
|
|
561
564
|
const nextId = `M${String(milestoneIds.length + 1).padStart(3, "0")}`;
|
|
562
565
|
|
|
563
|
-
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId };
|
|
566
|
+
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId, step: stepMode };
|
|
564
567
|
dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
565
568
|
`New milestone ${nextId}.`,
|
|
566
569
|
basePath
|
|
@@ -63,13 +63,43 @@ export default function (pi: ExtensionAPI) {
|
|
|
63
63
|
registerGSDCommand(pi);
|
|
64
64
|
registerWorktreeCommand(pi);
|
|
65
65
|
|
|
66
|
-
// ──
|
|
66
|
+
// ── /exit — kill the process immediately ──────────────────────────────
|
|
67
|
+
pi.registerCommand("exit", {
|
|
68
|
+
description: "Exit GSD immediately",
|
|
69
|
+
handler: async (_ctx) => {
|
|
70
|
+
process.exit(0);
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// ── Dynamic-cwd bash tool with default timeout ────────────────────────
|
|
67
75
|
// The built-in bash tool captures cwd at startup. This replacement uses
|
|
68
76
|
// a spawnHook to read process.cwd() dynamically so that process.chdir()
|
|
69
77
|
// (used by /worktree switch) propagates to shell commands.
|
|
70
|
-
|
|
78
|
+
//
|
|
79
|
+
// The upstream SDK's bash tool has no default timeout — if the LLM omits
|
|
80
|
+
// the timeout parameter, commands run indefinitely, causing hangs on
|
|
81
|
+
// Windows where process killing is unreliable (see #40). We wrap execute
|
|
82
|
+
// to inject a 120-second default when no timeout is provided.
|
|
83
|
+
const DEFAULT_BASH_TIMEOUT_SECS = 120;
|
|
84
|
+
const baseBash = createBashTool(process.cwd(), {
|
|
71
85
|
spawnHook: (ctx) => ({ ...ctx, cwd: process.cwd() }),
|
|
72
86
|
});
|
|
87
|
+
const dynamicBash = {
|
|
88
|
+
...baseBash,
|
|
89
|
+
execute: async (
|
|
90
|
+
toolCallId: string,
|
|
91
|
+
params: { command: string; timeout?: number },
|
|
92
|
+
signal?: AbortSignal,
|
|
93
|
+
onUpdate?: any,
|
|
94
|
+
ctx?: any,
|
|
95
|
+
) => {
|
|
96
|
+
const paramsWithTimeout = {
|
|
97
|
+
...params,
|
|
98
|
+
timeout: params.timeout ?? DEFAULT_BASH_TIMEOUT_SECS,
|
|
99
|
+
};
|
|
100
|
+
return baseBash.execute(toolCallId, paramsWithTimeout, signal, onUpdate, ctx);
|
|
101
|
+
},
|
|
102
|
+
};
|
|
73
103
|
pi.registerTool(dynamicBash as any);
|
|
74
104
|
|
|
75
105
|
// ── session_start: render branded GSD header ───────────────────────────
|
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
{{preamble}}
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Ask: "What's the vision?" once, and then use whatever the user replies with as the vision input to continue.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Special handling: if the user message is not a project description (for example, they ask about status, branch state, or other clarifications), treat it as the vision input and proceed with discussion logic instead of repeating "What's the vision?".
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Reflection Step
|
|
8
|
+
|
|
9
|
+
After the user describes their idea, **do not ask questions yet**. First, prove you understood by reflecting back:
|
|
10
|
+
|
|
11
|
+
1. Summarize what you understood in your own words — concretely, not abstractly.
|
|
12
|
+
2. Include a complexity/scale read: "This sounds like [task/project/product] scale — roughly N milestone(s)."
|
|
13
|
+
3. Include scope honesty — a bullet list of the major capabilities you're hearing: "Here's what I'm hearing: [bullet list of major capabilities]."
|
|
14
|
+
4. Ask: "Did I get that right, or did I miss something?" — plain text, not `ask_user_questions`. Let them correct freely.
|
|
15
|
+
|
|
16
|
+
This prevents runaway questioning by forcing comprehension proof before anything else. Do not skip this step. Do not combine it with the first question round.
|
|
8
17
|
|
|
9
18
|
## Vision Mapping
|
|
10
19
|
|
|
11
|
-
|
|
20
|
+
After reflection is confirmed, classify the scale:
|
|
12
21
|
|
|
13
22
|
- **Task** — a focused piece of work (single milestone, few slices)
|
|
14
23
|
- **Project** — a coherent product with multiple major capabilities (multi-milestone likely)
|
|
@@ -19,40 +28,69 @@ Before diving into detailed Q&A, read the user's description and classify its sc
|
|
|
19
28
|
2. Present this to the user for confirmation or adjustment
|
|
20
29
|
3. Only then begin the deep Q&A — and scope the Q&A to the full vision, not just M001
|
|
21
30
|
|
|
22
|
-
**For Task scale:** Proceed directly to
|
|
31
|
+
**For Task scale:** Proceed directly to questioning.
|
|
23
32
|
|
|
24
33
|
**Anti-reduction rule:** If the user describes a big vision, plan the big vision. Do not ask "what's the minimum viable version?" or try to reduce scope unless the user explicitly asks for an MVP or minimal version. When something is complex or risky, phase it into a later milestone — do not cut it. The user's ambition is the target, and your job is to sequence it intelligently, not shrink it.
|
|
25
34
|
|
|
26
|
-
|
|
35
|
+
## Mandatory Investigation Before First Question Round
|
|
36
|
+
|
|
37
|
+
Before asking your first question, do a mandatory investigation pass. This is not optional.
|
|
38
|
+
|
|
39
|
+
1. **Scout the codebase** — `ls`, `find`, `rg`, or `scout` for broad unfamiliar areas. Understand what already exists, what patterns are established, what constraints current code imposes.
|
|
40
|
+
2. **Check library docs** — `resolve_library` / `get_library_docs` for any tech the user mentioned. Get current facts about capabilities, constraints, API shapes, version-specific behavior.
|
|
41
|
+
3. **Web search** — `search-the-web` if the domain is unfamiliar, if you need current best practices, or if the user referenced external services/APIs you need facts about. Use `fetch_page` for full content when snippets aren't enough.
|
|
42
|
+
|
|
43
|
+
This happens ONCE, before the first round. The goal: your first questions should reflect what's actually true, not what you assume.
|
|
44
|
+
|
|
45
|
+
For subsequent rounds, continue investigating between rounds — check docs, search, or scout as needed to make each round's questions smarter. But the first-round investigation is mandatory and explicit.
|
|
46
|
+
|
|
47
|
+
## Questioning Philosophy
|
|
48
|
+
|
|
49
|
+
You are a thinking partner, not an interviewer.
|
|
27
50
|
|
|
28
|
-
**
|
|
51
|
+
**Start open, follow energy.** Let the user's enthusiasm guide where you dig deeper. If they light up about a particular aspect, explore it. If they're vague about something, that's where you probe.
|
|
29
52
|
|
|
30
|
-
**
|
|
53
|
+
**Challenge vagueness, make abstract concrete.** When the user says something abstract ("it should be smart" / "it needs to handle edge cases" / "good UX"), push for specifics. What does "smart" mean in practice? Which edge cases? What does good UX look like for this specific interaction?
|
|
31
54
|
|
|
32
|
-
|
|
33
|
-
- Do web searches (`search-the-web`) to verify the landscape — what solutions exist, what's changed recently, what's the current best practice. Use `freshness` for recency-sensitive queries, `domain` to target specific sites. Use `fetch_page` to read the full content of promising URLs when snippets aren't enough.
|
|
34
|
-
- Scout the codebase (`ls`, `find`, `rg`, or `scout` for broad unfamiliar areas) to understand what already exists, what patterns are established, what constraints current code imposes
|
|
55
|
+
**Questions must be about the experience, not the implementation.** Never ask "what auth provider?" — ask "when someone logs in, what should that feel like?" Never ask "what database?" — ask "when they come back tomorrow, what should they see?" Implementation is your job. Understanding what they want to experience is the discussion's job.
|
|
35
56
|
|
|
36
|
-
|
|
57
|
+
**Freeform rule:** When the user selects "Other" or clearly wants to explain something freely, stop using `ask_user_questions` and switch to plain text follow-ups. Let them talk. Resume structured questions when appropriate.
|
|
37
58
|
|
|
38
|
-
**
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
59
|
+
**Anti-patterns — never do these:**
|
|
60
|
+
- **Checklist walking** — going through a predetermined list of topics regardless of what the user said
|
|
61
|
+
- **Canned questions** — asking generic questions that could apply to any project
|
|
62
|
+
- **Corporate speak** — "What are your key success metrics?" / "Who are the stakeholders?"
|
|
63
|
+
- **Interrogation** — rapid-fire questions without acknowledging or building on answers
|
|
64
|
+
- **Rushing** — trying to get through questions quickly to move to planning
|
|
65
|
+
- **Shallow acceptance** — accepting vague answers without probing ("Sounds good!" then moving on)
|
|
66
|
+
- **Premature constraints** — asking about tech stack, deployment targets, or architecture before understanding what they're building
|
|
67
|
+
- **Asking about technical skill** — never ask "how technical are you?" or "are you familiar with X?" — adapt based on how they communicate
|
|
44
68
|
|
|
45
|
-
|
|
69
|
+
## Depth Enforcement
|
|
46
70
|
|
|
47
|
-
|
|
71
|
+
Do NOT offer to proceed until ALL of the following are satisfied. Track these internally as a background checklist:
|
|
48
72
|
|
|
49
|
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
73
|
+
- [ ] **What they're building** — concrete enough that you could explain it to a stranger
|
|
74
|
+
- [ ] **Why it needs to exist** — the problem it solves or the desire it fulfills
|
|
75
|
+
- [ ] **Who it's for** — even if just themselves
|
|
76
|
+
- [ ] **What "done" looks like** — observable outcomes, not abstract goals
|
|
77
|
+
- [ ] **The biggest technical unknowns / risks** — what could fail, what hasn't been proven
|
|
78
|
+
- [ ] **What external systems/services this touches** — APIs, databases, third-party services, hardware
|
|
52
79
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
80
|
+
**Minimum round counts before the wrap-up gate is allowed:**
|
|
81
|
+
- **Task scale:** at least 2 full rounds (6+ questions asked and answered)
|
|
82
|
+
- **Project/Product scale:** at least 4 full rounds (12+ questions asked and answered)
|
|
83
|
+
|
|
84
|
+
Do not count the reflection step as a question round. Rounds start after reflection is confirmed.
|
|
85
|
+
|
|
86
|
+
## Wrap-up Gate
|
|
87
|
+
|
|
88
|
+
Only after the depth checklist is fully satisfied AND minimum rounds are hit, offer to proceed.
|
|
89
|
+
|
|
90
|
+
The wrap-up gate must include a scope reflection:
|
|
91
|
+
"Here's what I'm planning to build: [list of capabilities with rough complexity]. Does this match your vision, or did I miss something?"
|
|
92
|
+
|
|
93
|
+
Then offer options: "Ready to confirm requirements and milestone plan (Recommended)", "I have more to discuss"
|
|
56
94
|
|
|
57
95
|
If the user wants to keep going, keep asking. If they're ready, proceed.
|
|
58
96
|
|
|
@@ -105,7 +143,9 @@ Rules:
|
|
|
105
143
|
|
|
106
144
|
For multi-milestone projects, requirements should span the full vision. Requirements owned by later milestones get provisional ownership. The full requirement set captures the user's complete vision — milestones are the sequencing strategy, not the scope boundary.
|
|
107
145
|
|
|
108
|
-
If the project is new or has no `REQUIREMENTS.md`, confirm candidate requirements with the user before writing the roadmap.
|
|
146
|
+
If the project is new or has no `REQUIREMENTS.md`, confirm candidate requirements with the user before writing the roadmap.
|
|
147
|
+
|
|
148
|
+
**Print the requirements in chat before asking for confirmation.** Do not say "here are the requirements" and then only write them to a file. The user must see them in the terminal. Print a markdown table with columns: ID, Title, Status, Owner, Source. Group by status (Active, Deferred, Out of Scope). After the table, ask: "Confirm, adjust, or add?"
|
|
109
149
|
|
|
110
150
|
## Scope Assessment
|
|
111
151
|
|
|
@@ -115,6 +155,12 @@ If Vision Mapping classified the work as Task but discussion revealed Project-sc
|
|
|
115
155
|
|
|
116
156
|
## Output Phase
|
|
117
157
|
|
|
158
|
+
### Roadmap Preview
|
|
159
|
+
|
|
160
|
+
Before writing any files, **print the planned roadmap in chat** so the user can see and approve it. Print a markdown table with columns: Slice, Title, Risk, Depends, Demo. One row per slice. Below the table, print the milestone definition of done as a bullet list.
|
|
161
|
+
|
|
162
|
+
Ask: "Ready to write the plan, or want to adjust?" Only proceed to writing files after the user confirms.
|
|
163
|
+
|
|
118
164
|
### Naming Convention
|
|
119
165
|
|
|
120
166
|
Directories use bare IDs. Files use ID-SUFFIX format. Titles live inside file content, not in names.
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
You are merging
|
|
1
|
+
You are merging changes from worktree **{{worktreeName}}** (branch `{{worktreeBranch}}`) into target branch `{{mainBranch}}`.
|
|
2
|
+
|
|
3
|
+
## Working Directory
|
|
4
|
+
|
|
5
|
+
Your current working directory has been set to the **main project tree** at `{{mainTreePath}}`. You are on the `{{mainBranch}}` branch. All git and file commands run from here.
|
|
6
|
+
|
|
7
|
+
- **Main tree (CWD):** `{{mainTreePath}}` — this is where you run `git merge`, read main-branch files, and commit
|
|
8
|
+
- **Worktree directory:** `{{worktreePath}}` — the worktree's working copy; read files here to inspect worktree versions before merging
|
|
9
|
+
- **Worktree branch:** `{{worktreeBranch}}`
|
|
2
10
|
|
|
3
11
|
## Context
|
|
4
12
|
|
|
5
|
-
The worktree was created as a parallel workspace. It may contain new milestones, updated roadmaps, new plans, research, decisions, or other
|
|
13
|
+
The worktree was created as a parallel workspace. It may contain code changes, new milestones, updated roadmaps, new plans, research, decisions, or other artifacts that need to be merged into the target branch.
|
|
6
14
|
|
|
7
15
|
### Commit History (worktree)
|
|
8
16
|
|
|
@@ -10,7 +18,7 @@ The worktree was created as a parallel workspace. It may contain new milestones,
|
|
|
10
18
|
{{commitLog}}
|
|
11
19
|
```
|
|
12
20
|
|
|
13
|
-
###
|
|
21
|
+
### Changed Files
|
|
14
22
|
|
|
15
23
|
**Added files:**
|
|
16
24
|
{{addedFiles}}
|
|
@@ -21,10 +29,16 @@ The worktree was created as a parallel workspace. It may contain new milestones,
|
|
|
21
29
|
**Removed files:**
|
|
22
30
|
{{removedFiles}}
|
|
23
31
|
|
|
24
|
-
###
|
|
32
|
+
### Code Diff
|
|
33
|
+
|
|
34
|
+
```diff
|
|
35
|
+
{{codeDiff}}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### GSD Artifact Diff
|
|
25
39
|
|
|
26
40
|
```diff
|
|
27
|
-
{{
|
|
41
|
+
{{gsdDiff}}
|
|
28
42
|
```
|
|
29
43
|
|
|
30
44
|
## Your Task
|
|
@@ -33,7 +47,15 @@ Analyze the changes and guide the merge. Follow these steps exactly:
|
|
|
33
47
|
|
|
34
48
|
### Step 1: Categorize Changes
|
|
35
49
|
|
|
36
|
-
Classify each changed
|
|
50
|
+
Classify each changed file:
|
|
51
|
+
|
|
52
|
+
**Code changes:**
|
|
53
|
+
- **New source files** — new modules, components, utilities, tests
|
|
54
|
+
- **Modified source files** — changes to existing code
|
|
55
|
+
- **Config changes** — package.json, tsconfig, build config, etc.
|
|
56
|
+
- **Deleted files** — removed source or config files
|
|
57
|
+
|
|
58
|
+
**GSD artifact changes:**
|
|
37
59
|
- **New milestones** — entirely new M###/ directories with roadmaps
|
|
38
60
|
- **New slices/tasks** — new planning artifacts within existing milestones
|
|
39
61
|
- **Updated roadmaps** — modifications to existing M###-ROADMAP.md files
|
|
@@ -47,7 +69,12 @@ Classify each changed GSD artifact:
|
|
|
47
69
|
|
|
48
70
|
For each **modified** file, check whether the main branch version has also changed since the worktree branched off. Flag any files where both branches have diverged — these need manual reconciliation.
|
|
49
71
|
|
|
50
|
-
|
|
72
|
+
To compare versions:
|
|
73
|
+
- **Main-branch version:** read the file at its normal path (your CWD is the main tree)
|
|
74
|
+
- **Worktree version:** read the file at `{{worktreePath}}/<relative-path>`
|
|
75
|
+
- Use `git merge-base {{mainBranch}} {{worktreeBranch}}` to find the common ancestor if needed
|
|
76
|
+
|
|
77
|
+
Classify each modified file:
|
|
51
78
|
- **Clean merges** — main hasn't changed, worktree changes can apply directly
|
|
52
79
|
- **Conflicts** — both branches changed the same file; needs reconciliation
|
|
53
80
|
- **Stale changes** — worktree modified a file that main has since replaced or removed
|
|
@@ -58,28 +85,35 @@ Present a merge plan to the user:
|
|
|
58
85
|
|
|
59
86
|
1. For **clean merges**: list files that will merge without conflict
|
|
60
87
|
2. For **conflicts**: show both versions side-by-side and propose a reconciled version
|
|
61
|
-
3. For **new
|
|
62
|
-
4. For **removed
|
|
88
|
+
3. For **new files**: confirm they should be added to the main branch
|
|
89
|
+
4. For **removed files**: confirm the removals are intentional
|
|
63
90
|
|
|
64
91
|
Ask the user to confirm the merge plan before proceeding.
|
|
65
92
|
|
|
66
93
|
### Step 4: Execute Merge
|
|
67
94
|
|
|
68
|
-
Once confirmed:
|
|
95
|
+
Once confirmed, run all commands from `{{mainTreePath}}` (your CWD):
|
|
69
96
|
|
|
70
|
-
1.
|
|
71
|
-
2.
|
|
72
|
-
3.
|
|
73
|
-
4.
|
|
74
|
-
5.
|
|
97
|
+
1. Ensure you are on the target branch: `git checkout {{mainBranch}}`
|
|
98
|
+
2. If there are conflicts requiring manual reconciliation, apply the reconciled versions first
|
|
99
|
+
3. Run `git merge --squash {{worktreeBranch}}` to bring in all changes
|
|
100
|
+
4. Review the staged changes — if any reconciled files need adjustment, apply them now
|
|
101
|
+
5. Commit with message: `merge(worktree/{{worktreeName}}): <summary of what was merged>`
|
|
102
|
+
6. Report what was merged
|
|
75
103
|
|
|
76
104
|
### Step 5: Cleanup Prompt
|
|
77
105
|
|
|
78
106
|
After a successful merge, ask the user whether to:
|
|
79
|
-
- **Remove the worktree** — delete
|
|
107
|
+
- **Remove the worktree** — delete the worktree directory and the `{{worktreeBranch}}` branch
|
|
80
108
|
- **Keep the worktree** — leave it for continued parallel work
|
|
81
109
|
|
|
82
|
-
If the user chooses to remove it, run
|
|
110
|
+
If the user chooses to remove it, run these commands from `{{mainTreePath}}`:
|
|
111
|
+
```
|
|
112
|
+
git worktree remove {{worktreePath}}
|
|
113
|
+
git branch -D {{worktreeBranch}}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Do NOT use `/worktree remove` — the command handler may not have the correct state after the merge.** Use the git commands directly.
|
|
83
117
|
|
|
84
118
|
## Important
|
|
85
119
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
let passed = 0;
|
|
5
|
+
let failed = 0;
|
|
6
|
+
|
|
7
|
+
function assert(condition: boolean, message: string): void {
|
|
8
|
+
if (condition) passed++;
|
|
9
|
+
else {
|
|
10
|
+
failed++;
|
|
11
|
+
console.error(` FAIL: ${message}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const promptPath = join(process.cwd(), 'src/resources/extensions/gsd/prompts/discuss.md');
|
|
16
|
+
const discussPrompt = readFileSync(promptPath, 'utf-8');
|
|
17
|
+
|
|
18
|
+
console.log('\n=== discuss prompt: resilient vision framing ===');
|
|
19
|
+
{
|
|
20
|
+
const hardenedPattern = /Say exactly:\s*"What's the vision\?"/;
|
|
21
|
+
assert(!hardenedPattern.test(discussPrompt), 'prompt no longer uses exact-verbosity lock');
|
|
22
|
+
assert(
|
|
23
|
+
discussPrompt.includes('Ask: "What\'s the vision?" once'),
|
|
24
|
+
'prompt asks for vision exactly once',
|
|
25
|
+
);
|
|
26
|
+
assert(
|
|
27
|
+
discussPrompt.includes('Special handling'),
|
|
28
|
+
'prompt documents special handling for non-vision user messages',
|
|
29
|
+
);
|
|
30
|
+
assert(
|
|
31
|
+
discussPrompt.includes('instead of repeating "What\'s the vision?"'),
|
|
32
|
+
'prompt forbids repeating the vision question',
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
console.log(`\nResults: ${passed} passed, ${failed} failed`);
|
|
37
|
+
if (failed > 0) process.exit(1);
|
|
38
|
+
console.log('All tests passed ✓');
|