Skip to content

feat(trigger-service): classifier + start/resume matchers (TS-IMPL-012)#665

Merged
toddysm merged 1 commit into
mainfrom
ts-impl-012-classifier
Jun 5, 2026
Merged

feat(trigger-service): classifier + start/resume matchers (TS-IMPL-012)#665
toddysm merged 1 commit into
mainfrom
ts-impl-012-classifier

Conversation

@toddysm
Copy link
Copy Markdown
Owner

@toddysm toddysm commented Jun 5, 2026

TS-IMPL-012 — Classifier + Start Matcher + Resume Matcher

Implements the Classify → Match stage of the trigger pipeline (issue #642,
design § Module responsibilities).

What

  • pipeline/classify.pyclassify(event) -> Classification(to_start, to_resume).
    Every event is a start candidate; every event except a manual fire
    (source.type == manual, a direct targeted start trigger) is also a resume
    candidate. Both arms can match the same event.
  • pipeline/match_start.pyStartMatcher.match(event, candidates) keeps the
    active kind=start subscriptions whose CEL selector evaluates True (no
    selector = unconditional; a non-bool result is a no-match per design
    § Selector Language).
  • pipeline/match_resume.pyResumeMatcher.match(event, candidates) resumes
    kind=resume subscriptions on an exact (runId, stepId, eventKey) triple,
    then narrows by the optional CEL selector. resume_key_from_event reads
    runId/stepId from event.data and uses event.kind as the event key; an
    event with no run context yields no resume matches.

Design note

The matchers are pure routing functions over a caller-supplied candidate set.
The locked SPL MetadataStoreProvider exposes no subscription/resume list
surface (only the write methods + the dev/test in-memory read accessors), so
candidate enumeration is the receiver/dispatcher's concern (TS-IMPL-014..018) —
the matchers focus on the selection logic the scope describes.

Acceptance

  • An event can match both arms; resume match is exact on the triple. ✅
  • Start matches gated by the CEL selector. ✅
  • classify.py / match_start.py / match_resume.py at 100% coverage;
    suite 321 passed. ✅
  • ruff + mypy clean. ✅

Closes #642

Add the Classify -> Match stage of the trigger pipeline (TS-IMPL-012).

- `pipeline/classify.py` — `classify(event)` routes every event to the start
  arm and, by default, the resume arm too (both can match, e.g. a
  `workflow.completed` event starts a chained workflow *and* resumes a parent
  waiting on its child). A manual fire is start-only.
- `pipeline/match_start.py` — `StartMatcher` keeps active `kind=start`
  subscriptions whose CEL selector evaluates `True`; no selector =
  unconditional; a non-bool selector result is a no-match.
- `pipeline/match_resume.py` — `ResumeMatcher` resumes `kind=resume`
  subscriptions on an exact `(runId, stepId, eventKey)` triple, then narrows by
  the optional CEL selector. `resume_key_from_event` reads `runId`/`stepId`
  from `event.data` and uses `event.kind` as the event key; an event with no
  run context yields no resume matches.

Candidate enumeration stays with the caller — the locked SPL metadata store
exposes no subscription list surface, so the matchers are pure routing
functions over the candidate set. All three modules at 100% coverage.

Closes #642
Copilot AI review requested due to automatic review settings June 5, 2026 04:22
@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 the Trigger Service pipeline’s Classify → Match stage (TS-IMPL-012), adding pure routing/matching helpers that operate over a caller-supplied candidate set and are gated by CEL selector evaluation.

Changes:

  • Added classify(event) -> Classification to route every event to the start arm and route all non-manual events to the resume arm.
  • Added StartMatcher (active kind=start + optional CEL selector) and ResumeMatcher (exact (runId, stepId, eventKey) + optional CEL selector), plus resume_key_from_event.
  • Added unit tests covering classifier behavior and matcher semantics (including non-bool selector results as no-match) and marked TS-IMPL-012 as complete in the design TODOs.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/services/trigger-service/src/custos_trigger/pipeline/classify.py Adds classifier that routes events to start and (usually) resume arms.
src/services/trigger-service/src/custos_trigger/pipeline/match_start.py Adds start-subscription matcher (active start + CEL selector gating).
src/services/trigger-service/src/custos_trigger/pipeline/match_resume.py Adds resume matcher with exact triple matching + optional CEL selector narrowing.
src/services/trigger-service/src/custos_trigger/pipeline/init.py Exposes the pipeline surface area via package exports.
src/services/trigger-service/tests/test_pipeline.py Adds focused unit coverage for classifier, matchers, and resume key extraction.
design/components/trigger-service/todos.md Updates TS-IMPL-012 status to completed.

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

@toddysm toddysm merged commit 245d637 into main Jun 5, 2026
31 checks passed
@toddysm toddysm deleted the ts-impl-012-classifier branch June 5, 2026 04:31
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-012: Classifier + Start Matcher + Resume Matcher

2 participants