# Tancho Observation Program 詳細実装設計 | 項目 | 内容 | |---|---| | 文書版 | 1.0 | | 日付 | 2026年9月21日 | | 状態 | Release 1実装用 | | 上位要件 | [Tancho PRD](tancho-prd-2026-09-21.md) | | 対象範囲 | `slope_failure_v1`、`access_clearance_v1`を初回実装。後続profileの拡張点も定義 | 対象ミッションの正本は [Tanchoのミッション台帳](tancho-mission-inventory-2026-09-21.md)、製品要件の正本は [Tancho PRD](tancho-prd-2026-09-21.md)、開発順と採用条件の正本は [Open-weight Cosmos 3 Edge Generator計画](open-weight-generator-plan-2026-09-21.md) とする。本書は、その方針をコードへ実装できる粒度まで落とした詳細設計である。 ## 1. 設計の不変条件 1. 対象の発見と範囲抽出は、物体検出器、面分類器、地図照合が担う。 2. 同じCosmos 3 Edge派生checkpointを、Reasoner roleとGenerator roleの別呼出しで使う。 3. Reasonerは未回答の運用上の問いを選ぶ。Generatorは検査済みの問いに必要な観測関係を組む。 4. モデルは座標、角度、距離、速度、滞在時間、緯度経度、PX4命令、安全制約を出さない。 5. 観測コンパイラ、軌道計画器、RFLが数値の視点と経路を決める。 6. モデルの生出力を補修、丸め、近い列挙値へ置換しない。不正出力はそのまま拒否する。 7. 決定論的fallbackで飛行できても、モデルの採用成績には数えない。 8. 旧 `tancho-viewpoints-1.0` と固定場面SITLの意味を変更しない。新しい版からadapterで接続する。 ## 2. データフロー ```text FrameBundle + telemetry + detector/classifier/map outputs │ ▼ build_mission_context() │ MissionContext(trusted) ▼ Cosmos 3 Edge / Reasoner role │ raw ObservationIntent ▼ validate_and_bind_intents() │ VerifiedIntentSet(trusted IDs/revision) ▼ Cosmos 3 Edge / Generator role │ raw ObservationProgram ▼ validate_observation_program() │ VerifiedObservationProgram ▼ compile_observations() │ CompiledViewPlan ▼ adapt_to_viewpoints_v1() │ tancho-viewpoints-1.0 ▼ trajectory planner → RFL → PX4 → capture │ ▼ verify_observation_result() ``` モデル呼出し間で渡すのは、生のReasoner JSONではなく `VerifiedIntentSet` である。アプリケーションがcanonical JSONのSHA-256から `intent_id` と `intent_revision` を作り、内部で固定する。Generator promptでは各intentを安定した `sequence` で示し、生出力の `intent_sequence` を検証器がopaque IDへ束縛する。 ## 3. MissionContext 1.0 ### 3.1 生存期間と上限 | 項目 | 値 | |---|---| | schema | `tancho-mission-context-1.1` | | 最大対象数 | 32 | | 最大根拠画像数 | 8 | | 最大完了済みquestion数 | 対象ごと32 | | 最大センサー数 | 8 | | 時刻 | 同期済みの整数milliseconds | | 有効期限 | アプリケーションが設定。モデルは延長不可 | 上限はメモリ使用量と攻撃面を閉じるための契約上限であり、運用上必要な件数を示す値ではない。上限を超えた入力は分割し、同じcontextとして黙って切り捨てない。 ### 3.2 JSON形状 ```json { "schema_version": "tancho-mission-context-1.1", "context_id": "ctx-...", "mission_id": "mission-...", "mission_profile": "slope_failure_v1", "captured_at_ms": 0, "expires_at_ms": 0, "input_sha256": "64 lowercase hex", "model_revision": "...", "profile_revision": "...", "map_revision": "...", "calibration_id": "...", "envelope_revision": "...", "evidence_ids": ["frame-1"], "sensor_capabilities": ["rgb"], "targets": [ { "target_id": "target-1", "category": "landslide_area", "source": "area_classifier", "geometry_ref": "geometry-1", "map_relations": ["intersects_road"], "required_questions": ["landslide_road_connection"], "completed_questions": [] } ], "policy": { "max_intents": 4, "max_observations": 8, "max_viewpoints": 8, "max_reobservation_cycles": 1 } } ``` `input_sha256` は画像bytesのhash、対象レジストリ、センサー能力、各revision、policyを含むcanonical入力からアプリケーションが計算する。`context_id` もアプリケーションが発行し、モデル出力との照合にだけ使う。 ### 3.3 列挙値 `sensor_capabilities` は初版で `rgb` と `thermal` のみを許す。SIYI A8 miniだけの構成は `rgb` だけになる。`thermal` をモデルが出力に追加しても能力が増えたとは扱わない。 `source` は `object_detector`、`area_classifier`、`map`、`map_difference`、`telemetry` のいずれか。`category` と `map_relations` は [§7](#7-ミッションプロファイル) のprofileで許可されたものだけを受ける。 ## 4. Reasoner role ### 4.1 モデル生出力 ```json { "schema_version": "tancho-observation-intent-1.0", "context_id": "ctx-...", "mission_id": "mission-...", "outcome": "inspect", "evidence_ids": ["frame-1"], "intents": [ { "sequence": 0, "target_id": "target-1", "question": "landslide_road_connection", "priority": 1, "evidence_ids": ["frame-1"] } ], "reason_code": "unanswered_question" } ``` ### 4.2 outcomeと整合条件 | outcome | intents | evidence_ids | reason_code | |---|---:|---:|---| | `inspect` | 1以上、policy以下 | 1以上 | `unanswered_question` | | `satisfied` | 0 | 1以上 | `all_required_questions_completed` | | `unsupported_sensor` | 0 | 1以上 | `required_sensor_unavailable` | | `insufficient_evidence` | 0 | 0以上 | `target_unresolved` または `evidence_unusable` | `priority` は1が最優先で1〜3。`sequence` は0から欠番なし。`question` はprofileの許可表にあるだけでなく、そのtargetの `required_questions` に明示され、`completed_questions` に無いことを要求する。同じ `target_id + question` の重複は拒否する。`completed_questions` は `required_questions` の部分集合でなければならない。`satisfied` は全targetで両集合が一致した場合だけ許可する。これにより、Reasonerは画像だけから任務目的を推測して質問を増やせず、旧 `no_action` の移行も具体的な完了対象に束縛される。 ### 4.3 検証後の内部表現 `validate_and_bind_intents(raw, context, now_ms)` は生出力を変更せず検査し、成功時だけ次をアプリケーション側で追加する。 - `intent_id = sha256(context_id + sequence + target_id + question)` の64文字lowercase hex - `intent_revision = sha256(canonical verified intent set)` - `source_output_sha256 = sha256(raw model bytes)` これらは次のモデルに渡す信頼済みIDであり、Reasoner自身には生成させない。 ## 5. Generator role ### 5.1 入力 Generatorは同じFrameBundle、MissionContext、VerifiedIntentSetを受ける。Reasonerの自由文や未検証JSONをプロンプトへ連結しない。プロンプトには、アプリケーションが検証したintentの `sequence`、対象、question、priority、根拠画像IDを渡す。`intent_id`、`intent_revision`、context/mission IDなどのopaqueな値はモデルに再生成させない。 ### 5.2 モデル生出力 ```json { "schema_version": "tancho-observation-program-1.1", "outcome": "observe", "observations": [ { "sequence": 0, "intent_sequence": 0, "view_relation": "along_axis", "coverage": "both_sides", "detail_level": "damage", "sensor": "rgb", "stop_condition": "corridor_continuity_visible" } ], "reason_code": "program_created" } ``` ### 5.3 outcomeと整合条件 | outcome | observations | reason_code | |---|---:|---| | `observe` | 1以上、policy以下 | `program_created` | | `uncompilable_intent` | 0 | `unsupported_observation_primitive` | Generatorは `satisfied` を返せない。問いが既に満たされたかを決めるのはReasonerである。Generatorはセンサー能力を変更できず、入力intentを追加、削除、改名できない。`observe` の場合は各intentが少なくとも1回参照される。完了済みquestionに結び付くintentは入力段階で存在できない。 ### 5.4 共通の観測語彙 | field | 初版の列挙値 | |---|---| | `view_relation` | `overview`, `nadir`, `oblique`, `cross_section`, `along_axis`, `context`, `intercept`, `search_sweep` | | `coverage` | `full_target`, `boundary`, `upper_lower_edges`, `both_sides`, `connection`, `upstream_downstream`, `target_and_context`, `facade_foot`, `approach_corridor`, `search_region` | | `detail_level` | `detect`, `identify`, `state`, `damage` | | `sensor` | `rgb`, `thermal` | 検証器は `intent_sequence` をVerifiedIntentSetの同じsequenceへ決定論的に結び、そこで初めてopaqueな `intent_id`、context/mission ID、`intent_revision` を付与する。未知sequence、欠落intent、同じ `intent_sequence + view_relation + coverage + detail_level + sensor + stop_condition` の重複は拒否する。旧1.0入力は保存済み証拠の検証用に読み取れるが、新しいpromptと教師は1.1だけを生成する。順序違いだけの重複教師を別正解として数えない。 ## 6. アプリケーション状態機械 ```text CAPTURED → CONTEXT_VALIDATED → INTENTS_PENDING → INTENTS_VERIFIED → PROGRAM_PENDING → PROGRAM_VERIFIED → COMPILED → SAFETY_VALIDATED → EXECUTING → RESULT_CAPTURED → RESULT_VERIFIED ├─ COMPLETE └─ CAPTURED(policyのcycle上限内だけ) ``` どの状態からも `ABORTED` へ移れる。状態を飛ばさない。context、intent、program、compiled plan、trajectory、実測結果のhashを同じ監査recordへ結び付ける。 `max_reobservation_cycles` はアプリケーションpolicyであり、モデルは変更できない。固定場面baselineは1を維持する。ミッション別の別値は、飛行時間と帰還余力を測定してからprofile revisionとして固定する。 ### 6.1 失敗時の処理 | 失敗 | 処理 | モデル成功に数えるか | |---|---|---| | JSON・schema・ID・revision違反 | 生出力を保存して停止 | 数えない | | 推論timeout・provider不一致 | 停止または明示的fallback | 数えない | | context期限切れ | 全出力を破棄し再撮影 | 数えない | | 未搭載センサー要求 | program拒否 | 数えない | | compiler解なし | `uncompilable` として停止または人へ返す | 数えない | | RFL拒否 | 拒否理由を保存して停止または明示的fallback | 数えない | | 実行中に対象消失・地図更新 | 実行を中止し、新contextからやり直す | 数えない | | 撮影品質未達 | cycle上限と資源内だけReasonerへ戻す | 最終達成時だけ閉ループ成功 | fallbackを使う場合は `decision_source = deterministic_fallback` と記録する。モデル出力をfallbackの入力に使わず、モデル採用ゲートの分母から除外もしない。 ## 7. ミッションプロファイル profileは、許可された対象、問い、観測語彙、停止条件の組合せをコード上の定数として持つ。ここで正解の観測セットを一意に規定しない。questionから常に同じprogramが出るなら画像不要のlookup課題になるため、可視状態、遮蔽、既観測範囲によって必要な観測が変わる評価対を必須にする。 ### 7.1 `slope_failure_v1` | category | question | |---|---| | `landslide_area` | `landslide_extent`, `landslide_road_connection`, `landslide_river_connection`, `landslide_occluded_region`, `slope_precursor_detail` | 許可する停止条件は `full_boundary_visible`、`upper_lower_edges_visible`、`connection_visible`、`occluded_region_resolved`、`precursor_detail_visible`。`thermal` は許可しない。 ### 7.2 `access_clearance_v1` | category | question | |---|---| | `road_segment`, `rail_segment`, `obstruction_area`, `bridge` | `corridor_continuity`, `obstruction_material`, `obstruction_extent`, `roadbed_loss`, `bridge_damage`, `approach_access` | 停止条件は `corridor_continuity_visible`、`obstruction_type_and_extent_visible`、`roadbed_edges_visible`、`bridge_damage_context_visible`、`approach_corridor_visible`。道路の「覆われる型」と「路体が失われる型」を別caseにする。 ### 7.3 `flood_river_v1` | category | question | |---|---| | `flood_area`, `river_segment`, `embankment`, `building`, `debris_area` | `flood_extent`, `flood_boundary`, `building_waterline`, `embankment_damage`, `channel_blockage`, `debris_accumulation` | 停止条件は `flood_boundary_visible`、`facade_waterline_visible`、`bank_damage_context_visible`、`channel_cross_section_visible`、`upstream_downstream_context_visible`。 ### 7.4 `rescue_v1` | category | question | |---|---| | `person`, `vehicle` | `person_state`, `person_surrounding_hazard`, `rescue_access`, `notification_frame`, `vehicle_state`, `vehicle_occupant_evidence` | 停止条件は `person_state_and_context_visible`、`rescue_approach_visible`、`notification_frame_sufficient`、`vehicle_state_and_context_visible`。RGBで状態を判定できる必要画質は現時点で未測定なので、profileの画質値を運用値として固定しない。 ### 7.5 `building_earthquake_v1` | category | question | |---|---| | `building`, `fire_region`, `person` | `building_collapse_extent`, `facade_damage`, `entrance_access`, `road_encroachment`, `fire_context` | 停止条件は `roof_and_collapse_extent_visible`、`required_facades_visible`、`facade_foot_visible`、`entrance_access_visible`、`fire_perimeter_context_visible`。熱画像を必須とするcaseで `thermal` が無ければReasonerは `unsupported_sensor` を返す。 ### 7.6 `orbitpod_recovery_v1` | category | question | |---|---| | `orbitpod_track`, `river_search_region` | `intercept_region`, `cross_river_search`, `detector_handoff` | 停止条件は `intercept_region_covered`、`search_region_covered`、`orbitpod_detector_handoff`。許可するview relationは `intercept` と `search_sweep` を中心とする。物体検出後の並走、索の位置合わせ、吸着、吊り上げは本profileの外である。 ### 7.7 未実装profile 山岳遭難、森林火災、野生動物は初版registryへ登録しない。未知profileとして拒否する。センサー、運用上の問い、独立素材、停止条件が揃ってから新しいversionで追加する。 ## 8. 観測コンパイラ ### 8.1 入力と出力 ```python compile_observations( program: VerifiedObservationProgram, context: MissionContext, scene: SceneSnapshot, vehicle: VehicleSnapshot, ) -> CompiledViewPlan ``` `SceneSnapshot` は対象geometry、地形mesh、占有・自由・未知を区別した障害物地図、道路・河川・建物等のmap geometry、各revisionを持つ。`VehicleSnapshot` は現在位置、速度、残電力、時刻を持つ。どちらもモデル出力から作らない。 `CompiledViewPlan` は `tancho-compiled-viewplan-1.0` とし、各視点に `observation_sequence` と `intent_id` を残す。既存の `tancho-viewpoints-1.0` へ渡すadapterは飛行用フィールドだけを変換し、元planと出力のhashを監査recordへ残す。 ### 8.2 コンパイル手順 1. profileの `view_relation + coverage + detail_level + sensor + stop_condition` を幾何制約へ変換する。 2. 対象surface、boundary、connection、axis、search regionを信頼済みgeometryから取り出す。 3. カメラ校正とdetail levelから必要GSDまたは画素条件を取得する。未測定の条件は推測せず `missing_quality_requirement` で失敗する。 4. 承認領域内に、profile固定の角度・距離samplingで視点候補を作る。この候補はモデルへ見せない。 5. 視錐台、遮蔽、未知空間、地形・障害物離隔、ジンバル可動域、画質余裕を検査する。 6. 1つの観測要求に複数視点が必要なら、必要coverageを満たす最小集合を決定論的に選ぶ。 7. programのsequenceとintent priorityを保ち、同順位内だけ移動時間を短くする。 8. 全視点を既存の範囲、期限、帰還検査へ渡す。総視点数がpolicy上限を超えたら切り捨てず失敗する。 ### 8.3 決定規則 複数の成立解は、次のlexicographic keyで一意に選ぶ。 ```text ( uncovered_required_area, unknown_space_intersection, collision_clearance_penalty, sensor_resolution_deficit, number_of_viewpoints, total_travel_seconds, canonical_quantized_coordinates ) ``` 前4項目は0が必須で、満たさない候補は採用しない。後3項目が同じ場合は1cm単位に量子化したENU座標の辞書順をtie-breakに使う。量子化は選択の再現性のためだけに使い、危険な座標を範囲内へ丸める処理には使わない。 ### 8.4 OrbitPodの分岐 `orbitpod_recovery_v1` は静止対象コンパイラへ入れない。位置列、時刻、流向、川幅geometryから待受け領域と探索走査を作る `compile_dynamic_search()` へ送る。OrbitPod検出後は状態機械を `DETECTOR_HANDOFF` で終了し、低遅延tracking controllerへ移す。Generatorを追跡loop内で再呼出ししない。 ## 9. モデルpromptとdecode roleごとにsystem instruction、schema、許可語彙を分ける。Reasoner promptへGeneratorの列挙値を、Generator promptへReasonerの未検証文章を入れない。画像は同じbytesをrole間で再利用し、processor後のpixel hashも記録する。 decodeはtemperature 0、1回だけ、修復・再試行なしを評価条件とする。運用で再試行を導入する場合は、評価値と分け、attemptごとのraw出力を残す。可能ならgrammar constrained decodingを使うが、grammarが正しい意味を保証したとは数えない。 ### 9.1 実行provider 新規学習は `deploy/modal_training/` からModal H100 1基で実行する。payloadは学習コード、固定Cosmos Framework revision、親model revision、training pack、save/resume/finish設定をファイル単位のSHA-256で固定する。成果物は `tancho-observation-program-artifacts` Volumeのrun ID別directoryへ保存し、同じrun IDを上書きしない。起動は既定でdry runとし、明示した `--execute` だけがcloud resourceを作る。 fresh model-in-loop SITLは `deploy/modal_observation_program/pipeline.json` の順序で実行する。PX4/Gazeboはnested Dockerを必要とするためModal VM Sandbox、ReasonerとGeneratorはModal H100、compilerとRFLは決定論的CPU stageとする。全stageは同じcontext、画像hash、公開checkpoint revision、監査chainをModal Volumeで受け渡す。Nebius call、保存済みmodel出力のfallback、Generator生出力の修復を含む試行はRelease 1証拠として拒否する。 既公開v4を作ったNebius job IDとarchive hashは履歴provenanceとして保持する。providerを遡及的にModalへ書き換えない。2026年9月22日以降に作る学習・SITL receiptは `deploy/execution-provider-policy.json` と `tancho/execution_provider.py` でModal以外をfail-closedにする。 ## 10. 学習データ ### 10.1 1レコード ```text sample_id leakage_group_id split role = reasoner | generator mission_profile context.json frames/* verified_intents.json # generator roleだけ target.json provenance.json ``` `target.json` はモデルの厳格JSONだけを持つ。chain-of-thoughtを教師や公開物へ入れない。教師の作成理由、代替正解、レビュー記録は別ファイルに保存する。 ### 10.2 分割 world、災害イベント、地点、関連飛行、遮蔽物配置、元画像hashのいずれかが同じものを同じ `leakage_group_id` に入れる。回転、左右反転、色変更、同一sceneの別カメラを独立現場として数えない。実写に位置・姿勢・校正が無ければ、Reasonerと意味的なGenerator教師には使えても、コンパイラの正解座標には使わない。 ### 10.3 必須対照 - 同じ画像でquestionを変え、必要観測を変える - 同じquestionで遮蔽・可視範囲だけを変え、必要観測を変える - 同じpromptと数値条件で画像だけを交換する - 灰色、欠損、古い画像を入れる - RGBだけのcontextでthermal必須の問いを出す - completed questionを含むcontextを入れる - mission profileと対象categoryを意図的に食い違わせる - questionから固定表を引くだけのrule baselineを先に測る 画像を見ないruleが最終評価の正解へ到達したprofileは、Generatorの学習課題として不成立と判定し、GPU学習へ進めない。 ### 10.4 段階追加 1. schemaとrole分離のsynthetic smoke 2. `slope_failure_v1` 3. `access_clearance_v1` 4. `flood_river_v1` 5. `rescue_v1` と `building_earthquake_v1` 6. `orbitpod_recovery_v1` 各段階は以前のprofileをreplayし、role比とprofile比をmanifestへ固定する。データ数、学習率、更新数、checkpoint間隔、費用上限はdevelopment dataと検出力設計から事前固定し、本書では根拠のない件数を置かない。 ## 11. 評価 ### 11.1 Reasoner単体 - strict schema valid率 - questionのmicro/macro precision、recall、F1 - 不要なinspect率 - completed question再要求率 - `unsupported_sensor` recall - evidence grounding率 ### 11.2 Generator単体 - 必要観測primitiveのmicro/macro precision、recall、F1 - 不要観測数 - 全intent coverage率 - sensor/profile違反率 - strict schema valid率 - rule baseline、base Cosmos 3 Edge、公開v5との比較 複数の観測セットが同じ目的を満たす場合は、finalを開く前に許可した同値集合をgoldへ記録する。結果を見てから同値扱いを追加しない。 ### 11.3 コンパイラ - gold programのcompile成功率 - coverage、遮蔽、画質、衝突、envelope、期限、帰還の各条件 - 同一入力のbyte-identical出力 - 1条件だけを変えたときの期待された差 - 解なしを解なしとして返す率 ### 11.4 閉ループ - モデル生出力に由来する観測達成率 - 実画像の有効率 - mission完了時間、移動距離、消費電力 - 不要な再観測数 - fallback率と人の介入数 - 対象消失、古い地図、推論停止、通信断での停止結果 ## 12. テスト設計 ### 12.1 unit - 全schemaの正常例と、未知・欠落・重複key - NaN、Infinity、bool-as-number、長過ぎる文字列、件数超過 - 未知context・target・evidence・intent ID - 古い時刻、異なるrevision、変更された画像bytes - profile/category/question/primitiveの全許可・拒否matrix - completed questionの復活、同一観測の重複 - unavailable sensor、role間schema取り違え ### 12.2 compiler property/golden - 同一入力の決定性 - targetの平行移動・90度回転でplanも対応して変換される - 障害物追加で貫通経路を作らない - 狭いenvelope、未知空間、画質不足、帰還余力不足で失敗する - 道路を覆う型と路体流失型が別のcoverageを要求する - OrbitPodを静止対象compilerへ渡すと拒否する ### 12.3 integration - raw Reasoner → verified intent → raw Generator → verified program → compiled plan → viewpoints v1 - 各境界でhashとrevisionが保持される - fallbackをモデル成功として記録しない - cycle上限、return reserve、対象消失、provider不一致で停止する - 旧viewpoint/PX4/SITLテストの結果を変更しない モデルの文章をそのまま写しただけのテストは作らない。安全境界、role混同、画像依存、決定性を壊す変更を検出できるテストに限る。 ## 13. コード配置と公開API | file | 公開関数・型 | |---|---| | `tancho/mission_profiles.py` | `MissionProfile`, `profile(name)`, `validate_profile_relation(...)` | | `tancho/mission_context.py` | `build_context(...)`, `validate_context_v1(...)`, `MissionContext` | | `tancho/observation_intent.py` | `parse_intent_output(raw)`, `validate_and_bind_intents(...)`, `VerifiedIntentSet` | | `tancho/observation_program.py` | `parse_program_output(raw)`, `validate_observation_program(...)`, `VerifiedObservationProgram` | | `tancho/observation_program_prompts.py` | `reasoner_prompt(...)`, `generator_prompt(...)` | | `tancho/observation_program_inference.py` | `infer_role(...)`、1回・期限付きのrole呼出しとreceipt | | `tancho/observation_compiler.py` | `compile_program(...)`, `compile_observations(...)`, `CompiledViewPlan`, `CompileError` | | `tancho/dynamic_search_compiler.py` | `compile_dynamic_search(...)` | | `tancho/viewpoint_adapter.py` | `adapt_to_viewpoints_v1(...)` | | `tancho/observation_program_runtime.py` | 状態機械と監査record | | `tancho/observation_result.py` | `verify_observation_result(...)` | | `tancho/observation_flight.py` | `prepare_px4_mission(...)`、RFL合格後の未送信mission生成 | | `training/build_observation_program_pack.py` | role別pack生成・分割検査 | | `training/observation_program_loader.py` | native Cosmos SFT loaderとpack再検査 | | `training/build_observation_program_review.py` | 旧素材からの未承認review queue生成 | | `training/promote_observation_program_review.py` | 人レビューexportの改ざん・権利・契約検査とSFT packへの昇格 | | `training/build_observation_program_synthetic_r1.py` | scene ground truthへ結び付いたRelease 1合成教師と独立validation生成 | | `training/score_observation_program.py` | 単体・paired・profile回帰評価 | | `training/check_observation_program_release.py` | 学習、評価、SITL、Orin、匿名公開の最終hard gate | | `deploy/modal_training/` | immutable payload作成、Modal H100 dry run/明示実行、Volume成果物receipt | | `deploy/modal_observation_program/` | Modal VM+H100のfresh SITL stage契約と準備record | | `tancho/execution_provider.py` | 新規学習・SITLのModal provider policyとreceipt検査 | 既存 `tancho/contracts.py`、`tancho/reasoner_mission.py`、`tancho/viewpoint_plan.py`、`tancho/px4_mission.py` は初版で変更しない。新runtimeからadapter経由で呼び、既存の評価と履歴を保持する。 ## 14. 実装PRの分割 1. **Contracts**: profile registry、MissionContext、Reasoner/Generator validator、unit tests 2. **Compiler**: 静止対象compiler、compiled plan、viewpoints v1 adapter、golden/property tests 3. **Slope and access data**: 合成world、teacher、rule floors、凍結split 4. **SFT and evaluation**: role別pack、学習recipe、単体評価、回帰評価 5. **Closed loop SITL**: 新runtime、監査record、fresh inference、失敗注入 6. **Additional profiles**: flood、rescue、building、OrbitPodを1profileずつ追加 7. **Open-weight release**: checkpoint、hash、model card、schema、compiler、全評価 PR 1と2はGPUを使わない。PR 3で画像不要のrule floorを測り、課題が成立した場合だけPR 4の有料学習へ進む。 ### 14.1 既存ラベルから学習packへの昇格 既存の人レビュー済みdecisionは再レビューしない。Release 1に一意対応する山王谷34件だけを対象にし、元の `inspect`、`no_action`、`abstain` を、それぞれ `inspect/unanswered_question`、`satisfied/all_required_questions_completed`、`insufficient_evidence/evidence_unusable` へ固定写像する。元decision、observation goal、source manifest、frame bytes、ontology crosswalk、期待Reasoner targetをproof JSONへ束縛し、`label_authority=deterministic_legacy_migration` とする。新しい構造化target自体を人が再確認したとは記録しないため `human_reviewed=false` を維持する。 旧ラベルのscreen pointやrangeは、Generator 1.1のview relation、coverage、detail level、stop conditionを一意に含意しない。そのため実写34件はReasoner教師だけに使い、旧数値からGenerator教師を推定しない。Generator教師は§14.2の決定論的scene ground truthから供給する。loaderはproof欠損、source bytes変更、旧decision変更、crosswalk変更、期待target変更をすべて拒否する。 新規素材を人がレビューする場合だけ `review.html` と `promote_observation_program_review.py` の経路を使う。この経路は元queueの非review部分、source manifest、全frame bytes、reviewer、timezone付き時刻、利用許諾、profile relation、両role契約を検査し、1件でも未確認・改ざん・禁止があればpackを作らない。既存34件の再ラベリングには使わない。 ### 14.2 決定論的scene ground truth 合成教師は人レビュー済み実写と同じ権限を名乗らない。`source_kind=synthetic`、`human_reviewed=false`、`label_authority=deterministic_scene_ground_truth` を設定し、renderer、world seed、target geometry、visibility、profile、role、question、期待するstrict targetを含むproof JSONのcanonical SHA-256へ各recordを結び付ける。packは対応する `proofs/.json` が無い、hashが違う、split/profile/role/targetが一致しない場合に学習用途で開けない。AI生成文、keyword候補、画像だけから推定したgeometryはこの権限を使えない。 Release 1のprocedural packは法面と道路について、明瞭、樹木遮蔽、利用不能のsceneを固定投影で描画する。同じ非画像入力のvisual pairでReasonerの `inspect` / `insufficient_evidence` とGeneratorの観測primitiveを変え、画像を無視するshortcutを検出する。world seedはカメラ座標として直接使わず、SHA-256から固定範囲のcamera/look-at parameterへ写像する。これによりtrain、development、finalのseed番号が異なっても同じ宣言済みcamera envelopeに入り、各splitはworld、event、site、flight、画像hashで分離される。v4ではtrain seed 1〜24、validation seed 101〜104、development seed 201〜204、final seed 301〜304を用いた。これは実写独立評価を代替せず、合成成績と実写成績を分けて報告する。 ## 15. 未確定値 次は実装漏れではなく、測定または運用判断が必要な未確定値としてmanifestに空で持つ。 - 人、車両、外壁、亀裂、護岸損傷ごとの必要画質 - missionごとの再観測cycle上限 - 観測primitiveの最終採用閾値 - Orin NX上のReasoner・Generator各roleのdeadlineと同時負荷 - thermal sensorの機種、校正、利用可能profile - OrbitPodの位置更新周期、探索高度、tracking controllerへの引渡し条件 これらを仮の数値で埋めた教師を作らない。値が無いprofile/caseは `unsupported_sensor`、`missing_quality_requirement`、または未実装として明示的に止める。 ## 16. PRD要件との対応 | PRD要件 | 詳細設計 | 主な実装 | |---|---|---| | FR-CTX-001〜004 | §3 | `mission_context.py` | | FR-REA-001〜004 | §4 | `observation_intent.py` | | FR-GEN-001〜005 | §5、§7 | `observation_program.py`, `mission_profiles.py` | | FR-CMP-001〜005 | §8 | `observation_compiler.py`, `dynamic_search_compiler.py`, `viewpoint_adapter.py` | | FR-FLT-001〜003 | §6、§8 | `observation_program_runtime.py`, 既存RFL/PX4経路 | | FR-RES-001〜002 | §6、§11.4 | runtimeと結果検証器 | | FR-AUD-001〜002 | §2、§6 | runtime監査record | | FR-PUB-001〜002 | §10、§11、§14 | pack、評価、release package | | NFR-SAF-001〜004 | §1、§6、§8、§12 | validator、compiler、runtime | | NFR-DET-001〜002 | §4.3、§8.3、§12 | canonicalizationとgolden tests | | NFR-REP-001〜003 | §9.1、§10.2、§11 | provider policy、split validatorとfinal runner | | NFR-PER-001〜003 | §6、§9、§15 | runtime metricsとdeadline guard | | NFR-DAT-001〜003 | §10、§14 | provenance manifestとrelease builder | | MR-001〜008 | §9〜§11 | training pack、recipe、score report | ## 17. 実装完了の定義 各PRは対象要件ID、変更schema、migrationの有無、正常系・拒否系テスト、既存回帰結果を記録する。Release 1の実装完了はPRD §12の全項目が証拠artifactへ結び付いた時点とする。schemaとprofileの変更はversionを上げ、保存済み評価入力の意味を上書きしない。