@geminixiang/pi-simplify 0.0.7 → 0.0.9
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/.pi/skills/release/SKILL.md +9 -9
- package/CHANGELOG.md +23 -0
- package/README.md +11 -1
- package/package.json +1 -1
- package/prompt.ts +2 -2
- package/selector.ts +52 -39
- package/workflow.ts +149 -7
|
@@ -11,15 +11,15 @@ Repo defaults:
|
|
|
11
11
|
- remote: `origin`
|
|
12
12
|
- repo: `geminixiang/pi-simplify`
|
|
13
13
|
- npm package: `@geminixiang/pi-simplify`
|
|
14
|
-
- use `package.json` version
|
|
14
|
+
- use `package.json` version for npm/package files, and `v<version>` for the git tag and GitHub release title
|
|
15
15
|
- versions with `-alpha.`, `-beta.`, or `-rc.` are prereleases by default
|
|
16
16
|
|
|
17
17
|
## Version rules
|
|
18
18
|
|
|
19
19
|
Examples:
|
|
20
20
|
|
|
21
|
-
- stable: `0.2.1`, `0.3.0`, `1.0.0`
|
|
22
|
-
- prerelease: `0.2.0-beta.8`, `0.3.0-rc.1`, `1.0.0-alpha.2`
|
|
21
|
+
- stable package version: `0.2.1`, `0.3.0`, `1.0.0` → release tag/title: `v0.2.1`, `v0.3.0`, `v1.0.0`
|
|
22
|
+
- prerelease package version: `0.2.0-beta.8`, `0.3.0-rc.1`, `1.0.0-alpha.2` → release tag/title: `v0.2.0-beta.8`, `v0.3.0-rc.1`, `v1.0.0-alpha.2`
|
|
23
23
|
|
|
24
24
|
Guidance:
|
|
25
25
|
|
|
@@ -100,17 +100,17 @@ Write concise notes focused on user-visible changes, usually with:
|
|
|
100
100
|
- `### Docs and maintenance`
|
|
101
101
|
- `### Verification`
|
|
102
102
|
|
|
103
|
-
Write notes to `/tmp/pi-simplify-release-<version>.md`. Keep them consistent with the CHANGELOG entry from step 3.
|
|
103
|
+
Write notes to `/tmp/pi-simplify-release-<version>.md`. Keep them consistent with the CHANGELOG entry from step 3. Use `v<previous-version>...v<version>` in compare links.
|
|
104
104
|
|
|
105
105
|
### 6. Create or update release
|
|
106
106
|
|
|
107
107
|
Prerelease:
|
|
108
108
|
|
|
109
109
|
```bash
|
|
110
|
-
gh release create <version> \
|
|
110
|
+
gh release create v<version> \
|
|
111
111
|
--repo geminixiang/pi-simplify \
|
|
112
112
|
--target main \
|
|
113
|
-
--title <version> \
|
|
113
|
+
--title v<version> \
|
|
114
114
|
--notes-file /tmp/pi-simplify-release-<version>.md \
|
|
115
115
|
--prerelease
|
|
116
116
|
```
|
|
@@ -118,14 +118,14 @@ gh release create <version> \
|
|
|
118
118
|
Stable:
|
|
119
119
|
|
|
120
120
|
```bash
|
|
121
|
-
gh release create <version> \
|
|
121
|
+
gh release create v<version> \
|
|
122
122
|
--repo geminixiang/pi-simplify \
|
|
123
123
|
--target main \
|
|
124
|
-
--title <version> \
|
|
124
|
+
--title v<version> \
|
|
125
125
|
--notes-file /tmp/pi-simplify-release-<version>.md
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
-
If it already exists, use `gh release edit <version> ...` and keep prerelease/stable intent consistent.
|
|
128
|
+
If it already exists, use `gh release edit v<version> ...` and keep prerelease/stable intent consistent.
|
|
129
129
|
|
|
130
130
|
## Report back
|
|
131
131
|
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,29 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.0.9] - 2026-05-27
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Support simplifying specific folders and files as snapshot reviews.
|
|
14
|
+
- Add a preset selector for choosing uncommitted changes or folder snapshot mode.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Respect configured selection keybindings in simplify TUI selectors.
|
|
19
|
+
- Keep release tags and GitHub release titles v-prefixed.
|
|
20
|
+
|
|
21
|
+
## [0.0.8] - 2026-05-25
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Support simplifying specific folders and files as snapshot reviews.
|
|
26
|
+
- Add a preset selector for choosing uncommitted changes or folder snapshot mode.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- Keep release tags and GitHub release titles v-prefixed.
|
|
31
|
+
|
|
9
32
|
## [0.0.7] - 2026-05-25
|
|
10
33
|
|
|
11
34
|
### Changed
|
package/README.md
CHANGED
|
@@ -30,12 +30,22 @@ pi install npm:@geminixiang/pi-simplify
|
|
|
30
30
|
/simplify
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
Opens a preset selector. Choose uncommitted changes or a folder snapshot.
|
|
34
|
+
|
|
35
|
+
Uncommitted mode analyzes all git changes and presents cleanup candidates:
|
|
34
36
|
|
|
35
37
|
- **Safe** (green) - auto-selected, will be deleted
|
|
36
38
|
- **Confirm** (yellow) - delete after user confirms
|
|
37
39
|
- **Review** (orange) - user should review first
|
|
38
40
|
|
|
41
|
+
### Simplify Folders
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
/simplify folder src docs
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Analyzes the specified folders/files as a snapshot (not a diff), even when there are no local git changes.
|
|
48
|
+
|
|
39
49
|
### With Focus
|
|
40
50
|
|
|
41
51
|
```
|
package/package.json
CHANGED
package/prompt.ts
CHANGED
|
@@ -50,8 +50,8 @@ Before flagging, **search the codebase** (utility directories, shared modules, f
|
|
|
50
50
|
|
|
51
51
|
## How to Analyze
|
|
52
52
|
|
|
53
|
-
1.
|
|
54
|
-
2. For each change, classify as **Essential** / **Residual** / **Legacy** (don't flag legacy code unless the diff touches it).
|
|
53
|
+
1. Unless the user explicitly asks for a folder/snapshot review, run \`git diff\` to see what changed. For folder/snapshot review, read the files directly under the requested paths and ignore files outside that scope.
|
|
54
|
+
2. For each change or in-scope snapshot finding, classify as **Essential** / **Residual** / **Legacy** (don't flag legacy code unless the diff touches it; in folder/snapshot mode, flag only in-scope code that is clearly removable or simplifiable).
|
|
55
55
|
3. For each finding:
|
|
56
56
|
- Identify exact file and line(s)
|
|
57
57
|
- Assign **category** (reuse / quality / efficiency) and **risk**
|
package/selector.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { getSelectListTheme, type ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "@earendil-works/pi-tui";
|
|
2
|
+
getSelectListTheme,
|
|
3
|
+
keyHint,
|
|
4
|
+
rawKeyHint,
|
|
5
|
+
type ExtensionCommandContext,
|
|
6
|
+
} from "@earendil-works/pi-coding-agent";
|
|
7
|
+
import { matchesKey, SelectList, wrapTextWithAnsi, type SelectItem } from "@earendil-works/pi-tui";
|
|
9
8
|
|
|
10
9
|
import type { Action, SimplifyResult } from "./types.js";
|
|
11
10
|
|
|
@@ -64,7 +63,7 @@ export async function showCandidateSelector(
|
|
|
64
63
|
Math.min(selectedIndex - Math.floor(maxVisible / 2), selectableItems.length - maxVisible),
|
|
65
64
|
);
|
|
66
65
|
|
|
67
|
-
const result = await ctx.ui.custom<SimplifyResult[]>((tui, theme,
|
|
66
|
+
const result = await ctx.ui.custom<SimplifyResult[]>((tui, theme, keybindings, done) => {
|
|
68
67
|
const updateListLabel = (index: number) => {
|
|
69
68
|
const item = listItems[index];
|
|
70
69
|
const { candidate } = selectableItems[index];
|
|
@@ -82,6 +81,34 @@ export async function showCandidateSelector(
|
|
|
82
81
|
};
|
|
83
82
|
selectList.onCancel = () => done([]);
|
|
84
83
|
|
|
84
|
+
const submitSelection = () => {
|
|
85
|
+
done(Array.from(selectedSet).map((i) => selectableItems[i].candidate));
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const cancelSelection = () => {
|
|
89
|
+
done([]);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const toggleCurrent = () => {
|
|
93
|
+
if (selectedSet.has(cursorPos)) {
|
|
94
|
+
selectedSet.delete(cursorPos);
|
|
95
|
+
} else {
|
|
96
|
+
selectedSet.add(cursorPos);
|
|
97
|
+
}
|
|
98
|
+
updateListLabel(cursorPos);
|
|
99
|
+
tui.requestRender();
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const toggleAll = () => {
|
|
103
|
+
if (selectedSet.size === selectableItems.length) {
|
|
104
|
+
selectedSet.clear();
|
|
105
|
+
} else {
|
|
106
|
+
for (let i = 0; i < selectableItems.length; i++) selectedSet.add(i);
|
|
107
|
+
}
|
|
108
|
+
updateAllListLabels();
|
|
109
|
+
tui.requestRender();
|
|
110
|
+
};
|
|
111
|
+
|
|
85
112
|
return {
|
|
86
113
|
render(width: number) {
|
|
87
114
|
selectList.setSelectedIndex(cursorPos);
|
|
@@ -119,14 +146,23 @@ export async function showCandidateSelector(
|
|
|
119
146
|
);
|
|
120
147
|
lines.push(theme.fg("muted", `${detailPrefix}Kind: ${current.category}`));
|
|
121
148
|
lines.push(theme.fg("muted", `${detailPrefix}Fix: ${ACTION_LABEL[current.action]}`));
|
|
122
|
-
lines.push(
|
|
149
|
+
lines.push(
|
|
150
|
+
theme.fg("borderMuted", `${detailIndent}└─ ${rawKeyHint("space", "selects this fix")}`),
|
|
151
|
+
);
|
|
123
152
|
}
|
|
124
153
|
|
|
125
154
|
lines.push("");
|
|
126
155
|
lines.push(
|
|
127
156
|
theme.fg(
|
|
128
157
|
"muted",
|
|
129
|
-
|
|
158
|
+
[
|
|
159
|
+
`Selected: ${selectedSet.size}`,
|
|
160
|
+
rawKeyHint("↑↓", "navigate"),
|
|
161
|
+
rawKeyHint("space", "toggle"),
|
|
162
|
+
rawKeyHint("a", "select all"),
|
|
163
|
+
keyHint("tui.select.confirm", "confirm"),
|
|
164
|
+
keyHint("tui.select.cancel", "cancel"),
|
|
165
|
+
].join(" • "),
|
|
130
166
|
),
|
|
131
167
|
);
|
|
132
168
|
return lines;
|
|
@@ -135,35 +171,12 @@ export async function showCandidateSelector(
|
|
|
135
171
|
selectList.invalidate();
|
|
136
172
|
},
|
|
137
173
|
handleInput(data: string) {
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (matchesKey(data,
|
|
144
|
-
done([]);
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
if (matchesKey(data, Key.space)) {
|
|
148
|
-
if (selectedSet.has(cursorPos)) {
|
|
149
|
-
selectedSet.delete(cursorPos);
|
|
150
|
-
} else {
|
|
151
|
-
selectedSet.add(cursorPos);
|
|
152
|
-
}
|
|
153
|
-
updateListLabel(cursorPos);
|
|
154
|
-
tui.requestRender();
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
if (matchesKey(data, "a")) {
|
|
158
|
-
if (selectedSet.size === selectableItems.length) {
|
|
159
|
-
selectedSet.clear();
|
|
160
|
-
} else {
|
|
161
|
-
for (let i = 0; i < selectableItems.length; i++) selectedSet.add(i);
|
|
162
|
-
}
|
|
163
|
-
updateAllListLabels();
|
|
164
|
-
tui.requestRender();
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
174
|
+
if (keybindings.matches(data, "tui.select.confirm")) return submitSelection();
|
|
175
|
+
if (keybindings.matches(data, "tui.select.cancel")) return cancelSelection();
|
|
176
|
+
|
|
177
|
+
// Extra shortcuts: these selector-specific actions are not registered pi keybinding ids.
|
|
178
|
+
if (matchesKey(data, "space")) return toggleCurrent();
|
|
179
|
+
if (matchesKey(data, "a")) return toggleAll();
|
|
167
180
|
|
|
168
181
|
const previousCursorPos = cursorPos;
|
|
169
182
|
selectList.handleInput(data);
|
package/workflow.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defineTool,
|
|
3
|
+
DynamicBorder,
|
|
4
|
+
keyHint,
|
|
3
5
|
type ExtensionAPI,
|
|
4
6
|
type ExtensionCommandContext,
|
|
5
7
|
} from "@earendil-works/pi-coding-agent";
|
|
8
|
+
import { Container, SelectList, Text, type SelectItem } from "@earendil-works/pi-tui";
|
|
6
9
|
import { Type } from "typebox";
|
|
7
10
|
|
|
8
11
|
import { SIMPLIFY_PROMPT } from "./prompt.js";
|
|
@@ -26,6 +29,58 @@ const actionSchema = Type.Union([
|
|
|
26
29
|
Type.Literal("parallelize"),
|
|
27
30
|
]);
|
|
28
31
|
|
|
32
|
+
type SimplifyTarget = { type: "uncommitted" } | { type: "folder"; paths: string[] };
|
|
33
|
+
type ParsedArgs = {
|
|
34
|
+
target: SimplifyTarget | null;
|
|
35
|
+
additionalFocus?: string;
|
|
36
|
+
error?: string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const SIMPLIFY_PRESETS = [
|
|
40
|
+
{ value: "uncommitted", label: "Simplify uncommitted changes", description: "" },
|
|
41
|
+
{ value: "folder", label: "Simplify a folder (or more)", description: "(snapshot, not diff)" },
|
|
42
|
+
] as const;
|
|
43
|
+
|
|
44
|
+
type SimplifyPresetValue = (typeof SIMPLIFY_PRESETS)[number]["value"];
|
|
45
|
+
|
|
46
|
+
function parseSimplifyPaths(value: string): string[] {
|
|
47
|
+
return value
|
|
48
|
+
.split(/\s+/)
|
|
49
|
+
.map((item) => item.trim())
|
|
50
|
+
.filter((item) => item.length > 0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function parseArgs(args: string): ParsedArgs {
|
|
54
|
+
const trimmed = args.trim();
|
|
55
|
+
if (!trimmed) return { target: null };
|
|
56
|
+
|
|
57
|
+
const [subcommand, ...rest] = trimmed.split(/\s+/);
|
|
58
|
+
if (subcommand?.toLowerCase() !== "folder") {
|
|
59
|
+
return { target: { type: "uncommitted" }, additionalFocus: trimmed };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const paths = parseSimplifyPaths(rest.join(" "));
|
|
63
|
+
if (paths.length === 0)
|
|
64
|
+
return { target: null, error: "Usage: /simplify folder <path> [path...]" };
|
|
65
|
+
return { target: { type: "folder", paths } };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function hasUncommittedChanges(pi: ExtensionAPI): Promise<boolean> {
|
|
69
|
+
const { stdout, code } = await pi.exec("git", ["status", "--porcelain"]);
|
|
70
|
+
return code === 0 && stdout.trim().length > 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function buildSimplifyPrompt(target: SimplifyTarget, additionalFocus?: string): string {
|
|
74
|
+
let fullPrompt = SIMPLIFY_PROMPT;
|
|
75
|
+
|
|
76
|
+
if (target.type === "folder") {
|
|
77
|
+
fullPrompt += `\n\n## Scope Override: Folder Snapshot\n\nReview only the code in these repository-relative paths: ${target.paths.join(", ")}\n\nThis is a snapshot review, not a git diff review. Read files directly under these paths instead of relying on \`git diff\`. Only return candidates whose \`file\` is inside one of these paths.`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (additionalFocus?.trim()) fullPrompt += `\n\n## Additional Focus\n\n${additionalFocus.trim()}`;
|
|
81
|
+
return fullPrompt;
|
|
82
|
+
}
|
|
83
|
+
|
|
29
84
|
function registerSimplifyCandidatesTool(
|
|
30
85
|
pi: ExtensionAPI,
|
|
31
86
|
state: {
|
|
@@ -107,6 +162,79 @@ function registerSimplifyCandidatesTool(
|
|
|
107
162
|
);
|
|
108
163
|
}
|
|
109
164
|
|
|
165
|
+
async function showFolderInput(ctx: ExtensionCommandContext): Promise<SimplifyTarget | null> {
|
|
166
|
+
const result = await ctx.ui.editor(
|
|
167
|
+
"Enter folders/files to simplify (space-separated or one per line):",
|
|
168
|
+
".",
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
if (!result?.trim()) return null;
|
|
172
|
+
const paths = parseSimplifyPaths(result);
|
|
173
|
+
if (paths.length === 0) return null;
|
|
174
|
+
|
|
175
|
+
return { type: "folder", paths };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async function showSimplifyTargetSelector(
|
|
179
|
+
ctx: ExtensionCommandContext,
|
|
180
|
+
pi: ExtensionAPI,
|
|
181
|
+
): Promise<SimplifyTarget | null> {
|
|
182
|
+
const presetItems: SelectItem[] = SIMPLIFY_PRESETS.map((preset) => ({
|
|
183
|
+
value: preset.value,
|
|
184
|
+
label: preset.label,
|
|
185
|
+
description: preset.description,
|
|
186
|
+
}));
|
|
187
|
+
const smartDefault = (await hasUncommittedChanges(pi)) ? "uncommitted" : "folder";
|
|
188
|
+
const smartDefaultIndex = presetItems.findIndex((item) => item.value === smartDefault);
|
|
189
|
+
|
|
190
|
+
while (true) {
|
|
191
|
+
const result = await ctx.ui.custom<SimplifyPresetValue | null>((tui, theme, _kb, done) => {
|
|
192
|
+
const container = new Container();
|
|
193
|
+
container.addChild(new DynamicBorder((str) => theme.fg("accent", str)));
|
|
194
|
+
container.addChild(new Text(theme.fg("accent", theme.bold("Select a simplify preset"))));
|
|
195
|
+
|
|
196
|
+
const selectList = new SelectList(presetItems, Math.min(presetItems.length, 10), {
|
|
197
|
+
selectedPrefix: (text) => theme.fg("accent", text),
|
|
198
|
+
selectedText: (text) => theme.fg("accent", text),
|
|
199
|
+
description: (text) => theme.fg("muted", text),
|
|
200
|
+
scrollInfo: (text) => theme.fg("dim", text),
|
|
201
|
+
noMatch: (text) => theme.fg("warning", text),
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
if (smartDefaultIndex >= 0) selectList.setSelectedIndex(smartDefaultIndex);
|
|
205
|
+
selectList.onSelect = (item) => done(item.value as SimplifyPresetValue);
|
|
206
|
+
selectList.onCancel = () => done(null);
|
|
207
|
+
|
|
208
|
+
container.addChild(selectList);
|
|
209
|
+
container.addChild(
|
|
210
|
+
new Text(
|
|
211
|
+
`${keyHint("tui.select.confirm", "confirm")} ${keyHint("tui.select.cancel", "cancel")}`,
|
|
212
|
+
),
|
|
213
|
+
);
|
|
214
|
+
container.addChild(new DynamicBorder((str) => theme.fg("accent", str)));
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
render(width: number) {
|
|
218
|
+
return container.render(width);
|
|
219
|
+
},
|
|
220
|
+
invalidate() {
|
|
221
|
+
container.invalidate();
|
|
222
|
+
},
|
|
223
|
+
handleInput(data: string) {
|
|
224
|
+
selectList.handleInput(data);
|
|
225
|
+
tui.requestRender();
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
if (!result) return null;
|
|
231
|
+
if (result === "uncommitted") return { type: "uncommitted" };
|
|
232
|
+
|
|
233
|
+
const target = await showFolderInput(ctx);
|
|
234
|
+
if (target) return target;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
110
238
|
async function applyFindings(
|
|
111
239
|
ctx: ExtensionCommandContext,
|
|
112
240
|
selected: SimplifyResult[],
|
|
@@ -167,7 +295,8 @@ export function registerSimplifyWorkflow(pi: ExtensionAPI) {
|
|
|
167
295
|
});
|
|
168
296
|
|
|
169
297
|
pi.registerCommand("simplify", {
|
|
170
|
-
description:
|
|
298
|
+
description:
|
|
299
|
+
"Review changed code or folders for reuse, quality, and efficiency, then apply fixes",
|
|
171
300
|
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
172
301
|
if (!ctx.hasUI) {
|
|
173
302
|
ctx.ui.notify("Simplify requires interactive mode", "error");
|
|
@@ -188,16 +317,29 @@ export function registerSimplifyWorkflow(pi: ExtensionAPI) {
|
|
|
188
317
|
return;
|
|
189
318
|
}
|
|
190
319
|
|
|
191
|
-
const
|
|
192
|
-
if (
|
|
193
|
-
ctx.ui.notify(
|
|
320
|
+
const parsed = parseArgs(args);
|
|
321
|
+
if (parsed.error) {
|
|
322
|
+
ctx.ui.notify(parsed.error, "error");
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
let target = parsed.target;
|
|
327
|
+
if (!target) target = await showSimplifyTargetSelector(ctx, pi);
|
|
328
|
+
if (!target) {
|
|
329
|
+
ctx.ui.notify("Simplify cancelled", "info");
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (target.type === "uncommitted" && !(await hasUncommittedChanges(pi))) {
|
|
334
|
+
ctx.ui.notify("No git changes found. Choose folder mode to simplify a snapshot.", "info");
|
|
194
335
|
return;
|
|
195
336
|
}
|
|
196
337
|
|
|
197
|
-
|
|
338
|
+
const targetHint =
|
|
339
|
+
target.type === "folder" ? `folders: ${target.paths.join(", ")}` : "uncommitted changes";
|
|
340
|
+
ctx.ui.notify(`Analyzing ${targetHint} for review findings...`, "info");
|
|
198
341
|
|
|
199
|
-
|
|
200
|
-
if (args.trim()) fullPrompt += `\n\n## Additional Focus\n\n${args.trim()}`;
|
|
342
|
+
const fullPrompt = buildSimplifyPrompt(target, parsed.additionalFocus);
|
|
201
343
|
|
|
202
344
|
latestToolCandidates = null;
|
|
203
345
|
const turnStarted = new Promise<void>((r) => {
|