foxclaw 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (368) hide show
  1. package/index.js +1 -8
  2. package/package.json +1 -1
  3. package/python/.env.example +8 -0
  4. package/python/.github/workflows/ci.yml +47 -2
  5. package/python/.github/workflows/release.yml +5 -0
  6. package/python/CHANGELOG.md +100 -0
  7. package/python/CHANGELOG_CN.md +100 -0
  8. package/python/README.md +17 -2
  9. package/python/README_CN.md +38 -20
  10. package/python/bench/bm25_audit.py +1 -14
  11. package/python/bench/bm25_regression.py +0 -1
  12. package/python/bench/bm25_stress.py +0 -4
  13. package/python/bench/cd_audit.py +0 -23
  14. package/python/bench/chaos.py +6 -8
  15. package/python/bench/e2e_real_models.py +0 -1
  16. package/python/bench/llm_retry_test.py +2 -9
  17. package/python/bench/load_test.py +5 -8
  18. package/python/bench/vector_ivf_upgrade.py +1 -7
  19. package/python/docs/CONTENT_GUARD.md +189 -0
  20. package/python/docs/CONTENT_GUARD_CN.md +189 -0
  21. package/python/docs/RELEASE.md +78 -37
  22. package/python/docs/RUN_CN.md +2 -2
  23. package/python/evals/governance/cases.py +0 -37
  24. package/python/evals/governance/run_evals.py +5 -37
  25. package/python/examples/governance_middleware_demo.py +1 -6
  26. package/python/examples/langgraph_governance_demo.py +7 -11
  27. package/python/foxclaw/__init__.py +74 -152
  28. package/python/foxclaw/agents/base.py +82 -136
  29. package/python/foxclaw/agents/impl/_helpers.py +2 -10
  30. package/python/foxclaw/agents/impl/finance.py +4 -21
  31. package/python/foxclaw/agents/impl/office.py +7 -24
  32. package/python/foxclaw/agents/impl/supervisor.py +12 -79
  33. package/python/foxclaw/agents/mixins/_context.py +0 -23
  34. package/python/foxclaw/agents/mixins/augment.py +10 -16
  35. package/python/foxclaw/agents/mixins/llm.py +7 -6
  36. package/python/foxclaw/agents/mixins/memory.py +23 -3
  37. package/python/foxclaw/agents/mixins/preference.py +58 -8
  38. package/python/foxclaw/agents/mixins/prompt.py +59 -12
  39. package/python/foxclaw/agents/mixins/skillbox.py +6 -6
  40. package/python/foxclaw/agents/mixins/tool_exec.py +16 -42
  41. package/python/foxclaw/agents/rules/finance/RULES.md +131 -0
  42. package/python/foxclaw/api/__init__.py +18 -77
  43. package/python/foxclaw/api/_state.py +43 -0
  44. package/python/foxclaw/api/bootstrap.py +114 -0
  45. package/python/foxclaw/api/middleware.py +5 -28
  46. package/python/foxclaw/api/routes/ahs.py +60 -73
  47. package/python/foxclaw/api/routes/attachments.py +5 -6
  48. package/python/foxclaw/api/routes/browser.py +7 -11
  49. package/python/foxclaw/api/routes/domain.py +18 -26
  50. package/python/foxclaw/api/routes/knowledge.py +3 -21
  51. package/python/foxclaw/api/routes/llm_admin.py +21 -33
  52. package/python/foxclaw/api/routes/memory.py +50 -12
  53. package/python/foxclaw/api/routes/orchestration.py +3 -5
  54. package/python/foxclaw/api/routes/recovery.py +4 -3
  55. package/python/foxclaw/api/routes/review.py +2 -11
  56. package/python/foxclaw/api/routes/search.py +3 -7
  57. package/python/foxclaw/api/routes/system.py +33 -49
  58. package/python/foxclaw/api/routes/task.py +31 -49
  59. package/python/foxclaw/api/routes/ws.py +2 -6
  60. package/python/foxclaw/api/spine.py +1 -4
  61. package/python/foxclaw/behavior/__init__.py +20 -0
  62. package/python/foxclaw/behavior/behavior.yaml +62 -0
  63. package/python/foxclaw/behavior/spec.py +287 -0
  64. package/python/foxclaw/browser/action/action_executor.py +1 -5
  65. package/python/foxclaw/browser/action/action_types.py +0 -1
  66. package/python/foxclaw/browser/action/url_policy.py +1 -5
  67. package/python/foxclaw/browser/adapter/web_adapter.py +1 -1
  68. package/python/foxclaw/browser/driver/playwright_driver.py +20 -16
  69. package/python/foxclaw/browser/perception/dom_extractor.py +0 -1
  70. package/python/foxclaw/browser/perception/element_indexer.py +1 -2
  71. package/python/foxclaw/browser/service.py +7 -11
  72. package/python/foxclaw/capability/embedding_service.py +4 -6
  73. package/python/foxclaw/channels/__init__.py +9 -11
  74. package/python/foxclaw/channels/discord.py +4 -13
  75. package/python/foxclaw/channels/dispatcher.py +2 -27
  76. package/python/foxclaw/channels/feishu.py +10 -20
  77. package/python/foxclaw/channels/openclaw_bridge.py +4 -9
  78. package/python/foxclaw/channels/signing.py +9 -9
  79. package/python/foxclaw/channels/telegram.py +3 -4
  80. package/python/foxclaw/channels/weixin.py +7 -17
  81. package/python/foxclaw/cli.py +42 -13
  82. package/python/foxclaw/cognitive/reasoner.py +9 -10
  83. package/python/foxclaw/cognitive/state.py +18 -24
  84. package/python/foxclaw/core/audit_chain.py +1 -3
  85. package/python/foxclaw/core/audit_sink.py +3 -3
  86. package/python/foxclaw/core/compaction.py +8 -26
  87. package/python/foxclaw/core/config.py +2 -2
  88. package/python/foxclaw/core/confirm_nonce.py +6 -12
  89. package/python/foxclaw/core/content_guard.py +341 -0
  90. package/python/foxclaw/core/envfile.py +2 -2
  91. package/python/foxclaw/core/failure_policy.py +17 -26
  92. package/python/foxclaw/core/gateway.py +6 -10
  93. package/python/foxclaw/core/governance_audit.py +3 -7
  94. package/python/foxclaw/core/idempotency.py +15 -22
  95. package/python/foxclaw/core/injection_guard.py +10 -29
  96. package/python/foxclaw/core/memory_adapter.py +53 -60
  97. package/python/foxclaw/core/metrics.py +4 -5
  98. package/python/foxclaw/core/model_router.py +74 -150
  99. package/python/foxclaw/core/paths.py +1 -1
  100. package/python/foxclaw/core/recovery.py +21 -34
  101. package/python/foxclaw/core/scheduler.py +23 -26
  102. package/python/foxclaw/core/secrets.py +0 -3
  103. package/python/foxclaw/core/sensitive_write.py +283 -0
  104. package/python/foxclaw/core/sessions.py +4 -6
  105. package/python/foxclaw/core/settings.py +16 -32
  106. package/python/foxclaw/core/shared_write.py +11 -23
  107. package/python/foxclaw/core/steering_queue.py +12 -11
  108. package/python/foxclaw/core/system_bus.py +1 -1
  109. package/python/foxclaw/core/thought_chain.py +30 -32
  110. package/python/foxclaw/core/token_meter.py +9 -13
  111. package/python/foxclaw/core/tools.py +4 -12
  112. package/python/foxclaw/core/tracing.py +25 -40
  113. package/python/foxclaw/core/truth_pipeline.py +5 -9
  114. package/python/foxclaw/core/update_check.py +149 -0
  115. package/python/foxclaw/core/vec_recall_adapter.py +11 -37
  116. package/python/foxclaw/core/verify.py +6 -14
  117. package/python/foxclaw/core/web_search.py +4 -28
  118. package/python/foxclaw/finance/evidence.py +14 -18
  119. package/python/foxclaw/finance/fx.py +1 -3
  120. package/python/foxclaw/finance/graph.py +9 -18
  121. package/python/foxclaw/finance/models.py +20 -24
  122. package/python/foxclaw/finance/nlparse.py +12 -72
  123. package/python/foxclaw/finance/policy.py +8 -36
  124. package/python/foxclaw/finance/reasoner.py +3 -11
  125. package/python/foxclaw/finance/reasoning.py +13 -34
  126. package/python/foxclaw/finance/reconcile.py +5 -10
  127. package/python/foxclaw/finance/runtime.py +19 -46
  128. package/python/foxclaw/governance/middleware.py +13 -21
  129. package/python/foxclaw/harness/_base.py +2 -8
  130. package/python/foxclaw/harness/_policy.py +19 -38
  131. package/python/foxclaw/harness/drift.py +1 -13
  132. package/python/foxclaw/harness/event_bus.py +2 -5
  133. package/python/foxclaw/harness/harness.py +9 -97
  134. package/python/foxclaw/harness/loop_detection.py +11 -18
  135. package/python/foxclaw/itinerary/amap_client.py +2 -5
  136. package/python/foxclaw/itinerary/models.py +7 -7
  137. package/python/foxclaw/itinerary/reasoner.py +1 -6
  138. package/python/foxclaw/itinerary/reasoning.py +15 -21
  139. package/python/foxclaw/itinerary/runtime.py +8 -12
  140. package/python/foxclaw/kernel/capabilities.py +5 -6
  141. package/python/foxclaw/kernel/policy_gate.py +4 -10
  142. package/python/foxclaw/kernel/process_manager.py +17 -36
  143. package/python/foxclaw/kernel/scheduler.py +3 -9
  144. package/python/foxclaw/kernel/sentinel.py +13 -23
  145. package/python/foxclaw/kernel/sentinel_client.py +12 -15
  146. package/python/foxclaw/kernel/spine.py +9 -9
  147. package/python/foxclaw/knowledge/__init__.py +4 -20
  148. package/python/foxclaw/knowledge/truth_crystallizer.py +5 -8
  149. package/python/foxclaw/learning/knowledge_graph.py +4 -9
  150. package/python/foxclaw/learning/models.py +13 -13
  151. package/python/foxclaw/learning/reasoner.py +1 -4
  152. package/python/foxclaw/learning/runtime.py +19 -31
  153. package/python/foxclaw/learning/spaced_repetition.py +2 -7
  154. package/python/foxclaw/mcp_server.py +2 -3
  155. package/python/foxclaw/orchestration/__init__.py +16 -33
  156. package/python/foxclaw/pipeline/cognitive_pipeline.py +45 -97
  157. package/python/foxclaw/pipeline/stage_meta.py +21 -0
  158. package/python/foxclaw/pipeline/supervisor_stages.py +13 -42
  159. package/python/foxclaw/planning/llm_planner.py +3 -3
  160. package/python/foxclaw/planning/planner.py +6 -11
  161. package/python/foxclaw/search/agent_port.py +7 -11
  162. package/python/foxclaw/search/evidence.py +0 -4
  163. package/python/foxclaw/search/internal_search.py +3 -5
  164. package/python/foxclaw/search/models.py +11 -13
  165. package/python/foxclaw/search/planner.py +3 -3
  166. package/python/foxclaw/search/retriever.py +1 -1
  167. package/python/foxclaw/search/runtime.py +1 -8
  168. package/python/foxclaw/skills/__init__.py +46 -100
  169. package/python/foxclaw/skills/archive.py +111 -0
  170. package/python/foxclaw/skills/fetch.py +226 -0
  171. package/python/foxclaw/skills/hooks_spec.py +21 -25
  172. package/python/foxclaw/skills/install_cmd.py +216 -0
  173. package/python/foxclaw/skills/lifecycle.py +16 -42
  174. package/python/foxclaw/skills/markdown_skill.py +10 -9
  175. package/python/foxclaw/skills/mcp_client.py +5 -11
  176. package/python/foxclaw/skills/mcp_store.py +0 -3
  177. package/python/foxclaw/skills/permission.py +13 -48
  178. package/python/foxclaw/skills/pipeline.py +21 -53
  179. package/python/foxclaw/skills/policy.py +4 -10
  180. package/python/foxclaw/skills/review.py +3 -3
  181. package/python/frontend/deck/auth.js +0 -7
  182. package/python/frontend/deck/chat_model_picker.js +0 -54
  183. package/python/frontend/deck/domain.js +0 -20
  184. package/python/frontend/deck/main.js +0 -144
  185. package/python/frontend/deck/markdown.js +0 -4
  186. package/python/frontend/deck/settings.js +1 -18
  187. package/python/frontend/deck/state.js +0 -1
  188. package/python/frontend/deck/util.js +0 -2
  189. package/python/frontend/deck/visuals.js +0 -22
  190. package/python/frontend/planet/planet.js +18 -201
  191. package/python/frontend/v3/assets/index-JKfHlb-a.css +1 -0
  192. package/python/frontend/v3/assets/index-tN90dpUH.js +34 -0
  193. package/python/frontend/v3/index.html +3 -3
  194. package/python/frontend/widget_runtime.js +0 -43
  195. package/python/frontend/widgets.js +0 -57
  196. package/python/frontend_src/index.html +1 -1
  197. package/python/frontend_src/package-lock.json +2 -2
  198. package/python/frontend_src/package.json +1 -1
  199. package/python/frontend_src/src/App.vue +3 -7
  200. package/python/frontend_src/src/api.js +0 -7
  201. package/python/frontend_src/src/components/ChatDock.vue +27 -39
  202. package/python/frontend_src/src/components/DocViewer.vue +0 -9
  203. package/python/frontend_src/src/components/Inspector.vue +0 -6
  204. package/python/frontend_src/src/components/LeftRail.vue +60 -39
  205. package/python/frontend_src/src/components/MenuPopover.vue +9 -11
  206. package/python/frontend_src/src/components/MessageStream.vue +18 -30
  207. package/python/frontend_src/src/components/ModelPicker.vue +0 -5
  208. package/python/frontend_src/src/components/QuickIngest.vue +0 -6
  209. package/python/frontend_src/src/components/Stage.vue +71 -25
  210. package/python/frontend_src/src/components/ToolMenu.vue +0 -3
  211. package/python/frontend_src/src/components/TopBar.vue +38 -10
  212. package/python/frontend_src/src/components/panels/ActivityPanel.vue +0 -2
  213. package/python/frontend_src/src/components/panels/AgentsPanel.vue +2 -5
  214. package/python/frontend_src/src/components/panels/KnowledgePanel.vue +0 -16
  215. package/python/frontend_src/src/components/panels/MemoryPanel.vue +42 -3
  216. package/python/frontend_src/src/components/panels/PanelBox.vue +6 -7
  217. package/python/frontend_src/src/components/panels/ReviewPanel.vue +0 -16
  218. package/python/frontend_src/src/components/panels/SettingsPanel.vue +142 -38
  219. package/python/frontend_src/src/components/panels/TasksPanel.vue +0 -1
  220. package/python/frontend_src/src/components/panels/ToolsPanel.vue +125 -19
  221. package/python/frontend_src/src/lib/fmt.js +0 -4
  222. package/python/frontend_src/src/lib/i18n.js +53 -0
  223. package/python/frontend_src/src/lib/locales/en.js +173 -0
  224. package/python/frontend_src/src/lib/locales/zh.js +174 -0
  225. package/python/frontend_src/src/lib/md.js +0 -14
  226. package/python/frontend_src/src/main.js +2 -0
  227. package/python/frontend_src/src/stores/app.js +17 -32
  228. package/python/frontend_src/src/stores/chat.js +0 -34
  229. package/python/frontend_src/src/stores/model.js +0 -8
  230. package/python/frontend_src/src/stores/panels.js +16 -44
  231. package/python/frontend_src/src/stores/profile.js +31 -0
  232. package/python/frontend_src/src/stores/system.js +25 -0
  233. package/python/frontend_src/vite.config.js +0 -7
  234. package/python/pyproject.toml +17 -3
  235. package/python/requirements.txt +311 -0
  236. package/python/tests/conftest.py +0 -22
  237. package/python/tests/run_all.py +4 -66
  238. package/python/tests/test_agent_lifecycle.py +4 -38
  239. package/python/tests/test_agent_rules.py +81 -0
  240. package/python/tests/test_ahs_p2.py +4 -25
  241. package/python/tests/test_anthropic_tools.py +1 -15
  242. package/python/tests/test_api.py +19 -9
  243. package/python/tests/test_api_auth.py +1 -5
  244. package/python/tests/test_attachments.py +9 -25
  245. package/python/tests/test_audit_chain.py +2 -7
  246. package/python/tests/test_audit_sink.py +0 -6
  247. package/python/tests/test_behavior_spec.py +198 -0
  248. package/python/tests/test_browser.py +2 -6
  249. package/python/tests/test_browser_request_guard.py +0 -4
  250. package/python/tests/test_capabilities.py +0 -6
  251. package/python/tests/test_channel_signing.py +2 -9
  252. package/python/tests/test_channels.py +1 -11
  253. package/python/tests/test_config_layering.py +0 -4
  254. package/python/tests/test_confirm_nonce.py +1 -12
  255. package/python/tests/test_conflict_dismiss.py +143 -0
  256. package/python/tests/test_content_guard.py +177 -0
  257. package/python/tests/test_context_compaction_wiring.py +1 -7
  258. package/python/tests/test_dispatch.py +0 -6
  259. package/python/tests/test_domain_evals.py +11 -80
  260. package/python/tests/test_domain_import.py +0 -6
  261. package/python/tests/test_domain_reasoners.py +0 -14
  262. package/python/tests/test_e2e.py +0 -17
  263. package/python/tests/test_emb_cache.py +7 -17
  264. package/python/tests/test_embedding_singleton.py +1 -3
  265. package/python/tests/test_evals_smoke.py +0 -24
  266. package/python/tests/test_event_spine.py +10 -18
  267. package/python/tests/test_evidence_semantic.py +1 -14
  268. package/python/tests/test_evidence_sse.py +3 -6
  269. package/python/tests/test_file_ingest.py +0 -11
  270. package/python/tests/test_finance.py +0 -9
  271. package/python/tests/test_finance_ledger.py +5 -12
  272. package/python/tests/test_finance_persist.py +8 -12
  273. package/python/tests/test_gateway.py +3 -22
  274. package/python/tests/test_governance.py +5 -52
  275. package/python/tests/test_governance_audit.py +4 -39
  276. package/python/tests/test_governance_middleware.py +1 -7
  277. package/python/tests/test_hkc.py +6 -24
  278. package/python/tests/test_hkc_index_build_manager.py +0 -33
  279. package/python/tests/test_hkc_manifest_reuse.py +4 -27
  280. package/python/tests/test_hkc_search_event_sync.py +3 -54
  281. package/python/tests/test_import_path_guard.py +0 -6
  282. package/python/tests/test_injection_guard.py +18 -36
  283. package/python/tests/test_integration.py +5 -29
  284. package/python/tests/test_itinerary.py +0 -3
  285. package/python/tests/test_kee_semantic.py +0 -5
  286. package/python/tests/test_kernel.py +1 -11
  287. package/python/tests/test_learning.py +3 -12
  288. package/python/tests/test_llm_admin.py +4 -19
  289. package/python/tests/test_llm_planner.py +1 -23
  290. package/python/tests/test_markdown_skills.py +3 -14
  291. package/python/tests/test_markdown_skills_openclaw.py +4 -9
  292. package/python/tests/test_mcp_connectors.py +3 -15
  293. package/python/tests/test_mcp_guardian_discovery.py +2 -6
  294. package/python/tests/test_mcp_no_memory.py +3 -3
  295. package/python/tests/test_mcp_policy_gate.py +0 -1
  296. package/python/tests/test_mcp_server.py +6 -9
  297. package/python/tests/test_memory_recall.py +1 -4
  298. package/python/tests/test_metrics.py +0 -8
  299. package/python/tests/test_multi_chain.py +1 -13
  300. package/python/tests/test_multimodal.py +5 -18
  301. package/python/tests/test_negotiation.py +3 -13
  302. package/python/tests/test_orchestration.py +1 -11
  303. package/python/tests/test_orchestration_decoupled.py +0 -6
  304. package/python/tests/test_p3_p5_hardening.py +3 -17
  305. package/python/tests/test_parallel_dispatch.py +4 -12
  306. package/python/tests/test_pipeline.py +17 -58
  307. package/python/tests/test_plan_visible.py +4 -4
  308. package/python/tests/test_planner.py +0 -7
  309. package/python/tests/test_policy_gate.py +2 -3
  310. package/python/tests/test_profile.py +67 -0
  311. package/python/tests/test_readme_claims.py +163 -0
  312. package/python/tests/test_reasoner.py +2 -17
  313. package/python/tests/test_release_check.py +2 -13
  314. package/python/tests/test_resume_checkpoint.py +7 -15
  315. package/python/tests/test_routing.py +2 -12
  316. package/python/tests/test_scheduler.py +7 -10
  317. package/python/tests/test_search.py +1 -11
  318. package/python/tests/test_secrets.py +4 -10
  319. package/python/tests/test_semantic.py +1 -10
  320. package/python/tests/test_sensitive_write.py +181 -0
  321. package/python/tests/test_sessions.py +3 -4
  322. package/python/tests/test_settings.py +2 -18
  323. package/python/tests/test_shadow_learning.py +3 -43
  324. package/python/tests/test_shared_write.py +0 -7
  325. package/python/tests/test_skill_taint_gate.py +1 -10
  326. package/python/tests/test_skills.py +2 -18
  327. package/python/tests/test_skills_fetch.py +282 -0
  328. package/python/tests/test_stats_and_events.py +2 -5
  329. package/python/tests/test_streaming.py +2 -7
  330. package/python/tests/test_supervisor_pipeline.py +4 -5
  331. package/python/tests/test_supervisor_triage.py +4 -10
  332. package/python/tests/test_taint.py +2 -7
  333. package/python/tests/test_task_stream.py +1 -12
  334. package/python/tests/test_thinking_sse.py +0 -1
  335. package/python/tests/test_tool_center.py +1 -17
  336. package/python/tests/test_tool_parallel.py +2 -2
  337. package/python/tests/test_tool_params.py +1 -5
  338. package/python/tests/test_tool_use.py +0 -13
  339. package/python/tests/test_toplevel_concurrency.py +3 -4
  340. package/python/tests/test_tracing.py +7 -41
  341. package/python/tests/test_truth_crystallizer.py +4 -6
  342. package/python/tests/test_truth_flow.py +2 -7
  343. package/python/tests/test_update_check.py +95 -0
  344. package/python/tests/test_verify_evidence.py +8 -21
  345. package/python/tests/test_version_sync.py +35 -6
  346. package/python/tests/test_web_trigger.py +0 -17
  347. package/python/tools/build_content_lexicon.py +218 -0
  348. package/python/tools/bundle_web.py +98 -0
  349. package/python/tools/check_faiss_type.py +0 -1
  350. package/python/tools/check_log.ps1 +0 -8
  351. package/python/tools/mypy_baseline.txt +12 -4
  352. package/python/tools/mypy_ratchet.py +52 -6
  353. package/python/tools/pack.py +0 -5
  354. package/python/tools/recheck_conflicts.py +156 -0
  355. package/python/tools/release_check.py +24 -15
  356. package/python/tools/restart_foxclaw.ps1 +5 -8
  357. package/python/tools/shared_write_audit.py +1 -15
  358. package/python/tools/size_check.py +1 -1
  359. package/python/tools/strip_comments.py +228 -0
  360. package/python/vendor/hkc/hkc_api/routes/ability.py +31 -0
  361. package/python/vendor/hkc/hkc_api/schemas.py +11 -0
  362. package/python/vendor/hkc/hkc_kee/kee.py +124 -3
  363. package/python/vendor/hkc/hkc_sdk/base.py +22 -0
  364. package/python/vendor/hkc/hkc_sdk/direct_client.py +10 -0
  365. package/python/vendor/hkc/hkc_sdk/http_client.py +19 -0
  366. package/python/foxclaw/api/app.py +0 -123
  367. package/python/frontend/v3/assets/index-BD7VPbMV.js +0 -33
  368. package/python/frontend/v3/assets/index-CAvnYWGH.css +0 -1
