@entelligentsia/forgecli 1.0.2 → 1.0.10

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 (423) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +2 -1
  3. package/dist/CHANGELOG-forge-plugin.md +124 -0
  4. package/dist/CHANGELOG-pi.md +94 -0
  5. package/dist/extensions/forgecli/audience-gate.js +1 -1
  6. package/dist/extensions/forgecli/audience-gate.js.map +1 -1
  7. package/dist/extensions/forgecli/fix-bug.d.ts +1 -2
  8. package/dist/extensions/forgecli/fix-bug.js +678 -609
  9. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  10. package/dist/extensions/forgecli/forge-artifact-tool.js +42 -7
  11. package/dist/extensions/forgecli/forge-artifact-tool.js.map +1 -1
  12. package/dist/extensions/forgecli/forge-subagent.d.ts +17 -0
  13. package/dist/extensions/forgecli/forge-subagent.js +31 -12
  14. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  15. package/dist/extensions/forgecli/forge-tools.d.ts +6 -0
  16. package/dist/extensions/forgecli/forge-tools.js +71 -8
  17. package/dist/extensions/forgecli/forge-tools.js.map +1 -1
  18. package/dist/extensions/forgecli/run-task.js +461 -391
  19. package/dist/extensions/forgecli/run-task.js.map +1 -1
  20. package/dist/extensions/forgecli/session-registry.d.ts +12 -0
  21. package/dist/extensions/forgecli/session-registry.js +23 -0
  22. package/dist/extensions/forgecli/session-registry.js.map +1 -1
  23. package/dist/extensions/forgecli/subagent/caller-context.d.ts +35 -11
  24. package/dist/extensions/forgecli/subagent/caller-context.js +49 -21
  25. package/dist/extensions/forgecli/subagent/caller-context.js.map +1 -1
  26. package/dist/extensions/forgecli/subagent/orchestrator-transcript.d.ts +66 -0
  27. package/dist/extensions/forgecli/subagent/orchestrator-transcript.js +66 -0
  28. package/dist/extensions/forgecli/subagent/orchestrator-transcript.js.map +1 -0
  29. package/dist/extensions/forgecli/subagent/phase-guard.d.ts +34 -0
  30. package/dist/extensions/forgecli/subagent/phase-guard.js +149 -0
  31. package/dist/extensions/forgecli/subagent/phase-guard.js.map +1 -0
  32. package/dist/extensions/forgecli/subagent/phase-summary-map.d.ts +2 -0
  33. package/dist/extensions/forgecli/subagent/phase-summary-map.js +39 -0
  34. package/dist/extensions/forgecli/subagent/phase-summary-map.js.map +1 -0
  35. package/dist/extensions/forgecli/thread-switcher.js +2 -2
  36. package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
  37. package/dist/extensions/forgecli/viewport-events.d.ts +4 -0
  38. package/dist/extensions/forgecli/viewport-events.js +18 -1
  39. package/dist/extensions/forgecli/viewport-events.js.map +1 -1
  40. package/dist/extensions/forgecli/viewport-renderer.d.ts +12 -2
  41. package/dist/extensions/forgecli/viewport-renderer.js +8 -6
  42. package/dist/extensions/forgecli/viewport-renderer.js.map +1 -1
  43. package/dist/forge-payload/.base-pack/workflows/_fragments/store-cli-verbs.md +18 -3
  44. package/dist/forge-payload/.base-pack/workflows/architect_approve.md +4 -5
  45. package/dist/forge-payload/.base-pack/workflows/collator_agent.md +1 -1
  46. package/dist/forge-payload/.base-pack/workflows/commit_task.md +2 -3
  47. package/dist/forge-payload/.base-pack/workflows/fix_bug.md +10 -28
  48. package/dist/forge-payload/.base-pack/workflows/implement_plan.md +3 -2
  49. package/dist/forge-payload/.base-pack/workflows/orchestrate_task.md +41 -47
  50. package/dist/forge-payload/.base-pack/workflows/triage.md +190 -0
  51. package/dist/forge-payload/.base-pack/workflows/validate_task.md +2 -3
  52. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  53. package/dist/forge-payload/.schemas/_defs/locator.schema.json +13 -0
  54. package/dist/forge-payload/.schemas/bug.schema.json +1 -0
  55. package/dist/forge-payload/.schemas/enum-catalog.json +2 -2
  56. package/dist/forge-payload/.schemas/migrations.json +72 -0
  57. package/dist/forge-payload/.schemas/sprint.schema.json +1 -0
  58. package/dist/forge-payload/.schemas/task.schema.json +1 -0
  59. package/dist/forge-payload/integrity.json +3 -3
  60. package/dist/forge-payload/meta/fragments/tool-discipline.md +21 -2
  61. package/dist/forge-payload/meta/workflows/_fragments/store-cli-verbs.md +18 -3
  62. package/dist/forge-payload/meta/workflows/meta-approve.md +4 -5
  63. package/dist/forge-payload/meta/workflows/meta-bug-triage.md +210 -0
  64. package/dist/forge-payload/meta/workflows/meta-collate.md +1 -1
  65. package/dist/forge-payload/meta/workflows/meta-commit.md +2 -3
  66. package/dist/forge-payload/meta/workflows/meta-fix-bug.md +10 -28
  67. package/dist/forge-payload/meta/workflows/meta-implement.md +3 -2
  68. package/dist/forge-payload/meta/workflows/meta-orchestrate.md +41 -47
  69. package/dist/forge-payload/meta/workflows/meta-validate.md +2 -3
  70. package/dist/forge-payload/schemas/_defs/locator.schema.json +13 -0
  71. package/dist/forge-payload/schemas/bug.schema.json +1 -0
  72. package/dist/forge-payload/schemas/enum-catalog.json +2 -2
  73. package/dist/forge-payload/schemas/sprint.schema.json +1 -0
  74. package/dist/forge-payload/schemas/structure-manifest.json +22 -2
  75. package/dist/forge-payload/schemas/task.schema.json +1 -0
  76. package/dist/forge-payload/tools/artifact-store.cjs +242 -0
  77. package/dist/forge-payload/tools/artifact.cjs +69 -100
  78. package/dist/forge-payload/tools/lib/artifact-kinds.cjs +95 -0
  79. package/dist/forge-payload/tools/lib/store-nlp.cjs +6 -0
  80. package/dist/forge-payload/tools/lib/store-query-exec.cjs +39 -5
  81. package/dist/forge-payload/tools/lib/suggest.cjs +2 -1
  82. package/dist/forge-payload/tools/preflight-gate.cjs +55 -5
  83. package/dist/forge-payload/tools/store-cli.cjs +50 -15
  84. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.d.ts +5 -2
  85. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
  86. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js +81 -18
  87. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
  88. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
  89. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.js +1 -0
  90. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.js.map +1 -1
  91. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.d.ts.map +1 -1
  92. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +19 -24
  93. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js.map +1 -1
  94. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.d.ts +1 -0
  95. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.d.ts.map +1 -1
  96. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.js +14 -1
  97. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.js.map +1 -1
  98. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts +22 -8
  99. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts.map +1 -1
  100. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.js.map +1 -1
  101. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  102. package/node_modules/@earendil-works/pi-ai/README.md +1 -1
  103. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +374 -122
  104. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  105. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +424 -232
  106. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
  107. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.d.ts +1 -1
  108. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.d.ts.map +1 -1
  109. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +38 -2
  110. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  111. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  112. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +21 -12
  113. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js.map +1 -1
  114. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
  115. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js +6 -10
  116. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
  117. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.d.ts.map +1 -1
  118. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js +1 -1
  119. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js.map +1 -1
  120. package/node_modules/@earendil-works/pi-ai/dist/providers/google.d.ts.map +1 -1
  121. package/node_modules/@earendil-works/pi-ai/dist/providers/google.js +5 -3
  122. package/node_modules/@earendil-works/pi-ai/dist/providers/google.js.map +1 -1
  123. package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.d.ts.map +1 -1
  124. package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.js +3 -4
  125. package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.js.map +1 -1
  126. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.d.ts.map +1 -1
  127. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.js +2 -3
  128. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.js.map +1 -1
  129. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  130. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js +159 -78
  131. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  132. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  133. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js +16 -11
  134. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js.map +1 -1
  135. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
  136. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.js +4 -1
  137. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
  138. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
  139. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js +6 -10
  140. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js.map +1 -1
  141. package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  142. package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.js +1 -0
  143. package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.js.map +1 -1
  144. package/node_modules/@earendil-works/pi-ai/dist/stream.d.ts.map +1 -1
  145. package/node_modules/@earendil-works/pi-ai/dist/stream.js +14 -2
  146. package/node_modules/@earendil-works/pi-ai/dist/stream.js.map +1 -1
  147. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +14 -4
  148. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  149. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  150. package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.d.ts +6 -0
  151. package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.d.ts.map +1 -0
  152. package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.js +34 -0
  153. package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.js.map +1 -0
  154. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts +9 -7
  155. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts.map +1 -1
  156. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js +8 -7
  157. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js.map +1 -1
  158. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  159. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js +1 -1
  160. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  161. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.d.ts +1 -1
  162. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.d.ts.map +1 -1
  163. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js +1 -1
  164. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js.map +1 -1
  165. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.d.ts +10 -1
  166. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.d.ts.map +1 -1
  167. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.js +179 -79
  168. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.js.map +1 -1
  169. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  170. package/node_modules/@earendil-works/pi-coding-agent/CHANGELOG.md +94 -0
  171. package/node_modules/@earendil-works/pi-coding-agent/README.md +9 -0
  172. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.d.ts +3 -0
  173. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
  174. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.js +27 -0
  175. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.js.map +1 -1
  176. package/node_modules/@earendil-works/pi-coding-agent/dist/config.d.ts.map +1 -1
  177. package/node_modules/@earendil-works/pi-coding-agent/dist/config.js +15 -2
  178. package/node_modules/@earendil-works/pi-coding-agent/dist/config.js.map +1 -1
  179. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.d.ts +1 -0
  180. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.d.ts.map +1 -1
  181. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.js +1 -0
  182. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.js.map +1 -1
  183. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.d.ts +5 -1
  184. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  185. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js +28 -4
  186. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  187. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  188. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js +18 -24
  189. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  190. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.d.ts +1 -1
  191. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  192. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js +8 -2
  193. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  194. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts +7 -5
  195. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  196. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  197. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  198. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js +65 -13
  199. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  200. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  201. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js +1 -1
  202. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  203. package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.d.ts +9 -1
  204. package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.d.ts.map +1 -1
  205. package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.js +134 -11
  206. package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.js.map +1 -1
  207. package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.d.ts +2 -0
  208. package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  209. package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.js +10 -6
  210. package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.js.map +1 -1
  211. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.d.ts +6 -7
  212. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  213. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js +75 -28
  214. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  215. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.d.ts +2 -0
  216. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  217. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js +14 -9
  218. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  219. package/node_modules/@earendil-works/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  220. package/node_modules/@earendil-works/pi-coding-agent/dist/core/system-prompt.js +0 -3
  221. package/node_modules/@earendil-works/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  222. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  223. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js +7 -10
  224. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  225. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  226. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  227. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
  228. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
  229. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
  230. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js +5 -7
  231. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
  232. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  233. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js +6 -7
  234. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  235. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.d.ts +5 -2
  236. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.d.ts.map +1 -1
  237. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.js +17 -1
  238. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.js.map +1 -1
  239. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  240. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js +5 -6
  241. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  242. package/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts +2 -0
  243. package/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts.map +1 -1
  244. package/node_modules/@earendil-works/pi-coding-agent/dist/index.js +2 -0
  245. package/node_modules/@earendil-works/pi-coding-agent/dist/index.js.map +1 -1
  246. package/node_modules/@earendil-works/pi-coding-agent/dist/main.d.ts.map +1 -1
  247. package/node_modules/@earendil-works/pi-coding-agent/dist/main.js +69 -16
  248. package/node_modules/@earendil-works/pi-coding-agent/dist/main.js.map +1 -1
  249. package/node_modules/@earendil-works/pi-coding-agent/dist/migrations.d.ts.map +1 -1
  250. package/node_modules/@earendil-works/pi-coding-agent/dist/migrations.js +118 -1
  251. package/node_modules/@earendil-works/pi-coding-agent/dist/migrations.js.map +1 -1
  252. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +1 -3
  253. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  254. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +2 -4
  255. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  256. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  257. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.js +1 -1
  258. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  259. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  260. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  261. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +59 -6
  262. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  263. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  264. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.js +10 -0
  265. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  266. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  267. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js +3 -1
  268. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  269. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +1 -0
  270. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  271. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
  272. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/deprecation.d.ts +4 -0
  273. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/deprecation.d.ts.map +1 -0
  274. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/deprecation.js +13 -0
  275. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/deprecation.js.map +1 -0
  276. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/json.d.ts +3 -0
  277. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/json.d.ts.map +1 -0
  278. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/json.js +7 -0
  279. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/json.js.map +1 -0
  280. package/node_modules/@earendil-works/pi-coding-agent/docs/custom-provider.md +13 -10
  281. package/node_modules/@earendil-works/pi-coding-agent/docs/development.md +1 -1
  282. package/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md +12 -6
  283. package/node_modules/@earendil-works/pi-coding-agent/docs/models.md +25 -12
  284. package/node_modules/@earendil-works/pi-coding-agent/docs/providers.md +13 -5
  285. package/node_modules/@earendil-works/pi-coding-agent/docs/quickstart.md +1 -0
  286. package/node_modules/@earendil-works/pi-coding-agent/docs/rpc.md +2 -1
  287. package/node_modules/@earendil-works/pi-coding-agent/docs/sdk.md +6 -0
  288. package/node_modules/@earendil-works/pi-coding-agent/docs/session-format.md +1 -1
  289. package/node_modules/@earendil-works/pi-coding-agent/docs/sessions.md +8 -0
  290. package/node_modules/@earendil-works/pi-coding-agent/docs/settings.md +7 -3
  291. package/node_modules/@earendil-works/pi-coding-agent/docs/terminal-setup.md +2 -0
  292. package/node_modules/@earendil-works/pi-coding-agent/docs/tui.md +2 -2
  293. package/node_modules/@earendil-works/pi-coding-agent/docs/usage.md +9 -0
  294. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/README.md +1 -0
  295. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/index.ts +1 -1
  296. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/package.json +1 -1
  297. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-gitlab-duo/index.ts +54 -3
  298. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  299. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/git-merge-and-resolve.ts +115 -0
  300. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/input-transform-streaming.ts +39 -0
  301. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/sandbox/package.json +1 -1
  302. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/with-deps/package.json +1 -1
  303. package/node_modules/@earendil-works/pi-coding-agent/npm-shrinkwrap.json +443 -61
  304. package/node_modules/@earendil-works/pi-coding-agent/package.json +6 -6
  305. package/node_modules/@earendil-works/pi-tui/README.md +2 -2
  306. package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
  307. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +24 -83
  308. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
  309. package/node_modules/@earendil-works/pi-tui/dist/components/input.d.ts.map +1 -1
  310. package/node_modules/@earendil-works/pi-tui/dist/components/input.js +7 -55
  311. package/node_modules/@earendil-works/pi-tui/dist/components/input.js.map +1 -1
  312. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts +7 -1
  313. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts.map +1 -1
  314. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js +12 -2
  315. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js.map +1 -1
  316. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +1 -1
  317. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
  318. package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
  319. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts +1 -1
  320. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts.map +1 -1
  321. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js +34 -7
  322. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js.map +1 -1
  323. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +33 -10
  324. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  325. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +172 -37
  326. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  327. package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts +6 -1
  328. package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts.map +1 -1
  329. package/node_modules/@earendil-works/pi-tui/dist/utils.js +27 -15
  330. package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
  331. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.d.ts +25 -0
  332. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.d.ts.map +1 -0
  333. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.js +96 -0
  334. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.js.map +1 -0
  335. package/node_modules/@earendil-works/pi-tui/package.json +2 -2
  336. package/node_modules/@entelligentsia/forge-compress/LICENSE +21 -0
  337. package/node_modules/@entelligentsia/forge-compress/README.md +85 -0
  338. package/node_modules/@entelligentsia/forge-compress/dist/compressor.d.ts +6 -0
  339. package/node_modules/@entelligentsia/forge-compress/dist/compressor.js +137 -0
  340. package/node_modules/@entelligentsia/forge-compress/dist/entropy.d.ts +3 -0
  341. package/node_modules/@entelligentsia/forge-compress/dist/entropy.js +99 -0
  342. package/node_modules/@entelligentsia/forge-compress/dist/forge/entity.d.ts +8 -0
  343. package/node_modules/@entelligentsia/forge-compress/dist/forge/entity.js +149 -0
  344. package/node_modules/@entelligentsia/forge-compress/dist/forge/index.d.ts +7 -0
  345. package/node_modules/@entelligentsia/forge-compress/dist/forge/index.js +4 -0
  346. package/node_modules/@entelligentsia/forge-compress/dist/forge/markdown.d.ts +5 -0
  347. package/node_modules/@entelligentsia/forge-compress/dist/forge/markdown.js +92 -0
  348. package/node_modules/@entelligentsia/forge-compress/dist/forge/query.d.ts +7 -0
  349. package/node_modules/@entelligentsia/forge-compress/dist/forge/query.js +60 -0
  350. package/node_modules/@entelligentsia/forge-compress/dist/forge/validate.d.ts +1 -0
  351. package/node_modules/@entelligentsia/forge-compress/dist/forge/validate.js +82 -0
  352. package/node_modules/@entelligentsia/forge-compress/dist/index.d.ts +6 -0
  353. package/node_modules/@entelligentsia/forge-compress/dist/index.js +5 -0
  354. package/node_modules/@entelligentsia/forge-compress/dist/progressive.d.ts +1 -0
  355. package/node_modules/@entelligentsia/forge-compress/dist/progressive.js +108 -0
  356. package/node_modules/@entelligentsia/forge-compress/dist/strip.d.ts +4 -0
  357. package/node_modules/@entelligentsia/forge-compress/dist/strip.js +55 -0
  358. package/node_modules/@entelligentsia/forge-compress/dist/tokens.d.ts +2 -0
  359. package/node_modules/@entelligentsia/forge-compress/dist/tokens.js +17 -0
  360. package/node_modules/@entelligentsia/forge-compress/package.json +45 -0
  361. package/node_modules/@entelligentsia/forge-compress/src/__tests__/compress.test.ts +409 -0
  362. package/node_modules/@entelligentsia/forge-compress/src/compressor.ts +147 -0
  363. package/node_modules/@entelligentsia/forge-compress/src/entropy.ts +105 -0
  364. package/node_modules/@entelligentsia/forge-compress/src/forge/entity.ts +184 -0
  365. package/node_modules/@entelligentsia/forge-compress/src/forge/index.ts +10 -0
  366. package/node_modules/@entelligentsia/forge-compress/src/forge/markdown.ts +122 -0
  367. package/node_modules/@entelligentsia/forge-compress/src/forge/query.ts +105 -0
  368. package/node_modules/@entelligentsia/forge-compress/src/forge/validate.ts +86 -0
  369. package/node_modules/@entelligentsia/forge-compress/src/index.ts +22 -0
  370. package/node_modules/@entelligentsia/forge-compress/src/progressive.ts +123 -0
  371. package/node_modules/@entelligentsia/forge-compress/src/strip.ts +58 -0
  372. package/node_modules/@entelligentsia/forge-compress/src/tokens.ts +19 -0
  373. package/node_modules/@mariozechner/clipboard/Cargo.toml +3 -3
  374. package/node_modules/@mariozechner/clipboard/index.d.ts +34 -20
  375. package/node_modules/@mariozechner/clipboard/index.js +546 -257
  376. package/node_modules/@mariozechner/clipboard/package.json +5 -6
  377. package/node_modules/@mariozechner/clipboard/package.json.prepack-backup +14 -14
  378. package/node_modules/@mariozechner/clipboard/src/lib.rs +4 -9
  379. package/node_modules/@mariozechner/clipboard-linux-x64-gnu/clipboard.linux-x64-gnu.node +0 -0
  380. package/node_modules/@mariozechner/clipboard-linux-x64-gnu/package.json +2 -2
  381. package/package.json +11 -16
  382. package/dist/forge-payload/.base-pack/commands/quiz-agent.md +0 -6
  383. package/dist/forge-payload/.base-pack/commands/retrospective.md +0 -6
  384. package/dist/forge-payload/.base-pack/commands/sprint-intake.md +0 -6
  385. package/dist/forge-payload/.base-pack/commands/sprint-plan.md +0 -6
  386. package/dist/forge-payload/commands/calibrate.md +0 -10
  387. package/dist/forge-payload/commands/materialize.md +0 -119
  388. package/dist/forge-payload/commands/migrate.md +0 -12
  389. package/dist/forge-payload/commands/quiz-agent.md +0 -6
  390. package/dist/forge-payload/commands/regenerate.md +0 -6
  391. package/dist/forge-payload/commands/store-query.md +0 -6
  392. package/dist/forge-payload/commands/store-repair.md +0 -6
  393. package/dist/forge-payload/commands/update-tools.md +0 -10
  394. package/dist/forge-payload/meta/templates/meta-retrospective.md +0 -28
  395. package/dist/forge-payload/tools/prompts/sprint-plan-prompt.md +0 -70
  396. package/dist/forge-payload/tools/schemas/task-list.schema.json +0 -53
  397. package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.d.ts +0 -4
  398. package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.d.ts.map +0 -1
  399. package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.js +0 -3
  400. package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.js.map +0 -1
  401. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.d.ts +0 -20
  402. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.d.ts.map +0 -1
  403. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.js +0 -92
  404. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.js.map +0 -1
  405. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.d.ts +0 -18
  406. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.d.ts.map +0 -1
  407. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.js +0 -42
  408. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.js.map +0 -1
  409. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.d.ts +0 -10
  410. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.d.ts.map +0 -1
  411. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.js +0 -31
  412. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.js.map +0 -1
  413. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.d.ts +0 -30
  414. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.d.ts.map +0 -1
  415. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.js +0 -170
  416. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.js.map +0 -1
  417. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.d.ts +0 -26
  418. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.d.ts.map +0 -1
  419. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.js +0 -90
  420. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.js.map +0 -1
  421. package/node_modules/@mariozechner/clipboard-linux-x64-musl/README.md +0 -3
  422. package/node_modules/@mariozechner/clipboard-linux-x64-musl/clipboard.linux-x64-musl.node +0 -0
  423. package/node_modules/@mariozechner/clipboard-linux-x64-musl/package.json +0 -25
