Commit Graph

2654 Commits

Author SHA1 Message Date
Levi Neely d5efe575ce consistent agent naming: parent:prefix convention
Agent names derived from cwd using parent:prefix format:
- /home/user/src/ollie -> src:ollie
- /home/user/proj/ABC-123_feature/repo -> abc-123:repo

Updates:
- Kate plugin: one agent per project, git root fallback if no project plugin
- acme-ollie-ensure: single 'acme' session, per-project agents
- ollie-session-here: single 'default' session, per-project agents

Also fixed write -> rdwr for session/agent creation endpoints
2026-10-07 14:39:47 +02:00
Levi Neely 1c02b50add proc events, bypass shortcuts, Kate session fix
Backend:
- Add proc.start/proc.exit events for background process lifecycle
- Add proc idx ctl command for machine-readable process listing (TSV)
- Add event.pub file for external event publishing
- Add ListProcsIdx to toolclient and toolsrv
- Fix bypass commands to use Setpgid for process group isolation

GUI:
- Add configurable bypass approval shortcuts (Ctrl+Y/Ctrl+N default)
- Add Keyboard Shortcuts section to Settings dialog
- Store shortcuts in theme.conf

Kate:
- Fix 'Start Session Here' - use rdwr for session/new endpoint
2026-10-07 14:22:44 +02:00
Levi Neely b9026bb48b fix: allow group access to ctl, plan, fifo for frontend interaction
Changed from 0600 (owner only) to 0660 (owner + group):
- ctl: frontends need to send slash commands
- plan: frontends need to read/write plan
- fifo: frontends need to submit prompts via queue

The agent group includes frontends, so group permissions enable
frontend interaction while still maintaining ownership-based isolation.
2026-10-07 11:01:01 +02:00
Levi Neely d65c06f27b implement namespace-bounded capability model
Per-agent file ownership with Unix permission enforcement:
- Agent directories owned by agent ID (UID), group 'agent' (GID)
- Private files (plan, ctl, fifo): mode 0600 - owner only
- Group-readable (chat, log): mode 0440 - owner + agent group
- World-readable (state, id): mode 0444 - observable by all
- Prompt: mode 0220 - CLI and owner can write

virtfs: fix UID/GID inheritance through nested paths
- Added findChildWithInheritance() to accumulate inherited UID/GID
- Stat now correctly shows agent ID as owner for nested files

server: admin bypass for server owner
- serverAdmin variable captures the Unix user running olliesrv
- Admin bypass includes empty uname, 'admin', or server owner

Documentation updates:
- fs/doc.go: 'The Namespace IS the Security Model'
- registry/doc.go: capability-based tool access
- peer.go: capability-based peer access
- lessons-learned.md: 'Model compliance is not a security boundary'
- architecture-9p.md: per-agent file ownership section

Security evaluation:
- Added experiments/security-eval/ with NERV attack corpus adaptation
- Test scripts for Landlock sandbox validation
- RESULTS.md documenting 0% ASR on hostile operations

This implements the NERV thesis: 'An agent can only access resources
explicitly bound into its namespace.' Enforcement is structural via
file permissions, not behavioral via model compliance.
2026-10-06 17:41:27 +02:00
Levi Neely 91f295dc2d gui: add activeSessionPaused property for reactive paused state
The isSessionPaused() Q_INVOKABLE didn't trigger QML binding
re-evaluation on pause/resume. New property with proper signal
makes ChatPane bindings reactive.

