調査日: 2026-08-18 / 調査範囲: Issue #69本体、Track #70〜#88(全Issue本文+全コメント)、親Issue #60、
docs/standards/*、docs/specifications/p6-ui-spec.md、docs/runbooks/navigation-*.md、
apps/android-tablet/track-core・pc-tool・simulator-ui(TypeScript)の該当コード。
本報告は調査のみであり、コード・ドキュメント・Issue・Track Ledgerへの変更、B-2g/B-2hの着手、
work_publishはいずれも行っていない。
仕様から乖離している。 乖離は Track #87/#88 で初めて発生したのではなく、Track #78(境界B-2d 重ね幅solver 初版)と Track #81(境界B-2e 中央候補列生成 初版)の時点で、既に「値の接続」が失われた状態で実装が始まっている。 Track #87/#88 はこの空白の上に WorkArea 内部順序探索を積み増しただけであり、Track #88 最終コメント(#4920)でようやく問題が言語化・可視化された「発覚点」にすぎない。
根拠を要約する。
requiredParity(列数偶奇)は Track #78 の関数シグネチャ設計の時点から一貫して外部入力である(FieldPlanningGeometry.centerTillageOverlapAdjustment(..., requiredParity: OverlapParity)、FieldPlanningGeometry.kt:747)。KDoc自身が「後続工程(始終端拘束)が決める入力」(:730)と書いており、B-2dの設計段階で「幾何から導出する」実装を先送りしたまま、その先送り先(B-2h)が現在も未実装である。finishingSide(LateralSpanSide MIN/MAX)は Track #81 の初版から「呼び出し側が明示する(入口や頂点順から推測しない)」設計(FieldPlanningGeometry.kt:1235)。これも同じ構造の空白。finishingLap3StartAnchorという契約用語自体は Track #72(Issue #69 comment #4730)で確定したが、対応する値・関数・フィールドはコード中に一度も実装されていない(grep全文検索でKDoc内の未来形言及以外に実体なし)。EntranceSnapshot/resolveEntrance()/centerTillageOrientation()(peelPosition・deferredTargets)は、それぞれ Track #70/#71 で実装されているが、本番の呼び出し経路(FieldPlanPreviewService、FieldPlanWorkAreaService)から一度も呼ばれていないことを直接grepで確認した(定義行以外にヒットなし)。TillagePlan(最終計画。RouteAction列、CenterTillageDetourによる中断・復帰、退出等を含む)を実際に構築する本番コンポーザーが存在しない(コンストラクタ呼び出しはテストfixtureのみ)。つまりルール1・4・5・12・13(入口進入〜退出、追い詰め中断・復帰)は、契約書・fixture上には存在するが、コードとしては一度も統合されたことがない。requiredParity/finishingSideは simulator-ui の HTML <select>(index.html:298-306)から HTTP 経由で pc-tool → track-core へそのまま渡されている(直接grepで確認)。#87/#88だけの問題ではない。 #78(B-2d)・#81(B-2e)という、より上流かつ承認済みbaselineとされてきたTrackの設計段階から、上位規則(入口・仕上げ終点からの逆算)との接続が欠落していた。Track #72(境界B-2契約、baseline)自体も、Stage 7(重ね幅solver)・Stage 8/9(候補列生成)がStage 13(WorkArea全体同時評価、finishingLap3StartAnchorの逆算はここで初めて定義)より先に実行される構成になっており(8章のStage順序)、Stage 7/8/9が必要とする「requiredParity」「finishingSide」をどのStageがどう計算してStage 7/8/9へ渡すかを契約書自身が一度も明記していない。この意味で、乖離の一次原因は「Track #87/#88が独自に規則を破った」ことではなく、「境界Bを B-2a〜B-2l へ細分した契約(Track #72)が、値の受け渡し経路を規定しないまま各境界が個別にbaseline化されてしまった」という、より根の深いプロセス上の欠陥である。
requiredParityが幾何から導出されず外部入力になっているdocs/runbooks/navigation-field-geometry-pipeline-contract.md 11.3節「候補の優先順位」の第1位は「必要な偶奇(laneCountParity)を満たす」であり、これはfinishingLap3StartAnchorへの接続条件から導出される制約のはず(1.9節「2アンカーを固定して全体経路を探索する」)。docs/runbooks/navigation-tablet-preview-claude-implementation.md 4.4節は「終端拘束…を同時に満たす解を探索する」と明記し、9節「禁止事項」は「現在位置に最も近い端を開始点として、終点を偶奇任せにしない」を明示的に禁止している。FieldPlanningGeometry.centerTillageOverlapAdjustment(..., requiredParity: OverlapParity)(FieldPlanningGeometry.kt:747)。呼び出し元 FieldPlanPreviewService.kt:130がrequest.requiredParity(HTTPリクエストの生値)をそのまま渡す。simulator-ui main.ts:3071,3211が<select id="field-plan-required-parity">(index.html:298-299)の選択値を送信。テスト(FieldOverlapAdjustmentSolverTest.kt)もOverlapParity.EVEN/ODDをリテラル指定するのみ。FieldPlanningGeometry.kt:747,730(KDoc「必要な偶奇(requiredParity)は後続工程(始終端拘束)が決める入力」)、Issue #78 comment #4796、Issue #88 comment #4920(「requiredParityがsimulator-ui手入力(EVEN既定)」)。laneCount(項目8)、actualOverlapCm/actualPitchCm(項目9・10)、ひいては候補列全体の幾何。finishingSideが入口と無関係なUI手動入力になっているFieldPlanningGeometry.centerTillageCandidateLanes(..., finishingSide: LateralSpanSide, ...)(FieldPlanningGeometry.kt:1261)、KDoc「呼び出し側が明示する(入口や頂点順から推測しない)」(:1235)。simulator-ui <select id="field-plan-finishing-side">(index.html:305-306)から送信。FieldPlanningGeometry.kt:1235,1261,1474-1477、Issue #81 comment #4823(「呼び出し側が明示する(入口・頂点順から推測しない)」)、Issue #85 comment #4871(実装者自身が「finishing anchorは…完成済みの実走行経路・終点を意味しない」と説明)、Issue #88 comment #4919(「finishingSideはUI手動dropdown…既定値へ実質固定」)。finishingLap3StartAnchorがコード上に実在しないNavGeometryWarning.kt:169、CenterTillageSegmentOrderSearch.kt:165、CenterTillageWorkAreaOrder.kt:37、pc-tool FieldPlanWorkAreaJson.kt:23、TS workAreaPreview.ts:63のKDoc/コメント内に「未実装で将来必要になる接続先」として言及されるのみで、実体(型・関数・フィールド)は存在しない。EntranceSnapshot/resolveEntrance()/centerTillageOrientation()が本番経路から呼ばれていないEntranceSnapshot)を入力に持つ。resolveEntrance()(FieldPlanningGeometry.kt:338)、centerTillageOrientation()(:467)は共に定義行以外に呼び出しが1件もない(直接grep確認済み)。FieldPlanWorkAreaService.runが受け取るFieldPlanPreviewRequestはheadingDeg/implementWidthCm/overlapWidthCm/marginCm/maxOverlapAdjustmentCm/requiredParity/finishingSide/minSegmentLengthMのみで、入口や現在位置に相当する入力を一切持たない。FieldPlanWorkAreaService.kt:33-52。deferredTargets/peelPositionが計算されても下流消費者がゼロpeelPositionはローカル変数のみ(FieldPlanningGeometry.kt:531、同一関数内で破棄)。CenterTillageOrientation.deferredCornerIndicesはcenterTillageOrientation()の戻り値だが、この関数自体が未呼出のため、main配下での消費者はゼロ(テストのみが直接呼んでassertしている)。FieldPlanningGeometry.kt:531-534、grep確認(consumer検索でmain配下ヒットなし)。CenterTillageDetour)およびTillagePlan本体が本番未構築RouteActionRole.CenterTillageDetour(cornerIndex, purpose)(RouteAction.kt:65)、CornerTillStage(:39)としてTrack #70で型定義済み。RouteActionを生成する本番コードが存在しない。TillagePlan(のインスタンス化はテストfixture(TillagePlanFixtures.kt)のみ。TillagePlanComposer相当のコンポーネントが一度も実装されていない(pipeline-contract.md 16章のB-2j「全体composer」は依然未着手)。TillagePlan(のヒットは定義+テストのみ)。finishingLap3StartAnchorへの接続を要求。bestPathFromAnchorLane/bestPathBetweenAnchorLanes(CenterTillageSegmentOrderSearch.kt:133-196)はlateralAxis両端のlaneId文字列のみを受け取り、入口座標・進入方位・finishingLap3StartAnchorは一切引数に無い。呼び出し元centerTillageWorkAreaInternalPlanCandidates(FieldPlanningGeometry.kt:2044-2189)も、anchorLaneIdをworkArea.memberSegments内のlateralOffsetM最小/最大から機械的に選ぶのみで、どちらが入口に近いかを判定しない。CenterTillageSegmentOrderSearch.kt:74-75のKDoc(「lateralAxis上の両端のみを開始点候補にする」制約を意図的に満たさないsearchSegmentOrderの存在を含む)、Issue #72 comment #4728、Issue #87 comment #4904。MAX_EXHAUSTIVE_ORDER_SEGMENT_COUNT = 14(CenterTillageSegmentOrderSearch.kt:60)。実測デモfixturefixture:rectangle(25 segment)、fixture:multi-concave(63 segment)は共にこの閾値を超え、bestPathBetweenAnchorLanesはこの場合探索を放棄しnullを返す(:189)。bestPathFromAnchorLaneは貪欲法(最適性未保証)へfallback。CenterTillageSegmentOrderSearch.kt:44-59,60,141,189、Issue #87 comment #4905。WorkAreaInternalPlanCandidate(最大4件)を生成するのみで、selectedInternalPlan(最終選択)はnullのまま(CenterTillageWorkArea.ktKDoc「この段階ではWorkArea間のtransfer…は扱わない」)。simulator-uiは開始側/終端側をボタンで人間に選ばせる設計(workAreaPreview.ts:330-358)。FieldPlanningGeometry.kt:2044-2189、workAreaPreview.ts:330-358。headingDeg=0固定のまま候補列を生成していた欠落が発覚(Issue #69 comment #4873)。Track #86で修正されbaseline化。同種の「契約はあるが配線されていない」パターンが、この案件でTrack #86以前にも一度発生し修正された前例であり、B-2d/B-2eのrequiredParity/finishingSideも同型の欠落である可能性を示唆する。凡例: 「入力」=幾何から導出されず外部から渡される値。「計算値」=コードが導出する値。「未実装」=コード実体なし。
| 値 | 仕様上の決定根拠 | 本来のproducer | 現在のproducer | 現在のconsumer | 欠落・不整合 | 乖離が入ったTrack/境界 | 関連コード | 関連テスト | 必要な確認方法 |
|---|---|---|---|---|---|---|---|---|---|
EntranceSnapshot |
pc-closed-loop-implementation.md 3.1/3.4節 | 筆・入口選択責務(未実装のUI/plannerフロー) | 型定義のみ(EntranceSnapshot.kt:16-21)。近縁EntranceResolutionはresolveEntrance()が生成するが未呼出 |
TillagePlan.entrance(未構築のため実質consumer無し) |
本番producerが存在しない | Track #70(型定義)〜現在まで一度も配線されず | EntranceSnapshot.kt, FieldPlanningGeometry.kt:338-452 |
TillagePlanFixtures.kt(手書き)のみ |
grep -rn "resolveEntrance(\|EntranceSnapshot(" track-core/src/main pc-tool/src/mainで呼び出し元皆無を再確認 |
| approach heading | pc-closed-loop-implementation.md 3.4節 | 入口検出処理 | resolveEntrance(approachHeadingDeg: Double? = null)の呼び出し元供給パラメータ(FieldPlanningGeometry.kt:343) |
保持のみ(KDoc「周回方向の決定には使わない」) | 記録用途のみで計算に不使用、かつ関数自体未呼出 | Track #71 | EntranceResolution.kt:19-20 |
FieldPlanningGeometryTest.kt |
resolveEntranceの呼び出し元grep |
| 導入/仕上げ周回の方向(circulation) | p6-ui-spec.md 345-347行、pc-closed-loop 3.2節 | 入口・巻き方向から一般に導出すべき | explicitCirculationAtCornerという曖昧ケース限定の入力(FieldPlanningGeometry.kt:342,380-403) |
TillagePlanInvariants.validateCirculationConsistency(構築されたRouteAction列に対する事後検証のみ) |
一般的な周回方向の自動決定ロジックが存在しない | Track #71 | FieldPlanningGeometry.kt:380-403 |
FieldPlanningGeometryTest.kt(AmbiguousEntranceCorner系) |
同上 |
finishingLap3StartAnchor |
pipeline-contract.md 1.9節(Track #72 comment #4730で確定) | Stage 5/6相当(安全領域・span算出)で入口+field幾何から導出すべき | 未実装 | — | 契約用語のみでコード実体が皆無 | Track #72(契約確定)〜現在 | KDoc言及のみ: NavGeometryWarning.kt:169, CenterTillageSegmentOrderSearch.kt:165, CenterTillageWorkAreaOrder.kt:37 |
なし | grep -rn "finishingLap3StartAnchor" apps/android-tabletで実体なしを確認済み |
| 中央耕の理想終点 | pc-closed-loop 3.3節「理想終点を通る最後の隣接耕中心線をanchor」 | 同上 | 代替としてLateralSpanSide(MIN/MAX)という離散2値の外部入力が使われている |
centerTillageCandidateLanesImplのfinishing lane固定処理 |
実座標としての理想終点が存在せず、MIN/MAX二値で代用 | Track #81(初版から) | FieldPlanningGeometry.kt:1235,1481 |
CenterTillageCandidateLaneTest.kt |
上記grep + FieldPlanPreviewModels.ktの入力経路確認 |
finishingSide |
同上 | 入口から最も遠い側として自動導出すべき | 外部入力(LateralSpanSide)。pc-tool FieldPlanPreviewService.kt:140→simulator-ui <select id="field-plan-finishing-side">(index.html:305-306) |
centerTillageCandidateLanesImpl(lane offset計算、:1474-1477) |
入口非依存のUI手動選択 | Track #81(comment #4823「呼び出し側が明示する」) | FieldPlanningGeometry.kt:1261,1474-1477, main.ts:3072,3212 |
CenterTillageCandidateLaneTest.kt:113,128,144...(MAX固定リテラル) |
main.ts/FieldPlanPreviewModels.ktのHTTP入力経路を再確認 |
requiredParity |
pipeline-contract.md 11.3節 | finishingLap3StartAnchorへの接続条件から導出すべき |
外部入力(OverlapParity)。FieldPlanPreviewService.kt:130→<select id="field-plan-required-parity"> |
evaluatePitchの偶奇フィルタ(:1047) |
同上 | Track #78(comment #4796「指定偶奇」、初版から) | FieldPlanningGeometry.kt:747,730,1047, main.ts:3071,3211 |
FieldOverlapAdjustmentSolverTest.kt:36-49(EVEN/ODDリテラル) |
同上 |
laneCount |
上記から導出される列数 | evaluatePitch(B-2d) |
計算値(FieldPlanningGeometry.kt:1011-) |
lane生成ループ(:1393,1472)、validateCenterTillagePassContinuity |
計算自体は正しいが、入力requiredParityが既に汚染されている |
Track #78以降、requiredParity汚染を継承 | FieldPlanningGeometry.kt:948,926 |
FieldOverlapAdjustmentSolverTest.kt |
requiredParityが是正されれば自動的に是正される可能性 |
実際の重ね幅(actualOverlapCm) |
同上 | evaluatePitch |
計算値(:950,924) |
OverlapAdjustmentのinit検証 |
同上(入力汚染を継承) | 同上 | FieldOverlapAdjustmentSolverTest.kt |
同上 | |
実際のpitch(actualPitchCm) |
同上 | evaluatePitch |
計算値(:949,928) |
centerTillageCandidateLanesImplのoffset計算(:1471-1477) |
同上 | 同上 | 同上 | 同上 | |
| 最初の中央レーン/最後の中央レーン | pc-closed-loop 3.3節「終端をanchorし開始側へ逆算」 | 理想終点からの逆算 | 部分的に正しい: laneIndex=laneCount-1をfinishingSide境界へ固定しlaneIndex=0を逆算(FieldPlanningGeometry.kt:1472-1495)。ただしfinishingSide自体が外部入力 |
preview・後続segment生成 | 逆算の「方向」は正しいが、逆算の「起点」(finishingSide)が入口非依存の手入力 | Track #81 | FieldPlanningGeometry.kt:1472-1495 |
CenterTillageCandidateLaneTest.kt |
finishingSideの由来を追うのみで判定可能 |
peelPosition |
pipeline-contract.md 5.7節 | centerTillageOrientation() |
計算値だがローカル変数のみ(FieldPlanningGeometry.kt:531) |
同一関数内でのみ使用、直後破棄 | centerTillageOrientation()自体が未呼出のため実質死コード |
Track #71(実装)〜現在(未配線) | FieldPlanningGeometry.kt:531 |
直接テスト不可(内部変数) | centerTillageOrientation呼び出し元grep |
duringInitialLoopTargets |
pipeline-contract.md 5.7節 | 同上 | 同名識別子はコードに存在しない。近縁CornerTillStage.DURING_INITIAL_LOOP(enum) |
RouteActionRole.CornerTill.stage |
概念名がドキュメントとコードで一致していない、かつproducer不在 | Track #70(enum定義)〜現在 | RouteAction.kt:39,53 |
TillagePlanFixtures.kt(手書き) |
grepDURING_INITIAL_LOOPの生成箇所確認 |
deferredTargets |
pipeline-contract.md 5.7節 | 同上 | CenterTillageOrientation.deferredCornerIndices(FieldPlanningGeometry.kt:532-534) |
main配下consumer ゼロ(grep確認) | 計算されるが下流未使用 | Track #71(実装)〜現在(未配線) | CenterTillageOrientation.kt:16,21 |
FieldPlanningGeometryTest.kt |
consumer grep |
中断・追い詰め・帰還・再開pass(CenterTillageDetour) |
既決規則12・13 | TillagePlanComposer相当(未実装) |
本番producerなし | TillagePlanInvariants.validateCenterTillageInterruption(検証対象が本番未生成) |
Composer自体が存在しない | Track #70(型定義)〜現在(組み立て不在) | RouteAction.kt:42,65, TillagePlanInvariants.kt:203-259 |
TillagePlanFixtures.kt, TillagePlanInvariantsTest.kt |
grep "TillagePlan(" track-core/src/mainで定義+テスト以外ゼロを確認済み |
WorkArea(CenterTillageWorkArea) |
pipeline-contract.md 1章 | centerTillageWorkAreas() |
計算値(FieldPlanningGeometry.kt:1901-2032) |
centerTillageWorkAreaInternalPlanCandidates()、pc-tool GeoJSON、simulator-ui |
実装として妥当(入口非依存の安全接続グラフ問題として設計通り) | Track #87 | FieldPlanningGeometry.kt:1901-2032 |
CenterTillageWorkAreaTest.kt |
— |
WorkArea内部plan(internalPlanCandidates) |
pipeline-contract.md 1.5/1.6節 | finishingLap3StartAnchor拘束付き探索 |
計算値だが**lateralAxis両端のlaneIdのみを拘束**、入口・終端anchorの実座標は不知(CenterTillageSegmentOrderSearch.kt:133-196) |
pc-tool/simulator-ui(手動候補切替) | 「候補」止まりで最終選択(selectedInternalPlan)が未実装 | Track #87→#88(2件→4件) | FieldPlanningGeometry.kt:2044-2189, CenterTillageWorkAreaOrder.kt |
CenterTillageWorkAreaOrderTest.kt, CenterTillageSegmentOrderSearchTest.kt |
— |
| B-2h最終選択(WorkArea間transfer全体同時評価) | pipeline-contract.md 1.6/1.9節・3/4章 | Stage 13 | 未実装(型PerimeterConnectionCandidateすらコードに存在せず) |
UI手動選択(workAreaPreview.ts:330-358)に委ねられている |
未実装 | 未着手(B-2h) | CenterTillageWorkArea.kt:23(KDoc) |
workAreaPreview.test.ts |
— |
| Track | 判定 | 理由 |
|---|---|---|
| #70(境界A domain/fixture) | そのまま保持可能 | RouteActionRole/TillagePlan/TillagePlanInvariantsの型設計・invariantは既決規則を正しく反映している。未使用なのは「後続が接続していない」ためであり、型自体に問題はない。 |
| #71(境界B-1 FieldPlanningGeometry) | 技術部品のみ保持可能 | resolveEntrance/centerTillageOrientationの幾何ロジック自体は妥当そうだが、一度も本番から呼ばれておらず、出力(peelPosition/deferredCornerIndices)を後続へ渡す配線が存在しない。関数を保持しつつ、呼び出し経路の新設が必要。 |
| #72(境界B-2 契約, exploration) | 追加調査が必要 | 頂点分類・Coverage 3分離・安全性検証等の設計は妥当。一方で、WorkArea順序をHamiltonian/path-cover問題として定式化した設計(comment #4728)と、Stage 7/8/9(B-2d/B-2e)がStage 13より先に実行される8章のStage順序が、requiredParity/finishingSideの受け渡し経路を規定しないまま両立しており、これが後続全体の空白の温床になった。契約文書自体の再設計(誰がいつrequiredParity/finishingSideを計算するか)が利用者確認込みで必要。 |
| #73→#74(頂点分類) | そのまま保持可能 | 入口非依存の純粋な幾何処理として仕様通り。乖離の原因ではない。 |
| #75(安全領域・外周・中央領域) | そのまま保持可能 | 同上。tillageRegions(field, profile, marginCm)は設計上入口を必要としない前処理であり、これ自体は正しい。 |
| #76→#77(span算出) | そのまま保持可能 | 同上。 |
| #78→#79→#80(境界B-2d 重ね幅solver) | 技術部品のみ保持可能 | pitch探索アルゴリズム(overflow対策・優先順位ロジック)自体は健全。しかしrequiredParityを外部入力として設計した最初のTrackであり、この関数シグネチャ自体を「入口・finishingLap3StartAnchorから内部導出する」形へ作り替える必要がある。restart相当の変更が必要。 |
| #81→#82→#83→#84(境界B-2e 中央候補列) | 技術部品のみ保持可能 | polygon交差・region union等の幾何処理は健全(4回のレビューで堅牢化済み)。しかしfinishingSideを外部入力とした設計そのもの(comment #4823)を作り替える必要がある。 |
| #85(B-2e可視化) | そのまま保持可能 | camera fit等の可視化基盤に問題なし。ここで発見されたheadingDeg欠落(→Track #86)は正しく機能したレビューgateの実例。 |
| #86(境界B-1 restart, headingDeg決定契約) | そのまま保持可能 | 辺基準方向候補・自由回転の実装は利用者確定契約と一致し、目視レビューも通過済み。同種の欠落パターン(契約はあるが配線されない)を実際に見つけて直した唯一の成功例であり、B-2d/B-2eのrequiredParity/finishingSideもこの前例に倣って修正すべき。 |
| #87(境界B-2f 段階1〜4) | restartが必要(Track #88により既に着手されたrestartを継続) | 接続候補生成・安全判定・WorkAreaグルーピングの幾何ロジック自体は妥当。しかし入口・finishingLap3StartAnchorを一切受け取らない設計で内部順序探索を組んでおり、Track #88のrestartはこの空白を部分的にしか埋めていない。 |
| #88(境界B-2f restart) | 仕様上の意味を破棄して再利用を検討 / 追加調査が必要 | bestPathFromAnchorLane/bestPathBetweenAnchorLanes等のアルゴリズム部品(bitmask DP・貪欲fallback)は技術的に再利用できる。しかし「WorkArea内で複数候補を生成し人間に選ばせる」という設計方針自体は、本来finishingLap3StartAnchorから一意に近い解を導出できるはずの問題を、上流接続の欠落によって組合せ最適化問題へ格上げしてしまった結果である。上流接続が回復すれば、候補生成の枠組みは大幅に単純化できる可能性が高く、現行のUI(候補ボタン切替、免責文言)も再設計対象になりうる。outcome=needs-review継続は妥当。 |
幾何演算・UI基盤の保持可否と耕耘順序の意味の正しさは明確に分離する: #70/#73-77/#85/#86の幾何・UI・可視化部品は技術的に健全で保持できる。一方、#78/#81/#87/#88が実装した「値の受け渡し」は、たとえ各Trackのアルゴリズムが数学的に正しくとも、耕耘順序としての意味(入口・仕上げ周回との整合)を持たない状態で組み立てられている。
以下は現状のコードでは実現していない、あるべき順序である(現状の断絶点を明記する)。
EntranceSnapshot(入口ID・境界座標・進入方位・取得元)を確定する(pc-closed-loop 3.4節)。→ 現状: EntranceSnapshotを生成する本番コード自体が存在しない。FieldPlanningGeometry.centerTillageDirectionCandidates(field)(Track #86実装済み)で筆の各辺基準のheadingDeg候補を提示し、利用者が選択または自由回転する。→ これは正しく配線されている(Track #86)。resolveEntrance(field, entrance, approachHeadingDeg, ...)でEntranceResolution(近い角・反対側の角・introductionVisitOrder)を求め、centerTillageOrientation(field, headingDeg, entrance)でpeelCornerIndex/deferredCornerIndicesを求める。→ 現状: どちらの関数も本番から呼ばれていない。tillageRegions(field, profile, marginCm)(Track #75)でsafeCenterlineRegion/perimeterLaps/centerTillageRegionを求める。この処理自体は入口非依存で正しい。finishingLap3StartAnchorの算出(あるべき処理、現状未実装): 3で求めた入口情報と4で求めたperimeterLaps(特にlap3中心線)から、「入口から最も遠い側にある、3列目周回の開始点」を実座標として1点求める。同時に、この点がlateralAxisのどちら側(MIN/MAX)にあるかからfinishingSideを、field幅からrequiredParity相当の制約条件(Dとlaneの偶奇関係)を導出する。この計算ステップ自体がコードに存在しないのが最大の欠落点。centerTillageLateralSpan(centerTillageRegion, headingDeg)(Track #76/#77)でoverallSpanを求める。入口非依存の処理として正しい。requiredParityと、6のoverallSpanからD(開始側〜理想終点距離)を使い、centerTillageOverlapAdjustmentでlaneCount/actualOverlapCm/actualPitchCmを決める。現状: requiredParityは5から渡されず、UIの<select>から直接渡される。finishingSideと、7の結果からcenterTillageCandidateLanesで各laneのoffsetを決め、polygonでclipしてCenterTillageCandidateLane群を得る。現状: finishingSideも5から渡されずUI入力。CenterTillageWorkArea群を得る(Track #87実装済み、入口非依存で妥当)。bestPathBetweenAnchorLanes等がその情報を使って候補を絞り込める。現状: 5が無いため、lateralAxis両端という代理指標だけで探索し、最大4候補を生成して終わる(未実装のB-2hへ選択を先送り)。selectedInternalPlanを確定する。deferredTargetsを、10/11で確定した中央passへCenterTillageDetourとして挿入する。TillagePlan(RouteAction列)へ統合する。TillagePlanInvariantsで構造検証し、開始前previewへ表示する。現状のコードは4・6・9(および可視化)は実装されているが、1・3・5・7の一部(内部導出)・10(部分的)・11・12・13が欠落している。7・8は「計算アルゴリズム」としては実装済みだが「入力の出所」が5を経由していないため、耕耘順序としての意味を持たない。
注記: 以下は既決規則・fixtureに基づくあるべき挙動であり、現状のコードには一切実装されていない(§3・§4参照)。
centerTillageOrientation(field, headingDeg, entrance)が、introductionVisitOrder(導入周回で訪れる頂点順)とpeelCornerIndex(回転後の中央耕開始位置に対応する頂点)から、peelPosition = introductionVisitOrder.indexOf(peelCornerIndex)を求める。duringInitialLoopTargets = cornerTillTargets ∩ introductionVisitOrder[0..peelPosition](外周一周中に処理できる追い詰め対象)、deferredTargets = cornerTillTargets ∩ introductionVisitOrder[(peelPosition+1)..](処理できず残る対象、通常90度回転時は1件)を求める(pipeline-contract.md 5.7節)。duringInitialLoopTargetsをすべて処理し、deferredTargetsは未処理のまま中央隣接耕へ入る。deferredTargetsの各頂点への垂線の足(中断位置候補)を、その頂点に近いWorkArea内の全passから探す(pipeline-contract.md 7.2節、B-2i未実装)。RouteActionRole.CenterTillageDetour(cornerIndex, TO_CORNER)(DEADHEAD)により中央passを離脱する。RouteActionRole.CornerTill(cornerIndex, DEFERRED)(TILL)で追い詰め対象の頂点を耕す(cornerStopPointまで、pipeline-contract.md 2.3節)。RouteActionRole.CenterTillageDetour(cornerIndex, RETURN_TO_INTERRUPTION)(DEADHEAD)で、6の中断位置へ正確に復帰する。passIdのまま(segmentIndexを1つ進めて)中央passを再開する(TillagePlanInvariants.validateCenterTillageInterruptionが、TO_CORNER→CornerTill→RETURN_TO_INTERRUPTIONのサンドイッチ構造と座標連続性を検証する契約、TillagePlanInvariants.kt:203-259)。現状、2(centerTillageOrientation)は関数として実装済みだが呼ばれておらず、3(duringInitialLoopTargetsは識別子自体不在、deferredTargetsは計算されるが未使用)、5〜9(CenterTillageDetour/CornerTillの生成、B-2i)はいずれも本番未実装である。したがって「90度回転時の追い詰け中断・再開」という、この案件で最も複雑な既決規則(規則12・13)は、現時点で契約書・fixture上にのみ存在し、コードとしては一度も動いたことがない。
依存関係の観点から、次の順に再開するのが妥当と考えられる。各段階で成立させるべきテストも示す。
finishingLap3StartAnchor・requiredParity・finishingSideを「どのStageが」「どの入力から」計算するかを明記する形へ pipeline-contract.md を改訂し、利用者承認を得る(現状は8章のStage順序と1.9節のアンカー概念が整合していない)。テストなし(文書レビューのみ)。resolveEntrance/centerTillageOrientationの出力から、finishingLap3StartAnchor(実座標+lateralAxis側)を計算する新関数を追加する。テスト: 矩形・斜行筆で、入口位置を変えるとアンカー座標・side が追随して変わることをfixtureで確認。centerTillageOverlapAdjustmentのシグネチャから生のrequiredParity引数を廃し、2のアンカーから内部導出する形へ変更。テスト: 入口位置を変えた同一筆で、laneCountの偶奇が自動的に変わることを確認する新fixture。既存FieldOverlapAdjustmentSolverTestのpitch探索ロジック自体はそのまま流用可能。centerTillageCandidateLanesから生のfinishingSide引数を廃し、同じアンカーから導出。テスト: 同上、入口位置を変えるとfinishing laneのoffsetが追随することを確認。bestPathFromAnchorLane等へ実際のアンカー情報を結線し、WorkArea内部探索が「入口に近い側から遠い側(アンカー)へ」向かう制約を持つよう変更。simulator-uiのrequiredParity/finishingSideの手動<select>を削除。テスト: 既存の反例fixture(4segment、距離3 vs 102)が、入口情報を与えるだけで手動指定なしに正しい経路を選ぶことを確認。CenterTillageDetour/CornerTill)をTillagePlanへ統合する。テスト: 90度回転fixtureで、中断→追い詰け→復帰→再開のRouteAction列がTillagePlanInvariants.validateCenterTillageInterruptionを満たすこと。selectedInternalPlanを確定する。テスト: 14章fixture計画にある「WorkArea 3個」「仕上げ周回始点の反対側に複数WorkArea」等の数値assert。MAX_EXHAUSTIVE_ORDER_SEGMENT_COUNT=14): Track #87 comment #4905で利用者の事前承認なしに12→14へ変更。実測デモfixture(25/63 segment)が既にこの閾値を超えており、契約書7.4節が求める「実測に基づく決定」プロセスを経ていない。requiredParity/finishingSideの手入力化: Track #78/#81でこれらをUI手動入力として設計したこと自体、利用者への明示的な提案・承認プロセスを経た記録が見当たらない(むしろKDocに「後続工程が決める入力」と書かれ、暗黙に先送りされた)。docs/runbooks/navigation-field-geometry-pipeline-contract.md自体がTrack #88により自己改訂されている点: 同文書冒頭の改訂履歴に「Track #88(境界B-2f restart再修正)により1.5節(5)・3.1節を修正」と明記されており、実装が発見した問題を機に契約書自体を書き換えるという手順を踏んでいる。これがreview-gates.mdの「可視化で契約との解釈差が見つかった場合は、後工程で吸収せず、その境界の契約・fixture・実装へ戻して修正する」という原則に沿った適切な対応か、それとも実装都合による契約の後追い修正かは、利用者の判断を要する。TillagePlanを組み立てるcomposerが一度も実装されていないという事実そのもの: Track #70〜#88のいずれも、この欠落を明示的に課題として利用者へ提示した記録が見当たらない(pipeline-contract.md 16章でB-2jとして将来課題化されているのみ)。既決規則(特に規則12・13)が実質未実装であることを、利用者が現状どこまで認識しているかの確認が必要。docs/standards/*、docs/specifications/p6-ui-spec.md(全441行)、docs/runbooks/navigation-pc-closed-loop-implementation.md(全文)、docs/runbooks/navigation-tablet-preview-claude-implementation.md(全文)、docs/runbooks/navigation-field-geometry-pipeline-contract.md(全878行)、docs/runbooks/navigation-field-geometry-review-gates.md(全文)を通読。resolveEntrance/centerTillageOrientation/TillagePlan(の呼び出し元検索、requiredParity/finishingSideのUI配線、MAX_EXHAUSTIVE_ORDER_SEGMENT_COUNTの実装箇所を本報告作成者自身が直接grepで再検証済み)。work_record/work_publishはいずれも行っていない。