From 81e78a952dbf0c9cf6c8b41cd03b7b644b34846b Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Thu, 13 Aug 2026 14:28:20 +0200 Subject: [PATCH] add observer agent: read-only watcher with git-based feeder script - observer.json: read-only tool set (file_read, file_grep, file_glob, reasoning_think) - agent-observer.md: terse observation-only prompt - observer-feed: polls git diff, feeds changes to agent prompt - justfile: install new files --- data/agents/observer.json | 14 ++++++++ data/prompts/agent-observer.md | 34 ++++++++++++++++++ data/scripts/observer-feed | 66 ++++++++++++++++++++++++++++++++++ justfile | 7 ++-- 4 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 data/agents/observer.json create mode 100644 data/prompts/agent-observer.md create mode 100644 data/scripts/observer-feed diff --git a/data/agents/observer.json b/data/agents/observer.json new file mode 100644 index 0000000..66b522c --- /dev/null +++ b/data/agents/observer.json @@ -0,0 +1,14 @@ +{ + "prompt": [ + "$XDG_CONFIG_HOME/ollie/prompts/agent-observer.md" + ], + "autoLoad": [ + "reasoning_think", + "file_read", + "file_glob", + "file_grep" + ], + "maxSteps": 5, + "temperature": 0.3, + "maxTokens": 4096 +} diff --git a/data/prompts/agent-observer.md b/data/prompts/agent-observer.md new file mode 100644 index 0000000..2394d9e --- /dev/null +++ b/data/prompts/agent-observer.md @@ -0,0 +1,34 @@ +# Observer + +You are a code observer. You watch a developer's changes in real-time and provide brief, useful observations. + +## Role + +- You receive diffs as they happen — staged and unstaged changes in a git repository. +- You observe patterns, spot bugs, note style issues, flag logic errors, and catch missed edge cases. +- You do NOT make changes. You have no write tools. You are read-only. + +## Output rules + +- Be terse. One to three sentences per observation. No preamble. +- Only speak when you have something genuinely useful to say. Silence is fine. +- If a diff is trivial (whitespace, formatting, rename), say nothing. +- Focus on: correctness bugs, security issues, missed error handling, race conditions, broken invariants. +- Do NOT repeat yourself. If you already noted something, don't note it again. +- Do NOT suggest rewrites or provide code unless specifically asked. + +## Context + +Each message you receive is a `git diff` snapshot. The diff shows what the developer just changed. You may use your read-only tools to look at surrounding code for context if the diff alone is ambiguous. + +## Examples + +Good observations: +- "The new error path on line 34 doesn't release the lock acquired on line 28." +- "This nil check is inverted — it'll panic on the happy path." +- "The SQL query interpolates user input directly. Use a parameterized query." + +Bad observations (don't do this): +- "Nice refactor!" (empty praise) +- "You might want to consider..." (hedging) +- "Here's how I'd rewrite this: ..." (unsolicited rewrites) diff --git a/data/scripts/observer-feed b/data/scripts/observer-feed new file mode 100644 index 0000000..08139b8 --- /dev/null +++ b/data/scripts/observer-feed @@ -0,0 +1,66 @@ +#!/bin/bash +# observer-feed — watches git repo for changes and feeds diffs to an observer agent. +# +# Usage: observer-feed / [interval] +# +# Watches the git working tree. When the diff changes, pushes the new diff +# to the agent's prompt. Runs until killed. +# +# Arguments: +# session/agent Target agent (e.g., myproj/observer) +# interval Poll interval in seconds (default: 5) +# +# The agent should be created first: +# o myproj/observer new /path/to/repo +# +# Environment: +# Respects the repo at the agent's cwd. Falls back to $PWD. + +set -euo pipefail + +if [[ $# -lt 1 ]]; then + echo "usage: observer-feed / [interval]" >&2 + exit 1 +fi + +TARGET="$1" +INTERVAL="${2:-5}" + +# Parse session/agent +if [[ "$TARGET" != */* ]]; then + echo "error: must specify session/agent (e.g., myproj/observer)" >&2 + exit 1 +fi + +SESSION="${TARGET%%/*}" +AGENT="${TARGET#*/}" +PROMPT_PATH="session/$SESSION/agent/$AGENT/prompt" + +# Get the agent's cwd for the git repo +CWD=$(ollie-9p read "session/$SESSION/agent/$AGENT/cfg" 2>/dev/null | grep '^cwd=' | cut -d= -f2-) +if [[ -z "$CWD" ]]; then + CWD="$PWD" +fi + +cd "$CWD" + +if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then + echo "error: $CWD is not a git repository" >&2 + exit 1 +fi + +echo "[observer-feed] watching $CWD every ${INTERVAL}s → $TARGET" + +LAST_DIFF="" + +while true; do + # Capture current diff (unstaged + staged vs HEAD) + DIFF=$(git diff HEAD -- 2>/dev/null || true) + + if [[ -n "$DIFF" && "$DIFF" != "$LAST_DIFF" ]]; then + printf '%s\n' "$DIFF" | ollie-9p write "$PROMPT_PATH" + LAST_DIFF="$DIFF" + fi + + sleep "$INTERVAL" +done diff --git a/justfile b/justfile index 36b6d07..4df39d1 100644 --- a/justfile +++ b/justfile @@ -92,7 +92,7 @@ install-el: migrate-bin: #!/usr/bin/env sh old="$HOME/bin" - for f in olliesrv ollie-9p ollie-remote toolsrv ollie-gui ollie-remount logseq-cli o; do + for f in olliesrv ollie-9p ollie-remote toolsrv ollie-gui ollie-remount logseq-cli o observer-feed; do if [ -f "$old/$f" ]; then echo " removing stale $old/$f" rm -f "$old/$f" @@ -114,6 +114,7 @@ install-data: install -m644 data/agents/README.md {{cfg}}/agents/README.md install -m644 data/agents/taskmanager.json {{cfg}}/agents/taskmanager.json install -m644 data/agents/theo.json {{cfg}}/agents/theo.json + install -m644 data/agents/observer.json {{cfg}}/agents/observer.json # Prompts mkdir -p {{cfg}}/prompts mkdir -p {{cfg}}/memory @@ -124,6 +125,7 @@ install-data: install -m644 data/prompts/agent-navigator.md {{cfg}}/prompts/agent-navigator.md install -m644 data/prompts/agent-taskmanager.md {{cfg}}/prompts/agent-taskmanager.md install -m644 data/prompts/agent-theo.md {{cfg}}/prompts/agent-theo.md + install -m644 data/prompts/agent-observer.md {{cfg}}/prompts/agent-observer.md install -m644 data/prompts/user-preferences.md {{cfg}}/prompts/user-preferences.md # Sandbox install -m644 cmd/toolsrv/internal/sandbox/sandbox.yaml {{cfg}}/sandbox.yaml @@ -182,11 +184,12 @@ install-data: install -m644 data/tools/_lib/__init__.py {{cfg}}/tools/_lib/__init__.py install -m644 data/tools/_lib/args.py {{cfg}}/tools/_lib/args.py install -m755 data/tools/_lib/args.sh {{cfg}}/tools/_lib/args.sh - # Scripts (ollie-remount, logseq-cli, o) + # Scripts (ollie-remount, logseq-cli, o, observer-feed) mkdir -p {{bin}} install -m755 data/scripts/ollie-remount {{bin}}/ollie-remount install -m755 data/scripts/logseq-cli {{bin}}/logseq-cli install -m755 data/scripts/o {{bin}}/o + install -m755 data/scripts/observer-feed {{bin}}/observer-feed # Acme scripts install -m755 data/scripts/acme/acme-ollie-ensure {{bin}}/acme-ollie-ensure install -m755 data/scripts/acme/AskFile {{bin}}/AskFile