stageflow 0.36.0 → 0.40.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 (288) hide show
  1. package/README.md +61 -26
  2. package/dist/agent/claudeAdapter.js +21 -1
  3. package/dist/agent/claudeTools.d.ts +13 -0
  4. package/dist/agent/claudeTools.js +98 -0
  5. package/dist/agent/piAdapter.d.ts +9 -1
  6. package/dist/agent/piAdapter.js +59 -18
  7. package/dist/agent/piIsolatedMcp.js +14 -2
  8. package/dist/agent/piIsolatedMcpProbe.d.ts +5 -1
  9. package/dist/agent/piIsolatedMcpProbe.js +16 -30
  10. package/dist/agent/port.d.ts +5 -0
  11. package/dist/agent/sandboxPiTools.d.ts +99 -0
  12. package/dist/agent/sandboxPiTools.js +109 -0
  13. package/dist/agents/agentId.d.ts +8 -0
  14. package/dist/agents/agentId.js +27 -0
  15. package/dist/agents/approvalBroker.d.ts +16 -0
  16. package/dist/agents/approvalBroker.js +45 -0
  17. package/dist/agents/authorChat.d.ts +19 -0
  18. package/dist/agents/authorChat.js +63 -0
  19. package/dist/agents/chatTurn.d.ts +23 -0
  20. package/dist/agents/chatTurn.js +77 -0
  21. package/dist/agents/communications/agentmail.d.ts +19 -0
  22. package/dist/agents/communications/agentmail.js +46 -0
  23. package/dist/agents/communications/agentmailListener.d.ts +59 -0
  24. package/dist/agents/communications/agentmailListener.js +183 -0
  25. package/dist/agents/communications/allowlist.d.ts +10 -0
  26. package/dist/agents/communications/allowlist.js +36 -0
  27. package/dist/agents/communications/channelConnections.d.ts +3 -0
  28. package/dist/agents/communications/channelConnections.js +51 -0
  29. package/dist/agents/communications/delivery.d.ts +53 -0
  30. package/dist/agents/communications/delivery.js +142 -0
  31. package/dist/agents/communications/email.d.ts +26 -0
  32. package/dist/agents/communications/email.js +20 -0
  33. package/dist/agents/communications/identity.d.ts +13 -0
  34. package/dist/agents/communications/identity.js +18 -0
  35. package/dist/agents/communications/imessageListener.d.ts +41 -0
  36. package/dist/agents/communications/imessageListener.js +92 -0
  37. package/dist/agents/communications/inbound.d.ts +63 -0
  38. package/dist/agents/communications/inbound.js +143 -0
  39. package/dist/agents/communications/listener.d.ts +36 -0
  40. package/dist/agents/communications/listener.js +38 -0
  41. package/dist/agents/communications/photon.d.ts +19 -0
  42. package/dist/agents/communications/photon.js +38 -0
  43. package/dist/agents/communications/port.d.ts +27 -0
  44. package/dist/agents/communications/port.js +6 -0
  45. package/dist/agents/communications/slack.d.ts +28 -0
  46. package/dist/agents/communications/slack.js +65 -0
  47. package/dist/agents/communications/supervisor.d.ts +36 -0
  48. package/dist/agents/communications/supervisor.js +96 -0
  49. package/dist/agents/communications/telegram.d.ts +19 -0
  50. package/dist/agents/communications/telegram.js +52 -0
  51. package/dist/agents/definitionSummary.d.ts +13 -0
  52. package/dist/agents/definitionSummary.js +91 -0
  53. package/dist/agents/delegate.d.ts +3 -0
  54. package/dist/agents/delegate.js +8 -0
  55. package/dist/agents/errors.d.ts +10 -0
  56. package/dist/agents/errors.js +32 -0
  57. package/dist/agents/guardrails.d.ts +24 -0
  58. package/dist/agents/guardrails.js +39 -0
  59. package/dist/agents/historyFit.d.ts +10 -0
  60. package/dist/agents/historyFit.js +26 -0
  61. package/dist/agents/hostContext.d.ts +54 -0
  62. package/dist/agents/hostContext.js +156 -0
  63. package/dist/agents/ledgers.d.ts +29 -0
  64. package/dist/agents/ledgers.js +31 -0
  65. package/dist/agents/lineDiff.d.ts +12 -0
  66. package/dist/agents/lineDiff.js +46 -0
  67. package/dist/agents/ndjson.d.ts +9 -0
  68. package/dist/agents/ndjson.js +47 -0
  69. package/dist/agents/otlpExport.d.ts +9 -0
  70. package/dist/agents/otlpExport.js +58 -0
  71. package/dist/agents/otlpSink.d.ts +7 -0
  72. package/dist/agents/otlpSink.js +23 -0
  73. package/dist/agents/policy.d.ts +31 -0
  74. package/dist/agents/policy.js +84 -0
  75. package/dist/agents/projectRoot.d.ts +5 -0
  76. package/dist/agents/projectRoot.js +15 -0
  77. package/dist/agents/runtime/piRuntime.d.ts +52 -0
  78. package/dist/agents/runtime/piRuntime.js +474 -0
  79. package/dist/agents/runtime/types.d.ts +77 -0
  80. package/dist/agents/runtime/types.js +26 -0
  81. package/dist/agents/sandbox.d.ts +17 -0
  82. package/dist/agents/sandbox.js +10 -0
  83. package/dist/agents/scheduleSource.d.ts +32 -0
  84. package/dist/agents/scheduleSource.js +100 -0
  85. package/dist/agents/service.d.ts +298 -0
  86. package/dist/agents/service.js +1105 -0
  87. package/dist/agents/sessions.d.ts +38 -0
  88. package/dist/agents/sessions.js +321 -0
  89. package/dist/agents/store.d.ts +277 -0
  90. package/dist/agents/store.js +643 -0
  91. package/dist/agents/trace.d.ts +27 -0
  92. package/dist/agents/trace.js +29 -0
  93. package/dist/agents/turnLifecycle.d.ts +72 -0
  94. package/dist/agents/turnLifecycle.js +157 -0
  95. package/dist/agents/webChat/publicChat.d.ts +36 -0
  96. package/dist/agents/webChat/publicChat.js +290 -0
  97. package/dist/agents/webChat/rateLimit.d.ts +15 -0
  98. package/dist/agents/webChat/rateLimit.js +33 -0
  99. package/dist/agents/webChat/slug.d.ts +2 -0
  100. package/dist/agents/webChat/slug.js +9 -0
  101. package/dist/channels/providers/agentmail.js +14 -1
  102. package/dist/channels/providers/photonImessage.js +36 -0
  103. package/dist/channels/providers/slack.js +2 -1
  104. package/dist/channels/providers/telegram.js +2 -1
  105. package/dist/channels/types.d.ts +27 -0
  106. package/dist/cli/agentsCommand.d.ts +14 -0
  107. package/dist/cli/agentsCommand.js +291 -0
  108. package/dist/cli.js +9 -0
  109. package/dist/config/browseCatalog.js +4 -11
  110. package/dist/config/draftPackage.d.ts +1 -0
  111. package/dist/config/draftPackage.js +4 -0
  112. package/dist/config/hostConfig.js +9 -0
  113. package/dist/config/loadAgent.d.ts +266 -0
  114. package/dist/config/loadAgent.js +374 -0
  115. package/dist/config/loadPipeline.js +5 -2
  116. package/dist/config/loadTask.js +34 -1
  117. package/dist/config/mcpHostCatalog.d.ts +50 -0
  118. package/dist/config/mcpHostCatalog.js +405 -0
  119. package/dist/config/mcpOAuth.d.ts +37 -0
  120. package/dist/config/mcpOAuth.js +263 -0
  121. package/dist/config/mcpRedaction.d.ts +42 -0
  122. package/dist/config/mcpRedaction.js +314 -0
  123. package/dist/config/mcpToolCache.d.ts +20 -0
  124. package/dist/config/mcpToolCache.js +43 -0
  125. package/dist/config/mergePipelineIncludes.d.ts +2 -0
  126. package/dist/config/mergePipelineIncludes.js +25 -0
  127. package/dist/config/resolveStageMcpServers.d.ts +35 -3
  128. package/dist/config/resolveStageMcpServers.js +124 -9
  129. package/dist/config/validateCatalog.d.ts +1 -1
  130. package/dist/config/validateCatalog.js +22 -1
  131. package/dist/mcp/agentTools.d.ts +8 -0
  132. package/dist/mcp/agentTools.js +132 -0
  133. package/dist/mcp/catalogTools.js +17 -10
  134. package/dist/mcp/deps.d.ts +6 -0
  135. package/dist/mcp/pipelineAuthorSupport.d.ts +19 -0
  136. package/dist/mcp/pipelineAuthorSupport.js +10 -0
  137. package/dist/mcp/pipelineAuthorTools.d.ts +8 -0
  138. package/dist/mcp/pipelineAuthorTools.js +109 -0
  139. package/dist/mcp/server.js +5 -0
  140. package/dist/mcp/tools.js +4 -0
  141. package/dist/mcp/triggerTools.js +32 -0
  142. package/dist/memory/access.d.ts +36 -0
  143. package/dist/memory/access.js +116 -0
  144. package/dist/memory/agentIssues.d.ts +3 -0
  145. package/dist/memory/agentIssues.js +23 -0
  146. package/dist/memory/bashDeny.d.ts +6 -0
  147. package/dist/memory/bashDeny.js +35 -0
  148. package/dist/memory/host.d.ts +51 -0
  149. package/dist/memory/host.js +394 -0
  150. package/dist/memory/ids.d.ts +15 -0
  151. package/dist/memory/ids.js +31 -0
  152. package/dist/memory/worker.d.ts +1 -0
  153. package/dist/memory/worker.js +84 -0
  154. package/dist/models/catalog.d.ts +113 -0
  155. package/dist/models/catalog.js +238 -0
  156. package/dist/models/response.d.ts +29 -0
  157. package/dist/models/response.js +25 -0
  158. package/dist/operatorAgent/agentAuthorContext.d.ts +17 -0
  159. package/dist/operatorAgent/agentAuthorContext.js +32 -0
  160. package/dist/operatorAgent/fakeHost.js +2 -0
  161. package/dist/operatorAgent/host.js +6 -3
  162. package/dist/operatorAgent/index.d.ts +4 -0
  163. package/dist/operatorAgent/index.js +4 -0
  164. package/dist/operatorAgent/piModel.js +2 -0
  165. package/dist/operatorAgent/profiles/agentAuthor.d.ts +11 -0
  166. package/dist/operatorAgent/profiles/agentAuthor.js +192 -0
  167. package/dist/operatorAgent/profiles/agentAuthorPlaybook.d.ts +1 -0
  168. package/dist/operatorAgent/profiles/agentAuthorPlaybook.js +29 -0
  169. package/dist/operatorAgent/profiles/workshopAuthor.js +2 -2
  170. package/dist/operatorAgent/profiles/workshopAuthorTools.js +3 -3
  171. package/dist/operatorAgent/proposals.d.ts +1 -0
  172. package/dist/operatorAgent/proposals.js +23 -2
  173. package/dist/package-meta.d.ts +1 -1
  174. package/dist/package-meta.js +1 -1
  175. package/dist/preflight/pipelinePreflight.js +1 -0
  176. package/dist/runstore/createStore.d.ts +2 -0
  177. package/dist/runstore/createStore.js +8 -0
  178. package/dist/runstore/overviewSummary.d.ts +56 -0
  179. package/dist/runstore/overviewSummary.js +134 -0
  180. package/dist/runstore/port.d.ts +3 -0
  181. package/dist/runstore/sqlite/SqliteRunStore.d.ts +2 -0
  182. package/dist/runstore/sqlite/SqliteRunStore.js +18 -0
  183. package/dist/runstore/sqlite/migrations/013-agents.d.ts +12 -0
  184. package/dist/runstore/sqlite/migrations/013-agents.js +156 -0
  185. package/dist/runstore/sqlite/migrations/014-agent-deliveries.d.ts +11 -0
  186. package/dist/runstore/sqlite/migrations/014-agent-deliveries.js +32 -0
  187. package/dist/runstore/sqlite/migrations/index.js +4 -0
  188. package/dist/runtime/gitCheckoutCapability.d.ts +1 -0
  189. package/dist/runtime/gitCheckoutCapability.js +1 -1
  190. package/dist/runtime/gitWorktreeCheckout.d.ts +22 -0
  191. package/dist/runtime/gitWorktreeCheckout.js +120 -0
  192. package/dist/runtime/sandboxContainer.d.ts +62 -0
  193. package/dist/runtime/sandboxContainer.js +151 -0
  194. package/dist/runtime/sandboxDesk.d.ts +28 -0
  195. package/dist/runtime/sandboxDesk.js +242 -0
  196. package/dist/runtime/sandboxFiles.d.ts +20 -0
  197. package/dist/runtime/sandboxFiles.js +150 -0
  198. package/dist/runtime/stageAttemptBootstrap.js +15 -1
  199. package/dist/runtime/stageEnvironment.d.ts +2 -0
  200. package/dist/runtime/stageEnvironment.js +8 -1
  201. package/dist/runtime/stageProcessLauncher.js +23 -0
  202. package/dist/runtime/stageRoots.d.ts +9 -0
  203. package/dist/runtime/stageRoots.js +14 -0
  204. package/dist/runtime/stageRunner.d.ts +5 -0
  205. package/dist/runtime/stageRunner.js +38 -4
  206. package/dist/runtime/stageSandbox.d.ts +16 -0
  207. package/dist/runtime/stageSandbox.js +54 -0
  208. package/dist/runtime/stageSecrets.d.ts +6 -1
  209. package/dist/runtime/stageSecrets.js +34 -1
  210. package/dist/runtime/stageWorker.js +138 -105
  211. package/dist/runtime/workspaceBinding.d.ts +2 -1
  212. package/dist/runtime/workspaceBinding.js +20 -4
  213. package/dist/server/agentAuthorRoutes.d.ts +5 -0
  214. package/dist/server/agentAuthorRoutes.js +64 -0
  215. package/dist/server/agentRoutes.d.ts +5 -0
  216. package/dist/server/agentRoutes.js +323 -0
  217. package/dist/server/bootstrap.d.ts +8 -0
  218. package/dist/server/bootstrap.js +36 -10
  219. package/dist/server/controlToken.js +8 -0
  220. package/dist/server/http.d.ts +8 -1
  221. package/dist/server/http.js +172 -20
  222. package/dist/server/mcpHost.js +1 -0
  223. package/dist/server/memoryRoutes.d.ts +5 -0
  224. package/dist/server/memoryRoutes.js +146 -0
  225. package/dist/server/projectMcpRoutes.d.ts +1 -0
  226. package/dist/server/projectMcpRoutes.js +241 -3
  227. package/dist/toolkit/guard.d.ts +27 -0
  228. package/dist/toolkit/guard.js +98 -0
  229. package/dist/toolkit/index.d.ts +48 -0
  230. package/dist/toolkit/index.js +82 -0
  231. package/dist/toolkit/meta.d.ts +36 -0
  232. package/dist/toolkit/meta.js +117 -0
  233. package/dist/toolkit/profiles.d.ts +13 -0
  234. package/dist/toolkit/profiles.js +25 -0
  235. package/dist/toolkit/record.d.ts +15 -0
  236. package/dist/toolkit/record.js +17 -0
  237. package/dist/tools/memoryTools.d.ts +95 -0
  238. package/dist/tools/memoryTools.js +179 -0
  239. package/dist/types/pipeline.d.ts +3 -0
  240. package/dist/types/stage.d.ts +2 -0
  241. package/dist/types/task.d.ts +11 -1
  242. package/dist/ui/assets/AssistantRuntimeProvider-CsiPFhCT.js +9 -0
  243. package/dist/ui/assets/MarkdownText-D7tYaIFO.js +29 -0
  244. package/dist/ui/assets/ReadonlyStore-BfXqHykm.js +6 -0
  245. package/dist/ui/assets/Tooltip-DrpoRRNi.js +1 -0
  246. package/dist/ui/assets/chat-BbLukq9W.js +5 -0
  247. package/dist/ui/assets/chat-zIZU_bP1.css +2 -0
  248. package/dist/ui/assets/jsx-runtime-iVoFAvQ_.js +1 -0
  249. package/dist/ui/assets/{index-Clv4sJpU.css → main-BFo79krC.css} +1 -1
  250. package/dist/ui/assets/main-CijYMeM0.js +259 -0
  251. package/dist/ui/chat.html +25 -0
  252. package/dist/ui/index.html +6 -2
  253. package/dist/workshop/modelSettings.d.ts +2 -2
  254. package/dist/workshop/modelSettings.js +5 -11
  255. package/examples/README.md +1 -0
  256. package/examples/channels-smoke/README.md +12 -1
  257. package/examples/github-release/README.md +1 -1
  258. package/examples/memory/README.md +101 -0
  259. package/examples/memory/desk-outage.task.yaml +15 -0
  260. package/examples/memory/desk-refund.task.yaml +15 -0
  261. package/examples/memory/desk-revisit-outage.task.yaml +11 -0
  262. package/examples/memory/desk-revisit.pipeline.yaml +123 -0
  263. package/examples/memory/desk.pipeline.yaml +192 -0
  264. package/examples/memory/file-card.pipeline.yaml +39 -0
  265. package/examples/memory/file-ledger.task.yaml +22 -0
  266. package/examples/memory/file-release.task.yaml +24 -0
  267. package/examples/memory/file-rich.pipeline.yaml +40 -0
  268. package/examples/memory/file-ticket.task.yaml +7 -0
  269. package/examples/memory/file-timeline.task.yaml +28 -0
  270. package/examples/memory/find-card.pipeline.yaml +46 -0
  271. package/examples/memory/find-ticket.task.yaml +7 -0
  272. package/examples/memory/missing.pipeline.yaml +16 -0
  273. package/examples/memory/probe-bash.task.yaml +3 -0
  274. package/examples/memory/recall.pipeline.yaml +24 -0
  275. package/examples/memory/recall.task.yaml +5 -0
  276. package/examples/memory/remember-ada.task.yaml +6 -0
  277. package/examples/memory/remember-grace.task.yaml +6 -0
  278. package/examples/memory/remember.pipeline.yaml +58 -0
  279. package/examples/memory/sandbox-memory-bash.pipeline.yaml +28 -0
  280. package/examples/memory/stageflow.yaml +12 -0
  281. package/examples/memory/update-card.pipeline.yaml +43 -0
  282. package/examples/memory/update-ledger.task.yaml +23 -0
  283. package/examples/memory/update-rich.pipeline.yaml +44 -0
  284. package/examples/memory/update-ticket.task.yaml +7 -0
  285. package/examples/ship-feature/README.md +15 -0
  286. package/examples/stage-mcp/README.md +1 -1
  287. package/package.json +2 -1
  288. package/dist/ui/assets/index-BOhqnPNg.js +0 -260
