jfl 0.4.4 → 0.5.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 (427) hide show
  1. package/dist/commands/context-hub.d.ts.map +1 -1
  2. package/dist/commands/context-hub.js +818 -39
  3. package/dist/commands/context-hub.js.map +1 -1
  4. package/dist/commands/eval.d.ts +1 -1
  5. package/dist/commands/eval.d.ts.map +1 -1
  6. package/dist/commands/eval.js +192 -1
  7. package/dist/commands/eval.js.map +1 -1
  8. package/dist/commands/findings.d.ts +6 -0
  9. package/dist/commands/findings.d.ts.map +1 -0
  10. package/dist/commands/findings.js +203 -0
  11. package/dist/commands/findings.js.map +1 -0
  12. package/dist/commands/hud.d.ts.map +1 -1
  13. package/dist/commands/hud.js +47 -9
  14. package/dist/commands/hud.js.map +1 -1
  15. package/dist/commands/ide.d.ts +27 -0
  16. package/dist/commands/ide.d.ts.map +1 -0
  17. package/dist/commands/ide.js +546 -0
  18. package/dist/commands/ide.js.map +1 -0
  19. package/dist/commands/onboard.d.ts.map +1 -1
  20. package/dist/commands/onboard.js +212 -2
  21. package/dist/commands/onboard.js.map +1 -1
  22. package/dist/commands/openclaw.d.ts +3 -0
  23. package/dist/commands/openclaw.d.ts.map +1 -1
  24. package/dist/commands/openclaw.js +76 -2
  25. package/dist/commands/openclaw.js.map +1 -1
  26. package/dist/commands/peter.d.ts +1 -0
  27. package/dist/commands/peter.d.ts.map +1 -1
  28. package/dist/commands/peter.js +935 -15
  29. package/dist/commands/peter.js.map +1 -1
  30. package/dist/commands/pi-fleet.d.ts +18 -0
  31. package/dist/commands/pi-fleet.d.ts.map +1 -0
  32. package/dist/commands/pi-fleet.js +382 -0
  33. package/dist/commands/pi-fleet.js.map +1 -0
  34. package/dist/commands/pi.d.ts.map +1 -1
  35. package/dist/commands/pi.js +18 -3
  36. package/dist/commands/pi.js.map +1 -1
  37. package/dist/commands/scope.d.ts.map +1 -1
  38. package/dist/commands/scope.js +90 -1
  39. package/dist/commands/scope.js.map +1 -1
  40. package/dist/commands/services.d.ts.map +1 -1
  41. package/dist/commands/services.js +18 -0
  42. package/dist/commands/services.js.map +1 -1
  43. package/dist/commands/status.d.ts.map +1 -1
  44. package/dist/commands/status.js +22 -4
  45. package/dist/commands/status.js.map +1 -1
  46. package/dist/commands/viz.d.ts.map +1 -1
  47. package/dist/commands/viz.js +417 -0
  48. package/dist/commands/viz.js.map +1 -1
  49. package/dist/dashboard-static/assets/index-B6b867Pv.js +121 -0
  50. package/dist/dashboard-static/assets/index-Y4BrqxV-.css +1 -0
  51. package/dist/dashboard-static/index.html +2 -2
  52. package/dist/index.js +225 -61
  53. package/dist/index.js.map +1 -1
  54. package/dist/lib/agent-config.d.ts +52 -0
  55. package/dist/lib/agent-config.d.ts.map +1 -0
  56. package/dist/lib/agent-config.js +231 -0
  57. package/dist/lib/agent-config.js.map +1 -0
  58. package/dist/lib/agent-generator.d.ts +10 -0
  59. package/dist/lib/agent-generator.d.ts.map +1 -1
  60. package/dist/lib/agent-generator.js +64 -10
  61. package/dist/lib/agent-generator.js.map +1 -1
  62. package/dist/lib/agent-session.d.ts +104 -0
  63. package/dist/lib/agent-session.d.ts.map +1 -0
  64. package/dist/lib/agent-session.js +627 -0
  65. package/dist/lib/agent-session.js.map +1 -0
  66. package/dist/lib/eval-snapshot.d.ts +47 -0
  67. package/dist/lib/eval-snapshot.d.ts.map +1 -0
  68. package/dist/lib/eval-snapshot.js +315 -0
  69. package/dist/lib/eval-snapshot.js.map +1 -0
  70. package/dist/lib/eval-store.d.ts +5 -0
  71. package/dist/lib/eval-store.d.ts.map +1 -1
  72. package/dist/lib/eval-store.js +33 -3
  73. package/dist/lib/eval-store.js.map +1 -1
  74. package/dist/lib/findings-engine.d.ts +51 -0
  75. package/dist/lib/findings-engine.d.ts.map +1 -0
  76. package/dist/lib/findings-engine.js +338 -0
  77. package/dist/lib/findings-engine.js.map +1 -0
  78. package/dist/lib/flow-engine.d.ts +8 -0
  79. package/dist/lib/flow-engine.d.ts.map +1 -1
  80. package/dist/lib/flow-engine.js +84 -2
  81. package/dist/lib/flow-engine.js.map +1 -1
  82. package/dist/lib/hub-client.d.ts +1 -0
  83. package/dist/lib/hub-client.d.ts.map +1 -1
  84. package/dist/lib/hub-client.js +33 -6
  85. package/dist/lib/hub-client.js.map +1 -1
  86. package/dist/lib/ide-panes.d.ts +58 -0
  87. package/dist/lib/ide-panes.d.ts.map +1 -0
  88. package/dist/lib/ide-panes.js +508 -0
  89. package/dist/lib/ide-panes.js.map +1 -0
  90. package/dist/lib/memory-db.js +4 -4
  91. package/dist/lib/memory-db.js.map +1 -1
  92. package/dist/lib/memory-indexer.d.ts.map +1 -1
  93. package/dist/lib/memory-indexer.js +3 -0
  94. package/dist/lib/memory-indexer.js.map +1 -1
  95. package/dist/lib/memory-search.d.ts +148 -4
  96. package/dist/lib/memory-search.d.ts.map +1 -1
  97. package/dist/lib/memory-search.js +496 -58
  98. package/dist/lib/memory-search.js.map +1 -1
  99. package/dist/lib/meta-orchestrator.d.ts +104 -0
  100. package/dist/lib/meta-orchestrator.d.ts.map +1 -0
  101. package/dist/lib/meta-orchestrator.js +373 -0
  102. package/dist/lib/meta-orchestrator.js.map +1 -0
  103. package/dist/lib/peer-agent-generator.d.ts.map +1 -1
  104. package/dist/lib/peer-agent-generator.js +43 -19
  105. package/dist/lib/peer-agent-generator.js.map +1 -1
  106. package/dist/lib/policy-head.d.ts +25 -0
  107. package/dist/lib/policy-head.d.ts.map +1 -0
  108. package/dist/lib/policy-head.js +136 -0
  109. package/dist/lib/policy-head.js.map +1 -0
  110. package/dist/lib/replay-buffer.d.ts +93 -0
  111. package/dist/lib/replay-buffer.d.ts.map +1 -0
  112. package/dist/lib/replay-buffer.js +302 -0
  113. package/dist/lib/replay-buffer.js.map +1 -0
  114. package/dist/lib/sentinel-rl.d.ts +97 -0
  115. package/dist/lib/sentinel-rl.d.ts.map +1 -0
  116. package/dist/lib/sentinel-rl.js +430 -0
  117. package/dist/lib/sentinel-rl.js.map +1 -0
  118. package/dist/lib/session-lock.d.ts +61 -0
  119. package/dist/lib/session-lock.d.ts.map +1 -0
  120. package/dist/lib/session-lock.js +438 -0
  121. package/dist/lib/session-lock.js.map +1 -0
  122. package/dist/lib/stratus-client.d.ts +1 -0
  123. package/dist/lib/stratus-client.d.ts.map +1 -1
  124. package/dist/lib/stratus-client.js +24 -2
  125. package/dist/lib/stratus-client.js.map +1 -1
  126. package/dist/lib/telemetry-agent-v2.d.ts +128 -0
  127. package/dist/lib/telemetry-agent-v2.d.ts.map +1 -0
  128. package/dist/lib/telemetry-agent-v2.js +1042 -0
  129. package/dist/lib/telemetry-agent-v2.js.map +1 -0
  130. package/dist/lib/telemetry-agent.d.ts.map +1 -1
  131. package/dist/lib/telemetry-agent.js +27 -6
  132. package/dist/lib/telemetry-agent.js.map +1 -1
  133. package/dist/lib/telemetry-digest.d.ts.map +1 -1
  134. package/dist/lib/telemetry-digest.js +27 -5
  135. package/dist/lib/telemetry-digest.js.map +1 -1
  136. package/dist/lib/telemetry.d.ts.map +1 -1
  137. package/dist/lib/telemetry.js +29 -4
  138. package/dist/lib/telemetry.js.map +1 -1
  139. package/dist/lib/text-preprocessing.d.ts +83 -0
  140. package/dist/lib/text-preprocessing.d.ts.map +1 -0
  141. package/dist/lib/text-preprocessing.js +261 -0
  142. package/dist/lib/text-preprocessing.js.map +1 -0
  143. package/dist/lib/training-buffer.d.ts +86 -0
  144. package/dist/lib/training-buffer.d.ts.map +1 -0
  145. package/dist/lib/training-buffer.js +139 -0
  146. package/dist/lib/training-buffer.js.map +1 -0
  147. package/dist/lib/tuple-miner.d.ts +30 -0
  148. package/dist/lib/tuple-miner.d.ts.map +1 -0
  149. package/dist/lib/tuple-miner.js +427 -0
  150. package/dist/lib/tuple-miner.js.map +1 -0
  151. package/dist/lib/vm-backend.d.ts +72 -0
  152. package/dist/lib/vm-backend.d.ts.map +1 -0
  153. package/dist/lib/vm-backend.js +175 -0
  154. package/dist/lib/vm-backend.js.map +1 -0
  155. package/dist/lib/workspace/backend.d.ts +53 -0
  156. package/dist/lib/workspace/backend.d.ts.map +1 -0
  157. package/dist/lib/workspace/backend.js +37 -0
  158. package/dist/lib/workspace/backend.js.map +1 -0
  159. package/dist/lib/workspace/cmux-adapter.d.ts +46 -0
  160. package/dist/lib/workspace/cmux-adapter.d.ts.map +1 -0
  161. package/dist/lib/workspace/cmux-adapter.js +261 -0
  162. package/dist/lib/workspace/cmux-adapter.js.map +1 -0
  163. package/dist/lib/workspace/data-pipeline.d.ts +35 -0
  164. package/dist/lib/workspace/data-pipeline.d.ts.map +1 -0
  165. package/dist/lib/workspace/data-pipeline.js +463 -0
  166. package/dist/lib/workspace/data-pipeline.js.map +1 -0
  167. package/dist/lib/workspace/engine.d.ts +64 -0
  168. package/dist/lib/workspace/engine.d.ts.map +1 -0
  169. package/dist/lib/workspace/engine.js +397 -0
  170. package/dist/lib/workspace/engine.js.map +1 -0
  171. package/dist/lib/workspace/notifications.d.ts +14 -0
  172. package/dist/lib/workspace/notifications.d.ts.map +1 -0
  173. package/dist/lib/workspace/notifications.js +41 -0
  174. package/dist/lib/workspace/notifications.js.map +1 -0
  175. package/dist/lib/workspace/surface-registry.d.ts +49 -0
  176. package/dist/lib/workspace/surface-registry.d.ts.map +1 -0
  177. package/dist/lib/workspace/surface-registry.js +217 -0
  178. package/dist/lib/workspace/surface-registry.js.map +1 -0
  179. package/dist/lib/workspace/surface-type.d.ts +153 -0
  180. package/dist/lib/workspace/surface-type.d.ts.map +1 -0
  181. package/dist/lib/workspace/surface-type.js +9 -0
  182. package/dist/lib/workspace/surface-type.js.map +1 -0
  183. package/dist/lib/workspace/surfaces/agent-overview.d.ts +16 -0
  184. package/dist/lib/workspace/surfaces/agent-overview.d.ts.map +1 -0
  185. package/dist/lib/workspace/surfaces/agent-overview.js +116 -0
  186. package/dist/lib/workspace/surfaces/agent-overview.js.map +1 -0
  187. package/dist/lib/workspace/surfaces/agent.d.ts +16 -0
  188. package/dist/lib/workspace/surfaces/agent.d.ts.map +1 -0
  189. package/dist/lib/workspace/surfaces/agent.js +112 -0
  190. package/dist/lib/workspace/surfaces/agent.js.map +1 -0
  191. package/dist/lib/workspace/surfaces/claude.d.ts +15 -0
  192. package/dist/lib/workspace/surfaces/claude.d.ts.map +1 -0
  193. package/dist/lib/workspace/surfaces/claude.js +23 -0
  194. package/dist/lib/workspace/surfaces/claude.js.map +1 -0
  195. package/dist/lib/workspace/surfaces/dashboard.d.ts +21 -0
  196. package/dist/lib/workspace/surfaces/dashboard.d.ts.map +1 -0
  197. package/dist/lib/workspace/surfaces/dashboard.js +32 -0
  198. package/dist/lib/workspace/surfaces/dashboard.js.map +1 -0
  199. package/dist/lib/workspace/surfaces/eval.d.ts +15 -0
  200. package/dist/lib/workspace/surfaces/eval.d.ts.map +1 -0
  201. package/dist/lib/workspace/surfaces/eval.js +42 -0
  202. package/dist/lib/workspace/surfaces/eval.js.map +1 -0
  203. package/dist/lib/workspace/surfaces/event-stream.d.ts +16 -0
  204. package/dist/lib/workspace/surfaces/event-stream.d.ts.map +1 -0
  205. package/dist/lib/workspace/surfaces/event-stream.js +40 -0
  206. package/dist/lib/workspace/surfaces/event-stream.js.map +1 -0
  207. package/dist/lib/workspace/surfaces/flow.d.ts +16 -0
  208. package/dist/lib/workspace/surfaces/flow.d.ts.map +1 -0
  209. package/dist/lib/workspace/surfaces/flow.js +49 -0
  210. package/dist/lib/workspace/surfaces/flow.js.map +1 -0
  211. package/dist/lib/workspace/surfaces/index.d.ts +16 -0
  212. package/dist/lib/workspace/surfaces/index.d.ts.map +1 -0
  213. package/dist/lib/workspace/surfaces/index.js +16 -0
  214. package/dist/lib/workspace/surfaces/index.js.map +1 -0
  215. package/dist/lib/workspace/surfaces/portfolio.d.ts +16 -0
  216. package/dist/lib/workspace/surfaces/portfolio.d.ts.map +1 -0
  217. package/dist/lib/workspace/surfaces/portfolio.js +102 -0
  218. package/dist/lib/workspace/surfaces/portfolio.js.map +1 -0
  219. package/dist/lib/workspace/surfaces/service.d.ts +16 -0
  220. package/dist/lib/workspace/surfaces/service.d.ts.map +1 -0
  221. package/dist/lib/workspace/surfaces/service.js +45 -0
  222. package/dist/lib/workspace/surfaces/service.js.map +1 -0
  223. package/dist/lib/workspace/surfaces/shell.d.ts +15 -0
  224. package/dist/lib/workspace/surfaces/shell.d.ts.map +1 -0
  225. package/dist/lib/workspace/surfaces/shell.js +19 -0
  226. package/dist/lib/workspace/surfaces/shell.js.map +1 -0
  227. package/dist/lib/workspace/surfaces/telemetry.d.ts +16 -0
  228. package/dist/lib/workspace/surfaces/telemetry.d.ts.map +1 -0
  229. package/dist/lib/workspace/surfaces/telemetry.js +48 -0
  230. package/dist/lib/workspace/surfaces/telemetry.js.map +1 -0
  231. package/dist/lib/workspace/surfaces/topology.d.ts +15 -0
  232. package/dist/lib/workspace/surfaces/topology.d.ts.map +1 -0
  233. package/dist/lib/workspace/surfaces/topology.js +19 -0
  234. package/dist/lib/workspace/surfaces/topology.js.map +1 -0
  235. package/dist/lib/workspace/surfaces/training.d.ts +16 -0
  236. package/dist/lib/workspace/surfaces/training.d.ts.map +1 -0
  237. package/dist/lib/workspace/surfaces/training.js +22 -0
  238. package/dist/lib/workspace/surfaces/training.js.map +1 -0
  239. package/dist/lib/workspace/tmux-adapter.d.ts +27 -0
  240. package/dist/lib/workspace/tmux-adapter.d.ts.map +1 -0
  241. package/dist/lib/workspace/tmux-adapter.js +106 -0
  242. package/dist/lib/workspace/tmux-adapter.js.map +1 -0
  243. package/dist/mcp/context-hub-mcp.js +7 -24
  244. package/dist/mcp/context-hub-mcp.js.map +1 -1
  245. package/dist/types/flows.d.ts +2 -0
  246. package/dist/types/flows.d.ts.map +1 -1
  247. package/dist/types/ide.d.ts +49 -0
  248. package/dist/types/ide.d.ts.map +1 -0
  249. package/dist/types/ide.js +5 -0
  250. package/dist/types/ide.js.map +1 -0
  251. package/dist/types/platform-digest.d.ts +228 -0
  252. package/dist/types/platform-digest.d.ts.map +1 -0
  253. package/dist/types/platform-digest.js +5 -0
  254. package/dist/types/platform-digest.js.map +1 -0
  255. package/dist/types/telemetry-digest.d.ts +2 -0
  256. package/dist/types/telemetry-digest.d.ts.map +1 -1
  257. package/dist/utils/ensure-project.d.ts +1 -0
  258. package/dist/utils/ensure-project.d.ts.map +1 -1
  259. package/dist/utils/ensure-project.js +19 -7
  260. package/dist/utils/ensure-project.js.map +1 -1
  261. package/dist/utils/jfl-config.d.ts +1 -0
  262. package/dist/utils/jfl-config.d.ts.map +1 -1
  263. package/dist/utils/jfl-config.js +19 -1
  264. package/dist/utils/jfl-config.js.map +1 -1
  265. package/dist/utils/jfl-paths.d.ts +5 -0
  266. package/dist/utils/jfl-paths.d.ts.map +1 -1
  267. package/dist/utils/jfl-paths.js +25 -3
  268. package/dist/utils/jfl-paths.js.map +1 -1
  269. package/package.json +3 -2
  270. package/packages/pi/AGENTS.md +112 -0
  271. package/packages/pi/extensions/agent-grid.ts +191 -0
  272. package/packages/pi/extensions/agent-names.ts +178 -0
  273. package/packages/pi/extensions/autoresearch.ts +427 -0
  274. package/packages/pi/extensions/bookmarks.ts +85 -0
  275. package/packages/pi/extensions/context.ts +151 -0
  276. package/packages/pi/extensions/crm-tool.ts +61 -0
  277. package/packages/pi/extensions/eval-tool.ts +224 -0
  278. package/packages/pi/extensions/eval.ts +60 -0
  279. package/packages/pi/extensions/footer.ts +239 -0
  280. package/packages/pi/extensions/hud-tool.ts +145 -0
  281. package/packages/pi/extensions/index.ts +392 -0
  282. package/packages/pi/extensions/journal.ts +224 -0
  283. package/packages/pi/extensions/map-bridge.ts +178 -0
  284. package/packages/pi/extensions/memory-tool.ts +68 -0
  285. package/packages/pi/extensions/notifications.ts +73 -0
  286. package/packages/pi/extensions/peter-parker.ts +202 -0
  287. package/packages/pi/extensions/policy-head-tool.ts +276 -0
  288. package/packages/pi/extensions/portfolio-bridge.ts +90 -0
  289. package/packages/pi/extensions/session.ts +90 -0
  290. package/packages/pi/extensions/shortcuts.ts +259 -0
  291. package/packages/pi/extensions/stratus-bridge.ts +115 -0
  292. package/packages/pi/extensions/synopsis-tool.ts +83 -0
  293. package/packages/pi/extensions/tool-renderers.ts +352 -0
  294. package/packages/pi/extensions/training-buffer-tool.ts +368 -0
  295. package/packages/pi/extensions/types.ts +163 -0
  296. package/packages/pi/package-lock.json +346 -0
  297. package/packages/pi/package.json +44 -0
  298. package/packages/pi/skills/agent-browser/SKILL.md +116 -0
  299. package/packages/pi/skills/brand-architect/SKILL.md +240 -0
  300. package/packages/pi/skills/brand-architect/config.yaml +137 -0
  301. package/packages/pi/skills/campaign-hud/config.yaml +112 -0
  302. package/packages/pi/skills/content-creator/SKILL.md +294 -0
  303. package/packages/pi/skills/context/SKILL.md +65 -0
  304. package/packages/pi/skills/debug/MULTI_AGENT.md +360 -0
  305. package/packages/pi/skills/debug/SKILL.md +554 -0
  306. package/packages/pi/skills/end/SKILL.md +1782 -0
  307. package/packages/pi/skills/eval/SKILL.md +75 -0
  308. package/packages/pi/skills/fly-deploy/SKILL.md +676 -0
  309. package/packages/pi/skills/founder-video/SKILL.md +467 -0
  310. package/packages/pi/skills/hud/SKILL.md +160 -0
  311. package/packages/pi/skills/orchestrate/SKILL.md +74 -0
  312. package/packages/pi/skills/pi-agents/SKILL.md +78 -0
  313. package/packages/pi/skills/react-best-practices/AGENTS.md +2249 -0
  314. package/packages/pi/skills/react-best-practices/README.md +123 -0
  315. package/packages/pi/skills/react-best-practices/SKILL.md +125 -0
  316. package/packages/pi/skills/react-best-practices/metadata.json +15 -0
  317. package/packages/pi/skills/react-best-practices/rules/_sections.md +46 -0
  318. package/packages/pi/skills/react-best-practices/rules/_template.md +28 -0
  319. package/packages/pi/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  320. package/packages/pi/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  321. package/packages/pi/skills/react-best-practices/rules/async-api-routes.md +38 -0
  322. package/packages/pi/skills/react-best-practices/rules/async-defer-await.md +80 -0
  323. package/packages/pi/skills/react-best-practices/rules/async-dependencies.md +36 -0
  324. package/packages/pi/skills/react-best-practices/rules/async-parallel.md +28 -0
  325. package/packages/pi/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  326. package/packages/pi/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  327. package/packages/pi/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  328. package/packages/pi/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  329. package/packages/pi/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  330. package/packages/pi/skills/react-best-practices/rules/bundle-preload.md +50 -0
  331. package/packages/pi/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  332. package/packages/pi/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  333. package/packages/pi/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  334. package/packages/pi/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  335. package/packages/pi/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  336. package/packages/pi/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  337. package/packages/pi/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  338. package/packages/pi/skills/react-best-practices/rules/js-early-exit.md +50 -0
  339. package/packages/pi/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  340. package/packages/pi/skills/react-best-practices/rules/js-index-maps.md +37 -0
  341. package/packages/pi/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  342. package/packages/pi/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  343. package/packages/pi/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  344. package/packages/pi/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  345. package/packages/pi/skills/react-best-practices/rules/rendering-activity.md +26 -0
  346. package/packages/pi/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  347. package/packages/pi/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  348. package/packages/pi/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  349. package/packages/pi/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  350. package/packages/pi/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  351. package/packages/pi/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  352. package/packages/pi/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  353. package/packages/pi/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  354. package/packages/pi/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  355. package/packages/pi/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  356. package/packages/pi/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  357. package/packages/pi/skills/react-best-practices/rules/rerender-memo.md +44 -0
  358. package/packages/pi/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  359. package/packages/pi/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  360. package/packages/pi/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  361. package/packages/pi/skills/react-best-practices/rules/server-cache-react.md +26 -0
  362. package/packages/pi/skills/react-best-practices/rules/server-parallel-fetching.md +79 -0
  363. package/packages/pi/skills/react-best-practices/rules/server-serialization.md +38 -0
  364. package/packages/pi/skills/remotion-best-practices/SKILL.md +43 -0
  365. package/packages/pi/skills/remotion-best-practices/rules/3d.md +86 -0
  366. package/packages/pi/skills/remotion-best-practices/rules/animations.md +29 -0
  367. package/packages/pi/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
  368. package/packages/pi/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
  369. package/packages/pi/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +108 -0
  370. package/packages/pi/skills/remotion-best-practices/rules/assets.md +78 -0
  371. package/packages/pi/skills/remotion-best-practices/rules/audio.md +172 -0
  372. package/packages/pi/skills/remotion-best-practices/rules/calculate-metadata.md +104 -0
  373. package/packages/pi/skills/remotion-best-practices/rules/can-decode.md +75 -0
  374. package/packages/pi/skills/remotion-best-practices/rules/charts.md +58 -0
  375. package/packages/pi/skills/remotion-best-practices/rules/compositions.md +146 -0
  376. package/packages/pi/skills/remotion-best-practices/rules/display-captions.md +126 -0
  377. package/packages/pi/skills/remotion-best-practices/rules/extract-frames.md +229 -0
  378. package/packages/pi/skills/remotion-best-practices/rules/fonts.md +152 -0
  379. package/packages/pi/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
  380. package/packages/pi/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  381. package/packages/pi/skills/remotion-best-practices/rules/get-video-duration.md +58 -0
  382. package/packages/pi/skills/remotion-best-practices/rules/gifs.md +138 -0
  383. package/packages/pi/skills/remotion-best-practices/rules/images.md +130 -0
  384. package/packages/pi/skills/remotion-best-practices/rules/import-srt-captions.md +67 -0
  385. package/packages/pi/skills/remotion-best-practices/rules/lottie.md +68 -0
  386. package/packages/pi/skills/remotion-best-practices/rules/measuring-dom-nodes.md +35 -0
  387. package/packages/pi/skills/remotion-best-practices/rules/measuring-text.md +143 -0
  388. package/packages/pi/skills/remotion-best-practices/rules/sequencing.md +106 -0
  389. package/packages/pi/skills/remotion-best-practices/rules/tailwind.md +11 -0
  390. package/packages/pi/skills/remotion-best-practices/rules/text-animations.md +20 -0
  391. package/packages/pi/skills/remotion-best-practices/rules/timing.md +179 -0
  392. package/packages/pi/skills/remotion-best-practices/rules/transcribe-captions.md +19 -0
  393. package/packages/pi/skills/remotion-best-practices/rules/transitions.md +122 -0
  394. package/packages/pi/skills/remotion-best-practices/rules/trimming.md +53 -0
  395. package/packages/pi/skills/remotion-best-practices/rules/videos.md +171 -0
  396. package/packages/pi/skills/search/SKILL.md +220 -0
  397. package/packages/pi/skills/spec/SKILL.md +377 -0
  398. package/packages/pi/skills/startup/SKILL.md +315 -0
  399. package/packages/pi/skills/web-architect/SKILL.md +309 -0
  400. package/packages/pi/skills/x-algorithm/SKILL.md +305 -0
  401. package/packages/pi/teams/dev-team.yaml +63 -0
  402. package/packages/pi/teams/gtm-team.yaml +79 -0
  403. package/packages/pi/themes/jfl.theme.json +76 -0
  404. package/packages/pi/tsconfig.json +21 -0
  405. package/scripts/collect-tuples.sh +124 -0
  406. package/scripts/destroy-fleet.sh +37 -0
  407. package/scripts/jfl-ide.sh +48 -0
  408. package/scripts/session/session-cleanup.sh +4 -11
  409. package/scripts/session/session-init.sh +6 -0
  410. package/scripts/session/session-sync.sh +25 -0
  411. package/scripts/setup-branch-protection.sh +106 -0
  412. package/scripts/spawn-fleet.sh +144 -0
  413. package/scripts/train-policy-head.py +434 -0
  414. package/scripts/vm-swarm/README.md +301 -0
  415. package/scripts/vm-swarm/collect-tuples.sh +331 -0
  416. package/scripts/vm-swarm/create-base-template.sh +339 -0
  417. package/scripts/vm-swarm/kill-fleet.sh +204 -0
  418. package/scripts/vm-swarm/monitor-fleet.sh +346 -0
  419. package/scripts/vm-swarm/spawn-fleet.sh +304 -0
  420. package/template/.github/workflows/jfl-eval.yml +6 -1
  421. package/template/.github/workflows/jfl-review.yml +4 -0
  422. package/template/scripts/session/session-end.sh +69 -6
  423. package/template/scripts/session/session-init.sh +55 -30
  424. package/template/scripts/session/session-lock.sh +464 -0
  425. package/template/templates/service-agent/workflows/jfl-eval.yml +19 -0
  426. package/dist/dashboard-static/assets/index-B6kRK9Rq.js +0 -116
  427. package/dist/dashboard-static/assets/index-BpdKJPLu.css +0 -1
