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,577 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """crwu 审核技能校验工具(kb_tool)v0.2 —— 只读引用与实时协议校验
4
+
5
+ 知识正文的唯一来源是钉钉知识库,由 `crwu-dws` 按本次审核清单**实时下载**。
6
+ 本仓不再维护本地知识库根(`CRWU_KB_ROOT` / `~/.crwu/knowledge/knowledge-base`):
7
+ 技能侧只写 RULE/CHK 编号与库内层级路径寻址键,正文一律运行时获取。
8
+
9
+ 因此本工具只保留两类**不依赖本地知识库**的检查:
10
+
11
+ 1. 技能引用卫生(`--skill-root`)
12
+ - 旧树残留标记(`01-规则库`、`02-审核清单库`、`06-素材库` 等漂移名);
13
+ - `KB/…` 省略号(不可解析引用);
14
+ - 已废止的本地根相对引用 `KB/<rel>`;
15
+ - 已废止的本地知识库根常量与本地根路径字面(`~/.crwu/...`,目录缓存除外)。
16
+ 2. 实时引用协议 lint(`--skill-root`,作用于 `crwu-audit*` 与 `crwu-dev-audit-*` 族目录)
17
+ - 禁止本地知识库根字面、禁止硬编码 nodeId 赋值;
18
+ - `--forbid-literal` 追加禁止知识库名称等字面。
19
+ 纪律文本(含"禁止/不写…字面"的说明行)自动豁免。
20
+
21
+ 装配清单不再由本工具生成:下载清单 = 命中资产/业务子技能的 `01-kb-assembly.md`
22
+ (一级目录根或单文件路径)+ 执行契约路径并集,由 `crwu-dws` M2 实时下载。
23
+
24
+ 叶子公共契约(2026-09-25 架构裁定):公共规则一个规范源
25
+ (`crwu-audit/references/12-leaf-common-contract.md`),由 `sync-leaf-common-contract --write`
26
+ 确定性同步为各资产/业务叶子的本地副本 `references/03-common-contract.md`;运行时只读本 Skill 内副本。
27
+ `validate` 自动执行同等检查(缺失/漂移/目标集合变化 → error;非完整源仓技能层 → skip 且不阻断)。
28
+
29
+ 子命令:validate | sync-leaf-common-contract
30
+ 用法示例见同目录 README.md。
31
+ """
32
+ from __future__ import annotations
33
+
34
+ import argparse
35
+ import os
36
+ import re
37
+ import sys
38
+ from urllib.parse import unquote
39
+
40
+ TOOL_VERSION = "0.2.0"
41
+
42
+ # 残留旧树标记(技能/治理文档中的漂移源;validate --skill-root 时告警)
43
+ LEGACY_MARKERS = [
44
+ "01-规则库", "02-审核清单库", "执业准则-对象类", "执业准则-评估方法",
45
+ "不动产准则2017-精编条目", "06-素材库", "KB 06/07", "KB 08", "现路径", "迁后",
46
+ ]
47
+
48
+ _LEGACY_RE = re.compile("|".join(re.escape(m) for m in LEGACY_MARKERS))
49
+
50
+ # KB/… 省略号(不可解析引用)
51
+ _ELLIPSIS_KB_RE = re.compile(r"KB/…")
52
+ # 本地知识库根路径字面(目录缓存 dws-dir-cache 例外)
53
+ _KB_LITERAL_RE = re.compile(r"`?~/.crwu/knowledge[^`\s()(),。;]*")
54
+ # 已废止的"本地根相对"引用:KB/<rel>
55
+ _KB_REL_RE = re.compile(r"`?KB/[^`\s()(),。;]*")
56
+ # 已废止的本地知识库根常量
57
+ _RETIRED_ROOT_RE = re.compile(r"CRWU_KB_ROOT")
58
+
59
+
60
+ # ---------------- 引用卫生 ----------------
61
+
62
+ def _is_meta_ellipsis_line(line: str) -> bool:
63
+ """说明性文字里的 'KB/…'(如 '下文 KB/… 均相对该根')不是引用,跳过告警。"""
64
+ return "KB/…" in line and any(
65
+ w in line for w in ("均相对", "均为该根", "一律相对", "相对该根", "禁止省略", "省略号", "省略", "禁止", "废弃", "弃用"))
66
+
67
+
68
+ def _is_forbidden_marker_line(line: str) -> bool:
69
+ """红线/规范里"禁止出现旧名"的列举行:故意含旧树字面量,不作残留告警。"""
70
+ return bool(_LEGACY_RE.search(line)) and any(
71
+ w in line for w in ("禁止出现", "一律禁止", "不允许出现", "不作残留"))
72
+
73
+
74
+ # 纪律/说明行自身会提到被废止的字面("已废止的 KB/<rel>"、"不再使用 CRWU_KB_ROOT"…)
75
+ _RETIREMENT_NOTE_WORDS = (
76
+ "废止", "弃用", "废弃", "不再", "禁止", "不得", "红线", "三不写",
77
+ "字面", "lint", "协议", "硬编码", "旧树", "retired", "deprecated",
78
+ )
79
+
80
+
81
+ def _is_retirement_note(line: str) -> bool:
82
+ """说明性的"某写法已废止/禁止"行本身含被禁字面,跳过误报。"""
83
+ return any(word in line for word in _RETIREMENT_NOTE_WORDS)
84
+
85
+
86
+ def skill_path_problems(skill_root: str):
87
+ """扫描技能/文档内的引用卫生问题:旧树标记、省略号、废止的本地根引用与字面。"""
88
+ errors, warns = [], []
89
+ for dirpath, _dirnames, filenames in os.walk(skill_root):
90
+ for fn in sorted(filenames):
91
+ if not fn.endswith(".md"):
92
+ continue
93
+ p = os.path.join(dirpath, fn)
94
+ rel = os.path.relpath(p, skill_root)
95
+ with open(p, encoding="utf-8") as fh:
96
+ for lineno, line in enumerate(fh, start=1):
97
+ line = line.rstrip("\n")
98
+ if _is_prohibition_note(line):
99
+ continue
100
+ if _ELLIPSIS_KB_RE.search(line) and not _is_meta_ellipsis_line(line):
101
+ warns.append(f"{rel}:{lineno} KB/… 省略号引用(不可解析)")
102
+ if _LEGACY_RE.search(line) and not _is_forbidden_marker_line(line):
103
+ warns.append(f"{rel}:{lineno} 旧树残留标记")
104
+ if _RETIRED_ROOT_RE.search(line) and not _is_retirement_note(line):
105
+ errors.append(
106
+ f"{rel}:{lineno} 已废止的本地知识库根常量(正文唯一来源为钉钉,经 crwu-dws 实时下载)")
107
+ for lit in _KB_LITERAL_RE.findall(line):
108
+ t = lit.lstrip("`")
109
+ if not t.startswith("~"):
110
+ continue
111
+ if "dws-dir-cache" in t:
112
+ # crwu-dws 目录缓存层:运行时 M1/M3 才生成,未生成不算引用缺失
113
+ continue
114
+ if not os.path.exists(os.path.abspath(os.path.expanduser(t))):
115
+ errors.append(f"{rel}:{lineno} 路径不存在 {t}")
116
+ for relref in _KB_REL_RE.findall(line):
117
+ t = relref.lstrip("`")
118
+ if not t.startswith("KB/"):
119
+ continue
120
+ seg = t[3:].split(" ")[0]
121
+ if not seg or seg.startswith("…"):
122
+ continue
123
+ if "省略" in seg or "『" in line or "』" in seg:
124
+ # 实时协议元说明("禁止「KB/…」式前缀省略"、"『KB/知识库』=…"释义等),非引用
125
+ continue
126
+ if _is_retirement_note(line):
127
+ continue
128
+ errors.append(
129
+ f"{rel}:{lineno} 已废止的本地根相对引用 {t}"
130
+ "(改用库内层级路径,由 crwu-dws 按清单实时下载)")
131
+ return errors, warns
132
+
133
+
134
+ # ---------------- 实时引用协议 lint(2026-09-08,crwu-dws × crwu-audit 实时引用改造) ----------------
135
+
136
+ # 只对审核族目录做"三不写"严格 lint(crwu-dws 等允许按需引用部署常量/默认库名)。
137
+ # 两组前缀都要覆盖:`crwu-audit*`(审核族)与 `crwu-dev-audit-*`(开发/维护侧成员,
138
+ # 如 crwu-dev-audit-optimize、crwu-dev-audit-skill-maintainer)——只认前者会让
139
+ # 改到 dev 前缀的技能**静默掉出 lint 范围**(2026-09-16 引入,2026-09-19 归组调整后仍适用)。
140
+ AUDIT_DIR_PREFIXES = ("crwu-audit", "crwu-dev-audit")
141
+ # ① 本地知识库根常量赋值 / 根路径字面 / 内容副本目录字面(推理引用实时化后一律禁止写死在技能内)
142
+ _LIVE_NO_ROOT_RES = [
143
+ re.compile(r"CRWU_KB_ROOT\s*="),
144
+ re.compile(r"~/?\.crwu/"),
145
+ re.compile(r"knowledge-base"),
146
+ ]
147
+ # ② 硬编码 nodeId(nodeId 一律由 crwu-dws 运行时解析;技能内只允许描述性提及,不允许赋值)
148
+ _LIVE_NODEID_ASSIGN_RE = re.compile(r"nodeId\s*[:=]\s*\S")
149
+
150
+
151
+ def _is_prohibition_note(line: str) -> bool:
152
+ """纪律文本("禁止…字面/三不写"等)自身可含被禁字面,跳过误报。"""
153
+ return ("禁止" in line or "不写" in line) and any(
154
+ w in line for w in ("字面", "三不写", "lint", "红线", "协议", "硬编码"))
155
+
156
+
157
+ def live_protocol_lint(skill_root: str, forbid_literals):
158
+ """实时引用协议 lint:crwu-audit 族技能内不得出现 ①本地 KB 根路径/根常量字面
159
+ (CRWU_KB_ROOT=、~/.crwu/、knowledge-base)②nodeId 硬编码赋值 ③--forbid-literal 指定的
160
+ 知识库名称字面。返回 (errors, warns)。"""
161
+ errors, warns = [], []
162
+ targets = []
163
+ if os.path.isdir(skill_root):
164
+ for d in sorted(os.listdir(skill_root)):
165
+ if d.startswith(AUDIT_DIR_PREFIXES):
166
+ targets.append(os.path.join(skill_root, d))
167
+ if not targets and os.path.basename(skill_root).startswith(AUDIT_DIR_PREFIXES):
168
+ targets.append(skill_root)
169
+ elif os.path.basename(skill_root).startswith(AUDIT_DIR_PREFIXES):
170
+ targets.append(skill_root)
171
+ for root in targets:
172
+ for dirpath, _dirnames, filenames in os.walk(root):
173
+ for fn in sorted(filenames):
174
+ if not fn.endswith(".md"):
175
+ continue
176
+ p = os.path.join(dirpath, fn)
177
+ rel = os.path.relpath(p, skill_root)
178
+ with open(p, encoding="utf-8") as fh:
179
+ for lineno, line in enumerate(fh, start=1):
180
+ line = line.rstrip("\n")
181
+ if _is_prohibition_note(line):
182
+ continue
183
+ for rx in _LIVE_NO_ROOT_RES:
184
+ if rx.search(line):
185
+ errors.append(
186
+ f"{rel}:{lineno} 实时协议禁止本地 KB 根字面:{rx.pattern}")
187
+ break
188
+ if _LIVE_NODEID_ASSIGN_RE.search(line):
189
+ errors.append(f"{rel}:{lineno} 禁止硬编码 nodeId(由 crwu-dws 运行时解析)")
190
+ for lit in forbid_literals or []:
191
+ if lit and lit in line:
192
+ errors.append(f"{rel}:{lineno} 禁止知识库名称字面:{lit}")
193
+ return errors, warns
194
+
195
+
196
+ # ---------------- 技能自洽性 lint(2026-09-10:技能不得引用代码仓库目录) ----------------
197
+
198
+ # 技能以副本安装(各技能同级放于 agent skills 根下)时必须能独立工作:
199
+ # 运行时内容里出现仓库目录/仓根文件引用 → 安装后一律不存在。
200
+ # 注意:路径名在此按"目录名 + 分隔符"拼装,避免本段定义被自身规则匹配。
201
+ _REPO_DIR_NAMES = ["docs", "tools", "cmd", "internal", "bin"]
202
+ _REPO_ROOT_FILES = ["Makefile", "go.mod"] # lint-self: 规则定义本身,非技能内容
203
+ # 允许 `./`、`../` 前缀(相对写法同样要拦);先剔除系统路径与 URL 再匹配,避免误报。
204
+ _REPO_PREFIX = r"(?<![\w/-])(?:\.{1,2}/)*" # lint-self: 规则定义本身
205
+ # shebang 等系统路径、文档链接里的 URL 不是仓库目录
206
+ _SAFE_BEFORE_MATCH = (
207
+ (re.compile(r"https?://\S+"), " "),
208
+ (re.compile(r"/usr/(?:local/)?bin/"), " "), # lint-self: 规则定义本身
209
+ )
210
+ _REPO_REF_PATTERNS = [(name, re.compile(_REPO_PREFIX + re.escape(name) + r"/"))
211
+ for name in _REPO_DIR_NAMES] + \
212
+ [(name, re.compile(_REPO_PREFIX + re.escape(name) + r"(?![\w.-])"))
213
+ for name in _REPO_ROOT_FILES] + \
214
+ [("skills/<层>/", re.compile(_REPO_PREFIX + r"skills/(?:crwu|dws)/")),
215
+ ("skills/<skill>/", re.compile(_REPO_PREFIX + r"skills/crwu-[a-z0-9]+[a-z0-9-]*/"))]
216
+ # 逃出技能目录的本地 Markdown 链接:按**规范化后的相对路径**判定(见 `escaping_links`)。
217
+ # 不能按「`../` 出现次数」判定:`references/sub/deep.md → ../../SKILL.md` 有 2 个 `../` 却仍在技能内,
218
+ # 而 `SKILL.md → ../sibling/x.md` 只有 1 个 `../` 却已逃逸。两条都是真实反例。
219
+ # 本地链接:`[text](target)` / `![alt](target)`;target 可被 `<>` 包裹,可带 fragment/query。 # lint-self: 规则定义本身
220
+ _MD_LINK_RE = re.compile(r"!?\[[^\]]*\]\(\s*(<[^>\n]*>|[^)\s]+)") # lint-self: 规则定义本身
221
+ # 外部 URI / 协议相对 URL / 纯锚点:不是本地相对路径。 # lint-self: 规则定义本身
222
+ _EXTERNAL_URI_RE = re.compile(r"^(?:[a-zA-Z][a-zA-Z0-9+.-]*:|//|#)") # lint-self: 规则定义本身
223
+ # 源仓契约测试:只在源仓维护时运行,允许定位源仓;文件头 30 行内声明即可豁免。
224
+ _SOURCE_REPO_TEST_MARKERS = ("源仓契约测试", "源仓维护工具")
225
+
226
+
227
+ def _local_link_target(raw: str):
228
+ """从 Markdown 链接目标里取出本地相对路径;外部 URI / 锚点 / 绝对路径返回 None。"""
229
+ target = raw.strip()
230
+ if target.startswith("<") and target.endswith(">"):
231
+ target = target[1:-1].strip()
232
+ if not target or _EXTERNAL_URI_RE.match(target):
233
+ return None
234
+ if target.startswith(("/", "\\")):
235
+ return None # 绝对路径由仓库引用 lint 负责,不计入"逃出技能目录"
236
+ for separator in ("#", "?"):
237
+ cut = target.find(separator)
238
+ if cut != -1:
239
+ target = target[:cut]
240
+ target = unquote(target.strip())
241
+ return target or None
242
+
243
+
244
+ def escaping_links(document: str, skill_dir: str):
245
+ """返回 `document` 中所有**逃出 `skill_dir`** 的本地 Markdown 链接。
246
+
247
+ 判定算法(只依赖路径边界,**不依赖目标文件当前是否存在**):
248
+ 1. 逐行解析 Markdown 本地链接目标(含 `<>` 包裹与 fragment/query);
249
+ 2. 跳过外部 URI(`http:`/`https:`/`mailto:`/其它 scheme、`//`)与纯 `#anchor`、绝对路径;
250
+ 3. 去 fragment/query、URL 解码后,相对**当前文件所在目录**解析并 `normpath`;
251
+ 4. 规范化结果必须仍位于 `skill_dir` 之内,否则即逃逸。
252
+
253
+ 这样 `references/01.md → ../SKILL.md`(在内)与 `SKILL.md → ../sibling/x.md`(逃逸)
254
+ 都能得到正确结论。
255
+ """
256
+ escapes = []
257
+ skill_root = os.path.abspath(skill_dir)
258
+ document = os.path.abspath(document)
259
+ base = os.path.dirname(document)
260
+ try:
261
+ with open(document, encoding="utf-8") as fh:
262
+ lines = fh.read().splitlines()
263
+ except OSError:
264
+ return escapes
265
+ for lineno, line in enumerate(lines, start=1):
266
+ if "# lint-self:" in line:
267
+ continue
268
+ for match in _MD_LINK_RE.finditer(line):
269
+ target = _local_link_target(match.group(1))
270
+ if target is None:
271
+ continue
272
+ resolved = os.path.normpath(os.path.join(base, target))
273
+ if resolved == skill_root or resolved.startswith(skill_root + os.sep):
274
+ continue
275
+ escapes.append({
276
+ "line": lineno,
277
+ "target": match.group(1),
278
+ "resolved": resolved,
279
+ "skill_root": skill_root,
280
+ })
281
+ return escapes
282
+
283
+
284
+ def _is_source_repo_test(lines) -> bool:
285
+ return any(marker in line for line in lines[:30] for marker in _SOURCE_REPO_TEST_MARKERS)
286
+
287
+
288
+ def repo_reference_lint(skill_root: str):
289
+ """技能自洽性 lint:技能目录内的 .md 与 .py 不得引用代码仓库目录/仓根文件。
290
+
291
+ 豁免:文件头 30 行内声明「源仓契约测试」或「源仓维护工具」的 .py(只在源仓维护时运行,
292
+ 运行时不需要);含「禁止/不写…字面」等纪律词或"已废止"说明的行;以及带 `# lint-self:`
293
+ 标记的行(规则定义本身)。
294
+ 返回 (errors, warns)。
295
+ """
296
+ errors, warns = [], []
297
+ root = os.path.abspath(skill_root)
298
+ if not os.path.isdir(root):
299
+ return errors, warns
300
+ # 只审"技能":skills 根本身与其下的源仓级文档(AGENTS.md / README.md)不是技能。
301
+ if os.path.isfile(os.path.join(root, "SKILL.md")):
302
+ skill_dirs = [root]
303
+ else:
304
+ skill_dirs = [
305
+ os.path.join(root, name)
306
+ for name in sorted(os.listdir(root))
307
+ if os.path.isfile(os.path.join(root, name, "SKILL.md"))
308
+ ]
309
+ for skill_dir in skill_dirs:
310
+ for dirpath, _dirnames, filenames in os.walk(skill_dir):
311
+ for fn in sorted(filenames):
312
+ if not (fn.endswith(".md") or fn.endswith(".py")):
313
+ continue
314
+ p = os.path.join(dirpath, fn)
315
+ rel = os.path.relpath(p, root)
316
+ with open(p, encoding="utf-8") as fh:
317
+ lines = fh.read().splitlines()
318
+ if fn.endswith(".py") and _is_source_repo_test(lines):
319
+ continue
320
+ # 逃逸判定按规范化路径逐文件算一次(行级正则做不到:是否逃逸取决于文件位置 + 目标)。
321
+ escape_by_line = {}
322
+ if fn.endswith(".md"):
323
+ for escape in escaping_links(p, skill_dir):
324
+ escape_by_line.setdefault(escape["line"], escape)
325
+ for lineno, line in enumerate(lines, start=1):
326
+ if "# lint-self:" in line:
327
+ continue
328
+ if _is_prohibition_note(line) or _is_retirement_note(line):
329
+ continue
330
+ scrubbed = line
331
+ for safe_rx, replacement in _SAFE_BEFORE_MATCH:
332
+ scrubbed = safe_rx.sub(replacement, scrubbed)
333
+ escape = escape_by_line.get(lineno)
334
+ if escape is not None:
335
+ errors.append(
336
+ f"{rel}:{lineno} 技能内不得出现逃出技能目录的链接:{escape['target']}"
337
+ "(技能以副本安装时该目标不存在;改为本 Skill 内 references/ 的相对路径)")
338
+ continue
339
+ for label, rx in _REPO_REF_PATTERNS:
340
+ if rx.search(scrubbed):
341
+ errors.append(
342
+ f"{rel}:{lineno} 技能不得引用代码仓库目录/文件:{label}"
343
+ "(技能以副本安装时不存在;改用技能内 references、同技能 scripts/,"
344
+ "或 $SKILLS_ROOT/<技能>/scripts/… 形式的跨技能引用)")
345
+ return errors, warns
346
+
347
+
348
+ # ---------------- 叶子公共契约:规范源 → 各叶子本地副本(源仓维护) ----------------
349
+ #
350
+ # 口径(2026-09-25 架构裁定「方案 A 的受控版本」):公共规则维护**一个规范源**,
351
+ # 通过确定性工具同步为各叶子的**本地副本**;运行时只读取本 Skill 内副本,源码门禁阻止漂移。
352
+ # 规范源与各副本逐字节相同 —— 它们是同一内容的多个副本,**不是多个独立事实源**。
353
+ #
354
+ # 规范源、目标相对路径与目标选择规则**只在这里定义一次**,避免多处各写一份。
355
+
356
+ LEAF_COMMON_CONTRACT = {
357
+ "source_skill": "crwu-audit",
358
+ "source": "crwu-audit/references/12-leaf-common-contract.md",
359
+ "target": "references/03-common-contract.md",
360
+ "leaf_prefixes": ("crwu-audit-asset-", "crwu-audit-biz-"),
361
+ "skip_note": "未发现 router 技能或资产/业务叶子集合;按「只安装了技能族子集」处理,跳过源码维护检查",
362
+ }
363
+
364
+
365
+ def discover_leaf_skills(skill_root: str):
366
+ """按目录发现资产/业务叶子:前缀匹配 **且** 实际存在 `SKILL.md`。
367
+
368
+ 数量不是事实源 —— 目录即名单,新增/改名的叶子会被自动收进同步集合。
369
+ """
370
+ root = os.path.abspath(skill_root)
371
+ if not os.path.isdir(root):
372
+ return []
373
+ prefixes = LEAF_COMMON_CONTRACT["leaf_prefixes"]
374
+ return sorted(
375
+ name for name in os.listdir(root)
376
+ if name.startswith(prefixes) and os.path.isfile(os.path.join(root, name, "SKILL.md"))
377
+ )
378
+
379
+
380
+ def leaf_common_contract_report(skill_root: str):
381
+ """叶子公共契约的缺失 / 漂移 / 目标集合变化报告(**只读**)。
382
+
383
+ 返回 dict:
384
+ - `status`:`ok`(已检查)或 `skip`(非完整源仓技能层,不报错);
385
+ - `skip_reason` / `source` / `target` / `leaves`;
386
+ - `missing`:缺本地副本的叶子(规范源本身缺失时为 `["__source__"]`);
387
+ - `drifted`:副本与规范源不一致的叶子;
388
+ - `unexpected`:目标集合**以外**却持有该副本的目录(改名/删除留下的残留,不得静默漏同步)。
389
+ """
390
+ root = os.path.abspath(skill_root)
391
+ cfg = LEAF_COMMON_CONTRACT
392
+ report = {
393
+ "status": "ok",
394
+ "skip_reason": "",
395
+ "skill_root": root,
396
+ "source": os.path.join(root, cfg["source"]),
397
+ "target": cfg["target"],
398
+ "leaves": 0,
399
+ "missing": [],
400
+ "drifted": [],
401
+ "unexpected": [],
402
+ }
403
+ router_entry = os.path.join(root, cfg["source_skill"], "SKILL.md")
404
+ leaves = discover_leaf_skills(root)
405
+ if not os.path.isfile(router_entry) or not leaves:
406
+ report["status"] = "skip"
407
+ report["skip_reason"] = cfg["skip_note"]
408
+ return report
409
+ report["leaves"] = len(leaves)
410
+ if not os.path.isfile(report["source"]):
411
+ report["missing"].append("__source__")
412
+ return report
413
+ with open(report["source"], "rb") as fh:
414
+ source_bytes = fh.read()
415
+ for leaf in leaves:
416
+ target = os.path.join(root, leaf, cfg["target"])
417
+ if not os.path.isfile(target):
418
+ report["missing"].append(leaf)
419
+ continue
420
+ with open(target, "rb") as fh:
421
+ if fh.read() != source_bytes:
422
+ report["drifted"].append(leaf)
423
+ leaf_set = set(leaves)
424
+ for name in sorted(os.listdir(root)):
425
+ skill_dir = os.path.join(root, name)
426
+ if not os.path.isfile(os.path.join(skill_dir, "SKILL.md")):
427
+ # 带叶子前缀但已不是技能目录(缺 SKILL.md),却残留副本 → 目标集合变化
428
+ if name.startswith(cfg["leaf_prefixes"]) and os.path.isfile(os.path.join(skill_dir, cfg["target"])):
429
+ report["unexpected"].append(f"{name}(缺 SKILL.md,副本应删除或恢复技能目录)")
430
+ continue
431
+ if name in leaf_set:
432
+ continue
433
+ # 非资产/业务叶子(router / 横切能力 / 元技能)不得持有叶子公共契约副本
434
+ if os.path.isfile(os.path.join(skill_dir, cfg["target"])):
435
+ report["unexpected"].append(f"{name}(非资产/业务叶子,不应持有叶子契约副本)")
436
+ return report
437
+
438
+
439
+ def sync_leaf_common_contract(skill_root: str, write: bool = False):
440
+ """确定性同步叶子公共契约副本。
441
+
442
+ - `write=True`:只为**缺失或漂移**的叶子写入规范源的逐字节副本(已一致的文件不触碰 → 幂等);
443
+ - `write=False`:等价 `--check`,只报告。
444
+
445
+ 返回 `leaf_common_contract_report` 的结果,另带 `written[]`(本次实际写入的叶子)。
446
+ """
447
+ before = leaf_common_contract_report(skill_root)
448
+ written = []
449
+ if write and before["status"] == "ok" and before["missing"] != ["__source__"]:
450
+ with open(before["source"], "rb") as fh:
451
+ source_bytes = fh.read()
452
+ for leaf in before["missing"] + before["drifted"]:
453
+ target = os.path.join(before["skill_root"], leaf, LEAF_COMMON_CONTRACT["target"])
454
+ os.makedirs(os.path.dirname(target), exist_ok=True)
455
+ with open(target, "wb") as fh:
456
+ fh.write(source_bytes)
457
+ written.append(leaf)
458
+ report = leaf_common_contract_report(skill_root) if write else before
459
+ report["written"] = sorted(written)
460
+ return report
461
+
462
+
463
+ def leaf_common_contract_lint(skill_root: str):
464
+ """把叶子公共契约检查接入 `validate`(返回 (errors, warns))。
465
+
466
+ 缺失 / 漂移 / 目标集合变化 → error;非完整源仓技能层 → warn(skip,不阻断安装子集)。
467
+ """
468
+ errors, warns = [], []
469
+ report = leaf_common_contract_report(skill_root)
470
+ if report["status"] == "skip":
471
+ warns.append(f"叶子公共契约同步检查:skip({report['skip_reason']})")
472
+ return errors, warns
473
+ if report["missing"] == ["__source__"]:
474
+ errors.append(
475
+ f"叶子公共契约规范源缺失:{report['source']}"
476
+ "(先恢复规范源,再跑 kb_tool.py sync-leaf-common-contract --write)")
477
+ return errors, warns
478
+ for leaf in report["missing"]:
479
+ errors.append(
480
+ f"{leaf}: 缺少本地公共契约副本 {report['target']}"
481
+ "(运行 kb_tool.py sync-leaf-common-contract --write 生成)")
482
+ for leaf in report["drifted"]:
483
+ errors.append(
484
+ f"{leaf}: 本地公共契约副本与规范源漂移"
485
+ "(重新运行 kb_tool.py sync-leaf-common-contract --write)")
486
+ for name in report["unexpected"]:
487
+ errors.append(f"{name}: 叶子公共契约副本出现在目标集合之外(不得静默保留)")
488
+ return errors, warns
489
+
490
+
491
+ # ---------------- CLI ----------------
492
+
493
+ def cmd_validate(args):
494
+ errors, warns = [], []
495
+ for sr in args.skill_root or []:
496
+ root = os.path.abspath(sr)
497
+ if not os.path.isdir(root):
498
+ errors.append(f"技能根不存在:{root}")
499
+ continue
500
+ e2, w2 = skill_path_problems(root)
501
+ errors += e2
502
+ warns += w2
503
+ e3, w3 = live_protocol_lint(root, args.forbid_literal)
504
+ errors += e3
505
+ warns += w3
506
+ e4, w4 = repo_reference_lint(root)
507
+ errors += e4
508
+ warns += w4
509
+ e5, w5 = leaf_common_contract_lint(root)
510
+ errors += e5
511
+ warns += w5
512
+ print("== validate 结果 ==")
513
+ for w in warns:
514
+ print(" [warn ] " + w)
515
+ for e_ in errors:
516
+ print(" [error] " + e_)
517
+ print(f"warn={len(warns)} error={len(errors)}")
518
+ return 1 if errors else 0
519
+
520
+
521
+ def cmd_sync_leaf_common_contract(args):
522
+ report = sync_leaf_common_contract(args.skill_root, write=bool(args.write))
523
+ print("== 叶子公共契约 %s ==" % ("同步(--write)" if args.write else "检查(--check)"))
524
+ print(f" 技能层:{report['skill_root']}")
525
+ print(f" 规范源:{report['source']}")
526
+ print(f" 目标副本:{report['target']}")
527
+ if report["status"] == "skip":
528
+ print(f" [skip ] {report['skip_reason']}")
529
+ return 0
530
+ print(f" 叶子集合:{report['leaves']} 个(目录发现,不写死)")
531
+ for leaf in report["missing"]:
532
+ print(f" [missing] {leaf}")
533
+ for leaf in report["drifted"]:
534
+ print(f" [drifted] {leaf}")
535
+ for name in report["unexpected"]:
536
+ print(f" [unexpected] {name}")
537
+ for leaf in report.get("written", []):
538
+ print(f" [written] {leaf}")
539
+ print(
540
+ f"missing={len(report['missing'])} drifted={len(report['drifted'])} "
541
+ f"unexpected={len(report['unexpected'])} written={len(report.get('written', []))}"
542
+ )
543
+ problems = len(report["missing"]) + len(report["drifted"]) + len(report["unexpected"])
544
+ return 1 if problems else 0
545
+
546
+
547
+ def main():
548
+ ap = argparse.ArgumentParser(
549
+ description="crwu 审核技能校验(只读引用卫生 + 实时引用协议 lint;知识正文唯一来源为钉钉)")
550
+ sub = ap.add_subparsers(dest="cmd", required=True)
551
+
552
+ p_v = sub.add_parser("validate", help="技能引用卫生(旧树标记/省略号/废止的本地根引用)与实时协议 lint")
553
+ p_v.add_argument("--skill-root", action="append", help="扫描的技能目录(如 plugins/dsh-crwu-workbench/skills/crwu),可多次")
554
+ p_v.add_argument("--forbid-literal", action="append", default=[], metavar="字面",
555
+ help="实时协议 lint:禁止出现的知识库名称等字面(可多次;根路径/nodeId 检查默认只对 crwu-audit*/crwu-dev-audit-* 目录生效)")
556
+ p_v.set_defaults(fn=cmd_validate)
557
+
558
+ p_s = sub.add_parser(
559
+ "sync-leaf-common-contract",
560
+ help="叶子公共契约:规范源 → 各叶子 references/03-common-contract.md(缺失/漂移/目标集合变化)")
561
+ p_s.add_argument("--skill-root", required=True,
562
+ help="技能层目录(如 plugins/dsh-crwu-workbench/skills/crwu)")
563
+ mode = p_s.add_mutually_exclusive_group()
564
+ mode.add_argument("--write", action="store_true", help="确定性生成/修复所有叶子副本(已一致的文件不触碰)")
565
+ mode.add_argument("--check", action="store_true", help="只报告 missing/drifted/unexpected,不写文件(默认)")
566
+ p_s.set_defaults(fn=cmd_sync_leaf_common_contract)
567
+
568
+ args = ap.parse_args()
569
+ try:
570
+ code = args.fn(args)
571
+ except BrokenPipeError:
572
+ code = 0
573
+ sys.exit(code if isinstance(code, int) else 0)
574
+
575
+
576
+ if __name__ == "__main__":
577
+ main()