Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
950ea7a
motion planning: collision-check welded partners of the held object
yichao-liang Aug 16, 2026
f97e838
bridge: harden oracle place samplers and glue-reach MoveTo bounds
yichao-liang Aug 16, 2026
e385fe2
bridge: recalibrate GT-sim cure gates so welds can latch
yichao-liang Aug 16, 2026
46cffb6
bridge: robustify carried-assembly planning and demo-time placement
yichao-liang Aug 16, 2026
04483de
bridge: stop glue/cure/attached sim_data leaking across env instances
yichao-liang Aug 17, 2026
c9d24fb
skills: guarded settle-to-contact release; bridge: kill drop-settle s…
yichao-liang Aug 17, 2026
3e953df
bridge: sustained-dwell glue wetting; observable block half extents
yichao-liang Aug 17, 2026
c3810b7
skills: gentle-stroke give-up advance; unbounded support-escape margins
yichao-liang Aug 17, 2026
b2bfd8e
bridge: kill weld creep and the systematic place landing bias
yichao-liang Aug 17, 2026
0456f8b
skills: collision-aware goal-config selection across IK branches
yichao-liang Aug 17, 2026
acdd65b
skills: robot-link start escape; start-local partner demotion
yichao-liang Aug 19, 2026
d1bbd04
skills: escalated goal-IK on goal collisions; proximity-ordered branches
yichao-liang Aug 19, 2026
de55f57
bridge: tack wet joints until they weld
yichao-liang Aug 19, 2026
c8ed44c
bridge: drop the validated-IK override
yichao-liang Aug 19, 2026
85741db
bridge: drop the -0.02 shallow-held margin override
yichao-liang Aug 19, 2026
a0d2b24
bridge: enable agent_oracle_hybrid_sim and skip agent_po_predicate_in…
yichao-liang Aug 19, 2026
b7b1c41
bridge: remove waypoint subsampling settings for pybullet_birrt
yichao-liang Aug 19, 2026
6d554a5
env: grasp detection requires a pinch, not a touch (position control)
yichao-liang Aug 19, 2026
b527650
skills: honest verification failures; pick verifies the lift
yichao-liang Aug 19, 2026
48f9ca4
bridge: verify PickBlock lifts; degenerate top-edge grasp regression …
yichao-liang Aug 19, 2026
dee20b2
types: fix the two remaining mypy errors
yichao-liang Aug 19, 2026
ae7f56c
motion planning: held probe runs for every body at both endpoints
yichao-liang Aug 20, 2026
69d6ee8
motion planning: robot start escape gets its own depth bound
yichao-liang Aug 20, 2026
e4b5825
skills: goal-IK candidates pin finger joints to the current config
yichao-liang Aug 20, 2026
d01252b
style: docformatter conformance; restore all.yaml trailing newline
yichao-liang Aug 20, 2026
f717a58
test: the hardened bridge oracle e2e passes strictly again
yichao-liang Aug 20, 2026
9a1a58c
agents: raise the plan-validation gate to 5 rollouts (10 after flaky)
yichao-liang Aug 19, 2026
7ca1c6b
agents: reproducible, agent-steerable plan validation
yichao-liang Aug 19, 2026
ef95b8f
update agent SDK model name from "claude-sonnet-5" to "claude-opus-5"
yichao-liang Aug 19, 2026
9f44c7e
style: isort and docformatter conformance for the capture tests
yichao-liang Aug 20, 2026
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
78 changes: 54 additions & 24 deletions predicators/agent_sdk/belief_probe.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
from predicators import utils
from predicators.agent_sdk.config import RefinementConfig, ToolSurfaceConfig, \
ValidationConfig
from predicators.agent_sdk.tools.context import decorrelated_rollout_seed
from predicators.agent_sdk.tools.context import absolute_rollout_seed, \
decorrelated_rollout_seed
from predicators.agent_sdk.tools.scene import apply_state_modifications, \
draw_pybullet_annotation, render_pybullet_image, render_scene_image
from predicators.agent_sdk.tools.verdicts import _EvalStateCollector, \
Expand Down Expand Up @@ -247,10 +248,12 @@ class ProbeTrialsResult(_StrLikeResult):

