Grok-style goal harness for Pi: expand a rough objective into a frozen plan, drive multi-turn pursuit, and harness-own verification so the model cannot self-certify.
Optional soft integration with @clanker-code/pi-subagents / upstream for planner/skeptic roles (degrades without it).
pi install npm:pi-goal-expander
# local:
# pi install /path/to/pi-goal-expander
# pi install git:github.com/clankercode/pi-goal-expanderSmoke:
pi -ne -e ./src/index.ts| Surface | Purpose |
|---|---|
/goal <objective> |
Start harness (research → expand plan → execute) |
/goal-expand <text> / /goal expand <text> |
Same as /goal (starts harness) |
/goal status | pause | resume | clear | help |
Lifecycle + help |
update_goal tool |
message / completed / blocked_reason |
goal_expand tool |
Same as /goal for the model |
- Start — create goal state under
.pi/goal/<id>/, inject a slim goal_set notice while the planner runs, then writeplan.md(planner subagent if available, else structural draft on disk only). When pi-subagents is available, the planner spawn setsinheritContext: true(session fork / parent conversation inheritance) and also hands off a compact parent-branch transcript into the planner prompt whensessionManager.getBranch()is available — so the planner sees prior chat/research, not only the objective string. - Execute kickoff — short message with objective + plan/evidence paths + steps (
triggerTurn: true). The full plan body stays on disk; kickoff does not paste the draft skeleton into the transcript - Execute — agent reads/rewrites
plan.mdas needed, works the checklist, keepsevidence/index.mdfilled - Verify —
update_goal({ completed: true })runs pre-verify + evidence-index gate (bias: not achieved without proof), then a blocking skeptic panel when pi-subagents is available (spawn → wait → aggregate before Achieved) - Continue / stall / complete — gaps replayed; same gap fingerprint twice → pause; verify cap → pause; success → receipt + user-visible completion summary (reload hint)
Statusline: ◎ plan · ◎ plan <agentId> (while planning) · ● active · 🔬 verify · ⏸ pause · ✓ done
While executing, call update_goal({ message }) at least for:
researched— codebase/context research doneimplementing— implementation underwaypre-complete— work done, about to request verify
Optional mid-checklist notes are fine. History stores these as typed progress events.
The harness emits custom session messages (customType: pi-goal-expander:event, usually display: false) with a details.kind field. Useful for dogfood logs and dashboards.
kind |
When |
|---|---|
session_restore |
Active goal reloaded on session_start |
goal_set |
Goal created; planner may still be running (display message) |
planning_started |
Phase → planning |
planning_completed |
Plan written; phase → executing |
planning_failed |
Planner hard-failed |
goal_start |
Execute kickoff injected |
progress |
update_goal({ message }) logged |
verify_started |
Verify round begins (may re-emit with panel agentIds) |
verify_not_achieved |
Verify failed; gaps recorded |
verify_achieved |
Verify passed |
goal_completed |
Goal status complete (after verify_achieved) |
verify_paused |
Verify cap hit → pause |
paused / resumed / cleared |
/goal pause|resume|clear |
blocked_attempt |
update_goal({ blocked_reason }) |
goal_complete_summary |
User-facing completion blurb (pi-goal-expander:complete, display true) |
Panel size is derived from plan.md Goal kind (see src/loop/verify-policy.ts):
| Goal kind | Default skeptic N |
|---|---|
analysis / research |
1 |
code-change |
3 |
| missing / unknown | config skepticN (default 3, clamp 1–5) |
Config skepticN is the fallback when kind is absent, not a hard override of kind defaults. Kind is read from the ## Goal kind section of the active plan at completed:true time.
| Condition | Outcome |
|---|---|
| No event bus / pi-subagents ping fails | Degraded path — Achieved only if preverify + evidence gates pass (no false “panel passed”) |
| Bus alive but all spawns fail, all waits timeout, or no usable verdict text | Fail-closed — NotAchieved with gap verifier panel unavailable |
| Partial verdicts | Aggregate what arrived (parseVerifierVerdict + aggregateVerdicts, bias-to-refute; malformed/empty = refute) |
Per-skeptic wait uses config subagentsTimeoutMs (default 600s). The panel is on the critical path: verify_achieved is not emitted until wait+aggregate finish or the fail-closed policy applies.
| Condition | Outcome |
|---|---|
| No bus / pi-subagents ping fails | Degraded structural draft (when soft mode); kickoff notes the real reason (ping_failed / unavailable) |
| Planner spawned but wait times out | Fail-closed — planning_failed, goal user_paused; planner agent stopped; no execute kickoff; no draft baseline as “success” |
| Structural draft write | Never overwrites a non-draft plan.md already on disk |
Planner wait uses config plannerTimeoutMs (default 30m), separate from panel subagentsTimeoutMs (default 10m). Lifecycle events planning_completed / planning_failed include plannerReason (ok | no_bus | ping_failed | wait_timeout | spawn_error | agent_failed | structural_fallback).
On Achieved the harness emits a user-visible notify + display summary (pi-goal-expander:complete) with objective, receipt path (when receipts enabled), and a generic reload hint (/reload if UI settings look stale). That is the last goal-owned UI action for the goal; further continuation / next-step injects for that goalId are suppressed. Other extensions may still emit after; the goal harness itself stays quiet.
| What | Where |
|---|---|
Goal store (plan.md, state.json, evidence/, receipts) |
<cwd>/.pi/goal/<id>/ by default |
| Override store root | PI_GOAL_ROOT (absolute path used as the goal root) |
| Override cwd used for store resolution | PI_GOAL_CWD (falls back to extension ctx.cwd, then process.cwd()) |
Edit scope is not limited to the goal store. Objectives often name files outside the session cwd (e.g. ~/.pi/agent/settings.json). Agents should treat .pi/goal/ as harness bookkeeping only; allowed write targets follow the objective.
Before completion succeeds, write:
.pi/goal/<id>/evidence/index.md
| Criterion | Artifact | Notes |
|-----------|----------|-------|
| 1 | tests/foo.test.ts | … |
| 2 | json:path/to/settings.json#powerline.cost.subscriptionDisplay=reported-cost | config assert |Artifact forms
- Path — any path-like string is checked for existence (
tests/…,src/…, absolute paths). - JSON assert —
json:<filePath>#<dotted.path>=<expected>reads the file, walks the dotted path, and requires an exact value match. Completion fails if the assertion fails even when the file exists (useful for config/settings goals).
Draft plan gate: update_goal(completed:true) returns NotAchieved with plan not expanded beyond draft if plan.md still matches the structural expand skeleton. Rewrite the plan with real criteria before completing.
npm install
just checkHarness contract test (tests/harness-contract.test.ts): memory bus + installMockSubagentsRpc asserts the dogfood event order goal_set → planning events → goal_start → verify_started → complete (no live LLM).
See RELEASE.md:
just release patch # or minor | major | 0.2.0docs/superpowers/specs/2026-07-20-goal-harness-design.md
Unlicense (public domain).