ultimate-pi 0.1.7 → 0.2.2

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 (524) hide show
  1. package/.agents/skills/graphify/.graphify_version +1 -0
  2. package/.agents/skills/graphify/SKILL.md +1204 -0
  3. package/.agents/skills/wiki-autoresearch/SKILL.md +225 -97
  4. package/.agents/skills/wiki-autoresearch/references/program.md +28 -62
  5. package/.agents/skills/wiki-autoresearch/references/quality-sites.md +32 -0
  6. package/.env.example +5 -1
  7. package/.gitattributes +1 -0
  8. package/.github/workflows/publish-github-packages.yml +1 -1
  9. package/.pi/SYSTEM.md +72 -18
  10. package/.pi/agents/harness/adversary.md +32 -0
  11. package/.pi/agents/harness/evaluator.md +32 -0
  12. package/.pi/agents/harness/executor.md +34 -0
  13. package/.pi/agents/harness/meta-optimizer.md +33 -0
  14. package/.pi/agents/harness/planner.md +33 -0
  15. package/.pi/agents/harness/tie-breaker.md +35 -0
  16. package/.pi/agents/harness/trace-librarian.md +32 -0
  17. package/.pi/extensions/banner.png +0 -0
  18. package/.pi/extensions/budget-guard.ts +265 -0
  19. package/.pi/extensions/custom-footer.ts +194 -22
  20. package/.pi/extensions/custom-header.ts +47 -9
  21. package/.pi/extensions/debate-orchestrator.ts +479 -0
  22. package/.pi/extensions/harness-live-widget.ts +438 -0
  23. package/.pi/extensions/policy-gate.ts +349 -0
  24. package/.pi/extensions/review-integrity.ts +198 -0
  25. package/.pi/extensions/test-diff-integrity.ts +240 -0
  26. package/.pi/extensions/trace-recorder.ts +315 -0
  27. package/.pi/harness/README.md +23 -0
  28. package/.pi/harness/router/README.md +35 -0
  29. package/.pi/harness/router/apply-router-proposal.mjs +153 -0
  30. package/.pi/harness/router/propose-router-tuning.mjs +149 -0
  31. package/.pi/harness/specs/README.md +37 -0
  32. package/.pi/harness/specs/adversary-report.schema.json +53 -0
  33. package/.pi/harness/specs/budget-exhausted-event.schema.json +93 -0
  34. package/.pi/harness/specs/consensus-packet.schema.json +175 -0
  35. package/.pi/harness/specs/eval-verdict.schema.json +59 -0
  36. package/.pi/harness/specs/incident-record.schema.json +84 -0
  37. package/.pi/harness/specs/plan-packet.schema.json +90 -0
  38. package/.pi/harness/specs/round-result.schema.json +126 -0
  39. package/.pi/harness/specs/router-tuning-proposal.schema.json +114 -0
  40. package/.pi/harness/specs/run-trace.schema.json +107 -0
  41. package/.pi/lib/harness-ui-state.ts +311 -0
  42. package/.pi/mcp.json +4 -0
  43. package/.pi/model-router.json +93 -93
  44. package/.pi/prompts/graphify.md +23 -0
  45. package/.pi/prompts/harness-abort.md +41 -0
  46. package/.pi/prompts/harness-auto.md +83 -0
  47. package/.pi/prompts/harness-critic.md +52 -0
  48. package/.pi/prompts/harness-eval.md +51 -0
  49. package/.pi/prompts/harness-incident.md +51 -0
  50. package/.pi/prompts/harness-plan.md +64 -0
  51. package/.pi/prompts/harness-review.md +52 -0
  52. package/.pi/prompts/harness-router-tune.md +74 -0
  53. package/.pi/prompts/harness-run.md +59 -0
  54. package/.pi/prompts/harness-setup.md +316 -216
  55. package/.pi/prompts/harness-trace.md +51 -0
  56. package/.pi/prompts/wiki-autoresearch.md +9 -7
  57. package/.pi/prompts/wiki-save.md +20 -0
  58. package/.pi/skills/agent-router/SKILL.md +2 -4
  59. package/.pi/skills/ast-grep/SKILL.md +354 -0
  60. package/.pi/sounds/project-sounds.json +18 -24
  61. package/AGENTS.md +30 -0
  62. package/CHANGELOG.md +89 -0
  63. package/CONTRIBUTING.md +51 -1
  64. package/README.md +264 -20
  65. package/biome.json +8 -2
  66. package/lefthook.yml +3 -2
  67. package/node_modules/@sting8k/pi-vcc/README.md +200 -0
  68. package/node_modules/@sting8k/pi-vcc/index.ts +14 -0
  69. package/node_modules/@sting8k/pi-vcc/package.json +26 -0
  70. package/node_modules/@sting8k/pi-vcc/scripts/audit-sessions.ts +88 -0
  71. package/node_modules/@sting8k/pi-vcc/scripts/benchmark-real-sessions.ts +25 -0
  72. package/node_modules/@sting8k/pi-vcc/scripts/compare-before-after.ts +36 -0
  73. package/node_modules/@sting8k/pi-vcc/scripts/dump-branch-output.ts +20 -0
  74. package/node_modules/@sting8k/pi-vcc/src/commands/pi-vcc.ts +36 -0
  75. package/node_modules/@sting8k/pi-vcc/src/commands/vcc-recall.ts +65 -0
  76. package/node_modules/@sting8k/pi-vcc/src/core/brief.ts +381 -0
  77. package/node_modules/@sting8k/pi-vcc/src/core/build-sections.ts +79 -0
  78. package/node_modules/@sting8k/pi-vcc/src/core/content.ts +60 -0
  79. package/node_modules/@sting8k/pi-vcc/src/core/filter-noise.ts +42 -0
  80. package/node_modules/@sting8k/pi-vcc/src/core/format-recall.ts +27 -0
  81. package/node_modules/@sting8k/pi-vcc/src/core/format.ts +49 -0
  82. package/node_modules/@sting8k/pi-vcc/src/core/lineage.ts +26 -0
  83. package/node_modules/@sting8k/pi-vcc/src/core/load-messages.ts +41 -0
  84. package/node_modules/@sting8k/pi-vcc/src/core/normalize.ts +66 -0
  85. package/node_modules/@sting8k/pi-vcc/src/core/recall-scope.ts +14 -0
  86. package/node_modules/@sting8k/pi-vcc/src/core/render-entries.ts +55 -0
  87. package/node_modules/@sting8k/pi-vcc/src/core/report.ts +237 -0
  88. package/node_modules/@sting8k/pi-vcc/src/core/sanitize.ts +5 -0
  89. package/node_modules/@sting8k/pi-vcc/src/core/search-entries.ts +221 -0
  90. package/node_modules/@sting8k/pi-vcc/src/core/settings.ts +77 -0
  91. package/node_modules/@sting8k/pi-vcc/src/core/skill-collapse.ts +35 -0
  92. package/node_modules/@sting8k/pi-vcc/src/core/summarize.ts +157 -0
  93. package/node_modules/@sting8k/pi-vcc/src/core/tool-args.ts +14 -0
  94. package/node_modules/@sting8k/pi-vcc/src/details.ts +7 -0
  95. package/node_modules/@sting8k/pi-vcc/src/extract/commits.ts +69 -0
  96. package/node_modules/@sting8k/pi-vcc/src/extract/files.ts +80 -0
  97. package/node_modules/@sting8k/pi-vcc/src/extract/goals.ts +79 -0
  98. package/node_modules/@sting8k/pi-vcc/src/extract/preferences.ts +55 -0
  99. package/node_modules/@sting8k/pi-vcc/src/hooks/before-compact.ts +322 -0
  100. package/node_modules/@sting8k/pi-vcc/src/sections.ts +12 -0
  101. package/node_modules/@sting8k/pi-vcc/src/tools/recall.ts +109 -0
  102. package/node_modules/@sting8k/pi-vcc/src/types.ts +14 -0
  103. package/node_modules/@sting8k/pi-vcc/tests/before-compact-hook.test.ts +181 -0
  104. package/node_modules/@sting8k/pi-vcc/tests/before-compact.test.ts +140 -0
  105. package/node_modules/@sting8k/pi-vcc/tests/brief.test.ts +206 -0
  106. package/node_modules/@sting8k/pi-vcc/tests/build-sections.test.ts +59 -0
  107. package/node_modules/@sting8k/pi-vcc/tests/compile.test.ts +80 -0
  108. package/node_modules/@sting8k/pi-vcc/tests/content.test.ts +31 -0
  109. package/node_modules/@sting8k/pi-vcc/tests/extract-goals.test.ts +86 -0
  110. package/node_modules/@sting8k/pi-vcc/tests/extract-preferences.test.ts +30 -0
  111. package/node_modules/@sting8k/pi-vcc/tests/filter-noise.test.ts +61 -0
  112. package/node_modules/@sting8k/pi-vcc/tests/fixtures.ts +61 -0
  113. package/node_modules/@sting8k/pi-vcc/tests/format-recall.test.ts +30 -0
  114. package/node_modules/@sting8k/pi-vcc/tests/format.test.ts +62 -0
  115. package/node_modules/@sting8k/pi-vcc/tests/lineage.test.ts +33 -0
  116. package/node_modules/@sting8k/pi-vcc/tests/load-messages.test.ts +51 -0
  117. package/node_modules/@sting8k/pi-vcc/tests/normalize.test.ts +97 -0
  118. package/node_modules/@sting8k/pi-vcc/tests/real-sessions.test.ts +38 -0
  119. package/node_modules/@sting8k/pi-vcc/tests/recall-expand.test.ts +15 -0
  120. package/node_modules/@sting8k/pi-vcc/tests/recall-scope.test.ts +32 -0
  121. package/node_modules/@sting8k/pi-vcc/tests/recall-tool-scope.test.ts +67 -0
  122. package/node_modules/@sting8k/pi-vcc/tests/render-entries.test.ts +62 -0
  123. package/node_modules/@sting8k/pi-vcc/tests/report.test.ts +44 -0
  124. package/node_modules/@sting8k/pi-vcc/tests/sanitize.test.ts +24 -0
  125. package/node_modules/@sting8k/pi-vcc/tests/search-entries.test.ts +144 -0
  126. package/node_modules/@sting8k/pi-vcc/tests/support/load-session.ts +23 -0
  127. package/node_modules/@sting8k/pi-vcc/tests/support/real-sessions.ts +51 -0
  128. package/package.json +15 -4
  129. package/scripts/__pycache__/merge_graphify_corpora.cpython-314.pyc +0 -0
  130. package/scripts/index_youtube_urls.py +376 -0
  131. package/scripts/merge_graphify_corpora.py +398 -0
  132. package/scripts/regen_graphify_html.py +46 -0
  133. package/.agents/skills/defuddle/SKILL.md +0 -90
  134. package/.agents/skills/wiki/SKILL.md +0 -215
  135. package/.agents/skills/wiki/references/css-snippets.md +0 -122
  136. package/.agents/skills/wiki/references/frontmatter.md +0 -107
  137. package/.agents/skills/wiki/references/git-setup.md +0 -58
  138. package/.agents/skills/wiki/references/mcp-setup.md +0 -149
  139. package/.agents/skills/wiki/references/modes.md +0 -259
  140. package/.agents/skills/wiki/references/plugins.md +0 -96
  141. package/.agents/skills/wiki/references/rest-api.md +0 -124
  142. package/.agents/skills/wiki-fold/SKILL.md +0 -204
  143. package/.agents/skills/wiki-fold/references/fold-template.md +0 -133
  144. package/.agents/skills/wiki-ingest/SKILL.md +0 -288
  145. package/.agents/skills/wiki-lint/SKILL.md +0 -183
  146. package/.agents/skills/wiki-query/SKILL.md +0 -176
  147. package/.pi/agents/rethink.md +0 -140
  148. package/.pi/agents/wiki-ingest.md +0 -67
  149. package/.pi/agents/wiki-lint.md +0 -75
  150. package/.pi/internal/cursor-sdk-transcript-parser.ts +0 -59
  151. package/.pi/prompts/save.md +0 -16
  152. package/.pi/prompts/wiki.md +0 -23
  153. package/.pi/providers/cursor-sdk-provider.test.mjs +0 -476
  154. package/.pi/providers/cursor-sdk-provider.ts +0 -1085
  155. package/vault/AGENTS.md +0 -37
  156. package/vault/wiki/_templates/comparison.md +0 -39
  157. package/vault/wiki/_templates/concept.md +0 -40
  158. package/vault/wiki/_templates/decision.md +0 -21
  159. package/vault/wiki/_templates/entity.md +0 -32
  160. package/vault/wiki/_templates/flow.md +0 -14
  161. package/vault/wiki/_templates/module.md +0 -18
  162. package/vault/wiki/_templates/question.md +0 -31
  163. package/vault/wiki/_templates/source.md +0 -39
  164. package/vault/wiki/concepts/AST-Aware Code Chunking.md +0 -44
  165. package/vault/wiki/concepts/Build-Time Prompt Compilation.md +0 -107
  166. package/vault/wiki/concepts/Context Engine (AI Coding).md +0 -47
  167. package/vault/wiki/concepts/Context-Aware System Reminders.md +0 -61
  168. package/vault/wiki/concepts/Contextualized Text Embedding.md +0 -42
  169. package/vault/wiki/concepts/Contractor vs Employee AI Model.md +0 -55
  170. package/vault/wiki/concepts/Dual-Model Agent Architecture.md +0 -65
  171. package/vault/wiki/concepts/Late Chunking vs Early Chunking.md +0 -43
  172. package/vault/wiki/concepts/Majority Vote Ensembling.md +0 -68
  173. package/vault/wiki/concepts/Meta-Harness.md +0 -16
  174. package/vault/wiki/concepts/Multi-Agent AI Coding Architecture.md +0 -75
  175. package/vault/wiki/concepts/Prompt Enhancement.md +0 -90
  176. package/vault/wiki/concepts/Prompt Renderer.md +0 -89
  177. package/vault/wiki/concepts/Semantic Codebase Indexing.md +0 -67
  178. package/vault/wiki/concepts/additive-config-hierarchy.md +0 -16
  179. package/vault/wiki/concepts/agent-artifacts-verifiable-deliverables.md +0 -71
  180. package/vault/wiki/concepts/agent-browser-browser-automation.md +0 -99
  181. package/vault/wiki/concepts/agent-codebase-interface.md +0 -43
  182. package/vault/wiki/concepts/agent-harness-architecture.md +0 -67
  183. package/vault/wiki/concepts/agent-loop-detection-patterns.md +0 -133
  184. package/vault/wiki/concepts/agent-search-enforcement.md +0 -126
  185. package/vault/wiki/concepts/agent-skills-ecosystem.md +0 -74
  186. package/vault/wiki/concepts/agent-skills-pattern.md +0 -68
  187. package/vault/wiki/concepts/agentic-harness-context-enforcement.md +0 -91
  188. package/vault/wiki/concepts/agentic-harness.md +0 -34
  189. package/vault/wiki/concepts/agentic-orchestration-pipeline.md +0 -56
  190. package/vault/wiki/concepts/agentic-search-no-embeddings.md +0 -18
  191. package/vault/wiki/concepts/anthropic-context-engineering.md +0 -13
  192. package/vault/wiki/concepts/antigravity-agent-first-architecture.md +0 -61
  193. package/vault/wiki/concepts/ast-compression.md +0 -19
  194. package/vault/wiki/concepts/ast-truncation.md +0 -66
  195. package/vault/wiki/concepts/barrel-files.md +0 -37
  196. package/vault/wiki/concepts/browser-harness-agent.md +0 -41
  197. package/vault/wiki/concepts/browser-subagent-visual-verification.md +0 -82
  198. package/vault/wiki/concepts/codebase-intelligence-ecosystem-comparison.md +0 -192
  199. package/vault/wiki/concepts/codebase-intelligence-harness-integration.md +0 -161
  200. package/vault/wiki/concepts/codebase-to-context-ingestion.md +0 -46
  201. package/vault/wiki/concepts/codex-harness-innovations.md +0 -147
  202. package/vault/wiki/concepts/consensus-debate-flow.md +0 -17
  203. package/vault/wiki/concepts/consensus-debate.md +0 -206
  204. package/vault/wiki/concepts/content-addressed-spec-identity.md +0 -166
  205. package/vault/wiki/concepts/context-anxiety.md +0 -57
  206. package/vault/wiki/concepts/context-compression-techniques.md +0 -19
  207. package/vault/wiki/concepts/context-continuity.md +0 -22
  208. package/vault/wiki/concepts/context-drift-in-agents.md +0 -106
  209. package/vault/wiki/concepts/context-engineering.md +0 -62
  210. package/vault/wiki/concepts/context-folding.md +0 -67
  211. package/vault/wiki/concepts/context-mode.md +0 -38
  212. package/vault/wiki/concepts/cursor-harness-innovations.md +0 -107
  213. package/vault/wiki/concepts/deterministic-session-compaction.md +0 -79
  214. package/vault/wiki/concepts/drift-detection-unified.md +0 -296
  215. package/vault/wiki/concepts/execution-feedback-loop.md +0 -46
  216. package/vault/wiki/concepts/feedforward-feedback-harness.md +0 -60
  217. package/vault/wiki/concepts/five-root-cause-metrics-sentrux.md +0 -40
  218. package/vault/wiki/concepts/fork-safe-spec-storage.md +0 -89
  219. package/vault/wiki/concepts/fts5-sandbox.md +0 -19
  220. package/vault/wiki/concepts/fuzzy-edit-matching.md +0 -71
  221. package/vault/wiki/concepts/gemini-cli-architecture.md +0 -104
  222. package/vault/wiki/concepts/generator-evaluator-architecture.md +0 -64
  223. package/vault/wiki/concepts/guardian-agent-pattern.md +0 -67
  224. package/vault/wiki/concepts/harness-configuration-layers.md +0 -89
  225. package/vault/wiki/concepts/harness-control-frameworks.md +0 -155
  226. package/vault/wiki/concepts/harness-engineering-first-principles.md +0 -90
  227. package/vault/wiki/concepts/harness-h-formalism.md +0 -53
  228. package/vault/wiki/concepts/hybrid-code-search.md +0 -61
  229. package/vault/wiki/concepts/inline-post-edit-validation.md +0 -112
  230. package/vault/wiki/concepts/legendary-engineering-patterns-harness.md +0 -110
  231. package/vault/wiki/concepts/lifecycle-hooks.md +0 -94
  232. package/vault/wiki/concepts/mcp-tool-routing.md +0 -102
  233. package/vault/wiki/concepts/memory-system-of-record-vs-ephemeral-cache.md +0 -47
  234. package/vault/wiki/concepts/meta-agent-context-pruning.md +0 -151
  235. package/vault/wiki/concepts/model-adaptive-harness.md +0 -122
  236. package/vault/wiki/concepts/model-routing-agents.md +0 -101
  237. package/vault/wiki/concepts/monorepo-architecture.md +0 -45
  238. package/vault/wiki/concepts/multi-agent-specialization.md +0 -61
  239. package/vault/wiki/concepts/permission-subsystem.md +0 -16
  240. package/vault/wiki/concepts/pi-messenger-analysis.md +0 -243
  241. package/vault/wiki/concepts/pi-vscode-extension-landscape.md +0 -37
  242. package/vault/wiki/concepts/policy-engine-pattern.md +0 -78
  243. package/vault/wiki/concepts/progressive-disclosure-agents.md +0 -53
  244. package/vault/wiki/concepts/progressive-skill-disclosure.md +0 -17
  245. package/vault/wiki/concepts/provider-native-prompting.md +0 -203
  246. package/vault/wiki/concepts/quality-signal-sentrux.md +0 -37
  247. package/vault/wiki/concepts/repo-map-ranking.md +0 -42
  248. package/vault/wiki/concepts/result-monad-error-handling.md +0 -47
  249. package/vault/wiki/concepts/safety-defense-in-depth.md +0 -83
  250. package/vault/wiki/concepts/sandbox-os-enforcement.md +0 -18
  251. package/vault/wiki/concepts/selective-debate-routing.md +0 -70
  252. package/vault/wiki/concepts/self-evolving-harness.md +0 -60
  253. package/vault/wiki/concepts/sentrux-mcp-integration.md +0 -36
  254. package/vault/wiki/concepts/sentrux-rules-engine.md +0 -49
  255. package/vault/wiki/concepts/shell-pattern-compression.md +0 -24
  256. package/vault/wiki/concepts/skill-first-architecture.md +0 -166
  257. package/vault/wiki/concepts/structured-compaction.md +0 -78
  258. package/vault/wiki/concepts/subagent-orchestration.md +0 -17
  259. package/vault/wiki/concepts/subagent-worktree-isolation.md +0 -68
  260. package/vault/wiki/concepts/superpowers-methodology.md +0 -78
  261. package/vault/wiki/concepts/think-in-code.md +0 -73
  262. package/vault/wiki/concepts/ts-execution-layer.md +0 -100
  263. package/vault/wiki/concepts/typescript-strict-mode.md +0 -37
  264. package/vault/wiki/concepts/vcc-conversation-compaction-for-pi.md +0 -53
  265. package/vault/wiki/concepts/verification-drift-detection.md +0 -19
  266. package/vault/wiki/consensus/consensus-records.md +0 -58
  267. package/vault/wiki/decisions/2026-04-30-pi-lean-ctx-native.md +0 -122
  268. package/vault/wiki/decisions/2026-05-07-replace-lean-ctx-with-context-mode.md +0 -59
  269. package/vault/wiki/decisions/adr-008.md +0 -40
  270. package/vault/wiki/decisions/adr-009.md +0 -46
  271. package/vault/wiki/decisions/adr-010.md +0 -55
  272. package/vault/wiki/decisions/adr-011.md +0 -165
  273. package/vault/wiki/decisions/adr-012.md +0 -102
  274. package/vault/wiki/decisions/adr-013.md +0 -59
  275. package/vault/wiki/decisions/adr-014.md +0 -73
  276. package/vault/wiki/decisions/adr-015.md +0 -81
  277. package/vault/wiki/decisions/adr-016.md +0 -91
  278. package/vault/wiki/decisions/adr-017.md +0 -79
  279. package/vault/wiki/decisions/adr-018.md +0 -100
  280. package/vault/wiki/decisions/adr-019.md +0 -75
  281. package/vault/wiki/decisions/adr-020.md +0 -106
  282. package/vault/wiki/decisions/adr-021.md +0 -86
  283. package/vault/wiki/decisions/adr-022.md +0 -113
  284. package/vault/wiki/decisions/adr-023.md +0 -113
  285. package/vault/wiki/decisions/adr-024.md +0 -73
  286. package/vault/wiki/decisions/adr-025.md +0 -130
  287. package/vault/wiki/decisions/adr-026.md +0 -56
  288. package/vault/wiki/decisions/adr-027.md +0 -94
  289. package/vault/wiki/decisions/colocate-wiki.md +0 -34
  290. package/vault/wiki/entities/Anders Hejlsberg.md +0 -29
  291. package/vault/wiki/entities/Anthropic.md +0 -17
  292. package/vault/wiki/entities/Augment Code.md +0 -49
  293. package/vault/wiki/entities/Bjarne Stroustrup.md +0 -26
  294. package/vault/wiki/entities/Bolt.new (StackBlitz).md +0 -39
  295. package/vault/wiki/entities/Boris Cherny.md +0 -11
  296. package/vault/wiki/entities/Claude Code.md +0 -19
  297. package/vault/wiki/entities/Dennis Ritchie.md +0 -26
  298. package/vault/wiki/entities/Emergent Labs.md +0 -32
  299. package/vault/wiki/entities/Google Cloud.md +0 -16
  300. package/vault/wiki/entities/Guido van Rossum.md +0 -28
  301. package/vault/wiki/entities/Ken Thompson.md +0 -28
  302. package/vault/wiki/entities/Lee et al.md +0 -16
  303. package/vault/wiki/entities/Linus Torvalds.md +0 -28
  304. package/vault/wiki/entities/Lovable (company).md +0 -40
  305. package/vault/wiki/entities/Martin Fowler.md +0 -16
  306. package/vault/wiki/entities/Meng et al.md +0 -16
  307. package/vault/wiki/entities/OpenAI.md +0 -16
  308. package/vault/wiki/entities/Rocket.new.md +0 -38
  309. package/vault/wiki/entities/VILA-Lab.md +0 -15
  310. package/vault/wiki/entities/autodev-codebase.md +0 -18
  311. package/vault/wiki/entities/ck-tool.md +0 -59
  312. package/vault/wiki/entities/codesearch.md +0 -18
  313. package/vault/wiki/entities/disler-indydevdan.md +0 -33
  314. package/vault/wiki/entities/gsd-get-shit-done.md +0 -56
  315. package/vault/wiki/entities/javascript-runtimes.md +0 -48
  316. package/vault/wiki/entities/jesse-vincent.md +0 -38
  317. package/vault/wiki/entities/lean-ctx.md +0 -32
  318. package/vault/wiki/entities/opendev.md +0 -41
  319. package/vault/wiki/entities/ops-codegraph-tool.md +0 -18
  320. package/vault/wiki/entities/pi-coding-agent.md +0 -53
  321. package/vault/wiki/entities/sentrux.md +0 -54
  322. package/vault/wiki/entities/vgrep-tool.md +0 -57
  323. package/vault/wiki/entities/vitest.md +0 -41
  324. package/vault/wiki/flows/harness-wiki-pipeline.md +0 -204
  325. package/vault/wiki/hot.md +0 -932
  326. package/vault/wiki/index.md +0 -437
  327. package/vault/wiki/log.md +0 -422
  328. package/vault/wiki/meta/dashboard.md +0 -30
  329. package/vault/wiki/meta/lint-report-2026-04-30.md +0 -86
  330. package/vault/wiki/meta/lint-report-2026-05-02.md +0 -251
  331. package/vault/wiki/meta/overview.canvas +0 -43
  332. package/vault/wiki/modules/adversarial-verification.md +0 -57
  333. package/vault/wiki/modules/automated-observability.md +0 -54
  334. package/vault/wiki/modules/bench.md +0 -20
  335. package/vault/wiki/modules/extensions.md +0 -23
  336. package/vault/wiki/modules/grounding-checkpoints.md +0 -62
  337. package/vault/wiki/modules/harness-implementation-plan.md +0 -345
  338. package/vault/wiki/modules/harness-wiki-skill-mapping.md +0 -135
  339. package/vault/wiki/modules/harness.md +0 -86
  340. package/vault/wiki/modules/persistent-memory.md +0 -85
  341. package/vault/wiki/modules/schema-orchestration.md +0 -68
  342. package/vault/wiki/modules/skills.md +0 -27
  343. package/vault/wiki/modules/spec-hardening.md +0 -58
  344. package/vault/wiki/modules/structured-planning.md +0 -53
  345. package/vault/wiki/modules/think-in-code-enforcement.md +0 -153
  346. package/vault/wiki/modules/wiki-query-interface.md +0 -64
  347. package/vault/wiki/overview.md +0 -51
  348. package/vault/wiki/questions/Research-pi-vs-claude-code-agentic-orchestration-pipeline.md +0 -87
  349. package/vault/wiki/questions/Research-sentrux-dev.md +0 -123
  350. package/vault/wiki/questions/Research-superpowers-skill-for-agentic-coding-agents.md +0 -164
  351. package/vault/wiki/questions/Research: Augment Code Context Engine.md +0 -244
  352. package/vault/wiki/questions/Research: Automating Software Engineering - Lovable, Bolt, Emergent, Rocket.md +0 -112
  353. package/vault/wiki/questions/Research: Claude Code State-of-the-Art Harness Improvements.md +0 -209
  354. package/vault/wiki/questions/Research: Codex State-of-the-Art Harness Improvements.md +0 -99
  355. package/vault/wiki/questions/Research: Engineering Workflows of Legendary Programmers and AI Harness Mapping.md +0 -107
  356. package/vault/wiki/questions/Research: Fallow Codebase Intelligence Harness Integration.md +0 -72
  357. package/vault/wiki/questions/Research: Gemini CLI SOTA Harness Integration.md +0 -166
  358. package/vault/wiki/questions/Research: GitHub Issues as Harness Spec Storage.md +0 -188
  359. package/vault/wiki/questions/Research: Google Antigravity Harness Integration.md +0 -120
  360. package/vault/wiki/questions/Research: Meta-Agent Context Drift Detection.md +0 -236
  361. package/vault/wiki/questions/Research: Model-Adaptive Agent Harness Design.md +0 -95
  362. package/vault/wiki/questions/Research: Model-Specific Prompting Guides.md +0 -165
  363. package/vault/wiki/questions/Research: Prompt Renderer for Multi-Model Agent Harness.md +0 -216
  364. package/vault/wiki/questions/Research: Skill-First Harness Architecture.md +0 -91
  365. package/vault/wiki/questions/Research: TypeScript Best Practices and Codebase Structure.md +0 -88
  366. package/vault/wiki/questions/Research: TypeScript Execution Layer for Agent Tool Calling.md +0 -81
  367. package/vault/wiki/questions/Research: claude-mem over Obsidian for Harness Layer.md +0 -71
  368. package/vault/wiki/questions/Research: claude-mem over obsidian wiki as the knowledge base for our agentic harness pipeline. think from first principles. does this replace or complement our current setup? no hard feelings about previous decisions. gimme accurate points.md +0 -80
  369. package/vault/wiki/questions/Research: context-mode vs lean-ctx.md +0 -72
  370. package/vault/wiki/questions/Research: cursor.sh Harness Innovations.md +0 -92
  371. package/vault/wiki/questions/Research: executor.sh Harness Integration.md +0 -170
  372. package/vault/wiki/questions/Research: how GSD fits into our coding harness setup.md +0 -97
  373. package/vault/wiki/questions/Research: how claude-mem fits into our workflow. and whether it should replace obsidian in the codebase. no hard feelings about previous actions, rethink from first principles always.md +0 -80
  374. package/vault/wiki/questions/Research: pi-vcc.md +0 -113
  375. package/vault/wiki/questions/Research: semantic code search tools.md +0 -69
  376. package/vault/wiki/questions/Research: vcc extension for pi coding agent.md +0 -73
  377. package/vault/wiki/questions/how-to-enable-semantic-code-search-now.md +0 -111
  378. package/vault/wiki/questions/mvp-implementation-blueprint.md +0 -552
  379. package/vault/wiki/questions/research-agent-first-codebase-exploration.md +0 -199
  380. package/vault/wiki/questions/research-agentic-coding-harness-latest-papers.md +0 -142
  381. package/vault/wiki/questions/research-gitingest-gitreverse-integration.md +0 -100
  382. package/vault/wiki/questions/research-wozcode-token-reduction.md +0 -67
  383. package/vault/wiki/questions/resolved-context-pruning-inplace-vs-restart.md +0 -95
  384. package/vault/wiki/questions/resolved-context-window-economics.md +0 -167
  385. package/vault/wiki/questions/resolved-imad-debate-gating-transfer.md +0 -126
  386. package/vault/wiki/questions/resolved-mcp-tool-preference.md +0 -112
  387. package/vault/wiki/questions/resolved-small-model-meta-agents.md +0 -107
  388. package/vault/wiki/questions/resolved-treesitter-dynamic-languages.md +0 -95
  389. package/vault/wiki/sources/Auggie Context MCP Server.md +0 -63
  390. package/vault/wiki/sources/Augment Code Codacy AI Giants.md +0 -61
  391. package/vault/wiki/sources/Augment Code MCP SiliconAngle.md +0 -49
  392. package/vault/wiki/sources/Augment Code WorkOS ERC 2025.md +0 -55
  393. package/vault/wiki/sources/Augment Context Engine Official.md +0 -71
  394. package/vault/wiki/sources/Augment SWE-bench Agent GitHub.md +0 -74
  395. package/vault/wiki/sources/Augment SWE-bench Pro Blog.md +0 -58
  396. package/vault/wiki/sources/Source: AgentBus Jinja2 Prompt Pipelines.md +0 -75
  397. package/vault/wiki/sources/Source: Arxiv /342/200/224 Don't Break the Cache.md" +0 -85
  398. package/vault/wiki/sources/Source: Augment - Harness Engineering for AI Coding Agents.md +0 -58
  399. package/vault/wiki/sources/Source: Blake Crosley Agent Architecture Guide.md +0 -100
  400. package/vault/wiki/sources/Source: Bolt.new Architecture & Case Study.md +0 -75
  401. package/vault/wiki/sources/Source: Build-Time Prompt Compilation Architecture.md +0 -107
  402. package/vault/wiki/sources/Source: Claude API Agent Skills Overview.md +0 -70
  403. package/vault/wiki/sources/Source: Gemini CLI Changelogs.md +0 -88
  404. package/vault/wiki/sources/Source: Google Blog - Gemini CLI Announcement.md +0 -57
  405. package/vault/wiki/sources/Source: Google Gemini CLI Architecture Docs.md +0 -53
  406. package/vault/wiki/sources/Source: LangChain - Anatomy of Agent Harness.md +0 -65
  407. package/vault/wiki/sources/Source: Lovable Architecture & Clone Analysis.md +0 -83
  408. package/vault/wiki/sources/Source: Martin Fowler - Harness Engineering.md +0 -70
  409. package/vault/wiki/sources/Source: OpenAI Harness Engineering Five Principles.md +0 -58
  410. package/vault/wiki/sources/Source: OpenAI Harness Engineering /342/200/224 0 Lines of Human Code.md" +0 -101
  411. package/vault/wiki/sources/Source: OpenDev /342/200/224 Building AI Coding Agents for the Terminal.md" +0 -100
  412. package/vault/wiki/sources/Source: Render AI Coding Agents Benchmark 2025.md +0 -53
  413. package/vault/wiki/sources/Source: Rocket.new /342/200/224 Vibe Solutioning Platform.md" +0 -70
  414. package/vault/wiki/sources/Source: SwirlAI Agent Skills Progressive Disclosure.md +0 -71
  415. package/vault/wiki/sources/Source: TianPan Prompt Caching Architecture.md +0 -89
  416. package/vault/wiki/sources/Source: Vercel Labs agent-browser.md +0 -155
  417. package/vault/wiki/sources/Source: browser-harness CDP Harness.md +0 -126
  418. package/vault/wiki/sources/agent-drift-academic-paper.md +0 -79
  419. package/vault/wiki/sources/aider-repomap-tree-sitter.md +0 -42
  420. package/vault/wiki/sources/anthropic-compaction-api.md +0 -58
  421. package/vault/wiki/sources/anthropic-effective-harnesses.md +0 -42
  422. package/vault/wiki/sources/anthropic-prompt-best-practices.md +0 -100
  423. package/vault/wiki/sources/anthropic2026-harness-design.md +0 -63
  424. package/vault/wiki/sources/barrel-files-tkdodo.md +0 -38
  425. package/vault/wiki/sources/birth-of-unix-kernighan-interview.md +0 -57
  426. package/vault/wiki/sources/bockeler2026-harness-engineering.md +0 -69
  427. package/vault/wiki/sources/cast-code-chunking-paper.md +0 -50
  428. package/vault/wiki/sources/ck-semantic-search.md +0 -78
  429. package/vault/wiki/sources/claude-code-architecture-karaxai-2026.md +0 -71
  430. package/vault/wiki/sources/claude-code-architecture-qubytes-2026.md +0 -50
  431. package/vault/wiki/sources/claude-code-architecture-vila-lab-2026.md +0 -64
  432. package/vault/wiki/sources/claude-code-security-architecture-penligent-2026.md +0 -70
  433. package/vault/wiki/sources/claude-context-editing-docs.md +0 -13
  434. package/vault/wiki/sources/cloudflare-codemode.md +0 -63
  435. package/vault/wiki/sources/code-chunk-library-supermemory.md +0 -63
  436. package/vault/wiki/sources/codeact-apple-2024.md +0 -62
  437. package/vault/wiki/sources/codex-dsc-rfc-8573.md +0 -41
  438. package/vault/wiki/sources/codex-open-source-agent-2026.md +0 -110
  439. package/vault/wiki/sources/coir-code-retrieval-benchmark.md +0 -51
  440. package/vault/wiki/sources/colinmcnamara-context-optimization-codemode.md +0 -48
  441. package/vault/wiki/sources/context-folding-paper.md +0 -61
  442. package/vault/wiki/sources/context-mode-website.md +0 -63
  443. package/vault/wiki/sources/cursor-agent-best-practices-2026.md +0 -62
  444. package/vault/wiki/sources/cursor-fork-29b-2025.md +0 -50
  445. package/vault/wiki/sources/cursor-harness-april-2026.md +0 -76
  446. package/vault/wiki/sources/cursor-instant-apply-2024.md +0 -45
  447. package/vault/wiki/sources/cursor-shadow-workspace-2024.md +0 -52
  448. package/vault/wiki/sources/cursor-shipped-coding-agent-2026.md +0 -53
  449. package/vault/wiki/sources/cursor-vs-antigravity-2026.md +0 -51
  450. package/vault/wiki/sources/disler-pi-vs-claude-code.md +0 -69
  451. package/vault/wiki/sources/distill-deterministic-context-compression.md +0 -53
  452. package/vault/wiki/sources/embedding-models-benchmark-supermemory-2025.md +0 -48
  453. package/vault/wiki/sources/executor-rhyssullivan.md +0 -122
  454. package/vault/wiki/sources/fallow-rs-codebase-intelligence.md +0 -125
  455. package/vault/wiki/sources/fan2025-imad.md +0 -60
  456. package/vault/wiki/sources/forgecode-gpt5-agent-improvements.md +0 -63
  457. package/vault/wiki/sources/gemini-3-prompting-guide.md +0 -78
  458. package/vault/wiki/sources/gh-cli-sub-issue-rfc.md +0 -50
  459. package/vault/wiki/sources/gh-sub-issue-extension.md +0 -72
  460. package/vault/wiki/sources/github-fork-issues-discussion.md +0 -44
  461. package/vault/wiki/sources/github-issue-dependencies-docs.md +0 -49
  462. package/vault/wiki/sources/github-sub-issues-docs.md +0 -51
  463. package/vault/wiki/sources/gitingest.md +0 -91
  464. package/vault/wiki/sources/gitreverse.md +0 -63
  465. package/vault/wiki/sources/google-antigravity-official-blog.md +0 -47
  466. package/vault/wiki/sources/google-antigravity-wikipedia.md +0 -53
  467. package/vault/wiki/sources/gsd-codecentric-deep-dive.md +0 -57
  468. package/vault/wiki/sources/gsd-github-repo.md +0 -51
  469. package/vault/wiki/sources/gsd-hn-discussion.md +0 -59
  470. package/vault/wiki/sources/guido-python-design-philosophy.md +0 -56
  471. package/vault/wiki/sources/hejlsberg-7-learnings.md +0 -48
  472. package/vault/wiki/sources/ironclaw-drift-monitor.md +0 -80
  473. package/vault/wiki/sources/langsight-loop-detection.md +0 -80
  474. package/vault/wiki/sources/leanctx-website.md +0 -69
  475. package/vault/wiki/sources/lee2026-meta-harness.md +0 -59
  476. package/vault/wiki/sources/linux-kernel-coding-workflow.md +0 -50
  477. package/vault/wiki/sources/lou2026-autoharness.md +0 -53
  478. package/vault/wiki/sources/martin-fowler-harness-engineering.md +0 -73
  479. package/vault/wiki/sources/mcp-architecture-docs.md +0 -13
  480. package/vault/wiki/sources/meng2026-agent-harness-survey.md +0 -79
  481. package/vault/wiki/sources/mindstudio-four-agent-types.md +0 -68
  482. package/vault/wiki/sources/ms-chat-history-management.md +0 -13
  483. package/vault/wiki/sources/openai-prompt-guidance.md +0 -104
  484. package/vault/wiki/sources/openclaw-session-pruning.md +0 -13
  485. package/vault/wiki/sources/opencode-dcp.md +0 -13
  486. package/vault/wiki/sources/opendev-arxiv-2603.05344v1.md +0 -79
  487. package/vault/wiki/sources/openhands-platform.md +0 -39
  488. package/vault/wiki/sources/oss-guide-codebase-exploration.md +0 -53
  489. package/vault/wiki/sources/pi-compaction-extensions-ecosystem.md +0 -102
  490. package/vault/wiki/sources/pi-context-prune-github-repo.md +0 -38
  491. package/vault/wiki/sources/pi-mono-compaction-docs.md +0 -38
  492. package/vault/wiki/sources/pi-omni-compact-github-repo.md +0 -50
  493. package/vault/wiki/sources/pi-rtk-optimizer-github-repo.md +0 -45
  494. package/vault/wiki/sources/pi-vcc-github-repo.md +0 -69
  495. package/vault/wiki/sources/pi-vscode-marketplace.md +0 -41
  496. package/vault/wiki/sources/pi-vscode-model-provider-marketplace.md +0 -39
  497. package/vault/wiki/sources/py-tree-sitter.md +0 -13
  498. package/vault/wiki/sources/sentrux-dev-landing.md +0 -40
  499. package/vault/wiki/sources/sentrux-docs-pro-architecture.md +0 -75
  500. package/vault/wiki/sources/sentrux-docs-quality-signal.md +0 -46
  501. package/vault/wiki/sources/sentrux-docs-root-cause-metrics.md +0 -57
  502. package/vault/wiki/sources/sentrux-docs-rules-engine.md +0 -58
  503. package/vault/wiki/sources/sentrux-github-repo.md +0 -56
  504. package/vault/wiki/sources/superpowers-github-repo.md +0 -56
  505. package/vault/wiki/sources/superpowers-release-blog.md +0 -54
  506. package/vault/wiki/sources/superpowers-termdock-analysis.md +0 -45
  507. package/vault/wiki/sources/swe-agent-aci.md +0 -42
  508. package/vault/wiki/sources/swe-bench.md +0 -45
  509. package/vault/wiki/sources/swe-pruner-context-pruning.md +0 -13
  510. package/vault/wiki/sources/think-in-code-blog.md +0 -48
  511. package/vault/wiki/sources/tree-sitter-docs.md +0 -13
  512. package/vault/wiki/sources/ts-best-practices-2025-devto.md +0 -42
  513. package/vault/wiki/sources/ts-folder-structure-mingyang.md +0 -58
  514. package/vault/wiki/sources/ts-monorepo-koerselman.md +0 -44
  515. package/vault/wiki/sources/ts-result-error-handling-kkalamarski.md +0 -52
  516. package/vault/wiki/sources/ts-runtimes-comparison-betterstack.md +0 -42
  517. package/vault/wiki/sources/ts-strict-mode-rishikc.md +0 -43
  518. package/vault/wiki/sources/unix-philosophy.md +0 -48
  519. package/vault/wiki/sources/vectara-chunking-vs-embedding-naacl2025.md +0 -39
  520. package/vault/wiki/sources/vectara-guardian-agents.md +0 -79
  521. package/vault/wiki/sources/vgrep-semantic-search.md +0 -76
  522. package/vault/wiki/sources/vitest-official.md +0 -41
  523. package/vault/wiki/sources/vscode-pi-community-extension.md +0 -40
  524. package/vault/wiki/sources/wozcode.md +0 -79