``trials`` holds one dict per trial (``goal_reached``,
``num_actions``, ``failure`` - ``None`` or ``"step {i} ({option}):
{reason}"``; with ``solved=True`` also ``solved``/``reward`` from
the task evaluator, ``None`` when the verdict errored). ``successes``
counts goal-reaching trials. The current state is NOT advanced -
repeated trials are a measurement, not a navigation step.
{reason}"``; ``planner_seed`` - the motion-planner seed the trial
ran at, reproducible via ``run(plan, seed=...)``; with
``solved=True`` also ``solved``/``reward`` from the task evaluator,
``None`` when the verdict errored). ``successes`` counts
goal-reaching trials. The current state is NOT advanced - repeated
trials are a measurement, not a navigation step.
"""
trials: List[Dict[str, Any]]
successes: int
Expand All @@ -272,13 +275,15 @@ def __repr__(self) -> str:
f"evaluator")
lines = [f"{headline} ({env_note})"]
for i, t in enumerate(self.trials):
seed_tag = (f" (planner seed {t['planner_seed']})"
if t.get("planner_seed") is not None else "")
if t["failure"]:
line = f" trial {i + 1}: FAILED - {t['failure']}"
line = f" trial {i + 1}{seed_tag}: FAILED - {t['failure']}"
elif t["goal_reached"]:
line = (f" trial {i + 1}: goal reached "
line = (f" trial {i + 1}{seed_tag}: goal reached "
f"({t['num_actions']} actions)")
else:
line = (f" trial {i + 1}: goal NOT reached "
line = (f" trial {i + 1}{seed_tag}: goal NOT reached "
f"({t['num_actions']} actions)")
if t.get("solved") is not None:
line += (f" - evaluator: solved={t['solved']}, "
Expand Down Expand Up @@ -852,7 +857,8 @@ def run(
trials: int = 1,
solved: bool = False,
contacts: bool = False,
physics_sweep: bool = False
physics_sweep: bool = False,
seed: Optional[int] = None,
) -> Union[ProbeResult, ProbeTrialsResult, ProbeSweepResult]:
"""Execute an option plan from the current state.

