Files
skill-template/development/RUNTIME.md
chendelian de127d7e71
All checks were successful
技能自动化发布 / release (push) Successful in 14s
docs: codify free PyArmor Trial packaging guidance
2026-10-13 15:55:44 +08:00

148 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 运行时约定
## 共享 Python Runtime
**skill-template** 及复制出的新技能,公共能力均来自宿主匠厂安装的共享 Python Runtime(`jiangchang-platform-kit>=1.2.11` 及其传递依赖,含 `playwright`)。`jiangchang_skill_core` **不得**在技能仓库内 vendored,应由共享 venv 的 site-packages 提供。
技能根目录 `requirements.txt` **只声明技能特有依赖**;**不要**重复声明 `jiangchang-platform-kit` 或 `playwright`。`SKILL.md` 的 `platform_kit_min_version` 是运行契约,**不是** pip 依赖声明。
kit **源码仓**(可 clone 学习,勿 vendor)与其它公开公共仓登记见 [`SHARED_REPOS.md`](SHARED_REPOS.md)。
### 何时上调 `platform_kit_min_version`
| 情况 | 做法 |
|------|------|
| 技能依赖 kit 某次修复/新 API(如 `.env` 空值+行尾 `#` 解析、`poll_until`、启动超时) | 把 `metadata.openclaw.platform_kit_min_version` 调到**需要的最低版本**(模板默认 `"1.2.11"`) |
| PyPI/私有源刚发了更新,但本技能行为未依赖 | **不必**仅为「追新」抬版本 |
| 宿主升级时机 | 宿主在技能/宿主声明的最低版本**未满足**时按需升级共享 venv;**不会**仅因源上有更新就后台拉 latest |
模板默认声明须与当前文档所依赖的最低 kit 能力对齐(见根 `SKILL.md`)。
| 场景 | 推荐做法 |
|------|----------|
| 日常运行(宿主 / Agent) | 使用 PATH 上的共享 venv `python`(`{JIANGCHANG_DATA_ROOT}/python-runtime/.venv`) |
| 手工排查 / 测试机(环境未注入时) | `{JIANGCHANG_DATA_ROOT}/python-runtime/.venv/.../python` 执行 `scripts/main.py` |
| **禁止** | 在技能目录内 `uv run python …` — 会创建临时 venv,加载不到宿主共享 runtime |
占位命令(路径因环境而异,勿写死本机目录):
```text
推荐(已注入环境时):
python {baseDir}/scripts/main.py health
Windows(未注入时):
{JIANGCHANG_DATA_ROOT}\python-runtime\.venv\Scripts\python.exe {baseDir}\scripts\main.py health
Unix(未注入时):
{JIANGCHANG_DATA_ROOT}/python-runtime/.venv/bin/python3 {baseDir}/scripts/main.py health
```
共享解释器通常位于 `{JIANGCHANG_DATA_ROOT}/python-runtime/.venv`。数据根由宿主注入(见 `jiangchang_skill_core.runtime_env`)。
## Runtime 诊断(platform-kit 1.2.11+;含既有 1.2.2+ 字段)
`health` 命令通过 **`jiangchang_skill_core.collect_runtime_diagnostics`** 输出共享 runtime 诊断,**不在技能内重复实现**。典型字段:
- `skill_slug`、`python_executable`、`platform_kit_version`、`platform_kit_min_version`
- `jiangchang_skill_core_file` — 若从技能目录加载会输出 `runtime_issue[warning]`
- `JIANGCHANG_DATA_ROOT` / `resolved_data_root`
- `media_assets_root`、`ffmpeg_path`、`background_music_*`
- `record_video_enabled`、`runtime_issue[warning|error]`
- `machine_power` — 只读供电/限频探测(探不到则 `probed=false`);**不得**单独作为 hard-fail 依据
`health` 是**只读诊断**,**不会**触发 media-assets 下载或修复。并补充 `env_path` / `env_exists` / `example_path` 配置路径字段。
## 配置 bootstrap
- 仓库内 `.env.example` 是配置模板(单一事实来源)。
- 用户实际 `.env`:`{JIANGCHANG_DATA_ROOT}/{JIANGCHANG_USER_ID}/{skill_slug}/.env`。
- `scripts/main.py` 与 `cli.app.main()` 启动时调用 `util.config_bootstrap.bootstrap_skill_config()`。
- 配置优先级:**进程环境变量** > **用户 `.env`** > **`.env.example` 默认值**。
- 公共 `config` / `merge_missing_env_keys` 来自共享 runtime 的 `jiangchang-platform-kit>=1.2.11`,**不得** vendored `scripts/jiangchang_skill_core/`。
## media-assets / ffmpeg / 背景音乐
背景音乐、ffmpeg 等共享资源由 platform-kit 统一解析,默认路径:
```text
{JIANGCHANG_DATA_ROOT}/shared/media-assets
```
(由宿主注入 `JIANGCHANG_DATA_ROOT`。)
RPA 录屏成片(`RpaVideoSession`)、ffmpeg 路径、背景音乐探测均由 platform-kit 提供;技能只 import,不重复实现。
## 目录结构
新技能建议采用以下根目录结构:
- `assets/`
- `development/`
- `references/`
- `scripts/`
- `tests/`
- `evals/`
**标准 `scripts/` 分层(不含 `jiangchang_skill_core/` 副本):**
- `scripts/main.py`:唯一 CLI 入口
- `scripts/cli/`:参数解析与命令分发
- `scripts/db/`:SQLite 或本地持久化层(标准时间字段见 `references/SCHEMA.md`)
- `scripts/service/`:业务用例与外部交互
- `scripts/util/`:通用工具、常量、日志、路径薄封装
## 数据路径
推荐:
```text
{JIANGCHANG_DATA_ROOT}/{JIANGCHANG_USER_ID}/{skill_slug}/
```
数据库文件建议:
```text
{...}/{skill_slug}.db
```
**业务文件(输入、输出、缓存等)** 须落在上述数据目录的标准子目录下,**不得**相对 workspace/CWD 写入。用户可见目录为 `input/`(上行)与 `output/`(下行)。完整子目录树、env 覆盖规则、`resolve_data_path()` 用法见 **[`DATA_PATHS.md`](DATA_PATHS.md)**。
- 业务表使用英文 snake_case;中文表名/字段名写入 `_jiangchang_tables` / `_jiangchang_columns`(见 `references/SCHEMA.md`)。
- 界面字段顺序由 `CREATE TABLE` 列定义顺序决定,**不要**维护 `display_order` 来调整顺序。
## 明确禁止
- **不得** vendored `scripts/jiangchang_skill_core/`
- **不得**在技能内本地重复实现 `RuntimeDiagnostics` / `collect_runtime_diagnostics`
- **不得**写死开发机绝对路径作为运行时约定
## 测试时的运行时隔离
本模板的 `tests/_support.IsolatedDataRoot` 会在测试期间设置:
- `JIANGCHANG_DATA_ROOT` → 临时 tempfile 目录
- `JIANGCHANG_USER_ID` → `_test`
退出时两个变量恢复,临时目录删除。所有 DB / 文件写入都被限制在临时目录内,不污染本机。
详见 `TESTING.md` 第 3 节。
## 编码与输出
- 所有提交到 skill 的源码、文档、配置文本文件必须是 **UTF-8 without BOM**(不要只写「UTF-8」)。
- Python 文件**绝对不能**带 UTF-8 BOM;否则 release CI 的 PyArmor 阶段可能报:`invalid non-printable character U+FEFF`。
- Windows 编辑器容易保存成 UTF-8 BOM;提交前确认文件开头无 `U+FEFF`。
- Windows 终端建议在 `scripts/main.py` 里做 UTF-8 stdout/stderr 包装
- 机读输出优先单行 JSON
- 错误前缀建议统一 `ERROR:`
## 发布打包约束(`scripts/**/*.py`)
release workflow 加密 `scripts/` 源码时,可能运行在 PyArmor 免费/试用模式:
- `scripts/**/*.py` 单文件必须 **< 1000 行**(`>= 1000` 可能在 CI 失败);推荐 **< 900 行**。这是预防性硬门槛,不代表低于该行数就一定能被 Trial 加密。
- 模块应按职责拆分到 `cli/`、`service/`、`db/`、`util/`;不要把 RPA 主流程、选择器、DB、CLI 堆进单文件。发现某个文件在免费 Trial 加密时报错时,按报错定位该文件并继续拆分其职责,重新走实际加密验证;不要通过猜测统一的源码字节数阈值代替验证。
- 拆分已有模块时,尽量保留原模块作为兼容门面(re-export / 委托到新模块),避免破坏现有 import 路径;先跑测试,再发布验证。
- 发布验收以 Gitea release workflow 中实际的 PyArmor Trial 加密结果为准:确认全部 `scripts/**/*.py` 均成功加密、加密包成功生成/上传且 job 成功。若 PyArmor 步骤失败,不得把版本视为已发布成功;按日志中的失败文件拆分、升补丁版本并重新 release。
- 此行数限制**仅适用于** `scripts/**/*.py`;不限制 README 等文档行数,也不把 examples 里的 HTML/README 纳入 PyArmor 行数约束。