|
FhSim
3.1.0
Marine systems simulation
|
Findings from code review that await an owner decision or an implementation. Each issue is one file in issues/details/, which holds the evidence, the effect, the possible fix, the test that would prove it and the risk. Resolved issues are kept in issues/resolved/ so that their numbers are never reused. Issues that concern a SimObject are also shown on that model's documentation page. Audit notes that are not issues are in issues/notes.md.
file:line given in the detail file, at HEAD.blocked item, get the owner's answer to "Decision needed" first, then set Status to ready.git mv the file to issues/resolved/, add a **Resolved:** <commit>, <date> paragraph after the table, delete the matching \xrefitem reviewissue "Review issues" "Review issues" \ref fhsim_fishery_issue_<ID> lines from the headers, rerun the script and commit it all together.New issue: --new <slug> "<title>", or add issues/details/<slug>.md with the metadata table but no ID row; the script assigns the next free number, writes the heading and renames the file to <TAG>-<ID>-<slug>.md.
BUG code does something other than its documentation or sibling code saysKNOWN-LIMITATION behaviour gap by design or omission, document rather than fix silentlyARCHITECTURE structure, dependencies, build layout, dead code and stale artefactsDOCUMENTATION missing or wrong documentation or exampleTEST test coverage or infrastructureAPI public name (port, state, parameter, registration string) whose change breaks input filesSECURITY credentials and supply chain3 wrong numbers, a crash or a secret exposure reaches a user2 a documented interface does not work as documented1 tidiness, readers and tools onlyblocked needs the owner decision named in the fileready fully specified| ID | Class | Severity | Status | |—|—|—|—|
pending, 2026-09-17. File: resolved/FISH-0001-test-suite-has-no-tests.mdresolved/FISH-0002-seineconnector-pos-vel-opposite-connected-sense.mdpending, 2026-09-17. File: resolved/FISH-0003-crowfoot-externalvel-always-zero.mdpending, 2026-09-25. File: resolved/FISH-0004-trawldooraddedfoil-discards-foil-force.mdpending, 2026-09-25. File: resolved/FISH-0005-trawldooraddedfoil-foilenergyconsumed-always-zero.mdpending, 2026-09-25. File: resolved/FISH-0006-trawldooraddedfoil-polar-interpolation-length.md82c8f64, 2026-09-15. File: resolved/FISH-0007-trawldooraddedfoil-documented-input-ports.md82c8f64, 2026-09-15. File: resolved/FISH-0008-trawldooraddedfoil-header-example-uses-a-wrong.md09db4fa, 2026-09-15. File: resolved/FISH-0009-examples-input-valuesdisplay-xml-references.md81fc225, 2026-09-15. File: resolved/FISH-0010-valuesdisplay-documents-numsignals-and-a-single.mdpending, 2026-09-17. File: resolved/FISH-0011-seineoperation-minwarplength-overwritten.mdpending, 2026-09-25. File: resolved/FISH-0012-seineoperation-hardcoded-haul-speed.mdpending, 2026-09-25. File: resolved/FISH-0013-remove-netwithattractor-sources.mdpending, 2026-09-25. File: resolved/FISH-0014-crowfoot-numlines-validation.md65e4104, 2026-09-15. File: resolved/FISH-0015-totrawldoors-roll-pitch-and-angleofattack-output.mdcca19cd, 2026-09-15. File: resolved/FISH-0016-crowfoot-and-trawldooraddedfoil-leak-their-heap.mdresolved/FISH-0017-no-seine-example-input.mdpending, 2026-09-25. File: resolved/FISH-0018-example-xml-door-output-nondeterministic.mdEnvironment/Basic from base, which no 3.x library registers. Resolved: pending, 2026-09-17. File: resolved/FISH-0019-trawl-examples-reference-environment-basic.md55db44d, 2026-09-15. File: resolved/FISH-0020-valuesdisplay-deletes-uninitialized-pointer.mdpending, 2026-09-17. File: resolved/FISH-0021-pidcontroller-out-uninitialised-before-first-step.mdpending, 2026-09-17. File: resolved/FISH-0022-trawldoor-angleofattack-reverse-flow-branch.mdcc0d115, 2026-09-21. File: resolved/FISH-0023-centerweight-drag-ignores-current.mdpending, 2026-09-17. File: resolved/FISH-0024-seineoperation-buoypos-read-before-written.mdpending, 2026-09-17. File: resolved/FISH-0025-seineoperation-warplength-not-a-state.mdresolved/FISH-0026-actuator-power-uninitialised-until-first-odefcn.mdpending, 2026-09-25. File: resolved/FISH-0027-outport-backing-members-uninitialised-at-tstart.mdbase SimObject library, which the package does not depend on. Resolved: pending, 2026-09-25. File: resolved/FISH-0028-fhsim-base-not-a-dependency.mdpending, 2026-09-17. File: resolved/FISH-0029-angleofattack-sampled-from-last-odefcn-evaluation.mdpending, 2026-09-24. File: resolved/FISH-0030-centerweight-regression-baseline-stale.md39a45c4, 2026-09-24. File: resolved/FISH-0031-developing-md-toutput-example-is-a-three-time-list.mdpending, 2026-09-24. File: resolved/FISH-0032-jacobian-callbacks-indexed-with-global-state-offsets.mdpending, 2026-09-25. File: resolved/FISH-0033-auv-thrust-is-independent-of-speed.mdpending, 2026-09-25. File: resolved/FISH-0034-auv-cross-flow-damping-has-no-speed-coupling.md1322f17, 2026-09-24. File: resolved/FISH-0035-pid-error-sign.mdpending, 2026-09-24. File: resolved/FISH-0036-environment-randomseed-defaults-to-wall-clock.mdpending, 2026-09-25. File: resolved/FISH-0037-undulation-vertical-speed-falls-short-of-the-dive-angle.md722fcfa; confirmed 2026-09-24. File: resolved/FISH-0038-auv-outports-crash-during-initial-condition-setup.mdpending, 2026-09-25. File: resolved/FISH-0039-echosounder-altitude-is-the-beam-projection-on-a-slope.mdresolved/FISH-0040-echosounder-up-beam-last-bin-samples-above-the-surface.mdpending, 2026-09-25. File: resolved/FISH-0041-render-teardown-runs-after-ogre-is-gone.mdpending, 2026-09-25. File: resolved/FISH-0042-auv-survey-mackerel-ambient-masks-calanus-at-38khz.mdpending, 2026-09-25. File: resolved/FISH-0043-fmu-scenario-xml-is-never-parsed.mdresolved/FISH-0044-auv-fmu-autocopy-does-not-bundle-the-ocean-fields.mdpending, 2026-09-25. File: resolved/FISH-0045-tovessel-no-test-coverage.mdresolved/FISH-0046-trawldooraddedfoil-valuesdisplay-no-test.mdresolved/FISH-0047-trawldoorbase-jacobian-unverified.mdresolved/FISH-0048-regression-tests-lack-closed-form-assertions.mdresolved/FISH-0049-auv-fmu-exports-no-validity-flags.mdresolved/FISH-0050-echosounder-echogram-truncated-by-every-model-build.mdresolved/FISH-0051-environment-null-during-initial-condition-setup.mdpending, 2026-09-25. File: resolved/FISH-0052-review-issues-script-package-from-directory.mdresolved/FISH-0053-sensor-notes-say-fhsim-base-is-outside-the-closure.mdresolved/FISH-0054-seineoperation-phase-durations-swapped.mdpending, 2026-09-25. File: resolved/FISH-0055-interp1d-picks-the-wrong-segment.mdresolved/FISH-0056-trawldooraddedfoil-uses-stale-inflow.mdresolved/FISH-0057-auvsurvey-cod-field-domain-ends-below-the-echosounder-beams.mdresolved/FISH-0058-internalcablewithattractor-addelementforce-hides-base.mdresolved/FISH-0059-trawlvessel-warpposprt-default-on-starboard.mdf4090d17, contained in fhsim 3.3.1 (tag v3.3.1), the FhSim this package requires (fhsim/[^3.3.1]) and the build resolves (fhsim/3.3.1@sintef/stable). The comments in SensorCtd.cpp and SensorCtd.h now say that LagT and LagS open at the field values. Test SimObject.Auv_CtdDefaultLagOpensAtTheFieldValues (fixture tests/in/Auv/Auv_CtdDefaultLag_in.xml: default time constants, the sensor at 30 m, 8.975 degC and 34.34 PSU there) passes; with the environment left unresolved in InitialConditionSetup (the behaviour before FHSIM-0025, reproduced by commenting out its ResolveEnvironment) it fails with LagT_0, LagS_0, Temperature_0 and Salinity_0 all 0 at t = 0. No baseline moves (Auv_CtdStatic has zero time constants, Auv_CtdRamp a zero field at the start).. File: resolved/FISH-0060-ctd-lag-states-open-at-zero.mdresolved/FISH-0061-readme-skip-tests-conf-name.mdresolved/FISH-0062-valuesdisplay-examples-fail-headless.mdresolved/FISH-0063-auv-fmu-bundles-a-leftover-echogram.md3e73dff, 2026-10-02 (owner ruling R131: a down beam that ends on the bottom keeps its samples RayTolerance (vertical, BottomClearance) short of the hit, SensorEchosounder::DownSampleRangeOf; test SimObject.SensorEchosounder_TheDownBeamSamplesStayRayToleranceAboveTheSeabedHit_FISH0064 did not compile before (no such functions), green after; the Echosounder, Auv, Ctd and SilCam tests (135) pass with no echogram baseline moved. The rough-seabed case, where the search returns the crossing nearest its start rather than the first along the beam, is split off as FISH-0099 (blocked)). File: resolved/FISH-0064-echosounder-down-beam-last-bin-samples-below-the-seabed.mdresolved/FISH-0065-trawlvessel-and-seine-cable-leak-their-heap.mdresolved/FISH-0066-seineoperation-renderupdate-uninitialised-textrenderer.mdresolved/FISH-0067-vessel-default-mesh-not-shipped.mdresolved/FISH-0068-default-vessel-mesh-flattened-above-water.mdresolved/FISH-0069-trawldoor-default-mesh-not-found.mdresolved/FISH-0070-shared-conan-generators-folder.mdresolved/FISH-0071-traaldoer-example-scale-oversized.mdresolved/FISH-0072-auv-header-doc-slips.mdSeineOperation.h now says isosceles triangle with apex angle α, sin(α/2) = (L2/2)/L1, L2 = L/(1 + 1/sin(α/2)), L1 = L2/(2 sin(α/2)); the stale commented-out formula in SeineOperation.cpp is deleted. doc/images/SeineOperation.jpg shows a general isosceles triangle with α at the apex, which agrees. Documentation only: no test, no baseline moves.. File: resolved/FISH-0073-seine-operation-leg-length-derivation.mdPhase_NotSet and Phase_SetFirstLeg). CalcOutput tests PhaseAt(dT) (FISH-0104) against Phase_NotSet || Phase_SetFirstLeg. Test SimObject.SeineOperation_NetSpeedsAreZeroBeforeTheNetIsSet runs SeineOperation_in.xml for 40 s with Fileoutput and reads the file: before the fix the 20 Not set rows had a normal speed of 0.5; after it every Not set and Setting first leg row is 0 and every later row 0.5 (normal) and 0 (tangential). No baseline moves (the regression output has no net speeds).. File: resolved/FISH-0074-seine-operation-duplicate-phase-test.mdresolved/FISH-0075-testing-report-needs-gui-stale.mdresolved/FISH-0076-trawl-example-slips.mdresolved/FISH-0077-trawl-description-placeholders.mddata/ still reference Environment/Basic, which no 3.x library registers. Resolved: commit "Resolve FISH-0078: port the data/trawl inputs to FhSim 3", 2026-10-06 (owner ruling 2026-10-06: port them as FISH-0019; TrawlPrepare.xml drops InitialStatesFile and starts from its initial conditions). All 11 files: the Environment block of fhsim_environment (Waves.NumWaves 0, Bathymetry.Depth = the old MeanDepth, Current.Model Constant with the vector the Environment.CurrentVel connection set, which is deleted); unknown <Integrator> attributes LogStates/UseRSSNorm removed. Also: Trawl/Crowfoot DampingRatio/EigenFrequency/IntegratorGain, Cable/LumpedMass Length, ValuesDisplay DisplayBox/Material, Src/Sine TrigoFunc and the net's Scale="1" (all unread) removed; apspeed corrected to ApSpeed (case-sensitive; the value was ignored); LibName="marine" → "fishery" in TrawlMovie.xml; FoilControl.xml connects the now-required Door.FoilRelativeAoaRate to 0. TrawlMovie.xml runs 600–730 s (FhSim 3 starts at the time stored in the states file; camera times shifted by 600 s) and resumes from TrawlPrepareStates1.txt, which TrawlPrepare.xml writes in the working directory; a comment says so. Verified headless (playpen bin as working directory, scratch copies with a short TEnd): flume, flume3, FoilControl, Trawl, TrawlSimple, TrawlPrepare run 5 s and exit 0 without NaN, and TrawlMovie resumes from TrawlPrepare's states and runs on; only visual parameters stay unqueried (meshes, scales, vessel MeshName/*Scale/Pitch, ValuesDisplay FilterFrames, camera settings). Not runnable: TrawlDoorControl, TrawlDoorControl2, TrawlDoorControlMovie and flume2 use Trawl/TrawlDoorWarpControl, which no library or branch has (FISH-0013); a header comment in each says so. With Trawl/TrawlDoor substituted (and its WarpControl* parameters, ControlLine1Length inputs and WarpPosLocal initial conditions removed) each ran 3 s cleanly, so the rest of these files is ported. TrawlDoorControl2.xml still reads states.txt (written by TrawlDoorControl.xml) and TrawlDoorControlMovie.xml its own moviestates.txt; left as they were.. File: resolved/FISH-0078-data-inputs-reference-environment-basic.mdresolved/FISH-0079-steady-tow-trawl-scenario.mdresolved/FISH-0080-morenot520-net-acceleration-limit.mdresolved/FISH-0081-validation-tests-run-by-default.mdRho). TrawlDoorBase::AddInternalForces uses m_rhoWater * wet; the header's Buoyancy section says Rho. Test SimObject.TrawlDoorBase_BuoyancyUsesRho (fixture TrawlDoorBase_FreeDoorRho998_in.xml, the free door with Rho and Density 998): before, the door rose (LocalVel_2 = -0.0265 m/s after 0.1 s); after, it stays at rest (|LocalVel| < 1e-6). At the default 1025 the result is identical: SimObject.TrawlDoorBase and every other door test pass against their unchanged references. The CenterWeight part was resolved earlier in cbdf038 (FISH-0102).. File: resolved/FISH-0082-trawl-door-buoyancy-and-centerweight-hard-code-1025.mdresolved/FISH-0083-seine-cable-general-fluidrho-unused.mdresolved/FISH-0084-steady-tow-header-names-a-missing-ctest-entry.mdresolved/FISH-0085-steady-tow-rig-files-copied-at-configure-only.mdab508bb ("Cable/Branched: no analytical Jacobian while in bottom contact (FISH-0086)"; no separate MARE issue, this issue is its record). Owner ruling 2026-10-06: R41's gate extends to both. CenterWeight::HasJacobians is false while the seafloor force was non-zero at the last OdeFcn state; CableBranched::HasJacobians while any node (sphere) or element (cylinder, InternalCableWithBottomContact) got a seafloor force there. MARE-0135 / review F1: the SUNDIALS Jacobian callback calls OdeJacobian (which differences the blocks without an analytical Jacobian) even when a model withdraws its claim during the run: FHSIM-0030, fhsim e8f634d6, merged in 94fd477f, in fhsim 3.3.1 (FhIntegratorSundials.cpp:396-403 at v3.3.1), which both packages require. Tests: fishery SimObject.CenterWeight_NoJacobianInBottomContact (the CenterWeight case checked to TEnd = 10 s, on the 55 m seafloor) failed before with the system check at t = 10.01 s (maxRelErr 1.03, the missing contact stiffness) and passes after, the weight's block still checked in mid-water; ME SimObject.CableBranched_NoJacobianWithANodeInBottomContact and ..._WithAnElementInBottomContact failed before (CB block maxRelErr 1.0 to 1.9) and pass after; CableBranched_JacobianClearOfTheSeabed keeps the CB block. No baseline moves.. File: resolved/FISH-0086-centerweight-jacobian-omits-bottom-contact.mdresolved/FISH-0087-seine-cable-duplicate-reads-and-state-base.mdresolved/FISH-0088-version-3-4-0-against-input-and-behaviour-break.mdresolved/FISH-0089-steady-tow-wall-clock-budget-tight.mdresolved/FISH-0090-trawl-door-inertia-fixed-5000.mdresolved/FISH-0091-trawl-door-damping-on-absolute-velocity.mdresolved/FISH-0092-trawl-door-submergence-against-mean-surface.mdresolved/FISH-0093-trawl-door-missing-rigid-body-omega-terms.mdresolved/FISH-0094-steady-tow-ends-on-path-chosen-cycle.mdresolved/FISH-0095-auv-closed-loop-envelopes-after-omega-terms.mdresolved/FISH-0096-added-mass-omega-terms-use-body-velocity-in-current.mdresolved/FISH-0097-trawldoor-trim-fixture-unstable-equilibrium.mdresolved/FISH-0098-internalcablewithattractor-netbin-force-unscoped-and-hardcoded-density.mddd0e186, 2026-10-02 (owner ruling R132: the bottom hit is the first seabed crossing along the beam; fixed in the ray search, marenv MENV-0062 (BathymetryField::ComputeRayIntersection marches from the origin), and fhsim_environment (ParametricBathymetry and NetCdfSeafloorBathymetry use it); test SimObject.Auv_EchoRidge_TheDownBeamReportsTheFirstSeabedCrossing_FISH0099 (a Parametric ridge between the transducer and the flat-seabed estimate) red before (141.42 m, the crossing at the estimate, against 62.95 m), green after; the fishery suite passes 196/196 with every Echosounder, Auv and AuvSurvey test unchanged; marenv 8b699a1 311/311, fhsim_environment c87a89a 265/265 (its test ParametricBathymetry.RayIntersectionIsTheFirstCrossingAlongTheRay_MENV0062 red before, 141.42 m, green after)). File: resolved/FISH-0099-echosounder-bottom-hit-nearest-crossing.md3956d22, 2026-10-02 (owner ruling R133: a transducer at or inside the seabed reads a valid 0 m, MeasureBottom accepts range >= 0; RayStepSize below RayTolerance and a non-finite RayStepSize or RayTolerance are parameter errors (SensorEchosounder::IsValidRaySearch), the cost ~ altitude / (RayStepSize cos(tilt)) is documented; test SimObject.Auv_EchoOnBottom_ATransducerAtOrInsideTheSeabedReadsAValidZero_FISH0100 red before (with marenv MENV-0063: Valid 0 for the transducer 5 mm above the seabed), green after; SimObject.SensorEchosounder_TheRaySearchSettingsMustBeFiniteWithAStepNotBelowTheTolerance_FISH0100 did not compile before (no IsValidRaySearch), green after; the fishery suite passes 198/198 with every Echosounder, Auv and AuvSurvey test unchanged). File: resolved/FISH-0100-echosounder-on-the-bottom-reads-lost.mda63adb2, 2026-10-02 (SensorEchosounder::IsValidMaxRange (positive and finite) replaces <= 0 for both ranges; test SimObject.SensorEchosounder_TheMaxRangesMustBeFiniteAndPositive_FISH0101: the predicate refuses 0, negative, NaN and infinity, and the fixture Auv_EchoZeroRange stops the model with an error that names MaxRangeUp; the FISH-0100 test now checks that its error names RayStepSize; the predicate test did not compile before; the parameter reader already rejects inf, nan, 1e999 and 1/0, so a model file cannot reach the non-finite case and the check is defensive, only its sign test can fire today, and it runs in the creator constructor only (gate review of batch P0); 199/199 fishery tests pass). File: resolved/FISH-0101-echosounder-max-range-not-checked-for-finite.mdcbdf038, 2026-10-04 (the drag and its Jacobian are environment::sphere_hydro::DragForce and DragJacobian; new parameters Rho (default 1025) and DragCoefficient (default 1.2); with CastWake the weight casts through an environment::wake::BodyWake and a sphere_hydro::SphereCaster, and it reads its water velocity through BodyWake::WaterVelocity. Tests CenterWeight.RhoAndDragCoefficientSetTheDragAndTheBuoyancy, CenterWeight.WithoutCastWakeTheWeightCastsNothingAndReadsTheEnvironmentsFlow and CenterWeight.UpstreamWeightsWakeSlowsTheDownstreamWeight; before the change they did not compile (no waterVelocity, no CastWake). SimObject.CenterWeight's output equals CenterWeight_ref.csv at every printed digit: no baseline moves. 202/202 fishery tests pass.). File: resolved/FISH-0102-centerweight-casts-no-wake.mdTrawlDoorControlledLiftAndMass (src/trawl/TrawlDoorControlledLiftAndMass.{h,cpp}) is TrawlDoorControlledLift with WeightModel::Mass: parameters MassMin (positive) and MassMax in place of WeightMin, WeightMax and WeightcontrolPID; input MassGoal in place of BottomForceGoal; state Mass (default (MassMin + MassMax) / 2) in place of IntegratedBottomforceError, d(mass)/dt = clamp(MassGoal, MassMin, MassMax) − mass, used as the inertia; weight 9.81 × 0.87 × mass. Registered once, as Trawl/TrawlDoorControlledLiftAndMass. The lift, drag, seafloor and spread logic, with the 3.x fixes of TrawlDoorControlledLift, are shared. Test SimObject.TrawlDoorControlledLiftAndMass_MassFollowsTheGoal (fixture tests/in/TrawlDoorControlledLiftAndMass/): MassGoal 15000 kg from 12500 kg, and 30000 kg bounded to 20000 kg; the mass is goal + (12500 − goal) e^(−t) and the weight 9.81 × 0.87 × mass at every output time. Before the port the model did not exist; the TrawlDoorControlledLift tests pass unchanged.. File: resolved/FISH-0103-trawl-door-controlled-lift-and-mass-not-ported.mdVel/Heading at (T, X) wherever they use them; Seine/Operation::PhaseAt(T) is a pure function of time used by every port; BuoyPos is latched in PreOdeFcn (the vessel position at the start of the last step that starts in Phase_NotSet; PreOdeFcn follows a port reset, AcceptedStep does not); an attractor gives its motion at the reader's (T, X) (AttractorBase::MotionAt, from Seine/Vessel's states and speed command and Seine/Operation's strength ramp), which Seine/Cable takes in OdeFcn and its port calculation (fhsim_marine_elements CableBranched::PrepareSections); Seine/Cable also applies its Length inputs in OdeFcn (as MARE-0037). Tests SeineCallOrder.* (tests/SeineCallOrder_Test.cpp): all five failed before the fix (vessel Vel 5 instead of 2; VesselSpeed at 5 s gave 4 instead of 2; BuoyPos (7, 8) instead of (1, 2); cable derivatives changed after a port read and after a vessel port read at another state) and pass after it. The SeineOperation and SeineCable baselines moved (commit "Baselines for FISH-0104 (SeineOperation, SeineCable)"): the vessel from the Phase_SetFirstLeg start at 10 s (position RMS 8.6e-2 m in SeineOperation, 1.5e-3 m in SeineCable); the Seine/Cable warp tensions from t = 1 s (a few percent before 10 s, up to 1.3 kN of 4.6 kN at 12 s, within 0.2 % at 60 s; Tension1 RMS 228 N), as the cable now applies its Length inputs in OdeFcn and sees the vessel's command of its own stage.. File: resolved/FISH-0104-seine-vessel-port-values-depend-on-call-order.mdCalcPosForTwoStretched removes the force direction's component along the line between the fastening points. CrowfootMath.TwoTautLinesMeetOnTheirCircle_FISH0105 is green (red at af6d6ed); the Crowfoot baseline holds; Trawl/TrawlDoorWarpControl (8aaf758) relies on it (SimObject.TrawlDoorWarpControl_ControlLineTensionBalancesTheWarp).. File: resolved/FISH-0105-crowfoot-two-lines-off-their-circle.mdPos1 and Vel1 are the door's WarpPos; the warp force acts at the collecting point solved at (T, X); new output CollectingPoint. SimObject.TrawlDoorWarpControl_SlackWarpEndStaysAtWarpPos_FISH0106 is green (red at 46e0833: Pos1 1.0 m off WarpPos). In TrawlDoorControl.xml (200 s, after 60 s) a slack control line gives the Trawl/TrawlDoor warp tension (mean 68 kN, max 102 kN) and no collecting-point jumps.. File: resolved/FISH-0106-warp-control-collecting-point-flips.mdm_outNetWidth holds one value per net; SimObject.TrawlGeometryController_NetWidthsAreSeparate_FISH0107 is green (red at 3b91f75: Net1Width read 30 m after Net2Width). Warp<N>Length and MinBottomContact were checked and are not affected.. File: resolved/FISH-0107-geometry-controller-net-width-shared.md