Skip to content

Release v1.13.0 — Immunopeptidomics Measurements & Story Tracking Structure#1457

Merged
sven1103 merged 19 commits into
mainfrom
release/v1.13.0
Jun 16, 2026
Merged

Release v1.13.0 — Immunopeptidomics Measurements & Story Tracking Structure#1457
sven1103 merged 19 commits into
mainfrom
release/v1.13.0

Conversation

@sven1103-agent

Copy link
Copy Markdown
Collaborator

Release Summary — v1.13.0

Feature: FEAT-IMMUNOPEPTIDOMICS-MEASUREMENT


What's included

All changes on development since the last release on main18 commits — spanning two delivery streams:

1. Immunopeptidomics Measurement Lifecycle (FEAT-IP-MEAS)

Full feature for managing immunopeptidomics measurements, covering all 5 stories:

Story ID Description PRs
Registration FEAT-IP-MEAS-01 Excel template upload with validation, IP- prefixed codes #1413, #1428
Editing FEAT-IP-MEAS-02 Pre-filled template, editable/read-only field handling, ACL-gated #1414, #1429
Deletion FEAT-IP-MEAS-03 Management-rights-gated deletion, dataset guard, OpenBIS sync #1415, #1430
View Measurements FEAT-IP-MEAS-04 Dedicated tab with 18+ domain columns, search/filter, count #1417, #1431
View Raw Datasets FEAT-IP-MEAS-05 Dedicated raw data tab, metadata display, filtering #1416, #1432

Bugfixes included: null-safety guard in update path, measurement code lookup fix, ACL-projectId fix, missing domain tag in Project Summary view.

OpenBIS integration: New dedicated object type for immunopeptidomics measurements (LAB-C-01 constraint — coordinated with lab integration team).

2. Story Tracking Structure (#1452)

Stable tracking of user stories with IDs, lifecycle workflow, and stakeholder-facing documentation:

  • Story ID Schema: FEAT-<SLUG>-<NN> (e.g., FEAT-IP-MEAS-01)
  • Story Lifecycle: Draft → Approved → Implement (tracked in docs/features.md and GitHub)
  • docs/features.md rewritten with full story content, acceptance criteria, status tracking
  • AGENTS.md updated with Story ID Schema, Story Lifecycle, and Creating Stories guidance

PRs included

PR Title Merged
#1433 docs: add immunopeptidomics measurement requirements to PRD and registry 2026-05-06
#1435 [Task] Registration of Immunopeptidomics Measurements (#1413) 2026-05-15
#1436 Add immunopeptidomics measurement metadata specification 2026-05-11
#1442 Story #1428: Register Immunopeptidomics Measurements via Excel Template 2026-05-15
#1443 Story #1429: Edit Immunopeptidomics Measurements via Pre-filled Excel Template 2026-06-09
#1447 Fixes #1430: Implement deletion guard and OpenBIS sync for Immunopeptidomics measurements 2026-06-10
#1450 Story #1432: Implement Immunopeptidomics raw datasets view 2026-06-12
#1451 fix: Add Immunopeptidomics domain tag to Project Summary view 2026-06-15
#1452 Story tracking structure: stable IDs, workflow, and features.md rewrite 2026-06-16

Changes

File Change
docs/features.md Rewritten: Story ID schema, story content, acceptance criteria, status tracking
AGENTS.md New Story ID Schema, Story Lifecycle, Creating Stories sections

Notes


Release checklist

  • Review release overview for accuracy
  • Confirm OpenBIS object type is available in target environment
  • Approve and merge to main
  • Tag and publish per create-release.yml workflow (auto-generates GitHub release changelog from PR titles)

sven1103 and others added 19 commits May 6, 2026 16:08
…try (#1433)

* docs: add immunopeptidomics measurement requirements to PRD and registry

- Update PRD §1 and §3 to include immunopeptidomics in measurement scope
- Add MEASUREMENT-R-01 through R-04 for registration, editing, deletion, and viewing
- Add DATA-R-01 through R-03 for raw dataset view, upload, and download

Refs: #1412

* docs: add Features and User Stories Tracker

Adds docs/features.md as the stakeholder-visible companion to the PRD,
tracking active Features, their Stories, and their live GitHub status.

Includes FEAT-IMMUNOPEPTIDOMICS-MEASUREMENT as the first tracked feature
with all 5 Stories, 5 implementation Tasks, and 1 integration-test Task.

Refs: #1412

---------

Co-authored-by: sven1103-agent <261423644+sven1103-agent@users.noreply.github.com>
Adds the stakeholder-provided Excel template and a diffable README
manifest to docs/stakeholder-artifacts/measurement-metadata/.

- immunopeptidomics-registration-spec-v1.0-2026-05-11.xlsx:
  Authoritative stakeholder artifact with 'Metadata' and 'Property
  information' sheets defining all 22 registration fields (14 mandatory,
  8 optional), their allowed values, and descriptions.

- README.md:
  Diffable manifest reproducing the 'Property information' sheet verbatim,
  sorted by provision (mandatory first) then alphabetically by column
  header. Includes traceability links to MEASUREMENT-R-01, MEASUREMENT-R-02,
  FEAT-IMMUNOPEPTIDOMICS-MEASUREMENT, and GitHub Stories #1428/#1429.

Refs: MEASUREMENT-R-01, MEASUREMENT-R-02
Related: #1428, #1429, #1413, #1414
Adds the stakeholder-provided Excel template and a diffable README
manifest to docs/stakeholder-artifacts/measurement-metadata/.

- immunopeptidomics-registration-spec-v1.0-2026-05-11.xlsx:
  Authoritative stakeholder artifact with 'Metadata' and 'Property
  information' sheets defining all 22 registration fields (14 mandatory,
  8 optional), their allowed values, and descriptions.

