Two bugs fixed:
1. Session monitor stale session bug: Sessions that were stale on first
poll got added to _knownSessions but never re-checked, even after
their transcript became active. Now stale sessions are tracked
separately in _staleSessions and re-checked on every poll cycle.
2. CLI live-status tool: create/update commands were creating plain text
posts without the custom_livestatus post type or plugin props. The
Mattermost webapp plugin only renders posts with type=custom_livestatus.
Now all CLI commands set the correct post type and livestatus props.
- Added completedBoxes map to track idle sessions and their post IDs
- On session reactivation, reuse existing post instead of creating new one
- Fixed variable scoping bug (saved -> savedState) in session-added handler
- Root cause: idle -> forgetSession -> re-detect -> new post -> repeat
This was creating 10+ duplicate status boxes per session per hour.
The main agent session uses key 'agent:main:main' which doesn't
contain a channel ID. The session monitor now falls back to reading
deliveryContext/lastTo from sessions.json and resolves 'user:XXXX'
format via the Mattermost direct channel API.
Fixes: status watcher not tracking the main agent's active transcript
- Add EnsureBotUser on plugin activate (fixes 'Unable to find user' error)
- Accept bot_user_id in create session request
- Await plugin health check before starting session monitor
(prevents race where sessions detect before plugin flag is set)
- Plugin now creates custom_livestatus posts with proper bot user
- Fix lint errors in plugin-client.js (unused var, empty block)
- Update README with plugin architecture and env vars
- Update STATE.json to v4.1 IMPLEMENTATION_COMPLETE
- All 96 tests passing, 0 lint errors
Plugin (Go server + React webapp):
- Custom post type 'custom_livestatus' with terminal-style rendering
- WebSocket broadcasts for real-time updates (no PUT, no '(edited)')
- KV store for session persistence across reconnects
- Shared secret auth for daemon-to-plugin communication
- Auto-scroll terminal with user scroll override
- Collapsible sub-agent sections
- Theme-compatible CSS (light/dark)
Daemon integration:
- PluginClient for structured data push to plugin
- Auto-detection: GET /health on startup + periodic re-check
- Graceful fallback: if plugin unavailable, uses REST API (PUT)
- Per-session mode tracking: sessions created via plugin stay on plugin
- Mid-session fallback: if plugin update fails, auto-switch to REST
Plugin deployed and active on Mattermost v11.4.0.
Code blocks collapse after ~4 lines in Mattermost, requiring click
to expand. Blockquotes (> prefix) never collapse and show all content
inline with a distinct left border.
- Tool calls: inline code formatting (backtick tool name)
- Thinking text: box drawing prefix for visual distinction
- Header: bold status + code agent name
- All lines visible without clicking to expand
- Removes flicker caused by delete+recreate pattern
- PUT updates modify post content in-place (smooth)
- Trade-off: Mattermost shows (edited) label, and PUT clears pin status
- Pin+PUT are incompatible in Mattermost API — every PUT clears is_pinned
- Fix pin API calls to use {} body instead of null
- Remove post-replaced event handler (no longer needed)
Added forgetSession() to SessionMonitor. When watcher marks a session
idle/done, it now clears the key from the monitor's known sessions map.
Next poll cycle re-detects the session if the transcript is still active,
creating a fresh status post.
- New sessions start from current file offset, not 0. Shows live
thinking from the moment of detection, not a backlog dump.
- Session poll reduced from 2s to 500ms for faster pickup.
- Auto-pin with null body (MM pin API quirk).
- Auto-pin status posts on creation, unpin on session completion
- Skip stale sessions (>5min since last transcript write)
- Parse OpenClaw JSONL format (type:message with nested role/content)
- Handle timestamp-prefixed transcript filenames
1. session-monitor: handle timestamp-prefixed transcript filenames
OpenClaw uses {ISO}_{sessionId}.jsonl — glob for *_{sessionId}.jsonl
when direct path doesn't exist.
2. session-monitor: skip stale sessions (>5min since last transcript write)
Prevents creating status boxes for every old session in sessions.json.
3. status-watcher: parse actual OpenClaw JSONL transcript format
Records are {type:'message', message:{role,content:[{type,name,...}]}}
not {type:'tool_call', name}. Now shows live tool calls with arguments
and assistant thinking text.
4. handler.js: fix module.exports for OpenClaw hook loader
Expects default export (function), not {handle: function}.
5. HOOK.md: add YAML frontmatter metadata for hook discovery.
- docs/v1-removal-checklist.md: exact sections to remove from 6 AGENTS.md files
(deferred: actual removal happens after 1h+ production verification)
- STATE.json: updated to IMPLEMENTATION_COMPLETE, phase 6, all test results,
v1RemovalStatus: DOCUMENTED_PENDING_PRODUCTION_VERIFICATION
- make check: clean
Phase 3 (Sub-Agent Support):
- session-monitor.js: sub-agents always passed through (inherit parent channel)
- watcher-manager.js enhancements:
- Pending sub-agent queue: child sessions that arrive before parent are queued
and processed when parent is registered (no dropped sub-agents)
- linkSubAgent(): extracted helper for clean parent-child linking
- Cascade completion: parent stays active until all children complete
- Sub-agents embedded in parent status post (no separate top-level post)
- status-formatter.js: recursive nested rendering at configurable depth
Integration tests - test/integration/sub-agent.test.js (9 tests):
3.1 Sub-agent detection via spawnedBy (monitor level)
3.2 Nested status rendering (depth indentation, multiple children, deep nesting)
3.3 Cascade completion (pending tool call tracking across sessions)
3.4 Sub-agent JSONL parsing (usage events, error tool results)
All 95 tests pass (59 unit + 36 integration). make check clean.
PROJ-035 Live Status v4 - implementation plan created by planner subagent.
Discovery findings documented in discoveries/README.md covering:
- JSONL transcript format (confirmed v3 schema)
- Session keying patterns (subagent spawnedBy linking)
- Hook events available (gateway:startup confirmed)
- Mattermost API (no edit time limit)
- Current v1 failure modes
Audit: 32/32 PASS, Simulation: READY