@enderfga/claw-orchestrator 3.7.1 → 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +45 -3
  2. package/configs/autoloop-coder-prompt.md +65 -28
  3. package/configs/autoloop-planner-prompt.md +103 -42
  4. package/configs/autoloop-reviewer-prompt.md +58 -30
  5. package/dist/bin/cli.js +30 -7
  6. package/dist/bin/cli.js.map +1 -1
  7. package/dist/src/autoloop/dispatcher.js +16 -2
  8. package/dist/src/autoloop/dispatcher.js.map +1 -1
  9. package/dist/src/autoloop/messages.d.ts +0 -2
  10. package/dist/src/autoloop/messages.js +0 -2
  11. package/dist/src/autoloop/messages.js.map +1 -1
  12. package/dist/src/autoloop/planner-tools.d.ts +11 -6
  13. package/dist/src/autoloop/planner-tools.js +24 -7
  14. package/dist/src/autoloop/planner-tools.js.map +1 -1
  15. package/dist/src/autoloop/runner.d.ts +1 -2
  16. package/dist/src/autoloop/runner.js +1 -2
  17. package/dist/src/autoloop/runner.js.map +1 -1
  18. package/dist/src/autoloop/types.d.ts +0 -2
  19. package/dist/src/autoloop/types.js +0 -2
  20. package/dist/src/autoloop/types.js.map +1 -1
  21. package/dist/src/council.js +1 -0
  22. package/dist/src/council.js.map +1 -1
  23. package/dist/src/dashboard/index.html +1066 -12
  24. package/dist/src/embedded-server.d.ts +7 -0
  25. package/dist/src/embedded-server.js +359 -17
  26. package/dist/src/embedded-server.js.map +1 -1
  27. package/dist/src/index.js +222 -1
  28. package/dist/src/index.js.map +1 -1
  29. package/dist/src/session-manager.d.ts +98 -1
  30. package/dist/src/session-manager.js +340 -5
  31. package/dist/src/session-manager.js.map +1 -1
  32. package/dist/src/ultraapp/build-events.d.ts +46 -0
  33. package/dist/src/ultraapp/build-events.js +6 -0
  34. package/dist/src/ultraapp/build-events.js.map +1 -0
  35. package/dist/src/ultraapp/build.d.ts +39 -0
  36. package/dist/src/ultraapp/build.js +111 -0
  37. package/dist/src/ultraapp/build.js.map +1 -0
  38. package/dist/src/ultraapp/conventions.d.ts +8 -0
  39. package/dist/src/ultraapp/conventions.js +248 -0
  40. package/dist/src/ultraapp/conventions.js.map +1 -0
  41. package/dist/src/ultraapp/council-adapter.d.ts +49 -0
  42. package/dist/src/ultraapp/council-adapter.js +152 -0
  43. package/dist/src/ultraapp/council-adapter.js.map +1 -0
  44. package/dist/src/ultraapp/deploy.d.ts +45 -0
  45. package/dist/src/ultraapp/deploy.js +82 -0
  46. package/dist/src/ultraapp/deploy.js.map +1 -0
  47. package/dist/src/ultraapp/diff-apply.d.ts +15 -0
  48. package/dist/src/ultraapp/diff-apply.js +48 -0
  49. package/dist/src/ultraapp/diff-apply.js.map +1 -0
  50. package/dist/src/ultraapp/docker.d.ts +57 -0
  51. package/dist/src/ultraapp/docker.js +83 -0
  52. package/dist/src/ultraapp/docker.js.map +1 -0
  53. package/dist/src/ultraapp/feedback-classifier.d.ts +24 -0
  54. package/dist/src/ultraapp/feedback-classifier.js +85 -0
  55. package/dist/src/ultraapp/feedback-classifier.js.map +1 -0
  56. package/dist/src/ultraapp/files.d.ts +24 -0
  57. package/dist/src/ultraapp/files.js +79 -0
  58. package/dist/src/ultraapp/files.js.map +1 -0
  59. package/dist/src/ultraapp/fix-on-failure-session.d.ts +23 -0
  60. package/dist/src/ultraapp/fix-on-failure-session.js +48 -0
  61. package/dist/src/ultraapp/fix-on-failure-session.js.map +1 -0
  62. package/dist/src/ultraapp/fix-on-failure.d.ts +39 -0
  63. package/dist/src/ultraapp/fix-on-failure.js +69 -0
  64. package/dist/src/ultraapp/fix-on-failure.js.map +1 -0
  65. package/dist/src/ultraapp/host-strategy.d.ts +57 -0
  66. package/dist/src/ultraapp/host-strategy.js +205 -0
  67. package/dist/src/ultraapp/host-strategy.js.map +1 -0
  68. package/dist/src/ultraapp/interview-parser.d.ts +41 -0
  69. package/dist/src/ultraapp/interview-parser.js +83 -0
  70. package/dist/src/ultraapp/interview-parser.js.map +1 -0
  71. package/dist/src/ultraapp/interview-tools.d.ts +16 -0
  72. package/dist/src/ultraapp/interview-tools.js +36 -0
  73. package/dist/src/ultraapp/interview-tools.js.map +1 -0
  74. package/dist/src/ultraapp/json-patch.d.ts +6 -0
  75. package/dist/src/ultraapp/json-patch.js +78 -0
  76. package/dist/src/ultraapp/json-patch.js.map +1 -0
  77. package/dist/src/ultraapp/lifecycle.d.ts +38 -0
  78. package/dist/src/ultraapp/lifecycle.js +31 -0
  79. package/dist/src/ultraapp/lifecycle.js.map +1 -0
  80. package/dist/src/ultraapp/manager.d.ts +150 -0
  81. package/dist/src/ultraapp/manager.js +684 -0
  82. package/dist/src/ultraapp/manager.js.map +1 -0
  83. package/dist/src/ultraapp/narrator-prompt.d.ts +10 -0
  84. package/dist/src/ultraapp/narrator-prompt.js +54 -0
  85. package/dist/src/ultraapp/narrator-prompt.js.map +1 -0
  86. package/dist/src/ultraapp/narrator.d.ts +49 -0
  87. package/dist/src/ultraapp/narrator.js +83 -0
  88. package/dist/src/ultraapp/narrator.js.map +1 -0
  89. package/dist/src/ultraapp/patcher.d.ts +35 -0
  90. package/dist/src/ultraapp/patcher.js +159 -0
  91. package/dist/src/ultraapp/patcher.js.map +1 -0
  92. package/dist/src/ultraapp/router.d.ts +39 -0
  93. package/dist/src/ultraapp/router.js +139 -0
  94. package/dist/src/ultraapp/router.js.map +1 -0
  95. package/dist/src/ultraapp/spec-delta.d.ts +18 -0
  96. package/dist/src/ultraapp/spec-delta.js +35 -0
  97. package/dist/src/ultraapp/spec-delta.js.map +1 -0
  98. package/dist/src/ultraapp/spec.d.ts +82 -0
  99. package/dist/src/ultraapp/spec.js +125 -0
  100. package/dist/src/ultraapp/spec.js.map +1 -0
  101. package/dist/src/ultraapp/store.d.ts +67 -0
  102. package/dist/src/ultraapp/store.js +177 -0
  103. package/dist/src/ultraapp/store.js.map +1 -0
  104. package/dist/src/ultraapp/versions.d.ts +50 -0
  105. package/dist/src/ultraapp/versions.js +65 -0
  106. package/dist/src/ultraapp/versions.js.map +1 -0
  107. package/openclaw.plugin.json +15 -1
  108. package/package.json +3 -1
  109. package/skills/SKILL.md +2 -2
  110. package/skills/references/autoloop.md +7 -4
  111. package/skills/references/dashboard.md +153 -0
  112. package/skills/references/mcp.md +2 -2
  113. package/skills/references/tools.md +183 -0
  114. package/skills/references/ultraapp.md +203 -0
  115. package/skills/ultraapp/SKILL.md +112 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versions.js","sourceRoot":"","sources":["../../../src/ultraapp/versions.ts"],"names":[],"mappings":"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"}
