70 KiB
70 KiB
Changelog
All notable changes to this project are documented here.
Format follows Keep a Changelog; versions use CalVer (YYYY.M.D with -N suffix for same-day releases) and match git tags.
Update policy and release automation live in .claude/rules/git.md § Changelog.
[Unreleased]
Added
/reflectskill (.claude/skills/reflect/SKILL.md) — deliberate whole-session "Improve" pass that operationalizes the Memory Improvement Protocol (context/rules/memory.md): scans the current conversation for durable behavioral patterns, applies the qualify filter, classifies survivors by tier, and proposesmemory/MEMORY.md/context/IDENTITY.mdadditions for explicit confirmation before writing (log-tier entry always appended). Manual-trigger, current-session scope, propose-then-confirm. Authored via the skill-builder agent forgithub:mifunedev/skills(#337)./cavemantoken-compression skill + subcommands (.claude/skills/caveman{,-commit,-review,-compress,-stats}/) — output-style mode that compresses agent prose ~65–75% via telegraphic phrasing while preserving code, API names, error strings, security warnings, and irreversible-action confirmations verbatim. Levels:lite/full/ultra/wenyan. Vendored adaptation of JuliusBrussee/caveman (MIT, commit655b7d9) authored natively to harness skill conventions; upstreamcurl | bashinstaller intentionally not run. Pinned in.mifune/skills.lockas manual/vendored entries (#335)./context-auditskill (.claude/skills/context-audit/) — data-backed, repeatable eval for the default-loaded context budget. Tier-1 scores each file on 4 dimensions (footprint, load-bearing, integrity, redundancy) and emits KEEP/TRIM/DEMOTE/CUT verdicts. Tier-2 ablation harness (runner.sh+ 7 probe files) removes a target file, runs a fixed task suite viaclaude -p, and measures behavior degradation — the only provably safe gate for cutting load-bearing content (#333)./render-htmlskill (.claude/skills/render-html/SKILL.md) — orchestrator skill for rendering an artifact as a bespoke, self-contained HTML file undermemory/<UTC-date>/<slug>.htmlfor one-shot human review (audit synthesis, council output, lint matrix, weekly digest). Output is gitignored via existingmemory/[0-9]*/rule (#314)./interviewskill (.claude/skills/interview/SKILL.md) — adaptive pre-work clarifier that batches 2–4 task-specific questions throughAskUserQuestion, echoes a 2–3 sentence scope brief, and proceeds. Skips trivial tasks with an announcement. Serves as the in-tree reference pattern forAskUserQuestion-based elicitation in future skills (#316).
Changed
- All 15 skills in
.claude/skills/now sourced from and version-pinned togithub.com/mifunedev/skills(commitc559c100) via.mifune/skills.lock;interviewandrender-htmlcontributed upstream and added to the lock (#327). README.md,docs/installation.md, anddocs/quickstart.mdrestructured to surface fork-and-clone and clone-and-own as first-class install paths alongside the upstream one-liner;scripts/install.shlocal-run detection is now the documented bootstrap for self-hosters (#331).- Skill
LICENSEfiles updated toCopyright (c) 2026 Mifune Dev (mifune.dev)to match upstream correction. - Re-synced
context-auditto the portable upstream form (mifunedev/skills#6): removed the top-levelargument-hintfrontmatter key, repinned.mifune/skills.lock(commitf95011fe, checksum02dd6324), and added the previously-missingLICENSEfor folder parity (#339).
Fixed
Removed
config.example.jsonand its install-time seeding step (scripts/install.sh); the base ships zero compose overlays and all readers tolerate a missingconfig.json, so the example template was dead weight. Packs that need overlays create their ownconfig.json(#323).
Deprecated
Security
[2026.5.18] - 2026-05-18
Added
OH_GITHUB_REPOandOH_GITHUB_REFenv vars for fork-friendly installs (#309)./worktreesskill (.claude/skills/worktrees/SKILL.md) — orchestrator skill for managing.worktrees/lifecycle: create, list, remove, clean, stale audit, project clones.
Changed
- README and
docs/installation.mdadd a "For forks / self-host" section; canonical upstreamoh.mifune.devURL unchanged (#309). /releaseskill now pushes the source branch back to origin immediately after the CHANGELOG promotion commit, before cutting the release branch. Without this, the promotion commit lived only onrelease/*, so the next round of work ondevelopmentre-carried already-released[Unreleased]entries and the next/releasewould double-promote them (#297).
Fixed
- Repaired
CHANGELOG.mddrift betweendevelopmentandmain: prior to the/releasefix above, three releases (2026.5.14,2026.5.15,2026.5.16) had promoted versioned sections onmainbut never landed those promotions back ondevelopment, leaving stale[Unreleased]entries that duplicated already-shipped content. This commit restores the versioned sections todevelopmentfrommainand trims[Unreleased]to the genuinely new (post-2026.5.16) entries (#297).
Removed
Deprecated
Security
[2026.5.16] - 2026-05-16
Added
docs/connecting.md— new runbook documenting the VSCode Attach + port-forwarding workflow for remote dev servers. Covers the "machine unreachable" debugging pattern: VS Code Remote SSH's automatic port-forwarding, manual fallback for direct-terminal users, and thelocalhost:prefix convention for accessing services on the Docker host. Referenced fromintro.md,quickstart.md,harnesses/overview.md,harnesses/t3code.md, andintegrations/slack.md. (#300)- Agents catalog: new
docs/agents/section (renamed fromdocs/agents/→docs/harnesses/after initial creation to match sidebar label). Includes_category_.jsonorganizing the section,overview.mdas the hub page, and five per-branch playbook pages (portfolio-mgr.md,blog-writer.md,linkedin-ghostwriter.md,dc-designer.md,uat-tester.md), each documenting use-case, harness selection, auth flow, and tmux launch pattern. (#300)
Changed
- Renamed
docs/agents/folder todocs/harnesses/so the folder name matches the sidebar label; added@docusaurus/plugin-client-redirectstoapps/docs/with seven redirects from/docs/agents/*→/docs/harnesses/*preserving URLs from the initial agents-catalog PR. (#300) - Cross-linked
docs/connecting.mdfromintro.md,quickstart.md,harnesses/overview.md,harnesses/t3code.md, andintegrations/slack.mdso the VSCode attach pattern is discoverable from each major entry point. (#300) - Fixed
apps/README.mdscript-name drift:pnpm --filter @openharness/docs dev→pnpm --filter @openharness/docs startto match the actualstartscript inapps/docs/package.json. (#300) - Docs frame the orchestrator-via-VS-Code-attach as the canonical workflow.
docs/quickstart.md"Enter the sandbox" now leads with the VS Code Dev Containers attach flow (Command Palette →Dev Containers: Attach to Running Container...→openharness), since it works identically on localhost and over Remote-SSH;make shellis demoted to a terminal fallback.docs/intro.md"How it works" names the orchestrator (the agent session attached at the project root that owns git, lifecycle, and edits, drives other containers over the Docker socket, and only needs host-shell intervention for things the running container can't do for itself — typically a new bind-mounted volume), frames a second sandbox as opt-in for isolation only, and closes with a Mermaid architecture diagram (orchestrator at the center of the sandbox subgraph, tmux session row,docker.sock→ optional second sandbox, external GitHub / LLM-provider edges, host bind-mount).docs/harnesses/overview.mdreplaces the redundant "Running an agent in tmux" section with "Default surfaces" (Pi+Slack, T3 Code, docs app on:3000), each as a named tmux session, with explicit guidance to open the two browser surfaces in VS Code's Simple Browser (Ctrl+Shift+P→Simple Browser: Show;Cmd+Shift+Pon macOS) so the live UI sits next to the code being edited. Documented tmux sessions renamedagent-pi→harness-piandagent-t3code→harness-t3codeindocs/harnesses/overview.mdonly — theoh config slackwizard atapps/oh/src/config/slack.tsstill createsagent-pi, andcontext/rules/sandbox-processes.mdstill defines theagent-prefix; full rename across wizard code, rule, and sibling docs (docs/intro.md,docs/integrations/slack.md,docs/harnesses/t3code.md,.pi/extensions/slack/README.md) will follow. (#302) .worktrees/README.mdnow reserves.worktrees/project/<owner>/<repo>/for durable standalone repo clones and narrows.worktrees/agent/to harness agent branches / legacy agent-owned clones, using generic examples so the layout applies cleanly to new users. (#295, #298)
Fixed
- Dark-mode inline
codepills in the docs site were nearly invisible against pure-black surfaces.apps/docs/src/css/custom.cssbackground bumped fromrgba(255, 255, 255, 0.06)→0.12, border0.1→0.22, and text raised to pure white. Light mode untouched. (#302)
Removed
Deprecated
Security
[2026.5.15] - 2026-05-15
Added
Changed
oh config slackwizard UX overhaul. Token prompts now echo●per keystroke (was: silent — looked frozen) via a TTY-aware raw-modeaskSecretthat handles backspace, Ctrl-U, and Ctrl-C; piped/non-TTY stdin still uses the legacy readline fallback asaskSecretPipedsoecho "" | oh config slackkeeps working. Flow is reframed into four numbered steps[1/4] … [4/4]with inline "Where:" hints and clickable URLs (OSC 8 hyperlinks; fall back tolabel (url)on legacy terminals). Each input shows✓ valid prefix/✓ N user(s) acceptedafter validation. A final summary screen lists the keys (tokens redacted, IDs visible) and gates the env-file write behind aProceed? [Y/n]confirmation. New helpers exported fromapps/oh/src/lib/prompt.ts:step(),link(),bold(). Zero new runtime dependencies. (#290)
Fixed
Removed
Deprecated
Security
[2026.5.14] - 2026-05-14
Added
.devcontainer/docker-compose.ymlpublishes container port 1455 to the host loopback (127.0.0.1:1455:1455) for the Pi harness login flow, whose OAuth callback bindshttp://localhost:1455. With the port on the host loopback, VS Code Remote SSH's automatic port-forwarding carries the redirect back to the laptop and Pi login completes out of the box; direct-terminal (plainssh) users still need to forward the port manually withssh -L 1455:localhost:1455 user@host. The Codex CLI is unaffected — it has its own headless path viacodex login --device-auth. (#287)
Removed
- In-tree docker-compose overlays under
.devcontainer/exceptdocker-compose.postgres.yml: the five host-auth overlays (claude-host.yml,codex-host.yml,opencode-host.yml,pi-host.yml,deepagents-host.yml), the three SSH overlays (ssh.yml,ssh-generate.yml,sshd.yml),git.yml, andcloudflared.yml. The host-auth overlays existed to share host agent credentials when the host UID matched the sandbox's UID 1000;.devcontainer/entrypoint.shnow syncs the sandbox user's UID/GID to the bind-mounted repo's owner on boot (replacing the host-group-membership workaround), so files written in either direction stay readable without per-agent overlays. Agent auth still persists in named volumes (claude-auth,codex-auth,pi-auth,opencode-auth,deepagents-auth,cloudflared-auth,gh-config);gh auth logincovers git over HTTPS without per-overlay setup. Postgres remains opt-in viadocker-compose.postgres.yml. Removed companion infrastructure:install/cloudflared-tunnel.sh, the/cloudflared-tunnelskill, the*_HOST_BIND_MOUNT/SANDBOX_PASSWORD/INSTALL_BROWSER/INSTALL_CLOUDFLARED/GIT_COMMON_DIR/HOST_SSH_DIR/HOST_*_DIRenv plumbing in.devcontainer/entrypoint.sh, and the host-UID overlay-stripping block inscripts/install.sh. Deleted doc:docs/integrations/cloudflare.md. ThecomposeOverrides[]mechanism inconfig.jsonis retained so downstream packs (Pi extensions, BYO harness packs) can still register their own overlays. (#283) - Orphaned
.pi/onboard-steps/slack.ts(and the empty.pi/onboard-steps/directory). The wizard logic lives inapps/oh/src/config/slack.tsnow, with the bugs from the original mifune port fixed (correct tmux session nameagent-pi, realpilaunch path, token-prefix validation, allowlist-ID validation, atomic env-file merge). (#281) - Stale documentation pages:
docs/onboarding.md,docs/sandbox-lifecycle.md,docs/connecting.md,docs/operations/{provision,destroy,repair}.md, anddocs/architecture/{overview,container-runtime,crons-and-heartbeats}.md. These pages described flows and tooling that no longer match the harness; rather than rewrite them, the docs site is trimmed tointro,quickstart,installation, and theguide/agents/integrationssections as the smaller accurate foundation.context/rules/repo-layout-source.mdis also removed — it pinneddocs/architecture/container-runtime.md#repo-layoutas the canonical repo-tree source; with that file gone, the rule has no anchor. Cross-references inAGENTS.md(which isCLAUDE.mdvia symlink),README.md,docs/intro.md,tasks/README.md,apps/README.md,crons/README.md,.claude/skills/harness-context/SKILL.md,context/rules/directory-readme.md,context/rules/memory.md,context/README.md,context/rules/README.md,.devcontainer/.example.env, andapps/docs/src/pages/index.tsxupdated to point at surviving docs or removed where they no longer apply. The brief## Project Structureblock inAGENTS.mdplus per-directoryREADME.mdfiles now stand in for the deleted repo-layout tree. (#279) .pi/overlays/docker-compose.slack.ymland all references to it. The in-tree Pi extension at.pi/extensions/slack/readsSLACK_APP_TOKEN/SLACK_BOT_TOKENdirectly fromprocess.envatsession_start, so the compose-time wiring overlay is redundant.docs/integrations/slack.md,README.md,docs/architecture/container-runtime.md,docs/guide/bring-your-own-harness.md,.devcontainer/docker-compose.yml, and.devcontainer/.example.envno longer reference the overlay;.pi/overlays/directory removed. Source of truth for Slack env wiring is.pi/extensions/slack/README.md.
Changed
- Migrate
.pi/extensions/slack/{index,tools}.tsfrom the deprecated@mariozechner/pi-coding-agent(and@mariozechner/pi-agent-core) to the upstream-recommended successors@earendil-works/pi-coding-agent(and@earendil-works/pi-agent-core). Pernpm view @mariozechner/pi-coding-agent's deprecation notice, the old package is no longer maintained. The other two in-tree extensions (path-guard.ts,plan-mode/index.ts) had already migrated; slack was the laggard..devcontainer/Dockerfile's[pi-coding-agent]mapping in thePKGarray,docs/agents/pi.md's upstream link,docs/installation.md's Pi row, and.pi/UPSTREAM.md's lineage label all updated to match. (#281) docs/integrations/slack.md§ 5 leads with the newoh config slackwizard; the manualset -a; source ...; tmux new-sessionritual is demoted to a<details>"Manual fallback" collapsible. Sections renumbered (8→7, 9→8). The wizard explicitly starts the Slack bridge for you at the end — kills any existingagent-pitmux session, launches a fresh one runningpiwith the new env sourced, and pollstmux capture-panefor theconnected and listeninglog line. (#281)- Sidebar label
Agents→Harnessesindocs/agents/_category_.json(and correspondingHarnesses OverviewH1 indocs/agents/overview.md). The "Pick your harness" section indocs/quickstart.mdnow links each harness to its per-harness page and adopts the t3code "authenticate at least one provider before use" framing across Codex (codex login), OpenCode (opencode auth login), Claude (OAuth on first launch), Pi (env vars), DeepAgents (~/.deepagents/.env), and the new T3 Code (npx t3+ pairing URL). Per-harness pages updated with matching Authentication sections. (#281) - Docusaurus theme: prose links inside
.markdowncontent now render in terminal green (#15803dlight /#4ade80dark) with a 1px underline (2px on hover). Sidebar / navbar / TOC / footer links unchanged — their position already signals affordance. Closes the "links blend with body text" UX issue. (#281) Makefilehelptarget now prints a "Configuration wizards" section after the auto-generated target list, surfacingoh config slackandoh --helpwith a note that they run inside the sandbox aftermake shell. Existing Make targets remain pure compose wrappers (verb-only naming preserved); wizards are listed separately as a different category. Decision rationale: 3-agent council (PM/Implementer/Critic) reviewed Makefile-target vs CLI vs hybrid shapes — picked CLI with help-text discoverability overdocker exec -itindirection (which has HIGH-severity TTY fragility through CI/non-interactive contexts). (#281)- Slack setup docs (
docs/integrations/slack.md,.pi/extensions/slack/README.md,.devcontainer/.example.env) now spell out the actual working flow: addSLACK_APP_TOKEN/SLACK_BOT_TOKEN/SLACK_ALLOW_USERS(orSLACK_ALLOW_CHANNELS) to.devcontainer/.envin ComposeKEY=valueformat, then inside the sandbox runset -a; source /home/sandbox/harness/.devcontainer/.env; set +abefore launchingpiso the child process inherits exported vars.piitself goes in a named tmux session (tmux new-session -d -s agent-pi 'pi 2>&1 | tee /tmp/agent-pi.log') percontext/rules/sandbox-processes.md. Theset -arequirement is documented as a temporary band-aid —.devcontainer/.envis dual-purpose (Compose substitution + shell source), and a future change should remove the manualset -astep. - Full rewrite of
docs/integrations/slack.mdto document ID allowlist semantics, Socket Mode smoke test, the token-freshness pattern, and migration from the legacy@ryaneggz/mifunepack;docs/quickstart.mdadds a "Next steps" section pointing to integration pages. References to the stale@ryaneggz/mifuneSlack context pack removed fromREADME.md,docs/installation.md,docs/agents/pi.md, anddocs/agents/overview.md. (#279)
Fixed
- Docusaurus marketing landing page hero quickstart still showed
cd ~/openharness && make shell, leaving new users at "no such directory" after the curl-pipe install. Updatedapps/docs/src/pages/index.tsxtocd ~/.openharness && make shellto match the installer rename in #200 / #210. The same rename had already landed inREADME.md,docs/quickstart.md, anddocs/installation.md; the JSX template literal in the home page was the last copy still pointing at the old path. pifailing on a fresh sandbox withFailed to load extension "/home/sandbox/harness/.pi/extensions/slack/index.ts": Cannot find module '@slack/socket-mode'. The in-tree Slack Pi extension imports@slack/socket-mode,@slack/web-api, andchalk, all declared in the rootpackage.jsonbut never installed automatically — the harness is bind-mounted, so a Dockerfile-time install would be shadowed at runtime..devcontainer/entrypoint.shnow runspnpm install --prefer-offlineat the harness root on first boot whennode_modules/is missing, before the cron runtime starts (which itself importscronerfrom the samepackage.json). SetSKIP_PNPM_INSTALL=1to opt out.- Docs landing page supported-agent copy and agent grid now include DeepAgents with a matching icon tile.
opencode --version(and anyopencodeinvocation) failing withEACCES: permission denied, mkdir '/home/sandbox/.config/opencode'on a fresh sandbox. Docker auto-creates~/.configas root to satisfy thegh-config:/home/sandbox/.config/ghnamed-volume mount, which then blocks the sandbox user from creating siblings like~/.config/opencode. The entrypoint's non-recursive parent-chown loop now also covers~/.configalongside the existing~/.local/~/.local/shareparents, while leaving the bind-mounted~/.config/ghcontents untouched. (#247)opencodeandopencode /connectfailing withEACCES: permission denied, mkdir '/home/sandbox/.local/state'on a fresh sandbox. Docker auto-creates~/.localand~/.local/shareas root to satisfy theopencode-hostbind-mount path; the entrypoint now non-recursively chowns those parent dirs tosandbox:sandboxso the user can create siblings like.local/state. The bind-mounted~/.local/share/opencodeitself stays untouched. Re-applies a fix that was lost when #241 merged a conflictingentrypoint.sh. (#245)
Added
oh config slack— in-sandbox CLI wizard that sets up the Slack integration end-to-end. Lives atapps/oh/(Node TypeScript, esbuild-bundled to ~13 kb, no runtime deps); installed via.devcontainer/Dockerfileto/usr/local/bin/oh(built from/opt/oh/, outside the bind-mount so the binary survives the runtime overlay). Walks the user through token entry (xapp-/xoxb-prefix validation), allowlist-mode prompt (users / channels / both withU…/C…ID validation and trim), atomic.devcontainer/.envmerge (per-key, comments preserved,<path>.tmp.<pid>+renameSyncfor crash safety), andagent-pitmux session restart withconnected and listeningpoll (15s). Pluggable viaoh config <integration>namespace — futureoh config github/postgres/cloudflareare one-file additions underapps/oh/src/config/. Replaces the orphaned.pi/onboard-steps/slack.tswith bugs fixed (correct tmux session name, realpilaunch path, prefix validation, redaction). (#281)docs/agents/t3code.md— new harness page documenting T3 Code (Theo Browne / ping.gg), the browser-based coding agent that wraps Claude/Codex/OpenCode as backends and listens on port 3773. Page includes pairing-URL auth model,npx t3invocation pattern, and tmux launch convention. Added to the harnesses overview, supported-agents table, authentication bullets, and the home-page agent grid inapps/docs/src/pages/index.tsx. (#281)build-essential(gcc, g++, make, libc6-dev, dpkg-dev) in the default sandbox image (.devcontainer/Dockerfile) so native-deps install hooks succeed out of the box — e.g.node-ptyfalling through tonode-gyp rebuildwhen no Linux prebuild is shipped, which was the root cause of thenpx t3silent-failure investigated upstream at pingdotgg/t3code#2621. Adds ~250MB to the image; intentional trade-off — the harness optimizes for "things work out of the box" over "smallest possible image". Supersedes the 707-LOC documentation-only PR #264, which was closed without merge. (#263, #271)context/rules/recursive-delegation.md: project rule encoding the inference-time structural patterns from Recursive Agent Optimization (arXiv 2605.06639, Gandhi et al., May 2026) — bounding compute (Max depth/Max children per level/Step budgetfields in briefings),Contextblock for context-as-parameter, structured-return schemas inAcceptance criteria, multi-level delegation protocol, and the orchestrator-vs-sandbox recursion boundary. The rule explicitly disclaims RAO's training-result benefits (depth-12 generalization, 2.5× wall-clock) — those require an RL-trained policy this harness does not have — and notes the harnessAgenttool is stateless/synchronous, unlike the paper'sasync launch_subagentREPL primitive.context/rules/advisor-model.mdgains aMulti-level (recursive)row in its Pipeline Variants table cross-linking the new rule;.claude/skills/delegate/SKILL.mdgains a distinct-scope decomposition rule and a recursion-authorization gate (Step 5 a.1) that confirmsMax depth/Max children per level/Step budgetare all present before allowing a worker to spawn grandchildren;.claude/protected-paths.txtregisters the new rule as load-bearing. Already-covered principles (fresh context per child, parallel-when-independent, quality-over-quantity, don't-delegate-trivial) intentionally not duplicated. (#269, #270)- Slack integration as a Pi extension at
.pi/extensions/slack/(#261). - Project-local Pi single-line footer extension showing cwd/branch, context usage, model/thinking state, extension statuses, token usage, and session name with width-aware truncation. Header copy now uses a plain
MIFUNEwordmark with anagent harnesssubtitle. - Project-local Pi config under
.pi/standing the agent up at the harness root: OpenAI-defaultsettings.json(gpt-4o, model-cycling list scoped to GPT/o-series),mifune-banner.tsextension replacing pi's startup header with a flush-leftMIFUNEwordmark +pi harness · github.com/ryaneggz/mifunesubtitle,path-guard.tsextension interceptingtool_callevents to confirm before write/edit on sensitive paths (.env*,secrets/,credentials.{json,yaml},*.pem,*.key, ssh keys) and risky bash (rm -rf,sudo,git push --force,git reset --hard, bare> /dev/sd*|nvme*|hd*|disk*) with case-insensitive matching andctx.hasUIguards for headless/RPC mode, generic consumer-agnosticAPPEND_SYSTEM.md,prompts/review.mdtemplate invokable as/review, andskills+rulesdirectory symlinks to../.claude/skills/../.claude/rulesmatching the single-source-of-truth pattern already in.codex/. New canonical.claude/skills/harness-context/SKILL.mdreachable from pi via the symlink. Test suite at.pi/extensions/__tests__/{path-guard,mifune-banner}.test.ts(32 + 7 cases, hand-rolled mockExtensionAPI, no pi devDep); pi source verified viagh apifor tool-name casing (lowercase) and write/edit canonical input key (path).vitest.config.tsincludeextended to.pi/**/__tests__/**/*.test.ts;.github/workflows/ci-harness.ymlpaths:filter extended (.pi/**,scripts/**,vitest.config.ts) and a new "Root tests" step runspnpm test:scripts, also bringing the previously-orphanedscripts/__tests__/cron-runtime.test.tsinto CI. Project Pi settings pinnpm:@tintinweb/pi-subagents@0.7.1so PR #256 starts with Claude Code-style sub-agents available in pi. (#255) - Project-local Pi plan-mode extension under
.pi/extensions/plan-mode/, with/plan,/plan approve,--plan, read-only tool/bash gating, plan approval prompts, and[DONE:n]progress tracking. - Directory README pattern: tracked
README.mdinapps/,crons/,scripts/,tasks/, and.worktrees/documenting each directory's intent, subfolder conventions, and lifecycle. New rule.claude/rules/directory-readme.mdcodifies the pattern;.gitignoreexempts only.worktrees/README.md(replacing the unused.gitkeepexemption);.claude/rules/git.md§ Worktrees points to the new README and documents the.worktrees/project/<project-name>/<repo>/slot for independent project clones;docs/architecture/container-runtime.mdmoves.worktrees/into the canonical tree (README tracked, contents ignored). Three session lessons appended tocontext/IDENTITY.mdcovering README-over-.gitkeep, "treat X same as Y" interpretation discipline, and semantic-subfolder enumeration. - OpenCode as a core sandbox agent: install
opencode-aiin the base image, persist~/.local/share/opencode, add theopencode-hostoverlay, supportscripts/ralph.sh --harness=opencode, and document OpenAI OAuth as the default OpenCode provider path. - DeepAgents CLI support as a first-class supported sandbox runtime alongside Claude Code, Codex, OpenCode, and Pi.
.devcontainer/Dockerfileinstallsdeepagents-cliviauv tool installinto/usr/local/bin;.devcontainer/docker-compose.ymladds adeepagents-authnamed volume at/home/sandbox/.deepagentsso provider keys, memory, skills, and sessions persist across rebuilds;.devcontainer/docker-compose.deepagents-host.ymlis an opt-in host-state overlay (off by default — DeepAgents stores raw provider API keys with no scope/expiry, so the blast radius is wider than the Claude/Codex host overlays);.devcontainer/entrypoint.shextends its chown loop to include.deepagentsand skips it whenDEEPAGENTS_HOST_BIND_MOUNT=1.scripts/ralph.shaccepts--harness=deepagents(orRALPH_HARNESS=deepagents) and dispatches to a constrained default invocationdeepagents -y --shell-allow-list recommended -q --no-stream --max-turns "$RALPH_DEEPAGENTS_MAX_TURNS" -n "$task"(default 25 turns);RALPH_DEEPAGENTS_FLAGSoverrides the safety/output flag string, and--max-turnsis always appended after so the per-iteration cap cannot be silently dropped.--shell-allow-list allcombined with the sandbox's mounted Docker socket can affect sibling containers or host Docker — only enable for trusted tasks via the env-var override.install/banner.shreports DeepAgents[installed]fromcommand -v deepagentsand[configured]only when~/.deepagents/.envor~/.deepagents/config.tomlis non-empty (an empty mounted directory is no longer treated as authenticated). New agent doc atdocs/agents/deepagents.md;docs/agents/overview.md,README.md,docs/quickstart.md,docs/onboarding.md,docs/installation.md,docs/operations/{provision,destroy,repair}.md,docs/guide/{overlays,permissions,configuration}.md, anddocs/architecture/{container-runtime,overview}.mdenumerate the new agent, volume, overlay, and Ralph harness option. Repo-local.deepagents/is project data and follows normal git review/ignore rules; secrets and provider keys belong only in~/.deepagentsor ignored local files. Claude remains the default Ralph harness; existing Claude/Pi/Codex execution and fallback behavior are unchanged. (#237) docs/agents/pi.mdstub (linking upstream tobadlogic/pi-mono) and a Pi entry in the home-page agent grid atapps/docs/src/pages/index.tsx, matching Pi's restoration as a default-installed CLI. (#233)- Top-level
Makefilewrappingdocker compose -f .devcontainer/docker-compose.ymlso users typemake sandbox/make shell/make destroyinstead of the 50-character compose lines. Targets:sandbox,shell,destroy,stop,logs,ps,restart,help(default, self-documenting via awk). Uses-include .devcontainer/.envsoSANDBOX_NAMEflows through. No agent-CLI targets — the harness's value is sandbox isolation, agent choice (claude/codex/pi) happens insidemake shell.
Changed
- Sandbox image-name convention flipped from
<name>-sandbox(Compose's default<project>-<service>tag) tosandbox-<name>so all harness images sort/group together indocker imagesanddocker ps..devcontainer/docker-compose.ymlnow sets an explicitimage: sandbox-${SANDBOX_NAME:-openharness}on the sandbox service; container name (${SANDBOX_NAME}) and the postgres/devnet sibling-service names (<name>-postgres,<name>-devnet) are unchanged. Existing built images on each host are left in place — the new tag takes effect on the nextmake sandboxrebuild and old*-sandboximages can bedocker rmi'd at leisure.docs/operations/destroy.mdupdated to match. (#265) - Move project rules from
.claude/rules/tocontext/rules/as the canonical, tool-agnostic location, alongside the existingSOUL.md,IDENTITY.md,TOOLS.md,USER.md..claude/rulesis retained as a directory symlink to../context/rulesso Claude Code's auto-loader keeps working unchanged. The previously inert.codex/rulesand.pi/rulessymlinks are removed — neither CLI has a rules-loading feature. Newcontext/README.mdandcontext/rules/README.mdperdirectory-readme.md. Canonical layout tree atdocs/architecture/container-runtime.mdand high-visibility teaching references (AGENTS.md,CLAUDE.md,.claude/agents/rule-builder.md) updated; ~50 scattered references in skills/agents/crons/archived PRDs left as-is — the.claude/rulessymlink resolves them. (#257) - BREAKING: Installer now clones to
~/.openharness/(was~/openharness/);scripts/install.shauto-migrates existing~/openharness/checkouts in place. - BREAKING: In-repo
.openharness/subdirectory removed entirely. - BREAKING:
composeOverrides[]config moved from.openharness/config.jsonto repo-rootconfig.json(gitignored, seeded from trackedconfig.example.json). - BREAKING:
pi-host.ymldropped from defaultcomposeOverrides— Pi users add it back manually inconfig.json. /cloudflared-tunnelskill reconstructs a missing<tunnel-id>.jsonfromcloudflared tunnel tokeninstead of failing — fixes the case where a tunnel exists in the Cloudflare account (e.g. created on another host) but onlycert.pemis on the running machine. Documents that token-mode runs (--token <T>) silently drop the local--urlflag, leaving Cloudflare to return 530s while connections register. (#249)- Quickstart collapsed from two parallel paths (installer + manual) to a single linear flow in
README.mdanddocs/quickstart.md. Manual setup demoted to a<details>block. New "Configuration" section in both docs surfaces.devcontainer/.envas the customization surface (make destroy && make sandboxto re-apply). install.shmoved toscripts/install.shto colocate withcron-runtime.tsandralph.shper the orchestrator-scripts convention. Repo-detection logic and help-text self-references updated for the new path. Action required for the curl-pipe URL: update thehttps://oh.mifune.dev/install.shredirect tohttps://raw.githubusercontent.com/ryaneggz/open-harness/refs/heads/main/scripts/install.sh.scripts/install.shsmarter: auto-detects hostgh auth tokenand prompts to share it with the sandbox (skips in-sandboxgh auth loginwhen accepted); auto-populates.devcontainer/.envwith host timezone and git identity; newprompt_ynhelper for interactive Y/n prompts; idempotency guard preserves existing.devcontainer/.envon re-runs. Dropped the unconditionalSANDBOX_PASSWORDprompt (only honored by the opt-in sshd overlay; defaults silently tochangeme). Build-time message added before the cold-cache build to set ~10-min expectations. "Next steps" output restructured to lead with the.devcontainer/.envpath so the customization surface is discoverable.CLAUDE.mdLifecycle section uses the newmaketargets (make sandbox,make shell,make ps,make destroy); deeper inspection commands (docker exec ... tmux ls) keep their docker-native form..devcontainer/.example.env: top header rewritten to document the file as the single customization surface;INSTALL_AGENT_BROWSERdefault flipped fromtruetofalse(~1 GB / +3 min on first build, opt-in only when needed);SANDBOX_PASSWORDcomment clarified to note it's only honored with the sshd overlay.- Consolidate repository layout documentation into
docs/architecture/container-runtime.md#repo-layout; reduce duplicate tree blocks inAGENTS.mdandREADME.mdto one-line pointers; add.claude/rules/repo-layout-source.mdto prevent the next drift round. Remove phantom heartbeat env vars (HEARTBEAT_ACTIVE_START,HEARTBEAT_ACTIVE_END,HEARTBEAT_AGENT,HEARTBEAT_INTERVAL) fromdocs/architecture/container-runtime.mdand.devcontainer/.example.env. Fix brokenREADME.mdcroner link (was.claude/specs/structure-spec-v0.7.md, nowdocs/architecture/crons-and-heartbeats.md).
Added
- Restore
@mariozechner/pi-coding-agentas a default-installed CLI alongside Claude Code and Codex.DockerfileAGENTSdefault goes back toclaude-code,codex,pi-coding-agent;.devcontainer/docker-compose.pi-host.ymloverlay restored and listed in.openharness/config.jsoncomposeOverrides;.devcontainer/entrypoint.shextends its host-bind skip-chown loop with.pi/PI_HOST_BIND_MOUNT. Pi auth shares the same trust tradeoffs as the claude/codex host overlays (host UID = 1000 + pre-existing~/.pi). The Mom Slack bot stays out of base — install@ryaneggz/mifunefor that.docs/installation.md,docs/onboarding.md,docs/operations/{provision,repair}.mdupdated; stalemomshell alias dropped frominstall/.zshrc(leftover from #209). "type": "module"in rootpackage.jsonto silence the NodeMODULE_TYPELESS_PACKAGE_JSONwarning emitted on everycron-runtime.tsinvocation. The script already uses ESMimportsyntax; no CommonJS inscripts/to break.## Active itemswatchlist insidecrons/heartbeat.md— session-curated section the hourly heartbeat reads each pulse to validate deferred follow-ups across session boundaries via an enumerated permitted-checks list (gh pr view,gh issue view,gh run list,gh release list, date-based reminders). Cron is read-only on the section; sessions add and remove lines. Newcrons/.cron.log(gitignored undercrons/*.log) appended each pulse as a one-line ISO-8601 liveness signal — additive to the existingmemory/<today>/log.mdwrites.context/USER.mdgains a 3-sentence "Tracking deferred follow-ups" pointer at theAuthorization patternsboundary. Plan at.claude/plans/polished-spinning-dijkstra.mdsurvived 3 critic rounds (round 1 rejected a separatememory/HEARTBEAT.md, round 2 rejectedAGENTS.mddocumentation, round 3 converged on the v5 shape). (#224)- Memory concept: long-term
memory/MEMORY.md, daily logs atmemory/YYYY-MM-DD/log.md, and canonical write-side protocol incontext/rules/memory.md; auto-loaded via CLAUDE.md session-start list.
Removed
ohCLI references and the multi-agent / N-worktree / heartbeat-daemon copy from the marketing landing page atapps/docs/src/pages/index.tsx; quickstart code block now usesmake shell, hero + architecture + WHY sections rewritten to "we provide the sandbox, you choose the harness".docs/agents/overview.mdsimilarly drops the "Why run multiple agents" framing and the deletedoh harness addinvocation. (#233)- Gemini hidden from the docs sidebar and sitemap via
unlisted: trueindocs/agents/gemini.md(Docusaurus 3); page stays reachable by direct URL for old links. The home-page agent grid swaps the Gemini tile for Pi. (#233) - Stale files missed in #223:
.devcontainer/tests/cli-binaries.sh,.devcontainer/init-env.sh(orphan helper —install.shwrites.devcontainer/.envdirectly and docker compose loads it from that folder by default),.claude/posts/{linkedin,x}.md,tsconfig.base.json,.claude/plans/crispy-beaming-torvalds.md. Doc tree comments indocs/architecture/container-runtime.mdand.openharness/README.mdupdated to drop theinit-env.shreferences. (#228) - Pruned four orphaned files in
.openharness/left over from the v0.7 convergence:agents(broken symlink to deletedworkspace/.claude/agents/),agent/settings.json(referenced non-existentgpt-5.4model andlastChangelogVersion: 0.66.1; no loader onmain),banner.json(custom-banner skill deleted infb71365), andsettings.json(pointed at non-existent./.claude/skills/). Refreshed.openharness/.gitignoreheader and added.openharness/README.mddocumenting the remaining live file (config.json) and the dormant status ofCaddyfile/exposures.json. The directory's load-bearing role —composeOverridesconsumed byinstall.shand the container build — is unchanged. (#222) - Remove 0 eligible stale remote branches after critic-gated review; preserve all live remote branches because none met the >60-day deletion gate, and the backup branch still contains unique commits. (#213)
- Remove five stale or corrupted
.worktrees/agent directories and stale worktree registrations, reducing the ignored worktree footprint below 100 MB. (#213) - Remove the dead legacy install-side setup, entrypoint, and tmux wrapper scripts now that the Dockerfile wires
.devcontainer/entrypoint.shdirectly. (#213) - Remove the empty untracked
packages/web-ui/andpackages/slack/husks, plus the stale Slack workspace and entrypoint references. (#213) - Remove the obsolete on-disk SPEC v0.6 artifact so
.claude/specs/only exposes canonical tracked specs. (#213) - BREAKING:
oh harness adddeprecated;mifune(and any other harness pack) installs viagit clone+ manualcpper the pack's README for v1. The CLI-driven pack installer was deleted along withpackages/sandbox/in US-006; itsfetchGitPack(command-injection-prone) andregisterComposeOverlays(path-traversal-prone) plumbing is gone with it. A redesigned, security-first standalone installer (~50 LOC) tracked for v0.8 in #211: URL allowlisting, signature/SHA verification, sandboxed install, command-injection-safespawnSync, path-traversal-safe overlay resolution, atomic registry write. Per SPEC v0.7 §"Pack mechanism status in v0.7". (#210) - BREAKING: workspace template emptied of pi-coupled scaffolding. Deleted
workspace/HEARTBEAT.md,workspace/IDENTITY.md,workspace/MEMORY.md,workspace/SOUL.md,workspace/TOOLS.md,workspace/USER.md(six identity files belonging to the v0 multi-agent persona);workspace/heartbeats/(replaced by rootcrons/per US-002),workspace/.ralph/,workspace/.codexsymlink,workspace/.openharnesssymlink, andworkspace/memory/(instance state in template);workspace/.claude/skills/{compress,content-gate,eval-conciseness,quality-gate,wiki-ingest,wiki-lint,wiki-query,ralph,prd,ci-status}/(ten workspace skills);workspace/.claude/agents/{council,critic,implementer,pm,agent-builder,command-builder,rule-builder,skill-builder}.md(eight sub-agents); andworkspace/.claude/hooks/notify_slack.sh(Slack hook + its references inworkspace/.claude/settings.local.json). Rewroteworkspace/AGENTS.md(and theCLAUDE.mdsymlink) as a generic ~22-line agent-runtime stub. Kept:workspace/AGENTS.md,workspace/startup.sh,workspace/.claude/.example.env.claude,workspace/.claude/rules/{code-quality,git,token-conservation}.md,workspace/.claude/settings.local.json,workspace/.claude/screenshots/.gitkeep. The workspace template is now agent-runtime-agnostic; identity, skills, sub-agents, and routines come from a harness pack (e.g.@ryaneggz/mifune), not from this directory. Per SPEC v0.7 §"Harness Packs". (#210) - BREAKING: orchestrator skill set triaged to a defensible 4-skill core. Deleted
.claude/skills/{delegate,harness-audit,strategic-proposal,skill-lint,prd,ralph}/(six skill directories that mapped to v0 multi-agent / autonomous-agent flows). Converted.claude/skills/{provision,destroy,repair}/to plain Markdown documentation atdocs/operations/{provision,destroy,repair}.md(the operations are nowdocker composeinvocations, not skills). Surviving orchestrator skills:/release,/ci-status,/cloudflared-tunnel,/agent-browser. Stale heartbeat/daemon/worktree-discovery docs (docs/heartbeats/,docs/architecture/daemon.md,docs/architecture/worktrees.md) deleted alongside; incidentalworkspace/heartbeats/references indocs/guide/{configuration,workspace}.mdanddocs/agents/{overview,claude-code}.mdrewritten to point at the croner runtime +crons/. Pack-side counterparts forcloudflared-tunnelandagent-browsertracked inryaneggz/mifune#1and#2. Per SPEC v0.7 §"Orchestrator vs workspace agent skills". (#210) - BREAKING: multi-agent comparison narrative archived. Deleted the still-draft
blog/2026-04-29-worktree-per-agent.md; movedblog/2026-04-28-byoh.mdtoblog/archive/2026-04-28-byoh.mdwitharchived: truefrontmatter and a top-of-post note that v1 framing differs. Stripped the residual "side-by-side" wording fromdocs/agents/overview.md. Per SPEC v0.7 §"oh CLI" + §"Documentation source"; the v1 ICP statement at.claude/ICP.mdnow explicitly rejects multi-agent comparison-shopping framing as out-of-scope. (#210) - BREAKING:
@openharness/sandboxCLI removed;docker composeis the canonical substrate. Deleted thepackages/sandbox/workspace package (CLI binary + harness/onboard/lib/tools source + tests), the entry frompnpm-workspace.yaml, thelink:cliscript from rootpackage.json, the now-stale.github/workflows/ci.yml(sandbox-only CI), and the duplicate.github/workflows/build.yml(which had been pushing a driftedghcr.io/ryaneggz/open-harnessimage alongside the canonicalghcr.io/ryaneggz/openharnessproduced byrelease.yml). The CLI build/symlink block in.devcontainer/entrypoint.shthat wired/usr/local/bin/openharnessand/usr/local/bin/ohis gone.release.ymlis now the sole image producer. Per SPEC v0.7 §"oh CLI". (#210) - BREAKING: heartbeat daemon removed. Deleted
packages/sandbox/src/lib/heartbeat/(~1,752 LOC),packages/sandbox/src/cli/heartbeat-daemon.ts,packages/sandbox/src/cli/actions/heartbeat.ts,packages/sandbox/src/tools/heartbeat.ts, theoh heartbeat {start,stop,status}command group, theheartbeat-daemonpackage bin, the sevenheartbeat-*.test.tssuites, and.claude/skills/heartbeat/. Heartbeat env vars (HEARTBEAT_ACTIVE_START/_END/_AGENT) stripped from.devcontainer/docker-compose.yml; the legacy install-side daemon-startup blocks and the/usr/local/bin/heartbeat-daemonsymlink in.devcontainer/entrypoint.share gone;install/banner.shno longer advertisesheartbeat-daemon status. The croner runtime (scripts/cron-runtime.ts, US-002/US-003/US-004) is the canonical replacement per SPEC v0.7 §"Croner runtime". (#210) - BREAKING:
@mariozechner/pi-coding-agentis no longer a dependency. The pi agent CLI and Mom Slack bot have been extracted to a separate harness pack atryaneggz/mifune(npm:@ryaneggz/mifune). Install withoh harness add @ryaneggz/mifune. (#208)
Added
context/folder at repo root — orchestrator identity layer per the gist v0.6 spec §"context/" (https://gist.github.com/ryaneggz/8f6811efa144ac94d3cdc383846134d8), adapted for single-user harness scope. Four files:SOUL.md(voice and disposition, ~30 lines),IDENTITY.md(operating principles + append-only lessons learned, ~80 lines),TOOLS.md(environment inventory, ~40 lines),USER.md(working-relationship patterns, living document, ~45 lines).AGENTS.mdbootloader updated with a session-start read instruction;.claude/protected-paths.txtextended with the four new entries so future cleanup passes do not delete them. Implements the session-loaded identity layer the v0.7 convergence (PR #212, US-013) correctly removed fromworkspace/(pack territory) but never created at the orchestrator level. TheIDENTITY.mdlessons-learned section captures the meta-principles surfaced this session (revealed > stated preference, critic-gate before destructive actions, short feedback loops over speculative infrastructure). (#220).claude/protected-paths.txt— list of load-bearing skills, scripts, and config paths that critics must NOT propose deleting without an explicit override note in the finding's RECOMMENDATION column. Wired into.claude/agents/critic.md(general adversarial review) and.claude/skills/ship-spec/SKILL.mdstage 3 (PRD critic gate). Replaces the per-invocation usage-logging proposal (closed as #217) after Critic B's proportionality argument: zero runtime overhead, works on day 1, ~20 LOC vs. an 8-story PRD with hooks. The v0.7 convergence (PR #212, US-012) deleted six load-bearing skills under "defensible 5-skill set" rationale; this list is the gate that would have caught it. (#218)/ship-specv1.1: stages 3 and 5 reordered — critics run BEFORE the GH issue is opened (was: issue first, then critics). Earlier ordering created dangling issues when critics halted; now no GitHub-side state changes until the spec passes the critic gate. Surfaced during the dogfood run on issue #217. (#218)/ship-specorchestrator skill at.claude/skills/ship-spec/SKILL.md. Composes/prd→ 2 critics (parallel, asymmetric: implementer + user lens) → critique gate →/ralph→gh issue→ branch + push →gh pr create --draftinto one durable invocation. Critics write totasks/<slug>/critique.md; pipeline HALTs on any high-severity finding without mitigation. v1 stops at draft PR; loop launch + CI verification stay manual until the critic phase has been proven valuable across 2-3 real runs. Idempotent at every stage. (#215)- v1 Ideal Customer Profile statement at
.claude/ICP.md: primary persona (single working developer, one project, agent-tended), top three jobs-to-be-done, top three needs, and explicit anti-ICP (not multi-tenant SaaS, not non-developers, not production agent operators, not comparison-shopping tinkerers). (#210) - Seeded the two SPEC-reserved crons:
crons/heartbeat.md(hourly pulse,0 * * * *) andcrons/cleanup-tasks.md(Sunday 23:00,0 23 * * 0). Bodies follow SPEC v0.7 §"Croner runtime" + §"Weekly cleanup cron"; substrate stays empty otherwise so users add their own. (#210) .devcontainer/entrypoint.shnow startsscripts/cron-runtime.tsin asystem-crontmux session on container boot, replacing the legacyheartbeat-daemonwatchdog block. Idempotent (tmux has-sessionguard); restart policy is per-container-start per SPEC v0.7 §"Croner runtime". (#210)scripts/cron-runtime.ts— minimal croner-backed runtime (≤120 LOC) that readscrons/*.mdfrontmatter, schedules per-cron tasks, runs the body as a prompt toclaude -p(or$CRON_AGENT_BIN), logs tocrons/.cron.log, and uses a PID-lock atcrons/.pidto prevent double-firing. Replaces the 1,900-LOC heartbeat daemon per SPEC v0.7. (#210)- SPEC v0.7 amendments at
.claude/specs/structure-spec-v0.7.md— additive-only revision resolving seven v0.6 conflicts (canonical image name, docs path,ohCLI deprecation, croner runtime contract, hook execution mechanism, memory directory format, tasks vs.ralphpaths) and adding sections for harness packs, orchestrator-vs-workspace skill scope, and shrunk prose on Docusaurus config / eval flakiness / wiki-sync rubric / blog authorship / weekly cleanup. (#210) - README "Docker only (no installer)" section — concise compose-based deploy path for hosts that have only Docker + git.
- Per-page OpenGraph + canonical link tags via theme.config.tsx head function (#140).
- Blog post draft: Worktree-per-agent — stages for Wed publish (#145).
- Blog section at /blog and About page nav entry (#143).
- Blog post: BYOH — stop installing agent CLIs on your laptop (#144).
- Root
CHANGELOG.mdand Keep-a-Changelog workflow documented in.claude/rules/git.md;/releasenow promotes[Unreleased]to the new version section at tag time. - Generate
sitemap.xmlandrobots.txtduring docs build vianext-sitemap(#141). - Launch runbook consolidating manual cutover steps (DNS, GH settings, OG validation, GSC, promotion).
- Docusaurus v3 docs site at
apps/docsdeployed to oh.mifune.dev (#164).
Changed
- Consolidated cron runtime log onto
crons/.cron.log; the daemon no longer writescrons/cron-runtime.log. Both files were already gitignored undercrons/*.log. (#228) - Aligned the remaining flat-format memory references in tracked docs to the directory-per-day form per SPEC v0.7 §"Memory structure". Updated
docs/guide/workspace.md(tree comment + daily-logs paragraph),docs/guide/identity.md(file table + memory protocol step + how-it-works paragraph), anddocs/architecture/container-runtime.md(workspace tree comment) to usememory/YYYY-MM-DD/log.md. Flatmemory/<date>.mdfiles are deprecated. (#210) - BREAKING:
CLAUDE.mdrewritten fordocker compose-only orchestrator instructions. The Lifecycle (Setup/Validate/Teardown), Permissions, "What You Do", "Exposing apps", and Project Structure sections no longer referenceopenharness sandbox/list/shell/clean/heartbeatoroh expose/oh harness add; commands now usedocker compose -f .devcontainer/docker-compose.yml up -d --build,docker compose ps,docker exec -it -u sandbox openharness zsh, anddocker compose ... down -v. Skills table trimmed to the 4-skill triaged set (/release,/ci-status,/cloudflared-tunnel,/agent-browser); provision/destroy/repair are documented indocs/operations/. The orphanedpackages/sandbox/entry in the project-structure block is removed andscripts/+crons/are added..claude/skills/cloudflared-tunnel/SKILL.mdno longer referencesoh expose(the gateway relationship is now described via.claude/rules/gateway-routing.md);.claude/skills/ci-status/SKILL.mdupdated to the actual workflow nameCI: Harness. Per SPEC v0.7 §"oh CLI" + §"Orchestrator vs workspace agent skills". (#210) - BREAKING:
docs/installation.md,docs/onboarding.md,docs/sandbox-lifecycle.md, anddocs/connecting.mdrewritten to removeohCLI references. Installation is nowdocker compose -f .devcontainer/docker-compose.yml up -d --build; sandbox lifecycle usesdocker compose up/stop/down -v; connecting usesdocker exec -it -u sandbox <name> zsh. Onboarding is now a manual checklist run inside the sandbox (gh auth, claude, optional ssh / cloudflared / pack-supplied Slack). Deleted the entiredocs/cli/reference tree (overview, oh-sandbox, oh-shell, oh-clean, oh-onboard) and aligned strayoh expose/oh cleanmentions indocs/integrations/{cloudflare,github,postgres}.md,docs/architecture/{overview,container-runtime}.md, anddocs/guide/overlays.md. Per SPEC v0.7 §"oh CLI". (#210) - BREAKING:
README.md,docs/intro.md, anddocs/quickstart.mdrewritten for single-project framing. The "run Claude, Codex, Gemini, and Pi side-by-side" tagline is gone; the harness is now framed as a Docker-based agent harness for one project, agent-tended over time. Quickstart leads withdocker compose -f .devcontainer/docker-compose.yml up -d --build; allohCLI references in these three files are gone (multi-agent setups now point at the@ryaneggz/mifuneharness pack). Per SPEC v0.7 §"oh CLI". (#210) - BREAKING:
install.shrewritten as a docker-compose-only installer. Removed--cli,--with-cli,--install-nodeflags and the auto-detect / 3-waychoose_pathprompt; removeddetect_node,install_nvm, the nvm SHA-256 pin, thepnpm setup+pnpm link --global ./packages/sandboxblock, and the local-repopackages/sandbox/package.jsondetection at the repo-resolution step. The script now only checks Docker + git, clones / pulls into~/openharness, prepares host auth dirs (~/.claude,~/.codex,~/.claude.json), writes.devcontainer/.env, runsdocker compose -f .devcontainer/docker-compose.yml up -d --build, and prints next-steps usingdocker exec -it -u sandbox <name> zshanddocker compose ... down -v. Per SPEC v0.7 §"oh CLI". (#210) install.shcurl-pipe target renamed~/.openharness→~/openharnessso the cloned project no longer collides with the in-repo.openharness/config dir (~/.openharness/.openharness/was visually and semantically confusing). One-time migration: existing~/.openharnessclones aremv'd to~/openharnessautomatically when the new path is absent. In-container paths (/home/sandbox/.openharness) are unchanged. (#200)- Reverted the sandbox/orchestrator vocabulary realignment (#170, #172). The in-container Linux user is
sandboxagain (UID/GID 1000 preserved); theORCHESTRATOR_USER/ORCHESTRATOR_HOMEconstants are removed. The package name@openharness/sandbox, compose service, container default,SANDBOX_NAMEenv var,POSTGRES_USER, andsandbox_*Pi tool prefix were never changed.install/banner.shcarries an inverted migration guard for users coming back from a renamed image. (#198) - Consolidate documentation:
/docs/is now the single source of truth, served by Docusaurus fromapps/docs/viapath: '../../docs'. Enabled blog at/blog/. Removed the duplicateapps/docs/docs/tree. (#178) - Installer auto-detects Node 20+; new
--cli/--docker-only/--install-nodeflags;--with-clideprecated. (#176). - README and installation docs now use the short
https://oh.mifune.dev/install.shURL (302 redirect to the raw GitHub install script onmain) instead of the longraw.githubusercontent.comURL. /releasenow executes the[Unreleased]→[$VERSION]promotion (was prose-only) andrelease.ymlsources the GitHub Release body from the promoted CHANGELOG section viabody_pathinstead ofgenerate_release_notes, so the GitHub Release notes match the changelog byte-for-byte.- Revert prior secondary product name; "Open Harness" is the sole brand across README, docs, and onboarding (#157).
- Cloudflare onboarding step now requires an explicit public hostname (no default domain) (#157).
- Slim README to ~110 lines, lead with oh CLI flow (#139).
- Wiki promoted from
workspace/wiki/todocs/wiki/— same structure (pages/,sources/,index.md,log.md), now top-level alongside human-curated docs. - 26 docs pages converted from Nextra MDX to plain markdown rendered by GitHub.
Fixed
make sandboxandscripts/install.shnow expand.openharness/config.jsoncomposeOverridesinto-fflags so the default claude/codex/pi host-auth bind-mounts actually apply on a fresh install. Previously both paths ran the base compose file only, silently falling through to named-volume auth despite the documented intent. Also pre-creates~/.pialongside~/.claudeand~/.codexin the install-time host-auth-dir loop, and removes residual references to the deleted/provisionskill across docs and agent files.- Pi icon on the home-page agent grid no longer renders dim. Restored the inline
PiIconReact component pattern from #168 (commitfbda6a5) socurrentColorinverts cleanly between eggshell light and pure-black dark themes — the previous<img src="/img/agents/pi.svg">wiring sandboxed the SVG document and lost thecurrentColorinheritance.apps/docs/static/img/agents/pi.svgreverted tofill="currentColor"so the file stays theme-adaptive if loaded directly elsewhere. (#233) .claude/hooks/deny-env-dump.shno longer false-denies ongh ... --body "$(cat <<'EOF' ... EOF)"invocations whose prose contains words likehistoryor phrases likecat .env. Heredoc bodies are now stripped viaperl -0777before pattern matching (handles<<DELIM,<<'DELIM',<<"DELIM",<<-DELIM). The Tier-2ASKrule forecho|printfof any uppercase$VARwas also removed — too broad on benignecho "Branch: $BRANCH"patterns; the deny tier above already catches secret-named variables (TOKEN,SECRET,AUTH,KEY,GH_TOKEN,AWS_*, …)..claude/skills/ship-spec/SKILL.mdupdated to note heredoc bodies are now safe (was: "prefer--body-fileover heredoc"). (commit3ec98fe)- Correct the container runtime documentation to show Dockerfile
ENTRYPOINT ["entrypoint.sh"]invoking.devcontainer/entrypoint.shdirectly, withinstall/banner.shonly sourced for interactive shell status. (#213) - Restored six orchestrator skills removed in error during the v0.7 convergence (US-012, commit
fb71365):/ralph(PRD →prd.jsonconverter),/prd(PRD generator),/harness-audit(parallel-sub-agent codebase audit),/skill-lint(skill staleness scorer),/delegate(parallel execution coordinator), and/strategic-proposal(council-based roadmap planning). The triage rationale ("workspace-agent skills, not orchestrator") was wrong: the orchestrator actively uses theprd.jsonschema for its own task management (e.g.tasks/openharness-v07-convergence/prd.json), so removing the tools that produce that schema was a regression.scripts/ralph.sh(the runner) was kept all along — only the wrapper skills were lost. Restored fromfb71365^unchanged; CLAUDE.md skills table updated. install.shnow auto-disables the*-host.ymloverlays in.openharness/config.jsonwhen host UID ≠ 1000 (was: a multi-line warning telling the user to do it by hand). Mode-0600 credential files in~/.claude/~/.codex/~/.pican't be read across UIDs, and mode-0700 dirs (e.g.~/.pi/agent/sessions/) reject writes from non-owner UIDs — the sandbox user (UID 1000) would EACCES onoh/claude/codex/pi. The new logic usesjqto filterclaude-host.yml,codex-host.yml,pi-host.ymlout ofcomposeOverridesso the base named volumes take over. The original warning is retained as ajq-missing fallback. (#202)- Host auth (
~/.claude,~/.codex,~/.pi) is shared into the sandbox again.install.shnow pre-creates the three auth dirs and~/.claude.json(empty if missing) before sandbox bring-up so docker can't auto-create them root-owned, andclaude-host.yml/codex-host.yml/pi-host.ymlare restored to defaultcomposeOverrides. UID-mismatch hosts (UID ≠ 1000) get a loud install-time warning telling them to drop the overlays from.openharness/config.json(mode-0600 credential files can't be read across UIDs). Together this restores the convenience that was lost in #194 / #195 without re-introducing the EACCES failure mode that motivated those PRs. (#196) oh/claude/codexno longer fail withEACCES(or silent re-auth) on freshinstall.shinstalls. Removeddocker-compose.claude-host.yml,docker-compose.codex-host.yml, anddocker-compose.pi-host.ymlfrom the defaultcomposeOverridesin.openharness/config.json. Each overlay's own header documents that it requires host UID 1000 + the source dir to pre-exist; shipping them as defaults broke any host where either condition wasn't met (docker auto-creates missing source dirs as root → sandbox user (UID 1000) can't write). The base compose'sclaude-auth/codex-auth/pi-authnamed volumes now take effect by default;entrypoint.shchowns them to UID 1000 on first boot. Single-laptop developers wanting cross-sandbox auth sharing can opt back in by appending the relevant overlay(s) to.openharness/config.json. (#194)oh sandboxno longer fails on freshinstall.shinstalls with a Caddyfile bind-mount error. Removeddocker-compose.gateway.ymlanddocker-compose.cloudflared.ymlfrom the defaultcomposeOverridesin.openharness/config.json; both are additive overlays now loaded only when needed (oh exposere-adds the gateway viaSandboxConfig.addOverride()). (#192)install.shnext-steps now leads with a numbered "source your shell rc" step that detects$SHELL(bash→~/.bashrc,zsh→~/.zshrc,fish→~/.config/fish/config.fish) so users don't have to exit + reopen their shell to pick upoh/node/pnpm. Curl-piped install runs in a child bash whose exports cannot reach the parent shell — the source step is now Step 1 of next-steps (was a buried "Reminder").install.shbootstrapsPNPM_HOMEbeforepnpm link --globalso the CLI install no longer dies withERR_PNPM_NO_GLOBAL_BIN_DIRon fresh nvm-installed Node. Runspnpm setup(writesPNPM_HOMEexport to~/.bashrc+~/.zshrc) and also exportsPNPM_HOME/PATHinline so the link step succeeds in the current shell regardless of rc state.install.shno longer silently exits when sourcing a pre-existing~/.nvm/nvm.shunderset -euo pipefail. nvm + corepack calls are bracketed with relaxed strict mode and explicit$?checks, anERRtrap surfaces unexpected failures with the failing command and line, and pnpm is pinned to10.33.0(matchespackage.json#packageManager) instead of resolvingpnpm@latestover the network on every install.- Slack bot no longer drops oversized agent replies with cascading
msg_too_longerrors. Main message is capped at 2,900 chars with a_message truncated — full response in thread_footer; full content spills to thread replies;setWorking(false)always clears the working indicator. (#135)
Removed
- Removed legacy
/docs/{plans,wiki,launch-runbook,blog}/andapps/docs/docs/tree (consolidated into/docs/). (#178) - Nextra docs site and the
.github/workflows/docs.ymldeployment — documentation is now plain markdown indocs/, read in the GitHub UI. - Reference Next.js application at
workspace/projects/next-app/, along with its CI jobs (workspace/projects/next-apppaths inci.yml/release.yml) and the release pre-flight gate referencing it. - Root
package.jsonscripts:dev,docs:dev,docs:build,docs:preview.
Deprecated
Security
Release history prior to this file: see git tags and GitHub Releases. Most recent pre-changelog tag: 2026.4.22.