MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-365

6.6.2 Execution engine — `work-item/created` + `work-item/field.changed` events, the rule-run Inngest job (match → conditions → actions-as-owner), loop prevention, audit writes, auto-disable + owner error email, retention sweep

Done
Description

Estimate: 38m · Depends on: 6.6.1

The heart of the story: events in, attributed service calls out, every run audited.

New events (rung-2 emit points): work-item/created (post-commit from the shipped workItemsService create path) and work-item/field.changed (post-commit from its update path, carrying the changed built-in field ids the 1.4.6 revision-diff machinery already computes) — typed in JobEventDataMap, workspace-scoped, emit-on-commit-only (the 5.1.2/5.4.5 rule: a rolled-back tx emits nothing). Payloads carry viaAutomationRuleId?: string provenance — these are the same events the 5.7 stub anticipates for assignment notifications.

The engine job (a 1.6 defineJob per consumed event): load the project's ENABLED rules matching the trigger (narrowed by trigger config — from/to status, field id); skip any event carrying provenance (the Jira-default loop rule — no rule fires off another rule's action, ever); evaluate the condition group by compiling the rule's FilterAST through the 6.1.1 compiler scoped to the triggering item (AND id = :workItemId — one indexed query; empty group = pass); execute the action list IN ORDER through the shipped services as the rule owner (this subtask: transition via workflowsService — workflow-illegal target = a recorded failure, not a bypass; set-field via workItemsService.update), stamping provenance on every event those service calls emit; write the automation_rule_execution row (success / failure with the typed error / no_actions when the condition gates). Idempotent per (event × rule) — Inngest replays and retries never double-execute actions (the 5.1.6/5.4.5 idempotency pattern, keyed on event id × rule id).

Failure ops: a failed run increments consecutiveFailureCount; at 10 the rule auto-disables (the verified Jira number); a success resets the counter; the owner gets the error email on the FIRST failure after a success only (the verified dedupe) — a new lib/emailTemplates/automationRuleFailed.tsx through the 1.6 email pipeline. Retention: a daily cron sweep (the 1.6.4 system-job pattern) deletes execution rows older than 90 days (the verified Jira retention), batched.

Acceptance criteria

  • Both events typed + emitted post-commit only (rollback emits nothing — asserted); existing create/update tests stay green; payloads carry changed field ids + provenance.
  • The matrix holds: matching rules fire, trigger-config narrowing works (from/to, field id, the assignee preset), conditions gate (pass / fail / empty-group), actions execute in order attributed to the owner with real revision rows, and a workflow-illegal transition logs Failure without corrupting state.
  • Loop proof: a self-triggering rule (transition → transition) runs exactly once — the provenance-stamped follow-on event is skipped (asserted via the audit log + event payloads).
  • Replay/retry double-executes nothing (idempotency per event × rule); failure counting, auto-disable at 10, counter reset on success/re-enable, and the first-failure-only email all asserted; the sweep deletes only >90d rows.
  • pnpm test:coverage ≥90%; the engine lives in services/jobs per the 4-layer rule (no raw writes anywhere on the action path).

Context refs

  • lib/jobs/* (1.6 — defineJob, sendEvent, typed event map, idempotency + DLQ patterns); lib/jobs/definitions/dailyHealthCheck.ts (the cron-sweep exemplar)
  • 6.6.1 (registries + schema); 6.1.1 (the compiler the conditions ride)
  • workItemsService create/update + the 1.4.6 revision-diff machinery (the emit points); workflowsService.updateStatus (transition legality)
  • The 5.1.6/5.4.5 idempotent-notification-job pattern + the 5.1.2 emit-on-commit rule; the verified Jira loop/failure/retention facts in the Story 6.6 description
Status
Done
Type
Sub-task