@@ -0,0 +1,145 @@
1
+ /**
2
+ * HUD Tool Extension
3
+ *
4
+ * Registers jfl_hud tool and /hud command with custom TUI rendering.
5
+ * Shows a themed, collapsible dashboard in the tool output.
6
+ * Updates the aboveEditor widget after each agent turn.
7
+ *
8
+ * @purpose jfl_hud tool + /hud command + themed widget + custom rendering
9
+ */
10
+
11
+ import { existsSync, readFileSync } from "fs"
12
+ import { join } from "path"
13
+ import { execSync } from "child_process"
14
+ import type { PiContext, PiTheme } from "./types.js"
15
+ import { hudRenderCall, hudRenderResult } from "./tool-renderers.js"
16
+
17
+ let projectRoot = ""
18
+
19
+ function getDaysToLaunch(root: string): string | null {
20
+ const roadmapPath = join(root, "knowledge", "ROADMAP.md")
21
+ if (!existsSync(roadmapPath)) return null
22
+
23
+ const content = readFileSync(roadmapPath, "utf-8")
24
+ const dateMatch = content.match(/(\d{4}-\d{2}-\d{2})/m)
25
+ if (!dateMatch) return null
26
+
27
+ const launchDate = new Date(dateMatch[1])
28
+ const now = new Date()
29
+ const diff = Math.ceil((launchDate.getTime() - now.getTime()) / 86400000)
30
+ return diff > 0 ? `${diff}d to launch` : `${Math.abs(diff)}d past launch`
31
+ }
32
+
33
+ function getProjectPhase(root: string): string {
34
+ const roadmapPath = join(root, "knowledge", "ROADMAP.md")
35
+ if (!existsSync(roadmapPath)) return "unknown"
36
+
37
+ const content = readFileSync(roadmapPath, "utf-8")
38
+ const sameLineMatch = content.match(/## (?:Phase|Current Phase)[:\t ]*([^\n]+)/i)
39
+ if (sameLineMatch && sameLineMatch[1].trim() && !sameLineMatch[1].trim().startsWith("```")) {
40
+ return sameLineMatch[1].trim()
41
+ }
42
+
43
+ const sectionMatch = content.match(/## (?:Phase|Current Phase)[^\n]*\n+([^\n]+)/i)
44
+ if (sectionMatch) {
45
+ let line = sectionMatch[1].trim()
46
+ if (line.startsWith("```")) return "unknown"
47
+ line = line.replace(/^[`*_[\]]+|[`*_[\]]+$/g, "")
48
+ return line || "unknown"
49
+ }
50
+
51
+ return "unknown"
52
+ }
53
+
54
+ function buildHudLines(root: string): string[] {
55
+ const configPath = join(root, ".jfl", "config.json")
56
+ let projectName = root.split("/").pop() ?? "JFL"
57
+ let projectType = "gtm"
58
+
59
+ if (existsSync(configPath)) {
60
+ try {
61
+ const config = JSON.parse(readFileSync(configPath, "utf-8")) as { name?: string; type?: string }
62
+ if (config.name) projectName = config.name
63
+ if (config.type) projectType = config.type
64
+ } catch {}
65
+ }
66
+
67
+ const days = getDaysToLaunch(root)
68
+ const phase = getProjectPhase(root)
69
+
70
+ const lines = [
71
+ `◆ ${projectName} [${projectType}]`,
72
+ days ? ` ${days}` : "",
73
+ phase !== "unknown" ? ` Phase: ${phase}` : "",
74
+ ].filter(Boolean)
75
+
76
+ try {
77
+ const crmOutput = execSync("./crm list --compact 2>/dev/null | head -3", {
78
+ cwd: root,
79
+ timeout: 5000,
80
+ encoding: "utf-8",
81
+ }).trim()
82
+ if (crmOutput) {
83
+ lines.push(" Pipeline:", ...crmOutput.split("\n").map(l => ` ${l}`))
84
+ }
85
+ } catch {}
86
+
87
+ return lines
88
+ }
89
+
90
+ export function setupHudTool(ctx: PiContext): void {
91
+ projectRoot = ctx.session.projectRoot
92
+
93
+ // Themed widget above editor
94
+ ctx.ui.setWidget("jfl-hud", (_tui: any, theme: PiTheme) => {
95
+ const lines = buildHudLines(projectRoot)
96
+ const themed = lines.map((line, i) => {
97
+ if (i === 0) return theme.fg("accent", line)
98
+ if (line.includes("Phase:")) return theme.fg("warning", line)
99
+ if (line.includes("Pipeline")) return theme.fg("accent", line)
100
+ return theme.fg("muted", line)
101
+ })
102
+ return {
103
+ render: () => themed,
104
+ invalidate() {},
105
+ }
106
+ })
107
+
108
+ ctx.registerTool({
109
+ name: "jfl_hud",
110
+ description: "Get the current JFL project dashboard — timeline, phase, pipeline status, and next action",
111
+ promptSnippet: "Show project dashboard with timeline, phase, and pipeline",
112
+ inputSchema: {
113
+ type: "object",
114
+ properties: {},
115
+ },
116
+ async handler() {
117
+ return buildHudLines(projectRoot).join("\n")
118
+ },
119
+ renderCall: hudRenderCall,
120
+ renderResult: hudRenderResult,
121
+ })
122
+
123
+ ctx.registerCommand({
124
+ name: "hud",
125
+ description: "Show project dashboard",
126
+ async handler(_args, ctx) {
127
+ const lines = buildHudLines(projectRoot)
128
+ ctx.ui.notify(lines.join("\n"), { level: "info" })
129
+ },
130
+ })
131
+ }
132
+
133
+ export async function updateHudWidget(ctx: PiContext): Promise<void> {
134
+ if (!projectRoot) return
135
+ ctx.ui.setWidget("jfl-hud", (_tui: any, theme: PiTheme) => {
136
+ const lines = buildHudLines(projectRoot)
137
+ const themed = lines.map((line, i) => {
138
+ if (i === 0) return theme.fg("accent", line)
139
+ if (line.includes("Phase:")) return theme.fg("warning", line)
140
+ if (line.includes("Pipeline")) return theme.fg("accent", line)
141
+ return theme.fg("muted", line)
142
+ })
143
+ return { render: () => themed, invalidate() {} }
144
+ })
145
+ }
@@ -0,0 +1,392 @@
1
+ /**
2
+ * JFL Pi Extension — Master Entry (Factory Function)
3
+ *
4
+ * Pi loads this as a factory: export default async function(pi: ExtensionAPI).
5
+ * We construct a PiContext shim exposing full Pi TUI capabilities to all
6
+ * JFL sub-extensions: overlays, custom footer, shortcuts, tool rendering,
7
+ * interactive dialogs, notifications, state persistence, and more.
8
+ *
9
+ * @purpose Master entry point for @jfl/pi — full TUI-powered extension
10
+ */
11
+
12
+ import { readFileSync, existsSync } from "fs"
13
+ import { join } from "path"
14
+ import { execSync } from "child_process"
15
+ import type { PiContext, JflConfig, JflToolDef, JflCommandDef, PiTheme } from "./types.js"
16
+ import { setupSession, onShutdown } from "./session.js"
17
+ import { setupContext, injectContext } from "./context.js"
18
+ import { setupJournal, checkJournalBeforeCompact, onJournalAgentEnd, onToolExecutionEnd } from "./journal.js"
19
+ import { setupMapBridge, onMapBridgeShutdown, onMapToolEnd } from "./map-bridge.js"
20
+ import { setupEval, onAgentEnd as onEvalEnd } from "./eval.js"
21
+ import { setupHudTool, updateHudWidget } from "./hud-tool.js"
22
+ import { setupCrmTool } from "./crm-tool.js"
23
+ import { setupMemoryTool } from "./memory-tool.js"
24
+ import { setupSynopsisTool } from "./synopsis-tool.js"
25
+ import { initStratusBridge, onAgentStart as onStratusStart, onAgentEnd as onStratusEnd } from "./stratus-bridge.js"
26
+ import { setupPeterParker } from "./peter-parker.js"
27
+ import { setupPortfolioBridge, onPortfolioShutdown } from "./portfolio-bridge.js"
28
+ import { setupAgentGrid } from "./agent-grid.js"
29
+ import { initAgentNames } from "./agent-names.js"
30
+ import { setupEvalTool } from "./eval-tool.js"
31
+ import { setupPolicyHeadTool } from "./policy-head-tool.js"
32
+ import { setupTrainingBufferTool, onTrainingAgentEnd } from "./training-buffer-tool.js"
33
+ import { setupAutoresearch } from "./autoresearch.js"
34
+ import { setupFooter } from "./footer.js"
35
+ import { setupShortcuts } from "./shortcuts.js"
36
+ import { setupNotifications } from "./notifications.js"
37
+ import { setupBookmarks } from "./bookmarks.js"
38
+
39
+ function readJflConfig(projectRoot: string): JflConfig {
40
+ const configPath = join(projectRoot, ".jfl", "config.json")
41
+ if (!existsSync(configPath)) return {}
42
+ try {
43
+ return JSON.parse(readFileSync(configPath, "utf-8")) as JflConfig
44
+ } catch {
45
+ return {}
46
+ }
47
+ }
48
+
49
+ function getProjectName(projectRoot: string, config: JflConfig): string {
50
+ if (config.name) return config.name
51
+ const visionPath = join(projectRoot, "knowledge", "VISION.md")
52
+ if (existsSync(visionPath)) {
53
+ const content = readFileSync(visionPath, "utf-8")
54
+ const match = content.match(/^#\s+(.+)/m)
55
+ if (match) return match[1].trim()
56
+ }
57
+ return projectRoot.split("/").pop() ?? "JFL Project"
58
+ }
59
+
60
+ function getCurrentBranch(root: string): string {
61
+ try {
62
+ return execSync("git branch --show-current", { cwd: root, stdio: ["pipe", "pipe", "ignore"] })
63
+ .toString().trim() || "main"
64
+ } catch {
65
+ return "main"
66
+ }
67
+ }
68
+
69
+ // ─── Pi extension factory function ───────────────────────────────────────────
70
+
71
+ export default async function jflExtension(pi: any): Promise<void> {
72
+ let projectCwd = process.cwd()
73
+ let latestPiCtx: any = null
74
+
75
+ const internalHandlers = new Map<string, Array<(data: unknown) => void | Promise<void>>>()
76
+
77
+ function jflOn(event: string, handler: (data: unknown) => void | Promise<void>): void {
78
+ const list = internalHandlers.get(event) ?? []
79
+ list.push(handler)
80
+ internalHandlers.set(event, list)
81
+ }
82
+
83
+ function jflEmit(event: string, data?: unknown): void {
84
+ const list = internalHandlers.get(event) ?? []
85
+ list.forEach(h => Promise.resolve(h(data)).catch(() => {}))
86
+ }
87
+
88
+ // ─── Theme helper ───────────────────────────────────────────────────────────
89
+
90
+ function getTheme(): PiTheme {
91
+ if (latestPiCtx?.ui?.theme) return latestPiCtx.ui.theme
92
+ return {
93
+ fg: (_color: string, text: string) => text,
94
+ bg: (_color: string, text: string) => text,
95
+ bold: (text: string) => text,
96
+ }
97
+ }
98
+
99
+ // ─── PiContext shim — full TUI capabilities ─────────────────────────────────
100
+
101
+ const ctx: PiContext = {
102
+ get session() {
103
+ return {
104
+ projectRoot: projectCwd,
105
+ id: pi.getSessionName?.() ?? "jfl",
106
+ branch: getCurrentBranch(projectCwd),
107
+ }
108
+ },
109
+
110
+ log: (msg: string, level?: string) => {
111
+ const prefix = level === "debug" ? "[JFL debug]" : "[JFL]"
112
+ console.log(`${prefix} ${msg}`)
113
+ },
114
+
115
+ emit: jflEmit,
116
+ on: jflOn,
117
+
118
+ registerTool: (tool: JflToolDef) => {
119
+ pi.registerTool({
120
+ name: tool.name,
121
+ label: tool.label ?? tool.name,
122
+ description: tool.description,
123
+ promptSnippet: tool.promptSnippet,
124
+ promptGuidelines: tool.promptGuidelines,
125
+ parameters: tool.inputSchema,
126
+ async execute(_id: string, params: Record<string, unknown>) {
127
+ try {
128
+ const result = await tool.handler(params)
129
+ return {
130
+ content: [{ type: "text", text: result }],
131
+ details: { raw: result, toolName: tool.name },
132
+ }
133
+ } catch (err) {
134
+ throw new Error(`${err}`)
135
+ }
136
+ },
137
+ renderCall: tool.renderCall
138
+ ? (args: Record<string, any>, theme: PiTheme) => tool.renderCall!(args, theme)
139
+ : undefined,
140
+ renderResult: tool.renderResult
141
+ ? (result: any, options: any, theme: PiTheme) => tool.renderResult!(result, options, theme)
142
+ : undefined,
143
+ })
144
+ },
145
+
146
+ registerCommand: (cmd: JflCommandDef) => {
147
+ pi.registerCommand(cmd.name, {
148
+ description: cmd.description,
149
+ handler: async (args: string, piCtx: any) => {
150
+ latestPiCtx = piCtx
151
+ await cmd.handler(args, ctx)
152
+ },
153
+ })
154
+ },
155
+
156
+ registerShortcut: (key: string, opts: { description: string; handler: () => Promise<void> | void }) => {
157
+ pi.registerShortcut(key, {
158
+ description: opts.description,
159
+ handler: async (piCtx: any) => {
160
+ latestPiCtx = piCtx
161
+ await opts.handler()
162
+ },
163
+ })
164
+ },
165
+
166
+ ui: {
167
+ notify: (msg: string, opts?: { level?: string }) => {
168
+ const type = opts?.level ?? "info"
169
+ if (latestPiCtx?.ui?.notify) {
170
+ latestPiCtx.ui.notify(msg, type)
171
+ } else {
172
+ console.log(`[JFL ${type}] ${msg}`)
173
+ }
174
+ },
175
+
176
+ input: async (title: string, placeholder?: string) => {
177
+ if (latestPiCtx?.ui?.input) return latestPiCtx.ui.input(title, placeholder)
178
+ return undefined
179
+ },
180
+
181
+ confirm: async (title: string, message: string) => {
182
+ if (latestPiCtx?.ui?.confirm) return latestPiCtx.ui.confirm(title, message)
183
+ return false
184
+ },
185
+
186
+ select: async <T extends string>(title: string, items: Array<{ value: T; label: string; description?: string }>) => {
187
+ if (latestPiCtx?.ui?.select) return latestPiCtx.ui.select(title, items)
188
+ return null
189
+ },
190
+
191
+ editor: async (title: string, content: string) => {
192
+ if (latestPiCtx?.ui?.editor) return latestPiCtx.ui.editor(title, content)
193
+ return undefined
194
+ },
195
+
196
+ custom: async <T>(factory: any, opts?: any) => {
197
+ if (latestPiCtx?.ui?.custom) return latestPiCtx.ui.custom(factory, opts)
198
+ return undefined as T
199
+ },
200
+
201
+ setWidget: (id: string, content: any, opts?: { placement?: string }) => {
202
+ if (!latestPiCtx?.ui?.setWidget) return
203
+ if (content === undefined) {
204
+ latestPiCtx.ui.setWidget(id, undefined)
205
+ } else if (typeof content === "function") {
206
+ latestPiCtx.ui.setWidget(id, content, opts)
207
+ } else {
208
+ latestPiCtx.ui.setWidget(id, content, opts)
209
+ }
210
+ },
211
+
212
+ setStatus: (key: string, text: string | undefined) => {
213
+ if (latestPiCtx?.ui?.setStatus) latestPiCtx.ui.setStatus(key, text)
214
+ },
215
+
216
+ setFooter: (factory: any) => {
217
+ if (latestPiCtx?.ui?.setFooter) latestPiCtx.ui.setFooter(factory)
218
+ },
219
+
220
+ setEditorText: (text: string) => {
221
+ if (latestPiCtx?.ui?.setEditorText) latestPiCtx.ui.setEditorText(text)
222
+ },
223
+
224
+ get theme(): PiTheme {
225
+ return getTheme()
226
+ },
227
+
228
+ get hasUI(): boolean {
229
+ return latestPiCtx?.hasUI ?? false
230
+ },
231
+ },
232
+
233
+ pi: {
234
+ setSessionName: (name: string) => pi.setSessionName(name),
235
+
236
+ appendEntry: (type: string, data?: unknown) => {
237
+ if (pi.appendEntry) pi.appendEntry(type, data)
238
+ },
239
+
240
+ setLabel: (entryId: string, label: string | undefined) => {
241
+ if (pi.setLabel) pi.setLabel(entryId, label)
242
+ },
243
+
244
+ sendMessage: (msg: any, opts?: any) => {
245
+ if (pi.sendMessage) pi.sendMessage(msg, opts)
246
+ },
247
+
248
+ events: {
249
+ on: (event: string, handler: (data: unknown) => void) => {
250
+ if (pi.events?.on) pi.events.on(event, handler)
251
+ },
252
+ emit: (event: string, data?: unknown) => {
253
+ if (pi.events?.emit) pi.events.emit(event, data)
254
+ },
255
+ },
256
+
257
+ getActiveTools: () => pi.getActiveTools?.() ?? [],
258
+ getAllTools: () => pi.getAllTools?.() ?? [],
259
+
260
+ exec: async (command: string, args: string[], opts?: any) => {
261
+ if (pi.exec) return pi.exec(command, args, opts)
262
+ return { stdout: "", stderr: "exec unavailable", code: 1 }
263
+ },
264
+
265
+ get sessionManager() { return latestPiCtx?.sessionManager },
266
+ get model() { return latestPiCtx?.model },
267
+ },
268
+
269
+ cancel: () => ({ cancel: true as const }),
270
+ }
271
+
272
+ // ─── Session tracking state ────────────────────────────────────────────────
273
+
274
+ let turnCount = 0
275
+ let sessionStartTime = Date.now()
276
+ let currentModel = ""
277
+
278
+ // ─── Lifecycle handlers ────────────────────────────────────────────────────
279
+
280
+ pi.on("session_start", async (_event: unknown, piCtx: any) => {
281
+ latestPiCtx = piCtx
282
+ projectCwd = piCtx.cwd
283
+ turnCount = 0
284
+ sessionStartTime = Date.now()
285
+ currentModel = piCtx.model?.id ?? ""
286
+
287
+ const config = readJflConfig(projectCwd)
288
+ const projectName = getProjectName(projectCwd, config)
289
+
290
+ pi.setSessionName(`JFL: ${projectName}`)
291
+
292
+ await setupMapBridge(ctx, config)
293
+ await setupSession(ctx, config)
294
+ await setupContext(ctx, config)
295
+ await setupJournal(ctx, config)
296
+ await setupEval(ctx, config)
297
+
298
+ setupHudTool(ctx)
299
+ setupCrmTool(ctx)
300
+ setupMemoryTool(ctx)
301
+ setupSynopsisTool(ctx)
302
+ await setupEvalTool(ctx, config)
303
+ await setupPolicyHeadTool(ctx, config)
304
+ await setupTrainingBufferTool(ctx, config)
305
+ await setupAutoresearch(ctx, config)
306
+
307
+ initStratusBridge(projectCwd)
308
+ initAgentNames(projectCwd)
309
+ await setupPeterParker(ctx, config)
310
+ await setupPortfolioBridge(ctx, config)
311
+ setupAgentGrid(ctx)
312
+
313
+ setupFooter(ctx, config, { turnCount: () => turnCount, sessionStart: () => sessionStartTime, model: () => currentModel })
314
+ if (!config.pi?.disable_shortcuts) setupShortcuts(ctx, config)
315
+ if (!config.pi?.disable_notifications) setupNotifications(ctx, config)
316
+ setupBookmarks(ctx)
317
+
318
+ ctx.log(`JFL: ${projectName} — session ready`)
319
+
320
+ if (config.pi?.auto_start !== false && pi.sendUserMessage) {
321
+ setTimeout(() => {
322
+ pi.sendUserMessage(
323
+ `JFL session started in "${projectName}". Use the jfl_context tool to read recent project context, then show a brief status update with current focus and any blocking issues.`
324
+ )
325
+ }, 500)
326
+ }
327
+ })
328
+
329
+ pi.on("session_shutdown", async (_event: unknown, piCtx: any) => {
330
+ latestPiCtx = piCtx
331
+ await onPortfolioShutdown(ctx)
332
+ await onShutdown(ctx)
333
+ await onMapBridgeShutdown(ctx)
334
+ })
335
+
336
+ pi.on("session_before_compact", async (_event: unknown, piCtx: any) => {
337
+ latestPiCtx = piCtx
338
+ return checkJournalBeforeCompact(ctx)
339
+ })
340
+
341
+ pi.on("before_agent_start", async (event: any, piCtx: any) => {
342
+ latestPiCtx = piCtx
343
+ const result = await injectContext(ctx, event)
344
+ if (result?.systemPromptAddition) {
345
+ const current = piCtx.getSystemPrompt?.() ?? ""
346
+ return {
347
+ systemPrompt: current
348
+ ? `${current}\n\n${result.systemPromptAddition}`
349
+ : result.systemPromptAddition,
350
+ }
351
+ }
352
+ })
353
+
354
+ pi.on("agent_start", async (event: any, piCtx: any) => {
355
+ latestPiCtx = piCtx
356
+ await onStratusStart(ctx, event)
357
+ jflEmit("agent:start", event)
358
+ })
359
+
360
+ pi.on("agent_end", async (event: any, piCtx: any) => {
361
+ latestPiCtx = piCtx
362
+ await onStratusEnd(ctx, event)
363
+ await onEvalEnd(ctx, event)
364
+ await onTrainingAgentEnd(ctx, event)
365
+ await updateHudWidget(ctx)
366
+ await onJournalAgentEnd(ctx, event)
367
+ jflEmit("agent:end", event)
368
+ })
369
+
370
+ pi.on("turn_start", async (event: any, piCtx: any) => {
371
+ latestPiCtx = piCtx
372
+ turnCount++
373
+ jflEmit("turn:start", { ...event, turnCount })
374
+ })
375
+
376
+ pi.on("turn_end", async (event: any, piCtx: any) => {
377
+ latestPiCtx = piCtx
378
+ jflEmit("turn:end", { ...event, turnCount })
379
+ })
380
+
381
+ pi.on("tool_execution_end", async (event: any, piCtx: any) => {
382
+ latestPiCtx = piCtx
383
+ await onToolExecutionEnd(ctx, event)
384
+ await onMapToolEnd(ctx, event)
385
+ })
386
+
387
+ pi.on("model_select", async (event: any, piCtx: any) => {
388
+ latestPiCtx = piCtx
389
+ currentModel = event.model?.id ?? ""
390
+ jflEmit("model:changed", event)
391
+ })
392
+ }