ai-workflow-flow-dsl-reference 0.1.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.
Files changed (64) hide show
  1. package/dist/index.d.ts +8 -0
  2. package/dist/index.js +18 -0
  3. package/dist/resource-module/KindDefinitions/WikiPage/manifest.xnl +10 -0
  4. package/dist/resource-module/WikiPages/README/manifest.xnl +6 -0
  5. package/dist/resource-module/WikiPages/foundation__depa-axioms/manifest.xnl +6 -0
  6. package/dist/resource-module/WikiPages/foundation__naming-axioms/manifest.xnl +6 -0
  7. package/dist/resource-module/WikiPages/foundation__syntax-axioms/manifest.xnl +6 -0
  8. package/dist/resource-module/WikiPages/spec__ai-workflow__ctrl-workflow/manifest.xnl +6 -0
  9. package/dist/resource-module/WikiPages/spec__ai-workflow__data-workflow/manifest.xnl +6 -0
  10. package/dist/resource-module/WikiPages/spec__ai-workflow__resources/manifest.xnl +6 -0
  11. package/dist/resource-module/WikiPages/spec__bp-ctrl-flow__domains/manifest.xnl +6 -0
  12. package/dist/resource-module/WikiPages/spec__bp-ctrl-flow__nodes/manifest.xnl +6 -0
  13. package/dist/resource-module/WikiPages/spec__eager-data-flow__domains/manifest.xnl +6 -0
  14. package/dist/resource-module/WikiPages/spec__eager-data-flow__files/manifest.xnl +6 -0
  15. package/dist/resource-module/WikiPages/spec__eager-data-flow__nodes/manifest.xnl +6 -0
  16. package/dist/resource-module/WikiPages/spec__eager-data-flow__refs/manifest.xnl +6 -0
  17. package/dist/resource-module/WikiPages/spec__flow-core__domains/manifest.xnl +6 -0
  18. package/dist/resource-module/WikiPages/spec__flow-core__files/manifest.xnl +6 -0
  19. package/dist/resource-module/WikiPages/spec__flow-core__nodes/manifest.xnl +6 -0
  20. package/dist/resource-module/WikiPages/spec__flow-core__orchestration/manifest.xnl +6 -0
  21. package/dist/resource-module/WikiPages/spec__flow-core__refs/manifest.xnl +6 -0
  22. package/dist/resource-module/WikiPages/spec__instant-ctrl-flow__domains/manifest.xnl +6 -0
  23. package/dist/resource-module/WikiPages/spec__instant-ctrl-flow__nodes/manifest.xnl +6 -0
  24. package/dist/resource-module/WikiPages/spec__work-ctrl-flow__domains/manifest.xnl +6 -0
  25. package/dist/resource-module/WikiPages/spec__work-ctrl-flow__nodes/manifest.xnl +6 -0
  26. package/dist/resource-module/WikiPages/std__ai-ctrl-workflow__axioms/manifest.xnl +6 -0
  27. package/dist/resource-module/WikiPages/std__ai-data-workflow__axioms/manifest.xnl +6 -0
  28. package/dist/resource-module/WikiPages/std__behavior-tree__axioms/manifest.xnl +6 -0
  29. package/dist/resource-module/WikiPages/std__bp-ctrl-flow__axioms/manifest.xnl +6 -0
  30. package/dist/resource-module/WikiPages/std__eager-data-flow__axioms/manifest.xnl +6 -0
  31. package/dist/resource-module/WikiPages/std__instant-ctrl-flow__axioms/manifest.xnl +6 -0
  32. package/dist/resource-module/WikiPages/std__work-ctrl-flow__axioms/manifest.xnl +6 -0
  33. package/dist/resource-module/content/.depa-flow-dsl-provenance.json +127 -0
  34. package/dist/resource-module/content/README.md +164 -0
  35. package/dist/resource-module/content/foundation/depa-axioms.md +41 -0
  36. package/dist/resource-module/content/foundation/naming-axioms.md +167 -0
  37. package/dist/resource-module/content/foundation/syntax-axioms.md +60 -0
  38. package/dist/resource-module/content/spec/ai-workflow/ctrl-workflow.md +53 -0
  39. package/dist/resource-module/content/spec/ai-workflow/data-workflow.md +78 -0
  40. package/dist/resource-module/content/spec/ai-workflow/resources.md +242 -0
  41. package/dist/resource-module/content/spec/bp-ctrl-flow/domains.md +30 -0
  42. package/dist/resource-module/content/spec/bp-ctrl-flow/nodes.md +122 -0
  43. package/dist/resource-module/content/spec/eager-data-flow/domains.md +59 -0
  44. package/dist/resource-module/content/spec/eager-data-flow/files.md +68 -0
  45. package/dist/resource-module/content/spec/eager-data-flow/nodes.md +151 -0
  46. package/dist/resource-module/content/spec/eager-data-flow/refs.md +90 -0
  47. package/dist/resource-module/content/spec/flow-core/domains.md +39 -0
  48. package/dist/resource-module/content/spec/flow-core/files.md +50 -0
  49. package/dist/resource-module/content/spec/flow-core/nodes.md +203 -0
  50. package/dist/resource-module/content/spec/flow-core/orchestration.md +161 -0
  51. package/dist/resource-module/content/spec/flow-core/refs.md +78 -0
  52. package/dist/resource-module/content/spec/instant-ctrl-flow/domains.md +20 -0
  53. package/dist/resource-module/content/spec/instant-ctrl-flow/nodes.md +47 -0
  54. package/dist/resource-module/content/spec/work-ctrl-flow/domains.md +29 -0
  55. package/dist/resource-module/content/spec/work-ctrl-flow/nodes.md +90 -0
  56. package/dist/resource-module/content/std/ai-ctrl-workflow/axioms.md +31 -0
  57. package/dist/resource-module/content/std/ai-data-workflow/axioms.md +24 -0
  58. package/dist/resource-module/content/std/behavior-tree/axioms.md +72 -0
  59. package/dist/resource-module/content/std/bp-ctrl-flow/axioms.md +48 -0
  60. package/dist/resource-module/content/std/eager-data-flow/axioms.md +57 -0
  61. package/dist/resource-module/content/std/instant-ctrl-flow/axioms.md +37 -0
  62. package/dist/resource-module/content/std/work-ctrl-flow/axioms.md +54 -0
  63. package/dist/resource-module/manifest.xnl +9 -0
  64. package/package.json +29 -0