Expand Down Expand Up @@ -918,6 +924,15 @@ def run(
Rollouts are deterministic per point, so each point costs one
rollout and its outcome is a measurement, not a sample. The
current state is NOT advanced and nothing is rendered.

``seed=S`` overrides the base motion-planner seed for this call.
Trials report the planner seed each ran at (trial ``i`` runs at
``S + i``; without ``seed=`` at ``base + i``), and
``evaluate_option_plan``'s validation rollouts report theirs the
same way - so a failed rollout at a reported seed can be
reproduced exactly here: ``run(plan, seed=<reported seed>)``.
A single run (``trials=1``) executes entirely at ``S``; a
physics sweep runs every point at ``S`` instead of the base.
"""
# pylint: disable-next=import-outside-toplevel
import numpy as np
Expand Down Expand Up @@ -1007,7 +1022,8 @@ def _horizon_note(total_actions: int) -> Optional[str]:
# outcome flip between points is attributable to the
# physics perturbation alone.
with (fresh_scope() if point is None else fresh_scope(
physical_overrides=point)):
physical_overrides=point)), \
absolute_rollout_seed(seed):
model = self._option_model()
r = bilevel_sketch.execute_plan_forward(
probe_task,
Expand Down Expand Up @@ -1069,6 +1085,7 @@ def _horizon_note(total_actions: int) -> Optional[str]:
# pylint: disable-next=import-outside-toplevel
import contextlib
trial_dicts: List[Dict[str, Any]] = []
base_planner_seed = seed if seed is not None else CFG.seed
try:
for trial_idx in range(trials):
_check_time_budget(ctx)
Expand All @@ -1083,6 +1100,7 @@ def _horizon_note(total_actions: int) -> Optional[str]:
# env construction keeps the base seed.
with (fresh_scope() if fresh_scope is not None else
contextlib.nullcontext()), \
absolute_rollout_seed(seed), \
decorrelated_rollout_seed(trial_idx):
model = self._option_model()
collector = (_EvalStateCollector(
Expand Down Expand Up @@ -1130,12 +1148,20 @@ def _horizon_note(total_actions: int) -> Optional[str]:
f"{fs.failure_reason or 'not initiable'}")
total = sum(s.num_actions for s in r.steps)
trial_dicts.append({
"goal_reached": r.goal_reached,
"num_actions": total,
"failure": failure,
"solved": trial_solved,
"reward": trial_reward,
"verdict_coarse": coarse,
"goal_reached":
r.goal_reached,
"num_actions":
total,
"failure":
failure,
"solved":
trial_solved,
"reward":
trial_reward,
"verdict_coarse":
coarse,
"planner_seed":
base_planner_seed + trial_idx,
})
except ProbeBudgetExceeded as e:
# Completed trials are minutes of sim time and live in the
Expand Down Expand Up @@ -1224,15 +1250,19 @@ def _on_step(i: int, outcome: Any) -> None:
contact_env = env
contact_env.start_contact_recording()
contact_events: List[Dict[str, Any]] = []
if seed is not None:
notices.append(f"rollout ran at planner seed {seed} (base seed "
f"overridden for this call)")
try:
result = bilevel_sketch.execute_plan_forward(
probe_task,
grounded,
model,
predicates=all_predicates,
sketch=sketch_steps,
on_step=_on_step,
stop_on_failure=True)
with absolute_rollout_seed(seed):
result = bilevel_sketch.execute_plan_forward(
probe_task,
grounded,
model,
predicates=all_predicates,
sketch=sketch_steps,
on_step=_on_step,
stop_on_failure=True)
finally:
if contact_env is not None:
contact_events = contact_env.stop_contact_recording()
Expand Down
13 changes: 10 additions & 3 deletions predicators/agent_sdk/sketch_prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,9 +372,16 @@ def _has_tool(name: str) -> bool:
"task_idx). When it reaches the goal, that plan is captured as "
"your answer, so do NOT finish until evaluate_option_plan "
"CONFIRMS the capture. A goal-reaching plan is re-run several "
"times before capture (simulation varies across runs); if it is "
"reported FLAKY, add margin to the fragile step and resubmit. " +
margin_guidance +
"times before capture (simulation varies across runs; each "
"rollout reports the motion-planner seed it ran at); if it is "
"reported FLAKY, reproduce the failed rollout exactly (pass "
"its reported seed as rollout_seed to evaluate_option_plan, or "
"`sim.run(plan_text, seed=...)` in explore_python) to see WHY, "
"then add margin to the fragile step and resubmit. For a plan "
"you suspect is marginal, request a stricter gate up front "
"with validation_rollouts=N (more repeats; never fewer than "
"configured) or measure reliability first with "
"`sim.run(plan_text, trials=N)`. " + margin_guidance +
"CAPTURE FIRST, OPTIMIZE SECOND: when the reward charges for "
"resources used (read the scoring section), a captured "
"modest-reward solve outscores an uncaptured optimal attempt "
Expand Down
25 changes: 25 additions & 0 deletions predicators/agent_sdk/tools/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,3 +304,28 @@ def decorrelated_rollout_seed(rollout_idx: int) -> Iterator[None]:
yield
finally:
CFG.seed = base_seed


@contextmanager
def absolute_rollout_seed(seed: Optional[int]) -> Iterator[None]:
"""Run a scope at an explicit motion-planner seed (None = no-op).

The agent-facing counterpart of ``decorrelated_rollout_seed``:
validation repeats and probe trials REPORT the planner seed each
rollout ran at, and this scope lets a follow-up call re-run a plan
at exactly that seed - the only way to reproduce a seed-dependent
failure (e.g. one FLAKY validation rollout out of five) instead of
re-sampling and hoping to draw it again. Composes with
``decorrelated_rollout_seed``: enter this first, and trial ``i``
runs at ``seed + i``. Enter AFTER any fresh env is created so env
construction (and its task-cache key) still sees the base seed.
"""
if seed is None:
yield
return
base_seed = CFG.seed
CFG.seed = seed
try:
yield
finally:
CFG.seed = base_seed
Loading
Loading