Skip to content

Commit 7ca8964

Browse files
committed
docs: align backend and release-readiness guidance
1 parent 4eee534 commit 7ca8964

11 files changed

Lines changed: 30 additions & 105 deletions

File tree

docs/architecture/backends.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,13 @@ Reads `llm.backend` from `adjutant.yaml` (via `load_typed_config()`) and returns
7373

7474
Wraps the existing `core/opencode.py` module. Delegates to `opencode_run()` for async calls and `_find_opencode()` for binary lookup. Parses NDJSON output via `lib/ndjson.py`.
7575

76-
**Capabilities:** vision, model_listing, reaping, web_server, streaming.
76+
**Capabilities:** vision, model_listing, reaping, streaming.
7777

7878
### `ClaudeCLIBackend` (`backend_claude_cli.py`)
7979

8080
Invokes `claude -p --output-format json` directly. Parses JSON output via `lib/claude_json.py`. Handles agent prompts by stripping YAML frontmatter from `.opencode/agents/*.md` and passing the body via `--system-prompt-file`.
8181

82-
**Capabilities:** web_server, cost_tracking.
82+
**Capabilities:** model_listing, cost_tracking.
8383

8484
---
8585

@@ -124,6 +124,8 @@ At startup, `lifecycle/control.py` compares `adjutant.yaml`'s `llm.backend` agai
124124
4. Update `state/backend.txt`
125125
5. Log the switch
126126

127+
Backend-native web servers are retired on both backends, so the switch now translates model/session state only.
128+
127129
This is handled by `_detect_backend_change()` and `_handle_backend_switch()`.
128130

129131
---

docs/architecture/identity.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Natural language processing and long-running agent tasks use the LLM backend. Al
3838

3939
Two backends are supported:
4040
- **OpenCode** (`opencode`): Uses the OpenCode CLI with an Anthropic API key. Supports vision, streaming, model listing, and process reaping.
41-
- **Claude Code CLI** (`claude-cli`): Uses the Claude Code CLI with a Claude subscription. Supports cost tracking and a web server (CloudCLI).
41+
- **Claude Code CLI** (`claude-cli`): Uses the Claude Code CLI with a Claude subscription. Supports cost tracking and model listing.
4242

4343
The backend is configured in `adjutant.yaml` under `llm.backend`. See [Backend Architecture](backends.md) for the full protocol and capability system.
4444

docs/development/backend-guide.md

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -243,22 +243,9 @@ See `portfolio-kb/src/pipeline/analyze.py` for a complete working example of a K
243243

244244
---
245245

246-
## Web server services
246+
## Web UI
247247

248-
Each backend has a web server that provides a browser-based UI for remote development:
249-
250-
| Backend | Web server | Binary | Default port | PID file | Health check |
251-
|---------|-----------|--------|-------------|----------|-------------|
252-
| `opencode` | OpenCode web | `opencode web --mdns` | 4096 (`OPENCODE_WEB_PORT`) | `state/opencode_web.pid` | HTTP GET `http://localhost:{port}/` |
253-
| `claude-cli` | CloudCLI | `cloudcli --port {port}` | 3001 (`CLOUDCLI_PORT`) | `state/cloudcli_web.pid` | HTTP GET `http://localhost:{port}/health` |
254-
255-
The web server is managed by `lifecycle/control.py`:
256-
- **Start**: `start_backend_service()` dispatches to `start_opencode_web()` or `_start_cloudcli_web()` based on the active backend
257-
- **Stop**: `restart()` and `emergency_kill()` terminate both web servers (handles mid-switch state)
258-
- **Watchdog**: `listener.py` checks the PID file every ~5 minutes and restarts if dead
259-
- **Backend switch**: `_handle_backend_switch()` kills the old backend's web server
260-
261-
CloudCLI receives `WORKSPACES_ROOT` (set to `adj_dir`) and `CLAUDE_CLI_PATH` (set to the `claude` binary) as environment variables so it discovers the correct project directory and CLI binary.
248+
Backend-native web servers are retired on both backends. Adjutant's browser UI is the `web/` app in this monorepo, started with `adjutant web` during development.
262249

263250
---
264251

