docs: document JobStopped and lease cleanup contract for interrupt
All checks were successful
技能自动化发布 / release (push) Successful in 7s

This commit is contained in:
2026-09-17 13:26:28 +08:00
parent db2ed089a3
commit 2a3e971c76
10 changed files with 41 additions and 9 deletions

View File

@@ -122,6 +122,26 @@ RPA 等待用 `interruptible_sleep`,**不要**裸 `asyncio.sleep`(否则暂
Journal 会写入 `type: lifecycle` 事件(`paused` / `resumed` / `stopping`),供宿主任务中心显示状态。
**宿主中断(`stop`)与 `JobStopped`(必读):**
- 用户在任务中心点「中断」时,宿主写入 `control.json` `command=stop`,并**等待技能进程协作退出**(超时后才可能强杀)。
- 技能在 `emit` / `checkpoint` / `interruptible_sleep` / `rpa_step` 等闸门处会抛出 `JobStopped`;业务代码须让其冒泡到 `job_context` / 外层 `finally`,由技能**自己**释放租约、关闭浏览器等资源。
- **禁止**用裸 `except Exception:` 包住上述闸门调用。`JobStopped` 是 `Exception` 子类,会被吞掉,导致 UI 已停、进程仍占账号租约,下次采集必 `LEASE_CONFLICT`。
- 若必须兜底「emit 写 Journal 失败」,正确写法:
```python
from jiangchang_skill_core.activity import JobStopped, emit
try:
emit("正在处理…", skill=SKILL_SLUG, stage="fetch")
except JobStopped:
raise
except Exception:
log.debug("emit_failed", exc_info=True)
```
- 宿主**不会**按技能类型统一代收 account-manager 租约(许多技能根本不用账号管理)。强杀后的残留靠租约 TTL / 数据管理手工 force-release;主路径必须是技能自清。
### 2.3 可观测性三分法(禁止 task_logs)
| 信息类型 | 去哪里 | 技能怎么做 |