@open-mercato/cezar 0.1.5-pr506.357

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 (264) hide show
  1. package/README.md +573 -0
  2. package/dist/config.d.ts +144 -0
  3. package/dist/config.js +106 -0
  4. package/dist/config.js.map +1 -0
  5. package/dist/core/agent-runner.d.ts +169 -0
  6. package/dist/core/agent-runner.js +23 -0
  7. package/dist/core/agent-runner.js.map +1 -0
  8. package/dist/core/backend-detect.d.ts +16 -0
  9. package/dist/core/backend-detect.js +118 -0
  10. package/dist/core/backend-detect.js.map +1 -0
  11. package/dist/core/claude-cli-runner.d.ts +56 -0
  12. package/dist/core/claude-cli-runner.js +416 -0
  13. package/dist/core/claude-cli-runner.js.map +1 -0
  14. package/dist/core/claude-ui-mapper.d.ts +71 -0
  15. package/dist/core/claude-ui-mapper.js +567 -0
  16. package/dist/core/claude-ui-mapper.js.map +1 -0
  17. package/dist/core/codex-app-server-runner.d.ts +29 -0
  18. package/dist/core/codex-app-server-runner.js +489 -0
  19. package/dist/core/codex-app-server-runner.js.map +1 -0
  20. package/dist/core/codex-ui-mapper.d.ts +63 -0
  21. package/dist/core/codex-ui-mapper.js +491 -0
  22. package/dist/core/codex-ui-mapper.js.map +1 -0
  23. package/dist/core/ndjson.d.ts +6 -0
  24. package/dist/core/ndjson.js +23 -0
  25. package/dist/core/ndjson.js.map +1 -0
  26. package/dist/core/opencode-server-runner.d.ts +30 -0
  27. package/dist/core/opencode-server-runner.js +488 -0
  28. package/dist/core/opencode-server-runner.js.map +1 -0
  29. package/dist/core/opencode-ui-mapper.d.ts +105 -0
  30. package/dist/core/opencode-ui-mapper.js +588 -0
  31. package/dist/core/opencode-ui-mapper.js.map +1 -0
  32. package/dist/core/process-usage.d.ts +63 -0
  33. package/dist/core/process-usage.js +181 -0
  34. package/dist/core/process-usage.js.map +1 -0
  35. package/dist/core/runner-factory.d.ts +8 -0
  36. package/dist/core/runner-factory.js +22 -0
  37. package/dist/core/runner-factory.js.map +1 -0
  38. package/dist/core/tool-display.d.ts +30 -0
  39. package/dist/core/tool-display.js +156 -0
  40. package/dist/core/tool-display.js.map +1 -0
  41. package/dist/core/ui-events.d.ts +308 -0
  42. package/dist/core/ui-events.js +25 -0
  43. package/dist/core/ui-events.js.map +1 -0
  44. package/dist/core/usage.d.ts +11 -0
  45. package/dist/core/usage.js +15 -0
  46. package/dist/core/usage.js.map +1 -0
  47. package/dist/git-worktree.d.ts +88 -0
  48. package/dist/git-worktree.js +297 -0
  49. package/dist/git-worktree.js.map +1 -0
  50. package/dist/handoff.d.ts +62 -0
  51. package/dist/handoff.js +147 -0
  52. package/dist/handoff.js.map +1 -0
  53. package/dist/index.d.ts +2 -0
  54. package/dist/index.js +466 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/install-as-command.d.ts +39 -0
  57. package/dist/install-as-command.js +51 -0
  58. package/dist/install-as-command.js.map +1 -0
  59. package/dist/pack-check.d.ts +17 -0
  60. package/dist/pack-check.js +27 -0
  61. package/dist/pack-check.js.map +1 -0
  62. package/dist/paths.d.ts +23 -0
  63. package/dist/paths.js +34 -0
  64. package/dist/paths.js.map +1 -0
  65. package/dist/planner.d.ts +17 -0
  66. package/dist/planner.js +248 -0
  67. package/dist/planner.js.map +1 -0
  68. package/dist/release/snapshot.d.ts +64 -0
  69. package/dist/release/snapshot.js +75 -0
  70. package/dist/release/snapshot.js.map +1 -0
  71. package/dist/release/stable.d.ts +46 -0
  72. package/dist/release/stable.js +57 -0
  73. package/dist/release/stable.js.map +1 -0
  74. package/dist/runs/auto-name.d.ts +75 -0
  75. package/dist/runs/auto-name.js +168 -0
  76. package/dist/runs/auto-name.js.map +1 -0
  77. package/dist/runs/retention.d.ts +60 -0
  78. package/dist/runs/retention.js +86 -0
  79. package/dist/runs/retention.js.map +1 -0
  80. package/dist/runs/review-gate.d.ts +18 -0
  81. package/dist/runs/review-gate.js +21 -0
  82. package/dist/runs/review-gate.js.map +1 -0
  83. package/dist/runs/store.d.ts +408 -0
  84. package/dist/runs/store.js +526 -0
  85. package/dist/runs/store.js.map +1 -0
  86. package/dist/runs/task-refs.d.ts +24 -0
  87. package/dist/runs/task-refs.js +74 -0
  88. package/dist/runs/task-refs.js.map +1 -0
  89. package/dist/runs/ui-event-sink.d.ts +81 -0
  90. package/dist/runs/ui-event-sink.js +210 -0
  91. package/dist/runs/ui-event-sink.js.map +1 -0
  92. package/dist/server/capabilities.d.ts +33 -0
  93. package/dist/server/capabilities.js +43 -0
  94. package/dist/server/capabilities.js.map +1 -0
  95. package/dist/server/forge/github.d.ts +70 -0
  96. package/dist/server/forge/github.js +375 -0
  97. package/dist/server/forge/github.js.map +1 -0
  98. package/dist/server/forge/index.d.ts +24 -0
  99. package/dist/server/forge/index.js +45 -0
  100. package/dist/server/forge/index.js.map +1 -0
  101. package/dist/server/forge/types.d.ts +80 -0
  102. package/dist/server/forge/types.js +2 -0
  103. package/dist/server/forge/types.js.map +1 -0
  104. package/dist/server/git-changes.d.ts +195 -0
  105. package/dist/server/git-changes.js +497 -0
  106. package/dist/server/git-changes.js.map +1 -0
  107. package/dist/server/git.d.ts +26 -0
  108. package/dist/server/git.js +103 -0
  109. package/dist/server/git.js.map +1 -0
  110. package/dist/server/github.d.ts +8 -0
  111. package/dist/server/github.js +8 -0
  112. package/dist/server/github.js.map +1 -0
  113. package/dist/server/launch-key.d.ts +7 -0
  114. package/dist/server/launch-key.js +33 -0
  115. package/dist/server/launch-key.js.map +1 -0
  116. package/dist/server/open-in-app.d.ts +51 -0
  117. package/dist/server/open-in-app.js +189 -0
  118. package/dist/server/open-in-app.js.map +1 -0
  119. package/dist/server/open-in-terminal.d.ts +25 -0
  120. package/dist/server/open-in-terminal.js +120 -0
  121. package/dist/server/open-in-terminal.js.map +1 -0
  122. package/dist/server/pr.d.ts +7 -0
  123. package/dist/server/pr.js +7 -0
  124. package/dist/server/pr.js.map +1 -0
  125. package/dist/server/server.d.ts +41 -0
  126. package/dist/server/server.js +1390 -0
  127. package/dist/server/server.js.map +1 -0
  128. package/dist/server/static-ui.d.ts +49 -0
  129. package/dist/server/static-ui.js +92 -0
  130. package/dist/server/static-ui.js.map +1 -0
  131. package/dist/server/wsl.d.ts +25 -0
  132. package/dist/server/wsl.js +92 -0
  133. package/dist/server/wsl.js.map +1 -0
  134. package/dist/server-install/engine.d.ts +33 -0
  135. package/dist/server-install/engine.js +314 -0
  136. package/dist/server-install/engine.js.map +1 -0
  137. package/dist/server-install/platforms/macosx-ngrok.d.ts +6 -0
  138. package/dist/server-install/platforms/macosx-ngrok.js +345 -0
  139. package/dist/server-install/platforms/macosx-ngrok.js.map +1 -0
  140. package/dist/server-install/platforms/ubuntu-vps.d.ts +39 -0
  141. package/dist/server-install/platforms/ubuntu-vps.js +746 -0
  142. package/dist/server-install/platforms/ubuntu-vps.js.map +1 -0
  143. package/dist/server-install/state.d.ts +26 -0
  144. package/dist/server-install/state.js +125 -0
  145. package/dist/server-install/state.js.map +1 -0
  146. package/dist/server-install/steps.d.ts +109 -0
  147. package/dist/server-install/steps.js +330 -0
  148. package/dist/server-install/steps.js.map +1 -0
  149. package/dist/server-install/strategies.d.ts +4 -0
  150. package/dist/server-install/strategies.js +20 -0
  151. package/dist/server-install/strategies.js.map +1 -0
  152. package/dist/server-install/types.d.ts +597 -0
  153. package/dist/server-install/types.js +98 -0
  154. package/dist/server-install/types.js.map +1 -0
  155. package/dist/server-install/ui.d.ts +42 -0
  156. package/dist/server-install/ui.js +130 -0
  157. package/dist/server-install/ui.js.map +1 -0
  158. package/dist/skills-banner.d.ts +21 -0
  159. package/dist/skills-banner.js +40 -0
  160. package/dist/skills-banner.js.map +1 -0
  161. package/dist/skills-remote.d.ts +35 -0
  162. package/dist/skills-remote.js +266 -0
  163. package/dist/skills-remote.js.map +1 -0
  164. package/dist/skills.d.ts +45 -0
  165. package/dist/skills.js +182 -0
  166. package/dist/skills.js.map +1 -0
  167. package/dist/todos.d.ts +63 -0
  168. package/dist/todos.js +168 -0
  169. package/dist/todos.js.map +1 -0
  170. package/dist/ui-state.d.ts +12 -0
  171. package/dist/ui-state.js +25 -0
  172. package/dist/ui-state.js.map +1 -0
  173. package/dist/update-check.d.ts +12 -0
  174. package/dist/update-check.js +41 -0
  175. package/dist/update-check.js.map +1 -0
  176. package/dist/workflows/load.d.ts +15 -0
  177. package/dist/workflows/load.js +56 -0
  178. package/dist/workflows/load.js.map +1 -0
  179. package/dist/workflows/run.d.ts +281 -0
  180. package/dist/workflows/run.js +1511 -0
  181. package/dist/workflows/run.js.map +1 -0
  182. package/dist/workflows/types.d.ts +307 -0
  183. package/dist/workflows/types.js +171 -0
  184. package/dist/workflows/types.js.map +1 -0
  185. package/package.json +90 -0
  186. package/scripts/check-pack.mjs +46 -0
  187. package/scripts/dev.mjs +74 -0
  188. package/scripts/install-as-command.mjs +120 -0
  189. package/scripts/mock-claude.mjs +310 -0
  190. package/scripts/release-snapshot.mjs +130 -0
  191. package/scripts/release.mjs +119 -0
  192. package/scripts/test-process-usage.mjs +47 -0
  193. package/web/dist/assets/arrow-left-BE957rJs.js +1 -0
  194. package/web/dist/assets/bundle-mjs-DLPpRFyl.js +1 -0
  195. package/web/dist/assets/centered-state-BddhEEtO.js +43 -0
  196. package/web/dist/assets/chunk-BO2N2NFS-f5igTtpB.js +131 -0
  197. package/web/dist/assets/command-CjhFbABo.js +1 -0
  198. package/web/dist/assets/compare-variants-Cs52IAEG.js +1 -0
  199. package/web/dist/assets/core-BuMqAF_1.js +12 -0
  200. package/web/dist/assets/css-BsVw1vtW.js +1 -0
  201. package/web/dist/assets/dialog-DFvXTkFv.js +1 -0
  202. package/web/dist/assets/diff-view-C9b8AITq.js +4 -0
  203. package/web/dist/assets/diff-woXpYk--.js +1 -0
  204. package/web/dist/assets/dist-FBs4wmIY.js +1 -0
  205. package/web/dist/assets/dist-o_kVMXjg.js +1 -0
  206. package/web/dist/assets/engine-javascript-FQvzRocB.js +141 -0
  207. package/web/dist/assets/file-BVuztAOd.js +1 -0
  208. package/web/dist/assets/folder-0pJ1NZ_S.js +1 -0
  209. package/web/dist/assets/git-pull-request-DJkAMT0f.js +1 -0
  210. package/web/dist/assets/git-toolbar-CwhQdx3J.js +1 -0
  211. package/web/dist/assets/github-D0rAX4-r.js +1 -0
  212. package/web/dist/assets/go-rLFTqkRN.js +1 -0
  213. package/web/dist/assets/highlighted-body-OFNGDK62-DGHHie_q.js +1 -0
  214. package/web/dist/assets/highlighter-BKVEsACy.js +3 -0
  215. package/web/dist/assets/html-BY76lXLH.js +1 -0
  216. package/web/dist/assets/index-CEkI7QxN.css +2 -0
  217. package/web/dist/assets/index-CO2lH2et.js +11 -0
  218. package/web/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  219. package/web/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  220. package/web/dist/assets/javascript-BgS3c2Ky.js +1 -0
  221. package/web/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  222. package/web/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  223. package/web/dist/assets/json-qhed-kSA.js +1 -0
  224. package/web/dist/assets/jsonc-CYpm1nAK.js +1 -0
  225. package/web/dist/assets/jsx-Bz0zcwM4.js +1 -0
  226. package/web/dist/assets/lib-CNGa3Dig.js +1 -0
  227. package/web/dist/assets/loader-circle-BV3DO9mE.js +1 -0
  228. package/web/dist/assets/markdown-BYOwaDjH.js +1 -0
  229. package/web/dist/assets/markdown-D4-ADgH9.js +1 -0
  230. package/web/dist/assets/mermaid-GHXKKRXX-DM2VsGBG.js +1 -0
  231. package/web/dist/assets/open-mercato-toBr6SOa.svg +11 -0
  232. package/web/dist/assets/prompt-templates-C7ptKvDd.js +15 -0
  233. package/web/dist/assets/python-gzcpVVnB.js +1 -0
  234. package/web/dist/assets/react-dom-Ddtik4qM.js +1 -0
  235. package/web/dist/assets/refresh-cw-DCa-Rlwz.js +1 -0
  236. package/web/dist/assets/repo-git-DIhryGDx.js +1 -0
  237. package/web/dist/assets/run-diff-Dyow8B1q.js +3 -0
  238. package/web/dist/assets/run-header-jx9-18b8.js +1 -0
  239. package/web/dist/assets/rust-Cfkwpbl8.js +1 -0
  240. package/web/dist/assets/search-x-CoCyl7zT.js +1 -0
  241. package/web/dist/assets/shellscript-CLZ0U2zV.js +1 -0
  242. package/web/dist/assets/skill-detail-DB7x_FQp.js +1 -0
  243. package/web/dist/assets/skills-98vCroU8.js +1 -0
  244. package/web/dist/assets/skills-BKIoqD6K.js +1 -0
  245. package/web/dist/assets/sql-BsFa4tDR.js +1 -0
  246. package/web/dist/assets/square-terminal-B6PZX4Qp.js +1 -0
  247. package/web/dist/assets/tab-link-C5--YMQd.js +1 -0
  248. package/web/dist/assets/task-changes-ejxPGVJw.js +1 -0
  249. package/web/dist/assets/task-commits-C6GO5qT-.js +1 -0
  250. package/web/dist/assets/task-files-CatpCBXa.js +2 -0
  251. package/web/dist/assets/task-thread-BMbXDM3d.js +5 -0
  252. package/web/dist/assets/tasks-table-dgezlCcg.js +1 -0
  253. package/web/dist/assets/trash-2-CDtxmmc8.js +1 -0
  254. package/web/dist/assets/triangle-alert-6su4Js5O.js +1 -0
  255. package/web/dist/assets/tsx-udAQXfEw.js +1 -0
  256. package/web/dist/assets/typescript-bsJCZSQ-.js +1 -0
  257. package/web/dist/assets/upload-Bp7hQxll.js +1 -0
  258. package/web/dist/assets/use-desktop-CvTwojOJ.js +3 -0
  259. package/web/dist/assets/utils-rQGbOrwc.js +1 -0
  260. package/web/dist/assets/workflows-Dy2c6790.js +11 -0
  261. package/web/dist/assets/x-Br_jIDBw.js +1 -0
  262. package/web/dist/assets/yaml-rwi0_p6S.js +1 -0
  263. package/web/dist/index.html +70 -0
  264. package/web/open-mercato.svg +11 -0
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Per-user cezar home. Literal `~/.cezar` on every platform (no XDG, no
3
+ * `%LOCALAPPDATA%` branch) — one rule, and it matches how the existing cache
4
+ * path already behaves (`skills-remote.ts` hardcodes `~/.cache/cez`).
5
+ *
6
+ * `CEZ_HOME` overrides the base so tests (and containers) never touch a real
7
+ * home dir. This is the first shared home-path helper in the repo; two other
8
+ * 2026-07-16 specs (multi-project-switcher, agent-config-files) extend it —
9
+ * first writer owns the file, later specs import it. Do not duplicate this
10
+ * homedir logic elsewhere.
11
+ */
12
+ export declare function cezarHomeDir(): string;
13
+ /**
14
+ * Host-level, install-once record written by `server-install` (spec
15
+ * 2026-07-16-server-installer). Distinct from the per-instance registry the
16
+ * multi-project switcher keeps under `~/.cezar/instances/` — they coexist.
17
+ */
18
+ export declare function serverStatePath(): string;
19
+ /**
20
+ * Single-writer lock the installer/uninstaller hold for a whole run. The
21
+ * host-level installer is not concurrency-safe with itself.
22
+ */
23
+ export declare function serverLockPath(): string;
package/dist/paths.js ADDED
@@ -0,0 +1,34 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ /**
4
+ * Per-user cezar home. Literal `~/.cezar` on every platform (no XDG, no
5
+ * `%LOCALAPPDATA%` branch) — one rule, and it matches how the existing cache
6
+ * path already behaves (`skills-remote.ts` hardcodes `~/.cache/cez`).
7
+ *
8
+ * `CEZ_HOME` overrides the base so tests (and containers) never touch a real
9
+ * home dir. This is the first shared home-path helper in the repo; two other
10
+ * 2026-07-16 specs (multi-project-switcher, agent-config-files) extend it —
11
+ * first writer owns the file, later specs import it. Do not duplicate this
12
+ * homedir logic elsewhere.
13
+ */
14
+ export function cezarHomeDir() {
15
+ // `|| undefined` so an EMPTY CEZ_HOME (e.g. `CEZ_HOME= cezar …`) falls back
16
+ // to the default instead of yielding relative paths in the cwd.
17
+ return (process.env.CEZ_HOME || undefined) ?? join(homedir(), '.cezar');
18
+ }
19
+ /**
20
+ * Host-level, install-once record written by `server-install` (spec
21
+ * 2026-07-16-server-installer). Distinct from the per-instance registry the
22
+ * multi-project switcher keeps under `~/.cezar/instances/` — they coexist.
23
+ */
24
+ export function serverStatePath() {
25
+ return join(cezarHomeDir(), 'server.json');
26
+ }
27
+ /**
28
+ * Single-writer lock the installer/uninstaller hold for a whole run. The
29
+ * host-level installer is not concurrency-safe with itself.
30
+ */
31
+ export function serverLockPath() {
32
+ return join(cezarHomeDir(), 'server.install.lock');
33
+ }
34
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY;IAC1B,4EAA4E;IAC5E,gEAAgE;IAChE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,SAAS,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC1E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,aAAa,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,qBAAqB,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ import { type WorkflowStepDef } from './workflows/types.js';
3
+ export interface PlanResult {
4
+ steps: WorkflowStepDef[];
5
+ rationale: string;
6
+ /** True when this is the degraded one-step quick-task plan. */
7
+ fallback: boolean;
8
+ }
9
+ export declare function planChain(repoRoot: string, task: string): Promise<PlanResult>;
10
+ export declare function slugify(name: string): string;
11
+ /**
12
+ * Best-effort structured-output extraction (trimmed from @cezar/core's
13
+ * `parseStructured`): try the whole string after stripping a ```json fence,
14
+ * then scan for balanced top-level `{...}` blocks and return the first that
15
+ * validates. Null when nothing does — the caller decides how to recover.
16
+ */
17
+ export declare function parseStructured<T>(raw: string, schema: z.ZodType<T, z.ZodTypeDef, unknown>): T | null;
@@ -0,0 +1,248 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { z } from 'zod';
4
+ import { createRunner } from './core/runner-factory.js';
5
+ import { loadConfig } from './config.js';
6
+ import { discoverSkills } from './skills.js';
7
+ import { workflowStepSchema } from './workflows/types.js';
8
+ /**
9
+ * Chain-from-prompt (spec 008): one cheap `claude` call turns the user's task
10
+ * into a proposed chain of workflow steps built from the skills at hand plus a
11
+ * detected verification command. The planner NEVER blocks the user — any
12
+ * error, timeout or unparseable answer degrades to a one-step quick-task plan
13
+ * with `fallback: true` so the GUI can show a dim note.
14
+ */
15
+ const PLANNER_TIMEOUT_MS = 60_000;
16
+ const PLANNER_SYSTEM_PROMPT = 'You are a planning assistant for an AI coding agent cockpit. Respond with ONLY a JSON object: ' +
17
+ '{"steps":[{"skill"?:string,"name":string,"prompt"?:string,"command"?:string}],"rationale":string}. ' +
18
+ 'Rules: pick skills ONLY from the provided catalog; a step has either "prompt" (an agent step) or ' +
19
+ '"command" (a shell verification check); include the {{task}} placeholder in agent prompts where ' +
20
+ "the user's task text belongs; 1-5 steps; prefer fewer.";
21
+ const plannerResponseSchema = z.object({
22
+ steps: z
23
+ .array(z.object({
24
+ skill: z.string().optional(),
25
+ name: z.string().min(1),
26
+ prompt: z.string().optional(),
27
+ command: z.string().optional(),
28
+ }))
29
+ .min(1)
30
+ .max(5),
31
+ rationale: z.string().default(''),
32
+ });
33
+ export async function planChain(repoRoot, task) {
34
+ const [skills, config, verifyCommands] = await Promise.all([
35
+ discoverSkills(repoRoot),
36
+ loadConfig(repoRoot),
37
+ detectVerifyCommands(repoRoot),
38
+ ]);
39
+ const skillNames = new Set(skills.map((s) => s.name));
40
+ const userPrompt = buildPlannerPrompt(task, skills, verifyCommands);
41
+ // Plan with the configured default runner. `plannerModel` ("sonnet") is a
42
+ // Claude alias, so only pass it when the planner runs on Claude — Codex /
43
+ // OpenCode pick their own default model instead.
44
+ const runner = createRunner(config.defaultRunner);
45
+ const plannerModel = config.defaultRunner === 'claude' ? config.plannerModel : undefined;
46
+ // One retry on an unparseable answer; a runner error goes straight to fallback.
47
+ for (let attempt = 0; attempt < 2; attempt++) {
48
+ let text;
49
+ try {
50
+ const result = await runner.run({
51
+ systemPrompt: PLANNER_SYSTEM_PROMPT,
52
+ userPrompt,
53
+ cwd: repoRoot,
54
+ allowedTools: [],
55
+ model: plannerModel,
56
+ timeoutMs: PLANNER_TIMEOUT_MS,
57
+ });
58
+ text = result.text;
59
+ }
60
+ catch {
61
+ break;
62
+ }
63
+ const parsed = parseStructured(text, plannerResponseSchema);
64
+ if (!parsed)
65
+ continue;
66
+ const steps = sanitizeSteps(parsed.steps, skillNames);
67
+ if (steps.length === 0)
68
+ break; // everything got rejected — degrade
69
+ return { steps, rationale: parsed.rationale, fallback: false };
70
+ }
71
+ return {
72
+ steps: [{ id: 'task', name: 'Do the task', prompt: '{{task}}' }],
73
+ rationale: 'planner unavailable — single-step plan',
74
+ fallback: true,
75
+ };
76
+ }
77
+ /** The `[cez-planner]` marker lets the CEZ_DRY_RUN mock recognize a planning call. */
78
+ function buildPlannerPrompt(task, skills, verifyCommands) {
79
+ const catalog = skills.length
80
+ ? skills.map((s) => `- ${s.name} — ${s.description ?? ''}`).join('\n')
81
+ : '(no skills available)';
82
+ const verify = verifyCommands.length
83
+ ? verifyCommands.map((c) => `- ${c}`).join('\n')
84
+ : '(none detected)';
85
+ return [
86
+ '[cez-planner] Plan a chain of steps for this task.',
87
+ '',
88
+ 'Task:',
89
+ task,
90
+ '',
91
+ 'Skill catalog (name — description):',
92
+ catalog,
93
+ '',
94
+ 'Verification commands detected in this repo:',
95
+ verify,
96
+ ].join('\n');
97
+ }
98
+ /**
99
+ * Detect verification commands the planner may propose as `check` steps:
100
+ * `package.json` scripts (test/lint/build) and Makefile targets (first 50
101
+ * lines). Best effort — an unreadable file just contributes nothing.
102
+ */
103
+ async function detectVerifyCommands(repoRoot) {
104
+ const out = [];
105
+ const pkgSchema = z.object({ scripts: z.record(z.string()).default({}) });
106
+ try {
107
+ const raw = JSON.parse(await readFile(join(repoRoot, 'package.json'), 'utf8'));
108
+ const pkg = pkgSchema.safeParse(raw);
109
+ if (pkg.success) {
110
+ if (pkg.data.scripts['test'])
111
+ out.push('npm test');
112
+ if (pkg.data.scripts['lint'])
113
+ out.push('npm run lint');
114
+ if (pkg.data.scripts['build'])
115
+ out.push('npm run build');
116
+ }
117
+ }
118
+ catch {
119
+ // no package.json — fine
120
+ }
121
+ try {
122
+ const make = await readFile(join(repoRoot, 'Makefile'), 'utf8');
123
+ for (const line of make.split('\n').slice(0, 50)) {
124
+ const m = /^([A-Za-z0-9_.-]+):(?!=)/.exec(line);
125
+ if (m && m[1] && !m[1].startsWith('.'))
126
+ out.push(`make ${m[1]}`);
127
+ if (out.length >= 8)
128
+ break;
129
+ }
130
+ }
131
+ catch {
132
+ // no Makefile — fine
133
+ }
134
+ return out;
135
+ }
136
+ /**
137
+ * Turn the model's raw steps into valid `WorkflowStepDef`s: exactly one of
138
+ * prompt/command, unknown skills stripped (the prompt still carries the step),
139
+ * ids derived from names with `-2`-style dedup. Steps that can't be repaired
140
+ * are dropped — the caller falls back when nothing survives.
141
+ */
142
+ function sanitizeSteps(raw, skillNames) {
143
+ const out = [];
144
+ const usedIds = new Set();
145
+ for (const s of raw) {
146
+ let skill = s.skill?.trim() || undefined;
147
+ const prompt = s.prompt?.trim() || undefined;
148
+ const command = s.command?.trim() || undefined;
149
+ if (Boolean(prompt) === Boolean(command))
150
+ continue; // needs exactly one
151
+ if (command)
152
+ skill = undefined; // a shell check carries no skill
153
+ if (skill && !skillNames.has(skill))
154
+ skill = undefined; // unknown skill → plain prompt
155
+ const id = uniqueId(slugify(s.name) || 'step', usedIds);
156
+ const candidate = workflowStepSchema.safeParse({
157
+ id,
158
+ name: s.name,
159
+ ...(skill ? { skill } : {}),
160
+ ...(prompt ? { prompt } : {}),
161
+ ...(command ? { command } : {}),
162
+ });
163
+ if (!candidate.success)
164
+ continue;
165
+ usedIds.add(id);
166
+ out.push(candidate.data);
167
+ }
168
+ return out;
169
+ }
170
+ export function slugify(name) {
171
+ return name
172
+ .toLowerCase()
173
+ .replace(/[^a-z0-9]+/g, '-')
174
+ .replace(/^-+|-+$/g, '');
175
+ }
176
+ function uniqueId(base, used) {
177
+ if (!used.has(base))
178
+ return base;
179
+ for (let n = 2;; n++) {
180
+ const id = `${base}-${n}`;
181
+ if (!used.has(id))
182
+ return id;
183
+ }
184
+ }
185
+ /**
186
+ * Best-effort structured-output extraction (trimmed from @cezar/core's
187
+ * `parseStructured`): try the whole string after stripping a ```json fence,
188
+ * then scan for balanced top-level `{...}` blocks and return the first that
189
+ * validates. Null when nothing does — the caller decides how to recover.
190
+ */
191
+ export function parseStructured(raw, schema) {
192
+ const cleaned = raw
193
+ .replace(/^```(?:json|javascript|js|jsonl)?\s*\n?/im, '')
194
+ .replace(/\n?```\s*$/m, '')
195
+ .trim();
196
+ try {
197
+ return schema.parse(JSON.parse(cleaned));
198
+ }
199
+ catch {
200
+ for (const candidate of extractJsonObjectCandidates(raw)) {
201
+ try {
202
+ return schema.parse(JSON.parse(candidate));
203
+ }
204
+ catch {
205
+ continue;
206
+ }
207
+ }
208
+ return null;
209
+ }
210
+ }
211
+ function extractJsonObjectCandidates(raw) {
212
+ const candidates = [];
213
+ let start = -1;
214
+ let depth = 0;
215
+ let inString = false;
216
+ let escaped = false;
217
+ for (let i = 0; i < raw.length; i++) {
218
+ const ch = raw[i];
219
+ if (inString) {
220
+ if (escaped)
221
+ escaped = false;
222
+ else if (ch === '\\')
223
+ escaped = true;
224
+ else if (ch === '"')
225
+ inString = false;
226
+ continue;
227
+ }
228
+ if (ch === '"') {
229
+ inString = true;
230
+ }
231
+ else if (ch === '{') {
232
+ if (depth === 0)
233
+ start = i;
234
+ depth++;
235
+ }
236
+ else if (ch === '}') {
237
+ if (depth === 0)
238
+ continue;
239
+ depth--;
240
+ if (depth === 0 && start >= 0) {
241
+ candidates.push(raw.slice(start, i + 1));
242
+ start = -1;
243
+ }
244
+ }
245
+ }
246
+ return candidates;
247
+ }
248
+ //# sourceMappingURL=planner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.js","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /** Snapshot release decisions — the pure half of `scripts/release-snapshot.mjs`.
2
+ *
3
+ * Spec `.ai/specs/2026-07-18-npm-preview-publish.md` (#482): every green CI run
4
+ * publishes an installable preview of the CLI. This module decides *whether* a
5
+ * given CI event publishes, under *which* version and dist-tag, and how the two
6
+ * manifests (the scoped package and its unscoped alias) are stamped. Kept
7
+ * dependency-free and side-effect-free so the decision is unit-testable; the
8
+ * script owns file writes, `npm publish`, and the exit code.
9
+ *
10
+ * Deliberately name-agnostic: package names come from the checked-out manifests
11
+ * at call time, never from constants — so the `@pat-lewczuk/cezar` →
12
+ * `@open-mercato/cezar` rename (PR #501) lands independently of this pipeline.
13
+ */
14
+ /** The CI facts the decision needs, straight from GitHub Actions' env/event. */
15
+ export interface SnapshotContext {
16
+ /** `GITHUB_EVENT_NAME` — only `pull_request` and `push` ever publish. */
17
+ eventName: string;
18
+ /** `GITHUB_REF_NAME` for push events — only `develop` publishes a snapshot;
19
+ * `main` is reserved for owner-driven stable releases (see stable.ts). */
20
+ refName: string;
21
+ /** PR number for pull_request events; absent/invalid → no publish. */
22
+ prNumber?: number;
23
+ /** `owner/name` of the PR head repo — fork PRs (≠ `repo`) never publish. */
24
+ headRepo?: string;
25
+ /** `GITHUB_REPOSITORY` — this repo's `owner/name`. */
26
+ repo?: string;
27
+ /** The base version from the root `package.json` (e.g. `0.1.5`). */
28
+ baseVersion: string;
29
+ /** `GITHUB_RUN_NUMBER` — monotonic per workflow; makes versions unique. */
30
+ runNumber: number;
31
+ /** `GITHUB_RUN_ATTEMPT` — appended only when > 1 so re-runs never collide. */
32
+ runAttempt?: number;
33
+ }
34
+ /** A publishable snapshot: prerelease version + the explicit dist-tag.
35
+ * The dist-tag is structurally never `latest` — snapshots must not become the
36
+ * default install; stable releases stay owner-driven (spec, resolved Q2). */
37
+ export interface SnapshotPlan {
38
+ channel: string;
39
+ version: string;
40
+ distTag: string;
41
+ }
42
+ export declare function computeSnapshot(ctx: SnapshotContext): SnapshotPlan | null;
43
+ /** The minimal manifest shape the stamper touches; everything else passes through. */
44
+ export interface ManifestLike {
45
+ name: string;
46
+ version: string;
47
+ dependencies?: Record<string, string>;
48
+ [key: string]: unknown;
49
+ }
50
+ /** Stamp both manifests to the snapshot version.
51
+ *
52
+ * The alias is a bin-shim whose only dependency is the scoped package; a
53
+ * snapshot must pin that dependency **exact** (`0.1.5-pr482.123`, no range) so
54
+ * `npx <alias>@<version>` runs exactly the PR's code — a `^` range would
55
+ * resolve to whatever newer version exists (spec, resolved Q5). Stable
56
+ * releases keep their `^` range and never go through this stamper. */
57
+ export declare function stampManifests(rootPkg: ManifestLike, aliasPkg: ManifestLike, version: string): {
58
+ root: ManifestLike;
59
+ alias: ManifestLike;
60
+ };
61
+ /** The copy-pasteable commands for the sticky PR comment and the step summary.
62
+ * Rendered from the *actual* alias package name so a future rename of the npx
63
+ * command can never leave stale instructions (spec, resolved Q1). */
64
+ export declare function buildInstallLines(aliasName: string, version: string): string[];
@@ -0,0 +1,75 @@
1
+ /** Snapshot release decisions — the pure half of `scripts/release-snapshot.mjs`.
2
+ *
3
+ * Spec `.ai/specs/2026-07-18-npm-preview-publish.md` (#482): every green CI run
4
+ * publishes an installable preview of the CLI. This module decides *whether* a
5
+ * given CI event publishes, under *which* version and dist-tag, and how the two
6
+ * manifests (the scoped package and its unscoped alias) are stamped. Kept
7
+ * dependency-free and side-effect-free so the decision is unit-testable; the
8
+ * script owns file writes, `npm publish`, and the exit code.
9
+ *
10
+ * Deliberately name-agnostic: package names come from the checked-out manifests
11
+ * at call time, never from constants — so the `@pat-lewczuk/cezar` →
12
+ * `@open-mercato/cezar` rename (PR #501) lands independently of this pipeline.
13
+ */
14
+ export function computeSnapshot(ctx) {
15
+ const channel = resolveChannel(ctx);
16
+ if (!channel)
17
+ return null;
18
+ if (!ctx.baseVersion || !Number.isInteger(ctx.runNumber) || ctx.runNumber <= 0)
19
+ return null;
20
+ const attempt = ctx.runAttempt !== undefined && Number.isInteger(ctx.runAttempt) && ctx.runAttempt > 1
21
+ ? `.${ctx.runAttempt}`
22
+ : '';
23
+ return {
24
+ channel: channel.channel,
25
+ version: `${ctx.baseVersion}-${channel.channel}.${ctx.runNumber}${attempt}`,
26
+ distTag: channel.distTag,
27
+ };
28
+ }
29
+ function resolveChannel(ctx) {
30
+ if (ctx.eventName === 'pull_request') {
31
+ const n = ctx.prNumber;
32
+ if (n === undefined || !Number.isInteger(n) || n <= 0)
33
+ return null;
34
+ // Defense in depth: the workflow's `if` already excludes forks, and fork PRs
35
+ // get no secrets — but the decision must not rely on workflow wiring alone.
36
+ if (!ctx.headRepo || !ctx.repo || ctx.headRepo !== ctx.repo)
37
+ return null;
38
+ return { channel: `pr${n}`, distTag: `pr-${n}` };
39
+ }
40
+ if (ctx.eventName === 'push') {
41
+ // Only `develop` publishes a snapshot. `main` is deliberately excluded so a
42
+ // merge to main never touches npm — stable `latest` releases are cut
43
+ // manually via the Release workflow (stable.ts). Defense in depth: the
44
+ // workflow's `if` already restricts the push channel to develop.
45
+ if (ctx.refName === 'develop')
46
+ return { channel: 'develop', distTag: 'develop' };
47
+ return null;
48
+ }
49
+ return null;
50
+ }
51
+ /** Stamp both manifests to the snapshot version.
52
+ *
53
+ * The alias is a bin-shim whose only dependency is the scoped package; a
54
+ * snapshot must pin that dependency **exact** (`0.1.5-pr482.123`, no range) so
55
+ * `npx <alias>@<version>` runs exactly the PR's code — a `^` range would
56
+ * resolve to whatever newer version exists (spec, resolved Q5). Stable
57
+ * releases keep their `^` range and never go through this stamper. */
58
+ export function stampManifests(rootPkg, aliasPkg, version) {
59
+ return {
60
+ root: { ...rootPkg, version },
61
+ alias: { ...aliasPkg, version, dependencies: { [rootPkg.name]: version } },
62
+ };
63
+ }
64
+ /** The copy-pasteable commands for the sticky PR comment and the step summary.
65
+ * Rendered from the *actual* alias package name so a future rename of the npx
66
+ * command can never leave stale instructions (spec, resolved Q1). */
67
+ export function buildInstallLines(aliasName, version) {
68
+ const cmd = `npx ${aliasName}@${version}`;
69
+ return [
70
+ `${cmd} # cockpit at http://localhost:4321`,
71
+ `${cmd} run "…" # headless run`,
72
+ `${cmd} server-deploy --platform <id> # roll a server to this exact build`,
73
+ ];
74
+ }
75
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/release/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAgCH,MAAM,UAAU,eAAe,CAAC,GAAoB;IAClD,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,SAAS,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5F,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,UAAU,GAAG,CAAC;QACpG,CAAC,CAAC,IAAI,GAAG,CAAC,UAAU,EAAE;QACtB,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,GAAG,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,OAAO,IAAI,GAAG,CAAC,SAAS,GAAG,OAAO,EAAE;QAC3E,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,GAAoB;IAC1C,IAAI,GAAG,CAAC,SAAS,KAAK,cAAc,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC;QACvB,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACnE,6EAA6E;QAC7E,4EAA4E;QAC5E,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACzE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IACnD,CAAC;IACD,IAAI,GAAG,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QAC7B,4EAA4E;QAC5E,qEAAqE;QACrE,uEAAuE;QACvE,iEAAiE;QACjE,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;QACjF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAUD;;;;;;uEAMuE;AACvE,MAAM,UAAU,cAAc,CAC5B,OAAqB,EACrB,QAAsB,EACtB,OAAe;IAEf,OAAO;QACL,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE;QAC7B,KAAK,EAAE,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE;KAC3E,CAAC;AACJ,CAAC;AAED;;sEAEsE;AACtE,MAAM,UAAU,iBAAiB,CAAC,SAAiB,EAAE,OAAe;IAClE,MAAM,GAAG,GAAG,OAAO,SAAS,IAAI,OAAO,EAAE,CAAC;IAC1C,OAAO;QACL,GAAG,GAAG,oEAAoE;QAC1E,GAAG,GAAG,gDAAgD;QACtD,GAAG,GAAG,qEAAqE;KAC5E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,46 @@
1
+ /** Stable-release decisions — the pure half of `scripts/release.mjs`.
2
+ *
3
+ * Sibling of `snapshot.ts`, but for the *owner-driven* `latest` channel. The
4
+ * `Release` workflow (`.github/workflows/release.yml`) is run manually and
5
+ * never fires from a push, so — unlike snapshots — a stable release is the only
6
+ * thing that ever moves the `latest` dist-tag (spec
7
+ * `.ai/specs/2026-07-18-npm-preview-publish.md`, #482).
8
+ *
9
+ * Two decisions live here so they stay unit-testable, side-effect-free, and
10
+ * name-agnostic (names come from the checked-out manifests, never constants):
11
+ * the next stable version for a given bump, and how both manifests are stamped.
12
+ * Crucially, the alias keeps a **caret** range on its scoped dependency — the
13
+ * opposite of the snapshot stamper's exact pin — so a stable `cezar-cli` picks
14
+ * up compatible patch releases of the implementation package.
15
+ */
16
+ /** The version-bump modes the Release workflow offers. `existing` publishes the
17
+ * version already committed to the root manifest (for hand-prepared releases);
18
+ * the rest increment semver from the current base. */
19
+ export type ReleaseBump = 'patch' | 'minor' | 'major' | 'existing';
20
+ export declare const RELEASE_BUMPS: readonly ReleaseBump[];
21
+ export declare function isReleaseBump(value: string): value is ReleaseBump;
22
+ /** Compute the next stable version from the current base and a bump mode.
23
+ *
24
+ * `base` must be a plain `major.minor.patch` (no prerelease/build suffix) — a
25
+ * stable release should never start from a snapshot version. `existing` returns
26
+ * the base verbatim; the increments zero out the lower components the way
27
+ * `npm version` does. Returns `null` for an unparseable base so the caller can
28
+ * fail loudly instead of publishing a garbage version. */
29
+ export declare function computeStableVersion(bump: ReleaseBump, base: string): string | null;
30
+ /** The minimal manifest shape the stamper touches; everything else passes through. */
31
+ export interface ManifestLike {
32
+ name: string;
33
+ version: string;
34
+ dependencies?: Record<string, string>;
35
+ [key: string]: unknown;
36
+ }
37
+ /** Stamp both manifests to a stable version.
38
+ *
39
+ * Mirror of `stampManifests` in `snapshot.ts`, but the alias's dependency on
40
+ * the scoped package is a **caret** range (`^0.1.6`), not an exact pin — a
41
+ * stable `cezar-cli` should follow compatible releases of the implementation
42
+ * package, whereas a snapshot must pin the one exact build it was cut from. */
43
+ export declare function stampStableManifests(rootPkg: ManifestLike, aliasPkg: ManifestLike, version: string): {
44
+ root: ManifestLike;
45
+ alias: ManifestLike;
46
+ };
@@ -0,0 +1,57 @@
1
+ /** Stable-release decisions — the pure half of `scripts/release.mjs`.
2
+ *
3
+ * Sibling of `snapshot.ts`, but for the *owner-driven* `latest` channel. The
4
+ * `Release` workflow (`.github/workflows/release.yml`) is run manually and
5
+ * never fires from a push, so — unlike snapshots — a stable release is the only
6
+ * thing that ever moves the `latest` dist-tag (spec
7
+ * `.ai/specs/2026-07-18-npm-preview-publish.md`, #482).
8
+ *
9
+ * Two decisions live here so they stay unit-testable, side-effect-free, and
10
+ * name-agnostic (names come from the checked-out manifests, never constants):
11
+ * the next stable version for a given bump, and how both manifests are stamped.
12
+ * Crucially, the alias keeps a **caret** range on its scoped dependency — the
13
+ * opposite of the snapshot stamper's exact pin — so a stable `cezar-cli` picks
14
+ * up compatible patch releases of the implementation package.
15
+ */
16
+ export const RELEASE_BUMPS = ['patch', 'minor', 'major', 'existing'];
17
+ export function isReleaseBump(value) {
18
+ return RELEASE_BUMPS.includes(value);
19
+ }
20
+ /** Compute the next stable version from the current base and a bump mode.
21
+ *
22
+ * `base` must be a plain `major.minor.patch` (no prerelease/build suffix) — a
23
+ * stable release should never start from a snapshot version. `existing` returns
24
+ * the base verbatim; the increments zero out the lower components the way
25
+ * `npm version` does. Returns `null` for an unparseable base so the caller can
26
+ * fail loudly instead of publishing a garbage version. */
27
+ export function computeStableVersion(bump, base) {
28
+ const m = /^(\d+)\.(\d+)\.(\d+)$/.exec(base.trim());
29
+ if (!m)
30
+ return null;
31
+ const [major, minor, patch] = [Number(m[1]), Number(m[2]), Number(m[3])];
32
+ switch (bump) {
33
+ case 'existing':
34
+ return `${major}.${minor}.${patch}`;
35
+ case 'patch':
36
+ return `${major}.${minor}.${patch + 1}`;
37
+ case 'minor':
38
+ return `${major}.${minor + 1}.0`;
39
+ case 'major':
40
+ return `${major + 1}.0.0`;
41
+ default:
42
+ return null;
43
+ }
44
+ }
45
+ /** Stamp both manifests to a stable version.
46
+ *
47
+ * Mirror of `stampManifests` in `snapshot.ts`, but the alias's dependency on
48
+ * the scoped package is a **caret** range (`^0.1.6`), not an exact pin — a
49
+ * stable `cezar-cli` should follow compatible releases of the implementation
50
+ * package, whereas a snapshot must pin the one exact build it was cut from. */
51
+ export function stampStableManifests(rootPkg, aliasPkg, version) {
52
+ return {
53
+ root: { ...rootPkg, version },
54
+ alias: { ...aliasPkg, version, dependencies: { [rootPkg.name]: `^${version}` } },
55
+ };
56
+ }
57
+ //# sourceMappingURL=stable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stable.js","sourceRoot":"","sources":["../../src/release/stable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,MAAM,CAAC,MAAM,aAAa,GAA2B,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AAE7F,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAQ,aAAmC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;2DAM2D;AAC3D,MAAM,UAAU,oBAAoB,CAAC,IAAiB,EAAE,IAAY;IAClE,MAAM,CAAC,GAAG,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACpD,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,UAAU;YACb,OAAO,GAAG,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;QACtC,KAAK,OAAO;YACV,OAAO,GAAG,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC1C,KAAK,OAAO;YACV,OAAO,GAAG,KAAK,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC;QACnC,KAAK,OAAO;YACV,OAAO,GAAG,KAAK,GAAG,CAAC,MAAM,CAAC;QAC5B;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAUD;;;;;gFAKgF;AAChF,MAAM,UAAU,oBAAoB,CAClC,OAAqB,EACrB,QAAsB,EACtB,OAAe;IAEf,OAAO;QACL,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE;QAC7B,KAAK,EAAE,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,EAAE,EAAE;KACjF,CAAC;AACJ,CAAC"}