Skip to content

Intent DSL: no way to guard a status consumer by HOW the status was reached - an automatic lookup and a manual task are indistinguishable #6957

Description

@delchev

Problem — a DSL expressiveness gap, not a bug

When a status can be reached by more than one path — an automatic resolves: register lookup routes to DRIVER_IDENTIFIED on success, and an officer's user task sets the same status manually — there is no way to bind a consumer to only ONE of those paths. A generates: rule (or notification / integration / posting) bound to

event: { onTransition: Fine, when: "Status == DRIVER_IDENTIFIED" }

fires on both, so "append a DRIVER_IDENTIFICATION_SUCCESS log row on automatic identification" also fires when the identification was manual — and the model has no way to say otherwise.

Why the existing constructs cannot express it

  • event.when is a single comparison against a status seed (<Property> == <seed id or name>, one term, no ||, numeric after StatusSymbolResolver rewrites the name). The resolves: outcome: trace field — which stamps exactly the provenance needed (found / notFound / ambiguous) — is a string field and cannot be guarded on.
  • Splitting into two statuses (DRIVER_IDENTIFIED_AUTO / DRIVER_IDENTIFIED_MANUAL) does not compose: a downstream at-most-once generates: (mint the Declaration once identification succeeded, however it succeeded) needs ONE converged status — its when guard is a single comparison — and two mode: once rules sharing the same target + back-reference are refused by design (Two generates:/posts: rules sharing a target back-reference silently collide - detect it at parse time #6813, validateIdempotencyGuardOwnership).

So the requirement "log which path identified the driver" is currently inexpressible; the closest authoring degrades to a shared status plus a log rule that admits (in its own description) that it fires on both paths.

Possible directions (design discussion, not a prescription)

  1. String-literal equality in event.when on a declared string fieldwhen: "resolution == 'found'". Smallest change; makes the resolves: trace field the provenance carrier it was designed to be. Needs a decision on quoting/escaping and on keeping the grammar a single comparison.
  2. An AND of two comparisons in event.when (Status == DRIVER_IDENTIFIED && resolution == 'found') — more general, more grammar.
  3. Provenance on the transition itself — the -transitioned publishers (workflow setters, transitions: buttons, resolves: outcome routing, generates.sourceStatus) already know who they are; carrying a source marker in the payload and letting event: filter on it would guard by writer rather than by data. Bigger, but guards the actual question ("who moved it") instead of a proxy field.

Worth noting: a hand-written specification for this process missed the double-fire too — it is not visible until you try to write the guard. The diagram half (#6954's cardinality badges) makes the symptom visible; this issue is about making the distinction expressible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions