foxclaw 0.1.0 → 0.1.2

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 (495) hide show
  1. package/README.md +54 -29
  2. package/bin/foxclaw.cjs +51 -0
  3. package/index.js +11 -10
  4. package/package.json +46 -38
  5. package/python/.dockerignore +35 -0
  6. package/python/.env.example +165 -0
  7. package/python/.gitattributes +46 -0
  8. package/python/.github/workflows/ci.yml +122 -0
  9. package/python/.github/workflows/release.yml +183 -0
  10. package/python/Dockerfile +64 -0
  11. package/python/LICENSE +21 -0
  12. package/python/MANIFEST.in +14 -0
  13. package/python/README.md +192 -0
  14. package/python/README_CN.md +324 -0
  15. package/python/bench/bm25_audit.py +199 -0
  16. package/python/bench/bm25_regression.py +178 -0
  17. package/python/bench/bm25_stress.py +159 -0
  18. package/python/bench/cd_audit.py +238 -0
  19. package/python/bench/chaos.py +142 -0
  20. package/python/bench/concurrency.py +103 -0
  21. package/python/bench/e2e_real_models.py +95 -0
  22. package/python/bench/llm_retry_test.py +248 -0
  23. package/python/bench/load_test.py +196 -0
  24. package/python/bench/vector_ivf_upgrade.py +134 -0
  25. package/python/docs/CHANNELS.md +195 -0
  26. package/python/docs/GOVERNANCE.md +164 -0
  27. package/python/docs/RELEASE.md +109 -0
  28. package/python/docs/RUN.md +75 -0
  29. package/python/docs/RUN_CN.md +121 -0
  30. package/python/docs//351/205/215/347/275/256/346/214/207/345/215/227.md +152 -0
  31. package/python/evals/__init__.py +0 -0
  32. package/python/evals/governance/README.md +61 -0
  33. package/python/evals/governance/__init__.py +0 -0
  34. package/python/evals/governance/cases.py +152 -0
  35. package/python/evals/governance/compare_embeddings.py +94 -0
  36. package/python/evals/governance/convergence.svg +11 -0
  37. package/python/evals/governance/report.json +371 -0
  38. package/python/evals/governance/run_evals.py +400 -0
  39. package/python/examples/governance_middleware_demo.py +77 -0
  40. package/python/examples/langgraph_governance_demo.py +108 -0
  41. package/python/examples/sample_itinerary.csv +6 -0
  42. package/python/examples/sample_knowledge.csv +9 -0
  43. package/python/examples/sample_transactions.csv +14 -0
  44. package/python/foxclaw/__init__.py +526 -0
  45. package/python/foxclaw/agents/__init__.py +12 -0
  46. package/python/foxclaw/agents/agents.py +35 -0
  47. package/python/foxclaw/agents/base.py +865 -0
  48. package/python/foxclaw/agents/impl/__init__.py +1 -0
  49. package/python/foxclaw/agents/impl/_helpers.py +78 -0
  50. package/python/foxclaw/agents/impl/finance.py +248 -0
  51. package/python/foxclaw/agents/impl/office.py +367 -0
  52. package/python/foxclaw/agents/impl/supervisor.py +659 -0
  53. package/python/foxclaw/agents/mixins/_context.py +151 -0
  54. package/python/foxclaw/agents/mixins/augment.py +149 -0
  55. package/python/foxclaw/agents/mixins/llm.py +66 -0
  56. package/python/foxclaw/agents/mixins/memory.py +35 -0
  57. package/python/foxclaw/agents/mixins/preference.py +81 -0
  58. package/python/foxclaw/agents/mixins/prompt.py +77 -0
  59. package/python/foxclaw/agents/mixins/skillbox.py +58 -0
  60. package/python/foxclaw/agents/mixins/tool_exec.py +443 -0
  61. package/python/foxclaw/api/__init__.py +283 -0
  62. package/python/foxclaw/api/app.py +123 -0
  63. package/python/foxclaw/api/middleware.py +317 -0
  64. package/python/foxclaw/api/routes/ahs.py +417 -0
  65. package/python/foxclaw/api/routes/attachments.py +117 -0
  66. package/python/foxclaw/api/routes/browser.py +39 -0
  67. package/python/foxclaw/api/routes/domain.py +314 -0
  68. package/python/foxclaw/api/routes/knowledge.py +163 -0
  69. package/python/foxclaw/api/routes/llm_admin.py +461 -0
  70. package/python/foxclaw/api/routes/memory.py +89 -0
  71. package/python/foxclaw/api/routes/orchestration.py +41 -0
  72. package/python/foxclaw/api/routes/recovery.py +43 -0
  73. package/python/foxclaw/api/routes/review.py +275 -0
  74. package/python/foxclaw/api/routes/search.py +37 -0
  75. package/python/foxclaw/api/routes/system.py +327 -0
  76. package/python/foxclaw/api/routes/task.py +281 -0
  77. package/python/foxclaw/api/routes/ws.py +68 -0
  78. package/python/foxclaw/api/spine.py +55 -0
  79. package/python/foxclaw/browser/__init__.py +13 -0
  80. package/python/foxclaw/browser/action/__init__.py +1 -0
  81. package/python/foxclaw/browser/action/action_executor.py +54 -0
  82. package/python/foxclaw/browser/action/action_types.py +45 -0
  83. package/python/foxclaw/browser/action/action_verifier.py +68 -0
  84. package/python/foxclaw/browser/action/url_policy.py +147 -0
  85. package/python/foxclaw/browser/adapter/__init__.py +1 -0
  86. package/python/foxclaw/browser/adapter/base_adapter.py +23 -0
  87. package/python/foxclaw/browser/adapter/web_adapter.py +46 -0
  88. package/python/foxclaw/browser/driver/__init__.py +1 -0
  89. package/python/foxclaw/browser/driver/base_driver.py +61 -0
  90. package/python/foxclaw/browser/driver/playwright_driver.py +166 -0
  91. package/python/foxclaw/browser/perception/__init__.py +1 -0
  92. package/python/foxclaw/browser/perception/dom_extractor.py +43 -0
  93. package/python/foxclaw/browser/perception/element_indexer.py +57 -0
  94. package/python/foxclaw/browser/perception/semantic_reducer.py +33 -0
  95. package/python/foxclaw/browser/perception/snapshot.py +29 -0
  96. package/python/foxclaw/browser/service.py +148 -0
  97. package/python/foxclaw/browser/session/__init__.py +1 -0
  98. package/python/foxclaw/browser/session/session_manager.py +57 -0
  99. package/python/foxclaw/capability/__init__.py +12 -0
  100. package/python/foxclaw/capability/embedding_service.py +67 -0
  101. package/python/foxclaw/channels/__init__.py +140 -0
  102. package/python/foxclaw/channels/discord.py +184 -0
  103. package/python/foxclaw/channels/dispatcher.py +204 -0
  104. package/python/foxclaw/channels/feishu.py +225 -0
  105. package/python/foxclaw/channels/openclaw_bridge.py +156 -0
  106. package/python/foxclaw/channels/signing.py +187 -0
  107. package/python/foxclaw/channels/telegram.py +121 -0
  108. package/python/foxclaw/channels/weixin.py +225 -0
  109. package/python/foxclaw/cli.py +154 -0
  110. package/python/foxclaw/cognitive/__init__.py +4 -0
  111. package/python/foxclaw/cognitive/reasoner.py +82 -0
  112. package/python/foxclaw/cognitive/state.py +147 -0
  113. package/python/foxclaw/core/__init__.py +9 -0
  114. package/python/foxclaw/core/audit_chain.py +133 -0
  115. package/python/foxclaw/core/audit_sink.py +100 -0
  116. package/python/foxclaw/core/compaction.py +283 -0
  117. package/python/foxclaw/core/config.py +65 -0
  118. package/python/foxclaw/core/confirm_nonce.py +157 -0
  119. package/python/foxclaw/core/dispatch.py +27 -0
  120. package/python/foxclaw/core/envfile.py +48 -0
  121. package/python/foxclaw/core/failure_policy.py +151 -0
  122. package/python/foxclaw/core/gateway.py +85 -0
  123. package/python/foxclaw/core/governance_audit.py +175 -0
  124. package/python/foxclaw/core/idempotency.py +289 -0
  125. package/python/foxclaw/core/injection_guard.py +221 -0
  126. package/python/foxclaw/core/memory_adapter.py +516 -0
  127. package/python/foxclaw/core/metrics.py +89 -0
  128. package/python/foxclaw/core/model_router.py +1097 -0
  129. package/python/foxclaw/core/paths.py +103 -0
  130. package/python/foxclaw/core/recovery.py +362 -0
  131. package/python/foxclaw/core/scheduler.py +144 -0
  132. package/python/foxclaw/core/secrets.py +134 -0
  133. package/python/foxclaw/core/sessions.py +157 -0
  134. package/python/foxclaw/core/settings.py +430 -0
  135. package/python/foxclaw/core/shared_write.py +198 -0
  136. package/python/foxclaw/core/steering_queue.py +153 -0
  137. package/python/foxclaw/core/system_bus.py +84 -0
  138. package/python/foxclaw/core/thought_chain.py +318 -0
  139. package/python/foxclaw/core/token_meter.py +235 -0
  140. package/python/foxclaw/core/tools.py +172 -0
  141. package/python/foxclaw/core/tracing.py +390 -0
  142. package/python/foxclaw/core/truth_pipeline.py +114 -0
  143. package/python/foxclaw/core/vec_recall_adapter.py +503 -0
  144. package/python/foxclaw/core/verify.py +181 -0
  145. package/python/foxclaw/core/web_search.py +242 -0
  146. package/python/foxclaw/finance/__init__.py +15 -0
  147. package/python/foxclaw/finance/evidence.py +153 -0
  148. package/python/foxclaw/finance/fx.py +100 -0
  149. package/python/foxclaw/finance/graph.py +188 -0
  150. package/python/foxclaw/finance/models.py +150 -0
  151. package/python/foxclaw/finance/nlparse.py +575 -0
  152. package/python/foxclaw/finance/policy.py +329 -0
  153. package/python/foxclaw/finance/reasoner.py +129 -0
  154. package/python/foxclaw/finance/reasoning.py +340 -0
  155. package/python/foxclaw/finance/reconcile.py +180 -0
  156. package/python/foxclaw/finance/runtime.py +527 -0
  157. package/python/foxclaw/governance/__init__.py +24 -0
  158. package/python/foxclaw/governance/middleware.py +184 -0
  159. package/python/foxclaw/harness/__init__.py +17 -0
  160. package/python/foxclaw/harness/_base.py +72 -0
  161. package/python/foxclaw/harness/_policy.py +359 -0
  162. package/python/foxclaw/harness/drift.py +89 -0
  163. package/python/foxclaw/harness/event_bus.py +31 -0
  164. package/python/foxclaw/harness/harness.py +446 -0
  165. package/python/foxclaw/harness/loop_detection.py +152 -0
  166. package/python/foxclaw/itinerary/__init__.py +10 -0
  167. package/python/foxclaw/itinerary/amap_client.py +117 -0
  168. package/python/foxclaw/itinerary/models.py +80 -0
  169. package/python/foxclaw/itinerary/reasoner.py +101 -0
  170. package/python/foxclaw/itinerary/reasoning.py +174 -0
  171. package/python/foxclaw/itinerary/runtime.py +148 -0
  172. package/python/foxclaw/kernel/__init__.py +13 -0
  173. package/python/foxclaw/kernel/capabilities.py +73 -0
  174. package/python/foxclaw/kernel/policy_gate.py +114 -0
  175. package/python/foxclaw/kernel/process_manager.py +205 -0
  176. package/python/foxclaw/kernel/scheduler.py +131 -0
  177. package/python/foxclaw/kernel/sentinel.py +453 -0
  178. package/python/foxclaw/kernel/sentinel_client.py +246 -0
  179. package/python/foxclaw/kernel/spine.py +97 -0
  180. package/python/foxclaw/knowledge/__init__.py +376 -0
  181. package/python/foxclaw/knowledge/truth_crystallizer.py +92 -0
  182. package/python/foxclaw/learning/__init__.py +12 -0
  183. package/python/foxclaw/learning/knowledge_graph.py +149 -0
  184. package/python/foxclaw/learning/models.py +93 -0
  185. package/python/foxclaw/learning/reasoner.py +70 -0
  186. package/python/foxclaw/learning/runtime.py +363 -0
  187. package/python/foxclaw/learning/spaced_repetition.py +96 -0
  188. package/python/foxclaw/mcp_server.py +189 -0
  189. package/python/foxclaw/orchestration/__init__.py +184 -0
  190. package/python/foxclaw/pipeline/__init__.py +23 -0
  191. package/python/foxclaw/pipeline/cognitive_pipeline.py +481 -0
  192. package/python/foxclaw/pipeline/supervisor_stages.py +230 -0
  193. package/python/foxclaw/planning/__init__.py +17 -0
  194. package/python/foxclaw/planning/llm_planner.py +232 -0
  195. package/python/foxclaw/planning/planner.py +99 -0
  196. package/python/foxclaw/search/__init__.py +24 -0
  197. package/python/foxclaw/search/agent_port.py +194 -0
  198. package/python/foxclaw/search/evidence.py +113 -0
  199. package/python/foxclaw/search/external_search.py +50 -0
  200. package/python/foxclaw/search/hkc_read_port.py +60 -0
  201. package/python/foxclaw/search/internal_search.py +73 -0
  202. package/python/foxclaw/search/models.py +129 -0
  203. package/python/foxclaw/search/planner.py +44 -0
  204. package/python/foxclaw/search/retriever.py +39 -0
  205. package/python/foxclaw/search/runtime.py +134 -0
  206. package/python/foxclaw/search/strategy.py +44 -0
  207. package/python/foxclaw/skills/__init__.py +613 -0
  208. package/python/foxclaw/skills/hooks_spec.py +73 -0
  209. package/python/foxclaw/skills/lifecycle.py +278 -0
  210. package/python/foxclaw/skills/markdown_skill.py +174 -0
  211. package/python/foxclaw/skills/markdown_store.py +39 -0
  212. package/python/foxclaw/skills/mcp_client.py +190 -0
  213. package/python/foxclaw/skills/mcp_store.py +43 -0
  214. package/python/foxclaw/skills/permission.py +180 -0
  215. package/python/foxclaw/skills/pipeline.py +386 -0
  216. package/python/foxclaw/skills/policy.py +80 -0
  217. package/python/foxclaw/skills/review.py +72 -0
  218. package/python/foxclaw/skills/store.py +57 -0
  219. package/python/frontend/assets/core_bg.jpg +0 -0
  220. package/python/frontend/deck/auth.js +32 -0
  221. package/python/frontend/deck/chat_model_picker.js +537 -0
  222. package/python/frontend/deck/domain.js +296 -0
  223. package/python/frontend/deck/main.js +1950 -0
  224. package/python/frontend/deck/markdown.js +48 -0
  225. package/python/frontend/deck/settings.js +324 -0
  226. package/python/frontend/deck/state.js +6 -0
  227. package/python/frontend/deck/util.js +6 -0
  228. package/python/frontend/deck/visuals.js +212 -0
  229. package/python/frontend/deck.css +855 -0
  230. package/python/frontend/deck.html +686 -0
  231. package/python/frontend/deck_v2.html +341 -0
  232. package/python/frontend/planet/index.html +266 -0
  233. package/python/frontend/planet/planet.css +579 -0
  234. package/python/frontend/planet/planet.js +1637 -0
  235. package/python/frontend/planet/vendor/three.core.min.js +6 -0
  236. package/python/frontend/planet/vendor/three.module.min.js +6 -0
  237. package/python/frontend/v3/assets/index-BD7VPbMV.js +33 -0
  238. package/python/frontend/v3/assets/index-CAvnYWGH.css +1 -0
  239. package/python/frontend/v3/index.html +15 -0
  240. package/python/frontend/widget_runtime.js +295 -0
  241. package/python/frontend/widgets.js +696 -0
  242. package/python/frontend_src/index.html +14 -0
  243. package/python/frontend_src/package-lock.json +1376 -0
  244. package/python/frontend_src/package.json +19 -0
  245. package/python/frontend_src/src/App.vue +62 -0
  246. package/python/frontend_src/src/api.js +89 -0
  247. package/python/frontend_src/src/components/ChatDock.vue +377 -0
  248. package/python/frontend_src/src/components/ComposerMenu.vue +75 -0
  249. package/python/frontend_src/src/components/DocViewer.vue +171 -0
  250. package/python/frontend_src/src/components/Inspector.vue +241 -0
  251. package/python/frontend_src/src/components/LeftRail.vue +394 -0
  252. package/python/frontend_src/src/components/MenuPopover.vue +130 -0
  253. package/python/frontend_src/src/components/MessageStream.vue +401 -0
  254. package/python/frontend_src/src/components/ModelPicker.vue +355 -0
  255. package/python/frontend_src/src/components/QuickIngest.vue +118 -0
  256. package/python/frontend_src/src/components/Stage.vue +226 -0
  257. package/python/frontend_src/src/components/ToolMenu.vue +144 -0
  258. package/python/frontend_src/src/components/TopBar.vue +90 -0
  259. package/python/frontend_src/src/components/panels/ActivityPanel.vue +84 -0
  260. package/python/frontend_src/src/components/panels/AgentsPanel.vue +86 -0
  261. package/python/frontend_src/src/components/panels/KnowledgePanel.vue +441 -0
  262. package/python/frontend_src/src/components/panels/MemoryPanel.vue +118 -0
  263. package/python/frontend_src/src/components/panels/PanelBox.vue +51 -0
  264. package/python/frontend_src/src/components/panels/ReviewPanel.vue +308 -0
  265. package/python/frontend_src/src/components/panels/SettingsPanel.vue +254 -0
  266. package/python/frontend_src/src/components/panels/TasksPanel.vue +74 -0
  267. package/python/frontend_src/src/components/panels/ToolsPanel.vue +640 -0
  268. package/python/frontend_src/src/components/panels/UsagePanel.vue +105 -0
  269. package/python/frontend_src/src/lib/fmt.js +48 -0
  270. package/python/frontend_src/src/lib/md.js +204 -0
  271. package/python/frontend_src/src/main.js +7 -0
  272. package/python/frontend_src/src/stores/app.js +106 -0
  273. package/python/frontend_src/src/stores/chat.js +484 -0
  274. package/python/frontend_src/src/stores/model.js +104 -0
  275. package/python/frontend_src/src/stores/panels.js +330 -0
  276. package/python/frontend_src/src/styles/base.css +138 -0
  277. package/python/frontend_src/src/styles/panel.css +117 -0
  278. package/python/frontend_src/src/styles/tokens.css +78 -0
  279. package/python/frontend_src/vite.config.js +46 -0
  280. package/python/pyproject.toml +265 -0
  281. package/python/skills/README.md +123 -0
  282. package/python/skills/execution-contract/SKILL.md +30 -0
  283. package/python/skills/general-assistant/SKILL.md +34 -0
  284. package/python/skills/planner/SKILL.md +33 -0
  285. package/python/skills/schedule-itinerary/SKILL.md +35 -0
  286. package/python/skills/skill-composition/SKILL.md +31 -0
  287. package/python/skills/skill-guard/SKILL.md +67 -0
  288. package/python/skills/skill-memory/SKILL.md +50 -0
  289. package/python/skills/skill-router/SKILL.md +35 -0
  290. package/python/tests/conftest.py +76 -0
  291. package/python/tests/run_all.py +263 -0
  292. package/python/tests/test_agent_lifecycle.py +360 -0
  293. package/python/tests/test_ahs_p2.py +414 -0
  294. package/python/tests/test_anthropic_tools.py +206 -0
  295. package/python/tests/test_api.py +87 -0
  296. package/python/tests/test_api_auth.py +83 -0
  297. package/python/tests/test_api_host_guard.py +69 -0
  298. package/python/tests/test_attachments.py +167 -0
  299. package/python/tests/test_audit_chain.py +121 -0
  300. package/python/tests/test_audit_sink.py +136 -0
  301. package/python/tests/test_browser.py +153 -0
  302. package/python/tests/test_browser_request_guard.py +184 -0
  303. package/python/tests/test_capabilities.py +158 -0
  304. package/python/tests/test_channel_signing.py +192 -0
  305. package/python/tests/test_channel_trust.py +109 -0
  306. package/python/tests/test_channels.py +184 -0
  307. package/python/tests/test_cli.py +46 -0
  308. package/python/tests/test_compaction_toolpair.py +119 -0
  309. package/python/tests/test_config_layering.py +65 -0
  310. package/python/tests/test_confirm_nonce.py +197 -0
  311. package/python/tests/test_context_compaction_wiring.py +130 -0
  312. package/python/tests/test_dispatch.py +95 -0
  313. package/python/tests/test_domain_evals.py +403 -0
  314. package/python/tests/test_domain_import.py +78 -0
  315. package/python/tests/test_domain_reasoners.py +148 -0
  316. package/python/tests/test_e2e.py +178 -0
  317. package/python/tests/test_emb_cache.py +107 -0
  318. package/python/tests/test_embedding_singleton.py +89 -0
  319. package/python/tests/test_envfile.py +83 -0
  320. package/python/tests/test_evals_smoke.py +114 -0
  321. package/python/tests/test_event_spine.py +182 -0
  322. package/python/tests/test_evidence_semantic.py +101 -0
  323. package/python/tests/test_evidence_sse.py +97 -0
  324. package/python/tests/test_file_ingest.py +146 -0
  325. package/python/tests/test_finance.py +153 -0
  326. package/python/tests/test_finance_ledger.py +252 -0
  327. package/python/tests/test_finance_persist.py +178 -0
  328. package/python/tests/test_gateway.py +144 -0
  329. package/python/tests/test_governance.py +468 -0
  330. package/python/tests/test_governance_audit.py +359 -0
  331. package/python/tests/test_governance_middleware.py +143 -0
  332. package/python/tests/test_hkc.py +286 -0
  333. package/python/tests/test_hkc_index_build_manager.py +339 -0
  334. package/python/tests/test_hkc_manifest_reuse.py +317 -0
  335. package/python/tests/test_hkc_search_event_sync.py +533 -0
  336. package/python/tests/test_import_path_guard.py +161 -0
  337. package/python/tests/test_injection_guard.py +211 -0
  338. package/python/tests/test_integration.py +141 -0
  339. package/python/tests/test_itinerary.py +103 -0
  340. package/python/tests/test_kee_semantic.py +89 -0
  341. package/python/tests/test_kernel.py +222 -0
  342. package/python/tests/test_learning.py +110 -0
  343. package/python/tests/test_llm_admin.py +160 -0
  344. package/python/tests/test_llm_planner.py +366 -0
  345. package/python/tests/test_markdown_skills.py +73 -0
  346. package/python/tests/test_markdown_skills_openclaw.py +71 -0
  347. package/python/tests/test_mcp_connectors.py +109 -0
  348. package/python/tests/test_mcp_guardian_discovery.py +91 -0
  349. package/python/tests/test_mcp_no_memory.py +43 -0
  350. package/python/tests/test_mcp_policy_gate.py +77 -0
  351. package/python/tests/test_mcp_server.py +95 -0
  352. package/python/tests/test_memory_recall.py +95 -0
  353. package/python/tests/test_metrics.py +66 -0
  354. package/python/tests/test_multi_chain.py +102 -0
  355. package/python/tests/test_multimodal.py +135 -0
  356. package/python/tests/test_negotiation.py +146 -0
  357. package/python/tests/test_orchestration.py +119 -0
  358. package/python/tests/test_orchestration_decoupled.py +109 -0
  359. package/python/tests/test_p3_p5_hardening.py +338 -0
  360. package/python/tests/test_parallel_dispatch.py +215 -0
  361. package/python/tests/test_pipeline.py +533 -0
  362. package/python/tests/test_plan_visible.py +86 -0
  363. package/python/tests/test_planner.py +95 -0
  364. package/python/tests/test_policy_gate.py +109 -0
  365. package/python/tests/test_reasoner.py +185 -0
  366. package/python/tests/test_release_check.py +263 -0
  367. package/python/tests/test_resume_checkpoint.py +156 -0
  368. package/python/tests/test_routing.py +95 -0
  369. package/python/tests/test_scheduler.py +141 -0
  370. package/python/tests/test_search.py +204 -0
  371. package/python/tests/test_secrets.py +159 -0
  372. package/python/tests/test_semantic.py +78 -0
  373. package/python/tests/test_sessions.py +91 -0
  374. package/python/tests/test_settings.py +281 -0
  375. package/python/tests/test_shadow_learning.py +330 -0
  376. package/python/tests/test_shared_write.py +207 -0
  377. package/python/tests/test_skill_taint_gate.py +154 -0
  378. package/python/tests/test_skills.py +133 -0
  379. package/python/tests/test_stats_and_events.py +165 -0
  380. package/python/tests/test_streaming.py +60 -0
  381. package/python/tests/test_supervisor_pipeline.py +177 -0
  382. package/python/tests/test_supervisor_triage.py +108 -0
  383. package/python/tests/test_taint.py +117 -0
  384. package/python/tests/test_task_stream.py +85 -0
  385. package/python/tests/test_thinking_sse.py +67 -0
  386. package/python/tests/test_thinking_stream.py +76 -0
  387. package/python/tests/test_tool_center.py +129 -0
  388. package/python/tests/test_tool_parallel.py +113 -0
  389. package/python/tests/test_tool_params.py +103 -0
  390. package/python/tests/test_tool_use.py +242 -0
  391. package/python/tests/test_toplevel_concurrency.py +117 -0
  392. package/python/tests/test_tracing.py +290 -0
  393. package/python/tests/test_truth_crystallizer.py +127 -0
  394. package/python/tests/test_truth_flow.py +93 -0
  395. package/python/tests/test_url_policy.py +53 -0
  396. package/python/tests/test_verify_evidence.py +225 -0
  397. package/python/tests/test_version_sync.py +71 -0
  398. package/python/tests/test_web_trigger.py +99 -0
  399. package/python/tools/check_faiss_type.py +31 -0
  400. package/python/tools/check_log.ps1 +46 -0
  401. package/python/tools/ivf_status.py +72 -0
  402. package/python/tools/mypy_baseline.txt +5 -0
  403. package/python/tools/mypy_ratchet.py +97 -0
  404. package/python/tools/pack.py +178 -0
  405. package/python/tools/release_check.py +349 -0
  406. package/python/tools/restart_foxclaw.ps1 +74 -0
  407. package/python/tools/shared_write_audit.py +204 -0
  408. package/python/tools/size_baseline.txt +28 -0
  409. package/python/tools/size_check.py +102 -0
  410. package/python/tools/verify_env.bat +2 -0
  411. package/python/tools/verify_env.py +25 -0
  412. package/python/vendor/HMR_LICENSE +37 -0
  413. package/python/vendor/HMR_README.md +65 -0
  414. package/python/vendor/hkc/LICENSE +37 -0
  415. package/python/vendor/hkc/hkc_ace/__init__.py +0 -0
  416. package/python/vendor/hkc/hkc_ace/ace.py +457 -0
  417. package/python/vendor/hkc/hkc_ace/skill_taxonomy.json +465 -0
  418. package/python/vendor/hkc/hkc_api/__init__.py +0 -0
  419. package/python/vendor/hkc/hkc_api/container.py +416 -0
  420. package/python/vendor/hkc/hkc_api/ingest_jobs.py +103 -0
  421. package/python/vendor/hkc/hkc_api/main.py +157 -0
  422. package/python/vendor/hkc/hkc_api/routes/__init__.py +0 -0
  423. package/python/vendor/hkc/hkc_api/routes/ability.py +151 -0
  424. package/python/vendor/hkc/hkc_api/routes/config.py +51 -0
  425. package/python/vendor/hkc/hkc_api/routes/knowledge.py +630 -0
  426. package/python/vendor/hkc/hkc_api/routes/search.py +88 -0
  427. package/python/vendor/hkc/hkc_api/schemas.py +153 -0
  428. package/python/vendor/hkc/hkc_api/synthesis.py +179 -0
  429. package/python/vendor/hkc/hkc_core/__init__.py +0 -0
  430. package/python/vendor/hkc/hkc_core/graph/__init__.py +0 -0
  431. package/python/vendor/hkc/hkc_core/graph/base.py +188 -0
  432. package/python/vendor/hkc/hkc_core/graph/sqlite_store.py +789 -0
  433. package/python/vendor/hkc/hkc_core/models/__init__.py +0 -0
  434. package/python/vendor/hkc/hkc_core/models/enums.py +65 -0
  435. package/python/vendor/hkc/hkc_core/models/ku.py +307 -0
  436. package/python/vendor/hkc/hkc_core/utils/__init__.py +0 -0
  437. package/python/vendor/hkc/hkc_core/utils/id_gen.py +113 -0
  438. package/python/vendor/hkc/hkc_crystallizer/__init__.py +44 -0
  439. package/python/vendor/hkc/hkc_crystallizer/adapters.py +94 -0
  440. package/python/vendor/hkc/hkc_crystallizer/candidate.py +145 -0
  441. package/python/vendor/hkc/hkc_crystallizer/crystallizer.py +179 -0
  442. package/python/vendor/hkc/hkc_crystallizer/ingress.py +90 -0
  443. package/python/vendor/hkc/hkc_kde/__init__.py +0 -0
  444. package/python/vendor/hkc/hkc_kde/chunker.py +197 -0
  445. package/python/vendor/hkc/hkc_kde/extractor.py +623 -0
  446. package/python/vendor/hkc/hkc_kde/kde.py +298 -0
  447. package/python/vendor/hkc/hkc_kde/loaders/__init__.py +0 -0
  448. package/python/vendor/hkc/hkc_kde/loaders/ebook_loader.py +153 -0
  449. package/python/vendor/hkc/hkc_kde/loaders/office_loader.py +194 -0
  450. package/python/vendor/hkc/hkc_kde/loaders/pdf_loader.py +162 -0
  451. package/python/vendor/hkc/hkc_kde/loaders/text_loader.py +157 -0
  452. package/python/vendor/hkc/hkc_kde/loaders/web_loader.py +91 -0
  453. package/python/vendor/hkc/hkc_kde/models.py +74 -0
  454. package/python/vendor/hkc/hkc_kde/packager.py +329 -0
  455. package/python/vendor/hkc/hkc_kde/relation_disc.py +151 -0
  456. package/python/vendor/hkc/hkc_kee/__init__.py +0 -0
  457. package/python/vendor/hkc/hkc_kee/dedup.py +227 -0
  458. package/python/vendor/hkc/hkc_kee/fingerprint.py +106 -0
  459. package/python/vendor/hkc/hkc_kee/kee.py +541 -0
  460. package/python/vendor/hkc/hkc_kep/__init__.py +0 -0
  461. package/python/vendor/hkc/hkc_kep/event_bus.py +205 -0
  462. package/python/vendor/hkc/hkc_sdk/__init__.py +63 -0
  463. package/python/vendor/hkc/hkc_sdk/base.py +151 -0
  464. package/python/vendor/hkc/hkc_sdk/direct_client.py +153 -0
  465. package/python/vendor/hkc/hkc_sdk/exceptions.py +39 -0
  466. package/python/vendor/hkc/hkc_sdk/http_client.py +166 -0
  467. package/python/vendor/hkc/hkc_sdk/models.py +171 -0
  468. package/python/vendor/hkc/hkc_search/__init__.py +0 -0
  469. package/python/vendor/hkc/hkc_search/bm25.py +325 -0
  470. package/python/vendor/hkc/hkc_search/embedding_backends.py +374 -0
  471. package/python/vendor/hkc/hkc_search/graph_search.py +132 -0
  472. package/python/vendor/hkc/hkc_search/hybrid.py +331 -0
  473. package/python/vendor/hkc/hkc_search/index_build_manager.py +378 -0
  474. package/python/vendor/hkc/hkc_search/vector_search.py +484 -0
  475. package/python/vendor/hmr/__init__.py +0 -0
  476. package/python/vendor/hmr/core/__init__.py +0 -0
  477. package/python/vendor/hmr/core/hmr.py +684 -0
  478. package/python/vendor/hmr/core/models.py +310 -0
  479. package/python/vendor/hmr/engines/__init__.py +0 -0
  480. package/python/vendor/hmr/engines/evolution.py +710 -0
  481. package/python/vendor/hmr/engines/jit_compiler.py +472 -0
  482. package/python/vendor/hmr/engines/lifecycle.py +264 -0
  483. package/python/vendor/hmr/engines/policy.py +625 -0
  484. package/python/vendor/hmr/engines/recall.py +260 -0
  485. package/python/vendor/hmr/engines/runtime_state.py +158 -0
  486. package/python/vendor/hmr/engines/scheduler.py +323 -0
  487. package/python/vendor/hmr/engines/semantic.py +150 -0
  488. package/python/vendor/hmr/engines/temporal.py +261 -0
  489. package/python/vendor/hmr/engines/thought_chain.py +635 -0
  490. package/python/vendor/hmr/graph/__init__.py +0 -0
  491. package/python/vendor/hmr/graph/cwg.py +338 -0
  492. package/python/vendor/hmr/graph/memory_graph.py +530 -0
  493. package/python/vendor/hmr/storage/__init__.py +0 -0
  494. package/python/vendor/hmr/storage/memory_fs.py +300 -0
  495. package/python/vendor/hmr/storage/vector_store.py +520 -0
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: skill-guard
3
+ version: "1.0-foxclaw"
4
+ implements: agent-harness-skills/skill-guard
5
+ description: Foxclaw 实现版守门 skill。四阶段权限管线落地在 permission.py;Foxclaw 另有 Harness 三维漂移检测(标准之外的认知护城河);V2 后两者经统一门 PolicyGate 归一。
6
+ bound_modules:
7
+ - foxclaw/skills/permission.py (★ 四阶段权限管线 evaluate)
8
+ - foxclaw/kernel/policy_gate.py (★ V2 统一门:权限 + 漂移归一)
9
+ - foxclaw/harness/harness.py (三维漂移检测,认知护栏)
10
+ - foxclaw/skills/__init__.py (SkillAdapter.invoke 调 check_action)
11
+ - foxclaw/agents/base.py (_think → _reasoning_result → check_reasoning)
12
+ side_effect: read
13
+ trust_level: high
14
+ ---
15
+
16
+ # Skill Guard(Foxclaw 实现版)
17
+
18
+ > 本文件是 AHS 标准 `skill-guard` 在 Foxclaw 的具体实现说明。
19
+ > 标准定义"应该怎样守门",本文件定义"Foxclaw 用哪些真实模块守门"。
20
+
21
+ ## 标准四阶段 → Foxclaw 真实落地
22
+
23
+ > ⚠️ 四阶段**全部实现在 `foxclaw/skills/permission.py::evaluate`**(不是 harness.py——harness 做的是下面另一回事的三维漂移检测)。`SkillAdapter.invoke` 经统一门 `PolicyGate.check_action` 调用 evaluate。
24
+
25
+ | AHS 标准阶段 | Foxclaw 实现 | 代码位置 |
26
+ |-------------|------------|---------|
27
+ | Stage1 validate | 校验 `SkillSpec.params` 必填项 | `skills/permission.py: evaluate`(Stage1) |
28
+ | Stage2 deny>ask>allow | `PermissionRules` 规则匹配(deny 铁律不可覆盖) | `skills/permission.py: evaluate`(Stage2) |
29
+ | Stage3 capability | `side_effect` + `destructive` + `external` + readonly 模式,Fail-closed | `skills/permission.py: evaluate`(Stage3) |
30
+ | Stage4 confirm | 有副作用/external/ask 规则且未确认 → 需确认 | `skills/permission.py: evaluate`(Stage4) |
31
+
32
+ **V2 统一门(①Step4)**:动作权限(上表,`check_action`)与推理漂移(下节 Harness,`check_reasoning`)现归一到 `foxclaw/kernel/policy_gate.py` 的一套 `Verdict`;非 allow 发统一 `policy.decision.*` 审计事件。底层仍是同一次 evaluate/check,行为逐字不变。
33
+
34
+ **V2 管线内 dispatch(A 方案)**:Agent 在认知管线内自主用工具时,`stage_act` 同样经 `SkillAdapter→PolicyGate.check_action` 走本四阶段——**只读自动、有副作用挂起 needs_confirmation(权限门在 dispatch 前拦截⇒零副作用)**,与直呼工具面同一治理。见 `foxclaw/pipeline/cognitive_pipeline.py`。
35
+
36
+ ## Foxclaw 超出标准的部分(护城河)⭐
37
+
38
+ 标准的 guard 只管"工具权限"。Foxclaw 的 Harness 在此之上**增加了认知护栏**,这是 Foxclaw
39
+ 作为认知型 Agent OS 的核心差异:
40
+
41
+ ### 1. 三维漂移检测(标准没有)
42
+ `harness.check(node)` 对每个 ThoughtChain 推理节点计算:
43
+ ```
44
+ delta = 0.5·语义漂移 + 0.3·工具漂移 + 0.2·范围漂移
45
+ ```
46
+ - 语义漂移:推理内容与 Agent 职责基准的距离(防"财务 Agent 去写诗")
47
+ - 工具漂移:是否超出 ALLOWED_TOOL_CATEGORIES
48
+ - 范围漂移:是否超出任务初始范围
49
+
50
+ 判定:`< warn` PASS / `warn~block` WARN / `≥ block` BLOCK(抛 HarnessBlockedError)。
51
+
52
+ ### 2. Shadow 校准模式(标准没有)
53
+ 新 Agent 前 `FOXCLAW_SHADOW_ROUNDS` 轮只观测不拦截,收集真实漂移分布自动校准阈值,
54
+ 避免阈值拍脑袋导致误杀。
55
+
56
+ ### 3. 调度层豁免(对应标准的 mode,但 Foxclaw 特化)
57
+ - `IS_ROUTER=True` 的主管 Agent → `block_on_semantic=False`
58
+ - 主管收到任意输入豁免语义拦截(接收一切是其本职),但工具/范围越权仍拦
59
+ - 领域 Agent 保留完整三维拦截
60
+
61
+ ### 4. Policy 自学习(标准没有)
62
+ 重复出现的漂移模式自动沉淀为 Policy 规则,Policy 版本递增。
63
+
64
+ ## 与标准的关系
65
+
66
+ > Foxclaw 的 guard = AHS 标准的工具权限管线 + Foxclaw 原创的认知漂移检测。
67
+ > 满足标准的同时,在认知维度超出标准。
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: skill-memory
3
+ version: "1.0-foxclaw"
4
+ implements: agent-harness-skills/skill-memory
5
+ description: Foxclaw 实现版记忆 skill。把 AHS 标准的后端无关记忆协议落地到 HMR v2.0 双层记忆引擎。
6
+ bound_modules:
7
+ - foxclaw/core/memory_adapter.py (HMR 适配器)
8
+ - foxclaw/agents/base.py (_recall_memory / _store_memory)
9
+ side_effect: read
10
+ trust_level: high
11
+ ---
12
+
13
+ # Skill Memory(Foxclaw 实现版)
14
+
15
+ > 本文件是 AHS 标准 `skill-memory` 在 Foxclaw 的具体实现说明。
16
+ > 标准定义"后端无关的记忆协议",本文件定义"Foxclaw 用 HMR 怎么实现"。
17
+
18
+ ## 标准三操作 → Foxclaw 真实落地
19
+
20
+ | AHS 标准操作 | Foxclaw 实现 | 代码位置 |
21
+ |-------------|------------|---------|
22
+ | recall 召回 | `_recall_memory(task)` 调 HMR 向量检索 | `agents/base.py` |
23
+ | inject 注入 | 召回结果写入 Agent messages 上下文 | `agents/base.py` |
24
+ | extract 提取 | `_store_memory()` 写入 HMR | `agents/agents.py: OfficeAgent` |
25
+
26
+ ## Foxclaw 的真实记忆引擎(HMR v2.0)
27
+
28
+ 标准说"后端无关",Foxclaw 绑定的真实后端是 **HMR(Hierarchical Memory Runtime)**:
29
+
30
+ ### 双层架构(对应标准的 private/shared)
31
+ - **私有层**:每个 Agent 只能召回自己的记忆(by_agent 分布)
32
+ - **共享层**:标记 shared 的记忆所有 Agent 可召回(如主管的全局决策)
33
+ - 真实统计:`/api/memory/stats` 返回 private/shared/by_agent/relations
34
+
35
+ ### Embedding(对应标准的相关性计算)
36
+ Foxclaw 实际用三档(自动探测):
37
+ - OpenAI Embedding(配了 openai key)
38
+ - Sentence-Transformers(装了 800MB 包)
39
+ - TF-IDF n-gram(降级默认,无需额外依赖)
40
+
41
+ ### 知识图谱(标准未强制,Foxclaw 增强)
42
+ HMR 维护记忆间的关系图(relations),办公 Agent 入库时自动抽取知识关系。
43
+
44
+ ### 衰减(对应标准的 decay_management)
45
+ HMR 按时间 + 引用频率管理记忆生命周期。
46
+
47
+ ## 与标准的关系
48
+
49
+ > 标准是抽象协议(任何向量库/KV 都能实现);
50
+ > Foxclaw 是绑定 HMR v2.0 的真实引擎,带双层、知识图谱、三档 embedding。
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: skill-router
3
+ version: "1.0-foxclaw"
4
+ implements: agent-harness-skills/skill-router
5
+ description: Foxclaw 实现版路由。把 AHS 标准的任务→skill 匹配落地到主管 Agent 的分诊逻辑。
6
+ bound_modules:
7
+ - foxclaw/planning/planner.py (★ P1-2 统一路由原语:is_negated / trigger_route / keyword_hits)
8
+ - foxclaw/skills/pipeline.py (route:在 skill 候选上打分)
9
+ - foxclaw/pipeline/cognitive_pipeline.py (stage_route:A 方案管线内选 skill)
10
+ - foxclaw/agents/agents.py (SupervisorAgent._route / _is_meta:分派到子 Agent)
11
+ side_effect: read
12
+ trust_level: high
13
+ ---
14
+
15
+ # Skill Router(Foxclaw 实现版)
16
+
17
+ > AHS 标准 `skill-router` 在 Foxclaw 的落地。标准定义匹配算法,本文件定义 Foxclaw 用主管 Agent 实现。
18
+
19
+ ## 标准 → Foxclaw 真实落地
20
+
21
+ > ⚠️ **P1-2 后:路由/规划的三步打分原语(否定过滤 0.8×触发命中 + 0.2×描述匹配、`is_negated`、`split_on`)统一收敛到 `foxclaw/planning/planner.py` 单一真源**;主管分派、`skills/pipeline.py::route`、管线内 `stage_route` 都复用它,不再各写一套。
22
+
23
+ | AHS 标准 | Foxclaw 实现 | 代码位置 |
24
+ |---------|------------|---------|
25
+ | 三步打分 / 选主 | `trigger_route(task, candidates)` 统一引擎 | `planning/planner.py: trigger_route` |
26
+ | 否定词检测 | `is_negated`(统一原语);主管另有 `_is_meta` 判元问题 | `planning/planner.py`、`agents.py: _is_meta` |
27
+ | 触发词匹配 | 候选的 triggers 命中(skill 侧)/ `ROUTING_KEYWORDS`(Agent 侧) | `planning/planner.py`、`agents.py` |
28
+ | 选 skill(A 方案) | 管线内 `stage_route` 用 `skills.pipeline.route` 选主 skill 写 `ctx.route` | `pipeline/cognitive_pipeline.py: stage_route` |
29
+ | 兜底 fallback | 无法归类 → 主管自答(助手/行政已下放为 `general-assistant` / `schedule-itinerary` 技能) | `pipeline/supervisor_stages.py: sv_route / sv_dispatch` |
30
+ | 实际分派 | 主管 `subagents[target].run_task()` | `agents.py: SupervisorAgent.run_task` |
31
+
32
+ ## 关键差异
33
+
34
+ > 标准是"选一个 skill_id";Foxclaw 有**两条落地**:① 主管把任务分派给一个**真实 Agent 实例**(agents.py);② A 方案下管线内 `stage_route` 直接选 **skill**(opt-in,默认关)。两者共用 `planning.planner` 打分引擎。
35
+ > 元问题(你是谁/能联网吗)由主管自答,跳过分派——Foxclaw 特有。
@@ -0,0 +1,76 @@
1
+ """pytest 共享配置:sys.path 注入 + 环境隔离(等价于 run_all.py 的 env 注入)。
2
+
3
+ 关键点:env 必须在**模块级**设置(而非 fixture)。因为 pytest 收集阶段就会 import
4
+ 每个测试文件,若 env 晚于 import 设置,测试文件顶层的 `Foxclaw(...)` /
5
+ `TestClient(app)` 会读到未隔离的环境(真实 Key 打外部 API、读真实数据目录等)。
6
+ conftest.py 由 pytest 在收集前加载,故模块级赋值能保证先于任何测试文件 import 生效。
7
+ """
8
+ import os
9
+ import sys
10
+ import tempfile
11
+ from pathlib import Path
12
+
13
+ import pytest
14
+
15
+ _REPO_ROOT = Path(__file__).parent.parent
16
+ if str(_REPO_ROOT) not in sys.path:
17
+ sys.path.insert(0, str(_REPO_ROOT))
18
+
19
+ # ── HKC vendor 隔离 ────────────────────────────────────────────────────────────
20
+ # IDE/Cursor 等 shim 常把 `C:\GitHub\foxclaw-hkc\src` 注入到 sys.path 第一位,
21
+ # 而那是上游低质量代码、跟本项目 vendor/hkc/ 是不同等级。**测试必须打 vendor 真代码**,
22
+ # 否则会出现 tests/test_vendor_path_isolation.py 里那类「绿了但打错对象」的事故。
23
+ # 把 vendor/hkc 强制插到 sys.path[0](即使 shim 在前也覆盖之),后续 `import hkc_*`
24
+ # 全部解析到本仓库 vendor 副本。foxclaw.knowledge 自身也调 _ensure_hkc_importable()
25
+ # 做同样事,但那只在 import foxclaw.knowledge 之后才生效;本测试文件顶层直接
26
+ # import hkc_search 早于它,故在 conftest 阶段就注入更稳。
27
+ _VENDOR_HKC = _REPO_ROOT / "vendor" / "hkc"
28
+ if _VENDOR_HKC.exists() and str(_VENDOR_HKC) not in sys.path:
29
+ sys.path.insert(0, str(_VENDOR_HKC))
30
+
31
+ # ── 规避 pytest 在 Windows + Python 3.14 下的 junction 清理 bug ────────────────
32
+ # pytest 用 Path.symlink_to() 创建 `pytest-current` / `test_*current` 目录 junction
33
+ # 作为「指向最新临时目录」的便利链接。Windows 会把这类 junction 标记为
34
+ # 「不受信任的装入点(untrusted mount point)」,Python 3.14 的 ntpath.realpath 在
35
+ # pytest_sessionfinish 的 cleanup_dead_symlinks 里对它调用 Path.resolve() 时抛
36
+ # WinError 448,并令 pytest 退出码变 1(测试本身全通过)。该 junction 仅作调试便利,
37
+ # 不影响任何测试功能,故在 Windows 上禁用其创建(必须在 basetemp 建立前生效,
38
+ # 而 conftest 的模块级代码早于 basetemp 创建执行,时序安全)。
39
+ if sys.platform == "win32":
40
+ import _pytest.pathlib as _ppl
41
+
42
+ def _skip_force_symlink(root, target, link_to):
43
+ return None
44
+
45
+ _ppl._force_symlink = _skip_force_symlink
46
+
47
+ # ── 环境隔离(与 run_all.py 的 env 注入保持一致,强制覆盖继承环境)──────────────
48
+ # FOXCLAW_SKIP_DOTENV=1:让 api.py 完全不读项目根 .env,防止真实 Key 灌回 / 写真实数据目录。
49
+ os.environ["FOXCLAW_SKIP_DOTENV"] = "1"
50
+ # 锁 shadow 轮数、stub 嵌入、关 MCP、清 provider/model:回归保持离线/免费/确定性。
51
+ os.environ["FOXCLAW_SHADOW_ROUNDS"] = "50"
52
+ os.environ["HF_HUB_OFFLINE"] = "1"
53
+ os.environ["TRANSFORMERS_OFFLINE"] = "1"
54
+ os.environ["HKC_EMBEDDING"] = "stub"
55
+ os.environ["FOXCLAW_MCP_SERVER"] = "0"
56
+ os.environ["FOXCLAW_PROVIDER"] = ""
57
+ os.environ["FOXCLAW_MODEL"] = ""
58
+ # 清空外部 API key(第二道防线):鉴权/网关测试要自行控制 FOXCLAW_API_KEY。
59
+ for _k in ("DEEPSEEK_API_KEY", "ANTHROPIC_API_KEY", "OPENAI_API_KEY",
60
+ "GOOGLE_API_KEY", "DASHSCOPE_API_KEY", "FOXCLAW_API_KEY"):
61
+ os.environ[_k] = ""
62
+
63
+ # 兜底:为未自设 FOXCLAW_DATA_DIR 的测试提供一个临时目录,避免 KeyError。
64
+ # (各测试文件顶层通常会自行 mkdtemp 覆盖此值,此处仅作安全网。)
65
+ os.environ.setdefault("FOXCLAW_DATA_DIR", tempfile.mkdtemp(prefix="foxclaw_test_"))
66
+
67
+
68
+ @pytest.fixture
69
+ def test_dir(tmp_path) -> str:
70
+ """字符串路径的临时目录,替代脚本式测试里的 tempfile.mkdtemp。
71
+
72
+ 注意不能直接用 pytest 内置 `tmpdir`(旧式 py.path.local,在 Windows + Python 3.14
73
+ 下会触发 WinError 448),故返回 str(tmp_path) 供 `Path()` / `tempfile.mkdtemp(dir=...)`
74
+ 等接受字符串的调用点使用。
75
+ """
76
+ return str(tmp_path)
@@ -0,0 +1,263 @@
1
+ """
2
+ Foxclaw — 全量回归测试运行器
3
+ 一次跑完 tests/ 下所有测试,汇总通过/失败,确认整个系统端到端健康。
4
+ 用法:python tests/run_all.py
5
+ """
6
+ import os
7
+ import shutil
8
+ import subprocess
9
+ import sys
10
+ import tempfile
11
+ import time
12
+ from pathlib import Path
13
+
14
+ # Windows GBK 控制台无法编码 ✓/✗(✓/✗)等字符 → 运行器自己把 stdout/stderr 切到
15
+ # utf-8,不依赖调用者预先 set PYTHONUTF8。否则打印结果时 UnicodeEncodeError 直接崩掉汇总。
16
+ # line_buffering=True:本文件由 run_all 汇总输出,单个测试跑满 300s 时整轮可达十余分钟;
17
+ # 若不开行缓冲,`python tests/run_all.py > log.txt` 会因块缓冲而**全程看不到进度**,
18
+ # 只能等结束。开启后每条结果即时落盘,可 tail -f 观察。
19
+ for _s in (sys.stdout, sys.stderr):
20
+ try:
21
+ _s.reconfigure(encoding="utf-8", line_buffering=True)
22
+ except Exception:
23
+ pass
24
+
25
+ TESTS = [
26
+ ("test_e2e.py", "认知运行时端到端"),
27
+ ("test_api.py", "API 端点"),
28
+ ("test_integration.py", "A · 前后端实时链路"),
29
+ ("test_dispatch.py", "D · 主管调度 + 共享记忆"),
30
+ ("test_finance.py", "B · 财务内核"),
31
+ ("test_learning.py", "B · 学习内核"),
32
+ ("test_itinerary.py", "B · 行程内核"),
33
+ ("test_orchestration.py","主管编排 + 跨 Agent"),
34
+ ("test_skills.py", "助手 Skill 接入层"),
35
+ ("test_kernel.py", "内核新模块回归"),
36
+ ("test_governance.py", "运行时治理(幂等/恢复/队列/压缩/循环/钩子)"),
37
+ # —— M5 新增:压缩器工具消息配对(防孤立 tool_call 致 provider 400)——
38
+ ("test_compaction_toolpair.py", "M5·压缩器工具消息配对(原子组切分+畸形输入安全降级)"),
39
+ # —— M4 新增:工具入参校验 + permission Stage 1 真正生效 ——
40
+ ("test_tool_params.py", "M4·工具入参校验(执行侧 schema/Stage1/解析失败可见)"),
41
+ ("test_shared_write.py", "P0-3 · 共享层写入策略(audit/warn/enforce)"),
42
+ ("test_audit_sink.py", "P0-3 · 审计落盘 sink(环形缓冲外的持久样本)"),
43
+ ("test_governance_audit.py", "批次3 · 治理审计链(P1-2/P1-3/P2-0/P3-4 decision_id)"),
44
+ ("test_shadow_learning.py", "批次4 · P0-1 影子学习(shadow→promote/discard+回滚+边界)"),
45
+ ("test_channels.py", "消息渠道(四适配器+闭环+幂等去重)"),
46
+ ("test_evals_smoke.py", "M1 · 治理评测冒烟(拦截率/误报/收敛)"),
47
+ ("test_parallel_dispatch.py", "M2 · 并行子 Agent(fork-join/隔离/并发安全)"),
48
+ ("test_governance_middleware.py", "M3 · 治理中间件(框架无关/装饰器/审计)"),
49
+ ("test_memory_recall.py", "M4 · 记忆隔离召回完整性(根治)"),
50
+ ("test_toplevel_concurrency.py", "顶层任务并发隔离(contextvars)"),
51
+ ("test_api_auth.py", "API 可选鉴权(X-API-Key)"),
52
+ ("test_supervisor_triage.py", "主管分诊与自答策略(关键词直路 / 自答 / stub 兜底)"),
53
+ ("test_supervisor_pipeline.py", "批次5 · P1-1 主管 pipeline 化(八 stage/统一 emit/流式/恢复记账)"),
54
+ ("test_ahs_p2.py", "批次6 · P2层(compose pending/run_async/idempotency日志/recovery计划)+P3-2"),
55
+ ("test_p3_p5_hardening.py", "批次7 · P3收尾(isinstance/常量时间/exact/blocked短路/system归因)+P5-1/P5-3"),
56
+ ("test_browser.py", "浏览器子系统(HIR-Browser:核心逻辑/线程包装/降级)"),
57
+ ("test_hkc.py", "知识核心(HKC融入:装配/检索/H1资源修复/惰性teardown)"),
58
+ ("test_hkc_manifest_reuse.py", "P1·Stage A — manifest v2 复用(roundtrip/8步校验/bm25 0-corpus)"),
59
+ ("test_hkc_search_event_sync.py", "P1·Stage B — 事件→索引 C/U/D 五分支同步(text_hash 跳过/立即落盘)"),
60
+ ("test_hkc_index_build_manager.py", "P1·Stage C — 后台冷构建(状态机/检查点/锁/batch/取消/重启续传)"),
61
+ ("test_search.py", "认知搜索(HSR融入:编排/证据融合/迭代上限/端口降级)"),
62
+ ("test_embedding_singleton.py", "P0·EmbeddingService单例(同名模型进程内只加载一次)"),
63
+ ("test_event_spine.py", "P0·统一事件脊柱(EventSpine/SystemBus门面/harness转发/统一投影)"),
64
+ ("test_agent_lifecycle.py", "P1·任务生命周期收敛(5 run_task→1 模板 + _execute 钩子)"),
65
+ ("test_planner.py", "P1-2·规划原语统一(主管/AHS/search 三处委托一个引擎)"),
66
+ ("test_capabilities.py", "P1-3·能力中枢(Composition Root/打断两处对象环)"),
67
+ ("test_truth_flow.py", "P2·真值流全路径触发(直连任务也进真值链 + _no_emit 防双发)"),
68
+ ("test_orchestration_decoupled.py", "P3·编排层去领域硬编码(通用聚合/路由,领域归属Agent)"),
69
+ ("test_pipeline.py", "v2②·认知管线(perceive/recall/plan/route/act/verify/reflect)"),
70
+ ("test_scheduler.py", "v2①·微内核调度器(并发配额/背压/生命周期/记账)+Lifecycle统一"),
71
+ ("test_policy_gate.py", "v2①Step4·统一准入门(Harness+skill-guard→一套Verdict+审计)"),
72
+ ("test_truth_crystallizer.py", "v2④Step1·真值走HKC/KEE(默认关双写+后台结晶+订阅接线)"),
73
+ ("test_reasoner.py", "v2③Step1·领域认知化(观察→假设→证据→裁决;财务守门人形式化)"),
74
+ ("test_domain_reasoners.py", "v2③Step4·认知化推广(itinerary冲突/learning复习;规则权威+LLM只增强)"),
75
+ ("test_tool_center.py", "工具中心①·技能台真实化(安装/启停/删除/测试/持久化/SSRF审核门/治理)"),
76
+ ("test_mcp_connectors.py", "工具中心②·MCP 连接器(接入/工具成技能/审核/调用/移除/持久化)"),
77
+ ("test_markdown_skills.py", "工具中心③·SKILL.md 指令技能(上传/解析/审核/注入/持久化)"),
78
+ ("test_markdown_skills_openclaw.py", "工具中心③·OpenClaw 兼容(zip包/描述触发/编辑触发词·进程隔离防原生库崩溃)"),
79
+ ("test_mcp_server.py", "内置 MCP 服务器(Foxclaw 作提供者:只读知识+记忆暴露成 MCP 工具)"),
80
+ ("test_mcp_no_memory.py", "MCP ask_foxclaw 不污染记忆(外部任务不写 HMR,正常任务照写)"),
81
+ ("test_streaming.py", "LLM 流式输出(router.stream 分块 + /api/chat/stream SSE 逐字)"),
82
+ ("test_task_stream.py", "D1 · /api/task/stream 任务流式化(逐 stage 进度 + act token + 结果)"),
83
+ ("test_config_layering.py", "E1 · 分层配置(LayeredConfig 三层 + policy 层 deny 不可覆盖)"),
84
+ ("test_semantic.py", "真语义检索 + KEE 语义化(共享ST单例/余弦/矛盾方向;无缓存优雅跳过)"),
85
+ ("test_metrics.py", "ops 监控(请求/LLM 延迟分位+错误率 · 深度健康 · Prometheus)"),
86
+ ("test_routing.py", "任务感知模型路由(fast/smart 分档 + 跨 provider fallback 链)"),
87
+ ("test_file_ingest.py", "文件摄入打通交互层(docx/xlsx 加载器 + KDE 分派 + 上传格式门)"),
88
+ ("test_multimodal.py", "多模态对话(图片随问题发视觉模型 · 按 provider 组装 · 护栏 · stub 降级)"),
89
+ ("test_attachments.py", "多模态渲染·聊天附件(上传/下载/正文提取/护栏/LLM 注入/会话落盘)"),
90
+ ("test_gateway.py", "统一 API 网关(per-client 令牌桶+配额+空闲淘汰+429/Retry-After+启用哲学)"),
91
+ ("test_kee_semantic.py", "KEE 身份/去重(别名确定性匹配·类型隔离·Fact 完整 statement 守 exact)"),
92
+ ("test_domain_import.py", "OS 领域导入超越 csv(finance/learning/itinerary 上传 csv/xlsx/json)"),
93
+ ("test_tracing.py", "请求链路追踪(trace_id 贯穿 请求→Agent→LLM·跨线程 span·有界环存)"),
94
+ ("test_emb_cache.py", "检索/embedding 共享向量缓存(批量只编未命中·跨层共享·LRU 有界·并发)"),
95
+ ("test_multi_chain.py", "智能体层·多步跨 Agent 链式协作(后一步看得到前序结果·上下文封顶)"),
96
+ ("test_web_trigger.py", "联网触发判定(个人数据不误搜·外部话题照搜·纯时间词不触发)"),
97
+ ("test_evidence_semantic.py", "证据融合语义化(否定词边界·幻影矛盾·语义支持边·降级)"),
98
+ ("test_domain_evals.py", "领域推理评测(漏报/误报率+误报归因到规则+规则实例隔离)"),
99
+ ("test_negotiation.py", "智能体层·跨域协商闭环(被拒→让步→再裁决·有界·拒绝不降级)"),
100
+ # —— 以下 4 项此前遗漏于本运行器(P4-4 修复)——
101
+ ("test_tool_use.py", "P2·function-calling 工具化(多轮工具循环/注册表/降级)"),
102
+ ("test_injection_guard.py", "提示词注入纵深防御(检出/wrap_untrusted/内核前缀/隔离)"),
103
+ ("test_sessions.py", "会话存储(增删改查/标题提炼/路径穿越/并发追加)"),
104
+ ("test_stats_and_events.py","记忆统计 + 活动事件(hmr.stats 计数修复/chat.completed)"),
105
+ # —— 以下 4 项为近期新功能测试,此前遗漏于本运行器(接线)——
106
+ ("test_llm_planner.py", "P0-1·LLM 驱动规划器(llm_plan/replan·opt-in+fail-safe+sv_replan)"),
107
+ ("test_anthropic_tools.py", "P0-2·Anthropic tool_use 原生接入(格式转换/解析/回灌/降级)"),
108
+ ("test_taint.py", "数据污点追踪+动态审批门槛(污点分级/传播/TAINT_CONFIRM)"),
109
+ ("test_mcp_guardian_discovery.py", "MCP 发现进守门人(凭证不出主进程·代发现·序列化)"),
110
+ ("test_verify_evidence.py", "三个薄点·失败策略表/执行后核验/执行证据(重试只限只读)"),
111
+ ("test_evidence_sse.py", "执行凭据 SSE 命名事件(与正文分离·纯对话不发)"),
112
+ ]
113
+
114
+ # S2 迁移完成:全部测试均已迁移为 pytest(见 pyproject [tool.pytest.ini_options] 白名单)。
115
+ # 故下面所有文件统一用 `python -m pytest <file> -q` 跑,且**每个文件独立子进程**:
116
+ # 网关/内置MCP/流式限流等测试依赖模块级单例,同一进程内会被首个 import 定死、相互污染。
117
+
118
+ def main():
119
+ here = Path(__file__).parent
120
+ # ── 命令行:支持 --list / --only <substr>(M7)──────────────────────
121
+ # 为什么需要:全量回归 6-7 分钟,改一行代码后只想验 1-2 个文件时成本过高。
122
+ # 此前只能整跑,拖慢了「改完立刻验」的内循环(这也是很多缺陷被放过的原因之一)。
123
+ _argv = sys.argv[1:]
124
+ global TESTS
125
+ if "--list" in _argv:
126
+ print(f"共 {len(TESTS)} 项:")
127
+ for _f, _d in TESTS:
128
+ print(f" {_f:<40} {_d}")
129
+ sys.exit(0)
130
+ _only = None
131
+ if "--only" in _argv:
132
+ _i = _argv.index("--only")
133
+ _only = _argv[_i + 1] if _i + 1 < len(_argv) else None
134
+ if not _only:
135
+ print("--only 需要一个子串参数,例:python tests/run_all.py --only governance")
136
+ sys.exit(2)
137
+ _before = len(TESTS)
138
+ TESTS = [(f, d) for f, d in TESTS if _only in f or _only in d]
139
+ print(f"[filter] '{_only}' 匹配 {len(TESTS)}/{_before} 项\n")
140
+ # HF_HUB_OFFLINE:装了 sentence-transformers 时,每个 Foxclaw() 会载入 all-MiniLM
141
+ # 模型 6 次(5 Harness + 1 HMR embedding),且每次都向 HF Hub 发未认证网络请求——
142
+ # 即便模型已缓存。实测让单次 init 从 ~44s 降到 ~7s,并去除网络抖动(否则被 HF 限流时
143
+ # 某个子测试会顶穿 300s 超时)。模型已本地缓存,离线读取即可;未缓存时 Harness 会自动
144
+ # 降级 n-gram 哈希嵌入,不影响测试判定。PYTHONUTF8:防 Windows GBK 控制台的 ✓/✗ 编码错。
145
+ # ── 测试环境隔离(必须放在最前,否则回归不可复现)────────────────────────
146
+ # FOXCLAW_SKIP_DOTENV=1:让 api.py 完全不读项目根目录的 .env。
147
+ # 为什么不能只靠下面那些空字符串:.env 的加载是 load_dotenv(override=False),
148
+ # 它只保护「当前进程里已存在的键」。但测试常常要 pop 掉某键来验证「未设时的行为」
149
+ # (如 test_gateway.py / test_api_auth.py pop FOXCLAW_API_KEY),pop 完再 import api,
150
+ # .env 就会把键灌回来 —— 空字符串挡不住这种路径。
151
+ # 实测证据:对照树(0 改动)+ 含 FOXCLAW_API_KEY 的 .env → test_gateway 报
152
+ # KeyError: 'enabled';同树删掉 .env → 通过。故必须在源头关掉 .env。
153
+ # 另:开发者 .env 里有真实 Key 与 FOXCLAW_DATA_DIR=./foxclaw_data,不隔离会让测试
154
+ # 真的打外部 API(花钱)并写进真实数据目录。
155
+ # 下面显式置空的 key 作为**第二道防线**,覆盖那些会 import 本运行器 env dict
156
+ # 或直接读 os.environ 的路径(且便于单独运行单个测试文件时也保持确定性)。
157
+ env = dict(os.environ, FOXCLAW_SHADOW_ROUNDS="50",
158
+ HF_HUB_OFFLINE="1", TRANSFORMERS_OFFLINE="1",
159
+ PYTHONUTF8="1", PYTHONIOENCODING="utf-8",
160
+ FOXCLAW_SKIP_DOTENV="1",
161
+ # 强制 stub:回归保持离线/免费/确定性。鉴权与网关必须为「未设」态——
162
+ # test_api_auth / test_gateway 要自行控制 FOXCLAW_API_KEY,这里先兜底清空。
163
+ DEEPSEEK_API_KEY="", ANTHROPIC_API_KEY="", OPENAI_API_KEY="",
164
+ GOOGLE_API_KEY="", DASHSCOPE_API_KEY="", FOXCLAW_API_KEY="",
165
+ # .env 里 FOXCLAW_MCP_SERVER=1 会让 api.py 在 import 时构建 MCP 服务器,
166
+ # 而 test_tracing.py 有两处 `with TestClient(app)`(82/189 行),第二次进
167
+ # lifespan 会撞 StreamableHTTPSessionManager「.run() can only be called
168
+ # once per instance」。回归默认关;test_mcp_server.py 自己会置 1。
169
+ FOXCLAW_MCP_SERVER="0",
170
+ # 锁 stub 模型路由:.env 里 FOXCLAW_PROVIDER=openai/FOXCLAW_MODEL=abab6.5s-chat
171
+ # 是开发者的真实配置,回归不继承(否则路由判定随机器变化)。
172
+ FOXCLAW_PROVIDER="", FOXCLAW_MODEL="",
173
+ # 产品默认 HKC_EMBEDDING=auto(真语义),但回归锁 stub 保确定+快;
174
+ # 真语义单独由 test_semantic.py 显式验证。
175
+ HKC_EMBEDDING="stub")
176
+ print("=" * 64)
177
+ print("Foxclaw · 全量回归测试")
178
+ print("=" * 64)
179
+ results = []
180
+ try:
181
+ import pytest # noqa: F401
182
+ have_pytest = True
183
+ except Exception:
184
+ have_pytest = False
185
+ if not have_pytest:
186
+ print("⚠ 未安装 pytest —— 依赖它的测试将标记为「跳过」。"
187
+ "完整回归请先 `pip install -e \".[dev]\"` 或 `pip install pytest`。\n")
188
+ for fn, desc in TESTS:
189
+ if not have_pytest:
190
+ results.append((desc, "跳过", 0.0))
191
+ print(f" ○ {desc:<28} [跳过:需 pytest]")
192
+ continue
193
+ path = here / fn
194
+ if not path.exists():
195
+ results.append((desc, "缺失", 0)); continue
196
+ t0 = time.time()
197
+ # 每个文件用**独立的 basetemp**,不共用 %TEMP%\pytest-of-<user> 根目录。
198
+ # 为什么:Windows 上该根目录一旦留下损坏的 reparse point(实测 pytest-current
199
+ # unlink 报 WinError 5),pytest 会在 sessionfinish 的 cleanup_numbered_dir 阶段
200
+ # 抛 PermissionError —— 断言全过也返回非 0,7 个文件同时假红,真回归被淹没。
201
+ # 显式 basetemp 后 pytest 不再遍历/清理共用根目录;目录必须预先存在(pytest 不会
202
+ # 为 --basetemp 建父目录,缺了直接 FileNotFoundError),故用 mkdtemp 建好再传。
203
+ _bt = Path(tempfile.mkdtemp(prefix="foxclaw-pt-"))
204
+ try:
205
+ # 统一走 pytest(每文件独立子进程,隔离模块级单例)。
206
+ _cmd = [sys.executable, "-m", "pytest", str(path), "-q",
207
+ f"--basetemp={_bt}"]
208
+ # 显式 utf-8 解码子进程输出:子进程已被 PYTHONUTF8=1 强制输出 utf-8,
209
+ # 父进程若用 Windows 默认 GBK 解码会 UnicodeDecodeError(模型加载进度条等
210
+ # 含非 GBK 字节)→ r.stdout 变 None → 后续拼接 TypeError。errors=replace 兜底。
211
+ r = subprocess.run(_cmd,
212
+ capture_output=True, text=True, timeout=300, env=env,
213
+ encoding="utf-8", errors="replace")
214
+ ok = r.returncode == 0
215
+ # 简单判定:退出码 0 且输出里没有 Traceback
216
+ if "Traceback" in (r.stdout + r.stderr):
217
+ ok = False
218
+ # 原生库偶发崩溃的精准重试:Windows 访问冲突 0xC0000005
219
+ # 是 torch/FAISS/ST 在模型重加载或解释器 teardown 阶段的进程级崩溃——
220
+ # 无 Python Traceback、与断言失败(exit=1)互不混淆,故只对它在同一干净
221
+ # 环境下重试一次(批次4/7 均实锤:基线对照同样崩溃,与业务改动无关;
222
+ # 手动小范围跑全绿,全量回归高内存压力下概率显著升高)。
223
+ # 注意:subprocess 在 Windows 返回无符号 DWORD(0xC0000005=3221225477),
224
+ # PowerShell $LASTEXITCODE 则按有符号显示(-1073741819),两种都表示同一崩溃。
225
+ _ACCESS_VIOLATION = (3221225477, -1073741819)
226
+ if not ok and r.returncode in _ACCESS_VIOLATION and \
227
+ "Traceback" not in (r.stdout + r.stderr):
228
+ r = subprocess.run(_cmd,
229
+ capture_output=True, text=True, timeout=300, env=env,
230
+ encoding="utf-8", errors="replace")
231
+ ok = r.returncode == 0 and "Traceback" not in (r.stdout + r.stderr)
232
+ if ok:
233
+ print(f" ↻ {desc} 首次 0xC0000005 原生崩溃,重试通过(已知环境性偶发)")
234
+ results.append((desc, "通过" if ok else "失败", time.time() - t0))
235
+ if not ok:
236
+ # 打印 15 行而非 3 行:pytest 的 collection error(如缺依赖)把原因
237
+ # 放在 traceback 中段,只截最后 3 行会只剩「ERROR xxx.py」+「Interrupted」,
238
+ # 在 CI 里完全无法定位(2026-10-17 实际踩过:CI 红但日志看不出缺 faiss)。
239
+ tail = (r.stdout + r.stderr).strip().splitlines()[-15:]
240
+ print(f" ✗ {desc} 失败:")
241
+ for line in tail: print(f" {line}")
242
+ # 失败时落盘完整输出,便于复现/定位偶发失败(尤其 teardown 期崩溃)。
243
+ (here / f"_fail_{fn}.txt").write_text(
244
+ r.stdout + r.stderr, encoding="utf-8")
245
+ except subprocess.TimeoutExpired:
246
+ results.append((desc, "超时", 300))
247
+ finally:
248
+ # basetemp 是本文件专用的一次性目录:正常结束由 pytest 自己清,
249
+ # 子进程崩溃/超时会残留,这里统一回收。ignore_errors 兜 Windows 文件占用。
250
+ shutil.rmtree(_bt, ignore_errors=True)
251
+ print(f" {'✓' if results[-1][1]=='通过' else '✗'} {desc:<28} [{results[-1][1]}] {results[-1][2]:.0f}s")
252
+
253
+ print("\n" + "=" * 64)
254
+ passed = sum(1 for _, s, _ in results if s == "通过")
255
+ skipped = sum(1 for _, s, _ in results if s == "跳过")
256
+ total = len(results) - skipped
257
+ suffix = f"(另有 {skipped} 项因缺 pytest 跳过)" if skipped else ""
258
+ print(f"结果:{passed}/{total} 通过{suffix}")
259
+ print("=" * 64)
260
+ return 0 if passed == total else 1
261
+
262
+ if __name__ == "__main__":
263
+ sys.exit(main())