Metadata-Version: 2.4
Name: report-data-contract
Version: 0.0.1
Summary: SSOT contracts for Engine ↔ Backend report data (Python dataclasses + JSON Schema).
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: pydantic<3.0,>=2.0

# Report Data Contract（Engine ↔ Backend 报告数据契约 SSOT）

本仓库用于定义 **Engine 写盘/发布** 与 **Portal Backend 读取/加工** 所使用的“申明式报告数据”契约（Single Source of Truth, SSOT）。

目标：
- 把跨边界（写盘 → 发布 → 读取）的 payload 结构 **显式定义**，避免 Engine/Backend/Frontend 各自维护导致 drift；
- 支持 **fail-fast 校验**：Engine 写出前校验、Backend 读入后/transform 后校验；
- 数据结构尽量保持 **render-agnostic**（语义组件树），不与 HTML/PDF/Word 等具体渲染实现强绑定。

> 说明：本契约使用 `$component_type` 作为组件判别字段，表达的是“组件种类/语义块”，不与 HTML/PDF/Word 等具体渲染实现强绑定。

## Python（Engine/Backend）使用方式

本仓库提供 `src/report_data_contract/` 下的 **Python dataclass 契约类型**：
- Engine/Backend 可直接 import；
- 在边界处用 Pydantic v2 `TypeAdapter(...).validate_python(...)` 做运行时校验与收口（fail-fast）。

安装（本地开发）：

```bash
pip install -e .
```

示例（从 raw dict 校验并收口）：

```py
from report_data_contract import REPORT_NODE_DATA_ADAPTER, TOPOLOGY_ADAPTER

report_section = REPORT_NODE_DATA_ADAPTER.validate_python(raw_report_data_dict)
topology = TOPOLOGY_ADAPTER.validate_python(raw_topology_dict)
```

## 导出 JSON Schema（供 OpenAPI/跨语言复用）

如果你希望把本仓库的结构进一步投影到 OpenAPI / 前端 / 其它语言，可以从 TypeAdapter 导出 JSON Schema（派生产物，不手改）：

```bash
python -m report_data_contract.export_json_schema --out-dir json_schema
```

输出：
- `json_schema/*.schema.json`：每个核心结构一份独立 JSON Schema（含 `$defs`）
- `json_schema/index.json`：文件索引

## 版本策略

- 本仓库以 **Python 包版本** 作为唯一的契约版本管理机制（Engine/Backend 通过依赖版本对齐）。
- git tag 是发布版本真源。`v0.1.0` 会在 CI 中发布为 Python 包 `report-data-contract==0.1.0`。
- 当前只接受 `vX.Y.Z` 形式的 release tag；tag 格式不合法时，workflow 会直接失败。
- 消费方应锁定明确版本，例如 `report-data-contract==0.1.0`，并由 Sugarglider 的版本依赖锁定能力统一编排升级。
- 本仓库不在 Engine 落盘产物（如 `meta.json`）里再重复写入“契约版本号”；版本不匹配时，应通过边界校验失败 fail-fast。

## CI/CD

仓库在 PR、`main` push 和手动触发时会自动：

- 构建 Python wheel；
- 校验 wheel metadata；
- 安装构建出的 wheel；
- 验证核心 adapter 可 import；
- 验证 JSON Schema 可导出。

仓库在收到版本 tag push 后会额外：

- 从 git tag 派生 Python 包版本；
- 构建 `report-data-contract` wheel；
- 发布到私有 pypiserver。

发布约定：

1. 通过 PR 合并到 `main`。
2. 在目标提交上打版本 tag，例如 `v0.1.0`。
3. push tag 后触发 GitHub Actions 构建与发布。

GitHub Actions 复用组织级私有源配置，并授权本仓库访问：

- organization secret：`SCIENITH_PRIVATE_NETRC`
- organization secret/variable：`SCIENITH_PRIVATE_PYPI_SIMPLE_URL`
- organization secret/variable，可选：`SCIENITH_PRIVATE_PYPI_PUBLISH_URL`

其中：

- `SCIENITH_PRIVATE_NETRC` 是包含私有 PyPI host 凭证的 `.netrc` 内容。
- `SCIENITH_PRIVATE_PYPI_SIMPLE_URL` 形如 `http://<host>:8080/simple/`。
- `SCIENITH_PRIVATE_PYPI_PUBLISH_URL` 通常不需要单独配置；workflow 会默认从 simple URL 反推出 `http://<host>:8080/`。

本地发布到私有 pypiserver：

```bash
CONTRACT_RELEASE_TAG=v0.1.0 ./scripts/apply_release_version.sh
PRIVATE_PYPI_PUBLISH_URL=http://<host>:8080/ \
TWINE_USERNAME=<username> \
TWINE_PASSWORD=<password> \
./scripts/publish_python_package.sh
```

消费方式：

```bash
pip install --index-url http://<host>:8080/simple/ report-data-contract==0.1.0
```

## 覆盖范围

本仓库以 Python dataclass/TypeAdapter 为 SSOT，覆盖以下核心文件/数据：
- `meta.json`（包含 `node_uid/node_path/...` 等）
- `views/<lang>/report_data.json`（节点报告的组件树）
- `views/<lang>/topology.json`（GraphNode 拓扑）
- `graph_index.json`（GraphNode 索引）
- `views/<lang>/loop_index.json`（LoopNode 迭代选择器索引）
- `views/<lang>/io_schema.json`（GraphNode 输入 schema，v1）
- `io_values.json`（GraphNode 输入 values，v1）
- `input_binding` / `node_input_bindings`（inputs 溯源 SSOT，用于 Portal “来自上游步骤/源头路径”展示）
- Backend 聚合的 `ReportData`（给前端/渲染器的统一报告结构）

目录结构：
- `src/report_data_contract/`：Python dataclass 契约类型 + `TypeAdapter` 校验入口（`adapters.py`）
