rdstudio 0.2.0__py3-none-any.whl

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 (251) hide show
  1. rdstudio/__init__.py +3 -0
  2. rdstudio/_node/rdstudio.mjs +59351 -0
  3. rdstudio/brief.py +46 -0
  4. rdstudio/build.py +218 -0
  5. rdstudio/classify.py +131 -0
  6. rdstudio/cli.py +369 -0
  7. rdstudio/config.py +115 -0
  8. rdstudio/gitlog.py +92 -0
  9. rdstudio/launcher.py +63 -0
  10. rdstudio/learner.py +187 -0
  11. rdstudio/mcp_server.py +313 -0
  12. rdstudio/okf.py +775 -0
  13. rdstudio/procedures.py +233 -0
  14. rdstudio/references.py +228 -0
  15. rdstudio/reports.py +75 -0
  16. rdstudio/scaffold.py +227 -0
  17. rdstudio/scopes.py +162 -0
  18. rdstudio/search.py +149 -0
  19. rdstudio/serve.py +214 -0
  20. rdstudio/store.py +161 -0
  21. rdstudio/templates/agents/critic.md +20 -0
  22. rdstudio/templates/agents/librarian.md +21 -0
  23. rdstudio/templates/agents/searcher.md +21 -0
  24. rdstudio/templates/agents_section.md +31 -0
  25. rdstudio/templates/claude_section.md +3 -0
  26. rdstudio/templates/knowledge/overview.md +20 -0
  27. rdstudio/templates/knowledge/tasks/bootstrap-knowledge-base.md +45 -0
  28. rdstudio/templates/skills/decision/SKILL.md +47 -0
  29. rdstudio/templates/skills/handoff/SKILL.md +18 -0
  30. rdstudio/templates/skills/ingest-ref/SKILL.md +32 -0
  31. rdstudio/templates/skills/lint-okf/SKILL.md +15 -0
  32. rdstudio/templates/skills/promote/SKILL.md +25 -0
  33. rdstudio/templates/skills/question/SKILL.md +33 -0
  34. rdstudio/templates/skills/record-okf/SKILL.md +61 -0
  35. rdstudio/templates/skills/report/SKILL.md +46 -0
  36. rdstudio/templates/skills/report/template.html +74 -0
  37. rdstudio/templates/skills/search-okf/SKILL.md +36 -0
  38. rdstudio/templates/skills/task/SKILL.md +51 -0
  39. rdstudio/web/app.js +140 -0
  40. rdstudio/web/fonts.css +48 -0
  41. rdstudio/web/icon-192.png +0 -0
  42. rdstudio/web/icon-512.png +0 -0
  43. rdstudio/web/index.html +109 -0
  44. rdstudio/web/js/data.js +125 -0
  45. rdstudio/web/js/diagrams.js +116 -0
  46. rdstudio/web/js/graph.js +396 -0
  47. rdstudio/web/js/knowledge.js +212 -0
  48. rdstudio/web/js/layout-worker.js +15 -0
  49. rdstudio/web/js/layout.js +226 -0
  50. rdstudio/web/js/learn.js +83 -0
  51. rdstudio/web/js/map.js +1293 -0
  52. rdstudio/web/js/markdown.js +173 -0
  53. rdstudio/web/js/pages.js +219 -0
  54. rdstudio/web/js/procedures.js +262 -0
  55. rdstudio/web/js/settings.js +95 -0
  56. rdstudio/web/js/util.js +99 -0
  57. rdstudio/web/report.css +35 -0
  58. rdstudio/web/report.js +104 -0
  59. rdstudio/web/style.css +566 -0
  60. rdstudio/web/sw.js +166 -0
  61. rdstudio/web/themes/cyber.css +139 -0
  62. rdstudio/web/themes/map.css +133 -0
  63. rdstudio/web/themes/notebook.css +134 -0
  64. rdstudio/web/themes/space.css +135 -0
  65. rdstudio/web/themes/studio.css +110 -0
  66. rdstudio/web/vendor/d3.min.js +2 -0
  67. rdstudio/web/vendor/fonts/atkinson-hyperlegible-next-latin-ext-wght-italic.woff2 +0 -0
  68. rdstudio/web/vendor/fonts/atkinson-hyperlegible-next-latin-ext-wght-normal.woff2 +0 -0
  69. rdstudio/web/vendor/fonts/atkinson-hyperlegible-next-latin-wght-italic.woff2 +0 -0
  70. rdstudio/web/vendor/fonts/atkinson-hyperlegible-next-latin-wght-normal.woff2 +0 -0
  71. rdstudio/web/vendor/fonts/caveat-latin-wght-normal.woff2 +0 -0
  72. rdstudio/web/vendor/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
  73. rdstudio/web/vendor/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
  74. rdstudio/web/vendor/fonts/ibm-plex-sans-latin-wght-italic.woff2 +0 -0
  75. rdstudio/web/vendor/fonts/ibm-plex-sans-latin-wght-normal.woff2 +0 -0
  76. rdstudio/web/vendor/fonts/inter-latin-opsz-italic.woff2 +0 -0
  77. rdstudio/web/vendor/fonts/inter-latin-opsz-normal.woff2 +0 -0
  78. rdstudio/web/vendor/fonts/jetbrains-mono-latin-wght-italic.woff2 +0 -0
  79. rdstudio/web/vendor/fonts/jetbrains-mono-latin-wght-normal.woff2 +0 -0
  80. rdstudio/web/vendor/fonts/literata-latin-ext-opsz-italic.woff2 +0 -0
  81. rdstudio/web/vendor/fonts/literata-latin-ext-opsz-normal.woff2 +0 -0
  82. rdstudio/web/vendor/fonts/literata-latin-opsz-italic.woff2 +0 -0
  83. rdstudio/web/vendor/fonts/literata-latin-opsz-normal.woff2 +0 -0
  84. rdstudio/web/vendor/fonts/source-sans-3-latin-wght-italic.woff2 +0 -0
  85. rdstudio/web/vendor/fonts/source-sans-3-latin-wght-normal.woff2 +0 -0
  86. rdstudio/web/vendor/fonts/source-serif-4-latin-opsz-italic.woff2 +0 -0
  87. rdstudio/web/vendor/fonts/source-serif-4-latin-opsz-normal.woff2 +0 -0
  88. rdstudio/web/vendor/hljs/github-dark.min.css +10 -0
  89. rdstudio/web/vendor/hljs/github.min.css +10 -0
  90. rdstudio/web/vendor/hljs/highlight.min.js +1262 -0
  91. rdstudio/web/vendor/hljs/julia.min.js +18 -0
  92. rdstudio/web/vendor/hljs/latex.min.js +33 -0
  93. rdstudio/web/vendor/hljs/matlab.min.js +15 -0
  94. rdstudio/web/vendor/katex/auto-render.min.js +1 -0
  95. rdstudio/web/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  96. rdstudio/web/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  97. rdstudio/web/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  98. rdstudio/web/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  99. rdstudio/web/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  100. rdstudio/web/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  101. rdstudio/web/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  102. rdstudio/web/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  103. rdstudio/web/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  104. rdstudio/web/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  105. rdstudio/web/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  106. rdstudio/web/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  107. rdstudio/web/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  108. rdstudio/web/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  109. rdstudio/web/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  110. rdstudio/web/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  111. rdstudio/web/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  112. rdstudio/web/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  113. rdstudio/web/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  114. rdstudio/web/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  115. rdstudio/web/vendor/katex/katex.min.css +1 -0
  116. rdstudio/web/vendor/katex/katex.min.js +1 -0
  117. rdstudio/web/vendor/licenses/atkinson-hyperlegible-next-OFL.txt +93 -0
  118. rdstudio/web/vendor/licenses/caveat-OFL.txt +93 -0
  119. rdstudio/web/vendor/licenses/d3-7.9.0.txt +13 -0
  120. rdstudio/web/vendor/licenses/highlightjs-cdn-assets-11.12.0.txt +29 -0
  121. rdstudio/web/vendor/licenses/ibm-plex-mono-OFL.txt +93 -0
  122. rdstudio/web/vendor/licenses/ibm-plex-sans-OFL.txt +93 -0
  123. rdstudio/web/vendor/licenses/inter-OFL.txt +93 -0
  124. rdstudio/web/vendor/licenses/jetbrains-mono-OFL.txt +93 -0
  125. rdstudio/web/vendor/licenses/katex-0.18.7.txt +21 -0
  126. rdstudio/web/vendor/licenses/literata-OFL.txt +93 -0
  127. rdstudio/web/vendor/licenses/markdown-it-15.0.2.txt +22 -0
  128. rdstudio/web/vendor/licenses/markdown-it-footnote-4.0.0.txt +22 -0
  129. rdstudio/web/vendor/licenses/markdown-it-texmath-1.0.0.txt +21 -0
  130. rdstudio/web/vendor/licenses/mermaid-12.0.0.txt +21 -0
  131. rdstudio/web/vendor/licenses/source-sans-3-OFL.txt +93 -0
  132. rdstudio/web/vendor/licenses/source-serif-4-OFL.txt +93 -0
  133. rdstudio/web/vendor/licenses/vega-6.4.0.txt +27 -0
  134. rdstudio/web/vendor/licenses/vega-embed-7.2.0.txt +27 -0
  135. rdstudio/web/vendor/licenses/vega-lite-6.4.3.txt +27 -0
  136. rdstudio/web/vendor/markdown-it-footnote.min.js +2 -0
  137. rdstudio/web/vendor/markdown-it.min.js +14 -0
  138. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/abnfDiagram-DGLNOSUI.mjs +1 -0
  139. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/architecture-7GRP2DOG-HF4J73XS.mjs +1 -0
  140. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/architectureDiagram-IU6H5EVY.mjs +36 -0
  141. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/blockDiagram-FSX6DT2V.mjs +140 -0
  142. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/c4Diagram-YNRVYILN.mjs +38 -0
  143. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-22SYA5HA.mjs +1 -0
  144. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-2FTYKNOQ.mjs +1 -0
  145. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-36VM3LGA.mjs +1 -0
  146. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-3SEI7E7V.mjs +1 -0
  147. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-3T2MNPEU.mjs +1 -0
  148. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-44AU3KAP.mjs +174 -0
  149. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-4MZOTL6B.mjs +1 -0
  150. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-52IMQVNL.mjs +1 -0
  151. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-5NYYYZGL.mjs +1 -0
  152. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-BOZ75642.mjs +15 -0
  153. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-CVBX6EWK.mjs +1 -0
  154. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-D36F7FYG.mjs +14 -0
  155. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-DEGLBX6O.mjs +213 -0
  156. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-F6PIGZHG.mjs +1 -0
  157. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-FE53TMRB.mjs +133 -0
  158. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-FNR2RGIF.mjs +1 -0
  159. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-GDOATIN3.mjs +32 -0
  160. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-H7BX327W.mjs +2 -0
  161. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-HI3EPXIC.mjs +2 -0
  162. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-JCBDXJ5W.mjs +1 -0
  163. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-JGXDHUYS.mjs +1 -0
  164. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-L2B47AAZ.mjs +1 -0
  165. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-LIEGGFIX.mjs +1 -0
  166. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-LLWYPJEZ.mjs +1 -0
  167. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-MFYRHTYG.mjs +1 -0
  168. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-MIE3LDYP.mjs +1 -0
  169. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-MLQVGYRW.mjs +1 -0
  170. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-MNT3HHAC.mjs +1 -0
  171. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-NRRTYJAG.mjs +1 -0
  172. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-OCMJQKYE.mjs +10 -0
  173. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-PKJCTQEK.mjs +339 -0
  174. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-QADHU5CF.mjs +2 -0
  175. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-QVIEFLGF.mjs +1 -0
  176. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-QX7LGXZU.mjs +1 -0
  177. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-R2KH53MI.mjs +1 -0
  178. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-RXM7Z7NK.mjs +2 -0
  179. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-S4TE5DX6.mjs +1 -0
  180. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-SDIBIOXT.mjs +1 -0
  181. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-TDFULVG6.mjs +1 -0
  182. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-TECWHJ6D.mjs +62 -0
  183. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-TINYC7RT.mjs +70 -0
  184. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-V3KJR4XU.mjs +1 -0
  185. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-VTMXW4ES.mjs +1 -0
  186. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-Y5NT6LW5.mjs +88 -0
  187. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-Y5O5OPKC.mjs +3 -0
  188. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-YZG4BXY6.mjs +1 -0
  189. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZZ52EIBP.mjs +1 -0
  190. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-v2-VV4INRHB.mjs +217 -0
  191. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/cose-bilkent-MSIMRU2B.mjs +1 -0
  192. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/cynefin-OW5HDTMX-KMPDV6GS.mjs +1 -0
  193. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/cynefinDiagram-KTGLXFXK.mjs +62 -0
  194. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/dagre-QJJCSHY4.mjs +4 -0
  195. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/diagram-2ZIM67RP.mjs +3 -0
  196. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/diagram-FYHH5O6R.mjs +24 -0
  197. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/diagram-LYLDACMS.mjs +200 -0
  198. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/diagram-TYT3HRBC.mjs +24 -0
  199. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/diagram-XVIN6YVD.mjs +30 -0
  200. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/diagram-ZO2NLLYC.mjs +41 -0
  201. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/ebnfDiagram-TU3FGH35.mjs +1 -0
  202. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/elk-GHAXNSLK.mjs +27 -0
  203. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/erDiagram-XID3VV23.mjs +99 -0
  204. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/eventmodeling-NTZA5JFV-P5QJSWSK.mjs +1 -0
  205. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/flowDiagram-WPHQAKTU.mjs +1 -0
  206. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/ganttDiagram-QACGSKG6.mjs +292 -0
  207. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/gitGraph-4MIJSDKK-V5NEQQYP.mjs +1 -0
  208. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/gitGraphDiagram-EB76O4HC.mjs +106 -0
  209. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/info-A6RAGUB7-IGBHH2L7.mjs +1 -0
  210. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/infoDiagram-343ZKIDN.mjs +2 -0
  211. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/ishikawaDiagram-UEEU5D75.mjs +70 -0
  212. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/journeyDiagram-4QTZOVLF.mjs +139 -0
  213. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/kanban-definition-VEJL4RG2.mjs +89 -0
  214. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/katex-QVRI4OIV.mjs +257 -0
  215. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/mindmap-definition-C5K5ZT7T.mjs +96 -0
  216. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/packet-AYTQ26CC-PJTKDECJ.mjs +1 -0
  217. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/pegDiagram-FHIILVJB.mjs +1 -0
  218. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/pie-WAS4IAKB-U3JFQXZN.mjs +1 -0
  219. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/pieDiagram-S76BU6V7.mjs +39 -0
  220. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/quadrantDiagram-HZBLWUZE.mjs +7 -0
  221. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/radar-RG4KPBEZ-7T2UW32D.mjs +1 -0
  222. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/railroad-74A4TZTK-DZY7ARDL.mjs +1 -0
  223. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/railroad-abnf-HS5TGJTU-LWS535ZK.mjs +1 -0
  224. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/railroad-ebnf-LZEXJU2U-EA3S4ZFM.mjs +1 -0
  225. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/railroad-peg-WCYAUIDC-DUKZONPX.mjs +1 -0
  226. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/railroadDiagram-R6RP3MQ2.mjs +1 -0
  227. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/requirementDiagram-SGBABQV6.mjs +84 -0
  228. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/sankeyDiagram-IM6M5BOW.mjs +40 -0
  229. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/sequenceDiagram-FGJOIFJ2.mjs +169 -0
  230. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/sizeCapture-ERV5D3W5.mjs +1 -0
  231. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-v2-6KDGCZ5J.mjs +291 -0
  232. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/swimlanes-OJBUSBEF.mjs +1 -0
  233. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/swimlanesDiagram-LNXYTHDW.mjs +8 -0
  234. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/timeline-definition-7G6YQRTY.mjs +120 -0
  235. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/treeView-Q6P3EWNA-AABPVERA.mjs +1 -0
  236. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/treemap-WGGIJYW6-F2JSY3V3.mjs +1 -0
  237. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/usecaseDiagram-6Y6TMLBO.mjs +383 -0
  238. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/vennDiagram-6RODYPCK.mjs +34 -0
  239. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/wardley-WFR3VGLG-EIT5NWVN.mjs +1 -0
  240. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/wardleyDiagram-RFZKLAPA.mjs +78 -0
  241. rdstudio/web/vendor/mermaid/chunks/mermaid.esm.min/xychartDiagram-TWWI2QJZ.mjs +7 -0
  242. rdstudio/web/vendor/mermaid/mermaid.esm.min.mjs +14 -0
  243. rdstudio/web/vendor/texmath.js +368 -0
  244. rdstudio/web/vendor/vega/vega-embed.min.js +7 -0
  245. rdstudio/web/vendor/vega/vega-lite.min.js +2 -0
  246. rdstudio/web/vendor/vega/vega.min.js +1 -0
  247. rdstudio-0.2.0.dist-info/METADATA +201 -0
  248. rdstudio-0.2.0.dist-info/RECORD +251 -0
  249. rdstudio-0.2.0.dist-info/WHEEL +4 -0
  250. rdstudio-0.2.0.dist-info/entry_points.txt +3 -0
  251. rdstudio-0.2.0.dist-info/licenses/LICENSE +21 -0
