@percher/core 0.2.6 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/dist/ai-files-manifest.d.ts +28 -0
  2. package/dist/ai-files-manifest.d.ts.map +1 -0
  3. package/dist/ai-files-manifest.js +96 -0
  4. package/dist/ai-files-manifest.js.map +1 -0
  5. package/dist/commands/account.d.ts +51 -0
  6. package/dist/commands/account.d.ts.map +1 -0
  7. package/dist/commands/account.js +88 -0
  8. package/dist/commands/account.js.map +1 -0
  9. package/dist/commands/ai-files.d.ts +73 -0
  10. package/dist/commands/ai-files.d.ts.map +1 -0
  11. package/dist/commands/ai-files.js +179 -0
  12. package/dist/commands/ai-files.js.map +1 -0
  13. package/dist/commands/billing.d.ts +1 -1
  14. package/dist/commands/billing.d.ts.map +1 -1
  15. package/dist/commands/billing.js +1 -1
  16. package/dist/commands/billing.js.map +1 -1
  17. package/dist/commands/continue.d.ts +48 -0
  18. package/dist/commands/continue.d.ts.map +1 -0
  19. package/dist/commands/continue.js +121 -0
  20. package/dist/commands/continue.js.map +1 -0
  21. package/dist/commands/create.d.ts +1 -1
  22. package/dist/commands/create.d.ts.map +1 -1
  23. package/dist/commands/create.js +1 -1
  24. package/dist/commands/create.js.map +1 -1
  25. package/dist/commands/dashboard.d.ts +15 -0
  26. package/dist/commands/dashboard.d.ts.map +1 -0
  27. package/dist/commands/dashboard.js +33 -0
  28. package/dist/commands/dashboard.js.map +1 -0
  29. package/dist/commands/data-export.d.ts +21 -0
  30. package/dist/commands/data-export.d.ts.map +1 -0
  31. package/dist/commands/data-export.js +36 -0
  32. package/dist/commands/data-export.js.map +1 -0
  33. package/dist/commands/data.d.ts +3 -3
  34. package/dist/commands/data.d.ts.map +1 -1
  35. package/dist/commands/data.js +1 -1
  36. package/dist/commands/data.js.map +1 -1
  37. package/dist/commands/delete.d.ts +1 -1
  38. package/dist/commands/delete.d.ts.map +1 -1
  39. package/dist/commands/delete.js +1 -1
  40. package/dist/commands/delete.js.map +1 -1
  41. package/dist/commands/deploys.d.ts +2 -2
  42. package/dist/commands/deploys.d.ts.map +1 -1
  43. package/dist/commands/deploys.js +21 -5
  44. package/dist/commands/deploys.js.map +1 -1
  45. package/dist/commands/dev.d.ts +1 -9
  46. package/dist/commands/dev.d.ts.map +1 -1
  47. package/dist/commands/dev.js +79 -24
  48. package/dist/commands/dev.js.map +1 -1
  49. package/dist/commands/diagnose.d.ts +1 -1
  50. package/dist/commands/diagnose.d.ts.map +1 -1
  51. package/dist/commands/diagnose.js +1 -1
  52. package/dist/commands/diagnose.js.map +1 -1
  53. package/dist/commands/doctor.d.ts +75 -3
  54. package/dist/commands/doctor.d.ts.map +1 -1
  55. package/dist/commands/doctor.js +822 -10
  56. package/dist/commands/doctor.js.map +1 -1
  57. package/dist/commands/domains.d.ts +1 -1
  58. package/dist/commands/domains.d.ts.map +1 -1
  59. package/dist/commands/domains.js +1 -1
  60. package/dist/commands/domains.js.map +1 -1
  61. package/dist/commands/env-scan.d.ts +2 -0
  62. package/dist/commands/env-scan.d.ts.map +1 -0
  63. package/dist/commands/env-scan.js +92 -0
  64. package/dist/commands/env-scan.js.map +1 -0
  65. package/dist/commands/env.d.ts +1 -1
  66. package/dist/commands/env.d.ts.map +1 -1
  67. package/dist/commands/env.js +1 -1
  68. package/dist/commands/env.js.map +1 -1
  69. package/dist/commands/export.d.ts +1 -1
  70. package/dist/commands/export.js +1 -1
  71. package/dist/commands/generate.d.ts +1 -1
  72. package/dist/commands/generate.d.ts.map +1 -1
  73. package/dist/commands/generate.js +14 -9
  74. package/dist/commands/generate.js.map +1 -1
  75. package/dist/commands/github.d.ts +60 -0
  76. package/dist/commands/github.d.ts.map +1 -0
  77. package/dist/commands/github.js +112 -0
  78. package/dist/commands/github.js.map +1 -0
  79. package/dist/commands/import-project.d.ts +1 -1
  80. package/dist/commands/import-project.d.ts.map +1 -1
  81. package/dist/commands/import-project.js +1 -1
  82. package/dist/commands/import-project.js.map +1 -1
  83. package/dist/commands/init.d.ts +1 -1
  84. package/dist/commands/init.d.ts.map +1 -1
  85. package/dist/commands/init.js +1 -1
  86. package/dist/commands/init.js.map +1 -1
  87. package/dist/commands/insights.d.ts +1 -1
  88. package/dist/commands/insights.d.ts.map +1 -1
  89. package/dist/commands/insights.js +1 -1
  90. package/dist/commands/insights.js.map +1 -1
  91. package/dist/commands/login.d.ts +1 -1
  92. package/dist/commands/login.d.ts.map +1 -1
  93. package/dist/commands/login.js +1 -1
  94. package/dist/commands/login.js.map +1 -1
  95. package/dist/commands/logs.d.ts +1 -1
  96. package/dist/commands/logs.d.ts.map +1 -1
  97. package/dist/commands/logs.js +1 -1
  98. package/dist/commands/logs.js.map +1 -1
  99. package/dist/commands/mcp.d.ts +1 -1
  100. package/dist/commands/mcp.d.ts.map +1 -1
  101. package/dist/commands/mcp.js +1 -1
  102. package/dist/commands/mcp.js.map +1 -1
  103. package/dist/commands/open.d.ts +1 -1
  104. package/dist/commands/open.d.ts.map +1 -1
  105. package/dist/commands/open.js +1 -1
  106. package/dist/commands/open.js.map +1 -1
  107. package/dist/commands/publish-failure.d.ts +31 -0
  108. package/dist/commands/publish-failure.d.ts.map +1 -0
  109. package/dist/commands/publish-failure.js +150 -0
  110. package/dist/commands/publish-failure.js.map +1 -0
  111. package/dist/commands/publish-node.d.ts +16 -0
  112. package/dist/commands/publish-node.d.ts.map +1 -0
  113. package/dist/commands/publish-node.js +42 -0
  114. package/dist/commands/publish-node.js.map +1 -0
  115. package/dist/commands/publish.d.ts +105 -3
  116. package/dist/commands/publish.d.ts.map +1 -1
  117. package/dist/commands/publish.js +746 -158
  118. package/dist/commands/publish.js.map +1 -1
  119. package/dist/commands/push.d.ts +45 -8
  120. package/dist/commands/push.d.ts.map +1 -1
  121. package/dist/commands/push.js +233 -22
  122. package/dist/commands/push.js.map +1 -1
  123. package/dist/commands/redeploy.d.ts +28 -0
  124. package/dist/commands/redeploy.d.ts.map +1 -0
  125. package/dist/commands/redeploy.js +421 -0
  126. package/dist/commands/redeploy.js.map +1 -0
  127. package/dist/commands/rename.d.ts +1 -1
  128. package/dist/commands/rename.d.ts.map +1 -1
  129. package/dist/commands/rename.js +1 -1
  130. package/dist/commands/rename.js.map +1 -1
  131. package/dist/commands/reproduce.d.ts +64 -0
  132. package/dist/commands/reproduce.d.ts.map +1 -0
  133. package/dist/commands/reproduce.js +211 -0
  134. package/dist/commands/reproduce.js.map +1 -0
  135. package/dist/commands/reset-superuser.d.ts +1 -1
  136. package/dist/commands/reset-superuser.d.ts.map +1 -1
  137. package/dist/commands/reset-superuser.js +1 -1
  138. package/dist/commands/reset-superuser.js.map +1 -1
  139. package/dist/commands/restore.d.ts +79 -0
  140. package/dist/commands/restore.d.ts.map +1 -0
  141. package/dist/commands/restore.js +164 -0
  142. package/dist/commands/restore.js.map +1 -0
  143. package/dist/commands/resume.d.ts +1 -1
  144. package/dist/commands/resume.d.ts.map +1 -1
  145. package/dist/commands/resume.js +1 -1
  146. package/dist/commands/resume.js.map +1 -1
  147. package/dist/commands/rollback.d.ts +21 -8
  148. package/dist/commands/rollback.d.ts.map +1 -1
  149. package/dist/commands/rollback.js +12 -6
  150. package/dist/commands/rollback.js.map +1 -1
  151. package/dist/commands/status.d.ts +33 -0
  152. package/dist/commands/status.d.ts.map +1 -0
  153. package/dist/commands/status.js +48 -0
  154. package/dist/commands/status.js.map +1 -0
  155. package/dist/commands/unsuspend.d.ts +35 -0
  156. package/dist/commands/unsuspend.d.ts.map +1 -0
  157. package/dist/commands/unsuspend.js +27 -0
  158. package/dist/commands/unsuspend.js.map +1 -0
  159. package/dist/commands/versions.d.ts +1 -1
  160. package/dist/commands/versions.d.ts.map +1 -1
  161. package/dist/commands/versions.js +1 -1
  162. package/dist/commands/versions.js.map +1 -1
  163. package/dist/commands/wait-deploy.d.ts +92 -0
  164. package/dist/commands/wait-deploy.d.ts.map +1 -0
  165. package/dist/commands/wait-deploy.js +226 -0
  166. package/dist/commands/wait-deploy.js.map +1 -0
  167. package/dist/env-scan-source.d.ts +39 -0
  168. package/dist/env-scan-source.d.ts.map +1 -0
  169. package/dist/env-scan-source.js +332 -0
  170. package/dist/env-scan-source.js.map +1 -0
  171. package/dist/error-classifier.d.ts.map +1 -1
  172. package/dist/error-classifier.js +67 -4
  173. package/dist/error-classifier.js.map +1 -1
  174. package/dist/errors.d.ts +8 -1
  175. package/dist/errors.d.ts.map +1 -1
  176. package/dist/errors.js +2 -0
  177. package/dist/errors.js.map +1 -1
  178. package/dist/event-renderer.d.ts +17 -0
  179. package/dist/event-renderer.d.ts.map +1 -0
  180. package/dist/event-renderer.js +130 -0
  181. package/dist/event-renderer.js.map +1 -0
  182. package/dist/index.d.ts +16 -1
  183. package/dist/index.d.ts.map +1 -1
  184. package/dist/index.js +15 -0
  185. package/dist/index.js.map +1 -1
  186. package/dist/plans.d.ts +20 -0
  187. package/dist/plans.d.ts.map +1 -1
  188. package/dist/plans.js +15 -0
  189. package/dist/plans.js.map +1 -1
  190. package/dist/poll-deployment.d.ts +59 -0
  191. package/dist/poll-deployment.d.ts.map +1 -0
  192. package/dist/poll-deployment.js +93 -0
  193. package/dist/poll-deployment.js.map +1 -0
  194. package/dist/publish-retry.d.ts +29 -0
  195. package/dist/publish-retry.d.ts.map +1 -0
  196. package/dist/publish-retry.js +224 -0
  197. package/dist/publish-retry.js.map +1 -0
  198. package/dist/recovery.d.ts +356 -0
  199. package/dist/recovery.d.ts.map +1 -0
  200. package/dist/recovery.js +300 -0
  201. package/dist/recovery.js.map +1 -0
  202. package/dist/stream-utils.d.ts +21 -0
  203. package/dist/stream-utils.d.ts.map +1 -0
  204. package/dist/stream-utils.js +41 -0
  205. package/dist/stream-utils.js.map +1 -0
  206. package/dist/structured-error-codes.d.ts +30 -0
  207. package/dist/structured-error-codes.d.ts.map +1 -0
  208. package/dist/structured-error-codes.js +86 -0
  209. package/dist/structured-error-codes.js.map +1 -0
  210. package/dist/tarball.d.ts +11 -0
  211. package/dist/tarball.d.ts.map +1 -1
  212. package/dist/tarball.js +30 -9
  213. package/dist/tarball.js.map +1 -1
  214. package/dist/templates/ai-files/claude-md.d.ts +7 -0
  215. package/dist/templates/ai-files/claude-md.d.ts.map +1 -0
  216. package/dist/templates/ai-files/claude-md.js +78 -0
  217. package/dist/templates/ai-files/claude-md.js.map +1 -0
  218. package/dist/templates/ai-files/cursor-percher-mdc.d.ts +7 -0
  219. package/dist/templates/ai-files/cursor-percher-mdc.d.ts.map +1 -0
  220. package/dist/templates/ai-files/cursor-percher-mdc.js +111 -0
  221. package/dist/templates/ai-files/cursor-percher-mdc.js.map +1 -0
  222. package/dist/templates/ai-files/index.d.ts +8 -0
  223. package/dist/templates/ai-files/index.d.ts.map +1 -0
  224. package/dist/templates/ai-files/index.js +4 -0
  225. package/dist/templates/ai-files/index.js.map +1 -0
  226. package/package.json +6 -5