@@ -0,0 +1,25 @@
1
+ <!doctype html>
2
+ <html lang="en" data-redesign="on" data-theme="dark">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
6
+ <meta name="robots" content="noindex, nofollow" />
7
+ <meta name="color-scheme" content="dark light" />
8
+ <script>
9
+ try {
10
+ var light = window.matchMedia && window.matchMedia("(prefers-color-scheme: light)").matches;
11
+ document.documentElement.setAttribute("data-theme", light ? "light" : "dark");
12
+ } catch (e) {}
13
+ </script>
14
+ <link rel="icon" type="image/svg+xml" href="/stageflow-icon.svg" />
15
+ <title>Chat</title>
16
+ <script type="module" crossorigin src="/assets/chat-BbLukq9W.js"></script>
17
+ <link rel="modulepreload" crossorigin href="/assets/jsx-runtime-iVoFAvQ_.js">
18
+ <link rel="modulepreload" crossorigin href="/assets/ReadonlyStore-BfXqHykm.js">
19
+ <link rel="modulepreload" crossorigin href="/assets/AssistantRuntimeProvider-CsiPFhCT.js">
20
+ <link rel="stylesheet" crossorigin href="/assets/chat-zIZU_bP1.css">
21
+ </head>
22
+ <body>
23
+ <div id="root"></div>
24
+ </body>
25
+ </html>
@@ -13,8 +13,12 @@
13
13
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Figtree:wght@400;500;600;700&display=swap" />
14
14
  <link rel="icon" type="image/svg+xml" href="/stageflow-icon.svg" />
