Problem Statement
IdLE evaluates Condition only during plan creation. The plan is then executed 1:1. This makes planning deterministic, but it introduces a safety gap when time passes between plan and execution:
- External state can change (e.g., group membership / entitlements / device state).
- A plan that was correct at planning time may be unsafe or invalid at execution time.
- For safety/policy scenarios we must prevent execution from performing an action if the current (live) state violates a precondition.
Concrete example (BYOD policy):
- If the user is currently in a BYOD group (Android/iOS), company data must be wiped/retired in Intune before disabling the identity.
- If the plan was created earlier and the user later enters/leaves those groups, a plan-only condition can become stale and either:
- incorrectly allow disablement (policy violation), or
- incorrectly block disablement (unnecessary stop).
We need a generic, read-only, runtime mechanism to guard execution with “fail fast” behavior without introducing side effects or turning IdLE into an interactive system.
Related / Dependencies
This issue intentionally does not define request schema naming or planning-time context enrichment. It assumes those are handled by separate issues:
- Issue (Schema): Separate
Request.Intent from Request.Context (rename DesiredState, forbid Request.Identity)
- Issue (Snapshot): Plan snapshot/export contract for
Request.Intent and Request.Context (auditability + safety)
- Issue (Planning Context): Planning-time
ContextResolvers (read-only) using provider capabilities to populate Request.Context
Runtime Preconditions may use:
- live provider queries (preferred for safety), and/or
Request.Context when available.
Proposed Solution
Introduce Runtime Preconditions (read-only execution guards) that are evaluated during execution immediately before running a step.
High-level concept
- Keep existing
Condition semantics as planning-time (deterministic plan building).
- Add an optional
Preconditions capability per step that is evaluated at execution time (online evaluation).
- Preconditions are read-only checks, allowed to query providers (live state), but must not change state.
- If a precondition fails, the engine must stop execution in a controlled manner and surface a Blocked outcome (not a generic failure), optionally emitting a structured event payload for hosts.
Workflow schema (proposal)
Add optional properties to step definitions:
Preconditions: list of preconditions to evaluate at execution time (read-only).
OnPreconditionFalse: Blocked | Fail (default: Blocked if Preconditions exists; otherwise N/A).
PreconditionEvent: optional structured object that is emitted when precondition fails, e.g.:
Type (e.g., ManualActionRequired)
Message
Data (key-value payload, safe for logs)
Notes:
- This issue does not require choosing the final schema names yet, but implementation MUST include an explicit, documented and testable structure.
Engine behavior
Plan creation remains unchanged:
- Evaluate
Condition during planning and set step Status accordingly.
Execution phase:
- For each step with
Status == Planned (or equivalent), evaluate Preconditions before invoking the step action.
- If all pass, invoke step action as usual.
- If any fails:
- If
OnPreconditionFalse == Blocked: mark step outcome as Blocked and stop the plan execution (do not continue to subsequent steps).
- If
OnPreconditionFalse == Fail: mark step outcome as Failed and stop, running existing failure semantics as appropriate.
- Emit
PreconditionEvent as a structured engine event (if provided).
Minimal API surface
- Add a new step-result/outcome classification:
Blocked.
- Add execution logic that stops the run when a step becomes
Blocked (or Failed), with predictable return objects/events.
- Keep compatibility: steps without
Preconditions behave exactly as before.
Semantics: Blocked vs Failed
Blocked is not a “technical failure”. It represents a policy / precondition gate and is intended to support human-in-the-loop or external dependency resolution.
Required clarifications/behavior:
Blocked MUST stop execution immediately (no subsequent steps).
Blocked MUST be distinguishable from Failed in the returned plan execution result.
- Failure handlers (e.g., “on failure” steps / compensation) MUST NOT run for
Blocked by default.
- If IdLE supports configurable failure handling, document how
Blocked is treated.
Failed remains reserved for genuine errors (provider failure, unexpected exception, etc.) and continues to follow existing failure semantics.
Alternatives Considered
-
Gate Step (e.g., RequireManualProcedure) before actions:
- Works, but pushes policy gating into workflow authoring and duplicates a common pattern.
- Less generic and harder to standardize across all safety policies.
-
Re-evaluate Conditions at runtime:
- Makes plan vs execution nondeterministic and blurs responsibilities.
- Harder to audit: plan no longer explains why a step executed or not.
-
Host-only gating:
- Host can block execution, but IdLE should provide a consistent, testable mechanism for safety guards across hosts.
Impact
Does this affect existing workflows?
- No. Existing workflows without
Preconditions are unaffected.
Backward compatibility concerns?
- Introducing a new outcome/status
Blocked requires consumers (hosts/tests) to tolerate the new value.
- Default behavior must remain unchanged unless
Preconditions is configured.
Additional Context
BYOD use case enabled by this feature
A host can:
- Create a plan that includes
DisableIdentity.
- Configure
DisableIdentity with a runtime precondition like:
- “User is NOT currently member of BYOD groups OR a caller-provided wipe confirmation flag is true”
- The exact request path for the confirmation flag is defined by the request schema issue (e.g.,
Request.Intent.Byod.WipeConfirmed), and is not introduced by this issue.
If membership is detected live at execution time, execution stops as Blocked and emits:
Type=ManualActionRequired
Message=Perform Intune retire / wipe company data for BYOD device
Data including platform hints and identity keys.
Definition of Done (Step-0-Ready / Agent-Safe)
Design / Contracts
Implementation
Tests (Pester)
Docs / Examples
Non-Goals (explicit)
- No interactive UI prompts in IdLE.
- No “Terraform-like” full data engine or resource graph; only read-only runtime checks used as guards.
- No automatic re-planning or plan mutation during execution beyond step outcome marking.
Problem Statement
IdLE evaluates
Conditiononly during plan creation. The plan is then executed 1:1. This makes planning deterministic, but it introduces a safety gap when time passes between plan and execution:Concrete example (BYOD policy):
We need a generic, read-only, runtime mechanism to guard execution with “fail fast” behavior without introducing side effects or turning IdLE into an interactive system.
Related / Dependencies
This issue intentionally does not define request schema naming or planning-time context enrichment. It assumes those are handled by separate issues:
Request.IntentfromRequest.Context(renameDesiredState, forbidRequest.Identity)Request.IntentandRequest.Context(auditability + safety)ContextResolvers(read-only) using provider capabilities to populateRequest.ContextRuntime Preconditions may use:
Request.Contextwhen available.Proposed Solution
Introduce Runtime Preconditions (read-only execution guards) that are evaluated during execution immediately before running a step.
High-level concept
Conditionsemantics as planning-time (deterministic plan building).Preconditionscapability per step that is evaluated at execution time (online evaluation).Workflow schema (proposal)
Add optional properties to step definitions:
Preconditions: list of preconditions to evaluate at execution time (read-only).OnPreconditionFalse:Blocked | Fail(default:BlockedifPreconditionsexists; otherwise N/A).PreconditionEvent: optional structured object that is emitted when precondition fails, e.g.:Type(e.g.,ManualActionRequired)MessageData(key-value payload, safe for logs)Notes:
Engine behavior
Plan creation remains unchanged:
Conditionduring planning and set stepStatusaccordingly.Execution phase:
Status == Planned(or equivalent), evaluatePreconditionsbefore invoking the step action.OnPreconditionFalse == Blocked: mark step outcome asBlockedand stop the plan execution (do not continue to subsequent steps).OnPreconditionFalse == Fail: mark step outcome asFailedand stop, running existing failure semantics as appropriate.PreconditionEventas a structured engine event (if provided).Minimal API surface
Blocked.Blocked(orFailed), with predictable return objects/events.Preconditionsbehave exactly as before.Semantics: Blocked vs Failed
Blockedis not a “technical failure”. It represents a policy / precondition gate and is intended to support human-in-the-loop or external dependency resolution.Required clarifications/behavior:
BlockedMUST stop execution immediately (no subsequent steps).BlockedMUST be distinguishable fromFailedin the returned plan execution result.Blockedby default.Blockedis treated.Failedremains reserved for genuine errors (provider failure, unexpected exception, etc.) and continues to follow existing failure semantics.Alternatives Considered
Gate Step (e.g.,
RequireManualProcedure) before actions:Re-evaluate Conditions at runtime:
Host-only gating:
Impact
Does this affect existing workflows?
Preconditionsare unaffected.Backward compatibility concerns?
Blockedrequires consumers (hosts/tests) to tolerate the new value.Preconditionsis configured.Additional Context
BYOD use case enabled by this feature
A host can:
DisableIdentity.DisableIdentitywith a runtime precondition like:Request.Intent.Byod.WipeConfirmed), and is not introduced by this issue.If membership is detected live at execution time, execution stops as
Blockedand emits:Type=ManualActionRequiredMessage=Perform Intune retire / wipe company data for BYOD deviceDataincluding platform hints and identity keys.Definition of Done (Step-0-Ready / Agent-Safe)
Design / Contracts
Preconditions,OnPreconditionFalse, optional event payload).Blockedas a first-class outcome/status with clear semantics vsFailed.Blockedinteracts with failure/compensation handling (default: do not run failure handlers).Implementation
Blockedhandling:Blocked.Tests (Pester)
Blockedand stops execution (no next step).OnPreconditionFalse=FailproducesFailedand stops execution.Blockeddoes not trigger failure/compensation handlers (default behavior).PreconditionEventis emitted and contains expected fields.Docs / Examples
Non-Goals (explicit)