Skip to content

fix: warn on empty destination include; correct README default docs - #100

Merged
Diego Colombo (colombod) merged 1 commit into
mainfrom
fix/include-default-docs-and-validation
Aug 20, 2026
Merged

fix: warn on empty destination include; correct README default docs#100
Diego Colombo (colombod) merged 1 commit into
mainfrom
fix/include-default-docs-and-validation

Conversation

@bkrabach

Copy link
Copy Markdown
Collaborator

Summary

Small fail-closed-documentation + validation-warning fix for the destination fan-out include config.

Bugs Fixed

Bug 1: README Documentation Contradiction

File reference: README.md

The README incorrectly claimed that an omitted include defaults to ["**"] (match everything) in two places:

  1. The destination config table row
  2. The "Defaults & validation" paragraph

However, the actual code behavior is:

  • config_resolver.py defines Destination.include = () (empty tuple as default)
  • fanout._matches() returns False on empty patterns → destination receives nothing

The README even contradicted itself within 30 lines — a third line correctly stated "empty include list → nothing (destination inactive)".

Resolution: All three statements now agree: an omitted include fails closed to match nothing. The legacy-scalar note (correctly documenting that legacy config synthesizes include: ["**"]) was verified accurate and remains untouched.

Why fail-closed is correct: An operator accidentally omitting include should get a safe, inactive destination — not silent data loss. Documentation was updated to match code, not vice versa.

Bug 2: Silent Validation of Inactive Destinations

File reference: config_resolver.py validate_destinations()

The validator passed a silently-dead destination without any signal. An operator following the (incorrect) README and omitting include would end up with a destination that never receives anything, with no warning whatsoever.

Resolution: Added a per-destination WARNING when include is empty: "this destination will never match any session... set include: ["**"] to receive all sessions".

This is a warning, not an error — an inactive destination is legal (still reachable via the query tool with source=), just surprising. The warning gives operators visibility into what they've accidentally created.

Evidence

Unit tests (all passing):

  • 610 hook-module tests
  • 753 repo-root tests
  • ruff formatting: clean
  • pyright type checking: clean

New test coverage (5 cases):

  1. Omitted include → warns
  2. Explicit empty list [] → warns
  3. Non-empty include → no warning
  4. Legacy-synthesized ("**",) → no warning
  5. Already-invalid destination → no double-warn

Implementation Scope

No DTU run performed. This change consists of:

  • Documentation corrections (README)
  • One log warning on destination creation
  • No seam-crossing behavior change
  • No changes to event flow, validation logic, or fanout behavior

All changes are covered by unit tests. Reviewers who want DTU evidence should say so.

Related Work

This fix was discovered during the telemetry secret-leak investigation that produced microsoft/amplifier-bundle-redaction PR #9. The two are independent but related in origin.

Generated with Amplifier

… default docs

The `include` fan-out pattern has always been fail-closed in code -- an
omitted or empty `include` matches NOTHING (the `Destination` docstring
and `fanout.py`'s `_matches`, which returns `False` on empty patterns) --
but the README documented the opposite default (`["**"]`, match
everything) in two places, and `validate_destinations()` never surfaced
the fail-closed default with any signal, silent or otherwise. A
destination with a forgotten `include` line silently receives nothing,
with no warning anywhere.

- README.md: correct the `include` sub-key's default-column entry and the
  "Defaults & validation" paragraph to state the real fail-closed
  behavior. The one already-correct statement ("empty include list ->
  nothing") and the legacy-scalar synthesis note (`include: ["**"]`) are
  left as-is and cross-checked for consistency with the corrected text.
- config_resolver.py: `validate_destinations()` now emits a per-destination
  WARNING (not an error -- an inactive destination is a legal config, just
  easy to produce by accident) when a destination that otherwise passes
  validation has an empty `include`. The destination is NOT dropped from
  the returned dict -- it remains reachable explicitly via the query
  tools' `source=` override.
- tests: five new cases in `TestEmptyIncludeWarning` covering an omitted
  `include`, an explicit `include: []`, a populated `include` (no
  warning), the legacy-scalar synthesized destination (no warning --
  always gets `("**",)`), and a destination already dropped for a bad
  url/api_key (must not also emit the include warning).

Verified: modules/hook-context-intelligence unit suite (610 passed),
repo-root tests/ suite (753 passed), ruff check + format clean, pyright
clean on the touched module file.

Not included: a real DTU run. This repo's AGENTS.md requires DTU evidence
for seam-crossing changes; that run is a separate follow-up step, not
part of this commit.

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

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
@colombod
Diego Colombo (colombod) merged commit fcea53f into main Aug 20, 2026
8 checks passed
@colombod
Diego Colombo (colombod) deleted the fix/include-default-docs-and-validation branch August 20, 2026 09:12
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.

3 participants