@pugi/cli 0.1.0-beta.10 → 0.1.0-beta.101

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 (464) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/LICENSE +1 -1
  3. package/README.md +55 -11
  4. package/assets/pugi-prozr2-mascot.ansi +9 -0
  5. package/bin/run.js +33 -1
  6. package/dist/commands/deploy.js +40 -40
  7. package/dist/commands/flatten.js +191 -0
  8. package/dist/commands/jobs-watch.js +201 -0
  9. package/dist/commands/jobs.js +42 -27
  10. package/dist/commands/retro.js +210 -0
  11. package/dist/commands/smoke.js +133 -0
  12. package/dist/core/agent-progress/cleanup.js +134 -0
  13. package/dist/core/agent-progress/schema.js +144 -0
  14. package/dist/core/agent-progress/writer.js +101 -0
  15. package/dist/core/agents/adaptive-router.js +330 -0
  16. package/dist/core/agents/query-decomposer.js +297 -0
  17. package/dist/core/agents/registry.js +3 -3
  18. package/dist/core/approvals/shortcut-resolver.js +98 -0
  19. package/dist/core/artifact-chain/dispatcher.js +148 -0
  20. package/dist/core/artifact-chain/exporter.js +164 -0
  21. package/dist/core/artifact-chain/state.js +243 -0
  22. package/dist/core/artifact-chain/steps.js +169 -0
  23. package/dist/core/ask-user/question.js +92 -0
  24. package/dist/core/audit/audit-trail.js +275 -0
  25. package/dist/core/auth/ensure-authenticated.js +129 -0
  26. package/dist/core/auth/env-provider.js +238 -0
  27. package/dist/core/auto-open-browser.js +4 -4
  28. package/dist/core/auto-update/channels.js +122 -0
  29. package/dist/core/auto-update/checker.js +241 -0
  30. package/dist/core/auto-update/state.js +235 -0
  31. package/dist/core/bare-mode/index.js +107 -0
  32. package/dist/core/bash/redirect.js +281 -0
  33. package/dist/core/bash-classifier.js +436 -40
  34. package/dist/core/checkpoint/resumer.js +149 -0
  35. package/dist/core/checkpoint/rewinder.js +291 -0
  36. package/dist/core/checkpoints/shadow-git.js +670 -0
  37. package/dist/core/citations/parser.js +109 -0
  38. package/dist/core/classifier/yolo-classifier.js +88 -0
  39. package/dist/core/codegraph/db.js +506 -0
  40. package/dist/core/codegraph/decision-store.js +248 -0
  41. package/dist/core/codegraph/detect-repo.js +459 -0
  42. package/dist/core/codegraph/install.js +134 -0
  43. package/dist/core/codegraph/offer-hook.js +220 -0
  44. package/dist/core/codegraph/parser.js +598 -0
  45. package/dist/core/codegraph/queries/go.scm +57 -0
  46. package/dist/core/codegraph/queries/javascript.scm +56 -0
  47. package/dist/core/codegraph/queries/python.scm +55 -0
  48. package/dist/core/codegraph/queries/rust.scm +63 -0
  49. package/dist/core/codegraph/queries/typescript.scm +91 -0
  50. package/dist/core/codegraph/reindex.js +218 -0
  51. package/dist/core/codegraph/resolve-edges.js +107 -0
  52. package/dist/core/codegraph/types.js +34 -0
  53. package/dist/core/codegraph/watcher.js +440 -0
  54. package/dist/core/compact/auto-trigger.js +96 -0
  55. package/dist/core/compact/buffer-rewriter.js +115 -0
  56. package/dist/core/compact/summarizer.js +208 -0
  57. package/dist/core/compact/token-counter.js +108 -0
  58. package/dist/core/consensus/anvil-fanout.js +25 -25
  59. package/dist/core/consensus/diff-capture.js +121 -12
  60. package/dist/core/consensus/rubric.js +21 -21
  61. package/dist/core/context/builder.js +6 -6
  62. package/dist/core/context/compaction-events.js +8 -8
  63. package/dist/core/context/compaction.js +31 -31
  64. package/dist/core/context/index.js +15 -8
  65. package/dist/core/context/invariants.js +51 -51
  66. package/dist/core/context/markdown-loader.js +28 -10
  67. package/dist/core/context/markdown-traverse.js +255 -0
  68. package/dist/core/context/pugiignore.js +41 -41
  69. package/dist/core/context/repo-skeleton.js +37 -37
  70. package/dist/core/context/tool-eviction.js +55 -0
  71. package/dist/core/context/watcher.js +32 -32
  72. package/dist/core/context/working-set.js +23 -23
  73. package/dist/core/coordinator/agent-tools.js +77 -0
  74. package/dist/core/coordinator/agent-toolset.js +65 -0
  75. package/dist/core/coordinator/fsm.js +73 -0
  76. package/dist/core/coordinator/mode-fsm.js +70 -0
  77. package/dist/core/cost/rate-card.js +129 -0
  78. package/dist/core/cost/tracker.js +221 -0
  79. package/dist/core/credentials.js +13 -13
  80. package/dist/core/cron/scheduler.js +138 -0
  81. package/dist/core/denial-tracking/index.js +8 -0
  82. package/dist/core/denial-tracking/state.js +264 -0
  83. package/dist/core/diagnostics/probe-runner.js +93 -0
  84. package/dist/core/diagnostics/probes/api.js +46 -0
  85. package/dist/core/diagnostics/probes/auth.js +93 -0
  86. package/dist/core/diagnostics/probes/bare-mode.js +42 -0
  87. package/dist/core/diagnostics/probes/cli-version.js +127 -0
  88. package/dist/core/diagnostics/probes/config.js +72 -0
  89. package/dist/core/diagnostics/probes/denial-tracking.js +57 -0
  90. package/dist/core/diagnostics/probes/disk.js +81 -0
  91. package/dist/core/diagnostics/probes/engine-live.js +46 -0
  92. package/dist/core/diagnostics/probes/git.js +65 -0
  93. package/dist/core/diagnostics/probes/hooks.js +118 -0
  94. package/dist/core/diagnostics/probes/mcp.js +75 -0
  95. package/dist/core/diagnostics/probes/node.js +59 -0
  96. package/dist/core/diagnostics/probes/pnpm.js +36 -0
  97. package/dist/core/diagnostics/probes/pugi-md.js +89 -0
  98. package/dist/core/diagnostics/probes/sandbox.js +67 -0
  99. package/dist/core/diagnostics/probes/session.js +74 -0
  100. package/dist/core/diagnostics/probes/status-snapshot.js +488 -0
  101. package/dist/core/diagnostics/probes/workspace.js +63 -0
  102. package/dist/core/diagnostics/types.js +70 -0
  103. package/dist/core/dispatch/cache-cleanup.js +197 -0
  104. package/dist/core/dispatch/cache-handoff.js +295 -0
  105. package/dist/core/edits/apply-patch-layer-e.js +189 -0
  106. package/dist/core/edits/dispatch.js +333 -7
  107. package/dist/core/edits/format-detector.js +260 -0
  108. package/dist/core/edits/format-matrix.js +26 -0
  109. package/dist/core/edits/fuzzy-ladder.js +650 -0
  110. package/dist/core/edits/index.js +5 -1
  111. package/dist/core/edits/journal.js +199 -0
  112. package/dist/core/edits/layer-a-apply.js +15 -15
  113. package/dist/core/edits/layer-a-fuzzy-apply.js +198 -0
  114. package/dist/core/edits/layer-b-apply.js +9 -9
  115. package/dist/core/edits/layer-c-apply.js +6 -6
  116. package/dist/core/edits/layer-d-ast.js +557 -14
  117. package/dist/core/edits/marker-parser.js +12 -12
  118. package/dist/core/edits/security-gate.js +27 -27
  119. package/dist/core/edits/verify-hook.js +273 -0
  120. package/dist/core/edits/worktree.js +29 -29
  121. package/dist/core/engine/anvil-client.js +214 -26
  122. package/dist/core/engine/auto-compact.js +247 -0
  123. package/dist/core/engine/budgets.js +220 -0
  124. package/dist/core/engine/compact-llm-summarizer.js +124 -0
  125. package/dist/core/engine/context-prefix.js +155 -0
  126. package/dist/core/engine/index.js +1 -1
  127. package/dist/core/engine/intensity.js +163 -0
  128. package/dist/core/engine/intent.js +260 -0
  129. package/dist/core/engine/native-pugi.js +1559 -227
  130. package/dist/core/engine/prompts.js +219 -19
  131. package/dist/core/engine/strip-internal-fields.js +124 -0
  132. package/dist/core/engine/tool-bridge.js +1887 -59
  133. package/dist/core/engine/verification-patterns.js +195 -0
  134. package/dist/core/eval/v1/ledger.js +83 -0
  135. package/dist/core/eval/v1/runner.js +280 -0
  136. package/dist/core/eval/v1/scoring.js +68 -0
  137. package/dist/core/eval/v1/task-loader.js +191 -0
  138. package/dist/core/eval/v1/types.js +14 -0
  139. package/dist/core/eval/v1/verifier.js +176 -0
  140. package/dist/core/eval/v1/yaml-parser.js +250 -0
  141. package/dist/core/evaluation/golden-dataset.js +293 -0
  142. package/dist/core/feedback/queue.js +177 -0
  143. package/dist/core/feedback/submitter.js +145 -0
  144. package/dist/core/file-cache.js +113 -1
  145. package/dist/core/flatten/flatten-repo.js +439 -0
  146. package/dist/core/format/osc8-link.js +28 -0
  147. package/dist/core/hook-chains.js +392 -0
  148. package/dist/core/hooks/citation-verify-hook.js +138 -0
  149. package/dist/core/hooks/citation-verify.js +112 -0
  150. package/dist/core/hooks/events.js +46 -0
  151. package/dist/core/hooks/index.js +15 -0
  152. package/dist/core/hooks/registry.js +216 -0
  153. package/dist/core/hooks/runner.js +236 -0
  154. package/dist/core/hooks/v2/event-emitter.js +115 -0
  155. package/dist/core/hooks/v2/executor.js +282 -0
  156. package/dist/core/hooks/v2/index.js +25 -0
  157. package/dist/core/hooks/v2/lifecycle.js +104 -0
  158. package/dist/core/hooks/v2/loader.js +216 -0
  159. package/dist/core/hooks/v2/matcher.js +125 -0
  160. package/dist/core/hooks/v2/trust.js +143 -0
  161. package/dist/core/hooks/v2/types.js +86 -0
  162. package/dist/core/hooks/worktree-events.js +158 -0
  163. package/dist/core/image/renderer.js +71 -0
  164. package/dist/core/init/detector.js +582 -0
  165. package/dist/core/init/template-renderer.js +242 -0
  166. package/dist/core/jobs/registry.js +18 -18
  167. package/dist/core/ledger/results-tsv.js +142 -0
  168. package/dist/core/log-discipline/stdout-redirect.js +51 -0
  169. package/dist/core/lsp/cache.js +105 -0
  170. package/dist/core/lsp/client.js +551 -41
  171. package/dist/core/lsp/language-detect.js +66 -0
  172. package/dist/core/lsp/post-edit-diagnostics.js +171 -0
  173. package/dist/core/lsp/server-detect.js +173 -0
  174. package/dist/core/lsp/symbol-cache.js +162 -0
  175. package/dist/core/lsp/symbol-tools.js +664 -0
  176. package/dist/core/mcp/client.js +97 -28
  177. package/dist/core/mcp/http-server.js +553 -0
  178. package/dist/core/mcp/orchestrator-config.js +192 -0
  179. package/dist/core/mcp/orchestrator-tools.js +806 -0
  180. package/dist/core/mcp/permission.js +190 -0
  181. package/dist/core/mcp/registry.js +39 -17
  182. package/dist/core/mcp/server-tools.js +219 -0
  183. package/dist/core/mcp/server.js +397 -0
  184. package/dist/core/mcp/trust.js +10 -10
  185. package/dist/core/memory/dual-write.js +416 -0
  186. package/dist/core/memory/passive-extract.js +130 -0
  187. package/dist/core/memory/phase1-kinds.js +20 -0
  188. package/dist/core/memory/secret-scanner.js +304 -0
  189. package/dist/core/memory-sync/queue.js +170 -0
  190. package/dist/core/metrics/extract.js +113 -0
  191. package/dist/core/modes/roo-modes.js +68 -0
  192. package/dist/core/notes/notes-paths.js +113 -0
  193. package/dist/core/notes/notes-recorder.js +140 -0
  194. package/dist/core/notes/notes-writer.js +53 -0
  195. package/dist/core/notes/renderers.js +0 -0
  196. package/dist/core/notes/slug.js +105 -0
  197. package/dist/core/onboarding/ensure-initialized.js +133 -0
  198. package/dist/core/onboarding/marker.js +111 -0
  199. package/dist/core/onboarding/telemetry-state.js +108 -0
  200. package/dist/core/output-style/presets.js +176 -0
  201. package/dist/core/output-style/state.js +185 -0
  202. package/dist/core/path-security.js +287 -5
  203. package/dist/core/permission.js +82 -22
  204. package/dist/core/permissions/auto-classifier.js +124 -0
  205. package/dist/core/permissions/bash-parser.js +371 -0
  206. package/dist/core/permissions/circuit-breaker.js +83 -0
  207. package/dist/core/permissions/constrained-edit.js +91 -0
  208. package/dist/core/permissions/gate.js +278 -0
  209. package/dist/core/permissions/index.js +20 -0
  210. package/dist/core/permissions/mode.js +174 -0
  211. package/dist/core/permissions/network-egress.js +137 -0
  212. package/dist/core/permissions/state.js +241 -0
  213. package/dist/core/permissions/tool-class.js +107 -0
  214. package/dist/core/plan-mode/ui-state.js +51 -0
  215. package/dist/core/plans/plan-artifact.js +721 -0
  216. package/dist/core/policy-limits/etag-store.js +122 -0
  217. package/dist/core/prd-check/parser.js +215 -0
  218. package/dist/core/prd-check/reporter.js +127 -0
  219. package/dist/core/prd-check/session-review.js +557 -0
  220. package/dist/core/prd-check/verifiers.js +223 -0
  221. package/dist/core/prompt-cache/client-cache.js +99 -0
  222. package/dist/core/prompts/assembly.js +29 -0
  223. package/dist/core/prompts/registry.js +364 -0
  224. package/dist/core/pugi-gitignore.js +52 -0
  225. package/dist/core/pugi-md/cc-compat-rules.js +735 -0
  226. package/dist/core/pugi-md/context-injector.js +76 -0
  227. package/dist/core/pugi-md/walk-up.js +207 -0
  228. package/dist/core/python/uv-installer.js +270 -0
  229. package/dist/core/python/uv-resolver.js +83 -0
  230. package/dist/core/rate-limit/narrator.js +146 -0
  231. package/dist/core/recipes/cli-types.js +20 -0
  232. package/dist/core/recipes/loader.js +103 -0
  233. package/dist/core/recipes/runner.js +345 -0
  234. package/dist/core/recipes/schema.js +587 -0
  235. package/dist/core/release-notes/parser.js +241 -0
  236. package/dist/core/release-notes/state.js +116 -0
  237. package/dist/core/repl/ask.js +37 -37
  238. package/dist/core/repl/cancellation.js +26 -26
  239. package/dist/core/repl/cap-warning.js +4 -4
  240. package/dist/core/repl/clipboard-read.js +11 -11
  241. package/dist/core/repl/dispatch-fsm.js +12 -12
  242. package/dist/core/repl/engine-bridge.js +303 -0
  243. package/dist/core/repl/history-search.js +15 -15
  244. package/dist/core/repl/history.js +28 -18
  245. package/dist/core/repl/kill-ring.js +5 -5
  246. package/dist/core/repl/model-pricing.js +135 -0
  247. package/dist/core/repl/privacy-banner.js +22 -22
  248. package/dist/core/repl/session.js +2690 -229
  249. package/dist/core/repl/slash-commands.js +540 -41
  250. package/dist/core/repl/store/index.js +1 -1
  251. package/dist/core/repl/store/jsonl-log.js +22 -22
  252. package/dist/core/repl/store/lockfile.js +10 -10
  253. package/dist/core/repl/store/session-store.js +136 -107
  254. package/dist/core/repl/store/types.js +15 -15
  255. package/dist/core/repl/store/uuid-v7.js +12 -12
  256. package/dist/core/repl/tool-route.js +382 -0
  257. package/dist/core/repl/workspace-context.js +43 -21
  258. package/dist/core/repo-map/build.js +125 -0
  259. package/dist/core/repo-map/cache.js +185 -0
  260. package/dist/core/repo-map/extractor.js +254 -0
  261. package/dist/core/repo-map/formatter.js +145 -0
  262. package/dist/core/repo-map/page-rank.js +105 -0
  263. package/dist/core/repo-map/scanner.js +211 -0
  264. package/dist/core/retro/git-collector.js +251 -0
  265. package/dist/core/retro/health-card.js +25 -0
  266. package/dist/core/retro/metrics.js +342 -0
  267. package/dist/core/retro/narrative.js +249 -0
  268. package/dist/core/retro/plane-collector.js +274 -0
  269. package/dist/core/retro/pr-issue-link.js +65 -0
  270. package/dist/core/retro/types.js +16 -0
  271. package/dist/core/retry-budget/budget.js +284 -0
  272. package/dist/core/retry-budget/index.js +5 -0
  273. package/dist/core/retry-budget/retry-cap.js +74 -0
  274. package/dist/core/routing/lead-worker.js +43 -0
  275. package/dist/core/routing/pre-flight-estimator.js +108 -0
  276. package/dist/core/runs/run-tree.js +103 -0
  277. package/dist/core/sandboxing/adapter.js +43 -0
  278. package/dist/core/sandboxing/bubblewrap.js +209 -0
  279. package/dist/core/sandboxing/index.js +78 -0
  280. package/dist/core/sandboxing/none.js +19 -0
  281. package/dist/core/sandboxing/policy.js +97 -0
  282. package/dist/core/sandboxing/seatbelt.js +231 -0
  283. package/dist/core/security/injection-scanner.js +367 -0
  284. package/dist/core/security/output-filter.js +418 -0
  285. package/dist/core/session/env-file.js +105 -0
  286. package/dist/core/session/section-budgets.js +140 -0
  287. package/dist/core/session.js +119 -0
  288. package/dist/core/settings.js +402 -5
  289. package/dist/core/share/formatter.js +271 -0
  290. package/dist/core/share/redactor.js +221 -0
  291. package/dist/core/share/uploader.js +267 -0
  292. package/dist/core/skills/defaults.js +30 -30
  293. package/dist/core/skills/loader.js +22 -22
  294. package/dist/core/skills/sources.js +27 -27
  295. package/dist/core/smoke/headless-driver.js +174 -0
  296. package/dist/core/smoke/orchestrator.js +194 -0
  297. package/dist/core/smoke/runner.js +238 -0
  298. package/dist/core/smoke/scenario-parser.js +316 -0
  299. package/dist/core/statusline.js +99 -0
  300. package/dist/core/subagents/dispatcher-real.js +600 -0
  301. package/dist/core/subagents/dispatcher.js +146 -52
  302. package/dist/core/subagents/index.js +19 -6
  303. package/dist/core/subagents/isolation-matrix.js +213 -0
  304. package/dist/core/subagents/spawn.js +19 -4
  305. package/dist/core/telemetry/emitter.js +229 -0
  306. package/dist/core/telemetry/queue.js +251 -0
  307. package/dist/core/theme/context.js +91 -0
  308. package/dist/core/theme/presets.js +228 -0
  309. package/dist/core/theme/state.js +181 -0
  310. package/dist/core/todos/invariant.js +10 -0
  311. package/dist/core/todos/state.js +177 -0
  312. package/dist/core/tool-schema/compressor.js +89 -0
  313. package/dist/core/transport/version-interceptor.js +166 -0
  314. package/dist/core/trust.js +2 -2
  315. package/dist/core/tui/thinking-block.js +64 -0
  316. package/dist/core/vim/keymap.js +288 -0
  317. package/dist/core/vim/state.js +92 -0
  318. package/dist/core/watch-markers/marker-watcher.js +133 -0
  319. package/dist/core/worktree/include-parser.js +249 -0
  320. package/dist/core/worktree-manager/cleanup.js +123 -0
  321. package/dist/core/worktree-manager/manager.js +303 -0
  322. package/dist/index.js +36 -0
  323. package/dist/runtime/bootstrap.js +190 -0
  324. package/dist/runtime/cli.js +4403 -561
  325. package/dist/runtime/commands/agents.js +31 -31
  326. package/dist/runtime/commands/budget.js +5 -5
  327. package/dist/runtime/commands/cancel.js +231 -0
  328. package/dist/runtime/commands/chain.js +489 -0
  329. package/dist/runtime/commands/codegraph-status.js +227 -0
  330. package/dist/runtime/commands/compact.js +297 -0
  331. package/dist/runtime/commands/config.js +74 -40
  332. package/dist/runtime/commands/cost.js +199 -0
  333. package/dist/runtime/commands/delegate.js +27 -4
  334. package/dist/runtime/commands/dispatch.js +126 -0
  335. package/dist/runtime/commands/doctor.js +579 -0
  336. package/dist/runtime/commands/eval-v1.js +266 -0
  337. package/dist/runtime/commands/feedback.js +184 -0
  338. package/dist/runtime/commands/hooks.js +187 -0
  339. package/dist/runtime/commands/index-cmd.js +459 -0
  340. package/dist/runtime/commands/init.js +254 -0
  341. package/dist/runtime/commands/lsp.js +200 -38
  342. package/dist/runtime/commands/mcp.js +935 -0
  343. package/dist/runtime/commands/memory.js +582 -0
  344. package/dist/runtime/commands/model.js +237 -0
  345. package/dist/runtime/commands/onboarding.js +275 -0
  346. package/dist/runtime/commands/patch.js +12 -12
  347. package/dist/runtime/commands/permissions.js +112 -0
  348. package/dist/runtime/commands/plan.js +143 -0
  349. package/dist/runtime/commands/prd-check.js +285 -0
  350. package/dist/runtime/commands/privacy.js +17 -17
  351. package/dist/runtime/commands/recipe.js +325 -0
  352. package/dist/runtime/commands/redo-blob-store.js +92 -0
  353. package/dist/runtime/commands/redo.js +361 -0
  354. package/dist/runtime/commands/release-notes.js +229 -0
  355. package/dist/runtime/commands/repo-map.js +95 -0
  356. package/dist/runtime/commands/report.js +299 -0
  357. package/dist/runtime/commands/resume.js +118 -0
  358. package/dist/runtime/commands/review-consensus.js +68 -53
  359. package/dist/runtime/commands/rewind.js +333 -0
  360. package/dist/runtime/commands/roster.js +14 -14
  361. package/dist/runtime/commands/servers-cli.js +182 -0
  362. package/dist/runtime/commands/servers.js +236 -0
  363. package/dist/runtime/commands/sessions.js +163 -0
  364. package/dist/runtime/commands/share.js +316 -0
  365. package/dist/runtime/commands/skills.js +31 -31
  366. package/dist/runtime/commands/status.js +186 -0
  367. package/dist/runtime/commands/stickers.js +82 -0
  368. package/dist/runtime/commands/style.js +194 -0
  369. package/dist/runtime/commands/theme.js +196 -0
  370. package/dist/runtime/commands/undo.js +54 -22
  371. package/dist/runtime/commands/update.js +289 -0
  372. package/dist/runtime/commands/vim.js +140 -0
  373. package/dist/runtime/commands/worktree.js +8 -8
  374. package/dist/runtime/commands/worktrees.js +155 -0
  375. package/dist/runtime/deprecation-warning.js +69 -0
  376. package/dist/runtime/engine-exit-code.js +50 -0
  377. package/dist/runtime/headless-repl.js +195 -0
  378. package/dist/runtime/headless.js +548 -0
  379. package/dist/runtime/load-hooks-or-exit.js +71 -0
  380. package/dist/runtime/plan-decompose.js +22 -22
  381. package/dist/runtime/sigint-guard.js +272 -0
  382. package/dist/runtime/stream-renderer.js +195 -0
  383. package/dist/runtime/update-check.js +28 -28
  384. package/dist/runtime/version.js +65 -0
  385. package/dist/runtime/worktree-bootstrap.js +579 -0
  386. package/dist/skills/bundled/batch.js +617 -0
  387. package/dist/skills/bundled/index.js +45 -0
  388. package/dist/skills/bundled/loop.js +358 -0
  389. package/dist/skills/bundled/remember.js +383 -0
  390. package/dist/skills/bundled/simplify.js +289 -0
  391. package/dist/skills/bundled/skillify.js +373 -0
  392. package/dist/skills/bundled/stuck.js +558 -0
  393. package/dist/skills/bundled/verify.js +439 -0
  394. package/dist/testing/vcr.js +486 -0
  395. package/dist/tools/agent-tool.js +229 -0
  396. package/dist/tools/apply-patch.js +89 -28
  397. package/dist/tools/ask-user-question.js +337 -0
  398. package/dist/tools/ask-user.js +115 -0
  399. package/dist/tools/bash.js +811 -49
  400. package/dist/tools/brief.js +224 -0
  401. package/dist/tools/cron.js +433 -0
  402. package/dist/tools/enter-worktree.js +250 -0
  403. package/dist/tools/exit-worktree.js +147 -0
  404. package/dist/tools/file-tools.js +161 -44
  405. package/dist/tools/http-request.js +336 -0
  406. package/dist/tools/lsp-tools.js +377 -1
  407. package/dist/tools/mcp-tool.js +260 -0
  408. package/dist/tools/multi-edit.js +361 -0
  409. package/dist/tools/powershell.js +268 -0
  410. package/dist/tools/registry.js +120 -5
  411. package/dist/tools/server-tools.js +892 -0
  412. package/dist/tools/skill-tool.js +96 -0
  413. package/dist/tools/sleep.js +99 -0
  414. package/dist/tools/synthetic-output.js +133 -0
  415. package/dist/tools/tasks.js +208 -0
  416. package/dist/tools/todo-write.js +184 -0
  417. package/dist/tools/verify-plan-execution.js +295 -0
  418. package/dist/tools/web-fetch-injection-scanner.js +207 -0
  419. package/dist/tools/web-fetch.js +195 -10
  420. package/dist/tools/web-search.js +458 -0
  421. package/dist/tui/agent-progress-card.js +111 -0
  422. package/dist/tui/agent-tree.js +22 -1
  423. package/dist/tui/ask-modal.js +14 -14
  424. package/dist/tui/ask-user-question-chips.js +315 -0
  425. package/dist/tui/ask-user-question-prompt.js +203 -0
  426. package/dist/tui/compact-banner.js +81 -0
  427. package/dist/tui/conversation-pane.js +85 -11
  428. package/dist/tui/cost-table.js +111 -0
  429. package/dist/tui/device-flow.js +2 -2
  430. package/dist/tui/doctor-table.js +46 -0
  431. package/dist/tui/feedback-prompt.js +156 -0
  432. package/dist/tui/input-box.js +247 -32
  433. package/dist/tui/login-picker.js +3 -3
  434. package/dist/tui/markdown-render.js +6 -6
  435. package/dist/tui/multi-file-diff-approval.js +375 -0
  436. package/dist/tui/onboarding-wizard.js +240 -0
  437. package/dist/tui/permissions-picker.js +86 -0
  438. package/dist/tui/render.js +36 -1
  439. package/dist/tui/repl-render.js +239 -25
  440. package/dist/tui/repl-splash-art.js +16 -16
  441. package/dist/tui/repl-splash-mascot.js +48 -24
  442. package/dist/tui/repl-splash.js +22 -22
  443. package/dist/tui/repl.js +125 -45
  444. package/dist/tui/slash-palette.js +6 -6
  445. package/dist/tui/splash.js +2 -2
  446. package/dist/tui/status-bar.js +109 -31
  447. package/dist/tui/status-table.js +7 -0
  448. package/dist/tui/stickers-art.js +136 -0
  449. package/dist/tui/style-table.js +28 -0
  450. package/dist/tui/theme-table.js +29 -0
  451. package/dist/tui/thinking-spinner.js +123 -0
  452. package/dist/tui/tool-stream-pane.js +53 -4
  453. package/dist/tui/update-banner.js +27 -2
  454. package/dist/tui/vim-input.js +267 -0
  455. package/dist/tui/welcome-banner.js +107 -0
  456. package/dist/tui/welcome-data.js +293 -0
  457. package/dist/tui/workspace-context.js +2 -2
  458. package/package.json +29 -6
  459. package/test/scenarios/codegen-create-file.scenario.txt +13 -0
  460. package/test/scenarios/compact-force.scenario.txt +12 -0
  461. package/test/scenarios/identity.scenario.txt +11 -0
  462. package/test/scenarios/persona-handoff.scenario.txt +12 -0
  463. package/test/scenarios/walkback.scenario.txt +12 -0
  464. package/dist/core/engine/compaction-hook.js +0 -154
