Skip to content

Commit d1ac52d

Browse files
Tiny Systemsclaude
andcommitted
send_signal: wait for the target flow to settle before start fires
Wire the SDK's shared readiness gate (WaitFlowReady) into the send_signal tool: on {send:true}/{start:true}, poll the flow's node statuses until settled (bounded, best-effort), then fire — and surface still-reconciling nodes and hard reconcile faults in the output. Closes the 'spans:1, errors:0 false clean' gap where a signal fired right after build_flow vanished downstream and the model re-fired blindly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 37f3fea commit d1ac52d

3 files changed

Lines changed: 28 additions & 4 deletions

File tree

cmd/signal_tool.go

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,32 @@ func (sendSignalTool) Execute(ctx context.Context, execCtx sdktools.ExecutionCon
6262
if err != nil {
6363
return sdktools.ToolResult{Success: false, Error: fmt.Sprintf("marshal data: %v", err)}
6464
}
65+
66+
// Readiness gate for start fires ({send:true}/{start:true}): a signal
67+
// fired into a half-reconciled flow reaches the trigger but downstream
68+
// nodes aren't routing yet — the message vanishes and the trace shows a
69+
// lone trigger span that reads as a clean run. Wait for the target flow's
70+
// node statuses to settle (best-effort, bounded), then fire regardless,
71+
// surfacing any nodes that are still pending or hard-failed so the model
72+
// knows what a thin trace means. Same gate the platform playground uses.
73+
out := map[string]interface{}{"sent": true, "node_id": nodeID, "port": port}
74+
if sdktools.IsStartFire(data) {
75+
els, waited := sdktools.WaitFlowReady(ctx, execCtx, nodeID)
76+
if waited > 0 {
77+
out["readiness_waited_ms"] = waited.Milliseconds()
78+
}
79+
var warnings []string
80+
warnings = append(warnings, sdktools.NodeStatusFaults(els)...)
81+
if pending := sdktools.NotReadyNodes(els); len(pending) > 0 {
82+
warnings = append(warnings, fmt.Sprintf("nodes still reconciling (a signal may not reach them yet): %v — if the trace shows only the trigger span, re-fire after they settle", pending))
83+
}
84+
if len(warnings) > 0 {
85+
out["warnings"] = warnings
86+
}
87+
}
88+
6589
if err := execCtx.SignalSender.SendSignal(ctx, execCtx.ProjectName, nodeID, port, payload, ""); err != nil {
6690
return sdktools.ToolResult{Success: false, Error: err.Error()}
6791
}
68-
return sdktools.ToolResult{Success: true, Output: map[string]interface{}{
69-
"sent": true, "node_id": nodeID, "port": port,
70-
}}
92+
return sdktools.ToolResult{Success: true, Output: out}
7193
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/rs/zerolog v1.34.0
1313
github.com/spf13/cobra v1.10.2
1414
github.com/tiny-systems/ajson v0.1.6
15-
github.com/tiny-systems/module v0.13.38
15+
github.com/tiny-systems/module v0.13.39
1616
github.com/tiny-systems/platform-api v0.5.6
1717
github.com/tiny-systems/platform-go v0.2.4
1818
google.golang.org/grpc v1.81.1

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,8 @@ github.com/tiny-systems/module v0.13.37 h1:a4xsLJQbWhXGqo3CPNxnYmcLD+kmreBHFZk8A
723723
github.com/tiny-systems/module v0.13.37/go.mod h1:Fu40dAvHY301ZoXVa3NErAR+M24WmpGkg0tjK7RQP+E=
724724
github.com/tiny-systems/module v0.13.38 h1:3INHGYHGhtkVLIjC15l6AHwiNRQV603t5dRhjIWd2Fk=
725725
github.com/tiny-systems/module v0.13.38/go.mod h1:Fu40dAvHY301ZoXVa3NErAR+M24WmpGkg0tjK7RQP+E=
726+
github.com/tiny-systems/module v0.13.39 h1:tKQg7szqH2N4t938dNzc5ga5VJ0ZhT4N4bDCcW+zK/8=
727+
github.com/tiny-systems/module v0.13.39/go.mod h1:Fu40dAvHY301ZoXVa3NErAR+M24WmpGkg0tjK7RQP+E=
726728
github.com/tiny-systems/otel-collector v0.5.1 h1:tylLj7f7O7n5o9R383Lojd0fN7j5jgZ76zFshJ0SE6c=
727729
github.com/tiny-systems/otel-collector v0.5.1/go.mod h1:EGo1dQ3+5iG3ejGJ8y9kMgHhOGB6WyoasJDUHesKXEA=
728730
github.com/tiny-systems/platform-api v0.5.6 h1:IJPslzpV06cJcHaloZ9mm18pE8DCpCqLc/PD0NGFOUA=

0 commit comments

Comments
 (0)