Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 32 additions & 16 deletions docs/design/declarative_expert_program_plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
Pick/Place/settle/validator cycle, while the full three-cycle run remains in
threshold calibration. Dual-UR5/PGI HandOver has completed three consecutive
supported-simulation Pick/transfer/settle/validator runs using contact
dynamics only.
dynamics only. Named trajectory-segment effect gates now block Pick lift,
Place retract, and HandOver source release until fresh physical evidence
confirms the required acquisition or release.
- Baseline: `main@bcccb787dcafdafd7b944ba210e5e85f9cd1d0cb`
- Last updated: 2026-08-11
- Related issues: [#471](https://github.com/DexForce/EmbodiChain/issues/471),
Expand Down Expand Up @@ -600,8 +602,9 @@ controller intent, not physical proof.
passed the selected monitor. The target contract must treat contradictory
evidence, including object-to-endpoint slip, as a real effect failure, invalidate
the affected row's assumed relation, and enter bounded recovery instead of
repairing the scene. The runtime now exposes the active named motion phase,
observes phase-scoped held-object invariants from fresh physical evidence, and
repairing the scene. The runtime now exposes the active named trajectory
segment, observes segment-scoped held-object invariants from fresh physical
evidence, and
applies removal-only ``StateDelta`` reconciliation to failed rows before any
retry or recovery hand-off. The monitor publishes one current-observation
outcome per physical expectation, including the stronger proof that every
Expand All @@ -615,10 +618,23 @@ external recovery, but the core owns the removal-only invalidation delta and
applies it before either path. Evidence that remains unresolved at the action
deadline is reconciled fail-closed: any active verified state covered by the
pending effect is removed before external recovery. Workflow-level
re-acquisition and blocking acquisition gates remain open; neither may repair
the scene implicitly. For handover, success transfers the verified relation
from source to destination while the destination remains physically closed.
Releasing the destination is a separate ``Place`` or ``Release`` semantic call.
re-acquisition remains open and may not repair the scene implicitly.

Blocking physical-effect gates are enforced at named trajectory-segment
entries. ``Pick`` requires destination attachment before ``lift``; ``Place``
requires source detachment before ``retract``; and ``HandOver`` requires
destination attachment before the source ``release`` segment. While a gate is
unresolved, the session does not advance its waypoint cursor and replays the
preceding command for the complete synchronized active cohort, so gripper
preload or open intent remains active under real dynamics. Gate success only
unlocks motion and never commits ``TaskState``; terminal effect verification
remains authoritative. Contradiction uses the enclosing action's bounded retry
policy, stale request IDs are rejected, and the action deadline covers gate
polling. Every gate owns a fresh monitor instance independent from the terminal
monitor and in-flight loss guard. For handover, terminal success transfers the
verified relation from source to destination while the destination remains
physically closed. Releasing the destination is a separate ``Place`` or
``Release`` semantic call.

The first pure-dynamics rollout uses the staged **B** continuation policy. The
standard simulation factory lowers both trajectory ``control_dt`` and runner
Expand Down Expand Up @@ -1225,18 +1241,18 @@ The backend-neutral typed state expectations, evidence addresses and sources,
pose/binary/scalar/joint evidence clauses, versioned monitor registry,
profile-owned monitor selection, grounded Pick/Place/HandOver/articulation
effects, row-local composite hysteresis kernel, canonical `SkillRuntime`, and
production simulation evidence ports are wired end to end. Phase-scoped
production simulation evidence ports are wired end to end. Segment-scoped
held-object guard requests, live evidence collection, row-local symbolic
invalidation, bounded Pick retry, and typed external-recovery hand-off are also
implemented. Physical simulation acceptance is partial: Open Drawer and one
cube Pick/Place/settle/validator cycle have completed. The embodiment-owned
dual-UR5/PGI HandOver slice now completes Pick, transfer, terminal
physical-effect verification, settling, and target validation through real
contact dynamics. Per-expectation terminal outcomes, core-owned failure
invalidation, row-local retry/recovery decisions, and fail-closed deadline
reconciliation are implemented. Blocking acquisition gates, workflow-level
re-acquisition, fault-injection coverage, and the full repeated-cube run remain
validation or design work.
invalidation, row-local retry/recovery decisions, fail-closed deadline
reconciliation, and blocking named-segment effect gates are implemented.
Workflow-level re-acquisition, fault-injection coverage, and the full
repeated-cube run remain validation or design work.

Deliverables:

Expand Down Expand Up @@ -1492,12 +1508,12 @@ The design is complete when all of the following hold:
synthetic attachment, freezes the object, or overrides its pose.
- [ ] Physical held-object loss is observed as effect failure, invalidates the
affected symbolic relation, and exercises bounded recovery rather than
being hidden by a simulator-side attachment. The phase-aware observation,
being hidden by a simulator-side attachment. The segment-aware observation,
row-local core-owned invalidation, per-expectation terminal
reconciliation, fail-closed deadline handling, bounded Pick/retained-Place
retry, and typed recovery boundary are implemented; blocking acquisition,
workflow-level re-acquisition, and real-simulation fault injection remain
open.
retry, typed recovery boundary, and blocking acquisition/release gates are
implemented; workflow-level re-acquisition and real-simulation fault
injection remain open.
- [x] Repeated sub-threshold motion eventually publishes the correct scene
revision.
- [x] Custom actions have a documented and tested intentional hard-break
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ embodichain.lab.sim.atomic_actions
ControlPartCommandProfile
ActionControlOverrides
ActionInvocation
PhaseEffectGateRequirement
ResolvedActionRequest
ActionOptions
MotionPolicy
Expand Down Expand Up @@ -73,6 +74,11 @@ embodichain.lab.sim.atomic_actions
SimulationExecutionAdapter
ExecutionTick
EffectVerificationRequest
EffectVerificationResult
PhaseEffectGateRequest
PhaseEffectGateResult
HeldObjectGuardRequest
HeldObjectGuardResult
ExecutionEvent
ExecutionEventKind
ExecutionStatus
Expand Down
27 changes: 22 additions & 5 deletions docs/source/overview/sim/atomic_actions/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -837,8 +837,8 @@ and resets the history. Evidence exactly at the deadline is valid, while a due
observation after the deadline is handled by session timeout without invoking
the verifier.

The curated semantic runtime also installs phase-scoped, negative
held-object guards for named trajectory segments. Before a due command is
The curated semantic runtime also installs segment-scoped, negative held-object
guards for named trajectory segments. Before a due command is
dispatched, `ExecutionRunner` passes a fresh observation and the current
`HeldObjectGuardRequest` to its synchronous guard verifier. Each request has a
single-use verification ID, the active waypoint/segment identity, and the
Expand All @@ -849,10 +849,27 @@ before retrying or emitting `RECOVERY_REQUIRED`.
Unavailable or unresolved evidence does not count as a physical contradiction,
and the guard verifier is not invoked after the authoritative action deadline.

The current guard is observational and negative; a blocking positive
acquisition gate, outcome-aware terminal reconciliation, and workflow-level
re-acquisition remain separate policies. Neither the monitor nor runtime
The curated `Pick`, `Place`, and `HandOver` paths additionally install blocking
positive-effect gates at named trajectory-segment entries. Pick must verify the
destination attachment before `lift`, Place must verify source detachment before
`retract`, and HandOver must verify the destination attachment before source
`release`. The compiler creates a monitor instance for each gate independently
from both the terminal monitor and negative held-object guard.

`ExecutionSession` exposes a correlated `PhaseEffectGateRequest` at the segment
boundary. While its result remains unresolved, the waypoint cursor does not
advance and the preceding command is replayed for the complete synchronized
active cohort. This preserves gripper preload or open intent instead of
replacing it with an observed-position hold. A successful
`PhaseEffectGateResult` only unlocks the segment; it does not commit
`TaskState`. Contradiction uses the enclosing action's bounded retry policy,
request IDs are single-use, and the action deadline covers all polling. Calling
`run_until_blocked()` without a gate verifier returns this boundary for an
external verifier.

The guards and gates are observational. Neither a monitor nor the runtime
creates a simulator attachment, freezes an object, or overrides its pose.
Workflow-level re-acquisition remains a separate recovery policy.

## Action Agent integration

Expand Down
28 changes: 28 additions & 0 deletions docs/source/tutorial/atomic_actions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,34 @@ same invocation remains physically valid. Other failed rows enter external
recovery after selected invalidation. Unresolved evidence at the action
deadline is reconciled fail-closed when covered verified state is still active.

Trajectory-segment effect gates
-------------------------------

An invocation may declare a
:class:`~embodichain.lab.sim.atomic_actions.PhaseEffectGateRequirement` for a
named, non-initial trajectory segment. The execution session then exposes a
:class:`~embodichain.lab.sim.atomic_actions.PhaseEffectGateRequest` immediately
before the first frame of that segment. Curated semantic calls install these
automatically: Pick gates ``lift`` on destination attachment, Place gates
``retract`` on source detachment, and HandOver gates source ``release`` on
destination attachment.

Supply ``phase_effect_gate_verifier(context, request)`` to ``runner.step()`` or
``runner.run_until_blocked()``. It runs on a fresh due-cycle observation and
returns a correlated
:class:`~embodichain.lab.sim.atomic_actions.PhaseEffectGateResult`. If neither
the success nor failure mask selects every remaining active row, the session
keeps the whole cohort at the boundary and resends the command immediately
before the gated segment. This preserves a close/open command and its physical
preload; it is not an observed-position hold.

Gate success only permits the next command and does not update ``TaskState``.
The terminal effect verifier still owns the semantic commit. A contradictory
row may consume the enclosing action's retry budget; a row outside the result's
``retry_mask`` requires external recovery. The gate shares the action timeout,
and each consumed observation replaces its request ID. Without a gate verifier,
``run_until_blocked()`` returns the pending boundary for asynchronous handling.

Adding an action
----------------

Expand Down
14 changes: 13 additions & 1 deletion embodichain/lab/sim/atomic_actions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
ExecutionTick,
HeldObjectGuardRequest,
HeldObjectGuardResult,
PhaseEffectGateRequest,
PhaseEffectGateResult,
)
from .goals import (
ActionGoal,
Expand All @@ -78,7 +80,12 @@
SceneArticulationOperationGeometry,
SceneEntityPose,
)
from .invocation import ActionInvocation, ActionOptions, ResolvedActionRequest
from .invocation import (
ActionInvocation,
ActionOptions,
PhaseEffectGateRequirement,
ResolvedActionRequest,
)
from .plans import (
ActionPlan,
CompiledTrajectory,
Expand Down Expand Up @@ -196,6 +203,7 @@
HeldObjectGuardVerifier,
MonotonicExecutionClock,
ObservationProvider,
PhaseEffectGateVerifier,
RunnerStatus,
RunnerStep,
RunnerStepCallback,
Expand Down Expand Up @@ -279,6 +287,10 @@
"ExecutionTick",
"HeldObjectGuardRequest",
"HeldObjectGuardResult",
"PhaseEffectGateRequest",
"PhaseEffectGateRequirement",
"PhaseEffectGateResult",
"PhaseEffectGateVerifier",
"HeldObjectGuardVerifier",
"EndpointTrackingChannelBinding",
"EndpointTrackingFeedbackAddress",
Expand Down
1 change: 1 addition & 0 deletions embodichain/lab/sim/atomic_actions/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ def resolve_request(
motion_policy=invocation.motion_policy,
tracking_policy=invocation.tracking_policy,
recovery_policy=invocation.recovery_policy,
phase_effect_gates=invocation.phase_effect_gates,
skill_options=options,
invocation_id=invocation.invocation_id,
revision=invocation.revision,
Expand Down
Loading