dsh-crwu-workbench 0.0.10

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 (479) hide show
  1. package/CHANGELOG.md +1516 -0
  2. package/LICENSE +26 -0
  3. package/README.en.md +204 -0
  4. package/README.md +521 -0
  5. package/SECURITY.md +39 -0
  6. package/bin/darwin-arm64/crwu +0 -0
  7. package/bin/darwin-arm64/dws +0 -0
  8. package/bin/darwin-arm64/ossutil +0 -0
  9. package/bin/manifest.json +82 -0
  10. package/bin/win32-x64/crwu.exe +0 -0
  11. package/bin/win32-x64/dws.exe +4 -0
  12. package/bin/win32-x64/ossutil.exe +0 -0
  13. package/common/skills/.synced.json +8 -0
  14. package/common/skills/crwu-dws/SKILL.md +208 -0
  15. package/common/skills/crwu-dws/references/00-/347/233/256/345/275/225/345/277/253/347/205/247schema.md +113 -0
  16. package/common/skills/crwu-dws/references/01-/345/256/241/346/240/270/344/270/213/350/275/275/344/270/216manifest/350/247/204/350/214/203.md +115 -0
  17. package/common/skills/crwu-dws/references/02-/347/274/223/345/255/230/344/270/216/345/205/234/345/272/225/346/237/245/346/211/276/350/247/204/350/214/203.md +119 -0
  18. package/common/skills/crwu-dws/scripts/test_dws_source_contract.py +493 -0
  19. package/common/skills/crwu-h3yun-login/SKILL.md +130 -0
  20. package/common/skills/crwu-h3yun-query/SKILL.md +192 -0
  21. package/config/crwu-workbench.yml +26 -0
  22. package/cordis.patch.yml +46 -0
  23. package/lib/client.js +10346 -0
  24. package/lib/index.js +11584 -0
  25. package/package.json +119 -0
  26. package/scripts/prepare.mjs +59 -0
  27. package/skills/README.md +26 -0
  28. package/skills/crwu/crwu-audit/SKILL.md +152 -0
  29. package/skills/crwu/crwu-audit/references/00-input-and-route-profile.md +232 -0
  30. package/skills/crwu/crwu-audit/references/01-report-id-resolution.md +13 -0
  31. package/skills/crwu/crwu-audit/references/02-scope-classification.md +25 -0
  32. package/skills/crwu/crwu-audit/references/03-asset-classification.md +27 -0
  33. package/skills/crwu/crwu-audit/references/04-business-classification.md +63 -0
  34. package/skills/crwu/crwu-audit/references/05-method-classification.md +66 -0
  35. package/skills/crwu/crwu-audit/references/06-overlay-classification.md +42 -0
  36. package/skills/crwu/crwu-audit/references/07-skill-registry.md +57 -0
  37. package/skills/crwu/crwu-audit/references/08-union-dispatch-rules.md +142 -0
  38. package/skills/crwu/crwu-audit/references/09-review-risk-classification.md +85 -0
  39. package/skills/crwu/crwu-audit/references/10-capability-gap-proposal.md +68 -0
  40. package/skills/crwu/crwu-audit/references/11-html-delivery-spec.md +881 -0
  41. package/skills/crwu/crwu-audit/references/12-leaf-common-contract.md +202 -0
  42. package/skills/crwu/crwu-audit/references/13-dingtalk-result-publish.md +88 -0
  43. package/skills/crwu/crwu-audit/references/14-orchestration-workflow.md +52 -0
  44. package/skills/crwu/crwu-audit/references/99-maintenance.md +62 -0
  45. package/skills/crwu/crwu-audit/scripts/README.md +157 -0
  46. package/skills/crwu/crwu-audit/scripts/audit_delivery.py +2736 -0
  47. package/skills/crwu/crwu-audit/scripts/audit_result.schema.json +1659 -0
  48. package/skills/crwu/crwu-audit/scripts/examples/audit-result.sample.json +739 -0
  49. package/skills/crwu/crwu-audit/scripts/fetch_review_records.py +85 -0
  50. package/skills/crwu/crwu-audit/scripts/media_extract.py +513 -0
  51. package/skills/crwu/crwu-audit/scripts/prepare_materials.py +1252 -0
  52. package/skills/crwu/crwu-audit/scripts/test_audit_delivery.py +1678 -0
  53. package/skills/crwu/crwu-audit/scripts/test_audit_multiaxis_router.py +1339 -0
  54. package/skills/crwu/crwu-audit/scripts/test_fetch_review_records.py +77 -0
  55. package/skills/crwu/crwu-audit/scripts/test_media_extract.py +332 -0
  56. package/skills/crwu/crwu-audit/scripts/test_prepare_materials.py +1081 -0
  57. package/skills/crwu/crwu-audit/template/audit-report.html +435 -0
  58. package/skills/crwu/crwu-audit-asset-asset-group-goodwill/SKILL.md +38 -0
  59. package/skills/crwu/crwu-audit-asset-asset-group-goodwill/references/00-applicability.md +28 -0
  60. package/skills/crwu/crwu-audit-asset-asset-group-goodwill/references/01-kb-assembly.md +31 -0
  61. package/skills/crwu/crwu-audit-asset-asset-group-goodwill/references/02-review-focus.md +21 -0
  62. package/skills/crwu/crwu-audit-asset-asset-group-goodwill/references/03-common-contract.md +202 -0
  63. package/skills/crwu/crwu-audit-asset-debt/SKILL.md +38 -0
  64. package/skills/crwu/crwu-audit-asset-debt/references/00-applicability.md +40 -0
  65. package/skills/crwu/crwu-audit-asset-debt/references/01-kb-assembly.md +41 -0
  66. package/skills/crwu/crwu-audit-asset-debt/references/02-review-focus.md +54 -0
  67. package/skills/crwu/crwu-audit-asset-debt/references/03-common-contract.md +202 -0
  68. package/skills/crwu/crwu-audit-asset-enterprise-value/SKILL.md +38 -0
  69. package/skills/crwu/crwu-audit-asset-enterprise-value/references/00-applicability.md +31 -0
  70. package/skills/crwu/crwu-audit-asset-enterprise-value/references/01-kb-assembly.md +35 -0
  71. package/skills/crwu/crwu-audit-asset-enterprise-value/references/02-review-focus.md +33 -0
  72. package/skills/crwu/crwu-audit-asset-enterprise-value/references/03-common-contract.md +202 -0
  73. package/skills/crwu/crwu-audit-asset-equipment/SKILL.md +38 -0
  74. package/skills/crwu/crwu-audit-asset-equipment/references/00-applicability.md +40 -0
  75. package/skills/crwu/crwu-audit-asset-equipment/references/01-kb-assembly.md +39 -0
  76. package/skills/crwu/crwu-audit-asset-equipment/references/02-review-focus.md +52 -0
  77. package/skills/crwu/crwu-audit-asset-equipment/references/03-common-contract.md +202 -0
  78. package/skills/crwu/crwu-audit-asset-intangible/SKILL.md +38 -0
  79. package/skills/crwu/crwu-audit-asset-intangible/references/00-applicability.md +36 -0
  80. package/skills/crwu/crwu-audit-asset-intangible/references/01-kb-assembly.md +40 -0
  81. package/skills/crwu/crwu-audit-asset-intangible/references/02-review-focus.md +68 -0
  82. package/skills/crwu/crwu-audit-asset-intangible/references/03-common-contract.md +202 -0
  83. package/skills/crwu/crwu-audit-asset-inventory/SKILL.md +38 -0
  84. package/skills/crwu/crwu-audit-asset-inventory/references/00-applicability.md +28 -0
  85. package/skills/crwu/crwu-audit-asset-inventory/references/01-kb-assembly.md +31 -0
  86. package/skills/crwu/crwu-audit-asset-inventory/references/02-review-focus.md +21 -0
  87. package/skills/crwu/crwu-audit-asset-inventory/references/03-common-contract.md +202 -0
  88. package/skills/crwu/crwu-audit-asset-mining-right/SKILL.md +38 -0
  89. package/skills/crwu/crwu-audit-asset-mining-right/references/00-applicability.md +31 -0
  90. package/skills/crwu/crwu-audit-asset-mining-right/references/01-kb-assembly.md +35 -0
  91. package/skills/crwu/crwu-audit-asset-mining-right/references/02-review-focus.md +33 -0
  92. package/skills/crwu/crwu-audit-asset-mining-right/references/03-common-contract.md +202 -0
  93. package/skills/crwu/crwu-audit-asset-other/SKILL.md +38 -0
  94. package/skills/crwu/crwu-audit-asset-other/references/00-applicability.md +28 -0
  95. package/skills/crwu/crwu-audit-asset-other/references/01-kb-assembly.md +31 -0
  96. package/skills/crwu/crwu-audit-asset-other/references/02-review-focus.md +21 -0
  97. package/skills/crwu/crwu-audit-asset-other/references/03-common-contract.md +202 -0
  98. package/skills/crwu/crwu-audit-asset-portfolio/SKILL.md +38 -0
  99. package/skills/crwu/crwu-audit-asset-portfolio/references/00-applicability.md +28 -0
  100. package/skills/crwu/crwu-audit-asset-portfolio/references/01-kb-assembly.md +31 -0
  101. package/skills/crwu/crwu-audit-asset-portfolio/references/02-review-focus.md +21 -0
  102. package/skills/crwu/crwu-audit-asset-portfolio/references/03-common-contract.md +202 -0
  103. package/skills/crwu/crwu-audit-asset-realestate/SKILL.md +38 -0
  104. package/skills/crwu/crwu-audit-asset-realestate/references/00-applicability.md +43 -0
  105. package/skills/crwu/crwu-audit-asset-realestate/references/01-kb-assembly.md +75 -0
  106. package/skills/crwu/crwu-audit-asset-realestate/references/02-review-focus.md +93 -0
  107. package/skills/crwu/crwu-audit-asset-realestate/references/03-common-contract.md +202 -0
  108. package/skills/crwu/crwu-audit-asset-scrap-materials/SKILL.md +38 -0
  109. package/skills/crwu/crwu-audit-asset-scrap-materials/references/00-applicability.md +28 -0
  110. package/skills/crwu/crwu-audit-asset-scrap-materials/references/01-kb-assembly.md +31 -0
  111. package/skills/crwu/crwu-audit-asset-scrap-materials/references/02-review-focus.md +21 -0
  112. package/skills/crwu/crwu-audit-asset-scrap-materials/references/03-common-contract.md +202 -0
  113. package/skills/crwu/crwu-audit-asset-transport-equipment/SKILL.md +38 -0
  114. package/skills/crwu/crwu-audit-asset-transport-equipment/references/00-applicability.md +31 -0
  115. package/skills/crwu/crwu-audit-asset-transport-equipment/references/01-kb-assembly.md +35 -0
  116. package/skills/crwu/crwu-audit-asset-transport-equipment/references/02-review-focus.md +33 -0
  117. package/skills/crwu/crwu-audit-asset-transport-equipment/references/03-common-contract.md +202 -0
  118. package/skills/crwu/crwu-audit-biz-asset-operation/SKILL.md +38 -0
  119. package/skills/crwu/crwu-audit-biz-asset-operation/references/00-applicability.md +30 -0
  120. package/skills/crwu/crwu-audit-biz-asset-operation/references/01-kb-assembly.md +32 -0
  121. package/skills/crwu/crwu-audit-biz-asset-operation/references/02-review-focus.md +42 -0
  122. package/skills/crwu/crwu-audit-biz-asset-operation/references/03-common-contract.md +202 -0
  123. package/skills/crwu/crwu-audit-biz-consulting-review/SKILL.md +38 -0
  124. package/skills/crwu/crwu-audit-biz-consulting-review/references/00-applicability.md +30 -0
  125. package/skills/crwu/crwu-audit-biz-consulting-review/references/01-kb-assembly.md +32 -0
  126. package/skills/crwu/crwu-audit-biz-consulting-review/references/02-review-focus.md +40 -0
  127. package/skills/crwu/crwu-audit-biz-consulting-review/references/03-common-contract.md +202 -0
  128. package/skills/crwu/crwu-audit-biz-financial-reporting/SKILL.md +38 -0
  129. package/skills/crwu/crwu-audit-biz-financial-reporting/references/00-applicability.md +41 -0
  130. package/skills/crwu/crwu-audit-biz-financial-reporting/references/01-kb-assembly.md +40 -0
  131. package/skills/crwu/crwu-audit-biz-financial-reporting/references/02-review-focus.md +64 -0
  132. package/skills/crwu/crwu-audit-biz-financial-reporting/references/03-common-contract.md +202 -0
  133. package/skills/crwu/crwu-audit-biz-financing-debt/SKILL.md +38 -0
  134. package/skills/crwu/crwu-audit-biz-financing-debt/references/00-applicability.md +31 -0
  135. package/skills/crwu/crwu-audit-biz-financing-debt/references/01-kb-assembly.md +34 -0
  136. package/skills/crwu/crwu-audit-biz-financing-debt/references/02-review-focus.md +47 -0
  137. package/skills/crwu/crwu-audit-biz-financing-debt/references/03-common-contract.md +202 -0
  138. package/skills/crwu/crwu-audit-biz-investment-capital/SKILL.md +38 -0
  139. package/skills/crwu/crwu-audit-biz-investment-capital/references/00-applicability.md +31 -0
  140. package/skills/crwu/crwu-audit-biz-investment-capital/references/01-kb-assembly.md +34 -0
  141. package/skills/crwu/crwu-audit-biz-investment-capital/references/02-review-focus.md +47 -0
  142. package/skills/crwu/crwu-audit-biz-investment-capital/references/03-common-contract.md +202 -0
  143. package/skills/crwu/crwu-audit-biz-judicial-liquidation-compensation/SKILL.md +38 -0
  144. package/skills/crwu/crwu-audit-biz-judicial-liquidation-compensation/references/00-applicability.md +30 -0
  145. package/skills/crwu/crwu-audit-biz-judicial-liquidation-compensation/references/01-kb-assembly.md +32 -0
  146. package/skills/crwu/crwu-audit-biz-judicial-liquidation-compensation/references/02-review-focus.md +40 -0
  147. package/skills/crwu/crwu-audit-biz-judicial-liquidation-compensation/references/03-common-contract.md +202 -0
  148. package/skills/crwu/crwu-audit-biz-tax-history/SKILL.md +38 -0
  149. package/skills/crwu/crwu-audit-biz-tax-history/references/00-applicability.md +29 -0
  150. package/skills/crwu/crwu-audit-biz-tax-history/references/01-kb-assembly.md +30 -0
  151. package/skills/crwu/crwu-audit-biz-tax-history/references/02-review-focus.md +33 -0
  152. package/skills/crwu/crwu-audit-biz-tax-history/references/03-common-contract.md +202 -0
  153. package/skills/crwu/crwu-audit-biz-transaction-disposal/SKILL.md +38 -0
  154. package/skills/crwu/crwu-audit-biz-transaction-disposal/references/00-applicability.md +31 -0
  155. package/skills/crwu/crwu-audit-biz-transaction-disposal/references/01-kb-assembly.md +34 -0
  156. package/skills/crwu/crwu-audit-biz-transaction-disposal/references/02-review-focus.md +47 -0
  157. package/skills/crwu/crwu-audit-biz-transaction-disposal/references/03-common-contract.md +202 -0
  158. package/skills/crwu/crwu-audit-datacheck/SKILL.md +59 -0
  159. package/skills/crwu/crwu-audit-datacheck/references/00-KB/350/243/205/351/205/215/350/241/250.md +25 -0
  160. package/skills/crwu/crwu-audit-datacheck/references/01-runtime-and-check-catalog.md +139 -0
  161. package/skills/crwu/crwu-audit-datacheck/scripts/recalc_check.py +521 -0
  162. package/skills/crwu/crwu-audit-datacheck/scripts/test_recalc_check.py +419 -0
  163. package/skills/crwu/crwu-audit-datacheck/scripts/test_skill_self_containment.py +44 -0
  164. package/skills/crwu/crwu-audit-external-data/SKILL.md +73 -0
  165. package/skills/crwu/crwu-audit-external-data/references/00-KB/350/243/205/351/205/215/350/241/250.md +38 -0
  166. package/skills/crwu/crwu-audit-external-data/references/01-connector-access.md +116 -0
  167. package/skills/crwu/crwu-audit-external-data/references/02-verification-workflow.md +78 -0
  168. package/skills/crwu/crwu-audit-external-data/scripts/connector_probe.py +374 -0
  169. package/skills/crwu/crwu-audit-external-data/scripts/test_connector_probe.py +264 -0
  170. package/skills/crwu/crwu-audit-output-filter/SKILL.md +34 -0
  171. package/skills/crwu/crwu-audit-output-filter/references/00-applicability.md +7 -0
  172. package/skills/crwu/crwu-audit-output-filter/references/01-kb-assembly.md +11 -0
  173. package/skills/crwu/crwu-audit-output-filter/references/02-review-focus.md +25 -0
  174. package/skills/crwu/crwu-audit-public-general-standards/SKILL.md +46 -0
  175. package/skills/crwu/crwu-audit-public-general-standards/references/00-applicability.md +41 -0
  176. package/skills/crwu/crwu-audit-public-general-standards/references/01-kb-assembly.md +66 -0
  177. package/skills/crwu/crwu-audit-public-general-standards/references/02-review-focus.md +111 -0
  178. package/skills/crwu/crwu-audit-public-general-standards/references/03-execution-contract.md +89 -0
  179. package/skills/crwu/crwu-dev-audit-optimize/SKILL.md +98 -0
  180. package/skills/crwu/crwu-dev-audit-optimize/references/00-/344/274/230/345/214/226/350/247/204/350/214/203/344/270/216/346/226/207/344/273/266/350/220/275/347/202/271.md +132 -0
  181. package/skills/crwu/crwu-dev-audit-optimize/references/01-/345/217/215/351/246/210/345/256/232/344/275/215/344/270/216/347/224/273/345/203/217/346/265/201/347/250/213.md +108 -0
  182. package/skills/crwu/crwu-dev-audit-optimize/references/02-/346/226/271/346/241/210/346/250/241/346/235/277/344/270/216/347/241/256/350/256/244/351/227/250/347/246/201.md +92 -0
  183. package/skills/crwu/crwu-dev-audit-optimize/references/03-AI/344/272/272/345/267/245/345/267/256/350/267/235/345/210/206/346/236/220/346/265/201/347/250/213.md +95 -0
  184. package/skills/crwu/crwu-dev-audit-optimize/scripts/examples/gap-analysis.sample.json +116 -0
  185. package/skills/crwu/crwu-dev-audit-optimize/scripts/gap_analysis.schema.json +33 -0
  186. package/skills/crwu/crwu-dev-audit-optimize/scripts/gap_analysis_delivery.py +475 -0
  187. package/skills/crwu/crwu-dev-audit-optimize/scripts/test_gap_analysis_delivery.py +855 -0
  188. package/skills/crwu/crwu-dev-audit-optimize/template/NOTICE.echarts.txt +7 -0
  189. package/skills/crwu/crwu-dev-audit-optimize/template/echarts.min.js +45 -0
  190. package/skills/crwu/crwu-dev-audit-optimize/template/gap-analysis-report.html +71 -0
  191. package/skills/crwu/crwu-dev-audit-skill-maintainer/SKILL.md +74 -0
  192. package/skills/crwu/crwu-dev-audit-skill-maintainer/references/00-responsibility-and-modes.md +62 -0
  193. package/skills/crwu/crwu-dev-audit-skill-maintainer/references/01-kb-source-discovery.md +89 -0
  194. package/skills/crwu/crwu-dev-audit-skill-maintainer/references/02-child-skill-contract.md +99 -0
  195. package/skills/crwu/crwu-dev-audit-skill-maintainer/references/03-review-item-execution-contract.md +51 -0
  196. package/skills/crwu/crwu-dev-audit-skill-maintainer/references/04-registry-and-mapping-update.md +73 -0
  197. package/skills/crwu/crwu-dev-audit-skill-maintainer/references/05-validation-and-delivery.md +127 -0
  198. package/skills/crwu/crwu-dev-audit-skill-maintainer/references/06-live-routing-reconciliation.md +136 -0
  199. package/skills/crwu/crwu-dev-audit-skill-maintainer/references/07-kb-skill-map.md +411 -0
  200. package/skills/crwu/crwu-dev-audit-skill-maintainer/scripts/README.md +200 -0
  201. package/skills/crwu/crwu-dev-audit-skill-maintainer/scripts/check_audit_skill_mappings.py +2477 -0
  202. package/skills/crwu/crwu-dev-audit-skill-maintainer/scripts/kb_tool.py +577 -0
  203. package/skills/crwu/crwu-dev-audit-skill-maintainer/scripts/test_audit_skill_maintainer.py +5097 -0
  204. package/skills/dws/LICENSE +178 -0
  205. package/skills/dws/NOTICE +17 -0
  206. package/skills/dws/dingtalk-aisearch/SKILL.md +83 -0
  207. package/skills/dws/dingtalk-aisearch/references/aisearch.md +249 -0
  208. package/skills/dws/dingtalk-aisearch/references/intent-guide.md +15 -0
  209. package/skills/dws/dingtalk-aisearch/references/lite-recipes.md +31 -0
  210. package/skills/dws/dingtalk-aitable/SKILL.md +139 -0
  211. package/skills/dws/dingtalk-aitable/references/06-data-analytics.md +11 -0
  212. package/skills/dws/dingtalk-aitable/references/aitable/aitable-advperm.md +251 -0
  213. package/skills/dws/dingtalk-aitable/references/aitable/aitable-attachment.md +49 -0
  214. package/skills/dws/dingtalk-aitable/references/aitable/aitable-best-practices.md +48 -0
  215. package/skills/dws/dingtalk-aitable/references/aitable/aitable-cell-value.md +346 -0
  216. package/skills/dws/dingtalk-aitable/references/aitable/aitable-dashboard-chart.md +46 -0
  217. package/skills/dws/dingtalk-aitable/references/aitable/aitable-data-analysis-sop.md +131 -0
  218. package/skills/dws/dingtalk-aitable/references/aitable/aitable-datasource.md +272 -0
  219. package/skills/dws/dingtalk-aitable/references/aitable/aitable-error-recovery.md +128 -0
  220. package/skills/dws/dingtalk-aitable/references/aitable/aitable-export-import.md +113 -0
  221. package/skills/dws/dingtalk-aitable/references/aitable/aitable-field-properties.md +238 -0
  222. package/skills/dws/dingtalk-aitable/references/aitable/aitable-field.md +186 -0
  223. package/skills/dws/dingtalk-aitable/references/aitable/aitable-filter-sort.md +135 -0
  224. package/skills/dws/dingtalk-aitable/references/aitable/aitable-form.md +130 -0
  225. package/skills/dws/dingtalk-aitable/references/aitable/aitable-formula-guide.md +224 -0
  226. package/skills/dws/dingtalk-aitable/references/aitable/aitable-primary-doc.md +58 -0
  227. package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-create.md +52 -0
  228. package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-delete.md +20 -0
  229. package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-history.md +97 -0
  230. package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-name-key.md +47 -0
  231. package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-query.md +120 -0
  232. package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-share.md +54 -0
  233. package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-stats.md +59 -0
  234. package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-update.md +66 -0
  235. package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-upsert.md +89 -0
  236. package/skills/dws/dingtalk-aitable/references/aitable/aitable-view-config.md +140 -0
  237. package/skills/dws/dingtalk-aitable/references/aitable/aitable-view-extras.md +195 -0
  238. package/skills/dws/dingtalk-aitable/references/aitable/aitable-view-types.md +95 -0
  239. package/skills/dws/dingtalk-aitable/references/aitable/aitable-workflow.md +384 -0
  240. package/skills/dws/dingtalk-aitable/references/aitable-record-ops.md +80 -0
  241. package/skills/dws/dingtalk-aitable/references/aitable-section.md +30 -0
  242. package/skills/dws/dingtalk-aitable/references/aitable.md +59 -0
  243. package/skills/dws/dingtalk-aitable/references/field-rules.md +17 -0
  244. package/skills/dws/dingtalk-aitable/references/intent-guide.md +17 -0
  245. package/skills/dws/dingtalk-aitable/references/recipes/conventions.md +44 -0
  246. package/skills/dws/dingtalk-aitable/references/url-patterns.md +144 -0
  247. package/skills/dws/dingtalk-aitable/scripts/aitable_export_via_task.py +210 -0
  248. package/skills/dws/dingtalk-aitable/scripts/aitable_import_via_task.py +173 -0
  249. package/skills/dws/dingtalk-aitable/scripts/bulk_add_fields.py +273 -0
  250. package/skills/dws/dingtalk-aitable/scripts/import_records.py +333 -0
  251. package/skills/dws/dingtalk-aitable/scripts/upload_attachment.py +190 -0
  252. package/skills/dws/dingtalk-calendar/SKILL.md +137 -0
  253. package/skills/dws/dingtalk-calendar/references/03-meeting.md +56 -0
  254. package/skills/dws/dingtalk-calendar/references/calendar.md +760 -0
  255. package/skills/dws/dingtalk-calendar/references/intent-guide.md +9 -0
  256. package/skills/dws/dingtalk-calendar/references/lite-recipes.md +25 -0
  257. package/skills/dws/dingtalk-calendar/scripts/calendar_free_slot_finder.py +199 -0
  258. package/skills/dws/dingtalk-calendar/scripts/calendar_schedule_meeting.py +233 -0
  259. package/skills/dws/dingtalk-calendar/scripts/calendar_today_agenda.py +139 -0
  260. package/skills/dws/dingtalk-chat/SKILL.md +127 -0
  261. package/skills/dws/dingtalk-chat/references/01-messaging.md +103 -0
  262. package/skills/dws/dingtalk-chat/references/card/callback.md +10 -0
  263. package/skills/dws/dingtalk-chat/references/card/create.md +27 -0
  264. package/skills/dws/dingtalk-chat/references/card/schema.md +14 -0
  265. package/skills/dws/dingtalk-chat/references/card/update.md +13 -0
  266. package/skills/dws/dingtalk-chat/references/chat/chat-bot.md +187 -0
  267. package/skills/dws/dingtalk-chat/references/chat/chat-conversation.md +165 -0
  268. package/skills/dws/dingtalk-chat/references/chat/group-admin.md +144 -0
  269. package/skills/dws/dingtalk-chat/references/chat/group-discovery.md +121 -0
  270. package/skills/dws/dingtalk-chat/references/chat/message-actions.md +132 -0
  271. package/skills/dws/dingtalk-chat/references/chat/message-media.md +76 -0
  272. package/skills/dws/dingtalk-chat/references/chat/message-query.md +135 -0
  273. package/skills/dws/dingtalk-chat/references/chat/thread.md +46 -0
  274. package/skills/dws/dingtalk-chat/references/chat-emoji-list.md +216 -0
  275. package/skills/dws/dingtalk-chat/references/chat.md +140 -0
  276. package/skills/dws/dingtalk-chat/references/contracts.md +70 -0
  277. package/skills/dws/dingtalk-chat/references/intent-guide.md +56 -0
  278. package/skills/dws/dingtalk-contact/SKILL.md +122 -0
  279. package/skills/dws/dingtalk-contact/references/08-directory.md +51 -0
  280. package/skills/dws/dingtalk-contact/references/contact.md +595 -0
  281. package/skills/dws/dingtalk-contact/references/intent-guide.md +14 -0
  282. package/skills/dws/dingtalk-contact/references/lite-recipes.md +30 -0
  283. package/skills/dws/dingtalk-contact/references/recipes/conventions.md +44 -0
  284. package/skills/dws/dingtalk-contact/scripts/contact_dept_members.py +130 -0
  285. package/skills/dws/dingtalk-doc/SKILL.md +112 -0
  286. package/skills/dws/dingtalk-doc/references/04-document.md +57 -0
  287. package/skills/dws/dingtalk-doc/references/contracts.md +40 -0
  288. package/skills/dws/dingtalk-doc/references/doc/doc-block.md +39 -0
  289. package/skills/dws/dingtalk-doc/references/doc/doc-comment.md +29 -0
  290. package/skills/dws/dingtalk-doc/references/doc/doc-create.md +54 -0
  291. package/skills/dws/dingtalk-doc/references/doc/doc-export.md +30 -0
  292. package/skills/dws/dingtalk-doc/references/doc/doc-import.md +28 -0
  293. package/skills/dws/dingtalk-doc/references/doc/doc-info.md +12 -0
  294. package/skills/dws/dingtalk-doc/references/doc/doc-media.md +46 -0
  295. package/skills/dws/dingtalk-doc/references/doc/doc-read.md +56 -0
  296. package/skills/dws/dingtalk-doc/references/doc/doc-update.md +87 -0
  297. package/skills/dws/dingtalk-doc/references/doc/format/doc-jsonml-cookbook.md +469 -0
  298. package/skills/dws/dingtalk-doc/references/doc/format/doc-jsonml-schema.json +526 -0
  299. package/skills/dws/dingtalk-doc/references/doc/format/doc-jsonml-schema.md +711 -0
  300. package/skills/dws/dingtalk-doc/references/doc/style/doc-create-workflow.md +414 -0
  301. package/skills/dws/dingtalk-doc/references/doc/style/doc-style-guideline.md +404 -0
  302. package/skills/dws/dingtalk-doc/references/doc/style/doc-update-workflow.md +316 -0
  303. package/skills/dws/dingtalk-doc/references/doc.md +82 -0
  304. package/skills/dws/dingtalk-doc/references/intent-guide.md +20 -0
  305. package/skills/dws/dingtalk-drive/SKILL.md +128 -0
  306. package/skills/dws/dingtalk-drive/references/drive.md +126 -0
  307. package/skills/dws/dingtalk-drive/references/folder-sync.md +40 -0
  308. package/skills/dws/dingtalk-drive/references/intent-guide.md +22 -0
  309. package/skills/dws/dingtalk-drive/references/lite-recipes.md +39 -0
  310. package/skills/dws/dingtalk-event/SKILL.md +106 -0
  311. package/skills/dws/dingtalk-event/references/event-im-keys.md +54 -0
  312. package/skills/dws/dingtalk-event/references/event-im-lifecycle.md +35 -0
  313. package/skills/dws/dingtalk-event/references/event-im-operations.md +52 -0
  314. package/skills/dws/dingtalk-event/references/event-im-output.md +39 -0
  315. package/skills/dws/dingtalk-event/references/event-im.md +58 -0
  316. package/skills/dws/dingtalk-event/references/event-oa.md +155 -0
  317. package/skills/dws/dingtalk-event/references/event-todo.md +50 -0
  318. package/skills/dws/dingtalk-event/references/event-voip.md +69 -0
  319. package/skills/dws/dingtalk-mail/SKILL.md +113 -0
  320. package/skills/dws/dingtalk-mail/references/09-mail.md +45 -0
  321. package/skills/dws/dingtalk-mail/references/intent-guide.md +8 -0
  322. package/skills/dws/dingtalk-mail/references/lite-recipes.md +45 -0
  323. package/skills/dws/dingtalk-mail/references/mail.md +1889 -0
  324. package/skills/dws/dingtalk-mail/references/recipes/conventions.md +44 -0
  325. package/skills/dws/dingtalk-mail/scripts/mail_send_with_cc.py +122 -0
  326. package/skills/dws/dingtalk-mail/scripts/mail_unread_summary.py +114 -0
  327. package/skills/dws/dingtalk-minutes/SKILL.md +116 -0
  328. package/skills/dws/dingtalk-minutes/references/07-minutes.md +149 -0
  329. package/skills/dws/dingtalk-minutes/references/10-minutes-speaker-match.md +32 -0
  330. package/skills/dws/dingtalk-minutes/references/11-minutes-speaker-correct.md +40 -0
  331. package/skills/dws/dingtalk-minutes/references/intent-guide.md +79 -0
  332. package/skills/dws/dingtalk-minutes/references/lite-recipes.md +25 -0
  333. package/skills/dws/dingtalk-minutes/references/minutes.md +210 -0
  334. package/skills/dws/dingtalk-minutes/references/recipes/conventions.md +33 -0
  335. package/skills/dws/dingtalk-minutes/scripts/minutes_recent_summary.py +196 -0
  336. package/skills/dws/dingtalk-minutes/scripts/test_minutes_scripts.py +222 -0
  337. package/skills/dws/dingtalk-misc/SKILL.md +55 -0
  338. package/skills/dws/dingtalk-misc/references/05-reporting.md +29 -0
  339. package/skills/dws/dingtalk-misc/references/agoal.md +302 -0
  340. package/skills/dws/dingtalk-misc/references/attendance-intent-guide.md +7 -0
  341. package/skills/dws/dingtalk-misc/references/attendance-report.md +109 -0
  342. package/skills/dws/dingtalk-misc/references/attendance-schedule.md +115 -0
  343. package/skills/dws/dingtalk-misc/references/attendance-vacation.md +129 -0
  344. package/skills/dws/dingtalk-misc/references/attendance.md +149 -0
  345. package/skills/dws/dingtalk-misc/references/dev/app.md +42 -0
  346. package/skills/dws/dingtalk-misc/references/dev/connect.md +108 -0
  347. package/skills/dws/dingtalk-misc/references/dev/credentials.md +26 -0
  348. package/skills/dws/dingtalk-misc/references/dev/dev-index.md +13 -0
  349. package/skills/dws/dingtalk-misc/references/dev/event.md +47 -0
  350. package/skills/dws/dingtalk-misc/references/dev/mcp.md +106 -0
  351. package/skills/dws/dingtalk-misc/references/dev/member.md +19 -0
  352. package/skills/dws/dingtalk-misc/references/dev/permission.md +56 -0
  353. package/skills/dws/dingtalk-misc/references/dev/recipes.md +58 -0
  354. package/skills/dws/dingtalk-misc/references/dev/robot.md +74 -0
  355. package/skills/dws/dingtalk-misc/references/dev/security.md +21 -0
  356. package/skills/dws/dingtalk-misc/references/dev/version.md +99 -0
  357. package/skills/dws/dingtalk-misc/references/dev/webapp.md +22 -0
  358. package/skills/dws/dingtalk-misc/references/devapp.md +148 -0
  359. package/skills/dws/dingtalk-misc/references/devdoc-intent-guide.md +7 -0
  360. package/skills/dws/dingtalk-misc/references/devdoc.md +42 -0
  361. package/skills/dws/dingtalk-misc/references/ding.md +184 -0
  362. package/skills/dws/dingtalk-misc/references/hrbrain.md +67 -0
  363. package/skills/dws/dingtalk-misc/references/live.md +23 -0
  364. package/skills/dws/dingtalk-misc/references/markdown.md +167 -0
  365. package/skills/dws/dingtalk-misc/references/oa/oa-form-components.md +345 -0
  366. package/skills/dws/dingtalk-misc/references/oa/oa-process-nodes.md +374 -0
  367. package/skills/dws/dingtalk-misc/references/oa.md +1014 -0
  368. package/skills/dws/dingtalk-misc/references/openapi-explorer.md +47 -0
  369. package/skills/dws/dingtalk-misc/references/pat.md +52 -0
  370. package/skills/dws/dingtalk-misc/references/profile.md +41 -0
  371. package/skills/dws/dingtalk-misc/references/recruit.md +89 -0
  372. package/skills/dws/dingtalk-misc/references/report-conventions.md +44 -0
  373. package/skills/dws/dingtalk-misc/references/report-intent-guide.md +11 -0
  374. package/skills/dws/dingtalk-misc/references/report-lite-recipes.md +25 -0
  375. package/skills/dws/dingtalk-misc/references/report.md +109 -0
  376. package/skills/dws/dingtalk-misc/references/sheet/sheet-batch-operations.md +104 -0
  377. package/skills/dws/dingtalk-misc/references/sheet/sheet-chart.md +69 -0
  378. package/skills/dws/dingtalk-misc/references/sheet/sheet-comment.md +166 -0
  379. package/skills/dws/dingtalk-misc/references/sheet/sheet-conditional-format.md +59 -0
  380. package/skills/dws/dingtalk-misc/references/sheet/sheet-dimension-operations.md +60 -0
  381. package/skills/dws/dingtalk-misc/references/sheet/sheet-dropdown.md +103 -0
  382. package/skills/dws/dingtalk-misc/references/sheet/sheet-export.md +135 -0
  383. package/skills/dws/dingtalk-misc/references/sheet/sheet-filter-view.md +51 -0
  384. package/skills/dws/dingtalk-misc/references/sheet/sheet-filter.md +181 -0
  385. package/skills/dws/dingtalk-misc/references/sheet/sheet-formula.md +192 -0
  386. package/skills/dws/dingtalk-misc/references/sheet/sheet-import.md +76 -0
  387. package/skills/dws/dingtalk-misc/references/sheet/sheet-media-image.md +263 -0
  388. package/skills/dws/dingtalk-misc/references/sheet/sheet-pivot-table.md +292 -0
  389. package/skills/dws/dingtalk-misc/references/sheet/sheet-range-operations.md +161 -0
  390. package/skills/dws/dingtalk-misc/references/sheet/sheet-read-data.md +60 -0
  391. package/skills/dws/dingtalk-misc/references/sheet/sheet-revision-changeset.md +46 -0
  392. package/skills/dws/dingtalk-misc/references/sheet/sheet-search-replace.md +120 -0
  393. package/skills/dws/dingtalk-misc/references/sheet/sheet-style-format.md +71 -0
  394. package/skills/dws/dingtalk-misc/references/sheet/sheet-version.md +84 -0
  395. package/skills/dws/dingtalk-misc/references/sheet/sheet-workbook.md +59 -0
  396. package/skills/dws/dingtalk-misc/references/sheet/sheet-write-data.md +93 -0
  397. package/skills/dws/dingtalk-misc/references/sheet-conventions.md +44 -0
  398. package/skills/dws/dingtalk-misc/references/sheet-intent-guide.md +12 -0
  399. package/skills/dws/dingtalk-misc/references/sheet.md +166 -0
  400. package/skills/dws/dingtalk-misc/references/skill.md +98 -0
  401. package/skills/dws/dingtalk-misc/references/unsupported-scripts.md +49 -0
  402. package/skills/dws/dingtalk-misc/references/url-patterns.md +144 -0
  403. package/skills/dws/dingtalk-misc/references/whiteboard/compose.md +200 -0
  404. package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/01-overview.md +57 -0
  405. package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/02-query.md +288 -0
  406. package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/03-update.md +249 -0
  407. package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/04-text-style.md +395 -0
  408. package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/05-shape-frame-group-connector.md +186 -0
  409. package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/06-vector-icon-path.md +313 -0
  410. package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/07-examples-errors-write-support.md +270 -0
  411. package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/08-catalogs.md +61 -0
  412. package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1.md +54 -0
  413. package/skills/dws/dingtalk-misc/references/whiteboard/replace.md +41 -0
  414. package/skills/dws/dingtalk-misc/references/whiteboard/vector.md +51 -0
  415. package/skills/dws/dingtalk-misc/references/whiteboard.md +115 -0
  416. package/skills/dws/dingtalk-misc/scripts/aiapp_create_and_poll.py +138 -0
  417. package/skills/dws/dingtalk-misc/scripts/attendance_my_record.py +91 -0
  418. package/skills/dws/dingtalk-misc/scripts/attendance_report_checkin.py +440 -0
  419. package/skills/dws/dingtalk-misc/scripts/attendance_report_common.py +1698 -0
  420. package/skills/dws/dingtalk-misc/scripts/attendance_report_daily.py +558 -0
  421. package/skills/dws/dingtalk-misc/scripts/attendance_report_detail.py +809 -0
  422. package/skills/dws/dingtalk-misc/scripts/attendance_report_monthly.py +758 -0
  423. package/skills/dws/dingtalk-misc/scripts/attendance_report_record.py +947 -0
  424. package/skills/dws/dingtalk-misc/scripts/attendance_schedule_export.py +344 -0
  425. package/skills/dws/dingtalk-misc/scripts/attendance_schedule_import.py +498 -0
  426. package/skills/dws/dingtalk-misc/scripts/attendance_team_shift.py +89 -0
  427. package/skills/dws/dingtalk-misc/scripts/attendance_vacation_balance.py +617 -0
  428. package/skills/dws/dingtalk-misc/scripts/finance_daily_cashflow.py +70 -0
  429. package/skills/dws/dingtalk-misc/scripts/finance_expense_flow.py +138 -0
  430. package/skills/dws/dingtalk-misc/scripts/oa_batch_approve.py +158 -0
  431. package/skills/dws/dingtalk-misc/scripts/oa_pending_review.py +132 -0
  432. package/skills/dws/dingtalk-misc/scripts/report_received_today.py +315 -0
  433. package/skills/dws/dingtalk-misc/scripts/yida_custom_page_update.py +401 -0
  434. package/skills/dws/dingtalk-misc/scripts/yida_form_builder.py +526 -0
  435. package/skills/dws/dingtalk-misc/scripts/yida_form_fields.py +315 -0
  436. package/skills/dws/dingtalk-misc/scripts/yida_form_inspector.py +311 -0
  437. package/skills/dws/dingtalk-misc/scripts/yida_form_update.py +185 -0
  438. package/skills/dws/dingtalk-misc/scripts/yida_jsx_pipeline.py +1588 -0
  439. package/skills/dws/dingtalk-misc/scripts/yida_page_compiler.py +1441 -0
  440. package/skills/dws/dingtalk-misc/scripts/yida_page_generate.py +514 -0
  441. package/skills/dws/dingtalk-misc/scripts/yida_page_schema.py +519 -0
  442. package/skills/dws/dingtalk-misc/scripts/yida_page_self_check.py +398 -0
  443. package/skills/dws/dingtalk-misc/scripts/yida_process_flow.py +1478 -0
  444. package/skills/dws/dingtalk-misc/scripts/yida_process_update.py +589 -0
  445. package/skills/dws/dingtalk-misc/scripts/yida_report_builder.py +494 -0
  446. package/skills/dws/dingtalk-misc/scripts/yida_report_charts.py +1434 -0
  447. package/skills/dws/dingtalk-misc/scripts/yida_report_update.py +244 -0
  448. package/skills/dws/dingtalk-misc/scripts/yida_schema_common.py +340 -0
  449. package/skills/dws/dingtalk-shared/SKILL.md +83 -0
  450. package/skills/dws/dingtalk-shared/references/capability-limits.md +31 -0
  451. package/skills/dws/dingtalk-shared/references/channel-login.md +26 -0
  452. package/skills/dws/dingtalk-shared/references/confirmation.md +59 -0
  453. package/skills/dws/dingtalk-shared/references/error-codes.md +155 -0
  454. package/skills/dws/dingtalk-shared/references/global-reference.md +122 -0
  455. package/skills/dws/dingtalk-shared/references/intent-guide.md +537 -0
  456. package/skills/dws/dingtalk-shared/references/recipes/conventions.md +45 -0
  457. package/skills/dws/dingtalk-shared/references/recipes/lite-catalog.md +275 -0
  458. package/skills/dws/dingtalk-shared/references/recipes/meta.md +67 -0
  459. package/skills/dws/dingtalk-shared/references/routing.md +52 -0
  460. package/skills/dws/dingtalk-shared/references/runtime-contract.md +11 -0
  461. package/skills/dws/dingtalk-shared/references/schema-usage.md +88 -0
  462. package/skills/dws/dingtalk-shared/references/url-patterns.md +144 -0
  463. package/skills/dws/dingtalk-shared/references/workflow-routing.md +45 -0
  464. package/skills/dws/dingtalk-todo/SKILL.md +119 -0
  465. package/skills/dws/dingtalk-todo/references/02-task.md +70 -0
  466. package/skills/dws/dingtalk-todo/references/intent-guide.md +15 -0
  467. package/skills/dws/dingtalk-todo/references/lite-recipes.md +68 -0
  468. package/skills/dws/dingtalk-todo/references/recipes/conventions.md +44 -0
  469. package/skills/dws/dingtalk-todo/references/todo.md +517 -0
  470. package/skills/dws/dingtalk-todo/scripts/todo_batch_create.py +354 -0
  471. package/skills/dws/dingtalk-todo/scripts/todo_daily_summary.py +153 -0
  472. package/skills/dws/dingtalk-todo/scripts/todo_overdue_check.py +101 -0
  473. package/skills/dws/dingtalk-wiki/SKILL.md +117 -0
  474. package/skills/dws/dingtalk-wiki/references/intent-guide.md +14 -0
  475. package/skills/dws/dingtalk-wiki/references/lite-recipes.md +44 -0
  476. package/skills/dws/dingtalk-wiki/references/wiki-members.md +32 -0
  477. package/skills/dws/dingtalk-wiki/references/wiki-node-ops.md +46 -0
  478. package/skills/dws/dingtalk-wiki/references/wiki.md +65 -0
  479. package/skills/dws/provenance.json +27 -0
