@blxzer/cursor-trellis 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (687) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/LICENSE +235 -0
  3. package/README.md +9 -0
  4. package/bin/smart-search.js +79 -0
  5. package/bin/trellis.js +3 -0
  6. package/dist/cli/index.d.ts +3 -0
  7. package/dist/cli/index.d.ts.map +1 -0
  8. package/dist/cli/index.js +258 -0
  9. package/dist/cli/index.js.map +1 -0
  10. package/dist/commands/channel/adapters/claude.d.ts +29 -0
  11. package/dist/commands/channel/adapters/claude.d.ts.map +1 -0
  12. package/dist/commands/channel/adapters/claude.js +203 -0
  13. package/dist/commands/channel/adapters/claude.js.map +1 -0
  14. package/dist/commands/channel/adapters/codex.d.ts +85 -0
  15. package/dist/commands/channel/adapters/codex.d.ts.map +1 -0
  16. package/dist/commands/channel/adapters/codex.js +505 -0
  17. package/dist/commands/channel/adapters/codex.js.map +1 -0
  18. package/dist/commands/channel/adapters/index.d.ts +84 -0
  19. package/dist/commands/channel/adapters/index.d.ts.map +1 -0
  20. package/dist/commands/channel/adapters/index.js +115 -0
  21. package/dist/commands/channel/adapters/index.js.map +1 -0
  22. package/dist/commands/channel/adapters/types.d.ts +33 -0
  23. package/dist/commands/channel/adapters/types.d.ts.map +1 -0
  24. package/dist/commands/channel/adapters/types.js +2 -0
  25. package/dist/commands/channel/adapters/types.js.map +1 -0
  26. package/dist/commands/channel/agent-loader.d.ts +32 -0
  27. package/dist/commands/channel/agent-loader.d.ts.map +1 -0
  28. package/dist/commands/channel/agent-loader.js +154 -0
  29. package/dist/commands/channel/agent-loader.js.map +1 -0
  30. package/dist/commands/channel/context-loader.d.ts +26 -0
  31. package/dist/commands/channel/context-loader.d.ts.map +1 -0
  32. package/dist/commands/channel/context-loader.js +290 -0
  33. package/dist/commands/channel/context-loader.js.map +1 -0
  34. package/dist/commands/channel/context.d.ts +16 -0
  35. package/dist/commands/channel/context.d.ts.map +1 -0
  36. package/dist/commands/channel/context.js +83 -0
  37. package/dist/commands/channel/context.js.map +1 -0
  38. package/dist/commands/channel/create.d.ts +27 -0
  39. package/dist/commands/channel/create.d.ts.map +1 -0
  40. package/dist/commands/channel/create.js +39 -0
  41. package/dist/commands/channel/create.js.map +1 -0
  42. package/dist/commands/channel/dev-parse-trace.d.ts +14 -0
  43. package/dist/commands/channel/dev-parse-trace.d.ts.map +1 -0
  44. package/dist/commands/channel/dev-parse-trace.js +70 -0
  45. package/dist/commands/channel/dev-parse-trace.js.map +1 -0
  46. package/dist/commands/channel/guard.d.ts +150 -0
  47. package/dist/commands/channel/guard.d.ts.map +1 -0
  48. package/dist/commands/channel/guard.js +474 -0
  49. package/dist/commands/channel/guard.js.map +1 -0
  50. package/dist/commands/channel/index.d.ts +3 -0
  51. package/dist/commands/channel/index.d.ts.map +1 -0
  52. package/dist/commands/channel/index.js +531 -0
  53. package/dist/commands/channel/index.js.map +1 -0
  54. package/dist/commands/channel/interrupt.d.ts +10 -0
  55. package/dist/commands/channel/interrupt.d.ts.map +1 -0
  56. package/dist/commands/channel/interrupt.js +22 -0
  57. package/dist/commands/channel/interrupt.js.map +1 -0
  58. package/dist/commands/channel/kill.d.ts +7 -0
  59. package/dist/commands/channel/kill.d.ts.map +1 -0
  60. package/dist/commands/channel/kill.js +121 -0
  61. package/dist/commands/channel/kill.js.map +1 -0
  62. package/dist/commands/channel/list.d.ts +17 -0
  63. package/dist/commands/channel/list.d.ts.map +1 -0
  64. package/dist/commands/channel/list.js +233 -0
  65. package/dist/commands/channel/list.js.map +1 -0
  66. package/dist/commands/channel/messages.d.ts +15 -0
  67. package/dist/commands/channel/messages.d.ts.map +1 -0
  68. package/dist/commands/channel/messages.js +245 -0
  69. package/dist/commands/channel/messages.js.map +1 -0
  70. package/dist/commands/channel/rm.d.ts +27 -0
  71. package/dist/commands/channel/rm.d.ts.map +1 -0
  72. package/dist/commands/channel/rm.js +216 -0
  73. package/dist/commands/channel/rm.js.map +1 -0
  74. package/dist/commands/channel/run.d.ts +30 -0
  75. package/dist/commands/channel/run.d.ts.map +1 -0
  76. package/dist/commands/channel/run.js +130 -0
  77. package/dist/commands/channel/run.js.map +1 -0
  78. package/dist/commands/channel/send.d.ts +11 -0
  79. package/dist/commands/channel/send.d.ts.map +1 -0
  80. package/dist/commands/channel/send.js +24 -0
  81. package/dist/commands/channel/send.js.map +1 -0
  82. package/dist/commands/channel/spawn.d.ts +40 -0
  83. package/dist/commands/channel/spawn.d.ts.map +1 -0
  84. package/dist/commands/channel/spawn.js +244 -0
  85. package/dist/commands/channel/spawn.js.map +1 -0
  86. package/dist/commands/channel/store/events.d.ts +39 -0
  87. package/dist/commands/channel/store/events.d.ts.map +1 -0
  88. package/dist/commands/channel/store/events.js +87 -0
  89. package/dist/commands/channel/store/events.js.map +1 -0
  90. package/dist/commands/channel/store/filter.d.ts +3 -0
  91. package/dist/commands/channel/store/filter.d.ts.map +1 -0
  92. package/dist/commands/channel/store/filter.js +2 -0
  93. package/dist/commands/channel/store/filter.js.map +1 -0
  94. package/dist/commands/channel/store/lock.d.ts +23 -0
  95. package/dist/commands/channel/store/lock.d.ts.map +1 -0
  96. package/dist/commands/channel/store/lock.js +99 -0
  97. package/dist/commands/channel/store/lock.js.map +1 -0
  98. package/dist/commands/channel/store/paths.d.ts +63 -0
  99. package/dist/commands/channel/store/paths.d.ts.map +1 -0
  100. package/dist/commands/channel/store/paths.js +246 -0
  101. package/dist/commands/channel/store/paths.js.map +1 -0
  102. package/dist/commands/channel/store/schema.d.ts +27 -0
  103. package/dist/commands/channel/store/schema.d.ts.map +1 -0
  104. package/dist/commands/channel/store/schema.js +34 -0
  105. package/dist/commands/channel/store/schema.js.map +1 -0
  106. package/dist/commands/channel/store/thread-state.d.ts +5 -0
  107. package/dist/commands/channel/store/thread-state.d.ts.map +1 -0
  108. package/dist/commands/channel/store/thread-state.js +16 -0
  109. package/dist/commands/channel/store/thread-state.js.map +1 -0
  110. package/dist/commands/channel/store/watch.d.ts +19 -0
  111. package/dist/commands/channel/store/watch.d.ts.map +1 -0
  112. package/dist/commands/channel/store/watch.js +146 -0
  113. package/dist/commands/channel/store/watch.js.map +1 -0
  114. package/dist/commands/channel/supervisor/idle.d.ts +46 -0
  115. package/dist/commands/channel/supervisor/idle.d.ts.map +1 -0
  116. package/dist/commands/channel/supervisor/idle.js +72 -0
  117. package/dist/commands/channel/supervisor/idle.js.map +1 -0
  118. package/dist/commands/channel/supervisor/inbox.d.ts +30 -0
  119. package/dist/commands/channel/supervisor/inbox.d.ts.map +1 -0
  120. package/dist/commands/channel/supervisor/inbox.js +160 -0
  121. package/dist/commands/channel/supervisor/inbox.js.map +1 -0
  122. package/dist/commands/channel/supervisor/shutdown.d.ts +68 -0
  123. package/dist/commands/channel/supervisor/shutdown.d.ts.map +1 -0
  124. package/dist/commands/channel/supervisor/shutdown.js +146 -0
  125. package/dist/commands/channel/supervisor/shutdown.js.map +1 -0
  126. package/dist/commands/channel/supervisor/stdout.d.ts +51 -0
  127. package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -0
  128. package/dist/commands/channel/supervisor/stdout.js +121 -0
  129. package/dist/commands/channel/supervisor/stdout.js.map +1 -0
  130. package/dist/commands/channel/supervisor/turns.d.ts +31 -0
  131. package/dist/commands/channel/supervisor/turns.d.ts.map +1 -0
  132. package/dist/commands/channel/supervisor/turns.js +45 -0
  133. package/dist/commands/channel/supervisor/turns.js.map +1 -0
  134. package/dist/commands/channel/supervisor/warning.d.ts +48 -0
  135. package/dist/commands/channel/supervisor/warning.d.ts.map +1 -0
  136. package/dist/commands/channel/supervisor/warning.js +77 -0
  137. package/dist/commands/channel/supervisor/warning.js.map +1 -0
  138. package/dist/commands/channel/supervisor.d.ts +59 -0
  139. package/dist/commands/channel/supervisor.d.ts.map +1 -0
  140. package/dist/commands/channel/supervisor.js +344 -0
  141. package/dist/commands/channel/supervisor.js.map +1 -0
  142. package/dist/commands/channel/text-body.d.ts +13 -0
  143. package/dist/commands/channel/text-body.d.ts.map +1 -0
  144. package/dist/commands/channel/text-body.js +47 -0
  145. package/dist/commands/channel/text-body.js.map +1 -0
  146. package/dist/commands/channel/threads.d.ts +39 -0
  147. package/dist/commands/channel/threads.d.ts.map +1 -0
  148. package/dist/commands/channel/threads.js +106 -0
  149. package/dist/commands/channel/threads.js.map +1 -0
  150. package/dist/commands/channel/title.d.ts +12 -0
  151. package/dist/commands/channel/title.d.ts.map +1 -0
  152. package/dist/commands/channel/title.js +24 -0
  153. package/dist/commands/channel/title.js.map +1 -0
  154. package/dist/commands/channel/wait.d.ts +17 -0
  155. package/dist/commands/channel/wait.d.ts.map +1 -0
  156. package/dist/commands/channel/wait.js +75 -0
  157. package/dist/commands/channel/wait.js.map +1 -0
  158. package/dist/commands/init.d.ts +62 -0
  159. package/dist/commands/init.d.ts.map +1 -0
  160. package/dist/commands/init.js +1656 -0
  161. package/dist/commands/init.js.map +1 -0
  162. package/dist/commands/mem.d.ts +30 -0
  163. package/dist/commands/mem.d.ts.map +1 -0
  164. package/dist/commands/mem.js +424 -0
  165. package/dist/commands/mem.js.map +1 -0
  166. package/dist/commands/rollout.d.ts +34 -0
  167. package/dist/commands/rollout.d.ts.map +1 -0
  168. package/dist/commands/rollout.js +102 -0
  169. package/dist/commands/rollout.js.map +1 -0
  170. package/dist/commands/uninstall.d.ts +27 -0
  171. package/dist/commands/uninstall.d.ts.map +1 -0
  172. package/dist/commands/uninstall.js +339 -0
  173. package/dist/commands/uninstall.js.map +1 -0
  174. package/dist/commands/update.d.ts +80 -0
  175. package/dist/commands/update.d.ts.map +1 -0
  176. package/dist/commands/update.js +2185 -0
  177. package/dist/commands/update.js.map +1 -0
  178. package/dist/commands/upgrade.d.ts +28 -0
  179. package/dist/commands/upgrade.d.ts.map +1 -0
  180. package/dist/commands/upgrade.js +84 -0
  181. package/dist/commands/upgrade.js.map +1 -0
  182. package/dist/commands/workflow.d.ts +35 -0
  183. package/dist/commands/workflow.d.ts.map +1 -0
  184. package/dist/commands/workflow.js +219 -0
  185. package/dist/commands/workflow.js.map +1 -0
  186. package/dist/configurators/antigravity.d.ts +7 -0
  187. package/dist/configurators/antigravity.d.ts.map +1 -0
  188. package/dist/configurators/antigravity.js +19 -0
  189. package/dist/configurators/antigravity.js.map +1 -0
  190. package/dist/configurators/claude.d.ts +9 -0
  191. package/dist/configurators/claude.d.ts.map +1 -0
  192. package/dist/configurators/claude.js +72 -0
  193. package/dist/configurators/claude.js.map +1 -0
  194. package/dist/configurators/codebuddy.d.ts +10 -0
  195. package/dist/configurators/codebuddy.d.ts.map +1 -0
  196. package/dist/configurators/codebuddy.js +30 -0
  197. package/dist/configurators/codebuddy.js.map +1 -0
  198. package/dist/configurators/codex.d.ts +8 -0
  199. package/dist/configurators/codex.d.ts.map +1 -0
  200. package/dist/configurators/codex.js +87 -0
  201. package/dist/configurators/codex.js.map +1 -0
  202. package/dist/configurators/copilot.d.ts +10 -0
  203. package/dist/configurators/copilot.d.ts.map +1 -0
  204. package/dist/configurators/copilot.js +51 -0
  205. package/dist/configurators/copilot.js.map +1 -0
  206. package/dist/configurators/cursor.d.ts +20 -0
  207. package/dist/configurators/cursor.d.ts.map +1 -0
  208. package/dist/configurators/cursor.js +49 -0
  209. package/dist/configurators/cursor.js.map +1 -0
  210. package/dist/configurators/cursor2plus-local.d.ts +6 -0
  211. package/dist/configurators/cursor2plus-local.d.ts.map +1 -0
  212. package/dist/configurators/cursor2plus-local.js +20 -0
  213. package/dist/configurators/cursor2plus-local.js.map +1 -0
  214. package/dist/configurators/droid.d.ts +10 -0
  215. package/dist/configurators/droid.d.ts.map +1 -0
  216. package/dist/configurators/droid.js +30 -0
  217. package/dist/configurators/droid.js.map +1 -0
  218. package/dist/configurators/gemini.d.ts +16 -0
  219. package/dist/configurators/gemini.d.ts.map +1 -0
  220. package/dist/configurators/gemini.js +38 -0
  221. package/dist/configurators/gemini.js.map +1 -0
  222. package/dist/configurators/index.d.ts +69 -0
  223. package/dist/configurators/index.d.ts.map +1 -0
  224. package/dist/configurators/index.js +395 -0
  225. package/dist/configurators/index.js.map +1 -0
  226. package/dist/configurators/kilo.d.ts +7 -0
  227. package/dist/configurators/kilo.d.ts.map +1 -0
  228. package/dist/configurators/kilo.js +19 -0
  229. package/dist/configurators/kilo.js.map +1 -0
  230. package/dist/configurators/kiro.d.ts +8 -0
  231. package/dist/configurators/kiro.d.ts.map +1 -0
  232. package/dist/configurators/kiro.js +24 -0
  233. package/dist/configurators/kiro.js.map +1 -0
  234. package/dist/configurators/opencode.d.ts +14 -0
  235. package/dist/configurators/opencode.d.ts.map +1 -0
  236. package/dist/configurators/opencode.js +96 -0
  237. package/dist/configurators/opencode.js.map +1 -0
  238. package/dist/configurators/pi.d.ts +3 -0
  239. package/dist/configurators/pi.d.ts.map +1 -0
  240. package/dist/configurators/pi.js +45 -0
  241. package/dist/configurators/pi.js.map +1 -0
  242. package/dist/configurators/qoder.d.ts +11 -0
  243. package/dist/configurators/qoder.d.ts.map +1 -0
  244. package/dist/configurators/qoder.js +31 -0
  245. package/dist/configurators/qoder.js.map +1 -0
  246. package/dist/configurators/shared.d.ts +183 -0
  247. package/dist/configurators/shared.d.ts.map +1 -0
  248. package/dist/configurators/shared.js +557 -0
  249. package/dist/configurators/shared.js.map +1 -0
  250. package/dist/configurators/windsurf.d.ts +7 -0
  251. package/dist/configurators/windsurf.d.ts.map +1 -0
  252. package/dist/configurators/windsurf.js +19 -0
  253. package/dist/configurators/windsurf.js.map +1 -0
  254. package/dist/configurators/workflow.d.ts +46 -0
  255. package/dist/configurators/workflow.d.ts.map +1 -0
  256. package/dist/configurators/workflow.js +180 -0
  257. package/dist/configurators/workflow.js.map +1 -0
  258. package/dist/constants/paths.d.ts +70 -0
  259. package/dist/constants/paths.d.ts.map +1 -0
  260. package/dist/constants/paths.js +79 -0
  261. package/dist/constants/paths.js.map +1 -0
  262. package/dist/constants/version.d.ts +9 -0
  263. package/dist/constants/version.d.ts.map +1 -0
  264. package/dist/constants/version.js +15 -0
  265. package/dist/constants/version.js.map +1 -0
  266. package/dist/index.d.ts +9 -0
  267. package/dist/index.d.ts.map +1 -0
  268. package/dist/index.js +9 -0
  269. package/dist/index.js.map +1 -0
  270. package/dist/migrations/index.d.ts +62 -0
  271. package/dist/migrations/index.d.ts.map +1 -0
  272. package/dist/migrations/index.js +187 -0
  273. package/dist/migrations/index.js.map +1 -0
  274. package/dist/migrations/manifests/0.1.0.json +9 -0
  275. package/dist/templates/claude/agents/trellis-check.md +124 -0
  276. package/dist/templates/claude/agents/trellis-implement.md +110 -0
  277. package/dist/templates/claude/agents/trellis-research.md +137 -0
  278. package/dist/templates/claude/index.d.ts +22 -0
  279. package/dist/templates/claude/index.d.ts.map +1 -0
  280. package/dist/templates/claude/index.js +46 -0
  281. package/dist/templates/claude/index.js.map +1 -0
  282. package/dist/templates/claude/settings.json +84 -0
  283. package/dist/templates/codebuddy/agents/trellis-check.md +115 -0
  284. package/dist/templates/codebuddy/agents/trellis-implement.md +110 -0
  285. package/dist/templates/codebuddy/agents/trellis-research.md +137 -0
  286. package/dist/templates/codebuddy/index.d.ts +15 -0
  287. package/dist/templates/codebuddy/index.d.ts.map +1 -0
  288. package/dist/templates/codebuddy/index.js +15 -0
  289. package/dist/templates/codebuddy/index.js.map +1 -0
  290. package/dist/templates/codebuddy/settings.json +70 -0
  291. package/dist/templates/codex/agents/trellis-check.toml +67 -0
  292. package/dist/templates/codex/agents/trellis-implement.toml +40 -0
  293. package/dist/templates/codex/agents/trellis-research.toml +73 -0
  294. package/dist/templates/codex/config.toml +28 -0
  295. package/dist/templates/codex/hooks/session-start.py +575 -0
  296. package/dist/templates/codex/hooks.json +15 -0
  297. package/dist/templates/codex/index.d.ts +39 -0
  298. package/dist/templates/codex/index.d.ts.map +1 -0
  299. package/dist/templates/codex/index.js +85 -0
  300. package/dist/templates/codex/index.js.map +1 -0
  301. package/dist/templates/codex/skills/before-dev/SKILL.md +40 -0
  302. package/dist/templates/codex/skills/brainstorm/SKILL.md +112 -0
  303. package/dist/templates/codex/skills/break-loop/SKILL.md +130 -0
  304. package/dist/templates/codex/skills/check/SKILL.md +98 -0
  305. package/dist/templates/codex/skills/check-cross-layer/SKILL.md +158 -0
  306. package/dist/templates/codex/skills/create-command/SKILL.md +101 -0
  307. package/dist/templates/codex/skills/finish-work/SKILL.md +90 -0
  308. package/dist/templates/codex/skills/improve-ut/SKILL.md +69 -0
  309. package/dist/templates/codex/skills/integrate-skill/SKILL.md +221 -0
  310. package/dist/templates/codex/skills/onboard/SKILL.md +363 -0
  311. package/dist/templates/codex/skills/record-session/SKILL.md +67 -0
  312. package/dist/templates/codex/skills/start/SKILL.md +66 -0
  313. package/dist/templates/codex/skills/update-spec/SKILL.md +335 -0
  314. package/dist/templates/common/bundled-skills/smart-search-cli/SKILL.md +388 -0
  315. package/dist/templates/common/bundled-skills/smart-search-cli/agents/openai.yaml +3 -0
  316. package/dist/templates/common/bundled-skills/smart-search-cli/examples/batch-search.md +98 -0
  317. package/dist/templates/common/bundled-skills/smart-search-cli/examples/evidence-gathering.md +89 -0
  318. package/dist/templates/common/bundled-skills/smart-search-cli/references/cli-contract.md +337 -0
  319. package/dist/templates/common/bundled-skills/trellis-cursor2plus-setup/SKILL.md +62 -0
  320. package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +73 -0
  321. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/add-project-local-conventions.md +83 -0
  322. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-agents.md +54 -0
  323. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-context-loading.md +84 -0
  324. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-hooks.md +57 -0
  325. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +80 -0
  326. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-spec-structure.md +83 -0
  327. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-task-lifecycle.md +88 -0
  328. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-workflow.md +65 -0
  329. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +55 -0
  330. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/context-injection.md +68 -0
  331. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +80 -0
  332. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/overview.md +51 -0
  333. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/spec-system.md +102 -0
  334. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +133 -0
  335. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/workflow.md +75 -0
  336. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/workspace-memory.md +71 -0
  337. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +80 -0
  338. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +69 -0
  339. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +61 -0
  340. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +76 -0
  341. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +128 -0
  342. package/dist/templates/common/bundled-skills/trellis-micro-grill/SKILL.md +47 -0
  343. package/dist/templates/common/bundled-skills/trellis-skill-creator/SKILL.md +44 -0
  344. package/dist/templates/common/bundled-skills/trellis-skill-creator/references/authoring-rules.md +97 -0
  345. package/dist/templates/common/bundled-skills/trellis-skill-creator/references/review-checklist.md +47 -0
  346. package/dist/templates/common/bundled-skills/trellis-skill-creator/references/trellis-skill-locations.md +52 -0
  347. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/SKILL.md +41 -0
  348. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/mcp-setup.md +90 -0
  349. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/repository-analysis.md +59 -0
  350. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/spec-task-planning.md +61 -0
  351. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/spec-writing.md +70 -0
  352. package/dist/templates/common/commands/continue.md +63 -0
  353. package/dist/templates/common/commands/finish-work.md +68 -0
  354. package/dist/templates/common/commands/start.md +69 -0
  355. package/dist/templates/common/index.d.ts +48 -0
  356. package/dist/templates/common/index.d.ts.map +1 -0
  357. package/dist/templates/common/index.js +104 -0
  358. package/dist/templates/common/index.js.map +1 -0
  359. package/dist/templates/common/skills/before-dev.md +35 -0
  360. package/dist/templates/common/skills/brainstorm.md +164 -0
  361. package/dist/templates/common/skills/break-loop.md +125 -0
  362. package/dist/templates/common/skills/check.md +106 -0
  363. package/dist/templates/common/skills/update-spec.md +364 -0
  364. package/dist/templates/copilot/hooks/session-start.py +557 -0
  365. package/dist/templates/copilot/hooks.json +19 -0
  366. package/dist/templates/copilot/index.d.ts +23 -0
  367. package/dist/templates/copilot/index.d.ts.map +1 -0
  368. package/dist/templates/copilot/index.js +54 -0
  369. package/dist/templates/copilot/index.js.map +1 -0
  370. package/dist/templates/copilot/prompts/before-dev.prompt.md +39 -0
  371. package/dist/templates/copilot/prompts/brainstorm.prompt.md +111 -0
  372. package/dist/templates/copilot/prompts/break-loop.prompt.md +129 -0
  373. package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +157 -0
  374. package/dist/templates/copilot/prompts/check.prompt.md +97 -0
  375. package/dist/templates/copilot/prompts/create-command.prompt.md +116 -0
  376. package/dist/templates/copilot/prompts/finish-work.prompt.md +99 -0
  377. package/dist/templates/copilot/prompts/integrate-skill.prompt.md +223 -0
  378. package/dist/templates/copilot/prompts/onboard.prompt.md +362 -0
  379. package/dist/templates/copilot/prompts/parallel.prompt.md +204 -0
  380. package/dist/templates/copilot/prompts/record-session.prompt.md +66 -0
  381. package/dist/templates/copilot/prompts/start.prompt.md +63 -0
  382. package/dist/templates/copilot/prompts/update-spec.prompt.md +358 -0
  383. package/dist/templates/cursor/agents/trellis-check.md +139 -0
  384. package/dist/templates/cursor/agents/trellis-implement.md +119 -0
  385. package/dist/templates/cursor/agents/trellis-research.md +147 -0
  386. package/dist/templates/cursor/commands/cursor2plus-setup.md +82 -0
  387. package/dist/templates/cursor/hooks.json +30 -0
  388. package/dist/templates/cursor/index.d.ts +19 -0
  389. package/dist/templates/cursor/index.d.ts.map +1 -0
  390. package/dist/templates/cursor/index.js +19 -0
  391. package/dist/templates/cursor/index.js.map +1 -0
  392. package/dist/templates/cursor/rules/trellis-triage.mdc +38 -0
  393. package/dist/templates/cursor/worktrees.json +11 -0
  394. package/dist/templates/droid/droids/trellis-check.md +107 -0
  395. package/dist/templates/droid/droids/trellis-implement.md +102 -0
  396. package/dist/templates/droid/droids/trellis-research.md +137 -0
  397. package/dist/templates/droid/index.d.ts +15 -0
  398. package/dist/templates/droid/index.d.ts.map +1 -0
  399. package/dist/templates/droid/index.js +15 -0
  400. package/dist/templates/droid/index.js.map +1 -0
  401. package/dist/templates/droid/settings.json +70 -0
  402. package/dist/templates/extract.d.ts +40 -0
  403. package/dist/templates/extract.d.ts.map +1 -0
  404. package/dist/templates/extract.js +106 -0
  405. package/dist/templates/extract.js.map +1 -0
  406. package/dist/templates/gemini/agents/trellis-check.md +107 -0
  407. package/dist/templates/gemini/agents/trellis-implement.md +102 -0
  408. package/dist/templates/gemini/agents/trellis-research.md +136 -0
  409. package/dist/templates/gemini/index.d.ts +13 -0
  410. package/dist/templates/gemini/index.d.ts.map +1 -0
  411. package/dist/templates/gemini/index.js +13 -0
  412. package/dist/templates/gemini/index.js.map +1 -0
  413. package/dist/templates/gemini/settings.json +28 -0
  414. package/dist/templates/kiro/agents/trellis-check.json +26 -0
  415. package/dist/templates/kiro/agents/trellis-implement.json +26 -0
  416. package/dist/templates/kiro/agents/trellis-research.json +30 -0
  417. package/dist/templates/kiro/index.d.ts +18 -0
  418. package/dist/templates/kiro/index.d.ts.map +1 -0
  419. package/dist/templates/kiro/index.js +18 -0
  420. package/dist/templates/kiro/index.js.map +1 -0
  421. package/dist/templates/markdown/agents.md +32 -0
  422. package/dist/templates/markdown/gitignore.txt +15 -0
  423. package/dist/templates/markdown/index.d.ts +30 -0
  424. package/dist/templates/markdown/index.d.ts.map +1 -0
  425. package/dist/templates/markdown/index.js +55 -0
  426. package/dist/templates/markdown/index.js.map +1 -0
  427. package/dist/templates/markdown/spec/backend/database-guidelines.md.txt +51 -0
  428. package/dist/templates/markdown/spec/backend/directory-structure.md.txt +54 -0
  429. package/dist/templates/markdown/spec/backend/error-handling.md.txt +51 -0
  430. package/dist/templates/markdown/spec/backend/index.md.txt +38 -0
  431. package/dist/templates/markdown/spec/backend/logging-guidelines.md.txt +51 -0
  432. package/dist/templates/markdown/spec/backend/quality-guidelines.md.txt +51 -0
  433. package/dist/templates/markdown/spec/frontend/component-guidelines.md.txt +59 -0
  434. package/dist/templates/markdown/spec/frontend/directory-structure.md.txt +54 -0
  435. package/dist/templates/markdown/spec/frontend/hook-guidelines.md.txt +51 -0
  436. package/dist/templates/markdown/spec/frontend/index.md.txt +39 -0
  437. package/dist/templates/markdown/spec/frontend/quality-guidelines.md.txt +51 -0
  438. package/dist/templates/markdown/spec/frontend/state-management.md.txt +51 -0
  439. package/dist/templates/markdown/spec/frontend/type-safety.md.txt +51 -0
  440. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +223 -0
  441. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +259 -0
  442. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +633 -0
  443. package/dist/templates/markdown/spec/guides/cursor-context-injection-guide.md.txt +65 -0
  444. package/dist/templates/markdown/spec/guides/cursor-subagent-policy.md.txt +382 -0
  445. package/dist/templates/markdown/spec/guides/durable-learning-decision-guide.md.txt +76 -0
  446. package/dist/templates/markdown/spec/guides/index.md.txt +101 -0
  447. package/dist/templates/markdown/spec/guides/retrieval-daily-guide.md.txt +92 -0
  448. package/dist/templates/markdown/workspace-index.md +125 -0
  449. package/dist/templates/markdown/worktree.yaml.txt +58 -0
  450. package/dist/templates/opencode/agents/trellis-check.md +122 -0
  451. package/dist/templates/opencode/agents/trellis-implement.md +118 -0
  452. package/dist/templates/opencode/agents/trellis-research.md +145 -0
  453. package/dist/templates/opencode/lib/session-utils.js +667 -0
  454. package/dist/templates/opencode/lib/trellis-context.js +336 -0
  455. package/dist/templates/opencode/package.json +5 -0
  456. package/dist/templates/opencode/plugins/inject-subagent-context.js +495 -0
  457. package/dist/templates/opencode/plugins/inject-workflow-state.js +159 -0
  458. package/dist/templates/opencode/plugins/session-start.js +101 -0
  459. package/dist/templates/pi/agents/trellis-check.md +37 -0
  460. package/dist/templates/pi/agents/trellis-implement.md +42 -0
  461. package/dist/templates/pi/agents/trellis-research.md +25 -0
  462. package/dist/templates/pi/extensions/trellis/index.ts.txt +1600 -0
  463. package/dist/templates/pi/index.d.ts +5 -0
  464. package/dist/templates/pi/index.d.ts.map +1 -0
  465. package/dist/templates/pi/index.js +12 -0
  466. package/dist/templates/pi/index.js.map +1 -0
  467. package/dist/templates/pi/settings.json +12 -0
  468. package/dist/templates/qoder/agents/trellis-check.md +108 -0
  469. package/dist/templates/qoder/agents/trellis-implement.md +103 -0
  470. package/dist/templates/qoder/agents/trellis-research.md +137 -0
  471. package/dist/templates/qoder/index.d.ts +15 -0
  472. package/dist/templates/qoder/index.d.ts.map +1 -0
  473. package/dist/templates/qoder/index.js +15 -0
  474. package/dist/templates/qoder/index.js.map +1 -0
  475. package/dist/templates/qoder/settings.json +47 -0
  476. package/dist/templates/shared-hooks/index.d.ts +50 -0
  477. package/dist/templates/shared-hooks/index.d.ts.map +1 -0
  478. package/dist/templates/shared-hooks/index.js +92 -0
  479. package/dist/templates/shared-hooks/index.js.map +1 -0
  480. package/dist/templates/shared-hooks/inject-shell-session-context.py +183 -0
  481. package/dist/templates/shared-hooks/inject-subagent-context.py +774 -0
  482. package/dist/templates/shared-hooks/inject-workflow-state.py +366 -0
  483. package/dist/templates/shared-hooks/research-end-retrieval-pack.py +220 -0
  484. package/dist/templates/shared-hooks/session-start.py +873 -0
  485. package/dist/templates/template-utils.d.ts +28 -0
  486. package/dist/templates/template-utils.d.ts.map +1 -0
  487. package/dist/templates/template-utils.js +83 -0
  488. package/dist/templates/template-utils.js.map +1 -0
  489. package/dist/templates/trellis/config.yaml +132 -0
  490. package/dist/templates/trellis/gitignore.txt +39 -0
  491. package/dist/templates/trellis/index.d.ts +80 -0
  492. package/dist/templates/trellis/index.d.ts.map +1 -0
  493. package/dist/templates/trellis/index.js +171 -0
  494. package/dist/templates/trellis/index.js.map +1 -0
  495. package/dist/templates/trellis/local/README.md +59 -0
  496. package/dist/templates/trellis/local/config.local.json.example +6 -0
  497. package/dist/templates/trellis/local/index.d.ts +7 -0
  498. package/dist/templates/trellis/local/index.d.ts.map +1 -0
  499. package/dist/templates/trellis/local/index.js +14 -0
  500. package/dist/templates/trellis/local/index.js.map +1 -0
  501. package/dist/templates/trellis/local/patch_wpelc8.py +297 -0
  502. package/dist/templates/trellis/local/subagent-models.json.example +4 -0
  503. package/dist/templates/trellis/local/trellis-task-models.json.example +10 -0
  504. package/dist/templates/trellis/local/trellis-task-models.json5.example +45 -0
  505. package/dist/templates/trellis/local/trellis_task_models_config.py +200 -0
  506. package/dist/templates/trellis/scripts/__init__.py +5 -0
  507. package/dist/templates/trellis/scripts/add_session.py +547 -0
  508. package/dist/templates/trellis/scripts/build_context_pack.py +12 -0
  509. package/dist/templates/trellis/scripts/build_retrieval_pack.py +12 -0
  510. package/dist/templates/trellis/scripts/common/__init__.py +103 -0
  511. package/dist/templates/trellis/scripts/common/active_task.py +607 -0
  512. package/dist/templates/trellis/scripts/common/artifact_search.py +587 -0
  513. package/dist/templates/trellis/scripts/common/cli_adapter.py +811 -0
  514. package/dist/templates/trellis/scripts/common/cli_environment.py +155 -0
  515. package/dist/templates/trellis/scripts/common/codebase_retrieval_router.py +902 -0
  516. package/dist/templates/trellis/scripts/common/config.py +458 -0
  517. package/dist/templates/trellis/scripts/common/context_pack.py +371 -0
  518. package/dist/templates/trellis/scripts/common/developer.py +190 -0
  519. package/dist/templates/trellis/scripts/common/git.py +31 -0
  520. package/dist/templates/trellis/scripts/common/git_context.py +149 -0
  521. package/dist/templates/trellis/scripts/common/io.py +37 -0
  522. package/dist/templates/trellis/scripts/common/log.py +45 -0
  523. package/dist/templates/trellis/scripts/common/packages_context.py +239 -0
  524. package/dist/templates/trellis/scripts/common/parent_orchestration.py +691 -0
  525. package/dist/templates/trellis/scripts/common/paths.py +457 -0
  526. package/dist/templates/trellis/scripts/common/retrieval_adapter_metadata.py +889 -0
  527. package/dist/templates/trellis/scripts/common/retrieval_evidence.py +917 -0
  528. package/dist/templates/trellis/scripts/common/retrieval_pack.py +425 -0
  529. package/dist/templates/trellis/scripts/common/retrieval_pack_context.py +126 -0
  530. package/dist/templates/trellis/scripts/common/safe_commit.py +285 -0
  531. package/dist/templates/trellis/scripts/common/session_context.py +1159 -0
  532. package/dist/templates/trellis/scripts/common/session_memory.py +360 -0
  533. package/dist/templates/trellis/scripts/common/smart_search_evidence.py +479 -0
  534. package/dist/templates/trellis/scripts/common/smart_search_resolve.py +125 -0
  535. package/dist/templates/trellis/scripts/common/task_context.py +223 -0
  536. package/dist/templates/trellis/scripts/common/task_dashboard.py +140 -0
  537. package/dist/templates/trellis/scripts/common/task_gates.py +1735 -0
  538. package/dist/templates/trellis/scripts/common/task_map.py +586 -0
  539. package/dist/templates/trellis/scripts/common/task_queue.py +188 -0
  540. package/dist/templates/trellis/scripts/common/task_store.py +1533 -0
  541. package/dist/templates/trellis/scripts/common/task_utils.py +274 -0
  542. package/dist/templates/trellis/scripts/common/tasks.py +231 -0
  543. package/dist/templates/trellis/scripts/common/test_retrieval_arbitration.py +333 -0
  544. package/dist/templates/trellis/scripts/common/trellis_config.py +131 -0
  545. package/dist/templates/trellis/scripts/common/types.py +110 -0
  546. package/dist/templates/trellis/scripts/common/workflow_phase.py +212 -0
  547. package/dist/templates/trellis/scripts/get_context.py +17 -0
  548. package/dist/templates/trellis/scripts/get_developer.py +26 -0
  549. package/dist/templates/trellis/scripts/hooks/linear_sync.py +243 -0
  550. package/dist/templates/trellis/scripts/init_developer.py +51 -0
  551. package/dist/templates/trellis/scripts/route_codebase_retrieval.py +77 -0
  552. package/dist/templates/trellis/scripts/run_smart_search.py +12 -0
  553. package/dist/templates/trellis/scripts/search_artifacts.py +13 -0
  554. package/dist/templates/trellis/scripts/search_memory.py +12 -0
  555. package/dist/templates/trellis/scripts/task.py +851 -0
  556. package/dist/templates/trellis/tasks/.gitkeep +0 -0
  557. package/dist/templates/trellis/tasks/templates/release-execution/design.md +61 -0
  558. package/dist/templates/trellis/tasks/templates/release-execution/handoff-template.md +29 -0
  559. package/dist/templates/trellis/tasks/templates/release-execution/implement.md +29 -0
  560. package/dist/templates/trellis/tasks/templates/release-execution/prd.md +31 -0
  561. package/dist/templates/trellis/tasks/templates/release-readiness/design.md +50 -0
  562. package/dist/templates/trellis/tasks/templates/release-readiness/handoff-template.md +39 -0
  563. package/dist/templates/trellis/tasks/templates/release-readiness/implement.md +29 -0
  564. package/dist/templates/trellis/tasks/templates/release-readiness/prd.md +31 -0
  565. package/dist/templates/trellis/workflow.md +960 -0
  566. package/dist/types/ai-tools.d.ts +106 -0
  567. package/dist/types/ai-tools.d.ts.map +1 -0
  568. package/dist/types/ai-tools.js +294 -0
  569. package/dist/types/ai-tools.js.map +1 -0
  570. package/dist/types/migration.d.ts +125 -0
  571. package/dist/types/migration.d.ts.map +1 -0
  572. package/dist/types/migration.js +8 -0
  573. package/dist/types/migration.js.map +1 -0
  574. package/dist/utils/codebase-retrieval-router.d.ts +77 -0
  575. package/dist/utils/codebase-retrieval-router.d.ts.map +1 -0
  576. package/dist/utils/codebase-retrieval-router.js +767 -0
  577. package/dist/utils/codebase-retrieval-router.js.map +1 -0
  578. package/dist/utils/compare-versions.d.ts +12 -0
  579. package/dist/utils/compare-versions.d.ts.map +1 -0
  580. package/dist/utils/compare-versions.js +86 -0
  581. package/dist/utils/compare-versions.js.map +1 -0
  582. package/dist/utils/cwd-guard.d.ts +38 -0
  583. package/dist/utils/cwd-guard.d.ts.map +1 -0
  584. package/dist/utils/cwd-guard.js +62 -0
  585. package/dist/utils/cwd-guard.js.map +1 -0
  586. package/dist/utils/file-writer.d.ts +36 -0
  587. package/dist/utils/file-writer.d.ts.map +1 -0
  588. package/dist/utils/file-writer.js +203 -0
  589. package/dist/utils/file-writer.js.map +1 -0
  590. package/dist/utils/manifest-prune.d.ts +61 -0
  591. package/dist/utils/manifest-prune.d.ts.map +1 -0
  592. package/dist/utils/manifest-prune.js +136 -0
  593. package/dist/utils/manifest-prune.js.map +1 -0
  594. package/dist/utils/posix.d.ts +13 -0
  595. package/dist/utils/posix.d.ts.map +1 -0
  596. package/dist/utils/posix.js +15 -0
  597. package/dist/utils/posix.js.map +1 -0
  598. package/dist/utils/post-update-smoke.d.ts +7 -0
  599. package/dist/utils/post-update-smoke.d.ts.map +1 -0
  600. package/dist/utils/post-update-smoke.js +40 -0
  601. package/dist/utils/post-update-smoke.js.map +1 -0
  602. package/dist/utils/project-capabilities.d.ts +54 -0
  603. package/dist/utils/project-capabilities.d.ts.map +1 -0
  604. package/dist/utils/project-capabilities.js +515 -0
  605. package/dist/utils/project-capabilities.js.map +1 -0
  606. package/dist/utils/project-detector.d.ts +46 -0
  607. package/dist/utils/project-detector.d.ts.map +1 -0
  608. package/dist/utils/project-detector.js +666 -0
  609. package/dist/utils/project-detector.js.map +1 -0
  610. package/dist/utils/proxy.d.ts +25 -0
  611. package/dist/utils/proxy.d.ts.map +1 -0
  612. package/dist/utils/proxy.js +60 -0
  613. package/dist/utils/proxy.js.map +1 -0
  614. package/dist/utils/readiness.d.ts +20 -0
  615. package/dist/utils/readiness.d.ts.map +1 -0
  616. package/dist/utils/readiness.js +430 -0
  617. package/dist/utils/readiness.js.map +1 -0
  618. package/dist/utils/retrieval-execution-telemetry.d.ts +162 -0
  619. package/dist/utils/retrieval-execution-telemetry.d.ts.map +1 -0
  620. package/dist/utils/retrieval-execution-telemetry.js +288 -0
  621. package/dist/utils/retrieval-execution-telemetry.js.map +1 -0
  622. package/dist/utils/retrieval-result-ranking.d.ts +40 -0
  623. package/dist/utils/retrieval-result-ranking.d.ts.map +1 -0
  624. package/dist/utils/retrieval-result-ranking.js +162 -0
  625. package/dist/utils/retrieval-result-ranking.js.map +1 -0
  626. package/dist/utils/task-json.d.ts +13 -0
  627. package/dist/utils/task-json.d.ts.map +1 -0
  628. package/dist/utils/task-json.js +12 -0
  629. package/dist/utils/task-json.js.map +1 -0
  630. package/dist/utils/template-fetcher.d.ts +150 -0
  631. package/dist/utils/template-fetcher.d.ts.map +1 -0
  632. package/dist/utils/template-fetcher.js +907 -0
  633. package/dist/utils/template-fetcher.js.map +1 -0
  634. package/dist/utils/template-hash.d.ts +123 -0
  635. package/dist/utils/template-hash.d.ts.map +1 -0
  636. package/dist/utils/template-hash.js +334 -0
  637. package/dist/utils/template-hash.js.map +1 -0
  638. package/dist/utils/uninstall-scrubbers.d.ts +66 -0
  639. package/dist/utils/uninstall-scrubbers.d.ts.map +1 -0
  640. package/dist/utils/uninstall-scrubbers.js +342 -0
  641. package/dist/utils/uninstall-scrubbers.js.map +1 -0
  642. package/dist/utils/update-rollout-report.d.ts +137 -0
  643. package/dist/utils/update-rollout-report.d.ts.map +1 -0
  644. package/dist/utils/update-rollout-report.js +108 -0
  645. package/dist/utils/update-rollout-report.js.map +1 -0
  646. package/dist/utils/workflow-resolver.d.ts +86 -0
  647. package/dist/utils/workflow-resolver.d.ts.map +1 -0
  648. package/dist/utils/workflow-resolver.js +265 -0
  649. package/dist/utils/workflow-resolver.js.map +1 -0
  650. package/package.json +137 -0
  651. package/scripts/postinstall.js +45 -0
  652. package/vendor/smart-search/LICENSE +21 -0
  653. package/vendor/smart-search/README.md +412 -0
  654. package/vendor/smart-search/README.zh-CN.md +430 -0
  655. package/vendor/smart-search/npm/bin/smart-search.js +63 -0
  656. package/vendor/smart-search/npm/scripts/postinstall.js +87 -0
  657. package/vendor/smart-search/npm/scripts/resolve-prerelease-version.js +108 -0
  658. package/vendor/smart-search/npm/scripts/set-package-version.js +35 -0
  659. package/vendor/smart-search/npm/scripts/sync-python-version.js +22 -0
  660. package/vendor/smart-search/npm/scripts/test-wrapper-repair.js +99 -0
  661. package/vendor/smart-search/npm/scripts/test.js +85 -0
  662. package/vendor/smart-search/package.json +42 -0
  663. package/vendor/smart-search/pyproject.toml +37 -0
  664. package/vendor/smart-search/skills/smart-search-cli/SKILL.md +387 -0
  665. package/vendor/smart-search/skills/smart-search-cli/agents/openai.yaml +3 -0
  666. package/vendor/smart-search/skills/smart-search-cli/examples/batch-search.md +98 -0
  667. package/vendor/smart-search/skills/smart-search-cli/examples/evidence-gathering.md +89 -0
  668. package/vendor/smart-search/skills/smart-search-cli/references/cli-contract.md +337 -0
  669. package/vendor/smart-search/src/smart_search/__init__.py +1 -0
  670. package/vendor/smart-search/src/smart_search/assets/skills/smart-search-cli/SKILL.md +387 -0
  671. package/vendor/smart-search/src/smart_search/assets/skills/smart-search-cli/agents/openai.yaml +3 -0
  672. package/vendor/smart-search/src/smart_search/assets/skills/smart-search-cli/examples/batch-search.md +98 -0
  673. package/vendor/smart-search/src/smart_search/assets/skills/smart-search-cli/examples/evidence-gathering.md +89 -0
  674. package/vendor/smart-search/src/smart_search/assets/skills/smart-search-cli/references/cli-contract.md +337 -0
  675. package/vendor/smart-search/src/smart_search/cli.py +2003 -0
  676. package/vendor/smart-search/src/smart_search/config.py +580 -0
  677. package/vendor/smart-search/src/smart_search/logger.py +43 -0
  678. package/vendor/smart-search/src/smart_search/providers/__init__.py +16 -0
  679. package/vendor/smart-search/src/smart_search/providers/base.py +41 -0
  680. package/vendor/smart-search/src/smart_search/providers/context7.py +141 -0
  681. package/vendor/smart-search/src/smart_search/providers/exa.py +206 -0
  682. package/vendor/smart-search/src/smart_search/providers/jina.py +136 -0
  683. package/vendor/smart-search/src/smart_search/providers/openai_compatible.py +370 -0
  684. package/vendor/smart-search/src/smart_search/providers/zhipu.py +143 -0
  685. package/vendor/smart-search/src/smart_search/service.py +2865 -0
  686. package/vendor/smart-search/src/smart_search/sources.py +429 -0
  687. package/vendor/smart-search/src/smart_search/utils.py +220 -0
