docs(automation): read a sweep's outcome counters, not just its status - #1355
Merged
Conversation
The platform now reports what every flow run actually did — selected / acted / skipped, per node, with the same numbers persisted as columns on `sys_automation_run`. Nothing here consumed that yet, and the admin guide still sent operators to the run's status, which is the one signal that cannot tell a sweep doing its job from a sweep silently doing nothing. "Where to monitor automation" now names the counters, the alert predicate worth wiring, and the qualifier that keeps it honest: this app's sweeps re-select the same records every morning and gate each on whether it was already handled, so their healthy steady state trips the run-level predicate exactly as a broken sweep does. The per-node fold is what separates them — whether the idempotency lookup accounts for the gate skips. Prose only, in all three locales; no anchors or anchored links. `test/flow-run-summary.test.ts` pins the adoption. Nothing in `src/` consumes the summary, so a platform bump that stopped populating it would return this app to having no production signal, silently — which is the failure mode the whole thread is about. The test also pins the reading rule as an executable A/B: a correctly idempotent run and a dead gate both trip the run-level predicate, and only the per-node probe count tells them apart. No app-side counter, and none coming: that route is rejected permanently now that the platform ships the measurement for every flow.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #568
Adoption and verification, not implementation. The app-side detector that card considered —
assignment+decision+notifycounters inside a loop — stays rejected, permanently: the platform ships the measurement for every flow now, so there is nothing here for an app to build or maintain. Nosrc/edits, noscriptnodes, no per-flow instrumentation.Verified green on
4def180(the tip of this branch):pnpm verify— validate, typecheck, lint, i18n gate, hygiene, token ratchet, build, test — 143 test files, 3009 passed, 1 skipped, 0 failed.Step 1 — the counters populate, measured off real runs
The card asked for a measurement rather than a status, so these are read from
result.summaryon a terminal run of the realAutomationEngine, through the in-memory harness intest/helpers/flow-harness.ts. Command:opportunity_stagnationcontract_renewalcampaign_enrollmentAll three populate. Two details worth recording:
campaign_enrollmentis not a scheduled sweep any more — it istype: 'screen', rewritten since the incident this card records (a cron seeds no input variables). Its firstexecutepauses at the screen and correctly carries no summary; the summary arrives onresume. That matches the platform contract, which setssummaryonly on a terminal result.result.statusisundefinedon a completed run andsuccessistruein every row above, including the ones that wrote nothing. The counters really are the only signal that separates them, which is the card's thesis holding up.The reading rule — the run-level predicate is not sufficient on its own
The platform's headline detector is
selected > 0 AND acted = 0 AND unmeasured = 0. Measured against this app's sweeps, it fires on a healthy run too, and the reason is structural rather than a defect:opportunity_stagnationandcontract_renewalboth re-select the same records every morning and gate each one on whether it was already handled, so "everything has already been nudged" is also selected-but-not-acted.find_existing_task.selectedThe per-node fold separates them cleanly: healthy means the idempotency lookup accounts for the gate skips; the bug means the gate closed on records nothing had handled. The idle run stays quiet either way, which is the property the card most needed.
What changed
content/docs/administration/automation.mdxand both translations — the "Where to monitor automation" section named only the run's status, the one signal this card documents as the lie. It now names the counters, the alert predicate, and the qualifier above. Prose only: no new headings, no anchors, no anchored links.test/flow-run-summary.test.ts— pins the adoption and the reading rule. Nothing insrc/consumes the summary, so a platform bump that stopped populating it would return this app to having no production signal, silently. The A/B above is pinned as an executable pair rather than left in prose.Step 2 and 3
Step 2 (is anything worth documenting) — yes, and it is the diff above; the operator half was actively misdirecting. Step 3 — the counters populate, so the card's own exit condition is met and this closes it.
One finding for upstream, reported rather than filed: the platform states the alert as
selected_count > 0 AND acted_count = 0 AND unmeasured_count = 0on theacted_countfield description without the idempotent-sweep caveat, and any app using a re-select-then-gate sweep will false-positive on it in normal operation. Not a blocker here and not a local workaround — the per-node data needed to disambiguate is already shipped.Generated by Claude Code