@guandata/guanwf 0.1.6 → 0.1.820

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/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## @guandata/guanwf 0.1.820 - 2026-07-14
6
+
7
+ - 新增工作流参数 DSL、运行时 `--param` 覆盖和参数三方合并。
8
+ - 定时调度与事件调度新增可重复的 `--param key=value`,更新单个参数时保留其他显式值和工作流默认值。
9
+ - 新增 Dataset、Shell、HTTP、SQL、参数赋值、Switch、Loop 的结构化 TaskNode DSL 与无损 passthrough。
10
+ - 修复 8.2.0 DATASET 节点错误接受空 `datasetId` 的问题;该节点只刷新已有数据集,创建/写入目标数据集需使用 DATAFLOW/DB_DATAFLOW。
11
+ - 新增 `instance list/tasks/logs/latest`、完整日志分页和失败子工作流递归日志。
12
+ - 扩展 SHELL/HTTP/SQL 初始工作流及 `node add` 节点脚手架。
13
+ - 所有 `run` 操作新增 mutation 安全门:先用 `--dry-run` 查看计划,实际执行必须追加 `--confirm`(兼容 `--yes`);既有自动化脚本需要同步更新。
14
+ - 修复工作流三方合并、敏感凭据落盘、实例状态与日志、JSON 输出和跨平台原子写入问题。
15
+ - 精确合并快照会自动加入工作区 `.gitignore`;所有 `task.json` 统一使用当前用户受限权限,HTTP URL 查询凭据不会进入普通权限源码,日志中的常见键值凭据统一脱敏。
16
+ - 按 8.2.0 后端能力收口:SHELL/LOOP 在创建、导出和保存前明确拒绝;离线开发输出 DatasetNode、直连数据集参数赋值在提交前给出可执行替代方案。
17
+ - 修复参数赋值在 DATABASE/DATASET 来源切换后残留另一来源账号或数据集字段的问题。
18
+ - 修复 8.2.0 DB Dataflow 预览误用普通数据流 v1 接口、任务长期停留在 PROCESSING 的问题;改用 Core v2 提交和通用任务轮询/取消接口。
19
+
20
+ ## @guandata/guanwf 0.1.7 - 2026-07-08
21
+
22
+ - 工作流离线开发能力增强,支持文件夹、实例、权限、告警和调度相关命令。
23
+ - 新增工作流依赖分析、执行计划和依赖校验能力,便于把一批作业编排为统一调度主工作流。
24
+ - 数据流保存和合并能力增强,补充子工作流、事件调度和恢复场景支持。
25
+
3
26
  ## @guandata/guanwf 0.1.6 - 2026-06-24
4
27
 
5
28
  - `install-skill` 适配 WorkBuddy 配置目录,提升本机编码助手安装兼容性。
package/LICENSE ADDED
@@ -0,0 +1,133 @@
1
+ Guandata Developer Tools Free Evaluation License
2
+
3
+ Copyright (c) Hangzhou Guandata Co., Ltd.
4
+
5
+ This software and its related source code, documentation, examples, packages,
6
+ configuration files, command-line tools, MCP servers, SDKs, plugins, and tool
7
+ integrations are proprietary software of Hangzhou Guandata Co., Ltd. or its
8
+ licensors.
9
+
10
+ This license applies to Guandata developer tools, including but not limited to
11
+ Guandata CLI, Guandata MCP Server, related npm packages, source code,
12
+ documentation, examples, configuration files, and tool integrations.
13
+
14
+ 1. Free Personal Evaluation Use
15
+
16
+ Hangzhou Guandata Co., Ltd. grants you a limited, non-exclusive,
17
+ non-transferable, revocable license to use this software free of charge solely
18
+ for personal learning, local testing, technical evaluation, and non-production
19
+ experiments.
20
+
21
+ This free license does not permit enterprise, commercial, production, internal
22
+ business, team, organizational, hosted, customer-facing, or revenue-generating
23
+ use.
24
+
25
+ 2. Enterprise and Commercial Use
26
+
27
+ Any use by or for a company, organization, institution, government entity, team,
28
+ client, or other non-individual entity requires a separate commercial license
29
+ from Hangzhou Guandata Co., Ltd.
30
+
31
+ Enterprise or commercial use includes, but is not limited to:
32
+
33
+ - use in production, staging, shared, or hosted environments;
34
+ - use for internal business operations or automated business workflows;
35
+ - use by employees, contractors, consultants, service providers, or
36
+ representatives on behalf of an organization;
37
+ - integration into commercial products, services, platforms, workflows, AI
38
+ agents, MCP clients, or customer deliverables;
39
+ - connection to, access to, processing of, exposure of, or operation on
40
+ enterprise data, business systems, customer data, or production data;
41
+ - redistribution, hosting, resale, sublicensing, or provision of this software
42
+ as part of a paid or unpaid service.
43
+
44
+ To obtain an enterprise or commercial license, please contact Hangzhou Guandata
45
+ Co., Ltd. through its official sales, support, or business channels.
46
+
47
+ 3. MCP Server and Agent Integration
48
+
49
+ For Guandata MCP Server or any MCP-compatible tool integration, the free license
50
+ is limited to local personal testing, learning, and non-production evaluation.
51
+
52
+ The free license does not permit use of the MCP Server in enterprise agent
53
+ platforms, production AI applications, shared team environments,
54
+ customer-facing systems, hosted services, automated business workflows, or
55
+ integrations that access, process, expose, or operate on enterprise data.
56
+
57
+ Any organizational, commercial, hosted, production, or data-connected use of the
58
+ MCP Server requires a separate commercial license from Hangzhou Guandata Co., Ltd.
59
+
60
+ 4. Restrictions
61
+
62
+ Unless expressly permitted by this license, reasonably necessary to install and
63
+ use the software as allowed by this license, or expressly permitted by a
64
+ separate written agreement with Hangzhou Guandata Co., Ltd., you may not:
65
+
66
+ - copy, distribute, sublicense, sell, lease, host, or provide this software to
67
+ third parties;
68
+ - modify, adapt, translate, create derivative works of, or otherwise alter this
69
+ software;
70
+ - reverse engineer, decompile, disassemble, or attempt to derive the source
71
+ code, structure, sequence, organization, or underlying ideas of this software,
72
+ except to the extent such restriction is prohibited by applicable law;
73
+ - remove or alter copyright, trademark, license, or proprietary notices;
74
+ - use Guandata names, logos, trademarks, product names, or brand assets without
75
+ permission;
76
+ - use this software in violation of applicable laws, regulations, or third-party
77
+ rights;
78
+ - circumvent license, access control, usage limitation, telemetry, audit, or
79
+ security mechanisms, if any.
80
+
81
+ 5. Ownership
82
+
83
+ Hangzhou Guandata Co., Ltd. and its licensors retain all rights, title, and
84
+ interest in and to this software. No rights are granted except as expressly
85
+ stated in this license.
86
+
87
+ 6. Third-Party Components
88
+
89
+ Third-party open source components, if any, are licensed under their respective
90
+ licenses. This license applies only to software owned by Hangzhou Guandata Co., Ltd.
91
+ and does not modify any third-party license terms.
92
+
93
+ 7. No Warranty
94
+
95
+ This software is provided "as is" and "as available", without warranties of any
96
+ kind, whether express, implied, statutory, or otherwise, including but not
97
+ limited to warranties of merchantability, fitness for a particular purpose,
98
+ accuracy, availability, security, and non-infringement.
99
+
100
+ 8. Limitation of Liability
101
+
102
+ To the maximum extent permitted by applicable law, Hangzhou Guandata Co., Ltd.
103
+ shall not be liable for any indirect, incidental, special, consequential,
104
+ exemplary, or punitive damages, or for any loss of profits, revenue, data,
105
+ goodwill, business opportunity, or business interruption arising from or related
106
+ to this software, even if Hangzhou Guandata Co., Ltd. has been advised of the
107
+ possibility of such damages.
108
+
109
+ 9. Termination
110
+
111
+ Your rights under this license terminate automatically if you violate any term of
112
+ this license. Upon termination, you must stop using the software and delete all
113
+ copies in your possession or control.
114
+
115
+ 10. Governing Law and Dispute Resolution
116
+
117
+ This license shall be governed by the laws of the People's Republic of China,
118
+ without regard to its conflict of laws principles.
119
+
120
+ Any dispute arising from or related to this license or the software shall be
121
+ submitted to the competent court with jurisdiction in Hangzhou, Zhejiang
122
+ Province, China, unless otherwise required by applicable law.
123
+
124
+ 11. Contact
125
+
126
+ For enterprise licensing, commercial authorization, partnership, procurement, or
127
+ other questions, please contact Hangzhou Guandata Co., Ltd. through its official
128
+ website or official business channels.
129
+
130
+ 12. Language
131
+
132
+ If this license is provided in multiple languages, the English version controls
133
+ unless Hangzhou Guandata Co., Ltd. expressly states otherwise in writing.
package/LICENSE.zh-CN ADDED
@@ -0,0 +1,82 @@
1
+ 观远开发者工具免费评估许可协议
2
+
3
+ 版权所有 (c) 杭州观远数据有限公司。
4
+
5
+ 本软件及其相关源代码、文档、示例、软件包、配置文件、命令行工具、MCP Server、SDK、插件和工具集成,属于杭州观远数据有限公司或其授权方的专有软件。
6
+
7
+ 本协议适用于观远开发者工具,包括但不限于观远 CLI、观远 MCP Server、相关 npm 包、源代码、文档、示例、配置文件和工具集成。
8
+
9
+ 1. 免费个人评估使用
10
+
11
+ 杭州观远数据有限公司授予你一项有限的、非独占的、不可转让的、可撤销的许可,允许你免费使用本软件,但仅限于个人学习、本地测试、技术评估和非生产环境实验。
12
+
13
+ 本免费许可不允许企业使用、商业使用、生产环境使用、内部业务使用、团队使用、组织使用、托管使用、面向客户的使用,或任何直接或间接产生商业收益的使用。
14
+
15
+ 2. 企业及商业使用
16
+
17
+ 任何由公司、组织、机构、政府单位、团队、客户或其他非个人主体进行的使用,或代表上述主体进行的使用,均需事先取得杭州观远数据有限公司的单独商业授权。
18
+
19
+ 企业或商业使用包括但不限于:
20
+
21
+ - 在生产环境、预发布环境、共享环境或托管环境中使用;
22
+ - 用于内部业务运营或自动化业务流程;
23
+ - 由员工、承包商、顾问、服务商或代理人代表组织使用;
24
+ - 集成到商业产品、服务、平台、工作流、AI 智能体、MCP 客户端或客户交付物中;
25
+ - 连接、访问、处理、暴露或操作企业数据、业务系统、客户数据或生产数据;
26
+ - 对本软件进行分发、托管、转售、再许可,或作为任何付费或免费的服务的一部分提供。
27
+
28
+ 如需企业或商业授权,请通过观远官方销售、支持或商务渠道联系杭州观远数据有限公司。
29
+
30
+ 3. MCP Server 与智能体集成
31
+
32
+ 对于观远 MCP Server 或任何兼容 MCP 的工具集成,免费许可仅限于个人本地测试、学习和非生产环境评估。
33
+
34
+ 免费许可不允许将 MCP Server 用于企业级智能体平台、生产环境 AI 应用、团队共享环境、面向客户的系统、托管服务、自动化业务流程,或任何访问、处理、暴露、操作企业数据的集成场景。
35
+
36
+ 任何组织用途、商业用途、托管用途、生产用途,或涉及企业数据连接的 MCP Server 使用,均需取得杭州观远数据有限公司的单独商业授权。
37
+
38
+ 4. 限制
39
+
40
+ 除非本协议明确允许、为按照本协议安装和使用本软件所合理必需,或杭州观远数据有限公司通过单独书面协议明确允许,你不得:
41
+
42
+ - 复制、分发、再许可、销售、出租、托管本软件,或向第三方提供本软件;
43
+ - 修改、改编、翻译本软件,创作本软件的衍生作品,或以其他方式变更本软件;
44
+ - 对本软件进行反向工程、反编译、反汇编,或试图获取本软件的源代码、结构、顺序、组织方式或底层思想,但适用法律禁止限制的情形除外;
45
+ - 删除或修改版权、商标、许可或专有权利声明;
46
+ - 未经许可使用杭州观远数据有限公司或观远品牌的名称、标识、商标、产品名称或品牌资产;
47
+ - 以违反适用法律法规或第三方权利的方式使用本软件;
48
+ - 绕过任何许可、访问控制、使用限制、遥测、审计或安全机制。
49
+
50
+ 5. 权利归属
51
+
52
+ 本软件的所有权利、所有权和利益均归杭州观远数据有限公司及其授权方所有。除本协议明确授予的权利外,不授予任何其他权利。
53
+
54
+ 6. 第三方组件
55
+
56
+ 本软件中如包含第三方开源组件,该等组件适用其各自的许可协议。本协议仅适用于杭州观远数据有限公司拥有权利的软件部分,并不修改任何第三方许可条款。
57
+
58
+ 7. 无担保
59
+
60
+ 本软件按“现状”和“现有”基础提供,不作任何明示、默示、法定或其他形式的担保,包括但不限于适销性、特定用途适用性、准确性、可用性、安全性和不侵权担保。
61
+
62
+ 8. 责任限制
63
+
64
+ 在适用法律允许的最大范围内,杭州观远数据有限公司不对因本软件引起或与本软件相关的任何间接、附带、特殊、后果性、惩罚性或惩戒性损害承担责任,也不对利润、收入、数据、商誉、商业机会损失或业务中断承担责任,即使杭州观远数据有限公司已被告知可能发生该等损害。
65
+
66
+ 9. 终止
67
+
68
+ 如果你违反本协议的任何条款,你在本协议项下的权利将自动终止。终止后,你必须停止使用本软件,并删除你持有或控制的所有副本。
69
+
70
+ 10. 适用法律与争议解决
71
+
72
+ 本协议适用中华人民共和国法律,但不包括其冲突法规则。
73
+
74
+ 因本协议或本软件引起或与之相关的任何争议,应提交中国浙江省杭州市有管辖权的人民法院解决,除非适用法律另有强制性规定。
75
+
76
+ 11. 联系方式
77
+
78
+ 如需企业授权、商业许可、合作、采购或有其他问题,请通过观远官方网站或官方商务渠道联系杭州观远数据有限公司。
79
+
80
+ 12. 语言
81
+
82
+ 如本协议提供多个语言版本,除非杭州观远数据有限公司另有明确书面说明,以英文版本为准。
package/README.md CHANGED
@@ -16,13 +16,25 @@ npm link
16
16
 
