Metadata-Version: 2.4
Name: minieye-runtime-config
Version: 0.1.2
Summary: Strict v1 runtime, path, private configuration, initialization, and migration helpers.
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: tomli>=2.0; python_version < "3.11"
Requires-Dist: tomli-w>=1.2.0
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"

# minieye-runtime-config

Version: 0.1.2

Strict v1 runtime configuration for Minieye workflows. This release keeps the
0.0.7 public read APIs while replacing the legacy `config.toml` entrypoint with
`config.v1.toml`, deriving host project paths from one storage root, and moving
all private Feishu values into adjacent `private.v1.toml`. Version 0.1.2 moves
vehicle dimensions, sensor names, and vehicle-level design initial extrinsics
into one registered TOML sidecar per `vehicle_type`, folds the old Feishu
credential/member sidecars into private TOML fields, and exposes packaged
legacy runtime templates for explicit migration tools.

## Entrypoint And Permissions

The only main-config entrypoints are:

- `MINIEYE_CONFIG_FILE`
- `~/.minieye_config/config.v1.toml`

There is no fallback to `config.toml`. The config directory must be `0700`.
These real files must be `0600`:

- `config.v1.toml`
- `private.v1.toml`

`private.v1.md` is a local field guide generated by `init-v1` and may be
`0644`.

Every public read API validates the exact metadata below before returning data:

```toml
[meta]
config_schema_version = "1.0"
d13_runtime_config_version = "0.1.2"
```

## Main Config

Host paths are configured once:

```toml
[storage]
host_disk_root = "/media/mini/T9"

[common.paths]
nas_dir = "/run/user/1000/gvfs/smb-share:server=example,share=data"
mdrive_root_dir = "/home/mini/code/mdrive_git"

[projects.mdrive_pb.paths]
docker_disk_dir = "/mdrive/second_ground_truth/T9/mdrive-pb"

[projects.mdrive4_json.paths]
docker_disk_dir = "/mdrive/mdrive4-json"

[feishu]
auth_identity = "bot"
default_doc_type = "docx"

[vehicle_catalog]
vehicle_types = ["bus", "t5", "t5_pro"]

[vehicle_catalog.vehicle_type_models]
bus = ["OH_HW4"]
t5 = ["ECAR_HW4"]
t5_pro = []
```

`mdrive_pb` derives:

- `<host_disk_root>/mdrive-pb`
- `01_record_data`
- `02_parsed_frames`
- `03_single_frame`
- `04.calibration_results`
- `05.feishu_report_info`
- `00_temp`

`mdrive4_json` derives the same layout except its L1 directory is
`01_mcap_data`. Each family retains its own explicit `docker_disk_dir`.
`common.paths`, `projects.*.git`, `runtime_project`, and `docker` remain
explicit non-derived configuration.

Main-config key names containing `token`, `secret`, `open_id`, `cookie`,
`credential`, `password`, `oauth`, `member_open_ids`, or `log_id` are rejected.

## Vehicle Catalog

`vehicle_catalog.vehicle_types` is the only vehicle sidecar index. For a
selected config such as `/tmp/runtime/config.v1.toml`, D13 reads sidecars only
from `/tmp/runtime/vehicle_base_info/<vehicle_type>.toml`; it never scans
unregistered files and never falls back to `~/.minieye_config/config.toml`.

Each registered sidecar has this shape:

```toml
design_initial_extrinsics = []

[meta]
schema_version = "1.0"
vehicle_type = "bus"
description = "Bus vehicle base information"

[dimensions]
long = 5.98
wide = 2.08
high = 2.93
wheelbase = 4.36
front_overhang = -1.0
rear_overhang = 0.777

[sensor_categories]
lidar = ["at128p_front"]
camera = ["camera_front"]
ins = ["ins"]
vrf = ["vrf"]
radar = []
uss = []
other = ["lidar_fusion"]
```

Design initial extrinsics use `[[design_initial_extrinsics]]` entries with
`source_frame`, `target_frame`, `t_xyz_m`, `q_xyzw`,
`output_mode = "compute"`, and `source = "vehicle_design_initial"`.
They are fixed design seeds, not measured PB/JSON calibration results. D13 does
not import or overwrite them from PB/JSON; D03 remains responsible for TF
calculation and compute/projection conversion.

`vehicle_type`, `vehicle_model_id`, and `repo_vehicle_model` are independent.
`vehicle_type_models` is an optional explicit link only: an absent entry returns
an empty list and D13 never guesses a mapping from names.

## Private Config

Private TOML is always located beside the selected main config:

```toml
# private.v1.toml
[feishu]
host_open_id = "ou_xxx"
default_folder_token = "fld_xxx"

[feishu.calibration_report_archive]
wiki_space_id = "7615..."
wiki_parent_node_token = "wikcn_xxx"
bot_app_id = "cli_xxx"

[feishu.company_view_permission]
tenant_entity_id = "tenant_xxx"

[feishu.bot_credentials]
app_id = "cli_xxx"
app_secret = "xxx"

[feishu.member_open_ids.members]
owner = "ou_xxx"
```

