* feat(segmentation): replace One Click Segment with ClickSegmentTool
Wire OHIF to ClickSegmentTool from Cornerstone3D (#2780), rename the
toolbox button to Click to Segment, and enable it only on PET (PT)
viewports.
* chore(deps): bump @cornerstonejs packages to 5.4.13
Pick up ClickSegmentTool from the published Cornerstone3D release so
OHIF installs the tool from npm without a local CS3D link.
The Queue tests measured real setTimeout wall-clock time and asserted
elapsed < 2 * threshold. On busy CI runners a 2400ms timer can take
longer than 4800ms to fire, failing the assertion intermittently (seen
in downstream validation runs). Switch to jest's modern fake timers so
elapsed is exactly the timeout delay: the tests are deterministic and
no longer spend ~5 seconds of real time waiting.
* feat: Add extensibility for tmtv and segmentation modes
* Fixes for ordering issues on laod
* Remove unnecessary reference lookup
* Chane side panel timing to fix tests
* PR comments - change how mode definitions get created
* Improvements to mode customizations
* Start organizing customizations
* Misc fixes for a customization demo page
* Security fixes
* PR requested changes to naming
* fix: Several new worklist issues
* refactor: Export a single OnStudyDoubleClick type from the StudyList barrel
Addresses PR review feedback: the double-click handler signature was
written out in both TableProps and the WorkList customization cast,
so the two could drift apart.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: Run worklist study double-click as a command, registrable by modes
- Modes can now export getCommandsModule on their definition; appInit
registers it (via the new ExtensionManager.registerCommandsModule)
before the mode is instantiated, in a new 'WORKLIST' commands context,
so the commands are available on the worklist before any mode route
is entered.
- The workList.onStudyDoubleClick customization is now a command run
input (name/options) instead of a bare function, defaulting to the
new launchDefaultMode command, which launches the default workflow
falling back to the first applicable one. commandOptions.workflowId
overrides it to a specific mode.
- Duplicate mode ids are now skipped before running their modeFactory
rather than after.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat: Update to use pnpm (#6031) [simulated squash-merge]
* feat: load DICOM SEG images via imageLoader
* feat: load DICOM SEG images via imageLoader
* PR review fixes
* Test fragment of compressed multiframes
* fix: Removed dependencies incorrectly
* Update frame as a targetted change to avoid stripping remaining params
* lock
* Update test to agree with the missing representation branch
* test(contour): contour color change coverage (#6042)
* test(contour): contour interactions delete segment (#6069)
---------
Co-authored-by: Bill Wallace <wayfarer3130@gmail.com>
* chore(version): Update package versions to 3.13.0-beta.98 [skip ci]
* feat(testing): OHIF Test Agent Skills (#5993)
* chore(version): Update package versions to 3.13.0-beta.99 [skip ci]
* test(contour): Add the ContourSegmentToggleLock.spec.ts test file to test contour locking (#6072)
* chore(version): Update package versions to 3.13.0-beta.100 [skip ci]
* chore(testing): Flock lock for playwright tests; Pin node version for OHIF; add more workers (#6099)
* update Cypress apt deps for Ubuntu Noble (drop libgconf-2-4, libasound2→libasound2t64)
* chore(version): Update package versions to 3.13.0-beta.101 [skip ci]
* Debug fixes
* perf(seg): pass explicit frame decode concurrency (16) to SEG loader
Pass an explicit concurrency value (SEG_FRAME_DECODE_CONCURRENCY = 16) into
createFromDicomSegImageId rather than relying on the adapter default, so the
SEG frame fetch/decode parallelism is set at the call site and is ready to
become configurable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(behaviours): add behaviours section + multiframe Part 10 prefetch proposal
Start a "Behaviours" docs section for documenting how the system and UI behave
end-to-end (observed behaviours, design proposals, and failure modes), with an
index README and a Docusaurus category.
First entry is the proposal for loading a multiframe SEG as a single Part 10
instance: prefetch the whole instance (gated by loadMultiframeAsPart10RaceTimeMs),
parse it with dcmjs (handling multipart/related vs raw DICOM), and register the
per-frame compressed pixels into the Cornerstone3D core image cache (the single
uniform frame registry) so the per-frame load path is served locally while the
standard decode path is unchanged. Best-effort: falls back to per-frame fetches
on any failure.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Pre-cache the image data using a full part10 file for performance
* Add customizations to specify type of segmentation save
* Add clearcache of the cacheData
* Bump @cornerstonejs/* pins 5.1.3 -> 5.4.10 to match libs/@cornerstonejs base
libs/@cornerstonejs (fix/use-imageLoader-for-seg) is based on the released
cs3d 5.4.10 (merge-base with origin/main is the 5.4.10 version bump), so pin
OHIF to that release. The local branch changes still reach the app via the
cs3d:link symlinks; these pins keep the lockfile/npm fallback aligned.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Fix seg OOM
* fix: file meta garbage element, bogus NumberOfFrames, unguarded source-map-loader
- dicomWriter: drop the naturalized meta.TransferSyntaxUID assignment that
dcmjs wrote as a garbage (0000,0000) element into every saved file's meta
group (download / clipboard / local wadouri blob / local store); keep the
hex 00020010 assignment, which is required for string-form _meta fallbacks.
- registerNaturalizedDatasetForLocalWadouri: keep the computed frame count
local so single-frame IODs (SR, RTSTRUCT) no longer gain a bogus
NumberOfFrames element in their serialized form.
- rsbuild.config: resolve source-map-loader opportunistically (it is not a
project dependency; the rule only serves the gitignored cs3d-link
workflow) so fresh clones no longer crash at config load.
- Regression tests for both writer fixes (mutation-checked).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* PR review comment fixes
* Update versions
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: diattamo <mmddiatta@gmail.com>
Co-authored-by: ohif-bot <danny.ri.brown+ohif-bot@gmail.com>
Co-authored-by: Joe Boccanfuso <109477394+jbocce@users.noreply.github.com>
* Add customization URL parameter
* fix: Preserve should be customizeable
* Update customizations docs
* fix: Overlay items on patient name
* Add customization test
* Fix resolve to absolute path
* fix: Warn on no data in load
* Remove unused customization stuff
* fix: PR comments
* Update stored parameters to only use an array for mulitples
* Remove requires ohif.* special call out
* Remove strict mode
* PR comments
* Document segmentation examples
* Add three examples as requested
* PR comments
* lock
* Remove old customizatoin export
* fix: Ordering issues on customization loads
* fix: Use correct default for dev builds app config
* Fixes for conflicts
* chore: restore pnpm-lock.yaml to match master
The lockfile diff was incidental peer-descriptor churn and carried no
functional dependency change. It tripped the CircleCI security-audit gate
(which only runs when pnpm-lock.yaml is in the PR diff), surfacing a
pre-existing critical `decompress` transitive vuln that also exists on
master. Restoring master's lockfile removes the audit trigger.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(ci): restore json5 lockfile entry; ignore unfixable decompress GHSA
The previous commit restored pnpm-lock.yaml from master, which dropped the
json5@2.2.3 entry that platform/core legitimately depends on (JSONC parsing
for the customization feature). That broke `--frozen-lockfile` install
(ERR_PNPM_OUTDATED_LOCKFILE). This restores the correct lockfile.
Because the lockfile must change (json5), the CircleCI security-audit gate
runs and previously failed on a critical `decompress` <=4.2.1 zip-slip
advisory. This is a pre-existing transitive vuln (present on master too) with
no published patch — decompress's latest release is 4.2.1, so no version
bump/override can resolve it. It reaches the tree only via @itk-wasm/dam, a
build/data-asset extraction tool under @cornerstonejs/labelmap-interpolation.
Add GHSA-mp2f-45pm-3cg9 to the existing pnpm-workspace.yaml auditConfig
ignoreGhsas accepted-risk list, matching how the repo already exempts other
build-tooling advisories. `pnpm audit --audit-level high` now passes locally
(1 critical ignored, 0 high).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(e2e): fix visitStudy URL encoding that broke mpr2 study load
The visitStudy rewrite (added for the ?customization= option) built the URL
with new URLSearchParams({ StudyInstanceUIDs: studyInstanceUID }), which
percent-encodes the value. mpr2.spec.ts embeds an extra param in the UID
string ('<uid>&hangingprotocolid=mpr'), so the & and = were encoded and the
whole thing collapsed into one invalid StudyInstanceUIDs value -> the study
could not be found ('studies are not available'), the viewer never rendered,
and the side-panel-header-right click timed out.
Restore master's raw concatenation for StudyInstanceUIDs (so embedded params
survive as separate query params) while still appending the customization
option separately. Only mpr2 embeds & in the UID, matching the single failure.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* PR comments
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- move authenticated rendered media loading into the datasource\n- route DICOM video display sets through Cornerstone video viewports\n- add a 3.12 to 3.13 migration note for the removed DICOM-video viewport namespace
Testing this needs a release and there are no functional changes, only pnpm migration issues, so merging early for test.
* fix: pnpm related dependency bugs - nothing funcitonal
* Undo peer dependency due to non-pnpm integration issues
This is a fix to pnpm deployment which needs testing as the final part of origin/master release
No functional changes
* fix(docs): remove stray tool-call tags breaking the MDX build
platform/docs/docs/migration-guide/3p12-to-3p13/build-tooling.md ended with
two orphan closing tags (leftover tool-call serialization artifacts):
</content>
</invoke>
Docusaurus compiles Markdown as MDX (JSX-aware), so the orphan closing tag
failed the docs build:
MDX compilation failed ... Unexpected closing slash in tag, expected an
open tag first (build-tooling.md line 402)
This was the remaining blocker for build-and-deploy-docs once the
--no-frozen-lockfile change let the install step succeed. A scan of the docs
tree found no other such artifacts. Verified locally: docusaurus build now
generates static files with no MDX errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Update lockfile and avoid freshness check on every command
* fix(release): keep workspace:* in the repo, concretize only at publish
The release flow rewrote internal @ohif/* dependency specifiers to the concrete
version and committed them, so pnpm-lock.yaml (which records workspace links)
drifted from the manifests on every version bump. The resulting
ERR_PNPM_OUTDATED_LOCKFILE broke every frozen install: Netlify (viewer-dev),
the docs deploy, pnpm's pre-run deps check, and post-merge installs.
Keep workspace:* everywhere in the committed repo and move the concrete-version
substitution to publish time only:
- publish-version.mjs: bump each package's own `version` field only; stop
rewriting @ohif/* dependency/peerDependency specifiers.
- publish-package.mjs: publish with `pnpm publish --no-git-checks` instead of
`npm publish`. pnpm rewrites workspace:* to the exact version in the published
tarball; npm would publish the literal "workspace:*", which npm/yarn consumers
cannot resolve.
- One-time: revert the 25 workspace manifests' @ohif/* specifiers to workspace:*
(version fields untouched) and regenerate pnpm-lock.yaml to match.
Because internal deps are workspace:* (links, not versions in the lockfile),
version bumps no longer change pnpm-lock.yaml, so it stays in sync and frozen
installs keep working.
Verified: `pnpm install --frozen-lockfile` passes, and `pnpm pack` of @ohif/core
emits a tarball whose @ohif/ui dependency is the exact version (3.13.0-beta.92),
not workspace:*.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(ci): correct build-docs install comment for workspace:* release flow
publish-version.mjs no longer rewrites @ohif/* deps to concrete versions, so
the old comment was stale. Internal deps stay workspace:* and the lockfile
stays consistent; pnpm publish concretizes only the published tarball.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci(docs): use --frozen-lockfile now that the lockfile no longer drifts
With internal deps as workspace:* the lockfile stays in sync across version
bumps, so the docs deploy can install frozen -- failing fast on genuine
lockfile drift instead of silently reconciling. The --no-frozen-lockfile
workaround is no longer needed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: use --frozen-lockfile in CI install steps now that the lockfile is stable
Internal @ohif/* deps are workspace:* so pnpm-lock.yaml no longer drifts; the
UNIT_TESTS/BUILD/NPM_PUBLISH installs can run frozen and fail fast on genuine
drift. Kept --no-frozen-lockfile only where it is still required: the Dockerfile
(platform/docs is excluded from the build context) and the playwright CS3D-version
step (mutates @cornerstonejs versions before installing).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test: stability of seg load mpr test
* Better drag fix for crosshairs
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Merging for testing since this can't be tested without a merge to master
fix(ci): use --no-frozen-lockfile for docs deploy (pnpm migration)
The Build and Deploy Docs workflow ran `pnpm install --frozen-lockfile` and
failed on every master push after the pnpm migration:
[ERR_PNPM_OUTDATED_LOCKFILE] pnpm-lock.yaml is not up to date with
platform/core/package.json
- @ohif/ui (lockfile: workspace:*, manifest: 3.13.0-beta.90)
publish-version.mjs rewrites @ohif/* workspace deps from "workspace:*" to the
concrete release version and commits that bump to master, so the committed
manifests intentionally drift from pnpm-lock.yaml. Every CircleCI job already
passes --no-frozen-lockfile for exactly this reason (pnpm-workspace.yaml sets
frozenLockfile:true as the default); the docs workflow was the lone job still
using frozen and so broke the docs deploy.
Switch the docs install to --no-frozen-lockfile to match the rest of CI.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
* fix(ci): write npm auth token to ~/.npmrc so publishes authenticate
NPM_PUBLISH wrote the registry auth token to ~/repo/.npmrc (the repo root),
but publish-package.mjs does process.chdir(packageDirectory) and runs
`npm publish` from inside each package (platform/ui, extensions/*, ...). npm
reads the project .npmrc from that package dir and the user .npmrc from
$HOME -- it never walks up to ~/repo/.npmrc -- so every publish failed with
ENEEDAUTH ("need auth ... requires you to be logged in").
publish-package.mjs catches and swallows per-package publish errors, so
NPM_PUBLISH still exited 0 and reported green; the breakage was silent. As a
result no @ohif/* package newer than 3.13.0-beta.89 (the last publish before
the pnpm migration) reached npm -- beta.90 and beta.91 are missing and the
beta dist-tag is stuck at beta.89.
Write the token to ~/.npmrc (npm per-user config, read regardless of cwd)
instead. This also stops clobbering the committed workspace-config .npmrc
(node-linker=hoisted) at the repo root, which the in-job pnpm install/build
relies on. Applied to all three auth steps for consistency.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(docker): copy preinstall.js before pnpm install in builder stage
The builder stage copies only the package.json manifests, runs
`pnpm install --no-frozen-lockfile`, and copies the rest of the source
afterward (for layer caching). But the root package.json defines a
"preinstall" lifecycle script (node preinstall.js) that pnpm runs at the
start of install -- before the source copy -- so the script file was absent
and install aborted:
. preinstall$ node preinstall.js
Error: Cannot find module '/usr/src/app/preinstall.js' (MODULE_NOT_FOUND)
ERROR: process "pnpm install --no-frozen-lockfile" did not complete
This surfaced once the .npmrc COPY fix (#6076) let the build advance past
the earlier COPY failure. preinstall.js is self-contained (it no-ops without
GITHUB_TOKEN and guards the AGENTS.md/CLAUDE.md symlink with existsSync), so
copying just the script into the early manifest layer is sufficient.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(build): declare postcss plugins in platform/app for Docker build
The shared root postcss.config.js (which platform/app re-exports) loads
postcss-import, postcss-preset-env, and cssnano, but none were declared in
platform/app or the root. They only reached node_modules by being hoisted
from platform/docs (postcss-import, postcss-preset-env) and transitively
(cssnano). The Docker image excludes platform/docs via .dockerignore and
libs/@cornerstonejs is not a workspace member, so under pnpm's stricter
node-linker=hoisted the app build failed to resolve the plugins:
Loading PostCSS "postcss-preset-env" plugin failed:
Cannot find module 'postcss-preset-env'
(The accompanying "Can't resolve assets/woff2/latin.woff2" error was a
cascade from the broken PostCSS chain and clears with this fix.)
Declare the three plugins the config explicitly loads as devDependencies of
platform/app, pinned to the versions already resolved by working builds
(postcss-import@14.1.0, postcss-preset-env@7.8.3, cssnano@5.1.15), so the
build no longer depends on incidental hoisting from docs.
The lockfile was regenerated against a workspace:* baseline so the only
@ohif change is none -- the diff adds just the postcss plugin trees, keeping
specifiers at workspace:* per the repo's convention. Verified by building the
full Docker image locally: rspack compiles with 0 errors and the image
exports successfully.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>