@hassangameryt/freeflow 0.7.3 → 0.9.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 (426) hide show
  1. package/.agents/plugins/marketplace.json +2 -2
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/.claude-plugin/plugin.json +2 -2
  4. package/.codex-plugin/plugin.json +3 -3
  5. package/.cursor-plugin/plugin.json +1 -1
  6. package/NOTICE +14 -0
  7. package/README.md +101 -159
  8. package/capabilities/cognitive-routing/SKILL.md +47 -210
  9. package/capabilities/cognitive-routing/references/coordinator.md +163 -0
  10. package/capabilities/cognitive-routing/references/worker.md +38 -0
  11. package/capabilities/compaction/SKILL.md +49 -0
  12. package/capabilities/compaction/references/summary-format.md +250 -0
  13. package/capabilities/messaging/SKILL.md +49 -0
  14. package/capabilities/task-memory/SKILL.md +87 -0
  15. package/command-surface.json +8 -52
  16. package/gemini-extension.json +1 -1
  17. package/hooks/claude/hooks.json +13 -3
  18. package/hooks/codex/hooks.json +2 -1
  19. package/hooks/shared/runtime-context.mjs +73 -83
  20. package/licenses/Apache-2.0.txt +55 -0
  21. package/package.json +42 -12
  22. package/pi-extension/README.md +41 -0
  23. package/pi-extension/dist/ask-user/ask.js +108 -0
  24. package/pi-extension/dist/ask-user/form.js +250 -0
  25. package/pi-extension/dist/ask-user/questions.js +66 -0
  26. package/pi-extension/dist/ask-user/tool.js +124 -0
  27. package/pi-extension/dist/cognitive-routing/assembler.js +417 -0
  28. package/pi-extension/dist/cognitive-routing/bootstrap.js +90 -0
  29. package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/config.js +8 -6
  30. package/pi-extension/dist/cognitive-routing/economics.js +45 -0
  31. package/pi-extension/dist/cognitive-routing/event-schema.js +388 -0
  32. package/pi-extension/dist/{session-sources/events.js → cognitive-routing/event-store.js} +107 -41
  33. package/pi-extension/dist/cognitive-routing/gate.js +256 -0
  34. package/pi-extension/dist/cognitive-routing/handlers.js +901 -0
  35. package/pi-extension/dist/cognitive-routing/handoffs.js +350 -0
  36. package/pi-extension/dist/cognitive-routing/model-control.js +476 -0
  37. package/pi-extension/dist/cognitive-routing/projection.js +520 -0
  38. package/pi-extension/dist/cognitive-routing/provenance.js +83 -0
  39. package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/render.js +15 -15
  40. package/pi-extension/dist/cognitive-routing/runtime.js +398 -0
  41. package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/schemas.js +47 -11
  42. package/pi-extension/dist/cognitive-routing/session.js +223 -0
  43. package/pi-extension/dist/{session-sources → cognitive-routing}/sources.js +126 -87
  44. package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/state.js +55 -386
  45. package/pi-extension/dist/cognitive-routing/status.js +81 -0
  46. package/pi-extension/dist/cognitive-routing/tools.js +74 -0
  47. package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/types.js +14 -11
  48. package/pi-extension/dist/compaction/carry.js +205 -0
  49. package/pi-extension/dist/compaction/config.js +24 -0
  50. package/pi-extension/dist/compaction/controller.js +494 -0
  51. package/pi-extension/dist/compaction/harness.js +93 -0
  52. package/pi-extension/dist/compaction/results.js +159 -0
  53. package/pi-extension/dist/compaction/thresholds.js +35 -0
  54. package/pi-extension/dist/compaction/tool.js +57 -0
  55. package/pi-extension/dist/host/branch.js +13 -0
  56. package/pi-extension/dist/host/canonical.js +12 -0
  57. package/pi-extension/dist/host/catalog.js +62 -0
  58. package/pi-extension/dist/host/config-validation.js +233 -0
  59. package/pi-extension/dist/host/config.js +361 -0
  60. package/pi-extension/dist/host/inbound.js +142 -0
  61. package/pi-extension/dist/host/projection-tags.js +60 -0
  62. package/pi-extension/dist/host/prompts.js +93 -0
  63. package/pi-extension/dist/{session-sources → host}/read-only-session.js +117 -1
  64. package/pi-extension/dist/{runtime → host}/request-history.js +125 -39
  65. package/pi-extension/dist/host/rows.js +25 -0
  66. package/pi-extension/dist/host/runtime-state.js +204 -0
  67. package/pi-extension/dist/host/section-keeper.js +85 -0
  68. package/pi-extension/dist/host/settings/freeflow-command.js +2323 -0
  69. package/pi-extension/dist/{settings/settings-tui.js → host/settings/settings-view.js} +205 -73
  70. package/pi-extension/dist/host/staging.js +28 -0
  71. package/pi-extension/dist/host/status.js +115 -0
  72. package/pi-extension/dist/index.js +1004 -188
  73. package/pi-extension/dist/messaging/config.js +27 -0
  74. package/pi-extension/dist/messaging/messaging.js +398 -0
  75. package/pi-extension/dist/messaging/registry.js +57 -0
  76. package/pi-extension/dist/messaging/render.js +90 -0
  77. package/pi-extension/dist/messaging/tools.js +109 -0
  78. package/pi-extension/dist/messaging/transport.js +101 -0
  79. package/pi-extension/dist/provider-support/cache/anchor.js +21 -0
  80. package/pi-extension/dist/provider-support/cache/anthropic.js +102 -0
  81. package/pi-extension/dist/provider-support/cache/health.js +73 -0
  82. package/pi-extension/dist/provider-support/cache/index.js +58 -0
  83. package/pi-extension/dist/provider-support/cache/keepalive.js +222 -0
  84. package/pi-extension/dist/provider-support/cache/monitor.js +17 -0
  85. package/pi-extension/dist/provider-support/cache/openai-responses.js +48 -0
  86. package/pi-extension/dist/provider-support/effort.js +13 -0
  87. package/pi-extension/dist/provider-support/index.js +44 -3
  88. package/pi-extension/dist/provider-support/{astra → openai}/adapter.js +46 -29
  89. package/pi-extension/dist/provider-support/{astra → openai}/history.js +10 -8
  90. package/pi-extension/dist/provider-support/{astra → openai}/index.js +8 -4
  91. package/pi-extension/dist/provider-support/{astra → openai}/session-state.js +29 -38
  92. package/pi-extension/dist/provider-support/routes.js +17 -0
  93. package/pi-extension/dist/task-memory/config.js +49 -0
  94. package/pi-extension/dist/task-memory/registry.js +119 -0
  95. package/pi-extension/dist/task-memory/render.js +107 -0
  96. package/pi-extension/dist/task-memory/runtime.js +994 -0
  97. package/pi-extension/dist/task-memory/tool.js +233 -0
  98. package/pi-extension/dist/tool-execution/apply-patch/grammar.js +23 -0
  99. package/pi-extension/dist/tool-execution/apply-patch/match.js +38 -0
  100. package/pi-extension/dist/tool-execution/apply-patch/parser.js +177 -0
  101. package/pi-extension/dist/tool-execution/apply-patch/plan.js +201 -0
  102. package/pi-extension/dist/tool-execution/apply-patch/tool.js +84 -0
  103. package/pi-extension/dist/tool-execution/background.js +430 -0
  104. package/pi-extension/dist/tool-execution/bash-guard.js +23 -0
  105. package/pi-extension/dist/tool-execution/config.js +33 -0
  106. package/pi-extension/dist/tool-execution/edit-messages.js +120 -0
  107. package/pi-extension/dist/tool-execution/file-state.js +138 -0
  108. package/pi-extension/dist/tool-execution/file-tracking.js +163 -0
  109. package/pi-extension/dist/tool-execution/guidance-notices.js +124 -0
  110. package/pi-extension/dist/tool-execution/prompt.js +54 -0
  111. package/pi-extension/dist/tool-execution/skill-reads.js +143 -0
  112. package/pi-extension/dist/tool-execution/tools.js +16 -0
  113. package/pi-extension/freeflow/README.md +9 -0
  114. package/runtime/prompts/cognitive-routing.md +4 -4
  115. package/runtime/prompts/core.md +29 -72
  116. package/runtime/prompts/interaction-contract.md +18 -8
  117. package/runtime/prompts/tool-execution.md +25 -0
  118. package/runtime/prompts/working-method.md +25 -0
  119. package/skills/deliver-work/SKILL.md +76 -0
  120. package/skills/deliver-work/references/branch-closeout.md +134 -0
  121. package/skills/deliver-work/references/commit.md +83 -0
  122. package/skills/deliver-work/references/launch.md +94 -0
  123. package/skills/deliver-work/references/release.md +85 -0
  124. package/skills/deliver-work/scripts/commit-state.mjs +139 -0
  125. package/skills/deliver-work/scripts/delivery-state.mjs +107 -0
  126. package/skills/deliver-work/scripts/lib/git-state.mjs +178 -0
  127. package/skills/deliver-work/scripts/push-route.mjs +122 -0
  128. package/skills/deliver-work/scripts/release-preflight.mjs +177 -0
  129. package/skills/discuss-work/SKILL.md +148 -0
  130. package/skills/{discuss → discuss-work}/references/discussion-continuity.md +13 -50
  131. package/skills/discuss-work/references/learning-action.md +36 -0
  132. package/skills/discuss-work/scripts/choices.mjs +101 -0
  133. package/skills/discuss-work/scripts/lib/choices.mjs +159 -0
  134. package/skills/evaluate-behavior/SKILL.md +107 -0
  135. package/skills/evaluate-behavior/references/authoring.md +381 -0
  136. package/skills/evaluate-behavior/references/coding-tasks.md +145 -0
  137. package/skills/evaluate-behavior/references/conversations-pipelines-judges.md +177 -0
  138. package/skills/evaluate-behavior/references/design-and-measurement.md +273 -0
  139. package/skills/evaluate-behavior/references/running-and-evidence.md +245 -0
  140. package/skills/evaluate-behavior/scripts/claude-guard.mjs +76 -0
  141. package/skills/evaluate-behavior/scripts/guard-rules.mjs +309 -0
  142. package/skills/evaluate-behavior/scripts/lib/agreement.mjs +90 -0
  143. package/skills/evaluate-behavior/scripts/lib/arms.mjs +55 -0
  144. package/skills/evaluate-behavior/scripts/lib/budget.mjs +87 -0
  145. package/skills/evaluate-behavior/scripts/lib/build-source.mjs +287 -0
  146. package/skills/evaluate-behavior/scripts/lib/clear.mjs +74 -0
  147. package/skills/evaluate-behavior/scripts/lib/container.mjs +395 -0
  148. package/skills/evaluate-behavior/scripts/lib/decision.mjs +418 -0
  149. package/skills/evaluate-behavior/scripts/lib/definitions.mjs +1072 -0
  150. package/skills/evaluate-behavior/scripts/lib/freeflow.mjs +103 -0
  151. package/skills/evaluate-behavior/scripts/lib/grade-command.mjs +591 -0
  152. package/skills/evaluate-behavior/scripts/lib/grade-comparison.mjs +90 -0
  153. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-interaction.mjs +19 -18
  154. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-support.mjs +32 -5
  155. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-workspace.mjs +28 -12
  156. package/skills/evaluate-behavior/scripts/lib/grade.mjs +101 -0
  157. package/skills/evaluate-behavior/scripts/lib/hooks.mjs +98 -0
  158. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/confinement.mjs +196 -0
  159. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/constraints.mjs +111 -0
  160. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/index.mjs +48 -0
  161. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/isolation.mjs +74 -0
  162. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/launch.mjs +123 -0
  163. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/model-call.mjs +73 -0
  164. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/recorder.mjs +178 -0
  165. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/session.mjs +494 -0
  166. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/skills.mjs +81 -0
  167. package/skills/evaluate-behavior/scripts/lib/hosts/index.mjs +31 -0
  168. package/skills/evaluate-behavior/scripts/lib/hosts/names.mjs +3 -0
  169. package/skills/evaluate-behavior/scripts/lib/hosts/pi/confinement.mjs +173 -0
  170. package/skills/evaluate-behavior/scripts/lib/hosts/pi/host.mjs +148 -0
  171. package/skills/evaluate-behavior/scripts/lib/hosts/pi/index.mjs +70 -0
  172. package/skills/evaluate-behavior/scripts/lib/hosts/pi/isolation.mjs +81 -0
  173. package/skills/evaluate-behavior/scripts/lib/hosts/pi/model-call.mjs +79 -0
  174. package/skills/evaluate-behavior/scripts/lib/hosts/pi/process.mjs +241 -0
  175. package/skills/{evaluate-skill/scripts/lib → evaluate-behavior/scripts/lib/hosts/pi}/rpc.mjs +144 -26
  176. package/skills/evaluate-behavior/scripts/lib/identity.mjs +82 -0
  177. package/skills/evaluate-behavior/scripts/lib/judge.mjs +688 -0
  178. package/skills/evaluate-behavior/scripts/lib/metrics.mjs +332 -0
  179. package/skills/evaluate-behavior/scripts/lib/model-call.mjs +17 -0
  180. package/skills/evaluate-behavior/scripts/lib/participants.mjs +616 -0
  181. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/process.mjs +22 -0
  182. package/skills/evaluate-behavior/scripts/lib/queue.mjs +54 -0
  183. package/skills/evaluate-behavior/scripts/lib/reference.mjs +343 -0
  184. package/skills/evaluate-behavior/scripts/lib/reuse.mjs +277 -0
  185. package/skills/evaluate-behavior/scripts/lib/review.mjs +933 -0
  186. package/skills/evaluate-behavior/scripts/lib/runner.mjs +732 -0
  187. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/sandbox.mjs +121 -14
  188. package/skills/evaluate-behavior/scripts/lib/scan-shell.mjs +457 -0
  189. package/skills/evaluate-behavior/scripts/lib/scan.mjs +479 -0
  190. package/skills/evaluate-behavior/scripts/lib/seal.mjs +91 -0
  191. package/skills/evaluate-behavior/scripts/lib/shell.mjs +560 -0
  192. package/skills/evaluate-behavior/scripts/lib/source-override.mjs +64 -0
  193. package/skills/evaluate-behavior/scripts/lib/subject-file.mjs +88 -0
  194. package/skills/{evaluate-skill/scripts/lib/pi.mjs → evaluate-behavior/scripts/lib/subject.mjs} +239 -262
  195. package/skills/evaluate-behavior/scripts/lib/task-copy.mjs +124 -0
  196. package/skills/evaluate-behavior/scripts/lib/trials.mjs +524 -0
  197. package/skills/evaluate-behavior/scripts/lib/validity.mjs +68 -0
  198. package/skills/evaluate-behavior/scripts/lib/view-html.mjs +454 -0
  199. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/view.mjs +218 -11
  200. package/skills/evaluate-behavior/scripts/pi-command-tool.mjs +159 -0
  201. package/skills/evaluate-behavior/scripts/pi-container-route.mjs +23 -0
  202. package/skills/evaluate-behavior/scripts/pi-guard.mjs +77 -0
  203. package/skills/evaluate-behavior/scripts/pi-login-refresh.mjs +31 -0
  204. package/skills/evaluate-behavior/scripts/skill-eval.mjs +586 -0
  205. package/skills/execute-work/SKILL.md +96 -72
  206. package/skills/execute-work/references/code-practices.md +27 -49
  207. package/skills/execute-work/references/design.md +271 -0
  208. package/skills/execute-work/references/diagnose.md +117 -0
  209. package/skills/execute-work/references/migration.md +108 -0
  210. package/skills/execute-work/references/simplify.md +65 -0
  211. package/skills/execute-work/scripts/self-review.mjs +422 -0
  212. package/skills/execute-work/scripts/touch-map.mjs +290 -0
  213. package/skills/review-work/SKILL.md +94 -64
  214. package/skills/review-work/references/adjudication.md +94 -0
  215. package/skills/review-work/references/artifact.md +198 -0
  216. package/skills/review-work/references/evals-and-judges.md +66 -0
  217. package/skills/review-work/references/work.md +177 -0
  218. package/skills/review-work/scripts/check-brief.mjs +128 -0
  219. package/skills/review-work/scripts/review-packet.mjs +233 -0
  220. package/skills/setup-freeflow/SKILL.md +69 -16
  221. package/skills/track-work/SKILL.md +135 -151
  222. package/skills/track-work/references/handoff.md +190 -0
  223. package/skills/track-work/references/projects.md +51 -0
  224. package/skills/track-work/references/working-record-format.md +201 -344
  225. package/skills/track-work/scripts/lib/document.mjs +79 -19
  226. package/skills/track-work/scripts/lib/format.mjs +18 -1
  227. package/skills/track-work/scripts/lib/recover.mjs +254 -0
  228. package/skills/track-work/scripts/lib/registry.mjs +656 -0
  229. package/skills/track-work/scripts/lib/search.mjs +40 -0
  230. package/skills/track-work/scripts/lib/store.mjs +53 -21
  231. package/skills/track-work/scripts/lib/transitions.mjs +79 -4
  232. package/skills/track-work/scripts/lib/views.mjs +50 -1
  233. package/skills/track-work/scripts/working-record.mjs +263 -22
  234. package/skills/verify-work/SKILL.md +64 -47
  235. package/skills/verify-work/references/feature-map.md +120 -0
  236. package/skills/verify-work/references/runtime-evidence.md +203 -0
  237. package/skills/verify-work/references/test-design.md +27 -6
  238. package/skills/verify-work/scripts/test-changes.mjs +246 -0
  239. package/skills/write-docs/SKILL.md +171 -0
  240. package/skills/write-docs/references/documentation-shapes.md +184 -0
  241. package/skills/write-docs/references/spec-and-plan-shapes.md +308 -0
  242. package/skills/write-docs/scripts/artifact-check.mjs +148 -0
  243. package/skills/write-docs/scripts/docs-check.mjs +229 -0
  244. package/skills/write-docs/scripts/plan-lint.mjs +123 -0
  245. package/skills/write-skill/SKILL.md +165 -165
  246. package/skills/write-skill/references/activation-and-wording.md +143 -0
  247. package/skills/write-skill/references/placement-and-dependencies.md +154 -0
  248. package/skills/write-skill/scripts/lib/compare.mjs +701 -0
  249. package/skills/write-skill/scripts/lib/similarity.mjs +56 -0
  250. package/skills/write-skill/scripts/lib/skill-author.mjs +197 -3
  251. package/skills/write-skill/scripts/skill-author.mjs +67 -8
  252. package/capabilities/context-virtualization/SKILL.md +0 -103
  253. package/capabilities/conversation-history/SKILL.md +0 -53
  254. package/hooks/tests/check-host-adapters.test.mjs +0 -82
  255. package/hooks/tests/check-runtime-context-hook.sh +0 -212
  256. package/pi-extension/dist/cognitive-routing-v2/projection.js +0 -330
  257. package/pi-extension/dist/cognitive-routing-v2/runtime.js +0 -2181
  258. package/pi-extension/dist/cognitive-routing-v2/tools.js +0 -60
  259. package/pi-extension/dist/context-virtualization/commands.js +0 -89
  260. package/pi-extension/dist/context-virtualization/projector.js +0 -42
  261. package/pi-extension/dist/context-virtualization/runtime.js +0 -378
  262. package/pi-extension/dist/context-virtualization/state.js +0 -57
  263. package/pi-extension/dist/context-virtualization/types.js +0 -10
  264. package/pi-extension/dist/conversation-history/passages.js +0 -66
  265. package/pi-extension/dist/conversation-history/ranking.js +0 -105
  266. package/pi-extension/dist/conversation-history/runtime.js +0 -226
  267. package/pi-extension/dist/conversation-history/search.js +0 -56
  268. package/pi-extension/dist/conversation-history/types.js +0 -1
  269. package/pi-extension/dist/freeflow-context/resolver.js +0 -120
  270. package/pi-extension/dist/freeflow-context/runtime.js +0 -80
  271. package/pi-extension/dist/freeflow-context/source-projector.js +0 -95
  272. package/pi-extension/dist/freeflow-context/tool.js +0 -314
  273. package/pi-extension/dist/freeflow-context/types.js +0 -12
  274. package/pi-extension/dist/freeflow-context/visibility.js +0 -28
  275. package/pi-extension/dist/integrations/mcp-config.js +0 -29
  276. package/pi-extension/dist/runtime/runtime-context.js +0 -754
  277. package/pi-extension/dist/runtime/runtime-identity.js +0 -5
  278. package/pi-extension/dist/session-sources/provenance.js +0 -32
  279. package/pi-extension/dist/settings/settings-ui.js +0 -1360
  280. package/pi-extension/dist/ui/text-component.js +0 -57
  281. package/pi-extension/src/cognitive-routing-v2/budget.ts +0 -42
  282. package/pi-extension/src/cognitive-routing-v2/config.ts +0 -173
  283. package/pi-extension/src/cognitive-routing-v2/projection.ts +0 -375
  284. package/pi-extension/src/cognitive-routing-v2/render.ts +0 -277
  285. package/pi-extension/src/cognitive-routing-v2/runtime.ts +0 -2241
  286. package/pi-extension/src/cognitive-routing-v2/schemas.ts +0 -180
  287. package/pi-extension/src/cognitive-routing-v2/state.ts +0 -839
  288. package/pi-extension/src/cognitive-routing-v2/tools.ts +0 -62
  289. package/pi-extension/src/cognitive-routing-v2/types.ts +0 -254
  290. package/pi-extension/src/context-virtualization/commands.ts +0 -111
  291. package/pi-extension/src/context-virtualization/projector.ts +0 -62
  292. package/pi-extension/src/context-virtualization/runtime.ts +0 -428
  293. package/pi-extension/src/context-virtualization/state.ts +0 -79
  294. package/pi-extension/src/context-virtualization/types.ts +0 -92
  295. package/pi-extension/src/conversation-history/passages.ts +0 -81
  296. package/pi-extension/src/conversation-history/ranking.ts +0 -155
  297. package/pi-extension/src/conversation-history/runtime.ts +0 -250
  298. package/pi-extension/src/conversation-history/search.ts +0 -79
  299. package/pi-extension/src/conversation-history/types.ts +0 -31
  300. package/pi-extension/src/freeflow-context/resolver.ts +0 -139
  301. package/pi-extension/src/freeflow-context/runtime.ts +0 -100
  302. package/pi-extension/src/freeflow-context/source-projector.ts +0 -106
  303. package/pi-extension/src/freeflow-context/tool.ts +0 -366
  304. package/pi-extension/src/freeflow-context/types.ts +0 -70
  305. package/pi-extension/src/freeflow-context/visibility.ts +0 -53
  306. package/pi-extension/src/index.ts +0 -390
  307. package/pi-extension/src/integrations/mcp-config.ts +0 -32
  308. package/pi-extension/src/provider-support/astra/adapter.ts +0 -108
  309. package/pi-extension/src/provider-support/astra/history.ts +0 -145
  310. package/pi-extension/src/provider-support/astra/index.ts +0 -12
  311. package/pi-extension/src/provider-support/astra/session-state.ts +0 -113
  312. package/pi-extension/src/provider-support/index.ts +0 -5
  313. package/pi-extension/src/runtime/request-history.ts +0 -243
  314. package/pi-extension/src/runtime/runtime-context.ts +0 -860
  315. package/pi-extension/src/runtime/runtime-identity.ts +0 -8
  316. package/pi-extension/src/session-sources/events.ts +0 -230
  317. package/pi-extension/src/session-sources/provenance.ts +0 -39
  318. package/pi-extension/src/session-sources/read-only-session.ts +0 -170
  319. package/pi-extension/src/session-sources/sources.ts +0 -334
  320. package/pi-extension/src/settings/settings-tui.ts +0 -501
  321. package/pi-extension/src/settings/settings-ui.ts +0 -1652
  322. package/pi-extension/src/ui/text-component.ts +0 -66
  323. package/pi-extension/tests/cache-reuse/history.test.js +0 -117
  324. package/pi-extension/tests/cache-reuse/native.test.js +0 -91
  325. package/pi-extension/tests/cache-reuse/settings.test.js +0 -211
  326. package/pi-extension/tests/cognitive-routing-v2/communication.test.js +0 -577
  327. package/pi-extension/tests/cognitive-routing-v2/compaction-input.test.js +0 -183
  328. package/pi-extension/tests/cognitive-routing-v2/delegation.test.js +0 -557
  329. package/pi-extension/tests/cognitive-routing-v2/native.test.js +0 -474
  330. package/pi-extension/tests/cognitive-routing-v2/performance.test.js +0 -87
  331. package/pi-extension/tests/cognitive-routing-v2/persistence.test.js +0 -300
  332. package/pi-extension/tests/cognitive-routing-v2/projection.test.js +0 -241
  333. package/pi-extension/tests/cognitive-routing-v2/recovery.test.js +0 -1034
  334. package/pi-extension/tests/cognitive-routing-v2/render.test.js +0 -244
  335. package/pi-extension/tests/cognitive-routing-v2/runtime.test.js +0 -423
  336. package/pi-extension/tests/cognitive-routing-v2/stabilization.test.js +0 -521
  337. package/pi-extension/tests/cognitive-routing-v2/state.test.js +0 -586
  338. package/pi-extension/tests/context-virtualization/extension.test.js +0 -775
  339. package/pi-extension/tests/context-virtualization/projector.test.js +0 -110
  340. package/pi-extension/tests/context-virtualization/runtime.test.js +0 -230
  341. package/pi-extension/tests/conversation-history/runtime.test.js +0 -98
  342. package/pi-extension/tests/conversation-history/search.test.js +0 -97
  343. package/pi-extension/tests/fixtures/pi-host.js +0 -4
  344. package/pi-extension/tests/fixtures/routing-native.js +0 -191
  345. package/pi-extension/tests/integration/mode-free-core.test.js +0 -220
  346. package/pi-extension/tests/integration/pi-extension.test.js +0 -1447
  347. package/pi-extension/tests/integration/prompt-architecture.test.js +0 -447
  348. package/pi-extension/tests/integration/unaffected-regressions.test.js +0 -478
  349. package/pi-extension/tests/provider-support/astra-boundaries.test.js +0 -75
  350. package/pi-extension/tests/provider-support/astra.test.js +0 -306
  351. package/pi-extension/tests/provider-support/cli.test.js +0 -92
  352. package/pi-extension/tests/provider-support/native.test.js +0 -183
  353. package/pi-extension/tests/settings/settings-tui.test.js +0 -243
  354. package/pi-extension/tsconfig.json +0 -16
  355. package/plugin.json +0 -33
  356. package/runtime/prompts/context-virtualization.md +0 -3
  357. package/runtime/prompts/conversation-history.md +0 -3
  358. package/skills/action-selection/SKILL.md +0 -100
  359. package/skills/action-selection/references/trajectory-stalls.md +0 -71
  360. package/skills/bypass/SKILL.md +0 -153
  361. package/skills/commit-work/SKILL.md +0 -145
  362. package/skills/commit-work/references/git-state-edges.md +0 -94
  363. package/skills/commit-work/references/simple-push.md +0 -92
  364. package/skills/commit-work/references/staging-decisions.md +0 -106
  365. package/skills/decision-gate/SKILL.md +0 -106
  366. package/skills/design-for-depth/SKILL.md +0 -117
  367. package/skills/design-for-depth/references/design-pressure-signals.md +0 -182
  368. package/skills/design-for-depth/references/implementation-decisions.md +0 -76
  369. package/skills/design-for-depth/references/interface-design-loop.md +0 -136
  370. package/skills/design-for-depth/references/module-and-dependency-design.md +0 -147
  371. package/skills/design-for-depth/references/software-design-philosophy.md +0 -202
  372. package/skills/design-for-depth/references/state-and-failure-boundaries.md +0 -136
  373. package/skills/diagnose-failure/SKILL.md +0 -125
  374. package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +0 -48
  375. package/skills/diagnose-failure/references/flaky-and-performance-diagnosis.md +0 -51
  376. package/skills/discuss/SKILL.md +0 -116
  377. package/skills/evaluate-skill/SKILL.md +0 -219
  378. package/skills/evaluate-skill/references/evaluation-definition-schema.md +0 -385
  379. package/skills/evaluate-skill/references/evaluation-design.md +0 -112
  380. package/skills/evaluate-skill/references/execution-and-evidence.md +0 -90
  381. package/skills/evaluate-skill/references/review-and-revision.md +0 -92
  382. package/skills/evaluate-skill/scripts/lib/definitions.mjs +0 -407
  383. package/skills/evaluate-skill/scripts/lib/grade-comparison.mjs +0 -60
  384. package/skills/evaluate-skill/scripts/lib/grade.mjs +0 -64
  385. package/skills/evaluate-skill/scripts/lib/runner.mjs +0 -368
  386. package/skills/evaluate-skill/scripts/pi-guard.mjs +0 -164
  387. package/skills/evaluate-skill/scripts/skill-eval.mjs +0 -102
  388. package/skills/execute-work/references/execute-work-edges.md +0 -68
  389. package/skills/finish-branch/SKILL.md +0 -117
  390. package/skills/finish-branch/references/integration-options.md +0 -80
  391. package/skills/handoff/SKILL.md +0 -82
  392. package/skills/handoff/references/handoff-templates.md +0 -150
  393. package/skills/launch-work/SKILL.md +0 -116
  394. package/skills/launch-work/references/launch-readiness.md +0 -85
  395. package/skills/migration-work/SKILL.md +0 -115
  396. package/skills/migration-work/references/migration-lifecycle.md +0 -82
  397. package/skills/release-work/SKILL.md +0 -118
  398. package/skills/release-work/references/release-evidence.md +0 -78
  399. package/skills/review-artifact/SKILL.md +0 -142
  400. package/skills/review-artifact/references/adjudicate-artifact-review.md +0 -101
  401. package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +0 -159
  402. package/skills/review-work/references/adjudicate-work-review.md +0 -97
  403. package/skills/review-work/references/independent-work-reviewer-contract.md +0 -139
  404. package/skills/review-work/references/security-risk-lens.md +0 -69
  405. package/skills/setup-freeflow/references/activation-contract.md +0 -109
  406. package/skills/setup-freeflow/references/host-setup.md +0 -67
  407. package/skills/simplify-code/SKILL.md +0 -85
  408. package/skills/simplify-code/references/simplification-patterns.md +0 -70
  409. package/skills/verify-work/references/browser-runtime-evidence.md +0 -55
  410. package/skills/verify-work/references/integration-evidence.md +0 -47
  411. package/skills/verify-work/references/performance-evidence.md +0 -57
  412. package/skills/workflow/SKILL.md +0 -127
  413. package/skills/workflow/references/domain-skill-composition.md +0 -43
  414. package/skills/write-plan/SKILL.md +0 -92
  415. package/skills/write-plan/references/plan-shapes.md +0 -156
  416. package/skills/write-skill/references/activation-boundaries.md +0 -104
  417. package/skills/write-skill/references/agent-first-instructions.md +0 -121
  418. package/skills/write-skill/references/progressive-disclosure.md +0 -127
  419. package/skills/write-skill/references/skill-dependency-graphs.md +0 -190
  420. package/skills/write-spec/SKILL.md +0 -92
  421. package/skills/write-spec/references/artifact-standards.md +0 -86
  422. package/skills/write-spec/references/decision-records.md +0 -78
  423. package/skills/write-spec/references/spec-shapes.md +0 -143
  424. /package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/budget.js +0 -0
  425. /package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/evidence.mjs +0 -0
  426. /package/skills/{evaluate-skill → evaluate-behavior}/scripts/pi-observer.mjs +0 -0
