@kontourai/flow-agents 3.11.0 → 3.12.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 (247) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/build/src/builder-flow-run-adapter.d.ts +1 -0
  3. package/build/src/builder-flow-run-adapter.js +2 -0
  4. package/build/src/builder-flow-runtime.d.ts +5 -0
  5. package/build/src/builder-flow-runtime.js +90 -68
  6. package/build/src/builder-gate-action-envelope.d.ts +151 -0
  7. package/build/src/builder-gate-action-envelope.js +367 -0
  8. package/build/src/cli/public-contracts.d.ts +139 -0
  9. package/build/src/cli/public-contracts.js +37 -0
  10. package/build/src/cli/workflow-sidecar.js +9 -13
  11. package/build/src/cli/workflow.d.ts +1 -0
  12. package/build/src/cli/workflow.js +49 -12
  13. package/build/src/continuation-driver.d.ts +40 -3
  14. package/build/src/continuation-driver.js +361 -412
  15. package/build/src/continuation-persistence.d.ts +4 -0
  16. package/build/src/continuation-persistence.js +296 -0
  17. package/build/src/continuation-validation.d.ts +9 -0
  18. package/build/src/continuation-validation.js +139 -0
  19. package/build/src/flow-kit/action-metadata.d.ts +28 -0
  20. package/build/src/flow-kit/action-metadata.js +162 -0
  21. package/build/src/flow-kit/action-repository-validation.d.ts +16 -0
  22. package/build/src/flow-kit/action-repository-validation.js +237 -0
  23. package/build/src/flow-kit/validate.d.ts +2 -14
  24. package/build/src/flow-kit/validate.js +18 -345
  25. package/build/src/index.d.ts +4 -2
  26. package/build/src/index.js +2 -1
  27. package/dist/base/build/package.json +1 -1
  28. package/dist/base/build/src/builder-flow-run-adapter.d.ts +1 -0
  29. package/dist/base/build/src/builder-flow-run-adapter.js +2 -0
  30. package/dist/base/build/src/builder-flow-runtime.d.ts +5 -0
  31. package/dist/base/build/src/builder-flow-runtime.js +90 -68
  32. package/dist/base/build/src/builder-gate-action-envelope.d.ts +151 -0
  33. package/dist/base/build/src/builder-gate-action-envelope.js +367 -0
  34. package/dist/base/build/src/cli/public-contracts.d.ts +139 -0
  35. package/dist/base/build/src/cli/public-contracts.js +37 -0
  36. package/dist/base/build/src/cli/workflow-sidecar.js +9 -13
  37. package/dist/base/build/src/cli/workflow.d.ts +1 -0
  38. package/dist/base/build/src/cli/workflow.js +49 -12
  39. package/dist/base/build/src/continuation-driver.d.ts +40 -3
  40. package/dist/base/build/src/continuation-driver.js +361 -412
  41. package/dist/base/build/src/continuation-persistence.d.ts +4 -0
  42. package/dist/base/build/src/continuation-persistence.js +296 -0
  43. package/dist/base/build/src/continuation-validation.d.ts +9 -0
  44. package/dist/base/build/src/continuation-validation.js +139 -0
  45. package/dist/base/build/src/flow-kit/action-metadata.d.ts +28 -0
  46. package/dist/base/build/src/flow-kit/action-metadata.js +162 -0
  47. package/dist/base/build/src/flow-kit/action-repository-validation.d.ts +16 -0
  48. package/dist/base/build/src/flow-kit/action-repository-validation.js +237 -0
  49. package/dist/base/build/src/flow-kit/validate.d.ts +2 -14
  50. package/dist/base/build/src/flow-kit/validate.js +18 -345
  51. package/dist/base/build/src/index.d.ts +4 -2
  52. package/dist/base/build/src/index.js +2 -1
  53. package/dist/base/docs/public-workflow-cli.md +41 -5
  54. package/dist/base/docs/spec/builder-flow-runtime.md +117 -0
  55. package/dist/base/evals/integration/test_builder_step_producers.sh +60 -21
  56. package/dist/base/evals/integration/test_bundle_install.sh +15 -15
  57. package/dist/base/evals/integration/test_phase_map_and_gate_claim.sh +9 -22
  58. package/dist/base/install.sh +1 -1
  59. package/dist/base/kits/builder/kit.json +88 -14
  60. package/dist/claude-code/build/package.json +1 -1
  61. package/dist/claude-code/build/src/builder-flow-run-adapter.d.ts +1 -0
  62. package/dist/claude-code/build/src/builder-flow-run-adapter.js +2 -0
  63. package/dist/claude-code/build/src/builder-flow-runtime.d.ts +5 -0
  64. package/dist/claude-code/build/src/builder-flow-runtime.js +90 -68
  65. package/dist/claude-code/build/src/builder-gate-action-envelope.d.ts +151 -0
  66. package/dist/claude-code/build/src/builder-gate-action-envelope.js +367 -0
  67. package/dist/claude-code/build/src/cli/public-contracts.d.ts +139 -0
  68. package/dist/claude-code/build/src/cli/public-contracts.js +37 -0
  69. package/dist/claude-code/build/src/cli/workflow-sidecar.js +9 -13
  70. package/dist/claude-code/build/src/cli/workflow.d.ts +1 -0
  71. package/dist/claude-code/build/src/cli/workflow.js +49 -12
  72. package/dist/claude-code/build/src/continuation-driver.d.ts +40 -3
  73. package/dist/claude-code/build/src/continuation-driver.js +361 -412
  74. package/dist/claude-code/build/src/continuation-persistence.d.ts +4 -0
  75. package/dist/claude-code/build/src/continuation-persistence.js +296 -0
  76. package/dist/claude-code/build/src/continuation-validation.d.ts +9 -0
  77. package/dist/claude-code/build/src/continuation-validation.js +139 -0
  78. package/dist/claude-code/build/src/flow-kit/action-metadata.d.ts +28 -0
  79. package/dist/claude-code/build/src/flow-kit/action-metadata.js +162 -0
  80. package/dist/claude-code/build/src/flow-kit/action-repository-validation.d.ts +16 -0
  81. package/dist/claude-code/build/src/flow-kit/action-repository-validation.js +237 -0
  82. package/dist/claude-code/build/src/flow-kit/validate.d.ts +2 -14
  83. package/dist/claude-code/build/src/flow-kit/validate.js +18 -345
  84. package/dist/claude-code/build/src/index.d.ts +4 -2
  85. package/dist/claude-code/build/src/index.js +2 -1
  86. package/dist/claude-code/docs/public-workflow-cli.md +41 -5
  87. package/dist/claude-code/docs/spec/builder-flow-runtime.md +117 -0
  88. package/dist/claude-code/evals/integration/test_builder_step_producers.sh +60 -21
  89. package/dist/claude-code/evals/integration/test_bundle_install.sh +15 -15
  90. package/dist/claude-code/evals/integration/test_phase_map_and_gate_claim.sh +9 -22
  91. package/dist/claude-code/install.sh +1 -1
  92. package/dist/claude-code/kits/builder/kit.json +88 -14
  93. package/dist/codex/build/package.json +1 -1
  94. package/dist/codex/build/src/builder-flow-run-adapter.d.ts +1 -0
  95. package/dist/codex/build/src/builder-flow-run-adapter.js +2 -0
  96. package/dist/codex/build/src/builder-flow-runtime.d.ts +5 -0
  97. package/dist/codex/build/src/builder-flow-runtime.js +90 -68
  98. package/dist/codex/build/src/builder-gate-action-envelope.d.ts +151 -0
  99. package/dist/codex/build/src/builder-gate-action-envelope.js +367 -0
  100. package/dist/codex/build/src/cli/public-contracts.d.ts +139 -0
  101. package/dist/codex/build/src/cli/public-contracts.js +37 -0
  102. package/dist/codex/build/src/cli/workflow-sidecar.js +9 -13
  103. package/dist/codex/build/src/cli/workflow.d.ts +1 -0
  104. package/dist/codex/build/src/cli/workflow.js +49 -12
  105. package/dist/codex/build/src/continuation-driver.d.ts +40 -3
  106. package/dist/codex/build/src/continuation-driver.js +361 -412
  107. package/dist/codex/build/src/continuation-persistence.d.ts +4 -0
  108. package/dist/codex/build/src/continuation-persistence.js +296 -0
  109. package/dist/codex/build/src/continuation-validation.d.ts +9 -0
  110. package/dist/codex/build/src/continuation-validation.js +139 -0
  111. package/dist/codex/build/src/flow-kit/action-metadata.d.ts +28 -0
  112. package/dist/codex/build/src/flow-kit/action-metadata.js +162 -0
  113. package/dist/codex/build/src/flow-kit/action-repository-validation.d.ts +16 -0
  114. package/dist/codex/build/src/flow-kit/action-repository-validation.js +237 -0
  115. package/dist/codex/build/src/flow-kit/validate.d.ts +2 -14
  116. package/dist/codex/build/src/flow-kit/validate.js +18 -345
  117. package/dist/codex/build/src/index.d.ts +4 -2
  118. package/dist/codex/build/src/index.js +2 -1
  119. package/dist/codex/docs/public-workflow-cli.md +41 -5
  120. package/dist/codex/docs/spec/builder-flow-runtime.md +117 -0
  121. package/dist/codex/evals/integration/test_builder_step_producers.sh +60 -21
  122. package/dist/codex/evals/integration/test_bundle_install.sh +15 -15
  123. package/dist/codex/evals/integration/test_phase_map_and_gate_claim.sh +9 -22
  124. package/dist/codex/install.sh +1 -1
  125. package/dist/codex/kits/builder/kit.json +88 -14
  126. package/dist/kiro/build/package.json +1 -1
  127. package/dist/kiro/build/src/builder-flow-run-adapter.d.ts +1 -0
  128. package/dist/kiro/build/src/builder-flow-run-adapter.js +2 -0
  129. package/dist/kiro/build/src/builder-flow-runtime.d.ts +5 -0
  130. package/dist/kiro/build/src/builder-flow-runtime.js +90 -68
  131. package/dist/kiro/build/src/builder-gate-action-envelope.d.ts +151 -0
  132. package/dist/kiro/build/src/builder-gate-action-envelope.js +367 -0
  133. package/dist/kiro/build/src/cli/public-contracts.d.ts +139 -0
  134. package/dist/kiro/build/src/cli/public-contracts.js +37 -0
  135. package/dist/kiro/build/src/cli/workflow-sidecar.js +9 -13
  136. package/dist/kiro/build/src/cli/workflow.d.ts +1 -0
  137. package/dist/kiro/build/src/cli/workflow.js +49 -12
  138. package/dist/kiro/build/src/continuation-driver.d.ts +40 -3
  139. package/dist/kiro/build/src/continuation-driver.js +361 -412
  140. package/dist/kiro/build/src/continuation-persistence.d.ts +4 -0
  141. package/dist/kiro/build/src/continuation-persistence.js +296 -0
  142. package/dist/kiro/build/src/continuation-validation.d.ts +9 -0
  143. package/dist/kiro/build/src/continuation-validation.js +139 -0
  144. package/dist/kiro/build/src/flow-kit/action-metadata.d.ts +28 -0
  145. package/dist/kiro/build/src/flow-kit/action-metadata.js +162 -0
  146. package/dist/kiro/build/src/flow-kit/action-repository-validation.d.ts +16 -0
  147. package/dist/kiro/build/src/flow-kit/action-repository-validation.js +237 -0
  148. package/dist/kiro/build/src/flow-kit/validate.d.ts +2 -14
  149. package/dist/kiro/build/src/flow-kit/validate.js +18 -345
  150. package/dist/kiro/build/src/index.d.ts +4 -2
  151. package/dist/kiro/build/src/index.js +2 -1
  152. package/dist/kiro/docs/public-workflow-cli.md +41 -5
  153. package/dist/kiro/docs/spec/builder-flow-runtime.md +117 -0
  154. package/dist/kiro/evals/integration/test_builder_step_producers.sh +60 -21
  155. package/dist/kiro/evals/integration/test_bundle_install.sh +15 -15
  156. package/dist/kiro/evals/integration/test_phase_map_and_gate_claim.sh +9 -22
  157. package/dist/kiro/install.sh +1 -1
  158. package/dist/kiro/kits/builder/kit.json +88 -14
  159. package/dist/opencode/build/package.json +1 -1
  160. package/dist/opencode/build/src/builder-flow-run-adapter.d.ts +1 -0
  161. package/dist/opencode/build/src/builder-flow-run-adapter.js +2 -0
  162. package/dist/opencode/build/src/builder-flow-runtime.d.ts +5 -0
  163. package/dist/opencode/build/src/builder-flow-runtime.js +90 -68
  164. package/dist/opencode/build/src/builder-gate-action-envelope.d.ts +151 -0
  165. package/dist/opencode/build/src/builder-gate-action-envelope.js +367 -0
  166. package/dist/opencode/build/src/cli/public-contracts.d.ts +139 -0
  167. package/dist/opencode/build/src/cli/public-contracts.js +37 -0
  168. package/dist/opencode/build/src/cli/workflow-sidecar.js +9 -13
  169. package/dist/opencode/build/src/cli/workflow.d.ts +1 -0
  170. package/dist/opencode/build/src/cli/workflow.js +49 -12
  171. package/dist/opencode/build/src/continuation-driver.d.ts +40 -3
  172. package/dist/opencode/build/src/continuation-driver.js +361 -412
  173. package/dist/opencode/build/src/continuation-persistence.d.ts +4 -0
  174. package/dist/opencode/build/src/continuation-persistence.js +296 -0
  175. package/dist/opencode/build/src/continuation-validation.d.ts +9 -0
  176. package/dist/opencode/build/src/continuation-validation.js +139 -0
  177. package/dist/opencode/build/src/flow-kit/action-metadata.d.ts +28 -0
  178. package/dist/opencode/build/src/flow-kit/action-metadata.js +162 -0
  179. package/dist/opencode/build/src/flow-kit/action-repository-validation.d.ts +16 -0
  180. package/dist/opencode/build/src/flow-kit/action-repository-validation.js +237 -0
  181. package/dist/opencode/build/src/flow-kit/validate.d.ts +2 -14
  182. package/dist/opencode/build/src/flow-kit/validate.js +18 -345
  183. package/dist/opencode/build/src/index.d.ts +4 -2
  184. package/dist/opencode/build/src/index.js +2 -1
  185. package/dist/opencode/docs/public-workflow-cli.md +41 -5
  186. package/dist/opencode/docs/spec/builder-flow-runtime.md +117 -0
  187. package/dist/opencode/evals/integration/test_builder_step_producers.sh +60 -21
  188. package/dist/opencode/evals/integration/test_bundle_install.sh +15 -15
  189. package/dist/opencode/evals/integration/test_phase_map_and_gate_claim.sh +9 -22
  190. package/dist/opencode/install.sh +1 -1
  191. package/dist/opencode/kits/builder/kit.json +88 -14
  192. package/dist/pi/build/package.json +1 -1
  193. package/dist/pi/build/src/builder-flow-run-adapter.d.ts +1 -0
  194. package/dist/pi/build/src/builder-flow-run-adapter.js +2 -0
  195. package/dist/pi/build/src/builder-flow-runtime.d.ts +5 -0
  196. package/dist/pi/build/src/builder-flow-runtime.js +90 -68
  197. package/dist/pi/build/src/builder-gate-action-envelope.d.ts +151 -0
  198. package/dist/pi/build/src/builder-gate-action-envelope.js +367 -0
  199. package/dist/pi/build/src/cli/public-contracts.d.ts +139 -0
  200. package/dist/pi/build/src/cli/public-contracts.js +37 -0
  201. package/dist/pi/build/src/cli/workflow-sidecar.js +9 -13
  202. package/dist/pi/build/src/cli/workflow.d.ts +1 -0
  203. package/dist/pi/build/src/cli/workflow.js +49 -12
  204. package/dist/pi/build/src/continuation-driver.d.ts +40 -3
  205. package/dist/pi/build/src/continuation-driver.js +361 -412
  206. package/dist/pi/build/src/continuation-persistence.d.ts +4 -0
  207. package/dist/pi/build/src/continuation-persistence.js +296 -0
  208. package/dist/pi/build/src/continuation-validation.d.ts +9 -0
  209. package/dist/pi/build/src/continuation-validation.js +139 -0
  210. package/dist/pi/build/src/flow-kit/action-metadata.d.ts +28 -0
  211. package/dist/pi/build/src/flow-kit/action-metadata.js +162 -0
  212. package/dist/pi/build/src/flow-kit/action-repository-validation.d.ts +16 -0
  213. package/dist/pi/build/src/flow-kit/action-repository-validation.js +237 -0
  214. package/dist/pi/build/src/flow-kit/validate.d.ts +2 -14
  215. package/dist/pi/build/src/flow-kit/validate.js +18 -345
  216. package/dist/pi/build/src/index.d.ts +4 -2
  217. package/dist/pi/build/src/index.js +2 -1
  218. package/dist/pi/docs/public-workflow-cli.md +41 -5
  219. package/dist/pi/docs/spec/builder-flow-runtime.md +117 -0
  220. package/dist/pi/evals/integration/test_builder_step_producers.sh +60 -21
  221. package/dist/pi/evals/integration/test_bundle_install.sh +15 -15
  222. package/dist/pi/evals/integration/test_phase_map_and_gate_claim.sh +9 -22
  223. package/dist/pi/install.sh +1 -1
  224. package/dist/pi/kits/builder/kit.json +88 -14
  225. package/docs/public-workflow-cli.md +41 -5
  226. package/docs/spec/builder-flow-runtime.md +117 -0
  227. package/evals/integration/test_builder_step_producers.sh +60 -21
  228. package/evals/integration/test_bundle_install.sh +15 -15
  229. package/evals/integration/test_phase_map_and_gate_claim.sh +9 -22
  230. package/kits/builder/kit.json +88 -14
  231. package/package.json +1 -1
  232. package/src/builder-flow-run-adapter.ts +3 -0
  233. package/src/builder-flow-runtime.ts +73 -46
  234. package/src/builder-gate-action-envelope.ts +529 -0
  235. package/src/cli/builder-flow-runtime.test.mjs +287 -58
  236. package/src/cli/continuation-driver.test.mjs +527 -24
  237. package/src/cli/kit-metadata-security.test.mjs +161 -8
  238. package/src/cli/public-contracts.ts +41 -0
  239. package/src/cli/workflow-sidecar.ts +9 -13
  240. package/src/cli/workflow.ts +48 -12
  241. package/src/continuation-driver.ts +466 -378
  242. package/src/continuation-persistence.ts +228 -0
  243. package/src/continuation-validation.ts +107 -0
  244. package/src/flow-kit/action-metadata.ts +155 -0
  245. package/src/flow-kit/action-repository-validation.ts +192 -0
  246. package/src/flow-kit/validate.ts +19 -326
  247. package/src/index.ts +17 -0
