@shundoo-ai/dsh-cosmic 1.0.10 → 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shundoo-ai/dsh-cosmic",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "苍穹助手:金蝶云苍穹ERP的开发与数据分析,涵盖表单元数据建模、插件开发与热部署、数据可视化报告。",
5
5
  "keywords": [
6
6
  "dsh",
@@ -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 忽略、不入库);② **本手册是唯一权威**——手册更新后重新生成,不得反向以脚本为准;③ 脚本只做编排(发现 → 构建 → 注入),**不得引入手册之外的行为**(**允许**只读的发现/干跑模式 —— 不构建、不注入、不改环境,如 `-DryRun`);④ **不得写死本机路径**(工作区 / Gradle 根 / profile 名 / JDK 安装路径),工作区与 Gradle 根按 R1.1 推导、profile 用 `$DSH_PROFILE_DIR`、JDK 按 R2.1 顺位选择 —— 实测有脚本写死 `$cwd` 与 `profiles\web`,换机器即失效。**生成后自查**:在脚本里 grep 一遍本机绝对路径与写死的 profile 名,应当**只出现推导逻辑、不出现具体值**。
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 解码);`$env:VAR=` | bash/sh;`export VAR=` |
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 探测**端口(不依赖任何权限) | `200`/`302` | 非 2xx/3xx → cosmic 没起或端口不对,停 |
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 解析布局
@@ -402,6 +408,10 @@ try { & $GRADLE ":<模块>:build" -x test --console=plain } finally { Pop-Locati
402
408
  | F8 | 构建长时间无输出 | 多半是冷缓存建快照,不一定是死锁 | 用 R3.2 判据;确卡住再清 Gradle 守护进程重试(**不要动 cosmic 进程**) |
403
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 |
404
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) |
405
415
 
406
416
  ### 自检(每轮执行后)
407
417