@@ -0,0 +1,421 @@
1
+ import { PercherApiError } from "@percher/client";
2
+ import { TIMEOUTS } from "@percher/shared/timeouts";
3
+ import { z } from "zod/v3";
4
+ import { readPercherTomlAppName } from "../app-name";
5
+ import { pollDeployment } from "../poll-deployment";
6
+ import { RECOVERY_NEEDS_LOGIN, RECOVERY_NONE, recoveryAsk, recoveryEnv, recoveryFixConfig, recoveryFromErrorClass, recoveryRetry, } from "../recovery";
7
+ import { classifyDeploymentFailure } from "./publish-failure";
8
+ export const redeployInputSchema = z.object({
9
+ app: z
10
+ .string()
11
+ .optional()
12
+ .describe("App name. Defaults to the [app].name in the current directory's percher.toml."),
13
+ deployId: z
14
+ .string()
15
+ .optional()
16
+ .describe("Specific deploy id (e.g. dep_abc123). Defaults to the latest live deploy for the app."),
17
+ });
18
+ /**
19
+ * FUTURE1 Phase 3.2 — re-run an existing deploy without re-uploading
20
+ * source. Wraps the API's POST /apps/:appRef/deploys/:deployId/rerun
21
+ * (Phase 3.1, b6887ea + 335a893) and polls to terminal status. Returns
22
+ * the same PublishResult shape as `publish` so CLI/MCP consumers can
23
+ * reuse rendering and recovery logic.
24
+ *
25
+ * Typical wall-clock: <10s when the cache is hot (the source's
26
+ * build_input_hash matches an existing image and the build skips).
27
+ * Falls back to a normal build (no cache hit) if the cache row was
28
+ * evicted or anything in the build env changed.
29
+ */
30
+ export async function redeploy(ctx, input = {}) {
31
+ const t0 = Date.now();
32
+ const appName = input.app ?? readPercherTomlAppName(ctx.cwd);
33
+ if (!appName) {
34
+ return failureResult({
35
+ title: "App name required",
36
+ explanation: "redeploy needs either an explicit `app` argument or a percher.toml in the current directory.",
37
+ suggestion: "Pass --app=<name>, or cd into a project that has a percher.toml.",
38
+ });
39
+ }
40
+ let app;
41
+ try {
42
+ app = await ctx.client.apps.get(appName);
43
+ }
44
+ catch (err) {
45
+ if (err instanceof PercherApiError) {
46
+ // Codex P2 follow-up on 6ad76be: only 404 is a "wrong app name"
47
+ // signal. 401 is auth, anything else (5xx, network, rate-limit
48
+ // on the read path) is a real driftfel — bubble so the caller
49
+ // sees the actual API error instead of a misleading
50
+ // "App not found" that points the user the wrong way.
51
+ if (err.status === 401) {
52
+ return {
53
+ status: "needs_login",
54
+ fileCount: 0,
55
+ bytes: 0,
56
+ recovery: RECOVERY_NEEDS_LOGIN,
57
+ summary: "Not logged in — run `bunx percher login` first.",
58
+ configPath: "",
59
+ bundle: { fileCount: 0, bytes: 0 },
60
+ };
61
+ }
62
+ if (err.status === 404) {
63
+ return failureResult({
64
+ title: "App not found",
65
+ explanation: `Could not resolve app "${appName}".`,
66
+ suggestion: "Check the app name with `bunx percher whoami` or your dashboard.",
67
+ });
68
+ }
69
+ }
70
+ throw err;
71
+ }
72
+ // Resolve source deploy: explicit id wins; otherwise the latest live
73
+ // deploy. We deliberately don't fall back to the most recent FAILED
74
+ // deploy — re-running a known-bad deploy has no value when the
75
+ // tarball is unchanged (you'd just hit cache and produce the same
76
+ // failure). The user must opt into re-running a specific id if
77
+ // that's really what they want.
78
+ let sourceDeployId = input.deployId;
79
+ if (!sourceDeployId) {
80
+ const recent = await ctx.client.apps.listDeploys(app.id, { limit: 20 });
81
+ const lastLive = recent.find((d) => d.status === "live" && d.type !== "preview");
82
+ if (!lastLive) {
83
+ return failureResult({
84
+ title: "No live deploy to re-run",
85
+ explanation: `App "${appName}" has no successful live deploy in the last 20 entries.`,
86
+ suggestion: "Pass an explicit --deploy-id, or run `bunx percher publish` to make a fresh deploy first.",
87
+ });
88
+ }
89
+ sourceDeployId = lastLive.id;
90
+ }
91
+ ctx.status(`Re-running ${sourceDeployId}...`);
92
+ let initial;
93
+ try {
94
+ initial = await ctx.client.apps.rerunDeploy(app.id, sourceDeployId);
95
+ }
96
+ catch (err) {
97
+ if (err instanceof PercherApiError) {
98
+ // Codex P2 follow-up on 6ad76be: the canonical code is
99
+ // DEPLOY_RATE_LIMIT (singular, matches the API's throw site at
100
+ // routes/deploys.ts:370+675). The previous DEPLOY_RATE_LIMITED
101
+ // never matched, so hourly-limit hits bubbled as raw
102
+ // PercherApiError instead of a structured PublishResult.
103
+ switch (err.code) {
104
+ case "TARBALL_GONE":
105
+ return failureResult({
106
+ title: "Source tarball is gone",
107
+ explanation: "The deploy you tried to re-run has been retention-evicted. Percher only keeps tarballs for a bounded window per plan.",
108
+ suggestion: "Run `bunx percher publish` to upload a fresh tarball, then redeploy that one in the future.",
109
+ });
110
+ case "DAILY_QUOTA_EXCEEDED": {
111
+ // Mirror publish.ts's structured quota mapping so agents
112
+ // see kind/used/limit/resetAt and can advise the user when
113
+ // the counter resets. Codex P2 follow-up on 6ad76be — the
114
+ // generic ask_user fallback dropped these fields and made
115
+ // /redeploy a worse recovery path than /publish for the
116
+ // same failure.
117
+ const extra = err.extra ?? {};
118
+ const kind = extra.kind ?? "live";
119
+ const used = extra.used ?? 0;
120
+ const limit = extra.limit ?? 0;
121
+ const resetAt = extra.resetAt ?? "";
122
+ const otherKind = kind === "live" ? "preview" : "live";
123
+ return {
124
+ status: "failed",
125
+ app,
126
+ fileCount: 0,
127
+ bytes: 0,
128
+ error: {
129
+ title: "Daily deploy quota reached",
130
+ explanation: `You've used ${used} of ${limit} ${kind} deploys today on this account. Counter resets at ${resetAt}.`,
131
+ suggestion: `Wait until the counter resets, deploy a ${otherKind} instead, or upgrade your plan at https://percher.app/settings to raise this cap.`,
132
+ },
133
+ recovery: recoveryAsk({
134
+ prompt: `Daily ${kind}-deploy quota reached (${used}/${limit}). Counter resets at ${resetAt}. Wait until then, deploy a ${otherKind} instead, or upgrade at https://percher.app/settings.`,
135
+ options: ["wait", `deploy ${otherKind}`, "upgrade"],
136
+ reasonCode: "quota_exceeded",
137
+ }),
138
+ summary: `Daily ${kind}-deploy quota reached (${used}/${limit}). Resets ${resetAt}.`,
139
+ configPath: "",
140
+ bundle: { fileCount: 0, bytes: 0 },
141
+ };
142
+ }
143
+ case "DEPLOY_RATE_LIMIT":
144
+ // Per-app hourly cap from deploysPerHour. Throw site:
145
+ // routes/deploys.ts:640 (also :370 for POST /deploys).
146
+ return failureResult({
147
+ title: "Deploy rate limit reached",
148
+ explanation: err.message,
149
+ suggestion: "Wait a minute or two and try again. Hourly limits scale with your plan; upgrade at https://percher.app/settings to raise it.",
150
+ });
151
+ case "DEPLOY_RATE_LIMITED": {
152
+ // Per-app burst limit from middleware/rate-limit.ts:241.
153
+ // The middleware carries `retryAfterSec` in extra — surface
154
+ // it on recovery.args so agents can wait the correct
155
+ // duration instead of guessing. Codex P2 follow-up on
156
+ // ee194f4 — the previous fix removed this case thinking it
157
+ // was a typo, but the two codes are distinct gates that
158
+ // both fire from /rerun.
159
+ //
160
+ // Codex P2 follow-up on 1851aa4: include app + deployId in
161
+ // recovery.args so an agent can deterministically retry
162
+ // THIS redeploy via percher_redeploy. Without them, the
163
+ // fallback resolution ("latest live") would re-pick at
164
+ // retry time and could hit a different deploy than the
165
+ // user originally targeted.
166
+ const extra = err.extra ?? {};
167
+ const retryAfterSec = extra.retryAfterSec ?? 60;
168
+ return {
169
+ status: "failed",
170
+ app,
171
+ fileCount: 0,
172
+ bytes: 0,
173
+ error: {
174
+ title: "Deploy burst limit reached",
175
+ explanation: err.message,
176
+ suggestion: `Wait ${retryAfterSec}s and try again — this is a short-window burst limit, not the daily quota.`,
177
+ },
178
+ recovery: recoveryRetry({
179
+ suggestedTool: "percher_redeploy",
180
+ args: {
181
+ app: app.name,
182
+ deployId: sourceDeployId,
183
+ retryAfterSec,
184
+ code: "DEPLOY_RATE_LIMITED",
185
+ },
186
+ reasonCode: "infra_transient",
187
+ }),
188
+ summary: `Deploy burst limit hit. Retry in ${retryAfterSec}s.`,
189
+ configPath: "",
190
+ bundle: { fileCount: 0, bytes: 0 },
191
+ };
192
+ }
193
+ case "ACCOUNT_SUSPENDED":
194
+ case "APP_SUSPENDED":
195
+ case "EMAIL_NOT_VERIFIED":
196
+ case "PREVIEW_LIMIT_REACHED":
197
+ return failureResult({
198
+ title: err.message,
199
+ explanation: err.message,
200
+ suggestion: "See the suggestion in the API error response. This affordance is also surfaced via percher_publish on the next attempt.",
201
+ });
202
+ case "RETRY_LIMIT_REACHED": {
203
+ // Codex round 12 P1 fix — /rerun now mirrors POST /deploys's
204
+ // retry-state guard. Surface as ask_user with reasonCode
205
+ // retry_limit_reached so agents stop auto-retrying after the
206
+ // one allowed retry inside the 10-minute window.
207
+ const extra = err.extra ?? {};
208
+ const resetAt = extra.resetAt ?? "";
209
+ return {
210
+ status: "failed",
211
+ app,
212
+ fileCount: 0,
213
+ bytes: 0,
214
+ error: {
215
+ title: "Retry limit reached",
216
+ explanation: err.message,
217
+ suggestion: "Percher already retried once after an infrastructure failure for this app. Wait until the window resets or surface to the user.",
218
+ },
219
+ recovery: recoveryAsk({
220
+ prompt: `Percher already retried once after an infrastructure failure on ${app.name}. Wait until ${resetAt} or surface to the user.`,
221
+ options: ["wait before retrying", "inspect status"],
222
+ reasonCode: "retry_limit_reached",
223
+ retryable: false,
224
+ }),
225
+ summary: `Retry limit reached for ${app.name}. Resets ${resetAt}.`,
226
+ configPath: "",
227
+ bundle: { fileCount: 0, bytes: 0 },
228
+ };
229
+ }
230
+ case "REQUIRED_ENV_MISSING": {
231
+ // Codex round 12 P1 fix — /rerun now runs the Phase 6c env
232
+ // gate. Mirror publish.ts's mapping so agents get
233
+ // set_env_vars with the exact keys to set.
234
+ const extra = err.extra ?? {};
235
+ const keys = extra.keys ?? [];
236
+ return {
237
+ status: "failed",
238
+ app,
239
+ fileCount: 0,
240
+ bytes: 0,
241
+ error: {
242
+ title: "Missing required env keys",
243
+ explanation: err.message,
244
+ suggestion: `Set ${keys.length === 1 ? "it" : "them"} with \`bunx percher env set KEY=value\` and re-run.`,
245
+ errorClass: "missing_env",
246
+ missingEnvVars: keys,
247
+ },
248
+ recovery: recoveryEnv({
249
+ app: app.name,
250
+ keys,
251
+ reasonCode: "missing_env",
252
+ }),
253
+ summary: `Missing required env ${keys.length === 1 ? "key" : "keys"} on ${app.name}: ${keys.join(", ")}.`,
254
+ configPath: "",
255
+ bundle: { fileCount: 0, bytes: 0 },
256
+ };
257
+ }
258
+ case "ENV_KEY_UNDECLARED": {
259
+ // Codex round 12 P1 fix — /rerun now runs the Phase 6c env
260
+ // gate. Mirror publish.ts's fix_config mapping so agents
261
+ // get the per-ref problems for direct file edits.
262
+ const extra = err.extra ?? {};
263
+ const apiProblems = extra.problems ?? [];
264
+ const problems = apiProblems
265
+ .filter((p) => p.file)
266
+ .map((p) => ({
267
+ file: p.file,
268
+ line: p.line,
269
+ message: `Source references env key \`${p.key ?? "?"}\` not declared in [env]. Add it to [env].required, [env].optional, or [env].ignore in percher.toml.${p.context ? `\nContext: ${p.context}` : ""}`,
270
+ }));
271
+ return {
272
+ status: "failed",
273
+ app,
274
+ fileCount: 0,
275
+ bytes: 0,
276
+ error: {
277
+ title: "Env keys not declared",
278
+ explanation: err.message,
279
+ suggestion: "Add each undeclared key to [env].required / [env].optional / [env].ignore in percher.toml, then re-run.",
280
+ },
281
+ recovery: recoveryFixConfig({
282
+ problems,
283
+ reasonCode: "env_key_undeclared",
284
+ }),
285
+ summary: `${problems.length} undeclared env reference${problems.length === 1 ? "" : "s"} on ${app.name}.`,
286
+ configPath: "",
287
+ bundle: { fileCount: 0, bytes: 0 },
288
+ };
289
+ }
290
+ }
291
+ }
292
+ throw err;
293
+ }
294
+ // Poll the new deployment to terminal status. Mirrors publish's
295
+ // poll budget (sourced from the shared timeout contract — Phase 7.1)
296
+ // + heartbeat pattern, just compressed (no upload step to wait through).
297
+ const buildStart = Date.now();
298
+ const timeoutMs = TIMEOUTS.clientPublishPoll;
299
+ let lastStatus;
300
+ let nextHeartbeatMs = 15_000;
301
+ let deployment = initial;
302
+ let timedOut = null;
303
+ try {
304
+ deployment = await pollDeployment({
305
+ ctx,
306
+ appId: app.id,
307
+ initial,
308
+ intervalMs: 2000,
309
+ timeoutMs,
310
+ appName: app.name,
311
+ onTick: (d) => {
312
+ const elapsedMs = Date.now() - buildStart;
313
+ if (d.status !== lastStatus) {
314
+ ctx.status(`${d.status}...`);
315
+ lastStatus = d.status;
316
+ nextHeartbeatMs = elapsedMs + 15_000;
317
+ }
318
+ else if (elapsedMs >= nextHeartbeatMs) {
319
+ ctx.status(`${d.status}... (${Math.round(elapsedMs / 1000)}s elapsed)`);
320
+ nextHeartbeatMs = elapsedMs + 15_000;
321
+ }
322
+ },
323
+ onTimeout: (d) => {
324
+ timedOut = { deployment: d };
325
+ throw new (class PollTimeoutSentinel extends Error {
326
+ })("__poll_timeout__");
327
+ },
328
+ });
329
+ }
330
+ catch (err) {
331
+ if (!timedOut) {
332
+ return failureResult({
333
+ title: "Redeploy did not complete",
334
+ explanation: err instanceof Error
335
+ ? err.message
336
+ : "The deploy stopped responding before reaching a terminal state.",
337
+ suggestion: `Inspect with \`bunx percher deploys inspect ${initial.id}\`.`,
338
+ });
339
+ }
340
+ }
341
+ if (timedOut) {
342
+ const stuck = timedOut.deployment;
343
+ return failureResult({
344
+ title: "Redeploy timed out",
345
+ explanation: "The redeploy did not complete within 5 minutes.",
346
+ suggestion: `Inspect with \`bunx percher deploys inspect ${stuck.id}\`.`,
347
+ });
348
+ }
349
+ const totalSeconds = (Date.now() - t0) / 1000;
350
+ const url = deployment.previewUrl ?? deployment.url ?? app.url;
351
+ if (deployment.status === "failed") {
352
+ // P2 review-fix 2026-05-08: route through the same
353
+ // classifier the publish + wait paths use so failed
354
+ // redeploys get the same Phase 4 structured-code rendering
355
+ // (`WORKER_UNAVAILABLE` → "platform issue, retry" guidance,
356
+ // `DEPLOY_STALLED` → "republish" guidance, etc.). Before
357
+ // this, redeploy failures always rendered as a generic
358
+ // build_failed regardless of `deployment.errorCode`.
359
+ const { error, recovery, summary } = await classifyDeploymentFailure({
360
+ ctx,
361
+ app,
362
+ deployment,
363
+ });
364
+ return {
365
+ status: "failed",
366
+ app,
367
+ deployment,
368
+ fileCount: 0,
369
+ bytes: 0,
370
+ error,
371
+ recovery,
372
+ summary,
373
+ configPath: "",
374
+ bundle: { fileCount: 0, bytes: 0 },
375
+ };
376
+ }
377
+ // FUTURE1 Phase 1.6 — detect cache hit so the summary tells the
378
+ // user "cached, Ns" when the build skipped. Best-effort; left
379
+ // undefined on fetch failure (caller distinguishes that from
380
+ // confirmed false).
381
+ let cacheHit;
382
+ try {
383
+ const { events } = await ctx.client.apps.getDeployEvents(app.id, deployment.id);
384
+ cacheHit = events.some((e) => e.stage === "build" && e.status === "ok" && e.subStage === "cache_hit");
385
+ }
386
+ catch {
387
+ /* leave undefined */
388
+ }
389
+ ctx.status(`Live at ${url} (${totalSeconds.toFixed(0)}s)`);
390
+ const cacheTag = cacheHit ? "cached, " : "";
391
+ return {
392
+ status: "live",
393
+ app,
394
+ deployment,
395
+ url,
396
+ timing: { totalSeconds, packageMs: 0, uploadMs: 0, buildMs: Date.now() - buildStart },
397
+ fileCount: 0,
398
+ bytes: 0,
399
+ cacheHit,
400
+ recovery: RECOVERY_NONE,
401
+ summary: `${appName} redeployed (${cacheTag}${totalSeconds.toFixed(0)}s) → ${url}`,
402
+ configPath: "",
403
+ bundle: { fileCount: 0, bytes: 0 },
404
+ };
405
+ }
406
+ function failureResult(error) {
407
+ return {
408
+ status: "failed",
409
+ fileCount: 0,
410
+ bytes: 0,
411
+ error,
412
+ recovery: recoveryAsk({
413
+ prompt: `${error.title}: ${error.explanation} ${error.suggestion}`.trim(),
414
+ reasonCode: "unknown",
415
+ }),
416
+ summary: error.title,
417
+ configPath: "",
418
+ bundle: { fileCount: 0, bytes: 0 },
419
+ };
420
+ }
421
+ //# sourceMappingURL=redeploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redeploy.js","sourceRoot":"","sources":["../../src/commands/redeploy.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { z } from "zod";
1
+ import { z } from "zod/v3";
2
2
  import type { Context } from "../context";
