Commit Graph

6 Commits

Author SHA1 Message Date
Michael Ramos 776fcb427b fix(pi): append-only phase framing so plan transitions keep the prompt cache (#1381)
The context filter stripped delivered framing from mid-history at phase
transitions, shifting every later message and invalidating the provider's
cached prefix (88 of 119 messages re-billed in the reporter's session).
History is now append-only: delivered framing stays, and stale instructions
are neutralized by superseding language in the phase templates plus the
existing plan-mode-off countermand.

Fixes #1380
2026-08-23 10:35:03 -07:00
Michael Ramos a5f9937f9c fix(pi): never touch Pi's system prompt; phase framing as conversation messages (#922) (#1269)
* fix(pi): never touch Pi's system prompt; deliver phase framing as messages (#922)

The extension replaced Pi's system prompt with its phase framing during
planning and execution, dropping AGENTS.md context, the skills catalog,
tools guidance, and user append text, and re-templating the todo list
into the system prompt busted the provider's prompt-cache prefix on
every checklist update.

Plannotator now never returns or modifies systemPrompt (approach
suggested by Karrq on the PR). Phase framing is delivered exactly once
per phase entry as a hidden plannotator-framing conversation message,
execution progress rides in small per-turn plannotator-context todo
messages, and a phase-aware context filter keeps only the newest framing
for the current phase (idle still clears everything). Cache-busting
reduces to conversation-suffix appends plus one history adjustment per
phase transition.

BREAKING CHANGE: the Pi plan-mode toggle command is renamed from
/plannotator to /plannotator-plan-mode with no alias, and the
phases.*.systemPrompt config key is retired in favor of
phases.*.instructions (a phase-entry message template); old systemPrompt
keys are ignored with a session-start warning.

* docs: root README uses the renamed plannotator-plan-mode command

* fix(pi): make the framing latch survive compaction and tree navigation (#922)

Review follow-ups on the message-based framing design:

- session_compact reopens the framing latch: compaction can summarize
  away the delivered framing message, so the next prompt re-delivers it
  (the context filter keeps only the newest copy if the old one survived
  in the kept tail).
- session_tree re-derives phase, latch, and checklist state from the new
  active path via the restore logic session_start uses (now shared as
  resyncPhaseFromSession and reading getBranch(), the active path,
  instead of the whole append-only entry file). A path with no
  plannotator state means idle.
- The per-turn todo message restates the [DONE:n] convention in one line
  so the protocol survives between a compaction and re-delivery.
- Warn at session start when the bundled plannotator.json is missing, so
  a packaging regression cannot silently produce a rule-less planning
  phase.
- Tests pin the persistState payload on both sides of the latch, cover
  compaction re-delivery (exactly once) and tree-switch resync, and the
  harnesses expose getBranch.
2026-08-11 13:15:39 -07:00
Reveck 26a5314a99 feat(pi): add external plan execution handoff (#1126)
* feat(pi): add external plan execution handoff

* fix(pi): release phase-added tools on external plan handoff

#1124 made every idle-exit path hand back the tools the phase added, but
the external handoff path introduced here restored the saved model and
thinking level without releasing them. Approving a plan in
executionMode "external" therefore leaked the planning tool scope (grep,
find, ls, plannotator_submit_plan) into the idle session.

Extract the shared exit sequence into returnToIdle() and use it from all
three idle transitions (manual exit, execution completion, handoff), so
a new exit path cannot miss a step again. Callers keep their own
messaging, session entries, and events.

Also add a default-mode parity test: with executionMode unset, approval
enters executing, emits no plannotator:plan-approved, appends the
plannotator-execute entry, and still sends the continuation message.

Claude-Session: https://claude.ai/code/session_01H5KQWqXqjrPxyxUNso1QHS

* chore(pi): warn on unknown executionMode and document the handoff payload

An unrecognized executionMode was silently dropped, so a typo like
"handoff" left the session in automatic execution with no explanation.
Warn through the existing config warning channel (the same one malformed
JSON uses) and keep the automatic fallback.

README: note that planFilePath is relative to cwd and should be resolved
against it, and that companions can subscribe with the raw channel
string without importing Plannotator internals, matching how the
plannotator:request channel is already described.

Claude-Session: https://claude.ai/code/session_01H5KQWqXqjrPxyxUNso1QHS

---------

Co-authored-by: Michael Ramos <support@plannotator.ai>
2026-07-26 23:25:00 -07:00
Peete d26289060d fix(pi): preserve extension tool selections (#1124)
* fix(pi): preserve extension tool selections

* fix(pi): release phase tools when the plan completes

The agent_end plan-completion path dropped back to idle via
restoreSavedState but never called releaseAddedPhaseTools(), so tools
Plannotator activated for the executing phase stayed active in idle and
a stale phaseAddedTools list was persisted. Mirror exitToIdle.

Claude-Session: https://claude.ai/code/session_01H5KQWqXqjrPxyxUNso1QHS

* fix(pi): keep grep/find/ls in the default planning tool set

Dropping them from the planning phase profile silently removed native
search from default planning sessions. Restore them as default planning
phase tools so they now flow through the new tracking mechanism: they
are recorded in phaseAddedTools and released on phase exit, and a
discovery tool another extension already activated is neither claimed
nor removed. A user's own planning.activeTools still overrides them.

Claude-Session: https://claude.ai/code/session_01H5KQWqXqjrPxyxUNso1QHS

* fix(pi): always keep the submit tool active during planning

Planning tools now come purely from the resolved profile's activeTools,
which uses replace semantics: a phases.planning.activeTools in
~/.pi/agent/plannotator.json or cwd/.pi/plannotator.json supersedes the
built-in list wholesale. Pi's setActiveToolsByName then replaces the
session's tool list outright, so such a config silently dropped
plannotator_submit_plan while the planning system prompt kept telling the
model to call it - a dead end with no way to submit a plan.

Union PLAN_SUBMIT_TOOL into the configured list for the planning phase
only (deduped if the config already lists it). It flows through
phaseAddedTools like any other addition, so it is released normally on
phase exit. Other tools are left to the user: overriding
planning.activeTools is a deliberate choice of tool set, and only the
submit tool is contractually required for the phase to function.

Also corrects the README's "extra tools ... additive" wording, which
described the old merge behavior.

Claude-Session: https://claude.ai/code/session_01H5KQWqXqjrPxyxUNso1QHS

---------

Co-authored-by: Michael Ramos <support@plannotator.ai>
Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-07-26 22:28:11 -07:00
Michael Ramos c80ace825a fix(pi): let agent submit any markdown plan file by path (#595)
* fix(pi): let agent submit any markdown plan file by path

Removes all configured plan-file state (module var, --plan-file flag,
/plannotator-set-file command, interactive path prompt). The agent now
writes its plan as a markdown file anywhere inside the working directory
and calls plannotator_submit_plan with the file path.

During planning, the write gate allows any .md / .mdx file inside cwd
(with traversal/absolute-escape rejection) instead of a single configured
path. plannotator_submit_plan gains a required filePath parameter, which
is validated, stat-checked, and read. Version history in ~/.plannotator
continues to key off plan content so naming is free-form without losing
version linking.

For provenance purposes, this commit was AI assisted.

* refactor(pi): drop isSubmitPathAllowed alias

isSubmitPathAllowed was a pure pass-through to isPlanWritePathAllowed
with no plausible reason to diverge. Use the write-gate helper directly
from submit_plan and drop the alias.

For provenance purposes, this commit was AI assisted.

* fix(pi): update bundled planning prompt for filePath-based submit

The shipped plannotator.json planning prompt still referenced
${planFilePath} and instructed the agent to call plannotator_submit_plan
with no arguments. After the submit tool gained a required filePath
parameter, default sessions hit the stale prompt and submits failed.
Rewritten to match the new flow: agent picks its own plan filename and
passes it to plannotator_submit_plan.

For provenance purposes, this commit was AI assisted.

* fix(pi): persist state on plan denial

Mirror the approve branches by calling persistState() before returning
on the deny path. Without this, a Pi restart between denial and the
agent's next submit would lose the lastSubmittedPath in memory, forcing
the agent to re-pick a plan file instead of resuming on the same one.

For provenance purposes, this commit was AI assisted.
2026-04-21 17:50:16 -07:00
Stefan Kaufmann fc4e634789 feat(pi): support phase config files (#446)
* allow Plannotator phase configs in pi-extension

* fix tool name
2026-03-31 15:22:29 -07:00