Skip to content

Conversation

@emilyburghardt
Copy link
Collaborator

Overview

Update the Flex manual for dynamic pipetting/concurrent module actions in RS 8.8.

Test Plan and Hands on Testing

sandbox

Changelog

TODO:

  • update in PAPI-exclusive features. PD 8.7 will support more partial tip configurations

Review requests

Anywhere else this makes sense?

Some of this fits under Flex-exclusive features, but not all. In fact, most of this can be run on the OT-2 as well.

Risk assessment

low.

mjhuff and others added 30 commits November 18, 2025 14:07
…moving runs (#20185)

Closes RABR-839

Currently, if a run is started and the 21st run is a CSV protocol, the run cannot start.

Run deletion is failing with a FOREIGN KEY constraint error when auto-deleting old runs to make room for new ones. The error occurred because run_store.remove() is not deleting associations in the input_data_files_table and output_data_files_table before attempting to delete the run record in the RunAutoDeleter.

To fix, we just add deletion of input and output data file associations in RunStore.remove() before deleting the run record itself. This ensures all foreign key constraints are satisfied during the deletion cascade.

Note that there is currently a 1:1 relationship between input files:runs and output files: runs, and we may have to revisit this logic in the future.
* fix(app): fix quick transfer waste chute option issue
* fix(app): fix deck view container styling in visualization page
# Overview

adding PD 8.7.0 release notes. 

few bugs/tickets I _didn't_ add yet but thought about it (either not
ready yet or probably not important enough:

- https://opentrons.atlassian.net/browse/AUTH-2357 (users should already
see this modal if working properly?)
- https://opentrons.atlassian.net/browse/AUTH-2474 (users already
couldn't do this, as far as I know)
- maybe worth a bug fix mention when it's ready:
https://opentrons.atlassian.net/browse/AUTH-2511

## Test Plan and Hands on Testing



## Changelog



## Review requests

did I cover all the tip selection changes/options? 
are there any lid stacking changes I'm missing? I know there's been some
updates but not sure what of this is user-facing.

## Risk assessment

low.
We were waiting for multiple acks from certain commands, but if those
commands fail at the module's gcode parser stage (i.e. because the
module isn't updated and doesn't handle that gcode) then we'll never get
a second ack and we'll just wait a really long time. This is ultimately
fine in that it doesn't fail the protocol, but it makes anything that
uses modules that have this problem take a really really long time.

## testing
- [x] on a robot with a module that doesn't handle M411, check that the
module polls don't take 60 seconds to complete

Closes RABR-843
…th concurrent Thermocycler profiles (#20193)

## Overview

Protocol Designer lets the user Shift-click to select a range of steps
in the timeline. Now that the timeline has nesting (concurrent
Thermocycler profiles), we need to update that logic to account for some
hazards when the range crosses the boundary of a nested group. This PR
does that.

Closes EXEC-2060. See that ticket for a more full example of the problem
we're solving.

## Changelog

* Update the logic in `getShiftSelectedSteps()` to avoid selecting steps
that are not "user-visible"—i.e., the hidden "wait for profile to
complete" step that implicitly comes at the end of every Thermocycler
profile. Some of the other step CRUD actions are already doing the same
thing.
* Various small renames for clarity.
* Delete `SelectMultipleStepsForGroupAction`, which was unused (never
created, nor used in any reducer).
#20176)

* refactor(app-shell, app-shell-odd): update electron-devtools-installer
# Overview

Copy error on OT2 pipette leveling flow

## Test Plan and Hands on Testing

## Changelog

- changed calibration block statement to accurately reflect orientation

## Risk assessment

low

Closes EXEC-1687
* fix(app):  add unit to disposal volume
…20182)

# Overview

Refactor start run disablement button to display toast description.

## Test Plan and Hands on Testing

- smoke tested on the app
<img width="929" height="754" alt="Screenshot 2025-11-17 at 4 47 31 PM"
src="https://github.com/user-attachments/assets/ae2f7cb6-5923-4ef1-98bc-973d6edd2f5b"
/>