@@ -0,0 +1,108 @@
1
+ import { truncateToTokenBudget } from "./tokens.js";
2
+ const LAMBDA = 1.35;
3
+ function expWeights(n) {
4
+ return Array.from({ length: n }, (_, i) => Math.exp(LAMBDA * i));
5
+ }
6
+ function allocateBudget(budgetTokens, weights) {
7
+ const n = weights.length;
8
+ if (n === 0 || budgetTokens === 0)
9
+ return new Array(n).fill(0);
10
+ const sumW = Math.max(weights.reduce((a, b) => a + b, 0), Number.EPSILON);
11
+ const base = new Array(n).fill(0);
12
+ const frac = new Array(n).fill(0);
13
+ for (let i = 0; i < n; i++) {
14
+ const exact = (budgetTokens * weights[i]) / sumW;
15
+ base[i] = Math.floor(exact);
16
+ frac[i] = exact - base[i];
17
+ }
18
+ const given = base.reduce((a, b) => a + b, 0);
19
+ const order = Array.from({ length: n }, (_, i) => i).sort((a, b) => frac[b] - frac[a]);
20
+ let extra = budgetTokens - given;
21
+ for (const i of order) {
22
+ if (extra <= 0)
23
+ break;
24
+ base[i]++;
25
+ extra--;
26
+ }
27
+ return base;
28
+ }
29
+ function tierForIndex(i, n) {
30
+ if (n <= 1)
31
+ return 2;
32
+ const r = i / (n - 1);
33
+ if (r < 1 / 3)
34
+ return 0;
35
+ if (r < 2 / 3)
36
+ return 1;
37
+ return 2;
38
+ }
39
+ const STRUCTURE_KEYWORDS = [
40
+ "fn ",
41
+ "pub ",
42
+ "struct ",
43
+ "enum ",
44
+ "trait ",
45
+ "impl ",
46
+ "mod ",
47
+ "use ",
48
+ "def ",
49
+ "class ",
50
+ "function ",
51
+ "export ",
52
+ "import ",
53
+ "const ",
54
+ "interface ",
55
+ ];
56
+ function mapLike(s, maxTokens) {
57
+ const picked = [];
58
+ const lines = s.split("\n");
59
+ for (let i = 0; i < lines.length; i++) {
60
+ if (i === 0 || STRUCTURE_KEYWORDS.some((k) => lines[i].includes(k))) {
61
+ picked.push(lines[i]);
62
+ }
63
+ if (picked.length >= 48)
64
+ break;
65
+ }
66
+ if (picked.length === 0 && lines.length > 0) {
67
+ picked.push(lines[0]);
68
+ }
69
+ return truncateToTokenBudget(picked.join("\n"), Math.max(4, maxTokens));
70
+ }
71
+ function oneLineSummary(segIdx, s, maxTokens) {
72
+ const preview = s.split("\n")[0]?.slice(0, 120) ?? "";
73
+ const lineCount = s.split("\n").length;
74
+ const draft = `// seg[${segIdx}] ${lineCount} lines, ${s.length} chars | ${preview}`;
75
+ return truncateToTokenBudget(draft, Math.max(8, maxTokens));
76
+ }
77
+ export function compressProgressive(segments, budgetTokens) {
78
+ const n = segments.length;
79
+ if (n === 0)
80
+ return [];
81
+ if (budgetTokens === 0)
82
+ return segments.map(() => "");
83
+ const weights = expWeights(n);
84
+ const allocs = allocateBudget(budgetTokens, weights);
85
+ const out = [];
86
+ for (let i = 0; i < n; i++) {
87
+ const alloc = allocs[i];
88
+ const tier = tierForIndex(i, n);
89
+ if (alloc === 0) {
90
+ out.push("");
91
+ continue;
92
+ }
93
+ let compressed;
94
+ switch (tier) {
95
+ case 2:
96
+ compressed = truncateToTokenBudget(segments[i], alloc);
97
+ break;
98
+ case 1:
99
+ compressed = mapLike(segments[i], alloc);
100
+ break;
101
+ default:
102
+ compressed = oneLineSummary(i, segments[i], alloc);
103
+ break;
104
+ }
105
+ out.push(truncateToTokenBudget(compressed, alloc));
106
+ }
107
+ return out;
108
+ }
@@ -0,0 +1,4 @@
1
+ export declare function stripAnsi(s: string): string;
2
+ export declare function stripTimestampsAndHashes(line: string): string;
3
+ export declare function normalizeWhitespace(line: string): string;
4
+ export declare function isBoilerplate(line: string): boolean;
@@ -0,0 +1,55 @@
1
+ const ANSI_RE = /\x1b\[[0-9;]*[a-zA-Z]/g;
2
+ export function stripAnsi(s) {
3
+ if (!s.includes("\x1b"))
4
+ return s;
5
+ return s.replace(ANSI_RE, "");
6
+ }
7
+ const TS_RE = /\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?/g;
8
+ const HASH_RE = /\b[0-9a-f]{32,64}\b/g;
9
+ export function stripTimestampsAndHashes(line) {
10
+ return line.replace(TS_RE, "[TS]").replace(HASH_RE, "[HASH]");
11
+ }
12
+ export function normalizeWhitespace(line) {
13
+ let result = "";
14
+ let prevSpace = false;
15
+ for (const ch of line) {
16
+ if (ch === " " || ch === "\t") {
17
+ if (!prevSpace) {
18
+ result += " ";
19
+ prevSpace = true;
20
+ }
21
+ }
22
+ else {
23
+ result += ch;
24
+ prevSpace = false;
25
+ }
26
+ }
27
+ return result;
28
+ }
29
+ const BOILERPLATE_PREFIXES = [
30
+ "copyright",
31
+ "licensed under",
32
+ "license:",
33
+ "all rights reserved",
34
+ "generated by",
35
+ "auto-generated",
36
+ ];
37
+ const SEPARATOR_CHARS = new Set(["=", "-", "*", "─", "━"]);
38
+ export function isBoilerplate(line) {
39
+ const lower = line.toLowerCase();
40
+ if (BOILERPLATE_PREFIXES.some((p) => lower.startsWith(p)))
41
+ return true;
42
+ if (line.length >= 4) {
43
+ const first = line[0];
44
+ if (SEPARATOR_CHARS.has(first)) {
45
+ let same = 0;
46
+ for (const c of line) {
47
+ if (c === first)
48
+ same++;
49
+ }
50
+ if (same / line.length > 0.8)
51
+ return true;
52
+ }
53
+ }
54
+ return false;
55
+ }
@@ -0,0 +1,2 @@
1
+ export declare function countTokens(text: string): number;
2
+ export declare function truncateToTokenBudget(text: string, maxTokens: number): string;
@@ -0,0 +1,17 @@
1
+ const CHARS_PER_TOKEN = 3.7;
2
+ export function countTokens(text) {
3
+ if (!text)
4
+ return 0;
5
+ return Math.ceil(text.length / CHARS_PER_TOKEN);
6
+ }
7
+ export function truncateToTokenBudget(text, maxTokens) {
8
+ if (maxTokens <= 0)
9
+ return "";
10
+ if (countTokens(text) <= maxTokens)
11
+ return text;
12
+ const charBudget = Math.floor(maxTokens * CHARS_PER_TOKEN);
13
+ const truncated = text.slice(0, charBudget);
14
+ const lastNewline = truncated.lastIndexOf("\n");
15
+ const clean = lastNewline > 0 ? truncated.slice(0, lastNewline) : truncated;
16
+ return `${clean} …`;
17
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@entelligentsia/forge-compress",
3
+ "repository": {
4
+ "type": "git",
5
+ "url": "https://github.com/Entelligentsia/forge-compress.git"
6
+ },
7
+ "version": "0.1.0",
8
+ "description": "Token-efficient compression for Forge SDLC tool outputs — store queries, entities, artifacts",
9
+ "type": "module",
10
+ "main": "dist/index.js",
11
+ "types": "dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "src"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "lint": "biome check src/",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "keywords": [
30
+ "compression",
31
+ "forge",
32
+ "sdlc",
33
+ "ai-agent",
34
+ "token-reduction"
35
+ ],
36
+ "license": "MIT",
37
+ "devDependencies": {
38
+ "typescript": "^5.7.0",
39
+ "vitest": "^3.0.0",
40
+ "@biomejs/biome": "^1.9.0"
41
+ },
42
+ "engines": {
43
+ "node": ">=18"
44
+ }
45
+ }
@@ -0,0 +1,409 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import {
3
+ compressStoreQuery,
4
+ compressEntity,
5
+ compressEntityList,
6
+ compressMarkdown,
7
+ compressValidateStore,
8
+ countTokens,
9
+ compressIb,
10
+ compressProgressive,
11
+ truncateToTokenBudget,
12
+ lightweightCleanup,
13
+ verbatimCompact,
14
+ stripAnsi,
15
+ } from "../index.js";
16
+
17
+ // ── store-query compressor ──────────────────────────────────
18
+
19
+ const SAMPLE_QUERY = JSON.stringify(
20
+ {
21
+ query: "open tasks in S12",
22
+ path: "intent-nlp",
23
+ traversalTrace: [
24
+ "parsed intent: entity=task, status=open, sprint=S12",
25
+ "resolved S12 → PROJ-S12",
26
+ "loaded 8 task records",
27
+ "filtered by status: 5 matched",
28
+ ],
29
+ results: [
30
+ {
31
+ id: "PROJ-S12-T01",
32
+ title: "Add auth middleware",
33
+ status: "implementing",
34
+ type: "task",
35
+ relationships: { sprintId: "PROJ-S12", featureId: "F-AUTH", blockedBy: null },
36
+ fileRefs: { json: ".forge/store/tasks/PROJ-S12-T01.json", md: ".forge/sprints/S12/tasks/T01/INDEX.md" },
37
+ storeRef: ".forge/store/tasks/PROJ-S12-T01.json",
38
+ indexRef: ".forge/sprints/S12/tasks/T01/INDEX.md",
39
+ excerpt: "# T01: Add auth middleware\n\n## Status: implementing\n\n## Plan\nImplement JWT-based auth middleware...\n\n## Key Changes\n- Added middleware handler\n- Updated route config\n- Added token validation\n\n## Notes\nBlocked by upstream API changes.\nNeed to coordinate with team B.\nAlso requires DB migration.\nSee PR #42 for details.\nReviewed by @alice.",
40
+ },
41
+ {
42
+ id: "PROJ-S12-T02",
43
+ title: "Fix rate limiter",
44
+ status: "planned",
45
+ type: "task",
46
+ relationships: { sprintId: "PROJ-S12" },
47
+ fileRefs: { json: ".forge/store/tasks/PROJ-S12-T02.json", md: ".forge/sprints/S12/tasks/T02/INDEX.md" },
48
+ storeRef: ".forge/store/tasks/PROJ-S12-T02.json",
49
+ indexRef: ".forge/sprints/S12/tasks/T02/INDEX.md",
50
+ excerpt: "# T02: Fix rate limiter\n\n## Status: planned\n\nRate limiter is dropping legitimate requests under load.",
51
+ },
52
+ ],
53
+ relatedFileRefs: [".forge/sprints/S12/INDEX.md", ".forge/features/F-AUTH.md"],
54
+ config: { store: ".forge/store", engineering: ".forge/engineering" },
55
+ meta: { mode: "intent-nlp", engineVersion: "1.2.0", totalTimeMs: 42 },
56
+ },
57
+ null,
58
+ 2,
59
+ );
60
+
61
+ describe("compressStoreQuery", () => {
62
+ it("strips envelope fields", () => {
63
+ const result = compressStoreQuery(SAMPLE_QUERY);
64
+ const parsed = JSON.parse(result);
65
+ expect(parsed.traversalTrace).toBeUndefined();
66
+ expect(parsed.config).toBeUndefined();
67
+ expect(parsed.meta).toBeUndefined();
68
+ expect(parsed.relatedFileRefs).toBeUndefined();
69
+ expect(parsed.results).toHaveLength(2);
70
+ });
71
+
72
+ it("strips fileRefs and storeRef from results", () => {
73
+ const result = compressStoreQuery(SAMPLE_QUERY);
74
+ const parsed = JSON.parse(result);
75
+ expect(parsed.results[0].fileRefs).toBeUndefined();
76
+ expect(parsed.results[0].storeRef).toBeUndefined();
77
+ expect(parsed.results[0].indexRef).toBeUndefined();
78
+ });
79
+
80
+ it("strips excerpts by default", () => {
81
+ const result = compressStoreQuery(SAMPLE_QUERY);
82
+ const parsed = JSON.parse(result);
83
+ expect(parsed.results[0].excerpt).toBeUndefined();
84
+ });
85
+
86
+ it("keeps truncated excerpts when requested", () => {
87
+ const result = compressStoreQuery(SAMPLE_QUERY, {
88
+ keepExcerpts: true,
89
+ maxExcerptLines: 3,
90
+ });
91
+ const parsed = JSON.parse(result);
92
+ expect(parsed.results[0].excerpt).toContain("Add auth middleware");
93
+ expect(parsed.results[0].excerpt).toContain("more lines");
94
+ });
95
+
96
+ it("preserves query and path", () => {
97
+ const result = compressStoreQuery(SAMPLE_QUERY);
98
+ const parsed = JSON.parse(result);
99
+ expect(parsed.query).toBe("open tasks in S12");
100
+ expect(parsed.path).toBe("intent-nlp");
101
+ });
102
+
103
+ it("limits results count", () => {
104
+ const result = compressStoreQuery(SAMPLE_QUERY, { maxResults: 1 });
105
+ const parsed = JSON.parse(result);
106
+ expect(parsed.results).toHaveLength(1);
107
+ expect(parsed.truncated).toBe(1);
108
+ });
109
+
110
+ it("strips null relationships", () => {
111
+ const result = compressStoreQuery(SAMPLE_QUERY);
112
+ const parsed = JSON.parse(result);
113
+ expect(parsed.results[0].relationships.blockedBy).toBeUndefined();
114
+ });
115
+
116
+ it("is significantly smaller than input", () => {
117
+ const result = compressStoreQuery(SAMPLE_QUERY);
118
+ expect(countTokens(result)).toBeLessThan(countTokens(SAMPLE_QUERY) * 0.5);
119
+ });
120
+
121
+ it("passes through non-JSON input", () => {
122
+ expect(compressStoreQuery("not json")).toBe("not json");
123
+ });
124
+ });
125
+
126
+ // ── entity compressor ───────────────────────────────────────
127
+
128
+ const SAMPLE_TASK = JSON.stringify(
129
+ {
130
+ taskId: "PROJ-S12-T01",
131
+ sprintId: "PROJ-S12",
132
+ title: "Add auth middleware",
133
+ status: "implementing",
134
+ path: "sprints/S12/tasks/T01",
135
+ feature_id: "F-AUTH",
136
+ description: "Implement JWT-based authentication middleware for all API routes.",
137
+ estimate: "M",
138
+ dependencies: ["PROJ-S12-T03"],
139
+ knowledgeUpdates: [{ file: "auth.md", delta: "Added JWT flow" }],
140
+ planIterations: 2,
141
+ codeReviewIterations: 1,
142
+ assignedModel: "claude-opus-4-7",
143
+ pipeline: "standard",
144
+ summaries: {
145
+ plan: {
146
+ objective: "Design JWT middleware architecture",
147
+ written_at: "2026-05-20T10:00:00Z",
148
+ key_changes: ["Created middleware handler", "Updated route config", "Added token validation", "Set up refresh flow"],
149
+ findings: ["Need to handle expired tokens gracefully"],
150
+ verdict: "approved",
151
+ artifact_ref: "PLAN.md",
152
+ },
153
+ review_plan: {
154
+ objective: "Review plan for auth middleware",
155
+ written_at: "2026-05-20T14:00:00Z",
156
+ key_changes: ["Approved with minor suggestions"],
157
+ verdict: "approved",
158
+ },
159
+ implementation: {
160
+ objective: "Implement auth middleware per plan",
161
+ written_at: "2026-05-21T09:00:00Z",
162
+ key_changes: ["Implemented JWT parsing", "Added route guards", "Unit tests passing", "Integration tests added", "Error handling complete"],
163
+ verdict: "approved",
164
+ artifact_ref: "PROGRESS.md",
165
+ },
166
+ },
167
+ },
168
+ null,
169
+ 2,
170
+ );
171
+
172
+ describe("compressEntity", () => {
173
+ it("keeps essential fields", () => {
174
+ const result = compressEntity(SAMPLE_TASK);
175
+ const parsed = JSON.parse(result);
176
+ expect(parsed.taskId).toBe("PROJ-S12-T01");
177
+ expect(parsed.title).toBe("Add auth middleware");
178
+ expect(parsed.status).toBe("implementing");
179
+ expect(parsed.sprintId).toBe("PROJ-S12");
180
+ });
181
+
182
+ it("drops verbose fields by default", () => {
183
+ const result = compressEntity(SAMPLE_TASK);
184
+ const parsed = JSON.parse(result);
185
+ expect(parsed.description).toBeUndefined();
186
+ expect(parsed.knowledgeUpdates).toBeUndefined();
187
+ expect(parsed.assignedModel).toBeUndefined();
188
+ expect(parsed.path).toBeUndefined();
189
+ expect(parsed.planIterations).toBeUndefined();
190
+ });
191
+
192
+ it("keeps only latest summary by default", () => {
193
+ const result = compressEntity(SAMPLE_TASK);
194
+ const parsed = JSON.parse(result);
195
+ expect(parsed.summaries).toBeUndefined();
196
+ expect(parsed.latestPhase).toBe("implementation");
197
+ expect(parsed.latestSummary.objective).toBe("Implement auth middleware per plan");
198
+ expect(parsed.latestSummary.verdict).toBe("approved");
199
+ });
200
+
201
+ it("truncates key_changes in summary", () => {
202
+ const result = compressEntity(SAMPLE_TASK, { maxKeyChanges: 2 });
203
+ const parsed = JSON.parse(result);
204
+ expect(parsed.latestSummary.key_changes).toHaveLength(3);
205
+ expect(parsed.latestSummary.key_changes[2]).toContain("+3 more");
206
+ });
207
+
208
+ it("keeps all summaries when requested", () => {
209
+ const result = compressEntity(SAMPLE_TASK, { keepSummaries: "all" });
210
+ const parsed = JSON.parse(result);
211
+ expect(parsed.summaries).toBeDefined();
212
+ expect(parsed.summaries.plan).toBeDefined();
213
+ expect(parsed.summaries.implementation).toBeDefined();
214
+ });
215
+
216
+ it("produces flat format", () => {
217
+ const result = compressEntity(SAMPLE_TASK, { flatFormat: true });
218
+ expect(result).toContain("taskId: PROJ-S12-T01");
219
+ expect(result).toContain("status: implementing");
220
+ expect(result).not.toContain("{");
221
+ });
222
+
223
+ it("is smaller than input", () => {
224
+ const result = compressEntity(SAMPLE_TASK);
225
+ expect(countTokens(result)).toBeLessThan(countTokens(SAMPLE_TASK) * 0.5);
226
+ });
227
+ });
228
+
229
+ describe("compressEntityList", () => {
230
+ it("compresses array of entities", () => {
231
+ const list = JSON.stringify([JSON.parse(SAMPLE_TASK), JSON.parse(SAMPLE_TASK)], null, 2);
232
+ const result = compressEntityList(list);
233
+ const parsed = JSON.parse(result);
234
+ expect(parsed).toHaveLength(2);
235
+ expect(parsed[0].taskId).toBe("PROJ-S12-T01");
236
+ expect(parsed[0].description).toBeUndefined();
237
+ });
238
+ });
239
+
240
+ // ── markdown compressor ─────────────────────────────────────
241
+
242
+ const SAMPLE_MD = `---
243
+ title: Sprint S12 Progress
244
+ date: 2026-05-25
245
+ ---
246
+
247
+ # Sprint S12: Auth & Rate Limiting
248
+
249
+ ## Overview
250
+ This sprint covers the implementation of JWT authentication
251
+ middleware and fixing the rate limiter under high load.
252
+ There are multiple sub-tasks involved.
253
+
254
+ ## Tasks
255
+
256
+ ### T01: Add auth middleware
257
+ - **Status**: implementing
258
+ - **Estimate**: M
259
+ - Started implementation on May 20th
260
+ - Plan was approved after 2 iterations
261
+ - Currently blocked on upstream API
262
+
263
+ ### T02: Fix rate limiter
264
+ - **Status**: planned
265
+ - **Estimate**: S
266
+ - Root cause identified as connection pool exhaustion
267
+
268
+ ## Risks
269
+ - Upstream API team may not deliver on time
270
+ - Rate limiter fix requires load testing infrastructure
271
+ - JWT library has a known CVE that needs patching
272
+
273
+ ## Timeline
274
+ | Milestone | Date | Status |
275
+ |-----------|------|--------|
276
+ | Plan approval | May 20 | Done |
277
+ | Auth impl | May 25 | In progress |
278
+ | Rate limiter | May 28 | Not started |
279
+ `;
280
+
281
+ describe("compressMarkdown", () => {
282
+ it("map mode keeps headings and key lines", () => {
283
+ const result = compressMarkdown(SAMPLE_MD, { mode: "map" });
284
+ expect(result).toContain("# Sprint S12");
285
+ expect(result).toContain("### T01");
286
+ expect(result).toContain("### T02");
287
+ expect(result).toContain("**Status**");
288
+ expect(result).toContain("body lines omitted");
289
+ expect(countTokens(result)).toBeLessThan(countTokens(SAMPLE_MD) * 0.7);
290
+ });
291
+
292
+ it("headings mode extracts structure only", () => {
293
+ const result = compressMarkdown(SAMPLE_MD, { mode: "headings" });
294
+ expect(result).toContain("Sprint S12");
295
+ expect(result).toContain("T01: Add auth middleware");
296
+ expect(result).toContain("sections");
297
+ expect(result).not.toContain("implementing");
298
+ });
299
+
300
+ it("truncate mode respects token budget", () => {
301
+ const result = compressMarkdown(SAMPLE_MD, { mode: "truncate", maxTokens: 50 });
302
+ expect(countTokens(result)).toBeLessThanOrEqual(60);
303
+ });
304
+
305
+ it("skips frontmatter", () => {
306
+ const result = compressMarkdown(SAMPLE_MD, { mode: "map" });
307
+ expect(result).not.toContain("title: Sprint S12 Progress");
308
+ expect(result).not.toContain("date: 2026");
309
+ });
310
+
311
+ it("handles empty input", () => {
312
+ expect(compressMarkdown("")).toBe("");
313
+ expect(compressMarkdown(" ")).toBe("");
314
+ });
315
+ });
316
+
317
+ // ── validate-store compressor ───────────────────────────────
318
+
319
+ describe("compressValidateStore", () => {
320
+ it("compresses JSON report", () => {
321
+ const report = JSON.stringify({
322
+ ok: false,
323
+ errors: [
324
+ { entity: "task", id: "PROJ-S12-T01", category: "missing-required", field: "title", message: "title is required" },
325
+ { entity: "task", id: "PROJ-S12-T02", category: "missing-required", field: "status", message: "status is required" },
326
+ { entity: "bug", id: "PROJ-B01", category: "orphaned-fk", field: "sprintId", message: "references non-existent sprint" },
327
+ ],
328
+ warnings: [
329
+ { entity: "task", id: "PROJ-S12-T03", category: "stale-path", message: "path does not match filesystem" },
330
+ ],
331
+ fixes: [
332
+ { entity: "task", id: "PROJ-S12-T01", category: "backfill", message: "backfilled path", applied: true },
333
+ ],
334
+ summary: { sprints: 2, tasks: 5, bugs: 1, features: 0, errors: 3, warnings: 1, fixes: 1 },
335
+ });
336
+ const result = compressValidateStore(report);
337
+ expect(result).toContain("missing-required (2)");
338
+ expect(result).toContain("orphaned-fk (1)");
339
+ expect(result).toContain("1 warnings");
340
+ expect(result).toContain("1 fixes (1 applied)");
341
+ expect(countTokens(result)).toBeLessThan(countTokens(report) * 0.6);
342
+ });
343
+
344
+ it("returns ok for valid store", () => {
345
+ const report = JSON.stringify({
346
+ ok: true,
347
+ errors: [],
348
+ warnings: [],
349
+ fixes: [],
350
+ summary: { sprints: 3, tasks: 12, bugs: 2, features: 1, errors: 0, warnings: 0, fixes: 0 },
351
+ });
352
+ const result = compressValidateStore(report);
353
+ expect(result).toContain("3 sprints");
354
+ expect(result).toContain("12 tasks");
355
+ });
356
+
357
+ it("compresses plain text validation output", () => {
358
+ const lines = Array.from({ length: 20 }, (_, i) =>
359
+ `ERROR PROJ-S12-T${String(i).padStart(2, "0")}: missing required field`
360
+ ).join("\n");
361
+ const result = compressValidateStore(lines);
362
+ expect(result).toContain("20 errors");
363
+ expect(result).toContain("... +15 more");
364
+ });
365
+ });
366
+
367
+ // ── core utilities ──────────────────────────────────────────
368
+
369
+ describe("core utilities", () => {
370
+ it("countTokens", () => {
371
+ expect(countTokens("")).toBe(0);
372
+ expect(countTokens("hello world")).toBeGreaterThan(0);
373
+ });
374
+
375
+ it("stripAnsi", () => {
376
+ expect(stripAnsi("\x1b[31mERROR\x1b[0m")).toBe("ERROR");
377
+ expect(stripAnsi("clean")).toBe("clean");
378
+ });
379
+
380
+ it("truncateToTokenBudget", () => {
381
+ const long = "word ".repeat(1000);
382
+ const result = truncateToTokenBudget(long, 50);
383
+ expect(countTokens(result)).toBeLessThanOrEqual(60);
384
+ });
385
+
386
+ it("compressIb preserves high-entropy lines", () => {
387
+ let boring = "aaa bbb aaa bbb\n".repeat(30);
388
+ boring += "unique_identifier_xyz_quartz\n";
389
+ const result = compressIb(boring, 0.15);
390
+ expect(result).toContain("unique_identifier_xyz_quartz");
391
+ });
392
+
393
+ it("compressProgressive respects budget", () => {
394
+ const segs = Array.from({ length: 4 }, (_, i) => `segment ${i} content\n`);
395
+ const out = compressProgressive(segs, 80);
396
+ const total = out.reduce((acc, s) => acc + countTokens(s), 0);
397
+ expect(total).toBeLessThanOrEqual(80);
398
+ });
399
+
400
+ it("lightweightCleanup collapses blanks", () => {
401
+ const result = lightweightCleanup("a\n\n\n\n\nb");
402
+ expect(result.match(/\n/g)?.length ?? 0).toBeLessThanOrEqual(3);
403
+ });
404
+
405
+ it("verbatimCompact deduplicates", () => {
406
+ const result = verbatimCompact("same\n".repeat(20));
407
+ expect(result).toContain("[20x]");
408
+ });
409
+ });