@kanyun-ai-infra/band-cli 0.0.0-stage → 0.1.0

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 (306) hide show
  1. package/README.md +11 -2
  2. package/bundled/examples/aitutor-tool/band/agent/instructions.md +12 -0
  3. package/bundled/examples/aitutor-tool/band/agent/stages/backfill.md +3 -0
  4. package/bundled/examples/aitutor-tool/band/agent/stages/engineering.md +3 -0
  5. package/bundled/examples/aitutor-tool/band/agent/stages/spec.md +5 -0
  6. package/bundled/examples/aitutor-tool/band/agent/stages/strategy.md +10 -0
  7. package/bundled/examples/aitutor-tool/band/dev/fixture.ts +500 -0
  8. package/bundled/examples/aitutor-tool/band/dev/resources.ts +40 -0
  9. package/bundled/examples/aitutor-tool/band/dev/tool-bundle.ts +201 -0
  10. package/bundled/examples/aitutor-tool/band/jobs/publish.mjs +4 -0
  11. package/bundled/examples/aitutor-tool/band/params/publish.schema.json +15 -0
  12. package/bundled/examples/aitutor-tool/band/views/release/index.ts +147 -0
  13. package/bundled/examples/aitutor-tool/band/views/release/package.json +11 -0
  14. package/bundled/examples/aitutor-tool/band/views/release/plugin.yaml +11 -0
  15. package/bundled/examples/aitutor-tool/band/views/tool-preview/host-page.ts +183 -0
  16. package/bundled/examples/aitutor-tool/band/views/tool-preview/index.ts +738 -0
  17. package/bundled/examples/aitutor-tool/band/views/tool-preview/model.ts +177 -0
  18. package/bundled/examples/aitutor-tool/band/views/tool-preview/package.json +11 -0
  19. package/bundled/examples/aitutor-tool/band/views/tool-preview/plugin.yaml +11 -0
  20. package/bundled/examples/aitutor-tool/band/workshop.yaml +99 -0
  21. package/bundled/examples/analysis/band/agent/instructions.md +25 -0
  22. package/bundled/examples/analysis/band/agent/stages/query.md +8 -0
  23. package/bundled/examples/analysis/band/agent/stages/report.md +17 -0
  24. package/bundled/examples/analysis/band/agent/stages/scope.md +10 -0
  25. package/bundled/examples/analysis/band/dev/fixture.ts +161 -0
  26. package/bundled/examples/analysis/band/params/intake.schema.json +17 -0
  27. package/bundled/examples/analysis/band/views/intake/index.ts +201 -0
  28. package/bundled/examples/analysis/band/views/intake/package.json +11 -0
  29. package/bundled/examples/analysis/band/views/intake/plugin.yaml +12 -0
  30. package/bundled/examples/analysis/band/views/intake/sample-data.ts +149 -0
  31. package/bundled/examples/analysis/band/workshop.yaml +63 -0
  32. package/bundled/examples/compliance/band/dev/fixture.ts +117 -0
  33. package/bundled/examples/compliance/band/views/compliance/index.ts +268 -0
  34. package/bundled/examples/compliance/band/views/compliance/package.json +11 -0
  35. package/bundled/examples/compliance/band/views/compliance/plugin.yaml +8 -0
  36. package/bundled/examples/compliance/band/views/compliance/rules.ts +74 -0
  37. package/bundled/examples/compliance/band/workshop.yaml +29 -0
  38. package/bundled/examples/content-review/band/agent/instructions.md +32 -0
  39. package/bundled/examples/content-review/band/agent/skills/content-review-guide/SKILL.md +52 -0
  40. package/bundled/examples/content-review/band/agent/skills/content-review-variants/SKILL.md +15 -0
  41. package/bundled/examples/content-review/band/agent/skills/content-review-variants/exam.md +7 -0
  42. package/bundled/examples/content-review/band/agent/skills/content-review-variants/lesson-plan.md +6 -0
  43. package/bundled/examples/content-review/band/agent/skills/content-review-variants/manual.md +6 -0
  44. package/bundled/examples/content-review/band/agent/skills/content-review-variants/reader.md +6 -0
  45. package/bundled/examples/content-review/band/agent/stages/revise.md +8 -0
  46. package/bundled/examples/content-review/band/agent/stages/scan.md +16 -0
  47. package/bundled/examples/content-review/band/dev/fixture.ts +202 -0
  48. package/bundled/examples/content-review/band/dev/samples.ts +61 -0
  49. package/bundled/examples/content-review/band/params/intake.schema.json +20 -0
  50. package/bundled/examples/content-review/band/views/checklist/index.ts +464 -0
  51. package/bundled/examples/content-review/band/views/checklist/package.json +11 -0
  52. package/bundled/examples/content-review/band/views/checklist/plugin.yaml +17 -0
  53. package/bundled/examples/content-review/band/views/checklist/rules.ts +127 -0
  54. package/bundled/examples/content-review/band/views/checklist/variants/exam.ts +54 -0
  55. package/bundled/examples/content-review/band/views/checklist/variants/lesson-plan.ts +27 -0
  56. package/bundled/examples/content-review/band/views/checklist/variants/manual.ts +37 -0
  57. package/bundled/examples/content-review/band/views/checklist/variants/reader.ts +27 -0
  58. package/bundled/examples/content-review/band/views/checklist/variants/types.ts +27 -0
  59. package/bundled/examples/content-review/band/workshop.yaml +59 -0
  60. package/bundled/examples/doc-writing/band/agent/instructions.md +27 -0
  61. package/bundled/examples/doc-writing/band/agent/skills/doc-writing-guide/SKILL.md +24 -0
  62. package/bundled/examples/doc-writing/band/agent/stages/draft.md +9 -0
  63. package/bundled/examples/doc-writing/band/agent/stages/revise.md +8 -0
  64. package/bundled/examples/doc-writing/band/dev/fixture.ts +198 -0
  65. package/bundled/examples/doc-writing/band/params/brief.schema.json +30 -0
  66. package/bundled/examples/doc-writing/band/workshop.yaml +52 -0
  67. package/bundled/examples/illustration/band/dev/concept-dawn.jpg +0 -0
  68. package/bundled/examples/illustration/band/dev/concept-night.jpg +0 -0
  69. package/bundled/examples/illustration/band/dev/concept-noon.jpg +0 -0
  70. package/bundled/examples/illustration/band/dev/cover-1.jpg +0 -0
  71. package/bundled/examples/illustration/band/dev/cover-2.jpg +0 -0
  72. package/bundled/examples/illustration/band/dev/fixture.ts +169 -0
  73. package/bundled/examples/illustration/band/dev/sketch.jpg +0 -0
  74. package/bundled/examples/illustration/band/workshop.yaml +31 -0
  75. package/bundled/examples/rush-site/band/dev/fixture.ts +197 -0
  76. package/bundled/examples/rush-site/band/dev/resources.ts +110 -0
  77. package/bundled/examples/rush-site/band/jobs/deploy.mjs +3 -0
  78. package/bundled/examples/rush-site/band/params/deploy.schema.json +23 -0
  79. package/bundled/examples/rush-site/band/views/rush-db/index.ts +281 -0
  80. package/bundled/examples/rush-site/band/views/rush-db/package.json +17 -0
  81. package/bundled/examples/rush-site/band/views/rush-db/plugin.yaml +19 -0
  82. package/bundled/examples/rush-site/band/views/rush-deploy/index.ts +445 -0
  83. package/bundled/examples/rush-site/band/views/rush-deploy/package.json +11 -0
  84. package/bundled/examples/rush-site/band/views/rush-deploy/plugin.yaml +11 -0
  85. package/bundled/examples/rush-site/band/workshop.yaml +41 -0
  86. package/bundled/examples/video/band/agent/stages/render.md +16 -0
  87. package/bundled/examples/video/band/agent/stages/script.md +10 -0
  88. package/bundled/examples/video/band/agent/stages/storyboard.md +24 -0
  89. package/bundled/examples/video/band/dev/cut-2.webm +0 -0
  90. package/bundled/examples/video/band/dev/cut.webm +0 -0
  91. package/bundled/examples/video/band/dev/fixture.ts +205 -0
  92. package/bundled/examples/video/band/dev/li.png +0 -0
  93. package/bundled/examples/video/band/dev/vo.ogg +0 -0
  94. package/bundled/examples/video/band/views/shots.ts +54 -0
  95. package/bundled/examples/video/band/views/timeline/index.ts +112 -0
  96. package/bundled/examples/video/band/views/timeline/package.json +11 -0
  97. package/bundled/examples/video/band/views/timeline/plugin.yaml +6 -0
  98. package/bundled/examples/video/band/workshop.yaml +66 -0
  99. package/bundled/examples/visual/band/agent/instructions.md +34 -0
  100. package/bundled/examples/visual/band/agent/skills/visual-guide/SKILL.md +19 -0
  101. package/bundled/examples/visual/band/agent/skills/visual-layouts/SKILL.md +24 -0
  102. package/bundled/examples/visual/band/agent/skills/visual-layouts/templates/infographic.html +17 -0
  103. package/bundled/examples/visual/band/agent/skills/visual-layouts/templates/poster.html +15 -0
  104. package/bundled/examples/visual/band/agent/skills/visual-layouts/templates/ppt.html +16 -0
  105. package/bundled/examples/visual/band/agent/stages/draft.md +18 -0
  106. package/bundled/examples/visual/band/agent/stages/pack.md +26 -0
  107. package/bundled/examples/visual/band/agent/stages/refine.md +9 -0
  108. package/bundled/examples/visual/band/dev/fixture.ts +229 -0
  109. package/bundled/examples/visual/band/params/brief.schema.json +30 -0
  110. package/bundled/examples/visual/band/workshop.yaml +60 -0
  111. package/bundled/examples/web-page/band/agent/instructions.md +41 -0
  112. package/bundled/examples/web-page/band/agent/skills/web-page-guide/SKILL.md +38 -0
  113. package/bundled/examples/web-page/band/agent/stages/make.md +12 -0
  114. package/bundled/examples/web-page/band/dev/fixture.ts +131 -0
  115. package/bundled/examples/web-page/band/workshop.yaml +35 -0
  116. package/bundled/kernel/fixture.js +1 -0
  117. package/bundled/kernel/index.js +1 -0
  118. package/bundled/kernel/kernel.css +165 -0
  119. package/bundled/official/activity/dist/index.js +1 -0
  120. package/bundled/official/activity/package.json +15 -0
  121. package/bundled/official/activity/plugin.yaml +6 -0
  122. package/bundled/official/approval/dist/index.js +1 -0
  123. package/bundled/official/approval/package.json +15 -0
  124. package/bundled/official/approval/plugin.yaml +6 -0
  125. package/bundled/official/artifacts/dist/index.js +1 -0
  126. package/bundled/official/artifacts/package.json +15 -0
  127. package/bundled/official/artifacts/plugin.yaml +21 -0
  128. package/bundled/official/band.profiles.yaml +10 -0
  129. package/bundled/official/chat/dist/index.js +1 -0
  130. package/bundled/official/chat/package.json +15 -0
  131. package/bundled/official/chat/plugin.yaml +6 -0
  132. package/bundled/official/chunks/c-67VUENUQ.js +1 -0
  133. package/bundled/official/chunks/chunk-3V3JRXAQ.js +1 -0
  134. package/bundled/official/chunks/chunk-56PO7I4U.js +2 -0
  135. package/bundled/official/chunks/chunk-5DRIG2M4.js +1 -0
  136. package/bundled/official/chunks/chunk-AYEPQBDC.js +1 -0
  137. package/bundled/official/chunks/chunk-CKWPKYHU.js +1 -0
  138. package/bundled/official/chunks/chunk-DK64JRQO.js +1 -0
  139. package/bundled/official/chunks/chunk-DTW5OO3F.js +1 -0
  140. package/bundled/official/chunks/chunk-EY65A4JR.js +1 -0
  141. package/bundled/official/chunks/chunk-GBH4NY2K.js +1 -0
  142. package/bundled/official/chunks/chunk-GZVWJ5MP.js +1 -0
  143. package/bundled/official/chunks/chunk-HZZ2FUCQ.js +1 -0
  144. package/bundled/official/chunks/chunk-JFPQMFKF.js +1 -0
  145. package/bundled/official/chunks/chunk-JI6ZNGOE.js +1 -0
  146. package/bundled/official/chunks/chunk-LHIEW7ZT.js +1 -0
  147. package/bundled/official/chunks/chunk-N6N56MWF.js +1 -0
  148. package/bundled/official/chunks/chunk-NGLQNSBH.js +1 -0
  149. package/bundled/official/chunks/chunk-NUFRM6SI.js +0 -0
  150. package/bundled/official/chunks/chunk-O5HVOIC4.js +1 -0
  151. package/bundled/official/chunks/chunk-OBPNVP4S.js +88 -0
  152. package/bundled/official/chunks/chunk-PSLWCPAE.js +139 -0
  153. package/bundled/official/chunks/chunk-TWQQ2CCT.js +1 -0
  154. package/bundled/official/chunks/chunk-TWS74FML.js +1 -0
  155. package/bundled/official/chunks/chunk-VL7UVRSN.js +1 -0
  156. package/bundled/official/chunks/chunk-VPF6VRIC.js +1 -0
  157. package/bundled/official/chunks/chunk-Z47EOZYW.js +1 -0
  158. package/bundled/official/chunks/chunk-ZQBKXVFT.js +1 -0
  159. package/bundled/official/chunks/cpp-KHELUZ24.js +1 -0
  160. package/bundled/official/chunks/csharp-NVIMI5QZ.js +1 -0
  161. package/bundled/official/chunks/css-GBIZVTSQ.js +1 -0
  162. package/bundled/official/chunks/diff-YYYHQ6TV.js +1 -0
  163. package/bundled/official/chunks/dockerfile-ERGBWYZB.js +1 -0
  164. package/bundled/official/chunks/dotenv-VSILHLF2.js +1 -0
  165. package/bundled/official/chunks/go-PAZVXFEC.js +1 -0
  166. package/bundled/official/chunks/graphql-FATFQ6IO.js +1 -0
  167. package/bundled/official/chunks/html-6TMDETJ7.js +1 -0
  168. package/bundled/official/chunks/ini-LAQL4BNQ.js +1 -0
  169. package/bundled/official/chunks/java-DWLFUFNZ.js +1 -0
  170. package/bundled/official/chunks/javascript-UVXV4LH3.js +1 -0
  171. package/bundled/official/chunks/json-2XC65KYC.js +1 -0
  172. package/bundled/official/chunks/jsx-5I35UFYY.js +1 -0
  173. package/bundled/official/chunks/kotlin-5JRS2Y56.js +1 -0
  174. package/bundled/official/chunks/make-CDBZHRX5.js +1 -0
  175. package/bundled/official/chunks/markdown-DE5SI3PT.js +1 -0
  176. package/bundled/official/chunks/php-BJ2OQ7YC.js +1 -0
  177. package/bundled/official/chunks/python-D4KWGJEP.js +1 -0
  178. package/bundled/official/chunks/ruby-R6E5QHMT.js +1 -0
  179. package/bundled/official/chunks/rust-3WT5W4OK.js +1 -0
  180. package/bundled/official/chunks/scss-Q3LNFLO3.js +1 -0
  181. package/bundled/official/chunks/shellscript-A6FRVMCN.js +1 -0
  182. package/bundled/official/chunks/shellsession-D7BY6YDO.js +1 -0
  183. package/bundled/official/chunks/sql-Y6GNM3QQ.js +1 -0
  184. package/bundled/official/chunks/swift-WXOACTZS.js +1 -0
  185. package/bundled/official/chunks/toml-FEEEOEB3.js +1 -0
  186. package/bundled/official/chunks/tsx-EDWPMJ6D.js +1 -0
  187. package/bundled/official/chunks/typescript-KL7ZFXF4.js +1 -0
  188. package/bundled/official/chunks/vue-KN7U54VZ.js +1 -0
  189. package/bundled/official/chunks/xml-VCN5P46E.js +1 -0
  190. package/bundled/official/chunks/yaml-3DO32XY4.js +1 -0
  191. package/bundled/official/comment/dist/index.js +4 -0
  192. package/bundled/official/comment/package.json +21 -0
  193. package/bundled/official/comment/plugin.yaml +27 -0
  194. package/bundled/official/header/dist/index.js +1 -0
  195. package/bundled/official/header/package.json +15 -0
  196. package/bundled/official/header/plugin.yaml +9 -0
  197. package/bundled/official/home/dist/index.js +1 -0
  198. package/bundled/official/home/package.json +15 -0
  199. package/bundled/official/home/plugin.yaml +12 -0
  200. package/bundled/official/layouts/dist/index.js +1 -0
  201. package/bundled/official/layouts/package.json +15 -0
  202. package/bundled/official/layouts/plugin.yaml +29 -0
  203. package/bundled/official/library/dist/index.js +1 -0
  204. package/bundled/official/library/package.json +16 -0
  205. package/bundled/official/library/plugin.yaml +38 -0
  206. package/bundled/official/members/dist/index.js +1 -0
  207. package/bundled/official/members/package.json +16 -0
  208. package/bundled/official/members/plugin.yaml +13 -0
  209. package/bundled/official/memory/dist/index.js +3 -0
  210. package/bundled/official/memory/package.json +15 -0
  211. package/bundled/official/memory/plugin.yaml +10 -0
  212. package/bundled/official/native/dist/index.js +1 -0
  213. package/bundled/official/native/package.json +12 -0
  214. package/bundled/official/native/plugin.yaml +6 -0
  215. package/bundled/official/params-form/dist/index.js +1 -0
  216. package/bundled/official/params-form/package.json +15 -0
  217. package/bundled/official/params-form/plugin.yaml +12 -0
  218. package/bundled/official/plugins/dist/index.js +3 -0
  219. package/bundled/official/plugins/package.json +15 -0
  220. package/bundled/official/plugins/plugin.yaml +19 -0
  221. package/bundled/official/project/dist/index.js +1 -0
  222. package/bundled/official/project/package.json +15 -0
  223. package/bundled/official/project/plugin.yaml +140 -0
  224. package/bundled/official/queue/dist/index.js +1 -0
  225. package/bundled/official/queue/package.json +15 -0
  226. package/bundled/official/queue/plugin.yaml +5 -0
  227. package/bundled/official/settings/dist/index.js +1 -0
  228. package/bundled/official/settings/package.json +16 -0
  229. package/bundled/official/settings/plugin.yaml +150 -0
  230. package/bundled/official/shell/dist/index.js +1 -0
  231. package/bundled/official/shell/package.json +14 -0
  232. package/bundled/official/shell/plugin.yaml +43 -0
  233. package/bundled/official/stages/dist/index.js +1 -0
  234. package/bundled/official/stages/package.json +15 -0
  235. package/bundled/official/stages/plugin.yaml +17 -0
  236. package/bundled/official/threads/dist/index.js +1 -0
  237. package/bundled/official/threads/package.json +15 -0
  238. package/bundled/official/threads/plugin.yaml +26 -0
  239. package/bundled/official/turn-bar/dist/index.js +1 -0
  240. package/bundled/official/turn-bar/package.json +15 -0
  241. package/bundled/official/turn-bar/plugin.yaml +6 -0
  242. package/bundled/official/turn-trace/dist/index.js +1 -0
  243. package/bundled/official/turn-trace/package.json +15 -0
  244. package/bundled/official/turn-trace/plugin.yaml +6 -0
  245. package/bundled/official/version-switch/dist/index.js +1 -0
  246. package/bundled/official/version-switch/package.json +15 -0
  247. package/bundled/official/version-switch/plugin.yaml +12 -0
  248. package/bundled/official/viewer-entity/index.js +38 -0
  249. package/bundled/official/viewer-entity/package.json +13 -0
  250. package/bundled/official/viewer-entity/plugin.yaml +20 -0
  251. package/bundled/official/viewer-external/index.js +49 -0
  252. package/bundled/official/viewer-external/package.json +13 -0
  253. package/bundled/official/viewer-external/plugin.yaml +6 -0
  254. package/bundled/official/viewer-image/index.js +45 -0
  255. package/bundled/official/viewer-image/package.json +19 -0
  256. package/bundled/official/viewer-image/plugin.yaml +20 -0
  257. package/bundled/official/viewer-media/index.js +326 -0
  258. package/bundled/official/viewer-media/package.json +19 -0
  259. package/bundled/official/viewer-media/plugin.yaml +32 -0
  260. package/bundled/official/viewer-storyboard/index.js +95 -0
  261. package/bundled/official/viewer-storyboard/package.json +27 -0
  262. package/bundled/official/viewer-storyboard/plugin.yaml +19 -0
  263. package/bundled/official/viewer-text/dist/index.js +2 -0
  264. package/bundled/official/viewer-text/package.json +15 -0
  265. package/bundled/official/viewer-text/plugin.yaml +25 -0
  266. package/bundled/official/viewer-tool/index.js +183 -0
  267. package/bundled/official/viewer-tool/package.json +13 -0
  268. package/bundled/official/viewer-tool/plugin.yaml +9 -0
  269. package/bundled/official/viewer-web/dist/index.js +1 -0
  270. package/bundled/official/viewer-web/package.json +13 -0
  271. package/bundled/official/viewer-web/plugin.yaml +27 -0
  272. package/bundled/official/viewer-web-app/index.js +164 -0
  273. package/bundled/official/viewer-web-app/package.json +13 -0
  274. package/bundled/official/viewer-web-app/plugin.yaml +8 -0
  275. package/bundled/official/workshops/dist/index.js +24 -0
  276. package/bundled/official/workshops/package.json +15 -0
  277. package/bundled/official/workshops/plugin.yaml +61 -0
  278. package/bundled/skills/band-plugin/SKILL.md +289 -0
  279. package/bundled/tokens/components.css +386 -0
  280. package/bundled/tokens/tokens.css +128 -0
  281. package/dev-host/Inspector.tsx +140 -0
  282. package/dev-host/app.tsx +362 -0
  283. package/dev-host/host.css +193 -0
  284. package/dev-host/index.html +12 -0
  285. package/dev-host/main.tsx +33 -0
  286. package/dist/bin.d.ts +1 -0
  287. package/dist/bin.js +10 -0
  288. package/dist/build-plugin.d.ts +48 -0
  289. package/dist/build-plugin.js +263 -0
  290. package/dist/chunk-CL3FV65M.js +101 -0
  291. package/dist/chunk-I2WGLXTV.js +13 -0
  292. package/dist/chunk-RAD6MMSL.js +246 -0
  293. package/dist/chunk-TN7Z3OF6.js +2292 -0
  294. package/dist/chunk-VVJNG5GV.js +2020 -0
  295. package/dist/dev-server-RAZQ32W7.js +272 -0
  296. package/dist/fixture.d.ts +94 -0
  297. package/dist/fixture.js +0 -0
  298. package/dist/index.d.ts +144 -0
  299. package/dist/index.js +59 -0
  300. package/dist/plugin-entry.d.ts +37 -0
  301. package/dist/plugin-entry.js +10 -0
  302. package/dist/vite.d.ts +32 -0
  303. package/dist/vite.js +108 -0
  304. package/dist/workshop-repo-CO6YMDee.d.ts +714 -0
  305. package/package.json +61 -4
  306. package/src/load-plugins.ts +61 -0
