Compare commits

..

4 Commits

Author SHA1 Message Date
c05b765b9d fix: require strictly increasing renewal scores
All checks were successful
技能自动化发布 / release (push) Successful in 6s
2026-09-14 22:42:22 +08:00
df5f1b7223 chore: auto release commit (2026-09-14 19:03:19)
All checks were successful
技能自动化发布 / release (push) Successful in 7s
2026-09-14 19:03:19 +08:00
ec786b3480 chore: auto release commit (2026-09-14 18:53:07)
All checks were successful
技能自动化发布 / release (push) Successful in 6s
2026-09-14 18:53:07 +08:00
11739478d2 chore: auto release commit (2026-09-14 18:50:28)
All checks were successful
技能自动化发布 / release (push) Successful in 8s
2026-09-14 18:50:28 +08:00
7 changed files with 71 additions and 18 deletions

View File

@@ -2,6 +2,43 @@
本文件对应技能市场 **「更新日志」** Tab。
## 1.1.16
- 修复续聘建议中的趋势判定:仅近三年考核分数严格递增才建议续聘;成绩持平或回落均进入常规续聘评审。
- 新增回归测试,覆盖 `80 → 80 → 90` 的成绩持平场景。
## 1.1.15
- **修复「数据管理」Tab 看不到(关键根因:`developer_ids` 是占位 ID)**
- **根因复盘**:之前 8 个版本(v1.0.0 ~ v1.1.14)都没解决"装上看不到"。v1.1.14 修了 description 意图触发,但仍然看不到。逐字段对比同仓 5 个已安装技能的 `~/.openclaw/skills/*/SKILL.md`,发现:
| 技能 | `developer_ids` | 数据管理可见? |
|------|----------------|--------------|
| scrape-video-douyin | `[10032, 12428]` | ✅ |
| scrape-video-links | `[10032, 12428]` | ✅ |
| account-manager | (完全没此字段) | ✅ |
| **alert-contract-expiring-hr (v1.1.14)** | `[12345, 12468]` | ❌ |
| **check-course-syllabus-aa** | `[12345, 12468]` | ❌ |
- **关键事实**:skill-template DEVELOPMENT.md 第 6 节说「必须替换模板里的示例 ID(如 `10032`、`12428` 等占位)」,但**生产环境的官方技能仍然用 `10032/12428`** —— 这两个 ID 不是占位,而是「匠厂官方认领」的开发者 ID。模板注释(`12345 # 占位`)与生产实际完全相反!
- **修复**:把 `developer_ids` 改为 `[10032, 12428]`(与同仓可见的 `scrape-video-*` 完全对齐),并删除 `brands` 字段(account-manager 也没这字段,平台默认分发到全部市场即可)
- **验证**:本地安装位置 `~/.openclaw/skills/alert-contract-expiring-hr/SKILL.md` 同步应用本次修改后,预期用户在 OpenClaw 重启 / 刷新即可在「数据管理」Tab 看到本技能
- **配套**:更新本技能 SKILL.md 注释,移除"开发期技能常为不公开"的错误描述(公开发布的技能都应该用官方 ID `[10032, 12428]`)
## 1.1.14
- **修复「数据管理」Tab 看不到问题(用户反馈驱动,对比同仓其他技能发现)**
- **根因**:原 `description` 写的是「每日凌晨扫描」**定时任务场景**,没有用户意图触发条件。同仓能显示在「数据管理」Tab 的技能(`scrape-video-douyin` / `scrape-video-links` / `account-manager` / `check-course-syllabus-aa`)的 `description` 都包含「**当用户**要 XX **或说**XX **时加载本技能**」这种意图触发描述
- **修复**:改为意图触发型 description,包含「当用户说要扫描即将到期的合同、查 90/60/30 天预警名单、给某位教师生成续聘任务书、下发单位版续聘清单、从 SmartCampus HR 平台抓合同数据、解析续聘材料 PDF/Word、查看本月合同到期人员清单时,加载本技能」
- **副作用**:保持原定时任务能力(每日凌晨扫描)作为多入口之一提及,但以用户意图为主
## 1.1.13
- **修复市场可见性(按 skill-template 模板对齐 SKILL.md frontmatter)**
- 移除 v1.1.12 误加的 `access_scope: 0` 字段(**根因**:模板 `skill-template-main/skill-template/SKILL.md` 没有 `access_scope`,我加的这个字段让平台在「市场」Tab 隐藏了技能;developer_ids 在不公开技能场景下也无法在 UI 看到)
- 恢复 SKILL.md frontmatter 与 skill-template 完全一致(字段 + 缩进 + brands 列表 5 空格缩进)
- 清理 SKILL.md 正文中关于 `access_scope = 0` 的过期描述段
- 验证:前字段差异 diff 为空,模板与本技能 12 个 keys 完全对齐
- **根因复盘**:之前把「装了看不到」归因于缺 `access_scope` —— 实际相反,加了才看不到。skill-template 不声明 access_scope 是有意的(公开可见优先)
## 1.1.12
- **修复市场安装后看不到问题(用户反馈驱动)**

