Skip to content

Releases: herehigher/sapwood

v0.3.0-alpha.4

v0.3.0-alpha.4 Pre-release
Pre-release

Choose a tag to compare

@herehigher herehigher released this 31 Aug 02:00
Immutable release. Only release title and notes can be modified.
2da3b67

Security

  • The guard's Bash write-path scan no longer drops a --leading argv token that contains a path
    separator, so a relative path whose first segment starts with - (cp src -x/../sapwood.config.yaml,
    rm -- -x/../.sapwood/PAUSE) is examined like any other and denied; the .claude/settings*.json
    human-merge-only rule matches the documented glob (any settings*.json directly under .claude/),
    not just settings.json and settings.local.json.
  • Dependabot watches the github-actions ecosystem (monthly, two open PRs at most) so SHA-pinned
    actions stop going stale silently; npm dependencies stay on the alerts-only posture.

Changed

  • Every GitHub Release carries the packed engine tarball (sapwood-<version>.tgz) and its Sigstore
    provenance bundle (sapwood-<version>.tgz.sigstore.json) next to release-evidence.txt, attested
    with actions/attest-build-provenance from the tag-push run; a consumer verifies with
    gh attestation verify sapwood-<version>.tgz --repo herehigher/sapwood --bundle <bundle>.
  • The getting-started "Trust model prerequisites" and docs/security.md state producer≠merger as what
    it is — credentialTier: L1 + the guard + a single merge call site — instead of implying a distinct
    merger identity; they name when a separate merger principal (a GitHub App or machine account) is
    worth deploying for the single merge call, and the platform constraints on running the whole
    conductor as an App (installation-token /user 403, bot author_association: NONE, user-owned
    Projects v2 closed to Apps).
  • README shows the OpenSSF Best Practices badge next to the Scorecard badge.

Fixed

  • The forge reads the authenticated actor through GraphQL viewer { login }, so a GitHub App
    installation token resolves to its <slug>[bot] login instead of falling closed to null (REST
    GET /user answers 403 for it) and having the trusted-author filter withhold the engine's own comments.
  • The startup write-access check accepts gh 2.95's raw read_only spelling in the deploy-key list, so
    the L1 gate confirms write access on a healthy key instead of failing closed.

