create-yss-spec 2.1.11 → 2.1.14

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 (354) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/template/.agents/skills/high-fidelity-html-prototype/SKILL.md +1 -18
  4. package/template/.agents/skills/llm-wiki/SKILL.md +60 -0
  5. package/template/.agents/skills/llm-wiki/assets/CLAUDE.md.template +26 -0
  6. package/template/.agents/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/CLAUDE.md +3 -0
  7. package/template/.agents/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/index.md +5 -0
  8. package/template/.agents/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/log.md +1 -0
  9. package/template/.agents/skills/llm-wiki/assets/fixtures/broken-wiki/wiki//345/255/230/345/234/250/347/232/204/351/241/265.md +7 -0
  10. package/template/.agents/skills/llm-wiki/references/compile.md +126 -0
  11. package/template/.agents/skills/llm-wiki/references/discover.md +41 -0
  12. package/template/.agents/skills/llm-wiki/references/ingest.md +36 -0
  13. package/template/.agents/skills/llm-wiki/references/lint.md +54 -0
  14. package/template/.agents/skills/llm-wiki/references/query.md +21 -0
  15. package/template/.agents/skills/llm-wiki/references/schema.md +45 -0
  16. package/template/.agents/skills/llm-wiki/references/writing.md +35 -0
  17. package/template/.agents/skills/llm-wiki/scripts/advise.mjs +196 -0
  18. package/template/.agents/skills/llm-wiki/scripts/advise.test.mjs +91 -0
  19. package/template/.agents/skills/llm-wiki/scripts/extract.mjs +55 -0
  20. package/template/.agents/skills/llm-wiki/scripts/extract.test.mjs +34 -0
  21. package/template/.agents/skills/llm-wiki/scripts/inventory.mjs +174 -0
  22. package/template/.agents/skills/llm-wiki/scripts/inventory.test.mjs +98 -0
  23. package/template/.agents/skills/llm-wiki/scripts/lint-wikilinks.mjs +177 -0
  24. package/template/.agents/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +212 -0
  25. package/template/.agents/skills/yss-antd-design/SKILL.md +34 -0
  26. package/template/.agents/skills/yss-antd-design/references/boundaries.md +30 -0
  27. package/template/.agents/skills/yss-antd-design/references/cli-matrix.md +38 -0
  28. package/template/.agents/skills/yss-antd-design/references/evidence.md +26 -0
  29. package/template/.agents/skills/yss-antd-design/scripts/validate-frontmatter.mjs +46 -0
  30. package/template/.agents/skills/yss-antd-design/scripts/validate-frontmatter.test.mjs +27 -0
  31. package/template/.agents/skills/yss-design-system/SKILL.md +9 -5
  32. package/template/.agents/skills/yss-design-system/references/design-qa-theme.md +64 -0
  33. package/template/.agents/skills/yss-design-system/references/design-system.md +20 -12
  34. package/template/.agents/skills/yss-product-lifecycle/SKILL.md +1 -1
  35. package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +1 -1
  36. package/template/.agents/skills/yss-prototype-stage/SKILL.md +3 -1
  37. package/template/.agents/skills/yss-ui/SKILL.md +1 -1
  38. package/template/.claude/skills/high-fidelity-html-prototype/SKILL.md +1 -18
  39. package/template/.claude/skills/llm-wiki/SKILL.md +60 -0
  40. package/template/.claude/skills/llm-wiki/assets/CLAUDE.md.template +26 -0
  41. package/template/.claude/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/CLAUDE.md +3 -0
  42. package/template/.claude/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/index.md +5 -0
  43. package/template/.claude/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/log.md +1 -0
  44. package/template/.claude/skills/llm-wiki/assets/fixtures/broken-wiki/wiki//345/255/230/345/234/250/347/232/204/351/241/265.md +7 -0
  45. package/template/.claude/skills/llm-wiki/references/compile.md +126 -0
  46. package/template/.claude/skills/llm-wiki/references/discover.md +41 -0
  47. package/template/.claude/skills/llm-wiki/references/ingest.md +36 -0
  48. package/template/.claude/skills/llm-wiki/references/lint.md +54 -0
  49. package/template/.claude/skills/llm-wiki/references/query.md +21 -0
  50. package/template/.claude/skills/llm-wiki/references/schema.md +45 -0
  51. package/template/.claude/skills/llm-wiki/references/writing.md +35 -0
  52. package/template/.claude/skills/llm-wiki/scripts/advise.mjs +196 -0
  53. package/template/.claude/skills/llm-wiki/scripts/advise.test.mjs +91 -0
  54. package/template/.claude/skills/llm-wiki/scripts/extract.mjs +55 -0
  55. package/template/.claude/skills/llm-wiki/scripts/extract.test.mjs +34 -0
  56. package/template/.claude/skills/llm-wiki/scripts/inventory.mjs +174 -0
  57. package/template/.claude/skills/llm-wiki/scripts/inventory.test.mjs +98 -0
  58. package/template/.claude/skills/llm-wiki/scripts/lint-wikilinks.mjs +177 -0
  59. package/template/.claude/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +212 -0
  60. package/template/.claude/skills/yss-antd-design/SKILL.md +34 -0
  61. package/template/.claude/skills/yss-antd-design/references/boundaries.md +30 -0
  62. package/template/.claude/skills/yss-antd-design/references/cli-matrix.md +38 -0
  63. package/template/.claude/skills/yss-antd-design/references/evidence.md +26 -0
  64. package/template/.claude/skills/yss-antd-design/scripts/validate-frontmatter.mjs +46 -0
  65. package/template/.claude/skills/yss-antd-design/scripts/validate-frontmatter.test.mjs +27 -0
  66. package/template/.claude/skills/yss-design-system/SKILL.md +9 -5
  67. package/template/.claude/skills/yss-design-system/references/design-qa-theme.md +64 -0
  68. package/template/.claude/skills/yss-design-system/references/design-system.md +20 -12
  69. package/template/.claude/skills/yss-product-lifecycle/SKILL.md +1 -1
  70. package/template/.claude/skills/yss-product-lifecycle/references/orchestration-contract.yaml +1 -1
  71. package/template/.claude/skills/yss-prototype-stage/SKILL.md +3 -1
  72. package/template/.claude/skills/yss-ui/SKILL.md +1 -1
  73. package/template/.codex/skills/high-fidelity-html-prototype/SKILL.md +1 -18
  74. package/template/.codex/skills/llm-wiki/SKILL.md +60 -0
  75. package/template/.codex/skills/llm-wiki/assets/CLAUDE.md.template +26 -0
  76. package/template/.codex/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/CLAUDE.md +3 -0
  77. package/template/.codex/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/index.md +5 -0
  78. package/template/.codex/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/log.md +1 -0
  79. package/template/.codex/skills/llm-wiki/assets/fixtures/broken-wiki/wiki//345/255/230/345/234/250/347/232/204/351/241/265.md +7 -0
  80. package/template/.codex/skills/llm-wiki/references/compile.md +126 -0
  81. package/template/.codex/skills/llm-wiki/references/discover.md +41 -0
  82. package/template/.codex/skills/llm-wiki/references/ingest.md +36 -0
  83. package/template/.codex/skills/llm-wiki/references/lint.md +54 -0
  84. package/template/.codex/skills/llm-wiki/references/query.md +21 -0
  85. package/template/.codex/skills/llm-wiki/references/schema.md +45 -0
  86. package/template/.codex/skills/llm-wiki/references/writing.md +35 -0
  87. package/template/.codex/skills/llm-wiki/scripts/advise.mjs +196 -0
  88. package/template/.codex/skills/llm-wiki/scripts/advise.test.mjs +91 -0
  89. package/template/.codex/skills/llm-wiki/scripts/extract.mjs +55 -0
  90. package/template/.codex/skills/llm-wiki/scripts/extract.test.mjs +34 -0
  91. package/template/.codex/skills/llm-wiki/scripts/inventory.mjs +174 -0
  92. package/template/.codex/skills/llm-wiki/scripts/inventory.test.mjs +98 -0
  93. package/template/.codex/skills/llm-wiki/scripts/lint-wikilinks.mjs +177 -0
  94. package/template/.codex/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +212 -0
  95. package/template/.codex/skills/yss-antd-design/SKILL.md +34 -0
  96. package/template/.codex/skills/yss-antd-design/references/boundaries.md +30 -0
  97. package/template/.codex/skills/yss-antd-design/references/cli-matrix.md +38 -0
  98. package/template/.codex/skills/yss-antd-design/references/evidence.md +26 -0
  99. package/template/.codex/skills/yss-antd-design/scripts/validate-frontmatter.mjs +46 -0
  100. package/template/.codex/skills/yss-antd-design/scripts/validate-frontmatter.test.mjs +27 -0
  101. package/template/.codex/skills/yss-design-system/SKILL.md +9 -5
  102. package/template/.codex/skills/yss-design-system/references/design-qa-theme.md +64 -0
  103. package/template/.codex/skills/yss-design-system/references/design-system.md +20 -12
  104. package/template/.codex/skills/yss-product-lifecycle/SKILL.md +1 -1
  105. package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +1 -1
  106. package/template/.codex/skills/yss-prototype-stage/SKILL.md +3 -1
  107. package/template/.codex/skills/yss-ui/SKILL.md +1 -1
  108. package/template/.cursor/skills/high-fidelity-html-prototype/SKILL.md +1 -18
  109. package/template/.cursor/skills/llm-wiki/SKILL.md +60 -0
  110. package/template/.cursor/skills/llm-wiki/assets/CLAUDE.md.template +26 -0
  111. package/template/.cursor/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/CLAUDE.md +3 -0
  112. package/template/.cursor/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/index.md +5 -0
  113. package/template/.cursor/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/log.md +1 -0
  114. package/template/.cursor/skills/llm-wiki/assets/fixtures/broken-wiki/wiki//345/255/230/345/234/250/347/232/204/351/241/265.md +7 -0
  115. package/template/.cursor/skills/llm-wiki/references/compile.md +126 -0
  116. package/template/.cursor/skills/llm-wiki/references/discover.md +41 -0
  117. package/template/.cursor/skills/llm-wiki/references/ingest.md +36 -0
  118. package/template/.cursor/skills/llm-wiki/references/lint.md +54 -0
  119. package/template/.cursor/skills/llm-wiki/references/query.md +21 -0
  120. package/template/.cursor/skills/llm-wiki/references/schema.md +45 -0
  121. package/template/.cursor/skills/llm-wiki/references/writing.md +35 -0
  122. package/template/.cursor/skills/llm-wiki/scripts/advise.mjs +196 -0
  123. package/template/.cursor/skills/llm-wiki/scripts/advise.test.mjs +91 -0
  124. package/template/.cursor/skills/llm-wiki/scripts/extract.mjs +55 -0
  125. package/template/.cursor/skills/llm-wiki/scripts/extract.test.mjs +34 -0
  126. package/template/.cursor/skills/llm-wiki/scripts/inventory.mjs +174 -0
  127. package/template/.cursor/skills/llm-wiki/scripts/inventory.test.mjs +98 -0
  128. package/template/.cursor/skills/llm-wiki/scripts/lint-wikilinks.mjs +177 -0
  129. package/template/.cursor/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +212 -0
  130. package/template/.cursor/skills/yss-antd-design/SKILL.md +34 -0
  131. package/template/.cursor/skills/yss-antd-design/references/boundaries.md +30 -0
  132. package/template/.cursor/skills/yss-antd-design/references/cli-matrix.md +38 -0
  133. package/template/.cursor/skills/yss-antd-design/references/evidence.md +26 -0
  134. package/template/.cursor/skills/yss-antd-design/scripts/validate-frontmatter.mjs +46 -0
  135. package/template/.cursor/skills/yss-antd-design/scripts/validate-frontmatter.test.mjs +27 -0
  136. package/template/.cursor/skills/yss-design-system/SKILL.md +9 -5
  137. package/template/.cursor/skills/yss-design-system/references/design-qa-theme.md +64 -0
  138. package/template/.cursor/skills/yss-design-system/references/design-system.md +20 -12
  139. package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +1 -1
  140. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +1 -1
  141. package/template/.cursor/skills/yss-prototype-stage/SKILL.md +3 -1
  142. package/template/.cursor/skills/yss-ui/SKILL.md +1 -1
  143. package/template/.hermes/skills/high-fidelity-html-prototype/SKILL.md +1 -18
  144. package/template/.hermes/skills/llm-wiki/SKILL.md +60 -0
  145. package/template/.hermes/skills/llm-wiki/assets/CLAUDE.md.template +26 -0
  146. package/template/.hermes/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/CLAUDE.md +3 -0
  147. package/template/.hermes/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/index.md +5 -0
  148. package/template/.hermes/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/log.md +1 -0
  149. package/template/.hermes/skills/llm-wiki/assets/fixtures/broken-wiki/wiki//345/255/230/345/234/250/347/232/204/351/241/265.md +7 -0
  150. package/template/.hermes/skills/llm-wiki/references/compile.md +126 -0
  151. package/template/.hermes/skills/llm-wiki/references/discover.md +41 -0
  152. package/template/.hermes/skills/llm-wiki/references/ingest.md +36 -0
  153. package/template/.hermes/skills/llm-wiki/references/lint.md +54 -0
  154. package/template/.hermes/skills/llm-wiki/references/query.md +21 -0
  155. package/template/.hermes/skills/llm-wiki/references/schema.md +45 -0
  156. package/template/.hermes/skills/llm-wiki/references/writing.md +35 -0
  157. package/template/.hermes/skills/llm-wiki/scripts/advise.mjs +196 -0
  158. package/template/.hermes/skills/llm-wiki/scripts/advise.test.mjs +91 -0
  159. package/template/.hermes/skills/llm-wiki/scripts/extract.mjs +55 -0
  160. package/template/.hermes/skills/llm-wiki/scripts/extract.test.mjs +34 -0
  161. package/template/.hermes/skills/llm-wiki/scripts/inventory.mjs +174 -0
  162. package/template/.hermes/skills/llm-wiki/scripts/inventory.test.mjs +98 -0
  163. package/template/.hermes/skills/llm-wiki/scripts/lint-wikilinks.mjs +177 -0
  164. package/template/.hermes/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +212 -0
  165. package/template/.hermes/skills/yss-antd-design/SKILL.md +34 -0
  166. package/template/.hermes/skills/yss-antd-design/references/boundaries.md +30 -0
  167. package/template/.hermes/skills/yss-antd-design/references/cli-matrix.md +38 -0
  168. package/template/.hermes/skills/yss-antd-design/references/evidence.md +26 -0
  169. package/template/.hermes/skills/yss-antd-design/scripts/validate-frontmatter.mjs +46 -0
  170. package/template/.hermes/skills/yss-antd-design/scripts/validate-frontmatter.test.mjs +27 -0
  171. package/template/.hermes/skills/yss-design-system/SKILL.md +9 -5
  172. package/template/.hermes/skills/yss-design-system/references/design-qa-theme.md +64 -0
  173. package/template/.hermes/skills/yss-design-system/references/design-system.md +20 -12
  174. package/template/.hermes/skills/yss-product-lifecycle/SKILL.md +1 -1
  175. package/template/.hermes/skills/yss-product-lifecycle/references/orchestration-contract.yaml +1 -1
  176. package/template/.hermes/skills/yss-prototype-stage/SKILL.md +3 -1
  177. package/template/.hermes/skills/yss-ui/SKILL.md +1 -1
  178. package/template/.pi/skills/high-fidelity-html-prototype/SKILL.md +1 -18
  179. package/template/.pi/skills/llm-wiki/SKILL.md +60 -0
  180. package/template/.pi/skills/llm-wiki/assets/CLAUDE.md.template +26 -0
  181. package/template/.pi/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/CLAUDE.md +3 -0
  182. package/template/.pi/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/index.md +5 -0
  183. package/template/.pi/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/log.md +1 -0
  184. package/template/.pi/skills/llm-wiki/assets/fixtures/broken-wiki/wiki//345/255/230/345/234/250/347/232/204/351/241/265.md +7 -0
  185. package/template/.pi/skills/llm-wiki/references/compile.md +126 -0
  186. package/template/.pi/skills/llm-wiki/references/discover.md +41 -0
  187. package/template/.pi/skills/llm-wiki/references/ingest.md +36 -0
  188. package/template/.pi/skills/llm-wiki/references/lint.md +54 -0
  189. package/template/.pi/skills/llm-wiki/references/query.md +21 -0
  190. package/template/.pi/skills/llm-wiki/references/schema.md +45 -0
  191. package/template/.pi/skills/llm-wiki/references/writing.md +35 -0
  192. package/template/.pi/skills/llm-wiki/scripts/advise.mjs +196 -0
  193. package/template/.pi/skills/llm-wiki/scripts/advise.test.mjs +91 -0
  194. package/template/.pi/skills/llm-wiki/scripts/extract.mjs +55 -0
  195. package/template/.pi/skills/llm-wiki/scripts/extract.test.mjs +34 -0
  196. package/template/.pi/skills/llm-wiki/scripts/inventory.mjs +174 -0
  197. package/template/.pi/skills/llm-wiki/scripts/inventory.test.mjs +98 -0
  198. package/template/.pi/skills/llm-wiki/scripts/lint-wikilinks.mjs +177 -0
  199. package/template/.pi/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +212 -0
  200. package/template/.pi/skills/yss-antd-design/SKILL.md +34 -0
  201. package/template/.pi/skills/yss-antd-design/references/boundaries.md +30 -0
  202. package/template/.pi/skills/yss-antd-design/references/cli-matrix.md +38 -0
  203. package/template/.pi/skills/yss-antd-design/references/evidence.md +26 -0
  204. package/template/.pi/skills/yss-antd-design/scripts/validate-frontmatter.mjs +46 -0
  205. package/template/.pi/skills/yss-antd-design/scripts/validate-frontmatter.test.mjs +27 -0
  206. package/template/.pi/skills/yss-design-system/SKILL.md +9 -5
  207. package/template/.pi/skills/yss-design-system/references/design-qa-theme.md +64 -0
  208. package/template/.pi/skills/yss-design-system/references/design-system.md +20 -12
  209. package/template/.pi/skills/yss-product-lifecycle/SKILL.md +1 -1
  210. package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +1 -1
  211. package/template/.pi/skills/yss-prototype-stage/SKILL.md +3 -1
  212. package/template/.pi/skills/yss-ui/SKILL.md +1 -1
  213. package/template/.qoder/skills/high-fidelity-html-prototype/SKILL.md +1 -18
  214. package/template/.qoder/skills/llm-wiki/SKILL.md +60 -0
  215. package/template/.qoder/skills/llm-wiki/assets/CLAUDE.md.template +26 -0
  216. package/template/.qoder/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/CLAUDE.md +3 -0
  217. package/template/.qoder/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/index.md +5 -0
  218. package/template/.qoder/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/log.md +1 -0
  219. package/template/.qoder/skills/llm-wiki/assets/fixtures/broken-wiki/wiki//345/255/230/345/234/250/347/232/204/351/241/265.md +7 -0
  220. package/template/.qoder/skills/llm-wiki/references/compile.md +126 -0
  221. package/template/.qoder/skills/llm-wiki/references/discover.md +41 -0
  222. package/template/.qoder/skills/llm-wiki/references/ingest.md +36 -0
  223. package/template/.qoder/skills/llm-wiki/references/lint.md +54 -0
  224. package/template/.qoder/skills/llm-wiki/references/query.md +21 -0
  225. package/template/.qoder/skills/llm-wiki/references/schema.md +45 -0
  226. package/template/.qoder/skills/llm-wiki/references/writing.md +35 -0
  227. package/template/.qoder/skills/llm-wiki/scripts/advise.mjs +196 -0
  228. package/template/.qoder/skills/llm-wiki/scripts/advise.test.mjs +91 -0
  229. package/template/.qoder/skills/llm-wiki/scripts/extract.mjs +55 -0
  230. package/template/.qoder/skills/llm-wiki/scripts/extract.test.mjs +34 -0
  231. package/template/.qoder/skills/llm-wiki/scripts/inventory.mjs +174 -0
  232. package/template/.qoder/skills/llm-wiki/scripts/inventory.test.mjs +98 -0
  233. package/template/.qoder/skills/llm-wiki/scripts/lint-wikilinks.mjs +177 -0
  234. package/template/.qoder/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +212 -0
  235. package/template/.qoder/skills/yss-antd-design/SKILL.md +34 -0
  236. package/template/.qoder/skills/yss-antd-design/references/boundaries.md +30 -0
  237. package/template/.qoder/skills/yss-antd-design/references/cli-matrix.md +38 -0
  238. package/template/.qoder/skills/yss-antd-design/references/evidence.md +26 -0
  239. package/template/.qoder/skills/yss-antd-design/scripts/validate-frontmatter.mjs +46 -0
  240. package/template/.qoder/skills/yss-antd-design/scripts/validate-frontmatter.test.mjs +27 -0
  241. package/template/.qoder/skills/yss-design-system/SKILL.md +9 -5
  242. package/template/.qoder/skills/yss-design-system/references/design-qa-theme.md +64 -0
  243. package/template/.qoder/skills/yss-design-system/references/design-system.md +20 -12
  244. package/template/.qoder/skills/yss-product-lifecycle/SKILL.md +1 -1
  245. package/template/.qoder/skills/yss-product-lifecycle/references/orchestration-contract.yaml +1 -1
  246. package/template/.qoder/skills/yss-prototype-stage/SKILL.md +3 -1
  247. package/template/.qoder/skills/yss-ui/SKILL.md +1 -1
  248. package/template/.trae/skills/high-fidelity-html-prototype/SKILL.md +1 -18
  249. package/template/.trae/skills/llm-wiki/SKILL.md +60 -0
  250. package/template/.trae/skills/llm-wiki/assets/CLAUDE.md.template +26 -0
  251. package/template/.trae/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/CLAUDE.md +3 -0
  252. package/template/.trae/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/index.md +5 -0
  253. package/template/.trae/skills/llm-wiki/assets/fixtures/broken-wiki/wiki/log.md +1 -0
  254. package/template/.trae/skills/llm-wiki/assets/fixtures/broken-wiki/wiki//345/255/230/345/234/250/347/232/204/351/241/265.md +7 -0
  255. package/template/.trae/skills/llm-wiki/references/compile.md +126 -0
  256. package/template/.trae/skills/llm-wiki/references/discover.md +41 -0
  257. package/template/.trae/skills/llm-wiki/references/ingest.md +36 -0
  258. package/template/.trae/skills/llm-wiki/references/lint.md +54 -0
  259. package/template/.trae/skills/llm-wiki/references/query.md +21 -0
  260. package/template/.trae/skills/llm-wiki/references/schema.md +45 -0
  261. package/template/.trae/skills/llm-wiki/references/writing.md +35 -0
  262. package/template/.trae/skills/llm-wiki/scripts/advise.mjs +196 -0
  263. package/template/.trae/skills/llm-wiki/scripts/advise.test.mjs +91 -0
  264. package/template/.trae/skills/llm-wiki/scripts/extract.mjs +55 -0
  265. package/template/.trae/skills/llm-wiki/scripts/extract.test.mjs +34 -0
  266. package/template/.trae/skills/llm-wiki/scripts/inventory.mjs +174 -0
  267. package/template/.trae/skills/llm-wiki/scripts/inventory.test.mjs +98 -0
  268. package/template/.trae/skills/llm-wiki/scripts/lint-wikilinks.mjs +177 -0
  269. package/template/.trae/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +212 -0
  270. package/template/.trae/skills/yss-antd-design/SKILL.md +34 -0
  271. package/template/.trae/skills/yss-antd-design/references/boundaries.md +30 -0
  272. package/template/.trae/skills/yss-antd-design/references/cli-matrix.md +38 -0
  273. package/template/.trae/skills/yss-antd-design/references/evidence.md +26 -0
  274. package/template/.trae/skills/yss-antd-design/scripts/validate-frontmatter.mjs +46 -0
  275. package/template/.trae/skills/yss-antd-design/scripts/validate-frontmatter.test.mjs +27 -0
  276. package/template/.trae/skills/yss-design-system/SKILL.md +9 -5
  277. package/template/.trae/skills/yss-design-system/references/design-qa-theme.md +64 -0
  278. package/template/.trae/skills/yss-design-system/references/design-system.md +20 -12
  279. package/template/.trae/skills/yss-product-lifecycle/SKILL.md +1 -1
  280. package/template/.trae/skills/yss-product-lifecycle/references/orchestration-contract.yaml +1 -1
  281. package/template/.trae/skills/yss-prototype-stage/SKILL.md +3 -1
  282. package/template/.trae/skills/yss-ui/SKILL.md +1 -1
  283. package/template/AGENTS.md +5 -3
  284. package/template/CLAUDE.md +13 -0
  285. package/template/CONTEXT.md +75 -65
  286. package/template/docs/agents/domain.md +4 -3
  287. package/template/docs/agents/yss-skill-registry.yaml +12 -0
  288. package/template/docs/design/README.md +5 -5
  289. package/template/docs/design/design.md +94 -29
  290. package/template/docs/design/templates/prototype-evidence-template.yaml +12 -1
  291. package/template/docs/design/tokens/theme.json +16 -9
  292. package/template/docs/design/tokens/tokens.compact.json +35 -32
  293. package/template/docs/design/tokens/tokens.dark.json +5 -5
  294. package/template/docs/design/tokens/tokens.default.json +41 -32
  295. package/template/docs/design/tokens/variables.css +62 -37
  296. package/template/docs/design/tokens/variables.dark.css +5 -5
  297. package/template/docs/process/implementation-repo-integration.md +9 -0
  298. package/template/docs/templates/requirement-freeze-template.md +1 -1
  299. package/template/docs/templates/review-report-template.md +1 -0
  300. package/template/docs/templates/spec-template.md +1 -1
  301. package/template/docs/templates/vertical-slice-ticket-template.md +1 -1
  302. package/template/docs/user-guide//344/272/247/345/223/201/347/224/237/345/221/275/345/221/250/346/234/237/345/267/245/344/275/234/346/265/201.md +10 -10
  303. package/template/docs/user-guide//344/272/247/345/223/201/347/240/224/345/217/221/345/205/250/347/224/237/345/221/275/345/221/250/346/234/237/346/234/200/344/275/263/345/256/236/350/267/265.md +7 -7
  304. package/template/docs/user-guide//347/224/237/345/221/275/345/221/250/346/234/237/346/234/200/344/275/263/345/256/236/350/267/265.md +5 -5
  305. package/template/docs/user-guide//351/234/200/346/261/202/346/276/204/346/270/205/346/214/207/345/215/227.md +6 -7
  306. package/template/docs/user-guide//351/234/200/346/261/202/346/276/204/346/270/205/346/234/200/344/275/263/345/256/236/350/267/265.md +3 -3
  307. package/template/skills-lock.json +37 -5
  308. package/template/wiki/.wiki-manifest.json +390 -0
  309. package/template/wiki/raw/AGENTS.md +43 -62
  310. package/template/wiki/raw/CONTEXT.md +76 -42
  311. package/template/wiki/raw/README.md +4 -1
  312. package/template/wiki/raw/create-yss-spec-repository-mode-contract.md +95 -0
  313. package/template/wiki/raw/harness-process-tailoring.md +64 -0
  314. package/template/wiki/raw/implementation-repo-integration.md +62 -0
  315. package/template/wiki/raw/issue-tracker.md +135 -0
  316. package/template/wiki/raw/lifecycle-registry.yaml +369 -0
  317. package/template/wiki/raw/maintenance-intensity.yaml +25 -0
  318. package/template/wiki/raw/skills-lock-names.md +93 -0
  319. package/template/wiki/raw/skills-maintenance.md +90 -0
  320. package/template/wiki/raw/spec-template.md +4 -5
  321. package/template/wiki/raw/triage-labels.md +15 -0
  322. package/template/wiki/raw/vertical-slice-ticket-template.md +15 -9
  323. package/template/wiki/raw/yss-skill-registry.yaml +510 -0
  324. package/template/wiki/wiki/Agent/345/205/245/345/217/243/350/247/204/345/210/231.md +17 -5
  325. package/template/wiki/wiki/CLAUDE.md +15 -11
  326. package/template/wiki/wiki/Fresh/351/252/214/350/257/201/344/270/216/347/213/254/347/253/213/345/256/241/346/237/245.md +15 -5
  327. package/template/wiki/wiki/LLM Wiki.md +30 -0
  328. package/template/wiki/wiki/Matt/346/212/200/350/203/275/344/275/223/347/263/273.md +17 -5
  329. package/template/wiki/wiki/OpenAPI/345/245/221/347/272/246.md +16 -5
  330. package/template/wiki/wiki/SpecDelta.md +15 -5
  331. package/template/wiki/wiki/Spec/345/237/272/347/272/277.md +18 -5
  332. package/template/wiki/wiki/Ticket/344/270/216/346/265/201/347/250/213/347/212/266/346/200/201.md +17 -5
  333. package/template/wiki/wiki/YSS/345/267/245/347/250/213/346/212/200/350/203/275/344/275/223/347/263/273.md +19 -5
  334. package/template/wiki/wiki/YSS/350/267/257/347/224/261/344/270/216/345/220/210/345/220/214/347/274/226/350/257/221.md +16 -5
  335. package/template/wiki/wiki/concept-table.md +9 -0
  336. package/template/wiki/wiki/index.md +12 -11
  337. package/template/wiki/wiki/log.md +34 -0
  338. package/template/wiki/wiki//344/272/247/345/223/201/347/240/224/345/217/221/347/224/237/345/221/275/345/221/250/346/234/237.md +15 -4
  339. package/template/wiki/wiki//344/272/247/345/223/201/350/256/276/350/256/241/345/275/261/345/223/215/344/270/216/345/216/237/345/236/213.md +14 -4
  340. package/template/wiki/wiki//344/273/223/345/272/223/350/272/253/344/273/275/344/270/216/350/267/257/347/224/261.md +15 -4
  341. package/template/wiki/wiki//345/210/207/347/211/207/345/256/236/347/216/260/345/220/210/345/220/214.md +17 -5
  342. package/template/wiki/wiki//345/236/202/347/233/264/345/210/207/347/211/207Ticket.md +19 -5
  343. package/template/wiki/wiki//345/244/215/347/233/230/344/270/216/346/235/203/345/250/201/350/265/204/344/272/247/344/277/256/350/256/242.md +15 -4
  344. package/template/wiki/wiki//345/256/236/347/216/260/344/273/223/345/272/223/344/270/216/350/267/250/344/273/223/345/272/223/345/245/221/347/272/246.md +17 -4
  345. package/template/wiki/wiki//345/275/261/345/223/215/351/235/242/345/210/206/350/257/212/344/270/216/346/265/201/347/250/213/350/243/201/345/211/252.md +15 -4
  346. package/template/wiki/wiki//346/212/200/350/203/275/346/212/225/345/275/261/344/270/216/351/224/201/345/256/232.md +18 -4
  347. package/template/wiki/wiki//346/235/241/344/273/266/345/274/272/345/210/266/351/227/250/347/246/201.md +13 -4
  348. package/template/wiki/wiki//346/250/241/346/235/277/345/217/221/345/270/203/351/227/250/347/246/201/344/270/216/351/252/214/350/257/201.md +17 -4
  349. package/template/wiki/wiki//346/250/241/346/235/277/346/200/273/350/247/210.md +16 -5
  350. package/template/wiki/wiki//346/250/241/346/235/277/347/273/264/346/212/244/346/265/201/347/250/213.md +14 -4
  351. package/template/yss-public-skills.json +2 -0
  352. package/template.snapshot.json +4 -4
  353. package/template/wiki/raw/create-yss-spec-contract.md +0 -59
  354. package/template/wiki/raw/skills-lock.json +0 -1379
