From c210644cb4a6389855cdecbaf733bf5f3ef9f6f5 Mon Sep 17 00:00:00 2001 From: zayJu Date: Wed, 11 Nov 2026 19:02:15 +0800 Subject: [PATCH 1/4] =?UTF-8?q?docs(install):=20=E7=A7=BB=E9=99=A4=20go=20?= =?UTF-8?q?install=20=E6=B8=A0=E9=81=93=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 引擎不再作为 Go 模块发布,安装只走发布包、Homebrew tap 与 Linux 包。 删除中英两版的 go install 段落、卸载器里 GOPATH 的旁注,以及 README 的渠道列举。 Co-Authored-By: Claude Code --- README.md | 2 +- README.zh.md | 2 +- docs/install.md | 26 -------------------------- docs/install.zh.md | 24 ------------------------ 4 files changed, 2 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 9d734589..a9d28744 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ Windows (PowerShell): irm https://raw.githubusercontent.com/SheathedSharp/option-berth/main/install.ps1 | iex ``` -Homebrew, `go install`, Linux `.deb`/`.rpm`, pinned versions, uninstall, upgrades and the platform +Homebrew, Linux `.deb`/`.rpm`, pinned versions, uninstall, upgrades and the platform boundaries are in [Install and uninstall](docs/install.md). The scripts only download and verify release archives: they start no service and write no Git data. diff --git a/README.zh.md b/README.zh.md index d0cdbfc2..60e1874f 100644 --- a/README.zh.md +++ b/README.zh.md @@ -72,7 +72,7 @@ Windows(PowerShell): irm https://raw.githubusercontent.com/SheathedSharp/option-berth/main/install.ps1 | iex ``` -Homebrew、`go install`、Linux `.deb`/`.rpm`、固定版本、卸载、升级与各平台边界见 +Homebrew、Linux `.deb`/`.rpm`、固定版本、卸载、升级与各平台边界见 [安装与卸载](docs/install.zh.md)。安装脚本只下载并校验发布包:不启动服务,也不写 Git。 直接运行 `oberth` 会显示本机版本;有更新时给出本平台的升级命令。也可以随时运行 diff --git a/docs/install.md b/docs/install.md index 9cd51d00..4746b460 100644 --- a/docs/install.md +++ b/docs/install.md @@ -64,17 +64,6 @@ The Windows installer supports the same mirror fallback, and can also be launche irm https://ghfast.top/https://raw.githubusercontent.com/SheathedSharp/option-berth/main/install.ps1 | iex ``` -`go install` does not go through release assets, so a Go module proxy suffices and checksums are still -verified: - -```sh -GOPROXY=https://goproxy.cn go install github.com/sheathedsharp/option-berth/engine/cmd/oberth@latest -``` - -Setting only `GOPROXY` is enough: Go verifies the module through the proxy's `/sumdb/` endpoint. Do not -append `,direct` — when the proxy misses, Go falls back to a direct GitHub connection, which is the path -that times out; `GOSUMDB=off` is unnecessary too. - A third-party proxy can see download traffic and can be replaced. When you need a strict origin, pin the version with `--version` and compare against the `SHA256SUMS` in Releases; release-archive signature verification is not available yet. @@ -96,18 +85,6 @@ Pin a version or leave PATH alone: `.\install.ps1 -Version v1.0.0 -NoModifyPath` Before replacing files, the Windows installer checks whether `oberth` / `jev-attention` are running; if they are, it runs `oberth daemon stop` first and then reinstalls. -## go install (Go 1.25+) - -```sh -go install github.com/sheathedsharp/option-berth/engine/cmd/oberth@latest - -# Optional Jev adapter -go install github.com/sheathedsharp/option-berth/engine/cmd/jev-attention@latest -``` - -This needs v1.1.2 or later. Pin a version with `@v1.1.2`. The binaries land in `$(go env GOPATH)/bin` -(or `GOBIN`), which must be on PATH. - ## Homebrew A self-hosted tap, so there is no need to wait for homebrew-core inclusion. It installs the engine CLI @@ -182,9 +159,6 @@ The uninstaller: - Removes the exact line the installer wrote into a shell startup file (only that line; other PATH configuration is untouched). -Binaries installed by `go install` are not managed by these uninstallers: delete -`$(go env GOPATH)/bin/oberth` and `jev-attention` directly; runtime state is handled as below. - By default it **keeps** `~/.option-berth` runtime state (database, logs, runs, configuration). When you are sure it is no longer needed: diff --git a/docs/install.zh.md b/docs/install.zh.md index 9df29320..80e69002 100644 --- a/docs/install.zh.md +++ b/docs/install.zh.md @@ -60,15 +60,6 @@ Windows 安装器同样支持镜像回退,也可以用代理入口启动: irm https://ghfast.top/https://raw.githubusercontent.com/SheathedSharp/option-berth/main/install.ps1 | iex ``` -`go install` 不经过 Release 资产,改用 Go 模块代理即可,校验和仍会核对: - -```sh -GOPROXY=https://goproxy.cn go install github.com/sheathedsharp/option-berth/engine/cmd/oberth@latest -``` - -只设 `GOPROXY` 就够了:Go 会通过代理的 `/sumdb/` 端点校验模块。不要追加 `,direct`, -代理未命中时会回落到直连 GitHub,也就是超时的那条路径;也不需要 `GOSUMDB=off`。 - 第三方代理能看到下载流量,也可能被替换。需要严格来源时用 `--version` 固定版本,并对照 Releases 里的 `SHA256SUMS`;发布包签名校验尚未提供。 @@ -89,18 +80,6 @@ irm https://raw.githubusercontent.com/SheathedSharp/option-berth/main/install.ps Windows 安装器在替换文件前会检查 `oberth` / `jev-attention` 是否正在运行; 正在运行就先执行 `oberth daemon stop`,再重新安装。 -## go install(Go 1.25+) - -```sh -go install github.com/sheathedsharp/option-berth/engine/cmd/oberth@latest - -# Optional Jev adapter -go install github.com/sheathedsharp/option-berth/engine/cmd/jev-attention@latest -``` - -需要 v1.1.2 或更新版本。固定版本用 `@v1.1.2`。二进制进 `$(go env GOPATH)/bin`(或 `GOBIN`), -该目录需要在 PATH 中。 - ## Homebrew 自建 tap,不需要等 homebrew-core 收录。它安装引擎 CLI(`oberth` 和 `jev-attention`), @@ -170,9 +149,6 @@ irm https://raw.githubusercontent.com/SheathedSharp/option-berth/main/uninstall. - 删除安装器放在 `~/.local/share/option-berth` 的许可与构建清单; - 删除安装器写进 shell 启动文件的那一行(只删自己写的精确行,不动其他 PATH 配置)。 -`go install` 安装的二进制不由这些卸载器管理:直接删除 `$(go env GOPATH)/bin/oberth` 与 -`jev-attention`;运行状态的处理与下面相同。 - 默认**保留** `~/.option-berth` 运行状态(数据库、日志、runs、配置)。确认不再需要时: ```sh From 3aec0e34751cb81ebf12d19c29310c13d372e0fc Mon Sep 17 00:00:00 2001 From: zayJu Date: Wed, 11 Nov 2026 19:02:24 +0800 Subject: [PATCH 2/4] =?UTF-8?q?chore(release):=20=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E4=B8=8D=E5=86=8D=E5=88=9B=E5=BB=BA=20engine/=20=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit engine/ 标签的唯一用途是 go install 的模块版本标记。渠道移除后它没有消费方, release.py 的 --validate-tag 不再要求它存在,发版只创建 vX.Y.Z。 Co-Authored-By: Claude Code --- .agents/skills/option-berth-delivery/SKILL.md | 4 ++-- docs/agent/releasing.md | 11 +++-------- scripts/release.py | 5 ----- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/.agents/skills/option-berth-delivery/SKILL.md b/.agents/skills/option-berth-delivery/SKILL.md index c291e7e5..ca67ce3f 100644 --- a/.agents/skills/option-berth-delivery/SKILL.md +++ b/.agents/skills/option-berth-delivery/SKILL.md @@ -76,7 +76,7 @@ worktree、提交信息与用户确认的规则不变。 ## 发布 发布和普通改动走同一条 PR 路径:版本 PR 只改 `VERSION`(协议版本发布同时改 -`ProtocolVersion` 与生成的 schema),合并后在合并提交上创建注释标签 `vX.Y.Z` 与 -`engine/vX.Y.Z` 并推送。`Verified release` 在 runner 上跑完整门槛,通过后才构建和发布资产。 +`ProtocolVersion` 与生成的 schema),合并后在合并提交上创建注释标签 `vX.Y.Z` 并推送。 +`Verified release` 在 runner 上跑完整门槛,通过后才构建和发布资产。 本机不再有创建版本提交、打标签或推送的快捷入口;`scripts/release.py` 只保留 `--verify-only` 与 `--validate-tag`。打标签仍是发布动作,需要单独授权。 diff --git a/docs/agent/releasing.md b/docs/agent/releasing.md index 8d9c9493..443aad6b 100644 --- a/docs/agent/releasing.md +++ b/docs/agent/releasing.md @@ -16,10 +16,6 @@ This repository's release assets are the engine only: No macOS application, DMG, notarized bundle, client screenshot or skill installer is published here. -The engine module path is `github.com/sheathedsharp/option-berth/engine`; -`go install github.com/sheathedsharp/option-berth/engine/cmd/oberth@vX.Y.Z` builds straight from the -Git tag without going through release assets and without needing an extra module repository. - The install entry points are `install.sh` (macOS/Linux) and `install.ps1` (Windows) at the repository root, plus the matching `uninstall.sh` / `uninstall.ps1`; they are not release assets and are served from `main`: @@ -62,9 +58,8 @@ maintained only in their own repositories. The product version is **X1.X2.X3**, and the root `VERSION` file is the single source of the engine version (no `v`). Git tags use `vX1.X2.X3`, must be annotated, and must point at a verified commit that -belongs to `main`'s history. Every release also creates an annotated `engine/vX1.X2.X3` tag on the same -commit; it is the Go version tag for the `engine/` submodule, and -`go install .../engine/cmd/oberth@vX1.X2.X3` depends on it. +belongs to `main`'s history. The release assets are the only install channel the tag drives: the engine +is not published as a Go module, and a release creates no `engine/` tag. | Change | Step | Example | | --- | --- | --- | @@ -101,7 +96,7 @@ pushing; `scripts/release.py` keeps only `--verify-only` and `--validate-tag` fo 1. Branch from `main`, change only `VERSION` (a protocol release also changes `ProtocolVersion` and regenerates the schema), commit `chore(release): vX.Y.Z`, and open a PR. 2. Once the PR's required checks pass and it is confirmed, merge with a merge commit. -3. Create the annotated tags `vX.Y.Z` and `engine/vX.Y.Z` on the merge commit and push them. +3. Create the annotated tag `vX.Y.Z` on the merge commit and push it. 4. `Verified release` runs `policy` / `verify` / `windows` / `package` / `publish` against the tag, executing the same gates as `scripts/release.py --verify-only` on the runner, and only then builds assets and promotes the draft. diff --git a/scripts/release.py b/scripts/release.py index 41ecb0d2..afe7950b 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -91,11 +91,6 @@ def validate_tag(root: Path, tag: str) -> None: raise ValueError("release tag must be annotated") if run(root, "git", "rev-parse", "refs/tags/" + tag + "^{commit}") != run(root, "git", "rev-parse", "HEAD"): raise ValueError("checkout is not the tagged commit") - module_tag = "engine/" + tag - if run(root, "git", "cat-file", "-t", "refs/tags/" + module_tag) != "tag": - raise ValueError("engine module tag must be annotated") - if run(root, "git", "rev-parse", "refs/tags/" + module_tag + "^{commit}") != run(root, "git", "rev-parse", "HEAD"): - raise ValueError("engine module tag does not point at the tagged commit") run(root, "git", "merge-base", "--is-ancestor", "HEAD", "origin/main") From bcd7b628663d7f66770cab48c01d6590e148d327 Mon Sep 17 00:00:00 2001 From: zayJu Date: Wed, 11 Nov 2026 19:02:37 +0800 Subject: [PATCH 3/4] =?UTF-8?q?chore(engine):=20=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=85=9C=E5=BA=95=E4=B8=8E=E5=AE=89=E8=A3=85=E6=B8=A0=E9=81=93?= =?UTF-8?q?=E8=AF=B4=E6=98=8E=E4=B8=8D=E5=86=8D=E7=89=B9=E6=8C=87=20go=20i?= =?UTF-8?q?nstall?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit buildinfo 的模块版本兜底对任何未打 ldflags 的构建都适用,注释与用例标题按实际语义命名。 欢迎屏的渠道列举同步去掉已移除的 go install。 Co-Authored-By: Claude Code --- engine/internal/buildinfo/buildinfo.go | 6 +++--- engine/internal/buildinfo/buildinfo_test.go | 4 ++-- engine/internal/cmd/root.go | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/engine/internal/buildinfo/buildinfo.go b/engine/internal/buildinfo/buildinfo.go index 4a196510..5be39e29 100644 --- a/engine/internal/buildinfo/buildinfo.go +++ b/engine/internal/buildinfo/buildinfo.go @@ -30,9 +30,9 @@ func VersionString() string { // VersionValue returns the normalized SemVer value stamped into this build. // -// `go install module@version` does not apply this package's link flags, so the -// stamped value stays "dev". In that case the module version is still available -// through the build info and is what a user expects `oberth version` to show. +// A build that does not apply this package's link flags leaves the stamped +// value at "dev". In that case the module version is still available through +// the build info and is what a user expects `oberth version` to show. // Development builds keep their explicit `dev` marker. func VersionValue() string { return versionValue(Version, debug.ReadBuildInfo) diff --git a/engine/internal/buildinfo/buildinfo_test.go b/engine/internal/buildinfo/buildinfo_test.go index 50693a87..c6bd1580 100644 --- a/engine/internal/buildinfo/buildinfo_test.go +++ b/engine/internal/buildinfo/buildinfo_test.go @@ -22,8 +22,8 @@ func TestVersionValueFallsBackToModuleVersion(t *testing.T) { }{ {name: "linked version wins", stamped: "1.2.3", read: installed, want: "v1.2.3"}, {name: "linked v prefix is kept", stamped: "v1.2.3", read: installed, want: "v1.2.3"}, - {name: "go install falls back to module version", stamped: "dev", read: installed, want: "v1.2.3"}, - {name: "go install normalizes bare module version", stamped: "dev", read: func() (*debug.BuildInfo, bool) { + {name: "unstamped build falls back to module version", stamped: "dev", read: installed, want: "v1.2.3"}, + {name: "unstamped build normalizes bare module version", stamped: "dev", read: func() (*debug.BuildInfo, bool) { return &debug.BuildInfo{Main: debug.Module{Version: "1.2.3"}}, true }, want: "v1.2.3"}, {name: "development build keeps dev", stamped: "dev", read: devel, want: "dev"}, diff --git a/engine/internal/cmd/root.go b/engine/internal/cmd/root.go index 05f05c21..c6a4bd6e 100644 --- a/engine/internal/cmd/root.go +++ b/engine/internal/cmd/root.go @@ -237,8 +237,8 @@ var rootCmd = &cobra.Command{ } printWelcome(cmd.OutOrStdout(), welcomeVersion()) // The first screen is the only place the product asks. It is also the - // only place that reaches every install channel — the scripts, brew, - // deb/rpm and `go install` all end up running this binary. + // only place that reaches every install channel — the scripts, brew and + // deb/rpm all end up running this binary. askFeedbackOnce() return nil }, From 2289196b62c2ffe3cc440e4cd6ec932db0c10598 Mon Sep 17 00:00:00 2001 From: zayJu Date: Wed, 11 Nov 2026 19:03:11 +0800 Subject: [PATCH 4/4] =?UTF-8?q?test(release):=20=E5=88=A0=E9=99=A4=20go=20?= =?UTF-8?q?install=20=E6=A8=A1=E5=9D=97=E4=BB=A3=E7=90=86=E5=9B=9E?= =?UTF-8?q?=E5=BD=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 该用例走本地 file 代理并写死 v1.99.0-test 版本,永远只覆盖 1.x 形状,渠道移除后失去意义。 validation.md 同步删掉对应说明。 Co-Authored-By: Claude Code --- docs/agent/validation.md | 5 --- scripts/go_install_test.py | 72 -------------------------------------- 2 files changed, 77 deletions(-) delete mode 100644 scripts/go_install_test.py diff --git a/docs/agent/validation.md b/docs/agent/validation.md index 253cf34f..28652a44 100644 --- a/docs/agent/validation.md +++ b/docs/agent/validation.md @@ -361,11 +361,6 @@ releases API, and do not contact real GitHub; cache reads and writes use a tempo automatic check on the first screen is enabled only in terminal sessions, and does not fire when the test process's stdout is not a terminal. -`scripts/go_install_test.py` runs a real `go install` through a local file module proxy, installing -`engine/cmd/oberth` and `engine/cmd/jev-attention`, and verifies that `version --json` uses the -module version. This validates the module paths, the binary name of `cmd/oberth`, and the version -fallback when `go install` does not go through `-ldflags`. - The Linux package tests generate `.deb`/`.rpm` from fixture archives with `nfpm` and check control fields, install paths, license, and md5sums; when `dpkg-deb` is available the package is read with dpkg, and when `rpm` is available the package contents are listed. `nfpm` does not depend on diff --git a/scripts/go_install_test.py b/scripts/go_install_test.py deleted file mode 100644 index 634649e9..00000000 --- a/scripts/go_install_test.py +++ /dev/null @@ -1,72 +0,0 @@ -"""Install the engine through a local file module proxy, the way `go install` does. - -This catches the two things a normal build does not: the module path must match -the repository subdirectory, and cmd/oberth must be the installed package name. -""" -import json -import os -from pathlib import Path -import shutil -import subprocess -import tempfile -import time -import unittest -import zipfile - -ROOT = Path(__file__).resolve().parent.parent -ENGINE = ROOT / "engine" -MODULE = "github.com/sheathedsharp/option-berth/engine" -PACKAGE = MODULE + "/cmd/oberth" -ADAPTER = MODULE + "/cmd/jev-attention" - - -@unittest.skipUnless(shutil.which("go"), "go is not installed") -class GoInstallTests(unittest.TestCase): - def test_go_install_produces_oberth_and_jev_attention_with_release_version(self): - version = f"v1.99.0-test.{int(time.time() * 1000)}" - with tempfile.TemporaryDirectory(prefix="berth-go-install-test-") as temporary: - root = Path(temporary) - proxy = root / "proxy" - module_dir = proxy / MODULE / "@v" - module_dir.mkdir(parents=True) - prefix = f"{MODULE}@{version}/" - with zipfile.ZipFile(module_dir / f"{version}.zip", "w", zipfile.ZIP_DEFLATED) as zipped: - for path in sorted(ENGINE.rglob("*")): - if not path.is_file() or ".git" in path.parts: - continue - zipped.write(path, prefix + path.relative_to(ENGINE).as_posix()) - (module_dir / f"{version}.mod").write_bytes((ENGINE / "go.mod").read_bytes()) - (module_dir / f"{version}.info").write_text( - json.dumps({"Version": version, "Time": "2026-10-29T00:00:00Z"}) + "\n" - ) - (module_dir / "list").write_text(version + "\n") - - binaries = root / "bin" - (root / "home").mkdir() - env = dict(os.environ) - env.update( - GOPROXY=f"file://{proxy},https://proxy.golang.org,direct", - GOSUMDB="off", - GOFLAGS="-mod=mod", - GOBIN=str(binaries), - GOTOOLCHAIN="local", - ) - for package in (PACKAGE, ADAPTER): - result = subprocess.run( - ["go", "install", f"{package}@{version}"], - cwd=root, env=env, capture_output=True, text=True, timeout=300, - ) - self.assertEqual(result.returncode, 0, result.stderr[-4000:]) - - oberth = binaries / "oberth" - self.assertTrue(oberth.is_file()) - self.assertTrue((binaries / "jev-attention").is_file()) - document = json.loads(subprocess.run( - [str(oberth), "version", "--json"], - capture_output=True, text=True, timeout=20, env=dict(os.environ, HOME=str(root / "home")), - ).stdout) - self.assertEqual(document["version"], version) - - -if __name__ == "__main__": - unittest.main()