Skip to content

Commit 8fbfacb

Browse files
committed
docs: add readiness and web session reference notes
1 parent 8dfbe11 commit 8fbfacb

5 files changed

Lines changed: 831 additions & 4 deletions

File tree

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
# Deployment Readiness Assessment — 2026-04-14
2+
3+
Adjutant v2.0.0 monorepo. Assessed against the on-disk codebase in this repository.
4+
5+
Generated using the evaluation prompt in `docs/reference/deployment-readiness.md`.
6+
7+
---
8+
9+
## 1. Deployment Readiness Verdict
10+
11+
**Verdict: Not Ready**
12+
13+
The single biggest blocker is that the public release contract is inconsistent at
14+
the user boundary: installation and command documentation materially disagree with
15+
shipped behavior, shell-based scheduled command execution still needs hardening,
16+
and this assessment does not yet have a recorded clean full-suite release gate.
17+
18+
**Deployment** here means: a public GitHub Release that ships the Adjutant tarball
19+
and checksum, supports the documented installation flow, and gets a new user to a
20+
working local install via the published setup or installer path.
21+
22+
---
23+
24+
## 2. Completeness Audit (MECE — 7 branches)
25+
26+
### A. Core runtime is implemented, but release confidence is reduced by drift
27+
28+
- **Status:** Partial
29+
- **Evidence:** CLI and runtime entrypoints exist in `src/adjutant/cli.py`.
30+
Dispatcher/auth/rate-limit/feature gating are centralized in
31+
`src/adjutant/messaging/dispatch.py`. Lifecycle control exists in
32+
`src/adjutant/lifecycle/control.py` and `src/adjutant/lifecycle/cron.py`.
33+
Lockfile state is handled in `src/adjutant/core/lockfiles.py`. Process
34+
management exists in `src/adjutant/core/process.py`.
35+
- **Evidence:** The security-critical dispatch path is explicit and centralized:
36+
auth check in `dispatch.py`, rate limiting in `_check_rate_limit()`, and
37+
feature-gate rejection in the `_FEATURE_GATES` block.
38+
- **Gap:** The runtime surface is real, but release confidence is reduced by
39+
command/docs drift and the absence of a clearly demonstrated clean release gate.
40+
41+
### B. Setup and onboarding exist, but installer distribution is only partially integrated
42+
43+
- **Status:** Partial
44+
- **Evidence:** Interactive setup exists in `src/adjutant/setup/wizard.py`.
45+
Repair and uninstall flows exist in `src/adjutant/setup/repair.py` and
46+
`src/adjutant/setup/uninstall.py`. Service installation support exists in
47+
`src/adjutant/setup/steps/service.py`. A curl-style installer exists in
48+
`src/adjutant/setup/install.py`.
49+
- **Evidence:** Public release packaging exists in `.github/workflows/release.yml`.
50+
- **Gap:** The installer exists as a standalone Python entrypoint, but the public
51+
release flow still tells users to clone or unpack the tarball, create a venv,
52+
`pip install -e .`, and run `adjutant setup`.
53+
`.github/workflows/release.yml:92-111` does not present the installer as the
54+
canonical path, so the distribution story is only partially integrated.
55+
56+
### C. Security posture is strong in design, but subprocess shell usage is a release risk
57+
58+
- **Status:** Partial
59+
- **Evidence:** Single-operator authentication is enforced in
60+
`src/adjutant/messaging/dispatch.py` by comparing `from_id` to `chat_id`.
61+
Feature-gated commands fail closed on config parse failure in the same module.
62+
`.env` parsing is hand-rolled and non-exec-based in `src/adjutant/core/env.py`.
63+
KB sandboxing is documented in `docs/guides/knowledge-bases.md` and scaffolded
64+
in the KB management path.
65+
- **Evidence:** Source-wide subprocess counts gathered during this audit:
66+
`subprocess.run(...)` = **44**, `subprocess.Popen(...)` = **6**,
67+
`shell=True` = **3**, `os.system(...)` = **0**.
68+
- **Evidence:** The `shell=True` call sites are:
69+
- `src/adjutant/cli.py:1097`
70+
- `src/adjutant/capabilities/schedule/notify_wrap.py:78-84`
71+
- `src/adjutant/capabilities/schedule/install.py:237-240`
72+
- **Gap:** Scheduled-command execution still relies on shell-string execution in
73+
public-release code paths. Even if these inputs are operator-authored, they
74+
should be tightened before public release.
75+
76+
### D. Test coverage is large, but release cleanliness is not yet demonstrated
77+
78+
- **Status:** Partial
79+
- **Evidence:** Test tree count gathered during this audit found
80+
**61 unit test files / 1422 unit test functions** and
81+
**2 integration test files / 19 integration test functions**, for a total of
82+
**1441** discovered test functions.
83+
- **Evidence:** Security-relevant coverage exists in
84+
`tests/unit/test_messaging_dispatch.py`, `tests/integration/test_feature_gating.py`,
85+
`tests/unit/test_env.py`, `tests/unit/test_kb_manage.py`,
86+
`tests/unit/test_schedule_install.py`, and related backend/config tests.
87+
- **Gap:** Release readiness requires a clearly recorded clean full-suite pass.
88+
At the time of this assessment, that release gate was not documented here as a
89+
final clean result. Repo docs and builder guidance also still contain stale,
90+
lower approximate test-count figures.
91+
92+
### E. Public distribution infrastructure exists, but is not yet coherent end-to-end
93+
94+
- **Status:** Partial
95+
- **Evidence:** `.github/workflows/release.yml` verifies tag vs `VERSION`, builds
96+
a tarball, generates a `.sha256`, and publishes a GitHub Release. Versioning is
97+
driven from `VERSION` through packaging metadata. Self-update logic exists in
98+
`src/adjutant/lifecycle/update.py`.
99+
- **Gap:** Artifact production is implemented, but the install story is split
100+
between release assets, manual editable installation, and a separate installer.
101+
Public distribution exists mechanically, not yet as one coherent user flow.
102+
103+
### F. Documentation is extensive, but materially out of sync with shipped behavior
104+
105+
- **Status:** Partial
106+
- **Evidence:** Public docs exist across `README.md`, `docs/guides/`,
107+
`docs/architecture/`, and `site/`.
108+
- **Evidence:** `README.md:71-79` advertises Telegram commands `/models`,
109+
`/memory`, and `/news`, but targeted search found no corresponding command
110+
handlers in `src/adjutant/messaging/telegram/*.py`.
111+
- **Evidence:** `README.md:122` links to `docs/getting-started/installation.md`,
112+
while the current tracked guide structure includes `docs/guides/getting-started.md`.
113+
- **Evidence:** `docs/guides/commands.md` still references backend-native web
114+
server concepts such as `cloudcli`, while current backend capability objects in
115+
`src/adjutant/core/backend_opencode.py` and
116+
`src/adjutant/core/backend_claude_cli.py` explicitly set `web_server=False`.
117+
- **Gap:** A public release cannot rely on docs that advertise commands, links,
118+
or backend behavior the shipped code does not provide.
119+
120+
### G. Cross-platform support is implemented for macOS and Linux, with operational caveats
121+
122+
- **Status:** Implemented
123+
- **Evidence:** Platform/service support exists in the setup and platform layers,
124+
including macOS launchd, Linux systemd-user, and cron-backed scheduled jobs.
125+
These paths are represented in `src/adjutant/setup/steps/service.py`,
126+
`src/adjutant/core/platform.py`, and schedule modules under
127+
`src/adjutant/capabilities/schedule/`.
128+
- **Gap:** The remaining issue is not missing platform support. It is the safety
129+
and robustness of shell-based scheduled-command execution across those supported
130+
platforms.
131+
132+
---
133+
134+
## 3. Code Quality Deep Dive
135+
136+
### Unused or weakly integrated code still exists
137+
138+
- **Declared-but-unused dependency:** `rich` appears to be unused as a runtime
139+
import. Search in `src/` found no actual `rich` import usage; only incidental
140+
text matches.
141+
- **Standalone-but-unwired installer:** `src/adjutant/setup/install.py` is a real
142+
installer, but the public release workflow still routes users through manual
143+
clone or tarball extraction plus editable install.
144+
- **Decorative or stale docs abstractions:** docs still describe retired
145+
backend-native web-server behavior while backend capability objects explicitly
146+
declare `web_server=False`.
147+
148+
### Broad exception handling is frequent
149+
150+
- **Count:** `except Exception` in `src/` = **100**
151+
- **Approximate categories gathered during this audit:**
152+
- `catch_and_log`: **41**
153+
- `fallback_default`: **28**
154+
- `silent_swallow`: **20**
155+
- `user_visible_fallback`: **3**
156+
- `reraises_or_raises`: **5**
157+
- `other`: **3**
158+
- **Observation:** `src/adjutant/core/config.py` returns defaults on parse/load
159+
errors. That is acceptable in some branches, but security-sensitive paths must
160+
explicitly fail closed. `src/adjutant/messaging/dispatch.py` does this correctly
161+
for feature-gated commands.
162+
163+
### Subprocess safety is the sharpest code-quality and security intersection
164+
165+
- **Counts:** `subprocess.run` = **44**, `subprocess.Popen` = **6**,
166+
`shell=True` = **3**, `os.system` = **0**.
167+
- **High-risk or high-scrutiny call sites:**
168+
- `src/adjutant/cli.py:1095-1097` — scheduled job execution via shell
169+
- `src/adjutant/capabilities/schedule/notify_wrap.py:78-84` — wrapper runs a
170+
command string via shell
171+
- `src/adjutant/capabilities/schedule/install.py:237-240` — KB-backed
172+
scheduled jobs via shell
173+
- **Assessment:** These do not appear to be directly fed from arbitrary Telegram
174+
input, but they are still the main hardening target before a public installer
175+
release.
176+
177+
### Naming and boundary violations are small but real
178+
179+
- **Private helper imports discovered during this audit:**
180+
- `src/adjutant/capabilities/schedule/install.py` imports `_resolve_command`
181+
- `src/adjutant/capabilities/kb/query.py` imports `_get_kb`
182+
- **Assessment:** This weakens module boundaries and violates the project's own
183+
naming conventions for underscore-prefixed internals.
184+
185+
### Dependency hygiene is imperfect
186+
187+
- Runtime dependencies are small and mostly justified.
188+
- `rich` appears unused.
189+
- Public docs still describe old backend or web-server concepts that are no
190+
longer reflected by code.
191+
- This is not a release blocker on its own, but it is visible polish debt.
192+
193+
---
194+
195+
## 4. Critical Path: P0 / P1 / P2
196+
197+
### P0 — blocks release
198+
199+
1. **Public docs advertise commands the Telegram dispatcher does not implement**
200+
- **Files:** `README.md`, `docs/guides/commands.md`,
201+
`src/adjutant/messaging/dispatch.py`,
202+
`src/adjutant/messaging/telegram/commands.py`
203+
- **Action:** Align public command docs to actual shipped handlers, or
204+
implement the missing commands before release.
205+
206+
2. **Release and install story is not coherent end-to-end**
207+
- **Files:** `.github/workflows/release.yml`, `src/adjutant/setup/install.py`,
208+
`README.md`
209+
- **Action:** Pick one supported public install path and document it
210+
consistently. If the Python installer is the intended story, wire and
211+
publish it as such. If not, stop presenting it as part of release readiness.
212+
213+
3. **Shell-based scheduled command execution needs hardening before public ship**
214+
- **Files:** `src/adjutant/cli.py`,
215+
`src/adjutant/capabilities/schedule/notify_wrap.py`,
216+
`src/adjutant/capabilities/schedule/install.py`
217+
- **Action:** Replace shell-string execution with argument-list execution where
218+
possible, or constrain and validate command generation so no user- or
219+
config-derived string reaches `shell=True` unsafely.
220+
221+
4. **Release gate requires a clearly recorded clean full test run**
222+
- **Files:** `tests/`, release/testing docs, backend and schedule test paths
223+
- **Action:** Run the full suite, resolve any failures, and make a clean full
224+
pass the explicit release gate before tagging.
225+
226+
### P1 — degrades quality
227+
228+
1. **Documentation still references retired backend-native web server behavior**
229+
- **Files:** `docs/guides/commands.md`, `docs/guides/backends.md`,
230+
`docs/guides/configuration.md`, `README.md`
231+
- **Action:** Remove CloudCLI or opencode-web-era references and align docs to
232+
the current `web/` architecture.
233+
234+
2. **Unused runtime dependency likely remains**
235+
- **Files:** `pyproject.toml`
236+
- **Action:** Remove `rich` if it is truly unused, or add the missing usage
237+
intentionally.
238+
239+
3. **Private helper imports weaken code boundaries**
240+
- **Files:** `src/adjutant/capabilities/schedule/install.py`,
241+
`src/adjutant/capabilities/kb/query.py`
242+
- **Action:** Promote these helpers to public APIs or stop importing
243+
underscore-prefixed functions across modules.
244+
245+
4. **Exception swallowing remains high**
246+
- **Files:** distributed across `src/`
247+
- **Action:** Review silent-swallow and fallback-default cases, especially
248+
around config, filesystem, and subprocess branches.
249+
250+
### P2 — acceptable to defer
251+
252+
- Fuzz or property-style testing for hand-rolled parsers (`.env`, registry,
253+
NDJSON, Claude JSON)
254+
- Further reduction of broad exception usage in non-critical paths
255+
- Cleanup of stale historical doc references and outdated test-count statements
256+
257+
---
258+
259+
## 5. Structural Strengths Worth Protecting
260+
261+
1. **Centralized dispatch security envelope**
262+
- `src/adjutant/messaging/dispatch.py` keeps auth, rate limiting, feature
263+
gating, and routing in one place.
264+
- This is worth protecting because fail-closed behavior remains reviewable and
265+
testable.
266+
267+
2. **Backend abstraction with explicit capability flags**
268+
- `src/adjutant/core/backend.py` plus backend-specific capability objects form
269+
a good boundary.
270+
- This is worth protecting because optional features can degrade via declared
271+
capabilities instead of backend-specific conditionals scattered everywhere.
272+
273+
3. **Lockfile-based lifecycle model**
274+
- `KILLED` and `PAUSED` precedence is simple and operationally legible.
275+
- This is worth protecting because it reduces hidden state and keeps recovery
276+
logic understandable.
277+
278+
4. **Hand-rolled, non-exec parsing for environment and config-adjacent inputs**
279+
- The `.env` parser and related small parsers avoid dangerous shell sourcing
280+
behavior.
281+
- This is worth protecting because it removes an entire class of injection and
282+
config-evaluation surprises.
283+
284+
5. **KB sandbox model**
285+
- KB queries and KB-local operations are scoped through controlled boundaries.
286+
- This is worth protecting because it prevents the main runtime from casually
287+
traversing external project trees.
288+
289+
---
290+
291+
## 6. Implementation Roadmap (Immediate / Short-term / Long-term)
292+
293+
### Immediate (before any public release)
294+
295+
- **Make the full test suite green and record the result****Small**
296+
- **Align README and docs with actual Telegram and CLI commands****Medium**
297+
- **Decide and unify the public installation path****Medium**
298+
- **Harden all `shell=True` schedule execution paths****Medium**
299+
- **Remove retired backend web-server references from docs****Small**
300+
301+
**Sequencing dependencies:**
302+
303+
- Docs alignment should follow the installation-path decision.
304+
- Release should wait on shell hardening and a confirmed clean full-suite pass.
305+
306+
### Short-term (next minor)
307+
308+
- **Remove unused dependency or dependency drift (`rich`)****Small**
309+
- **Clean private-helper cross-imports****Small**
310+
- **Audit and reduce silent `except Exception` cases in non-critical paths**
311+
**Medium**
312+
- **Refresh stale test-count and architecture statements in docs****Small**
313+
314+
### Long-term (next major)
315+
316+
- **Add stronger parser fuzz or property tests****Medium**
317+
- **Refactor schedule command resolution toward structured argv throughout**
318+
**Medium**
319+
- **Continue tightening backend/docs/feature-contract discipline****Medium**