@@ -0,0 +1,159 @@
1
+ import { estimateTokens } from "./carry.js";
2
+ import { currentCycle } from "./harness.js";
3
+ import { withoutGuidanceNotices } from "../tool-execution/guidance-notices.js";
4
+ import { isFreeflowInstruction } from "../tool-execution/skill-reads.js";
5
+ /**
6
+ * The result index: this cycle's larger tool results, each with an id the agent can carry by. Ids number tool results
7
+ * in branch order (r1, r2, ...), so they stay stable while the branch grows, and a result from an earlier cycle still
8
+ * resolves because its entry stays stored after compaction.
9
+ */
10
+ const SIZE_FLOOR = 500;
11
+ const MAX_ROWS = 40;
12
+ /**
13
+ * The most tokens the rendered index can take: 40 rows of at most about 140 characters (an 80-character label plus
14
+ * id, tool, size and carried note) and a heading. Below the warning by more than this, the index cannot reach it.
15
+ */
16
+ export const INDEX_TOKEN_BOUND = 2_000;
17
+ /** Freeflow's own control calls: no evidence to carry, as routing's evidence selection also excludes them. */
18
+ const CONTROL_TOOLS = new Set([
19
+ "delegate_work",
20
+ "return_work",
21
+ "select_evidence",
22
+ "routing_unit",
23
+ "compact_context",
24
+ // The same tools' names before Task 003's rename, still in sessions saved earlier.
25
+ "freeflow_delegate",
26
+ "freeflow_return",
27
+ "freeflow_project",
28
+ "freeflow_unit",
29
+ "freeflow_compact",
30
+ ]);
31
+ /** A result's text without the guidance notices that joined it. */
32
+ const resultText = (message) =>
33
+ withoutGuidanceNotices(
34
+ (message?.content ?? [])
35
+ .map((part) => (part?.type === "text" ? part.text : part?.type === "image" ? "[image]" : ""))
36
+ .join(""),
37
+ );
38
+ function label(name, input) {
39
+ const firstLine = (text) =>
40
+ text
41
+ .split("\n")
42
+ .map((line) => line.trim())
43
+ .find(Boolean) ?? "";
44
+ const value =
45
+ typeof input?.command === "string"
46
+ ? input.command
47
+ : typeof input?.path === "string"
48
+ ? input.path
49
+ : typeof input?.url === "string"
50
+ ? input.url
51
+ : typeof input?.code === "string"
52
+ ? `script: ${firstLine(input.code)}`
53
+ : Array.isArray(input?.queries)
54
+ ? input.queries.join("; ")
55
+ : typeof input?.query === "string"
56
+ ? input.query
57
+ : name;
58
+ const line = firstLine(String(value));
59
+ return line.length > 80 ? `${line.slice(0, 77)}...` : line;
60
+ }
61
+ /** Every tool result on the branch with its id, oldest first. */
62
+ function allResults(branch) {
63
+ const calls = new Map();
64
+ const results = [];
65
+ for (const entry of branch) {
66
+ const message = entry?.type === "message" ? entry.message : undefined;
67
+ if (message?.role === "assistant")
68
+ for (const block of message.content ?? [])
69
+ if (block?.type === "toolCall") calls.set(block.id, { name: block.name, input: block.arguments });
70
+ if (message?.role !== "toolResult") continue;
71
+ const call = calls.get(message.toolCallId);
72
+ const text = resultText(message);
73
+ const tool = call?.name ?? message.toolName ?? "tool";
74
+ results.push({
75
+ id: `r${results.length + 1}`,
76
+ tool,
77
+ label: label(tool, call?.input),
78
+ tokens: estimateTokens(text),
79
+ text,
80
+ ...firstLineOf(tool, call?.input, message),
81
+ entry,
82
+ input: call?.input,
83
+ });
84
+ }
85
+ return results;
86
+ }
87
+ /** A text read of a file starts at its offset (Pi's read is 1-based); an image or failed read has no lines. */
88
+ function firstLineOf(tool, input, message) {
89
+ if (tool !== "read" || typeof input?.path !== "string" || message?.isError) return {};
90
+ if ((message?.content ?? []).some((part) => part?.type === "image")) return {};
91
+ return { firstLine: Number.isInteger(input?.offset) && input.offset > 0 ? input.offset : 1 };
92
+ }
93
+ /** The first line of the read result in a session entry, for a result carried by routing ref. */
94
+ export function resultFirstLine(branch, entryId) {
95
+ return allResults(branch).find((result) => result.entry?.id === entryId)?.firstLine;
96
+ }
97
+ export function resolveResult(branch, id) {
98
+ const found = allResults(branch).find((result) => result.id === id);
99
+ if (!found) return undefined;
100
+ const { entry: _entry, input: _input, ...result } = found;
101
+ return result;
102
+ }
103
+ /**
104
+ * The tool results of the work in progress, newest first: the current assignment's under Cognitive Routing (by
105
+ * routing ref), otherwise this cycle's (by r-id). Freeflow's control calls and reads of its own instructions are left
106
+ * out: they are how the agent works, not what it worked on.
107
+ */
108
+ export function scopeResults(branch, assignment) {
109
+ const cycle = new Set(currentCycle(branch));
110
+ return allResults(branch)
111
+ .filter((result) => (assignment ? assignment.entryIds.has(result.entry.id) : cycle.has(result.entry)))
112
+ .filter((result) => !CONTROL_TOOLS.has(result.tool) && !isFreeflowInstruction(result.tool, result.input))
113
+ .reverse()
114
+ .map(({ entry, input, ...result }) => ({
115
+ ...result,
116
+ id: assignment ? `ctx:${entry.id}` : result.id,
117
+ entryId: entry.id,
118
+ ...(typeof input?.path === "string" ? { path: input.path } : {}),
119
+ }));
120
+ }
121
+ /** This cycle's results above the size floor, newest first, then results the last Freeflow compaction carried. */
122
+ export function resultIndex(branch) {
123
+ const cycle = new Set(currentCycle(branch));
124
+ const results = allResults(branch);
125
+ const rows = results
126
+ .filter(
127
+ (result) =>
128
+ cycle.has(result.entry) &&
129
+ result.tokens >= SIZE_FLOOR &&
130
+ !CONTROL_TOOLS.has(result.tool) &&
131
+ !isFreeflowInstruction(result.tool, result.input),
132
+ )
133
+ .reverse()
134
+ .map(({ id, tool, label, tokens }) => ({ id, tool, label, tokens }));
135
+ const latest = [...branch].reverse().find((entry) => entry?.type === "compaction" && entry.details?.freeflow);
136
+ for (const item of latest?.details?.freeflow?.carried ?? []) {
137
+ if (item?.kind !== "result" || rows.some((row) => row.id === item.ref)) continue;
138
+ const result = results.find((each) => each.id === item.ref);
139
+ if (result)
140
+ rows.push({
141
+ id: result.id,
142
+ tool: result.tool,
143
+ label: result.label,
144
+ tokens: result.tokens,
145
+ firstCycle: item.firstCycle,
146
+ });
147
+ }
148
+ return rows.slice(0, MAX_ROWS);
149
+ }
150
+ export function renderIndex(rows) {
151
+ if (!rows.length) return "No tool results large enough to list; carry files by path.";
152
+ return [
153
+ "Results you can carry by id:",
154
+ ...rows.map(
155
+ (row) =>
156
+ `- ${row.id} ${row.tool} ${row.label} ~${row.tokens} tokens${row.firstCycle ? ` (carried since cycle ${row.firstCycle})` : ""}`,
157
+ ),
158
+ ].join("\n");
159
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * When compaction is due. Pi compacts on its own once context passes the window minus its reserve, and stays as the
3
+ * fallback for a full context. Freeflow says "compact now" 25k tokens before that, leaving room to prepare after a
4
+ * safe point, and warns earlier still: at 70% of the window, and at least 20k tokens before "compact now", so the
5
+ * agent has room to reach a safe point first.
6
+ */
7
+ export const DEFAULT_RESERVE_TOKENS = 16_384;
8
+ const WARNING_SHARE = 0.7;
9
+ const WARNING_LEAD = 20_000;
10
+ const COMPACT_NOW_HEADROOM = 25_000;
11
+ /** Pi's effective reserve for a model: its per-model override, else the ordinary setting, else Pi's default. */
12
+ export function reserveTokens(settings, model) {
13
+ const compaction = settings?.compaction ?? {};
14
+ const override = model ? compaction.modelOverrides?.[`${model.provider}/${model.id}`] : undefined;
15
+ const value = override?.reserveTokens ?? compaction.reserveTokens;
16
+ return Number.isSafeInteger(value) && value >= 0 ? value : DEFAULT_RESERVE_TOKENS;
17
+ }
18
+ export function thresholds(window, reserve) {
19
+ const trigger = Math.max(0, window - reserve);
20
+ const compactNow = Math.max(0, trigger - COMPACT_NOW_HEADROOM);
21
+ return {
22
+ window,
23
+ trigger,
24
+ warning: Math.max(0, Math.min(Math.floor(window * WARNING_SHARE), compactNow - WARNING_LEAD)),
25
+ compactNow,
26
+ };
27
+ }
28
+ /** The strictest thresholds across models that may receive the full history (the active model and routing workers). */
29
+ export function strictest(models, settings) {
30
+ const all = models
31
+ .filter((model) => typeof model?.contextWindow === "number" && model.contextWindow > 0)
32
+ .map((model) => thresholds(model.contextWindow, reserveTokens(settings, model)));
33
+ if (!all.length) return undefined;
34
+ return all.reduce((a, b) => (b.warning < a.warning ? b : a));
35
+ }
@@ -0,0 +1,57 @@
1
+ export const COMPACT_CONTEXT = "compact_context";
2
+ const DESCRIPTION =
3
+ "Compact the conversation into a new cycle. Use only when Freeflow says compaction is due or the user asks, and read the compaction skill first. Pass your summary and what to carry; compaction happens at the end of this turn, and the run continues from the summary, the carried context and a recovery message.";
4
+ /** Registered once, declared only while Freeflow compaction is effective (see applyCompactionTools). */
5
+ export function registerCompactionTool(pi, controller) {
6
+ pi.registerTool({
7
+ name: COMPACT_CONTEXT,
8
+ label: "Compact",
9
+ description: DESCRIPTION,
10
+ parameters: {
11
+ type: "object",
12
+ additionalProperties: false,
13
+ properties: {
14
+ summary: {
15
+ type: "string",
16
+ description:
17
+ "The next cycle's working state, for a reader with none of this conversation. The compaction skill says what it must keep.",
18
+ },
19
+ carry: {
20
+ type: "array",
21
+ description:
22
+ "What to carry into the next cycle, within the budget the notice gives: files by path (read fresh at compaction, optional line ranges) and tool results by id from the notice's index.",
23
+ items: {
24
+ type: "object",
25
+ additionalProperties: false,
26
+ properties: {
27
+ file: { type: "string" },
28
+ lines: { type: "array", items: { type: "integer" }, description: "[first, last], 1-based" },
29
+ result: {
30
+ type: "string",
31
+ description:
32
+ "A tool result: its routing ref (such as ctx:1a2b3c4d) when Cognitive Routing is on, otherwise its id from the notice's list (such as r12)",
33
+ },
34
+ },
35
+ },
36
+ },
37
+ },
38
+ required: ["summary"],
39
+ },
40
+ // Callable from codemode scripts as well: agents that look for tools there first concluded, when it was missing,
41
+ // that they could not compact. The compaction still happens at the end of the turn, after the script returns.
42
+ exposure: "direct",
43
+ defaultActive: false,
44
+ executionMode: "sequential",
45
+ async execute(_id, params, _signal, _update, ctx) {
46
+ return { content: [{ type: "text", text: await controller.request(params, ctx) }] };
47
+ },
48
+ });
49
+ }
50
+ /** Declare or withdraw compact_context when compaction's effective state changes, keeping other tools in place. */
51
+ export function applyCompactionTools(pi, effective) {
52
+ if (typeof pi.getActiveTools !== "function" || typeof pi.setActiveTools !== "function") return;
53
+ const current = pi.getActiveTools();
54
+ const present = current.includes(COMPACT_CONTEXT);
55
+ if (effective && !present) pi.setActiveTools([...current, COMPACT_CONTEXT]);
56
+ if (!effective && present) pi.setActiveTools(current.filter((name) => name !== COMPACT_CONTEXT));
57
+ }
@@ -0,0 +1,13 @@
1
+ // Keyed by the reader and its getBranch function, so a reader whose source is swapped is walked again.
2
+ const cache = new WeakMap();
3
+ export function cachedBranch(reader) {
4
+ if (!reader?.getBranch) return [];
5
+ // Without a leaf id the branch cannot be keyed; fall back to Pi's walk.
6
+ if (!reader.getLeafId) return reader.getBranch();
7
+ const leaf = reader.getLeafId();
8
+ const hit = cache.get(reader);
9
+ if (hit && hit.leaf === leaf && hit.source === reader.getBranch) return hit.branch;
10
+ const branch = Object.freeze([...reader.getBranch()]);
11
+ cache.set(reader, { leaf, source: reader.getBranch, branch });
12
+ return branch;
13
+ }
@@ -0,0 +1,12 @@
1
+ const isObject = (value) => !!value && typeof value === "object" && !Array.isArray(value);
2
+ /** Deterministic JSON: object keys sorted, undefined properties omitted, so equal values serialize equally. */
3
+ export function canonical(value) {
4
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
5
+ if (isObject(value))
6
+ return `{${Object.keys(value)
7
+ .filter((k) => value[k] !== undefined)
8
+ .sort()
9
+ .map((k) => `${JSON.stringify(k)}:${canonical(value[k])}`)
10
+ .join(",")}}`;
11
+ return JSON.stringify(value) ?? "null";
12
+ }
@@ -0,0 +1,62 @@
1
+ import { fileURLToPath } from "node:url";
2
+ /**
3
+ * Freeflow's fixed command and skill surface: the commands it registers, the skills it lists to the model, and where
4
+ * their files live.
5
+ */
6
+ export const WORKFLOW_COMMANDS = [
7
+ { command: "discuss-work", skill: "discuss-work" },
8
+ { command: "track-work", skill: "track-work" },
9
+ { command: "write-docs", skill: "write-docs" },
10
+ { command: "execute-work", skill: "execute-work" },
11
+ { command: "verify-work", skill: "verify-work" },
12
+ { command: "review-work", skill: "review-work" },
13
+ { command: "deliver-work", skill: "deliver-work" },
14
+ ];
15
+ export const CONTRIBUTOR_COMMANDS = ["setup-freeflow", "write-skill", "evaluate-behavior"];
16
+ /**
17
+ * Every portable skill Freeflow ships, by directory name. The canonical list: validation scripts and tests compare the
18
+ * skills directory, the package and the coverage matrix against it instead of a fixed count.
19
+ */
20
+ export const FREEFLOW_MODEL_SKILL_NAMES = [
21
+ "deliver-work",
22
+ "discuss-work",
23
+ "evaluate-behavior",
24
+ "execute-work",
25
+ "review-work",
26
+ "setup-freeflow",
27
+ "track-work",
28
+ "verify-work",
29
+ "write-docs",
30
+ "write-skill",
31
+ ];
32
+ export const STABLE_FREEFLOW_SURFACE = Object.freeze({
33
+ enabled: true,
34
+ cognitiveRouting: { effective: true },
35
+ toolExecution: { effective: true },
36
+ compaction: { effective: true },
37
+ taskMemory: { effective: true },
38
+ messaging: { effective: true },
39
+ });
40
+ export function freeflowSkillPath(skillName) {
41
+ return fileURLToPath(new URL(`../../../skills/${skillName}/SKILL.md`, import.meta.url));
42
+ }
43
+ export function freeflowCapabilitySkillPath(skillName) {
44
+ return fileURLToPath(new URL(`../../../capabilities/${skillName}/SKILL.md`, import.meta.url));
45
+ }
46
+ export function freeflowModelSkillPaths(capabilityState = undefined) {
47
+ // A skill the user turned off is not loaded (config-validation.ts SWITCHABLE_SKILLS).
48
+ const off = capabilityState?.skills?.off ?? [];
49
+ const paths = FREEFLOW_MODEL_SKILL_NAMES.filter((skillName) => !off.includes(skillName)).map((skillName) =>
50
+ freeflowSkillPath(skillName),
51
+ );
52
+ if (capabilityState?.cognitiveRouting?.effective === true)
53
+ paths.push(freeflowCapabilitySkillPath("cognitive-routing"));
54
+ if (capabilityState?.compaction?.effective === true) paths.push(freeflowCapabilitySkillPath("compaction"));
55
+ if (capabilityState?.taskMemory?.effective === true) paths.push(freeflowCapabilitySkillPath("task-memory"));
56
+ if (capabilityState?.messaging?.effective === true) paths.push(freeflowCapabilitySkillPath("messaging"));
57
+ return paths;
58
+ }
59
+ export function skillPrompt(skill, args) {
60
+ const trimmed = args?.trim();
61
+ return trimmed ? `/skill:${skill}\n\n${trimmed}` : `/skill:${skill}`;
62
+ }
@@ -0,0 +1,233 @@
1
+ import { validateCompactionConfig } from "../compaction/config.js";
2
+ import { validateTaskMemoryConfig } from "../task-memory/config.js";
3
+ import { validateMessagingConfig } from "../messaging/config.js";
4
+ import { validateToolExecutionConfig } from "../tool-execution/config.js";
5
+ import { FREEFLOW_MODEL_SKILL_NAMES } from "./catalog.js";
6
+ /**
7
+ * Whether a Freeflow config file is valid: one answer for Pi and for the session-start hooks of the other hosts, which
8
+ * import the built file. Also how the settings every host reads, `prompts`, `review` and `skills`, layer. Keep this module and its
9
+ * imports free of Pi packages; the hooks run in plain Node.
10
+ */
11
+ function isRecord(value) {
12
+ return typeof value === "object" && value !== null && !Array.isArray(value);
13
+ }
14
+ /** The runtime prompts Freeflow delivers on every host, each on unless a config turns it off. */
15
+ export const RUNTIME_PROMPTS = ["core", "interactionContract", "workingMethod"];
16
+ /** The keys `prompts` accepts: a master switch for all three, and one switch per prompt. */
17
+ export const PROMPTS_KEYS = ["enabled", ...RUNTIME_PROMPTS];
18
+ /** A section's master switch (`prompts.enabled`, `skills.enabled`) for two valid layers; on unless a config turns it off. */
19
+ export function sectionEnabled(repository, local, section) {
20
+ const layer = (config) => (isRecord(config?.[section]) ? config[section] : {});
21
+ return (layer(local).enabled ?? layer(repository).enabled ?? true) === true;
22
+ }
23
+ function validatePromptsConfig(value) {
24
+ if (!isRecord(value)) return "prompts must be an object";
25
+ const unknown = Object.keys(value).find((key) => !PROMPTS_KEYS.includes(key));
26
+ if (unknown) return `prompts has unsupported key: ${unknown}`;
27
+ for (const key of PROMPTS_KEYS)
28
+ if (value[key] !== undefined && typeof value[key] !== "boolean") return `prompts.${key} must be a boolean`;
29
+ return null;
30
+ }
31
+ /**
32
+ * The prompts Freeflow delivers for two valid config layers: the personal layer overrides the repository's, and the
33
+ * master switch off turns all three off.
34
+ */
35
+ export function selectedRuntimePrompts(repository, local) {
36
+ const layer = (config) => (isRecord(config?.prompts) ? config.prompts : {});
37
+ const [shared, personal] = [layer(repository), layer(local)];
38
+ const master = sectionEnabled(repository, local, "prompts");
39
+ const selection = {};
40
+ for (const key of RUNTIME_PROMPTS) selection[key] = master && (personal[key] ?? shared[key] ?? true) === true;
41
+ return selection;
42
+ }
43
+ /**
44
+ * The skills a user can turn off. Setup Freeflow always stays, so a user can repair a configuration; the capability
45
+ * skills follow their capability's switch. On Pi an off skill is not loaded; other hosts load plugin skills themselves,
46
+ * so there the Runtime State only tells the agent not to use it.
47
+ */
48
+ export const SWITCHABLE_SKILLS = FREEFLOW_MODEL_SKILL_NAMES.filter((name) => name !== "setup-freeflow").sort();
49
+ /** The keys `skills` accepts: a master switch for every switchable skill, and one switch per skill. */
50
+ export const SKILLS_KEYS = ["enabled", ...SWITCHABLE_SKILLS];
51
+ function validateSkillsConfig(value) {
52
+ if (!isRecord(value)) return "skills must be an object";
53
+ const unknown = Object.keys(value).find((key) => !SKILLS_KEYS.includes(key));
54
+ if (unknown) return `skills has unsupported key: ${unknown}; use ${SKILLS_KEYS.join(", ")}`;
55
+ for (const [key, on] of Object.entries(value)) if (typeof on !== "boolean") return `skills.${key} must be a boolean`;
56
+ return null;
57
+ }
58
+ /**
59
+ * The skills turned off for two valid config layers: the personal layer overrides the repository's, skill by skill,
60
+ * and the master switch off turns every switchable skill off.
61
+ */
62
+ export function skillsOff(repository, local) {
63
+ const layer = (config) => (isRecord(config?.skills) ? config.skills : {});
64
+ const [shared, personal] = [layer(repository), layer(local)];
65
+ if (!sectionEnabled(repository, local, "skills")) return [...SWITCHABLE_SKILLS];
66
+ return SWITCHABLE_SKILLS.filter((name) => (personal[name] ?? shared[name] ?? true) === false);
67
+ }
68
+ /** The Runtime State line for skills the user turned off; none while every skill is on. */
69
+ export function skillsStateLine(off) {
70
+ return off?.length ? `Skills off: ${off.map((name) => `\`${name}\``).join(", ")}; do not open or follow them.` : null;
71
+ }
72
+ /**
73
+ * How Review Work reviews finished work. Without the key it runs `auto`, its own risk gate; `off` and `always` are the
74
+ * user's choice for every task, and `model` names the model a reviewer runs on. `auto` is accepted so a personal file
75
+ * can return a shared `off` or `always` to the default.
76
+ */
77
+ export const REVIEW_MODES = ["auto", "off", "always"];
78
+ export const REVIEW_KEYS = ["mode", "model"];
79
+ function validateReviewConfig(value) {
80
+ if (!isRecord(value)) return "review must be an object";
81
+ const unknown = Object.keys(value).find((key) => !REVIEW_KEYS.includes(key));
82
+ if (unknown) return `review has unsupported key: ${unknown}`;
83
+ if (value.mode !== undefined && !REVIEW_MODES.includes(value.mode))
84
+ return `review.mode must be one of ${REVIEW_MODES.join(", ")}`;
85
+ // The model is shown to the agent in the Runtime State, so it must fit on one line in a code span.
86
+ if (
87
+ value.model !== undefined &&
88
+ (typeof value.model !== "string" || !value.model.trim() || /[\p{Cc}`]/u.test(value.model))
89
+ )
90
+ return "review.model must be a non-empty model name on one line";
91
+ return null;
92
+ }
93
+ /** Review settings for two valid config layers: the personal layer overrides the repository's, field by field. */
94
+ export function resolveReviewSettings(repository, local) {
95
+ const layer = (config) => (isRecord(config?.review) ? config.review : {});
96
+ const [shared, personal] = [layer(repository), layer(local)];
97
+ const mode = personal.mode ?? shared.mode ?? "auto";
98
+ const model = personal.model ?? shared.model;
99
+ return model === undefined ? { mode } : { mode, model };
100
+ }
101
+ /** The Runtime State line for the user's review choice; none for the default, `auto` with no model. */
102
+ export function reviewStateLine(review) {
103
+ if (!review || (review.mode === "auto" && review.model === undefined)) return null;
104
+ return `Review: \`${review.mode}\`${review.model === undefined ? "" : `, reviewer model \`${review.model}\``}`;
105
+ }
106
+ function removedContextConfigError(value, filePath) {
107
+ const removedKeys = ["contextVirtualization", "conversationHistory"].filter((key) =>
108
+ Object.prototype.hasOwnProperty.call(value, key),
109
+ );
110
+ return removedKeys.length > 0
111
+ ? `Removed Freeflow context setting(s) in ${filePath}: ${removedKeys.join(", ")}. Delete those keys before using Freeflow.`
112
+ : null;
113
+ }
114
+ function validateCoreConfigFields(value) {
115
+ if (value.enabled !== undefined && typeof value.enabled !== "boolean") {
116
+ return "enabled must be a boolean";
117
+ }
118
+ return null;
119
+ }
120
+ /** The top-level keys Freeflow acts on; the settings test checks that every key under them has a settings row. */
121
+ export const CONFIG_SECTIONS = [
122
+ "enabled",
123
+ "cognitiveRouting",
124
+ "toolExecution",
125
+ "compaction",
126
+ "taskMemory",
127
+ "messaging",
128
+ "prompts",
129
+ "review",
130
+ "skills",
131
+ ];
132
+ // outputRouter, observedRouting, and scriptTransform belong to retired features; they are accepted and ignored so
133
+ // existing configs keep loading.
134
+ const RETIRED_SECTIONS = ["outputRouter", "observedRouting", "scriptTransform"];
135
+ export function validateRepositoryConfig(value) {
136
+ if (!isRecord(value)) {
137
+ return "config must be a JSON object";
138
+ }
139
+ const removedContextError = removedContextConfigError(value, ".freeflow/config.json");
140
+ if (removedContextError) return removedContextError;
141
+ const allowedKeys = new Set([...CONFIG_SECTIONS, ...RETIRED_SECTIONS]);
142
+ for (const key of Object.keys(value)) {
143
+ if (!allowedKeys.has(key)) {
144
+ return `unsupported top-level config key: ${key}`;
145
+ }
146
+ }
147
+ const coreError = validateCoreConfigFields(value);
148
+ if (coreError) return coreError;
149
+ for (const key of ["outputRouter", "observedRouting", "scriptTransform"]) {
150
+ if (value[key] !== undefined && !isRecord(value[key])) {
151
+ return `${key} must be an object`;
152
+ }
153
+ }
154
+ if (value.toolExecution !== undefined) {
155
+ const error = validateToolExecutionConfig(value.toolExecution);
156
+ if (error) return error;
157
+ }
158
+ if (value.prompts !== undefined) {
159
+ const error = validatePromptsConfig(value.prompts);
160
+ if (error) return error;
161
+ }
162
+ if (value.compaction !== undefined) {
163
+ const error = validateCompactionConfig(value.compaction);
164
+ if (error) return error;
165
+ }
166
+ if (value.taskMemory !== undefined) {
167
+ const error = validateTaskMemoryConfig(value.taskMemory);
168
+ if (error) return error;
169
+ }
170
+ if (value.messaging !== undefined) {
171
+ const error = validateMessagingConfig(value.messaging);
172
+ if (error) return error;
173
+ }
174
+ if (value.skills !== undefined) {
175
+ const error = validateSkillsConfig(value.skills);
176
+ if (error) return error;
177
+ }
178
+ if (value.review !== undefined) return validateReviewConfig(value.review);
179
+ return null;
180
+ }
181
+ export function validateLocalConfig(value) {
182
+ if (!isRecord(value)) {
183
+ return "local config must be a JSON object";
184
+ }
185
+ const removedContextError = removedContextConfigError(value, ".freeflow/local.json");
186
+ if (removedContextError) return removedContextError;
187
+ // processing belongs to a retired feature; it is accepted and ignored so existing local configs keep loading.
188
+ const allowedKeys = new Set([
189
+ "enabled",
190
+ "processing",
191
+ "cognitiveRouting",
192
+ "toolExecution",
193
+ "compaction",
194
+ "taskMemory",
195
+ "messaging",
196
+ "prompts",
197
+ "review",
198
+ "skills",
199
+ ]);
200
+ for (const key of Object.keys(value)) {
201
+ if (!allowedKeys.has(key)) {
202
+ return `unsupported top-level local config key: ${key}`;
203
+ }
204
+ }
205
+ const coreError = validateCoreConfigFields(value);
206
+ if (coreError) return coreError;
207
+ if (value.toolExecution !== undefined) {
208
+ const error = validateToolExecutionConfig(value.toolExecution);
209
+ if (error) return error;
210
+ }
211
+ if (value.prompts !== undefined) {
212
+ const error = validatePromptsConfig(value.prompts);
213
+ if (error) return error;
214
+ }
215
+ if (value.compaction !== undefined) {
216
+ const error = validateCompactionConfig(value.compaction);
217
+ if (error) return error;
218
+ }
219
+ if (value.taskMemory !== undefined) {
220
+ const error = validateTaskMemoryConfig(value.taskMemory);
221
+ if (error) return error;
222
+ }
223
+ if (value.messaging !== undefined) {
224
+ const error = validateMessagingConfig(value.messaging);
225
+ if (error) return error;
226
+ }
227
+ if (value.skills !== undefined) {
228
+ const error = validateSkillsConfig(value.skills);
229
+ if (error) return error;
230
+ }
231
+ if (value.review !== undefined) return validateReviewConfig(value.review);
232
+ return null;
233
+ }