Skip to content

v0.9.0 — Harness manager: manifest-driven adapter system

Choose a tag to compare

@codejunkie99 codejunkie99 released this 24 Apr 12:33

Added

  • Harness manager: manifest-driven adapter system. Each adapter now
    ships an adapters/<name>/adapter.json declaring 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
    new harness_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 synthesizing install.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.ps1 is now a 70-line
    thin dispatcher to the same Python backend install.sh uses. The
    new add/remove/doctor/status verbs 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.json template now uses
    {{BRAIN_ROOT}} placeholder, which the manifest backend substitutes
    with $CLAUDE_PROJECT_DIR at 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 to skills_link.target and skills_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.sh shrinks from 175 lines of bash case-statements to 35
    lines of dispatcher. All install logic moved to harness_manager/.
    Existing CLI surface preserved: ./install.sh <adapter> [target] [--yes|--reconfigure|--force] works identically.
  • install.ps1 shrinks 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.