@shundoo-ai/dsh-cosmic 1.0.9 → 1.0.11
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,8 @@ 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
|
+
> 🔧 **Windows 物化脚本的三个必踩点**(均实测,对应 F11–F13):① 脚本含中文 ⇒ **必须存为 UTF-8 with BOM**(PS 5.1 否则按 ANSI 解码 → 中文碾碎、引号配对错乱);**任何 write/edit 都会去掉 BOM** ⇒ 每次改动后**重新加 BOM + 跑一次 `Parser::ParseFile` 语法检查**(见 F11);② **函数参数名避开只读自动变量**(`$Home`/`$Host`/`$PID`/`$Args`/`$Error`…),否则报 `Cannot overwrite variable …` 且**行号指向调用点**(见 F13);③ 别写 `Invoke-WebRequest -MaximumRedirection 0`(PS 5.1 必抛异常,见 F12)。
|
|
94
95
|
|
|
95
96
|
> **平台约定:本手册三平台通用**(Windows / macOS / Linux 各步骤都可用)。平台差异见下表;
|
|
96
97
|
> 失败分支表里**未标注平台的条目三平台通用**,标 `[Win]` 的只会发生在 Windows。
|
|
@@ -105,7 +106,7 @@ description: >
|
|
|
105
106
|
> | PID 定位 | `Get-NetTCPConnection` → `Get-CimInstance`(**`jps` 看不到 SYSTEM 账户的 cosmic**) | `lsof -tiTCP:<port> -sTCP:LISTEN` 或 `jps -l \| grep JettyServer` |
|
|
106
107
|
> | classpath 分隔符 | `;` | `:` |
|
|
107
108
|
> | 沙箱 | 受限沙箱**砍令牌特权**(实测只剩 `SeChangeNotifyPrivilege`)→ 端口查询被拒、attach 缺 `SeDebugPrivilege`(见 F4);构建的 `CreatePipe error=5` 是另一条(见 F3) | 无此限制 |
|
|
108
|
-
> | shell / 变量 | PowerShell(DSH 兜底到 5.1,注意默认 ANSI
|
|
109
|
+
> | shell / 变量 | PowerShell(DSH 兜底到 5.1,注意默认 ANSI 解码;**物化脚本含中文须存 UTF-8 with BOM**,见 F11);`$env:VAR=` | bash/sh;`export VAR=` |
|
|
109
110
|
> | 构建可执行 | `gradle.bat`(按 wrapper 定版) | `gradle`(按 wrapper 定版) |
|
|
110
111
|
> | 缓存预热命令 | `robocopy`(见 R3.2) | `cp -R`(见 R3.2) |
|
|
111
112
|
|
|
@@ -115,7 +116,7 @@ description: >
|
|
|
115
116
|
|---|------|------|----------|
|
|
116
117
|
| R0.1 | `<DSH工作区>/.dsh/cosmic/config/dev.json` 存在 | 存在 | 跑 `dev.py init`(或先「设置 erp 登录信息」) |
|
|
117
118
|
| R0.2 | dev.json 的 `port` / `account_id` / `tenant_id` | 非空 | `tenant_id` 空 → 默认 `ierp`;`account_id` 空 → 重跑 `dev.py init` |
|
|
118
|
-
| R0.3 | **HTTP
|
|
119
|
+
| R0.3 | **HTTP 探测**端口(一般不需要特权;**受限沙箱是例外**,见下注) | 最终状态码 `200`/`302`(`Invoke-WebRequest` 默认跟随重定向,通常得 `200`;`curl` 不带 `-L` 则得 `302`) | 非 2xx/3xx → cosmic 没起或端口不对,停 |
|
|
119
120
|
| R0.4 | 目标进程定位(R1.2) | 得到 PID,且命令行含 `kd.bos.service.webserver.JettyServer` | 见 F5 |
|
|
120
121
|
|
|
121
122
|
```bash
|
|
@@ -123,6 +124,11 @@ description: >
|
|
|
123
124
|
curl -s -o /dev/null -w '%{http_code}\n' --max-time 5 http://127.0.0.1:<port>/ierp
|
|
124
125
|
```
|
|
125
126
|
|
|
127
|
+
> ⚠️ **PowerShell 写这条探测时不要加 `-MaximumRedirection 0`**(实测,见 F12):PS 5.1 下它**必然**抛
|
|
128
|
+
> `Operation is not valid due to the current state of the object`(与 cosmic 死活无关,`$_.Exception.Response` 也为空)—— 照抄会误判成「cosmic 没起」。**用默认(跟随重定向)即可**;判据与上表一致:**最终状态码为 2xx/3xx**。
|
|
129
|
+
> ⚠️ **受限沙箱下 `Invoke-WebRequest` 可能连控制台缓冲区都拿不到**(`Win32 internal error "Access is denied" 0x5 … reading the console output buffer`,**这不是 HTTP 错误码**)→ 改用 **TCP 兜底**:`(New-Object System.Net.Sockets.TcpClient).Connect('127.0.0.1',<port>)` 不抛异常即"端口有监听"(见 F14)。
|
|
130
|
+
> ⚠️ **TCP 兜底只证明"端口有人监听",不等于"是 cosmic"** —— 仍必须接着走 R0.4 校验命令行(含 `kd.bos.service.webserver.JettyServer`)。另注:**"HTTP 探测不需要特权"是有前提的**,受限令牌下请用 TCP 探测。
|
|
131
|
+
|
|
126
132
|
> ⚠️ **顺序不可颠倒**:先 R0.3 再 R0.4。端口反查被沙箱拒绝 ≠ cosmic 没启动 —— 这两件事必须能区分开(Windows 上曾因 `jps` 为空误判"cosmic 没启动")。
|
|
127
133
|
|
|
128
134
|
### R1 解析布局
|
|
@@ -252,13 +258,15 @@ try { & $GRADLE ":<模块>:build" -x test --console=plain } finally { Pop-Locati
|
|
|
252
258
|
|
|
253
259
|
| 现象 | 含义 | 处置 |
|
|
254
260
|
|------|------|------|
|
|
255
|
-
| `:X:compileJava UP-TO-DATE` + 秒级完成 | **javac 没跑**,产物是旧字节码 | 要验证"改的代码进了 jar"
|
|
261
|
+
| `:X:compileJava UP-TO-DATE` + 秒级完成 | **javac 没跑**,产物是旧字节码 | 要验证"改的代码进了 jar":加 `--no-build-cache` 重跑,**以 `compileJava` 的任务结果为准**(⚠️ **别只看 class 时间戳** —— `FROM-CACHE` 解包也会把它刷成"刚刚",见下) |
|
|
256
262
|
| `:X:compileJava FROM-CACHE`(`clean` 后常见) | 从构建缓存还原,同样没跑 javac | 加 `--no-build-cache` |
|
|
257
263
|
| 有 javac 的 `deprecation` / `unchecked` 提示 | 真编译 | 正常 |
|
|
258
264
|
| `BUILD SUCCESSFUL` 但 `build/classes` 为空 | 伪成功 | 同上,重跑 |
|
|
259
265
|
|
|
260
|
-
>
|
|
261
|
-
> **②
|
|
266
|
+
> 真编译判据:**只有 ① 是判别器** —— ① `compileJava` 后**没有** `UP-TO-DATE`/`FROM-CACHE`。
|
|
267
|
+
> **② / ③ 都只是旁证**:
|
|
268
|
+
> - ② 出现 javac 的 `deprecation`/`unchecked` 提示可佐证真编译;但**该文件没触发这类警告时就不会出现 —— 不代表没编译**(实测:1 个 class 真编译,① 成立而 ② 为空)。
|
|
269
|
+
> - ⚠️ **③ 不能当判别器**:`UP-TO-DATE` 时它确实为 False,但 **`FROM-CACHE` 时 Gradle 会解包缓存产物、把每个 class 的 mtime 批量改成同一时刻** → ③ 也变 True(实测:`FROM-CACHE` 且 javac 未跑,100 个 class 的 mtime 同为 13:59:22)。③ 只在 ① 成立时作旁证。
|
|
262
270
|
> ⚠️ 本模板 `gradle.properties` 带 `org.gradle.caching=true`,`clean` 后仍可能 `FROM-CACHE`(macOS 实测 **879ms**、Windows 约 **2 秒** 跑完)。**要真编译必须加 `--no-build-cache`**(必要时再加 `--rerun-tasks` 强制重跑整任务图 —— 注意它在大模块上会连 jar transform 一起重跑,见 R3.2)。
|
|
263
271
|
> 🔬 **一个可复用的诊断手法**:想逼出"真实 javac"又不想全量重编,可**删掉某一个产出的 `.class`** 再构建 —— 如果它 **1~2 秒就从 `FROM-CACHE` 还原**,说明构建缓存(`org.gradle.caching=true`)在起作用、**javac 依然没跑**;此时要真编译必须 `--no-build-cache`。(实测:Windows 1.5s `FROM-CACHE`。)
|
|
264
272
|
|
|
@@ -288,6 +296,19 @@ try { & $GRADLE ":<模块>:build" -x test --console=plain } finally { Pop-Locati
|
|
|
288
296
|
> 四点数据:间隔 **13.5h → 139s**(阻塞型)|**46min → 8.65s**|**8min → 8.75s**|**1–8min → 3–4s**。→ **相关因子是"距上次真编译的间隔",不是 daemon 寿命**。
|
|
289
297
|
> 🔁 **跨日复现(唯一的非当日样本)**:`daemon-28568`(**9/23** 22:49)**首次构建 157s → 同一 daemon 第 2 次 8.7s**,与今日同一形态 ⇒ 该现象**不是当日偶发**。⚠️ 该次只留存 wall(构建期 daemon 日志 0 行、客户端输出未留存),**无法确认当次 javac 是否真跑**,故记"首次构建"而非"首次真编译"。
|
|
290
298
|
> 成因**未定**:OS page cache 冷读(371 MB 快照被换出)与 Gradle 缓存状态需重新校验,**两者都能解释现有数据,没有可区分二者的证据** —— 不要写成已证结论。
|
|
299
|
+
> 🎯 **判决实验(待做,约 1 分钟;能把"未定"变"已证")** ——两个候选在机制上互斥,一次即可判定:
|
|
300
|
+
> **做法**:在**自然的"隔几小时"冷态**下、**跑构建之前**,先把快照**整目录**读一遍人为预热 page cache,再跑那次"首次真编译":
|
|
301
|
+
> ```powershell
|
|
302
|
+
> # ⚠️ 必须预热整个 javaCompile 快照目录,不能只预热 classAnalysis.bin ——
|
|
303
|
+
> # 该目录下还有 jarAnalysis.bin(41 MB,构建时同样被打开);只预热一个文件
|
|
304
|
+
> # 会让"仍慢"的结果无法定案(可能是剩余文件没预热,而非候选②)。
|
|
305
|
+
> Get-ChildItem "<Gradle根>\.gradle\user-home\caches\<ver>\javaCompile\*.bin" |
|
|
306
|
+
> ForEach-Object { Get-FileHash $_.FullName -Algorithm SHA1 | Out-Null }
|
|
307
|
+
> # 紧接着跑 hotdeploy / :<模块>:build,量 wall(用 daemon 日志的 started/finished 时间戳对)
|
|
308
|
+
> ```
|
|
309
|
+
> (为什么这样就够:R3.2 的判据已限定「`classAnalysis.bin` 已存在**且不再增长**」⇒ 快照不是在**建**、而是在被**读**,所以"先把这批文件读进内存"正好精确检验 page cache 假设。)
|
|
310
|
+
> **判读**:变快(~10s 量级)→ 成因 = **① page cache 冷读** ✅;仍 ~140s → 成因 = **② Gradle 缓存状态重新校验**(与磁盘读无关)✅。**两种结果都定案,不必跑两次。**
|
|
311
|
+
> ⚠️ 前提:必须是**自然冷态**(连续构建会把窗口消耗掉);做完后把结果与结论写回本条,并删除"未定"字样。
|
|
291
312
|
> 内存已排除:实测该机 **65 GB 总量 / 40.6 GB 可用**(也印证删掉 `-Xmx` 那条建议是对的)。
|
|
292
313
|
> 源文件可追溯:`<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))。
|
|
293
314
|
|
|
@@ -387,6 +408,10 @@ try { & $GRADLE ":<模块>:build" -x test --console=plain } finally { Pop-Locati
|
|
|
387
408
|
| F8 | 构建长时间无输出 | 多半是冷缓存建快照,不一定是死锁 | 用 R3.2 判据;确卡住再清 Gradle 守护进程重试(**不要动 cosmic 进程**) |
|
|
388
409
|
| F9 | `Full recompilation is required because <类> could not be analyzed` | 增量编译失效(classpath 上有注解处理器 / Java17+ 类 / MR-JAR) | 见 `cosmic-dev-best-practices/references/cosmic-hotdeploy-build-slow-windows.md` §4 |
|
|
389
410
|
| F10 | 同一条命令第二次才成功(第一次报 cwd / 编码等) | 环境差异没被前移成决策规则 | **回写本手册**:补进 R1/R2 的规则或本表 |
|
|
411
|
+
| F11 | `[Win]` **物化脚本**报 `Unrecognized token in source text` / `The string is missing the terminator: "@`(**位置指向中文字符串中间**) | 脚本文件是 **UTF-8 无 BOM**,PS 5.1 按 ANSI 解码 → 中文被碾碎、引号配对错乱。**与脚本逻辑无关** | 把 `.ps1` 存为 **UTF-8 with BOM**:`$t=[IO.File]::ReadAllText($p); [IO.File]::WriteAllText($p,$t,(New-Object Text.UTF8Encoding($true)))`。⚠️ **任何重写该脚本的工具/编辑器(含 agent 的 write/edit)都会去掉 BOM** ⇒ 每次改动后**重新加 BOM + 跑语法检查**:`[Management.Automation.Language.Parser]::ParseFile($p,[ref]$null,[ref]$err)` |
|
|
412
|
+
| F12 | `[Win]` `Invoke-WebRequest … -MaximumRedirection 0` 抛 `Operation is not valid due to the current state of the object` | PS 5.1 的已知行为,**不是** cosmic 没起 | 去掉 `-MaximumRedirection 0`(见 R0.3 注) |
|
|
413
|
+
| F13 | `[Win]` 物化脚本报 `Cannot overwrite variable Home because it is read-only or constant`,**行号指向"调用该函数的那一行"而非函数定义** | PowerShell 函数**参数名**与**只读自动变量**同名(`$Home` / `$Host` / `$PID` / `$Input` / `$Args` / `$Error` / `$Matches` / `$Profile` …)→ 参数绑定时写只读变量失败。⚠️ 报错位置在**调用点**,极易去调用点找不存在的 bug | 改参数名(实测:`function Test-Jdk([string]$Home)` → `$JdkDir`);物化脚本自查时顺手扫一遍这些保留名 |
|
|
414
|
+
| F14 | `[Win]` 受限沙箱下 `Invoke-WebRequest` 抛 `Win32 internal error "Access is denied" 0x5 occurred while reading the console output buffer`(**不是** HTTP 错误码) | 受限令牌下控制台/管道被砍,**与 cosmic 死活无关**;照抄会误判成"cosmic 没起" | 用 **TCP 兜底**:`(New-Object System.Net.Sockets.TcpClient).Connect('127.0.0.1',<port>)` 不抛异常 = **端口有监听**(⚠️ **不等于"是 cosmic"**,仍须走 R0.4 校验命令行);放开权限后 HTTP 探测恢复正常(实测放开后同一 URL 返回 200) |
|
|
390
415
|
|
|
391
416
|
### 自检(每轮执行后)
|
|
392
417
|
|
|
@@ -30,7 +30,7 @@ CreatePipe error=5, 拒绝访问
|
|
|
30
30
|
|
|
31
31
|
- 用户只改一行 Java 代码,`gradle :<模块>:build` 耗时 **32 秒**(预期 5~10 秒)
|
|
32
32
|
- 无改动构建约 4 秒(UP-TO-DATE 正常),**一旦有改动就全量重编**(583 个类)
|
|
33
|
-
- 判断标准:改一行后看 `build/classes/java/main` 下 class 文件时间戳,**全部更新 =
|
|
33
|
+
- 判断标准:改一行后看 `build/classes/java/main` 下 class 文件时间戳,**全部更新 = 全量重编**(⚠️ 此法有 `FROM-CACHE` 假阳性,见 §1.1 末尾)
|
|
34
34
|
|
|
35
35
|
### 1.1 快速识别"增量失效"
|
|
36
36
|
|
|
@@ -47,6 +47,17 @@ $new = $classes | Where-Object { $_.LastWriteTime -ge (Get-Date).AddMinutes(-2)
|
|
|
47
47
|
> ⚠️ 注意:如果两次构建间隔很短(如先全量后增量),2 分钟窗口会混入前一次全量的产物,
|
|
48
48
|
> 造成"还是全量"的误判。精确做法:以**最后一次构建结束后**为基准,取最新时间戳 ±30s 窗口,
|
|
49
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。
|
|
50
61
|
|
|
51
62
|
## 2. 排查工具速查
|
|
52
63
|
|
|
@@ -398,7 +409,8 @@ $jar = "<模块>\build\libs\<模块>-1.0.0.jar"
|
|
|
398
409
|
5. **`Get-NetTCPConnection` 在非管理员权限下会误报"无监听"**,用 `Invoke-WebRequest` 探测兜底
|
|
399
410
|
6. **build 前确认 Daemon 活着**:`gradle --status` 应见 `IDLE` 条目;`--no-daemon` 会为每次构建重付 JVM 冷启动 + 配置(本项目实测 Δ≈10s;另一工作区全新 daemon 冷启动 3–5s —— **别引用"+30s"**,见 §4.7 注)
|
|
400
411
|
7. **识别全量重编**:改一行后 class 文件时间戳全变 = 全量;只有个别变 = 增量正常;
|
|
401
|
-
多次构建间隔短时用「最新时间戳 ±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`**,时间戳只能当旁证。
|
|
402
414
|
8. **`dependencies --configuration compileClasspath` 对 fileTree 是惰性展开**,不一定显示 jar 明细,
|
|
403
415
|
要确认真实 classpath 必须用自定义任务打印 `sourceSets.main.compileClasspath.files`
|
|
404
416
|
9. **`jps` 看不到 cosmic 进程**(实测):本机 cosmic 由 **SYSTEM** 账户启动
|
|
@@ -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`。)
|