Commit 5b56c39
committed
feat(core): Workflow P4a — extractAndStripMeta + meta on RunOutcome (#4721)
First half of P4 (per the refined #4721 plan). Extracts the script's
`export const meta = {...}` declaration into a typed object so the
workflow tool's display payload, and the future /workflows command +
phase-tree UI, can read it without re-parsing the script source. The
other half of P4 (slash command + KIND_NAMES extension + phase-tree
UI + WorkflowTaskRegistry) is queued as a follow-up PR.
Architecture: reuse the P1 brace-walker (zero-dep, no parser deps) to
locate the meta object literal's source range, then evaluate the literal
inside a fresh `vm.createContext(Object.create(null))` — null-prototyped
globalThis, no host bridge (no `args` / `process` / `require` / workflow-
sandbox globals). The vm realm still exposes its OWN intrinsics
(`Object` / `Math` / `Date` / `JSON`), which is fine: meta extraction is
one-shot at tool invocation, not replayed on resume. validateMeta walks
the eval result field-by-field and copies into a fresh host-realm plain
object — no JSON round-trip needed because every contract field is a
primitive.
User-visible additions:
- `extractAndStripMeta(source)` exported from workflow-sandbox.ts
- `WorkflowMeta` interface (`{ name, description, whenToUse?, phases?: Array<{title, detail?, model?}> }`) — verbatim shape from upstream Claude Code 2.1.168
- `WorkflowSandbox.getMeta()` accessor alongside `getPhases()` / `getLogs()`
- `WorkflowRunOutcome.meta: WorkflowMeta | null` (non-breaking add)
- `WorkflowExecutionError.meta: WorkflowMeta | null` so the failure
display shows the workflow's name / description / phases even when
the script body throws
- `WorkflowTool.execute` adds `meta` to the returnDisplay payload when
present (omitted when the script had no meta)
Error messages verbatim from upstream where applicable:
- `meta.name must be a non-empty string`
- `meta.description must be a non-empty string`
Refactor: P1's `stripExportMeta` is preserved as a thin wrapper around
a new `findMetaBlockBounds` helper that both old and new functions
share. All 86 existing sandbox tests pass unchanged (no behavior
regression in the strip path).
Tests:
- 11 new `extractAndStripMeta` unit tests covering happy path, optional
fields, missing-required validation, malformed shape, vm-eval failure,
null-prototype globalThis (no `args` / `process` / `require`), and
unbalanced braces
- 3 new `createWorkflowSandbox.getMeta()` integration tests
- 3 new `WorkflowOrchestrator` outcome.meta tests (null path, parsed path,
meta-survives-body-throw on the error path)
- 3 new `WorkflowTool` display payload tests (meta in payload, omitted
when absent, present on failure path)
Suite: 207/207 workflow + adjacent regression green; typecheck +
lint clean on packages/core. (Pre-existing acp test type errors in
packages/cli are unrelated; CI will confirm.)
Related #4721 (parent design — multi-phase, not closed by this PR)
Related #4732 (P1) #4947 (P2) #5034 (P3) — all merged
P4b follow-up: /workflows command + TaskKind workflow union + BackgroundTasksPill KIND_NAMES + phase-tree UI + WorkflowTaskRegistry1 parent e834271 commit 5b56c39
6 files changed
Lines changed: 502 additions & 6 deletions
File tree
- packages/core/src
- agents/runtime
- tools/workflow
Lines changed: 48 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
177 | 177 | | |
178 | 178 | | |
179 | 179 | | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
180 | 228 | | |
181 | 229 | | |
182 | 230 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
164 | 165 | | |
165 | 166 | | |
166 | 167 | | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
167 | 175 | | |
168 | 176 | | |
169 | 177 | | |
| |||
172 | 180 | | |
173 | 181 | | |
174 | 182 | | |
175 | | - | |
| 183 | + | |
176 | 184 | | |
177 | 185 | | |
178 | 186 | | |
| |||
199 | 207 | | |
200 | 208 | | |
201 | 209 | | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
202 | 218 | | |
203 | 219 | | |
204 | 220 | | |
| |||
1091 | 1107 | | |
1092 | 1108 | | |
1093 | 1109 | | |
| 1110 | + | |
1094 | 1111 | | |
1095 | 1112 | | |
1096 | 1113 | | |
| |||
1105 | 1122 | | |
1106 | 1123 | | |
1107 | 1124 | | |
| 1125 | + | |
1108 | 1126 | | |
1109 | 1127 | | |
1110 | 1128 | | |
| |||
Lines changed: 163 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
9 | 13 | | |
10 | 14 | | |
11 | 15 | | |
| |||
136 | 140 | | |
137 | 141 | | |
138 | 142 | | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
139 | 262 | | |
140 | 263 | | |
141 | 264 | | |
| |||
175 | 298 | | |
176 | 299 | | |
177 | 300 | | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
178 | 340 | | |
179 | 341 | | |
180 | 342 | | |
| |||
0 commit comments