self-evolve-framework 1.6.0 → 1.6.1

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 (301) hide show
  1. package/README.md +33 -23
  2. package/bin/cli.js +24 -67
  3. package/package.json +1 -1
  4. package/template/rules/knowledge/README.md +56 -0
  5. package/template/rules/knowledge/ant-design-vue.mdc +54 -0
  6. package/template/rules/knowledge/general.mdc +56 -0
  7. package/template/rules/knowledge/rust.mdc +55 -0
  8. package/template/rules/knowledge/shadcn-svelte.mdc +64 -0
  9. package/template/rules/knowledge/svelte.mdc +135 -0
  10. package/template/rules/knowledge/tailwind.mdc +66 -0
  11. package/template/rules/knowledge/tauri.mdc +65 -0
  12. package/template/rules/knowledge/typescript.mdc +41 -0
  13. package/template/rules/knowledge/vue.mdc +48 -0
  14. package/template/rules/ponytail.mdc +23 -98
  15. package/template/rules/self-evolve.mdc +24 -0
  16. package/template/skills/impeccable/SKILL.md +47 -174
  17. package/template/skills/skillopt-sleep/SKILL.md +32 -88
  18. package/template/skills/impeccable/agents/impeccable_asset_producer.toml +0 -92
  19. package/template/skills/impeccable/agents/impeccable_manual_edit_applier.toml +0 -95
  20. package/template/skills/impeccable/agents/openai.yaml +0 -4
  21. package/template/skills/impeccable/reference/adapt.md +0 -311
  22. package/template/skills/impeccable/reference/animate.md +0 -201
  23. package/template/skills/impeccable/reference/audit.md +0 -133
  24. package/template/skills/impeccable/reference/bolder.md +0 -113
  25. package/template/skills/impeccable/reference/brand.md +0 -108
  26. package/template/skills/impeccable/reference/clarify.md +0 -288
  27. package/template/skills/impeccable/reference/codex.md +0 -105
  28. package/template/skills/impeccable/reference/colorize.md +0 -257
  29. package/template/skills/impeccable/reference/craft.md +0 -123
  30. package/template/skills/impeccable/reference/critique.md +0 -790
  31. package/template/skills/impeccable/reference/delight.md +0 -302
  32. package/template/skills/impeccable/reference/distill.md +0 -111
  33. package/template/skills/impeccable/reference/document.md +0 -429
  34. package/template/skills/impeccable/reference/extract.md +0 -69
  35. package/template/skills/impeccable/reference/harden.md +0 -347
  36. package/template/skills/impeccable/reference/hooks.md +0 -90
  37. package/template/skills/impeccable/reference/init.md +0 -172
  38. package/template/skills/impeccable/reference/interaction-design.md +0 -189
  39. package/template/skills/impeccable/reference/layout.md +0 -161
  40. package/template/skills/impeccable/reference/live.md +0 -720
  41. package/template/skills/impeccable/reference/onboard.md +0 -234
  42. package/template/skills/impeccable/reference/optimize.md +0 -258
  43. package/template/skills/impeccable/reference/overdrive.md +0 -130
  44. package/template/skills/impeccable/reference/polish.md +0 -241
  45. package/template/skills/impeccable/reference/product.md +0 -60
  46. package/template/skills/impeccable/reference/quieter.md +0 -99
  47. package/template/skills/impeccable/reference/shape.md +0 -165
  48. package/template/skills/impeccable/reference/typeset.md +0 -279
  49. package/template/skills/impeccable/scripts/command-metadata.json +0 -94
  50. package/template/skills/impeccable/scripts/context-signals.mjs +0 -225
  51. package/template/skills/impeccable/scripts/context.mjs +0 -961
  52. package/template/skills/impeccable/scripts/critique-storage.mjs +0 -242
  53. package/template/skills/impeccable/scripts/detect-csp.mjs +0 -198
  54. package/template/skills/impeccable/scripts/detect.mjs +0 -21
  55. package/template/skills/impeccable/scripts/detector/browser/injected/index.mjs +0 -1937
  56. package/template/skills/impeccable/scripts/detector/cli/main.mjs +0 -290
  57. package/template/skills/impeccable/scripts/detector/design-system.mjs +0 -750
  58. package/template/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +0 -5138
  59. package/template/skills/impeccable/scripts/detector/detect-antipatterns.mjs +0 -50
  60. package/template/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +0 -277
  61. package/template/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +0 -568
  62. package/template/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +0 -1015
  63. package/template/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +0 -234
  64. package/template/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs +0 -189
  65. package/template/skills/impeccable/scripts/detector/findings.mjs +0 -12
  66. package/template/skills/impeccable/scripts/detector/node/file-system.mjs +0 -198
  67. package/template/skills/impeccable/scripts/detector/profile/profiler.mjs +0 -166
  68. package/template/skills/impeccable/scripts/detector/registry/antipatterns.mjs +0 -448
  69. package/template/skills/impeccable/scripts/detector/rules/checks.mjs +0 -2671
  70. package/template/skills/impeccable/scripts/detector/shared/color.mjs +0 -124
  71. package/template/skills/impeccable/scripts/detector/shared/constants.mjs +0 -101
  72. package/template/skills/impeccable/scripts/detector/shared/inline-ignores.mjs +0 -148
  73. package/template/skills/impeccable/scripts/detector/shared/page.mjs +0 -7
  74. package/template/skills/impeccable/scripts/hook-admin.mjs +0 -661
  75. package/template/skills/impeccable/scripts/hook-before-edit.mjs +0 -476
  76. package/template/skills/impeccable/scripts/hook-lib.mjs +0 -1632
  77. package/template/skills/impeccable/scripts/hook.mjs +0 -61
  78. package/template/skills/impeccable/scripts/lib/design-parser.mjs +0 -842
  79. package/template/skills/impeccable/scripts/lib/impeccable-config.mjs +0 -638
  80. package/template/skills/impeccable/scripts/lib/impeccable-paths.mjs +0 -128
  81. package/template/skills/impeccable/scripts/lib/is-generated.mjs +0 -69
  82. package/template/skills/impeccable/scripts/lib/target-args.mjs +0 -42
  83. package/template/skills/impeccable/scripts/live/browser-script-parts.mjs +0 -49
  84. package/template/skills/impeccable/scripts/live/completion.mjs +0 -19
  85. package/template/skills/impeccable/scripts/live/event-validation.mjs +0 -137
  86. package/template/skills/impeccable/scripts/live/insert-ui.mjs +0 -458
  87. package/template/skills/impeccable/scripts/live/manual-apply.mjs +0 -939
  88. package/template/skills/impeccable/scripts/live/manual-edit-routes.mjs +0 -357
  89. package/template/skills/impeccable/scripts/live/manual-edits-buffer.mjs +0 -152
  90. package/template/skills/impeccable/scripts/live/session-store.mjs +0 -289
  91. package/template/skills/impeccable/scripts/live/svelte-component.mjs +0 -826
  92. package/template/skills/impeccable/scripts/live/sveltekit-adapter.mjs +0 -274
  93. package/template/skills/impeccable/scripts/live/ui-core.mjs +0 -180
  94. package/template/skills/impeccable/scripts/live/vocabulary.mjs +0 -36
  95. package/template/skills/impeccable/scripts/live-accept.mjs +0 -812
  96. package/template/skills/impeccable/scripts/live-browser-dom.js +0 -146
  97. package/template/skills/impeccable/scripts/live-browser-session.js +0 -123
  98. package/template/skills/impeccable/scripts/live-browser.js +0 -11173
  99. package/template/skills/impeccable/scripts/live-commit-manual-edits.mjs +0 -1241
  100. package/template/skills/impeccable/scripts/live-complete.mjs +0 -75
  101. package/template/skills/impeccable/scripts/live-copy-edit-agent.mjs +0 -683
  102. package/template/skills/impeccable/scripts/live-discard-manual-edits.mjs +0 -51
  103. package/template/skills/impeccable/scripts/live-inject.mjs +0 -583
  104. package/template/skills/impeccable/scripts/live-insert.mjs +0 -272
  105. package/template/skills/impeccable/scripts/live-manual-edit-evidence.mjs +0 -363
  106. package/template/skills/impeccable/scripts/live-poll.mjs +0 -384
  107. package/template/skills/impeccable/scripts/live-resume.mjs +0 -94
  108. package/template/skills/impeccable/scripts/live-server.mjs +0 -1135
  109. package/template/skills/impeccable/scripts/live-status.mjs +0 -61
  110. package/template/skills/impeccable/scripts/live-target.mjs +0 -30
  111. package/template/skills/impeccable/scripts/live-wrap.mjs +0 -894
  112. package/template/skills/impeccable/scripts/live.mjs +0 -297
  113. package/template/skills/impeccable/scripts/modern-screenshot.umd.js +0 -14
  114. package/template/skills/impeccable/scripts/palette.mjs +0 -633
  115. package/template/skills/impeccable/scripts/pin.mjs +0 -214
  116. package/template/skills/skillopt-sleep/configs/_base_/default.yaml +0 -103
  117. package/template/skills/skillopt-sleep/configs/alfworld/default.yaml +0 -29
  118. package/template/skills/skillopt-sleep/configs/docvqa/default.yaml +0 -28
  119. package/template/skills/skillopt-sleep/configs/features/soft_gate.yaml +0 -47
  120. package/template/skills/skillopt-sleep/configs/livemathematicianbench/default.yaml +0 -22
  121. package/template/skills/skillopt-sleep/configs/officeqa/default.yaml +0 -34
  122. package/template/skills/skillopt-sleep/configs/searchqa/default.yaml +0 -32
  123. package/template/skills/skillopt-sleep/configs/spreadsheetbench/default.yaml +0 -34
  124. package/template/skills/skillopt-sleep/scripts/framework/skillopt/__init__.py +0 -28
  125. package/template/skills/skillopt-sleep/scripts/framework/skillopt/config.py +0 -282
  126. package/template/skills/skillopt-sleep/scripts/framework/skillopt/datasets/__init__.py +0 -7
  127. package/template/skills/skillopt-sleep/scripts/framework/skillopt/datasets/base.py +0 -512
  128. package/template/skills/skillopt-sleep/scripts/framework/skillopt/engine/__init__.py +0 -9
  129. package/template/skills/skillopt-sleep/scripts/framework/skillopt/engine/trainer.py +0 -2379
  130. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/__init__.py +0 -1
  131. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/_template/README.md +0 -43
  132. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/_template/config_template.yaml +0 -55
  133. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/_template/env_template.py +0 -151
  134. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/_template/loader_template.py +0 -87
  135. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/__init__.py +0 -5
  136. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/adapter.py +0 -428
  137. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/dataloader.py +0 -123
  138. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/analyst_error.md +0 -55
  139. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/analyst_success.md +0 -33
  140. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/rollout_no_history.md +0 -8
  141. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/rollout_with_history.md +0 -9
  142. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/rollout_with_memory.md +0 -16
  143. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/reflect.py +0 -4
  144. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/rollout.py +0 -366
  145. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/skills/initial.md +0 -45
  146. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/__init__.py +0 -9
  147. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/alfworld_envs.py +0 -221
  148. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/alfworld_projection.py +0 -60
  149. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/alfworld_prompts.py +0 -8
  150. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/config_tw.yaml +0 -145
  151. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/env_base.py +0 -84
  152. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/env_manager.py +0 -139
  153. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/memory.py +0 -87
  154. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/base.py +0 -329
  155. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/__init__.py +0 -1
  156. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/adapter.py +0 -90
  157. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/dataloader.py +0 -61
  158. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/evaluator.py +0 -113
  159. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/prompts/analyst_error.md +0 -35
  160. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/prompts/analyst_success.md +0 -24
  161. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/prompts/rollout_system.md +0 -12
  162. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/rollout.py +0 -391
  163. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/skills/initial.md +0 -11
  164. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/__init__.py +0 -1
  165. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/adapter.py +0 -129
  166. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/dataloader.py +0 -308
  167. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/evaluator.py +0 -62
  168. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/prompts/analyst_error.md +0 -37
  169. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/prompts/analyst_success.md +0 -25
  170. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/prompts/rollout_system.md +0 -12
  171. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/reflect.py +0 -4
  172. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/rollout.py +0 -434
  173. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/skills/initial.md +0 -16
  174. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/__init__.py +0 -1
  175. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/adapter.py +0 -112
  176. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/dataloader.py +0 -71
  177. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/evaluator.py +0 -46
  178. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/prompts/analyst_error.md +0 -37
  179. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/prompts/analyst_success.md +0 -25
  180. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/prompts/rollout_system.md +0 -15
  181. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/rollout.py +0 -799
  182. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/skills/initial.md +0 -15
  183. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/tool_runtime.py +0 -552
  184. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/__init__.py +0 -1
  185. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/adapter.py +0 -96
  186. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/dataloader.py +0 -42
  187. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/evaluator.py +0 -100
  188. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/prompts/analyst_error.md +0 -46
  189. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/prompts/analyst_success.md +0 -32
  190. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/prompts/rollout_system.md +0 -13
  191. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/reflect.py +0 -4
  192. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/rollout.py +0 -494
  193. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/skills/initial.md +0 -3
  194. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/__init__.py +0 -5
  195. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/adapter.py +0 -159
  196. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/codegen_agent.py +0 -731
  197. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/dataloader.py +0 -37
  198. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/evaluator.py +0 -158
  199. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/executor.py +0 -67
  200. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/analyst_error.md +0 -46
  201. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/analyst_success.md +0 -32
  202. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/codegen_system.md +0 -1
  203. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/critical_rules.md +0 -9
  204. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/react_system.md +0 -21
  205. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/react_agent.py +0 -395
  206. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/reflect.py +0 -4
  207. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/rollout.py +0 -979
  208. package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/skills/initial.md +0 -56
  209. package/template/skills/skillopt-sleep/scripts/framework/skillopt/evaluation/__init__.py +0 -13
  210. package/template/skills/skillopt-sleep/scripts/framework/skillopt/evaluation/gate.py +0 -148
  211. package/template/skills/skillopt-sleep/scripts/framework/skillopt/gradient/__init__.py +0 -15
  212. package/template/skills/skillopt-sleep/scripts/framework/skillopt/gradient/aggregate.py +0 -253
  213. package/template/skills/skillopt-sleep/scripts/framework/skillopt/gradient/reflect.py +0 -635
  214. package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/__init__.py +0 -514
  215. package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/azure_openai.py +0 -915
  216. package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/backend_config.py +0 -185
  217. package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/claude_backend.py +0 -371
  218. package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/codex_backend.py +0 -666
  219. package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/codex_harness.py +0 -1057
  220. package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/common.py +0 -229
  221. package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/minimax_backend.py +0 -277
  222. package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/qwen_backend.py +0 -456
  223. package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/router.py +0 -236
  224. package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/__init__.py +0 -15
  225. package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/appendix.py +0 -156
  226. package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/clip.py +0 -109
  227. package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/lr_autonomous.py +0 -108
  228. package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/meta_skill.py +0 -79
  229. package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/rewrite.py +0 -59
  230. package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/scheduler.py +0 -127
  231. package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/select.py +0 -4
  232. package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/skill.py +0 -201
  233. package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/skill_aware.py +0 -206
  234. package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/slow_update.py +0 -396
  235. package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/update_modes.py +0 -135
  236. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/__init__.py +0 -63
  237. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_error.md +0 -41
  238. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_error_full_rewrite.md +0 -32
  239. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_error_rewrite.md +0 -44
  240. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_success.md +0 -36
  241. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_success_full_rewrite.md +0 -30
  242. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_success_rewrite.md +0 -33
  243. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/lr_autonomous.md +0 -20
  244. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_failure.md +0 -30
  245. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_failure_full_rewrite.md +0 -28
  246. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_failure_rewrite.md +0 -26
  247. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_final.md +0 -33
  248. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_final_full_rewrite.md +0 -28
  249. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_final_rewrite.md +0 -25
  250. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_success.md +0 -28
  251. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_success_full_rewrite.md +0 -28
  252. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_success_rewrite.md +0 -25
  253. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/meta_skill.md +0 -40
  254. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/ranking.md +0 -20
  255. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/ranking_rewrite.md +0 -15
  256. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/rewrite_skill.md +0 -25
  257. package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/slow_update.md +0 -60
  258. package/template/skills/skillopt-sleep/scripts/framework/skillopt/scheduler/__init__.py +0 -8
  259. package/template/skills/skillopt-sleep/scripts/framework/skillopt/types.py +0 -306
  260. package/template/skills/skillopt-sleep/scripts/framework/skillopt/utils/__init__.py +0 -4
  261. package/template/skills/skillopt-sleep/scripts/framework/skillopt/utils/json_utils.py +0 -172
  262. package/template/skills/skillopt-sleep/scripts/framework/skillopt/utils/scoring.py +0 -28
  263. package/template/skills/skillopt-sleep/scripts/python/__init__.py +0 -20
  264. package/template/skills/skillopt-sleep/scripts/python/__main__.py +0 -343
  265. package/template/skills/skillopt-sleep/scripts/python/backend.py +0 -1371
  266. package/template/skills/skillopt-sleep/scripts/python/budget.py +0 -75
  267. package/template/skills/skillopt-sleep/scripts/python/config.py +0 -162
  268. package/template/skills/skillopt-sleep/scripts/python/consolidate.py +0 -238
  269. package/template/skills/skillopt-sleep/scripts/python/cycle.py +0 -291
  270. package/template/skills/skillopt-sleep/scripts/python/dream.py +0 -138
  271. package/template/skills/skillopt-sleep/scripts/python/experiments/__init__.py +0 -1
  272. package/template/skills/skillopt-sleep/scripts/python/experiments/gbrain_bench.py +0 -119
  273. package/template/skills/skillopt-sleep/scripts/python/experiments/personas.py +0 -86
  274. package/template/skills/skillopt-sleep/scripts/python/experiments/report.py +0 -132
  275. package/template/skills/skillopt-sleep/scripts/python/experiments/run_experiment.py +0 -178
  276. package/template/skills/skillopt-sleep/scripts/python/experiments/run_gbrain.py +0 -209
  277. package/template/skills/skillopt-sleep/scripts/python/experiments/run_transfer.py +0 -155
  278. package/template/skills/skillopt-sleep/scripts/python/experiments/sweep.py +0 -164
  279. package/template/skills/skillopt-sleep/scripts/python/gate.py +0 -50
  280. package/template/skills/skillopt-sleep/scripts/python/harvest.py +0 -304
  281. package/template/skills/skillopt-sleep/scripts/python/harvest_codex.py +0 -253
  282. package/template/skills/skillopt-sleep/scripts/python/harvest_sources.py +0 -41
  283. package/template/skills/skillopt-sleep/scripts/python/judges.py +0 -84
  284. package/template/skills/skillopt-sleep/scripts/python/llm_miner.py +0 -134
  285. package/template/skills/skillopt-sleep/scripts/python/memory.py +0 -129
  286. package/template/skills/skillopt-sleep/scripts/python/mine.py +0 -312
  287. package/template/skills/skillopt-sleep/scripts/python/replay.py +0 -146
  288. package/template/skills/skillopt-sleep/scripts/python/rollout.py +0 -153
  289. package/template/skills/skillopt-sleep/scripts/python/scheduler.py +0 -138
  290. package/template/skills/skillopt-sleep/scripts/python/slow_update.py +0 -142
  291. package/template/skills/skillopt-sleep/scripts/python/staging.py +0 -103
  292. package/template/skills/skillopt-sleep/scripts/python/state.py +0 -96
  293. package/template/skills/skillopt-sleep/scripts/python/tasks_file.py +0 -81
  294. package/template/skills/skillopt-sleep/scripts/python/types.py +0 -146
  295. package/template/skills/skillopt-sleep/scripts/shell/__init__.py +0 -0
  296. package/template/skills/skillopt-sleep/scripts/shell/eval_only.py +0 -466
  297. package/template/skills/skillopt-sleep/scripts/shell/materialize_searchqa.py +0 -148
  298. package/template/skills/skillopt-sleep/scripts/shell/run_alfworld.sh +0 -60
  299. package/template/skills/skillopt-sleep/scripts/shell/run_searchqa.sh +0 -40
  300. package/template/skills/skillopt-sleep/scripts/shell/run_spreadsheetbench.sh +0 -39
  301. package/template/skills/skillopt-sleep/scripts/shell/train.py +0 -556
