pi-usereq 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/.g.conf +20 -0
  2. package/.github/workflows/release-npm.yml +131 -0
  3. package/.gitignore +270 -0
  4. package/CHANGELOG.md +221 -0
  5. package/LICENSE +674 -0
  6. package/README.md +260 -0
  7. package/TODO.md +20 -0
  8. package/docs/pi.dev/agent-document-manifest.json +6399 -0
  9. package/docs/pi.dev/coding-agent-docs/compaction.md +394 -0
  10. package/docs/pi.dev/coding-agent-docs/custom-provider.md +596 -0
  11. package/docs/pi.dev/coding-agent-docs/development.md +71 -0
  12. package/docs/pi.dev/coding-agent-docs/extensions.md +2262 -0
  13. package/docs/pi.dev/coding-agent-docs/images/doom-extension.png +0 -0
  14. package/docs/pi.dev/coding-agent-docs/images/exy.png +0 -0
  15. package/docs/pi.dev/coding-agent-docs/images/interactive-mode.png +0 -0
  16. package/docs/pi.dev/coding-agent-docs/images/tree-view.png +0 -0
  17. package/docs/pi.dev/coding-agent-docs/json.md +82 -0
  18. package/docs/pi.dev/coding-agent-docs/keybindings.md +175 -0
  19. package/docs/pi.dev/coding-agent-docs/models.md +392 -0
  20. package/docs/pi.dev/coding-agent-docs/packages.md +218 -0
  21. package/docs/pi.dev/coding-agent-docs/prompt-templates.md +67 -0
  22. package/docs/pi.dev/coding-agent-docs/providers.md +195 -0
  23. package/docs/pi.dev/coding-agent-docs/rpc.md +1377 -0
  24. package/docs/pi.dev/coding-agent-docs/sdk.md +1124 -0
  25. package/docs/pi.dev/coding-agent-docs/session.md +412 -0
  26. package/docs/pi.dev/coding-agent-docs/settings.md +247 -0
  27. package/docs/pi.dev/coding-agent-docs/shell-aliases.md +13 -0
  28. package/docs/pi.dev/coding-agent-docs/skills.md +232 -0
  29. package/docs/pi.dev/coding-agent-docs/terminal-setup.md +106 -0
  30. package/docs/pi.dev/coding-agent-docs/termux.md +127 -0
  31. package/docs/pi.dev/coding-agent-docs/themes.md +295 -0
  32. package/docs/pi.dev/coding-agent-docs/tmux.md +61 -0
  33. package/docs/pi.dev/coding-agent-docs/tree.md +231 -0
  34. package/docs/pi.dev/coding-agent-docs/tui.md +887 -0
  35. package/docs/pi.dev/coding-agent-docs/windows.md +17 -0
  36. package/docs/pi.dev/mom-docs/artifacts-server.md +475 -0
  37. package/docs/pi.dev/mom-docs/events.md +307 -0
  38. package/docs/pi.dev/mom-docs/new.md +970 -0
  39. package/docs/pi.dev/mom-docs/sandbox.md +153 -0
  40. package/docs/pi.dev/mom-docs/slack-bot-minimal-guide.md +399 -0
  41. package/docs/pi.dev/mom-docs/v86.md +319 -0
  42. package/docs/pi.dev/pods-docs/gml-4.5.md +189 -0
  43. package/docs/pi.dev/pods-docs/gpt-oss.md +233 -0
  44. package/docs/pi.dev/pods-docs/implementation-plan.md +183 -0
  45. package/docs/pi.dev/pods-docs/kimi-k2.md +197 -0
  46. package/docs/pi.dev/pods-docs/models.md +116 -0
  47. package/docs/pi.dev/pods-docs/plan.md +166 -0
  48. package/docs/pi.dev/pods-docs/qwen3-coder.md +132 -0
  49. package/images/flowchart-bw.png +0 -0
  50. package/images/flowchart-bw.svg +102 -0
  51. package/images/flowchart.md +100 -0
  52. package/images/flowchart.png +0 -0
  53. package/images/flowchart.svg +3 -0
  54. package/package.json +46 -0
  55. package/req/docs/REFERENCES.md +4554 -0
  56. package/req/docs/REQUIREMENTS.md +475 -0
  57. package/req/docs/WORKFLOW.md +1059 -0
  58. package/scripts/debug-extension.ts +497 -0
  59. package/scripts/lib/extension-debug-harness.ts +450 -0
  60. package/scripts/lib/recording-extension-api.ts +786 -0
  61. package/scripts/lib/sdk-smoke.ts +503 -0
  62. package/scripts/pi-usereq-debug.sh +330 -0
  63. package/scripts/tool-args-to-params.ts +208 -0
  64. package/src/cli.ts +349 -0
  65. package/src/core/agent-tool-json.ts +621 -0
  66. package/src/core/compress-files.ts +72 -0
  67. package/src/core/compress-payload.ts +648 -0
  68. package/src/core/compress.ts +464 -0
  69. package/src/core/config.ts +272 -0
  70. package/src/core/doxygen-parser.ts +318 -0
  71. package/src/core/errors.ts +31 -0
  72. package/src/core/extension-status.ts +660 -0
  73. package/src/core/find-constructs.ts +319 -0
  74. package/src/core/find-payload.ts +915 -0
  75. package/src/core/generate-markdown.ts +120 -0
  76. package/src/core/path-context.ts +196 -0
  77. package/src/core/pi-notify.ts +430 -0
  78. package/src/core/pi-usereq-tools.ts +140 -0
  79. package/src/core/prompts.ts +184 -0
  80. package/src/core/reference-payload.ts +818 -0
  81. package/src/core/resources.ts +63 -0
  82. package/src/core/runtime-project-paths.ts +99 -0
  83. package/src/core/settings-menu.ts +233 -0
  84. package/src/core/source-analyzer.ts +1721 -0
  85. package/src/core/static-check.ts +674 -0
  86. package/src/core/token-counter.ts +729 -0
  87. package/src/core/tool-runner.ts +717 -0
  88. package/src/core/utils.ts +185 -0
  89. package/src/index.ts +2209 -0
  90. package/src/resources/guidelines/Google_C++_Style_Guide.md +3711 -0
  91. package/src/resources/guidelines/Google_Python_Style_Guide.md +3709 -0
  92. package/src/resources/prompts/analyze.md +130 -0
  93. package/src/resources/prompts/change.md +227 -0
  94. package/src/resources/prompts/check.md +139 -0
  95. package/src/resources/prompts/cover.md +219 -0
  96. package/src/resources/prompts/create.md +104 -0
  97. package/src/resources/prompts/fix.md +221 -0
  98. package/src/resources/prompts/flowchart.md +220 -0
  99. package/src/resources/prompts/implement.md +163 -0
  100. package/src/resources/prompts/new.md +226 -0
  101. package/src/resources/prompts/readme.md +182 -0
  102. package/src/resources/prompts/recreate.md +213 -0
  103. package/src/resources/prompts/refactor.md +213 -0
  104. package/src/resources/prompts/references.md +100 -0
  105. package/src/resources/prompts/renumber.md +119 -0
  106. package/src/resources/prompts/workflow.md +202 -0
  107. package/src/resources/prompts/write.md +99 -0
  108. package/src/resources/sounds/Machine-alert-beep-sound-effect.mp3 +0 -0
  109. package/src/resources/sounds/Soft-high-tech-notification-sound-effect.mp3 +0 -0
  110. package/src/resources/templates/Document_Source_Code_in_Doxygen_Style.md +130 -0
  111. package/src/resources/templates/HDT_Test_Authoring_Guide.md +318 -0
  112. package/src/resources/templates/Requirements_Template.md +78 -0
  113. package/tests/attended-results-scenarios.ts +758 -0
  114. package/tests/attended-results.test.ts +39 -0
  115. package/tests/cli-command-option-parity.test.ts +815 -0
  116. package/tests/debug-extension-harness.test.ts +463 -0
  117. package/tests/extension-registration.test.ts +2006 -0
  118. package/tests/fixtures/fixture_c.c +361 -0
  119. package/tests/fixtures/fixture_cpp.cpp +407 -0
  120. package/tests/fixtures/fixture_csharp.cs +411 -0
  121. package/tests/fixtures/fixture_elixir.ex +409 -0
  122. package/tests/fixtures/fixture_go.go +341 -0
  123. package/tests/fixtures/fixture_haskell.hs +250 -0
  124. package/tests/fixtures/fixture_java.java +430 -0
  125. package/tests/fixtures/fixture_javascript.js +383 -0
  126. package/tests/fixtures/fixture_kotlin.kt +451 -0
  127. package/tests/fixtures/fixture_lua.lua +276 -0
  128. package/tests/fixtures/fixture_perl.pl +310 -0
  129. package/tests/fixtures/fixture_php.php +433 -0
  130. package/tests/fixtures/fixture_python.py +502 -0
  131. package/tests/fixtures/fixture_ruby.rb +345 -0
  132. package/tests/fixtures/fixture_rust.rs +380 -0
  133. package/tests/fixtures/fixture_scala.scala +398 -0
  134. package/tests/fixtures/fixture_shell.sh +276 -0
  135. package/tests/fixtures/fixture_swift.swift +397 -0
  136. package/tests/fixtures/fixture_typescript.ts +434 -0
  137. package/tests/fixtures/fixture_zig.zig +295 -0
  138. package/tests/fixtures_attended_results/project/compress-line-numbers.json +5 -0
  139. package/tests/fixtures_attended_results/project/compress.json +5 -0
  140. package/tests/fixtures_attended_results/project/enable-static-check-invalid-command.json +5 -0
  141. package/tests/fixtures_attended_results/project/enable-static-check-valid.json +5 -0
  142. package/tests/fixtures_attended_results/project/files-static-check.json +5 -0
  143. package/tests/fixtures_attended_results/project/find-line-numbers.json +5 -0
  144. package/tests/fixtures_attended_results/project/find.json +5 -0
  145. package/tests/fixtures_attended_results/project/get-base-path.json +5 -0
  146. package/tests/fixtures_attended_results/project/git-check-clean.json +5 -0
  147. package/tests/fixtures_attended_results/project/git-check-dirty.json +5 -0
  148. package/tests/fixtures_attended_results/project/git-path.json +5 -0
  149. package/tests/fixtures_attended_results/project/git-wt-create-invalid.json +5 -0
  150. package/tests/fixtures_attended_results/project/git-wt-create-valid.json +5 -0
  151. package/tests/fixtures_attended_results/project/git-wt-delete-nonexistent.json +5 -0
  152. package/tests/fixtures_attended_results/project/git-wt-delete-valid.json +5 -0
  153. package/tests/fixtures_attended_results/project/git-wt-name.json +5 -0
  154. package/tests/fixtures_attended_results/project/references.json +5 -0
  155. package/tests/fixtures_attended_results/project/static-check.json +5 -0
  156. package/tests/fixtures_attended_results/project/tokens.json +5 -0
  157. package/tests/fixtures_attended_results/standalone/files-compress/fixture_c.c.json +5 -0
  158. package/tests/fixtures_attended_results/standalone/files-compress/fixture_cpp.cpp.json +5 -0
  159. package/tests/fixtures_attended_results/standalone/files-compress/fixture_csharp.cs.json +5 -0
  160. package/tests/fixtures_attended_results/standalone/files-compress/fixture_elixir.ex.json +5 -0
  161. package/tests/fixtures_attended_results/standalone/files-compress/fixture_go.go.json +5 -0
  162. package/tests/fixtures_attended_results/standalone/files-compress/fixture_haskell.hs.json +5 -0
  163. package/tests/fixtures_attended_results/standalone/files-compress/fixture_java.java.json +5 -0
  164. package/tests/fixtures_attended_results/standalone/files-compress/fixture_javascript.js.json +5 -0
  165. package/tests/fixtures_attended_results/standalone/files-compress/fixture_kotlin.kt.json +5 -0
  166. package/tests/fixtures_attended_results/standalone/files-compress/fixture_lua.lua.json +5 -0
  167. package/tests/fixtures_attended_results/standalone/files-compress/fixture_perl.pl.json +5 -0
  168. package/tests/fixtures_attended_results/standalone/files-compress/fixture_php.php.json +5 -0
  169. package/tests/fixtures_attended_results/standalone/files-compress/fixture_python.py.json +5 -0
  170. package/tests/fixtures_attended_results/standalone/files-compress/fixture_ruby.rb.json +5 -0
  171. package/tests/fixtures_attended_results/standalone/files-compress/fixture_rust.rs.json +5 -0
  172. package/tests/fixtures_attended_results/standalone/files-compress/fixture_scala.scala.json +5 -0
  173. package/tests/fixtures_attended_results/standalone/files-compress/fixture_shell.sh.json +5 -0
  174. package/tests/fixtures_attended_results/standalone/files-compress/fixture_swift.swift.json +5 -0
  175. package/tests/fixtures_attended_results/standalone/files-compress/fixture_typescript.ts.json +5 -0
  176. package/tests/fixtures_attended_results/standalone/files-compress/fixture_zig.zig.json +5 -0
  177. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_c.c.json +5 -0
  178. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_cpp.cpp.json +5 -0
  179. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_csharp.cs.json +5 -0
  180. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_elixir.ex.json +5 -0
  181. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_go.go.json +5 -0
  182. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_haskell.hs.json +5 -0
  183. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_java.java.json +5 -0
  184. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_javascript.js.json +5 -0
  185. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_kotlin.kt.json +5 -0
  186. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_lua.lua.json +5 -0
  187. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_perl.pl.json +5 -0
  188. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_php.php.json +5 -0
  189. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_python.py.json +5 -0
  190. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_ruby.rb.json +5 -0
  191. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_rust.rs.json +5 -0
  192. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_scala.scala.json +5 -0
  193. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_shell.sh.json +5 -0
  194. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_swift.swift.json +5 -0
  195. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_typescript.ts.json +5 -0
  196. package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_zig.zig.json +5 -0
  197. package/tests/fixtures_attended_results/standalone/files-find/fixture_c.c.json +5 -0
  198. package/tests/fixtures_attended_results/standalone/files-find/fixture_cpp.cpp.json +5 -0
  199. package/tests/fixtures_attended_results/standalone/files-find/fixture_csharp.cs.json +5 -0
  200. package/tests/fixtures_attended_results/standalone/files-find/fixture_elixir.ex.json +5 -0
  201. package/tests/fixtures_attended_results/standalone/files-find/fixture_go.go.json +5 -0
  202. package/tests/fixtures_attended_results/standalone/files-find/fixture_haskell.hs.json +5 -0
  203. package/tests/fixtures_attended_results/standalone/files-find/fixture_java.java.json +5 -0
  204. package/tests/fixtures_attended_results/standalone/files-find/fixture_javascript.js.json +5 -0
  205. package/tests/fixtures_attended_results/standalone/files-find/fixture_kotlin.kt.json +5 -0
  206. package/tests/fixtures_attended_results/standalone/files-find/fixture_lua.lua.json +5 -0
  207. package/tests/fixtures_attended_results/standalone/files-find/fixture_perl.pl.json +5 -0
  208. package/tests/fixtures_attended_results/standalone/files-find/fixture_php.php.json +5 -0
  209. package/tests/fixtures_attended_results/standalone/files-find/fixture_python.py.json +5 -0
  210. package/tests/fixtures_attended_results/standalone/files-find/fixture_ruby.rb.json +5 -0
  211. package/tests/fixtures_attended_results/standalone/files-find/fixture_rust.rs.json +5 -0
  212. package/tests/fixtures_attended_results/standalone/files-find/fixture_scala.scala.json +5 -0
  213. package/tests/fixtures_attended_results/standalone/files-find/fixture_shell.sh.json +5 -0
  214. package/tests/fixtures_attended_results/standalone/files-find/fixture_swift.swift.json +5 -0
  215. package/tests/fixtures_attended_results/standalone/files-find/fixture_typescript.ts.json +5 -0
  216. package/tests/fixtures_attended_results/standalone/files-find/fixture_zig.zig.json +5 -0
  217. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_c.c.json +5 -0
  218. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_cpp.cpp.json +5 -0
  219. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_csharp.cs.json +5 -0
  220. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_elixir.ex.json +5 -0
  221. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_go.go.json +5 -0
  222. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_haskell.hs.json +5 -0
  223. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_java.java.json +5 -0
  224. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_javascript.js.json +5 -0
  225. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_kotlin.kt.json +5 -0
  226. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_lua.lua.json +5 -0
  227. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_perl.pl.json +5 -0
  228. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_php.php.json +5 -0
  229. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_python.py.json +5 -0
  230. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_ruby.rb.json +5 -0
  231. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_rust.rs.json +5 -0
  232. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_scala.scala.json +5 -0
  233. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_shell.sh.json +5 -0
  234. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_swift.swift.json +5 -0
  235. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_typescript.ts.json +5 -0
  236. package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_zig.zig.json +5 -0
  237. package/tests/fixtures_attended_results/standalone/files-references/fixture_c.c.json +5 -0
  238. package/tests/fixtures_attended_results/standalone/files-references/fixture_cpp.cpp.json +5 -0
  239. package/tests/fixtures_attended_results/standalone/files-references/fixture_csharp.cs.json +5 -0
  240. package/tests/fixtures_attended_results/standalone/files-references/fixture_elixir.ex.json +5 -0
  241. package/tests/fixtures_attended_results/standalone/files-references/fixture_go.go.json +5 -0
  242. package/tests/fixtures_attended_results/standalone/files-references/fixture_haskell.hs.json +5 -0
  243. package/tests/fixtures_attended_results/standalone/files-references/fixture_java.java.json +5 -0
  244. package/tests/fixtures_attended_results/standalone/files-references/fixture_javascript.js.json +5 -0
  245. package/tests/fixtures_attended_results/standalone/files-references/fixture_kotlin.kt.json +5 -0
  246. package/tests/fixtures_attended_results/standalone/files-references/fixture_lua.lua.json +5 -0
  247. package/tests/fixtures_attended_results/standalone/files-references/fixture_perl.pl.json +5 -0
  248. package/tests/fixtures_attended_results/standalone/files-references/fixture_php.php.json +5 -0
  249. package/tests/fixtures_attended_results/standalone/files-references/fixture_python.py.json +5 -0
  250. package/tests/fixtures_attended_results/standalone/files-references/fixture_ruby.rb.json +5 -0
  251. package/tests/fixtures_attended_results/standalone/files-references/fixture_rust.rs.json +5 -0
  252. package/tests/fixtures_attended_results/standalone/files-references/fixture_scala.scala.json +5 -0
  253. package/tests/fixtures_attended_results/standalone/files-references/fixture_shell.sh.json +5 -0
  254. package/tests/fixtures_attended_results/standalone/files-references/fixture_swift.swift.json +5 -0
  255. package/tests/fixtures_attended_results/standalone/files-references/fixture_typescript.ts.json +5 -0
  256. package/tests/fixtures_attended_results/standalone/files-references/fixture_zig.zig.json +5 -0
  257. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_c.c.json +5 -0
  258. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_cpp.cpp.json +5 -0
  259. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_csharp.cs.json +5 -0
  260. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_elixir.ex.json +5 -0
  261. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_go.go.json +5 -0
  262. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_haskell.hs.json +5 -0
  263. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_java.java.json +5 -0
  264. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_javascript.js.json +5 -0
  265. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_kotlin.kt.json +5 -0
  266. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_lua.lua.json +5 -0
  267. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_perl.pl.json +5 -0
  268. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_php.php.json +5 -0
  269. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_python.py.json +5 -0
  270. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_ruby.rb.json +5 -0
  271. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_rust.rs.json +5 -0
  272. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_scala.scala.json +5 -0
  273. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_shell.sh.json +5 -0
  274. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_swift.swift.json +5 -0
  275. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_typescript.ts.json +5 -0
  276. package/tests/fixtures_attended_results/standalone/files-tokens/fixture_zig.zig.json +5 -0
  277. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_c.c.json +5 -0
  278. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_cpp.cpp.json +5 -0
  279. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_csharp.cs.json +5 -0
  280. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_elixir.ex.json +5 -0
  281. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_go.go.json +5 -0
  282. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_haskell.hs.json +5 -0
  283. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_java.java.json +5 -0
  284. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_javascript.js.json +5 -0
  285. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_kotlin.kt.json +5 -0
  286. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_lua.lua.json +5 -0
  287. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_perl.pl.json +5 -0
  288. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_php.php.json +5 -0
  289. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_python.py.json +5 -0
  290. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_ruby.rb.json +5 -0
  291. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_rust.rs.json +5 -0
  292. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_scala.scala.json +5 -0
  293. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_shell.sh.json +5 -0
  294. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_swift.swift.json +5 -0
  295. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_typescript.ts.json +5 -0
  296. package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_zig.zig.json +5 -0
  297. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_c.c.json +5 -0
  298. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_cpp.cpp.json +5 -0
  299. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_csharp.cs.json +5 -0
  300. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_elixir.ex.json +5 -0
  301. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_go.go.json +5 -0
  302. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_haskell.hs.json +5 -0
  303. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_java.java.json +5 -0
  304. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_javascript.js.json +5 -0
  305. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_kotlin.kt.json +5 -0
  306. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_lua.lua.json +5 -0
  307. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_perl.pl.json +5 -0
  308. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_php.php.json +5 -0
  309. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_python.py.json +5 -0
  310. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_ruby.rb.json +5 -0
  311. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_rust.rs.json +5 -0
  312. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_scala.scala.json +5 -0
  313. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_shell.sh.json +5 -0
  314. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_swift.swift.json +5 -0
  315. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_typescript.ts.json +5 -0
  316. package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_zig.zig.json +5 -0
  317. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_c.c.json +5 -0
  318. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_cpp.cpp.json +5 -0
  319. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_csharp.cs.json +5 -0
  320. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_elixir.ex.json +5 -0
  321. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_go.go.json +5 -0
  322. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_haskell.hs.json +5 -0
  323. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_java.java.json +5 -0
  324. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_javascript.js.json +5 -0
  325. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_kotlin.kt.json +5 -0
  326. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_lua.lua.json +5 -0
  327. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_perl.pl.json +5 -0
  328. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_php.php.json +5 -0
  329. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_python.py.json +5 -0
  330. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_ruby.rb.json +5 -0
  331. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_rust.rs.json +5 -0
  332. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_scala.scala.json +5 -0
  333. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_shell.sh.json +5 -0
  334. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_swift.swift.json +5 -0
  335. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_typescript.ts.json +5 -0
  336. package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_zig.zig.json +5 -0
  337. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_c.c.json +5 -0
  338. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_cpp.cpp.json +5 -0
  339. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_csharp.cs.json +5 -0
  340. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_elixir.ex.json +5 -0
  341. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_go.go.json +5 -0
  342. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_haskell.hs.json +5 -0
  343. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_java.java.json +5 -0
  344. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_javascript.js.json +5 -0
  345. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_kotlin.kt.json +5 -0
  346. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_lua.lua.json +5 -0
  347. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_perl.pl.json +5 -0
  348. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_php.php.json +5 -0
  349. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_python.py.json +5 -0
  350. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_ruby.rb.json +5 -0
  351. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_rust.rs.json +5 -0
  352. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_scala.scala.json +5 -0
  353. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_shell.sh.json +5 -0
  354. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_swift.swift.json +5 -0
  355. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_typescript.ts.json +5 -0
  356. package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_zig.zig.json +5 -0
  357. package/tests/helpers.ts +204 -0
  358. package/tests/oracle-project.test.ts +63 -0
  359. package/tests/oracle-standalone.test.ts +48 -0
  360. package/tests/prompt-rendering.test.ts +66 -0
  361. package/tests/release-workflow.test.ts +133 -0
@@ -0,0 +1,4554 @@
1
+ # Files Structure
2
+ ```
3
+ .
4
+ ├── scripts
5
+ │ ├── debug-extension.ts
6
+ │ ├── lib
7
+ │ │ ├── extension-debug-harness.ts
8
+ │ │ ├── recording-extension-api.ts
9
+ │ │ └── sdk-smoke.ts
10
+ │ ├── pi-usereq-debug.sh
11
+ │ └── tool-args-to-params.ts
12
+ └── src
13
+ ├── cli.ts
14
+ ├── core
15
+ │ ├── agent-tool-json.ts
16
+ │ ├── compress-files.ts
17
+ │ ├── compress-payload.ts
18
+ │ ├── compress.ts
19
+ │ ├── config.ts
20
+ │ ├── doxygen-parser.ts
21
+ │ ├── errors.ts
22
+ │ ├── extension-status.ts
23
+ │ ├── find-constructs.ts
24
+ │ ├── find-payload.ts
25
+ │ ├── generate-markdown.ts
26
+ │ ├── path-context.ts
27
+ │ ├── pi-notify.ts
28
+ │ ├── pi-usereq-tools.ts
29
+ │ ├── prompts.ts
30
+ │ ├── reference-payload.ts
31
+ │ ├── resources.ts
32
+ │ ├── runtime-project-paths.ts
33
+ │ ├── settings-menu.ts
34
+ │ ├── source-analyzer.ts
35
+ │ ├── static-check.ts
36
+ │ ├── token-counter.ts
37
+ │ ├── tool-runner.ts
38
+ │ └── utils.ts
39
+ └── index.ts
40
+ ```
41
+
42
+ # debug-extension.ts | TypeScript | 497L | 17 symbols | 4 imports | 19 comments
43
+ > Path: `scripts/debug-extension.ts`
44
+ - @brief Implements the standalone extension debug harness CLI.
45
+ - @details Parses debug-harness subcommands, dispatches offline inspection and replay operations, formats reports as JSON or human-readable markdown, and converts `ReqError` instances into process-style stderr plus exit codes. Runtime is dominated by the selected harness subcommand. Side effects include stdout/stderr writes and any extension-owned behavior triggered by delegated replay operations.
46
+
47
+ ## Imports
48
+ ```
49
+ import process from "node:process";
50
+ import { ReqError } from "../src/core/errors.js";
51
+ import {
52
+ import { runSdkSmoke, type ParityMismatch, type SdkSmokeReport } from "./lib/sdk-smoke.js";
53
+ ```
54
+
55
+ ## Definitions
56
+
57
+ - type `type OutputFormat = "json" | "pretty";` (L26)
58
+ - @brief Enumerates the supported harness output formats.
59
+ - @details Keeps the CLI formatter selection constrained to deterministic JSON output or human-readable markdown output. The alias is compile-time only and introduces no runtime cost.
60
+ ### iface `interface ParsedHarnessArgs` (L32-44)
61
+ - @brief Describes the parsed debug-harness CLI arguments.
62
+ - @details Captures the selected subcommand plus all recognized option values in the normalized shape consumed by `main`. The interface is compile-time only and introduces no runtime cost.
63
+
64
+ ### fn `function parseArgs(argv: string[]): ParsedHarnessArgs` (L78-141)
65
+ - @brief Parses raw CLI arguments into a normalized harness command object.
66
+ - @details Performs a single left-to-right scan, records the first positional token as the subcommand, supports repeatable `--select` and `--input` options, and defaults the output format to `pretty`. Runtime is O(n) in argument count. No external state is mutated.
67
+ - @param[in] argv {string[]} Raw CLI arguments excluding executable and script path.
68
+ - @return {ParsedHarnessArgs} Parsed harness arguments.
69
+
70
+ ### fn `function parseJsonObject(text: string | undefined, label: string, fallback: Record<string, unknown>): Record<string, unknown>` (L152-168)
71
+ - @brief Parses a JSON object option from the CLI.
72
+ - @details Accepts an omitted value as the supplied fallback, requires object payloads for present values, and wraps parse failures in `ReqError` for deterministic CLI error reporting. Runtime is O(n) in input size. No external state is mutated.
73
+ - @param[in] text {string | undefined} Raw JSON option value.
74
+ - @param[in] label {string} Human-readable option label.
75
+ - @param[in] fallback {Record<string, unknown>} Fallback object when the option is omitted.
76
+ - @return {Record<string, unknown>} Parsed JSON object.
77
+ - @throws {ReqError} Throws when the option is present but not valid JSON object syntax.
78
+
79
+ ### fn `function writeStdout(text: string): void` (L176-180)
80
+ - @brief Writes non-empty text to stdout.
81
+ - @details Skips zero-length writes so callers can compose output safely. Runtime is O(n) in text length. Side effects are limited to stdout writes.
82
+ - @param[in] text {string} Text payload.
83
+ - @return {void} No return value.
84
+
85
+ ### fn `function writeStderr(text: string): void` (L188-193)
86
+ - @brief Writes non-empty text to stderr with a trailing newline.
87
+ - @details Appends a newline when needed and skips empty payloads. Runtime is O(n) in text length. Side effects are limited to stderr writes.
88
+ - @param[in] text {string} Text payload.
89
+ - @return {void} No return value.
90
+
91
+ ### fn `function formatJson(value: unknown): string` (L201-203)
92
+ - @brief Serializes one arbitrary report as pretty-printed JSON.
93
+ - @details Uses two-space indentation and appends a trailing newline for stable automation-friendly output. Runtime is O(n) in report size. No external state is mutated.
94
+ - @param[in] value {unknown} Report payload.
95
+ - @return {string} JSON document.
96
+
97
+ ### fn `function formatSnapshotHeader(snapshot: OfflineContractSnapshot): string[]` (L211-222)
98
+ - @brief Formats the common snapshot header for human-readable output.
99
+ - @details Renders normalized path metadata, registration counts, and event names shared by all offline reports. Runtime is O(n) in inventory size. No external state is mutated.
100
+ - @param[in] snapshot {OfflineContractSnapshot} Snapshot payload.
101
+ - @return {string[]} Markdown lines.
102
+
103
+ ### fn `function formatInspectReport(report: InspectReport): string` (L230-249)
104
+ - @brief Formats one offline inspection report for human-readable output.
105
+ - @details Emits sections for inventory counts, commands, tools, sent user messages, and the generated usage manual. Runtime is O(n) in report size. No external state is mutated.
106
+ - @param[in] report {InspectReport} Inspection report.
107
+ - @return {string} Markdown document.
108
+
109
+ ### fn `function formatUiState(ui: SessionStartReport["ui"]): string[]` (L257-281)
110
+ - @brief Formats one recorded UI state snapshot for human-readable output.
111
+ - @details Emits statuses, notifications, editor text, and scripted interaction traces used by session-start and command/tool replay reports. Runtime is O(n) in interaction count. No external state is mutated.
112
+ - @param[in] ui {SessionStartReport["ui"]} UI-state snapshot.
113
+ - @return {string[]} Markdown lines.
114
+
115
+ ### fn `function formatSessionStartReport(report: SessionStartReport): string` (L289-300)
116
+ - @brief Formats one session-start replay report for human-readable output.
117
+ - @details Emits common snapshot metadata plus the recorded event payload and UI side effects. Runtime is O(n) in report size. No external state is mutated.
118
+ - @param[in] report {SessionStartReport} Session-start replay report.
119
+ - @return {string} Markdown document.
120
+
121
+ ### fn `function formatCommandReplayReport(report: CommandReplayReport): string` (L308-325)
122
+ - @brief Formats one command replay report for human-readable output.
123
+ - @details Emits common snapshot metadata, command identity, sent user messages, and UI side effects. Runtime is O(n) in report size. No external state is mutated.
124
+ - @param[in] report {CommandReplayReport} Command replay report.
125
+ - @return {string} Markdown document.
126
+
127
+ ### fn `function formatToolReplayReport(report: ToolReplayReport): string` (L333-352)
128
+ - @brief Formats one tool replay report for human-readable output.
129
+ - @details Emits common snapshot metadata, tool identity, input parameters, streamed updates, final result payload, and UI side effects. Runtime is O(n) in report size. No external state is mutated.
130
+ - @param[in] report {ToolReplayReport} Tool replay report.
131
+ - @return {string} Markdown document.
132
+
133
+ ### fn `function formatMismatch(mismatch: ParityMismatch): string[]` (L360-367)
134
+ - @brief Formats one parity mismatch for human-readable output.
135
+ - @details Emits the category, subject, detail, and normalized offline versus SDK payloads for deterministic troubleshooting. Runtime is O(n) in payload size. No external state is mutated.
136
+ - @param[in] mismatch {ParityMismatch} Mismatch payload.
137
+ - @return {string[]} Markdown lines.
138
+
139
+ ### fn `function formatSdkSmokeReport(report: SdkSmokeReport): string` (L375-395)
140
+ - @brief Formats one SDK smoke report for human-readable output.
141
+ - @details Emits parity status, offline versus SDK inventory counts, runtime-shape metadata, and detailed mismatch entries when parity fails. Runtime is O(n) in report size. No external state is mutated.
142
+ - @param[in] report {SdkSmokeReport} SDK smoke report.
143
+ - @return {string} Markdown document.
144
+
145
+ ### fn `function formatReport(` (L405-427)
146
+ - @brief Formats the selected report according to the requested output mode.
147
+ - @details Uses JSON for automation-friendly output and markdown for human review. Runtime is O(n) in report size. No external state is mutated.
148
+ - @param[in] format {OutputFormat} Requested output format.
149
+ - @param[in] subcommand {string} Executed harness subcommand.
150
+ - @param[in] report {InspectReport | SessionStartReport | CommandReplayReport | ToolReplayReport | SdkSmokeReport} Report payload.
151
+ - @return {string} Final stdout payload.
152
+
153
+ ### fn `export async function main(argv = process.argv.slice(2)): Promise<number>` (L436-491)
154
+ - @brief Executes one standalone debug-harness invocation.
155
+ - @details Parses CLI arguments, validates subcommand-specific requirements, dispatches the selected harness workflow, and formats the result for stdout while converting `ReqError` failures into stderr plus exit codes. Runtime is dominated by the selected subcommand. Side effects include stdout/stderr writes and delegated extension replay behavior.
156
+ - @param[in] argv {string[]} Raw CLI arguments. Defaults to `process.argv.slice(2)`.
157
+ - @return {Promise<number>} Process exit code.
158
+ - @throws {ReqError} Internally catches `ReqError` and returns its exit code.
159
+
160
+ ## Symbol Index
161
+ |Symbol|Kind|Vis|Lines|Sig|
162
+ |---|---|---|---|---|
163
+ |`OutputFormat`|type||26||
164
+ |`ParsedHarnessArgs`|iface||32-44|interface ParsedHarnessArgs|
165
+ |`parseArgs`|fn||78-141|function parseArgs(argv: string[]): ParsedHarnessArgs|
166
+ |`parseJsonObject`|fn||152-168|function parseJsonObject(text: string | undefined, label:...|
167
+ |`writeStdout`|fn||176-180|function writeStdout(text: string): void|
168
+ |`writeStderr`|fn||188-193|function writeStderr(text: string): void|
169
+ |`formatJson`|fn||201-203|function formatJson(value: unknown): string|
170
+ |`formatSnapshotHeader`|fn||211-222|function formatSnapshotHeader(snapshot: OfflineContractSn...|
171
+ |`formatInspectReport`|fn||230-249|function formatInspectReport(report: InspectReport): string|
172
+ |`formatUiState`|fn||257-281|function formatUiState(ui: SessionStartReport["ui"]): str...|
173
+ |`formatSessionStartReport`|fn||289-300|function formatSessionStartReport(report: SessionStartRep...|
174
+ |`formatCommandReplayReport`|fn||308-325|function formatCommandReplayReport(report: CommandReplayR...|
175
+ |`formatToolReplayReport`|fn||333-352|function formatToolReplayReport(report: ToolReplayReport)...|
176
+ |`formatMismatch`|fn||360-367|function formatMismatch(mismatch: ParityMismatch): string[]|
177
+ |`formatSdkSmokeReport`|fn||375-395|function formatSdkSmokeReport(report: SdkSmokeReport): st...|
178
+ |`formatReport`|fn||405-427|function formatReport(|
179
+ |`main`|fn||436-491|export async function main(argv = process.argv.slice(2)):...|
180
+
181
+
182
+ ---
183
+
184
+ # extension-debug-harness.ts | TypeScript | 450L | 17 symbols | 6 imports | 20 comments
185
+ > Path: `scripts/lib/extension-debug-harness.ts`
186
+ - @brief Implements offline extension inspection and replay for the standalone debug harness.
187
+ - @details Loads the extension default export as a black box, records registrations through `RecordingExtensionAPI`, replays `session_start`, command, and tool handlers through recorded public boundaries, and renders a deterministic usage manual. Runtime is O(r + u) where r is the number of registrations and u is the number of replayed side effects. Side effects are limited to dynamic module loading, temporary `process.cwd()` mutation during replay, filesystem existence checks, and any extension-owned side effects triggered by the recorded handlers.
188
+
189
+ ## Imports
190
+ ```
191
+ import fs from "node:fs";
192
+ import path from "node:path";
193
+ import process from "node:process";
194
+ import { pathToFileURL } from "node:url";
195
+ import { ReqError } from "../../src/core/errors.js";
196
+ import {
197
+ ```
198
+
199
+ ## Definitions
200
+
201
+ ### iface `export interface ExtensionFactory` (L25-27)
202
+ - @brief Describes the public shape of an extension factory loaded by the harness.
203
+ - @details Constrains the dynamic import result to the default-export contract used by pi extensions while remaining independent from the official SDK package at compile time. The interface is compile-time only and introduces no runtime cost.
204
+
205
+ ### iface `export interface OfflineContractSnapshot extends RecordingExtensionSnapshot` : RecordingExtensionSnapshot (L33-38)
206
+ - @brief Describes the shared offline snapshot returned by all harness operations.
207
+ - @details Aggregates normalized paths plus the recorded command, tool, event, active-tool, and user-message inventories so every subcommand can emit a stable machine-readable payload. The interface is compile-time only and introduces no runtime cost.
208
+
209
+ ### iface `export interface InspectReport extends OfflineContractSnapshot` : OfflineContractSnapshot (L44-46)
210
+ - @brief Describes the `inspect` subcommand result.
211
+ - @details Extends the base offline snapshot with a generated usage manual covering every registered `req-*` command and agent tool. The interface is compile-time only and introduces no runtime cost.
212
+
213
+ ### iface `export interface SessionStartReport extends OfflineContractSnapshot` : OfflineContractSnapshot (L52-56)
214
+ - @brief Describes the `session-start` subcommand result.
215
+ - @details Extends the base offline snapshot with the invoked event payload and all recorded UI side effects produced during `session_start` replay. The interface is compile-time only and introduces no runtime cost.
216
+
217
+ ### iface `export interface CommandReplayReport extends OfflineContractSnapshot` : OfflineContractSnapshot (L62-66)
218
+ - @brief Describes the `command` subcommand result.
219
+ - @details Extends the base offline snapshot with the executed command name, raw argument string, and recorded UI side effects produced by the command handler. The interface is compile-time only and introduces no runtime cost.
220
+
221
+ ### iface `export interface ToolReplayReport extends OfflineContractSnapshot` : OfflineContractSnapshot (L72-78)
222
+ - @brief Describes the `tool` subcommand result.
223
+ - @details Extends the base offline snapshot with the executed tool name, input parameter object, streamed updates, final result payload, and recorded UI side effects. The interface is compile-time only and introduces no runtime cost.
224
+
225
+ ### iface `export interface HarnessPaths` (L84-87)
226
+ - @brief Describes the resolved harness execution target paths.
227
+ - @details Stores absolute normalized filesystem locations for the requested working directory and extension entry path. The interface is compile-time only and introduces no runtime cost.
228
+
229
+ ### fn `function toJsonValue(value: unknown): JsonValue` (L95-106)
230
+ - @brief Serializes arbitrary replay payloads into deterministic JSON-compatible values.
231
+ - @details Uses JSON stringify/parse with function elision and bigint normalization so tool results, streamed updates, and event payloads remain stable in offline reports. Runtime is O(n) in payload size. No external state is mutated.
232
+ - @param[in] value {unknown} Arbitrary payload value.
233
+ - @return {JsonValue} JSON-compatible representation.
234
+
235
+ ### fn `export function resolveHarnessPaths(cwd?: string, extensionPath?: string): HarnessPaths` (L116-126)
236
+ - @brief Validates and resolves the requested working directory and extension path.
237
+ - @details Normalizes both inputs to absolute paths, rejects missing directories and files, and defaults the extension entry to `./src/index.ts` relative to the current process cwd when omitted. Runtime is O(p) in path length plus filesystem existence checks. Side effects are limited to filesystem reads.
238
+ - @param[in] cwd {string | undefined} Requested working directory.
239
+ - @param[in] extensionPath {string | undefined} Requested extension entry path.
240
+ - @return {HarnessPaths} Resolved absolute paths.
241
+ - @throws {ReqError} Throws when the working directory or extension entry does not exist.
242
+
243
+ ### fn `export async function loadExtensionFactory(extensionPath: string): Promise<ExtensionFactory>` (L136-143)
244
+ - @brief Loads the extension default export as a black-box factory.
245
+ - @details Performs a dynamic ESM import from the resolved extension path, verifies that the module exposes a callable default export, and returns that function without inspecting extension internals. Runtime is dominated by module loading. Side effects are limited to module evaluation.
246
+ - @param[in] extensionPath {string} Absolute extension entry path.
247
+ - @return {Promise<ExtensionFactory>} Loaded extension factory.
248
+ - @throws {ReqError} Throws when the module lacks a callable default export.
249
+ - @satisfies REQ-048
250
+
251
+ ### fn `async function withProcessCwd<T>(cwd: string, action: () => Promise<T> | T): Promise<{ value: T; effectiveProcessCwd: string }>` (L152-161)
252
+ - @brief Executes a callback with `process.cwd()` temporarily set to the requested directory.
253
+ - @details Changes the current working directory before invoking the callback, records the effective cwd observed inside the callback, and restores the previous cwd in a `finally` block. Runtime is dominated by the callback. Side effects transiently mutate process cwd.
254
+ - @param[in] cwd {string} Requested working directory.
255
+ - @param[in] action {() => Promise<T> | T} Callback executed under the requested cwd.
256
+ - @return {Promise<{ value: T; effectiveProcessCwd: string }>} Callback result plus the cwd observed during execution.
257
+
258
+ ### fn `async function registerExtensionOffline(` (L171-183)
259
+ - @brief Registers the target extension into a fresh recording API instance.
260
+ - @details Resolves the harness paths, loads the extension default export, instantiates a new recorder, and invokes the factory as a black box under the requested cwd. Runtime is dominated by module loading plus extension registration. Side effects include any extension-owned registration-time behavior.
261
+ - @param[in] cwd {string | undefined} Requested working directory.
262
+ - @param[in] extensionPath {string | undefined} Requested extension entry path.
263
+ - @return {Promise<{ api: RecordingExtensionAPI; paths: HarnessPaths; effectiveProcessCwd: string }>} Recorder plus resolved paths.
264
+ - @satisfies REQ-048
265
+
266
+ ### fn `export function buildDebugManual(snapshot: RecordingExtensionSnapshot): string` (L239-265)
267
+ - @brief Builds the generated harness usage manual.
268
+ - @details Emits one example for each debug mode plus one concrete replay example for every registered `req-*` command and agent tool. Runtime is O(c + t) in command and tool count. No external state is mutated.
269
+ - @param[in] snapshot {RecordingExtensionSnapshot} Recorded registration snapshot.
270
+ - @return {string} Markdown manual.
271
+ - @satisfies REQ-052
272
+
273
+ ### fn `export async function inspectExtension(cwd?: string, extensionPath?: string): Promise<InspectReport>` (L275-290)
274
+ - @brief Builds an offline inspection report without replaying runtime handlers.
275
+ - @details Loads and registers the extension as a black box, captures the registration snapshot, and appends the generated usage manual. Runtime is dominated by extension registration. Side effects are limited to registration-time extension behavior.
276
+ - @param[in] cwd {string | undefined} Requested working directory.
277
+ - @param[in] extensionPath {string | undefined} Requested extension entry path.
278
+ - @return {Promise<InspectReport>} Offline inspection report.
279
+ - @satisfies REQ-048, REQ-050, REQ-051, REQ-052
280
+
281
+ ### fn `export async function replaySessionStart(` (L302-336)
282
+ - @brief Replays the recorded `session_start` handlers offline.
283
+ - @details Loads and registers the extension as a black box, invokes every recorded `session_start` handler in registration order, and captures final active tools, user messages, and UI side effects. Runtime is dominated by handler execution. Side effects include temporary `process.cwd()` mutation plus extension-owned handler behavior.
284
+ - @param[in] cwd {string | undefined} Requested working directory.
285
+ - @param[in] extensionPath {string | undefined} Requested extension entry path.
286
+ - @param[in] eventPayload {Record<string, unknown> | undefined} Optional session-start payload. Defaults to `{ reason: "startup" }`.
287
+ - @param[in] uiPlan {RecordingUiPlan | undefined} Optional scripted UI responses.
288
+ - @return {Promise<SessionStartReport>} Offline session-start replay report.
289
+ - @satisfies REQ-048, REQ-049, REQ-050, REQ-051, REQ-053
290
+
291
+ ### fn `export async function replayCommand(` (L350-386)
292
+ - @brief Replays one recorded command handler offline.
293
+ - @details Loads and registers the extension as a black box, resolves the named command from the recording API, executes its handler under the requested cwd, and captures resulting user messages plus UI side effects. Runtime is dominated by the command handler. Side effects include temporary `process.cwd()` mutation plus extension-owned command behavior.
294
+ - @param[in] commandName {string} Registered command name.
295
+ - @param[in] commandArgs {string} Raw command argument string.
296
+ - @param[in] cwd {string | undefined} Requested working directory.
297
+ - @param[in] extensionPath {string | undefined} Requested extension entry path.
298
+ - @param[in] uiPlan {RecordingUiPlan | undefined} Optional scripted UI responses.
299
+ - @return {Promise<CommandReplayReport>} Offline command replay report.
300
+ - @throws {ReqError} Throws when the named command is not registered.
301
+ - @satisfies REQ-048, REQ-049, REQ-050, REQ-051, REQ-054, REQ-058
302
+
303
+ ### fn `export async function replayTool(` (L400-450)
304
+ - @brief Replays one recorded tool execute handler offline.
305
+ - @details Loads and registers the extension as a black box, resolves the named tool from the recording API, executes its `execute(...)` handler under the requested cwd, records streamed updates, and captures the final return payload plus UI side effects. Runtime is dominated by the tool handler. Side effects include temporary `process.cwd()` mutation plus extension-owned tool behavior.
306
+ - @param[in] toolName {string} Registered tool name.
307
+ - @param[in] toolParams {Record<string, unknown>} Tool parameter object.
308
+ - @param[in] cwd {string | undefined} Requested working directory.
309
+ - @param[in] extensionPath {string | undefined} Requested extension entry path.
310
+ - @param[in] uiPlan {RecordingUiPlan | undefined} Optional scripted UI responses.
311
+ - @return {Promise<ToolReplayReport>} Offline tool replay report.
312
+ - @throws {ReqError} Throws when the named tool is not registered or lacks an execute handler.
313
+ - @satisfies REQ-048, REQ-049, REQ-050, REQ-051, REQ-055, REQ-058
314
+
315
+ ## Symbol Index
316
+ |Symbol|Kind|Vis|Lines|Sig|
317
+ |---|---|---|---|---|
318
+ |`ExtensionFactory`|iface||25-27|export interface ExtensionFactory|
319
+ |`OfflineContractSnapshot`|iface||33-38|export interface OfflineContractSnapshot extends Recordin...|
320
+ |`InspectReport`|iface||44-46|export interface InspectReport extends OfflineContractSna...|
321
+ |`SessionStartReport`|iface||52-56|export interface SessionStartReport extends OfflineContra...|
322
+ |`CommandReplayReport`|iface||62-66|export interface CommandReplayReport extends OfflineContr...|
323
+ |`ToolReplayReport`|iface||72-78|export interface ToolReplayReport extends OfflineContract...|
324
+ |`HarnessPaths`|iface||84-87|export interface HarnessPaths|
325
+ |`toJsonValue`|fn||95-106|function toJsonValue(value: unknown): JsonValue|
326
+ |`resolveHarnessPaths`|fn||116-126|export function resolveHarnessPaths(cwd?: string, extensi...|
327
+ |`loadExtensionFactory`|fn||136-143|export async function loadExtensionFactory(extensionPath:...|
328
+ |`withProcessCwd`|fn||152-161|async function withProcessCwd<T>(cwd: string, action: () ...|
329
+ |`registerExtensionOffline`|fn||171-183|async function registerExtensionOffline(|
330
+ |`buildDebugManual`|fn||239-265|export function buildDebugManual(snapshot: RecordingExten...|
331
+ |`inspectExtension`|fn||275-290|export async function inspectExtension(cwd?: string, exte...|
332
+ |`replaySessionStart`|fn||302-336|export async function replaySessionStart(|
333
+ |`replayCommand`|fn||350-386|export async function replayCommand(|
334
+ |`replayTool`|fn||400-450|export async function replayTool(|
335
+
336
+
337
+ ---
338
+
339
+ # recording-extension-api.ts | TypeScript | 786L | 23 symbols | 2 imports | 55 comments
340
+ > Path: `scripts/lib/recording-extension-api.ts`
341
+ - @brief Implements recording adapters for offline extension registration and replay.
342
+ - @details Provides a minimal pi-compatible extension API plus command-context UI recorder used by the standalone debug harness. The module captures registered commands, registered tools, event handlers, active-tool state, user-message payloads, and UI side effects without invoking the official pi runtime. Runtime cost is O(n) in the number of recorded registrations and side effects. Side effects are limited to in-memory state mutation.
343
+
344
+ ## Imports
345
+ ```
346
+ import path from "node:path";
347
+ import {
348
+ ```
349
+
350
+ ## Definitions
351
+
352
+ - type `export type JsonValue =` (L17)
353
+ - @brief Represents a JSON-compatible serialized value.
354
+ - @details Constrains harness snapshots to deterministic, stringifiable payloads so offline reports remain stable across process boundaries. The alias is compile-time only and introduces no runtime cost.
355
+ ### iface `export interface RecordingSourceInfo` (L29-35)
356
+ - @brief Describes normalized provenance metadata for commands and tools.
357
+ - @details Mirrors the source-information shape documented by the pi SDK while remaining serializable for offline snapshots and parity reports. The interface is compile-time only and introduces no runtime cost.
358
+
359
+ ### iface `export interface RecordingCommandSnapshot` (L41-46)
360
+ - @brief Describes one offline-recorded slash command registration.
361
+ - @details Stores user-visible metadata plus synthesized provenance for deterministic inspection and parity comparison. The interface is compile-time only and introduces no runtime cost.
362
+
363
+ ### iface `export interface RecordingToolSnapshot` (L52-61)
364
+ - @brief Describes one offline-recorded tool registration.
365
+ - @details Stores registration metadata, parameter-schema presence, and normalized provenance while omitting executable function references from serialized output. The interface is compile-time only and introduces no runtime cost.
366
+
367
+ ### iface `export interface RecordedUserMessage` (L67-70)
368
+ - @brief Describes one recorded prompt-delivery payload.
369
+ - @details Preserves serialized content and optional delivery metadata for direct `pi.sendUserMessage(...)` calls and user messages appended during offline new-session setup. The interface is compile-time only and introduces no runtime cost.
370
+
371
+ ### iface `export interface RecordingNotification` (L76-79)
372
+ - @brief Describes one recorded notification side effect.
373
+ - @details Captures the emitted message and severity level from `ctx.ui.notify(...)`. The interface is compile-time only and introduces no runtime cost.
374
+
375
+ ### iface `export interface RecordingStatusUpdate` (L85-88)
376
+ - @brief Describes one recorded status-bar mutation.
377
+ - @details Stores the status key and the written or cleared value from `ctx.ui.setStatus(...)`. The interface is compile-time only and introduces no runtime cost.
378
+
379
+ ### iface `export interface RecordingSelectCall` (L94-98)
380
+ - @brief Describes one recorded `ctx.ui.select(...)` interaction.
381
+ - @details Captures the menu title, offered items, and dequeued scripted response so interactive command replays remain deterministic and auditable. The interface is compile-time only and introduces no runtime cost.
382
+
383
+ ### iface `export interface RecordingInputCall` (L104-108)
384
+ - @brief Describes one recorded `ctx.ui.input(...)` interaction.
385
+ - @details Captures the prompt title, placeholder, and dequeued scripted response so interactive command replays remain deterministic and auditable. The interface is compile-time only and introduces no runtime cost.
386
+
387
+ ### iface `export interface RecordingUiStateSnapshot` (L114-124)
388
+ - @brief Describes the complete UI-side-effect snapshot for one command context.
389
+ - @details Aggregates notifications, statuses, editor mutations, select/input interactions, and unconsumed scripted responses for deterministic replay evidence. The interface is compile-time only and introduces no runtime cost.
390
+
391
+ ### iface `export interface RecordingUiPlan` (L130-133)
392
+ - @brief Describes scripted UI responses supplied to offline command replay.
393
+ - @details Provides FIFO queues for `select` and `input` calls so the harness can execute interactive handlers without a live terminal UI. The interface is compile-time only and introduces no runtime cost.
394
+
395
+ ### iface `export interface RecordingCommandDefinition` (L139-142)
396
+ - @brief Describes the minimal command shape accepted by `registerCommand(...)`.
397
+ - @details Matches the subset of the pi command-registration contract exercised by `src/index.ts`. The interface is compile-time only and introduces no runtime cost.
398
+
399
+ ### iface `export interface RecordingToolDefinition` (L148-163)
400
+ - @brief Describes the minimal tool shape accepted by `registerTool(...)`.
401
+ - @details Matches the subset of the pi tool-registration contract exercised by `src/index.ts` while remaining independent from the official SDK package at compile time. The interface is compile-time only and introduces no runtime cost.
402
+
403
+ ### fn `function toJsonValue(value: unknown): JsonValue | undefined` (L171-188)
404
+ - @brief Serializes arbitrary registration payloads into deterministic JSON-compatible values.
405
+ - @details Uses JSON stringify/parse with function elision and `undefined` normalization so TypeBox schemas and options objects can be embedded in snapshots without executable references. Runtime is O(n) in serialized payload size. No external state is mutated.
406
+ - @param[in] value {unknown} Arbitrary value to serialize.
407
+ - @return {JsonValue | undefined} JSON-compatible copy or `undefined` when the value cannot be represented.
408
+
409
+ ### fn `function normalizeSessionUserMessageContent(message: unknown): JsonValue` (L196-210)
410
+ - @brief Normalizes `SessionManager.appendMessage(...)` payloads into recorder user-message content.
411
+ - @details Collapses single- or multi-part text arrays into one comparable string and preserves non-text payloads as JSON-compatible values. Runtime is O(n) in content size. No external state is mutated.
412
+ - @param[in] message {unknown} Session-manager message payload supplied during `ctx.newSession(...setup)`.
413
+ - @return {JsonValue} Normalized user-message content.
414
+
415
+ ### fn `function buildSourceInfo(extensionPath: string, override?: Partial<RecordingSourceInfo>): RecordingSourceInfo` (L219-228)
416
+ - @brief Builds synthesized provenance metadata for offline registrations.
417
+ - @details Normalizes the extension path and derives project-scoped extension source metadata that approximates the official runtime provenance contract. Runtime is O(p) in path length. No external state is mutated.
418
+ - @param[in] extensionPath {string} Absolute extension entry path.
419
+ - @param[in] override {Partial<RecordingSourceInfo> | undefined} Optional source-info overrides supplied during registration.
420
+ - @return {RecordingSourceInfo} Normalized provenance record.
421
+
422
+ ### fn `function buildBuiltinSourceInfo(name: string): RecordingSourceInfo` (L236-244)
423
+ - @brief Builds synthesized provenance metadata for one builtin tool.
424
+ - @details Produces the stable pseudo-path shape used by pi for builtin tools so extension runtime logic can distinguish builtin inventory entries during offline replay. Runtime is O(1). No external state is mutated.
425
+ - @param[in] name {string} Builtin tool name.
426
+ - @return {RecordingSourceInfo} Normalized builtin provenance record.
427
+
428
+ ### fn `function buildBuiltinToolDefinition(name: string): RecordingToolDefinition & { sourceInfo: RecordingSourceInfo }` (L252-259)
429
+ - @brief Builds one supported builtin tool descriptor for offline inventory queries.
430
+ - @details Creates a minimal tool descriptor containing the builtin name, label, generic description, and synthesized builtin provenance metadata. Runtime is O(1). No external state is mutated.
431
+ - @param[in] name {string} Builtin tool name.
432
+ - @return {RecordingToolDefinition & { sourceInfo: RecordingSourceInfo }} Builtin tool descriptor.
433
+
434
+ ### fn `function formatRecordedThemeForeground(color: string, text: string): string` (L268-270)
435
+ - @brief Encodes one fake themed fragment for offline status capture.
436
+ - @details Wraps the requested color and text in stable XML-like markers so offline replay can preserve color intent in serialized status snapshots without terminal escape sequences. Runtime is O(n) in text length. No external state is mutated.
437
+ - @param[in] color {string} Requested theme color token.
438
+ - @param[in] text {string} Raw text payload.
439
+ - @return {string} Encoded themed fragment.
440
+
441
+ ### fn `function formatRecordedThemeBackgroundFromForeground(color: string, text: string): string` (L281-283)
442
+ - @brief Encodes one fake background fragment derived from a foreground color.
443
+ - @details Wraps the provided text in stable XML-like markers so offline status
444
+ snapshots can preserve context-bar background intent without terminal escape
445
+ sequences. Runtime is O(n) in text length. No external state is mutated.
446
+ - @param[in] color {string} Foreground color reused as synthetic background.
447
+ - @param[in] text {string} Raw text payload.
448
+ - @return {string} Encoded background fragment.
449
+
450
+ ### class `export class RecordingCommandContext` (L289-524)
451
+ - @brief Records UI activity and session-control side effects for one offline command context.
452
+ - @brief Stores the working directory exposed to handlers through `ctx.cwd`.
453
+ - @details Exposes the subset of `ctx.ui` plus command-only session APIs consumed by the extension, including shared settings-menu custom UI replay, dequeues scripted responses for interactive handlers, encodes theme-color output deterministically, and accumulates deterministic side-effect evidence. Runtime is O(1) per UI or session-control operation plus delegated setup cost. Side effects are limited to in-memory state mutation.
454
+ - @details The value is immutable after construction and is consumed by extension code that resolves project-local configuration and prompt paths. Access complexity is O(1).
455
+
456
+ ### iface `export interface RecordingExtensionSnapshot` (L530-536)
457
+ - @brief Aggregates the offline registration snapshot maintained by `RecordingExtensionAPI`.
458
+ - @details Combines command metadata, tool metadata, event names, active tools, and sent user messages for deterministic inspection and parity comparison. The interface is compile-time only and introduces no runtime cost.
459
+
460
+ ### class `export class RecordingExtensionAPI` (L542-786)
461
+ - @brief Records extension registrations and runtime-like mutations for offline replay.
462
+ - @details Implements the subset of the pi extension API exercised by `src/index.ts`, synthesizes provenance metadata, preserves registration order, and exposes lookup helpers for harness commands. Runtime is O(1) per registration or mutation plus payload serialization. Side effects are limited to in-memory state mutation.
463
+
464
+ ## Symbol Index
465
+ |Symbol|Kind|Vis|Lines|Sig|
466
+ |---|---|---|---|---|
467
+ |`JsonValue`|type||17||
468
+ |`RecordingSourceInfo`|iface||29-35|export interface RecordingSourceInfo|
469
+ |`RecordingCommandSnapshot`|iface||41-46|export interface RecordingCommandSnapshot|
470
+ |`RecordingToolSnapshot`|iface||52-61|export interface RecordingToolSnapshot|
471
+ |`RecordedUserMessage`|iface||67-70|export interface RecordedUserMessage|
472
+ |`RecordingNotification`|iface||76-79|export interface RecordingNotification|
473
+ |`RecordingStatusUpdate`|iface||85-88|export interface RecordingStatusUpdate|
474
+ |`RecordingSelectCall`|iface||94-98|export interface RecordingSelectCall|
475
+ |`RecordingInputCall`|iface||104-108|export interface RecordingInputCall|
476
+ |`RecordingUiStateSnapshot`|iface||114-124|export interface RecordingUiStateSnapshot|
477
+ |`RecordingUiPlan`|iface||130-133|export interface RecordingUiPlan|
478
+ |`RecordingCommandDefinition`|iface||139-142|export interface RecordingCommandDefinition|
479
+ |`RecordingToolDefinition`|iface||148-163|export interface RecordingToolDefinition|
480
+ |`toJsonValue`|fn||171-188|function toJsonValue(value: unknown): JsonValue | undefined|
481
+ |`normalizeSessionUserMessageContent`|fn||196-210|function normalizeSessionUserMessageContent(message: unkn...|
482
+ |`buildSourceInfo`|fn||219-228|function buildSourceInfo(extensionPath: string, override?...|
483
+ |`buildBuiltinSourceInfo`|fn||236-244|function buildBuiltinSourceInfo(name: string): RecordingS...|
484
+ |`buildBuiltinToolDefinition`|fn||252-259|function buildBuiltinToolDefinition(name: string): Record...|
485
+ |`formatRecordedThemeForeground`|fn||268-270|function formatRecordedThemeForeground(color: string, tex...|
486
+ |`formatRecordedThemeBackgroundFromForeground`|fn||281-283|function formatRecordedThemeBackgroundFromForeground(colo...|
487
+ |`RecordingCommandContext`|class||289-524|export class RecordingCommandContext|
488
+ |`RecordingExtensionSnapshot`|iface||530-536|export interface RecordingExtensionSnapshot|
489
+ |`RecordingExtensionAPI`|class||542-786|export class RecordingExtensionAPI|
490
+
491
+
492
+ ---
493
+
494
+ # sdk-smoke.ts | TypeScript | 503L | 20 symbols | 4 imports | 21 comments
495
+ > Path: `scripts/lib/sdk-smoke.ts`
496
+ - @brief Implements SDK-parity probing and comparison for the standalone debug harness.
497
+ - @details Dynamically loads the official pi SDK when available, inventories extension-owned commands and tools from the runtime surface, normalizes provenance metadata, and compares the result against the offline recorder snapshot. Runtime is O(c + t) in command and tool counts plus the cost of SDK session creation. Side effects are limited to dynamic module loading, optional SDK-managed filesystem reads, and any extension-owned startup behavior triggered by the official runtime.
498
+
499
+ ## Imports
500
+ ```
501
+ import path from "node:path";
502
+ import { ReqError } from "../../src/core/errors.js";
503
+ import type { JsonValue } from "./recording-extension-api.js";
504
+ import { replaySessionStart, resolveHarnessPaths, type OfflineContractSnapshot } from "./extension-debug-harness.js";
505
+ ```
506
+
507
+ ## Definitions
508
+
509
+ ### iface `export interface NormalizedSourceInfo` (L16-22)
510
+ - @brief Describes normalized provenance metadata used for parity comparison.
511
+ - @details Reduces raw SDK and offline `sourceInfo` payloads to stable path and ownership fields so comparison is deterministic across absolute-path variations. The interface is compile-time only and introduces no runtime cost.
512
+
513
+ ### iface `export interface NormalizedCommandRecord` (L28-32)
514
+ - @brief Describes one normalized command record used by the parity comparator.
515
+ - @details Stores the command name, description, and normalized provenance fields that are stable across offline and SDK inventories. The interface is compile-time only and introduces no runtime cost.
516
+
517
+ ### iface `export interface NormalizedToolRecord` (L38-43)
518
+ - @brief Describes one normalized tool record used by the parity comparator.
519
+ - @details Stores the tool name, description, parameter-schema presence flag, and normalized provenance fields that are stable across offline and SDK inventories. The interface is compile-time only and introduces no runtime cost.
520
+
521
+ ### iface `export interface SdkContractSnapshot` (L49-56)
522
+ - @brief Describes one normalized SDK inventory snapshot.
523
+ - @details Aggregates extension-owned commands, extension-owned tools, active tools, and runtime-shape metadata extracted from the official SDK surface. The interface is compile-time only and introduces no runtime cost.
524
+
525
+ ### iface `export interface ParityMismatch` (L62-76)
526
+ - @brief Describes one parity mismatch emitted by the comparator.
527
+ - @details Records the mismatch category, subject identifier, and normalized offline versus SDK payloads so callers can render deterministic error reports. The interface is compile-time only and introduces no runtime cost.
528
+
529
+ ### iface `export interface SdkSmokeReport` (L82-87)
530
+ - @brief Describes the complete SDK parity smoke result.
531
+ - @details Combines the offline session-start snapshot, normalized SDK snapshot, and mismatch list into one machine-readable report. The interface is compile-time only and introduces no runtime cost.
532
+
533
+ ### iface `interface SdkApiLike` (L93-97)
534
+ - @brief Describes the minimal SDK runtime methods required by the parity probe.
535
+ - @details Uses structural typing so the probe can adapt to minor SDK surface variations without compile-time coupling to package-local types. The interface is compile-time only and introduces no runtime cost.
536
+
537
+ ### fn `function normalizePathValue(value: unknown, projectRoot: string): string | undefined` (L106-119)
538
+ - @brief Normalizes one path relative to the requested project root.
539
+ - @details Converts absolute paths under the project root to slash-normalized relative paths and leaves non-project or pseudo-path values unchanged. Runtime is O(p) in path length. No external state is mutated.
540
+ - @param[in] value {unknown} Candidate path value.
541
+ - @param[in] projectRoot {string} Absolute project root.
542
+ - @return {string | undefined} Normalized path or `undefined` when unavailable.
543
+
544
+ ### fn `export function normalizeSourceInfo(sourceInfo: unknown, projectRoot: string): NormalizedSourceInfo | undefined` (L128-141)
545
+ - @brief Normalizes raw provenance metadata for parity comparison.
546
+ - @details Extracts documented `sourceInfo` fields, normalizes path-like members relative to the requested project root, and drops undefined fields for deterministic deep comparison. Runtime is O(p) in field size. No external state is mutated.
547
+ - @param[in] sourceInfo {unknown} Raw `sourceInfo` value.
548
+ - @param[in] projectRoot {string} Absolute project root.
549
+ - @return {NormalizedSourceInfo | undefined} Normalized provenance record or `undefined`.
550
+
551
+ ### fn `export function normalizeCommandRecord(command: unknown, projectRoot: string): NormalizedCommandRecord | undefined` (L150-163)
552
+ - @brief Normalizes one raw command descriptor.
553
+ - @details Extracts the stable fields required by the parity comparator and trims empty descriptions to `undefined`. Runtime is O(p) in metadata size. No external state is mutated.
554
+ - @param[in] command {unknown} Raw command descriptor.
555
+ - @param[in] projectRoot {string} Absolute project root.
556
+ - @return {NormalizedCommandRecord | undefined} Normalized command record or `undefined` when the payload is invalid.
557
+
558
+ ### fn `export function normalizeToolRecord(tool: unknown, projectRoot: string): NormalizedToolRecord | undefined` (L172-186)
559
+ - @brief Normalizes one raw tool descriptor.
560
+ - @details Extracts the stable fields required by the parity comparator, including only the presence of a parameter schema instead of the raw schema object. Runtime is O(p) in metadata size. No external state is mutated.
561
+ - @param[in] tool {unknown} Raw tool descriptor.
562
+ - @param[in] projectRoot {string} Absolute project root.
563
+ - @return {NormalizedToolRecord | undefined} Normalized tool record or `undefined` when the payload is invalid.
564
+
565
+ ### fn `function extractSdkApi(createAgentSessionResult: unknown): { api: SdkApiLike; runtimeShape: string } | undefined` (L194-216)
566
+ - @brief Selects the first candidate object that exposes the SDK inventory methods.
567
+ - @details Tries several plausible access paths derived from documented return objects and runtime wrappers so the parity probe can tolerate minor SDK surface differences. Runtime is O(k) in candidate count. No external state is mutated.
568
+ - @param[in] createAgentSessionResult {unknown} Raw `createAgentSession(...)` result.
569
+ - @return {{ api: SdkApiLike; runtimeShape: string } | undefined} Matched runtime surface descriptor.
570
+
571
+ ### fn `function isExtensionCommand(command: unknown, projectRoot: string): boolean` (L225-234)
572
+ - @brief Tests whether one normalized command belongs to the target extension.
573
+ - @details Accepts descriptors whose provenance identifies extension ownership and rejects prompt-template or skill commands discovered by the SDK. Runtime is O(1). No external state is mutated.
574
+ - @param[in] command {unknown} Raw SDK command descriptor.
575
+ - @param[in] projectRoot {string} Absolute project root.
576
+ - @return {boolean} `true` when the command belongs to the target extension.
577
+
578
+ ### fn `function isExtensionTool(tool: unknown, projectRoot: string): boolean` (L243-250)
579
+ - @brief Tests whether one normalized tool belongs to the target extension.
580
+ - @details Accepts descriptors whose provenance identifies extension ownership and rejects built-in or SDK-injected tools from the official runtime. Runtime is O(1). No external state is mutated.
581
+ - @param[in] tool {unknown} Raw SDK tool descriptor.
582
+ - @param[in] projectRoot {string} Absolute project root.
583
+ - @return {boolean} `true` when the tool belongs to the target extension.
584
+
585
+ ### fn `function compareCommandInventories(` (L260-300)
586
+ - @brief Compares two command inventories and appends mismatches.
587
+ - @details Detects missing names, differing descriptions, and differing normalized provenance metadata by command name. Runtime is O(n) in combined inventory size. Side effects mutate the mismatch accumulator only.
588
+ - @param[in] offline {NormalizedCommandRecord[]} Offline command inventory.
589
+ - @param[in] sdk {NormalizedCommandRecord[]} SDK command inventory.
590
+ - @param[in,out] mismatches {ParityMismatch[]} Mutable mismatch accumulator.
591
+ - @return {void} No return value.
592
+
593
+ ### fn `function compareToolInventories(` (L310-359)
594
+ - @brief Compares two tool inventories and appends mismatches.
595
+ - @details Detects missing names, differing descriptions, differing parameter-schema presence, and differing normalized provenance metadata by tool name. Runtime is O(n) in combined inventory size. Side effects mutate the mismatch accumulator only.
596
+ - @param[in] offline {NormalizedToolRecord[]} Offline tool inventory.
597
+ - @param[in] sdk {NormalizedToolRecord[]} SDK tool inventory.
598
+ - @param[in,out] mismatches {ParityMismatch[]} Mutable mismatch accumulator.
599
+ - @return {void} No return value.
600
+
601
+ ### fn `function compareActiveTools(offline: string[], sdk: string[], mismatches: ParityMismatch[]): void` (L369-381)
602
+ - @brief Compares offline and SDK active-tool sets after `session_start`.
603
+ - @details Normalizes both arrays as sorted unique sets so parity checks are robust to incidental ordering differences. Runtime is O(n log n) in active-tool count. Side effects mutate the mismatch accumulator only.
604
+ - @param[in] offline {string[]} Offline active-tool names.
605
+ - @param[in] sdk {string[]} SDK active-tool names.
606
+ - @param[in,out] mismatches {ParityMismatch[]} Mutable mismatch accumulator.
607
+ - @return {void} No return value.
608
+
609
+ ### fn `export function buildParityReport(offline: OfflineContractSnapshot, sdk: SdkContractSnapshot): SdkSmokeReport` (L391-413)
610
+ - @brief Builds a parity report from an offline snapshot and an SDK snapshot.
611
+ - @details Normalizes both inventories by name, compares required mismatch categories, and returns an `ok` flag when no mismatches remain. Runtime is O(n log n) in combined inventory size. No external state is mutated.
612
+ - @param[in] offline {OfflineContractSnapshot} Offline session-start snapshot.
613
+ - @param[in] sdk {SdkContractSnapshot} SDK parity snapshot.
614
+ - @return {SdkSmokeReport} Complete parity report.
615
+ - @satisfies REQ-057
616
+
617
+ ### fn `export async function probeSdkRuntime(cwd?: string, extensionPath?: string): Promise<SdkContractSnapshot>` (L424-489)
618
+ - @brief Loads the official pi SDK runtime and extracts the extension-owned command and tool inventories.
619
+ - @details Dynamically imports `@mariozechner/pi-coding-agent`, creates a `DefaultResourceLoader` with the requested extension path, creates an SDK session, extracts inventory methods from the returned runtime surface, and filters to extension-owned commands and tools only. Runtime is dominated by SDK startup. Side effects include SDK-managed resource loading and extension startup behavior.
620
+ - @param[in] cwd {string | undefined} Requested working directory.
621
+ - @param[in] extensionPath {string | undefined} Requested extension entry path.
622
+ - @return {Promise<SdkContractSnapshot>} Normalized SDK inventory snapshot.
623
+ - @throws {ReqError} Throws when the SDK package is unavailable, runtime extraction fails, or session creation fails.
624
+ - @satisfies REQ-050, REQ-056, REQ-058
625
+
626
+ ### fn `export async function runSdkSmoke(cwd?: string, extensionPath?: string): Promise<SdkSmokeReport>` (L499-503)
627
+ - @brief Executes the full SDK parity smoke workflow.
628
+ - @details Replays offline `session_start`, probes the official SDK runtime, and compares the resulting command, tool, provenance, parameter-schema, and active-tool inventories. Runtime is dominated by SDK startup plus offline replay. Side effects include both offline and SDK extension startup behavior.
629
+ - @param[in] cwd {string | undefined} Requested working directory.
630
+ - @param[in] extensionPath {string | undefined} Requested extension entry path.
631
+ - @return {Promise<SdkSmokeReport>} Complete parity smoke result.
632
+ - @satisfies REQ-050, REQ-056, REQ-057, REQ-058
633
+
634
+ ## Symbol Index
635
+ |Symbol|Kind|Vis|Lines|Sig|
636
+ |---|---|---|---|---|
637
+ |`NormalizedSourceInfo`|iface||16-22|export interface NormalizedSourceInfo|
638
+ |`NormalizedCommandRecord`|iface||28-32|export interface NormalizedCommandRecord|
639
+ |`NormalizedToolRecord`|iface||38-43|export interface NormalizedToolRecord|
640
+ |`SdkContractSnapshot`|iface||49-56|export interface SdkContractSnapshot|
641
+ |`ParityMismatch`|iface||62-76|export interface ParityMismatch|
642
+ |`SdkSmokeReport`|iface||82-87|export interface SdkSmokeReport|
643
+ |`SdkApiLike`|iface||93-97|interface SdkApiLike|
644
+ |`normalizePathValue`|fn||106-119|function normalizePathValue(value: unknown, projectRoot: ...|
645
+ |`normalizeSourceInfo`|fn||128-141|export function normalizeSourceInfo(sourceInfo: unknown, ...|
646
+ |`normalizeCommandRecord`|fn||150-163|export function normalizeCommandRecord(command: unknown, ...|
647
+ |`normalizeToolRecord`|fn||172-186|export function normalizeToolRecord(tool: unknown, projec...|
648
+ |`extractSdkApi`|fn||194-216|function extractSdkApi(createAgentSessionResult: unknown)...|
649
+ |`isExtensionCommand`|fn||225-234|function isExtensionCommand(command: unknown, projectRoot...|
650
+ |`isExtensionTool`|fn||243-250|function isExtensionTool(tool: unknown, projectRoot: stri...|
651
+ |`compareCommandInventories`|fn||260-300|function compareCommandInventories(|
652
+ |`compareToolInventories`|fn||310-359|function compareToolInventories(|
653
+ |`compareActiveTools`|fn||369-381|function compareActiveTools(offline: string[], sdk: strin...|
654
+ |`buildParityReport`|fn||391-413|export function buildParityReport(offline: OfflineContrac...|
655
+ |`probeSdkRuntime`|fn||424-489|export async function probeSdkRuntime(cwd?: string, exten...|
656
+ |`runSdkSmoke`|fn||499-503|export async function runSdkSmoke(cwd?: string, extension...|
657
+
658
+
659
+ ---
660
+
661
+ # pi-usereq-debug.sh | Shell | 330L | 15 symbols | 0 imports | 63 comments
662
+ > Path: `scripts/pi-usereq-debug.sh`
663
+
664
+ ## Definitions
665
+
666
+ - var `readonly SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"` (L10)
667
+ - @brief Resolves the absolute directory containing `pi-usereq-debug.sh`.
668
+ - @details Uses `BASH_SOURCE[0]` so invocation through relative paths or symlinks still anchors repository-relative lookups. Runtime is O(p) in path length. No filesystem mutation occurs.
669
+ - var `readonly REPO_ROOT="$(CDPATH= cd -- "${SCRIPT_DIR}/.." && pwd)"` (L14)
670
+ - @brief Resolves the repository root that owns the debug wrapper.
671
+ - @details Moves one level above `SCRIPT_DIR` so delegated Node execution can load the repository-local `tsx` dependency and extension entry. Runtime is O(p) in path length. No filesystem mutation occurs.
672
+ - var `readonly DEFAULT_EXTENSION="${REPO_ROOT}/src/index.ts"` (L18)
673
+ - @brief Stores the default extension entry path used by the wrapper.
674
+ - @details Binds all convenience subcommands to the repository's `src/index.ts` entry unless the caller provides a later `--extension` override. Runtime is O(1). No filesystem mutation occurs.
675
+ - var `readonly CALLER_CWD="${PWD}"` (L22)
676
+ - @brief Stores the caller working directory used as the default debug cwd.
677
+ - @details Captures the shell cwd before the wrapper enters the repository root so replayed commands and tools observe the caller-selected project context. Runtime is O(1). No filesystem mutation occurs.
678
+ - fn `resolve_tsx_binary() {` (L28)
679
+ - @brief Resolves the `tsx` executable visible to the wrapper.
680
+ - @details Searches the active repository install first, then the shared git-common checkout used by worktrees, and finally the process `PATH`. When a shared checkout provides `node_modules`, the function links that directory into the worktree before returning the executable path. Runtime is O(1) plus one git subprocess. Side effects may include creating `REPO_ROOT/node_modules` as a symlink.
681
+ - @return {string} Absolute or PATH-resolved `tsx` executable path.
682
+ - @throws {shell-error} Returns non-zero when no usable `tsx` executable is available.
683
+ - var `readonly TSX_BIN="$(resolve_tsx_binary)"` (L62)
684
+ - @brief Stores the resolved `tsx` executable path.
685
+ - @details Captures the executable once during wrapper startup so later dispatch paths do not repeat repository lookup logic. Runtime is dominated by `resolve_tsx_binary()`. Side effects may include creating a worktree-local `node_modules` symlink.
686
+ - fn `print_usage() {` (L68)
687
+ - @brief Prints the wrapper usage contract.
688
+ - @details Emits subcommand semantics, override rules, and concrete examples covering registrations, session replay, prompt replay, tool replay, and raw pass-through. Runtime is O(1). Side effect: writes to stdout.
689
+ - @return {void} No return value.
690
+ - @satisfies REQ-061, REQ-062, REQ-065
691
+ - fn `contains_exact_option() {` (L109)
692
+ - @brief Tests whether one exact option token is present in an argument list.
693
+ - @details Performs a linear scan over forwarded tokens and returns success when any token equals the requested option string. Runtime is O(n) in argument count. No external state is mutated.
694
+ - @param[in] needle {string} Exact option token to match.
695
+ - @param[in] ... {string[]} Forwarded CLI tokens.
696
+ - @return {int} Shell status `0` when the option exists; `1` otherwise.
697
+ - fn `contains_long_option() {` (L125)
698
+ - @brief Tests whether an argument list already contains any long option token.
699
+ - @details Detects tokens beginning with `--` so the wrapper can avoid inferring positional payloads when the caller is already using the underlying debug-harness option grammar. Runtime is O(n) in argument count. No external state is mutated.
700
+ - @param[in] ... {string[]} Forwarded CLI tokens.
701
+ - @return {int} Shell status `0` when a long option exists; `1` otherwise.
702
+ - fn `normalize_prompt_name() {` (L140)
703
+ - @brief Normalizes prompt aliases to registered `req-*` command names.
704
+ - @details Returns the input unchanged when it already begins with `req-`; otherwise prepends the prefix required by extension registration. Runtime is O(p) in prompt-name length. No external state is mutated.
705
+ - @param[in] prompt_name {string} Prompt command alias supplied by the caller.
706
+ - @return {string} Registered prompt command name.
707
+ - @satisfies REQ-062
708
+ - fn `run_debug_extension() {` (L154)
709
+ - @brief Executes `scripts/debug-extension.ts` with wrapper defaults.
710
+ - @details Enters the repository root so the resolved `tsx` dependency and shared `node_modules` tree remain visible, prepends default `--cwd` and `--extension` values, and forwards all remaining arguments unchanged so later overrides win. Runtime is dominated by the delegated Node process. Side effects include spawning one subprocess.
711
+ - @param[in] ... {string[]} Debug-harness CLI tokens beginning with the target subcommand.
712
+ - @return {int} Exit status produced by the delegated Node process.
713
+ - @satisfies REQ-060, REQ-062
714
+ - fn `build_tool_params_json() {` (L167)
715
+ - @brief Converts wrapper tool `--args` text into a JSON `--params` payload.
716
+ - @details Executes the repository-local TypeScript converter so shell callers can reuse the same structured tool-parameter mapping as the debug interface without hand-writing JSON. Runtime is dominated by the helper subprocess. Side effects include spawning one subprocess.
717
+ - @param[in] tool_name {string} Registered tool name.
718
+ - @param[in] args_text {string} Raw wrapper `--args` payload.
719
+ - @return {string} JSON object serialized on stdout.
720
+ - @satisfies REQ-065
721
+ - fn `forward_tool_subcommand() {` (L182)
722
+ - @brief Replays one tool subcommand with wrapper-level `--args` normalization.
723
+ - @details Preserves direct `--params` passthrough, rewrites wrapper `--args` values into JSON `--params` payloads, forwards unrelated debug-harness options unchanged, and keeps the legacy single-positional-JSON shortcut. Runtime is O(n) in forwarded argument count plus delegated subprocess cost. Side effects include stdout/stderr writes and subprocess execution.
724
+ - @param[in] tool_name {string} Registered tool name.
725
+ - @param[in] ... {string[]} Forwarded wrapper tokens after the tool name.
726
+ - @return {int} Exit status propagated from the delegated harness or local validation.
727
+ - @satisfies REQ-060, REQ-062, REQ-065
728
+ - fn `require_value() {` (L250)
729
+ - @brief Validates that one required subcommand operand is present.
730
+ - @details Emits a deterministic stderr error when the caller omits a required positional name such as a command or tool identifier. Runtime is O(1). Side effect: writes to stderr on failure.
731
+ - @param[in] label {string} Human-readable operand label.
732
+ - @param[in] value {string} Operand value.
733
+ - @return {int} Shell status `0` when the operand exists; `1` otherwise.
734
+ - fn `main() {` (L265)
735
+ - @brief Dispatches wrapper subcommands to the standalone TypeScript harness.
736
+ - @details Implements the convenience grammar documented by `print_usage`, including session and SDK aliases, prompt-name normalization, tool `--args` to `--params` rewriting, default tool params, and raw pass-through mode. Runtime is O(n) in wrapper argument count plus delegated harness cost. Side effects include stdout/stderr writes and subprocess execution.
737
+ - @param[in] ... {string[]} Wrapper CLI arguments excluding the script path.
738
+ - @return {int} Exit status propagated from the delegated harness or local validation.
739
+ - @satisfies REQ-060, REQ-061, REQ-062, REQ-065
740
+ ## Symbol Index
741
+ |Symbol|Kind|Vis|Lines|Sig|
742
+ |---|---|---|---|---|
743
+ |`SCRIPT_DIR`|var||10||
744
+ |`REPO_ROOT`|var||14||
745
+ |`DEFAULT_EXTENSION`|var||18||
746
+ |`CALLER_CWD`|var||22||
747
+ |`resolve_tsx_binary`|fn||28|resolve_tsx_binary()|
748
+ |`TSX_BIN`|var||62||
749
+ |`print_usage`|fn||68|print_usage()|
750
+ |`contains_exact_option`|fn||109|contains_exact_option()|
751
+ |`contains_long_option`|fn||125|contains_long_option()|
752
+ |`normalize_prompt_name`|fn||140|normalize_prompt_name()|
753
+ |`run_debug_extension`|fn||154|run_debug_extension()|
754
+ |`build_tool_params_json`|fn||167|build_tool_params_json()|
755
+ |`forward_tool_subcommand`|fn||182|forward_tool_subcommand()|
756
+ |`require_value`|fn||250|require_value()|
757
+ |`main`|fn||265|main()|
758
+
759
+
760
+ ---
761
+
762
+ # tool-args-to-params.ts | TypeScript | 208L | 7 symbols | 3 imports | 9 comments
763
+ > Path: `scripts/tool-args-to-params.ts`
764
+ - @brief Converts pi-usereq-debug tool `--args` text into the JSON object expected by `--params`.
765
+ - @details Parses the wrapper-only tool-argument grammar, tokenizes shell-style text without invoking a shell, validates the argument shape for the current registered tool set, and emits one compact JSON object for `scripts/pi-usereq-debug.sh`. Runtime is O(n) in argument length. Side effects are limited to stdout and stderr writes.
766
+
767
+ ## Imports
768
+ ```
769
+ import process from "node:process";
770
+ import { ReqError } from "../src/core/errors.js";
771
+ import { shellSplit } from "../src/core/utils.js";
772
+ ```
773
+
774
+ ## Definitions
775
+
776
+ ### iface `interface ParsedToolArgsCli` (L15-19)
777
+ - @brief Describes the normalized CLI request consumed by the tool-argument converter.
778
+ - @details Captures the target tool name, raw `--args` text, and help-mode state for the standalone converter entrypoint. The interface is compile-time only and introduces no runtime side effects.
779
+
780
+ ### fn `function parseCliArgs(argv: string[]): ParsedToolArgsCli` (L39-66)
781
+ - @brief Parses CLI flags for the standalone tool-argument converter.
782
+ - @details Performs one left-to-right scan, records the last `--name` and `--args` values, and ignores unrelated tokens so the wrapper can compose deterministic invocations. Runtime is O(n) in argument count. No external state is mutated.
783
+ - @param[in] argv {string[]} Raw CLI arguments excluding executable and script path.
784
+ - @return {ParsedToolArgsCli} Parsed converter request.
785
+
786
+ ### fn `function takeBooleanFlag(tokens: string[], flag: string): { tokens: string[]; present: boolean }` (L75-86)
787
+ - @brief Removes one boolean flag from a shell-token array.
788
+ - @details Preserves token order for all non-matching items and reports whether the requested flag appeared at least once. Runtime is O(n) in token count. No external state is mutated.
789
+ - @param[in] tokens {string[]} Tokenized `--args` payload.
790
+ - @param[in] flag {string} Flag token to remove.
791
+ - @return {{ tokens: string[]; present: boolean }} Remaining tokens plus presence marker.
792
+
793
+ ### fn `export function buildToolParamsFromArgsText(toolName: string, argsText: string): Record<string, unknown>` (L97-152)
794
+ - @brief Converts one pi-usereq-debug tool `--args` string into a tool-parameter object.
795
+ - @details Tokenizes shell-style text with `shellSplit`, applies tool-specific positional and flag mappings, and rejects unsupported or structurally incomplete argument layouts before wrapper forwarding. Runtime is O(n) in token count. No external state is mutated.
796
+ - @param[in] toolName {string} Registered tool name selected by `scripts/pi-usereq-debug.sh`.
797
+ - @param[in] argsText {string} Raw wrapper `--args` payload.
798
+ - @return {Record<string, unknown>} JSON-serializable tool-parameter object compatible with `--params`.
799
+ - @throws {ReqError} Throws when the selected tool has no supported `--args` mapping or when the token layout is invalid.
800
+ - @satisfies REQ-065
801
+
802
+ ### fn `function writeStdout(text: string): void` (L160-164)
803
+ - @brief Writes non-empty text to stdout.
804
+ - @details Skips zero-length payloads so callers can compose CLI output without duplicate blank writes. Runtime is O(n) in text length. Side effects are limited to stdout writes.
805
+ - @param[in] text {string} Text payload.
806
+ - @return {void} No return value.
807
+
808
+ ### fn `function writeStderr(text: string): void` (L172-177)
809
+ - @brief Writes non-empty text to stderr with a trailing newline.
810
+ - @details Appends a newline when absent and suppresses zero-length payloads. Runtime is O(n) in text length. Side effects are limited to stderr writes.
811
+ - @param[in] text {string} Text payload.
812
+ - @return {void} No return value.
813
+
814
+ ### fn `export async function main(argv = process.argv.slice(2)): Promise<number>` (L187-202)
815
+ - @brief Executes one standalone tool-argument conversion request.
816
+ - @details Parses converter CLI flags, validates the presence of `--name`, transforms wrapper `--args` text into a JSON object, and writes the serialized payload for shell consumption while converting `ReqError` failures into stderr plus exit codes. Runtime is O(n) in argument length. Side effects are limited to stdout and stderr writes.
817
+ - @param[in] argv {string[]} Raw CLI arguments. Defaults to `process.argv.slice(2)`.
818
+ - @return {Promise<number>} Process exit code.
819
+ - @throws {ReqError} Internally catches `ReqError` and returns its exit code.
820
+ - @satisfies REQ-065
821
+
822
+ ## Symbol Index
823
+ |Symbol|Kind|Vis|Lines|Sig|
824
+ |---|---|---|---|---|
825
+ |`ParsedToolArgsCli`|iface||15-19|interface ParsedToolArgsCli|
826
+ |`parseCliArgs`|fn||39-66|function parseCliArgs(argv: string[]): ParsedToolArgsCli|
827
+ |`takeBooleanFlag`|fn||75-86|function takeBooleanFlag(tokens: string[], flag: string):...|
828
+ |`buildToolParamsFromArgsText`|fn||97-152|export function buildToolParamsFromArgsText(toolName: str...|
829
+ |`writeStdout`|fn||160-164|function writeStdout(text: string): void|
830
+ |`writeStderr`|fn||172-177|function writeStderr(text: string): void|
831
+ |`main`|fn||187-202|export async function main(argv = process.argv.slice(2)):...|
832
+
833
+
834
+ ---
835
+
836
+ # cli.ts | TypeScript | 349L | 9 symbols | 5 imports | 9 comments
837
+ > Path: `src/cli.ts`
838
+ - @brief Implements the standalone pi-usereq command-line entry point.
839
+ - @details Parses CLI flags, resolves project configuration, dispatches tool-runner operations, and converts thrown `ReqError` instances into process-style stdout, stderr, and exit codes. Runtime is dominated by the selected subcommand. Side effects include stdout/stderr writes and any filesystem or git operations performed by delegated commands.
840
+
841
+ ## Imports
842
+ ```
843
+ import process from "node:process";
844
+ import { ReqError } from "./core/errors.js";
845
+ import { loadConfig, normalizeConfigPaths, saveConfig, type UseReqConfig } from "./core/config.js";
846
+ import {
847
+ import {
848
+ ```
849
+
850
+ ## Definitions
851
+
852
+ ### iface `interface ParsedArgs` (L43-67)
853
+ - @brief Represents the parsed CLI flag state for one invocation.
854
+ - @details The interface captures every supported command and option in a normalized shape consumed by `main`. It is compile-time only and introduces no runtime cost.
855
+
856
+ ### fn `function parseArgs(argv: string[]): ParsedArgs` (L75-199)
857
+ - @brief Parses raw CLI tokens into a normalized argument object.
858
+ - @details Performs a single left-to-right scan, supports options with variable-length value tails, and records only the last occurrence of scalar flags. Runtime is O(n) in argument count. No external state is mutated.
859
+ - @param[in] argv {string[]} Raw CLI arguments excluding the executable and script path.
860
+ - @return {ParsedArgs} Parsed flag object.
861
+
862
+ ### fn `const takeUntilOption = (start: number): [string[], number] =>` (L77-85)
863
+
864
+ ### fn `function writeStdout(text: string): void` (L207-209)
865
+ - @brief Writes text to stdout when non-empty.
866
+ - @details Avoids emitting zero-length writes so callers can compose result output safely. Runtime is O(n) in text length. Side effect: writes to `process.stdout`.
867
+ - @param[in] text {string} Text to emit.
868
+ - @return {void} No return value.
869
+
870
+ ### fn `function writeStderr(text: string): void` (L217-220)
871
+ - @brief Writes text to stderr and ensures a trailing newline.
872
+ - @details Skips empty input, appends a newline when necessary, and emits the final text to `process.stderr`. Runtime is O(n) in text length. Side effect: writes to `process.stderr`.
873
+ - @param[in] text {string} Text to emit.
874
+ - @return {void} No return value.
875
+
876
+ ### fn `function writeResult(result: { stdout: string; stderr: string; code: number }): number` (L228-232)
877
+ - @brief Emits a tool result object to process streams.
878
+ - @details Writes stdout first, then stderr, and returns the embedded exit code without modification. Runtime is O(n) in total emitted text size. Side effects are stdout/stderr writes.
879
+ - @param[in] result {{ stdout: string; stderr: string; code: number }} Command result payload.
880
+ - @return {number} Exit code to propagate from the invoked command.
881
+
882
+ ### fn `function loadMutableProjectConfig(projectBase: string): { base: string; config: UseReqConfig }` (L241-245)
883
+ - @brief Loads mutable project config state without persisting runtime path metadata.
884
+ - @details Resolves the project base, loads existing config or defaults, normalizes persisted directory fields into project-relative form, and returns the in-memory pair used by CLI mutations. Runtime is dominated by config I/O. Side effects are limited to config reads.
885
+ - @param[in] projectBase {string} Candidate project root path.
886
+ - @return {{ base: string; config: UseReqConfig }} Validated project base and normalized in-memory config.
887
+ - @satisfies REQ-035, REQ-146
888
+
889
+ ### fn `function applyEnableStaticCheckSpecs(projectBase: string, specs: string[]): UseReqConfig` (L256-278)
890
+ - @brief Applies repeatable `--enable-static-check` specifications to project config.
891
+ - @details Parses each specification, validates command-backed entries before persistence, appends only non-duplicate identities in argument order, preserves existing entries, and writes the merged config once after all validations succeed. Runtime is O(s + e) plus PATH probing where s is spec count and e is existing entry count. Side effects include config writes.
892
+ - @param[in] projectBase {string} Candidate project root path.
893
+ - @param[in] specs {string[]} Raw `--enable-static-check` specifications in CLI order.
894
+ - @return {UseReqConfig} Persisted merged project configuration.
895
+ - @throws {ReqError} Throws when parsing or validation fails.
896
+ - @satisfies REQ-035, REQ-036, REQ-037
897
+
898
+ ### fn `export function main(argv = process.argv.slice(2)): number` (L287-345)
899
+ - @brief Executes one pi-usereq CLI invocation.
900
+ - @details Parses arguments, enforces mutually exclusive project-selection rules, normalizes persisted config when needed, dispatches the first matching command handler, and converts thrown `ReqError` instances into stream output plus numeric exit codes. Runtime is O(n) in argument count plus delegated command cost. Side effects include config normalization writes and stdout/stderr output.
901
+ - @param[in] argv {string[]} Raw CLI arguments. Defaults to `process.argv.slice(2)`.
902
+ - @return {number} Process exit code for the invocation.
903
+ - @throws {ReqError} Internally catches `ReqError` and returns its code; other errors are coerced into exit code `1` with stderr output.
904
+
905
+ ## Symbol Index
906
+ |Symbol|Kind|Vis|Lines|Sig|
907
+ |---|---|---|---|---|
908
+ |`ParsedArgs`|iface||43-67|interface ParsedArgs|
909
+ |`parseArgs`|fn||75-199|function parseArgs(argv: string[]): ParsedArgs|
910
+ |`takeUntilOption`|fn||77-85|const takeUntilOption = (start: number): [string[], numbe...|
911
+ |`writeStdout`|fn||207-209|function writeStdout(text: string): void|
912
+ |`writeStderr`|fn||217-220|function writeStderr(text: string): void|
913
+ |`writeResult`|fn||228-232|function writeResult(result: { stdout: string; stderr: st...|
914
+ |`loadMutableProjectConfig`|fn||241-245|function loadMutableProjectConfig(projectBase: string): {...|
915
+ |`applyEnableStaticCheckSpecs`|fn||256-278|function applyEnableStaticCheckSpecs(projectBase: string,...|
916
+ |`main`|fn||287-345|export function main(argv = process.argv.slice(2)): number|
917
+
918
+
919
+ ---
920
+
921
+ # agent-tool-json.ts | TypeScript | 621L | 23 symbols | 7 imports | 24 comments
922
+ > Path: `src/core/agent-tool-json.ts`
923
+ - @brief Builds structured agent-tool JSON payloads for path, git, docs, worktree, and static-check tools.
924
+ - @details Converts extension-tool execution state into deterministic JSON-first payloads optimized for direct LLM traversal. The module normalizes execution metadata, path facts, required-doc status, worktree mutation facts, and static-check file-selection facts without depending on presentation-oriented text. Runtime is O(F) in the number of described files plus path normalization cost. Side effects are limited to filesystem reads.
925
+
926
+ ## Imports
927
+ ```
928
+ import fs from "node:fs";
929
+ import path from "node:path";
930
+ import type { StaticCheckEntry } from "./config.js";
931
+ import type { RuntimePathFacts } from "./path-context.js";
932
+ import { ReqError } from "./errors.js";
933
+ import { STATIC_CHECK_EXT_TO_LANG } from "./static-check.js";
934
+ import type { ToolResult } from "./tool-runner.js";
935
+ ```
936
+
937
+ ## Definitions
938
+
939
+ ### iface `export interface ToolExecutionSection` (L19-27)
940
+ - @brief Describes normalized execution metadata shared by structured tool payloads.
941
+ - @details Separates numeric status, line-oriented diagnostics, and optional raw text so downstream agents can branch on stable fields before consulting residual text. The interface is compile-time only and introduces no runtime cost.
942
+
943
+ ### iface `export interface StructuredToolExecuteResult<T>` (L33-36)
944
+ - @brief Describes the standard execute return wrapper used by structured agent tools.
945
+ - @details Mirrors the same JSON payload into both the text content channel and the machine-readable details channel so agents can consume stable fields without reparsing ad-hoc prose. The interface is compile-time only and introduces no runtime cost.
946
+
947
+ ### iface `export interface PathQueryToolPayload` (L42-58)
948
+ - @brief Describes the structured payload returned by path-query tools.
949
+ - @details Exposes the requested config key, caller cwd, resolved project base, resolved path value, and shared runtime path facts as direct-access fields. The interface is compile-time only and introduces no runtime cost.
950
+
951
+ ### iface `export interface GitCheckToolPayload` (L64-80)
952
+ - @brief Describes the structured payload returned by `git-check`.
953
+ - @details Exposes git-root presence, repository validation status, shared runtime path facts, and normalized execution diagnostics as stable fields. The interface is compile-time only and introduces no runtime cost.
954
+
955
+ ### iface `export interface DocsCheckFileRecord` (L86-94)
956
+ - @brief Describes one canonical-doc status record returned by `docs-check`.
957
+ - @details Binds each required filename to its prompt generator, normalized path facts, and presence status so agents can branch per missing document deterministically. The interface is compile-time only and introduces no runtime cost.
958
+
959
+ ### iface `export interface DocsCheckToolPayload` (L100-116)
960
+ - @brief Describes the structured payload returned by `docs-check`.
961
+ - @details Exposes docs-root selection, per-document presence facts, remediation prompt commands, shared runtime path facts, and execution diagnostics as stable JSON fields. The interface is compile-time only and introduces no runtime cost.
962
+
963
+ ### iface `export interface WorktreeNameToolPayload` (L122-137)
964
+ - @brief Describes the structured payload returned by `git-wt-name`.
965
+ - @details Exposes the generated worktree name, its normative format, shared runtime path facts, and execution diagnostics as direct-access fields. The interface is compile-time only and introduces no runtime cost.
966
+
967
+ ### iface `export interface WorktreeMutationToolPayload` (L143-161)
968
+ - @brief Describes the structured payload returned by worktree mutation tools.
969
+ - @details Exposes the requested operation, exact worktree name, derived worktree path, mutation status, shared runtime path facts, and execution diagnostics as stable JSON fields. The interface is compile-time only and introduces no runtime cost.
970
+
971
+ ### iface `export interface StaticCheckFileRecord` (L167-179)
972
+ - @brief Describes one file-selection record inside a static-check payload.
973
+ - @details Exposes request order, normalized path facts, detected language, configured checker modules, and stable selection status without forcing agents to parse checker output text. The interface is compile-time only and introduces no runtime cost.
974
+
975
+ ### iface `export interface StaticCheckToolPayload` (L185-207)
976
+ - @brief Describes the structured payload returned by static-check agent tools.
977
+ - @details Exposes scope selection, configured checker coverage, per-file selection facts, shared runtime path facts, and normalized execution diagnostics while keeping residual checker text optional under execution. The interface is compile-time only and introduces no runtime cost.
978
+
979
+ ### fn `function formatJsonToolPayload(payload: unknown): string` (L215-217)
980
+ - @brief Serializes one structured payload as pretty-printed JSON.
981
+ - @details Uses two-space indentation and omits a trailing newline so the mirrored text payload remains deterministic and compact. Runtime is O(n) in payload size. No external state is mutated.
982
+ - @param[in] payload {unknown} Structured JSON-compatible payload.
983
+ - @return {string} Pretty-printed JSON text.
984
+
985
+ ### fn `function splitToolOutputLines(text: string): string[]` (L225-228)
986
+ - @brief Splits one stdout or stderr text block into normalized non-empty lines.
987
+ - @details Trims trailing newlines, preserves internal line order, and omits empty records so downstream agents can branch on stable arrays without reparsing blank output. Runtime is O(n) in text length. No external state is mutated.
988
+ - @param[in] text {string} Raw output text.
989
+ - @return {string[]} Normalized non-empty output lines.
990
+
991
+ ### fn `function canonicalizeToolPath(baseDir: string, candidatePath: string): string` (L237-244)
992
+ - @brief Normalizes one path into a canonical slash-separated form relative to the project base when possible.
993
+ - @details Resolves the candidate against the provided base, emits a relative path for in-project targets, and falls back to an absolute slash-normalized path for external targets. Runtime is O(p) in path length. No external state is mutated.
994
+ - @param[in] baseDir {string} Absolute project base path.
995
+ - @param[in] candidatePath {string} Relative or absolute path candidate.
996
+ - @return {string} Canonical slash-normalized path.
997
+
998
+ - fn `export function buildStructuredToolExecuteResult<T extends { execution: ToolExecutionSection }>(` (L252)
999
+ - @brief Converts one structured tool payload into the standard execute wrapper.
1000
+ - @details Mirrors the same payload into `content[0].text` and `details` so agents can use direct JSON fields or raw JSON text interchangeably without divergence. Runtime is O(n) in payload size. No external state is mutated.
1001
+ - @param[in] payload {T} Structured payload containing an `execution` section.
1002
+ - @return {StructuredToolExecuteResult<T>} Standard execute wrapper with mirrored payload.
1003
+ ### fn `export function buildToolExecutionSection(result: ToolResult): ToolExecutionSection` (L267-281)
1004
+ - @brief Converts one raw `ToolResult` into a normalized execution section.
1005
+ - @details Separates numeric exit status, line-oriented stdout/stderr arrays, and optional raw text so downstream agents can consume structured facts before consulting residual text. Runtime is O(n) in output size. No external state is mutated.
1006
+ - @param[in] result {ToolResult} Raw tool result.
1007
+ - @return {ToolExecutionSection} Normalized execution metadata.
1008
+
1009
+ ### fn `export function normalizeToolFailure(error: unknown): ToolResult` (L290-299)
1010
+ - @brief Converts one `ReqError` into a synthetic `ToolResult` for structured payload emission.
1011
+ - @details Preserves the numeric exit code and message in stderr so agent tools can return deterministic JSON even when the underlying runner fails. Non-`ReqError` values are rethrown. Runtime is O(1). No external state is mutated.
1012
+ - @param[in] error {unknown} Thrown value captured from a runner.
1013
+ - @return {ToolResult} Synthetic tool result with empty stdout.
1014
+ - @throws {unknown} Rethrows non-`ReqError` failures unchanged.
1015
+
1016
+ ### fn `export function buildPathQueryToolPayload(` (L312-338)
1017
+ - @brief Builds the structured payload returned by `git-path` or `get-base-path`.
1018
+ - @details Exposes the resolved runtime path value as a direct-access field and preserves normalized execution metadata separately from path facts. Runtime is O(p) in path length. No external state is mutated.
1019
+ - @param[in] toolName {"git-path" | "get-base-path"} Target tool name.
1020
+ - @param[in] workingDirectoryPath {string} Caller working directory.
1021
+ - @param[in] projectBasePath {string} Resolved project base path.
1022
+ - @param[in] resolvedPath {string} Resolved config path value.
1023
+ - @param[in] runtimePaths {RuntimePathFacts} Shared runtime path facts.
1024
+ - @param[in] execution {ToolExecutionSection} Normalized execution metadata.
1025
+ - @return {PathQueryToolPayload} Structured path-query payload.
1026
+
1027
+ ### fn `export function buildGitCheckToolPayload(` (L349-373)
1028
+ - @brief Builds the structured payload returned by `git-check`.
1029
+ - @details Encodes runtime git-root presence plus clean-versus-error status as direct fields while preserving raw diagnostics under execution. Runtime is O(p) in path length. No external state is mutated.
1030
+ - @param[in] projectBasePath {string} Resolved project base path.
1031
+ - @param[in] configuredGitPath {string | undefined} Runtime git root path.
1032
+ - @param[in] runtimePaths {RuntimePathFacts} Shared runtime path facts.
1033
+ - @param[in] execution {ToolExecutionSection} Normalized execution metadata.
1034
+ - @return {GitCheckToolPayload} Structured git-check payload.
1035
+
1036
+ ### fn `export function buildDocsCheckToolPayload(` (L383-433)
1037
+ - @brief Builds the structured payload returned by `docs-check`.
1038
+ - @details Enumerates required canonical documents, binds each missing file to its remediation prompt command, and emits summary counts plus normalized execution metadata. Runtime is O(k) in required file count plus filesystem reads. Side effects are limited to filesystem reads.
1039
+ - @param[in] projectBasePath {string} Resolved project base path.
1040
+ - @param[in] docsDirPath {string} Configured docs directory relative to the project base.
1041
+ - @param[in] runtimePaths {RuntimePathFacts} Shared runtime path facts.
1042
+ - @return {DocsCheckToolPayload} Structured docs-check payload.
1043
+
1044
+ ### fn `export function buildWorktreeNameToolPayload(` (L444-467)
1045
+ - @brief Builds the structured payload returned by `git-wt-name`.
1046
+ - @details Preserves the generated worktree name plus its normative format string as direct-access fields and reports failures through structured execution metadata. Runtime is O(n) in output size. No external state is mutated.
1047
+ - @param[in] projectBasePath {string} Resolved project base path.
1048
+ - @param[in] configuredGitPath {string | undefined} Runtime git root path.
1049
+ - @param[in] runtimePaths {RuntimePathFacts} Shared runtime path facts.
1050
+ - @param[in] execution {ToolExecutionSection} Normalized execution metadata.
1051
+ - @return {WorktreeNameToolPayload} Structured worktree-name payload.
1052
+
1053
+ ### fn `export function buildWorktreeMutationToolPayload(` (L480-514)
1054
+ - @brief Builds the structured payload returned by `git-wt-create` or `git-wt-delete`.
1055
+ - @details Exposes the requested operation, exact worktree name, derived worktree path, and mutation outcome as stable JSON fields while preserving raw diagnostics under execution. Runtime is O(p) in path length. No external state is mutated.
1056
+ - @param[in] toolName {"git-wt-create" | "git-wt-delete"} Target tool name.
1057
+ - @param[in] projectBasePath {string} Resolved project base path.
1058
+ - @param[in] configuredGitPath {string | undefined} Runtime git root path.
1059
+ - @param[in] worktreeName {string} Exact requested worktree name.
1060
+ - @param[in] runtimePaths {RuntimePathFacts} Shared runtime path facts.
1061
+ - @param[in] execution {ToolExecutionSection} Normalized execution metadata.
1062
+ - @return {WorktreeMutationToolPayload} Structured worktree mutation payload.
1063
+
1064
+ ### fn `function buildStaticCheckFileRecord(` (L525-564)
1065
+ - @brief Builds one static-check file-selection record.
1066
+ - @details Resolves filesystem status, detects the configured language by file extension, counts configured checker entries, and emits a stable selection status without parsing checker output text. Runtime is O(p + c) in path length plus configured checker count. Side effects are limited to filesystem reads.
1067
+ - @param[in] inputPath {string} Caller-supplied file path.
1068
+ - @param[in] requestIndex {number} Zero-based request position.
1069
+ - @param[in] projectBasePath {string} Resolved project base path.
1070
+ - @param[in] staticCheckConfig {Record<string, StaticCheckEntry[]>} Effective static-check configuration.
1071
+ - @return {StaticCheckFileRecord} Structured file-selection record.
1072
+
1073
+ ### fn `export function buildStaticCheckToolPayload(` (L580-621)
1074
+ - @brief Builds the structured payload returned by `files-static-check` or `static-check`.
1075
+ - @details Exposes configured checker coverage, per-file selection facts, and normalized execution diagnostics while leaving raw checker output under execution for residual inspection only. Runtime is O(F + C). Side effects are limited to filesystem reads.
1076
+ - @param[in] toolName {"files-static-check" | "static-check"} Target tool name.
1077
+ - @param[in] scope {"explicit-files" | "configured-source-and-test-directories"} Selection scope label.
1078
+ - @param[in] projectBasePath {string} Resolved project base path.
1079
+ - @param[in] requestedPaths {string[]} Explicit or discovered file paths.
1080
+ - @param[in] selectionDirectoryPaths {string[]} Directories that produced the selection.
1081
+ - @param[in] excludedDirectoryPaths {string[]} Directory roots excluded from project selection.
1082
+ - @param[in] staticCheckConfig {Record<string, StaticCheckEntry[]>} Effective static-check configuration.
1083
+ - @param[in] runtimePaths {RuntimePathFacts} Shared runtime path facts.
1084
+ - @param[in] execution {ToolExecutionSection} Normalized execution metadata.
1085
+ - @return {StaticCheckToolPayload} Structured static-check payload.
1086
+
1087
+ ## Symbol Index
1088
+ |Symbol|Kind|Vis|Lines|Sig|
1089
+ |---|---|---|---|---|
1090
+ |`ToolExecutionSection`|iface||19-27|export interface ToolExecutionSection|
1091
+ |`StructuredToolExecuteResult`|iface||33-36|export interface StructuredToolExecuteResult<T>|
1092
+ |`PathQueryToolPayload`|iface||42-58|export interface PathQueryToolPayload|
1093
+ |`GitCheckToolPayload`|iface||64-80|export interface GitCheckToolPayload|
1094
+ |`DocsCheckFileRecord`|iface||86-94|export interface DocsCheckFileRecord|
1095
+ |`DocsCheckToolPayload`|iface||100-116|export interface DocsCheckToolPayload|
1096
+ |`WorktreeNameToolPayload`|iface||122-137|export interface WorktreeNameToolPayload|
1097
+ |`WorktreeMutationToolPayload`|iface||143-161|export interface WorktreeMutationToolPayload|
1098
+ |`StaticCheckFileRecord`|iface||167-179|export interface StaticCheckFileRecord|
1099
+ |`StaticCheckToolPayload`|iface||185-207|export interface StaticCheckToolPayload|
1100
+ |`formatJsonToolPayload`|fn||215-217|function formatJsonToolPayload(payload: unknown): string|
1101
+ |`splitToolOutputLines`|fn||225-228|function splitToolOutputLines(text: string): string[]|
1102
+ |`canonicalizeToolPath`|fn||237-244|function canonicalizeToolPath(baseDir: string, candidateP...|
1103
+ |`buildStructuredToolExecuteResult`|fn||252|export function buildStructuredToolExecuteResult<T extend...|
1104
+ |`buildToolExecutionSection`|fn||267-281|export function buildToolExecutionSection(result: ToolRes...|
1105
+ |`normalizeToolFailure`|fn||290-299|export function normalizeToolFailure(error: unknown): Too...|
1106
+ |`buildPathQueryToolPayload`|fn||312-338|export function buildPathQueryToolPayload(|
1107
+ |`buildGitCheckToolPayload`|fn||349-373|export function buildGitCheckToolPayload(|
1108
+ |`buildDocsCheckToolPayload`|fn||383-433|export function buildDocsCheckToolPayload(|
1109
+ |`buildWorktreeNameToolPayload`|fn||444-467|export function buildWorktreeNameToolPayload(|
1110
+ |`buildWorktreeMutationToolPayload`|fn||480-514|export function buildWorktreeMutationToolPayload(|
1111
+ |`buildStaticCheckFileRecord`|fn||525-564|function buildStaticCheckFileRecord(|
1112
+ |`buildStaticCheckToolPayload`|fn||580-621|export function buildStaticCheckToolPayload(|
1113
+
1114
+
1115
+ ---
1116
+
1117
+ # compress-files.ts | TypeScript | 72L | 2 symbols | 3 imports | 3 comments
1118
+ > Path: `src/core/compress-files.ts`
1119
+ - @brief Compresses explicit source-file lists into compact fenced-markdown excerpts.
1120
+ - @details Bridges file validation, language detection, per-file source compression, and final markdown packaging for prompt consumption. Runtime is O(F + S) where F is file count and S is total source size processed. Side effects are limited to filesystem reads and optional stderr logging.
1121
+
1122
+ ## Imports
1123
+ ```
1124
+ import fs from "node:fs";
1125
+ import path from "node:path";
1126
+ import { compressFileDetailed, detectLanguage } from "./compress.js";
1127
+ ```
1128
+
1129
+ ## Definitions
1130
+
1131
+ ### fn `function formatOutputPath(filePath: string, outputBase?: string): string` (L18-21)
1132
+ - @brief Formats one source path for markdown output.
1133
+ - @details Returns the original file path when no base is provided. Otherwise computes a normalized POSIX-style relative path against the resolved output base. Time complexity is O(p) in path length. No I/O side effects occur.
1134
+ - @param[in] filePath {string} Source file path.
1135
+ - @param[in] outputBase {string | undefined} Optional base directory for relative formatting.
1136
+ - @return {string} Display path used in the markdown header.
1137
+
1138
+ ### fn `export function compressFiles(` (L33-72)
1139
+ - @brief Compresses a list of explicit source files into concatenated markdown sections.
1140
+ - @details Validates file existence, infers each supported language, invokes per-file compression, preserves optional line numbers, and emits one fenced block per successful file. Runtime is O(F + S) where F is file count and S is total processed source size. Side effects are limited to filesystem reads and optional stderr progress logging.
1141
+ - @param[in] filePaths {string[]} Explicit file paths to process.
1142
+ - @param[in] includeLineNumbers {boolean} When `true`, preserve original source line numbers in the emitted code block.
1143
+ - @param[in] verbose {boolean} When `true`, write progress and skip diagnostics to stderr.
1144
+ - @param[in] outputBase {string | undefined} Optional base directory used to shorten output paths.
1145
+ - @return {string} Markdown document containing one section per successfully compressed file.
1146
+ - @throws {Error} Throws when no valid source files can be processed.
1147
+
1148
+ ## Symbol Index
1149
+ |Symbol|Kind|Vis|Lines|Sig|
1150
+ |---|---|---|---|---|
1151
+ |`formatOutputPath`|fn||18-21|function formatOutputPath(filePath: string, outputBase?: ...|
1152
+ |`compressFiles`|fn||33-72|export function compressFiles(|
1153
+
1154
+
1155
+ ---
1156
+
1157
+ # compress-payload.ts | TypeScript | 648L | 22 symbols | 5 imports | 23 comments
1158
+ > Path: `src/core/compress-payload.ts`
1159
+ - @brief Builds agent-oriented JSON payloads for `files-compress` and `compress`.
1160
+ - @details Converts compression results into deterministic JSON sections ordered for LLM traversal, including request metadata, repository scope, structured file metrics, structured compressed lines, symbols, and Doxygen fields. Runtime is O(F log F + S) where F is file count and S is total source size. Side effects are limited to filesystem reads and optional stderr logging.
1161
+
1162
+ ## Imports
1163
+ ```
1164
+ import fs from "node:fs";
1165
+ import path from "node:path";
1166
+ import {
1167
+ import { compressFileDetailed, detectLanguage, type CompressedLineEntry } from "./compress.js";
1168
+ import {
1169
+ ```
1170
+
1171
+ ## Definitions
1172
+
1173
+ - type `export type CompressToolScope = "explicit-files" | "configured-source-directories";` (L27)
1174
+ - @brief Enumerates supported compression-payload scopes.
1175
+ - @details Distinguishes explicit-file requests from configured project scans while preserving one stable JSON contract. The alias is compile-time only and introduces no runtime cost.
1176
+ - type `export type CompressFileStatus = "compressed" | "error" | "skipped";` (L33)
1177
+ - @brief Enumerates supported per-file compression statuses.
1178
+ - @details Separates compressed files, hard failures, and skipped inputs so downstream agents can branch without reparsing stderr text. The alias is compile-time only and introduces no runtime cost.
1179
+ - type `export type CompressLineNumberMode = "enabled" | "disabled";` (L39)
1180
+ - @brief Enumerates the rendered line-number mode for compression output.
1181
+ - @details Distinguishes payloads whose display strings include original source line numbers from payloads whose display strings contain plain compressed text only. The alias is compile-time only and introduces no runtime cost.
1182
+ - type `export type CompressSymbolAnalysisStatus = "analyzed" | "error" | "not_attempted";` (L45)
1183
+ - @brief Enumerates structured symbol-analysis statuses for compressed files.
1184
+ - @details Separates successful symbol extraction from supplementary analysis failures so compression can still succeed when analyzer enrichment is unavailable. The alias is compile-time only and introduces no runtime cost.
1185
+ ### iface `export interface CompressLineRange` (L51-55)
1186
+ - @brief Describes one numeric line range.
1187
+ - @details Exposes start and end line numbers plus the same inclusive range as a numeric tuple for direct agent access. The interface is compile-time only and introduces no runtime cost.
1188
+
1189
+ ### iface `export interface CompressToolLineEntry` (L61-66)
1190
+ - @brief Describes one structured compressed line entry in the tool payload.
1191
+ - @details Preserves output order, original source coordinates, raw compressed text, and rendered display text so agents can choose between normalized data and user-facing rendering without reparsing strings. The interface is compile-time only and introduces no runtime cost.
1192
+
1193
+ ### iface `export interface CompressToolSymbolEntry extends CompressLineRange` : CompressLineRange (L72-87)
1194
+ - @brief Describes one structured symbol record inside the compression payload.
1195
+ - @details Orders direct-access identity fields before hierarchy, locations, and Doxygen metadata so agents can branch without reparsing compressed source text. The interface is compile-time only and introduces no runtime cost.
1196
+
1197
+ ### iface `export interface CompressToolFileEntry extends CompressLineRange` : CompressLineRange (L93-120)
1198
+ - @brief Describes one per-file compression payload entry.
1199
+ - @details Stores path identity, compression metrics, rendered line-number mode, optional file-level and symbol-level metadata, structured compressed lines, and stable failure facts. The interface is compile-time only and introduces no runtime cost.
1200
+
1201
+ ### iface `export interface CompressToolRequestSection` (L126-136)
1202
+ - @brief Describes the request section of the compression payload.
1203
+ - @details Captures tool identity, scope, base directory, line-number mode, requested inputs, and configured source-directory scope so agents can reason about how the file set was selected. The interface is compile-time only and introduces no runtime cost.
1204
+
1205
+ ### iface `export interface CompressToolSummarySection` (L142-153)
1206
+ - @brief Describes the summary section of the compression payload.
1207
+ - @details Exposes aggregate file, line, symbol, and Doxygen counts as numeric fields with explicit unit names so agents can branch on totals without reparsing display strings. The interface is compile-time only and introduces no runtime cost.
1208
+
1209
+ ### iface `export interface CompressToolRepositorySection` (L159-164)
1210
+ - @brief Describes the repository section of the compression payload.
1211
+ - @details Stores the base path, configured source-directory scope, and canonical file list used during compression. The interface is compile-time only and introduces no runtime cost.
1212
+
1213
+ ### iface `export interface CompressToolPayload` (L170-175)
1214
+ - @brief Describes the full agent-oriented compression payload.
1215
+ - @details Orders the top-level sections as request, summary, repository, and files so execution metadata can be appended deterministically by the tool wrapper. The interface is compile-time only and introduces no runtime cost.
1216
+
1217
+ ### iface `export interface BuildCompressToolPayloadOptions` (L181-189)
1218
+ - @brief Describes the options required to build one compression payload.
1219
+ - @details Supplies tool identity, scope, base directory, requested paths, line-number mode, and optional configured source directories while keeping payload construction deterministic. The interface is compile-time only and introduces no runtime cost.
1220
+
1221
+ ### fn `function canonicalizeCompressionPath(targetPath: string, baseDir: string): string` (L198-206)
1222
+ - @brief Canonicalizes one filesystem path relative to the payload base directory.
1223
+ - @details Emits a slash-normalized relative path when the target is under the base directory; otherwise emits the normalized absolute path. Runtime is O(p) in path length. No side effects occur.
1224
+ - @param[in] targetPath {string} Absolute or relative filesystem path.
1225
+ - @param[in] baseDir {string} Base directory used for relative canonicalization.
1226
+ - @return {string} Canonicalized path string.
1227
+
1228
+ ### fn `function buildLineRange(startLineNumber: number, endLineNumber: number): CompressLineRange` (L215-221)
1229
+ - @brief Builds one structured line-range record.
1230
+ - @details Duplicates the inclusive range as start, end, and tuple fields so callers can address whichever shape is most convenient. Runtime is O(1). No side effects occur.
1231
+ - @param[in] startLineNumber {number} Inclusive start line number.
1232
+ - @param[in] endLineNumber {number} Inclusive end line number.
1233
+ - @return {CompressLineRange} Structured line-range record.
1234
+
1235
+ ### fn `function resolveSymbolName(element: SourceElement): string` (L229-231)
1236
+ - @brief Resolves one stable symbol name from an analyzed element.
1237
+ - @details Prefers explicit analyzer name metadata, then falls back to the derived signature or the first source line so every symbol retains a direct-access identifier. Runtime is O(1). No side effects occur.
1238
+ - @param[in] element {SourceElement} Source element.
1239
+ - @return {string} Stable symbol name.
1240
+
1241
+ ### fn `function resolveParentElement(definitions: SourceElement[], child: SourceElement): SourceElement | undefined` (L240-249)
1242
+ - @brief Resolves the direct parent element for one child symbol.
1243
+ - @details Matches by parent name plus inclusive line containment and chooses the deepest enclosing definition. Runtime is O(n) in definition count. No side effects occur.
1244
+ - @param[in] definitions {SourceElement[]} Sorted definition elements.
1245
+ - @param[in] child {SourceElement} Candidate child symbol.
1246
+ - @return {SourceElement | undefined} Matched parent definition when available.
1247
+
1248
+ ### fn `function mapCompressedLines(compressedLines: CompressedLineEntry[]): CompressToolLineEntry[]` (L257-264)
1249
+ - @brief Maps structured compression lines into the payload line-entry contract.
1250
+ - @details Performs a shallow field copy so the payload remains decoupled from the core compression result type. Runtime is O(n) in compressed line count. No side effects occur.
1251
+ - @param[in] compressedLines {CompressedLineEntry[]} Structured compression lines.
1252
+ - @return {CompressToolLineEntry[]} Payload line entries.
1253
+
1254
+ ### fn `function analyzeCompressedFileSymbols(` (L276-360)
1255
+ - @brief Builds structured symbol entries for one successfully analyzed file.
1256
+ - @details Extracts definition elements, computes parent-child relationships, attaches structured Doxygen metadata, and repeats the canonical file path inside each symbol record for direct-access agent indexing. Runtime is O(n log n) in definition count. No side effects occur.
1257
+ - @param[in] analyzer {SourceAnalyzer} Shared analyzer instance.
1258
+ - @param[in] absolutePath {string} Absolute file path.
1259
+ - @param[in] canonicalPath {string} Canonical path emitted in the payload.
1260
+ - @param[in] languageId {string} Canonical language identifier.
1261
+ - @return {{ languageName: string | undefined; symbols: CompressToolSymbolEntry[]; fileDoxygen: StructuredDoxygenFields | undefined; fileDescriptionText: string | undefined; doxygenFieldCount: number }} Structured symbol-analysis result.
1262
+ - @throws {Error} Throws when source analysis or enrichment fails.
1263
+
1264
+ ### fn `function analyzeCompressFile(` (L374-505)
1265
+ - @brief Analyzes one path into a structured compression file entry.
1266
+ - @details Resolves path identity, performs compression, attempts supplementary symbol and Doxygen extraction, preserves stable skip or error reasons, and keeps compression success independent from symbol-analysis success. Runtime is dominated by file I/O and analyzer cost. Side effects are limited to filesystem reads and optional stderr logging.
1267
+ - @param[in] analyzer {SourceAnalyzer} Shared analyzer instance.
1268
+ - @param[in] inputPath {string} Caller-supplied path.
1269
+ - @param[in] absolutePath {string} Absolute path resolved against the payload base directory.
1270
+ - @param[in] requestIndex {number} Caller-order index.
1271
+ - @param[in] baseDir {string} Base directory used for canonical path derivation.
1272
+ - @param[in] includeLineNumbers {boolean} When `true`, rendered compressed text includes original source line numbers.
1273
+ - @param[in] verbose {boolean} When `true`, emit per-file diagnostics to stderr.
1274
+ - @return {CompressToolFileEntry} Structured file entry.
1275
+
1276
+ ### fn `export function buildCompressToolPayload(options: BuildCompressToolPayloadOptions): CompressToolPayload` (L514-628)
1277
+ - @brief Builds the full agent-oriented compression payload.
1278
+ - @details Validates requested paths against the filesystem, compresses processable files in caller order, preserves skipped and failed inputs in structured file entries, computes aggregate numeric totals, and emits repository scope metadata. Runtime is O(F log F + S). Side effects are limited to filesystem reads and optional stderr logging.
1279
+ - @param[in] options {BuildCompressToolPayloadOptions} Payload-construction options.
1280
+ - @return {CompressToolPayload} Structured compression payload ordered as request, summary, repository, and files.
1281
+ - @satisfies REQ-081, REQ-082, REQ-083, REQ-084, REQ-085, REQ-087
1282
+
1283
+ ### fn `export function buildCompressToolExecutionStderr(payload: CompressToolPayload): string` (L637-648)
1284
+ - @brief Builds execution diagnostics for one compression payload.
1285
+ - @details Serializes skipped inputs, hard compression failures, and supplementary symbol-analysis warnings into stable stderr lines while keeping successful compressed files silent. Runtime is O(n) in issue count. No side effects occur.
1286
+ - @param[in] payload {CompressToolPayload} Structured compression payload.
1287
+ - @return {string} Newline-delimited execution diagnostics.
1288
+ - @satisfies REQ-087
1289
+
1290
+ ## Symbol Index
1291
+ |Symbol|Kind|Vis|Lines|Sig|
1292
+ |---|---|---|---|---|
1293
+ |`CompressToolScope`|type||27||
1294
+ |`CompressFileStatus`|type||33||
1295
+ |`CompressLineNumberMode`|type||39||
1296
+ |`CompressSymbolAnalysisStatus`|type||45||
1297
+ |`CompressLineRange`|iface||51-55|export interface CompressLineRange|
1298
+ |`CompressToolLineEntry`|iface||61-66|export interface CompressToolLineEntry|
1299
+ |`CompressToolSymbolEntry`|iface||72-87|export interface CompressToolSymbolEntry extends Compress...|
1300
+ |`CompressToolFileEntry`|iface||93-120|export interface CompressToolFileEntry extends CompressLi...|
1301
+ |`CompressToolRequestSection`|iface||126-136|export interface CompressToolRequestSection|
1302
+ |`CompressToolSummarySection`|iface||142-153|export interface CompressToolSummarySection|
1303
+ |`CompressToolRepositorySection`|iface||159-164|export interface CompressToolRepositorySection|
1304
+ |`CompressToolPayload`|iface||170-175|export interface CompressToolPayload|
1305
+ |`BuildCompressToolPayloadOptions`|iface||181-189|export interface BuildCompressToolPayloadOptions|
1306
+ |`canonicalizeCompressionPath`|fn||198-206|function canonicalizeCompressionPath(targetPath: string, ...|
1307
+ |`buildLineRange`|fn||215-221|function buildLineRange(startLineNumber: number, endLineN...|
1308
+ |`resolveSymbolName`|fn||229-231|function resolveSymbolName(element: SourceElement): string|
1309
+ |`resolveParentElement`|fn||240-249|function resolveParentElement(definitions: SourceElement[...|
1310
+ |`mapCompressedLines`|fn||257-264|function mapCompressedLines(compressedLines: CompressedLi...|
1311
+ |`analyzeCompressedFileSymbols`|fn||276-360|function analyzeCompressedFileSymbols(|
1312
+ |`analyzeCompressFile`|fn||374-505|function analyzeCompressFile(|
1313
+ |`buildCompressToolPayload`|fn||514-628|export function buildCompressToolPayload(options: BuildCo...|
1314
+ |`buildCompressToolExecutionStderr`|fn||637-648|export function buildCompressToolExecutionStderr(payload:...|
1315
+
1316
+
1317
+ ---
1318
+
1319
+ # compress.ts | TypeScript | 464L | 13 symbols | 3 imports | 17 comments
1320
+ > Path: `src/core/compress.ts`
1321
+ - @brief Removes comments and redundant whitespace from source code while preserving semantic structure.
1322
+ - @details Provides extension-based language detection and language-aware source compression backed by analyzer language specs. Runtime is linear in processed source size. Side effects are limited to filesystem reads in file-based helpers.
1323
+
1324
+ ## Imports
1325
+ ```
1326
+ import fs from "node:fs";
1327
+ import path from "node:path";
1328
+ import { buildLanguageSpecs } from "./source-analyzer.js";
1329
+ ```
1330
+
1331
+ ## Definitions
1332
+
1333
+ ### iface `export interface CompressedLineEntry` (L57-62)
1334
+ - @brief Describes one structured compressed output line.
1335
+ - @details Separates source coordinates, output order, raw compressed text, and rendered display text so downstream JSON payloads can expose line facts without reparsing prefixed strings. The interface is compile-time only and introduces no runtime cost.
1336
+
1337
+ ### iface `export interface CompressedSourceResult` (L68-79)
1338
+ - @brief Describes one structured compression result.
1339
+ - @details Exposes language identity, source line metrics, removed-line totals, structured compressed lines, and the final rendered excerpt text so CLI and agent-tool layers can share one canonical compression model. The interface is compile-time only and introduces no runtime cost.
1340
+
1341
+ ### fn `function getSpecs()` (L86-89)
1342
+ - @brief Returns the cached language specification table.
1343
+ - @details Initializes the cache on first access by calling `buildLanguageSpecs`, then reuses the result for all subsequent calls. Time complexity is O(1) after cold start. Mutates module-local cache state only.
1344
+ - @return {ReturnType<typeof buildLanguageSpecs>} Cached language specification map.
1345
+
1346
+ ### fn `export function detectLanguage(filePath: string): string | undefined` (L97-99)
1347
+ - @brief Infers a compression language from a file path extension.
1348
+ - @details Lowercases the file extension and looks it up in `EXT_LANG_MAP`. Time complexity is O(1). No I/O side effects occur.
1349
+ - @param[in] filePath {string} Source file path.
1350
+ - @return {string | undefined} Canonical compression language identifier, or `undefined` when unsupported.
1351
+
1352
+ ### fn `function countLogicalLines(content: string): number` (L107-113)
1353
+ - @brief Counts logical lines in one text payload.
1354
+ - @details Counts newline separators while treating a trailing newline as line termination instead of an extra empty logical line. Runtime is O(n) in text length. No side effects occur.
1355
+ - @param[in] content {string} Source text.
1356
+ - @return {number} Logical line count; `0` for empty content.
1357
+
1358
+ ### fn `function isInString(line: string, pos: number, stringDelimiters: string[]): boolean` (L123-158)
1359
+ - @brief Tests whether a character position falls inside a string literal.
1360
+ - @details Scans the line left-to-right while tracking active string delimiters and escaped quote characters. Runtime is O(n) in inspected prefix length. No side effects occur.
1361
+ - @param[in] line {string} Source line to inspect.
1362
+ - @param[in] pos {number} Zero-based character position.
1363
+ - @param[in] stringDelimiters {string[]} Supported string delimiters for the language.
1364
+ - @return {boolean} `true` when the position is inside a string literal.
1365
+
1366
+ ### fn `function removeInlineComment(line: string, singleComment: string | undefined, stringDelimiters: string[]): string` (L168-208)
1367
+ - @brief Removes a trailing single-line comment from a source line.
1368
+ - @details Scans the line while respecting string literals so comment markers inside strings are preserved. Runtime is O(n) in line length. No external state is mutated.
1369
+ - @param[in] line {string} Source line to strip.
1370
+ - @param[in] singleComment {string | undefined} Language single-line comment marker.
1371
+ - @param[in] stringDelimiters {string[]} Supported string delimiters for the language.
1372
+ - @return {string} Line content before the first real comment marker.
1373
+
1374
+ ### fn `function buildCompressedLineEntry(` (L219-231)
1375
+ - @brief Builds one rendered compressed line entry.
1376
+ - @details Materializes both the raw compressed text and the display text that optionally prefixes the original source line number. Runtime is O(n) in line length. No side effects occur.
1377
+ - @param[in] text {string} Compressed source text for one retained line.
1378
+ - @param[in] sourceLineNumber {number} Original source line number.
1379
+ - @param[in] compressedLineNumber {number} One-based output line number inside the compressed excerpt.
1380
+ - @param[in] includeLineNumbers {boolean} When `true`, prefix the display text with the original source line number.
1381
+ - @return {CompressedLineEntry} Structured compressed line entry.
1382
+
1383
+ ### fn `function formatCompressedSourceText(entries: CompressedLineEntry[]): string` (L239-241)
1384
+ - @brief Formats compressed line entries as newline-delimited text.
1385
+ - @details Joins pre-rendered display lines without adding headers, fences, or other presentation artifacts. Runtime is O(n) in entry count and aggregate content length. No side effects occur.
1386
+ - @param[in] entries {CompressedLineEntry[]} Structured compressed line entries.
1387
+ - @return {string} Final compressed source text.
1388
+
1389
+ ### fn `export function compressSourceDetailed(source: string, language: string, includeLineNumbers = true): CompressedSourceResult` (L252-420)
1390
+ - @brief Compresses in-memory source text into the structured compression model.
1391
+ - @details Removes blank lines and comments, preserves shebangs, respects string-literal boundaries, retains leading indentation for indentation-significant languages, and emits both structured line entries and a rendered text excerpt. Runtime is O(n) in source length. No external state is mutated.
1392
+ - @param[in] source {string} Raw source text.
1393
+ - @param[in] language {string} Canonical compression language identifier.
1394
+ - @param[in] includeLineNumbers {boolean} When `true`, prefix rendered text lines with original source line numbers.
1395
+ - @return {CompressedSourceResult} Structured compression result.
1396
+ - @throws {Error} Throws when the language is unsupported.
1397
+
1398
+ ### fn `export function compressSource(source: string, language: string, includeLineNumbers = true): string` (L431-433)
1399
+ - @brief Compresses in-memory source text for one language.
1400
+ - @details Delegates to `compressSourceDetailed(...)` and returns only the rendered compressed source text so legacy CLI and markdown-oriented paths keep their existing behavior. Runtime is O(n) in source length. No external state is mutated.
1401
+ - @param[in] source {string} Raw source text.
1402
+ - @param[in] language {string} Canonical compression language identifier.
1403
+ - @param[in] includeLineNumbers {boolean} When `true`, include original line-number prefixes in the output.
1404
+ - @return {string} Compressed source text.
1405
+ - @throws {Error} Throws when the language is unsupported.
1406
+
1407
+ ### fn `export function compressFileDetailed(filePath: string, language?: string, includeLineNumbers = true): CompressedSourceResult` (L444-451)
1408
+ - @brief Compresses one source file from disk into the structured compression model.
1409
+ - @details Detects the language when not supplied, reads the file as UTF-8, and delegates to `compressSourceDetailed(...)`. Runtime is O(n) in file size. Side effects are limited to filesystem reads.
1410
+ - @param[in] filePath {string} Source file path.
1411
+ - @param[in] language {string | undefined} Optional explicit language override.
1412
+ - @param[in] includeLineNumbers {boolean} When `true`, prefix rendered text lines with original source line numbers.
1413
+ - @return {CompressedSourceResult} Structured compression result.
1414
+ - @throws {Error} Throws when the language cannot be detected or the file cannot be read.
1415
+
1416
+ ### fn `export function compressFile(filePath: string, language?: string, includeLineNumbers = true): string` (L462-464)
1417
+ - @brief Compresses one source file from disk.
1418
+ - @details Delegates to `compressFileDetailed(...)` and returns only the rendered compressed source text so CLI and markdown emitters can retain their established text contract. Runtime is O(n) in file size. Side effects are limited to filesystem reads.
1419
+ - @param[in] filePath {string} Source file path.
1420
+ - @param[in] language {string | undefined} Optional explicit language override.
1421
+ - @param[in] includeLineNumbers {boolean} When `true`, include original line-number prefixes in the output.
1422
+ - @return {string} Compressed source text.
1423
+ - @throws {Error} Throws when the language cannot be detected or the file cannot be read.
1424
+
1425
+ ## Symbol Index
1426
+ |Symbol|Kind|Vis|Lines|Sig|
1427
+ |---|---|---|---|---|
1428
+ |`CompressedLineEntry`|iface||57-62|export interface CompressedLineEntry|
1429
+ |`CompressedSourceResult`|iface||68-79|export interface CompressedSourceResult|
1430
+ |`getSpecs`|fn||86-89|function getSpecs()|
1431
+ |`detectLanguage`|fn||97-99|export function detectLanguage(filePath: string): string ...|
1432
+ |`countLogicalLines`|fn||107-113|function countLogicalLines(content: string): number|
1433
+ |`isInString`|fn||123-158|function isInString(line: string, pos: number, stringDeli...|
1434
+ |`removeInlineComment`|fn||168-208|function removeInlineComment(line: string, singleComment:...|
1435
+ |`buildCompressedLineEntry`|fn||219-231|function buildCompressedLineEntry(|
1436
+ |`formatCompressedSourceText`|fn||239-241|function formatCompressedSourceText(entries: CompressedLi...|
1437
+ |`compressSourceDetailed`|fn||252-420|export function compressSourceDetailed(source: string, la...|
1438
+ |`compressSource`|fn||431-433|export function compressSource(source: string, language: ...|
1439
+ |`compressFileDetailed`|fn||444-451|export function compressFileDetailed(filePath: string, la...|
1440
+ |`compressFile`|fn||462-464|export function compressFile(filePath: string, language?:...|
1441
+
1442
+
1443
+ ---
1444
+
1445
+ # config.ts | TypeScript | 272L | 9 symbols | 7 imports | 13 comments
1446
+ > Path: `src/core/config.ts`
1447
+ - @brief Loads, normalizes, and persists pi-usereq project configuration.
1448
+ - @details Defines the configuration schema, default directory conventions, JSON serialization helpers, and prompt placeholder expansion paths. Runtime is dominated by filesystem reads and writes plus linear normalization over configured entries. Side effects include config-file persistence under `.pi-usereq`.
1449
+
1450
+ ## Imports
1451
+ ```
1452
+ import fs from "node:fs";
1453
+ import path from "node:path";
1454
+ import { ReqError } from "./errors.js";
1455
+ import {
1456
+ import {
1457
+ import { normalizeEnabledPiUsereqTools } from "./pi-usereq-tools.js";
1458
+ import { makeRelativeIfContainsProject } from "./utils.js";
1459
+ ```
1460
+
1461
+ ## Definitions
1462
+
1463
+ ### iface `export interface StaticCheckEntry` (L32-36)
1464
+ - @brief Describes one static-check module configuration entry.
1465
+ - @details Each record identifies the checker module and optional command or parameter list used during per-language static analysis dispatch. The interface is type-only and has no runtime cost.
1466
+
1467
+ ### iface `export interface UseReqConfig` (L42-56)
1468
+ - @brief Defines the persisted pi-usereq project configuration schema.
1469
+ - @details Captures documentation paths, source/test directory selection, static-check configuration, enabled startup tools, and notification settings while excluding runtime-derived path metadata. The interface is compile-time only and introduces no runtime side effects.
1470
+
1471
+ ### fn `export function getProjectConfigPath(projectBase: string): string` (L80-82)
1472
+ - @brief Computes the per-project config file path.
1473
+ - @details Joins the project base with `.pi-usereq/config.json`, producing the canonical persistence location used by CLI and extension code. Time complexity is O(1). No I/O side effects occur.
1474
+ - @param[in] projectBase {string} Absolute project root path.
1475
+ - @return {string} Absolute config file path.
1476
+
1477
+ ### fn `export function getDefaultConfig(_projectBase: string): UseReqConfig` (L91-107)
1478
+ - @brief Builds the default project configuration.
1479
+ - @details Populates canonical docs/test/source directories, the default startup tool set, and default pi-notify fields while excluding runtime-derived path metadata. Time complexity is O(n) in default tool count. No filesystem side effects occur.
1480
+ - @param[in] projectBase {string} Absolute project root path.
1481
+ - @return {UseReqConfig} Fresh default configuration object.
1482
+ - @satisfies CTN-001, CTN-012, REQ-066, REQ-146
1483
+
1484
+ ### fn `export function loadConfig(projectBase: string): UseReqConfig` (L117-167)
1485
+ - @brief Loads and sanitizes the persisted project configuration.
1486
+ - @details Returns defaults when the config file does not exist. Otherwise parses JSON, validates directory and static-check field shapes, normalizes enabled tool names and pi-notify fields, and ignores removed or runtime-derived path metadata. Runtime is O(n) in config size. Side effects are limited to filesystem reads.
1487
+ - @param[in] projectBase {string} Absolute project root path.
1488
+ - @return {UseReqConfig} Sanitized effective configuration.
1489
+ - @throws {ReqError} Throws with exit code `11` when the config file contains invalid JSON or a non-object payload.
1490
+ - @satisfies CTN-012, REQ-066, REQ-146
1491
+
1492
+ ### fn `function buildPersistedConfig(config: UseReqConfig): UseReqConfig` (L176-201)
1493
+ - @brief Builds the persisted configuration payload that excludes runtime-derived fields.
1494
+ - @details Copies only the canonical persisted configuration keys into a fresh object so runtime-derived metadata such as `base-path` and `git-path` can never be written to disk. Runtime is O(n) in config size. No external state is mutated.
1495
+ - @param[in] config {UseReqConfig} Effective configuration object.
1496
+ - @return {UseReqConfig} Persistable configuration payload.
1497
+ - @satisfies CTN-012, REQ-146
1498
+
1499
+ ### fn `export function saveConfig(projectBase: string, config: UseReqConfig): void` (L211-215)
1500
+ - @brief Persists the project configuration to disk.
1501
+ - @details Creates the parent `.pi-usereq` directory when necessary, strips runtime-derived fields from the serialized payload, and writes formatted JSON terminated by a newline. Runtime is O(n) in serialized config size. Side effects include directory creation and file overwrite.
1502
+ - @param[in] projectBase {string} Absolute project root path.
1503
+ - @param[in] config {UseReqConfig} Configuration object to persist.
1504
+ - @return {void} No return value.
1505
+ - @satisfies CTN-012, REQ-146
1506
+
1507
+ ### fn `export function normalizeConfigPaths(projectBase: string, config: UseReqConfig): UseReqConfig` (L224-234)
1508
+ - @brief Normalizes persisted directory fields to project-relative forms.
1509
+ - @details Rewrites docs, tests, and source directories using project containment heuristics, strips trailing separators, and restores defaults for empty results. Runtime is O(n) in configured path count plus path-length processing. No filesystem writes occur.
1510
+ - @param[in] projectBase {string} Absolute project root path.
1511
+ - @param[in] config {UseReqConfig} Configuration object to normalize.
1512
+ - @return {UseReqConfig} Normalized configuration copy.
1513
+
1514
+ ### fn `export function buildPromptReplacementPaths(projectBase: string, config: UseReqConfig): Record<string, string>` (L244-272)
1515
+ - @brief Builds placeholder replacements for bundled prompt rendering.
1516
+ - @details Computes runtime path context from the execution path, derives installation-owned template and guideline paths, enumerates visible guideline files from the installed resource tree, and returns the token map consumed by prompt templates. Runtime is O(g log g + s) where g is guideline count and s is source-directory count. Side effects are limited to filesystem reads.
1517
+ - @param[in] projectBase {string} Absolute project root path.
1518
+ - @param[in] config {UseReqConfig} Effective project configuration.
1519
+ - @return {Record<string, string>} Placeholder-to-string replacement map including runtime path tokens.
1520
+ - @satisfies REQ-002, REQ-103, REQ-106, REQ-107, CTN-011
1521
+
1522
+ ## Symbol Index
1523
+ |Symbol|Kind|Vis|Lines|Sig|
1524
+ |---|---|---|---|---|
1525
+ |`StaticCheckEntry`|iface||32-36|export interface StaticCheckEntry|
1526
+ |`UseReqConfig`|iface||42-56|export interface UseReqConfig|
1527
+ |`getProjectConfigPath`|fn||80-82|export function getProjectConfigPath(projectBase: string)...|
1528
+ |`getDefaultConfig`|fn||91-107|export function getDefaultConfig(_projectBase: string): U...|
1529
+ |`loadConfig`|fn||117-167|export function loadConfig(projectBase: string): UseReqCo...|
1530
+ |`buildPersistedConfig`|fn||176-201|function buildPersistedConfig(config: UseReqConfig): UseR...|
1531
+ |`saveConfig`|fn||211-215|export function saveConfig(projectBase: string, config: U...|
1532
+ |`normalizeConfigPaths`|fn||224-234|export function normalizeConfigPaths(projectBase: string,...|
1533
+ |`buildPromptReplacementPaths`|fn||244-272|export function buildPromptReplacementPaths(projectBase: ...|
1534
+
1535
+
1536
+ ---
1537
+
1538
+ # doxygen-parser.ts | TypeScript | 318L | 13 symbols | 0 imports | 19 comments
1539
+ > Path: `src/core/doxygen-parser.ts`
1540
+ - @brief Parses repository-approved Doxygen tags and renders them as markdown bullets.
1541
+ - @details Implements a constrained Doxygen grammar used by the source analyzer and construct finder. Parsing cost is linear in comment length. The module is pure and performs no I/O.
1542
+
1543
+ ## Definitions
1544
+
1545
+ - type `export type DoxygenFieldMap = Record<string, string[]>;` (L62)
1546
+ - @brief Represents parsed Doxygen fields grouped by normalized tag name.
1547
+ - @details Each key maps to one or more textual payloads because the same tag may appear multiple times in a single comment. The alias is compile-time only and adds no runtime cost.
1548
+ - type `export type StructuredDoxygenParamDirection = "in" | "out" | "in,out" | "unspecified";` (L68)
1549
+ - @brief Enumerates supported structured parameter directions.
1550
+ - @details Normalizes `
1551
+ - @param ` direction modifiers into one small closed set so agents can branch on parameter flow without reparsing raw tag names. The alias is compile-time only and introduces no runtime cost.
1552
+ ### iface `export interface StructuredDoxygenParameterEntry` (L74-80)
1553
+ - @brief Describes one structured Doxygen parameter field.
1554
+ - @details Separates parameter direction, optional parameter name, optional declared type, and residual text so agents can access argument contracts without reparsing monolithic tag strings. The interface is compile-time only and introduces no runtime cost.
1555
+
1556
+ ### iface `export interface StructuredDoxygenFields` (L86-101)
1557
+ - @brief Describes the structured Doxygen field contract used by LLM-oriented JSON payloads.
1558
+ - @details Converts repeated raw tag strings into tag-specific arrays and specialized parameter records while keeping unsplittable residual text local to the affected field. The interface is compile-time only and introduces no runtime cost.
1559
+
1560
+ ### fn `export function parseDoxygenComment(commentText: string): DoxygenFieldMap` (L109-142)
1561
+ - @brief Parses repository-approved Doxygen fields from one comment block.
1562
+ - @details Normalizes line endings, strips comment delimiters, locates supported tags, and accumulates tag payloads in declaration order. Unsupported content is ignored. Runtime is O(n) in comment length. No side effects occur.
1563
+ - @param[in] commentText {string} Raw comment text including delimiters.
1564
+ - @return {DoxygenFieldMap} Parsed tag payloads keyed by normalized tag name.
1565
+
1566
+ ### fn `export function stripCommentDelimiters(text: string): string` (L150-166)
1567
+ - @brief Removes language comment delimiters from raw comment text.
1568
+ - @details Drops standalone opening and closing markers, strips leading comment prefixes on each line, and preserves semantic payload lines only. Runtime is O(n) in line count. No external state is mutated.
1569
+ - @param[in] text {string} Raw comment text.
1570
+ - @return {string} Cleaned multi-line payload without delimiter syntax.
1571
+
1572
+ ### fn `export function normalizeWhitespace(text: string): string` (L174-190)
1573
+ - @brief Collapses redundant whitespace while preserving paragraph boundaries.
1574
+ - @details Converts repeated spaces to single spaces, trims each line, and reduces multiple blank lines to one blank separator. Runtime is O(n) in text length. No side effects occur.
1575
+ - @param[in] text {string} Input text to normalize.
1576
+ - @return {string} Canonically spaced text.
1577
+
1578
+ ### fn `export function formatDoxygenFieldsAsMarkdown(doxygenFields: DoxygenFieldMap): string[]` (L198-207)
1579
+ - @brief Serializes parsed Doxygen fields into markdown bullet lines.
1580
+ - @details Iterates over `DOXYGEN_TAGS` in canonical order and emits one `- @tag value` line for every stored payload. Runtime is O(t + v) where t is tag count and v is total values. No side effects occur.
1581
+ - @param[in] doxygenFields {DoxygenFieldMap} Parsed Doxygen field map.
1582
+ - @return {string[]} Ordered markdown bullet lines.
1583
+
1584
+ ### fn `export function countDoxygenFieldValues(doxygenFields: DoxygenFieldMap): number` (L215-217)
1585
+ - @brief Counts the total number of parsed Doxygen field values.
1586
+ - @details Sums the value-array lengths across all tags so payload builders can expose aggregate Doxygen density as a numeric fact. Runtime is O(t) in tag count. No side effects occur.
1587
+ - @param[in] doxygenFields {DoxygenFieldMap} Parsed Doxygen fields.
1588
+ - @return {number} Total stored Doxygen value count.
1589
+
1590
+ ### fn `function structureDoxygenParameterValue(value: string, direction: StructuredDoxygenParamDirection): StructuredDoxygenParameterEntry` (L226-228)
1591
+ - @brief Parses one raw Doxygen parameter value into structured fields.
1592
+ - @details Supports the repository-preferred `name {type} description` form, the alternate `{type} name description` form, and a residual-text fallback when no safe split is possible. Runtime is O(n) in value length. No side effects occur.
1593
+ - @param[in] value {string} Raw Doxygen parameter value.
1594
+ - @param[in] direction {StructuredDoxygenParamDirection} Normalized parameter direction.
1595
+ - @return {StructuredDoxygenParameterEntry} Structured parameter record.
1596
+
1597
+ ### fn `function splitCommaSeparatedDoxygenValues(values: string[] | undefined): string[]` (L264-269)
1598
+ - @brief Splits comma-delimited Doxygen value strings into normalized items.
1599
+ - @details Trims surrounding whitespace, drops empty segments, and preserves original declaration order. Runtime is O(n) in aggregate text length. No side effects occur.
1600
+ - @param[in] values {string[] | undefined} Raw Doxygen value strings.
1601
+ - @return {string[]} Normalized item list.
1602
+
1603
+ ### fn `function extractSatisfiedRequirementIds(values: string[] | undefined): string[]` (L277-280)
1604
+ - @brief Extracts normalized requirement IDs from raw `
1605
+ - @details Matches repository requirement ID prefixes directly from the raw value text so agents receive requirement links as a dedicated string array. Runtime is O(n) in aggregate text length. No side effects occur.
1606
+ - @param[in] values {string[] | undefined} Raw `
1607
+ - @return {string[]} Normalized requirement IDs in declaration order.
1608
+ - @satisfies ` values.
1609
+ - @satisfies ` values.
1610
+
1611
+ ### fn `export function structureDoxygenFields(doxygenFields: DoxygenFieldMap): StructuredDoxygenFields` (L289-318)
1612
+ - @brief Converts raw parsed Doxygen fields into the structured JSON contract.
1613
+ - @details Reorders raw tags into tag-specific arrays, structures parameter fields, normalizes `
1614
+ - @param[in] doxygenFields {DoxygenFieldMap} Raw parsed Doxygen field map.
1615
+ - @return {StructuredDoxygenFields} Structured Doxygen fields.
1616
+ - @see ` aliases, and extracts requirement IDs from `
1617
+ - @satisfies `. Runtime is O(t + v) where t is tag count and v is total value count. No side effects occur.
1618
+ - @satisfies REQ-078
1619
+
1620
+ ## Symbol Index
1621
+ |Symbol|Kind|Vis|Lines|Sig|
1622
+ |---|---|---|---|---|
1623
+ |`DoxygenFieldMap`|type||62||
1624
+ |`StructuredDoxygenParamDirection`|type||68||
1625
+ |`StructuredDoxygenParameterEntry`|iface||74-80|export interface StructuredDoxygenParameterEntry|
1626
+ |`StructuredDoxygenFields`|iface||86-101|export interface StructuredDoxygenFields|
1627
+ |`parseDoxygenComment`|fn||109-142|export function parseDoxygenComment(commentText: string):...|
1628
+ |`stripCommentDelimiters`|fn||150-166|export function stripCommentDelimiters(text: string): string|
1629
+ |`normalizeWhitespace`|fn||174-190|export function normalizeWhitespace(text: string): string|
1630
+ |`formatDoxygenFieldsAsMarkdown`|fn||198-207|export function formatDoxygenFieldsAsMarkdown(doxygenFiel...|
1631
+ |`countDoxygenFieldValues`|fn||215-217|export function countDoxygenFieldValues(doxygenFields: Do...|
1632
+ |`structureDoxygenParameterValue`|fn||226-228|function structureDoxygenParameterValue(value: string, di...|
1633
+ |`splitCommaSeparatedDoxygenValues`|fn||264-269|function splitCommaSeparatedDoxygenValues(values: string[...|
1634
+ |`extractSatisfiedRequirementIds`|fn||277-280|function extractSatisfiedRequirementIds(values: string[] ...|
1635
+ |`structureDoxygenFields`|fn||289-318|export function structureDoxygenFields(doxygenFields: Dox...|
1636
+
1637
+
1638
+ ---
1639
+
1640
+ # errors.ts | TypeScript | 31L | 1 symbols | 0 imports | 4 comments
1641
+ > Path: `src/core/errors.ts`
1642
+ - @brief Defines the repository-specific error class used by CLI and extension workflows.
1643
+ - @details Centralizes deterministic failure signaling by pairing an error message with a numeric exit code. The module is pure and performs no I/O. Access complexity is O(1).
1644
+
1645
+ ## Definitions
1646
+
1647
+ ### class `export class ReqError extends Error` : Error (L11-31)
1648
+ - @brief Represents a useReq failure with a stable numeric exit code.
1649
+ - @brief Stores the process-style exit code associated with the failure.
1650
+ - @details Extends `Error` so callers can propagate human-readable diagnostics together with process-style status codes. Construction and property access are O(1). State mutation is limited to the created instance.
1651
+ - @details Downstream CLI and extension handlers read this field to decide the final command status. Access complexity is O(1). The field is assigned during construction.
1652
+
1653
+ ## Symbol Index
1654
+ |Symbol|Kind|Vis|Lines|Sig|
1655
+ |---|---|---|---|---|
1656
+ |`ReqError`|class||11-31|export class ReqError extends Error|
1657
+
1658
+
1659
+ ---
1660
+
1661
+ # extension-status.ts | TypeScript | 660L | 30 symbols | 4 imports | 30 comments
1662
+ > Path: `src/core/extension-status.ts`
1663
+ - @brief Tracks pi-usereq extension status state and renders status-bar telemetry.
1664
+ - @details Centralizes hook interception, context-usage snapshots, run timing,
1665
+ and deterministic status-bar formatting for the pi-usereq extension. Runtime
1666
+ is O(1) per event plus O(s) in configured source-path count during status
1667
+ rendering. Side effects are limited to in-memory state mutation and interval
1668
+ scheduling through exported controller helpers.
1669
+
1670
+ ## Imports
1671
+ ```
1672
+ import type {
1673
+ import type { UseReqConfig } from "./config.js";
1674
+ import { formatPiNotifyBeepStatus } from "./pi-notify.js";
1675
+ import { formatAbsoluteGitPath, formatBasePathRelativeToGitPath, resolveRuntimeGitPath } from "./runtime-project-paths.js";
1676
+ ```
1677
+
1678
+ ## Definitions
1679
+
1680
+ - type `type StatusForegroundColor = Extract<` (L27)
1681
+ - @brief Enumerates the CLI-supported theme tokens consumed by status rendering.
1682
+ - @details Restricts the status formatter to documented pi theme tokens so the
1683
+ status bar remains compatible with the active CLI theme schema. Compile-time
1684
+ only and introduces no runtime cost.
1685
+ ### iface `interface RawStatusTheme` (L38-42)
1686
+ - @brief Describes the raw theme capabilities required for status rendering.
1687
+ - @details Accepts the `ctx.ui.theme` foreground renderer plus optional helpers
1688
+ that can convert a foreground color into a background-styled fragment for the
1689
+ context-usage bar. Compile-time only and introduces no runtime cost.
1690
+
1691
+ ### iface `interface StatusThemeAdapter` (L50-58)
1692
+ - @brief Describes the normalized theme adapter used by status formatters.
1693
+ - @details Exposes deterministic label, value, foreground, background, and
1694
+ context-cell renderers so status text generation stays independent from the
1695
+ raw theme API. Compile-time only and introduces no runtime cost.
1696
+
1697
+ ### iface `interface ContextUsageOverlaySpec` (L66-70)
1698
+ - @brief Describes one fixed-width context-bar overlay.
1699
+ - @details Stores the literal text plus foreground and background color roles
1700
+ used when the context bar must render threshold-specific labels instead of
1701
+ block glyphs. Compile-time only and introduces no runtime cost.
1702
+
1703
+ - type `export type PiUsereqStatusHookName = (typeof PI_USEREQ_STATUS_HOOK_NAMES)[number];` (L113)
1704
+ - @brief Represents one hook name handled by the pi-usereq status controller.
1705
+ - @details Narrows hook registration and event-update calls to the canonical
1706
+ intercepted-hook set. Compile-time only and introduces no runtime cost.
1707
+ ### iface `export interface PiUsereqStatusState` (L122-126)
1708
+ - @brief Stores the mutable runtime facts displayed by the status bar.
1709
+ - @details Persists the latest context-usage snapshot, the active run start
1710
+ timestamp, and the most recent normally completed run duration. Runtime state
1711
+ is mutated in-place by controller helpers. Compile-time only and introduces
1712
+ no runtime cost.
1713
+
1714
+ ### iface `export interface PiUsereqStatusController` (L135-141)
1715
+ - @brief Stores the controller state required for event-driven status updates.
1716
+ - @details Keeps the mutable status snapshot, the current configuration, the
1717
+ latest extension context used for rendering, the active-tools provider, and
1718
+ the interval handle used for live elapsed-time refreshes. Compile-time only
1719
+ and introduces no runtime cost.
1720
+
1721
+ ### fn `function convertForegroundAnsiToBackgroundAnsi(` (L151-159)
1722
+ - @brief Converts a foreground ANSI sequence into the equivalent background ANSI.
1723
+ - @details Supports the standard `38;` foreground prefix emitted by pi themes.
1724
+ Returns `undefined` when the input cannot be transformed deterministically.
1725
+ Runtime is O(n) in ANSI sequence length. No external state is mutated.
1726
+ - @param[in] foregroundAnsi {string} Foreground ANSI sequence.
1727
+ - @return {string | undefined} Background ANSI sequence when derivable.
1728
+
1729
+ ### fn `function applyForegroundAsBackground(` (L172-189)
1730
+ - @brief Applies a foreground-derived background style to one text fragment.
1731
+ - @details Prefers a theme-provided `bgFromFg` encoder for deterministic test
1732
+ rendering and falls back to ANSI conversion when the runtime theme exposes
1733
+ `getFgAnsi`. Runtime is O(n) in fragment length. No external state is
1734
+ mutated.
1735
+ - @param[in] theme {RawStatusTheme} Raw theme adapter.
1736
+ - @param[in] color {StatusForegroundColor} Foreground color reused as background.
1737
+ - @param[in] text {string} Already-colored foreground fragment.
1738
+ - @return {string} Background-decorated text fragment.
1739
+
1740
+ ### fn `function createStatusThemeAdapter(theme: RawStatusTheme): StatusThemeAdapter` (L200-220)
1741
+ - @brief Builds the normalized theme adapter used by pi-usereq status formatters.
1742
+ - @details Precomputes label, value, foreground, background, separator, and
1743
+ context-cell renderers so status formatting remains stable across real TUI
1744
+ themes and deterministic test doubles. Runtime is O(1). No external state
1745
+ is mutated.
1746
+ - @param[in] theme {RawStatusTheme} Raw theme implementation from `ctx.ui.theme`.
1747
+ - @return {StatusThemeAdapter} Normalized status-theme adapter.
1748
+
1749
+ ### fn `const colorize = (color: StatusForegroundColor, text: string): string =>` (L201-219)
1750
+
1751
+ ### fn `const backgroundize = (color: StatusForegroundColor, text: string): string =>` (L203-219)
1752
+
1753
+ ### fn `function normalizeContextUsage(` (L230-247)
1754
+ - @brief Normalizes one raw context-usage snapshot.
1755
+ - @details Preserves the runtime token and context-window counts, derives a
1756
+ percentage when the runtime omits it, and clamps percentages into `[0, 100]`.
1757
+ Runtime is O(1). No external state is mutated.
1758
+ - @param[in] contextUsage {ContextUsage | undefined} Raw runtime snapshot.
1759
+ - @return {ContextUsage | undefined} Normalized snapshot.
1760
+
1761
+ ### fn `function refreshContextUsage(` (L259-264)
1762
+ - @brief Refreshes the stored context-usage snapshot from the active extension context.
1763
+ - @details Calls `ctx.getContextUsage()` on every intercepted event so the
1764
+ controller retains the newest context-usage facts available from the pi
1765
+ runtime. Runtime is O(1). Side effect: mutates `state.contextUsage`.
1766
+ - @param[in] ctx {ExtensionContext} Active extension context.
1767
+ - @param[in,out] state {PiUsereqStatusState} Mutable status state.
1768
+ - @return {void} No return value.
1769
+ - @satisfies REQ-118, REQ-119
1770
+
1771
+ ### fn `function countFilledContextCells(` (L275-283)
1772
+ - @brief Counts the filled cells rendered by the 5-cell context bar.
1773
+ - @details Uses ceiling semantics for positive percentages so any non-zero
1774
+ usage occupies at least one cell and zero usage occupies none. Runtime is
1775
+ O(1). No external state is mutated.
1776
+ - @param[in] contextUsage {ContextUsage | undefined} Normalized context snapshot.
1777
+ - @return {number} Filled-cell count in the inclusive range `[0, 5]`.
1778
+ - @satisfies REQ-122
1779
+
1780
+ ### fn `function resolveContextUsageOverlay(` (L295-314)
1781
+ - @brief Resolves the threshold-specific context-bar overlay when required.
1782
+ - @details Returns the empty-state `CLEAR` overlay when normalized context
1783
+ usage is unavailable or non-positive and returns the high-water `FULL!`
1784
+ overlay with the active theme `error` token when usage exceeds 90 percent.
1785
+ Runtime is O(1). No external state is mutated.
1786
+ - @param[in] contextUsage {ContextUsage | undefined} Normalized context snapshot.
1787
+ - @return {ContextUsageOverlaySpec | undefined} Overlay spec when a replacement label is required.
1788
+ - @satisfies REQ-127, REQ-128
1789
+
1790
+ ### fn `function formatContextUsageOverlay(` (L327-335)
1791
+ - @brief Formats one threshold-specific context-bar overlay.
1792
+ - @details Renders the fixed-width overlay text with the requested foreground
1793
+ color and reuses the selected bar color as the background so the bar width
1794
+ and state-specific backdrop remain preserved. Runtime is O(n) in overlay
1795
+ width. No external state is mutated.
1796
+ - @param[in] theme {StatusThemeAdapter} Normalized status theme.
1797
+ - @param[in] overlay {ContextUsageOverlaySpec} Overlay specification.
1798
+ - @return {string} Rendered overlay text.
1799
+ - @satisfies REQ-127, REQ-128
1800
+
1801
+ ### fn `function formatContextUsageBar(` (L349-361)
1802
+ - @brief Formats one 5-cell context-usage bar.
1803
+ - @details Renders threshold-specific overlays for empty and high-water states;
1804
+ otherwise renders filled cells with the theme `warning` token on an
1805
+ accent-derived background and unfilled cells in `dim` on the same background
1806
+ to preserve constant bar width. Runtime is O(1). No external state is
1807
+ mutated.
1808
+ - @param[in] theme {StatusThemeAdapter} Normalized status theme.
1809
+ - @param[in] contextUsage {ContextUsage | undefined} Normalized context snapshot.
1810
+ - @return {string} Rendered 5-cell bar or overlay.
1811
+ - @satisfies REQ-121, REQ-122, REQ-126, REQ-127, REQ-128
1812
+
1813
+ ### fn `function formatStatusDuration(durationMs: number): string` (L372-377)
1814
+ - @brief Formats one elapsed-duration value as `M:SS`.
1815
+ - @details Floors the input to whole seconds, keeps minutes unbounded above 59,
1816
+ and zero-pads seconds to two digits. Runtime is O(1). No external state is
1817
+ mutated.
1818
+ - @param[in] durationMs {number} Duration in milliseconds.
1819
+ - @return {string} Duration rendered as `M:SS`.
1820
+ - @satisfies REQ-125
1821
+
1822
+ ### fn `function formatStatusField(` (L388-394)
1823
+ - @brief Formats one standard status-bar field.
1824
+ - @details Renders the field label in accent color and the value in warning
1825
+ color. Runtime is O(n) in combined text length. No external state is mutated.
1826
+ - @param[in] theme {StatusThemeAdapter} Normalized status theme.
1827
+ - @param[in] fieldName {string} Field label emitted before the colon.
1828
+ - @param[in] value {string} Unstyled field value.
1829
+ - @return {string} Rendered status-field fragment.
1830
+
1831
+ ### fn `function formatRenderedStatusField(` (L406-412)
1832
+ - @brief Formats one pre-rendered status-bar field value.
1833
+ - @details Preserves the accent-colored field label while allowing callers to
1834
+ provide a custom styled value such as the context-usage bar. Runtime is O(n)
1835
+ in combined text length. No external state is mutated.
1836
+ - @param[in] theme {StatusThemeAdapter} Normalized status theme.
1837
+ - @param[in] fieldName {string} Field label emitted before the colon.
1838
+ - @param[in] renderedValue {string} Pre-rendered field value.
1839
+ - @return {string} Rendered status-field fragment.
1840
+
1841
+ ### fn `function didAgentEndAbort(messages: AgentEndEvent["messages"]): boolean` (L423-430)
1842
+ - @brief Detects whether an agent run ended through abort semantics.
1843
+ - @details Treats any assistant message whose `stopReason` equals `aborted` as
1844
+ an escape-triggered termination that must not overwrite the `last` timer.
1845
+ Runtime is O(n) in message count. No external state is mutated.
1846
+ - @param[in] messages {AgentEndEvent["messages"]} Messages emitted by `agent_end`.
1847
+ - @return {boolean} `true` when the run ended in aborted state.
1848
+ - @satisfies REQ-125
1849
+
1850
+ ### fn `function buildPiUsereqStatusText(` (L444-481)
1851
+ - @brief Builds the full single-line pi-usereq status-bar payload.
1852
+ - @details Renders git, base, docs, tests, src, tools, context, elapsed, last, beep, and sound fields in the canonical order with dim bullet separators and threshold-specific context-bar overlays. Runtime is O(s) in configured source-path count plus runtime git probing. No external state is mutated.
1853
+ - @param[in] cwd {string} Runtime working directory used for git/base path derivation.
1854
+ - @param[in] config {UseReqConfig} Effective project configuration.
1855
+ - @param[in] activeTools {readonly string[]} Active runtime tool names.
1856
+ - @param[in] theme {StatusThemeAdapter} Normalized status theme.
1857
+ - @param[in] state {PiUsereqStatusState} Mutable status state snapshot.
1858
+ - @param[in] nowMs {number} Current wall-clock time in milliseconds.
1859
+ - @return {string} Single-line status-bar text.
1860
+ - @satisfies REQ-109, REQ-112, REQ-120, REQ-121, REQ-123, REQ-124, REQ-125, REQ-126, REQ-127, REQ-128, REQ-135, REQ-136, REQ-147, REQ-148, REQ-156
1861
+
1862
+ ### fn `function stopStatusTicker(controller: PiUsereqStatusController): void` (L491-496)
1863
+ - @brief Stops the live elapsed-time ticker when it is active.
1864
+ - @details Clears the interval handle and resets the stored timer reference so
1865
+ subsequent runs can reinitialize live status refreshes deterministically.
1866
+ Runtime is O(1). Side effect: mutates `controller.tickHandle`.
1867
+ - @param[in,out] controller {PiUsereqStatusController} Mutable status controller.
1868
+ - @return {void} No return value.
1869
+
1870
+ ### fn `function syncPiUsereqStatusTicker(` (L508-524)
1871
+ - @brief Synchronizes the live elapsed-time ticker with the current run state.
1872
+ - @details Starts a 1-second render ticker while a run is active and stops the
1873
+ ticker when the run returns to idle. Runtime is O(1). Side effects include
1874
+ interval creation, interval disposal, and footer-status mutation on timer
1875
+ ticks.
1876
+ - @param[in,out] controller {PiUsereqStatusController} Mutable status controller.
1877
+ - @return {void} No return value.
1878
+ - @satisfies REQ-123
1879
+
1880
+ ### fn `export function createPiUsereqStatusController(` (L535-549)
1881
+ - @brief Creates an empty pi-usereq status controller.
1882
+ - @details Initializes the mutable status snapshot, stores the active-tools
1883
+ provider used by render-time tool counting, and starts with no config, no
1884
+ context, and no live ticker. Runtime is O(1). No external state is mutated.
1885
+ - @param[in] getActiveTools {() => readonly string[]} Provider for active tools.
1886
+ - @return {PiUsereqStatusController} New status controller.
1887
+ - @satisfies DES-010
1888
+
1889
+ ### fn `export function setPiUsereqStatusConfig(` (L561-566)
1890
+ - @brief Stores the effective project configuration used by status rendering.
1891
+ - @details Replaces the controller's cached configuration so later status
1892
+ renders reuse the latest docs, tests, source-path, and pi-notify values
1893
+ without reading from disk on every event. Runtime is O(1). Side effect:
1894
+ mutates `controller.config`.
1895
+ - @param[in] config {UseReqConfig} Effective project configuration.
1896
+ - @param[in,out] controller {PiUsereqStatusController} Mutable status controller.
1897
+ - @return {void} No return value.
1898
+
1899
+ ### fn `export function renderPiUsereqStatus(` (L579-599)
1900
+ - @brief Renders the current pi-usereq status bar into the active UI context.
1901
+ - @details Updates the controller's latest context pointer and writes the
1902
+ single-line status text only when configuration is available, including any
1903
+ threshold-specific context-bar overlays. Runtime is O(s) in configured
1904
+ source-path count. Side effect: mutates `ctx.ui` status.
1905
+ - @param[in] ctx {ExtensionContext} Active extension context.
1906
+ - @param[in,out] controller {PiUsereqStatusController} Mutable status controller.
1907
+ - @return {void} No return value.
1908
+ - @satisfies REQ-120, REQ-121, REQ-123, REQ-124, REQ-125, REQ-126, REQ-127, REQ-128, REQ-135, REQ-136
1909
+
1910
+ ### fn `export function updateExtensionStatus(` (L616-644)
1911
+ - @brief Updates mutable status state for one intercepted lifecycle hook.
1912
+ - @details Refreshes stored context usage on every hook, starts run timing on
1913
+ `agent_start`, captures non-aborted run duration on `agent_end`, clears live
1914
+ timing on shutdown, synchronizes the live ticker, and re-renders the status
1915
+ bar when configuration is available. Runtime is O(n) in `agent_end` message
1916
+ count and otherwise O(1). Side effects include in-memory state mutation,
1917
+ interval scheduling, and footer-status updates.
1918
+ - @param[in] hookName {PiUsereqStatusHookName} Intercepted hook name.
1919
+ - @param[in] event {unknown} Hook payload forwarded from the wrapper.
1920
+ - @param[in] ctx {ExtensionContext} Active extension context.
1921
+ - @param[in,out] controller {PiUsereqStatusController} Mutable status controller.
1922
+ - @return {void} No return value.
1923
+ - @satisfies REQ-117, REQ-118, REQ-119, REQ-123, REQ-124, REQ-125
1924
+
1925
+ ### fn `export function disposePiUsereqStatusController(` (L655-660)
1926
+ - @brief Disposes the pi-usereq status controller.
1927
+ - @details Stops the live ticker, clears the cached context pointer, and leaves
1928
+ the last captured status snapshot available for inspection until the
1929
+ controller object itself is discarded. Runtime is O(1). Side effects are
1930
+ limited to interval disposal and in-memory state mutation.
1931
+ - @param[in,out] controller {PiUsereqStatusController} Mutable status controller.
1932
+ - @return {void} No return value.
1933
+
1934
+ ## Symbol Index
1935
+ |Symbol|Kind|Vis|Lines|Sig|
1936
+ |---|---|---|---|---|
1937
+ |`StatusForegroundColor`|type||27||
1938
+ |`RawStatusTheme`|iface||38-42|interface RawStatusTheme|
1939
+ |`StatusThemeAdapter`|iface||50-58|interface StatusThemeAdapter|
1940
+ |`ContextUsageOverlaySpec`|iface||66-70|interface ContextUsageOverlaySpec|
1941
+ |`PiUsereqStatusHookName`|type||113||
1942
+ |`PiUsereqStatusState`|iface||122-126|export interface PiUsereqStatusState|
1943
+ |`PiUsereqStatusController`|iface||135-141|export interface PiUsereqStatusController|
1944
+ |`convertForegroundAnsiToBackgroundAnsi`|fn||151-159|function convertForegroundAnsiToBackgroundAnsi(|
1945
+ |`applyForegroundAsBackground`|fn||172-189|function applyForegroundAsBackground(|
1946
+ |`createStatusThemeAdapter`|fn||200-220|function createStatusThemeAdapter(theme: RawStatusTheme):...|
1947
+ |`colorize`|fn||201-219|const colorize = (color: StatusForegroundColor, text: str...|
1948
+ |`backgroundize`|fn||203-219|const backgroundize = (color: StatusForegroundColor, text...|
1949
+ |`normalizeContextUsage`|fn||230-247|function normalizeContextUsage(|
1950
+ |`refreshContextUsage`|fn||259-264|function refreshContextUsage(|
1951
+ |`countFilledContextCells`|fn||275-283|function countFilledContextCells(|
1952
+ |`resolveContextUsageOverlay`|fn||295-314|function resolveContextUsageOverlay(|
1953
+ |`formatContextUsageOverlay`|fn||327-335|function formatContextUsageOverlay(|
1954
+ |`formatContextUsageBar`|fn||349-361|function formatContextUsageBar(|
1955
+ |`formatStatusDuration`|fn||372-377|function formatStatusDuration(durationMs: number): string|
1956
+ |`formatStatusField`|fn||388-394|function formatStatusField(|
1957
+ |`formatRenderedStatusField`|fn||406-412|function formatRenderedStatusField(|
1958
+ |`didAgentEndAbort`|fn||423-430|function didAgentEndAbort(messages: AgentEndEvent["messag...|
1959
+ |`buildPiUsereqStatusText`|fn||444-481|function buildPiUsereqStatusText(|
1960
+ |`stopStatusTicker`|fn||491-496|function stopStatusTicker(controller: PiUsereqStatusContr...|
1961
+ |`syncPiUsereqStatusTicker`|fn||508-524|function syncPiUsereqStatusTicker(|
1962
+ |`createPiUsereqStatusController`|fn||535-549|export function createPiUsereqStatusController(|
1963
+ |`setPiUsereqStatusConfig`|fn||561-566|export function setPiUsereqStatusConfig(|
1964
+ |`renderPiUsereqStatus`|fn||579-599|export function renderPiUsereqStatus(|
1965
+ |`updateExtensionStatus`|fn||616-644|export function updateExtensionStatus(|
1966
+ |`disposePiUsereqStatusController`|fn||655-660|export function disposePiUsereqStatusController(|
1967
+
1968
+
1969
+ ---
1970
+
1971
+ # find-constructs.ts | TypeScript | 319L | 12 symbols | 4 imports | 14 comments
1972
+ > Path: `src/core/find-constructs.ts`
1973
+ - @brief Finds named language constructs in explicit source-file lists and renders compact excerpts.
1974
+ - @details Combines source analysis, tag filtering, regex name matching, optional Doxygen extraction, and comment-stripped code rendering. Runtime is O(F + S + M) where F is file count, S is analyzed source size, and M is candidate element count. Side effects are limited to filesystem reads and optional stderr logging.
1975
+
1976
+ ## Imports
1977
+ ```
1978
+ import fs from "node:fs";
1979
+ import { compressSource, detectLanguage } from "./compress.js";
1980
+ import { formatDoxygenFieldsAsMarkdown, parseDoxygenComment } from "./doxygen-parser.js";
1981
+ import { SourceAnalyzer, SourceElement, ElementType } from "./source-analyzer.js";
1982
+ ```
1983
+
1984
+ ## Definitions
1985
+
1986
+ ### fn `export function formatAvailableTags(): string` (L44-49)
1987
+ - @brief Formats the supported tag matrix for user-facing error messages.
1988
+ - @details Sorts languages alphabetically and emits one bullet per language containing its sorted construct tags. Runtime is O(l * t log t). No side effects occur.
1989
+ - @return {string} Multiline markdown-like tag summary.
1990
+
1991
+ ### fn `export function parseTagFilter(tagString: string): Set<string>` (L57-64)
1992
+ - @brief Parses a pipe-delimited construct tag filter.
1993
+ - @details Splits the raw filter on `|`, trims whitespace, uppercases entries, and removes empty tokens. Runtime is O(n) in input length. No side effects occur.
1994
+ - @param[in] tagString {string} Raw pipe-delimited tag expression.
1995
+ - @return {Set<string>} Normalized tag set.
1996
+
1997
+ ### fn `export function languageSupportsTags(language: string, tagSet: Set<string>): boolean` (L73-76)
1998
+ - @brief Tests whether a language supports at least one requested tag.
1999
+ - @details Performs O(k) membership checks across the requested tag set against the language-specific supported-tag set. No external state is mutated.
2000
+ - @param[in] language {string} Canonical analyzer language identifier.
2001
+ - @param[in] tagSet {Set<string>} Requested construct tags.
2002
+ - @return {boolean} `true` when at least one requested tag is supported for the language.
2003
+
2004
+ ### fn `export function constructMatches(element: SourceElement, tagSet: Set<string>, pattern: string): boolean` (L86-94)
2005
+ - @brief Tests whether one analyzed element satisfies tag and name filters.
2006
+ - @details Rejects elements whose type label is outside the requested tag set or that do not expose a name, then applies the user regex to the name. Invalid regex patterns are treated as non-matches. Runtime is O(p) for regex evaluation plus constant filtering work.
2007
+ - @param[in] element {SourceElement} Candidate source element.
2008
+ - @param[in] tagSet {Set<string>} Requested construct tags.
2009
+ - @param[in] pattern {string} User-provided regular expression applied to element names.
2010
+ - @return {boolean} `true` when the element matches both tag and name criteria.
2011
+
2012
+ ### fn `function mergeDoxygenFields(baseFields: Record<string, string[]>, extraFields: Record<string, string[]>): Record<string, string[]>` (L103-109)
2013
+ - @brief Merges parsed Doxygen field arrays into one accumulator.
2014
+ - @details Appends values for matching tags without deduplication so comment order is preserved. Runtime is O(v) in merged value count. The function mutates `baseFields` in place.
2015
+ - @param[in] extraFields {Record<string, string[]>} Source map to append.
2016
+ - @param[in,out] baseFields {Record<string, string[]>} Mutable destination map.
2017
+ - @return {Record<string, string[]>} The mutated destination map.
2018
+
2019
+ ### fn `function extractConstructDoxygenFields(element: SourceElement): Record<string, string[]>` (L117-127)
2020
+ - @brief Collects Doxygen fields associated with one construct.
2021
+ - @details Starts with fields already attached to the element and extends them with nearby body comments from the first three lines of the body. Runtime is O(c) in inspected comment count. No external state is mutated.
2022
+ - @param[in] element {SourceElement} Source element whose documentation should be aggregated.
2023
+ - @return {Record<string, string[]>} Aggregated Doxygen field map.
2024
+
2025
+ ### fn `function extractFileLevelDoxygenFields(elements: SourceElement[]): Record<string, string[]>` (L135-146)
2026
+
2027
+ ### iface `export interface StrippedConstructLineEntry` (L152-157)
2028
+ - @brief Describes one stripped-code line extracted from a matched construct.
2029
+ - @details Preserves output order, original source coordinates, normalized stripped text, and rendered display text so markdown and JSON renderers can share one canonical intermediate format. The interface is compile-time only and introduces no runtime cost.
2030
+
2031
+ ### fn `export function buildStrippedConstructLineEntries(` (L168-199)
2032
+ - @brief Removes comments from a construct excerpt and returns structured stripped-code lines.
2033
+ - @details Reuses `compressSource` for comment stripping, translates local compressed line numbers back into absolute file coordinates, and emits both direct-access text fields and rendered display strings. Runtime is O(n) in excerpt length. No external state is mutated.
2034
+ - @param[in] codeLines {string[]} Raw code lines belonging to the construct.
2035
+ - @param[in] language {string} Canonical analyzer language identifier.
2036
+ - @param[in] lineStart {number} Absolute starting line number of the construct.
2037
+ - @param[in] includeLineNumbers {boolean} When `true`, `display_text` includes absolute source line prefixes.
2038
+ - @return {StrippedConstructLineEntry[]} Structured stripped-code line entries.
2039
+
2040
+ ### fn `function stripConstructComments(codeLines: string[], language: string, lineStart: number, includeLineNumbers: boolean): string` (L210-214)
2041
+ - @brief Removes comments from a construct excerpt while preserving optional absolute line numbers.
2042
+ - @details Delegates to `buildStrippedConstructLineEntries(...)` and joins the rendered display strings into one newline-delimited excerpt. Runtime is O(n) in excerpt length. No external state is mutated.
2043
+ - @param[in] codeLines {string[]} Raw code lines belonging to the construct.
2044
+ - @param[in] language {string} Canonical analyzer language identifier.
2045
+ - @param[in] lineStart {number} Absolute starting line number of the construct.
2046
+ - @param[in] includeLineNumbers {boolean} When `true`, emit absolute source line prefixes.
2047
+ - @return {string} Comment-stripped construct excerpt.
2048
+
2049
+ ### fn `export function formatConstruct(element: SourceElement, sourceLines: string[], includeLineNumbers: boolean, language = "python"): string` (L225-240)
2050
+ - @brief Formats one matched construct as markdown.
2051
+ - @details Emits construct metadata, attached Doxygen fields, and a fenced code block stripped of comments. Runtime is O(n) in construct span length plus attached documentation size. No side effects occur.
2052
+ - @param[in] element {SourceElement} Matched source element.
2053
+ - @param[in] sourceLines {string[]} Full source file split into line-preserving entries.
2054
+ - @param[in] includeLineNumbers {boolean} When `true`, include absolute source line prefixes.
2055
+ - @param[in] language {string} Canonical analyzer language identifier. Defaults to `python`.
2056
+ - @return {string} Markdown section for the matched construct.
2057
+
2058
+ ### fn `export function findConstructsInFiles(` (L253-319)
2059
+ - @brief Finds named constructs across explicit files and renders markdown excerpts.
2060
+ - @details Validates files, infers languages, skips unsupported tag/language combinations, analyzes source elements, filters matches by tag and regex, and emits one markdown section per file containing matches. Runtime is O(F + S + M). Side effects are limited to filesystem reads and optional stderr logging.
2061
+ - @param[in] filePaths {string[]} Explicit file paths to search.
2062
+ - @param[in] tagFilter {string} Pipe-delimited requested construct tags.
2063
+ - @param[in] pattern {string} Regular expression applied to construct names.
2064
+ - @param[in] includeLineNumbers {boolean} When `true`, preserve absolute source line numbers in code excerpts.
2065
+ - @param[in] verbose {boolean} When `true`, write progress and skip diagnostics to stderr.
2066
+ - @return {string} Concatenated markdown output grouped by file.
2067
+ - @throws {Error} Throws when no valid tags are provided or when no constructs match the request.
2068
+
2069
+ ## Symbol Index
2070
+ |Symbol|Kind|Vis|Lines|Sig|
2071
+ |---|---|---|---|---|
2072
+ |`formatAvailableTags`|fn||44-49|export function formatAvailableTags(): string|
2073
+ |`parseTagFilter`|fn||57-64|export function parseTagFilter(tagString: string): Set<st...|
2074
+ |`languageSupportsTags`|fn||73-76|export function languageSupportsTags(language: string, ta...|
2075
+ |`constructMatches`|fn||86-94|export function constructMatches(element: SourceElement, ...|
2076
+ |`mergeDoxygenFields`|fn||103-109|function mergeDoxygenFields(baseFields: Record<string, st...|
2077
+ |`extractConstructDoxygenFields`|fn||117-127|function extractConstructDoxygenFields(element: SourceEle...|
2078
+ |`extractFileLevelDoxygenFields`|fn||135-146|function extractFileLevelDoxygenFields(elements: SourceEl...|
2079
+ |`StrippedConstructLineEntry`|iface||152-157|export interface StrippedConstructLineEntry|
2080
+ |`buildStrippedConstructLineEntries`|fn||168-199|export function buildStrippedConstructLineEntries(|
2081
+ |`stripConstructComments`|fn||210-214|function stripConstructComments(codeLines: string[], lang...|
2082
+ |`formatConstruct`|fn||225-240|export function formatConstruct(element: SourceElement, s...|
2083
+ |`findConstructsInFiles`|fn||253-319|export function findConstructsInFiles(|
2084
+
2085
+
2086
+ ---
2087
+
2088
+ # find-payload.ts | TypeScript | 915L | 32 symbols | 6 imports | 33 comments
2089
+ > Path: `src/core/find-payload.ts`
2090
+ - @brief Builds agent-oriented JSON payloads for `files-find` and `find`.
2091
+ - @details Converts construct-search results into deterministic JSON sections ordered for LLM traversal, including request metadata, repository scope, file statuses, structured matches, structured Doxygen fields, typed line ranges, and normalized stripped code lines. Runtime is O(F log F + S + M) where F is file count, S is analyzed source size, and M is matched construct count. Side effects are limited to filesystem reads and optional stderr logging.
2092
+
2093
+ ## Imports
2094
+ ```
2095
+ import fs from "node:fs";
2096
+ import path from "node:path";
2097
+ import {
2098
+ import { detectLanguage } from "./compress.js";
2099
+ import {
2100
+ import {
2101
+ ```
2102
+
2103
+ ## Definitions
2104
+
2105
+ - type `export type FindToolScope = "explicit-files" | "configured-source-directories";` (L33)
2106
+ - @brief Enumerates supported find-payload scopes.
2107
+ - @details Distinguishes explicit-file requests from configured project scans while preserving one stable JSON contract. The alias is compile-time only and introduces no runtime cost.
2108
+ - type `export type FindFileStatus = "matched" | "no_match" | "error" | "skipped";` (L39)
2109
+ - @brief Enumerates supported per-file find-entry statuses.
2110
+ - @details Separates matched files, analyzed no-match files, analysis failures, and skipped inputs so downstream agents can branch without reparsing stderr text. The alias is compile-time only and introduces no runtime cost.
2111
+ - type `export type FindRequestStatus = "valid" | "invalid";` (L45)
2112
+ - @brief Enumerates request-validation statuses for tag-filter and regex fields.
2113
+ - @details Distinguishes validated search inputs from invalid request parameters without requiring stderr parsing. The alias is compile-time only and introduces no runtime cost.
2114
+ - type `export type FindLineNumberMode = "enabled" | "disabled";` (L51)
2115
+ - @brief Enumerates rendered line-number modes for find output.
2116
+ - @details Distinguishes payloads whose display strings include original source line prefixes from payloads whose display strings contain plain stripped code only. The alias is compile-time only and introduces no runtime cost.
2117
+ - type `export type FindSearchStatus = "matched" | "no_matches" | "invalid_tag_filter" | "invalid_regex";` (L57)
2118
+ - @brief Enumerates top-level find execution outcomes.
2119
+ - @details Separates successful match delivery from invalid request states and valid no-match searches so agents can branch on one canonical field. The alias is compile-time only and introduces no runtime cost.
2120
+ ### iface `export interface FindLineRange` (L63-67)
2121
+ - @brief Describes one numeric source line range.
2122
+ - @details Exposes start and end line numbers plus the same inclusive range as a numeric tuple for direct agent access. The interface is compile-time only and introduces no runtime cost.
2123
+
2124
+ ### iface `export interface FindToolCodeLineEntry` (L73-78)
2125
+ - @brief Describes one structured stripped-code line.
2126
+ - @details Preserves output order, original source coordinates, normalized stripped text, and rendered display text so agents can choose between direct-access facts and human-visible rendering without reparsing strings. The interface is compile-time only and introduces no runtime cost.
2127
+
2128
+ ### iface `export interface FindToolMatchEntry extends FindLineRange` : FindLineRange (L84-103)
2129
+ - @brief Describes one structured matched construct.
2130
+ - @details Orders direct-access identity fields before hierarchy, locations, Doxygen metadata, and stripped code so agents can branch without reparsing monolithic markdown. The interface is compile-time only and introduces no runtime cost.
2131
+
2132
+ ### iface `export interface FindToolFileEntry extends FindLineRange` : FindLineRange (L109-131)
2133
+ - @brief Describes one per-file find payload entry.
2134
+ - @details Stores path identity, file status, supported-tag metadata, line metrics, file-level Doxygen metadata, and matched-construct records while keeping failure facts structured. The interface is compile-time only and introduces no runtime cost.
2135
+
2136
+ ### iface `export interface FindToolRequestSection` (L137-155)
2137
+ - @brief Describes the request section of the find payload.
2138
+ - @details Captures tool identity, scope, base directory, line-number mode, tag filter, regex, validation statuses, and requested path inventory so agents can reason about how the search was executed. The interface is compile-time only and introduces no runtime cost.
2139
+
2140
+ ### iface `export interface FindToolSummarySection` (L161-171)
2141
+ - @brief Describes the summary section of the find payload.
2142
+ - @details Exposes aggregate file, match, line, and Doxygen counts as numeric fields plus one stable search-status discriminator. The interface is compile-time only and introduces no runtime cost.
2143
+
2144
+ ### iface `export interface FindToolRepositorySection` (L177-183)
2145
+ - @brief Describes the repository section of the find payload.
2146
+ - @details Stores the base path, configured source-directory scope, canonical file list, and supported-tag matrix needed to specialize later searches without rereading tool descriptions. The interface is compile-time only and introduces no runtime cost.
2147
+
2148
+ ### iface `export interface FindToolPayload` (L189-194)
2149
+ - @brief Describes the full agent-oriented find payload.
2150
+ - @details Orders the top-level sections as request, summary, repository, and files so execution metadata can be appended deterministically by the tool wrapper. The interface is compile-time only and introduces no runtime cost.
2151
+
2152
+ ### iface `export interface BuildFindToolPayloadOptions` (L200-210)
2153
+ - @brief Describes the options required to build one find payload.
2154
+ - @details Supplies tool identity, scope, base directory, tag filter, regex, requested paths, line-number mode, and optional configured source directories while keeping payload construction deterministic. The interface is compile-time only and introduces no runtime cost.
2155
+
2156
+ ### iface `interface ValidatedRegex` (L216-220)
2157
+ - @brief Describes the result of validating one regex pattern.
2158
+ - @details Separates valid compiled regex instances from invalid user input while preserving a stable machine-readable status and error message. The interface is compile-time only and introduces no runtime cost.
2159
+
2160
+ ### iface `interface ValidatedTagFilter` (L226-231)
2161
+ - @brief Describes the result of validating one tag filter.
2162
+ - @details Separates normalized tag values from invalid or empty filters while preserving a stable status and error message. The interface is compile-time only and introduces no runtime cost.
2163
+
2164
+ ### fn `function canonicalizeFindPath(targetPath: string, baseDir: string): string` (L240-248)
2165
+ - @brief Canonicalizes one filesystem path relative to the payload base directory.
2166
+ - @details Emits a slash-normalized relative path when the target is under the base directory; otherwise emits the normalized absolute path. Runtime is O(p) in path length. No side effects occur.
2167
+ - @param[in] targetPath {string} Absolute or relative filesystem path.
2168
+ - @param[in] baseDir {string} Base directory used for relative canonicalization.
2169
+ - @return {string} Canonicalized path string.
2170
+
2171
+ ### fn `function buildLineRange(startLineNumber: number, endLineNumber: number): FindLineRange` (L257-263)
2172
+ - @brief Builds one structured line-range record.
2173
+ - @details Duplicates the inclusive range as start, end, and tuple fields so callers can address whichever shape is most convenient. Runtime is O(1). No side effects occur.
2174
+ - @param[in] startLineNumber {number} Inclusive start line number.
2175
+ - @param[in] endLineNumber {number} Inclusive end line number.
2176
+ - @return {FindLineRange} Structured line-range record.
2177
+
2178
+ ### fn `function buildSupportedTagsByLanguage(): Record<string, string[]>` (L270-276)
2179
+ - @brief Returns the supported-tag matrix ordered for deterministic JSON emission.
2180
+ - @details Sorts languages alphabetically and tag arrays lexicographically so downstream agents can reuse the matrix without reparsing human prose. Runtime is O(l * t log t). No side effects occur.
2181
+ - @return {Record<string, string[]>} Supported tags keyed by canonical language identifier.
2182
+
2183
+ ### fn `function resolveSymbolName(element: SourceElement): string` (L284-286)
2184
+ - @brief Resolves one stable symbol name from an analyzed element.
2185
+ - @details Prefers explicit analyzer name metadata, then falls back to the derived signature or the first source line so every matched construct retains a direct-access identifier. Runtime is O(1). No side effects occur.
2186
+ - @param[in] element {SourceElement} Source element.
2187
+ - @return {string} Stable symbol name.
2188
+
2189
+ ### fn `function resolveParentElement(definitions: SourceElement[], element: SourceElement): SourceElement | undefined` (L295-304)
2190
+ - @brief Resolves the direct parent definition for one source element.
2191
+ - @details Matches by parent name plus inclusive line containment and chooses the deepest enclosing definition. Runtime is O(n) in definition count. No side effects occur.
2192
+ - @param[in] definitions {SourceElement[]} Sorted definition elements.
2193
+ - @param[in] element {SourceElement} Candidate child element.
2194
+ - @return {SourceElement | undefined} Matched parent definition when available.
2195
+
2196
+ ### fn `function mapCodeLines(lineEntries: StrippedConstructLineEntry[]): FindToolCodeLineEntry[]` (L312-319)
2197
+ - @brief Converts stripped-code line entries into the payload line-entry contract.
2198
+ - @details Performs a shallow field copy so the payload remains decoupled from the lower-level strip helper type. Runtime is O(n) in stripped line count. No side effects occur.
2199
+ - @param[in] lineEntries {StrippedConstructLineEntry[]} Normalized stripped-code line entries.
2200
+ - @return {FindToolCodeLineEntry[]} Payload line entries.
2201
+
2202
+ ### fn `function buildStrippedSourceText(lineEntries: FindToolCodeLineEntry[]): string | undefined` (L327-332)
2203
+ - @brief Joins stripped-code line entries into one optional monolithic text field.
2204
+ - @details Preserves rendered display strings in line order so agents that need a contiguous excerpt can read one field without losing access to the structured line array. Runtime is O(n) in stripped line count. No side effects occur.
2205
+ - @param[in] lineEntries {FindToolCodeLineEntry[]} Structured stripped-code line entries.
2206
+ - @return {string | undefined} Joined stripped-source text, or `undefined` when no lines remain.
2207
+
2208
+ ### fn `function validateTagFilter(tagFilter: string): ValidatedTagFilter` (L340-356)
2209
+ - @brief Validates and normalizes one tag filter.
2210
+ - @details Parses the raw pipe-delimited filter, sorts the resulting unique tag values, and marks the filter invalid when no recognized tag remains after normalization. Runtime is O(n log n) in requested tag count. No side effects occur.
2211
+ - @param[in] tagFilter {string} Raw pipe-delimited tag filter.
2212
+ - @return {ValidatedTagFilter} Validation result containing the normalized tag set and status.
2213
+
2214
+ ### fn `function validateRegexPattern(pattern: string): ValidatedRegex` (L364-376)
2215
+ - @brief Validates and compiles one construct-name regex pattern.
2216
+ - @details Uses the JavaScript `RegExp` engine with search-style `.test(...)` evaluation and records a stable error message when compilation fails. Runtime is O(n) in pattern length. No side effects occur.
2217
+ - @param[in] pattern {string} Raw user pattern.
2218
+ - @return {ValidatedRegex} Validation result containing the compiled regex when valid.
2219
+
2220
+ ### fn `function elementMatches(element: SourceElement, tagSet: Set<string>, regex: RegExp): boolean` (L386-394)
2221
+ - @brief Tests whether one element matches a validated tag filter and regex.
2222
+ - @details Rejects unnamed elements and elements outside the requested tag set before applying the precompiled regex to the construct name. Runtime is O(1) plus regex evaluation. No side effects occur.
2223
+ - @param[in] element {SourceElement} Candidate source element.
2224
+ - @param[in] tagSet {Set<string>} Normalized requested tag set.
2225
+ - @param[in] regex {RegExp} Precompiled construct-name regex.
2226
+ - @return {boolean} `true` when the element matches both filters.
2227
+
2228
+ ### fn `function countLogicalLines(fileContent: string): number` (L402-407)
2229
+ - @brief Counts logical source lines from one file content string.
2230
+ - @details Preserves the repository's line-count convention that excludes the terminal empty split produced by trailing newlines. Runtime is O(n) in content length. No side effects occur.
2231
+ - @param[in] fileContent {string} Raw file content.
2232
+ - @return {number} Logical source-line count.
2233
+
2234
+ ### fn `function buildSkippedFileEntry(` (L422-457)
2235
+ - @brief Builds one skipped file entry for a request path.
2236
+ - @details Preserves path identity, filesystem status, language metadata when detectable, supported tags for the language, and a stable skip reason without attempting search analysis. Runtime is O(t) in supported-tag count. No side effects occur.
2237
+ - @param[in] inputPath {string} Caller-supplied path.
2238
+ - @param[in] absolutePath {string} Absolute path resolved against the payload base directory.
2239
+ - @param[in] requestIndex {number} Caller-order index.
2240
+ - @param[in] baseDir {string} Base directory used for canonical path derivation.
2241
+ - @param[in] errorReason {string} Stable skip reason identifier.
2242
+ - @param[in] errorMessage {string} Human-readable skip reason.
2243
+ - @param[in] exists {boolean} Filesystem existence flag.
2244
+ - @param[in] isFile {boolean} Filesystem file-kind flag.
2245
+ - @return {FindToolFileEntry} Structured skipped file entry.
2246
+
2247
+ ### fn `function buildMatchEntry(` (L471-514)
2248
+ - @brief Builds one matched construct entry from an analyzed element.
2249
+ - @details Resolves symbol identity, hierarchy hints, structured Doxygen fields, numeric declaration lines, and stripped code excerpts while keeping monolithic source text optional. Runtime is O(n) in construct span length plus Doxygen size. No side effects occur.
2250
+ - @param[in] element {SourceElement} Matched element.
2251
+ - @param[in] matchIndex {number} Match index within the file.
2252
+ - @param[in] definitions {SourceElement[]} Sorted definition elements used for parent resolution.
2253
+ - @param[in] qualifiedNameByLineStart {Map<number, string>} Precomputed qualified-name map for definitions.
2254
+ - @param[in] sourceLines {string[]} Full file content split into line-preserving entries.
2255
+ - @param[in] languageId {string} Canonical language identifier.
2256
+ - @param[in] includeLineNumbers {boolean} When `true`, rendered display strings include absolute source line prefixes.
2257
+ - @return {FindToolMatchEntry} Structured match entry.
2258
+
2259
+ ### fn `function analyzeFindFile(` (L530-716)
2260
+ - @brief Analyzes one path into a structured find file entry.
2261
+ - @details Resolves path identity, validates language and tag support, parses the file with `SourceAnalyzer`, builds structured match entries, and preserves stable status facts for no-match or failure outcomes. Runtime is dominated by file I/O and analyzer cost. Side effects are limited to filesystem reads and optional stderr logging.
2262
+ - @param[in] analyzer {SourceAnalyzer} Shared analyzer instance.
2263
+ - @param[in] inputPath {string} Caller-supplied path.
2264
+ - @param[in] absolutePath {string} Absolute path resolved against the payload base directory.
2265
+ - @param[in] requestIndex {number} Caller-order index.
2266
+ - @param[in] baseDir {string} Base directory used for canonical path derivation.
2267
+ - @param[in] tagSet {Set<string>} Validated requested tag set.
2268
+ - @param[in] regex {RegExp} Validated construct-name regex.
2269
+ - @param[in] includeLineNumbers {boolean} When `true`, rendered stripped-source text includes original line prefixes.
2270
+ - @param[in] verbose {boolean} When `true`, emit per-file diagnostics to stderr.
2271
+ - @return {FindToolFileEntry} Structured file entry.
2272
+
2273
+ ### fn `export function buildFindToolPayload(options: BuildFindToolPayloadOptions): FindToolPayload` (L725-881)
2274
+ - @brief Builds the full agent-oriented find payload.
2275
+ - @details Validates request parameters, analyzes requested files in caller order when the request is valid, preserves skipped and no-match outcomes in structured file entries, computes aggregate numeric totals, and emits a structured supported-tag matrix. Runtime is O(F log F + S + M). Side effects are limited to filesystem reads and optional stderr logging.
2276
+ - @param[in] options {BuildFindToolPayloadOptions} Payload-construction options.
2277
+ - @return {FindToolPayload} Structured find payload ordered as request, summary, repository, and files.
2278
+ - @satisfies REQ-089, REQ-090, REQ-091, REQ-092, REQ-093, REQ-094, REQ-096, REQ-098
2279
+
2280
+ ### fn `export function buildFindToolExecutionStderr(payload: FindToolPayload): string` (L890-915)
2281
+ - @brief Builds deterministic stderr diagnostics from a find payload.
2282
+ - @details Serializes invalid request states, skipped inputs, no-match files, and analysis failures into stable newline-delimited diagnostics while leaving successful matched files silent. Runtime is O(n) in file-entry count. No side effects occur.
2283
+ - @param[in] payload {FindToolPayload} Structured find payload.
2284
+ - @return {string} Newline-delimited diagnostics.
2285
+ - @satisfies REQ-096
2286
+
2287
+ ## Symbol Index
2288
+ |Symbol|Kind|Vis|Lines|Sig|
2289
+ |---|---|---|---|---|
2290
+ |`FindToolScope`|type||33||
2291
+ |`FindFileStatus`|type||39||
2292
+ |`FindRequestStatus`|type||45||
2293
+ |`FindLineNumberMode`|type||51||
2294
+ |`FindSearchStatus`|type||57||
2295
+ |`FindLineRange`|iface||63-67|export interface FindLineRange|
2296
+ |`FindToolCodeLineEntry`|iface||73-78|export interface FindToolCodeLineEntry|
2297
+ |`FindToolMatchEntry`|iface||84-103|export interface FindToolMatchEntry extends FindLineRange|
2298
+ |`FindToolFileEntry`|iface||109-131|export interface FindToolFileEntry extends FindLineRange|
2299
+ |`FindToolRequestSection`|iface||137-155|export interface FindToolRequestSection|
2300
+ |`FindToolSummarySection`|iface||161-171|export interface FindToolSummarySection|
2301
+ |`FindToolRepositorySection`|iface||177-183|export interface FindToolRepositorySection|
2302
+ |`FindToolPayload`|iface||189-194|export interface FindToolPayload|
2303
+ |`BuildFindToolPayloadOptions`|iface||200-210|export interface BuildFindToolPayloadOptions|
2304
+ |`ValidatedRegex`|iface||216-220|interface ValidatedRegex|
2305
+ |`ValidatedTagFilter`|iface||226-231|interface ValidatedTagFilter|
2306
+ |`canonicalizeFindPath`|fn||240-248|function canonicalizeFindPath(targetPath: string, baseDir...|
2307
+ |`buildLineRange`|fn||257-263|function buildLineRange(startLineNumber: number, endLineN...|
2308
+ |`buildSupportedTagsByLanguage`|fn||270-276|function buildSupportedTagsByLanguage(): Record<string, s...|
2309
+ |`resolveSymbolName`|fn||284-286|function resolveSymbolName(element: SourceElement): string|
2310
+ |`resolveParentElement`|fn||295-304|function resolveParentElement(definitions: SourceElement[...|
2311
+ |`mapCodeLines`|fn||312-319|function mapCodeLines(lineEntries: StrippedConstructLineE...|
2312
+ |`buildStrippedSourceText`|fn||327-332|function buildStrippedSourceText(lineEntries: FindToolCod...|
2313
+ |`validateTagFilter`|fn||340-356|function validateTagFilter(tagFilter: string): ValidatedT...|
2314
+ |`validateRegexPattern`|fn||364-376|function validateRegexPattern(pattern: string): Validated...|
2315
+ |`elementMatches`|fn||386-394|function elementMatches(element: SourceElement, tagSet: S...|
2316
+ |`countLogicalLines`|fn||402-407|function countLogicalLines(fileContent: string): number|
2317
+ |`buildSkippedFileEntry`|fn||422-457|function buildSkippedFileEntry(|
2318
+ |`buildMatchEntry`|fn||471-514|function buildMatchEntry(|
2319
+ |`analyzeFindFile`|fn||530-716|function analyzeFindFile(|
2320
+ |`buildFindToolPayload`|fn||725-881|export function buildFindToolPayload(options: BuildFindTo...|
2321
+ |`buildFindToolExecutionStderr`|fn||890-915|export function buildFindToolExecutionStderr(payload: Fin...|
2322
+
2323
+
2324
+ ---
2325
+
2326
+ # generate-markdown.ts | TypeScript | 120L | 3 symbols | 3 imports | 5 comments
2327
+ > Path: `src/core/generate-markdown.ts`
2328
+ - @brief Generates useReq reference markdown from explicit source-file lists.
2329
+ - @details Combines file validation, language detection, source analysis, metadata enrichment, and final markdown rendering for downstream prompt workflows. Runtime is O(F + S) where F is file count and S is total source size. Side effects are limited to filesystem reads and optional stderr logging.
2330
+
2331
+ ## Imports
2332
+ ```
2333
+ import fs from "node:fs";
2334
+ import path from "node:path";
2335
+ import { SourceAnalyzer, formatMarkdown } from "./source-analyzer.js";
2336
+ ```
2337
+
2338
+ ## Definitions
2339
+
2340
+ ### fn `export function detectLanguage(filePath: string): string | undefined` (L47-49)
2341
+ - @brief Infers the analyzer language from a file path extension.
2342
+ - @details Normalizes the extension to lowercase and resolves it through `EXT_LANG_MAP`. Time complexity is O(1). No I/O side effects occur.
2343
+ - @param[in] filePath {string} Source file path.
2344
+ - @return {string | undefined} Canonical analyzer language identifier, or `undefined` for unsupported extensions.
2345
+
2346
+ ### fn `function formatOutputPath(filePath: string, outputBase?: string): string` (L58-61)
2347
+ - @brief Formats one analyzed file path for markdown output.
2348
+ - @details Returns the original path when no base is supplied; otherwise computes a slash-normalized relative path against the resolved output base. Time complexity is O(p) in path length. No side effects occur.
2349
+ - @param[in] filePath {string} Source file path.
2350
+ - @param[in] outputBase {string | undefined} Optional base directory used for relative formatting.
2351
+ - @return {string} Display path used in the rendered markdown header.
2352
+
2353
+ ### fn `export function generateMarkdown(filePaths: string[], verbose = false, outputBase?: string): string` (L72-120)
2354
+ - @brief Generates reference markdown for explicit source files.
2355
+ - @details Filters unsupported or missing files, analyzes each valid source file, enriches extracted symbols with signatures and Doxygen metadata, and concatenates per-file markdown sections separated by horizontal rules. Runtime is O(F + S). Side effects are limited to filesystem reads and optional stderr logging.
2356
+ - @param[in] filePaths {string[]} Explicit file paths to analyze.
2357
+ - @param[in] verbose {boolean} When `true`, write per-file progress diagnostics to stderr.
2358
+ - @param[in] outputBase {string | undefined} Optional base directory used to shorten output paths.
2359
+ - @return {string} Concatenated markdown reference document.
2360
+ - @throws {Error} Throws when no valid source files can be processed.
2361
+
2362
+ ## Symbol Index
2363
+ |Symbol|Kind|Vis|Lines|Sig|
2364
+ |---|---|---|---|---|
2365
+ |`detectLanguage`|fn||47-49|export function detectLanguage(filePath: string): string ...|
2366
+ |`formatOutputPath`|fn||58-61|function formatOutputPath(filePath: string, outputBase?: ...|
2367
+ |`generateMarkdown`|fn||72-120|export function generateMarkdown(filePaths: string[], ver...|
2368
+
2369
+
2370
+ ---
2371
+
2372
+ # path-context.ts | TypeScript | 196L | 9 symbols | 4 imports | 12 comments
2373
+ > Path: `src/core/path-context.ts`
2374
+ - @brief Derives shared runtime path context for prompts, tools, and configuration flows.
2375
+ - @details Resolves installation, execution, base, config, resource, docs, test, source, and optional git paths from the active runtime context, validates ancestor constraints for repository roots, and formats prompt-visible paths relative to the user home via platform-native environment variables. Runtime is O(s + p) where s is configured source-directory count and p is aggregate path length. Side effects are limited to filesystem-path normalization.
2376
+
2377
+ ## Imports
2378
+ ```
2379
+ import os from "node:os";
2380
+ import path from "node:path";
2381
+ import { fileURLToPath } from "node:url";
2382
+ import type { UseReqConfig } from "./config.js";
2383
+ ```
2384
+
2385
+ ## Definitions
2386
+
2387
+ ### iface `export interface RuntimePathContext` (L28-44)
2388
+ - @brief Describes the absolute runtime path context shared across extension components.
2389
+ - @details Aggregates the derived installation, execution, base, config, resource, documentation, tests, source, template, guideline, and optional git paths needed by prompt rendering and tool payload generation. The interface is compile-time only and introduces no runtime cost.
2390
+
2391
+ ### iface `export interface RuntimePathFacts` (L50-64)
2392
+ - @brief Describes the prompt/tool-facing runtime paths rendered with a home-environment-variable prefix when possible.
2393
+ - @details Mirrors `RuntimePathContext` in a serialization-oriented shape so downstream agents can consume stable, user-home-relative path strings without reparsing absolute local paths. The interface is compile-time only and introduces no runtime cost.
2394
+
2395
+ ### fn `export function getInstallationPath(): string` (L71-73)
2396
+ - @brief Resolves the installed extension root that owns `index.ts` and bundled resources.
2397
+ - @details Uses the current module location under `src/core` or its installed equivalent, then moves one directory upward so the returned path is the runtime installation root containing `resources/`. Runtime is O(1). No external state is mutated.
2398
+ - @return {string} Absolute installation path.
2399
+
2400
+ ### fn `export function getConfigPath(basePath: string): string` (L81-83)
2401
+ - @brief Computes the absolute project config path for one base path.
2402
+ - @details Appends `.pi-usereq/config.json` to the supplied base path using the canonical repository-local configuration layout. Runtime is O(1). No external state is mutated.
2403
+ - @param[in] basePath {string} Absolute or relative base path.
2404
+ - @return {string} Absolute config-file path.
2405
+
2406
+ ### fn `export function normalizePathSlashes(value: string): string` (L91-93)
2407
+ - @brief Formats one path with slash separators.
2408
+ - @details Normalizes the supplied path and converts platform separators to `/` so serialized payloads remain stable across operating systems. Runtime is O(p) in path length. No external state is mutated.
2409
+ - @param[in] value {string} Absolute or relative filesystem path.
2410
+ - @return {string} Slash-normalized path string.
2411
+
2412
+ ### fn `export function isSameOrAncestorPath(ancestorPath: string, childPath: string): boolean` (L102-107)
2413
+ - @brief Tests whether one path is identical to or an ancestor of another path.
2414
+ - @details Resolves both inputs, computes a relative traversal from the candidate ancestor to the candidate child, and accepts only exact matches or descendant traversals that stay within the ancestor subtree. Runtime is O(p) in path length. No external state is mutated.
2415
+ - @param[in] ancestorPath {string} Candidate ancestor or identical path.
2416
+ - @param[in] childPath {string} Candidate child or identical path.
2417
+ - @return {boolean} `true` when `ancestorPath` equals `childPath` or strictly contains it.
2418
+
2419
+ ### fn `export function formatRuntimePathForDisplay(absolutePath: string): string` (L115-127)
2420
+ - @brief Formats one absolute path relative to the user home using platform-native home environment variables when possible.
2421
+ - @details Returns `$HOME` for POSIX platforms and `%USERPROFILE%` for Windows when the path equals or descends from the current home directory; otherwise returns the normalized absolute path unchanged. Runtime is O(p) in path length. No external state is mutated.
2422
+ - @param[in] absolutePath {string} Absolute or relative path candidate.
2423
+ - @return {string} Home-environment-relative or slash-normalized absolute path.
2424
+
2425
+ ### fn `export function buildRuntimePathContext(` (L137-140)
2426
+ - @brief Builds the absolute runtime path context for one execution directory and configuration.
2427
+ - @details Derives `base-path` from the supplied execution path, derives `config-path` under `.pi-usereq`, resolves docs/tests/source directories against the base path, derives installation-owned resource directories, and keeps `git-path` only when it satisfies the base-path ancestor constraint. Runtime is O(s + p) where s is configured source-directory count and p is aggregate path length. No external state is mutated.
2428
+ - @param[in] executionPath {string} Current execution directory.
2429
+ - @param[in] config {Pick<UseReqConfig, "docs-dir" | "tests-dir" | "src-dir">} Effective configuration fields required for path derivation.
2430
+ - @param[in] options {{ installationPath?: string; gitPath?: string | undefined } | undefined} Optional installation and git-root overrides.
2431
+ - @return {RuntimePathContext} Absolute runtime path context.
2432
+
2433
+ ### fn `export function buildRuntimePathFacts(context: RuntimePathContext): RuntimePathFacts` (L180-196)
2434
+ - @brief Converts the absolute runtime path context into prompt/tool-facing path facts.
2435
+ - @details Re-encodes every absolute path with the user-home environment-variable formatter while preserving path presence for the optional git root. Runtime is O(s + p) where s is source-directory count and p is aggregate path length. No external state is mutated.
2436
+ - @param[in] context {RuntimePathContext} Absolute runtime path context.
2437
+ - @return {RuntimePathFacts} Display-oriented runtime path facts.
2438
+
2439
+ ## Symbol Index
2440
+ |Symbol|Kind|Vis|Lines|Sig|
2441
+ |---|---|---|---|---|
2442
+ |`RuntimePathContext`|iface||28-44|export interface RuntimePathContext|
2443
+ |`RuntimePathFacts`|iface||50-64|export interface RuntimePathFacts|
2444
+ |`getInstallationPath`|fn||71-73|export function getInstallationPath(): string|
2445
+ |`getConfigPath`|fn||81-83|export function getConfigPath(basePath: string): string|
2446
+ |`normalizePathSlashes`|fn||91-93|export function normalizePathSlashes(value: string): string|
2447
+ |`isSameOrAncestorPath`|fn||102-107|export function isSameOrAncestorPath(ancestorPath: string...|
2448
+ |`formatRuntimePathForDisplay`|fn||115-127|export function formatRuntimePathForDisplay(absolutePath:...|
2449
+ |`buildRuntimePathContext`|fn||137-140|export function buildRuntimePathContext(|
2450
+ |`buildRuntimePathFacts`|fn||180-196|export function buildRuntimePathFacts(context: RuntimePat...|
2451
+
2452
+
2453
+ ---
2454
+
2455
+ # pi-notify.ts | TypeScript | 430L | 24 symbols | 4 imports | 31 comments
2456
+ > Path: `src/core/pi-notify.ts`
2457
+ - @brief Implements pi-usereq terminal-beep and external sound-hook helpers.
2458
+ - @details Centralizes configuration defaults, status serialization, agent-end outcome classification, terminal notification dispatch, and successful-run external sound-command execution. Runtime is O(m + c) in `agent_end` message count plus command length. Side effects include stdout writes and detached child-process spawning.
2459
+
2460
+ ## Imports
2461
+ ```
2462
+ import { execFile, spawn } from "node:child_process";
2463
+ import type { AgentEndEvent } from "@mariozechner/pi-coding-agent";
2464
+ import { getInstallationPath } from "./path-context.js";
2465
+ import type { UseReqConfig } from "./config.js";
2466
+ ```
2467
+
2468
+ ## Definitions
2469
+
2470
+ - type `export type PiNotifySoundLevel = (typeof PI_NOTIFY_SOUND_LEVELS)[number];` (L22)
2471
+ - @brief Represents one supported successful-run sound level.
2472
+ - @details Narrows configuration parsing and runtime command dispatch to the canonical four-state sound-hook domain. Compile-time only and introduces no runtime cost.
2473
+ - type `export type PiNotifyOutcome = (typeof PI_NOTIFY_OUTCOMES)[number];` (L34)
2474
+ - @brief Represents one supported prompt-end notification outcome.
2475
+ - @details Narrows prompt-end event classification and status serialization to the canonical three-outcome domain. Compile-time only and introduces no runtime cost.
2476
+ - type `export type PiNotifyConfigFields = Pick<` (L68)
2477
+ - @brief Describes the configuration fields consumed by pi-notify helpers.
2478
+ - @details Narrows the full project config to the persisted notification and sound-hook fields used by status rendering, prompt-end routing, and shortcut toggles. Compile-time only and introduces no runtime cost.
2479
+ ### fn `export function normalizePiNotifySoundLevel(value: unknown): PiNotifySoundLevel` (L87-91)
2480
+ - @brief Normalizes one persisted sound level.
2481
+ - @details Accepts only canonical `none|low|mid|high` values and falls back to `none` for missing or invalid payloads. Runtime is O(1). No external state is mutated.
2482
+ - @param[in] value {unknown} Raw persisted sound-level payload.
2483
+ - @return {PiNotifySoundLevel} Canonical sound level.
2484
+ - @satisfies REQ-131
2485
+
2486
+ ### fn `export function normalizePiNotifyShortcut(value: unknown): string` (L100-104)
2487
+ - @brief Normalizes one persisted sound toggle shortcut.
2488
+ - @details Accepts any non-empty string so project config can carry raw pi shortcut syntax and falls back to the canonical default when the payload is empty or invalid. Runtime is O(n) in shortcut length. No external state is mutated.
2489
+ - @param[in] value {unknown} Raw persisted shortcut payload.
2490
+ - @return {string} Canonical non-empty shortcut string.
2491
+ - @satisfies REQ-134
2492
+
2493
+ ### fn `export function normalizePiNotifyCommand(value: unknown, fallback: string): string` (L114-116)
2494
+ - @brief Normalizes one persisted sound command string.
2495
+ - @details Accepts any non-empty string so project config can override bundled commands verbatim and falls back to the supplied default when the payload is empty or invalid. Runtime is O(n) in command length. No external state is mutated.
2496
+ - @param[in] value {unknown} Raw persisted command payload.
2497
+ - @param[in] fallback {string} Canonical fallback command.
2498
+ - @return {string} Canonical non-empty command string.
2499
+ - @satisfies REQ-133
2500
+
2501
+ ### fn `export function formatPiNotifyBeepStatus(config: PiNotifyConfigFields): string` (L125-137)
2502
+ - @brief Formats enabled terminal-beep flags for status rendering.
2503
+ - @details Emits the canonical comma-ordered enabled outcome tokens `end`, `esc`, and `err`, or `none` when all prompt-end beep flags are disabled. Runtime is O(1). No external state is mutated.
2504
+ - @param[in] config {PiNotifyConfigFields} Effective notification configuration.
2505
+ - @return {string} Status-bar beep payload.
2506
+ - @satisfies REQ-135
2507
+
2508
+ ### fn `export function cyclePiNotifySoundLevel(currentLevel: PiNotifySoundLevel): PiNotifySoundLevel` (L146-152)
2509
+ - @brief Cycles one sound level through the canonical shortcut order.
2510
+ - @details Advances persisted sound state in the exact order `none -> low -> mid -> high -> none`, enabling deterministic shortcut toggling and menu reuse. Runtime is O(1). No external state is mutated.
2511
+ - @param[in] currentLevel {PiNotifySoundLevel} Current persisted sound level.
2512
+ - @return {PiNotifySoundLevel} Next sound level in the cycle.
2513
+ - @satisfies REQ-134
2514
+
2515
+ ### fn `function escapePowerShellLiteral(value: string): string` (L160-162)
2516
+ - @brief Escapes one string for single-quoted PowerShell embedding.
2517
+ - @details Doubles embedded apostrophes so the generated Windows toast script preserves literal title and body text. Runtime is O(n) in text length. No external state is mutated.
2518
+ - @param[in] value {string} Raw literal text.
2519
+ - @return {string} PowerShell-safe single-quoted literal content.
2520
+
2521
+ ### fn `function windowsToastScript(title: string, body: string): string` (L171-186)
2522
+ - @brief Builds the PowerShell script used for Windows toast notifications.
2523
+ - @details Reuses the pi notify example contract, escapes title and body literals, and emits a one-shot script that shows a toast notification through the Windows Runtime API. Runtime is O(n) in payload length. No external state is mutated.
2524
+ - @param[in] title {string} Notification title.
2525
+ - @param[in] body {string} Notification body.
2526
+ - @return {string} PowerShell script passed to `powershell.exe`.
2527
+
2528
+ ### fn `export function notifyOSC777(title: string, body: string): void` (L196-198)
2529
+ - @brief Emits one OSC 777 terminal notification.
2530
+ - @details Writes the Ghostty/iTerm2/WezTerm-compatible OSC 777 escape sequence directly to stdout using the supplied title and body payloads. Runtime is O(n) in payload length. Side effect: writes to stdout.
2531
+ - @param[in] title {string} Notification title.
2532
+ - @param[in] body {string} Notification body.
2533
+ - @return {void} No return value.
2534
+ - @satisfies REQ-130
2535
+
2536
+ ### fn `export function notifyOSC99(title: string, body: string): void` (L208-211)
2537
+ - @brief Emits one Kitty OSC 99 terminal notification.
2538
+ - @details Writes the two-part Kitty OSC 99 sequence that carries the title and body payloads under one notification identifier. Runtime is O(n) in payload length. Side effect: writes to stdout.
2539
+ - @param[in] title {string} Notification title.
2540
+ - @param[in] body {string} Notification body.
2541
+ - @return {void} No return value.
2542
+ - @satisfies REQ-130
2543
+
2544
+ ### fn `export function notifyOSC9(title: string, body: string): void` (L221-223)
2545
+ - @brief Emits one OSC 9 terminal notification.
2546
+ - @details Writes the single-part OSC 9 sequence commonly used by terminals that accept message-only desktop notifications. Runtime is O(n) in payload length. Side effect: writes to stdout.
2547
+ - @param[in] title {string} Notification title.
2548
+ - @param[in] body {string} Notification body.
2549
+ - @return {void} No return value.
2550
+ - @satisfies REQ-130
2551
+
2552
+ ### fn `export function notifyWindows(title: string, body: string): void` (L233-239)
2553
+ - @brief Emits one Windows toast notification.
2554
+ - @details Spawns `powershell.exe` without waiting, delegates payload rendering to `windowsToastScript(...)`, and ignores transport failures so prompt-end handling remains non-blocking. Runtime is dominated by process spawn. Side effects include child-process execution.
2555
+ - @param[in] title {string} Notification title.
2556
+ - @param[in] body {string} Notification body.
2557
+ - @return {void} No return value.
2558
+ - @satisfies REQ-130
2559
+
2560
+ ### fn `export function notifyPiTerminal(title: string, body: string): void` (L249-263)
2561
+ - @brief Routes one prompt-end terminal notification through the detected terminal protocol.
2562
+ - @details Prefers Windows toast delivery inside Windows Terminal, Kitty OSC 99 inside Kitty, OSC 9 inside iTerm-like terminals, and OSC 777 as the fallback path. Runtime is O(n) in payload length plus optional process spawn cost. Side effects include stdout writes or child-process execution.
2563
+ - @param[in] title {string} Notification title.
2564
+ - @param[in] body {string} Notification body.
2565
+ - @return {void} No return value.
2566
+ - @satisfies REQ-130
2567
+
2568
+ ### fn `function hasAgentEndStopReason(` (L272-282)
2569
+ - @brief Detects whether one agent-end payload contains the requested stop reason.
2570
+ - @details Scans assistant messages only so prompt-end classification remains stable even when user or tool-result messages also appear in the payload. Runtime is O(m) in message count. No external state is mutated.
2571
+ - @param[in] messages {AgentEndEvent["messages"]} Agent-end message list.
2572
+ - @param[in] stopReason {"aborted" | "error"} Stop reason to detect.
2573
+ - @return {boolean} `true` when an assistant message carries the requested stop reason.
2574
+
2575
+ ### fn `export function classifyPiNotifyOutcome(event: Pick<AgentEndEvent, "messages">): PiNotifyOutcome` (L291-299)
2576
+ - @brief Classifies one agent-end payload into the canonical pi-notify outcome.
2577
+ - @details Treats assistant `stopReason=error` as `err`, `stopReason=aborted` as `esc`, and every remaining terminal state as successful `end`. Runtime is O(m) in message count. No external state is mutated.
2578
+ - @param[in] event {Pick<AgentEndEvent, "messages">} Agent-end payload subset.
2579
+ - @return {PiNotifyOutcome} Canonical prompt-end outcome.
2580
+ - @satisfies REQ-129
2581
+
2582
+ ### fn `function buildPiNotifyTitle(): string` (L306-308)
2583
+ - @brief Builds the user-visible prompt-end notification title.
2584
+ - @details Keeps a stable `pi-usereq` title across outcomes so terminal notification stacks remain easy to correlate with this extension. Runtime is O(1). No external state is mutated.
2585
+ - @return {string} Notification title.
2586
+
2587
+ ### fn `function buildPiNotifyBody(outcome: PiNotifyOutcome): string` (L316-325)
2588
+ - @brief Builds the user-visible prompt-end notification body.
2589
+ - @details Maps each canonical outcome to one deterministic English phrase so downstream tests and users can distinguish success, abort, and error notifications. Runtime is O(1). No external state is mutated.
2590
+ - @param[in] outcome {PiNotifyOutcome} Canonical prompt-end outcome.
2591
+ - @return {string} Notification body.
2592
+
2593
+ ### fn `function quotePiNotifyInstallPath(installationPath: string): string` (L333-338)
2594
+ - @brief Quotes one installation path for shell substitution.
2595
+ - @details Emits POSIX single-quoted literals for `sh -lc` execution and CMD double-quoted literals for `cmd.exe /c` execution so `%%INSTALLATION_PATH%%` substitutions preserve whitespace safely. Runtime is O(n) in path length. No external state is mutated.
2596
+ - @param[in] installationPath {string} Absolute extension installation path.
2597
+ - @return {string} Shell-quoted installation path fragment.
2598
+
2599
+ ### fn `export function substitutePiNotifyInstallPath(command: string, installationPath: string): string` (L348-350)
2600
+ - @brief Substitutes `%%INSTALLATION_PATH%%` inside one sound command.
2601
+ - @details Replaces every `%%INSTALLATION_PATH%%` token with a shell-quoted runtime installation path so bundled sound assets can be addressed safely from external commands. Runtime is O(n) in command length. No external state is mutated.
2602
+ - @param[in] command {string} Raw configured sound command.
2603
+ - @param[in] installationPath {string} Absolute extension installation path.
2604
+ - @return {string} Runtime-ready command string.
2605
+ - @satisfies REQ-133
2606
+
2607
+ ### fn `function resolvePiNotifySoundCommand(` (L359-371)
2608
+ - @brief Resolves the configured command for one non-`none` sound level.
2609
+ - @details Selects the matching persisted command string from config without performing runtime substitution or shell execution. Runtime is O(1). No external state is mutated.
2610
+ - @param[in] config {PiNotifyConfigFields} Effective notification configuration.
2611
+ - @param[in] soundLevel {Exclude<PiNotifySoundLevel, "none">} Non-disabled sound level.
2612
+ - @return {string} Configured command string for the requested level.
2613
+
2614
+ ### fn `export function runPiNotifySoundCommand(` (L381-397)
2615
+ - @brief Executes the configured successful-run sound command on an external shell.
2616
+ - @details Resolves the runtime installation path, substitutes `%%INSTALLATION_PATH%%`, spawns the configured shell command without waiting, and ignores transport failures so prompt-end handling remains non-blocking. Runtime is dominated by process spawn. Side effects include detached child-process execution.
2617
+ - @param[in] config {PiNotifyConfigFields} Effective notification configuration.
2618
+ - @param[in] soundLevel {Exclude<PiNotifySoundLevel, "none">} Requested non-disabled sound level.
2619
+ - @return {void} No return value.
2620
+ - @satisfies REQ-132, REQ-133
2621
+
2622
+ ### fn `export function runPiNotifyEffects(` (L407-430)
2623
+ - @brief Dispatches prompt-end beep and sound effects for one agent-end payload.
2624
+ - @details Classifies the terminal outcome, emits the configured terminal notification only for the enabled outcome flag, and executes the configured external sound command only for successful completion with a non-disabled sound level. Runtime is O(m + c) in message count plus command length. Side effects include stdout writes and child-process spawning.
2625
+ - @param[in] config {PiNotifyConfigFields} Effective notification configuration.
2626
+ - @param[in] event {Pick<AgentEndEvent, "messages">} Agent-end payload subset.
2627
+ - @return {void} No return value.
2628
+ - @satisfies REQ-129, REQ-130, REQ-131, REQ-132, REQ-133
2629
+
2630
+ ## Symbol Index
2631
+ |Symbol|Kind|Vis|Lines|Sig|
2632
+ |---|---|---|---|---|
2633
+ |`PiNotifySoundLevel`|type||22||
2634
+ |`PiNotifyOutcome`|type||34||
2635
+ |`PiNotifyConfigFields`|type||68||
2636
+ |`normalizePiNotifySoundLevel`|fn||87-91|export function normalizePiNotifySoundLevel(value: unknow...|
2637
+ |`normalizePiNotifyShortcut`|fn||100-104|export function normalizePiNotifyShortcut(value: unknown)...|
2638
+ |`normalizePiNotifyCommand`|fn||114-116|export function normalizePiNotifyCommand(value: unknown, ...|
2639
+ |`formatPiNotifyBeepStatus`|fn||125-137|export function formatPiNotifyBeepStatus(config: PiNotify...|
2640
+ |`cyclePiNotifySoundLevel`|fn||146-152|export function cyclePiNotifySoundLevel(currentLevel: PiN...|
2641
+ |`escapePowerShellLiteral`|fn||160-162|function escapePowerShellLiteral(value: string): string|
2642
+ |`windowsToastScript`|fn||171-186|function windowsToastScript(title: string, body: string):...|
2643
+ |`notifyOSC777`|fn||196-198|export function notifyOSC777(title: string, body: string)...|
2644
+ |`notifyOSC99`|fn||208-211|export function notifyOSC99(title: string, body: string):...|
2645
+ |`notifyOSC9`|fn||221-223|export function notifyOSC9(title: string, body: string): ...|
2646
+ |`notifyWindows`|fn||233-239|export function notifyWindows(title: string, body: string...|
2647
+ |`notifyPiTerminal`|fn||249-263|export function notifyPiTerminal(title: string, body: str...|
2648
+ |`hasAgentEndStopReason`|fn||272-282|function hasAgentEndStopReason(|
2649
+ |`classifyPiNotifyOutcome`|fn||291-299|export function classifyPiNotifyOutcome(event: Pick<Agent...|
2650
+ |`buildPiNotifyTitle`|fn||306-308|function buildPiNotifyTitle(): string|
2651
+ |`buildPiNotifyBody`|fn||316-325|function buildPiNotifyBody(outcome: PiNotifyOutcome): string|
2652
+ |`quotePiNotifyInstallPath`|fn||333-338|function quotePiNotifyInstallPath(installationPath: strin...|
2653
+ |`substitutePiNotifyInstallPath`|fn||348-350|export function substitutePiNotifyInstallPath(command: st...|
2654
+ |`resolvePiNotifySoundCommand`|fn||359-371|function resolvePiNotifySoundCommand(|
2655
+ |`runPiNotifySoundCommand`|fn||381-397|export function runPiNotifySoundCommand(|
2656
+ |`runPiNotifyEffects`|fn||407-430|export function runPiNotifyEffects(|
2657
+
2658
+
2659
+ ---
2660
+
2661
+ # pi-usereq-tools.ts | TypeScript | 140L | 5 symbols | 0 imports | 14 comments
2662
+ > Path: `src/core/pi-usereq-tools.ts`
2663
+ - @brief Declares the configurable pi-usereq active-tool inventory.
2664
+ - @details Provides canonical custom-tool names, supported embedded-tool names, default enablement subsets, and normalization helpers shared by configuration loading, extension startup, and test doubles. The module is side-effect free. Lookup and normalization costs are linear in configured tool count.
2665
+
2666
+ ## Definitions
2667
+
2668
+ - type `export type PiUsereqCustomToolName = (typeof PI_USEREQ_CUSTOM_TOOL_NAMES)[number];` (L83)
2669
+ - @brief Represents one valid extension-owned configurable tool identifier.
2670
+ - @details Narrows arbitrary strings to the literal union derived from `PI_USEREQ_CUSTOM_TOOL_NAMES`. The alias is compile-time only and introduces no runtime cost.
2671
+ - type `export type PiUsereqEmbeddedToolName = (typeof PI_USEREQ_EMBEDDED_TOOL_NAMES)[number];` (L89)
2672
+ - @brief Represents one valid embedded configurable tool identifier.
2673
+ - @details Narrows arbitrary strings to the literal union derived from `PI_USEREQ_EMBEDDED_TOOL_NAMES`. The alias is compile-time only and introduces no runtime cost.
2674
+ - type `export type PiUsereqStartupToolName = (typeof PI_USEREQ_STARTUP_TOOL_NAMES)[number];` (L95)
2675
+ - @brief Represents one valid configurable active-tool identifier.
2676
+ - @details Narrows arbitrary strings to the literal union derived from `PI_USEREQ_STARTUP_TOOL_NAMES`. The alias is compile-time only and introduces no runtime cost.
2677
+ ### fn `export function isPiUsereqEmbeddedToolName(name: string): name is PiUsereqEmbeddedToolName` (L121-123)
2678
+ - @brief Tests whether one tool name belongs to the supported embedded-tool subset.
2679
+ - @details Performs one set-membership probe against `PI_USEREQ_EMBEDDED_TOOL_SET`. Runtime is O(1). No external state is mutated.
2680
+ - @param[in] name {string} Candidate tool name.
2681
+ - @return {boolean} `true` when the name belongs to the embedded configurable-tool subset.
2682
+
2683
+ ### fn `export function normalizeEnabledPiUsereqTools(value: unknown): PiUsereqStartupToolName[]` (L133-140)
2684
+ - @brief Normalizes a user-configured active-tool list.
2685
+ - @details Returns the default enabled-tool tuple when the input is not an array. Otherwise filters to string entries, removes names outside the configurable tool set, and deduplicates while preserving first-seen order. Time complexity is O(n). No external state is mutated.
2686
+ - @param[in] value {unknown} Raw configuration payload for `enabled-tools`.
2687
+ - @return {PiUsereqStartupToolName[]} Deduplicated canonical tool names.
2688
+ - @satisfies REQ-064
2689
+ - @post Returned values are members of `PI_USEREQ_STARTUP_TOOL_NAMES` only.
2690
+
2691
+ ## Symbol Index
2692
+ |Symbol|Kind|Vis|Lines|Sig|
2693
+ |---|---|---|---|---|
2694
+ |`PiUsereqCustomToolName`|type||83||
2695
+ |`PiUsereqEmbeddedToolName`|type||89||
2696
+ |`PiUsereqStartupToolName`|type||95||
2697
+ |`isPiUsereqEmbeddedToolName`|fn||121-123|export function isPiUsereqEmbeddedToolName(name: string):...|
2698
+ |`normalizeEnabledPiUsereqTools`|fn||133-140|export function normalizeEnabledPiUsereqTools(value: unkn...|
2699
+
2700
+
2701
+ ---
2702
+
2703
+ # prompts.ts | TypeScript | 184L | 5 symbols | 4 imports | 11 comments
2704
+ > Path: `src/core/prompts.ts`
2705
+ - @brief Renders bundled pi-usereq prompts for the current project context.
2706
+ - @details Applies placeholder substitution, legacy tool-name rewrites, and conditional pi.dev conformance guidance before prompt text is sent to the agent. Runtime is linear in prompt size plus replacement count. Side effects are limited to filesystem reads used for manifest checks and bundled prompt loading.
2707
+
2708
+ ## Imports
2709
+ ```
2710
+ import fs from "node:fs";
2711
+ import path from "node:path";
2712
+ import { buildPromptReplacementPaths, type UseReqConfig } from "./config.js";
2713
+ import { readBundledPrompt } from "./resources.js";
2714
+ ```
2715
+
2716
+ ## Definitions
2717
+
2718
+ ### fn `function buildPiDevConformanceBlock(promptName: string, projectBase: string): string` (L96-105)
2719
+ - @brief Builds the conditional pi.dev conformance block for one rendered prompt.
2720
+ - @details Emits the manifest-driven rules only when the selected bundled prompt can analyze or mutate source code and the project root contains the pi.dev manifest. Time complexity O(1). No filesystem writes.
2721
+ - @param[in] promptName {string} Bundled prompt identifier.
2722
+ - @param[in] projectBase {string} Absolute project root used for manifest existence checks.
2723
+ - @return {string} Markdown bullet block or the empty string when injection is not applicable.
2724
+ - @satisfies REQ-032, REQ-033, REQ-034, REQ-108
2725
+
2726
+ ### fn `function injectPiDevConformanceBlock(text: string, promptName: string, projectBase: string): string` (L116-123)
2727
+ - @brief Injects the pi.dev conformance block into the prompt behavior section.
2728
+ - @details Inserts the block immediately after the `## Behavior` heading so downstream agents evaluate the rule before workflow steps. Leaves prompts unchanged when no behavior section exists or the block is already present. Time complexity O(n).
2729
+ - @param[in] text {string} Prompt markdown after placeholder replacement.
2730
+ - @param[in] promptName {string} Bundled prompt identifier.
2731
+ - @param[in] projectBase {string} Absolute project root used for manifest existence checks.
2732
+ - @return {string} Prompt markdown with zero or one injected conformance block.
2733
+ - @satisfies REQ-032, REQ-033, REQ-034, REQ-108
2734
+
2735
+ ### fn `export function adaptPromptForInternalTools(text: string): string` (L132-138)
2736
+ - @brief Rewrites bundled prompt tool references from legacy `req --...` syntax to internal tool names.
2737
+ - @details Applies deterministic global regex replacements so prompt text matches the extension-registered tool surface instead of the standalone CLI spelling. Time complexity O(p*r) where p is pattern count and r is prompt length.
2738
+ - @param[in] text {string} Prompt markdown before tool-reference normalization.
2739
+ - @return {string} Prompt markdown with internal tool names.
2740
+ - @satisfies REQ-003
2741
+
2742
+ ### fn `export function applyReplacements(text: string, replacements: Record<string, string>): string` (L148-154)
2743
+ - @brief Applies literal placeholder replacements to bundled prompt markdown.
2744
+ - @details Replaces every placeholder token using split/join semantics so all occurrences are updated without regex escaping. Time complexity O(t*n) where t is replacement count and n is prompt length.
2745
+ - @param[in] text {string} Prompt markdown containing placeholder tokens.
2746
+ - @param[in] replacements {Record<string, string>} Token-to-value map.
2747
+ - @return {string} Prompt markdown with all placeholder tokens expanded.
2748
+ - @satisfies REQ-002
2749
+
2750
+ ### fn `export function renderPrompt(` (L166-184)
2751
+ - @brief Renders a bundled prompt for the current project context.
2752
+ - @details Loads the bundled markdown template, expands configuration-derived placeholders, injects conditional pi.dev conformance guidance, and rewrites legacy tool references to internal names. Time complexity O(n) relative to prompt size. No tracked files are modified.
2753
+ - @param[in] promptName {string} Bundled prompt identifier.
2754
+ - @param[in] args {string} Raw user-supplied prompt arguments.
2755
+ - @param[in] projectBase {string} Absolute project root used for placeholder and manifest resolution.
2756
+ - @param[in] config {UseReqConfig} Effective project configuration used for path substitutions.
2757
+ - @return {string} Fully rendered prompt markdown ready for `pi.sendUserMessage(...)`.
2758
+ - @satisfies REQ-002, REQ-003, REQ-032, REQ-033, REQ-034, REQ-108
2759
+
2760
+ ## Symbol Index
2761
+ |Symbol|Kind|Vis|Lines|Sig|
2762
+ |---|---|---|---|---|
2763
+ |`buildPiDevConformanceBlock`|fn||96-105|function buildPiDevConformanceBlock(promptName: string, p...|
2764
+ |`injectPiDevConformanceBlock`|fn||116-123|function injectPiDevConformanceBlock(text: string, prompt...|
2765
+ |`adaptPromptForInternalTools`|fn||132-138|export function adaptPromptForInternalTools(text: string)...|
2766
+ |`applyReplacements`|fn||148-154|export function applyReplacements(text: string, replaceme...|
2767
+ |`renderPrompt`|fn||166-184|export function renderPrompt(|
2768
+
2769
+
2770
+ ---
2771
+
2772
+ # reference-payload.ts | TypeScript | 818L | 28 symbols | 5 imports | 27 comments
2773
+ > Path: `src/core/reference-payload.ts`
2774
+ - @brief Builds agent-oriented JSON payloads for `files-references` and `references`.
2775
+ - @details Converts analyzed source files into deterministic JSON sections ordered for LLM traversal, including repository structure, per-file metrics, imports, symbols, structured Doxygen fields, and structured comment evidence. Runtime is O(F log F + S) where F is file count and S is total source size. Side effects are limited to filesystem reads and optional stderr logging.
2776
+
2777
+ ## Imports
2778
+ ```
2779
+ import fs from "node:fs";
2780
+ import path from "node:path";
2781
+ import {
2782
+ import { detectLanguage } from "./compress.js";
2783
+ import {
2784
+ ```
2785
+
2786
+ ## Definitions
2787
+
2788
+ - type `export type ReferenceToolScope = "explicit-files" | "configured-source-directories";` (L27)
2789
+ - @brief Enumerates supported references-payload scopes.
2790
+ - @details Distinguishes explicit-file requests from configured project scans while preserving one stable JSON contract. The alias is compile-time only and introduces no runtime cost.
2791
+ - type `export type ReferenceFileStatus = "analyzed" | "error" | "skipped";` (L33)
2792
+ - @brief Enumerates supported per-file references entry statuses.
2793
+ - @details Separates analyzed files, analysis failures, and skipped inputs so downstream agents can branch without reparsing stderr text. The alias is compile-time only and introduces no runtime cost.
2794
+ ### iface `export interface ReferenceLineRange` (L39-43)
2795
+ - @brief Describes one numeric source line range.
2796
+ - @details Exposes start and end line numbers plus the same inclusive range as a numeric tuple for direct agent access. The interface is compile-time only and introduces no runtime cost.
2797
+
2798
+ ### iface `export interface ReferenceImportEntry extends ReferenceLineRange` : ReferenceLineRange (L49-52)
2799
+ - @brief Describes one structured import record.
2800
+ - @details Stores the normalized import identity, raw import statement, and declaration line range without requiring agents to parse markdown blocks. The interface is compile-time only and introduces no runtime cost.
2801
+
2802
+ ### iface `export interface ReferenceCommentEntry extends ReferenceLineRange` : ReferenceLineRange (L58-61)
2803
+ - @brief Describes one structured standalone or attached comment record.
2804
+ - @details Preserves normalized comment text plus per-line comment fragments so agents can consume comment evidence without reparsing source delimiters. The interface is compile-time only and introduces no runtime cost.
2805
+
2806
+ ### iface `export interface ReferenceExitPointEntry` (L67-70)
2807
+ - @brief Describes one structured exit-point annotation.
2808
+ - @details Preserves the normalized exit expression text together with its source line number for downstream reasoning about control flow hints. The interface is compile-time only and introduces no runtime cost.
2809
+
2810
+ ### iface `export interface ReferenceSymbolEntry extends ReferenceLineRange` : ReferenceLineRange (L76-96)
2811
+ - @brief Describes one structured symbol record.
2812
+ - @details Orders direct-access identity fields before hierarchy, locations, Doxygen metadata, and comment evidence so agents can branch without reparsing monolithic summaries. The interface is compile-time only and introduces no runtime cost.
2813
+
2814
+ ### iface `export interface ReferenceToolFileEntry extends ReferenceLineRange` : ReferenceLineRange (L102-125)
2815
+ - @brief Describes one per-file references payload entry.
2816
+ - @details Stores canonical path identity, filesystem status, line metrics, structured imports, structured symbols, structured comment evidence, and optional file-level Doxygen metadata. The interface is compile-time only and introduces no runtime cost.
2817
+
2818
+ ### iface `export interface ReferenceToolRequestSection` (L131-140)
2819
+ - @brief Describes the request section of the references payload.
2820
+ - @details Captures tool identity, scope, base directory, requested path inventory, and configured source-directory scope so agents can reason about how the file set was selected. The interface is compile-time only and introduces no runtime cost.
2821
+
2822
+ ### iface `export interface ReferenceToolSummarySection` (L146-157)
2823
+ - @brief Describes the summary section of the references payload.
2824
+ - @details Exposes aggregate file, symbol, import, comment, and Doxygen counts as numeric fields plus deterministic symbol-kind totals. The interface is compile-time only and introduces no runtime cost.
2825
+
2826
+ ### iface `export interface ReferenceRepositoryTreeNode` (L163-169)
2827
+ - @brief Describes one repository tree node in the references payload.
2828
+ - @details Encodes directory and file hierarchy without ASCII-art decoration so agents can traverse repository structure as structured JSON. The interface is compile-time only and introduces no runtime cost.
2829
+
2830
+ ### iface `export interface ReferenceToolRepositorySection` (L175-181)
2831
+ - @brief Describes the repository section of the references payload.
2832
+ - @details Stores the base path, configured source-directory scope, canonical file list, and structured directory tree used during analysis. The interface is compile-time only and introduces no runtime cost.
2833
+
2834
+ ### iface `export interface ReferenceToolPayload` (L187-192)
2835
+ - @brief Describes the full agent-oriented references payload.
2836
+ - @details Orders the top-level sections as request, summary, repository, and files for deterministic downstream traversal. The interface is compile-time only and introduces no runtime cost.
2837
+
2838
+ ### iface `export interface BuildReferenceToolPayloadOptions` (L198-205)
2839
+ - @brief Describes the options required to build one references payload.
2840
+ - @details Supplies tool identity, scope, base directory, requested paths, and optional configured source directories while keeping payload construction deterministic. The interface is compile-time only and introduces no runtime cost.
2841
+
2842
+ ### fn `function canonicalizeReferencePath(targetPath: string, baseDir: string): string` (L214-222)
2843
+ - @brief Canonicalizes one filesystem path relative to the payload base directory.
2844
+ - @details Emits a slash-normalized relative path when the target is under the base directory; otherwise emits the normalized absolute path. Runtime is O(p) in path length. No side effects occur.
2845
+ - @param[in] targetPath {string} Absolute or relative filesystem path.
2846
+ - @param[in] baseDir {string} Base directory used for relative canonicalization.
2847
+ - @return {string} Canonicalized path string.
2848
+
2849
+ ### fn `function buildLineRange(startLineNumber: number, endLineNumber: number): ReferenceLineRange` (L231-237)
2850
+ - @brief Builds one structured line-range record.
2851
+ - @details Duplicates the inclusive range as start, end, and tuple fields so callers can address whichever shape is most convenient. Runtime is O(1). No side effects occur.
2852
+ - @param[in] startLineNumber {number} Inclusive start line number.
2853
+ - @param[in] endLineNumber {number} Inclusive end line number.
2854
+ - @return {ReferenceLineRange} Structured line-range record.
2855
+
2856
+ ### fn `function extractCommentText(commentElement: SourceElement, maxLength = 0): string` (L246-266)
2857
+ - @brief Extracts normalized plain text from one comment element.
2858
+ - @details Removes language comment markers, drops delimiter-only lines, joins content with spaces, and optionally truncates the result. Runtime is O(n) in comment length. No side effects occur.
2859
+ - @param[in] commentElement {SourceElement} Comment element.
2860
+ - @param[in] maxLength {number} Optional maximum output length; `0` disables truncation.
2861
+ - @return {string} Cleaned comment text.
2862
+
2863
+ ### fn `function extractCommentLines(commentElement: SourceElement): string[]` (L274-288)
2864
+ - @brief Extracts cleaned individual lines from one comment element.
2865
+ - @details Removes language comment markers while preserving line granularity for structured comment payloads. Runtime is O(n) in comment length. No side effects occur.
2866
+ - @param[in] commentElement {SourceElement} Comment element.
2867
+ - @return {string[]} Cleaned comment lines.
2868
+
2869
+ ### fn `function buildCommentMaps(elements: SourceElement[]): [Record<number, SourceElement[]>, SourceElement[], string]` (L296-346)
2870
+ - @brief Associates nearby comment blocks with definitions and standalone comment groups.
2871
+ - @details Reuses the repository comment-attachment heuristic that binds comments within three lines of a definition while preserving early file-description text. Runtime is O(n log n). No side effects occur.
2872
+ - @param[in] elements {SourceElement[]} Analyzed source elements.
2873
+ - @return {[Record<number, SourceElement[]>, SourceElement[], string]} Attached-comment map, standalone comments, and compact file description.
2874
+
2875
+ ### fn `function resolveSymbolName(element: SourceElement): string` (L354-356)
2876
+ - @brief Resolves one stable symbol name from an analyzed element.
2877
+ - @details Prefers explicit analyzer name metadata, then falls back to the derived signature or the first source line so every symbol retains a direct-access identifier. Runtime is O(1). No side effects occur.
2878
+ - @param[in] element {SourceElement} Source element.
2879
+ - @return {string} Stable symbol name.
2880
+
2881
+ ### fn `function resolveParentElement(definitions: SourceElement[], child: SourceElement): SourceElement | undefined` (L365-374)
2882
+ - @brief Resolves the direct parent element for one child symbol.
2883
+ - @details Matches by parent name plus inclusive line containment and chooses the deepest enclosing definition. Runtime is O(n) in definition count. No side effects occur.
2884
+ - @param[in] definitions {SourceElement[]} Sorted definition elements.
2885
+ - @param[in] child {SourceElement} Candidate child symbol.
2886
+ - @return {SourceElement | undefined} Matched parent definition when available.
2887
+
2888
+ ### fn `function buildCommentEntry(commentElement: SourceElement): ReferenceCommentEntry` (L382-389)
2889
+ - @brief Builds one structured comment record from a comment element.
2890
+ - @details Preserves numeric line-range metadata plus normalized text and per-line fragments. Runtime is O(n) in comment length. No side effects occur.
2891
+ - @param[in] commentElement {SourceElement} Source comment element.
2892
+ - @return {ReferenceCommentEntry} Structured comment record.
2893
+
2894
+ ### fn `function buildRepositoryTree(canonicalPaths: string[]): ReferenceRepositoryTreeNode` (L397-456)
2895
+ - @brief Builds one structured repository tree from canonical file paths.
2896
+ - @details Materializes a nested directory map and converts it into recursively ordered JSON nodes without decorative ASCII formatting. Runtime is O(n log n) in path count. No side effects occur.
2897
+ - @param[in] canonicalPaths {string[]} Canonical file paths.
2898
+ - @return {ReferenceRepositoryTreeNode} Structured repository tree rooted at `.`.
2899
+
2900
+ ### fn `const ensureDirectory = (parent: ReferenceRepositoryTreeNode, nodeName: string, relativePath: string): ReferenceRepositoryTreeNode =>` (L406-420)
2901
+
2902
+ ### fn `const finalizeNode = (node: ReferenceRepositoryTreeNode): ReferenceRepositoryTreeNode =>` (L442-453)
2903
+
2904
+ ### fn `function analyzeReferenceFile(` (L469-662)
2905
+ - @brief Builds one analyzed file entry for the references payload.
2906
+ - @details Parses the file with `SourceAnalyzer`, extracts structured imports and symbols, attaches structured Doxygen fields, and preserves standalone comment evidence. Runtime is O(S log S) in file size and symbol count. Side effects are limited to filesystem reads and optional stderr logging.
2907
+ - @param[in] analyzer {SourceAnalyzer} Shared source analyzer instance.
2908
+ - @param[in] inputPath {string} Caller-provided input path.
2909
+ - @param[in] absolutePath {string} Absolute file path.
2910
+ - @param[in] requestIndex {number} Zero-based request index.
2911
+ - @param[in] baseDir {string} Base directory used for canonical paths.
2912
+ - @param[in] verbose {boolean} When `true`, emit per-file progress diagnostics to stderr.
2913
+ - @return {ReferenceToolFileEntry} Structured file entry.
2914
+
2915
+ ### fn `export function buildReferenceToolPayload(options: BuildReferenceToolPayloadOptions): ReferenceToolPayload` (L671-796)
2916
+ - @brief Builds the full agent-oriented references payload.
2917
+ - @details Validates requested paths against the filesystem, analyzes processable files in caller order, preserves skipped and failed inputs in structured file entries, computes aggregate numeric totals, and emits a structured repository tree. Runtime is O(F log F + S). Side effects are limited to filesystem reads and optional stderr logging.
2918
+ - @param[in] options {BuildReferenceToolPayloadOptions} Payload-construction options.
2919
+ - @return {ReferenceToolPayload} Structured references payload ordered as request, summary, repository, and files.
2920
+ - @satisfies REQ-011, REQ-014, REQ-076, REQ-077, REQ-078, REQ-079
2921
+
2922
+ ### fn `export function buildReferenceToolExecutionStderr(payload: ReferenceToolPayload): string` (L804-818)
2923
+ - @brief Builds deterministic stderr diagnostics from a references payload.
2924
+ - @details Serializes skipped-input and analysis-error entries into stable newline-delimited diagnostics while leaving fully analyzed payloads silent. Runtime is O(n) in file-entry count. No side effects occur.
2925
+ - @param[in] payload {ReferenceToolPayload} Structured references payload.
2926
+ - @return {string} Newline-delimited diagnostics.
2927
+
2928
+ ## Symbol Index
2929
+ |Symbol|Kind|Vis|Lines|Sig|
2930
+ |---|---|---|---|---|
2931
+ |`ReferenceToolScope`|type||27||
2932
+ |`ReferenceFileStatus`|type||33||
2933
+ |`ReferenceLineRange`|iface||39-43|export interface ReferenceLineRange|
2934
+ |`ReferenceImportEntry`|iface||49-52|export interface ReferenceImportEntry extends ReferenceLi...|
2935
+ |`ReferenceCommentEntry`|iface||58-61|export interface ReferenceCommentEntry extends ReferenceL...|
2936
+ |`ReferenceExitPointEntry`|iface||67-70|export interface ReferenceExitPointEntry|
2937
+ |`ReferenceSymbolEntry`|iface||76-96|export interface ReferenceSymbolEntry extends ReferenceLi...|
2938
+ |`ReferenceToolFileEntry`|iface||102-125|export interface ReferenceToolFileEntry extends Reference...|
2939
+ |`ReferenceToolRequestSection`|iface||131-140|export interface ReferenceToolRequestSection|
2940
+ |`ReferenceToolSummarySection`|iface||146-157|export interface ReferenceToolSummarySection|
2941
+ |`ReferenceRepositoryTreeNode`|iface||163-169|export interface ReferenceRepositoryTreeNode|
2942
+ |`ReferenceToolRepositorySection`|iface||175-181|export interface ReferenceToolRepositorySection|
2943
+ |`ReferenceToolPayload`|iface||187-192|export interface ReferenceToolPayload|
2944
+ |`BuildReferenceToolPayloadOptions`|iface||198-205|export interface BuildReferenceToolPayloadOptions|
2945
+ |`canonicalizeReferencePath`|fn||214-222|function canonicalizeReferencePath(targetPath: string, ba...|
2946
+ |`buildLineRange`|fn||231-237|function buildLineRange(startLineNumber: number, endLineN...|
2947
+ |`extractCommentText`|fn||246-266|function extractCommentText(commentElement: SourceElement...|
2948
+ |`extractCommentLines`|fn||274-288|function extractCommentLines(commentElement: SourceElemen...|
2949
+ |`buildCommentMaps`|fn||296-346|function buildCommentMaps(elements: SourceElement[]): [Re...|
2950
+ |`resolveSymbolName`|fn||354-356|function resolveSymbolName(element: SourceElement): string|
2951
+ |`resolveParentElement`|fn||365-374|function resolveParentElement(definitions: SourceElement[...|
2952
+ |`buildCommentEntry`|fn||382-389|function buildCommentEntry(commentElement: SourceElement)...|
2953
+ |`buildRepositoryTree`|fn||397-456|function buildRepositoryTree(canonicalPaths: string[]): R...|
2954
+ |`ensureDirectory`|fn||406-420|const ensureDirectory = (parent: ReferenceRepositoryTreeN...|
2955
+ |`finalizeNode`|fn||442-453|const finalizeNode = (node: ReferenceRepositoryTreeNode):...|
2956
+ |`analyzeReferenceFile`|fn||469-662|function analyzeReferenceFile(|
2957
+ |`buildReferenceToolPayload`|fn||671-796|export function buildReferenceToolPayload(options: BuildR...|
2958
+ |`buildReferenceToolExecutionStderr`|fn||804-818|export function buildReferenceToolExecutionStderr(payload...|
2959
+
2960
+
2961
+ ---
2962
+
2963
+ # resources.ts | TypeScript | 63L | 4 symbols | 3 imports | 5 comments
2964
+ > Path: `src/core/resources.ts`
2965
+ - @brief Resolves installation-owned bundled resource locations.
2966
+ - @details Encapsulates installation-path discovery, bundled-resource validation, prompt enumeration, and prompt loading directly from the installed extension payload. Runtime is proportional to directory-entry enumeration and prompt file size. Side effects are limited to filesystem reads.
2967
+
2968
+ ## Imports
2969
+ ```
2970
+ import fs from "node:fs";
2971
+ import path from "node:path";
2972
+ import { getInstallationPath, RESOURCE_ROOT_DIRNAME } from "./path-context.js";
2973
+ ```
2974
+
2975
+ ## Definitions
2976
+
2977
+ ### fn `export function getBundledResourceRoot(): string` (L16-18)
2978
+ - @brief Resolves the bundled resource directory inside the installed extension payload.
2979
+ - @details Joins the installation path with `resources`, producing the immutable source tree used for prompt, template, and guideline access during runtime. Time complexity is O(1). No I/O side effects occur.
2980
+ - @return {string} Absolute bundled resource root path.
2981
+
2982
+ ### fn `export function ensureBundledResourcesAccessible(): string` (L26-38)
2983
+ - @brief Validates that installed bundled resources are accessible.
2984
+ - @details Verifies that the installation-owned resource root plus `prompts`, `templates`, and `guidelines` directories exist before prompt or tool execution. Runtime is O(1) plus bounded filesystem metadata checks. Side effects are limited to filesystem reads.
2985
+ - @return {string} Absolute bundled resource root path.
2986
+ - @throws {Error} Propagates a deterministic error when required installed resource directories are missing.
2987
+
2988
+ ### fn `export function readBundledPrompt(promptName: string): string` (L47-50)
2989
+ - @brief Reads one bundled markdown prompt by logical prompt name.
2990
+ - @details Resolves the prompt file under the installation-owned `resources/prompts` directory, validates resource accessibility, and loads it as UTF-8 text. Time complexity is O(n) in file size. Side effects are limited to filesystem reads.
2991
+ - @param[in] promptName {string} Prompt identifier without the `.md` suffix.
2992
+ - @return {string} Raw prompt markdown content.
2993
+ - @throws {Error} Propagates `fs.readFileSync` errors when the prompt file is missing or unreadable.
2994
+
2995
+ ### fn `export function listBundledPromptNames(): string[]` (L57-63)
2996
+ - @brief Lists bundled prompt identifiers available in the installed extension payload.
2997
+ - @details Scans the installation-owned prompt directory, keeps visible markdown files only, strips the `.md` suffix, and returns a lexicographically sorted list. Time complexity is O(n log n). Side effects are limited to filesystem reads.
2998
+ - @return {string[]} Sorted prompt names without file extensions.
2999
+
3000
+ ## Symbol Index
3001
+ |Symbol|Kind|Vis|Lines|Sig|
3002
+ |---|---|---|---|---|
3003
+ |`getBundledResourceRoot`|fn||16-18|export function getBundledResourceRoot(): string|
3004
+ |`ensureBundledResourcesAccessible`|fn||26-38|export function ensureBundledResourcesAccessible(): string|
3005
+ |`readBundledPrompt`|fn||47-50|export function readBundledPrompt(promptName: string): st...|
3006
+ |`listBundledPromptNames`|fn||57-63|export function listBundledPromptNames(): string[]|
3007
+
3008
+
3009
+ ---
3010
+
3011
+ # runtime-project-paths.ts | TypeScript | 99L | 6 symbols | 4 imports | 7 comments
3012
+ > Path: `src/core/runtime-project-paths.ts`
3013
+ - @brief Derives runtime-only repository and base-path facts.
3014
+ - @details Centralizes git-repository probing, repository-root resolution, and base-path-to-git-path formatting for extension status, tool execution, and CLI flows. Runtime is dominated by git subprocess execution plus path normalization. Side effects are limited to subprocess spawning.
3015
+
3016
+ ## Imports
3017
+ ```
3018
+ import path from "node:path";
3019
+ import { spawnSync } from "node:child_process";
3020
+ import { ReqError } from "./errors.js";
3021
+ import { isSameOrAncestorPath, normalizePathSlashes } from "./path-context.js";
3022
+ ```
3023
+
3024
+ ## Definitions
3025
+
3026
+ ### fn `function runGitCapture(command: string[], cwd?: string): ReturnType<typeof spawnSync>` (L19-24)
3027
+ - @brief Executes one git subprocess and captures UTF-8 output.
3028
+ - @details Delegates to `spawnSync`, keeps execution synchronous for deterministic command flows, and supports an optional working directory. Runtime is dominated by the spawned git process. Side effects include subprocess creation.
3029
+ - @param[in] command {string[]} Git executable plus argument vector.
3030
+ - @param[in] cwd {string | undefined} Optional working directory.
3031
+ - @return {ReturnType<typeof spawnSync>} Captured subprocess result.
3032
+
3033
+ ### fn `export function isInsideGitRepo(targetPath: string): boolean` (L33-36)
3034
+ - @brief Tests whether one path is inside a git work tree.
3035
+ - @details Executes `git rev-parse --is-inside-work-tree` in the supplied directory and returns `true` only for a successful literal `true` response. Runtime is dominated by git execution. Side effects include subprocess creation.
3036
+ - @param[in] targetPath {string} Directory to probe.
3037
+ - @return {boolean} `true` when the directory belongs to a git work tree.
3038
+ - @satisfies REQ-145
3039
+
3040
+ ### fn `export function resolveGitRoot(targetPath: string): string` (L46-52)
3041
+ - @brief Resolves the repository root for one path inside a git work tree.
3042
+ - @details Executes `git rev-parse --show-toplevel`, normalizes the result to an absolute path, and rejects non-repository paths with `ReqError`. Runtime is dominated by git execution. Side effects include subprocess creation.
3043
+ - @param[in] targetPath {string} Directory inside the target repository.
3044
+ - @return {string} Absolute repository-root path.
3045
+ - @throws {ReqError} Throws when the path is not inside a git repository.
3046
+ - @satisfies REQ-145
3047
+
3048
+ ### fn `export function resolveRuntimeGitPath(executionPath: string): string | undefined` (L61-68)
3049
+ - @brief Resolves the runtime git root for one execution path.
3050
+ - @details Returns `undefined` when the path is outside a git repository. Otherwise resolves the repository root and rejects roots that are not identical to or ancestors of the execution path. Runtime is dominated by git execution. Side effects include subprocess creation.
3051
+ - @param[in] executionPath {string} Runtime execution path.
3052
+ - @return {string | undefined} Absolute repository-root path or `undefined` when unavailable.
3053
+ - @satisfies REQ-105, REQ-145
3054
+
3055
+ ### fn `export function formatBasePathRelativeToGitPath(basePath: string, gitPath: string | undefined): string` (L78-88)
3056
+ - @brief Formats the runtime `base-path` relative to the runtime `git-path`.
3057
+ - @details Returns `.` when the repository root is unavailable or identical to the base path. Otherwise returns the slash-normalized relative path from `git-path` to `base-path`. Runtime is O(p) in path length. No external state is mutated.
3058
+ - @param[in] basePath {string} Runtime base path.
3059
+ - @param[in] gitPath {string | undefined} Runtime repository root.
3060
+ - @return {string} Relative base-path token for status rendering.
3061
+ - @satisfies REQ-148
3062
+
3063
+ ### fn `export function formatAbsoluteGitPath(gitPath: string | undefined): string` (L97-99)
3064
+ - @brief Formats the runtime git path for status rendering.
3065
+ - @details Returns a slash-normalized absolute path or an empty string when no repository root is available. Runtime is O(p) in path length. No external state is mutated.
3066
+ - @param[in] gitPath {string | undefined} Runtime repository root.
3067
+ - @return {string} Absolute repository path or an empty string.
3068
+ - @satisfies REQ-147
3069
+
3070
+ ## Symbol Index
3071
+ |Symbol|Kind|Vis|Lines|Sig|
3072
+ |---|---|---|---|---|
3073
+ |`runGitCapture`|fn||19-24|function runGitCapture(command: string[], cwd?: string): ...|
3074
+ |`isInsideGitRepo`|fn||33-36|export function isInsideGitRepo(targetPath: string): boolean|
3075
+ |`resolveGitRoot`|fn||46-52|export function resolveGitRoot(targetPath: string): string|
3076
+ |`resolveRuntimeGitPath`|fn||61-68|export function resolveRuntimeGitPath(executionPath: stri...|
3077
+ |`formatBasePathRelativeToGitPath`|fn||78-88|export function formatBasePathRelativeToGitPath(basePath:...|
3078
+ |`formatAbsoluteGitPath`|fn||97-99|export function formatAbsoluteGitPath(gitPath: string | u...|
3079
+
3080
+
3081
+ ---
3082
+
3083
+ # settings-menu.ts | TypeScript | 233L | 11 symbols | 2 imports | 12 comments
3084
+ > Path: `src/core/settings-menu.ts`
3085
+ - @brief Renders pi-usereq configuration menus with the shared pi.dev settings style.
3086
+ - @details Wraps `SettingsList` in one extension-command helper that exposes right-aligned current values, built-in circular scrolling, bottom-line descriptions, and a deterministic bridge for offline test harnesses. Runtime is O(n) in visible choice count plus user interaction cost. Side effects are limited to transient custom-UI rendering.
3087
+
3088
+ ## Imports
3089
+ ```
3090
+ import { getSettingsListTheme, type ThemeColor, type ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
3091
+ import { Container, SettingsList, Text, type Component, type SettingItem, type SettingsListTheme } from "@mariozechner/pi-tui";
3092
+ ```
3093
+
3094
+ ## Definitions
3095
+
3096
+ ### iface `export interface PiUsereqSettingsMenuChoice` (L14-19)
3097
+ - @brief Describes one selectable pi-usereq settings-menu choice.
3098
+ - @details Stores the stable action identifier, left-column label, right-column current value, and bottom-line description consumed by the shared settings-menu renderer. The interface is compile-time only and introduces no runtime cost.
3099
+
3100
+ ### iface `export interface PiUsereqSettingsMenuBridge` (L25-30)
3101
+ - @brief Describes the offline bridge exposed by shared settings-menu components.
3102
+ - @details Lets deterministic harnesses and unit tests drive the same settings-menu choices by label without simulating raw terminal key streams. The interface is runtime-facing but carries no side effects by itself.
3103
+
3104
+ ### iface `export interface PiUsereqSettingsMenuComponent extends Component` : Component (L36-38)
3105
+ - @brief Represents a custom menu component augmented with the offline bridge.
3106
+ - @details Extends the generic TUI `Component` contract with one optional bridge field consumed only by deterministic test and debug harness adapters. The interface is compile-time only and introduces no runtime cost.
3107
+
3108
+ - type `type PiUsereqSettingsThemeColor = Extract<ThemeColor, "accent" | "muted" | "dim">;` (L46)
3109
+ - @brief Enumerates the CLI-supported theme tokens consumed by settings menus.
3110
+ - @details Narrows callback-local theme calls to the documented settings-list
3111
+ semantics used by the pi CLI. Compile-time only and introduces no runtime
3112
+ cost.
3113
+ ### iface `interface PiUsereqSettingsTheme` (L55-58)
3114
+ - @brief Describes the callback-local theme surface required by settings menus.
3115
+ - @details Captures the subset of the custom-UI theme API needed to rebuild
3116
+ title and fallback settings-list styling when the shared global theme is not
3117
+ available in tests or offline replay. Compile-time only and introduces no
3118
+ runtime cost.
3119
+
3120
+ ### fn `function buildFallbackPiUsereqSettingsListTheme(` (L70-82)
3121
+ - @brief Builds the fallback settings-list theme matching CLI settings semantics.
3122
+ - @details Mirrors the shared CLI settings theme token mapping for labels,
3123
+ values, descriptions, cursor, and hints while avoiding the global theme
3124
+ singleton used by the live pi runtime. Runtime is O(1). No external state is
3125
+ mutated.
3126
+ - @param[in] theme {PiUsereqSettingsTheme} Callback-local pi theme adapter.
3127
+ - @return {SettingsListTheme} Fallback settings-list theme.
3128
+ - @satisfies REQ-151, REQ-156
3129
+
3130
+ ### fn `function buildPiUsereqSettingsListTheme(` (L95-109)
3131
+ - @brief Resolves the settings-list theme used by pi-usereq configuration menus.
3132
+ - @details Prefers the shared CLI `getSettingsListTheme()` API so extension
3133
+ menus inherit active-theme behavior from pi itself, then falls back to an
3134
+ equivalent callback-local mapping when the shared theme singleton is
3135
+ unavailable in deterministic tests or offline replay. Runtime is O(1). No
3136
+ external state is mutated.
3137
+ - @param[in] theme {PiUsereqSettingsTheme} Callback-local pi theme adapter.
3138
+ - @return {SettingsListTheme} Settings-list theme used by pi-usereq menus.
3139
+ - @satisfies REQ-151, REQ-156
3140
+
3141
+ ### fn `function formatPiUsereqSettingsMenuTitle(` (L121-126)
3142
+ - @brief Formats the settings-menu title with active-theme semantics.
3143
+ - @details Applies the callback-local `accent` token and bold styling on every
3144
+ rebuild so custom-menu titles stay synchronized with live theme changes.
3145
+ Runtime is O(n) in title length. No external state is mutated.
3146
+ - @param[in] theme {PiUsereqSettingsTheme} Callback-local pi theme adapter.
3147
+ - @param[in] title {string} Menu title.
3148
+ - @return {string} Styled title text.
3149
+ - @satisfies REQ-151, REQ-156
3150
+
3151
+ ### fn `function createImmediateSelectionComponent(choiceId: string, done: (value?: string) => void): Component` (L135-147)
3152
+ - @brief Closes a settings menu immediately with one selected action identifier.
3153
+ - @details Provides the submenu callback used by `SettingsList` so pressing Enter on any menu row resolves the outer custom UI promise with the row identifier. Runtime is O(1). Side effects are limited to one custom-UI completion callback.
3154
+ - @param[in] choiceId {string} Stable choice identifier to emit.
3155
+ - @param[in] done {(value?: string) => void} Outer custom-UI completion callback.
3156
+ - @return {Component} Immediate-completion submenu component.
3157
+
3158
+ ### fn `function buildSettingItems(` (L156-167)
3159
+ - @brief Builds `SettingsList` items from one menu-choice vector.
3160
+ - @details Copies labels, current values, and descriptions into `SettingItem` records and attaches a submenu that resolves the outer custom UI with the selected choice identifier. Runtime is O(n) in choice count. No external state is mutated.
3161
+ - @param[in] choices {PiUsereqSettingsMenuChoice[]} Ordered menu-choice vector.
3162
+ - @param[in] done {(value?: string) => void} Outer custom-UI completion callback.
3163
+ - @return {SettingItem[]} `SettingsList` item vector.
3164
+
3165
+ ### fn `export async function showPiUsereqSettingsMenu(` (L178-233)
3166
+ - @brief Renders one shared pi-usereq settings menu and resolves the selected action.
3167
+ - @details Uses `ctx.ui.custom(...)` plus `SettingsList` so every configuration menu shares pi.dev styling, right-aligned current values, circular scrolling, and bottom-line descriptions. The returned custom component also exposes an offline bridge for deterministic tests and debug harnesses. Runtime is O(n) in visible choice count plus user interaction cost. Side effects are limited to transient custom-UI rendering.
3168
+ - @param[in] ctx {ExtensionCommandContext} Active command context.
3169
+ - @param[in] title {string} Menu title displayed in the heading and offline bridge.
3170
+ - @param[in] choices {PiUsereqSettingsMenuChoice[]} Ordered menu-choice vector.
3171
+ - @return {Promise<string | undefined>} Selected choice identifier or `undefined` when cancelled.
3172
+ - @satisfies REQ-151, REQ-152, REQ-153, REQ-154, REQ-156
3173
+
3174
+ ## Symbol Index
3175
+ |Symbol|Kind|Vis|Lines|Sig|
3176
+ |---|---|---|---|---|
3177
+ |`PiUsereqSettingsMenuChoice`|iface||14-19|export interface PiUsereqSettingsMenuChoice|
3178
+ |`PiUsereqSettingsMenuBridge`|iface||25-30|export interface PiUsereqSettingsMenuBridge|
3179
+ |`PiUsereqSettingsMenuComponent`|iface||36-38|export interface PiUsereqSettingsMenuComponent extends Co...|
3180
+ |`PiUsereqSettingsThemeColor`|type||46||
3181
+ |`PiUsereqSettingsTheme`|iface||55-58|interface PiUsereqSettingsTheme|
3182
+ |`buildFallbackPiUsereqSettingsListTheme`|fn||70-82|function buildFallbackPiUsereqSettingsListTheme(|
3183
+ |`buildPiUsereqSettingsListTheme`|fn||95-109|function buildPiUsereqSettingsListTheme(|
3184
+ |`formatPiUsereqSettingsMenuTitle`|fn||121-126|function formatPiUsereqSettingsMenuTitle(|
3185
+ |`createImmediateSelectionComponent`|fn||135-147|function createImmediateSelectionComponent(choiceId: stri...|
3186
+ |`buildSettingItems`|fn||156-167|function buildSettingItems(|
3187
+ |`showPiUsereqSettingsMenu`|fn||178-233|export async function showPiUsereqSettingsMenu(|
3188
+
3189
+
3190
+ ---
3191
+
3192
+ # source-analyzer.ts | TypeScript | 1721L | 18 symbols | 4 imports | 38 comments
3193
+ > Path: `src/core/source-analyzer.ts`
3194
+ - @brief Analyzes source files into language-agnostic structural elements and markdown references.
3195
+ - @details Defines the language-spec registry, source-element model, structural analyzer, Doxygen association logic, and markdown rendering helpers used by compression, reference generation, and construct search tools. Runtime is generally linear in source size plus language-pattern count. Side effects are limited to filesystem reads.
3196
+
3197
+ ## Imports
3198
+ ```
3199
+ import fs from "node:fs";
3200
+ import os from "node:os";
3201
+ import path from "node:path";
3202
+ import { formatDoxygenFieldsAsMarkdown, parseDoxygenComment } from "./doxygen-parser.js";
3203
+ ```
3204
+
3205
+ ## Definitions
3206
+
3207
+ ### enum `export enum ElementType` (L16-42)
3208
+ - @brief Enumerates the normalized source-element kinds emitted by the analyzer.
3209
+ - @details The enum lets language-specific regex matches collapse into a shared symbol taxonomy for downstream markdown generation and construct filtering. Access complexity is O(1).
3210
+
3211
+ ### class `export class SourceElement` (L48-95)
3212
+ - @brief Represents one analyzed source element or comment block.
3213
+ - @details Stores location metadata, extracted source text, normalized naming/signature data, hierarchy information, attached Doxygen fields, and body annotations used by downstream renderers. Instance initialization is O(1) aside from object assignment.
3214
+
3215
+ ### iface `export interface LanguageSpec` (L101-108)
3216
+ - @brief Describes language-specific parsing behavior for the source analyzer.
3217
+ - @details Each spec defines comment syntax, string delimiters, and ordered regex patterns mapping source lines to `ElementType` values. The interface is compile-time only and introduces no runtime cost.
3218
+
3219
+ ### fn `function re(pattern: string): RegExp` (L116-118)
3220
+ - @brief Creates a regular expression from a raw pattern string.
3221
+ - @details Wraps `new RegExp(...)` to keep the language-spec table compact and visually uniform. Runtime is O(1) relative to call-site complexity. No side effects occur.
3222
+ - @param[in] pattern {string} Raw regular-expression pattern.
3223
+ - @return {RegExp} Constructed regular expression.
3224
+
3225
+ ### fn `export function buildLanguageSpecs(): Record<string, LanguageSpec>` (L125-424)
3226
+ - @brief Builds the analyzer language-spec registry.
3227
+ - @details Materializes comment syntax, string delimiters, and ordered construct-detection regexes for all supported languages and aliases. Runtime is O(l) in the number of language definitions. No side effects occur.
3228
+ - @return {Record<string, LanguageSpec>} Language-spec map keyed by canonical names and aliases.
3229
+
3230
+ ### class `export class SourceAnalyzer` (L491-790)
3231
+ - @brief Performs language-aware structural analysis and metadata enrichment on source files.
3232
+ - @brief Matches explicit early-exit statements inside analyzed bodies.
3233
+ - @details Parses files into `SourceElement` records, derives signatures, hierarchy, visibility, inheritance, body annotations, and Doxygen fields, then exposes the enriched element list to higher-level renderers. Runtime is generally O(n * p) where n is line count and p is pattern count for the selected language. Side effects are limited to filesystem reads.
3234
+ - @details The regex captures return-like constructs that downstream markdown renderers should surface as exit annotations. Evaluation cost is linear in line length.
3235
+
3236
+ ### fn `const isFileLevelComment = (comment: SourceElement): boolean =>` (L983-986)
3237
+ - @brief Associates parsed Doxygen comments with analyzed elements.
3238
+ - @details Searches inline postfix comments, nearby preceding comments, and selected following postfix comments while excluding file-level comments, then stores the parsed Doxygen field map on each element. Runtime is O(n^2) in the worst case due to proximity scans across comments and elements. Side effect: mutates `element.doxygenFields`.
3239
+ - @param[in,out] elements {SourceElement[]} Elements to enrich.
3240
+ - @return {void} No return value.
3241
+
3242
+ ### fn `const hasBlockingElement = (comment: SourceElement): boolean =>` (L1007-1027)
3243
+
3244
+ ### fn `function mdLoc(element: SourceElement): string` (L1260-1262)
3245
+ - @brief Formats one element location for markdown output.
3246
+ - @details Returns either a single-line `Lx` token or an inclusive line-range token `Lx-y`. Runtime is O(1). No side effects occur.
3247
+ - @param[in] element {SourceElement} Source element.
3248
+ - @return {string} Markdown location token.
3249
+
3250
+ ### fn `function mdKind(element: SourceElement): string` (L1270-1299)
3251
+ - @brief Maps an element type to its compact markdown kind code.
3252
+ - @details Converts `ElementType` values into the abbreviated tokens used by reference markdown and symbol indexes. Runtime is O(1). No side effects occur.
3253
+ - @param[in] element {SourceElement} Source element.
3254
+ - @return {string} Compact kind code.
3255
+
3256
+ ### fn `function extractCommentText(commentElement: SourceElement, maxLength = 0): string` (L1308-1329)
3257
+ - @brief Extracts normalized plain text from a comment element.
3258
+ - @details Removes comment markers, drops language-specific block delimiters, joins lines with spaces, and optionally truncates the result. Runtime is O(n) in comment length. No side effects occur.
3259
+ - @param[in] commentElement {SourceElement} Comment element.
3260
+ - @param[in] maxLength {number} Optional maximum output length, where `0` disables truncation.
3261
+ - @return {string} Cleaned comment text.
3262
+
3263
+ ### fn `function extractCommentLines(commentElement: SourceElement): string[]` (L1337-1352)
3264
+ - @brief Extracts cleaned individual lines from a comment element.
3265
+ - @details Removes comment markers and delimiter-only lines while preserving line granularity for markdown rendering. Runtime is O(n) in comment length. No side effects occur.
3266
+ - @param[in] commentElement {SourceElement} Comment element.
3267
+ - @return {string[]} Cleaned comment lines.
3268
+
3269
+ ### fn `function buildCommentMaps(elements: SourceElement[]): [Record<number, SourceElement[]>, SourceElement[], string]` (L1360-1400)
3270
+ - @brief Builds lookup structures linking comments to definitions and file descriptions.
3271
+ - @details Sorts elements, associates nearby non-inline comments with following definitions, collects standalone comments, and derives a compact file description from early comment text. Runtime is O(n log n). No side effects occur.
3272
+ - @param[in] elements {SourceElement[]} Analyzed source elements.
3273
+ - @return {[Record<number, SourceElement[]>, SourceElement[], string]} Attached-comment map, standalone comments, and file description.
3274
+
3275
+ ### fn `function mergeDoxygenFields(baseFields: Record<string, string[]>, extraFields: Record<string, string[]>): Record<string, string[]>` (L1409-1415)
3276
+ - @brief Merges Doxygen field values into one accumulator map.
3277
+ - @details Appends values for matching tags without deduplication so relative source order is preserved. Runtime is O(v) in appended value count. Side effect: mutates `baseFields`.
3278
+ - @param[in] extraFields {Record<string, string[]>} Source field map.
3279
+ - @param[in,out] baseFields {Record<string, string[]>} Mutable destination field map.
3280
+ - @return {Record<string, string[]>} The mutated destination map.
3281
+
3282
+ ### fn `export function collectElementDoxygenFields(element: SourceElement): Record<string, string[]>` (L1423-1437)
3283
+ - @brief Aggregates all Doxygen fields associated with one element.
3284
+ - @details Starts with directly attached fields and then merges early body comments from the first three body lines when they parse as Doxygen. Runtime is O(c) in considered comment count. No external state is mutated.
3285
+ - @param[in] element {SourceElement} Source element.
3286
+ - @return {Record<string, string[]>} Aggregated Doxygen field map.
3287
+
3288
+ ### fn `export function collectFileLevelDoxygenFields(elements: SourceElement[]): Record<string, string[]>` (L1445-1456)
3289
+
3290
+ ### fn `export function formatMarkdown(` (L1469-1721)
3291
+ - @brief Renders analyzed source elements as the repository reference-markdown format.
3292
+ - @details Builds file metadata, imports, top-level definitions, child elements, comments, and a symbol index while incorporating Doxygen fields and optional legacy annotations. Runtime is O(n log n) in element count. No side effects occur.
3293
+ - @param[in] elements {SourceElement[]} Enriched source elements.
3294
+ - @param[in] filePath {string} Display file path.
3295
+ - @param[in] language {string} Canonical analyzer language identifier.
3296
+ - @param[in] specName {string} Human-readable language name.
3297
+ - @param[in] totalLines {number} Total source-line count.
3298
+ - @param[in] includeLegacyAnnotations {boolean} When `true`, include non-Doxygen comment annotations.
3299
+ - @return {string} Rendered markdown document for the file.
3300
+
3301
+ ### fn `function renderBodyAnnotations(` (L1695-1721)
3302
+ - @brief Renders body comments and exit-point annotations for one element.
3303
+ - @details Merges comment and exit maps, skips excluded line ranges, and emits normalized markdown lines that summarize body-level annotations. Runtime is O(a log a) in annotation count. No side effects occur.
3304
+ - @param[in] element {SourceElement} Source element whose body annotations should be rendered.
3305
+ - @param[in] indent {string} Prefix applied to each rendered annotation line.
3306
+ - @param[in] excludeRanges {ReadonlyArray<readonly [number, number]> | undefined} Optional line ranges to suppress.
3307
+ - @param[in,out] out {string[]} Markdown output buffer.
3308
+ - @return {void} No return value.
3309
+
3310
+ ## Symbol Index
3311
+ |Symbol|Kind|Vis|Lines|Sig|
3312
+ |---|---|---|---|---|
3313
+ |`ElementType`|enum||16-42|export enum ElementType|
3314
+ |`SourceElement`|class||48-95|export class SourceElement|
3315
+ |`LanguageSpec`|iface||101-108|export interface LanguageSpec|
3316
+ |`re`|fn||116-118|function re(pattern: string): RegExp|
3317
+ |`buildLanguageSpecs`|fn||125-424|export function buildLanguageSpecs(): Record<string, Lang...|
3318
+ |`SourceAnalyzer`|class||491-790|export class SourceAnalyzer|
3319
+ |`isFileLevelComment`|fn||983-986|const isFileLevelComment = (comment: SourceElement): bool...|
3320
+ |`hasBlockingElement`|fn||1007-1027|const hasBlockingElement = (comment: SourceElement): bool...|
3321
+ |`mdLoc`|fn||1260-1262|function mdLoc(element: SourceElement): string|
3322
+ |`mdKind`|fn||1270-1299|function mdKind(element: SourceElement): string|
3323
+ |`extractCommentText`|fn||1308-1329|function extractCommentText(commentElement: SourceElement...|
3324
+ |`extractCommentLines`|fn||1337-1352|function extractCommentLines(commentElement: SourceElemen...|
3325
+ |`buildCommentMaps`|fn||1360-1400|function buildCommentMaps(elements: SourceElement[]): [Re...|
3326
+ |`mergeDoxygenFields`|fn||1409-1415|function mergeDoxygenFields(baseFields: Record<string, st...|
3327
+ |`collectElementDoxygenFields`|fn||1423-1437|export function collectElementDoxygenFields(element: Sour...|
3328
+ |`collectFileLevelDoxygenFields`|fn||1445-1456|export function collectFileLevelDoxygenFields(elements: S...|
3329
+ |`formatMarkdown`|fn||1469-1721|export function formatMarkdown(|
3330
+ |`renderBodyAnnotations`|fn||1695-1721|function renderBodyAnnotations(|
3331
+
3332
+
3333
+ ---
3334
+
3335
+ # static-check.ts | TypeScript | 674L | 18 symbols | 7 imports | 34 comments
3336
+ > Path: `src/core/static-check.ts`
3337
+ - @brief Defines static-check language mappings and checker dispatch implementations.
3338
+ - @details Parses static-check configuration syntax, resolves file targets, and runs built-in or command-based analyzers such as Pylance and Ruff. Runtime is linear in file count plus external tool cost. Side effects include filesystem reads, PATH probing, process spawning, and console output.
3339
+
3340
+ ## Imports
3341
+ ```
3342
+ import fs from "node:fs";
3343
+ import path from "node:path";
3344
+ import process from "node:process";
3345
+ import { spawnSync } from "node:child_process";
3346
+ import fg from "fast-glob";
3347
+ import type { StaticCheckEntry } from "./config.js";
3348
+ import { ReqError } from "./errors.js";
3349
+ ```
3350
+
3351
+ ## Definitions
3352
+
3353
+ ### iface `export interface StaticCheckLanguageSupport` (L85-88)
3354
+ - @brief Describes supported extensions for one canonical static-check language.
3355
+ - @details The interface is used for UI rendering and capability reporting only. It is compile-time only and adds no runtime cost.
3356
+
3357
+ ### fn `export function getSupportedStaticCheckLanguages(): string[]` (L106-108)
3358
+ - @brief Returns the sorted list of canonical languages with extension support.
3359
+ - @details Deduplicates the extension map values and sorts them alphabetically for stable UI and error messages. Runtime is O(n log n). No side effects occur.
3360
+ - @return {string[]} Sorted canonical language names.
3361
+
3362
+ ### fn `export function getSupportedStaticCheckLanguageSupport(): StaticCheckLanguageSupport[]` (L115-126)
3363
+ - @brief Returns supported languages paired with their known file extensions.
3364
+ - @details Groups extensions by canonical language and emits alphabetically sorted extension lists. Runtime is O(n log n). No external state is mutated.
3365
+ - @return {StaticCheckLanguageSupport[]} Sorted language-support descriptors.
3366
+
3367
+ ### fn `function formatStaticCheckModules(): string` (L133-135)
3368
+ - @brief Formats the supported module list for diagnostics.
3369
+ - @details Joins `STATIC_CHECK_MODULES` with commas for direct insertion into error strings. Time complexity is O(n). No side effects occur.
3370
+ - @return {string} Comma-delimited module names.
3371
+
3372
+ ### fn `function splitCsvLikeTokens(specRhs: string): string[]` (L143-165)
3373
+ - @brief Splits a comma-delimited static-check specification while honoring quotes.
3374
+ - @details Performs a single pass over the right-hand side of `LANG=...`, preserving commas inside quoted segments. Runtime is O(n). No side effects occur.
3375
+ - @param[in] specRhs {string} Right-hand side of the enable-static-check specification.
3376
+ - @return {string[]} Parsed tokens with surrounding whitespace trimmed.
3377
+
3378
+ ### fn `export function parseEnableStaticCheck(spec: string): [string, StaticCheckEntry]` (L174-222)
3379
+ - @brief Parses one `LANG=MODULE[,CMD[,PARAM...]]` static-check specification.
3380
+ - @details Validates the language alias, canonicalizes the module name, enforces module-specific argument requirements, and returns a config entry ready for persistence. Runtime is O(n) in specification length. No external state is mutated.
3381
+ - @param[in] spec {string} Raw static-check specification string.
3382
+ - @return {[string, StaticCheckEntry]} Tuple of canonical language name and normalized checker configuration.
3383
+ - @throws {ReqError} Throws for missing separators, unknown languages, unknown modules, or missing required command arguments.
3384
+
3385
+ ### fn `export function buildStaticCheckEntryIdentity(language: string, entry: StaticCheckEntry): string` (L232-237)
3386
+ - @brief Builds the duplicate-identity token for one static-check entry.
3387
+ - @details Canonicalizes the language key, module name, command name, and parameter list into a stable JSON tuple used for merge deduplication. Runtime is O(p) in parameter count. No side effects occur.
3388
+ - @param[in] language {string} Canonical or alias language name associated with the entry.
3389
+ - @param[in] entry {StaticCheckEntry} Static-check configuration entry to normalize.
3390
+ - @return {string} Stable identity token suitable for equality comparison.
3391
+ - @satisfies REQ-036
3392
+
3393
+ ### fn `export function validateStaticCheckEntry(entry: StaticCheckEntry): void` (L247-258)
3394
+ - @brief Validates pre-persistence invariants for one static-check entry.
3395
+ - @details Rejects `Command` entries whose executable cannot be resolved before config writes while leaving non-command modules untouched. Runtime is O(p) in PATH entry count. Side effects are limited to filesystem reads.
3396
+ - @param[in] entry {StaticCheckEntry} Static-check configuration entry to validate.
3397
+ - @return {void} No return value.
3398
+ - @throws {ReqError} Throws when a `Command` entry omits `cmd` or resolves to a non-executable program.
3399
+ - @satisfies REQ-037
3400
+
3401
+ ### fn `function resolveFiles(inputs: string[]): string[]` (L266-290)
3402
+ - @brief Resolves explicit files, directories, and glob patterns into absolute file paths.
3403
+ - @details Expands glob inputs with `fast-glob`, enumerates direct children for directory inputs, accepts regular files, and warns for invalid entries. Runtime is O(n + m) where m is the total matched path count. Side effects are filesystem reads and warning output to stderr.
3404
+ - @param[in] inputs {string[]} Raw file, directory, or glob inputs.
3405
+ - @return {string[]} Unique absolute file paths.
3406
+
3407
+ ### class `export class StaticCheckBase` (L296-370)
3408
+ - @brief Provides the base implementation for file-oriented static checks.
3409
+ - @details Resolves input files once, emits standardized headers, and defines overridable `checkFile` and `emitLine` hooks used by concrete analyzers. Runtime is O(f) plus subclass checker cost. Side effects include console output.
3410
+
3411
+ ### fn `function detectPythonExecutable(projectBase?: string): string` (L378-398)
3412
+ - @brief Resolves the preferred Python executable for Python-based checkers.
3413
+ - @details Checks the project virtual environment first, then `PI_USEREQ_PYTHON`, then `python3`, then `python`, and finally falls back to the literal `python3` string. Runtime is O(c) in candidate count. Side effects are filesystem reads and PATH probing.
3414
+ - @param[in] projectBase {string | undefined} Optional project root used to probe `.venv/bin/python`.
3415
+ - @return {string} Executable path or command name.
3416
+
3417
+ ### class `export class StaticCheckPylance extends StaticCheckBase` : StaticCheckBase (L404-455)
3418
+ - @brief Runs Pyright/Pylance checks through the selected Python interpreter.
3419
+ - @details Invokes `python -m pyright` for each resolved file and emits standardized OK/FAIL records. Runtime is dominated by external checker execution. Side effects include process spawning and console output.
3420
+
3421
+ ### class `export class StaticCheckRuff extends StaticCheckBase` : StaticCheckBase (L461-509)
3422
+ - @brief Runs Ruff checks through the selected Python interpreter.
3423
+ - @details Invokes `python -m ruff check` for each resolved file and emits standardized OK/FAIL records. Runtime is dominated by external checker execution. Side effects include process spawning and console output.
3424
+
3425
+ ### class `export class StaticCheckCommand extends StaticCheckBase` : StaticCheckBase (L515-564)
3426
+ - @brief Runs an arbitrary external command as a static checker.
3427
+ - @brief Initializes a command-backed checker instance.
3428
+ - @details Validates command availability on PATH during construction, then invokes the command with configured extra arguments plus one target file at a time. Runtime is dominated by external command execution. Side effects include PATH probing, process spawning, and console output.
3429
+ - @details Validates that the executable exists on PATH before delegating file resolution to the base class and recording the command label. Runtime is O(p + f) where p is PATH entry count and f is resolved input count. Side effects are filesystem reads.
3430
+ - @param[in] cmd {string} Executable name.
3431
+ - @param[in] inputs {string[]} Raw file inputs.
3432
+ - @param[in] extraArgs {string[] | undefined} Extra command arguments.
3433
+ - @param[in] failOnly {boolean} When `true`, suppress successful-file output.
3434
+ - @throws {ReqError} Throws when the executable cannot be found on PATH.
3435
+
3436
+ ### fn `function isExecutableFile(candidate: string): boolean` (L572-582)
3437
+ - @brief Tests whether one filesystem path is executable.
3438
+ - @details Requires the candidate to exist, be a regular file, and pass `X_OK` access checks. Runtime is O(1). Side effects are limited to filesystem reads.
3439
+ - @param[in] candidate {string} Absolute or relative path to inspect.
3440
+ - @return {boolean} `true` when the candidate is executable by the current process.
3441
+
3442
+ ### fn `function findExecutable(cmd: string): string | undefined` (L590-601)
3443
+ - @brief Locates an executable by scanning the current PATH.
3444
+ - @details Checks each PATH directory for an executable file named exactly as the requested command. Runtime is O(p) in PATH entry count. Side effects are filesystem reads.
3445
+ - @param[in] cmd {string} Executable name to locate.
3446
+ - @return {string | undefined} Absolute executable path, or `undefined` when not found.
3447
+
3448
+ ### fn `export function dispatchStaticCheckForFile(` (L612-615)
3449
+ - @brief Dispatches one configured static checker for a single file.
3450
+ - @details Selects the checker implementation by module name, normalizes parameter arrays, and runs exactly one checker instance against the target file. Runtime is dominated by the selected checker. Side effects include console output and possible process spawning.
3451
+ - @param[in] filePath {string} Absolute or relative file path to check.
3452
+ - @param[in] langConfig {StaticCheckEntry} Normalized static-check configuration entry.
3453
+ - @param[in] options {{ failOnly?: boolean; projectBase?: string }} Optional execution controls.
3454
+ - @return {number} Checker exit status where `0` means success and non-zero means failure.
3455
+ - @throws {ReqError} Throws when configuration is incomplete or names an unknown module.
3456
+
3457
+ ### fn `export function runStaticCheck(argv: string[]): number` (L649-674)
3458
+ - @brief Runs the standalone static-check test driver.
3459
+ - @details Dispatches subcommands to the built-in checker implementations without consulting project configuration. Runtime is O(n) in argument count plus checker cost. Side effects include console output and external process spawning.
3460
+ - @param[in] argv {string[]} Raw static-check subcommand arguments.
3461
+ - @return {number} Checker exit status where `0` means success.
3462
+ - @throws {ReqError} Throws when no subcommand is provided, the subcommand is unknown, or required arguments are missing.
3463
+
3464
+ ## Symbol Index
3465
+ |Symbol|Kind|Vis|Lines|Sig|
3466
+ |---|---|---|---|---|
3467
+ |`StaticCheckLanguageSupport`|iface||85-88|export interface StaticCheckLanguageSupport|
3468
+ |`getSupportedStaticCheckLanguages`|fn||106-108|export function getSupportedStaticCheckLanguages(): string[]|
3469
+ |`getSupportedStaticCheckLanguageSupport`|fn||115-126|export function getSupportedStaticCheckLanguageSupport():...|
3470
+ |`formatStaticCheckModules`|fn||133-135|function formatStaticCheckModules(): string|
3471
+ |`splitCsvLikeTokens`|fn||143-165|function splitCsvLikeTokens(specRhs: string): string[]|
3472
+ |`parseEnableStaticCheck`|fn||174-222|export function parseEnableStaticCheck(spec: string): [st...|
3473
+ |`buildStaticCheckEntryIdentity`|fn||232-237|export function buildStaticCheckEntryIdentity(language: s...|
3474
+ |`validateStaticCheckEntry`|fn||247-258|export function validateStaticCheckEntry(entry: StaticChe...|
3475
+ |`resolveFiles`|fn||266-290|function resolveFiles(inputs: string[]): string[]|
3476
+ |`StaticCheckBase`|class||296-370|export class StaticCheckBase|
3477
+ |`detectPythonExecutable`|fn||378-398|function detectPythonExecutable(projectBase?: string): st...|
3478
+ |`StaticCheckPylance`|class||404-455|export class StaticCheckPylance extends StaticCheckBase|
3479
+ |`StaticCheckRuff`|class||461-509|export class StaticCheckRuff extends StaticCheckBase|
3480
+ |`StaticCheckCommand`|class||515-564|export class StaticCheckCommand extends StaticCheckBase|
3481
+ |`isExecutableFile`|fn||572-582|function isExecutableFile(candidate: string): boolean|
3482
+ |`findExecutable`|fn||590-601|function findExecutable(cmd: string): string | undefined|
3483
+ |`dispatchStaticCheckForFile`|fn||612-615|export function dispatchStaticCheckForFile(|
3484
+ |`runStaticCheck`|fn||649-674|export function runStaticCheck(argv: string[]): number|
3485
+
3486
+
3487
+ ---
3488
+
3489
+ # token-counter.ts | TypeScript | 729L | 29 symbols | 5 imports | 35 comments
3490
+ > Path: `src/core/token-counter.ts`
3491
+ - @brief Provides token, size, and structure counting utilities for agent-oriented file payloads.
3492
+ - @details Wraps `js-tiktoken` encoding lookup, extracts per-file structural facts, and builds machine-oriented JSON payloads for token-centric tools. Runtime is linear in processed text size plus sort cost for derived ordering hints. Side effects are limited to filesystem reads in file-based helpers.
3493
+
3494
+ ## Imports
3495
+ ```
3496
+ import fs from "node:fs";
3497
+ import path from "node:path";
3498
+ import { getEncoding } from "js-tiktoken";
3499
+ import { detectLanguage as detectSourceLanguage } from "./compress.js";
3500
+ import { parseDoxygenComment, type DoxygenFieldMap } from "./doxygen-parser.js";
3501
+ ```
3502
+
3503
+ ## Definitions
3504
+
3505
+ - type `export type TokenToolScope = "explicit-files" | "canonical-docs";` (L23)
3506
+ - @brief Enumerates supported token-payload scopes.
3507
+ - @details Distinguishes explicit-file requests from canonical-document requests while preserving one stable JSON contract. The alias is compile-time only and introduces no runtime cost.
3508
+ - type `export type TokenFileStatus = "counted" | "error" | "skipped";` (L29)
3509
+ - @brief Enumerates supported per-file token-entry statuses.
3510
+ - @details Separates counted files, read-time failures, and skipped inputs so downstream agents can branch without reparsing text diagnostics. The alias is compile-time only and introduces no runtime cost.
3511
+ ### iface `export interface CountFileMetricsResult` (L35-48)
3512
+ - @brief Describes one per-file token metric record.
3513
+ - @details Stores canonical file identity plus numeric token, character, byte, and line metrics extracted from one readable file. Optional metadata remains isolated in dedicated fields so agents can access headings and Doxygen fields without reparsing monolithic text. The interface is compile-time only and introduces no runtime cost.
3514
+
3515
+ ### iface `export interface TokenToolFileEntry` (L54-77)
3516
+ - @brief Describes one file entry in the agent-oriented token payload.
3517
+ - @details Orders direct-access path identifiers before source facts and numeric metrics so agents can branch without reparsing formatted strings. Optional metadata captures markdown headings or Doxygen file fields when they can be derived from the source content. The interface is compile-time only and introduces no runtime cost.
3518
+
3519
+ ### iface `export interface TokenToolRequestSection` (L83-93)
3520
+ - @brief Describes the request section of the agent-oriented token payload.
3521
+ - @details Captures tool identity, scope, path-resolution base, encoding, and requested path inventories so agents can reason about how metrics were selected. The interface is compile-time only and introduces no runtime cost.
3522
+
3523
+ ### iface `export interface TokenToolSummarySection` (L99-112)
3524
+ - @brief Describes the summary section of the agent-oriented token payload.
3525
+ - @details Exposes aggregate counts, sizes, totals, and per-file averages as numeric fields with explicit units so agents can branch on totals without reparsing formatted strings. The interface is compile-time only and introduces no runtime cost.
3526
+
3527
+ ### iface `export interface TokenToolPathIssue` (L118-122)
3528
+ - @brief Describes one skipped-input or read-error observation.
3529
+ - @details Preserves both the caller-provided path and the canonicalized path plus a stable machine-readable reason string. The interface is compile-time only and introduces no runtime cost.
3530
+
3531
+ ### iface `export interface TokenToolDominantFileObservation` (L128-132)
3532
+ - @brief Describes the dominant counted file for one metric ordering.
3533
+ - @details Exposes the canonical path plus the numeric token metrics that justify why the file dominates the current context budget. The interface is compile-time only and introduces no runtime cost.
3534
+
3535
+ ### iface `export interface TokenToolSourceObservationsSection` (L138-144)
3536
+ - @brief Describes the source-observation subsection of the guidance payload.
3537
+ - @details Separates measured ordering facts and path issues from derived recommendations so agents can reason about raw observations independently. The interface is compile-time only and introduces no runtime cost.
3538
+
3539
+ ### iface `export interface TokenToolRecommendation` (L150-154)
3540
+ - @brief Describes one derived recommendation in the guidance payload.
3541
+ - @details Provides a stable recommendation kind, the basis metric used to derive it, and the ordered path list the agent can follow directly. The interface is compile-time only and introduces no runtime cost.
3542
+
3543
+ ### iface `export interface TokenToolNextStepHint` (L160-164)
3544
+ - @brief Describes one actionable next-step hint in the guidance payload.
3545
+ - @details Supplies a stable hint kind, a focused ordered path subset, and the goal the agent can apply without reparsing surrounding prose. The interface is compile-time only and introduces no runtime cost.
3546
+
3547
+ ### iface `export interface TokenToolGuidanceSection` (L170-174)
3548
+ - @brief Describes the guidance section of the agent-oriented token payload.
3549
+ - @details Separates source observations, derived recommendations, and actionable next-step hints so downstream agents can choose between raw evidence and planning heuristics without reparsing mixed prose. The interface is compile-time only and introduces no runtime cost.
3550
+
3551
+ ### iface `export interface TokenToolPayload` (L180-185)
3552
+ - @brief Describes the full agent-oriented token payload.
3553
+ - @details Orders the top-level sections as request, summary, files, and guidance for deterministic downstream traversal. The interface is compile-time only and introduces no runtime cost.
3554
+
3555
+ ### iface `export interface BuildTokenToolPayloadOptions` (L191-199)
3556
+ - @brief Describes the options required to build one agent-oriented token payload.
3557
+ - @details Supplies tool identity, scope, path base, requested paths, and optional canonical-doc metadata while keeping counting behavior configurable through a stable object contract. The interface is compile-time only and introduces no runtime cost.
3558
+
3559
+ ### class `export class TokenCounter` (L205-245)
3560
+ - @brief Encapsulates one tokenizer instance for repeated token counting.
3561
+ - @brief Stores the tokenizer implementation used for subsequent counts.
3562
+ - @details Caches a `js-tiktoken` encoding object so multiple documents can be counted without repeated encoding lookup. Counting cost is O(n) in content length. The class mutates only instance state during construction.
3563
+ - @details The field holds the encoder returned by `getEncoding`. Access complexity is O(1). The value is initialized once per instance.
3564
+
3565
+ ### fn `function canonicalizeTokenPath(filePath: string, baseDir: string): string` (L254-262)
3566
+ - @brief Converts one filesystem path into the canonical token-payload path form.
3567
+ - @details Emits a slash-normalized relative path when the target is under the supplied base directory; otherwise emits a slash-normalized absolute path. Runtime is O(p) in path length. No external state is mutated.
3568
+ - @param[in] filePath {string} Candidate absolute or relative filesystem path.
3569
+ - @param[in] baseDir {string} Reference directory used for relative canonicalization.
3570
+ - @return {string} Canonicalized path string.
3571
+
3572
+ ### fn `function countLines(content: string): number` (L270-276)
3573
+ - @brief Counts logical lines in one text payload.
3574
+ - @details Counts newline separators while treating a trailing newline as line termination instead of an extra empty logical line. Runtime is O(n) in text length. No side effects occur.
3575
+ - @param[in] content {string} Text payload.
3576
+ - @return {number} Logical line count; `0` for empty content.
3577
+
3578
+ ### fn `function stripMarkdownFrontMatter(content: string): string` (L284-287)
3579
+ - @brief Strips YAML front matter from markdown content before heading extraction.
3580
+ - @details Removes the first `--- ... ---` block only when it appears at the file start so heading detection can operate on semantic markdown content instead of metadata. Runtime is O(n) in content length. No side effects occur.
3581
+ - @param[in] content {string} Markdown payload.
3582
+ - @return {string} Markdown body without the leading front matter block.
3583
+
3584
+ ### fn `function extractPrimaryHeadingText(content: string, filePath: string): string | undefined` (L296-303)
3585
+ - @brief Extracts the first level-one markdown heading when present.
3586
+ - @details Restricts extraction to markdown-like files, skips YAML front matter, and returns the first `# ` heading payload without surrounding whitespace. Runtime is O(n) in content length. No side effects occur.
3587
+ - @param[in] content {string} File content.
3588
+ - @param[in] filePath {string} Source path used for extension-based markdown detection.
3589
+ - @return {string | undefined} First heading text, or `undefined` when absent or the file is not markdown-like.
3590
+
3591
+ ### fn `function inferLanguageName(filePath: string): string | undefined` (L311-320)
3592
+ - @brief Infers a file language label optimized for agent payloads.
3593
+ - @details Reuses source-language detection when available, normalizes markdown extensions explicitly, and falls back to the lowercase extension name without the leading dot. Runtime is O(1). No side effects occur.
3594
+ - @param[in] filePath {string} File path whose extension should be classified.
3595
+ - @return {string | undefined} Normalized language label, or `undefined` when the path has no usable extension.
3596
+
3597
+ ### fn `function extractLeadingDoxygenFields(content: string): DoxygenFieldMap | undefined` (L328-346)
3598
+ - @brief Extracts leading Doxygen file fields when present.
3599
+ - @details Tests common leading-comment syntaxes, normalizes an optional shebang away before matching, and returns the first non-empty parsed Doxygen map. Runtime is O(n) in comment length. No side effects occur.
3600
+ - @param[in] content {string} File content.
3601
+ - @return {DoxygenFieldMap | undefined} Parsed Doxygen field map, or `undefined` when no supported file-level fields are present.
3602
+
3603
+ ### fn `function roundRatio(numerator: number, denominator: number): number` (L355-360)
3604
+ - @brief Rounds one ratio to six decimal places.
3605
+ - @details Preserves zero exactly and otherwise limits floating-point noise so share fields remain stable across executions. Runtime is O(1). No side effects occur.
3606
+ - @param[in] numerator {number} Partial numeric value.
3607
+ - @param[in] denominator {number} Total numeric value.
3608
+ - @return {number} Rounded ratio in range `[0, 1]` when the denominator is positive; `0` otherwise.
3609
+
3610
+ ### fn `function orderPathsByMetric(` (L370-395)
3611
+ - @brief Orders canonical file paths by one numeric metric while removing duplicates.
3612
+ - @details Filters to counted file entries, sorts by the supplied metric direction, breaks ties by canonical path, and preserves only the first occurrence of each path. Runtime is O(n log n). No external state is mutated.
3613
+ - @param[in] files {TokenToolFileEntry[]} Token payload file entries.
3614
+ - @param[in] metric {(entry: TokenToolFileEntry) => number} Numeric metric selector.
3615
+ - @param[in] direction {"asc" | "desc"} Sort direction.
3616
+ - @return {string[]} Unique canonical paths ordered by the requested metric.
3617
+
3618
+ ### fn `function probeRequestedPath(absolutePath: string): { exists: boolean; isFile: boolean; reason?: string }` (L403-417)
3619
+ - @brief Probes one requested path before token counting.
3620
+ - @details Resolves whether the target exists and is a regular file while capturing a stable skip reason for missing or non-file inputs. Runtime is dominated by one filesystem stat. Side effects are limited to filesystem reads.
3621
+ - @param[in] absolutePath {string} Absolute path to inspect.
3622
+ - @return {{ exists: boolean; isFile: boolean; reason?: string }} Path probe result.
3623
+
3624
+ ### fn `function buildCountFileMetricsResult(filePath: string, content: string, counter: TokenCounter): CountFileMetricsResult` (L427-442)
3625
+ - @brief Builds one rich per-file metrics record from readable content.
3626
+ - @details Combines token, character, byte, and line counts with file-extension, inferred-language, heading, and Doxygen metadata extraction so agents can consume direct-access facts without reparsing the raw file. Runtime is O(n) in content length. No external state is mutated.
3627
+ - @param[in] filePath {string} Absolute or project-local file path.
3628
+ - @param[in] content {string} UTF-8 file content.
3629
+ - @param[in] counter {TokenCounter} Reused token counter instance.
3630
+ - @return {CountFileMetricsResult} Structured per-file metrics record.
3631
+
3632
+ ### fn `export function countFileMetrics(content: string, encodingName = TOKEN_COUNTER_ENCODING):` (L451-464)
3633
+ - @brief Counts tokens, characters, bytes, and lines for one in-memory content string.
3634
+ - @details Instantiates a `TokenCounter`, tokenizes the supplied text, and pairs the result with raw character length, UTF-8 byte size, and logical line count. Runtime is O(n). No filesystem I/O occurs.
3635
+ - @param[in] content {string} Text payload to measure.
3636
+ - @param[in] encodingName {string} Tokenizer identifier. Defaults to `cl100k_base`.
3637
+ - @return {{ tokens: number; chars: number; bytes: number; lines: number }} Aggregate metrics for the supplied content.
3638
+
3639
+ ### fn `export function countFilesMetrics(filePaths: string[], encodingName = TOKEN_COUNTER_ENCODING): CountFileMetricsResult[]` (L474-495)
3640
+ - @brief Counts tokens, characters, bytes, and lines for multiple files.
3641
+ - @details Reuses a single `TokenCounter`, reads each file as UTF-8, and returns per-file metrics plus direct-access metadata such as heading and Doxygen file fields. Read failures are captured as error strings instead of aborting the entire batch. Runtime is O(F + S). Side effects are limited to filesystem reads.
3642
+ - @param[in] filePaths {string[]} File paths to measure.
3643
+ - @param[in] encodingName {string} Tokenizer identifier. Defaults to `cl100k_base`.
3644
+ - @return {CountFileMetricsResult[]} Per-file metrics and optional read errors.
3645
+ - @satisfies REQ-010, REQ-070, REQ-073
3646
+
3647
+ ### fn `export function buildTokenToolPayload(options: BuildTokenToolPayloadOptions): TokenToolPayload` (L504-697)
3648
+ - @brief Builds the agent-oriented JSON payload for token-centric tools.
3649
+ - @details Validates requested paths against the filesystem, counts token metrics for processable files, preserves caller order in the file table, separates raw observations from derived guidance, and emits direct-access file facts such as line ranges, sizes, headings, and optional Doxygen file fields. Runtime is O(F log F + S). Side effects are limited to filesystem reads.
3650
+ - @param[in] options {BuildTokenToolPayloadOptions} Payload-construction options.
3651
+ - @return {TokenToolPayload} Structured token payload ordered as request, summary, files, guidance.
3652
+ - @satisfies REQ-010, REQ-017, REQ-069, REQ-070, REQ-071, REQ-073, REQ-074, REQ-075
3653
+
3654
+ ### fn `export function formatPackSummary(results: CountFileMetricsResult[]): string` (L705-729)
3655
+ - @brief Formats per-file token metrics as a human-readable summary block.
3656
+ - @details Aggregates totals, emits one status line per file, and appends a summary footer containing file, token, and character counts. Runtime is O(n). No external state is mutated.
3657
+ - @param[in] results {CountFileMetricsResult[]} Per-file metric records.
3658
+ - @return {string} Multiline summary suitable for CLI or editor output.
3659
+
3660
+ ## Symbol Index
3661
+ |Symbol|Kind|Vis|Lines|Sig|
3662
+ |---|---|---|---|---|
3663
+ |`TokenToolScope`|type||23||
3664
+ |`TokenFileStatus`|type||29||
3665
+ |`CountFileMetricsResult`|iface||35-48|export interface CountFileMetricsResult|
3666
+ |`TokenToolFileEntry`|iface||54-77|export interface TokenToolFileEntry|
3667
+ |`TokenToolRequestSection`|iface||83-93|export interface TokenToolRequestSection|
3668
+ |`TokenToolSummarySection`|iface||99-112|export interface TokenToolSummarySection|
3669
+ |`TokenToolPathIssue`|iface||118-122|export interface TokenToolPathIssue|
3670
+ |`TokenToolDominantFileObservation`|iface||128-132|export interface TokenToolDominantFileObservation|
3671
+ |`TokenToolSourceObservationsSection`|iface||138-144|export interface TokenToolSourceObservationsSection|
3672
+ |`TokenToolRecommendation`|iface||150-154|export interface TokenToolRecommendation|
3673
+ |`TokenToolNextStepHint`|iface||160-164|export interface TokenToolNextStepHint|
3674
+ |`TokenToolGuidanceSection`|iface||170-174|export interface TokenToolGuidanceSection|
3675
+ |`TokenToolPayload`|iface||180-185|export interface TokenToolPayload|
3676
+ |`BuildTokenToolPayloadOptions`|iface||191-199|export interface BuildTokenToolPayloadOptions|
3677
+ |`TokenCounter`|class||205-245|export class TokenCounter|
3678
+ |`canonicalizeTokenPath`|fn||254-262|function canonicalizeTokenPath(filePath: string, baseDir:...|
3679
+ |`countLines`|fn||270-276|function countLines(content: string): number|
3680
+ |`stripMarkdownFrontMatter`|fn||284-287|function stripMarkdownFrontMatter(content: string): string|
3681
+ |`extractPrimaryHeadingText`|fn||296-303|function extractPrimaryHeadingText(content: string, fileP...|
3682
+ |`inferLanguageName`|fn||311-320|function inferLanguageName(filePath: string): string | un...|
3683
+ |`extractLeadingDoxygenFields`|fn||328-346|function extractLeadingDoxygenFields(content: string): Do...|
3684
+ |`roundRatio`|fn||355-360|function roundRatio(numerator: number, denominator: numbe...|
3685
+ |`orderPathsByMetric`|fn||370-395|function orderPathsByMetric(|
3686
+ |`probeRequestedPath`|fn||403-417|function probeRequestedPath(absolutePath: string): { exis...|
3687
+ |`buildCountFileMetricsResult`|fn||427-442|function buildCountFileMetricsResult(filePath: string, co...|
3688
+ |`countFileMetrics`|fn||451-464|export function countFileMetrics(content: string, encodin...|
3689
+ |`countFilesMetrics`|fn||474-495|export function countFilesMetrics(filePaths: string[], en...|
3690
+ |`buildTokenToolPayload`|fn||504-697|export function buildTokenToolPayload(options: BuildToken...|
3691
+ |`formatPackSummary`|fn||705-729|export function formatPackSummary(results: CountFileMetri...|
3692
+
3693
+
3694
+ ---
3695
+
3696
+ # tool-runner.ts | TypeScript | 717L | 34 symbols | 13 imports | 35 comments
3697
+ > Path: `src/core/tool-runner.ts`
3698
+ - @brief Implements the executable back-end for all pi-usereq CLI and extension tools.
3699
+ - @details Centralizes project discovery, git helpers, source-file collection, documentation generation, compression, construct lookup, static-check dispatch, and worktree lifecycle operations. Runtime depends on the selected command and may include filesystem reads, config writes, process spawning, and git mutations.
3700
+
3701
+ ## Imports
3702
+ ```
3703
+ import fs from "node:fs";
3704
+ import path from "node:path";
3705
+ import { spawnSync } from "node:child_process";
3706
+ import { ReqError } from "./errors.js";
3707
+ import { loadConfig, normalizeConfigPaths, saveConfig, type UseReqConfig } from "./config.js";
3708
+ import { formatRuntimePathForDisplay } from "./path-context.js";
3709
+ import { resolveRuntimeGitPath } from "./runtime-project-paths.js";
3710
+ import { countFilesMetrics, formatPackSummary } from "./token-counter.js";
3711
+ import {
3712
+ import { compressFiles } from "./compress-files.js";
3713
+ import { findConstructsInFiles } from "./find-constructs.js";
3714
+ import { STATIC_CHECK_EXT_TO_LANG, dispatchStaticCheckForFile } from "./static-check.js";
3715
+ import { makeRelativeIfContainsProject } from "./utils.js";
3716
+ ```
3717
+
3718
+ ## Definitions
3719
+
3720
+ ### iface `export interface ToolResult` (L28-32)
3721
+ - @brief Represents the normalized output contract for a tool invocation.
3722
+ - @details Every tool emits stdout, stderr, and a numeric exit code so CLI and extension front-ends can handle results uniformly. The interface is compile-time only and adds no runtime cost.
3723
+
3724
+ ### fn `function ok(stdout = "", stderr = ""): ToolResult` (L52-54)
3725
+ - @brief Creates a successful tool result payload.
3726
+ - @details Wraps stdout and stderr text with exit code `0`. Runtime is O(1). No side effects occur.
3727
+ - @param[in] stdout {string} Standard-output text.
3728
+ - @param[in] stderr {string} Standard-error text.
3729
+ - @return {ToolResult} Successful result object.
3730
+
3731
+ ### fn `function fail(message: string, code = 1, stdout = "", stderr = ""): never` (L66-71)
3732
+ - @brief Throws a `ReqError` populated with tool-result stream content.
3733
+ - @details Creates a structured failure object, attaches optional stdout and stderr payloads, and throws immediately. Runtime is O(1). Side effect: throws an exception.
3734
+ - @param[in] message {string} Primary failure message.
3735
+ - @param[in] code {number} Exit code to attach. Defaults to `1`.
3736
+ - @param[in] stdout {string} Optional stdout payload.
3737
+ - @param[in] stderr {string} Optional stderr payload. Defaults to `message` when omitted.
3738
+ - @return {never} This function never returns.
3739
+ - @throws {ReqError} Always throws.
3740
+
3741
+ ### fn `function runCapture(command: string[], options: { cwd?: string } = {})` (L80-85)
3742
+ - @brief Executes a subprocess synchronously and captures its output.
3743
+ - @details Delegates to `spawnSync`, passes through an optional working directory, and forces UTF-8 decoding. Runtime is dominated by external process execution. Side effects include process spawning.
3744
+ - @param[in] command {string[]} Executable plus argument vector.
3745
+ - @param[in] options {{ cwd?: string }} Optional process-spawn settings.
3746
+ - @return {ReturnType<typeof spawnSync>} Captured subprocess result.
3747
+
3748
+ ### fn `function resolveEffectiveGitPath(projectBase: string): string | undefined` (L94-96)
3749
+ - @brief Resolves the effective runtime git root for the current base path.
3750
+ - @details Delegates to the shared runtime-only repository resolver so git helpers never consult persisted `git-path` metadata. Runtime is dominated by git probing. Side effects include subprocess execution.
3751
+ - @param[in] projectBase {string} Resolved base path.
3752
+ - @return {string | undefined} Effective git root path or `undefined` when unavailable.
3753
+ - @satisfies REQ-145, REQ-146
3754
+
3755
+ ### fn `export function sanitizeBranchName(branch: string): string` (L104-106)
3756
+ - @brief Rewrites a branch name into a filesystem-safe token.
3757
+ - @details Replaces characters invalid for worktree directory and branch-name generation with `-`. Runtime is O(n). No side effects occur.
3758
+ - @param[in] branch {string} Raw branch name.
3759
+ - @return {string} Sanitized token.
3760
+
3761
+ ### fn `export function validateWtName(wtName: string): boolean` (L114-117)
3762
+ - @brief Validates a requested worktree or branch name.
3763
+ - @details Rejects empty names, dot-path markers, whitespace, and filesystem-invalid characters. Runtime is O(n). No side effects occur.
3764
+ - @param[in] wtName {string} Candidate worktree name.
3765
+ - @return {boolean} `true` when the name is acceptable for worktree creation.
3766
+
3767
+ ### fn `export function collectSourceFiles(srcDirs: string[], projectBase: string): string[]` (L127-154)
3768
+ - @brief Collects tracked and untracked source files from configured source directories.
3769
+ - @details Uses `git ls-files` to enumerate candidate files, filters them by configured source roots, excluded directories, and supported extensions, and returns sorted absolute paths. Runtime is O(n log n) in collected file count plus git execution cost. Side effects include process spawning.
3770
+ - @param[in] srcDirs {string[]} Configured source-directory roots.
3771
+ - @param[in] projectBase {string} Absolute project root.
3772
+ - @return {string[]} Sorted absolute source-file paths.
3773
+ - @throws {ReqError} Throws when `git ls-files` fails.
3774
+
3775
+ ### fn `function buildAsciiTree(paths: string[]): string` (L162-190)
3776
+ - @brief Builds an ASCII tree from relative file paths.
3777
+ - @details Materializes a nested object tree and renders it using box-drawing characters for markdown display. Runtime is O(n log n) in path count due to sorting. No side effects occur.
3778
+ - @param[in] paths {string[]} Relative POSIX-style file paths.
3779
+ - @return {string} Rendered ASCII tree.
3780
+
3781
+ ### fn `const emit = (branch: Record<string, Record<string, unknown> | null>, prefix = "") =>` (L178-187)
3782
+
3783
+ ### fn `function formatFilesStructureMarkdown(files: string[], projectBase: string): string` (L199-202)
3784
+ - @brief Formats the collected file structure as markdown.
3785
+ - @details Converts absolute file paths to project-relative POSIX paths, renders an ASCII tree, and wraps the result in a fenced markdown block. Runtime is O(n log n) in file count. No side effects occur.
3786
+ - @param[in] files {string[]} Absolute file paths.
3787
+ - @param[in] projectBase {string} Absolute project root.
3788
+ - @return {string} Markdown section describing the file structure.
3789
+
3790
+ ### fn `export function resolveProjectBase(projectBase?: string): string` (L211-217)
3791
+ - @brief Resolves and validates the project base directory.
3792
+ - @details Uses the supplied path or the current working directory, normalizes it to an absolute path, and verifies that it exists. Runtime is O(1) plus one filesystem existence check. Side effects are limited to filesystem reads.
3793
+ - @param[in] projectBase {string | undefined} Optional project-root override.
3794
+ - @return {string} Absolute validated project root.
3795
+ - @throws {ReqError} Throws when the resolved path does not exist.
3796
+
3797
+ ### fn `export function resolveProjectSrcDirs(projectBase: string, config?: UseReqConfig): [string, string[]]` (L227-235)
3798
+ - @brief Resolves the project base and effective source-directory list.
3799
+ - @details Loads configuration when not supplied, validates that at least one source directory exists in config, and returns both the absolute base path and source-directory array. Runtime is O(s). Side effects are limited to config reads.
3800
+ - @param[in] projectBase {string} Candidate project root.
3801
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3802
+ - @return {[string, string[]]} Tuple of absolute project base and configured source directories.
3803
+ - @throws {ReqError} Throws when no source directories are configured.
3804
+
3805
+ ### fn `export function loadAndRepairConfig(projectBase: string): UseReqConfig` (L244-249)
3806
+ - @brief Loads project configuration and persists normalized path fields.
3807
+ - @details Resolves the base path, normalizes persisted docs/tests/source directories into project-relative form, writes the normalized config back to disk, and returns the in-memory result without persisting runtime-derived path metadata. Runtime is dominated by config I/O. Side effects include config writes.
3808
+ - @param[in] projectBase {string} Candidate project root.
3809
+ - @return {UseReqConfig} Normalized effective configuration.
3810
+ - @satisfies CTN-012, REQ-146
3811
+
3812
+ ### fn `export function runFilesTokens(files: string[]): ToolResult` (L258-270)
3813
+ - @brief Counts tokens and characters for explicit files.
3814
+ - @details Filters missing files into stderr warnings, counts metrics for valid files, and returns a formatted summary. Runtime is O(F + S). Side effects are limited to filesystem reads.
3815
+ - @param[in] files {string[]} Explicit file paths.
3816
+ - @return {ToolResult} Tool result containing the formatted summary and warnings.
3817
+ - @throws {ReqError} Throws when no valid files are provided.
3818
+
3819
+ ### fn `export function runFilesReferences(files: string[], cwd = process.cwd(), verbose = false): ToolResult` (L281-297)
3820
+ - @brief Generates the structured references JSON payload for explicit files.
3821
+ - @details Builds the agent-oriented references payload in caller order, preserves skipped and failed inputs as structured file records, emits deterministic JSON to stdout, and mirrors structured diagnostics to stderr. Runtime is O(F log F + S). Side effects are limited to filesystem reads and optional stderr logging.
3822
+ - @param[in] files {string[]} Explicit file paths.
3823
+ - @param[in] cwd {string} Base directory used for canonical path resolution. Defaults to `process.cwd()`.
3824
+ - @param[in] verbose {boolean} When `true`, emit per-file progress diagnostics to stderr.
3825
+ - @return {ToolResult} Successful tool result containing structured JSON.
3826
+ - @satisfies REQ-011, REQ-076, REQ-077, REQ-078, REQ-079
3827
+
3828
+ ### fn `export function runFilesCompress(files: string[], cwd = process.cwd(), enableLineNumbers = false, verbose = false): ToolResult` (L308-310)
3829
+ - @brief Compresses explicit files into compact source excerpts.
3830
+ - @details Delegates to `compressFiles` using the caller working directory as the relative-output base by default. Runtime is O(F + S). Side effects are limited to filesystem reads and optional stderr logging.
3831
+ - @param[in] files {string[]} Explicit file paths.
3832
+ - @param[in] cwd {string} Base directory for relative output formatting. Defaults to `process.cwd()`.
3833
+ - @param[in] enableLineNumbers {boolean} When `true`, preserve original source line numbers.
3834
+ - @param[in] verbose {boolean} When `true`, emit per-file diagnostics to stderr.
3835
+ - @return {ToolResult} Successful tool result containing compressed output.
3836
+
3837
+ ### fn `export function runFilesFind(argsList: string[], enableLineNumbers = false, verbose = false): ToolResult` (L321-327)
3838
+ - @brief Finds named constructs in explicit files.
3839
+ - @details Expects `[TAG, PATTERN, ...FILES]`, validates minimum arity, and delegates to `findConstructsInFiles`. Runtime is O(F + S + M). Side effects are limited to filesystem reads and optional stderr logging.
3840
+ - @param[in] argsList {string[]} Positional argument list containing tag filter, regex pattern, and files.
3841
+ - @param[in] enableLineNumbers {boolean} When `true`, preserve original source line numbers in excerpts.
3842
+ - @param[in] verbose {boolean} When `true`, emit diagnostics to stderr.
3843
+ - @return {ToolResult} Successful tool result containing construct markdown.
3844
+ - @throws {ReqError} Throws when required arguments are missing.
3845
+
3846
+ ### fn `export function runReferences(projectBase: string, config?: UseReqConfig, verbose = false): ToolResult` (L339-356)
3847
+ - @brief Generates the structured references JSON payload for configured source directories.
3848
+ - @details Resolves the project base, collects configured source files, builds the agent-oriented references payload, emits deterministic JSON to stdout, and mirrors structured diagnostics to stderr. Runtime is O(F log F + S). Side effects are limited to filesystem reads and optional stderr logging.
3849
+ - @param[in] projectBase {string} Candidate project root.
3850
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3851
+ - @param[in] verbose {boolean} When `true`, emit per-file diagnostics to stderr.
3852
+ - @return {ToolResult} Successful tool result containing structured JSON.
3853
+ - @throws {ReqError} Throws when no source files are found or no file can be analyzed.
3854
+ - @satisfies REQ-014, REQ-076, REQ-077, REQ-078, REQ-079
3855
+
3856
+ ### fn `export function runCompress(projectBase: string, config?: UseReqConfig, enableLineNumbers = false, verbose = false): ToolResult` (L368-373)
3857
+ - @brief Compresses all source files from configured source directories.
3858
+ - @details Resolves the project base, collects source files, and delegates to `compressFiles`. Runtime is O(F + S). Side effects are limited to filesystem reads and optional stderr logging.
3859
+ - @param[in] projectBase {string} Candidate project root.
3860
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3861
+ - @param[in] enableLineNumbers {boolean} When `true`, preserve original source line numbers.
3862
+ - @param[in] verbose {boolean} When `true`, emit per-file diagnostics to stderr.
3863
+ - @return {ToolResult} Successful tool result containing compressed output.
3864
+ - @throws {ReqError} Throws when no source files are found.
3865
+
3866
+ ### fn `export function runFind(projectBase: string, tagFilter: string, pattern: string, config?: UseReqConfig, enableLineNumbers = false, verbose = false): ToolResult` (L387-396)
3867
+ - @brief Finds named constructs across configured project source files.
3868
+ - @details Resolves the project base, collects source files, delegates to `findConstructsInFiles`, and converts thrown search errors into structured `ReqError` failures. Runtime is O(F + S + M). Side effects are limited to filesystem reads and optional stderr logging.
3869
+ - @param[in] projectBase {string} Candidate project root.
3870
+ - @param[in] tagFilter {string} Pipe-delimited tag filter.
3871
+ - @param[in] pattern {string} Regular expression applied to construct names.
3872
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3873
+ - @param[in] enableLineNumbers {boolean} When `true`, preserve original source line numbers in excerpts.
3874
+ - @param[in] verbose {boolean} When `true`, emit diagnostics to stderr.
3875
+ - @return {ToolResult} Successful tool result containing construct markdown.
3876
+ - @throws {ReqError} Throws when no source files are found or the search fails.
3877
+
3878
+ ### fn `export function runTokens(projectBase: string, config?: UseReqConfig): ToolResult` (L406-415)
3879
+ - @brief Counts tokens for canonical documentation files.
3880
+ - @details Loads the configured docs directory, selects `REQUIREMENTS.md`, `WORKFLOW.md`, and `REFERENCES.md` when present, and delegates to `runFilesTokens`. Runtime is O(F + S). Side effects are limited to filesystem reads.
3881
+ - @param[in] projectBase {string} Candidate project root.
3882
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3883
+ - @return {ToolResult} Tool result containing documentation token metrics.
3884
+ - @throws {ReqError} Throws when no canonical docs files exist.
3885
+
3886
+ ### fn `export function runFilesStaticCheck(files: string[], projectBase: string, config?: UseReqConfig): ToolResult` (L425-461)
3887
+ - @brief Runs configured static checks for explicit files.
3888
+ - @details Loads the effective static-check config, groups checks by file extension language, captures checker stdout for each configured entry, and aggregates stderr warnings for invalid paths. Runtime is O(F * C) plus external checker cost. Side effects include filesystem reads, stdout interception, and process spawning.
3889
+ - @param[in] files {string[]} Explicit file paths.
3890
+ - @param[in] projectBase {string} Candidate project root.
3891
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3892
+ - @return {ToolResult} Aggregated static-check result.
3893
+
3894
+ ### fn `export function runProjectStaticCheck(projectBase: string, config?: UseReqConfig): ToolResult` (L471-484)
3895
+ - @brief Runs configured static checks for project source and test directories.
3896
+ - @details Collects source and test files, excludes fixture roots, and delegates to `runFilesStaticCheck`. Runtime is O(F * C) plus external checker cost. Side effects include filesystem reads, stdout interception, and process spawning.
3897
+ - @param[in] projectBase {string} Candidate project root.
3898
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3899
+ - @return {ToolResult} Aggregated static-check result.
3900
+ - @throws {ReqError} Throws when no source files are found.
3901
+
3902
+ ### fn `export function runGitCheck(projectBase: string, config?: UseReqConfig): ToolResult` (L495-518)
3903
+ - @brief Verifies that the effective repository root is clean and has a valid HEAD.
3904
+ - @details Resolves the runtime git root for the current execution path, checks work-tree status, rejects uncommitted changes, and verifies either a symbolic ref or detached HEAD hash exists. Runtime is dominated by git execution. Side effects include process spawning.
3905
+ - @param[in] projectBase {string} Candidate project root.
3906
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3907
+ - @return {ToolResult} Successful empty result when the repository state is valid.
3908
+ - @throws {ReqError} Throws when the runtime git root is unavailable or repository status is unclear.
3909
+ - @satisfies REQ-145, REQ-146
3910
+
3911
+ ### fn `export function runDocsCheck(projectBase: string, config?: UseReqConfig): ToolResult` (L528-545)
3912
+ - @brief Verifies that canonical documentation files exist.
3913
+ - @details Checks the configured docs directory for `REQUIREMENTS.md`, `WORKFLOW.md`, and `REFERENCES.md`, and throws a guided error for the first missing file. Runtime is O(1) plus filesystem existence checks. Side effects are limited to filesystem reads.
3914
+ - @param[in] projectBase {string} Candidate project root.
3915
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3916
+ - @return {ToolResult} Successful empty result when all canonical docs exist.
3917
+ - @throws {ReqError} Throws when a required doc file is missing.
3918
+
3919
+ ### fn `export function runGitWtName(projectBase: string, config?: UseReqConfig): ToolResult` (L556-570)
3920
+ - @brief Generates the standardized worktree name for the effective repository root.
3921
+ - @details Resolves the runtime git root constrained by the current base path, combines the repository basename, sanitized current branch, and a timestamp-based execution identifier into a deterministic `useReq-...` name. Runtime is O(1) plus git execution cost. Side effects include process spawning.
3922
+ - @param[in] projectBase {string} Candidate project root.
3923
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3924
+ - @return {ToolResult} Successful result containing the generated worktree name and trailing newline.
3925
+ - @throws {ReqError} Throws when the runtime git root is unavailable.
3926
+ - @satisfies REQ-145, REQ-146
3927
+
3928
+ ### fn `function worktreePathExistsExact(gitPath: string, targetPath: string): boolean` (L580-585)
3929
+ - @brief Tests whether a git worktree exists at an exact filesystem path.
3930
+ - @details Parses `git worktree list --porcelain` output and compares normalized paths for exact equality. Runtime is O(n) in reported worktree count plus git execution cost. Side effects include process spawning.
3931
+ - @param[in] gitPath {string} Git root used to query worktrees.
3932
+ - @param[in] targetPath {string} Candidate worktree path.
3933
+ - @return {boolean} `true` when a worktree exists at the exact target path.
3934
+ - @throws {ReqError} Throws when the worktree list cannot be queried.
3935
+
3936
+ ### fn `function rollbackWorktreeCreate(gitPath: string, wtPath: string, wtName: string): void` (L596-602)
3937
+ - @brief Rolls back a partially created worktree and branch.
3938
+ - @details Forces worktree removal and branch deletion, then throws if either rollback action fails. Runtime is dominated by git execution. Side effects include destructive git mutations.
3939
+ - @param[in] gitPath {string} Git root path.
3940
+ - @param[in] wtPath {string} Worktree path to remove.
3941
+ - @param[in] wtName {string} Branch name to delete.
3942
+ - @return {void} No return value.
3943
+ - @throws {ReqError} Throws when rollback cannot be completed.
3944
+
3945
+ ### fn `export function runGitWtCreate(projectBase: string, wtName: string, config?: UseReqConfig): ToolResult` (L613-646)
3946
+ - @brief Creates a dedicated git worktree and copies pi-usereq metadata into it.
3947
+ - @details Validates the requested name, resolves base and git roots under the ancestor constraint, creates the worktree and branch, then mirrors the `.pi-usereq` directory into the corresponding path inside the new worktree. Runtime is dominated by git and filesystem operations. Side effects include worktree creation, branch creation, directory creation, and file copying.
3948
+ - @param[in] projectBase {string} Candidate project root.
3949
+ - @param[in] wtName {string} Requested worktree and branch name.
3950
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3951
+ - @return {ToolResult} Successful empty result when creation completes.
3952
+ - @throws {ReqError} Throws for invalid names, missing git metadata, git failures, or copy finalization failures.
3953
+
3954
+ ### fn `export function runGitWtDelete(projectBase: string, wtName: string, config?: UseReqConfig): ToolResult` (L657-690)
3955
+ - @brief Deletes a dedicated git worktree and its branch.
3956
+ - @details Verifies that either the worktree path or branch exists, removes the worktree when present, deletes the branch when present, and fails atomically when either delete step reports an error. Runtime is dominated by git execution. Side effects include destructive git mutations.
3957
+ - @param[in] projectBase {string} Candidate project root.
3958
+ - @param[in] wtName {string} Exact worktree and branch name.
3959
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3960
+ - @return {ToolResult} Successful empty result when deletion completes.
3961
+ - @throws {ReqError} Throws when git metadata is missing, the target does not exist, or removal fails.
3962
+
3963
+ ### fn `const branchExists = (() =>` (L667-670)
3964
+
3965
+ ### fn `export function runGitPath(projectBase: string, config?: UseReqConfig): ToolResult` (L699-704)
3966
+ - @brief Returns the effective git root path for the current execution context.
3967
+ - @details Resolves the git root constrained by the current base path, formats it with the runtime path display serializer, and writes the resulting path followed by a newline. Runtime is O(p) plus config-load and optional git-probing cost. Side effects are limited to filesystem reads and git subprocess execution.
3968
+ - @param[in] projectBase {string} Candidate project root.
3969
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3970
+ - @return {ToolResult} Successful result containing the derived git path or an empty line.
3971
+
3972
+ ### fn `export function runGetBasePath(projectBase: string, config?: UseReqConfig): ToolResult` (L713-717)
3973
+ - @brief Returns the current base path for the execution context.
3974
+ - @details Resolves the current execution path, formats it with the runtime path display serializer, and writes the resulting base path followed by a newline. Runtime is O(p). Side effects are limited to filesystem reads.
3975
+ - @param[in] projectBase {string} Candidate project root.
3976
+ - @param[in] config {UseReqConfig | undefined} Optional preloaded configuration.
3977
+ - @return {ToolResult} Successful result containing the base path and trailing newline.
3978
+
3979
+ ## Symbol Index
3980
+ |Symbol|Kind|Vis|Lines|Sig|
3981
+ |---|---|---|---|---|
3982
+ |`ToolResult`|iface||28-32|export interface ToolResult|
3983
+ |`ok`|fn||52-54|function ok(stdout = "", stderr = ""): ToolResult|
3984
+ |`fail`|fn||66-71|function fail(message: string, code = 1, stdout = "", std...|
3985
+ |`runCapture`|fn||80-85|function runCapture(command: string[], options: { cwd?: s...|
3986
+ |`resolveEffectiveGitPath`|fn||94-96|function resolveEffectiveGitPath(projectBase: string): st...|
3987
+ |`sanitizeBranchName`|fn||104-106|export function sanitizeBranchName(branch: string): string|
3988
+ |`validateWtName`|fn||114-117|export function validateWtName(wtName: string): boolean|
3989
+ |`collectSourceFiles`|fn||127-154|export function collectSourceFiles(srcDirs: string[], pro...|
3990
+ |`buildAsciiTree`|fn||162-190|function buildAsciiTree(paths: string[]): string|
3991
+ |`emit`|fn||178-187|const emit = (branch: Record<string, Record<string, unkno...|
3992
+ |`formatFilesStructureMarkdown`|fn||199-202|function formatFilesStructureMarkdown(files: string[], pr...|
3993
+ |`resolveProjectBase`|fn||211-217|export function resolveProjectBase(projectBase?: string):...|
3994
+ |`resolveProjectSrcDirs`|fn||227-235|export function resolveProjectSrcDirs(projectBase: string...|
3995
+ |`loadAndRepairConfig`|fn||244-249|export function loadAndRepairConfig(projectBase: string):...|
3996
+ |`runFilesTokens`|fn||258-270|export function runFilesTokens(files: string[]): ToolResult|
3997
+ |`runFilesReferences`|fn||281-297|export function runFilesReferences(files: string[], cwd =...|
3998
+ |`runFilesCompress`|fn||308-310|export function runFilesCompress(files: string[], cwd = p...|
3999
+ |`runFilesFind`|fn||321-327|export function runFilesFind(argsList: string[], enableLi...|
4000
+ |`runReferences`|fn||339-356|export function runReferences(projectBase: string, config...|
4001
+ |`runCompress`|fn||368-373|export function runCompress(projectBase: string, config?:...|
4002
+ |`runFind`|fn||387-396|export function runFind(projectBase: string, tagFilter: s...|
4003
+ |`runTokens`|fn||406-415|export function runTokens(projectBase: string, config?: U...|
4004
+ |`runFilesStaticCheck`|fn||425-461|export function runFilesStaticCheck(files: string[], proj...|
4005
+ |`runProjectStaticCheck`|fn||471-484|export function runProjectStaticCheck(projectBase: string...|
4006
+ |`runGitCheck`|fn||495-518|export function runGitCheck(projectBase: string, config?:...|
4007
+ |`runDocsCheck`|fn||528-545|export function runDocsCheck(projectBase: string, config?...|
4008
+ |`runGitWtName`|fn||556-570|export function runGitWtName(projectBase: string, config?...|
4009
+ |`worktreePathExistsExact`|fn||580-585|function worktreePathExistsExact(gitPath: string, targetP...|
4010
+ |`rollbackWorktreeCreate`|fn||596-602|function rollbackWorktreeCreate(gitPath: string, wtPath: ...|
4011
+ |`runGitWtCreate`|fn||613-646|export function runGitWtCreate(projectBase: string, wtNam...|
4012
+ |`runGitWtDelete`|fn||657-690|export function runGitWtDelete(projectBase: string, wtNam...|
4013
+ |`branchExists`|fn||667-670|const branchExists = (() =>|
4014
+ |`runGitPath`|fn||699-704|export function runGitPath(projectBase: string, config?: ...|
4015
+ |`runGetBasePath`|fn||713-717|export function runGetBasePath(projectBase: string, confi...|
4016
+
4017
+
4018
+ ---
4019
+
4020
+ # utils.ts | TypeScript | 185L | 8 symbols | 3 imports | 9 comments
4021
+ > Path: `src/core/utils.ts`
4022
+ - @brief Provides path-normalization, shell-tokenization, and regex-escaping helpers.
4023
+ - @details Concentrates small pure utilities used by configuration loading, prompt rendering, and command dispatch. Most operations are linear in string length. Side effects are limited to filesystem existence checks in path normalization helpers.
4024
+
4025
+ ## Imports
4026
+ ```
4027
+ import fs from "node:fs";
4028
+ import os from "node:os";
4029
+ import path from "node:path";
4030
+ ```
4031
+
4032
+ ## Definitions
4033
+
4034
+ ### fn `export function formatSubstitutedPath(value: string): string` (L17-19)
4035
+ - @brief Normalizes path separators to forward slashes.
4036
+ - @details Leaves empty input as an empty string and converts platform-specific separators to POSIX form for prompt-safe display. Time complexity is O(n) in path length. No side effects occur.
4037
+ - @param[in] value {string} Path-like string.
4038
+ - @return {string} Slash-normalized path string.
4039
+
4040
+ ### fn `export function makeRelativeIfContainsProject(pathValue: string, projectBase: string): string` (L28-68)
4041
+ - @brief Rewrites a path to be project-relative when it resolves inside the project root.
4042
+ - @details Handles absolute paths, repeated project-name prefixes, and embedded project-name segments, then falls back to the original value when safe relativization is not possible. Runtime is O(p) plus filesystem checks for candidate suffixes. Side effects are limited to existence checks.
4043
+ - @param[in] pathValue {string} User-supplied path value.
4044
+ - @param[in] projectBase {string} Absolute project root used as the relativization anchor.
4045
+ - @return {string} Project-relative path when derivable; otherwise the original or best-effort normalized input.
4046
+
4047
+ ### fn `export function resolveAbsolute(normalized: string, projectBase: string): string | undefined` (L77-80)
4048
+ - @brief Resolves a normalized path against the project root.
4049
+ - @details Returns `undefined` for empty input, preserves absolute paths, and resolves relative paths from `projectBase`. Time complexity is O(p). No side effects occur.
4050
+ - @param[in] normalized {string} Normalized path token.
4051
+ - @param[in] projectBase {string} Absolute project root.
4052
+ - @return {string | undefined} Absolute path or `undefined` for empty input.
4053
+
4054
+ ### fn `export function computeSubPath(normalized: string, absolute: string | undefined, projectBase: string): string` (L90-99)
4055
+ - @brief Computes a slash-normalized project subpath for display or config storage.
4056
+ - @details Prefers a relative path derived from the provided absolute path when it stays inside the project root; otherwise formats the normalized input directly. Runtime is O(p). No side effects occur.
4057
+ - @param[in] normalized {string} Original normalized path token.
4058
+ - @param[in] absolute {string | undefined} Absolute candidate path.
4059
+ - @param[in] projectBase {string} Absolute project root.
4060
+ - @return {string} Slash-normalized subpath.
4061
+
4062
+ ### fn `export function makeRelativeToken(raw: string, keepTrailing = false): string` (L108-114)
4063
+ - @brief Normalizes a raw path token into a relative slash-separated fragment.
4064
+ - @details Removes leading and trailing separators, converts backslashes to slashes, and optionally preserves a trailing slash marker. Runtime is O(n). No side effects occur.
4065
+ - @param[in] raw {string} Raw token to normalize.
4066
+ - @param[in] keepTrailing {boolean} When `true`, preserve a trailing slash if the input contained one.
4067
+ - @return {string} Normalized relative token.
4068
+
4069
+ ### fn `export function shellSplit(value: string): string[]` (L122-160)
4070
+ - @brief Splits a shell-style argument string into tokens.
4071
+ - @details Supports single quotes, double quotes, backslash escaping, and whitespace token boundaries without invoking an external shell. Runtime is O(n). No side effects occur.
4072
+ - @param[in] value {string} Raw argument string.
4073
+ - @return {string[]} Parsed token list.
4074
+
4075
+ ### fn `export function homeRelative(absolutePath: string): string` (L168-175)
4076
+ - @brief Rewrites an absolute path relative to the user's home directory when possible.
4077
+ - @details Returns `~` for the home directory itself, `~/...` for descendants, and a slash-normalized original path otherwise. Runtime is O(p). No side effects occur.
4078
+ - @param[in] absolutePath {string} Absolute path candidate.
4079
+ - @return {string} Home-relative or slash-normalized path string.
4080
+
4081
+ ### fn `export function escapeRegExp(value: string): string` (L183-185)
4082
+ - @brief Escapes regular-expression metacharacters in a literal string.
4083
+ - @details Replaces every regex-significant character with its escaped form so the result can be embedded safely into a dynamic pattern. Runtime is O(n). No side effects occur.
4084
+ - @param[in] value {string} Literal string to escape.
4085
+ - @return {string} Regex-safe literal fragment.
4086
+
4087
+ ## Symbol Index
4088
+ |Symbol|Kind|Vis|Lines|Sig|
4089
+ |---|---|---|---|---|
4090
+ |`formatSubstitutedPath`|fn||17-19|export function formatSubstitutedPath(value: string): string|
4091
+ |`makeRelativeIfContainsProject`|fn||28-68|export function makeRelativeIfContainsProject(pathValue: ...|
4092
+ |`resolveAbsolute`|fn||77-80|export function resolveAbsolute(normalized: string, proje...|
4093
+ |`computeSubPath`|fn||90-99|export function computeSubPath(normalized: string, absolu...|
4094
+ |`makeRelativeToken`|fn||108-114|export function makeRelativeToken(raw: string, keepTraili...|
4095
+ |`shellSplit`|fn||122-160|export function shellSplit(value: string): string[]|
4096
+ |`homeRelative`|fn||168-175|export function homeRelative(absolutePath: string): string|
4097
+ |`escapeRegExp`|fn||183-185|export function escapeRegExp(value: string): string|
4098
+
4099
+
4100
+ ---
4101
+
4102
+ # index.ts | TypeScript | 2209L | 50 symbols | 21 imports | 53 comments
4103
+ > Path: `src/index.ts`
4104
+ - @brief Registers the pi-usereq extension commands, tools, and configuration UI.
4105
+ - @details Bridges the standalone tool-runner layer into the pi extension API by registering prompt commands, agent tools, and interactive configuration menus. Runtime at module load is O(1); later behavior depends on the selected command or tool. Side effects include extension registration, UI updates, filesystem reads/writes, and delegated tool execution.
4106
+
4107
+ ## Imports
4108
+ ```
4109
+ import path from "node:path";
4110
+ import type {
4111
+ import { Type } from "@sinclair/typebox";
4112
+ import {
4113
+ import {
4114
+ import {
4115
+ import {
4116
+ import {
4117
+ import {
4118
+ import {
4119
+ import { buildRuntimePathContext, buildRuntimePathFacts } from "./core/path-context.js";
4120
+ import { resolveRuntimeGitPath } from "./core/runtime-project-paths.js";
4121
+ import { showPiUsereqSettingsMenu, type PiUsereqSettingsMenuChoice } from "./core/settings-menu.js";
4122
+ import {
4123
+ import { renderPrompt } from "./core/prompts.js";
4124
+ import { ensureBundledResourcesAccessible } from "./core/resources.js";
4125
+ import {
4126
+ import {
4127
+ import { LANGUAGE_TAGS } from "./core/find-constructs.js";
4128
+ import {
4129
+ import { makeRelativeIfContainsProject, shellSplit } from "./core/utils.js";
4130
+ ```
4131
+
4132
+ ## Definitions
4133
+
4134
+ ### iface `interface PiShortcutRegistrar` (L137-145)
4135
+ - @brief Describes the optional shortcut-registration surface used by pi-usereq.
4136
+ - @details Narrows the runtime API to the documented `registerShortcut(...)`
4137
+ method so the extension can remain compatible with offline harnesses that do
4138
+ not implement shortcut capture. Compile-time only and introduces no runtime
4139
+ cost.
4140
+
4141
+ ### fn `function getProjectBase(cwd: string): string` (L153-155)
4142
+ - @brief Resolves the effective project base from a working directory.
4143
+ - @details Normalizes the provided cwd into an absolute path without consulting configuration. Time complexity is O(1). No I/O side effects occur.
4144
+ - @param[in] cwd {string} Current working directory.
4145
+ - @return {string} Absolute project base path.
4146
+
4147
+ ### fn `function buildSharedRuntimePathFacts(cwd: string, config: UseReqConfig): import("./core/path-context.js").RuntimePathFacts` (L165-169)
4148
+ - @brief Builds the shared runtime path facts for the current command or tool context.
4149
+ - @details Derives installation, execution, base, config, resource, docs, test, source, and optional git paths from the cwd-derived project configuration plus runtime-only repository probing, then converts them into prompt/tool-facing strings. Runtime is O(s + p) where s is configured source-directory count and p is aggregate path length. Side effects are limited to git subprocess execution.
4150
+ - @param[in] cwd {string} Current working directory.
4151
+ - @param[in] config {UseReqConfig} Effective project configuration.
4152
+ - @return {import("./core/path-context.js").RuntimePathFacts} Shared runtime path facts.
4153
+ - @satisfies REQ-145, REQ-146
4154
+
4155
+ ### fn `function loadProjectConfig(cwd: string): UseReqConfig` (L178-181)
4156
+ - @brief Loads project configuration for the extension runtime.
4157
+ - @details Resolves the project base, loads persisted config, and normalizes configured directory paths without reading or persisting runtime-derived `base-path` or `git-path` metadata. Runtime is dominated by config I/O. Side effects are limited to filesystem reads.
4158
+ - @param[in] cwd {string} Current working directory.
4159
+ - @return {UseReqConfig} Effective project configuration.
4160
+ - @satisfies REQ-030, REQ-145, REQ-146
4161
+
4162
+ ### fn `function saveProjectConfig(cwd: string, config: UseReqConfig): void` (L191-194)
4163
+ - @brief Persists project configuration from the extension runtime.
4164
+ - @details Resolves the project base, normalizes configured directory paths into project-relative form, and delegates persistence to `saveConfig` without serializing runtime-derived path metadata. Runtime is O(n) in config size. Side effects include config-file writes.
4165
+ - @param[in] cwd {string} Current working directory.
4166
+ - @param[in] config {UseReqConfig} Configuration to persist.
4167
+ - @return {void} No return value.
4168
+ - @satisfies REQ-146
4169
+
4170
+ ### fn `function collectProjectStaticCheckSelection(` (L203-234)
4171
+ - @brief Collects the project-scoped static-check selection used by the agent tool.
4172
+ - @details Resolves configured source plus test directories, reuses the same fixture-root exclusions as `runProjectStaticCheck`, and returns canonical relative file paths for structured payload emission. Runtime is O(F) plus project file-discovery cost. Side effects are limited to filesystem reads and git subprocesses delegated through `collectSourceFiles`.
4173
+ - @param[in] projectBase {string} Resolved project base path.
4174
+ - @param[in] config {UseReqConfig} Effective project configuration.
4175
+ - @return {{ selectionDirectoryPaths: string[]; excludedDirectoryPaths: string[]; selectedPaths: string[] }} Structured static-check selection facts.
4176
+
4177
+ ### fn `function buildTokenToolExecutionStderr(payload: TokenToolPayload): string` (L242-248)
4178
+ - @brief Builds execution diagnostics for one token-tool payload.
4179
+ - @details Serializes skipped-input and read-error observations into stable stderr lines while leaving successful counted files silent. Runtime is O(n) in issue count. No side effects occur.
4180
+ - @param[in] payload {TokenToolPayload} Structured token payload.
4181
+ - @return {string} Newline-delimited execution diagnostics.
4182
+
4183
+ ### fn `function buildTokenToolExecuteResult(` (L257-274)
4184
+ - @brief Builds the agent-oriented execute result returned by token-count tools.
4185
+ - @details Mirrors the structured token payload into both the text `content` channel and the machine-readable `details` channel while isolating execution metadata under `execution`. Runtime is O(n) in payload size. No side effects occur.
4186
+ - @param[in] payload {TokenToolPayload} Structured token payload.
4187
+ - @return {{ content: Array<{ type: "text"; text: string }>; details: TokenToolPayload & { execution: { code: number; stderr: string } } }} Token-tool execute result.
4188
+ - @satisfies REQ-069, REQ-070, REQ-071, REQ-073, REQ-074, REQ-075, REQ-099, REQ-102
4189
+
4190
+ ### fn `function buildReferenceToolExecuteResult(` (L283-300)
4191
+ - @brief Builds the agent-oriented execute result returned by references tools.
4192
+ - @details Mirrors the structured references payload into both the text `content` channel and the machine-readable `details` channel while isolating execution metadata under `execution`. Runtime is O(n) in payload size. No side effects occur.
4193
+ - @param[in] payload {ReferenceToolPayload} Structured references payload.
4194
+ - @return {{ content: Array<{ type: "text"; text: string }>; details: ReferenceToolPayload & { execution: { code: number; stderr: string } } }} References-tool execute result.
4195
+ - @satisfies REQ-076, REQ-077, REQ-078, REQ-079, REQ-099, REQ-102
4196
+
4197
+ ### fn `function buildCompressionToolExecuteResult(` (L309-326)
4198
+ - @brief Builds the agent-oriented execute result returned by compression tools.
4199
+ - @details Mirrors the structured compression payload into both the text `content` channel and the machine-readable `details` channel while isolating execution metadata under `execution`. Runtime is O(n) in payload size. No side effects occur.
4200
+ - @param[in] payload {CompressToolPayload} Structured compression payload.
4201
+ - @return {{ content: Array<{ type: "text"; text: string }>; details: CompressToolPayload & { execution: { code: number; stderr: string } } }} Compression-tool execute result.
4202
+ - @satisfies REQ-081, REQ-082, REQ-083, REQ-084, REQ-085, REQ-087, REQ-088, REQ-099, REQ-102
4203
+
4204
+ ### fn `function buildFindToolSupportedTagGuidelines(): string[]` (L387-391)
4205
+ - @brief Builds the supported-tag guidance lines embedded in find-tool registrations.
4206
+ - @details Emits one deterministic line per supported language containing its canonical registration label and sorted tag list so downstream agents can specialize requests without invoking the tool first. Runtime is O(l * t log t). No side effects occur.
4207
+ - @return {string[]} Supported-tag guidance lines.
4208
+
4209
+ ### fn `function buildFindToolSchemaDescription(scope: FindToolScope): string` (L399-404)
4210
+ - @brief Builds the schema description for one find-tool registration.
4211
+ - @details Specializes the input-scope sentence for explicit-file or configured-directory searches while keeping the JSON output contract stable and fully machine-readable. Runtime is O(1). No side effects occur.
4212
+ - @param[in] scope {FindToolScope} Find-tool scope.
4213
+ - @return {string} Parameter-schema description.
4214
+
4215
+ ### fn `function buildFindToolPromptGuidelines(scope: FindToolScope): string[]` (L412-428)
4216
+ - @brief Builds the prompt-guideline set for one find-tool registration.
4217
+ - @details Encodes scope selection, output schema, regex semantics, line-number behavior, tag-filter rules, and the full language-to-tag matrix as stable agent-oriented strings. Runtime is O(l * t log t). No side effects occur.
4218
+ - @param[in] scope {FindToolScope} Find-tool scope.
4219
+ - @return {string[]} Prompt-guideline strings.
4220
+
4221
+ ### fn `function buildFindToolExecuteResult(` (L437-455)
4222
+ - @brief Builds the agent-oriented execute result returned by find tools.
4223
+ - @details Mirrors the structured find payload into both the text `content` channel and the machine-readable `details` channel while isolating execution metadata under `execution`. Runtime is O(n) in payload size. No side effects occur.
4224
+ - @param[in] payload {FindToolPayload} Structured find payload.
4225
+ - @return {{ content: Array<{ type: "text"; text: string }>; details: FindToolPayload & { execution: { code: number; stderr: string } } }} Find-tool execute result.
4226
+ - @satisfies REQ-089, REQ-090, REQ-091, REQ-092, REQ-093, REQ-094, REQ-097, REQ-098, REQ-099, REQ-102
4227
+
4228
+ ### fn `async function deliverPromptCommand(pi: ExtensionAPI, content: string): Promise<void>` (L465-467)
4229
+ - @brief Delivers one rendered prompt into the active session.
4230
+ - @details Writes the rendered prompt directly through `pi.sendUserMessage(...)` without creating replacement sessions or pre-reset flows. Runtime is O(n) in prompt length. Side effects are limited to user-message delivery.
4231
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4232
+ - @param[in] content {string} Rendered prompt markdown.
4233
+ - @return {Promise<void>} Promise resolved after the prompt is queued for delivery.
4234
+ - @satisfies REQ-004, REQ-067, REQ-068
4235
+
4236
+ ### fn `function getPiUsereqStartupTools(pi: ExtensionAPI): ToolInfo[]` (L476-481)
4237
+ - @brief Returns the configurable active-tool inventory visible to the extension.
4238
+ - @details Filters runtime tools against the canonical configurable-tool set, thereby combining extension-owned tools with supported embedded pi CLI tools. Output order is sorted by tool name. Runtime is O(t log t). No external state is mutated.
4239
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4240
+ - @return {ToolInfo[]} Sorted configurable tool descriptors.
4241
+ - @satisfies REQ-007, REQ-063
4242
+
4243
+ ### fn `function getConfiguredEnabledPiUsereqTools(config: UseReqConfig): string[]` (L489-493)
4244
+ - @brief Normalizes and returns the configured enabled active tools.
4245
+ - @details Reuses repository normalization rules, updates the config object in place, and returns the normalized array. Runtime is O(n) in configured tool count. Side effect: mutates `config["enabled-tools"]`.
4246
+ - @param[in,out] config {UseReqConfig} Mutable configuration object.
4247
+ - @return {string[]} Normalized enabled tool names.
4248
+
4249
+ ### fn `function getPiUsereqToolKind(tool: ToolInfo): "builtin" | "extension"` (L501-506)
4250
+ - @brief Classifies one configurable tool as embedded or extension-owned.
4251
+ - @details Uses the runtime `sourceInfo.source` field plus the supported embedded-name subset to produce one stable UI label. Runtime is O(1). No external state is mutated.
4252
+ - @param[in] tool {ToolInfo} Runtime tool descriptor.
4253
+ - @return {"builtin" | "extension"} Stable tool-kind label.
4254
+
4255
+ ### fn `function applyConfiguredPiUsereqTools(pi: ExtensionAPI, config: UseReqConfig): void` (L516-533)
4256
+ - @brief Applies the configured active-tool enablement to the current session.
4257
+ - @details Preserves non-configurable active tools, removes every configurable tool from the active set, then re-adds only configured tools that exist in the current runtime inventory. Runtime is O(t). Side effects include `pi.setActiveTools(...)`.
4258
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4259
+ - @param[in] config {UseReqConfig} Effective project configuration.
4260
+ - @return {void} No return value.
4261
+ - @satisfies REQ-009, REQ-064
4262
+
4263
+ ### fn `async function handleExtensionStatusEvent(` (L553-573)
4264
+ - @brief Handles one intercepted pi lifecycle hook for pi-usereq status updates.
4265
+ - @details Applies session-start-specific resource validation, project-config
4266
+ refresh, and startup-tool enablement before forwarding the originating hook
4267
+ name and payload into the shared `updateExtensionStatus(...)` pipeline.
4268
+ On `agent_end`, also dispatches configured pi-notify beep and sound effects.
4269
+ Runtime is dominated by configuration loading during `session_start`; all
4270
+ other hooks are O(1). Side effects include resource checks, active-tool
4271
+ mutation, status updates, live-ticker disposal on shutdown, stdout writes,
4272
+ and optional child-process spawning.
4273
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4274
+ - @param[in] hookName {PiUsereqStatusHookName} Intercepted hook name.
4275
+ - @param[in] event {unknown} Hook payload forwarded by pi.
4276
+ - @param[in] ctx {ExtensionContext} Active extension context.
4277
+ - @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
4278
+ - @return {Promise<void>} Promise resolved when hook processing completes.
4279
+ - @satisfies REQ-117, REQ-118, REQ-119, REQ-129, REQ-130, REQ-131, REQ-132, REQ-133
4280
+
4281
+ ### fn `function registerExtensionStatusHooks(` (L586-599)
4282
+ - @brief Registers shared wrappers for every supported pi lifecycle hook.
4283
+ - @details Installs one generic wrapper per intercepted hook so every resource,
4284
+ session, agent, model, tool, bash, and input event is routed through the
4285
+ same extension-status update pipeline. Runtime is O(h) in registered hook
4286
+ count. Side effects include hook registration.
4287
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4288
+ - @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
4289
+ - @return {void} No return value.
4290
+ - @satisfies DES-002, REQ-113, REQ-114, REQ-115, REQ-116, REQ-117
4291
+
4292
+ ### fn `function setConfiguredPiUsereqTools(pi: ExtensionAPI, config: UseReqConfig, enabledTools: string[]): void` (L609-612)
4293
+ - @brief Replaces the configured active-tool selection and applies it immediately.
4294
+ - @details Normalizes the requested tool names, stores them in config, and synchronizes the active tool set with runtime registration state. Runtime is O(n + t). Side effect: mutates config and active tools.
4295
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4296
+ - @param[in] enabledTools {string[]} Requested enabled tool names.
4297
+ - @param[in,out] config {UseReqConfig} Mutable configuration object.
4298
+ - @return {void} No return value.
4299
+
4300
+ ### fn `function renderPiUsereqToolsReference(pi: ExtensionAPI, config: UseReqConfig): string` (L621-649)
4301
+ - @brief Renders a textual reference for configurable-tool configuration and runtime state.
4302
+ - @details Lists every configurable tool with configured enablement, runtime activation, builtin-versus-extension classification, source metadata, and optional descriptions. Runtime is O(t). No side effects occur.
4303
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4304
+ - @param[in] config {UseReqConfig} Effective project configuration.
4305
+ - @return {string} Multiline tool-status report.
4306
+
4307
+ - type `type PiNotifyBeepConfigKey =` (L657)
4308
+ - @brief Represents one persisted pi-notify beep flag key.
4309
+ - @details Restricts menu toggles to the three independent prompt-end beep
4310
+ flags stored in project configuration. Compile-time only and introduces no
4311
+ runtime cost.
4312
+ ### fn `function togglePiNotifyBeepFlag(config: UseReqConfig, key: PiNotifyBeepConfigKey): boolean` (L669-672)
4313
+ - @brief Flips one persisted pi-notify beep flag.
4314
+ - @details Negates the selected prompt-end beep flag in place and returns the resulting boolean value so callers can emit deterministic UI feedback. Runtime is O(1). Side effect: mutates `config`.
4315
+ - @param[in] key {PiNotifyBeepConfigKey} Beep flag key to toggle.
4316
+ - @param[in,out] config {UseReqConfig} Mutable configuration object.
4317
+ - @return {boolean} Next enabled state.
4318
+
4319
+ ### fn `function buildPiNotifyMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice[]` (L681-738)
4320
+ - @brief Builds the shared settings-menu choices for notification configuration.
4321
+ - @details Serializes the current beep flags, selected notify command, hotkey bind, and per-level notify commands into right-valued menu rows consumed by the shared settings-menu renderer. Runtime is O(1) plus command-length formatting. No external state is mutated.
4322
+ - @param[in] config {UseReqConfig} Effective project configuration.
4323
+ - @return {PiUsereqSettingsMenuChoice[]} Ordered notification-menu choice vector.
4324
+ - @satisfies REQ-137, REQ-149, REQ-150, REQ-151, REQ-152
4325
+
4326
+ ### fn `async function selectPiNotifySoundLevel(` (L748-779)
4327
+ - @brief Opens the shared settings-menu selector for the selected notify command.
4328
+ - @details Reuses the pi-usereq settings-menu renderer so notify-command selection remains stylistically aligned with the main configuration UI and returns the chosen sound level or `undefined` on cancel. Runtime depends on user interaction count. Side effects are limited to transient custom-UI rendering.
4329
+ - @param[in] ctx {ExtensionCommandContext} Active command context.
4330
+ - @param[in] currentLevel {PiNotifySoundLevel} Currently selected notify command.
4331
+ - @return {Promise<PiNotifySoundLevel | undefined>} Selected sound level or `undefined` when cancelled.
4332
+ - @satisfies REQ-131, REQ-137, REQ-149, REQ-151, REQ-152, REQ-153, REQ-154
4333
+
4334
+ ### fn `async function configurePiNotifyMenu(` (L789-854)
4335
+ - @brief Runs the interactive notification-configuration menu.
4336
+ - @details Exposes prompt-end beep toggles, selected notify-command selection, hotkey-bind editing, and per-level notify-command editors through the shared settings-menu renderer. Runtime depends on user interaction count. Side effects include UI updates and config mutation.
4337
+ - @param[in] ctx {ExtensionCommandContext} Active command context.
4338
+ - @param[in,out] config {UseReqConfig} Mutable configuration object.
4339
+ - @return {Promise<boolean>} `true` when the sound-toggle shortcut changed.
4340
+ - @satisfies REQ-129, REQ-131, REQ-133, REQ-134, REQ-137, REQ-149, REQ-150, REQ-151, REQ-152, REQ-153, REQ-154
4341
+
4342
+ ### fn `function registerPiNotifyShortcut(` (L869-889)
4343
+ - @brief Registers the configurable successful-run sound shortcut when supported.
4344
+ - @details Loads the current project config, registers one raw pi shortcut when
4345
+ the runtime exposes `registerShortcut(...)`, cycles persisted sound state on
4346
+ invocation, saves the config, refreshes the status bar, and emits one info
4347
+ notification. Runtime is O(1) for registration plus config I/O per shortcut
4348
+ use. Side effects include shortcut registration, config writes, and status
4349
+ updates.
4350
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4351
+ - @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
4352
+ - @return {void} No return value.
4353
+ - @satisfies REQ-131, REQ-134, REQ-136
4354
+
4355
+ ### fn `function registerPromptCommands(pi: ExtensionAPI): void` (L898-911)
4356
+ - @brief Registers bundled prompt commands with the extension.
4357
+ - @details Creates one `req-<prompt>` command per bundled prompt name. Each handler ensures resources exist, renders the prompt, and sends it into the current active session. Runtime is O(p) for registration; handler cost depends on prompt rendering plus prompt dispatch. Side effects include command registration and user-message delivery during execution.
4358
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4359
+ - @return {void} No return value.
4360
+ - @satisfies REQ-004, REQ-067, REQ-068
4361
+
4362
+ ### fn `function registerAgentTools(pi: ExtensionAPI): void` (L921-1220)
4363
+ - @brief Registers pi-usereq agent tools exposed to the model.
4364
+ - @details Defines the tool schemas, prompt metadata, and execution handlers that bridge extension tool calls into tool-runner operations without registering duplicate custom slash commands for the same capabilities. Runtime is O(t) for registration; execution cost depends on the selected tool. Side effects include tool registration.
4365
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4366
+ - @return {void} No return value.
4367
+ - @satisfies REQ-005, REQ-010, REQ-011, REQ-014, REQ-017, REQ-044, REQ-045, REQ-069, REQ-070, REQ-071, REQ-072, REQ-073, REQ-074, REQ-075, REQ-076, REQ-077, REQ-078, REQ-079, REQ-080, REQ-089, REQ-090, REQ-091, REQ-092, REQ-093, REQ-094, REQ-095, REQ-096, REQ-097, REQ-098, REQ-099, REQ-100, REQ-101, REQ-102
4368
+
4369
+ ### fn `function buildPiUsereqToolsMenuChoices(pi: ExtensionAPI, config: UseReqConfig): PiUsereqSettingsMenuChoice[]` (L1564-1604)
4370
+ - @brief Builds the shared settings-menu choices for startup-tool management.
4371
+ - @details Serializes startup-tool actions into right-valued menu rows consumed by the shared settings-menu renderer. Runtime is O(t) in configurable-tool count. No external state is mutated.
4372
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4373
+ - @param[in] config {UseReqConfig} Effective project configuration.
4374
+ - @return {PiUsereqSettingsMenuChoice[]} Ordered startup-tool menu choices.
4375
+ - @satisfies REQ-007, REQ-151, REQ-152, REQ-153, REQ-154
4376
+
4377
+ ### fn `function buildPiUsereqToolToggleChoices(pi: ExtensionAPI, config: UseReqConfig): PiUsereqSettingsMenuChoice[]` (L1614-1630)
4378
+ - @brief Builds the shared settings-menu choices for per-tool startup toggles.
4379
+ - @details Exposes every configurable startup tool as one row whose right-side value reports the current enabled state. Runtime is O(t) in configurable-tool count. No external state is mutated.
4380
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4381
+ - @param[in] config {UseReqConfig} Effective project configuration.
4382
+ - @return {PiUsereqSettingsMenuChoice[]} Ordered per-tool toggle choices.
4383
+ - @satisfies REQ-007, REQ-151, REQ-152, REQ-153, REQ-154
4384
+
4385
+ ### fn `async function configurePiUsereqToolsMenu(pi: ExtensionAPI, ctx: ExtensionCommandContext, config: UseReqConfig): Promise<void>` (L1641-1692)
4386
+ - @brief Runs the interactive active-tool configuration menu.
4387
+ - @details Synchronizes runtime active tools with persisted config, renders startup-tool actions through the shared settings-menu UI, and updates configuration state in response to selections until the user exits. Runtime depends on user interaction count. Side effects include UI updates, active-tool changes, and config mutation.
4388
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4389
+ - @param[in] ctx {ExtensionCommandContext} Active command context.
4390
+ - @param[in,out] config {UseReqConfig} Mutable configuration object.
4391
+ - @return {Promise<void>} Promise resolved when the menu closes.
4392
+ - @satisfies REQ-007, REQ-063, REQ-064, REQ-151, REQ-152, REQ-153, REQ-154
4393
+
4394
+ ### fn `function formatStaticCheckEntry(entry: StaticCheckEntry): string` (L1700-1706)
4395
+ - @brief Formats one static-check configuration entry for UI display.
4396
+ - @details Renders command-backed entries as `Command(cmd args...)` and all other modules as `Module(args...)`. Runtime is O(n) in parameter count. No side effects occur.
4397
+ - @param[in] entry {StaticCheckEntry} Static-check configuration entry.
4398
+ - @return {string} Human-readable entry summary.
4399
+
4400
+ ### fn `function formatStaticCheckLanguagesSummary(config: UseReqConfig): string` (L1714-1720)
4401
+ - @brief Summarizes configured static-check languages.
4402
+ - @details Keeps only languages with at least one configured checker, sorts them, and emits a compact `Language (count)` list. Runtime is O(l log l). No side effects occur.
4403
+ - @param[in] config {UseReqConfig} Effective project configuration.
4404
+ - @return {string} Compact summary string or `(none)`.
4405
+
4406
+ ### fn `function renderStaticCheckReference(config: UseReqConfig): string` (L1728-1749)
4407
+ - @brief Renders the static-check configuration reference view.
4408
+ - @details Produces a markdown-like summary containing configured entries, supported languages, supported modules, and example specifications. Runtime is O(l log l). No side effects occur.
4409
+ - @param[in] config {UseReqConfig} Effective project configuration.
4410
+ - @return {string} Reference text for the editor view.
4411
+
4412
+ ### fn `function buildStaticCheckMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice[]` (L1758-1793)
4413
+ - @brief Builds the shared settings-menu choices for static-check management.
4414
+ - @details Serializes static-check actions into right-valued menu rows consumed by the shared settings-menu renderer. Runtime is O(1). No external state is mutated.
4415
+ - @param[in] config {UseReqConfig} Effective project configuration.
4416
+ - @return {PiUsereqSettingsMenuChoice[]} Ordered static-check menu choices.
4417
+ - @satisfies REQ-008, REQ-151, REQ-152, REQ-153, REQ-154
4418
+
4419
+ ### fn `function buildSupportedStaticCheckLanguageChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice[]` (L1801-1820)
4420
+ - @brief Builds the shared settings-menu choices for supported static-check languages.
4421
+ - @details Exposes every supported language as one row whose right-side value reports extensions plus the current configured checker count. Runtime is O(l log l). No external state is mutated.
4422
+ - @param[in] config {UseReqConfig} Effective project configuration.
4423
+ - @return {PiUsereqSettingsMenuChoice[]} Ordered language-choice vector.
4424
+
4425
+ ### fn `function buildStaticCheckModuleChoices(language: string): PiUsereqSettingsMenuChoice[]` (L1828-1845)
4426
+ - @brief Builds the shared settings-menu choices for static-check modules.
4427
+ - @details Exposes every supported static-check module as one selectable row with a concise execution description. Runtime is O(m) in module count. No external state is mutated.
4428
+ - @param[in] language {string} Canonical selected language.
4429
+ - @return {PiUsereqSettingsMenuChoice[]} Ordered module-choice vector.
4430
+
4431
+ ### fn `function buildConfiguredStaticCheckLanguageChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice[]` (L1853-1870)
4432
+ - @brief Builds the shared settings-menu choices for configured static-check languages.
4433
+ - @details Exposes only languages that currently have at least one configured checker so removal remains deterministic. Runtime is O(l log l). No external state is mutated.
4434
+ - @param[in] config {UseReqConfig} Effective project configuration.
4435
+ - @return {PiUsereqSettingsMenuChoice[]} Ordered configured-language vector.
4436
+
4437
+ ### fn `async function configureStaticCheckMenu(ctx: ExtensionCommandContext, config: UseReqConfig): Promise<void>` (L1880-1953)
4438
+ - @brief Runs the interactive static-check configuration menu.
4439
+ - @details Lets the user inspect support, add entries by guided prompts or raw spec strings, and remove configured language entries through the shared settings-menu renderer until the user exits. Runtime depends on user interaction count. Side effects include UI updates and config mutation.
4440
+ - @param[in] ctx {ExtensionCommandContext} Active command context.
4441
+ - @param[in,out] config {UseReqConfig} Mutable configuration object.
4442
+ - @return {Promise<void>} Promise resolved when the menu closes.
4443
+ - @satisfies REQ-008, REQ-151, REQ-152, REQ-153, REQ-154
4444
+
4445
+ ### fn `function buildPiUsereqMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice[]` (L1962-2019)
4446
+ - @brief Builds the shared settings-menu choices for the top-level pi-usereq configuration UI.
4447
+ - @details Serializes primary configuration actions into right-valued menu rows consumed by the shared settings-menu renderer. Runtime is O(s) in source-directory count. No external state is mutated.
4448
+ - @param[in] config {UseReqConfig} Effective project configuration.
4449
+ - @return {PiUsereqSettingsMenuChoice[]} Ordered top-level menu choices.
4450
+ - @satisfies REQ-006, REQ-031, REQ-137, REQ-150, REQ-151, REQ-152
4451
+
4452
+ ### fn `function buildSrcDirMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice[]` (L2028-2049)
4453
+ - @brief Builds the shared settings-menu choices for source-directory management.
4454
+ - @details Exposes add and remove actions for `src-dir` entries through right-valued menu rows consumed by the shared settings-menu renderer. Runtime is O(s) in source-directory count. No external state is mutated.
4455
+ - @param[in] config {UseReqConfig} Effective project configuration.
4456
+ - @return {PiUsereqSettingsMenuChoice[]} Ordered source-directory management choices.
4457
+ - @satisfies REQ-006, REQ-151, REQ-152, REQ-153, REQ-154
4458
+
4459
+ ### fn `function buildSrcDirRemovalChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice[]` (L2058-2073)
4460
+ - @brief Builds the shared settings-menu choices for removing one source-directory entry.
4461
+ - @details Exposes every configured `src-dir` entry as one removable row and appends a `Back` action for cancellation. Runtime is O(s) in source-directory count. No external state is mutated.
4462
+ - @param[in] config {UseReqConfig} Effective project configuration.
4463
+ - @return {PiUsereqSettingsMenuChoice[]} Ordered removable source-directory choices.
4464
+ - @satisfies REQ-006, REQ-151, REQ-152, REQ-153, REQ-154
4465
+
4466
+ ### fn `async function configurePiUsereq(` (L2084-2165)
4467
+ - @brief Runs the top-level pi-usereq configuration menu.
4468
+ - @details Loads project config, exposes docs/test/source/static-check/startup-tool/notification actions through the shared settings-menu renderer, persists changes on exit, and refreshes the single-line status bar. Runtime depends on user interaction count. Side effects include UI updates, config writes, and active-tool changes.
4469
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4470
+ - @param[in] ctx {ExtensionCommandContext} Active command context.
4471
+ - @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
4472
+ - @return {Promise<void>} Promise resolved when configuration is saved and the menu closes.
4473
+ - @satisfies REQ-006, REQ-031, REQ-137, REQ-150, REQ-151, REQ-152, REQ-153, REQ-154
4474
+
4475
+ ### fn `const ensureSaved = () => saveProjectConfig(ctx.cwd, config)` (L2092-2096)
4476
+
4477
+ ### fn `const refreshStatus = () =>` (L2093-2096)
4478
+
4479
+ ### fn `function registerConfigCommands(` (L2175-2185)
4480
+ - @brief Registers configuration-management commands.
4481
+ - @details Adds the interactive `pi-usereq` configuration command only; the config-viewer action is now exposed exclusively inside that menu. Runtime is O(1) for registration. Side effects include command registration.
4482
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4483
+ - @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
4484
+ - @return {void} No return value.
4485
+ - @satisfies REQ-006, REQ-031
4486
+
4487
+ ### fn `export default function piUsereqExtension(pi: ExtensionAPI): void` (L2201-2209)
4488
+ - @brief Registers the complete pi-usereq extension.
4489
+ - @details Validates installation-owned bundled resources, registers prompt and
4490
+ configuration commands plus agent tools, registers the configurable
4491
+ successful-run sound shortcut when the runtime supports shortcuts, and
4492
+ installs shared wrappers for all supported pi lifecycle hooks so status
4493
+ telemetry, context usage, prompt timing, and pi-notify effects remain
4494
+ synchronized with runtime events. Runtime is O(h) in hook count during
4495
+ registration. Side effects include filesystem reads, command/tool/shortcut
4496
+ registration, UI updates, active-tool changes, and timer scheduling.
4497
+ - @param[in] pi {ExtensionAPI} Active extension API instance.
4498
+ - @return {void} No return value.
4499
+ - @satisfies DES-002, REQ-004, REQ-005, REQ-009, REQ-044, REQ-045, REQ-067, REQ-068, REQ-109, REQ-110, REQ-111, REQ-112, REQ-113, REQ-114, REQ-115, REQ-116, REQ-117, REQ-118, REQ-119, REQ-120, REQ-121, REQ-122, REQ-123, REQ-124, REQ-125, REQ-126, REQ-129, REQ-130, REQ-131, REQ-132, REQ-133, REQ-134, REQ-135, REQ-136, REQ-137
4500
+
4501
+ ## Symbol Index
4502
+ |Symbol|Kind|Vis|Lines|Sig|
4503
+ |---|---|---|---|---|
4504
+ |`PiShortcutRegistrar`|iface||137-145|interface PiShortcutRegistrar|
4505
+ |`getProjectBase`|fn||153-155|function getProjectBase(cwd: string): string|
4506
+ |`buildSharedRuntimePathFacts`|fn||165-169|function buildSharedRuntimePathFacts(cwd: string, config:...|
4507
+ |`loadProjectConfig`|fn||178-181|function loadProjectConfig(cwd: string): UseReqConfig|
4508
+ |`saveProjectConfig`|fn||191-194|function saveProjectConfig(cwd: string, config: UseReqCon...|
4509
+ |`collectProjectStaticCheckSelection`|fn||203-234|function collectProjectStaticCheckSelection(|
4510
+ |`buildTokenToolExecutionStderr`|fn||242-248|function buildTokenToolExecutionStderr(payload: TokenTool...|
4511
+ |`buildTokenToolExecuteResult`|fn||257-274|function buildTokenToolExecuteResult(|
4512
+ |`buildReferenceToolExecuteResult`|fn||283-300|function buildReferenceToolExecuteResult(|
4513
+ |`buildCompressionToolExecuteResult`|fn||309-326|function buildCompressionToolExecuteResult(|
4514
+ |`buildFindToolSupportedTagGuidelines`|fn||387-391|function buildFindToolSupportedTagGuidelines(): string[]|
4515
+ |`buildFindToolSchemaDescription`|fn||399-404|function buildFindToolSchemaDescription(scope: FindToolSc...|
4516
+ |`buildFindToolPromptGuidelines`|fn||412-428|function buildFindToolPromptGuidelines(scope: FindToolSco...|
4517
+ |`buildFindToolExecuteResult`|fn||437-455|function buildFindToolExecuteResult(|
4518
+ |`deliverPromptCommand`|fn||465-467|async function deliverPromptCommand(pi: ExtensionAPI, con...|
4519
+ |`getPiUsereqStartupTools`|fn||476-481|function getPiUsereqStartupTools(pi: ExtensionAPI): ToolI...|
4520
+ |`getConfiguredEnabledPiUsereqTools`|fn||489-493|function getConfiguredEnabledPiUsereqTools(config: UseReq...|
4521
+ |`getPiUsereqToolKind`|fn||501-506|function getPiUsereqToolKind(tool: ToolInfo): "builtin" |...|
4522
+ |`applyConfiguredPiUsereqTools`|fn||516-533|function applyConfiguredPiUsereqTools(pi: ExtensionAPI, c...|
4523
+ |`handleExtensionStatusEvent`|fn||553-573|async function handleExtensionStatusEvent(|
4524
+ |`registerExtensionStatusHooks`|fn||586-599|function registerExtensionStatusHooks(|
4525
+ |`setConfiguredPiUsereqTools`|fn||609-612|function setConfiguredPiUsereqTools(pi: ExtensionAPI, con...|
4526
+ |`renderPiUsereqToolsReference`|fn||621-649|function renderPiUsereqToolsReference(pi: ExtensionAPI, c...|
4527
+ |`PiNotifyBeepConfigKey`|type||657||
4528
+ |`togglePiNotifyBeepFlag`|fn||669-672|function togglePiNotifyBeepFlag(config: UseReqConfig, key...|
4529
+ |`buildPiNotifyMenuChoices`|fn||681-738|function buildPiNotifyMenuChoices(config: UseReqConfig): ...|
4530
+ |`selectPiNotifySoundLevel`|fn||748-779|async function selectPiNotifySoundLevel(|
4531
+ |`configurePiNotifyMenu`|fn||789-854|async function configurePiNotifyMenu(|
4532
+ |`registerPiNotifyShortcut`|fn||869-889|function registerPiNotifyShortcut(|
4533
+ |`registerPromptCommands`|fn||898-911|function registerPromptCommands(pi: ExtensionAPI): void|
4534
+ |`registerAgentTools`|fn||921-1220|function registerAgentTools(pi: ExtensionAPI): void|
4535
+ |`buildPiUsereqToolsMenuChoices`|fn||1564-1604|function buildPiUsereqToolsMenuChoices(pi: ExtensionAPI, ...|
4536
+ |`buildPiUsereqToolToggleChoices`|fn||1614-1630|function buildPiUsereqToolToggleChoices(pi: ExtensionAPI,...|
4537
+ |`configurePiUsereqToolsMenu`|fn||1641-1692|async function configurePiUsereqToolsMenu(pi: ExtensionAP...|
4538
+ |`formatStaticCheckEntry`|fn||1700-1706|function formatStaticCheckEntry(entry: StaticCheckEntry):...|
4539
+ |`formatStaticCheckLanguagesSummary`|fn||1714-1720|function formatStaticCheckLanguagesSummary(config: UseReq...|
4540
+ |`renderStaticCheckReference`|fn||1728-1749|function renderStaticCheckReference(config: UseReqConfig)...|
4541
+ |`buildStaticCheckMenuChoices`|fn||1758-1793|function buildStaticCheckMenuChoices(config: UseReqConfig...|
4542
+ |`buildSupportedStaticCheckLanguageChoices`|fn||1801-1820|function buildSupportedStaticCheckLanguageChoices(config:...|
4543
+ |`buildStaticCheckModuleChoices`|fn||1828-1845|function buildStaticCheckModuleChoices(language: string):...|
4544
+ |`buildConfiguredStaticCheckLanguageChoices`|fn||1853-1870|function buildConfiguredStaticCheckLanguageChoices(config...|
4545
+ |`configureStaticCheckMenu`|fn||1880-1953|async function configureStaticCheckMenu(ctx: ExtensionCom...|
4546
+ |`buildPiUsereqMenuChoices`|fn||1962-2019|function buildPiUsereqMenuChoices(config: UseReqConfig): ...|
4547
+ |`buildSrcDirMenuChoices`|fn||2028-2049|function buildSrcDirMenuChoices(config: UseReqConfig): Pi...|
4548
+ |`buildSrcDirRemovalChoices`|fn||2058-2073|function buildSrcDirRemovalChoices(config: UseReqConfig):...|
4549
+ |`configurePiUsereq`|fn||2084-2165|async function configurePiUsereq(|
4550
+ |`ensureSaved`|fn||2092-2096|const ensureSaved = () => saveProjectConfig(ctx.cwd, config)|
4551
+ |`refreshStatus`|fn||2093-2096|const refreshStatus = () =>|
4552
+ |`registerConfigCommands`|fn||2175-2185|function registerConfigCommands(|
4553
+ |`piUsereqExtension`|fn||2201-2209|export default function piUsereqExtension(pi: ExtensionAP...|
4554
+