dsh-compound-engineering 0.1.1 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/README.zh.md +4 -3
- package/docs/releasing.md +423 -0
- package/package.json +4 -2
- package/skills/ce-babysit-pr/scripts/pr-snapshot +0 -0
- package/skills/ce-brainstorm/scripts/elevation-dispatch.sh +0 -0
- package/skills/ce-code-review/scripts/cross-model-adversarial-review.sh +0 -0
- package/skills/ce-compound/scripts/session-history/discover-sessions.sh +0 -0
- package/skills/ce-doc-review/scripts/cross-model-doc-review.sh +0 -0
- package/skills/ce-optimize/scripts/experiment-worktree.sh +0 -0
- package/skills/ce-optimize/scripts/measure.sh +0 -0
- package/skills/ce-optimize/scripts/parallel-probe.sh +0 -0
- package/skills/ce-plan/scripts/elevation-dispatch.sh +0 -0
- package/skills/ce-polish/scripts/detect-project-type.sh +0 -0
- package/skills/ce-polish/scripts/detect-riffrec.sh +0 -0
- package/skills/ce-polish/scripts/read-launch-json.sh +0 -0
- package/skills/ce-polish/scripts/resolve-package-manager.sh +0 -0
- package/skills/ce-polish/scripts/resolve-port.sh +0 -0
- package/skills/ce-pov/scripts/cross-model-pov.sh +0 -0
- package/skills/ce-resolve-pr-feedback/scripts/get-pr-comments +0 -0
- package/skills/ce-resolve-pr-feedback/scripts/get-thread-for-comment +0 -0
- package/skills/ce-resolve-pr-feedback/scripts/reply-to-pr-thread +0 -0
- package/skills/ce-resolve-pr-feedback/scripts/resolve-pr-thread +0 -0
- package/skills/ce-setup/scripts/check-health +0 -0
- package/skills/ce-test-browser/scripts/resolve-port.sh +0 -0
- package/skills/ce-work/scripts/cross-model-work.sh +0 -0
- package/skills/ce-compound/scripts/session-history/__pycache__/dsh_session.cpython-314.pyc +0 -0
- package/skills/ce-work/scripts/__pycache__/unit_workspace_jobs.cpython-314.pyc +0 -0
- package/skills/ce-work/scripts/__pycache__/unit_workspace_state.cpython-314.pyc +0 -0
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ Or do it by hand: add the dependency to the profile's `package.json`, then list
|
|
|
39
39
|
|
|
40
40
|
```jsonc
|
|
41
41
|
{
|
|
42
|
-
"dependencies": { "dsh-compound-engineering": "^0.1.
|
|
42
|
+
"dependencies": { "dsh-compound-engineering": "^0.1.1" },
|
|
43
43
|
"dsh": { "profile": { "bundles": ["dsh-compound-engineering"] } }
|
|
44
44
|
}
|
|
45
45
|
```
|
|
@@ -103,11 +103,12 @@ Upstream targets 14 hosts including Claude Code. The port does this:
|
|
|
103
103
|
|
|
104
104
|
```bash
|
|
105
105
|
npm test # JS unit + integration, then the Python suites
|
|
106
|
-
npm run test:smoke # three layers: provider / registry / plugin lifecycle
|
|
107
106
|
npm run test:py # Python suites only (session reader, Windows compat)
|
|
108
107
|
```
|
|
109
108
|
|
|
110
|
-
Integration tests need to find a DSH runtime: they import by package name first, then scan `~/.dsh/runtime/versions/*`. Point `DSH_RUNTIME` at it to override.
|
|
109
|
+
Integration tests need to find a DSH runtime: they import by package name first, then scan `~/.dsh/runtime/versions/*`. Point `DSH_RUNTIME` at it to override. When no runtime is found the whole group is skipped rather than failed.
|
|
110
|
+
|
|
111
|
+
Releasing is tag-driven: pushing a `v*` tag runs `.github/workflows/publish.yml`, which publishes through npm's OIDC trusted publisher (no local OTP, no stored token). See [docs/releasing.md](docs/releasing.md) for the full procedure and the failure modes already hit.
|
|
111
112
|
|
|
112
113
|
After pulling in upstream changes, re-run the two idempotent patch scripts:
|
|
113
114
|
|
package/README.zh.md
CHANGED
|
@@ -39,7 +39,7 @@ dsh plugin --profile web add dsh-compound-engineering
|
|
|
39
39
|
|
|
40
40
|
```jsonc
|
|
41
41
|
{
|
|
42
|
-
"dependencies": { "dsh-compound-engineering": "^0.1.
|
|
42
|
+
"dependencies": { "dsh-compound-engineering": "^0.1.1" },
|
|
43
43
|
"dsh": { "profile": { "bundles": ["dsh-compound-engineering"] } }
|
|
44
44
|
}
|
|
45
45
|
```
|
|
@@ -103,11 +103,12 @@ dsh plugin --profile web add dsh-compound-engineering
|
|
|
103
103
|
|
|
104
104
|
```bash
|
|
105
105
|
npm test # JS 单元 + 集成测试,随后跑 Python 测试
|
|
106
|
-
npm run test:smoke # 三层冒烟:provider / registry / 插件生命周期
|
|
107
106
|
npm run test:py # 只跑 Python 测试(会话读取器、Windows 兼容)
|
|
108
107
|
```
|
|
109
108
|
|
|
110
|
-
集成测试需要能找到 DSH 运行时。默认从包名 import,失败则扫描 `~/.dsh/runtime/versions/*`;也可以用 `DSH_RUNTIME`
|
|
109
|
+
集成测试需要能找到 DSH 运行时。默认从包名 import,失败则扫描 `~/.dsh/runtime/versions/*`;也可以用 `DSH_RUNTIME` 指过去。找不到运行时时整组跳过,不会报失败。
|
|
110
|
+
|
|
111
|
+
发版由 tag 驱动:推送 `v*` tag 会触发 `.github/workflows/publish.yml`,走 npm 的 OIDC trusted publisher 发布(无需本地 OTP、不在仓库里存 token)。完整流程与已踩过的坑见 [docs/releasing.md](docs/releasing.md)。
|
|
111
112
|
|
|
112
113
|
改上游技能后,重新跑这两个幂等补丁脚本:
|
|
113
114
|
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
# 发版与推送流程
|
|
2
|
+
|
|
3
|
+
> 本文记录 `dsh-compound-engineering` 的完整发布链路。踩过的坑都写进来了,
|
|
4
|
+
> 遇到异常先来这里对照,不要凭直觉重试。
|
|
5
|
+
|
|
6
|
+
## 0. 一页速查
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
cd /e/project/dsh-compound-engineering
|
|
10
|
+
|
|
11
|
+
npm version patch --no-git-tag-version # 0.1.2 → 0.1.3
|
|
12
|
+
git commit -am "chore: 0.1.3"
|
|
13
|
+
git tag v0.1.3
|
|
14
|
+
git push origin main
|
|
15
|
+
git push origin v0.1.3 # 关键:tag 必须单独推
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
推完去看 <https://github.com/zzzhangy/dsh-compound-engineering/actions>,
|
|
19
|
+
`publish` workflow 跑绿即发版完成。
|
|
20
|
+
|
|
21
|
+
**`git push origin main` 不会带上 tag。** 忘了这一条,Actions 会显示
|
|
22
|
+
“This workflow has no runs yet”,很多人误以为 workflow 没配好。
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 1. 前置条件(只需配一次)
|
|
27
|
+
|
|
28
|
+
### 1.1 npm 侧:登记 Trusted Publisher
|
|
29
|
+
|
|
30
|
+
<https://www.npmjs.com/package/dsh-compound-engineering/access> → **Trusted Publisher**
|
|
31
|
+
|
|
32
|
+
| 字段 | 值 |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| Publisher | GitHub Actions |
|
|
35
|
+
| Organization or user | `zzzhangy` |
|
|
36
|
+
| Repository | `dsh-compound-engineering` |
|
|
37
|
+
| Workflow filename | `publish.yml`(只填文件名,不要带 `.github/workflows/` 路径) |
|
|
38
|
+
| Environment name | 留空 |
|
|
39
|
+
|
|
40
|
+
Allowed actions 两个都勾:**Allow npm publish**、**Allow npm dist-tag**。
|
|
41
|
+
|
|
42
|
+
配好后状态是 `Pending validation` —— **必须成功发布一次才会转正**。
|
|
43
|
+
npm 给的期限是配置后 7 天内。
|
|
44
|
+
|
|
45
|
+
### 1.2 npm 侧:收紧发布策略
|
|
46
|
+
|
|
47
|
+
同一个 Settings 页面的 **Publishing access**,选:
|
|
48
|
+
|
|
49
|
+
> Require two-factor authentication **and disallow bypass 2fa tokens**
|
|
50
|
+
|
|
51
|
+
理由见 §4.1。改完点 **Update Package Settings**。
|
|
52
|
+
|
|
53
|
+
### 1.3 仓库侧:workflow 文件存在
|
|
54
|
+
|
|
55
|
+
`.github/workflows/publish.yml` 必须在**默认分支**上,且文件名与 npm 后台
|
|
56
|
+
填的完全一致(`publish.yml`)。OIDC 校验失败时 npm 的报错很模糊,通常是这里错了。
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 2. 发版步骤详解
|
|
61
|
+
|
|
62
|
+
### 2.1 升版本号
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm version patch --no-git-tag-version
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
用 `--no-git-tag-version` 是因为我们**想自己控制 tag 的创建时机和注解**。
|
|
69
|
+
`patch` / `minor` / `major` 按改动性质选。
|
|
70
|
+
|
|
71
|
+
### 2.2 提交
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
git commit -am "chore: 0.1.3"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 2.3 打 tag
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
git tag v0.1.3
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
tag 名必须与 `package.json` 的 version 严格对应(`v` + 版本号)。
|
|
84
|
+
workflow 第一步就会校验,不一致直接失败:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
tag v0.1.3 与 package.json 的 0.1.2 不一致,中止发布
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
想带说明可以用注解 tag(此时 `--follow-tags` 才会认):
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
git tag -a v0.1.3 -m "0.1.3"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 2.4 推送分支和 tag
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
git push origin main
|
|
100
|
+
git push origin v0.1.3
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**不要只推 main。** 触发条件是 `on: push: tags: ['v*']`,分支推送不触发。
|
|
104
|
+
|
|
105
|
+
`git push origin main --follow-tags` 看起来更省事,但 **`--follow-tags` 只推注解 tag**,
|
|
106
|
+
轻量 tag(`git tag v0.1.3` 这种)会被静默跳过。分两条命令最稳。
|
|
107
|
+
|
|
108
|
+
### 2.5 观察运行
|
|
109
|
+
|
|
110
|
+
<https://github.com/zzzhangy/dsh-compound-engineering/actions>
|
|
111
|
+
|
|
112
|
+
成功会看到 7 个步骤全绿:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
✓ checkout
|
|
116
|
+
✓ setup-node
|
|
117
|
+
✓ 校验 tag 与 package.json 版本一致
|
|
118
|
+
✓ 确保 python 命令可用
|
|
119
|
+
✓ 跑测试
|
|
120
|
+
✓ 确认打包结果里没有 __pycache__
|
|
121
|
+
✓ 发布到 npm
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
发布完成后 npm 页面上:
|
|
125
|
+
|
|
126
|
+
- Trusted Publisher 的黄色 `Pending validation` 变成绿勾
|
|
127
|
+
- 包名旁出现 **Provenance** 徽章(证明包来自该仓库的该 commit)
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 3. 发布前自检
|
|
132
|
+
|
|
133
|
+
workflow 会跑这些,本地最好先过一遍,省一轮 CI:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npm test # 期望 JS 38 pass / 0 fail、py 33 OK
|
|
137
|
+
npm pack --dry-run # 看文件数和大小,期望 459 文件 / 1.8MB
|
|
138
|
+
git status --short # 期望干净
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
关于 `npm pack --dry-run` 的文件数:0.1.0 / 0.1.1 是 461(含 3 个 `.pyc`),
|
|
142
|
+
`prepack` 清掉 pyc 后是 458,`files` 收录 `docs/` 后是 **459**(0.1.3 起)。
|
|
143
|
+
**如果比上面多出 3 个,说明 pyc 又混进来了。**
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 4. 踩过的坑
|
|
148
|
+
|
|
149
|
+
### 4.1 bypass-2FA token 会强制走 staged publishing
|
|
150
|
+
|
|
151
|
+
**症状**(本项目首发时全套踩中):
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
npm publish → + dsh-compound-engineering@0.1.0 (显示成功)
|
|
155
|
+
curl registry.npmjs.org/... → dist-tags: {"latest":"0.0.0-stage"} (只有占位包)
|
|
156
|
+
npm publish → 409 Cannot publish over previously staged version "0.1.0"
|
|
157
|
+
npm stage list → No staged versions.(空的)
|
|
158
|
+
npm stage publish → 409 Cannot stage previously published version "0.1.0"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
服务端把版本记成“已暂存/已发布”,但 register 查不到、stage 列表为空 —— 版本进了黑洞。
|
|
162
|
+
|
|
163
|
+
**根因**:npm 11.x 对 bypass-2FA token 强制暂存发布,会先建 `0.0.0-stage`
|
|
164
|
+
占位包再异步处理。这个流程在“首次发布 + 占位包”组合下有 bug。
|
|
165
|
+
|
|
166
|
+
**后果**:`0.1.0` 这个版本号被永久占用,无法重发,只能升到 `0.1.1`。
|
|
167
|
+
|
|
168
|
+
**解决**:不要用 bypass token 首发新包。改用 §4.2 的 OIDC 路线,或普通 token。
|
|
169
|
+
|
|
170
|
+
### 4.2 普通 token 首发要浏览器授权(EOTP)
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
npm error code EOTP
|
|
174
|
+
npm error This operation requires a one-time password.
|
|
175
|
+
npm error Open this URL in your browser to authenticate:
|
|
176
|
+
npm error https://www.npmjs.com/auth/cli/<uuid>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
终端里那条 URL 在日志中被 `***` 遮蔽,**只出现在终端输出**。按 Enter 让 npm
|
|
180
|
+
打开浏览器,点 Authorize 后发布会自动继续。这是绕过 staged publishing 的方式,
|
|
181
|
+
但每次发版都要人工点一下 —— 所以才改用 OIDC。
|
|
182
|
+
|
|
183
|
+
### 4.3 发布有 5 分钟传播延迟
|
|
184
|
+
|
|
185
|
+
发布成功后立刻 `curl` 查 registry 可能查不到,tarball 返回 404。
|
|
186
|
+
**这是正常的**,等 5 分钟再查。当时我们误判成发布失败,白折腾了很久。
|
|
187
|
+
|
|
188
|
+
### 4.4 国内镜像导致安装 404
|
|
189
|
+
|
|
190
|
+
`~/.npmrc` 里 `registry` 指向淘宝镜像时,npm 的 `replace-registry-host`
|
|
191
|
+
(默认值 `npmjs`)会把官方 tarball 地址也改写成镜像域名。镜像尚未同步新版本时:
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
404 https://cdn.npmmirror.com/packages/dsh-compound-engineering/0.1.1/...tgz
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
包本身没问题。装新包时显式指定:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
npm i dsh-compound-engineering --registry=https://registry.npmjs.org --replace-registry-host=never
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### 4.5 `__pycache__` 混进发布包
|
|
204
|
+
|
|
205
|
+
**症状**:tarball 里出现 `skills/**/__pycache__/*.pyc`。
|
|
206
|
+
|
|
207
|
+
**根因**:`package.json` 的 `files` 白名单写了整个 `skills` 目录,而 npm 的规则是
|
|
208
|
+
—— **目录一旦被 `files` 收录,其中的忽略规则(`.npmignore` / `.gitignore`)全部失效**。
|
|
209
|
+
实测在根目录写 `**/__pycache__/` 也拦不住。
|
|
210
|
+
|
|
211
|
+
**解决**:`prepack` 钩子在打包前从磁盘删除(`scripts/clean-pycache.mjs`):
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
"prepack": "node scripts/clean-pycache.mjs"
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### 4.6 workflow 里用 `grep` 查 pyc 会必然误报
|
|
218
|
+
|
|
219
|
+
`prepack` 的日志本身就会打印 `prepack: 清理了 3 个 __pycache__ 目录`,
|
|
220
|
+
所以下面这种写法**每次都会失败**:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# ❌ 错误:日志命中
|
|
224
|
+
if npm pack --dry-run 2>&1 | grep -qE '__pycache__|\.pyc'; then exit 1; fi
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
正确做法是解析 `--json` 的文件清单。另外 `prepack` 的 stdout 会混在 JSON 之前,
|
|
228
|
+
必须按行首的 `[` 定位数组起点:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
npm pack --dry-run --json > pack.json
|
|
232
|
+
node -e '
|
|
233
|
+
const raw = require("fs").readFileSync("pack.json", "utf8");
|
|
234
|
+
const m = raw.match(/^\[$/m);
|
|
235
|
+
...'
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### 4.7 ubuntu runner 没有 `python` 命令
|
|
239
|
+
|
|
240
|
+
`npm run test:py` 调的是 `python`,而 ubuntu-latest 默认只有 `python3`。
|
|
241
|
+
workflow 里补了一步软链(见 `.github/workflows/publish.yml`)。
|
|
242
|
+
|
|
243
|
+
### 4.8 tag 推了但 Actions 没跑
|
|
244
|
+
|
|
245
|
+
看远端到底有没有 tag:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
git ls-remote origin main refs/tags/v0.1.3
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
如果只有 `main` 没有 `refs/tags/...`,就是 tag 没推上去(最常见的原因)。
|
|
252
|
+
再确认 tag 名匹配 `v*` 通配符。
|
|
253
|
+
|
|
254
|
+
### 4.9 Windows 上 git push 挂起
|
|
255
|
+
|
|
256
|
+
**症状**:`git push` 长时间无输出,120s/150s 超时,`exit code 124`。
|
|
257
|
+
|
|
258
|
+
**根因**:卡在 `git credential-helper-selector get`(Windows Git 的凭据选择器弹窗),
|
|
259
|
+
在无头/自动化环境里会一直阻塞。用 `GIT_TRACE=1 git push` 可以看到卡点。
|
|
260
|
+
|
|
261
|
+
**解决**:在真实终端里手动推一次,弹窗里选 GitHub 账号即可。之后的推送
|
|
262
|
+
会用缓存的凭据,不再弹窗。
|
|
263
|
+
|
|
264
|
+
排查时可以排除的因素(本次都验证过不是它们):
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
git config --get http.proxy # 空
|
|
268
|
+
env | grep -i proxy # 有 127.0.0.1:7890,但绕过代理照样挂起
|
|
269
|
+
git config --get credential.helper # helper-selector ← 就是它
|
|
270
|
+
GIT_TERMINAL_PROMPT=0 git ls-remote origin main # 1.2s 返回,说明网络正常
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
`ls-remote` 秒回而 `push` 挂起,说明卡在认证而非网络。
|
|
274
|
+
|
|
275
|
+
### 4.10 GitHub 仓库建的时候勾了 Add README
|
|
276
|
+
|
|
277
|
+
远端会有一个 `Initial commit`,与本地历史无共同祖先,push 直接被拒:
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
! [rejected] main -> main (fetch first)
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
解决:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
git fetch origin
|
|
287
|
+
git rebase origin/main # README.md 会有 add/add 冲突
|
|
288
|
+
# 解决冲突:保留本地完整 README,删掉 GitHub 生成的单行简介
|
|
289
|
+
git add README.md
|
|
290
|
+
GIT_EDITOR=true git rebase --continue
|
|
291
|
+
git push origin main
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
下次建仓库记得**不要勾 Add README**。
|
|
295
|
+
|
|
296
|
+
### 4.11 测试在 Windows 全绿、Linux CI 必挂
|
|
297
|
+
|
|
298
|
+
本项目是在 Windows 上开发的,而 CI 跑 ubuntu-latest。v0.1.2 的 CI 就挂在
|
|
299
|
+
「跑测试」这一步,本地怎么都复现不出来。根因是**测试自身的前置条件**踩到了
|
|
300
|
+
脚本里的 POSIX 校验,而 Windows 分支走的是 ACL/owner 检查,根本不看 mode 位。
|
|
301
|
+
|
|
302
|
+
两处(都在 `test/test_windows_compat.py`):
|
|
303
|
+
|
|
304
|
+
```python
|
|
305
|
+
# ❌ os.makedirs 用默认 umask 建成 0755,随后 ensure_private_dir 的
|
|
306
|
+
# validate_private_dir 要求 mode 恰好 0700,POSIX 分支直接抛 TrustFailure
|
|
307
|
+
os.makedirs(result_dir)
|
|
308
|
+
state.ensure_private_dir(result_dir)
|
|
309
|
+
|
|
310
|
+
# ✅ 交给它自己创建,内部是 os.mkdir(path, 0o700)
|
|
311
|
+
state.ensure_private_dir(result_dir)
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
```python
|
|
315
|
+
# ❌ 默认 umask 022 → 0644,而 read_private_at 要求 0600
|
|
316
|
+
with open(target, "wb") as handle:
|
|
317
|
+
handle.write(payload)
|
|
318
|
+
|
|
319
|
+
# ✅ 显式指定 mode
|
|
320
|
+
fd = os.open(target, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
|
|
321
|
+
with os.fdopen(fd, "wb") as handle:
|
|
322
|
+
handle.write(payload)
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**教训**:任何涉及 `mode & 0o777`、`stat.S_IMODE`、`os.chmod`、`umask` 的测试,
|
|
326
|
+
在 Windows 上都得不到真实结果(Windows 的 mode 是合成的,目录一律显示 0777)。
|
|
327
|
+
写这类测试要么显式指定 mode,要么就假定它会跑在 Linux 上。
|
|
328
|
+
|
|
329
|
+
另外两个当时排除掉的怀疑方向,记下来省得下次重查:
|
|
330
|
+
|
|
331
|
+
- **路径大小写**:Linux 区分大小写,`References/x.md` 与 `references/x.md` 不等价。
|
|
332
|
+
实际用「按目录真实条目逐个解析」比对,缺失数 0。
|
|
333
|
+
- **行尾**:`.gitattributes` 已是 `* text=auto eol=lf`,`git ls-files --eol` 显示
|
|
334
|
+
`i/lf w/lf`,检出到 Linux 不会混入 `\r`。
|
|
335
|
+
|
|
336
|
+
### 4.12 CI 日志看不到时怎么定位
|
|
337
|
+
|
|
338
|
+
私有仓库 + 细粒度 token 权限不足时,日志接口会直接拒绝:
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
curl -H "Authorization: Bearer $TOKEN" \
|
|
342
|
+
https://api.github.com/repos/<owner>/<repo>/actions/jobs/<id>/logs
|
|
343
|
+
# → {"message": "Must have admin rights to Repository.", "status": 403}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
此时仍能看到**哪一步失败**(`GET /actions/runs` 里的 `conclusion`,配合 web 页面
|
|
347
|
+
高亮的步骤名),只是拿不到 stdout。剩下的靠读代码推:
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
# 列出所有平台分支敏感的调用
|
|
351
|
+
grep -n "IS_WINDOWS\|sys.platform\|process.platform" test/*.py test/*.mjs
|
|
352
|
+
# 找出「先建目录/文件、后校验」的组合
|
|
353
|
+
grep -n "makedirs\|os.mkdir\|open(.*\"wb\")" test/*.py
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## 5. 回滚与补救
|
|
359
|
+
|
|
360
|
+
### 5.1 想撤销一次发布
|
|
361
|
+
|
|
362
|
+
npm 不允许删除 24 小时内的版本,也不建议 `unpublish`。正确做法是**发布修复版本**,
|
|
363
|
+
然后把 `latest` 指回稳定版:
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
npm dist-tag add dsh-compound-engineering@0.1.2 latest
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
这也是为什么 Trusted Publisher 里要勾 **Allow npm dist-tag**。
|
|
370
|
+
|
|
371
|
+
### 5.2 把包标记为废弃
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
npm deprecate dsh-compound-engineering@0.1.3 "此版本有已知问题,请用 0.1.4"
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
用户安装时会看到警告,但已装的不会坏。
|
|
378
|
+
|
|
379
|
+
### 5.3 版本号被黑洞占用
|
|
380
|
+
|
|
381
|
+
如 §4.1 的 `0.1.0`:registry 查不到,但服务端记着“已发布”,无法重发。
|
|
382
|
+
只能升版本号。要彻底清理可以去 <https://github.com/npm/feedback> 提 issue。
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## 6. 本地开发与 profile 同步
|
|
387
|
+
|
|
388
|
+
开发期把本地目录装进 DSH profile 调试:
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
DSH=C:/Users/zhiAngZhang/.dsh/runtime/node_modules/.bin/dsh
|
|
392
|
+
"$DSH" plugin --profile web add "file:E:/project/dsh-compound-engineering"
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
⚠️ `file:` 安装走 pnpm directory 依赖,`node_modules/` 里是**实体拷贝不是软链**,
|
|
396
|
+
且 pnpm 把内容记在 lockfile 里 —— **改完源码后 `pnpm install` / `plugin update`
|
|
397
|
+
都不会刷新那份拷贝**,你会一直跑到旧代码。
|
|
398
|
+
|
|
399
|
+
刷新办法:删掉再装。
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
"$DSH" plugin --profile web remove dsh-compound-engineering
|
|
403
|
+
"$DSH" plugin --profile web add "file:E:/project/dsh-compound-engineering"
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
或者直接覆盖拷贝后比对:
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
SRC=E:/project/dsh-compound-engineering
|
|
410
|
+
DST=C:/Users/zhiAngZhang/.dsh/profiles/web/node_modules/dsh-compound-engineering
|
|
411
|
+
cp -rf "$SRC/skills" "$SRC/lib" "$SRC/package.json" "$DST/"
|
|
412
|
+
diff -rq "$SRC/skills" "$DST/skills" && echo "一致"
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## 7. 待办
|
|
418
|
+
|
|
419
|
+
- [x] Trusted Publisher 跑通一次,状态从 `Pending validation` 转正(v0.1.3 首次全绿)
|
|
420
|
+
- [ ] 把 `Publishing access` 改为 disallow bypass 2fa tokens
|
|
421
|
+
- [ ] 确认已删除临时 bypass token(<https://www.npmjs.com/settings/zhiangzhang1/tokens>)
|
|
422
|
+
- [ ] README 加 npm 徽章与 provenance 徽章
|
|
423
|
+
- [ ] 考虑加一个 `test:linux` 的本地校验脚本,提前拦住 §4.11 那类问题
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-compound-engineering",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Every 的 compound-engineering 方法论技能包 —— brainstorm → plan → work → review → compound,让每一次改动都让下一次更容易。DeepSeek Harness 移植版。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"files": [
|
|
15
15
|
"lib",
|
|
16
16
|
"skills",
|
|
17
|
+
"docs",
|
|
17
18
|
"cordis.patch.yml",
|
|
18
19
|
"LICENSE",
|
|
19
20
|
"README.md",
|
|
@@ -59,6 +60,7 @@
|
|
|
59
60
|
},
|
|
60
61
|
"scripts": {
|
|
61
62
|
"test": "node --test \"test/*.test.mjs\" && npm run test:py",
|
|
62
|
-
"test:py": "python -m unittest discover -s test -p \"test_*.py\""
|
|
63
|
+
"test:py": "python -m unittest discover -s test -p \"test_*.py\"",
|
|
64
|
+
"prepack": "node scripts/clean-pycache.mjs"
|
|
63
65
|
}
|
|
64
66
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|