chore: auto release commit (2026-09-14 23:55:58)
All checks were successful
技能自动化发布 / release (push) Successful in 6s
All checks were successful
技能自动化发布 / release (push) Successful in 6s
This commit is contained in:
@@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
本文件对应技能市场 **「更新日志」** Tab。
|
本文件对应技能市场 **「更新日志」** Tab。
|
||||||
|
|
||||||
|
## 1.1.17
|
||||||
|
|
||||||
|
- 补齐数据管理的“立即同步合同台账”工具栏入口,调用 SmartCampus 平台采集能力。
|
||||||
|
- 补齐合同业务行状态规范,并增加 Action 声明与 CLI 命令一致性的发布前校验。
|
||||||
|
- 平台采集默认显示浏览器,登录态失效时可直接手工登录;自动化任务须显式传 `--headless`。
|
||||||
|
|
||||||
## 1.1.16
|
## 1.1.16
|
||||||
|
|
||||||
- 修复续聘建议中的趋势判定:仅近三年考核分数严格递增才建议续聘;成绩持平或回落均进入常规续聘评审。
|
- 修复续聘建议中的趋势判定:仅近三年考核分数严格递增才建议续聘;成绩持平或回落均进入常规续聘评审。
|
||||||
|
|||||||
2
SKILL.md
2
SKILL.md
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: 合同到期智能预警与续聘辅助
|
name: 合同到期智能预警与续聘辅助
|
||||||
description: "当用户说要扫描即将到期的合同、查 90/60/30 天预警名单、给某位教师生成续聘任务书、下发单位版续聘清单、从 SmartCampus HR 平台抓合同数据、解析续聘材料 PDF/Word、查看本月合同到期人员清单时,加载本技能。支持定时扫描(每日凌晨)+ 数据管理 + Agent 三入口,覆盖合同到期智能预警与续聘辅助全流程。"
|
description: "当用户说要扫描即将到期的合同、查 90/60/30 天预警名单、给某位教师生成续聘任务书、下发单位版续聘清单、从 SmartCampus HR 平台抓合同数据、解析续聘材料 PDF/Word、查看本月合同到期人员清单时,加载本技能。支持定时扫描(每日凌晨)+ 数据管理 + Agent 三入口,覆盖合同到期智能预警与续聘辅助全流程。"
|
||||||
version: 1.1.16
|
version: 1.1.17
|
||||||
author: 深圳匠厂科技有限公司
|
author: 深圳匠厂科技有限公司
|
||||||
metadata:
|
metadata:
|
||||||
openclaw:
|
openclaw:
|
||||||
|
|||||||
@@ -53,6 +53,21 @@
|
|||||||
"args": ["--thresholds", "90,60,30"]
|
"args": ["--thresholds", "90,60,30"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "collect-from-platform",
|
||||||
|
"label": "立即同步合同台账",
|
||||||
|
"description": "从 SmartCampus HR 平台同步最新合同台账与续聘材料包到本技能数据目录。",
|
||||||
|
"placements": ["toolbar", "agent"],
|
||||||
|
"executionProfile": "async",
|
||||||
|
"bind": {
|
||||||
|
"tables": ["合同台账"]
|
||||||
|
},
|
||||||
|
"entrypoint": {
|
||||||
|
"type": "cli",
|
||||||
|
"command": "collect-from-platform",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "generate-renewal-task",
|
"id": "generate-renewal-task",
|
||||||
"label": "生成续聘任务书",
|
"label": "生成续聘任务书",
|
||||||
|
|||||||
14
references/WORK_ITEM_STATUS.md
Normal file
14
references/WORK_ITEM_STATUS.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# 合同台账业务行状态规范
|
||||||
|
|
||||||
|
本规范定义“合同台账”中每条合同可由数据管理动作处理的状态边界。
|
||||||
|
|
||||||
|
| 状态 | 角色 | 允许的动作 | 说明 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 可续聘 | 可操作 | 同步、扫描、生成续聘任务书、下发通知、标记已续签 | 默认初始状态。 |
|
||||||
|
| 预警中 | 进行中 | 同步、生成续聘任务书、下发通知、标记已续签 | 已产生黄、橙或红色预警。 |
|
||||||
|
| 已续签 | 成功终态 | 同步 | 续签材料已确认,关联 open 预警必须关闭。 |
|
||||||
|
| 已驳回 | 失败终态 | 同步 | 不再自动生成任务或派发通知。 |
|
||||||
|
| 已过期 | 失败终态 | 同步 | 合同已到期,保留记录供人工处置。 |
|
||||||
|
| 已撤回 | 跳过终态 | 同步 | 教师或单位撤回续聘申请。 |
|
||||||
|
|
||||||
|
状态由人事处人工复核后可回退至“可续聘”;自动任务不得覆盖成功、失败或撤回终态。
|
||||||
@@ -198,8 +198,8 @@ def cmd_render_html(args: argparse.Namespace) -> int:
|
|||||||
def cmd_collect_platform(args: argparse.Namespace) -> int:
|
def cmd_collect_platform(args: argparse.Namespace) -> int:
|
||||||
"""Playwright RPA 抓 SmartCampus HR 平台数据 → 落库。
|
"""Playwright RPA 抓 SmartCampus HR 平台数据 → 落库。
|
||||||
|
|
||||||
首次需用户手工登录保存 cookie(默认 headless=False 便于交互);
|
默认显示浏览器,以便登录态失效时可立即手工登录;
|
||||||
后续可用 headless=True 复用 profile。
|
传 --headless 可复用已保存的 profile 进行无头采集。
|
||||||
|
|
||||||
退出码:
|
退出码:
|
||||||
0 = 成功(即使抓到 0 行也返回 0,错误信息在 output["error"])
|
0 = 成功(即使抓到 0 行也返回 0,错误信息在 output["error"])
|
||||||
@@ -209,7 +209,7 @@ def cmd_collect_platform(args: argparse.Namespace) -> int:
|
|||||||
try:
|
try:
|
||||||
result = platform_collector.collect_all(
|
result = platform_collector.collect_all(
|
||||||
limit=args.limit,
|
limit=args.limit,
|
||||||
headless=not args.show_browser,
|
headless=args.headless,
|
||||||
human_wait_timeout=args.human_wait_timeout or HUMAN_WAIT_TIMEOUT,
|
human_wait_timeout=args.human_wait_timeout or HUMAN_WAIT_TIMEOUT,
|
||||||
)
|
)
|
||||||
except platform_collector.RPAError as e:
|
except platform_collector.RPAError as e:
|
||||||
@@ -344,8 +344,11 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
)
|
)
|
||||||
sp.add_argument("--limit", type=int, default=0,
|
sp.add_argument("--limit", type=int, default=0,
|
||||||
help="限制抓取行数(0=全量)")
|
help="限制抓取行数(0=全量)")
|
||||||
sp.add_argument("--show-browser", action="store_true",
|
browser_mode = sp.add_mutually_exclusive_group()
|
||||||
help="显示浏览器(首次手工登录用,默认 headless)")
|
browser_mode.add_argument("--headless", action="store_true",
|
||||||
|
help="无头运行(仅适合已保存有效登录态的自动化任务)")
|
||||||
|
browser_mode.add_argument("--show-browser", dest="headless", action="store_false",
|
||||||
|
help=argparse.SUPPRESS)
|
||||||
sp.add_argument("--human-wait-timeout", type=int, default=None,
|
sp.add_argument("--human-wait-timeout", type=int, default=None,
|
||||||
help="手工登录 fallback 等待秒数(默认 180 = HUMAN_WAIT_TIMEOUT)")
|
help="手工登录 fallback 等待秒数(默认 180 = HUMAN_WAIT_TIMEOUT)")
|
||||||
sp.set_defaults(handler=cmd_collect_platform)
|
sp.set_defaults(handler=cmd_collect_platform)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
SKILL_SLUG = "alert-contract-expiring-hr"
|
SKILL_SLUG = "alert-contract-expiring-hr"
|
||||||
SKILL_VERSION = "1.1.16"
|
SKILL_VERSION = "1.1.17"
|
||||||
LOG_LOGGER_NAME = "openclaw.skill.alert_contract_expiring_hr"
|
LOG_LOGGER_NAME = "openclaw.skill.alert_contract_expiring_hr"
|
||||||
PLATFORM_KIT_MIN_VERSION = "1.2.11"
|
PLATFORM_KIT_MIN_VERSION = "1.2.11"
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ test_* 返回 (False, msg) 即 abort 发布。
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
@@ -217,6 +218,49 @@ def test_skill_md_slug_alignment() -> tuple[bool, str]:
|
|||||||
return True, f"slug={md_slug}"
|
return True, f"slug={md_slug}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_data_management_actions() -> tuple[bool, str]:
|
||||||
|
"""数据管理动作必须绑定业务表,并映射到实际 CLI 命令。"""
|
||||||
|
actions_path = _REPO_ROOT / "assets" / "actions.json"
|
||||||
|
actions = json.loads(actions_path.read_text(encoding="utf-8"))["actions"]
|
||||||
|
by_id = {action["id"]: action for action in actions}
|
||||||
|
|
||||||
|
expected = {
|
||||||
|
"scan-expiring-contracts": "toolbar",
|
||||||
|
"collect-from-platform": "toolbar",
|
||||||
|
"generate-renewal-task": "row",
|
||||||
|
"dispatch-task-notice": "batch",
|
||||||
|
"mark-contract-renewed": "row",
|
||||||
|
}
|
||||||
|
for action_id, placement in expected.items():
|
||||||
|
action = by_id.get(action_id)
|
||||||
|
if not action:
|
||||||
|
return False, f"缺少数据管理动作 {action_id}"
|
||||||
|
if placement not in action.get("placements", []):
|
||||||
|
return False, f"{action_id} 缺少 {placement} placement"
|
||||||
|
if "合同台账" not in action.get("bind", {}).get("tables", []):
|
||||||
|
return False, f"{action_id} 未绑定合同台账"
|
||||||
|
if action.get("entrypoint", {}).get("command") != action_id:
|
||||||
|
return False, f"{action_id} CLI command 映射错误"
|
||||||
|
return True, "5 个数据管理动作均绑定合同台账并映射到 CLI"
|
||||||
|
|
||||||
|
|
||||||
|
def test_collect_platform_defaults_to_browser() -> tuple[bool, str]:
|
||||||
|
"""平台采集默认显示浏览器;--headless 仅用于已登录自动化。"""
|
||||||
|
from cli.app import build_parser
|
||||||
|
|
||||||
|
parser = build_parser()
|
||||||
|
default_args = parser.parse_args(["collect-from-platform"])
|
||||||
|
if default_args.headless:
|
||||||
|
return False, "collect-from-platform 默认不应使用无头模式"
|
||||||
|
headless_args = parser.parse_args(["collect-from-platform", "--headless"])
|
||||||
|
if not headless_args.headless:
|
||||||
|
return False, "--headless 未启用无头模式"
|
||||||
|
legacy_args = parser.parse_args(["collect-from-platform", "--show-browser"])
|
||||||
|
if legacy_args.headless:
|
||||||
|
return False, "--show-browser 兼容别名未保留浏览器模式"
|
||||||
|
return True, "默认浏览器模式,--headless 和 --show-browser 行为正确"
|
||||||
|
|
||||||
|
|
||||||
# ---------- db.repository:v1.1.2 新增的 sandbox card 解析 ----------
|
# ---------- db.repository:v1.1.2 新增的 sandbox card 解析 ----------
|
||||||
|
|
||||||
def test_parse_sandbox_card_row_format() -> tuple[bool, str]:
|
def test_parse_sandbox_card_row_format() -> tuple[bool, str]:
|
||||||
@@ -716,6 +760,8 @@ def main() -> int:
|
|||||||
_run("util/month_match", test_month_match)
|
_run("util/month_match", test_month_match)
|
||||||
_run("constants/skill_md_version_alignment", test_skill_md_version_alignment)
|
_run("constants/skill_md_version_alignment", test_skill_md_version_alignment)
|
||||||
_run("constants/skill_md_slug_alignment", test_skill_md_slug_alignment)
|
_run("constants/skill_md_slug_alignment", test_skill_md_slug_alignment)
|
||||||
|
_run("assets/data_management_actions", test_data_management_actions)
|
||||||
|
_run("cli/collect_platform_browser_default", test_collect_platform_defaults_to_browser)
|
||||||
_run("db/parse_sandbox_card_row", test_parse_sandbox_card_row_format)
|
_run("db/parse_sandbox_card_row", test_parse_sandbox_card_row_format)
|
||||||
_run("db/parse_sandbox_card_narrative", test_parse_sandbox_card_narrative_format)
|
_run("db/parse_sandbox_card_narrative", test_parse_sandbox_card_narrative_format)
|
||||||
_run("db/parse_sandbox_card_empty_invalid", test_parse_sandbox_card_empty_and_invalid)
|
_run("db/parse_sandbox_card_empty_invalid", test_parse_sandbox_card_empty_and_invalid)
|
||||||
|
|||||||
Reference in New Issue
Block a user