@microi.net/cli 5.8.1 → 5.8.3
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/.codebuddy-plugin/marketplace.json +2 -2
- package/.codebuddy-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.workbuddy-plugin/marketplace.json +2 -2
- package/.workbuddy-plugin/plugin.json +1 -1
- package/assets/build-meta.json +4 -4
- package/cordis.patch.yml +1 -1
- package/package.json +1 -1
- package/scripts/mcp-server.js +99 -99
- package/scripts/microi-skills.meta.json +218 -218
- package/skills/.microi-skills-version.json +2 -2
- package/skills/.progressive-disclosure-manifest.json +40 -40
- package/skills/ai-engine/references/self-hosted-digital-human.md +14 -0
- package/skills/app-store/SKILL.md +71 -0
- package/skills/dos-orm/SKILL.md +1 -0
- package/skills/job-engine/SKILL.md +4 -0
- package/skills/microi-client-frontend/SKILL.md +4 -1
- package/skills/microi-codex/SKILL.md +4 -1
- package/skills/microi-deployment/SKILL.md +10 -8
- package/skills/microi-form-engine/SKILL.md +5 -3
- package/skills/microi-microservice/SKILL.md +3 -0
- package/skills/module-engine/SKILL.md +5 -0
- package/skills/playwright-e2e/SKILL.md +2 -3
- package/skills/ui-design/references/motion-and-media.md +7 -0
- package/skills/unity-integration/SKILL.md +16 -0
- package/skills/v8-crud-api/SKILL.md +2 -1
- package/skills/v8-file-upload/SKILL.md +4 -4
- package/skills/v8-file-upload/references/progressive-01-/345/205/254/346/234/211/346/241/266-vs-/347/247/201/346/234/211/346/241/266.md +24 -1
- package/skills/v8-saas-multi-tenant/SKILL.md +43 -0
- package/skills/v8-security/SKILL.md +4 -0
- package/skills/v8-utilities/SKILL.md +8 -0
- package/skills/v8-workflow/SKILL.md +2 -1
- package/skills/workspace-conventions/SKILL.md +3 -3
- package/skills/workspace-conventions/references/progressive-02-microi-net-api-/346/234/254/345/234/260/345/220/257/345/212/250/347/272/246/345/256/232.md +7 -6
|
@@ -69,3 +69,10 @@ idle -> entering -> settled -> interacting -> paused -> reduced
|
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
同时检查低端 Android、后台标签页、弱网、资源失败、浏览器缩放 200% 和高对比模式。视觉效果不能成为业务完成事实源。
|
|
72
|
+
|
|
73
|
+
## 复盘:烘焙棋格与可交互覆盖层错位
|
|
74
|
+
|
|
75
|
+
- 触发场景:非母版比例屏幕、DPR 改变、横竖屏切换或背景呼吸动画后,点击/棋子未落在实际棋格。
|
|
76
|
+
- 根因:图片 cover 尺寸、设计尺寸与 framebuffer 尺寸混用,或图片独立变换而交互层静止。
|
|
77
|
+
- 通用规则:从实际图片尺寸与同一个父级变换推导烘焙 UV 位置;拾取为渲染的精确逆变换,棋子、提示、点击和特效共用坐标事实源。换肤与 resize 后重算,不增加第二层运行网格掩盖错位。
|
|
78
|
+
- 自动化检查:逐格 round-trip;原生比例/16:9/超宽/竖屏与不同 DPR 的真实 pointer 点击;动画前后、resize 和换肤后核对索引与截图。
|
|
@@ -89,6 +89,15 @@ did: {DeviceId}
|
|
|
89
89
|
- 表、索引、菜单、接口与权限通过应用 Manifest 安装,不为游戏资源新增 `Microi.Upgrade` 定制迁移。
|
|
90
90
|
- 所有接口必须声明 `ResourcePolicies.ApiEngines`:官方核心 `Managed`;租户扩展 `CreateIfMissing`,后续升级不覆盖。
|
|
91
91
|
|
|
92
|
+
### 持续权威模拟与平台宿主
|
|
93
|
+
|
|
94
|
+
- 先区分接口引擎业务编排、持续固定步模拟和实时通知。SignalR版本通知不是规则执行;秒级Job只用于恢复/扫描/补偿,不能宣称20Hz连续模拟。
|
|
95
|
+
- 仅在现有纯V8无法满足固定步规则时使用通用受信规则宿主。Domain与应用适配仍属于私有应用程序集,平台只提供调度/预算/作用域;禁止把整套游戏规则加入Microi.Server或新增游戏Controller。
|
|
96
|
+
- 后台发行固定tenant、入口、审批摘要和实际DLL/依赖hash;主库绑定已安装与已完成发布版本,每次运行回读撤销。不得从玩家Param、可编辑V8或MCP传路径/URL/Type来装载代码。明确原生代码是受信后端代码,不是沙箱。
|
|
97
|
+
- 使用 `RunPlatformApiRuntime` 之前核后端实际安装。公开入口只收意图,成员和席位由DiyToken重算;DB时钟、租约/fence、完整checkpoint与inbox在同一事务。未知提交保持原RequestId,停机停止接收并有界排空,旧owner不得续写。
|
|
98
|
+
- 连续宿主唤醒需接Owned提示;当前无afterCommit回调,只能在持久写入成功后、return Code=1前发出有界提示,不能说已经提交后唤醒。pump仍须重新锁主库并核owner/fence/租约;原事务回滚不能产生合法推进。终局用DrainOwnedRoom停止后续调度,允许当前事务返回提交;StopOwnedRoom会立即取消当前请求。无外部主机不等于无需后端部署。只给本人/同队可见投影,公开频道不传全量状态。
|
|
99
|
+
- 验收分离规则测试、原子编译、真实Jint/SQL、两节点/强杀恢复、HTTP与实际渲染;固定频率或协议夹具通过不能代表商业竞技品质。
|
|
100
|
+
|
|
92
101
|
### 5. 构建可安装 AI 应用
|
|
93
102
|
|
|
94
103
|
- `ApplicationType` 使用 `Web`;Vue 3 + Vite + TypeScript 作为页面外壳,Unity Canvas/WebGL 与普通 DOM 分层。
|
|
@@ -147,6 +156,13 @@ did: {DeviceId}
|
|
|
147
156
|
|
|
148
157
|
## 停止发布的条件
|
|
149
158
|
|
|
159
|
+
### 复盘:运行时特效在 WebGL 被裁剪或短到看不见
|
|
160
|
+
|
|
161
|
+
- 触发场景:编辑器开炮正常,公开 WebGL 只出现命中,没有可见飞行子弹。
|
|
162
|
+
- 根因:仅运行时 AddComponent 的 LineRenderer、ParticleSystem 或 Collider 未纳入引擎保留,或高速 easing/过短 lifetime 使飞行阶段几乎不可见。
|
|
163
|
+
- 通用规则:真实发布构建中保留所需模块与动态 Shader;炮口取实际炮管世界变换,飞行持续时间按距离限界,弹芯/尾迹/命中分层,共享材质不可逐次克隆泄漏。
|
|
164
|
+
- 自动化检查:公开 WASM 实际加载,连续至少三帧断言弹体位置变化;检验四种武器、空射、真实权威命中与资源/console 错误。单帧截图不能证明动态特效。
|
|
165
|
+
|
|
150
166
|
- Unity 许可证未激活或 WebGL 模块缺失。
|
|
151
167
|
- Unity 构建只有外壳,没有真实 WASM/Data。
|
|
152
168
|
- 素材许可证、AI 提示词或资产来源不可追溯。
|
|
@@ -38,7 +38,7 @@ Microi.net.Api 普通本地启动不要额外设置 `ASPNETCORE_ENVIRONMENT` / `
|
|
|
38
38
|
生成接口引擎代码时,代码内容本身(文件头、普通注释、`console.log`、返回 `Msg` 等)不要包含 `Microi`、`吾码` 等平台品牌文字,除非业务数据或字段值本身必须如此。生成代码要有可维护注释:每个 `function` 前写清用途、关键参数和返回值;跨表事务、权限校验、状态机、金额/库存计算、复杂 `_Where` 条件等代码段前写短注释说明业务原因;避免“给变量赋值”这类无信息量注释。
|
|
39
39
|
|
|
40
40
|
<!-- /microi-progressive:chunk -->
|
|
41
|
-
<!-- microi-progressive:chunk id=v8-crud-api-001 sha256=
|
|
41
|
+
<!-- microi-progressive:chunk id=v8-crud-api-001 sha256=d0bed55dcaa08fd84319107269643dd5aba5aadecf4f394c8ac55d80ab959677 -->
|
|
42
42
|
## 核心规则
|
|
43
43
|
|
|
44
44
|
- 接口引擎文件是纯 JavaScript(Jint 引擎,非 Node.js)
|
|
@@ -47,6 +47,7 @@ Microi.net.Api 普通本地启动不要额外设置 `ASPNETCORE_ENVIRONMENT` / `
|
|
|
47
47
|
- 严格业务字段白名单先逐项排除本入口支持的宿主传输字段:固定 `ApiEngineKey / ApiAddress`、调用类型、设备和 HTTP 请求元数据;不得把整个下划线前缀视为安全字段,不解析 `_RawBody` 重写动作,也不从传输字段取授权。历史调试器的 `TestParam1` 仅兼容 null/undefined、最多 200 字符的字符串、有限数字或布尔值并立即丢弃;对象、数组、超长值和其它未知字段继续拒绝。真实 HTTP 与内部调用都须验收,普通岗位无初始化配置副作用,权限继续读取权威当前用户与目标租户。
|
|
48
48
|
- `V8.Param` 中嵌套 JSON 的 `JObject/JArray` 可能是 Jint 宿主对象,`Array.isArray` 不一定成立。需要严格数组、布尔或结构校验时,在业务入口对有界业务参数使用 `JSON.parse(JSON.stringify(V8.Param || {}))` 转为纯 JSON,再执行原字段白名单、类型、大小与权限校验;不能把只有 `length` 的对象当数组。只规范化业务参数,不复制或信任客户端身份、`V8.CurrentUser`、`V8.DbTrans` 或 `V8.WF`;大文件继续使用专用文件通道。验收须同时覆盖真实 HTTP 宿主集合和离线 JavaScript 数组。
|
|
49
49
|
- 通过 `V8.CurrentUser` 获取当前登录用户信息
|
|
50
|
+
- 高精度 `decimal(p,s)` / 带小数位 `number(p,s)` 的金额、数量、换算率使用无分组、英文小数点的十进制字符串,避免先 `Number()` / `parseFloat()` 或浮点运算丢位。后端使用固定文化解析,拒绝逗号分组、本地化逗号小数、指数、非数字和越界;业务层仍须按字段约束精度、小数位、范围和权限。空值兼容不变,不能从舍入后的历史值重建精度或擅自回填。用真实 HTTP、数据库写后读与目标租户验收,不能把 CLR 参数绑定冒充数据库成功。
|
|
50
51
|
- 返回结果统一格式:`{ Code: 1, Data: any, Msg: '成功' }`
|
|
51
52
|
- 所有 FormEngine 方法在服务器端支持第三个参数传入 `V8.DbTrans`(事务对象)
|
|
52
53
|
- 服务端调用 FormEngine 默认**不触发**表单 V8 事件,加 `_InvokeType: 'Client'` 才触发
|
|
@@ -7,7 +7,7 @@ description: Microi V8 与 MCP 文件上传下载指南。用于处理流式 AI
|
|
|
7
7
|
|
|
8
8
|
# Microi V8 文件上传下载
|
|
9
9
|
|
|
10
|
-
你正在为 Microi 吾码平台编写文件上传/下载/返回相关代码。平台分布式存储(HDFS)支持阿里云OSS、MinIO、亚马逊S3,存储方案由 SaaS
|
|
10
|
+
你正在为 Microi 吾码平台编写文件上传/下载/返回相关代码。平台分布式存储(HDFS)支持阿里云OSS、MinIO、亚马逊S3,存储方案由 SaaS 引擎按租户配置。上传对象的 `Content-Type` 由框架按实际对象路径统一确定,覆盖 HTML、JS/MJS、CSS、JSON/MAP、SVG、字体与 WASM,未知后缀保留 `application/octet-stream`。MinIO、S3、OSS 普通与分片上传使用同一映射;该映射不替代上传权限、内容和配额校验。旧对象不会因后端升级自动改变元数据:先核对字节数和 SHA-256,再修正类型或按正式应用发布流程产生新版本。不要把源码与公有编译产物混在一起,也不要关闭 `nosniff` 掩盖类型错误。
|
|
11
11
|
|
|
12
12
|
公开入口覆盖 `V8.uploadFile`、多文件 `V8.uploadFiles` 与 MCP `microi_upload_file_base64`。多文件上传必须限制并发、逐文件返回结果;Base64 工具只接受明确文件名、大小和租户内目标范围,写后回读路径、大小与哈希。
|
|
13
13
|
|
|
@@ -89,7 +89,7 @@ description: Microi V8 与 MCP 文件上传下载指南。用于处理流式 AI
|
|
|
89
89
|
官网客户端读取私有文件统一调用 `/apiengine/platform-private-file-url`,提交 `FilePathName` 或有界 `FilePathNames`,并按资源类型提供权威定位参数:普通表单字段使用 `FormEngineKey + FormDataId + FieldId + SysMenuId`;用户头像使用 `ResourceKind=UserAvatar + ResourceId=用户Id`;菜单/部门导入模板分别使用 `MenuImportTemplate`、`DeptImportTemplate` 与对应记录 Id。CAD 私有派生预览使用 `ResourceKind=FormFieldDerivedPreview`,除表单四元组外必须同时提交字段中保存的 `OriginalFilePathName` 和单个派生 `FilePathName`;后端只接受同目录同 basename 的 DWG→`_preview.dxf`、STEP/STP→`_preview.stl` 唯一映射,并在对象存在后签名。文件柜对象使用 `ResourceKind=FileManagerObject`,`ResourceId` 必须与单个 `FilePathName` 大小写精确相同,并提交能力探针返回的当前租户权威 `SysMenuId`;此类签名只允许平台超级管理员 DiyToken 会话,访问密钥和普通菜单用户一律拒绝。后端会从权威字段或对象存储重新读取并精确匹配路径;管理员也不能只传裸路径绕过对象引用,普通客户端禁止换取私有文件原始 Byte/Stream。旧 `/api/HDFS/GetPrivateFileUrl` 与 `/api/HDFS/MallFileUrl` 只保留令牌格式兼容并转发同一 Managed 接口,新代码不得继续引用。
|
|
90
90
|
|
|
91
91
|
<!-- microi-progressive:begin -->
|
|
92
|
-
<!-- microi-progressive:chunk id=v8-file-upload-000 sha256=
|
|
92
|
+
<!-- microi-progressive:chunk id=v8-file-upload-000 sha256=d134ef9d7df6a00a6f11149a7f73595d96d4feb0ffa159e520136c72de7f495a -->
|
|
93
93
|
## 核心 API
|
|
94
94
|
|
|
95
95
|
| API | 说明 |
|
|
@@ -107,6 +107,8 @@ description: Microi V8 与 MCP 文件上传下载指南。用于处理流式 AI
|
|
|
107
107
|
|
|
108
108
|
固定 CDN 应用回填优先使用服务端 `CopyObject`,公有桶复制编译资产、私有桶复制源码;`Limit` 在源与目标间保持一致,`Path` 和 `FilePathName` 均由后端收敛到当前租户。大对象用 `GetObjectSha256` 流式核对原对象和复制目标,公有体验路径仍须从 CDN 独立回读。历史版本目标已存在时须核对字节哈希,发现不同内容立即停止;固定根可在新版本验证后覆盖。`ListObjects` 必须分页并限制到单个应用前缀,不得把这些存储管理原子直接开放为匿名业务接口。
|
|
109
109
|
|
|
110
|
+
MinIO SDK 7 的复制签名不匹配还可能来自带参数 MIME:SDK 对源 `Content-Type` 签名,却在 HTTP 请求中额外保留 `StringContent` 的默认 MIME。先在独立夹具核对源 MIME、重复头和真实存储返回,再升级后端复制传输修复;不能去掉 `charset`、关闭签名校验或下载后重传来伪造通过。修复后必须同时验证公私桶原始字节、精确 MIME、源元数据及源对象保留,固定入口恢复另覆盖主库权威、真实共享租约、双节点竞争和新进程重跑。取消/超时后保持原请求键,先回读目标再决定是否继续。
|
|
111
|
+
|
|
110
112
|
<!-- /microi-progressive:chunk -->
|
|
111
113
|
<!-- microi-progressive:chunk id=v8-file-upload-001 sha256=d535a333639a9005f5d20f25e36e2753a11835380713c1bb063ae618e6cea4af -->
|
|
112
114
|
## 第三方数据库附件迁移
|
|
@@ -276,9 +278,7 @@ return upResult;
|
|
|
276
278
|
|
|
277
279
|
<!-- /microi-progressive:chunk -->
|
|
278
280
|
## 详细参考路由(渐进披露)
|
|
279
|
-
|
|
280
281
|
仅在当前任务涉及对应主题时读取;下列文件合计保留了原 SKILL.md 的全部详细知识。
|
|
281
|
-
|
|
282
282
|
- [references/progressive-01-公有桶-vs-私有桶.md](references/progressive-01-公有桶-vs-私有桶.md):公有桶 vs 私有桶;接口直接响应文件(下载/导出);通过 URL 列表批量下载并入库
|
|
283
283
|
- [references/progressive-02-office-文件在线编辑版本号规则.md](references/progressive-02-office-文件在线编辑版本号规则.md):Office 文件在线编辑版本号规则;ImgUpload / FileUpload 字段值兼容规则;安全注意
|
|
284
284
|
<!-- microi-progressive:end -->
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> 按需读取;本文件由 SKILL.md 的原章节无损拆分。
|
|
4
4
|
|
|
5
|
-
<!-- microi-progressive:chunk id=v8-file-upload-005 sha256=
|
|
5
|
+
<!-- microi-progressive:chunk id=v8-file-upload-005 sha256=0b4d57f32bfe913c3a2567d2e2a86f4d5ba505d60c4348ad472c117774bbfc31 -->
|
|
6
6
|
## 公有桶 vs 私有桶
|
|
7
7
|
|
|
8
8
|
### 应用商城 ZIP
|
|
@@ -31,6 +31,29 @@ var extractResult = V8.Method.ExtractZip({
|
|
|
31
31
|
|
|
32
32
|
`System.IO` 在 Jint 沙箱中被禁止,不能在 V8 代码里直接构造 `MemoryStream/ZipArchive`;必须使用以上受控方法。
|
|
33
33
|
|
|
34
|
+
### 安装后的私有源码完整性
|
|
35
|
+
|
|
36
|
+
私有源码安装还须把旧日期/时间戳上传对象复制到完整清单摘要对应的活动目录,精确保存原始
|
|
37
|
+
`FilePath` 的大小写、中文与空格。复制后校验目标的 `Data.Sha256` 与 `Data.Size`,再写当前
|
|
38
|
+
文件元数据和最终应用指针;保留旧对象,不用 `MoveObject` 或删除旧源。复制 ACK 丢失时只
|
|
39
|
+
通过目标原始字节摘要回读确认,不盲目重传;目标已存在但摘要不同、权限不足或能力缺失均
|
|
40
|
+
停止。复用文件的验签和路径修正也计入资产分片预算,不能只对新上传文件计数。完成安装后
|
|
41
|
+
源码 ZIP 导出前后按完整原始文件路径、摘要和大小核对 `store-` 活动根的清单承诺,部分旧根
|
|
42
|
+
或漂移拒绝输出;ZIP 中兼容去掉 `source/` 包装目录不改变安装根的原始路径摘要。
|
|
43
|
+
仍须下载原生源码 ZIP 并逐文件验签,不用对象摘要代替 ZIP 实际返回字节的独立验证。
|
|
44
|
+
|
|
45
|
+
### 已提交应用的 CDN 特殊字符别名修复(强制)
|
|
46
|
+
|
|
47
|
+
- 区分逻辑路径、对象键和 URL:原始 `@` 对象的 URL 可写 `%40`;字面量 `%40` 对象的 URL 需写 `%2540`。禁止在 HDFS 全局反解码对象键,禁止迁移或覆盖协议 v3 不可变编码对象、完整性标记及清单摘要。
|
|
48
|
+
- 此类修复使用现有受管接口引擎 `ai_app_cdn_backfill` 的 `Action=RepairCommittedCdnAliases`,不是任意文件复制接口。当前租户超级管理员仍须满足 `Level >= 9999`,精确匹配 `AppId/ConfirmAppId`;只补充已提交公有运行资产的原始 `@` 别名,不接收文件体、桶、URL 或自定义来源/目标路径。
|
|
49
|
+
- 先回读商城及完整版本记录,显式冻结 `ExpectedAppKey/ExpectedVersionId/ExpectedVersionNo`、`ExpectedRequestId/ExpectedRequestFingerprint/ExpectedRuntimeManifestHash`、`ExpectedCommittedPublishVersionId/ExpectedCommittedRuntimeManifestHash`、`ExpectedCurrentVersion/ExpectedPublishFence/ExpectedPublishRowVersion`。后三个数值使用规范十进制字符串。服务端须同时核对活动指针、协议、版本归属、版本 `FencingToken`、派生 `ReleasePrefix` 及完整清单;不得用调用方传入的清单替代权威记录。
|
|
50
|
+
- 商城与版本状态只接受 `ProjectionPending/RepairRequired/Completed`。完整运行清单按平台 ordinal 路径顺序,以 `Path<TAB>Sha256<TAB>Size`、行间 LF、末尾无 LF、UTF-8 重算 SHA-256;后续每次回读还须保持冻结清单字符串不变。指针、活动版本、栅栏、行版本或清单变化即停止,先核对部分副作用,再重新取得契约,不能盲目替换预期值续跑。
|
|
51
|
+
- 仅接受 `assets/<bundle>/import/<两位十六进制>/<文件名>@<子资源>.json` 的非入口、公有运行 JSON,每个不超过 1 MiB;拒绝源码、私有资源、百分号转义、绝对路径、目录穿越和不支持的 `@` 路径。来源为同版本目录中把原始 `@` 替换成字面量 `%40` 的既有对象;目标为版本目录及固定目录的原始 `@` 对象。全部使用当前租户内对象路径和 `Limit:false`,不能用 HTTPS 来源 URL 代替。
|
|
52
|
+
- `DryRun` 默认 `true`,显式 `false` 才复制。`AliasStart` 是冻结清单内符合条件的原始 `@` JSON 列表的零基游标,`AliasCount` 只允许 1–5;每资产最多复制版本和固定两个别名,一批最多 10 次复制。写入前预检整批来源和已有目标:`Sha256` 是原始物理字节摘要,与 `Size` 一同绑定清单;`WireSha256` 是字节转为 Base64 文本后的历史兼容摘要,只校验格式及来源、目标一致,禁止将它与清单原始摘要作相等判断。目标同字节跳过,任一不同即整批拒绝。每次复制前后重新核对摘要及最新绑定。
|
|
53
|
+
- `V8.Method.CopyObject` 没有原子的 create-if-absent/禁止覆盖保证,此动作必须如实返回 `AtomicCreateOnly:false`。预检查存在检查与复制之间的竞态,不能与另一发布者或任意写入者竞争同一固定路径;原后台投影可继续写同一冻结版本的相同字节。不得把“先查不存在再复制”描述为原子 create-only。
|
|
54
|
+
- 每批先 DryRun,再用同一绑定复制,保存 `Attempted/Copied/RequiresReadback/NextAliasStart`,从版本与固定 CDN 独立核对实际字节后再续批。超时、未知结果或 `Code=0` 先回读已尝试路径,不能盲重试;数据库事务无法回滚 OSS 副作用。禁止删除旧对象、重新上传字节、HTTP 回退或直接修改数据库状态。
|
|
55
|
+
- 修复不刷新 CDN、不推进指针、不修改清单或发布状态。原后台必须继续完成刷新、公开回读与 `Completed` 状态收敛;不能以对象复制成功代替公网资源及真实浏览器验收。操作说明见 [分布式存储](https://microi.net/doc/more/hdfs.html)。
|
|
56
|
+
|
|
34
57
|
### AI 应用编译目录流式发布(首选)
|
|
35
58
|
|
|
36
59
|
发布 Web、UniApp、MicroService 的 `dist` / H5 编译目录时,必须优先使用 `microi_publish_application_directory_stream`,不要把每个文件读成 Base64 后传给 `ai_app_build`、`microi_publish_microservice` 或普通 JSON 接口。旧工具仅为小文件兼容保留。
|
|
@@ -21,6 +21,12 @@ Microi 多租户 = **`OsClient` + `OsClientType` + `OsClientNetwork`** 三参数
|
|
|
21
21
|
|
|
22
22
|
主租户不是固定字符串 `master`,而是由当前部署的环境变量 `OsClient` 或 `AppSettings:OsClient` 决定。租户记录存放在受保护的 `sys_osclients` 表中;普通业务角色和普通 V8 不得直接查询、复制或修改该表。
|
|
23
23
|
|
|
24
|
+
标准 MCP 连接必须保持 API 与这三个租户坐标一致。`MICROI_OS_CLIENT_TYPE`、`MICROI_OS_CLIENT_NETWORK` 是 MCP 进程的可选连接配置,显式设置时必须绑定非空 `MICROI_OS_CLIENT`;它们随 Login 表单、Refresh 正文、所有 API Header 和流式 multipart 表单传输,普通 JSON 业务正文与 GET 查询不额外注入 Type/Network。省略可选项保持原协议。SSE 对应 `X-Microi-OsClient`、`X-Microi-OsClientType`、`X-Microi-OsClientNetwork`,每个连接独立绑定身份;单次请求与已配置坐标冲突、重复或含非法标识时发送前拒绝。
|
|
25
|
+
|
|
26
|
+
连接或恢复后先执行 `initialize`、`tools/list`、`microi_get_status`,按服务端实际 API、OsClient、Type、Network 核验目标分区,再读基线或写入。Token 文件的四段键不能证明 HTTP 已选中该分区;不匹配时修复连接传输,不修改 SaaS 租户网络记录、跨分区借用身份或更换原业务请求键。
|
|
27
|
+
|
|
28
|
+
API 必须指向目标分区的真实节点。三参数 Header 只声明连接目标,不能切换节点可信运行分区或发布门禁;Header 已正确而 status 仍不匹配时停止写入并修正节点地址,禁止修改 SaaS/gate、借其它分区任务或用请求头强迫节点切区。
|
|
29
|
+
|
|
24
30
|
## 上下文变量
|
|
25
31
|
|
|
26
32
|
```javascript
|
|
@@ -51,6 +57,37 @@ V8.OsClientModel.AliOssPublicDomain // 可公开的文件域名
|
|
|
51
57
|
|
|
52
58
|
## 平台级配置与主租户规则
|
|
53
59
|
|
|
60
|
+
### 推广中心与匿名空库开通
|
|
61
|
+
|
|
62
|
+
- 主租户现有 `V8.FormEngine` 允许显式指定子租户;子租户被 `V8TenantContext.EnforceOsClient`
|
|
63
|
+
强制限制到自身。主租户业务员的业务范围须由接口引擎再次授权,不能仅凭主租户上下文放行全部租户。
|
|
64
|
+
- SaaS 官方应用唯一拥有三个 Managed Key:`platform-saas-promotion`、`platform-saas-public-trial`、
|
|
65
|
+
`platform-saas-public-trial-worker`。内置微服务的 `/saas-promotion` 归系统引擎,公开 `/saas-trial`
|
|
66
|
+
仅固定主租户、固定应用可匿名解析,禁止用 src/appKey/routePath 查询参数扩大匿名宿主范围。
|
|
67
|
+
- `V8.Method.AuthorizeSaasPromotion()` 仅绑定推广接口,重新读取有效账号、角色、菜单与管理角色。
|
|
68
|
+
默认业务员范围为 `ReferralUserId=当前sys_user.Id`;管理角色可读全局,平台管理员才可配置。
|
|
69
|
+
`V8.Method.ReadSaasTenantUsage({TenantIds,Refresh})` 只绑定同一接口,最多20个已授权子租户,无任意SQL或连接参数。
|
|
70
|
+
- 统计使用目标库主库固定聚合,缓存60秒、刷新至少15秒、并行最多4库。缺失或失败显示未知,
|
|
71
|
+
近7/30天登录用户与日期分布来自 `LastLoginTime`,不能声称获得历史登录次数。旧租户归属和期限为空
|
|
72
|
+
时保持未分配/未登记;试用结束不代替许可证,也不自动停库。
|
|
73
|
+
- `V8.Method.CreateSaasReferralCapability(linkId)` 只为授权推荐人或管理者签发绑定主租户与分区的链接票据。
|
|
74
|
+
- `V8.Method.ResumeSaasPublicTrialTask(taskId)` 仅供同一推广接口的原推荐人或授权管理者恢复失败申请。
|
|
75
|
+
保留原幂等键和加密数据库检查点,最多执行三次;不得重新分配已有数据库账号密码。
|
|
76
|
+
公开空库使用主租户提供的启动地址,`DomainName` 保持未绑定,不能把含下划线的租户标识拼成独立域名。
|
|
77
|
+
- 公开接口通过 `V8.Method.SaasPublicTrialAtom` 校验主配置、签名链接、推荐人、验证码和额度,冻结单向密码哈希
|
|
78
|
+
与受认证加密的限开通票据。Worker 设置 `StopHttp=1`,`V8.Method.ProvisionPublicSaasTrial` 验证固定Key、
|
|
79
|
+
持久任务身份与 fencing token,不接受伪造管理员。相同UUID和相同输入复用任务,不同输入拒绝。
|
|
80
|
+
DDL 前持久化加密账号检查点;强杀后恢复同一任务,已有账号必须使用检查点原凭据通过验证,禁止覆盖密码。
|
|
81
|
+
进度只用独立短期票据和安全结果投影,不能暴露连接、密码、任务正文或票据密钥。
|
|
82
|
+
- 公开开关与额度字段 `SaasPublicTrial*`、管理角色 `SaasPromotionManagerRoleIds` 仅当前主租户分区有效;
|
|
83
|
+
推荐Id、请求Id、完成检查点、试用期限、联系与跟进字段不得从主租户复制给子租户。
|
|
84
|
+
- `platform-saas-promotion-hook` 为 CreateIfMissing,仅 `BeforeCreateLink/Assign/UpdateFollowup` 脱敏事件。
|
|
85
|
+
不直接修改 Managed 接口保存个性化代码。更新 SaaS 应用和基础空库包两条链,并验证真实业务员、
|
|
86
|
+
管理员、匿名开库、同UUID重复提交、暂停后恢复及子租户越权,不以离线测试代替。
|
|
87
|
+
- 复用标准 MCP `microi_get_db_schema`、`microi_add_field`、`microi_create_table_index`、`microi_create_engine`、
|
|
88
|
+
`microi_save_engine_code`、`microi_create_module`、`microi_run_engine` 及应用源码/流式发布工具;
|
|
89
|
+
先完整回读、计划和dryRun,再按已授权范围写入。已有推广Hook采用CreateIfMissing,不覆盖。
|
|
90
|
+
|
|
54
91
|
制作空数据库时,角色、账号绑定和权限快照必须作为同一初始模板处理。只保留明确声明的初始角色,按权威角色重建保留账号的 `RoleIds` 与等级;删除业务角色及孤立菜单权限,清空包含源业务菜单的角色权限快照。初始角色缺失、删除或等级不符时停止制作,不得根据账号现有角色列表、角色名称或高等级推测哪些角色应保留。
|
|
55
92
|
|
|
56
93
|
组织数据属于同一空库模板边界:只保留明确声明的初始组织和部门,将保留账号的部门绑定与名称同步归一,并清理旧版账号关系表。保护这些平台表的物理结构,初始组织缺失或已删除时停止制作;验收必须在新租户查看真实组织树,不能只检查角色数量。清理只能作用于制作过程的隔离副本。
|
|
@@ -233,3 +270,9 @@ SELECT * FROM Contact WHERE OwnerId = $CurrentUser.Id$ AND Spouse = $CurrentUser
|
|
|
233
270
|
- 开库入口把 ApiKey 传给后台 worker 后,worker 还必须继续显式传入最终的原子初始化方法;不能只在父接口或中间参数中“带过”。每个异步/后台边界都应对空值立即失败,避免租户创建成功但 `mic_ai.ApiKey` 静默为空。
|
|
234
271
|
- 自动化验收必须通过新租户 `admin` 登录回读 `mic_ai`,只输出“非空、长度、与官网账号 ApiKey 是否一致”等布尔结果,不得把真实 ApiKey 写入日志、截图或测试报告。
|
|
235
272
|
- 中转模型公开目录只返回模型 Id、显示名、厂商等非敏感字段,可匿名读取;严禁把官方上游模型的 ApiKey、Endpoint 私密配置随模型列表返回前端。
|
|
273
|
+
|
|
274
|
+
### 旧结构空库制作验收
|
|
275
|
+
|
|
276
|
+
空库脱敏生成器应只读实际物理列;组织机构旧表缺少可选父级名称列时,只写已有父级 Id,不为制作模板修改主库结构。物理字段发现失败应在输出清理 SQL 前失败关闭。验收同时覆盖有该列、缺少该列及读取失败,最终检查隔离副本和官方空库下载包。
|
|
277
|
+
|
|
278
|
+
应用文件与版本清理不得在 MySQL 5.7 的 DELETE 外连接中用 `Id = AppId OR AppKey = AppId`。先在隔离副本内物化带主键的 Id/AppKey 保留集合,分别覆盖当前商城 Id、历史 AppKey、业务应用、孤立记录与 NULL;验证新旧结果一致,源主库只读。真实 SQL 耗时与 Node 生成器测试需分别记录。
|
|
@@ -9,8 +9,12 @@ description: Microi V8 安全指南。用于审查 DiyToken 与权限、可逆
|
|
|
9
9
|
|
|
10
10
|
你正在开发 Microi 吾码平台的 V8 引擎代码,必须遵守以下安全规范。
|
|
11
11
|
|
|
12
|
+
登录与安全开关只能读取已启用且未删除的 `sys_config`;开关写入后须回读匿名能力和实际登录界面,避免历史停用/软删除行造成数据库与运行状态不一致。
|
|
13
|
+
|
|
12
14
|
访问密钥由 `microi_list_my_access_keys`、`microi_create_my_access_key`、`microi_revoke_my_access_key` 管理,只允许当前用户、限期、最小 scope,明文仅创建时返回一次。外部身份回调固定为 `/api/ExternalLogin/Callback`,服务端校验租户、Provider、state、redirect 和回调域名,验证成功后仍签发 DiyToken。
|
|
13
15
|
|
|
16
|
+
外部登录回调优先按当前有效 `sys_config.ApiBase` 的公网 HTTPS 地址与路径前缀生成,不能从前端参数或未受信 `X-Forwarded-*` Header 获取。反向代理终止 TLS 时,容器的 HTTP Scheme 不能代替该地址;供应商控制台登记值须与真实 Begin 返回的 `CallbackUrl` 一致。配置不允许账号密码、查询参数或片段;未配置时仅兼容直接 HTTPS 或本机 HTTP,无效配置失败关闭。协议验收必须覆盖外部 HTTPS、内部 HTTP 与公网路径前缀,不能只测试本机请求。
|
|
17
|
+
|
|
14
18
|
微信网站扫码登录先读取当前租户能力、`WeChatLoginEnabled` 和私密设置元信息,
|
|
15
19
|
再核对开放平台已审核网站应用的微信登录权限与授权回调域名。
|
|
16
20
|
`Login.WeChat.ClientId` 保存 AppID,`Login.WeChat.ClientSecret` 通过专用密钥工具保存,
|
|
@@ -69,6 +69,14 @@ var clientDecoded = V8.Base64.decode(clientEncoded);
|
|
|
69
69
|
- 原有前后端全局 V8 必须保留,合并顺序为内置日期、函数库、租户原有代码;同名原有函数优先。不得用官方全局脚本整段覆盖客户脚本。函数库种子 `InsertIfMissing`,不得升级覆盖客户已改源码。
|
|
70
70
|
- 列表和合并代码走 L1/Redis,表单引擎真实提交后更新租户版本并通知其它节点;回滚不变更版本。禁止通过直接 SQL 修改函数库规避失效。前端已打开页面需要刷新。
|
|
71
71
|
|
|
72
|
+
## 受信固定步长运行时发现
|
|
73
|
+
|
|
74
|
+
`V8.Method.RunPlatformApiRuntime({RuntimeKey:'fixed-step-simulation',Action,Param})` 属于需后端正式安装的通用原子。动作是 DescribeInvocation/CreateInitialState/AdvanceBatch/Project/ObserveOwnedRoom/StopOwnedRoom/DrainOwnedRoom;精确引擎Key由后台已审批目录限制,不能用通用private转发接口原样接受玩家信封。Param只能承载经接口引擎授权后的数据,不能指定Tenant/EngineKey/NodeId/客户端时钟作为真实上下文。Observe是提交前有界调度提示,后续须重新核DB,不是提交回执;终局用Drain保留当前请求提交机会,Stop则立即取消。规则程序集入口与hash须由私有后端发行组合固定,V8/MCP不提供上传即执行的注册能力。详细边界见unity-integration及后端V8主文档;线上缺原子时明确未安装,不能用Job/SignalR冒充。
|
|
75
|
+
|
|
76
|
+
固定步运行时的临时拒绝仅使用 `DataAppend.ErrorCode` 六码白名单:KernelBusy/HostMemoryPressure/RoomStillDraining/CoordinatorStopping/StaleLease/ComputeBudgetExceeded,并要求 `Retryable===true`。Managed须显式catch-return稳定Code0并回滚,客户端有界同键重试;禁止按中文Msg或带行号异常猜测重试,更不能把授权/来源/未知失败当临时成功。此兼容扩展不增加审批表/配置或MCP任意注册入口。
|
|
77
|
+
|
|
78
|
+
普通租户的编译证明默认 `TenantInstallation`,保留真实 Installed 回执及旧摘要。官方同租户发布源禁止安装自己,只能由后端发行组合明确固定 `OfficialPublishedSnapshot`:`InstallRecordId` 绑定 `mic_data_version.Id`,原始 `Data` 的UTF-8 SHA-256另固定于编译回执并参与独立审批摘要。该类别与快照摘要不从Param或自由表字段选择、不新增表字段、不伪造Installed。受信官方身份、当前Published/审批有效指针、Verified包hash/size/HDFS、不可变快照、V3 Completed源码hash及实际DLL依赖须全部匹配;当前状态变化、软删或主库不可用下次调用立即拒绝,旧历史存在不足以授权。跨租户仍拒绝,结构发布不等于后端安装或代码审批。审批表纳入通用强制管理员清单,普通用户即使误授表/菜单权限仍不得改授权状态;V8Limit和ReadPrimary不是写权限。
|
|
79
|
+
|
|
72
80
|
## 平台兼容入口索引
|
|
73
81
|
|
|
74
82
|
下列旧 HTTP 地址仍由受控兼容链路识别,不能据此绕过 DiyToken、租户或权限校验:`/api/FormEngine/GetSysConfig`、`/api/Os/GetDateTimeNow`、`/api/SysLog/AddSysLog`、`/api/SysUser/`。畅捷通 V2 回调在接口引擎中编排,可信后端只提供当前租户绑定的 `V8.Method.DecodeChanjetCallbackV2` 原子。
|
|
@@ -74,7 +74,7 @@ MCP 写入前会回读当前租户的用户、角色、部门和岗位 Id;回
|
|
|
74
74
|
生成工作流 V8 代码时,代码内容本身(文件头、普通注释、`console.log`、返回 `Msg` 等)不要包含 `Microi`、`吾码` 等平台品牌文字,除非业务数据或字段值本身必须如此。生成代码要有可维护注释:每个 `function` 前写清用途、关键参数和返回值;路线选择、审批人计算、状态回写、撤回/驳回处理、跨表联动等复杂代码段前写短注释说明业务原因;避免“给变量赋值”这类无信息量注释。若工作流存储表支持 `Version`/`ChangeHistory`,历史说明也必须最新在前并保留旧记录。
|
|
75
75
|
|
|
76
76
|
<!-- /microi-progressive:chunk -->
|
|
77
|
-
<!-- microi-progressive:chunk id=v8-workflow-001 sha256=
|
|
77
|
+
<!-- microi-progressive:chunk id=v8-workflow-001 sha256=935b29e9f3afde02aa78a77468b48afd204facb3b1dafaf9d23dc3bd69832717 -->
|
|
78
78
|
## 工作流物理表
|
|
79
79
|
|
|
80
80
|
| 表名 | 说明 |
|
|
@@ -94,6 +94,7 @@ MCP 写入前会回读当前租户的用户、角色、部门和岗位 Id;回
|
|
|
94
94
|
- 当前 `CancelFlow(WFParam)` 使用独立事务,没有 `StartWork/SendWork` 的共享 `DbTrans` 重载。应用不得在持有实例、工作或业务行锁的接口事务内调用取消,也不能假设给它多传一个参数便会共享事务。微服务可顺序执行“服务端核验并返回真实待办坐标 → 原生取消 → 业务终态复核”,每个请求完成后释放其事务;网络结果未知时先复核终态,不能盲目重发取消或提前恢复业务状态。
|
|
95
95
|
- 业务接口与原生节点共同读取配置、公共引用和业务行时,先画出宿主与脚本合并的锁图。原生审批进入节点前可能已持有流程实例锁;既存流程的业务复核应先通过当前主库有界只读发现真实实例,再在同一共享事务锁定该实例,随后获取固定配置/引用锁及业务行锁,重读验证归属未变。待办发现扫描只读不能提前锁工作行后再等流程;公共引用围栏只协调锁序,不能读取配置值来继承授权。必须逐入口审查包括定义、身份与配置的相反锁序,不以一条 SQL 或单次模拟成功宣称全系统无死锁。
|
|
96
96
|
- 已由可信原生历史证明取消或驳回的终态恢复只校验原提交归属、当前授权和可恢复状态,不应要求审批期间未发生正常库存、成本或其他业务余额变化;此恢复不产生过账副作用。批准与过账仍必须严格比较冻结快照、当前期间及业务版本,并覆盖撤权、并发和响应未知时使用原请求键恢复。
|
|
97
|
+
- 真实原生多接收人流程中的 `OtherDone` 只表示同阶段并列待办被 `CloseOtherWork` 关闭,不是该接收人已经审批。仅在同实体/实例/定义/审批节点/来源节点与唯一真实 `Agree` + `Done` 工作精确绑定,接收人不同于实际办理人,且没有该并列工作办理历史时,才能作为终态旁证;不能把它计作独立审核人。开始提交、实际人工审批仍必须 `Done`,未知节点、待办、撤回、取消、重复历史或模糊绑定失败关闭。覆盖真实五工作(3 `Done`、2 `OtherDone`)原生来源及新稿/原键恢复,不能靠把状态统一映射为 `Done` 通过。
|
|
97
98
|
- 验收至少覆盖真实取消时不传 `FormData`、伪造取消载荷、退回后直接重提被拒绝、取消后新实例重提、自动结束继承 `Agree`,以及普通角色不能修改取证用的流程历史。模拟正确 JSON 不替代原生 HTTP 验收。
|
|
98
99
|
|
|
99
100
|
直接 SQL 查询常用场景:
|
|
@@ -87,14 +87,14 @@ Microi 平台后端功能必须默认按多节点部署设计:多个 API/Worke
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
<!-- /microi-progressive:chunk -->
|
|
90
|
-
<!-- microi-progressive:chunk id=workspace-conventions-003 sha256=
|
|
90
|
+
<!-- microi-progressive:chunk id=workspace-conventions-003 sha256=66922955adb5ff6198efefd6d4d8d8f6525ef7559663ea034e86e1e45f89eb9f -->
|
|
91
91
|
## 本地资源与 OOM 保护规范(强制)
|
|
92
92
|
|
|
93
93
|
AI 在用户本机启动 Node.js、Vite、Webpack、dotnet build、Java、Docker build、浏览器自动化、压力测试或其他可能长时间占用 CPU/内存的进程前,必须先评估资源,不得为了“让构建跑过”无限抬高堆内存或 Worker 数。
|
|
94
94
|
|
|
95
95
|
- 启动前检查物理内存总量、当前占用率、可用内存,并检查是否已有同类 dev server/构建进程。已有可复用服务时禁止重复启动。
|
|
96
|
-
-
|
|
97
|
-
-
|
|
96
|
+
- API、PC 框架、官网和 Agent 发布按各自范围独立排队,可以并行执行;同一范围的发布互斥,不得用一个全局发布窗口阻塞无关产品。并行任务必须隔离输出、日志、测试目录和临时服务,显式限制 Worker/并发数;仅在实际共享输出、服务或资源预算不足时串行。
|
|
97
|
+
- 启动重任务前按“当前并行阶段的进程树预算总和 + 系统安全余量”判断:阶段预算优先采用实测峰值;尚无实测时,用已限制的堆/容器上限加明确的原生进程、Worker 与缓冲开销。系统安全余量取 `max(1.5 GB, 物理内存的 5%)`,不得再按固定 20% 将大内存机器的启动门槛线性放大。顺序执行的阶段分别计算,禁止把不会并发的阶段峰值相加。机器总内存占用达到 95% 时,立即暂停或终止 AI 启动的重任务及其子进程,不得等待 OOM。
|
|
98
98
|
- 禁止将 `--max-old-space-size`、JVM heap、Docker memory 或类似上限设为接近物理内存总量。除非用户明确授权独占构建窗口,单个 AI 启动的进程树不得持续占用超过物理内存的 25%。
|
|
99
99
|
- 后台/长任务必须记录根 PID、子进程、启动时间和独立日志,每 15-30 秒监测一次进程树内存与全机可用内存。任务失败、中断或达阈值时必须停止整个子进程树,不得遗留孤儿 Node/dotnet/Java 进程。
|
|
100
100
|
- 全量构建无法在上述阈值内完成时,先停止并改用定向 lint、类型检查、按模块构建或按测试文件验证。如仍必须进行全量验收,应明确报告资源瓶颈,交由 CI/专用构建机或经用户明确同意的独占时段执行,禁止在用户正在使用的 VS Code 会话里硬跑。
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> 按需读取;本文件由 SKILL.md 的原章节无损拆分。
|
|
4
4
|
|
|
5
|
-
<!-- microi-progressive:chunk id=workspace-conventions-024 sha256=
|
|
5
|
+
<!-- microi-progressive:chunk id=workspace-conventions-024 sha256=92c453b5fafa36d68098b3da5817d0de260a3cf454d8cae63f71a3f65e57bbdc -->
|
|
6
6
|
## Microi.net.Api 本地启动约定
|
|
7
7
|
|
|
8
8
|
默认本地后端项目是 `Microi.Server/Microi.net.Api/Microi.net.Api.csproj`。AI 需要启动后端、验证接口、跑 Playwright、回读接口引擎或排查前后端联调问题时,优先使用下面的 PowerShell 命令:
|
|
@@ -17,19 +17,20 @@ Pop-Location
|
|
|
17
17
|
|
|
18
18
|
普通本地启动默认不要额外设置 `ASPNETCORE_ENVIRONMENT` 或 `DOTNET_ENVIRONMENT`;如果这些变量已由 `launchSettings.json`、`launch.json`、终端环境或测试脚本显式设置,`.microi-local` 不会覆盖它们。实际监听地址必须读取 `Microi.Server/Microi.net.Api/Properties/launchSettings.json` 的 `Microi.net.Api` profile;当前标准工作区是后端 `61501`、前端 `61500`,不能继续硬编码历史 `7266/1988`。
|
|
19
19
|
|
|
20
|
-
**本地后端自动重启要求(强制)**:本地联调需要启动或重启 `Microi.net.Api`
|
|
20
|
+
**本地后端自动重启要求(强制)**:本地联调需要启动或重启 `Microi.net.Api` 时,先执行 `node Microi.Server/tools/release-lock.mjs assert api <工作区根>`;API 锁存在时禁止启动或重启后端。PC、官网和 Agent 发布不阻塞 API 服务。无发布时先回读标准端口和 `/api/Diagnostics/liveness`,健康服务默认复用;只有本任务修改了需重载的后端代码、服务不健康或用户明确要求重启时,才可精确停止当前工作区的后端进程,然后在 `Microi.Server/Microi.net.Api` 目录执行 `dotnet run --launch-profile Microi.net.Api`。优先使用用户能在 VS Code 中看到和停止的终端(包含 VS Code 集成终端、VS Code 任务终端、用户明确允许的 VS Code 可追踪隐藏终端);如果当前工具没有 VS Code 终端能力,允许使用本机可见的 `cmd`/PowerShell 窗口启动,禁止使用脱离用户可见窗口的后台服务或守护进程。不要误杀数据库、Redis、Node 前端或其它业务进程。
|
|
21
21
|
|
|
22
22
|
<!-- /microi-progressive:chunk -->
|
|
23
|
-
<!-- microi-progressive:chunk id=workspace-conventions-025 sha256=
|
|
23
|
+
<!-- microi-progressive:chunk id=workspace-conventions-025 sha256=4cf40c4ca771f7e04b80279646323a816378b98669f562ff8f4c647d5bf837ca -->
|
|
24
24
|
## 多 AI 对话共享本地服务与发布互斥(强制)
|
|
25
25
|
|
|
26
|
-
同一工作区的 4、5 个 AI 对话共用同一份源码和固定端口时,`61500/61501` 是工作区级单例共享服务,不属于某个对话。端口相同意味着无法让每个对话拥有一套独立进程;正确模型是“复用健康服务 + 需要重载时串行重启 +
|
|
26
|
+
同一工作区的 4、5 个 AI 对话共用同一份源码和固定端口时,`61500/61501` 是工作区级单例共享服务,不属于某个对话。端口相同意味着无法让每个对话拥有一套独立进程;正确模型是“复用健康服务 + 需要重载时串行重启 + 同范围发布时独占”,不能让每个对话都无条件先杀再启动。
|
|
27
27
|
|
|
28
28
|
- 启动前先检查端口、健康接口、PID、命令行和工作区路径。健康且代码无需重载时直接复用;不得仅为声明“本对话拥有服务”而重启。
|
|
29
29
|
- 长期本地后端必须通过项目目录里的 `dotnet run --launch-profile Microi.net.Api` 使用开发输出。禁止把 `bin/Release/net10.0` 或 `bin/Release/publish` 的 `dotnet Microi.net.Api.dll` 当长期 E2E 服务;运行中的 Release DLL 会让后续 `dotnet build` 报 `MSB3021/MSB3027` 文件锁。
|
|
30
|
-
-
|
|
30
|
+
- 一键编译发布按所选产品创建 `.tmp/microi-process-state/api-release.lock`、`pc-release.lock`、`website-release.lock` 或 `agent-release.lock`。合并发布按固定顺序取得所需锁;任何一项占用时撤回本次已取得的锁。Windows 的 `PrepareRelease -ReleaseScope api|pc|all` 仅清理所选范围:API 处理本工作区后端与 Release DLL,PC 处理本工作区 Vite;官网不停止二者。身份不匹配时停止,不得按进程名全杀。
|
|
31
31
|
- Vite 子进程可能由相对 `node_modules/vite/bin/vite.js` 启动,父 npm/终端退出后命令行不再包含工作区绝对路径。Windows 进程管理器应先匹配命令行绝对路径;无法匹配时只读回读进程 CWD,只有 CWD 精确等于当前工作区 `Microi.Client` 且入口确为 Vite 才可结束。CWD 无法读取、属于其它目录或仅仅“父进程不存在”时必须失败关闭。
|
|
32
|
-
-
|
|
32
|
+
- API、PC、官网和 Agent 可以同时发布,同类发布互斥。旧 `platform-release.lock` 与 `release.lock` 仅在真实 PID 命令入口及共享状态目录证明属于 API 热修复或 Agent 时缩小阻塞范围;未知归属继续保守阻塞,禁止删除活跃旧锁。Full 仍是 PC/API 发布硬门禁;其 .NET 输出放入本次结果目录的 `.net-artifacts`,并行 Full 使用独立结果目录、测试服务和隔离租户。共享版本号或跨产品源码必须先准备冻结,再启动并行发布,禁止测试期间改写候选。 macOS/Linux 的 Full apphost 仅允许当前工作区 `.tmp/microi-release-gate/日期-时间-PID/.net-artifacts/bin/Microi.net.Api/debug|release/Microi.net.Api` 的规范路径,且 CWD 必须精确等于 API 项目;任意外部输出、其它工作区或路径归一化差异继续失败关闭。
|
|
33
|
+
- 启动或重启 API 前检查 `assert api`,PC 前检查 `assert pc`;只有对应范围发布时等待或退出,官网/Agent 不阻塞共享服务。需要同时启动二者时分别检查两项;正常结束或中断由原进程和唯一令牌释放自身锁。
|
|
33
34
|
- Edge/Chrome 主浏览器、VS Code 持有的 Playwright Test Server、语言服务和 MCP Node 进程不属于发布文件锁清理范围。浏览器自动化必须关闭本用例创建的 context/browser;不得通过 `taskkill /IM chrome.exe|msedge.exe|node.exe|dotnet.exe` 清空整机进程。
|
|
34
35
|
- 人工盘点使用:`powershell -NoProfile -ExecutionPolicy Bypass -File Microi.Server/tools/Microi.LocalProcessManager.ps1 -Action Status`。需要单独停止当前工作区服务时使用 `-Action StopBackend` 或 `-Action StopFrontend`,不再让用户根据任务管理器猜进程。
|
|
35
36
|
|