- activeSessionPaused property tracks active session's paused state
- Updated on refreshSessions() and switchAgent()
- ChatPane.qml uses property instead of function call
2026-10-06 15:23:44 +02:00
Levi Neely 4be78447fa gui: restart agent streams on session resume
When resuming the active session, restart chat stream so user
can continue working without switching agents.
2026-10-06 15:20:50 +02:00
Levi Neely 7cbaaed014 gui: gray state indicator when session is paused
Session paused state overrides agent state for the indicator.
Reacts to sessionsChanged signal for pause/resume updates.
2026-10-06 15:16:57 +02:00
Levi Neely 0744d9227a doc: update for bypass coordination and state indicators
evolution.md: add Phase 39, update timeline and size snapshot
event-topics.md: bypass events are per-agent, add resolved event
architecture-kde.md: document state dot and bypass indicator
usage.md: add bypass, approve, deny commands
2026-10-06 15:15:16 +02:00
Levi Neely af772e5e8b gui: use relative geometry for state indicator
Size and margins scale with row height:
- height: 30% of row height
- width: same as height (circular)
- left margin: 15% of row height
- right margin: 25% of row height
2026-10-06 15:13:01 +02:00
Levi Neely 8c207a0f3a gui: add right margin to state indicator dot 2026-10-06 15:12:00 +02:00
Levi Neely 64559de661 gui: add agent state indicator dot to session tree
Small colored dot to the right of agent name shows execution state:
- Green: idle
- Blue: thinking
- Orange: calling tool
- Gray: paused

Updates reactively via agentStateChanged event signal.
2026-10-06 15:10:12 +02:00
Levi Neely d8b24ae26d o: add bypass command to inspect pending request
o sess bypass - shows id, agent, cwd, cmd without resolving

Workflow: bypass -> review -> approve/deny
2026-10-06 14:58:22 +02:00
Levi Neely 7b6ddc1b1a o: accept optional request id for approve/deny
o sess approve [id]  - approve pending, optionally verify id
o sess deny [id]     - deny pending, optionally verify id

Shows request id in output: [42] approving: cmd
Errors if specified id doesn't match pending request.
2026-10-06 14:57:21 +02:00
Levi Neely b25e5e2fc6 bypass: emit resolved event for cross-client coordination
Server emits session.{sid}.agent.{aid}.bypass.resolved with id and
action (approved/denied) when a bypass is resolved by any client.

GUI handles bypass.resolved events to clear the banner and pending
count when CLI or another client resolves a bypass request.

This allows CLI 'o sess approve' to clear the GUI banner automatically.
2026-10-06 14:54:55 +02:00
Levi Neely b440622441 o: add approve/deny commands for bypass requests
Works at session or agent context (bypass is session-level).
Reads pending request from session/{s}/bypass, extracts ID,
writes '{id} approve' or '{id} deny' to resolve.
2026-10-06 14:52:07 +02:00
Levi Neely 150ca5dfdd gui: add pending bypass indicator to agent tree
Track multiple concurrent pending bypasses per agent in C++ backend:
- Add m_pendingBypasses QHash<QString,QSet<QString>> keyed by session:agent
- Add pendingBypassCount(sessionId, agentId) Q_INVOKABLE
- Add pendingBypassCountChanged(sessionId, agentId) signal
- Update resolveBypass to take agentId and remove from tracking set

SessionTree.qml: show ⚠ indicator left of agent name when the agent
has pending bypass requests. Uses Connections to refresh on signal.

ChatPane.qml: pass agentId to resolveBypass calls.
2026-10-06 14:47:55 +02:00
Levi Neely f9e6785add gui: hide bypass banner when switching away from the requesting agent 2026-10-06 14:41:09 +02:00
Levi Neely a269a6f790 gui: fix bypass banner - use activeAgentId not agentId in QML 2026-10-06 14:37:48 +02:00
Levi Neely 6dc9ffe3b1 gui: show bypass banner per-agent, not globally
- Changed event topic: session.{sid}.agent.{aid}.bypass.request
- Added agentId parameter to bypassRequested signal
- Filter bypass events to show only for the active agent
2026-10-06 14:32:30 +02:00
Levi Neely 59d07d3b4a fix bypass event payload truncation at newlines
The shell command in bypass requests contains embedded newlines.
Escape them as \n in the event payload, unescape in GUI.
2026-10-06 14:28:10 +02:00
Levi Neely ceec28c2b9 gui: show bypass banner for any session, not just active
The GUI is a global view - show bypass requests immediately
regardless of which session is currently selected.
2026-10-06 14:07:05 +02:00
Levi Neely 7b870443bb remove desktop notification for bypass requests
Bypass approval now flows through:
1. GUI - via event stream and banner
2. CLI - via agent loop (to be implemented)

