Skip to content

docs(automation): read a sweep's outcome counters, not just its status - #1355

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-568-adopt-flow-run-summaries
Aug 27, 2026
Merged

docs(automation): read a sweep's outcome counters, not just its status#1355
os-steve merged 1 commit into
mainfrom
claude/issue-568-adopt-flow-run-summaries

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes #568

Adoption and verification, not implementation. The app-side detector that card considered — assignment + decision + notify counters 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. No src/ edits, no script nodes, 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.summary on a terminal run of the real AutomationEngine, through the in-memory harness in test/helpers/flow-harness.ts. Command:

pnpm exec vitest run test/flow-run-summary.test.ts --maxWorkers=2
flow run selected acted skipped writes observed
opportunity_stagnation 2 stalled deals, none nudged yet 2 4 0 2 tasks + 2 notifications
contract_renewal 2 contracts inside the notice window 2 5 1 2 tasks + 1 renewal opp + 2 notifications
campaign_enrollment 2 eligible leads, after the screen resume 3 2 1 2 member rows

All three populate. Two details worth recording:

  • campaign_enrollment is not a scheduled sweep any more — it is type: 'screen', rewritten since the incident this card records (a cron seeds no input variables). Its first execute pauses at the screen and correctly carries no summary; the summary arrives on resume. That matches the platform contract, which sets summary only on a terminal result.
  • result.status is undefined on a completed run and success is true in 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_stagnation and contract_renewal both 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.

run totals run-level predicate find_existing_task.selected gate skips
healthy steady state (all deals already nudged) selected 4, acted 0 fires 2 2
dead gate (the shape the incident had) selected 2, acted 0 fires 0 2
genuinely idle (nothing stalled) selected 0, acted 0 quiet 0

The 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.mdx and 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 in src/ 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.
  • Empty-frontmatter changeset: docs and tests only, so this releases nothing to users.

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 = 0 on the acted_count field 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

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.
@vercel

vercel Bot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hotcrm Ignored Ignored Aug 27, 2026 8:57am

Request Review

@github-actions github-actions Bot added the ci/cd CI plumbing and the verification pipeline label Aug 27, 2026
@os-steve
os-steve marked this pull request as ready for review August 27, 2026 09:01
@os-steve
os-steve added this pull request to the merge queue Aug 27, 2026
Merged via the queue into main with commit 78fb58f Aug 27, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd CI plumbing and the verification pipeline

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No production signal when a scheduled sweep runs and does nothing

2 participants