site/src/css/custom.css

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@
223223
@keyframes pageIn {
224224
from {
225225
opacity: 0;
226-
transform: translateY(15px);
226+
227227
}
228228
to {
229229
opacity: 1;
@@ -312,13 +312,14 @@
312312

313313
@media (min-width: 997px) {
314314
.theme-doc-sidebar-container {
315-
background: var(--glass-subtle-bg);
316-
backdrop-filter: blur(var(--glass-subtle-blur));
317-
-webkit-backdrop-filter: blur(var(--glass-subtle-blur));
318315
border-right: var(--glass-border) !important;
319316
box-shadow: var(--glass-shadow);
320317
}
321318
}
319+
.menu {
320+
padding: 0 0.5rem !important;
321+
margin-top: 1rem;
322+
}
322323

323324
.menu__link {
324325
border-radius: var(--radius-sm);
@@ -364,6 +365,7 @@
364365
backdrop-filter: blur(var(--glass-subtle-blur));
365366
-webkit-backdrop-filter: blur(var(--glass-subtle-blur));
366367
border-top: var(--glass-border);
368+
color: var(--color-text-secondary);
367369
}
368370

369371
.footer--dark {
@@ -372,10 +374,12 @@
372374

373375
.footer__title {
374376
font-family: var(--ifm-heading-font-family);
377+
color: var(--color-text-primary);
375378
}
376379

377380
.footer__link-item {
378381
transition: color var(--transition-fast);
382+
color: var(--color-text-secondary);
379383
}
380384

381385
/* ─── Admonitions ─────────────────────────────────────── */

site/src/pages/index.module.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
position: relative;
1313
overflow: hidden;
1414
background: transparent;
15+
margin-top: calc(-1 * (var(--ifm-navbar-height) + var(--spacing-4)));
1516
}
1617

1718
.heroText {

0 commit comments

Comments
 (0)