Scope
Implement Part 4, Phase 5 (Calibration UI) as specified in Design-RemainingAndEw.md.
Stop at Phase 5. Phases 0–4 already shipped and are validated — build on them, do not rework them.
Do NOT modify the validated low-level SCSI path (TapeDriveWin32Backend.lto-direct.cs).
Step 0 — Review and improve the design FIRST (do this before coding)
Read Design-RemainingAndEw.md fully: Phase 5 plus Parts 1–4 for context. Then cross-check
every Phase 5 assumption against the ACTUAL code before implementing — the same "As-built
notes / critical review" discipline every earlier phase followed. Specifically verify:
- The service operation pattern:
ServiceOperationRequest → operation → ServiceOperationResult
and ServiceOperationProgressHandler (as used by Backup / Restore / List).
WpfServiceHost progress plumbing (the Backup/Restore Update…Progress methods).
- The MainWindow operation overlay (percent bar, phase text, Abort button).
DeleteBackupSetsWindow (pattern for the confirm/warning dialog).
IoRateSparklineControl (basis for the curve graph).
TapeCalibrator, TapeCalibration, TapeCalibrationStore, AppSettings.Calibrations.
Where the spec diverges from reality, correct it in code and record the divergence in the PR
description as an "As-built notes" section.
Step 1 — Calibration service (TapeLibNET.Services)
New file TapeServiceBase.EW.cs. Mirror the existing operation triad:
ExecuteCalibrateAsync(...) → ExecuteCalibrateCore(), with optional media eject at the end.
- Reuse
ServiceOperationProgressHandler so progress plugs into the existing MainWindow overlay,
and reuse the established cooperative Abort path bound to TapeCalibrator.IsAbortRequested.
- Bridge the semantic gap: Backup/Restore/List operate on FILES; Calibrate operates on CHUNKS.
The Calibrate flavor of the operation classes/records maps chunks → files. Calibrate needs NO
agent (no TOC involved).
- Backend-agnostic — drive only the public
TapeDrive / TapeCalibrator surface.
Step 2 — WPF UI (TapeWinNET)
- CalibrateWindow — confirm/warning dialog patterned after
DeleteBackupSetsWindow:
explicit destructive-operation warning (scratch cartridge required), profile summary
(vendor / product / revision / capacity bucket), and a confirm gate.
- Progress — reuse the MainWindow operation overlay. Add
UpdateCalibrateProgress() to
WpfServiceHost, patterned after the Backup/Restore versions: percent bar,
bytes-written / estimated-capacity, current phase (writing to EOM, capturing EW, finalizing),
and an Abort button.
- CalibrationWindow (result) — show measured
CapacityActual, the EW landmark, and
EwToEomDistance; offer Save Profile (into TapeCalibrationStore via
AppSettings.Calibrations) and immediate Apply Profile (via AddCalibration).
Also emit a result summary to the log pane, consistent with the Backup/Restore summaries.
- Curve graph (bonus, implement it) — a simple 2D plot of Reported → Actual remaining, with
EW and EOM points marked. Reuse IoRateSparklineControl; lift shared drawing into a common
base class if that simplifies both. Flip the X-axis (full capacity left → EOM right).
PROPOSE AND IMPLEMENT a solution to magnify the small-but-critical EW→EOM tail region
(e.g. a piecewise / non-linear X-axis or a split axis) — document your choice.
- MVVM — a
CalibrationViewModel owns the run on a background thread, marshaling
progress/log to the UI via the established dispatch helpers; reuse WarningLevel/LogEntry
styling for status.
Constraints & conventions
- Solution must build; ALL existing TapeLibNET / FclNET tests stay green. Add tests where the
established pattern allows (service-layer calibrate operation especially).
- Follow the codebase's existing formatting conventions — preserve blank-line usage and
comment placement; match surrounding style, do not reformat untouched code.
- Keep changes surgical and confined to Phase 5. Open a DRAFT pull request.
Acceptance
User can run, monitor, abort, and save a calibration entirely from the GUI; a saved profile
immediately improves the remaining-capacity figure for matching media (per the Phase 5
acceptance criteria in the design doc).
Scope
Implement Part 4, Phase 5 (Calibration UI) as specified in
Design-RemainingAndEw.md.Stop at Phase 5. Phases 0–4 already shipped and are validated — build on them, do not rework them.
Do NOT modify the validated low-level SCSI path (
TapeDriveWin32Backend.lto-direct.cs).Step 0 — Review and improve the design FIRST (do this before coding)
Read
Design-RemainingAndEw.mdfully: Phase 5 plus Parts 1–4 for context. Then cross-checkevery Phase 5 assumption against the ACTUAL code before implementing — the same "As-built
notes / critical review" discipline every earlier phase followed. Specifically verify:
ServiceOperationRequest→ operation →ServiceOperationResultand
ServiceOperationProgressHandler(as used by Backup / Restore / List).WpfServiceHostprogress plumbing (the Backup/RestoreUpdate…Progressmethods).DeleteBackupSetsWindow(pattern for the confirm/warning dialog).IoRateSparklineControl(basis for the curve graph).TapeCalibrator,TapeCalibration,TapeCalibrationStore,AppSettings.Calibrations.Where the spec diverges from reality, correct it in code and record the divergence in the PR
description as an "As-built notes" section.
Step 1 — Calibration service (TapeLibNET.Services)
New file
TapeServiceBase.EW.cs. Mirror the existing operation triad:ExecuteCalibrateAsync(...)→ExecuteCalibrateCore(), with optional media eject at the end.ServiceOperationProgressHandlerso progress plugs into the existing MainWindow overlay,and reuse the established cooperative Abort path bound to
TapeCalibrator.IsAbortRequested.The Calibrate flavor of the operation classes/records maps chunks → files. Calibrate needs NO
agent (no TOC involved).
TapeDrive/TapeCalibratorsurface.Step 2 — WPF UI (TapeWinNET)
DeleteBackupSetsWindow:explicit destructive-operation warning (scratch cartridge required), profile summary
(vendor / product / revision / capacity bucket), and a confirm gate.
UpdateCalibrateProgress()toWpfServiceHost, patterned after the Backup/Restore versions: percent bar,bytes-written / estimated-capacity, current phase (writing to EOM, capturing EW, finalizing),
and an Abort button.
CapacityActual, the EW landmark, andEwToEomDistance; offer Save Profile (intoTapeCalibrationStoreviaAppSettings.Calibrations) and immediate Apply Profile (viaAddCalibration).Also emit a result summary to the log pane, consistent with the Backup/Restore summaries.
EW and EOM points marked. Reuse
IoRateSparklineControl; lift shared drawing into a commonbase class if that simplifies both. Flip the X-axis (full capacity left → EOM right).
PROPOSE AND IMPLEMENT a solution to magnify the small-but-critical EW→EOM tail region
(e.g. a piecewise / non-linear X-axis or a split axis) — document your choice.
CalibrationViewModelowns the run on a background thread, marshalingprogress/log to the UI via the established dispatch helpers; reuse
WarningLevel/LogEntrystyling for status.
Constraints & conventions
established pattern allows (service-layer calibrate operation especially).
comment placement; match surrounding style, do not reformat untouched code.
Acceptance
User can run, monitor, abort, and save a calibration entirely from the GUI; a saved profile
immediately improves the remaining-capacity figure for matching media (per the Phase 5
acceptance criteria in the design doc).