@@ -0,0 +1,196 @@
1
+ #!/usr/bin/env node
2
+ import { readFile, readdir } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { exists } from "./inventory.mjs";
6
+ import { articlesDir, extractLinks, INFRA } from "./lint-wikilinks.mjs";
7
+
8
+ const SOURCE_HEADING_RE = /^##\s+来源\s*$/m;
9
+ const H1_RE = /^#\s+(.+?)\s*$/m;
10
+ const NUMBER_RE = /\b\d+(?:\.\d+)?[A-Za-z%]+\b/g;
11
+ const ISO_DATE_RE = /\b\d{4}-\d{2}-\d{2}\b/g;
12
+ const LONG_QUOTE_RE = /[“"]([^”"]{12,})[”"]/g;
13
+ const BACKTICK_RE = /`([^`\n]{2,64})`/g;
14
+ const BOLD_RE = /\*\*([^*]{2,32})\*\*/g;
15
+ const HEADING_RE = /^#{2,6}\s+(.+)$/gm;
16
+
17
+ export function sourceSection(text) {
18
+ const match = text.match(SOURCE_HEADING_RE);
19
+ if (!match) return "";
20
+ return text.slice(match.index + match[0].length);
21
+ }
22
+
23
+ export function firstParagraph(text) {
24
+ const afterH1 = text.replace(/^---[\s\S]*?---\s*/, "").replace(H1_RE, "").trimStart();
25
+ const block = afterH1.split(/\n\s*\n/)[0] || "";
26
+ return block.trim();
27
+ }
28
+
29
+ export function articleBody(text) {
30
+ const source = text.search(SOURCE_HEADING_RE);
31
+ const head = source === -1 ? text : text.slice(0, source);
32
+ return head.replace(/^---[\s\S]*?---\s*/, "");
33
+ }
34
+
35
+ export function highSignalLiterals(text) {
36
+ const found = new Set();
37
+ for (const match of text.matchAll(NUMBER_RE)) found.add(match[0]);
38
+ for (const match of text.matchAll(ISO_DATE_RE)) found.add(match[0]);
39
+ for (const match of text.matchAll(LONG_QUOTE_RE)) found.add(match[1]);
40
+ return [...found];
41
+ }
42
+
43
+ function addTerm(counter, term) {
44
+ const value = term.trim();
45
+ if (!value) return;
46
+ counter.set(value, (counter.get(value) || 0) + 1);
47
+ }
48
+
49
+ export function collectTerms(text) {
50
+ const body = articleBody(text);
51
+ const counter = new Map();
52
+ for (const match of body.matchAll(BACKTICK_RE)) addTerm(counter, match[1]);
53
+ for (const match of body.matchAll(BOLD_RE)) addTerm(counter, match[1]);
54
+ for (const match of body.matchAll(HEADING_RE)) addTerm(counter, match[1]);
55
+ return counter;
56
+ }
57
+
58
+ export async function loadArticles(wikiRoot) {
59
+ const dir = articlesDir(wikiRoot);
60
+ const names = (await readdir(dir)).filter((name) => name.endsWith(".md"));
61
+ const files = names.filter((name) => !INFRA.has(name.toLowerCase()));
62
+ const articles = [];
63
+ for (const file of files) {
64
+ const text = await readFile(path.join(dir, file), "utf8");
65
+ articles.push({
66
+ id: file.slice(0, -3),
67
+ file,
68
+ text,
69
+ links: extractLinks(text).ids,
70
+ });
71
+ }
72
+ return articles;
73
+ }
74
+
75
+ export function oneWayLinks(articles) {
76
+ const inbound = new Map();
77
+ for (const article of articles) inbound.set(article.id, new Set());
78
+ for (const article of articles) {
79
+ for (const target of article.links) {
80
+ if (!inbound.has(target)) continue;
81
+ inbound.get(target).add(article.id);
82
+ }
83
+ }
84
+ const findings = [];
85
+ for (const article of articles) {
86
+ for (const target of new Set(article.links)) {
87
+ if (target === article.id) continue;
88
+ if (!inbound.has(target)) continue;
89
+ if (inbound.get(article.id).has(target)) continue;
90
+ findings.push({ from: article.id, to: target });
91
+ }
92
+ }
93
+ return findings;
94
+ }
95
+
96
+ export function missingTermPages(articles) {
97
+ const ids = new Set(articles.map((article) => article.id));
98
+ const counts = new Map();
99
+ for (const article of articles) {
100
+ const local = collectTerms(article.text);
101
+ for (const [term, count] of local) {
102
+ if (ids.has(term)) continue;
103
+ counts.set(term, (counts.get(term) || 0) + count);
104
+ }
105
+ }
106
+ return [...counts.entries()]
107
+ .filter(([, count]) => count >= 2)
108
+ .map(([term, count]) => ({ term, count }))
109
+ .sort((a, b) => b.count - a.count || a.term.localeCompare(b.term));
110
+ }
111
+
112
+ export function unreferencedRaws(manifest, articles) {
113
+ const cited = articles.map((article) => sourceSection(article.text)).join("\n");
114
+ const findings = [];
115
+ for (const source of manifest.sources || []) {
116
+ if (!source.rawPath) continue;
117
+ if (cited.includes(source.rawPath) || cited.includes(source.id)) continue;
118
+ findings.push({ id: source.id, rawPath: source.rawPath });
119
+ }
120
+ return findings;
121
+ }
122
+
123
+ async function citedCorpus({ wikiRoot, repoRoot, article, manifest }) {
124
+ const cited = sourceSection(article.text);
125
+ const chunks = [cited];
126
+ for (const source of manifest.sources || []) {
127
+ const mentioned =
128
+ (source.rawPath && cited.includes(source.rawPath)) ||
129
+ (source.id && cited.includes(source.id)) ||
130
+ (source.livePath && cited.includes(source.livePath));
131
+ if (!mentioned) continue;
132
+ if (source.rawPath) {
133
+ const raw = path.resolve(wikiRoot, source.rawPath);
134
+ if (await exists(raw)) chunks.push(await readFile(raw, "utf8"));
135
+ }
136
+ if (source.livePath) {
137
+ const live = path.resolve(repoRoot, source.livePath);
138
+ if (await exists(live)) chunks.push(await readFile(live, "utf8"));
139
+ }
140
+ }
141
+ return chunks.join("\n");
142
+ }
143
+
144
+ export async function evidenceSuspects({ wikiRoot, repoRoot, articles, manifest }) {
145
+ const findings = [];
146
+ for (const article of articles) {
147
+ const literals = highSignalLiterals(articleBody(article.text));
148
+ if (!literals.length) continue;
149
+ const corpus = await citedCorpus({ wikiRoot, repoRoot, article, manifest });
150
+ for (const value of literals) {
151
+ if (!corpus.includes(value)) {
152
+ findings.push({ article: article.id, value });
153
+ }
154
+ }
155
+ }
156
+ return findings;
157
+ }
158
+
159
+ export async function adviseWiki(wikiRoot, { repoRoot = process.cwd() } = {}) {
160
+ const articles = await loadArticles(wikiRoot);
161
+ const manifestFile = path.join(wikiRoot, ".wiki-manifest.json");
162
+ const manifest = (await exists(manifestFile))
163
+ ? JSON.parse(await readFile(manifestFile, "utf8"))
164
+ : { sources: [] };
165
+ return {
166
+ oneWayLinks: oneWayLinks(articles),
167
+ missingTermPages: missingTermPages(articles),
168
+ unreferencedRaws: unreferencedRaws(manifest, articles),
169
+ suspects: await evidenceSuspects({ wikiRoot, repoRoot, articles, manifest }),
170
+ };
171
+ }
172
+
173
+ function parseArgs(argv) {
174
+ const args = { wiki: null, repo: process.cwd() };
175
+ for (let i = 0; i < argv.length; i += 1) {
176
+ if (argv[i] === "--repo") args.repo = argv[++i];
177
+ else if (argv[i] === "--wiki") args.wiki = argv[++i];
178
+ else if (!args.wiki && !argv[i].startsWith("-")) args.wiki = argv[i];
179
+ }
180
+ return args;
181
+ }
182
+
183
+ async function main(argv = process.argv.slice(2)) {
184
+ const args = parseArgs(argv);
185
+ if (!args.wiki) throw new Error("usage: advise.mjs <wiki-root> [--repo <repo-root>]");
186
+ const wikiRoot = path.resolve(args.repo, args.wiki);
187
+ const report = await adviseWiki(wikiRoot, { repoRoot: path.resolve(args.repo) });
188
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
189
+ }
190
+
191
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
192
+ main().catch((error) => {
193
+ process.stderr.write(`${error.message}\n`);
194
+ process.exitCode = 2;
195
+ });
196
+ }
@@ -0,0 +1,91 @@
1
+ import assert from "node:assert/strict";
2
+ import { spawnSync } from "node:child_process";
3
+ import { mkdir, mkdtemp, writeFile } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import path from "node:path";
6
+ import test from "node:test";
7
+ import { fileURLToPath } from "node:url";
8
+ import { sha256 } from "./inventory.mjs";
9
+ import { adviseWiki } from "./advise.mjs";
10
+ import { lintWiki } from "./lint-wikilinks.mjs";
11
+
12
+ const adviseCli = fileURLToPath(new URL("./advise.mjs", import.meta.url));
13
+
14
+ async function seedAdvise() {
15
+ const repo = await mkdtemp(path.join(tmpdir(), "llm-wiki-advise-"));
16
+ const wikiRoot = path.join(repo, "wiki-root");
17
+ const wiki = path.join(wikiRoot, "wiki");
18
+ await mkdir(wiki, { recursive: true });
19
+ await mkdir(path.join(wikiRoot, "raw"), { recursive: true });
20
+ await mkdir(path.join(repo, "docs"), { recursive: true });
21
+ await writeFile(path.join(repo, "docs", "api.md"), "version one\n", "utf8");
22
+ await writeFile(path.join(wikiRoot, "raw", "api.md"), "version one\n", "utf8");
23
+ await writeFile(path.join(wikiRoot, "raw", "orphan-raw.md"), "unused\n", "utf8");
24
+ await writeFile(path.join(wiki, "index.md"), "# index\n\n## 分类\n\n- [[Alpha]]\n- [[Beta]]\n", "utf8");
25
+ await writeFile(
26
+ path.join(wiki, "Alpha.md"),
27
+ "# Alpha\n\nSee [[Beta]] and **孤立术语**. The figure is 42K.\n\n## 来源\n\n- raw/api.md\n",
28
+ "utf8",
29
+ );
30
+ await writeFile(
31
+ path.join(wiki, "Beta.md"),
32
+ "# Beta\n\nMentions **孤立术语** again.\n\n## 来源\n\n- raw/api.md\n",
33
+ "utf8",
34
+ );
35
+ await writeFile(path.join(wiki, "concept-table.md"), "# concepts\n", "utf8");
36
+ await writeFile(
37
+ path.join(wikiRoot, ".wiki-manifest.json"),
38
+ JSON.stringify({
39
+ schemaVersion: 1,
40
+ profile: "documents",
41
+ sources: [
42
+ {
43
+ id: "api.md",
44
+ kind: "document",
45
+ livePath: "docs/api.md",
46
+ rawPath: "raw/api.md",
47
+ sha256: sha256(Buffer.from("version one\n")),
48
+ },
49
+ {
50
+ id: "orphan-raw.md",
51
+ kind: "document",
52
+ livePath: "docs/api.md",
53
+ rawPath: "raw/orphan-raw.md",
54
+ sha256: sha256(Buffer.from("version one\n")),
55
+ },
56
+ ],
57
+ articles: [
58
+ { id: "Alpha", file: "wiki/Alpha.md", sourceIds: ["api.md"] },
59
+ { id: "Beta", file: "wiki/Beta.md", sourceIds: ["api.md"] },
60
+ ],
61
+ }),
62
+ "utf8",
63
+ );
64
+ return { repo, wikiRoot };
65
+ }
66
+
67
+ test("advise reports one-way links, missing terms, unreferenced raw, and suspects without failing lint", async () => {
68
+ const { repo, wikiRoot } = await seedAdvise();
69
+ const lint = await lintWiki(wikiRoot, { repoRoot: repo });
70
+ assert.equal(lint.ok, true, lint.errors.join("\n"));
71
+ const report = await adviseWiki(wikiRoot, { repoRoot: repo });
72
+ assert.ok(report.oneWayLinks.some((item) => item.from === "Alpha" && item.to === "Beta"));
73
+ assert.ok(report.missingTermPages.some((item) => item.term === "孤立术语" && item.count >= 2));
74
+ assert.ok(report.unreferencedRaws.some((item) => item.rawPath === "raw/orphan-raw.md"));
75
+ assert.ok(report.suspects.some((item) => item.article === "Alpha" && item.value === "42K"));
76
+ });
77
+
78
+ test("advise CLI exits 0 and prints JSON", async () => {
79
+ const { repo, wikiRoot } = await seedAdvise();
80
+ const ran = spawnSync(process.execPath, [adviseCli, wikiRoot, "--repo", repo], { encoding: "utf8" });
81
+ assert.equal(ran.status, 0, ran.stderr);
82
+ const report = JSON.parse(ran.stdout);
83
+ assert.ok(Array.isArray(report.suspects));
84
+ });
85
+
86
+ test("concept-table.md is infrastructure and does not fail lint as an orphan", async () => {
87
+ const { repo, wikiRoot } = await seedAdvise();
88
+ const lint = await lintWiki(wikiRoot, { repoRoot: repo });
89
+ assert.equal(lint.ok, true, lint.errors.join("\n"));
90
+ assert.equal(lint.counts.articles, 2);
91
+ });
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ export const EXTRACT_KINDS = Object.freeze(["skill-names", "heading-list", "prose-note"]);
7
+
8
+ function namesOf(value) {
9
+ if (!value || typeof value !== "object" || Array.isArray(value)) return [];
10
+ return Object.keys(value).sort((a, b) => a.localeCompare(b));
11
+ }
12
+
13
+ export function extractSkillNames(lock) {
14
+ if (!lock || typeof lock !== "object" || Array.isArray(lock)) {
15
+ throw new TypeError("skill-names input must be a lock object");
16
+ }
17
+ const shared = namesOf(lock.skills?.shared);
18
+ const platform = lock.skills?.platform && typeof lock.skills.platform === "object" ? lock.skills.platform : {};
19
+ const lines = ["# skills-lock names", "", "Derived names only. Do not copy hashes, paths, or the lock file.", "", "## shared", ""];
20
+ for (const name of shared) lines.push(`- \`${name}\``);
21
+ const roots = namesOf(platform);
22
+ if (roots.length) {
23
+ lines.push("", "## platform", "");
24
+ for (const root of roots) {
25
+ lines.push(`### \`${root}\``, "");
26
+ for (const name of namesOf(platform[root])) lines.push(`- \`${name}\``);
27
+ lines.push("");
28
+ }
29
+ }
30
+ return `${lines.join("\n").replace(/\n+$/, "")}\n`;
31
+ }
32
+
33
+ async function main(argv = process.argv.slice(2)) {
34
+ const kind = argv[0];
35
+ let input;
36
+ let output;
37
+ for (let i = 1; i < argv.length; i += 1) {
38
+ if (argv[i] === "--in") input = argv[++i];
39
+ else if (argv[i] === "--out") output = argv[++i];
40
+ }
41
+ if (kind !== "skill-names" || !input || !output) {
42
+ throw new Error("usage: extract.mjs skill-names --in <lock.json> --out <raw.md>");
43
+ }
44
+ const text = extractSkillNames(JSON.parse(await readFile(input, "utf8")));
45
+ await mkdir(path.dirname(output), { recursive: true });
46
+ await writeFile(output, text, "utf8");
47
+ process.stdout.write(`${output}\n`);
48
+ }
49
+
50
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
51
+ main().catch((error) => {
52
+ process.stderr.write(`${error.message}\n`);
53
+ process.exitCode = 2;
54
+ });
55
+ }
@@ -0,0 +1,34 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { EXTRACT_KINDS, extractSkillNames } from "./extract.mjs";
4
+
5
+ test("skill-names lists shared and platform keys, sorted, without hashes", () => {
6
+ const text = extractSkillNames({
7
+ skills: {
8
+ shared: {
9
+ zeta: { effectiveHash: "aaa", skillPath: "hidden" },
10
+ alpha: { effectiveHash: "bbb" },
11
+ },
12
+ platform: {
13
+ ".codex/skills": {
14
+ "product-design": { effectiveHash: "ccc" },
15
+ "data-analytics": { effectiveHash: "ddd" },
16
+ },
17
+ },
18
+ },
19
+ });
20
+ assert.match(text, /## shared/);
21
+ assert.match(text, /## platform/);
22
+ assert.ok(text.indexOf("`alpha`") < text.indexOf("`zeta`"));
23
+ assert.ok(text.indexOf("`data-analytics`") < text.indexOf("`product-design`"));
24
+ assert.doesNotMatch(text, /aaa|bbb|ccc|ddd|skillPath|effectiveHash/);
25
+ assert.doesNotMatch(text, /"version"|canonicalRoot/);
26
+ });
27
+
28
+ test("skill-names rejects a whole-file dump of a non-object", () => {
29
+ assert.throws(() => extractSkillNames("not-json-object"), /lock object/);
30
+ });
31
+
32
+ test("declared extract kinds stay the documented set", () => {
33
+ assert.deepEqual([...EXTRACT_KINDS], ["skill-names", "heading-list", "prose-note"]);
34
+ });
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env node
2
+ import { createHash } from "node:crypto";
3
+ import { execFileSync } from "node:child_process";
4
+ import { readFile, writeFile, access } from "node:fs/promises";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ const MANIFEST = ".wiki-manifest.json";
9
+
10
+ export function sha256(buffer) {
11
+ return createHash("sha256").update(buffer).digest("hex");
12
+ }
13
+
14
+ export function resolveWikiRoot(wikiArg, cwd = process.cwd()) {
15
+ if (!wikiArg) throw new Error("missing --wiki <wiki-root>");
16
+ return path.resolve(cwd, wikiArg);
17
+ }
18
+
19
+ export function manifestPath(wikiRoot) {
20
+ return path.join(wikiRoot, MANIFEST);
21
+ }
22
+
23
+ export async function loadManifest(wikiRoot) {
24
+ const file = manifestPath(wikiRoot);
25
+ const raw = await readFile(file, "utf8");
26
+ return JSON.parse(raw);
27
+ }
28
+
29
+ export async function saveManifest(wikiRoot, manifest) {
30
+ const file = manifestPath(wikiRoot);
31
+ await writeFile(file, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
32
+ return file;
33
+ }
34
+
35
+ export async function exists(file) {
36
+ try {
37
+ await access(file);
38
+ return true;
39
+ } catch {
40
+ return false;
41
+ }
42
+ }
43
+
44
+ export function gitCommit(repoRoot) {
45
+ try {
46
+ return execFileSync("git", ["-C", repoRoot, "rev-parse", "HEAD"], {
47
+ encoding: "utf8",
48
+ stdio: ["ignore", "pipe", "ignore"],
49
+ }).trim();
50
+ } catch {
51
+ return "";
52
+ }
53
+ }
54
+
55
+ export async function hashSources({ wikiRoot, repoRoot, now = new Date().toISOString() }) {
56
+ const manifest = await loadManifest(wikiRoot);
57
+ const missing = [];
58
+ for (const source of manifest.sources || []) {
59
+ if (!source.livePath) {
60
+ source.sha256 = "";
61
+ continue;
62
+ }
63
+ const live = path.resolve(repoRoot, source.livePath);
64
+ if (!(await exists(live))) {
65
+ missing.push(source.id);
66
+ source.sha256 = "";
67
+ continue;
68
+ }
69
+ source.sha256 = sha256(await readFile(live));
70
+ }
71
+ manifest.compiledAt = now;
72
+ manifest.gitCommit = gitCommit(repoRoot);
73
+ await saveManifest(wikiRoot, manifest);
74
+ return { manifest, missing };
75
+ }
76
+
77
+ export function normalizeLivePath(livePath) {
78
+ return String(livePath || "").replace(/\\/g, "/").replace(/^\.\/+/, "");
79
+ }
80
+
81
+ export function unmappedCandidates(sources, candidates = []) {
82
+ const mapped = new Set(
83
+ (sources || []).map((source) => normalizeLivePath(source.livePath)).filter(Boolean),
84
+ );
85
+ const unmapped = [];
86
+ const seen = new Set();
87
+ for (const candidate of candidates) {
88
+ const livePath = normalizeLivePath(candidate);
89
+ if (!livePath || mapped.has(livePath) || seen.has(livePath)) continue;
90
+ seen.add(livePath);
91
+ unmapped.push(livePath);
92
+ }
93
+ return unmapped;
94
+ }
95
+
96
+ export async function drift({ wikiRoot, repoRoot, candidates = [] }) {
97
+ const manifest = await loadManifest(wikiRoot);
98
+ const changed = [];
99
+ const missing = [];
100
+ const unchanged = [];
101
+ for (const source of manifest.sources || []) {
102
+ if (!source.livePath) {
103
+ unchanged.push(source.id);
104
+ continue;
105
+ }
106
+ const live = path.resolve(repoRoot, source.livePath);
107
+ if (!(await exists(live))) {
108
+ missing.push(source.id);
109
+ continue;
110
+ }
111
+ const current = sha256(await readFile(live));
112
+ if (current !== source.sha256) changed.push(source.id);
113
+ else unchanged.push(source.id);
114
+ }
115
+ const hit = new Set([...changed, ...missing]);
116
+ const articles = [];
117
+ const humanOwned = [];
118
+ for (const article of manifest.articles || []) {
119
+ const impacted = (article.sourceIds || []).some((id) => hit.has(id));
120
+ if (!impacted) continue;
121
+ articles.push(article.id);
122
+ if (article.humanOwned === true) humanOwned.push(article.id);
123
+ }
124
+ return {
125
+ changed,
126
+ missing,
127
+ unchanged,
128
+ articles,
129
+ unmapped: unmappedCandidates(manifest.sources, candidates),
130
+ humanOwned,
131
+ };
132
+ }
133
+
134
+ function parseArgs(argv) {
135
+ const args = { command: argv[0], wiki: null, repo: process.cwd(), candidates: [] };
136
+ for (let i = 1; i < argv.length; i += 1) {
137
+ if (argv[i] === "--wiki") args.wiki = argv[++i];
138
+ else if (argv[i] === "--repo") args.repo = argv[++i];
139
+ else if (argv[i] === "--candidate") args.candidates.push(argv[++i]);
140
+ else if (!args.wiki && !argv[i].startsWith("-")) args.wiki = argv[i];
141
+ }
142
+ return args;
143
+ }
144
+
145
+ async function main(argv = process.argv.slice(2)) {
146
+ const args = parseArgs(argv);
147
+ if (!args.command || !["hash", "drift", "status"].includes(args.command)) {
148
+ throw new Error(
149
+ "usage: inventory.mjs hash|drift|status --wiki <wiki-root> [--repo <repo-root>] [--candidate <livePath>]",
150
+ );
151
+ }
152
+ const wikiRoot = resolveWikiRoot(args.wiki, args.repo);
153
+ const repoRoot = path.resolve(args.repo);
154
+ if (!(await exists(manifestPath(wikiRoot)))) {
155
+ throw new Error(`manifest not found: ${manifestPath(wikiRoot)}`);
156
+ }
157
+ if (args.command === "hash") {
158
+ const result = await hashSources({ wikiRoot, repoRoot });
159
+ process.stdout.write(
160
+ `${JSON.stringify({ hashed: (result.manifest.sources || []).length, missing: result.missing }, null, 2)}\n`,
161
+ );
162
+ if (result.missing.length) process.exitCode = 1;
163
+ return;
164
+ }
165
+ const report = await drift({ wikiRoot, repoRoot, candidates: args.candidates });
166
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
167
+ }
168
+
169
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
170
+ main().catch((error) => {
171
+ process.stderr.write(`${error.message}\n`);
172
+ process.exitCode = 2;
173
+ });
174
+ }
@@ -0,0 +1,98 @@
1
+ import assert from "node:assert/strict";
2
+ import { spawnSync } from "node:child_process";
3
+ import { mkdir, mkdtemp, writeFile } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import path from "node:path";
6
+ import test from "node:test";
7
+ import { fileURLToPath } from "node:url";
8
+ import { drift, hashSources, sha256, unmappedCandidates } from "./inventory.mjs";
9
+
10
+ const inventoryCli = fileURLToPath(new URL("./inventory.mjs", import.meta.url));
11
+
12
+ async function seed() {
13
+ const repo = await mkdtemp(path.join(tmpdir(), "llm-wiki-inv-"));
14
+ const wiki = path.join(repo, "wiki-root");
15
+ await mkdir(path.join(wiki, "raw"), { recursive: true });
16
+ const liveRel = "docs/api.md";
17
+ const live = path.join(repo, liveRel);
18
+ await mkdir(path.dirname(live), { recursive: true });
19
+ await writeFile(live, "v1\n", "utf8");
20
+ await writeFile(
21
+ path.join(wiki, ".wiki-manifest.json"),
22
+ JSON.stringify({
23
+ schemaVersion: 1,
24
+ wikiRoot: "wiki-root",
25
+ profile: "documents",
26
+ sources: [
27
+ {
28
+ id: "api.md",
29
+ kind: "document",
30
+ livePath: liveRel,
31
+ rawPath: "raw/api.md",
32
+ sha256: "",
33
+ role: "copy",
34
+ },
35
+ ],
36
+ articles: [
37
+ { id: "API契约", file: "wiki/API契约.md", sourceIds: ["api.md"], humanOwned: false },
38
+ { id: "人工页", file: "wiki/人工页.md", sourceIds: ["api.md"], humanOwned: true },
39
+ ],
40
+ }),
41
+ "utf8",
42
+ );
43
+ return { repo, wiki, live, liveRel };
44
+ }
45
+
46
+ test("hash-sources fills sha256; drift is empty until live file changes", async () => {
47
+ const { repo, wiki, live } = await seed();
48
+ const hashed = await hashSources({ wikiRoot: wiki, repoRoot: repo, now: "2026-01-01T00:00:00Z" });
49
+ assert.equal(hashed.missing.length, 0);
50
+ assert.equal(hashed.manifest.sources[0].sha256, sha256(Buffer.from("v1\n")));
51
+ const clean = await drift({ wikiRoot: wiki, repoRoot: repo });
52
+ assert.deepEqual(clean.changed, []);
53
+ assert.deepEqual(clean.articles, []);
54
+ await writeFile(live, "v2\n", "utf8");
55
+ const dirty = await drift({ wikiRoot: wiki, repoRoot: repo });
56
+ assert.deepEqual(dirty.changed, ["api.md"]);
57
+ assert.deepEqual(dirty.articles, ["API契约", "人工页"]);
58
+ assert.deepEqual(dirty.humanOwned, ["人工页"]);
59
+ assert.deepEqual(dirty.unmapped, []);
60
+ });
61
+
62
+ test("unmapped candidates are listed without scanning the tree", () => {
63
+ const sources = [{ livePath: "docs/api.md" }];
64
+ assert.deepEqual(unmappedCandidates(sources, ["docs/api.md", "docs/new.md", "./docs/new.md"]), [
65
+ "docs/new.md",
66
+ ]);
67
+ });
68
+
69
+ test("drift CLI exits 0 when sources changed and prints JSON", async () => {
70
+ const { repo, wiki, live } = await seed();
71
+ await hashSources({ wikiRoot: wiki, repoRoot: repo, now: "2026-01-01T00:00:00Z" });
72
+ await writeFile(live, "v2\n", "utf8");
73
+ const ran = spawnSync(process.execPath, [inventoryCli, "drift", "--wiki", wiki, "--repo", repo], {
74
+ encoding: "utf8",
75
+ });
76
+ assert.equal(ran.status, 0, ran.stderr);
77
+ const report = JSON.parse(ran.stdout);
78
+ assert.deepEqual(report.changed, ["api.md"]);
79
+ assert.deepEqual(report.articles, ["API契约", "人工页"]);
80
+ assert.deepEqual(report.humanOwned, ["人工页"]);
81
+ assert.deepEqual(report.unmapped, []);
82
+ });
83
+
84
+ test("status CLI exits 0 and lists unmapped candidates", async () => {
85
+ const { repo, wiki, live } = await seed();
86
+ await hashSources({ wikiRoot: wiki, repoRoot: repo, now: "2026-01-01T00:00:00Z" });
87
+ await writeFile(live, "v2\n", "utf8");
88
+ const ran = spawnSync(
89
+ process.execPath,
90
+ [inventoryCli, "status", "--wiki", wiki, "--repo", repo, "--candidate", "docs/extra.md"],
91
+ { encoding: "utf8" },
92
+ );
93
+ assert.equal(ran.status, 0, ran.stderr);
94
+ const report = JSON.parse(ran.stdout);
95
+ assert.deepEqual(report.changed, ["api.md"]);
96
+ assert.deepEqual(report.unmapped, ["docs/extra.md"]);
97
+ assert.deepEqual(report.humanOwned, ["人工页"]);
98
+ });