@pugi/cli 0.1.0-beta.99 → 1.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (448) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +11 -191
  3. package/bin/pugi +8 -0
  4. package/package.json +15 -71
  5. package/postinstall.mjs +31 -0
  6. package/CHANGELOG.md +0 -132
  7. package/THIRD_PARTY_NOTICES.md +0 -40
  8. package/assets/pugi-mascot.ansi +0 -16
  9. package/assets/pugi-prozr2-mascot.ansi +0 -9
  10. package/bin/run.js +0 -34
  11. package/dist/commands/deploy.js +0 -439
  12. package/dist/commands/flatten.js +0 -191
  13. package/dist/commands/jobs-watch.js +0 -201
  14. package/dist/commands/jobs.js +0 -260
  15. package/dist/commands/retro.js +0 -210
  16. package/dist/commands/smoke.js +0 -133
  17. package/dist/core/agent-progress/cleanup.js +0 -134
  18. package/dist/core/agent-progress/schema.js +0 -144
  19. package/dist/core/agent-progress/writer.js +0 -101
  20. package/dist/core/agents/adaptive-router.js +0 -330
  21. package/dist/core/agents/loader.js +0 -104
  22. package/dist/core/agents/query-decomposer.js +0 -297
  23. package/dist/core/agents/registry.js +0 -69
  24. package/dist/core/approvals/shortcut-resolver.js +0 -98
  25. package/dist/core/artifact-chain/dispatcher.js +0 -148
  26. package/dist/core/artifact-chain/exporter.js +0 -164
  27. package/dist/core/artifact-chain/state.js +0 -243
  28. package/dist/core/artifact-chain/steps.js +0 -169
  29. package/dist/core/ask-user/question.js +0 -92
  30. package/dist/core/audit/audit-trail.js +0 -275
  31. package/dist/core/auth/ensure-authenticated.js +0 -129
  32. package/dist/core/auth/env-provider.js +0 -238
  33. package/dist/core/auto-open-browser.js +0 -128
  34. package/dist/core/auto-update/channels.js +0 -122
  35. package/dist/core/auto-update/checker.js +0 -241
  36. package/dist/core/auto-update/state.js +0 -235
  37. package/dist/core/bare-mode/index.js +0 -107
  38. package/dist/core/bash/redirect.js +0 -281
  39. package/dist/core/bash-classifier.js +0 -1397
  40. package/dist/core/checkpoint/resumer.js +0 -149
  41. package/dist/core/checkpoint/rewinder.js +0 -291
  42. package/dist/core/checkpoints/shadow-git.js +0 -670
  43. package/dist/core/citations/parser.js +0 -109
  44. package/dist/core/classifier/yolo-classifier.js +0 -88
  45. package/dist/core/clipboard.js +0 -70
  46. package/dist/core/codegraph/decision-store.js +0 -248
  47. package/dist/core/codegraph/detect-repo.js +0 -459
  48. package/dist/core/codegraph/install.js +0 -134
  49. package/dist/core/codegraph/offer-hook.js +0 -220
  50. package/dist/core/compact/auto-trigger.js +0 -96
  51. package/dist/core/compact/buffer-rewriter.js +0 -115
  52. package/dist/core/compact/summarizer.js +0 -208
  53. package/dist/core/compact/token-counter.js +0 -108
  54. package/dist/core/consensus/anvil-fanout.js +0 -276
  55. package/dist/core/consensus/diff-capture.js +0 -491
  56. package/dist/core/consensus/rubric.js +0 -233
  57. package/dist/core/context/builder.js +0 -114
  58. package/dist/core/context/compaction-events.js +0 -99
  59. package/dist/core/context/compaction.js +0 -602
  60. package/dist/core/context/index.js +0 -28
  61. package/dist/core/context/invariants.js +0 -250
  62. package/dist/core/context/markdown-loader.js +0 -288
  63. package/dist/core/context/markdown-traverse.js +0 -255
  64. package/dist/core/context/pugiignore.js +0 -316
  65. package/dist/core/context/repo-skeleton.js +0 -533
  66. package/dist/core/context/tool-eviction.js +0 -55
  67. package/dist/core/context/watcher.js +0 -342
  68. package/dist/core/context/working-set.js +0 -165
  69. package/dist/core/coordinator/agent-tools.js +0 -77
  70. package/dist/core/coordinator/agent-toolset.js +0 -65
  71. package/dist/core/coordinator/fsm.js +0 -73
  72. package/dist/core/coordinator/mode-fsm.js +0 -70
  73. package/dist/core/cost/rate-card.js +0 -129
  74. package/dist/core/cost/tracker.js +0 -221
  75. package/dist/core/credentials.js +0 -355
  76. package/dist/core/cron/scheduler.js +0 -138
  77. package/dist/core/denial-tracking/index.js +0 -8
  78. package/dist/core/denial-tracking/state.js +0 -264
  79. package/dist/core/diagnostics/probe-runner.js +0 -93
  80. package/dist/core/diagnostics/probes/api.js +0 -46
  81. package/dist/core/diagnostics/probes/auth.js +0 -93
  82. package/dist/core/diagnostics/probes/bare-mode.js +0 -42
  83. package/dist/core/diagnostics/probes/cli-version.js +0 -127
  84. package/dist/core/diagnostics/probes/config.js +0 -72
  85. package/dist/core/diagnostics/probes/denial-tracking.js +0 -57
  86. package/dist/core/diagnostics/probes/disk.js +0 -81
  87. package/dist/core/diagnostics/probes/engine-live.js +0 -46
  88. package/dist/core/diagnostics/probes/git.js +0 -65
  89. package/dist/core/diagnostics/probes/hooks.js +0 -118
  90. package/dist/core/diagnostics/probes/mcp.js +0 -75
  91. package/dist/core/diagnostics/probes/node.js +0 -59
  92. package/dist/core/diagnostics/probes/pnpm.js +0 -36
  93. package/dist/core/diagnostics/probes/pugi-md.js +0 -89
  94. package/dist/core/diagnostics/probes/sandbox.js +0 -72
  95. package/dist/core/diagnostics/probes/session.js +0 -74
  96. package/dist/core/diagnostics/probes/status-snapshot.js +0 -488
  97. package/dist/core/diagnostics/probes/workspace.js +0 -63
  98. package/dist/core/diagnostics/types.js +0 -70
  99. package/dist/core/dispatch/cache-cleanup.js +0 -197
  100. package/dist/core/dispatch/cache-handoff.js +0 -295
  101. package/dist/core/edits/apply-patch-layer-e.js +0 -189
  102. package/dist/core/edits/dispatch.js +0 -511
  103. package/dist/core/edits/format-detector.js +0 -260
  104. package/dist/core/edits/format-matrix.js +0 -26
  105. package/dist/core/edits/fuzzy-ladder.js +0 -650
  106. package/dist/core/edits/index.js +0 -19
  107. package/dist/core/edits/journal.js +0 -199
  108. package/dist/core/edits/layer-a-apply.js +0 -217
  109. package/dist/core/edits/layer-a-fuzzy-apply.js +0 -198
  110. package/dist/core/edits/layer-b-apply.js +0 -211
  111. package/dist/core/edits/layer-c-apply.js +0 -160
  112. package/dist/core/edits/layer-d-ast.js +0 -572
  113. package/dist/core/edits/marker-parser.js +0 -401
  114. package/dist/core/edits/security-gate.js +0 -223
  115. package/dist/core/edits/verify-hook.js +0 -273
  116. package/dist/core/edits/worktree.js +0 -322
  117. package/dist/core/engine/adapter-runner.js +0 -8
  118. package/dist/core/engine/anvil-client.js +0 -344
  119. package/dist/core/engine/auto-compact.js +0 -179
  120. package/dist/core/engine/budgets.js +0 -195
  121. package/dist/core/engine/context-prefix.js +0 -155
  122. package/dist/core/engine/index.js +0 -12
  123. package/dist/core/engine/intensity.js +0 -163
  124. package/dist/core/engine/intent.js +0 -260
  125. package/dist/core/engine/native-pugi.js +0 -1616
  126. package/dist/core/engine/noop.js +0 -27
  127. package/dist/core/engine/prompts.js +0 -236
  128. package/dist/core/engine/strip-internal-fields.js +0 -124
  129. package/dist/core/engine/tool-bridge.js +0 -2173
  130. package/dist/core/engine/verification-patterns.js +0 -195
  131. package/dist/core/evaluation/golden-dataset.js +0 -293
  132. package/dist/core/feedback/queue.js +0 -177
  133. package/dist/core/feedback/submitter.js +0 -145
  134. package/dist/core/file-cache.js +0 -141
  135. package/dist/core/flatten/flatten-repo.js +0 -439
  136. package/dist/core/format/osc8-link.js +0 -28
  137. package/dist/core/hook-chains.js +0 -392
  138. package/dist/core/hooks/citation-verify-hook.js +0 -138
  139. package/dist/core/hooks/citation-verify.js +0 -112
  140. package/dist/core/hooks/events.js +0 -46
  141. package/dist/core/hooks/index.js +0 -15
  142. package/dist/core/hooks/registry.js +0 -216
  143. package/dist/core/hooks/runner.js +0 -236
  144. package/dist/core/hooks/v2/event-emitter.js +0 -115
  145. package/dist/core/hooks/v2/executor.js +0 -282
  146. package/dist/core/hooks/v2/index.js +0 -25
  147. package/dist/core/hooks/v2/lifecycle.js +0 -104
  148. package/dist/core/hooks/v2/loader.js +0 -216
  149. package/dist/core/hooks/v2/matcher.js +0 -125
  150. package/dist/core/hooks/v2/trust.js +0 -143
  151. package/dist/core/hooks/v2/types.js +0 -86
  152. package/dist/core/hooks/worktree-events.js +0 -158
  153. package/dist/core/hooks.js +0 -415
  154. package/dist/core/image/renderer.js +0 -71
  155. package/dist/core/index-store.js +0 -260
  156. package/dist/core/init/detector.js +0 -582
  157. package/dist/core/init/template-renderer.js +0 -242
  158. package/dist/core/jobs/registry.js +0 -462
  159. package/dist/core/ledger/results-tsv.js +0 -142
  160. package/dist/core/log-discipline/stdout-redirect.js +0 -51
  161. package/dist/core/lsp/cache.js +0 -105
  162. package/dist/core/lsp/client.js +0 -1229
  163. package/dist/core/lsp/language-detect.js +0 -66
  164. package/dist/core/lsp/post-edit-diagnostics.js +0 -171
  165. package/dist/core/lsp/server-detect.js +0 -173
  166. package/dist/core/lsp/symbol-cache.js +0 -162
  167. package/dist/core/lsp/symbol-tools.js +0 -664
  168. package/dist/core/mcp/client.js +0 -385
  169. package/dist/core/mcp/http-server.js +0 -553
  170. package/dist/core/mcp/orchestrator-config.js +0 -192
  171. package/dist/core/mcp/orchestrator-tools.js +0 -806
  172. package/dist/core/mcp/permission.js +0 -190
  173. package/dist/core/mcp/registry.js +0 -193
  174. package/dist/core/mcp/server-tools.js +0 -219
  175. package/dist/core/mcp/server.js +0 -397
  176. package/dist/core/mcp/trust.js +0 -91
  177. package/dist/core/memory/dual-write.js +0 -416
  178. package/dist/core/memory/passive-extract.js +0 -130
  179. package/dist/core/memory/phase1-kinds.js +0 -20
  180. package/dist/core/memory/secret-scanner.js +0 -304
  181. package/dist/core/memory-sync/queue.js +0 -170
  182. package/dist/core/metrics/extract.js +0 -113
  183. package/dist/core/modes/roo-modes.js +0 -68
  184. package/dist/core/onboarding/ensure-initialized.js +0 -133
  185. package/dist/core/onboarding/marker.js +0 -111
  186. package/dist/core/onboarding/telemetry-state.js +0 -108
  187. package/dist/core/output-style/presets.js +0 -176
  188. package/dist/core/output-style/state.js +0 -185
  189. package/dist/core/path-security.js +0 -345
  190. package/dist/core/permission.js +0 -369
  191. package/dist/core/permissions/auto-classifier.js +0 -124
  192. package/dist/core/permissions/bash-parser.js +0 -371
  193. package/dist/core/permissions/circuit-breaker.js +0 -83
  194. package/dist/core/permissions/constrained-edit.js +0 -91
  195. package/dist/core/permissions/gate.js +0 -278
  196. package/dist/core/permissions/index.js +0 -20
  197. package/dist/core/permissions/mode.js +0 -174
  198. package/dist/core/permissions/network-egress.js +0 -137
  199. package/dist/core/permissions/state.js +0 -241
  200. package/dist/core/permissions/tool-class.js +0 -107
  201. package/dist/core/plan-mode/ui-state.js +0 -51
  202. package/dist/core/plans/plan-artifact.js +0 -721
  203. package/dist/core/policy-limits/etag-store.js +0 -122
  204. package/dist/core/prd-check/parser.js +0 -215
  205. package/dist/core/prd-check/reporter.js +0 -127
  206. package/dist/core/prd-check/session-review.js +0 -557
  207. package/dist/core/prd-check/verifiers.js +0 -223
  208. package/dist/core/prompt-cache/client-cache.js +0 -99
  209. package/dist/core/prompts/assembly.js +0 -29
  210. package/dist/core/prompts/registry.js +0 -364
  211. package/dist/core/pugi-gitignore.js +0 -52
  212. package/dist/core/pugi-md/cc-compat-rules.js +0 -735
  213. package/dist/core/pugi-md/context-injector.js +0 -76
  214. package/dist/core/pugi-md/walk-up.js +0 -207
  215. package/dist/core/python/uv-installer.js +0 -270
  216. package/dist/core/python/uv-resolver.js +0 -83
  217. package/dist/core/rate-limit/narrator.js +0 -146
  218. package/dist/core/recipes/cli-types.js +0 -20
  219. package/dist/core/recipes/loader.js +0 -103
  220. package/dist/core/recipes/runner.js +0 -345
  221. package/dist/core/recipes/schema.js +0 -587
  222. package/dist/core/release-notes/parser.js +0 -241
  223. package/dist/core/release-notes/state.js +0 -116
  224. package/dist/core/repl/ask.js +0 -512
  225. package/dist/core/repl/cancellation.js +0 -98
  226. package/dist/core/repl/cap-warning.js +0 -91
  227. package/dist/core/repl/clipboard-read.js +0 -174
  228. package/dist/core/repl/dispatch-fsm.js +0 -220
  229. package/dist/core/repl/engine-bridge.js +0 -303
  230. package/dist/core/repl/history-search.js +0 -175
  231. package/dist/core/repl/history.js +0 -182
  232. package/dist/core/repl/kill-ring.js +0 -138
  233. package/dist/core/repl/model-pricing.js +0 -135
  234. package/dist/core/repl/privacy-banner.js +0 -71
  235. package/dist/core/repl/session.js +0 -4962
  236. package/dist/core/repl/slash-commands.js +0 -747
  237. package/dist/core/repl/store/index.js +0 -12
  238. package/dist/core/repl/store/jsonl-log.js +0 -321
  239. package/dist/core/repl/store/lockfile.js +0 -155
  240. package/dist/core/repl/store/session-store.js +0 -821
  241. package/dist/core/repl/store/types.js +0 -44
  242. package/dist/core/repl/store/uuid-v7.js +0 -68
  243. package/dist/core/repl/tool-route.js +0 -382
  244. package/dist/core/repl/workspace-context.js +0 -206
  245. package/dist/core/repo-map/build.js +0 -125
  246. package/dist/core/repo-map/cache.js +0 -185
  247. package/dist/core/repo-map/extractor.js +0 -254
  248. package/dist/core/repo-map/formatter.js +0 -145
  249. package/dist/core/repo-map/page-rank.js +0 -105
  250. package/dist/core/repo-map/scanner.js +0 -211
  251. package/dist/core/retro/git-collector.js +0 -251
  252. package/dist/core/retro/health-card.js +0 -25
  253. package/dist/core/retro/metrics.js +0 -342
  254. package/dist/core/retro/narrative.js +0 -249
  255. package/dist/core/retro/plane-collector.js +0 -274
  256. package/dist/core/retro/pr-issue-link.js +0 -65
  257. package/dist/core/retro/types.js +0 -16
  258. package/dist/core/retry-budget/budget.js +0 -284
  259. package/dist/core/retry-budget/index.js +0 -5
  260. package/dist/core/retry-budget/retry-cap.js +0 -74
  261. package/dist/core/routing/lead-worker.js +0 -43
  262. package/dist/core/routing/pre-flight-estimator.js +0 -108
  263. package/dist/core/runs/run-tree.js +0 -103
  264. package/dist/core/sandboxing/adapter.js +0 -29
  265. package/dist/core/sandboxing/index.js +0 -49
  266. package/dist/core/sandboxing/none.js +0 -19
  267. package/dist/core/sandboxing/seatbelt.js +0 -183
  268. package/dist/core/security/injection-scanner.js +0 -367
  269. package/dist/core/security/output-filter.js +0 -418
  270. package/dist/core/session/env-file.js +0 -105
  271. package/dist/core/session/section-budgets.js +0 -140
  272. package/dist/core/session.js +0 -377
  273. package/dist/core/settings.js +0 -400
  274. package/dist/core/share/formatter.js +0 -271
  275. package/dist/core/share/redactor.js +0 -221
  276. package/dist/core/share/uploader.js +0 -267
  277. package/dist/core/skills/defaults.js +0 -457
  278. package/dist/core/skills/loader.js +0 -454
  279. package/dist/core/skills/sources.js +0 -480
  280. package/dist/core/skills/trust.js +0 -172
  281. package/dist/core/smoke/headless-driver.js +0 -174
  282. package/dist/core/smoke/orchestrator.js +0 -194
  283. package/dist/core/smoke/runner.js +0 -238
  284. package/dist/core/smoke/scenario-parser.js +0 -316
  285. package/dist/core/statusline.js +0 -99
  286. package/dist/core/subagents/dispatcher-real.js +0 -600
  287. package/dist/core/subagents/dispatcher.js +0 -352
  288. package/dist/core/subagents/index.js +0 -39
  289. package/dist/core/subagents/isolation-matrix.js +0 -213
  290. package/dist/core/subagents/spawn.js +0 -101
  291. package/dist/core/telemetry/emitter.js +0 -229
  292. package/dist/core/telemetry/queue.js +0 -251
  293. package/dist/core/theme/context.js +0 -91
  294. package/dist/core/theme/presets.js +0 -228
  295. package/dist/core/theme/state.js +0 -181
  296. package/dist/core/todos/invariant.js +0 -10
  297. package/dist/core/todos/state.js +0 -177
  298. package/dist/core/tool-schema/compressor.js +0 -89
  299. package/dist/core/transport/version-interceptor.js +0 -166
  300. package/dist/core/trust.js +0 -109
  301. package/dist/core/tui/thinking-block.js +0 -64
  302. package/dist/core/vim/keymap.js +0 -288
  303. package/dist/core/vim/state.js +0 -92
  304. package/dist/core/watch-markers/marker-watcher.js +0 -133
  305. package/dist/core/worktree/include-parser.js +0 -249
  306. package/dist/core/worktree-manager/cleanup.js +0 -123
  307. package/dist/core/worktree-manager/manager.js +0 -303
  308. package/dist/index.js +0 -44
  309. package/dist/runtime/bootstrap.js +0 -190
  310. package/dist/runtime/cli.js +0 -8121
  311. package/dist/runtime/commands/agents.js +0 -385
  312. package/dist/runtime/commands/budget.js +0 -192
  313. package/dist/runtime/commands/cancel.js +0 -231
  314. package/dist/runtime/commands/chain.js +0 -489
  315. package/dist/runtime/commands/codegraph-status.js +0 -227
  316. package/dist/runtime/commands/compact.js +0 -297
  317. package/dist/runtime/commands/config.js +0 -595
  318. package/dist/runtime/commands/cost.js +0 -199
  319. package/dist/runtime/commands/delegate.js +0 -312
  320. package/dist/runtime/commands/dispatch.js +0 -126
  321. package/dist/runtime/commands/doctor.js +0 -579
  322. package/dist/runtime/commands/feedback.js +0 -184
  323. package/dist/runtime/commands/hooks.js +0 -187
  324. package/dist/runtime/commands/init.js +0 -254
  325. package/dist/runtime/commands/lsp.js +0 -368
  326. package/dist/runtime/commands/mcp.js +0 -935
  327. package/dist/runtime/commands/memory.js +0 -582
  328. package/dist/runtime/commands/model.js +0 -237
  329. package/dist/runtime/commands/onboarding.js +0 -275
  330. package/dist/runtime/commands/patch.js +0 -128
  331. package/dist/runtime/commands/permissions.js +0 -112
  332. package/dist/runtime/commands/plan.js +0 -143
  333. package/dist/runtime/commands/prd-check.js +0 -285
  334. package/dist/runtime/commands/privacy.js +0 -107
  335. package/dist/runtime/commands/recipe.js +0 -325
  336. package/dist/runtime/commands/redo-blob-store.js +0 -92
  337. package/dist/runtime/commands/redo.js +0 -361
  338. package/dist/runtime/commands/release-notes.js +0 -229
  339. package/dist/runtime/commands/repo-map.js +0 -95
  340. package/dist/runtime/commands/report.js +0 -299
  341. package/dist/runtime/commands/resume.js +0 -118
  342. package/dist/runtime/commands/review-consensus.js +0 -414
  343. package/dist/runtime/commands/rewind.js +0 -333
  344. package/dist/runtime/commands/roster.js +0 -117
  345. package/dist/runtime/commands/sessions.js +0 -163
  346. package/dist/runtime/commands/share.js +0 -316
  347. package/dist/runtime/commands/skills.js +0 -401
  348. package/dist/runtime/commands/status.js +0 -186
  349. package/dist/runtime/commands/stickers.js +0 -82
  350. package/dist/runtime/commands/style.js +0 -194
  351. package/dist/runtime/commands/theme.js +0 -196
  352. package/dist/runtime/commands/undo.js +0 -361
  353. package/dist/runtime/commands/update.js +0 -289
  354. package/dist/runtime/commands/vim.js +0 -140
  355. package/dist/runtime/commands/worktree.js +0 -177
  356. package/dist/runtime/commands/worktrees.js +0 -155
  357. package/dist/runtime/deprecation-warning.js +0 -69
  358. package/dist/runtime/engine-exit-code.js +0 -50
  359. package/dist/runtime/headless-repl.js +0 -195
  360. package/dist/runtime/headless.js +0 -548
  361. package/dist/runtime/load-hooks-or-exit.js +0 -71
  362. package/dist/runtime/plan-decompose.js +0 -531
  363. package/dist/runtime/sigint-guard.js +0 -272
  364. package/dist/runtime/stream-renderer.js +0 -195
  365. package/dist/runtime/update-check.js +0 -294
  366. package/dist/runtime/version.js +0 -65
  367. package/dist/runtime/worktree-bootstrap.js +0 -579
  368. package/dist/skills/bundled/batch.js +0 -617
  369. package/dist/skills/bundled/index.js +0 -45
  370. package/dist/skills/bundled/loop.js +0 -358
  371. package/dist/skills/bundled/remember.js +0 -383
  372. package/dist/skills/bundled/simplify.js +0 -289
  373. package/dist/skills/bundled/skillify.js +0 -373
  374. package/dist/skills/bundled/stuck.js +0 -558
  375. package/dist/skills/bundled/verify.js +0 -439
  376. package/dist/testing/vcr.js +0 -486
  377. package/dist/tools/agent-tool.js +0 -229
  378. package/dist/tools/apply-patch.js +0 -556
  379. package/dist/tools/ask-user-question.js +0 -337
  380. package/dist/tools/ask-user.js +0 -115
  381. package/dist/tools/bash.js +0 -1238
  382. package/dist/tools/brief.js +0 -224
  383. package/dist/tools/cron.js +0 -433
  384. package/dist/tools/enter-worktree.js +0 -250
  385. package/dist/tools/exit-worktree.js +0 -147
  386. package/dist/tools/file-tools.js +0 -553
  387. package/dist/tools/http-request.js +0 -336
  388. package/dist/tools/lsp-tools.js +0 -565
  389. package/dist/tools/mcp-tool.js +0 -260
  390. package/dist/tools/multi-edit.js +0 -361
  391. package/dist/tools/powershell.js +0 -268
  392. package/dist/tools/registry.js +0 -166
  393. package/dist/tools/server-tools.js +0 -892
  394. package/dist/tools/skill-tool.js +0 -96
  395. package/dist/tools/sleep.js +0 -99
  396. package/dist/tools/synthetic-output.js +0 -133
  397. package/dist/tools/tasks.js +0 -208
  398. package/dist/tools/todo-write.js +0 -184
  399. package/dist/tools/verify-plan-execution.js +0 -295
  400. package/dist/tools/web-fetch-injection-scanner.js +0 -207
  401. package/dist/tools/web-fetch.js +0 -720
  402. package/dist/tools/web-search.js +0 -458
  403. package/dist/tui/agent-progress-card.js +0 -111
  404. package/dist/tui/agent-tree-pane.js +0 -9
  405. package/dist/tui/agent-tree.js +0 -87
  406. package/dist/tui/ask-cli.js +0 -52
  407. package/dist/tui/ask-modal.js +0 -211
  408. package/dist/tui/ask-user-question-chips.js +0 -315
  409. package/dist/tui/ask-user-question-prompt.js +0 -203
  410. package/dist/tui/compact-banner.js +0 -81
  411. package/dist/tui/conversation-pane.js +0 -164
  412. package/dist/tui/cost-table.js +0 -111
  413. package/dist/tui/device-flow.js +0 -142
  414. package/dist/tui/doctor-table.js +0 -46
  415. package/dist/tui/feedback-prompt.js +0 -156
  416. package/dist/tui/input-box.js +0 -732
  417. package/dist/tui/login-picker.js +0 -69
  418. package/dist/tui/markdown-render.js +0 -266
  419. package/dist/tui/multi-file-diff-approval.js +0 -375
  420. package/dist/tui/onboarding-wizard.js +0 -240
  421. package/dist/tui/permissions-picker.js +0 -86
  422. package/dist/tui/render.js +0 -160
  423. package/dist/tui/repl-render.js +0 -770
  424. package/dist/tui/repl-splash-art.js +0 -64
  425. package/dist/tui/repl-splash-mascot.js +0 -154
  426. package/dist/tui/repl-splash.js +0 -117
  427. package/dist/tui/repl.js +0 -378
  428. package/dist/tui/slash-palette.js +0 -106
  429. package/dist/tui/splash-data.js +0 -61
  430. package/dist/tui/splash.js +0 -31
  431. package/dist/tui/status-bar.js +0 -209
  432. package/dist/tui/status-table.js +0 -7
  433. package/dist/tui/stickers-art.js +0 -136
  434. package/dist/tui/style-table.js +0 -28
  435. package/dist/tui/theme-table.js +0 -29
  436. package/dist/tui/thinking-spinner.js +0 -123
  437. package/dist/tui/tool-stream-pane.js +0 -140
  438. package/dist/tui/update-banner.js +0 -33
  439. package/dist/tui/vim-input.js +0 -267
  440. package/dist/tui/welcome-banner.js +0 -107
  441. package/dist/tui/welcome-data.js +0 -293
  442. package/dist/tui/workspace-context.js +0 -105
  443. package/docs/examples/codegraph.mcp.json +0 -10
  444. package/test/scenarios/codegen-create-file.scenario.txt +0 -13
  445. package/test/scenarios/compact-force.scenario.txt +0 -12
  446. package/test/scenarios/identity.scenario.txt +0 -11
  447. package/test/scenarios/persona-handoff.scenario.txt +0 -12
  448. package/test/scenarios/walkback.scenario.txt +0 -12