17
17
  ```bash
18
18
  guanwf create --name "我的数据流" --parent-dir <dirId>
19
+ guanwf create --name "HTTP作业" --type HTTP --parent-dir <dirId>
20
+ guanwf create --name "SQL作业" --type SQL --parent-dir <dirId>
19
21
  guanwf edit <parentWorkflowId>
20
22
  guanwf export --dir <workdir>
21
23
  guanwf preview --dir <workdir>
22
- guanwf save --dir <workdir>
23
- guanwf run --wait --dir <workdir>
24
+ guanwf save --dir <workdir> --dry-run
25
+ guanwf save --dir <workdir> --confirm
26
+ guanwf run --wait --dir <workdir> --dry-run
27
+ guanwf run --wait --dir <workdir> --confirm
28
+ guanwf run --dir <workdir> --param biz_date=2026-07-14 --confirm
29
+ guanwf schedule set --cron "0 0 2 * * ?" --param biz_date=2026-07-14 --dir <workdir> --confirm
30
+ guanwf schedule event set --rule <datasetId>:<taskName> --param biz_date=2026-07-14 --dir <workdir> --confirm
31
+ guanwf instance latest --dir <workdir> --logs -f json
24
32
  ```
25
33
 
34
+ 8.2.0 兼容说明:SHELL/LOOP 后端未注册,CLI 会提前拒绝;离线开发输出数据集不能作为
35
+ DatasetNode 刷新目标,应使用 SubWorkflowNode 调用产出工作流。参数赋值查询 StarRocks
36
+ 直连表时使用 DATABASE 来源,不要把直连数据集作为 DATASET 来源。
37
+
26
38
  说明:npm 包名为 `@guandata/guanwf`,用户侧 CLI 命令统一为 `guanwf`。
27
39
 
28
40
  也可以为 AI Coding Assistant 安装 Skill:
@@ -33,6 +45,18 @@ guanwf install-skill
33
45
 
34
46
  ## 版本更新
35
47
 
48
+ ### @guandata/guanwf 0.1.820
49
+
50
+ - 8.2.0 专用兼容版本;请勿与面向 master 的 CLI 版本混用。
51
+ - 新增结构化工作流节点、参数、实例诊断和安全 mutation 门,并修复 8.2.0 保存、预览、运行及恢复链路问题。
52
+ - 对 8.2.0 不支持的 SHELL、LOOP、PROCESS 事件源等能力在提交前给出明确阻断。
53
+
54
+ ### @guandata/guanwf 0.1.7
55
+
56
+ - 工作流离线开发能力增强,支持文件夹、实例、权限、告警和调度相关命令。
57
+ - 新增工作流依赖分析、执行计划和依赖校验能力,便于把一批作业编排为统一调度主工作流。
58
+ - 数据流保存和合并能力增强,补充子工作流、事件调度和恢复场景支持。
59
+
36
60
  ### @guandata/guanwf 0.1.6
37
61
 
38
62
  - `install-skill` 适配 WorkBuddy 配置目录,提升本机编码助手安装兼容性。
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guandata/guanwf",
3
- "version": "0.1.6",
3
+ "version": "0.1.820",
4
4
  "description": "观远工作流数据流编辑工具 - 创建、编辑、导出、预览、保存数据流",