@@ -1,19 +1,21 @@
1
1
  import { getJobRegistry, summarizeJobsForPrompt, } from '../jobs/registry.js';
2
+ import { compileStyleBlock } from '../output-style/presets.js';
3
+ import { resolveOutputStyle } from '../output-style/state.js';
2
4
  /**
3
5
  * System prompts for each engine command. Each prompt:
4
- * - Anchors the model in Pugi's local-first contract (ADR-0037).
5
- * - Lists the tools the model may call (the registry is authoritative,
6
- * but stating it inline prevents the model from inventing tool names
7
- * when the tool schema is large).
8
- * - Defines the deliverable shape so the model produces a useful final
9
- * text answer instead of "here is what I did".
6
+ * - Anchors the model in Pugi's local-first contract .
7
+ * - Lists the tools the model may call (the registry is authoritative,
8
+ * but stating it inline prevents the model from inventing tool names
9
+ * when the tool schema is large).
10
+ * - Defines the deliverable shape so the model produces a useful final
11
+ * text answer instead of "here is what I did".
10
12
  *
11
13
  * The prompts are intentionally terse. Per gstack `engineering-standards`
12
14
  * the persona system prompt comes from the runtime (Anvil bridge
13
15
  * prepends `oes-dev` / Sigma prompt automatically when configured); these
14
16
  * prompts ride on top and scope the model to the current command.
15
17
  *
16
- * Sprint α5.9 (ADR-0056 PR-PUGI-CLI-M1-GAP-J): the system prompt picks up
18
+ * Sprint : the system prompt picks up
17
19
  * a `BACKGROUND JOBS:` snapshot appended at the tail so the agent loop
18
20
  * knows what background bash work is currently on watch and can avoid
19
21
  * spawning a duplicate. The snapshot is sourced from `JobRegistry` and
@@ -21,31 +23,197 @@ import { getJobRegistry, summarizeJobsForPrompt, } from '../jobs/registry.js';
21
23
  */
