114 Commits
Author SHA1 Message Date
ryaneggzandClaude Opus 4.7 b17242590c task: rename agent-pi → client-slack tmux session + restore on restart
- Add `client-` prefix to sandbox-processes.md naming table for
  external-surface clients bridging an in-sandbox agent.
- Tighten the `agent-` example off interactive CLIs; document that
  claude/codex/opencode are foreground tools, not tmux sessions.
- entrypoint.sh: restore client-slack on container start when
  SLACK_APP_TOKEN + SLACK_BOT_TOKEN are present and `pi` is installed.
- Propagate rename through wizard code, READMEs, and docs.
- Fold in half-finished harness-pi rename from #302.

Closes #344

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 20:39:51 +00:00
ryaneggzandClaude Sonnet 4.6 84777e5ee6 task: improve self-hosting DX for fork-and-clone and clone-and-own
Surface scripts/install.sh local-run detection as three equal-weight install
paths (upstream / fork-and-clone / clone-and-own) in README, installation.md,
and quickstart.md. No script changes — the installer already handled both
self-hosting flows; docs were the only gap.

Closes #331

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 04:23:05 +00:00
Ryan EgglestonandClaude Opus 4.7 2a54508627 FROM feat/308-fork-friendly-install TO development (#309)
* feat: scaffold fork-friendly-install task

Four-file contract per SPEC v0.7 §tasks/:
- prd.md: 7 user stories with post-critic-mitigation AC
- prd.json: schemaVersion 1, branchName feat/308-fork-friendly-install
- prompt.md: Ralph iteration instructions
- progress.txt: empty header
- critique.md: 2-critic review (implementer + user lens),
  all 6 H-severity findings mitigated; 1 M-severity ICP.md
  drift flagged as separate orchestrator hygiene

Source: 5-seat AI council unanimous Option E (Hybrid B+A) +
Critic concur-with-amendments. Parameterizes the clone source
via OH_GITHUB_REPO so a forked Open Harness installs the
forker's code, not upstream's; keeps oh.mifune.dev canonical
upstream URL unchanged.

Tracks #308. PRD generated by /prd; reviewed by 2 critics
(implementer + user lens); converted by /ralph.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: US-005 — README adds a "For forks / self-host" block

Inserts a ### 📦 For forks / self-host subsection into README.md after
the closing paragraph of ## 📦 Install and before ## 🚀 Use it. Includes
blockquote visual-hierarchy guard, matching <your-org>/<your-fork>
placeholders in both curl URL path and OH_GITHUB_REPO env var, branch
substitution note, mutable-HEAD trust caveat, and .devcontainer/ footnote
with concrete patch guidance. Upstream line 17 is byte-identical.

* feat: US-001 — OH_GITHUB_REPO env var parameterizes the clone

- Adds OH_GITHUB_REPO="${OH_GITHUB_REPO:-ryaneggz/open-harness}" immediately after REPO_DIR is set (line 180) and before the migration block (line 182)
- Validates with bash [[ =~ ]] regex (^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$); dies with clear message on mismatch
- Emits warn "Cloning from fork: $OH_GITHUB_REPO" when non-default value supplied
- Replaces both hardcoded clone URLs (with and without --branch) with https://github.com/${OH_GITHUB_REPO}.git in lockstep
- bash -n passes; shellcheck: baseline 11, post-edit 11 (no new warnings)

* task: US-001 — update progress.txt with commit SHA dbf8623

* feat: US-002 — OH_GITHUB_REF aliases OH_INSTALL_REF

Adds OH_GITHUB_REF alias resolution block after the fork-warn block,
before the population/migration classification. When both
OH_GITHUB_REF and OH_INSTALL_REF are set to differing non-empty
values, a warn fires before the alias resolution overrides
OH_INSTALL_REF. The fresh-clone branch-guard now keys on the
resolved $OH_GITHUB_REF, so either var triggers --branch clone form.

Back-compat preserved: OH_INSTALL_REF=v1.2.3 with OH_GITHUB_REF
unset still results in --branch v1.2.3 (alias resolves to v1.2.3).
No deprecation warning emitted in this release.

bash -n: PASS. shellcheck: 11 warnings (no regression vs baseline).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: US-003 — pull path validates remote against OH_GITHUB_REPO

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: US-004 — help text documents OH_GITHUB_REPO and OH_GITHUB_REF

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: US-007 — CHANGELOG records OH_GITHUB_REPO/REF additions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 14:18:33 -06:00
Ryan Eggleston f8006f4825 task: docs runbook + agents catalog (#301)
Closes #300.
2026-05-15 22:14:45 -06:00
Ryan Eggleston 5951874e06 task: docs orchestrator-as-default + arch diagram + VS Code attach flow (#303)
Lead `docs/quickstart.md` "Enter the sandbox" 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 shell` demoted to a terminal fallback.

Add an orchestrator-as-default framing block to `docs/intro.md` "How it works" plus a Mermaid architecture diagram showing the host/sandbox split, the orchestrator at the center of the sandbox subgraph, the tmux session row, the `docker.sock` path to an optional second sandbox, and external GitHub / LLM-provider edges.

Repurpose `docs/agents/overview.md` "Running an agent in tmux" into "Default surfaces" (Pi+Slack, T3 Code, docs app) with VS Code Simple Browser guidance. Rename documented tmux sessions to `harness-pi` / `harness-t3code` in this page only — `apps/oh/src/config/slack.ts` and `context/rules/sandbox-processes.md` still use the `agent-` prefix; full rename will follow.

Fix dark-mode inline-code pill contrast in `apps/docs/src/css/custom.css` (background 0.06 → 0.12, border 0.1 → 0.22, text → pure white).

Docs-only; tests not run.

Closes #302
2026-05-15 21:33:12 -06:00
ryaneggzandClaude Opus 4.7 6e51b4b88c fix: reframe port 1455 mapping as Pi-harness-specific
The 1455 callback is the Pi harness's own OAuth login flow, not Codex.
Codex CLI has its own headless path (codex login --device-auth) and
doesn't need the port. Move the detail to docs/agents/pi.md with a
cross-reference note in codex.md; correct CHANGELOG and the compose
comment.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 06:20:00 +00:00
ryaneggzandClaude Opus 4.7 cb8b5dfea6 task: document Codex callback port 1455 for Pi harness login
Detail in docs/agents/codex.md that codex login is a prerequisite for
the Pi harness, that the 1455 callback works out of the box via VS Code
Remote SSH, and that direct-terminal users must forward the port
manually. Link CHANGELOG entry to issue #287.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 06:14:13 +00:00
ryaneggzandClaude Opus 4.7 d14bc330eb task: cloudflared/SSH/host-overlay doc cleanup (keep postgres)
Apply PR #284's doc updates selectively — cloudflared, SSH overlays,
host-bind overlays, SANDBOX_PASSWORD, and openssh-server references
removed everywhere. Postgres mentions preserved; postgres compose
overlay restored.

Doc edits:
- AGENTS.md / CLAUDE.md (symlink): drop /cloudflared-tunnel skill row,
  rewrite "Exposing apps" to mention generic tunnels/proxies.
- README.md, docs/installation.md: drop SANDBOX_PASSWORD, cloudflared,
  openssh-server, host-overlay references.
- docs/quickstart.md: keep postgres link, drop cloudflare link, mention
  postgres overlay is opt-in.
- docs/integrations/github.md: drop SSH-overlay section.
- docs/integrations/cloudflare.md: deleted.
- docs/agents/{deepagents,opencode}.md: drop host-overlay sections.
- context/rules/git.md: drop "Advanced opt-ins" SSH section.
- Makefile: drop _check-jq / _check-config gates; jq invocation is now
  defensive (only runs when jq + config.json both present).
- apps/docs/src/pages/index.tsx: keep postgres in "composable substrate"
  copy, drop cloudflare tunnels / Caddy gateway mentions.
- .claude/skills/{agent-browser,harness-audit,strategic-proposal}/SKILL.md
  and .claude/agents/command-builder.md: drop cloudflared references
  (strategic-proposal infra row keeps PostgreSQL 16).
- CHANGELOG.md [Unreleased] § Removed: new entry for #283 listing the
  10 deleted overlays + companion infrastructure; note postgres was
  kept.

Infra:
- Restored .devcontainer/docker-compose.postgres.yml.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 02:36:15 +00:00
OpenHarness Bot 49db140d21 Merge remote-tracking branch 'origin/development' into feat/281-oh-config-slack
# Conflicts:
#	CHANGELOG.md
2026-05-12 22:44:50 -06:00
OpenHarness BotandClaude Opus 4.7 a4642042de feat: oh config slack — in-sandbox Slack integration setup wizard
Standalone CLI at apps/oh/ (Node TS, esbuild ~13kb, no runtime deps).
Walks user through token entry (xapp-/xoxb- prefix validation), allowlist
mode (users/channels/both with U…/C… ID validation), atomic .env merge
(temp+rename for crash safety), and agent-pi tmux restart with
'connected and listening' poll. Pluggable as oh config <integration>
namespace for future github/postgres/cloudflare wizards.

Bundled prerequisites and adjacent polish:
- Migrate .pi/extensions/slack/{index,tools}.ts from deprecated
  @mariozechner/pi-coding-agent to @earendil-works/pi-coding-agent
  (per upstream npm deprecation notice)
- Sidebar label Agents → Harnesses; per-harness pages get unified
  Authentication section (codex login / opencode auth login / etc)
- New T3 Code harness page (browser UI on port 3773)
- Docs theme: prose links now green + underlined for affordance
- Slack docs § 5 leads with `oh config slack`; manual procedure
  demoted to <details> Manual fallback
- Drop orphaned .pi/onboard-steps/ (logic moved to apps/oh/)
- Makefile help adds Configuration wizards section pointing at
  oh config slack (3-agent council picked CLI over Make-target
  due to docker exec -it TTY fragility)

Closes #281

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 22:26:26 -06:00
OpenHarness BotandClaude Opus 4.7 9241da6e5c task: drop stale docs/guide subdir + sweep README/ICP refs
Removes the legacy docs/guide/ pages superseded by the new harness +
integrations sections, plus the broken README links and the orphan
.claude/ICP.md. Matches the ongoing stale-docs cleanup on this branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 22:22:06 -06:00
OpenHarness BotandClaude Opus 4.7 5036a93273 task: drop stale onboarding/lifecycle/connecting/architecture/operations docs
Removes nine documentation pages whose content no longer matches the
harness (`docs/onboarding.md`, `docs/sandbox-lifecycle.md`,
`docs/connecting.md`, `docs/operations/{provision,destroy,repair}.md`,
`docs/architecture/{overview,container-runtime,crons-and-heartbeats}.md`)
plus the now-orphaned `context/rules/repo-layout-source.md` rule that
pinned the architecture page as the canonical repo-tree source. The
docs site is left with `intro`, `quickstart`, `installation`, and the
`guide` / `agents` / `integrations` sections as the smaller accurate
foundation; per-directory `README.md` files plus the brief
`## Project Structure` block in `AGENTS.md` cover layout.

Closes #279

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 19:30:53 -06:00
OpenHarness BotandClaude Opus 4.7 2366f7b551 task: drop slack compose overlay; extension is source of truth
The in-tree Pi extension at .pi/extensions/slack/ reads SLACK_APP_TOKEN /
SLACK_BOT_TOKEN directly from process.env at session_start, so the
.pi/overlays/docker-compose.slack.yml wiring overlay is redundant.

- Delete .pi/overlays/docker-compose.slack.yml and the empty .pi/overlays/ dir
- Rewrite docs/integrations/slack.md setup with the actual working flow
  (set -a; source .devcontainer/.env; set +a + named tmux session)
- Mirror the same flow in .pi/extensions/slack/README.md "How to Run"
- Rewrite the Slack section of .devcontainer/.example.env with the set -a
  pattern and rationale, plus commented placeholders for both allowlist vars
- Remove overlay references from README.md, docs/architecture/container-runtime.md,
  docs/guide/bring-your-own-harness.md, and .devcontainer/docker-compose.yml
- CHANGELOG entries under [Unreleased] > Removed + Changed; flag the set -a
  step as a band-aid pending a wrapper / extension fallback

Closes #276.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 23:36:21 -06:00
OpenHarness BotandClaude Opus 4.7 dc96472d3a task: flip sandbox image-name convention to sandbox-<name>
Built images defaulted to Compose's `<project>-<service>` tag,
producing `<name>-sandbox`. With multiple sandboxes on one host the
suffix scatters them in `docker images` listings.

Add an explicit `image: sandbox-${SANDBOX_NAME:-openharness}` to the
sandbox service so the tag sorts/groups together. Container name and
postgres/devnet sibling-service names are unchanged; existing built
images are left in place and the new tag takes effect on the next
`make sandbox` rebuild.

Closes #265

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 22:41:47 -06:00
OpenHarness BotandClaude Opus 4.7 f31960c5d5 task: drop redundant ASCII-art diagram from architecture overview
The mermaid diagram above already renders on GitHub and Docusaurus;
the ASCII duplicate added maintenance cost without value.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 23:24:21 -06:00
OpenHarness BotandClaude Opus 4.7 3039ef0b0d task: point docs/agents/ at in-tree Slack extension
docs/agents/pi.md and docs/agents/overview.md previously sent
Slack-curious users to the @ryaneggz/mifune harness pack. With the
in-tree .pi/extensions/slack/ extension landing in this PR, both
pages now lead with the extension path and demote mifune to "legacy,
still works during transition."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 23:19:49 -06:00
OpenHarness BotandClaude Opus 4.7 e7e96ccfdd feat: add Slack support to .pi/ as a Pi extension
Adds .pi/extensions/slack/ with Socket Mode bridge, allowlist gating,
and 4 LLM-callable tools (slack_post/reply/react/upload). Inbound
messages bridge into pi.sendUserMessage() with ctx.isIdle() guard;
turn_end posts the assistant's reply back to Slack via SlackContext.
session_shutdown tears down the Socket Mode connection.

Customizations preserved from portfolio-advisor reference:
- threadTs field on event types (7 sites in events.ts)
- threadParent routing in createSlackContext (context.ts:45)
- exported parseEventContent + buildSyntheticEvent

Tests: 27 new (3 files); 78 pre-existing tests still green; 114 total.

Plan: .claude/plans/context-study-https-github-com-ryaneggz-binary-hartmanis.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 23:03:04 -06:00
OpenHarness BotandClaude Opus 4.7 aa6fd0026e feat: adopt openclaw memory concept (#259)
Two-tier markdown memory adapted from https://docs.openclaw.ai/concepts/memory:
long-term `memory/MEMORY.md` + daily logs at `memory/YYYY-MM-DD/log.md`.
Formalize the Memory Improvement Protocol as a canonical rule, fix path
drift across skills (workspace/memory/ -> memory/, file form -> subdir
form), and wire the read side via the AGENTS.md/CLAUDE.md session-start list.

New:
- context/rules/memory.md - canonical Memory Improvement Protocol (lifted
  + generalized from delegate/SKILL.md so any skill can reference it)
- memory/README.md - directory README per context/rules/directory-readme.md
- memory/MEMORY.md - long-term lessons stub (append-only)
- memory/x-campaign.md - relocated from memory/2026-05-04/ via git mv
  (it's a tracked persistent note, not a daily log)

Edits:
- AGENTS.md - session-start list extended with MEMORY.md, today's log,
  and pointer to the new rule
- .gitignore - ignore memory/[0-9]*/ daily logs; top-level memory files
  remain tracked
- docs/architecture/container-runtime.md - memory/ entry in the canonical
  Repo Layout tree
- .claude/skills/{delegate,harness-audit,skill-lint,strategic-proposal}
  /SKILL.md - replace inlined Memory Protocol with cross-ref to the new
  canonical rule; fix workspace/memory/ -> memory/; fix
  memory/YYYY-MM-DD.md (file form) -> memory/YYYY-MM-DD/log.md (subdir
  form) to match what the heartbeat cron and 5 existing daily dirs
  already use
- CHANGELOG.md - Unreleased entry

Plan: .claude/plans/study-https-docs-openclaw-ai-concepts-m-cozy-babbage.md

Closes #259

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:57:30 -06:00
OpenHarness BotandClaude Opus 4.7 9647ead2ec task: update canonical layout tree for context/rules/ relocation
Annotate .claude/rules/ as 'symlink → context/rules/'. Expand context/ block
with its identity-file children plus the new rules/ child annotated as the
canonical, tool-agnostic location. Add one prose sentence below the tree
describing the access model (Claude Code via symlink; Codex/Pi consume
context/rules/ directly).

Mandatory follow-up to PR #258 per .claude/rules/repo-layout-source.md
which requires the canonical tree to update whenever a top-level directory
is added or moved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:28:44 -06:00
OpenHarness BotandClaude Opus 4.7 7bb3c4b3f0 feat: repurpose .openharness as install root
Deletes the in-repo .openharness/ subdir, moves composeOverrides config
to repo-root config.json (gitignored, seeded from config.example.json),
and reworks scripts/install.sh to clone into ~/.openharness/ with an
in-place migration for existing ~/openharness/ checkouts.

Closes #251

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:52:08 -06:00
OpenHarness BotandClaude Opus 4.7 f27e3aadf1 task: directory README pattern + rule
Add tracked README to apps/, crons/, scripts/, tasks/, .worktrees/
documenting each directory's intent, subfolders, and lifecycle.
Codify the pattern as .claude/rules/directory-readme.md so future
directories follow it.

.gitignore now exempts only .worktrees/README.md (replacing the
unused .gitkeep exemption); .claude/rules/git.md § Worktrees
points to the new README and documents the
.worktrees/project/<project-name>/<repo>/ slot for independent
project clones (own .git, not harness branches);
docs/architecture/container-runtime.md moves .worktrees/ into
the canonical tree.

context/IDENTITY.md gains three lessons from this session:
README-over-.gitkeep for tracked-empty dirs, "treat X same as Y"
interpretation discipline, and semantic-subfolder enumeration in
directory READMEs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:22:07 -06:00
OpenHarness Bot 40a5a58a72 feat: US-005 — document DeepAgents support 2026-05-03 20:28:00 -06:00
OpenHarness BotandClaude Opus 4.7 ffe989310f feat: US-003 — add a DeepAgents host-state overlay
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 20:25:16 -06:00
OpenHarness BotandClaude Opus 4.7 de7b62e72d feat: add OpenCode as a core sandbox agent
Install opencode-ai in the base image, persist ~/.local/share/opencode,
add the opencode-host overlay (bind-mount host auth), wire opencode-host
into default composeOverrides, support scripts/ralph.sh --harness=opencode,
and document OpenAI OAuth via /connect as the default OpenCode auth path.

Closes #239

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 19:45:06 -06:00
OpenHarness Bot 90d5808065 Updates codex to work 2026-05-03 18:48:25 -06:00
OpenHarness Bot 748e8079a2 feat: US-007 — Drift cleanup in workspace docs (workspace.md, uat-testing.md) 2026-05-03 17:42:23 -06:00
OpenHarness BotandClaude Opus 4.7 05be240986 feat: US-004 — add forward link to canonical repo layout in overview.md
Append a one-line pointer to the existing "Where to go next" section
linking docs/architecture/container-runtime.md#repo-layout. The
topology diagrams (mermaid + ASCII) are untouched.

Refs #235.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:59:10 -06:00
OpenHarness BotandClaude Opus 4.7 bd07712902 feat: US-003 — reduce README tree to pointer + fix broken croner link
- Replace the ## 🗂️ Project layout fenced tree (lines 78-85) with
  a one-line pointer to docs/architecture/container-runtime.md
  #repo-layout. Heading retained so the section anchor stays stable
  for inbound links.
- Line 6: fix the broken croner-runtime link that pointed at
  .claude/specs/structure-spec-v0.7.md (the file is at
  .claude/specs/archive/...). New target is the canonical
  docs/architecture/crons-and-heartbeats.md.
- Create docs/architecture/crons-and-heartbeats.md as a stub with
  sidebar_position: 3 frontmatter so the README link does not 404
  in the interim. PR-B replaces stub content with the full doc.

Refs #235.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:58:58 -06:00
OpenHarness BotandClaude Opus 4.7 235b33037f feat: US-001 — rewrite canonical tree in container-runtime.md
- Add {#repo-layout} anchor to ## Repo Layout heading.
- Replace tree block with the canonical tree from
  .claude/plans/we-can-focus-on-cuddly-harp.md, including all live
  top-level dirs (.claude, .codex, .devcontainer, .github, .husky,
  .openharness, apps, blog, context, crons, docs, install, scripts,
  tasks, workspace) and trimming workspace/ to its real contents.
- Drop phantom env-var rows (HEARTBEAT_ACTIVE_START,
  HEARTBEAT_ACTIVE_END, HEARTBEAT_AGENT) from the env-vars table;
  add the live CRONS_DIR and CRON_AGENT_BIN overrides instead.
- Trim "Workspace identity files" table to actual workspace/
  contents (AGENTS.md, CLAUDE.md symlink, startup.sh, .claude/);
  note that SOUL/IDENTITY/TOOLS/USER live under top-level context/.
- Excluded-from-tree footnote calls out node_modules/, .pnpm-store/,
  .worktrees/ as gitignored / transient.

Refs #235.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:58:08 -06:00
OpenHarness Bot f378cc17c8 Take all changes 2026-05-03 16:24:05 -06:00
OpenHarness BotandClaude Opus 4.7 348692d231 feat: home page v1 positioning — drop oh CLI, hide Gemini, add Pi
The marketing landing page at oh.mifune.dev was still on v0: pitched
the removed `oh onboard` / `oh shell` CLI, the archived multi-agent
"N worktrees" narrative, the removed heartbeat daemon, and listed
Gemini while omitting Pi.

New positioning: "We provide the sandbox. You choose the harness."
The sandbox is the product; the agent CLI inside is the user's call.
Pi is positioned as "a lightweight, customizable harness" — distinct
from the fixed-CLI shape of Claude Code and Codex.

Five edits:
- apps/docs/src/pages/index.tsx — content rewrite (~14 sections);
  Quickstart code block uses `make shell`; agent grid swaps Gemini
  for Pi; WHY cards drop multi-agent / N-worktree / heartbeat copy;
  hero + architecture sections rewritten
- apps/docs/static/img/agents/pi.svg — fill="currentColor" replaced
  with hardcoded #1a1a1a so the icon renders inside <img> tags
  (currentColor doesn't inherit through sandboxed SVG-via-img)
- docs/agents/overview.md — drop Gemini row, drop "Why run multiple
  agents" + per-agent SOUL framing, drop deleted `oh harness add`
- docs/agents/gemini.md — add `unlisted: true` (Docusaurus 3) so
  Gemini is hidden from sidebar/sitemap while staying reachable
  via direct URL for old links
- docs/agents/pi.md — new stub, links upstream to badlogic/pi-mono

Closes #232

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 15:20:24 -06:00
OpenHarness BotandClaude Opus 4.7 f36bcf2628 feat: simplify quickstart — Makefile + smarter installer + single docs path
Two commands from zero to working sandbox: `curl ... | bash` then
`make shell`. Collapses the previous installer/manual fork, hides the
50-char compose lines behind `make sandbox/shell/destroy`, auto-detects
host gh token, and surfaces .devcontainer/.env as the customization
surface. Moves install.sh to scripts/ alongside cron-runtime.ts and
ralph.sh.

Closes #230

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 11:21:51 -06:00
OpenHarness BotandClaude Opus 4.7 17de8f458e task: prune stale files + consolidate cron logs
Pass 2 of stale-file cleanup, after PR #223 narrowly scoped to .openharness/.

Removed:
- .devcontainer/tests/cli-binaries.sh (no caller)
- .devcontainer/init-env.sh (documented in 2 places but never invoked;
  install.sh:187-192 seeds the file directly and docker compose loads
  it from .devcontainer/ by default)
- .claude/posts/{linkedin,x}.md (orphan drafts)
- tsconfig.base.json (never extended)
- .claude/plans/crispy-beaming-torvalds.md (lone plan tracked despite
  the **/.claude/plans gitignore rule)

Changed:
- scripts/cron-runtime.ts:21 — log path renamed
  crons/cron-runtime.log -> crons/cron.log so the daemon and per-cron
  bodies share one log file. Both names were already gitignored under
  crons/*.log.
- docs/architecture/container-runtime.md and .openharness/README.md —
  drop init-env.sh references from tree comment and consumers list.
- CHANGELOG.md [Unreleased] — drop the now-stale "distinct from the
  daemon-level cron-runtime.log" clause from the heartbeat-watchlist
  entry; update scripts/cron-runtime.ts entry to point at cron.log.

Closes #228

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 10:26:08 -06:00
OpenHarness BotandClaude Opus 4.7 d79b7ae2c3 feat: restore pi-coding-agent as default sandbox CLI
Re-add @mariozechner/pi-coding-agent to the base Dockerfile AGENTS
list and recreate the docker-compose.pi-host.yml overlay deleted in
PR #209. The Mom Slack bot stays in @ryaneggz/mifune; only the pi
binary and host-auth wiring come back to base. Brings the orchestrator
in sync with what install/banner.sh and the pi-auth named volume
already advertise.

Also silence the Node MODULE_TYPELESS_PACKAGE_JSON warning emitted on
every cron-runtime.ts invocation by setting "type": "module" in root
package.json (cron-runtime.ts already uses ESM imports; no CommonJS in
scripts/ to break).

Closes #226

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 10:16:50 -06:00
OpenHarness Bot e7baab2f3d audit: US-003 — Delete dead install scripts (critic-gated)
Risk Assessment (critic gate):
- High/Low: accidental deletion of the active entrypoint; mitigation: only removed legacy install-side scripts, preserved .devcontainer/entrypoint.sh, and verified Dockerfile COPY plus docker compose config.
- Medium/High: stale docs or skills could point agents at deleted files; mitigation: updated harness-audit, container-runtime docs, AGENTS, install-prereq notes, cloudflared references, changelog, and task docs.
- Medium/Medium: external/manual workflows could still invoke removed helpers; mitigation: retained supported banner/cloudflared assets and documented system-package or INSTALL_CLOUDFLARED=true install path.
- High/Low-Medium: missed active caller outside normal grep scope; mitigation: ran tracked grep for legacy setup/install-entrypoint paths and checked tmux wrapper references before deletion.

Critic invocation note: Claude Task tool was unavailable in this pi API harness; the critic prompt was executed read-only via codex exec before deletion using .claude/agents/critic.md's rubric. No high-severity finding lacked a mitigation.

Validation:
- docker compose -f .devcontainer/docker-compose.yml config
- pnpm run lint
- pnpm -r --if-present run typecheck
- pnpm run test
2026-05-02 19:18:06 -06:00
OpenHarness Bot 9b540b9e4d audit: US-001 — Delete obsolete spec v0.6 from disk + fix call-graph claim 2026-05-02 19:05:18 -06:00
OpenHarness Bot 32436cc5d1 task: US-014 — migrate memory structure to directory-per-day
Align the remaining flat-format memory references in tracked docs to
the canonical memory/YYYY-MM-DD/log.md form per SPEC v0.7 §"Memory
structure". docs/guide/workspace.md (tree comment + daily-logs
paragraph), docs/guide/identity.md (file table + how-it-works +
memory-protocol step), docs/architecture/container-runtime.md
(workspace tree comment). The grep-gate AC `memory/[0-9]{4}-[0-9]{2}-
[0-9]{2}\.md` returns zero hits in tracked files. CLAUDE.md and
.claude/skills/repair/SKILL.md required no edits (CLAUDE.md does not
reference memory format; repair/ was deleted in US-012).

Refs: #210
2026-05-02 15:17:54 -06:00
OpenHarness Bot fb7136581f task: US-012 — triage orchestrator skills to defensible set
Drop six skills (delegate, harness-audit, strategic-proposal, skill-lint,
prd, ralph), convert provision/destroy/repair to docs/operations/, keep
release/ci-status/cloudflared-tunnel/agent-browser. Delete stale
heartbeat/daemon/worktree-discovery docs and patch incidental refs to
point at the croner runtime + crons/. Pack-side counterparts tracked in
ryaneggz/mifune#1 and #2. Per SPEC v0.7 §"Orchestrator vs workspace agent
skills".

Refs #210
2026-05-02 15:09:33 -06:00
OpenHarness Bot 9a0ea70f25 task: US-011 — archive multi-agent blogs and write anti-ICP
Delete the still-draft blog/2026-04-29-worktree-per-agent.md and move
blog/2026-04-28-byoh.md into blog/archive/ with archived: true and a
top-of-post note that the v1 framing differs. Add .claude/ICP.md with
primary persona, three JTBDs, top-3 needs, and an explicit anti-ICP
table (not multi-tenant SaaS, not non-developers, not production agent
operators, not comparison-shopping tinkerers). Strip the residual
"side-by-side" wording from docs/agents/overview.md so the grep gate
clears outside blog/archive/. Per SPEC v0.7 + the v07-convergence PRD.

Refs #210
2026-05-02 15:02:37 -06:00
OpenHarness Bot b88ff4e79a task: US-009 — rewrite remaining docs to remove oh CLI references
Closes part of #210.
2026-05-02 14:53:05 -06:00
OpenHarness Bot 69aba9900a task: US-008 — rewrite README and docs/intro.md for single-project framing
Per SPEC v0.7 §"oh CLI". Drops the multi-agent side-by-side framing and
all oh CLI references from README.md, docs/intro.md, docs/quickstart.md.
Quickstart leads with docker compose -f .devcontainer/docker-compose.yml
up -d --build; multi-agent setups now point at @ryaneggz/mifune.
Refs #210
2026-05-02 14:43:55 -06:00
Ryan EgglestonandOpenHarness Bot 6064fb739e FROM breaking/extract-mifune-to-pack TO development (#209)
* feat!: extract pi-coding-agent + slack to ryaneggz/mifune

BREAKING CHANGE: pi-coding-agent dep, packages/slack, slack/pi-host
overlays, and pi-specific docs all removed. Users who want the prior
behavior install the mifune harness pack:

  oh harness add @ryaneggz/mifune

See ryaneggz/mifune for the extracted code and docs (npm:
@ryaneggz/mifune, image: ghcr.io/ryaneggz/mifune:latest).

Closes Phase C of the openharness/mifune split. Phase A landed in PR
#208 (pack contract); Phase B published the mifune repo + tag 2026.5.2.

Changes:
- Drop @mariozechner/pi-coding-agent from packages/sandbox/package.json
- Add @types/node devDep (was a transitive of the dropped pi dep)
- Remove packages/slack (Mom slack bot)
- Remove .devcontainer/docker-compose.{slack,pi-host}.yml overlays
- Remove .openharness/extensions/custom-banner.ts
- Remove packages/sandbox/extensions/{sandbox,claude-rules}.ts
  (only consumers were the pi-extensions API)
- Remove packages/sandbox/src/onboard/steps/slack.ts
  (now contributed by the mifune pack via onboard_steps[])
- Strip slackStep from ALL_STEPS export in onboard/steps/index.ts
- Update onboard-pack-steps test: slack is no longer a core step
- Default Dockerfile AGENTS to "claude-code,codex" (was including
  pi-coding-agent); drop `alias mom=...` in .bashrc
- Default .openharness/config.json drops slack/pi-host overlays
- Strip test-slack job + packages/slack path triggers from ci.yml
- Strip INSTALL_PI_AGENT / INSTALL_MOM env vars + prompts from
  install/setup.sh; suggest `oh harness add @ryaneggz/mifune` instead
- Replace pi-auth symlink + Mom auto-launch in entrypoint.sh with a
  generic harness-pack hook loop (/usr/local/bin/*-entrypoint-hook.sh)
- Strip .pi from the chown skip-loop in entrypoint.sh (no more
  PI_HOST_BIND_MOUNT)
- Update README.md, AGENTS.md/CLAUDE.md, docs/{intro,quickstart,
  installation,onboarding,agents/overview,guide/{overlays,permissions,
  configuration,identity},integrations/slack}.md, apps/docs/src/pages/
  index.tsx — strip pi/slack mentions, link to @ryaneggz/mifune
- Add CHANGELOG entry under [Unreleased] § Removed

Signed-off-by: OpenHarness Bot <noreply@openharness.local>

* chore: gitignore .claude/worktrees, drop stale heartbeat, log 2026-05-02

- .gitignore: ignore .claude/worktrees/ — agent worktrees registered against the
  in-container git dir leak into host git status as untracked at the project root.
  Their content lives on the registered branches (and via squash merge typically
  ends up in development), so the host root never needs to track them.
- workspace/heartbeats/resume-bc471449-continue.md: removed (untracked). Per
  workspace/memory/2026-05-02.md, the heartbeat fired and the target Claude
  session ID was already gone ("No conversation found"). Stale; daemon was
  emitting failures every 10:31 UTC.
- workspace/memory/2026-05-02.md: today's daily memory log — same pattern as
  the 23 prior 2026-04-*.md files already tracked under workspace/memory/.

Companion to #209 (mifune extraction); cleans up loose orchestrator state.

Signed-off-by: OpenHarness Bot <noreply@openharness.local>

---------

Signed-off-by: OpenHarness Bot <noreply@openharness.local>
Co-authored-by: OpenHarness Bot <noreply@openharness.local>
2026-05-02 10:48:56 -06:00
9db79fbcfd FROM feat/207-pi-decouple-pack-contract TO development (#208)
* task: parameterize Dockerfile agent CLI installs via ARG AGENTS

Replace hardcoded `npm install -g @anthropic-ai/claude-code @openai/codex
@mariozechner/pi-coding-agent` with a build-arg-driven loop.

`ARG AGENTS` defaults to `claude-code,codex,pi-coding-agent` so the
default build behavior is unchanged (non-breaking). Downstream images
or future PRs can override via `--build-arg AGENTS="claude-code,codex"`.

Adds `SHELL ["/bin/bash", "-c"]` so `declare -A` (associative array
mapping agent key → npm package) is available; the previous Debian-sh
default would not parse it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* task: decouple ToolDefinition types from pi-coding-agent

* feat: add onboard step plugin contract for harness packs

Define HarnessPack and PackStep types and a registry-based loader
(loadPackSteps + orderSteps + getAllSteps) that merges core onboard
steps with steps contributed by installed harness packs. The loader
reads .openharness/harnesses.json, dynamic-imports each pack's compiled
step modules, and topo-orders the result via the after-by-id map.

Wires getAllSteps() into the onboard CLI entrypoint so pack authors can
extend onboarding without forking the core package. Slack step stays
hardcoded in ALL_STEPS for now; Phase C extracts it to mifune as the
first user of the plugin contract.

Adds 8 unit tests covering missing/empty registry, importer override,
pack step loading, error swallowing, and topo ordering.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: migrate oh CLI to Commander.js

Replace the hand-rolled subcommand router (~260 lines of switch in
cli/index.ts plus ~324 lines of helpers in cli/cli.ts) with a
Commander.js-based program. Each subcommand is now a single
.action(...) call that lazy-loads its implementation from
src/cli/actions/*.ts via dynamic import — keeps cold-start fast for
--help and --version.

Notable changes:
- Drop `import { main, VERSION } from "@mariozechner/pi-coding-agent"`.
  Bare `oh` no longer launches a TUI; Commander auto-prints help.
- `--version` returns the package.json version (no "(pi VERSION)"
  suffix).
- Heartbeat is now a subcommand group: oh heartbeat start|stop|status
  <name> (replaces the legacy `oh heartbeat <action> <name>` form;
  drops `migrate` action entirely).
- New harness subcommand group: oh harness add|list|remove. Action
  handlers print "not yet implemented (T5)" and exit 1 — wiring lands
  in the harness-pack-contract PR.
- Host-only enforcement (sandbox/run/stop/clean/shell/list) moved
  from an ad-hoc check to a Commander preAction hook.
- buildProgram() exported for tests so they can introspect the
  registered command tree without spawning a subprocess.

Tests rewritten to verify the Commander program structure
(registered commands, required vs optional args, option flags,
subcommand groups). The legacy parseToolArgs / resolveSubcommand /
helpText / formatResult helpers are gone; the surface they tested
no longer exists.

24 test files / 349 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: add harness-pack contract (oh harness add|list|remove)

Build the openharness side of the openharness/mifune split:

src/harness/pack.ts — pack source resolver (npm / git / local) plus
installer + uninstaller pipeline. The resolver classifies a `oh harness
add <spec>` argument into one of three modes:
  - @scope/name | bare name → npm install -g
  - owner/repo | https:// | git@ → git clone
  - ./path | /abs            → local symlink (no copy)

After source resolution, every pack runs the same install pipeline:
validate harness.json, append compose_overlays to .openharness/config.json,
run install-hook.sh, symlink entrypoint-hook.sh into /usr/local/bin/, and
register the pack in .openharness/harnesses.json. Side effects route
through a PackEnv injection bag so unit tests swap fakes.

src/harness/registry.ts — moved from onboard/registry.ts to its proper
home alongside the installer. Extended with writeHarnessRegistry,
addInstalled, removeInstalled. Defensive parser upgrades pre-T5 entries
in place (missing source/spec default to "local" + path).

src/cli/actions/harness.ts — replace the T2-era "not yet implemented"
placeholders with real installPack / uninstallPack / readHarnessRegistry
calls, formatted output for the CLI surface.

docs/guide/bring-your-own-harness.md — pack contract reference for
authors: schema, source modes, onboard-step shape, distribution options.

Adds 25 unit tests covering source resolution, manifest validation,
registry round-trip, install/uninstall against a tmp pack with mocked
PackEnv. 26 test files / 382 tests pass total.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* task: make @openharness/sandbox installable via npm link

- packages/sandbox/package.json: add postbuild chmod +x on bin scripts
  (tsc strips the executable bit; npm link / npm install -g need it).
  Add `files` field listing the publishable surface so `npm publish`
  produces a clean tarball.
- package.json: split the broken `pnpm link --global` out of `setup`
  (PNPM_HOME = /usr/local/share/pnpm is root-owned in the sandbox image
  so the global link errors EACCES). Replace with an explicit
  `pnpm run link:cli` script the user opts into when they have a
  user-writable pnpm prefix.
- docs/contributing.md: document the build-and-link sequence + clarify
  that the orchestrator sandbox's entrypoint already auto-links the
  CLI on every container boot, so `pnpm run link:cli` is only needed
  on a local-laptop checkout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: OpenHarness Bot <noreply@openharness.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 10:17:34 -06:00
OpenHarness BotandClaude Opus 4.7 3d104a5b45 task: rename curl-install path ~/.openharness → ~/openharness (#200)
install.sh curl-pipe install cloned the project to $HOME/.openharness,
which collided visually with the in-repo .openharness/ config dir
(curl-pipe users ended up with ~/.openharness/.openharness/). Project
clones aren't dotfiles by convention; rename the install target to
$HOME/openharness. The in-repo config dir keeps its .openharness/ name.

One-time migration: existing ~/.openharness clones are mv'd to
~/openharness automatically when the new path is absent and the old
one has a .git dir.

In-container paths (/home/sandbox/.openharness, slack auth symlinks
under ~/.openharness/agent/... inside the sandbox) are unchanged —
those address the bind-mounted config dir, not the host install path.

Closes #200

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 13:19:28 -06:00
Ryan EgglestonandOpenHarness Bot 1f79918daa FROM revert/170-172-vocabulary-realignment TO main (#199)
* task: revert Phase 2 sandbox→orchestrator user rename (#172)

Reverts b17698a. The in-container Linux user is restored from `orchestrator`
back to `sandbox` (UID/GID 1000 preserved). Removes the `ORCHESTRATOR_USER`
/ `ORCHESTRATOR_HOME` constants in packages/sandbox/src/lib/config.ts; the
literal `sandbox` and `/home/sandbox` are inlined again.

We no longer operate the harness on remote servers, so the conceptual
disambiguation no longer pays its keep. The simpler name `sandbox` already
matches the package name @openharness/sandbox, the compose service `sandbox:`,
the container name default, the SANDBOX_NAME env var, POSTGRES_USER=sandbox,
and the sandbox_* Pi tool prefix.

Conflict resolution:
- install.sh: kept post-rename install-prereq-detection structure (#176, #197),
  changed `-u orchestrator` → `-u sandbox` and "sandbox orchestrator user"
  → "sandbox user" (post-rename strays from #197).
- docs/quickstart.md: kept the consolidated content (#179), restored
  pre-rename "as the `sandbox` user" wording.
- 7 docs files deleted by the docs consolidation (#179) stay deleted —
  they were superseded.

Closes part of #198.

* task: revert Phase 1 sandbox/harness/agent vocabulary realignment (#170)

Reverts 5693fa4 across surviving files. Restores pre-Phase-1 wording in
AGENTS.md, README.md, workspace/USER.md, .github/ISSUE_TEMPLATE/agent.md
(retitled back to [AGENT]), .claude/skills/strategic-proposal/SKILL.md,
docs/guide/identity.md, docs/guide/workspace.md, and CHANGELOG.md
[Unreleased].

Conflict resolution:
- 3 files deleted by the docs consolidation (#179) stay deleted:
  docs/README.md, docs/about.md, docs/architecture/structure.md.
- docs/architecture/overview.md and docs/architecture/worktrees.md were
  rewritten by #179 — keep the consolidated structure (no Phase 1 wording
  to revert in the new structure).
- CHANGELOG: drop the [Unreleased] entry that 5693fa4 added.

Closes part of #198.

* task: clean post-rename strays + add inverted migration guard (#198)

Cleans up `/home/orchestrator/...` paths and `-u orchestrator` invocations
that were introduced after b17698a and weren't reachable by `git revert`.
Adds an inverted migration guard in install/banner.sh for users coming
back from the orchestrator-renamed image.

Stray fixes (Linux-user/path references; orchestrator-as-role refs left
as-is, e.g. cli.ts tagline, agent/orchestrator branch convention,
provision/destroy skill examples):
- docs/installation.md: `-u orchestrator` → `-u sandbox`
- docs/architecture/{overview,worktrees,daemon}.md: `/home/orchestrator/harness`
  → `/home/sandbox/harness`
- .claude/specs/install-prereq-detection.md: `-u orchestrator` → `-u sandbox`

CHANGELOG: add Unreleased Changed entry referencing #198.

397 vitest tests pass; tsc --noEmit clean. Closes #198.

---------

Co-authored-by: OpenHarness Bot <noreply@openharness.local>
2026-04-30 00:12:46 -06:00
0edfbae4a9 task: consolidate docs into single source of truth at /docs/ (#179)
Two parallel doc trees (/docs/ legacy + apps/docs/docs/ Docusaurus) had
been hand-maintained in parallel. This consolidates into one canonical
markdown tree at repo-root /docs/, served by Docusaurus from apps/docs/
via path: '../../docs'. Blog enabled at repo-root /blog/.

Highlights:
- Move all 28 apps/docs/docs/* into /docs/, delete apps/docs/docs/
- Preserve deep Slack subdocs (8 pages) and operations Guide (10 pages)
  from the legacy tree as winners
- Merge unique architecture content (worktrees topology, namespaced
  scheduler keys, repo layout, boot sequence) into apps versions before
  move
- Convert apps/docs/docs/integrations/slack.md to a stub linking to
  /docs/slack/overview
- Enable Docusaurus blog with the two existing posts migrated to
  /blog/<date>-<slug>.md, drop ogImage references for missing files
- Delete internal-only artifacts: /docs/plans/, /docs/wiki/,
  /docs/launch-runbook.md, /docs/.next/ stale Nextra cache
- Add explicit sidebar_position frontmatter and _category_.json files
  with collapsible/collapsed flags
- Use editUrl callback form for both docs and blog so file paths
  resolve correctly with non-default content path
- Configure search-local plugin docsDir/blogDir for the new layout
- Expand .github/workflows/docs.yml paths trigger to docs/** and blog/**
- Add fetch-depth: 0 to checkout so showLastUpdateTime works

Closes #178

Co-authored-by: OpenHarness Bot <noreply@openharness.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 19:15:30 -06:00
7fa8ea9997 FROM task/175-install-prereq-detection TO development (#176)
* task: add spec for install.sh pre-req detection

Captures design for auto-detecting Node 20+ on host and branching the
installer between CLI-first (build + link 'oh', no auto-sandbox) and a
3-way prompt when Node is missing (nvm + Node 22 / docker-only / abort).

Spec includes 4 mermaid diagrams, 23-scenario verification matrix,
SHA-256-pinned nvm install, and an explicit list of follow-up issues to
open at implementation time. Reviewed by two parallel critic agents.

.gitignore exception lets this single spec ship while keeping other
specs in .claude/specs local-only.

Refs #175

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* task: add prd.md + prd.json for install pre-req detection

Adds the per-feature PRD folder for the install.sh rewrite tracked in
issue #175. prd.md slices the spec into 7 right-sized user stories
(foundation helpers -> bug fixes -> mode dispatch -> CLI/docker/nvm
paths -> doc sync) with cross-references back to the 23-scenario
verification matrix in the spec. prd.json is the synchronized Ralph
v1 schema with branchName 'task/175-install-prereq-detection'.

Also adjusts .gitignore to ignore only 'tasks/*/archive/' instead of
the whole 'tasks/' tree, so per-feature PRDs are tracked while
archive snapshots from re-runs stay local.

Refs #175

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* task: update docs for install.sh auto-detect (drop --with-cli from primary examples)

Refs #175

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* task: add install.sh foundations (helpers, prompt_input, .env path fix)

US-001 + US-002 + US-003 from tasks/install-prereq-detection/prd.md.
Lays the substrate for T3 mode dispatch without changing user-visible
behavior yet.

Adds:
- detect_node() helper (returns 0 iff Node >= 20; sets DETECTED_NODE_VERSION
  and DETECTED_NODE_REASON; load-bearing comment on the set -e guard)
- warn() helper writing to stderr in YELLOW
- print_help() block listing all flags + env vars + examples
- Multi-flag arg parser handling --cli, --docker-only (alias --no-cli),
  --install-node, --with-cli (deprecated alias for --cli with WARN),
  -y/--yes, -n/--no, -h/--help; rejects --cli=value style explicitly
- Reads OH_INSTALL_MODE, OH_ASSUME_YES, OH_INSTALL_REF, SANDBOX_NAME, and
  the credential env var from env (flags win on conflict)
- Conflict checks (4 mutually-exclusive pairs) run AFTER the parse loop
- prompt_input(varname, msg, default, secret-flag) helper resolving via
  env-var -> /dev/tty interactive -> default fallback (warn) -> die
- OH_INSTALL_REF clone path for users who want to pin to a tag/SHA

Fixes:
- .env target was $REPO_DIR/.env; now writes $REPO_DIR/.devcontainer/.env
  (matches packages/sandbox/src/lib/config.ts:7 ENV_FILE constant). Without
  this, oh sandbox <name> after curl-install silently fell back to default
  name 'sandbox' instead of the user-typed value.
- read calls for the sandbox name and credential are broken in pipe mode
  (they read from the script source, not the keyboard). Both call sites
  now use prompt_input which reads from /dev/tty.
- git -C $REPO_DIR pull no longer dies on dirty working tree; gates on
  diff --quiet && diff --cached --quiet, warns and skips on dirty.
- Sandbox name and credential single-quoted in heredoc with literal
  single-quote escaping; protects against shell metacharacters.

T3 (mode dispatch + nvm install + mode-aware next-steps) is the next wave
and will replace the WITH_CLI shim with resolve_mode() + choose_path() +
install_nvm() with SHA-256 verification.

Refs #175

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* task: add install.sh modes (resolve_mode + 3-way prompt + nvm)

US-004 + US-005 + US-006 from tasks/install-prereq-detection/prd.md.
Replaces the WITH_CLI shim from T1 with a proper mode dispatcher and
adds the nvm + Node 22 path with SHA-256 verification.

Adds:
- NVM_VERSION=v0.40.4 + NVM_SHA256 constants pinned together (bump
  procedure documented inline; URL is mutable so the hash is what
  makes piping nvm install.sh to bash safe).
- install_nvm() — functional already-installed check (sources nvm.sh
  in subshell + verifies `nvm --version` exits 0; file existence alone
  is not sufficient because corrupt installs pass it). Downloads the
  installer to a temp file, computes SHA-256, aborts with die() on
  mismatch, then bash-execs the verified file. After install: sources
  nvm, runs nvm install <NODE_LTS_MAJOR> --lts, alias default,
  corepack enable, corepack prepare pnpm. Order is load-bearing:
  corepack runs in the nvm-managed Node context only (no sudo needed).
  Re-runs detect_node afterward; dies cleanly if still failing rather
  than falling through to a broken pnpm install. Sets OH_FISH_REMINDER
  for the next-steps message when SHELL points at fish.
- choose_path() — 3-way interactive prompt (default option 1 = nvm +
  CLI, option 2 = docker, option 3 = abort). Honors --yes / --no.
  Reads from /dev/tty so curl-piped installs still get keystrokes.
  No-TTY + no flag = die with hint about --yes / --docker-only / --no.
- resolve_mode() — forcing flags > OH_INSTALL_MODE > auto-detect.
  --cli with no Node 20+ hard-fails with --install-node hint. Auto-
  detect picks INSTALL_MODE=cli when Node is present, calls choose_path
  when not. Runs after Docker/git checks so we fail-fast on missing
  prereqs before any UI.

Mode dispatch (replaces the bottom of the script):
- INSTALL_MODE=cli — build + link CLI on host, NO docker compose up.
- INSTALL_MODE=node-then-cli — install_nvm, then build + link CLI.
- INSTALL_MODE=docker — docker compose up, no host CLI.

Mode-aware "Next Steps" output:
- CLI-first leads with `cd $REPO_DIR` (oh sandbox resolves compose
  paths relative to CWD), then explicit oh sandbox / oh shell. gh
  auth login moved INSIDE the sandbox shell — gh's credential helper
  writes into the sandbox home, not the host home.
- Node-then-CLI appends a reminder about sourcing ~/.bashrc; Fish
  users get an explicit nvm.fish hint.
- Docker-first shows docker exec, compose stop/restart with the
  required cd $REPO_DIR step, and the --install-node re-run hint.

Smoke-tested:
- bash -n install.sh passes
- 4 conflict pairs all die() correctly (--cli + --docker-only,
  --cli + --install-node, --docker-only + --install-node, --yes + --no)
- Auto-detect with Node 22 present routes to INSTALL_MODE=cli without
  prompting
- --help block lists all flags + env vars + examples

Refs #175

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* task: add SANDBOX_* env vars to docs flag tables + commit /prd /ralph skills

Two follow-ups for PR #176.

Docs:
- T2 sub-agent could not write the literal SANDBOX_PASSWORD env-var name
  to the flag tables because the deny-env-dump.sh hook's case-insensitive
  PASSWORD regex matched any Bash command containing it. The agent worked
  around this with paraphrases ("sandbox passphrase prompt") which lost
  the specific contract. Patches written via Edit (no Bash, no hook) so
  the tables now list both SANDBOX_NAME and SANDBOX_PASSWORD with the
  partial-set independence note.
- Adds OH_INSTALL_REF row to the legacy docs/getting-started flag table
  (was already in apps/docs/docs).

Skills:
- Adds .claude/skills/prd/SKILL.md and .claude/skills/ralph/SKILL.md.
  These were imported as faithful copies of the workspace versions to
  drive the per-feature tasks/ folder workflow this PR establishes
  (tasks/install-prereq-detection/{prd.md,prd.json}). Tracking them
  alongside the workflow they enable keeps the skills and their
  consumers in sync.

Refs #175

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* task: mark all 7 prd.json stories as passing with implementation notes

All 7 user stories from tasks/install-prereq-detection/prd.md have shipped
in PR #176. Flips passes: false -> passes: true on every story and adds
notes pointing at the commit SHA(s) where the work landed plus honest
caveats about what was verified vs deferred:

- US-001/002/003 -> dea6c1a (foundations: helpers, prompt_input, .env path)
- US-004/005/006 -> de2e218 (modes: resolve_mode + 3-way prompt + nvm SHA)
- US-007        -> de84063 + b42f19b (docs sync + literal env-var rows)

Notes call out where end-to-end verification was skipped to avoid mutating
the orchestrator's host (live nvm install, pnpm global link, browser
agent-browser pass) — those move to manual-reviewer / CI-gate territory.

Refs #175

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: OpenHarness Bot <noreply@openharness.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 17:54:43 -06:00
b17698ab7b task: rename in-container Linux user sandbox -> orchestrator (#172) (#173)
Phase 2 of the vocabulary realignment. The principal Linux user inside
the sandbox container is renamed from `sandbox` to `orchestrator`,
reflecting that the user is the root harness (not a sandbox).

Behavior change: requires fresh image pull AND full rebuild
(`docker compose pull && docker compose up --build`). UID/GID 1000
preserved so existing named volumes (claude-auth, codex-auth, pi-auth,
cloudflared-auth, gh-config) remain readable.

Migration paths (documented in CHANGELOG and surfaced via banner.sh):
  - Recommended (preserves auth):
      docker exec -u root <container> chown -R 1000:1000 /home/orchestrator
  - Reset (destroys auth):
      docker compose down -v && docker compose up --build

A runtime migration guard in install/banner.sh fires on shell entry when
both /home/sandbox exists AND $(whoami) is orchestrator -- catches
upgraders who pull and rebuild without reading the changelog.

What changed:
  - useradd -u 1000 ... orchestrator (Dockerfile)
  - All COPY --chown, su -, gosu, chown, /home/sandbox -> /home/orchestrator
    in Dockerfile + install/setup.sh + .devcontainer/entrypoint.sh +
    install/entrypoint.sh
  - chpasswd "orchestrator:..." (was silent SSH failure landmine)
  - Final exec gosu orchestrator (was container-as-root landmine)
  - All 7 named volume mount paths in compose files
  - 12 TypeScript source files now import ORCHESTRATOR_USER /
    ORCHESTRATOR_HOME constants from packages/sandbox/src/lib/config.ts
    (single source of truth)
  - 12 test files updated; 397 tests pass; tsc --noEmit clean
  - 4 skill files (skill-lint, repair, provision, harness-audit) had
    executable bash blocks updated -- they would have silently failed
    after rename otherwise
  - All user-facing docs (~25 files) updated incl. Mermaid diagram label
  - install/banner.sh migration guard added
  - workspace/TOOLS.md and historical memory logs updated

What stays as `sandbox`:
  - packages/sandbox/ package + @openharness/sandbox name
  - Compose service name `sandbox:` (docker network hostname)
  - SANDBOX_NAME env var + container name default
  - POSTGRES_USER=sandbox (separate cred namespace)
  - lib/docker.ts service-label filter
  - sandbox_* tool name prefix (Pi extension slash commands)

Closes #172

Co-authored-by: OpenHarness Bot <noreply@openharness.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:34:48 -06:00
5693fa418c task: realign sandbox/harness/agent vocabulary in docs (#170) (#171)
Locks in vocabulary across user-facing docs:
- sandbox = Docker container
- harness = configured env + agent (SOUL/MEMORY/branch/schedule)
- orchestrator = role label for the root harness; not a separate primitive
- agent = the AI CLI (Claude Code, Codex, Pi, Gemini)

Phase 1 — docs only, no behavior change. The in-container Linux user
rename (sandbox -> orchestrator) is deferred to Phase 2.

Carve-outs preserved:
- "Worktree-per-agent" marketing label (blog post title, brand)
- agent/<name> branch convention (stable git convention)
- "agent" referring to AI CLIs throughout

Files: README, docs/{README,about}.md, AGENTS.md (CLAUDE.md symlinks),
docs/architecture/{structure,overview,orchestrator-worktrees}.md,
docs/guide/{workspace,identity}.md, .github/ISSUE_TEMPLATE/agent.md
(retitled [HARNESS], filename and YAML keys preserved with explanatory
comment), workspace/USER.md, .claude/skills/strategic-proposal/SKILL.md.

Closes #170

Co-authored-by: OpenHarness Bot <noreply@openharness.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:32:01 -06:00
Ryan Eggleston 9cc09b46e8 task: short install URL via oh.mifune.dev (#162)
Swap README and docs to use https://oh.mifune.dev/install.sh — a
Cloudflare Worker that 302-redirects to the raw GitHub install.sh on
main. Source-of-truth is unchanged; URL is shorter and project-branded.

Closes #161
2026-04-26 15:19:41 -06:00