5
5
  "bin": {
6
6
  "guanwf": "bin/run.js"
@@ -16,6 +16,8 @@
16
16
  "binaries/",
17
17
  "skills/",
18
18
  "CHANGELOG.md",
19
+ "LICENSE",
20
+ "LICENSE.zh-CN",
19
21
  "README.md"
20
22
  ],
21
23
  "keywords": [
@@ -25,7 +27,7 @@
25
27
  "cli",
26
28
  "agent-skill"
27
29
  ],
28
- "license": "UNLICENSED",
30
+ "license": "SEE LICENSE IN LICENSE",
29
31
  "os": [
30
32
  "darwin",
31
33
  "linux",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: guanwf
3
- description: 当用户要创建、编辑、保存工作流引擎中的工作流(含数据流节点、Python 节点、参数赋值等多节点 DAG),或需要预览数据流节点、校验/试运行 Python 脚本、运行工作流,或需要查询工作流/数据流列表和详情时使用。数据流是 BI ETL 的扩展,运行在独立的工作流引擎中。适用于用户说"创建一个数据流""创建一个带 Python 节点的工作流""编辑这个工作流""保存数据流""预览数据流节点""运行工作流""验证这个 Python 脚本能不能跑""列出所有数据流""查看这个工作流的定义"等场景。
3
+ description: 当用户要创建、编辑、保存工作流引擎中的工作流(含数据流节点、Python 节点、子工作流编排、参数赋值等多节点 DAG),或需要预览数据流节点、校验/试运行 Python 脚本、运行工作流、配置定时调度、从失败处恢复续跑,或需要查询工作流/数据流列表和详情时使用。也适用于把一批已有作业工作流按依赖串成统一调度的主工作流(编排):从血缘自动推导依赖生成编排(deps plan)、对账编排依赖与血缘是否一致(deps verify)、配置 cron 调度上下线(schedule)、失败后增量恢复(run --recover)。数据流是 BI ETL 的扩展,运行在独立的工作流引擎中。适用于用户说"创建一个数据流""创建一个带 Python 节点的工作流""编辑这个工作流""保存数据流""预览数据流节点""运行工作流""验证这个 Python 脚本能不能跑""列出所有数据流""查看这个工作流的定义""把这批作业串起来统一调度""按血缘生成调度依赖""给工作流配个每天凌晨的调度""调度先下线""编排里有作业挂了修好后接着跑"等场景。
4
4
  compatibility: "Requires Node.js 14+. Install via npm link (local) or npm install -g @guandata/guanwf (from internal Nexus registry). CLI command: guanwf."
5
5
  ---
6
6
 
@@ -11,7 +11,8 @@ compatibility: "Requires Node.js 14+. Install via npm link (local) or npm instal
11
11
 
12
12
  这是一个执行型 skill,不是只读分析 skill。
13
13
 
14
- - `guancli workflow` 负责查询工作流、数据流、目录和线上结构。
14
+ - `guancli workflow` 负责通用工作流、数据流、目录和线上结构查询;v0.1.820(8.2.0 兼容线)实例诊断使用
15
+ `guanwf instance list/tasks/logs/latest`,可直接解析 `--dir` 工作区。
15
16
  - `guanwf` 负责把目标工作流拉到本地工作目录,修改事实源,再完成 `export -> preview/validate -> save-draft/save -> run`。
16
17
 
17
18
  ## 核心概念
@@ -20,7 +21,16 @@ compatibility: "Requires Node.js 14+. Install via npm link (local) or npm instal
20
21
  - **数据流 (Dataflow / DATAFLOW)**: 嵌入在工作流中的 ETL 流程,actions 结构与 BI ETL 相同
21
22
  - **数据库数据流 (DB_DATAFLOW)**: 数据流的变体,支持 SQL 下推
22
23
  - **Python 节点 (SECURE_PYTHON)**: 工作流级 Python 任务,沙箱内运行脚本,可读输入数据集并创建输出数据集
24
+ - **子工作流节点 (SUB_PROCESS + PROCESS)**: 引用另一个已存在的工作流作为节点,用于把一批作业编排成统一调度的主工作流
23
25
  - **节点依赖**: 节点间用 `After`(成功后)/ `AfterFailure`(失败后)/ `AfterAny`(完成后)声明执行顺序
26
+ - **工作流参数**: `Workflow.Params` 声明,使用 `ParamRef` / `DynamicParamRef` / `DataDrivenParamRef` 引用
27
+ - **结构化任务节点**: DATASET、HTTP、SQL、PARAMETER_ASSIGNMENT、SWITCH 均有 8.2.0 可执行的强类型 DSL,未知字段由 `task.json` 保留;SHELL/LOOP 仅保留导入模型,8.2.0 不可创建、导出、保存或运行
28
+
29
+ ### 8.2.0 兼容边界
30
+
31
+ - 8.2.0 后端没有注册 `SHELL`、`LOOP` TaskParameters,CLI 会在脚手架、导出、保存前明确拒绝。
32
+ - `DatasetNode` 可刷新数据库抽取/直连数据集;不能刷新 `DATA_SET_OFFLINE_DEV`,该路径在 8.2.0 会把 BI 文本响应误当 JSON。需要更新离线开发产出时,使用 `SubWorkflowNode` 调用产出工作流。
33
+ - `ParameterAssignmentNode` 的 `DATASET` 来源不能选数据库直连数据集(BI 返回 60006);三张 StarRocks 表应使用 `DataSourceType: "DATABASE"` 和数据账户。抽取/产出数据集可使用 `DATASET` 来源及 `input1` 查询。
24
34
 
25
35
  ## 关键不变式
26
36
 
@@ -52,18 +62,23 @@ compatibility: "Requires Node.js 14+. Install via npm link (local) or npm instal
52
62
  node_*.json # 可编辑事实源:LoadNodeFromFile 透传节点配置
53
63
  script.py # 可编辑事实源:PYTHON 节点脚本正文
54
64
  python.json # 服务端字段透传(edit 生成,勿手改;改配置去 workflow.go 的 PythonConfig)
55
- task.json # 可编辑事实源:RAW 透传节点完整 TaskNode JSON
65
+ task.json # 0600/当前用户 ACL;RAW 节点为完整事实源,结构化节点保留未知字段
66
+ script.sh # SHELL 节点脚本
67
+ query.sql # SQL / PARAMETER_ASSIGNMENT 节点 SQL
68
+ body.json/body.txt # HTTP 请求体
56
69
  _input.json / meta.json # 导入快照/派生产物,不手改
57
70
  _layout.json # 画布坐标(edit 保留线上坐标;新节点自动布局补位)
58
71
  _wf_state.json # 系统状态,不手改
59
- _parent_snapshot.json # 服务端快照,不手改;save 时重新拉取最新版本合并
72
+ _parent_snapshot.json # 脱敏服务端快照,不手改
73
+ _parent_merge_snapshot.json # 受限权限的精确三方合并基线,不手改
74
+ .gitignore # 自动忽略含原始凭据的精确合并基线
60
75
  _exported_workflow.json # 派生产物,不手改;由 export 重新生成
61
76
  ```
62
77
 
63
78
  ### 禁止的偷懒路径
64
79
 
65
80
  - 不要直接编辑 `_exported_workflow.json` 来"修好"预览或保存。
66
- - 不要直接编辑 `_parent_snapshot.json` 来拼保存 payload。
81
+ - 不要直接编辑 `_parent_snapshot.json` 或 `_parent_merge_snapshot.json` 来拼保存 payload。
67
82
  - 不要手改 `python.json`;输入/输出/资源配置改 `workflow.go` 的 `PythonConfig`。
68
83
  - 不要跳过 `export`,拿上一次的导出结果去 `preview` 或 `save`。
69
84
 
@@ -83,10 +98,27 @@ guancli auth status # 检查连接状态
83
98
  ### 0. 先分场景
84
99
 
85
100
  - `只读查询`: 用 `guancli workflow`,不要创建工作目录。
86
- - `新建工作流`: `guanwf create --name ... --parent-dir ...`(`--type DATAFLOW/DB_DATAFLOW/PYTHON` 控制初始节点骨架),然后编辑 `workflow.go` 和 `nodes/`。
101
+ - `新建工作流`: `guanwf create --name ... --parent-dir ...`(8.2.0 支持 `--type DATAFLOW/DB_DATAFLOW/PYTHON/HTTP/SQL/ORCHESTRATION`),然后编辑 `workflow.go` 和 `nodes/`。
87
102
  - `编辑已有工作流`: `guanwf edit <workflowId>` 导入整个工作流(数据流节点 → etl.go,Python 节点 → script.py)。
103
+ - `编排一批作业`: `guanwf create --type ORCHESTRATION` + `guanwf deps plan` 从血缘自动生成依赖,见「编排工作流」一节。
88
104
  - `修复失败`: 先定位失败发生在 `export`、`preview`、`save` 还是 `run`,只修最小责任源文件。
89
105
 
106
+ ### v0.1.820 参数、节点和实例命令
107
+
108
+ ```bash
109
+ guanwf node add http --id http_1 --name "通知下游" --dir <workdir>
110
+ guanwf node add sql --id sql_1 --name "执行SQL" --dir <workdir>
111
+
112
+ guanwf run --dir <workdir> --param biz_date=2026-07-14 --confirm
113
+ guanwf instance list --dir <workdir> --state FAILURE -f json
114
+ guanwf instance tasks <instanceId> --dir <workdir> -f json
115
+ guanwf instance logs <instanceId> --dir <workdir> --node "<节点名>" --full --log-type ALL -f json
116
+ guanwf instance latest --dir <workdir> --logs -f json
117
+ ```
118
+
119
+ `node add` 只生成节点目录和可粘贴 DSL 片段,不自动修改 `workflow.go` AST。节点真实字段、
120
+ 参数类型兼容和外置文件约定见 `references/TASK_NODE_CONTRACTS.md`。
121
+
90
122
  ### 1. 缺上下文先查,不要猜
91
123
 
92
124
  查询工作流和数据流定义时使用 `guancli workflow`。工作流/数据流由独立的 workflow 引擎管理。
@@ -128,9 +160,9 @@ guancli workflow get <id> -f json # JSON 格式输出
128
160
 
129
161
  1. `guanwf export --dir <workdir>`
130
162
  2. 数据流节点要看数据结果时 `guanwf preview --dir <workdir>`;Python 节点要校验时
131
- `guanwf run --node "<节点名>" --validate --dir <workdir>`(需先 save-draft)
132
- 3. 确认无误后才 `guanwf save-draft --dir <workdir>` 或 `guanwf save --dir <workdir>`
133
- 4. 需要执行时再 `guanwf run --wait --dir <workdir>`
163
+ `guanwf run --node "<节点名>" --validate --dir <workdir> --dry-run`,确认计划后追加 `--confirm`(需先保存草稿)
164
+ 3. 先用 `guanwf save-draft --dir <workdir> --dry-run` 或 `guanwf save --dir <workdir> --dry-run` 查看计划,确认后追加 `--confirm`
165
+ 4. 需要执行时先运行 `guanwf run --wait --dir <workdir> --dry-run`,确认后追加 `--confirm`
134
166
 
135
167
  如果 `export` 没过,不要直接 `preview` 或 `save`。
136
168
 
@@ -144,10 +176,11 @@ guanwf create --name "Python清洗" --type PYTHON --parent-dir <dirId> --dir <wo
144
176
 
145
177
  # 编辑 workflow.go(节点 + 依赖)和 nodes/ 下源文件后:
146
178
  guanwf export --dir <workdir>
147
- guanwf save-draft --dir <workdir>
179
+ guanwf save-draft --dir <workdir> --dry-run
180
+ guanwf save-draft --dir <workdir> --confirm
148
181
  guanwf preview --dir <workdir> # 数据流节点:预览数据
149
- guanwf run --node "<节点名>" --validate --dir <workdir> # Python 节点:校验(不创建输出数据集)
150
- guanwf save --dir <workdir> # 正式发布
182
+ guanwf run --node "<节点名>" --validate --dir <workdir> --confirm # Python 节点:校验(不创建输出数据集)
183
+ guanwf save --dir <workdir> --confirm # 正式发布
151
184
  ```
152
185
 
153
186
  ### 编辑已有工作流
@@ -173,16 +206,22 @@ guanwf edit <workflowId> --dir <workdir>
173
206
  ### 运行工作流
174
207
 
175
208
  ```bash
176
- guanwf run --dir <workdir> # 触发运行(已发布版本)
177
- guanwf run --wait --dir <workdir> # 等待完成
178
- guanwf run --wait --timeout 600 --dir <workdir> # 自定义超时
179
- guanwf run --wait --logs --dir <workdir> # 完成后输出任务日志
180
- guanwf run --node "<节点名>" --validate --dir <workdir> # 校验 Python 脚本(不创建输出数据集)
181
- guanwf run --node "<节点名>" --draft --wait --logs --dir <workdir> # 单节点真实运行草稿
209
+ guanwf run --dir <workdir> --confirm # 触发运行(已发布版本)
210
+ guanwf run --wait --dir <workdir> --dry-run # 查看执行计划
211
+ guanwf run --wait --dir <workdir> --confirm # 确认并等待完成
212
+ guanwf run --wait --timeout 600 --dir <workdir> --confirm # 自定义超时
213
+ guanwf run --wait --logs --dir <workdir> --confirm # 完成后输出任务日志
214
+ guanwf run --node "<节点名>" --validate --dir <workdir> --confirm # 校验 Python 脚本(不创建输出数据集)
215
+ guanwf run --node "<节点名>" --draft --wait --logs --dir <workdir> --confirm # 单节点真实运行草稿
216
+ guanwf run --recover --wait --dir <workdir> --confirm # 从最近失败实例的失败节点续跑
217
+ guanwf instance resume-failed <instanceId> --dom-id <domId> --wait --timeout 900 --confirm
182
218
  ```
183
219
 
184
220
  `--node` 按节点显示名只运行指定节点(TASK_ONLY);`--draft` 运行 save-draft 的草稿版本;
185
- `--logs` 输出任务实例日志(失败时自动拉取)。
221
+ `--logs` 输出任务实例日志(失败时自动拉取,失败的子工作流节点自动下钻子实例日志);
222
+ `--recover` 从失败处续跑(见「失败恢复」一节)。
223
+ `run --recover` 和 `instance resume-failed` 的最外层实例只有传 `--wait` 才等待完成;嵌套
224
+ PROCESS 子实例始终等待成功后才恢复父实例。长任务用 `--timeout` 调整等待上限。
186
225
 
187
226
  **`--validate` 是验证 Python 脚本的默认方法**:临时草稿中把 `save_outputN` 替换为只打印
188
227
  dtypes/head 的 stub,脚本完整执行但不写输出文件,服务端跳过数据集注册(不创建真实数据集),
@@ -198,6 +237,99 @@ guanwf preview <actionId> --dir <workdir> # 多个数据流节点时按 action
198
237
  `preview` 基于 export 的本地定义直接发起预览,无需先 save。Python 节点没有 preview API,
199
238
  校验用 `run --node "<节点名>" --validate`。
200
239
 
240
+ ## 编排工作流(把一批作业统一调度)
241
+
242
+ 场景:已有一批作业工作流(每个作业产出数据集),要按依赖串成一个主工作流统一调度。
243
+
244
+ 用户可能这样下达任务(自然语言 → 执行路径映射):
245
+
246
+ | 用户说 | Agent 执行 |
247
+ |---|---|
248
+ | "把 xslh 开头的这批作业串成一个统一调度,每天凌晨 2 点跑" | create ORCHESTRATION → deps plan --search "xslh" → verify → save → schedule set --cron "0 0 2 * * ?" |
249
+ | "这三个作业 A、B、C 编排起来,A 必须在 B 之前" | deps plan --jobs <idA>,<idB>,<idC> + hints.json 里 before:[{first:A,then:B}] |
250
+ | "作业C 是读昨天的快照,别给它连边" | hints.json 里 cross_batch:[{consumer:C,dataset:<dsId>}] |
251
+ | "统一调度里有个作业挂了,帮我修好后接着跑,成功的别重跑" | 下钻日志定位失败作业 → 回作业目录修复+save → 编排目录 run --recover --wait |
252
+ | "调度先别上线/先停掉" | schedule set ... --offline / schedule disable |
253
+ | "看下现在的调度配置" | schedule info |
254
+
255
+ **依赖的事实源是平台血缘**(作业定义中的输入/输出数据集),不是文档/Excel 的口头描述。
256
+ 用 `deps plan` 从血缘自动推导,用 `deps verify` 对账,人工只补血缘表达不了的提示
257
+ (先后顺序 hint、跨批次 CrossBatch、剔除 exclude)。
258
+
259
+ ```bash
260
+ # 1. 建编排工作区(无初始节点)
261
+ guanwf create --name "统一调度" --type ORCHESTRATION --parent-dir <dirId> --dir <workdir>
262
+
263
+ # 2. 从血缘自动生成 workflow.go(SubWorkflowNode + After 边,每条边注释依据)
264
+ guanwf deps plan --search "<作业名模式>" --yes --dir <workdir> # 或 --jobs <id1>,<id2>,...
265
+ guanwf deps plan ... --hints hints.json # 人工提示(before/cross_batch/exclude)
266
+
267
+ # 3. 人工微调后对账(ERROR 必须修复;有 ERROR 时 exit 1)
268
+ guanwf export --dir <workdir>
269
+ guanwf deps verify --dir <workdir>
270
+
271
+ # 4. 保存并运行
272
+ guanwf save --dir <workdir> --confirm
273
+ guanwf run --wait --dir <workdir> --confirm
274
+ ```
275
+
276
+ ```bash
277
+ # 5. 配置定时调度并上线
278
+ guanwf schedule set --cron "0 0 2 * * ?" --dir <workdir> --confirm
279
+ guanwf schedule set --cron "0 0 2 * * ?" --param biz_date=2026-07-14 --dir <workdir> --confirm
280
+ guanwf schedule event set --rule <datasetId>:<taskName> --param biz_date=2026-07-14 --dir <workdir> --confirm
281
+ ```
282
+
283
+ 规则要点:
284
+
285
+ - 一个数据集只能有一个产出作业(DUP_PRODUCER 是 ERROR)。
286
+ - A 读 B 的产出则编排中必须有 B→A 路径,否则 verify 报 MISSING_EDGE;
287
+ 刻意读上一批(T-1)产物时在 `Workflow.CrossBatch` 中声明,verify 降级为 INFO。
288
+ - 子作业失败 → 主实例失败,下游不执行;失败日志会自动下钻到子实例定位真实报错。
289
+ - **失败恢复**:修复失败作业并 `guanwf save --confirm` 后,在编排目录执行
290
+ `guanwf run --recover --wait --confirm`——自底向上恢复失败的子实例和主实例,
291
+ 成功祖先和无关分支不重跑;恢复节点的全部 DAG 后继会重跑(包括先前为 SUCCESS 的后继)。
292
+ 例如 job_a/job_b 是 job_c 的成功祖先、job_c 失败时只从 job_c 及其后继开始重跑。
293
+ - 修改编排结构改 `workflow.go`(`SubWorkflowNode` / `After` / `CrossBatch`),
294
+ 不要去改被引用作业的内容;作业内容问题回作业自己的工作目录修。
295
+
296
+ `SubWorkflowNode` DSL、hints.json 结构、verify 全部检查项见 `references/WORKFLOW_DSL.md`
297
+ 「编排工作流」一节。
298
+
299
+ ## 定时调度
300
+
301
+ ```bash
302
+ guanwf schedule info --dir <workdir> # 查看当前调度
303
+ guanwf schedule set --cron "0 0 2 * * ?" --dir <workdir> --confirm # 创建/更新并上线
304
+ guanwf schedule set --cron "0 0 2 * * ?" --offline --dir <workdir> --confirm # 只保存不上线
305
+ guanwf schedule enable --dir <workdir> --confirm # 上线
306
+ guanwf schedule disable --dir <workdir> --confirm # 下线
307
+ ```
308
+
309
+ - crontab 是 Quartz 6/7 段表达式(秒 分 时 日 月 周 [年]),如 `0 30 6 * * ?` 每天 06:30。
310
+ - `set` 可选 `--failure-strategy CONTINUE|END`(默认 CONTINUE)、
311
+ `--warning NONE|SUCCESS|FAILURE|ALL`(默认 FAILURE)、`--start/--end` 生效区间、
312
+ `--auto-cancel-queued`(上一批未跑完时自动取消堆积实例)。
313
+ - 已有调度时未指定的参数保留现状;事件调度使用 `guanwf schedule event get/set/disable`。
314
+
315
+ ## 失败恢复(run --recover)
316
+
317
+ ```bash
318
+ guanwf run --recover --wait --dir <workdir> --confirm
319
+ ```
320
+
321
+ 找到最近一次 FAILURE 实例,从恢复节点处续跑;成功祖先和无关分支不重跑,恢复节点的
322
+ 全部 DAG 后继会重跑。8.2.0 的恢复种子状态包括 FAILURE、STOP、KILL、
323
+ NEED_FAULT_TOLERANCE。适用于长链路编排中
324
+ 个别作业失败:先回失败作业的工作目录修复并 `guanwf save --confirm`,再回编排目录 `--recover --confirm`。
325
+
326
+ 平台语义(已实测):失败的子工作流节点会复用原子实例,且子实例持有失败时的旧定义快照。
327
+ `--recover` 已处理这一点——自底向上先恢复失败子实例(`update=true` 吸收失败节点及后继
328
+ 的最新发布定义),并对恢复范围内已成功的 PROCESS 后继显式执行 `REPEAT_RUNNING`,再恢复
329
+ 父实例。若子工作流引用已切换、编排 DAG 结构已变更(加减节点/改依赖),CLI/平台会拒绝
330
+ 恢复,此时直接
331
+ `guanwf run --confirm` 重跑整链。
332
+
201
333
  ## save 的工作机制
202
334
 
203
335
  `save` / `save-draft` 不是简单把本地 JSON 上传。内部流程是:
@@ -205,7 +337,7 @@ guanwf preview <actionId> --dir <workdir> # 多个数据流节点时按 action
205
337
  1. 读取本地 `_exported_workflow.json`(必须由 `export` 重新生成)
206
338
  2. 从服务端重新拉取工作流最新版本作为基底
207
339
  3. tasks 按节点 id 做字段级合并:本地定义的字段覆盖,服务端独有字段(dsId、运行时注册信息等)保留
208
- 4. 节点成员按三方判断(服务端最新 + 本地 `_parent_snapshot.json` + 本地导出):
340
+ 4. 节点成员按三方判断(服务端最新 + 本地 `_parent_merge_snapshot.json` + 本地导出):
209
341
  本地快照里有、导出里删了的节点 → 删除;服务端有、本地快照不知道的节点(他人并发新增)→
210
342
  保留并打印提示
211
343
  5. dataflowJson 按 dataflow id 经 etlmerge 做 actions 字段级合并(成员判断同上)
@@ -228,13 +360,19 @@ guanwf preview <actionId> --dir <workdir> # 多个数据流节点时按 action
228
360
  | 查询详情 | GET | `/api/offline-dev/process/{id}/select-by-id` |
229
361
  | 保存草稿 | POST | `/api/offline-dev/process/save-draft` |
230
362
  | 保存发布 | POST | `/api/offline-dev/process/save` |
231
- | 预览数据流 | POST | `/api/offline-dev/dataflow/preview-async` |
232
- | 查询预览任务 | GET | `/api/offline-dev/dataflow/task/{taskId}` |
233
- | 取消预览 | POST | `/api/offline-dev/dataflow/task/{taskId}/cancel` |
363
+ | 预览普通数据流 | POST | `/api/offline-dev/dataflow/preview-async` |
364
+ | 查询/取消普通预览 | GET/POST | `/api/offline-dev/dataflow/task/{taskId}`、`/cancel` |
365
+ | 预览 DB Dataflow | POST | `/api/offline-dev/dataflow/v2/preview-async` |
366
+ | 查询/取消 DB Dataflow 预览 | GET/POST | `/api/task/{taskId}`、`/cancel` |
234
367
  | 运行工作流 | POST | `/api/offline-dev/process/{id}/start-process-instance` |
235
368
  | 查询运行实例 | GET | `/api/offline-dev/process/instance/{id}/select-by-id?domId=<domId>` |
236
369
  | 实例任务列表 | GET | `/api/offline-dev/process/instance/{id}/task-list-by-process-id?domId=<domId>` |
237
370
  | 任务日志 | GET | `/api/offline-dev/log/detail?taskInstId=<id>&logType=UI&domId=<domId>` |
371
+ | 实例列表分页 | GET | `/api/offline-dev/instance/list-paging?processDefinitionId=<id>&domId=<domId>` |
372
+ | 恢复/停止实例 | POST | `/api/offline-dev/process/{id}/instance/{instId}/execute` |
373
+ | 子实例定位 | GET | `/api/offline-dev/process/instance/{instId}/task/{taskInstId}/select-sub-process?domId=<domId>` |
374
+ | 调度查询 | GET | `/api/offline-dev/process/{id}/schedule/info?domId=<domId>` |
375
+ | 调度创建/更新 | POST | `/api/offline-dev/process/{id}/schedule/create`、`/schedule/{scheduleId}/update` |
238
376
 
239
377
  实例/日志查询接口要求 `domId` 参数(工作流详情 `select-by-id` 响应中的 `domId` 字段),
240
378
  `guanwf run` 内部自动处理。`list-paging` 请求体的搜索字段是 `searchVal`。
@@ -0,0 +1,64 @@
1
+ # 工作流 TaskNode 合约(v0.1.820 / 8.2.0)
2
+
3
+ 本文件记录 `guanwf` 结构化 DSL 的平台事实源。合约来自当前 `workflow_web` 节点定义和
4
+ `guandata-workflow` DTO/校验逻辑;未知或版本新增字段由 `nodes/<id>/task.json` 无损保留。
5
+
6
+ ## 通用字段
7
+
8
+ 所有结构化节点导出 `id/name/type/desc/params/preTasks/preTaskScheduleTypes`,并带平台默认的
9
+ `runFlag/retryEnabled/maxRetryTimes/retryInterval/workerGroupId/taskTimeoutParameter`。Go DSL
10
+ 字段覆盖 `task.json`,base-only 字段保留。依赖始终以 `workflow.go` 为准。
11
+
12
+ ## 工作流参数
13
+
14
+ `Workflow.Params` 保存到 `processDefinitionJson.globalParams`。平台识别:
15
+
16
+ - `STRING`、`NUMBER`、`DATE`;bool 兼容为 STRING,日期时间/时间宏兼容为 DATE。
17
+ - 字段:`name/description/valueType/defaultValue/optionValue/customize/multiple/freeze/paramType`。
18
+ - 引用:`[WORKFLOW_PARAMS.name]`、`[DYNAMIC_PARAMS.name]`、
19
+ `[DATADRIVEN_PARAMS.name]`、`[BUILTIN_PARAMS.name]`。
20
+ - `run --param key=value` 复制完整参数对象并只覆盖 `value`。
21
+
22
+ `required` 是本地 DSL 元数据,当前平台没有同名持久化字段;因此
23
+ `ParamRequired()` 会在本地导出校验时要求提供非空 `DefaultValue`,确保保存到平台后仍有可执行值。
24
+
25
+ ## 节点 params
26
+
27
+ | TaskNode.type | 结构化 DSL | 已确认 params |
28
+ |---|---|---|
29
+ | `DATASET` | `DatasetNode` | `datasetId/datasetName/dbAccount/dbType/dirPath/displayType/schemaSql/uniformResourceType/updateSql` |
30
+ | `SHELL` | `ShellNode` | 仅模型保留;8.2.0 后端未注册,CLI 拒绝保存 |
31
+ | `HTTP` | `HTTPNode` | `connectionConfig{type,url,headers,parameters,body,authentication}`,以及递归轮询配置 |
32
+ | `SQL` | `SQLNode` | `cnId/acId/sql/preSqlList/postSqlList/fieldConfigs` |
33
+ | `PARAMETER_ASSIGNMENT` | `ParameterAssignmentNode` | `dataSourceType/sql/fieldConfigs`;DATABASE 使用 `cnId/acId`,DATASET 使用 `dsId/dsName/dirPath/displayType` |
34
+ | `SWITCH` | `SwitchNode` | `switchResult.dependTaskList[]`,每项含 `nextNode/combineType/conditions` |
35
+ | `LOOP` | `LoopNode` | 仅模型保留;8.2.0 后端未注册,CLI 拒绝保存 |
36
+ | `SUB_PROCESS+PROCESS` | `SubWorkflowNode` / `SubTaskNode` | `subProcessId/subProcessName/subProcessParams/subProcessDynamicParams/runTimeParams` |
37
+
38
+ ## 关键语义
39
+
40
+ - `PARAMETER_ASSIGNMENT` 是查询结果列到数据驱动参数的映射,不是任意 key/value 赋值。
41
+ - DATASET 必须使用已有数据集的 `datasetId`。8.2.0 的 DATASET 执行器只会按 ID 触发 BI
42
+ 数据集刷新,不会根据 `datasetName + schemaSql` 创建数据集;需要创建/写入目标数据集时,
43
+ 应使用 DATAFLOW/DB_DATAFLOW 的输出节点。`DATA_SET_OFFLINE_DEV` 不能用于 DatasetNode:8.2.0
44
+ 会把刷新接口的文本响应当 JSON,CLI 会提前阻断并提示改用产出工作流的 SubWorkflowNode。
45
+ - 参数赋值的 `DATASET` 来源遵守 8.2.0 后端 SQL 执行契约。数据库直连数据集会返回 60006,
46
+ CLI 会提前阻断;查询 StarRocks 表请改用 `DATABASE` 来源。后端支持的非直连抽取/离线开发
47
+ 产出数据集可使用 `DATASET` 来源(这是 CLI 相对页面选择器的明确扩展),SQL 中表名为 `input1`。
48
+ - `SWITCH.nextNode` 必须是 Switch 的直接 DAG 下游节点。
49
+ - SHELL/LOOP 的字段模型供兼容导入和后续版本使用,不代表 8.2.0 可执行能力。
50
+ - Switch/条件 Loop 的 `combineType` 仅支持 `AND/OR`,FilterType 与 FieldType 必须是 BI
51
+ 条件评估接口支持的枚举,参数来源和值不能为空。
52
+ - `LOOP` 循环调用另一个工作流,不内嵌任意节点;模式为 `ITERATE` 或 `CONDITION`,
53
+ `maxLoopTimes` 为 2–500,默认 128;遍历项必须提供 `prop/type`。
54
+ - HTTP 当前确认 GET/POST。认证值只保存在权限为 0600 的 `task.json`;导入不把明文凭据复制到
55
+ `workflow.go`。
56
+ - SQL TaskNode 与数据流内部 `SQL_SCRIPT` 是两类节点。
57
+ - 无法满足当前合约的旧 payload 自动回退 `RawTask`,避免导入时虚构字段或破坏保存结果。
58
+
59
+ ## 外置文件
60
+
61
+ - SHELL: `script.sh`
62
+ - SQL / PARAMETER_ASSIGNMENT: `query.sql`
63
+ - HTTP: `body.json` 或 `body.txt`;递归请求体为 `recursion-body.txt`
64
+ - 所有路径必须位于对应节点目录内,禁止 `..` 或绝对路径逃逸。
@@ -17,9 +17,14 @@
17
17
  etl.go # DATAFLOW/DB_DATAFLOW 节点:guanetl DSL(可附 *.sql、node_*.json)
18
18
  script.py # PYTHON 节点:脚本正文
19
19
  python.json # PYTHON 节点:服务端字段透传(edit 生成,勿手改)
20
- task.json # RAW 透传节点:完整 TaskNode JSON
20
+ task.json # 0600/当前用户 ACL;RAW 透传节点为完整 TaskNode JSON
21
+ script.sh # SHELL 节点脚本
22
+ query.sql # SQL / PARAMETER_ASSIGNMENT 节点 SQL
23
+ body.json/body.txt # HTTP 请求体
21
24
  _wf_state.json # 系统状态(mode=workflow),不手改
22
- _parent_snapshot.json # 服务端快照,不手改
25
+ _parent_snapshot.json # 脱敏服务端快照,不手改
26
+ _parent_merge_snapshot.json # 0600/当前用户 ACL 的精确合并基线,不手改
27
+ .gitignore # 自动忽略含原始凭据的精确合并基线
23
28
  _layout.json # 节点画布坐标(edit 时保留线上坐标),可不存在
24
29
  _exported_workflow.json # export 派生产物,不手改
25
30
  ```
@@ -62,13 +67,42 @@ func DefineWorkflow() Workflow {
62
67
  | `DataflowNode(id, name, DataflowConfig, deps...)` | SUB_PROCESS(数据流) | `nodes/<id>/etl.go` |
63
68
  | `DBDataflowNode(id, name, DataflowConfig, deps...)` | SUB_PROCESS(DB 数据流,SQL 下推) | `nodes/<id>/etl.go` |
64
69
  | `PythonNode(id, name, PythonConfig, deps...)` | SECURE_PYTHON | `nodes/<id>/script.py`(+ `python.json` 透传) |
70
+ | `SubWorkflowNode(id, name, SubWorkflowConfig, deps...)` | SUB_PROCESS(子工作流) | 无(引用已存在的工作流 ID) |
71
+ | `DatasetNode(id, name, DatasetConfig, deps...)` | DATASET | `task.json` passthrough base |
72
+ | `ShellNode(id, name, ShellConfig, deps...)` | SHELL | 仅导入模型;8.2.0 不支持执行 |
73
+ | `HTTPNode(id, name, HTTPConfig, deps...)` | HTTP | `body.json/body.txt` + `task.json` base |
74
+ | `SQLNode(id, name, SQLConfig, deps...)` | SQL | `query.sql` + `task.json` base |
75
+ | `ParameterAssignmentNode(...)` | PARAMETER_ASSIGNMENT | `query.sql` + `task.json` base |
76
+ | `SwitchNode(...)` | SWITCH | `task.json` passthrough base |
77
+ | `LoopNode(...)` | LOOP | 仅导入模型;8.2.0 不支持执行 |
65
78
  | `RawTask(id, deps...)` | 任意(透传) | `nodes/<id>/task.json` |
66
79
 
67
80
  - `id`:节点目录名,也是 TaskNode 的 id。同一工作流内唯一,建议用 `python_1`、`dataflow_1`
68
81
  这类稳定短名;edit 回读的节点保留线上原 id。
69
82
  - `name`:节点显示名。**同一工作流内必须唯一**(后端 preTasks 依赖按名字引用)。
70
- - `RawTask` 不带 name 参数,名称从 `task.json` 的 `name` 字段读取。用于 DSL 未结构化建模的
71
- 节点类型(PARAMETER_ASSIGNMENT、SHELL、HTTP、SWITCH、旧版 PYTHON 等),除依赖外全部透传。
83
+ - `RawTask` 不带 name 参数,名称从 `task.json` 的 `name` 字段读取。用于未知类型或不符合当前
84
+ 结构化合约的旧 payload,除依赖外全部透传。
85
+ - `SubWorkflowNode` 用于编排工作流,见下文「编排工作流」一节。
86
+ - 8.2.0 的后端 TaskParameters 注册表不含 SHELL/LOOP,因此 CLI 会在创建、导出或保存时拒绝这两类节点;循环/脚本能力不能作为本版本 POC 的可用能力承诺。
87
+
88
+ ### 工作流参数与引用
89
+
90
+ ```go
91
+ return Workflow{
92
+ Name: "每日加工",
93
+ Params: []Param{
94
+ StringParam("biz_date", "${yyyy-MM-dd-1}", ParamDesc("业务日期")),
95
+ NumberParam("batch", 1),
96
+ },
97
+ Nodes: []*WfNode{node},
98
+ }
99
+ ```
100
+
101
+ `ParamRef("biz_date")`、`DynamicParamRef("system.biz")`、
102
+ `DataDrivenParamRef("result")` 和 `BuiltinParamRef("looptimes")` 只生成平台引用表达式,不在本地求值。
103
+ 平台持久化类型为 STRING/NUMBER/DATE;BoolParam 兼容 STRING,TimeParam 兼容 DATE。
104
+
105
+ 完整 TaskNode 字段见 `TASK_NODE_CONTRACTS.md`。
72
106
 
73
107
  ### 依赖与执行条件
74
108
 
@@ -163,8 +197,8 @@ print("rows:", len(result)) # print 输出会出现在任务日志里,可用
163
197
 
164
198
  ```bash
165
199
  guanwf export --dir <workdir> # 1. 导出验证 DSL
166
- guanwf save-draft --dir <workdir> # 2. 保存草稿(不影响已发布版本)
167
- guanwf run --dir <workdir> --node "<节点名>" --validate # 3. 校验运行
200
+ guanwf save-draft --dir <workdir> --confirm # 2. 保存草稿(不影响已发布版本)
201
+ guanwf run --dir <workdir> --node "<节点名>" --validate --confirm # 3. 校验运行
168
202
  ```
169
203
 
170
204
  `--validate` 的工作机制:
@@ -187,7 +221,7 @@ guanwf run --dir <workdir> --node "<节点名>" --validate # 3. 校验运行
187
221
  AI 应根据 dtypes/head 检查输出 schema 是否符合预期,确认后用 `save` 发布并正式
188
222
  `run`(正式运行才会真实创建输出数据集)。
189
223
 
190
- 如果校验中途断掉导致草稿仍带 stub,重新执行 `guanwf save-draft` 即可恢复(命令结束时
224
+ 如果校验中途断掉导致草稿仍带 stub,重新执行 `guanwf save-draft --confirm` 即可恢复(命令结束时
191
225
  会有显式警告)。
192
226
 
193
227
  `--validate` 必须搭配 `--node`(节点**显示名**不是 id),隐含 `--draft --wait --logs`。
@@ -197,6 +231,148 @@ AI 应根据 dtypes/head 检查输出 schema 是否符合预期,确认后用 `
197
231
  试运行失败时,根据日志区分:脚本语法/库缺失问题改 `script.py`;输入输出配置问题改
198
232
  `workflow.go`;平台/环境错误(如输出数据集注册失败)须排查环境,不要改本地源文件硬绕。
199
233
 
234
+ ## 编排工作流(子工作流节点)
235
+
236
+ 把一批已存在的作业工作流(每个作业产出数据集)按依赖串成一个主工作流统一调度。
237
+ 每个 `SubWorkflowNode` 引用一个已发布的作业工作流;主工作流运行时按依赖顺序触发
238
+ 各作业的子实例,任一作业失败则主实例失败(下游不再执行)。
239
+
240
+ ```go
241
+ func DefineWorkflow() Workflow {
242
+ // id 直接用被引用的工作流 ID,name 用作业名(同一工作流内唯一)
243
+ a := SubWorkflowNode("<工作流ID_A>", "作业A", SubWorkflowConfig{WorkflowID: "<工作流ID_A>"})
244
+ // data-dep: 销售明细 (dsId...) ← 依赖边注释标明依据
245
+ b := SubWorkflowNode("<工作流ID_B>", "作业B", SubWorkflowConfig{WorkflowID: "<工作流ID_B>"},
246
+ After(a))
247
+
248
+ return Workflow{
249
+ Name: "统一调度主流程",
250
+ Nodes: []*WfNode{a, b},
251
+ // 跨批次依赖声明:消费方刻意读生产方上一批(T-1)产物,不加执行顺序边
252
+ CrossBatch: []CrossBatchDep{
253
+ {Consumer: "作业B", Dataset: "<dsId>", Reason: "读上月快照"},
254
+ },
255
+ }
256
+ }
257
+ ```
258
+
259
+ 约束(export 校验):
260
+
261
+ - `SubWorkflowConfig.WorkflowID` 必填;同一编排中同一个工作流只能被一个节点引用。
262
+ - 不允许引用编排自身(自引用);嵌套编排如果形成运行时循环,`deps verify` 报 NESTED_CYCLE。
263
+ - `CrossBatch` 声明按 `Consumer`(节点显示名)+ `Dataset`(dsId)匹配,用于把
264
+ verify 的 MISSING_EDGE 降级为 INFO——表示"读旧数据"是刻意设计而不是漏了依赖边。
265
+
266
+ ### 依赖从哪里来:血缘,不是口头描述
267
+
268
+ 编排的依赖边应来自平台血缘(作业定义中的输入/输出数据集),用 `deps` 子命令自动推导
269
+ 和对账,不要凭文档/Excel 手写依赖:
270
+
271
+ ```bash
272
+ # 1) 从血缘自动生成编排草稿(推荐入口)
273
+ guanwf create --name "统一调度" --type ORCHESTRATION --parent-dir <dirId> --dir <workdir>
274
+ guanwf deps plan --search "<作业名模式>" --yes --dir <workdir> # 按名字搜索作业
275
+ guanwf deps plan --jobs <id1>,<id2>,... --dir <workdir> # 或显式指定工作流 ID
276
+ guanwf deps plan ... --hints hints.json # 附加人工提示
277
+ guanwf deps plan ... --force # 覆盖已有非骨架 workflow.go
278
+
279
+ # 2) 人工微调 workflow.go 后对账
280
+ guanwf export --dir <workdir>
281
+ guanwf deps verify --dir <workdir> # ERROR 必须修复;exit 1 表示有 ERROR
282
+ ```
283
+
284
+ `deps plan` 输出的 `workflow.go` 中每条 `After` 边带注释:`data-dep: <数据集>`(血缘推导)
285
+ 或 `hint: <原因>`(人工提示)。数据推不出顺序的作业归入"孤岛"层(无依赖边,仍纳入调度)。
286
+
287
+ hints.json 结构(全部可选):
288
+
289
+ ```json
290
+ {
291
+ "before": [
292
+ {"first": "作业A", "then": "作业B", "reason": "先清洗后汇总"}
293
+ ],
294
+ "cross_batch": [
295
+ {"consumer": "作业C", "dataset": "<dsId>", "reason": "读上一批快照"}
296
+ ],
297
+ "exclude": ["废弃作业X"]
298
+ }
299
+ ```
300
+
301
+ - `before`:加一条控制依赖边(血缘推不出来但业务要求先后)。
302
+ - `cross_batch`:声明跨批次读旧数据,plan 不会为它加边,且生成 `CrossBatch` 声明。
303
+ - `exclude`:从编排中剔除某些作业(按名或 ID)。
304
+ - 作业引用支持显示名或工作流 ID;重名时必须用 ID。
305
+
306
+ ### deps verify 检查项
307
+
308
+ | 级别 | 代码 | 含义 |
309
+ |---|---|---|
310
+ | ERROR | MISSING_EDGE | A 读 B 的产出但编排中没有 B→A 路径(若刻意读旧数据,声明 CrossBatch) |
311
+ | ERROR | DUP_PRODUCER | 同一数据集被多个作业产出(产权冲突,先收敛产出方) |
312
+ | ERROR | REF_NOT_FOUND | 引用的作业工作流不存在(已删除/ID 错误) |
313
+ | ERROR | SELF_REF / NESTED_CYCLE | 自引用 / 嵌套编排成环 |
314
+ | WARN | NAME_MISMATCH | 节点显示名与线上工作流名不一致(edit 后重命名过) |
315
+ | WARN | PENDING_OUTPUT | 作业输出数据集尚未物化(从未成功运行过),血缘对账不完整 |
316
+ | WARN | UNUSED_CROSS | CrossBatch 声明没有匹配到任何血缘(可能写错 Consumer/Dataset) |
317
+ | INFO | CROSS_BATCH | 已声明的跨批次依赖(对账通过) |
318
+ | INFO | CONTROL_DEP | 依赖边没有血缘支撑(纯控制依赖,确认是否刻意) |
319
+
320
+ 血缘提取覆盖:Python 节点(inputDatasets / outputDatasets)、数据流节点(actions 中的
321
+ INPUT_DATASET / OUTPUT_DATASET / INCREMENT_OUTPUT_DATASET)、嵌套子工作流(递归展开)。
322
+ 作业定义拉取结果缓存在 `<workdir>/_deps_cache.json`(10 分钟 TTL),`--refresh` 强制重新拉取。
323
+
324
+ ### 编排的运行与失败语义
325
+
326
+ - `guanwf run --wait --dir <workdir> --confirm` 运行主工作流,按边的顺序触发各作业子实例。
327
+ - 子作业失败 → 主实例失败,其 `After` 下游不执行;已成功的作业产出保留。
328
+ - 失败时 `run` 自动拉日志:失败的 SUB_PROCESS 节点 UI 日志为空,会自动下钻到
329
+ 子实例逐任务打印(含 Python traceback 脚本输出),无需手动定位子实例。
330
+ - **推荐修复方式(增量恢复)**:修好失败作业(在作业自己的工作目录里改、save),
331
+ 回编排目录 `guanwf run --recover --wait --confirm`——从恢复节点续跑;成功祖先和无关
332
+ 分支不重跑,但恢复节点的全部 DAG 后继会重跑(即使后继先前为 SUCCESS)。
333
+ - 整链重跑:`guanwf run --wait --confirm`(已成功作业也会重跑;作业输出是 OVERWRITE 时幂等)。
334
+ - 作业节点的重试/超时用 `SubWorkflowConfig` 所在 TaskNode 的通用字段(edit 回读后在
335
+ task 层,当前 DSL 不展开;需要精细重试策略时在作业工作流内部配)。
336
+
337
+ ### run --recover 的平台语义
338
+
339
+ `--recover` 找到最近一次 FAILURE 实例并自底向上恢复:
340
+
341
+ 1. 列出恢复节点(FAILURE / STOP / KILL / NEED_FAULT_TOLERANCE);对其中的
342
+ SUB_PROCESS 节点,经 `select-sub-process` 定位子实例。
343
+ 2. 递归先恢复子实例(`execute` + `START_FAILURE_TASK_PROCESS` + `update=true`,
344
+ 使子实例吸收作业最新发布定义——否则会用失败时的旧定义快照重跑)。
345
+ 3. 子实例成功后恢复父实例。8.2.0 会重跑恢复节点及其全部 DAG 后继;成功祖先和
346
+ 无关分支保留原状态。
347
+
348
+ 最外层实例只有传 `--wait` 才等待完成;嵌套 PROCESS 子实例为保证自底向上顺序始终等待。
349
+ `guanwf instance resume-failed <instanceId> --wait --timeout 900 --confirm` 可对指定实例使用
350
+ 相同恢复器并调整长任务超时。若子工作流引用已从 A 改为 B,CLI 会阻止复用 A 的旧实例,
351
+ 应直接新运行整条工作流。
352
+
353
+ 限制:只有 FAILURE 状态的最近实例可恢复;若编排 DAG 结构已变更(加减节点/改依赖),
354
+ 平台 `checkProcessChange` 会拒绝,此时直接 `guanwf run --confirm` 重跑整链。
355
+ 不可与 `--node` / `--draft` / `--validate` 同用。
356
+
357
+ ### 编排的定时调度
358
+
359
+ ```bash
360
+ guanwf schedule info --dir <workdir>
361
+ guanwf schedule set --cron "0 0 2 * * ?" --dir <workdir> --confirm # 创建/更新并上线
362
+ guanwf schedule set --cron "0 0 2 * * ?" --param biz_date=2026-07-14 --dir <workdir> --confirm
363
+ guanwf schedule set --cron "0 0 2 * * ?" --offline --dir <workdir> --confirm # 只保存不上线
364
+ guanwf schedule event set --rule <datasetId>:<taskName> --param biz_date=2026-07-14 --dir <workdir> --confirm
365
+ guanwf schedule enable --dir <workdir> --confirm
366
+ guanwf schedule disable --dir <workdir> --confirm
367
+ ```
368
+
369
+ - crontab 为 Quartz 表达式(秒 分 时 日 月 周 [年]),服务端校验合法性。
370
+ - `--failure-strategy CONTINUE|END`:某作业失败后,无依赖关系的其他分支是否继续(默认 CONTINUE)。
371
+ - `--warning NONE|SUCCESS|FAILURE|ALL`:告警时机(默认 FAILURE)。
372
+ - `--auto-cancel-queued`:上一批未跑完时自动取消堆积的排队实例(长链路编排建议开启)。
373
+ - 已有调度时未指定的参数保留现状;只调度主工作流,被编排的作业自身不要再配调度
374
+ (避免同一作业被两条链路并发触发)。
375
+
200
376
  ## 命令闭环
201
377
 
202
378
  ### 新建工作流
@@ -206,12 +382,13 @@ guanwf create --name "我的工作流" --parent-dir <工作流目录ID> --dir <w
206
382
  # 默认生成数据流节点骨架: workflow.go + nodes/dataflow_1/etl.go
207
383
  # --type PYTHON 生成 Python 节点骨架: workflow.go + nodes/python_1/script.py
208
384
  # --type DB_DATAFLOW 生成数据库数据流骨架
385
+ # --type ORCHESTRATION 生成编排骨架(无初始节点,配合 deps plan 使用)
209
386
 
210
387
  # 编辑 workflow.go 和节点源文件后:
211
388
  guanwf export --dir <workdir>
212
- guanwf save-draft --dir <workdir>
213
- guanwf run --dir <workdir> --node "<节点名>" --validate # 校验(不创建真实输出数据集)
214
- guanwf save --dir <workdir> # 正式发布
389
+ guanwf save-draft --dir <workdir> --confirm
390
+ guanwf run --dir <workdir> --node "<节点名>" --validate --confirm # 校验(不创建真实输出数据集)
391
+ guanwf save --dir <workdir> --confirm # 正式发布
215
392
  ```
216
393
 
217
394
  新增数据流节点时:`mkdir -p nodes/<节点ID>`,创建 `nodes/<节点ID>/etl.go`(guanetl DSL,
@@ -225,7 +402,7 @@ guanwf edit <workflowId> --dir <workdir>
225
402
 
226
403
  回读生成:
227
404
 
228
- - `workflow.go`:节点 + 依赖结构(PARAMETER_ASSIGNMENT 等未建模类型生成 `RawTask` + 注释)
405
+ - `workflow.go`:节点 + 依赖结构(当前合约外或不满足结构化校验的节点生成 `RawTask` + 注释)
229
406
  - 数据流节点 → `nodes/<id>/etl.go`(经 guanetl json2go,SQL 外置为 `*.sql`)
230
407
  - Python 节点 → `nodes/<id>/script.py` + `nodes/<id>/python.json`
231
408
  - 其他节点 → `nodes/<id>/task.json`
@@ -236,13 +413,16 @@ guanwf edit <workflowId> --dir <workdir>
236
413
  ### 运行
237
414
 
238
415
  ```bash
239
- guanwf run --dir <workdir> # 触发整个工作流(已发布版本)
240
- guanwf run --dir <workdir> --wait # 等待完成
241
- guanwf run --dir <workdir> --wait --logs # 完成后输出任务日志
242
- guanwf run --dir <workdir> --node "<节点名>" --validate # 校验运行(不创建输出数据集)
243
- guanwf run --dir <workdir> --node "<节点名>" --draft --wait --logs # 单节点真实运行草稿
416
+ guanwf run --dir <workdir> --confirm # 触发整个工作流(已发布版本)
417
+ guanwf run --dir <workdir> --wait --confirm # 等待完成
418
+ guanwf run --dir <workdir> --wait --logs --confirm # 完成后输出任务日志
419
+ guanwf run --dir <workdir> --node "<节点名>" --validate --confirm # 校验运行(不创建输出数据集)
420
+ guanwf run --dir <workdir> --node "<节点名>" --draft --wait --logs --confirm # 单节点真实运行草稿
244
421
  ```
245
422
 
423
+ `run` 会创建线上执行实例,升级后必须显式传 `--confirm`(兼容别名 `--yes`);
424
+ 自动化脚本可先执行 `--dry-run` 检查目标、参数和请求计划。
425
+
246
426
  ### 预览数据流节点
247
427
 
248
428
  ```bash
@@ -260,11 +440,11 @@ Python 节点没有 preview API,校验用 `run --node "<节点名>" --validate
260
440
  1. 读取 `_exported_workflow.json`(必须由 `export` 重新生成)
261
441
  2. 从服务端拉取父工作流最新版本作为基底
262
442
  3. tasks 按节点 id 做字段级合并:本地定义的字段覆盖,服务端独有字段(dsId、运行时注册信息等)保留
263
- 4. 节点成员按三方判断(服务端最新 + 本地 `_parent_snapshot.json` + 本地导出):
443
+ 4. 节点成员按三方判断(服务端最新 + 本地 `_parent_merge_snapshot.json` + 本地导出):
264
444
  本地快照里有、导出里删了的节点 → 删除;服务端有、本地快照不知道的节点(他人并发新增)→
265
445
  保留并打印提示
266
446
  5. dataflowJson 按 dataflow id 经 etlmerge 做 actions 字段级合并(成员判断同上)
267
- 6. 保存成功后刷新本地 `_parent_snapshot.json`,并把服务端回写的 Python 参数同步进 `python.json`
447
+ 6. 保存成功后刷新本地脱敏 `_parent_snapshot.json` 与受限权限 `_parent_merge_snapshot.json`,并把服务端回写的 Python 参数同步进 `python.json`
268
448
 
269
449
  因此多人/多端并发修改同一工作流时,以服务端最新版本为基底合并,不会把别人新加的节点冲掉;
270
450
  但同一节点的并发修改仍是后保存者覆盖。