@@ -1,6 +1,9 @@
1
1
  import fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { readJson } from "../lib/fs.js";
4
+ import { parseKitFlowStepActions, workflowTriggerIdentifier } from "./action-metadata.js";
5
+ import { validateActionRepositoryMetadata } from "./action-repository-validation.js";
6
+ export { isObservableBuilderArtifactRef, isSafeBuilderArtifactRef, parseKitFlowStepActions } from "./action-metadata.js";
4
7
  // Extension-only asset classes: validated by Flow Agents. Flows are validated by @kontourai/flow.
5
8
  const EXTENSION_ASSET_CLASSES = ["skills", "docs", "adapters", "evals", "assets"];
6
9
  // Core container fields owned by kontourai/flow (flow-kit-container.schema.json).
@@ -15,88 +18,6 @@ const AGENT_EXTENSION_CLASSES = new Set(["skills", "docs", "adapters", "evals",
15
18
  // and first_party is legacy catalog/marketplace metadata. It does not grant runtime
16
19
  // capability or steering privilege.
17
20
  const KNOWN_METADATA_FIELDS = new Set(["dependencies", "workflow_triggers", "hook_influence_expectations", "flow_step_actions", "skill_roles", "first_party"]);
18
- const MAX_FLOW_DEFINITION_BYTES = 1024 * 1024;
19
- function sameFileIdentity(left, right) {
20
- return left.dev === right.dev && left.ino === right.ino;
21
- }
22
- function lstatSafePath(root, relativePath) {
23
- const parts = relativePath.split(path.sep);
24
- let current = root;
25
- for (const [index, part] of parts.entries()) {
26
- if (!part || part === "." || part === "..")
27
- return { error: "path must stay inside the kit directory" };
28
- current = path.join(current, part);
29
- const stat = fs.lstatSync(current);
30
- if (stat.isSymbolicLink())
31
- return { error: "path must not traverse a symbolic link" };
32
- if (index < parts.length - 1 && !stat.isDirectory())
33
- return { error: "path component must be a directory" };
34
- if (index === parts.length - 1)
35
- return { file: current, stat };
36
- }
37
- return { error: "path must reference a regular file" };
38
- }
39
- function readSafeFlowDefinition(kitDir, relativePath) {
40
- const root = path.resolve(kitDir);
41
- if (path.isAbsolute(relativePath))
42
- return { error: "path must be relative" };
43
- const lexicalFile = path.resolve(root, relativePath);
44
- if (lexicalFile === root || !lexicalFile.startsWith(`${root}${path.sep}`))
45
- return { error: "path must stay inside the kit directory" };
46
- let rootDescriptor;
47
- let descriptor;
48
- try {
49
- const realRoot = fs.realpathSync.native(root);
50
- rootDescriptor = fs.openSync(realRoot, fs.constants.O_RDONLY | fs.constants.O_DIRECTORY);
51
- const rootIdentity = fs.fstatSync(rootDescriptor);
52
- if (!rootIdentity.isDirectory() || !sameFileIdentity(rootIdentity, fs.lstatSync(realRoot)))
53
- return { error: "kit directory identity changed while opening flow definition" };
54
- const initialPath = lstatSafePath(realRoot, relativePath);
55
- if (!initialPath.file || !initialPath.stat)
56
- return { error: initialPath.error };
57
- if (!initialPath.stat.isFile())
58
- return { error: "path must reference a regular file" };
59
- if (initialPath.stat.size > MAX_FLOW_DEFINITION_BYTES)
60
- return { error: `file exceeds ${MAX_FLOW_DEFINITION_BYTES} bytes` };
61
- // O_NOFOLLOW protects the terminal component. Identity checks before and after
62
- // opening make a race on any intermediate component fail closed on macOS/Node,
63
- // where openat-style traversal from a directory descriptor is not exposed.
64
- descriptor = fs.openSync(initialPath.file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
65
- const stat = fs.fstatSync(descriptor);
66
- if (!stat.isFile())
67
- return { error: "path must reference a regular file" };
68
- if (!sameFileIdentity(initialPath.stat, stat))
69
- return { error: "flow definition identity changed while opening" };
70
- if (stat.size > MAX_FLOW_DEFINITION_BYTES)
71
- return { error: `file exceeds ${MAX_FLOW_DEFINITION_BYTES} bytes` };
72
- const verifiedPath = lstatSafePath(realRoot, relativePath);
73
- if (!verifiedPath.stat || !sameFileIdentity(stat, verifiedPath.stat))
74
- return { error: "flow definition identity changed while opening" };
75
- const buffer = Buffer.alloc(stat.size);
76
- let offset = 0;
77
- while (offset < buffer.length) {
78
- const read = fs.readSync(descriptor, buffer, offset, buffer.length - offset, offset);
79
- if (read === 0)
80
- break;
81
- offset += read;
82
- }
83
- const finalStat = fs.fstatSync(descriptor);
84
- if (offset !== stat.size || finalStat.size !== stat.size || !sameFileIdentity(stat, finalStat))
85
- return { error: "file changed while being read" };
86
- return { definition: JSON.parse(buffer.toString("utf8")) };
87
- }
88
- catch (error) {
89
- if (error.code === "ELOOP")
90
- return { error: "path must not reference a symbolic link" };
91
- return { error: `path is not readable: ${error.message}` };
92
- }
93
- finally {
94
- if (descriptor !== undefined)
95
- fs.closeSync(descriptor);
96
- if (rootDescriptor !== undefined)
97
- fs.closeSync(rootDescriptor);
98
- }
99
- }
100
21
  /**
101
22
  * Parse and shape-validate a kit manifest's `dependencies` field (Flow Agents
102
23
  * extension-layer metadata; see docs/adr/0019-kit-dependency-ownership.md).
@@ -155,10 +76,6 @@ export function parseKitDependencies(manifest, manifestPath) {
155
76
  function nonEmptyStringList(value) {
156
77
  return Array.isArray(value) && value.length > 0 && value.every((item) => typeof item === "string" && item.trim().length > 0);
157
78
  }
158
- const WORKFLOW_TRIGGER_IDENTIFIER_RE = /^[a-z0-9]+(?:[.-][a-z0-9]+)*$/;
159
- function workflowTriggerIdentifier(value) {
160
- return typeof value === "string" && WORKFLOW_TRIGGER_IDENTIFIER_RE.test(value);
161
- }
162
79
  function optionalWorkflowTriggerIdentifier(value) {
163
80
  return value === undefined || workflowTriggerIdentifier(value);
164
81
  }
@@ -304,76 +221,6 @@ export function parseKitHookInfluenceExpectations(manifest, manifestPath) {
304
221
  });
305
222
  return { entries, errors };
306
223
  }
307
- export function parseKitFlowStepActions(manifest, manifestPath) {
308
- const entries = [];
309
- const errors = [];
310
- const raw = manifest.flow_step_actions;
311
- if (raw === undefined)
312
- return { entries, errors };
313
- if (!Array.isArray(raw)) {
314
- errors.push(`${manifestPath}: .flow_step_actions must be a list`);
315
- return { entries, errors };
316
- }
317
- const seen = new Set();
318
- raw.forEach((entry, index) => {
319
- if (typeof entry !== "object" || entry === null) {
320
- errors.push(`${manifestPath}: flow_step_actions[${index}] must be an object`);
321
- return;
322
- }
323
- const record = entry;
324
- if (!workflowTriggerIdentifier(record.flow_id)) {
325
- errors.push(`${manifestPath}: flow_step_actions[${index}].flow_id must be a Flow identifier`);
326
- return;
327
- }
328
- if (!workflowTriggerIdentifier(record.step_id)) {
329
- errors.push(`${manifestPath}: flow_step_actions[${index}].step_id must be a step identifier`);
330
- return;
331
- }
332
- const skills = record.skills;
333
- const operations = record.operations ?? [];
334
- const expectationIds = record.expectation_ids;
335
- const artifacts = record.artifacts ?? [];
336
- if (!Array.isArray(skills) || !skills.every(workflowTriggerIdentifier)) {
337
- errors.push(`${manifestPath}: flow_step_actions[${index}].skills must be an identifier list`);
338
- return;
339
- }
340
- if (new Set(skills).size !== skills.length) {
341
- errors.push(`${manifestPath}: flow_step_actions[${index}].skills must not contain duplicates`);
342
- return;
343
- }
344
- if (!Array.isArray(operations) || !operations.every(workflowTriggerIdentifier)) {
345
- errors.push(`${manifestPath}: flow_step_actions[${index}].operations must be an identifier list when present`);
346
- return;
347
- }
348
- if (new Set(operations).size !== operations.length) {
349
- errors.push(`${manifestPath}: flow_step_actions[${index}].operations must not contain duplicates`);
350
- return;
351
- }
352
- if (expectationIds !== undefined && (!Array.isArray(expectationIds) || !expectationIds.every(workflowTriggerIdentifier) || new Set(expectationIds).size !== expectationIds.length)) {
353
- errors.push(`${manifestPath}: flow_step_actions[${index}].expectation_ids must be a unique identifier list when present`);
354
- return;
355
- }
356
- if (!Array.isArray(artifacts) || !artifacts.every((artifact) => typeof artifact === "string" && artifact.trim().length > 0) || new Set(artifacts).size !== artifacts.length) {
357
- errors.push(`${manifestPath}: flow_step_actions[${index}].artifacts must be a unique non-empty string list when present`);
358
- return;
359
- }
360
- const key = `${record.flow_id}/${record.step_id}`;
361
- if (seen.has(key)) {
362
- errors.push(`${manifestPath}: flow_step_actions[${index}] duplicates '${key}'`);
363
- return;
364
- }
365
- seen.add(key);
366
- entries.push({
367
- flow_id: record.flow_id,
368
- step_id: record.step_id,
369
- skills: skills,
370
- operations: operations,
371
- artifacts: artifacts,
372
- ...(Array.isArray(expectationIds) ? { expectation_ids: expectationIds } : {}),
373
- });
374
- });
375
- return { entries, errors };
376
- }
377
224
  export function parseKitSkillRoles(manifest, manifestPath) {
378
225
  const entries = [];
379
226
  const errors = [];
@@ -556,15 +403,15 @@ export async function validateKitRepository(kitDir) {
556
403
  errors.push(`${manifestPath}: invalid JSON: ${error.message}`);
557
404
  return errors;
558
405
  }
559
- // Delegate core container validation (schema_version, id, name, flows including file
560
- // existence) to @kontourai/flow — the container contract lives once, in Flow.
561
- // This enforces the degradation invariant: a Flow Agents Kit must remain a valid
562
- // core Flow Kit container when extension fields are stripped.
563
- const coreErrors = await delegateCoreContainerValidation(kitDir, manifest);
564
- for (const err of coreErrors)
565
- errors.push(err);
566
- // Flow Agents extension validation: skills, docs, adapters, evals, assets.
567
- // Flows are validated above by @kontourai/flow; only extension classes are checked here.
406
+ errors.push(...await delegateCoreContainerValidation(kitDir, manifest));
407
+ errors.push(...validateExtensionAssets(kitDir, manifestPath, manifest));
408
+ errors.push(...validateAgentMetadata(kitDir, manifestPath, manifest));
409
+ if (manifest.first_party !== undefined && typeof manifest.first_party !== "boolean")
410
+ errors.push(`${manifestPath}: .first_party must be a boolean when present`);
411
+ return errors;
412
+ }
413
+ function validateExtensionAssets(kitDir, manifestPath, manifest) {
414
+ const errors = [];
568
415
  for (const section of EXTENSION_ASSET_CLASSES) {
569
416
  const entries = manifest[section];
570
417
  if (entries === undefined)
@@ -606,9 +453,10 @@ export async function validateKitRepository(kitDir) {
606
453
  }
607
454
  });
608
455
  }
609
- // Flow Agents metadata: cross-kit dependency declarations (extension-layer;
610
- // see docs/adr/0019-kit-dependency-ownership.md). Shape-only here — presence is
611
- // checked separately (non-blocking at install, hard error at activation).
456
+ return errors;
457
+ }
458
+ function validateAgentMetadata(kitDir, manifestPath, manifest) {
459
+ const errors = [];
612
460
  const depResult = parseKitDependencies(manifest, manifestPath);
613
461
  for (const err of depResult.errors)
614
462
  errors.push(err);
@@ -624,183 +472,8 @@ export async function validateKitRepository(kitDir) {
624
472
  const skillRoleResult = parseKitSkillRoles(manifest, manifestPath);
625
473
  for (const err of skillRoleResult.errors)
626
474
  errors.push(err);
627
- if (manifest.skill_roles !== undefined && skillRoleResult.errors.length === 0) {
628
- const declaredSkillIds = new Set(Array.isArray(manifest.skills)
629
- ? manifest.skills.flatMap((entry) => typeof entry === "object" && entry !== null && typeof entry.id === "string" ? [entry.id] : [])
630
- : []);
631
- const roleSkillIds = new Set(skillRoleResult.entries.map((entry) => entry.skill_id));
632
- for (const id of declaredSkillIds)
633
- if (!roleSkillIds.has(id))
634
- errors.push(`${manifestPath}: skill_roles is missing declared skill '${id}'`);
635
- for (const id of roleSkillIds)
636
- if (!declaredSkillIds.has(id))
637
- errors.push(`${manifestPath}: skill_roles references undeclared skill '${id}'`);
638
- const flows = new Map();
639
- if (Array.isArray(manifest.flows)) {
640
- for (const entry of manifest.flows) {
641
- if (typeof entry !== "object" || entry === null)
642
- continue;
643
- const flow = entry;
644
- if (typeof flow.id !== "string" || typeof flow.path !== "string")
645
- continue;
646
- const safeDefinition = readSafeFlowDefinition(kitDir, flow.path);
647
- if (!safeDefinition.definition) {
648
- errors.push(`${manifestPath}: flows '${flow.id}' ${safeDefinition.error}`);
649
- continue;
650
- }
651
- try {
652
- const definition = safeDefinition.definition;
653
- const steps = new Set(Array.isArray(definition.steps) ? definition.steps.flatMap((step) => typeof step === "object" && step !== null && typeof step.id === "string" ? [step.id] : []) : []);
654
- const usesFlowByStep = new Map();
655
- if (Array.isArray(definition.steps)) {
656
- for (const step of definition.steps) {
657
- if (typeof step !== "object" || step === null)
658
- continue;
659
- const stepRecord = step;
660
- if (typeof stepRecord.id === "string" && typeof stepRecord.uses_flow === "string")
661
- usesFlowByStep.set(stepRecord.id, stepRecord.uses_flow);
662
- }
663
- }
664
- const expectationsByStep = new Map();
665
- if (typeof definition.gates === "object" && definition.gates !== null) {
666
- for (const gate of Object.values(definition.gates)) {
667
- if (typeof gate !== "object" || gate === null)
668
- continue;
669
- const gateRecord = gate;
670
- if (typeof gateRecord.step !== "string" || !Array.isArray(gateRecord.expects))
671
- continue;
672
- const expectations = expectationsByStep.get(gateRecord.step) ?? new Map();
673
- for (const expectation of gateRecord.expects) {
674
- if (typeof expectation !== "object" || expectation === null)
675
- continue;
676
- const expectationRecord = expectation;
677
- if (typeof expectationRecord.id !== "string")
678
- continue;
679
- const exportKeys = new Set([expectationRecord.id]);
680
- const claimType = expectationRecord.bundle_claim?.claimType;
681
- if (typeof claimType === "string")
682
- exportKeys.add(claimType);
683
- expectations.set(expectationRecord.id, { id: expectationRecord.id, exportKeys });
684
- }
685
- expectationsByStep.set(gateRecord.step, expectations);
686
- }
687
- }
688
- flows.set(flow.id, {
689
- steps,
690
- expectationsByStep,
691
- usesFlowByStep,
692
- exports: new Set(Array.isArray(definition.exports) ? definition.exports.filter((entry) => typeof entry === "string" && entry.length > 0) : []),
693
- });
694
- }
695
- catch {
696
- // Core Flow validation reports missing or malformed definitions.
697
- }
698
- }
699
- }
700
- const resolveEffectiveFlowStep = (flowId, stepId, seen = new Set()) => {
701
- const cycleKey = `${flowId}\u0000${stepId}`;
702
- if (seen.has(cycleKey))
703
- return undefined;
704
- seen.add(cycleKey);
705
- const flow = flows.get(flowId);
706
- if (!flow)
707
- return undefined;
708
- const direct = flow.expectationsByStep.get(stepId);
709
- if (direct)
710
- return { sourceFlowId: flowId, stepId, expectations: direct, flowIds: new Set([flowId]) };
711
- const childFlowId = flow.usesFlowByStep.get(stepId);
712
- if (!childFlowId)
713
- return { sourceFlowId: flowId, stepId, expectations: new Map(), flowIds: new Set([flowId]) };
714
- const child = resolveEffectiveFlowStep(childFlowId, stepId, seen);
715
- const childFlow = flows.get(childFlowId);
716
- if (!child || !childFlow || [...child.expectations.values()].some((expectation) => ![...expectation.exportKeys].some((key) => childFlow.exports.has(key))))
717
- return undefined;
718
- child.flowIds.add(flowId);
719
- return child;
720
- };
721
- for (const row of skillRoleResult.entries) {
722
- if (!row.flow_id)
723
- continue;
724
- const flow = flows.get(row.flow_id);
725
- if (!flow) {
726
- errors.push(`${manifestPath}: skill_roles '${row.skill_id}' references unknown flow '${row.flow_id}'`);
727
- continue;
728
- }
729
- for (const stepId of row.step_ids)
730
- if (!flow.steps.has(stepId))
731
- errors.push(`${manifestPath}: skill_roles '${row.skill_id}' references unknown step '${row.flow_id}/${stepId}'`);
732
- const allowedExpectations = new Set(row.step_ids.flatMap((stepId) => [...(resolveEffectiveFlowStep(row.flow_id, stepId)?.expectations.keys() ?? [])]));
733
- for (const expectationId of row.expectation_ids)
734
- if (!allowedExpectations.has(expectationId))
735
- errors.push(`${manifestPath}: skill_roles '${row.skill_id}' expectation '${expectationId}' is not owned by its bound step(s)`);
736
- }
737
- const roleByShortId = new Map(skillRoleResult.entries.map((entry) => [entry.skill_id.replace(`${String(manifest.id)}.`, ""), entry]));
738
- const producerOwners = new Map();
739
- for (const row of skillRoleResult.entries) {
740
- if (row.role !== "step" || !row.flow_id)
741
- continue;
742
- for (const stepId of row.step_ids) {
743
- const effectiveStep = resolveEffectiveFlowStep(row.flow_id, stepId);
744
- if (!effectiveStep)
745
- continue;
746
- for (const expectationId of row.expectation_ids) {
747
- if (!effectiveStep.expectations.has(expectationId))
748
- continue;
749
- const key = `${effectiveStep.sourceFlowId}\u0000${effectiveStep.stepId}\u0000${expectationId}`;
750
- producerOwners.set(key, [...(producerOwners.get(key) ?? []), `skill:${row.skill_id}`]);
751
- }
752
- }
753
- }
754
- for (const action of flowStepActionResult.entries) {
755
- const containingFlow = flows.get(action.flow_id);
756
- if (!containingFlow || !containingFlow.steps.has(action.step_id)) {
757
- errors.push(`${manifestPath}: flow_step_actions '${action.flow_id}/${action.step_id}' references an unknown flow step`);
758
- continue;
759
- }
760
- const effectiveStep = resolveEffectiveFlowStep(action.flow_id, action.step_id);
761
- if (!effectiveStep) {
762
- errors.push(`${manifestPath}: flow_step_actions '${action.flow_id}/${action.step_id}' cannot resolve its composed Flow step`);
763
- continue;
764
- }
765
- const expectedAtStep = effectiveStep.expectations;
766
- for (const expectationId of action.expectation_ids ?? []) {
767
- if (!expectedAtStep.has(expectationId))
768
- errors.push(`${manifestPath}: flow_step_actions '${action.flow_id}/${action.step_id}' operation expectation '${expectationId}' is not owned by its resolved Flow step`);
769
- }
770
- if (action.skills.length === 0 && action.operations.length > 0 && expectedAtStep.size > 0 && !(action.expectation_ids?.length)) {
771
- errors.push(`${manifestPath}: flow_step_actions '${action.flow_id}/${action.step_id}' operation-only action must explicitly declare expectation_ids`);
772
- }
773
- const actionRows = [];
774
- for (const skill of action.skills) {
775
- const row = roleByShortId.get(skill);
776
- if (!row || row.role !== "step" || !row.flow_id || !effectiveStep.flowIds.has(row.flow_id) || !row.step_ids.includes(action.step_id)) {
777
- errors.push(`${manifestPath}: flow_step_actions '${action.flow_id}/${action.step_id}' skill '${skill}' must match one step-role binding`);
778
- }
779
- else {
780
- actionRows.push(row);
781
- }
782
- }
783
- for (const expectationId of expectedAtStep.keys()) {
784
- const key = `${effectiveStep.sourceFlowId}\u0000${effectiveStep.stepId}\u0000${expectationId}`;
785
- const owners = producerOwners.get(key) ?? [];
786
- if (action.operations.length > 0 && action.expectation_ids?.includes(expectationId))
787
- owners.push(`operation:${action.flow_id}/${action.step_id}`);
788
- producerOwners.set(key, owners);
789
- }
790
- }
791
- for (const [flowId, flow] of flows) {
792
- for (const [stepId, expectations] of flow.expectationsByStep) {
793
- for (const expectationId of expectations.keys()) {
794
- const owners = producerOwners.get(`${flowId}\u0000${stepId}\u0000${expectationId}`) ?? [];
795
- if (owners.length !== 1) {
796
- errors.push(`${manifestPath}: flow expectation '${flowId}/${stepId}/${expectationId}' must have exactly one producer owner; found ${owners.length}`);
797
- }
798
- }
799
- }
800
- }
801
- }
802
- if (manifest.first_party !== undefined && typeof manifest.first_party !== "boolean") {
803
- errors.push(`${manifestPath}: .first_party must be a boolean when present`);
475
+ if ((manifest.skill_roles !== undefined || manifest.flow_step_actions !== undefined) && skillRoleResult.errors.length === 0) {
476
+ errors.push(...validateActionRepositoryMetadata({ kitDir, manifestPath, manifest, actions: flowStepActionResult.entries, skillRoles: skillRoleResult.entries }));
804
477
  }
805
478
  return errors;
806
479
  }
@@ -2,8 +2,10 @@ export { BUILDER_BUILD_FLOW_ID, BUILDER_BUILD_FLOW_RELATIVE_PATH, BuilderBuildRu
2
2
  export type { BuilderBuildRunResult, BuilderBuildRunIdentityMismatch, BuilderBuildTrustBundleEvidenceInput, EvaluateBuilderBuildRunInput, LoadBuilderBuildRunInput, StartBuilderBuildRunInput, } from "./builder-flow-run-adapter.js";
3
3
  export { archiveBuilderFlowSession, cancelBuilderFlowSession, pauseBuilderFlowSession, recoverBuilderFlowSession, releaseBuilderFlowAssignment, resumeBuilderFlowSession, startBuilderFlowSession, syncBuilderFlowSession, } from "./builder-flow-runtime.js";
4
4
  export type { BuilderFlowAgentLifecycleInput, BuilderFlowAuthorizedLifecycleInput, BuilderFlowSessionInput, BuilderFlowSessionResult } from "./builder-flow-runtime.js";
5
- export { ContinuationAdapterTimeoutError, createFileContinuationStore, driveBuilderFlowSession, runContinuationDriver, withContinuationDriverLock, } from "./continuation-driver.js";
6
- export type { ContinuationBarrier, ContinuationDriverEvent, ContinuationDriverLockLease, ContinuationDriverOutcome, ContinuationDriverState, ContinuationRuntimePort, ContinuationSnapshot, ContinuationStateStore, ContinuationTurnAuthority, ContinuationTurnContext, ContinuationTurnRequest, ContinuationTurnResult, DriveBuilderFlowSessionInput, RunContinuationDriverInput, } from "./continuation-driver.js";
5
+ export { deriveBuilderGateActionEnvelope, gateActionProgressSnapshot, withGateActionPriorProgress, } from "./builder-gate-action-envelope.js";
6
+ export type { BuilderGateActionEnvelopeInput, GateActionEnvelope, GateActionInterfaceParameter, GateActionPriorProgress, GateActionProgressSnapshot, GateActionPublicMutation, } from "./builder-gate-action-envelope.js";
7
+ export { ContinuationAdapterTimeoutError, MAX_CONTINUATION_ADAPTER_EVIDENCE_BYTES, MAX_CONTINUATION_TURN_RESULT_BYTES, createFileContinuationStore, driveBuilderFlowSession, runContinuationDriver, withContinuationDriverLock, } from "./continuation-driver.js";
8
+ export type { ContinuationBarrier, ContinuationAcceptedTurn, ContinuationDriverEvent, ContinuationDriverLockLease, ContinuationDriverOutcome, ContinuationDriverState, ContinuationRuntimePort, ContinuationSnapshot, ContinuationStateStore, ContinuationTurnAuthority, ContinuationTurnContext, ContinuationTurnRequest, ContinuationTurnResult, DriveBuilderFlowSessionInput, RunContinuationDriverInput, } from "./continuation-driver.js";
7
9
  export { builderLifecycleAuthorizationPayload, loadBuilderLifecycleAuthorization } from "./builder-lifecycle-authority.js";
8
10
  export type { BuilderLifecycleAuthorization } from "./builder-lifecycle-authority.js";
9
11
  export { defaultArtifactRootForRead, defaultCodexHome, defaultTelemetryDirForRead, defaultTelemetryDirsForRead, durableFlowAgentsRoot, durableInstallRecordPath, DURABLE_FLOW_AGENTS_DIR, FLOW_AGENTS_RUNTIME_DIR, FLOW_AGENTS_RUNTIME_SUBDIR, firstExistingPath, flowAgentsArtifactRoot, KONTOURAI_DIR, legacyTelemetryDataDir, LEGACY_TELEMETRY_DIR, telemetryDataDir, } from "./lib/local-artifact-root.js";
@@ -15,7 +15,8 @@ import * as path from "node:path";
15
15
  import { loadJson as _loadJson, writeJson as _writeJson } from "./cli/workflow-sidecar.js";
16
16
  export { BUILDER_BUILD_FLOW_ID, BUILDER_BUILD_FLOW_RELATIVE_PATH, BuilderBuildRunInputError, BuilderBuildRunIdentityError, evaluateBuilderBuildRun, loadBuilderBuildRun, resolveBuilderBuildFlowDefinitionPath, startBuilderBuildRun, } from "./builder-flow-run-adapter.js";
17
17
  export { archiveBuilderFlowSession, cancelBuilderFlowSession, pauseBuilderFlowSession, recoverBuilderFlowSession, releaseBuilderFlowAssignment, resumeBuilderFlowSession, startBuilderFlowSession, syncBuilderFlowSession, } from "./builder-flow-runtime.js";
18
- export { ContinuationAdapterTimeoutError, createFileContinuationStore, driveBuilderFlowSession, runContinuationDriver, withContinuationDriverLock, } from "./continuation-driver.js";
18
+ export { deriveBuilderGateActionEnvelope, gateActionProgressSnapshot, withGateActionPriorProgress, } from "./builder-gate-action-envelope.js";
19
+ export { ContinuationAdapterTimeoutError, MAX_CONTINUATION_ADAPTER_EVIDENCE_BYTES, MAX_CONTINUATION_TURN_RESULT_BYTES, createFileContinuationStore, driveBuilderFlowSession, runContinuationDriver, withContinuationDriverLock, } from "./continuation-driver.js";
19
20
  // Pure serialization contract used by external lifecycle authorities when
20
21
  // signing requests. This does not load, create, or mutate a Flow run.
21
22
  export { builderLifecycleAuthorizationPayload, loadBuilderLifecycleAuthorization } from "./builder-lifecycle-authority.js";
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@kontourai/flow-agents",
3
- "version": "3.11.0",
3
+ "version": "3.12.0",
4
4
  "type": "module"
5
5
  }
@@ -62,6 +62,7 @@ export interface BuilderFlowRunResult {
62
62
  attachedEvidence: FlowEvidenceEntry[];
63
63
  outcomes: GateOutcome[];
64
64
  manifest: JsonObject;
65
+ config: JsonObject;
65
66
  freshnessTransitions: JsonObject[];
66
67
  }
67
68
  export interface BuilderBuildRunResult extends Omit<BuilderFlowRunResult, "definitionId"> {
@@ -109,6 +109,7 @@ export async function evaluateBuilderFlowRun(input) {
109
109
  attachedEvidence,
110
110
  outcomes: evaluated.outcomes,
111
111
  manifest: evaluated.manifest,
112
+ config: evaluated.config,
112
113
  freshnessTransitions: evaluated.freshness_transitions,
113
114
  };
114
115
  }
@@ -174,6 +175,7 @@ function resultFromRun(run, runId) {
174
175
  attachedEvidence: [],
175
176
  outcomes: [],
176
177
  manifest: run.manifest,
178
+ config: run.config,
177
179
  freshnessTransitions: [],
178
180
  };
179
181
  }
@@ -1,3 +1,4 @@
1
+ import { type GateActionEnvelope, type GateActionProgressSnapshot } from "./builder-gate-action-envelope.js";
1
2
  import { type BuilderFlowId, type BuilderFlowRunResult } from "./builder-flow-run-adapter.js";
2
3
  type AnyRecord = Record<string, any>;
3
4
  export interface BuilderFlowSessionInput {
@@ -15,6 +16,10 @@ export interface BuilderFlowSessionResult {
15
16
  projectRoot: string;
16
17
  run: BuilderFlowRunResult;
17
18
  projection: AnyRecord;
19
+ /** Ephemeral adapter context; deliberately excluded from durable state.json projection. */
20
+ gateActionEnvelope: GateActionEnvelope | null;
21
+ /** Canonical progress observation, retained even when terminal runs emit no action envelope. */
22
+ progressSnapshot: GateActionProgressSnapshot;
18
23
  attached: boolean;
19
24
  }
20
25
  export declare function startBuilderFlowSession(input: BuilderFlowSessionInput): Promise<BuilderFlowSessionResult>;