Problem
Signals posts inbox report notifications to Slack and invites the reader to "reply in this thread and mention @PostHog". Doing so creates a Code task, but that task has no link to the report:
posthog/temporal/ai/slack_app/activities/task_creation.py creates it with origin_product=SLACK and no signal_report_id.
- Nothing writes a
task_run artefact, so the task never appears in the report's Runs section in the inbox (that section reads the artefact log, see products/signals/frontend/inbox/logics/inboxReportDetailLogic.ts around reportTasks). The in-app "Ask AI" discussion does appear there because POST /tasks with origin_product=signal_report calls record_report_task(relationship="discussion").
- No engagement is recorded either: no
Inbox report action event, no SignalReportAction row, no task/report association. A Slack conversation about a report is invisible to the scout inactivity sweep (scout_harness/inactivity.py, which already exempts Slack-routed scouts for this reason) and to the report lifecycle dashboards.
Even when the Slack agent changes the report's state (dismiss/resolve), only the dismissal artefact and a signal_report_status_changed event land. The task_run link is still missing.
Example: a report was resolved through a Slack mention today. The report shows status=resolved with no linked task and no recorded action; the task shows no report.
What we need
1. Resolve the report id at mention time
Both report notification paths put the report URL in a "View report in PostHog" button:
products/signals/backend/slack_inbox_notifications.py (_build_message_blocks, url /project/<team>/inbox/reports/<uuid>)
products/signals/backend/scout_harness/slack_delivery.py (scout emissions, url /project/<team>/inbox/<uuid>)
Neither persists thread_ts, so the mention handler cannot look the report up. Options, in order of preference:
- a. Persist a
(integration, channel, thread_ts) -> report_id mapping when the notification is posted (chat_postMessage returns ts). Cleanest and survives message edits.
- b. Parse the parent message's button URL from the thread messages the mention workflow already fetches. No schema change, but couples the handler to the URL shape.
Should also work for the evidence replies the notification posts into the same thread (they share thread_ts).
2. Link the task to the report
In task_creation.py, when the thread resolves to a report:
- pass
signal_report_id to tasks_facade.create_and_run_task (it already accepts it), so Task.signal_report_id is set and the task joins the report in analytics;
- call
products.signals.backend.task_run_artefacts.record_report_task(relationship=TASK_RUN_TYPE_DISCUSSION, run_id=...) inside the same transaction, so the task shows in the report's Runs section as "Discussion", like Ask AI. create_and_run_task does not do this itself; only the create_task REST path does.
Decisions:
- Keep
origin_product=SLACK? The Slack relay (SlackThreadTaskMapping, follow-up forwarding) keys on it, and the discussion-note forward (_forward_signals_discussion_note) and the repo-less "exempt" task shape key on SIGNAL_REPORT. Proposal: keep SLACK, write the artefact explicitly, and forward the discussion note (forward_report_discussion_note) from the Slack path too so the report's scout sees the question.
- Does a Slack discussion count toward the report task cap (
enforce_report_task_cap)? Proposal: yes, same as Ask AI.
- Should the task file into the report's channel rather than the mentioning user's personal channel?
3. Record engagement
Once the task is linked, the discussion should count as report engagement the same way Ask AI does. Either:
- fire a server-side
Inbox report action event with action_type=discuss and surface=slack from the handler (matches the frontend contract in products/signals/frontend/inbox/inboxAnalytics.ts, needs report_id and the mentioning user's identity), or
- treat a user-attributed
task_run artefact of type discussion as engagement in the sweep and dashboards.
The first keeps one event family for all surfaces and is probably the smaller change.
4. Related: user-requested pr_merged resolutions read as automatic
When the Slack agent resolves a report at a person's request, it picks reason=pr_merged. The dismissal artefact carries user_id/user_uuid, but consumers that exclude pr_merged as an automatic transition drop it. The identity fields distinguish the two cases; the exclusion should only apply when no user identity is present. Can ship separately.
Out of scope
- The legacy "Dismiss" button handler (
products/slack_app/backend/api.py, _handle_signals_dismiss_report) already attributes its artefact to the user and is unaffected.
- Reactions on agent replies are turn-level feedback, not report engagement.
Verification
- Mention
@PostHog in a report notification thread and ask a question. The task appears under the report's Runs section as "Discussion", Task.signal_report_id is set, and the report shows a discuss action from surface=slack.
- Ask the agent to resolve the report from the thread. The report resolves, the task is linked, and the resolution counts as user engagement.
- A mention in a thread that is not a report notification still creates a plain Slack task with no report link.
Problem
Signals posts inbox report notifications to Slack and invites the reader to "reply in this thread and mention
@PostHog". Doing so creates a Code task, but that task has no link to the report:posthog/temporal/ai/slack_app/activities/task_creation.pycreates it withorigin_product=SLACKand nosignal_report_id.task_runartefact, so the task never appears in the report's Runs section in the inbox (that section reads the artefact log, seeproducts/signals/frontend/inbox/logics/inboxReportDetailLogic.tsaroundreportTasks). The in-app "Ask AI" discussion does appear there becausePOST /taskswithorigin_product=signal_reportcallsrecord_report_task(relationship="discussion").Inbox report actionevent, noSignalReportActionrow, no task/report association. A Slack conversation about a report is invisible to the scout inactivity sweep (scout_harness/inactivity.py, which already exempts Slack-routed scouts for this reason) and to the report lifecycle dashboards.Even when the Slack agent changes the report's state (dismiss/resolve), only the
dismissalartefact and asignal_report_status_changedevent land. Thetask_runlink is still missing.Example: a report was resolved through a Slack mention today. The report shows
status=resolvedwith no linked task and no recorded action; the task shows no report.What we need
1. Resolve the report id at mention time
Both report notification paths put the report URL in a "View report in PostHog" button:
products/signals/backend/slack_inbox_notifications.py(_build_message_blocks, url/project/<team>/inbox/reports/<uuid>)products/signals/backend/scout_harness/slack_delivery.py(scout emissions, url/project/<team>/inbox/<uuid>)Neither persists
thread_ts, so the mention handler cannot look the report up. Options, in order of preference:(integration, channel, thread_ts) -> report_idmapping when the notification is posted (chat_postMessagereturnsts). Cleanest and survives message edits.Should also work for the evidence replies the notification posts into the same thread (they share
thread_ts).2. Link the task to the report
In
task_creation.py, when the thread resolves to a report:signal_report_idtotasks_facade.create_and_run_task(it already accepts it), soTask.signal_report_idis set and the task joins the report in analytics;products.signals.backend.task_run_artefacts.record_report_task(relationship=TASK_RUN_TYPE_DISCUSSION, run_id=...)inside the same transaction, so the task shows in the report's Runs section as "Discussion", like Ask AI.create_and_run_taskdoes not do this itself; only thecreate_taskREST path does.Decisions:
origin_product=SLACK? The Slack relay (SlackThreadTaskMapping, follow-up forwarding) keys on it, and the discussion-note forward (_forward_signals_discussion_note) and the repo-less "exempt" task shape key onSIGNAL_REPORT. Proposal: keepSLACK, write the artefact explicitly, and forward the discussion note (forward_report_discussion_note) from the Slack path too so the report's scout sees the question.enforce_report_task_cap)? Proposal: yes, same as Ask AI.3. Record engagement
Once the task is linked, the discussion should count as report engagement the same way Ask AI does. Either:
Inbox report actionevent withaction_type=discussandsurface=slackfrom the handler (matches the frontend contract inproducts/signals/frontend/inbox/inboxAnalytics.ts, needsreport_idand the mentioning user's identity), ortask_runartefact of typediscussionas engagement in the sweep and dashboards.The first keeps one event family for all surfaces and is probably the smaller change.
4. Related: user-requested
pr_mergedresolutions read as automaticWhen the Slack agent resolves a report at a person's request, it picks
reason=pr_merged. The dismissal artefact carriesuser_id/user_uuid, but consumers that excludepr_mergedas an automatic transition drop it. The identity fields distinguish the two cases; the exclusion should only apply when no user identity is present. Can ship separately.Out of scope
products/slack_app/backend/api.py,_handle_signals_dismiss_report) already attributes its artefact to the user and is unaffected.Verification
@PostHogin a report notification thread and ask a question. The task appears under the report's Runs section as "Discussion",Task.signal_report_idis set, and the report shows adiscussaction fromsurface=slack.