Removed:
- bypass_notify.go (D-Bus notification)
- BypassNotifyFunc type and all references
- godbus/dbus dependency

The bypass event is still published via SetBypassPending.
2026-10-06 14:03:07 +02:00
Levi Neely 5882192ae9 gui: fix bypass banner not appearing until session switch
QML's property var change detection doesn't reliably trigger
binding updates when comparing to null. Added explicit bool
hasPendingBypass property that properly triggers visibility.
2026-10-06 13:56:28 +02:00
Levi Neely a4378c1be4 server: also match /event path in read handler 2026-10-06 13:51:25 +02:00
Levi Neely 5077dfea8e server: fix event file fallthrough when fid lookup fails
If fidOK was false for the event file, we fell through to the
default stream handling path which doesn't work for events.
Now we return 'bad fid' error instead of falling through.
2026-10-06 13:50:58 +02:00
Levi Neely d7d9e9654a replace pubsub library with simple fan-out event hub
The pubsub library had issues:
- Published to literal '*' topic (nonsensical)
- Used TrySend which drops events
- Complex hierarchical wildcard publishing

New implementation:
- Simple eventHub with map of subscribers
- PublishEvent fans out to all subscribers (blocking send)
- SubscribeEvents returns channel, cleaned up on ctx cancel
- SubscribeEventsFiltered filters client-side with MatchTopic
- Removed simonfxr/pubsub dependency
2026-10-06 13:43:57 +02:00
Levi Neely 63e7ed5c65 server: clarify event subscription uses 9P client connection context 2026-10-06 13:37:56 +02:00
Levi Neely 43d3051a78 server: fix event subscription context - use connection ctx not request ctx
The subscription was being cancelled after the first read completed
because we used the per-request context. Now using the connection
context so the subscription lives until the fid is clunked or
connection closed.
2026-10-06 13:36:26 +02:00
Levi Neely 79ab165ffd server: fix event dropping - use blocking callback instead of TrySend
The pubsub library's SubscribeChan uses non-blocking TrySend which
drops events when the channel is full. Switch to Subscribe with a
blocking callback to ensure no events are lost.

Also increased channel buffers from 64 to 256.
2026-10-06 13:32:56 +02:00
Levi Neely cd94cdf259 server: event file plain read now uses per-fid subscription
Plain reads (without writing a filter first) now get a per-fid
subscription with '*' filter, identical to 'echo * | rdwrs event'.

This fixes event loss — the old EventStream path overwrote events
when multiple arrived before the reader consumed them.
2026-10-06 13:27:02 +02:00
Levi Neely c96ccd51e8 doc: simplify size table - focus on core runtime only
~25K core + ~15.7K KDE = ~40.7K interesting code.
Backends, prompts, skills, docs excluded from headline.
2026-10-06 12:59:53 +02:00
Levi Neely 53efc8945e doc: refine size snapshot to highlight core runtime vs boilerplate
Backend adapters (~8.3K) are mostly mechanical API glue.
Core runtime is ~25K lines (22K Go core + 3K compiled tools).
KDE adds another ~15.7K. The interesting logic is concentrated.
2026-10-06 12:59:20 +02:00
Levi Neely 83f51dffef doc: add Phase 38 (streaming rdwr, event filtering) and size snapshot
- Document streaming rdwr pattern for filtered event subscriptions
- Add current size table (~59,600 SLOC total)
- Record removal of statewait, bypasswait, feed files
- Update timeline with explicit tool loading and event filters
2026-10-06 12:57:46 +02:00
Levi Neely a90ca6b57c remove unused feed file and observer agent support
The feed file was documented but never used by any frontend
or script. The observer agent pattern was never adopted.

- Remove feed.go, FeedWrite, ConsumeFeed
- Remove WatchFeed constant
- Remove feed file from 9P namespace
- Remove ConsumeFeed goroutine spawns from session
- Update docs (architecture-9p, architecture-ide, architecture, usage)

