From 79f9a84407a081cde635fe289e2ffd99142481d7 Mon Sep 17 00:00:00 2001 From: Pepijn Date: Tue, 2 Jun 2026 15:36:23 +0200 Subject: [PATCH] annotate: make full-episode subtask coverage unconditional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the subtask_full_coverage config flag. Stitching subtask spans into a contiguous full-episode cover is now always applied in _generate_subtasks — a sparse / gap-ridden subtask timeline is never desirable for conditioning, so there's no reason to make it optional. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../annotations/steerable_pipeline/config.py | 15 ++++++--------- .../modules/plan_subtasks_memory.py | 9 +++++---- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/lerobot/annotations/steerable_pipeline/config.py b/src/lerobot/annotations/steerable_pipeline/config.py index 0389363b8..09c935e66 100644 --- a/src/lerobot/annotations/steerable_pipeline/config.py +++ b/src/lerobot/annotations/steerable_pipeline/config.py @@ -73,15 +73,12 @@ class PlanConfig: # nothing). +1 VLM call/ep. subtask_verify: bool = True - # ``subtask_full_coverage``: deterministic post-step (no VLM call) - # that stitches the surviving subtask spans into a contiguous cover - # of the whole episode — first subtask pulled back to t0, each span's - # end snapped to the next span's start, last span extended to t_last. - # Without it the verify pass (which prunes spans) can leave the - # subtask timeline starting late or full of gaps, so frames fall - # through with no active subtask. On by default; disable only if a - # downstream consumer genuinely wants sparse (non-tiling) subtasks. - subtask_full_coverage: bool = True + # NOTE: subtask spans are ALWAYS stitched into a contiguous + # full-episode cover (first subtask pulled back to t0, gaps closed, + # last span extended to t_last) as a deterministic post-step in + # ``_generate_subtasks._stitch_full_coverage``. This is not + # configurable — a sparse / gap-ridden subtask timeline is never + # desirable for conditioning, so it is unconditional. # When True (and backend supports it, e.g. ``openai``), the ``plan`` # module sends a ``video_url`` block pointing at a per-episode mp4 diff --git a/src/lerobot/annotations/steerable_pipeline/modules/plan_subtasks_memory.py b/src/lerobot/annotations/steerable_pipeline/modules/plan_subtasks_memory.py index b117c5657..4ffef49c1 100644 --- a/src/lerobot/annotations/steerable_pipeline/modules/plan_subtasks_memory.py +++ b/src/lerobot/annotations/steerable_pipeline/modules/plan_subtasks_memory.py @@ -578,10 +578,11 @@ class PlanSubtasksMemoryModule: # The VLM (especially after the verify pass prunes spans) can # leave the first subtask starting after t0 or leave gaps between # spans, so the subtask timeline no longer tiles the whole - # episode and frames fall through with no active subtask. Stitch - # the surviving spans into a contiguous cover of [t0, t_last]. - if getattr(self.config, "subtask_full_coverage", True): - cleaned = self._stitch_full_coverage(cleaned, record) + # episode and frames fall through with no active subtask. Always + # stitch the surviving spans into a contiguous cover of + # [t0, t_last] — there is no scenario where a sparse, gap-ridden + # subtask timeline is desirable for conditioning. + cleaned = self._stitch_full_coverage(cleaned, record) return cleaned