Context
For an OSS framework, release friction is a direct throttle on how fast improvements reach users. Since 0.1.7 the project has shipped via a fully manual process: the automated release-PR flow (release-please) was removed because the org cannot grant CI the permission to create/merge PRs. A release now means hand-editing four version files plus the changelog, with no guard against a partial bump. This is an organizational + process decision — we need to pick a release-ownership and automation boundary, not just patch a script.
This issue is a discussion to decide that boundary. It maps to D7 in the capability-gap roadmap.
Current state
release-please automation is gone. There is no .github/workflows/release-please.yml (only ci.yml, publish.yml, deploy-pages.yml, docs-pr.yml remain in .github/workflows/). A .release-please-manifest.json file still exists at the repo root pinning {".": "0.1.7"}, but nothing consumes it automatically anymore.
- Publishing is triggered by a version change on
main, not by a tag or release PR. See .github/workflows/publish.yml:3-7 — on: push: branches: [main] filtered to paths: ['pyproject.toml']. The check-version job (.github/workflows/publish.yml:18-49) extracts the version from pyproject.toml and skips if that version already exists on PyPI; the tag job (.github/workflows/publish.yml:124-138) creates v<version> after publish.
- PyPI publishing already uses Trusted Publishing / OIDC (no API token). See
.github/workflows/publish.yml:9-11 (id-token: write) and the publish step at .github/workflows/publish.yml:119-122 (pypa/gh-action-pypi-publish@release/v1, "Uses Trusted Publisher — no API token needed"). So option (3) below is largely already in place — the open question is confirming/hardening it, not introducing it.
- A release requires bumping four version files by hand, plus the changelog. This is documented inline in
CHANGELOG.md:8-15, which instructs the maintainer to bump the version in:
pyproject.toml:7 — version = "0.1.7" (the trigger file)
src/hebb/__init__.py:45 — __version__ = "0.1.7"
.release-please-manifest.json — {".": "0.1.7"}
.claude-plugin/plugin.json:3 — "version": "0.1.7"
- and add a dated section to
CHANGELOG.md (currently ## [0.1.7] - 2026-06-08, CHANGELOG.md:16).
- There is no release helper today.
scripts/ contains only install.sh; there is no Makefile and no make release / release script. The bump is entirely manual, with no tooling to keep the four files in lockstep or to fail if one drifts.
Proposed approach (decide one direction)
- Restore automated release PRs — ask the org to grant a scoped token or install a GitHub App with PR create/merge permission, then reinstate a
release-please-style workflow that opens/merges the version-bump PR. Removes manual bumping entirely but depends on an org-level permission grant that was previously denied.
- Maintainer-run one-command release script — a
make release (or scripts/release.py / hebb-dev release) that performs the four-file bump + changelog stamp + git tag in one step, with a check that fails if any of the four version strings disagree. Reduces manual error without needing any CI PR permission; publish.yml still ships on the resulting pyproject.toml change to main. Lowest-dependency option.
- Confirm / harden Trusted Publishing (OIDC) — Trusted Publishing is already wired in
publish.yml; ratify it as the supported path, document the PyPI publisher config, and ensure no fallback API token is ever needed. Pairs with either (1) or (2).
These are not mutually exclusive: (2) + (3) is a fully self-serve maintainer path with no org dependency; (1) + (3) is the fully-automated path if the permission can be obtained.
Acceptance criteria
Scope / out of scope
- In scope: the release-ownership decision, the manual-bump error surface, and the one-command release path.
- Out of scope: the test/build matrix in
ci.yml and publish.yml (these already re-run before publish, publish.yml:51-108); changes to the SemVer policy or the publish trigger (version change on main) unless a chosen option requires it.
References
.github/workflows/publish.yml — publish trigger, OIDC/Trusted Publishing, tagging.
.github/workflows/ci.yml — existing test/lint/e2e/model/docker gates.
CHANGELOG.md (header at lines 8-15) — the documented manual four-file bump procedure.
reports/audit/core-system-audit-2026-06-07.md
reports/audit/newuser-experience-audit-2026-06-08.md
reports/design/capability-gap-roadmap-2026-06-11.md (D7)
Filed from the capability-gap roadmap (reports/design/capability-gap-roadmap-2026-06-11.md).
Context
For an OSS framework, release friction is a direct throttle on how fast improvements reach users. Since
0.1.7the project has shipped via a fully manual process: the automated release-PR flow (release-please) was removed because the org cannot grant CI the permission to create/merge PRs. A release now means hand-editing four version files plus the changelog, with no guard against a partial bump. This is an organizational + process decision — we need to pick a release-ownership and automation boundary, not just patch a script.This issue is a discussion to decide that boundary. It maps to D7 in the capability-gap roadmap.
Current state
release-pleaseautomation is gone. There is no.github/workflows/release-please.yml(onlyci.yml,publish.yml,deploy-pages.yml,docs-pr.ymlremain in.github/workflows/). A.release-please-manifest.jsonfile still exists at the repo root pinning{".": "0.1.7"}, but nothing consumes it automatically anymore.main, not by a tag or release PR. See.github/workflows/publish.yml:3-7—on: push: branches: [main]filtered topaths: ['pyproject.toml']. Thecheck-versionjob (.github/workflows/publish.yml:18-49) extracts the version frompyproject.tomland skips if that version already exists on PyPI; thetagjob (.github/workflows/publish.yml:124-138) createsv<version>after publish..github/workflows/publish.yml:9-11(id-token: write) and the publish step at.github/workflows/publish.yml:119-122(pypa/gh-action-pypi-publish@release/v1, "Uses Trusted Publisher — no API token needed"). So option (3) below is largely already in place — the open question is confirming/hardening it, not introducing it.CHANGELOG.md:8-15, which instructs the maintainer to bump the version in:pyproject.toml:7—version = "0.1.7"(the trigger file)src/hebb/__init__.py:45—__version__ = "0.1.7".release-please-manifest.json—{".": "0.1.7"}.claude-plugin/plugin.json:3—"version": "0.1.7"CHANGELOG.md(currently## [0.1.7] - 2026-06-08,CHANGELOG.md:16).scripts/contains onlyinstall.sh; there is noMakefileand nomake release/ release script. The bump is entirely manual, with no tooling to keep the four files in lockstep or to fail if one drifts.Proposed approach (decide one direction)
release-please-style workflow that opens/merges the version-bump PR. Removes manual bumping entirely but depends on an org-level permission grant that was previously denied.make release(orscripts/release.py/hebb-dev release) that performs the four-file bump + changelog stamp + git tag in one step, with a check that fails if any of the four version strings disagree. Reduces manual error without needing any CI PR permission;publish.ymlstill ships on the resultingpyproject.tomlchange tomain. Lowest-dependency option.publish.yml; ratify it as the supported path, document the PyPI publisher config, and ensure no fallback API token is ever needed. Pairs with either (1) or (2).These are not mutually exclusive: (2) + (3) is a fully self-serve maintainer path with no org dependency; (1) + (3) is the fully-automated path if the permission can be obtained.
Acceptance criteria
pyproject.toml,src/hebb/__init__.py,.release-please-manifest.json,.claude-plugin/plugin.json) and stampsCHANGELOG.mdfrom one input version.publish.ymlis confirmed as the supported publish mechanism and documented (no API token fallback).Scope / out of scope
ci.ymlandpublish.yml(these already re-run before publish,publish.yml:51-108); changes to the SemVer policy or the publish trigger (version change onmain) unless a chosen option requires it.References
.github/workflows/publish.yml— publish trigger, OIDC/Trusted Publishing, tagging..github/workflows/ci.yml— existing test/lint/e2e/model/docker gates.CHANGELOG.md(header at lines 8-15) — the documented manual four-file bump procedure.reports/audit/core-system-audit-2026-06-07.mdreports/audit/newuser-experience-audit-2026-06-08.mdreports/design/capability-gap-roadmap-2026-06-11.md(D7)Filed from the capability-gap roadmap (reports/design/capability-gap-roadmap-2026-06-11.md).