@@ -0,0 +1,1159 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Session context generation (default + record modes).
4
+
5
+ Provides:
6
+ get_context_json - JSON output for default mode
7
+ get_context_text - Text output for default mode
8
+ get_context_record_json - JSON for record mode
9
+ get_context_text_record - Text for record mode
10
+ output_json - Print JSON
11
+ output_text - Print text
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import json
17
+ import os
18
+ import re
19
+ import subprocess
20
+ from pathlib import Path
21
+
22
+ from .active_task import resolve_context_key
23
+ from .config import get_git_packages
24
+ from .git import run_git
25
+ from .packages_context import get_packages_section
26
+ from .tasks import iter_active_tasks, load_task, get_all_statuses, children_progress
27
+ from .task_dashboard import render_task_dashboard
28
+ from .paths import (
29
+ DIR_SCRIPTS,
30
+ DIR_SPEC,
31
+ DIR_TASKS,
32
+ DIR_WORKFLOW,
33
+ DIR_WORKSPACE,
34
+ count_lines,
35
+ get_active_journal_file,
36
+ get_selected_task,
37
+ get_selected_task_source,
38
+ get_developer,
39
+ get_repo_root,
40
+ get_tasks_dir,
41
+ )
42
+
43
+
44
+ # =============================================================================
45
+ # Helpers
46
+ # =============================================================================
47
+
48
+ _PACKAGE_NAME = "@blxzer/cursor-trellis"
49
+ _PYTHON_CMD = "python3"
50
+ _UPDATE_CHECK_TIMEOUT_SECONDS = 1.0
51
+ _VERSION_RE = re.compile(
52
+ r"^\s*(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([0-9A-Za-z.-]+))?\s*$"
53
+ )
54
+ _VERSION_TOKEN_RE = re.compile(r"\b\d+(?:\.\d+){1,2}(?:-[0-9A-Za-z.-]+)?\b")
55
+ _POLYREPO_IGNORED_DIRS = {
56
+ "node_modules",
57
+ "target",
58
+ "dist",
59
+ "build",
60
+ "out",
61
+ "bin",
62
+ "obj",
63
+ "vendor",
64
+ "coverage",
65
+ "tmp",
66
+ "__pycache__",
67
+ }
68
+ _POLYREPO_SCAN_MAX_DEPTH = 2
69
+
70
+
71
+ def _is_git_worktree(path: Path) -> bool:
72
+ """Return True when path is inside a Git worktree."""
73
+ rc, out, _ = run_git(["rev-parse", "--is-inside-work-tree"], cwd=path)
74
+ return rc == 0 and out.strip().lower() == "true"
75
+
76
+
77
+ def _parse_recent_commits(log_output: str) -> list[dict]:
78
+ """Parse `git log --oneline` output into structured commit entries."""
79
+ commits = []
80
+ for line in log_output.splitlines():
81
+ if not line.strip():
82
+ continue
83
+ parts = line.split(" ", 1)
84
+ if len(parts) >= 2:
85
+ commits.append({"hash": parts[0], "message": parts[1]})
86
+ elif len(parts) == 1:
87
+ commits.append({"hash": parts[0], "message": ""})
88
+ return commits
89
+
90
+
91
+ def _collect_git_repo_info(name: str, rel_path: str, repo_dir: Path) -> dict | None:
92
+ """Collect Git status for one known repository directory."""
93
+ if not (repo_dir / ".git").exists():
94
+ return None
95
+
96
+ _, branch_out, _ = run_git(["branch", "--show-current"], cwd=repo_dir)
97
+ branch = branch_out.strip() or "unknown"
98
+
99
+ _, status_out, _ = run_git(["status", "--porcelain"], cwd=repo_dir)
100
+ changes = len([l for l in status_out.splitlines() if l.strip()])
101
+
102
+ _, log_out, _ = run_git(["log", "--oneline", "-5"], cwd=repo_dir)
103
+
104
+ return {
105
+ "name": name,
106
+ "path": rel_path,
107
+ "branch": branch,
108
+ "isClean": changes == 0,
109
+ "uncommittedChanges": changes,
110
+ "recentCommits": _parse_recent_commits(log_out),
111
+ }
112
+
113
+
114
+ def _collect_root_git_info(repo_root: Path) -> dict:
115
+ """Collect root Git info without pretending a non-Git root is clean."""
116
+ if not _is_git_worktree(repo_root):
117
+ return {
118
+ "isRepo": False,
119
+ "branch": "",
120
+ "isClean": False,
121
+ "uncommittedChanges": 0,
122
+ "recentCommits": [],
123
+ }
124
+
125
+ _, branch_out, _ = run_git(["branch", "--show-current"], cwd=repo_root)
126
+ branch = branch_out.strip() or "unknown"
127
+
128
+ _, status_out, _ = run_git(["status", "--porcelain"], cwd=repo_root)
129
+ status_lines = [line for line in status_out.splitlines() if line.strip()]
130
+
131
+ _, short_out, _ = run_git(["status", "--short"], cwd=repo_root)
132
+
133
+ _, log_out, _ = run_git(["log", "--oneline", "-5"], cwd=repo_root)
134
+
135
+ return {
136
+ "isRepo": True,
137
+ "branch": branch,
138
+ "isClean": len(status_lines) == 0,
139
+ "uncommittedChanges": len(status_lines),
140
+ "statusShort": short_out.splitlines(),
141
+ "recentCommits": _parse_recent_commits(log_out),
142
+ }
143
+
144
+
145
+ def _discover_child_git_repos(repo_root: Path) -> list[tuple[str, str]]:
146
+ """Discover child Git repositories using the init-time polyrepo heuristic."""
147
+ found: list[str] = []
148
+
149
+ def is_candidate_dir(path: Path) -> bool:
150
+ name = path.name
151
+ return not name.startswith(".") and name not in _POLYREPO_IGNORED_DIRS
152
+
153
+ def scan(rel_dir: Path, depth: int) -> None:
154
+ if depth >= _POLYREPO_SCAN_MAX_DEPTH:
155
+ return
156
+ abs_dir = repo_root / rel_dir
157
+ try:
158
+ children = sorted(abs_dir.iterdir(), key=lambda p: p.name)
159
+ except OSError:
160
+ return
161
+
162
+ for child in children:
163
+ if not child.is_dir() or not is_candidate_dir(child):
164
+ continue
165
+
166
+ child_rel = (
167
+ rel_dir / child.name if rel_dir != Path(".") else Path(child.name)
168
+ )
169
+ if (child / ".git").exists():
170
+ found.append(child_rel.as_posix())
171
+ continue
172
+ scan(child_rel, depth + 1)
173
+
174
+ scan(Path("."), 0)
175
+ if len(found) < 2:
176
+ return []
177
+ return [(path.replace("/", "_"), path) for path in sorted(found)]
178
+
179
+
180
+ def _collect_package_git_info(
181
+ repo_root: Path,
182
+ discover_unconfigured: bool = False,
183
+ ) -> list[dict]:
184
+ """Collect Git status for independent package repositories.
185
+
186
+ Packages marked with ``git: true`` in config.yaml are authoritative.
187
+ When the Trellis root is not a Git repo and no configured package repos are
188
+ available, optionally fall back to the bounded polyrepo child scan.
189
+
190
+ Returns:
191
+ List of dicts with keys: name, path, branch, isClean,
192
+ uncommittedChanges, recentCommits.
193
+ Empty list if no git-repo packages are configured.
194
+ """
195
+ git_pkgs = get_git_packages(repo_root)
196
+ result = []
197
+ for pkg_name, pkg_path in git_pkgs.items():
198
+ pkg_dir = repo_root / pkg_path
199
+ info = _collect_git_repo_info(pkg_name, pkg_path, pkg_dir)
200
+ if info is not None:
201
+ result.append(info)
202
+
203
+ if result or not discover_unconfigured:
204
+ return result
205
+
206
+ discovered = []
207
+ for pkg_name, pkg_path in _discover_child_git_repos(repo_root):
208
+ info = _collect_git_repo_info(pkg_name, pkg_path, repo_root / pkg_path)
209
+ if info is not None:
210
+ discovered.append(info)
211
+ return discovered
212
+
213
+
214
+ def _append_root_git_context(lines: list[str], root_git_info: dict) -> None:
215
+ """Append root Git status without misleading non-Git roots."""
216
+ lines.append("## GIT STATUS")
217
+ if not root_git_info["isRepo"]:
218
+ lines.append("Root is not a Git repository.")
219
+ lines.append("Run Git commands from the package repository paths listed below.")
220
+ else:
221
+ lines.append(f"Branch: {root_git_info['branch']}")
222
+ if root_git_info["isClean"]:
223
+ lines.append("Working directory: Clean")
224
+ else:
225
+ lines.append(
226
+ f"Working directory: {root_git_info['uncommittedChanges']} "
227
+ "uncommitted change(s)"
228
+ )
229
+ lines.append("")
230
+ lines.append("Changes:")
231
+ for line in root_git_info.get("statusShort", [])[:10]:
232
+ lines.append(line)
233
+ lines.append("")
234
+
235
+ lines.append("## RECENT COMMITS")
236
+ if not root_git_info["isRepo"]:
237
+ lines.append(
238
+ "Root has no Git commit history because it is not a Git repository."
239
+ )
240
+ elif root_git_info["recentCommits"]:
241
+ for commit in root_git_info["recentCommits"]:
242
+ lines.append(f"{commit['hash']} {commit['message']}")
243
+ else:
244
+ lines.append("(no commits)")
245
+ lines.append("")
246
+
247
+
248
+ def _append_package_git_context(lines: list[str], package_git_info: list[dict]) -> None:
249
+ """Append Git status and recent commits for package repositories."""
250
+ for pkg in package_git_info:
251
+ lines.append(f"## GIT STATUS ({pkg['name']}: {pkg['path']})")
252
+ lines.append(f"Branch: {pkg['branch']}")
253
+ if pkg["isClean"]:
254
+ lines.append("Working directory: Clean")
255
+ else:
256
+ lines.append(
257
+ f"Working directory: {pkg['uncommittedChanges']} uncommitted change(s)"
258
+ )
259
+ lines.append("")
260
+ lines.append(f"## RECENT COMMITS ({pkg['name']}: {pkg['path']})")
261
+ if pkg["recentCommits"]:
262
+ for commit in pkg["recentCommits"]:
263
+ lines.append(f"{commit['hash']} {commit['message']}")
264
+ else:
265
+ lines.append("(no commits)")
266
+ lines.append("")
267
+
268
+
269
+ def _read_project_version(repo_root: Path) -> str | None:
270
+ try:
271
+ version = (repo_root / DIR_WORKFLOW / ".version").read_text(
272
+ encoding="utf-8"
273
+ ).strip()
274
+ except OSError:
275
+ return None
276
+ return version or None
277
+
278
+
279
+ def _fetch_trellis_version_output() -> str | None:
280
+ try:
281
+ result = subprocess.run(
282
+ ["trellis", "--version"],
283
+ capture_output=True,
284
+ text=True,
285
+ encoding="utf-8",
286
+ errors="replace",
287
+ timeout=_UPDATE_CHECK_TIMEOUT_SECONDS,
288
+ )
289
+ except (OSError, subprocess.SubprocessError, TimeoutError):
290
+ return None
291
+
292
+ if result.returncode != 0:
293
+ return None
294
+ output = f"{result.stdout}\n{result.stderr}".strip()
295
+ return output or None
296
+
297
+
298
+ def _extract_available_update_version(output: str) -> str | None:
299
+ update_match = re.search(
300
+ r"Trellis update available:\s*"
301
+ r"(?P<current>\S+)\s*(?:→|->)\s*(?P<latest>\S+)",
302
+ output,
303
+ )
304
+ if update_match:
305
+ return update_match.group("latest").strip()
306
+ candidates = _VERSION_TOKEN_RE.findall(output)
307
+ return candidates[-1] if candidates else None
308
+
309
+
310
+ def _resolve_available_update_version() -> str | None:
311
+ output = _fetch_trellis_version_output()
312
+ if not output:
313
+ return None
314
+ return _extract_available_update_version(output)
315
+
316
+
317
+ def _parse_version(version: str) -> tuple[tuple[int, int, int], tuple[str, ...] | None] | None:
318
+ match = _VERSION_RE.match(version)
319
+ if not match:
320
+ return None
321
+ major, minor, patch, prerelease = match.groups()
322
+ numbers = (int(major), int(minor or "0"), int(patch or "0"))
323
+ prerelease_parts = tuple(prerelease.split(".")) if prerelease else None
324
+ return numbers, prerelease_parts
325
+
326
+
327
+ def _compare_prerelease(
328
+ left: tuple[str, ...] | None,
329
+ right: tuple[str, ...] | None,
330
+ ) -> int:
331
+ if left is None and right is None:
332
+ return 0
333
+ if left is None:
334
+ return 1
335
+ if right is None:
336
+ return -1
337
+
338
+ for left_part, right_part in zip(left, right):
339
+ if left_part == right_part:
340
+ continue
341
+ left_numeric = left_part.isdigit()
342
+ right_numeric = right_part.isdigit()
343
+ if left_numeric and right_numeric:
344
+ left_int = int(left_part)
345
+ right_int = int(right_part)
346
+ return (left_int > right_int) - (left_int < right_int)
347
+ if left_numeric:
348
+ return -1
349
+ if right_numeric:
350
+ return 1
351
+ return (left_part > right_part) - (left_part < right_part)
352
+
353
+ return (len(left) > len(right)) - (len(left) < len(right))
354
+
355
+
356
+ def _compare_versions(left: str, right: str) -> int | None:
357
+ parsed_left = _parse_version(left)
358
+ parsed_right = _parse_version(right)
359
+ if parsed_left is None or parsed_right is None:
360
+ return None
361
+
362
+ left_numbers, left_prerelease = parsed_left
363
+ right_numbers, right_prerelease = parsed_right
364
+ if left_numbers != right_numbers:
365
+ return (left_numbers > right_numbers) - (left_numbers < right_numbers)
366
+ return _compare_prerelease(left_prerelease, right_prerelease)
367
+
368
+
369
+ def _update_marker_path(repo_root: Path) -> Path:
370
+ context_key = resolve_context_key()
371
+ if not context_key:
372
+ terminal_key = os.environ.get("TERM_SESSION_ID", "").strip()
373
+ context_key = terminal_key or f"ppid-{os.getppid()}"
374
+ safe_key = re.sub(r"[^A-Za-z0-9._-]+", "_", context_key).strip("._-")
375
+ if not safe_key:
376
+ safe_key = "session"
377
+ return (
378
+ repo_root
379
+ / DIR_WORKFLOW
380
+ / ".runtime"
381
+ / f"update-check-{safe_key[:160]}.marker"
382
+ )
383
+
384
+
385
+ def _mark_update_check_attempted(repo_root: Path) -> bool:
386
+ marker_path = _update_marker_path(repo_root)
387
+ if marker_path.exists():
388
+ return False
389
+ try:
390
+ marker_path.parent.mkdir(parents=True, exist_ok=True)
391
+ marker_path.write_text("checked\n", encoding="utf-8")
392
+ except OSError:
393
+ pass
394
+ return True
395
+
396
+
397
+ def _get_update_hint(repo_root: Path) -> str | None:
398
+ marker_path = _update_marker_path(repo_root)
399
+ if marker_path.exists():
400
+ return None
401
+
402
+ current_version = _read_project_version(repo_root)
403
+ if not current_version:
404
+ return None
405
+
406
+ latest_version = _resolve_available_update_version()
407
+ if not latest_version:
408
+ return None
409
+
410
+ _mark_update_check_attempted(repo_root)
411
+ comparison = _compare_versions(current_version, latest_version)
412
+ if comparison is None or comparison >= 0:
413
+ return None
414
+
415
+ return (
416
+ f"Trellis update available: {current_version} -> {latest_version}, "
417
+ "run trellis upgrade"
418
+ )
419
+
420
+
421
+ def _quote_command_value(value: str) -> str:
422
+ return value.replace("\\", "\\\\").replace('"', '\\"')
423
+
424
+
425
+ def _artifact_search_command(query: str = "<topic>") -> str:
426
+ return (
427
+ f"{_PYTHON_CMD} ./{DIR_WORKFLOW}/{DIR_SCRIPTS}/search_artifacts.py "
428
+ f'--query "{_quote_command_value(query)}" --json'
429
+ )
430
+
431
+
432
+ def _session_memory_command(query: str = "<topic>") -> str:
433
+ return (
434
+ f"{_PYTHON_CMD} ./{DIR_WORKFLOW}/{DIR_SCRIPTS}/search_memory.py "
435
+ f'--query "{_quote_command_value(query)}" --json'
436
+ )
437
+
438
+
439
+ def _smart_search_evidence_command(question: str = "<question>") -> str:
440
+ return (
441
+ f"{_PYTHON_CMD} ./{DIR_WORKFLOW}/{DIR_SCRIPTS}/run_smart_search.py "
442
+ f'"{_quote_command_value(question)}" --intent deep-research --json'
443
+ )
444
+
445
+
446
+ def _query_tokens(*values: object) -> list[str]:
447
+ tokens: list[str] = []
448
+ seen: set[str] = set()
449
+ for value in values:
450
+ if not value:
451
+ continue
452
+ for raw_token in re.findall(r"[\w.-]+", str(value)):
453
+ token = raw_token.strip("._-")
454
+ if not token:
455
+ continue
456
+ key = token.lower()
457
+ if key in seen:
458
+ continue
459
+ seen.add(key)
460
+ tokens.append(token)
461
+ if len(tokens) >= 8:
462
+ return tokens
463
+ return tokens
464
+
465
+
466
+ def _selected_task_query(selected_task: str, task_info: object | None) -> str:
467
+ if task_info:
468
+ tokens = _query_tokens(
469
+ getattr(task_info, "title", ""),
470
+ getattr(task_info, "name", ""),
471
+ getattr(task_info, "package", ""),
472
+ getattr(task_info, "description", ""),
473
+ )
474
+ else:
475
+ tokens = _query_tokens(Path(selected_task).name)
476
+ return " ".join(tokens) if tokens else selected_task
477
+
478
+
479
+ def _recommendation(
480
+ source: str,
481
+ priority: int,
482
+ confidence: str,
483
+ reason: str,
484
+ action: str,
485
+ reference: str,
486
+ ) -> dict[str, object]:
487
+ return {
488
+ "source": source,
489
+ "priority": priority,
490
+ "confidence": confidence,
491
+ "reason": reason,
492
+ "action": action,
493
+ "reference": reference,
494
+ }
495
+
496
+
497
+ def _resolve_selected_task_dir(repo_root: Path, selected_task: str) -> Path:
498
+ task_path = Path(selected_task)
499
+ if task_path.is_absolute():
500
+ return task_path
501
+ return repo_root / task_path
502
+
503
+
504
+ def _selected_task_artifacts(
505
+ repo_root: Path,
506
+ selected_task: str | None,
507
+ ) -> dict[str, object] | None:
508
+ if not selected_task:
509
+ return None
510
+
511
+ task_dir = _resolve_selected_task_dir(repo_root, selected_task)
512
+ research_dir = task_dir / "research"
513
+ research_count = 0
514
+ if research_dir.is_dir():
515
+ research_count = len([p for p in research_dir.glob("*.md") if p.is_file()])
516
+
517
+ return {
518
+ "taskPath": selected_task,
519
+ "prd": (task_dir / "prd.md").is_file(),
520
+ "design": (task_dir / "design.md").is_file(),
521
+ "implement": (task_dir / "implement.md").is_file(),
522
+ "research": research_dir.is_dir(),
523
+ "researchCount": research_count,
524
+ "verify": (task_dir / "verify.md").is_file(),
525
+ }
526
+
527
+
528
+ def _get_retrieval_guide(
529
+ repo_root: Path,
530
+ selected_task: str | None,
531
+ ) -> dict[str, object]:
532
+ guide: dict[str, object] = {
533
+ "artifactSearch": {
534
+ "command": _artifact_search_command(),
535
+ "purpose": (
536
+ "Find durable Trellis specs, tasks, research, verification "
537
+ "notes, and workspace journals."
538
+ ),
539
+ },
540
+ "sessionMemory": {
541
+ "command": _session_memory_command(),
542
+ "purpose": (
543
+ "Find reusable session history, prior decisions, and recent "
544
+ "work context from local workspace journals."
545
+ ),
546
+ },
547
+ "smartSearchEvidence": {
548
+ "command": _smart_search_evidence_command(),
549
+ "purpose": (
550
+ "Explicitly run Smart Search and save a task-local evidence "
551
+ "manifest for source-backed research."
552
+ ),
553
+ },
554
+ "codebaseEvidence": (
555
+ "Treat adapter output as candidate evidence until current source, "
556
+ "Git, or validation confirms it."
557
+ ),
558
+ "evidenceSinks": {
559
+ "exploratory": "selected task research/*.md",
560
+ "final": "selected task verify.md",
561
+ },
562
+ }
563
+ selected_artifacts = _selected_task_artifacts(repo_root, selected_task)
564
+ if selected_artifacts is not None:
565
+ guide["selectedTaskArtifacts"] = selected_artifacts
566
+ guide["recommendations"] = _get_retrieval_recommendations(
567
+ repo_root,
568
+ selected_task,
569
+ selected_artifacts,
570
+ )
571
+ return guide
572
+
573
+
574
+ def _get_retrieval_recommendations(
575
+ repo_root: Path,
576
+ selected_task: str | None,
577
+ selected_artifacts: dict[str, object] | None = None,
578
+ ) -> list[dict[str, object]]:
579
+ if not selected_task:
580
+ return []
581
+
582
+ task_dir = _resolve_selected_task_dir(repo_root, selected_task)
583
+ task_info = load_task(task_dir)
584
+ artifacts = (
585
+ selected_artifacts
586
+ or _selected_task_artifacts(repo_root, selected_task)
587
+ or {}
588
+ )
589
+ query = _selected_task_query(selected_task, task_info)
590
+ recommendations: list[dict[str, object]] = []
591
+
592
+ has_local_artifacts = any(
593
+ bool(artifacts.get(key))
594
+ for key in ("prd", "design", "implement", "research", "verify")
595
+ )
596
+ if has_local_artifacts:
597
+ recommendations.append(
598
+ _recommendation(
599
+ "task-artifacts",
600
+ 100,
601
+ "high",
602
+ "Selected task has local planning or evidence artifacts; read them first.",
603
+ "Read selected task prd.md, design.md, implement.md, research/*.md, and verify.md as present.",
604
+ selected_task,
605
+ )
606
+ )
607
+
608
+ recommendations.extend(
609
+ [
610
+ _recommendation(
611
+ "artifact-search",
612
+ 90,
613
+ "high",
614
+ "Search durable Trellis specs, tasks, research, and verification notes for related context.",
615
+ _artifact_search_command(query),
616
+ selected_task,
617
+ ),
618
+ _recommendation(
619
+ "session-memory",
620
+ 80,
621
+ "medium",
622
+ "Search local session history for prior decisions and recent related work.",
623
+ _session_memory_command(query),
624
+ f"{DIR_WORKFLOW}/{DIR_WORKSPACE}/",
625
+ ),
626
+ ]
627
+ )
628
+
629
+ if bool(artifacts.get("research")):
630
+ smart_priority = 55
631
+ smart_confidence = "low"
632
+ smart_reason = (
633
+ "Research artifacts already exist; run Smart Search only for current external source gaps."
634
+ )
635
+ else:
636
+ smart_priority = 70
637
+ smart_confidence = "medium"
638
+ smart_reason = (
639
+ "No selected-task research artifacts are present; capture explicit external evidence when needed."
640
+ )
641
+
642
+ recommendations.extend(
643
+ [
644
+ _recommendation(
645
+ "smart-search",
646
+ smart_priority,
647
+ smart_confidence,
648
+ smart_reason,
649
+ _smart_search_evidence_command(query),
650
+ f"{selected_task}/research/smart-search/",
651
+ ),
652
+ _recommendation(
653
+ "codebase-evidence",
654
+ 60,
655
+ "medium",
656
+ "Confirm candidate codebase evidence against current source, Git state, or validation.",
657
+ "Inspect current source and run focused validation before treating codebase retrieval as proof.",
658
+ "current source tree",
659
+ ),
660
+ ]
661
+ )
662
+
663
+ recommendations.sort(
664
+ key=lambda item: (-int(item["priority"]), str(item["source"]))
665
+ )
666
+ return recommendations
667
+
668
+
669
+ def _present_missing(value: object) -> str:
670
+ return "present" if bool(value) else "missing"
671
+
672
+
673
+ def _append_retrieval_recommendations(
674
+ lines: list[str],
675
+ recommendations: list[dict[str, object]],
676
+ ) -> None:
677
+ if not recommendations:
678
+ return
679
+ lines.append("Retrieval recommendations:")
680
+ for index, recommendation in enumerate(recommendations, start=1):
681
+ source = recommendation.get("source", "")
682
+ confidence = recommendation.get("confidence", "")
683
+ priority = recommendation.get("priority", "")
684
+ reason = recommendation.get("reason", "")
685
+ lines.append(f"{index}. {source} [{confidence}] priority {priority}: {reason}")
686
+ lines.append(f" Action: {recommendation.get('action', '')}")
687
+ lines.append(f" Reference: {recommendation.get('reference', '')}")
688
+
689
+
690
+ def _append_retrieval_guide(
691
+ lines: list[str],
692
+ repo_root: Path,
693
+ selected_task: str | None,
694
+ ) -> None:
695
+ lines.append("## RETRIEVAL GUIDE")
696
+ lines.append(f"Artifact search: {_artifact_search_command()}")
697
+ lines.append(f"Session memory: {_session_memory_command()}")
698
+ lines.append(f"Smart Search evidence: {_smart_search_evidence_command()}")
699
+ lines.append(
700
+ "Use artifact search for durable Trellis specs, tasks, research, "
701
+ "verification notes, and workspace journals."
702
+ )
703
+ lines.append(
704
+ "Use session memory for reusable prior decisions and recent work "
705
+ "recorded in local workspace journals."
706
+ )
707
+ lines.append(
708
+ "Run Smart Search evidence only when external/current source evidence is "
709
+ "needed; it writes a task-local manifest under research/smart-search/."
710
+ )
711
+ lines.append(
712
+ "Codebase evidence: adapter output is candidate evidence until current "
713
+ "source, Git, or validation confirms it."
714
+ )
715
+
716
+ if selected_task:
717
+ lines.append(
718
+ f"Evidence sinks: {selected_task}/research/*.md for exploratory "
719
+ f"chains; {selected_task}/verify.md for final proof."
720
+ )
721
+ artifacts = _selected_task_artifacts(repo_root, selected_task)
722
+ if artifacts:
723
+ research_count = int(artifacts.get("researchCount", 0))
724
+ research_state = (
725
+ f"{research_count} markdown file(s)"
726
+ if research_count
727
+ else _present_missing(artifacts.get("research"))
728
+ )
729
+ lines.append("Selected-task artifacts:")
730
+ lines.append(f"- prd.md: {_present_missing(artifacts.get('prd'))}")
731
+ lines.append(f"- design.md: {_present_missing(artifacts.get('design'))}")
732
+ lines.append(
733
+ f"- implement.md: {_present_missing(artifacts.get('implement'))}"
734
+ )
735
+ lines.append(f"- research/: {research_state}")
736
+ lines.append(f"- verify.md: {_present_missing(artifacts.get('verify'))}")
737
+ _append_retrieval_recommendations(
738
+ lines,
739
+ _get_retrieval_recommendations(repo_root, selected_task, artifacts),
740
+ )
741
+ else:
742
+ lines.append(
743
+ "Evidence sinks: task research/*.md for exploratory chains; task "
744
+ "verify.md for final proof."
745
+ )
746
+ lines.append("")
747
+
748
+
749
+ # =============================================================================
750
+ # JSON Output
751
+ # =============================================================================
752
+
753
+ def get_context_json(repo_root: Path | None = None) -> dict:
754
+ """Get context as a dictionary.
755
+
756
+ Args:
757
+ repo_root: Repository root path. Defaults to auto-detected.
758
+
759
+ Returns:
760
+ Context dictionary.
761
+ """
762
+ if repo_root is None:
763
+ repo_root = get_repo_root()
764
+
765
+ developer = get_developer(repo_root)
766
+ tasks_dir = get_tasks_dir(repo_root)
767
+ journal_file = get_active_journal_file(repo_root)
768
+
769
+ journal_lines = 0
770
+ journal_relative = ""
771
+ if journal_file and developer:
772
+ journal_lines = count_lines(journal_file)
773
+ journal_relative = (
774
+ f"{DIR_WORKFLOW}/{DIR_WORKSPACE}/{developer}/{journal_file.name}"
775
+ )
776
+
777
+ root_git_info = _collect_root_git_info(repo_root)
778
+
779
+ # Tasks
780
+ tasks = [
781
+ {
782
+ "dir": t.dir_name,
783
+ "name": t.name,
784
+ "status": t.status,
785
+ "children": list(t.children),
786
+ "parent": t.parent,
787
+ }
788
+ for t in iter_active_tasks(tasks_dir)
789
+ ]
790
+
791
+ # Package git repos (independent sub-repositories)
792
+ pkg_git_info = _collect_package_git_info(
793
+ repo_root,
794
+ discover_unconfigured=not root_git_info["isRepo"],
795
+ )
796
+ selected_task = get_selected_task(repo_root)
797
+
798
+ result = {
799
+ "developer": developer or "",
800
+ "git": {
801
+ "isRepo": root_git_info["isRepo"],
802
+ "branch": root_git_info["branch"],
803
+ "isClean": root_git_info["isClean"],
804
+ "uncommittedChanges": root_git_info["uncommittedChanges"],
805
+ "recentCommits": root_git_info["recentCommits"],
806
+ },
807
+ "tasks": {
808
+ "active": tasks,
809
+ "directory": f"{DIR_WORKFLOW}/{DIR_TASKS}",
810
+ },
811
+ "journal": {
812
+ "file": journal_relative,
813
+ "lines": journal_lines,
814
+ "nearLimit": journal_lines > 1800,
815
+ },
816
+ "retrievalGuide": _get_retrieval_guide(repo_root, selected_task),
817
+ }
818
+
819
+ if pkg_git_info:
820
+ result["packageGit"] = pkg_git_info
821
+
822
+ return result
823
+
824
+
825
+ def output_json(repo_root: Path | None = None) -> None:
826
+ """Output context in JSON format.
827
+
828
+ Args:
829
+ repo_root: Repository root path. Defaults to auto-detected.
830
+ """
831
+ context = get_context_json(repo_root)
832
+ print(json.dumps(context, indent=2, ensure_ascii=False))
833
+
834
+
835
+ # =============================================================================
836
+ # Text Output
837
+ # =============================================================================
838
+
839
+ def get_context_text(repo_root: Path | None = None) -> str:
840
+ """Get context as formatted text.
841
+
842
+ Args:
843
+ repo_root: Repository root path. Defaults to auto-detected.
844
+
845
+ Returns:
846
+ Formatted text output.
847
+ """
848
+ if repo_root is None:
849
+ repo_root = get_repo_root()
850
+
851
+ lines = []
852
+ lines.append("========================================")
853
+ lines.append("SESSION CONTEXT")
854
+ lines.append("========================================")
855
+ lines.append("")
856
+
857
+ developer = get_developer(repo_root)
858
+
859
+ # Developer section
860
+ lines.append("## DEVELOPER")
861
+ if not developer:
862
+ lines.append(
863
+ f"ERROR: Not initialized. Run: python3 ./{DIR_WORKFLOW}/{DIR_SCRIPTS}/init_developer.py <name>"
864
+ )
865
+ return "\n".join(lines)
866
+
867
+ lines.append(f"Name: {developer}")
868
+ lines.append("")
869
+
870
+ root_git_info = _collect_root_git_info(repo_root)
871
+ _append_root_git_context(lines, root_git_info)
872
+
873
+ # Package git repos — independent sub-repositories
874
+ _append_package_git_context(
875
+ lines,
876
+ _collect_package_git_info(
877
+ repo_root,
878
+ discover_unconfigured=not root_git_info["isRepo"],
879
+ ),
880
+ )
881
+
882
+ # Selected task
883
+ lines.append("## SELECTED TASK")
884
+ selected_task = get_selected_task(repo_root)
885
+ if selected_task:
886
+ selected_task_dir = repo_root / selected_task
887
+ source_type, context_key, _ = get_selected_task_source(repo_root)
888
+ lines.append(f"Path: {selected_task}")
889
+ lines.append(
890
+ f"Source: {source_type}" + (f":{context_key}" if context_key else "")
891
+ )
892
+
893
+ ct = load_task(selected_task_dir)
894
+ if ct:
895
+ lines.append(f"Name: {ct.name}")
896
+ lines.append(f"Status: {ct.status}")
897
+ lines.append(f"Created: {ct.raw.get('createdAt', 'unknown')}")
898
+ if ct.description:
899
+ lines.append(f"Description: {ct.description}")
900
+
901
+ # Check for prd.md
902
+ prd_file = selected_task_dir / "prd.md"
903
+ if prd_file.is_file():
904
+ lines.append("")
905
+ lines.append("[!] This task has prd.md - read it for task details")
906
+ else:
907
+ lines.append("(none)")
908
+ lines.append("")
909
+
910
+ _append_retrieval_guide(lines, repo_root, selected_task)
911
+
912
+ lines.append("## TASK DASHBOARD")
913
+ lines.extend(render_task_dashboard(repo_root).splitlines())
914
+ lines.append("")
915
+
916
+ # Active tasks
917
+ lines.append("## ACTIVE TASKS")
918
+ tasks_dir = get_tasks_dir(repo_root)
919
+ task_count = 0
920
+
921
+ # Collect all task data for hierarchy display
922
+ all_tasks = {t.dir_name: t for t in iter_active_tasks(tasks_dir)}
923
+ all_statuses = {name: t.status for name, t in all_tasks.items()}
924
+
925
+ def _print_task_tree(name: str, indent: int = 0) -> None:
926
+ nonlocal task_count
927
+ t = all_tasks[name]
928
+ progress = children_progress(t.children, all_statuses)
929
+ prefix = " " * indent
930
+ lines.append(f"{prefix}- {name}/ ({t.status}){progress} @{t.assignee or '-'}")
931
+ task_count += 1
932
+ for child in t.children:
933
+ if child in all_tasks:
934
+ _print_task_tree(child, indent + 1)
935
+
936
+ for dir_name in sorted(all_tasks.keys()):
937
+ if not all_tasks[dir_name].parent:
938
+ _print_task_tree(dir_name)
939
+
940
+ if task_count == 0:
941
+ lines.append("(no active tasks)")
942
+ lines.append(f"Total: {task_count} active task(s)")
943
+ lines.append("")
944
+
945
+ # My tasks
946
+ lines.append("## MY TASKS (Assigned to me)")
947
+ my_task_count = 0
948
+
949
+ for t in all_tasks.values():
950
+ if t.assignee == developer and t.status != "done":
951
+ progress = children_progress(t.children, all_statuses)
952
+ lines.append(f"- [{t.priority}] {t.title} ({t.status}){progress}")
953
+ my_task_count += 1
954
+
955
+ if my_task_count == 0:
956
+ lines.append("(no tasks assigned to you)")
957
+ lines.append("")
958
+
959
+ # Journal file
960
+ lines.append("## JOURNAL FILE")
961
+ journal_file = get_active_journal_file(repo_root)
962
+ if journal_file:
963
+ journal_lines = count_lines(journal_file)
964
+ relative = f"{DIR_WORKFLOW}/{DIR_WORKSPACE}/{developer}/{journal_file.name}"
965
+ lines.append(f"Active file: {relative}")
966
+ lines.append(f"Line count: {journal_lines} / 2000")
967
+ if journal_lines > 1800:
968
+ lines.append("[!] WARNING: Approaching 2000 line limit!")
969
+ else:
970
+ lines.append("No journal file found")
971
+ lines.append("")
972
+
973
+ # Packages
974
+ packages_text = get_packages_section(repo_root)
975
+ if packages_text:
976
+ lines.append(packages_text)
977
+ lines.append("")
978
+
979
+ # Paths
980
+ lines.append("## PATHS")
981
+ lines.append(f"Workspace: {DIR_WORKFLOW}/{DIR_WORKSPACE}/{developer}/")
982
+ lines.append(f"Tasks: {DIR_WORKFLOW}/{DIR_TASKS}/")
983
+ lines.append(f"Spec: {DIR_WORKFLOW}/{DIR_SPEC}/")
984
+ lines.append("")
985
+
986
+ lines.append("========================================")
987
+
988
+ return "\n".join(lines)
989
+
990
+
991
+ # =============================================================================
992
+ # Record Mode
993
+ # =============================================================================
994
+
995
+ def get_context_record_json(repo_root: Path | None = None) -> dict:
996
+ """Get record-mode context as a dictionary.
997
+
998
+ Focused on: my active tasks, git status, selected task.
999
+ """
1000
+ if repo_root is None:
1001
+ repo_root = get_repo_root()
1002
+
1003
+ developer = get_developer(repo_root)
1004
+ tasks_dir = get_tasks_dir(repo_root)
1005
+
1006
+ root_git_info = _collect_root_git_info(repo_root)
1007
+
1008
+ # My tasks (single pass — collect statuses and filter by assignee)
1009
+ all_tasks_list = list(iter_active_tasks(tasks_dir))
1010
+ all_statuses = {t.dir_name: t.status for t in all_tasks_list}
1011
+
1012
+ my_tasks = []
1013
+ for t in all_tasks_list:
1014
+ if t.assignee == developer:
1015
+ done = sum(
1016
+ 1 for c in t.children
1017
+ if all_statuses.get(c) in ("completed", "done")
1018
+ )
1019
+ my_tasks.append({
1020
+ "dir": t.dir_name,
1021
+ "title": t.title,
1022
+ "status": t.status,
1023
+ "priority": t.priority,
1024
+ "children": list(t.children),
1025
+ "childrenDone": done,
1026
+ "parent": t.parent,
1027
+ "meta": t.meta,
1028
+ })
1029
+
1030
+ # Selected task
1031
+ selected_task_info = None
1032
+ selected_task = get_selected_task(repo_root)
1033
+ if selected_task:
1034
+ source_type, context_key, _ = get_selected_task_source(repo_root)
1035
+ ct = load_task(repo_root / selected_task)
1036
+ if ct:
1037
+ selected_task_info = {
1038
+ "path": selected_task,
1039
+ "name": ct.name,
1040
+ "status": ct.status,
1041
+ "source": source_type,
1042
+ "contextKey": context_key,
1043
+ }
1044
+
1045
+ # Package git repos
1046
+ pkg_git_info = _collect_package_git_info(
1047
+ repo_root,
1048
+ discover_unconfigured=not root_git_info["isRepo"],
1049
+ )
1050
+
1051
+ result = {
1052
+ "developer": developer or "",
1053
+ "git": {
1054
+ "isRepo": root_git_info["isRepo"],
1055
+ "branch": root_git_info["branch"],
1056
+ "isClean": root_git_info["isClean"],
1057
+ "uncommittedChanges": root_git_info["uncommittedChanges"],
1058
+ "recentCommits": root_git_info["recentCommits"],
1059
+ },
1060
+ "myTasks": my_tasks,
1061
+ "selectedTask": selected_task_info,
1062
+ }
1063
+
1064
+ if pkg_git_info:
1065
+ result["packageGit"] = pkg_git_info
1066
+
1067
+ return result
1068
+
1069
+
1070
+ def get_context_text_record(repo_root: Path | None = None) -> str:
1071
+ """Get context as formatted text for record-session mode.
1072
+
1073
+ Focused output: MY ACTIVE TASKS first (with [!!!] emphasis),
1074
+ then GIT STATUS, RECENT COMMITS, SELECTED TASK.
1075
+ """
1076
+ if repo_root is None:
1077
+ repo_root = get_repo_root()
1078
+
1079
+ lines: list[str] = []
1080
+ lines.append("========================================")
1081
+ lines.append("SESSION CONTEXT (RECORD MODE)")
1082
+ lines.append("========================================")
1083
+ lines.append("")
1084
+
1085
+ developer = get_developer(repo_root)
1086
+ if not developer:
1087
+ lines.append(
1088
+ f"ERROR: Not initialized. Run: python3 ./{DIR_WORKFLOW}/{DIR_SCRIPTS}/init_developer.py <name>"
1089
+ )
1090
+ return "\n".join(lines)
1091
+
1092
+ # MY ACTIVE TASKS — first and prominent
1093
+ lines.append(f"## [!!!] MY ACTIVE TASKS (Assigned to {developer})")
1094
+ lines.append("[!] Review whether any should be archived before recording this session.")
1095
+ lines.append("")
1096
+
1097
+ tasks_dir = get_tasks_dir(repo_root)
1098
+ my_task_count = 0
1099
+
1100
+ # Single pass — collect all tasks and filter by assignee
1101
+ all_statuses = get_all_statuses(tasks_dir)
1102
+
1103
+ for t in iter_active_tasks(tasks_dir):
1104
+ if t.assignee == developer:
1105
+ progress = children_progress(t.children, all_statuses)
1106
+ lines.append(f"- [{t.priority}] {t.title} ({t.status}){progress} — {t.dir_name}")
1107
+ my_task_count += 1
1108
+
1109
+ if my_task_count == 0:
1110
+ lines.append("(no active tasks assigned to you)")
1111
+ lines.append("")
1112
+
1113
+ root_git_info = _collect_root_git_info(repo_root)
1114
+ _append_root_git_context(lines, root_git_info)
1115
+
1116
+ # Package git repos — independent sub-repositories
1117
+ _append_package_git_context(
1118
+ lines,
1119
+ _collect_package_git_info(
1120
+ repo_root,
1121
+ discover_unconfigured=not root_git_info["isRepo"],
1122
+ ),
1123
+ )
1124
+
1125
+ # SELECTED TASK
1126
+ lines.append("## SELECTED TASK")
1127
+ selected_task = get_selected_task(repo_root)
1128
+ if selected_task:
1129
+ source_type, context_key, _ = get_selected_task_source(repo_root)
1130
+ lines.append(f"Path: {selected_task}")
1131
+ lines.append(
1132
+ f"Source: {source_type}" + (f":{context_key}" if context_key else "")
1133
+ )
1134
+ ct = load_task(repo_root / selected_task)
1135
+ if ct:
1136
+ lines.append(f"Name: {ct.name}")
1137
+ lines.append(f"Status: {ct.status}")
1138
+ else:
1139
+ lines.append("(none)")
1140
+ lines.append("")
1141
+
1142
+ lines.append("========================================")
1143
+
1144
+ return "\n".join(lines)
1145
+
1146
+
1147
+ def output_text(repo_root: Path | None = None) -> None:
1148
+ """Output context in text format.
1149
+
1150
+ Args:
1151
+ repo_root: Repository root path. Defaults to auto-detected.
1152
+ """
1153
+ if repo_root is None:
1154
+ repo_root = get_repo_root()
1155
+ update_hint = _get_update_hint(repo_root)
1156
+ if update_hint:
1157
+ print(update_hint)
1158
+ print("")
1159
+ print(get_context_text(repo_root))