@godv61/dsh-task-engine 0.8.0 → 0.10.0

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 CHANGED
@@ -18,7 +18,8 @@ cordis.patch.yml bundle 声明 + host 组合 patch(一行,只挂 host
18
18
  defaults/eng.json 内置默认工作流(可被项目 .dsh/eng.json 覆盖)
19
19
  hooks/commit-msg git 提交门禁钩子(install_hook 装进 .git/hooks/)
20
20
  src/engine.ts 纯函数状态机 + 配置校验(无 harness 依赖,双端复用)
21
- src/index.ts host 入口:只挂 task-engine Remote 控制器(配置面板用,非模型可见)
21
+ src/index.ts host 入口:挂 task-engine Remote 控制器 + 首次启动自动 seed「工程化开发引擎」预设
22
+ src/seed-preset.ts 对齐当前 standard 复制出 eng 预设(换人设 + 加 agent 行,幂等)
22
23
  src/agent.ts agent 入口(./agent 出品):在调用它的预设 scope 里注册 dev_task + 内置技能
23
24
  src/dev-task.ts dev_task 工具定义 + 全部文件系统辅助(模型门禁,随 agent 入口激活)
24
25
  src/shipped-skills.ts 内置技能扫描 + 注册(随 agent 入口激活)
@@ -26,7 +27,8 @@ src/controller.ts Host 端 Remote 控制器:网页读写 .dsh/eng.json +
26
27
  src/client/ 浏览器半:全屏工作台(流程配置 / 技能 skill / 规则 rule 三个标签页)
27
28
  skills/ 内置技能库(需求分析/方案设计/实现/验证/审核/提交/交付编排)
28
29
  rules/ 内置规则库(编码规范/提交规范/安全红线)
29
- preset/agent.cordis.yml 预设接入片段(persona 行 + agent 行,复制进你的预设)
30
+ preset/agent.cordis.yml 预设接入片段(persona 行 + agent 行,供自定义预设照抄)
31
+ preset/enable.mjs 手动重建 eng 预设的命令行兜底(bin: dsh-task-engine-enable)
30
32
  preset/preset.yml 预设元数据
31
33
  preset/persona.md 预设 persona 文案
32
34
  ```
@@ -52,23 +54,26 @@ dsh plugin --profile <name> add github:<你的org>/dsh-task-engine
52
54
  dsh plugin --profile <name> add .
53
55
  ```
54
56
 
55
- ## 启用(按预设激活)
57
+ ## 启用(点选即用)
56
58
 
57
- 装 bundle 只挂 host 半(配置工作台),**不**给任何会话挂 `dev_task` 或技能——流程惰性待命。要在哪个预设激活,就在那个预设的 `agent.cordis.yml` 加一行:
59
+ 装完 bundle、重启 web,预设列表里会**自动多出一个「工程化开发引擎」**——host 半在首次启动时把它对齐当前 `standard` 生成(换好工程人设 + 加好 agent 行),落在 `~/.dsh/.agent-presets/eng/`。
58
60
 
59
- 1. 复制一个预设(GUI 预设管理里复制 `standard` → `eng`,落在 `~/.dsh/.agent-presets/eng/`)。
60
- 2. 打开 `eng` 的 `agent.cordis.yml`,做两处改动(可直接照抄 `preset/agent.cordis.yml` 片段):
61
- - `persona` 行换成工程化人设(`preset/persona.md` 的内容);
62
- - 追加一行 agent 入口:
63
- ```yaml
64
- - id: task-engine-agent
65
- name: '@godv61/dsh-task-engine/agent'
66
- ```
67
- 3. 新会话选 `eng`:挂上 `dev_task` 工具 + 内置技能 + 工程化人设,模型走完整流程。
68
- - 换回 `standard` / `minimal` / 其它**没加那行**的预设:没有 `dev_task`、没有内置技能、没有工程化人设——流程完全不介入。
69
- - 侧边栏「工程流程」全屏工作台仍在(host 半),随时供人查看/配置 `.dsh/eng.json` 和 skill/rule,与激活与否无关。
61
+ - **用**:新建会话(或设置 → agent 预设)选「工程化开发引擎」,这个会话就挂上 `dev_task` + 内置技能 + 工程人设,按流程走。
62
+ - **不用**:选 `standard` / `minimal` / 其它预设,就没有 `dev_task`、没有内置技能、没有工程人设,流程完全不介入。
63
+ - 侧边栏「工程流程」工作台不受影响,随时供人配置 `.dsh/eng.json` 和 skill/rule。
70
64
 
71
- 这一层对称由 DSH 的工具/技能 scope 机制保证:host 半从不把 `dev_task` 注册进全局工具层,agent 半只在命名它的预设 scope 里注册——不是一个“开关”,而是两个不同层的注册位置。
65
+ 这一层对称由 DSH 的工具/技能 scope 机制保证:host 半从不把 `dev_task` 注册进全局工具层,agent 半(`@godv61/dsh-task-engine/agent` 行)只在命名它的预设里注册——所以切换预设本身就是开关。
66
+
67
+ ### 兜底 / 自定义
68
+
69
+ 自动生成只在 `eng` 不存在时发生,绝不覆盖你手改过的预设;删掉 `eng` 后下次启动会重新生成。想**手动**造一个(不同名字、或改人设)才需要:复制 `standard` → 在 `agent.cordis.yml` 末尾加一行:
70
+
71
+ ```yaml
72
+ - id: task-engine-agent
73
+ name: '@godv61/dsh-task-engine/agent'
74
+ ```
75
+
76
+ 也可重跑 `dsh-task-engine-enable` 强制重建默认的 `eng`。
72
77
 
73
78
  ## 项目配置(让流程贴合你的项目)
74
79
 
@@ -133,4 +138,7 @@ dsh plugin --profile <name> add .
133
138
  - **skill/rule 挂载与渐进披露(0.6.0)**:`WorkflowConfig` 新增 `stage_bindings`(每阶段挂 skills/rules,可选字段),`dev_task` 的 `status`/`advance` 按当前阶段披露挂载的 skill 名 + rule 正文;内置 6 技能 + 3 规则库;Host 控制器新增 `listSkills`/`listRules`/`writeSkill`/`writeRule`;设置页新增「节点挂载」和「新建 skill / rule」两块,同时补上 `dev_task` 缺失的 `items` 操作(更新实施项状态)。引擎层 `stage_bindings` 校验(未知阶段/空名)与合并已单测通过。
134
139
  - **配置页精简 + 自建 skill 可观测(0.6.1)**:设置页的流转/产物/提交规则/新建默认折叠,「节点挂载」从六阶段全平铺改成「选一个阶段再看它挂了什么」;新建成功提示带回显路径(`.dsh/skills/<name>/SKILL.md` 或 `$DSH_HOME/…`),挂载清单给非内置的 skill/rule 标「(项目)/(用户)」来源。修复 `listSkills` 依赖 host skill registry 导致项目 `.dsh/skills` 自建技能不显示的问题——改为与 `listRules` 一致,直接扫「内置 + 项目 + 用户」三层目录。浏览器 e2e 全绿。
135
140
  - **全屏工作台 + 在线编辑(0.7.0)**:配置页从设置弹窗迁出,改为侧边栏 `sidebar.footer.action`「工程流程」按钮,点开 `shell.overlay` 全屏工作台(触发按钮与覆盖层共享一个 store 控制开关)。工作台分「流程配置 / 技能 skill / 规则 rule」三个标签页;技能和规则列表支持在线编辑——`readSkill`/`readRule` 读回正文、改 description/whenToUse/正文、`writeSkill`/`writeRule` 写回;内置项只读,项目/用户项可原地编辑,新建同时支持项目级/用户级。旧的 `settings.section` 入口移除,统一走侧边栏按钮。浏览器 e2e 全绿。
136
- - **按预设激活(0.8.0)**:`dev_task` 工具与内置技能从 host 全局层拆到 agent 层。host 入口只挂 `task-engine` Remote 控制器 + 工作台 UI(`src/index.ts`);新增 `src/agent.ts`(`./agent` 出品)、`src/dev-task.ts`、`src/shipped-skills.ts`,由预设的 `agent.cordis.yml` 命名后,在**该预设的 scope** 里注册工具与技能。实机 boot 验证:`standard` 会话工具目录不含 `dev_task`(26 个工具),加了 `@godv61/dsh-task-engine/agent` 行的 `eng` 会话含 `dev_task`(27 个工具)且描述正确,换回 `standard` 再次不含——切换预设即切换流程激活状态。
141
+ - **按预设激活(0.8.0)**:`dev_task` 工具与内置技能从 host 全局层拆到 agent 层。host 入口只挂 `task-engine` Remote 控制器 + 工作台 UI(`src/index.ts`);新增 `src/agent.ts`(`./agent` 出品)、`src/dev-task.ts`、`src/shipped-skills.ts`,由预设的 `agent.cordis.yml` 命名后,在**该预设的 scope** 里注册工具与技能。实机 boot 验证:`standard` 会话工具目录不含 `dev_task`(26 个工具),加了 `@godv61/dsh-task-engine/agent` 行的 `eng` 会话含 `dev_task`(27 个工具)且描述正确,换回 `standard` 再次不含——切换预设即切换流程激活状态。
142
+ - **一键激活(0.8.1)**:新增 `preset/enable.mjs`(bin: `dsh-task-engine-enable`),一条命令自动复制 `standard` → `eng`、把 persona 换成工程人设、追加 agent 行、写 `preset.yml`。persona 从「必须换」降级为「可选」——`eng-delivery` 技能自带 `whenToUse`,即使不加人设,模型遇到开发请求也自己加载技能走 `dev_task`;最简激活只剩「复制预设 + 追加一行 agent 行」。实机验证:脚本生成的 `eng` 预设挂载后 `dev_task` 可见、persona 以工程人设(含「铁律」)渲染、`standard` 仍无 `dev_task`。
143
+ - **点选即用(0.9.0)**:host 入口新增 `src/seed-preset.ts`——首次启动自动把当前 `standard` 复制成 `eng` 预设(换工程人设 + 追加 agent 行,幂等、不覆盖手改)。装 bundle 重启后预设列表直接出现「工程化开发引擎」,点选即激活、切走即不激活,零复制/零编辑/零脚本。实机 boot 验证:boot 后 `.agent-presets/eng` 自动生成(agent 行 + 工程人设齐全)、roster 列出 `eng`(user)、`eng` 会话有 `dev_task` 且 persona 含「铁律」、`standard` 会话无 `dev_task`。
144
+ - **工作台可用性(0.9.1)**:修复「新建 skill / 新建 rule」按钮点击不弹出表单(`formOpen` 只认编辑态,新建态缺少显式标志);给六个守卫补 hover 说明、把「产物齐全」改名「产物字段已填全」并讲清「产物 = 阶段要写清楚的记录、字段 = 这份记录里必填的空」,「节点挂载」改名「阶段技能 / 规则」。
package/lib/client.js CHANGED
@@ -4816,12 +4816,12 @@ var cardV = {
4816
4816
  padding: "10px 12px"
4817
4817
  };
4818
4818
  var GUARD_OPTIONS = [
4819
- { value: "requirement_confirmation", label: "\u9700\u6C42\u786E\u8BA4" },
4820
- { value: "solution_confirmation", label: "\u65B9\u6848\u786E\u8BA4" },
4821
- { value: "todos_done", label: "\u5F85\u529E\u5B8C\u6210" },
4822
- { value: "verified", label: "\u5DF2\u9A8C\u8BC1" },
4823
- { value: "review_passed", label: "\u8BC4\u5BA1\u901A\u8FC7" },
4824
- { value: "artifacts_present", label: "\u4EA7\u7269\u9F50\u5168" }
4819
+ { value: "requirement_confirmation", label: "\u9700\u6C42\u786E\u8BA4", hint: "\u9700\u6C42\u5DF2\u7ECF\u4EBA\u786E\u8BA4\u8FC7" },
4820
+ { value: "solution_confirmation", label: "\u65B9\u6848\u786E\u8BA4", hint: "\u65B9\u6848\u5DF2\u7ECF\u4EBA\u786E\u8BA4\u8FC7" },
4821
+ { value: "todos_done", label: "\u5F85\u529E\u5B8C\u6210", hint: "\u4EFB\u52A1\u6E05\u5355\u91CC\u7684\u6BCF\u4E00\u9879\u90FD\u5DF2\u52FE\u9009\u5B8C\u6210" },
4822
+ { value: "verified", label: "\u5DF2\u9A8C\u8BC1", hint: "\u5DF2\u901A\u8FC7\u9A8C\u8BC1\uFF08\u9AD8\u98CE\u9669\u4EFB\u52A1\u8FD8\u5FC5\u987B\u9644\u9A8C\u8BC1\u8BC1\u636E\uFF09" },
4823
+ { value: "review_passed", label: "\u8BC4\u5BA1\u901A\u8FC7", hint: "\u4EE3\u7801\u5BA1\u6838\u7ED3\u8BBA\u4E3A\u901A\u8FC7" },
4824
+ { value: "artifacts_present", label: "\u4EA7\u7269\u5B57\u6BB5\u5DF2\u586B\u5168", hint: "\u8BE5\u9636\u6BB5\u58F0\u660E\u7684\u6BCF\u4E00\u4E2A\u4EA7\u7269\u5B57\u6BB5\u90FD\u5DF2\u586B\u4E0A\u5185\u5BB9" }
4825
4825
  ];
4826
4826
  var POLICY_OPTIONS = [
4827
4827
  { value: "task", label: "task", hint: "\u68C0\u67E5\u70B9\u4E00\u6B21\u63D0\u4EA4" },
@@ -4916,9 +4916,9 @@ function TaskEngineSection(props) {
4916
4916
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.flowCard, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FlowDiagram, { config, onAddTransition: addTransition, onRemoveTransition: removeTransition }) }),
4917
4917
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconSettingsOutline16, { size: 16 }), title: "\u9636\u6BB5", hint: "\u6D41\u7A0B\u7531\u8FD9\u4E9B\u9636\u6BB5\u6309\u987A\u5E8F\u7EC4\u6210\u3002\u70B9\u4E00\u4E2A\u6807\u7B7E\u53EF\u5220\u9664\u5B83\uFF08\u8D77\u59CB\u9636\u6BB5\u9664\u5916\uFF09\uFF1B\u7528\u4E2D\u6587\u540D\u66F4\u6613\u61C2\uFF0C\u4F8B\u5982\u300C\u9700\u6C42\u8BC4\u5BA1\u300D\u300C\u5F00\u53D1\u300D\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StageEditor, { config, setConfig }) }),
4918
4918
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u6D41\u8F6C\uFF08\u9636\u6BB5 \u2192 \u9636\u6BB5\uFF0C\u53EF\u5E26\u5B88\u536B\uFF09", defaultOpen: false, hint: "\u6BCF\u6761\u6D41\u8F6C = \u4ECE\u300C\u4E0A\u4E00\u6B65\u300D\u5230\u300C\u4E0B\u4E00\u6B65\u300D\u5141\u8BB8\u8D70\u7684\u8DEF\uFF1B\u53EF\u9644\u52A0\u5B88\u536B\uFF0C\u6EE1\u8DB3\u5B88\u536B\u624D\u653E\u884C\u3002\u4E5F\u53EF\u5728\u6D41\u7A0B\u56FE\u91CC\u76F4\u63A5\u8FDE\u7EBF/\u70B9\u7BAD\u5934\u5220\u9664\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TransitionEditor, { config, setConfig }) }),
4919
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }), title: "\u4EA7\u7269\uFF08\u6BCF\u4E2A\u9636\u6BB5\u8981\u586B\u7684\u5B57\u6BB5\uFF09", defaultOpen: false, hint: "\u7ED9\u67D0\u9636\u6BB5\u58F0\u660E\u8981\u4EA4\u7684\u4EA7\u7269\u548C\u5FC5\u586B\u5B57\u6BB5\uFF1B\u914D\u5408\u6D41\u8F6C\u91CC\u7684\u300C\u4EA7\u7269\u9F50\u5168\u300D\u5B88\u536B\uFF0C\u5B57\u6BB5\u6CA1\u586B\u5168\u5C31\u8FC7\u4E0D\u53BB\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArtifactEditor, { config, setConfig }) }),
4919
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }), title: "\u4EA7\u7269\uFF08\u6BCF\u4E2A\u9636\u6BB5\u8981\u5199\u6E05\u695A\u7684\u8BB0\u5F55\uFF09", defaultOpen: false, hint: "\u4EA7\u7269 = \u67D0\u9636\u6BB5\u5FC5\u987B\u4EA4\u4ED8\u7684\u4E00\u4EFD\u300C\u586B\u5199\u8BB0\u5F55\u300D\uFF1B\u5B57\u6BB5 = \u8FD9\u4EFD\u8BB0\u5F55\u91CC\u5927\u6A21\u578B\u5FC5\u987B\u586B\u4E0A\u7684\u7A7A\u3002\u4F8B\u5982\u300C\u9700\u6C42\u8BC4\u5BA1\u300D\u9636\u6BB5\u7684\u4EA7\u7269\u300C\u9700\u6C42\u8BF4\u660E\u300D\u8981\u586B scope\uFF08\u8303\u56F4\uFF09\u3001acceptance_criteria\uFF08\u9A8C\u6536\u6807\u51C6\uFF09\u4E24\u4E2A\u5B57\u6BB5\uFF1B\u518D\u7ED9\u300C\u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1\u300D\u8FD9\u6761\u6D41\u8F6C\u6302\u4E0A\u300C\u4EA7\u7269\u5B57\u6BB5\u5DF2\u586B\u5168\u300D\u5B88\u536B\uFF0C\u5B57\u6BB5\u6CA1\u586B\u5168\u5C31\u8FDB\u4E0D\u4E86\u4E0B\u4E00\u9636\u6BB5\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArtifactEditor, { config, setConfig }) }),
4920
4920
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconEditOutline16, { size: 16 }), title: "\u63D0\u4EA4\u89C4\u5219", defaultOpen: false, hint: "\u63D0\u4EA4\u7B56\u7565\u3001\u6D88\u606F\u683C\u5F0F\u3001\u63D0\u4EA4\u68C0\u67E5\u70B9\u3001\u6587\u4EF6\u8303\u56F4\uFF0C\u4EE5\u53CA\u9AD8\u98CE\u9669\u662F\u5426\u5FC5\u987B\u9644\u9A8C\u8BC1\u8BC1\u636E\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitEditor, { config, setConfig }) }),
4921
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u8282\u70B9\u6302\u8F7D\uFF08skill / rule\uFF09", hint: "\u7ED9\u6BCF\u4E2A\u9636\u6BB5\u6302\u300C\u8FD9\u4E2A\u9636\u6BB5\u7528\u4EC0\u4E48 skill\u300D\u548C\u300C\u5B88\u54EA\u6761 rule\u300D\u3002\u5927\u6A21\u578B\u8D70\u5230\u8BE5\u9636\u6BB5\u65F6\uFF0Cdev_task \u53EA\u62AB\u9732\u8FD9\u9636\u6BB5\u6302\u8F7D\u7684\u5185\u5BB9\uFF1B\u8981\u65B0\u5EFA\u6216\u6539\u6B63\u6587\uFF0C\u8BF7\u5207\u5230\u4E0A\u65B9\u7684\u300C\u6280\u80FD / \u89C4\u5219\u300D\u6807\u7B7E\u9875\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BindingEditor, { config, setConfig, skills, rules }) }),
4921
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u9636\u6BB5\u6280\u80FD / \u89C4\u5219", hint: "\u9009\u4E00\u4E2A\u9636\u6BB5\uFF0C\u52FE\u9009\u5B83\u300C\u7528\u4EC0\u4E48 skill\uFF08\u6280\u80FD\uFF09\u300D\u548C\u300C\u5B88\u54EA\u6761 rule\uFF08\u89C4\u5219\uFF09\u300D\u3002\u5927\u6A21\u578B\u8D70\u5230\u8BE5\u9636\u6BB5\u65F6\uFF0C\u53EA\u4F1A\u770B\u5230\u7ED9\u5B83\u6302\u8F7D\u7684\u8FD9\u51E0\u6761\u6280\u80FD\u4E0E\u89C4\u5219\uFF1B\u8981\u65B0\u5EFA\u6216\u6539\u6B63\u6587\uFF0C\u5207\u5230\u4E0A\u65B9\u7684\u300C\u6280\u80FD\u300D/\u300C\u89C4\u5219\u300D\u6807\u7B7E\u9875\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BindingEditor, { config, setConfig, skills, rules }) }),
4922
4922
  problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