22
24
  const COMMON_LOCAL_FIRST_PREAMBLE = [
23
25
  'You are the Pugi CLI agent running locally inside the operator\'s repository.',
24
- 'The local filesystem is the source of truth. Every change you make is committed locally; nothing is uploaded by default (ADR-0037 local-first).',
25
- // R1 fix (2026-05-26, PR #413 r1, Fix 5 Option B): only advertise the
26
- // tools currently wired in `tool-bridge.ts::WIRED_TOOLS`. α7.7 ships
26
+ 'The local filesystem is the source of truth. Every change you make is committed locally; nothing is uploaded by default .',
27
+ // R1 fix (2026-05-26, PR r1, Fix 5 Option B): only advertise the
28
+ // tools currently wired in `tool-bridge.ts::WIRED_TOOLS`. ships
27
29
  // apply_patch / lsp_* / worktree_* as CLI-only surfaces (`pugi patch`,
28
30
  // `pugi lsp`, `pugi worktree`); wiring them into the engine loop is
29
31
  // deferred to β2 (apply_patch), β4 (LSP tools), β7 (worktree tools)
30
32
  // per the consolidated sprint plan. Advertising them in the system
31
- // prompt without a matching executor entry caused Mira to attempt
33
+ // prompt without a matching executor entry caused Pugi to attempt
32
34
  // calls that returned `unknown_tool` — broken eval surface.
33
35
  'You have a tool registry: read, write, edit, grep, glob, bash. Call tools to inspect and modify the workspace.',
34
36
  'Cite file paths relative to the workspace root. Keep edits minimal and reversible.',
35
37
  'When you are done, return a single final text answer that the operator can read on the CLI.',
36
38
  ].join(' ');