The event stream now covers real-time observation patterns better.
2026-10-06 12:55:39 +02:00
Levi Neely 88062d0ed0 server: remove redundant bypasswait file
Bypass requests are delivered via the event stream.
The bypasswait file was unused.
2026-10-06 12:47:57 +02:00
Levi Neely b6d6d9e41e doc: add event topics reference 2026-10-06 12:45:18 +02:00
Levi Neely 3b6c78d08d docs: state file is read-only 2026-10-06 12:44:37 +02:00
Levi Neely 86fbc90b43 server: remove statewait file, use event stream instead
The event stream with filtering replaces statewait:
- echo filter | rdwrs event

Removed:
- statewait file from agent namespace
- All non-historical references in docs and code

The state file remains for simple polling reads.
2026-10-06 12:44:02 +02:00
Levi Neely 7e7c29c900 docs: update to reflect event stream pattern over statewait
- AGENTS.md: simplified architecture description
- architecture-9p.md: examples use event stream with filtering
- usage.md: o tui and wiring examples use rdwrs event
2026-10-06 12:40:58 +02:00
Levi Neely 9d0b59671c o: use filtered event stream instead of statewait loop
Subscribe to agent-specific state events via streaming rdwr pattern.
No more polling loop - single filtered subscription.
2026-10-06 12:39:25 +02:00
Levi Neely 59f162a57e doc: document streaming rdwr pattern for filtered subscriptions 2026-10-06 12:35:10 +02:00
Levi Neely 772d77940c server: implement filtered event subscriptions
Event file now supports streaming rdwr pattern:
- Read: streams all events (unchanged)
- Write filter, then read: streams only matching events

Filter syntax:
- * matches single segment
- > matches rest of topic
- Examples: session.*.agent.*.state, session.abc.>

Usage: echo filter | rdwrs event

Per-fid subscription state is cleaned up on clunk.
2026-10-06 12:34:14 +02:00
Levi Neely 13831fb9f3 experiments: remove accidentally committed binary 2026-10-06 12:31:53 +02:00
Levi Neely 9a66944859 ollie-9p: add rdwrs command for streaming rdwr
rdwrs writes stdin then streams reads (does not wait for EOF).
Use for event subscription: echo filter | rdwrs event

Also adds prototype in experiments/streamrdwr demonstrating:
- Write topic filter, stream matching events
- Glob-style filtering: * (single segment), > (rest)
2026-10-06 12:31:06 +02:00
Levi Neely 6ea2bc052e server: add non-blocking state file separate from statewait
- state: immediate read of current agent state
- statewait: blocks until state changes

Clearer semantics than overloading statewait with both behaviors.
2026-10-06 12:17:19 +02:00
Levi Neely 021436bfbf gui: remove per-agent statewait stream, use server event bus
The server event stream already delivers state change events for all
agents. Removed the redundant per-agent statewait streamer - now agent
switching has no teardown/startup overhead for state monitoring.

- Removed m_state streamer entirely
- State updates come via event stream's session.{sid}.agent.{aid}.state events
- Only chat stream needs per-agent setup/teardown
2026-10-06 12:11:14 +02:00
Levi Neely f86c8d3cdc docs: update all references from eventwait to event 2026-10-06 12:08:35 +02:00
Levi Neely 25d7fbfc5b server: rename eventwait to event 2026-10-06 12:02:37 +02:00
Levi Neely adb08fc51d server: fix eventwait to use Stream instead of BlockOnce
EventValue was storing only the latest event and using hash comparison,
which caused events to be overwritten if they arrived faster than the
client could read them.

Now eventwait uses Stream mode with EventStream which delivers each
event as it arrives. Events won't be lost due to rapid arrival.
2026-10-06 12:01:26 +02:00
Levi Neely 70c00541df gui: poll bypass file on session switch
Events can be missed if GUI wasn't connected when they were published.
Now checkPendingBypass() reads the bypass file directly when switching
agents/sessions to catch any pending requests.
2026-10-06 11:51:27 +02:00