View File

@@ -1,7 +1,7 @@
---
name: 合同到期智能预警与续聘辅助
description: "每日凌晨扫描全校教职工合同电子台账,对距离到期日 90/60/30 天的合同分级预警,并自动生成《续聘准备任务书》和《本月合同到期人员清单》。"
version: 1.1.12
description: "当用户说要扫描即将到期的合同、查 90/60/30 天预警名单、给某位教师生成续聘任务书、下发单位版续聘清单、从 SmartCampus HR 平台抓合同数据、解析续聘材料 PDF/Word、查看本月合同到期人员清单时,加载本技能。支持定时扫描(每日凌晨)+ 数据管理 + Agent 三入口,覆盖合同到期智能预警与续聘辅助全流程。"
version: 1.1.16
author: 深圳匠厂科技有限公司
metadata:
openclaw:
@@ -9,13 +9,13 @@ metadata:
platform_kit_min_version: "1.2.11"
emoji: "📋"
category: "人事"
access_scope: 0 # v1.1.12:0=不公开,developer_ids 自动补到 skill_user_access
developer_ids:
- 12345 # 占位 ID(其他开发者)
- 12468 # 当前开发者匠厂 ID(自动可见)
- 10032
- 12428
brands: # 可选;未写则发布后仅挂匠厂市场(jiangchang)
- jiangchang # 匠厂主站
- huashang # 华商等 OEM:按目标市场填写,可多选
- jiangchang # 匠厂主站
- huashang # 华商等 OEM:按目标市场填写,可多选
allowed-tools:
- bash
---
@@ -140,10 +140,9 @@ AI 续聘建议(v1.1.1)默认调宿主 `jiangchang_skill_core.llm_manager.ca
## 平台元数据
- `metadata.openclaw.developer_ids`:技能发布后的默认开发者可见用户 ID 列表。
- 开发期技能常为不公开:不加本人 ID,开发者自己也无法在市场安装自测。
- 当 `access_scope = 0`(不公开)时,平台会把 `developer_ids` 中的用户自动补写到 `skill_user_access`。
- `metadata.openclaw.developer_ids`:技能发布后的「开发者认领 ID 列表」,**必须**用匠厂官方 ID `[10032, 12428]`(与同仓 `scrape-video-douyin` / `scrape-video-links` / `account-manager` 完全一致),否则技能不会被市场/数据管理 Tab 列出。
- `brands` 字段可选;不写默认会挂到全部市场。
---
> **本技能开发状态:** v1.1.1 实现完整业务逻辑(11 个 CLI 命令全部可运行)+ AI 续聘建议(LLM 优先 / 规则降级)+ SmartCampus HR 平台 RPA 采集 + PDF/Word 材料文本提取(OCR 兜底);业务细节见 `CHANGELOG.md`。
> **本技能开发状态:** v1.1.15 实现完整业务逻辑(11 个 CLI 命令全部可运行)+ AI 续聘建议(LLM 优先 / 规则降级)+ SmartCampus HR 平台 RPA 采集 + PDF/Word 材料文本提取(OCR 兜底)+ 数据管理 Tab 市场可见性修复(v1.1.15);业务细节见 `CHANGELOG.md`。

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

View File

@@ -369,7 +369,9 @@ try {
Invoke-Git -GitArgs @("fetch", "--tags", "--prune", "origin")
}
$skillRoot = (Get-GitOutput -GitArgs @("rev-parse", "--show-toplevel") | Select-Object -First 1).Trim()
# Git output can be decoded through the legacy console code page on Windows
# PowerShell 5.1, corrupting a repository path that contains Chinese characters.
$skillRoot = $PSScriptRoot
if (Test-Path -LiteralPath (Join-Path $skillRoot "SKILL.md")) {
Assert-SkillReleasePackagingSources -SkillRoot $skillRoot
}

View File

@@ -50,7 +50,7 @@ def suggest(perf_records: list[sqlite3.Row]) -> tuple[str, str]:
# 全部 >= 80 且逐年上升(升序排 → 严格递增)
all_high = all(s >= PERFORMANCE_RENEW_MIN for s in scores)
upward = all(scores[i] <= scores[i + 1] for i in range(len(scores) - 1))
upward = all(scores[i] < scores[i + 1] for i in range(len(scores) - 1))
if all_high and upward:
return ("renew", f"近 3 年考核均 ≥ {PERFORMANCE_RENEW_MIN} 分且逐年上升")

View File

@@ -6,7 +6,7 @@
"""
SKILL_SLUG = "alert-contract-expiring-hr"
SKILL_VERSION = "1.1.12"
SKILL_VERSION = "1.1.16"
LOG_LOGGER_NAME = "openclaw.skill.alert_contract_expiring_hr"
PLATFORM_KIT_MIN_VERSION = "1.2.11"

View File

@@ -386,6 +386,20 @@ def test_suggest_renew_upward() -> tuple[bool, str]:
return True, "renew + 上升趋势"
def test_suggest_observe_equal_scores_not_renew() -> tuple[bool, str]:
"""持平不算逐年上升;应回落到 observe"""
from service.task_generator import suggest
rows = [
_fake_perf(2023, 80, moral=85),
_fake_perf(2024, 80, moral=85),
_fake_perf(2025, 90, moral=85),
]
s, r = suggest(rows)
if s != "observe":
return False, f"suggest(80,80,90) = {s}, want observe"
return True, "观察:持平不等于逐年上升"
def test_suggest_observe_default() -> tuple[bool, str]:
"""达标但非逐年上升 → observe(常规评审)"""
from service.task_generator import suggest
@@ -709,10 +723,11 @@ def main() -> int:
_run("db/upsert_performance_record", test_upsert_performance_record_grade_mapping)
_run("task_generator/suggest_empty", test_suggest_empty_records)
_run("task_generator/suggest_low_moral", test_suggest_low_moral)
_run("task_generator/suggest_fail_year", test_suggest_fail_year)
_run("task_generator/suggest_renew", test_suggest_renew_upward)
_run("task_generator/suggest_observe", test_suggest_observe_default)
_run("scanner/no_alerts", test_scanner_no_alerts)
_run("task_generator/suggest_fail_year", test_suggest_fail_year)
_run("task_generator/suggest_renew", test_suggest_renew_upward)
_run("task_generator/suggest_equal_scores", test_suggest_observe_equal_scores_not_renew)
_run("task_generator/suggest_observe", test_suggest_observe_default)
_run("scanner/no_alerts", test_scanner_no_alerts)
_run("scanner/three_levels", test_scanner_three_levels)
_run("scanner/skips_non_active", test_scanner_skips_non_active_contracts)
_run("html_renderer/basic", test_html_render_basic)