← Files FlowerARCHIVED FILE

skills/flower-app-guide/references/60-flower-check-adoption.md

5.03 KB · Oct 3, 2026 · 06:30 UTC

↓ Download file

# Flower Check Adoption

Use this when adding `flower-check` to a host application or fixing findings in
application code.

## Contents

- [Purpose](#purpose)
- [Common Findings To Fix](#common-findings-to-fix)
- [Adoption Pattern](#adoption-pattern)
- [Parser Integrity](#parser-integrity)
- [Fixing Findings](#fixing-findings)

## Purpose

`flower-check` is a build-time guardrail for Flower application code. It helps
reject known anti-patterns before generated or handwritten workflow code is
merged.

It is not a replacement for tests.

## Common Findings To Fix

- Blocking inside Step ticks, such as `Thread.sleep`.
- Direct LLM/provider calls inside Steps.
- Hidden orchestration outside Flow/Step boundaries.
- Wait-style Steps without timeout or cancellation behavior.
- Durable Steps without recovery policy.
- Guard callbacks that write, publish, dispatch, subscribe, signal, or perform
  other business side effects (`FLOWER-CHECK-017`).
- Finite EventStep waits without a deadline (`FLOWER-CHECK-018`).
- Durable EventStep waits without `onRecover(...)`, or with predicate-based
  event waits (`FLOWER-CHECK-019`).

## Adoption Pattern

For exact Maven and Gradle installation blocks, read
`references/05-build-and-module-selection.md`. For Maven host applications,
add the check plugin to the build and run:

```powershell
mvn verify
```

If the host app has existing findings, create a baseline intentionally and then
work it down. Do not silence new findings casually.

## Parser Integrity

Flower `0.1.3` emits `FLOWER-CHECK-PARSE` when a Java source file falls back to
conservative non-AST analysis. Treat that diagnostic as incomplete coverage,
not as proof that the file has no findings. It is deliberately outside
suppression and baseline acceptance.

Enable strict parsing in CI when incomplete structural analysis must fail the
build:

```yaml
strictParsing: true
```

The equivalent CLI flag is `--strict-parsing`; Maven and Gradle integrations
also expose `strictParsing`. Fix the source syntax or parser compatibility
instead of trying to baseline the diagnostic. A strict parse error prevents
baseline generation.

## Fixing Findings

When fixing a finding:

1. Read the finding's what/why/fix text.
2. Prefer a Flower-native pattern over suppressing the rule.
3. Add or update a deterministic Flow test.
4. Re-run the host build check.

Before accepting the result, confirm that there are no parse diagnostics, then
search the changed workflow source for every
`flower-check` suppression or ignore directive, including directives that were
already present. `flower-check: no findings` only describes unsuppressed
findings; it is not proof that the suppressions are justified.

Use official suppression or acknowledgement annotations only when the pattern is
intentional and documented. A wait is not safe merely because it is described
as "intentional" or "unbounded." Do not suppress a wait finding unless:

1. the checker-recognized native alternative is incompatible or unsuitable for
   the selected persistence, semantics, or operational model and the source
   records the concrete reason;
2. the wait has a cancellation, deadline/timeout, max-bound, or other terminal
   path appropriate to its semantics; durable controls live in persisted
   state, and a durable time-bounded wait persists its deadline before
   waiting; and
3. deterministic tests prove the selected terminal control, duplicate
   delivery, and restart behavior where recovery is supported.

The explanation in item 1 must be written next to the suppression. Merely
stating that domain state contains a cancellation flag or deadline does not
explain why `EventStep`, a timeout, or another Flower-native alternative cannot
be used with the selected persistence mode.

For example, when the current core durable mode rejects
`StepContext.startTimeout(...)`, a persisted domain deadline can be the correct
alternative, but the suppression must say that and the test must prove the
deadline survives restart. A truly indefinite monitor needs a reason that
documents its ownership, liveness, and shutdown model.

A suppression is not justified when durable completion still depends on a
Step-local `Future`, `CompletionStage`, or callback handle. Persist the external
operation lifecycle and prove that recovery observes the same operation without
submitting a second provider/business request for a dispatch-once contract.

For item 3, actually deliver the same logical signal or event more than once.
Assert that no business side effect is repeated and that the final domain and
Flow state remain correct. Repeated worker ticks alone are not
duplicate-delivery evidence.

Apply these three conditions to every suppression independently. Maintain a
suppression-to-test map when multiple waits are present: duplicate delivery,
terminal-control, or recovery coverage for one wait cannot justify another
wait. In particular, recovery from a later Step does not cover a suppressed
earlier Step, and new work must preserve existing suppression-specific tests.

Otherwise fix the design and keep the finding active until the complete
verification passes.

SHA-256: 952b746fd046ab0e8840162563e948b77381c30f5cf694d784a28d63cf225967