15
15
  <title>Stageflow</title>
16
- <script type="module" crossorigin src="/assets/index-BOhqnPNg.js"></script>
17
- <link rel="stylesheet" crossorigin href="/assets/index-Clv4sJpU.css">
16
+ <script type="module" crossorigin src="/assets/main-CijYMeM0.js"></script>
17
+ <link rel="modulepreload" crossorigin href="/assets/jsx-runtime-iVoFAvQ_.js">
18
+ <link rel="modulepreload" crossorigin href="/assets/ReadonlyStore-BfXqHykm.js">
19
+ <link rel="modulepreload" crossorigin href="/assets/AssistantRuntimeProvider-CsiPFhCT.js">
20
+ <link rel="modulepreload" crossorigin href="/assets/Tooltip-DrpoRRNi.js">
21
+ <link rel="stylesheet" crossorigin href="/assets/main-BFo79krC.css">
18
22
  </head>
19
23
  <body>
20
24
  <div id="root"></div>
@@ -1,11 +1,11 @@
1
- export declare const DEFAULT_WORKSHOP_MODEL = "cursor/auto";
2
1
  export type ResolveWorkshopModelInput = {
3
2
  sessionOverride?: string | null;
4
3
  settingsDefault?: string | null;
5
4
  profileDefault?: string | null;
6
5
  };
