@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,6 +1,7 @@
1
1
  import {
2
2
  ACTIVE_SLICE_FIELDS,
3
3
  CHECKPOINT_TYPES,
4
+ CONTEXT_HEADINGS,
4
5
  CURRENT_SLICE_STATES,
5
6
  DECISION_FIELDS,
6
7
  DECISION_STATES,
@@ -11,11 +12,16 @@ import {
11
12
  HISTORICAL_SLICE_FIELDS,
12
13
  HISTORICAL_SLICE_STATES,
13
14
  HISTORY_HEADINGS,
15
+ LEGACY_CHECKPOINT_TYPES,
16
+ OCCURRED_PATTERN,
14
17
  PROPOSED_SLICE_FIELDS,
18
+ RECORDED_PATTERN,
15
19
  SCHEMA_VERSION,
16
20
  SLICE_TYPES,
17
21
  TASK_STATES,
18
22
  TOP_LEVEL_SECTIONS,
23
+ WORK_AGREEMENT_HEADING,
24
+ isCalendarDate,
19
25
  joinLines,
20
26
  nextId,
21
27
  parseId,
@@ -251,34 +257,53 @@ function parseTopLevelSections(lines) {
251
257
  );
252
258
  }
253
259
 
260
+ const CONTEXT_LAYOUTS = [CONTEXT_HEADINGS, [CONTEXT_HEADINGS[0], WORK_AGREEMENT_HEADING, ...CONTEXT_HEADINGS.slice(1)]];
261
+
254
262
  function parseContext(lines, section) {
255
263
  const headings = findHeadings(lines, section.start, section.end, 3);
256
- if (headings.length !== 7)
257
- fail("invalid-context", "Current Context must contain exactly the seven canonical headings");
264
+ const titles = headings.map((heading) => heading.title);
265
+ if (!CONTEXT_LAYOUTS.some((layout) => layout.join("\n") === titles.join("\n")))
266
+ fail(
267
+ "invalid-context",
268
+ `Current Context must contain the seven canonical headings, with an optional ${WORK_AGREEMENT_HEADING} directly after Goal`,
269
+ );
258
270
  const statements = new Map();
259
271
  for (let index = 0; index < headings.length; index += 1) {
260
- const expected = [
261
- "Goal",
262
- "What defines this task",
263
- "Settled",
264
- "Tentative",
265
- "Open",
266
- "Current direction",
267
- "Boundaries",
268
- ][index];
269
- if (headings[index].title !== expected) fail("invalid-context", `Expected Current Context heading ${expected}`);
270
272
  const end = headings[index + 1]?.index ?? section.end;
271
- statements.set(expected, { headingIndex: headings[index].index, start: headings[index].index + 1, end });
273
+ statements.set(titles[index], { headingIndex: headings[index].index, start: headings[index].index + 1, end });
272
274
  }
273
275
  return { ...section, headings: statements };
274
276
  }
275
277
 
278
+ const CURRENT_WORK_LAYOUTS = [
279
+ ["Current Slice", "Next useful action"],
280
+ ["Current Slice", "Recovery sources", "Next useful action"],
281
+ ];
282
+
276
283
  function parseCurrentWork(lines, section) {
277
284
  const headings = findHeadings(lines, section.start, section.end, 3);
278
- if (headings.length !== 2 || headings[0].title !== "Current Slice" || headings[1].title !== "Next useful action")
279
- fail("invalid-current-work", "Current Work must contain Current Slice followed by Next useful action");
285
+ const titles = headings.map((heading) => heading.title);
286
+ if (!CURRENT_WORK_LAYOUTS.some((layout) => layout.join("\n") === titles.join("\n")))
287
+ fail(
288
+ "invalid-current-work",
289
+ "Current Work must contain Current Slice, optional Recovery sources, then Next useful action",
290
+ );
291
+ const nextActionHeading = headings[headings.length - 1];
292
+ const recoveryHeading = headings.length === 3 ? headings[1] : null;
280
293
  const sliceContentStart = headings[0].index + 1;
281
294
  const sliceContentEnd = headings[1].index;
295
+ let recoverySources = null;
296
+ if (recoveryHeading) {
297
+ recoverySources = {
298
+ headingIndex: recoveryHeading.index,
299
+ start: recoveryHeading.index + 1,
300
+ end: nextActionHeading.index,
301
+ };
302
+ for (let index = recoverySources.start; index < recoverySources.end; index += 1) {
303
+ if (lineHeading(lines[index]))
304
+ fail("invalid-recovery-sources", `Recovery sources cannot contain headings: ${lines[index]}`);
305
+ }
306
+ }
282
307
  const content = nonBlankLines(lines.slice(sliceContentStart, sliceContentEnd));
283
308
  let currentSlice = null;
284
309
  if (content.length === 1 && content[0] === "None") {
@@ -304,9 +329,11 @@ function parseCurrentWork(lines, section) {
304
329
  return {
305
330
  ...section,
306
331
  sliceHeadingIndex: headings[0].index,
307
- nextActionHeadingIndex: headings[1].index,
332
+ sliceEnd: sliceContentEnd,
333
+ nextActionHeadingIndex: nextActionHeading.index,
308
334
  currentSlice,
309
- nextAction: { start: headings[1].index + 1, end: section.end },
335
+ recoverySources,
336
+ nextAction: { start: nextActionHeading.index + 1, end: section.end },
310
337
  };
311
338
  }
312
339
 
@@ -385,6 +412,8 @@ function parseHistory(lines, section) {
385
412
  };
386
413
  }
387
414
 
415
+ const READABLE_CHECKPOINT_TYPES = new Set([...CHECKPOINT_TYPES, ...LEGACY_CHECKPOINT_TYPES]);
416
+
388
417
  function validateChoice(block, field, choices, required = true) {
389
418
  const value = scalarValue(block, field);
390
419
  if (!value && !required) return "";
@@ -459,16 +488,46 @@ function validateReferences(document) {
459
488
  }
460
489
  }
461
490
 
491
+ export function validateOccurred(value, path) {
492
+ const match = OCCURRED_PATTERN.exec(value ?? "");
493
+ if (!match || !isCalendarDate(match[1]) || (match[2] && !isCalendarDate(match[2])))
494
+ fail("invalid-occurred", `Occurred in ${path} must be YYYY-MM-DD or YYYY-MM-DD to YYYY-MM-DD: ${value}`);
495
+ if (match[2] && match[2] < match[1]) fail("invalid-occurred", `Occurred in ${path} ends before it starts: ${value}`);
496
+ return match[2] ?? match[1];
497
+ }
498
+
499
+ function validateRecordedTime(slice) {
500
+ const occurred = scalarValue(slice, "Occurred");
501
+ const recorded = scalarValue(slice, "Recorded");
502
+ if (!occurred && !recorded) return;
503
+ if (!occurred || !recorded)
504
+ fail("missing-field", `Occurred and Recorded appear together in ${slice.path}; only slice record writes them`);
505
+ const end = validateOccurred(occurred, slice.path);
506
+ const match = RECORDED_PATTERN.exec(recorded);
507
+ if (!match || !isCalendarDate(match[1]))
508
+ fail("invalid-recorded", `Recorded in ${slice.path} must be "retroactively on YYYY-MM-DD": ${recorded}`);
509
+ if (end > match[1]) fail("invalid-occurred", `Occurred in ${slice.path} ends after it was recorded: ${occurred}`);
510
+ }
511
+
462
512
  export function validateDocument(document) {
463
513
  const { header, context, current, future, history } = document;
464
514
  if (!header.name) fail("malformed-header", "Task name cannot be empty");
465
515
  const goal = context.headings.get("Goal");
466
516
  if (!hasMeaningfulContent(document.lines, goal.start, goal.end))
467
517
  fail("missing-field", "Current Context Goal must contain meaningful content");
518
+ const agreement = context.headings.get(WORK_AGREEMENT_HEADING);
519
+ if (agreement && !hasMeaningfulContent(document.lines, agreement.start, agreement.end))
520
+ fail(
521
+ "missing-field",
522
+ `Current Context ${WORK_AGREEMENT_HEADING} must contain meaningful content; omit the heading until something is agreed`,
523
+ );
468
524
  if (!hasMeaningfulContent(document.lines, current.nextAction.start, current.nextAction.end))
469
525
  fail("missing-field", "Next useful action must contain meaningful content");
470
526
  for (const block of allBlocks(document)) {
471
527
  if (block.id && !parseId(block.id, block.kind)) fail("invalid-id", `Invalid ${block.kind} ID ${block.id}`);
528
+ for (const [name, field] of block.fields) {
529
+ if (!valueText(field)) fail("empty-field", `Empty field ${name} in ${block.path}; omit fields without a value`);
530
+ }
472
531
  }
473
532
 
474
533
  const ids = new Set();
@@ -489,7 +548,7 @@ export function validateDocument(document) {
489
548
  } else {
490
549
  validateFields(item, ["State"], {});
491
550
  validateChoice(item, "State", FUTURE_CHECKPOINT_STATES);
492
- validateChoice(item, "Type", CHECKPOINT_TYPES);
551
+ validateChoice(item, "Type", READABLE_CHECKPOINT_TYPES);
493
552
  validateFields(item, ["Condition", "Applies to"]);
494
553
  if (item.id && !parseId(item.id, "checkpoint")) fail("invalid-id", `Invalid Checkpoint ID ${item.id}`);
495
554
  const checkpointState = scalarValue(item, "State");
@@ -530,7 +589,7 @@ export function validateDocument(document) {
530
589
 
531
590
  for (const checkpoint of history.checkpoints.blocks) {
532
591
  validateChoice(checkpoint, "State", HISTORICAL_CHECKPOINT_STATES);
533
- validateChoice(checkpoint, "Type", CHECKPOINT_TYPES);
592
+ validateChoice(checkpoint, "Type", READABLE_CHECKPOINT_TYPES);
534
593
  validateFields(checkpoint, ["Condition", "Applies to", "Result", "Task effect"]);
535
594
  const state = scalarValue(checkpoint, "State");
536
595
  if (state === "cancelled" || state === "replaced") requiredValue(checkpoint, "Reason");
@@ -543,6 +602,7 @@ export function validateDocument(document) {
543
602
  const state = scalarValue(slice, "State");
544
603
  if (state === "blocked") requiredValue(slice, "Resume when");
545
604
  if (state === "abandoned") requiredValue(slice, "Reason");
605
+ validateRecordedTime(slice);
546
606
  }
547
607
 
548
608
  if (header.state === "paused" && current.currentSlice && scalarValue(current.currentSlice, "State") !== "paused")
@@ -10,13 +10,17 @@ export const CONTEXT_HEADINGS = [
10
10
  "Current direction",
11
11
  "Boundaries",
12
12
  ];
13
+ // Optional: allowed only directly after Goal, and never empty.
14
+ export const WORK_AGREEMENT_HEADING = "Work agreement";
13
15
  export const HISTORY_HEADINGS = ["Decisions", "Checkpoints", "Slices"];
14
16
 
15
17
  export const TASK_STATES = new Set(["active", "paused", "completed", "abandoned"]);
16
18
  export const SLICE_TYPES = new Set(["learning", "delivery", "deepening"]);
17
19
  export const CURRENT_SLICE_STATES = new Set(["in_progress", "paused"]);
18
20
  export const HISTORICAL_SLICE_STATES = new Set(["completed", "blocked", "abandoned"]);
19
- export const CHECKPOINT_TYPES = new Set(["independent_review", "local_commit", "user_decision", "continuity"]);
21
+ export const CHECKPOINT_TYPES = new Set(["preserve", "publish", "review", "decision", "continuity"]);
22
+ // Earlier type names remain readable so existing records stay valid.
23
+ export const LEGACY_CHECKPOINT_TYPES = new Set(["local_commit", "independent_review", "user_decision"]);
20
24
  export const FUTURE_CHECKPOINT_STATES = new Set(["proposed", "pending", "deferred"]);
21
25
  export const HISTORICAL_CHECKPOINT_STATES = new Set(["completed", "cancelled", "replaced"]);
22
26
  export const DECISION_STATES = new Set(["active", "superseded", "retired"]);
@@ -60,6 +64,8 @@ export const DECISION_FIELDS = new Set([
60
64
  export const HISTORICAL_SLICE_FIELDS = new Set([
61
65
  "State",
62
66
  "Type",
67
+ "Occurred",
68
+ "Recorded",
63
69
  "Intended result",
64
70
  "Authority source",
65
71
  "Result",
@@ -71,6 +77,15 @@ export const HISTORICAL_SLICE_FIELDS = new Set([
71
77
  "Residual effects",
72
78
  ]);
73
79
 
80
+ // A Slice recorded after the fact carries when it happened and the date it was recorded.
81
+ export const OCCURRED_PATTERN = /^(\d{4}-\d{2}-\d{2})(?: to (\d{4}-\d{2}-\d{2}))?$/;
82
+ export const RECORDED_PATTERN = /^retroactively on (\d{4}-\d{2}-\d{2})$/;
83
+
84
+ export function isCalendarDate(value) {
85
+ const date = new Date(`${value}T00:00:00Z`);
86
+ return !Number.isNaN(date.getTime()) && date.toISOString().slice(0, 10) === value;
87
+ }
88
+
74
89
  export const IDS = {
75
90
  slice: /^S-(\d{3,})$/,
76
91
  checkpoint: /^C-(\d{3,})$/,
@@ -111,6 +126,8 @@ export function canonicalLines(name, state = "active", lastUpdated = new Date().
111
126
  "",
112
127
  "None",
113
128
  "",
129
+ "### Recovery sources",
130
+ "",
114
131
  "### Next useful action",
115
132
  "",
116
133
  "## Future Work",
@@ -0,0 +1,254 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { dirname, isAbsolute, join, relative } from "node:path";
5
+ import { parseDocument, sectionContentLines } from "./document.mjs";
6
+ import { renderResume } from "./views.mjs";
7
+
8
+ // Recovery in one call (Track Work, "Recover After Context Loss"): the resume view, then what each defining artifact
9
+ // and Recovery source points to and whether it can be read now, then where live Git state disagrees with the record.
10
+ // It reports; reading the sources and reconciling stays the agent's work.
11
+ //
12
+ // It also finds the evidence pointers in Material updates for `validate`: files and commits a later context will
13
+ // rely on. A pointer inside the repository that does not resolve is a problem; one outside it is reported, not checked.
14
+
15
+ const PATH_TOKEN = /^(~\/|\/|\.{1,2}\/)?[A-Za-z0-9_@.-]+(\/[A-Za-z0-9_@.()-]+)*\/?(#[^\s]*)?$/;
16
+ const COMMIT = /^[0-9a-f]{7,40}$/;
17
+ const URL = /^[a-z][a-z0-9+.-]*:\/\//i;
18
+
19
+ function git(root, args) {
20
+ try {
21
+ return execFileSync("git", args, { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+
27
+ // A path names a file with an extension, a directory with a trailing "/", or starts like one (./, ../, ~/, /). Slashed
28
+ // words such as "lost/weakened" or "17/9" are not paths.
29
+ const looksLikePath = (token) =>
30
+ PATH_TOKEN.test(token) &&
31
+ !COMMIT.test(token) &&
32
+ !token.includes("*") &&
33
+ (/^(~\/|\/|\.{1,2}\/)/.test(token) ||
34
+ /\/$/.test(token) ||
35
+ (/\.[A-Za-z][A-Za-z0-9]{0,7}(#.*)?$/.test(token) && (token.includes("/") || /^[^.]+\.[A-Za-z]/.test(token))));
36
+ const looksLikeCommit = (token) => COMMIT.test(token) && /\d/.test(token) && /[a-f]/.test(token);
37
+
38
+ // The pointers a line names: backticked tokens, Markdown link targets, a leading "pointer — ..." token, typed
39
+ // trail pointers (commit:<sha>, file:<path>), and bare commit hashes.
40
+ export function pointersIn(line) {
41
+ const found = [];
42
+ const add = (kind, value) => {
43
+ if (!found.some((each) => each.kind === kind && each.value === value)) found.push({ kind, value });
44
+ };
45
+ const text = line.replace(/^\s*[-*]\s+/, "");
46
+ for (const match of text.matchAll(/\]\(([^)\s]+)\)/g)) classify(match[1], add);
47
+ for (const match of text.matchAll(/`([^`\n]+)`/g)) classify(match[1].trim(), add);
48
+ const lead = /^(\S+)\s+[—–-]\s/.exec(text);
49
+ if (lead) classify(lead[1].replace(/[,;:]$/, ""), add);
50
+ const prose = text.replace(/`[^`\n]*`/g, " ").replace(/\]\([^)]*\)/g, " ");
51
+ for (const match of prose.matchAll(/\b(?:commit|file|path):([^\s,;)]+)/g))
52
+ classify(match[1], add, match[0].startsWith("commit:"));
53
+ for (const word of prose.split(/[\s,;()[\]"'“”]+/)) {
54
+ const token = word.replace(/[.:]+$/, "");
55
+ if (looksLikeCommit(token)) add("commit", token);
56
+ // A bare path in prose must name a file: a slashed word ending in "/" is usually a folder named in passing.
57
+ else if (token.includes("/") && !token.endsWith("/") && looksLikePath(token) && !URL.test(token))
58
+ add("path", token.replace(/#.*$/, ""));
59
+ }
60
+ return found;
61
+ }
62
+
63
+ function classify(raw, add, commitOnly = false) {
64
+ const token = raw.replace(/^(file|path|commit):/, "");
65
+ if (URL.test(token)) return add("url", token);
66
+ if (commitOnly || looksLikeCommit(token)) return add("commit", token);
67
+ const range = /^([0-9a-f]{7,40})\.\.\.?([0-9a-f]{7,40}|HEAD)$/.exec(token);
68
+ if (range) {
69
+ add("commit", range[1]);
70
+ if (range[2] !== "HEAD") add("commit", range[2]);
71
+ return;
72
+ }
73
+ if (looksLikePath(token)) add("path", token.replace(/#.*$/, ""));
74
+ }
75
+
76
+ // Where a path pointer resolves: the repository root, the task folder, or as given when absolute or home-relative.
77
+ export function resolvePointer(pointer, { root, taskDir }) {
78
+ if (pointer.startsWith("~/")) return { outside: true, path: join(homedir(), pointer.slice(2)) };
79
+ if (isAbsolute(pointer)) {
80
+ const inside = !relative(root, pointer).startsWith("..");
81
+ return { outside: !inside, path: pointer };
82
+ }
83
+ const candidates = [join(taskDir, pointer), join(root, pointer)];
84
+ const hit = candidates.find((candidate) => existsSync(candidate));
85
+ return { outside: false, path: hit ?? candidates[1] };
86
+ }
87
+
88
+ function describe(path) {
89
+ try {
90
+ const stat = statSync(path);
91
+ if (stat.isDirectory()) return `directory, ${readdirSync(path).length} entries`;
92
+ const text = readFileSync(path, "utf8");
93
+ return `${text.split("\n").length} lines, ${text.split(/\s+/).filter(Boolean).length} words`;
94
+ } catch {
95
+ return null;
96
+ }
97
+ }
98
+
99
+ function checkPointer(pointer, context) {
100
+ if (pointer.kind === "url") return { ...pointer, state: "not checked (URL)" };
101
+ if (pointer.kind === "commit") {
102
+ if (!context.isGit) return { ...pointer, state: "not checked (not a Git repository)" };
103
+ const full = git(context.root, ["rev-parse", "--verify", "--quiet", `${pointer.value}^{commit}`]);
104
+ return full
105
+ ? { ...pointer, state: "resolves", commit: full }
106
+ : { ...pointer, state: "missing", problem: `commit ${pointer.value} is not in this repository` };
107
+ }
108
+ const where = resolvePointer(pointer.value, context);
109
+ const size = describe(where.path);
110
+ if (size) return { ...pointer, state: "resolves", size, ...(where.outside ? { outside: true } : {}) };
111
+ if (where.outside) return { ...pointer, state: "not checked (outside the repository)", outside: true };
112
+ return { ...pointer, state: "missing", problem: `${pointer.value} does not exist` };
113
+ }
114
+
115
+ const bullets = (lines) => lines.filter((line) => /^\s*[-*]\s+\S/.test(line));
116
+
117
+ function sourceEntries(lines, context) {
118
+ return bullets(lines).map((line) => {
119
+ const text = line.trim().replace(/^[-*]\s+/, "");
120
+ const trigger = /\bread (?:only )?(?:when|if) ([^.;]+)/i.exec(text)?.[1]?.trim() ?? null;
121
+ return { text, trigger, pointers: pointersIn(line).map((pointer) => checkPointer(pointer, context)) };
122
+ });
123
+ }
124
+
125
+ function liveState(document, context) {
126
+ const { root } = context;
127
+ if (!context.isGit) return { git: false, mismatches: [], notes: ["not a Git repository: no live state to compare"] };
128
+ const branch = git(root, ["branch", "--show-current"]) || null;
129
+ const head = git(root, ["rev-parse", "--short=12", "HEAD"]);
130
+ const subject = head ? git(root, ["log", "-1", "--format=%s"]) : null;
131
+ const dirty = (git(root, ["status", "--porcelain"]) ?? "").split("\n").filter(Boolean).length;
132
+ const mismatches = [];
133
+ const notes = [];
134
+ const current = document.sections["Current Work"];
135
+ const sliceText = current ? document.lines.slice(current.start, current.end).join("\n") : "";
136
+ const contextText = sectionContentLines(document, "Current Context").join("\n");
137
+ const branches = (git(root, ["for-each-ref", "--format=%(refname:short)", "refs/heads"]) ?? "")
138
+ .split("\n")
139
+ .filter(Boolean);
140
+ const named = branches.filter((name) =>
141
+ new RegExp(`(^|[\\s\`(])${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}([\\s\`),.;:]|$)`).test(
142
+ `${sliceText}\n${contextText}`,
143
+ ),
144
+ );
145
+ if (!branch) mismatches.push(`HEAD is detached at ${head}`);
146
+ else if (named.length && !named.includes(branch))
147
+ mismatches.push(`the record names branch ${named.join(", ")}; HEAD is on ${branch}`);
148
+ const commits = [...new Set(pointersIn(sliceText.replace(/\n/g, " ")).filter((each) => each.kind === "commit"))];
149
+ for (const { value } of commits) {
150
+ const full = git(root, ["rev-parse", "--verify", "--quiet", `${value}^{commit}`]);
151
+ if (!full) mismatches.push(`the Current Slice names commit ${value}, which this repository does not have`);
152
+ else if (head && git(root, ["merge-base", "--is-ancestor", full, "HEAD"]) === null)
153
+ mismatches.push(`the Current Slice names commit ${value}, which is not in HEAD's history`);
154
+ }
155
+ const updated = /^Last updated:\s*(\S+)/m.exec(document.lines.slice(0, 10).join("\n"))?.[1];
156
+ if (updated && head) {
157
+ const since = (git(root, ["log", "--oneline", `--since=${updated}`, "HEAD"]) ?? "").split("\n").filter(Boolean);
158
+ if (since.length)
159
+ notes.push(
160
+ `${since.length} commit(s) on HEAD since the record's Last updated (${updated}); it may not describe them`,
161
+ );
162
+ }
163
+ if (dirty) notes.push(`${dirty} uncommitted or untracked path(s)`);
164
+ return { git: true, branch, head, subject, dirty, namedBranches: named, mismatches, notes };
165
+ }
166
+
167
+ function contextFor(root, recordPath) {
168
+ return {
169
+ root,
170
+ taskDir: dirname(recordPath),
171
+ isGit: git(root, ["rev-parse", "--is-inside-work-tree"]) === "true",
172
+ };
173
+ }
174
+
175
+ function gitRoot(root) {
176
+ return git(root, ["rev-parse", "--show-toplevel"]) ?? root;
177
+ }
178
+
179
+ export function renderRecover(text, { root, recordPath }) {
180
+ const document = parseDocument(text);
181
+ const context = contextFor(gitRoot(root), recordPath);
182
+ const defines = document.context.headings.get("What defines this task");
183
+ const defining = sourceEntries(document.lines.slice(defines.start, defines.end), context);
184
+ const sources = document.current.recoverySources;
185
+ const recovery = sources ? sourceEntries(document.lines.slice(sources.start, sources.end), context) : [];
186
+ const live = liveState(document, context);
187
+ const pointerLine = (pointer) =>
188
+ `${pointer.value}: ${pointer.state}${pointer.size ? ` (${pointer.size})` : ""}${pointer.outside && pointer.size ? ", outside the repository" : ""}`;
189
+ const entryLines = (entries, withTrigger) =>
190
+ entries.length
191
+ ? entries.flatMap((entry) => [
192
+ `- ${entry.text}`,
193
+ ...(withTrigger ? [` - ${entry.trigger ? `read when ${entry.trigger}` : "read now"}`] : []),
194
+ ...(entry.pointers.length
195
+ ? entry.pointers.map((pointer) => ` - ${pointerLine(pointer)}`)
196
+ : [" - no pointer found: recover it from the text"]),
197
+ ])
198
+ : ["None."];
199
+ const lines = [
200
+ "## Recovery",
201
+ "",
202
+ "Read in this order: every defining artifact, then each Recovery source whose trigger applies, then the History entries the next action depends on (`view entry <ID>`).",
203
+ "",
204
+ "### Defining artifacts",
205
+ "",
206
+ ...entryLines(defining, false),
207
+ "",
208
+ "### Recovery sources",
209
+ "",
210
+ ...entryLines(recovery, true),
211
+ "",
212
+ "### Live state",
213
+ "",
214
+ ...(live.git
215
+ ? [
216
+ `- ${live.branch ? `branch ${live.branch}` : "detached HEAD"}, HEAD ${live.head ?? "none"}${live.subject ? ` (${live.subject})` : ""}`,
217
+ ]
218
+ : []),
219
+ ...live.notes.map((note) => `- ${note}`),
220
+ ...(live.mismatches.length
221
+ ? ["", "Mismatches: resolve each from sources before acting.", ...live.mismatches.map((each) => `- ${each}`)]
222
+ : ["- no mismatch found between the record and live Git state"]),
223
+ ];
224
+ const resume = renderResume(text);
225
+ return `${resume.trimEnd()}${document.newline}${document.newline}${lines.join(document.newline)}${document.newline}`;
226
+ }
227
+
228
+ // Evidence pointers in every Material updates list. An unresolved pointer inside the repository is a problem on an
229
+ // Evidence or Result line, which claims it exists, and a warning on any other line (an Extension may name a planned
230
+ // path); the caller decides whether problems fail. Pointers outside the repository are listed, not checked.
231
+ export function checkEvidencePointers(text, { root, recordPath }) {
232
+ const document = parseDocument(text);
233
+ const context = contextFor(gitRoot(root), recordPath);
234
+ const lines = document.lines;
235
+ const problems = [];
236
+ const warnings = [];
237
+ const outside = [];
238
+ let checked = 0;
239
+ for (let index = 0; index < lines.length; index += 1) {
240
+ if (!/^#####\s+Material updates\s*$/.test(lines[index])) continue;
241
+ for (let at = index + 1; at < lines.length && !/^#{1,5}\s/.test(lines[at]); at += 1) {
242
+ for (const pointer of pointersIn(lines[at])) {
243
+ if (pointer.kind === "url") continue;
244
+ const result = checkPointer(pointer, context);
245
+ const claims = /^\s*[-*]\s+(Evidence|Result)\b/.test(lines[at]);
246
+ if (result.problem) (claims ? problems : warnings).push(`line ${at + 1}: ${result.problem}`);
247
+ else if (result.outside || result.state.startsWith("not checked"))
248
+ outside.push(`line ${at + 1}: ${pointer.value}`);
249
+ if (!result.outside && !result.state.startsWith("not checked")) checked += 1;
250
+ }
251
+ }
252
+ }
253
+ return { checked, problems, warnings, outside };
254
+ }