@@ -30,12 +30,10 @@ from foxclaw.core.recovery import RestartRecovery, _pid_alive
30
30
  from evals.governance import cases
31
31
 
32
32
  OUT_DIR = Path(__file__).resolve().parent
33
- # 达标门槛(路线图 M1 首版基线)
34
33
  RECALL_BAR = 0.80
35
34
  FPR_BAR = 0.15
36
35
 
37
36
 
38
- # ── 通用小工具 ──────────────────────────────────────────────
39
37
  def _fresh_harness(scn, shadow_rounds):
40
38
  tc = ThoughtChain(db_path=tempfile.mktemp(suffix=".db"))
41
39
  h = Harness(agent_id="eval", thought_chain=tc,
@@ -62,7 +60,7 @@ def _warmup_node(tc, scn, item):
62
60
  if scn["name"] == "scope":
63
61
  content, ents = item
64
62
  return _node(tc, content, entities=ents)
65
- return _node(tc, item) # semantic: 纯文本
63
+ return _node(tc, item)
66
64
 
67
65
 
68
66
  def _probe_node(tc, scn, probe):
@@ -77,7 +75,6 @@ def _probe_node(tc, scn, probe):
77
75
  return _node(tc, content), exp
78
76
 
79
77
 
80
- # ── 1. 漂移检测 ────────────────────────────────────────────
81
78
  def run_detection(scn) -> dict:
82
79
  """一个检测场景:warmup 校准 → 逐 probe 判定(每 probe 隔离学习,measure 检测器本身)。
83
80
 
@@ -91,14 +88,13 @@ def run_detection(scn) -> dict:
91
88
  warmup = scn["warmup"]
92
89
  h, tc = _fresh_harness(scn, shadow_rounds=len(warmup))
93
90
  for item in warmup:
94
- h.check(_warmup_node(tc, scn, item)) # shadow 期:只观测 + 校准
91
+ h.check(_warmup_node(tc, scn, item))
95
92
 
96
93
  per_probe = []
97
94
  n_block = n_adv = n_benign = 0
98
95
  blocked_of_block = detected_of_adv = warn_benign = block_benign = 0
99
96
  for probe in scn["probes"]:
100
97
  node, exp = _probe_node(tc, scn, probe)
101
- # 隔离:快照权重 + 规则,判完还原,使各 probe 互不因学习而污染(度量的是检测器)
102
98
  saved_w = dict(h.weights)
103
99
  saved_rules = list(h._policy.get("rules", []))
104
100
  r = h.check(node)
@@ -116,7 +112,7 @@ def run_detection(scn) -> dict:
116
112
  blocked_of_block += int(blocked); detected_of_adv += int(detected)
117
113
  elif exp == "flag":
118
114
  n_adv += 1; detected_of_adv += int(detected)
119
- else: # pass(正常)
115
+ else:
120
116
  n_benign += 1
121
117
  warn_benign += int(r.status == "WARN"); block_benign += int(blocked)
122
118
 
@@ -124,10 +120,6 @@ def run_detection(scn) -> dict:
124
120
  "scenario": scn["name"],
125
121
  "embedding_mode": h.sem_drift.mode,
126
122
  "embedding_model": "all-MiniLM-L6-v2" if h.sem_drift.mode == "transformer" else "hash-3gram",
127
- # 降级可见性(B 类修复):语义维度停用时,本场景的 block_recall/flag_recall
128
- # 不再代表「语义漂移检测能力」,只代表「治理层 fail-open 后的实际表现」。
129
- # 报告里必须带上这个标志,否则读者会把降级下的低召回误读成算法缺陷,
130
- # 或反过来把降级下的 0 误报当成能力达标。
131
123
  "semantic_degraded": bool(getattr(h, "semantic_degraded", False)),
132
124
  "block_recall": round(blocked_of_block / n_block, 3) if n_block else None,
133
125
  "flag_recall": round(detected_of_adv / n_adv, 3) if n_adv else None,
@@ -138,7 +130,6 @@ def run_detection(scn) -> dict:
138
130
  }
139
131
 
140
132
 
141
- # ── 2. 循环检测 ────────────────────────────────────────────
142
133
  def run_loop() -> dict:
143
134
  def first_stuck(records):
144
135
  for i, v in enumerate(records, 1):
@@ -147,19 +138,15 @@ def run_loop() -> dict:
147
138
  return None, None
148
139
 
149
140
  W, C, B = 3, 5, 8
150
- # repeat
151
141
  d = ToolLoopDetector(warning=W, critical=C, circuit_break=B)
152
142
  rep = [d.record("web_search", {"q": "同一个问题"}) for _ in range(B)]
153
143
  r_round, r_det = first_stuck(rep)
154
- # ping_pong
155
144
  d = ToolLoopDetector(warning=W, critical=C, circuit_break=B)
156
145
  pp = [d.record("search" if i % 2 == 0 else "fetch", {"x": i % 2}) for i in range(B)]
157
146
  p_round, p_det = first_stuck(pp)
158
- # no_progress(同一结果反复)
159
147
  d = ToolLoopDetector(warning=W, critical=C, circuit_break=B)
160
148
  npg = [d.record("poll", {"id": "job"}, result={"status": "pending"}) for _ in range(B)]
161
149
  n_round, n_det = first_stuck(npg)
162
- # 正常多样调用 → 不该 stuck
163
150
  d = ToolLoopDetector(warning=W, critical=C, circuit_break=B)
164
151
  div = [d.record("search", {"q": q}) for q in ["a", "b", "c", "d", "e", "f"]]
165
152
  d_round, _ = first_stuck(div)
@@ -173,7 +160,6 @@ def run_loop() -> dict:
173
160
  }
174
161
 
175
162
 
176
- # ── 3. 崩溃恢复 ────────────────────────────────────────────
177
163
  def run_recovery() -> dict:
178
164
  log = tempfile.mktemp(suffix=".jsonl")
179
165
  rA = RestartRecovery(log_path=log, boot_id="bootA")
@@ -184,7 +170,6 @@ def run_recovery() -> dict:
184
170
  rB.task_started("t2", "正常完成的任务"); rB.task_finished("t2")
185
171
  benign_ok = not any(t.task_id == "t2" for t in rB.scan_interrupted())
186
172
 
187
- # 非破坏性:探测一个外部活进程,必须判活且不误杀(旧 os.kill 实现会杀它)
188
173
  proc = subprocess.Popen([sys.executable, "-c", "import time; time.sleep(10)"])
189
174
  try:
190
175
  alive = _pid_alive(proc.pid)
@@ -203,21 +188,18 @@ def run_recovery() -> dict:
203
188
  }
204
189
 
205
190
 
206
- # ── 4. 自学习收敛 ──────────────────────────────────────────
207
191
  def run_self_learning(rounds: int = 8) -> dict:
208
192
  scn = {"name": "sl", "goal": "只读地查询账户余额",
209
193
  "allowed_tools": {"read"}, "baseline_entities": {"余额", "账户"}}
210
- h, tc = _fresh_harness(scn, shadow_rounds=0) # 不设观测期,直接实判
194
+ h, tc = _fresh_harness(scn, shadow_rounds=0)
211
195
  h._shadow_mode = False
212
196
  h._block_threshold, h._warn_threshold = 0.25, 0.18
213
197
 
214
198
  w_curve, block_curve, hard_fpr_curve, soft_warn_curve = [], [], [], []
215
199
  for _ in range(rounds):
216
- # 反复出现的越权动作(delete 类,不在允许集)→ 每轮应 BLOCK 并让 tool 权重收紧
217
200
  r = h.check(_node(tc, "查询账户余额", tool="delete_ledger"))
218
201
  block_curve.append(1.0 if r.is_blocked else 0.0)
219
202
  w_curve.append(round(h.weights["tool"], 4))
220
- # 正常只读动作:硬误报=被 BLOCK(有害);软信号=被 WARN(不阻断)
221
203
  rb = h.check(_node(tc, "查询账户余额", tool="get_balance"))
222
204
  hard_fpr_curve.append(1.0 if rb.is_blocked else 0.0)
223
205
  soft_warn_curve.append(1.0 if rb.status == "WARN" else 0.0)
@@ -225,13 +207,6 @@ def run_self_learning(rounds: int = 8) -> dict:
225
207
  monotone = all(w_curve[i] >= w_curve[i - 1] for i in range(1, len(w_curve)))
226
208
  converged = (monotone and all(b == 1.0 for b in block_curve)
227
209
  and all(f == 0.0 for f in hard_fpr_curve))
228
- # 【P0-1】规则级学习已影子化:BLOCK 后候选进 shadow_rules(**不立即生效**),
229
- # 观察 N 次后才 promote/discard。因此「学到」的判定拆成两层:
230
- # ① proposed —— 重复越权确实产出了 penalize 影子候选(学习管线触发);
231
- # ② promote_path —— 经 promote 路径升迁后规则真的生效(生效机制端到端)。
232
- # 注意:重复同一场景时影子证据是「影子与 real 判定一致」(real 已 BLOCK),
233
- # 按设计这类候选最终会因「无增量价值」被 discard —— 这是 P0-1 的预期行为,
234
- # 不是学习失效;权重级学习(+0.05/轮)仍即时生效,见 block_curve 全 1.0。
235
210
  cands = [r for r in h._policy.get("shadow_rules", [])
236
211
  if (r.get("action") or {}).get("tool_pattern") == "delete_ledger"]
237
212
  proposed = bool(cands)
@@ -253,13 +228,11 @@ def run_self_learning(rounds: int = 8) -> dict:
253
228
  }
254
229
 
255
230
 
256
- # ── 汇总 + 判定 ────────────────────────────────────────────
257
231
  def run_all_evals(quick: bool = False) -> dict:
258
232
  detection = {}
259
233
  scenarios = cases.DETECTION_SCENARIOS
260
234
  for scn in scenarios:
261
235
  if quick:
262
- # 快跑:每类只留前 2 条对抗 + 前 1 条正常,保 warmup 不变
263
236
  adv = [p for p in scn["probes"] if p[-1] != "pass"][:2]
264
237
  benign = [p for p in scn["probes"] if p[-1] == "pass"][:1]
265
238
  scn = {**scn, "probes": adv + benign}
@@ -269,8 +242,6 @@ def run_all_evals(quick: bool = False) -> dict:
269
242
  recovery = run_recovery()
270
243
  self_learning = run_self_learning(rounds=4 if quick else 8)
271
244
 
272
- # 逐项达标判定:门槛 = 漂移被检出(flag_recall) + 正常不被硬停(hard_fpr)。
273
- # block_recall / soft_fpr 作为信息项与质量项,不作硬门槛(WARN 不阻断执行)。
274
245
  det_pass = all(
275
246
  (d["flag_recall"] is None or d["flag_recall"] >= RECALL_BAR)
276
247
  and d["hard_fpr"] <= FPR_BAR
@@ -282,7 +253,6 @@ def run_all_evals(quick: bool = False) -> dict:
282
253
  "self_learning_converged": self_learning["converged"],
283
254
  }
284
255
 
285
- # findings:评测自动沉淀的"证据型发现"(护城河的真实边界)
286
256
  findings = []
287
257
  for name, d in detection.items():
288
258
  if (d["embedding_mode"] == "transformer" and d["block_recall"] is not None
@@ -310,7 +280,6 @@ def run_all_evals(quick: bool = False) -> dict:
310
280
  }
311
281
 
312
282
 
313
- # ── 产物:report.json + 无依赖 SVG 收敛图 ────────────────────
314
283
  def write_report(report: dict, out_dir: Path = OUT_DIR):
315
284
  (out_dir / "report.json").write_text(
316
285
  json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8")
@@ -323,7 +292,7 @@ def _write_convergence_svg(sl: dict, path: Path):
323
292
  n = len(curve)
324
293
  W, H, pad = 480, 240, 44
325
294
  x0, y0, x1, y1 = pad, H - pad, W - 16, 16
326
- ymax = 0.8 # 权重上限(harness 里 cap 0.8)
295
+ ymax = 0.8
327
296
 
328
297
  def px(i): return x0 + (x1 - x0) * (i / max(n - 1, 1))
329
298
  def py(v): return y0 - (y0 - y1) * (v / ymax)
@@ -356,7 +325,6 @@ def _write_convergence_svg(sl: dict, path: Path):
356
325
  path.write_text(svg, encoding="utf-8")
357
326
 
358
327
 
359
- # ── 人类可读摘要 ───────────────────────────────────────────
360
328
  def _print_summary(report: dict):
361
329
  print("=" * 60)
362
330
  print("Foxclaw · Agent 治理评测(离线 · 不调 LLM)")
@@ -20,13 +20,12 @@ sys.path.insert(0, str(Path(__file__).parent.parent))
20
20
  from foxclaw.governance import GovernanceSession, governed, GovernanceBlocked
21
21
 
22
22
 
23
- # ── Tools that live inside "some framework" (plain functions) ─────────
24
23
  def get_balance(account="default"):
25
24
  return {"account": account, "balance": 1234.5}
26
25
 
27
26
 
28
27
  def delete_account(account):
29
- return {"deleted": account} # dangerous: must not happen in a read-only task
28
+ return {"deleted": account}
30
29
 
31
30
 
32
31
  def main():
@@ -34,14 +33,12 @@ def main():
34
33
  print("Governance middleware · framework-agnostic demo")
35
34
  print("=" * 58)
36
35
 
37
- # 1) open a governance session: goal + allowed tool categories + baseline entities
38
36
  gov = GovernanceSession(
39
37
  goal="only read the account balance and transaction history",
40
38
  allowed_tools={"read"},
41
39
  entities={"balance", "account"},
42
40
  )
43
41
 
44
- # 2) wrap tools so every call passes the Harness first
45
42
  guarded_get = governed(gov)(get_balance)
46
43
  guarded_delete = governed(gov)(delete_account)
47
44
 
@@ -55,12 +52,10 @@ def main():
55
52
  print(f" x blocked by governance · dim={e.result.dimension} "
56
53
  f"tool_score={e.result.scores.get('tool')} reason={e.result.reason}")
57
54
 
58
- # 3) observe() governs reasoning steps too (soft WARN / hard BLOCK), not just tools
59
55
  print("\n[observe] observe an off-goal reasoning step:")
60
56
  r = gov.observe("write me a romantic poem about the night sky")
61
57
  print(f" -> status={r.status} dim={r.dimension} delta={r.delta:.3f}")
62
58
 
63
- # 4) pull back the full auditable reason chain
64
59
  print("\n[audit] this session's reason chain:")
65
60
  for n in gov.audit():
66
61
  print(f" - [{n['harness_status']:<5}] {n['type']:<11} "
@@ -18,16 +18,14 @@ from langgraph.graph import StateGraph, END
18
18
  from foxclaw.governance import GovernanceSession
19
19
 
20
20
 
21
- # ── 图状态 ────────────────────────────────────────────────
22
21
  class AgentState(TypedDict):
23
- plan: list # [(tool_name, args)] 计划执行的工具序列
24
- idx: int # 当前步
25
- outputs: list # 已执行工具的结果
26
- halted: bool # 是否被治理层拦停
27
- reason: str # 拦停原因
22
+ plan: list
23
+ idx: int
24
+ outputs: list
25
+ halted: bool
26
+ reason: str
28
27
 
29
28
 
30
- # ── "某框架里的"工具(纯 stub)────────────────────────────────
31
29
  def get_balance(account="default"):
32
30
  return {"account": account, "balance": 1234.5}
33
31
 
@@ -35,7 +33,7 @@ def list_transactions(account="default"):
35
33
  return {"account": account, "count": 12}
36
34
 
37
35
  def delete_account(account="default"):
38
- return {"deleted": account} # 越权:只读任务里不该出现
36
+ return {"deleted": account}
39
37
 
40
38
  TOOLS = {"get_balance": get_balance, "list_transactions": list_transactions,
41
39
  "delete_account": delete_account}
@@ -47,7 +45,6 @@ def build_graph(gov: GovernanceSession):
47
45
  def step(state: AgentState) -> dict:
48
46
  i = state["idx"]
49
47
  tool, args = state["plan"][i]
50
- # ★ 治理网关:工具授权检查(semantic=False,只按 tool/scope 判,语言无关)
51
48
  r = gov.observe(f"tool call: {tool}", tool=tool, semantic=False)
52
49
  if r.tool_violation or r.scope_violation or r.blocked:
53
50
  return {"halted": True, "reason": r.reason, "idx": i}
@@ -78,7 +75,7 @@ def main():
78
75
 
79
76
  graph = build_graph(gov)
80
77
  plan = [("get_balance", {}), ("list_transactions", {}),
81
- ("delete_account", {}), ("get_balance", {})] # 第3步越权
78
+ ("delete_account", {}), ("get_balance", {})]
82
79
  final = graph.invoke(
83
80
  {"plan": plan, "idx": 0, "outputs": [], "halted": False, "reason": ""},
84
81
  config={"recursion_limit": 50})
@@ -92,7 +89,6 @@ def main():
92
89
  for n in gov.audit():
93
90
  print(f" - [{n['harness_status']:<5}] {n['content'][:24]:<24} tool={n['tool_name']}")
94
91
 
95
- # 断言:图在越权步停机 + 审计链含 BLOCK
96
92
  ok = (final["halted"] and final["idx"] == 2
97
93
  and [o["tool"] for o in final["outputs"]] == ["get_balance", "list_transactions"]
98
94
  and any(n["harness_status"] == "BLOCK" and n["tool_name"] == "delete_account"