7
6
  /**
8
- * Effective Workshop chat model: session override → Settings default → profile fallback.
7
+ * Effective Workshop chat model: session override → Settings default → profile fallback → the
8
+ * model catalog's default.
9
9
  * Credentials stay on the shared Stageflow provider auth stack; this only picks a model id.
10
10
  */
11
11
  export declare function resolveWorkshopModel(input?: ResolveWorkshopModelInput): string;
@@ -1,9 +1,7 @@
1
- import { globalModelFromManifest } from "../config/resolveModel.js";
2
- import { resolveStageflowContext } from "../project/resolveStageflowContext.js";
3
- import { readFactorySettings } from "../runtime/settingsFile.js";
4
- export const DEFAULT_WORKSHOP_MODEL = "cursor/auto";
1
+ import { getModelCatalog, peekDefaultModel } from "../models/catalog.js";
5
2
  /**
6
- * Effective Workshop chat model: session override → Settings default → profile fallback.
3
+ * Effective Workshop chat model: session override → Settings default → profile fallback → the
4
+ * model catalog's default.
7
5
  * Credentials stay on the shared Stageflow provider auth stack; this only picks a model id.
8
6
  */
9
7
  export function resolveWorkshopModel(input = {}) {
@@ -16,7 +14,7 @@ export function resolveWorkshopModel(input = {}) {
16
14
  const profile = normalizeModelId(input.profileDefault);
17
15
  if (profile)
18
16
  return profile;
19
- return DEFAULT_WORKSHOP_MODEL;
17
+ return peekDefaultModel();
20
18
  }
21
19
  export function parseWorkshopModel(value) {
22
20
  if (typeof value !== "string")
@@ -30,11 +28,7 @@ export function parseWorkshopModel(value) {
30
28
  * when the manifest has none.
31
29
  */
32
30
  export async function readWorkshopOpenModel(cwd) {
33
- const ctx = await resolveStageflowContext(cwd);
34
- return resolveWorkshopModel({
35
- settingsDefault: globalModelFromManifest(ctx.manifest) ??
36
- readFactorySettings(cwd).workshopModel,
37
- });
31
+ return getModelCatalog(cwd).defaultModel();
38
32
  }
39
33
  function normalizeModelId(value) {
40
34
  if (typeof value !== "string")
@@ -44,6 +44,7 @@ More CI-focused examples will follow this pattern (prepare context → run pipel
44
44
  | [verify-tour](verify-tour/) | Verify check types: artifact, command, checklist, payload_schema, gate, checkout_changes | `sf ui`, then pick `verify-tour` |
45
45
  | [retry-tour](retry-tour/) | Retry surfaces: emit soft-reject, automatic repair, manual recover, ordinary Retry | `sf ui`, then pick `retry-tour` |
46
46
  | [mcp-hitl-tour](mcp-hitl-tour/) | MCP HITL tour: free_text gate, ungated fan-out + Clone Chain join, wait_for_human loop, artifacts | `sf ui` / MCP `start_run`, then [README](mcp-hitl-tour/README.md) |
47
+ | [memory](memory/) | Two pipelines share one data-directory page: one writes a line, the next run reads it | Create `notebook` first, then [README](memory/README.md) |
47
48
 
48
49
  Current wiring tours: [`route-wiring-smoke-test`](route-wiring-smoke-test/), [`route-if-tour`](route-if-tour/).
49
50
 
@@ -2,10 +2,21 @@
2
2
 
3
3
  Two stages, one channel each: `send-email` sends one email (AgentMail) and then `send-text` sends one text (iMessage via Photon), through the connections on the Connections page. A stage can use one channel, so the two are separate stages. Nothing is sent until you start a run.
4
4
 
5
+ This example is **excluded** from the repo-root catalog manifest (see `stageflow.yaml`) so host-only Connections do not fail `sf validate --strict` or release CI. It remains loadable by explicit path.
6
+
5
7
  1. Connect AgentMail and iMessage on the Connections page. The stage expects the connection ids `agentmail` and `imessage`; if yours differ, edit `connection:` in the two stage files.
6
8
  2. Pin your recipients: in `send-email.yaml` replace `to: [change-me@example.invalid]` with your email, and in `send-text.yaml` replace `to: "+10000000000"` with your phone in E.164 form (for example `+14155550123`). On a Free or Pro Photon project the phone must be a project user, and that person must have texted their assigned Photon line once, or the send is rejected.
7
9
  3. Change `model:` to one you have a provider for.
8
- 4. Run `sf validate` on the pipeline, then open `channels-smoke` in the console and start it with `channels-smoke-task`. The run checks both connections live before the stage starts.
10
+ 4. From the repo root, validate and run by path (Connections must already exist):
11
+
12
+ ```bash
13
+ sf validate --strict --pipeline examples/channels-smoke/channels-smoke.pipeline.yaml
14
+ sf run \
15
+ --pipeline examples/channels-smoke/channels-smoke.pipeline.yaml \
16
+ --task examples/channels-smoke/channels-smoke.task.yaml
17
+ ```
18
+
19
+ Or open the console and start `channels-smoke` with `channels-smoke-task` after loading the pipeline by path. The run checks both connections live before the stage starts.
9
20
 
10
21
  The Claude agent backend does not provide `send_message`; use a Pi model (the default).
11
22
 
@@ -47,7 +47,7 @@ DRY_RUN=1 bash scripts/run-github-release-local.sh
47
47
  Manual equivalent:
48
48
 
49
49
  ```bash
50
- sf validate --strict
50
+ sf validate --strict --pipeline examples/github-release/github-release.pipeline.yaml
51
51
  export CURSOR_API_KEY=… # no trailing newline; or use repo-root .env
52
52
  export GH_TOKEN=…
53
53
  CURRENT="$(node -p "require('./package.json').version")"
@@ -0,0 +1,101 @@
1
+ # memory
2
+
3
+ Two pipelines share one memory, `notebook`, in the data directory. `remember` adds a line to the cover page. `recall` only reads the cover, so a later run can see what an earlier run wrote. `notebook` is the memory id. It is not a card key.
4
+
5
+ Create the memory before either pipeline runs. A run does not create it. `missing.pipeline.yaml` names an id that is not there, so validate fails and a run does not start.
6
+
7
+ ## Create the memory
8
+
9
+ With `sf ui` running:
10
+
11
+ ```bash
12
+ curl -sS -X POST http://127.0.0.1:3847/api/memories \
13
+ -H 'Origin: http://127.0.0.1:3847' \
14
+ -H 'Content-Type: application/json' \
15
+ -d '{"id":"notebook","description":"Lines this pipeline has already recorded."}'
16
+ ```
17
+
18
+ Or use **Memories** in the console. The id is `notebook`. `memory.yaml` stays version 1. The cover is `body.md`. Cards live beside it.
19
+
20
+ ## Run the cover
21
+
22
+ From the repository root, after the memory exists:
23
+
24
+ ```bash
25
+ sf validate --pipeline examples/memory/remember.pipeline.yaml --strict
26
+ sf run \
27
+ --pipeline examples/memory/remember.pipeline.yaml \
28
+ --task examples/memory/remember-ada.task.yaml
29
+
30
+ sf run \
31
+ --pipeline examples/memory/remember.pipeline.yaml \
32
+ --task examples/memory/remember-grace.task.yaml
33
+
34
+ sf run \
35
+ --pipeline examples/memory/recall.pipeline.yaml \
36
+ --task examples/memory/recall.task.yaml
37
+ ```
38
+
39
+ The cover is `$STAGEFLOW_HOME/memories/notebook/body.md`. After the two remember runs it should contain both lines (`Ada was sourced.` and `Grace was shortlisted.`). Recall's envelope `page` should match that file. Replacing the cover does not delete cards.
40
+
41
+ ```bash
42
+ sf validate --pipeline examples/memory/missing.pipeline.yaml --strict
43
+ ```
44
+
45
+ That command fails with `pipeline.memory_unavailable`.
46
+
47
+ ## Cards
48
+
49
+ `file-card` adds one card. `update-card` replaces that card. `find-card` reads it, searches the current cards, and reads the cover without changing either. All three attach `notebook`. Run them in that order, after the memory exists. The cover runs above are optional. A stage cannot delete a card.
50
+
51
+ ```bash
52
+ sf run \
53
+ --pipeline examples/memory/file-card.pipeline.yaml \
54
+ --task examples/memory/file-ticket.task.yaml
55
+
56
+ sf run \
57
+ --pipeline examples/memory/find-card.pipeline.yaml \
58
+ --task examples/memory/find-ticket.task.yaml
59
+
60
+ sf run \
61
+ --pipeline examples/memory/update-card.pipeline.yaml \
62
+ --task examples/memory/update-ticket.task.yaml
63
+
64
+ sf run \
65
+ --pipeline examples/memory/find-card.pipeline.yaml \
66
+ --task examples/memory/find-ticket.task.yaml
67
+ ```
68
+
69
+ The first find should return the filed note for `TICKET-1842` and a search hit for `refund`. The second find should return the updated note. The cover text should be unchanged by these four runs. Add refuses a key that already exists, so a second `file-card` run of the same task fails. Update refuses a key that is missing.
70
+
71
+ `remember` and `recall` attach the same memory, so they can call the card tools too. Their tasks only use the cover. The prompt lists the memory id and its description, not the cover or any card body. The session never receives a filesystem path.
72
+
73
+ Search is a case-insensitive word scan of the current keys and bodies, at most 20 hits, snippet only.
74
+
75
+ ## A desk with several cards
76
+
77
+ `desk` files every card in the task, updates only the focus key, then reads the cover and the other cards back. `desk-revisit` does that update on a later run, after the cards already exist. Both attach `new-notebook`. Create that memory in the console before the first run.
78
+
79
+ `desk-outage` uses a ticket id, a release path (`releases/2.4.1`), and an email. `desk-refund` uses a different ticket, an order path (`orders/4412/refund`), and a different email, so it can run beside the outage without sharing a key. Run each `desk` task once. A second run fails because add refuses a key that already exists.
80
+
81
+ ```bash
82
+ sf run \
83
+ --pipeline examples/memory/desk.pipeline.yaml \
84
+ --task examples/memory/desk-outage.task.yaml
85
+
86
+ sf run \
87
+ --pipeline examples/memory/desk-revisit.pipeline.yaml \
88
+ --task examples/memory/desk-revisit-outage.task.yaml
89
+ ```
90
+
91
+ After `desk-outage`, the release card should be the hold-the-deploy decision. `TICKET-1904` and `ada@example.com` should still be the original notes. The last stage's `cover_same` should be `yes`.
92
+
93
+ After `desk-revisit-outage`, the release card should be the rollback-finished note, and the previous copy in **Memories** should be the hold-the-deploy decision. The ticket and the email card should still be the original notes. `cover_same` should stay `yes`.
94
+
95
+ `desk-refund` is the same pipeline with a second set of keys. Run it on its own, not after those keys already exist. Search during that run looks for `reviewer`, which is only in the email card, while the card that gets updated is the order path.
96
+
97
+ The operator, in **Memories**, can list keys, open the `TICKET-1842` card, correct it, and delete it. Delete removes the current card and the previous copy and cannot be undone. The page shows the previous card copy and the previous cover text when they exist. The operator can edit the cover. The operator does not create cards; a session adds them. There is one previous copy, not a full history, and no restore action.
98
+
99
+ `sandbox-memory-bash` is the sandbox probe. It attaches `shared-notes` and its `probe` stage runs one bash command, then reports whether that command printed a `body.md` path. The task is `probe-bash`. Create `shared-notes` before running it. Edit the `probe` stage prompt in the pipeline file.
100
+
101
+ This directory is excluded from the repo-root catalog scan, because those commands fail until `notebook` exists.
@@ -0,0 +1,15 @@
1
+ id: desk-outage
2
+ goal: File three notes for one incident, then record the rollback decision on the release card only
3
+ context: The memory new-notebook already exists. None of these card keys exist yet. The cover page is a separate instruction and must stay as it is.
4
+ constraints: Do not delete a card. Do not replace the cover. Update only the focus key.
5
+ input:
6
+ focus: releases/2.4.1
7
+ decision: Rollback is the plan. Hold the deploy until payments confirms the migration.
8
+ query: pager
9
+ cards:
10
+ - key: TICKET-1904
11
+ note: Checkout returns 502 for EU customers since 14:10 UTC.
12
+ - key: releases/2.4.1
13
+ note: Rollback is blocked on the payments migration.
14
+ - key: ada@example.com
15
+ note: On-call pager owner for the checkout outage.
@@ -0,0 +1,15 @@
1
+ id: desk-refund
2
+ goal: File a refund, the order path, and the reviewer, then record the payout on the order path only
3
+ context: The memory new-notebook already exists. None of these card keys exist yet. Run this only if desk-outage has not already used these keys.
4
+ constraints: Do not delete a card. Do not replace the cover. Update only the focus key.
5
+ input:
6
+ focus: orders/4412/refund
7
+ decision: Store credit was declined. The refund was paid to the original card.
8
+ query: reviewer
9
+ cards:
10
+ - key: TICKET-2040
11
+ note: Customer asked for store credit on order 4412.
12
+ - key: orders/4412/refund
13
+ note: Refund is waiting on a reviewer.
14
+ - key: grace@example.com
15
+ note: Refund reviewer for order 4412.
@@ -0,0 +1,11 @@
1
+ id: desk-revisit-outage
2
+ goal: Change the release card again and leave the ticket and the pager owner alone
3
+ context: desk-outage has already filed TICKET-1904, releases/2.4.1, and ada@example.com. This run only replaces the release card.
4
+ constraints: Do not add a card. Do not replace the cover. Do not update TICKET-1904 or ada@example.com.
5
+ input:
6
+ focus: releases/2.4.1
7
+ decision: Rollback finished at 16:40 UTC. Checkout 502s stopped after the payments migration was reverted.
8
+ query: "502"
9
+ neighbors:
10
+ - TICKET-1904
11
+ - ada@example.com
@@ -0,0 +1,123 @@
1
+ id: desk-revisit
2
+ memories:
3
+ - new-notebook
4
+ stages:
5
+ - id: revise-one
6
+ entry: true
7
+ route:
8
+ - to: check-neighbors
9
+ model: openrouter/nvidia/nemotron-3.5-lightning:free
10
+ system_prompt: |
11
+ The task input has "focus", "decision", "query", and "neighbors". "neighbors" is a list of keys that must not change.
12
+ Do these steps in order, then stop:
13
+ 1. Call read_memory with memory "new-notebook".
14
+ 2. Call search_memory_cards with memory "new-notebook" and the query.
15
+ 3. Call read_memory_card with memory "new-notebook" and the focus key.
16
+ 4. For each neighbor key, call read_memory_card with memory "new-notebook" and that key.
17
+ 5. Call update_memory_card with memory "new-notebook", the focus key, and content set to the decision. Do not update a neighbor.
18
+ 6. Call read_memory_card again for the focus key.
19
+ 7. Call emit_stage_envelope once with status success, a one-line summary, artifacts [], and payload {"cover":"<the exact cover>","focus":"<focus>","decision":"<decision>","before":"<the focus body before the update>","after":"<the focus body after the update>","neighbors":"<one line per neighbor, as key then a tab then the body you read before the update>","hits":"<the search result as JSON text>"}.
20
+ Do not call add_memory_card or replace_memory. Do not write files. If the focus card is missing, emit status failure.
21
+ io:
22
+ input:
23
+ schema:
24
+ type: object
25
+ required:
26
+ - focus
27
+ - decision
28
+ - query
29
+ - neighbors
30
+ properties:
31
+ focus:
32
+ type: string
33
+ decision:
34
+ type: string
35
+ query:
36
+ type: string
37
+ neighbors:
38
+ type: array
39
+ minItems: 1
40
+ items:
41
+ type: string
42
+ additionalProperties: false
43
+ output:
44
+ schema:
45
+ type: object
46
+ required:
47
+ - cover
48
+ - focus
49
+ - decision
50
+ - before
51
+ - after
52
+ - neighbors
53
+ - hits
54
+ properties:
55
+ cover:
56
+ type: string
57
+ focus:
58
+ type: string
59
+ decision:
60
+ type: string
61
+ before:
62
+ type: string
63
+ after:
64
+ type: string
65
+ neighbors:
66
+ type: string
67
+ hits:
68
+ type: string
69
+ additionalProperties: false
70
+ - id: check-neighbors
71
+ model: openrouter/nvidia/nemotron-3.5-lightning:free
72
+ system_prompt: |
73
+ The input has "cover", "focus", "decision", "neighbors", and "after".
74
+ "neighbors" is lines of "key<tab>body" from before the update.
75
+ Do these steps in order, then stop:
76
+ 1. Call read_memory with memory "new-notebook".
77
+ 2. Call read_memory_card with memory "new-notebook" and the focus key.
78
+ 3. For each neighbor key, call read_memory_card with memory "new-notebook" and that key.
79
+ 4. Call emit_stage_envelope once with status success, a one-line summary, artifacts [], and payload {"focus":"<focus>","after":"<the focus body you just read>","untouched":"<one line per neighbor, as key then a tab then the body you just read>","page":"<the exact cover>","cover_same":"yes or no"}.
80
+ Set cover_same to yes only when the cover equals the "cover" you were given. The focus body should equal "decision". Each neighbor body should equal the body on its line in "neighbors". Do not call add_memory_card, update_memory_card, or replace_memory. Do not write files.
81
+ io:
82
+ input:
83
+ schema:
84
+ type: object
85
+ required:
86
+ - cover
87
+ - focus
88
+ - decision
89
+ - neighbors
90
+ - after
91
+ properties:
92
+ cover:
93
+ type: string
94
+ focus:
95
+ type: string
96
+ decision:
97
+ type: string
98
+ neighbors:
99
+ type: string
100
+ after:
101
+ type: string
102
+ additionalProperties: true
103
+ output:
104
+ schema:
105
+ type: object
106
+ required:
107
+ - focus
108
+ - after
109
+ - untouched
110
+ - page
111
+ - cover_same
112
+ properties:
113
+ focus:
114
+ type: string
115
+ after:
116
+ type: string
117
+ untouched:
118
+ type: string
119
+ page:
120
+ type: string
121
+ cover_same:
122
+ type: string
123
+ additionalProperties: false
@@ -0,0 +1,192 @@
1
+ id: desk
2
+ memories:
3
+ - new-notebook
4
+ stages:
5
+ - id: file-batch
6
+ entry: true
7
+ route:
8
+ - to: decide
9
+ model: openrouter/nvidia/nemotron-3.5-lightning:free
10
+ system_prompt: |
11
+ The task input has "focus", "decision", "query", and "cards". "cards" is a list of objects with "key" and "note".
12
+ Do these steps in order, then stop:
13
+ 1. Call read_memory with memory "new-notebook". Keep that text. Do not call replace_memory.
14
+ 2. For each card, in order, call add_memory_card with memory "new-notebook", that key, and content set to that note. A key may contain "/", spaces, or "@". Pass it through unchanged.
15
+ 3. For each card, call read_memory_card with memory "new-notebook" and that key. The body must equal the note you just wrote.
16
+ 4. Call emit_stage_envelope once with status success, a one-line summary, artifacts [], and payload {"cover":"<the exact read_memory text>","filed":"<a JSON array of {key, note} for every card, in the same order>","focus":"<focus>","decision":"<decision>","query":"<query>"}.
17
+ Do not call update_memory_card. Do not call any memory id other than new-notebook. Do not write files. If any add_memory_card fails, stop and emit status failure. Do not keep filing after a failure.
18
+ io:
19
+ input:
20
+ schema:
21
+ type: object
22
+ required:
23
+ - focus
24
+ - decision
25
+ - query
26
+ - cards
27
+ properties:
28
+ focus:
29
+ type: string
30
+ decision:
31
+ type: string
32
+ query:
33
+ type: string
34
+ cards:
35
+ type: array
36
+ minItems: 2
37
+ items:
38
+ type: object
39
+ required:
40
+ - key
41
+ - note
42
+ properties:
43
+ key:
44
+ type: string
45
+ note:
46
+ type: string
47
+ additionalProperties: false
48
+ additionalProperties: false
49
+ output:
50
+ schema:
51
+ type: object
52
+ required:
53
+ - cover
54
+ - filed
55
+ - focus
56
+ - decision
57
+ - query
58
+ properties:
59
+ cover:
60
+ type: string
61
+ filed:
62
+ type: string
63
+ focus:
64
+ type: string
65
+ decision:
66
+ type: string
67
+ query:
68
+ type: string
69
+ additionalProperties: false
70
+ - id: decide
71
+ route:
72
+ - to: audit
73
+ model: openrouter/nvidia/nemotron-3.5-lightning:free
74
+ system_prompt: |
75
+ The input has "cover", "filed", "focus", "decision", and "query".
76
+ Do these steps in order, then stop:
77
+ 1. Call search_memory_cards with memory "new-notebook" and the query. Do not treat a short hit list as permission to skip a card. There may be more matches than the tool returns.
78
+ 2. Call read_memory_card with memory "new-notebook" and the focus key.
79
+ 3. Call update_memory_card with memory "new-notebook", the focus key, and content set to the decision. This replaces the whole card. Do not update any other key.
80
+ 4. Call read_memory_card again with memory "new-notebook" and the focus key.
81
+ 5. Call emit_stage_envelope once with status success, a one-line summary, artifacts [], and payload {"cover":"<the cover you were given, unchanged>","filed":"<the filed text you were given, unchanged>","focus":"<focus>","decision":"<decision>","query":"<query>","before":"<the first read of the focus card>","after":"<the second read of the focus card>","hits":"<the search result as JSON text>"}.
82
+ Do not call add_memory_card or replace_memory. Do not call any memory id other than new-notebook. Do not write files. If the focus card is missing, emit status failure.
83
+ io:
84
+ input:
85
+ schema:
86
+ type: object
87
+ required:
88
+ - cover
89
+ - filed
90
+ - focus
91
+ - decision
92
+ - query
93
+ properties:
94
+ cover:
95
+ type: string
96
+ filed:
97
+ type: string
98
+ focus:
99
+ type: string
100
+ decision:
101
+ type: string
102
+ query:
103
+ type: string
104
+ additionalProperties: false
105
+ output:
106
+ schema:
107
+ type: object
108
+ required:
109
+ - cover
110
+ - filed
111
+ - focus
112
+ - decision
113
+ - query
114
+ - before
115
+ - after
116
+ - hits
117
+ properties:
118
+ cover:
119
+ type: string
120
+ filed:
121
+ type: string
122
+ focus:
123
+ type: string
124
+ decision:
125
+ type: string
126
+ query:
127
+ type: string
128
+ before:
129
+ type: string
130
+ after:
131
+ type: string
132
+ hits:
133
+ type: string
134
+ additionalProperties: false
135
+ - id: audit
136
+ model: openrouter/nvidia/nemotron-3.5-lightning:free
137
+ system_prompt: |
138
+ The input has "cover", "filed", "focus", "decision", "before", and "after".
139
+ "filed" is a JSON array of objects with "key" and "note".
140
+ Do these steps in order, then stop:
141
+ 1. Call read_memory with memory "new-notebook".
142
+ 2. Call read_memory_card with memory "new-notebook" and the focus key.
143
+ 3. For every other key in "filed", call read_memory_card with memory "new-notebook" and that key.
144
+ 4. Call emit_stage_envelope once with status success, a one-line summary, artifacts [], and payload {"focus":"<focus>","after":"<the focus card body you just read>","untouched":"<one line per other key, as key then a tab then the body>","page":"<the exact cover you just read>","cover_same":"yes or no"}.
145
+ Set cover_same to yes only when the cover you just read is exactly the "cover" you were given. Set it to no otherwise.
146
+ The focus body should equal "decision". Each other body should equal the note in "filed" for that key. Do not call add_memory_card, update_memory_card, or replace_memory. Do not write files.
147
+ io:
148
+ input:
149
+ schema:
150
+ type: object
151
+ required:
152
+ - cover
153
+ - filed
154
+ - focus
155
+ - decision
156
+ - before
157
+ - after
158
+ properties:
159
+ cover:
160
+ type: string
161
+ filed:
162
+ type: string
163
+ focus:
164
+ type: string
165
+ decision:
166
+ type: string
167
+ before:
168
+ type: string
169
+ after:
170
+ type: string
171
+ additionalProperties: true
172
+ output:
173
+ schema:
174
+ type: object
175
+ required:
176
+ - focus
177
+ - after
178
+ - untouched
179
+ - page
180
+ - cover_same
181
+ properties:
182
+ focus:
183
+ type: string
184
+ after:
185
+ type: string
186
+ untouched:
187
+ type: string
188
+ page:
189
+ type: string
190
+ cover_same:
191
+ type: string
192
+ additionalProperties: false
@@ -0,0 +1,39 @@
1
+ id: file-card
2
+ stages:
3
+ - id: file
4
+ entry: true
5
+ model: openrouter/nvidia/nemotron-3.5-lightning:free
6
+ system_prompt: |
7
+ The task input has "key" and "note".
8
+ Do these steps in order, then stop:
9
+ 1. Call add_memory_card with memory "notebook", that key, and content set to the note.
10
+ 2. Call read_memory_card with memory "notebook" and that key.
11
+ 3. Call emit_stage_envelope once with status success, a one-line summary, artifacts [], and payload {"key":"<the key>","note":"<the exact text read_memory_card returned>"}.
12
+ Do not call replace_memory. Do not call update_memory_card. Do not call any memory id other than notebook. Do not write files. If add_memory_card returns MEMORY_CARD_EXISTS, stop and emit status failure with the same payload shape and the error code in the summary.
13
+ io:
14
+ input:
15
+ schema:
16
+ type: object
17
+ required:
18
+ - key
19
+ - note
20
+ properties:
21
+ key:
22
+ type: string
23
+ note:
24
+ type: string
25
+ additionalProperties: false
26
+ output:
27
+ schema:
28
+ type: object
29
+ required:
30
+ - key
31
+ - note
32
+ properties:
33
+ key:
34
+ type: string
35
+ note:
36
+ type: string
37
+ additionalProperties: false
38
+ memories:
39
+ - notebook
@@ -0,0 +1,22 @@
1
+ id: file-ledger
2
+ goal: File the refund ledger as a card, keeping the table
3
+ context: Memory new-notebook already exists. This key does not.
4
+ constraints: The card body is the note exactly. Do not change the cover.
5
+ input:
6
+ key: orders/4412/ledger
7
+ note: |
8
+ # Refund ledger — order 4412
9
+
10
+ Customer asked for store credit. Finance paid the original card instead.
11
+
12
+ | When | Who | Action | Amount |
13
+ | --- | --- | --- | --- |
14
+ | 2026-10-18 09:12 | grace@example.com | Request opened | 86.40 USD |
15
+ | 2026-10-18 11:04 | TICKET-2040 | Store credit declined | — |
16
+ | 2026-10-19 16:22 | payments | Paid to original card | 86.40 USD |
17
+
18
+ Still open:
19
+
20
+ - [ ] Customer confirmed the payout
21
+ - [x] Reviewer recorded the decline
22
+ - [ ] Receipt attached to the ticket