Skip to content

feat(events): feed events from scripts beside agent events - #235

Open
adefreitas wants to merge 2 commits into
StackOneHQ:mainfrom
adefreitas:feat/event-model
Open

adefreitas wants to merge 2 commits into
StackOneHQ:mainfrom
adefreitas:feat/event-model

Conversation

@adefreitas

Copy link
Copy Markdown
Collaborator

Summary

Events today are agent hooks only. This adds the model for events from somewhere else (a script now, GitHub and the calendar later): a source, tag, severity, link, repo, PR number and key, plus how the Events tab shows them. Agent events behave as before. No feed ships in this PR; a script posting to the socket is the only producer.

Changes

  • NudgeEvent gains source (agent, github, calendar, script), tag, severity (info, action, alert), url, repo, pr and key, all defaulted. A feed event is always NudgeKind.other, so it stays out of the handoff ledger, the Slack stop path and the permission gates.
  • EventStore: a keyed feed event replaces its earlier self; a feed never takes the selection from the prompt being triaged; each source keeps its own 20 events, apart from the per-session cap.
  • Socket: scripts may send the new fields. Only http and https links are kept, an unknown source or agent becomes a plain agent event, and a feed is forced to kind other and loses fifo_path, hook_pid and has_action_button, so it can't be answered as a prompt.
  • Events tab (FeedStyle): icon by tag, falling back to the source's icon; colour by severity; a chip such as GitHub · api#9. ⏎ and O open the link (primary action reads Open, or Done with no link).
  • Banners: a feed banner doesn't clear other delivered banners (that removed a permission banner's Allow/Deny), reuses its key so a newer one replaces the older, and opens its link when clicked.
  • History records and searches source and tag. Older lines still parse.
  • README: the socket fields and an example, for scripts.
  • Tests: FeedEventTests covers the model, store (keyed replacement, selection, caps), decoding and validation of the socket fields, an unchanged agent hook event, and history round trip.
  • Not included: the notify.sh event command, which is a later PR.

Testing

Automated: ./build.sh (no new warnings), make test-without-xcode (1485 tests, 0 failures), make typecheck-tests.

Manual, after make reload:

  1. Open the panel on Events. Run:
    printf '%s\n' '{"agent":"deploy-bot","event":"other","title":"Deployed","message":"api to production","source":"script","tag":"deploy","severity":"action","url":"https://example.com/deploys/9","repo":"acme/api","pr":9,"key":"deploy:9"}' | nc -U ~/.stack-nudge/panel.sock
    A row appears with an orange box icon and the chip Script · api#9. The footer's primary action reads Open.
  2. Select it and press ⏎. The link opens in the browser and the row goes.
  3. Post the same line again with "message":"api to staging" twice. There is one row, not two.
  4. Trigger a real permission prompt from an agent, then post a feed event. The selection stays on the prompt, and ⏎ still approves the prompt.
  5. Post a feed event with "source":"script","event":"permission","has_action_button":true. It shows as a plain row with no Approve.
  6. Post one with "url":"file:///etc/hosts". The row shows, the footer reads Done, and ⏎ only dismisses it.
  7. Press H, filter by deploy. The feed records show up with the box icon.

Related issues

None.

🤖 Generated with Claude Code

adefreitas and others added 2 commits October 30, 2026 15:14
…o the socket

NudgeEvent gains source (agent, github, calendar, script), tag, severity
(info, action, alert), url, repo, pr and key, all defaulted, so agent hooks
and every existing caller are unchanged. A feed event stays NudgeKind.other,
which keeps it out of the handoff ledger, the Slack stop path and every
permission gate.

- EventStore: a keyed feed event replaces its earlier self; a feed never
  takes the selection from what is being triaged; each source has its own
  cap of 20 instead of sharing the per-session one.
- Banners: a feed banner no longer clears delivered banners (which took a
  permission banner's Allow/Deny with it), reuses its key so a newer one
  replaces the older, and opens its link when clicked.
- Events tab: a tag icon coloured by severity and a source chip
  ("GitHub · api#9"); ⏎ and O open the link, labelled Open.
- Socket: scripts may send the new fields. Only http(s) links are kept, an
  unknown source falls back to agent, and a feed is forced to kind other and
  loses fifo_path, hook_pid and has_action_button, so it can never be a
  prompt.
- History records and searches source and tag; older lines still parse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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