ultimate-pi 0.10.0 → 0.11.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/.agents/skills/harness-decisions/SKILL.md +3 -3
- package/.agents/skills/harness-orchestration/SKILL.md +19 -11
- package/.agents/skills/harness-plan/SKILL.md +15 -9
- package/.pi/agents/harness/planner.md +6 -47
- package/.pi/agents/harness/planning/decompose.md +84 -0
- package/.pi/agents/harness/planning/hypothesis-eval.md +59 -0
- package/.pi/agents/harness/planning/hypothesis.md +90 -0
- package/.pi/agents/harness/planning/plan-adversary.md +50 -0
- package/.pi/agents/harness/planning/planner.md +20 -0
- package/.pi/agents/harness/planning/scout-graphify.md +48 -0
- package/.pi/agents/harness/planning/scout-semantic.md +42 -0
- package/.pi/agents/harness/planning/scout-structure.md +44 -0
- package/.pi/extensions/harness-ask-user.ts +5 -0
- package/.pi/extensions/harness-live-widget.ts +48 -28
- package/.pi/extensions/harness-plan-approval.ts +192 -24
- package/.pi/extensions/harness-run-context.ts +24 -15
- package/.pi/extensions/harness-subagents.ts +8 -3
- package/.pi/extensions/harness-web-tools.ts +2 -0
- package/.pi/extensions/lib/extension-load-guard.ts +39 -0
- package/.pi/extensions/lib/harness-subagents/harness-subagent-policy.ts +33 -5
- package/.pi/extensions/lib/harness-subagents/parent-harness-ui-bridge.ts +2 -171
- package/.pi/extensions/lib/harness-subagents/parent-harness-ui-hooks.ts +18 -0
- package/.pi/extensions/lib/harness-subagents/spawn-policy.ts +1 -5
- package/.pi/extensions/lib/harness-subagents/vendored/agent-runner.ts +0 -18
- package/.pi/extensions/lib/harness-subagents/vendored/index.ts +4 -36
- package/.pi/extensions/lib/harness-subagents/vendored/ui/agent-widget.ts +2 -0
- package/.pi/extensions/lib/plan-approval/create-plan.ts +5 -0
- package/.pi/extensions/lib/plan-approval/dialog.ts +231 -147
- package/.pi/extensions/lib/plan-approval/plan-review.ts +393 -0
- package/.pi/extensions/lib/plan-approval/schema.ts +16 -1
- package/.pi/extensions/lib/plan-approval/types.ts +10 -0
- package/.pi/extensions/lib/plan-approval/validate.ts +2 -0
- package/.pi/extensions/policy-gate.ts +1 -1
- package/.pi/extensions/ultimate-pi-vcc.ts +5 -0
- package/.pi/harness/agents.manifest.json +114 -82
- package/.pi/harness/docs/adrs/0032-harness-command-orchestration.md +3 -3
- package/.pi/harness/docs/adrs/0033-parent-orchestrated-planning.md +34 -0
- package/.pi/harness/docs/adrs/0034-darwin-plan-research-pipeline.md +41 -0
- package/.pi/harness/docs/adrs/README.md +2 -0
- package/.pi/harness/specs/README.md +1 -1
- package/.pi/harness/specs/harness-spawn-context.schema.json +2 -1
- package/.pi/harness/specs/plan-adversary-brief.schema.json +45 -0
- package/.pi/harness/specs/plan-decomposition-brief.schema.json +108 -0
- package/.pi/harness/specs/plan-hypothesis-brief.schema.json +96 -0
- package/.pi/harness/specs/plan-hypothesis-eval.schema.json +61 -0
- package/.pi/lib/harness-run-context.ts +12 -0
- package/.pi/prompts/harness-auto.md +1 -1
- package/.pi/prompts/harness-plan.md +116 -20
- package/.pi/prompts/harness-setup.md +1 -1
- package/.pi/scripts/harness-resolve-up-pkg.mjs +13 -0
- package/CHANGELOG.md +18 -0
- package/biome.json +4 -1
- package/package.json +2 -2
|
@@ -12,6 +12,51 @@ interface CustomAnswer {
|
|
|
12
12
|
response: { kind: "selection"; selections: string[] };
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
/** Lines reserved below overlay: harness-live widget + editor + footer. */
|
|
16
|
+
export const PLAN_APPROVAL_BOTTOM_RESERVE_LINES = 11;
|
|
17
|
+
/** Estimate agents widget height when stacking above harness live. */
|
|
18
|
+
export const PLAN_APPROVAL_AGENTS_TOP_RESERVE_LINES = 12;
|
|
19
|
+
export const PLAN_APPROVAL_MIN_VIEWPORT = 6;
|
|
20
|
+
|
|
21
|
+
export function computePlanViewport(
|
|
22
|
+
availableHeight: number,
|
|
23
|
+
chromeLines: number,
|
|
24
|
+
): number {
|
|
25
|
+
return Math.max(PLAN_APPROVAL_MIN_VIEWPORT, availableHeight - chromeLines);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function computePlanOverlayMaxHeight(termHeight: number): number {
|
|
29
|
+
return Math.max(
|
|
30
|
+
PLAN_APPROVAL_MIN_VIEWPORT + 8,
|
|
31
|
+
termHeight -
|
|
32
|
+
PLAN_APPROVAL_BOTTOM_RESERVE_LINES -
|
|
33
|
+
PLAN_APPROVAL_AGENTS_TOP_RESERVE_LINES,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function countPlanChromeLines(
|
|
38
|
+
validated: ValidatedApprovePlanParams,
|
|
39
|
+
displayOptions: ValidatedApprovePlanParams["options"],
|
|
40
|
+
useOverlay: boolean,
|
|
41
|
+
): number {
|
|
42
|
+
let chrome = useOverlay ? 2 : 0; // borders
|
|
43
|
+
chrome += 1; // title
|
|
44
|
+
if (validated.human_summary) {
|
|
45
|
+
chrome += validated.human_summary.split("\n").length;
|
|
46
|
+
}
|
|
47
|
+
chrome += 1; // blank before plan
|
|
48
|
+
chrome += 1; // plan label
|
|
49
|
+
chrome += 1; // blank before options
|
|
50
|
+
chrome += 1; // options label
|
|
51
|
+
for (const opt of displayOptions) {
|
|
52
|
+
chrome += 1;
|
|
53
|
+
if (opt.description) chrome += 1;
|
|
54
|
+
}
|
|
55
|
+
chrome += 1; // blank before hints
|
|
56
|
+
chrome += 1; // hints
|
|
57
|
+
return chrome;
|
|
58
|
+
}
|
|
59
|
+
|
|
15
60
|
function withTimeout<T>(
|
|
16
61
|
promise: Promise<T | null>,
|
|
17
62
|
ms: number | undefined,
|
|
@@ -25,177 +70,216 @@ function withTimeout<T>(
|
|
|
25
70
|
]);
|
|
26
71
|
}
|
|
27
72
|
|
|
73
|
+
export type RunPlanApprovalDialogOptions = {
|
|
74
|
+
onMounted?: () => void;
|
|
75
|
+
};
|
|
76
|
+
|
|
28
77
|
export async function runPlanApprovalDialog(
|
|
29
78
|
ui: ExtensionUIContext,
|
|
30
79
|
validated: ValidatedApprovePlanParams,
|
|
80
|
+
options?: RunPlanApprovalDialogOptions,
|
|
31
81
|
): Promise<PlanApprovalDialogResult> {
|
|
32
82
|
const planLines = formatPlanPacketLines(validated.plan_packet, 100);
|
|
33
83
|
const displayOptions = validated.options;
|
|
84
|
+
const useOverlay = validated.displayMode !== "inline";
|
|
85
|
+
let overlayTermHeight = 24;
|
|
34
86
|
|
|
35
87
|
const result = await withTimeout(
|
|
36
|
-
ui.custom<CustomAnswer | null>(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function handleInput(data: string) {
|
|
55
|
-
if (focus === "plan") {
|
|
56
|
-
if (matchesKey(data, Key.up) || data === "k") {
|
|
57
|
-
scrollOffset = Math.max(0, scrollOffset - 1);
|
|
58
|
-
refresh();
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
if (matchesKey(data, Key.down) || data === "j") {
|
|
62
|
-
scrollOffset += 1;
|
|
63
|
-
refresh();
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
if (matchesKey(data, Key.pageUp)) {
|
|
67
|
-
scrollOffset = Math.max(0, scrollOffset - 8);
|
|
68
|
-
refresh();
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
if (matchesKey(data, Key.pageDown)) {
|
|
72
|
-
scrollOffset += 8;
|
|
73
|
-
refresh();
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
if (matchesKey(data, Key.tab)) {
|
|
77
|
-
focus = "options";
|
|
78
|
-
refresh();
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
88
|
+
ui.custom<CustomAnswer | null>(
|
|
89
|
+
(tui, theme, _kb, done) => {
|
|
90
|
+
const tuiHeight = (tui as unknown as { height?: number }).height;
|
|
91
|
+
overlayTermHeight =
|
|
92
|
+
typeof tuiHeight === "number" && tuiHeight > 10 ? tuiHeight : 24;
|
|
93
|
+
options?.onMounted?.();
|
|
94
|
+
|
|
95
|
+
let scrollOffset = 0;
|
|
96
|
+
let optionIndex = 0;
|
|
97
|
+
let focus: FocusRegion = "plan";
|
|
98
|
+
let cachedLines: string[] | undefined;
|
|
99
|
+
|
|
100
|
+
function refresh() {
|
|
101
|
+
cachedLines = undefined;
|
|
102
|
+
tui.requestRender();
|
|
81
103
|
}
|
|
82
104
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
105
|
+
function submitSelection() {
|
|
106
|
+
const opt = displayOptions[optionIndex];
|
|
107
|
+
done({
|
|
108
|
+
response: { kind: "selection", selections: [opt.title] },
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function handleInput(data: string) {
|
|
113
|
+
if (focus === "plan") {
|
|
114
|
+
if (matchesKey(data, Key.up) || data === "k") {
|
|
115
|
+
scrollOffset = Math.max(0, scrollOffset - 1);
|
|
116
|
+
refresh();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (matchesKey(data, Key.down) || data === "j") {
|
|
120
|
+
scrollOffset += 1;
|
|
121
|
+
refresh();
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (matchesKey(data, Key.pageUp)) {
|
|
125
|
+
scrollOffset = Math.max(0, scrollOffset - 8);
|
|
126
|
+
refresh();
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (matchesKey(data, Key.pageDown)) {
|
|
130
|
+
scrollOffset += 8;
|
|
131
|
+
refresh();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (matchesKey(data, Key.tab)) {
|
|
135
|
+
focus = "options";
|
|
136
|
+
refresh();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
93
139
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
140
|
+
|
|
141
|
+
if (focus === "options") {
|
|
142
|
+
if (matchesKey(data, Key.up)) {
|
|
143
|
+
optionIndex = Math.max(0, optionIndex - 1);
|
|
144
|
+
refresh();
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (matchesKey(data, Key.down)) {
|
|
148
|
+
optionIndex = Math.min(
|
|
149
|
+
displayOptions.length - 1,
|
|
150
|
+
optionIndex + 1,
|
|
151
|
+
);
|
|
152
|
+
refresh();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (matchesKey(data, Key.tab)) {
|
|
156
|
+
focus = "plan";
|
|
157
|
+
refresh();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (matchesKey(data, Key.enter)) {
|
|
161
|
+
submitSelection();
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
98
164
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
165
|
+
|
|
166
|
+
if (matchesKey(data, Key.escape)) {
|
|
167
|
+
done(null);
|
|
102
168
|
}
|
|
103
169
|
}
|
|
104
170
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function render(width: number): string[] {
|
|
111
|
-
if (cachedLines) return cachedLines;
|
|
112
|
-
|
|
113
|
-
const lines: string[] = [];
|
|
114
|
-
const add = (s: string) => lines.push(truncateToWidth(s, width));
|
|
115
|
-
const useOverlay = validated.displayMode !== "inline";
|
|
116
|
-
const dims = (tui as { height?: number }).height;
|
|
117
|
-
const termHeight = typeof dims === "number" && dims > 10 ? dims : 24;
|
|
118
|
-
const footerLines = displayOptions.length * 2 + 8;
|
|
119
|
-
const planViewport = Math.max(
|
|
120
|
-
6,
|
|
121
|
-
Math.floor(termHeight * 0.55) - footerLines,
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
if (useOverlay) {
|
|
125
|
-
add(theme.fg("accent", "─".repeat(width)));
|
|
126
|
-
}
|
|
171
|
+
function render(width: number): string[] {
|
|
172
|
+
if (cachedLines) return cachedLines;
|
|
127
173
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const maxScroll = Math.max(0, planLines.length - planViewport);
|
|
137
|
-
scrollOffset = Math.min(scrollOffset, maxScroll);
|
|
138
|
-
const visible = planLines.slice(
|
|
139
|
-
scrollOffset,
|
|
140
|
-
scrollOffset + planViewport,
|
|
141
|
-
);
|
|
142
|
-
const planLabel =
|
|
143
|
-
focus === "plan"
|
|
144
|
-
? theme.fg("accent", " [plan — ↑↓/Pg scroll, Tab → options]")
|
|
145
|
-
: theme.fg("dim", " [plan]");
|
|
146
|
-
add(planLabel);
|
|
147
|
-
for (const line of visible) {
|
|
148
|
-
add(theme.fg("text", ` ${line}`));
|
|
149
|
-
}
|
|
150
|
-
if (planLines.length > planViewport) {
|
|
151
|
-
add(
|
|
152
|
-
theme.fg(
|
|
153
|
-
"dim",
|
|
154
|
-
` … ${scrollOffset + 1}-${scrollOffset + visible.length} of ${planLines.length}`,
|
|
155
|
-
),
|
|
174
|
+
const lines: string[] = [];
|
|
175
|
+
const add = (s: string) => lines.push(truncateToWidth(s, width));
|
|
176
|
+
const dims = (tui as { height?: number }).height;
|
|
177
|
+
const termHeight = typeof dims === "number" && dims > 10 ? dims : 24;
|
|
178
|
+
const chromeLines = countPlanChromeLines(
|
|
179
|
+
validated,
|
|
180
|
+
displayOptions,
|
|
181
|
+
useOverlay,
|
|
156
182
|
);
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
? theme.fg("accent", " Options (↑↓, Enter, Tab → plan):")
|
|
163
|
-
: theme.fg("dim", " Options (Tab to focus):");
|
|
164
|
-
add(optLabel);
|
|
165
|
-
for (let i = 0; i < displayOptions.length; i++) {
|
|
166
|
-
const opt = displayOptions[i];
|
|
167
|
-
const focused = focus === "options" && i === optionIndex;
|
|
168
|
-
const prefix = focused ? theme.fg("accent", "> ") : " ";
|
|
169
|
-
const num = `${i + 1}. `;
|
|
170
|
-
if (focused) {
|
|
171
|
-
add(prefix + theme.fg("accent", `${num}${opt.title}`));
|
|
183
|
+
|
|
184
|
+
let availableHeight: number;
|
|
185
|
+
if (useOverlay) {
|
|
186
|
+
const overlayMax = computePlanOverlayMaxHeight(termHeight);
|
|
187
|
+
availableHeight = overlayMax;
|
|
172
188
|
} else {
|
|
173
|
-
|
|
189
|
+
availableHeight = termHeight - PLAN_APPROVAL_BOTTOM_RESERVE_LINES;
|
|
174
190
|
}
|
|
175
|
-
|
|
176
|
-
|
|
191
|
+
const planViewport = computePlanViewport(
|
|
192
|
+
availableHeight,
|
|
193
|
+
chromeLines,
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
if (useOverlay) {
|
|
197
|
+
add(theme.fg("accent", "─".repeat(width)));
|
|
177
198
|
}
|
|
178
|
-
}
|
|
179
199
|
|
|
180
|
-
|
|
181
|
-
|
|
200
|
+
add(theme.fg("accent", " Plan approval"));
|
|
201
|
+
if (validated.human_summary) {
|
|
202
|
+
for (const line of validated.human_summary.split("\n")) {
|
|
203
|
+
add(theme.fg("muted", ` ${line}`));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
lines.push("");
|
|
182
207
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
208
|
+
const maxScroll = Math.max(0, planLines.length - planViewport);
|
|
209
|
+
scrollOffset = Math.min(scrollOffset, maxScroll);
|
|
210
|
+
const visible = planLines.slice(
|
|
211
|
+
scrollOffset,
|
|
212
|
+
scrollOffset + planViewport,
|
|
213
|
+
);
|
|
214
|
+
const planLabel =
|
|
215
|
+
focus === "plan"
|
|
216
|
+
? theme.fg("accent", " [plan — ↑↓/Pg scroll, Tab → options]")
|
|
217
|
+
: theme.fg("dim", " [plan]");
|
|
218
|
+
add(planLabel);
|
|
219
|
+
for (const line of visible) {
|
|
220
|
+
add(theme.fg("text", ` ${line}`));
|
|
221
|
+
}
|
|
222
|
+
if (planLines.length > planViewport) {
|
|
223
|
+
add(
|
|
224
|
+
theme.fg(
|
|
225
|
+
"dim",
|
|
226
|
+
` … ${scrollOffset + 1}-${scrollOffset + visible.length} of ${planLines.length}`,
|
|
227
|
+
),
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
lines.push("");
|
|
186
231
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
232
|
+
const optLabel =
|
|
233
|
+
focus === "options"
|
|
234
|
+
? theme.fg("accent", " Options (↑↓, Enter, Tab → plan):")
|
|
235
|
+
: theme.fg("dim", " Options (Tab to focus):");
|
|
236
|
+
add(optLabel);
|
|
237
|
+
for (let i = 0; i < displayOptions.length; i++) {
|
|
238
|
+
const opt = displayOptions[i];
|
|
239
|
+
const focused = focus === "options" && i === optionIndex;
|
|
240
|
+
const prefix = focused ? theme.fg("accent", "> ") : " ";
|
|
241
|
+
const num = `${i + 1}. `;
|
|
242
|
+
if (focused) {
|
|
243
|
+
add(prefix + theme.fg("accent", `${num}${opt.title}`));
|
|
244
|
+
} else {
|
|
245
|
+
add(`${prefix}${theme.fg("text", `${num}${opt.title}`)}`);
|
|
246
|
+
}
|
|
247
|
+
if (opt.description) {
|
|
248
|
+
add(` ${theme.fg("muted", opt.description)}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
190
251
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
252
|
+
lines.push("");
|
|
253
|
+
add(theme.fg("dim", " Tab: plan ↔ options • Esc: cancel"));
|
|
254
|
+
|
|
255
|
+
if (useOverlay) {
|
|
256
|
+
add(theme.fg("accent", "─".repeat(width)));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
cachedLines = lines;
|
|
260
|
+
return lines;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
render,
|
|
265
|
+
invalidate: () => {
|
|
266
|
+
cachedLines = undefined;
|
|
267
|
+
},
|
|
268
|
+
handleInput,
|
|
269
|
+
};
|
|
270
|
+
},
|
|
271
|
+
useOverlay
|
|
272
|
+
? {
|
|
273
|
+
overlay: true,
|
|
274
|
+
overlayOptions: () => ({
|
|
275
|
+
anchor: "bottom-center",
|
|
276
|
+
width: "100%",
|
|
277
|
+
margin: { bottom: PLAN_APPROVAL_BOTTOM_RESERVE_LINES },
|
|
278
|
+
maxHeight: computePlanOverlayMaxHeight(overlayTermHeight),
|
|
279
|
+
}),
|
|
280
|
+
}
|
|
281
|
+
: undefined,
|
|
282
|
+
),
|
|
199
283
|
undefined,
|
|
200
284
|
);
|
|
201
285
|
|