Files
oh-my-pi/packages/coding-agent
roboomp ce4f5b8615 fix(advisor): enforced one-advise-per-update + dedupe + noise filter at the enqueueAdvice boundary
The advisor system prompt told the watcher model "at most one advise per
update" and "NEVER send the same advice twice", but nothing enforced
either rule. Issue #3520 captured a session where the advisor emitted
309 advise() calls covering 92 unique notes - 114x "Stop.", 52x "No
issue; continue.", 41x "Done." - landing 309 <advisory severity="blocker">
injections in the primary transcript and destabilizing the watched agent
after the task was already complete.

New AdvisorEmissionGuard sits on AgentSession#enqueueAdvice and:

- Normalizes notes (lowercase, NFKC, punctuation->space, trim) so every
  "Stop.", "*Stop*", "STOP!" variant keys to the same canonical form.
- Drops a small allowlist of content-free self-talk filler (stop, done,
  complete, no issue continue, lgtm, nothing to add, no further input,
  carry on, ...) - silence is the correct expression of "no concerns".
- Dedupes by exact normalized text across the session, FIFO-bounded at
  4096 entries.
- Rate-limits to one accepted advise per advisor model prompt cycle. The
  runtime calls host.beginAdvisorUpdate?.() before each agent.prompt(),
  so the new batch starts with a fresh budget. Suppressed calls don't
  consume the budget - a noise call never displaces a real concern.

Reset on advisor reset (compaction, session switch, /new) so a re-primed
reviewer can re-raise old concerns against the rewritten transcript.

Suppression is invisible to the advisor model: AdviseTool still returns
"Recorded." for a dropped call. Surfacing "suppressed" risks the model
rephrasing the same useless note ("Stop." -> "Halt." -> "Cease.") to
bypass the dedupe.

Fixes #3520
2026-06-26 02:48:27 +00:00
..
2026-06-17 04:37:39 +02:00
2026-06-25 22:45:00 +02:00

@oh-my-pi/pi-coding-agent

Core implementation package for the omp coding agent in the oh-my-pi monorepo.

For installation, setup, provider configuration, model roles, slash commands, and full CLI reference, see:

Package-specific references:

Memory backends

The agent supports three mutually-exclusive memory backends, selected via the memory.backend setting (Settings → Memory tab, or ~/.omp/config.yml):

  • off (default) — no memory subsystem runs.
  • local — existing rollout-summarisation pipeline; writes memory_summary.md and consolidated artifacts under the agent dir.
  • hindsight — talks to a Hindsight server (Cloud or self-hosted Docker), retains transcripts every Nth user turn, recalls memories on the first turn of a session, and exposes retain, recall, and reflect.

Hindsight quickstart

  1. Run a Hindsight server (Cloud or docker run -p 8888:8888 ghcr.io/vectorize-io/hindsight:latest).
  2. Set memory.backend = "hindsight" and hindsight.apiUrl = "http://localhost:8888" (or your Cloud URL).
  3. Optional environment overrides (env wins over settings):
    • HINDSIGHT_API_URL, HINDSIGHT_API_TOKEN — connection
    • HINDSIGHT_BANK_ID, HINDSIGHT_DYNAMIC_BANK_ID, HINDSIGHT_AGENT_NAME — bank addressing
    • HINDSIGHT_AUTO_RECALL, HINDSIGHT_AUTO_RETAIN, HINDSIGHT_RETAIN_MODE — lifecycle
    • HINDSIGHT_RECALL_BUDGET, HINDSIGHT_RECALL_MAX_TOKENS — recall sizing
    • HINDSIGHT_BANK_MISSION, HINDSIGHT_DEBUG

Switching backends mid-session is honoured on the next system-prompt rebuild and the next /memory slash command. Existing users with memories.enabled = true|false are migrated to memory.backend = "local"|"off" exactly once on first launch.