39
+ /**
40
+ * PR I (2026-06-05) — locale + currency defaults for customer apps.
41
+ *
42
+ * CEO 2026-06-05 escalation: Pugi customer asked "lets build pizza
43
+ * finder in react" (English-ish brief but conversation was Russian).
44
+ * Hiroshi shipped а Russian UI с ₽ rubles без asking, projecting
45
+ * the chat language onto the target market. Pugi is global-product
46
+ * positioning — defaulting к ₽+RU из-за chat language limits the
47
+ * generated app's market reach by default.
48
+ *
49
+ * Rule (CEO confirmed clarification: «по умолчанию доллары»):
50
+ *
51
+ * When generating customer-facing UI:
52
+ * - Currency default = USD unless operator brief explicitly named другое
53
+ * - UI language default = English unless operator brief explicitly named другое
54
+ * - Locale default = en-US
55
+ *
56
+ * Operator's CHAT language ≠ target market language. A Russian
57
+ * brief asking for "pizza finder" does NOT imply RU+₽ — it just
58
+ * means the operator speaks Russian. Default to USD+English and
59
+ * ask one clarifying question if the brief is ambiguous about
60
+ * the target market.
61
+ *
62
+ * Memory pointer: `feedback_default_no_rubles_ask_language.md`.
63
+ */
64
+ const CUSTOMER_APP_DEFAULTS = [
65
+ '# Customer app defaults',
66
+ 'When generating a customer-facing UI app that needs currency or locale-aware text:',
67
+ ' - Currency: default to USD ($) unless the operator brief explicitly named another currency.',
68
+ ' - UI language: default to English unless the operator brief explicitly named another language.',
69
+ ' - Locale: default to en-US for date/number formatting unless overridden.',
70
+ 'The operator\'s CHAT language is NOT the target market language. A brief sent in Russian or Ukrainian does NOT imply the generated app should ship in Russian / Ukrainian / ₽ / ₴. If the target market is ambiguous, ask one clarifying question OR ship the USD + English default and surface the choice in your final answer so the operator can override.',
71
+ ].join('\n');
72
+ /**
73
+ * PR N (2026-06-05) - simplicity criterion for customer apps (task #112).
74
+ *
75
+ * Hiroshi (dev persona) tends к overengineer customer apps. The
76
+ * Pizza Finder dogfood demo shipped 8 features + multi-filter UI
77
+ * when "MVP" would have been 3 pizzas + name search. CEO directive
78
+ * 2026-06-05: bake a simplicity criterion into the code/build
79
+ * prompt so the first turn ships the smallest shape that proves
80
+ * the brief.
81
+ *
82
+ * Pattern reference: Karpathy speedrun (smallest end-to-end loop
83
+ * first, then add capacity). Shipping the maximalist version on
84
+ * turn 1 wastes tokens AND makes the demo harder к reason about;
85
+ * ship the simplest shape, ask "want me to add X next?" only if
86
+ * context strongly hints the brief implies it.
87
+ *
88
+ * Memory pointer: backlog task #112 (P1, Simplicity criterion baked
89
+ * into Hiroshi system prompt).
90
+ */
91
+ const SIMPLICITY_CRITERION = [
92
+ '# Simplicity criterion',
93
+ 'When implementing a customer feature, default to the SIMPLEST shape that proves the brief:',
94
+ ' - Prefer 3 sample items over 8. Operator can ask for more.',
95
+ ' - Prefer 1 filter over 5. Operator can ask for more.',
96
+ ' - Prefer 1 sort option over 3. Operator can ask for more.',
97
+ ' - Hardcoded data over fetching, until the operator names a backend.',
98
+ ' - Inline CSS over Tailwind / library imports, for single-file demos.',
99
+ ' - Single file over multi-file, until the operator names structure.',
100
+ 'The brief tells you WHAT to build. The operator\'s NEXT brief tells you HOW MUCH to add. Shipping the maximalist version on turn 1 wastes tokens AND makes the demo harder to reason about. Ship the simplest shape; ask "want me to add X next?" only if context strongly hints the brief implies it.',
101
+ ].join('\n');
102
+ /**
103
+ * PR I (2026-06-05) — server-kill guidance.
104
+ *
105
+ * Same dogfood session: Hiroshi launched а Vite dev server via
106
+ * `server_start` (PID 45800 on :5173) and told the operator
107
+ * "use `pugi stop` or kill pid 45800". `/stop <persona>` halts
108
+ * persona agents — NOT spawned server processes. The customer
109
+ * tried `pugi stop`, нічого не сталося, the server kept running.
110
+ *
111
+ * PR H shipped the actual fix (`/servers stop ...` slash command).
112
+ * This prompt block teaches Hiroshi to recommend the correct
113
+ * surface so the next dogfood session does not repeat the bug.
114
+ */
115
+ const SERVER_KILL_HINT = [
116
+ '# Server lifecycle hint',
117
+ 'When you start a dev server via the `server_start` tool, your final answer SHOULD include the exact way to stop it:',
118
+ ' - From the Pugi REPL: `/servers` to list, `/servers stop <runId>` or `/servers stop all` to kill.',
119
+ ' - From a shell: `kill <pid>` (the pid is in the `server_start` result).',
120
+ 'DO NOT suggest `pugi stop` for server termination. `pugi stop <persona>` halts a persona agent, not a spawned server process — recommending it has historically misled operators into thinking nothing works.',
121
+ ].join('\n');
122
+ /**
123
+ * β5a P1+P6 : prompt v2 — intent marker contract +
124
+ * definitional examples + jargon ban. Fixes the dominant Pugi loss
125
+ * mode in the .X Phase 2 comparative eval: tool-use on pure
126
+ * knowledge questions ("What is grep?" → bash man grep).
127
+ *
128
+ * The CLI-side `classifyIntent` (apps/pugi-cli/src/core/engine/intent.ts)
129
+ * wraps definitional questions with `<intent kind="definitional">` on
130
+ * the user message before send. The rules below teach the model what
131
+ * to do with that marker.
132
+ *
133
+ * Voice constraint: same banned-jargon list as the cabinet Pugi
134
+ * persona (брифую / диспатчу / шипаю and the English jargon list
135
+ * from BANNED_WORDS in pugi.system-prompt.ts). Repeated here verbatim
136
+ * so the CLI surface has its own enforcement copy; the cabinet copy
137
+ * is the source of truth and ships through the runtime persona
138
+ * prompt for the cabinet UI. CLI runs DO NOT load the cabinet
139
+ * persona prompt — engine prompts are the only place to enforce
140
+ * voice for `pugi explain` / `pugi code` callers.
141
+ */
142
+ const INTENT_MARKER_CONTRACT = [
143
+ '# Intent contract',
144
+ 'When the operator\'s message starts with `<intent kind="definitional">`, treat it as a knowledge question:',
145
+ ' - Answer in prose. Do NOT call any tools.',
146
+ ' - Cite a file from the repo only when it directly supports the explanation.',
147
+ ' - Keep the answer to one short paragraph unless the operator asked for depth.',
148
+ 'When no intent marker is present OR the marker is operational, use tools as needed.',
149
+ '',
150
+ '# Definitional examples',
151
+ 'Operator: `<intent kind="definitional">What is grep?</intent>`',
152
+ 'You: `grep is a Unix command-line tool that searches plain text for lines matching a regular expression. It reads stdin or files and prints matching lines to stdout.`',
153
+ '(No tool calls. One paragraph. No file paths because grep is a generic Unix tool, not a repo artefact.)',
154
+ '',
155
+ 'Operator: `<intent kind="definitional">что такое pgvector?</intent>`',
156
+ 'You: `pgvector - это расширение PostgreSQL для хранения и поиска векторных эмбеддингов. Поддерживает ivfflat и hnsw индексы; используется для RAG и semantic search.`',
157
+ '(One short paragraph. No tools.)',
158
+ ].join('\n');
159
+ const JARGON_BAN = [
160
+ '# Voice',
161
+ 'Brand voice: terse, operator-grade, English in code paths / Russian-Ukrainian permitted in chat answers.',
162
+ 'Banned words (CLI customer-facing output): "брифую", "диспатчу", "шипаю", "journey", "explore", "delight", "magical", "friendly", "let me help", "I\'d be happy to", "pug-tastic". Use neutral verbs instead: brief / dispatch / ship / build / read / write.',
163
+ 'No em-dashes. No emoji. No "AI assistant" framing.',
164
+ ].join('\n');
165
+ const PROMPT_V2_APPENDIX = [INTENT_MARKER_CONTRACT, JARGON_BAN].join('\n\n');
37
166
  const PLAN_TOOLS_NOTE = 'PLAN MODE IS READ-ONLY. You may call read, grep, glob. Calls to write, edit, or bash will be refused and end the run. Produce a written plan, not changes.';