@@ -1,164 +0,0 @@
1
- """SkillOpt-Sleep — benchmark sweep driver.
2
-
3
- Runs many (backend, model, seed, transfer-pair) configurations SEQUENTIALLY in
4
- one process, appending each result to a JSONL file as it finishes. Designed to
5
- run unattended in the background; safe to interrupt (already-written rows
6
- survive) and resume (skip configs whose row already exists).
7
-
8
- Then `report.py` turns the JSONL into a presented Markdown scorecard.
9
-
10
- Usage:
11
- python -m skillopt_sleep.experiments.sweep --plan quick --out docs/sleep/sweep.jsonl
12
- python -m skillopt_sleep.experiments.sweep --plan full --out docs/sleep/sweep.jsonl
13
- """
14
- from __future__ import annotations
15
-
16
- import argparse
17
- import json
18
- import os
19
- import sys
20
- import time
21
- from typing import Any, Dict, List
22
-
23
- from skillopt_sleep.backend import build_backend, get_backend
24
- from skillopt_sleep.experiments.gbrain_bench import find_data_root, load_seed
25
- from skillopt_sleep.experiments.run_gbrain import run_seed as bench_seed
26
- from skillopt_sleep.experiments.run_transfer import run_seed as transfer_seed
27
-
28
-
29
- # Plans: lists of config dicts. Kept small per-run to bound cost/latency.
30
- def _direct_cfg(backend, model, seed, nights=2):
31
- return {"kind": "direct", "backend": backend, "model": model, "seed": seed, "nights": nights}
32
-
33
-
34
- def _dual_cfg(opt_backend, opt_model, tgt_backend, tgt_model, seed, nights=2):
35
- # a 'direct' run on a DualBackend: strong optimizer proposes, weak target runs
36
- return {"kind": "dual", "optimizer_backend": opt_backend, "optimizer_model": opt_model,
37
- "target_backend": tgt_backend, "target_model": tgt_model, "seed": seed, "nights": nights}
38
-
39
-
40
- def _transfer_cfg(sb, sm, tb, tm, seed, nights=2):
41
- return {"kind": "transfer", "source_backend": sb, "source_model": sm,
42
- "target_backend": tb, "target_model": tm, "seed": seed, "nights": nights}
43
-
44
-
45
- PLANS: Dict[str, List[Dict[str, Any]]] = {
46
- # one cheap seed each, both backends — fast sanity
47
- "quick": [
48
- _direct_cfg("claude", "haiku", "brief-writer", 1),
49
- _direct_cfg("codex", "", "brief-writer", 2),
50
- ],
51
- # SkillOpt-faithful: STRONG optimizer (sonnet) proposes, WEAK target (haiku)
52
- # runs — the reliable config. Plus Codex self-optimized. All 4 gbrain seeds,
53
- # including quick-answerer (real tool loop).
54
- "direct": [
55
- _dual_cfg("claude", "sonnet", "claude", "haiku", "brief-writer"),
56
- _dual_cfg("claude", "sonnet", "claude", "haiku", "advisor"),
57
- _dual_cfg("claude", "sonnet", "claude", "haiku", "thorough-analyst"),
58
- _dual_cfg("claude", "sonnet", "claude", "haiku", "quick-answerer"),
59
- _direct_cfg("codex", "", "brief-writer"),
60
- _direct_cfg("codex", "", "advisor"),
61
- _direct_cfg("codex", "", "quick-answerer"),
62
- ],
63
- # the price-difference story: optimize cheap, deploy expensive (and reverse)
64
- "transfer": [
65
- _transfer_cfg("claude", "haiku", "claude", "sonnet", "brief-writer"),
66
- _transfer_cfg("claude", "sonnet", "claude", "haiku", "brief-writer"),
67
- _transfer_cfg("codex", "", "claude", "haiku", "brief-writer"),
68
- _transfer_cfg("claude", "haiku", "codex", "", "brief-writer"),
69
- ],
70
- }
71
- PLANS["full"] = PLANS["direct"] + PLANS["transfer"]
72
-
73
-
74
- def _cfg_key(c: Dict[str, Any]) -> str:
75
- return json.dumps({k: c[k] for k in sorted(c)}, ensure_ascii=False)
76
-
77
-
78
- def _load_done(out_path: str) -> set:
79
- done = set()
80
- if os.path.exists(out_path):
81
- with open(out_path) as f:
82
- for line in f:
83
- try:
84
- row = json.loads(line)
85
- if "cfg_key" in row:
86
- done.add(row["cfg_key"])
87
- except Exception:
88
- pass
89
- return done
90
-
91
-
92
- def _append(out_path: str, row: Dict[str, Any]) -> None:
93
- os.makedirs(os.path.dirname(out_path) or ".", exist_ok=True)
94
- with open(out_path, "a") as f:
95
- f.write(json.dumps(row, ensure_ascii=False) + "\n")
96
-
97
-
98
- def run_one(cfg: Dict[str, Any], data_root: str, codex_path: str,
99
- limit_replay: int, limit_holdout: int) -> Dict[str, Any]:
100
- seed = cfg["seed"]
101
- skill, tasks = load_seed(data_root, seed)
102
- t0 = time.time()
103
- if cfg["kind"] in ("direct", "dual"):
104
- if cfg["kind"] == "dual":
105
- be = build_backend(
106
- optimizer_backend=cfg["optimizer_backend"], optimizer_model=cfg.get("optimizer_model", ""),
107
- target_backend=cfg["target_backend"], target_model=cfg.get("target_model", ""),
108
- codex_path=codex_path,
109
- )
110
- else:
111
- be = get_backend(cfg["backend"], model=cfg.get("model", ""), codex_path=codex_path)
112
- r = bench_seed(be, seed, skill, tasks, nights=cfg["nights"],
113
- limit_replay=limit_replay, limit_holdout=limit_holdout)
114
- out = {"baseline": r["held_out_before"], "after": r["held_out_after"],
115
- "improved": r["improved"], "tokens": be.tokens_used()}
116
- else:
117
- src = get_backend(cfg["source_backend"], model=cfg.get("source_model", ""), codex_path=codex_path)
118
- tgt = get_backend(cfg["target_backend"], model=cfg.get("target_model", ""), codex_path=codex_path)
119
- r = transfer_seed(seed, skill, tasks, source=src, target=tgt, nights=cfg["nights"],
120
- edit_budget=4, limit_replay=limit_replay, limit_holdout=limit_holdout,
121
- do_direct=False)
122
- out = {"baseline_target": r["baseline_target"], "transferred": r["transferred"],
123
- "transfer_gain": r["transfer_gain"],
124
- "tokens": src.tokens_used() + tgt.tokens_used()}
125
- out.update({"cfg": cfg, "cfg_key": _cfg_key(cfg), "elapsed_s": round(time.time() - t0, 1)})
126
- return out
127
-
128
-
129
- def main(argv=None) -> int:
130
- ap = argparse.ArgumentParser(description="SkillOpt-Sleep benchmark sweep")
131
- ap.add_argument("--plan", default="quick", choices=list(PLANS.keys()))
132
- ap.add_argument("--out", default="docs/sleep/sweep.jsonl")
133
- ap.add_argument("--data-root", default="")
134
- ap.add_argument("--codex-path", default="")
135
- ap.add_argument("--limit-replay", type=int, default=3)
136
- ap.add_argument("--limit-holdout", type=int, default=3)
137
- args = ap.parse_args(argv)
138
-
139
- data_root = find_data_root(args.data_root)
140
- if not data_root:
141
- print("ERROR: gbrain-evals data not found; pass --data-root", file=sys.stderr)
142
- return 2
143
-
144
- plan = PLANS[args.plan]
145
- done = _load_done(args.out)
146
- print(f"[sweep] plan={args.plan} configs={len(plan)} already_done={len(done)} -> {args.out}")
147
- for i, cfg in enumerate(plan, 1):
148
- key = _cfg_key(cfg)
149
- if key in done:
150
- print(f"[sweep] ({i}/{len(plan)}) skip (done): {cfg}")
151
- continue
152
- print(f"[sweep] ({i}/{len(plan)}) running: {cfg}", flush=True)
153
- try:
154
- row = run_one(cfg, data_root, args.codex_path, args.limit_replay, args.limit_holdout)
155
- except Exception as e: # never let one config kill the sweep
156
- row = {"cfg": cfg, "cfg_key": key, "error": f"{type(e).__name__}: {e}"}
157
- _append(args.out, row)
158
- print(f"[sweep] -> {json.dumps({k: v for k, v in row.items() if k not in ('cfg','cfg_key')})}", flush=True)
159
- print(f"[sweep] done. rows in {args.out}: {len(_load_done(args.out))}")
160
- return 0
161
-
162
-
163
- if __name__ == "__main__":
164
- sys.exit(main())
@@ -1,50 +0,0 @@
1
- """SkillOpt-Sleep — vendored validation gate.
2
-
3
- This is a self-contained copy of the SkillOpt validation gate so the sleep
4
- engine has ZERO dependency on the research package (skillopt/*). The research
5
- repo's ``skillopt.evaluation.gate`` is the reference implementation and the two
6
- are kept behaviourally identical; vendoring keeps this open-source tool
7
- decoupled from the paper's experiment code.
8
- """
9
- from __future__ import annotations
10
-
11
- from dataclasses import dataclass
12
-
13
-
14
- @dataclass(frozen=True)
15
- class GateResult:
16
- action: str # "accept_new_best" | "accept" | "reject"
17
- current_skill: str
18
- current_score: float
19
- best_skill: str
20
- best_score: float
21
- best_step: int
22
-
23
-
24
- def select_gate_score(hard: float, soft: float, metric: str = "hard",
25
- mixed_weight: float = 0.5) -> float:
26
- """Project (hard, soft) onto a single comparison metric."""
27
- if metric == "hard":
28
- return float(hard)
29
- if metric == "soft":
30
- return float(soft)
31
- if metric == "mixed":
32
- w = max(0.0, min(1.0, float(mixed_weight)))
33
- return (1.0 - w) * float(hard) + w * float(soft)
34
- raise ValueError(f"unknown gate metric {metric!r}; expected hard/soft/mixed")
35
-
36
-
37
- def evaluate_gate(candidate_skill: str, cand_hard: float, current_skill: str,
38
- current_score: float, best_skill: str, best_score: float,
39
- best_step: int, global_step: int, *, cand_soft: float = 0.0,
40
- metric: str = "hard", mixed_weight: float = 0.5) -> GateResult:
41
- """Pure gate decision: compare candidate score to current/best."""
42
- cand_score = select_gate_score(cand_hard, cand_soft, metric, mixed_weight)
43
- if cand_score > current_score:
44
- if cand_score > best_score:
45
- return GateResult("accept_new_best", candidate_skill, cand_score,
46
- candidate_skill, cand_score, global_step)
47
- return GateResult("accept", candidate_skill, cand_score,
48
- best_skill, best_score, best_step)
49
- return GateResult("reject", current_skill, current_score,
50
- best_skill, best_score, best_step)
@@ -1,304 +0,0 @@
1
- """SkillOpt-Sleep — Stage 1: harvest.
2
-
3
- Read the user's local Claude Code records (read-only) and normalize them
4
- into :class:`SessionDigest` objects.
5
-
6
- Sources (verified schema):
7
- * ~/.claude/history.jsonl — one JSON/line:
8
- {"display": <prompt text>, "pastedContents": {...},
9
- "timestamp": <epoch ms>, "project": <abs path>}
10
- * ~/.claude/projects/<slug>/<sessionId>.jsonl — one record/line; the
11
- records we care about have type "user"/"assistant" and carry:
12
- message{role, content}, cwd, gitBranch, timestamp, sessionId, version
13
-
14
- This module performs NO writes and NO network calls.
15
- """
16
- from __future__ import annotations
17
-
18
- import json
19
- import os
20
- from datetime import datetime
21
- from typing import Any, Dict, Iterable, List, Optional
22
-
23
- from skillopt_sleep.types import SessionDigest
24
-
25
-
26
- # Heuristic phrases that signal the user (dis)approving of prior output.
27
- # English-only by default. Users whose sessions are in another language can add
28
- # their own phrases via the SKILLOPT_SLEEP_NEG_FEEDBACK / _POS_FEEDBACK env vars
29
- # (comma-separated), so the capability is extensible without hardcoding locales.
30
- _NEGATIVE_FEEDBACK = (
31
- "still broken", "still not", "still wrong", "doesn't work", "does not work",
32
- "not working", "that's wrong", "thats wrong", "incorrect", "wrong",
33
- "no,", "nope", "fix it", "didn't", "did not", "broken", "error again",
34
- "still failing", "still fails", "not fixed", "revert", "undo",
35
- )
36
- _POSITIVE_FEEDBACK = (
37
- "thanks", "thank you", "perfect", "great", "works now", "fixed",
38
- "that works", "lgtm", "looks good", "nice", "awesome", "correct",
39
- )
40
-
41
-
42
- def _extra_phrases(env_var: str) -> tuple:
43
- raw = os.environ.get(env_var, "")
44
- return tuple(p.strip().lower() for p in raw.split(",") if p.strip())
45
-
46
-
47
- _NEGATIVE_FEEDBACK = _NEGATIVE_FEEDBACK + _extra_phrases("SKILLOPT_SLEEP_NEG_FEEDBACK")
48
- _POSITIVE_FEEDBACK = _POSITIVE_FEEDBACK + _extra_phrases("SKILLOPT_SLEEP_POS_FEEDBACK")
49
-
50
-
51
- def _iter_jsonl(path: str) -> Iterable[Dict[str, Any]]:
52
- try:
53
- with open(path, encoding="utf-8") as f:
54
- for line in f:
55
- line = line.strip()
56
- if not line:
57
- continue
58
- try:
59
- yield json.loads(line)
60
- except Exception:
61
- continue
62
- except (FileNotFoundError, IsADirectoryError, PermissionError):
63
- return
64
-
65
-
66
- def _text_from_content(content: Any) -> str:
67
- """Flatten a message.content (str or list of blocks) into text."""
68
- if isinstance(content, str):
69
- return content
70
- if isinstance(content, list):
71
- parts: List[str] = []
72
- for b in content:
73
- if isinstance(b, dict):
74
- if b.get("type") == "text" and b.get("text"):
75
- parts.append(str(b["text"]))
76
- return "\n".join(parts)
77
- return ""
78
-
79
-
80
- def _tool_names_from_content(content: Any) -> List[str]:
81
- names: List[str] = []
82
- if isinstance(content, list):
83
- for b in content:
84
- if isinstance(b, dict) and b.get("type") == "tool_use" and b.get("name"):
85
- names.append(str(b["name"]))
86
- return names
87
-
88
-
89
- def _detect_feedback(text: str) -> List[str]:
90
- low = text.lower()
91
- sig: List[str] = []
92
- for ph in _NEGATIVE_FEEDBACK:
93
- if ph in low:
94
- sig.append("neg:" + ph)
95
- for ph in _POSITIVE_FEEDBACK:
96
- if ph in low:
97
- sig.append("pos:" + ph)
98
- return sig
99
-
100
-
101
- def _is_meta_prompt(text: str) -> bool:
102
- """Skip slash-commands / system noise that aren't real user intents."""
103
- t = text.strip()
104
- if not t:
105
- return True
106
- if t.startswith("<") and t.endswith(">"):
107
- return True
108
- if t.startswith("/") and len(t.split()) <= 3:
109
- return True
110
- if t.startswith("[Pasted text") or t.startswith("Caveat:"):
111
- return True
112
- return False
113
-
114
-
115
- # ── Issue #62: filter headless replay sessions ─────────────────────────
116
-
117
- # Prompt markers generated by the engine's own headless `claude -p` calls
118
- # (judge, reflect, attempt). If the sole user prompt in a single-turn
119
- # session matches any of these, the session is engine-generated, not a
120
- # real user task.
121
- _REPLAY_PROMPT_MARKERS = (
122
- "## CURRENT SKILL",
123
- "## FAILED TASKS",
124
- "## SUCCESSFUL TASKS",
125
- "## OUTPUT FORMAT",
126
- "You are a strict grader",
127
- "Score the response 0.0-1.0",
128
- "You are SkillOpt-Sleep",
129
- "## TASK\n",
130
- "## SKILL\n",
131
- )
132
-
133
-
134
- def _is_headless_replay(digest: "SessionDigest") -> bool:
135
- """Detect sessions created by the engine's own headless replay calls.
136
-
137
- Heuristics (conservatively applied):
138
- 1. Session has exactly 1 user turn AND
139
- 2. The sole prompt matches engine-generated patterns (grader/reflect),
140
- OR the session lasted < 3 seconds (programmatic, not interactive).
141
- Multi-turn sessions are always kept (interactive by definition).
142
- """
143
- if digest.n_user_turns > 1:
144
- return False
145
- if digest.n_user_turns == 0:
146
- return True
147
- prompt = digest.user_prompts[0] if digest.user_prompts else ""
148
- for marker in _REPLAY_PROMPT_MARKERS:
149
- if marker in prompt:
150
- return True
151
- # Sub-3-second single-turn sessions with short prompts are almost
152
- # certainly programmatic (engine grader/judge calls). We require the
153
- # prompt to also be short (<200 chars) to avoid false-positives on
154
- # real one-shot questions that Claude happens to answer quickly.
155
- if digest.started_at and digest.ended_at and len(prompt) < 200:
156
- try:
157
- fmt = "%Y-%m-%dT%H:%M:%S"
158
- start = datetime.strptime(digest.started_at[:19], fmt)
159
- end = datetime.strptime(digest.ended_at[:19], fmt)
160
- if (end - start).total_seconds() < 3:
161
- return True
162
- except (ValueError, TypeError):
163
- pass
164
- return False
165
-
166
-
167
- def digest_transcript(path: str) -> Optional[SessionDigest]:
168
- """Build a SessionDigest from one ``<sessionId>.jsonl`` transcript."""
169
- session_id = os.path.splitext(os.path.basename(path))[0]
170
- project = ""
171
- git_branch = ""
172
- started = ""
173
- ended = ""
174
- user_prompts: List[str] = []
175
- assistant_finals: List[str] = []
176
- tools: List[str] = []
177
- files: List[str] = []
178
- feedback: List[str] = []
179
- n_user = 0
180
- n_asst = 0
181
-
182
- for rec in _iter_jsonl(path):
183
- rtype = rec.get("type")
184
- ts = rec.get("timestamp")
185
- if isinstance(ts, str) and ts:
186
- if not started:
187
- started = ts
188
- ended = ts
189
- if rec.get("cwd") and not project:
190
- project = str(rec.get("cwd"))
191
- if rec.get("gitBranch") and not git_branch:
192
- git_branch = str(rec.get("gitBranch"))
193
- if rtype == "file-history-snapshot":
194
- snap = rec.get("snapshot") or rec.get("files") or {}
195
- if isinstance(snap, dict):
196
- files.extend([str(k) for k in list(snap.keys())[:20]])
197
- msg = rec.get("message")
198
- if not isinstance(msg, dict):
199
- continue
200
- role = msg.get("role")
201
- content = msg.get("content")
202
- if role == "user":
203
- text = _text_from_content(content)
204
- if text and not _is_meta_prompt(text):
205
- n_user += 1
206
- user_prompts.append(text.strip())
207
- feedback.extend(_detect_feedback(text))
208
- elif role == "assistant":
209
- n_asst += 1
210
- tools.extend(_tool_names_from_content(content))
211
- text = _text_from_content(content)
212
- if text.strip():
213
- assistant_finals.append(text.strip())
214
-
215
- if n_user == 0 and n_asst == 0:
216
- return None
217
-
218
- # de-dup tools/files preserving order
219
- def _dedup(xs: List[str]) -> List[str]:
220
- seen = set()
221
- out = []
222
- for x in xs:
223
- if x not in seen:
224
- seen.add(x)
225
- out.append(x)
226
- return out
227
-
228
- return SessionDigest(
229
- session_id=session_id,
230
- project=project,
231
- git_branch=git_branch,
232
- started_at=started,
233
- ended_at=ended,
234
- user_prompts=user_prompts,
235
- assistant_finals=assistant_finals[-5:], # last few finals are the useful ones
236
- tools_used=_dedup(tools),
237
- files_touched=_dedup(files),
238
- feedback_signals=feedback,
239
- n_user_turns=n_user,
240
- n_assistant_turns=n_asst,
241
- raw_path=path,
242
- )
243
-
244
-
245
- def _project_matches(project: str, scope: Any, invoked: str) -> bool:
246
- if scope == "all":
247
- return True
248
- if isinstance(scope, (list, tuple)):
249
- return any(os.path.abspath(project) == os.path.abspath(p) for p in scope)
250
- # "invoked": match the invoked project (or a subdir of it)
251
- if not invoked:
252
- return True
253
- a = os.path.abspath(project)
254
- b = os.path.abspath(invoked)
255
- return a == b or a.startswith(b + os.sep) or b.startswith(a + os.sep)
256
-
257
-
258
- def harvest(
259
- transcripts_dir: str,
260
- *,
261
- scope: Any = "all",
262
- invoked_project: str = "",
263
- since_iso: Optional[str] = None,
264
- limit: int = 0,
265
- ) -> List[SessionDigest]:
266
- """Walk ~/.claude/projects and return digests matching scope/time.
267
-
268
- Parameters
269
- ----------
270
- transcripts_dir : str ~/.claude/projects
271
- scope : "all" | "invoked" | list[path]
272
- invoked_project : str used when scope == "invoked"
273
- since_iso : str|None ISO8601; only sessions ending after this are kept
274
- limit : int cap number of digests (0 = no cap)
275
- """
276
- digests: List[SessionDigest] = []
277
- if not os.path.isdir(transcripts_dir):
278
- return digests
279
-
280
- paths: List[str] = []
281
- for root, _dirs, files in os.walk(transcripts_dir):
282
- for fn in files:
283
- if fn.endswith(".jsonl"):
284
- paths.append(os.path.join(root, fn))
285
- # newest first by mtime
286
- paths.sort(key=lambda p: os.path.getmtime(p), reverse=True)
287
-
288
- for p in paths:
289
- d = digest_transcript(p)
290
- if d is None:
291
- continue
292
- if _is_headless_replay(d):
293
- continue # Issue #62: skip engine's own headless replay sessions
294
- if not _project_matches(d.project or "", scope, invoked_project):
295
- continue
296
- if since_iso and d.ended_at and d.ended_at < since_iso:
297
- # Note: files are sorted by mtime but we compare the embedded
298
- # ended_at timestamp — mtime can diverge (copy/touch), so we
299
- # cannot break here; we must continue to check all files.
300
- continue
301
- digests.append(d)
302
- if limit and len(digests) >= limit:
303
- break
304
- return digests