Skip to content

Support '!' prefix in broker messages as inline interrupt#375

Merged
ptone merged 5 commits into
GoogleCloudPlatform:mainfrom
ptone:scion/interrupt-prefix-feature
Jun 9, 2026
Merged

Support '!' prefix in broker messages as inline interrupt#375
ptone merged 5 commits into
GoogleCloudPlatform:mainfrom
ptone:scion/interrupt-prefix-feature

Conversation

@ptone

@ptone ptone commented Jun 9, 2026

Copy link
Copy Markdown
Member

Summary

  • Messages arriving via the broker (Telegram, webhooks, direct messages) that start with ! are now treated as interrupt messages
  • The ! prefix is stripped from the message body before delivery
  • The message is delivered with urgent=true / interrupt semantics, equivalent to --interrupt on the CLI
  • Detection happens in deliverToAgent in the message broker proxy, before persistence and dispatch, so both the stored message and the delivered message reflect the stripped content and urgent flag

Test plan

  • TestMessageBrokerProxy_InterruptPrefix — verifies !-prefixed message is stripped and dispatched with interrupt=true
  • TestMessageBrokerProxy_InterruptPrefixNotStrippedWithoutBang — verifies normal messages are unaffected
  • TestMessageBrokerProxy_InterruptPrefixPersistence — verifies the persisted message has stripped content and urgent=true
  • All existing message broker tests continue to pass

ptone added 2 commits June 8, 2026 03:41
Messages arriving via the broker (Telegram, webhooks, direct messages)
that start with "!" are now treated as interrupt messages: the "!" is
stripped and the message is delivered with urgent/interrupt semantics,
equivalent to --interrupt on the CLI.
deliverToAgent mutates msg.Msg and msg.Urgent in place, but at the
direct-subscriber call site the pointer comes from the event bus and is
shared across all matching subscribers. Shallow-copy before mutating so
the original bus message stays intact.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an inline interrupt signal feature where messages prefixed with '!' are promoted to urgent and have the prefix stripped before delivery. Corresponding unit tests were added to verify the prefix stripping, persistence, and behavior when the prefix is absent. The review feedback highlights a potential issue where messages containing only '!' or trailing spaces after '!' would result in an empty message body, violating validation requirements; a code suggestion is provided to handle this edge case by trimming whitespace and using a fallback default message.

Comment thread pkg/hub/messagebroker.go
Comment on lines +498 to +507
// A leading "!" in the message body acts as an inline interrupt signal:
// strip the prefix and promote to urgent so the harness is interrupted
// before delivery — equivalent to --interrupt on the CLI.
// Shallow-copy to avoid mutating the event-bus pointer shared across subscribers.
if strings.HasPrefix(msg.Msg, "!") {
stripped := *msg
stripped.Msg = msg.Msg[1:]
stripped.Urgent = true
msg = &stripped
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If the incoming message is exactly ! or contains only spaces after ! (e.g., ! ), stripping the prefix leaves an empty string "". According to pkg/messages/types.go (lines 127-129), the Msg field is strictly required to be non-empty (msg field is required). Any downstream component or validation check that runs on the message after retrieval or delivery will fail if Msg is empty.

Additionally, trimming leading and trailing whitespace makes the prefix detection more robust against accidental spaces (e.g., !restart or ! restart).

We can resolve this by trimming the message and falling back to a default non-empty string like "interrupt" if the stripped message would otherwise be empty.

	// A leading "!" in the message body acts as an inline interrupt signal:
	// strip the prefix and promote to urgent so the harness is interrupted
	// before delivery — equivalent to --interrupt on the CLI.
	// Shallow-copy to avoid mutating the event-bus pointer shared across subscribers.
	if trimmed := strings.TrimSpace(msg.Msg); strings.HasPrefix(trimmed, "!") {
		stripped := *msg
		content := strings.TrimSpace(trimmed[1:])
		if content == "" {
			content = "interrupt"
		}
		stripped.Msg = content
		stripped.Urgent = true
		msg = &stripped
	}

Scion Agent (fix-interrupt-prefix) added 3 commits June 9, 2026 15:22
TrimSpace the message before checking for the "!" prefix so leading
whitespace (e.g. "  !restart") is handled correctly. TrimSpace the
content after stripping the prefix so "!  restart" works too. Default
to "interrupt" when the stripped content is empty (bare "!" or "!   ")
to satisfy the Msg-required invariant in StructuredMessage.Validate.

Adds table-driven tests covering all edge cases.
- Use t.Cleanup with explicit error discard for eventbus Close() calls
  in new test functions to satisfy the errcheck linter.
- Add //go:build !no_sqlite constraint to signing_key_shared_test.go
  so newTestStore is available when `go vet -tags no_sqlite` runs.
@ptone ptone merged commit 75d72cf into GoogleCloudPlatform:main Jun 9, 2026
7 of 8 checks passed
@ptone ptone deleted the scion/interrupt-prefix-feature branch June 9, 2026 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant