docs: 沉淀 account-manager 多账号与 Profile 工业标准
All checks were successful
技能自动化发布 / release (push) Successful in 7s

This commit is contained in:
2026-07-24 16:50:57 +08:00
parent 0ea924958f
commit c15e23e0d4
20 changed files with 604 additions and 41 deletions

View File

@@ -37,6 +37,7 @@ POLICY_IDS = (
"POLICY-RPA-003",
"POLICY-RPA-004",
"POLICY-RPA-005",
"POLICY-RPA-006",
"POLICY-PACKAGING-001",
"POLICY-PACKAGING-002",
"POLICY-DOCS-001",
@@ -175,6 +176,26 @@ RPA_005_STEP_DELAY_KEY_RE = re.compile(
r"(?m)^\s*(STEP_DELAY_MIN|STEP_DELAY_MAX)\s*=\s*([^\s#]+)"
)
RPA_006_SOURCE = (
"development/ACCOUNT_MANAGER.md; development/ADAPTER.md §兄弟依赖; "
"development/RPA.md §0.2; development/POLICY_MATRIX.md"
)
RPA_006_REQUIRED_DOC_MARKERS = (
"一账号一",
"profile_dir",
"lease_token",
"数据管理页面",
"account-manager.db",
"account list",
"lease list",
"关闭浏览器并释放租约",
"两个以上账号",
)
RPA_006_EXAMPLE_CLIENTS = (
"examples/real_browser_rpa/scripts/service/account_client.py",
"examples/simulator_browser_rpa/scripts/service/account_client.py",
)
LOGGING_001_SOURCE = "development/LOGGING.md; development/RUNTIME.md"
LOGGING_002_SOURCE = "development/LOGGING.md; development/DEVELOPMENT.md"
LOGGING_003_SOURCE = "development/LOGGING.md"
@@ -736,6 +757,40 @@ class TestPolicyRpa005(unittest.TestCase):
)
class TestPolicyRpa006(unittest.TestCase):
def test_account_manager_lifecycle_doc_has_required_markers(self) -> None:
skill_root = get_skill_root()
path = os.path.join(skill_root, "development", "ACCOUNT_MANAGER.md")
self.assertTrue(
os.path.isfile(path),
msg=_policy_msg("POLICY-RPA-006", RPA_006_SOURCE, "development/ACCOUNT_MANAGER.md missing"),
)
text = _read_text(path)
missing = [marker for marker in RPA_006_REQUIRED_DOC_MARKERS if marker not in text]
self.assertEqual(
missing,
[],
msg=_policy_msg(
"POLICY-RPA-006",
RPA_006_SOURCE,
"ACCOUNT_MANAGER.md missing markers: " + ", ".join(missing),
),
)
def test_example_account_id_selection_keeps_lease(self) -> None:
skill_root = get_skill_root()
for rel in RPA_006_EXAMPLE_CLIENTS:
text = _read_text(os.path.join(skill_root, *rel.split("/")))
self.assertIn("_pick_by_id_with_lease", text, msg=f"{rel} must lease explicit account ids")
self.assertIn('"account",\n "pick-web"', text, msg=f"{rel} must use pick-web for lease")
self.assertIn("lease_token", text, msg=f"{rel} must validate lease_token")
self.assertNotIn(
'data["lease_token"] = ""',
text,
msg=f"{rel} must not return an explicit account without a lease",
)
def _scan_sensitive_logging_assignments(skill_root: str) -> list[str]:
offenders: list[str] = []
for path in _walk_files(skill_root, "scripts", suffix=".py"):

View File

@@ -249,6 +249,21 @@ class TestDocsStandards(unittest.TestCase):
msg="RPA.md §0.2 must separate site-login from Profile requirement",
)
def test_account_manager_standard_is_discoverable(self) -> None:
account_text = self._read("development/ACCOUNT_MANAGER.md")
for marker in (
"一账号一",
"profile_dir",
"lease_token",
"数据管理",
"account-manager.db",
"关闭浏览器并释放租约",
"两个以上账号",
):
self.assertIn(marker, account_text)
for rel in ("SKILL.md", "development/README.md", "development/RPA.md"):
self.assertIn("ACCOUNT_MANAGER.md", self._read(rel), msg=f"{rel} must link account standard")
def test_simulator_example_readme_covers_async_and_account_manager(self) -> None:
text = self._read("examples/simulator_browser_rpa/README.md")
self.assertIn("async", text.lower())