@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
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { existsSync } from "node:fs";
3
4
  import { rm } from "node:fs/promises";
4
5
  import { cwd } from "node:process";
5
- import { dirname } from "node:path";
6
- import { canonicalLines, joinLines, slugify, TASK_STATES } from "./lib/format.mjs";
6
+ import { dirname, isAbsolute, resolve, sep } from "node:path";
7
+ import { WORK_AGREEMENT_HEADING, canonicalLines, joinLines, slugify } from "./lib/format.mjs";
7
8
  import { parseDocument, validateDocument } from "./lib/document.mjs";
8
9
  import { runTransition } from "./lib/transitions.mjs";
9
10
  import {
@@ -12,17 +13,30 @@ import {
12
13
  readInput,
13
14
  readRecord,
14
15
  resolveRecordPath,
16
+ storeOf,
15
17
  writeInitialAtomically,
16
18
  } from "./lib/store.mjs";
17
- import { renderFull, renderResume } from "./lib/views.mjs";
19
+ import { renderEntries, renderFull, renderResume } from "./lib/views.mjs";
20
+ import { checkEvidencePointers, renderRecover } from "./lib/recover.mjs";
21
+ import { PROJECT_LINK, Registry, TASK_ID, removalText, startCommand } from "./lib/registry.mjs";
22
+ import { searchRecords } from "./lib/search.mjs";
23
+
24
+ const ROOT_HELP =
25
+ "--record is resolved against --root, which defaults to the current directory; an absolute --record path finds its own root.";
18
26
 
19
27
  function usage() {
20
28
  return [
21
29
  "Usage:",
22
30
  " working-record.mjs init --root <path> --name <task name> [--input <file|->]",
23
- " working-record.mjs view resume|full --record <record.md>",
31
+ " working-record.mjs view resume|recover|full --record <record.md>",
32
+ " working-record.mjs view entry <ID> [<ID> ...] --record <record.md>",
24
33
  " working-record.mjs validate --record <record.md>",
25
34
  " working-record.mjs <slice|checkpoint|decision|task> <operation> ...",
35
+ " working-record.mjs project <new|link|show|list|remove> ...",
36
+ " working-record.mjs task <create|import|search|env|here|fanout|remove> ...",
37
+ "",
38
+ ROOT_HELP,
39
+ "A registered task's ID (such as my-project/task-003) may be given as --record.",
26
40
  ].join("\n");
27
41
  }
28
42
 
@@ -31,7 +45,7 @@ const COMMAND_HELP = new Map([
31
45
  "slice",
32
46
  [
33
47
  "Usage: working-record.mjs slice <operation> ...",
34
- "Operations: slice propose, slice start, slice start-direct, slice pause, slice resume, slice close, slice reopen.",
48
+ "Operations: slice propose, slice start, slice start-direct, slice pause, slice resume, slice close, slice reopen, slice record.",
35
49
  "Run working-record.mjs <group> <operation> --help for options and input fields.",
36
50
  "Use --input - to read Markdown fragments from stdin.",
37
51
  ].join("\n"),
@@ -58,19 +72,74 @@ const COMMAND_HELP = new Map([
58
72
  "task",
59
73
  [
60
74
  "Usage: working-record.mjs task <operation> ...",
61
- "Operations: task set-state.",
75
+ "Operations: task set-state; and for projects: task create, task import, task search, task env, task here, task fanout, task remove.",
62
76
  "Run working-record.mjs <group> <operation> --help for options and input fields.",
63
77
  ].join("\n"),
64
78
  ],
65
79
  [
66
80
  "init",
67
- "Usage: init --root <path> --name <task name> [--state <state>] [--input <file|->]\nInput: Goal and Next useful action required; the seven Current Context headings are accepted. Use --input - to read Markdown fragments from stdin.",
81
+ "Usage: init --root <path> --name <task name> [--input <file|->]\nInput: Goal and Next useful action required; the seven Current Context headings, Work agreement (written only when given) and Recovery sources are accepted, and every line must sit under one of them. The record starts active. Use --input - to read Markdown fragments from stdin.",
82
+ ],
83
+ [
84
+ "view",
85
+ "Usage: view resume|recover|full --record <record.md>\n view entry <ID> [<ID> ...] --record <record.md>\nresume: the header, Current Context, active Decisions, Current Work, Future Work, a one-line index of closed History, and Notes. recover: the resume view, then each defining artifact and Recovery source with its trigger, whether it resolves and its size, then live Git state and where it disagrees with the record: what recovery after context loss reads first. entry: the named S-NNN, C-NNN, or D-NNN entries exactly as stored. full: the file exactly as stored, valid or not.",
86
+ ],
87
+ [
88
+ "validate",
89
+ "Usage: validate --record <record.md> [--strict]\nChecks the record's structure, and whether the pointers in Material updates resolve: files (from the repository root or the task folder) and commits. An unresolved pointer is a warning, since it may name a planned path or a commit not fetched yet; with --strict, one on an Evidence or Result line fails. Pointers outside the repository are listed, not checked.",
90
+ ],
91
+ [
92
+ "project",
93
+ "Usage: working-record.mjs project <operation> ...\nOperations: project new, project link, project show, project list, project remove.\nA project groups tasks; its records live in a store under the Freeflow home (FREEFLOW_HOME, default ~/.freeflow), outside any repository. Create or link a project only when the user asks.",
94
+ ],
95
+ [
96
+ "project new",
97
+ "Usage: project new --name <name> [--cwd <directory>] [--worktrees <directory>]\nCreates the project and links the repository containing --cwd (default: the current directory) to it. --worktrees is where fan-out puts children's worktrees (default: the repository's parent directory).",
98
+ ],
99
+ [
100
+ "project link",
101
+ "Usage: project link --name <name> [--cwd <directory>] [--worktrees <directory>]\nLinks another repository to an existing project; --worktrees changes where fan-out puts worktrees.",
102
+ ],
103
+ [
104
+ "task env",
105
+ "Usage: task env --id <task-id> [--primary <directory>] [--add-dir <directory>] [--remove-dir <directory>]\nPrints where the task's work happens: its primary directory with its current Git branch, and additional directories. The options change it; change it only when the user asks.",
106
+ ],
107
+ [
108
+ "task here",
109
+ "Usage: task here [--cwd <directory>]\nPrints the registered tasks whose primary directory contains the directory, deepest first.",
110
+ ],
111
+ [
112
+ "task fanout",
113
+ "Usage: task fanout --parent <task-id> --title <title> --goal <goal> [--path <directory>] [--base <ref>] [--agent <command>]\nCreates a child of the task, a Git worktree for it on branch <project>/<task-NNN>-<slug> (at <worktrees>/<repo>-<slug> unless --path), copies .freeflow/local.json into it when it has none, and makes the worktree the child's directory. The user then starts a session there: --agent is the command that starts this host's agent (such as claude or codex), and the output ends with a command for the user to paste into a new terminal.",
114
+ ],
115
+ [
116
+ "project show",
117
+ "Usage: project show [--cwd <directory>] [--name <project>]\nPrints a project and its tasks: ID, title, parent, and whether a session owns it. Without --name, the project linked to the repository containing --cwd.",
118
+ ],
119
+ ["project list", "Usage: project list\nPrints every project: name, number of tasks, and linked repositories."],
120
+ [
121
+ "project remove",
122
+ "Usage: project remove --name <project>\nMoves the project's store (every task's record) to the trash under the Freeflow home, removes the project and its tasks from the registry, and removes its .freeflow/project links. Git worktrees and branches stay; the output gives the commands to remove them. Run it only when the user asked to remove that project. Never empty the trash: the user does.",
123
+ ],
124
+ [
125
+ "task remove",
126
+ "Usage: task remove --id <task ID>\nMoves the task's record, and its children's, to the trash under the Freeflow home and removes them from the registry. Task numbers are never reused. Git worktrees and branches stay; the output gives the commands to remove them. Run it only when the user asked to remove that task. Never empty the trash: the user does.",
127
+ ],
128
+ [
129
+ "task create",
130
+ "Usage: task create --title <title> --goal <goal> [--parent <task-id>] [--cwd <directory>]\nCreates a registered record in the project linked to --cwd, or with --parent a child of that task in its project, and prints its ID and path. A child has no children.",
131
+ ],
132
+ [
133
+ "task import",
134
+ "Usage: task import --record <record.md> --project <name>\nMoves an unregistered record's task directory into the project's store, with the next free number, and registers it. Ask the user first.",
135
+ ],
136
+ [
137
+ "task search",
138
+ "Usage: task search --query <text> (--id <task-id> --scope task|tree|project | --project <name>)\nPrints matching lines with the record, entry heading and state. tree is the task's root (its parent, or itself) and the root's children. Read-only.",
68
139
  ],
69
- ["view", "Usage: view resume|full --record <record.md>"],
70
- ["validate", "Usage: validate --record <record.md>"],
71
140
  [
72
141
  "slice propose",
73
- "Usage: slice propose --record <record.md> --title <title> --input <file|->\nInput: Intended result required; Type, Expected evidence, and Dependencies optional. Use --input - to read the fragment from stdin.",
142
+ "Usage: slice propose --record <record.md> --title <title> --input <file|->\nInput: Intended result required; Type, Expected evidence, and Dependencies optional. Commands set State; input never includes it. Use --input - to read the fragment from stdin.",
74
143
  ],
75
144
  [
76
145
  "slice start",
@@ -93,9 +162,13 @@ const COMMAND_HELP = new Map([
93
162
  "slice reopen",
94
163
  "Usage: slice reopen --record <record.md> --id <S-NNN> --next-action <text> --input <file|->\nInput: fresh Authority source, Scope, Expected evidence, Stop condition, and Starting state required. Use --input - to read the fragment from stdin.",
95
164
  ],
165
+ [
166
+ "slice record",
167
+ "Usage: slice record --record <record.md> --title <title> --state <completed|blocked|abandoned> --input <file|->\nRecords a Slice that finished before it could be recorded, directly into History. The Current Slice, Future Work, and Next useful action are unchanged; the ID follows recording order and the command adds Recorded: retroactively on <today>.\nInput: Occurred (YYYY-MM-DD or YYYY-MM-DD to YYYY-MM-DD), Intended result, Authority source, Result, Evidence and limits, and Task effect required; Type and Residual effects optional; Resume when required for blocked; Reason required for abandoned. Use --input - to read the fragment from stdin.",
168
+ ],
96
169
  [
97
170
  "checkpoint propose",
98
- "Usage: checkpoint propose --record <record.md> --title <title> --input <file|->\nInput: Type, Condition, and Applies to required. Use --input - to read the fragment from stdin.",
171
+ "Usage: checkpoint propose --record <record.md> --title <title> --input <file|->\nInput: Type (preserve, publish, review, decision, or continuity), Condition, and Applies to required. Use --input - to read the fragment from stdin.",
99
172
  ],
100
173
  [
101
174
  "checkpoint activate",
@@ -123,7 +196,9 @@ const COMMAND_HELP = new Map([
123
196
  ]);
124
197
 
125
198
  function commandHelp(command, operation) {
126
- return `${COMMAND_HELP.get([command, operation].filter(Boolean).join(" ")) ?? COMMAND_HELP.get(command) ?? usage()}\n`;
199
+ const help = COMMAND_HELP.get([command, operation].filter(Boolean).join(" ")) ?? COMMAND_HELP.get(command);
200
+ if (!help) return `${usage()}\n`;
201
+ return command === "init" ? `${help}\n` : `${help}\n${ROOT_HELP}\n`;
127
202
  }
128
203
 
129
204
  class CliError extends Error {
@@ -144,7 +219,7 @@ function parseOptions(args) {
144
219
  continue;
145
220
  }
146
221
  if (options[token] !== undefined) throw new CliError(`Duplicate option: ${token}`);
147
- if (token === "--help") {
222
+ if (token === "--help" || token === "--strict") {
148
223
  options[token] = true;
149
224
  continue;
150
225
  }
@@ -159,9 +234,9 @@ function parseOptions(args) {
159
234
  function allowedOptions(command, operation) {
160
235
  const common = new Set(["--root", "--record", "--input", "--help"]);
161
236
  const withNextAction = new Set([...common, "--next-action"]);
162
- if (command === "init") return new Set(["--root", "--name", "--state", "--input", "--help"]);
237
+ if (command === "init") return new Set(["--root", "--name", "--input", "--help"]);
163
238
  if (command === "view") return new Set(["--root", "--record", "--view", "--help"]);
164
- if (command === "validate") return new Set(["--root", "--record", "--help"]);
239
+ if (command === "validate") return new Set(["--root", "--record", "--strict", "--help"]);
165
240
  if (command === "slice") {
166
241
  if (operation === "propose") return new Set([...common, "--title"]);
167
242
  if (operation === "start" || operation === "start-direct") return new Set([...withNextAction, "--title"]);
@@ -169,6 +244,7 @@ function allowedOptions(command, operation) {
169
244
  if (operation === "resume") return new Set([...withNextAction, "--resolution"]);
170
245
  if (operation === "close") return new Set([...withNextAction, "--state"]);
171
246
  if (operation === "reopen") return new Set([...withNextAction, "--id", "--title"]);
247
+ if (operation === "record") return new Set([...common, "--title", "--state"]);
172
248
  }
173
249
  if (command === "checkpoint") {
174
250
  if (operation === "propose") return new Set([...common, "--title"]);
@@ -183,6 +259,22 @@ function allowedOptions(command, operation) {
183
259
  }
184
260
  if (command === "task" && operation === "set-state")
185
261
  return new Set(["--root", "--record", "--state", "--next-action", "--help"]);
262
+ if (command === "task" && operation === "create")
263
+ return new Set(["--title", "--goal", "--parent", "--cwd", "--help"]);
264
+ if (command === "task" && operation === "import") return new Set(["--record", "--project", "--help"]);
265
+ if (command === "task" && operation === "search")
266
+ return new Set(["--query", "--id", "--scope", "--project", "--help"]);
267
+ if (command === "task" && operation === "env")
268
+ return new Set(["--id", "--primary", "--add-dir", "--remove-dir", "--help"]);
269
+ if (command === "task" && operation === "here") return new Set(["--cwd", "--help"]);
270
+ if (command === "task" && operation === "fanout")
271
+ return new Set(["--parent", "--title", "--goal", "--path", "--base", "--cwd", "--agent", "--help"]);
272
+ if (command === "project" && (operation === "new" || operation === "link"))
273
+ return new Set(["--name", "--cwd", "--worktrees", "--help"]);
274
+ if (command === "project" && operation === "show") return new Set(["--cwd", "--name", "--help"]);
275
+ if (command === "project" && operation === "list") return new Set(["--help"]);
276
+ if (command === "task" && operation === "remove") return new Set(["--id", "--help"]);
277
+ if (command === "project" && operation === "remove") return new Set(["--name", "--help"]);
186
278
  return null;
187
279
  }
188
280
 
@@ -202,7 +294,16 @@ function requireOption(options, name) {
202
294
  }
203
295
 
204
296
  function rootOption(options) {
205
- return options["--root"] ?? cwd();
297
+ if (options["--root"]) return options["--root"];
298
+ const record = options["--record"];
299
+ if (record && isAbsolute(record)) {
300
+ const marker = `${sep}.freeflow${sep}tasks${sep}`;
301
+ const index = record.lastIndexOf(marker);
302
+ if (index > 0) return record.slice(0, index);
303
+ const store = storeOf(record);
304
+ if (store) return store;
305
+ }
306
+ return cwd();
206
307
  }
207
308
 
208
309
  function initialContent(skeletonLines, input) {
@@ -211,21 +312,27 @@ function initialContent(skeletonLines, input) {
211
312
  const targets = new Map();
212
313
  const names = [
213
314
  "Goal",
315
+ WORK_AGREEMENT_HEADING,
214
316
  "What defines this task",
215
317
  "Settled",
216
318
  "Tentative",
217
319
  "Open",
218
320
  "Current direction",
219
321
  "Boundaries",
322
+ "Recovery sources",
220
323
  "Next useful action",
221
324
  ];
222
325
  const allowed = new Set(names);
326
+ let seenHeading = false;
223
327
  for (let index = 0; index < inputLines.length; index += 1) {
224
328
  const levelThree = /^### (.+?)\s*$/.exec(inputLines[index]);
329
+ if (!levelThree && !seenHeading && inputLines[index].trim() !== "")
330
+ throw new CliError(`Initialization text outside a heading would be lost: ${inputLines[index].trim()}`);
225
331
  if (levelThree) {
226
332
  const name = levelThree[1];
227
333
  if (!allowed.has(name)) throw new CliError(`Unknown initialization heading: ${name}`);
228
334
  if (targets.has(name)) throw new CliError(`Duplicate initialization heading: ${name}`);
335
+ seenHeading = true;
229
336
  const content = [];
230
337
  for (let next = index + 1; next < inputLines.length; next += 1) {
231
338
  if (/^### /.test(inputLines[next]) || /^## /.test(inputLines[next])) break;
@@ -237,6 +344,9 @@ function initialContent(skeletonLines, input) {
237
344
  if (/^## /.test(inputLines[index])) throw new CliError(`Unknown initialization heading: ${inputLines[index]}`);
238
345
  }
239
346
  const output = [...skeletonLines];
347
+ // The skeleton has no Work agreement heading: it is written only when the input gives one.
348
+ if (targets.has(WORK_AGREEMENT_HEADING))
349
+ output.splice(output.indexOf("### What defines this task"), 0, `### ${WORK_AGREEMENT_HEADING}`, "");
240
350
  for (const name of names) {
241
351
  const content = targets.get(name);
242
352
  if (!content) continue;
@@ -255,10 +365,8 @@ function initialContent(skeletonLines, input) {
255
365
  async function initialize(options) {
256
366
  const root = rootOption(options);
257
367
  const name = requireOption(options, "--name");
258
- const state = options["--state"] ?? "active";
259
- if (!TASK_STATES.has(state)) throw new CliError(`Invalid task state: ${state}`);
260
368
  const input = await readInput(options["--input"], cwd());
261
- const text = initialContent(canonicalLines(name, state), input);
369
+ const text = initialContent(canonicalLines(name), input);
262
370
  parseDocument(text);
263
371
  const created = await createRecordPath(root, name, slugify(name));
264
372
  try {
@@ -277,25 +385,158 @@ async function readExisting(options) {
277
385
  return { root, ...loaded };
278
386
  }
279
387
 
388
+ /** Projects, registered tasks and search, through the registry under the Freeflow home. */
389
+ async function runRegistry(command, operation, options) {
390
+ const registry = new Registry();
391
+ const where = options["--cwd"] ?? cwd();
392
+ // Where the user can browse the project's records, when the project link was made.
393
+ const browse = async () => {
394
+ const link = resolve(await registry.repoRoot(where), PROJECT_LINK);
395
+ return existsSync(link) ? ` The user can browse its records at ${link}.` : "";
396
+ };
397
+ if (command === "project" && operation === "new")
398
+ return `Project ${await registry.createProject(requireOption(options, "--name"), where, options["--worktrees"])} created and linked to ${await registry.repoRoot(where)}.${await browse()}\n`;
399
+ if (command === "project" && operation === "link")
400
+ return `${await registry.repoRoot(where)} linked to project ${await registry.linkProject(requireOption(options, "--name"), where, options["--worktrees"])}.${await browse()}\n`;
401
+ // Removal moves records to the trash; nothing here empties it, which is the user's to do (Task 006).
402
+ if (command === "task" && operation === "remove")
403
+ return `${removalText(await registry.removeTask(requireOption(options, "--id")), registry.trash)}\n`;
404
+ if (command === "project" && operation === "remove")
405
+ return `${removalText(await registry.removeProject(requireOption(options, "--name")), registry.trash)}\n`;
406
+ if (command === "project" && operation === "list") {
407
+ const data = await registry.read();
408
+ const projects = Object.entries(data.projects);
409
+ if (!projects.length) return "No projects.\n";
410
+ const count = (slug) => Object.values(data.tasks).filter((task) => task.project === slug).length;
411
+ return `${projects.map(([slug, project]) => `- ${project.name} (${slug}): ${count(slug)} task(s); repositories ${project.repos.join(", ")}`).join("\n")}\n`;
412
+ }
413
+ if (command === "project" && operation === "show") {
414
+ const found = options["--name"] ? await registry.project(options["--name"]) : await registry.projectFor(where);
415
+ if (!found)
416
+ return options["--name"]
417
+ ? `No project named ${options["--name"]}.\n`
418
+ : `No project is linked to ${await registry.repoRoot(where)}.\n`;
419
+ const lines = [`Project ${found.project.name} (${found.slug}), store ${found.project.store}`];
420
+ for (const { id, task } of await registry.projectTasks(found.slug))
421
+ lines.push(
422
+ `- ${id} — ${task.title} (${task.record})${task.parent ? `, child of ${task.parent}` : ""}${task.owner ? `, owned by session ${task.owner.session}` : ""}`,
423
+ );
424
+ return `${lines.join("\n")}\n`;
425
+ }
426
+ if (operation === "create") {
427
+ const title = requireOption(options, "--title");
428
+ const goal = requireOption(options, "--goal");
429
+ const parent = options["--parent"];
430
+ const slug = parent ? (await registry.task(parent))?.project : (await registry.projectFor(where))?.slug;
431
+ if (!slug)
432
+ throw new CliError(parent ? `No task ${parent}.` : `No project is linked to ${await registry.repoRoot(where)}.`);
433
+ const primary = parent ? undefined : await registry.repoRoot(where);
434
+ const created = await registry.createTask(slug, title, goal, parent, primary);
435
+ return `${created.id}\n${created.record}\n`;
436
+ }
437
+ if (operation === "import") {
438
+ const record = resolve(requireOption(options, "--record"));
439
+ const moved = await registry.importRecord(requireOption(options, "--project"), record);
440
+ return `${moved.id}\n${moved.record}\n`;
441
+ }
442
+ if (operation === "env") {
443
+ const id = requireOption(options, "--id");
444
+ if (options["--primary"] || options["--add-dir"] || options["--remove-dir"])
445
+ await registry.setEnvironment(id, {
446
+ primary: options["--primary"],
447
+ add: options["--add-dir"],
448
+ remove: options["--remove-dir"],
449
+ });
450
+ const env = await registry.environment(id);
451
+ if (!env.primary) return `${id} has no recorded directory.\n`;
452
+ const facts =
453
+ env.exists === false
454
+ ? ["missing"]
455
+ : [env.worktree ? "Git worktree" : "", env.branch ? `branch ${env.branch}` : ""];
456
+ const state = facts.filter(Boolean).join(", ");
457
+ return `${[`primary: ${env.primary}${state ? ` (${state})` : ""}`, ...env.directories.map((dir) => `also: ${dir}`)].join("\n")}\n`;
458
+ }
459
+ if (operation === "here") {
460
+ const found = await registry.here(where);
461
+ if (!found.length) return `No registered task works in ${resolve(where)}.\n`;
462
+ return `${found.map(({ id, task }) => `${id} — ${task.title} (${task.environment.primary})`).join("\n")}\n`;
463
+ }
464
+ if (operation === "fanout") {
465
+ const result = await registry.fanout(
466
+ requireOption(options, "--parent"),
467
+ requireOption(options, "--title"),
468
+ requireOption(options, "--goal"),
469
+ { path: options["--path"], base: options["--base"], cwd: where },
470
+ );
471
+ if (result.error) throw new CliError(result.error);
472
+ return `${result.id}\n${result.path}\nbranch ${result.branch}${result.copiedConfig ? "; copied .freeflow/local.json" : ""}\nNext: open a new terminal and run:\n ${startCommand(result.path, options["--agent"])}${options["--agent"] ? "" : " (then start the agent there)"}\n`;
473
+ }
474
+ if (operation === "search") {
475
+ const query = requireOption(options, "--query");
476
+ let records;
477
+ if (options["--id"]) records = await registry.scope(options["--id"], options["--scope"] ?? "task");
478
+ else {
479
+ const slug = (await registry.read()).projects[options["--project"] ?? ""] ? options["--project"] : undefined;
480
+ if (!slug) throw new CliError("Give --id with --scope, or --project with a project's slug.");
481
+ records = (await registry.projectTasks(slug)).map(({ id, task }) => [id, task.record]);
482
+ }
483
+ return `${await searchRecords(records, query)}\n`;
484
+ }
485
+ throw new CliError(`Unknown command: ${command} ${operation}`);
486
+ }
487
+
280
488
  async function runCore(command, rest) {
281
489
  const { options, positionals } = parseOptions(rest);
282
490
  const operation = positionals[0];
283
491
  if (options["--help"]) return commandHelp(command, operation);
284
492
  validateCommandOptions(command, operation, options);
493
+ if (
494
+ command === "project" ||
495
+ (command === "task" && ["create", "import", "search", "env", "here", "fanout", "remove"].includes(operation))
496
+ )
497
+ return runRegistry(command, operation, options);
498
+ // A registered task's ID stands for its record's path.
499
+ if (typeof options["--record"] === "string" && TASK_ID.test(options["--record"])) {
500
+ const task = await new Registry().task(options["--record"]);
501
+ if (!task) throw new CliError(`No task ${options["--record"]} in the registry.`);
502
+ options["--record"] = task.record;
503
+ }
285
504
  if (command === "init") return initialize(options);
286
505
  if (command === "view") {
287
- if (positionals.length > 1) throw new CliError("View accepts only resume or full");
288
506
  const view = positionals[0] ?? options["--view"];
289
- if (!view || !["resume", "full"].includes(view)) throw new CliError("View must be resume or full");
507
+ if (!view || !["resume", "recover", "full", "entry"].includes(view))
508
+ throw new CliError("View must be resume, recover, full, or entry");
509
+ const ids = positionals.slice(1);
510
+ if (view === "entry") {
511
+ if (!ids.length) throw new CliError("View entry needs at least one S-NNN, C-NNN, or D-NNN ID");
512
+ const invalid = ids.find((id) => !/^[SCD]-\d{3,}$/.test(id));
513
+ if (invalid) throw new CliError(`Not an entry ID: ${invalid}`);
514
+ } else if (ids.length) throw new CliError(`View ${view} accepts no further arguments`);
290
515
  const loaded = await readExisting(options);
291
516
  if (view === "full") return renderFull(loaded.text);
517
+ if (view === "entry") return renderEntries(loaded.text, ids);
518
+ if (view === "recover") return renderRecover(loaded.text, { root: loaded.root, recordPath: loaded.path });
292
519
  return renderResume(loaded.text);
293
520
  }
294
521
  if (command === "validate") {
295
522
  if (positionals.length) throw new CliError("Validate does not accept positional arguments");
296
523
  const loaded = await readExisting(options);
297
524
  validateDocument(parseDocument(loaded.text));
298
- return `valid\n${displayPath(loaded.root, loaded.path)}\n`;
525
+ const pointers = checkEvidencePointers(loaded.text, { root: loaded.root, recordPath: loaded.path });
526
+ const outside = pointers.outside.length
527
+ ? `\n${pointers.outside.length} evidence pointer(s) outside the repository, not checked:\n${pointers.outside.map((each) => `- ${each}`).join("\n")}`
528
+ : "";
529
+ // Unresolved pointers warn: a record may name a planned path or a commit not fetched yet. --strict fails on those
530
+ // an Evidence or Result line claims exist.
531
+ const unresolved = options["--strict"] ? pointers.warnings : [...pointers.problems, ...pointers.warnings];
532
+ const warnings = unresolved.length
533
+ ? `\n${unresolved.length} pointer(s) in Material updates do not resolve here (a planned path, or a commit not fetched?):\n${unresolved.map((each) => `- ${each}`).join("\n")}`
534
+ : "";
535
+ if (options["--strict"] && pointers.problems.length)
536
+ throw new CliError(
537
+ `Evidence pointers on Evidence or Result lines do not resolve:\n${pointers.problems.map((each) => `- ${each}`).join("\n")}${warnings}${outside}`,
538
+ );
539
+ return `valid\n${displayPath(loaded.root, loaded.path)}\n${pointers.checked} evidence pointer(s) checked${warnings}${outside}\n`;
299
540
  }
300
541
  if (positionals.length !== 1) throw new CliError(`Expected one operation for ${command}`);
301
542
  const loaded = await readExisting(options);