Skip to content

Release notes

Every published release of Systematic, newest first. Narratives are written by Fro Bot; see also GitHub Releases.

Published 2026-10-15 · Updated 2026-10-15 · View on GitHub

The local operation observer now checks worktree content independently of Git’s clean filters and configuration, preventing changed files from appearing unchanged and stale evidence from being reused. Snapshots include HEAD paths dropped from the index and ignore-rule contents, compare raw file bytes and modes against HEAD, and refuse snapshots when repository anchors move or content changes during the read. Submodule checks distinguish uninitialized and displaced paths, while length-prefixed digest fields prevent ambiguous tree identities. These changes close false-clean paths that could otherwise allow an uncommitted edit to mint a commit receipt. (#1129)

PostCSS’s compatible Nano ID dependency is resolved to 3.3.20 to address the denial-of-service advisory GHSA-2v37-7h3g-55p8, with manifests and other locked packages unchanged. (#1127)

New solution records capture the digest-collapse, release-gate, brokered-push and action-pin fixes, along with the operation observer’s false-clean fixes and the review-spiral scope cut, preserving those findings for future work. (#1122, #1130)

Release tests no longer tie the App token action to one specific commit, avoiding test failures on Renovate updates. The step test checks the action’s identity, while the shared action-pin test continues to require a full 40-character commit SHA and a version comment. (#1121)

  • deps: Update actions/create-github-app-token to v3.3.0 (#1102), fro-bot/agent to v0.122.2 (#1123), and github/codeql-action to v4.39.0 (#1132).

v3.22.3…v3.22.4

Published 2026-10-14 · Updated 2026-10-14 · View on GitHub

Guarded workflows now fingerprint full-length identities and operation arguments. Previously, identities longer than 1,024 characters shared a constant digest, hiding changes, while write, edit, and patch arguments longer than 8,192 characters could make an active guard unavailable. Identity hashing now includes the complete trimmed value, and argument serialization removes the size budget while retaining its depth limit. JSON-encoded state fields preserve field boundaries, and validation rejects non-plain objects and symbol-keyed properties before patch canonicalization can hide them. (#1119)

Sessions without active guarded work no longer pay for before-and-after worktree snapshots. Operations are observed only while an epoch is active or an allowlisted skill load is pending; skipped operations also stay silent when after-hooks arrive more than once. This avoids unnecessary snapshot overhead and prevents unrelated snapshot failures from disabling the guard. (#1116)

The scheduled release gate now accepts GitHub-verified release commits whose committer is web-flow, matching commits created through the GitHub API. Every commit must still be authored by the release App, and an App committer remains accepted. This fixes the gate refusing release PRs produced by the refresh job. (#1120)

Security fixes bound indexed source-map processing, patch the Sharp librsvg vulnerability, and reject injected URI authority components. (#1060, #1059, #1052)

Trusted comments on same-repository PRs now anchor checkout and brokered push to the resolved PR head SHA, so fixes are delivered rather than losing the agent’s local commit. Fork heads remain refused. The brokered push also permits changes to skills, agents, tests, and registry files while keeping workflow files, scripts, manifests, and lockfiles denied. (#1117)

The hourly release reconcile has been removed: pushes to main already refresh the release PR, and publication follows the merge of an approved release PR. Recovery remains available by rerunning or dispatching the Release workflow while main still points at the release merge. (#1112)

The Biome schema now matches the installed release, and Renovate updates the schema alongside the package. This release also records the v3.22.3 release commit. (#1056, a3e4273)

  • dev: Update OpenCode to v1.19.0. (#1118)
  • deps: Update fro-bot/agent to v0.122.1. (#1114)

v3.22.2…v3.22.3

Published 2026-10-13 · Updated 2026-10-13 · View on GitHub

Loading a skill no longer starts an unrelated guarded workflow. Previously, unrecognized skills were treated as ce:work, so loading ce:review, ce:brainstorm, or another skill could demand implementation evidence, reopen a completed unit, or collide with an active shipping workflow. Only ce:work, git-commit, and git-commit-push-pr now activate a workflow epoch, with or without the systematic: prefix; other skill loads leave guard state unchanged. (#1107)

Bundled workflow handoff targets now resolve, and skill instructions and review persona descriptions use loadable names such as ce:plan, ce:brainstorm, and document-review instead of directory-form names that caused not-found errors. Content-integrity checks reject stale names in code spans and prose while preserving paths, filenames, qualified agent IDs, and fenced code. (#1110, #1111)

Real-host guard tests now verify that skill loads actually succeed, rather than accepting the absence of guard markers as sufficient evidence. The non-allowlisted ce:plan scenario confirms output exceeding 32 KB and an inactive guard on a follow-up status call; the allowlisted ce:work scenario also checks the size threshold. Coverage additionally pins the fail-closed outcome when a skill name changes between hooks. (#1109, #1107)

  • release: Version metadata updated for v3.22.2.

v3.22.1…v3.22.2

Published 2026-10-13 · Updated 2026-10-13 · View on GitHub

The workflow guard can now snapshot larger repositories without becoming unavailable on the first shell command: local limits rise to 128 MiB of file content, 20,000 files, and 8 MiB of listing output. Remote readbacks retain separate limits of 4,096 items and 1 MiB, so larger local snapshots do not loosen remote bounds. (#1101)

When a hook makes the guard unavailable, status now records a bounded, enum-only cause and the hook site instead of a bare unavailable state. Initialization failures are recorded, protected mode rejects tool calls when no guard can be published, and history confirmation preserves an already-recorded hook failure. Diagnostic causes exclude raw exception messages, including potentially sensitive file names. (#1101)

Releases now publish only by merging the gated release pull request, with npm authentication through OIDC trusted publishing. The legacy publish path and RELEASE_MODE switch are removed. Release follow-on workflows rely on a GitHub release authored by the release App as evidence that npm publishing completed, avoiding failures caused by registry visibility delays. The real-host contract check is required on main, and recovery documentation covers both a failed npm upload that leaves a tag and an npm publish whose GitHub release is missing. Release narration also uses the runner’s permitted scratch directory. (#1100)

The release pull-request refresh job now runs even when the upstream publish job is skipped, while still requiring a successful render on main. This fixes ordinary merges rendering a release pull request without opening it. (#1103)

  • deps: Update web-tree-sitter to v0.27.1. (#1085)
  • release: Record the v3.22.1 version bump.

v3.22.0…v3.22.1

Published 2026-10-12 · Updated 2026-10-13 · View on GitHub

Releases gain an approval-gated path: a release-app pull request carries the pending version and its CHANGELOG.md entry, previewed with semantic-release’s existing version rules. In gated mode, publishing requires approval on the exact pull-request head from the maintainer or an attested scheduled gate. The approved changelog entry becomes the release notes, and a version mismatch stops publishing before a tag is created. (#1094)

The scheduled gate checks the release pull request against current main and all required checks before approving it. A release hold blocks gate-only publishing and is read live immediately before publication. Reconciliation refreshes the pending release, preserves approvals when its contents are unchanged, and handles superseded or already-published releases. RELEASING.md documents the cutover, holds, verification, and recovery procedures; a generated docs changelog shows entries through the deployed release tag.

Release-note rewriting runs in its own workflow, and documentation builds use the published release tag so the deployed docs correspond to that release. (#1092)

The release pipeline separates read-only preview and build jobs from credentialed publishing. Claude Code plugin publication moves to a dedicated post-release workflow that waits for the version to appear on npm. Repository rules require an approved pull request for changes to main and restrict release branches to the release app; Fro Bot approval is limited to maintainer-authored pull requests without Fro Bot commits. (#1094)

  • deps: Updated fro-bot/agent through v0.121.0 to v0.122.0 (#1093, #1098) and ossf/scorecard-action to v2.5.0 (#1091).
  • dev: Updated @types/node to v26.6.5 (#1097).

v3.21.8…v3.22.0

Published 2026-10-12 · Updated 2026-10-12 · View on GitHub

Workflow-guard readback timeouts no longer disable the guard for the rest of the session after an operation has succeeded. Status refreshes now report timed-out probes in unconfirmedReadbacks, while completion attempts return a retryable readback-timeout and leave the unit active. This lets a slow git or gh readback recover without treating an unverified result as confirmed. Guidance allows at most two completion retries before reporting the timeout; other readback failures still fail closed. (#1088)

  • deps: Update bfra-me/.github to v4.38.0 (#1086) and fro-bot/agent to v0.120.0 (#1087).

v3.21.7…v3.21.8

Published 2026-10-11 · Updated 2026-10-12 · View on GitHub

The workflow guard now defers only the affected remote operation when its activation probe times out, rather than permanently disabling the entire session. The unit and epoch stay active, and the deferred operation remains required. Its own before-read can establish a baseline from the same observer and target, with one retry on timeout. A push with no upstream also defers instead of disabling the session, though that first push still cannot produce a receipt.

PR creation now establishes its baseline from the after-read only when the before-read reported a missing resource. Timed-out or failed before-reads no longer admit a PR-creation receipt as though no PR had existed. Check and review readbacks retain their deferrals when their before-read reports a missing resource. Other activation-seeding failures remain fatal. See #1082.

v3.21.6…v3.21.7

Published 2026-10-11 · Updated 2026-10-11 · View on GitHub

The workflow guard now reports a session that has not started a guarded workflow as inactive / no-active-epoch, reserving unavailable for genuine failures. This prevents agents checking status first from treating an idle session as terminal and skipping completion enforcement. Status calls no longer poison fresh-session initialization or discard pending sibling operations, and completion before a workflow starts returns a guard-owned rejection rather than an error. Unavailable status also exposes a bounded diagnostic cause, while failed history reads continue to fail closed. See #1079.

The architecture guide now explains the optional arguments parameter on systematic_skill: supplied arguments replace $ARGUMENTS and positional $N placeholders, or are appended when the skill has no placeholders. This documents how callers pass task-specific input into loaded skills. See #1078.

  • Development tooling: OpenCode v1.18.35, conventional-changelog-conventionalcommits v10.4.1, Playwright v1.64.0, TypeBox updates through v1.3.36, and routine non-major dependency updates.
  • Dependencies: smol-toml ~1.9.0 and successive fro-bot/agent updates through v0.119.3.
  • CI actions: actions/setup-node v7.1.0, actions/upload-artifact v7.0.2, bfra-me/.github v4.37.0, and github/codeql-action v4.38.3.

v3.21.5…v3.21.6

Published 2026-10-04 · Updated 2026-10-04 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • security: prevent devalue serialization vulnerabilities (#1045) (2b8ef00)
  • security: prevent malformed TOML parser hangs (#1048) (7e4d564)

Published 2026-10-04 · Updated 2026-10-04 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • security: bound vulnerable brace expansion (#1044) (c12588b)

Published 2026-10-04 · Updated 2026-10-04 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • security: patch runtime YAML merge-source denial of service (#1042) (98a6dfb)

Published 2026-10-04 · Updated 2026-10-04 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • security: patch Astro AVIF image processing (#1039) (749e3ab)

Published 2026-10-04 · Updated 2026-10-04 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • guard: keep the workflow-guard marker stable across requests (#1049) (bb68089)
  • architecture: document profile selector precedence and protected-fields module (#1031) (891518c)
  • solutions: document skill output truncation, guard size cap, and jq false default (#1032) (2e43db4)
  • prevent bot edits from retriggering Renovate (#1038) (ce89aea)
  • deps: update bfra-me/.github action to v4.34.0 (#1035) (85f5d5d)
  • deps: update bfra-me/.github action to v4.35.0 (#1041) (1bfa2cb)
  • deps: update fro-bot/agent to v0.116.0 (#1033) (569c32c)
  • deps: update fro-bot/agent to v0.117.0 (#1036) (b4a62cd)
  • deps: update fro-bot/agent to v0.117.1 (#1040) (f9f2029)
  • dev: update dependency @biomejs/biome to v2.5.15 (#1046) (db78f32)
  • dev: update dependency @types/node to v26.6.3 (#1037) (4b7eebd)

Published 2026-09-26 · Updated 2026-09-26 · View on GitHub

OpenCode now delivers the complete text of skills loaded through systematic_skill, including large skills such as ce:review and ce:plan that previously arrived truncated by OpenCode’s tool-output cap. The tool restores its saved result only when OpenCode marked it as truncated and the preview matches; explicit user-configured output limits remain in effect. systematic_skill also accepts optional arguments for skill placeholders, while commands for discovered skills now include the full skill body. A related workflow-guard fix lets skills larger than 32 KB start guarded workflows. The ce:review snippet was adjusted so command argument substitution does not erase its awk variables. (#1029)

Three new solution notes capture lessons about reviewing worktree diffs, expressing a guarantee through merge order and field-additive merging, and sharing constants across dependency boundaries. Two existing notes now reflect current configuration behavior: protected fields are stripped with a warning rather than rejecting the load, and opted-in project profile bundles can fill unset user fields. Citation paths and declaration references were corrected so readers can follow them from the repository root. (#1013, #1016)

Fro Bot’s comment-trigger fork check now distinguishes false from a missing fork flag. This allows comments on same-repository PRs to run the agent, while fork PRs and missing head-repository data remain refused. (#1030)

  • Updated the OpenCode development dependency to v1.18.32, TypeBox to v1.3.34, and @types/node to v26.6.2.
  • Updated bfra-me/.github to v4.33.0, fro-bot/agent to v0.115.1, and github/codeql-action to v4.38.2.
  • Aligned the Biome schema version.

v3.20.0…v3.21.0

Published 2026-09-20 · Updated 2026-09-20 · View on GitHub

A repository can now ship the model routing it depends on. Until this release, a repository that declared its own OpenCode provider had no way to distribute the routing that consumes it. Project config could select a named profile but never define one, so the routing had to live in every teammate’s global config — unshareable by cloning, and dead weight in every other repository. This release adds allow_project_profiles: when a user turns it on, a repository’s project config may define its own profiles map (#1011, 7fbecd0).

The guarantee is that a project-defined bundle supplies routing only where user-owned config is silent. It can never override, and never partially clobber, a value you set. That holds structurally rather than by policy: the overlay chain is normally user base → active profile → project → custom, but when the active bundle came from project config it is placed first instead, so user base merges over it. Nothing checks “is this allowed” — the ordering is the guarantee. Merging is field-additive one level into the opencode and pi blocks, reusing the same mergeProfileOverlayValue a normal profile already uses, with only the argument order differing, so next wins each field it sets and the other side fills the gaps.

Whole-entry replacement was the alternative, and it fails concretely: setting opencode.variant on an agent whose project bundle sets opencode.model erases the model, leaving a qualifier with no model — which assertRoutingInvariants rejects, breaking the whole config load because you customised one field. There is a test for exactly that case. Because the guarantee comes from two separated code sites rather than a single check, a test pins each one; the ordering test was verified to fail for the right reason, reporting the project’s losing value where the user’s should be. ARCHITECTURE.md states plainly that the guarantee is a consequence of the implementation as written and is not separately enforced.

The opt-in is itself protected. allow_project_profiles joins workflow_guard in a new PROJECT_ALWAYS_PROTECTED_FIELDS set stripped from a project source unconditionally, and its effective value resolves from custom and user config only — a repository cannot grant itself the permission. A project config that sets the opt-in and ships a profiles map in the same file gets both stripped, which is covered by a test. profiles moved out of the always-protected set into a conditional strip, the only behavioural change when the opt-in is off; with it off, everything is byte-identical to before, and the existing test locking project-profile stripping passes unmodified. Name collisions cannot shadow either: bundle lookup is custom, then user, then project last, so a user-defined name always wins, and SYSTEMATIC_PROFILE still overrides which profile a repository selects for itself. SECURITY_OVERLAY_FIELDS is untouched and ProfileOverlaySchema remains routing-only, so a bundle is structurally incapable of carrying permission or skills — which is what keeps this a narrow surface.

Two supporting changes ship alongside. Config sources previously loaded user → project → custom, but the opt-in can be set in OPENCODE_CONFIG_DIR config, which outranks user, so a custom-set opt-in was unknown when the project source was parsed and stripped. User and custom now load ahead of project, with the alias machinery — where project and custom can resolve to the same file — re-verified against its existing tests unchanged. Separately, because advisory semantics make “the bundle applied nothing” a normal outcome, a bundle fully absorbed by user config would otherwise be indistinguishable from no bundle at all. config show now reports Defined in: naming the file that defined the active bundle, and each routing field carries an origin (user, custom, user-profile, custom-profile, project-profile) alongside the existing shape provenance, so full absorption reads as every field user-origin while a project profile is active. Origin is tracked per merge step rather than derived from the overlay entry’s sourcePath, which is last-writer-wins and would misattribute a field whose value survived from an earlier step. Both surface in --json as activeProfileSourcePath and per-field source.*.origin.

v3.19.0…v3.20.0

Published 2026-09-19 · Updated 2026-09-19 · View on GitHub

The active model profile can now be selected from the environment. Deployments and automation can choose the intended profile at runtime instead of requiring a project configuration change for each environment.

The architecture guide now records the guard cause diagnostic and the solution-schema gate, making both validation mechanisms explicit for contributors investigating workflow behavior.

  • dev: Updated all non-major development dependencies.

v3.18.10…v3.19.0

Published 2026-09-19 · Updated 2026-09-19 · View on GitHub

Workflow guard status now preserves the first failure encountered while seeding remote-operation scope. Instead of reducing every seeding problem to an unexplained guard-unavailable result, systematic_workflow_status reports a bounded diagnostic with the failure site and kind, the affected operation or observer reason when available, and whether the probe timed out. This makes intermittent Host Contract failures actionable without exposing raw command output, paths, environment values, or tokens.

The change is diagnostic only: existing failure branches, tolerance rules, timeouts, and control flow remain unchanged. The first-cause record stays outside receipt and marker envelopes, so integrity digests, schemas, and the workflow protocol version are unaffected.

v3.18.9…v3.18.10

Published 2026-09-19 · Updated 2026-09-19 · View on GitHub

This patch hardens protected configuration handling and expands content-integrity validation, alongside routine dependency updates.

Configuration handling now ignores protected project overrides safely, keeping project-level settings from replacing values that are designated as protected (#1002).

The content-integrity checks now validate solution-document frontmatter against the compound schema, so invalid solution metadata is caught by CI instead of passing through unchecked (#1000).

  • deps: Updated github/codeql-action to v4.38.1 (#999).
  • dev: Updated @types/node through v26.6.1 (#1001, #1003).

v3.18.8…v3.18.9

Published 2026-09-18 · Updated 2026-09-18 · View on GitHub

ce:review now carries the route narrowing reason all the way to finalize and the artifact. This closes the last gap left open by #984, where the behavior was pinned by a test rather than fixed.

deriveRoute requires a route_narrowing_reason whenever the model proposes a route narrower than the meet over a finding’s contributing survivors. That rule worked at merge time and was inert everywhere after it. MergedFindingSchema carried the resulting route — autofix_class, owner, requires_verification — but not the reason, so the finalize-phase verifier reconstructed a proposed_route from those carried fields and fabricated route_narrowing_reason: 'carried route verification' to get past the guard. A check that constructs its own passing input cannot fail.

The consequence was downstream and silent: partitionFindings routes strictly on owner, with no severity carve-out. A finding whose owner narrowed to release left the fixer queue for report_only — so a P0 could drop out of actionable work with nothing in the artifact recording why.

The reason now travels on the merge wire and onto the persisted finding, and finalize checks it against the real meet in both directions: a route narrower than the meet must carry a reason, and a route equal to the meet must not — a reason without a narrowing claims a decision that was never made. The second half was missing entirely, not merely unenforced. This adds a new reject reason, merged finding route narrowing reason mismatch.

The pairing is enforced in the pipeline rather than in the artifact schema, because the schema cannot see contributing survivors and therefore cannot compute the meet. That constraint is documented inline where a reader would otherwise expect a superRefine, alongside the existing validated/validation_reason rule it resembles.

Contract impact: review-summary-schema.json gains one optional field. schema_version stays 1 — the field is additive, so existing artifacts still validate. findings-schema.json and review-pipeline-schema.json are byte-identical: reviewers do not author route narrowing, and the reviewer-facing shapes (ParentFindingSchema, SubAgentFindingSchema, SubAgentReturnSchema) are untouched.

Verification: the behavior-changing assertions were confirmed failing against unpatched sources before the fix, so they test the gap rather than the implementation. Coverage includes a narrowed route with no reason, an unnarrowed route carrying one, a narrowed route whose reason reaches the artifact, and the specific P0 → release → report_only path that motivated the change. tests/unit/review-pipeline-finalize.test.ts previously pinned the permissive behavior; it is updated rather than removed and now asserts the reason is carried. 3106 unit tests pass, with typecheck, Biome, content-integrity, and all four drift gates clean. (#998, 9d45da3)

v3.18.7…v3.18.8

Published 2026-09-18 · Updated 2026-09-18 · View on GitHub

This patch closes the diagnostic half of systematic config show — a broken config now explains itself, and reports failure the way a script expects.

config show now tells you why a config failed to load. The prose renderer printed Resolved configuration: unavailable (the configuration failed to load). and stopped — no file, no key, no reason — because a bare catch in printResolvedSection discarded the Error object. The --json renderer never had that gap: buildConfigShowJson bound the error and returned its message, so identical input produced a useful explanation in one rendering and a dead end in the other. Nothing in the code or docs suggested the prose form was meant to be less informative; the two catches were simply written differently. The failure report now carries a Reason: line with the same message --json returns, naming the offending file and key (#995, 555595a).

This deliberately does not relax the rejection itself. A project-level agents.*.model or categories.*.model overlay is still refused by design as a trust boundary; the change only ensures that if the failure is meant to be hard, it at least says why.

The same failure now produces a non-zero exit and lands on stderr. After the diagnostic fix, the two renderings agreed on the reason and disagreed on everything else: config show exited 0 on a broken config while config show --json exited 1, and the earlier test had pinned that 0 rather than flagging it. A script or agent invoking the default form read success from a config that had not loaded. printResolvedSection now reports whether the load succeeded and configShow exits 1 when it did not. The report also moves from stdout to stderr in full, so config show 2>err.log no longer yields an empty error log beside a non-zero exit — splitting a two-line report across streams would leave either half unreadable on its own. The --json envelope stays on stdout on purpose: that document is the machine-readable output, error field included, and consumers still pipe it to jq (#997, 3019c96).

Both changes were verified across rejected, valid, and absent project configs to confirm the healthy paths still exit 0. The regression tests pin the two renderings to each other — matching exit codes and matching reason strings against the same broken config — so a future divergence fails regardless of which side moves. Exit codes are now stated in the model-profiles guide, which previously described what config show prints but not what it returns.

  • deps: Update OpenCode to v1.18.31 (#994, 35daceb).
  • deps: Update dependency typebox to v1.3.31 (#996, 4edb4af).

v3.18.6…v3.18.7

Published 2026-09-17 · Updated 2026-09-17 · View on GitHub

A maintenance-only patch. No plugin, skill, or agent content changed in this release — both commits are Renovate dependency updates that keep the runtime validation layer and the CI workflow surface current.

fix(deps) (#991, 7707bb3) rolls the non-major dependency group forward on two fronts.

zod moved from 4.6.4 to 4.6.5. Zod is the runtime schema layer Systematic’s config parsing depends on, so patch-level movement here touches every config-validation path. Upstream, 4.6.5 keys the .properties() shape off the instance type for z.instanceof() schemas (colinhacks/zod#6600) and settles the z.currencyCode() churn from the prior patch — it was reverted and then restored over a vendored ISO 4217 list refreshed weekly by CI (colinhacks/zod#6595). The rest of the upstream delta is documentation folded into the 4.6 release post.

The shared workflow dependency bfra-me/.github moved from v4.29.0 to v4.30.0. That bump is itself a rollup: bfra-me/renovate-action advanced across 10.39.0 through 10.42.1, fro-bot/agent advanced from 0.112.0 to 0.113.2 inside the reusable workflows, and pnpm moved from 11.26.0 to 11.27.0. The practical effect for this repository is that the Renovate and Fro Bot automation running against it is now on current action revisions.

  • deps: fro-bot/agent updated from v0.113.1 to v0.113.2 (#990, ef78e36). Upstream that patch carries a Node.js v24.21.0 runtime bump, a yaml v2.9.1 fix, and internal vite / lint-staged maintenance — this pins the direct action reference to match the version the bfra-me/.github rollup above already reached.

v3.18.5…v3.18.6

Published 2026-09-16 · Updated 2026-09-16 · View on GitHub

A documentation-focused patch. The substance of this release is a new docs/solutions/ entry capturing a defect class that survived three independent rounds of review, plus routine dependency maintenance.

docs(solutions) adds re-verify-carried-state-at-phase-boundaries-2026-09-15.md, a learning drawn from building the ce:review synthesis pipeline. The same defect appeared five separate times in one place: the seam where a phase hands derived state to a later phase that must re-verify it rather than trust it. Three separate passes of scrutiny — a read-only architectural review, running the pipeline against its own code, and two rounds of PR review — each found instances the others missed, and every blocking finding from the final round landed in a seam the earlier passes had already inspected.

The recurring shapes were a wire projection that dropped derived fields and forced the consumer to re-infer them; a verifier fed the very field it was testing, so a tampered value plus a matching dependent value round-tripped cleanly; joins that checked presence but not completeness, so a deleted request passed as satisfied; a “by construction” argument living inside a verifier whose entire premise is untrusted input; and two derivations over different row sets whose reconciling invariant was documented but never asserted.

The reason this matters beyond ce:review: every bad envelope was schema-valid. Strict Zod contracts and a clean typecheck caught none of them, because shape was never the problem. One case needed no adversarial input at all — any run with an unavailable reviewer emitted an artifact whose counts disagreed with its own ledger. The document states seven checkable rules with before/after excerpts from the shipped implementation, names the concrete consequence class (forged dedup identity, laundered confidence, misattributed ownership, and artifacts that do not reconcile with themselves), and describes the recognizable situations where it applies.

It was written through ce:compound in full mode. Overlap against the nearest prior art — the artifact-contract learning from #793 — scored Moderate, so this landed as a new document that cross-links to it rather than an edit to the existing one.

  • deps: zod updated to v4.6.4 (#989).
  • deps: fro-bot/agent updated to v0.113.0 (#987), then to v0.113.1 (#988).

v3.18.4…v3.18.5

Published 2026-09-15 · Updated 2026-09-15 · View on GitHub

The ce:review synthesis pipeline is now executable code instead of prose instructions the model had to follow by hand. That is the substantive change in this release; the rest is dependency repinning.

ce:review previously asked the model to perform deterministic synthesis manually — confidence gating, candidate grouping, provenance, route narrowing, action queues, counts, sorting, and risk coverage were all prose instructions. That produced non-conforming artifacts on the first try, drifted between harnesses, and left “the same evidence yields the same report” as an aspiration rather than a property. #984 moves synthesis into code, closing #795.

Four pure phases now live in src/lib/review-pipeline.ts behind a strict Zod contract (src/lib/review-pipeline-contract.ts) and ship in the bundled helper skills/ce-review/scripts/validate-review.mjs, which every harness already resolves through SKILL_DIR:

  • screen admits one raw reviewer return, binds it to the dispatched persona, and extracts rejected severities as bounded enum values. Admission depends only on the payload, the expected reviewer, and the harness — the shell environment cannot change it.
  • prepare applies the confidence gate, groups admitted findings into candidate pairs by normalized file, and unions selection surfaces.
  • merge validates the model’s adjudication as a strict partition over the prepared candidates, then derives each merged finding’s severity, agreement-boosted confidence, fingerprint, submitters, and conservatively narrowed route, returning the exact set of findings that need a validator.
  • finalize re-verifies every cross-phase join, re-runs the merge derivation over carried survivors as a verifier, reconciles validator outcomes, derives dispositions, counts, action queues, and replacement risk coverage, routes plan-assessment results, and emits either the schema-parsed review-summary.json artifact or a report-only projection. Both modes pass the same integrity gates.

The model keeps what only it can do: adjudicating candidate groups, judging validator evidence, assessing the plan, and rendering the report. Stages 4–6 of skills/ce-review/SKILL.md now call the phases at their decision boundaries, with invocation blocks and envelope shapes documented in the new references/pipeline-invocation.md, explicit never-bypass rules for helper failure, and an atomic temp-file write for the artifact.

Carried envelopes are treated as trust inputs, not proof. finalize rejects a tampered severity, confidence, file, or route; a duplicated or missing dispatch record; a survivor cited twice; a citation of an unavailable reviewer; a forged validation state; or a screen result that disagrees with its dispatch record. Diagnostics name the failing phase and, on a pipeline rejection, the fixed reason and safe path — never payload content.

Existing artifact consumers are unaffected: review-summary-schema.json and findings-schema.json are byte-identical at schema version 1, and only review-pipeline-schema.json — covering the model-authored envelopes — is new. Verification covered 3,038 unit tests including roughly 330 new ones across the contract and each phase, a packaging test that runs all four phases under real Node from the npm, OCX, and Claude Code layouts, and an integration test that drives a complete Stage 4–6 run plus an equivalent report-only run through a real OpenCode host.

  • deps: fro-bot/agent updated to v0.112.1 (#985).
  • deps: bfra-me/.github action updated to v4.29.0 (#983).

v3.18.3…v3.18.4

Published 2026-09-14 · Updated 2026-09-14 · View on GitHub

A maintenance release. No plugin behavior changes — this release repins dependencies, refreshes the vendored bundle that the ce:review artifact validator runs, and completes a Biome configuration schema migration.

The scheduled Renovate sweep in #982 moved zod from 4.6.1 to 4.6.2. Because skills/ce-review/scripts/validate-review.mjs ships a vendored, pre-bundled copy of its validation dependency so the script can run standalone, that bundle was regenerated in the same commit and now matches the zod build the package itself depends on. The sweep also repinned the bfra-me/.github reusable workflows consumed by renovate.yaml and update-repo-settings.yaml from v4.27.0 to v4.28.0, keeping the automation workflows current with their upstream pinned SHAs.

Biome configuration was migrated to the current schema in #975. The deprecated linter.rules.recommended field was replaced with the equivalent preset: "recommended" form, and the biome.json schema reference advanced from 2.5.1 to 2.5.12 to match the installed toolchain. The existing lint policy is preserved verbatim — noExcessiveCognitiveComplexity and noNonNullAssertion remain warnings. Verification for that change covered lint, typecheck, the unit suite, build, content integrity, registry and generated-artifact drift checks, and the docs build.

Biome itself then advanced to 2.5.13 in #980, landing after the schema migration so the config and the linter stayed in step.

  • deps: fro-bot/agent updated to v0.112.0 (#981).

v3.18.2…v3.18.3

Published 2026-09-13 · Updated 2026-09-13 · View on GitHub

Zod moves from 4.6.0 to 4.6.1, bringing upstream fixes that preserve unique tags with defaulted discriminators and defer recursive object index inference. This keeps Systematic’s schema validation and TypeScript inference aligned with the latest patch behavior without otherwise changing its dependency surface.

v3.18.1…v3.18.2

Published 2026-09-12 · Updated 2026-09-12 · View on GitHub

This maintenance release keeps Systematic aligned with the current OpenCode development surface. The OpenCode plugin and SDK packages move from 1.18.29 to 1.18.30, while the broader non-major refresh updates Zod from 4.5.4 to 4.6.0 and Node.js type definitions from 26.5.0 to 26.5.1.

  • dev: TypeBox updated from 1.3.29 to 1.3.30.

v3.18.0…v3.18.1

Published 2026-09-12 · Updated 2026-09-12 · View on GitHub

ce:review now validates each raw persona return before parsing, screening, or persistence. The new bounded, stdin-only validator rejects empty, oversized, invalid UTF-8, malformed JSON, and schema-invalid payloads without writing them to disk, while keeping diagnostics payload-safe. Review selection is also risk-based: correctness, testing, and project standards form the core team, and maintainability, agent-native, learnings, deployment, and other specialists are selected only when the changed repository surface warrants them. Selection reasons remain visible in coverage, and failures from risk-critical reviewers stay blocking rather than disappearing from the reported team.

The architecture and structure guides now document review-artifact cleanup’s preview/execute safety model, the paired .context ignore prerequisite before persistent review runs, and the content-integrity check for completed plans left marked active. A new solution note captures how to test filesystem safety at the operation boundary, including FIFO substitution, bounded descriptor reads, metadata identity checks, and isolated fault injection.

  • deps: Updated fro-bot/agent through v0.111.0 and typebox to v1.3.29.

v3.17.0…v3.18.0

Published 2026-09-10 · Updated 2026-09-10 · View on GitHub

This release adds an operator-facing cleanup path for ce:review artifacts, turns on noUncheckedIndexedAccess repo-wide, and converts a hand-measured eval-scanner coverage claim into a test that re-runs itself.

Review artifacts can now be cleaned up, and are ignored before they are written. Review runs retain private source excerpts indefinitely, with no supported way to age them out. The new ce:review-cleanup skill (#965) closes that gap with a deliberately conservative shape: a required age cutoff, a read-only preview, and a separate deletion approval bound to the previewed selection and that fixed cutoff. Before removal it rechecks directory identity, ancestry, and subtree metadata, rejects unsafe traversal, and reports partial failures instead of an all-clear. Complementing it, writable review runs now prepare .context/.gitignore with /systematic/ce-review/ before artifacts exist, preserving existing bytes; missing Git or ambiguous verification blocks persistence, and report-only mode remains no-write. Both ship as independent Node helpers alongside their owning skills, with strict argument handling and read-only usage help.

The safety boundaries are stated rather than implied. Age means the latest filesystem modification within a run, not proof that nothing is writing to it — the offline acknowledgment is an operator precondition, not a liveness check, and the preview token detects stale state without authenticating approval. There is no automatic expiry and no new source-redaction mode. Ignore rules do not protect tracked files, force-adds, or copies made elsewhere, and deletion is irreversible with no rollback or backup.

ARCHITECTURE.md and STRUCTURE.md caught up with three shipped changes (#960). Review artifact validation now documents the containment default and the --allow-outside-artifact-root escape hatch. Named model profiles gained a cross-cutting entry covering resolveActiveProfile, resolveProfileSelector, and the trust boundary: profiles sits in PROJECT_PROTECTED_FIELDS alongside workflow_guard, so a project systematic.json may select a profile but a profiles map it defines is ignored with a warning rather than merged. The host-contract gate is recorded too — the host-contract job, scripts/host-contract-guard.ts, and scripts/lib/opencode-pin.ts — including that it is a required predecessor of release and that evidence gathered at one pinned OpenCode version is not evidence at another. Every claim was checked against the code it describes.

A new learning records what counts as evidence for a “nothing changed” claim (#961). Two changes shipped the same defect an hour apart: one asserted no runtime behavior changed while reassigning an array OpenCode owns, and one claimed a project overlay could override profile-supplied routing when the code rejects rather than strips. Both were confident claims about the far side of a boundary, and both survived multi-persona review — eleven personas returned zero findings on the array conversion, because every existing test read the value back off the same object and so passed under either semantics. The rule the doc records: a no-change claim is scoped to a boundary, neither the diff nor a passing suite is evidence for it, and if the contract is real you pin it with a test that fails under the wrong semantics. It is indexed by symptom rather than by lesson, so the tags carry the identifiers actually involved.

Three shipped plans in docs/plans/ are marked completed (#957). Each unit was verified against the current tree rather than against the plan’s own prose, and half the reported drift turned out not to be drift — a program document and two genuinely incomplete plans were correctly left active, with reasons stated. content-integrity.ts now catches one narrow shape of this problem: a plan marked status: active whose units are all ticked fails the gate. Notably, it does not catch the drift this change fixed, since “shipped but nobody ticked a box” is indistinguishable from “not started” using frontmatter and checkboxes alone.

The eval fixture scanner re-proves its own coverage on every run (#958). The scanner’s blind spots had been measured by hand and quoted as a number at a commit — a technique nobody could re-run, so nothing re-checked it when the scanner or the files it reads changed. probeScannerBlindSpots now plants a version literal at every line position of every allowlisted fixture file and asserts the scanner reports it, across all four historical injection shapes, so a regression confined to one shape or one scanner code path cannot hide behind the others passing. Non-detections inside comments or inside an already-open template literal are classified as legitimate per shape, derived from the scanner’s own tokenizer output rather than a second hand-written walk over the source. The probe is itself proven: reconstructing each of the three prior scanner designs makes the sweep fail and name the positions each would have missed, and a deliberately crippled stub scanner produces a real miss. The stated limit is that the sweep re-proves detection only for the shapes and positions present in today’s files.

noUncheckedIndexedAccess is on, and all 132 surfaced sites are fixed (#959). z.record(z.string(), V) infers Record<string, V>, so parsed.categories.anything type-checked clean and threw at runtime — a trap that applied to every indexed read in the repo, not just the config schema. The flag now lives in the base tsconfig.json, inherited by the scripts and tests configs, with all sites fixed in the same commit because typecheck:all is a required gate and a partial fix would land red. One site changed observably and was corrected: an interim output.system = output.system.map(...) in applyBootstrapContent reassigned an array that a sibling hook captures by reference, which would have silently dropped injected bootstrap content; the loop now mutates in place and a test pins array identity across the call. Every other site was checked individually and is type-only, with four regression tests pinning the narrowings that landed on live branches. Consumers are unaffected — dist/lib/config-schema.d.ts is byte-identical with and without the flag.

The parsed config shape is inferred instead of erased (#955). createSystematicConfigSchema declared its return type as z.ZodObject<z.core.$ZodLooseShape>, which threw away the shape the schema actually parses; callers got a loose object, and the config test compensated with a hand-maintained ParsedSystematicConfig mirror plus a cast helper that nothing kept in sync. Removing the annotations lets the shape infer from the builders and deletes the mirror. Inference degrades gracefully here — record-keyed fields infer as Record<string, T> rather than expanding to literal keys, and typecheck:all stays clean at roughly the same speed. Ordinary toEqual assertions now fail to compile when the schema gains an unaccounted required field, though an added .optional() field with no default still drifts silently, and SystematicConfigParsed’s docstring records that scope. Because annotating a Zod schema builder erases its inferred shape, AGENTS.md and .github/copilot-instructions.md now record an explicit exception to the repo’s explicit-return-type convention.

  • deps: update bfra-me/.github action to v4.27.0 (#966)
  • deps: update github/codeql-action action to v4.38.0 (#963)
  • dev: update @types/node to v26.5.0 (#967)
  • dev: update typebox to v1.3.27 and v1.3.28 (#956, #962)

v3.16.5…v3.17.0

Published 2026-09-08 · Updated 2026-09-08 · View on GitHub

Workflow guard replay keeps the original failure reason (#954). When a completion tool call was delivered twice for the same callID, two terminal outcomes lost their specific reason code on the second delivery: a mismatched completion target (invalid-transition) and a host-tool failure (failed-operation) both fell through to a generic guard-unavailable. Both branches now record a terminal completion and replay it with the reason code that produced it. The host-tool-failure record is flagged metadata-only, so a replay corrects the guard metadata without overwriting the host’s own failure title and output — that text is evidence and has to survive untouched.

Two related fidelity gaps closed alongside it. TerminalComplete.target is now optional, so a genuinely-unknown target is omitted from the emitted workflowGuard metadata rather than fabricated as unit. And stale questionAttestation stripping is now gated on the guard instance’s own sourceDigest, so two guard instances sharing an output reference can no longer erase each other’s attestation evidence. All three gaps were safety-neutral — the host failure sentinel survived in every case, and no fail-closed behaviour was weakened — but each degraded the accuracy of the completion evidence record the guard exists to protect.

The host-contract CI guard is now a tested script (#949). The host-contract job’s skip/pass guard lived as a ~135-line inline .mjs heredoc inside .github/workflows/main.yaml. It parsed JUnit XML and the bun test log with regexes and gated release — an untested parser sitting on a required release gate, invisible to biome check ., typecheck:all, and bun test. It now lives in scripts/host-contract-guard.ts as pure functions plus a thin CLI wrapper, with unit tests covering all five failure conditions, XML entity decoding, and the artifact-reading paths.

The move also fixed a gating bug that had survived two rounds of review. The guard step’s if: condition contained no status check function, so GitHub Actions applied its own implicit, job-scoped success() on top — skipping the guard on exactly the runs where its diagnosis matters most, a failing suite. Adding !cancelled() fixes it, and tests/unit/host-contract-workflow.test.ts now mechanically pins the condition’s properties so this class of regression fails a test instead of shipping a third time. A missing or unreadable artifact is now reported as the contract failure it is — routed through the same evaluate() path a truncated one already used — instead of a raw ENOENT crash.

A mis-detected quote can no longer blind the fixture-version scanner (#947). The scanner in tests/unit/opencode-pin.test.ts enforces that every OpenCode-shaped version literal in the allowlisted fixture files stays inside the unpinnable 9999.x sentinel range. Its tokenizer could misread an apostrophe inside a regex literal in an unrecognised position — if (a && /don't/.test(b)) — as an opening quote; the phantom string then searched forward for the next real quote and swallowed everything in between.

Rather than extend the regex-position heuristic for a third time, this applies a structural bound: a ' or " string cannot span a real newline in JS/TS, so the tokenizer abandons an unterminated span the moment it reaches a line break. That caps the damage from any mis-detected quote, whatever the trigger, to the rest of the current line. Backtick template literals are excluded, since they legitimately span newlines. Three regression tests pin each of the three historical hazards, and the plant-at-every-line-position probe reports zero genuine misses across all four scanned files.

How to measure a source scanner’s blind spots (#950). A new docs/solutions/best-practices/ entry records the lesson from that scanner work: a guard that scans source text has to have its blind spots measured, because reading it finds nothing. Three successive designs each read as correct and each had a measured hole — context-anchored matching missed the four literal shapes the scanned file actually used, a blanket match with a comment stripper went blind over 143 of 143 positions after a single // inside a string desynced quote parity, and removing comment awareness entirely missed 166–580 positions to a phantom string opened by an apostrophe in prose. The doc records the probe that found all three, the structural bound that caps any future mis-detection regardless of cause, and the cheap positive result: the same probe cleared the sibling guards in tests/unit/spawn-and-signal-conventions.test.ts at zero misses, so the technique validates as well as condemns.

  • dev: OpenCode updated to v1.18.28 (#944) and v1.18.29 (#952).
  • dev: Playwright updated to v1.63.0 (#953); TypeBox updated to v1.3.26 (#948).

v3.16.4…v3.16.5

Published 2026-09-07 · Updated 2026-09-07 · View on GitHub

One theme dominates this release: the OpenCode host contract stopped being a local ritual and became a required, fail-closed CI gate. A five-unit plan landed end to end (#916, #928, #930, #931, #937), and the very first real-host CI runs immediately caught four bugs sitting in already-merged code — each now pinned by a host-free regression test. In parallel, the typecheck:all backlog opened in #914 was burned all the way down: 343 errors across 30 files, to zero.

systematic_workflow_complete could report success while carrying stale evidence. The tool returns runtime.metadata() first, which may describe a ready-but-not-finalized unit (reasonCode: 'unit-ready', no workflowGuard block). Four branches in finishComplete()/finalizeComplete() returned without ever rewriting that output, so a completion the host marked completed was indistinguishable from a real success. Each branch now writes an explicit terminal result using the existing WorkflowReasonCode vocabulary — invalid-transition for a mismatched finalize target, guard-unavailable when nothing replayable is known, finalization-failed on an unavailable readback, and failed-operation when the host tool itself failed. No new status or reason literal was introduced, and the guard’s state-machine semantics are unchanged; only the evidence written to tool output changed.

Two follow-on defects surfaced during review of the same change and were fixed in it. The completion writers replaced output.metadata wholesale instead of layering onto it, dropping the host’s own failure sentinel on the shared output reference and letting a second guard instance take the success path. And metadata() emitted a bare, unprefixed status key whenever workflow_guard.debug was enabled, which still overwrote the host’s status: 'error' sentinel even after the layering fix — reintroducing the same fail-open through a user-settable option. That debug-only key is now debugEpochStatus, so it cannot collide with a host-owned status field in any mode. Seven bidirectional proofs back the change (#945).

The pinned OpenCode development dependency moved to v1.18.22 (#880). Because the host pin is now derived from package.json rather than hand-copied constants (see Code Refactoring below), a bump like this is a single-field edit that the host-contract job re-proves automatically.

Two solutions docs record what the host-contract work actually taught. host-contract-evidence-is-ci-owned-2026-09-04.md keeps the surviving invariant from the earlier 2026-08-16 doc — evidence gathered at one pinned OpenCode version is not evidence at another — and replaces the mechanism: the pin lives in package.json, the host is bunx opencode-ai@<pin>, and the evidence is the required host-contract job that release depends on. A Renovate OpenCode bump is now complete when that job is green on the PR; nobody re-runs the suite by hand. The superseded doc keeps its body as history with status: superseded frontmatter and a pointer to the replacement (#937).

The companion doc, real-host-ci-catches-what-offline-gates-cannot-2026-09-06.md, catalogues the bug classes only a real host can catch: four defects in merged code that passed unit tests, typecheck:all, lint, content-integrity, review, and offline skip runs, and were caught only by the new required job. It records the measured launcher topology on both macOS and Linux, two diagnostic traps, and the practice of pinning each host-caught bug with a host-free unit test (#938).

The real-host CI job found four bugs on its first runs, and this release fixes all of them.

A 180-second hang with zero output turned out to be stdio: spawnOpencodeChild used Node’s default spawn stdio, leaving stdin an open, unclosed pipe that a real opencode run blocks on waiting for EOF. Switching to stdio: ['ignore', 'pipe', 'pipe'] took the previously-hanging tests from a 180s kill to a ~25s pass. The same PR converted one remaining bare opencode spawn site — missed by the earlier bunx conversion — to bunx opencode-ai@<pin> (#932).

The full integration suite exited 130 (SIGINT) even though every individual test passed. process is a single process-wide emitter shared by every test file in a Bun worker, so one eval-runner test’s process.emit('SIGINT') reached the host fixture’s never-removed SIGINT safety net, which called process.exit(130) unconditionally. The synthetic signal is now isolated to the listener under test (#933).

A test asserting that the fixture’s launcher pid equals the pid the plugin reports from inside the OpenCode process passed on macOS and failed in CI with values exactly +1 apart. bunx execs the binary in place on macOS but forks it as a child on Linux, so the identity never held cross-platform. The test now asserts what it actually needs to prove — one probe load per host generation, in order (#936).

The fixture’s reaper failed open: isProcessGroupAlive() treated every error from process.kill(-pid, 0) as proof the group was gone, collapsing POSIX EPERM (“exists, not yours to signal”) into ESRCH (“gone”). That let the pruner drop a live entry and the SIGKILL sweep skip a still-running group, leaking a live opencode process past exit — a failure mode that previously caused a machine reboot on this project. It now returns false only for ESRCH and fails closed on everything else (#943).

A broader hardening pass on the host fixture’s spawn, stdio, and signal handling landed alongside these: pruneLiveOpencodeProcesses() re-probes and evicts stale pids on every check instead of relying on a one-shot eviction at settle time, multi-byte UTF-8 chunk reassembly is pinned by a test, and buildDetachedChildSpawnOptions is now the single shared spawn-options builder both spawn sites call through, so they cannot diverge on stdio (#941).

Two host-free source-scan guards now pin the bug classes CI caught, so they cannot regress silently: one rejects any spawn call whose first argv element is the literal 'opencode', the other rejects any process.emit of a terminal signal anywhere under tests/ (#939).

The rest of the Tests bucket is the typecheck:all burn-down against #897, which finished in this release. The four highest-error test files accounted for 195 of the 343 baseline errors and went to zero by narrowing discriminated-union results behind explicit helpers, giving fixture builders real return types instead of Record<string, unknown>, and correcting a wrong-module type import (#919). Three real-host integration files adopted a per-file unwrapData() helper rather than reading the SDK’s {data?, error?} response wrapper unguarded (#922). The eval fixture factories and case unions were typed against the real EvalResult, SourceProvenance, and CaseId exports (#923). Six unit files got complete SDK-shaped Model fixtures, ToolResult union narrowing, and type guards in place of runtime-only assertions (#924). The final batch took the count from 55 to zero, with the only source-side changes being additive: exporting CapabilityCliRoots, and adding a narrow read helper for the skill permission map that config-handler.ts genuinely writes but the imported v1 Config type omits (#926). No assertion behaviour changed anywhere in the burn-down.

Separately, the last two mkdtempSync cleanup gaps in the unit suite were closed — agent-resolver and pi-delegate-session were leaving 19 orphaned temp directories per run (#918).

The headline change is a required host-contract job that runs tests/integration against a real, bunx-launched OpenCode host and gates release. It builds dist/ before testing (load-bearing: the dist-local assertion is computed at module scope, so a late build would silently skip it), sets SYSTEMATIC_REQUIRE_OPENCODE=1 in workflow-owned env that a fork PR cannot alter, and always runs to completion so it is a valid required check. Path gating lives at step level and fails closed on any unexpected filter output. A JUnit-parsing guard then refuses to pass unless every one of the eleven integration files produced at least one test suite, the skipped set matches the known-exempt set exactly, and the pass count clears a floor — so “green with everything skipped” is not reachable (#931).

The wider type check landed as a staged rollout: typecheck:scripts covering src/, scripts/, and docs/scripts/ as a required step with no backlog, and typecheck:all covering tests/ too as advisory (continue-on-error: true) so the then-343-error backlog could surface without gating merges (#914).

The Node ESM load probe now covers dist/cli.js. package.json declares bin.systematic -> ./dist/cli.js, but the probe only imported dist/index.js and dist/pi.js — so a bare specifier that resolves under Bun but not plain Node would have shipped an unloadable systematic bin with no CI signal. This is not hypothetical: another project shipped exactly that failure from a bare jsonc-parser import resolving to a UMD main, and Systematic imports jsonc-parser bare in src/lib/setup.ts and src/lib/config.ts. The probe asserts loadability only, since dist/cli.js legitimately exports named symbols (#940).

The pinned OpenCode host version now has one readable source. scripts/lib/opencode-pin.ts reads the @opencode-ai/sdk devDependency from package.json, resolved relative to the module rather than cwd, and throws a clear error naming the field if it is missing or not an exact version. The two hand-maintained constants in scripts/run-evals.ts and the integration fixture became re-exports of it, retiring a four-way lockstep (#916).

Every host the suite spawns now launches through bunx opencode-ai@<pin> instead of npx, with no PATH lookup. A new probeOpencodeAvailability classifies a host as available, mismatch (exit 0 at the wrong version), or unavailable, and requireOpencodeAvailable turns a bad classification into a module-scope throw when SYSTEMATIC_REQUIRE_OPENCODE=1. Critically, the fixture module itself probes nothing at module scope, so tests/unit importers never spawn bunx. The shared bun install cache directory is resolved with lstat on every call — never stat, which would follow a planted symlink — and is refused outright if it is a symlink, not a directory, or not owned by the current uid (#928).

The host model test’s last network dependency is gone. runOpencode now starts a local OpenAI-compatible scripted model server per invocation and merges its provider config into the fixture’s isolated config, dispatching on request-body shape rather than call order — OpenCode forks a background title-generation call concurrently with the main chat loop, so ordering assumptions do not hold. All seven call sites were left untouched because the scripted-provider logic lives entirely inside runOpencode. The same change deleted the suite’s only unfalsifiable test, which asserted that a cell status was one of two values that covered every possible outcome (#930).

  • deps: update fro-bot/agent to v0.109.1, v0.109.2, v0.109.3, v0.109.4 (#917, #920, #921, #929)
  • deps: update bfra-me/.github action to v4.26.0 (#934)
  • dev: update dependency @biomejs/biome to v2.5.12 (#925)

v3.16.3…v3.16.4

Published 2026-09-06 · Updated 2026-09-06 · View on GitHub

A maintenance release: the review-artifact validator can now check artifacts that live outside a live run directory, the Fro Bot autoheal workflow actually lands its file changes instead of discarding them, and the plan corpus was refreshed.

validate-review-artifact gains a --allow-outside-artifact-root flag, wired into both the standalone CLI (src/cli.ts) and the bundled Claude Code validator entry (src/claude-code-validator.ts). Previously the resolved path had to stay inside .context/systematic/ce-review, and that directory had to exist — which meant an artifact fetched from CI, attached to an issue, or checked in as a fixture could not be validated without first being copied into a live run directory. The flag drops both requirements.

Every other guarantee stays enforced regardless of the flag: lexical .. traversal rejection, symlink rejection on every path component, realpath canonicalization before the file check, a regular-file check on the resolved target, and the no-echo guarantee that error output never contains the supplied path or file contents. Argument parsing, the usage string, and the flag constant were hoisted into src/lib/review-artifact-path.ts — the module both entries already shared for path resolution — so the two command surfaces are the same code rather than hand-maintained copies. The flag is idempotent, and a successful external-mode validation prints a distinct message so a transcript cannot mistake it for the current run’s evidence.

The synthesis artifact contract doc records the flag as an external-validation mode with an explicit warning: the ce:review parent must never pass it when validating its own run’s review-summary.json, since that would silently accept a mismatched or misplaced artifact as that run’s evidence (#915, 690a7f1).

The Fro Bot workflow now requests branch-pr delivery for autoheal runs, so the daily autoheal cron and prompt-less autoheal dispatches land their file changes on a branch instead of discarding them. The gate mirrors the PROMPT ladder directly above it, and a test pins that the two expressions agree. Because inputs.mode defaults to autoheal, the inputs.prompt == '' guard is what keeps prompt-only dispatches — such as the release-notes narrative automation in scripts/dispatch-release-notes.sh — comment-only. PR-review, comment, workflow_call, and review-mode runs resolve to the empty string and keep their current behavior.

The autoheal prompt’s code-quality list and quality-gates table now cover all four drift gates: review-schema:drift and agent-browser:drift join the existing registry:drift and schema:drift, with new assertions in tests/unit/fro-bot-workflow.test.ts. Delivery still depends on FRO_BOT_PAT scopes — an insufficient token fails closed to the previous discard behavior, so the first scheduled run’s resolved-output-mode is worth checking (#912, 5f38bb9).

A new plan covers a CI gate that resolves every shipped model identifier — OMO profile routing, config-schema.ts examples, hand-written docs, and skill-reference examples — against a committed snapshot of the models.dev registry, plus a refresh script with a drift check and a weekly workflow that opens a PR when the registry changes. A retired identifier then fails that PR’s gate by name; nothing rewrites routing choices. The gate is planned to live inside content-integrity as a hard, offline pass/fail so main.yaml gains no new step, and schema examples are read from the same Zod producer that emits the published JSON Schema rather than by parsing TypeScript (#908, a0ccd3b).

Three shipped plans were marked completed — the review-artifact executable contract fix, the review-artifact contract refactor, and the OpenCode plugin load-failure fix — taking the active plan census from 10 down to 7 (#911, 58ece67).

  • deps: update fro-bot/agent to v0.109.0 (#913)

v3.16.2…v3.16.3

Published 2026-09-05 · Updated 2026-09-05 · View on GitHub

Example model identifiers across the user-facing surfaces had drifted several generations behind the current models.dev registry, so anyone copying a snippet out of the docs or the schema was starting from stale ids. This refreshes them everywhere they are authored: the src/lib/config-schema.ts meta examples and descriptions — which regenerate the published JSON Schema under docs/public/schemas/v3 and the generated reference region — plus the hand-written examples in configuration.mdx, the Pi subagents guide, and one skill reference.

The OMO routing profile moved with them. Its category models now point at gemini-3.1-pro-preview instead of gemini-3-pro-preview, claude-opus-5 instead of claude-opus-4-6, and claude-sonnet-5 instead of claude-sonnet-4-5, while gpt-5.3-codex and variant: max were already current and stay as they are. Two schema-test fixtures that had pinned the old example ids were updated to match.

Several surfaces were deliberately left alone, because rewriting them would cost expected-byte churn for no behavioural gain: the deleted-defaults table in model-defaults-migration.mdx stands as a historical record, and the recorded with/without eval, the plans, the solutions docs, and the config corpus fixtures all use arbitrary ids rather than assertions against the schema examples. claude-haiku-4-5 also stays, since no Haiku 5 exists to move to. (#907)

The model profiles and per-harness routing feature shipped in #903 with its rules documented in the configuration reference, but no task-oriented page to work from. The new guides/model-profiles.mdx is that task layer: define profiles once, select one per repository, route a single agent differently on OpenCode and Pi, migrate off pi_subagents.thinking, and read the resolved result out of config show --json. It sits in the sidebar next to the model-defaults migration guide, and the reference’s Profiles section now links across to it.

The config show --json sample in the guide was captured from the built CLI under an isolated HOME and then generalised for paths, rather than being written by hand, so it reflects real output. Its examples use current model ids and the high variant, matching the refresh above. (#906)

v3.16.1…v3.16.2

Published 2026-09-05 · Updated 2026-09-05 · View on GitHub

A small patch release: one runtime dependency bump and one expansion of the solutions corpus around deletion and preservation gates.

web-tree-sitter moves from 0.26.12 to 0.27.0. This is a production dependency rather than a dev tool — it is the WASM parser runtime behind the receipt classifier in src/lib/receipt-classifier.ts, and it stays version-pinned and Renovate-grouped with tree-sitter-bash because the runtime and the grammar have to move together. (#877)

The deletion-gate learning doc (deletion-gates-must-observe-every-field-the-deleted-code-wrote-2026-08-16.md) gains the sign-flipped case found while landing #903: a preservation gate — a corpus meant to prove that a rewrite still matches the code it replaced — is only as complete as the deleted code’s branches, not just the fields that code wrote.

The concrete failure is the useful part. The variant-clearing heuristic that the doc already named as a live regression target was replaced by the routing resolver in #903. Its twelve-entry compatibility corpus had been seeded from existing fixtures, and none of those fixtures set a category variant and then overrode model at the agent level. The rewrite consequently dropped two of the heuristic’s three branches and still passed byte-for-byte. Two rows built directly from the heuristic’s own conditions — corpus entries 013 and 014, with expected output captured from pre-change main — were what actually caught it.

The update adds a Guidance subsection covering the three-branch heuristic, why fixture-seeded corpora systematically miss deleted branches, and a three-step procedure for enumerating those branches; an Examples table mapping input to pre-change output to the rewrite’s output as it behaved before those rows existed; and refreshed frontmatter (last_updated, two new tags, two new applies_when entries, all within schema limits). It landed as an update to the existing doc rather than a new one — overlap scored High on all five dimensions, sharing the same deleted code, the same root cause (a gate derived from something other than the deleted code itself), the same enumerate-from-git show remedy, and the same files, with the prevention rule generalised from fields to branches. (#905)

v3.16.0…v3.16.1

Published 2026-09-05 · Updated 2026-09-05 · View on GitHub

Named model profiles with per-harness routing blocks (#903) — User config can now define named profiles, and any config source, including a repository’s project config, can select one by name. Agent and category overlays gain optional per-harness blocks — opencode: { model, variant } and pi: { model, thinking } — so a single systematic.jsonc routes correctly on both OpenCode and Pi. One routing resolver feeds the OpenCode config hook, the Pi delegate tool, Pi persona export, and systematic config show.

~/.config/opencode/systematic.jsonc
{
"profile": "personal",
"profiles": {
"personal": {
"categories": {
"review": {
"opencode": {"model": "anthropic/claude-opus-4", "variant": "high"},
"pi": {"model": "github-copilot/claude-opus-4", "thinking": "high"}
}
}
},
"work": {"categories": {"review": {"model": "openai/gpt-5.2-codex"}}}
}
}

Resolution is layered and predictable. The profile selector follows source strength (OPENCODE_CONFIG_DIR > project > user) and is tri-state, so null explicitly selects the base config. Overlays merge user base, then the selected profile, then the project’s permitted fields, then custom; per target per harness the precedence is agent block, agent flat, category block, category flat. An unknown profile name warns once and falls back to the user’s own default rather than base — a repository can never push a contributor off the routing they chose.

The trust boundary holds: project config may select a profile but never define one. profiles coming from project config is stripped with a warning, and model, variant, and thinking inside harness blocks are rejected from project config exactly like the flat fields already were.

One behaviour change is worth noting. A flat agents.<name>.model now routes Pi delegates too; previously it was OpenCode-only and Pi always inherited the parent model. The first dispatch of a config-routed agent says so in the tool result, naming the model, its source, and the active profile. pi_subagents.<name>.thinking is superseded by agents.<name>.pi.thinking, with the old location still working when the new one is absent and emitting one deprecation warning per written field. Every pre-existing configuration produces byte-identical OpenCode agent config, asserted byte-for-byte against a fourteen-configuration corpus.

Alongside the resolver, systematic config show now reports the active profile, its source, any fallback, and per-agent routing per harness, with --json emitting the same information as a single object. Claude Code routing, fallback_models chains, and shipping the OMO registry routing as a named profile remain out of scope.

The OpenCode host-contract suite now has a plan for becoming CI-owned (#898). Today the integration tests that spawn OpenCode assert real host mechanics — plugin loading, config-hook merge, tool registration, system-prompt transforms, question API shapes, receipt persistence across restart — but none of it runs in CI, and the only automated effect of the version pin is a unit test that goes red on every Renovate OpenCode bump until someone re-runs a 15–17 minute suite locally. The plan makes package.json’s @opencode-ai/sdk the single pin read at runtime, launches every host through bunx opencode-ai@<pin>, and adds a host-contract CI job that is a required predecessor of release with a post-run guard so a green job cannot simply be a run of skipped suites.

ARCHITECTURE.md and STRUCTURE.md were also synced to the bundled validator work (#894): the Claude Code plugin build section now documents that bin/ entries are written with executable mode and that the CI pre-publish guard asserts the bundled validator is executable rather than merely present, and the brittle unit-test file counts were refreshed.

The Claude Code integration suite now builds the real validator bundle (#895). That suite had been failing on main since the bundled validator landed: generatePluginFiles gained a required validator Buffer argument and the integration suite still called it with one argument, throwing at module load before any test ran. buildValidatorBundle is now exported and built once per module load, both call sites pass it, and a new assertion checks that the generated bin/systematic-validate-review-artifact is exactly one shebang line followed by the bundle bytes. A second latent failure — agent stem discovery picking up agents/review/README.md, which the build already excludes — was hidden behind the original error and is fixed too.

Integration runs also stop leaking OpenCode servers (#896). Both host spawn sites launched through a launcher chain and stopped only the direct child, so the server outlived every failed, timed-out, or aborted run until the machine had to be rebooted. Hosts now spawn detached in their own process group and are reaped with SIGTERM, a five-second wait, then SIGKILL of the group; startup-timeout cleanup is awaited before the failure surfaces; and a suite-level registry of live hosts is drained in afterAll so a test that aborts before its own finally still leaves nothing behind. Availability probing switched from which to running opencode --version under a throwaway HOME/XDG root, so a shim that only resolves through the redirected HOME makes the suite skip instead of spawning servers that cannot start.

  • ci: bfra-me/.github bumped to v4.25.1 (#899), which takes bfra-me/renovate-action 10.34.1 and restores tar in the Renovate runtime. Renovate on 10.34.0 exits before servicing any dependencies, so this pin could not self-update.
  • deps: fro-bot/agent updated to v0.107.2, v0.107.3, and v0.108.1 (#901, #902, #904).
  • dev: all non-major dependencies updated (#900).

v3.15.1…v3.16.0

Published 2026-09-04 · Updated 2026-09-04 · View on GitHub

A maintenance release whose one substantive change closes a drift gap in the dependency-update pipeline: artifacts that are generated from a dependency now regenerate inside the Renovate branch that bumps it, so a schema-affecting upgrade lands complete rather than red.

Zod moves from 4.4.3 to 4.5.4 (#891, 4e99f0e). The upgrade changes the JSON Schema that Zod emits for ISO date-time fields: the date-time pattern in skills/ce-review/references/review-summary-schema.json now requires an explicit seconds component instead of treating it as optional. Because that file is checked in and generated from Zod’s toJSONSchema output, the regenerated schema travels in the same commit as the bump — the first Renovate PR to exercise the post-upgrade wiring described below. The same PR also carries typebox to 1.3.24.

If you validate ce:review summary payloads against the published schema, completed_at values must now include seconds (2026-09-04T17:52:51Z), not just hours and minutes.

Renovate regenerates every dependency-derived artifact, not just one (#893, aff01fe). The postupgrade script that Renovate runs in-branch previously covered only bun run build and the agent-browser stub regeneration. It now also runs schema:generate, review-schema:generate, and scripts/generate-registry.ts.

The gap stayed invisible until a bump hit it: an update that shifted the config schema, the review-summary schema, or registry content would open a PR that failed its own drift gates, and a human had to regenerate the file by hand before the update could merge. Extending postUpgradeTasks moves that work into the branch that caused it. The Zod bump above is the immediate proof — its regenerated schema arrived inside the update PR instead of as a follow-up fix.

A stated merge order is not an enforced one (#874, dd32db0). A new learning in docs/solutions/workflow-issues/ records a pull request that stated the precondition it then failed to satisfy: its body said to merge a dependency first, explained precisely why, and was based on a commit that predated it — leaving it mergeable in exactly the order it warned against. The warning was accurate and completely inert. The reviewer caught it only by building the artifact at that branch’s head and finding that the command the prose told readers to run was not executable.

The doc gives equal weight to the alternative, because stacking had failed the same day: a pull request opened against another open pull request’s branch lost its base when that branch merged and was deleted, and creation failed outright. Being burned by that is what produced the retreat to prose, which felt safer and was strictly weaker. So the guidance is conditional rather than a slogan — stack when the dependency is not about to merge and let the platform refuse the wrong order; hold the dependent branch unopened when the dependency is approved and could land at any moment; write the dependency down as well, but never only that. Recovery from a vanished base is documented too, since knowing it is cheap makes the stacking risk feel correctly sized.

Both failures share a cause: the ordering lived somewhere that could not enforce it. Of the two, the description is worse — a vanished base fails loudly and immediately, while a description fails by saying nothing at all.

  • deps: fro-bot/agent advanced through v0.105.1, v0.106.0, v0.106.1, v0.106.2, v0.107.0, and v0.107.1 (#882, #884, #886, #887, #889, #892).
  • deps: bfra-me/.github to v4.22.0 (#878), github/codeql-action to v4.37.9 (#876), plus a non-major roll-up (#875).
  • dev: typebox to v1.3.18, v1.3.19, and v1.3.20 (#879, #883, #890); @types/node to v26.3.0 and v26.4.0 (#881, #885); plus a non-major roll-up (#888).

v3.15.0…v3.15.1

Published 2026-08-25 · Updated 2026-08-25 · View on GitHub

This release closes the loop on the Claude Code review-artifact validator: it now ships as a real, executable command inside the plugin bundle instead of prose describing one that couldn’t run, and the contract that names it has been corrected to describe how the parent actually reaches it.

The Claude Code bundle had shipped prose naming a validate-review-artifact command with nothing able to run it, so validation there recorded an absence rather than a result (#871). It now carries a real executable — bin/systematic-validate-review-artifact, built in memory at bundle time and reachable as a bare command. Containment helpers moved out of the CLI into their own module: the CLI’s import graph reaches the JSONC config loader, and a bundle that pulls that in builds cleanly but dies at runtime looking for a module its own wrapper requires by name. Exporting from the CLI would have reintroduced exactly that defect. The entry imports only the schema and the extracted helpers, keeping it at 0.28 MB with nothing resolved at runtime, and reproduces the subcommand’s behavior exactly — including the projection that reports only field paths and error codes so artifact contents never reach the output. A companion refactor consolidated three functions and a type that had been duplicated byte-for-byte between the CLI and the bundled validator, closing the risk that one copy could quietly regain a legacy-artifact classification bug already caught once in review. Verified by running the built artifact from outside the repository against valid, invalid, legacy, malformed, and missing inputs, and confirming a planted marker in every string field of an invalid artifact never leaked into the output.

The bundle writer had been creating every file with a default mode, so the validator shipped without an executable bit and could only run via an interpreter named in front of it — defeating the point of living in a bin directory (#872). Entries under bin are now written executable; nothing else changes mode, since restoring source modes across the whole bundle would be a broader change with no demand behind it. The pre-publish guard also gained this check, now asserting the entry is executable rather than merely present — presence alone wouldn’t catch a file that exists, passes every other check, and still can’t run. Verified by copying the built entry outside the repository with its mode preserved and running it directly with no interpreter: valid, invalid, legacy, malformed, and missing inputs all returned their documented codes, and removing then restoring the bit confirmed the guard catches both directions.

skills/ce-review/references/synthesis-artifact-contract.md told the parent to look for one command on PATH and warned that a harness installing only bundled markdown wouldn’t have it — true when written, false now that the Claude Code bundle ships its own validator beside the prose naming it (#873). The revised passage states the resolution order explicitly: the bundled command first, then the packaged subcommand. It also directs callers to run the command rather than test for its presence, since a name on PATH can be a shim that fails on every invocation — a documented failure elsewhere in this repository — so resolving a name proves nothing that running it doesn’t prove better. Absent and present-but-broken stay distinct: both record the run as unavailable, but neither is ever a failed validation, since that value means an artifact was read and did not conform. Two learnings that had asserted the bundle carries no executable were corrected; the recommendations they made survive untouched. A companion change marked the bundled-validator plan complete, since all five units had shipped across three pull requests but the plan still read as though none had.

v3.14.5…v3.15.0

Published 2026-08-25 · Updated 2026-08-25 · View on GitHub

A small documentation-heavy release: one scoring fix in the compound workflow’s related-docs step, plus four docs that trace a costly false assumption from discovery to correction.

skills: derive the overlap score from the dimension count (#870)

The compound workflow’s related-docs step scores how similar a proposed learning is to an existing one across five named dimensions, and that score decides whether a session writes a new document or updates an existing one. The scoring logic got this decision wrong four times in one session, in two distinct ways: the score was judged as a holistic read of “how related do these feel” rather than a literal count of matched dimensions, letting a report score two documents as near-duplicates while recommending a new document be written in the same breath; and the document search couldn’t find work clustered under a shared module, because it took its search term from keywords in the problem description rather than from the actual curated module identifiers in use. Both are fixed: the dimension count now reads directly into the score, with the count stated in the returned assessment — when the two disagree, the count wins — and the module search now enumerates the real module values in use and picks the closest match. A companion fix also separates the score-follows-count and recommendation-follows-score checks, which a prior read had collapsed into a single rule, obscuring which one had actually failed.

Four documentation changes landed, spanning solution captures and plan corrections that all trace back to one costly false premise.

Two solution docs record the lesson from a session where a plan was designed around an assumption that was never tested. The Claude Code plugin bundle was assumed unable to carry an executable, so an MCP server, a runtime version floor bump, a launch pin, and a new dependency were designed, reviewed by six personas, and merged as a plan — all before a single local install proved the premise false. A marketplace install actually copies the entire plugin directory, including files the manifest never declares, with the executable bit intact and bin/ already on the Bash tool’s PATH; no transport is needed to reach a bundled executable (#869). That doc captures the general lesson — a working capability that has never had its cause isolated hasn’t proven anything; remove the suspected cause and re-run to confirm — and links it to an existing five-week-old rule about probing unproven runtime channels before designing around them. A second doc records the specific anchor convention now required in every fenced script block: skills that invoked helper scripts with bare relative paths resolved against the consumer’s working directory rather than the skill’s install directory, breaking on every harness. The fix is three rules: every block (not just the file) must (re)set the anchor, the assignment must use a form that terminates correctly even when a host flattens a fenced block to one line, and the anchor stays model-filled rather than sourced from a host variable, since a substitution offered by one harness silently expands to nothing on the others (#866).

The two plan documents in this release close out that same story. The MCP server plan is marked superseded, since its central assumption — that a Claude Code bundle can’t carry an executable — was never measured and turned out to be false; the real constraint is entry-point scope, since the full CLI can’t be bundled (a jsonc-parser UMD branch requires runtime resolution the bundler can’t do statically), but a narrower entry importing only the review-artifact schema builds to a self-contained file. The plan stays in place behind a status banner rather than being deleted, pointing at the measurements that replaced it (#867). In its place, a new plan describes building a review-artifact validator that ships as an in-bundle executable, with every claim it depends on — the install copies undeclared directories, the executable bit survives, the entry is reachable as a bare shell command, confirmed via negative control — measured against a real install rather than assumed from documentation (#868). A follow-up correction to that plan notes that the claimed containment helper imports don’t actually exist yet as exports; extracting resolveReviewArtifactPath, hasParentDirectoryTraversal, and pathContainsSymlink from src/cli.ts is a prerequisite the file list should call out rather than assume.

v3.14.4…v3.14.5

Published 2026-08-24 · Updated 2026-08-24 · View on GitHub

Five bundled skills invoked helper scripts with bare relative paths — things like bash references/resolve-base.sh — which a shell resolves against the working directory (the user’s project) rather than the directory the skill was actually installed into. These invocations could never work, in any repository, including this one. Each call now resolves through a SKILL_DIR variable set from the directory the harness reports when the skill loads, with every fenced block setting the variable itself since blocks are copied and run independently. A follow-up fix closed a related gap where some hosts flatten a fenced block into a single line: an unterminated SKILL_DIR="..." assignment then collapses into the env-var-prefix form, causing the shell to expand the variable from the outer scope before the assignment takes effect and reproducing the same broken path by a different route. All twenty anchors now terminate correctly, and a new test covers the four properties these invocations depend on (#862).

A persona that omits the tools frontmatter field is not equally restricted across harnesses: on Pi it resolves to a read-only set (read, grep, find, ls), but on OpenCode the same omission means no restriction at all, because the comma-separated string form isn’t the map shape OpenCode expects and is silently ignored. Two personas were caught by this divergence with their capabilities backwards relative to their jobs — the PR comment resolver (which is supposed to implement fixes) and the bug reproduction validator (whose entire purpose is running reproductions) both effectively had no working tools declared. Both personas now explicitly declare the tools their instructions already assume. Granting shell access to the validator also required a new untrusted-input rule, since its input is a bug report — text that routinely arrives pasted from an issue tracker or a stranger’s terminal — and instructions embedded in that text must never be treated as instructions to the agent (#861).

A proposal to add an MCP server to the Claude Code bundle, premised on the bundle having no way to execute anything, was disproven by a local install: the install copies the whole plugin tree rather than only the manifest-declared components, preserves the executable bit, and bin/ reaches the Bash tool’s PATH. The real constraint turned out to be packaging, not execution — shipping the existing CLI failed three separate ways (a sibling-chunk import, externalized runtime dependencies with no node_modules to resolve them, and a UMD module with an AMD branch that no bundler can follow). An entry point that imports only the single module the surface needs avoids all three failure modes. The learning captured here: an unshippable dependency may have arrived through entry-point scope rather than through the feature being shipped, and is worth checking before being written off as fatal (#865).

Adding a module under src/lib/ has always carried two registration obligations, but only the ARCHITECTURE.md codemap was documented — the src/lib/AGENTS.md module table is equally required and equally gate-enforced (checkCodemapCompleteness and checkLibModuleTableCompleteness in scripts/content-integrity.ts). The guidance now names both obligations and the verification command, and points the intentional-omission escape hatch at whichever document the exclusion actually belongs to, rather than assuming the codemap (#863).

  • deps: update dependency @biomejs/biome to v2.5.10 (#864)

v3.14.3…v3.14.4

Published 2026-08-24 · Updated 2026-08-24 · View on GitHub

ce-plan’s plan template records an origin field pointing at the brainstorm requirements document a plan was built from. Some repositories deliberately don’t track that directory, treating requirements as local planning input the plan itself supersedes — which meant every plan generated from such a repo carried a link that resolved to nothing once cloned elsewhere. The field itself is correct to keep: it preserves real provenance for whoever wrote the plan, and dropping it in favor of a second, equally-authoritative document just creates staleness the moment the plan lands. What was missing was a way for a reader to distinguish context they’re missing from context that was never shared in the first place. The Sources entry now states explicitly when the origin path is untracked, and the field contract documents why that’s a legitimate state rather than a broken link. The deepening pass previously assumed the origin file would always be readable; it now falls back to continuing from the plan alone and records that the fidelity check couldn’t run, instead of reporting a missing file (#860).

A new solutions note captures a diagnostic lesson from an incident where three dependency upgrades failed simultaneously and two were initially misdiagnosed from version numbers alone. The tree-sitter runtime failure looked like a grammar/ABI mismatch — the grammar trails the runtime by a minor version, peers pin the older range, and both were locked to the same line — but it was actually a renamed WASM asset; loading the pinned grammar under the new runtime confirmed the ABI was never involved. What obscured the real cause is that the command classifier fails closed: every shell classification came back unavailable, so forty-four assertions reported a classification result rather than surfacing a missing file, meaning the component was accurately describing its own state while saying nothing about the underlying cause. The third failure, a YAML dependency bump, looked like an ESM-only migration but the package still ships both formats — only the default export was removed — and because the importing module is the most depended-on file in the tree, the breakage fanned out across packaging, module resolution, and codegen in a way that reflected centrality rather than severity (#858).

v3.14.2…v3.14.3

Published 2026-08-24 · Updated 2026-08-24 · View on GitHub

This release lands two dependency-maintenance changes that both required real verification work rather than a rubber-stamped version bump.

OpenCode was updated to v1.18.21 (#856). Renovate had proposed v1.18.19, but moving the OpenCode pin invalidates the evidence gathered at the old version and costs a seventeen-minute suite run against the real host — landing one patch behind current would mean paying that cost twice to catch up, so this bump goes straight to the latest published version instead. Four places have to agree or a guard fails: both OpenCode devDependencies, the expected version in the eval runner, and the exact version in the receipt workflow fixture. The version-dependent suite was re-run at 1.18.21 rather than assumed — fifty-one tests pass across the eval runner, artifact, and fixture files.

The tree-sitter runtime and grammar dependencies were grouped into a single change (#857). web-tree-sitter is the WASM runtime and tree-sitter-bash is the grammar it loads; a grammar is compiled against an ABI version and the runtime accepts a range, so moving one without the other can land the pair outside that range. Both are pinned exactly rather than with a caret for that reason, but nothing had previously stopped them from being proposed separately. The risk became concrete when the 0.26 bump renamed the runtime’s exported WASM file, breaking every call site that resolved the old name — the command classifier fails closed, so forty-four tests failed without a single parse having been attempted, and the fix belonged in the same change as the bump. Grouping these dependencies means that class of change now arrives as one reviewable PR instead of a half that cannot pass on its own.

v3.14.1…v3.14.2

Published 2026-08-24 · Updated 2026-08-24 · View on GitHub

Updated the web-tree-sitter dependency to v0.26.12, which surfaced a real regression rather than being a routine bump. The new runtime renamed the WASM asset it exports, from tree-sitter.wasm to web-tree-sitter.wasm, and three places in the codebase still asked for the old filename — so grammar resolution failed before the parser was ever initialized. Because the command classifier fails closed, every shell operation it needed to classify came back unavailable and minted no evidence, and forty-four tests failed without a single parse having been attempted. The grammar itself was never the problem: tree-sitter-bash 0.25.1 declares ABI 15, and the 0.26.12 runtime accepts ABI 13 through 15, so the pinned grammar continues to parse real commands correctly once the asset reference points at the renamed file. (#727)

Drafted a plan for an MCP server in the Claude Code bundle. Systematic reaches Claude Code as markdown only, so bundled prose that names the command line tool can’t be satisfied there — Anthropic documents two ways a plugin can reach executable capability, and the current bundle uses neither, making the gap a build choice rather than a limit of the harness. The plan adds a stdio server declared in the bundle and launched on enable, exposing review artifact validation as a callable tool, sequenced across six units so the server exists before anything references it. Two findings reshaped the plan along the way: the validation path anchors its containment root to the process working directory, and a server started by the harness doesn’t have the project as its working directory, so every validation would have failed silently without adjustment; and the published package version at rest is a placeholder, so the launch reference has to come from the release job rather than the manifest. A companion claim about symlinked ancestors did not survive checking and is recorded with the scope it was actually measured in. (#855)

v3.14.0…v3.14.1

Published 2026-08-23 · Updated 2026-08-23 · View on GitHub

Small, focused release: the review artifact contract can now say exactly why a validation didn’t run, and a solutions doc that quoted the old, unconditional version of that instruction has been corrected.

ce-review: Unrun validations in the review artifact now record exactly where and why. Previously the contract told the parent to note that a validation didn’t run, without saying where that note should live — neighboring rules in the same file name their fields, so this one read as an instruction with nowhere to land (#853).

The run artifact now carries a validation object with an explicit status: passed, failed, unavailable, or not_attempted. A reason is required for the three non-passing states and rejected for passed, since a check that succeeded has nothing to explain and the field shouldn’t invite narration. The object deliberately does not reuse the existing coverage object — a validator_failures list already lives there and refers to the per-finding validation pass, a different mechanism that happens to share the word “validation.” Keeping them apart is the point of the change.

The status is self-reported: an agent can claim passed without having run anything, so this is not evidence that validation happened. What it buys is that four outcomes which previously produced one identical silence can now be told apart.

A follow-up commit tightened the documentation itself: the paragraph wiring the unavailable status to its trigger left the not_attempted case to inference, using the word “skipped” twice without ever pairing it with the status name. Both trigger conditions now name their status explicitly where the distinction is drawn.

A learning captured in docs/solutions/ describing the review artifact contract had gone stale the day after it was written. The note quoted the unconditional form of the validator instruction as the shipped design — but that instruction was corrected a day later, after it reached a harness with no executable to run (#852).

Two passages were wrong. The worked example told a reader to run the validator command outright, and the honest-limitation passage repeated the claim that an agent producing no evidence is an acceptable outcome, without the distinction the contract now draws between an agent choosing not to run a check and being unable to. The packaging section also gains the half the incident exposed: getting the validator into a reachable location is not the same as every reader of the contract being able to invoke it — bundled prose is copied into all three harness packages, while the bin entry only reaches installs of the npm package. An instruction naming a command has a wider reach than the command itself.

v3.13.7…v3.14.0

Published 2026-08-23 · Updated 2026-08-23 · View on GitHub

The ce-review synthesis contract told the parent agent to run a validator after writing the run artifact, with no condition attached to whether that validator existed. That instruction shipped verbatim into the Claude Code bundle, which is built without npm coupling and carries no executable at all — so an operator there was told to run something that cannot exist. The failure mode was silent in the worst available way: the same section said an agent that never runs the command produces no evidence either way, making an impossible command and a skipped one indistinguishable in the record. The instruction now states the condition under which the validator is reachable and says what to record when it is not, so unavailable and skipped are no longer conflated (#851).

A learning written on 16 August had already named the exact reason the review dedup fingerprint cannot match two reviewers describing one defect. An issue was filed against that same fingerprint on 20 August with the wrong cause, and the right cause was worked out again from scratch on 23 August — the answer had been sitting in docs/solutions the whole time. It was unfindable: its frontmatter read module: measurement with tags about evidence and instrument validation, naming neither the skill it came from nor the algorithm it described. Someone debugging deduplication searches for deduplication, not for an epistemics lesson they haven’t learned yet. The fix splits the two jobs — the title and body carry the general lesson, the frontmatter carries the particulars someone would actually search for — adding three tags to the older note was enough to make it reachable without disturbing its framing. It also fixes the knowledge-track template, which still listed four problem types after four more were added, and syncs the copy the refresh skill keeps (#850).

  • deps: Renovate bumps and minor dependency updates (fro-bot/agent to v0.105.0, bfra-me/.github to v4.20.0).

v3.13.6…v3.13.7

Published 2026-08-23 · Updated 2026-08-23 · View on GitHub

ce-review: The risk-aware degraded verdict in code review dispatch used to block unless another persona “covered the same surface” — a judgement call with no formal definition, so identical diffs and identical review findings could pass or block depending on who read them. Four independent reviewers of the change that introduced the rule ran into exactly this ambiguity.

The fix keeps signal that was already being computed and discarded: Stage 3 dispatch selection already determines and announces why each conditional persona was chosen, naming the endpoint or migration that triggered it. That reasoning is now recorded on the dispatch alongside the changed files, and “coverage” becomes a mechanical test — a validated finding covers a lost surface when its file is one of the recorded paths. A blocked verdict now states what would clear it (re-run the lost persona, or supply a validated finding on one of the recorded paths), and the verdict cites the specific finding that satisfied coverage so the decision can be reproduced from the artifact instead of taken on trust (#847).

A follow-up refactor in the same change widened the risk-critical persona-name tuple from an asserted cast to readonly string[], removing a type assertion that claimed an arbitrary string was one of five literals without anything actually checking it. Behavior is unchanged — all five risk-critical personas still require a selection surface, and always-on personas still do not.

v3.13.5…v3.13.6

Published 2026-08-23 · Updated 2026-08-23 · View on GitHub

ce-review: Finding deduplication was keyed on a fingerprint that included each finding’s normalized title. Because two reviewers rarely phrase the same finding the same way, the fingerprint almost never matched, so near-duplicate findings from independent reviewers passed through as separate results instead of being merged.

Measuring stored review runs quantified the problem: across twenty runs there were 375 cross-reviewer pairs of findings on the same file — 55 of them within three lines of each other and 39 on the exact same line — and none of them ever merged. That means the confidence boost meant to fire when independent reviewers converge on the same issue had never actually fired.

Line proximity was never the real signal, and prose files weren’t a special case either. Grouping is now mechanical and file-only, and the decision about whether two findings describe the same underlying defect is left to judgement — the one thing the model running this stage is actually good at. Declining to merge two findings is now recorded along with a reason: a wrong merge is obvious to a reader, but a missed merge just looks like two separate findings, so recording the decision either way leaves a trace.

A follow-up commit clarified how a partially-merged candidate group is recorded: when a group of three findings has two that merge and a third that doesn’t, one entry is written per declined separation, naming the IDs on both sides of it — so a three-finding group with a partial merge produces a single entry listing all three. A group that merges completely produces no declined-separation entries at all.

v3.13.4…v3.13.5

Published 2026-08-23 · Updated 2026-08-23 · View on GitHub

Planning previously could name a new file and its test but omit the registration obligations elsewhere — a codemap entry, a module table row, a manifest listing, or a generated artifact — until a gate failed or, worse, never caught the gap at all. ce-plan now carries registration obligations into the unit that actually creates the file, using the contributor guidance it already reads to name both the surfaces that must list the new file and the command that regenerates them (#845).

The src/lib module tables in src/lib/AGENTS.md had drifted from the codemap in ARCHITECTURE.md, documenting only 19 of 34 modules despite both being intended to cover the same set. This is now gated the same way the codemap already is: a content-integrity check fails when a module exists without a table row, or a row names a module that doesn’t exist — including a visible exclusions escape hatch for intentional omissions. The fix also adds the fifteen missing modules (including the previously undocumented receipt-guard subsystem), corrects two false export claims caught during an audit of all 155 export claims across the 34 rows, and hardens the gate to fail loudly rather than silently collapsing two modules that share a basename in different subdirectories (#844).

The architecture overview and structure tree still described a CLI with three subcommands, but it has grown to six — including two that ship user-facing behavior, capabilities and validate-review-artifact. Docs now cover the full CLI surface and document the review artifact contract as the real enforcement mechanism it has become: a Zod source, a generated schema committed under the skill, a drift gate, and a CLI validator shipped in dist. Every count in the three root documents was re-enumerated against the actual tree rather than searched for by expected value, which caught four stale test counts across four different phrasings (#843).

v3.13.3…v3.13.4

Published 2026-08-23 · Updated 2026-08-23 · View on GitHub

The ce:review contract specified writing a metadata.json file alongside the review summary, capturing the run ID, branch, HEAD, harness, verdict, and completion time — but no run had ever written it, and nothing in the repository read it. The instructions even described downstream skills falling back to file mtime when the file was absent, documentation for a consumer that was never built.

Investigation found that half of the contract had already collapsed on its own: the run artifact’s schema already carries run_id, harness, and verdict, and every real artifact on disk includes a verdict despite the (unwritten) contract placing that field elsewhere. Only branch, HEAD, and the completion timestamp were still homeless, so this fix moves those three fields into the artifact that is actually produced and validated (#842, 476a3b6).

The distinction the original design was reaching for still holds: branch and HEAD are captured at dispatch time, before any autofix lands, while the run artifact is written after the verdict is final — so a reader can tell whether the recorded state describes the checkout in front of them. Only the destination changed, not the semantics.

An earlier attempt to delete the dead metadata.json contract outright was dropped because the supporting evidence was flawed: a claim of zero writes across twenty-six runs counted twenty runs that predated the field’s existence. This fix instead rests on two facts that don’t depend on that count — there is no reader for the file, and three of its six fields already live elsewhere.

v3.13.2…v3.13.3

Published 2026-08-23 · Updated 2026-08-23 · View on GitHub

ce:compound-refresh carried its own copy of the solution-document contract that ce:compound writes against, and that copy had drifted. It recognized four fewer knowledge-track problem types than the canonical contract, so documents filed as architecture_pattern or convention — three of which already exist in the repo — read as invalid to the very skill responsible for judging whether they’re correct.

The bigger issue was two missing YAML quoting rules. Without them, a value containing a space followed by a hash ( #) is silently truncated by the YAML parser with no error raised. Because ce:compound-refresh’s entire job is rewriting documents, it was exactly the surface where losing that rule would reintroduce the bug it exists to prevent.

Both files are now byte-identical to their ce:compound counterparts — matching the resolution template the two skills already shared. A new test asserts all three shared files stay identical and that the two knowledge-track enums parse to the same set, so this drift can’t recur silently. The duplication itself stays intentional: the Claude Code build flattens each skill into a self-contained bundle, so having one skill point at another’s file isn’t safe across harnesses. The compound-docs copy of the contract is untouched — it has no track sections and predates this contract, so aligning it is a separate decision. (#841)

v3.13.1…v3.13.2

Published 2026-08-23 · Updated 2026-08-23 · View on GitHub

A small maintenance release: a fix to the knowledge-doc categorization schema and two new solution-doc learnings drawn from the review artifact contract work.

  • ce-compound: The knowledge-track schema accepted architecture_pattern, design_pattern, tooling_decision, and convention as valid track values, but the reference guide’s track table listed none of them and gave none of them a category directory — an author choosing one of these four had a valid problem_type and nowhere to file the document. All four now map to best-practices/, the directory where documents already using these tracks were already being filed, rather than splintering into four directories that would each hold a single document. The guide also now states that the narrowest applicable value is preferred, gives a one-line description of what each of the four tracks means, and clarifies that the knowledge-track field rules apply to every type in the table, not just the original four.
  • Adds a learning on why an artifact contract with no validated write path ends up with no conforming producers, drawn from measuring review-run artifacts before scoping issue #793: seven artifacts across 26 runs, no two sharing a shape, every documented ledger field absent, and an undocumented field present in all of them.
  • Extends the existing input-set learning with a third contaminant beyond gitignored build output and ambient user config: standing on the wrong branch, which defeats the usual “check for untracked/dirty files” recommendation because another branch’s tracked files are clean and so never show up as ignored or dirty.
  • Documents a verification method: correcting a repeated fact by searching for one phrasing leaves other occurrences worded differently, so enumerate the individual claims instead — doing so turned up an error nobody was looking for. The learning’s title was broadened from counts to repository claims generally, since it now covers whether a documented path exists at all.

v3.13.0…v3.13.1

Published 2026-08-23 · Updated 2026-08-23 · View on GitHub

The review pipeline now validates its own run-level artifact instead of trusting it by convention. ce:review writes two kinds of artifact — per-persona records, which the parent has always validated before persisting, and the run-level review-summary.json, which nothing checked. An audit of 26 runs found 138 per-persona files sharing 21 shapes (111 identical), against 7 run-level artifacts with 7 distinct shapes written under two different filenames.

The run artifact now has a Zod source of truth, with the input ledger modeled as a discriminated union on record_type so admitted rows and rejected-payload summaries are machine-separable without inferring state from which keys happen to be present. A generated JSON Schema is committed and gated against drift, and validation ships as a new CLI command, systematic validate-review-artifact <path>, distinguishing four outcomes — valid, schema violation, operational failure (missing file, malformed JSON), and pre-contract legacy artifacts with no schema_version. Error output is projected through an explicit allowlist so validation failures never echo review content back into logs. The ce:review skill now requires the parent to stamp schema_version and run the validator immediately after writing, with a stated failure path: repair and re-run, never report a verdict over a failing artifact, and never delete it to dodge the check (#830).

Project docs had drifted from the tree they describe: skills were listed as 45 against 31 on disk, agents as 51 against 37, unit tests as 20 against 59 (later corrected again to 56 to match this branch), and integration tests as 2 against 11. Two script roles were also swapped in a way that could mislead a reader following them — build-registry.ts was documented as the drift checker, when drift is actually checked by generate-registry.ts (which regenerates registry.jsonc from skill and agent frontmatter), while build-registry.ts builds the OCX packument from the already-synced file. Undocumented parts of the tree — the Pi extension entry point, the evals harness and runner, and the codegen/drift-check scripts for Pi personas, the agent-browser skill, and the review artifact schema — are now described, and a script that only exists on an unmerged branch was removed from the list. Every backticked repository path in both files was checked for existence against this branch rather than spot-checked (#831).

Renovate’s package rules now give release-pipeline packages a minimum release age of three days before they’re picked up, and group semantic-release and conventional-changelog-conventionalcommits major updates under a single rule so they land together rather than piecemeal. A follow-up fix adjusted the package matching to include semantic-release-export-data for more accurate dependency management (#835).

  • build(dev): Bump conventional-changelog-conventionalcommits to v10.4.0.
  • deps: Add a conventional-changelog-writer override; bump bfra-me/.github, fro-bot/agent (three releases), and github/codeql-action.
  • dev: Bump @biomejs/biome, agent-browser, and typebox (twice).

v3.12.4…v3.13.0

Published 2026-08-20 · Updated 2026-08-20 · View on GitHub

ce:review’s Stage 5 verdict could read as clean even when a review had actually degraded, for three separate reasons closed by this release (#818).

First, environment-value redaction was too aggressive: it matched any runtime environment value, exact or embedded, and discarded an entire persona payload on a hit. Short values are common — in a typical shell, 19 of 101 environment values are eight characters or fewer, including strings like 0, 1, 3, 30, and -c — so a finding that merely quoted a diff line containing a digit could cause a reviewer’s whole payload to be thrown away. Value matching is now limited to values of at least 16 characters that are not purely digits, dots, dashes, or path separators, plus any value whose variable name looks secret-bearing regardless of length. Structural detectors are unchanged, and a match inside a single finding now drops only that finding rather than the entire payload.

Second, a rejected reviewer could still contribute to a “clean” verdict. When the persona assigned to a risk-critical surface came back malformed or never returned, the coverage note recorded the gap but the verdict itself did not reflect it. The verdict is now blocking unless another persona covered the same surface with validated evidence, and the same rule applies when a risk-critical persona loses findings to finding-level rejection. A follow-up fix refined this rule further: keying the block on any nonzero rejected-finding count was both too strict (blocking the verdict over a single dropped P3) and too loose. The rule now keys on severity — a rejected P0, P1, or unknown-severity finding blocks the verdict, while P2/P3 losses are only recorded in Coverage, and unknown severity fails closed.

Third, rejected payloads no longer get per-finding ledger entries, so deduplication — which runs only over validated returns — can no longer undercount cross-reviewer agreement by excluding an enumerated rejected finding from the fingerprint group of an identical surviving one. A rejected payload now rolls up into a single weighted summary entry, keeping disposition counts consistent with the findings actually observed.

The secret-bearing variable-name list used for redaction also gained coverage for common short-secret variables — DB_PASS, MYSQL_PWD, GPG_PASSPHRASE, SIGNING_PASSPHRASE, AUTH_SALT, and HMAC_SALT — via new _PASS, _PWD, PASSPHRASE, and _SALT patterns, underscore-qualified specifically to avoid catching benign names like BYPASS_CACHE, PWD, BASALT_DIR, or SALT_ROUNDS.

  • deps: Updated fro-bot/agent to v0.101.0 (#817).

v3.12.3…v3.12.4

Published 2026-08-19 · Updated 2026-08-19 · View on GitHub

Agent and command discovery walked every .md file it found, so a plain README.md dropped into agents/<category>/ became a dispatchable agent named README and shipped as a registry component (#816). README is documentation by universal convention and was never meant to be content. Four independent code paths had reimplemented the same “every .md is an agent” rule — runtime agent discovery, command discovery, the overlay inventory that validates user config, and the content-integrity predicate that decides which files must satisfy the agent frontmatter contract — and each had to be corrected. They now share one helper. The integrity gate still scans README files for reference-integrity and banned-pattern checks; only the agent frontmatter contract is relaxed, so a real agent missing temperature: still fails the gate. The issue surfaced while adding a README to agents/review/ to record that the directory is a shared persona pool rather than a review roster.

The same change consolidated the synthesis artifact contract to one canonical home at skills/ce-review/references/synthesis-artifact-contract.md. It previously lived in three places that could drift apart; SKILL.md and review-output-template.md now summarize and link instead of restating the rules, and findings-schema.json remains the executable definition. AGENTS.md also now documents the generated-surface cascade — editing an agent description or body drifts the registry and the Pi persona fixtures, and adding a file under a skill’s references/ drifts the registry’s per-component file list — each of which was previously discoverable only by hitting a red gate.

A content-integrity check now fails the build when prose tells an orchestrator to pass a model argument to the dispatch tool (#815). The dispatch tool accepts a fixed set of arguments, and model is not among them — prose instructing an orchestrator to pass one degrades the dispatch to a generic sub-agent with no configured model, which silently discards the user’s per-agent and per-category model assignments. Three instances of this had already shipped; one survived a fix, a ten-persona review, and an automated review pass, and was found only by reading the published package rather than the source tree. The new check requires two co-occurring signals on the same line — a model: <value> assignment written as inline code, and vocabulary indicating a sub-agent dispatch — since either signal alone is ordinary in legitimate content. The vocabulary list deliberately omits the bare word “agent” (used constantly in legitimate docs about “bundled agents”), and model: inherit is exempted as a frontmatter literal that skills must name precisely in order to prohibit it. Requiring the assignment to sit inside an inline-code span, rather than merely following a colon, separates a real code-shaped argument from ordinary prose that would otherwise trip a false positive on a gate with no advisory channel.

The docs build and deploy jobs stopped reinstalling system packages the runner already has (#814). The docs job spent sixty seconds preparing a browser to render two Mermaid diagrams and only ten seconds building the site itself — almost all of that cost came from Playwright’s --with-deps flag, which runs apt-get update and installs CJK, Thai, and Cyrillic fonts plus a fontconfig trigger pass for diagrams whose labels are English. The flag is dropped; if a required library ever does go missing, Chromium now fails at launch instead of degrading quietly, keeping the failure visible. The remaining cost — the browser binary download — is now cached against the lockfile that pins Playwright, so a cache hit skips it and only a version bump triggers a fresh download. The same treatment was applied to the docs deploy job.

Three release and verification learnings were captured in docs/solutions/ (#812). A release run had reported success while publishing nothing: the job conclusion was green, and the release tool’s own closing line named a version and channel that did not exist in the registry, because that line prints in dry-run mode too — two workflow defects produced it, each hiding the other, so the behavior split by branch while ignoring the caller’s input in both directions. Separately, verification delegated into a fresh worktree had reported a malformed dependency import and three dozen failing tests that turned out to be an empty node_modules, not real breakage — a brief that names a fresh environment now has to name its preparation too, and has to let the reply distinguish a gate that failed from a gate that could not run. And publishing a fix for an older major was documented as resting on one fact: dist-tags play no part in semver range resolution, so a consumer on a caret range receives the newest matching version whether or not a tag points at it, which allows a one-shot release under a throwaway tag that is then deleted, leaving the default install untouched. The existing document on measured counts also gained a second instance — a test suite reading the developer’s own config file showed the configuration factor escaping version control, not just the filesystem factor it previously named alone.

v3.12.2…v3.12.3

Published 2026-08-18 · Updated 2026-08-18 · View on GitHub

The ce:plan reference documentation still instructed orchestrators to dispatch research agents with a model argument on the Agent tool — an argument that doesn’t exist in the tool’s schema. When present, the dispatch silently degraded to a generic sub-agent with no configured model, which then inherited the session model and discarded the user’s per-agent and per-category model assignments (#813).

This is the same defect previously reported in #784 and fixed across two skills in v3.10.2. That earlier pass missed this occurrence because it lives in a reference file rather than a skill body, and it was only caught this time by inspecting the published package rather than the source tree — the same line had already been corrected on the v2 maintenance branch by a wider sweep. A full sweep of bundled skills and agents confirms no remaining instance. The content-integrity gate checks that bundled agents omit a model field in frontmatter and validates literal subagent_type values, but nothing yet inspects prose for instructions to pass an unsupported argument — worth closing in a future pass.

The release job’s dry-run flag ignored the value passed to it, in both directions: a dispatch from the default branch always published regardless of what the caller asked for, and a dispatch from any other branch never did (#810).

Two causes masked each other. The workflow expression relied on operator precedence that doesn’t hold — && binds tighter than ||, and a workflow_dispatch input arrives as a string, so inputs.dry-run && 'true' evaluated truthy even when the caller passed false. The flag was therefore always true; the expression now compares against the string explicitly and parenthesizes the intent. A later step then forced the flag back to false whenever the run was on the default branch, which is what made real releases work at all and is why the first bug stayed invisible — but it also meant an explicitly requested dry run on the default branch performed a real release. With the expression corrected, that override step is redundant for every event the workflow handles, so it was removed rather than left to contradict the input. Pushes to the default branch are unaffected: they carry no inputs and evaluated false both before and after.

  • deps: Update bfra-me/.github to v4.18.0 (#811).

v3.12.1…v3.12.2

Published 2026-08-18 · Updated 2026-08-18 · View on GitHub

A one-shot v2-line maintenance release that repairs three defects causing Fro Bot skill dispatches to silently do the wrong thing, plus a release-tooling fix that makes dry-run dispatches actually honor the dry-run flag.

Every agent reference is now dispatchable on the v2 line. This is a backport of the v3 fix for the dispatch failures reported in #784, for users who can’t yet move to v3 because it removed bundled skills and agents they still depend on.

Three defects were fixed, each of which caused a dispatch to silently do the wrong thing instead of failing loudly:

  • Twenty-four agent references carried a ce- prefix that never matched any agent file, so every one of them failed to resolve. They’re now written in the qualified form the integrity gate actually validates, so they resolve and can’t rot again unnoticed.
  • The agent-native audit named a subagent_type of Explore, which isn’t an agent this package ships. It now dispatches the bundled research analyst instead.
  • Several skills instructed the orchestrator to pass a model parameter to the task tool. That parameter doesn’t exist in the tool’s schema, so the dispatch silently fell back to a generic sub-agent with no configured model, which then inherited the session model — discarding per-agent and per-category model assignments without any error. Model policy is user-owned configuration, so the skills no longer try to set it.

This release adds no ongoing v2 support line: the release configuration change is scoped to this branch, publishes under a throwaway dist-tag that’s removed afterward, and leaves the default install pointing at the current major.

The release workflow now honors the dry-run input when releasing from a manual dispatch, preventing dry-run invocations from accidentally publishing a real release.

v2.33.3…v2.33.4

Published 2026-08-18 · Updated 2026-08-18 · View on GitHub

ce-plan: closed two escape hatches in the prior-art survey contract (#809). Both had shipped as known limitations, and neither needed new machinery to close.

The first hatch was in the exemption for plans with no survey section. That exemption exists because every plan written before the contract lacks the section, and without it none of them could execute — so the exemption is load-bearing. But it applied to any plan lacking a section, so a plan authored afterward with the section simply deleted got the same free pass, preserving exactly the duplicate-work outcome the survey exists to prevent. Since every plan already records its own date, the exemption is now conditional on it: a plan dated before the contract keeps the pass, one dated after must carry a survey, and a plan whose date cannot be established stops rather than guessing in either direction. The five states a plan can be in are now enumerated as an explicit partition, each mapped to exactly one branch, replacing prose that review had found self-contradictory.

The second hatch was in the survey itself. Because the agent chooses its own search boundary, one that preferred building something new could select a narrow but defensible scope excluding an existing equivalent, find only weak candidates inside it, and legitimately conclude nothing sufficient existed — every step defensible, the verdict worthless, and invisible because the survey recorded only what it searched, never what it declined to search. A verdict of building new now requires recording the adjacent scopes that were deliberately not searched, each with a reason; an empty list explicitly means no adjacent scope exists. Plan review now asks whether the concern would plausibly live in one of the excluded scopes, turning a private choice into a reviewable claim.

The survey contract’s version was bumped alongside the shape change, since making a field conditionally required changes what the contract describes, and leaving the version unchanged would have taught future readers that the field doesn’t track shape.

solutions: recorded three verification lessons from the prior-art survey work (#808), plus broadened one existing document to match what the round showed.

An exemption must be predicated on the condition that actually makes verification impossible, not on a signal that usually accompanies it. A gate comparing documented plugin hooks against registered ones had exempted any assertion saying “all” or “every” as a proxy for “asserts completeness without enumerating” — but a document claiming all six hooks while listing three matched the proxy, was fully checkable, and passed clean anyway. The predicate now names the real condition: the section enumerates nothing comparable.

A stop condition comparing current state against earlier state requires the contract to record that earlier state. A rule refusing stale survey results had shipped against a schema with no timestamp, revision, or digest, so the check could only ever report that freshness was unknown. The fix specifies the recorded baseline, how current state is computed, and what happens when comparison is impossible, in the same change as the rule.

Design review and literal-text review find different defect classes. Nine specialist reviewers assessed the ce-plan change above and found real defects; an automated reviewer then found that the shipped paragraph contradicted itself, scoping validation to plans that have a section and then treating an absent section as a halt. The design was right and the reviewers were reviewing the design — when prose is the enforcement mechanism, reading the final wording as an executable contract is a separate pass.

The generated-artifact drift document previously covered description edits only. Editing an agent or skill body drifts the Pi export fixtures too, because the export embeds full persona text, and adding a file under a skill’s references directory drifts the registry, which records per-component file lists — both invisible to targeted tests by construction. The generator source behind the drift claim was also cited directly.

v3.12.0…v3.12.1

Published 2026-08-18 · Updated 2026-08-18 · View on GitHub

This release grounds ce:plan in existing code before it lets a plan proceed, closing a gap where an agent could plan a duplicate of a subsystem it never looked for. Planning now dispatches a prior-art scope alongside its existing research: the survey receives the concern as trigger, effect, state, and boundary rather than a proposed design, so it cannot inherit the planner’s framing and can’t quietly confirm a solution shape it was handed. It bounds itself to a workspace and a stated budget, collects every plausible candidate before dispositioning any of them, and describes what each one owns in the vocabulary the code itself uses — because a subsystem named in accounting terms is invisible to a search framed in enforcement terms, even when its files are in view.

The survey’s result is a validated JSON contract, not prose: a missing or malformed block now gets a specific remediation instead of dissolving into unverifiable narrative. Five verdicts are available and the schema constrains what each may claim — building something new requires naming the candidates that were insufficient, an unpickable scope requires naming the scopes that were weighed, and running out of budget preserves whatever was already found rather than discarding it. A unscoped or unresolved verdict now stops planning until the scope narrows or a user explicitly accepts the uncertainty, and that acceptance is recorded so later stages can tell it apart from a verdict nobody handled. The survey also carries a freshness record — a version-control reference or a portable baseline — so work execution can refuse a plan whose surveyed scope has drifted since the survey ran, and plan review confirms each named candidate resolves to real code rather than taking the survey at its word. Plans written before this contract still run; a missing survey section is treated as pre-dating it, not as a failure.

Alongside the survey, the content-integrity gate gained two new checks against root documentation. One compares the hooks a document claims the plugin registers against the typed inventory the plugin entry point actually returns — closing a hole where a document could assert “all hooks” while enumerating only half of them and still pass. The other compares the modules named in the architecture codemap against the modules on disk in both directions, so an undocumented module and a stale codemap entry for a deleted one both fail the build. Together these catch the exact failure mode that motivated them: four contributor-facing documents claiming the plugin registers three hooks when it registers six, with the three unmentioned hooks being the ones the workflow guard runs on.

The documentation gap the new content-integrity checks were built to catch is fixed in the same window: ARCHITECTURE.md, STRUCTURE.md, .github/copilot-instructions.md, and AGENTS.md all previously claimed the plugin registers three hooks, when src/index.ts registers six — including the three observation hooks (tool.execute.before, tool.execute.after, and event) that the workflow guard depends on. An agent orienting from any of those documents could reasonably conclude the plugin has no enforcement path. ARCHITECTURE.md now describes the workflow guard directly: what the observation hooks feed, how operations get classified, what a receipt proves, and that it’s OpenCode-only. The project-local documentation-generation skill had also hardcoded “three hooks” into its own template, which meant regenerating ARCHITECTURE.md would have restored the error; the template now derives hooks from src/index.ts at generation time instead of carrying a frozen list.

A separate solutions entry records three verification boundaries discovered while shipping the dispatch-identifier gate. First, the release pipeline has two stages with opposite commit-body ingestion: release-notes-generator reads subject lines only, but the release-notes-narrative skill (the one producing this note) reads every commit body and, when thin, the originating PR description — so a commit body does reach the published notes, just through the second stage rather than the first. Second, releaseRules is scope-aware while presetConfig.types is not, so a non-releasing commit can still earn a notes section; v3.11.0’s Documentation section opened by quoting an internal planning label for exactly this reason. Third, tsconfig.json scopes typecheck to src/**/* only, leaving the eight files under scripts/ — including content-integrity itself — untypechecked; a deliberately injected type error and a call to an undefined function both passed bun run typecheck silently.

  • deps: Updated bfra-me/.github to v4.17.1.

v3.11.0…v3.12.0

Published 2026-08-17 · Updated 2026-08-17 · View on GitHub

The content-integrity gate’s checkReferenceIntegrity validates references shaped systematic:<category>:<name> against real agent files, but anything spelled differently was invisible to it — 24 phantom ce--prefixed references and a subagent_type: Explore pointing at nothing sat in bundled content while the gate reported clean. v3.10.2 fixed those instances by hand, but the mechanism that let them rot in the first place was unchanged.

This release adds checkDispatchIdentifiers, closing the two decidable parts of that gap: a literal subagent_type value must resolve to a bundled agent filename stem, and an inline-code kebab-case token that ends with a real bundled stem but isn’t itself resolvable is flagged as a near miss. Both checks are deliberately narrow — deciding whether arbitrary prose refers to an agent is undecidable, and structural exclusions (path tokens, canonical references, skill directory names) keep the gate quiet without an allowlist to maintain.

The gate’s safety no longer rests on the coincidence that no bundled agent is named plan or review. Skill directories like ce-plan are now excluded explicitly rather than relying on an unenforced naming invariant that would have broken every ce-plan reference the moment an agent named plan shipped.

The change also fixes skills/using-systematic/references/opencode-profile.md, which had demonstrated dispatch using explorer and fixer — agents this package doesn’t ship. Readers without those agents in their own OpenCode configuration would follow the example and hit an unresolvable dispatch; the examples now use bundled agents so every reader can run them.

Review surfaced four defects that fixtures missed, all reproduced before fixing: quoted property keys never matched (so {"subagent_type": "x"} passed unchecked), the unquoted-value branch didn’t stop at a quote, updateFenceMarker kept only the first fence character, and a single path token suppressed near-miss detection for every token sharing its inline-code span. Verified against the real pre-fix tree: restoring the two files that shipped with 24 violations reproduces exit code 1.

Plan item I5 is marked complete. Every approach bullet has shipped: src/lib/source-model-defaults.ts and src/lib/model-availability.ts were deleted rather than narrowed, no provider-name routing survives in src/ (v3.10.0), every bundled agent reference resolves under checkReferenceIntegrity, and the model: task-tool parameter that silently bypassed user model policy is gone (v3.10.2).

Two sets of provider literals remain deliberately: JSON Schema examples in config-schema.ts documenting the provider/model shape for users writing config, and sample application code in skills/agent-native-architecture/references/ that teaches tiered agent design. Removing either would make the artifact worse, not less market-pinned.

The dispatch-identifier gap (see Features, above) was folded into this plan item because unresolvable references bypass model policy, making bad routing the visible symptom. With every instance closed, the residual is scoped down to the reference-integrity gate itself and filed as a standalone issue rather than left as an open-ended initiative.

  • deps: update dependency typebox to v1.3.14 (#802)

v3.10.2…v3.11.0

Published 2026-08-17 · Updated 2026-08-17 · View on GitHub

skills/ce-plan/references/deepening-workflow.md referenced 24 agents using a ce- prefix that matched no bundled agent — names like ce-spec-flow-analyzer, ce-deployment-verification-agent, and ce-architecture-strategist had never existed. skills/deepen-plan/SKILL.md carried the same roster in its correct, canonical form, revealing the ce--prefixed list as a stale duplicate that content-integrity checks never caught: checkReferenceIntegrity only validates the qualified systematic:<category>:<name> shape, so references written any other way rot in place unnoticed. Converting the 24 references to the qualified form brought them under the gate, verified by deliberately introducing a wrong category and confirming CI now fails with the file, line, and missing-agent path — a failure mode that could not fire before this fix.

Two related defects of the same class were corrected alongside it. skills/agent-native-audit/SKILL.md dispatched a subagent type (Explore) that doesn’t exist in the bundle; it now dispatches systematic:research:repo-research-analyst, whose purpose matches the read-only codebase enumeration the skill performs. skills/ce-review/SKILL.md and skills/ce-ideate/SKILL.md instructed orchestrators to pass a model: parameter to the task tool, but the tool accepts no such parameter — the unactionable instruction caused dispatch to silently fall back to a generic model rather than the user’s configured assignment. Both skills now dispatch named bundled agents directly, since that is the mechanism that actually causes per-agent model configuration to apply. ce:compound’s Phase 1 also named three researcher roles in prose with no concrete identifier, which invited silent substitution with a different model tier and had already produced a materially wrong classification in a real run; each role now binds to a specific agent (e.g., Related Docs Finder resolves to systematic:research:learnings-researcher).

Two accompanying documentation updates capture the underlying lessons for future contributors. One records that an unvalidated complement to a validated surface accumulates rot silently — 24 dead references sat undetected in one file because the integrity checker only recognizes one reference spelling. The other documents a lint-baseline discrepancy: bun run lint walks the filesystem rather than the git index, so a gitignored build-staging directory inflated a locally-reported warning count (17 vs. 11 on a clean checkout) in a way that looked like tooling drift but wasn’t. A follow-up fix made the verification snippet in that second doc portable by replacing BSD-only sed -i '' syntax with perl -pi -e, which behaves identically on GNU and BSD systems, and added the restore-and-recheck step that had been described but not shown.

v3.10.1…v3.10.2

Published 2026-08-17 · Updated 2026-08-17 · View on GitHub

ce:review artifact contract enforcement (#798). Across 24 recorded review runs, only 11 of 19 qualifying runs produced any synthesis artifact and just 5 recorded which reviewers contributed to a merged finding; one run logged 22 findings and 8 named outcomes with no disposition for the other 14. Of 252 findings in the corpus, 60 had blank why_it_matters, 58 had empty evidence, and 3 artifacts were Markdown wearing a .json extension. The root cause: sub-agents wrote artifacts directly and nothing validated what landed. On Pi this never worked at all — every review persona declares tools: Read, Grep, Glob, Bash, which resolves to no write capability, while sub-agents were instructed to write a file anyway.

Persistence now lives in the parent orchestrator. Sub-agents return a single inline payload; the parent validates it against a tightened JSON Schema and writes it. A follow-up review found the original schema’s enforcement claim was empirically false — a payload with a 50,000-character field, an absolute path in evidence[], a 10,000-entry array, and injected unknown fields still validated as valid: true. The schema is now fully closed: additionalProperties: false on every object, maxLength/maxItems derived from observed corpus maxima, and path rejection covering absolute POSIX, drive-letter, and UNC forms. The contract is also split into a subAgentReturn shape (forbids forged provenance fields) and a parentRecord shape (requires them).

Three persona descriptions were also corrected: architecture-strategist, pattern-recognition-specialist, and code-simplicity-reviewer live under agents/review/ but are never selected by ce:review — their real consumers are ce-compound, deepen-plan, and ce-plan’s deepening workflow. Tests grew from 11 to 35 across the series, pinning each schema constraint at both the rejecting and accepting boundary rather than only asserting valid === false.

Captured verification blind spots from the model-defaults wedge — three failure modes that passed every automated gate at the moment they mattered. A new eval case registered at all documented touch points still let an integration test fail because it kept a hand-maintained verbatim copy of runner help text with nothing linking it to the source. A regression gate built to catch reintroduced source-owned defaults checked the model field but not variant, so a variant-only regression would have passed clean. And a dependency field annotated “retained for compatibility” had no reader anywhere, while a commit’s hardening rationale was silently erased by the next commit deleting that file — both examples of prose making claims no type, test, or linter evaluates.

  • deps: Update bfra-me/.github to v4.17.0.

v3.10.0…v3.10.1

Published 2026-08-17 · Updated 2026-08-17 · View on GitHub

Bundled agents stop being pinned to a Systematic-chosen model — they inherit whatever model invoked them, closing out a six-unit removal plan alongside a documentation drop on two release-pipeline traps discovered while shipping it.

Systematic no longer picks a provider/model pair for bundled agents on the user’s behalf. SOURCE_CATEGORY_MODEL_DEFAULTS used to map five agent categories to ordered provider chains, resolved against discovered availability before user overlays applied — and when nothing matched, it fell back to returning the first provider’s first model anyway, so a user on a provider Systematic didn’t enumerate could get pinned to a model chosen for someone else (an anthropic-only user invoking a design agent landed on vercel/v0-1.5-md). That table encoded the August 2026 model market as package policy, in tension with a harness whose thesis is “get better as models get better.”

The table, its schema, resolver, docs formatter, and the src/lib/model-availability.ts availability subsystem it depended on are all deleted. The config hook now performs no network call and no model-cache filesystem read, and agent resolution begins at category overlays with no source layer beneath them — category and exact-agent overlays, precedence between them, model: null restoring inheritance, and permission reconstruction all behave identically to before. This is a removal for plain npm consumers specifically: OCX/OMO installers keep curated category routing through their registry profile, while plain npm users lose category-aware routing unless they opt in. docs/src/content/docs/guides/model-defaults-migration.mdx records all five former provider chains (with variants) so any prior pin can be reproduced in explicit config.

A new model-inheritance eval case gates the behavior against regression, grading all 37 bundled agents across all 5 categories rather than a sample, and checking both model and variant together after an initial version of the gate proved less than its commit message claimed — it observed model but not variant, so a regression reintroducing variant pinning without a model would have passed clean. Agent identifiers from the eval manifest are now validated fail-closed against the live bundled inventory before being persisted.

Two traps surfaced while shipping the bootstrap catalog deletion, both quiet enough to reach main unnoticed, are now captured as solution docs. The first: this repository’s PR title decides whether a change publishes at all — squash merges are the only merge mode, squash_merge_commit_title is COMMIT_OR_PR_TITLE, and @semantic-release/commit-analyzer reads that header. refactor looks like a releasing type in presetConfig.types but isn’t one; a user-visible payload reduction nearly merged under refactor: and would have published nothing. The second: evidence collected against a pinned external runtime expires when the pin moves. The host-pin drift guard fired when main bumped OpenCode to 1.18.18, and the correct response was to move the pins and re-run the real-host eval suite rather than bump constants to silence the guard.

The existing gh heredoc doc now also covers git commit -m, since the backtick trap that mangles commit bodies (and the release notes they carry) is a shell rule, not a gh-specific one. The bootstrap catalog deletion and local eval foundation plans are marked complete.

  • deps: update fro-bot/agent to v0.100.0 (#789)

v3.9.1…v3.10.0

Published 2026-08-16 · Updated 2026-08-16 · View on GitHub

A performance-focused release: Systematic trims a redundant chunk out of every bootstrap prompt now that OpenCode’s native skill discovery covers the same ground.

Systematic no longer injects an <available_skills> block into the bootstrap prompt. OpenCode already registers bundled skills under native skills.paths, renders its own permission-aware catalog, and the systematic_skill tool description exposes the same names and descriptions — so the bootstrap-injected catalog was pure duplication. Removing it cuts the generated bootstrap payload from 18,145 to 6,232 characters and eliminates 23 absolute machine paths from prompt output.

renderCatalogVerbose() and formatSkillsXml() are removed along with their supporting escaping helpers, and CatalogEntry no longer carries path and skillFile, since those fields only existed for the deleted verbose path. The receipt-workflow fixture now requires exactly one opening and one closing workflow marker and verifies retained systematic_skill discovery guidance in place of the removed bootstrap catalog. ARCHITECTURE.md documents the per-harness discovery semantics this change relies on: OpenCode and Pi discovery surfaces, the unavailable-tool contract, and host-upgrade revalidation requirements — Pi has no registerSkillsPaths() equivalent, so denying systematic_skill removes the remaining catalog discovery path there.

The eval host pin moved from 1.18.5 to 1.18.18 to match the repository’s @opencode-ai/plugin and @opencode-ai/sdk dependency versions, and a drift check now fails the build if the pin and dependency version diverge. Because host catalog rendering is version-dependent, the bootstrap-catalog deletion was re-proven rather than assumed: the real-host eval suite passes 51/51 at 1.18.18, with the host still covering every bundled skill.

  • dev: update OpenCode to v1.18.18 (#787)
  • deps: update bfra-me/.github to v4.16.47 (#785)

v3.9.0…v3.9.1

Published 2026-08-15 · Updated 2026-08-15 · View on GitHub

The evals harness now records bounded prompt-composition evidence and models three distinct observation states for each catalog check — present, absent, and impossible — instead of collapsing the latter two together. Previously, a run where the coverage signal simply couldn’t be observed was treated the same as a run that observed no coverage at all, which masked infrastructure problems as real coverage gaps.

Systematic and OpenCode catalog evidence is now partitioned by workflow-block containment, and that partitioning fails closed on malformed or unmatched blocks. This guarantees that Systematic-rendered catalog content can never be miscounted as host-runtime coverage, even when a workflow-block marker is broken or missing.

A new permanent host-skill-coverage case performs host-catalog coverage on the pinned runtime as exact set inclusion against the raw bundled skill names. Extra host entries are tolerated, but missing entries fail the case and are explicitly named in the failure output, and the case manifest is drift-protected by deriving expected names from the live bundled catalog at test time — so the manifest can’t silently go stale as skills are added or renamed.

Execution failures are also now split into two categories: diagnosed task failures (including host runtime timeouts) and undiagnosed infrastructure failures when no transform is observable at all, giving clearer signal about where a failing eval run actually broke.

This release also lands a fast differential test that feeds a shared corpus — including valid markers, unmatched markers, nested markers, duplicated Systematic catalogs outside the workflow block, mixed host/Systematic catalogs, and non-string entries — through both the typed TypeScript catalog-observation logic and the generated JS that actually executes in the spawned host, to keep the two implementations from drifting apart. A positive control ensures the test can’t pass by having both implementations return the same “impossible” state. The probe artifact identifiers (probeId and probeDigest) were also bumped to v3 so persisted run artifacts map cleanly to the implementation revision that produced them.

This work covers eval observation and gating only; no production behavior under src/ changed in this release.

  • build: Updated OpenCode to v1.18.17.
  • deps: Updated typebox to v1.3.13, bfra-me/.github to v4.16.46, and fro-bot/agent to v0.99.0.

v3.8.0…v3.9.0

Published 2026-08-15 · Updated 2026-08-15 · View on GitHub

Added a local OpenCode outcome runner for evals (#778), giving the project a deterministic way to execute and verify evaluation cases against local OpenCode runs without any telemetry or upload. The runner covers two cases — bootstrap-loading and fixture-local-write — each executable in both source and installed (packed-installed) modes, with distinct provenance tracked per mode so results are traceable back to how the code under test was actually running.

Fixture isolation is scoped rather than OS-sandboxed: child-process environment inheritance is denied by default, with explicit allowlisting required for test execution. Fail-closed behavior is enforced throughout — archive and dependency-resolution handling, privacy redaction, residue/quarantine cleanup, and manifest persistence all default to blocking rather than silently succeeding on the unsafe path. Signal-safe lifecycle handling was also wired in to guarantee best-effort cleanup of fixtures, spawned processes, and installed artifacts if a run is interrupted mid-flight, and outputs are written only to local run artifacts under evals/runs/<runId>/.

Follow-up review findings were folded into the same change: eval child-environment inspection was made CodeQL-safe by passing dynamic fixture values through argv instead of the environment, OpenCode secret matching was narrowed from a broad sk-* token regex to explicit sk- / sk_ shapes to cut false positives, and a regression test was added confirming legitimate skill-loading remains allowed while token-shaped sk values are still rejected.

  • deps: Renovate updated @biomejs/biome to v2.5.8 (#777).

v3.7.0…v3.8.0

Published 2026-08-14 · Updated 2026-08-14 · View on GitHub

Systematic gains a read-only diagnostics surface — a way to ask the CLI “what do you actually see?” without touching bootstrap, config resolution, or the plugin’s write paths.

systematic capabilities — deterministic, privacy-safe CLI diagnostics. The new cli-capabilities.v1 command exposes a versioned JSON snapshot of package/config/discovery state that was previously only inferable by reading source or guessing from behavior. It reports which skills and agents “won” discovery, separates config source presence from proven per-field authority, and surfaces bounded discovery failures — all without exposing discarded entries, local file paths, or other information that would leak privacy-sensitive details.

The diagnostic is strictly observational: bootstrap, config handling, setup, routing, and workflow protection behavior are all unchanged. Config loading was extended with read-only observation metadata, injectable roots, and warning sinks, and discovery keeps its existing winner semantics — failing closed on agent collisions and modeling malformed skill sources as bounded issue facts rather than crashing or silently dropping them.

This work also lands three new planning documents under docs/plans/ (the “Bitter Lesson” migration program, the capability-diagnostic plan itself, and a focused local OpenCode eval-foundation child plan) that capture the dependency-ordered modernization initiatives this feature is part of, along with the safety and evidence gates required before any related cleanup work proceeds.

Along the way, a CLI fixture-tree test was hardened: Bun 1.3.14 writes its own module-resolution cache under $HOME/.bun as a side effect of spawning bun src/cli.ts as a subprocess, which was tripping a byte-identical fixture-tree snapshot assertion. The .bun cache directory is now excluded from the snapshot — it’s Bun’s own runtime artifact, not something the CLI under test writes, so ignoring it doesn’t weaken the actual security assertion that the CLI writes no unexpected files.

  • deps: update fro-bot/agent to v0.98.5 (#775)
  • build: update dependency conventional-changelog-conventionalcommits to v10.3.0 (#774)

v3.6.2…v3.7.0

Published 2026-08-13 · Updated 2026-08-13 · View on GitHub

The workflow guard’s marker parser (parseMarkerBody) hard-rejected any persisted marker whose protocolVersion didn’t exactly match the current MARKER_PROTOCOL_VERSION (2), with no fallback for v1 markers minted before PR #741’s version bump.

A user resuming an OpenCode session across the upgrade would carry v1 markers into v2 code, where the read path treated them as malformed, aggregating to guard-unavailable and dropping an in-flight guarded unit instead of recovering it.

Since MarkerSource’s shape didn’t change between v1 and v2 (the version bump was coordinated with an unrelated receipt-envelope schema bump), a persisted v1 marker recovers identically under v2 parsing. This fix mirrors the existing LEGACY_RECEIPT_PROTOCOL_VERSION pattern already used in receipt-ledger.ts: parseMarkerBody now accepts both MARKER_PROTOCOL_VERSION and a new LEGACY_MARKER_PROTOCOL_VERSION, with test coverage added for a persisted v1 marker parsed under v2 code.

v3.6.1…v3.6.2

Published 2026-08-13 · Updated 2026-08-13 · View on GitHub

A single security-scoped patch drives this release: a High-severity denial-of-service advisory in the js-yaml parser is patched, alongside routine automated dependency maintenance.

  • security: js-yaml is bumped from the resolved 4.3.0 to 4.3.1, patching GHSA-5p4m-2wfm-xmqj (CVE-2026-59870, CVSS 7.5, High). The advisory is in resolveYamlOmap(), whose key-uniqueness check does a linear scan per element when resolving YAML !!omap sequences — making the operation O(n²) overall. Because !!omap is part of the default YAML schema, any yaml.load() call is exposed without special options; a roughly 2.5MB crafted document can block the Node.js event loop for around 10 seconds. js-yaml is used directly in src/lib/frontmatter.ts to parse skill, agent, and command frontmatter, so this was real attack surface for anyone feeding untrusted skill/agent files through Systematic.

    4.3.1 back-ports the same Set-based key-tracking fix already shipped in the 5.x line (since 5.2.1) and satisfies the existing ^4.1.1 semver range in package.json, so the fix is a lockfile-scoped patch bump with no source changes required. It is independent of the pending major-version migration tracked in #733 (js-yaml v5), which additionally requires an import-shape fix for a dropped default export and is left to the normal Renovate/category-1 repair path.

    Verified on the fix branch: typecheck, lint, bun test tests/unit (1827 pass), build, content-integrity, and an ESM default-export smoke test all passed.

  • deps: Renovate-driven updates — OpenCode bumped through v1.18.12 → v1.18.16, fro-bot/agent through v0.96.2 → v0.98.4, bfra-me/.github to v4.16.45, @types/node to v26.2.0, typebox to v1.3.10 and v1.3.11, @biomejs/biome to v2.5.7, semantic-release to v25.0.9, and a batched non-major dependency update.

v3.6.0…v3.6.1

Published 2026-08-04 · Updated 2026-08-04 · View on GitHub

automation: Fro Bot’s scheduled repository stewardship and autohealing have been consolidated into a single daily agent pass (#748). Previously the bot ran a separate Monday maintenance schedule alongside its daily autoheal run; that split schedule, dispatch mode, and prompt are gone, and stale-item detection, workflow-health checks, and repository metrics now all feed into one daily autoheal report. The consolidated pass combines proactive detection with bounded reactive repair (schedule-only issue healing, deduplicated, capped at a one-PR mutation budget per run) and adds progressive-improvement tracking that compares each report against prior reports, solutions, and recurring failures over time. Cross-project intelligence was also expanded, surfacing evidence-backed adopt/monitor/reject dispositions rather than raw signal, and agent-targeted follow-ups were replaced with cold-start notes any LLM agent can pick up without prior context.

To keep this safe to run unattended, the change enforces exactly one canonical Daily Autohealing Report (migrating any bot-authored legacy weekly/daily reports), constrains automatic issue triage to read-only analysis, and prevents checkout credentials from persisting across steps. Two follow-up commits harden this further: report-continuity tests were added to guard the new report lifecycle, and autoheal report writes were made atomic so a crash or interrupted run can no longer leave a corrupted or partial report file on disk. Scheduled and manual agent runs are now serialized so they cannot overlap, and GITHUB_TOKEN permissions remain read-only, with writes continuing to flow through the dedicated FRO_BOT_PAT.

  • build(dev): Updated OpenCode to v1.18.11 (#750).
  • chore(deps): Updated github/codeql-action to v4.37.6 (#751).
  • chore(deps): Updated fro-bot/agent to v0.96.1 (#749).

v3.5.9…v3.6.0

Published 2026-08-04 · Updated 2026-08-04 · View on GitHub

Guard: canonicalize apply_patch paths in operation fingerprint (#747) — An apply_patch operation could fail closed to guard-unavailable, minting no implementation receipt, when a co-installed plugin’s before-hook rewrote the patch file path (absolute↔relative) before the receipt guard observed it. The guard fingerprints apply_patch arguments over the raw patchText string, so the before-hook fingerprint (computed over the rewritten output.args) and the after-hook fingerprint (computed over the original input.args) diverged, causing takePendingOperation to seal the operation as abandoned.

The fix canonicalizes apply_patch path targets to their lexical absolute form (via path.resolve against the effective session location, not realpath) before fingerprinting, at both prepareOperation and finishOperation. The patch body, target ordering, move destinations, and all non-path arguments remain part of the hash, so a changed patch body or a different target file still changes the fingerprint. Ambiguous or unparseable patches fail closed, leaving args unchanged.

Four regression tests cover the relative-before/absolute-after mint-once case, a changed body producing unavailable, a different file producing unavailable, and an equivalent duplicate after-event replaying without a double mint — exercising the before/after args divergence that the existing unit and integration suites (which feed fixed args directly to the guard) never covered. A follow-up commit adds two more regression tests closing gaps flagged in review: hunks-array form canonicalization including move_path, and fail-closed behavior for a malformed patch with an empty file-target path.

  • deps: Update all non-major dependencies (#745).

v3.5.8…v3.5.9

Published 2026-08-03 · Updated 2026-08-03 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

Published 2026-08-03 · Updated 2026-08-03 · View on GitHub

Fixed a bug where apply_patch operations targeting an absolute path inside a registered nested worktree would fail closed to guard-unavailable when no workdir argument was given. The root cause: deriveApplyPatchTarget seeded the shared-root set with the parent checkout root, so even though per-file targets correctly resolved to the worktree, a mismatch between the parent and worktree paths made sharedTargetRoot return undefined.

The fix derives the shared root from the patch-file targets alone when workdir is absent and the patch names files, matching deriveFileOperationTarget’s existing handling of write/edit operations. Behavior is otherwise unchanged: an explicit workdir, or a patch with no file targets, still seeds the workdir root, preserving both the multi-worktree spanning guard and the parent fallback for fileless patches. (#744, closes #743)

Added a documented solution for receipt guard issues to the workflow-guard docs, along with a follow-up fix correcting the solution’s category. (#742)

v3.5.6…v3.5.7

Published 2026-08-03 · Updated 2026-08-03 · View on GitHub

The receipt guard now correctly attributes worktree-targeted operations to the worktree they actually touched, closing out issue #678 end-to-end. Previously, child operations that acted on a registered worktree could have their receipts rolled up under the parent observer’s identity, and ambient GIT_DIR/GIT_WORK_TREE environment variables could spoof which repository an observer subprocess believed it was operating in. The fix introduces validateRegisteredWorktree (checking common-dir identity, git worktree list membership, and .git linkage) and strips GIT_* variables from observer subprocesses before they run.

On top of that validation, deriveOpencodeOperationTarget resolves the actual worktree a bash/write/edit/apply_patch operation acted on — from workdir, filePath, path, or multi-file patch targets — and fails closed on escaping, mixed-worktree, or git-admin paths. rollupForegroundTask now snapshots each recovered child receipt’s authenticated operationTargetIdentity instead of assuming the fixed parent observer, and is fatal on workspace/target/registration mismatches while remaining skippable only for repository/worktree revision staleness after the target already matches.

Completion readback was the last gap: it now resolves a single effective completion observer — the pinned registered worktree for pinned units, the parent observer otherwise — and anchors both the global and remote final readbacks to that target’s revision, while workspaceIdentity stays the stable parent identity. This eliminates the cross-root false “worktree delta” that had been marking legitimate worktree-targeted evidence as stale, and adds defense-in-depth by requiring a pinned unit’s global readback to carry the pinned operationTargetIdentity.

Follow-up review fixes registered operation-target-mismatch in the REASON_CODES set so the reason round-trips at the host marker boundary instead of degrading to guard-unavailable, threaded operationTargetIdentity through the legacy single-readback parser, and replaced an unsafe cast with proper digest narrowing at the receipt envelope parse boundary.

  • build: Bump OpenCode to v1.18.10.
  • chore: Bump the playwright dependency to v1.62.1.

v3.5.5…v3.5.6

Published 2026-08-01 · Updated 2026-08-01 · View on GitHub

The ce-review shared reviewer prompt previously encouraged open-ended surrounding-code investigation, which led reviewers to repeatedly re-read unchanged files and drift across a single unresolved area instead of converging on a verdict. This release enforces a bounded, diff-first prompt contract: investigators now treat the supplied diff as the primary source of truth, read each unresolved surrounding range only once, and re-read only when ambiguity remains or the file has actually changed.

The contract also requires a terminal conclusion path — reviewers must return a finding/verdict or an explicit blocker/residual-risk statement rather than broadening scope indefinitely. A contract test now pins these semantics in the content-integrity checks, and a live pressure review confirmed convergence after a single diff read (#737).

v3.5.4…v3.5.5

Published 2026-08-01 · Updated 2026-08-01 · View on GitHub

A single reliability fix to the guarded-workflow protocol, plus routine toolchain upkeep.

systematic_workflow_start and systematic_workflow_complete now treat an unavailable / guard-unavailable guard state as terminal for the current execution unit (#736). Previously the documented bootstrap guidance was ambiguous about what to do once a guard reported itself unavailable, which could lead an agent to keep reattempting the same guarded call in a retry loop. The runtime already closed over this case correctly, but the guidance gap meant behavior wasn’t guaranteed to be deterministic under failure. This release canonicalizes the using-systematic bootstrap guidance so an unavailable guard is not retried, and pins regression coverage for that behavior.

  • dev: update dependency typescript to v7 (#732)
  • dev: update dependency @types/node to v26 (#731)
  • deps: update actions/setup-node action to v7 (#730)
  • deps: update actions/checkout action to v7 (#729)

v3.5.3…v3.5.4

Published 2026-07-31 · Updated 2026-08-01 · View on GitHub

The operation observer used to discover a single Git directory and reuse it for both command execution and filesystem reads. In repositories with a separate Git directory (core.worktree), that conflation meant commands resolved paths relative to .git while file hashing used repository-subpath semantics — snapshots could go stale or be reported unavailable, breaking readback and closure checks. This release (#735) splits command execution context from filesystem context: commands now use the discovered Git command directory, while file reads use the resolved worktree root. Tracked, staged, and untracked paths are now read with repository-root pathspec semantics (--full-name and :/) so snapshots stay repo-wide even when the command directory points at a subdirectory, submodule revision reads use absolute paths to avoid resolution drift, and remote readback operations share the same Git invocation root as local snapshot collection.

Renovate PR builds previously ran a separate artifact-generation step outside the normal build pipeline. That path is now consolidated into the standard build so Renovate PRs produce artifacts the same way any other PR does, and a postupgrade script/task was added now that bfra-me/renovate-action 10.1.0 supports allowed post-upgrade commands (#725). The Renovate and update-repo-settings workflows were also bumped to v4.16.44 (#734).

Delegated receipt recovery is now documented under docs/solutions, capturing the recovery flow and aligning the worked example with the current source implementation (#723).

  • deps: Updated agent-browser to v0.33.1 (#718).
  • build(dev): Updated OpenCode to v1.18.9 (#724).

v3.5.2…v3.5.3

Published 2026-07-31 · Updated 2026-07-31 · View on GitHub

Write-capable delegation now requires an explicit workspace attestation before changes are accepted. Delegation briefs must name the expected workspace and return actual-root/file-change attestation, and both the expected and source checkouts are independently verified before a delegated change is trusted — closing a gap where a worktree path named in a prompt was treated as proof that changes actually landed there. The fix also documents the distinction between fresh plugin processes, clean conversations, and same-session restart recovery, since restarting OpenCode reloads plugin code while preserving resumed conversation history, and those two paths need separate stale-session recovery handling. (#722, 3420c5c)

v3.5.1…v3.5.2

Published 2026-07-31 · Updated 2026-07-31 · View on GitHub

Protected workflows could fail closed after a successful foreground task delegation. Child receipts were being compared against the parent session’s salt and boot-time revisions, so stale intermediate receipts aborted the entire rollup, and explicit operation requirements declared after skill activation weren’t preserved across recovery. This release validates foreign child lineage and reconstructs receipt identities with the child session salt, preflights receipt batches before minting so stale mutable revisions are skipped while foreign workspaces stay fail-closed, and re-attests current child evidence against the parent’s live pre-task state without exposing a classifier bypass to model tools. Explicit starts can now monotonically extend pristine auto-started units — including resource scopes — with replay-safe recovery, and exactly-once rollup behavior is preserved across duplicate callbacks and host restarts. Test coverage was hardened to use semantic integration checks in place of model-wording-sensitive and raw marker-count assertions (#719).

The pinned OpenCode dev dependency was bumped twice this cycle, first to v1.18.7 (#712) and then to v1.18.8 (#717), keeping the local dev toolchain current with upstream fixes.

Ownership and trust boundaries for the pi-subagents persona export were documented, covering manifest, lock, and hash checks; transactional mutation safety with rollback and canonical path containment; and runtime verification via the pinned @tintinweb/pi-subagents@0.14.3 integration tests (#711).

  • deps: Bumped fro-bot/agent to v0.96.0 (#721).
  • deps: Bumped github/codeql-action to v4.37.4 (#713).
  • dev: Bumped @biomejs/biome to v2.5.6 (#720).

v3.5.0…v3.5.1

Published 2026-07-30 · Updated 2026-07-30 · View on GitHub

Persona interoperability for pi-subagents, plus a SessionStart hook contract fix and routine dependency maintenance.

pi-subagents persona interoperability (#710) — Systematic categories and agents can now be exported as personas compatible with @tintinweb/pi-subagents, via an opt-in systematic pi-subagents <preview|export|refresh|cleanup> lifecycle for both project- and global-scoped exports. The generator projects Systematic’s category/agent model overlays alongside Pi-native thinking, max_turns, tools, and skills fields, while systematic_delegate stays the bounded default so the new pi-subagents delegation boundary remains opt-in and clearly separated.

The export path is hardened for concurrent and adversarial filesystem conditions: a manifest with an exclusive mutation lock, anchored path checks, transactional rollback, and hash-gated deletion. Filesystem and locking code fails closed on symlink or non-directory path components, refuses unsafe manifest edits, and verifies manifest-owned files with hash-drift checks before removal. Manifest reads open and validate a single descriptor before parsing — rejecting symlinked paths via O_NOFOLLOW where available, and verifying opened-file identity via lstat as a fallback to close symlink/replacement race conditions. Real exported-persona discovery and execution were verified end-to-end against pinned @tintinweb/pi-subagents@0.14.3.

claude: the SessionStart hook contract was aligned to intentionally omit a matcher (#709), so the hook covers all session-start event sources (startup, resume, clear, compact) per the documented contract, rather than being scoped to startup only.

  • dev: update OpenCode to v1.18.6 (#706)
  • deps: update bfra-me/.github to v4.16.42 (#707)
  • deps: update fro-bot/agent to v0.95.1 (#708)

v3.4.1…v3.5.0

Published 2026-07-28 · Updated 2026-07-28 · View on GitHub

Fixed a workflow-guard recovery bug that surfaced when Systematic was registered twice in the same OpenCode session — for example, when the published package (via user config) and the repo source (via project config) were both loaded. Both registrations had been appending receipt markers into the same shared, unnamespaced metadata array, so on restart each registration saw the other’s seed during recovery, misread it as a conflicting-seed, and forced the runtime to unavailable. The guard reported guard-unavailable even when protected config was active, and both registrations failed closed.

Recovery now classifies markers collected from session parts into own, provably-foreign, or ambiguous, and each registration recovers only its own markers, filtered by registration digest, instead of treating a foreign registration’s markers as a conflict. This is applied on both the main-session recovery path and the foreground-task child rollup path. Ambiguity still fails closed: if no own seed is resolvable and any marker is malformed or seedless, recovery still reports guard-unavailable rather than silently resetting the guard and risking state loss or corruption. Genuinely foreign-only marker arrays still start fresh, and the change is read-side only — the persisted marker format is unchanged and backward-compatible with existing sessions.

The public tagline was repositioned from “structured/compound-engineering workflows” to “Compound-engineering loops for OpenCode, Pi, and Claude Code,” applied uniformly across package.json, GitHub About (.github/settings.yml), the Claude Code marketplace and plugin/output-style descriptions, the README, the banner SVG, the docs site config and landing page, ARCHITECTURE.md, AGENTS.md, and the regenerated OCX registry. The pass also fixed stale harness lists that had named only OpenCode or only Claude Code, updating them to name all three shipped harnesses; runtime system-prompt prose was left unchanged.

Two new solution docs were added from the agent-browser vendoring work (v3.4.0): a best-practices doc on vendoring an npm-packaged upstream skill as a generated, drift-guarded artifact (pinned devDependency, copy from node_modules, CI drift gate, attribution version sync, Renovate postUpgradeTasks), and a test-failures doc covering an unguarded generator main() that silently repaired drift when imported by its own unit test, fixed with an import.meta.main guard. Five related docs received reciprocal cross-links.

v3.4.0…v3.4.1

Published 2026-07-28 · Updated 2026-07-28 · View on GitHub

The agent-browser skill moves from a hand-vendored bundle to a generated stub kept in sync with its upstream npm package, plus routine dependency maintenance.

  • agent-browser: vendor upstream skill as auto-synced thin stub (#700)

The hand-vendored agent-browser skill bundle — a SKILL.md, 7 reference docs, and 3 templates maintained by hand in this repo — is replaced with a thin discovery stub generated deterministically from a pinned agent-browser npm devDependency (0.33.0). A new scripts/generate-agent-browser-skill.ts copies the stub from node_modules and keeps the ATTRIBUTIONS pinned-version references in sync, guarded by an agent-browser:drift CI gate alongside the existing registry/schema drift checks. Renovate’s postUpgradeTasks regenerates the stub automatically on version bumps, so future upstream refreshes land in the same PR as the dependency bump instead of requiring a manual follow-up edit. An Apache-2.0 ATTRIBUTIONS entry for vercel-labs/agent-browser was added to reflect the new upstream dependency.

The change also adds 25 unit tests (tests/unit/generate-agent-browser-skill.test.ts) covering the frontmatter hidden-strip, ATTRIBUTIONS version sync, pinned-version read, and compare-normalization helpers, matching the test conventions of the sibling generator scripts. The generator entrypoint is now guarded with if (import.meta.main) so importing the script — as its own unit test does — no longer triggers generate-mode side effects that would silently rewrite skills/agent-browser/SKILL.md and ATTRIBUTIONS.md and mask real drift instead of detecting it.

  • deps: update dependency playwright to v1.62.0 (#702)
  • deps: update OpenCode to v1.18.5 (#701)

v3.3.1…v3.4.0

Published 2026-07-27 · Updated 2026-07-27 · View on GitHub

The workflow-guard transform hook now fails closed. experimental.chat.system.transform runs inside a try/catch so host-side errors are swallowed the same way event/after hooks already handle them, instead of propagating and potentially destabilizing the session. The inline session SDK double-casts that had been duplicated across call sites were also replaced with a single shared SessionReadMethod boundary type, now used consistently for both messages and children reads. Behavior is unchanged — this is a type-safety and consistency cleanup (#698).

  • dev: Bump typebox to v1.3.8 (#699)

v3.3.0…v3.3.1

Published 2026-07-27 · Updated 2026-07-27 · View on GitHub

Receipt-backed workflow completion guard (#697) — Workflow transitions (implementation, verification, commit, push, PR creation, check/review readback) are now grounded in host-observed evidence rather than self-reported state. A session-scoped, privacy-safe receipt ledger paired with an AST-bounded Bash classifier records real operations as they happen, and guarded transitions require runtime-trusted receipt minima before they’re allowed to complete. The guard fails closed on no-ops, replay, ambiguous shell shapes, and incompatible or stale receipt metadata — qualifying receipts are consumed exactly once.

Key pieces of the system:

  • OpenCode adapter wiring: a trust-bounded guard configuration supports observe/protected modes with project-scope protection, per-session/per-registration activation, and bounded workflow-control tools. Tool lifecycle hooks can surface blocks before execution while post-execution finalization never throws.
  • Operation evidence verification: current-state-bound before/after evidence, class-specific no-op and resource validation, and operation-aware staleness tracking ensure receipts reflect the true state of the workspace, repository, or resource in question.
  • Restart and recovery: receipts persist deterministically across restarts, with replay-safe readback, stale-evidence repair, and session-scoped projections. Foreground task child receipts roll up into fresh, parent-scoped, once-only evidence, failing closed on fork copies or mismatched lineage.
  • Local and remote operation observation: production write/edit/apply-patch and Bash verification/commit operations now mint real receipts using a stable-target/mutable-revision identity model and symlink-safe worktree hashing. Push, PR creation, and check/review readback observation use narrow, read-only git/gh JSON readbacks, storing digest-only resource identity and failing closed on unavailable or oversized readbacks.
  • Question attestation: a host-neutral, one-time attestation state machine (challenge → bind-asked → observe-reply → consume) gates certain transitions behind an exact-token yes/confirm reply, with replay and substitution protection and no retained user prose.
  • Skill-to-operation mapping: guarded skills are mapped to their required shipping operations on activation, with PR-check/review resource scopes deferred until the PR materializes and push upstream refs bound at start.

The guard also picks up several correctness fixes along the way: worktree digests now reflect working-tree content (not just the git index) so staleness checks stay accurate after staged edits; push classification recognizes more common git push command forms while still rejecting destructive refspecs (force/delete/mirror-like); and workflow observer subprocess calls now have bounded timeouts with fail-closed behavior. Configuration and generated documentation were updated to document the observe/protected/disabled modes, and CodeQL findings around predictable temp-file paths and a TOCTOU read window in test helpers were resolved using secure temp directories and readlink-first reads.

  • deps: Update bfra-me/.github to v4.16.41 (#696)
  • dev: Update dependency typebox to v1.3.7 (#695)

v3.2.8…v3.3.0

Published 2026-07-25 · Updated 2026-07-25 · View on GitHub

Security: markdownlint-cli has been bumped from 0.48.0 to 0.49.1 to pull in patched versions of two transitive dependencies flagged by OSSF Scorecard’s OSV scan (code-scanning alert #28): js-yaml (4.1.1 → 5.2.2) and markdown-it (14.1.1 → 14.3.0). Both packages were pinned by markdownlint-cli’s own dependency ranges (js-yaml: ~4.1.1, markdown-it: ~14.1.1) and could not be resolved by bumping top-level version ranges alone — the fix required moving to markdownlint-cli@0.49.1, which requires js-yaml: ~5.2.1 and markdown-it: ~14.3.0.

The advisories addressed are quadratic-complexity denial-of-service issues: GHSA-52cp-r559-cp3m and GHSA-h67p-54hq-rp68 (high/moderate severity CPU exhaustion via YAML merge-key chains and repeated aliases in js-yaml), and GHSA-6v5v-wf23-fmfq (moderate severity DoS in markdown-it’s smartquotes rule). markdownlint-cli is a devDependency used for ad hoc Markdown linting and is not wired into the published plugin runtime or CI, so there is no production exposure. The change is scoped to a package.json version bump and a regenerated lockfile, with no source code changes.

v3.2.7…v3.2.8

Published 2026-07-25 · Updated 2026-07-25 · View on GitHub

security: brace-expansion is pinned to 5.0.8 via a package.json override, remediating GHSA-mh99-v99m-4gvg (CVE-2026-14257, High). Versions 5.0.7 and earlier have an unbounded expansion length that can crash the Node process with an uncatchable out-of-memory error from a roughly 7.5KB crafted input. The package reaches this repo only as a transitive dependency — pulled in via minimatch, which is required by markdownlint-cli, glob, and @earendil-works/pi-coding-agent, all devDependencies — so exposure was limited to local tooling and CI rather than runtime or published packages. (#694)

  • build: update OpenCode to v1.18.4 (#688)
  • deps: update fro-bot/agent to v0.95.0 (#693)
  • deps: update dependency @biomejs/biome to v2.5.5 (#692)
  • deps: update fro-bot/agent to v0.94.3 (#691)
  • deps: update ossf/scorecard-action action to v2.4.4 (#689)
  • deps: update bfra-me/.github to v4.16.40 (#686)
  • deps: update fro-bot/agent to v0.94.2 (#687)

v3.2.6…v3.2.7

Published 2026-07-22 · Updated 2026-07-22 · View on GitHub

A maintenance-only release: one dependency bump, one Renovate config tweak, and a batch of patch-level action updates. No functional changes to the project itself.

  • deps: Bumped @earendil-works/pi-ai and @earendil-works/pi-coding-agent from 0.80.7 to 0.80.10 (#671), keeping the Pi coding-agent toolchain current with upstream provider and model fixes.
  • renovate: Disabled artifact updates for bun and npm in the Renovate config (#685), so lockfile-artifact-only PRs from those managers no longer get opened.
  • deps: bfra-me/.github bumped v4.16.38 to v4.16.39 and github/codeql-action bumped v4.37.2 to v4.37.3 (#684).

v3.2.5…v3.2.6

Published 2026-07-22 · Updated 2026-07-22 · View on GitHub

sharp is patched to ^0.35.0, resolving four inherited libvips vulnerabilities disclosed in GHSA-f88m-g3jw-g9cj (CVE-2026-33327, CVE-2026-33328, CVE-2026-35590, CVE-2026-35591). Two of the four are rated High severity (CVSS 7.0) and affect anyone processing untrusted input through sharp prior to 0.35.0. The upgrade pulls in libvips 8.18.3, which tightens bounds-checking across several image operations (clahe, trim, recomb, extract, raw input dimensions) to prevent signed-integer overflow.

Agent contract verification is now documented as a reusable learning: compile the real JSON Schema, validate emitted objects against it, and confirm that uncorrected live producer output is accepted by its existing consumer — rather than asserting against a mocked or simplified schema. The learning is cross-linked with adjacent contract-boundary and schema-validation guidance, and the v3.2.4 findings-contract plan is marked complete with its shipped provenance.

  • deps: Renovate bumped fro-bot/agent to v0.94.1 and github/codeql-action to v4.37.2.

v3.2.4…v3.2.5

Published 2026-07-21 · Updated 2026-07-21 · View on GitHub

The document-review skill now uses a single findings contract from reviewer output through synthesis. Previously, the shipped reviewer schema and prompts still produced legacy vocabulary — decimal confidence scores and auto/present autofix values — while synthesis expected the newer contract, so valid reviewer findings were misclassified as malformed and silently dropped.

This change makes the JSON Schema authoritative and aligns every producer and consumer surface to it: discrete confidence anchors (0, 25, 50, 75, 100), canonical autofix classes (safe_auto, gated_auto, manual), and consistent producer guidance, headless behavior, synthesis examples, and presentation templates across all seven reviewer personas. Legacy decimal confidence and auto/present values are now strictly rejected, and auto-class findings that omit a suggested fix are deterministically demoted rather than passed through inconsistently (#679).

  • deps: update fro-bot/agent to v0.94.0 (#676)

v3.2.3…v3.2.4

Published 2026-07-21 · Updated 2026-07-21 · View on GitHub

Astro’s v7 security release (fixing GHSA-4g3v-8h47-v7g6) initially broke the docs build: @astrojs/starlight@^0.39.0 bundles @astrojs/mdx@^5.0.4, which imports an Astro subpath (./jsx/rehype.js) that was removed from Astro v7’s package.json exports map. Bumping Starlight to v0.41.3 pulls in astro@^7.0.2 and @astrojs/mdx@^7.0.0, resolving the incompatibility. bun.lock was regenerated from a clean install to also clear a stale hoisted @astrojs/markdown-remark@7.1.2 entry that was causing a separate “unified is not a function” failure during Astro’s legacy markdown-plugin config coercion. (#674, c82e0f0)

  • build(dev): update dependency semantic-release to v25.0.8 (#675)
  • build(dev): update OpenCode to v1.18.3 (#672)
  • chore(deps): update bfra-me/.github to v4.16.38 (#673)

v3.2.2…v3.2.3

Published 2026-07-19 · Updated 2026-07-19 · View on GitHub

The build hardens Claude Code agent flattening: it now parses frontmatter and enforces uniqueness on the NFC + case-folded dispatch identity (both file stem and frontmatter name), failing closed when a name is missing, empty, or the wrong type. This guards against silent overwrites from case- or Unicode-folded collisions on case-insensitive filesystems. Bundle staging is now genuinely atomic — the prior bundle is renamed aside (not deleted) before the new one swaps in and restored on any swap failure — and the rename-aside step itself was folded inside the same try/catch so a stray staging directory can never leak, whether the failure happens in the write loop, the aside setup, or the swap itself. The SessionStart hook also drops its startup-only matcher so its declarative state facts fire on all sources (startup, resume, clear, compact), matching Claude Code’s own convention for the “all sources” form. No behavior change on the clean corpus (151 files, 37 agents, 31 skills). (#670)

This release ships an arc of workflow-first documentation across the banner, root docs, and docs site. The banner tagline now reads “Compound-Engineering Workflows for OpenCode, Pi, and Claude Code” (previously OpenCode-only), the empty Commands feature pill is replaced with Workflows, and the byte-identical duplicate banner in the docs site is removed in favor of a single source. (#668)

README, ARCHITECTURE, and STRUCTURE are brought current with the workflow-first framing across all three delivery surfaces. README now leads with the ce:* workflow as Systematic’s identity, with harnesses framed as supporting delivery surfaces; Quick Install gains the Claude Code marketplace path, and the First-Run Checklist is harness-agnostic. ARCHITECTURE documents the three-harness delivery model (OpenCode plugin, Pi setup, Claude Code CI-built marketplace bundle), and STRUCTURE adds the .claude-plugin/ directory and its build script. (#667)

The docs site landing page and Installation guide now lead with the ce:* compound-engineering pipeline (brainstorm, plan, work, review), demoting the supported harnesses to a supporting mention. The dedicated pi-harness and claude-code-harness guide pages are removed — their install steps folded into Installation, their boundary detail (Pi’s “honest parity differences”, Claude Code’s layered/capability-boundary model) consolidated into HARNESSES.md — with their URLs redirected to Installation. Usage sections across Installation are made harness-aware (prerequisites, asset discovery, first-workflow loop) rather than speaking only for OpenCode. (#666)

Two learnings from this docs arc are captured for reuse: authored .mdx GFM tables rendered as raw pipe text until remark-gfm was wired into the Astro markdown pipeline, and OpenCode’s plugin config key is singular plugin (not plugins) — the plural is silently ignored so the plugin never loads. (#669)

  • deps: Pin remark-gfm to 4.0.1 (#664)

v3.2.1…v3.2.2

Published 2026-07-19 · Updated 2026-07-19 · View on GitHub

OpenCode’s config schema uses a singular plugin array, but the plural plugins key is silently ignored, so a configured plugin would simply never load. Several install docs and both shipped registry profile configs (standalone and omo) used the wrong plural key, which meant users following the documented setup ended up with instructions that failed silently. The docs and shipped configs — README, installation/index/agent-install pages, and the registry profile opencode.jsonc files — are now swept to the singular plugin key, aligning them with the behavior Systematic’s own setup.ts already enforces and its integration tests already exercise (#665).

Authored .mdx content pages weren’t picking up Astro’s default GFM table parsing, so pipe tables rendered as raw text inside a <p> element across the live docs site (configuration, main-loop, v3-migration, and others) instead of as actual <table> elements. Plain generated .md reference pages were unaffected. remark-gfm is now wired explicitly into markdown.remarkPlugins so .mdx content gets proper GFM table parsing — verified against built HTML output (configuration 0→1 tables, main-loop 0→1, v3-migration 0→2 tables), with no raw pipe-text tables remaining, mermaid diagrams unaffected, and all 85 pages building clean (#663).

Two knowledge-track solution docs capture learnings from the Claude Code harness work: best-practices/claude-code-plugin-build-and-publish-architecture documents the build-and-publish-from-CI packaging pattern (gitignored staging, build-time identifier translation on generated output only, a generated-namespace integrity gate, release-gated orphan-branch publishing, SHA versioning, and the marketplace catalog), and workflow-issues/verify-installed-artifacts-not-just-build-gates captures the verification lesson that artifacts should be verified as-installed rather than assuming build gates passing is sufficient, and that unproven host channels should be probed empirically before designing against them. Both docs add reciprocal cross-links to the qualified-persona-ids, reference-integrity, and neutral-v1-gate sibling docs (#662).

The publish-claude-code-plugin job previously ran independent of the release job, so the plugin branch could ship a non-release commit, or drift from the published npm package if the release itself failed. The job is now gated on the release job and on an actually-cut version: semantic-release’s new-release-published/new-release-version are exposed as release job outputs, the publish job now depends on release, and publishing only happens when new-release-published is true. The plugin remains SHA-versioned — this change only couples its publish timing to npm releases (#661).

v3.2.0…v3.2.1

Published 2026-07-18 · Updated 2026-07-18 · View on GitHub

Systematic now ships as a distributable Claude Code plugin (#660). The work landed as a series of coordinated changes: a new Claude Code capability profile (skills/using-systematic/references/claude-code-profile.md) documents the harness’s verified mechanisms — name-based subagent dispatch, AskUserQuestion, the TaskCreate family, and native Skill/SKILL.md discovery — grounded in HARNESSES.md evidence and a live Desktop probe, resolving a previously-unverified subagent_type note. HARNESSES.md promotes Claude Code from Tier 2 to Tier 1 accordingly, with a new install guide covering the output-style/hook/native-skill channel model.

The bundle itself is generated, not committed: scripts/build-claude-code-plugin.ts mirrors the existing registry codegen pattern, walking skills/ and agents/ source to flatten 37 agents and copy 31 skills into a self-contained plugin, rendering an output-style from the using-systematic skill body plus the CC profile, and emitting a declarative SessionStart hook well under the platform’s size cap. After an initial approach that committed the bundle, the design was reworked mid-series into an ephemeral, build-time-translated artifact — identifiers are rewritten to Claude Code’s plugin-namespaced form (e.g., ce:brainstorm → systematic:ce-brainstorm), a generated-namespace integrity gate catches any untranslated reference, and the 151 previously-committed bundle files were removed in favor of gitignoring claude-code/ as build staging.

Distribution happens from CI: a .claude-plugin/marketplace.json on main points Claude Code at the built plugin on a dedicated claude-code-plugin branch, which a publish job fast-forwards on every push to main using the built-in GITHUB_TOKEN (no App token or PAT, and its pushes don’t recursively trigger workflows). Users install via claude plugin marketplace add marcusrbrown/systematic. Along the way, two dangling skill references (ce:debug, ce:polish-beta) with no bundled directory were found and neutralized, and a new content-integrity check now hard-fails the build if any ce:<name> reference fails to resolve to a real skills/ce-<name>/ directory — closing off that class of broken reference for good. Validation is covered by tests/integration/claude-code.test.ts, which checks shared-core fidelity, artifact self-containment, and that the build never writes to src/.

The ce-plan skill’s Phase 1.1/1.3/1.5 research-agent dispatch instructions used a fake function-call form (task systematic:research:X(...)) that read as literal, executable code on any harness (#656). It’s rewritten as prose (Dispatch \systematic::` — pass …) matching ce-plan's own existing dispatch-instruction style. The qualified persona IDs themselves are unchanged: they're the canonical, phantom-validated cross-reference form that checkReferenceIntegritychecks againstagents//.md`, and a broader bare-name conversion was investigated and reverted specifically because it would have dropped that validation coverage.

Two solutions entries compound recent learnings. One captures why the ce-plan pseudo-dispatch fix above collapsed from a planned four-skill refactor plus a new content-integrity gate down to a five-line prose change: the qualified persona ID syntax was never the bug, only the fake-call form was (#657). The other closes out the harness-portability plan from v3.1.0, adding the neutral-v1 marker and migrated-set identifier gate patterns, documenting a unit-suite-rewrites-repo-file trap that caused a double re-review on #653, and cross-linking related warning-channel and dry-run-integration docs (#655).

Renovate’s pi-coding-agent bump to v0.80.7 uncovered a matched-pair dependency hazard: a bare lockfile re-resolve floated the transitive pi-ai package to v0.80.10, which dropped the getOAuthApiKey OAuth export the Pi CLI imports at startup, crashing dist/cli.js (#651). The fix pins pi-ai to the version-matched v0.80.7, and Renovate is now configured to group the @earendil-works packages together so future bumps raise one matched PR instead of letting the pair drift independently.

  • build: update OpenCode to v1.18.2 (#659)
  • build: update OpenCode to v1.18.1 (#654)
  • chore(deps): update dependency @biomejs/biome to v2.5.4 (#658)

v3.1.0…v3.2.0

Published 2026-07-17 · Updated 2026-07-17 · View on GitHub

Harness-portable skills — the using-systematic bootstrap and its dependent skills now describe capability resolution in neutral terms instead of assuming OpenCode-specific primitives, so the same skill bodies can run correctly on other harnesses (starting with Pi).

feat(skills): harness-portable skills — capability profiles, neutral spine, identifier gate (#653) implements the B′-thin portability increment (plan 2026-07-16-001):

  • Two capability profiles (OpenCode, Pi) live under using-systematic/references/, covering the four capabilities that diverge across harnesses: subagent delegation, blocking user interaction, task tracking, and skill loading. Both are inlined into the controlled bootstraps via BootstrapDeps.profileBlock inside the existing <SYSTEMATIC_WORKFLOWS> zone, snapshot-pinned and double-run idempotent.
  • using-systematic was migrated to neutral capability-resolution routing, dropping the two OpenCode-specific routing lines now that the bootstrap carries the harness binding.
  • orchestrating-subagents was structurally rewritten to neutral delegation language — all task( and subagent_type occurrences (12 and 8, respectively) were removed while preserving the substance of the skill.
  • The blocking-question idiom gained a Pi binding at 24 sites across 16 skills, and ce-review’s internally drifted site was normalized to match.
  • A new content-integrity check (#13) bans harness-specific identifiers in migrated-skill bodies (flagged via the harness-portability: neutral-v1 metadata marker). The check is fence-aware, exempts profile files inside fences, and exempts the sanctioned idiom parenthetical.
  • New Pi harness proof scenarios cover profile presence and cross-profile absence, migrated-skill activation payload scans, and sequential-delegation markers.
  • HARNESSES.md is a new evidence-backed harness registry: every tool name maps to in-repo lines, cloned/installed source, or an authoritative URL, with unverified capabilities explicitly marked. The profiles and AGENTS.md are cross-linked to it, and it now ships in the npm package alongside the profiles that reference it.
  • The skill registry was regenerated (73 components).

Follow-up commits in the same PR hardened the work against ce:review findings: isMigratedSkill now keys off the harness-portability marker only (closing a path where unrelated non-string metadata could disable check #13), the idiom exemption is identifier-aware so only blocking-question identifiers are exempt on sanctioned lines, a 9th banned pattern (backtick question) was added per the plan spec, and readHarnessProfile now emits a stderr diagnostic on read failure without ever throwing. A portable bootstrap-snapshot fix normalizes the resolved skills directory to a <SKILLS_DIR> placeholder so the pinned bootstrap bytes stay machine-independent, and a docs fix stops the unit suite from silently downgrading configuration.mdx’s $schema example from v3 to v2 on every local run — the generator test now runs against a temp copy and asserts the repo file is untouched.

  • dev: update OpenCode to v1.18.0 (#652)
  • deps: update fro-bot/agent to v0.93.1 (#650)

v3.0.3…v3.1.0

Published 2026-07-17 · Updated 2026-07-17 · View on GitHub

A config-loading regression on v3 could brick agent registration entirely for any workspace carrying a v2-era docs-category override. Once a removed agent category reached overlay validation, the strict category check failed hard, taking down the whole config hook instead of just the stale entry. This release mirrors the existing removed-names handling: known-removed categories are now warned about and dropped before strict validation runs, rather than causing a fatal failure (#649, c2851a9). Regression coverage was added for stale docs overrides, preserved agents, unknown categories, and valid category overlays to prevent recurrence.

v3.0.2…v3.0.3

Published 2026-07-17 · Updated 2026-07-17 · View on GitHub

The optional @opencode-ai/plugin peer dependency was still imported at runtime from skill-tool.ts, causing cache installs to fail with ERR_MODULE_NOT_FOUND for consumers who don’t have the SDK installed. This release eliminates the SDK’s identity helper and returns the tool definition directly, removing the runtime dependency entirely. An isolated --omit=dev install plus a bare-node import regression test now guard against this class of failure.

Follow-up review fixes corrected the placement of Bun’s custom failure messages (they belong on expect(actual, msg), not as a second matcher argument, so install/import diagnostics now surface on failure) and documented why the args double-cast is required — guarding against the SDK’s bundled-zod nominal incompatibility (#648).

The docs homepage and README still presented Systematic as OpenCode-only, even after v3.0.0 shipped the Pi extension. Both surfaces now name both harnesses: the homepage title, hero copy, and “not another chat UI” section reference OpenCode and Pi, and Quick Start gains a Pi Extension install path linking to the Pi harness guide. The README’s “What You Get” section names the second harness and corrects stale catalog counts (40+/50+ → 31/37), and Quick Install adds the Pi setup command (#646).

v3.0.0 shipped in #641, so the long-lived v3 integration branch was deleted. This release drops v3 from the pull_request branch filters in main.yaml, fro-bot.yaml, and codeql-analysis.yaml — filters that were added in #584 solely to give v3 PRs full CI and review coverage during the development window (#645).

  • deps: update fro-bot/agent to v0.93.0 (#647)

v3.0.1…v3.0.2

Published 2026-07-17 · Updated 2026-07-17 · View on GitHub

A follow-up patch to the v3.0.0 major release — hardening the release-notes tooling that shipped in v3.0.0 and finishing the post-tag schema cleanup that could only happen once the v3 tag existed.

The release-notes-narrative skill’s step-13 rollback gate previously asserted that a rewritten narrative body must be longer than the auto-generated body it replaced. That assumption broke on major releases: the v3.0.0 squash commit embedded its entire prose under BREAKING CHANGES in the auto-generated body (11,048 chars), so the correctly-rendered 4,394-char narrative was auto-rolled back by CI — the length gate rejected exactly the rewrite it was meant to protect (#644).

Step 13 now verifies the render contract structurally instead: the body must start with ## What's new, contain at least one recognized bucket heading, include the Compare link, and differ from the pre-edit snapshot. Length comparison is explicitly forbidden, with the v3.0.0 incident recorded as the rationale.

With the v3 tag now cut, the schema publishing pipeline moved off its v2-transition scaffolding. The published schema is now regenerated at docs/public/schemas/v3/ (byte-identical to latest/, with $id pointing at the v3 URL), and the tracked v2/ bridge copy was deleted. The release-gated v2-mirror cleanup step was removed from docs.yaml since the real directory deletion now supersedes that transition hack, and the configuration reference was regenerated so $schema examples cite v3 (including a hand-written v2 URL fix in the Schema and Autocomplete section). schema:drift now reports “up to date (v3)”; the docs build is green, all 85 schema tests pass, and typecheck/lint/content-integrity are clean (#643).

  • deps: update all non-major dependencies (#642)

v3.0.0…v3.0.1

Published 2026-07-17 · Updated 2026-07-17 · View on GitHub

Systematic 3.0.0 is the curation major: the bundled catalog is reshaped around the compound-engineering workflow core, the legacy conversion machinery is gone, and the same npm package now ships a second harness — the Pi coding agent.

The bundle is curated down to 31 skills and 37 agents (from 46 and 51). The Ruby/Every vertical (dspy-ruby, dhh-rails-style, andrew-kane-gem-writer, every-style-editor, ankane-readme-writer), peripheral integrations (rclone, gemini-imagegen, test-xcode, proof, feature-video, report-bug-ce, changelog, generate_command), stack-specific review personas (kieran-rails-reviewer, kieran-python-reviewer, dhh-rails-reviewer, julik-frontend-races-reviewer, schema-drift-detector, lint), duplicate standalone reviewers (security-sentinel, performance-oracle, data-integrity-guardian, data-migration-expert, cli-agent-readiness-reviewer), the Figma-dependent design agents, and the setup placeholder skill are removed. The todo trio (todo-create, todo-resolve, todo-triage) merges into a single todos skill, and writing-systematic-skills folds into writing-skills. (#611, #587)

Removed names fail soft. Referencing any removed skill or agent in disabled_skills/disabled_agents warns and is ignored instead of failing config validation, and the warning links the migration guide. Every removal is mapped to its replacement in the v3 migration guide. (#614)

The CC→OpenCode runtime converter and systematic convert CLI are removed (#612). Bundled content ships pre-normalized; the converter had been a no-op on every load since 2.32. The skill deprecation-warning machinery and the deprecated: frontmatter contract go with it.

Pi coding-agent harness support. The same @fro.bot/systematic package now loads in Pi via a pi manifest (extensions, skills): bundled skills surface as native Pi skills, systematic_skill resolves skill content through the shared resolver, the using-systematic bootstrap is injected into every session, and a new systematic_delegate tool runs bundled agent personas as in-process child sessions — fail-closed on unknown personas, capped at 20 turns, with least-privilege tool allowlists derived from each persona’s frontmatter. A setup --harness opencode|pi CLI command writes the project-local config for either harness atomically, with backup and idempotent re-runs. Where Pi parity honestly ends (no systematic.json config consumption, no permission gating in Pi 0.80.6) is documented in the Pi harness guide. (#623–#638)

The Pi integration is proven against the real runtime: an integration suite spawns the actual Pi CLI in RPC mode with a mocked model and asserts extension load, skill discovery, skill resolution, bootstrap injection, and persona delegation end-to-end from the packaged tarball. (#637)

The v3 migration guide maps every removed skill and agent to its replacement and covers the converter removal and config cleanup. The published JSON Schema moves to schemas/v3/ (the config $schema example now points at schemas/latest/).

  • deps: OpenCode 1.17.20, semantic-release 25.0.7, fro-bot/agent v0.92.1, CodeQL action v4.37.1, setup-node v6.5.0, and bfra-me/.github v4.16.37 updates.

v2.33.3…v3.0.0

Published 2026-07-14 · Updated 2026-08-18 · View on GitHub

A security fix for Pillow, plus a steady stream of tooling and dependency maintenance.

Pillow’s minimum version floor moves to 12.3.0, closing off resolution of versions vulnerable to five decompression-bomb / command-injection advisories (GHSA-8v84-f9pq-wr9x and related PIL PcfFontFile, FontFile, BdfFontFile, GdImageFile, and WindowsViewer issues; PYSEC-2026-2253 through 2257) that remained reachable under the previous >=12.2.0 constraint. 12.3.0 is the first Pillow release that patches all five advisories, and the bump directly addresses the OSSF Scorecard Vulnerabilities check flagged by code-scanning alert #28.

  • dev: update OpenCode from v1.17.14 through v1.17.18 (#599, #601, #606, #607, #608)
  • dev: update semantic-release to v25.0.6 (#619)
  • deps: update fro-bot/agent from v0.84.0 through v0.88.0 (#595, #598, #600, #602, #604, #605, #610, #613, #616)
  • deps: update bfra-me/.github to v4.16.35 and v4.16.36 (#597, #609)
  • deps: update github/codeql-action action to v4.37.0 (#596)
  • dev: update all non-major dependencies (#603)

v2.33.2…v2.33.3

Published 2026-07-07 · Updated 2026-07-07 · View on GitHub

Discovered skills (a user’s or project’s own skills, registered as commands) were being labelled with the (Systematic - Skill) prefix, which falsely implied that Systematic had authored them. That prefix is now dropped entirely for discovered skills, and the command instead surfaces the skill’s own description as-is.

Bundled Systematic skills-as-commands also had their labelling tightened: the - Skill qualifier is removed, so their prefix now reads simply (Systematic), matching how bundled plain commands are already labelled. isSystematicCommandConfig was updated to recognize only the (Systematic) prefix going forward — the retired (Systematic - Skill) label needs no migration path, since OpenCode applies config-hook mutations in memory on each load and never persists them, so a previously-injected entry can never reappear in existing config. Discovered commands are consequently left unmarked and are added if absent rather than refreshed or cleaned across reloads, which is safe because every launch rebuilds the command config from disk and simply omits any skills that were deleted (#594).

v2.33.1…v2.33.2

Published 2026-07-07 · Updated 2026-07-07 · View on GitHub

A follow-up patch to discovered-skill command registration (#592): disabled_commands now actually suppresses discovered-skill commands, a single-read fix removes a redundant file read, and a CodeQL-flagged TOCTOU race in the same code path is closed.

Discovered skills register as slash commands under their bare name, but collectDiscoveredSkillsAsCommands was ignoring the disabled_commands field, so there was no way to suppress a single discovered skill’s command short of turning off the whole feature. The fix filters discovered-command emission by disabled_commands — the free-form field that governs command names — while leaving the stricter disabled_skills bundled-name enum untouched. The configuration guide now documents the split: disabled_skills governs bundled skills, disabled_commands governs discovered-skill commands.

The same follow-up also closed a file-system race CodeQL flagged (js/file-system-race) in the discovered-skill file read: a statSync check-then-readFileSync pattern left a time-of-check/time-of-use window. The pre-check is dropped in favor of reading the file directly — a directory throws EISDIR and a missing path throws ENOENT, both already handled by the existing catch, so the same skip behavior holds with one fewer syscall and no race window.

As a performance side effect, command-only discovered skills (e.g., skills with model invocation disabled) previously read their SKILL.md twice — once via extractFrontmatter during discovery, which discarded the body, and again via readFileSync in the inline command path. extractFrontmatterFromContent was split out of extractFrontmatter so the file is read once in toDiscoveredSkill, with the body carried on DiscoveredSkill for the inline command path to reuse.

v2.33.0…v2.33.1

Published 2026-07-07 · Updated 2026-07-07 · View on GitHub

Skills discovered from user and project locations can now surface as /slash commands, not just as model-invocable tools (#592, 142c090). A new discovery pass (src/lib/discovered-skills.ts) walks the same six roots OpenCode itself uses to find skills — global ~/.claude and ~/.agents, project .claude/.agents directories walked up to the worktree root, and .opencode config dirs — applying upstream’s own last-write-wins precedence (.opencode beats .claude/.agents beats global) so the command that wins matches what OpenCode’s skill tool would resolve. Discovered skills are gated behind a skills_as_commands toggle (on by default): model-invocable skills get a one-line shim that loads the skill via the native skill tool with $ARGUMENTS passed through as data, while command-only skills (those with model-invocation disabled) get the SKILL.md body inlined directly. Each generated command carries a (Systematic - Skill) ownership marker so re-runs stay idempotent and any user-defined command with the same name always wins. A follow-up review pass tightened the drop predicate for orphaned commands, honored user-invocable: false parity with bundled skills, bounded the discovery walk so it never climbs past the worktree root when there’s no git root, and filled in precedence and edge-case test coverage.

PRs targeting the long-lived v3 branch now get the full check suite and Fro Bot review: v3 was added to the pull_request.branches filter across the main, fro-bot, and CodeQL workflows (#584, 268e996). Push triggers stay scoped to main, so the release job still never runs against v3 — work in progress there can’t accidentally trigger a publish.

Plan housekeeping this cycle: a future-dated plan artifact (dated 2026-07-13, a week ahead of when it was written) was corrected to 2026-07-06, with its internal date, origin, and superseded_* cross-references fixed to match (#591, 75187a3). Separately, stale v3-adjacent plan statuses were reconciled: the removed-name config-safety plan had been left marked executed-pending-pr despite having shipped in #534 (v2.32.0), so it’s now marked completed with provenance, and an older v3-compatibility-cleanup plan was marked superseded by the newer v3-cleanup-release brainstorm, with superseded_at/superseded_reason frontmatter added for consistency with other superseded plans (#583, c02a0dfd).

The two worst noExcessiveCognitiveComplexity offenders in the codebase, validateFieldExamples (cognitive complexity 41) and extractFrontmatter (cognitive complexity 25), were split into file-local helper functions while preserving exact behavior, ordering, and exported signatures (#582, 77fbd7f). Repo-wide complexity warnings dropped from 6 to 4.

  • deps: Update fro-bot/agent to v0.83.1 (#589) and v0.83.0 (#581); update bfra-me/.github to v4.16.34 (#588).

v2.32.2…v2.33.0

Published 2026-07-04 · Updated 2026-07-04 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • security: bump Pillow minimum version to patch known CVEs (#576) (015e665)
  • deps: update bfra-me/.github to v4.16.32 (#567) (65c413e)
  • deps: update bfra-me/.github to v4.16.33 (#572) (401b9e7)
  • deps: update fro-bot/agent to v0.79.0 (#563) (b972e5f)
  • deps: update fro-bot/agent to v0.79.1 (#564) (c11a628)
  • deps: update fro-bot/agent to v0.79.2 (#568) (1c468a8)
  • deps: update fro-bot/agent to v0.79.3 (#569) (f7ddff0)
  • deps: update fro-bot/agent to v0.79.4 (#570) (6652e7f)
  • deps: update fro-bot/agent to v0.80.0 (#573) (b5590fd)
  • deps: update fro-bot/agent to v0.81.0 (#574) (21bb7a4)
  • deps: update fro-bot/agent to v0.82.0 (#578) (5c9bdf5)
  • deps: update github/codeql-action action to v4.36.3 (#575) (1dd87cd)
  • dev: update all non-major dependencies to v2.5.0 (#538) (378602b)
  • dev: update dependency @biomejs/biome to v2.5.2 (#579) (a7505c8)
  • dev: update dependency playwright to v1.61.1 (#562) (256dc01)
  • lint: update biome.json schema to 2.5.1 to match CLI (#571) (c2c43fd)

Published 2026-06-26 · Updated 2026-06-26 · View on GitHub

Biome 2.5.0 introduced two new error-level lint rules that would have blocked the pending @biomejs/biome dependency update (PR #538) from passing CI. This release pre-emptively fixes both violations before the dependency bump lands:

  • lint/a11y/noSvgWithoutTitle in docs/public/favicon.svg — Biome now requires SVG elements to carry an accessible title. Added <title id="favicon-title">Systematic</title> and the corresponding role="img" aria-labelledby="favicon-title" attributes so screen readers can identify the favicon.
  • lint/complexity/noImportantStyles in docs/src/styles/custom.css — Three !important declarations on .install-title (for margin, font-size, and color) were used to override Starlight’s heading specificity. Replaced with the higher-specificity selector .install-header .install-title, which beats the Starlight h3 rule without !important. Visual appearance is unchanged.

Merging this fix first unblocks the Biome upgrade PR from failing the Lint check.

  • dev: OpenCode updated through v1.17.4 → v1.17.9 (#536, #541, #542, #544, #552, #557)
  • deps: fro-bot/agent updated through v0.64.2 → v0.78.0 (14 Renovate bumps across #535–#561)
  • dev: Playwright monorepo updated to v1.61.0 (#547)

v2.32.0…v2.32.1

Published 2026-06-15 · Updated 2026-06-15 · View on GitHub

Config validation now handles the full lifecycle of bundled skill and agent names — including names that have been removed in past releases. Previously, listing a no-longer-bundled name in disabled_skills or disabled_agents would fail validation and prevent plugin load, effectively bricking setups that had disabled something Systematic later cleaned up.

v2.32.0 introduces a removed-names mechanism with three coordinated layers:

  • Schema acceptance: The JSON Schema generator now includes the removed-names list in the enum for disabled_skills and disabled_agents, so editors and runtime stay in sync. While the list ships empty today, the schema will reflect any future additions without requiring editor configuration updates.
  • Validation acceptance: Removed names are accepted during config validation alongside current bundled names, maintaining the strict rejection of genuinely-unknown names.
  • Load-time cleanup: After validation, removed names are silently dropped from the effective disabled lists and a per-load [systematic] warning identifies each stale entry. Raw config is preserved for merge precedence; the dedup is stateless per load.

A content-integrity gate enforces that removed names never overlap current bundled names, preventing accidental misclassification as a name moves from active to removed.

  • deps: Synced biome.json $schema to 2.4.16 to match the pinned @biomejs/biome CLI version — a mismatch caused the newer CLI to treat it as a config deserialize error and fail local lint.
  • deps: Renovate non-major dependency updates to v4.16.26.
  • deps: Updated fro-bot/agent to v0.64.1.

v2.31.1…v2.32.0

Published 2026-06-14 · Updated 2026-06-14 · View on GitHub

The orchestrating-subagents skill has been updated to match the current behavior of OpenCode 1.17.6. A prior version of the skill documented a task_status polling tool that OpenCode has since removed. In OpenCode’s current model, background subagents (enabled via OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS) push their results into the parent session automatically on completion — there is no status tool to poll. The skill’s background-dispatch guidance, failure/retry instructions, quick-reference section, and common-mistakes list have all been rewritten to describe this push-notification model accurately.

The same PR also adds an optional setup recommendation: enabling OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true. The flag is experimental but stable in recent OpenCode versions, and without it Systematic falls back to foreground dispatch.

Plan documents were reconciled with shipped reality after v2.31.0: the agent temperature hardening plan now records its v2.29.0 provenance, the skill frontmatter tune-up plan is marked completed (shipped in v2.31.0), and the promotion-and-growth plan is marked completed with remaining ecosystem-listing work reframed as externally tracked upstream work.

Four test names in the JSONC-precedence suite carried AE1/AE2/AE3 prefixes that leaked internal planning taxonomy into the shipped test file. These prefixes have been stripped, leaving only the behavioral descriptions.

A solutions document was added capturing a durable lesson from the skill frontmatter tune-up work: scripts/content-integrity.ts has no general non-failing warning channel — every check other than allowlist warnings counts toward totalViolations() and fails CI. This makes “advisory warning” checks infeasible without building new plumbing. The doc records the end-to-end wiring checklist, the fence-aware body-scan pattern, and the meta-lesson: ground the mechanism a plan relies on, not just the intent.

  • build(dev): OpenCode updated through v1.16.0, v1.16.2, v1.17.0, v1.17.1, v1.17.2, and v1.17.3.
  • build(dev): semantic-release monorepo updated to v25.0.4.
  • deps: fro-bot/agent updated through v0.56.1, v0.56.2, v0.57.0, v0.58.0, v0.59.0, v0.59.1, v0.60.0, v0.61.0, v0.62.0, v0.63.0, and v0.64.0.
  • deps: Miscellaneous non-major dependency updates (v4.16.24, v4.16.25, v24.13.1, v24.13.2).

v2.31.0…v2.31.1

Published 2026-06-07 · Updated 2026-06-07 · View on GitHub

The ce:compound-refresh skill now declares an argument-hint in its frontmatter, making its $ARGUMENTS interface visible to callers and the OpenCode command surface. This skill accepts a mode:autofix flag and an optional docs/solutions/ scope hint — both are now documented where they can actually be discovered. Beyond the hint itself, this change establishes which frontmatter fields are enforced: a new enforcement column in writing-systematic-skills/references/foundation-conventions.md clarifies that allowed-tools is parsed but not permission-gated, while argument-hint is now subject to content-integrity checking. A new guard fails any skill that references $ARGUMENTS outside fenced code blocks without declaring argument-hint, preventing the gap from recurring. The check correctly strips fenced code blocks first, so skills that merely document $ARGUMENTS in an example are not flagged.

A new solutions doc captures the reusable lessons from the npx skills install command rollout (v2.30.0–v2.30.1): how to make a load-side-effect generator testable by exporting the helper and guarding the entrypoint behind import.meta.main; driving the --skill selector from frontmatter name values; two MDX traps (a <name> placeholder in a table cell parses as JSX and breaks the table; copy buttons only attach to fenced code blocks, never inline code in table cells); and verifying rendered docs against built HTML rather than source or a blocking dev server. The doc cross-references the related MDX, codegen, and verification docs rather than duplicating them.

The release pipeline no longer fails when the release-notes narration dispatch confirmation times out. Previously, scripts/dispatch-release-notes.sh would exit 1 if it could not confirm the dispatched Fro Bot run within the poll budget — even though the dispatch had already succeeded and the narration had run. This happened on v2.30.1: the release published and the body was narrated correctly, but the job showed red because GitHub surfaced the dispatched run after the poll window closed. A successful gh workflow run call means the dispatch was accepted; failing to observe the run is an observability gap, not a dispatch failure. The confirmation timeout now emits a ::warning:: and exits 0. The poll budget was also bumped from 90s to 180s to reduce the race for future releases.

  • deps: fro-bot/agent updated to v0.55.6 (three security hardening fixes: IPv6 literal egress bypass, DNS resolution timeout, and compose topology guard).

v2.30.1…v2.31.0

Published 2026-06-07 · Updated 2026-06-07 · View on GitHub

The npx skills install section in the documentation had two rendering problems. A <name> placeholder in a table cell was being parsed as a JSX tag, breaking the “Useful flags” table. Inline-code cells in that table also lacked copy buttons, despite the surrounding copy claiming they did. The fix replaces the broken table with the same install-path command blocks used on the homepage — every command is now a real, copyable code block.

The “Choosing an install path” blockquote was also removed; it rendered as an out-of-place italic quote box. Its guidance is now expressed as clean intro prose under each install path, making it clear what the plugin installs and what the npx skills path installs (and doesn’t). The plugin remains the primary, recommended installation path throughout.

  • deps: Updated fro-bot/agent to v0.55.5 (#499).
  • dev: Updated all non-major dependencies to v24.13.0 (#500).

v2.30.0…v2.30.1

Published 2026-06-07 · Updated 2026-06-07 · View on GitHub

The docs site now surfaces npx skills as a first-class, portable install path alongside the OpenCode npm plugin. Previously, Systematic’s installation story pointed exclusively at @opencode/systematic, which is an OpenCode-specific runtime. Skills themselves are harness-agnostic Markdown content that work in any agent environment — OpenCode, Claude Code, Cursor, Copilot, or any other harness. The npx skills add marcusrbrown/systematic command installs that content directly from this repo, no registry required.

The homepage now presents a dual install-path block with chooser cues to help readers pick fast: “OpenCode, full runtime” for the npm plugin (still the recommended path for the complete OpenCode experience), and “Any harness, skills only” for npx skills. The Installation page gains a dedicated secondary section with a scannable flag table. The README Quick Install section reflects both paths. Every non-deprecated skill reference page now carries a copyable npx skills add marcusrbrown/systematic --skill <name> command, auto-injected by the docs generator — deprecated skills are correctly excluded and the generator change is covered by nine new unit tests.

A new best-practices solution doc captures the converter-injected default hardening pattern that emerged across v2.27.0 (agent mode) and v2.29.0 (agent temperature). Both cases followed the same shape: derive a runtime-injected default’s resolved value mechanically from the real inference function, write it explicitly into frontmatter, change the runtime to fill-if-absent, and add a content-integrity gate that requires the value to be usable — not merely present.

Two lessons are encoded for future reference. First, zero-behavior-change must be proven mechanically by deriving the expected value for every agent and asserting zero mismatches, not assumed. Second, a presence-only gate is a false lock: the runtime treats present-but-invalid values as absent and falls back anyway, so the gate must verify usability. The doc cross-references the two related overlay and gate best-practices docs.

  • deps: update fro-bot/agent to v0.55.4 (#497)

v2.29.0…v2.30.0

Published 2026-06-07 · Updated 2026-06-07 · View on GitHub

Agent temperature is now explicit in every bundled agent’s frontmatter and respected by the runtime, removing a hidden inference heuristic that had been silently overwriting any hand-authored value.

All 51 bundled agents now declare an explicit temperature:. The 37 that previously relied on runtime inference have their resolved value written into frontmatter, derived mechanically from the same function the runtime used, so no agent’s effective temperature changes in practice. The config hook now reads that explicit value instead of always overwriting it, preserving the precedence chain: user overlay > explicit frontmatter > inferred fallback.

A content-integrity gate enforces the invariant going forward: every bundled agent must declare an explicit, finite-number temperature:, and the check fails closed on malformed frontmatter. This brings temperature to parity with mode, model, and color — each agent’s value is now auditable in source rather than computed invisibly at load time.

  • deps: Updated fro-bot/agent to v0.55.1, v0.55.2, and v0.55.3 (#492, #493, #494).

v2.28.0…v2.29.0

Published 2026-06-05 · Updated 2026-06-05 · View on GitHub

The new orchestrating-subagents skill gives agents a portable, OpenCode-native primitive for coordinating both serial and parallel subagent work. It centres on task() dispatch as the default mechanism — foreground dispatch that works in any context — while documenting background subagents and task_status as experimental, gated surfaces for environments that support them.

Beyond the dispatch primitive itself, the skill covers the full coordination lifecycle: how to divide work across subagents without file overlap, how to track git ownership when multiple agents write concurrently, how to synthesise results from independent runs, and how to handle retry when a subagent stalls or fails.

The skill ships alongside a v3 compatibility cleanup plan that will remove converter-era compatibility surfaces and deprecated orchestration guidance now that the replacement is in place. Bundled skill surfaces, the OCX registry, and cloned OpenCode source metadata (pinned to v1.15.10) were all updated in the same change so the skill is discoverable immediately. (#491)

Two long-running plans — the upstream ce:brainstorm + ce:plan merge and the agent-mode explicit hardening work — are now marked completed with release provenance. The merge shipped in v2.26.0 and the hardening work shipped in v2.27.0; this change closes the loop in the plan tracker. No behaviour changes. (#490)

  • deps: Bump all non-major dependencies to v0.55.0 (#489)

v2.27.0…v2.28.0

Published 2026-06-05 · Updated 2026-06-05 · View on GitHub

Two hardening-and-learning changes: one closes a latent converter dependency before it becomes a breaking change in v3.0.0; the other turns a failed detection attempt into a permanent correctness rule.

mode: subagent is now declared explicitly on all 51 bundled agents. Previously, 36 agents relied on the OpenCode runtime converter to fill in mode: subagent as a default at load time — an invisible dependency that would silently break when the converter is removed in v3.0.0. Without an explicit mode, those agents would fall back to OpenCode’s native default (all) and appear as primary agents in the agent picker rather than staying hidden as background workers.

This is a zero-runtime-behavior-change hardening. The converter already resolves these agents to subagent, so making the field explicit changes nothing today while severing the converter dependency for the future. To lock in the invariant, a new checkAgentMode gate in scripts/content-integrity.ts fails CI if any bundled agent is missing an explicit mode: subagent, sets a non-subagent value, or has non-object frontmatter. A converter-equivalence test mechanically proves the change is behavior-preserving by resolving agent config both with and without an explicit mode and asserting the outputs are identical.

The PR also records a tracked audit of every other field the converter injects — notably temperature, which is computed per-agent via a name/description heuristic and represents an equally high-risk dependency for v3.0.0. Resolving the temperature dependency is out of scope for this patch; the audit exists so it is not forgotten.

A new solution doc under docs/solutions/ captures the undecidability lesson from the content-integrity verification work: some YAML frontmatter problems cannot be detected by parse-diff analysis alone.

The concrete case: a truncating comment (problem: cache miss # under load, where the author intended the full string including # under load) and a legitimate inline comment (date: 2026-01-01 # created) are byte-identical to the YAML parser — both parse to the text before the #. No amount of parse-diff analysis can distinguish “lost content” from “intentional comment.” Rather than ship a heuristic that would silently misclassify edge cases, the ban rule approach was taken: unquoted inline comments in solution-doc frontmatter are banned outright. This collapsed the detector to a simple lexical rule and removed approximately 50 lines of parse-diff guessing that could never have been correct.

The doc records the undecidability, the reasoning for the ban, and the general principle: when a detection problem is provably undecidable at the data level, a clear bright-line rule beats a heuristic that quietly gets edge cases wrong.

v2.26.0…v2.27.0

Published 2026-06-05 · Updated 2026-06-05 · View on GitHub

The ce:brainstorm and ce:plan skills have been updated with the strongest improvements from the upstream Compound Engineering plugin, adapted to Systematic’s conventions and kept markdown-only throughout.

ce:brainstorm gains a Phase 2.5 Synthesis Summary — a scope checkpoint that fires before the requirements doc is written. This lets scope be confirmed or corrected before research is spent, and pairs cleanly with the existing Phase 3.5 Document Review: Phase 2.5 is the scope gate (before writing), Phase 3.5 is the quality review (after writing), with no overlap between them. The skill also picks up markdown rendering guidance (markdown-rendering.md) and a section-rendering layer (brainstorm-sections.md) that govern how output is structured without changing the content contracts.

ce:plan gains three focused additions. Anti-Expansion (step 3.7) routes tangential “while we’re here” work to a Deferred section instead of letting it bloat active plan units — keeping plans scoped to what was actually decided. Scope synthesis adds two mutually exclusive paths at plan stage: a solo-mode path when there is no origin document and a brainstorm-sourced path when one exists. The same markdown rendering and section-rendering layer from ce:brainstorm is applied here as well, giving both skills a consistent presentation layer.

The Phase 3.5 Document Review, requirements-capture and Core Plan Template content contracts, and visual-communication guidance are preserved unchanged. A pre-existing dangling visual-communication.md reference in ce:brainstorm was also resolved, and slash-command residue in skill prose was cleaned up so references use the portable ce:work form. The registry was regenerated after the merge. (#486, 3b9d0e6)

v2.25.0…v2.26.0

Published 2026-06-05 · Updated 2026-06-05 · View on GitHub

ce:review gains an independent finding-validation pass. A new Stage 5b validator runs between merge and synthesis: each P0/P1 or requires_verification finding is independently re-checked, and rejected findings are surfaced in a “Filtered (not validated)” group rather than silently dropped — so a weak finding is visible and accountable instead of disappearing (#485).

The same release adds a content-integrity check for solution-doc frontmatter. Unquoted inline YAML comments (a # with leading whitespace or at value-start) are silently stripped by YAML parsers and risk data loss, so the check now flags them. Solution docs are scanned through a dedicated target set isolated from banned-pattern enforcement, the ce-compound category enums were tightened, and frontmatter-block extraction was refactored into a shared extractFrontmatterBlock helper so the parse-safety scan and parseFrontmatter no longer carry divergent delimiter regexes.

The bulk of this release is a promotion-and-growth push that turned the docs site into a real product landing surface. The homepage was redesigned around a custom hero, a live stats banner, and an aligned feature grid built on the existing OKLCH theme tokens — replacing the stock Starlight splash and fixing long-standing CSS issues where invalid :global() selectors in MDX style tags were silently dropped. A build-time stats emitter walks skills/, agents/, and the registry to publish live skill/agent/component counts and a git-tag-resolved version, so the homepage never renders stale or broken numbers. Quick Start was merged into a single canonical Installation page (with a redirect from the old URL), structured SEO metadata (Open Graph, Twitter cards, JSON-LD) was added, and a Privacy page now documents the cookie-free, self-hosted, DNT-respecting, no-PII analytics posture. The interior reference and guide pages were restyled to match the homepage’s restrained list-and-spacing language, and a stray OCX mention was removed from the homepage.

Several engineering learnings were captured alongside the docs work: an Astro Steps HMR regression and CSS-liveness verification guidance, a refreshed live-server QA learning emphasizing that an HTTP 200 is not a render signal, and updated static-preview guidance. The promotion-and-growth plan was reconciled against shipped provenance to track which units actually landed.

The docs analytics wiring was activated end to end: the Umami website id is now threaded into the docs build step (GitHub Actions does not auto-expose repo variables to run steps, so analytics had never actually fired), and the Privacy page placeholders were replaced with live metrics.fro.bot facts — no raw IPs or personal identifiers stored, a monthly-rotating one-way hash for visitor counting, locally-derived approximate location, and Do-Not-Track visitors not recorded.

The two previously-separate Fro Bot workflows (fro-bot.yaml and fro-bot-autoheal.yaml) were consolidated into a single workflow handling all three operating modes — PR review, daily autohealing, and weekly maintenance — with inline prompt routing instead of a separate resolve-prompt job (#446). The release-notes-narrative automation contract is preserved verbatim: workflow_call still accepts the prompt and correlation-id inputs and resolves them at highest precedence. Follow-up changes documented two subtle invariants inline for future maintainers: why the workflow_call/workflow_dispatch prompt branches must precede the mode-gated branches (so external prompt-only callers like the release-notes automation aren’t silently captured), and why explicit fork-detection exists only for issue_comment events (the only PR-adjacent path where github.event.pull_request is null even when the issue is a PR).

Editor tooling was kept current with three OpenCode bumps (v1.15.11 through v1.15.13).

Interior documentation pages were brought in line with the homepage design language — Markdown tables now use row dividers instead of a heavy outer border and solid header fill, blockquotes lost their accent side-stripe, and a dead .card/.link-card rule that no Starlight component rendered was removed.

Astro was bumped to >=6.1.3 to fix a dev-server crash in Starlight’s <Steps> component. Astro 6.0.x had an HMR regression where editing an unrelated file made Astro.slots.render() return escaped text instead of an ordered list, throwing on reload. This is a docs-only dependency; the published package is unaffected (#463).

  • A reproducible “with and without Systematic” eval harness, task prompts, rubrics, recorded transcripts, and a running-with-without-evals skill, plus a demo guide built from real recorded sessions (#455).
  • deps: Renovate bumps across fro-bot/agent (v0.46.0–v0.52.1), bfra-me/.github (v4.16.21–v4.16.23), actions/checkout (v6.0.3), github/codeql-action (v4.36.1), and several non-major dependency rollups (through v0.54.2).
  • chore: lint auto-fixes from an autohealing run.

v2.24.0…v2.25.0

Published 2026-05-27 · Updated 2026-05-27 · View on GitHub

Adds a docs:verify script that runs the exact three-command sequence the CI Docs Build job runs — bun install --frozen-lockfile, bun run --cwd docs playwright install --with-deps chromium, and bun run docs:build — so a docs-framework Renovate PR (Starlight, Astro, expressive-code, etc.) can be locally pre-verified before approval.

The motivation is concrete: PR #444 (Starlight 0.38→0.39) cleared every local gate — typecheck, lint, content-integrity, registry-drift, unit tests — and only failed at CI’s Docs Build step, because Starlight’s astro:config:setup hook runs exclusively under a real Astro build. The fix was straightforward, but the round-trip to CI cost time that docs:verify eliminates. This was the second such incident in two weeks.

The script is a single chained shell command rather than a separate shell file: zero new files, zero new dependencies, zero new documentation surface beyond the AGENTS.md line that names it. On a hot cache the whole run takes ~5 seconds; on a cold cache the Playwright Chromium download dominates (~30–60 s).

v2.23.6…v2.24.0

Published 2026-05-27 · Updated 2026-05-27 · View on GitHub

Starlight 0.39.0 removed the { label, autogenerate } shorthand syntax for sidebar groups. Without a corresponding migration, the docs site would fail to build with a config-validation error.

This release updates @astrojs/starlight to ^0.39.0 and migrates the four affected sidebar entries — Getting Started, Guides, Skills, and Agents — to the new { label, items: [{ autogenerate: { directory } }] } shape that Starlight 0.39 requires. The Reference > Configuration entry and the top-level Reference group were already using compatible forms and needed no changes.

The updated docs build emits 110 pages, pagefind indexes 112 HTML files, and the sitemap is generated cleanly with no config-validation warnings.

v2.23.5…v2.23.6

Published 2026-05-26 · Updated 2026-05-26 · View on GitHub

Security hygiene and documentation completeness — a defense-in-depth fix for a long-standing static analysis warning, companion documentation for the May sprint arc, and a set of plan records updated to reflect what actually shipped.

A CodeQL js/incomplete-multi-character-sanitization alert (#31) on docs/scripts/transform-content.ts had been stable in the weekly maintenance report for over five weeks. The cleanDescription helper was using a single-pass replace(/<[^>]+>/g, '') strip — the textbook shape the analyzer flags, because adversarial input like <<tag> survives one pass with the leading < intact.

The trust boundary here is real: this helper only runs against committed SKILL.md and agent frontmatter description fields, never against runtime user input. The fix iterates the strip to a fixed point so any residue from the first pass is caught on the next, and a comment above the loop documents the constraint explicitly for future contributors who might reach for the helper in a higher-trust context. No build output changed; docs:build still emits the same 110 pages.

Two documentation efforts closed out the May 22–23 sprint arc:

Plan status reconciliation (#438): Three plan docs from the sprint were still marked status: active despite all their work shipping in merged PRs. The fix sets each to status: completed with a shipped: block carrying the PR number, release tag, and date. The CI automation plan doc also enumerates the four hotfix PRs (#431–#434) that followed the initial merge, giving future readers a complete picture of the delivery sequence.

Solutions compound (#437): Two solution docs were refreshed with verified-in-production content from the five-PR chain (PRs #430–#434) that landed end-to-end CI release-notes-narrative automation. Key updates include:

  • The architecture doc’s trigger-chain block now reflects the final scripts/dispatch-release-notes.sh + timestamp-based identification design, replacing the original inline successCmd + log-scan approach.
  • The “Correlation-token-based polling” decision was replaced with “Timestamp-based polling with correlation as audit anchor,” documenting the v2.23.3 production failure (Fro Bot bootstrap time exceeding the 90s log-scan budget) and the v2.23.4 fix (DISPATCH_EPOCH + gh run list createdAt filtering).
  • A new “Production Verification” section captures the four-failure-mode table and the structural lesson: mock-based integration tests cannot model real-world Lodash rendering, GitHub API contract validation, or agent runtime characteristics.
  • The semantic-release-body-ingestion-myth doc was updated with a pointer to the v2 CI architecture and a clarification that the underlying myth remains true.
  • build(dev): Update OpenCode through v1.15.6 → v1.15.7 → v1.15.8 → v1.15.10 (#436, #439, #441, #442)
  • build(dev): Pin @semantic-release/exec to 7.1.0 (#435)
  • deps: Update all non-major dependencies (#440)

v2.23.4…v2.23.5

Published 2026-05-24 · Updated 2026-05-24 · View on GitHub

The release-notes-narrative automation chain gains its fourth consecutive hotfix, this time replacing the log-scanning strategy for identifying dispatched Fro Bot runs with a timestamp-based approach.

v2.23.3 (#433) had resolved the HTTP 422 input-validation problem and Fro Bot’s dispatch was actually firing. But the polling loop in dispatch-release-notes.sh timed out after 90 seconds trying to match the dispatched run by scanning its early log lines for the correlation token. The token never appeared within that window because the Fro Bot OpenCode agent has a substantial bootstrap sequence — runner spin-up, full checkout, bun install, model/auth setup, and MCP server startup all happen before any prompt-derived content reaches the run’s logs.

The fix captures a DISPATCH_EPOCH timestamp immediately before gh workflow run, then polls gh run list --event=workflow_dispatch for the newest run whose createdAt is strictly greater than that epoch. Because gh run list reflects run-creation time rather than first-log time, the dispatched run is visible to the API as soon as it’s registered — long before the agent boots — so identification is reliable regardless of how long startup takes.

The correlation-id field is preserved as a secondary audit anchor. It’s still passed to gh workflow run and still declared in fro-bot.yaml, so it appears in the run’s inputs metadata for any future debugging session, but it is no longer the primary identification mechanism.

Test coverage was updated alongside the fix: makeRunListJson now accepts an optional createdAt argument and defaults to a far-future ISO timestamp so the default run is always selected by the timestamp filter; the scenario for correlation-via-log-scan was replaced with a “no run created after dispatch epoch” scenario (exit 1); and a new scenario was added for the newest-wins case when two runs have different future createdAt values. The suite grew from 19 to 20 passing tests.

A follow-up commit refreshed the block comment in dispatch-release-notes.sh (which still described the old log-scan strategy), updated the prompt body to drop the now-obsolete instruction to echo the correlation token, and renamed a stale test fixture suffix (scenario-18) to a scenario-agnostic name.

v2.23.3…v2.23.4

Published 2026-05-24 · Updated 2026-05-24 · View on GitHub

The third hotfix in the release-notes-narrative v2 automation chain resolves the final blocker preventing fully automated post-release narrative generation.

After v2.23.2 published (which fixed the missing dispatch-release-notes.sh script), the Release CI job was still failing with HTTP 422: Unexpected inputs provided: ["correlation-id"]. The root cause: dispatch-release-notes.sh passes a UUID correlation token as a structured -f correlation-id=... workflow dispatch field so that the polling loop can identify the correct Fro Bot run, but fro-bot.yaml had never declared correlation-id as a known input. GitHub’s Actions runtime validates every field in a workflow_dispatch or workflow_call invocation against the workflow’s declared inputs: block and rejects any unrecognized name.

This fix adds correlation-id as an optional string input to both the workflow_dispatch and workflow_call entry points in fro-bot.yaml. The field is purely a polling correlation primitive — Fro Bot echoes it as its first log line so the dispatching script can scan early job output and match the run unambiguously, eliminating same-second collision risk. No existing entry point (PR comments, issue events, scheduled maintenance) is affected; they simply omit the field, which is valid for an optional input.

With this declaration in place, the end-to-end acceptance gate for v2 — where a published release automatically triggers Fro Bot to rewrite its notes — can proceed without operator intervention.

v2.23.2…v2.23.3

Published 2026-05-23 · Updated 2026-05-24 · View on GitHub

The release-notes-narrative v2 automation no longer crashes the Release job on bash parameter expansion. v2.23.0 and v2.23.1 both shipped to npm successfully but failed their Release job with SyntaxError: Unexpected token ':', because @semantic-release/exec renders the entire successCmd YAML block through lodash-es template() with no escape support — every ${...} in the bash script (including ${VAR:-default} parameter expansion and even ${...} inside comments) was being evaluated as a JavaScript expression.

The fix moves the dispatch logic out of the YAML scalar entirely. The successCmd: is now a one-line invocation of an external script:

successCmd: 'scripts/dispatch-release-notes.sh "${nextRelease.gitTag}"'

scripts/dispatch-release-notes.sh receives the target tag as $1 and is otherwise a normal shell script — no Lodash collision surface. The only template interpolation Lodash sees is the one we want: the target version from semantic-release context.

This is the third hotfix in the v2 automation sequence. The two earlier attempts (#430 introduced the inline successCmd; #431 tried to fix it with backslash escapes) failed because Lodash’s default template settings have no backslash-escape semantics — \${VAR} still evaluates VAR as JavaScript and just leaves the backslash as a literal character in the output. Verified empirically by running template('\\${VAR}')({}) locally and observing the same is not defined error.

The 19 integration tests in tests/integration/release-notes-ci.test.ts continue to cover the full dispatch chain: tag validation, correlation-token generation, polling fallback, conclusion-taxonomy classification (success, neutral, failure, cancelled, timed_out, action_required, skipped), security signals (HTTP 401/403, off-target release edits, body-integrity check post-write), and unexpected gh run watch exit codes.

The fourth hotfix in this chain (still in flight at PR #433) addresses a separate production failure surfaced by this release: gh workflow run rejected the dispatch with HTTP 422: Unexpected inputs provided: ["correlation-id"] because the fro-bot.yaml workflow did not declare correlation-id as a valid workflow_call/workflow_dispatch input. That fix adds the input declaration. v2.23.2’s release notes you are reading right now were rewritten manually using the v1 skill procedure.

v2.23.1…v2.23.2

Published 2026-05-23 · Updated 2026-05-23 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • release: escape bash ${VAR} for Lodash render in successCmd (#431) (d07b090)

Published 2026-05-23 · Updated 2026-05-23 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • release: automate release-notes-narrative skill via @semantic-release/exec (#430) (cbe4c33)

Published 2026-05-23 · Updated 2026-05-23 · View on GitHub

A new project-scoped skill at .agents/skills/release-notes-narrative/ that turns sparse semantic-release output into useful changelog narrative. The skill is loaded on demand by any agent to patch a published GitHub release body via gh release edit --notes-file, defending against two known release-notes-generator failure modes already observed on this repo: bare bucket bullets (semantic-release ingests only commit subject lines, never commit bodies or PR descriptions) and spurious closes [URL-fragment] autolinks (the generator misparses path#fragment substrings in commit bodies as Closes #N footers).

The skill ships as a 13-step procedure with a hardcoded bucket map mirrored from .releaserc.yaml, a calibrated thin-commit-body threshold for triggering PR-body enrichment, and a 4-condition AST-based autolink-strip allowlist with documented positive and negative examples. Three-layer defense for the live gh release edit step (pre-edit snapshot, preflight check, post-edit rollback) keeps blast radius bounded. Structural idempotence — same buckets, same Compare link, same referenced PRs across reruns — is the explicit guarantee; LLM-generated narrative prose is allowed to vary by run (#429).

This release is itself the first dogfood: the skill was applied to v2.20.5, v2.20.6, and v2.21.0 retroactively as acceptance evidence before merge, and the v2.22.0 release notes you’re reading now are the skill’s output.

v2.21.0…v2.22.0

Published 2026-05-23 · Updated 2026-05-23 · View on GitHub

Launch-surface cleanup — the first ~30 seconds a developer spends with this project. README, home page, Quick Start, config docs, and contributor docs now tell a coherent story instead of repeating each other.

AGENTS.md was carrying three audiences in 188 lines. Split into:

  • ARCHITECTURE.md — bird’s eye overview, codemap, invariants, data flow, cross-cutting concerns
  • STRUCTURE.md — directory layout, per-directory purposes, naming conventions, where to add new code
  • AGENTS.md — slimmed to 68 lines of contributor conventions plus a routing table that points at the other two

400 lines of tables + Mermaid diagram + CLI reference → 75 lines of problem-first prose. The detail moved to the docs site where it belongs.

  • Home page rewritten as a real product landing page — concrete capability cards, the actual workflow as Steps, Quick Start snippet, and a “What Systematic Is Not” honesty section.
  • New getting-started/quick-start.mdx — 5-minute walkthrough from opencode.json install to a first completed workflow (brainstorm → plan → work → review). Uses a canonical example task across every surface so the story stays consistent.

Two overlapping pages (getting-started/configuration + reference/systematic-config) → one human-owned reference/configuration page with auto-generated regions injected between sentinel markers. Legacy URLs redirect to the new location.

.agents/skills/generating-project-docs/SKILL.md replaces the old .opencode/commands/generate-readme.md slash command. Picked up automatically by OpenCode via agentskills.io discovery. Broader scope: README + ARCHITECTURE + STRUCTURE, plus scoped section updates.

Every page under docs/src/content/docs/ now has a real frontmatter description (120–160 chars, action-oriented).

  • MDX {#anchor} heading syntax crashes the Astro/MDX 3 build — drop the explicit anchor; Starlight auto-slugs to the same fragment.
  • Astro redirects destinations don’t get base-prefixed — production-404 class. Source keys resolve against base, but destinations write verbatim. Include base manually in every destination.

Three solution docs added under docs/solutions/ capturing the learnings.

  • bun test — 950 pass, 0 fail (+11 new tests)
  • bun run docs:build — green
  • bun run docs:dev + live-server navigation — visual rendering and redirect behavior confirmed
  • ce:review (7 reviewers) — 5 non-blocking findings, all resolved before merge

v2.20.6…v2.21.0


  • deps: update github/codeql-action action to v4.36.0 (#427)

Published 2026-05-21 · Updated 2026-05-23 · View on GitHub

Cleaned stale cross-references across 8 bundled skill files. Eight different broken references were corrected: three /ce-setup placeholders replaced with direct npm install -g agent-browser instructions; the self-referential ce-pr-description removed and its PR-description logic inlined into git-commit-push-pr; two ce-demo-reel references updated to feature-video; an obsolete /doc-fix removed and /compound corrected to /ce:compound; and three /todo-* references corrected to their /systematic:todo-* form (#426).

Two new institutional knowledge docs capturing the docs refresh arc that produced PRs #418–#422. The first documents the third-party design-law import pattern — merge protocol, attribution chain handling, content normalization, and GREEN verification discipline. The second documents the OKLCH color-system migration for Starlight docs — CSS custom properties, the Mermaid hex-approximation gotcha that broke the build during migration, heading-font specificity issues, and a deployment-pipeline lesson (#423).

v2.20.5…v2.20.6

Published 2026-05-21 · Updated 2026-05-23 · View on GitHub

Renovate now correctly groups @opencode-ai/* package updates under a unified “OpenCode” heading. Previously these dependency PRs were lumped into the generic “non-major dependencies” group, which made it harder to spot upstream OpenCode releases in the queue. The fix adds groupName: 'OpenCode' to the relevant Renovate package rule (#425).

Updated @opencode-ai/plugin and @opencode-ai/sdk from 1.15.4 to 1.15.5 (#424).

v2.20.4…v2.20.5

Published 2026-05-21 · Updated 2026-05-21 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

Published 2026-05-21 · Updated 2026-05-21 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • docs: modernize main-loop and philosophy guides (#421) (1425dd6)
  • fix audit findings and remove stale guides (#420) (e8a981e)

Published 2026-05-21 · Updated 2026-05-21 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • design: align design-iterator and docs site with Impeccable design laws (#419) (9551607)

Published 2026-05-21 · Updated 2026-05-21 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • dev: update all non-major dependencies (#414) (f2eea2d)
  • dev: update all non-major dependencies to v1.15.1 (#407) (2411e5d)
  • dev: update all non-major dependencies to v1.15.2 (#410) (c4ede66)
  • dev: update all non-major dependencies to v1.15.3 (#411) (79ab6db)
  • skills: upgrade frontend-design with Impeccable design laws (#418) (350a637)
  • plans: mark 5 shipped plans as completed with provenance (#415) (b1ffda6)
  • solutions: capture OpenCode plugin hook silent-defect-swallow pattern (#413) (2fb32a1)
  • solutions: capture v2.20.0 cycle learnings on plan-spec rigor and gh CI polling (#406) (0e03d52), closes #405
  • solutions: compound SUBAGENT-STOP probe null result (#417) (c100d83)
  • probe: harden subagent-stop probe infrastructure + add sanity gate (#408) (f8c22b0)
  • deps: update bfra-me/.github to v4.16.19 (#416) (27ca9b3)
  • deps: update fro-bot/agent to v0.44.1 (#409) (5886459)
  • deps: update fro-bot/agent to v0.44.2 (#412) (92bbe2e)

Published 2026-05-18 · Updated 2026-05-18 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • skills: inject SUBAGENT-STOP block and Instruction Priority section into using-systematic bootstrap (#405) (4c780cb)
  • dev: update all non-major dependencies to v1.15.0 (#404) (832a474)
  • plans: commit v3.0.0 CC-residue excision plan from v2.19.0 cycle (#403) (12c2c13), closes #401 #320
  • solutions: compound 3 lessons from v2.19.0 release cycle (#402) (c58c55b), closes #401

Published 2026-05-18 · Updated 2026-05-18 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

Two bundled skills are now marked deprecated with removal: v3.0.0 (target not committed to a specific timeline). Both remain functional in v2.19.x — invoking either now emits a one-time console.warn per OpenCode session naming the planned removal and (where applicable) the replacement.

  • orchestrating-swarms → replacement: orchestrating-subagents (will land in the v3.0.0 cycle). Documents CEP’s Teammate API primitives (TeammateTool, spawnTeam, TaskCreate/TaskList/TaskGet, team_name parameter on task(), Claude Code subagent_type names) that do not exist in OpenCode.
  • claude-permissions-optimizer → no replacement planned. Targets Claude Code’s ~/.claude/settings.json allowlist mechanism. OpenCode uses a SQLite-backed session-scoped permission model with built-in always-persistence; there is no prompt-fatigue analog and no OpenCode equivalent to optimize.

Migration: When v3.0.0 ships, the rescue path is standard semver: install @fro.bot/systematic@^2.19 while migrating. v2.18.x and v2.19.x remain on npm.

If v3.0.0 never ships, the deprecation warning becomes the new steady state and both skills stay bundled.

Optional deprecated: block on SKILL.md with shape { since, removal, replacement?, reason? }. Runtime parser is permissive (silent drops on malformed values, never throws). Content-integrity gate is strict for bundled skills: since, removal, and reason must all be non-empty strings — mirrors the runtime drop rules so any bundled skill that passes the gate also produces a runtime warning.

Warning format when systematic_skill loads a deprecated skill:

[systematic] skill "<name>" is deprecated since v<since>; will be removed in v<removal>. Replacement: <replacement>. Reason: <reason>.

Replacement: and Reason: clauses appear only when set. Dedup via a closure-scoped Set<string> so each deprecated skill warns at most once per OpenCode session.

  • skills: deprecation surface + mark orchestrating-swarms and claude-permissions-optimizer (#401) (402ef5c)
  • dev: update all non-major dependencies to v1.14.51 (#400) (b0f182b)
  • deps: update all non-major dependencies (#399) (f0d2148)

Published 2026-05-17 · Updated 2026-05-17 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • config: surface every Zod issue in top-level config error message (#398) (862a098), closes #384
  • deps: update fro-bot/agent to v0.43.2 (#395) (5ccf5f8)
  • deps: update fro-bot/agent to v0.43.3 (#396) (ff11080)

Published 2026-05-17 · Updated 2026-05-17 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • skills: import test-driven-development and writing-skills from obra/superpowers + schema $ref dedup (#394) (095151e)
  • dev: update all non-major dependencies to v1.14.50 (#392) (9b649c0)
  • schema: factory pattern for SystematicConfigSchema construction (#393) (cffcdbe), closes #384

Published 2026-05-17 · Updated 2026-05-17 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • dev: update all non-major dependencies to v1.14.49 (#387) (f8fc45a)
  • solutions: compound learnings from typed-config-validation arc (#388) (8a2c2ad), closes #384

Published 2026-05-17 · Updated 2026-05-17 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

Published 2026-05-16 · Updated 2026-05-16 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • overlay: memoize getAvailableModels per OpencodeClient instance (#383) (c3287b8)
  • deps: bump cloned OpenCode source to v1.15.1 (#382) (c9cb642)
  • deps: update bfra-me/.github to v4.16.17 (#381) (f8a1d2c)

Published 2026-05-16 · Updated 2026-05-16 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • overlay: collapse empty cache to unknown availability status (#378) (e203a73), closes #373
  • solutions: capture discovery-before-validation lifecycle pattern (#376) (c34739a), closes #372
  • deps: update fro-bot/agent to v0.43.1 (#377) (828efd0)

Published 2026-05-15 · Updated 2026-05-15 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • overlay: collapse empty discovery to unknown + run discovery before validation (#372) (c4483eb)
  • deps: update github/codeql-action action to v4.35.5 (#375) (a20c351)
  • dev: update dependency @types/node to v24.12.4 (#374) (c4baed5)
  • dev: update dependency playwright to v1.60.0 (#371) (a5d37a7)

Published 2026-05-14 · Updated 2026-05-14 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • config: project-local Systematic overrides global Systematic output (#370) (14b8cf2)
  • integration: isolate opencode subprocess fixtures (#369) (2d24ae1)

Published 2026-05-14 · Updated 2026-05-14 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • bootstrap: simplify skill usage guidance (#368) (0999876)
  • dev: update all non-major dependencies (#367) (3064aac)

Published 2026-05-14 · Updated 2026-05-14 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • bootstrap: move skill catalog into system prompt (#365) (5158b49)
  • dev: update all non-major dependencies (#366) (a21cd96)

Published 2026-05-13 · Updated 2026-05-13 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • config: require model for variant overlays (#363) (94d3ad3)
  • dev: update all non-major dependencies (#364) (a6798aa)

Published 2026-05-13 · Updated 2026-05-13 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • stop fallback to models.json when OPENCODE_MODELS_URL is set (#362) (ce3eed6), closes #361

Published 2026-05-13 · Updated 2026-05-13 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • readme: update provider availability guidance (#360) (107510c)
  • solutions: capture provider-availability and source-default architectural arc (#359) (da6e94f), closes #358 #358 #358

Published 2026-05-13 · Updated 2026-05-13 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • overlay: replace auth.json with client-API availability + provider-grouped source defaults (#358) (66d7e43), closes #1 #2 #3 #4 #8 #9 #5

Published 2026-05-12 · Updated 2026-05-12 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • overlay: fix source models and adjust defaults (#357) (a059477)

Published 2026-05-11 · Updated 2026-05-11 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • plugin: move applyBootstrapContent out of entry point to restore plugin load (#355) (183b459), closes #309 #352 #335

Published 2026-05-11 · Updated 2026-05-11 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • config: tighten Zod-backed surfaces after v2.12.0 review (#354) (5470c60)
  • solutions: capture ReDoS learning from plugin trust-boundary inversion (#353) (adbd54f), closes #335 #352

Published 2026-05-11 · Updated 2026-05-11 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • plans: add zod-backed config schema + JSONC plan (#350) (a88a1cb)

Published 2026-05-10 · Updated 2026-05-10 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

Published 2026-05-09 · Updated 2026-05-09 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • config: seed source agent model defaults (#345) (1eecfb0)

Published 2026-05-09 · Updated 2026-05-09 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

Published 2026-05-09 · Updated 2026-05-09 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • config: harden agent overlay trust boundaries (#344) (0fb3fbc)

Published 2026-05-09 · Updated 2026-05-09 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • config: add agent configuration overlays (#343) (d5a3678)

Published 2026-05-09 · Updated 2026-05-09 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • deps: plugin config type mismatch after dependency pinning (#342) (dc0bd8d)

Published 2026-05-09 · Updated 2026-05-09 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • workflow: graduate ce-work subagent dispatch (#341) (7a5ef92)
  • deps: update all non-major dependencies (#338) (dfbe5c7)
  • deps: update github/codeql-action action to v4.35.4 (#339) (e4e8e33)

Published 2026-05-05 · Updated 2026-05-05 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

Published 2026-05-04 · Updated 2026-05-04 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • plugin: deduplicate factory registration across opencode.json sources (#335) (088598e)
  • deps: update bfra-me/.github to v4.16.12 (#333) (88b9412)
  • deps: update fro-bot/agent to v0.42.5 (#331) (f1b4f24)
  • deps: update fro-bot/agent to v0.42.6 (#332) (001d039)
  • deps: update fro-bot/agent to v0.42.7 (#334) (8564cc0)
  • deps: update github/codeql-action action to v4.35.3 (#330) (33249fc)

Published 2026-05-01 · Updated 2026-05-01 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • bootstrap: stabilize system prompt prefix (#329) (7d361ce)
  • repo: restore registry drift check and refresh AGENTS docs (#328) (ac8c336)

Published 2026-04-30 · Updated 2026-04-30 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • skills: add Systematic skill authoring guardrails (#325) (2e9453a)
  • plans: add registry automation plan retroactively (#320) (67191c9), closes #315
  • manual: add Phase 0 probe templates for empirical hypothesis validation (#321) (4e2f414)
  • deps: update bfra-me/.github to v4.16.10 (#322) (5ce820c)
  • deps: update bfra-me/.github to v4.16.11 (#326) (c8e6077)
  • deps: update fro-bot/agent to v0.42.3 (#323) (746cda2)
  • deps: update fro-bot/agent to v0.42.4 (#324) (9dbcedd)

Published 2026-04-28 · Updated 2026-04-28 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • skills: import 13 missing reference sub-files; gate sub-file integrity (#319) (b80f4ce)
  • deps: update bfra-me/.github to v4.16.9 (#318) (79ff184)
  • deps: update fro-bot/agent to v0.42.1 (#316) (7d407f0)
  • deps: update fro-bot/agent to v0.42.2 (#317) (458231f)

Published 2026-04-25 · Updated 2026-04-25 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • registry: automate component generation and migrate to OCX V2 schema (#315) (581f357)
  • update AGENTS.md hierarchy with current counts and code map (#314) (5cf7167)
  • wire content-integrity gate into build job (#313) (7a64113)

Published 2026-04-25 · Updated 2026-04-25 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • ci: fix Playwright install in docs deployment workflow (#312) (9eba3d5)

Published 2026-04-24 · Updated 2026-04-24 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • restore single-export plugin entry point (#309) (23955e1)
  • deps: update bfra-me/.github to v4.16.8 (#307) (ef02119)
  • deps: update fro-bot/agent to v0.41.4 (#308) (5986779)

Published 2026-04-21 · Updated 2026-04-21 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

Published 2026-04-20 · Updated 2026-04-20 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • gate: content-integrity gate + close validation/bootstrap test coverage gaps (#301) (d7e4125)
  • deps: update actions/setup-node action to v6.4.0 (#300) (21a9b85)
  • deps: update bfra-me/.github to v4.16.7 (#298) (41a3e26)
  • deps: update fro-bot/agent to v0.41.1 (#295) (11de5f1)
  • deps: update fro-bot/agent to v0.41.2 (#297) (92a2c04)
  • deps: update fro-bot/agent to v0.41.3 (#299) (b1f2a63)

Published 2026-04-18 · Updated 2026-04-18 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • replace Anthropic model aliases in reviewer/workflow agents with inherit (#294) (dedf778)

Published 2026-04-17 · Updated 2026-04-17 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • deps: update actions/create-github-app-token action to v3.1.0 (#280) (5a91c9c)
  • deps: update actions/create-github-app-token action to v3.1.1 (#282) (d5f0d75)
  • deps: update actions/upload-artifact action to v7.0.1 (#279) (22de945)
  • deps: update bfra-me/.github to v4.16.1 (#277) (4c6300a)
  • deps: update bfra-me/.github to v4.16.2 (#278) (2808502)
  • deps: update bfra-me/.github to v4.16.3 (#281) (828fa9d)
  • deps: update bfra-me/.github to v4.16.5 (#283) (505d7a5)
  • deps: update bfra-me/.github to v4.16.6 (#288) (1f4395f)
  • deps: update fro-bot/agent to v0.37.1 (#275) (c0bead3)
  • deps: update fro-bot/agent to v0.38.0 (#276) (7fb0a4d)
  • deps: update fro-bot/agent to v0.39.1 (#284) (623d70e)
  • deps: update fro-bot/agent to v0.40.1 (#287) (67eb0f7)
  • deps: update fro-bot/agent to v0.40.2 (#289) (d1b71bc)
  • deps: update github/codeql-action action to v4.35.2 (#286) (0097379)

Published 2026-04-06 · Updated 2026-04-06 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • ci: install Playwright in docs workspace (#274) (ceda57a)

Published 2026-04-06 · Updated 2026-04-06 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • bundle jsonc-parser to resolve Node.js ESM/CJS interop failure (#271) (7aaa69d)
  • deps: update bfra-me/.github to v4.16.0 (#272) (685dc96)
  • deps: update fro-bot/agent to v0.36.5 (#270) (b949f34)
  • deps: update fro-bot/agent to v0.37.0 (#273) (142c3f9)

Published 2026-04-06 · Updated 2026-04-06 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • use default import for jsonc-parser (Node.js ESM compat) (#269) (fd17a31)
  • deps: update bfra-me/.github to v4.14.6 (#263) (b044087)
  • deps: update bfra-me/.github to v4.14.7 (#265) (d453ca3)
  • deps: update bfra-me/.github to v4.15.0 (#267) (33ad5fe)
  • deps: update fro-bot/agent to v0.36.1 (#262) (f7b2b3a)
  • deps: update fro-bot/agent to v0.36.2 (#264) (eb5095d)
  • deps: update fro-bot/agent to v0.36.3 (#266) (fae62c8)
  • deps: update fro-bot/agent to v0.36.4 (#268) (c8a0843)

Published 2026-04-02 · Updated 2026-04-02 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • full CEP sync — import new skills/agents, replace deprecated, update sub-files (#261) (94448d5)
  • deps: update bfra-me/.github to v4.14.5 (#259) (e3ac485)
  • remove deprecated workflows:* skills and ce-review-beta (#260) (6db3057)

Published 2026-04-01 · Updated 2026-04-01 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • add missing skill reference sub-files from CEP upstream (#258) (308c899)

Published 2026-04-01 · Updated 2026-04-01 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • restore interactive /sync-cep command and supporting infrastructure (#255) (0087e09)
  • deps: update bfra-me/.github to v4.14.3 (#249) (51878b1)
  • deps: update bfra-me/.github to v4.14.4 (#253) (f80e4b4)
  • deps: update fro-bot/agent to v0.32.2 (#247) (53aadff)
  • deps: update fro-bot/agent to v0.32.3 (#248) (a67ffa1)
  • deps: update fro-bot/agent to v0.33.0 (#250) (72d73ad)
  • deps: update fro-bot/agent to v0.34.0 (#251) (28f4d7d)
  • deps: update fro-bot/agent to v0.34.1 (#252) (cfb82b8)
  • deps: update fro-bot/agent to v0.35.0 (#254) (d50d1e6)
  • deps: update fro-bot/agent to v0.36.0 (#257) (e03b80b)
  • deps: update github/codeql-action action to v4.35.0 (#245) (14ea200)
  • deps: update github/codeql-action action to v4.35.1 (#246) (eb4e099)

Published 2026-03-27 · Updated 2026-03-27 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • register bundled skills via config.skills.paths (#244) (d0fcffa)

Published 2026-03-26 · Updated 2026-03-26 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • docs: update create-agent-skills → create-agent-skill references (#242) (d2483f3)
  • sync: require post-conversion fixup checks (#240) (c823cb5)
  • deps: update actions/setup-node action to v6 (#233) (365e25f)
  • deps: update bfra-me/.github to v4.13.7 (#224) (1e75a3b)
  • deps: update bfra-me/.github to v4.13.8 (#228) (8dc72fe)
  • deps: update bfra-me/.github to v4.13.9 (#235) (c62ef19)
  • deps: update bfra-me/.github to v4.14.0 (#236) (064eaf7)
  • deps: update bfra-me/.github to v4.14.2 (#237) (da63bd0)
  • deps: update dependency node to v24 (#234) (7800d41)
  • deps: update fro-bot/agent to v0.32.0 (#225) (1bf938e)
  • deps: update fro-bot/agent to v0.32.1 (#232) (4fcf8d3)
  • sync CEP upstream definitions (#230) (30518af)
  • sync CEP upstream definitions (commit 0fdc25a) (#226) (9f5e1da)

Published 2026-03-23 · Updated 2026-03-23 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • preserve colon-prefixed skill names without systematic: prefix (#223) (4ddf475)

Published 2026-03-23 · Updated 2026-03-23 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • ci: add Node.js 22 setup to docs workflow for Astro 5 compat (#222) (7fa94a0)

Published 2026-03-23 · Updated 2026-03-23 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • The bundled commands/ directory is removed from the npm package. All former commands are now available as skills (e.g., ce:brainstorm, ce:plan, ce:review). Project-level commands in .opencode/commands/ remain supported.
  • remove bundled commands and update documentation for skills-only model (#221) (8516222)

Published 2026-03-23 · Updated 2026-03-23 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • lint: prefix unused output variable with underscore in plugin test (#220) (7b50387)

Published 2026-03-22 · Updated 2026-03-22 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • release: refine semantic-release rules (#218) (db581df)
  • deps: update fro-bot/agent to v0.31.2 (#217) (137d3b9)

Published 2026-03-22 · Updated 2026-03-22 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • agents: refresh generated guidance docs (#216) (3fe837b)
  • deps: update bfra-me/.github to v4.10.0 (#195) (13c214e)
  • deps: update bfra-me/.github to v4.10.1 (#196) (b587db0)
  • deps: update bfra-me/.github to v4.10.2 (#197) (eb1264e)
  • deps: update bfra-me/.github to v4.11.0 (#200) (64f702c)
  • deps: update bfra-me/.github to v4.12.0 (#201) (fba6859)
  • deps: update bfra-me/.github to v4.12.1 (#202) (338f999)
  • deps: update bfra-me/.github to v4.13.0 (#203) (cb5e321)
  • deps: update bfra-me/.github to v4.13.1 (#204) (d5dbdcf)
  • deps: update bfra-me/.github to v4.13.2 (#206) (8c7e9a3)
  • deps: update bfra-me/.github to v4.13.3 (#207) (90c4c87)
  • deps: update bfra-me/.github to v4.13.4 (#212) (69246da)
  • deps: update bfra-me/.github to v4.13.5 (#213) (13c419f)
  • deps: update bfra-me/.github to v4.13.6 (#215) (500b805)
  • deps: update bfra-me/.github to v4.8.1 (#193) (e872dba)
  • deps: update bfra-me/.github to v4.9.0 (#194) (44bf40f)
  • deps: update fro-bot/agent to v0.30.10 (#205) (cd8c2b1)
  • deps: update fro-bot/agent to v0.30.9 (#199) (a70003a)
  • deps: update fro-bot/agent to v0.31.1 (#214) (d3fe96b)
  • deps: update github/codeql-action action to v4.34.0 (#209) (ce9d424)
  • deps: update github/codeql-action action to v4.34.1 (#210) (087eb1e)

Published 2026-03-17 · Updated 2026-03-17 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • Sync CEP upstream - 27 new skills + 2 updated skills (#189) (851aa51)
  • deps: update actions/create-github-app-token action to v3 (#184) (e6c2e64)
  • deps: update bfra-me/.github to v4.8.0 (#188) (97b92a8)
  • deps: update fro-bot/agent to v0.30.8 (#187) (0ab7bb7)
  • deps: update github/codeql-action action to v4.33.0 (#190) (acccc04)

Published 2026-03-15 · Updated 2026-03-15 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • deps: update dependency @astrojs/starlight to ^0.38.0 (#183) (079a336)

Published 2026-03-15 · Updated 2026-03-15 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • ci: add Node 22 to docs job for Astro 6 support (#186) (1bd165e)
  • deps: update actions/create-github-app-token action to v2.2.2 (#175) (c2f6193)
  • deps: update bfra-me/.github to v4.5.5 (#177) (64c26e6)
  • deps: update bfra-me/.github to v4.6.0 (#178) (fe5270f)
  • deps: update bfra-me/.github to v4.7.0 (#179) (d1f9e3d)
  • deps: update fro-bot/agent to v0.30.7 (#182) (9fcea96)
  • deps: update oven-sh/setup-bun action to v2.2.0 (#180) (e91d7b9)
  • sync CEP upstream - update learnings-researcher agent (#176) (3184cad)
  • sync: update learnings-researcher agent from CEP upstream (#181) (6571197)

Published 2026-03-13 · Updated 2026-03-13 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • lint: update biome.json schema to match installed version 2.4.6 (#165) (294ce8f)
  • deps: update bfra-me/.github to v4.5.0 (#170) (09a5b96)
  • deps: update bfra-me/.github to v4.5.1 (#171) (5ea4b03)
  • deps: update bfra-me/.github to v4.5.2 (#172) (81b724d)
  • deps: update bfra-me/.github to v4.5.3 (#173) (99225a2)
  • deps: update bfra-me/.github to v4.5.4 (#174) (84c9142)

Published 2026-03-12 · Updated 2026-03-12 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • branding cohesion — Mermaid, banner, new guides, install-first CTAs (#161) (d857569)
  • deps: update bfra-me/.github to v4.4.0 (#167) (3d57343)
  • deps: update fro-bot/agent to v0.30.0 (#156) (15ae51f)
  • deps: update fro-bot/agent to v0.30.1 (#158) (3b07e35)
  • deps: update fro-bot/agent to v0.30.2 (#159) (dfcf76c)
  • deps: update fro-bot/agent to v0.30.3 (#160) (19f6b7e)
  • deps: update fro-bot/agent to v0.30.4 (#162) (9dc18cf)
  • deps: update fro-bot/agent to v0.30.5 (#164) (c3dffc8)
  • deps: update fro-bot/agent to v0.30.6 (#166) (960462c)

Published 2026-03-09 · Updated 2026-03-09 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • eliminate noExcessiveCognitiveComplexity lint warnings (#155) (5363356)

Published 2026-03-09 · Updated 2026-03-09 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

Published 2026-03-09 · Updated 2026-03-09 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • fro-bot: remove unnecessary write permissions (#152) (6c4adb5)

Published 2026-03-09 · Updated 2026-03-09 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • fro-bot: harden workflow guards and add autoheal (#150) (dd4e70e)
  • deps: update bfra-me/.github to v4.3.31 (#149) (f39ff46)
  • deps: update fro-bot/agent action to v0.29.1 (#146) (5571589)
  • deps: update fro-bot/agent to v0.29.2 (#151) (0de3810)
  • dev: update dependency markdownlint-cli to ^0.48.0 (#147) (8ced51b)
  • move OpenCode TUI config (#148) (2044c10)

Published 2026-03-08 · Updated 2026-03-08 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • sync: import ce/ namespace commands and resolve workflows/ deprecations (#145) (2d2c246)
  • deps: update actions/setup-node action to v6.3.0 (#140) (9b326c4)
  • deps: update actions/upload-artifact action to v7 (#133) (1906e9c)
  • deps: update bfra-me/.github to v4.3.28 (#131) (949f106)
  • deps: update bfra-me/.github to v4.3.29 (#134) (9387828)
  • deps: update bfra-me/.github to v4.3.30 (#142) (4ed12c8)
  • deps: update fro-bot/agent action to v0.28.0 (#132) (5d79bea)
  • deps: update fro-bot/agent action to v0.28.1 (#139) (a7ebae0)
  • deps: update github/codeql-action action to v4.32.5 (#138) (3e2ffa6)
  • deps: update github/codeql-action action to v4.32.6 (#143) (60e6e74)
  • deps: update oven-sh/setup-bun action to v2.1.3 (#141) (89d7fa2)
  • opencode: add tui.json for theme configuration (#128) (24698d6)
  • sync CEP upstream definitions (#130) (98c1da4)
  • sync CEP upstream definitions (#135) (0da83d7)
  • sync-sep: remove subtask config (#129) (a8b9ce9)

Published 2026-02-26 · Updated 2026-02-26 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • plugin: improve bootstrap system prompt injection (#127) (c255b6f)

Published 2026-02-25 · Updated 2026-02-25 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • sync-cep: handle precheck error flow in sync pipeline (#126) (61bf7a9)

Published 2026-02-25 · Updated 2026-02-25 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • fro-bot: update token handling and auth-json in workflows (#125) (b6fa627)
  • deps: update bfra-me/.github to v4.3.27 (#121) (f9db8d8)
  • deps: update fro-bot/agent action to v0.26.17 (#120) (86acad9)
  • deps: update fro-bot/agent action to v0.26.20 (#123) (b760ce4)
  • deps: update fro-bot/agent action to v0.26.21 (#124) (f7ad14f)

Published 2026-02-22 · Updated 2026-02-22 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • sync 15 definitions from CEP upstream (commit 63e76cf) (#119) (b37689c)
  • deps: update fro-bot/agent action to v0.26.16 (#117) (02c7577)

Published 2026-02-21 · Updated 2026-02-21 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • fro-bot: add dynamic ref handling for pull requests (#118) (3909d62)

Published 2026-02-21 · Updated 2026-02-21 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • sync-cep: wrap error messages in a collapsible details section (#116) (53b820a)

Published 2026-02-21 · Updated 2026-02-21 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • check-cep-upstream: add GitHub API authentication support (#115) (3478675)
  • sync-cep: add troubleshooting guide for missing sub-files (#112) (2b3f0fc)
  • deps: update fro-bot/agent action to v0.26.14 (#113) (48d3a9b)
  • deps: update github/codeql-action action to v4.32.4 (#114) (7c92f7a)

Published 2026-02-20 · Updated 2026-02-20 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • sync 30 new definitions from CEP upstream (#110) (56c7d07)

Published 2026-02-20 · Updated 2026-02-20 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • sync-cep: enhance skill file import process (#111) (3245e84)

Published 2026-02-19 · Updated 2026-02-19 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • deps: update dependency sharp to ^0.34.0 (#96) (23ef8ae)
  • deps: update fro-bot/agent action to v0.26.12 (#108) (e16fa29)

Published 2026-02-19 · Updated 2026-02-19 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • precheck: fix false-positive hashChanges, 404 hadError, and hash collisions (#109) (2014eef)

Published 2026-02-19 · Updated 2026-02-19 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • sync-cep: Improve error messages and add skill discoverability tests (#107) (7d63c7f)
  • deps: update bfra-me/.github to v4.3.26 (#106) (4e4235c)
  • deps: update fro-bot/agent action to v0.26.10 (#102) (5705952)

Published 2026-02-18 · Updated 2026-02-18 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • fro-bot: sync with fro-bot/agent example (#105) (c106ed2)

Published 2026-02-18 · Updated 2026-02-18 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • remove timeouts from Fro Bot agent actions (#104) (140d5dd)
  • deps: update actions/github-script action to v8 (#97) (21e2ab1)
  • deps: update fro-bot/agent action to v0.26.2 (#100) (826578d)
  • deps: update fro-bot/agent action to v0.26.4 (#101) (80ff556)

Published 2026-02-16 · Updated 2026-02-16 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • sync-cep: bump GitHub Actions versions (#98) (069dfbb)

Published 2026-02-16 · Updated 2026-02-16 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • sync-cep: support exit code 2 with enhanced error reporting (#95) (f18237f)
  • deps: pin (digest) actions/github-script action to f28e40c (#90) (1ee50d5)
  • deps: update actions/checkout digest to 0c366fd (#91) (0fe562b)
  • deps: update actions/github-script action to v7.1.0 (#94) (92d1887)
  • deps: update fro-bot/agent digest to d58b64b (#92) (9de47a9)
  • deps: update oven-sh/setup-bun digest to ab8cb4e (#93) (c402e4e)

Published 2026-02-16 · Updated 2026-02-16 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • add automated CEP resync workflow (#89) (b4e3f3a)
  • deps: update bfra-me/.github to v4.3.25 (#86) (19ad774)
  • deps: update fro-bot/agent action to v0.25.1 (#82) (647a329)
  • deps: update fro-bot/agent action to v0.26.1 (#85) (53ce355)
  • update .gitignore and .releaserc.yaml, remove brainstorm docs (#84) (fb8131d)

Published 2026-02-15 · Updated 2026-02-15 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • release: release docs for bundled definition scopes (#83) (5062d12)
  • skill: improve using-systematic skill flow diagram (#81) (36a080d)
  • deps: update fro-bot/agent action to v0.24.0 (#79) (dd1d052)

Published 2026-02-14 · Updated 2026-02-14 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • allow disable-model-invocation skills to be loaded via systematic_skill tool (#80) (fbe1780)

Published 2026-02-14 · Updated 2026-02-14 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • wrap command templates and stabilize integration tests (#78) (5a81409)
  • refresh reference section with category badges and dynamic index pages (#69) (5a0975c)
  • deps: update fro-bot/agent action to v0.23.27 (#77) (7538522)
  • deps: update fro-bot/agent digest to 322e7ef (#73) (aea28f9)
  • deps: update fro-bot/agent digest to aa439f2 (#74) (156017d)
  • deps: update fro-bot/agent digest to ca9c391 (#72) (f5209f2)
  • deps: update fro-bot/agent digest to cddd9cd (#75) (c7a6ea0)
  • deps: update fro-bot/agent to v0.23.26 (#76) (9a8e3f7)

Published 2026-02-13 · Updated 2026-02-13 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • deps: update github/codeql-action action to v4.32.3 (#71) (42970ac)

Published 2026-02-12 · Updated 2026-02-12 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

Published 2026-02-12 · Updated 2026-02-12 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • OCX registry compatibility and profile support (#67) (fd51016)

Published 2026-02-12 · Updated 2026-02-12 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • deps: update bfra-me/.github to v4.3.24 (#65) (ae49d08)
  • rename write-readme command, fix typo, and update asset counts (#64) (de733ce)

Published 2026-02-10 · Updated 2026-02-10 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • sync all CEP skills from upstream e8f3bbc (#63) (17335d3)

Published 2026-02-10 · Updated 2026-02-10 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • import 24 CEP agents and update write-readme command (#62) (26baac7)

Published 2026-02-10 · Updated 2026-02-10 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • import 5 CEP workflow commands and add convert-cc-defs skill (#61) (0b70ecd)

Published 2026-02-10 · Updated 2026-02-10 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • map-and-preserve strategy for frontmatter conversion (#60) (520fc6d)
  • standardize homepage URL and improve documentation (#59) (e18bc1f)

Published 2026-02-09 · Updated 2026-02-09 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • copy dotfiles (.nojekyll) in docs deployment (#58) (b00201d)
  • deps: update bfra-me/.github to v4.3.23 (#55) (75f73d3)

Published 2026-02-08 · Updated 2026-02-08 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • config: standardize Systematic branding in descriptions (#54) (13ffb65)
  • refactor AGENTS.md for clarity and completeness (#53) (13f50c3)

Published 2026-02-08 · Updated 2026-02-08 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • deps: update github/codeql-action action to v4.32.2 (#52) (bea1ad0)

Published 2026-02-05 · Updated 2026-02-05 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • update skill-tool to OpenCode v1.1.50 functionality (#50) (dc09cc8)
  • deps: update github/codeql-action action to v4.32.1 (#49) (bc5c6d6)

Published 2026-02-02 · Updated 2026-02-02 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • readme.md: restructure AGENTS.md and add module documentation (#48) (bf2aaa7)

Published 2026-02-01 · Updated 2026-02-01 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • readme.md: simplify installation step (#47) (decbf40)

Published 2026-02-01 · Updated 2026-02-01 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • agents: add new bundled specialist agents from CEP (#46) (285d448)
  • readme: update command names with systematic namespace (#45) (4909286)
  • opencode: add systematic theme configuration to opencode.json (#44) (2014d8f)

Published 2026-02-01 · Updated 2026-02-01 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • add Claude Code field compatibility to skills system (#43) (5d892f3)

Published 2026-02-01 · Updated 2026-02-01 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • commands: add agent routing and model override support (#42) (099cef9)
  • add comprehensive documentation and assets (#41) (11494af)
  • extract shared validation utilities and expand agent frontmatter support (#40) (0c9147d)

Published 2026-01-31 · Updated 2026-01-31 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • converter: add edge case handling for Task patterns and code blocks (#39) (486d4bb)
  • deps: update dependency node to v24 (#20) (a410cf4)

Published 2026-01-31 · Updated 2026-01-31 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • agents: update agent definitions with CEP content (#38) (a01c251)

Published 2026-01-31 · Updated 2026-01-31 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

Published 2026-01-31 · Updated 2026-01-31 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • converter: add Claude Code to OpenCode content transformation (#36) (9a4270e)
  • frontmatter: unify YAML parsing with js-yaml (#32) (db88f5b)
  • skills: add $ARGUMENTS placeholder to skill templates (#35) (505b0d8)
  • skills: extract skill loading into dedicated module (#34) (4bac76d)
  • deps: update bfra-me/.github to v4.3.22 (#33) (a892e8e)

Published 2026-01-28 · Updated 2026-01-28 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • modularize codebase and improve type generation (#31) (d4bfa75)

Published 2026-01-27 · Updated 2026-01-27 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • update Bun build process and remove bunfig.toml (#30) (99f70c7)

Published 2026-01-27 · Updated 2026-01-27 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • plugin: streamline converter and enhance config handling (#29) (2ff7334)

Published 2026-01-27 · Updated 2026-01-27 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • plugin: consolidate to single systematic_skill tool (#28) (bb262c9)
  • deps: maintain lockfiles (#26) (02d315d)
  • deps: update actions/checkout action to v6 (#17) (bed7d20)
  • deps: update actions/setup-node action to v6 (#18) (e1535aa)
  • deps: update actions/upload-artifact action to v6 (#19) (02df68b)
  • deps: update github/codeql-action action to v4 (#21) (b8f6fa6)
  • deps: update github/codeql-action action to v4.32.0 (#27) (904c1c6)
  • dev: update dependency @biomejs/biome to v2 (#22) (1118613)

Published 2026-01-26 · Updated 2026-01-26 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • update bfra-me/.github workflow to v4.3.21 (#25) (11232e2)

Published 2026-01-26 · Updated 2026-01-26 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • update bfra-me/.github workflow to v4.3.20 (#24) (b321471)
  • deps: update actions/checkout action to v4.3.1 (#12) (da5b787)
  • deps: update actions/create-github-app-token action to v2.2.1 (#13) (8ddb2ed)
  • deps: update bfra-me/.github to v4.3.19 (#10) (7e3c171)
  • deps: update github/codeql-action action to v3.31.11 (#14) (31da594)

Published 2026-01-26 · Updated 2026-01-26 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • improve workflow configuration and automation (#16) (c12ea06)
  • deps: update ossf/scorecard-action action to v2.4.3 (#11) (246c409)

Published 2026-01-26 · Updated 2026-01-26 · View on GitHub

Narrative unavailable. No Fro Bot narrative was published for this release; the notes below are the raw release body.

  • Command names and agent paths have changed

Content Changes:

  • Pull CEP skills: agent-browser, agent-native-architecture (with references/), brainstorming, compound-docs (with assets/references/), create-agent-skills (with references/templates/workflows/), file-todos, git-worktree
  • Remove skills: writing-plans, test-driven-development, systematic-debugging, verification-before-completion, executing-plans, using-git-worktrees, writing-skills
  • Pull CEP commands: workflows/{brainstorm,compound,plan,review,work}, agent-native-audit, create-agent-skill, deepen-plan, lfg
  • Remove sys-* prefix from commands - now /workflows:plan instead of /sys:plan
  • Restructure agents into review/ and research/ subdirectories

Code Changes:

  • Add CLI convert command for converting CEP content to OpenCode format
  • Update findAgentsInDir and findCommandsInDir to support nested directories
  • Commands in subdirs use category:name format (e.g., /workflows:plan)

Documentation:

  • Update README with new content tables and conversion instructions
  • Update using-systematic skill with available content reference
  • config: add config hook for OpenCode integration (#5) (190d7cf)
  • implement @fro.bot/systematic OpenCode plugin (#1) (a1f6983)
  • add AGENTS.md and improve README attribution (#4) (f855791)
  • add systematic plugin design document (3369fb2)
  • isolate opencode integration tests and add tests (#7) (25570d0)
  • remove config override support for agents, commands, and skills (#6) (a3124a2)
  • remove unused code and improve maintainability (#9) (dba4201)
  • remove unused resolveSkillPath function and ResolvedSkill interface (#8) (c078aa2)
  • add .worktrees to gitignore (9f09c3e)
  • migrate to OpenCode-native skill loading (#3) (f299847)