24 Commits
Author SHA1 Message Date
Ryan Eggleston f8006f4825 task: docs runbook + agents catalog (#301)
Closes #300.
2026-05-15 22:14:45 -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 Bot d6c4886d6e task: US-006 — delete packages/sandbox + build.yml workflow
Per SPEC v0.7 §"oh CLI" deprecation. Atomic file-deletion mass:
- Removed packages/sandbox/ workspace (CLI + harness/onboard/lib/tools + tests)
- Removed packages/sandbox entry from pnpm-workspace.yaml
- Removed link:cli script from root package.json
- Removed .github/workflows/build.yml (was duplicating release.yml's image
  build, pushing to ghcr.io/ryaneggz/open-harness — drifted from canonical
  ghcr.io/ryaneggz/openharness produced by release.yml)
- Removed .github/workflows/ci.yml (sandbox-only CI now stale)
- Removed CLI build/symlink block from .devcontainer/entrypoint.sh that
  wired /usr/local/bin/openharness and /usr/local/bin/oh
- Rewrote .husky/pre-commit to run root-level lint + test (was cd'ing into
  the now-deleted packages/sandbox/)
- Regenerated pnpm-lock.yaml (-49 packages)

release.yml is now the sole image producer pushing
ghcr.io/ryaneggz/openharness:<tag> + :latest.

Refs #210
2026-05-02 12:23:00 -06:00
OpenHarness BotandClaude Opus 4.7 b768f32a27 task: US-002 — implement croner runtime script
Adds scripts/cron-runtime.ts (119 LOC) that reads crons/*.md frontmatter
and schedules each cron with the croner npm package, replacing the
1,900-LOC heartbeat daemon per SPEC v0.7 §"Croner runtime".

- Frontmatter parser: id, schedule, timezone, enabled, overlap, catchup
- Skips files where enabled is false
- Fires each cron's markdown body as a prompt to claude -p (CRON_AGENT_BIN
  env var overrides the binary)
- Logs to crons/cron-runtime.log (ISO timestamp, cron id, status)
- PID lock at crons/.pid prevents double-firing; stale locks are stolen
- Clean SIGTERM/SIGINT cleanup unlinks the PID file

Adds 9 vitest tests covering frontmatter parsing, skip-when-disabled,
PID-lock acquisition, live-process collision, and stale-lock recovery.
Wires scripts/__tests__/ into a root vitest.config.ts so pnpm run test
picks them up.

Refs #210

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 12:05:50 -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
a1d87587d7 FROM task/164-docusaurus-docs-site TO development (#165)
* task: scaffold Docusaurus v3 docs site at apps/docs (oh.mifune.dev)

Production-ready Docusaurus v3 + TypeScript docs site at apps/docs/,
deployed to GitHub Pages with custom domain oh.mifune.dev.

- apps/docs scaffold: docusaurus.config.ts, sidebars.ts, custom CSS,
  CNAME, SVG placeholders, .gitignore
- pnpm workspace wired; root scripts: docs:dev, docs:build, docs:serve
- 28 doc pages: intro, quickstart, installation, onboarding,
  sandbox-lifecycle, connecting, agents/*, heartbeats/*,
  integrations/*, cli/*, architecture/*, contributing
- Custom homepage at /: hero, quickstart, supported agents,
  why, architecture preview, links
- .github/workflows/docs.yml: build on PR, deploy on push to main
  via official GitHub Pages actions
- pnpm.overrides pin webpack 5.98.0 (5.106.x breaks webpackbar
  ProgressPlugin schema)
- Existing root docs/ preserved unchanged

Closes #164

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

* task: docs site UX overhaul + ci-harness scoping (#164)

UX direction (terminal aesthetic baseline):
- Headline reframed to the actual problem ("Give every AI coding
  agent its own sandbox.") with monospace eyebrow + green status dot
- Split hero: copy left, terminal preview right with ~/open-harness
  zsh window chrome (red/amber/green dots)
- Mono agent icons (Claude/Codex/Gemini/Pi) inheriting currentColor
- Pure-black dark mode, eggshell #f6f3ec light mode for readable
  code-block contrast against page
- Custom Prism theme matching GitHub Primer Dark + Light tokens
  (apps/docs/src/theme/prism-terminal.ts)
- Replaced placeholder OH-on-blue logo with monochrome `>_` prompt
  mark; light + dark variants via srcDark
- Navbar/footer now flat surfaces matching body, single-pixel border,
  monospace footer titles
- @docusaurus/theme-mermaid wired; architecture overview renders
- @easyops-cn/docusaurus-search-local with ⌘K shortcut

Sidebar IA:
- _category_.json on all 5 doc groups (Title Case + explicit position)
- Installation now position 2, Quickstart 3 (matches intro reading order)
- Contributing pinned to position 999

SEO/a11y:
- robots.txt + 1280×720 social card PNG
- og:type meta, showLastUpdateTime, respectPrefersColorScheme
- WCAG-AA primary on white (#1d7dee→#1a1a1a depending on mode)
- prefers-reduced-motion + print stylesheet

Council-ratified ci-harness.yml fixes (must merge with this PR):
- Filter pnpm fan-out to ./packages/** (lint/format:check/build/test)
  so apps/docs no longer bleeds into the harness pipeline on
  pnpm-lock.yaml changes
- --if-present on root scripts as belt-and-suspenders for future
  workspaces lacking lint/test
- Root .gitignore covers apps/*/build, .docusaurus, node_modules
- Inter + JetBrains Mono via Google Fonts headTags

Decisions captured in:
- .claude/plans/i-d-like-to-explore-virtual-pebble.md (consolidation)
- .claude/plans/council-harness-doc-updates.md (Council ratification)

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-26 20:23:17 -06:00
OpenHarness BotandClaude Opus 4.7 e4042d5c29 task: regenerate pnpm-lock.yaml after removing @openharness/docs
Drops the docs workspace and its Next.js/Nextra dependencies from
pnpm-lock.yaml — direct consequence of removing docs/ in the parent
commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 22:08:06 -06:00
OpenHarness Bot 584f670699 task: add next-sitemap for sitemap.xml + robots.txt generation 2026-04-25 00:46:18 -06:00
OpenHarness BotandClaude Opus 4.7 f565b90a35 task: upgrade pi-mono packages to 0.70.0 and typebox 1.x
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 00:06:56 -06:00
OpenHarness BotandClaude Sonnet 4.6 b4d53f8552 task: upgrade pi-coding-agent to 0.70.0 and typebox 1.x
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 23:11:33 -06:00
ryaneggzandClaude Opus 4.7 eba3c6f3f6 feat: revert docs/ to Nextra 3 (#96)
Swap Fumadocs for Nextra 3 on Pages Router. Preserves user-preferred
Nextra sidebar/theme while avoiding Nextra 2.13.4's dep hell (zod 4 leak
via @anthropic-ai/sdk + @theguild/remark-mermaid 0.0.5's d3-shape ESM
issues).

Changes:
- docs/package.json: nextra@^3.3, nextra-theme-docs@^3.3, next@^14.2.29, react@^18.3
- docs/pages/: 28 MDX + 6 _meta.js (Nextra flat-map shape, not Fumadocs title/pages)
- docs/pages/_app.tsx: imports nextra-theme-docs/style.css (satisfies global-CSS guard on symlinked wiki content)
- docs/pages/wiki: symlink -> ../../workspace/wiki/pages
- docs/theme.config.tsx: Nextra 3 shape (footer.content, head; no useNextSeoProps)
- docs/next.config.mjs: experimental.externalDir + esmExternals:'loose' (required for symlinked external content + mermaid)
- Deleted: docs/app/, docs/content/, docs/lib/, docs/components/, docs/source.config.ts, docs/postcss.config.mjs
- Root package.json: pnpm.overrides.d3-shape ^3.2.0 (mermaid transitive fix); drop direct mermaid dep
- Updated specs + PRD to record D1 revision (Nextra 2 -> Nextra 3)

Build: pnpm --filter @openharness/docs build -> 30 static HTML pages in docs/out/.

Closes #96

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:35:26 -06:00
Ryan Eggleston 71b5583073 Fixes provision 2026-04-18 21:15:59 -06:00
ryaneggzandClaude Opus 4.6 3aff8105fd fix: update lockfile after pinning pi-coding-agent to 0.66.1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 00:56:45 -06:00
ryaneggzandClaude Opus 4.6 cdd2c740e2 feat: migrate docs from Nextra to Fumadocs, integrate wiki content source
Replace Nextra 2.13.4 with Fumadocs (fumadocs-core + fumadocs-ui + fumadocs-mdx)
on Next.js 16. Migrates from Pages Router to App Router with two content sources:
- /docs — static documentation (29 MDX pages migrated from Nextra)
- /wiki — LLM-generated wiki pages (symlinked from workspace/wiki/pages/)

Key changes:
- Swap nextra/nextra-theme-docs deps for fumadocs stack + Tailwind CSS 4
- Convert _meta.json nav files to Fumadocs meta.json format
- Convert Mermaid JSX components to fenced mermaid code blocks
- Update internal links from /open-harness/ to /docs/ prefix
- Add Orama search API route
- Support both dev server (tunnel) and static export (GitHub Pages)
- Update docs.yml workflow to trigger on workspace/wiki/** changes
- Update startup.sh: start docs on port 3001, support multiple tunnels
- Add wiki/pages/index.md landing page for /wiki route

Tunnel setup (manual, one-time):
  ~/install/cloudflared-tunnel.sh docs docs.ruska.dev 3001

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 17:43:08 -06:00
ryaneggzandClaude Opus 4.6 23f441dd91 feat: migrate heartbeat system from bash to TypeScript
Replace the 470-line install/heartbeat.sh with an in-process croner
daemon. New modules: config, logger, lock, gates, runner, scheduler,
daemon — all with vitest tests (110 new tests, 200 total).

- Add croner ^9.1.0 dependency for cron scheduling
- Update entrypoint.sh to start TS daemon instead of cron
- Update tools/heartbeat.ts to delegate to TS daemon
- Convert heartbeat.sh to deprecation shim

Closes #58

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 23:53:53 -06:00
ryaneggzandClaude Opus 4.6 7de6eb9c51 docs: add Mermaid architecture diagrams to Slack Bot pages
Add client-side Mermaid component and diagrams to overview (architecture
flowchart), how-it-works (sequence diagram), and events (event lifecycle
flowchart). Install mermaid dependency.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:17:15 -06:00
ryaneggz ab6e67dc64 init commit 2026-04-12 20:36:57 -06:00
ryaneggzandClaude Opus 4.6 41853af6e5 fix: add slack to workspace with conditional build, resolve CI deps
Add packages/slack to pnpm workspace so its dependencies (croner,
pi-agent-core, etc.) resolve in CI. Make build script skip gracefully
when tsgo is unavailable. Tests run via pnpm -r run test.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:24:08 -06:00
ryaneggzandClaude Opus 4.6 a5aa5f7937 fix: add vitest as root devDependency for CI slack tests
npx vitest downloads a mismatched version in CI that can't resolve the
config. Install vitest at root and run directly via `vitest run --config`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:21:29 -06:00
ryaneggzandClaude Opus 4.6 f36ea59349 fix: exclude vendored slack package from workspace, run tests via config path
The slack package uses tsgo (not available in CI). Revert workspace
addition and run slack tests directly via --config flag instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:19:35 -06:00
ryaneggzandClaude Opus 4.6 95426605e6 feat: suppress tool outputs in Slack responses, add event thread support
Remove verbose tool result thread posts for successful tool calls — only
errors now surface in Slack threads. Add threadTs support to the events
system so events can target existing threads. Includes 37 new tests
covering both features, integrated into CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:15:26 -06:00
ryaneggz 85c9abaa2a Create nextra 2026-04-11 20:06:13 -06:00
ryaneggzandClaude Opus 4.6 fceea28def task(#29): swap npm for pnpm across the entire project
- Replace npm workspaces with pnpm-workspace.yaml
- Rewrite all scripts: npm run → pnpm run, npx → pnpm exec
- Delete all package-lock.json files, generate pnpm-lock.yaml
- CI: add pnpm/action-setup@v4, use pnpm install --frozen-lockfile
- Dockerfile: corepack enable + pnpm add -g for agent CLIs
- install/setup.sh: add pnpm via corepack, swap all npm install -g
- Update all docs, rules, skills, agents, heartbeats, husky hooks
- Update quick-start UI component and playwright config
- All 108 tests pass, both workspace packages build clean

Closes #29

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 15:11:13 -06:00