What's Changed

  • docs(readme): drop the stale "go live with the first tagged release" sentence by @herehigher in #1201
  • security: Dependabot for the github-actions ecosystem only by @herehigher in #1207
  • release: attach the engine tarball and its Sigstore bundle to every GitHub Release by @herehigher in #1206
  • test(guard): fast-check property test on path-denial invariants by @herehigher in #1210
  • security(guard): leading-dash write-path bypass + .claude/settings*.json glob widen by @herehigher in #1214
  • chore(deps): bump actions/setup-node from 4.4.0 to 7.0.0 by @dependabot[bot] in #1209
  • chore(deps): bump actions/checkout from 4.4.0 to 7.0.1 by @dependabot[bot] in #1208
  • docs(readme): add OpenSSF Best Practices badge by @herehigher in #1216
  • fix(forge): read the actor login through GraphQL viewer so an App installation token resolves (#1165) by @sapwood-runner[bot] in #1217
  • security(#1165): dogfood flips to L1; docs state producer≠merger honestly by @herehigher in #1218
  • fix(cli): accept gh 2.95's raw read_only spelling in the deploy-key list parse by @herehigher in #1220
  • changelog: Unreleased entries for 0.3.0-alpha.4 by @herehigher in #1221
  • release: v0.3.0-alpha.4 by @herehigher in #1222

New Contributors

  • @dependabot[bot] made their first contribution in #1209
  • @sapwood-runner[bot] made their first contribution in #1217

Full Changelog: v0.3.0-alpha.3...v0.3.0-alpha.4

v0.3.0-alpha.3

v0.3.0-alpha.3 Pre-release
Pre-release

Choose a tag to compare

@herehigher herehigher released this 28 Aug 09:06
Immutable release. Only release title and notes can be modified.
797cdb7

Changed

  • release publish no longer runs npm publish locally — the tag-push run's npm-publish
    job publishes via npm trusted publishing (OIDC) with provenance; --otp removed; release dist-tag <version> added.

Fixed

  • The sapwood npm tarball ships README.md and LICENSE: engine's prepack stages the
    repository-root copies into the package root, so npmjs.com renders the README and shows the
    license instead of "This package does not have a README".

What's Changed

  • publish(npm): ship README.md and LICENSE in the engine tarball by @herehigher in #1197
  • release: npm-publish moves into release.yml via trusted publishing (OIDC); local npm publish and --otp retired by @herehigher in #1198
  • release: v0.3.0-alpha.3 by @herehigher in #1200

Full Changelog: v0.3.0-alpha.2...v0.3.0-alpha.3

v0.3.0-alpha.2

v0.3.0-alpha.2 Pre-release
Pre-release

Choose a tag to compare

@herehigher herehigher released this 28 Aug 07:04
Immutable release. Only release title and notes can be modified.
c7f21ae

Changed

  • docs/guide/configuration.md gains rows for 23 schema-valid keys that had none: the empty-spin
    breaker, pool-removal and concern-post caps, the architect drop cap, proxy audit-comment caps,
    per-role model/effort/promptFile, and roles.skills.enabled.
  • README badges and status reflect the published pre-release; the OpenSSF Scorecard badge uses
    the official scorecard.dev URLs.
  • Until the first plain release, the publishing human moves npm's latest tag to the newest
    pre-release after each publish, so a bare npx sapwood installs a working engine instead of
    the 0.0.1 placeholder.

Fixed

  • sapwood init and sapwood run in a directory with no config, or an invalid one, stop with
    sapwood validate's concise config-error formatting instead of a Node stack trace;
    sapwood init --help describes the flow init actually runs.
  • The getting-started bootstrap config validates as written, and sapwood run --dry-run applies
    the same engine-agent CI refusal as sapwood validate instead of exiting 0 with a warning.
  • The goal file, review doctrine, and architecture chapter reach prompts with HTML comments
    removed, so the authoring guidance in sapwood init's scaffolds no longer reads as doctrine
    or locked architecture. Comments inside Markdown code spans, fenced blocks, and indented code
    are kept; on-disk files are unchanged.
  • release publish's npm step runs on an interactive terminal so 2FA web-auth can complete, and
    publish --otp <code> is accepted; the runbook names the github-pages v* tag deployment
    policy the deploy-demo job needs.

Security

  • The PO/align backlog digest and plan-triage candidate selection apply the author-trust filter
    to issues: text is shown only for authors GitHub classifies as owner, member, or collaborator,
    the authenticated operator, or a known reviewer bot; other issues appear at most as an
    aggregate count, never as rendered text. The open-backlog read pages GraphQL with a fixed
    ten-page ceiling and fails closed if the ceiling is reached before exhaustion; the
    recently-closed dedup read is a separate bounded one-page window.
  • The shipped PO and verification-plan prompts carry the complete human-merge-only path list
    from docs/security.md; the guard-hook source, the compiled guard, guard-hook, reviewer, and
    merge-driver artifacts, both .yml config variants, and .github/CODEOWNERS were absent
    before this fix. The prompts are checked against the canonical section so a future addition
    cannot leave any carrier stale.

What's Changed

  • docs: README badge and status reflect the published pre-release; translations drop badges by @herehigher in #1180
  • cli: init --help describes the real flow; missing/invalid config is a one-line refusal for init and run (#1182) by @herehigher in #1184
  • docs(getting-started)+cli: bootstrap config validates verbatim; dry-run applies the engine-agent CI refusal (#1181) by @herehigher in #1183
  • docs(readme): OpenSSF Scorecard badge on the official scorecard.dev URLs by @herehigher in #1185
  • docs(configuration): rows for the six schema-valid keys that had none by @herehigher in #1186
  • prompts+test: human-merge-only path lists mirror docs/security.md's canonical section (derived oracle) by @herehigher in #1188
  • engine: prompt loaders strip HTML comments from doctrine, goal file and architecture chapter by @herehigher in #1189
  • security(align): author-trust filter covers issues in the PO/align digest and candidate selection by @herehigher in #1190
  • release: npm-publish inherits stdio / --otp passthrough; docs+workflow name the 2FA and Pages tag-policy prerequisites by @herehigher in #1187
  • docs(releasing): latest tracks the newest pre-release until the first plain release (bounded exception) by @herehigher in #1191
  • changelog: Unreleased entries for 0.3.0-alpha.2 by @herehigher in #1192
  • release: v0.3.0-alpha.2 by @herehigher in #1194

Full Changelog: v0.3.0-alpha.1...v0.3.0-alpha.2

v0.3.0-alpha.1

v0.3.0-alpha.1 Pre-release
Pre-release

Choose a tag to compare

@herehigher herehigher released this 27 Aug 09:58
Immutable release. Only release title and notes can be modified.
98d3ba9

Changed

  • Runtime directory rename — see Configuration — The .sapwood/ runtime
    directory
    for the layout.
    Upgrading: stop the engine before upgrading; the new CLI reads and writes .sapwood/
    only; no automatic migration. Cutover checklist (idempotent and resumable — safe to re-run
    if interrupted):

    # engine stopped (pid gone, no sapwood.lock holder)
    mkdir -p .sapwood/cache .sapwood/keys
    for f in sapwood.sqlite sapwood.sqlite-wal sapwood.sqlite-shm sapwood.lock KILL_SWITCH PAUSE EMERGENCY_STOP ESCALATION \
             DIRECTIVE.md attention-dismissals.jsonl directives rounds proxy-bundles logs sessions; do
      [ -e "data/$f" ] && mv "data/$f" .sapwood/
    done
    for d in review generated; do [ -e "data/$d" ] && mv "data/$d" .sapwood/cache/; done
    for k in data/worker-deploy-key*; do [ -e "$k" ] && mv "$k" .sapwood/keys/; done
    # sapwood.config.yaml: worker.deployKeyPath → .sapwood/keys/worker-deploy-key[-host]
    
  • Removed the repository's root AGENTS.md; the hosted-bot review-round discipline it carried
    is now documented as a snippet for a target repository's own instruction file (configuration
    guide → Hosted-bot review guidelines).

  • Review doctrine now ships as two carriers: engine/prompts/doctrine-core.md (generic,
    framework-owned, upgraded by every release) is injected ahead of doctrine.file (now genuinely
    this repo's own residue); loadDoctrine returns the concatenation, always present on every
    engine-composed surface. The hosted gate② review-trigger comment no longer carries any doctrine
    text — a hosted bot's standing review guidance belongs in its own instruction file instead.
    Upgrading: if you scaffolded doctrine.file from engine/prompts/doctrine-template.md
    before this change, delete its ## Adjudication doctrine section (principles 1–4) and its
    "Authoritative signals over inferred text" bullet — both now ship in the framework core and
    would otherwise be redundant.

  • The engine-agent review session's structured findings gain a per-finding owner tag
    (producer default, or operator — the finding's entire unmet requirement is evidence only
    an operator can post, e.g. a tier-C human-witnessed probe record). A rejected verdict whose
    blocking findings are ALL operator-owned now escalates straight to needs-human without
    dispatching a fix leg; a mixed verdict still dispatches for its producer-owned share, with the
    operator-owned findings excluded from convergence tracking.

Added

  • Bare sapwood npm package, including the packaged dashboard; post-publish dashboard canary
    and catalog promotion of the thin marketplace shell.
  • /sapwood-dashboard marketplace slash command and a Windows pack/install/dashboard smoke that release publish runs as its first, gating step.
  • Plugin skeleton, YAML/JSON config schema, IForge GitHub adapter, WAL-mode
    SQLite state layer; sapwood init onboarding — auth preflight, org
    detection, idempotent board/label/milestone provisioning.
  • Conductor tick loop + headless worker: one Ready issue per isolated worktree
    lane, guard wired live into every session.
  • Review gate + merge driver: CI-green plus a fresh non-author review gates an
    autonomous merge; produce-PR-and-stop selectable; cost ceiling, kill switch,
    TOCTOU-pinned merge.
  • run/status/validate/dashboard CLI, plugin slash commands, first-run
    trust ramp, kill-switch/pause sentinels, goal-based stop conditions.
  • Round orchestrator: peripheral roles (goal alignment, architecture review,
    gate⓪ verification-plan review, harvest, retrospective) wrapped around the
    tick loop; idle-round standby, gated-PR re-entry, round summaries, dispatch
    quotas, role toggles.
  • Review-doctrine injection and environment-failure park — env-vs-task failure
    classification with bounded-backoff auto-resume.
  • Round-pool selection, architect batch review, per-round budget/backlog
    accounting hardening.
  • Metered, audited read-only MCP proxy for judgment roles; write-ahead
    hardening on the engine's own forge writes.
  • Fix loop: workers resolve their own review findings under a three-tier
    hold/needs-human/blocked escalation, so humans adjudicate but never resolve
    reviews themselves.
  • engine-agent: an engine-composed, static, different-Claude-model gate②
    reviewer, promoted to the default review mode.
  • Egress tripwire (monitor-only), the L0–L3 autonomy ladder, native PO-issue
    decomposition.
  • v0.2 dashboard — event schema, GET /api/loop/state//events, React
    lane-board and event-feed UI — built end-to-end through sapwood's own loop as
    the flagship dogfood run.
  • Dogfood hardening surfaced by that run: worker capability containment
    (credential-free producer legs, gh alias/extension denial), engine
    robustness (cursor/snapshot drift recovery, merge-gate TOCTOU, resume/fix-leg
    interaction), and host-delegated capability management with configurable
    execution profiles (host.permissionMode, bashSandbox).

Security

  • Fail-closed guard.ts PreToolUse hook, zero-dependency, with a reproduced
    bypass suite and differential/fuzz tests — green before any autonomous run.
  • Human-merge-only enforcement for the guard, reviewer, merge driver, security
    config, .claude/settings*.json, and .github/workflows/**.
  • Branch-protection detection (warn-only) as the documented backstop for the
    inherited-host-tool-surface trust model.

What's Changed

  • docs: project overview + extracted framework plan by @herehigher in #1
  • docs: config format → YAML (commented; JSON still parses) by @herehigher in #18
  • docs: documentation principle (SoT partition + round-close doc gate) by @herehigher in #19
  • chore: rename borehole → sapwood by @herehigher in #20
  • docs: soft worker budget + verification-plan dispatch gate by @herehigher in #21
  • M0: skeleton + config schema + IForge + SQLite state by @herehigher in #22
  • docs: close M0 round — delivery + locked stack decisions by @herehigher in #23
  • M0.5: sapwood init — auth preflight + idempotent provisioning by @herehigher in #24
  • docs: close M0.5 round — sapwood init delivered by @herehigher in #25
  • M1: guard.ts (fail-closed PreToolUse safety core) + Write-path protection by @herehigher in #27
  • M1: differential/fuzz test of guard.ts vs guard.py by @herehigher in #28
  • docs: close M1 round — guard safety core delivered by @herehigher in #29
  • M2 #10: conductor tick (reclaim→drive→dispatch) + structured results by @herehigher in #30
  • M2 #11: worker.ts — headless claude -p wrapper (Supervisor impl) by @herehigher in #32
  • M2 #26: wire the guard hook live into worker sessions (hard default / soft opt-in) by @herehigher in #34
  • feat(cli): add --version and --help flags by @herehigher in #36
  • docs: close M2 round — engine core + live guard delivered, dogfood proven by @herehigher in #38
  • fix(guard): realpath direct-invocation check + honest budgetUsdSoft comment by @herehigher in #39
  • fix(init): preserve Status option ids to stop item-status wipe on board provisioning by @herehigher in #40
  • M3 #14: engine-enforced cost ceiling + kill switch by @herehigher in #41
  • M3 #13: review gate + opt-in autonomous-merge (reviewer.ts + merge-driver.ts) by @herehigher in #42
  • fix(guard): protect merge-driver source + gate dist artifacts from worker writes by @herehigher in #43
  • fix(conductor): harden double-failure rollback/requeue paths (#31) by @herehigher in #44
  • docs: close M3 round — review gate + merge modes + cost ceiling delivered by @herehigher in #45
  • M4 #47: cost telemetry — model + categorized token usage in the spend ledger by @herehigher in #48
  • M4 loop driver: tick cadence, resume cost-delta, gate② plan re-check by @herehigher in #50
  • ci: GitHub Actions — typecheck + test on Node 22 (unblocks gate①) by @herehigher in #52
  • fix(reviewer): wire the 👍 thumb verdict — gate② wedged on Codex's real clean-verdict shape by @herehigher in #55
  • fix(reviewer): comment-shaped clean verdict counts — the last Codex verdict channel by @herehigher in #56
  • cli: sapwood validate — config validation command (#49) by @herehigher in #51
  • chore: add .editorconfig by @herehigher in #58
  • fix(engine): drain writes .handoff via supervisor-side commit+push by @herehigher in #62
  • fix(conductor): kill switch freezes the DRIVE loop's merge path too by @herehigher in #61
  • fix(engine): detached-lane handoff — probe() confirms death and preserves WIP by @herehigher in #67
  • feat(reviewer): configurable failover, gate② s...
Read more