Merge pull request #702 from fabro-sh/fix/large-stage-event-payloads

Omit current.preamble from stage.completed events
This commit is contained in:
Bryan Helmkamp 2026-08-01 09:34:59 -04:00 committed by GitHub
commit 75a912f130
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 4 additions and 14 deletions

View file

@ -424,7 +424,7 @@ Emitted when a workflow node finishes execution.
| `failure_signature` | string? | Dedup key for repeated failures |
| `context_updates` | object? | Context delta written by this stage |
| `jump_to_node` | string? | Non-edge jump target |
| `context_values` | object? | Full context snapshot after the stage |
| `context_values` | object? | Context snapshot after the stage, minus runtime-only keys such as `current.preamble`. Artifact pointers are not normalized to blob refs — use `checkpoint.completed` for the durable projection |
| `node_visits` | object? | Node visit counts after the stage |
| `loop_failure_signatures` | object? | Loop failure signature counts |
| `restart_failure_signatures` | object? | Restart failure signature counts |

View file

@ -1190,7 +1190,6 @@ fn attach_json_errors_without_prompting_for_human_input() {
"properties": {
"attempt": 1,
"context_values": {
"current.preamble": "Goal: Wait for approval/n",
"current_node": "start",
"graph.goal": "Wait for approval",
"internal.fidelity": "compact",

View file

@ -95,16 +95,10 @@ fn response_from_outcome(node_id: &str, outcome: &Outcome) -> Option<String> {
.and_then(|value| value.as_str().map(ToOwned::to_owned))
}
/// Context values for `StageCompleted` events. Runtime-only keys are stripped,
/// except for `CURRENT_PREAMBLE`, which stage events have historically
/// included.
/// Context values for `StageCompleted` events. Runtime-only keys are stripped.
fn stage_context_values(workflow_context: &Context) -> Option<BTreeMap<String, serde_json::Value>> {
let mut snapshot = workflow_context.snapshot();
let preamble = snapshot.get(context::keys::CURRENT_PREAMBLE).cloned();
artifact::strip_transient_keys(&mut snapshot);
if let Some(preamble) = preamble {
snapshot.insert(context::keys::CURRENT_PREAMBLE.to_owned(), preamble);
}
(!snapshot.is_empty()).then(|| snapshot.into_iter().collect())
}
@ -512,7 +506,7 @@ mod tests {
use super::*;
#[test]
fn stage_context_values_drops_runtime_keys_but_keeps_current_preamble() {
fn stage_context_values_drops_runtime_keys_including_current_preamble() {
let workflow_context = Context::new();
workflow_context.set(
context::keys::INTERNAL_PARALLEL_BRANCH_PREAMBLES,
@ -532,10 +526,7 @@ mod tests {
assert!(!values.contains_key(context::keys::INTERNAL_PARALLEL_BRANCH_PREAMBLES));
assert!(!values.contains_key(context::keys::INTERNAL_STAGE_EXECUTION_ORDINAL));
assert_eq!(
values.get(context::keys::CURRENT_PREAMBLE),
Some(&serde_json::json!("active preamble"))
);
assert!(!values.contains_key(context::keys::CURRENT_PREAMBLE));
assert_eq!(
values.get("response.work"),
Some(&serde_json::json!("durable"))