ultimate-pi 0.23.0 → 0.25.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/.pi/extensions/agt-prompt-guard.ts +20 -6
- package/.pi/extensions/harness-ask-user.ts +14 -5
- package/.pi/extensions/harness-auto-compact.ts +94 -0
- package/.pi/extensions/harness-debate-tools.ts +59 -4
- package/.pi/extensions/harness-live-widget.ts +25 -0
- package/.pi/extensions/harness-plan-approval.ts +65 -15
- package/.pi/extensions/harness-plan-orchestration.ts +140 -0
- package/.pi/extensions/harness-run-context.ts +501 -48
- package/.pi/extensions/harness-telemetry.ts +1 -0
- package/.pi/extensions/harness-web-tools.ts +1 -0
- package/.pi/extensions/policy-gate.ts +9 -0
- package/.pi/extensions/trace-recorder.ts +1 -0
- package/.pi/harness/agents.manifest.json +1 -1
- package/.pi/harness/docs/adrs/0056-agent-native-speed-wiring.md +26 -0
- package/.pi/harness/env.harness.template +14 -0
- package/.pi/harness/specs/harness-posthog-event.schema.json +2 -0
- package/.pi/harness/specs/sentrux-signal.schema.json +1 -1
- package/.pi/lib/harness-auto-approve.ts +140 -0
- package/.pi/lib/harness-auto-compact-policy.ts +85 -0
- package/.pi/lib/harness-cocoindex-refresh.ts +82 -2
- package/.pi/lib/harness-phase-telemetry.ts +81 -0
- package/.pi/lib/harness-phase-worker.ts +23 -0
- package/.pi/lib/harness-plan-fsm.ts +162 -0
- package/.pi/lib/harness-plan-route.ts +134 -0
- package/.pi/lib/harness-posthog.ts +6 -1
- package/.pi/lib/harness-remediation.ts +79 -0
- package/.pi/lib/harness-repair-brief.ts +2 -2
- package/.pi/lib/harness-review-parallel.ts +18 -0
- package/.pi/lib/harness-run-context.ts +119 -72
- package/.pi/lib/harness-spawn-budget.ts +32 -4
- package/.pi/lib/harness-spawn-stall-detector.ts +106 -0
- package/.pi/lib/harness-spawn-topology.ts +50 -1
- package/.pi/lib/harness-subagent-precheck.ts +41 -0
- package/.pi/lib/harness-subagent-progress.ts +119 -0
- package/.pi/lib/harness-subagent-timeout.ts +81 -0
- package/.pi/lib/harness-subagents-bridge.ts +94 -8
- package/.pi/lib/harness-ui-state.ts +5 -0
- package/.pi/lib/harness-vcc-settings.ts +36 -0
- package/.pi/lib/plan-approval-readiness.ts +9 -5
- package/.pi/lib/plan-debate-eligibility-snapshot.ts +90 -0
- package/.pi/lib/plan-debate-eligibility.ts +16 -9
- package/.pi/lib/plan-debate-focus.ts +23 -11
- package/.pi/lib/plan-debate-gate.ts +94 -31
- package/.pi/lib/plan-debate-round-status.ts +23 -8
- package/.pi/lib/plan-debate-wall-clock.ts +57 -0
- package/.pi/lib/plan-headless-ux.ts +598 -0
- package/.pi/lib/plan-human-gates.ts +24 -85
- package/.pi/lib/plan-messenger.ts +3 -3
- package/.pi/lib/plan-review-gate.ts +56 -0
- package/.pi/prompts/harness-abort.md +1 -0
- package/.pi/prompts/harness-auto.md +1 -1
- package/.pi/prompts/harness-clear.md +6 -6
- package/.pi/prompts/harness-plan.md +15 -2
- package/.pi/prompts/harness-review.md +26 -12
- package/.pi/scripts/harness-e2e-workflow.mjs +94 -0
- package/.pi/scripts/harness-project-toggle.mjs +1 -1
- package/.pi/scripts/harness-sentrux-cli.mjs +26 -1
- package/.pi/scripts/harness-sentrux-report.mjs +41 -6
- package/CHANGELOG.md +16 -0
- package/README.md +2 -2
- package/package.json +1 -1
- package/vendor/pi-subagents/src/subagents.ts +41 -10
|
@@ -31,7 +31,17 @@ function usage() {
|
|
|
31
31
|
process.exit(2);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
function parseSentruxTimeoutMs() {
|
|
35
|
+
const raw = process.env.HARNESS_SENTRUX_TIMEOUT_MS;
|
|
36
|
+
if (raw?.trim()) {
|
|
37
|
+
const parsed = Number.parseInt(raw, 10);
|
|
38
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
39
|
+
}
|
|
40
|
+
return 300_000;
|
|
41
|
+
}
|
|
42
|
+
|
|
34
43
|
function runSentrux(args, projectRoot) {
|
|
44
|
+
const timeoutMs = parseSentruxTimeoutMs();
|
|
35
45
|
return new Promise((resolve, reject) => {
|
|
36
46
|
const child = spawn("sentrux", args, {
|
|
37
47
|
cwd: projectRoot,
|
|
@@ -39,6 +49,11 @@ function runSentrux(args, projectRoot) {
|
|
|
39
49
|
});
|
|
40
50
|
let stdout = "";
|
|
41
51
|
let stderr = "";
|
|
52
|
+
let timedOut = false;
|
|
53
|
+
const timer = setTimeout(() => {
|
|
54
|
+
timedOut = true;
|
|
55
|
+
child.kill("SIGTERM");
|
|
56
|
+
}, timeoutMs);
|
|
42
57
|
child.stdout?.on("data", (c) => {
|
|
43
58
|
stdout += c.toString();
|
|
44
59
|
});
|
|
@@ -46,6 +61,7 @@ function runSentrux(args, projectRoot) {
|
|
|
46
61
|
stderr += c.toString();
|
|
47
62
|
});
|
|
48
63
|
child.on("error", (err) => {
|
|
64
|
+
clearTimeout(timer);
|
|
49
65
|
if (err?.code === "ENOENT") {
|
|
50
66
|
reject(
|
|
51
67
|
Object.assign(new Error("sentrux not installed"), { code: 127 }),
|
|
@@ -55,7 +71,13 @@ function runSentrux(args, projectRoot) {
|
|
|
55
71
|
reject(err);
|
|
56
72
|
});
|
|
57
73
|
child.on("close", (code) => {
|
|
58
|
-
|
|
74
|
+
clearTimeout(timer);
|
|
75
|
+
resolve({
|
|
76
|
+
code: timedOut ? 124 : (code ?? 1),
|
|
77
|
+
stdout,
|
|
78
|
+
stderr,
|
|
79
|
+
timedOut,
|
|
80
|
+
});
|
|
59
81
|
});
|
|
60
82
|
});
|
|
61
83
|
}
|
|
@@ -104,11 +126,13 @@ function buildSignal(runId, report) {
|
|
|
104
126
|
run_id: runId || "unknown",
|
|
105
127
|
check_pass: check.check_pass,
|
|
106
128
|
gate_status:
|
|
107
|
-
gate.status === "
|
|
108
|
-
? "
|
|
109
|
-
: gate.status === "
|
|
110
|
-
? "
|
|
111
|
-
: "
|
|
129
|
+
gate.status === "timeout"
|
|
130
|
+
? "timeout"
|
|
131
|
+
: gate.status === "degraded"
|
|
132
|
+
? "degraded"
|
|
133
|
+
: gate.status === "pass"
|
|
134
|
+
? "pass"
|
|
135
|
+
: "skipped",
|
|
112
136
|
quality_signal_summary: summaryParts.join(" | ") || undefined,
|
|
113
137
|
recorded_at: report.captured_at,
|
|
114
138
|
phase: "review",
|
|
@@ -130,6 +154,7 @@ async function captureReport(projectRoot) {
|
|
|
130
154
|
|
|
131
155
|
const checkRun = await runSentrux(["check", projectRoot], projectRoot);
|
|
132
156
|
const gateRun = await runSentrux(["gate", projectRoot], projectRoot);
|
|
157
|
+
const timedOut = Boolean(checkRun.timedOut || gateRun.timedOut);
|
|
133
158
|
|
|
134
159
|
const checkFiltered = filterSentruxOutputLines(
|
|
135
160
|
`${checkRun.stdout}\n${checkRun.stderr}`,
|
|
@@ -160,6 +185,15 @@ async function captureReport(projectRoot) {
|
|
|
160
185
|
|
|
161
186
|
if (checkRun.code === 127) throw Object.assign(new Error("sentrux not installed"), { code: 127 });
|
|
162
187
|
|
|
188
|
+
if (timedOut) {
|
|
189
|
+
check.check_pass = false;
|
|
190
|
+
gate.status = "timeout";
|
|
191
|
+
gate.degraded_reasons = [
|
|
192
|
+
...(gate.degraded_reasons ?? []),
|
|
193
|
+
`sentrux CLI exceeded HARNESS_SENTRUX_TIMEOUT_MS (${parseSentruxTimeoutMs()}ms)`,
|
|
194
|
+
];
|
|
195
|
+
}
|
|
196
|
+
|
|
163
197
|
return {
|
|
164
198
|
schema_version: "1.0.0",
|
|
165
199
|
captured_at,
|
|
@@ -170,6 +204,7 @@ async function captureReport(projectRoot) {
|
|
|
170
204
|
check,
|
|
171
205
|
gate,
|
|
172
206
|
exit_codes: { check: checkRun.code, gate: gateRun.code },
|
|
207
|
+
timed_out: timedOut || undefined,
|
|
173
208
|
};
|
|
174
209
|
}
|
|
175
210
|
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
## [v0.25.0] — 2026-06-07
|
|
7
|
+
|
|
8
|
+
### ✨ Features
|
|
9
|
+
|
|
10
|
+
- Wire agent-native speed program: `parallel_probes` end-to-end, eligibility snapshot, plan FSM (`harness_plan_next_action`), synthesizer routing, auto-approve policy, per-phase spawn caps, review parallel default, 50% VCC auto-compact, ADR 0056.
|
|
11
|
+
|
|
12
|
+
### 🐛 Fixes
|
|
13
|
+
|
|
14
|
+
- Headless QA E2E: seed planning-context for smoke auto-approve, finalize plan on `agent_end`, write smoke ISO for `/harness-auto`, and exit via `ctx.abort()` without kill-switch false failures.
|
|
15
|
+
|
|
16
|
+
## [v0.24.0] — 2026-06-06
|
|
17
|
+
|
|
18
|
+
### ✨ Features
|
|
19
|
+
|
|
20
|
+
- Cut harness workflow latency with phase-aware subagent timeouts, debate wall-clock caps, ccc index debounce, optional parallel review spawns, progress UI with stall detection, and PostHog phase telemetry.
|
|
21
|
+
|
|
6
22
|
## [v0.23.0] — 2026-05-28
|
|
7
23
|
|
|
8
24
|
### ✨ Features
|
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ If `/harness-review` returns `implementation_gap`, run:
|
|
|
77
77
|
| `/harness-steer [--attempt N]` | Post-review repair pass for `implementation_gap`; executor reads `repair-brief.yaml`, then you re-run `/harness-review`. |
|
|
78
78
|
| `/harness-abort [reason]` | Safely aborts the active run, clears plan readiness, and re-locks mutation until a fresh plan is approved. |
|
|
79
79
|
|
|
80
|
-
| `/harness-clear` | Deletes
|
|
80
|
+
| `/harness-clear` | Deletes all `.pi/harness/runs/<run_id>/` directories, including the active run, after mandatory confirmation; non-affirmative/outage confirmation paths are no-op. |
|
|
81
81
|
| `/harness-trace [--run <id>] [--phase plan\|execute\|evaluate\|adversary\|merge]` | Summarizes run traces and artifact handoffs for replay/forensics. |
|
|
82
82
|
| `/harness-incident --trigger <reason> [--run <id>] [--severity low\|med\|high\|critical]` | Records incident, rollback, and override trail for harness failures. |
|
|
83
83
|
| `/harness-sentrux-steward [--run <id>]` | Ad-hoc architectural intent review for Sentrux manifest/rule alignment. |
|
|
@@ -130,7 +130,7 @@ Subagents run isolated from the parent session. They persist canonical YAML thro
|
|
|
130
130
|
| Need to inspect handoff | Run `/harness-trace` or inspect `.pi/harness/runs/<run_id>/`. |
|
|
131
131
|
| Need to restart safely | Run `/harness-abort [reason]`, then create a fresh plan. |
|
|
132
132
|
|
|
133
|
-
| Need to prune old run history safely | Run `/harness-clear`;
|
|
133
|
+
| Need to prune old run history safely | Run `/harness-clear`; all run directories, including the active run, are eligible and confirmation failure/cancel deletes nothing. |
|
|
134
134
|
| Review says `implementation_gap` | Run `/harness-steer`, then `/harness-review`. |
|
|
135
135
|
| Review says `plan_gap` | Revise with `/harness-plan "<updated task>"`. |
|
|
136
136
|
| Sentrux missing | Install/configure Sentrux or keep it skipped; harness verification still reports the status. |
|
package/package.json
CHANGED
|
@@ -69,10 +69,18 @@ export interface HarnessSubagentsOptions {
|
|
|
69
69
|
) => Promise<SpawnAuthForward | undefined>;
|
|
70
70
|
onSpawnStart?: (harnessAgentCount: number) => void;
|
|
71
71
|
onSpawnEnd?: (harnessAgentCount: number) => void;
|
|
72
|
+
/** Phase-aware default when tool params omit timeoutMs (harness bridge). */
|
|
73
|
+
resolveDefaultTimeoutMs?: (
|
|
74
|
+
params: Record<string, unknown>,
|
|
75
|
+
agents: AgentConfig[],
|
|
76
|
+
ctx: ExtensionContext,
|
|
77
|
+
) => number | undefined;
|
|
72
78
|
onCompleted?: (details: {
|
|
73
79
|
agents: string[];
|
|
74
80
|
mode: string;
|
|
75
81
|
durationMs: number;
|
|
82
|
+
timedOut?: boolean;
|
|
83
|
+
stop_reason?: "timeout" | "complete" | "aborted";
|
|
76
84
|
}) => void;
|
|
77
85
|
truncateDetails?: boolean;
|
|
78
86
|
}
|
|
@@ -1387,7 +1395,13 @@ export function createSubagentsExtension(
|
|
|
1387
1395
|
const agentScope: AgentScope = params.agentScope ?? defaultScope;
|
|
1388
1396
|
const discovery = discoverAgents(ctx.cwd, agentScope, packageRoot);
|
|
1389
1397
|
const agents = discovery.agents;
|
|
1390
|
-
const
|
|
1398
|
+
const resolvedDefault = options.resolveDefaultTimeoutMs?.(
|
|
1399
|
+
params as Record<string, unknown>,
|
|
1400
|
+
agents,
|
|
1401
|
+
ctx,
|
|
1402
|
+
);
|
|
1403
|
+
const defaultTimeoutMs =
|
|
1404
|
+
params.timeoutMs ?? resolvedDefault ?? ENV_TIMEOUT_MS;
|
|
1391
1405
|
const effectiveConfirmProjectAgents =
|
|
1392
1406
|
params.confirmProjectAgents ?? defaultConfirm;
|
|
1393
1407
|
const harnessAgents = collectHarnessAgents(params);
|
|
@@ -1430,6 +1444,7 @@ export function createSubagentsExtension(
|
|
|
1430
1444
|
}
|
|
1431
1445
|
|
|
1432
1446
|
options.onSpawnStart?.(harnessAgents.length);
|
|
1447
|
+
let spawnTimedOut = false;
|
|
1433
1448
|
try {
|
|
1434
1449
|
const mode = modeInfo(params);
|
|
1435
1450
|
if (mode.modeCount !== 1 || (params.aggregator && !mode.hasTasks)) {
|
|
@@ -1475,15 +1490,25 @@ export function createSubagentsExtension(
|
|
|
1475
1490
|
};
|
|
1476
1491
|
}
|
|
1477
1492
|
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1493
|
+
let toolResult: Awaited<
|
|
1494
|
+
ReturnType<typeof executeSingleMode>
|
|
1495
|
+
>;
|
|
1496
|
+
if (mode.hasChain) toolResult = await executeChainMode(execCtx);
|
|
1497
|
+
else if (mode.hasTasks) toolResult = await executeParallelMode(execCtx);
|
|
1498
|
+
else if (mode.hasSingle) toolResult = await executeSingleMode(execCtx);
|
|
1499
|
+
else {
|
|
1500
|
+
const available = agents.map((a) => `${a.name} (${a.source})`).join(", ") || "none";
|
|
1501
|
+
return {
|
|
1502
|
+
content: [{ type: "text" as const, text: `Invalid parameters. Available agents: ${available}` }],
|
|
1503
|
+
details: makeDetails("single")([]),
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1506
|
+
const allResults = [
|
|
1507
|
+
...(toolResult.details?.results ?? []),
|
|
1508
|
+
...(toolResult.details?.aggregator ? [toolResult.details.aggregator] : []),
|
|
1509
|
+
];
|
|
1510
|
+
spawnTimedOut = allResults.some((r) => r.timedOut === true);
|
|
1511
|
+
return toolResult;
|
|
1487
1512
|
} finally {
|
|
1488
1513
|
options.onSpawnEnd?.(harnessAgents.length);
|
|
1489
1514
|
const mode = params.chain?.length
|
|
@@ -1495,6 +1520,12 @@ export function createSubagentsExtension(
|
|
|
1495
1520
|
agents: harnessAgents,
|
|
1496
1521
|
mode,
|
|
1497
1522
|
durationMs: Date.now() - startedAt,
|
|
1523
|
+
timedOut: spawnTimedOut,
|
|
1524
|
+
stop_reason: spawnTimedOut
|
|
1525
|
+
? "timeout"
|
|
1526
|
+
: signal?.aborted
|
|
1527
|
+
? "aborted"
|
|
1528
|
+
: "complete",
|
|
1498
1529
|
});
|
|
1499
1530
|
}
|
|
1500
1531
|
},
|