## Changelog
- removed disabled state
- added new strings to support specific protocol disablement reasons.

## Review requests

- review additional messages added
- ensure changes I made don't mean you can start the run even if it
should be disabled.

## Risk assessment

- lowish

Closes EXEC-1635
…ense (#20195)

# Overview
We were not appending the aspirate/dispense result to the move result.
This means that the engine's state was not getting updated with the
current labware, so the *_while_tracking commands were not updating the
pipettes current location.

This means that if you did an action in labware_1, then did a
aspirate/dispense_while_tracking in labware_2 and then moved back to
labware_1 the engine would think that the pipettes current location was
still in labware 1 and it would calculate the safe Z movement and
properly use waypoints to travel back to labware_1.
* fix(app): disposal volume isn't reflected
…organisms (#20202)

* refactor(app): move protocol visualization components under pages to organisms
* fix(protocol-designer): remove unused prop resizedWidth
…art of QuickTransferSummaryState (#20212)

# Overview

This is a type-hinting change to tell TypeScript that the
`aspirateState`/`dispenseState` in `retrieveLiquidClassValues.ts` is
part of `QuickTransferSummaryState`.

Without this, VS Code doesn't find this file when we're looking for
places that touch `.disposalVolumeDispenseSettings`, wasting a lot of
time for programmers trying to find what is setting that field.

Adding this annotation also helps TypeScript catch typos. For example,
if this file had accidentally misspelled the field as
`disposalVolumeDispenseSettingsxx`, TypeScript would now complain about
it.

## Test Plan and Hands on Testing

Just run CI.

## Risk assessment

Very low. No functional change whatsoever.
* fix(app): fix small ui bugs in Protocol Visualization page
Correctly use `set_load_module` for StateUpdate when mapping 2.13 and below PAPI load module calls
Closes RQA-4807

To denote image capture on protocol error, the HTTP API uses the
`errorRecoveryCameraEnabled` field except for `GET /camera`, in which
case we use `errorRecoveryEnabled`. The JS code expects the shape of the
camera settings to conform to the pattern elsewhere. To keep the HTTP
API and the app consistent, let's update our one usage of
`errorRecoveryEnabled` to `errorRecoveryCameraEnabled`.

---------

Co-authored-by: Rhyann Clarke <[email protected]>
* fix(app): fix command step height issue
…20208)

* fix(components): fix timeline scrubber's background hover behavior
ddcc4 and others added 29 commits December 1, 2025 14:02
…ver (#20255)

# Overview

This is a temporary Python-only fix for AUTH-2537:

Previously, in step-generation for Transfer steps, we would emit a
liquid class with:
```
pipette.transfer_with_liquid_class(
  liquid_class=protocol.define_liquid_class(
    properties={ ... : {"tip rack the user selected for this step": {
      ...
    }
  )
)
```
But this is wrong if the user wants a tip handling policy of "never" for
this step, because "never" means we need to perform this transfer with
the tip that we picked up from a **previous** step, which could have
come from a different tip rack than the one the user selected for this
step.

This bug would cause the generated protocol to fail analysis.

This PR changes step-generation to use the tip rack from
`robotState.tipState.pipettes[pipette].tiprackURI` when generating
Python for `changeTip=="never"`.

## Test Plan and Hands on Testing

Here is a protocol from PD before this fix, that demonstrates the bug.
In Step 1, it uses `opentrons_96_tiprack_20ul`. In Step 2, it tries to
use `opentrons_96_tiprack_10ul` with tip handling "never". PD
successfully exports the protocol, but it fails in analysis:
[Tip_Management_Never.py](https://github.com/user-attachments/files/23862930/Tip_Management_Never.py)

The protocol will pass analysis when it's re-exported from PD with this
PR.

## Risk assessment

Low-medium. This logic is somewhat tricky.
Correctly reflect volume field title for moveLiquid volume field
depending on path according to designs. The pattern is as follows:

- single path -> "Volume per well"
- distribute path -> "Dispense volume per well"
- consolidate path -> "Aspirate volume per well"
…modal header (#20260)

ensure the `currentStep` prop passed to `WizardHeader` from
`TipSelectionModal` is 1-indexed
Closes RQA-4921

In #20088, we simplified the "robot is busy" banner state in robot settings by using a simplified conditional check, useRobotIsBusy. That works great for the robot settings page, and while we tried to harmonize the "busy" state logic by extending it to the robot details page, that didn't work out as well: we want users to be able to swap/calibrate pipettes on this page while a run is being set up. It's the only way to do so on the OT-2, too, so we definitely can't block it.

This PR effectively reverts the changes made in #20088 to the robot details page.
…nd (#20265)

This deletes an old hack, having something to do with modal positioning,
that hasn't been used since the code for the old designs got deleted in
#16653.
* fix(app): remove scrollbar from second window
* fix(app): fix font weight
…V file (#20245)

# Overview

A customer reported that a parameterized protocol works with a short CSV
file but fails with their longer CSV file:
https://opentrons.slack.com/archives/C389UCULX/p1763376654727119

The root cause seems to be that in `parse_as_csv()`, we were truncating
the CSV file to 1024 bytes before passing it to the `csv.Sniffer`. If
that chops up a line at an inopportune place, it would cause the sniffer
to fail with `Could not determine delimiter`.

We should just pass the whole CSV file to the sniffer.

From our meeting this morning, we said we would fix this in `edge`
rather than trying to get it into RS 8.8.0.

## Test Plan and Hands on Testing

Added a test case with a long CSV file derived from the customer report.

## Risk assessment

Low.

I guess there's a small risk that there could be some horrifying junk in
the CSV file after the first 1024 bytes, that the sniffer previously
wouldn't see, that would now be visible to the sniffer. But I think
overall, it's more correct to let the sniffer see the whole file, rather
than arbitrarily cutting it off at 1024 bytes.
* ci: update checkout and node versions
…FromSlot`s (#20275)

## Overview

These labware had a `cornerOffsetFromSlot.z` of -0.71, which is dubious
because that would put them slightly underground. Since it's the exact
same number as PR #17723 / EXEC-1268, I suspect this was a copy-paste
error and was not intentional.

Closes EXEC-2087.

## Changelog

For these labware:

* `black_96_well_microtiter_plate_lid`
* `corning_96_wellplate_360ul_lid`
* `corning_falcon_384_wellplate_130ul_flat_lid`

I did this:

* Create a new labware version, v2. It's exactly the same as v1 except
`cornerOffsetFromSlot.z` is zeroed out.
* In PAPIv2.28, start loading these new labware versions by default.

## Test Plan and Hands on Testing

I don't have these labware handy to test with, but we can expect the
gripper positions to move up by 0.71 mm now. I expect that to be fine
because they're currently only at ~7mm of ~10mm.
…indings to RobotSettings (#20266)

# Overview

Attach camera bindings to ODD and Desktop to enable use of image
settings

`Note:` these do not work yet because the end point
`camera/cameraSettings` does not exist

## Test Plan and Hands on Testing

Smoke tested app and ODD


https://github.com/user-attachments/assets/13d308de-55d9-421d-9e8b-25e7af1c6699


https://github.com/user-attachments/assets/80812eaa-b0f4-41d6-b116-e6ba79fbc5e4

## Changelog

- omitted cameraId from hook since it is set to `OT_SYSTEM_CAMERA`
- added cancel button on robot settings and loading state for save
button
- relocated hook to `local-resources` since it is used in ODD and
desktop
- added utils file to convert zoom from string / number
- added `backIconName` to allow for custom icon in place of the back
arrow in `ChildNavigation`

## Review requests

- What do you need from reviewers to feel confident this PR is ready to
merge?
- Ask questions.

## Risk assessment

medium - not in real use yet but made changes to ChildNavigation which
is a widely used component

Closes part 1 of EXEC-2079
…#20276)

# Overview

Send camera image settings during run setup 

## Test Plan and Hands on Testing

- smoke tested on desktop app and ODD and saw attempted post requests in
logs
**ODD camera settings** 
<img width="1246" height="665" alt="Screenshot 2025-12-03 at 10 41
54 AM"
src="https://github.com/user-attachments/assets/73af5b0c-9bcd-416b-81e3-0f523aa121a3"
/>

**Desktop protocol setup**
<img width="1339" height="735" alt="Screenshot 2025-12-03 at 10 43
06 AM"
src="https://github.com/user-attachments/assets/46fe2dd5-94b5-4d32-9a91-a044516c8f01"
/>

**ODD protocol set up**
<img width="1067" height="729" alt="Screenshot 2025-12-03 at 11 57
28 AM"
src="https://github.com/user-attachments/assets/d2cdceb2-6e3a-43e2-95ce-a61498c5f06a"
/>


## Changelog

- exported run hook from react-api-client
- passed `runId` into ODD camera controls to determine what hook to use

## Review requests

- passing in `runId` is a little messy in order to follow typing rules
and rule of hooks - how to fix

## Risk assessment

- medium - untested


Closes remaining part of EXEC-2079
# Overview

Link to opentrons.com in the header of docs.opentrons.com pages.

Addresses RTC-815.

## Test Plan and Hands on Testing

[Sandbox](https://sandbox.docs.opentrons.com/mkdocs-link-to-dotcom/)

## Changelog

- Add new partial override with extra <li> and hardcoded <svg> (our icon
library version is black only).

## Review requests

Is this the best way to do this?
Do we need the link to remain visible in the smallest responsive
designs, when the tab bar collapses to a sidebar?

## Risk assessment

low
…tiation (#20287)

Closes EXEC-2089

To harmonize the run behavior between quick transfer and standard runs (not protocols -- we want to keep that delineation), quick transfer runs should no longer make use of their own instance of the RunAutoDeleter and instead wire into a plain ol' RunAutoDeleter that does not delineate between protocol kinds.
* fix(app):  fix slot empty structure to align with the design
With the decision to treat Quick Transfer protocols more like standard
protocols, we want to show them in the desktop app's
`RecentProtocolRuns` component. This also allows us to view and download
any files from the run, which as of now would include photos taken
during any potential error recovery.

There are also a few instances in ODD where we implicitly delete QT
runs. We don't want to do this!
# Overview

Moved run status utils into `local-resources` since they are used across
platforms in the app
Replaced the majority of instances of bare `runStatus` strings with
utils

## Changelog
- moved utils from `ProtocolHeader` to `local-resources`
- fixed conditional bug that was preventing you from restarting a run
due to the robot being in idle state

## Test Plan and Hands on Testing
- smoke tested various places of app and odd

## Review requests

- Double check run status groupings aren't repeated
- Double check majority of run status bare string usage is addressed


## Risk assessment

medium - touches a lot of code but does not change functionality

Closes second half of EXEC-1478
…ls (#20197)

# Overview

Camera, concurrent modules, and dynamic liquid tracking implemented into
active ABR protocols

## Test Plan and Hands on Testing

- All protocols simulate
- `TODO:` protocols with the tc lid and dynamic liquid tracking have not
been tested on a robot yet

## Changelog
- also added a robot log script to compare duration of protocol commands

## Review requests

@ryanthecoder when implementing the dynamic pipetting, there were a
couple spots I needed to add `prepare_to_aspirate()` before a dynamic
aspirate to avoid getting this error:

```
ProtocolCommandFailedError [line 1035]: Error 4000 GENERAL_ERROR (ProtocolCommandFailedError): PipetteNotReadyToAspirateError: Pipette cannot aspirate while tracking because a previous dispense or blowout pushed the plunger beyond the bottom position. The subsequent aspirate must be from a specific well so the plunger can be reset in a known safe position.
```
Is this expected?

## Risk assessment

medium until the protocols are run on the robot
…ges (#20299)

Closes RQA-4941

Axios cannot return Blob types when in a Node.js environment (there is no native blob type in the version of Axios we use), and Electron's IPC mechanism does not properly serialize Blob objects into strings anyway.

To fix, on the node layer we can request an ArrayBuffer type instead, transform it to an Array type, and then send this data across the IPC as it becomes perfectly serializable. We can then parse this Array type back into a Blob on the browser layer.

Note that downloading images works perfectly fine - it's just an issue whenever we request the raw image files themselves.
@codecov
Copy link

codecov bot commented Dec 5, 2025

Codecov Report

❌ Patch coverage is 3.11388% with 1089 lines in your changes missing coverage. Please review.
✅ Project coverage is 25.83%. Comparing base (1667af8) to head (06b21aa).
⚠️ Report is 98 commits behind head on docs-8.8.

Files with missing lines Patch % Lines
app/src/molecules/MediaContainerContent/index.tsx 0.00% 90 Missing ⚠️
...s/Desktop/ProtocolDetails/AnnotatedSteps/index.tsx 0.00% 81 Missing ⚠️
app/src/local-resources/runs/utils.ts 0.00% 76 Missing ⚠️
app/src/local-resources/runs/constants.ts 0.00% 75 Missing ⚠️
...c/organisms/Desktop/Devices/RecentProtocolRuns.tsx 0.00% 75 Missing ⚠️
...unCamera/ImageGalleryContainer/GalleryItemCard.tsx 0.00% 66 Missing ⚠️
...p/src/molecules/ODDMediaContainerContent/index.tsx 0.00% 63 Missing ⚠️
app/src/atoms/buttons/TouchControlButton.tsx 0.00% 62 Missing ⚠️
...r/RunHeaderContent/RunHeaderSectionLower/index.tsx 0.00% 59 Missing ⚠️
...nt/ActionButton/hooks/useActionBtnDisabledUtils.ts 0.00% 39 Missing ⚠️
... and 60 more

❗ There is a different number of reports uploaded between BASE (1667af8) and HEAD (06b21aa). Click for more details.

HEAD has 2 uploads less than BASE
Flag BASE (1667af8) HEAD (06b21aa)
step-generation 2 1
protocol-designer 2 1
Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##           docs-8.8   #20305       +/-   ##
=============================================
- Coverage     56.80%   25.83%   -30.98%     
=============================================
  Files          3541     3627       +86     
  Lines        295922   302041     +6119     
  Branches      42766    42320      -446     
=============================================
- Hits         168100    78020    -90080     
- Misses       127542   223992    +96450     
+ Partials        280       29      -251     
Flag Coverage Δ
protocol-designer 19.35% <0.17%> (+0.68%) ⬆️
step-generation 5.59% <0.17%> (+0.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
app-shell-odd/src/config/__fixtures__/index.ts 99.42% <100.00%> (+0.04%) ⬆️
app-shell-odd/src/config/migrate.ts 96.24% <100.00%> (+0.30%) ⬆️
app/src/__testing-utils__/matchers.ts 6.66% <ø> (-73.34%) ⬇️
app/src/molecules/ODDInfoScreen/OddInfoScreen.tsx 0.00% <ø> (-100.00%) ⬇️
...op/Devices/ProtocolRun/ProtocolRunCamera/index.tsx 0.00% <ø> (-94.00%) ⬇️
...rotocolRun/ProtocolRunHeader/hooks/useRunErrors.ts 0.00% <ø> (-13.05%) ⬇️
...vices/ProtocolRun/SetupLabware/SetupLabwareMap.tsx 0.00% <ø> (-24.11%) ⬇️
.../RobotSettings/AdvancedTab/UpdateRobotSoftware.tsx 0.00% <ø> (-80.77%) ⬇️
app-shell-odd/src/main.ts 0.00% <0.00%> (ø)
app-shell-odd/src/notifications/connect.ts 0.00% <0.00%> (ø)
... and 68 more

... and 2013 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.