feat(phase6): docs, lint fixes, STATE.json update
- 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
This commit is contained in:
33
README.md
33
README.md
@@ -7,27 +7,47 @@ Agents no longer need to call `live-status`. The watcher auto-updates Mattermost
|
||||
|
||||
## Architecture
|
||||
|
||||
Two rendering modes (auto-detected):
|
||||
|
||||
### Plugin Mode (preferred)
|
||||
When the Mattermost plugin is installed, updates stream via WebSocket:
|
||||
- Custom post type `custom_livestatus` with terminal-style React rendering
|
||||
- Zero Mattermost post API calls during streaming (no "(edited)" label)
|
||||
- Auto-scroll, collapsible sub-agents, theme-compatible
|
||||
|
||||
### REST API Fallback
|
||||
When the plugin is unavailable, updates use the Mattermost REST API:
|
||||
- Blockquote-formatted posts updated via PUT
|
||||
- Shows "(edited)" label (Mattermost API limitation)
|
||||
|
||||
```
|
||||
OpenClaw Gateway
|
||||
Agent Sessions
|
||||
-> writes {uuid}.jsonl as they run
|
||||
|
||||
status-watcher daemon (SINGLE PROCESS)
|
||||
-> fs.watch recursive on transcript directory (inotify, Node 22)
|
||||
-> fs.watch + polling fallback on transcript directory
|
||||
-> Multiplexes all active sessions
|
||||
-> SessionState map: sessionKey -> { postId, pendingToolCalls, lines[] }
|
||||
-> Auto-detects plugin (GET /health every 60s)
|
||||
-> Plugin mode: POST/PUT/DELETE to plugin REST endpoint
|
||||
-> Plugin broadcasts via WebSocket to React component
|
||||
-> REST fallback: PUT to Mattermost post API
|
||||
-> Shared HTTP connection pool (keep-alive, maxSockets=4)
|
||||
-> Throttled Mattermost updates (leading edge + trailing flush, 500ms)
|
||||
-> Throttled updates (leading edge + trailing flush, 500ms)
|
||||
-> Circuit breaker for API failure resilience
|
||||
-> Graceful shutdown (SIGTERM -> mark all boxes "interrupted")
|
||||
-> Sub-agent nesting (child sessions under parent status box)
|
||||
|
||||
Mattermost Plugin (com.openclaw.livestatus)
|
||||
-> Go server: REST API + KV store + WebSocket broadcast
|
||||
-> React webapp: custom post type renderer
|
||||
-> Terminal-style UI with auto-scroll
|
||||
|
||||
gateway:startup hook
|
||||
-> hooks/status-watcher-hook/handler.js
|
||||
-> Checks PID file; spawns daemon if not running
|
||||
-> Daemon starts automatically with gateway
|
||||
|
||||
Mattermost API
|
||||
Mattermost API (fallback)
|
||||
-> PUT /api/v4/posts/{id} (in-place edits, unlimited)
|
||||
-> Shared http.Agent (keepAlive, maxSockets=4)
|
||||
-> Circuit breaker: open after 5 failures, 30s cooldown
|
||||
@@ -89,6 +109,9 @@ All config via environment variables. No hardcoded values.
|
||||
| `CIRCUIT_BREAKER_COOLDOWN_S` | `30` | Cooldown before half-open probe |
|
||||
| `TOOL_LABELS_FILE` | _(built-in)_ | External tool labels JSON override |
|
||||
| `DEFAULT_CHANNEL` | _none_ | Fallback channel for non-MM sessions |
|
||||
| `PLUGIN_URL` | _none_ | Plugin endpoint URL (enables plugin mode) |
|
||||
| `PLUGIN_SECRET` | _none_ | Shared secret for plugin authentication |
|
||||
| `PLUGIN_ENABLED` | `true` | Enable/disable plugin auto-detection |
|
||||
|
||||
## Status Box Format
|
||||
|
||||
|
||||
68
STATE.json
68
STATE.json
@@ -1,66 +1,24 @@
|
||||
{
|
||||
"projectId": "PROJ-035",
|
||||
"version": "v4.1",
|
||||
"state": "IMPLEMENTATION_COMPLETE",
|
||||
"planVersion": "v5-beta",
|
||||
"phase": 6,
|
||||
"totalPhases": 6,
|
||||
"lastAgent": "executor:proj035-phases4-6",
|
||||
"lastUpdated": "2026-03-07T17:43:00Z",
|
||||
"lastAgent": "main",
|
||||
"lastUpdated": "2026-03-07T22:15:00Z",
|
||||
"planPostedTo": "gitea",
|
||||
"giteaRepo": "ROOH/MATTERMOST_OPENCLAW_LIVESTATUS",
|
||||
"giteaIssueNumber": 3,
|
||||
"discoveryIssues": [],
|
||||
"completedDiscoveries": [],
|
||||
"synthesisComplete": true,
|
||||
"synthesisDoc": "discoveries/README.md",
|
||||
"auditComplete": true,
|
||||
"auditScore": "34/34",
|
||||
"auditFindings": [
|
||||
"WARNING: make check currently fails on existing live-status.js (43 lint issues) — Phase 0.2 addresses this",
|
||||
"WARNING: gateway restart needed to activate hook in Phase 4 — coordinate with Rooh"
|
||||
],
|
||||
"simulationComplete": true,
|
||||
"simulationVerdict": "READY",
|
||||
"hasOpenQuestions": true,
|
||||
"questionsAnswered": false,
|
||||
"approvedBy": null,
|
||||
"approvedAt": null,
|
||||
"completedPhases": [0, 1, 2, 3, 4, 5, 6],
|
||||
"phaseDetails": {
|
||||
"0": "Repo sync, lint fixes, env verification",
|
||||
"1": "Core components: config, logger, circuit-breaker, tool-labels, status-box, status-formatter, health, status-watcher",
|
||||
"2": "Session monitor, lifecycle, offset persistence, restart recovery, watcher-manager orchestrator",
|
||||
"3": "Sub-agent support: detection, nested rendering, cascade completion",
|
||||
"4": "Hook integration: gateway:startup hook deployed to workspace",
|
||||
"5": "Polish + deployment: SKILL.md, deploy-to-agents.sh, install.sh, systemd, Dockerfile, deprecation warning, README",
|
||||
"6": "v1 removal checklist: docs/v1-removal-checklist.md (actual removal deferred to post-production)"
|
||||
"giteaIssue": 4,
|
||||
"components": {
|
||||
"daemon": "src/ (Node.js, 96 tests)",
|
||||
"plugin_server": "plugin/server/ (Go, Mattermost plugin SDK)",
|
||||
"plugin_webapp": "plugin/webapp/ (React/TypeScript, 12.9KB bundle)",
|
||||
"hook": "hooks/status-watcher-hook/"
|
||||
},
|
||||
"errors": [],
|
||||
"maxConcurrentSubagents": 2,
|
||||
"activeSubagents": 0,
|
||||
"queuedTasks": [],
|
||||
"v4ReadyForProduction": true,
|
||||
"v1RemovalStatus": "DOCUMENTED_PENDING_PRODUCTION_VERIFICATION",
|
||||
"v1RemovalChecklist": "docs/v1-removal-checklist.md",
|
||||
"hookDeployedTo": "/home/node/.openclaw/workspace/hooks/status-watcher-hook/",
|
||||
"testResults": {
|
||||
"unitTests": 59,
|
||||
"integrationTests": 36,
|
||||
"totalTests": 95,
|
||||
"allPassing": true,
|
||||
"makeCheckErrors": 0,
|
||||
"makeCheckWarnings": 48
|
||||
},
|
||||
"notes": {
|
||||
"transcriptDir": "/home/node/.openclaw/agents/{agentId}/sessions/",
|
||||
"sessionsJsonPath": "/home/node/.openclaw/agents/{agentId}/sessions/sessions.json",
|
||||
"subagentKeyPattern": "agent:main:subagent:{uuid}",
|
||||
"subagentFields": ["sessionId", "spawnedBy", "spawnDepth", "label"],
|
||||
"mmApiReachable": true,
|
||||
"pinoInstallable": true,
|
||||
"fsWatchNode22": "confirmed (inotify recursive)",
|
||||
"makeCheckStatus": "CLEAN — 0 errors, 48 security warnings (expected, not blocking)",
|
||||
"pendingAction": "Gateway restart needed to activate hook. Coordinate with Rooh.",
|
||||
"pendingAction2": "After 1+ hour production verification, run v1-removal-checklist.md"
|
||||
"deployment": {
|
||||
"plugin": "com.openclaw.livestatus (active on Mattermost v11.4.0)",
|
||||
"daemon": "watcher-manager.js (PID file at /tmp/status-watcher.pid)",
|
||||
"renderingMode": "plugin (WebSocket) with REST API fallback"
|
||||
}
|
||||
}
|
||||
|
||||
1934
plugin/webapp/package-lock.json
generated
Normal file
1934
plugin/webapp/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -43,7 +43,6 @@ function PluginClient(opts) {
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
PluginClient.prototype.isHealthy = function () {
|
||||
var self = this;
|
||||
return this._request('GET', '/api/v1/health', null)
|
||||
.then(function (data) {
|
||||
return data && data.status === 'healthy';
|
||||
@@ -132,7 +131,7 @@ PluginClient.prototype._request = function (method, apiPath, body) {
|
||||
}
|
||||
} else {
|
||||
var msg = 'HTTP ' + res.statusCode;
|
||||
try { msg = JSON.parse(data).error || msg; } catch (_e) {}
|
||||
try { msg = JSON.parse(data).error || msg; } catch (_e) { /* ignore parse errors */ }
|
||||
var err = new Error(msg);
|
||||
err.statusCode = res.statusCode;
|
||||
reject(err);
|
||||
|
||||
Reference in New Issue
Block a user