Add DATA_PATHS golden standard and resolve_data_path helpers.
All checks were successful
技能自动化发布 / release (push) Successful in 5s

Document skill-owned file layout under user data dir, extend runtime_paths with standard subdir helpers, add POLICY-DATA-PATH-001, and update CONFIG/RUNTIME cross-references.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-13 14:14:38 +08:00
parent 6f958ded28
commit 2e5a8d5eed
11 changed files with 415 additions and 7 deletions

160
development/DATA_PATHS.md Normal file
View File

@@ -0,0 +1,160 @@
# 用户数据目录与文件路径黄金标准
> 本文是 skill **读写本地文件** 的权威约定。凡涉及下载、导入、导出、缓存、RPA 存证等路径复制模板后须遵守本文Agent 实现业务 skill 时也应先读本文。
---
## 1. 根目录
所有技能持久化数据(配置、数据库、业务文件)默认落在:
```text
{JIANGCHANG_DATA_ROOT}/{JIANGCHANG_USER_ID}/{skill_slug}/
```
示例:
```text
D:\jiangchang-data\12500\download-video-baidu-haokan\
```
实现:`util.runtime_paths.get_skill_data_dir()`
**禁止**把技能自己写入的文件落到:
- Agent / 宿主 **workspace**(进程 CWD
- 技能安装目录(含 `.openclaw/skills/...`
- 未在本文声明的任意相对 CWD 路径
---
## 2. 标准子目录树
| 子目录 | 用途 | 默认 helper |
|--------|------|-------------|
| `downloads/` | 从外部拉取的原始文件视频、回单、PDF… | `get_downloads_dir()` |
| `imports/` | 用户/Agent 放入的待处理清单urls.txt、batch.json、CSV | `get_imports_dir()` |
| `exports/` | 导出给用户的结果xlsx/csv/json | `get_exports_dir()` |
| `uploads/` | 待发布到外部平台的 staging可选 | `get_uploads_dir()` |
| `cache/` | 可再生缓存(页面快照、解析中间结果) | `get_cache_dir()` |
| `temp/` | 单次任务 scratch任务结束可删 | `get_temp_dir()` |
| `rpa-artifacts/` | RPA 失败截图、录屏中间产物 | `get_rpa_artifacts_dir(batch_id)` |
| `videos/` | RPA 录屏成片 MP4 | `get_videos_dir()` |
| `{skill_slug}.db` | SQLite | `get_db_path()` |
| `.env` | 用户配置 | `config.get_env_file_path()` |
复制后若业务不需要某目录,可不创建;**但一旦写入该类文件,必须走对应 helper**。
---
## 3. 两类路径
### A. 技能拥有skill-owned
技能**创建或更新**的文件:下载结果、导出报表、失败截图、队列 sidecar 等。
- **默认**必须在 `{skill_data_dir}/<子目录>/` 下。
- **必须**通过 `resolve_data_path()``get_*_dir()` 解析,**禁止** `os.path.abspath(config.get(...))` 相对 CWD。
### B. 用户显式输入user-owned
用户在 CLI / Agent 对话中给出的**已有文件**绝对路径,例如「发布这个视频 `D:\素材\x.mp4`」。
- 技能**只读**,路径可以是用户磁盘任意位置。
- 使用 `resolve_input_path()`:绝对路径原样;**相对路径**解析为 `{skill_data_dir}/imports/<相对路径>`**不**相对 workspace/CWD。
---
## 4. 配置项(`.env`
可选覆盖项(**留空则用默认子目录**
```ini
# ── 数据目录子路径(见 development/DATA_PATHS.md──
# 相对路径相对于 {JIANGCHANG_DATA_ROOT}/{USER_ID}/{slug}/,不是 workspace
# SKILL_DOWNLOAD_DIR=downloads/videos
# SKILL_IMPORT_DIR=imports
# SKILL_EXPORT_DIR=exports
# SKILL_UPLOAD_DIR=uploads
# SKILL_CACHE_DIR=cache
# SKILL_TEMP_DIR=temp
```
| 规则 | 说明 |
|------|------|
| 未配置 | `{skill_data_dir}/{default_subdir}` |
| 相对值 `downloads/videos` | `{skill_data_dir}/downloads/videos` |
| 绝对值 `D:\nas\exports` | 高级用户/NAS 挂载,原样使用 |
| **禁止** `./outputs/...` | 会随 CWD 漂移,不得作为 `.env.example` 活跃配置行 |
业务专属路径 env key 须带 **`SKILL_` 前缀**(或技能 slug 前缀),避免污染全局命名空间。
---
## 5. 代码用法
```python
from util.runtime_paths import (
get_downloads_dir,
get_imports_dir,
resolve_data_path,
resolve_input_path,
list_resolved_data_paths,
)
# 下载保存A 类)
dest = os.path.join(get_downloads_dir(), f"{vid}.mp4")
# 或带 env 覆盖
out_dir = resolve_data_path("SKILL_DOWNLOAD_DIR", "downloads")
# CLI -i urls.txtB 类,相对路径 → imports/
manifest = resolve_input_path(args.input_path)
# health 诊断
paths = list_resolved_data_paths()
```
**反模式(禁止):**
```python
# ❌ 相对 CWDAgent 从 workspace 执行时会写错盘
os.path.abspath(config.get("DOWNLOAD_OUTPUT_DIR"))
# ❌ .env.example 里写 ./outputs/videos
DOWNLOAD_OUTPUT_DIR=./outputs/videos
```
---
## 6. health / config-path
`health``config-path` 建议输出 `list_resolved_data_paths()` 中的路径,便于排查「文件写到哪里去了」。展示路径须与 `run` 实际使用的一致。
---
## 7. 与 RPA 存证的关系
- 失败截图、录屏中间文件:`rpa-artifacts/{batch_id}/`(见 [`RPA.md`](RPA.md) §5.1
- 录屏成片:`videos/`(见 [`RPA.md`](RPA.md) §5.3
业务 `downloads/` 与 RPA `videos/` **分工不同**:前者是业务产出文件,后者是操作过程录屏。
---
## 8. 测试
- 单元测试须用 `IsolatedDataRoot`,断言路径落在临时数据根下。
- `tests/test_runtime_paths.py` 覆盖 `resolve_data_path` / `resolve_input_path`
- `POLICY-DATA-PATH-001`:禁止 `.env.example``./` 路径;禁止业务代码 `abspath(config.get(...))`
---
## 9. 相关文档
| 文档 | 内容 |
|------|------|
| [`RUNTIME.md`](RUNTIME.md) | 数据根、共享 runtime、编码 |
| [`CONFIG.md`](CONFIG.md) | `.env` bootstrap 与三层优先级 |
| [`RPA.md`](RPA.md) | rpa-artifacts / videos 存证 |
| [`POLICY_MATRIX.md`](POLICY_MATRIX.md) | POLICY-DATA-PATH-001 |