From 5b072c0e35f49e34106052e646ea100647162cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E8=96=84=E4=BA=91?= Date: Fri, 31 Jul 2026 16:05:21 +0800 Subject: [PATCH] docs: gate Local G2 pipeline on stable region order --- .../2026-07-30-local-g2-path-presmoothing.md | 69 +++++++++++++++++-- 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/docs/superpowers/plans/2026-07-30-local-g2-path-presmoothing.md b/docs/superpowers/plans/2026-07-30-local-g2-path-presmoothing.md index 3e4fbd4..3a6f98b 100644 --- a/docs/superpowers/plans/2026-07-30-local-g2-path-presmoothing.md +++ b/docs/superpowers/plans/2026-07-30-local-g2-path-presmoothing.md @@ -1189,6 +1189,7 @@ git commit -m "feat: validate local G2 candidate quality" **Files:** - Create: `ClumsyPilot/ParkrobTrajplanner/PathSmoothing/LocalG2/LocalG2PreSmoothingPipeline.cs` +- Consume unchanged: `ClumsyPilot/ParkrobTrajplanner/PathSmoothing/LocalG2/LocalG2RegionWorkOrder.cs` - Modify: `ClumsyPilot/ParkrobTrajplanner/PathSmoothing/Facade/PathSmoothingService.cs` - Create: `ClumsyPilot/tests/verify_path_smoothing_local_g2_integration.ps1` - Modify: `ClumsyPilot/tests/verify_path_smoothing_service.ps1` @@ -1196,6 +1197,8 @@ git commit -m "feat: validate local G2 candidate quality" **Interfaces:** - Consumes: validated request, prepared path and fair raw baseline. +- Consumes `LocalG2RegionWorkOrder.TryCreate(...)`; pipeline iteration must not use report-order regions directly. +- Publishes region reports in the detector's original ascending order, independently of processing order. - Produces: ```csharp @@ -1242,6 +1245,21 @@ Assert-True ($result.Diagnostics.Metrics.MinimumBodyClearanceMeters -ge 0.02) ` For `Complete` and `PartialImprovement`, require at least one region report with `Improved`. For `PartialImprovement`, require at least one `RetainedOriginal`. Run every fixture twice and compare status, point count, coordinates and region reports. +Create one deterministic same-direction fixture with two disjoint detected +regions. Both accepted candidates must change their local replacement length. +Assert: + +1. the larger-original-arc region is evaluated first; +2. the second processed region still matches the intended original front + window endpoints; +3. both reports are `Improved`; +4. reports are published in ascending original arc order; +5. both Local G2 replacements are present in the final full path; +6. two identical requests produce equal status, candidate indices, report + order, point count and point coordinates. + +The test must fail if the pipeline replaces `workRegions` with `regions`. + Also create two explicit service cases: ```powershell @@ -1273,31 +1291,68 @@ Expected: fail because the service cannot resolve `LocalG2Quintic`. Pipeline pseudocode must be implemented directly: ```csharp +if (!_workOrder.TryCreate( + regions, + out IReadOnlyList workRegions, + out string orderReason)) +{ + return PathSmoothingResult.Failure( + PathSmoothingStatus.Failed, + new PathSmoothingDiagnostics( + new PathQualityMetrics(), + TimeSpan.Zero, + 0, + 0d, + orderReason)); +} + PreparedPath current = preparedPath; -var reports = new List(); +var reportsByRegion = new Dictionary(); int improvedCount = 0; -foreach (LocalG2SmoothingRegion region in regions) +foreach (LocalG2SmoothingRegion region in workRegions) { cancellationToken.ThrowIfCancellationRequested(); IReadOnlyList candidates = - _builder.Build(preparedPath.Segments[region.SegmentIndex], region, outputSpacing, options, cancellationToken); + _builder.Build( + preparedPath.Segments[region.SegmentIndex], + region, + outputSpacing, + options, + cancellationToken); var evaluations = new List(); foreach (LocalG2CandidateGeometry candidate in candidates) - evaluations.Add(_evaluator.Evaluate(preparedPath, current, region, candidate, request, options, cancellationToken)); + { + evaluations.Add( + _evaluator.Evaluate( + preparedPath, + current, + region, + candidate, + request, + options, + cancellationToken)); + } - LocalG2CandidateEvaluation best = LocalG2CandidateEvaluator.SelectBest(evaluations); + LocalG2CandidateEvaluation best = + LocalG2CandidateEvaluator.SelectBest(evaluations); if (best != null && best.Accepted) { current = best.SplicedPreparedPath; improvedCount++; - reports.Add(CreateImprovedReport(region, best)); + reportsByRegion.Add(region, CreateImprovedReport(region, best)); } else { - reports.Add(CreateRetainedReport(region, evaluations)); + reportsByRegion.Add( + region, + CreateRetainedReport(region, evaluations)); } } + +var reports = new List(regions.Count); +for (int reportIndex = 0; reportIndex < regions.Count; reportIndex++) + reports.Add(reportsByRegion[regions[reportIndex]]); ``` Regions are disjoint after merging, so successful earlier replacements remain when a later region fails.