38
167
  const EDIT_FLOW_RULES = [
39
168
  'Before calling edit on a file you have not yet read this session, call read first — the edit tool fails otherwise.',
40
169
  'Prefer edit over write when changing existing files; write only for newly created files.',
41
170
  'After your last tool call, summarise what you changed and what the operator should review.',
171
+ // Backlog — Layer A.5 fuzzy ladder advisory. The operator may
172
+ // have run with `--fuzzy-edits`; the ladder is invisible to the
173
+ // model but the model should still anchor its SEARCH blocks on
174
+ // verbatim source when possible. Ellipsis is the only relaxation
175
+ // we want the model к reach for explicitly; whitespace + edit-
176
+ // distance fire automatically and silently when they're needed.
177
+ 'If exact SEARCH match fails, the dispatcher may retry with a fuzzy ladder (whitespace-flex → ellipsis → 0.8 edit-distance). Prefer exact match; use `...` ellipsis only when you explicitly need to skip a long unchanged middle.',
42
178
  ].join(' ');
43
179
  export function systemPromptFor(kind) {
44
180
  const base = baseSystemPromptFor(kind);
181
+ // β5a P1+P6: append the prompt-v2 intent-marker contract +
182
+ // definitional examples + jargon ban to every command kind. The
183
+ // appendix is shared across kinds because the marker contract +
184
+ // voice gate are command-agnostic — a definitional question lands
185
+ // the same way under `pugi explain` and `pugi code`.
186
+ const withV2 = `${base}\n\n${PROMPT_V2_APPENDIX}`;
187
+ // output-style preset block. Compiled from
188
+ // workspace > user > default precedence. The `default` preset
189
+ // returns an empty block (no override over the base voice), so the
190
+ // injection is a no-op for the most-common case. Wrapped in
191
+ // try/catch — every IO failure inside `resolveOutputStyle` already
192
+ // degrades to the default slug, but defence in depth keeps the
193
+ // engine prompt assembly from ever crashing on a hand-edited
194
+ // config.json.
195
+ const styleBlock = formatOutputStyleBlock();
196
+ const withStyle = styleBlock ? `${withV2}\n\n${styleBlock}` : withV2;
45
197
  const snapshot = formatBackgroundJobsSnapshot(getJobRegistrySafely());
46
198
  if (!snapshot)
47
- return base;
48
- return `${base}\n\n${snapshot}`;
199
+ return withStyle;
200
+ return `${withStyle}\n\n${snapshot}`;
201
+ }
202
+ /**
203
+ * Resolve the active output-style preset for the current process
204
+ * and compile it into a prompt block. Returns empty string for the
205
+ * default preset OR for any unexpected IO failure so the engine
206
+ * prompt assembly path is unaffected by a missing / malformed
207
+ * config.json.
208
+ */
209
+ function formatOutputStyleBlock() {
210
+ try {
211
+ const resolved = resolveOutputStyle({ workspaceRoot: process.cwd() });
212
+ return compileStyleBlock(resolved.slug);
213
+ }
214
+ catch {
215
+ return '';
216
+ }
49
217
  }
