fix(skills): address code-review findings on the pick/skills-API branch - #587
Merged
theo-michel merged 1 commit intoJul 30, 2026
Merged
Conversation
- pick_any_object: explicit cancel point in the wrist-servo descend loop (the fast path never reached self.sleep(), so a Stop rode the descent for up to 60 s); verify the close/twist lift instead of discarding move_to_joint_positions' False (a skipped lift left the EE at floor_z for the verify backup drive), falling back to the FK-checked cartesian lift; monotonic loop deadlines; hoist _sweet_box() out of the 30 ms follow loop. - Skill.say(wait=True): the speech wait now aborts on cancel instead of ignoring a Stop for up to 45 s (best-effort return, no raise — say() also runs in post-cancel teardown). - catalog: load physical skills and write the physical_skills/ refs BEFORE importing code skills, in __init__ and reload_all — on a fresh workspace every `from physical_skills import X` skill was rostered broken for the whole first pass (self-healing only via the optional watcher). - initializer: regenerate refs for every non-code roster entry instead of a 4-type allowlist — with a "poses" skill present the two writers never agreed, so each rewrite retriggered the other's full reload forever. - arm_control: warn (throttled) when the idle gain decay is blocked by a short load read instead of silently holding stiff gains. Claude-Session: https://claude.ai/code/session_01QePrpqbeHd4TN8KGB5RTNY
theo-michel
marked this pull request as ready for review
July 30, 2026 18:47
Contributor
Greptile SummaryImproves cancellation responsiveness and physical-skill loading reliability while adding safer manipulation fallback handling and arm-load diagnostics.
Confidence Score: 5/5The PR appears safe to merge, with no concrete changed-code defects identified. The revised loading order, cancellation checks, monotonic deadlines, Boolean lift-result handling, and diagnostic logging remain consistent with their surrounding runtime contracts. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Discover physical skills] --> B[Generate physical_skills refs]
B --> C[Import code skills]
C --> D[Publish combined skill roster]
E[Pick object] --> F[Joint-space lift]
F -->|success| G[Continue grasp verification]
F -->|failure| H[FK-verified Cartesian lift]
H --> G
Reviews (1): Last reviewed commit: "fix(skills): address code-review finding..." | Re-trigger Greptile |
theo-michel
added a commit
that referenced
this pull request
Jul 30, 2026
…ch (#587) - pick_any_object: explicit cancel point in the wrist-servo descend loop (the fast path never reached self.sleep(), so a Stop rode the descent for up to 60 s); verify the close/twist lift instead of discarding move_to_joint_positions' False (a skipped lift left the EE at floor_z for the verify backup drive), falling back to the FK-checked cartesian lift; monotonic loop deadlines; hoist _sweet_box() out of the 30 ms follow loop. - Skill.say(wait=True): the speech wait now aborts on cancel instead of ignoring a Stop for up to 45 s (best-effort return, no raise — say() also runs in post-cancel teardown). - catalog: load physical skills and write the physical_skills/ refs BEFORE importing code skills, in __init__ and reload_all — on a fresh workspace every `from physical_skills import X` skill was rostered broken for the whole first pass (self-healing only via the optional watcher). - initializer: regenerate refs for every non-code roster entry instead of a 4-type allowlist — with a "poses" skill present the two writers never agreed, so each rewrite retriggered the other's full reload forever. - arm_control: warn (throttled) when the idle gain decay is blocked by a short load read instead of silently holding stiff gains. Claude-Session: https://claude.ai/code/session_01QePrpqbeHd4TN8KGB5RTNY Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes for the findings from this review of #542, targeting
theo/pick-wrist-servoso they fold into that PR.pick_any_object._wrist_descend: explicitcheck_cancelled()at the top of the descend loop — the fast path (fresh wrist frame already buffered, the common case after each 0.5 s blocking move) never reachedself.sleep(), so a Stop rode the descent for up to 60 s.pick_any_object._close_twist_lift: the joint-space lift'smove_to_joint_positionsreturn is now checked (it returnsFalseinstead of raising); a failed/skipped lift falls back to the FK-verifiedmove_checkedcartesian lift with the grip kept, instead of letting_grasp_verifiedback the base up 0.15 m with the EE still atfloor_z.pick_any_object: loop deadlines moved fromtime.time()totime.monotonic()(matchingbrain_client_node's NTP-step rationale);_sweet_box()hoisted out of the 30 ms follow loop.Skill.say(wait=True):_wait_for_speech_endnow aborts on cancel instead of ignoring a Stop for up to 45 s. Best-effort early return, no raise —say()also runs in post-cancel teardown paths.catalog.py:__init__andreload_allnow load physical skills and write thephysical_skills/refs before importing code skills. Previously, on a fresh workspace everyfrom physical_skills import Xskill was rostered broken for the whole first pass, self-healing only via the optional watchdog-based watcher.initializer.py:_regenerate_physical_refsnow includes every non-coderoster entry instead of a 4-type allowlist. The allowlist omitted"poses"(a real roster type perSkillInfo.msg), so with a poses skill present the two writers ofphysical_skills/__init__.pynever agreed — each rewrite retriggered the other's full reload forever; the content-compare could never converge.arm_control.cpp: throttled warning when the idle gain decay is blocked by a short load read, instead of silently holding stiff gains (behavior unchanged — staying stiff on unknown load is the safe call).Deliberately not addressed (author's call): the emptied
CLAUDE.md(confirmed intentional), the removed test suites /test_backwards_compat.py(deliberate per the PR body), composed children's interface-halt at call end (design question — halting shared interfaces mid-parent-run could stop parent-commanded motion), per-skill storage namespace collisions (changing the path orphans existing stored data — needs a migration decision), the double reload per recorded episode, and the head-camera constants scaling wrist pixels (latent only — both cameras run 640×480).Validation
ruff check+ruff format --checkclean on the touched Python files,clang-format --dry-run --Werrorclean onarm_control.cpp, pyright error count identical to the branch baseline (57, all missing-ROS-deps environment noise). No robot here — the descend-cancel and lift-fallback paths need a hardware pass../innate-sim up. — N/A, no simulator changes.sim/assets.lock.json. — N/A.https://claude.ai/code/session_01QePrpqbeHd4TN8KGB5RTNY
Generated by Claude Code