3
3
  export declare const renameInputSchema: z.ZodObject<{
4
4
  app: z.ZodOptional<z.ZodString>;
@@ -1 +1 @@
1
- {"version":3,"file":"rename.d.ts","sourceRoot":"","sources":["../../src/commands/rename.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,eAAO,MAAM,iBAAiB;;;;;;;;;EAG5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CASpF"}
1
+ {"version":3,"file":"rename.d.ts","sourceRoot":"","sources":["../../src/commands/rename.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,eAAO,MAAM,iBAAiB;;;;;;;;;EAG5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CASpF"}
@@ -1,4 +1,4 @@
1
- import { z } from "zod";
1
+ import { z } from "zod/v3";
2
2
  import { readPercherTomlAppName } from "../app-name";
3
3
  import { PercherCoreError } from "../errors";
4
4
  export const renameInputSchema = z.object({
@@ -1 +1 @@
1
- {"version":3,"file":"rename.js","sourceRoot":"","sources":["../../src/commands/rename.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;CAChC,CAAC,CAAC;AAUH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,GAAY,EAAE,KAAkB;IAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,IAAI,sBAAsB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,gBAAgB,CAAC,4CAA4C,EAAE;YACvE,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,6DAA6D;SACpE,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC"}
1
+ {"version":3,"file":"rename.js","sourceRoot":"","sources":["../../src/commands/rename.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;CAChC,CAAC,CAAC;AAUH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,GAAY,EAAE,KAAkB;IAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,IAAI,sBAAsB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,gBAAgB,CAAC,4CAA4C,EAAE;YACvE,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,6DAA6D;SACpE,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { z } from "zod/v3";
2
+ import type { Context } from "../context";
3
+ export declare const reproduceInputSchema: z.ZodObject<{
4
+ app: z.ZodOptional<z.ZodString>;
5
+ deployId: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ deployId: string;
8
+ app?: string | undefined;
9
+ }, {
10
+ deployId: string;
11
+ app?: string | undefined;
12
+ }>;
13
+ export type ReproduceInput = z.infer<typeof reproduceInputSchema>;
14
+ export interface ReproduceResult {
15
+ status: "extracted" | "extracted_and_built" | "needs_login" | "failed";
16
+ /** Absolute path to the extracted source. Always set on extracted/built. */
17
+ tmpDir?: string;
18
+ /** Path to the downloaded .tar.gz when extraction failed and the user
19
+ * should run `tar -xzf` manually. Set when status === "extracted" and
20
+ * no extraction took place. */
21
+ tarballPath?: string;
22
+ /** App name resolved at the start. Echoed back so an agent can pass
23
+ * it to follow-up tools without re-resolving. */
24
+ appName?: string;
25
+ /** Deploy id passed in. Echoed back for the same reason. */
26
+ deployId: string;
27
+ /**
28
+ * Env keys (NOT values) currently configured on the app. These reflect
29
+ * the *current* state of the env store, NOT a snapshot taken at the
30
+ * failed deploy's build time — Percher doesn't persist a per-deploy
31
+ * env snapshot today (Phase 1's image cache hashes them, but doesn't
32
+ * store them). If the user rotated keys between the failure and the
33
+ * reproduce, this list reflects the rotation. Treat as a starting
34
+ * hint, not a deploy-time inventory. Codex P2 follow-up on 3b609f9.
35
+ */
36
+ currentAppEnvKeys?: string[];
37
+ /** Whether nixpacks was found and ran successfully against the
38
+ * extracted source. False when nixpacks isn't installed locally OR
39
+ * when the local build also failed (in which case the user has the
40
+ * same error reproduced and can iterate from there). */
41
+ builtLocally?: boolean;
42
+ /** Human-readable summary echoed verbatim to humans. Always set. */
43
+ summary: string;
44
+ /** Optional error envelope when status === "failed". */
45
+ error?: {
46
+ title: string;
47
+ explanation: string;
48
+ suggestion: string;
49
+ };
50
+ }
51
+ /**
52
+ * FUTURE1 Phase 4.2 — download a deploy's source tarball + (optionally)
53
+ * run nixpacks against it locally. The intended use is "build failed
54
+ * in cloud, reproduce here to fix" — surfaced via
55
+ * `recovery.alternativeActions[]` after `inspect_build_log` didn't
56
+ * yield a clear fix.
57
+ *
58
+ * Privacy invariant: env values are NEVER fetched. The endpoint
59
+ * surfaces only env *keys* so the user knows what to set locally; the
60
+ * values come from their own machine (or stay missing if compile-only
61
+ * errors are what we're debugging).
62
+ */
63
+ export declare function reproduce(ctx: Context, input: ReproduceInput): Promise<ReproduceResult>;
64
+ //# sourceMappingURL=reproduce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reproduce.d.ts","sourceRoot":"","sources":["../../src/commands/reproduce.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,eAAO,MAAM,oBAAoB;;;;;;;;;EAU/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,WAAW,GAAG,qBAAqB,GAAG,aAAa,GAAG,QAAQ,CAAC;IACvE,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;oCAEgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;sDACkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B;;;6DAGyD;IACzD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CACpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAgM7F"}