From 4f91e8f85ee3c0274642003711113b9ea1c673d6 Mon Sep 17 00:00:00 2001 From: can4hou6joeng4 Date: Wed, 10 Jun 2026 23:44:13 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E8=A1=A5=E5=85=85=E5=B9=B3=E5=8F=B0?= =?UTF-8?q?=E8=83=BD=E5=8A=9B=E7=8A=B6=E6=80=81=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + README.en.md | 9 +++++++ README.md | 9 +++++++ src/boss_agent_cli/commands/platforms.py | 25 ++++++++++++++++++ tests/test_platforms_cmd.py | 33 ++++++++++++++++++++++++ 5 files changed, 77 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 190f56a..bf87f86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ### Added - `boss platforms` 新增 `--platform` 单平台过滤,支持 `qiancheng` 与 `51job` 别名,仅读取本地能力元数据并保持未知平台的 `INVALID_PARAM` JSON 包络。 +- `boss platforms` 输出新增 `capability_status_legend`,解释 `available` / `not_supported` / `placeholder_only` / `low_risk_blocked` 的清晰语义,避免 Agent 将占位或低风险阻断误读为真实能力。 ### Changed - 补强 `boss config` 未知配置项错误路径的 stdout 单行 JSON 包络契约测试,确保 Agent 可稳定解析 `INVALID_PARAM`。 diff --git a/README.en.md b/README.en.md index e00ca45..4bb89f1 100644 --- a/README.en.md +++ b/README.en.md @@ -162,6 +162,15 @@ boss-agent-cli covers both the job-seeker and the recruiter side, with a pluggab | Zhaopin (`zhilian`) | 🟡 candidate-side login + read/write flow wired | — | recruiter side is still intentionally unavailable at runtime | | 51job (`qiancheng`) | 🚧 registered placeholder | — | returns `NOT_SUPPORTED` until the read-only research gate is satisfied | +`boss platforms` includes `capability_status_legend` in both JSON and terminal output so agents can interpret capability states clearly: + +| State | Meaning | +|-------|---------| +| `available` | The local CLI has wired this capability; login requirements still follow the concrete command contract | +| `not_supported` | The current platform adapter does not implement this real workflow; the CLI returns a stable `NOT_SUPPORTED` envelope | +| `placeholder_only` | Registered only for platform identity, aliases, schema/config visibility; it does not mean a real platform capability is wired | +| `low_risk_blocked` | Write actions, sensitive data, or platform-risk boundaries are involved; default low-risk mode blocks the action and points users back to the official UI | + ```bash # pick a platform boss --platform zhilian search "Python" diff --git a/README.md b/README.md index f249166..caffa3a 100644 --- a/README.md +++ b/README.md @@ -291,6 +291,15 @@ boss hr candidates "Golang" | 智联招聘 (`zhilian`) | 🟡 候选者侧登录 + 读写链路已接通 | — | 招聘者侧未接入,运行时会直接拒绝 `hr` 子命令 | | 前程无忧 / 51job (`qiancheng`) | 🚧 已注册占位 | — | 统一返回 `NOT_SUPPORTED`,待只读研究门槛满足后再接入真实能力 | +`boss platforms` 会在 JSON 与终端输出中附带 `capability_status_legend`,用于解释能力状态: + +| 状态 | 语义 | +|------|------| +| `available` | 本地 CLI 已接入该能力;是否需要登录仍以具体命令契约为准 | +| `not_supported` | 当前平台适配器没有实现该真实工作流;CLI 会稳定返回 `NOT_SUPPORTED` | +| `placeholder_only` | 仅用于平台注册、别名、schema/config 可见性;不代表真实平台能力已接入 | +| `low_risk_blocked` | 涉及写操作、敏感数据或平台风险边界;默认低风险模式阻断并提示回到官方页面手动处理 | + ```bash # 指定平台 boss --platform zhilian search "Python" diff --git a/src/boss_agent_cli/commands/platforms.py b/src/boss_agent_cli/commands/platforms.py index 5d07086..df69a0e 100644 --- a/src/boss_agent_cli/commands/platforms.py +++ b/src/boss_agent_cli/commands/platforms.py @@ -41,6 +41,26 @@ }, } +_CAPABILITY_STATUS_LEGEND: dict[str, dict[str, str]] = { + "available": { + "label": "可用", + "description": "本地 CLI 已接入该能力;是否需要登录仍以具体命令契约为准。", + }, + "not_supported": { + "label": "不支持", + "description": "当前平台适配器没有实现该真实工作流;CLI 会稳定返回 NOT_SUPPORTED。", + }, + "placeholder_only": { + "label": "仅占位", + "description": "仅用于平台注册、别名、schema/config 可见性;不代表真实平台能力已接入。", + }, + "low_risk_blocked": { + "label": "低风险模式阻断", + "description": "涉及写操作、敏感数据或平台风险边界;默认低风险模式阻断并提示回到官方页面手动处理。", + }, +} + + _PLATFORM_NOTES = { "zhipin": "默认平台;候选者侧与招聘者侧注册表均已接入。", "zhilian": "候选者侧只读链路已接入;招聘者侧暂不可用。", @@ -96,6 +116,7 @@ def platform_capability_data(platform_name: str | None = None) -> dict[str, Any] "count": len(platforms), "default": "zhipin", "aliases": {"51job": "qiancheng"}, + "capability_status_legend": _CAPABILITY_STATUS_LEGEND, "platforms": platforms, } @@ -106,6 +127,10 @@ def _render_platforms(data: dict[str, Any]) -> None: candidate = "yes" if item["candidate"] else "no" recruiter = "yes" if item["recruiter"] else "no" lines.append(f"{item['name']}\t{item['display_name']}\t{item['status']}\t{candidate}\t{recruiter}") + lines.append("") + lines.append("capability_status_legend") + for status, meta in data["capability_status_legend"].items(): + lines.append(f"{status}\t{meta['label']}\t{meta['description']}") click.echo("\n".join(lines)) diff --git a/tests/test_platforms_cmd.py b/tests/test_platforms_cmd.py index bab619d..c9ad611 100644 --- a/tests/test_platforms_cmd.py +++ b/tests/test_platforms_cmd.py @@ -6,6 +6,7 @@ from click.testing import CliRunner +from boss_agent_cli.commands.platforms import _render_platforms, platform_capability_data from boss_agent_cli.main import cli @@ -19,6 +20,11 @@ def test_platforms_outputs_local_capability_matrix() -> None: assert payload["command"] == "platforms" assert payload["data"]["default"] == "zhipin" assert payload["data"]["aliases"] == {"51job": "qiancheng"} + legend = payload["data"]["capability_status_legend"] + assert set(legend) == {"available", "not_supported", "placeholder_only", "low_risk_blocked"} + assert "NOT_SUPPORTED" in legend["not_supported"]["description"] + assert "低风险模式" in legend["low_risk_blocked"]["label"] + assert "不代表真实平台能力" in legend["placeholder_only"]["description"] platforms = {item["name"]: item for item in payload["data"]["platforms"]} assert set(platforms) == {"qiancheng", "zhipin", "zhilian"} @@ -30,6 +36,33 @@ def test_platforms_outputs_local_capability_matrix() -> None: assert platforms["zhilian"]["capabilities"]["readonly"]["search"] == "available" +def test_platforms_json_payload_includes_status_legend() -> None: + runner = CliRunner() + result = runner.invoke(cli, ["platforms"]) + + assert result.exit_code == 0, result.output + payload = json.loads(result.output) + legend = payload["data"]["capability_status_legend"] + assert set(legend) == {"available", "not_supported", "placeholder_only", "low_risk_blocked"} + assert legend["available"]["label"] == "可用" + assert "NOT_SUPPORTED" in legend["not_supported"]["description"] + assert "不代表真实平台能力" in legend["placeholder_only"]["description"] + assert "默认低风险模式阻断" in legend["low_risk_blocked"]["description"] + + +def test_platforms_terminal_render_includes_status_legend(capsys) -> None: + _render_platforms(platform_capability_data()) + captured = capsys.readouterr() + + rendered = captured.out + captured.err + assert "capability_status_legend" in rendered + assert "available" in rendered + assert "可用" in rendered + assert "not_supported" in rendered + assert "placeholder_only" in rendered + assert "low_risk_blocked" in rendered + + def test_platforms_can_filter_single_platform_by_registered_name() -> None: runner = CliRunner() result = runner.invoke(cli, ["platforms", "--platform", "qiancheng"])