@@ -0,0 +1,167 @@
1
+ # L1 元公理 · 命名、寻址与制品组织
2
+
3
+ > 与领域无关的命名/引用/文件组织公理。任何基于 XNL 的 bundle 化 DSL 都遵守。编号 `M-N*`(Meta-Naming)。
4
+
5
+ ## M-N1 · 内容为真源,路径只是布局
6
+
7
+ 节点的身份、类别一律来自**文件内容**(根节点 tag + `#id`),绝不来自文件名或目录名。文件路径只是物理布局,可自由重组而不改变语义。
8
+
9
+ 推论:每个容器(一个可加载的制品、一个多文件单元)有且只有一个**入口清单**,统一命名 `manifest.xnl`。清单内根节点的 tag 决定容器类别,`#id` 决定容器身份。不允许用文件名编码类别(禁止 `page.xnl`/`component.xnl` 这类 kind-named 入口)。
10
+
11
+ ## M-N2 · 域组织与 entry 寻址分投影
12
+
13
+ 域名、文件名与域根 tag 描述**制品组织**;URI scheme 描述域内被引用的**单个 entry**。两者有关联但不做字符串机械等同:集合/复数词、facet 点分词、PascalCase tag 都不应泄漏进 scheme。
14
+
15
+ ```text
16
+ domain/file/root tag: commands / commands.xnl / <Commands>
17
+ entry URI scheme: command://#users.search
18
+
19
+ domain/file/root tag: config.def / config.def.xnl / <ConfigDef>
20
+ entry URI scheme: config-def://#users.search
21
+ ```
22
+
23
+ scheme 必须是单数 kebab-case,并符合:
24
+
25
+ ```text
26
+ ^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$
27
+ ```
28
+
29
+ `.` 可以留在 domain/file facet、FQN 与 `#id` 中,但不得出现在 scheme。每个 domain 到 entry scheme 的映射必须在其领域规范中显式登记。不可因为名称相近而臆造新 scheme。
30
+
31
+ ## M-N3 · def / seed 是域的 facet
32
+
33
+ 任何域 `X` 可以带两个伴生 facet:
34
+
35
+ - `X.def` — 描述 X 的**类型/形状**。
36
+ - `X.seed` — 描述 X 结构的**初始数据**。
37
+ - `X` 本身 — 当前声明/数据。
38
+
39
+ facet 是完整的域(独立文件、独立 entry scheme、独立节点),按 M-N2 分投影,与主域成对出现、允许缺省。这样“一个事物的类型”和“它的初值”用统一后缀表达,不为每种事物发明专属命名。
40
+
41
+ ## M-N4 · 统一 URI 引用
42
+
43
+ 一切跨节点引用是 URI,写在引号字符串里,分三类:
44
+
45
+ | 类 | 形态 | 寻址 | 例 |
46
+ |---|---|---|---|
47
+ | 物理 | `vfs://…` | 文件(`@/` 工作区根、`./` 当前目录、`../` 父目录) | `"vfs://@/shared/prefabs.xnl"`、`"vfs://./adapters/core.ts"` |
48
+ | 逻辑 | `<域名>://…` | 域内节点(默认容器私有,见领域层的私有性规则) | `"config://#api"`、`"config-def://#users-page"` |
49
+ | 注册表 | `<注册表名>://…` | 由制品结构派生的具名注册表(如单元表、路由表) | `"page://org.app.UsersPage"`、`"route://#users-route"` |
50
+
51
+ URI 三种寻址形态:
52
+
53
+ ```text
54
+ <scheme>://<path> 层级路径寻址 "route://reports/:id"
55
+ <scheme>://#<id> 节点 id 寻址(域内唯一) "scope://#users-filter"
56
+ <scheme>://#<id>/<sub-path> 锚定 id 后走结构路径 "config://#users-filter/keywordInput"
57
+ ```
58
+
59
+ 逐条展开:
60
+
61
+ - **`#id` 寻址**是最常用形态:定位某域中 `#id` 节点本身。`"config://#api"` = config 域里 `<ConfigEntry #api>` 整个节点。
62
+ - **`#id/<sub-path>` 寻址**在锚定节点后继续走**属性结构**:`"config://#api/baseUrl"` = `<ConfigEntry #api { baseUrl = "/api" }>` 里的 `baseUrl` 值;多级用 `/` 连(`"config://#users-filter/keywordInput/placeholder"`)。
63
+ - **`<path>` 寻址**用于本身有层级结构的域(如路由树按 path 匹配:`"route://reports/:id"`)。
64
+
65
+ 分隔符职责固定:**`.` 只做名字空间分隔**(FQN 段、域 facet 段),**`-` 连接 scheme 中的多个词**,**`/` 只做结构层级分隔**。对比:`"config-def://#users-page"` 中 `-` 是 scheme 词间连接,`"config://#api/baseUrl"` 中 `/` 是下钻一层属性——两个符号永不互换职责。
66
+
67
+ scheme 集合 = 明确登记的 domain-entry 映射 + 注册表名 + `vfs`。**引用必须写在引号字符串里**——`:` 不是 XNL identifier 字符,裸写 `ref = config://#x` 是语法错误。
68
+
69
+ ### 解析边界
70
+
71
+ URI 解析必须先确定"从哪个容器看出去":
72
+
73
+ - **逻辑 scheme 默认在当前容器内解析**:`"config://#api"` 命中的是当前 app / page / component 自己的 config 域,不会按全局搜索去找同名节点。
74
+ - **跨容器引用必须经显式通道**:要么经注册表 scheme 引用某个具名制品整体(如 `page://<FQN>`、`component://<FQN>`),要么经 `vfs://` import 共享文件。不要用逻辑 scheme 偷穿到别的容器内部。
75
+ - **注册表 scheme 的可见性由领域层定义**:L1 只规定它是结构派生的具名表;哪些注册表存在、键是什么、暴露何种公共契约,由 L2/L3 定。
76
+
77
+ 这条规则把"容器内部事实"与"可复用公共制品"分开:逻辑 URI 是私有域内引用,注册表 URI 是公开入口引用,物理 URI 是文件引用。
78
+
79
+ ## M-N5 · FQN 身份
80
+
81
+ 可跨容器复用的定义用**点分限定名(FQN)**作全局身份(`org.pkg.Name`,类比包名+类名)。FQN 写在定义根节点的 `#id` 上;引用处用 FQN 作 tag(M-S3 的点分档)或经注册表 scheme(M-N4)。FQN 与它所在的文件路径**相互独立**(M-N1)——移动文件不改 FQN,改文件名不影响引用。
82
+
83
+ ## M-N6 · 单/多文件同构
84
+
85
+ 一个容器/单元支持两种物理形态,语义完全等价(语法基础见 M-S4):
86
+
87
+ - **单文件**:域内联为 `( ... )` 区段节点 + 一个列表主体段。
88
+ - **多文件**:`manifest.xnl` 薄清单 + 每域一个 `<域名>.xnl` 文件;启用哪些域由**文件内容**(各域文件的根节点 tag)发现,不在清单上声明(M-N1 内容为真源)。
89
+
90
+ 单→多文件化是纯机械重构:`(...)` 区段节点原样搬进独立文件,所有引用零改动(M-N4 的逻辑寻址不感知物理布局)。
91
+
92
+ ## M-N7 · 节点二相:内联定义 or `ref` 引用
93
+
94
+ **每一个节点都有两种可互换的写法**,语义等价,任选其一:
95
+
96
+ 1. **内联定义**——把节点的属性/子节点直接写在原地。
97
+ 2. **`ref` 引用**——写一个**空壳 + `ref` 属性**,采用别处(同类型)已定义的节点:`<Scope ref="users-page">` 采用预定义的 `<Scope #users-page {…}>`。
98
+
99
+ `ref` 的值有两种形态,按目标位置选:
100
+ - **按名**(同域预定义):`ref="users-page"` —— 采用当前域内 `#users-page` 的定义。
101
+ - **按 URI**(需要显式定位时):`ref="scope://#users-page"` —— 用 M-N4 的 URI 定位;是否允许跨容器取决于 M-N4 的解析边界与领域层私有性规则。
102
+
103
+ 铁律(消除"Ref 又 ref"):
104
+ - **引用属性名统一为 `ref`**,不为每种节点发明 `xxxRef`(`scopeRef`/`contractRef`/`commandRef`…全部退役)。一个节点要引用什么,由它的 **tag** 表明(`<Scope ref=…>` 引用的必是 scope,`<Command ref=…>` 引用的必是 command),无需在属性名里重复类别。
105
+ - **不套包装节点**。要引用一个 command 或 event,写 `<Command ref="…">` / `<Event ref="…">`,**不是** `<MessageRef ref="…">`——后者用一个专门的"引用节点"去指向消息,是 tag 已能表达类别时的冗余(Ref 又 ref)。任何 `XxxRef` 包装 tag 都退役。
106
+ - **域绑定字段例外**:一个节点内**多个**指向不同域的绑定(如 Scope 绑定 config),用**裸名字段 + URI 值**(`config = "config://#x"`),因为它们是本节点的属性而非"采用另一个同类节点"。区别:`ref` 是"我就是那个节点",绑定字段是"我引用那个域的资源作为我的一个属性"。复杂依赖绑定(如 effect 实现)优先放入节点的 `()` 子区段。
107
+
108
+ **按 id 隐式关联**(第三种、免 `ref` 的手法):当定义与使用天然同 id 时,定义域中 `#foo` 的条目**自动**作用于结构中的 `#foo`,使用处连 `ref` 都不必写。用于契约↔元素这类一一对应关系。
109
+
110
+ 三种手法并排对照(同一个 Scope 的三种到位方式):
111
+
112
+ ```xnl
113
+ # 预定义(在 scopes 域里)
114
+ <Scope #users-page { config = "config://#users-page" }>
115
+
116
+ # ① 内联定义 —— 属性直接写在使用处,不进域
117
+ <Capsule #ad-hoc ( <Scope { config = "config://#ad-hoc" }> )>
118
+
119
+ # ② ref 引用 —— 空壳 + ref,采用预定义
120
+ <Capsule #users-filter ( <Scope ref="users-page"> )>
121
+
122
+ # ③ id 隐式关联(适用于契约类)—— 定义域 <ElementContract #users-filter> 自动作用于
123
+ # 树中 #users-filter 元素,使用处什么都不写
124
+ ```
125
+
126
+ 更多例子:
127
+
128
+ ```xnl
129
+ # ref 采用:Accepts/Sends 中这个节点本身就是一个 Command 或 Event
130
+ <Accepts [ <Command ref="command://#users.refresh"> ]>
131
+ <Sends [ <Event ref="event://#users.selected"> ]>
132
+
133
+ # 域绑定字段:Route 不是 Page;只是把 page 字段绑定到某个 Page 注册表条目
134
+ <Route #users-route { path = "/users" page = "page://dg.admin.basic.UsersPage" }>
135
+
136
+ # 物理引用:FuncEffect 不是采用另一个 FuncEffect 节点;只是把 type 字段绑定到代码类型入口
137
+ <FuncEffect #users.query { type = "vfs://./effects/users.effects.ts#UsersQueryEffect" }>
138
+ ```
139
+
140
+ 目标:同一份数据只有一处真源;"定义"与"引用"用 `ref` 的有无区分;类别用 tag 表达,不靠属性名或包装节点。
141
+
142
+ ## M-N8 · 数据自持
143
+
144
+ 一个节点的静态描述数据**内联在该节点上**(不寄存到别的域再引回来)。域之间只用引用表达**归属/绑定**关系,不表达数据搬运。
145
+
146
+ **裸值 vs 引用的分界**(判据只有一条:这份数据归谁所有):
147
+
148
+ - **归本节点所有的静态描述 → 内联裸值**。
149
+ - **指向其他节点的归属/绑定 → 引用**(M-N7 的 `ref` 或裸名 URI 字段)。
150
+ - 一个数据只在一处为真源。
151
+
152
+ ```xnl
153
+ # ✅ 正:effect binding 的类型入口归 binding 自己所有 —— 内联在节点属性上
154
+ <FuncEffect #users.query {
155
+ type = "vfs://./effects/users.effects.ts#UsersQueryEffect"
156
+ }>
157
+
158
+ # ❌ 反:把 effect binding 的类型入口寄存到 config 域,再从 binding 引回来 —— 寄存链
159
+ <ConfigEntry #effect-code { usersQuery = "vfs://./effects/users.effects.ts#UsersQueryEffect" }>
160
+ <FuncEffect #users.query { type = "config://#effect-code/usersQuery" }>
161
+ ```
162
+
163
+ 反例的问题:`type` 的真源漂到了 config 域(config 应只装静态开关/枚举/常量预设),读者要跨两个域拼出 binding 的全貌;改类型入口要去 config 改、但语义归属在 binding——职责错位。凡出现“A 的数据躺在 B 域、C 再引用回来”的链条,都违反本条。
164
+
165
+ ## M-N9 · 配置皆声明式 XNL
166
+
167
+ 制品内不允许 JSON/XML/YAML 等第二套配置入口——一切配置是 XNL(M-N2 的统一性前提)。可执行代码不是配置:纯函数脚本(`.ts` 等)以文件形式存在、经引用挂接(见 depa-axioms M-D3),但绝不内联进 XNL。
@@ -0,0 +1,60 @@
1
+ # L1 元公理 · XNL 语法层
2
+
3
+ > 这些公理直接源自 XNL 语法本身的特性,与任何领域无关。当前由 depa-flows 的 Flow DSL 遵守。
4
+ > 编号 `M-S*`(Meta-Syntax)。
5
+
6
+ ## M-S1 · 节点四段形态
7
+
8
+ XNL 节点完整形态:`<Tag #id 元数据 { 属性 } ( 单件段 ) [ 列表段 ]>`。各成分语义固定:
9
+
10
+ | 成分 | 承载 | 语法特性 |
11
+ |---|---|---|
12
+ | `Tag` | 节点类别 | 决定该节点如何被解释(见 M-S2) |
13
+ | `#id` | 节点身份 | 解析为 `Word{namespace, name}`,可点分(见 naming-axioms) |
14
+ | 元数据位 `key=value` | 系统级元信息 | 紧跟 tag/`#id` 之后、`{ }` 之前;承载 `apiVersion`/`version` 等系统级元数据,与业务属性分离 |
15
+ | `{ ... }` | 属性键值对 | 标量/内联结构数据(业务属性) |
16
+ | `( ... )` | 唯一的**子域概念** | 每种子域概念只出现一次;重复条目由该子域的复数容器承载 |
17
+ | `[ ... ]` | 直接、有序或可重复子节点 | 同 tag 可重复 |
18
+
19
+ `( ... )` 与 `[ ... ]` 顺序无关、各至多一次,可与 `{ ... }` 共存。
20
+
21
+ ## M-S2 · `()` 是子域,`[]` 是直接条目
22
+
23
+ `()` 不只是“不会重复的子节点”容器;它表达父节点拥有的**唯一子域概念**。同一个子域概念在 `()` 中只能出现一次。子域中若有多个同类条目,使用该概念的复数容器及其 `[]`:
24
+
25
+ ```xnl
26
+ <If #choose (
27
+ <Branches [
28
+ <Branch #active {
29
+ when = "vfs://./flow-code/route.ts#isActive"
30
+ } [
31
+ <Return #done { value = "active" }>
32
+ ]>
33
+ <Otherwise [
34
+ <Return #fallback { value = "inactive" }>
35
+ ]>
36
+ ]>
37
+ )>
38
+ ```
39
+
40
+ - `()`:`Branches`、`FlowContract`、`EffectBindings`、`Scope` 这类每父节点唯一的子域。
41
+ - `[]`:元素、语句、图节点、分支条目等父节点的直接顺序或可重复事实。
42
+ - 禁止为“凑层级”引入没有领域语义的 `<Block>`、`<Nodes>` 包装;根直接条目直接进入根 `[]`。
43
+
44
+ `()` 的 tag 去重是这一规则的语法保护,而不是把所有“单件节点”塞进去的理由。
45
+
46
+ ## M-S3 · tag 形态决定解析路径
47
+
48
+ 一个 DSL 应当让 **tag 的书写形态自身**携带"这个节点怎么解释"的信息,读者与 parser 无需查上下文:
49
+
50
+ | tag 形态 | 约定含义 |
51
+ |---|---|
52
+ | 小写裸词(`h1`、`div`) | 宿主原生/透传节点 |
53
+ | PascalCase 保留字 | DSL 结构节点(codec 白名单) |
54
+ | 点分限定名(`a.b.C`) | 注册表查找(引用其他定义) |
55
+
56
+ 具体每档映射到什么由领域层(L2)定;L1 只规定"形态分档"这条元规则。
57
+
58
+ ## M-S4 · 单件/列表段的物理可拆分性
59
+
60
+ 因为 `()` 里的节点是父节点的唯一子域,它可以**无损地外提为独立文件**(文件根节点 = 子域节点本身);`[]` 则承载该域的集合或直接条目。这条语法性质是“单文件 ⟷ 多文件同构”(见 naming-axioms M-N6)的语法基础:内联子域与拆出文件根**完全同型**,互转不改变语义或引用。
@@ -0,0 +1,53 @@
1
+ # L3 · AICtrlWorkflow profile
2
+
3
+ `AICtrlWorkflow` is the AI-facing WorkCtrlFlow profile. Use it when a run may wait for an agent, tool, human review, timer or other durable external signal.
4
+
5
+ ## Root shape
6
+
7
+ ```xnl
8
+ <AICtrlWorkflow #depa.examples.SupportReview apiVersion="depa.flows/v1" version="1.0.0" (
9
+ <FlowContract #depa.examples.SupportReview {
10
+ input = "vfs://./flow-code/agent.ts#SupportReviewInput"
11
+ output = "vfs://./flow-code/agent.ts#SupportReviewResult"
12
+ }>
13
+ ) [
14
+ <Run #draft-context {
15
+ src = "vfs://./flow-code/agent.ts#draftContext"
16
+ }>
17
+ <ExternalJob #agent-review {
18
+ signalKind = "ai.agent.reviewed"
19
+ signalKey = "support-review"
20
+ }>
21
+ <Return #done {
22
+ src = "vfs://./flow-code/agent.ts#toResult"
23
+ }>
24
+ ]>
25
+ ```
26
+
27
+ ## Statements
28
+
29
+ `AICtrlWorkflow` accepts the WorkCtrlFlow statement surface:
30
+
31
+ - shared CtrlFlow statements such as `Run`, `If`, `Fallback`, `Retry`, `Timeout`, `Until`, `ForEach`, `Parallel`, `Race`, `CallFlow` and `Return`;
32
+ - WorkCtrlFlow interruptible statements such as `ExternalJob` and `Timer`.
33
+
34
+ It does not accept BPCtrlFlow-only `TaskStep` unless a future profile explicitly extends it.
35
+
36
+ ## Runtime AI context
37
+
38
+ Dynamic code receives the host runtime. AI-capable runtimes include an `ai` field with roots, state store and embedded effect provider. Effects are invoked by operation name:
39
+
40
+ ```ts
41
+ await runtime.ai.effects.invoke({
42
+ effectId: "effect-1",
43
+ operation: "ai.review",
44
+ input,
45
+ run,
46
+ nodeId: "draft-context",
47
+ materialRefs: ["resource://depa.examples.SupportReview.Materials"]
48
+ })
49
+ ```
50
+
51
+ ## State and recovery
52
+
53
+ Recovery is WorkCtrlFlow-backed. AICtrlWorkflow run records project WorkCtrlFlow snapshots into AI node records and open wait handles. Node positioning must use stable ids/invocation keys, not array index.
@@ -0,0 +1,78 @@
1
+ # L3 · AIDataWorkflow profile
2
+
3
+ `AIDataWorkflow` is the AI-facing EagerDataFlow profile. Use it when AI work is best represented as a DAG whose nodes can be patched, invalidated and reused inside a long-running run.
4
+
5
+ ## Root shape
6
+
7
+ ```xnl
8
+ <AIDataWorkflow #depa.examples.SupportEvidenceDag apiVersion="depa.flows/v1" version="1.0.0" (
9
+ <FlowContract #depa.examples.SupportEvidenceDag {
10
+ inputPorts = ["ticket"]
11
+ outputPorts = ["summary"]
12
+ }>
13
+ ) [
14
+ <EntryNode #entry>
15
+ <TransformNode #retrieve {
16
+ inputs = { ticket = "flow-port://#entry/ticket" }
17
+ outputs = ["evidence"]
18
+ src = "vfs://./flow-code/evidence.ts#retrieveEvidence"
19
+ }>
20
+ <TransformNode #summarize {
21
+ inputs = { evidence = "flow-port://#retrieve/evidence" }
22
+ outputs = ["summary"]
23
+ src = "vfs://./flow-code/evidence.ts#summarizeEvidence"
24
+ }>
25
+ <ReturnNode #return {
26
+ inputs = { summary = "flow-port://#summarize/summary" }
27
+ }>
28
+ ]>
29
+ ```
30
+
31
+ ## Nodes
32
+
33
+ `AIDataWorkflow` accepts the EagerDataFlow node surface:
34
+
35
+ - `EntryNode`
36
+ - `TransformNode`
37
+ - `SinkNode`
38
+ - `SubFlowNode`
39
+ - `ReturnNode`
40
+
41
+ `flow-port://#node/port` creates a data dependency. `flow-node://#node` creates a completion dependency through `waitFor`.
42
+
43
+ ## RunGraph state
44
+
45
+ The XNL definition produces an EagerDataFlow authoring plan. At run time, AIDataWorkflow creates a RunGraph with:
46
+
47
+ - node status and generation;
48
+ - patch history;
49
+ - transitive invalidation records;
50
+ - node-level reuse policy and semantic fingerprints.
51
+
52
+ Definition edits and RunGraph patches are separate surfaces. A run patch does not rewrite the XNL definition.
53
+
54
+ ## Reuse policy
55
+
56
+ Machine nodes default to `semantic-hash`; manual nodes default to `never`. Author a canonical manual node through AIDataWorkflow config:
57
+
58
+ ```xnl
59
+ <TransformNode #human-review {
60
+ inputs = { evidence = "flow-port://#retrieve/evidence" }
61
+ outputs = ["review"]
62
+ src = "vfs://./flow-code/evidence.ts#reviewEvidence"
63
+ config = { node_type = "manual" }
64
+ }>
65
+ ```
66
+
67
+ `node_type = "manual"` is AIDataWorkflow policy metadata. EagerDataFlow's legacy `type` field remains an implementation binding. A node may override its reuse policy with config such as:
68
+
69
+ ```xnl
70
+ <TransformNode #fresh-review {
71
+ inputs = { evidence = "flow-port://#retrieve/evidence" }
72
+ outputs = ["review"]
73
+ src = "vfs://./flow-code/evidence.ts#reviewEvidence"
74
+ config = { reuse_policy = "never" }
75
+ }>
76
+ ```
77
+
78
+ Semantic reuse is run-local. Generation is history metadata and is not part of the reuse fingerprint.
@@ -0,0 +1,242 @@
1
+ # L3 · Halfcode-backed AI workflow resources
2
+
3
+ AI workflow 资源以 Halfcode `ResourcePackage` 为通用 authority。Halfcode 负责 Catalog、KindDefinition、文件发现、URI containment、identity、provenance、layer composition 与 dependency snapshot;depa-flows 只读取规范化 `ResourceRecord`,投影 AI workflow 领域语义。
4
+
5
+ 这意味着 `AIWorkflowAppBundle` 仍然存在,但它不再拥有一套通用 `ResourceCatalog`。它只是工作流领域的 app projection:明确声明哪些 `AICtrlWorkflow` / `AIDataWorkflow` 属于该 app,以及哪些 workflow 是 entrypoint。
6
+
7
+ ## Authority pipeline
8
+
9
+ ```text
10
+ XNL ResourcePackage
11
+ -> halfcode-compiler.xnl/resource-core loadResourceTree
12
+ -> ResourceTree.registry / EffectiveResourceRegistry.byKind
13
+ -> depa-flows projectAIWorkflowAppBundles / projectAIWorkflowAgentResources
14
+ -> AIWorkflowAppBundleProjection / AIWorkflowAgentResourceProjection
15
+ -> depa-flows run-freeze (Node-only)
16
+ -> Halfcode ResourceDependencySnapshot
17
+ ```
18
+
19
+ 边界约束:
20
+
21
+ - depa-flows 不遍历资源目录、不解析第二份 Catalog、不从路径推导 identity。
22
+ - `ResourcePackage`、`Catalog`、`KindDefinition` 和通用 `vfs://` containment 的规范均由 Halfcode 维护。
23
+ - wrapper(例如 Eidolon)绑定真实 root,但 root policy 不进入 workflow definition。
24
+ - workflow projector 只检查明确的 `WorkflowBindings` 结构,不扫描 prompt、任意 property 或自然语言。
25
+
26
+ ## Package shape
27
+
28
+ AI workflow app 可以与其他资源一起放在标准 Halfcode package 中:
29
+
30
+ ```text
31
+ support-agent/
32
+ manifest.xnl # ResourcePackage(Halfcode authority)
33
+ KindDefinitions/
34
+ AIWorkflowAppBundle/manifest.xnl
35
+ AICtrlWorkflow/manifest.xnl
36
+ AIDataWorkflow/manifest.xnl
37
+ Apps/
38
+ SupportAgent.xnl # AIWorkflowAppBundle domain resource
39
+ CtrlWorkflows/
40
+ SupportAgent.xnl
41
+ DataWorkflows/
42
+ Evidence.xnl
43
+ ```
44
+
45
+ package 根、Catalog 和 KindDefinition 的完整写法以 Halfcode Resource DSL 为准。depa-flows 只拥有下面的 workflow Kind 内容契约。
46
+
47
+ ## AIWorkflowAppBundle
48
+
49
+ `WorkflowBindings[]` 保留 authoring 顺序。每个 `WorkflowBinding` 必须显式声明:
50
+
51
+ - `#id`:app 内唯一 binding id;
52
+ - `kind`:精确为 `AICtrlWorkflow` 或 `AIDataWorkflow`;
53
+ - `ref`:`resource://<resource-id>`;
54
+ - `entrypoint`:显式 boolean。
55
+
56
+ ```xnl
57
+ <AIWorkflowAppBundle #depa.flows.demo.SupportAgent apiVersion="depa.flows/v1" version="1.0.0" {
58
+ lifecycle = "Active"
59
+ description = "Support agent workflow app"
60
+ } (
61
+ <WorkflowBindings [
62
+ <WorkflowBinding #primary {
63
+ kind = "AICtrlWorkflow"
64
+ ref = "resource://depa.flows.demo.SupportAgent.Workflow"
65
+ entrypoint = true
66
+ }>
67
+ <WorkflowBinding #evidence {
68
+ kind = "AIDataWorkflow"
69
+ ref = "resource://depa.flows.demo.SupportAgent.Evidence"
70
+ entrypoint = false
71
+ }>
72
+ ]>
73
+ )>
74
+ ```
75
+
76
+ projector 会按 exact resource identity 在 Halfcode registry 中解析目标,并核对目标 record 的 kind。任一 binding 缺失、重复、目标不存在或 kind 不一致时,整个 projection fail closed;不会返回 partial app。
77
+
78
+ 至少一个 binding 必须是 entrypoint。entrypoint 是 workflow 领域语义,不会替代 Halfcode package root 或 Catalog。
79
+
80
+ ## AIAgentDefinition
81
+
82
+ `AIAgentDefinition` 是可复用 Agent 能力的资源定义,不是 Eidolon actor/session 配置,也不是新的 WorkCtrlFlow statement。它只通过固定 child nodes 声明资源关系:
83
+
84
+ - `Messages[]`:按 authoring 顺序保存 `Message`;`#id` 在 Agent 内唯一,`role` 精确为 `system | developer | user | assistant`,prompt 使用显式 `promptKind + promptRef`;
85
+ - `InputSchemaRef` / `OutputSchemaRef`:可选的单一 typed ref;
86
+ - `ToolRefs[]`:有序 `ToolRef`,每项显式 `kind + ref`;
87
+ - `EffectPolicyRef`:可选的单一 typed ref;
88
+ - `MaterialPortRefs[]`:有序 `MaterialPortRef`,目标 kind 固定为 `MaterialPort`。
89
+
90
+ ```xnl
91
+ <AIAgentDefinition #depa.flows.demo.Agent.Support apiVersion="depa.flows/v1" version="1.0.0" {
92
+ lifecycle = "Active"
93
+ description = "Support Agent definition"
94
+ } (
95
+ <Messages [
96
+ <Message #system {
97
+ role = "system"
98
+ promptKind = "Prompt"
99
+ promptRef = "resource://depa.flows.demo.Prompt.Support.System"
100
+ }>
101
+ <Message #user {
102
+ role = "user"
103
+ promptKind = "Prompt"
104
+ promptRef = "resource://depa.flows.demo.Prompt.Support.User"
105
+ } (
106
+ <SchemaRef { kind = "MessageSchema" ref = "resource://depa.flows.demo.Schema.Request" }>
107
+ )>
108
+ ]>
109
+ <InputSchemaRef { kind = "MessageSchema" ref = "resource://depa.flows.demo.Schema.Request" }>
110
+ <OutputSchemaRef { kind = "MessageSchema" ref = "resource://depa.flows.demo.Schema.Response" }>
111
+ <ToolRefs [
112
+ <ToolRef #lookup { kind = "Tool" ref = "resource://depa.flows.demo.Tool.Lookup" }>
113
+ ]>
114
+ <EffectPolicyRef { kind = "EffectPolicy" ref = "resource://depa.flows.demo.Policy.Safe" }>
115
+ <MaterialPortRefs [
116
+ <MaterialPortRef #request { kind = "MaterialPort" ref = "resource://depa.flows.demo.Port.Request" }>
117
+ ]>
118
+ )>
119
+ ```
120
+
121
+ projector 只读取这些固定位置。普通 prompt、description、metadata 或其他 property 中即使出现 URI 形式文本或业务词语,也不会产生 tool、policy、task 或 dependency edge。
122
+
123
+ ## MaterialPort and MaterialBinding
124
+
125
+ `MaterialPort` 定义 Agent 可消费的 material contract:
126
+
127
+ ```xnl
128
+ <MaterialPort #depa.flows.demo.Port.Request apiVersion="depa.flows/v1" version="1.0.0" {
129
+ materialKind = "RequestMaterial"
130
+ required = true
131
+ cardinality = "one"
132
+ } (
133
+ <SchemaRef { kind = "MessageSchema" ref = "resource://depa.flows.demo.Schema.Request" }>
134
+ )>
135
+ ```
136
+
137
+ `required` 必须是 boolean,`cardinality` 精确为 `one | many`。`SchemaRef` 可选。Agent 的 `MaterialPortRefs[]` 顺序是 run freeze 的 port 顺序 authority;`many` port 内多个 binding 再按 resource id 的固定 UTF-16 code-unit 顺序排列。
138
+
139
+ `MaterialBinding` 把一个精确 workflow node + Agent tuple 的 port 绑定到一个 material:
140
+
141
+ ```xnl
142
+ <MaterialBinding #depa.flows.demo.Binding.Request apiVersion="depa.flows/v1" version="1.0.0" {
143
+ lifecycle = "Active"
144
+ } (
145
+ <AgentTaskRef {
146
+ workflowKind = "AICtrlWorkflow"
147
+ workflowRef = "resource://depa.flows.demo.Workflow.Support"
148
+ nodeId = "collect-request"
149
+ agentDefinitionRef = "resource://depa.flows.demo.Agent.Support"
150
+ }>
151
+ <PortRef { kind = "MaterialPort" ref = "resource://depa.flows.demo.Port.Request" }>
152
+ <MaterialRef { kind = "RequestMaterial" ref = "resource://depa.flows.demo.Material.Request.001" }>
153
+ )>
154
+ ```
155
+
156
+ `AgentTaskRef` 只是资源选择 tuple,不新增 substrate node,也不包含 run id、session、generation、actor 或 provider。所有 ref 都按完整 resource identity 和目标 kind 精确核对;相似名称没有关联语义。
157
+
158
+ ## Typed dependency relations
159
+
160
+ depa-flows 只发出闭集 relation:
161
+
162
+ - `agent-message-prompt`、`agent-message-schema`;
163
+ - `agent-input-schema`、`agent-output-schema`;
164
+ - `agent-tool`、`agent-effect-policy`、`agent-material-port`;
165
+ - `material-port-schema`;
166
+ - `material-binding-port`、`material-binding-material`;
167
+ - run freeze 期间的 `workflow-agent-task`、`workflow-material-binding`。
168
+
169
+ Halfcode 验证 edge endpoints、计算 reachable closure 并生成 revision;depa-flows 不实现 generic dependency resolver。
170
+
171
+ ## Run resource freeze
172
+
173
+ 纯 projection 仍从 root/browser entry 导出:
174
+
175
+ ```ts
176
+ import { projectAIWorkflowAgentResources } from "ai-workflow-logic"
177
+
178
+ const projection = projectAIWorkflowAgentResources(effectiveRegistry)
179
+ ```
180
+
181
+ Node/server consumer 使用独立 entry,输入必须是同一个 authentic effective registry、由该 registry 产生的 exact projection,以及 Halfcode loader-owned content identities:
182
+
183
+ ```ts
184
+ import { freezeAIWorkflowRunResources } from "ai-workflow-logic/run-freeze"
185
+
186
+ const receipt = freezeAIWorkflowRunResources({
187
+ registry: effectiveRegistry,
188
+ projection,
189
+ task: {
190
+ workflowKind: "AICtrlWorkflow",
191
+ workflowRef: "resource://depa.flows.demo.Workflow.Support",
192
+ nodeId: "collect-request",
193
+ agentDefinitionRef: "resource://depa.flows.demo.Agent.Support",
194
+ },
195
+ contentIdentities,
196
+ })
197
+ ```
198
+
199
+ freeze 会检查 port 属于 Agent、required/cardinality 与 material kind,然后直接调用 Halfcode `buildResourceDependencySnapshot`。receipt 深度不可变,包含:
200
+
201
+ - exact task 与 ordered binding resource ids;
202
+ - 完整 Halfcode `ResourceDependencySnapshot`,用于 proof/recovery;
203
+ - `sha256:` domain semantic fingerprint,只绑定所选 task、Agent/Message/Tool/Policy/Port/Binding、participating edges 与 reachable content digest。
204
+
205
+ 完整 snapshot revision 会绑定 effective registry revision,因此未被选择的资源变化也可能改变 proof。domain semantic fingerprint 排除未被选择的资源以及 host run/session/generation/path facts;两者不得混用。
206
+
207
+ ## Public consumer API
208
+
209
+ 纯 projection 可用于 browser 或任何已取得 normalized registry 的 consumer:
210
+
211
+ ```ts
212
+ import { projectAIWorkflowAppBundles } from "ai-workflow-logic"
213
+
214
+ const apps = projectAIWorkflowAppBundles(effectiveRegistry)
215
+ const agentResources = projectAIWorkflowAgentResources(effectiveRegistry)
216
+ ```
217
+
218
+ 输入是 Halfcode public `Pick<ResourceRegistry, "byKind">` read port;`ResourceTree.registry` 与 `EffectiveResourceRegistry` 都可直接使用。
219
+
220
+ 需要从 filesystem root 加载时,使用单独的 Node entry:
221
+
222
+ ```ts
223
+ import { loadAIWorkflowResourcePackage } from "ai-workflow-logic/filesystem"
224
+
225
+ const loaded = await loadAIWorkflowResourcePackage({ rootDir: resourceRootDir })
226
+ ```
227
+
228
+ 该 adapter 直接调用 Halfcode `loadResourceTree`。depa-flows 没有 fallback scanner 或 containment 实现。`ai-workflow-logic/browser` 仍只导出纯 projector。
229
+
230
+ ## Compatibility surface
231
+
232
+ 早期发布的 `AIWorkflowResourceCatalog`、`AIWorkflowAppBundleManifest`、`AIWorkflowResourceRef` 和 ref helper 在 `0.1.x` 中保留为 deprecated compatibility surface,避免 patch upgrade 破坏既有 import。它们不再出现在 canonical authoring pipeline 中,新 Kind 不得扩展这些旧类型形成第二套 registry。
233
+
234
+ ## Facts and runtime state
235
+
236
+ - XNL ResourcePackage 和 ResourceRecord:Halfcode-owned authoring facts。
237
+ - AIWorkflowAppBundleProjection:可从 normalized records 重建的 depa domain projection,不反写 source。
238
+ - AIWorkflowAgentResourceProjection:固定 Agent/Message/Material 关系的可重建 depa domain projection,不是第二份 registry。
239
+ - AIWorkflowRunResourceFreezeReceipt:Halfcode snapshot proof + depa selected-resource semantic fingerprint;由运行 host 持久化但不回写 source。
240
+ - AICtrlWorkflow / AIDataWorkflow definition:workflow domain facts。
241
+ - workflow snapshot / RunGraph:运行态,不回写 ResourcePackage 或 app projection。
242
+ - global/workspace root、installation 与 actor/session runtime:host-owned facts,不属于 depa-flows。
@@ -0,0 +1,30 @@
1
+ # L3 · BPCtrlFlow 事实与域
2
+
3
+ > BPCtrlFlow 继承 [flow-core 事实与域](../flow-core/domains.md)和 [WorkCtrlFlow 持久事实](../work-ctrl-flow/domains.md),只增加 TaskSpace authoring/runtime facts。
4
+
5
+ ## Authoring Facts
6
+
7
+ | fact / domain | file | root / scheme | 说明 |
8
+ |---|---|---|---|
9
+ | `<BPCtrlFlow>` definition | 单文件或 `manifest.xnl` | 根 `[]` | 共享 CtrlFlow statements,可使用 `ExternalJob` / `Timer` / `TaskStep` |
10
+ | `state.def` / `state.seed` | 同 WorkCtrlFlow | 同 WorkCtrlFlow | 可选实例 state shape 与只读 seed |
11
+ | `task.space` | `task.space.xnl` | `<TaskSpace>` / `task-space://` | TaskGroup/Task 层级与初始任务事实 |
12
+
13
+ `task-space://#<id>` 只在当前 bundle 内解析,唯一公开消费者是 `TaskStep.task`。目标必须是 TaskSpace 的直接子节点;深层任务由所属 TaskGroup 的 executionMode 推进。
14
+
15
+ definition 中的 task status 只表示新实例初始值。运行期任务事实写 TaskSpace store,不能回写 authoring bundle;实例目录可提供只读投影,但投影不成为第二份事实源。
16
+
17
+ ## Runtime Ownership
18
+
19
+ | fact | owner | flow 可见性 |
20
+ |---|---|---|
21
+ | task status/owner/history/payload | TaskSpace store | TaskStep 完成时投影为 TaskStepResult data |
22
+ | TaskStep WaitHandle / applied signal | BPCtrlFlow snapshot | 只用于挂起、恢复与幂等 |
23
+ | TaskStepResult | CtrlFlow data chain | 成为下一条 statement 的 input |
24
+ | branch decision | BPCtrlFlow snapshot | 记录后复用,不重算已发生任务路径 |
25
+
26
+ TaskSpace store、snapshot 与 definition 三个 owner 不得互相复制语义真源。特别是 `Refused` / `Forwarded` 等任务状态投影成 data 后,不能再写成 engine Failure。
27
+
28
+ ## Rejected Authoring Facts
29
+
30
+ `tree.xnl`、`action.types.xnl`、`Tree` 根、独立 `CtrlFlow` 根以及公开 `Sequence` / `Selector` / `Condition` 都是已移除语法。TaskSpace 不允许用这些节点描述会签/或签;只能使用 TaskGroup 的 executionMode。