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
This commit is contained in:
Levi Neely 2026-08-13 14:28:20 +02:00
parent 78d11f2ce8
commit 81e78a952d
4 changed files with 119 additions and 2 deletions

14
data/agents/observer.json Normal file
View File

@ -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
}

View File

@ -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)

View File

@ -0,0 +1,66 @@
#!/bin/bash
# observer-feed — watches git repo for changes and feeds diffs to an observer agent.
#
# Usage: observer-feed <session>/<agent> [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 <session>/<agent> [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

View File

@ -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