50
218
  function baseSystemPromptFor(kind) {
51
219
  switch (kind) {
@@ -54,6 +222,9 @@ function baseSystemPromptFor(kind) {
54
222
  COMMON_LOCAL_FIRST_PREAMBLE,
55
223
  'Command: `pugi code`. The operator gave you a feature request or refactor. Implement it end-to-end.',
56
224
  EDIT_FLOW_RULES,
225
+ CUSTOMER_APP_DEFAULTS,
226
+ SIMPLICITY_CRITERION,
227
+ SERVER_KILL_HINT,
57
228
  'If the request is ambiguous, ask one clarifying question by returning a text answer instead of editing.',
58
229
  ].join('\n\n');
59
230
  case 'explain':
@@ -68,6 +239,7 @@ function baseSystemPromptFor(kind) {
68
239
  COMMON_LOCAL_FIRST_PREAMBLE,
69
240
  'Command: `pugi fix`. The operator gave you a bug report or failing test. Investigate the root cause first, then apply the smallest patch that fixes it.',
70
241
  EDIT_FLOW_RULES,
242
+ SERVER_KILL_HINT,
71
243
  'Surface the root cause in your final answer so the operator can verify the diagnosis is correct.',
72
244
  ].join('\n\n');
73
245
  case 'plan':
@@ -82,6 +254,9 @@ function baseSystemPromptFor(kind) {
82
254
  COMMON_LOCAL_FIRST_PREAMBLE,
83
255
  'Command: `pugi build`. The operator wants you to scaffold a feature across multiple files.',
84
256
  EDIT_FLOW_RULES,
257
+ CUSTOMER_APP_DEFAULTS,
258
+ SIMPLICITY_CRITERION,
259
+ SERVER_KILL_HINT,
85
260
  'Group related edits, run lint/test via bash where it adds confidence, and list every file you created or modified in the final answer.',
86
261
  ].join('\n\n');
87
262
  }
@@ -115,12 +290,37 @@ function getJobRegistrySafely() {
115
290
  }
116
291
  }
