Skip to content

clankercode/pi-goal-expander

Repository files navigation

pi-goal-expander

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).

Install

pi install npm:pi-goal-expander
# local:
# pi install /path/to/pi-goal-expander
# pi install git:github.com/clankercode/pi-goal-expander

Smoke:

pi -ne -e ./src/index.ts

Surfaces

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

How it works

  1. Start — create goal state under .pi/goal/<id>/, inject a slim goal_set notice while the planner runs, then write plan.md (planner subagent if available, else structural draft on disk only). When pi-subagents is available, the planner spawn sets inheritContext: true (session fork / parent conversation inheritance) and also hands off a compact parent-branch transcript into the planner prompt when sessionManager.getBranch() is available — so the planner sees prior chat/research, not only the objective string.
  2. 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
  3. Execute — agent reads/rewrites plan.md as needed, works the checklist, keeps evidence/index.md filled
  4. Verifyupdate_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)
  5. 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

Progress milestones

While executing, call update_goal({ message }) at least for:

  • researched — codebase/context research done
  • implementing — implementation underway
  • pre-complete — work done, about to request verify

Optional mid-checklist notes are fine. History stores these as typed progress events.

Lifecycle 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)

Verify policy (goal kind → skeptic N)

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.

Panel timeout / infra policy

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-closedNotAchieved 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.

Planner timeout / degrade policy

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-closedplanning_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).

Completion UX

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.

Goal state location vs edit scope

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.

Evidence

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 assertjson:<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.

Development

npm install
just check

Harness contract test (tests/harness-contract.test.ts): memory bus + installMockSubagentsRpc asserts the dogfood event order goal_set → planning events → goal_startverify_started → complete (no live LLM).

Release

See RELEASE.md:

just release patch   # or minor | major | 0.2.0

Design

docs/superpowers/specs/2026-07-20-goal-harness-design.md

License

Unlicense (public domain).

About

Expand a rough goal into concrete objective, acceptance criteria, subgoals, and open questions for Pi sessions.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors