@kky42/pi-hermes-goal

Pi extension providing Hermes-style persistent /goal loop with judge-model evaluation, subgoals, and turn budget enforcement

Packages

Package details

extension

Install @kky42/pi-hermes-goal from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@kky42/pi-hermes-goal
Package
@kky42/pi-hermes-goal
Version
1.0.2
Published
May 25, 2026
Downloads
not available
Author
kky42
License
ISC
Types
extension
Size
84.8 KB
Dependencies
0 dependencies · 4 peers
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

@kky42/pi-hermes-goal

Pi extension providing a Hermes-style persistent /goal loop. Set a goal, and the agent keeps working across turns — a judge model evaluates each response and decides whether to continue or stop. No hidden tools, no system-prompt mutation. Just normal user messages in a loop.

Install

pi install npm:@kky42/pi-hermes-goal

How it works

  1. You set a goal with /goal <text>
  2. The agent starts working immediately — the goal text becomes the first user message
  3. After each turn, a judge model reads the agent's response and decides: {"done": true} or {"done": false}
  4. If not done, a continuation prompt is injected as a normal user message and the agent keeps going
  5. The loop stops when the judge says done, you pause/clear, or the turn budget runs out

The agent never sees goal-management tools. There are no create_goal, get_goal, or update_goal tools. The loop is entirely control-plane — the agent just sees user messages.

Commands

/goal <text>

Set a new goal and start working immediately.

/goal refactor the auth module to use the new token format
/goal --max-turns 10 write tests for all public API endpoints

Options:

  • --max-turns N — override the default turn budget (default: 20)

/goal status

Show the current goal state.

⊙ Goal (active, 3/20 turns): refactor the auth module
⏸ Goal (paused, 5/20 turns — user-paused): write integration tests
✓ Goal done (12/20 turns): add rate limiting middleware

/goal pause

Pause auto-continuation without clearing state. The goal can be resumed later.

/goal resume

Resume a paused goal. Resets the turn counter and re-activates the loop.

/goal clear

Clear the current goal and stop the loop.

Subgoals

Add mid-loop acceptance criteria that the judge will also check.

/subgoal <text>

/subgoal make sure all error messages are user-friendly
/subgoal add JSDoc comments to every exported function

/subgoal status

List current subgoals with their 1-based indices.

/subgoal remove N

Remove a specific subgoal by index.

/subgoal clear

Remove all subgoals while keeping the original goal.

Judge model

The judge is an auxiliary model call that happens after every agent turn. It sees:

  • The original goal text
  • Any subgoals
  • The agent's most recent response
  • Current time

It replies with a single JSON object:

{"done": true, "reason": "The response explicitly reports completion."}

The extension uses your session's current model as the judge by default. A strict JSON parsing contract handles fenced, embedded, or malformed judge output — three consecutive parse failures auto-pause the goal with a diagnostic.

Turn budget

Default: 20 turns. When the budget is exhausted, the goal pauses with a clear message:

⏸ Goal paused — 20/20 turns used. Use /goal resume to keep going, or /goal clear to stop.

No wrap-up prompt is sent — it just pauses. Resume resets the counter.

Interruption handling

  • Ctrl+C / abort: pauses the goal immediately with reason user-interrupted. No partial output is judged.
  • User messages: real user input takes priority over queued continuations
  • Empty responses: skipped (not judged)

E2E tests

Two real-model E2E tests verify the goal loop against deepseek/deepseek-v4-flash with reasoning high:

npm run e2e:wait   # agent must run ≥2min before claiming done
npm run e2e:count  # agent counts 1→10, one number per turn

Override model and reasoning:

npm run e2e:count -- --model openai/gpt-5.5 --thinking low

Package structure

src/
  core.ts              # goal state machine, transitions, subgoals
  judge.ts             # judge prompt templates, JSON parsing
  extension.ts         # Pi extension wiring, commands, turn_end hook
  e2e-runner.ts        # CLI builder shared by E2E scripts
  e2e-analysis.ts      # wait-test: timing analysis from session JSONL
  counting-analysis.ts # count-test: number-sequence analysis
scripts/
  run-wait-e2e.mjs     # wait E2E: spawn pi, verify ≥2min elapsed
  run-counting-e2e.mjs # count E2E: spawn pi, verify 1→10 sequence
tests/
  core.test.ts         # continuation prompts, subgoals block
  transitions.test.ts  # state machine: done, budget pause, parse failures
  timing-goals.test.ts # time-qualified goal enforcement
  subgoal.test.ts      # add, remove, clear subgoals
  judge.test.ts        # parser robustness
  extension.test.ts    # integration: faux provider, full goal loop