* fix(make): name what make clean deletes and refuse under a live gateway
`make help` described `make clean` as cleaning up "temporary files", but it
deletes backend/.deer-flow: the local database, users, threads, uploads,
memory, and secrets. Both Docker stacks mount that directory into the
deer-flow-gateway container, and `make stop` only stops local services, so
the data could be deleted under a running Gateway.
Say what is deleted in the help text and before deleting, and refuse while
the deer-flow-gateway container is running. The check runs before `make
stop`, which would otherwise stop the running stack's sandboxes first; a
missing or unreachable Docker passes.
* docs(changelog): reference #6351 for the make clean guard
* fix(make): share make clean's data list and pin stop before the delete
The help line listed "database, threads, uploads, secrets" while the
deletion notice also named users and memory. Define the list once in
RUNTIME_DATA_CONTENTS and use it in both.
Running sandbox containers left behind by `make down` are already stopped
by `make stop` (serve.sh --stop reaps deer-flow-sandbox*), which runs after
the guard and before the delete. Note that in the guard script, and pin
the ordering: the stub stop now records that the data still exists.
---------
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
* feat(skill): strengthen maintainer orchestrator review workflow
Add seven enhancements to the deerflow-maintainer-orchestrator skill and
mirror them in docs/agents/maintainer-sop.md:
- Posting gate as confidence x severity, with a maintainer-only notes
channel for sub-threshold observations. Clarifies that "no high-confidence
findings" spans P0/P1/P2, not just P0.
- Batch handling: cluster by relatedness, then synthesize cross-PR overlap,
merge-order/conflict surface, and composition risk.
- Competing PR comparison anchored to the issue's acceptance criteria, with a
maintainer-only ranking and a constructive per-PR public surface.
- Existing comments suppress duplicate posting, not analysis: review fully and
post only the net-new delta, with an idempotency guard for re-runs.
- Green-CI discipline: checks are signal not verdict; read the changed code
path regardless of a green rollup.
- Fork PR head resolution via pull/<n>/head and a pre-post head-SHA recheck.
- Competing-PR detection in artifact resolution; output gains Already
covered / Maintainer notes / Batch synthesis fields.
* docs(skill): rewrite maintainer SOP as design rationale, not a skill restatement
* docs(skill): rename maintainer SOP doc to maintainer-orchestrator-design
* feat(skill): allow controlled fan-out when a related cluster exceeds one context
---------
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
* feat(blocking-io): add changed-lines blocking-IO scanner (L1)
* feat(blocking-io): add scan-changed CLI wrapper
* feat(skill): add blocking-io-guard developer SOP skill
* docs(blocking-io): point contributors at the blocking-io-guard skill
* style(blocking-io): apply ruff format to scanner and tests
* docs(backend): document changed-lines blocking-IO scanner in CLAUDE.md
* feat(skill): add post-fix re-scan check and PR batching policy
* refactor(skill): fix SOP step ordering, align template with repo conventions
- Move re-scan into an explicit 'apply the fix' step (was wedged after
anchor generation while telling you to go back before the anchor)
- Renumber steps 0-6; drop undefined 'L1' jargon
- Mode A: document that the diff is <base>...HEAD (commit first)
- Mode B: prefer make detect-blocking-io + findings JSON file
- anchor template: module-level pytestmark per tests/blocking_io convention
- CLAUDE.md: fix 'git diff --base' phrasing
* fix(skill): catch findings introduced without touching the blocking line
Review follow-up: changed-line intersection alone misses the case where a
new async caller exposes an old sync helper — the static finding sits on
the untouched blocking line, so Mode A returned empty and the SOP stopped
on a false 'no blocking-IO surface'.
Selection is now a union over the changed files:
- findings on added lines of git diff <base>...HEAD (kept: a second
identical symbol in an already-flagged function collides on the stable
key and only this selection sees it);
- findings new versus the merge base, matched by (path, function,
symbol) — never line numbers.
Base sources are materialized via git show <merge-base>:<path>; files
absent at base count every head finding as new. SKILL.md now states the
residual same-file-only blind spot (cross-file async callers) instead of
treating an empty list as proof of zero exposure, and only requires
reading sop-skeleton.md when generalizing to another detector domain.
* docs(skill): examples teach test-writing, the teeth check defines the rule
All examples in the references/template are filesystem-flavored; make
explicit that they are instances, not the SOP's boundary — the same rules
apply to every detector category (FILE_IO, HTTP, SUBPROCESS, SLEEP) and
acceptance is always red/green teeth, never similarity to an example.
Neutralize the template's arrange comment accordingly.
* fix(blocking-io): harden changed-lines scanner per review
- Dedup the union selection by the stable key (path, function, symbol)
instead of dict identity, so a future selector returning copied dicts
cannot silently empty the result.
- parse_changed_lines now handles any unified diff: context lines advance
the new-file counter, \-markers and deletions do not, and the counter
resets at each +++ header. Previously correct only for --unified=0.
- Add blocking_io_static.scan_source (in-memory scan); base-version
comparison no longer round-trips through temp files.
- Empty Mode A report now prints the same-file-only reachability caveat
at the point of use instead of relying on the SOP text alone.
* docs(skill): bound best-effort cleanup when the offload sits in finally
Lesson from the #3505 review: the SOP routinely drives 'offload the
cleanup branch' transformations, and an awaited cleanup in finally can
mask or stall the primary exception. One sentence in Step 2 closes that
gap at the point where the fix is written.