• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Rotorsoft / act-root / 32887606970
100%

Build:
DEFAULT BRANCH: master
Ran 25 Aug 2026 07:08PM UTC
Jobs 1
Files 115
Run time 1min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

25 Aug 2026 07:05PM UTC coverage: 100.0%. Remained the same
32887606970

push

github

web-flow
fix(act): stop a dynamic resolution from hijacking a projection's target (#1571)

* fix(act): stop a dynamic resolution from hijacking a projection's target

A stream a projection serves is served by that projection alone — every
payload on it goes to the batch handler. A reaction resolving onto that target
therefore never runs, and worse, hands the projection an aggregate it knows
nothing about: a Counter fold's table receiving `{stream:"o1", state:{label:
"ping"}}` from an unrelated Other aggregate.

The static form is rejected at build. The dynamic form was not, because a
`.to(fn)` target is a function until an event arrives — so the guard skipped
it and nothing checked later.

One condition, at the one place that decides whether a reaction consumes a
stream:

    return !(dynamic && batch_handlers.has(stream));

`dynamic` is an exact discriminator rather than a heuristic: a static reaction
onto a projection's target is rejected at build, and a projection's own
consumption is synthesized static. So a dynamic resolution landing there is by
definition the misrouting the build guard could not see.

I first wrote this as a correlate-time check with injected dependencies on
both cycles — two mechanisms for one rule, and it only fixed the subscription
while the payload was still built from the registry. Reverted for the single
condition.

Closes #1563

* fix(act): report the skipped misrouting instead of dropping it silently

The first version of this fix stopped the projection being fed a foreign
aggregate and left the other half of #1563 exactly as it was: a reaction that
silently never runs, with no error, no retry and nothing in blocked_streams().
Fixing the corruption and keeping the silence is the same failure class as the
bug.

A throw is not available here — drain-cycle:693 hands anything thrown to the
circuit breaker as a store failure, so a config error that never resolves
itself would stall the whole drain on a cooldown loop. The signal is an ... (continued)

4290 of 4290 branches covered (100.0%)

Branch coverage included in aggregate %.

12 of 12 new or added lines in 1 file covered. (100.0%)

9261 of 9261 relevant lines covered (100.0%)

1166.39 hits per line

Jobs
ID Job ID Ran Files Coverage
1 32887606970.1 25 Aug 2026 07:08PM UTC 115
100.0
GitHub Action Run
Source Files on build 32887606970
  • Tree
  • List 115
  • Changed 1
  • Source Changed 1
  • Coverage Changed 1
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses
  • Back to Repo
  • Github Actions Build #32887606970
  • 0f53541d on github
  • Prev Build on master (#32881014490)
  • Next Build on master (#32896299477)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc