Skip to content

align exclude_events default with hooks-logging: drop llm:stream_block_delta by default#28

Merged
bkrabach merged 3 commits into
mainfrom
feat/align-exclude-default
May 31, 2026
Merged

align exclude_events default with hooks-logging: drop llm:stream_block_delta by default#28
bkrabach merged 3 commits into
mainfrom
feat/align-exclude-default

Conversation

@bkrabach
Copy link
Copy Markdown
Collaborator

Aligns the hook-context-intelligence exclude_events default with amplifier-module-hooks-logging — both now default to ['llm:stream_block_delta'], keeping the high-frequency per-token streaming delta out of the local events.jsonl AND the graph-server dispatch by default (opt back in with exclude_events: []). The two hooks share no code; they are aligned by value and by the common streaming contract. Backwards-compatible: the excluded event ships with the new streaming providers, so existing logs/dispatch are unchanged. This removes the need for users to set exclude_events manually.

What

  • Added _DEFAULT_EXCLUDE_EVENTS: list[str] = ["llm:stream_block_delta"] module-level constant to config_resolver.py with a comment explaining the intentional value-alignment with hooks-logging (not shared code — deliberately decoupled).
  • Updated ConfigResolver.exclude_events property to use _DEFAULT_EXCLUDE_EVENTS as the default (previously []).
  • Updated module docstring to document the default and opt-out pattern.
  • Updated tests/test_config_resolver.py: renamed test_defaults_to_empty_settest_defaults_to_block_delta and added 6 new tests covering the complete semantics.

Why

Before this change, hook-context-intelligence defaulted to exclude_events: [], meaning llm:stream_block_delta (the per-token streaming event, firing hundreds-to-thousands of times per turn) would flood both the local events.jsonl and the graph-server dispatch unless users manually configured the exclusion. amplifier-module-hooks-logging already excluded it by default on its feat/exclude-events branch. This change brings the two hooks into alignment.

Semantics

Config Behaviour
exclude_events unset frozenset({"llm:stream_block_delta"}) — delta suppressed
exclude_events: [] frozenset() — filter disabled, every event logged/dispatched
exclude_events: ["llm:stream_*"] all four streaming events suppressed

The existing if exclude else events gate in __init__.py ensures excluded events are never registered → suppressed from BOTH the local write and graph dispatch. No logic changes needed there.

No shared code

The two hooks are deliberately decoupled. _DEFAULT_EXCLUDE_EVENTS in config_resolver.py is an independent constant — no import, no shared module, no cross-repo dependency. If the value needs to change in future, both hooks are updated independently.

Tests

uv run pytest tests/test_config_resolver.py -v
# 75 passed in 0.16s

uv run pytest
# 310 passed in 1.28s

Brian Krabach and others added 3 commits May 31, 2026 06:06
…k_delta by default

Both hook-context-intelligence and amplifier-module-hooks-logging now default to
excluding ["llm:stream_block_delta"] from their respective sinks — the local
events.jsonl AND the graph-server dispatch — without sharing any code.

Root cause of the divergence:
  hook-context-intelligence's ConfigResolver.exclude_events defaulted to []
  (empty frozenset), so the per-token streaming delta flooded both the JSONL
  audit log and graph dispatch unless users manually set exclude_events.
  amplifier-module-hooks-logging already used _DEFAULT_EXCLUDE_EVENTS =
  ["llm:stream_block_delta"] on its feat/exclude-events branch.

What changed:
  - config_resolver.py: added _DEFAULT_EXCLUDE_EVENTS: list[str] =
    ["llm:stream_block_delta"] module-level constant with a comment explaining
    the intentional value-alignment with hooks-logging (not shared code).
  - ConfigResolver.exclude_events property: updated default from [] to
    _DEFAULT_EXCLUDE_EVENTS; updated docstring.
  - __init__.py module docstring: updated exclude_events config-key description
    to document the default and the opt-out pattern.
  - tests/test_config_resolver.py: updated test_defaults_to_empty_set
    (now test_defaults_to_block_delta) and added 6 new tests:
    explicit [] disables filter, block_delta excluded, block_start/end/aborted
    and llm:response NOT excluded by default.

Semantics preserved:
  exclude_events: []   → frozenset() → filter disabled (log/dispatch everything)
  exclude_events unset → frozenset({"llm:stream_block_delta"}) → delta suppressed
  The existing 'if exclude else events' registration gate in __init__.py already
  ensures excluded events are never registered → suppressed from BOTH local write
  and graph dispatch.

No shared module/import between the two hooks — alignment is by identical value
only, per the deliberate decoupling requirement.

Backwards-compatible: llm:stream_block_delta is emitted by the new streaming
providers (feat/exclude-events / streaming-contract work); existing deployments
without streaming providers see no change.

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Change _DEFAULT_EXCLUDE_EVENTS from ["llm:stream_block_delta"] to
["llm:stream_*delta"] — a fnmatch glob that expresses the transient-
streaming-delta *category* rather than one hardcoded event name.

The pattern comes from the "Event dispositions" convention in the
provider streaming contract.  It is intentionally IDENTICAL to the
default used by amplifier-module-hooks-logging, aligned by that
convention and NOT by shared code.  The two hooks must remain
decoupled; keep them in sync via the contract, never by extracting
a shared module.

The glob matches llm:stream_block_delta (the current per-token delta
event) and would absorb any future *delta variants, while sparing
the structural streaming events (block_start, block_end, stream_aborted).

Changes:
- config_resolver.py: constant value + comment + property docstring
- __init__.py: module docstring (configuration keys section)
- test_config_resolver.py: update TestExcludeEvents — default is now
  {"llm:stream_*delta"}; delta-excluded test uses fnmatch.fnmatch;
  structural-event tests use fnmatch; new
  test_glob_spares_structural_streaming_events asserts the full
  match/no-match matrix explicitly

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Auto-reformatted by `ruff format .` to bring two files into compliance
with the repo's 100-char line-length limit (pyproject.toml).

- config_resolver.py: wrap the frozenset(...) call in exclude_events
  that exceeded 100 chars
- tests/test_config_resolver.py: wrap two long test-method docstrings

No logic changes.  Both CI commands now pass locally:
  uv run ruff format --check .   → 84 files already formatted
  uv run ruff check .            → All checks passed!

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
@bkrabach bkrabach merged commit a9ce2a8 into main May 31, 2026
9 checks passed
@bkrabach bkrabach deleted the feat/align-exclude-default branch May 31, 2026 14:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant