v0.9.0 — Harness manager: manifest-driven adapter system
Added
- Harness manager: manifest-driven adapter system. Each adapter now
ships anadapters/<name>/adapter.jsondeclaring its files,
collision policy, optional skills directory mirror, and named
post-install actions. Adding a new adapter is now a JSON-only PR —
no Python code, no test wiring, no class registration. Lives in the
newharness_manager/Python package. ./install.sh add <adapter>— append an adapter to an existing
project without re-running the onboarding wizard../install.sh remove <adapter>— confirmation prompt lists every
file before deletion. Hard delete (no quarantine, no undo — git is
the safety net). Reverses post-install actions automatically (e.g.,
openclaw agents remove)../install.sh doctor— read-only audit of installed adapters.
Verifies tracked files exist, post-install state is valid,.agent/
brain is intact. Exits 0 on green, 1 on red. First run on a
pre-v0.9.0 project asks before synthesizinginstall.json— never
silently mutates../install.sh status— one-screen view of installed adapters,
brain stats (skills/episodic/lessons), last-updated timestamp..agent/install.json— authoritative record of what's installed.
Schema-versioned. Atomic write via tempfile + rename, fcntl-locked
on POSIX.- PowerShell parity from day one.
install.ps1is now a 70-line
thin dispatcher to the same Python backendinstall.shuses. The
newadd/remove/doctor/statusverbs behave identically across
mac/Linux/Windows. Was 270+ lines of duplicated bash-shaped logic. docs/per-harness/standalone-python.md— gap-fill for the only
harness that didn't have a per-harness doc.
Fixed
- #18 — Claude Code hook commands break when cwd is not the
project root.adapters/claude-code/settings.jsontemplate now uses
{{BRAIN_ROOT}}placeholder, which the manifest backend substitutes
with$CLAUDE_PROJECT_DIRat install time. Hook commands resolve
correctly regardless of which directory Claude Code's cwd points at.
Thanks to @palamp for the report and the proposal that shaped the
larger feature.
Security
- Manifest path-safety hardening (
harness_manager/schema.py). The
pre-existing path-traversal guard only tokenized on/and only
treated/-prefixed paths as absolute, so Windows-style inputs
(..\..\outside,\\server\share,C:\temp\x,C:foo) bypassed
validation and could let install/remove read or write outside the
adapter/project roots when run on Windows. Also extended the same
validation toskills_link.targetandskills_link.dst, which were
previously only checked for presence — a manifest could otherwise
point the symlink/rsync into arbitrary filesystem locations on any
platform. Both POSIX and Windows separators are now normalized
before traversal detection, and every common absolute-path form
(POSIX root, Windows root, UNC, drive-letter) is rejected.
Changed
install.shshrinks from 175 lines of bash case-statements to 35
lines of dispatcher. All install logic moved toharness_manager/.
Existing CLI surface preserved:./install.sh <adapter> [target] [--yes|--reconfigure|--force]works identically.install.ps1shrinks from 270+ lines to 70.
Migration
Existing v0.8.x users: brew upgrade agentic-stack, then run
./install.sh doctor in your project. Doctor detects existing
adapters from filesystem signals and asks before writing install.json.
Subsequent doctor runs are read-only.