@@ -98,7 +98,21 @@
98
98
  "ultraplan_start",
99
99
  "ultraplan_status",
100
100
  "ultrareview_start",
101
- "ultrareview_status"
101
+ "ultrareview_status",
102
+ "ultraapp_list",
103
+ "ultraapp_get",
104
+ "ultraapp_status",
105
+ "ultraapp_new",
106
+ "ultraapp_answer",
107
+ "ultraapp_add_file",
108
+ "ultraapp_spec_edit",
109
+ "ultraapp_build_start",
110
+ "ultraapp_build_cancel",
111
+ "ultraapp_feedback",
112
+ "ultraapp_promote_version",
113
+ "ultraapp_start_container",
114
+ "ultraapp_stop_container",
115
+ "ultraapp_delete"
102
116
  ]
103
117
  },
104
118
  "skills": ["skills/SKILL.md"]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enderfga/claw-orchestrator",
3
- "version": "3.7.1",
3
+ "version": "4.0.3",
4
4
  "description": "Claw Orchestrator — run Claude Code, Codex, Gemini, Cursor Agent, OpenCode and custom coding CLIs as one unified runtime. Drop into Hermes Agent, Claude Desktop, Cursor, Cline, Continue, Zed, Windsurf, Goose or any Model Context Protocol (MCP) host, install as an OpenClaw plugin, or run standalone. Persistent sessions, multi-agent council, ultraplan, ultrareview, autoloop, tool orchestration.",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",
@@ -92,6 +92,7 @@
92
92
  "dependencies": {
93
93
  "@modelcontextprotocol/sdk": "^1.29.0",
94
94
  "commander": "^12.1.0",
95
+ "diff": "^9.0.0",
95
96
  "re2": "^1.24.0"
96
97
  },
97
98
  "peerDependencies": {
@@ -99,6 +100,7 @@
99
100
  },