117
292
  /**
118
- * Anvil persona slug to invoke per command. Today every command routes
119
- * to `oes-dev` (Sigma) — the Tier-2 reviewer persona already configured
120
- * for Pugi runtime work. When we add per-command personas (e.g. `pugi-
121
- * planner`, `pugi-coder`) this is the single switch to update.
293
+ * Anvil persona slug to invoke per command. Routes each engine command
294
+ * to the appropriate Tier-1 persona from PERSONA_REGISTRY (admin-api/
295
+ * src/pugi-runtime/personas/persona-dispatch.ts):
296
+ *
297
+ * - code / fix / build → 'dev' (Hiroshi, coder, Sonnet codegen tag)
298
+ * - plan → 'architect' (Marcus, architect, Sonnet reason)
299
+ * - explain → 'main' (Pugi orchestrator, DeepSeek reason)
300
+ *
301
+ * Previously this returned 'oes-dev' unconditionally — that is an OES
302
+ * C++ reviewer persona, wrong tool set + wrong system prompt for
303
+ * customer dispatches. CEO live trace #53.
304
+ *
305
+ * Operator override: PUGI_ENGINE_PERSONA_<COMMAND> env (e.g.
306
+ * PUGI_ENGINE_PERSONA_CODE=frontend pins Mia for the next dispatch).
122
307
  */