@@ -0,0 +1,88 @@
1
+ import { basename, dirname } from "node:path";
2
+ import { compile } from "../src/core/summarize";
3
+ import { normalize } from "../src/core/normalize";
4
+ import { filterNoise } from "../src/core/filter-noise";
5
+ import { renderMessage } from "../src/core/render-entries";
6
+ import { prepareSessionSamples } from "../tests/support/real-sessions";
7
+ import { loadSessionMessages } from "../tests/support/load-session";
8
+
9
+ const SEP = "=".repeat(80);
10
+ const samples = await prepareSessionSamples(10);
11
+
12
+ for (const sample of samples) {
13
+ const loaded = loadSessionMessages(sample.copy);
14
+ const { messages } = loaded;
15
+
16
+ const rawBlocks = normalize(messages);
17
+ const filteredBlocks = filterNoise(rawBlocks);
18
+ const afterText = compile({ messages });
19
+
20
+ const rendered = messages.map((m, i) => renderMessage(m, i));
21
+ const beforeChars = rendered.reduce((s, e) => s + e.summary.length, 0);
22
+
23
+ const project = dirname(sample.source).split("--").filter(Boolean).pop() ?? "unknown";
24
+
25
+ const goalSection = afterText.match(/\[Session Goal\]\n([\s\S]*?)(?=\n\n\[|$)/)?.[1] ?? "(empty)";
26
+ const stateSection = afterText.match(/\[Current State\]\n([\s\S]*?)(?=\n\n\[|$)/)?.[1] ?? "(empty)";
27
+ const doneSection = afterText.match(/\[What Was Done\]\n([\s\S]*?)(?=\n\n\[|$)/)?.[1] ?? "(empty)";
28
+ const problemsSection = afterText.match(/\[Open Problems\]\n([\s\S]*?)(?=\n\n\[|$)/)?.[1] ?? "(empty)";
29
+ const nextSection = afterText.match(/\[Next Best Steps\]\n([\s\S]*?)(?=\n\n\[|$)/)?.[1] ?? "(empty)";
30
+
31
+ const doneLines = doneSection.split("\n").filter(l => l.trim());
32
+ const problemLines = problemsSection.split("\n").filter(l => l.trim());
33
+
34
+ // Detect issues
35
+ const issues: string[] = [];
36
+
37
+ // 1. Goal quality
38
+ const goalLines = goalSection.split("\n").map(l => l.replace(/^- /, "").trim()).filter(Boolean);
39
+ if (goalLines[0] && goalLines[0].length < 5) issues.push(`GOAL_TOO_SHORT: "${goalLines[0]}"`);
40
+ if (goalLines.length === 0) issues.push("GOAL_EMPTY");
41
+
42
+ // 2. Sensitive data in What Was Done
43
+ if (/sshpass|password|secret|token=|api[_-]?key/i.test(doneSection)) {
44
+ issues.push("SENSITIVE_DATA_IN_DONE");
45
+ }
46
+
47
+ // 3. Raw code/minified JS in summary
48
+ if (/\{[a-zA-Z$_]+:[a-zA-Z$_]+,[a-zA-Z$_]+:/.test(afterText) || /var [a-zA-Z]+=/.test(afterText)) {
49
+ issues.push("RAW_CODE_LEAK");
50
+ }
51
+
52
+ // 4. Open problems count
53
+ if (problemLines.length > 10) issues.push(`PROBLEMS_OVERCOUNT: ${problemLines.length}`);
54
+
55
+ // 5. Next steps empty
56
+ if (nextSection === "(empty)") issues.push("NEXT_STEPS_EMPTY");
57
+
58
+ // 6. What Was Done too verbose
59
+ if (doneLines.length > 15) issues.push(`DONE_TOO_VERBOSE: ${doneLines.length} lines`);
60
+
61
+ // 7. Summary too large (>10K chars)
62
+ if (afterText.length > 10000) issues.push(`SUMMARY_TOO_LARGE: ${afterText.length} chars`);
63
+
64
+ console.log(SEP);
65
+ console.log(`PROJECT: ${project}`);
66
+ console.log(`FILE: ${basename(sample.source)}`);
67
+ console.log(`Size: ${(sample.size / 1024).toFixed(0)}KB | Msgs: ${messages.length} | Blocks raw: ${rawBlocks.length} -> filtered: ${filteredBlocks.length}`);
68
+ console.log(`Before: ${beforeChars} chars | After: ${afterText.length} chars | Ratio: ${(beforeChars / afterText.length).toFixed(1)}x`);
69
+ console.log(`Issues: ${issues.length === 0 ? "NONE" : issues.join(", ")}`);
70
+ console.log("");
71
+ console.log("--- GOAL ---");
72
+ console.log(goalSection.slice(0, 300));
73
+ console.log("");
74
+ console.log("--- CURRENT STATE (first 300c) ---");
75
+ console.log(stateSection.slice(0, 300));
76
+ console.log("");
77
+ console.log("--- WHAT WAS DONE (first 5 lines) ---");
78
+ console.log(doneLines.slice(0, 5).join("\n"));
79
+ console.log(`... (${doneLines.length} total lines)`);
80
+ console.log("");
81
+ console.log("--- OPEN PROBLEMS (first 5 lines) ---");
82
+ console.log(problemLines.slice(0, 5).join("\n"));
83
+ console.log(`... (${problemLines.length} total lines)`);
84
+ console.log("");
85
+ console.log("--- NEXT STEPS ---");
86
+ console.log(nextSection.slice(0, 300));
87
+ console.log("");
88
+ }
@@ -0,0 +1,25 @@
1
+ import { performance } from "node:perf_hooks";
2
+ import { basename } from "node:path";
3
+ import { buildCompactReport } from "../src/core/report";
4
+ import { prepareSessionSamples } from "../tests/support/real-sessions";
5
+ import { loadSessionMessages } from "../tests/support/load-session";
6
+
7
+ const samples = await prepareSessionSamples(2);
8
+ for (const sample of samples) {
9
+ const loaded = loadSessionMessages(sample.copy);
10
+ const start = performance.now();
11
+ const report = buildCompactReport({ messages: loaded.messages });
12
+ const elapsedMs = performance.now() - start;
13
+ console.log(JSON.stringify({
14
+ sourceFile: basename(sample.source),
15
+ sourceSizeBytes: sample.size,
16
+ copiedToTemp: true,
17
+ loadedMessages: loaded.messageCount,
18
+ skippedMessages: loaded.skippedCount,
19
+ compileMs: Number(elapsedMs.toFixed(2)),
20
+ before: report.before,
21
+ after: report.after,
22
+ compression: report.compression,
23
+ recall: report.recall,
24
+ }, null, 2));
25
+ }
@@ -0,0 +1,36 @@
1
+ import { basename } from "node:path";
2
+ import { compile } from "../src/core/summarize";
3
+ import { renderMessage } from "../src/core/render-entries";
4
+ import { clip } from "../src/core/content";
5
+ import { prepareSessionSamples } from "../tests/support/real-sessions";
6
+ import { loadSessionMessages } from "../tests/support/load-session";
7
+
8
+ const SEP = "=".repeat(80);
9
+ const samples = await prepareSessionSamples(2);
10
+
11
+ for (const sample of samples) {
12
+ const loaded = loadSessionMessages(sample.copy);
13
+ const { messages } = loaded;
14
+
15
+ const rendered = messages.map((m, i) => renderMessage(m, i));
16
+ const beforeLines = rendered.map(
17
+ (e) => `#${e.index} [${e.role}] ${clip(e.summary, 300)}`,
18
+ );
19
+ const beforeText = beforeLines.join("\n");
20
+ const afterText = compile({ messages });
21
+
22
+ console.log(SEP);
23
+ console.log(`FILE: ${basename(sample.source)}`);
24
+ console.log(`Messages: ${messages.length} | Before chars: ${beforeText.length} | After chars: ${afterText.length}`);
25
+ console.log(`Compression: ${(beforeText.length / afterText.length).toFixed(1)}x`);
26
+ console.log(SEP);
27
+
28
+ console.log("\n--- BEFORE (raw context, first 40 + last 20 entries) ---\n");
29
+ for (const line of beforeLines.slice(0, 40)) console.log(line);
30
+ if (beforeLines.length > 60) console.log(`\n... (${beforeLines.length - 60} entries omitted) ...\n`);
31
+ for (const line of beforeLines.slice(-20)) console.log(line);
32
+
33
+ console.log("\n--- AFTER (pi-vcc compiled summary) ---\n");
34
+ console.log(afterText);
35
+ console.log("\n");
36
+ }
@@ -0,0 +1,20 @@
1
+ import { basename } from "node:path";
2
+ import { compile } from "../src/core/summarize";
3
+ import { prepareSessionSamples } from "../tests/support/real-sessions";
4
+ import { loadSessionMessages } from "../tests/support/load-session";
5
+ import { writeFileSync, mkdirSync } from "node:fs";
6
+
7
+ const outDir = "/tmp/pi-vcc-compare";
8
+ const branch = process.argv[2] || "unknown";
9
+ mkdirSync(`${outDir}/${branch}`, { recursive: true });
10
+
11
+ const samples = await prepareSessionSamples(5);
12
+ for (const sample of samples) {
13
+ const name = basename(sample.source).slice(0, 30);
14
+ const loaded = loadSessionMessages(sample.copy);
15
+ const summary = compile({ messages: loaded.messages });
16
+ const outFile = `${outDir}/${branch}/${name}.txt`;
17
+ writeFileSync(outFile, summary);
18
+ console.log(`${name} (${loaded.messageCount} msgs) => ${summary.length} chars`);
19
+ }
20
+ console.log(`\nSaved to ${outDir}/${branch}/`);
@@ -0,0 +1,36 @@
1
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import { getLastCompactionStats, PI_VCC_COMPACT_INSTRUCTION } from "../hooks/before-compact";
3
+
4
+ const formatTokens = (n: number): string => {
5
+ if (n >= 1000) return `${(n / 1000).toFixed(1)}k`;
6
+ return String(n);
7
+ };
8
+
9
+ export const registerPiVccCommand = (pi: ExtensionAPI) => {
10
+ pi.registerCommand("pi-vcc", {
11
+ description: "Compact conversation with pi-vcc structured summary",
12
+ handler: async (_args, ctx) => {
13
+ ctx.compact({
14
+ customInstructions: PI_VCC_COMPACT_INSTRUCTION,
15
+ onComplete: () => {
16
+ const stats = getLastCompactionStats();
17
+ if (stats) {
18
+ ctx.ui.notify(
19
+ `pi-vcc: ${stats.summarized} source entries processed; tail kept ${stats.kept} (~${formatTokens(stats.keptTokensEst)} tok).`,
20
+ "info",
21
+ );
22
+ } else {
23
+ ctx.ui.notify("Compacted with pi-vcc", "info");
24
+ }
25
+ },
26
+ onError: (err) => {
27
+ if (err.message === "Compaction cancelled" || err.message === "Already compacted") {
28
+ ctx.ui.notify("Nothing to compact", "warning");
29
+ } else {
30
+ ctx.ui.notify(`Compaction failed: ${err.message}`, "error");
31
+ }
32
+ },
33
+ });
34
+ },
35
+ });
36
+ };
@@ -0,0 +1,65 @@
1
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import { loadAllMessages } from "../core/load-messages";
3
+ import { searchEntries } from "../core/search-entries";
4
+ import { formatRecallOutput } from "../core/format-recall";
5
+ import { getActiveLineageEntryIds } from "../core/lineage";
6
+ import { parseRecallScope } from "../core/recall-scope";
7
+
8
+ const PAGE_SIZE = 5;
9
+ const DEFAULT_RECENT = 25;
10
+
11
+ export const registerVccRecallCommand = (pi: ExtensionAPI) => {
12
+ pi.registerCommand("pi-vcc-recall", {
13
+ description: "Search session history. Defaults to active lineage; add scope:all for off-lineage branches.",
14
+ handler: async (args: string, ctx) => {
15
+ const sessionFile = ctx.sessionManager.getSessionFile();
16
+ if (!sessionFile) {
17
+ ctx.ui.notify("No session file available.", "error");
18
+ return;
19
+ }
20
+
21
+ const raw = args.trim();
22
+ const parsed = parseRecallScope(raw);
23
+ const lineageEntryIds = parsed.scope === "lineage"
24
+ ? getActiveLineageEntryIds(ctx.sessionManager)
25
+ : undefined;
26
+ if (!parsed.text) {
27
+ // No query: show recent
28
+ const { rendered } = loadAllMessages(sessionFile, false, lineageEntryIds);
29
+ const recent = rendered.slice(-DEFAULT_RECENT);
30
+ const output = (parsed.scope === "all" ? "Scope: all\n\n" : "") + formatRecallOutput(recent);
31
+ pi.sendMessage({ customType: "vcc-recall", content: output, display: true }, { triggerTurn: true });
32
+ return;
33
+ }
34
+
35
+ // Parse page:N from args
36
+ const pageMatch = parsed.text.match(/\bpage:(\d+)\b/i);
37
+ const page = pageMatch ? Math.max(1, parseInt(pageMatch[1], 10)) : 1;
38
+ const query = parsed.text.replace(/\bpage:\d+\b/i, "").trim();
39
+
40
+ if (!query) {
41
+ const { rendered } = loadAllMessages(sessionFile, false, lineageEntryIds);
42
+ const recent = rendered.slice(-DEFAULT_RECENT);
43
+ const output = (parsed.scope === "all" ? "Scope: all\n\n" : "") + formatRecallOutput(recent);
44
+ pi.sendMessage({ customType: "vcc-recall", content: output, display: true }, { triggerTurn: true });
45
+ return;
46
+ }
47
+
48
+ const { rendered, rawMessages } = loadAllMessages(sessionFile, false, lineageEntryIds);
49
+ const allResults = searchEntries(rendered, rawMessages, query);
50
+
51
+ const start = (page - 1) * PAGE_SIZE;
52
+ const pageResults = allResults.slice(start, start + PAGE_SIZE);
53
+ const totalPages = Math.ceil(allResults.length / PAGE_SIZE);
54
+ const scopeSuffix = parsed.scope === "all" ? " (scope: all)" : "";
55
+ const header = totalPages > 1
56
+ ? `Page ${page}/${totalPages} (${allResults.length} total matches${scopeSuffix})`
57
+ : `${allResults.length} matches${scopeSuffix}`;
58
+ const footer = page < totalPages
59
+ ? `\n--- /pi-vcc-recall ${query}${parsed.scope === "all" ? " scope:all" : ""} page:${page + 1} ---`
60
+ : "";
61
+ const output = formatRecallOutput(pageResults, query, header) + footer;
62
+ pi.sendMessage({ customType: "vcc-recall", content: output, display: true }, { triggerTurn: true });
63
+ },
64
+ });
65
+ };
@@ -0,0 +1,381 @@
1
+ import type { NormalizedBlock } from "../types";
2
+ import { clip, firstLine } from "./content";
3
+ import { extractPath } from "./tool-args";
4
+ import { collapseSkillText } from "./skill-collapse";
5
+
6
+ const TRUNCATE_USER = 256;
7
+ const TRUNCATE_ASSISTANT = 200;
8
+
9
+ // Strip common self-reflective assistant prefixes that carry no semantic info.
10
+ // Conservative list: only removes the leading filler, preserves the actual content.
11
+ const SELF_TALK_PREFIX_RE =
12
+ /^\s*(?:hmm|wait|actually|oh|okay|ok|well|so)[,.!\s-]+/i;
13
+
14
+ // ── noise filtering ──
15
+
16
+ const isNoiseUser = (text: string): boolean => {
17
+ return !text.trim();
18
+ };
19
+
20
+ // ── truncation ──
21
+
22
+ // Unicode-aware word segmentation via Intl.Segmenter (built-in, zero dependency)
23
+ const segmenter = new Intl.Segmenter(undefined, { granularity: "word" });
24
+
25
+ /** Check if segment is a word (Bun's isWordLike is unreliable for alphanumeric tokens) */
26
+ const isWord = (seg: { segment: string; isWordLike: boolean }): boolean =>
27
+ seg.isWordLike || /[\p{L}\p{N}]/u.test(seg.segment);
28
+
29
+ // Common stop words — don't count toward budget
30
+ const STOP_WORDS = new Set([
31
+ "a", "an", "the", "is", "are", "was", "were", "be", "been", "being",
32
+ "have", "has", "had", "do", "does", "did", "will", "would", "could",
33
+ "should", "may", "might", "shall", "can", "need", "must",
34
+ "to", "of", "in", "for", "on", "with", "at", "by", "from", "as",
35
+ "into", "through", "during", "before", "after", "above", "below",
36
+ "between", "under", "over",
37
+ "and", "but", "or", "nor", "not", "so", "yet", "both", "either",
38
+ "neither", "each", "every", "all", "any", "few", "more", "most",
39
+ "other", "some", "such", "no",
40
+ "that", "this", "these", "those", "it", "its",
41
+ "i", "me", "my", "we", "our", "you", "your", "he", "him", "his",
42
+ "she", "her", "they", "them", "their", "who", "which", "what",
43
+ "if", "then", "than", "when", "where", "how", "just", "also",
44
+ ]);
45
+
46
+ const truncateTokens = (text: string, limit: number): string => {
47
+ const flat = text.replace(/\s+/g, " ").trim();
48
+ let count = 0;
49
+ let lastEnd = 0;
50
+ for (const seg of segmenter.segment(flat)) {
51
+ if (isWord(seg)) {
52
+ if (!STOP_WORDS.has(seg.segment.toLowerCase())) {
53
+ count++;
54
+ if (count > limit) {
55
+ return flat.slice(0, lastEnd).trimEnd() + "...(truncated)";
56
+ }
57
+ }
58
+ }
59
+ lastEnd = seg.index + seg.segment.length;
60
+ }
61
+ return flat;
62
+ };
63
+
64
+ // ── bash command compression ──
65
+
66
+ const BASH_CAP = 120;
67
+ const PIPE_TAIL_RE = /\s*\|\s*(?:head|tail|sort|wc|column|tr|cut|awk|uniq|python3|node|bun)(?:\s[^|]*)?$/;
68
+
69
+ /** Semantic compression: strip cd prefix, pipe tail formatting, cap length */
70
+ const compressBash = (raw: string): string => {
71
+ // Flatten multi-line: take first meaningful line
72
+ let cmd = raw.split("\n").map(l => l.trim()).filter(Boolean)[0] ?? raw;
73
+ // Strip cd <path> && prefix
74
+ cmd = cmd.replace(/^cd\s+\S+\s*&&\s*/, "");
75
+ // Strip pipe tail formatting commands (up to 3 times)
76
+ for (let i = 0; i < 3; i++) {
77
+ const stripped = cmd.replace(PIPE_TAIL_RE, "");
78
+ if (stripped === cmd) break;
79
+ cmd = stripped;
80
+ }
81
+ if (cmd.length > BASH_CAP) {
82
+ return cmd.slice(0, BASH_CAP - 3) + "...";
83
+ }
84
+ return cmd;
85
+ };
86
+
87
+ // ── tool summary ──
88
+
89
+ const TOOL_SUMMARY_FIELDS: Record<string, string> = {
90
+ Read: "file_path", Edit: "file_path", Write: "file_path",
91
+ read: "file_path", edit: "file_path", write: "file_path",
92
+ Glob: "pattern", Grep: "pattern",
93
+ };
94
+
95
+ const toolOneLiner = (name: string, args: Record<string, unknown>): string => {
96
+ const field = TOOL_SUMMARY_FIELDS[name];
97
+ if (field && typeof args[field] === "string") {
98
+ return `* ${name} "${args[field] as string}"`;
99
+ }
100
+ const path = extractPath(args);
101
+ if (path) return `* ${name} "${path}"`;
102
+ if (name === "bash" || name === "Bash") {
103
+ const raw = (args.command ?? args.description ?? "") as string;
104
+ const cmd = compressBash(raw);
105
+ return `* ${name} "${cmd}"`;
106
+ }
107
+ if (typeof args.query === "string") {
108
+ return `* ${name} "${clip(args.query as string, 60)}"`;
109
+ }
110
+ return `* ${name}`;
111
+ };
112
+
113
+ export interface BriefLine {
114
+ /** Section header like "[user]", "[assistant]", "[tool_error] bash" */
115
+ header: string;
116
+ /** Content lines for this section */
117
+ lines: string[];
118
+ }
119
+
120
+ /** Structured transcript entry for JSON output */
121
+ export interface TranscriptEntry {
122
+ role: "user" | "assistant" | "tool_error";
123
+ text?: string;
124
+ tool?: string;
125
+ cmd?: string;
126
+ ref?: string;
127
+ /** Collapse count when identical tool calls are grouped */
128
+ count?: number;
129
+ }
130
+
131
+ /**
132
+ * Build BriefLine sections from NormalizedBlocks.
133
+ */
134
+ export const buildBriefSections = (blocks: NormalizedBlock[]): BriefLine[] => {
135
+ const sections: BriefLine[] = [];
136
+ let lastHeader = "";
137
+
138
+ const push = (header: string, line: string) => {
139
+ if (header === lastHeader && sections.length > 0) {
140
+ sections[sections.length - 1].lines.push(line);
141
+ return;
142
+ }
143
+ sections.push({ header, lines: [line] });
144
+ lastHeader = header;
145
+ };
146
+
147
+ for (const b of blocks) {
148
+ switch (b.kind) {
149
+ case "user": {
150
+ if (isNoiseUser(b.text)) break;
151
+ const text = truncateTokens(collapseSkillText(b.text), TRUNCATE_USER);
152
+ if (text) {
153
+ const ref = b.sourceIndex != null ? ` (#${b.sourceIndex})` : "";
154
+ push("[user]", text + ref);
155
+ }
156
+ lastHeader = "[user]";
157
+ break;
158
+ }
159
+ case "assistant": {
160
+ let raw = b.text;
161
+ // Strip leading self-talk prefix (up to 2x; assistants sometimes chain "Hmm, actually, ...")
162
+ for (let i = 0; i < 2; i++) {
163
+ const stripped = raw.replace(SELF_TALK_PREFIX_RE, "");
164
+ if (stripped === raw) break;
165
+ raw = stripped;
166
+ }
167
+ const text = truncateTokens(raw, TRUNCATE_ASSISTANT);
168
+ if (text) {
169
+ const ref = b.sourceIndex != null ? ` (#${b.sourceIndex})` : "";
170
+ push("[assistant]", text + ref);
171
+ }
172
+ break;
173
+ }
174
+ case "tool_call": {
175
+ // Skip malformed tool calls from streaming providers (empty name / fragmented args).
176
+ if (!b.name || b.name.trim() === "") break;
177
+ const ref = b.sourceIndex != null ? ` (#${b.sourceIndex})` : "";
178
+ const summary = toolOneLiner(b.name, b.args) + ref;
179
+ push("[assistant]", summary);
180
+ break;
181
+ }
182
+ case "tool_result": {
183
+ if (b.isError) {
184
+ const body = firstLine(b.text, 150);
185
+ // Drop empty/placeholder error bodies — keep the line only if it carries info.
186
+ if (!body || body === "(no output)") break;
187
+ const ref = b.sourceIndex != null ? ` (#${b.sourceIndex})` : "";
188
+ const header = `[tool_error] ${b.name}${ref}`;
189
+ push(header, body);
190
+ lastHeader = header;
191
+ }
192
+ break;
193
+ }
194
+ case "thinking":
195
+ break;
196
+ }
197
+ }
198
+
199
+ // Collapse consecutive identical tool lines (same text, different #ref)
200
+ for (const sec of sections) {
201
+ if (sec.header !== "[assistant]") continue;
202
+ const out: string[] = [];
203
+ for (const line of sec.lines) {
204
+ if (!line.startsWith("* ")) { out.push(line); continue; }
205
+ const ref = line.match(/\(#(\d+)\)$/)?.[1] ?? "";
206
+ const base = ref ? line.slice(0, -(ref.length + 3)).trimEnd() : line;
207
+ const last = out.length > 0 ? out[out.length - 1] : "";
208
+ const m = last.match(/^(.*) \((#[\d, #]+)\) x(\d+)$/);
209
+ if (m && m[1] === base) {
210
+ out[out.length - 1] = `${base} (${m[2]}, #${ref}) x${parseInt(m[3]) + 1}`;
211
+ } else if (last.match(/\(#\d+\)$/) && last.replace(/\s*\(#\d+\)$/, "") === base) {
212
+ const prevRef = last.match(/\(#(\d+)\)$/)?.[1];
213
+ out[out.length - 1] = `${base} (#${prevRef}, #${ref}) x2`;
214
+ } else {
215
+ out.push(line);
216
+ }
217
+ }
218
+ sec.lines = out;
219
+ }
220
+
221
+ // Cap tool calls per [assistant] turn — keep tail (latest actions tend to
222
+ // be the deciding edits/writes; head is usually exploration noise).
223
+ const TOOL_CALLS_PER_TURN = 8;
224
+ for (const sec of sections) {
225
+ if (sec.header !== "[assistant]") continue;
226
+ const toolIdxs = sec.lines
227
+ .map((l, i) => (l.startsWith("* ") ? i : -1))
228
+ .filter((i) => i >= 0);
229
+ if (toolIdxs.length <= TOOL_CALLS_PER_TURN) continue;
230
+ const dropCount = toolIdxs.length - TOOL_CALLS_PER_TURN;
231
+ const dropSet = new Set(toolIdxs.slice(0, dropCount));
232
+ const firstKeptToolIdx = toolIdxs[dropCount];
233
+ const next: string[] = [];
234
+ let inserted = false;
235
+ for (let i = 0; i < sec.lines.length; i++) {
236
+ if (dropSet.has(i)) continue;
237
+ if (!inserted && i === firstKeptToolIdx) {
238
+ next.push(`* (${dropCount} earlier tool-call entries omitted)`);
239
+ inserted = true;
240
+ }
241
+ next.push(sec.lines[i]);
242
+ }
243
+ sec.lines = next;
244
+ }
245
+
246
+ // Collapse consecutive identical [tool_error] sections (same tool, same body).
247
+ // E.g. 20 back-to-back `[tool_error] bash (#N) ... Command aborted` become one
248
+ // `[tool_error] bash (#refs...) x20` entry.
249
+ const collapsedErrors: BriefLine[] = [];
250
+ for (const sec of sections) {
251
+ const m = sec.header.match(/^\[tool_error\]\s+(\S+?)(?:\s*\(#(\d+)\))?$/);
252
+ if (!m || sec.lines.length !== 1) {
253
+ collapsedErrors.push(sec);
254
+ continue;
255
+ }
256
+ const tool = m[1];
257
+ const ref = m[2];
258
+ const body = sec.lines[0];
259
+ const prev = collapsedErrors[collapsedErrors.length - 1];
260
+ const prevMatch = prev?.header.match(
261
+ /^\[tool_error\]\s+(\S+?)\s*\(((?:#\d+(?:,\s*)?)+)\)(?:\s*x(\d+))?$/,
262
+ );
263
+ if (prev && prevMatch && prevMatch[1] === tool && prev.lines.length === 1 && prev.lines[0] === body) {
264
+ const refs = prevMatch[2] + (ref ? `, #${ref}` : "");
265
+ const count = prevMatch[3] ? parseInt(prevMatch[3]) + 1 : 2;
266
+ prev.header = `[tool_error] ${tool} (${refs}) x${count}`;
267
+ } else {
268
+ collapsedErrors.push(sec);
269
+ }
270
+ }
271
+ sections.length = 0;
272
+ sections.push(...collapsedErrors);
273
+
274
+ return sections;
275
+ };
276
+
277
+ /**
278
+ * Stringify BriefLine sections into text format.
279
+ */
280
+ export const stringifyBrief = (sections: BriefLine[]): string => {
281
+
282
+ // Emit sections -- suppress blank lines between consecutive tool summaries
283
+ const out: string[] = [];
284
+ for (let i = 0; i < sections.length; i++) {
285
+ const sec = sections[i];
286
+ if (i > 0) {
287
+ const prev = sections[i - 1];
288
+ const prevIsTools = prev.header === "[assistant]" &&
289
+ prev.lines.every((l) => l.startsWith("* "));
290
+ const curIsTools = sec.header === "[assistant]" &&
291
+ sec.lines.every((l) => l.startsWith("* "));
292
+ if (!(prevIsTools && curIsTools)) {
293
+ out.push("");
294
+ }
295
+ }
296
+ out.push(sec.header);
297
+ for (const line of sec.lines) {
298
+ out.push(line);
299
+ }
300
+ }
301
+
302
+ return out.join("\n");
303
+ };
304
+
305
+ /** Parse a text line into a structured TranscriptEntry */
306
+ const parseToolLine = (line: string): { tool: string; cmd?: string; ref?: string; count?: number } | null => {
307
+ // * bash "cmd" (#5)
308
+ // * bash "cmd" (#1, #3) x2
309
+ // * tilth "query" (#7)
310
+ const m = line.match(/^\* (\S+)\s*(?:"([^"]*)")?\s*(?:\((#[\d, #]+)\))?\s*(?:x(\d+))?$/);
311
+ if (!m) return null;
312
+ return {
313
+ tool: m[1],
314
+ cmd: m[2] || undefined,
315
+ ref: m[3] || undefined,
316
+ count: m[4] ? parseInt(m[4]) : undefined,
317
+ };
318
+ };
319
+
320
+ const extractRef = (text: string): { clean: string; ref?: string } => {
321
+ const m = text.match(/\s*\(#(\d+)\)$/);
322
+ if (!m) return { clean: text };
323
+ return { clean: text.slice(0, m.index).trimEnd(), ref: `#${m[1]}` };
324
+ };
325
+
326
+ /**
327
+ * Convert BriefLine sections to structured TranscriptEntry array for JSON output.
328
+ */
329
+ export const sectionsToTranscript = (sections: BriefLine[]): TranscriptEntry[] => {
330
+ const entries: TranscriptEntry[] = [];
331
+
332
+ for (const sec of sections) {
333
+ if (sec.header === "[user]") {
334
+ for (const line of sec.lines) {
335
+ const { clean, ref } = extractRef(line);
336
+ entries.push({ role: "user", text: clean, ...(ref && { ref }) });
337
+ }
338
+ } else if (sec.header === "[assistant]") {
339
+ for (const line of sec.lines) {
340
+ if (line.startsWith("* ")) {
341
+ const parsed = parseToolLine(line);
342
+ if (parsed) {
343
+ entries.push({
344
+ role: "assistant",
345
+ tool: parsed.tool,
346
+ ...(parsed.cmd && { cmd: parsed.cmd }),
347
+ ...(parsed.ref && { ref: parsed.ref }),
348
+ ...(parsed.count && { count: parsed.count }),
349
+ });
350
+ } else {
351
+ // Fallback: unparseable tool line
352
+ const { clean, ref } = extractRef(line.slice(2));
353
+ entries.push({ role: "assistant", text: clean, ...(ref && { ref }) });
354
+ }
355
+ } else {
356
+ const { clean, ref } = extractRef(line);
357
+ entries.push({ role: "assistant", text: clean, ...(ref && { ref }) });
358
+ }
359
+ }
360
+ } else if (sec.header.startsWith("[tool_error]")) {
361
+ // [tool_error] bash (#5)
362
+ const headerMatch = sec.header.match(/^\[tool_error\]\s+(\S+)\s*(?:\(#(\d+)\))?/);
363
+ const tool = headerMatch?.[1] ?? "unknown";
364
+ const ref = headerMatch?.[2] ? `#${headerMatch[2]}` : undefined;
365
+ for (const line of sec.lines) {
366
+ entries.push({
367
+ role: "tool_error",
368
+ tool,
369
+ text: line,
370
+ ...(ref && { ref }),
371
+ });
372
+ }
373
+ }
374
+ }
375
+
376
+ return entries;
377
+ };
378
+
379
+ /** Convenience: build sections from blocks and stringify to text */
380
+ export const compileBrief = (blocks: NormalizedBlock[]): string =>
381
+ stringifyBrief(buildBriefSections(blocks));