Skip to content

feat(trigger-service): event normalizer (TS-IMPL-010)#663

Merged
toddysm merged 2 commits into
mainfrom
ts-impl-010-normalizer
Jun 5, 2026
Merged

feat(trigger-service): event normalizer (TS-IMPL-010)#663
toddysm merged 2 commits into
mainfrom
ts-impl-010-normalizer

Conversation

@toddysm
Copy link
Copy Markdown
Owner

@toddysm toddysm commented Jun 5, 2026

Summary

Implements TS-IMPL-010 — Event Normalizer (#640).

Adds custos_trigger.normalize, which converts the two platform-internal
source shapes — a manual :fire and an internal custos.workflow.events
lifecycle envelope — into the canonical NormalizedEvent envelope the
Classify → Match → Dedup → Dispatch pipeline expects. (Connector-sourced
events already arrive shaped as NormalizedEvent and do not pass through here.)

What's included

  • normalize_manual_fire(...) — manual fire body → manual.fire event;
    inputs become data; subscriptionId is the subject.
  • normalize_workflow_event(envelope, ...)custos.workflow.events
    envelope → NormalizedEvent. kind is taken from an explicit, taxonomy-valid
    envelope kind when present, otherwise derived from status. runId is the
    subject; data carries workflowVersionId/runId/workspace/status plus
    optional outputs/stepId; raw.body retains the full envelope for audit.
  • workflow_kind_from_status(status, *, domain="workflow") — maps the
    Workflow Service wire status vocabulary onto canonical taxonomy kinds
    (succeededcompleted, queued/runningstarted); domain selects
    workflow.* (default) or run.*.
  • generate_event_id(*parts) — deterministic, NUL-joined UUIDv5 under a
    fixed namespace; internal events derive their id from the producer's
    (runId, kind, occurredAt) dedup triple so at-least-once redelivery collapses
    in the dedup store.

Acceptance criteria

  • Manual + internal payloads normalize to the locked envelope with
    canonical kinds.
  • Deterministic eventId generation; unknown source/status raises a
    taxonomy error (InvalidKindError).
  • Coverage ≥ 90% (normalize.py 100%; suite 99.85%).
  • ruff + mypy clean.

Closes #640

Add `custos_trigger.normalize`, converting the two platform-internal source
shapes into the canonical `NormalizedEvent` envelope.

- `normalize_manual_fire(...)`: manual `:fire` body -> `manual.fire` event;
  inputs become `data`; deterministic `eventId` from
  (subscription, occurredAt, inputs) so a redelivered fire collapses in dedup.
- `normalize_workflow_event(envelope, ...)`: `custos.workflow.events` envelope
  -> `NormalizedEvent`. `kind` is taken from an explicit taxonomy-valid
  envelope `kind` when present, else derived from `status` via
  `workflow_kind_from_status` (succeeded->completed, queued/running->started).
  `domain` selects `workflow.*` (default) or `run.*`. `runId` is the subject;
  `eventId` is derived from (runId, kind, occurredAt) — the producer's dedup
  triple — so Dapr at-least-once redelivery collapses in dedup.
- An internal status with no canonical mapping (e.g. `paused`) surfaces as
  `InvalidKindError` (taxonomy error); missing required envelope fields raise
  `EventNormalizationError`.
- `generate_event_id(*parts)`: NUL-joined UUIDv5 under a fixed namespace.

Closes #640
Copilot AI review requested due to automatic review settings June 5, 2026 03:41
@toddysm toddysm added type:implementation Implementation work item phase:implementation Implementation phase component:trigger-service Trigger Service component labels Jun 5, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements TS-IMPL-010 for Trigger Service by introducing an event normalizer that converts manual :fire requests and internal custos.workflow.events envelopes into the canonical NormalizedEvent shape consumed by the downstream Classify → Match → Dedup → Dispatch pipeline.

Changes:

  • Added custos_trigger.normalize with helpers for canonical kind mapping and deterministic event ID generation.
  • Added a comprehensive unit test suite for manual-fire and workflow-envelope normalization behavior.
  • Updated the trigger-service design TODO tracker to mark TS-IMPL-010 as complete.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
src/services/trigger-service/src/custos_trigger/normalize.py New normalization module for manual and internal workflow events, including kind mapping and deterministic event_id generation.
src/services/trigger-service/tests/test_normalize.py New unit tests covering event ID generation, kind mapping, and normalization behavior/error cases.
design/components/trigger-service/todos.md Marks TS-IMPL-010 as completed.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/services/trigger-service/src/custos_trigger/normalize.py
Comment thread src/services/trigger-service/src/custos_trigger/normalize.py Outdated
Comment thread src/services/trigger-service/src/custos_trigger/normalize.py
Comment thread src/services/trigger-service/tests/test_normalize.py
…rnal event_id

Address Copilot review on PR #663:
- normalize_manual_fire now requires a non-empty subscription_id (manual fire
  is subscription-scoped), so the subject is unambiguous and dedup keys cannot
  collide across subscriptions.
- normalize_workflow_event derives event_id from (runId, kind, occurredAt)
  only; kind already embeds the domain, so dropping the extra domain part
  restores the stated 'same producer dedup triple' property.
- Document stepId in the workflow-event envelope wire shape.
@toddysm toddysm merged commit cd1da9a into main Jun 5, 2026
30 checks passed
@toddysm toddysm deleted the ts-impl-010-normalizer branch June 5, 2026 03:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component:trigger-service Trigger Service component phase:implementation Implementation phase type:implementation Implementation work item

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TS-IMPL-010: Event Normalizer

2 participants