4923
4923
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
4924
4924
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
@@ -5108,7 +5108,7 @@ function TransitionEditor({ config, setConfig }) {
5108
5108
  onClick: () => {
5109
5109
  toggleGuard(i, g.value);
5110
5110
  },
5111
- title: `\u5B88\u536B ${g.value}`,
5111
+ title: g.hint,
5112
5112
  children: g.label
5113
5113
  },
5114
5114
  g.value
@@ -5144,10 +5144,10 @@ function ArtifactEditor({ config, setConfig }) {
5144
5144
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { style: control, value: a.stage, onChange: (ev) => {
5145
5145
  setArtifact(i, { stage: ev.target.value });
5146
5146
  }, children: config.stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: s, children: s }, s)) }),
5147
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: { ...control, flex: "1 1 120px" }, placeholder: "id", value: a.id, onChange: (ev) => {
5147
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: { ...control, flex: "1 1 110px" }, placeholder: "\u82F1\u6587 id\uFF08\u5982 requirement\uFF09", value: a.id, onChange: (ev) => {
5148
5148
  setArtifact(i, { id: ev.target.value });
5149
5149
  } }),
5150
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: { ...control, flex: "1 1 140px" }, placeholder: "\u540D\u79F0", value: a.name, onChange: (ev) => {
5150
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: { ...control, flex: "1 1 130px" }, placeholder: "\u540D\u79F0\uFF08\u7ED9\u4EBA\u770B\uFF0C\u5982 \u9700\u6C42\u8BF4\u660E\uFF09", value: a.name, onChange: (ev) => {
5151
5151
  setArtifact(i, { name: ev.target.value });
5152
5152
  } }),