The old sibling `feishu_bot_credentials` and `member_open_ids.json` files are
accepted only as legacy `migrate-v1` inputs. `init-v1`, `init-v0`, and runtime
read APIs no longer create or read them.

`feishu_config()` deep-merges main `[feishu]` with private `[feishu]`, defaults
to bot identity, and rejects a configured user identity.

## Python API

```python
from minieye_runtime_config import (
    all_vehicle_base_info,
    feishu_bot_credentials,
    feishu_config,
    feishu_report_archive_config,
    get_private_value,
    project_paths,
    require_path,
    require_project_path,
    vehicle_base_info,
    vehicle_base_info_dir,
    vehicle_design_initial_extrinsics,
    vehicle_dimensions,
    vehicle_sensor_categories,
    vehicle_sensor_names,
)

pb_paths = project_paths("mdrive_pb")
json_l1 = require_project_path("mdrive4_json", "record_data_dir")
legacy_pb_l2 = require_path("paths.parsed_frames_dir")
host_open_id = get_private_value("feishu.host_open_id")
bot = feishu_bot_credentials()
feishu = feishu_config()
report_archive = feishu_report_archive_config()
vehicle_dir = vehicle_base_info_dir()
bus = vehicle_base_info("bus")
all_vehicles = all_vehicle_base_info()
bus_dimensions = vehicle_dimensions("bus")
bus_categories = vehicle_sensor_categories("bus")
bus_lidars = vehicle_sensor_names("bus", "lidar")
bus_design_initial = vehicle_design_initial_extrinsics("bus")
```

The 0.0.7 APIs remain available, including path tokens, project Git helpers,
`optional_float`, `runtime_paths`, and legacy `require_path("paths.*")`
aliases. Root `sensor_categories()` and `sensor_names()` keep a valid global
`[sensor_categories]` section as their first source, falling back to the
deduplicated registered-sidecar union only when that whole section is absent.
Similarly, root `vehicle_dimensions(vehicle_type)` keeps
`[vehicle.dimensions.<vehicle_type>]` authoritative whenever the legacy
dimensions section exists; a missing vehicle type or invalid legacy value is an
error, not a sidecar fallback. It reads a sidecar only when the whole legacy
dimensions section is absent. In contrast, `vehicle_base_info()`,
`vehicle_sensor_categories()`, `vehicle_sensor_names()`, and
`vehicle_design_initial_extrinsics()` always read the registered sidecar.
Sidecars are explicit candidate data for new callers, not the default source of
old root compatibility calls.

## CLI

```bash
minieye-runtime-config init-v0 \
  --host-disk-root /media/mini/T9 \
  --pb-docker-disk-dir /mdrive/second_ground_truth/T9/mdrive-pb \
  --json-docker-disk-dir /mdrive/mdrive4-json \
  --nas-dir /run/user/1000/gvfs/smb-share:server=example,share=data \
  --mdrive-root-dir /home/mini/code/mdrive_git

minieye-runtime-config init-v1 --target-dir ~/.minieye_config
minieye-runtime-config validate
minieye-runtime-config show-resolved
minieye-runtime-config vehicle-base-info list
minieye-runtime-config vehicle-base-info show bus
minieye-runtime-config vehicle-base-info validate
minieye-runtime-config inspect ~/.minieye_config/config.v1.toml
minieye-runtime-config migrate-v1
minieye-runtime-config migrate-v1 --apply
```

`init-v0` preserves the old parameterized initializer. `init-v1` does not
accept path parameters; it only copies the packaged blank v1 templates, refuses
overwrite by default, creates the config directory as `0700`, writes config and
private files as `0600`, and writes `private.v1.md` as `0644`. `migrate-v1`
reads sibling legacy `config.toml`, defaults to dry-run, validates both family
layouts, preserves the old file byte-for-byte, splits sensitive values, and
writes atomically only with `--apply`.

`vehicle-base-info validate` checks the registration list, directory and file
permissions, required files, filename/meta identity, TOML types, dimensions,
all seven sensor categories, duplicate sensor names, design-extrinsic fields,
unit quaternions, duplicate frame pairs, and unregistered TOML files.

## License

MIT

## Version Notes

- 0.1.2: update runtime metadata to `d13_runtime_config_version = "0.1.2"`,
  keep Feishu bot credentials and member open ID mappings inside
  `private.v1.toml`, package the 0.1.0 baseline template, and expose
  `legacy_template_text()` for migration callers that must not read D_pypi
  source paths directly.
- 0.1.1: split vehicle dimensions, sensor names, and design initial extrinsics
  into registered `vehicle_base_info/<vehicle_type>.toml` sidecars while keeping
  the main config runtime metadata at `d13_runtime_config_version = "0.1.1"`.

## 设计原则

- [版本无关设计原则](../../design_principle.md)
