# AtomGit 平台备忘与仓库描述文案(dsh-history-fictionologists) > 事实来源:本机对 `api.atomgit.com` 与 `atomgit.com` 的**实测探针**(命令与原始输出见 §5), > 以及官方 OpenAPI 文档 。 > 本文既是 About 文案备料,也是 `scripts/release-atomgit.mjs` 为什么长成那样的依据。 --- ## 1. 为什么单开一份 AtomGit 文档 AtomGit 不是「换了个域名的 GitHub」。把 `lib/release-kit.mjs` 的主机名一改就发版, 会在四个地方撞墙,其中两个**静默失败**。以下四条都是实测或官方文档确认的: | # | 差异 | 照搬 GitHub 的后果 | |---|---|---| | 1 | 认证头是 GitLab 风格的 **`PRIVATE-TOKEN`**(`Authorization: Bearer` 官方也认) | 用 `Authorization: token …` 会拿到 `401 token not found` | | 2 | Release 响应里**没有数字 `id`**,只有 `tag_name` | 后续「传附件 / 改正文」全部无从下手 | | 3 | **没有** `POST /releases/:id/attach_files`;附件走**签名两步法** | 该接口在 AtomGit 上返回 404 | | 4 | **同名附件覆盖不生效**(PUT 返回成功,下载拿到的还是旧文件) | 修了 bug 重新上传,用户下到的还是旧制品——**静默失败** | 签名两步法:先 `GET /api/v5/repos/:owner/:repo/releases/:tag/upload_url?file_name=<名字>` 拿到一个对象存储(OBS)的预签名 URL **和一组 `x-obs-*` 请求头**; 再把这些头**原样**带回 `PUT` 内容。少了任何一个 `x-obs-*`,对象存储要么拒绝, 要么写入成功但**回调不触发**——附件在 Release 页面上就是不出现。 > 另有一条来自社区实测记录(): > `PATCH /releases/:tag` **不接受部分更新**,必须把 `tag_name` / `target_commitish` / > `name` / `body` / `prerelease` / `draft` 全量传一遍,否则报 `PARAMETER_ERROR must not be blank`。 > 本仓库的脚本因此对「创建」和「更新」发送**同一个完整 body**。 --- ## 2. About 短描述 GitHub 的上限是 350 字符;AtomGit 的输入框更窄,沿用同一句即可(105 字符): ``` 基于《崩坏:星穹铁道》官方世界观的 DSH 二创插件(/gs):神人制造机出科幻灵感、构史文集写短篇、星际构史播报编新闻;12 个 Wiki 数据源增量抓取并本地缓存,抓不到就自动回退缓存。非营利二创,MIT。 ``` 英文备选(面向检索,226 字符): ``` A DeepSeek Harness (DSH) plugin (/gs) for Honkai: Star Rail fan fiction: story ideas, short stories and fake interstellar news built on 12 incrementally cached Bwiki datasets. Unofficial, non-commercial fan work. ``` --- ## 3. 安装地址(给 README / Release 正文用) ```powershell # AtomGit(国内网络更稳) dsh plugin --profile add https://atomgit.com/Scombriformes/dsh-history-fictionologists # GitHub dsh plugin --profile add github:Kaede0614/dsh-history-fictionologists ``` `package.json` 里的 `repository` / `homepage` / `bugs` 仍然指向 GitHub: **AtomGit 是分发镜像,不是主仓**。这一点是有意为之——不要为了「双平台对等」把字段改成其中之一,那样只会让两边各说各话。 > **附件下载域名有两条,实测都能用(2026-09-27,v0.3.0)**:Release API 里附件的 > `browser_download_url` 指向 **`gitcode.com`**,而 > `atomgit.com///releases/download//` 同样可取到同一份字节: > 两条链接都回 `HTTP 200`、**152089 字节、sha256 `de155aa1…` 一致**。 > 这条只是下载域名的镜像关系,不属于 §1 那张表讲的 REST API 形状差异, > 所以**不并进那四条**(`lib/atomgit-kit.mjs` 的文件头也仍按「四条差异」叙述)。 --- ## 4. 发版命令 ```powershell # 预演:只打计划,不写任何东西(本条无需令牌) node scripts/release-atomgit.mjs --repo Scombriformes/dsh-history-fictionologists # 首次建仓 + 推 main + 推 tag + 建 Release + 传 tgz + 下载回验 node scripts/release-atomgit.mjs --publish --create-repo # 之后每次发版(仓库已存在) node scripts/release-atomgit.mjs --publish --repo Scombriformes/dsh-history-fictionologists ``` 前置条件只有一条:在 建一把 classic 令牌, **并且勾上权限**(`api`、`read_user`、`read_repository`、`write_repository`), 写进仓库根的 `.atomgit-token`(**已 gitignore**)或环境变量 `ATOMGIT_TOKEN`。 **什么都不勾的令牌「有效但什么都做不了」**——见 §5.1 的实测两种报错。 令牌的两种用法都不进日志、不进 argv: - API 调用走 `PRIVATE-TOKEN` 请求头; - `git push` 走一次性 `credential.helper`,它从环境变量读密码 (`-c credential.helper=` 先清空继承来的 helper,否则本机的 Git Credential Manager 不认识 `atomgit.com`,会退回交互式提示)。 脚本与 GitHub 支路一样是**幂等**的:Release 已存在就 `PATCH`,同名附件先 `DELETE` 再上传 (第 4 条差异决定这一步不能省),传完把附件**下载回来比 sha256**—— 「API 里有一个同名附件」和「用户下到的字节就是我们构建的字节」不是一回事。 --- ## 5. 实测探针(原始命令与输出) ```powershell # 连通性:api.atomgit.com 可达 Invoke-WebRequest -Uri "https://api.atomgit.com" -Method Head -TimeoutSec 20 # -> HTTP 200 # 账号存在 Invoke-RestMethod "https://api.atomgit.com/api/v5/users/Scombriformes" # -> login=Scombriformes, id=6ab48d892985d10201b6ecc6, created_at=2026-09-24T10:40:09+08:00 # 仓库不存在时:git 传输层返回 403 + 「project could not be found」 git ls-remote --heads --tags https://atomgit.com/Scombriformes/dsh-history-fictionologists.git # -> remote: The project you were looking for could not be found. Request-id is jcxy2fNaFp. # fatal: ... The requested URL returned error: 403 # 仓库存在时:branches 端点 200,且能读到分支与提交 Invoke-RestMethod "https://api.atomgit.com/api/v5/repos///branches" # -> 200 [{"name":"main","commit":{...}}] # 404 是「没有 Release」而不是「没有仓库」的常规信号(本仓库发布前实测) Invoke-WebRequest "https://api.atomgit.com/api/v5/repos///releases/tags/v0.2.0" # -> 404 # 同一个「不存在」,**不同端点、不同传输层、甚至不同次调用给的状态码都不一样** # (实测,见 _evidence/atomgit-probe.txt): # 匿名 GET /repos/:owner/:repo -> 401(第一次跑) / 404(第二次跑)← 同一请求两种答案 # 匿名 GET /repos/:owner/:repo/branches -> 404 # git ls-remote https://atomgit.com/... -> 403 project could not be found # 带令牌 以上全部 -> 稳定 404 {"error_message":"Project not found:…"} # # 结论写进了 lib/atomgit-kit.mjs:**绝不从「未授权响应」推断任何事**。 # 本工具链的每一次调用都带令牌,只看带令牌时的 404。 ``` 再跑一遍全部只读探针(脚本只读、只 GET,**一个字符的令牌都不打印**): ```powershell node _evidence/atomgit-probe.mjs | Tee-Object -FilePath _evidence/atomgit-probe.txt ``` --- ## 5.1 令牌的 scope 不能留空(实测踩过) 在 建令牌时**必须勾权限**,否则令牌「有效但什么都不能做」: ```powershell # 一个没勾任何 scope 的令牌,实测表现: GET /api/v5/user -> 403 {"error_code_name":"FORBIDDEN","error_message":"no scopes:read_user"} GET /api/v5/repos/:owner/:repo/... -> 403 {"error_code_name":"UN_KNOW", "error_message":"CH.00000403 apig token has not permission to request url"} ``` 两种报错长得完全不同,但根因是一个。本工具链需要的 scope: ``` api read_user read_repository write_repository ``` (`issues` / `pull_requests` 本流程用不到,要提 Issue 再勾。) `lib/atomgit-kit.mjs` 的 `ATOMGIT_SCOPES` 就是这份清单,并会把它写进 403 的报错正文里。 --- ## 6. 一段需要如实记录的历史 AtomGit 上**曾经**有一个同名仓库(`Scombriformes/dsh-history-fictionologists`), 装的是本项目的一个**旧原型**: ``` .gitattributes .gitignore CHANGELOG.md cordis.patch.yml data/worldbook.json index.js lib/args.js lib/extract.js lib/fetch.js lib/prompts.js lib/sources.js LICENSE README.md RELEASE-NOTES-v0.1.0.md RELEASE-NOTES-v0.1.1.md ``` (`GET /api/v5/repos/:owner/:repo/git/trees/:sha?recursive=1` 实测输出。) 它与当前代码**没有任何共同提交历史**:旧仓 `main` 停在 `cc09bd5`(v0.1.1, `/fictionologist` 命令、14 个数据源、108 个单测),当前工作区是单提交的 `b8221bc`(v0.2.0, `/gs` 命令、12 个数据源、124 个单测),`git merge-base` 为空。 所以本次发布是**重新建仓**,而不是在旧仓上追加——旧仓由作者在 2026-09-26 删除。 记这一段的理由:AtomGit 上曾出现 `v0.1.1`,而当前代码是 `0.2.x`(GitHub 上 `v0.2.0`, 本次发 `v0.2.1`),看起来像「同一个仓库的版本往回走」。事实不是倒退,是两条血脉, 而其中一条已经作废。本次是**重新建仓**,新仓的第一个 tag 就是 `v0.2.1`。