5153
5153
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "ghost", size: "sm", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCloseOutline16, { size: 14 }), onClick: () => {
@@ -5158,7 +5158,7 @@ function ArtifactEditor({ config, setConfig }) {
5158
5158
  "input",
5159
5159
  {
5160
5160
  style: control,
5161
- placeholder: "\u5B57\u6BB5\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u5982 scope, acceptance_criteria\uFF09",
5161
+ placeholder: "\u8981\u586B\u7684\u5B57\u6BB5\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u5982 scope, acceptance_criteria\uFF09",
5162
5162
  value: a.fields.join(", "),
5163
5163
  onChange: (ev) => {
5164
5164
  setArtifact(i, { fields: splitList(ev.target.value) });
@@ -5284,7 +5284,7 @@ function BindingEditor({ config, setConfig, skills, rules }) {
5284
5284
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
5285
5285
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.bindingStage, children: [
5286
5286
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "skill\uFF08\u8FD9\u4E2A\u9636\u6BB5\u505A\u4EC0\u4E48\uFF09" }),
5287
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: skills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 skill\uFF0C\u53EF\u5728\u300C\u65B0\u5EFA skill / rule\u300D\u91CC\u5EFA" }) : skills.map((sk) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundSkills.includes(sk.name), onClick: () => {
5287
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: skills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 skill \u2014\u2014 \u5207\u5230\u4E0A\u65B9\u300C\u6280\u80FD\u300D\u6807\u7B7E\u9875\u65B0\u5EFA" }) : skills.map((sk) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundSkills.includes(sk.name), onClick: () => {
5288
5288
  toggleSkill(sk.name);
5289
5289
  }, title: `${sk.description}\uFF08${sourceLabel(sk.source)}\uFF09`, children: [
5290
5290
  sk.name,
@@ -5297,7 +5297,7 @@ function BindingEditor({ config, setConfig, skills, rules }) {
5297
5297
  ] }),
5298
5298
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.bindingStage, children: [
5299
5299
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "rule\uFF08\u8FD9\u4E2A\u9636\u6BB5\u5B88\u4EC0\u4E48\uFF09" }),
5300
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 rule\uFF0C\u53EF\u5728\u300C\u65B0\u5EFA skill / rule\u300D\u91CC\u5EFA" }) : rules.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundRules.includes(rule.name), onClick: () => {
5300
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 rule \u2014\u2014 \u5207\u5230\u4E0A\u65B9\u300C\u89C4\u5219\u300D\u6807\u7B7E\u9875\u65B0\u5EFA" }) : rules.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundRules.includes(rule.name), onClick: () => {
5301
5301
  toggleRule(rule.name);
5302
5302
  }, title: `\u6765\u6E90\uFF1A${sourceLabel(rule.source)}`, children: [
5303
5303
  rule.name,
@@ -5356,6 +5356,7 @@ function SkillManager({ workspace, remote }) {
5356
5356
  const [skills, setSkills] = (0, import_react3.useState)([]);
5357
5357
  const [level, setLevel] = (0, import_react3.useState)("project");
5358
5358
  const [editing, setEditing] = (0, import_react3.useState)(null);
5359
+ const [creating, setCreating] = (0, import_react3.useState)(false);
5359
5360
  const [name, setName] = (0, import_react3.useState)("");
5360
5361
  const [description, setDescription] = (0, import_react3.useState)("");
5361
5362
  const [whenToUse, setWhenToUse] = (0, import_react3.useState)("");
@@ -5372,6 +5373,7 @@ function SkillManager({ workspace, remote }) {
5372
5373
  }, [refresh]);
5373
5374
  const startCreate = () => {
5374
5375
  setEditing(null);
5376
+ setCreating(true);
5375
5377
  setLevel("project");
5376
5378
  setName("");
5377
5379
  setDescription("");
@@ -5382,6 +5384,7 @@ function SkillManager({ workspace, remote }) {
5382
5384
  const startEdit = (sk) => {
5383
5385
  const lvl = levelOf(sk.source);
5384
5386
  setEditing(sk.name);
5387
+ setCreating(false);
5385
5388
  setLevel(lvl);
5386
5389
  setMsg("");
5387
5390
  void remote.readSkill({ name: sk.name, level: lvl, path: workspace }).then((r) => {
@@ -5416,9 +5419,10 @@ function SkillManager({ workspace, remote }) {
5416
5419
  }
5417
5420
  setMsg(`\u5DF2\u4FDD\u5B58 skill\u300C${result.value.name}\u300D`);
5418
5421
  setEditing(null);
5422
+ setCreating(false);
5419
5423
  refresh();
5420
5424
  };
5421
- const formOpen = editing !== null || name !== "" || description !== "" || body2 !== "";
5425
+ const formOpen = editing !== null || creating;
5422
5426
  return (0, import_react3.createElement)(
5423
5427
  "div",
5424
5428
  { style: styles.section },
@@ -5495,6 +5499,7 @@ function SkillManager({ workspace, remote }) {
5495
5499
  }, "\u4FDD\u5B58"),
5496
5500
  (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "sm", onClick: () => {
5497
5501
  setEditing(null);
5502
+ setCreating(false);
5498
5503
  setName("");
5499
5504
  setDescription("");
5500
5505
  setWhenToUse("");
@@ -5538,6 +5543,7 @@ function RuleManager({ workspace, remote }) {
5538
5543
  const [rules, setRules] = (0, import_react4.useState)([]);
5539
5544
  const [level, setLevel] = (0, import_react4.useState)("project");
5540
5545
  const [editing, setEditing] = (0, import_react4.useState)(null);
5546
+ const [creating, setCreating] = (0, import_react4.useState)(false);
5541
5547
  const [name, setName] = (0, import_react4.useState)("");
5542
5548
  const [body2, setBody] = (0, import_react4.useState)("");
5543
5549
  const [msg, setMsg] = (0, import_react4.useState)("");
@@ -5552,6 +5558,7 @@ function RuleManager({ workspace, remote }) {
5552
5558
  }, [refresh]);
5553
5559
  const startCreate = () => {
5554
5560
  setEditing(null);
5561
+ setCreating(true);
5555
5562
  setLevel("project");
5556
5563
  setName("");
5557
5564
  setBody("");
@@ -5560,6 +5567,7 @@ function RuleManager({ workspace, remote }) {
5560
5567
  const startEdit = (rule) => {
5561
5568
  const lvl = levelOf2(rule.source);
5562
5569
  setEditing(rule.name);
5570
+ setCreating(false);
5563
5571
  setLevel(lvl);
5564
5572
  setMsg("");
5565
5573
  void remote.readRule({ name: rule.name, level: lvl, path: workspace }).then((r) => {
@@ -5589,9 +5597,10 @@ function RuleManager({ workspace, remote }) {
5589
5597
  }
5590
5598
  setMsg(`\u5DF2\u4FDD\u5B58 rule\u300C${result.value.name}\u300D`);
5591
5599
  setEditing(null);
5600
+ setCreating(false);
5592
5601
  refresh();
5593
5602
  };
5594
- const formOpen = editing !== null || name !== "" || body2 !== "";
5603
+ const formOpen = editing !== null || creating;
5595
5604
  return (0, import_react4.createElement)(
5596
5605
  "div",
5597
5606
  { style: styles.section },
@@ -5657,6 +5666,7 @@ function RuleManager({ workspace, remote }) {
5657
5666
  }, "\u4FDD\u5B58"),
5658
5667
  (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", size: "sm", onClick: () => {
5659
5668
  setEditing(null);
5669
+ setCreating(false);
5660
5670
  setName("");
5661
5671
  setBody("");
5662
5672
  setMsg("");