@@ -0,0 +1,119 @@
1
+ # crwu-dws references/02 —— 目录缓存与兜底查找规范(缓存层 / node-index / M3 协议)
2
+
3
+ > 版本 v1.3(2026-09-15:随 crwu-dws v0.6,node-index 条目新增 `extension`/`contentType` 并作为 §5 正文取数通道判据)。
4
+ > 版本 v1.2(2026-09-08:v1.1 随 crwu-dws v0.3.1 新增 §2 缓存身份与名一致性清理层,原 §2–6 顺移为 §3–7;v1.2 随 v0.4 新增 node-index 全路径键 `by_path`(M3 路径寻址)与路径命中报告口径)。
5
+ > 本文档随技能安装(源仓与运行时双份);
6
+ > 改前先读本技能 `SKILL.md` §5.0 与 references/00(快照 schema)。
7
+
8
+ ## 1. 核心原则(用户口径,不可违反)
9
+
10
+ 1. **目录可缓存**:目录结构与 nodeId 映射变化低频 → 本地缓存。
11
+ 2. **正文不缓存**:正文内容永远现场从钉钉导出(下载时点=钉钉当前版);M2 下载物仅供本次审核,跨审核必须重新下载。
12
+ 3. **缓存不是事实源**:事实源 = 钉钉实时。缓存只用于"少跑在线遍历";任何"存在性"权威结论须来自一次成功刷新或如实降级。
13
+ 4. **未命中必刷新**:缓存查不到 → 自动在线刷新 → 重查;仍无 → 如实报告"没找到",不编造。
14
+ 5. **防幻觉**:报告必须带结论依据标签(§6);刷新失败不得用旧缓存冒充新鲜。
15
+ 6. **缓存名一致(v0.3.1)**:缓存目录只对与其身份一致的目标库有效;身份(§2)与 skill 目标库名不一致 → **先清理该缓存目录、在线重下后再用**,禁止把别的库的缓存当目标库索引(跨库误命中;SKILL.md §5.0)。
16
+
17
+ ## 2. 缓存身份与名一致性清理(缓存库名 ≠ 目标库名 → 清理重下)
18
+
19
+ 1. **身份**:每个缓存目录的身份 = `.cache-meta.json.space`:`{name, workspaceId}`(服务端真实返回;两字段齐备才可证实身份)。
20
+ 2. **一致性基准(目标库名)**:skill 默认目标名「中瑞世联评估审核知识库」或本次指定库名。M1 与 M3 刷新路径叠加 P1 解析结果,按 name+workspaceId 双匹配对账;M3 命中路径不发起在线遍历,以请求库名做名级对账(workspaceId 一致性在写缓存时已由 P1 校验并固化于 meta)。
21
+ 3. **判据与动作**:身份与目标不一致(名级或双匹配)→ **整体删除该缓存目录**(正式 4 文件 + 残留 `.tmp-*`),再**在线重下目标库目录结构**(= 一次成功完整遍历 → §4 写缓存原子替换 → 重查)。meta 缺失/损坏 → 身份不可证实:目录名 ≠ 目标库名 → 同前删除重建;目录名 == 目标库名 → 不删除,按 §7 缓存损坏走刷新覆盖重建。
22
+ 4. **范围与安全**:删除只作用于 `dws-dir-cache`——目录缓存 = 可再生中间产物、无正文,删除即清理协议、不违红线;不碰 M2 当前审核 `knowledge/` 工作集或远端。删除失败 → 该缓存按不可用处理并报告路径问题,不静默复用。
23
+ 5. **防跨库误命中**:node-index 查找只允许发生在与本次目标一致的缓存目录内;被清理目录禁止在清理前被查询。
24
+ 6. **清理报告**:删除动作与原因必须可见("已清理不一致缓存:<目录>(缓存 space=<…>,目标=<…>)")。
25
+
26
+ ## 3. 缓存布局与文件格式
27
+
28
+ ```
29
+ ~/.crwu/knowledge/dws-dir-cache/<库名>/ # 多库各一份;同名多空间 → 追加 -<spaceType>(身份见 §2)
30
+ ├── 目录快照.json # crwu.kb-catalog.snapshot.v1(references/00)——目录元数据唯一事实文件
31
+ ├── 目录树.md # 人读视图(快照渲染,不单独成为事实)
32
+ ├── node-index.json # 查找索引(可由快照重建;写缓存时同步重建)
33
+ └── .cache-meta.json # 缓存元数据(last_successful_at/evidence/统计)
34
+ ```
35
+
36
+ - 缓存目录内**禁止出现任何正文内容文件**(md 正文副本、导出文件等);`.tmp-*` 只允许出现于原子替换的瞬时窗口,替换完即无。
37
+ - 父目录 `~/.crwu/knowledge/` 不可写 → 报告路径问题,不静默改落点、不把正文改存他处绕过红线。
38
+
39
+ ### node-index.json(`crwu.kb-dir-cache.nodeindex.v1`)
40
+
41
+ ```jsonc
42
+ {
43
+ "schema": "crwu.kb-dir-cache.nodeindex.v1",
44
+ "space": { "name": "…", "workspaceId": "…", "spaceType": "…" },
45
+ "built_from_snapshot_at": "ISO8601",
46
+ "by_node_id": { "<nodeId>": { "name": "…", "type": "file", "extension": "adoc", "contentType": "ALIDOC", "folderPath": "顶层folder/子folder…或空", "depth": 1, "parentNodeIds": ["…"] } },
47
+ "by_name": { "<精确名称>": ["<nodeId>", "…"] }, // 同名多命中 → 数组多条
48
+ "by_path": { "<目录链>/<名称>": ["<nodeId>"], "<目录链>/<文件夹>/": ["<nodeId>"] } // 全路径键(v0.4,路径寻址);folder 键尾带 "/"
49
+ }
50
+ ```
51
+
52
+ - `folderPath` = 从根到父的 folder 名称链(不含 node 自身),用于报告树路径上下文;由快照推导,快照缺字段则留空并在索引条目注 `path_partial:true`。
53
+ - **`extension`/`contentType` 随快照同步落索引(v0.6)**:M2/M3 的取数通道由它判定,因此索引必须携带;由旧快照(v0.6 前)重建的索引该字段为 `null` → 取数前按 §5 第 2 步对该 nodeId 补一次 `wiki +node-get`,**不得按名称后缀猜**。
54
+ - 名称索引 key 使用**原样精确名**(不折叠大小写/空白/全半角);查找时同样精确比对——歧义宁可多命中消歧,不做模糊近似命中。
55
+ - `by_path` 全路径键 = 从根起的完整层级链(`folder/…/名称`;folder 节点键尾加 `/`):供 M3 文件级精确命中 / 目录前缀展开(键前缀匹配);同层同名等罕见冲突 → 值可为 nodeId 数组并在报告全列消歧;由快照重建,写缓存时与 `by_name` 同步生成。
56
+
57
+ ### .cache-meta.json(`crwu.kb-dir-cache.meta.v1`)
58
+
59
+ ```jsonc
60
+ { "schema": "crwu.kb-dir-cache.meta.v1",
61
+ "space": { "name": "…", "workspaceId": "…", "spaceType": "…" },
62
+ "source": "dingtalk-live",
63
+ "last_successful_at": "ISO8601", // 最近一次成功完整遍历并写缓存时刻
64
+ "last_refresh_attempt_at": "ISO8601",
65
+ "last_failure": null, // {at, error} 或 null
66
+ "stats": { "total_nodes": 0, "complete": true },
67
+ "profile": { "id": "…", "isOrgCurrent": true } }
68
+ ```
69
+
70
+ ## 4. 写缓存(原子替换;M1 与 M3 刷新共用)
71
+
72
+ 1. 遍历完成且 P4 计数一致(`failures=[]`、每页 `autoPageComplete=true`)才进入写缓存;
73
+ 2. 依次写 `.tmp-目录快照.json` / `.tmp-目录树.md` / `.tmp-node-index.json` / `.tmp-.cache-meta.json` → 全部成功后再逐个 rename 覆盖正式文件(顺序:meta 最后覆盖,保证 meta 落成即代表整套新缓存可见);
74
+ 3. rename 失败 → 保留旧缓存,`last_failure` 记录,摘要说明"缓存未更新:<原因>";
75
+ 4. `complete=false`(遍历不完整)→ **不写缓存**(保留旧缓存),并在报告标注。
76
+
77
+ ## 5. 正文实时拉取协议(M3 命中取正文 / 任何"要最新内容"场景)
78
+
79
+ 1. 目标 = 已知 nodeId(来自缓存命中或刷新后命中)。
80
+ 2. **判通道**:读缓存条目的 `extension`;缺失/`null`(旧缓存)→ 对该 nodeId 补一次节点元数据读取(只读;结果记入本次 evidence,不回写——回写由 §4 写缓存整批完成)。DSH 下这一步由 `crwu_audit_knowledge_materialize` 内部完成。
81
+ 3. **取正文(按 `extension` 分流,与 M2 §1 表一致)**:
82
+ - `adoc` → 走导出通道(manifest 里 `channel=export`);
83
+ - `md` / `txt` → 走原样下载通道(`channel=download`;原件即正文,不转换);
84
+ - 其余类型 → 如实报告"该类型(`<extension>`)不提供正文",**不下载、不伪造、不改用 `doc +export` 硬试**。
85
+ 4. 导出/下载位置 = **本次审核工作目录或系统临时目录**(不属于缓存层);回执 `sizeBytes>0` 即终态。
86
+ 5. 交付内容仅供本次审核推理;进入案例 `knowledge/` 时按 M2 单文件语义登记 manifest,进入临时目录时使用完即清理;两者都**不进缓存层且不得跨审核复用**。
87
+ 6. 取数失败 → 如实报告(失败原因 + 不提供任何"缓存正文"替代——因为缓存根本没有正文)。
88
+
89
+ ## 6. M3 报告口径(结论依据标签必含其一)
90
+
91
+ | 情形 | 报告模板 |
92
+ | --- | --- |
93
+ | 缓存命中 | `缓存命中(generated_at=<…>):<名称>(<type>),目录 <folderPath>,workspaceId=<…>(<spaceType>)`;要正文 → 转 §5 |
94
+ | 名称/路径多命中 | `同名/同路径 <n> 个(缓存 generated_at=<…>):逐一列 <folderPath>;请指定 nodeId`(不猜) |
95
+ | 路径命中(文件级) | `路径命中(generated_at=<…>):<名称>(<type>),目录 <folderPath>,workspaceId=<…>(<spaceType>)`;要正文 → 转 §5 |
96
+ | 目录前缀命中 | `目录前缀命中(generated_at=<…>):<目录> 下条目 <n> 个(folder/adoc/axls/… 分类列出)` |
97
+ | 刷新后命中 | `刷新后命中(刷新于 <时间>):…` |
98
+ | 刷新后仍无 | `未找到:<名称/nodeId/路径>(目录已刷新至 <时间> 后仍不存在);相近候选:<名称列表 ≤5>` |
99
+ | 降级(刷新失败有旧缓存) | `缓存可能过期(generated_at=<…>,刷新失败:<原因>):<按旧缓存作答>,结论不具权威性` |
100
+ | 无法确认 | `无法确认(缓存缺失且在线刷新失败:<原因>)` |
101
+ | 未找到且无候选 | `未找到:<名称/nodeId/路径>(目录已刷新至 <时间>,无相近候选)` |
102
+
103
+ - "相近候选"来自刷新后快照的简单名称包含匹配(≤5),仅作提示,**不视为命中**。
104
+
105
+ ## 7. 校验与自查
106
+
107
+ - 缓存完整性:`.cache-meta.json` 的 `last_successful_at` 与 `目录快照.json.generated_at` 一致;`node-index.json.built_from_snapshot_at` 一致;任一文件 JSON 解析失败/缺失 → 视为缓存缺失,M3 自动刷新重建。
108
+ - 缓存身份自检:缓存目录名与其 `.cache-meta.json.space` 指向一致;身份与目标库名不一致的目录按 §2 清理重建(SKILL.md §5.0)。
109
+ - 正文红线自查:缓存目录递归列出,只允许 4 个正式文件 + 瞬时 `.tmp-*`;出现其他文件 → 报"缓存目录被污染"并报告(不自动删除用户文件,提示人工处置)。
110
+ - **通道判据自检(v0.6)**:node-index 中文档条目的 `extension` 覆盖率。v0.6 后新建/重建的缓存应为 100%(快照 §2 强制记录);低于 100% 说明该缓存源自旧结构 → 取数前按 §5 第 2 步逐节点补查,并在报告注明"缓存为旧版结构,通道判据已按 `node-get` 补齐"(这是可接受的降级,不是缓存损坏)。
111
+
112
+ <!-- crwu-cli-guard:legacy-compat-start -->
113
+ > **非 DSH 宿主兼容层(legacy CLI)**:上面两步在非 DSH 宿主分别对应
114
+ > `dws wiki +node-get --format json`(补 `extension`)、
115
+ > `dws doc +export --node <nodeId> --export-format markdown`(adoc 导出)与
116
+ > `dws drive +download --node <nodeId> --output <临时区相对路径>`(原生文本)。
117
+ > DSH 环境下这些都由 `crwu_audit_knowledge_materialize` 内部完成。
118
+
119
+ <!-- crwu-cli-guard:legacy-compat-end -->
@@ -0,0 +1,493 @@
1
+ from pathlib import Path
2
+ import glob
3
+ import unittest
4
+
5
+
6
+ # 源仓契约测试:据本文件位置上溯定位技能层与源仓根(不硬编码仓库布局)。
7
+ # 运行时不需要本测试;已安装副本内缺少同级技能或源仓文档时显式 skip(不静默通过)。
8
+ #
9
+ # **技能在源仓按层组织**:DSH 把每个技能**层**注册成一个技能根 ——
10
+ # `plugins/<插件>/skills/<层>/<技能>/`(本仓是 crwu / dws 两层)与公共层
11
+ # `plugins/common/skills/<技能>/`。所以"同级技能"必须**跨层**查找;只在本技能所在的层里找,
12
+ # 会把整个契约测试静默 skip 掉(2026-09 合并仓库时就发生过:8~12 条断言静默消失)。
13
+ SKILLS_ROOT = Path(__file__).resolve().parents[2] # skills/<层>/<技能>/scripts/<file> → 本技能所在的层
14
+
15
+
16
+ def _has_skill_child(directory: Path) -> bool:
17
+ """目录里直接放着技能(`<子目录>/SKILL.md`)—— 按内容判定,不靠目录名约定。"""
18
+ return directory.is_dir() and any(
19
+ (child / "SKILL.md").is_file() for child in directory.iterdir() if child.is_dir()
20
+ )
21
+
22
+
23
+ def _skill_roots(start: Path) -> tuple[Path, ...]:
24
+ """本技能所在的层 + 源仓里其它所有技能层(跨插件、跨层)。
25
+
26
+ DSH 运行时把每个层都注册成技能根,所以"同级技能"必须跨层查找(只在本技能所在的层里找,
27
+ 整个契约测试会被静默 skip 掉)。安装副本里没有 `plugins/`,只剩本技能所在的层 ——
28
+ 那时同级技能本来就不存在,记 skip 是对的。
29
+ """
30
+ roots = [start]
31
+ for candidate in start.parents:
32
+ plugins = candidate / "plugins"
33
+ if not plugins.is_dir():
34
+ continue
35
+ for skills in sorted(plugins.glob("*/skills")):
36
+ if not skills.is_dir():
37
+ continue
38
+ if _has_skill_child(skills):
39
+ roots.append(skills) # 公共层:技能直接放在 skills/ 下
40
+ else:
41
+ roots.extend(sorted(layer for layer in skills.iterdir() if _has_skill_child(layer)))
42
+ break
43
+ return tuple(dict.fromkeys(root for root in roots if root.is_dir()))
44
+
45
+
46
+ SKILLS_ROOTS = _skill_roots(SKILLS_ROOT)
47
+
48
+
49
+ def has_skill(name: str) -> bool:
50
+ """两个技能根里任一存在该技能目录即为已安装(安装副本只装了单个技能时为 False)。"""
51
+ return any((root / name).is_dir() for root in SKILLS_ROOTS)
52
+
53
+
54
+ def skill_path(rel: str) -> Path:
55
+ """按「技能名/技能内相对路径」在两个技能根里定位文件;都没有时回落到本技能所在的根。"""
56
+ for root in SKILLS_ROOTS:
57
+ candidate = root / rel
58
+ if candidate.exists():
59
+ return candidate
60
+ return SKILLS_ROOT / rel
61
+
62
+
63
+ def skill_root_of(name: str) -> Path:
64
+ """技能 `name` 所属的技能根(安装副本里找不到时回落到本技能所在的根)。"""
65
+ for root in SKILLS_ROOTS:
66
+ if (root / name).is_dir():
67
+ return root
68
+ return SKILLS_ROOT
69
+
70
+
71
+ def _source_repo_root(start: Path) -> Path:
72
+ """源仓根:向上找带 `go.mod` + `Makefile` 的那一层(安装副本里找不到就回落一层)。"""
73
+ for candidate in (start, *start.parents):
74
+ if (candidate / "go.mod").is_file() and (candidate / "Makefile").is_file():
75
+ return candidate
76
+ return start.parent
77
+
78
+
79
+ REPO_ROOT = _source_repo_root(Path(__file__).resolve())
80
+
81
+ # Active contracts that must never re-introduce a local knowledge-base root,
82
+ # a downloaded-body mirror, or a "publish gate" style local fallback.
83
+ # Router/DWS-side documents that are individually pinned.
84
+ PINNED_CONTRACT_FILES = [
85
+ "crwu-dws/SKILL.md",
86
+ "crwu-dws/references/00-目录快照schema.md",
87
+ "crwu-dws/references/01-审核下载与manifest规范.md",
88
+ "crwu-dws/references/02-缓存与兜底查找规范.md",
89
+ "crwu-audit/SKILL.md",
90
+ "crwu-audit/references/10-capability-gap-proposal.md",
91
+ "crwu-audit/references/99-maintenance.md",
92
+ "crwu-audit/references/04-business-classification.md",
93
+ "crwu-audit/references/12-leaf-common-contract.md",
94
+ "crwu-audit-asset-realestate/SKILL.md",
95
+ "crwu-audit-asset-realestate/references/01-kb-assembly.md",
96
+ "crwu-audit-biz-asset-operation/SKILL.md",
97
+ "crwu-audit-biz-asset-operation/references/02-review-focus.md",
98
+ # Public-axis capabilities are not matched by _leaf_files() (which enumerates only
99
+ # crwu-audit-asset-* / crwu-audit-biz-*), so they must be pinned explicitly or the
100
+ # whole public axis would go unchecked.
101
+ "crwu-audit-public-general-standards/SKILL.md",
102
+ "crwu-audit-public-general-standards/references/00-applicability.md",
103
+ "crwu-audit-public-general-standards/references/01-kb-assembly.md",
104
+ "crwu-audit-public-general-standards/references/02-review-focus.md",
105
+ "crwu-audit-datacheck/SKILL.md",
106
+ "crwu-dev-audit-optimize/SKILL.md",
107
+ "crwu-dev-audit-optimize/references/00-优化规范与文件落点.md",
108
+ "crwu-dev-audit-optimize/references/01-反馈定位与画像流程.md",
109
+ "crwu-dev-audit-skill-maintainer/SKILL.md",
110
+ "crwu-dev-audit-skill-maintainer/references/01-kb-source-discovery.md",
111
+ "crwu-dev-audit-skill-maintainer/references/02-child-skill-contract.md",
112
+ ]
113
+ # 源仓文档(不在 skills 内):只有源仓维护环境存在;已安装副本内缺失 → 相关断言 skip。
114
+ # 2026-09 合并仓库后,源仓设计文档归档到 `docs/v0.0.1/`(技能树移到 plugins/ 之下),
115
+ # 原 `skills/README.md` 变成源仓文档 `docs/skills.md`。路径按现状钉住,缺失即 skip。
116
+ PINNED_SOURCE_REPO_FILES = [
117
+ "docs/skills.md",
118
+ "docs/v0.0.1/design-audit-live-kb-protocol.md",
119
+ "docs/v0.0.1/design-crwu-dws.md",
120
+ ]
121
+
122
+
123
+ def _display(path: Path) -> str:
124
+ """给断言消息用的短路径:技能内相对 skills 根,源仓文档相对源仓根。"""
125
+ for root in (*SKILLS_ROOTS, REPO_ROOT):
126
+ try:
127
+ return str(path.relative_to(root))
128
+ except ValueError:
129
+ continue
130
+ return str(path)
131
+
132
+
133
+ def _source_repo_docs() -> list[Path]:
134
+ return [REPO_ROOT / rel for rel in PINNED_SOURCE_REPO_FILES if (REPO_ROOT / rel).is_file()]
135
+
136
+
137
+ def _leaf_dirs() -> list[Path]:
138
+ """两个技能根下的全部资产/业务叶子技能目录(合并仓库后它们在插件技能根里)。"""
139
+ found = []
140
+ for root in SKILLS_ROOTS:
141
+ for pattern in ("crwu-audit-asset-*", "crwu-audit-biz-*"):
142
+ found.extend(leaf for leaf in root.glob(pattern) if leaf.is_dir())
143
+ return sorted(found)
144
+
145
+
146
+ def _leaf_files():
147
+ """Every file of every asset/biz leaf, so the whole family is covered (not a sample)."""
148
+ found = []
149
+ for leaf in _leaf_dirs():
150
+ found.extend(sorted(leaf.rglob("*.md")))
151
+ return found
152
+
153
+
154
+ ACTIVE_CONTRACT_FILES = [skill_path(rel) for rel in PINNED_CONTRACT_FILES] + _leaf_files()
155
+ SOURCE_REPO_CONTRACT_FILES = _source_repo_docs()
156
+
157
+ FORBIDDEN_TERMS = [
158
+ "CRWU_KB_ROOT",
159
+ "M2-B",
160
+ "全量镜像",
161
+ "本地静态副本",
162
+ "本地静态根",
163
+ "维护/离线归档",
164
+ ]
165
+
166
+ # A contract still has to be able to *document* a retirement ("CRWU_KB_ROOT 已废止").
167
+ # Only lines that present the term as a usable source are violations.
168
+ RETIREMENT_NOTE_WORDS = (
169
+ "废止", "弃用", "废弃", "不再", "禁止", "不得", "红线", "三不写",
170
+ "字面", "lint", "协议", "硬编码", "旧树", "retired", "deprecated",
171
+ )
172
+
173
+
174
+ def _is_retirement_note(line):
175
+ return any(word in line for word in RETIREMENT_NOTE_WORDS)
176
+
177
+
178
+
179
+ # 源仓契约测试所需的完整技能族:安装副本里缺任何一个 → 显式 skip(不失败、不静默通过)。
180
+ _REQUIRED_SIBLINGS = (
181
+ "crwu-audit",
182
+ "crwu-audit-asset-realestate",
183
+ "crwu-audit-biz-asset-operation",
184
+ "crwu-audit-public-general-standards",
185
+ "crwu-audit-datacheck",
186
+ "crwu-dev-audit-optimize",
187
+ "crwu-dev-audit-skill-maintainer",
188
+ "crwu-dws",
189
+ )
190
+
191
+
192
+ def _requires_skill_tree(test):
193
+ """源仓契约测试前提:同级技能与源仓文档齐备。
194
+
195
+ 技能以副本安装时这些内容可能不在(例如只装了单个技能)——此时**显式 skip**,
196
+ 既不当成失败,也不静默通过。运行时不需要本测试。
197
+ """
198
+
199
+ def wrapper(self, *args, **kwargs):
200
+ missing = [name for name in _REQUIRED_SIBLINGS if not has_skill(name)]
201
+ if missing:
202
+ self.skipTest(f"非完整技能树(缺少同级技能 {', '.join(missing)}):跳过源仓契约测试")
203
+ return test(self, *args, **kwargs)
204
+
205
+ return wrapper
206
+
207
+
208
+ class DwsSourceContractTest(unittest.TestCase):
209
+ def test_source_repo_docs_are_optional_outside_the_source_repo(self):
210
+ """源仓文档(docs/)在已安装副本内不存在:显式 skip,不静默通过也不误报失败。"""
211
+ if (REPO_ROOT / "docs").is_dir():
212
+ self.assertEqual(
213
+ len(PINNED_SOURCE_REPO_FILES),
214
+ len(SOURCE_REPO_CONTRACT_FILES),
215
+ "源仓环境下设计文档必须齐备",
216
+ )
217
+ else:
218
+ self.skipTest("非源仓环境(无 docs/):跳过源仓文档契约检查")
219
+
220
+ @_requires_skill_tree
221
+ def test_every_active_contract_file_exists(self):
222
+ missing = [str(path) for path in ACTIVE_CONTRACT_FILES if not path.is_file()]
223
+
224
+ self.assertEqual([], missing, f"active contract list points at missing files: {missing}")
225
+
226
+ @_requires_skill_tree
227
+ def test_active_contracts_do_not_offer_local_or_full_mirror_bodies(self):
228
+ violations = []
229
+
230
+ for contract_path in ACTIVE_CONTRACT_FILES + SOURCE_REPO_CONTRACT_FILES:
231
+ relative_path = _display(contract_path)
232
+ text = contract_path.read_text(encoding="utf-8")
233
+ for lineno, line in enumerate(text.splitlines(), start=1):
234
+ for term in FORBIDDEN_TERMS:
235
+ if term not in line:
236
+ continue
237
+ if _is_retirement_note(line):
238
+ continue
239
+ violations.append(f"{relative_path}:{lineno}: {term}")
240
+
241
+ self.assertEqual([], violations, "\n".join(violations))
242
+
243
+ @_requires_skill_tree
244
+ def test_active_contracts_do_not_reference_a_local_kb_root_relative_path(self):
245
+ """`KB/<rel>` addressed the retired local root; kb_tool owns the precise rule.
246
+
247
+ `kb_tool.py validate --skill-root skills` distinguishes real `KB/<rel>` references
248
+ from prose such as 『KB/知识库』 and from prohibition notes. Re-implementing a cruder
249
+ text match here only produced false positives, so this test asserts the tool's
250
+ verdict on the repository instead of scanning the text itself.
251
+ """
252
+ import subprocess
253
+ import sys
254
+
255
+ result = subprocess.run(
256
+ [
257
+ sys.executable,
258
+ str(skill_path("crwu-dev-audit-skill-maintainer/scripts/kb_tool.py")),
259
+ "validate",
260
+ "--skill-root",
261
+ str(skill_root_of("crwu-dev-audit-skill-maintainer")),
262
+ ],
263
+ text=True,
264
+ capture_output=True,
265
+ check=False,
266
+ )
267
+
268
+ self.assertEqual(
269
+ 0,
270
+ result.returncode,
271
+ f"kb_tool validate reported reference violations:\n{result.stdout}{result.stderr}",
272
+ )
273
+
274
+ @_requires_skill_tree
275
+ def test_m2_supports_file_directory_and_mixed_manifest_entries(self):
276
+ text = (SKILLS_ROOT / "crwu-dws/SKILL.md").read_text(encoding="utf-8")
277
+ required_terms = [
278
+ "单文件路径",
279
+ "只下载该文件",
280
+ "目录路径",
281
+ "递归下载",
282
+ "同一清单",
283
+ "清单外零下载",
284
+ ]
285
+
286
+ for term in required_terms:
287
+ with self.subTest(term=term):
288
+ self.assertIn(term, text)
289
+
290
+ # ---- v0.6:按 extension 分流的双取数通道 ----------------------------------
291
+ #
292
+ # 缺陷背景(2026-09-15 实测):知识库文档的 nodeType 恒为 `file`,格式只在
293
+ # `extension` 里;`dw. doc +export` 仅支持 `extension=adoc`。整改前 M2 对所有
294
+ # 文档一律调用 `doc +export`,于是 25 个原生 `.md` 正文(整个 `03-评估方法/`)
295
+ # 每次都必然失败、被记成 failure,且没有任何门禁发现——因为校验只看"路径键
296
+ # 是否存在",不看节点类型。以下断言把整改口径钉死。
297
+
298
+ def _dws_docs(self) -> dict:
299
+ names = [
300
+ "SKILL.md",
301
+ "references/00-目录快照schema.md",
302
+ "references/01-审核下载与manifest规范.md",
303
+ "references/02-缓存与兜底查找规范.md",
304
+ ]
305
+ return {
306
+ name: (SKILLS_ROOT / "crwu-dws" / name).read_text(encoding="utf-8")
307
+ for name in names
308
+ }
309
+
310
+ @_requires_skill_tree
311
+ def test_whitelist_adds_read_only_drive_download(self):
312
+ """候选通道必须显式列入只读白名单,且仍禁止一切写命令。"""
313
+ text = self._dws_docs()["SKILL.md"]
314
+
315
+ self.assertIn("`+download`", text, "drive +download 未进入只读白名单")
316
+ self.assertIn("drive 域仅", text, "白名单未声明 drive 域边界")
317
+ # 白名单必须保持"仅"的排他语义:drive 域只放行 +download 一个命令。
318
+ drive_clause = next(
319
+ line for line in text.splitlines() if "drive 域仅" in line
320
+ )
321
+ self.assertIn("+download", drive_clause)
322
+ self.assertNotIn("+upload", drive_clause)
323
+ self.assertNotIn("+move", drive_clause)
324
+ self.assertNotIn("+delete", drive_clause)
325
+
326
+ @_requires_skill_tree
327
+ def test_channel_is_decided_by_extension_not_by_trial(self):
328
+ """通道由 extension 判定;明令禁止"先 export 试失败再换通道"的试错取数。"""
329
+ docs = self._dws_docs()
330
+ skill = docs["SKILL.md"]
331
+
332
+ # SKILL.md 必须给出分流表的三档判据。
333
+ for term in ("`adoc`", "`md`", "`txt`", "`skipped`"):
334
+ with self.subTest(term=term):
335
+ self.assertIn(term, skill)
336
+
337
+ # 试错取数必须被显式禁止(否则"必然失败"会被记成偶发 failure)。
338
+ self.assertIn("试错", skill, "SKILL.md 未禁止试错式取数")
339
+ self.assertRegex(
340
+ skill,
341
+ r"禁止[^\n]*试(错|一次)",
342
+ "SKILL.md 未写明禁止试错式通道选择",
343
+ )
344
+
345
+ # references/01 必须给出同一张分流表与展开范围口径。
346
+ m2 = docs["references/01-审核下载与manifest规范.md"]
347
+ self.assertIn("dws drive +download", m2)
348
+ self.assertIn("dws doc +export", m2)
349
+ self.assertIn("channel", m2)
350
+
351
+ @_requires_skill_tree
352
+ def test_unsupported_extension_is_skipped_not_failed(self):
353
+ """类型不支持是正常结论:必须记 skipped,禁止并入 failure。"""
354
+ docs = self._dws_docs()
355
+ skill = docs["SKILL.md"]
356
+ m2 = docs["references/01-审核下载与manifest规范.md"]
357
+
358
+ self.assertIn("skipped", skill)
359
+ self.assertRegex(
360
+ skill,
361
+ r"skipped[^\n]*不(得|是)[^\n]*failure|不(得|是)[^\n]*failure[^\n]*skipped",
362
+ "SKILL.md 未写明 skipped 不得计入 failure",
363
+ )
364
+ # 摘要口径必须把跳过与失败分开统计。
365
+ self.assertIn("跳过", skill)
366
+ self.assertIn("skipped", m2)
367
+ self.assertRegex(
368
+ m2,
369
+ r"(不得|禁止)[^\n]*failure",
370
+ "references/01 未写明 skipped 不得记为 failure",
371
+ )
372
+ # 明细表三态齐全:entry / skipped / failure。
373
+ for kind in ('"kind": "entry"', '"kind": "skipped"', '"kind": "failure"'):
374
+ with self.subTest(kind=kind):
375
+ self.assertIn(kind, m2)
376
+
377
+ @_requires_skill_tree
378
+ def test_snapshot_and_node_index_carry_the_channel_discriminator(self):
379
+ """extension/contentType 必须落快照与索引,否则 M2 快路径无法判通道。"""
380
+ docs = self._dws_docs()
381
+ snapshot = docs["references/00-目录快照schema.md"]
382
+ index = docs["references/02-缓存与兜底查找规范.md"]
383
+
384
+ for label, text in (("references/00", snapshot), ("references/02", index)):
385
+ with self.subTest(doc=label):
386
+ self.assertIn("extension", text, f"{label} 未记录 extension")
387
+ self.assertIn("contentType", text, f"{label} 未记录 contentType")
388
+
389
+ # 必须写明"缺失时补查 node-get、不按名称后缀猜"。
390
+ self.assertIn("node-get", index, "references/02 未给出 extension 缺失时的补查口径")
391
+ self.assertRegex(
392
+ snapshot + index,
393
+ r"不(推断|猜|按名称)",
394
+ "未写明 extension 缺失时不得推断/猜测",
395
+ )
396
+
397
+ @_requires_skill_tree
398
+ def test_type_field_is_not_used_as_a_format_discriminator(self):
399
+ """nodeType 恒为 file,不得再当格式判据(整改前的错误假设)。"""
400
+ snapshot = self._dws_docs()["references/00-目录快照schema.md"]
401
+
402
+ self.assertRegex(
403
+ snapshot,
404
+ r"type[^\n]*(不承载格式|只表示节点形态)",
405
+ "references/00 未写明 type 不承载格式信息",
406
+ )
407
+ # 渲染规则也必须按 extension 标注,而不是按 type。
408
+ self.assertIn("ext:", snapshot, "目录树渲染未按 extension 标注")
409
+
410
+ @_requires_skill_tree
411
+ def test_asset_and_business_leaves_declare_a_first_level_directory_root(self):
412
+ """Every asset/biz leaf must declare one exact recursive first-level root.
413
+
414
+ Parses the assembly table row (cell-level) rather than substring matching, and the
415
+ leaf must carry all four required references (not just the assembly table).
416
+ """
417
+ leaves = _leaf_dirs()
418
+ self.assertNotEqual([], leaves, "expected at least one asset/biz leaf skill")
419
+
420
+ required_references = (
421
+ "00-applicability.md",
422
+ "01-kb-assembly.md",
423
+ "02-review-focus.md",
424
+ )
425
+ problems = []
426
+ for leaf in leaves:
427
+ name = leaf.name
428
+ axis_root = "02-资产类型/" if name.startswith("crwu-audit-asset-") else "01-业务路线/"
429
+ for reference in required_references:
430
+ if not (leaf / "references" / reference).is_file():
431
+ problems.append(f"{name}: missing references/{reference}")
432
+ assembly = leaf / "references" / "01-kb-assembly.md"
433
+ if not assembly.is_file():
434
+ continue
435
+
436
+ rows = [
437
+ [cell.strip().strip("`") for cell in line.strip().strip("|").split("|")]
438
+ for line in assembly.read_text(encoding="utf-8").splitlines()
439
+ if line.strip().startswith("|")
440
+ ]
441
+ header = next((r for r in rows if "kb_root" in r and "request_kind" in r), None)
442
+ if header is None:
443
+ problems.append(f"{name}: assembly has no first-level root table")
444
+ continue
445
+ index = {key: i for i, key in enumerate(header)}
446
+ data = [
447
+ r for r in rows
448
+ if len(r) == len(header) and r[index["request_kind"]] in {"directory"}
449
+ ]
450
+ if len(data) != 1:
451
+ problems.append(
452
+ f"{name}: expected exactly one directory root row, found {len(data)}"
453
+ )
454
+ continue
455
+ row = data[0]
456
+ kb_root = row[index["kb_root"]]
457
+ label = row[index["canonical_label"]]
458
+ if not kb_root.startswith(axis_root) or not kb_root.endswith("/"):
459
+ problems.append(f"{name}: kb_root {kb_root!r} is not one {axis_root}<label>/ root")
460
+ if kb_root.count("/") != 2:
461
+ problems.append(f"{name}: kb_root {kb_root!r} is not a first-level root")
462
+ if row[index["recursive"]] != "true":
463
+ problems.append(f"{name}: recursive must be true")
464
+ if row[index["required"]] != "true":
465
+ problems.append(f"{name}: required must be true")
466
+ if label not in kb_root:
467
+ problems.append(f"{name}: canonical_label {label!r} not present in kb_root")
468
+ if ".md" in kb_root:
469
+ problems.append(f"{name}: kb_root must not carry the .md export suffix")
470
+
471
+ self.assertEqual([], problems, "\n".join(problems))
472
+
473
+ @_requires_skill_tree
474
+ def test_legacy_combined_and_business_prefixed_skills_are_gone(self):
475
+ offenders = sorted(
476
+ path.name
477
+ for root in SKILLS_ROOTS
478
+ for path in root.glob("crwu-audit-business-*")
479
+ if path.is_dir()
480
+ )
481
+ self.assertEqual(
482
+ [],
483
+ offenders,
484
+ f"legacy business-prefixed skill directories remain: {offenders}",
485
+ )
486
+ self.assertFalse(
487
+ (SKILLS_ROOT / "crwu-audit-realestate-rent").exists(),
488
+ "legacy combined skill crwu-audit-realestate-rent must stay deleted",
489
+ )
490
+
491
+
492
+ if __name__ == "__main__":
493
+ unittest.main()