100
101
  "devDependencies": {
101
102
  "@eslint/js": "^9.15.0",
103
+ "@types/diff": "^7.0.2",
102
104
  "@types/node": "^22.10.0",
103
105
  "@vitest/coverage-v8": "^3.1.0",
104
106
  "eslint": "^9.15.0",
package/skills/SKILL.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: claw-orchestrator
3
- description: Manage persistent coding sessions across Claude Code, Codex, Gemini, Cursor, and OpenCode engines. Use when orchestrating multi-engine coding agents, starting/sending/stopping sessions, running multi-agent council collaborations, cross-session messaging, ultraplan deep planning, ultrareview parallel code review, autoloop autonomous workspace iteration, switching models/tools at runtime, or exposing the orchestrator's 41 tools as an MCP server to Hermes Agent / Claude Desktop / Cursor / Cline / Continue / Zed / Windsurf / Goose. Triggers on "start a session", "send to session", "run council", "ultraplan", "ultrareview", "autoloop", "autonomous iteration", "iterate until goal", "deep paper review", "auto research", "switch model", "multi-agent", "coding session", "session inbox", "cursor agent", "opencode", "mcp server", "clawo-mcp", "hermes mcp", "model context protocol".
3
+ description: Manage persistent coding sessions across Claude Code, Codex, Gemini, Cursor, and OpenCode engines. Use when orchestrating multi-engine coding agents, starting/sending/stopping sessions, running multi-agent council collaborations, cross-session messaging, ultraplan deep planning, ultrareview parallel code review, autoloop autonomous workspace iteration, ultraapp building deployable web apps from a structured Q&A interview, switching models/tools at runtime, or exposing the orchestrator's 55 tools as an MCP server to Hermes Agent / Claude Desktop / Cursor / Cline / Continue / Zed / Windsurf / Goose. Triggers on "start a session", "send to session", "run council", "ultraplan", "ultrareview", "autoloop", "ultraapp", "Forge tab", "build a web app", "one-click app", "AppSpec", "autonomous iteration", "iterate until goal", "deep paper review", "auto research", "switch model", "multi-agent", "coding session", "session inbox", "cursor agent", "opencode", "mcp server", "clawo-mcp", "hermes mcp", "model context protocol".
4
4
  metadata:
5
5
  {
6
6
  "openclaw":
@@ -43,7 +43,7 @@ metadata:
43
43
 
44
44
  # Claw Orchestrator Skill
45
45
 
46
- Claw Orchestrator — persistent multi-engine coding session manager for claw-style agent systems. Runs as a standalone CLI/server, with first-class OpenClaw plugin support. Wraps Claude Code, Codex, Gemini, Cursor Agent, OpenCode, and custom CLIs into headless agentic engines with 35 tools.
46
+ Claw Orchestrator — persistent multi-engine coding session manager for claw-style agent systems. Runs as a standalone CLI/server, with first-class OpenClaw plugin support. Wraps Claude Code, Codex, Gemini, Cursor Agent, OpenCode, and custom CLIs into headless agentic engines with 55 tools.
47
47
 
48
48
  ## Engine Quick Reference
49
49
 
@@ -5,7 +5,7 @@ the **Planner** to design a plan; on your approval, the Planner spawns the
5
5
  **Coder** + **Reviewer** subloop, monitors it, and pushes you (wechat →
6
6
  whatsapp → email fallback chain) only when something needs your attention.
7
7
 
8
- Design rationale: `tasks/autoloop.md`. This page is the operator reference.
8
+ This page is the operator reference.
9
9
 
10
10
  ## When to use
11
11
 
@@ -100,8 +100,8 @@ never see the JSON — only the Planner's narrative.
100
100
  | `resume_loop` | — | Resume after pause. |
101
101
  | `terminate` | `reason` | End run. |
102
102
  | `update_push_policy` | partial PushPolicy | Mutate notification rules (e.g. when you say "tell me every iter"). |
103
- | `write_plan_committed` | `message?` | git-commit current plan.md. |
104
- | `write_goal_committed` | `message?` | git-commit current goal.json. |
103
+ | `write_plan` | `content` (full plan.md body), `commit_message?` | Write `plan.md` to the workspace and git-commit. The **only** way the Planner can author plan.md — Write/Edit are stripped from the Planner session as a hard role boundary. Re-running replaces the whole file. |
104
+ | `write_goal` | `content` (full goal.json body), `commit_message?` | Same, for `goal.json`. Content is JSON-validated before write; malformed content errors back to the Planner. |
105
105
 
106
106
  ## Default push policy
107
107
 
@@ -211,9 +211,12 @@ Every JSON artifact in the ledger carries a `schema_version` field (currently
211
211
  | Endpoint | Returns |
212
212
  |---|---|
213
213
  | `GET /autoloop/list` | `{ ok, runs: AutoloopState[] }` |
214
+ | `POST /autoloop/new` | `{ ok, run_id, planner_session }` — body `{ workspace, run_id?, planner_model?, send_timeout_ms? }` |
214
215
  | `GET /autoloop/<id>/state` | `{ ok, state: AutoloopState }` |
215
216
  | `GET /autoloop/<id>/push_log` | `{ ok, entries: PushLogEntry[] }` |
216
- | `GET /autoloop/<id>/events` | SSE: `snapshot` / `message` / `state` / `push` / `iter_done` / `planner_reply` / `coder_reply` / `reviewer_reply` / `terminated` |
217
+ | `GET /autoloop/<id>/events` | SSE: `snapshot` / `message` / `state` / `push` / `iter_done` / `planner_reply` / `planner_error` / `coder_reply` / `reviewer_reply` / `terminated` |
218
+ | `POST /autoloop/<id>/chat` | **202** `{ ok, queued: true }` — body `{ text }`. Fire-and-forget: the Planner's reply streams back via the `/events` SSE channel as a `planner_reply` event (or `planner_error` on failure); the HTTP response intentionally does NOT wait for it, because first-contact replies routinely exceed reverse-proxy idle limits (e.g. Cloudflare Tunnel cuts at ~100s → 524). 400 on empty text, 404 when the run is not in this process's memory. The MCP `autoloop_chat` tool path keeps the synchronous await-and-return-reply semantics (it runs in-process). |
219
+ | `POST /autoloop/<id>/delete` | `{ ok }` — stops the runner if still alive, scrubs the row from `~/.claw-orchestrator/autoloop-registry.jsonl`. The ledger directory under `<workspace>/tasks/<run_id>/` is kept on disk. 404 if the run was not present in either memory or the registry. |
217
220
 
218
221
  The 3-pane UI consumes these endpoints:
219
222
  - **Left**: Planner chat (subscribes to `planner_reply`)
@@ -0,0 +1,153 @@
1
+ # Dashboard
2
+
3
+ The dashboard is a single-page HTML app served by the orchestrator's embedded
4
+ HTTP server. It lets you **launch and observe** Council sessions, Autoloop
5
+ runs, and Forge (Ultraapp) builds from a browser — no CLI, no webchat, no
6
+ plugin tool calls needed.
7
+
8
+ URL: `http://127.0.0.1:18796/dash` (local) or whatever public hostname you
9
+ front the embedded server with (the recommended setup uses a path-based
10
+ reverse proxy, e.g. `https://<your-host>/dash`).
11
+
12
+ ## Tabs
13
+
14
+ | Tab | Backed by | Launch endpoint |
15
+ |---|---|---|
16
+ | Autoloop | `SessionManager.autoloopStart()` | `POST /autoloop/new` |
17
+ | Council | `SessionManager.councilStart()` | `POST /council/new` |
18
+ | Forge | `UltraappManager.createRun()` | `POST /ultraapp/new` |
19
+
20
+ Each tab has a `+ New` button in the sidebar. Council and Autoloop open a
21
+ modal form (because they need workspace/task input); Forge POSTs an empty
22
+ body and drops you into an interview (the spec is built conversationally).
23
+
24
+ ## Standalone deployment
25
+
26
+ The recommended way to run the dashboard 24/7 is a separate `clawo serve`
27
+ process under launchd — completely decoupled from the OpenClaw gateway. The
28
+ gateway's plugin-side embedded server still works (lazy init on first tool
29
+ call); when both processes try to bind the default port, the loser gracefully
30
+ skips, so the two coexist without conflict.
31
+
32
+ Example `~/Library/LaunchAgents/com.clawo.serve.plist`:
33
+
34
+ ```xml
35
+ <?xml version="1.0" encoding="UTF-8"?>
36
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
37
+ <plist version="1.0">
38
+ <dict>
39
+ <key>Label</key><string>com.clawo.serve</string>
40
+ <key>RunAtLoad</key><true/>
41
+ <key>KeepAlive</key><true/>
42
+ <key>ThrottleInterval</key><integer>5</integer>
43
+ <key>ProgramArguments</key>
44
+ <array>
45
+ <string>/opt/homebrew/bin/node</string>
46
+ <string>/opt/homebrew/bin/clawo</string>
47
+ <string>serve</string>
48
+ <string>--port</string><string>18796</string>
49
+ <string>--host</string><string>127.0.0.1</string>
50
+ </array>
51
+ <key>StandardOutPath</key>
52
+ <string>/Users/USER/.openclaw/logs/clawo-serve.log</string>
53
+ <key>StandardErrorPath</key>
54
+ <string>/Users/USER/.openclaw/logs/clawo-serve.log</string>
55
+ </dict>
56
+ </plist>
57
+ ```
58
+
59
+ Bootstrap:
60
+
61
+ ```sh
62
+ launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/com.clawo.serve.plist
63
+ launchctl print "gui/$(id -u)/com.clawo.serve" | grep state
64
+ ```
65
+
66
+ ## Auth
67
+
68
+ The embedded server self-generates a 32-byte token at startup and writes it
69
+ to `~/.openclaw/server-token` (mode 0600). Same-user processes on the box
70
+ read it and present it as `Authorization: Bearer <token>` (or
71
+ `?token=<v>` query / `clawo_auth` cookie).
72
+
73
+ ### Local access
74
+
75
+ ```
76
+ http://127.0.0.1:18796/dash?token=$(cat ~/.openclaw/server-token)
77
+ ```
78
+
79
+ The server sets a `clawo_auth` cookie on the first query-token request, so
80
+ the bookmark `/dash` works on subsequent visits.
81
+
82
+ ### Hosted access via reverse proxy (recommended)
83
+
84
+ Don't expose the token to the public internet. Instead, gate the public
85
+ hostname with whatever auth layer you already trust (CF Access passkey,
86
+ Tailscale, mTLS, etc.) and have the reverse proxy **inject the Bearer
87
+ token on behalf of the user** when forwarding to port 18796. The browser
88
+ authenticates only against your edge auth; the dashboard's own token stays
89
+ inside the box.
90
+
91
+ Example sasha-doctor pattern (matches the user-side setup):
92
+ ```js
93
+ // after the edge auth check passes:
94
+ if (!req.headers.authorization) {
95
+ req.headers.authorization =
96
+ "Bearer " + fs.readFileSync("~/.openclaw/server-token", "utf-8").trim();
97
+ }
98
+ proxyHTTP(req, res, 18796);
99
+ ```
100
+
101
+ The `/login?token=...&redirect=/dash` endpoint exists as a fallback for
102
+ quick one-shot setups (works locally and through proxies that DON'T inject
103
+ the Bearer for you), but the proxy-injects-Bearer pattern is preferred
104
+ because users never see or paste the token.
105
+
106
+ Token-file write is deferred to the `listen()`-success callback so a second
107
+ process that loses the EADDRINUSE race does NOT clobber the winner's token.
108
+
109
+ ## Cross-process visibility
110
+
111
+ When the dashboard runs in a different process from where you spawn runs
112
+ (e.g. you started a council via the OpenClaw plugin tool from webchat, but
113
+ the dashboard is in `clawo serve`), the run state is invisible across
114
+ in-memory boundaries. The dashboard fixes this by unioning in-memory state
115
+ with on-disk records on every list call:
116
+
117
+ - **Councils**: `~/.openclaw/council-logs/council-*.md` — parsed for
118
+ `- **ID**:`, `- **Time**:`, `- **Task**:`, `- **Status**:` headers.
119
+ Legacy transcripts (pre-v4.0) fall back to a filename-derived id.
120
+ - **Autoloops**: `~/.claw-orchestrator/autoloop-registry.jsonl` — an
121
+ append-only JSONL index written by `autoloopStart()`. Stale entries
122
+ whose ledger directory no longer exists are filtered out at read time.
123
+ - **Forge**: `UltraappStore.listRuns()` already reads from disk
124
+ (`~/.claw-orchestrator/ultraapps/`).
125
+
126
+ Result: any run you've ever started — from any process — shows up in the
127
+ sidebar, sorted newest-first, until the underlying files are deleted.
128
+
129
+ ## Reverse-proxy integration
130
+
131
+ If you front the embedded server with sasha-doctor (or another reverse
132
+ proxy), route these paths to `127.0.0.1:18796`:
133
+
134
+ - `/dashboard`, `/dash`, `/login`
135
+ - `/autoloop/*`, `/council/*`, `/ultraapp/*`
136
+
137
+ The dashboard's relative `fetch()` calls expect the proxy to preserve the
138
+ path verbatim — no prefix stripping. `/v1/openclaw/*` should keep routing
139
+ to the OpenClaw gateway, not the embedded server.
140
+
141
+ ## Reset
142
+
143
+ To wipe dashboard state without touching real run data:
144
+
145
+ ```sh
146
+ # Forget all known autoloops (council/forge unchanged).
147
+ rm ~/.claw-orchestrator/autoloop-registry.jsonl
148
+
149
+ # Force the standalone server to mint a fresh auth token.
150
+ launchctl kickstart -k "gui/$(id -u)/com.clawo.serve"
151
+ # Then visit /login?token=$(cat ~/.openclaw/server-token)&redirect=/dash once
152
+ # to refresh the cookie.
153
+ ```
@@ -1,6 +1,6 @@
1
1
  # MCP integration
2
2
 
3
- Claw Orchestrator ships a Model Context Protocol (MCP) server (`clawo-mcp`) so any MCP-compatible host can drive its 41 tools.
3
+ Claw Orchestrator ships a Model Context Protocol (MCP) server (`clawo-mcp`) so any MCP-compatible host can drive its 55 tools.
4
4
 
5
5
  This document covers:
6
6
 
@@ -229,7 +229,7 @@ The engines themselves (`claude`, `codex`, `gemini`, `agent`, `opencode`) must a
229
229
 
230
230
  ## Tool filtering
231
231
 
232
- 41 tools is a lot for a small context window. Reduce noise either at the host level (most hosts have an `include` / `exclude` filter — see Hermes example above) or at the server level via `CLAWO_MCP_TOOLS`:
232
+ 55 tools is a lot for a small context window. Reduce noise either at the host level (most hosts have an `include` / `exclude` filter — see Hermes example above) or at the server level via `CLAWO_MCP_TOOLS`:
233
233
 
234
234
  ```bash
235
235
  CLAWO_MCP_TOOLS="session_start,session_send,session_stop,council_start,council_status" clawo-mcp
@@ -414,3 +414,186 @@ Get status and findings when completed.
414
414
  | Parameter | Type | Required |
415
415
  |-----------|------|----------|
416
416
  | `id` | string | yes |
417
+
418
+ ---
419
+
420
+ ## Autoloop (6)
421
+
422
+ Three-agent autonomous iteration loop (Planner / Coder / Reviewer) over a git workspace. See [`autoloop.md`](./autoloop.md) for the operator reference (push policy, ledger layout, smoke test).
423
+
424
+ ### `autoloop_start`
425
+
426
+ Start an autoloop run. Planner is created persistent; Coder + Reviewer are spawned by the Planner once `plan.md` is ready.
427
+
428
+ | Parameter | Type | Required | Description |
429
+ |-----------|------|----------|-------------|
430
+ | `cwd` | string | yes | Workspace (must be a git repo) |
431
+ | `goal` | string | yes | High-level user goal in natural language |
432
+ | `model` | string | | Planner model (default Opus) |
433
+ | `coderModel` | string | | Coder subagent model |
434
+ | `reviewerModel` | string | | Reviewer subagent model |
435
+ | `maxIters` | number | | Cap on Coder/Reviewer rounds (default 50) |
436
+ | `pushChannels` | string[] | | Notification channels (`wechat`, `whatsapp`, `email`) |
437
+
438
+ ### `autoloop_chat`
439
+
440
+ Send a message into the Planner conversation (e.g. answer a clarifying question, refine the plan, kick off the subloop).
441
+
442
+ | Parameter | Type | Required |
443
+ |-----------|------|----------|
444
+ | `id` | string | yes |
445
+ | `message` | string | yes |
446
+
447
+ ### `autoloop_status`
448
+
449
+ Get current state, phase, recent inbox messages, and ledger summary.
450
+
451
+ | Parameter | Type | Required |
452
+ |-----------|------|----------|
453
+ | `id` | string | yes |
454
+
455
+ ### `autoloop_list`
456
+
457
+ List active and recent autoloop runs (in-memory + on-disk registry, deduped by run_id).
458
+
459
+ (no params)
460
+
461
+ ### `autoloop_reset_agent`
462
+
463
+ Reset one of the subagent sessions (Coder or Reviewer) without losing Planner state — useful when a subagent loops on a stale belief.
464
+
465
+ | Parameter | Type | Required | Description |
466
+ |-----------|------|----------|-------------|
467
+ | `id` | string | yes | Run id |
468
+ | `agent` | `'coder'` \| `'reviewer'` | yes | Which subagent to reset |
469
+
470
+ ### `autoloop_stop`
471
+
472
+ Terminate the run. All sessions are stopped and ledger state is finalised.
473
+
474
+ | Parameter | Type | Required |
475
+ |-----------|------|----------|
476
+ | `id` | string | yes |
477
+
478
+ ---
479
+
480
+ ## Ultraapp (14)
481
+
482
+ Forge tab — turn a structured Q&A interview into a deployed web app reachable at `localhost:19000/forge/<slug>/`. See [`ultraapp.md`](./ultraapp.md) for the operator reference (lifecycle, conventions §1–§7, runtime modes, file layout, HTTP routes).
483
+
484
+ ### `ultraapp_list`
485
+
486
+ List all ultraapp runs.
487
+
488
+ (no params)
489
+
490
+ ### `ultraapp_get`
491
+
492
+ Full snapshot of a run: spec + chat + state.
493
+
494
+ | Parameter | Type | Required |
495
+ |-----------|------|----------|
496
+ | `id` | string | yes |
497
+
498
+ ### `ultraapp_status`
499
+
500
+ Lightweight status (mode + timestamps).
501
+
502
+ | Parameter | Type | Required |
503
+ |-----------|------|----------|
504
+ | `id` | string | yes |
505
+
506
+ ### `ultraapp_new`
507
+
508
+ Create a fresh run. Optionally seeds the interview with the user's first message.
509
+
510
+ | Parameter | Type | Required | Description |
511
+ |-----------|------|----------|-------------|
512
+ | `firstMessage` | string | | Free-form opening line; the interview Opus reads it before its first question |
513
+
514
+ ### `ultraapp_answer`
515
+
516
+ Submit an answer to the current interview question.
517
+
518
+ | Parameter | Type | Required | Description |
519
+ |-----------|------|----------|-------------|
520
+ | `id` | string | yes | Run id |
521
+ | `value` | string | yes | One of the question's `options[].value`, or `''` when using freeform |
522
+ | `freeform` | string | | Free-form text when none of the options fit |
523
+
524
+ ### `ultraapp_add_file`
525
+
526
+ Upload a sample file to `examples/` (the interview engine will `extract_metadata` it).
527
+
528
+ | Parameter | Type | Required |
529
+ |-----------|------|----------|
530
+ | `id` | string | yes |
531
+ | `path` | string | yes |
532
+ | `content` | string \| Buffer | yes |
533
+
534
+ ### `ultraapp_spec_edit`
535
+
536
+ Apply RFC 6902 JSON Patch ops to the AppSpec mid-interview.
537
+
538
+ | Parameter | Type | Required |
539
+ |-----------|------|----------|
540
+ | `id` | string | yes |
541
+ | `patch` | object[] | yes |
542
+
543
+ ### `ultraapp_build_start`
544
+
545
+ Validate the spec strictly (shape + cross-refs + DAG) and enqueue the build. Council picks it up FIFO.
546
+
547
+ | Parameter | Type | Required |
548
+ |-----------|------|----------|
549
+ | `id` | string | yes |
550
+
551
+ ### `ultraapp_build_cancel`
552
+
553
+ Abort an active build. Council sessions are stopped and the worktrees are left as-is for inspection.
554
+
555
+ | Parameter | Type | Required |
556
+ |-----------|------|----------|
557
+ | `id` | string | yes |
558
+
559
+ ### `ultraapp_feedback`
560
+
561
+ Done-mode feedback. Haiku classifier routes into `cosmetic` (Opus patcher), `spec-delta` (focused interview + auto-rerun), or `structural` (suggest fresh run).
562
+
563
+ | Parameter | Type | Required | Description |
564
+ |-----------|------|----------|-------------|
565
+ | `id` | string | yes | Run id |
566
+ | `text` | string | yes | The feedback (1+ chars) |
567
+
568
+ ### `ultraapp_promote_version`
569
+
570
+ Atomically swap the deployed version. Stops the current container/process, starts the target's, updates the router map.
571
+
572
+ | Parameter | Type | Required | Description |
573
+ |-----------|------|----------|-------------|
574
+ | `id` | string | yes | Run id |
575
+ | `version` | string | yes | Target version label (`v1`, `v2`, …) |
576
+
577
+ ### `ultraapp_start_container`
578
+
579
+ Start the container/process for the active version (no-op if already running).
580
+
581
+ | Parameter | Type | Required |
582
+ |-----------|------|----------|
583
+ | `id` | string | yes |
584
+
585
+ ### `ultraapp_stop_container`
586
+
587
+ Stop the container/process without deleting any state.
588
+
589
+ | Parameter | Type | Required |
590
+ |-----------|------|----------|
591
+ | `id` | string | yes |
592
+
593
+ ### `ultraapp_delete`
594
+
595
+ Stop + remove the run completely (sessions, container, on-disk state, router entry).
596
+
597
+ | Parameter | Type | Required |
598
+ |-----------|------|----------|
599
+ | `id` | string | yes |
@@ -0,0 +1,203 @@
1
+ # ultraapp — Reference
2
+
3
+ Turn a structured Q&A interview into a deployed web app reachable at
4
+ `localhost:19000/forge/<slug>/`. The dashboard's **Forge** tab and a
5
+ 14-tool MCP surface drive the end-to-end loop: interview → 3-agent
6
+ council → fix-on-failure → deploy → done-mode feedback.
7
+
8
+ This page is the operator reference. The interview behavioural contract
9
+ lives in [`skills/ultraapp/SKILL.md`](../ultraapp/SKILL.md). The
10
+ council architectural conventions every generated app must satisfy live
11
+ in [`src/ultraapp/conventions.ts`](../../src/ultraapp/conventions.ts).
12
+
13
+ ## When to use
14
+
15
+ - You have a workflow in your head (or a sample input file) and want a
16
+ shareable web app for it without writing code.
17
+ - You want to iterate cosmetically on a deployed app via chat ("make
18
+ the button green", "shrink the hero h1") without touching the
19
+ codebase yourself.
20
+ - You want to evolve the AppSpec ("also output a thumbnail") and
21
+ rebuild without restarting the interview.
22
+
23
+ ## Lifecycle
24
+
25
+ ```text
26
+ interview ─► queued ─► building ─► build-complete ─► deploying ─► done
27
+ │
28
+ ▼
29
+ done-mode chat
30
+ (cosmetic /
31
+ spec-delta /
32
+ structural)
33
+ ```
34
+
35
+ | Mode | Meaning |
36
+ |------|---------|
37
+ | `interview` | AppSpec being filled by Q&A. Chat input goes to the interview Opus. |
38
+ | `queued` | Build accepted, waiting for a slot in the FIFO build queue. |
39
+ | `building` | Council writing code, fix-on-failure driving install/build/test. |
40
+ | `build-complete` | Codebase ready, awaiting `deploy` step. |
41
+ | `deploying` | Container/process being started, router map being updated. |
42
+ | `done` | App live at `/forge/<slug>/`. Chat input now goes to the done-mode classifier. |
43
+ | `failed` | Council didn't reach consensus, or fix-on-failure couldn't get the build green. |
44
+
45
+ ## Architectural conventions (§1–§7)
46
+
47
+ Every generated app MUST satisfy these. They're embedded in the council
48
+ super-task prompt verbatim from `src/ultraapp/conventions.ts`.
49
+
50
+ | § | Topic | Headline rule |
51
+ |---|-------|---------------|
52
+ | 1 | Path-based deploy | Mount at `BASE_PATH=/forge/<slug>/`; in-app links MUST be relative. |
53
+ | 2 | Async file-queue runtime | Exact endpoints: `GET /`, `POST /run`, `GET /status/:jobId`, `GET /result/:jobId`, `GET /health`. File-based job queue under `$DATA_DIR/jobs/<jobId>/`. NO database. Data path from `process.env.DATA_DIR ?? '/data'`. |
54
+ | 3 | BYOK | If `runtime.needsLLM`, API keys live in browser localStorage and are sent direct to the provider. The server MUST NEVER receive the key (enforced by `eslint-plugin-no-server-keys`). |
55
+ | 4 | Dockerfile + smoke test | Single multi-stage Dockerfile, `npm run smoke` drives one full job in < 90s using `examples[0].ref`. |
56
+ | 5 | Council voting protocol | 3 agents in git worktrees, all-YES vote required, max 8 rounds. |
57
+ | 6 | Tech stack | Modern TypeScript / JavaScript framework (Next.js, Vite + Hono, SvelteKit). NO Python, NO pure SSGs. |
58
+ | 7 | **Frontend quality** | **Real styling system + real type hierarchy + four-state coverage on every async surface + drag-and-drop forms + appropriate result presentation + one deliberate theme.** §7g requires every agent to capture Chrome-headless screenshots at 1440×900 AND 375×812 and visually inspect the PNGs before voting YES — source-code review is explicitly insufficient evidence. |
59
+
60
+ ## Runtime modes
61
+
62
+ ```bash
63
+ clawo serve --ultraapp-runtime host # default
64
+ clawo serve --ultraapp-runtime docker # opt-in
65
+ ```
66
+
67
+ | Mode | Build | Run | Pros | Cons |
68
+ |------|-------|-----|------|------|
69
+ | `host` | `npm install && npm run build` | `npm start` (detached, `setsid`-equivalent) | Zero extra deps; works anywhere Node works; faster start. | No process isolation; deps installed under the user. |
70
+ | `docker` | `docker build .` | `docker run -d --restart unless-stopped` | Per-app isolation, restart policy, image is the artefact. | Requires a running Docker daemon. |
71
+
72
+ Both modes allocate a backend port in `[19100, 19999]`. The reverse-
73
+ proxy router runs at port `19000` (auto-fallback up to `19099` if
74
+ taken) and maps `/forge/<slug>/*` to the right backend. Slug→port map
75
+ persists to `~/.claw-orchestrator/_router.json`. Host-mode pid metadata
76
+ persists to `~/.claw-orchestrator/host-procs.json`.
77
+
78
+ ## File layout (per run)
79
+
80
+ ```text
81
+ ~/.claw-orchestrator/ultraapps/<runId>/
82
+ ├── spec.json # current AppSpec (latest)
83
+ ├── spec.history.jsonl # every accepted update_spec patch
84
+ ├── chat.jsonl # all chat turns (interview + done-mode)
85
+ ├── state.json # { runId, mode, createdAt, updatedAt }
86
+ ├── examples/ # uploaded sample files
87
+ ├── data/ # passed to host-mode app as DATA_DIR
88
+ ├── council-project/ # fresh git repo the council collaborates in
89
+ │ ├── .worktrees/{agent-A,agent-B,agent-C}/
90
+ │ └── (council code, merged to main on consensus)
91
+ └── versions/
92
+ ├── v1/
93
+ │ ├── codebase/ # snapshot of council main HEAD
94
+ │ └── artifact.json # { worktreePath, builtAt, deploy: { url, port, … } }
95
+ └── v2/ # patcher / spec-delta produces v2, v3, …
96
+ ```
97
+
98
+ ## HTTP routes (drive headlessly)
99
+
100
+ All routes are served by the embedded server (default `:18796`), under
101
+ `Authorization: Bearer <token>` from `~/.openclaw/server-token`.
102
+
103
+ | Method + path | Purpose |
104
+ |----|----|
105
+ | `GET /ultraapp/list` | All runs with mode + createdAt. |
106
+ | `POST /ultraapp/new` | Body: `{ firstMessage?: string }`. Returns `{ runId }`. |
107
+ | `GET /ultraapp/<id>` | Full snapshot: spec + chat + state. |
108
+ | `POST /ultraapp/<id>/answer` | Body: `{ value, freeform? }`. Submit interview answer. |
109
+ | `POST /ultraapp/<id>/spec-edit` | Body: RFC 6902 patch ops. Edit the spec mid-interview. |
110
+ | `POST /ultraapp/<id>/files` | Multipart upload to `examples/`. |
111
+ | `GET /ultraapp/<id>/events` | SSE stream of build/chat events (mode pill, narrator, council activity). |
112
+ | `POST /ultraapp/<id>/build` | Validate spec strictly + enqueue. |
113
+ | `POST /ultraapp/<id>/build/cancel` | Abort the active build. |
114
+ | `GET /ultraapp/<id>/artifacts` | List `versions/vN/`. |
115
+ | `POST /ultraapp/<id>/start` | Start the deployed container/process for the active version. |
116
+ | `POST /ultraapp/<id>/stop` | Stop without deleting. |
117
+ | `POST /ultraapp/<id>/delete` | Stop + remove all per-run state. |
118
+ | `POST /ultraapp/<id>/feedback` | Body: `{ text }`. Done-mode classifier routes cosmetic / spec-delta / structural. |
119
+ | `POST /ultraapp/<id>/promote-version` | Body: `{ version: "vN" }`. Atomically swap deployed version. |
120
+
121
+ ## MCP tools (14)
122
+
123
+ Same surface as HTTP, callable from any Model Context Protocol host
124
+ (Claude Desktop, Hermes Agent, Cursor, Cline, Continue, Zed,
125
+ Windsurf, Goose). Param schemas in [`tools.md`](./tools.md#ultraapp).
126
+
127
+ ```text
128
+ ultraapp_list ultraapp_get ultraapp_status
129
+ ultraapp_new ultraapp_answer ultraapp_add_file
130
+ ultraapp_spec_edit ultraapp_build_start ultraapp_build_cancel
131
+ ultraapp_feedback ultraapp_promote_version
132
+ ultraapp_start_container ultraapp_stop_container ultraapp_delete
133
+ ```
134
+
135
+ ## Done-mode feedback classification
136
+
137
+ After the run reaches `done`, chat input goes to a per-run Haiku
138
+ classifier. Three classes:
139
+
140
+ | Class | Routes to | Behaviour |
141
+ |-------|-----------|-----------|
142
+ | `cosmetic` | Patcher | Opus generates a unified diff against the deployed worktree → `applyUnifiedDiff` → validate via fix-on-failure → on success snapshot to `versions/vN+1/`, on any failure restore the snapshot atomically and post the reason to chat. |
143
+ | `spec-delta` | Focused interview | Flips mode back to `interview` with a bootstrap message that names the field(s) being changed. Completion auto-triggers a fresh `startBuild`. |
144
+ | `structural` | Suggestion only | Posts a narrator note: "this sounds like a different app — click + New". |
145
+
146
+ To swap which version is live, use `promote-version` (HTTP) or
147
+ `ultraapp_promote_version` (MCP) — the router map and host-procs map
148
+ update atomically.
149
+
150
+ ## Reference traces + replay
151
+
152
+ 5 captured JSONL traces of real interviews ground-truth the interview
153
+ engine against drift:
154
+
155
+ ```text
156
+ src/__tests__/fixtures/ultraapp-traces/
157
+ ├── text-summariser.jsonl (synthetic, simple text in/out)
158
+ ├── image-batch-resize.jsonl (batch upload + Pillow + zip)
159
+ ├── vlog-cut.jsonl (ffmpeg + whisper + branching DAG)
160
+ ├── llm-agent-pipeline.jsonl (BYOK, multi-step LLM)
161
+ ├── branching-dag.jsonl (parallel paths converging)
162
+ ├── _format.md (trace JSONL schema)
163
+ └── expected/<name>.appspec.json (frozen target)
164
+ ```
165
+
166
+ ```bash
167
+ tsx scripts/test-ultraapp-integration.ts --trace=image-batch-resize
168
+ tsx scripts/test-ultraapp-integration.ts --trace=all
169
+ ```
170
+
171
+ The `spec-extraction-quality.test.ts` test replays each trace through
172
+ the interview engine and asserts the resulting `AppSpec` matches the
173
+ frozen snapshot — any future engine or skill drift fails this test.
174
+
175
+ ## Operator quick start
176
+
177
+ ```bash
178
+ # 1. Boot
179
+ clawo serve # dashboard at :18796, ultraapp router at :19000
180
+ open "http://127.0.0.1:18796/dashboard?token=$(cat ~/.openclaw/server-token)"
181
+
182
+ # 2. Forge tab → + New → walk through the interview
183
+
184
+ # 3. After [Start Build] (or POST /ultraapp/<id>/build), watch:
185
+ # mode pill: queued → building → done
186
+ # narrator: short conversational chat updates
187
+ # Versions panel: v1, v2, … with Promote per row
188
+
189
+ # 4. Live URL appears in the share card. The deployed app is reachable at:
190
+ curl http://127.0.0.1:19000/forge/<slug>/health
191
+ ```
192
+
193
+ ## Known limitations (v4.0.0)
194
+
195
+ - The done-mode patcher loop occasionally hangs between
196
+ feedback-classification and the patcher Opus session creation;
197
+ cosmetic changes can be applied manually until the underlying race
198
+ is fixed.
199
+ - The §7g frontend gate currently relies on per-agent honesty about
200
+ running the screenshot capture; agents that skip the inspection can
201
+ still pass the smoke gate. A follow-up will plumb a server-side
202
+ screenshot validator into the council verifier so the gate becomes
203
+ structurally enforced rather than persona-enforced.