- README.md:
  Diffable manifest reproducing the 'Property information' sheet verbatim,
  sorted by provision (mandatory first) then alphabetically by column
  header. Includes traceability links to MEASUREMENT-R-01, MEASUREMENT-R-02,
  FEAT-IMMUNOPEPTIDOMICS-MEASUREMENT, and GitHub Stories #1428/#1429.

Refs: MEASUREMENT-R-01, MEASUREMENT-R-02
Related: #1428, #1429, #1413, #1414
* feat: register immunopeptidomics measurements via Excel template (#1413)

Implements the registration of immunopeptidomics measurements following the
existing NGS/proteomics parallel-stack pattern.

Domain:
- Add IP to MeasurementCode.MEASUREMENT_PREFIX
- Create ImmunopeptidomicsMeasurement aggregate
- Create IPMeasurementEntry embeddable metadata
- Create IPMethodMetadata record

Repository & OpenBIS:
- Add ImmunopeptidomicsMeasurementJpaRepo
- Extend MeasurementRepository with IP methods
- Extend MeasurementDataRepo and OpenbisConnector with Q_IP_MEASUREMENT
- Add IP support to MeasurementRepositoryImplementation

Application:
- Add MeasurementRegistrationInformationIP / MeasurementSpecificIP to AsyncProjectService
- Add registerMeasurementIP and toDomain conversion to MeasurementService
- Add MeasurementIPValidator with mandatory field checks
- Wire IP validation into MeasurementValidationService

UI & Parsing:
- Add IMMUNOPEPTIDOMICS to MeasurementType
- Add IPMeasurementRegisterColumn enum matching template fields
- Add MeasurementRegistrationMetadataConverterIP
- Add MeasurementRegistrationProcessorIP for pool merging
- Register IP converter and processor
- Add Immunopeptidomics template to MeasurementTemplateSelectionComponent
- Wire IP submit flow in MeasurementMain and MeasurementUpload

Infrastructure:
- Add IpRegisterFactory and IPWorkbooks for template generation
- Add immunopeptidomics_measurement_registration_sheet.xlsx template

SQL:
- Extend project_measurements view with amountIpMeasurements
- Extend project_overview view with amountIpMeasurements

Refs: #1413, #1428

* fix(schema): add missing ip_measurements and specific_measurement_metadata_ip tables

Adds the required base tables for immunopeptidomics measurements:
- ip_measurements: aggregate table for IP measurement entities
- specific_measurement_metadata_ip: collection table for sample-specific
  IP metadata entries per measurement

Refs: #1413

* refactor(ip): move all measurement fields to measurement level, simplify specific metadata

For immunopeptidomics there is no per-sample metadata beyond the sample ID
itself. All template fields are measurement-level (shared across all samples
in a pool).

Changes:
- IPMethodMetadata: expanded to carry all measurement-level fields
- ImmunopeptidomicsMeasurement: constructor now sets all fields from method
- IPMeasurementEntry: simplified to just measuredSample (SampleId)
- specific_measurement_metadata_ip table: reduced to measurement_id + sample_id
- MeasurementService.toDomain: extracts measurement-level fields from the
  first MeasurementSpecificIP entry, creates simplified IPMeasurementEntry
  instances with only sample IDs

Refs: #1413

* Add amountIpMeasurements to project_overview and project_measurements SQL views

* fix: remove asterisk suffix from IP measurement column headers

The IPMeasurementRegisterColumn enum in datamanager-app contained
asterisk (*) suffixes in header names (e.g. 'QBiC Sample Id*').
This caused a mismatch with:

- The template generator in project-management-infrastructure,
  which uses plain headers without *
- The file parser's Sanitizer.headerEncoder(), which strips *
- The validator's IP_PROPERTY labels, which also use plain names

Because the parsed columnMap contained keys without * but the
converter searched for keys with *, every lookup missed and
returned empty strings. The validator then correctly reported
all mandatory fields as missing even when they were provided.

This fix removes the * suffixes from all 14 affected headers,
aligning them with the template generator, parser, and validator.

Closes #1413

* fix: add missing columns to ip_measurements DDL

The ImmunopeptidomicsMeasurement JPA entity defines six fields that
were not present in the ip_measurements CREATE TABLE statement:

- sampleMass (double)
- sampleVolume (double)
- cycleFractionName (varchar)
- prepDate (date)
- msRunDate (date)
- comment (varchar)

Without these columns, Hibernate fails with SQLGrammarException
'Unknown column im1_0.comment in SELECT' (and similar for the
other columns) when persisting or loading immunopeptidomics
measurements.

This fix aligns the DDL with the JPA entity so that measurement
registration works end-to-end.

Related to #1413

* Add immunopeptidomics measurement lookup and UI tab

- Create IpMeasurementLookup API interface with MeasurementInfo, SampleInfo,
  Instrument, Organisation, IpSortKey, and MeasurementFilter
- Create IpMeasurementJpaRepository with read-only JPA entities
  IpMeasurementInformation and IpSampleInfo, plus IpMeasurementFilter
- Extend MeasurementLookup to implement IpMeasurementLookup
- Extend MeasurementLookupService to count IP measurements and find by ID
- Add deleteIpMeasurements to MeasurementService
- Extend MeasurementDetailsComponent with Immunopeptidomics tab:
  grid, search, pooled sample dialog, delete, registration events
- Wire IpMeasurementLookup and IP event handlers in MeasurementMain

This makes IP- prefixed measurement codes user-facing and closes the gap
between registration and display for immunopeptidomics measurements.

* refactor(ip): align Excel column order with stakeholder spec and fix missing mandatory validations

Aligns the immunopeptidomics measurement registration template column order
with the authoritative stakeholder specification
(docs/stakeholder-artifacts/measurement-metadata/README.md):

- Reorder all 22 fields to match stakeholder positions exactly
  (e.g., Cycle/Fraction Name at 3, Sample Mass at 4, Facility at 10,
   Organisation URL at 11, Data Acquisition at 13, Charge range at 17,
   Mass range at 19, Retention time range at 20)

- Add missing mandatory validations for Sample Mass and Sample Volume in
  MeasurementIPValidator (application layer) and
  ImmunopeptidomicsMeasurement.evaluateMandatoryMetadata (domain layer)

- Add missing mandatory validation for Retention time range in domain model

- Update tests to match new column order and expected failure counts

Refs: MEASUREMENT-R-01, #1413, #1428

* feat(ip): align template descriptions with stakeholder spec and add template tests

Updates the immunopeptidomics measurement registration template to use
descriptions and example values that match the authoritative stakeholder
specification exactly (docs/stakeholder-artifacts/measurement-metadata/README.md).

Changes:
- Fix instrument CURIE example from EFO:0008633 to EFO:0008637 in both enums
- Update all 22 column descriptions to match stakeholder spec verbatim
- Keep asterisks on mandatory headers (intentional UX choice)
- Ensure both IPMeasurementRegisterColumn enums (infrastructure + datamanager-app)
  remain identical to prevent template/parser drift

New tests:
- IpRegisterFactorySpec (7 tests): validates column order, mandatory flags,
  example values, descriptions, and header names against the spec
- IPMeasurementRegisterColumnSyncSpec (1 test): uses reflection to assert
  both enum copies are in sync (headerName, index, mandatory, readOnly,
  exampleValue, description)

Refs: MEASUREMENT-R-01, #1413, #1428

* fix(ip): shorten sheet name and description to fit Excel/POI limits

Fixes two runtime issues when downloading the immunopeptidomics registration
template from the UI:

1. Crash: description exceeds POI's 255-char limit
   The SAMPLE_NAME column description was 261 characters, causing
   XSSFDataValidation.createPromptBox() to throw IllegalStateException.
   Truncated to 254 characters in both enum copies while preserving meaning.

2. Warning: sheet name exceeds Excel's 31-char limit
   Changed sheet name from "Immunopeptidomics Measurement Metadata" (38 chars)
   to "IP Measurement Metadata" (23 chars) to avoid POI silently trimming it.

New tests:
- IPMeasurementRegisterColumnDescriptionLengthSpec in both modules:
  asserts every column description is <= 255 chars, preventing future crashes
  if descriptions are updated from the stakeholder spec.

Refs: MEASUREMENT-R-01, #1413, #1428

* feat(ip): add all available columns to the immunopeptidomics measurement grid

Adds the 3 missing columns that were available in the backend lookup DTO
but not shown in the UI grid:

- MHC Typing Method
- Retention Time Range
- Ion Mobility Range

Backend changes:
- Added sort keys MHC_TYPING_METHOD, RETENTION_TIME_RANGE, ION_MOBILITY_RANGE
  to IpSortKey enum for server-side sorting
- Added the 3 fields to the global search term filter so they are searchable

UI changes:
- Added the 3 columns to createIpGrid() in MeasurementDetailsComponent
- Columns are sortable, auto-width, and resizable (matching existing columns)

The FilterGrid component already provides a Show/Hide Columns menu via
CheckboxGroup<Column<T>>, so users can toggle visibility of any column.

Refs: MEASUREMENT-R-01, #1413, #1428

* fix(ip): handle Excel numeric cell formatting in retention time parsing

When a user enters a whole number like '120' in the Excel template for
'Retention time range (min)', Excel stores it as a numeric cell. The
XLSXParser reads numeric cells via Double.toString(), producing '120.0'.

The existing parseIntegerOrNull() helper only used Integer.parseInt(),
which throws NumberFormatException on '120.0', causing the value to
become null. The domain model then rejected it as 'Missing metadata'.

Fix: parseIntegerOrNull() now falls back to Double.parseDouble() when
Integer.parseInt() fails, accepting the value only if it represents a
whole number (e.g. '120.0' -> 120). True decimals like '120.5' are
still rejected (return null).

New test: MeasurementServiceIntegerParsingSpec validates that:
- plain integers parse correctly ('120' -> 120)
- Excel numeric formatting parses correctly ('120.0' -> 120)
- true decimals are rejected ('120.5' -> null)
- blank and non-numeric inputs return null

Refs: MEASUREMENT-R-01, #1413, #1428

* fix(ip): add IP measurement lookup in UpdateProjectUponMeasurementCreation

The background job 'Update project upon creation of measurement' was
failing with 'Measurement not found' for all immunopeptidomics (IP)
measurements because the handler only looked up NGS and Proteomics
(PxP) measurements, never checking the IP repository.

This was not a race condition. The event dispatch happens after the JPA
transaction commits, so the measurement is in the DB when the JobRunr
job runs. The issue was simply a missing lookup branch.

Changes:
- UpdateProjectUponMeasurementCreation.updateProjectModified() now
  also queries measurementLookupService.findIPMeasurementById() when
  both NGS and Proteomics lookups return empty.
- Added Spock spec with 4 tests covering NGS, Proteomics, IP, and
  'not found' paths.

Refs: MEASUREMENT-R-01, #1413, #1428

* fix(ip): address reviewer findings for immunopeptidomics measurement registration

- Add TEAL tag color for immunopeptidomics to distinguish from proteomics
- Expose missing measurement-level fields in lookup/grid: prepDate, msRunDate,
  cycleFractionName, sampleMass, sampleVolume
- Fix validator message format and add missing validations:
  * facility check, negative value checks for sampleMass/sampleVolume/retentionTimeRange
  * date format checks for prepDate/msRunDate (YYYY-MM-DD)
  * range format checks for massRange/chargeRange/ionMobilityRange
- Add Spock tests for new validation rules
- Implement export template backend pipeline for IP measurements:
  * MeasurementInformationIP/CollectionIP/SpecificIP records in TemplateProvider
  * IPMeasurementEditColumn enum and IpEditFactory for workbook generation
  * TemplateProviderOpenXML handling, TemplateService query+convert logic
  * AsyncProjectService measurementUpdateIP endpoint
- Wire export button in UI: IpMeasurementExportRequested event, listener,
  and downloadIPMetadata handler in MeasurementMain

Edit functionality intentionally out of scope (separate user story).

* fix(ip): handle Excel numeric cell formatting in retention time validation

Excel numeric cells are parsed as doubles (e.g. 90 -> "90.0"), which
caused Integer.parseInt to throw NumberFormatException. Use the same
Double.parseDouble + whole-number check pattern already employed by
MeasurementService.parseIntegerOrNull().
…r-immunopeptidomics-measurements-via-excel-template

[Story] Register Immunopeptidomics Measurements via Excel Template (#1428)
…pre-filled Excel template

Implements IP measurement editing following the same parallel-stack pattern
used by NGS and Proteomics edit flows (Story #1429, Task #1414).

## Domain & Application Layer

- AsyncProjectService: Added MeasurementUpdateInformationIP record with
  measurementId, organisationId, instrumentCURIE, facility, samplePoolGroup,
  specificMetadata (MeasurementSpecificIP), and measurementName. Extended
  MeasurementUpdateRequestBody and ValidationRequestBody sealed interfaces.
- MeasurementService: Added updateMeasurementIP(), performUpdateIP(),
  toDomainUpdate() for ImmunopeptidomicsMeasurement updates with proper
  validation (missing ID, unknown measurement, org/instrument lookup).
- MeasurementIPValidator: Added validateUpdate() with ValidationPolicy
  inner class validating measurementId, organisation, instrument, and all
  mandatory IP fields (sampleMass, sampleVolume, MHC antibody, etc.).
- MeasurementValidationService: Added validateIP() overload for
  MeasurementUpdateInformationIP updates.
- AsyncProjectServiceImpl: Wired IP update case in updateMeasurement()
  and validateRequest() switches; added updateMeasurementIP() and
  validateMeasurementMetadataIPUpdate() helpers.

## UI Layer

- IPMeasurementEditColumn: New column enum mirroring infrastructure enum,
  with 25 columns (Measurement ID, QBiC Sample Id, Sample Name, etc.)
- MeasurementUpdateMetadataConverterIP: New converter parsing Excel rows
  into MeasurementUpdateInformationIP, only mapping editable columns.
- MeasurementUpdateProcessorIP: New processor grouping by measurementId
  and merging pooled IP measurements.
- ConverterRegistry / ProcessorRegistry: Registered new IP update classes.
- MeasurementUpload: Added case for MeasurementUpdateInformationIP.
- MeasurementDetailsComponent: Added IpMeasurementEditRequested event
  with addIpEditListener(), plus Edit button on IP grid.
- MeasurementMain: Added ipEditDialog() wired to addIpEditListener(),
  extended UpdateRequestPackage with IP support.

## Tests

All tests pass (160 project-management, 29 datamanager-app).

Requirement IDs: MEASUREMENT-R-02
…validator

The validateMeasurementCode method in MeasurementIPValidator was calling
measurementService.findIPMeasurementById(null, measurementCode), which
triggered IllegalArgumentException: identifier required in Spring Security
ACL's ObjectIdentityImpl because null projectId is not a valid ACL object
identity.

Fix: accept ProjectId parameter and pass projectId.value() to the lookup.
The projectId was already available at the validateUpdate call site.

All tests pass (160 project-management, 29 datamanager-app).
…lidator

MeasurementIPValidator.validateMeasurementCode was calling
findIPMeasurementById(projectId.value(), measurementCode), which parses
the input as a MeasurementId (internal UUID). However, the Excel template's
'Measurement ID' column contains the human-readable measurement CODE
(e.g. IP-001), not the internal UUID. MeasurementId.parse('IP-001') throws
IllegalArgumentException, which was caught silently, returning Optional.empty()
and causing valid measurements to be reported as 'Unknown measurement'.

Fix:
- Add findIPMeasurement(String) to MeasurementService and MeasurementLookupService
- Update validateMeasurementCode to use findIPMeasurement(measurementCode)
- Remove unnecessary ProjectId parameter from validateMeasurementCode

This follows the exact same pattern used by NGS (findNGSMeasurement)
and PxP (findProteomicsMeasurement) validators.

All tests pass (160 project-management, 29 datamanager-app).
Prevent NoSuchElementException when specificMetadata is empty by adding
an explicit null/empty check before iterator().next().

All tests pass (160 project-management, 29 datamanager-app).
Add 6 tests covering the IP measurement update validation path:
- Happy path: valid update returns successful result
- Blank measurement ID: returns failure
- Unknown measurement code: returns failure
- Missing mandatory fields: returns failures
- Unknown instrument: returns instrument failure
- Invalid ROR organisation: returns ROR format failure

All 21 tests pass (15 existing registration + 6 new update).
- Add comment field to edit template export data model (MeasurementInformationIP record)
- Add instrumentName field to update/registration data flow (MeasurementUpdateInformationIP and MeasurementRegistrationInformationIP records)
- Add date validation to update flow for prepDate and msRunDate
- Remove duplicate validation error messages for instrument, measurement ID, and organisation
- Fix capitalization inconsistency in error message ('Measurement ID' vs 'Measurement id')
- Update processor classes to include instrumentName parameter
- Update test specifications to reflect new record structures

Addresses bugs:
1. Missing comment field in edit template export
2. Instrument name not persisted (stored as empty string)
3. Missing date validation in update flow
4. Duplicate validation error for instrument
5. Duplicate validation error for measurementId
6. Instrument name in exported sheet
7. Comment in exported sheet
…munopeptidomics-measurements-via-pre-filled-excel-template

feat: edit immunopeptidomics measurements via pre-filled Excel template
…idomics measurements (#1447)

* Fixes #1430: Implement deletion guard and OpenBIS sync for Immunopeptidomics measurements

* Fix compilation error: Correctly implement deleteAllIP with overloaded private method

* Fix: Add deleteImmunopeptidomicsMeasurements to MockConnector

* Fix: Add deletion success notification with count for all measurement types (Addresses AC)
* Story #1432: Implement Immunopeptidomics raw datasets view

- Add LocalRawDatasetIpEntry and LocalRawDatasetIpJpaRepository
- Extend LocalRawDatasetRepository and LocalRawDatasetLookupService with IP methods
- Add RawDatasetInformationIp record and API methods in AsyncProjectService/Impl
- Update RawDataDetailsComponent to include IP tab with filtering, grids, and export
- Extend RemoteRawDataService.hasRawData() to check for IP measurements
- Optimize v_ip_measurement_sample_json view to use ip_measurement_sample_summary table
- Add sql/seed_ip_measurement_sample_summary.sql for one-time historical data migration
- Update LocalRawDatasetCache to automatically sync the summary table on new data

* refactor: remove materialized ip_measurement_sample_summary table, switch to correlated subquery view

The materialized table was introduced as a performance optimization but had
an inconsistency bug — deletions from ip_measurements were never reflected
in the summary. Since IP has a 1:1 sample-to-measurement relationship,
correlated subqueries (same pattern as NGS and PxP views) are performant.

- Drop ip_measurement_sample_summary table
- Rewrite v_ip_measurement_sample_json as a pure view with correlated
  subqueries (matching v_ngs_measurement_sample_json / v_pxp_measurement_sample_json)
- Remove LocalRawDatasetCache.updateIpSummary() — no longer needed
- Delete seed_ip_measurement_sample_summary.sql

Additionally ensure FK and index exist on specific_measurement_metadata_ip
to enable eq_ref joins (matching NGS/PxP query plan).

* refactor: remove unnecessary composite indexes on specific_measurement_metadata_ip

The composite index (measurement_id, sample_id) is not needed — the
query plan uses measurement_id for the indexed lookup and the sample_id
index (with FK) provides eq_ref joins.

* refactor: remove unnecessary composite indexes on NGS and PxP specific measurement tables

The composite indexes (measurement_id, sample_id) are not needed — the
query plan uses the single-column measurement_id index for the correlated
subquery lookup.

* chore: add sample_id index and FK on NGS specific_measurement_metadata table

NGS was missing both the sample_id index and the FK constraint to the
sample table. This patch adds them for consistency with PxP and IP,
ensuring FK insert/update performance and optimizer trust for joins.

* docs: add migration guide for materialized table removal and index optimization

Closes the gap where SQL schema changes had no deploy instructions for
existing production databases. The migration document covers:

- Dropping ip_measurement_sample_summary (was inconsistent on delete)
- Recreating v_ip_measurement_sample_json as a pure view with
  correlated subqueries (same pattern as NGS/PxP)
- Removing 3 unused composite indexes
- Adding sample_id indexes to all 3 specific_measurement_metadata tables
- Adding missing FK constraint on NGS table

Includes pre-flight checks, step-by-step SQL, verification queries,
and rollback plan.

---------

Co-authored-by: Sven Fillinger <sven.fillinger@qbic.uni-tuebingen.de>
* fix: Add Immunopeptidomics domain tag to Project Summary view

- Add GOLD color to TagColor enum (#FFF3CC fill, #A68500 text per Figma)
- Add .tag.gold CSS rule in span.css
- Fix ProjectSummaryComponent.buildTags() to include IP measurements
- Update ProjectCollectionComponent to use GOLD instead of TEAL
- Update TagFactory to use goldTag() for immunopeptidomics

* chore: Remove .run/ directory from tracking
#1452)

- Rewrite docs/features.md: story ID schema (FEAT-<SLUG>-<NN>),
  full story content with narrative and acceptance criteria,
  task section removed (tasks are GitHub-only)
- Update AGENTS.md: Story ID Schema section, Story Lifecycle
  workflow, Creating Stories section, Key Files Quick Reference
- Migrate FEAT-IP-MEAS-01 through FEAT-IP-MEAS-05 with complete
  story content from existing GitHub issues #1428-#1432

Co-authored-by: Sven Fillinger <sven.fillinger@qbic.uni-tuebingen.de>
@sven1103-agent sven1103-agent requested a review from a team as a code owner June 16, 2026 08:08
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)
19.5% Duplication on New Code (required ≤ 3%)
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@sven1103 sven1103 merged commit 894f7f2 into main Jun 16, 2026
11 of 12 checks passed
@sven1103 sven1103 deleted the release/v1.13.0 branch June 16, 2026 08:23
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.

[Story] FEAT-IP-MEAS-03 Delete Immunopeptidomics Measurements

2 participants