flood(): a zero-duration event silently blocks gap flooding between its neighbours

オープン
#201 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 10 日以内に返信

@TimeToBuildBob がすでに取り組んでいます。

2026年11月7日 から。

  • #202 @TimeToBuildBob による — オープン

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
55/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
python
領域
backend

調査の方向性

Start with aw_transform/flood.py and trace how events are normalized before the adjacent-pair flooding loop. Add a regression test alongside the flood tests for the provided zero-duration marker example, and check the behavior with the default pulsetime. Done means the gap is handled consistently and the result is idempotent; the issue leaves whether zero-duration events should be preserved as an open semantic question.

索引モデルが issue の本文から書いたものです。

説明

Found this while fuzzing flood() with zero-duration events (after the #165 changes, but I rebuilt the pre-#165 code and it's the same there, so not a regression).

tl;dr: a zero-duration event between two events blocks the gap between those events from being flooded, even though the zero-duration event itself never appears in the output.

Repro on master, default pulsetime=5:

from datetime import datetime, timedelta, timezone
from aw_core.models import Event
from aw_transform.flood import flood

now = datetime(2026, 1, 1, tzinfo=timezone.utc)
def ev(off, dur, tag):
    return Event(timestamp=now + timedelta(seconds=off),
                 duration=timedelta(seconds=dur), data={"t": tag})

# Two events with a 2s gap (16 -> 18), flooded normally:
flood([ev(9, 1, "b"), ev(9, 7, "c"), ev(18, 1, "a")])
# -> 9s+8s ("c"), 17s+2s ("a")    gap filled at midpoint, 10s total

# Same events, plus a zero-duration event in between:
flood([ev(9, 1, "b"), ev(9, 7, "c"), ev(12, 0, "marker"), ev(18, 1, "a")])
# -> 9s+7s ("c"), 18s+1s ("a")     gap NOT filled, 8s total

The marker never shows up in the output (the normalization pass filters out zero-duration events), but it still ate both pairwise slots: the zip(events[:-1], events[1:]) loop only looks at adjacent pairs, so the (c, a) pair is never considered for flooding.

Side effect: flood() isn't idempotent at default pulsetime — a second pass fills the gap, because by then the zero-duration event is gone:

p1 = flood([ev(9, 1, "b"), ev(9, 7, "c"), ev(12, 0, "marker"), ev(18, 1, "a")])
p2 = flood(p1)
# p1: 9s+7s ("c"), 18s+1s ("a")
# p2: 9s+8s ("c"), 17s+2s ("a")   <- different

test_flood_idempotent doesn't catch this since it runs with pulsetime=0.

Possible fix direction: drop/skip duration<=0 events before the pairwise pass. But that's really a semantic question (should zero-duration events be preserved in the output at all? aw-server-rust's flood filters them out entirely), so filing this as an issue first rather than jumping to a PR.

Duplicate check: looked through the flood-related issues/PRs (#73, #105, #135, #139, #142-#146, #165) and none seem to cover this.

主要言語
Python
スター
65
フォーク
74
平均マージ
6日 10時間
マージ済み PR(30日)
9

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

ActivityWatch/aw-core のほかの issue

ActivityWatch/aw-core の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。