Repository navigation
Releases: herehigher/sapwood
Release list
v0.3.0-alpha.4
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 (anysettings*.jsondirectly under.claude/),
not justsettings.jsonandsettings.local.json. - Dependabot watches the
github-actionsecosystem (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 torelease-evidence.txt, attested
withactions/attest-build-provenancefrom 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.mdstate 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/user403, botauthor_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 tonull(REST
GET /useranswers 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_onlyspelling 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
Changed
release publishno longer runsnpm publishlocally — the tag-push run'snpm-publish
job publishes via npm trusted publishing (OIDC) with provenance;--otpremoved;release dist-tag <version>added.
Fixed
- The
sapwoodnpm tarball shipsREADME.mdandLICENSE:engine'sprepackstages 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
Changed
docs/guide/configuration.mdgains 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-rolemodel/effort/promptFile, androles.skills.enabled.- README badges and status reflect the published pre-release; the OpenSSF Scorecard badge uses
the officialscorecard.devURLs. - Until the first plain release, the publishing human moves npm's
latesttag to the newest
pre-release after each publish, so a barenpx sapwoodinstalls a working engine instead of
the0.0.1placeholder.
Fixed
sapwood initandsapwood runin 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 --helpdescribes the flowinitactually runs.- The getting-started bootstrap config validates as written, and
sapwood run --dry-runapplies
the same engine-agent CI refusal assapwood validateinstead of exiting 0 with a warning. - The goal file, review doctrine, and architecture chapter reach prompts with HTML comments
removed, so the authoring guidance insapwood 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 thegithub-pagesv*tag deployment
policy thedeploy-demojob 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
fromdocs/security.md; the guard-hook source, the compiled guard, guard-hook, reviewer, and
merge-driver artifacts, both.ymlconfig variants, and.github/CODEOWNERSwere 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
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 ofdoctrine.file(now genuinely
this repo's own residue);loadDoctrinereturns 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 scaffoldeddoctrine.filefromengine/prompts/doctrine-template.md
before this change, delete its## Adjudication doctrinesection (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
ownertag
(producerdefault, oroperator— 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 toneeds-humanwithout
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
sapwoodnpm package, including the packaged dashboard; post-publish dashboard canary
and catalog promotion of the thin marketplace shell. /sapwood-dashboardmarketplace slash command and a Windows pack/install/dashboard smoke thatrelease publishruns as its first, gating step.- Plugin skeleton, YAML/JSON config schema,
IForgeGitHub adapter, WAL-mode
SQLite state layer;sapwood initonboarding — 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-stopselectable; cost ceiling, kill switch,
TOCTOU-pinned merge. run/status/validate/dashboardCLI, 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,ghalias/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.tsPreToolUse 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...