@@ -1,228 +0,0 @@
1
- /**
2
- * — TUI color theme presets.
3
- *
4
- * Sibling to `core/output-style/presets.ts` but addressing a different
5
- * layer of the operator surface:
6
- *
7
- * - `output-style` steers the engine's PROSE register (terse /
8
- * explanatory / russian-formal / casual). It compiles into a rule
9
- * block appended to the system prompt; the model adjusts voice.
10
- *
11
- * - `theme` steers the LOCAL TUI's color palette. It never reaches
12
- * the engine; only the Ink components in `tui/*.tsx` read it. The
13
- * operator can run any output-style under any theme — the two
14
- * surfaces are orthogonal.
15
- *
16
- * Design contract:
17
- *
18
- * - The catalogue is a closed set of 4 entries — `default`, `dark`,
19
- * `light`, `colorblind`. The slug union is intentionally tight so
20
- * the operator can hold the full surface in working memory and so
21
- * Ink consumers can switch on every slug without a fall-through.
22
- *
23
- * - Each preset defines 7 semantic color tokens (foreground, muted,
24
- * accent, success, warning, error, background). Ink components
25
- * reference these tokens via `useTheme()` instead of inlining
26
- * literal hex codes. The brand accent `#3da9fc` is preserved in
27
- * `default` so the existing header / splash chrome reads
28
- * identically when no override is active.
29
- *
30
- * - `colorblind` is tuned for deuteranopia (red-green color
31
- * blindness, ~5% of male population). Status colors are mapped to
32
- * a blue-yellow axis (`success` cyan, `warning` yellow, `error`
33
- * bright-magenta) so the OK/WARN/ERROR triplet remains
34
- * distinguishable without red/green discrimination. The accent is
35
- * also shifted to bright-yellow `#ffd166` so it does not collide
36
- * with the success cue.
37
- *
38
- * - `light` uses darker foreground + lighter accent values so the
39
- * palette reads on a white terminal background. Most operators
40
- * run dark terminals, so `dark` is closer to the default;
41
- * `light` exists specifically for screen-share / projector demos
42
- * where the room is bright.
43
- *
44
- * - All color values are 6-digit hex strings prefixed with `#`. Ink's
45
- * `Text color` prop accepts hex strings directly; we deliberately
46
- * do NOT use named colors like `green` / `red` so the palette is
47
- * fully under operator control. The Ink-named fallback for OK/
48
- * WARN/ERROR exists separately in `doctor-table.tsx` legacy code
49
- * and gets superseded once the theme context is wired.
50
- *
51
- * Test surface: `test/commands/theme-presets.spec.ts` exercises
52
- * catalogue invariants (4 entries, unique slugs, every preset has all
53
- * 7 tokens, hex format, colorblind palette avoids red-green for
54
- * status), the `isThemeSlug` predicate, and the `compileSampleRow`
55
- * helper used by the preview table.
56
- */
57
- /**
58
- * The closed list of theme slugs in catalogue order. Mirror used by
59
- * the CLI surface (`/theme` table, `pugi theme --list`) so the
60
- * operator sees themes in a stable order regardless of iteration
61
- * order of the keyed catalogue.
62
- */
63
- export const THEME_SLUGS = Object.freeze([
64
- 'default',
65
- 'dark',
66
- 'light',
67
- 'colorblind',
68
- ]);
69
- /**
70
- * Default slug used when no workspace-/user-level preference is set.
71
- * Exported so `state.ts` and the CLI handler share one constant.
72
- */
73
- export const DEFAULT_THEME = 'default';
74
- /**
75
- * Catalogue keyed by slug. Frozen so callers cannot mutate the
76
- * shared rows; the CLI handler returns slugs, not preset references,
77
- * to keep the boundary clean.
78
- *
79
- * Color choices:
80
- *
81
- * - `default` accent `#3da9fc` is the existing Pugi blue baked into
82
- * `repl.tsx` header + `/help` palette. Preserved verbatim so the
83
- * default theme reads identically to pre-L30 chrome.
84
- *
85
- * - `dark` saturates the brand palette for deep-black terminals
86
- * (true-black iTerm, kitty, alacritty). Accent cyan `#22d3ee`
87
- * pops against `#0a0a0a`; foreground is a near-white `#f5f5f5`
88
- * that does not glare.
89
- *
90
- * - `light` inverts the contrast: foreground is `#1a1a1a` (near-
91
- * black), background `#fafafa` (off-white), accent `#1e40af`
92
- * (deep blue, readable on white). Status colors are darkened
93
- * equivalents — `#15803d` green, `#a16207` amber, `#b91c1c`
94
- * deep-red — so they retain saturation on bright backgrounds.
95
- *
96
- * - `colorblind` shifts the status axis from red-green to
97
- * blue-yellow. `#0ea5e9` cyan replaces green, `#facc15` yellow
98
- * stays warning, `#d946ef` magenta replaces red. The
99
- * deuteranopia community can distinguish blue from yellow from
100
- * magenta even when red/green collapse. Accent moves to
101
- * `#ffd166` bright-yellow so it does not collide with success
102
- * cyan; we trade brand consistency for accessibility here, which
103
- * is the explicit purpose of the preset.
104
- */
105
- export const THEMES = Object.freeze({
106
- default: Object.freeze({
107
- slug: 'default',
108
- title: 'Default',
109
- gloss: 'Current Pugi palette — blue accent on dark terminal.',
110
- colors: Object.freeze({
111
- foreground: '#e5e7eb',
112
- background: '#0f172a',
113
- muted: '#94a3b8',
114
- accent: '#3da9fc',
115
- success: '#22c55e',
116
- warning: '#eab308',
117
- error: '#ef4444',
118
- }),
119
- }),
120
- dark: Object.freeze({
121
- slug: 'dark',
122
- title: 'Dark',
123
- gloss: 'Saturated palette for deep-black terminals (iTerm, alacritty, kitty).',
124
- colors: Object.freeze({
125
- foreground: '#f5f5f5',
126
- background: '#0a0a0a',
127
- muted: '#737373',
128
- accent: '#22d3ee',
129
- success: '#4ade80',
130
- warning: '#fbbf24',
131
- error: '#f87171',
132
- }),
133
- }),
134
- light: Object.freeze({
135
- slug: 'light',
136
- title: 'Light',
137
- gloss: 'Inverted palette for projector demos + white-background terminals.',
138
- colors: Object.freeze({
139
- foreground: '#1a1a1a',
140
- background: '#fafafa',
141
- muted: '#525252',
142
- accent: '#1e40af',
143
- success: '#15803d',
144
- warning: '#a16207',
145
- error: '#b91c1c',
146
- }),
147
- }),
148
- colorblind: Object.freeze({
149
- slug: 'colorblind',
150
- title: 'Colorblind',
151
- gloss: 'High-contrast deuteranopia-safe — status on blue-yellow-magenta axis.',
152
- colors: Object.freeze({
153
- foreground: '#f5f5f5',
154
- background: '#0f172a',
155
- muted: '#9ca3af',
156
- accent: '#ffd166',
157
- success: '#0ea5e9',
158
- warning: '#facc15',
159
- error: '#d946ef',
160
- }),
161
- }),
162
- });
163
- /**
164
- * Type-narrowing predicate. Used by the slash-command parser + state
165
- * loader so an unknown string from operator input or a stale config
166
- * file degrades to the default theme instead of crashing.
167
- */
168
- export function isThemeSlug(value) {
169
- return (typeof value === 'string' && THEME_SLUGS.includes(value));
170
- }
171
- /**
172
- * Resolve the colors for a slug. Pure lookup; never throws. Callers
173
- * pass the slug from `resolveTheme()` so unknown values cannot reach
174
- * this helper, but defensive isThemeSlug + DEFAULT_THEME fallback is
175
- * still applied so future refactors cannot regress to a runtime
176
- * crash on a stale config.
177
- */
178
- export function getThemeColors(slug) {
179
- const preset = THEMES[slug] ?? THEMES[DEFAULT_THEME];
180
- return preset.colors;
181
- }
182
- /**
183
- * Render the theme catalogue as a plain-text table for the `/theme`
184
- * + `pugi theme` surfaces. Marks the active slug with `*` so the
185
- * operator can see at a glance which theme is in effect.
186
- *
187
- * Pure renderer (no fs, no env). Identical text is emitted from both
188
- * the slash dispatcher and the top-level CLI command so operators
189
- * trained on one surface read the same table on the other.
190
- *
191
- * The plain-text variant skips the color-sample preview row — Ink's
192
- * `<ThemeTable>` in `tui/theme-table.tsx` renders the sample row
193
- * inline using `Text color={preset.colors.accent}` so the operator
194
- * can preview each palette before switching.
195
- */
196
- export function renderThemeTable(active) {
197
- const slugWidth = Math.max('NAME'.length, ...THEME_SLUGS.map((slug) => slug.length));
198
- const header = `${'NAME'.padEnd(slugWidth)} GLOSS`;
199
- const rows = THEME_SLUGS.map((slug) => {
200
- const preset = THEMES[slug];
201
- const marker = slug === active ? '*' : ' ';
202
- return `${marker} ${slug.padEnd(slugWidth)} ${preset.gloss}`;
203
- });
204
- return [header, ...rows].join('\n');
205
- }
206
- /**
207
- * Build the per-row sample text used by `<ThemeTable>`. Pure helper
208
- * so the spec can assert the canonical sample copy ("Aa 123 OK WARN
209
- * ERROR") without mounting Ink. The TUI component colors each
210
- * fragment with the matching token (`foreground`, `accent`, `success`,
211
- * `warning`, `error`) — this helper only returns the source strings
212
- * the renderer splices in.
213
- */
214
- export function compileSampleRow(slug) {
215
- // The strings are slug-independent today; the helper exists so
216
- // future presets can ship per-theme sample copy (e.g. localised
217
- // OK/ERROR labels for a future `russian-tui` preset) without
218
- // touching the consumer Ink component.
219
- void slug;
220
- return Object.freeze({
221
- foreground: 'Aa',
222
- accent: '123',
223
- success: 'OK',
224
- warning: 'WARN',
225
- error: 'ERROR',
226
- });
227
- }
228
- //# sourceMappingURL=presets.js.map
@@ -1,181 +0,0 @@
1
- /**
2
- * — Theme state persistence.
3
- *
4
- * Mirror of `core/output-style/state.ts` — same two-tier ladder
5
- * (workspace > user > default), same `~/.pugi/config.json` envelope,
6
- * same malformed-config tolerance. The two modules write to disjoint
7
- * keys (`outputStyle` vs `theme`) of the same JSON file so neighbour
8
- * settings (`permissionMode`, `privacy`, `model`, `outputStyle`)
9
- * survive a theme flip.
10
- *
11
- * Two-tier storage:
12
- *
13
- * 1. **Workspace** — `<workspaceRoot>/.pugi/config.json`. Set by
14
- * `/theme <name>` or `pugi theme <name>` without `--persist`.
15
- * Overrides the user default for the current workspace only.
16
- *
17
- * 2. **User default** — `~/.pugi/config.json` (PUGI_HOME-aware).
18
- * Set by `pugi theme <name> --persist` or `/theme <name>
19
- * --persist`. Applies to every workspace that has no
20
- * workspace-level override.
21
- *
22
- * Precedence (highest → lowest):
23
- *
24
- * workspace value > user value > DEFAULT_THEME ('default')
25
- *
26
- * The reader tolerates:
27
- * - missing file (returns the default slug),
28
- * - empty file (returns the default slug),
29
- * - malformed JSON (returns the default slug — DO NOT crash REPL
30
- * boot because of a hand-edited config),
31
- * - unknown slug (returns the default slug + emits no error; the
32
- * operator can `/theme` to see the table and re-set).
33
- *
34
- * The writer is a read-modify-write to preserve neighbouring keys
35
- * (`outputStyle`, `permissionMode`, etc.) — overwriting the whole
36
- * file would clobber the other tier's settings AND any sibling
37
- * module's slot in the same envelope.
38
- *
39
- * Test surface: `test/commands/theme-state.spec.ts` exercises
40
- * precedence, malformed-config tolerance, persistence across reads,
41
- * the `--persist` (user-default) path, reset semantics, and the
42
- * coexistence contract with `outputStyle` in the same file.
43
- */
44
- import { existsSync, mkdirSync, readFileSync, writeFileSync, } from 'node:fs';
45
- import { homedir } from 'node:os';
46
- import { dirname, resolve } from 'node:path';
47
- import { DEFAULT_THEME, isThemeSlug } from './presets.js';
48
- /**
49
- * Env override for `~/.pugi` so the spec can sandbox both tiers
50
- * without touching the developer's real config. Re-exported under a
51
- * theme-specific alias so consumers in this module do not need to
52
- * import the output-style constant; the underlying env key is shared
53
- * (`PUGI_HOME`) because the two modules write to the same config
54
- * envelope.
55
- */
56
- export const PUGI_HOME_ENV = 'PUGI_HOME';
57
- /**
58
- * Resolve the active theme for the workspace, applying the
59
- * precedence ladder (workspace > user > default).
60
- *
61
- * Pure read. Never writes, never throws — every IO failure degrades
62
- * to the default slug. The function returns the source label too so
63
- * the CLI surface can show the operator where the value came from.
64
- */
65
- export function resolveTheme(io) {
66
- const workspaceSlug = readSlugFromFile(workspaceConfigPath(io.workspaceRoot));
67
- if (workspaceSlug)
68
- return { slug: workspaceSlug, source: 'workspace' };
69
- const userSlug = readSlugFromFile(userConfigPath(io.env ?? process.env));
70
- if (userSlug)
71
- return { slug: userSlug, source: 'user' };
72
- return { slug: DEFAULT_THEME, source: 'default' };
73
- }
74
- /**
75
- * Write `slug` to the workspace tier. Creates `<workspaceRoot>/.pugi/`
76
- * if missing. Preserves neighbouring config keys via read-modify-write.
77
- */
78
- export function setWorkspaceTheme(slug, io) {
79
- writeSlugToFile(workspaceConfigPath(io.workspaceRoot), slug);
80
- }
81
- /**
82
- * Write `slug` to the user tier (`~/.pugi/config.json`).
83
- *
84
- * Mirrors the workspace writer's read-modify-write so the user's
85
- * `outputStyle` / `permissionMode` / `privacy` / `model` keys survive
86
- * a theme flip.
87
- */
88
- export function setUserTheme(slug, io) {
89
- writeSlugToFile(userConfigPath(io.env ?? process.env), slug);
90
- }
91
- /**
92
- * Clear the workspace tier's `theme` key. The user tier (and
93
- * therefore the eventual resolved theme) is left untouched.
94
- *
95
- * Used by `/theme --reset` so the operator can revert a workspace
96
- * override without nuking the rest of their workspace config (or the
97
- * user default).
98
- */
99
- export function clearWorkspaceTheme(io) {
100
- clearSlugInFile(workspaceConfigPath(io.workspaceRoot));
101
- }
102
- /**
103
- * Clear the user tier's `theme` key. Lower-blast-radius reset for
104
- * operators who want every workspace to fall back to `default` unless
105
- * an explicit workspace value is set.
106
- */
107
- export function clearUserTheme(io) {
108
- clearSlugInFile(userConfigPath(io.env ?? process.env));
109
- }
110
- /**
111
- * Workspace config path. Exported for the spec; production callers
112
- * should use the `setWorkspace…` / `resolveTheme` helpers.
113
- */
114
- export function workspaceConfigPath(workspaceRoot) {
115
- return resolve(workspaceRoot, '.pugi', 'config.json');
116
- }
117
- /**
118
- * User config path resolved against `PUGI_HOME` (or `~/.pugi`).
119
- * Exported for the spec.
120
- */
121
- export function userConfigPath(env = process.env) {
122
- const home = env[PUGI_HOME_ENV] ?? resolve(homedir(), '.pugi');
123
- return resolve(home, 'config.json');
124
- }
125
- /**
126
- * Read + parse a config file. Returns an empty object on any IO or
127
- * parse error. Caller-provided JSON must be a plain object; arrays /
128
- * scalars / null are treated as "no config" so a hand-edited file
129
- * never crashes the REPL.
130
- */
131
- function readConfigFile(path) {
132
- if (!existsSync(path))
133
- return {};
134
- let raw;
135
- try {
136
- raw = readFileSync(path, 'utf8');
137
- }
138
- catch {
139
- return {};
140
- }
141
- if (raw.trim().length === 0)
142
- return {};
143
- let parsed;
144
- try {
145
- parsed = JSON.parse(raw);
146
- }
147
- catch {
148
- return {};
149
- }
150
- if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
151
- return {};
152
- return parsed;
153
- }
154
- function writeConfigFile(path, config) {
155
- mkdirSync(dirname(path), { recursive: true });
156
- // 0o600 mirrors `core/output-style/state.ts` + `runtime/commands/config.ts` —
157
- // the config file may hold preferredEndpoint URLs etc. that should
158
- // not be world-readable.
159
- writeFileSync(path, `${JSON.stringify(config, null, 2)}\n`, {
160
- encoding: 'utf8',
161
- mode: 0o600,
162
- });
163
- }
164
- function readSlugFromFile(path) {
165
- const config = readConfigFile(path);
166
- const candidate = config.theme;
167
- return isThemeSlug(candidate) ? candidate : null;
168
- }
169
- function writeSlugToFile(path, slug) {
170
- const config = readConfigFile(path);
171
- config.theme = slug;
172
- writeConfigFile(path, config);
173
- }
174
- function clearSlugInFile(path) {
175
- const config = readConfigFile(path);
176
- if (!('theme' in config))
177
- return;
178
- delete config.theme;
179
- writeConfigFile(path, config);
180
- }
181
- //# sourceMappingURL=state.js.map
@@ -1,10 +0,0 @@
1
- /**
2
- * Single-in-progress invariant constants and types — .
3
- *
4
- * Kept in a separate module so the tool-bridge dispatcher and the
5
- * spec layer can import the sentinel string + types without pulling
6
- * in `node:fs` via `state.ts`. The sentinel prefix is stable so the
7
- * engine adapter / model prompt can pattern-match on it verbatim.
8
- */
9
- export const TODO_INVARIANT_VIOLATED = 'TODO_INVARIANT_VIOLATED';
10
- //# sourceMappingURL=invariant.js.map
@@ -1,177 +0,0 @@
1
- /**
2
- * Workspace-scoped todo board persistence — .
3
- *
4
- * `todo_write` is the BATCH-replace counterpart to the granular `task_*`
5
- * journal in `tools/tasks.ts`. Where `task_*` appends one journal line
6
- * per mutation (session-scoped, JSONL, append-only), `todo_write` snaps
7
- * the entire board to disk in one atomic write (workspace-scoped, JSON,
8
- * snapshot-only). They are complementary surfaces for the same problem
9
- * — `task_*` is fine-grained, `todo_write` mirrors the upstream tool's
10
- * TodoWrite verbatim so a model trained on that grammar speaks Pugi's
11
- * variant 1:1.
12
- *
13
- * Single-in-progress invariant
14
- * ----------------------------
15
- * the upstream tool TodoWrite enforces at most ONE todo `status: 'in_progress'`
16
- * at a time. The invariant prevents the model from fragmenting attention
17
- * across multiple parallel claims of "I am working on X right now" — a
18
- * pattern that empirically produces stalled work and operator confusion
19
- * about which thread is alive. We enforce the same invariant at the tool
20
- * boundary: a dispatch with >1 `in_progress` rejects with
21
- * `TODO_INVARIANT_VIOLATED: ...` and the board on disk is left unchanged.
22
- *
23
- * Persistence shape
24
- * -----------------
25
- * Path: `<workspaceRoot>/.pugi/todos.json` (one board per workspace).
26
- * Atomic: write to `<path>.pugi-tmp-<ts>` then `renameSync` — the rename
27
- * is the commit point. A crash mid-write leaves the previous snapshot
28
- * intact (or, on first write, leaves the dangling tmp file which the
29
- * loader ignores). Mode 0o600 — the board can contain operator task
30
- * descriptions and should not be world-readable through an inherited
31
- * umask.
32
- *
33
- * Why workspace-scoped, not session-scoped
34
- * ----------------------------------------
35
- * The the upstream tool TodoWrite contract is "the board persists across the
36
- * session". Pugi sessions are short-lived (one REPL run); the operator's
37
- * mental model of the board is "this is the workspace's plan", not "this
38
- * is THIS session's plan". Workspace scope matches that mental model and
39
- * lets `/todos` (when wired) read the latest board even after a CLI
40
- * restart. The `task_*` ledger remains session-scoped for the agent's
41
- * dispatch trace.
42
- */
43
- import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, } from 'node:fs';
44
- import { dirname, join } from 'node:path';
45
- import { TODO_INVARIANT_VIOLATED } from './invariant.js';
46
- /** Path the board lives at. Workspace-scoped, NOT session-scoped. */
47
- export function todoBoardPath(ctx) {
48
- return join(ctx.workspaceRoot, '.pugi', 'todos.json');
49
- }
50
- function ensureDir(path) {
51
- const dir = dirname(path);
52
- if (!existsSync(dir)) {
53
- mkdirSync(dir, { recursive: true });
54
- try {
55
- chmodSync(dir, 0o700);
56
- }
57
- catch {
58
- // Best-effort; Windows NTFS no-op. The 0o600 mode on the JSON
59
- // file itself remains the primary guard.
60
- }
61
- }
62
- }
63
- function nowIso(ctx) {
64
- return (ctx.now ? ctx.now() : new Date()).toISOString();
65
- }
66
- /**
67
- * Load the current board. Returns an empty board when the file is
68
- * absent or malformed — the rationale is that a corrupted state file
69
- * should NOT brick the tool surface; the model can re-emit the full
70
- * board on the next call. Malformed loads are silent (no throw) so a
71
- * fresh workspace and a corrupted workspace look identical to the
72
- * caller.
73
- *
74
- * The schema check is deliberately defensive: any missing field, wrong
75
- * type, or unexpected status string drops the load to an empty board.
76
- * The model will see `todos: []` and is free to redeclare the plan.
77
- */
78
- export function loadTodoBoard(ctx) {
79
- const path = todoBoardPath(ctx);
80
- if (!existsSync(path)) {
81
- return { version: 1, updatedAt: nowIso(ctx), todos: [] };
82
- }
83
- try {
84
- const raw = readFileSync(path, 'utf8');
85
- const parsed = JSON.parse(raw);
86
- if (!isPlainObject(parsed))
87
- return emptyBoard(ctx);
88
- if (parsed.version !== 1)
89
- return emptyBoard(ctx);
90
- if (typeof parsed.updatedAt !== 'string')
91
- return emptyBoard(ctx);
92
- if (!Array.isArray(parsed.todos))
93
- return emptyBoard(ctx);
94
- const todos = [];
95
- for (const entry of parsed.todos) {
96
- if (!isPlainObject(entry))
97
- return emptyBoard(ctx);
98
- if (typeof entry.id !== 'string' || entry.id.length === 0)
99
- return emptyBoard(ctx);
100
- if (typeof entry.content !== 'string' || entry.content.length === 0) {
101
- return emptyBoard(ctx);
102
- }
103
- if (entry.status !== 'pending' &&
104
- entry.status !== 'in_progress' &&
105
- entry.status !== 'completed') {
106
- return emptyBoard(ctx);
107
- }
108
- const item = {
109
- id: entry.id,
110
- content: entry.content,
111
- status: entry.status,
112
- ...(typeof entry.activeForm === 'string' && entry.activeForm.length > 0
113
- ? { activeForm: entry.activeForm }
114
- : {}),
115
- };
116
- todos.push(item);
117
- }
118
- return { version: 1, updatedAt: parsed.updatedAt, todos };
119
- }
120
- catch {
121
- return emptyBoard(ctx);
122
- }
123
- }
124
- function emptyBoard(ctx) {
125
- return { version: 1, updatedAt: nowIso(ctx), todos: [] };
126
- }
127
- function isPlainObject(value) {
128
- return typeof value === 'object' && value !== null && !Array.isArray(value);
129
- }
130
- /**
131
- * Persist a new board atomically. Enforces the single-in-progress
132
- * invariant BEFORE touching disk so a violating dispatch never reaches
133
- * the filesystem. On invariant violation, throws an Error whose message
134
- * starts with `TODO_INVARIANT_VIOLATED:` (the sentinel prefix the tool
135
- * dispatcher pattern-matches on).
136
- *
137
- * The atomic write uses tmp+rename — `writeFileSync` to a sibling tmp
138
- * path, then `renameSync` onto the real file. POSIX guarantees rename is
139
- * atomic within the same directory; on a crash, the operator sees the
140
- * previous board (or no board at all on first write), never a torn
141
- * write. Mode 0o600 is set on the tmp file so the rename inherits the
142
- * restrictive mode.
143
- */
144
- export function saveTodoBoard(ctx, todos) {
145
- // Invariant check FIRST — never write a violating board.
146
- const inProgress = todos.filter((t) => t.status === 'in_progress').length;
147
- if (inProgress > 1) {
148
- throw new Error(`${TODO_INVARIANT_VIOLATED}: ${inProgress} items in_progress simultaneously. ` +
149
- `Mark all-but-one as 'pending' or 'completed'.`);
150
- }
151
- // Duplicate-id check — every id must be unique within the board so
152
- // a `todo_get(id)` would have a single answer. The model emits ids;
153
- // we refuse to persist a board that would silently shadow one.
154
- const seen = new Set();
155
- for (const todo of todos) {
156
- if (seen.has(todo.id)) {
157
- throw new Error(`TODO_DUPLICATE_ID: id "${todo.id}" appears more than once in the batch. ` +
158
- `Use a stable, unique id per todo item.`);
159
- }
160
- seen.add(todo.id);
161
- }
162
- const board = {
163
- version: 1,
164
- updatedAt: nowIso(ctx),
165
- todos: todos.map((t) => ({ ...t })),
166
- };
167
- const path = todoBoardPath(ctx);
168
- ensureDir(path);
169
- const tmp = `${path}.pugi-tmp-${Date.now()}`;
170
- writeFileSync(tmp, `${JSON.stringify(board, null, 2)}\n`, {
171
- encoding: 'utf8',
172
- mode: 0o600,
173
- });
174
- renameSync(tmp, path);
175
- return board;
176
- }
177
- //# sourceMappingURL=state.js.map
@@ -1,89 +0,0 @@
1
- /**
2
- * Tool schema compression .
3
- *
4
- * LLM tool definitions are routinely 30-40% of system-prompt bytes
5
- * once a non-trivial tool surface lands. Most of those bytes are
6
- * boilerplate keys ("type"/"function"/"properties"/"required"/"description")
7
- * which repeat per tool. Compressing key names с a fixed mapping table
8
- * recovers ~20-25% on average per Anthropic's published benchmarks
9
- * без changing semantics OR runtime behaviour.
10
- *
11
- * What this module does:
12
- * - compress(schema) → smaller schema using single-char keys
13
- * - decompress(compressed) → original schema
14
- * - Round-trip stable: decompress(compress(x)) ≡ x
15
- *
16
- * What it does NOT do:
17
- * - Change tool semantics
18
- * - Compress key names that look like data (parameter names, enum values)
19
- * - Touch description strings (those go through prompt cache, not here)
20
- *
21
- * Caller decides when к use compression — typically applied only к
22
- * the tool-definitions block, never к user content or model output.
23
- */
24
- /**
25
- * Reserved JSON-schema key shortener. Order is stable; do NOT reorder
26
- * entries — downstream decompression depends на the exact mapping.
27
- *
28
- * Single-char codes were picked к not collide с common parameter
29
- * names (avoiding lowercase letters that appear в kebab/snake-case
30
- * tool param identifiers).
31
- */
32
- const KEY_MAP = Object.freeze({
33
- type: '$T',
34
- function: '$F',
35
- name: '$N',
36
- description: '$D',
37
- parameters: '$P',
38
- properties: '$O',
39
- required: '$R',
40
- items: '$I',
41
- enum: '$E',
42
- default: '$X',
43
- additionalProperties: '$A',
44
- minimum: '$m',
45
- maximum: '$M',
46
- minLength: '$l',
47
- maxLength: '$L',
48
- pattern: '$p',
49
- format: '$f',
50
- oneOf: '$1',
51
- anyOf: '$2',
52
- allOf: '$3',
53
- });
54
- const REVERSE_KEY_MAP = Object.freeze(Object.fromEntries(Object.entries(KEY_MAP).map(([k, v]) => [v, k])));
55
- export function compress(schema) {
56
- return walk(schema, true);
57
- }
58
- export function decompress(schema) {
59
- return walk(schema, false);
60
- }
61
- export function compressionStats(original, compressed) {
62
- const originalBytes = Buffer.byteLength(JSON.stringify(original), 'utf8');
63
- const compressedBytes = Buffer.byteLength(JSON.stringify(compressed), 'utf8');
64
- const savedBytes = originalBytes - compressedBytes;
65
- const ratio = originalBytes > 0 ? compressedBytes / originalBytes : 1;
66
- return { originalBytes, compressedBytes, savedBytes, ratio };
67
- }
68
- /** Expose key mapping for callers that need к interop с the protocol. */
69
- export function getKeyMap() {
70
- return KEY_MAP;
71
- }
72
- function walk(value, forward) {
73
- if (Array.isArray(value)) {
74
- return value.map(item => walk(item, forward));
75
- }
76
- if (value !== null && typeof value === 'object') {
77
- const obj = value;
78
- const out = {};
79
- for (const [key, val] of Object.entries(obj)) {
80
- const mapped = forward
81
- ? (KEY_MAP[key] ?? key)
82
- : (REVERSE_KEY_MAP[key] ?? key);
83
- out[mapped] = walk(val, forward);
84
- }
85
- return out;
86
- }
87
- return value;
88
- }
89
- //# sourceMappingURL=compressor.js.map