package/README.md CHANGED
@@ -1,3 +1,12 @@
1
- # Temporary Holding Version
1
+ # @kanyun-ai-infra/band-cli
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ `band`:写 Band 工坊和插件用的命令行。新建工坊与插件、`band dev` 本地起项目页调试、`band check` 校验、`band preview` / `band publish` 预览与发布工坊。
4
+
5
+ ```bash
6
+ npm install -g @kanyun-ai-infra/band-cli
7
+ band --help
8
+ band new workshop ~/my-workshop --example video
9
+ band dev ~/my-workshop
10
+ ```
11
+
12
+ 要 Node 22.19 以上。官方插件、示例工坊和给 Claude Code 用的 `band-plugin` skill 随包安装,版本跟着命令行走。用法见 Band 用户文档的「快速开始」与「band 命令行」两页。
@@ -0,0 +1,12 @@
1
+ # 教具工坊说明
2
+
3
+ 这个工坊生产 1v1 课堂教具:一次迭代把一个教具从需求走到能过验收的新版本。流程是 规格 → 策略 → 研发 → 自动检查 → 验收 → 发布 → 回填;回合输入的 `stage` 说明当前在哪一步,开工前先读本阶段说明(`.agent/workshop/stages/<阶段>.md`)。
4
+
5
+ ## 按仓库里的 skill 干活
6
+
7
+ 规格、策略、工程的具体模板和检查项在教具仓库自带的 skill 里(`develop-tool-strategy`、`develop-tool-engineering`)。仓库里没有对应 skill 时,停下来在回执里说明缺什么,不自己发明格式。
8
+
9
+ ## 处理意见
10
+
11
+ - 意见挂在教具元素上时,锚点带源码戳(`src`,形如 `src/renderer/Tree.vue:6`):先看那一行再改。
12
+ - 只改意见要的东西。对外指令有增删改时,同步更新变更声明(`变更声明.json`),备课侧靠它判断要不要迁移。
@@ -0,0 +1,3 @@
1
+ # 回填阶段
2
+
3
+ 本阶段挂内容仓库:把发布版本装进专题,照内容仓库的 `refresh-teaching-tools`——装到 `产出/assets/teaching-tools/<教具>/<版本>/`,登记进专题的 componentRegistry。专题里已有别的版本时,迁移要老师确认(本阶段门禁由教研批准),不悄悄改专题。
@@ -0,0 +1,3 @@
1
+ # 研发阶段
2
+
3
+ 按指令集写 Model 与 Renderer 源码,构建出 bundle,照 `develop-tool-engineering`。bundle 是构建产物(不进仓库,直接交 store 产物):IIFE 构建包、`manifest.json`、场景用例 `cases/*.json` —— 把配置说明里的示例场景转成用例放进去,格式是 `initData` 加逐步指令。评审用的预览只读这一版的文件,意见都落在它上面。
@@ -0,0 +1,5 @@
1
+ # 规格阶段(Gate R2)
2
+
3
+ 本阶段只写规格:实体、交互、状态模型、设计契约,照教具仓库 `_spec/` 的模板与 `develop-tool-strategy` 的第一段。写完就停,在回执里说明规格在哪:规格要过 Gate R2(教研与研发都批准),批准前不写指令集和代码。
4
+
5
+ 规格里带「验收看什么」一节,写要人判断的(设计判断、生命周期与体量、操作、与板书共存);能自动查的(入口体量、资源声明、E2E、性能、设计规范)归检查阶段,不写给人看。
@@ -0,0 +1,10 @@
1
+ # 策略阶段
2
+
3
+ 按批准的规格写四份文档,照 `develop-tool-strategy` 的第二段:
4
+
5
+ - 原子指令集(对外 API 契约,一条指令一件事,参数与错误码写全);
6
+ - 使用手册(给备课 Agent 读);
7
+ - 配置说明(工程配置与模型上下文的 schema,至少两个示例场景);
8
+ - 变更声明(对外指令相对上一版的增删改)。
9
+
10
+ 指令集是备课与课件的依赖,改动要在变更声明里看得出来。
@@ -0,0 +1,500 @@
1
+ /**
2
+ * `band dev` 用的教具夹具:一个教具「植树问题线段图」的一次迭代,走到验收。
3
+ * - 需求单是 GitLab Issue 的快照(外部产物),规格、指令集、使用手册、配置说明、变更声明、源码是 git 产物,
4
+ * 构建产物(bundle)两版:1.0.3 的棵数编号压在段长标注上,设计在预览里点了那个数字提意见,Rondo 改出 1.0.4。
5
+ * - 验收阶段:#1 已改好、设计确认过;#2、#3 还开着,所以教研和设计都还没批,发布阶段等验收。
6
+ * 所有内容都是为示例写的,不是业务仓库里的文件;教具源码见 tool-bundle.ts。当前成员是教研。
7
+ */
8
+ import type { FixtureData } from "@kanyun-ai-infra/band-kernel/fixture";
9
+ import type { Comment, ThreadView, Version } from "@kanyun-ai-infra/band-plugin-sdk";
10
+ import { bundleFiles } from "./tool-bundle.ts";
11
+
12
+ const PROJECT = "prj_tree_line";
13
+ const RUN = "run_tree_line_2";
14
+ const EXTERNAL = "application/vnd.band.external+json";
15
+
16
+ type Entry = Version["entries"][number];
17
+
18
+ const entry = (
19
+ path: string,
20
+ c: string,
21
+ mime: string,
22
+ storage: Entry["storage"] = "git",
23
+ ): Entry => ({
24
+ path,
25
+ sha256: c.repeat(64),
26
+ size: 800,
27
+ mime,
28
+ storage,
29
+ ref: storage === "git" ? `c${c}` : `store:${c}`,
30
+ });
31
+
32
+ const version = (
33
+ id: string,
34
+ artifactId: string,
35
+ c: string,
36
+ at: string,
37
+ label: string,
38
+ entries: Entry[],
39
+ author: Version["author"] = { kind: "agent", id: "rondo" },
40
+ ): Version => ({
41
+ id,
42
+ artifactId,
43
+ meta: { label },
44
+ hash: c.repeat(64),
45
+ entries,
46
+ provenance: [{ inputs: [], at }],
47
+ author,
48
+ createdAt: at,
49
+ });
50
+
51
+ const mimeOf = (path: string) =>
52
+ path.endsWith(".json")
53
+ ? "application/json"
54
+ : path.endsWith(".js")
55
+ ? "text/javascript"
56
+ : path.endsWith(".md")
57
+ ? "text/markdown"
58
+ : path.endsWith(".yaml")
59
+ ? "application/yaml"
60
+ : "text/plain";
61
+
62
+ const bundle = (id: string, c: string, at: string, v: "1.0.3" | "1.0.4") => {
63
+ const files = bundleFiles(v);
64
+ return {
65
+ version: version(
66
+ id,
67
+ "art_bundle",
68
+ c,
69
+ at,
70
+ `v${v}`,
71
+ Object.keys(files).map((p) => entry(p, c, mimeOf(p), "store")),
72
+ ),
73
+ files,
74
+ };
75
+ };
76
+
77
+ const REQUIREMENT = JSON.stringify({
78
+ source: {
79
+ platform: "gitlab-issue",
80
+ url: "https://gitlab.example.com/aitutor/teaching-tools/-/issues/218",
81
+ title: "【需求】植树问题线段图(三年级 · 植树问题)",
82
+ fetchedAt: "2026-10-19T02:00:00Z",
83
+ },
84
+ blocks: [
85
+ { id: "h1", kind: "heading", text: "植树问题线段图" },
86
+ { id: "p1", kind: "paragraph", text: "课程:三年级 · 植树问题。优先级:P1。" },
87
+ {
88
+ id: "p2",
89
+ kind: "paragraph",
90
+ text: "老师边讲边在线段上分段、种树,学生看清「段数」和「棵数」的关系:两端都种、两端都不种、只种一端三种情况。",
91
+ },
92
+ { id: "l1", kind: "list-item", text: "老师能指定全长和间隔,间隔除不尽时要提示" },
93
+ { id: "l2", kind: "list-item", text: "能高亮某一段,讲「一段对应一棵树」" },
94
+ { id: "l3", kind: "list-item", text: "整行占位,放在例题下面" },
95
+ ],
96
+ });
97
+
98
+ const SPEC = `# 植树问题线段图 · 规格
99
+
100
+ ## 实体
101
+ - 线段:全长(整数,单位随初始数据)
102
+ - 段:由间隔切出,间隔必须整除全长
103
+ - 树:按端点规则种在分点上,带编号
104
+
105
+ ## 交互
106
+ - 老师一句话对应一条指令;分段、种树、高亮分开下发
107
+
108
+ ## 状态
109
+ \`{ total_length, interval_length, ends, trees, highlighted }\`,每条指令后提交一次
110
+
111
+ ## 设计契约
112
+ - 颜色全部取宿主下发的设计变量,深色下可读
113
+ - 编号、标注互不重叠
114
+
115
+ ## 验收看什么
116
+ 验收人在教具预览里把场景用例都跑一遍,有问题直接在那一步或那个元素上标注;意见都确认后再批准。
117
+ - 讲的是板书讲不清的点,一个教具只服务一个知识点
118
+ - 同一份初始数据重进得到同样画面,回退一步不残留状态
119
+ - 老师一句话最多两条指令,指令名能读懂,非法参数报出可读的错误码
120
+ - 占位与清单声明一致,文字不压线、不重叠,深色下可读
121
+ - 入口体量、资源声明、E2E 由自动检查阶段覆盖(业务 CI 里要有对应检查),不用人再看
122
+ `;
123
+
124
+ const INSTRUCTIONS = `# 原子指令集(对外契约)
125
+ show:
126
+ attrs: { total_length: { type: integer, min: 1 } }
127
+ mark_intervals:
128
+ attrs: { interval_length: { type: integer, min: 1 } }
129
+ errors: [NOT_SHOWN, INTERVAL_NOT_DIVISIBLE]
130
+ plant_trees:
131
+ attrs: { ends: { enum: [both, none, one] } }
132
+ errors: [NO_INTERVALS]
133
+ highlight_segment:
134
+ attrs: { index: { type: integer, min: 0 } }
135
+ `;
136
+
137
+ const MANUAL = `# 植树问题线段图 · 使用手册
138
+
139
+ 给备课 Agent 读。
140
+
141
+ 1. 先 \`show\` 出全长,再 \`mark_intervals\` 分段,最后 \`plant_trees\`。
142
+ 2. 讲「一段对应一棵树」时用 \`highlight_segment\`,一次只高亮一段。
143
+ 3. 间隔要能整除全长,否则教具报 \`INTERVAL_NOT_DIVISIBLE\`,课件里不要出现这种组合。
144
+ `;
145
+
146
+ const CONFIG = `# 配置说明
147
+
148
+ - initData.title:线段上方的题目
149
+ - initData.unit:长度单位,默认「米」
150
+
151
+ 示例场景见构建产物的 cases/:两端都种、两端都不种。
152
+ `;
153
+
154
+ const CHANGE_DECL = `${JSON.stringify(
155
+ {
156
+ version: "1.0.4",
157
+ previous: "1.0.3",
158
+ instructions: { added: [], removed: [], changed: [] },
159
+ notes: "只改渲染:棵数编号挪到树上方,指令不变,备课侧无需迁移",
160
+ },
161
+ null,
162
+ 2,
163
+ )}\n`;
164
+
165
+ const TREE_SRC = `<template>
166
+ <g :data-tool-id="'tree-' + n">
167
+ <rect class="trunk" />
168
+ <circle class="crown" />
169
+ <text :y="NUMBER_Y" class="no">{{ n }}</text>
170
+ </g>
171
+ </template>
172
+ `;
173
+
174
+ const b1 = bundle("ver_bundle_1", "3", "2026-10-21T06:10:00.000Z", "1.0.3");
175
+ const b2 = bundle("ver_bundle_2", "4", "2026-10-22T03:30:00.000Z", "1.0.4");
176
+
177
+ const human = (id: string) => ({ kind: "human" as const, id });
178
+
179
+ const thread = (
180
+ id: string,
181
+ mark: number,
182
+ at: string,
183
+ status: ThreadView["status"],
184
+ by: string,
185
+ anchor: ThreadView["anchor"],
186
+ excerpt: string,
187
+ ): ThreadView => ({
188
+ id,
189
+ projectId: PROJECT,
190
+ runId: RUN,
191
+ artifactId: "art_bundle",
192
+ anchorId: anchor.id,
193
+ mark,
194
+ status,
195
+ createdBy: human(by),
196
+ createdAt: at,
197
+ updatedAt: at,
198
+ anchor,
199
+ excerpt,
200
+ });
201
+
202
+ const comment = (
203
+ id: string,
204
+ threadId: string,
205
+ at: string,
206
+ by: string,
207
+ body: string,
208
+ receipt?: Comment["receipt"],
209
+ ): Comment => ({
210
+ id,
211
+ threadId,
212
+ kind: receipt ? "receipt" : "comment",
213
+ author: receipt ? { kind: "agent", id: "rondo" } : human(by),
214
+ body,
215
+ mentions: [],
216
+ ...(receipt ? { receipt } : {}),
217
+ createdAt: at,
218
+ });
219
+
220
+ export const fixture: FixtureData = {
221
+ projectId: PROJECT,
222
+ runId: RUN,
223
+ versions: [
224
+ version(
225
+ "ver_req_1",
226
+ "art_req",
227
+ "1",
228
+ "2026-10-19T02:00:00.000Z",
229
+ "#218",
230
+ [
231
+ {
232
+ ...entry("issue.json", "1", EXTERNAL, "external"),
233
+ ref: "gitlab-issue:aitutor/teaching-tools#218",
234
+ sourceRevision: "2026-10-19T02:00:00Z",
235
+ },
236
+ ],
237
+ human("liuyan"),
238
+ ),
239
+ version("ver_spec_1", "art_spec", "2", "2026-10-19T08:00:00.000Z", "v1", [
240
+ entry("_spec/tree-planting-line-spec.md", "2", "text/markdown"),
241
+ ]),
242
+ version("ver_instr_1", "art_instr", "5", "2026-10-20T03:00:00.000Z", "v1", [
243
+ entry("原子指令集.yaml", "5", "application/yaml"),
244
+ ]),
245
+ version("ver_manual_1", "art_manual", "6", "2026-10-20T03:00:00.000Z", "v1", [
246
+ entry("使用手册.md", "6", "text/markdown"),
247
+ ]),
248
+ version("ver_config_1", "art_config", "7", "2026-10-20T03:00:00.000Z", "v1", [
249
+ entry("配置说明/README.md", "7", "text/markdown"),
250
+ ]),
251
+ version("ver_decl_1", "art_decl", "8", "2026-10-22T03:30:00.000Z", "v1.0.4", [
252
+ entry("变更声明.json", "8", "application/json"),
253
+ ]),
254
+ version("ver_src_1", "art_src", "9", "2026-10-22T03:30:00.000Z", "v1.0.4", [
255
+ entry("src/renderer/Tree.vue", "9", "text/plain"),
256
+ ]),
257
+ b1.version,
258
+ b2.version,
259
+ ],
260
+ files: {
261
+ ver_req_1: { "issue.json": REQUIREMENT },
262
+ ver_spec_1: { "_spec/tree-planting-line-spec.md": SPEC },
263
+ ver_instr_1: { "原子指令集.yaml": INSTRUCTIONS },
264
+ ver_manual_1: { "使用手册.md": MANUAL },
265
+ ver_config_1: { "配置说明/README.md": CONFIG },
266
+ ver_decl_1: { "变更声明.json": CHANGE_DECL },
267
+ ver_src_1: { "src/renderer/Tree.vue": TREE_SRC },
268
+ ver_bundle_1: b1.files,
269
+ ver_bundle_2: b2.files,
270
+ },
271
+ artifacts: [
272
+ { id: "art_req", name: "需求单", artifactType: "requirement" },
273
+ { id: "art_spec", name: "规格", artifactType: "spec" },
274
+ { id: "art_instr", name: "原子指令集", artifactType: "instructions" },
275
+ { id: "art_manual", name: "使用手册", artifactType: "manual" },
276
+ { id: "art_config", name: "配置说明", artifactType: "config" },
277
+ { id: "art_decl", name: "变更声明", artifactType: "change-decl" },
278
+ { id: "art_src", name: "教具源码", artifactType: "tool-src" },
279
+ { id: "art_bundle", name: "植树问题线段图", artifactType: "bundle" },
280
+ ],
281
+ threads: [
282
+ thread(
283
+ "thr_1",
284
+ 1,
285
+ "2026-10-21T07:02:00.000Z",
286
+ "resolved",
287
+ "chenxi",
288
+ {
289
+ id: "anc_thr_1",
290
+ versionId: "ver_bundle_1",
291
+ kind: "plugin:@aitutor/tool-preview/element",
292
+ payload: {
293
+ caseId: "both-ends",
294
+ step: 3,
295
+ selector: '[data-tool-id="tree-no-2"]',
296
+ toolId: "tree-no-2",
297
+ src: "src/renderer/Tree.vue:6",
298
+ label: "两端都种 · 第 3 步后 · 「2」",
299
+ },
300
+ snapshot: "2",
301
+ },
302
+ "棵数编号压在段长标注上了,挪到树上方。",
303
+ ),
304
+ thread(
305
+ "thr_2",
306
+ 2,
307
+ "2026-10-22T05:40:00.000Z",
308
+ "open",
309
+ "liuyan",
310
+ {
311
+ id: "anc_thr_2",
312
+ versionId: "ver_bundle_2",
313
+ kind: "plugin:@aitutor/tool-preview/step",
314
+ payload: {
315
+ caseId: "no-ends",
316
+ step: 3,
317
+ action: "mark_intervals",
318
+ label: "两端都不种 · 第 4 步 mark_intervals",
319
+ },
320
+ snapshot: "mark_intervals(interval_length: 7)",
321
+ },
322
+ "报错文案老师看不懂,改成「间隔要能整除全长」,错误码保留。",
323
+ ),
324
+ thread(
325
+ "thr_3",
326
+ 3,
327
+ "2026-10-22T06:15:00.000Z",
328
+ "open",
329
+ "chenxi",
330
+ {
331
+ id: "anc_thr_3",
332
+ versionId: "ver_bundle_2",
333
+ kind: "plugin:@aitutor/tool-preview/element",
334
+ payload: {
335
+ caseId: "both-ends",
336
+ step: 3,
337
+ selector: '[data-tool-id="tree-1"]',
338
+ toolId: "tree-1",
339
+ src: "src/renderer/Tree.vue:2",
340
+ label: "两端都种 · 第 3 步后 · 第 1 棵树",
341
+ },
342
+ snapshot: "第 1 棵树",
343
+ },
344
+ "深色模式下树干颜色发灰,跟背景分不开。",
345
+ ),
346
+ ],
347
+ comments: [
348
+ comment(
349
+ "cmt_1",
350
+ "thr_1",
351
+ "2026-10-21T07:02:00.000Z",
352
+ "chenxi",
353
+ "棵数编号压在段长标注上了,挪到树上方。",
354
+ ),
355
+ comment(
356
+ "cmt_2",
357
+ "thr_1",
358
+ "2026-10-22T03:30:00.000Z",
359
+ "",
360
+ "编号从树右下方挪到树冠正上方,不再和段长标注挤在一行,其余不变。",
361
+ {
362
+ turnId: "turn_3",
363
+ outcome: "changed",
364
+ files: ["src/renderer/Tree.vue"],
365
+ versionId: "ver_bundle_2",
366
+ },
367
+ ),
368
+ comment(
369
+ "cmt_3",
370
+ "thr_2",
371
+ "2026-10-22T05:40:00.000Z",
372
+ "liuyan",
373
+ "报错文案老师看不懂,改成「间隔要能整除全长」,错误码保留。",
374
+ ),
375
+ comment(
376
+ "cmt_4",
377
+ "thr_3",
378
+ "2026-10-22T06:15:00.000Z",
379
+ "chenxi",
380
+ "深色模式下树干颜色发灰,跟背景分不开。",
381
+ ),
382
+ ],
383
+ stages: [
384
+ { stage: "intake", name: "提需", kind: "human", status: "approved", versionId: "ver_req_1" },
385
+ {
386
+ stage: "spec",
387
+ name: "规格(Gate R2)",
388
+ kind: "agent",
389
+ gated: true,
390
+ status: "approved",
391
+ versionId: "ver_spec_1",
392
+ },
393
+ { stage: "strategy", name: "策略", kind: "agent", gated: true, status: "approved" },
394
+ {
395
+ stage: "engineering",
396
+ name: "研发",
397
+ kind: "agent",
398
+ status: "approved",
399
+ versionId: "ver_bundle_2",
400
+ },
401
+ { stage: "checks", name: "自动检查", kind: "job", status: "approved" },
402
+ { stage: "acceptance", name: "验收", kind: "human", gated: true, status: "in_review" },
403
+ { stage: "publish", name: "发布", kind: "job", status: "blocked" },
404
+ ],
405
+ gates: [
406
+ {
407
+ stage: "spec",
408
+ name: "规格(Gate R2)",
409
+ status: "approved",
410
+ approvedBy: ["liuyan", "wanglei"],
411
+ approveBy: ["research", "dev"],
412
+ mode: "all",
413
+ },
414
+ {
415
+ stage: "strategy",
416
+ name: "策略",
417
+ status: "approved",
418
+ approvedBy: ["liuyan"],
419
+ approveBy: ["research"],
420
+ },
421
+ {
422
+ stage: "acceptance",
423
+ name: "验收",
424
+ status: "in_review",
425
+ approvedBy: [],
426
+ approveBy: ["research", "design"],
427
+ mode: "all",
428
+ },
429
+ ],
430
+ members: [
431
+ {
432
+ actor: human("liuyan"),
433
+ displayName: "刘妍",
434
+ roles: ["research"],
435
+ roleLabels: { research: "教研" },
436
+ },
437
+ {
438
+ actor: human("wanglei"),
439
+ displayName: "王磊",
440
+ roles: ["dev"],
441
+ roleLabels: { dev: "教具研发" },
442
+ },
443
+ {
444
+ actor: human("chenxi"),
445
+ displayName: "陈曦",
446
+ roles: ["design"],
447
+ roleLabels: { design: "设计" },
448
+ },
449
+ { actor: { kind: "agent", id: "rondo" }, displayName: "Rondo", roles: [] },
450
+ ],
451
+ turn: {
452
+ current: null,
453
+ last: { number: 3, summary: "棵数编号挪到树上方", at: "2026-10-22T03:30:00.000Z" },
454
+ queue: [],
455
+ },
456
+ activity: [
457
+ {
458
+ id: "act_5",
459
+ at: "2026-10-22T06:15:00.000Z",
460
+ actor: human("chenxi"),
461
+ action: "thread.create",
462
+ text: "陈曦 在「第 1 棵树」上提了意见 #3",
463
+ threadId: "thr_3",
464
+ artifactId: "art_bundle",
465
+ },
466
+ {
467
+ id: "act_3",
468
+ at: "2026-10-22T05:40:00.000Z",
469
+ actor: human("liuyan"),
470
+ action: "thread.create",
471
+ text: "刘妍 在指令「mark_intervals」上提了意见 #2",
472
+ threadId: "thr_2",
473
+ artifactId: "art_bundle",
474
+ },
475
+ {
476
+ id: "act_2",
477
+ at: "2026-10-22T04:05:00.000Z",
478
+ actor: { kind: "agent", id: "rondo" },
479
+ action: "stage.approved",
480
+ text: "自动检查通过:结构校验、入口体量、资源声明、增量 E2E、性能、设计规范",
481
+ stage: "checks",
482
+ },
483
+ {
484
+ id: "act_1",
485
+ at: "2026-10-22T03:30:00.000Z",
486
+ actor: { kind: "agent", id: "rondo" },
487
+ action: "version.created",
488
+ text: "Rondo 交付 植树问题线段图 v1.0.4 · 编号挪到树上方",
489
+ artifactId: "art_bundle",
490
+ versionId: "ver_bundle_2",
491
+ },
492
+ ],
493
+ };
494
+
495
+ export const member = {
496
+ id: "liuyan",
497
+ displayName: "教研 · 刘妍",
498
+ roles: ["research"],
499
+ permissions: ["comment", "submit-change", "confirm", "approve"],
500
+ };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * `band dev` 用的内容平台模拟接口(只读):`GET /by-project/{projectId}` 给出教具的正式版、测试版,
3
+ * 以及引用它的专题各装到了哪一版。只在内存里,不连任何真实接口。
4
+ */
5
+ import type { ProxyRequest } from "@kanyun-ai-infra/band-kernel";
6
+ import type { ToolRelease } from "../views/release/index.ts";
7
+
8
+ const RELEASES: Record<string, ToolRelease> = {
9
+ prj_tree_line: {
10
+ toolId: "tree-planting-line",
11
+ online: { version: "1.0.2", at: "2026-10-12T09:00:00.000Z" },
12
+ beta: { version: "1.0.4-beta.1", at: "2026-10-22T04:20:00.000Z" },
13
+ topics: [
14
+ { topic: "三年级 · 植树问题(一)", version: "1.0.2" },
15
+ { topic: "三年级 · 植树问题(二)", version: "1.0.2" },
16
+ { topic: "四年级 · 间隔问题综合", version: "1.0.1" },
17
+ ],
18
+ },
19
+ };
20
+
21
+ export interface MockTeachingTools {
22
+ (req: ProxyRequest): Promise<Response>;
23
+ readonly calls: ProxyRequest[];
24
+ }
25
+
26
+ export function mockTeachingTools(): MockTeachingTools {
27
+ const calls: ProxyRequest[] = [];
28
+ const handler = async (req: ProxyRequest): Promise<Response> => {
29
+ calls.push(req);
30
+ const m = /^\/by-project\/([^/?]+)$/.exec(req.path);
31
+ const r = m?.[1] ? RELEASES[decodeURIComponent(m[1])] : undefined;
32
+ if (req.method === "GET" && r) {
33
+ return new Response(JSON.stringify(r), { headers: { "content-type": "application/json" } });
34
+ }
35
+ return new Response(JSON.stringify({ error: "not found" }), { status: 404 });
36
+ };
37
+ return Object.assign(handler, { calls });
38
+ }
39
+
40
+ export const resources = { "teaching-tools": mockTeachingTools() };