Skip to content

Releases: mifunedev/openharness

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 03 Sep 04:38
ff7a973

Added

  • Add oh sandbox install docker: a wizard writes a sandbox registry entry under ${OH_HOME:-~/.oh}/sandboxes/<name>/ and boots it from any directory, with no project checkout. (#950)
  • Add oh sandbox list [--json], reporting each registry entry's name, runtime, container status, and bound repo. (#950)
  • Add --sandbox <name> to oh config show|set and oh secret set|list, which read and write a registry entry instead of the project root. (#950)
  • Add microsandbox to the tool catalog: oh tool install microsandbox installs msb under ${NPM_USER_PREFIX:-$HOME/.local} from a pinned installer. (#950)

Changed

  • BREAKING: oh update is the bootstrap: it equips an empty checkout with .oh/ and crons/, writes nothing else, and never prompts. (#950)
  • BREAKING: oh shell|stop|restart|logs|ps|destroy take an optional sandbox name, resolving name, then the single entry, then the entry containing the cwd. (#950)
  • oh destroy <name> removes the registry entry after down -v, so the sandbox name becomes free again. (#950)
  • docs/deployment-prebuilt-image.md becomes the oh sandbox install docker page: running the published image is now the default, and --repo is the bind-mounted-checkout case. (#950)

Removed

  • Remove boot provisioning and every install switch: oh harness install <id> and oh tool install <id> are the only door. A fresh sandbox has no harness and no herdr. (#948)
  • BREAKING: Remove oh init. oh sandbox install docker owns sandbox configuration and oh update owns the control-plane payload. (#950)
  • BREAKING: Remove oh runtime. The runtime catalog lives under oh sandbox, and msb is installed with oh tool install microsandbox. (#950)
  • BREAKING: Remove the .oh/templates/ scaffold payload. The CLI writes no AGENTS.md, provider config, or .gitignore line beyond .env. (#950)
  • Remove gvisor from the runtime catalog; the isolation-tier landscape lives in docs/rfcs/rfc-runtime-support.md. (#950)

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 01 Sep 03:37
006c233

Added

  • Add spec-no-agent-handoff, spec-no-advisor-session-coupling, cleanup-no-agent-session-coupling, headless-tmux-preserved; rename advisor-monitored-loop to spec-single-owner (#928).
  • Add .oh/skills/wiki/scripts/knowledge-impact.sh, the single dependency-aware invalidation primitive: --verified for /wiki lint, --changed for the /spec execute knowledge gate. (#926)
  • Add evals-20260901-suite-tree-clean and docs-20260901-followup-artifact-cited: no probe may redirect into the repository, and a criterion met by a follow-up must cite its URL. (#926)
  • Add ten tier-A probes covering the knowledge surface, the planning recall and reconciliation gates, the RUNNING contract, structured completion, and the retired vocabulary. (#926)
  • Add /escalate: an unattended session delivers a human-addressed escalation to the operator's Slack channel. An unavailable channel no-ops loudly rather than failing the session. (#919)
  • Add .oh/logs/, gitignored by default with a tracked README, for records that outlive the session that wrote them; /escalate appends every attempt to escalations.jsonl. (#919)
  • Add escalate-contract.sh, a tier-A probe: a no-op names its reason, is recorded, and --dry-run makes no network call. (#919)
  • Add gate 5 to /audit implementation: fail a promotable change while its diff can still be smaller. Measures net lines and per-function CCN on changed TypeScript via uvx lizard. (#912)
  • Add audit-slop-gate.sh, a tier-A probe holding gate 5's termination contract: a finding needs a concrete smaller alternative, and the loop ends on the cap or a non-reducing round. (#912)
  • Add /wiki compile, a kind: pattern corpus layer, and an append-only skill-impact.md ledger, so a /retro lesson becomes a page /builder reads before proposing. (#916)
  • Add a --patterns mode to /wiki query that filters on kind:, reads up to five pattern entries, and ranks them by term-hit count before recency. (#916)
  • Add a fault-injection requirement to the probe contract: a probe is not green until its REGRESSION branch has been driven against a broken input. (#916)
  • Add capability task CB-005 scoring whether a lesson reaches a validated skill change; two runs score 0.67 then 1.33, moving the suite mean to 1.44 over a changed task set. (#916)
  • Add /architect, an inline architecture-decision skill that classifies significance, grounds analysis in repository sources, and returns one Architecture Brief (#929).
  • Add six tier-A probes covering the /architect contract, roles-as-skills, the retired builder agent type, the /delegate worker boundary, the absent agent catalog, and RFC/ADR reuse (#929).

Changed

  • BREAKING: Move durable repository knowledge to a tracked .oh/knowledge/ surface β€” source/, patterns/, raw/ tracked, local/ ignored β€” with no compatibility alias. (#926)
  • BREAKING: Make /spec plan recall tracked knowledge and re-ground it before the PRD; prd.md carries Knowledge Context, Expected Knowledge Impact, and Plan Reconciliation. (#926)
  • BREAKING: Derive final knowledge impact in /spec execute from the actual diff plus page dependencies, resolving every impacted page to UPDATED, REVERIFIED, or NOT-AFFECTED. (#926)
  • BREAKING: Replace age-based wiki staleness with source-change freshness: a kind: repo page pins verified_at and goes needs-review when a declared source changed after it. (#926)
  • BREAKING: Model /spec execute as PLANNED -> RUNNING -> READY | DRAFT-BLOCKED(gate), with RUNNING derived from prd.json and mirrored into /tmp/spec-<slug>.state. (#926)
  • Re-open /spec execute's promotable gate when a push lands after gh pr ready: the verdict binds to one head, so a moved head is re-audited or returned to draft. (#926)
  • Reduce /wiki lint to six correctness checks and demote /compact to an optional non-gating step that runs only after evidence, retro, and pattern compilation. (#926)
  • Reduce /spec retro to an explicit wrapper around /retro --task <slug>, which /retro now accepts; /retro stays report-only and /wiki compile stays the durable pattern writer. (#926)
  • BREAKING: Move eleven settings out of the compose environment: block into oh.json, read through the oh CLI; a hand-edited .devcontainer/.env no longer carries them (#920).
  • Make /spec ship by default: an unrecognized first token routes to a new ship node that runs plan then execute, so /spec <plan-path> produces a ready-for-review PR (#914).
  • BREAKING: Persist the sandbox home through one /home/sandbox mount, not eleven per-tool volumes; set storage.homePath for a host path, else <name>_workspace (#898).
  • Shrink the sandbox image ~540 MB: drop build caches from the baked home seed, stage the seed once via a builder stage, and keep untracked build output out of the build context (#900).
  • BREAKING: Stop baking Claude Code, Codex, and Pi into the image; boot installs them into the home mount, so a first boot needs network and runs 60-180s longer (#904).
  • BREAKING: Stop baking Herdr and cloudflared into the image; both become kind: "default" tools installed into ~/.local/bin at boot from a pinned, checksum-verified binary (#906).
  • BREAKING: Stop baking OpenCode, Hermes, and Grok Build into the image; oh harness install <id> installs them into ~/.local as the sandbox user (#908).
  • .oh/logs/ carries an AGENTS.md with a CLAUDE.md symlink instead of a README.md, matching the directories whose contents are produced apart from the root context. (#924)
  • BREAKING: /spec execute no longer launches a coding agent; the agent that runs it is the single implementation owner through the final PR gates (#928).
  • Task identity and RUNNING state depend on .oh/tasks/<slug>/ alone, never on a terminal session, tab, or pane (#928).
  • /delegate keeps work in the active session when phases share substantial context and spawns provider-native workers only for self-contained, isolated, or parallel work (#929).
  • /spec plan judges architecture significance once and routes a significant topic through /architect before planning (#929).
  • docs/glossary.md defines coding agent, skill, worker/subagent, rule, and RFC/ADR as five distinct terms (#929).
  • /t3 launches the headless t3 serve instead of the local-GUI t3, and gains --tailscale, a pair action for a second device, and a doctor preflight (#858).

Fixed

  • Fix /wiki lint generating the corpus index from the working tree instead of the git-tracked set, which made any untracked scratch entry a wiki-readme-index.sh regression. (#916)
  • Fix three unresolved related: and [[slug]] links in the recursive-language-models wiki entry, and add the /wiki lint check that would have caught them. (#916)
  • Provision the default harnesses into /home/sandbox/.local at boot, gated by OH_PROVISION_HARNESSES, so oh harness install also works from inside the sandbox (#902).
  • Add oh-home-mount.sh, a tier-A probe holding the single-$HOME-mount contract: one mount per compose file, the baked /opt/home-seed, and the checkout prune that replaces -xdev (#898).
  • Assert boot-provisioned harnesses in the boot smoke and reject a baked default harness in verify-sandbox-image.sh, so CI exercises the install path (#904).
  • Add oh tool list --defaults and generalize the boot provisioner over both catalogs as provision-defaults.sh (OH_PROVISION_DEFAULTS) (#906).
  • Fix oh harness install hanging on a sudo password prompt inside the sandbox: every harness now installs as the sandbox user,...
Read more

v0.5.1

Choose a tag to compare

@github-actions github-actions released this 29 Aug 20:04
36bf42e

Fixed

  • tsconfig.build.json excluded only src/__tests__/**, so prepublishOnly typechecked src/lib/__tests__/ and failed on the absent vitest, blocking the npm publish after the image had shipped.

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 27 Aug 05:06

Removed

  • Remove harness.yaml entirely. Configuration collapses to .devcontainer/.env plus the oh CLI. Deleted: harness.yaml.example, .oh/templates/harness.yaml, the 163-line awk parser .oh/scripts/harness-config.sh, the 251-line .oh/cli/src/lib/harness-yaml.ts, their two test files, the harness-yaml-schema-parity probe, and the make harness-config target. The layer never earned its place: every key it mapped already existed as a compose env var with a default, and it was invisible on the VS Code "Reopen in Container" path, which names .devcontainer/docker-compose.yml directly and so reads only .devcontainer/.env. A key set in harness.yaml silently did nothing there.
  • Remove the derived .devcontainer/.harness.yaml.env artifact and the second --env-file that carried it. The wrapper now passes exactly one env-file β€” the same one compose auto-loads on the VS Code path β€” so the two doors cannot disagree by construction.

Added

  • Add .oh/scripts/migrate-harness-yaml.sh: a one-shot automatic migration so no existing install silently loses a setting. It runs from .oh/scripts/docker-compose.sh and .oh/scripts/install.sh, so it fires on every lifecycle verb; it translates the 21 allowlisted keys into .env (uncommenting template lines in place), moves compose.overrides into .oh/config.json composeOverrides[], renames the file to harness.yaml.migrated, and prints every value it carried over β€” including both sides of any value it replaced. Absent a harness.yaml it exits 0 immediately. It is self-contained, carrying its own copy of the deleted parser, so the whole compatibility story is one file to delete in a later release.
  • Add .oh/cli/src/lib/env-file.ts β€” the one .env reader/writer, replacing lib/harness-yaml.ts. Reads go through the existing loadEnvInto, so no fifth env parser was added; writes carry over the uncomment-in-place discipline. Config reads are now plain filesystem reads: oh sandbox and oh shell spawn zero subprocesses to resolve configuration, where every read used to shell out to the vendored parser.
  • Add three probes replacing the deleted parity probe: env-schema-parity.sh (the two .example.env templates carry the same keys, and every var any docker-compose*.yml interpolates is documented β€” this closes a real gap: DOCKER_SOCKET, SANDBOX_SSH, SANDBOX_SSH_PORT, OH_SANDBOX_IMAGE, OH_PULL_POLICY and SKIP_PNPM_INSTALL were consumed but documented nowhere), harness-yaml-migration.sh (append / uncomment-in-place / preserve / overwrite, plus a silent second run), and compose-config-path-parity.sh (the wrapper path and the VS Code path resolve the same service β€” the parity harness.yaml made impossible).

Changed

  • .devcontainer/.example.env is now the schema document, carrying all 25 keys with their defaults and prose, lifted from harness.yaml.example. Its "Migrated to harness.yaml" block is gone. .oh/templates/.devcontainer/.example.env is brought to key parity β€” an oh init repo shipped a template documenting three vars.
  • The installer's config writes always run. install.sh put its entire config block inside if [ ! -f .devcontainer/.env ], so re-running it over an existing install wrote nothing; with .env as the only surface that would have become a total no-op. .env is now seeded when absent and the writes always follow, each idempotent and one line wide. Host detections (timezone, git identity) still only seed a fresh file, so a re-run never silently overwrites a hand-edited value.
  • .oh/scripts/docker-compose.sh drops five harness.yaml resolution ladders (hermes-dashboard, docker-socket, ssh.enabled, ssh.port, sandbox.name) and the compose-overrides loop; each collapses onto the .env fallback that was already the next line. The overlay -f list is byte-identical before and after, verified against a recorded baseline.
  • .oh/scripts/oh-path loses its paths.<name> ladder: the precedence is now <NAME>_DIR env β†’ .oh/<name>.
  • oh init's wizard writes one file. It used to split non-secret answers to harness.yaml and secrets to .env; both now land in .env in a single write, through the same line editor, so the operator's answers appear as uncommented lines inside the documented template.
  • CI path filters and their probes move from harness.yaml.example to .devcontainer/.example.env (ci-harness.yml, sandbox-boot-guard.yml, harness-ci-core-paths.sh, sandbox-boot-guard-ci.sh). oh-init-headless-config.sh retargets to the .example.env template and additionally asserts --yes writes no .env at all.
  • .gitignore keeps /harness.yaml and .devcontainer/.harness.yaml.env for one more release so a stale local artifact from a pre-0.4.0 checkout is never committed, and adds /harness.yaml.migrated.

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 26 Aug 03:34
6f5df5d

Added

  • Add oh harness <list|install|status> to install optional harnesses into a running sandbox without a rebuild, persisting the choice to install.<key> for the next build (#821).
  • Add oh runtime <list|install|status>, reporting the container runtime in use and gating a MicroSandbox install on the measured glibc and /dev/kvm blockers. It selects no runtime (#823).
  • Add oh tool <list|install|status> for sandbox tooling that is neither an agent CLI nor a runtime, making agent-browser installable without a rebuild behind a ~1 GB download gate (#824).
  • Add oh stop|restart|logs|ps, closing the lifecycle gap where make had verbs the CLI did not, and publish one make vs oh mapping doc that the other docs link to (#825).
  • Document running Open Harness on MicroSandbox by pointing msb at the published image, and re-scope the microsandbox blockers as devcontainer measurements that say nothing about the reader's host.
  • Add a "which door am I?" table plus two guard probes: harness-yaml-schema-parity.sh and oh-init-headless-config.sh.
  • Add ssh.enabled/ssh.port and sandbox.docker_socket prompts to the oh init wizard, the two settings most likely to need hand-editing.
  • Require .oh/tasks/<slug>/evidence.md before /spec execute undrafts a PR, and refuse an untracked one, so the reviewer gets the build's answer back to the plan they approved (#817).
  • Add a "why this is better" question to the reviewer evidence contract, ahead of the four correctness questions, with unmeasured benefits labelled as such (#817).
  • Add protected-path-deletion.sh, which reads .claude/protected-paths.txt at the merge base and fails when a listed path is deleted without a justification in a committed evidence.md (#817).
  • Add memory-probe-claims-resolve.sh and context-tier-size-budget.sh to hold the memory ledger's enforcement claims and the always-on context budget (#817).

Changed

  • Run /eval once per cycle instead of three times: /spec execute publishes a commit-keyed eval-result.json the downstream gates read, cutting 318 probe executions to 110 (#817).
  • Promote progress.txt into the PR body, so the build narrative reaches the reviewer instead of ending at the STATUS: COMPLETE sentinel (#817).
  • Write install.sh's non-secret answers to harness.yaml rather than the lower-precedence .devcontainer/.env, keeping DOCKER_SOCKET in .env as a documented exception.
  • Lead the README and quickstart with the two scripted installers and demote the untested manual clone sequence into the collapsed section, merging its two duplicate copies into one.

Fixed

  • Match the release-notes heading with index() instead of a regex built by string concatenation, so extraction does not depend on whether the runner's awk is mawk or gawk (#820).
  • Fix the build session launching headless: the prompt travels as argv instead of stdin and no arm carries --print, so the child no longer answers once and exits (#817).
  • Stop | tee in the launch path taking the child's TTY; tmux attaches pipe-pane after the pane exists and foreground mode inherits the caller's stdio (#817).
  • Fix firstmate.sh --kill exiting 1 silently while leaving the session running, the lock claimed, and no FIRSTMATE-INCOMPLETE line appended (#817).
  • Stop the /audit boundary exporting its lifecycle identity to the agent it launches, which made probes grade their caller and flipped one tree's verdict between runs (#817).
  • Rewrite 76 unbacked probe: claims in the memory ledger to explicit probe: none via a tracked idempotent script (#817).
  • Correct the MicroSandbox runner walkthrough: set entrypoint: explicitly, without which the seed and provider linking never run; drop the unsubstituted GH_TOKEN; and re-rank the untested inferences so the boot-breaking one leads.
  • Collapse the two disagreeing harness.yaml line editors into one setKeyInSection in lib/harness-yaml.ts; the wizard's section-blind copy silently dropped answers for keys absent from the template.
  • Reconcile .oh/templates/harness.yaml with harness.yaml.example, restoring the sandbox.docker_socket/image/pull_policy, paths.worktrees, crons, autopilot, slack, and compose keys that had no home to be written into.
  • Correct harness.yaml.example's claim that pull_policy reaches the VS Code "Reopen in Container" path β€” it does not, and no key in the file does.

Removed

  • Remove the critique/approve gate; the operator's approval of prd.md is the commitment gate, and no critic agents are spent per plan (#817).
  • Collapse three build executors to one, deleting .oh/scripts/ralph.sh and every executor toggle rather than reducing them to a single accepted value (#817).
  • Absorb /ship-spec into /spec execute and delete the skill, so the build mechanics read top to bottom in one file with no deferral (#817).
  • Delete .oh/prompts/, .pi/prompts/advisor/, and the First Mate charter, leaving .oh/skills/firstmate/templates/session-prompt.md as the only description of the build workflow (#817).
  • Delete /teach and its pipeline step; evidence.md carries the model to the reviewer, and the wiki half was already a gate in step 5 (#817).
  • Delete the DeepWiki comparison from the wiki gate, which regenerates on no schedule the gate can depend on, and rename the schema section to state its own requirements (#817).
  • Delete four STATUS: SPEC-* tokens with no executable consumer and drop the groom triad from the per-cycle path (#817).

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 24 Aug 07:48

Fixed

  • Stop /prompt-miner from mining markers against a censored statistic. scoreSession computed clamp(base + bonus, 0, 100), but base is already capped at 100 by construction and bonus adds up to 15, so every low-friction ground-truth session lands on the ceiling: 15 of 37 other-stratum sessions (41%) sat at exactly 100 on the 2026-08-13 run. The marker gate promotes on a standardized mean difference in that score, so the clamp β€” not the data β€” was deciding robustness verdicts. Measured on lenWords β‰₯ 25 in stratum other: d = 0.332 capped with 19 of 37 leave-one-out folds under the 0.3 bar, versus d = 0.423 uncensored with 0 of 37 folds under the bar. The engine now emits scoreUncapped = base + bonus as an additive sibling of score on every sessions[] and unranked[] record; score itself is unchanged, still clamped, and still the ranking and display scale. manifest.ceilingSaturation adds a per-stratum { atCeiling, total } census over the rankable population, rendered under the existing ## Manifest heading. references/markers.md, SKILL.md, references/report-schema.md, and references/scoring.md now all name scoreUncapped as the correlation scale, closing the ambiguity that produced the manual d_cap/d_unc workaround. A stability guard keeps the net change stricter rather than looser: each marker record carries effect_size (uncensored, authoritative) alongside effect_size_capped, and a marker whose two scales disagree on sign β€” or where exactly one clears the 0.3 bar β€” is reported UNSTABLE, is not promotable on either scale, and yields no memory proposal or auto-filed issue. That guard would have blocked the 2026-08-09 referencesSkill promotion already identified as a clamp artifact. This does not close #730 (cross-window irreproducibility); no window, threshold, or cross-run rule is touched. (#778)
  • Anchor the memory name in .oh/scripts/oh-path to the main worktree, so one durable ledger serves the whole checkout instead of one per branch. oh-path resolved every name against the parent of its own .oh/, which inside a linked git worktree is the worktree root; .oh/memory/MEMORY.md is gitignored, so a new worktree started without one and .oh/scripts/ensure-memory-file.sh seeded an empty stub there. Every build session in this harness runs in a worktree, so the ledger was structurally invisible to exactly the sessions that produce and consume lessons, and each /retro wrote into a file deleted with its branch β€” five of the seven lessons written in session c10a1f34 never reached the checkout's ledger, including the one that session had just re-derived. Measured across the live worktrees at the time: main checkout 86 lines, the incident worktree 17 (an auto-seeded header plus its own writes), the other six absent. Every other name (crons, evals, tasks, context, worktrees) stays branch-scoped, because a probe or a task must resolve the worktree it is testing; the journal is the exception. Absolute values from MEMORY_DIR or harness.yaml β†’ paths.memory are still honored verbatim β€” only relative values change which root they measure from β€” and the env β†’ harness.yaml β†’ default precedence is untouched. Resolution degrades to the previous root whenever git cannot answer (no git binary, not a repository, a damaged .git, or output naming a non-directory), so a fresh oh init before git init is unaffected and a git failure can never abort a caller running under set -eu. /retro computed the resolved path at SKILL.md:235 and then discarded it, passing the relative literal .oh/memory/$TODAY/log.md to locked-append.sh, so the resolver fix alone would not have reached the harness's most frequent memory writer; its log and ledger writes now use the resolved path. The docs that called the tier "local-per-instance" are corrected to name the checkout as the unit and to state that an empty ledger means the file was just created rather than that a fact went unrecorded β€” naming the unit wrong is why the same defect was worked around twice at individual call sites (#152, #693) without anyone fixing the resolver. This does not make memory portable across clones, operators, or providers: MEMORY.md stays gitignored, and that broader question is left open rather than answered by a side effect. Pinned by .oh/evals/probes/memory-dir-shared-across-worktrees.sh, which builds a real linked worktree and runs that worktree's own copy of oh-path β€” invoked from the main checkout the fixed and unfixed scripts print the same path, which is how the defect stayed invisible β€” and asserts the shared anchor, the absence of any worktree-local resolution, the unchanged branch-scoping of the other names, and the verbatim absolute override. It reads git topology and paths only, never MEMORY.md content or other untracked state, so a fresh CI clone and a developer worktree return the same verdict. Verified by rejection: against the unfixed script it fails on exactly the two assertions under test with the other five reporting zero, and swapping only the script inside one fixed worktree flips the result, which attributes the exit code to the anchor block rather than to its neighbours (#768).
  • Stop /retro from logging promotion counts it cannot yet know. .oh/skills/retro/SKILL.md ordered its steps Β§6 propose-then-confirm gate β†’ Β§7 write approved changes β†’ Β§8 append the log entry, but Β§8 is unconditional and renders render-log-entry.sh --memory <n> --identity <n> β€” promotion counts. For any run that is not auto-approve the agent's turn ends at the gate, because it must hand control back to the operator to get an answer, so the entry was written while the counts were still unknowable and became wrong the instant the operator approved. .oh/memory/<UTC-date>/log.md is append-only, so it could not be corrected in place: on 2026-08-13 the 06:02 entry recorded Promoted: 0 to MEMORY.md, three lessons were then approved, and a separate superseding line had to be appended at 06:03. The defect survived because auto-approve β€” the invocation used by .oh/prompts/advisor/implement.yml and pr.yml β€” collapses the gate into a single turn, so the common path never exercised it. The helper now refuses the guess rather than relying on step order alone: --result GATE-PENDING requires --memory pending --identity pending and exits 64 on an integer, pending is rejected on any other result, and a new --resolves HH:MM (valid only with --result OP) renders the join line back to the entry it resolves. SKILL.md Β§6 is now 6a filter duplicates β†’ 6b append the GATE-PENDING entry β†’ 6c print the proposal block, with the append placed before the block that ends the turn and an explicit "nothing placed after it is guaranteed to run"; Β§8 appends the resolving entry and derives its counts from the lines actually appended in Β§7 rather than from the size of the proposal list. The alternative shape sketched on the issue β€” defer the append until the gate resolves β€” was rejected because a run abandoned at the gate never resumes, so it would leave zero trace and trade the unconditional-log guarantee away to fix a count; rescuing it requires writing something at the gate anyway, which is this shape. retro-deterministic-contract.sh gains eight assertions, each with a unique 767-<id> message, verified by rejection against eight fixtures that each break exactly one thing and then attributed by mutation β€” deleting the assertion makes the same broken tree pass. Two of them cover the step order separately, because anchor reordering and anchor deletion fail differently and the deletion case is the dangerous one: grep -n … | cut -d: -f1 yields the empty string on no match and (( "" < 100 )) is true in bash, so an unguarded compare passes on a file whose anchor was removed. Scope is deliberately narrow β€” report-schema.md, memory-protocol.md, validate-retro-report.sh and check-memory-duplicates.sh are byte-unchanged. What this does not fix: the count is still the agent's self-report, so a miscount remains reachable; the change closes when the number is asserted, not whether the arithmetic is right (#767).
  • Make the /ste checker's clean exit name the two defects it cannot see. Measured on the skill's first production use: ste-check.sh exited 0 with zero findings on prose carrying a condition placed after the action it guards and a sentence opening with a pronoun that names no antecedent β€” questions 4 and 7 of the skill's own 10-question check, both caught by hand seconds later. A green run reads as approval, so the exit-0 line now states both escapes and points at SKILL.md, and the "checker misses" paragraph names them alongside missing actors and invented values. No detector was added, deliberately. A question-4 detector fires on approved after specimens in references/examples.md (lines 58, 86, 99, 140, 310, 324) and would turn --blocks after red, breaking the committed regression fixture; a question-7 detector cannot separate a bare pronoun from one whose antecedent sits in the previous sentence, because the checker reads one line at a time, and it would flip references/rules.md red too. ste-checker-contract.sh gains a section-7 assertion pinning the disclaimer, verified by rejection against three mutations β€” the bare pre-change line, and each half removed on its own. references/examples.md, references/rules.md, and references/dictionary.md are untouched, and no new rule identifier joins the six.
  • Keep the firstmate execution-context probe pane alive across its own read, so the...
Read more

v2026.8.7

Choose a tag to compare

@github-actions github-actions released this 07 Aug 03:36
b52c82d

Added

Changed

  • Set the default Pi driver to openai-codex/gpt-5.6-luna with max reasoning while retaining Sol, Terra, and Luna in the model selector (#700).
  • Release every push to main or master only after validation, using retry-safe UTC CalVer reservations, immutable CalVer/sha-<full-SHA> GHCR tags, canonical-branch digest promotion for latest, gated CLI publication, and post-image GitHub Release finalization (#689).
  • Expose the supported GPT-5.6 variants in Pi's model selector (#684).
  • Expand Advisor planning with a designer lens and make implementation/PR prompts explicitly finish with delegated audits and retrospectives (#680).

Fixed

  • Stop the cron reaper from reading a git status failure as evidence of uncommitted work. inspectFallbackWorktree returned dirty: true whenever git status --porcelain exited non-zero, so a worktree directory whose .git/worktrees/<name> admin entry had vanished was preserved as "needs manual salvage" on every single fire β€” 15 consecutive days for cron-prompt-miner-0718-0500, which also eroded WORKTREE_DIRTY's value as a triage signal by burying any real one under identical noise. Adds a distinct WORKTREE_ORPHANED outcome that removes the directory (git worktree remove fails once the admin entry is gone, and git worktree prune handles only the inverse case). The orphan is identified structurally β€” a .git file whose gitdir: target no longer exists β€” rather than by matching git status stderr, which is locale-dependent; every other status failure still preserves the worktree, since it cannot be shown that there is nothing to salvage (#694).
  • Resolve the prompt-miner daily-log write root to the main worktree instead of the ephemeral one. render-log-entry.sh used git rev-parse --show-toplevel, which under the cron's worktree: true returns the linked worktree β€” so every Step 5 log entry was written into .oh/worktrees/cron/<session>/ and destroyed when the runtime reaped it (fired 07-10, 07-14, 07-19, hand-recovered each time). Adopts the AUTOPILOT_LOG_ROOT β†’ CRON_WORKTREE β†’ toplevel resolution already proven at .oh/crons/prompt-miner.md:102 and documented at .oh/crons/README.md:120, preserving precedence for callers that do export the variable. Guarded by prompt-miner-log-root-worktree.sh, which builds a real linked worktree and asserts the entry lands in the main one β€” a fixture test cannot catch this class of bug (#693).
  • Make prompt-miner able to mine a marker at all, and stop it mining a wrong one. Three changes: (1) withinWindow now admits a session whose activity span overlaps the window instead of one that starts inside it β€” events are merged across resumed files by sessionId, so a long-lived session kept its original firstTs and vanished from a windowed query despite being worked in continuously; (2) subagent (isSidechain) turns are excluded from every signal β€” they carry the parent's sessionId and role: "user", so a delegate briefing was counted as a human turn, and at 45,167 sidechain vs 42,679 non-sidechain lines this corrupted correctionDensity/turnBloat/toolErrorRate for precisely the delegating sessions most worth mining; (3) the daily cron's window is decoupled from its cadence (--hours 24 β†’ --hours 336), because the marker gate needs β‰₯10 sessions in one stratum and a 24h corpus cannot supply that. Largest stratum by window, measured live: 24h β†’ 4, 168h β†’ 6, 336h β†’ 18. The engine's hardcoded single project directory is deliberately not changed β€” the 23 directories it would add are this cron's own worktree sessions, whose first prompts have one distinct length and two distinct hashes, so they would cross the corpus floor while being incapable of producing a marker (#692).
  • Make the prompt-miner engine run when invoked through the .claude/skills directory symlink that SKILL.md Step 1 and the daily cron both prescribe. Node resolves symlinks for import.meta.url but not for process.argv[1], so the old entrypoint guard silently no-opped β€” exit 0, zero stdout, nothing written β€” and both existing prompt-miner probes hardcode the real .oh/ path, leaving them structurally blind to it. Swaps in the symlink-safe basename guard already used by rlm and weigh, and adds prompt-miner-symlink-entrypoint.sh, which invokes the engine through a real symlink and rejects the comparison β€” in either operand order β€” on any executable line under .oh/skills/**/*.mjs. Does not change the NO-CORPUS outcome β€” see #692 (#663).
  • Index .oh/docs/rfcs/rfc-runtime-support.md from .oh/docs/README.md, which had left a quarter of the RFC/ADR corpus unreachable from the index humans enter through, and repoint the dangling .claude/rules/ context bullet in the critic and implementer agents at .oh/context/IDENTITY.md β€” that directory was removed by the B-state M4 rules collapse (#686).
  • Make Slack bridge admin commands discoverable and functional by declaring /help, /trusted, /channels, /enable, /disable, /revoke, and /toggletools in .pi/install/slack-manifest.json, pinning bridge-side Socket Mode command handlers, and separating Slack commands from Pi's /msg-bridge surface in docs (#354).

Removed

Deprecated

Security

v2026.8.3

Choose a tag to compare

@github-actions github-actions released this 03 Aug 05:24
b03e9f3

Added

Changed

  • Set the default Pi driver to openai-codex/gpt-5.6-luna with max reasoning while retaining Sol, Terra, and Luna in the model selector (#700).
  • Release every push to main or master only after validation, using retry-safe UTC CalVer reservations, immutable CalVer/sha-<full-SHA> GHCR tags, canonical-branch digest promotion for latest, gated CLI publication, and post-image GitHub Release finalization (#689).
  • Expose the supported GPT-5.6 variants in Pi's model selector (#684).
  • Expand Advisor planning with a designer lens and make implementation/PR prompts explicitly finish with delegated audits and retrospectives (#680).

Fixed

  • Stop the cron reaper from reading a git status failure as evidence of uncommitted work. inspectFallbackWorktree returned dirty: true whenever git status --porcelain exited non-zero, so a worktree directory whose .git/worktrees/<name> admin entry had vanished was preserved as "needs manual salvage" on every single fire β€” 15 consecutive days for cron-prompt-miner-0718-0500, which also eroded WORKTREE_DIRTY's value as a triage signal by burying any real one under identical noise. Adds a distinct WORKTREE_ORPHANED outcome that removes the directory (git worktree remove fails once the admin entry is gone, and git worktree prune handles only the inverse case). The orphan is identified structurally β€” a .git file whose gitdir: target no longer exists β€” rather than by matching git status stderr, which is locale-dependent; every other status failure still preserves the worktree, since it cannot be shown that there is nothing to salvage (#694).
  • Resolve the prompt-miner daily-log write root to the main worktree instead of the ephemeral one. render-log-entry.sh used git rev-parse --show-toplevel, which under the cron's worktree: true returns the linked worktree β€” so every Step 5 log entry was written into .oh/worktrees/cron/<session>/ and destroyed when the runtime reaped it (fired 07-10, 07-14, 07-19, hand-recovered each time). Adopts the AUTOPILOT_LOG_ROOT β†’ CRON_WORKTREE β†’ toplevel resolution already proven at .oh/crons/prompt-miner.md:102 and documented at .oh/crons/README.md:120, preserving precedence for callers that do export the variable. Guarded by prompt-miner-log-root-worktree.sh, which builds a real linked worktree and asserts the entry lands in the main one β€” a fixture test cannot catch this class of bug (#693).
  • Make prompt-miner able to mine a marker at all, and stop it mining a wrong one. Three changes: (1) withinWindow now admits a session whose activity span overlaps the window instead of one that starts inside it β€” events are merged across resumed files by sessionId, so a long-lived session kept its original firstTs and vanished from a windowed query despite being worked in continuously; (2) subagent (isSidechain) turns are excluded from every signal β€” they carry the parent's sessionId and role: "user", so a delegate briefing was counted as a human turn, and at 45,167 sidechain vs 42,679 non-sidechain lines this corrupted correctionDensity/turnBloat/toolErrorRate for precisely the delegating sessions most worth mining; (3) the daily cron's window is decoupled from its cadence (--hours 24 β†’ --hours 336), because the marker gate needs β‰₯10 sessions in one stratum and a 24h corpus cannot supply that. Largest stratum by window, measured live: 24h β†’ 4, 168h β†’ 6, 336h β†’ 18. The engine's hardcoded single project directory is deliberately not changed β€” the 23 directories it would add are this cron's own worktree sessions, whose first prompts have one distinct length and two distinct hashes, so they would cross the corpus floor while being incapable of producing a marker (#692).
  • Make the prompt-miner engine run when invoked through the .claude/skills directory symlink that SKILL.md Step 1 and the daily cron both prescribe. Node resolves symlinks for import.meta.url but not for process.argv[1], so the old entrypoint guard silently no-opped β€” exit 0, zero stdout, nothing written β€” and both existing prompt-miner probes hardcode the real .oh/ path, leaving them structurally blind to it. Swaps in the symlink-safe basename guard already used by rlm and weigh, and adds prompt-miner-symlink-entrypoint.sh, which invokes the engine through a real symlink and rejects the comparison β€” in either operand order β€” on any executable line under .oh/skills/**/*.mjs. Does not change the NO-CORPUS outcome β€” see #692 (#663).
  • Index .oh/docs/rfcs/rfc-runtime-support.md from .oh/docs/README.md, which had left a quarter of the RFC/ADR corpus unreachable from the index humans enter through, and repoint the dangling .claude/rules/ context bullet in the critic and implementer agents at .oh/context/IDENTITY.md β€” that directory was removed by the B-state M4 rules collapse (#686).
  • Make Slack bridge admin commands discoverable and functional by declaring /help, /trusted, /channels, /enable, /disable, /revoke, and /toggletools in .pi/install/slack-manifest.json, pinning bridge-side Socket Mode command handlers, and separating Slack commands from Pi's /msg-bridge surface in docs (#354).

Removed

Deprecated

Security

v2026.7.26

Choose a tag to compare

@github-actions github-actions released this 26 Jul 04:43

Added

  • Install Herdr by default as a persistent multi-agent terminal workspace (#651).
  • Add bounded local PDF, DOCX, PPTX, and XLSX normalization to /wiki ingest through Microsoft MarkItDown's pinned upstream CLI, preserving immutable source provenance without a wrapper command (#650).
  • Add the explicit nine-target /audit dispatcher, deterministic focused/queue PR classifier, correlated full campaigns, and shared locked ablation recovery (#646).
  • Adopt cc-safety-net@1.0.6 as the cross-provider destructive-command guard (claude, codex, and pi) β€” a PreToolUse hook that semantically blocks git reset --hard, rm -rf, git push --force, and peers under bypassPermissions/approval_policy=never; the binary is baked into the image at build time (exact pin, zero boot-time registry access), with a CC_SAFETY_NET_OFF=1 kill-switch that disables the claude/codex bash hooks without config edits, a new .oh/scripts/git-maintenance.sh shim so hook-mediated harness automation keeps its legitimate destructive-git operations, and a cc-safety-net-wiring eval probe guarding the wiring (#654).
  • Add the First Mate role charter at .oh/context/rules/first-mate.md and the git-tracked .oh/prompts/advisor/ prompt pack, with a new architect crew agent for solution-shape planning (#660).

Changed

  • Default agent-browser desktop sessions to a 1280Γ—720 viewport (#674).
  • Refresh the default Claude model, durable review-loop guidance, and Cloudflared public-surface verification instructions (#672).
  • Relicense from MIT to Apache License 2.0 with patent grants and trademark clarity; prior MIT releases remain available under MIT and the hosted Console stays proprietary (#666).
  • Make Herdr the canonical first interactive workspace after sandbox entry, with setup and agents organized inside persistent panes and a pinned, checksum-verified CLI (#653).
  • Protect the consolidated /audit owner in place of the superseded harness-audit, skill-lint, eval-lint, and drift-check entry points, staging their removal in the separate audit-consolidation implementation (#647).
  • BREAKING: Consolidate artifact authoring under /builder <agent|skill|command|rule> <name-or-request> with one authoritative reference per type (#643).

Fixed

  • Harden audit consolidation with real GitHub CI normalization, executable run/root/log lifecycle, focused watchdog classification, non-mutating implementation gates, and race-safe ablation recovery fixtures (#646).

Removed

  • BREAKING: Remove superseded audit-family entry points and the auditor agent. Migration: /pr-audit β†’ /audit pr or /audit prs; /harness-audit β†’ /audit harness; /context-audit β†’ /audit context; /skill-lint β†’ /audit skills; /eval-lint β†’ /audit eval-quality; /drift-check β†’ /audit drift; /audit <slug> β†’ /audit implementation <slug>; auditor campaigns β†’ /audit full (#646).
  • Remove the legacy agent-builder, skill-builder, command-builder, and rule-builder agents and the superseded /skill-builder entry point; migrate callers to /builder (#643).
  • Retire the dead RISKY_BASH array and its bash branch from pi's .pi/extensions/path-guard.ts β€” it was a no-op in both headless and TUI modes, now superseded by cc-safety-net's fail-closed pi extension; SENSITIVE_PATHS and the /guard command are retained (#654).

Deprecated

Security

  • Add a reproducible, audit-gated pi-langfuse@1.5.7 installer that overrides its vulnerable OpenTelemetry SDK tree to patched @opentelemetry/sdk-node@0.220.0 (#664).
  • Pin the transitive postcss dependency (reached via vitest > vite) to the patched ^8.5.18 via pnpm.overrides, clearing GHSA-r28c-9q8g-f849 and unblocking pnpm run security:audit on every PR (#668).
  • Move every pinned GitHub Action off the deprecated Node 20 runtime β€” actions/checkout@v7, actions/setup-node@v7, pnpm/action-setup@v6, actions/cache@v6, softprops/action-gh-release@v3, docker/setup-buildx-action@v4, docker/login-action@v4 β€” and unpin the major in the pnpm-audit-ci-gate probe so future runtime bumps do not read as regressions (#670).

v2026.7.15

Choose a tag to compare

@github-actions github-actions released this 15 Jul 06:16

Added

Changed

Fixed

  • Keep the cron-watchdog temp file (/tmp/cron-watchdog.sh) root-owned so a container restart (docker start) can rewrite it, and make the optional cron supervisor non-fatal under set -e; previously the root entrypoint could not overwrite the sandbox-chowned file on the second boot (EACCES on runtimes without CAP_DAC_OVERRIDE), which crash-looped the node (#640).

Removed

Deprecated

Security