rdstudio/serve.py ADDED
@@ -0,0 +1,214 @@
1
+ """Serve the dashboard with the standard library, rebuilding when sources change."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import email.utils
6
+ import functools
7
+ import gzip
8
+ import io
9
+ import json
10
+ import os
11
+ import secrets
12
+ import sys
13
+ import threading
14
+ import time
15
+ from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
16
+ from urllib.parse import urlsplit
17
+
18
+ from . import learner
19
+ from .build import WEB_DIR, build
20
+ from .config import Config
21
+
22
+ POLL_SECONDS = 1.0
23
+
24
+
25
+ LOOPBACK = {"localhost", "127.0.0.1", "::1"}
26
+ # Text worth compressing: on a slow link (a VS Code tunnel, say) the dashboard's
27
+ # 1.3 MB of scripts and data shrink to about 0.5 MB.
28
+ COMPRESSIBLE = (".html", ".js", ".mjs", ".css", ".json", ".md", ".svg", ".txt", ".webmanifest", ".map")
29
+ _gzipped: dict[tuple[str, int, int], bytes] = {}
30
+
31
+
32
+ class _Handler(SimpleHTTPRequestHandler):
33
+ """Static files, plus ``/api/learner`` for the private learner record.
34
+
35
+ Writes are accepted only from the dashboard's own pages: the Origin must
36
+ match the Host, the body must be JSON, and the request must carry the token
37
+ handed out by GET (which other sites cannot read). When bound to localhost,
38
+ the API answers only to localhost names, Tailscale names (``*.ts.net``, as
39
+ ``tailscale serve`` passes them through) and ``--allow-host`` names, against
40
+ DNS rebinding."""
41
+
42
+ # Keep connections open between requests: through a tunnel, each new
43
+ # connection is slow to set up and more likely to be dropped.
44
+ protocol_version = "HTTP/1.1"
45
+
46
+ cfg: Config
47
+ token: str
48
+ loopback: bool
49
+ allowed: frozenset[str] = frozenset()
50
+
51
+ def _host_ok(self) -> bool:
52
+ host = urlsplit("//" + (self.headers.get("Host") or "")).hostname or ""
53
+ return not self.loopback or host in LOOPBACK or host.endswith(".ts.net") or host in self.allowed
54
+
55
+ def _json(self, status: int, value: object) -> None:
56
+ body = json.dumps(value, ensure_ascii=False).encode()
57
+ self.send_response(status)
58
+ self.send_header("Content-Type", "application/json")
59
+ self.send_header("Content-Length", str(len(body)))
60
+ self.send_header("Cache-Control", "no-store")
61
+ if self.close_connection:
62
+ self.send_header("Connection", "close")
63
+ self.end_headers()
64
+ self.wfile.write(body)
65
+
66
+ def do_GET(self) -> None:
67
+ if urlsplit(self.path).path != "/api/learner":
68
+ return super().do_GET()
69
+ if not self._host_ok():
70
+ return self._json(403, {"error": "host not allowed"})
71
+ on = learner.enabled(self.cfg)
72
+ self._json(200, {
73
+ "enabled": on,
74
+ "token": self.token if on else None,
75
+ "dir": str(learner.record_dir(self.cfg)) if on else None,
76
+ "events": learner.events(self.cfg) if on else [],
77
+ })
78
+
79
+ def do_POST(self) -> None:
80
+ self.close_connection = True # a refused body is never read; do not reuse the connection
81
+ if urlsplit(self.path).path != "/api/learner":
82
+ return self._json(404, {"error": "not found"})
83
+ origin = urlsplit(self.headers.get("Origin") or "").netloc
84
+ if not self._host_ok() or origin != self.headers.get("Host"):
85
+ return self._json(403, {"error": "cross-origin request refused"})
86
+ if self.headers.get("X-Rdstudio-Token") != self.token:
87
+ return self._json(403, {"error": "bad token"})
88
+ if not (self.headers.get("Content-Type") or "").startswith("application/json"):
89
+ return self._json(415, {"error": "JSON only"})
90
+ if not learner.enabled(self.cfg):
91
+ return self._json(409, {"error": "the learner record is off ([learner] enabled in the user config)"})
92
+ length = int(self.headers.get("Content-Length") or 0)
93
+ if length > learner.MAX_EVENT_BYTES:
94
+ return self._json(413, {"error": "event too large"})
95
+ try:
96
+ event = learner.append(self.cfg, json.loads(self.rfile.read(length) or b"null"))
97
+ except (ValueError, learner.LearnerError) as exc:
98
+ return self._json(400, {"error": str(exc)})
99
+ self._json(200, event)
100
+
101
+ def _cache_control(self) -> str | None:
102
+ path = urlsplit(self.path).path
103
+ if path.startswith("/vendor/"):
104
+ return "public, max-age=604800" # changes only when rdstudio is upgraded
105
+ if path.startswith("/data/") or path.endswith((".html", ".js", ".css")) or path == "/":
106
+ return "no-cache" # revalidate (cheap: 304 when unchanged)
107
+ return None
108
+
109
+ def end_headers(self) -> None:
110
+ if cc := self._cache_control():
111
+ self.send_header("Cache-Control", cc)
112
+ super().end_headers()
113
+
114
+ def send_head(self): # type: ignore[override]
115
+ """Serve text gzipped when the browser accepts it; everything else as usual."""
116
+ path = self.translate_path(self.path)
117
+ if os.path.isdir(path) and urlsplit(self.path).path.endswith("/"):
118
+ path = os.path.join(path, "index.html")
119
+ if ("gzip" not in (self.headers.get("Accept-Encoding") or "") or not path.endswith(COMPRESSIBLE)
120
+ or not os.path.isfile(path)):
121
+ return super().send_head()
122
+ st = os.stat(path)
123
+ since = self.headers.get("If-Modified-Since")
124
+ if since:
125
+ try:
126
+ if int(st.st_mtime) <= email.utils.parsedate_to_datetime(since).timestamp():
127
+ self.send_response(304)
128
+ self.send_header("Vary", "Accept-Encoding")
129
+ self.end_headers()
130
+ return None
131
+ except (TypeError, ValueError, OverflowError):
132
+ pass
133
+ key = (path, st.st_mtime_ns, st.st_size)
134
+ body = _gzipped.get(key)
135
+ if body is None:
136
+ with open(path, "rb") as fh:
137
+ body = gzip.compress(fh.read(), compresslevel=6)
138
+ if len(_gzipped) > 512:
139
+ _gzipped.clear()
140
+ _gzipped[key] = body
141
+ self.send_response(200)
142
+ self.send_header("Content-Type", self.guess_type(path))
143
+ self.send_header("Content-Encoding", "gzip")
144
+ self.send_header("Content-Length", str(len(body)))
145
+ self.send_header("Last-Modified", self.date_time_string(int(st.st_mtime)))
146
+ self.send_header("Vary", "Accept-Encoding")
147
+ self.end_headers()
148
+ return io.BytesIO(body)
149
+
150
+ def log_message(self, format: str, *args: object) -> None: # noqa: A002 - stdlib signature
151
+ pass
152
+
153
+
154
+ def _fingerprint(cfg: Config) -> tuple:
155
+ """A cheap summary of everything the build reads."""
156
+ roots = [cfg.knowledge_dir, cfg.reports_dir, cfg.root / ".claude", WEB_DIR]
157
+ files = [cfg.root / "rdstudio.toml", cfg.root / ".git" / "HEAD", cfg.root / ".git" / "index"]
158
+ stamp: list[tuple[str, int, int]] = []
159
+ for root in roots:
160
+ if not root.is_dir():
161
+ continue
162
+ for dirpath, dirnames, filenames in os.walk(root):
163
+ dirnames[:] = [d for d in dirnames if not d.startswith(".")]
164
+ for name in filenames:
165
+ p = os.path.join(dirpath, name)
166
+ try:
167
+ st = os.stat(p)
168
+ except OSError:
169
+ continue
170
+ stamp.append((p, st.st_mtime_ns, st.st_size))
171
+ for f in files:
172
+ if f.exists():
173
+ st = f.stat()
174
+ stamp.append((str(f), st.st_mtime_ns, st.st_size))
175
+ return tuple(sorted(stamp))
176
+
177
+
178
+ def _watch(cfg: Config, stop: threading.Event) -> None:
179
+ last = _fingerprint(cfg)
180
+ while not stop.wait(POLL_SECONDS):
181
+ current = _fingerprint(cfg)
182
+ if current == last:
183
+ continue
184
+ try:
185
+ build(cfg)
186
+ print(f"[{time.strftime('%H:%M:%S')}] rebuilt", flush=True)
187
+ except Exception as exc: # keep serving the last good build
188
+ print(f"[{time.strftime('%H:%M:%S')}] build failed: {exc}", file=sys.stderr, flush=True)
189
+ last = _fingerprint(cfg) # the build may regenerate index.md files
190
+
191
+
192
+ def serve(cfg: Config, *, host: str = "127.0.0.1", port: int = 8000, watch: bool = True,
193
+ allow_hosts: tuple[str, ...] = ()) -> None:
194
+ site = build(cfg)
195
+ handler_cls = type("Handler", (_Handler,), {
196
+ "cfg": cfg, "token": secrets.token_urlsafe(24), "loopback": host in LOOPBACK,
197
+ "allowed": frozenset(h.lower() for h in allow_hosts)})
198
+ handler = functools.partial(handler_cls, directory=str(site))
199
+ server = ThreadingHTTPServer((host, port), handler)
200
+ stop = threading.Event()
201
+ if watch:
202
+ threading.Thread(target=_watch, args=(cfg, stop), daemon=True).start()
203
+ shown = "localhost" if host in ("127.0.0.1", "0.0.0.0") else host
204
+ print(f"Serving {cfg.title} at http://{shown}:{port}/ (Ctrl+C to stop)", flush=True)
205
+ if host == "0.0.0.0":
206
+ print("Listening on all interfaces (reachable over your tailnet/LAN).", flush=True)
207
+ try:
208
+ server.serve_forever()
209
+ except KeyboardInterrupt:
210
+ pass
211
+ finally:
212
+ stop.set()
213
+ server.server_close()
214
+
rdstudio/store.py ADDED
@@ -0,0 +1,161 @@
1
+ """Writing concepts with provenance: create, update (whole body or one section), verify."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import posixpath
6
+ import re
7
+ from dataclasses import dataclass
8
+ from pathlib import Path
9
+ from typing import Any
10
+
11
+ from .okf import (
12
+ RESERVED,
13
+ FrontmatterError,
14
+ headings,
15
+ now,
16
+ render_concept,
17
+ split_frontmatter,
18
+ )
19
+
20
+ _SAFE_ID = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._/-]*$")
21
+
22
+
23
+ class StoreError(ValueError):
24
+ pass
25
+
26
+
27
+ @dataclass
28
+ class WriteResult:
29
+ id: str
30
+ path: str
31
+ created: bool
32
+ significant: bool
33
+ decided_by: str = "caller"
34
+
35
+ def as_dict(self) -> dict[str, Any]:
36
+ return {"id": self.id, "path": self.path, "created": self.created, "significant": self.significant,
37
+ "decided_by": self.decided_by}
38
+
39
+
40
+ def concept_path(root: Path, cid: str) -> Path:
41
+ cid = cid.strip().lstrip("/")
42
+ if cid.endswith(".md"):
43
+ cid = cid[:-3]
44
+ norm = posixpath.normpath(cid)
45
+ if not _SAFE_ID.match(norm) or norm.startswith("..") or "/../" in f"/{norm}/":
46
+ raise StoreError(f"invalid concept id: {cid!r}")
47
+ if posixpath.basename(norm) + ".md" in RESERVED:
48
+ raise StoreError(f"{posixpath.basename(norm)}.md is reserved by OKF")
49
+ return root / f"{norm}.md"
50
+
51
+
52
+ def _read(path: Path) -> tuple[dict[str, Any], str]:
53
+ meta, body = split_frontmatter(path.read_text(encoding="utf-8"))
54
+ return (meta or {}), body
55
+
56
+
57
+ def replace_section(body: str, heading: str, content: str) -> str:
58
+ """Replace the content under ``heading`` (keeping the heading line); append the
59
+ section at the end when it does not exist."""
60
+ wanted = heading.strip().lstrip("#").strip()
61
+ hs = headings(body)
62
+ lines = body.split("\n")
63
+ for idx, h in enumerate(hs):
64
+ if h.text.lower() == wanted.lower():
65
+ end = len(lines)
66
+ for later in hs[idx + 1 :]:
67
+ if later.level <= h.level:
68
+ end = later.line
69
+ break
70
+ new = lines[: h.line + 1] + ["", content.strip(), ""] + lines[end:]
71
+ return "\n".join(new)
72
+ return body.rstrip() + f"\n\n# {wanted}\n\n{content.strip()}\n"
73
+
74
+
75
+ def record(
76
+ root: Path,
77
+ cid: str,
78
+ *,
79
+ actor: str,
80
+ body: str | None = None,
81
+ meta: dict[str, Any] | None = None,
82
+ section: str | None = None,
83
+ append: str | None = None,
84
+ significant: bool | None = True,
85
+ classifier: Any = None,
86
+ ) -> WriteResult:
87
+ """Create or update a concept.
88
+
89
+ - ``meta`` keys overwrite existing keys; a ``None`` value deletes the key.
90
+ Unknown keys already present are preserved.
91
+ - ``body`` replaces the whole body; ``section`` + ``body`` replaces only that
92
+ section; ``append`` adds text at the end.
93
+ - ``significant`` edits stamp ``generated: {by, at}`` (OKF: last meaningful
94
+ change). Minor edits leave provenance untouched. ``None`` lets the
95
+ classifier decide from the before and after text.
96
+ """
97
+ path = concept_path(root, cid)
98
+ created = not path.exists()
99
+ if created:
100
+ current_meta: dict[str, Any] = {}
101
+ current_body = ""
102
+ significant = True
103
+ else:
104
+ try:
105
+ current_meta, current_body = _read(path)
106
+ except FrontmatterError as exc:
107
+ raise StoreError(f"cannot update {path.name}: {exc}") from exc
108
+
109
+ new_meta = dict(current_meta)
110
+ for key, value in (meta or {}).items():
111
+ if value is None:
112
+ new_meta.pop(key, None)
113
+ else:
114
+ new_meta[key] = value
115
+ if not new_meta.get("type"):
116
+ raise StoreError("a concept needs a non-empty 'type'")
117
+
118
+ new_body = current_body
119
+ if body is not None:
120
+ new_body = replace_section(current_body, section, body) if section else body
121
+ if append:
122
+ new_body = new_body.rstrip() + "\n\n" + append.strip() + "\n"
123
+
124
+ decided_by = "caller"
125
+ if significant is None:
126
+ headline = any(new_meta.get(k) != current_meta.get(k) for k in ("type", "title", "description"))
127
+ if headline:
128
+ significant, decided_by = True, "rules"
129
+ else:
130
+ from .classify import RulesClassifier
131
+
132
+ decision = (classifier or RulesClassifier()).choose(
133
+ "edit_significance", ["minor", "significant"], {"before": current_body, "after": new_body})
134
+ significant, decided_by = decision.choice != "minor", decision.backend
135
+
136
+ if significant:
137
+ new_meta["generated"] = {"by": actor, "at": now()}
138
+
139
+ # Keep 'type' first for readability.
140
+ ordered = {"type": new_meta.pop("type"), **new_meta}
141
+ path.parent.mkdir(parents=True, exist_ok=True)
142
+ path.write_text(render_concept(ordered, new_body), encoding="utf-8")
143
+ rel = path.relative_to(root).as_posix()
144
+ return WriteResult(rel[:-3], rel, created, bool(significant), decided_by if not created else "new")
145
+
146
+
147
+ def verify(root: Path, cid: str, *, actor: str) -> WriteResult:
148
+ """Append a verification event by ``actor`` at the current time."""
149
+ path = concept_path(root, cid)
150
+ if not path.exists():
151
+ raise StoreError(f"no such concept: {cid}")
152
+ meta, body = _read(path)
153
+ events = meta.get("verified")
154
+ if isinstance(events, dict):
155
+ events = [events]
156
+ events = list(events or [])
157
+ events.append({"by": actor, "at": now()})
158
+ meta["verified"] = events
159
+ path.write_text(render_concept(meta, body), encoding="utf-8")
160
+ rel = path.relative_to(root).as_posix()
161
+ return WriteResult(rel[:-3], rel, False, False)
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: critic
3
+ description: Reviews a plan, design, change or claim critically against the project's recorded decisions, conventions and evidence. Use before committing to a plan, after a substantial change, or when a result seems too good.
4
+ tools: Read, Grep, Glob, mcp__rdstudio__search, mcp__rdstudio__outline, mcp__rdstudio__read
5
+ ---
6
+
7
+ You are a critic. Your job is to find what is wrong, missing or unjustified,
8
+ not to praise or rewrite.
9
+
10
+ Check the material you are given against:
11
+ 1. Recorded decisions (search `type: Decision`). Flag any conflict, and whether
12
+ the decision's stated assumption still holds.
13
+ 2. Recorded conventions and procedures.
14
+ 3. Internal consistency: do the claims follow from the evidence shown?
15
+ 4. Omissions: edge cases, untested paths, unstated assumptions.
16
+
17
+ Reply with a numbered list of issues, most serious first. For each: what is
18
+ wrong, why it matters, and the evidence (file:line or concept id). Separate
19
+ **blocking** issues from **worth considering**. If you find nothing
20
+ significant, say so in one line. Do not pad.
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: librarian
3
+ description: Answers questions from the project knowledge base (OKF) without filling the main agent's context. Use for lookups that need several searches, or to check whether something is already decided, answered or documented.
4
+ tools: mcp__rdstudio__search, mcp__rdstudio__outline, mcp__rdstudio__read, mcp__rdstudio__list_concepts, mcp__rdstudio__backlinks
5
+ ---
6
+
7
+ You are the librarian for this project's knowledge base. You find and report
8
+ what is recorded; you do not write to it and you do not speculate beyond it.
9
+
10
+ Method:
11
+ 1. Search with several phrasings and filters (type, tags, directory).
12
+ 2. Use outline before read, and read only the sections you need.
13
+ 3. Follow links when the answer spans concepts.
14
+
15
+ Reply in at most ~200 words:
16
+ - **Answer**: what the knowledge base says, in plain terms.
17
+ - **Sources**: concept ids, each with its trust (human-reviewed,
18
+ machine-confirmed, unverified; note if changed since review).
19
+ - **Gaps**: what is not recorded, or where concepts disagree.
20
+
21
+ If nothing relevant is recorded, say so plainly. Never invent content.
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: searcher
3
+ description: Finds and summarises external information (web pages, papers, documentation, PDFs) for a specific question. Use for literature or documentation lookups whose raw results would flood the main context.
4
+ tools: WebSearch, WebFetch, Read, Bash
5
+ ---
6
+
7
+ You are a research assistant. Find reliable sources that answer the question
8
+ you are given and summarise them compactly.
9
+
10
+ - Prefer primary sources: papers, official documentation, specifications.
11
+ - For PDFs available locally, extract only the relevant pages
12
+ (e.g. `pdftotext -f N -l M file.pdf -`).
13
+ - Record nothing in the knowledge base yourself; the main agent decides what to
14
+ keep.
15
+
16
+ Reply in at most ~300 words:
17
+ - **Findings**: bullet points, each with its source.
18
+ - **Sources**: full citation or URL for each, with a stable short id
19
+ (e.g. `tao2008circular`) the main agent can use in `sources`.
20
+ - **Confidence and gaps**: what is well supported, what is not, and what you
21
+ could not find.
@@ -0,0 +1,31 @@
1
+ <!-- rdstudio:start (managed by rdstudio init; edits between these markers are replaced) -->
2
+ ## Project knowledge (rdstudio)
3
+
4
+ This project keeps a knowledge base in `{knowledge}/`, in Open Knowledge Format
5
+ (markdown + YAML frontmatter). It records design, decisions, questions, tasks,
6
+ procedures, references and findings, authored jointly by the developer and
7
+ agents. A read-only dashboard shows it: `rdstudio serve`.
8
+
9
+ The `rdstudio` MCP server gives access to it, and the skills named below
10
+ (`search-okf`, `record-okf`, ...) describe how to use it; in Claude Code they
11
+ are also slash commands.
12
+
13
+ - **Start oriented.** If this session did not open with a knowledge-base brief,
14
+ call the rdstudio `brief` tool first.
15
+ - **Look before re-deriving.** Search the knowledge base (the `search-okf`
16
+ skill, or the `librarian` subagent) before reopening a question or
17
+ redesigning something. Recorded decisions stand unless their stated
18
+ assumption is shown false.
19
+ - **Record as you go.** Decisions (`decision`), questions (`question`),
20
+ findings and procedures (`record-okf`), tasks (`task`). Write through the
21
+ rdstudio MCP tools so provenance is stamped. Do not edit `index.md` files.
22
+ - **Report substantial work** as HTML in `{reports}/` (the `report` skill).
23
+ - **Close sessions** with the `handoff` skill.
24
+ - **Global knowledge:** if the developer has a cross-project knowledge base,
25
+ search it with `scope: "global"` (or `"all"`); suggest the `promote` skill
26
+ for knowledge that is not specific to this project.
27
+ - **Trust:** only the developer verifies concepts. Mark edits
28
+ `significant: false` only when trivial or dictated.
29
+ - The developer's actor id for provenance is `{human}`; the rdstudio tools
30
+ stamp yours.
31
+ <!-- rdstudio:end -->
@@ -0,0 +1,3 @@
1
+ <!-- rdstudio:start (managed by rdstudio init; edits between these markers are replaced) -->
2
+ @AGENTS.md
3
+ <!-- rdstudio:end -->
@@ -0,0 +1,20 @@
1
+ ---
2
+ type: Overview
3
+ title: {title}
4
+ description: What this project is, in one sentence. (Placeholder; replace.)
5
+ status: draft
6
+ tags: [overview]
7
+ ---
8
+
9
+ # Purpose
10
+
11
+ What this project sets out to do, and why.
12
+
13
+ # Scope
14
+
15
+ What is in and out of scope.
16
+
17
+ # Where things are
18
+
19
+ The knowledge base is organised into directories. See the
20
+ [bootstrap task](/tasks/bootstrap-knowledge-base.md) for how to set them up.
@@ -0,0 +1,45 @@
1
+ ---
2
+ type: Task
3
+ title: Bootstrap the knowledge base
4
+ description: Tailor this knowledge base to the project with the developer.
5
+ tags: [task, todo]
6
+ ---
7
+
8
+ # Prompt
9
+
10
+ This knowledge base was just created by `rdstudio init` and holds only
11
+ placeholders. Working with the developer, tailor it to this project.
12
+
13
+ 1. **Learn the project.** Read the repository's README, CLAUDE.md or
14
+ AGENTS.md, existing docs and recent history. Ask the developer what the
15
+ project is for, who it is for, and what stage it is at.
16
+ 2. **Propose a directory structure** suited to the project, and agree it with
17
+ the developer before creating anything. Common directories: `design/`,
18
+ `decisions/`, `questions/`, `tasks/`, `procedures/`, `references/`,
19
+ `research/`, `experiments/`. Add project-specific ones where they earn their
20
+ place (for example `thesis/` for a thesis project), and leave out ones that
21
+ do not.
22
+ 3. **Write the overview** ([overview](/overview.md)): purpose, scope, and a map
23
+ of the directories. Give each directory an `overview.md` (`type: Overview`)
24
+ when it needs explanation.
25
+ 4. **Seed from existing material.** Where the repository already holds design
26
+ notes, decision logs or references, record them as concepts. Material the
27
+ developer wrote is recorded with `generated.by` set to their actor id.
28
+ 5. **Record procedures** the developer repeats (release steps, data
29
+ regeneration, bibliography updates) as `type: Procedure` concepts.
30
+ 6. Write a short report (`/report`) summarising the structure and what was
31
+ seeded, and mark this task done.
32
+
33
+ # Plan
34
+
35
+ (To be written by the agent and approved by the developer.)
36
+
37
+ # Acceptance
38
+
39
+ - The developer has agreed the directory structure.
40
+ - The overview describes the project and maps the directories.
41
+ - `rdstudio check` passes.
42
+
43
+ # Outcome
44
+
45
+ Not started.
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: decision
3
+ description: Record a decision with its assumption and the conditions for reopening it. Use when the developer settles a design or research choice, or asks to log a decision.
4
+ ---
5
+
6
+ # Record a decision
7
+
8
+ Decisions are recorded so they are not relitigated. Each one states what was
9
+ decided, the assumption it rests on, and what would justify reopening it. A
10
+ decision is reopened only when its assumption is shown false or the goal it
11
+ serves changes; an interesting alternative is not enough.
12
+
13
+ ## Steps
14
+
15
+ 1. Search `type: Decision` for an existing decision on the topic. If one
16
+ exists, update it (and say whether you are revising or reopening it).
17
+ 2. Record at `decisions/<short-slug>` with the rdstudio `record` tool:
18
+
19
+ ```markdown
20
+ ---
21
+ type: Decision
22
+ title: <the decision, as a statement>
23
+ description: <one sentence>
24
+ tags: [<area>]
25
+ ---
26
+
27
+ # Decision
28
+
29
+ What was decided, concretely.
30
+
31
+ # Assumption
32
+
33
+ What must be true for this to be right, and the evidence for it.
34
+
35
+ # Alternatives considered
36
+
37
+ Briefly, and why they lost.
38
+
39
+ # Reopen if
40
+
41
+ The specific observations that would justify revisiting it.
42
+ ```
43
+
44
+ 3. Link the decision from the concepts it governs (design, tasks) and link to
45
+ the evidence (references, experiments).
46
+ 4. Decisions are the developer's. Record what they decided in their terms; if
47
+ you are proposing a decision, record it with `status: draft` and say so.
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: handoff
3
+ description: Close out a working session so the next session (human or agent) can pick up without re-deriving anything. Use at the end of a session or before a long break.
4
+ ---
5
+
6
+ # Hand off
7
+
8
+ 1. **Decisions** made this session: record each with the `decision` skill.
9
+ 2. **Questions** raised and not answered: record with the `question` skill. Mark any
10
+ answered ones.
11
+ 3. **Tasks**: update the `# Outcome` and state tag of every task touched.
12
+ 4. **Findings and procedures**: record anything learned the hard way with
13
+ the `record-okf` skill. If a repeated process emerged, record or update a
14
+ `type: Procedure` concept.
15
+ 5. **Report**: if substantial work was done, write one with the `report` skill.
16
+ 6. Summarise to the developer in chat: what was recorded (concept ids), what is
17
+ waiting for their review (the rdstudio `review_queue` tool), and the suggested
18
+ next step.
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: ingest-ref
3
+ description: Add a paper or book to the bibliography (papis) and the knowledge base. Use when the developer names a paper, DOI, arXiv id or ISBN to add, or after syncing items captured in Zotero.
4
+ ---
5
+
6
+ # Ingest a reference
7
+
8
+ Requires `[references] backend = "papis"` in `rdstudio.toml`. If a procedure
9
+ concept for adding references exists (search `type: Procedure`), follow it
10
+ with the rdstudio `procedure_next` tool instead of these generic steps; it holds
11
+ this project's conventions and known pitfalls.
12
+
13
+ 1. **Check it is not already there:** search with the rdstudio `ref_search` tool.
14
+ 2. **Add it to papis:** `papis add --from doi <doi>` (or `--from isbn`,
15
+ `--from arxiv`). Run non-interactively with `--batch` where the project's
16
+ procedure says so.
17
+ 3. **Fix the citekey** to the project's convention if papis generated a
18
+ different one: `papis update --batch --set ref <key> <current-ref>`.
19
+ 4. **Check the metadata:** authors split correctly into family and given names,
20
+ year, venue. Fix `author_list`, not the flat `author` field.
21
+ 5. **Create the knowledge stub:** `rdstudio refs sync`.
22
+ 6. **Summarise, if asked:** read only the pages you need with
23
+ the rdstudio `ref_text` tool (by page range or query), then fill the stub's
24
+ `# Summary` and `# Relevance` sections with the `record-okf` skill. Link the
25
+ decisions, questions or designs it bears on.
26
+ 7. Regenerate any exported bibliography the project uses (for example
27
+ `make refs`).
28
+
29
+ ## Items captured in Zotero
30
+
31
+ If the project pulls phone captures from Zotero (for example `make zotero-sync`),
32
+ run that first; the imported items then go through steps 3 to 6.
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: lint-okf
3
+ description: Check the knowledge base for OKF format errors and broken links, and fix what can be fixed. Use after bulk edits or when the dashboard's Review tab shows format errors.
4
+ ---
5
+
6
+ # Lint the knowledge base
7
+
8
+ 1. Run `rdstudio check -w`.
9
+ 2. Fix **errors** (missing frontmatter, missing `type`, frontmatter in a
10
+ non-root `index.md`) with the rdstudio `record` tool or by editing the file.
11
+ 3. **Broken links** point at knowledge that does not exist yet. Do not delete
12
+ them by reflex: list them for the developer as candidate concepts, and fix
13
+ only the ones that are typos or moved files.
14
+ 4. Run `rdstudio index` if indexes are out of date (the MCP server and the
15
+ dashboard server regenerate them automatically).