Let nested Factory automations poll, save settings safely, and show investigated Activity - #3383
Let nested Factory automations poll, save settings safely, and show investigated Activity#3383enzoames wants to merge 6 commits into
Conversation
Per-factory jobs live under jobs/factories/<id>/, so Run now and the governed poll check now treat the path as the automation name and the leaf as the role. Create and Settings share source cards with a sticky unsaved bar, and Activity keeps running automations visible under their display names. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Here's a visual recap of what changed: Open the full interactive recap |
…sions. Skip rewriting a legacy factory_config id when the scoped row already exists, merge source settings and poll cursors before deleting leftovers, restore the local self-dispatch fallback port to 3000, and share Slack member-id validation on create. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Addressed all three open Builder review items in ae5170d (also merged
No items skipped. PR not merged. |
Migration 24 now merges leftover factory_config rows before creating the Slack-channel unique index, and Settings/Automations reset per factory so unsaved values and queued run polling cannot leak across factories. Co-authored-by: Cursor <cursoragent@cursor.com>
This comment has been minimized.
This comment has been minimized.
|
Addressed all four open Builder review items in 300059e. Required — migration 24 reconciles duplicate Optional — Settings remounts/resets hydration on factory switch; Automations clears No items skipped. Branch is 1 commit behind |
…ueness. Activity lists held, dispatched, and failed items instead of raw checks. Migration 24 clears every duplicate Slack channel and creates the unique index through the migration SQL executor, Settings no longer clobber in-flight edits, and the generic run-now action accepts a nested jobs path. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Addressed all five open Builder review items in 4237cf9, and landed outcome-first Activity in the same commit. Required — migration 24 clears every duplicate Slack-channel assignment (not only leftover/ Optional — unique-index DDL goes through migration Activity now lists investigated items (held/dispatched/failed) with a collapsed Trace, including failed Slack dispatch from No items skipped. Branch is 1 commit behind |
The audit item-id predicate now returns a boolean so Factory typecheck can pass. Config merge takes slack_workspace from the same row that supplies the channel, so leftover secondary channels are not polled as primary. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Addressed both open Builder review items in b359136. Required — Optional — No items skipped. Branch is 6 commits behind |
There was a problem hiding this comment.
Builder reviewed your changes and found 1 potential issue 🟡
Review Details
Incremental Code Review Summary
The latest revision fixes both previously open issues: the audit report’s item-ID predicate now returns an explicit boolean, and Slack workspace selection stays coupled to the adopted channel during reconciliation. I resolved those stale review threads before this review.
The new Activity projection and audit reporting are otherwise well structured, with factory/org scoping, investigated-item aggregation, provider failure visibility, and focused regression coverage. One failure-state gap remains in the new reporting path. This remains high risk because the change touches shared automation execution and operational failure reporting.
New Findings
- 🟡 MEDIUM — Activity only treats
failedas a failed run, hiding persistedtimed_outandreconciliation_requiredoutcomes as successful/held activity without the stored error. - 🟡 LOW — Collapsed scan traces emit a raw English
Loaded … item(s).string instead of localized copy.
The migration ordering/conflict fixes, nested run-now support, and Settings state protections remain covered by the updated tests. 🧪 Browser testing: Will run after this review (PR touches UI code).
| function readDispatchError( | ||
| dispatch: FactoryAuditEventRecord | null, | ||
| run: FactoryAuditRunSnapshot | undefined, | ||
| ): string | null { | ||
| if (dispatch?.status === "error") { | ||
| return dispatch.summary.trim() || run?.error || "Dispatch failed."; | ||
| } | ||
| if (run?.status === "failed" && run.error) return run.error; |
There was a problem hiding this comment.
🟡 Show all terminal run failures in Activity
triageRuns can persist timed_out and reconciliation_required states with an error, but this projection only emits a dispatch error when status is exactly failed. Activity therefore presents callback/provider failures as successful or held outcomes with no error; treat all error-bearing terminal states as failed, including timed_out and reconciliation_required.

Summary
pathfor jobs nested underjobs/.factory_runs.Test plan
factory-slack-feedback.poll-slack-channelis no longer rejected with “not invoked by a governed Factory automation.”