@shundoo-ai/dsh-cosmic 1.0.8 → 1.0.10
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/package.json
CHANGED
|
@@ -90,7 +90,7 @@ description: >
|
|
|
90
90
|
> **build + 热部署**:R0 → R1 → R2 → R3 → R4 → R5。
|
|
91
91
|
> 每一步都给「期望」与「失败处置」;**不做即兴发挥**,缺规则就回写手册(见文末自检)。
|
|
92
92
|
|
|
93
|
-
> 🔁 **执行方式**:可以逐步执行,也可以把本手册**物化**成工作区内的临时脚本一次跑完(实测:Windows 会话把它写成 `<cwd>/.dsh/cosmic/scripts/hotdeploy.ps1`,此后"构建+热部署"每次只花 1 次调用)。**若物化,遵守四条**:① 放在 `.dsh/` 下(git 忽略、不入库);② **本手册是唯一权威**——手册更新后重新生成,不得反向以脚本为准;③ 脚本只做编排(发现 → 构建 →
|
|
93
|
+
> 🔁 **执行方式**:可以逐步执行,也可以把本手册**物化**成工作区内的临时脚本一次跑完(实测:Windows 会话把它写成 `<cwd>/.dsh/cosmic/scripts/hotdeploy.ps1`,此后"构建+热部署"每次只花 1 次调用)。**若物化,遵守四条**:① 放在 `.dsh/` 下(git 忽略、不入库);② **本手册是唯一权威**——手册更新后重新生成,不得反向以脚本为准;③ 脚本只做编排(发现 → 构建 → 注入),**不得引入手册之外的行为**(**允许**只读的发现/干跑模式 —— 不构建、不注入、不改环境,如 `-DryRun`);④ **不得写死本机路径**(工作区 / Gradle 根 / profile 名 / JDK 安装路径),工作区与 Gradle 根按 R1.1 推导、profile 用 `$DSH_PROFILE_DIR`、JDK 按 R2.1 顺位选择 —— 实测有脚本写死 `$cwd` 与 `profiles\web`,换机器即失效。**生成后自查**:在脚本里 grep 一遍本机绝对路径与写死的 profile 名,应当**只出现推导逻辑、不出现具体值**。
|
|
94
94
|
|
|
95
95
|
> **平台约定:本手册三平台通用**(Windows / macOS / Linux 各步骤都可用)。平台差异见下表;
|
|
96
96
|
> 失败分支表里**未标注平台的条目三平台通用**,标 `[Win]` 的只会发生在 Windows。
|
|
@@ -104,7 +104,7 @@ description: >
|
|
|
104
104
|
> |---|---|---|
|
|
105
105
|
> | PID 定位 | `Get-NetTCPConnection` → `Get-CimInstance`(**`jps` 看不到 SYSTEM 账户的 cosmic**) | `lsof -tiTCP:<port> -sTCP:LISTEN` 或 `jps -l \| grep JettyServer` |
|
|
106
106
|
> | classpath 分隔符 | `;` | `:` |
|
|
107
|
-
> | 沙箱 |
|
|
107
|
+
> | 沙箱 | 受限沙箱**砍令牌特权**(实测只剩 `SeChangeNotifyPrivilege`)→ 端口查询被拒、attach 缺 `SeDebugPrivilege`(见 F4);构建的 `CreatePipe error=5` 是另一条(见 F3) | 无此限制 |
|
|
108
108
|
> | shell / 变量 | PowerShell(DSH 兜底到 5.1,注意默认 ANSI 解码);`$env:VAR=` | bash/sh;`export VAR=` |
|
|
109
109
|
> | 构建可执行 | `gradle.bat`(按 wrapper 定版) | `gradle`(按 wrapper 定版) |
|
|
110
110
|
> | 缓存预热命令 | `robocopy`(见 R3.2) | `cp -R`(见 R3.2) |
|
|
@@ -157,7 +157,7 @@ $proc.CommandLine # 必须含 kd.bos.service.webserver.JettyServer
|
|
|
157
157
|
|
|
158
158
|
- ⚠️ **Windows 上 `jps` 看不到 cosmic**(实测):cosmic 常由 **SYSTEM** 账户启动,而 `jps` 只列举**当前用户**的 JVM → 输出为空,**极易误判「cosmic 没启动」**。用端口反查。
|
|
159
159
|
- 定位后必查命令行是否含 `-XX:+DisableAttachMechanism` —— 带此参数的 JVM **无法 attach**,直接停。
|
|
160
|
-
-
|
|
160
|
+
- attach 到 cosmic(**SYSTEM 属主**,与调用方**异属主/异 IL**)需要**打开目标进程句柄**的特权,判据就是调用方令牌带不带 **`SeDebugPrivilege`**(**`whoami /priv` 一眼可判**)。DSH 受限沙箱(`workspace-write`)/ 未提升 / UAC 过滤令牌,**都只是"缺这个特权"的不同成因** → `openProcess` 报 `拒绝访问`。⚠️ **别写"无需提权"**(早期结论已被证伪;本机 `EnableLUA=0` 恒带该特权,才看起来"不需要")。
|
|
161
161
|
- 同机多个 cosmic 进程,认命令行区分(例:`mservice-cosmic\lib` + `-agentlib:jdwp=…address=5005` = 热部署目标;`mservice\lib` + `-Dmonitor.dev.model=debug` = 另一套)。**勿杀错进程。**
|
|
162
162
|
|
|
163
163
|
#### R1.3 定位模块目录与产物
|
|
@@ -198,6 +198,7 @@ $GRADLE = Get-ChildItem "$env:USERPROFILE\.gradle\wrapper\dists\gradle-$VER-bin"
|
|
|
198
198
|
```
|
|
199
199
|
|
|
200
200
|
> ⚠️ 机器上可能并存要求 Java 22 的新版 Gradle —— 取"最新"会把构建带偏。
|
|
201
|
+
> ⚠️ **dist 可能只在两处之一**:系统 `~/.gradle/wrapper/dists/`(`$env:USERPROFILE\.gradle\wrapper\dists\`)**或**工作区 `<Gradle根>/.gradle/user-home/wrapper/dists/`(AGENTS.md 约定的 `GRADLE_USER_HOME`)。上面两段示例都只搜了系统那处 —— **两处都搜,命中即用**。
|
|
201
202
|
|
|
202
203
|
#### R2.3 agent jar(用机器级缓存副本,**不要**直接用 preset 原件)
|
|
203
204
|
|
|
@@ -251,46 +252,68 @@ try { & $GRADLE ":<模块>:build" -x test --console=plain } finally { Pop-Locati
|
|
|
251
252
|
|
|
252
253
|
| 现象 | 含义 | 处置 |
|
|
253
254
|
|------|------|------|
|
|
254
|
-
| `:X:compileJava UP-TO-DATE` + 秒级完成 | **javac 没跑**,产物是旧字节码 | 要验证"改的代码进了 jar"
|
|
255
|
+
| `:X:compileJava UP-TO-DATE` + 秒级完成 | **javac 没跑**,产物是旧字节码 | 要验证"改的代码进了 jar":加 `--no-build-cache` 重跑,**以 `compileJava` 的任务结果为准**(⚠️ **别只看 class 时间戳** —— `FROM-CACHE` 解包也会把它刷成"刚刚",见下) |
|
|
255
256
|
| `:X:compileJava FROM-CACHE`(`clean` 后常见) | 从构建缓存还原,同样没跑 javac | 加 `--no-build-cache` |
|
|
256
257
|
| 有 javac 的 `deprecation` / `unchecked` 提示 | 真编译 | 正常 |
|
|
257
258
|
| `BUILD SUCCESSFUL` 但 `build/classes` 为空 | 伪成功 | 同上,重跑 |
|
|
258
259
|
|
|
259
|
-
>
|
|
260
|
+
> 真编译判据:**只有 ① 是判别器** —— ① `compileJava` 后**没有** `UP-TO-DATE`/`FROM-CACHE`。
|
|
261
|
+
> **② / ③ 都只是旁证**:
|
|
262
|
+
> - ② 出现 javac 的 `deprecation`/`unchecked` 提示可佐证真编译;但**该文件没触发这类警告时就不会出现 —— 不代表没编译**(实测:1 个 class 真编译,① 成立而 ② 为空)。
|
|
263
|
+
> - ⚠️ **③ 不能当判别器**:`UP-TO-DATE` 时它确实为 False,但 **`FROM-CACHE` 时 Gradle 会解包缓存产物、把每个 class 的 mtime 批量改成同一时刻** → ③ 也变 True(实测:`FROM-CACHE` 且 javac 未跑,100 个 class 的 mtime 同为 13:59:22)。③ 只在 ① 成立时作旁证。
|
|
260
264
|
> ⚠️ 本模板 `gradle.properties` 带 `org.gradle.caching=true`,`clean` 后仍可能 `FROM-CACHE`(macOS 实测 **879ms**、Windows 约 **2 秒** 跑完)。**要真编译必须加 `--no-build-cache`**(必要时再加 `--rerun-tasks` 强制重跑整任务图 —— 注意它在大模块上会连 jar transform 一起重跑,见 R3.2)。
|
|
261
265
|
> 🔬 **一个可复用的诊断手法**:想逼出"真实 javac"又不想全量重编,可**删掉某一个产出的 `.class`** 再构建 —— 如果它 **1~2 秒就从 `FROM-CACHE` 还原**,说明构建缓存(`org.gradle.caching=true`)在起作用、**javac 依然没跑**;此时要真编译必须 `--no-build-cache`。(实测:Windows 1.5s `FROM-CACHE`。)
|
|
262
266
|
|
|
263
267
|
#### R3.2 构建耗时:先看"该花多少"的基准,再判异常
|
|
264
268
|
|
|
265
|
-
**实测基准**(Windows
|
|
269
|
+
**实测基准**(Windows;模块 ~100 class;编译类路径 **4497 jar** —— 该数是 **ymprj 工作区 `mservice-cosmic/lib` 目录的 jar 总数**,与 slow-windows 文档 §4.4 的"4008 个文件(khxty 工作区、模块 `compileClasspath` 文件数)"**口径与工程都不同**,别混;**同机,跨若干 daemon** —— 正是因为"daemon 新旧"被证明不是因子,才把两次全新 daemon 的对照都列进来):
|
|
266
270
|
|
|
267
271
|
| 场景 | Wall | javac 真跑了吗 |
|
|
268
272
|
|------|------|----------------|
|
|
269
273
|
| no-op(只做配置 + UP-TO-DATE 检查) | **1.4s** | 否 |
|
|
270
274
|
| 删产物 class → 构建缓存还原 | **1.5s** | 否(`FROM-CACHE`) |
|
|
271
|
-
| 真 javac(1
|
|
272
|
-
|
|
|
273
|
-
|
|
|
274
|
-
|
|
|
275
|
+
| 真 javac(1 个文件,**距上次真编译 1–8 分钟**) | **3~4.7s** | 是 |
|
|
276
|
+
| **全新 daemon**、缓存热(距上次真编译 **8 分钟**) | **8.75s** | 是 |
|
|
277
|
+
| **全新 daemon**、缓存热(距上次真编译 **46 分钟**) | **8.65s** | 是 |
|
|
278
|
+
| 真 javac,**距上次真编译 13.5 小时**(daemon 新旧**无关**) | **~139s** | 是 |
|
|
279
|
+
|
|
280
|
+
> 🔥 **热窗口(实测边界)**:间隔 **≤1 小时**仍为 ~9s 量级(8min→8.75s、**46min→8.65s**,几乎无变化);**13.5h → ~139s**。⇒ 冷热分界落在 **46 分钟 ~ 13.5 小时**之间(未进一步二分);**"全新 daemon"不是变慢的原因**(上表两行全新 daemon 都很便宜)。
|
|
275
281
|
|
|
276
282
|
**两种"冷"必须分开,判据不同:**
|
|
277
283
|
|
|
278
284
|
| 触发 | 判据 | 量级 | 处置 |
|
|
279
285
|
|---|---|---|---|
|
|
280
286
|
| ① 快照**从零建**(新工作区 / 新类路径) | `javaCompile/classAnalysis.bin` **持续增长** | 20 分钟级(4000+ jar / 1.9 GB) | 搬运现成快照(见下),或预热一次后等 |
|
|
281
|
-
| ② daemon
|
|
282
|
-
|
|
283
|
-
>
|
|
284
|
-
>
|
|
285
|
-
>
|
|
287
|
+
| ② 冷缓存的一次性开销(**触发是「距上次真编译的间隔」,与 daemon 是否新建无关**) | `classAnalysis.bin` 已存在(实测 ~370MB)**且不再增长**,而 **wall ≫ 进程 CPU**(139s wall / 累计 ~30s CPU → **≥3/4 时间不烧 CPU,阻塞型**;对照热态那次是 **CPU-bound**:36s 生命期烧 35.3s CPU) | **~140s(间隔小时级)**;**间隔 ≤1 小时**则 ~9s 量级(实测 8min→8.75s、46min→8.65s) | 等它跑完(**不要 kill**) |
|
|
288
|
+
|
|
289
|
+
> ⚠️ **归因修正(2026-09-24 实测,推翻早前写法)**:曾据两个数据点写成「每个 daemon 生命周期只付一次」,被**后续数据点证伪** —— 已有**两个**"全新 daemon 却很便宜"的独立反例(12:59 启动的 8.75s、13:44 启动的 8.65s,后者距上次真编译 **46 分钟**),而另一 daemon 在**隔 13.5 小时**后花了 139s。
|
|
290
|
+
> 四点数据:间隔 **13.5h → 139s**(阻塞型)|**46min → 8.65s**|**8min → 8.75s**|**1–8min → 3–4s**。→ **相关因子是"距上次真编译的间隔",不是 daemon 寿命**。
|
|
291
|
+
> 🔁 **跨日复现(唯一的非当日样本)**:`daemon-28568`(**9/23** 22:49)**首次构建 157s → 同一 daemon 第 2 次 8.7s**,与今日同一形态 ⇒ 该现象**不是当日偶发**。⚠️ 该次只留存 wall(构建期 daemon 日志 0 行、客户端输出未留存),**无法确认当次 javac 是否真跑**,故记"首次构建"而非"首次真编译"。
|
|
292
|
+
> 成因**未定**:OS page cache 冷读(371 MB 快照被换出)与 Gradle 缓存状态需重新校验,**两者都能解释现有数据,没有可区分二者的证据** —— 不要写成已证结论。
|
|
293
|
+
> 🎯 **判决实验(待做,约 1 分钟;能把"未定"变"已证")** ——两个候选在机制上互斥,一次即可判定:
|
|
294
|
+
> **做法**:在**自然的"隔几小时"冷态**下、**跑构建之前**,先把快照**整目录**读一遍人为预热 page cache,再跑那次"首次真编译":
|
|
295
|
+
> ```powershell
|
|
296
|
+
> # ⚠️ 必须预热整个 javaCompile 快照目录,不能只预热 classAnalysis.bin ——
|
|
297
|
+
> # 该目录下还有 jarAnalysis.bin(41 MB,构建时同样被打开);只预热一个文件
|
|
298
|
+
> # 会让"仍慢"的结果无法定案(可能是剩余文件没预热,而非候选②)。
|
|
299
|
+
> Get-ChildItem "<Gradle根>\.gradle\user-home\caches\<ver>\javaCompile\*.bin" |
|
|
300
|
+
> ForEach-Object { Get-FileHash $_.FullName -Algorithm SHA1 | Out-Null }
|
|
301
|
+
> # 紧接着跑 hotdeploy / :<模块>:build,量 wall(用 daemon 日志的 started/finished 时间戳对)
|
|
302
|
+
> ```
|
|
303
|
+
> (为什么这样就够:R3.2 的判据已限定「`classAnalysis.bin` 已存在**且不再增长**」⇒ 快照不是在**建**、而是在被**读**,所以"先把这批文件读进内存"正好精确检验 page cache 假设。)
|
|
304
|
+
> **判读**:变快(~10s 量级)→ 成因 = **① page cache 冷读** ✅;仍 ~140s → 成因 = **② Gradle 缓存状态重新校验**(与磁盘读无关)✅。**两种结果都定案,不必跑两次。**
|
|
305
|
+
> ⚠️ 前提:必须是**自然冷态**(连续构建会把窗口消耗掉);做完后把结果与结论写回本条,并删除"未定"字样。
|
|
306
|
+
> 内存已排除:实测该机 **65 GB 总量 / 40.6 GB 可用**(也印证删掉 `-Xmx` 那条建议是对的)。
|
|
307
|
+
> 源文件可追溯:`<Gradle根>/.gradle/user-home/daemon/<ver>/daemon-<pid>.out.log`(如 `daemon-33008`(46min→8.65s)/ `daemon-1944`(8min→8.75s)/ `daemon-7524`(13.5h→139s)/ `daemon-28568`(9/23 跨日复现:首次构建 157s → 第 2 次 8.7s))。
|
|
286
308
|
|
|
287
309
|
规则:
|
|
288
310
|
|
|
289
|
-
- **不要 `--no-daemon
|
|
290
|
-
-
|
|
291
|
-
-
|
|
311
|
+
- **不要 `--no-daemon`**:每次构建都要付 JVM 冷启动 + 配置开销,量级**因项目而异**:本工作区实测全新 daemon 冷启动 **3–5s**(13.9s 总 wall − daemon 内构建 8.75s,含客户端握手与本手册 R0–R2 发现 ~1.9s);另一工作区数据是 `--no-daemon` 42s vs 常驻 32s(**Δ≈10s**,见 `cosmic-dev-best-practices/references/cosmic-hotdeploy-build-slow-windows.md` §4.7/§5.1)。⚠️ 别引用 "+30s"(该文档早前版本有此处,与它自己的数据表不符,已修正)。方向不变:**保留常驻 daemon**;另⚠️ 本条与 ② 无关 —— 早前写的"否则 140s 每次都要重付"基于已被证伪的 daemon 寿命归因。
|
|
312
|
+
- **隔了几小时没编译后的第一次构建会慢(~140s),属正常**,别误判成卡死、也别急着重启 daemon。想把它与正式构建分开观察时,可以先跑一次 `:<模块>:compileJava` 把冷开销付掉再跑构建。
|
|
313
|
+
- 🔬 **量构建 wall 的两个仪表,含义不同,别混用**:① Gradle 自报 `BUILD SUCCESSFUL in Ns` = 客户端观测的整次构建;② `daemon-<pid>.out.log` 里成对的 `has started executing the build` / `has finished executing the build` = **daemon 侧真正执行构建的时段**。实测同一次构建两者可差几秒(**8.75s vs 12s**,差在客户端握手/启动)。做分档归因(如 ② 的冷开销)用 ②,报告用户感知耗时用总 wall。注意:该文件**只有生命周期标记、没有构建期内容日志**(见下条)。
|
|
314
|
+
- 判"卡住"必须**两个信号同时看**:进程 CPU 增量 ≈ 0 **且** `classAnalysis.bin` 不再增长。只看"没有输出"会把冷开销误判成死锁(这条是实测踩出来的)。
|
|
292
315
|
- **"低 CPU 不是活干在别的进程"的佐证**:Gradle 7.6 默认在 daemon 进程内执行 javac(未显式配 `options.fork`),且实测构建后 `Get-Process java` 只有 Gradle daemon + cosmic + MC 三个 JVM、**无额外 worker**(Gradle worker daemon 默认 idle 3 小时不会自动退,若 fork 过必然还在)。
|
|
293
|
-
- ⚠️ **别用
|
|
316
|
+
- ⚠️ **别用 `.out.log` 里 `Starting process / fork` 计数去证明"是否 fork"**:客户端连着构建时,daemon 把**内容日志全部转发给客户端**,`.out.log` 在构建期间**一行内容都不落** —— 那些计数为 0 是**结构性为零**,不是"观测到没 fork"(实测两份 daemon 日志在构建时段各 0 行;唯一像"编译"的行出现在 daemon **关闭**时释放缓存锁,属假阳性)。该文件里**只有生命周期标记**(上面那条仪表)是可用的。
|
|
294
317
|
- ⚠️ **`--rerun-tasks` 非必要不加**:它会强制重跑**整个任务图**(含 `jar transform`),在大模块上更慢,且实测在 `org.gradle.parallel=true` 下撞过 `AsyncCacheAccessDecoratedCache` 的跨进程缓存锁等待(54 线程 parked、守护进程 CPU≈0,12 分钟无进展)。怀疑缓存欺骗时,先试 `clean` + `--no-build-cache`(R3.1),仍不够再考虑它。
|
|
295
318
|
- 🔍 **别把这条与 ② 的 ~140s 合并成一条结论**:本条由 `--rerun-tasks` 触发,且跨**进程**锁需要 ≥2 个 Gradle 进程 —— 实测 ② 发生时机器上只有 **1 个** Gradle 进程(另有 cosmic、MC),条件不满足,两者是不同现象。
|
|
296
319
|
- 可选缓解(**未直证,仅现象吻合**):把安装根(含 `mservice-cosmic/lib`)与 `<Gradle根>/.gradle` 加入 **Defender 实时扫描排除**(需管理员)—— 411 MB 分析文件首次读入被 AV 拦一遍,与百秒级等待吻合,但没有做过 A/B。
|
|
@@ -350,7 +373,8 @@ try { & $GRADLE ":<模块>:build" -x test --console=plain } finally { Pop-Locati
|
|
|
350
373
|
[ ] PID 的命令行含 kd.bos.service.webserver.JettyServer(没杀错进程)
|
|
351
374
|
[ ] jar 是绝对路径、且是本次构建产物(时间戳/大小对得上)
|
|
352
375
|
[ ] account_id / tenant_id 非空
|
|
353
|
-
[ ]
|
|
376
|
+
[ ] 调用方令牌带 `SeDebugPrivilege`(`whoami /priv` 一眼可判)—— **attach 到 SYSTEM 属主的 cosmic 时,缺它必报 `拒绝访问`**;**同用户同 IL 的目标(如自己起的 dev JVM)则不需要**(见 F4 与 slow-windows §7.10)
|
|
377
|
+
—— 受限沙箱 / 未提升 / UAC 过滤令牌都会造成缺它;⚠️ `EnableLUA=0` 时"提升"是空操作
|
|
354
378
|
```
|
|
355
379
|
|
|
356
380
|
### R5 验证
|
|
@@ -370,9 +394,9 @@ try { & $GRADLE ":<模块>:build" -x test --console=plain } finally { Pop-Locati
|
|
|
370
394
|
|---|-------------|------|------|
|
|
371
395
|
| F1 | `Unexpected UTF-8 BOM` | 凭证文件带 BOM,某处用裸 `utf-8` 读 | 去 BOM;**别再手编辑该 JSON,改走 `erp-config.py write`** |
|
|
372
396
|
| F2 | `does not contain a Gradle build` | 执行构建的 cwd 不是 Gradle 根 | 按 R1.1 切到含 `settings.gradle` 的目录 |
|
|
373
|
-
| F3 | `[Win]` `拒绝访问` / `CreatePipe error=5
|
|
374
|
-
| F4 | `[Win]` attach 报 `拒绝访问`(`WindowsVirtualMachine.openProcess
|
|
375
|
-
| F5 | `jps` 查不到 /
|
|
397
|
+
| F3 | `[Win]` **端口查询 / 起子进程**阶段的 `拒绝访问` / `CreatePipe error=5`(**不含 attach** —— attach 一律走 F4) | 沙箱未放开 | 把「体检 + 构建 + 注入」合成**尽量少的命令**并带 `danger-full-access` 重发;**不要先单独跑体检**(白花一次授权)。⚠️ **若会话审批提示已被禁用**(approval=never)而策略仍为 `workspace-write`,则**无法自行放开** → 构建/注入 fail-closed,**须先请用户恢复策略或授权**再继续 |
|
|
398
|
+
| F4 | `[Win]` attach 报 `拒绝访问`(`WindowsVirtualMachine.openProcess`)——**与 F3 同因(受限令牌)、不同失败点**:本条的 Attacher **已起来**,卡在打开句柄 | **调用方令牌缺"打开目标进程"的权限**:判据 = `whoami /priv` 里有没有 **`SeDebugPrivilege`**(沙箱受限令牌 / 未提升 / UAC 过滤令牌都只是缺它的成因;cosmic 常为 SYSTEM 属主,故必须有)。**已证**:沙箱外用 `runas /trustlevel:0x20000` 摘掉特权、**IL 未变**亦复现同一签名 ⇒ 与"跨完整性级别"无关(实验全文 + 复现命令见 slow-windows §7.14) | ① 在**同一 shell** 跑 `whoami /priv`:**无**该特权 → 放开沙箱(`danger-full-access`)或提升后原样重跑;**有**仍失败 → 查集合外原因(attach socket 残留 / 目标 JVM 未就绪 / `DisableAttachMechanism`);② ⚠️ `EnableLUA=0` 时 `RunAs` 是空操作 —— 此时**最常见**的缺特权来源是沙箱,但**不止它**(显式降权启动如 `runas /trustlevel:0x20000` 同样会造成) |
|
|
399
|
+
| F5 | `jps` 查不到 / 端口反查为空或报 `CimException: 拒绝访问` | ① Windows 上 cosmic 由 SYSTEM 启动 ② 端口错 ③ **沙箱拒绝**(受限沙箱下 `Get-NetTCPConnection` 会被拒) | 先用 R0.3 的 HTTP 探测区分"活着"与"查不到";活着 → 用 R1.2 端口反查;若反查被**沙箱**拒(`CimException: 拒绝访问`)→ **放开 `danger-full-access` 重跑**(注意:受限沙箱下运行手册会**止步于 R0.4**,要单测 Attacher 见 slow-windows §7.14 的复现命令) |
|
|
376
400
|
| F6 | `Could not find tools.jar` | `JAVA_HOME` 指向 JRE(或被注册表带偏) | 显式设 `JAVA_HOME` 到含 `lib/tools.jar` 的 JDK |
|
|
377
401
|
| F7 | `AgentLoadException` | Attacher 与目标 JVM 大版本不一致 | 用目标进程自己的 JDK(R2.1 第 1 顺位) |
|
|
378
402
|
| F8 | 构建长时间无输出 | 多半是冷缓存建快照,不一定是死锁 | 用 R3.2 判据;确卡住再清 Gradle 守护进程重试(**不要动 cosmic 进程**) |
|
|
@@ -16,11 +16,13 @@ Caused by: java.io.IOException: Cannot run program "…\jdk1.8.0_281\bin\java.ex
|
|
|
16
16
|
CreatePipe error=5, 拒绝访问
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
- 根因:DSH Windows
|
|
20
|
-
|
|
19
|
+
- 根因:DSH Windows 沙箱(受限令牌)下 **Gradle fork daemon 会撞 `CreatePipe error=5`**(`--no-daemon` 也无效:仍 fork single-use daemon)。
|
|
20
|
+
⚠️ 但**"起子进程 / 跨进程管道被一刀切禁止"不成立**(2026-09-24 实测):`cmd /c "echo PIPE_OK"` 在 `workspace-write` 下**成功**;早期见到的 `Program 'NETSTAT.EXE' failed to run: 拒绝访问` 触发条件**未钉死** —— **别把这条写成普遍规则**,逐例判断。
|
|
21
|
+
- ⚠️ **与热部署 Attacher 的失败不是同一个失败点**(2026-09-24 实测修正):Attacher 进程**能正常起来**(会打印 `attaching to pid=…`),是在 `openProcess`(打开目标进程句柄)时才被拒 —— 轴是**令牌特权**(见 §7.14),与 `CreatePipe` 这条无关,**别合并叙述**。
|
|
21
22
|
- 解决:构建/热部署命令须**单命令级放开权限**(`danger-full-access`,仅该命令生效)或会话级放宽;
|
|
22
23
|
放开后本文的增量排查才可进行
|
|
23
|
-
- 区分:`CreatePipe error=5` = 权限问题(跑不起来);本文第 3/4 节 =
|
|
24
|
+
- 区分:`CreatePipe error=5` = 权限问题(跑不起来);本文第 3/4 节 = 增量失效(跑得慢)——先排除前者。
|
|
25
|
+
注:**attach 的 `拒绝访问` 是另一条**(`openProcess` 阶段、轴是令牌特权),见 §7.14,别与本条的 `CreatePipe` 混。
|
|
24
26
|
|
|
25
27
|
---
|
|
26
28
|
|
|
@@ -28,7 +30,7 @@ CreatePipe error=5, 拒绝访问
|
|
|
28
30
|
|
|
29
31
|
- 用户只改一行 Java 代码,`gradle :<模块>:build` 耗时 **32 秒**(预期 5~10 秒)
|
|
30
32
|
- 无改动构建约 4 秒(UP-TO-DATE 正常),**一旦有改动就全量重编**(583 个类)
|
|
31
|
-
- 判断标准:改一行后看 `build/classes/java/main` 下 class 文件时间戳,**全部更新 =
|
|
33
|
+
- 判断标准:改一行后看 `build/classes/java/main` 下 class 文件时间戳,**全部更新 = 全量重编**(⚠️ 此法有 `FROM-CACHE` 假阳性,见 §1.1 末尾)
|
|
32
34
|
|
|
33
35
|
### 1.1 快速识别"增量失效"
|
|
34
36
|
|
|
@@ -45,6 +47,17 @@ $new = $classes | Where-Object { $_.LastWriteTime -ge (Get-Date).AddMinutes(-2)
|
|
|
45
47
|
> ⚠️ 注意:如果两次构建间隔很短(如先全量后增量),2 分钟窗口会混入前一次全量的产物,
|
|
46
48
|
> 造成"还是全量"的误判。精确做法:以**最后一次构建结束后**为基准,取最新时间戳 ±30s 窗口,
|
|
47
49
|
> 或用两次构建的时间点精确切分(见第 5 节示例)。
|
|
50
|
+
>
|
|
51
|
+
> ⚠️⚠️ **时间戳法还有一个天然假阳性:`FROM-CACHE`**(2026-09-24 实测)。Gradle 从**构建缓存**解包产物时,
|
|
52
|
+
> 会把**所有** class 的 mtime 批量刷成同一时刻(实测 100 个 class 同为 13:59:22)——于是上面脚本也会报
|
|
53
|
+
> `recompiled == total`,**而 javac 根本没跑**。**照本节的"结果解读"会直接得出"全量重编、增量失效"的假诊断。**
|
|
54
|
+
> **所以判据必须回到 Gradle 日志的任务结果**:
|
|
55
|
+
> - `FROM-CACHE` → 缓存还原(**不是**重编,也不是增量失效)
|
|
56
|
+
> - `Full recompilation is required because …` → 真·全量重编
|
|
57
|
+
> - `Incremental compilation of N classes completed` → 真·增量
|
|
58
|
+
>
|
|
59
|
+
> 一句话:**时间戳只能当旁证,"有没有真编译"的唯一判别器是 `compileJava` 的任务结果里没有 `UP-TO-DATE`/`FROM-CACHE`**。
|
|
60
|
+
> 交叉引用:§7 第 7 条、`cosmic-vibe-coding/SKILL.md` 的 R3.1。
|
|
48
61
|
|
|
49
62
|
## 2. 排查工具速查
|
|
50
63
|
|
|
@@ -106,9 +119,16 @@ Gradle 增量编译被禁用时,任何一次源码改动都会触发全量重
|
|
|
106
119
|
### 4.1 修改根 `cosmic/build.gradle`
|
|
107
120
|
|
|
108
121
|
```groovy
|
|
109
|
-
// subprojects 块内,trd 依赖排除嫌疑 jar
|
|
122
|
+
// subprojects 块内,trd 依赖排除嫌疑 jar。
|
|
123
|
+
// ⚠️ 清单**必须按 §4.8 的全量扫描重算**(版本敏感,勿照抄早期清单):
|
|
124
|
+
// 早期清单里的 bcprov-jdk18on-1.78.1.jar 在当前 trd 中已**不存在**(现为 1.82)——
|
|
125
|
+
// 这种 exclude 属于**静默空排除**:不报错、也不生效,最难排查。
|
|
126
|
+
// 下列为 2026-09 实测集合,仅作对照(log4j-core 是注解处理器那条,其余是含 Java17+ 类的):
|
|
127
|
+
// log4j-core-*.jar | bcprov-jdk18on-*.jar | hive-service-*.jar
|
|
128
|
+
// | ImpalaJDBC42-*.jar | jackson-core-*.jar | jsch-*.jar
|
|
110
129
|
api fileTree(dir: trd, include: '*.jar',
|
|
111
|
-
exclude: ['
|
|
130
|
+
exclude: ['log4j-core-2.20.0.jar', 'bcprov-jdk18on-1.82.jar', 'hive-service-4.2.0.jar',
|
|
131
|
+
'ImpalaJDBC42-2.6.38.jar', 'jackson-core-2.16.2.jar', 'jsch-0.2.26.jar'])
|
|
112
132
|
|
|
113
133
|
// allprojects 块内,JavaCompile 关闭注解处理(可选项,非增量必需——
|
|
114
134
|
// 实测去掉后增量编译仍生效,仅在全量编译时省 ~10s javac 处理器扫描时间;本项目最终去掉,保留最小改动)
|
|
@@ -123,7 +143,8 @@ tasks.withType(JavaCompile) {
|
|
|
123
143
|
```groovy
|
|
124
144
|
api fileTree(trd) {
|
|
125
145
|
include '*.jar'
|
|
126
|
-
|
|
146
|
+
// ⚠️ 按 §4.8 的全量扫描结果重算后再填(下面是 2026-09 实测集合,版本变了就作废)
|
|
147
|
+
exclude 'qing-arthas-*.jar', 'log4j-core-2.20.0.jar', 'bcprov-jdk18on-1.82.jar', 'hive-service-4.2.0.jar', 'ImpalaJDBC42-2.6.38.jar', 'jackson-core-2.16.2.jar', 'jsch-0.2.26.jar'
|
|
127
148
|
}
|
|
128
149
|
```
|
|
129
150
|
|
|
@@ -185,7 +206,8 @@ allprojects {
|
|
|
185
206
|
$gradle ":<模块>:showCompileCp" -I "<path>\showcp.gradle" --console=plain
|
|
186
207
|
```
|
|
187
208
|
|
|
188
|
-
>
|
|
209
|
+
> 实测(**khxty 工程,2026-08**):排除前 4008 个文件且 3 个嫌疑 jar 都在;排除后 4005 个文件 `(none - exclusion OK)`。
|
|
210
|
+
> 注:这个 **4008** 是该模块 `compileClasspath` 的**文件数**,与"`mservice-cosmic/lib` 目录下 jar 总数"(另一工作区 ymprj 实测 **4497**,见 SKILL.md R3.2)**口径不同、环境也不同**,两个数字不矛盾,比较时别混。
|
|
189
211
|
|
|
190
212
|
### 4.5 扫描注解处理器(PowerShell)
|
|
191
213
|
|
|
@@ -226,12 +248,18 @@ $gradle = "C:\Users\<user>\.gradle\wrapper\dists\gradle-7.6.3-bin\<hash>\gradle-
|
|
|
226
248
|
> `~/.gradle/wrapper/dists` 下最新」。本机同时存在 `gradle-8.8-bin`,它要求 Java 22
|
|
227
249
|
> 运行时,与本项目 JDK 8 + tools.jar 链路不兼容,会直接把构建带偏。
|
|
228
250
|
>
|
|
251
|
+
> ⚠️ **gradle.bat 可能只在两处之一**:系统 `$env:USERPROFILE\.gradle\wrapper\dists\` **或**
|
|
252
|
+
> 工作区 `<Gradle根>\.gradle\user-home\wrapper\dists\`(AGENTS.md 约定的 `GRADLE_USER_HOME`)。
|
|
253
|
+
> 上面示例只写了前者 —— **找不到就改搜后者**(两个都搜更稳,见 `cosmic-vibe-coding/SKILL.md` R2.2)。
|
|
254
|
+
>
|
|
229
255
|
> 🧩 完整流程(端口反查 PID / JDK 选择 / Gradle 定版 / 构建 / 注入)见
|
|
230
256
|
> `cosmic-vibe-coding/SKILL.md` 的**运行手册(R0–R5)**,其中已内置上述 JDK、Gradle 版本、
|
|
231
257
|
> PID 发现、account/tenant 读取逻辑,以及失败分支表(F1–F10)。
|
|
232
258
|
|
|
233
|
-
> ❌ 不要加 `--no-daemon`:每次 fork 单次 Daemon(JVM 冷启动 +
|
|
259
|
+
> ❌ 不要加 `--no-daemon`:每次 fork 单次 Daemon(JVM 冷启动 + 重新加载配置都要重付)
|
|
234
260
|
> ✅ 复用常驻 Daemon(`org.gradle.daemon=true` 默认开启),改几行代码约 5-10 秒
|
|
261
|
+
>
|
|
262
|
+
> ℹ️ **量级以本项目实测为准,别引用 "+30s"**:本项目数据表(§5.1)是 `--no-daemon` **42s** vs 常驻 **32s** → **Δ≈10s**;本文「误区层」的结论也是「Daemon 只占几秒,大头是全量编译本身」。另一工作区(ymprj)实测全新 daemon 冷启动仅 **3–5s**。早前此处写的 "+30s" 与本文自身数据不符,已修正。
|
|
235
263
|
|
|
236
264
|
### 4.8 全量扫描定位「Java 17+ 类」jar(推荐,避免打地鼠)
|
|
237
265
|
|
|
@@ -363,9 +391,10 @@ $jar = "<模块>\build\libs\<模块>-1.0.0.jar"
|
|
|
363
391
|
- Windows classpath 分隔符用 **`;`**(不是 `:`)
|
|
364
392
|
- 成功标志:退出码 0 + `SUCCESS: N jar(s) deployed & reloaded`
|
|
365
393
|
|
|
366
|
-
> ⚠️
|
|
367
|
-
>
|
|
368
|
-
>
|
|
394
|
+
> ⚠️ **权限:attach 需要"能打开目标进程句柄"的特权** —— 一眼判据是调用方令牌带不带 **`SeDebugPrivilege`**(`whoami /priv`)。
|
|
395
|
+
> 沙箱受限令牌 / 未提升 / UAC 过滤令牌,**都只是"缺这个特权"的不同成因**;缺了就在 `openProcess` 报 `拒绝访问`(见 §7.14)。
|
|
396
|
+
> 处置:**先放开沙箱(`danger-full-access`)原样重跑**;仍不行再提升 Attacher(⚠️ `EnableLUA=0` 时提升是空操作)。
|
|
397
|
+
> 注:目标进程与调用方**同用户同 IL**(自己起的 dev JVM)时不带该特权也能 attach —— cosmic 这种 **SYSTEM 属主**则必须有。
|
|
369
398
|
- 原理:`ExtJarApi.save(字节)` 写 `t_meta_ext_jar` 表 → `ExtJarApi.reset(accountId)` 重载 ExtClassLoader
|
|
370
399
|
- 不重启 cosmic、不碰 mc;jar 无需拷到 `lib/cus`
|
|
371
400
|
|
|
@@ -378,37 +407,53 @@ $jar = "<模块>\build\libs\<模块>-1.0.0.jar"
|
|
|
378
407
|
改完依赖务必用自定义任务打印真实 compileClasspath 验证
|
|
379
408
|
4. **改 build.gradle 后首次构建必全量**,属正常;之后才增量
|
|
380
409
|
5. **`Get-NetTCPConnection` 在非管理员权限下会误报"无监听"**,用 `Invoke-WebRequest` 探测兜底
|
|
381
|
-
6. **build 前确认 Daemon 活着**:`gradle --status` 应见 `IDLE` 条目;`--no-daemon`
|
|
410
|
+
6. **build 前确认 Daemon 活着**:`gradle --status` 应见 `IDLE` 条目;`--no-daemon` 会为每次构建重付 JVM 冷启动 + 配置(本项目实测 Δ≈10s;另一工作区全新 daemon 冷启动 3–5s —— **别引用"+30s"**,见 §4.7 注)
|
|
382
411
|
7. **识别全量重编**:改一行后 class 文件时间戳全变 = 全量;只有个别变 = 增量正常;
|
|
383
|
-
多次构建间隔短时用「最新时间戳 ±30s
|
|
412
|
+
多次构建间隔短时用「最新时间戳 ±30s」窗口精确切分,避免混入前一次全量产物。
|
|
413
|
+
⚠️ **但别只靠时间戳下结论**(2026-09-24 实测):**`FROM-CACHE` 解包缓存产物时会把所有 class 的 mtime 批量刷成同一时刻**(实测 100 个 class 同为 13:59:22),看起来也像"全变",而 javac 根本没跑。要区分「全量重编」与「缓存还原」,**看 Gradle 日志**:`Full recompilation is required because …`(全量)vs `FROM-CACHE` / `Incremental compilation of N classes completed`(非全量)。同理,`compileJava` 是否为真编译,**唯一判别器是任务结果里没有 `UP-TO-DATE`/`FROM-CACHE`**,时间戳只能当旁证。
|
|
384
414
|
8. **`dependencies --configuration compileClasspath` 对 fileTree 是惰性展开**,不一定显示 jar 明细,
|
|
385
415
|
要确认真实 classpath 必须用自定义任务打印 `sourceSets.main.compileClasspath.files`
|
|
386
416
|
9. **`jps` 看不到 cosmic 进程**(实测):本机 cosmic 由 **SYSTEM** 账户启动
|
|
387
417
|
(`F:\cosmic\xinghan8\jdk\bin\java ... -DappName=cosmic ... kd.bos.service.webserver.JettyServer`),
|
|
388
418
|
而 `jps` 只列举当前用户的 JVM → 输出里完全没有它,容易误判「cosmic 没启动」。
|
|
389
419
|
用 §6.1 方式零(按端口反查 OwningProcess)替代。
|
|
390
|
-
10.
|
|
391
|
-
|
|
392
|
-
|
|
420
|
+
10. **attach 到 cosmic(SYSTEM 属主)是*需要特权*的 —— 早期"跨用户 attach 无需提权"的结论已被证伪**(2026-09-24 判决性测试):
|
|
421
|
+
- **实际判据**:调用方令牌是否带 **`SeDebugPrivilege`**(它绕过目标进程 DACL)—— `whoami /priv` 一眼可判。
|
|
422
|
+
- **为什么以前看起来"无需提权"**:本机 `EnableLUA = 0`(UAC 关闭)→ Administrator 进程**恒为 High IL 且默认带该特权**,所以每次 attach 都成功 —— **并非因为"不需要特权"**。
|
|
423
|
+
- **在 UAC 启用的机器、或 DSH 受限沙箱(`workspace-write`)下,该特权缺失 → `openProcess` 报 `拒绝访问`**。
|
|
424
|
+
- 精确表述:**需要能打开目标进程句柄**(目标与调用方**异属主/异 IL** ⇒ 需 `SeDebugPrivilege`;同用户同 IL 则不需要)。
|
|
425
|
+
**判决实验**:`runas /trustlevel:0x20000` 摘掉特权后,**完整性级别未变(仍 High)却复现同一签名** ⇒ 与"跨 IL"无关,轴是特权。
|
|
393
426
|
11. **`-XX:+DisableAttachMechanism` 是硬阻断**:本机 IDEA 侧另一个 JVM(`CosmicStudio-runnable.jar`)
|
|
394
427
|
带此参数,对它 attach 必然失败;发现 PID 后先扫命令行里有没有这个 flag。
|
|
395
|
-
|
|
428
|
+
12. **`java_home` 以 IDEA 项目 SDK 为准**(Windows 常见 `C:\Program Files\java\jdk`),
|
|
396
429
|
不要误填 cosmic 自带 JDK 目录;Attacher 只需与 cosmic 同 JDK 大版本(同为 JDK8 即兼容)
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
- 现象:`[reloadjar] FAILED: java.io.IOException:
|
|
400
|
-
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
-
|
|
405
|
-
|
|
430
|
+
13. **gradle 构建命令不要加 `--no-daemon`**;多 IDLE Daemon 并存无害,`--stop` 可一次性清理
|
|
431
|
+
14. **attach 报 `拒绝访问`(`WindowsVirtualMachine.openProcess`)—— 判据是 `SeDebugPrivilege`,不是"先试着提权"**:
|
|
432
|
+
- 现象:`[reloadjar] FAILED: java.io.IOException: 拒绝访问`(Attacher 进程**已正常起来**,卡在打开目标进程句柄)
|
|
433
|
+
- **原因(单一机制)**:attach 到 cosmic(常为 **SYSTEM** 属主,与调用方**异属主**)需要**打开目标进程句柄**的特权,实际判据就是调用方令牌带不带 **`SeDebugPrivilege`**(它绕过目标 DACL)。
|
|
434
|
+
**沙箱受限令牌 / 未提升 / UAC 过滤令牌,都只是"缺这个特权"的不同成因** —— 不要再按"沙箱 vs elevated"拆成两个候选,它们不是并列原因。
|
|
435
|
+
> **🎯 判决性证据(2026-09-24 三点实验)**:① `danger-full-access`:令牌含 `SeDebugPrivilege` → **SUCCESS**;② **沙箱外**用 `runas /trustlevel:0x20000`(同用户、摘掉管理员):令牌只剩 `SeChangeNotifyPrivilege`、**完整性级别仍是 High(未变)** → **同一签名 `拒绝访问`**;③ DSH `workspace-write`:令牌同样只剩 `SeChangeNotifyPrivilege` → **同一签名**。
|
|
436
|
+
> ⇒ **轴是「令牌特权」,不是「完整性级别」**(②里 IL 未变仍被拒),**也不是沙箱独有**(②在沙箱外复现)。
|
|
437
|
+
- 🔍 **一眼可判的观测**:失败时在**同一个 shell** 跑 **`whoami /priv`** ——
|
|
438
|
+
**在** `SeDebugPrivilege` → 不是特权问题,往集合外查(attach socket 残留 / 目标 JVM 未就绪 / `DisableAttachMechanism`);
|
|
439
|
+
**不在** → 就是它:**放开沙箱(`danger-full-access`)或提升后原样重跑**。
|
|
440
|
+
- ⚠️ **`EnableLUA = 0` 的机器上"提升"是空操作**(Administrator 恒为 High IL、恒带该特权):既解释了历史上"不用提权也成功",也意味着此时**最常见的**缺特权来源是沙箱(`workspace-write`)——**但不止它**:显式降权启动(`runas /trustlevel:0x20000`,即判决实验②,**沙箱外**)同样会造成。
|
|
441
|
+
- ⚠️ **与 §0 的 `CreatePipe error=5` 不是同一个失败点**:那个发生在**起子进程**阶段(Gradle fork),本条发生在**打开句柄**阶段;同因(受限令牌)不同环节,签名与处置都不同。
|
|
442
|
+
- 提升处置(仅当 `whoami /priv` 无该特权且本机 UAC 启用):`Start-Process -Verb RunAs`,详见 `cosmic-jdwp-debug-config.md` §9.3。
|
|
443
|
+
- 🧪 **复现命令**(会话策略切到 `workspace-write` 后)。⚠️ 此时**运行手册会在 R0.4(端口反查)就失败**(`Get-NetTCPConnection` → `CimException: 拒绝访问`),走不到 R4,所以要**直接调 Attacher**:
|
|
444
|
+
```powershell
|
|
445
|
+
whoami /priv # 期望:只剩 SeChangeNotifyPrivilege(无 SeDebugPrivilege)
|
|
446
|
+
$jdk='<安装根>\jdk'; $agent=Join-Path $HOME '.dsh\cache\cosmic\agent\kd-reloadjar-agent-d8ca9d80.jar'
|
|
447
|
+
& "$jdk\bin\java.exe" -cp "$jdk\lib\tools.jar;$agent" kd.reloadjar.Attacher <PID> "$agent" "<jar>" <account_id> <tenant_id>
|
|
448
|
+
```
|
|
449
|
+
15. **重启 cosmic 的连带影响**:PID 变化 + `t_meta_ext_jar` 清空(热部署状态失效),
|
|
406
450
|
重启后需重新 build + 热部署;新 PID 用 wmic 查 `-DappName=cosmic` 的 JettyServer 进程确认
|
|
407
|
-
|
|
451
|
+
16. **新版 trd jar 会带 Java 21+ 类,排除清单按实际扫描定**:bcprov 1.82 / jackson-core 2.16.2 /
|
|
408
452
|
jsch 0.2.26 / ImpalaJDBC42 2.6.38 / hive-service 4.2.0 共 5 个 jar 含 major≥65 的类(见 4.8),
|
|
409
453
|
旧文档只排除 3 个 jar 的方案在新版本下不够——必须用 4.8 的全量扫描一次性定位
|
|
410
|
-
|
|
454
|
+
17. **排除 jar 后仍报旧类无法分析 = 增量快照缓存坑**:`build/tmp/compileJava/previous-compilation-data.bin`
|
|
411
455
|
复用旧 classpath 分析结果,`clean`(或重启 daemon)后重建基线即恢复增量(见 4.9)
|
|
412
|
-
|
|
413
|
-
`CreatePipe error=5
|
|
414
|
-
`danger-full-access`(`--no-daemon` 无效),**不是**本文的增量失效问题;放开后仍慢再按第 3/4
|
|
456
|
+
18. **先分清"跑不起来"还是"跑得慢"**:DSH 受限沙箱(workspace-write)下**构建**直接报
|
|
457
|
+
`CreatePipe error=5 拒绝访问`(**Gradle fork daemon** 被拦)是**权限问题**,须单命令级放开
|
|
458
|
+
`danger-full-access`(`--no-daemon` 无效),**不是**本文的增量失效问题;放开后仍慢再按第 3/4 节排查。
|
|
459
|
+
⚠️ **热部署 attach 不走这条**:它报的是 `openProcess` + Java 栈的 `拒绝访问`(见 §7.14),别混。
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
|------|------|------|
|
|
34
34
|
| IDEA 项目目录 | = `<cwd>`(工作目录)| |
|
|
35
35
|
| IDEA MCP | 调工具一律传 `projectPath=<cwd>` | 否则报 Unable to determine the target project |
|
|
36
|
-
| build jar 热部署 | 走 cosmic-vibe-coding
|
|
36
|
+
| build jar 热部署 | 走 cosmic-vibe-coding 技能的**运行手册(R0–R5)**;**若工作区已存在 `.dsh/cosmic/scripts/hotdeploy.ps1`(手册的物化脚本),优先用它** | 物化脚本 = 1 次调用;从零推导手册 ≈ 15 次。脚本须遵守手册「执行方式」四条约束(放 `.dsh/` 下 / 手册为唯一权威、手册更新后重新生成 / 只做编排 / 不得写死本机路径),允许 `-DryRun` 这类**只读干跑** |
|
|
37
37
|
| cosmic-vibe-coding | `{PRESET}/skills/cosmic-build/skills/cosmic-vibe-coding` | |
|
|
38
38
|
| 苍穹服务地址、JDK | `dev.py read`(erp_url / java_home) | 见 cosmic-vibe-coding SKILL.md |
|
|
39
39
|
| appconfig.json | `<cwd>/app/config/appconfig.json` | **应用级开发配置**(compile / GRADLE_ROOT / JAVA_HOME / autoregister / pluginProjects),非 `_runtime` 运行时临时数据;`appconfig_load.py` 回退已固定工作区路径(`KD_APPCONFIG` 环境变量仍可覆盖) |
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
| GRADLE_USER_HOME | `<cwd>/.gradle/user-home` | gradle wrapper 缓存;dist 从系统 `~/.gradle/wrapper/dists` **复制**(勿用软链——wrapper 会删链重解压) |
|
|
42
42
|
| gradlew / gradlew.bat | POSIX:项目根 `gradlew` 需 `chmod +x`;Windows:需 `gradle/wrapper/`(gradle-wrapper.properties + gradle-wrapper.jar)齐全,`gradlew.bat` 才可运行 | 模板生成时可能缺 x 位;缺 wrapper 元数据时从模板/系统 dist 补齐 |
|
|
43
43
|
| 插件编译脚本 | `{VENV}/bin/python compile_plugin_source.py` | 脚本只注入 `JAVA_HOME`、**不注入 `GRADLE_USER_HOME`**,调用方必须显式 `export GRADLE_USER_HOME=<cwd>/.gradle/user-home`,否则 Gradle 默认写用户主目录(Windows:`%USERPROFILE%\.gradle`)触发权限拦截;cosmic_home、解释器约定见上 |
|
|
44
|
-
| 构建权限边界 | 产 jar 走 `:<模块>:build`(写工作区);勿用 `buildJar`/`deployJar`(写 cosmic 安装目录 outputdir,工作区外) | Windows 另有 `CreatePipe`
|
|
44
|
+
| 构建权限边界 | 产 jar 走 `:<模块>:build`(写工作区);勿用 `buildJar`/`deployJar`(写 cosmic 安装目录 outputdir,工作区外) | Windows 另有 `CreatePipe` 限制,构建/热部署须放开权限:受限沙箱下**把「体检+构建+注入」合成尽量少的命令**(授权按命令计),**不要先单独跑一次「体检」**(白花一次授权);⚠️ **受限策略下运行手册会止步于 R0.4**(端口反查 `CimException: 拒绝访问`)—— 先确认能否放开策略/授权,再开跑,别把它误判成"cosmic 没启动";完整步骤见 cosmic-vibe-coding 技能的**运行手册(R0–R5)**;Attacher classpath 分隔符 Windows 用 `;` |
|
|
45
45
|
|
|
46
46
|
> 📌 配置按**工作区**隔离(appconfig / GRADLE_USER_HOME / ERP 凭证均在 `<cwd>` 下),多工作区可并行开展不同项目;bash 每次调用为独立 shell,命令中需显式携带工作区约定值(如 `export GRADLE_USER_HOME=<cwd>/.gradle/user-home`),勿依赖跨调用 export。沙箱写权限仅限工作区(preset 技能脚本 `~/.dsh/...`、`~/kd` 等外部路径修改需授权)。权限放开按平台:**macOS/Linux 无管道限制,构建/热部署无需放开**(缓存入工作区即可);**Windows 禁跨进程管道(`CreatePipe error=5`),构建/热部署每次须单命令级放开 `danger-full-access`**(或会话级放宽;`--no-daemon` 无效)。
|
|
47
47
|
> 📌 **发邮件不需要提权**:`send_email.py` 用 `password = "授权码"` 时明文直读、**不起子进程**,纯网络调用,任何平台都无需放开权限。(只有 `auth_cmd` 那条路要起子进程捕获 stdout,Windows 受限令牌下才需提权 —— 见 `references/email-delivery.md`。)
|