123
- export function personaSlugFor(_kind) {
124
- return 'oes-dev';
308
+ export function personaSlugFor(kind) {
309
+ const envKey = `PUGI_ENGINE_PERSONA_${kind.toUpperCase()}`;
310
+ const override = process.env[envKey];
311
+ if (override && override.length > 0)
312
+ return override;
313
+ switch (kind) {
314
+ case 'code':
315
+ case 'fix':
316
+ case 'build':
317
+ return 'dev';
318
+ case 'plan':
319
+ return 'architect';
320
+ case 'explain':
321
+ return 'main';
322
+ default:
323
+ return 'main';
324
+ }
125
325
  }
126
326
  //# sourceMappingURL=prompts.js.map
@@ -0,0 +1,124 @@
1
+ /**
2
+ * L3 — leak-parity: underscore-prefix internal-fields filter.
3
+ *
4
+ * The convention (observed in the leaked the upstream tool BashTool surface and
5
+ * codified in `docs/research/2026-05-27-pugi-.md` §1)
6
+ * is that tool-argument fields whose names start with a leading underscore
7
+ * are INTERNAL — populated by the dispatcher at call time (sessionId,
8
+ * tenantId, correlation handles, hook context, ask-modal bridge handles)
9
+ * but never advertised to the model. The model schema MUST omit them so:
10
+ *
11
+ * 1. No token cost — internal context never burns model budget.
12
+ * 2. No fabrication risk — the model cannot hallucinate values for
13
+ * sessionId / tenantId / etc. because the field is invisible.
14
+ * 3. No leak surface — implementation detail stays implementation detail.
15
+ *
16
+ * The dispatcher (see `tool-bridge.ts::buildExecutor`) does NOT strip these
17
+ * fields at call time. It passes the full args record (including any
18
+ * `_internal*` keys an upstream layer injected) straight to the tool
19
+ * handler. Only the schema surface that the engine adapter ships to the
20
+ * model is filtered.
21
+ *
22
+ * This module is intentionally narrow: it accepts a JSON Schema fragment
23
+ * and returns a deep clone with `_`-prefixed keys removed from every
24
+ * `properties` map encountered while walking, and with `required` filtered
25
+ * to drop any references to those keys. It descends into nested object
26
+ * schemas and into the `items` schema of arrays. It is JSON-Schema-version
27
+ * agnostic (works on draft-07, 2019-09, 2020-12 alike) because it only
28
+ * inspects `properties`/`required`/`items` and leaves the rest of the
29
+ * fragment alone.
30
+ *
31
+ * Edge cases handled:
32
+ * - `_` alone (single underscore) is treated as internal and stripped.
33
+ * - Nested object schemas inside `properties` get the same treatment
34
+ * (a sub-property whose name starts with `_` is removed too).
35
+ * - Array `items` are walked. Tuple schemas (`items` as array) are
36
+ * walked element-by-element.
37
+ * - `oneOf`/`anyOf`/`allOf` branches are walked.
38
+ * - Non-object inputs (null, primitives, arrays passed as the root)
39
+ * are returned as-is — defensive no-op, never throws.
40
+ *
41
+ * Contract notes:
42
+ * - Pure function. Input is never mutated.
43
+ * - Output is a deep clone — every nested object/array is freshly
44
+ * allocated so callers can mutate safely.
45
+ * - JSON-only — does not preserve symbols, getters, or class instances
46
+ * because JSON Schema is plain-data by spec.
47
+ */
48
+ const INTERNAL_PREFIX = '_';
49
+ /**
50
+ * Returns true when the field name should be stripped from the model-
51
+ * facing schema. Leading underscore is the contract — single `_` is also
52
+ * stripped (no escape hatch). Empty-string keys (which are technically
53
+ * valid JSON) are left alone so we do not silently drop them.
54
+ */
55
+ export function isInternalFieldName(name) {
56
+ return name.length > 0 && name.startsWith(INTERNAL_PREFIX);
57
+ }
58
+ /**
59
+ * Strip `_`-prefixed properties from a JSON Schema fragment. Recursively
60
+ * walks nested object schemas and array `items`. Returns a deep clone;
61
+ * the input is never mutated.
62
+ *
63
+ * Pass-through behaviour:
64
+ * - Non-object / null / array inputs round-trip unchanged (as deep
65
+ * clones where applicable).
66
+ * - Fragments with no `properties` key are returned as deep clones
67
+ * after walking `items`/`oneOf`/`anyOf`/`allOf`.
68
+ */
69
+ export function stripInternalFields(schema) {
70
+ if (schema === null || typeof schema !== 'object')
71
+ return schema;
72
+ if (Array.isArray(schema)) {
73
+ return schema.map((item) => stripInternalFields(item));
74
+ }
75
+ return walkObject(schema);
76
+ }
77
+ function walkObject(node) {
78
+ const out = {};
79
+ for (const [key, value] of Object.entries(node)) {
80
+ if (key === 'properties' && value !== null && typeof value === 'object' && !Array.isArray(value)) {
81
+ out[key] = walkProperties(value);
82
+ continue;
83
+ }
84
+ if (key === 'required' && Array.isArray(value)) {
85
+ out[key] = value.filter((entry) => typeof entry === 'string' && !isInternalFieldName(entry));
86
+ continue;
87
+ }
88
+ if (key === 'items') {
89
+ out[key] = stripInternalFields(value);
90
+ continue;
91
+ }
92
+ if (key === 'oneOf' || key === 'anyOf' || key === 'allOf') {
93
+ if (Array.isArray(value)) {
94
+ out[key] = value.map((branch) => stripInternalFields(branch));
95
+ continue;
96
+ }
97
+ }
98
+ // Default: deep-clone any nested objects/arrays so the caller can
99
+ // mutate freely without touching the input. Primitives pass through.
100
+ out[key] = cloneJson(value);
101
+ }
102
+ return out;
103
+ }
104
+ function walkProperties(props) {
105
+ const out = {};
106
+ for (const [propName, propSchema] of Object.entries(props)) {
107
+ if (isInternalFieldName(propName))
108
+ continue;
109
+ out[propName] = stripInternalFields(propSchema);
110
+ }
111
+ return out;
112
+ }
113
+ function cloneJson(value) {
114
+ if (value === null || typeof value !== 'object')
115
+ return value;
116
+ if (Array.isArray(value))
117
+ return value.map((item) => cloneJson(item));
118
+ const out = {};
119
+ for (const [key, val] of Object.entries(value)) {
120
+ out[key] = cloneJson(val);
121
+ }
122
+ return out;
123
+ }
124
+ //# sourceMappingURL=strip-internal-fields.js.map