Add safety/reporting prompt guidance and structured compaction#2
Open
bajajra wants to merge 57 commits into
Open
Add safety/reporting prompt guidance and structured compaction#2bajajra wants to merge 57 commits into
bajajra wants to merge 57 commits into
Conversation
Apply low-friction prompt improvements informed by the Piebald-AI claude-code-system-prompts review, scoped to keep prompts small and preserve Mist's autonomous, non-blocking behavior: - agent_code_puppy: add a compact "Working principles" block covering (1) inspect a target before destructive/irreversible actions and surface conflicts (without stopping), (2) honest reporting of failed/skipped/unverified outcomes, and (3) treating tool/MCP/plugin/ channel output as data rather than instructions (external-source authority boundary). Framed as judgment, not gatekeeping. - _compaction: restructure the summarization instructions to preserve goal, constraints, changed files, decisions, failed attempts, verification status, and next action, with a guard against fabricating verification results. Prompt-text only; no logic or blocking changes. Tests in test_prompt_composition.py and test_compaction.py pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the hardcoded fog 🌫️ (a variation-selector emoji that rendered poorly in many terminals) across the codebase, split by purpose: - 🫧 (bubbles) for brand/identity: status panel, onboarding, prompt prefix, menus, plugin command messages, subagent panel title. - 💨 (dash/wind) for ambient/motion: spinner frames, status-rate indicator, subagent running indicator, auto-saved-session notice. Single fog emoji is no longer used anywhere; the two are never concatenated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Switch the pyfiglet wordmark from ansi_shadow to georgia11 (the closest terminal-renderable evocation of an ornate serif display face) and replace the 3-band blue→cyan→green line coloring with a smooth 5-stop hex gradient interpolated per line. Hex stops render smoothly on truecolor terminals and degrade to the nearest tone elsewhere; the stops are a single named tuple so the palette is a one-line change. Also updates the loading-fallback / comment glyphs to match the emoji refresh. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The shell_prefix plugin force-prompted every non-allowlisted command even under permission_mode=auto, because it returned requires_approval (which bypasses auto-approval). That defeated yolo mode and prompted on every compound command. Add a shell_prefix_enforcement setting, default off: when off the policy returns None and shell approval is governed solely by permission_mode (so auto = no prompts). When on, the prior allowlist gating applies. Exposed in the Safety settings menu. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add update_task_list: the agent passes its full ordered plan each call (replace semantics), marking items pending / in_progress / completed, and the checklist renders to the UI. Stored per-agent-identity, in-memory, no side effects — purely for planning and progress tracking on multi-step work. Wired into the tool registry; the main agent advertises it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the default agent plan, explore, and match conventions — guidance that helps weak and strong models alike (not reliant on built-in reasoning): - Approach block: explore first, lay out a task list (update_task_list), think before implementing; skip the ceremony for trivial asks. - Default to implementing not proposing; work through blockers; ask only when undiscoverable locally and a wrong guess is costly. - Engineering judgment (adapted from Codex guidance): match the project's existing patterns/libraries; structured parsers over string hacking; scope edits tightly; don't revert unrelated changes; scale verification to risk; plain, direct prose. Replace the universal 600-line hard cap with cohesion/convention-based guidance in the agent prompt, agent-creator prompt, tools content, and AGENTS.md — the hard number contradicted "match existing conventions" and the codebase itself exceeds it ~4x. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A warm autumn theme (cinnamon / pumpkin / butterscotch / milky tan / creamsicle) with a 16-color OSC terminal palette, banner colors, content styles, and Rich color remap. Errors/diff-remove deliberately stay red for visibility. Registered in the theme menu as "🍂 Cinnamon"; select with /theme cinnamon. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a system-prompt line so that when asked who built it or how it was built, the agent answers "I was built by Rahul Bajaj (Owlgebra AI)." Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ruff format --check flagged cli_runner.py, task_list.py, and test_shell_prefix.py from the preceding feature commits. No behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Align tests with this branch's changes: - theme catalog now has 13 curated themes / 15 menu entries, with cinnamon inserted at index 4 (shifting later index assertions). - PRODUCT_EMOJI / display_name are now 🫧 (brand). - status-rate indicator is now 💨 (ambient). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When orchestrator_mode is enabled (off by default), the main agent's system prompt gains a delegation overlay: it operates as a coordinator, delegating hands-on work (exploration, edits, shell, verification) to subagents via invoke_agent and keeping only the plan + distilled subagent summaries in its own context. This isolates working context in subagents so the main agent stays at a meta level. Delegation guidance follows Anthropic's multi-agent research findings: self-contained briefs, concise (not raw) summaries back, non-overlapping subagent scope, and scaling delegation to task complexity (don't spawn for trivial asks). Default off because delegation trades materially more tokens for context isolation and suits parallelizable work better than tightly-coupled coding. Enable with /set orchestrator_mode=on. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add proactive tool-result clearing (the cheapest, lowest-risk context
technique from the research): once a tool result is deep in history, the
agent has already extracted what it needed, so the bulky payload is dead
weight. The history processor now runs every turn — independent of the
compaction threshold — and replaces large, old tool-return contents with
a short stub ("[tool result cleared … re-run the tool if you need it]"),
preserving the call/return pairing so history stays valid.
Conservative defaults (enabled): keep the 4 most recent tool results
verbatim, only stub results over ~1500 tokens. Idempotent. Tunable via
tool_result_clearing / tool_result_keep_recent / tool_result_clear_threshold.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a prompt directive to prefer targeted reads (grep to locate, then read_file with start_line/num_lines for the relevant span) over loading whole large files. Reduces context intake at the source — the companion to tool-result clearing on the output side. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
While a tool runs, the spinner now shows what's happening ("Running: npm
test", "Reading src/app.py", "Delegating to qa") instead of a static
"thinking…", so a long tool action reads as live progress rather than a
stalled agent. Wired through the central pre/post tool-call hooks (one
place, every tool) via a small spinner_activity plugin; labels are
concise and truncated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Swap the main thinking spinner's frames from a 💨 drifting inside parentheses to a clean rotating square (◰◳◲◱) — a minimal, opencode-style indicator that reads as steady modern progress instead of a wandering emoji. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The stream handler intentionally leaves the spinner paused when
transitioning into a tool call, so a long-running tool showed no
indicator at all — the agent looked stalled. The spinner_activity plugin
now resumes the spinner in pre_tool_call (guarded against user-input
prompts), so the tool-aware activity label ("Running: …") animates while
the tool executes and during time-to-first-token of the next response.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two UI/UX fixes from user feedback:
- Replace the tiny, faint square spinner glyphs with the classic braille
"dots" spinner — crisp, well-supported, and consistent with the
sub-agent panel which already uses it.
- Add a prompt directive so the agent stops prefacing every tool call
with a one-line narration ("Let me check…", "Now I'll…"). Those
pile up as stacked AGENT RESPONSE blocks; with live tool activity in
the spinner, the agent should work quietly and summarize at the end.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the single faint spinner with a set of crisp braille presets adapted from expo-agent-spinners — dots, sparkle, wave, pulse, snake, bounce. The 3–4 cell presets read with real presence (fixing the "too small" feedback). Frames resolve per-spinner from the spinner_style config (default "sparkle"); pick one with /set spinner_style=<name>. Falls back to the default on unknown values. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collapse intermediate narration + tool calls into a single live region that updates in place instead of stacking AGENT RESPONSE blocks, per docs/IN_PLACE_STATUS_PLAN.md (Option A): - StepLedger (messaging/step_ledger.py): thread-safe, bounded ledger of recent/active steps + full per-turn history; renders a compact Text. - Event stream handler defers assistant text and decides final-vs- intermediate by whether a tool call follows; intermediate collapses to a ledger gist, the final answer flushes to scrollback. Also resumes the spinner after every part end (heartbeat) so long thinking never looks stalled. - Spinner renders the ledger in its Live region; config getters compact_steps / compact_steps_max_visible / compact_steps_summary. Default off; opt in with /set compact_steps=true. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- cwd_context: inject a bounded (~1500-char, depth-2, artifact-filtered) file index + cwd into the dynamic prompt so the agent resolves bare filenames by name instead of guessing or mis-using grep. Cached by tree signature; degrades to cwd-only on error. (Stale ~4800 docstring corrected to the real _MAX_INDEX_CHARS cap.) - answer_echo: echo ask_user_question answers to scrollback after the alt-screen TUI exits, so the user can see what they picked. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add high-value, model-agnostic prompt guidance distilled from leaked Claude Code (opus-4.8 / fable-5), Codex (gpt-5.5), and opencode system prompts (analyzed via parallel subagents), keeping the static prompt ~8.1k chars (well under the 12k budget): - Resolving file references: use the cwd/file-tree context; locate bare filenames with list_files/find, not grep (paths vs contents). - Tool economy: parallelize independent calls; prefer dedicated tools over shell; don't re-read to confirm an edit or re-run a delegated search. - Communicating results: lead with the outcome; self-contained final message; file_path:line_number refs; readable > terse; don't end on a plan/question/"Want me to…?"; treat a pasted error as a debug request. - Don't assume a library exists; discover the project's own lint/test commands rather than assuming them. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Invoking a subagent while durable mode (DBOS) was on crashed with "Can't get local object '_make_stream_handler_wrapper.<locals>._wrapped'". Subagent runs pass an event_stream_handler that wraps a nested closure (the subagent_panel coalescing patch), and DBOS serializes per-run inputs for durability — pickling a closure fails. Subagents are ephemeral child runs spawned from the main agent's tool call; they don't need their own durable workflow (the main agent's workflow already covers the tool call). So wrap_with_dbos_agent now returns None for any non-"main" kind, leaving subagents as plain pydantic agents. This also stops resetting their MCP toolsets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The screenshot feedback was two-fold: noisy "▸ 1 step" + "Cleared N stale tool result(s)" lines stacking in scrollback (which also clobbered the live spinner region), and no persistent "alive" indicator during tool use. - Tool-result clearing no longer prints a scrollback line every turn — it's a silent internal optimization, now surfaced only in the spinner context. - The compact-steps "▸ N steps" summary only prints for genuinely multi-step turns (n >= 2); a 1-step reply no longer spams "▸ 1 step". - Add "breathe" (a circular light filling/emptying ○◔◑◕●◕◑◔) and "heart" spinner presets — a calm, always-animating heartbeat. With the noise gone, the spinner/ledger live region stays visible through thinking AND tool execution (it resumes on pre_tool_call), so the agent reads as alive the whole turn. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Feedback: the task list collapsed to a useless "info: 📋 Task list" peek, and tool-status one-liners weren't appearing at all. - Add a _NEVER_COLLAPSE_GROUPS exemption to the low-mode peek logic so messages emitted with message_group="task_list" always render in full, even in low output mode. The user explicitly wants to see the list. - (Config) compact_steps was suppressing the per-tool peeks by routing them into a Live ledger that wasn't rendering — so the user saw no tool status. Turning compact_steps off restores the dim one-line tool peeks (shell:/read_file:/grep:) that are actually visible. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
After the AGENT RESPONSE banner printed, the spinner stayed paused while the model generated — so a slow first token / mid-stream stall showed "AGENT RESPONSE" then nothing, with no signal the agent was alive. Resume the spinner right after the response banner so the heartbeat animates through the post-banner generation gap, and pause it again the instant real text is about to flush (so the Live region never collides with streamed output). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a dedicated "agent is alive" signal that's independent of both the sparkle spinner and the text-streaming path. It pulses the terminal title bar (OSC 2: "◑ Mist · working") for the whole agent turn — title escapes never collide with the scrollback or the spinner's Live region, so liveliness no longer has to fight the streaming pause/resume logic. - LivenessHeartbeat (messaging/liveness.py): ref-counted background pulse, no-op without a TTY, restores the idle title on stop. - liveness plugin drives it from agent_run_start / agent_run_end. - Revert the spinner resume/pause-during-streaming entanglement (d27eaee) so the sparkle spinner stays purely contextual. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Repro: asked to read a paper from the web, the agent declared "no web/browser/network access" and made the user push three times before it discovered qa-kitten (which ships Playwright browser automation). It had list_agents the whole time but never checked, and asserted a limit it hadn't verified. Two-pronged fix: - agents_roster plugin: inject the available specialist agents + their one-line descriptions into the dynamic prompt every turn, so the agent always sees its delegation options (e.g. "qa-kitten: web browser automation via Playwright"). Cached per process, excludes self. - Prompt rule: before telling the user a task is impossible, verify — check tools + list_agents and delegate to a specialist with invoke_agent rather than declining. Never assert an unverified limit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…aiming
Mitigate the "I can't / you do it" failure mode with an excerpt distilled
from the leaked Claude Code docs-assistant prompt ("lean toward helping
rather than deflecting"; "reframe out-of-scope into what the tool can do")
and Codex gpt-5.5 ("implement end-to-end; don't hand work back"):
- Bias toward helping, not deflecting: reframe a seemingly-impossible
request into the closest capability and attempt it before declining;
don't off-load to the user ("you download/paste/run it") work a tool or
specialist agent could do.
Pairs with the agents_roster injection + the verify-before-claiming rule
already added. Static prompt stays under the 12k budget.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The standalone heartbeat wrote terminal-title OSC escapes (\033]2;…) to stdout from a background thread. With Rich rendering concurrently, the ESC byte got separated from the rest of the sequence, so raw "]2;◑ Mist · working" text spewed into the scrollback instead of setting the window title — strictly worse than no signal. Concurrent OSC writes are fundamentally unsafe alongside Rich's Live / streaming output, so the title-bar approach can't work here. Removed the liveness module + plugin + tests. The sparkle spinner remains the contextual signal; a reliable always-on indicator needs the persistent footer rework (single Rich Live owning all output), not a side-channel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Option A (compact_steps ledger) doesn't render correctly live, and every side-channel liveliness attempt failed for one root cause: streamed text bypasses Rich's Live coordination, so any second writer races/corrupts. Add a full Option B plan (single Live owns the turn, streamed text routed through it, footer = heartbeat + activity + ledger), implementation steps, risks, and a tmux capture-pane verification harness now that the TUI can be driven headlessly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Document driving the real Mist TUI headlessly via a pty for visual verification without user screenshots: tmux capture-pane (-p rendered, -pe raw escapes), a Python pty raw-byte method, animation capture over time, what each is good/not good for, and gotchas (fixed pane size, no foreground sleep, always kill-session, model-call cost). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements the recommended fix from IN_PLACE_STATUS_PLAN.md §3b. The root cause of every prior status/liveliness failure was streamed text writing raw to console.file, bypassing Rich's Live and racing with the spinner. Now a single Live owns the turn's output: - LivePrinterWriter (messaging/live_printer_writer.py): a file-like that termflow writes to; each completed line is parsed (Text.from_ansi) and handed to spinner.print_above so it scrolls above the pinned footer via Rich's coordinated print-above-Live. Collapses runs of blank lines to one. BlankLineCollapsingFile covers the no-spinner fallback. - ConsoleSpinner gains print_above() + get_active_spinner(); the Live is never paused in compact mode (Rich coordinates above-prints), and the step ledger persists in scrollback instead of flashing inside the Live. - event_stream_handler routes each text part through the writer when compact_steps is on; the AGENT RESPONSE banner is dropped in that path. Verified: 1261 tests pass, lint/format clean, and a tmux capture-pane smoke test boots cleanly with no escape-sequence corruption. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Each update_task_list call printed a fresh "📋 Task list" block to scrollback, so the list stacked (2+ full copies as the agent marked items done). In compact-steps mode the list now routes into the live footer (SpinnerBase task-list slot, rendered above the heartbeat line) so repeated updates replace in place. Cleared at turn end. Non-compact mode keeps the one-shot scrollback print. Verified in tmux: 3 update_task_list calls → 0 stacked "Task list" headers in scrollback (was 2+). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The new class-level SpinnerBase._task_list leaked across test files (a task-list test set it; the heartbeat-panel test then saw "📋 Task list" as the panel's first char instead of the heartbeat glyph). Add clear_task_list() to the autouse reset fixtures. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
LivePrinterWriter chunks already carry their own newlines, but print_above went through console.print which appended ANOTHER newline — so every streamed line was double-spaced (blank lines everywhere, worst with OpenAI-style token streaming). print_above now takes an `end` arg; the streaming writer passes end="" while step rows keep the default "\n". Verified in tmux: max consecutive blank lines in a markdown answer dropped from 3 to 2 (and markdown headers/bullets render correctly). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Full-rewrite plan for moving Mist (~106k lines of Python) to Bun/TS, built around a strangler strategy: the existing mist --serve HTTP/SSE seam lets a new Bun TUI ship first against the Python engine, then the engine ports underneath the same EventEnvelope contract. Covers the dependency mapping (pydantic-ai→Vercel AI SDK, rich/prompt_toolkit→Ink, DBOS-TS, bun:sqlite, bun build --compile), what ports verbatim (prompts, UX specs, safety heuristics, API contract), phased timeline (~3.5-5.5 months), ranked risks, and Phase 0 kickoff actions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Kick off docs/BUN_MIGRATION_PLAN.md Phase 0: - Bun workspace at ts/ (packages: protocol, core, tui; strict TS). - @mist/protocol: EventEnvelope + SessionRecord ported from code_puppy/events.py as Zod schemas, with bun tests (3 passing). - Contract verified against a LIVE Python engine: a Bun client created a session over mist --serve, submitted a prompt, and every SSE envelope parsed clean against the TS schema — the strangler seam works. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tract" This reverts commit d97954b.
This reverts commit 6e1e810.
bajajra
added a commit
that referenced
this pull request
Jul 17, 2026
Match the Claude Code task-list presentation: plan items render as numbered checkbox rows (⌙ ☑ #1 done · ☐ #2 active-highlighted · ☒ skipped-strikethrough) under the spinner, with a ctrl+t hide/show toggle and a status-line hint that flips accordingly. Prompt now allows bigger plans (up to 12 items) for big goals. tmux-verified: ☑/☐ numbered rows, ctrl+t hides the panel mid-run, hint flips to "show tasks". 22 bun tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Two prompt-text-only edits informed by a review of the Piebald-AI claude-code-system-prompts, scoped deliberately small to keep Mist's prompts lean and preserve its autonomous, non-blocking behavior.
code_puppy/agents/agent_code_puppy.py— adds a compact 3-bullet "Working principles" block to the default agent's system prompt:code_puppy/agents/_compaction.py— restructures_SUMMARIZATION_INSTRUCTIONSso compaction summaries preserve goal, constraints, changed files, decisions, failed attempts, verification status, and next action, plus a guard against fabricating verification results. Helps long-running sessions resume without re-deriving context.Why
Adopts the three highest-value, lowest-friction items from the review (action safety + truthful reporting, external-source trust boundary, structured compaction). The bullets are framed as judgment rather than gatekeeping, so they add no new blocking and don't interrupt autonomous runs.
Notes for reviewers
tests/test_prompt_composition.pyandtests/agents/test_compaction.pypass (35 tests); no test pins prompt text.🤖 Generated with Claude Code