docs/development/testing.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Adjutant uses [pytest](https://pytest.org) as its test framework. Tests are orga
1010

1111
| Tier | Location | Tests | Runtime | Description |
1212
|------|----------|-------|---------|-------------|
13-
| Unit | `tests/unit/` | ~1139 | ~75s | Fast, fully mocked, no external calls |
13+
| Unit | `tests/unit/` | ~1420+ | ~75s | Fast, fully mocked, no external calls |
1414
| Integration | `tests/integration/` | ~20 | ~5s | Real process spawning, mocked external services |
1515

1616
---
@@ -70,7 +70,7 @@ All tests must pass. Any failure blocks the release. This is enforced by discipl
7070

7171
```
7272
tests/
73-
└── unit/ # All tests (~52 files, ~1081 tests)
73+
└── unit/ # All tests (~61 files, ~1420+ tests)
7474
├── test_lockfiles.py
7575
├── test_env.py
7676
├── test_paths.py
@@ -90,7 +90,7 @@ tests/
9090
├── test_journal_rotate.py
9191
├── test_screenshot.py
9292
├── test_search.py
93-
└── ... (52 files total)
93+
└── ... (61 files total)
9494
```
9595

9696
---

docs/guides/backends.md

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ adjutant setup
4848
2. Restart Adjutant: `adjutant restart`
4949

5050
On restart, Adjutant detects the backend change and automatically:
51-
- Stops the old backend's service (OpenCode web server or CloudCLI web server)
5251
- Translates the active model ID to the new backend's format
5352
- Clears the Telegram session (new backend, new conversation)
5453
- Records the switch in `state/backend.txt`
@@ -64,7 +63,7 @@ No data is lost. You can switch back at any time.
6463
| Vision (image analysis) | Yes (native) | Yes (via Read tool image injection) |
6564
| Dynamic model listing | Yes | Yes |
6665
| Process reaping | Yes | No (not needed) |
67-
| Web server (remote access) | Yes (`opencode web`) | Yes (CloudCLI) |
66+
| Backend-native web server | No | No |
6867
| Streaming output | Yes | No (single-shot JSON) |
6968
| Cost tracking per request | No | Yes |
7069
| Session resume | Yes (`--session`) | Yes (`--resume`) |
@@ -87,48 +86,25 @@ npm install -g @anthropic-ai/claude-code
8786
claude login
8887
```
8988

90-
### 3. Install CloudCLI (web UI)
91-
92-
CloudCLI provides a browser-based web UI for the Claude CLI backend, equivalent to `opencode web` for the OpenCode backend. It starts automatically when the `claude-cli` backend is active.
93-
94-
```bash
95-
npm install -g @siteboon/claude-code-ui
96-
```
97-
98-
Verify it's installed:
99-
100-
```bash
101-
cloudcli version
102-
```
103-
104-
**Configuration** (optional — defaults work out of the box):
105-
106-
| Environment variable | Default | Description |
107-
|---------------------|---------|-------------|
108-
| `CLOUDCLI_PORT` | `3001` | Port for the CloudCLI web server |
109-
| `CLOUDCLI_BIN` | auto-detected from PATH | Explicit path to the `cloudcli` binary |
110-
111-
Adjutant sets `WORKSPACES_ROOT` and `CLAUDE_CLI_PATH` automatically so CloudCLI sees the correct project directory and Claude binary.
112-
113-
### 4. Configure Adjutant
89+
### 3. Configure Adjutant
11490

11591
```yaml
11692
# adjutant.yaml
11793
llm:
11894
backend: "claude-cli"
11995
```
12096

121-
### 5. Verify
97+
### 4. Verify
12298

12399
```bash
124100
adjutant doctor
125101
```
126102

127103
The doctor command checks that the `claude` binary is on PATH, hooks are executable, and the backend is healthy.
128104

129-
### 6. Access the web UI
105+
### 5. Access the web UI
130106

131-
After `adjutant start`, CloudCLI is available at `http://localhost:3001` (or your configured `CLOUDCLI_PORT`). Access it over VPN or local network to develop on Adjutant remotely from another device.
107+
Use `adjutant web` to start Adjutant's own web dashboard from the monorepo checkout. Backend-native web servers are retired on both backends.
132108

133109
---
134110

docs/guides/commands.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,6 @@ Dependencies:
202202
jq OK (jq-1.7)
203203
python3 OK (Python 3.12.0)
204204
claude OK (/opt/homebrew/bin/claude) # or opencode, depending on llm.backend
205-
cloudcli OK (/opt/homebrew/bin/cloudcli) # claude-cli backend only
206205
207206
Optional:
208207
playwright not installed (needed for screenshot)
@@ -221,6 +220,6 @@ State:
221220
Listener: Running (PID 12345)
222221
```
223222

224-
The backend-specific binaries shown depend on `llm.backend` in `adjutant.yaml`. With `opencode`, doctor checks for the `opencode` binary. With `claude-cli`, it checks for `claude` and `cloudcli`.
223+
The backend-specific binaries shown depend on `llm.backend` in `adjutant.yaml`. With `opencode`, doctor checks for the `opencode` binary. With `claude-cli`, it checks for `claude`.
225224

226225
If `adjutant doctor` reports missing dependencies or configuration, run `adjutant setup --repair` to fix them interactively.

docs/guides/configuration.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ features:
6161
enabled: false
6262
vision:
6363
enabled: false
64+
model: "cheap" # must be cheap|medium|expensive
6465
search:
6566
enabled: false # requires BRAVE_API_KEY in .env
6667
usage_tracking:
@@ -171,17 +172,14 @@ The `.env` file is never `source`d directly — Adjutant uses grep-based extract
171172

172173
### Backend environment variables
173174

174-
These are optional overrides for backend binary paths and web server configuration. They're set in `.env` or your shell environment, not in `adjutant.yaml`.
175+
These are optional overrides for backend binary paths. They're set in `.env` or your shell environment, not in `adjutant.yaml`.
175176

176177
| Variable | Default | Description |
177178
|----------|---------|-------------|
178179
| `OPENCODE_BIN` | auto-detected | Explicit path to the `opencode` binary |
179-
| `OPENCODE_WEB_PORT` | `4096` | Port for the OpenCode web server |
180180
| `CLAUDE_CODE_BIN` | auto-detected | Explicit path to the `claude` binary |
181-
| `CLOUDCLI_BIN` | auto-detected | Explicit path to the `cloudcli` binary |
182-
| `CLOUDCLI_PORT` | `3001` | Port for the CloudCLI web server (claude-cli backend) |
183181

184-
Adjutant auto-detects binaries from PATH. Only set these if the binary is installed in a non-standard location or you need to override the default port.
182+
Adjutant auto-detects binaries from PATH. Only set these if the binary is installed in a non-standard location.
185183

186184
---
187185

docs/guides/memory.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Adjutant has persistent long-term memory stored as plain Markdown files. The mem
66

77
Memory is stored under `memory/` in the Adjutant directory. Each category has its own file. When you tell Adjutant to remember something, it auto-classifies the content and appends it to the right file with a timestamp.
88

9-
The agent loads `memory/memory.md` (the index) at startup so it knows what's available. Individual memory files are loaded on demand when relevant to the current conversation.
9+
The agent loads `memory/memory.md` on demand when a conversation touches past decisions, corrections, preferences, or other memory-backed topics. Individual memory files are then loaded as needed.
1010

1111
## Directory Structure
1212

docs/guides/troubleshooting.md

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ Look for `[control] Emergency kill` entries.
9898

9999
Cron runs with a minimal `PATH` (`/usr/bin:/bin`), which typically excludes
100100
directories like `/opt/homebrew/bin` where your LLM backend binary is installed. Adjutant
101-
snapshots your interactive shell's `PATH` when installing cron entries (via
102-
`adjutant schedule sync`), so re-syncing usually fixes this:
101+
installs cron entries with a minimal explicit PATH that includes standard system
102+
paths plus common package-manager locations, so re-syncing usually fixes this:
103103

104104
```bash
105105
adjutant schedule sync
@@ -125,50 +125,6 @@ On macOS, cron needs Full Disk Access to run scripts that access files outside s
125125

126126
Check the job's log file (shown in `adjutant schedule list`). The log path is defined in the schedule's YAML config.
127127

128-
## CloudCLI Web Server Issues
129-
130-
### CloudCLI not found on PATH
131-
132-
CloudCLI is the web UI for the `claude-cli` backend. Install it:
133-
134-
```bash
135-
npm install -g @siteboon/claude-code-ui
136-
```
137-
138-
Or set the binary path explicitly:
139-
140-
```bash
141-
export CLOUDCLI_BIN=/path/to/cloudcli
142-
```
143-
144-
### CloudCLI web server won't start
145-
146-
Check the log:
147-
148-
```bash
149-
cat state/cloudcli_web.log
150-
```
151-
152-
Common causes:
153-
154-
| Cause | Fix |
155-
|-------|-----|
156-
| Port already in use | Set a different port: `export CLOUDCLI_PORT=4000` |
157-
| Binary not found | Install CloudCLI or set `CLOUDCLI_BIN` |
158-
| Node.js version mismatch | CloudCLI requires Node.js 18+. Check `node --version` |
159-
160-
### CloudCLI starts but is unreachable
161-
162-
CloudCLI binds to `0.0.0.0` by default (all interfaces). If accessing over VPN, ensure the VPN routes traffic to the correct IP. Check:
163-
164-
```bash
165-
curl http://localhost:3001/health
166-
```
167-
168-
Should return `{"status":"ok",...}`.
169-
170-
---
171-
172128
## Model / AI Issues
173129

174130
### "Model not found" errors

docs/reference/2026-04-14-deployment-readiness.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,13 +202,15 @@ working local install via the published setup or installer path.
202202
`src/adjutant/messaging/telegram/commands.py`
203203
- **Action:** Align public command docs to actual shipped handlers, or
204204
implement the missing commands before release.
205+
- **Resolved 2026-04-18:** Aligned the public command surface to the actual Telegram dispatcher and handlers. Removed stale `/models`, `/memory`, and `/news` references from `README.md` and `docs/getting-started/first-message.md`, and documented the shipped `/brief`, `/recall`, and `/digest` commands instead.
205206

206207
2. **Release and install story is not coherent end-to-end**
207208
- **Files:** `.github/workflows/release.yml`, `src/adjutant/setup/install.py`,
208209
`README.md`
209210
- **Action:** Pick one supported public install path and document it
210211
consistently. If the Python installer is the intended story, wire and
211212
publish it as such. If not, stop presenting it as part of release readiness.
213+
- **Resolved 2026-04-18:** Promoted the installer to the canonical public path. Added a repo-root `install.py` entrypoint so a fresh clone or extracted release tarball can run `python3 install.py` directly, updated `src/adjutant/setup/install.py` to create `.venv` and install Adjutant into it before launching the wizard, and rewrote the release body plus getting-started docs to use that single flow consistently.
212214

213215
3. **Shell-based scheduled command execution needs hardening before public ship**
214216
- **Files:** `src/adjutant/cli.py`,
@@ -217,11 +219,13 @@ working local install via the published setup or installer path.
217219
- **Action:** Replace shell-string execution with argument-list execution where
218220
possible, or constrain and validate command generation so no user- or
219221
config-derived string reaches `shell=True` unsafely.
222+
- **Resolved 2026-04-18:** Reworked scheduled-command resolution around structured argv. `schedule.manage.resolve_command_argv()` now parses `script:` entries safely, `schedule.install.run_now()` and `notify_wrap.py` execute argv lists instead of `shell=True`, `adjutant schedule run` now uses the shared runner, and the schedule wizard now installs jobs through the same hardened schedule API. Cron entries still use `/bin/bash -lc`, but only to execute a fully quoted command built from structured argv plus explicit env assignments, not a raw user-derived shell string.
220223

221224
4. **Release gate requires a clearly recorded clean full test run**
222225
- **Files:** `tests/`, release/testing docs, backend and schedule test paths
223226
- **Action:** Run the full suite, resolve any failures, and make a clean full
224227
pass the explicit release gate before tagging.
228+
- **Resolved 2026-04-18:** Ran `.venv/bin/pytest tests/ -q` and got `1428 passed, 73 skipped, 1 warning in 8.02s`. Also updated `docs/development/testing.md` to stop advertising the stale lower approximate test counts.
225229

226230
### P1 — degrades quality
227231

@@ -230,22 +234,26 @@ working local install via the published setup or installer path.
230234
`docs/guides/configuration.md`, `README.md`
231235
- **Action:** Remove CloudCLI or opencode-web-era references and align docs to
232236
the current `web/` architecture.
237+
- **Resolved 2026-04-18:** Removed backend-native web-server guidance from `docs/guides/backends.md`, `docs/guides/configuration.md`, `docs/guides/troubleshooting.md`, `docs/guides/commands.md`, and `docs/development/backend-guide.md`, and replaced it with the current `adjutant web` / `web/` dashboard architecture where relevant.
233238

234239
2. **Unused runtime dependency likely remains**
235240
- **Files:** `pyproject.toml`
236241
- **Action:** Remove `rich` if it is truly unused, or add the missing usage
237242
intentionally.
243+
- **Resolved 2026-04-18:** Removed `rich` from `pyproject.toml` after confirming there are no runtime imports in `src/`.
238244

239245
3. **Private helper imports weaken code boundaries**
240246
- **Files:** `src/adjutant/capabilities/schedule/install.py`,
241247
`src/adjutant/capabilities/kb/query.py`
242248
- **Action:** Promote these helpers to public APIs or stop importing
243249
underscore-prefixed functions across modules.
250+
- **Resolved 2026-04-18:** Promoted `resolve_path()` in `schedule.manage` and `get_kb()` in `kb.run` to public helpers, then updated the importing modules to use the public names instead of underscore-prefixed internals.
244251

245252
4. **Exception swallowing remains high**
246253
- **Files:** distributed across `src/`
247254
- **Action:** Review silent-swallow and fallback-default cases, especially
248255
around config, filesystem, and subprocess branches.
256+
- **Status 2026-04-18:** Not addressed in this pass. The release-blocking and release-facing issues above were fixed first; broad exception-audit work remains follow-up debt rather than a blocker for the corrected deployment path.
249257

250258
### P2 — acceptable to defer
251259

0 commit comments

Comments
 (0)