@abloatai/cli 0.53.0 → 0.55.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 (2) hide show
  1. package/dist/cli.cjs +1095 -704
  2. package/package.json +3 -3
package/dist/cli.cjs CHANGED
@@ -787,8 +787,8 @@ ${import_picocolors2.default.gray(d2)} ${t}
787
787
  if (i) process.stdout.write(`${I2} ${l2}...`);
788
788
  else if (t === "timer") process.stdout.write(`${I2} ${l2} ${O2(g2)}`);
789
789
  else {
790
- const z7 = ".".repeat(Math.floor(w2)).slice(0, 3);
791
- process.stdout.write(`${I2} ${l2}${z7}`);
790
+ const z8 = ".".repeat(Math.floor(w2)).slice(0, 3);
791
+ process.stdout.write(`${I2} ${l2}${z8}`);
792
792
  }
793
793
  h2 = h2 + 1 < n.length ? h2 + 1 : 0, w2 = w2 < n.length ? w2 + 0.125 : 0;
794
794
  }, r2);
@@ -3970,7 +3970,7 @@ var init_observeCliError = __esm({
3970
3970
  import_errorObservation = require("@abloatai/transaction/errorObservation");
3971
3971
  import_errors5 = require("@abloatai/transaction/errors");
3972
3972
  dsn = process.env.ABLO_CLI_SENTRY_DSN ?? "https://1ac154bff10b06836e1ea9de9e0d92f0@o4510928209772544.ingest.de.sentry.io/4511660691423312" ?? "";
3973
- release = process.env.ABLO_CLI_RELEASE ?? "@abloatai/cli@0.53.0";
3973
+ release = process.env.ABLO_CLI_RELEASE ?? "@abloatai/cli@0.55.0";
3974
3974
  initialized = false;
3975
3975
  nativeProcessExit = process.exit.bind(process);
3976
3976
  exitBoundaryInstalled = false;
@@ -4295,6 +4295,30 @@ var init_src2 = __esm({
4295
4295
  }
4296
4296
  });
4297
4297
 
4298
+ // src/cliEnvironment.ts
4299
+ function cliVersion() {
4300
+ return "0.55.0";
4301
+ }
4302
+ function cliOs() {
4303
+ const value = (0, import_node_os.platform)();
4304
+ return value === "darwin" || value === "linux" || value === "win32" ? value : "other";
4305
+ }
4306
+ function cliArchitecture() {
4307
+ const value = (0, import_node_os.arch)();
4308
+ return value === "arm64" || value === "x64" || value === "ia32" ? value : "other";
4309
+ }
4310
+ function nodeMajorVersion() {
4311
+ return Number(process.versions.node.split(".")[0]);
4312
+ }
4313
+ var import_node_os;
4314
+ var init_cliEnvironment = __esm({
4315
+ "src/cliEnvironment.ts"() {
4316
+ "use strict";
4317
+ init_cjs_shims();
4318
+ import_node_os = require("os");
4319
+ }
4320
+ });
4321
+
4298
4322
  // src/telemetry.ts
4299
4323
  function telemetryPath() {
4300
4324
  return (0, import_node_path.join)(configDir(), "telemetry.json");
@@ -4455,17 +4479,6 @@ function environmentBlocker() {
4455
4479
  function truthyEnvironmentValue(value) {
4456
4480
  return value !== void 0 && value !== "" && value !== "0" && value.toLowerCase() !== "false";
4457
4481
  }
4458
- function cliVersion() {
4459
- return "0.53.0";
4460
- }
4461
- function cliOs() {
4462
- const value = (0, import_node_os.platform)();
4463
- return value === "darwin" || value === "linux" || value === "win32" ? value : "other";
4464
- }
4465
- function cliArchitecture() {
4466
- const value = (0, import_node_os.arch)();
4467
- return value === "arm64" || value === "x64" || value === "ia32" ? value : "other";
4468
- }
4469
4482
  function durationBucket(durationMs) {
4470
4483
  if (durationMs < 1e3) return "under_1s";
4471
4484
  if (durationMs < 5e3) return "1s_to_5s";
@@ -4489,16 +4502,16 @@ function runTelemetryCommand(argv) {
4489
4502
  if (status2.blockedBy) console.log(`Environment override: ${status2.blockedBy}`);
4490
4503
  console.log(`Queued events: ${status2.queuedEvents}`);
4491
4504
  }
4492
- var import_node_crypto2, import_node_fs, import_node_os, import_node_path, TELEMETRY_FILE_VERSION, MAX_QUEUED_EVENTS, MAX_FLUSH_EVENTS, DEFAULT_FLUSH_TIMEOUT_MS, flushInFlight;
4505
+ var import_node_crypto2, import_node_fs, import_node_path, TELEMETRY_FILE_VERSION, MAX_QUEUED_EVENTS, MAX_FLUSH_EVENTS, DEFAULT_FLUSH_TIMEOUT_MS, flushInFlight;
4493
4506
  var init_telemetry = __esm({
4494
4507
  "src/telemetry.ts"() {
4495
4508
  "use strict";
4496
4509
  init_cjs_shims();
4497
4510
  import_node_crypto2 = require("crypto");
4498
4511
  import_node_fs = require("fs");
4499
- import_node_os = require("os");
4500
4512
  import_node_path = require("path");
4501
4513
  init_src2();
4514
+ init_cliEnvironment();
4502
4515
  init_controlPlane();
4503
4516
  init_config();
4504
4517
  TELEMETRY_FILE_VERSION = 1;
@@ -5955,6 +5968,28 @@ async function fetchPushedSchema(apiUrl3, apiKey) {
5955
5968
  clearTimeout(t);
5956
5969
  }
5957
5970
  }
5971
+ async function fetchDeliveryState(apiUrl3, apiKey, timeoutMs = 4e3) {
5972
+ if (!apiKey) return { kind: "unknown", detail: "no key" };
5973
+ const ctrl = new AbortController();
5974
+ const t = setTimeout(() => {
5975
+ ctrl.abort();
5976
+ }, timeoutMs);
5977
+ try {
5978
+ const res = await fetch(`${apiUrl3}/api/v1/logs/delivery`, {
5979
+ headers: { authorization: `Bearer ${apiKey}` },
5980
+ signal: ctrl.signal
5981
+ });
5982
+ if (!res.ok) return { kind: "unknown", detail: `HTTP ${res.status}` };
5983
+ const parsed = import_wire5.logDeliveryResponseSchema.safeParse(await res.json());
5984
+ if (!parsed.success) return { kind: "unknown", detail: "unrecognized response" };
5985
+ const { window_seconds, recorded, unroutable, sample } = parsed.data;
5986
+ return { kind: "known", window_seconds, recorded, unroutable, sample: sample ?? null };
5987
+ } catch {
5988
+ return { kind: "unknown", detail: "unreachable" };
5989
+ } finally {
5990
+ clearTimeout(t);
5991
+ }
5992
+ }
5958
5993
  async function fetchDataSourceState(apiUrl3, apiKey, timeoutMs = 4e3) {
5959
5994
  if (!apiKey) return { kind: "unknown", detail: "no key" };
5960
5995
  const ctrl = new AbortController();
@@ -6056,7 +6091,7 @@ function blockers(input) {
6056
6091
  }
6057
6092
  return found;
6058
6093
  }
6059
- var import_wire5, import_schema4;
6094
+ var import_wire5, import_schema4, WRITE_READY_VERDICT;
6060
6095
  var init_readiness = __esm({
6061
6096
  "src/readiness.ts"() {
6062
6097
  "use strict";
@@ -6066,6 +6101,7 @@ var init_readiness = __esm({
6066
6101
  init_dbProvider();
6067
6102
  init_remoteValidation();
6068
6103
  import_schema4 = require("@abloatai/transaction/schema");
6104
+ WRITE_READY_VERDICT = "write infrastructure is ready. Your database constraints and row-level policies still apply.";
6069
6105
  }
6070
6106
  });
6071
6107
 
@@ -219754,11 +219790,11 @@ var require_commonjs2 = __commonJS({
219754
219790
  if (pad2) {
219755
219791
  const need = width - c.length;
219756
219792
  if (need > 0) {
219757
- const z7 = new Array(need + 1).join("0");
219793
+ const z8 = new Array(need + 1).join("0");
219758
219794
  if (i < 0) {
219759
- c = "-" + z7 + c.slice(1);
219795
+ c = "-" + z8 + c.slice(1);
219760
219796
  } else {
219761
- c = z7 + c;
219797
+ c = z8 + c;
219762
219798
  }
219763
219799
  }
219764
219800
  }
@@ -283732,7 +283768,7 @@ Node text: ${this.#forgottenText}`;
283732
283768
 
283733
283769
  // src/index.ts
283734
283770
  init_cjs_shims();
283735
- var import_picocolors30 = __toESM(require_picocolors(), 1);
283771
+ var import_picocolors31 = __toESM(require_picocolors(), 1);
283736
283772
 
283737
283773
  // src/migrate.ts
283738
283774
  init_cjs_shims();
@@ -284085,9 +284121,287 @@ function truncate(text, max) {
284085
284121
  return collapsed.length <= max ? collapsed : `${collapsed.slice(0, max - 1).trimEnd()}\u2026`;
284086
284122
  }
284087
284123
 
284088
- // src/branches.ts
284124
+ // ../product-analytics/src/feedback.ts
284125
+ init_cjs_shims();
284126
+ var import_node_crypto3 = require("crypto");
284127
+ var import_zod5 = require("zod");
284128
+ init_events();
284129
+ var AGENT_FEEDBACK_VERSION = 1;
284130
+ var MAX_FEEDBACK_SUMMARY_LENGTH = 200;
284131
+ var MAX_FEEDBACK_DETAIL_LENGTH = 4e3;
284132
+ var FEEDBACK_KINDS = ["bug", "docs", "feature", "friction"];
284133
+ var feedbackKindSchema = import_zod5.z.enum(FEEDBACK_KINDS);
284134
+ var FEEDBACK_KIND_DESCRIPTIONS = {
284135
+ bug: "It broke, or did something other than what it said it would.",
284136
+ docs: "The answer was missing from the docs, or the docs were wrong.",
284137
+ feature: "The thing you needed does not exist yet.",
284138
+ friction: "It worked, and it was harder than it should have been."
284139
+ };
284140
+ var shortToken2 = import_zod5.z.string().trim().min(1).max(100);
284141
+ var feedbackContextSchema = import_zod5.z.strictObject({
284142
+ /** The command in play, e.g. `push` — the registry name, not the full argv. */
284143
+ command: shortToken2.optional(),
284144
+ /** A code from the `ERROR_CODES` registry. The strongest clustering signal
284145
+ * there is: it groups reports by the failure, not by how it was worded. */
284146
+ errorCode: shortToken2.optional(),
284147
+ /** Which agent is reporting, e.g. `claude-code`. The world owns this set and
284148
+ * adds to it faster than we could ship an enum, so it stays an open token. */
284149
+ reportedBy: shortToken2.optional(),
284150
+ cliVersion: shortToken2.optional(),
284151
+ os: cliOsSchema.optional(),
284152
+ architecture: cliArchitectureSchema.optional(),
284153
+ nodeMajorVersion: import_zod5.z.number().int().min(18).max(100).optional()
284154
+ });
284155
+ var agentFeedbackSchema = import_zod5.z.strictObject({
284156
+ feedbackVersion: import_zod5.z.literal(AGENT_FEEDBACK_VERSION),
284157
+ /** Idempotency: a retried submission is the same report, not a second one. */
284158
+ submissionId: import_zod5.z.uuid(),
284159
+ occurredAt: import_zod5.z.iso.datetime({ offset: true }),
284160
+ kind: feedbackKindSchema,
284161
+ /** One line. This is the ticket title a human reads in a list. */
284162
+ summary: import_zod5.z.string().trim().min(1).max(MAX_FEEDBACK_SUMMARY_LENGTH),
284163
+ /** What happened, in the reporter's own words. */
284164
+ detail: import_zod5.z.string().trim().min(1).max(MAX_FEEDBACK_DETAIL_LENGTH).optional(),
284165
+ context: feedbackContextSchema.default({})
284166
+ });
284167
+ var agentFeedbackSubmissionSchema = import_zod5.z.strictObject({
284168
+ feedback: agentFeedbackSchema
284169
+ });
284170
+ var agentFeedbackReceiptSchema = import_zod5.z.strictObject({
284171
+ submissionId: import_zod5.z.uuid(),
284172
+ accepted: import_zod5.z.boolean(),
284173
+ duplicate: import_zod5.z.boolean(),
284174
+ clusterKey: import_zod5.z.string(),
284175
+ clusterCount: import_zod5.z.number().int().positive()
284176
+ });
284177
+
284178
+ // src/feedback.ts
284089
284179
  init_cjs_shims();
284180
+ var import_node_crypto4 = require("crypto");
284181
+ var import_node_fs2 = require("fs");
284090
284182
  var import_picocolors14 = __toESM(require_picocolors(), 1);
284183
+ init_dist2();
284184
+ var import_errors12 = require("@abloatai/transaction/errors");
284185
+ var import_errorObservation2 = require("@abloatai/transaction/errorObservation");
284186
+ init_cliEnvironment();
284187
+ init_controlPlane();
284188
+ init_config();
284189
+ init_theme();
284190
+ var KIND_WIDTH = Math.max(...FEEDBACK_KINDS.map((kind) => kind.length));
284191
+ var USAGE_LINES = FEEDBACK_KINDS.map(
284192
+ (kind) => ` npx ablo feedback ${kind.padEnd(KIND_WIDTH)} "<one line>" [--detail <text>]`
284193
+ ).join("\n");
284194
+ var KIND_LINES = FEEDBACK_KINDS.map(
284195
+ (kind) => ` ${kind.padEnd(KIND_WIDTH + 2)}${FEEDBACK_KIND_DESCRIPTIONS[kind]}`
284196
+ ).join("\n");
284197
+ var FEEDBACK_USAGE = ` ablo feedback \u2014 tell us what got in your way
284198
+
284199
+ Usage
284200
+ ${USAGE_LINES}
284201
+
284202
+ Kinds
284203
+ ${KIND_LINES}
284204
+
284205
+ Options
284206
+ --detail <text> What happened, at length. Use \`-\` to read stdin.
284207
+ --command <name> The command in play, e.g. \`push\`.
284208
+ --error-code <code> The code the failure printed, e.g. \`schema_unknown_model\`.
284209
+ --from <agent> Who is reporting, e.g. \`claude-code\`. Detected when omitted.
284210
+ --yes Send without the confirmation step (agents/CI).
284211
+ --json Print the receipt as JSON.
284212
+
284213
+ Connection strings, API keys, and addresses are removed from what you write
284214
+ before it is sent, and on a terminal you see the redacted text first. Nothing
284215
+ is read from your repository. Reports are grouped by what they describe, so
284216
+ the receipt tells you how many others have hit the same thing.`;
284217
+ function parseFeedbackArgs(argv) {
284218
+ const kindRaw = argv[0];
284219
+ const kind = feedbackKindSchema.safeParse(kindRaw);
284220
+ if (!kind.success) {
284221
+ throw new import_errors12.AbloValidationError(
284222
+ `\`ablo feedback\` needs a kind first: ${FEEDBACK_KINDS.join(", ")}.`,
284223
+ { code: "cli_invalid_arguments" }
284224
+ );
284225
+ }
284226
+ const positional2 = [];
284227
+ let detail;
284228
+ let command;
284229
+ let errorCode;
284230
+ let from;
284231
+ let yes = false;
284232
+ let json = false;
284233
+ const flagValue = (flag2, value) => {
284234
+ if (value === void 0 || value.startsWith("--")) {
284235
+ throw new import_errors12.AbloValidationError(`\`${flag2}\` needs a value.`, {
284236
+ code: "cli_invalid_arguments"
284237
+ });
284238
+ }
284239
+ return value;
284240
+ };
284241
+ for (let i = 1; i < argv.length; i++) {
284242
+ const arg = argv[i];
284243
+ switch (arg) {
284244
+ case "--detail":
284245
+ detail = flagValue("--detail", argv[++i]);
284246
+ break;
284247
+ case "--command":
284248
+ command = flagValue("--command", argv[++i]);
284249
+ break;
284250
+ case "--error-code":
284251
+ errorCode = flagValue("--error-code", argv[++i]);
284252
+ break;
284253
+ case "--from":
284254
+ from = flagValue("--from", argv[++i]);
284255
+ break;
284256
+ case "--yes":
284257
+ yes = true;
284258
+ break;
284259
+ case "--json":
284260
+ json = true;
284261
+ break;
284262
+ default:
284263
+ if (arg !== void 0 && arg.startsWith("--")) {
284264
+ throw new import_errors12.AbloValidationError(`\`${arg}\` is not an option of this command.`, {
284265
+ code: "cli_invalid_arguments"
284266
+ });
284267
+ }
284268
+ if (arg !== void 0) positional2.push(arg);
284269
+ }
284270
+ }
284271
+ const summary = positional2.join(" ").trim();
284272
+ if (!summary) {
284273
+ throw new import_errors12.AbloValidationError(
284274
+ "Say in one line what got in your way, in quotes after the kind.",
284275
+ { code: "cli_invalid_arguments" }
284276
+ );
284277
+ }
284278
+ if (summary.length > MAX_FEEDBACK_SUMMARY_LENGTH) {
284279
+ throw new import_errors12.AbloValidationError(
284280
+ `Keep the first line under ${MAX_FEEDBACK_SUMMARY_LENGTH} characters and put the rest in \`--detail\`.`,
284281
+ { code: "cli_invalid_arguments" }
284282
+ );
284283
+ }
284284
+ return {
284285
+ kind: kind.data,
284286
+ summary,
284287
+ ...detail !== void 0 ? { detail } : {},
284288
+ ...command !== void 0 ? { command } : {},
284289
+ ...errorCode !== void 0 ? { errorCode } : {},
284290
+ ...from !== void 0 ? { from } : {},
284291
+ yes,
284292
+ json
284293
+ };
284294
+ }
284295
+ async function feedback(argv) {
284296
+ if (argv.includes("--help") || argv.includes("-h") || argv.length === 0) {
284297
+ console.log(FEEDBACK_USAGE);
284298
+ return;
284299
+ }
284300
+ const args = parseFeedbackArgs(argv);
284301
+ const detail = args.detail === "-" ? readStdin() : args.detail;
284302
+ if (detail !== void 0 && detail.length > MAX_FEEDBACK_DETAIL_LENGTH) {
284303
+ throw new import_errors12.AbloValidationError(
284304
+ `\`--detail\` holds up to ${MAX_FEEDBACK_DETAIL_LENGTH} characters.`,
284305
+ { code: "cli_invalid_arguments" }
284306
+ );
284307
+ }
284308
+ const reporter = reportedBy(args.from);
284309
+ const report = agentFeedbackSchema.parse({
284310
+ feedbackVersion: AGENT_FEEDBACK_VERSION,
284311
+ submissionId: (0, import_node_crypto4.randomUUID)(),
284312
+ occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
284313
+ kind: args.kind,
284314
+ summary: (0, import_errorObservation2.redactObservationString)(args.summary),
284315
+ ...detail ? { detail: (0, import_errorObservation2.redactObservationString)(detail) } : {},
284316
+ context: {
284317
+ ...args.command !== void 0 ? { command: args.command } : {},
284318
+ ...args.errorCode !== void 0 ? { errorCode: args.errorCode } : {},
284319
+ ...reporter !== void 0 ? { reportedBy: reporter } : {},
284320
+ cliVersion: cliVersion(),
284321
+ os: cliOs(),
284322
+ architecture: cliArchitecture(),
284323
+ nodeMajorVersion: nodeMajorVersion()
284324
+ }
284325
+ });
284326
+ const interactive = Boolean(process.stdout.isTTY && process.stdin.isTTY) && !args.yes;
284327
+ if (interactive) {
284328
+ printPreview(report);
284329
+ const proceed = await ye({ message: "Send this?" });
284330
+ if (pD(proceed) || !proceed) {
284331
+ console.log(` ${import_picocolors14.default.dim("Nothing sent.")}`);
284332
+ return;
284333
+ }
284334
+ }
284335
+ const managementKey = resolveManagementKey();
284336
+ const receipt = await requestControlPlane({
284337
+ path: "/v1/feedback",
284338
+ method: "POST",
284339
+ body: { feedback: report },
284340
+ ...managementKey !== void 0 ? { apiKey: managementKey } : {},
284341
+ responseSchema: agentFeedbackReceiptSchema,
284342
+ timeoutMs: 1e4
284343
+ });
284344
+ if (args.json || process.env.ABLO_JSON === "1") {
284345
+ console.log(JSON.stringify(receipt, null, 2));
284346
+ return;
284347
+ }
284348
+ if (receipt.duplicate) {
284349
+ console.log(` ${import_picocolors14.default.dim("Already recorded \u2014 this report was sent before.")}`);
284350
+ return;
284351
+ }
284352
+ console.log(` ${import_picocolors14.default.green("\u2713")} Thank you. Recorded as ${import_picocolors14.default.dim(receipt.submissionId)}`);
284353
+ if (receipt.clusterCount > 1) {
284354
+ console.log(
284355
+ ` ${import_picocolors14.default.dim(`${receipt.clusterCount} reports describe this same thing.`)}`
284356
+ );
284357
+ }
284358
+ }
284359
+ function printPreview(report) {
284360
+ console.log(`
284361
+ ${brand("ablo")} ${import_picocolors14.default.dim("feedback")} ${import_picocolors14.default.dim(report.kind)}
284362
+ `);
284363
+ console.log(` ${report.summary}`);
284364
+ if (report.detail) {
284365
+ console.log();
284366
+ for (const line of report.detail.split("\n")) console.log(` ${import_picocolors14.default.dim(line)}`);
284367
+ }
284368
+ const context = [
284369
+ report.context.command ? `command ${report.context.command}` : null,
284370
+ report.context.errorCode ? `code ${report.context.errorCode}` : null,
284371
+ report.context.reportedBy ? `from ${report.context.reportedBy}` : null,
284372
+ report.context.cliVersion ? `cli ${report.context.cliVersion}` : null,
284373
+ report.context.os ?? null
284374
+ ].filter((entry) => entry !== null);
284375
+ console.log(`
284376
+ ${import_picocolors14.default.dim(context.join(" \xB7 "))}
284377
+ `);
284378
+ }
284379
+ function reportedBy(explicit) {
284380
+ if (explicit) return explicit;
284381
+ const configured = process.env.ABLO_AGENT?.trim();
284382
+ if (configured) return configured;
284383
+ if (process.env.CLAUDECODE || process.env.CLAUDE_CODE_ENTRYPOINT) return "claude-code";
284384
+ return void 0;
284385
+ }
284386
+ function readStdin() {
284387
+ if (process.stdin.isTTY) {
284388
+ throw new import_errors12.AbloValidationError(
284389
+ "`--detail -` reads piped input. Pass the text directly instead.",
284390
+ { code: "cli_invalid_arguments" }
284391
+ );
284392
+ }
284393
+ try {
284394
+ return (0, import_node_fs2.readFileSync)(0, "utf8").trim();
284395
+ } catch {
284396
+ throw new import_errors12.AbloValidationError("Could not read `--detail` from stdin.", {
284397
+ code: "cli_invalid_arguments"
284398
+ });
284399
+ }
284400
+ }
284401
+
284402
+ // src/branches.ts
284403
+ init_cjs_shims();
284404
+ var import_picocolors15 = __toESM(require_picocolors(), 1);
284091
284405
  var import_branches = require("@abloatai/transaction/branches");
284092
284406
  init_controlPlane();
284093
284407
  init_config();
@@ -284150,12 +284464,12 @@ function valueAfter(argv, flag2) {
284150
284464
  function print(branches2) {
284151
284465
  const slugWidth = Math.max(...branches2.map((branch) => branch.slug.length), 6);
284152
284466
  for (const branch of branches2) {
284153
- const marker = branch.root ? import_picocolors14.default.green("\u25CF") : import_picocolors14.default.dim("\u25CB");
284154
- const kind = branch.root ? import_picocolors14.default.green("root") : import_picocolors14.default.dim(branch.kind);
284155
- const state = branch.state === "ready" ? import_picocolors14.default.green(branch.state) : import_picocolors14.default.yellow(branch.state);
284156
- const expiry = branch.expires_at ? import_picocolors14.default.dim(` expires ${new Date(branch.expires_at).toLocaleDateString()}`) : "";
284467
+ const marker = branch.root ? import_picocolors15.default.green("\u25CF") : import_picocolors15.default.dim("\u25CB");
284468
+ const kind = branch.root ? import_picocolors15.default.green("root") : import_picocolors15.default.dim(branch.kind);
284469
+ const state = branch.state === "ready" ? import_picocolors15.default.green(branch.state) : import_picocolors15.default.yellow(branch.state);
284470
+ const expiry = branch.expires_at ? import_picocolors15.default.dim(` expires ${new Date(branch.expires_at).toLocaleDateString()}`) : "";
284157
284471
  console.log(
284158
- ` ${marker} ${branch.slug.padEnd(slugWidth)} ${kind.padEnd(12)} ${state.padEnd(14)} ${import_picocolors14.default.dim(branch.id)}${expiry}`
284472
+ ` ${marker} ${branch.slug.padEnd(slugWidth)} ${kind.padEnd(12)} ${state.padEnd(14)} ${import_picocolors15.default.dim(branch.id)}${expiry}`
284159
284473
  );
284160
284474
  }
284161
284475
  }
@@ -284203,32 +284517,32 @@ async function readStatus(ref, context = {}) {
284203
284517
  }
284204
284518
  function printStatus(status2) {
284205
284519
  const { branch, schema, storage, data_source: source } = status2;
284206
- console.log(` ${import_picocolors14.default.bold(branch.slug)} ${import_picocolors14.default.dim(branch.id)}`);
284520
+ console.log(` ${import_picocolors15.default.bold(branch.slug)} ${import_picocolors15.default.dim(branch.id)}`);
284207
284521
  console.log(
284208
- ` ${import_picocolors14.default.dim("state")} ${branch.state === "ready" ? import_picocolors14.default.green(branch.state) : import_picocolors14.default.yellow(branch.state)}`
284522
+ ` ${import_picocolors15.default.dim("state")} ${branch.state === "ready" ? import_picocolors15.default.green(branch.state) : import_picocolors15.default.yellow(branch.state)}`
284209
284523
  );
284210
284524
  console.log(
284211
- ` ${import_picocolors14.default.dim("schema")} ${schema.active ? `${import_picocolors14.default.green("active")} ${import_picocolors14.default.dim(`v${schema.version ?? "?"} \xB7 ${schema.hash ?? "no hash"}`)}` : import_picocolors14.default.red("missing")}`
284525
+ ` ${import_picocolors15.default.dim("schema")} ${schema.active ? `${import_picocolors15.default.green("active")} ${import_picocolors15.default.dim(`v${schema.version ?? "?"} \xB7 ${schema.hash ?? "no hash"}`)}` : import_picocolors15.default.red("missing")}`
284212
284526
  );
284213
284527
  if (!branch.root) {
284214
- const counts = schema.changes > 0 ? import_picocolors14.default.dim(
284528
+ const counts = schema.changes > 0 ? import_picocolors15.default.dim(
284215
284529
  ` \xB7 ${schema.changes} changes, ${schema.warnings} warnings, ${schema.blockers} blockers`
284216
284530
  ) : "";
284217
284531
  console.log(
284218
- ` ${import_picocolors14.default.dim("parent")} ${import_picocolors14.default.bold(schema.parent_compatibility)}${counts}`
284532
+ ` ${import_picocolors15.default.dim("parent")} ${import_picocolors15.default.bold(schema.parent_compatibility)}${counts}`
284219
284533
  );
284220
284534
  }
284221
284535
  const sourceLabel = source ? `${source.connection} \xB7 ${source.host ?? "unknown host"}${source.database ? `/${source.database}` : ""} \xB7 ${source.status}` : storage.kind === "unbound" ? "not connected to a database" : storage.kind === "internal" ? `Ablo internal product storage \xB7 ${storage.implementation}` : storage.kind === "blocked" ? "storage configuration needs attention" : "customer database connection unavailable";
284222
- console.log(` ${import_picocolors14.default.dim("data")} ${sourceLabel}`);
284536
+ console.log(` ${import_picocolors15.default.dim("data")} ${sourceLabel}`);
284223
284537
  if (status2.ready) {
284224
284538
  console.log(`
284225
- ${import_picocolors14.default.green("\u2713 ready")}`);
284539
+ ${import_picocolors15.default.green("\u2713 ready")}`);
284226
284540
  } else {
284227
284541
  console.log(`
284228
- ${import_picocolors14.default.red("\u2717 not ready")}`);
284542
+ ${import_picocolors15.default.red("\u2717 not ready")}`);
284229
284543
  for (const blocker2 of status2.blockers) {
284230
- console.log(` ${import_picocolors14.default.red("\u2022")} ${blocker2.problem}`);
284231
- console.log(` ${import_picocolors14.default.dim(`Fix: ${blocker2.fix}`)}`);
284544
+ console.log(` ${import_picocolors15.default.red("\u2022")} ${blocker2.problem}`);
284545
+ console.log(` ${import_picocolors15.default.dim(`Fix: ${blocker2.fix}`)}`);
284232
284546
  }
284233
284547
  }
284234
284548
  }
@@ -284294,12 +284608,12 @@ async function branches(argv) {
284294
284608
  )
284295
284609
  );
284296
284610
  } else {
284297
- console.log(` ${import_picocolors14.default.green("\u2713")} ${row.slug} ${import_picocolors14.default.dim(row.id)}`);
284298
- console.log(import_picocolors14.default.dim(` parent ${row.parent_branch_id ?? "none"} \xB7 ${row.state}`));
284611
+ console.log(` ${import_picocolors15.default.green("\u2713")} ${row.slug} ${import_picocolors15.default.dim(row.id)}`);
284612
+ console.log(import_picocolors15.default.dim(` parent ${row.parent_branch_id ?? "none"} \xB7 ${row.state}`));
284299
284613
  if (credential) {
284300
284614
  console.log(credential.api_key);
284301
284615
  console.error(
284302
- import_picocolors14.default.dim(` expires ${credential.expires_at} \xB7 branch ${credential.branch_id}`)
284616
+ import_picocolors15.default.dim(` expires ${credential.expires_at} \xB7 branch ${credential.branch_id}`)
284303
284617
  );
284304
284618
  }
284305
284619
  }
@@ -284324,7 +284638,7 @@ async function branches(argv) {
284324
284638
  throw new Error(message(response.body, `Could not delete branch (HTTP ${response.status}).`));
284325
284639
  }
284326
284640
  const row = import_branches.branchResponseSchema.parse(response.body);
284327
- console.log(` ${import_picocolors14.default.green("\u2713")} deleted ${row.slug} ${import_picocolors14.default.dim(row.id)}`);
284641
+ console.log(` ${import_picocolors15.default.green("\u2713")} deleted ${row.slug} ${import_picocolors15.default.dim(row.id)}`);
284328
284642
  return;
284329
284643
  }
284330
284644
  if (command === "credential") {
@@ -284336,7 +284650,7 @@ async function branches(argv) {
284336
284650
  if (argv.includes("--json")) console.log(JSON.stringify(credential, null, 2));
284337
284651
  else {
284338
284652
  console.log(credential.api_key);
284339
- console.error(import_picocolors14.default.dim(` expires ${credential.expires_at} \xB7 branch ${credential.branch_id}`));
284653
+ console.error(import_picocolors15.default.dim(` expires ${credential.expires_at} \xB7 branch ${credential.branch_id}`));
284340
284654
  }
284341
284655
  return;
284342
284656
  }
@@ -284345,18 +284659,18 @@ async function branches(argv) {
284345
284659
 
284346
284660
  // src/branchDev.ts
284347
284661
  init_cjs_shims();
284348
- var import_node_crypto3 = require("crypto");
284662
+ var import_node_crypto5 = require("crypto");
284349
284663
  var import_node_child_process = require("child_process");
284350
284664
  var import_branches2 = require("@abloatai/transaction/branches");
284351
- var import_errors13 = require("@abloatai/transaction/errors");
284665
+ var import_errors14 = require("@abloatai/transaction/errors");
284352
284666
  init_config();
284353
284667
  init_telemetry();
284354
284668
 
284355
284669
  // src/dev.ts
284356
284670
  init_cjs_shims();
284357
- var import_errors12 = require("@abloatai/transaction/errors");
284671
+ var import_errors13 = require("@abloatai/transaction/errors");
284358
284672
  var import_credentialPolicy2 = require("@abloatai/transaction/auth/credentialPolicy");
284359
- var import_picocolors15 = __toESM(require_picocolors(), 1);
284673
+ var import_picocolors16 = __toESM(require_picocolors(), 1);
284360
284674
  init_dist2();
284361
284675
  var import_fs7 = require("fs");
284362
284676
  var import_path5 = require("path");
@@ -284400,7 +284714,7 @@ function parseDevArgs(argv) {
284400
284714
  sourcePath = argv[++i] ?? sourcePath;
284401
284715
  break;
284402
284716
  default:
284403
- throw new import_errors12.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
284717
+ throw new import_errors13.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
284404
284718
  }
284405
284719
  }
284406
284720
  url = apiBaseUrl(url);
@@ -284418,8 +284732,8 @@ function parseDevArgs(argv) {
284418
284732
  async function loadLocalSourceHandler(sourcePath) {
284419
284733
  const abs = (0, import_path5.resolve)(process.cwd(), sourcePath);
284420
284734
  if (!(0, import_fs7.existsSync)(abs)) {
284421
- throw new import_errors12.AbloValidationError(
284422
- `local Data Source not found at ${import_picocolors15.default.bold(sourcePath)}. Add the signed Data Source handler described by ${import_picocolors15.default.bold("npx ablo docs data-sources")}, or pass ${import_picocolors15.default.bold("--source <path>")}.`,
284735
+ throw new import_errors13.AbloValidationError(
284736
+ `local Data Source not found at ${import_picocolors16.default.bold(sourcePath)}. Add the signed Data Source handler described by ${import_picocolors16.default.bold("npx ablo docs data-sources")}, or pass ${import_picocolors16.default.bold("--source <path>")}.`,
284423
284737
  { code: "cli_invalid_arguments" }
284424
284738
  );
284425
284739
  }
@@ -284429,8 +284743,8 @@ async function loadLocalSourceHandler(sourcePath) {
284429
284743
  const nested = mod.default && typeof mod.default === "object" ? mod.default : void 0;
284430
284744
  const handler = mod.POST ?? nested?.POST;
284431
284745
  if (typeof handler !== "function") {
284432
- throw new import_errors12.AbloValidationError(
284433
- `${import_picocolors15.default.bold(sourcePath)} must export a ${import_picocolors15.default.bold("POST(request)")} Data Source handler.`,
284746
+ throw new import_errors13.AbloValidationError(
284747
+ `${import_picocolors16.default.bold(sourcePath)} must export a ${import_picocolors16.default.bold("POST(request)")} Data Source handler.`,
284434
284748
  { code: "cli_invalid_arguments" }
284435
284749
  );
284436
284750
  }
@@ -284453,7 +284767,7 @@ async function registerLocalSource(args) {
284453
284767
  });
284454
284768
  if (!response.ok) {
284455
284769
  const body = await response.text();
284456
- throw new import_errors12.AbloValidationError(
284770
+ throw new import_errors13.AbloValidationError(
284457
284771
  `Could not register the local Data Source (${response.status}): ${body}`,
284458
284772
  { code: "cli_invalid_arguments" }
284459
284773
  );
@@ -284463,19 +284777,19 @@ function classifyKey(apiKey) {
284463
284777
  if (!apiKey) {
284464
284778
  return {
284465
284779
  ok: false,
284466
- reason: `No API key. Run ${import_picocolors15.default.bold("npx ablo login")}, or set a branch-bound ${import_picocolors15.default.bold("ABLO_API_KEY")}. ${import_picocolors15.default.bold("npx ablo dev")} prepares a development branch.`
284780
+ reason: `No API key. Run ${import_picocolors16.default.bold("npx ablo login")}, or set a branch-bound ${import_picocolors16.default.bold("ABLO_API_KEY")}. ${import_picocolors16.default.bold("npx ablo dev")} prepares a development branch.`
284467
284781
  };
284468
284782
  }
284469
284783
  if ((0, import_credentialPolicy2.classifyCredentialKind)(apiKey) === "secret") return { ok: true };
284470
284784
  if ((0, import_credentialPolicy2.classifyCredentialKind)(apiKey) === "restricted") {
284471
284785
  return {
284472
284786
  ok: false,
284473
- reason: `Authoring schema needs a branch-bound secret ${import_picocolors15.default.bold("sk_")} key. ${import_picocolors15.default.bold("npx ablo dev")} prepares a development branch. A restricted ${import_picocolors15.default.bold("rk_")} key carries only the scopes it was minted with.`
284787
+ reason: `Authoring schema needs a branch-bound secret ${import_picocolors16.default.bold("sk_")} key. ${import_picocolors16.default.bold("npx ablo dev")} prepares a development branch. A restricted ${import_picocolors16.default.bold("rk_")} key carries only the scopes it was minted with.`
284474
284788
  };
284475
284789
  }
284476
284790
  return {
284477
284791
  ok: false,
284478
- reason: `${import_picocolors15.default.bold("ABLO_API_KEY")} is not a secret Ablo key. Expected a branch-bound ${import_picocolors15.default.bold("sk_\u2026")} credential. Run ${import_picocolors15.default.bold("npx ablo dev")} to prepare a development branch.`
284792
+ reason: `${import_picocolors16.default.bold("ABLO_API_KEY")} is not a secret Ablo key. Expected a branch-bound ${import_picocolors16.default.bold("sk_\u2026")} credential. Run ${import_picocolors16.default.bold("npx ablo dev")} to prepare a development branch.`
284479
284793
  };
284480
284794
  }
284481
284795
  function wireEnvLocal(apiKey, cwd = process.cwd(), projectId, branchId) {
@@ -284493,7 +284807,7 @@ ${projectLine ? `${projectLine}
284493
284807
  ` : ""}`,
284494
284808
  { mode: 384 }
284495
284809
  );
284496
- action = `Created ${import_picocolors15.default.bold(".env.local")} with ${import_picocolors15.default.bold("ABLO_API_KEY")}`;
284810
+ action = `Created ${import_picocolors16.default.bold(".env.local")} with ${import_picocolors16.default.bold("ABLO_API_KEY")}`;
284497
284811
  } else {
284498
284812
  const content = (0, import_fs7.readFileSync)(envPath, "utf8");
284499
284813
  const match = /^ABLO_API_KEY=(.*)$/m.exec(content);
@@ -284501,12 +284815,12 @@ ${projectLine ? `${projectLine}
284501
284815
  if (!match) {
284502
284816
  (0, import_fs7.appendFileSync)(envPath, `${content.endsWith("\n") || content.length === 0 ? "" : "\n"}${line}
284503
284817
  `);
284504
- action = `Added ${import_picocolors15.default.bold("ABLO_API_KEY")} to ${import_picocolors15.default.bold(".env.local")}`;
284818
+ action = `Added ${import_picocolors16.default.bold("ABLO_API_KEY")} to ${import_picocolors16.default.bold(".env.local")}`;
284505
284819
  } else if (existing === apiKey) {
284506
- action = `${import_picocolors15.default.bold(".env.local")} already has this key`;
284820
+ action = `${import_picocolors16.default.bold(".env.local")} already has this key`;
284507
284821
  } else {
284508
284822
  (0, import_fs7.writeFileSync)(envPath, content.replace(/^ABLO_API_KEY=.*$/m, line));
284509
- action = `Updated ${import_picocolors15.default.bold("ABLO_API_KEY")} in ${import_picocolors15.default.bold(".env.local")} ${import_picocolors15.default.dim(`(was ${existing.slice(0, 12)}\u2026)`)}`;
284823
+ action = `Updated ${import_picocolors16.default.bold("ABLO_API_KEY")} in ${import_picocolors16.default.bold(".env.local")} ${import_picocolors16.default.dim(`(was ${existing.slice(0, 12)}\u2026)`)}`;
284510
284824
  }
284511
284825
  if (projectLine) {
284512
284826
  const next = (0, import_fs7.readFileSync)(envPath, "utf8");
@@ -284538,7 +284852,7 @@ ${projectLine ? `${projectLine}
284538
284852
  `}.env.local
284539
284853
  `
284540
284854
  );
284541
- gitignoreNote = ` Added ${import_picocolors15.default.bold(".env.local")} to ${import_picocolors15.default.bold(".gitignore")} so the key can't be committed.`;
284855
+ gitignoreNote = ` Added ${import_picocolors16.default.bold(".env.local")} to ${import_picocolors16.default.bold(".gitignore")} so the key can't be committed.`;
284542
284856
  }
284543
284857
  return `${action}.${gitignoreNote}`;
284544
284858
  }
@@ -284553,7 +284867,7 @@ async function runPush(schema, args) {
284553
284867
  if (ok) {
284554
284868
  return {
284555
284869
  ok: true,
284556
- message: body.unchanged ? `schema unchanged ${import_picocolors15.default.dim(`(v${body.version})`)}` : `schema pushed (${args.planeLabel}) ${import_picocolors15.default.dim(`(v${body.version}, hash ${body.hash})`)}`
284870
+ message: body.unchanged ? `schema unchanged ${import_picocolors16.default.dim(`(v${body.version})`)}` : `schema pushed (${args.planeLabel}) ${import_picocolors16.default.dim(`(v${body.version}, hash ${body.hash})`)}`
284557
284871
  };
284558
284872
  }
284559
284873
  if (status2 === 409) {
@@ -284562,9 +284876,9 @@ async function runPush(schema, args) {
284562
284876
  return {
284563
284877
  ok: false,
284564
284878
  message: [
284565
- import_picocolors15.default.bold("Replication reset required \u2014 a removed model still has live rows in this log plane."),
284566
- ...models.map((model) => import_picocolors15.default.yellow(` Live vanished model: ${String(model)}`)),
284567
- import_picocolors15.default.dim(` Use ${import_picocolors15.default.bold("--rename old:new")} to carry it forward, or ${import_picocolors15.default.bold("--force")} to accept the drop/reset.`)
284879
+ import_picocolors16.default.bold("Replication reset required \u2014 a removed model still has live rows in this log plane."),
284880
+ ...models.map((model) => import_picocolors16.default.yellow(` Live vanished model: ${String(model)}`)),
284881
+ import_picocolors16.default.dim(` Use ${import_picocolors16.default.bold("--rename old:new")} to carry it forward, or ${import_picocolors16.default.bold("--force")} to accept the drop/reset.`)
284568
284882
  ].join("\n")
284569
284883
  };
284570
284884
  }
@@ -284574,46 +284888,46 @@ async function runPush(schema, args) {
284574
284888
  (s) => s.shadowed != null
284575
284889
  );
284576
284890
  const lines = [
284577
- import_picocolors15.default.bold("Incompatible schema change \u2014 not safe to apply as-is."),
284891
+ import_picocolors16.default.bold("Incompatible schema change \u2014 not safe to apply as-is."),
284578
284892
  "",
284579
- ...unexecutable.map((u2) => import_picocolors15.default.red(fmtSignal(u2))),
284580
- ...warnings.map((w2) => import_picocolors15.default.yellow(fmtSignal(w2))),
284893
+ ...unexecutable.map((u2) => import_picocolors16.default.red(fmtSignal(u2))),
284894
+ ...warnings.map((w2) => import_picocolors16.default.yellow(fmtSignal(w2))),
284581
284895
  "",
284582
284896
  ...hasShadowed ? [
284583
- import_picocolors15.default.dim(
284897
+ import_picocolors16.default.dim(
284584
284898
  " These models exist in the baseline above but not in your push. Sandbox readers"
284585
284899
  ),
284586
- import_picocolors15.default.dim(
284900
+ import_picocolors16.default.dim(
284587
284901
  " fall back to the production schema until you push your own, so applying this drops them."
284588
284902
  ),
284589
284903
  ""
284590
284904
  ] : [],
284591
- import_picocolors15.default.dim(
284592
- ` Fix: ${import_picocolors15.default.bold("ablo push --force")} to apply anyway, or ${import_picocolors15.default.bold("--rename old:new")} if you renamed a model.`
284905
+ import_picocolors16.default.dim(
284906
+ ` Fix: ${import_picocolors16.default.bold("ablo push --force")} to apply anyway, or ${import_picocolors16.default.bold("--rename old:new")} if you renamed a model.`
284593
284907
  )
284594
284908
  ];
284595
284909
  return { ok: false, message: lines.join("\n") };
284596
284910
  }
284597
284911
  if (status2 === 403) {
284598
284912
  const serverSays = body.message ?? body.reason;
284599
- const hint = schemaPushStorageHint(body.code) ?? (body.code === "database_role_cannot_enforce_rls" ? `Run ${import_picocolors15.default.bold("npx ablo migrate")} \u2014 it creates the scoped role for you (your DB credential never leaves this machine).` : `Schema authoring needs a branch-bound ${import_picocolors15.default.bold("sk_")} key with ${import_picocolors15.default.bold("schema:push")} \u2014 manage keys at ${import_picocolors15.default.cyan("https://abloatai.com")}.`);
284913
+ const hint = schemaPushStorageHint(body.code) ?? (body.code === "database_role_cannot_enforce_rls" ? `Run ${import_picocolors16.default.bold("npx ablo migrate")} \u2014 it creates the scoped role for you (your DB credential never leaves this machine).` : `Schema authoring needs a branch-bound ${import_picocolors16.default.bold("sk_")} key with ${import_picocolors16.default.bold("schema:push")} \u2014 manage keys at ${import_picocolors16.default.cyan("https://abloatai.com")}.`);
284600
284914
  return {
284601
284915
  ok: false,
284602
284916
  message: `${serverSays ?? "This key can't author schema (missing schema:push scope)."}
284603
- ` + import_picocolors15.default.dim(hint)
284917
+ ` + import_picocolors16.default.dim(hint)
284604
284918
  };
284605
284919
  }
284606
284920
  const serverMessage = String(body.message ?? body.reason ?? bodyText);
284607
284921
  const storageHint = schemaPushStorageHint(body.code);
284608
284922
  if (storageHint) {
284609
284923
  return { ok: false, message: `${serverMessage}
284610
- ${import_picocolors15.default.dim(storageHint)}` };
284924
+ ${import_picocolors16.default.dim(storageHint)}` };
284611
284925
  }
284612
284926
  if (looksLikeCredentialRefusal(serverMessage)) {
284613
284927
  const pooled = await poolerExplanation(apiBaseUrl(), args.apiKey);
284614
284928
  if (pooled) {
284615
284929
  return { ok: false, message: `${serverMessage}
284616
- ${import_picocolors15.default.dim(pooled)}` };
284930
+ ${import_picocolors16.default.dim(pooled)}` };
284617
284931
  }
284618
284932
  }
284619
284933
  return { ok: false, message: `Push failed (${status2}): ${serverMessage}` };
@@ -284623,32 +284937,32 @@ async function dev(argv, runtime = {}) {
284623
284937
  try {
284624
284938
  args = parseDevArgs(argv);
284625
284939
  } catch (err) {
284626
- console.error(import_picocolors15.default.red(` ${err instanceof Error ? err.message : String(err)}`));
284940
+ console.error(import_picocolors16.default.red(` ${err instanceof Error ? err.message : String(err)}`));
284627
284941
  process.exit(1);
284628
284942
  }
284629
284943
  if (runtime.apiKey) args.apiKey = runtime.apiKey;
284630
284944
  else if (!args.apiKey) args.apiKey = resolveRuntimeApiKey("sandbox").key;
284631
284945
  if (runtime.branch) args.planeLabel = runtime.branch.slug;
284632
284946
  if (args.local && !args.watch) {
284633
- throw new import_errors12.AbloValidationError(
284634
- `${import_picocolors15.default.bold("--local")} opens a long-lived secure connector and cannot be combined with ${import_picocolors15.default.bold("--no-watch")}.`,
284947
+ throw new import_errors13.AbloValidationError(
284948
+ `${import_picocolors16.default.bold("--local")} opens a long-lived secure connector and cannot be combined with ${import_picocolors16.default.bold("--no-watch")}.`,
284635
284949
  { code: "cli_invalid_arguments" }
284636
284950
  );
284637
284951
  }
284638
284952
  const key = classifyKey(args.apiKey);
284639
284953
  if (!key.ok) {
284640
- console.error(import_picocolors15.default.red(` ${key.reason}`));
284954
+ console.error(import_picocolors16.default.red(` ${key.reason}`));
284641
284955
  process.exit(1);
284642
284956
  }
284643
284957
  console.log(`
284644
- ${brand("ablo")} ${import_picocolors15.default.dim("push")} ${import_picocolors15.default.dim(`(${args.planeLabel})`)}
284958
+ ${brand("ablo")} ${import_picocolors16.default.dim("push")} ${import_picocolors16.default.dim(`(${args.planeLabel})`)}
284645
284959
  `);
284646
284960
  if (runtime.branch) {
284647
284961
  console.log(
284648
- ` ${import_picocolors15.default.dim("branch")} ${import_picocolors15.default.bold(runtime.branch.slug)} ${import_picocolors15.default.dim(runtime.branch.id)}`
284962
+ ` ${import_picocolors16.default.dim("branch")} ${import_picocolors16.default.bold(runtime.branch.slug)} ${import_picocolors16.default.dim(runtime.branch.id)}`
284649
284963
  );
284650
284964
  console.log(
284651
- ` ${import_picocolors15.default.dim("key")} temporary \xB7 expires ${runtime.branch.expiresAt}`
284965
+ ` ${import_picocolors16.default.dim("key")} temporary \xB7 expires ${runtime.branch.expiresAt}`
284652
284966
  );
284653
284967
  }
284654
284968
  let localAbort = null;
@@ -284668,27 +284982,27 @@ async function dev(argv, runtime = {}) {
284668
284982
  client: "ablo-dev",
284669
284983
  onStatus(status2) {
284670
284984
  if (status2 === "ready") {
284671
- console.log(` ${import_picocolors15.default.green("\u2713")} local Postgres connected through the secure reverse channel`);
284985
+ console.log(` ${import_picocolors16.default.green("\u2713")} local Postgres connected through the secure reverse channel`);
284672
284986
  }
284673
284987
  },
284674
284988
  onError(error) {
284675
- console.error(import_picocolors15.default.yellow(` local connector: ${error instanceof Error ? error.message : String(error)}`));
284989
+ console.error(import_picocolors16.default.yellow(` local connector: ${error instanceof Error ? error.message : String(error)}`));
284676
284990
  }
284677
284991
  });
284678
284992
  void connector.run(localAbort.signal).catch((error) => {
284679
- console.error(import_picocolors15.default.red(` local connector stopped: ${error instanceof Error ? error.message : String(error)}`));
284993
+ console.error(import_picocolors16.default.red(` local connector stopped: ${error instanceof Error ? error.message : String(error)}`));
284680
284994
  });
284681
- console.log(` ${import_picocolors15.default.dim("source")} ${args.sourcePath} ${import_picocolors15.default.dim("(outbound connector; no public URL)")}`);
284995
+ console.log(` ${import_picocolors16.default.dim("source")} ${args.sourcePath} ${import_picocolors16.default.dim("(outbound connector; no public URL)")}`);
284682
284996
  }
284683
284997
  const schema = await loadSchema(args.schemaPath, args.exportName);
284684
284998
  const modelCount = Object.keys(schema.models).length;
284685
284999
  console.log(
284686
- ` ${import_picocolors15.default.dim("schema")} ${import_picocolors15.default.bold(args.schemaPath)} ${import_picocolors15.default.dim(`(${modelCount} models, hash ${(0, import_schema6.schemaHash)(schema)})`)}`
285000
+ ` ${import_picocolors16.default.dim("schema")} ${import_picocolors16.default.bold(args.schemaPath)} ${import_picocolors16.default.dim(`(${modelCount} models, hash ${(0, import_schema6.schemaHash)(schema)})`)}`
284687
285001
  );
284688
285002
  if (!runtime.branch) {
284689
- console.log(` ${import_picocolors15.default.dim("key")} ${args.apiKey.slice(0, 12)}\u2026`);
285003
+ console.log(` ${import_picocolors16.default.dim("key")} ${args.apiKey.slice(0, 12)}\u2026`);
284690
285004
  }
284691
- console.log(` ${import_picocolors15.default.dim("api")} ${args.url}
285005
+ console.log(` ${import_picocolors16.default.dim("api")} ${args.url}
284692
285006
  `);
284693
285007
  const s = Y2();
284694
285008
  s.start("Pushing schema definition (development branch)");
@@ -284701,30 +285015,30 @@ async function dev(argv, runtime = {}) {
284701
285015
  if (runtime.branch) {
284702
285016
  console.log(
284703
285017
  `
284704
- ${import_picocolors15.default.green("\u2713")} ${wireEnvLocal(args.apiKey, process.cwd(), runtime.branch.projectId, runtime.branch.id)}`
285018
+ ${import_picocolors16.default.green("\u2713")} ${wireEnvLocal(args.apiKey, process.cwd(), runtime.branch.projectId, runtime.branch.id)}`
284705
285019
  );
284706
285020
  console.log(
284707
- ` ${import_picocolors15.default.dim(`Temporary branch credential expires ${runtime.branch.expiresAt}; rerun ablo dev to rotate it.`)}`
285021
+ ` ${import_picocolors16.default.dim(`Temporary branch credential expires ${runtime.branch.expiresAt}; rerun ablo dev to rotate it.`)}`
284708
285022
  );
284709
285023
  if (process.env.ABLO_API_KEY && process.env.ABLO_API_KEY !== args.apiKey) {
284710
285024
  console.log(
284711
- import_picocolors15.default.yellow(
285025
+ import_picocolors16.default.yellow(
284712
285026
  ` An exported ABLO_API_KEY overrides .env.local for child processes; unset it before starting your app.`
284713
285027
  )
284714
285028
  );
284715
285029
  }
284716
285030
  } else if (process.env.ABLO_API_KEY) {
284717
285031
  console.log(`
284718
- ${import_picocolors15.default.green("\u2713")} ${import_picocolors15.default.bold("ABLO_API_KEY")} is set in this shell \u2014 the SDK reads it directly.`);
285032
+ ${import_picocolors16.default.green("\u2713")} ${import_picocolors16.default.bold("ABLO_API_KEY")} is set in this shell \u2014 the SDK reads it directly.`);
284719
285033
  } else {
284720
285034
  console.log(`
284721
- ${import_picocolors15.default.green("\u2713")} ${wireEnvLocal(args.apiKey)}`);
284722
- console.log(` ${import_picocolors15.default.dim("Frameworks load it automatically; plain Node: node --env-file=.env.local app.ts")}`);
285035
+ ${import_picocolors16.default.green("\u2713")} ${wireEnvLocal(args.apiKey)}`);
285036
+ console.log(` ${import_picocolors16.default.dim("Frameworks load it automatically; plain Node: node --env-file=.env.local app.ts")}`);
284723
285037
  }
284724
285038
  console.log(` Your app is wired for ${runtime.branch ? `branch ${runtime.branch.slug}` : "this branch"}.`);
284725
285039
  if (!args.watch) return;
284726
285040
  const abs = (0, import_path5.resolve)(process.cwd(), args.schemaPath);
284727
- console.log(` ${import_picocolors15.default.dim(`watching ${args.schemaPath} \u2026 (Ctrl-C to stop)`)}
285041
+ console.log(` ${import_picocolors16.default.dim(`watching ${args.schemaPath} \u2026 (Ctrl-C to stop)`)}
284728
285042
  `);
284729
285043
  let timer2 = null;
284730
285044
  let pushing = false;
@@ -284744,7 +285058,7 @@ async function dev(argv, runtime = {}) {
284744
285058
  const r2 = await runPush(next, args);
284745
285059
  s2.stop(r2.message, r2.ok ? 0 : 1);
284746
285060
  } catch (err) {
284747
- s2.stop(import_picocolors15.default.red(`schema reload failed: ${err instanceof Error ? err.message : String(err)}`), 1);
285061
+ s2.stop(import_picocolors16.default.red(`schema reload failed: ${err instanceof Error ? err.message : String(err)}`), 1);
284748
285062
  } finally {
284749
285063
  pushing = false;
284750
285064
  }
@@ -284753,7 +285067,7 @@ async function dev(argv, runtime = {}) {
284753
285067
  watcher.close();
284754
285068
  localAbort?.abort();
284755
285069
  console.log(`
284756
- ${import_picocolors15.default.dim("stopped.")}`);
285070
+ ${import_picocolors16.default.dim("stopped.")}`);
284757
285071
  process.exit(0);
284758
285072
  };
284759
285073
  process.on("SIGINT", stop);
@@ -284781,7 +285095,7 @@ function parseBranchDevArgs(argv) {
284781
285095
  const arg = argv[index];
284782
285096
  if (!arg) continue;
284783
285097
  if (arg === "--no-branch") {
284784
- throw new import_errors13.AbloValidationError(
285098
+ throw new import_errors14.AbloValidationError(
284785
285099
  "--no-branch was removed: development is branch-isolated. Use --branch <slug> to select explicitly.",
284786
285100
  { code: "cli_invalid_arguments" }
284787
285101
  );
@@ -284789,7 +285103,7 @@ function parseBranchDevArgs(argv) {
284789
285103
  if (arg === "--branch") {
284790
285104
  branchSlug = argv[++index];
284791
285105
  if (!branchSlug) {
284792
- throw new import_errors13.AbloValidationError("--branch requires a slug", {
285106
+ throw new import_errors14.AbloValidationError("--branch requires a slug", {
284793
285107
  code: "cli_invalid_arguments"
284794
285108
  });
284795
285109
  }
@@ -284798,7 +285112,7 @@ function parseBranchDevArgs(argv) {
284798
285112
  if (arg === "--branch-ttl-hours") {
284799
285113
  const value = Number(argv[++index]);
284800
285114
  if (!Number.isInteger(value) || value < 1 || value > 168) {
284801
- throw new import_errors13.AbloValidationError("--branch-ttl-hours must be between 1 and 168", {
285115
+ throw new import_errors14.AbloValidationError("--branch-ttl-hours must be between 1 and 168", {
284802
285116
  code: "cli_invalid_arguments"
284803
285117
  });
284804
285118
  }
@@ -284816,12 +285130,12 @@ function parseBranchDevArgs(argv) {
284816
285130
  function branchSlugFromRef(ref) {
284817
285131
  const base = ref.normalize("NFKD").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
284818
285132
  if (!base) {
284819
- throw new import_errors13.AbloValidationError(`cannot derive an Ablo branch slug from "${ref}"`, {
285133
+ throw new import_errors14.AbloValidationError(`cannot derive an Ablo branch slug from "${ref}"`, {
284820
285134
  code: "cli_invalid_arguments"
284821
285135
  });
284822
285136
  }
284823
285137
  const nonRoot = base === "production" ? "production-dev" : base;
284824
- const shortened = nonRoot.length <= 40 ? nonRoot : `${nonRoot.slice(0, 31).replace(/-+$/g, "")}-${(0, import_node_crypto3.createHash)("sha256").update(nonRoot).digest("hex").slice(0, 8)}`;
285138
+ const shortened = nonRoot.length <= 40 ? nonRoot : `${nonRoot.slice(0, 31).replace(/-+$/g, "")}-${(0, import_node_crypto5.createHash)("sha256").update(nonRoot).digest("hex").slice(0, 8)}`;
284825
285139
  return import_branches2.branchSlugSchema.parse(shortened);
284826
285140
  }
284827
285141
  function gitBranch() {
@@ -284838,7 +285152,7 @@ function gitBranch() {
284838
285152
  function discoverBranchRef(explicit, env = process.env, readGitBranch = gitBranch) {
284839
285153
  const value = explicit ?? env.ABLO_BRANCH ?? env.GITHUB_HEAD_REF ?? env.GITHUB_REF_NAME ?? env.VERCEL_GIT_COMMIT_REF ?? env.CI_COMMIT_REF_NAME ?? readGitBranch();
284840
285154
  if (!value) {
284841
- throw new import_errors13.AbloValidationError(
285155
+ throw new import_errors14.AbloValidationError(
284842
285156
  "Could not determine the Git branch. Pass --branch <slug> or set ABLO_BRANCH.",
284843
285157
  { code: "cli_invalid_arguments" }
284844
285158
  );
@@ -284856,13 +285170,13 @@ async function runBranchDev(argv, dependencies = {}) {
284856
285170
  const slug = branchSlugFromRef(ref);
284857
285171
  const managementKey = dependencies.resolveManagementKey?.() ?? resolveManagementKey();
284858
285172
  if (!managementKey) {
284859
- throw new import_errors13.AbloValidationError(
285173
+ throw new import_errors14.AbloValidationError(
284860
285174
  "Creating a development branch needs a project management credential. Run `npx ablo login` or set ABLO_MANAGEMENT_KEY.",
284861
285175
  { code: "cli_invalid_arguments" }
284862
285176
  );
284863
285177
  }
284864
285178
  if (!managementKey.startsWith("mk_")) {
284865
- throw new import_errors13.AbloValidationError(
285179
+ throw new import_errors14.AbloValidationError(
284866
285180
  "Branch creation needs the active project management credential (mk_\u2026). Run `npx ablo login` to refresh it.",
284867
285181
  { code: "cli_invalid_arguments" }
284868
285182
  );
@@ -284890,8 +285204,8 @@ async function runBranchDev(argv, dependencies = {}) {
284890
285204
 
284891
285205
  // src/whoami.ts
284892
285206
  init_cjs_shims();
284893
- var import_picocolors16 = __toESM(require_picocolors(), 1);
284894
- var import_errors14 = require("@abloatai/transaction/errors");
285207
+ var import_picocolors17 = __toESM(require_picocolors(), 1);
285208
+ var import_errors15 = require("@abloatai/transaction/errors");
284895
285209
  init_config();
284896
285210
  init_controlPlane();
284897
285211
 
@@ -284966,7 +285280,7 @@ function parseWhoamiArgs(argv) {
284966
285280
  case "--key": {
284967
285281
  const value = argv[++i];
284968
285282
  if (!value || value.startsWith("--")) {
284969
- throw new import_errors14.AbloValidationError("`--key` needs a credential value.", {
285283
+ throw new import_errors15.AbloValidationError("`--key` needs a credential value.", {
284970
285284
  code: "cli_invalid_arguments"
284971
285285
  });
284972
285286
  }
@@ -284976,12 +285290,12 @@ function parseWhoamiArgs(argv) {
284976
285290
  case "--key-env": {
284977
285291
  const value = argv[++i];
284978
285292
  if (!value || value.startsWith("--")) {
284979
- throw new import_errors14.AbloValidationError("`--key-env` needs an environment variable name.", {
285293
+ throw new import_errors15.AbloValidationError("`--key-env` needs an environment variable name.", {
284980
285294
  code: "cli_invalid_arguments"
284981
285295
  });
284982
285296
  }
284983
285297
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
284984
- throw new import_errors14.AbloValidationError(
285298
+ throw new import_errors15.AbloValidationError(
284985
285299
  `\`${value}\` is not a valid environment variable name.`,
284986
285300
  { code: "cli_invalid_arguments" }
284987
285301
  );
@@ -284990,13 +285304,13 @@ function parseWhoamiArgs(argv) {
284990
285304
  break;
284991
285305
  }
284992
285306
  default:
284993
- throw new import_errors14.AbloValidationError(`unknown whoami flag: ${arg}`, {
285307
+ throw new import_errors15.AbloValidationError(`unknown whoami flag: ${arg}`, {
284994
285308
  code: "cli_invalid_arguments"
284995
285309
  });
284996
285310
  }
284997
285311
  }
284998
285312
  if (key && keyEnv) {
284999
- throw new import_errors14.AbloValidationError("Choose one credential source: `--key` or `--key-env`.", {
285313
+ throw new import_errors15.AbloValidationError("Choose one credential source: `--key` or `--key-env`.", {
285000
285314
  code: "cli_invalid_arguments"
285001
285315
  });
285002
285316
  }
@@ -285007,7 +285321,7 @@ function selectWhoamiCredential(args, cwd = process.cwd()) {
285007
285321
  if (args.keyEnv) {
285008
285322
  const found = readProjectEnvVariable(args.keyEnv, cwd);
285009
285323
  if (!found) {
285010
- throw new import_errors14.AbloAuthenticationError(
285324
+ throw new import_errors15.AbloAuthenticationError(
285011
285325
  `${args.keyEnv} is not set in the process environment, .env.local, or .env.`,
285012
285326
  { code: "cli_api_key_missing" }
285013
285327
  );
@@ -285036,7 +285350,7 @@ function selectWhoamiCredential(args, cwd = process.cwd()) {
285036
285350
  };
285037
285351
  }
285038
285352
  const ambient = ambientEnvKeyNote();
285039
- throw new import_errors14.AbloAuthenticationError(
285353
+ throw new import_errors15.AbloAuthenticationError(
285040
285354
  `No credential found. Run \`ablo login\`, set ABLO_API_KEY, or pass \`--key-env <NAME>\`.${ambient ? `
285041
285355
 
285042
285356
  ${ambient}` : ""}`,
@@ -285054,7 +285368,7 @@ async function whoami(argv) {
285054
285368
  });
285055
285369
  const confirmed = target.confirmed;
285056
285370
  if (!confirmed) {
285057
- throw new import_errors14.AbloAuthenticationError(
285371
+ throw new import_errors15.AbloAuthenticationError(
285058
285372
  "The server did not confirm an identity for this credential.",
285059
285373
  { code: "identity_resolve_failed" }
285060
285374
  );
@@ -285091,18 +285405,18 @@ async function whoami(argv) {
285091
285405
  return;
285092
285406
  }
285093
285407
  console.log(`
285094
- ${brand("ablo")} ${import_picocolors16.default.dim("whoami")}
285408
+ ${brand("ablo")} ${import_picocolors17.default.dim("whoami")}
285095
285409
  `);
285096
285410
  console.log(
285097
- ` ${import_picocolors16.default.dim("key")} ${selected.key.slice(0, 12)}\u2026 ${import_picocolors16.default.dim(`(${selected.source} \xB7 ${capability.label})`)}`
285411
+ ` ${import_picocolors17.default.dim("key")} ${selected.key.slice(0, 12)}\u2026 ${import_picocolors17.default.dim(`(${selected.source} \xB7 ${capability.label})`)}`
285098
285412
  );
285099
- console.log(` ${import_picocolors16.default.dim("org")} ${import_picocolors16.default.dim(confirmed.organizationId)}`);
285413
+ console.log(` ${import_picocolors17.default.dim("org")} ${import_picocolors17.default.dim(confirmed.organizationId)}`);
285100
285414
  console.log(
285101
- ` ${import_picocolors16.default.dim("project")} ${import_picocolors16.default.bold(projectLabel)}${project ? ` ${import_picocolors16.default.dim(`(${project.id})`)}` : ""}`
285415
+ ` ${import_picocolors17.default.dim("project")} ${import_picocolors17.default.bold(projectLabel)}${project ? ` ${import_picocolors17.default.dim(`(${project.id})`)}` : ""}`
285102
285416
  );
285103
- console.log(` ${import_picocolors16.default.dim("acts on")} ${import_picocolors16.default.bold(actsOn)}`);
285417
+ console.log(` ${import_picocolors17.default.dim("acts on")} ${import_picocolors17.default.bold(actsOn)}`);
285104
285418
  console.log(`
285105
- ${import_picocolors16.default.green("\u2713")} ${import_picocolors16.default.dim("credential accepted; target confirmed by the server")}
285419
+ ${import_picocolors17.default.green("\u2713")} ${import_picocolors17.default.dim("credential accepted; target confirmed by the server")}
285106
285420
  `);
285107
285421
  }
285108
285422
 
@@ -285111,14 +285425,14 @@ init_push();
285111
285425
 
285112
285426
  // src/setup/run.ts
285113
285427
  init_cjs_shims();
285114
- var import_picocolors18 = __toESM(require_picocolors(), 1);
285115
- var import_errors15 = require("@abloatai/transaction/errors");
285428
+ var import_picocolors19 = __toESM(require_picocolors(), 1);
285429
+ var import_errors16 = require("@abloatai/transaction/errors");
285116
285430
  init_theme();
285117
285431
 
285118
285432
  // src/setup/discover.ts
285119
285433
  init_cjs_shims();
285120
- var import_node_fs2 = require("fs");
285121
- var import_node_crypto4 = require("crypto");
285434
+ var import_node_fs3 = require("fs");
285435
+ var import_node_crypto6 = require("crypto");
285122
285436
  var import_node_child_process2 = require("child_process");
285123
285437
  var import_node_path2 = require("path");
285124
285438
  init_controlPlane();
@@ -285126,18 +285440,26 @@ init_config();
285126
285440
 
285127
285441
  // src/doctor.ts
285128
285442
  init_cjs_shims();
285129
- var import_picocolors17 = __toESM(require_picocolors(), 1);
285443
+ var import_picocolors18 = __toESM(require_picocolors(), 1);
285130
285444
  init_theme();
285131
285445
  init_controlPlane();
285132
285446
  init_config();
285133
285447
  init_target();
285134
285448
  init_readiness();
285135
285449
  function render(check2) {
285136
- const mark = check2.state === "ok" ? import_picocolors17.default.green("\u2713") : check2.state === "fail" ? import_picocolors17.default.red("\u2717") : import_picocolors17.default.dim("\u2013");
285450
+ const mark = check2.state === "ok" ? import_picocolors18.default.green("\u2713") : check2.state === "fail" ? import_picocolors18.default.red("\u2717") : import_picocolors18.default.dim("\u2013");
285137
285451
  console.log(
285138
- ` ${mark} ${check2.label.padEnd(10)} ${check2.state === "fail" ? check2.detail : import_picocolors17.default.dim(check2.detail)}`
285452
+ ` ${mark} ${check2.label.padEnd(10)} ${check2.state === "fail" ? check2.detail : import_picocolors18.default.dim(check2.detail)}`
285139
285453
  );
285140
- if (check2.fix) console.log(` ${" ".repeat(11)}${import_picocolors17.default.dim(`\u2192 ${check2.fix}`)}`);
285454
+ if (check2.fix) console.log(` ${" ".repeat(11)}${import_picocolors18.default.dim(`\u2192 ${check2.fix}`)}`);
285455
+ }
285456
+ function windowWords(seconds) {
285457
+ if (seconds % 3600 === 0) {
285458
+ const hours = seconds / 3600;
285459
+ return hours === 1 ? "the last hour" : `the last ${hours} hours`;
285460
+ }
285461
+ const minutes = Math.max(1, Math.round(seconds / 60));
285462
+ return minutes === 1 ? "the last minute" : `the last ${minutes} minutes`;
285141
285463
  }
285142
285464
  async function ping(apiUrl3) {
285143
285465
  const ctrl = new AbortController();
@@ -285281,6 +285603,24 @@ async function inspectDoctor(options = {}) {
285281
285603
  } else {
285282
285604
  checks.push({ label: "database", state: "skip", detail: "nothing connected to check" });
285283
285605
  }
285606
+ const delivery = reachable ? await fetchDeliveryState(apiUrl3, runtimeKey.key) : { kind: "unknown", detail: "unreachable" };
285607
+ if (delivery.kind === "known") {
285608
+ const when = windowWords(delivery.window_seconds);
285609
+ checks.push(
285610
+ delivery.unroutable > 0 ? {
285611
+ label: "delivery",
285612
+ state: "fail",
285613
+ detail: `${delivery.unroutable} of ${delivery.recorded} change${delivery.recorded === 1 ? "" : "s"} in ${when} reached nobody` + (delivery.sample ? ` (e.g. ${delivery.sample.model}/${delivery.sample.id})` : ""),
285614
+ fix: "run `ablo check`. Rows written to Postgres outside Ablo carry no tenancy value, so nothing can route the change."
285615
+ } : {
285616
+ label: "delivery",
285617
+ state: "ok",
285618
+ detail: delivery.recorded === 0 ? `no changes in ${when}` : `${delivery.recorded} change${delivery.recorded === 1 ? "" : "s"} in ${when}, all deliverable`
285619
+ }
285620
+ );
285621
+ } else {
285622
+ checks.push({ label: "delivery", state: "skip", detail: `not determined (${delivery.detail})` });
285623
+ }
285284
285624
  const blocking = blockers({
285285
285625
  reachable,
285286
285626
  hasKey: Boolean(runtimeKey.key),
@@ -285301,29 +285641,30 @@ async function inspectDoctor(options = {}) {
285301
285641
  target,
285302
285642
  dataSource,
285303
285643
  pushedSchema: pushed,
285304
- schemaDrift: drift
285644
+ schemaDrift: drift,
285645
+ delivery
285305
285646
  };
285306
285647
  }
285307
285648
  function renderDoctorReport(report) {
285308
285649
  console.log(`
285309
- ${brand("ablo")} ${import_picocolors17.default.dim("doctor")}
285650
+ ${brand("ablo")} ${import_picocolors18.default.dim("doctor")}
285310
285651
  `);
285311
285652
  for (const check2 of report.checks) render(check2);
285312
285653
  console.log();
285313
285654
  if (report.failed > 0) {
285314
285655
  console.log(
285315
- ` ${import_picocolors17.default.red("\u2717")} ${import_picocolors17.default.bold(`${report.failed} problem${report.failed === 1 ? "" : "s"}`)}` + import_picocolors17.default.dim(report.skipped > 0 ? `, ${report.skipped} check${report.skipped === 1 ? "" : "s"} skipped` : "")
285656
+ ` ${import_picocolors18.default.red("\u2717")} ${import_picocolors18.default.bold(`${report.failed} problem${report.failed === 1 ? "" : "s"}`)}` + import_picocolors18.default.dim(report.skipped > 0 ? `, ${report.skipped} check${report.skipped === 1 ? "" : "s"} skipped` : "")
285316
285657
  );
285317
285658
  console.log(
285318
- import_picocolors17.default.dim(" Fix them in the order above \u2014 an earlier one often explains a later one.")
285659
+ import_picocolors18.default.dim(" Fix them in the order above \u2014 an earlier one often explains a later one.")
285319
285660
  );
285320
285661
  } else if (report.skipped > 0) {
285321
285662
  console.log(
285322
- ` ${import_picocolors17.default.yellow("?")} ${import_picocolors17.default.dim(`nothing is blocking a write, but ${report.skipped} check${report.skipped === 1 ? "" : "s"} could not be run`)}`
285663
+ ` ${import_picocolors18.default.yellow("?")} ${import_picocolors18.default.dim(`nothing is blocking a write, but ${report.skipped} check${report.skipped === 1 ? "" : "s"} could not be run`)}`
285323
285664
  );
285324
285665
  } else {
285325
285666
  console.log(
285326
- ` ${import_picocolors17.default.green("\u2713")} ${import_picocolors17.default.dim("write infrastructure is ready \u2014 your database constraints and row-level policies still apply")}`
285667
+ ` ${import_picocolors18.default.green("\u2713")} ${import_picocolors18.default.dim(WRITE_READY_VERDICT)}`
285327
285668
  );
285328
285669
  }
285329
285670
  console.log();
@@ -285336,10 +285677,10 @@ async function doctor() {
285336
285677
 
285337
285678
  // src/setup/contracts.ts
285338
285679
  init_cjs_shims();
285339
- var import_zod5 = require("zod");
285680
+ var import_zod6 = require("zod");
285340
285681
  var SETUP_CONTRACT_VERSION = 1;
285341
- var setupEvidenceSchema = import_zod5.z.object({
285342
- source: import_zod5.z.enum([
285682
+ var setupEvidenceSchema = import_zod6.z.object({
285683
+ source: import_zod6.z.enum([
285343
285684
  "filesystem",
285344
285685
  "package_manifest",
285345
285686
  "git",
@@ -285349,32 +285690,32 @@ var setupEvidenceSchema = import_zod5.z.object({
285349
285690
  "inference",
285350
285691
  "user"
285351
285692
  ]),
285352
- locator: import_zod5.z.string().min(1).optional(),
285353
- detail: import_zod5.z.string().min(1),
285354
- observedAt: import_zod5.z.iso.datetime()
285693
+ locator: import_zod6.z.string().min(1).optional(),
285694
+ detail: import_zod6.z.string().min(1),
285695
+ observedAt: import_zod6.z.iso.datetime()
285355
285696
  }).strict();
285356
- var setupFactSchema = import_zod5.z.object({
285357
- key: import_zod5.z.string().min(1),
285358
- value: import_zod5.z.json(),
285359
- confidence: import_zod5.z.enum(["high", "medium", "low"]),
285360
- evidence: import_zod5.z.array(setupEvidenceSchema).min(1)
285697
+ var setupFactSchema = import_zod6.z.object({
285698
+ key: import_zod6.z.string().min(1),
285699
+ value: import_zod6.z.json(),
285700
+ confidence: import_zod6.z.enum(["high", "medium", "low"]),
285701
+ evidence: import_zod6.z.array(setupEvidenceSchema).min(1)
285361
285702
  }).strict();
285362
- var setupCoordinationAdoptionDispositionSchema = import_zod5.z.enum([
285703
+ var setupCoordinationAdoptionDispositionSchema = import_zod6.z.enum([
285363
285704
  "existing_state_reuse_candidate",
285364
285705
  "model_migration_required",
285365
285706
  "coordination_path_undetermined"
285366
285707
  ]);
285367
- var setupDecisionSchema = import_zod5.z.object({
285368
- id: import_zod5.z.string().min(1),
285369
- question: import_zod5.z.string().min(1),
285370
- status: import_zod5.z.enum(["unresolved", "resolved", "not_applicable"]),
285371
- choices: import_zod5.z.array(import_zod5.z.object({
285372
- value: import_zod5.z.string().min(1),
285373
- label: import_zod5.z.string().min(1),
285374
- consequence: import_zod5.z.string().min(1)
285708
+ var setupDecisionSchema = import_zod6.z.object({
285709
+ id: import_zod6.z.string().min(1),
285710
+ question: import_zod6.z.string().min(1),
285711
+ status: import_zod6.z.enum(["unresolved", "resolved", "not_applicable"]),
285712
+ choices: import_zod6.z.array(import_zod6.z.object({
285713
+ value: import_zod6.z.string().min(1),
285714
+ label: import_zod6.z.string().min(1),
285715
+ consequence: import_zod6.z.string().min(1)
285375
285716
  }).strict()),
285376
- selected: import_zod5.z.string().min(1).optional(),
285377
- reason: import_zod5.z.string().min(1)
285717
+ selected: import_zod6.z.string().min(1).optional(),
285718
+ reason: import_zod6.z.string().min(1)
285378
285719
  }).strict().superRefine((decision, ctx) => {
285379
285720
  if (decision.status === "resolved" && decision.selected === void 0) {
285380
285721
  ctx.addIssue({ code: "custom", message: "A resolved decision needs a selected value." });
@@ -285383,17 +285724,17 @@ var setupDecisionSchema = import_zod5.z.object({
285383
285724
  ctx.addIssue({ code: "custom", message: "The selected value must be one of the choices." });
285384
285725
  }
285385
285726
  });
285386
- var setupMutationClassSchema = import_zod5.z.enum([
285727
+ var setupMutationClassSchema = import_zod6.z.enum([
285387
285728
  "read_only",
285388
285729
  "local_write",
285389
285730
  "remote_write",
285390
285731
  "database_write"
285391
285732
  ]);
285392
- var setupApprovalClassSchema = import_zod5.z.enum(["none", "review", "explicit"]);
285393
- var setupActionSchema = import_zod5.z.object({
285394
- id: import_zod5.z.string().min(1),
285395
- stepId: import_zod5.z.string().min(1),
285396
- kind: import_zod5.z.enum([
285733
+ var setupApprovalClassSchema = import_zod6.z.enum(["none", "review", "explicit"]);
285734
+ var setupActionSchema = import_zod6.z.object({
285735
+ id: import_zod6.z.string().min(1),
285736
+ stepId: import_zod6.z.string().min(1),
285737
+ kind: import_zod6.z.enum([
285397
285738
  "inspect_repository",
285398
285739
  "analyze_compatibility",
285399
285740
  "select_application",
@@ -285408,20 +285749,20 @@ var setupActionSchema = import_zod5.z.object({
285408
285749
  "verify",
285409
285750
  "run_canary"
285410
285751
  ]),
285411
- summary: import_zod5.z.string().min(1),
285752
+ summary: import_zod6.z.string().min(1),
285412
285753
  mutation: setupMutationClassSchema,
285413
285754
  approval: setupApprovalClassSchema,
285414
- executor: import_zod5.z.enum(["deterministic", "agent", "user"]).default("deterministic"),
285415
- status: import_zod5.z.enum(["planned", "blocked", "not_needed"]),
285416
- blockedBy: import_zod5.z.array(import_zod5.z.string().min(1)).default([]),
285417
- paths: import_zod5.z.array(import_zod5.z.string().min(1)).default([]),
285418
- preconditions: import_zod5.z.array(import_zod5.z.string().min(1)).default([])
285755
+ executor: import_zod6.z.enum(["deterministic", "agent", "user"]).default("deterministic"),
285756
+ status: import_zod6.z.enum(["planned", "blocked", "not_needed"]),
285757
+ blockedBy: import_zod6.z.array(import_zod6.z.string().min(1)).default([]),
285758
+ paths: import_zod6.z.array(import_zod6.z.string().min(1)).default([]),
285759
+ preconditions: import_zod6.z.array(import_zod6.z.string().min(1)).default([])
285419
285760
  }).strict();
285420
- var setupMutationSiteSchema = import_zod5.z.object({
285421
- path: import_zod5.z.string().min(1),
285422
- line: import_zod5.z.number().int().positive(),
285423
- kind: import_zod5.z.enum(["prisma", "drizzle", "sql", "http", "ablo"]),
285424
- operation: import_zod5.z.enum([
285761
+ var setupMutationSiteSchema = import_zod6.z.object({
285762
+ path: import_zod6.z.string().min(1),
285763
+ line: import_zod6.z.number().int().positive(),
285764
+ kind: import_zod6.z.enum(["prisma", "drizzle", "sql", "http", "ablo"]),
285765
+ operation: import_zod6.z.enum([
285425
285766
  "create",
285426
285767
  "update",
285427
285768
  "delete",
@@ -285432,35 +285773,35 @@ var setupMutationSiteSchema = import_zod5.z.object({
285432
285773
  "sql_write",
285433
285774
  "http_write"
285434
285775
  ]),
285435
- modelHint: import_zod5.z.string().min(1).nullable(),
285436
- confidence: import_zod5.z.enum(["high", "medium", "low"])
285776
+ modelHint: import_zod6.z.string().min(1).nullable(),
285777
+ confidence: import_zod6.z.enum(["high", "medium", "low"])
285437
285778
  }).strict();
285438
- var setupDatabaseColumnSchema = import_zod5.z.object({
285439
- table: import_zod5.z.string().min(1),
285440
- column: import_zod5.z.string().min(1),
285441
- dataType: import_zod5.z.string().min(1),
285442
- nullable: import_zod5.z.boolean(),
285443
- defaultExpression: import_zod5.z.string().min(1).nullable(),
285444
- generatedBy: import_zod5.z.enum(["application", "database"]).default("application")
285779
+ var setupDatabaseColumnSchema = import_zod6.z.object({
285780
+ table: import_zod6.z.string().min(1),
285781
+ column: import_zod6.z.string().min(1),
285782
+ dataType: import_zod6.z.string().min(1),
285783
+ nullable: import_zod6.z.boolean(),
285784
+ defaultExpression: import_zod6.z.string().min(1).nullable(),
285785
+ generatedBy: import_zod6.z.enum(["application", "database"]).default("application")
285445
285786
  }).strict();
285446
- var setupCompatibilityBlockerCodeSchema = import_zod5.z.enum([
285787
+ var setupCompatibilityBlockerCodeSchema = import_zod6.z.enum([
285447
285788
  "database_schema_unavailable",
285448
285789
  "identity_type_unsupported",
285449
285790
  "stable_identity_missing"
285450
285791
  ]);
285451
- var setupDatabaseMappingSchema = import_zod5.z.object({
285452
- table: import_zod5.z.string().min(1),
285453
- field: import_zod5.z.enum(["id", "organizationId", "createdBy"]),
285454
- column: import_zod5.z.string().min(1).nullable(),
285455
- databaseType: import_zod5.z.enum([
285792
+ var setupDatabaseMappingSchema = import_zod6.z.object({
285793
+ table: import_zod6.z.string().min(1),
285794
+ field: import_zod6.z.enum(["id", "organizationId", "createdBy"]),
285795
+ column: import_zod6.z.string().min(1).nullable(),
285796
+ databaseType: import_zod6.z.enum([
285456
285797
  "text",
285457
285798
  "uuid",
285458
285799
  "bigint"
285459
285800
  ]).nullable(),
285460
- generatedBy: import_zod5.z.enum(["application", "ablo", "database"]).nullable(),
285461
- status: import_zod5.z.enum(["ready", "review_required"]),
285462
- reason: import_zod5.z.string().min(1),
285463
- evidence: import_zod5.z.array(setupEvidenceSchema).min(1)
285801
+ generatedBy: import_zod6.z.enum(["application", "ablo", "database"]).nullable(),
285802
+ status: import_zod6.z.enum(["ready", "review_required"]),
285803
+ reason: import_zod6.z.string().min(1),
285804
+ evidence: import_zod6.z.array(setupEvidenceSchema).min(1)
285464
285805
  }).strict().superRefine((mapping, ctx) => {
285465
285806
  if (mapping.column === null && (mapping.databaseType !== null || mapping.generatedBy !== null)) {
285466
285807
  ctx.addIssue({
@@ -285475,53 +285816,53 @@ var setupDatabaseMappingSchema = import_zod5.z.object({
285475
285816
  });
285476
285817
  }
285477
285818
  });
285478
- var setupCompatibilityRemediationSchema = import_zod5.z.object({
285479
- kind: import_zod5.z.enum(["migration", "translation", "retain_direct_path", "unsupported"]),
285480
- summary: import_zod5.z.string().min(1)
285819
+ var setupCompatibilityRemediationSchema = import_zod6.z.object({
285820
+ kind: import_zod6.z.enum(["migration", "translation", "retain_direct_path", "unsupported"]),
285821
+ summary: import_zod6.z.string().min(1)
285481
285822
  }).strict();
285482
- var setupCompatibilityBlockerSchema = import_zod5.z.object({
285823
+ var setupCompatibilityBlockerSchema = import_zod6.z.object({
285483
285824
  code: setupCompatibilityBlockerCodeSchema,
285484
- table: import_zod5.z.string().min(1).nullable(),
285485
- field: import_zod5.z.string().min(1).nullable(),
285486
- observed: import_zod5.z.string().min(1),
285487
- expected: import_zod5.z.string().min(1),
285488
- remediations: import_zod5.z.array(setupCompatibilityRemediationSchema).min(1),
285489
- evidence: import_zod5.z.array(setupEvidenceSchema).min(1)
285825
+ table: import_zod6.z.string().min(1).nullable(),
285826
+ field: import_zod6.z.string().min(1).nullable(),
285827
+ observed: import_zod6.z.string().min(1),
285828
+ expected: import_zod6.z.string().min(1),
285829
+ remediations: import_zod6.z.array(setupCompatibilityRemediationSchema).min(1),
285830
+ evidence: import_zod6.z.array(setupEvidenceSchema).min(1)
285490
285831
  }).strict();
285491
- var incompatibleDispositionSchema = import_zod5.z.object({
285492
- blockers: import_zod5.z.array(setupCompatibilityBlockerSchema).min(1),
285493
- mappings: import_zod5.z.array(setupDatabaseMappingSchema)
285832
+ var incompatibleDispositionSchema = import_zod6.z.object({
285833
+ blockers: import_zod6.z.array(setupCompatibilityBlockerSchema).min(1),
285834
+ mappings: import_zod6.z.array(setupDatabaseMappingSchema)
285494
285835
  }).strict();
285495
- var setupCompatibilityDispositionSchema = import_zod5.z.discriminatedUnion("status", [
285496
- import_zod5.z.object({
285497
- status: import_zod5.z.literal("compatible"),
285498
- blockers: import_zod5.z.array(import_zod5.z.never()).length(0),
285499
- mappings: import_zod5.z.array(setupDatabaseMappingSchema)
285836
+ var setupCompatibilityDispositionSchema = import_zod6.z.discriminatedUnion("status", [
285837
+ import_zod6.z.object({
285838
+ status: import_zod6.z.literal("compatible"),
285839
+ blockers: import_zod6.z.array(import_zod6.z.never()).length(0),
285840
+ mappings: import_zod6.z.array(setupDatabaseMappingSchema)
285500
285841
  }).strict(),
285501
- incompatibleDispositionSchema.extend({ status: import_zod5.z.literal("migration_required") }),
285502
- incompatibleDispositionSchema.extend({ status: import_zod5.z.literal("translation_required") }),
285503
- incompatibleDispositionSchema.extend({ status: import_zod5.z.literal("migration_or_translation_required") }),
285504
- incompatibleDispositionSchema.extend({ status: import_zod5.z.literal("unsupported") })
285842
+ incompatibleDispositionSchema.extend({ status: import_zod6.z.literal("migration_required") }),
285843
+ incompatibleDispositionSchema.extend({ status: import_zod6.z.literal("translation_required") }),
285844
+ incompatibleDispositionSchema.extend({ status: import_zod6.z.literal("migration_or_translation_required") }),
285845
+ incompatibleDispositionSchema.extend({ status: import_zod6.z.literal("unsupported") })
285505
285846
  ]);
285506
- var setupAdaptationTaskSchema = import_zod5.z.object({
285507
- schemaVersion: import_zod5.z.literal(SETUP_CONTRACT_VERSION),
285508
- kind: import_zod5.z.literal("ablo_setup_adaptation_task"),
285509
- recordId: import_zod5.z.string().min(1),
285510
- actionId: import_zod5.z.string().min(1),
285511
- repositoryRoot: import_zod5.z.string().min(1),
285512
- applicationRoot: import_zod5.z.string().min(1),
285513
- selectedModels: import_zod5.z.array(import_zod5.z.string().min(1)).min(1),
285514
- databaseMappings: import_zod5.z.array(setupDatabaseMappingSchema).default([]),
285515
- discoveryHints: import_zod5.z.array(setupMutationSiteSchema),
285516
- scope: import_zod5.z.object({
285517
- allowedRoot: import_zod5.z.string().min(1),
285518
- mustExploreBeyondHints: import_zod5.z.literal(true),
285519
- mayReadEnvironmentValues: import_zod5.z.literal(false),
285520
- maximumMutation: import_zod5.z.literal("local_write")
285847
+ var setupAdaptationTaskSchema = import_zod6.z.object({
285848
+ schemaVersion: import_zod6.z.literal(SETUP_CONTRACT_VERSION),
285849
+ kind: import_zod6.z.literal("ablo_setup_adaptation_task"),
285850
+ recordId: import_zod6.z.string().min(1),
285851
+ actionId: import_zod6.z.string().min(1),
285852
+ repositoryRoot: import_zod6.z.string().min(1),
285853
+ applicationRoot: import_zod6.z.string().min(1),
285854
+ selectedModels: import_zod6.z.array(import_zod6.z.string().min(1)).min(1),
285855
+ databaseMappings: import_zod6.z.array(setupDatabaseMappingSchema).default([]),
285856
+ discoveryHints: import_zod6.z.array(setupMutationSiteSchema),
285857
+ scope: import_zod6.z.object({
285858
+ allowedRoot: import_zod6.z.string().min(1),
285859
+ mustExploreBeyondHints: import_zod6.z.literal(true),
285860
+ mayReadEnvironmentValues: import_zod6.z.literal(false),
285861
+ maximumMutation: import_zod6.z.literal("local_write")
285521
285862
  }).strict(),
285522
- objective: import_zod5.z.string().min(1),
285523
- constraints: import_zod5.z.array(import_zod5.z.string().min(1)).min(1),
285524
- acceptanceCriteria: import_zod5.z.array(import_zod5.z.string().min(1)).min(1)
285863
+ objective: import_zod6.z.string().min(1),
285864
+ constraints: import_zod6.z.array(import_zod6.z.string().min(1)).min(1),
285865
+ acceptanceCriteria: import_zod6.z.array(import_zod6.z.string().min(1)).min(1)
285525
285866
  }).strict().superRefine((record, ctx) => {
285526
285867
  if (record.applicationRoot !== record.scope.allowedRoot) {
285527
285868
  ctx.addIssue({
@@ -285531,233 +285872,233 @@ var setupAdaptationTaskSchema = import_zod5.z.object({
285531
285872
  });
285532
285873
  }
285533
285874
  });
285534
- var setupSkillFileSchema = import_zod5.z.object({
285535
- path: import_zod5.z.string().min(1),
285536
- sha256: import_zod5.z.string().regex(/^[a-f0-9]{64}$/),
285537
- content: import_zod5.z.string().min(1)
285875
+ var setupSkillFileSchema = import_zod6.z.object({
285876
+ path: import_zod6.z.string().min(1),
285877
+ sha256: import_zod6.z.string().regex(/^[a-f0-9]{64}$/),
285878
+ content: import_zod6.z.string().min(1)
285538
285879
  }).strict();
285539
- var setupSkillBundleSchema = import_zod5.z.object({
285540
- schemaVersion: import_zod5.z.literal(SETUP_CONTRACT_VERSION),
285541
- kind: import_zod5.z.literal("ablo_setup_skill"),
285542
- id: import_zod5.z.literal("integrate-ablo"),
285543
- version: import_zod5.z.string().min(1),
285544
- entrypoint: import_zod5.z.literal("SKILL.md"),
285545
- files: import_zod5.z.array(setupSkillFileSchema).min(1)
285880
+ var setupSkillBundleSchema = import_zod6.z.object({
285881
+ schemaVersion: import_zod6.z.literal(SETUP_CONTRACT_VERSION),
285882
+ kind: import_zod6.z.literal("ablo_setup_skill"),
285883
+ id: import_zod6.z.literal("integrate-ablo"),
285884
+ version: import_zod6.z.string().min(1),
285885
+ entrypoint: import_zod6.z.literal("SKILL.md"),
285886
+ files: import_zod6.z.array(setupSkillFileSchema).min(1)
285546
285887
  }).strict();
285547
- var setupAgentBundleSchema = import_zod5.z.object({
285548
- schemaVersion: import_zod5.z.literal(SETUP_CONTRACT_VERSION),
285549
- kind: import_zod5.z.literal("ablo_setup_agent_bundle"),
285550
- createdAt: import_zod5.z.iso.datetime(),
285888
+ var setupAgentBundleSchema = import_zod6.z.object({
285889
+ schemaVersion: import_zod6.z.literal(SETUP_CONTRACT_VERSION),
285890
+ kind: import_zod6.z.literal("ablo_setup_agent_bundle"),
285891
+ createdAt: import_zod6.z.iso.datetime(),
285551
285892
  record: setupAdaptationTaskSchema,
285552
285893
  skill: setupSkillBundleSchema
285553
285894
  }).strict();
285554
- var setupWorkspaceSnapshotSchema = import_zod5.z.object({
285555
- schemaVersion: import_zod5.z.literal(SETUP_CONTRACT_VERSION),
285556
- kind: import_zod5.z.literal("ablo_setup_workspace_snapshot"),
285557
- repositoryRoot: import_zod5.z.string().min(1),
285558
- capturedAt: import_zod5.z.iso.datetime(),
285559
- truncated: import_zod5.z.boolean(),
285560
- files: import_zod5.z.array(import_zod5.z.object({
285561
- path: import_zod5.z.string().min(1),
285562
- fingerprint: import_zod5.z.string().regex(/^[a-f0-9]{64}$/),
285563
- size: import_zod5.z.number().int().nonnegative(),
285564
- protectedEnvironment: import_zod5.z.boolean()
285895
+ var setupWorkspaceSnapshotSchema = import_zod6.z.object({
285896
+ schemaVersion: import_zod6.z.literal(SETUP_CONTRACT_VERSION),
285897
+ kind: import_zod6.z.literal("ablo_setup_workspace_snapshot"),
285898
+ repositoryRoot: import_zod6.z.string().min(1),
285899
+ capturedAt: import_zod6.z.iso.datetime(),
285900
+ truncated: import_zod6.z.boolean(),
285901
+ files: import_zod6.z.array(import_zod6.z.object({
285902
+ path: import_zod6.z.string().min(1),
285903
+ fingerprint: import_zod6.z.string().regex(/^[a-f0-9]{64}$/),
285904
+ size: import_zod6.z.number().int().nonnegative(),
285905
+ protectedEnvironment: import_zod6.z.boolean()
285565
285906
  }).strict())
285566
285907
  }).strict();
285567
- var setupDiffEvaluationSchema = import_zod5.z.object({
285568
- schemaVersion: import_zod5.z.literal(SETUP_CONTRACT_VERSION),
285569
- kind: import_zod5.z.literal("ablo_setup_diff_evaluation"),
285570
- createdAt: import_zod5.z.iso.datetime(),
285571
- selectedModels: import_zod5.z.array(import_zod5.z.string().min(1)).min(1),
285572
- changes: import_zod5.z.array(import_zod5.z.object({
285573
- path: import_zod5.z.string().min(1),
285574
- kind: import_zod5.z.enum(["created", "modified", "deleted"])
285908
+ var setupDiffEvaluationSchema = import_zod6.z.object({
285909
+ schemaVersion: import_zod6.z.literal(SETUP_CONTRACT_VERSION),
285910
+ kind: import_zod6.z.literal("ablo_setup_diff_evaluation"),
285911
+ createdAt: import_zod6.z.iso.datetime(),
285912
+ selectedModels: import_zod6.z.array(import_zod6.z.string().min(1)).min(1),
285913
+ changes: import_zod6.z.array(import_zod6.z.object({
285914
+ path: import_zod6.z.string().min(1),
285915
+ kind: import_zod6.z.enum(["created", "modified", "deleted"])
285575
285916
  }).strict()),
285576
- checks: import_zod5.z.array(import_zod5.z.object({
285577
- id: import_zod5.z.string().min(1),
285578
- status: import_zod5.z.enum(["pass", "fail", "review"]),
285579
- detail: import_zod5.z.string().min(1),
285580
- evidencePaths: import_zod5.z.array(import_zod5.z.string().min(1))
285917
+ checks: import_zod6.z.array(import_zod6.z.object({
285918
+ id: import_zod6.z.string().min(1),
285919
+ status: import_zod6.z.enum(["pass", "fail", "review"]),
285920
+ detail: import_zod6.z.string().min(1),
285921
+ evidencePaths: import_zod6.z.array(import_zod6.z.string().min(1))
285581
285922
  }).strict()),
285582
- outcome: import_zod5.z.enum(["candidate", "incomplete", "unsafe"]),
285583
- summary: import_zod5.z.string().min(1)
285923
+ outcome: import_zod6.z.enum(["candidate", "incomplete", "unsafe"]),
285924
+ summary: import_zod6.z.string().min(1)
285584
285925
  }).strict();
285585
- var setupEvalVerificationSchema = import_zod5.z.object({
285586
- id: import_zod5.z.string().min(1),
285587
- status: import_zod5.z.enum(["pass", "fail", "error"]),
285588
- detail: import_zod5.z.string().min(1),
285589
- durationMs: import_zod5.z.number().int().nonnegative()
285926
+ var setupEvalVerificationSchema = import_zod6.z.object({
285927
+ id: import_zod6.z.string().min(1),
285928
+ status: import_zod6.z.enum(["pass", "fail", "error"]),
285929
+ detail: import_zod6.z.string().min(1),
285930
+ durationMs: import_zod6.z.number().int().nonnegative()
285590
285931
  }).strict();
285591
- var setupAgentHandoffSchema = import_zod5.z.object({
285592
- outcome: import_zod5.z.enum(["candidate", "blocked", "failed"]),
285593
- changedFiles: import_zod5.z.array(import_zod5.z.string().min(1)),
285594
- exploredWritePaths: import_zod5.z.array(import_zod5.z.object({
285595
- model: import_zod5.z.string().min(1),
285596
- path: import_zod5.z.string().min(1),
285597
- role: import_zod5.z.string().min(1)
285932
+ var setupAgentHandoffSchema = import_zod6.z.object({
285933
+ outcome: import_zod6.z.enum(["candidate", "blocked", "failed"]),
285934
+ changedFiles: import_zod6.z.array(import_zod6.z.string().min(1)),
285935
+ exploredWritePaths: import_zod6.z.array(import_zod6.z.object({
285936
+ model: import_zod6.z.string().min(1),
285937
+ path: import_zod6.z.string().min(1),
285938
+ role: import_zod6.z.string().min(1)
285598
285939
  }).strict()),
285599
- directWriteExceptions: import_zod5.z.array(import_zod5.z.object({
285600
- path: import_zod5.z.string().min(1),
285601
- reason: import_zod5.z.string().min(1)
285940
+ directWriteExceptions: import_zod6.z.array(import_zod6.z.object({
285941
+ path: import_zod6.z.string().min(1),
285942
+ reason: import_zod6.z.string().min(1)
285602
285943
  }).strict()),
285603
- verification: import_zod5.z.array(import_zod5.z.object({
285604
- command: import_zod5.z.string().min(1),
285605
- exitCode: import_zod5.z.number().int().nullable(),
285606
- result: import_zod5.z.string().min(1)
285944
+ verification: import_zod6.z.array(import_zod6.z.object({
285945
+ command: import_zod6.z.string().min(1),
285946
+ exitCode: import_zod6.z.number().int().nullable(),
285947
+ result: import_zod6.z.string().min(1)
285607
285948
  }).strict()),
285608
- blockers: import_zod5.z.array(import_zod5.z.string().min(1))
285949
+ blockers: import_zod6.z.array(import_zod6.z.string().min(1))
285609
285950
  }).strict();
285610
- var setupEvalResultSchema = import_zod5.z.object({
285611
- schemaVersion: import_zod5.z.literal(SETUP_CONTRACT_VERSION),
285612
- kind: import_zod5.z.literal("ablo_setup_eval_result"),
285613
- caseId: import_zod5.z.string().min(1),
285614
- runner: import_zod5.z.string().min(1),
285615
- model: import_zod5.z.string().min(1).nullable(),
285616
- startedAt: import_zod5.z.iso.datetime(),
285617
- finishedAt: import_zod5.z.iso.datetime(),
285618
- durationMs: import_zod5.z.number().int().nonnegative(),
285619
- agent: import_zod5.z.object({
285620
- status: import_zod5.z.enum(["completed", "failed", "timed_out"]),
285621
- exitCode: import_zod5.z.number().int().nullable(),
285951
+ var setupEvalResultSchema = import_zod6.z.object({
285952
+ schemaVersion: import_zod6.z.literal(SETUP_CONTRACT_VERSION),
285953
+ kind: import_zod6.z.literal("ablo_setup_eval_result"),
285954
+ caseId: import_zod6.z.string().min(1),
285955
+ runner: import_zod6.z.string().min(1),
285956
+ model: import_zod6.z.string().min(1).nullable(),
285957
+ startedAt: import_zod6.z.iso.datetime(),
285958
+ finishedAt: import_zod6.z.iso.datetime(),
285959
+ durationMs: import_zod6.z.number().int().nonnegative(),
285960
+ agent: import_zod6.z.object({
285961
+ status: import_zod6.z.enum(["completed", "failed", "timed_out"]),
285962
+ exitCode: import_zod6.z.number().int().nullable(),
285622
285963
  handoff: setupAgentHandoffSchema.nullable()
285623
285964
  }).strict(),
285624
285965
  diff: setupDiffEvaluationSchema,
285625
- verification: import_zod5.z.array(setupEvalVerificationSchema),
285626
- outcome: import_zod5.z.enum(["passed", "blocked", "failed", "incomplete", "unsafe"]),
285627
- summary: import_zod5.z.string().min(1)
285966
+ verification: import_zod6.z.array(setupEvalVerificationSchema),
285967
+ outcome: import_zod6.z.enum(["passed", "blocked", "failed", "incomplete", "unsafe"]),
285968
+ summary: import_zod6.z.string().min(1)
285628
285969
  }).strict();
285629
- var setupRepositoryBenchmarkCaseSchema = import_zod5.z.object({
285630
- schemaVersion: import_zod5.z.literal(SETUP_CONTRACT_VERSION),
285631
- kind: import_zod5.z.literal("ablo_setup_repository_benchmark_case"),
285632
- caseId: import_zod5.z.string().min(1),
285633
- repository: import_zod5.z.object({
285634
- url: import_zod5.z.url(),
285635
- commit: import_zod5.z.string().regex(/^[a-f0-9]{40}$/)
285970
+ var setupRepositoryBenchmarkCaseSchema = import_zod6.z.object({
285971
+ schemaVersion: import_zod6.z.literal(SETUP_CONTRACT_VERSION),
285972
+ kind: import_zod6.z.literal("ablo_setup_repository_benchmark_case"),
285973
+ caseId: import_zod6.z.string().min(1),
285974
+ repository: import_zod6.z.object({
285975
+ url: import_zod6.z.url(),
285976
+ commit: import_zod6.z.string().regex(/^[a-f0-9]{40}$/)
285636
285977
  }).strict(),
285637
- expectations: import_zod5.z.object({
285638
- applicationRoot: import_zod5.z.string().min(1),
285639
- persistenceIncludes: import_zod5.z.array(import_zod5.z.string().min(1)),
285640
- requiredMutationPaths: import_zod5.z.array(import_zod5.z.string().min(1)),
285641
- forbiddenMutationPathPrefixes: import_zod5.z.array(import_zod5.z.string().min(1)),
285978
+ expectations: import_zod6.z.object({
285979
+ applicationRoot: import_zod6.z.string().min(1),
285980
+ persistenceIncludes: import_zod6.z.array(import_zod6.z.string().min(1)),
285981
+ requiredMutationPaths: import_zod6.z.array(import_zod6.z.string().min(1)),
285982
+ forbiddenMutationPathPrefixes: import_zod6.z.array(import_zod6.z.string().min(1)),
285642
285983
  coordinationAdoption: setupCoordinationAdoptionDispositionSchema
285643
285984
  }).strict()
285644
285985
  }).strict();
285645
- var setupRepositoryBenchmarkResultSchema = import_zod5.z.object({
285646
- schemaVersion: import_zod5.z.literal(SETUP_CONTRACT_VERSION),
285647
- kind: import_zod5.z.literal("ablo_setup_repository_benchmark_result"),
285648
- caseId: import_zod5.z.string().min(1),
285649
- repositoryUrl: import_zod5.z.url(),
285650
- commit: import_zod5.z.string().regex(/^[a-f0-9]{40}$/),
285651
- checks: import_zod5.z.array(import_zod5.z.object({
285652
- id: import_zod5.z.string().min(1),
285653
- status: import_zod5.z.enum(["pass", "fail"]),
285654
- detail: import_zod5.z.string().min(1)
285986
+ var setupRepositoryBenchmarkResultSchema = import_zod6.z.object({
285987
+ schemaVersion: import_zod6.z.literal(SETUP_CONTRACT_VERSION),
285988
+ kind: import_zod6.z.literal("ablo_setup_repository_benchmark_result"),
285989
+ caseId: import_zod6.z.string().min(1),
285990
+ repositoryUrl: import_zod6.z.url(),
285991
+ commit: import_zod6.z.string().regex(/^[a-f0-9]{40}$/),
285992
+ checks: import_zod6.z.array(import_zod6.z.object({
285993
+ id: import_zod6.z.string().min(1),
285994
+ status: import_zod6.z.enum(["pass", "fail"]),
285995
+ detail: import_zod6.z.string().min(1)
285655
285996
  }).strict()),
285656
- outcome: import_zod5.z.enum(["passed", "failed"])
285997
+ outcome: import_zod6.z.enum(["passed", "failed"])
285657
285998
  }).strict();
285658
- var setupStepResultBaseSchema = import_zod5.z.object({
285659
- stepId: import_zod5.z.string().min(1),
285660
- summary: import_zod5.z.string().min(1),
285661
- facts: import_zod5.z.array(setupFactSchema).default([]),
285662
- decisions: import_zod5.z.array(setupDecisionSchema).default([]),
285663
- actions: import_zod5.z.array(setupActionSchema).default([]),
285664
- startedAt: import_zod5.z.iso.datetime(),
285665
- finishedAt: import_zod5.z.iso.datetime()
285999
+ var setupStepResultBaseSchema = import_zod6.z.object({
286000
+ stepId: import_zod6.z.string().min(1),
286001
+ summary: import_zod6.z.string().min(1),
286002
+ facts: import_zod6.z.array(setupFactSchema).default([]),
286003
+ decisions: import_zod6.z.array(setupDecisionSchema).default([]),
286004
+ actions: import_zod6.z.array(setupActionSchema).default([]),
286005
+ startedAt: import_zod6.z.iso.datetime(),
286006
+ finishedAt: import_zod6.z.iso.datetime()
285666
286007
  }).strict();
285667
- var setupStepResultSchema = import_zod5.z.discriminatedUnion("status", [
285668
- setupStepResultBaseSchema.extend({ status: import_zod5.z.literal("complete") }),
286008
+ var setupStepResultSchema = import_zod6.z.discriminatedUnion("status", [
286009
+ setupStepResultBaseSchema.extend({ status: import_zod6.z.literal("complete") }),
285669
286010
  setupStepResultBaseSchema.extend({
285670
- status: import_zod5.z.literal("incomplete"),
285671
- next: import_zod5.z.string().min(1)
286011
+ status: import_zod6.z.literal("incomplete"),
286012
+ next: import_zod6.z.string().min(1)
285672
286013
  }),
285673
286014
  setupStepResultBaseSchema.extend({
285674
- status: import_zod5.z.literal("blocked"),
285675
- blockers: import_zod5.z.array(import_zod5.z.string().min(1)).min(1),
285676
- next: import_zod5.z.string().min(1)
286015
+ status: import_zod6.z.literal("blocked"),
286016
+ blockers: import_zod6.z.array(import_zod6.z.string().min(1)).min(1),
286017
+ next: import_zod6.z.string().min(1)
285677
286018
  }),
285678
286019
  setupStepResultBaseSchema.extend({
285679
- status: import_zod5.z.literal("failed"),
285680
- error: import_zod5.z.object({
285681
- code: import_zod5.z.string().min(1),
285682
- message: import_zod5.z.string().min(1)
286020
+ status: import_zod6.z.literal("failed"),
286021
+ error: import_zod6.z.object({
286022
+ code: import_zod6.z.string().min(1),
286023
+ message: import_zod6.z.string().min(1)
285683
286024
  }).strict()
285684
286025
  })
285685
286026
  ]);
285686
- var setupTargetSchema = import_zod5.z.object({
285687
- repositoryRoot: import_zod5.z.string().min(1),
285688
- applicationRoot: import_zod5.z.string().min(1).nullable(),
285689
- packageName: import_zod5.z.string().min(1).nullable(),
285690
- abloProjectId: import_zod5.z.string().min(1).nullable(),
285691
- abloBranchId: import_zod5.z.string().min(1).nullable(),
285692
- databaseFingerprint: import_zod5.z.string().min(1).nullable(),
285693
- localSchemaDigest: import_zod5.z.string().min(1).nullable(),
285694
- pushedSchemaDigest: import_zod5.z.string().min(1).nullable()
286027
+ var setupTargetSchema = import_zod6.z.object({
286028
+ repositoryRoot: import_zod6.z.string().min(1),
286029
+ applicationRoot: import_zod6.z.string().min(1).nullable(),
286030
+ packageName: import_zod6.z.string().min(1).nullable(),
286031
+ abloProjectId: import_zod6.z.string().min(1).nullable(),
286032
+ abloBranchId: import_zod6.z.string().min(1).nullable(),
286033
+ databaseFingerprint: import_zod6.z.string().min(1).nullable(),
286034
+ localSchemaDigest: import_zod6.z.string().min(1).nullable(),
286035
+ pushedSchemaDigest: import_zod6.z.string().min(1).nullable()
285695
286036
  }).strict();
285696
- var setupPostconditionSchema = import_zod5.z.object({
285697
- id: import_zod5.z.string().min(1),
285698
- description: import_zod5.z.string().min(1),
285699
- status: import_zod5.z.enum(["unverified", "satisfied", "unsatisfied", "blocked"]),
285700
- evidence: import_zod5.z.array(setupEvidenceSchema).default([])
286037
+ var setupPostconditionSchema = import_zod6.z.object({
286038
+ id: import_zod6.z.string().min(1),
286039
+ description: import_zod6.z.string().min(1),
286040
+ status: import_zod6.z.enum(["unverified", "satisfied", "unsatisfied", "blocked"]),
286041
+ evidence: import_zod6.z.array(setupEvidenceSchema).default([])
285701
286042
  }).strict();
285702
- var setupInitPlanProjectionSchema = import_zod5.z.object({
285703
- root: import_zod5.z.string().min(1),
285704
- actions: import_zod5.z.array(import_zod5.z.object({
285705
- kind: import_zod5.z.enum(["create", "update", "unchanged"]),
285706
- path: import_zod5.z.string().min(1),
285707
- note: import_zod5.z.string().optional(),
285708
- precondition: import_zod5.z.discriminatedUnion("kind", [
285709
- import_zod5.z.object({ kind: import_zod5.z.literal("absent") }).strict(),
285710
- import_zod5.z.object({
285711
- kind: import_zod5.z.literal("content"),
285712
- sha256: import_zod5.z.string().regex(/^[a-f0-9]{64}$/)
286043
+ var setupInitPlanProjectionSchema = import_zod6.z.object({
286044
+ root: import_zod6.z.string().min(1),
286045
+ actions: import_zod6.z.array(import_zod6.z.object({
286046
+ kind: import_zod6.z.enum(["create", "update", "unchanged"]),
286047
+ path: import_zod6.z.string().min(1),
286048
+ note: import_zod6.z.string().optional(),
286049
+ precondition: import_zod6.z.discriminatedUnion("kind", [
286050
+ import_zod6.z.object({ kind: import_zod6.z.literal("absent") }).strict(),
286051
+ import_zod6.z.object({
286052
+ kind: import_zod6.z.literal("content"),
286053
+ sha256: import_zod6.z.string().regex(/^[a-f0-9]{64}$/)
285713
286054
  }).strict()
285714
286055
  ]).optional()
285715
286056
  }).strict()),
285716
- conflicts: import_zod5.z.array(import_zod5.z.object({
285717
- path: import_zod5.z.string().min(1),
285718
- reason: import_zod5.z.literal("occupied")
286057
+ conflicts: import_zod6.z.array(import_zod6.z.object({
286058
+ path: import_zod6.z.string().min(1),
286059
+ reason: import_zod6.z.literal("occupied")
285719
286060
  }).strict())
285720
286061
  }).strict();
285721
- var setupInitResultSchema = import_zod5.z.object({
285722
- status: import_zod5.z.enum(["planned", "applied"]),
286062
+ var setupInitResultSchema = import_zod6.z.object({
286063
+ status: import_zod6.z.enum(["planned", "applied"]),
285723
286064
  plan: setupInitPlanProjectionSchema
285724
286065
  }).strict();
285725
- var setupPlanSchema = import_zod5.z.object({
285726
- schemaVersion: import_zod5.z.literal(SETUP_CONTRACT_VERSION),
285727
- kind: import_zod5.z.literal("ablo_setup_plan"),
285728
- mode: import_zod5.z.literal("plan"),
285729
- createdAt: import_zod5.z.iso.datetime(),
286066
+ var setupPlanSchema = import_zod6.z.object({
286067
+ schemaVersion: import_zod6.z.literal(SETUP_CONTRACT_VERSION),
286068
+ kind: import_zod6.z.literal("ablo_setup_plan"),
286069
+ mode: import_zod6.z.literal("plan"),
286070
+ createdAt: import_zod6.z.iso.datetime(),
285730
286071
  target: setupTargetSchema,
285731
286072
  compatibility: setupCompatibilityDispositionSchema,
285732
- steps: import_zod5.z.array(setupStepResultSchema),
285733
- facts: import_zod5.z.array(setupFactSchema),
285734
- decisions: import_zod5.z.array(setupDecisionSchema),
285735
- actions: import_zod5.z.array(setupActionSchema),
285736
- postconditions: import_zod5.z.array(setupPostconditionSchema),
285737
- outcome: import_zod5.z.enum(["ready_to_apply", "needs_decisions", "blocked"]),
285738
- summary: import_zod5.z.string().min(1)
286073
+ steps: import_zod6.z.array(setupStepResultSchema),
286074
+ facts: import_zod6.z.array(setupFactSchema),
286075
+ decisions: import_zod6.z.array(setupDecisionSchema),
286076
+ actions: import_zod6.z.array(setupActionSchema),
286077
+ postconditions: import_zod6.z.array(setupPostconditionSchema),
286078
+ outcome: import_zod6.z.enum(["ready_to_apply", "needs_decisions", "blocked"]),
286079
+ summary: import_zod6.z.string().min(1)
285739
286080
  }).strict();
285740
- var setupCheckpointSchema = import_zod5.z.object({
285741
- schemaVersion: import_zod5.z.literal(SETUP_CONTRACT_VERSION),
285742
- kind: import_zod5.z.literal("ablo_setup_checkpoint"),
285743
- programId: import_zod5.z.string().min(1),
285744
- repositoryRoot: import_zod5.z.string().min(1),
285745
- createdAt: import_zod5.z.iso.datetime(),
285746
- updatedAt: import_zod5.z.iso.datetime(),
285747
- completedStepIds: import_zod5.z.array(import_zod5.z.string().min(1)),
285748
- results: import_zod5.z.array(setupStepResultSchema)
286081
+ var setupCheckpointSchema = import_zod6.z.object({
286082
+ schemaVersion: import_zod6.z.literal(SETUP_CONTRACT_VERSION),
286083
+ kind: import_zod6.z.literal("ablo_setup_checkpoint"),
286084
+ programId: import_zod6.z.string().min(1),
286085
+ repositoryRoot: import_zod6.z.string().min(1),
286086
+ createdAt: import_zod6.z.iso.datetime(),
286087
+ updatedAt: import_zod6.z.iso.datetime(),
286088
+ completedStepIds: import_zod6.z.array(import_zod6.z.string().min(1)),
286089
+ results: import_zod6.z.array(setupStepResultSchema)
285749
286090
  }).strict();
285750
- var setupReportSchema = import_zod5.z.object({
285751
- schemaVersion: import_zod5.z.literal(SETUP_CONTRACT_VERSION),
285752
- kind: import_zod5.z.literal("ablo_setup_report"),
285753
- createdAt: import_zod5.z.iso.datetime(),
286091
+ var setupReportSchema = import_zod6.z.object({
286092
+ schemaVersion: import_zod6.z.literal(SETUP_CONTRACT_VERSION),
286093
+ kind: import_zod6.z.literal("ablo_setup_report"),
286094
+ createdAt: import_zod6.z.iso.datetime(),
285754
286095
  target: setupTargetSchema,
285755
- outcome: import_zod5.z.enum(["complete", "incomplete", "blocked", "failed"]),
285756
- facts: import_zod5.z.array(setupFactSchema),
285757
- decisions: import_zod5.z.array(setupDecisionSchema),
285758
- actions: import_zod5.z.array(setupActionSchema),
285759
- postconditions: import_zod5.z.array(setupPostconditionSchema),
285760
- next: import_zod5.z.array(import_zod5.z.string().min(1))
286096
+ outcome: import_zod6.z.enum(["complete", "incomplete", "blocked", "failed"]),
286097
+ facts: import_zod6.z.array(setupFactSchema),
286098
+ decisions: import_zod6.z.array(setupDecisionSchema),
286099
+ actions: import_zod6.z.array(setupActionSchema),
286100
+ postconditions: import_zod6.z.array(setupPostconditionSchema),
286101
+ next: import_zod6.z.array(import_zod6.z.string().min(1))
285761
286102
  }).strict();
285762
286103
 
285763
286104
  // src/setup/program.ts
@@ -286132,7 +286473,7 @@ function walkFiles(root, maxDepth = 5) {
286132
286473
  const current = stack.pop();
286133
286474
  let entries;
286134
286475
  try {
286135
- entries = (0, import_node_fs2.readdirSync)(current.path, { withFileTypes: true });
286476
+ entries = (0, import_node_fs3.readdirSync)(current.path, { withFileTypes: true });
286136
286477
  } catch {
286137
286478
  continue;
286138
286479
  }
@@ -286152,7 +286493,7 @@ function walkFiles(root, maxDepth = 5) {
286152
286493
  }
286153
286494
  function readManifest(path) {
286154
286495
  try {
286155
- const parsed = JSON.parse((0, import_node_fs2.readFileSync)(path, "utf8"));
286496
+ const parsed = JSON.parse((0, import_node_fs3.readFileSync)(path, "utf8"));
286156
286497
  return {
286157
286498
  root: (0, import_node_path2.resolve)(path, ".."),
286158
286499
  name: typeof parsed.name === "string" ? parsed.name : null,
@@ -286229,8 +286570,8 @@ function detectedPersistence(manifest, files) {
286229
286570
  if (!SOURCE_EXTENSIONS.has(sourceExtension(path))) continue;
286230
286571
  let source;
286231
286572
  try {
286232
- if ((0, import_node_fs2.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
286233
- source = (0, import_node_fs2.readFileSync)(path, "utf8");
286573
+ if ((0, import_node_fs3.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
286574
+ source = (0, import_node_fs3.readFileSync)(path, "utf8");
286234
286575
  } catch {
286235
286576
  continue;
286236
286577
  }
@@ -286258,17 +286599,17 @@ function coordinationAdoptionReason(disposition, persistence) {
286258
286599
  }
286259
286600
  }
286260
286601
  function packageManager(root) {
286261
- if ((0, import_node_fs2.existsSync)((0, import_node_path2.join)(root, "pnpm-lock.yaml"))) return "pnpm";
286262
- if ((0, import_node_fs2.existsSync)((0, import_node_path2.join)(root, "yarn.lock"))) return "yarn";
286263
- if ((0, import_node_fs2.existsSync)((0, import_node_path2.join)(root, "bun.lockb")) || (0, import_node_fs2.existsSync)((0, import_node_path2.join)(root, "bun.lock"))) return "bun";
286602
+ if ((0, import_node_fs3.existsSync)((0, import_node_path2.join)(root, "pnpm-lock.yaml"))) return "pnpm";
286603
+ if ((0, import_node_fs3.existsSync)((0, import_node_path2.join)(root, "yarn.lock"))) return "yarn";
286604
+ if ((0, import_node_fs3.existsSync)((0, import_node_path2.join)(root, "bun.lockb")) || (0, import_node_fs3.existsSync)((0, import_node_path2.join)(root, "bun.lock"))) return "bun";
286264
286605
  return "npm";
286265
286606
  }
286266
286607
  function environmentKeyNames(root) {
286267
286608
  const names = [".env.local", ".env.development.local", ".env.development", ".env"];
286268
286609
  return names.flatMap((name) => {
286269
286610
  const path = (0, import_node_path2.join)(root, name);
286270
- if (!(0, import_node_fs2.existsSync)(path)) return [];
286271
- const keys = (0, import_node_fs2.readFileSync)(path, "utf8").split(/\r?\n/).flatMap((line) => {
286611
+ if (!(0, import_node_fs3.existsSync)(path)) return [];
286612
+ const keys = (0, import_node_fs3.readFileSync)(path, "utf8").split(/\r?\n/).flatMap((line) => {
286272
286613
  const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line);
286273
286614
  return match ? [match[1]] : [];
286274
286615
  });
@@ -286283,8 +286624,8 @@ function abloSourceFiles(root, files) {
286283
286624
  return files.flatMap((path) => {
286284
286625
  if (!SOURCE_EXTENSIONS.has(sourceExtension(path))) return [];
286285
286626
  try {
286286
- if ((0, import_node_fs2.lstatSync)(path).size > MAX_SOURCE_BYTES) return [];
286287
- return (0, import_node_fs2.readFileSync)(path, "utf8").includes("@abloatai/") ? [(0, import_node_path2.relative)(root, path) || "."] : [];
286627
+ if ((0, import_node_fs3.lstatSync)(path).size > MAX_SOURCE_BYTES) return [];
286628
+ return (0, import_node_fs3.readFileSync)(path, "utf8").includes("@abloatai/") ? [(0, import_node_path2.relative)(root, path) || "."] : [];
286288
286629
  } catch {
286289
286630
  return [];
286290
286631
  }
@@ -286311,8 +286652,8 @@ function discoverMutationSites(root, files) {
286311
286652
  if (!SOURCE_EXTENSIONS.has(sourceExtension(path))) continue;
286312
286653
  let source;
286313
286654
  try {
286314
- if ((0, import_node_fs2.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
286315
- source = (0, import_node_fs2.readFileSync)(path, "utf8");
286655
+ if ((0, import_node_fs3.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
286656
+ source = (0, import_node_fs3.readFileSync)(path, "utf8");
286316
286657
  } catch {
286317
286658
  continue;
286318
286659
  }
@@ -286352,9 +286693,9 @@ function isProductionMutationFile(root, path) {
286352
286693
  return !/(?:^|\/)(?:test|tests|__tests__|scripts)(?:\/|$)/.test(locator) && !/\.(?:test|spec)\.[cm]?[jt]sx?$/.test(locator);
286353
286694
  }
286354
286695
  function digestFile(path) {
286355
- if (!(0, import_node_fs2.existsSync)(path)) return null;
286696
+ if (!(0, import_node_fs3.existsSync)(path)) return null;
286356
286697
  try {
286357
- return (0, import_node_crypto4.createHash)("sha256").update((0, import_node_fs2.readFileSync)(path)).digest("hex");
286698
+ return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs3.readFileSync)(path)).digest("hex");
286358
286699
  } catch {
286359
286700
  return null;
286360
286701
  }
@@ -286398,8 +286739,8 @@ function localDiscoveryStep(state) {
286398
286739
  if (!SOURCE_EXTENSIONS.has(sourceExtension(path))) continue;
286399
286740
  let source;
286400
286741
  try {
286401
- if ((0, import_node_fs2.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
286402
- source = (0, import_node_fs2.readFileSync)(path, "utf8");
286742
+ if ((0, import_node_fs3.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
286743
+ source = (0, import_node_fs3.readFileSync)(path, "utf8");
286403
286744
  } catch {
286404
286745
  continue;
286405
286746
  }
@@ -286440,8 +286781,8 @@ function localDiscoveryStep(state) {
286440
286781
  "src/app/providers.tsx",
286441
286782
  "app/api/ablo-session/route.ts",
286442
286783
  "src/app/api/ablo-session/route.ts"
286443
- ].filter((path) => (0, import_node_fs2.existsSync)((0, import_node_path2.join)(envRoot, path)));
286444
- const localSchemaPath = [(0, import_node_path2.join)(envRoot, "ablo", "schema.ts"), (0, import_node_path2.join)(envRoot, "src", "ablo", "schema.ts")].find((path) => (0, import_node_fs2.existsSync)(path)) ?? (0, import_node_path2.join)(envRoot, "ablo", "schema.ts");
286784
+ ].filter((path) => (0, import_node_fs3.existsSync)((0, import_node_path2.join)(envRoot, path)));
286785
+ const localSchemaPath = [(0, import_node_path2.join)(envRoot, "ablo", "schema.ts"), (0, import_node_path2.join)(envRoot, "src", "ablo", "schema.ts")].find((path) => (0, import_node_fs3.existsSync)(path)) ?? (0, import_node_path2.join)(envRoot, "ablo", "schema.ts");
286445
286786
  state.localSchemaDigest = digestFile(localSchemaPath);
286446
286787
  const facts = [
286447
286788
  fact("repository.root", root, "git", tryGit(root, ["rev-parse", "--show-toplevel"]) ? "Resolved from Git." : "No Git root was available; using the requested directory.", root),
@@ -286843,7 +287184,7 @@ function parseSetupArgs(args) {
286843
287184
  if (arg === "--root") {
286844
287185
  const next = args[index + 1];
286845
287186
  if (!next || next.startsWith("-")) {
286846
- throw new import_errors15.AbloValidationError("`--root` requires a directory.", {
287187
+ throw new import_errors16.AbloValidationError("`--root` requires a directory.", {
286847
287188
  code: "cli_invalid_arguments"
286848
287189
  });
286849
287190
  }
@@ -286852,7 +287193,7 @@ function parseSetupArgs(args) {
286852
287193
  continue;
286853
287194
  }
286854
287195
  if (!allowedFlags.has(arg)) {
286855
- throw new import_errors15.AbloValidationError(`Unknown setup option: ${arg}`, {
287196
+ throw new import_errors16.AbloValidationError(`Unknown setup option: ${arg}`, {
286856
287197
  code: "cli_invalid_arguments"
286857
287198
  });
286858
287199
  }
@@ -286864,7 +287205,7 @@ function parseSetupArgs(args) {
286864
287205
  };
286865
287206
  }
286866
287207
  function renderValue(value) {
286867
- if (value === null) return import_picocolors18.default.dim("unknown");
287208
+ if (value === null) return import_picocolors19.default.dim("unknown");
286868
287209
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
286869
287210
  return String(value);
286870
287211
  }
@@ -286876,69 +287217,69 @@ function renderStatus(value) {
286876
287217
  }
286877
287218
  function renderHumanPlan(plan) {
286878
287219
  console.log(`
286879
- ${brand("ablo")} ${import_picocolors18.default.dim("setup plan")} ${import_picocolors18.default.dim("(read-only)")}
287220
+ ${brand("ablo")} ${import_picocolors19.default.dim("setup plan")} ${import_picocolors19.default.dim("(read-only)")}
286880
287221
  `);
286881
- console.log(` ${import_picocolors18.default.bold("Target")}`);
287222
+ console.log(` ${import_picocolors19.default.bold("Target")}`);
286882
287223
  console.log(` repository ${plan.target.repositoryRoot}`);
286883
- console.log(` application ${plan.target.applicationRoot ?? import_picocolors18.default.yellow("unresolved")}`);
286884
- console.log(` package ${plan.target.packageName ?? import_picocolors18.default.dim("unknown")}`);
286885
- console.log(` project ${plan.target.abloProjectId ?? import_picocolors18.default.dim("unconfirmed")}`);
286886
- console.log(` branch ${plan.target.abloBranchId ?? import_picocolors18.default.dim("unconfirmed")}`);
286887
- console.log(` compatibility ${plan.compatibility.status === "compatible" ? import_picocolors18.default.green("compatible") : import_picocolors18.default.yellow(renderStatus(plan.compatibility.status))}`);
287224
+ console.log(` application ${plan.target.applicationRoot ?? import_picocolors19.default.yellow("unresolved")}`);
287225
+ console.log(` package ${plan.target.packageName ?? import_picocolors19.default.dim("unknown")}`);
287226
+ console.log(` project ${plan.target.abloProjectId ?? import_picocolors19.default.dim("unconfirmed")}`);
287227
+ console.log(` branch ${plan.target.abloBranchId ?? import_picocolors19.default.dim("unconfirmed")}`);
287228
+ console.log(` compatibility ${plan.compatibility.status === "compatible" ? import_picocolors19.default.green("compatible") : import_picocolors19.default.yellow(renderStatus(plan.compatibility.status))}`);
286888
287229
  if (plan.compatibility.blockers.length > 0) {
286889
287230
  console.log(`
286890
- ${import_picocolors18.default.bold("Compatibility blockers")}`);
287231
+ ${import_picocolors19.default.bold("Compatibility blockers")}`);
286891
287232
  for (const blocker2 of plan.compatibility.blockers) {
286892
287233
  const location = blocker2.table ? `${blocker2.table}${blocker2.field ? ` (${blocker2.field})` : ""}` : "Repository";
286893
- console.log(` ${import_picocolors18.default.bold(location)} ${import_picocolors18.default.yellow(renderStatus(blocker2.code))}`);
287234
+ console.log(` ${import_picocolors19.default.bold(location)} ${import_picocolors19.default.yellow(renderStatus(blocker2.code))}`);
286894
287235
  console.log(` ${blocker2.observed}`);
286895
- console.log(` ${import_picocolors18.default.dim(`Required: ${blocker2.expected}`)}`);
287236
+ console.log(` ${import_picocolors19.default.dim(`Required: ${blocker2.expected}`)}`);
286896
287237
  for (const remediation of blocker2.remediations) {
286897
- console.log(` ${import_picocolors18.default.dim(`${renderStatus(remediation.kind)} \u2014 ${remediation.summary}`)}`);
287238
+ console.log(` ${import_picocolors19.default.dim(`${renderStatus(remediation.kind)} \u2014 ${remediation.summary}`)}`);
286898
287239
  }
286899
287240
  }
286900
287241
  }
286901
287242
  if (plan.compatibility.mappings.length > 0) {
286902
287243
  console.log(`
286903
- ${import_picocolors18.default.bold("Database mappings")}`);
287244
+ ${import_picocolors19.default.bold("Database mappings")}`);
286904
287245
  for (const mapping of plan.compatibility.mappings) {
286905
287246
  const target = mapping.column === null ? "disabled" : `${mapping.column} \xB7 ${mapping.databaseType ?? "unmapped"}`;
286906
- const status2 = mapping.status === "ready" ? import_picocolors18.default.green("ready") : import_picocolors18.default.yellow("review");
287247
+ const status2 = mapping.status === "ready" ? import_picocolors19.default.green("ready") : import_picocolors19.default.yellow("review");
286907
287248
  console.log(` ${`${mapping.table}.${mapping.field}`.padEnd(34)} ${target} \xB7 ${status2}`);
286908
- if (mapping.status === "review_required") console.log(` ${import_picocolors18.default.dim(mapping.reason)}`);
287249
+ if (mapping.status === "review_required") console.log(` ${import_picocolors19.default.dim(mapping.reason)}`);
286909
287250
  }
286910
287251
  }
286911
287252
  console.log(`
286912
- ${import_picocolors18.default.bold("Evidence")}`);
287253
+ ${import_picocolors19.default.bold("Evidence")}`);
286913
287254
  for (const item of plan.facts) {
286914
287255
  console.log(` ${item.key.padEnd(34)} ${renderValue(item.value)}`);
286915
287256
  }
286916
287257
  console.log(`
286917
- ${import_picocolors18.default.bold("Decisions")}`);
287258
+ ${import_picocolors19.default.bold("Decisions")}`);
286918
287259
  for (const decision of plan.decisions) {
286919
- const marker = decision.status === "resolved" ? import_picocolors18.default.green("\u2713") : import_picocolors18.default.yellow("?");
287260
+ const marker = decision.status === "resolved" ? import_picocolors19.default.green("\u2713") : import_picocolors19.default.yellow("?");
286920
287261
  console.log(` ${marker} ${decision.question}`);
286921
- console.log(` ${import_picocolors18.default.dim(decision.reason)}`);
287262
+ console.log(` ${import_picocolors19.default.dim(decision.reason)}`);
286922
287263
  }
286923
287264
  console.log(`
286924
- ${import_picocolors18.default.bold("Actions")}`);
287265
+ ${import_picocolors19.default.bold("Actions")}`);
286925
287266
  for (const action of plan.actions) {
286926
- const marker = action.status === "blocked" ? import_picocolors18.default.yellow("blocked") : import_picocolors18.default.green(action.status);
286927
- console.log(` ${marker.padEnd(18)} ${action.summary} ${import_picocolors18.default.dim(`[${action.executor}]`)}`);
287267
+ const marker = action.status === "blocked" ? import_picocolors19.default.yellow("blocked") : import_picocolors19.default.green(action.status);
287268
+ console.log(` ${marker.padEnd(18)} ${action.summary} ${import_picocolors19.default.dim(`[${action.executor}]`)}`);
286928
287269
  if (action.blockedBy.length > 0) {
286929
- console.log(` ${import_picocolors18.default.dim(`needs ${action.blockedBy.join(", ")}`)}`);
287270
+ console.log(` ${import_picocolors19.default.dim(`needs ${action.blockedBy.join(", ")}`)}`);
286930
287271
  }
286931
287272
  }
286932
287273
  console.log(`
286933
- ${import_picocolors18.default.bold("Result")} ${import_picocolors18.default.yellow(plan.outcome)}`);
287274
+ ${import_picocolors19.default.bold("Result")} ${import_picocolors19.default.yellow(plan.outcome)}`);
286934
287275
  console.log(` ${plan.summary}`);
286935
- console.log(import_picocolors18.default.dim(" Machine-readable: npx ablo setup --plan --json"));
287276
+ console.log(import_picocolors19.default.dim(" Machine-readable: npx ablo setup --plan --json"));
286936
287277
  console.log();
286937
287278
  }
286938
287279
  async function runSetup(args) {
286939
287280
  const options = parseSetupArgs(args);
286940
287281
  if (options.json && !options.plan) {
286941
- throw new import_errors15.AbloValidationError(
287282
+ throw new import_errors16.AbloValidationError(
286942
287283
  "`--json` is a plan renderer. Use `ablo setup --plan --json`.",
286943
287284
  { code: "cli_invalid_arguments" }
286944
287285
  );
@@ -287117,6 +287458,28 @@ var COMMANDS = [
287117
287458
  ]
287118
287459
  }
287119
287460
  },
287461
+ {
287462
+ // Sits beside `docs` on purpose. An agent that just failed to find an
287463
+ // answer is already reading this block, and the command that reports the
287464
+ // gap is the next line down rather than somewhere it would have to know to
287465
+ // look. Discoverability IS the feature: a channel an agent never finds
287466
+ // collects nothing.
287467
+ name: "feedback",
287468
+ usage: FEEDBACK_USAGE,
287469
+ core: { group: "More", does: "Tell us what got in your way, so the next agent does not hit it" },
287470
+ full: {
287471
+ group: "Read the docs",
287472
+ rows: [
287473
+ // The kinds come from the taxonomy rather than being spelled out here:
287474
+ // a help screen listing four when the schema knows five is the drift
287475
+ // this registry exists to stop.
287476
+ { run: `feedback <${FEEDBACK_KINDS.join("|")}> "<one line>"`, does: "Report one wall you hit" },
287477
+ { run: 'feedback bug "..." --detail <text>', does: "Add what happened, at length (`-` reads stdin)" },
287478
+ { run: " [--command <name>] [--error-code <code>] [--from <agent>]" },
287479
+ { run: " [--yes] [--json]" }
287480
+ ]
287481
+ }
287482
+ },
287120
287483
  {
287121
287484
  name: "whoami",
287122
287485
  usage: WHOAMI_USAGE,
@@ -287257,15 +287620,15 @@ function fullRows(group) {
287257
287620
  }
287258
287621
 
287259
287622
  // src/index.ts
287260
- var import_errors24 = require("@abloatai/transaction/errors");
287623
+ var import_errors25 = require("@abloatai/transaction/errors");
287261
287624
  init_push();
287262
287625
 
287263
287626
  // src/generate.ts
287264
287627
  init_cjs_shims();
287265
- var import_errors16 = require("@abloatai/transaction/errors");
287628
+ var import_errors17 = require("@abloatai/transaction/errors");
287266
287629
  var import_fs8 = require("fs");
287267
287630
  var import_path6 = require("path");
287268
- var import_picocolors19 = __toESM(require_picocolors(), 1);
287631
+ var import_picocolors20 = __toESM(require_picocolors(), 1);
287269
287632
  var import_schema7 = require("@abloatai/transaction/schema");
287270
287633
  init_push();
287271
287634
  var DEFAULT_SCHEMA_PATH4 = "ablo/schema.ts";
@@ -287288,7 +287651,7 @@ function parseGenerateArgs(argv) {
287288
287651
  out = argv[++i] ?? out;
287289
287652
  break;
287290
287653
  default:
287291
- throw new import_errors16.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
287654
+ throw new import_errors17.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
287292
287655
  }
287293
287656
  }
287294
287657
  return { schemaPath, exportName, out };
@@ -287298,7 +287661,7 @@ async function generate(argv) {
287298
287661
  try {
287299
287662
  args = parseGenerateArgs(argv);
287300
287663
  } catch (err) {
287301
- console.error(import_picocolors19.default.red(` ${err instanceof Error ? err.message : String(err)}`));
287664
+ console.error(import_picocolors20.default.red(` ${err instanceof Error ? err.message : String(err)}`));
287302
287665
  process.exit(1);
287303
287666
  }
287304
287667
  let source;
@@ -287307,21 +287670,21 @@ async function generate(argv) {
287307
287670
  const schemaJson = JSON.parse((0, import_schema7.serializeSchema)(schema));
287308
287671
  source = (0, import_schema7.generateTypes)(schemaJson);
287309
287672
  } catch (err) {
287310
- console.error(import_picocolors19.default.red(` ${err instanceof Error ? err.message : String(err)}`));
287673
+ console.error(import_picocolors20.default.red(` ${err instanceof Error ? err.message : String(err)}`));
287311
287674
  process.exit(1);
287312
287675
  }
287313
287676
  const abs = (0, import_path6.resolve)(process.cwd(), args.out);
287314
287677
  (0, import_fs8.mkdirSync)((0, import_path6.dirname)(abs), { recursive: true });
287315
287678
  (0, import_fs8.writeFileSync)(abs, source);
287316
- console.log(` ${import_picocolors19.default.green("\u2713")} Generated types \u2192 ${import_picocolors19.default.bold(args.out)}`);
287679
+ console.log(` ${import_picocolors20.default.green("\u2713")} Generated types \u2192 ${import_picocolors20.default.bold(args.out)}`);
287317
287680
  }
287318
287681
 
287319
287682
  // src/login.ts
287320
287683
  init_cjs_shims();
287321
287684
  var import_child_process2 = require("child_process");
287322
- var import_picocolors20 = __toESM(require_picocolors(), 1);
287685
+ var import_picocolors21 = __toESM(require_picocolors(), 1);
287323
287686
  init_dist2();
287324
- var import_errors17 = require("@abloatai/transaction/errors");
287687
+ var import_errors18 = require("@abloatai/transaction/errors");
287325
287688
  var import_wire8 = require("@abloatai/transaction/wire");
287326
287689
  init_config();
287327
287690
  init_theme();
@@ -287383,9 +287746,9 @@ async function deviceLogin(argv, deps = {}) {
287383
287746
  const code = await codeRes.json();
287384
287747
  const approvePath = `/cli?user_code=${code.user_code}${targetOrg ? `&org=${encodeURIComponent(targetOrg)}` : ""}`;
287385
287748
  const url = account === "signup" ? `${DASHBOARD_URL}/signup?next=${encodeURIComponent(approvePath)}` : `${DASHBOARD_URL}${approvePath}`;
287386
- Me(`${import_picocolors20.default.bold(code.user_code)}
287749
+ Me(`${import_picocolors21.default.bold(code.user_code)}
287387
287750
 
287388
- ${import_picocolors20.default.dim(url)}`, "Approve in your browser");
287751
+ ${import_picocolors21.default.dim(url)}`, "Approve in your browser");
287389
287752
  openUrl(url);
287390
287753
  const s = Y2();
287391
287754
  s.start("Waiting for approval\u2026");
@@ -287455,7 +287818,7 @@ ${import_picocolors20.default.dim(url)}`, "Approve in your browser");
287455
287818
  }
287456
287819
  if (!provRes.ok) {
287457
287820
  s.stop("Could not provision a key.");
287458
- const err = (0, import_errors17.translateHttpError)(
287821
+ const err = (0, import_errors18.translateHttpError)(
287459
287822
  provRes.status,
287460
287823
  await provRes.json().catch(() => null),
287461
287824
  provRes.headers.get("x-request-id") ?? void 0
@@ -287463,11 +287826,11 @@ ${import_picocolors20.default.dim(url)}`, "Approve in your browser");
287463
287826
  M2.error(err.message);
287464
287827
  if (err.code === "entity_not_found" && targetProject) {
287465
287828
  M2.error(
287466
- `If that isn't the account you meant, run ${import_picocolors20.default.bold("npx ablo logout")} and sign in again. Otherwise create it with ${import_picocolors20.default.bold(`npx ablo projects create ${targetProject}`)}.`
287829
+ `If that isn't the account you meant, run ${import_picocolors21.default.bold("npx ablo logout")} and sign in again. Otherwise create it with ${import_picocolors21.default.bold(`npx ablo projects create ${targetProject}`)}.`
287467
287830
  );
287468
287831
  } else {
287469
287832
  M2.error(
287470
- `The browser approval succeeded but the credential handoff failed. Try ${import_picocolors20.default.bold("npx ablo login")} again.`
287833
+ `The browser approval succeeded but the credential handoff failed. Try ${import_picocolors21.default.bold("npx ablo login")} again.`
287471
287834
  );
287472
287835
  }
287473
287836
  process.exit(1);
@@ -287478,7 +287841,7 @@ ${import_picocolors20.default.dim(url)}`, "Approve in your browser");
287478
287841
  if (!parsedProv.success) {
287479
287842
  s.stop("Could not provision a key.");
287480
287843
  M2.error("The key handoff returned something this version does not recognize.");
287481
- M2.error(`Try again, or upgrade with ${import_picocolors20.default.bold("npm i -g @abloatai/ablo")}.`);
287844
+ M2.error(`Try again, or upgrade with ${import_picocolors21.default.bold("npm i -g @abloatai/ablo")}.`);
287482
287845
  process.exit(1);
287483
287846
  }
287484
287847
  const prov = parsedProv.data;
@@ -287490,7 +287853,7 @@ ${import_picocolors20.default.dim(url)}`, "Approve in your browser");
287490
287853
  });
287491
287854
  if (targetOrg && prov.organizationSlug && prov.organizationSlug !== targetOrg) {
287492
287855
  M2.warn(
287493
- `The approval chose ${import_picocolors20.default.bold(prov.organizationSlug)}, not ${import_picocolors20.default.bold(targetOrg)}. The credential is scoped to ${import_picocolors20.default.bold(prov.organizationSlug)}.`
287856
+ `The approval chose ${import_picocolors21.default.bold(prov.organizationSlug)}, not ${import_picocolors21.default.bold(targetOrg)}. The credential is scoped to ${import_picocolors21.default.bold(prov.organizationSlug)}.`
287494
287857
  );
287495
287858
  }
287496
287859
  const profileName = prov.project?.slug ?? DEFAULT_PROFILE;
@@ -287502,10 +287865,10 @@ ${import_picocolors20.default.dim(url)}`, "Approve in your browser");
287502
287865
  { mode: "sandbox", activeProject: prov.project ?? void 0 }
287503
287866
  );
287504
287867
  s.stop(`Saved project credential to ${path}`);
287505
- const orgLabel = prov.organizationSlug ? ` to ${import_picocolors20.default.bold(prov.organizationSlug)}` : "";
287506
- const where = prov.project ? ` ${import_picocolors20.default.dim(`(project ${prov.project.slug})`)}` : "";
287868
+ const orgLabel = prov.organizationSlug ? ` to ${import_picocolors21.default.bold(prov.organizationSlug)}` : "";
287869
+ const where = prov.project ? ` ${import_picocolors21.default.dim(`(project ${prov.project.slug})`)}` : "";
287507
287870
  Se(
287508
- `${import_picocolors20.default.green("\u2713")} Logged in${orgLabel}${where}. Run ${import_picocolors20.default.bold("npx ablo dev")} to create or resume your Git branch and start with an expiring runtime key.`
287871
+ `${import_picocolors21.default.green("\u2713")} Logged in${orgLabel}${where}. Run ${import_picocolors21.default.bold("npx ablo dev")} to create or resume your Git branch and start with an expiring runtime key.`
287509
287872
  );
287510
287873
  }
287511
287874
  async function login(argv = [], deps = {}) {
@@ -287514,14 +287877,14 @@ async function login(argv = [], deps = {}) {
287514
287877
  function logout() {
287515
287878
  const removed = clearCredential();
287516
287879
  if (removed) {
287517
- console.log(` ${import_picocolors20.default.green("\u2713")} Logged out ${import_picocolors20.default.dim(`(credentials removed from ${configDir()})`)}`);
287880
+ console.log(` ${import_picocolors21.default.green("\u2713")} Logged out ${import_picocolors21.default.dim(`(credentials removed from ${configDir()})`)}`);
287518
287881
  } else {
287519
- console.log(` ${import_picocolors20.default.dim("\u25CB")} Not logged in \u2014 nothing to remove.`);
287882
+ console.log(` ${import_picocolors21.default.dim("\u25CB")} Not logged in \u2014 nothing to remove.`);
287520
287883
  }
287521
287884
  if (process.env.ABLO_MANAGEMENT_KEY) {
287522
287885
  console.log(
287523
- import_picocolors20.default.dim(
287524
- ` Note: ${import_picocolors20.default.bold("ABLO_MANAGEMENT_KEY")} is still set in this shell and takes precedence.`
287886
+ import_picocolors21.default.dim(
287887
+ ` Note: ${import_picocolors21.default.bold("ABLO_MANAGEMENT_KEY")} is still set in this shell and takes precedence.`
287525
287888
  )
287526
287889
  );
287527
287890
  }
@@ -287532,7 +287895,7 @@ init_projects();
287532
287895
 
287533
287896
  // src/status.ts
287534
287897
  init_cjs_shims();
287535
- var import_picocolors21 = __toESM(require_picocolors(), 1);
287898
+ var import_picocolors22 = __toESM(require_picocolors(), 1);
287536
287899
  init_config();
287537
287900
  init_target();
287538
287901
  init_theme();
@@ -287542,9 +287905,9 @@ init_readiness();
287542
287905
  function expiryLabel(iso) {
287543
287906
  const ms = Date.parse(iso) - Date.now();
287544
287907
  if (Number.isNaN(ms)) return "";
287545
- if (ms <= 0) return import_picocolors21.default.red("expired");
287908
+ if (ms <= 0) return import_picocolors22.default.red("expired");
287546
287909
  const days = Math.floor(ms / (24 * 60 * 60 * 1e3));
287547
- return import_picocolors21.default.dim(days > 0 ? `expires in ${days}d` : "expires <1d");
287910
+ return import_picocolors22.default.dim(days > 0 ? `expires in ${days}d` : "expires <1d");
287548
287911
  }
287549
287912
  async function ping2(apiUrl3) {
287550
287913
  const ctrl = new AbortController();
@@ -287571,38 +287934,38 @@ function printTargetLines(target, localProject, storedOrganizationId, storedOrga
287571
287934
  const confirmed = target?.confirmed ?? null;
287572
287935
  const org = confirmed?.organizationId ?? storedOrganizationId;
287573
287936
  if (org) {
287574
- const suffix = confirmed?.organizationId ? "" : ` ${import_picocolors21.default.yellow("(unconfirmed)")}`;
287937
+ const suffix = confirmed?.organizationId ? "" : ` ${import_picocolors22.default.yellow("(unconfirmed)")}`;
287575
287938
  const slug = org === storedOrganizationId ? storedOrganizationSlug : void 0;
287576
- const label = slug ? `${import_picocolors21.default.bold(slug)} ${import_picocolors21.default.dim(`(${org})`)}` : import_picocolors21.default.dim(org);
287577
- console.log(` ${import_picocolors21.default.dim("org")} ${label}${suffix}`);
287939
+ const label = slug ? `${import_picocolors22.default.bold(slug)} ${import_picocolors22.default.dim(`(${org})`)}` : import_picocolors22.default.dim(org);
287940
+ console.log(` ${import_picocolors22.default.dim("org")} ${label}${suffix}`);
287578
287941
  } else {
287579
287942
  console.log(
287580
- ` ${import_picocolors21.default.dim("org")} ${import_picocolors21.default.yellow("unknown")} ${import_picocolors21.default.dim("(the server did not confirm one for this key)")}`
287943
+ ` ${import_picocolors22.default.dim("org")} ${import_picocolors22.default.yellow("unknown")} ${import_picocolors22.default.dim("(the server did not confirm one for this key)")}`
287581
287944
  );
287582
287945
  }
287583
287946
  let projectLine;
287584
287947
  if (confirmed?.project) {
287585
287948
  const p2 = confirmed.project;
287586
- projectLine = p2.isDefault ? `${import_picocolors21.default.bold("default")} ${import_picocolors21.default.dim("(org-default)")}` : `${import_picocolors21.default.bold(p2.slug)} ${import_picocolors21.default.dim(`(${p2.id})`)}`;
287949
+ projectLine = p2.isDefault ? `${import_picocolors22.default.bold("default")} ${import_picocolors22.default.dim("(org-default)")}` : `${import_picocolors22.default.bold(p2.slug)} ${import_picocolors22.default.dim(`(${p2.id})`)}`;
287587
287950
  } else if (confirmed) {
287588
- projectLine = `${import_picocolors21.default.bold("default")} ${import_picocolors21.default.dim("(org-default)")}`;
287951
+ projectLine = `${import_picocolors22.default.bold("default")} ${import_picocolors22.default.dim("(org-default)")}`;
287589
287952
  } else if (localProject) {
287590
- projectLine = `${import_picocolors21.default.bold(localProject.slug)} ${import_picocolors21.default.dim(`(${localProject.id})`)} ${import_picocolors21.default.yellow("(unconfirmed)")}`;
287953
+ projectLine = `${import_picocolors22.default.bold(localProject.slug)} ${import_picocolors22.default.dim(`(${localProject.id})`)} ${import_picocolors22.default.yellow("(unconfirmed)")}`;
287591
287954
  } else {
287592
- projectLine = `${import_picocolors21.default.bold("default")} ${target ? import_picocolors21.default.yellow("(unconfirmed)") : import_picocolors21.default.dim("(org-default)")}`;
287955
+ projectLine = `${import_picocolors22.default.bold("default")} ${target ? import_picocolors22.default.yellow("(unconfirmed)") : import_picocolors22.default.dim("(org-default)")}`;
287593
287956
  }
287594
- console.log(` ${import_picocolors21.default.dim("project")} ${projectLine}`);
287957
+ console.log(` ${import_picocolors22.default.dim("project")} ${projectLine}`);
287595
287958
  const branch = confirmed?.branchId ?? null;
287596
287959
  const env = confirmed?.environment ?? target?.keyEnv ?? null;
287597
287960
  if (branch) {
287598
287961
  const label = confirmed?.branchRoot ? "production root" : `branch ${branch}`;
287599
- console.log(` ${import_picocolors21.default.dim("acts on")} ${import_picocolors21.default.bold(label)}`);
287962
+ console.log(` ${import_picocolors22.default.dim("acts on")} ${import_picocolors22.default.bold(label)}`);
287600
287963
  } else if (env) {
287601
- const suffix = confirmed ? "" : ` ${import_picocolors21.default.yellow("(unconfirmed)")}`;
287602
- console.log(` ${import_picocolors21.default.dim("acts on")} ${import_picocolors21.default.bold(env)}${suffix}`);
287964
+ const suffix = confirmed ? "" : ` ${import_picocolors22.default.yellow("(unconfirmed)")}`;
287965
+ console.log(` ${import_picocolors22.default.dim("acts on")} ${import_picocolors22.default.bold(env)}${suffix}`);
287603
287966
  }
287604
287967
  const divergence = describeMismatches(target?.mismatches ?? []);
287605
- if (divergence) console.log(` ${import_picocolors21.default.yellow(`\u26A0 ${divergence}`)}`);
287968
+ if (divergence) console.log(` ${import_picocolors22.default.yellow(`\u26A0 ${divergence}`)}`);
287606
287969
  }
287607
287970
  async function status(args = []) {
287608
287971
  const apiUrl3 = apiBaseUrl();
@@ -287686,15 +288049,15 @@ async function status(args = []) {
287686
288049
  return;
287687
288050
  }
287688
288051
  console.log(`
287689
- ${brand("ablo")} ${import_picocolors21.default.dim("status")}
288052
+ ${brand("ablo")} ${import_picocolors22.default.dim("status")}
287690
288053
  `);
287691
288054
  if (runtimeKey.key && runtimeKey.source && runtimeKey.source !== "stored") {
287692
288055
  const label = runtimeKey.source === "env" ? "ABLO_API_KEY env" : runtimeKey.source;
287693
288056
  console.log(
287694
- ` ${import_picocolors21.default.dim("key")} ${runtimeKey.key.slice(0, 12)}\u2026 ${import_picocolors21.default.dim(`(${label} \u2014 overrides stored)`)}`
288057
+ ` ${import_picocolors22.default.dim("key")} ${runtimeKey.key.slice(0, 12)}\u2026 ${import_picocolors22.default.dim(`(${label} \u2014 overrides stored)`)}`
287695
288058
  );
287696
288059
  } else if (!cfg) {
287697
- console.log(` ${import_picocolors21.default.yellow("!")} Not logged in \u2014 run ${import_picocolors21.default.bold("ablo login")}.`);
288060
+ console.log(` ${import_picocolors22.default.yellow("!")} Not logged in \u2014 run ${import_picocolors22.default.bold("ablo login")}.`);
287698
288061
  }
287699
288062
  const activeEntry = getKeyEntry(mode);
287700
288063
  const activeProject = getActiveProject();
@@ -287706,9 +288069,9 @@ async function status(args = []) {
287706
288069
  );
287707
288070
  const management = getManagementKeyEntry();
287708
288071
  console.log(
287709
- ` ${import_picocolors21.default.dim("\u25CB")} ${"management".padEnd(12)} ${management ? import_picocolors21.default.dim(
288072
+ ` ${import_picocolors22.default.dim("\u25CB")} ${"management".padEnd(12)} ${management ? import_picocolors22.default.dim(
287710
288073
  `${management.apiKey.slice(0, 12)}\u2026${management.expiresAt ? ` \xB7 ${expiryLabel(management.expiresAt)}` : ""}`
287711
- ) : import_picocolors21.default.dim("\u2014 no key")}`
288074
+ ) : import_picocolors22.default.dim("\u2014 no key")}`
287712
288075
  );
287713
288076
  for (const { key: m2, label } of [
287714
288077
  { key: "sandbox", label: "legacy child" },
@@ -287720,21 +288083,21 @@ async function status(args = []) {
287720
288083
  credentialCapability(entry.apiKey).label,
287721
288084
  entry.expiresAt ? expiryLabel(entry.expiresAt) : ""
287722
288085
  ].filter(Boolean);
287723
- const trail = facts.length ? ` ${import_picocolors21.default.dim("\xB7")} ${facts.join(import_picocolors21.default.dim(" \xB7 "))}` : "";
288086
+ const trail = facts.length ? ` ${import_picocolors22.default.dim("\xB7")} ${facts.join(import_picocolors22.default.dim(" \xB7 "))}` : "";
287724
288087
  console.log(
287725
- ` ${import_picocolors21.default.dim("\u25CB")} ${label.padEnd(12)} ${import_picocolors21.default.dim(`${entry.apiKey.slice(0, 12)}\u2026`)}${trail}`
288088
+ ` ${import_picocolors22.default.dim("\u25CB")} ${label.padEnd(12)} ${import_picocolors22.default.dim(`${entry.apiKey.slice(0, 12)}\u2026`)}${trail}`
287726
288089
  );
287727
288090
  }
287728
288091
  }
287729
288092
  const pushBranch = target?.confirmed?.branchRoot === true ? "production root" : target?.confirmed?.branchId ? `branch ${target.confirmed.branchId}` : runtimeKey.key ? "unknown branch" : "no branch";
287730
288093
  console.log(
287731
- ` ${import_picocolors21.default.dim("push")} ${runtimeKey.key ? `${import_picocolors21.default.bold(pushBranch)} ${import_picocolors21.default.dim(`with ${runtimeKey.key.slice(0, 12)}\u2026 (${runtimeKey.source})`)}` : `${import_picocolors21.default.bold(pushBranch)} ${import_picocolors21.default.yellow("\u2014 no runtime key")} ${import_picocolors21.default.dim(`(set ${import_picocolors21.default.bold("ABLO_API_KEY")} or run ${import_picocolors21.default.bold("ablo dev")})`)}`}`
288094
+ ` ${import_picocolors22.default.dim("push")} ${runtimeKey.key ? `${import_picocolors22.default.bold(pushBranch)} ${import_picocolors22.default.dim(`with ${runtimeKey.key.slice(0, 12)}\u2026 (${runtimeKey.source})`)}` : `${import_picocolors22.default.bold(pushBranch)} ${import_picocolors22.default.yellow("\u2014 no runtime key")} ${import_picocolors22.default.dim(`(set ${import_picocolors22.default.bold("ABLO_API_KEY")} or run ${import_picocolors22.default.bold("ablo dev")})`)}`}`
287732
288095
  );
287733
288096
  const capability = credentialCapability(runtimeKey.key);
287734
- if (capability.note) console.log(` ${import_picocolors21.default.dim(capability.note)}`);
287735
- process.stdout.write(` ${import_picocolors21.default.dim("api")} ${apiUrl3} `);
288097
+ if (capability.note) console.log(` ${import_picocolors22.default.dim(capability.note)}`);
288098
+ process.stdout.write(` ${import_picocolors22.default.dim("api")} ${apiUrl3} `);
287736
288099
  const reachable = await ping2(apiUrl3);
287737
- console.log(reachable ? import_picocolors21.default.green("reachable") : import_picocolors21.default.red("unreachable"));
288100
+ console.log(reachable ? import_picocolors22.default.green("reachable") : import_picocolors22.default.red("unreachable"));
287738
288101
  const introspectKey = runtimeKey.key;
287739
288102
  const { source: dataSource, validation } = reachable ? await fetchRoutingState(apiUrl3, introspectKey) : { source: { kind: "unknown", detail: "unreachable" }, validation: null };
287740
288103
  if (dataSource.kind === "connected") {
@@ -287742,65 +288105,65 @@ async function status(args = []) {
287742
288105
  const pooled = detectPoolerIn(dataSource.hosts);
287743
288106
  const unreachable = validation && !validation.ok ? validation.message : void 0;
287744
288107
  console.log(
287745
- ` ${import_picocolors21.default.dim("data")} ${import_picocolors21.default.green("\u2713")} ${import_picocolors21.default.dim(`database connected to this plane (${how})`)}`
288108
+ ` ${import_picocolors22.default.dim("data")} ${import_picocolors22.default.green("\u2713")} ${import_picocolors22.default.dim(`database connected to this plane (${how})`)}`
287746
288109
  );
287747
288110
  if (pooled) {
287748
288111
  console.log(
287749
- ` ${import_picocolors21.default.yellow("\u26A0")} ${import_picocolors21.default.dim(
288112
+ ` ${import_picocolors22.default.yellow("\u26A0")} ${import_picocolors22.default.dim(
287750
288113
  `${pooled.host} is a connection pooler` + (pooled.direct ? `; register the direct host instead: ${pooled.direct}` : "; register the direct host instead")
287751
288114
  )}`
287752
288115
  );
287753
288116
  }
287754
288117
  if (unreachable) {
287755
- console.log(` ${import_picocolors21.default.red("\u2717")} ${import_picocolors21.default.dim(`Ablo could not reach it \u2014 ${unreachable}`)}`);
288118
+ console.log(` ${import_picocolors22.default.red("\u2717")} ${import_picocolors22.default.dim(`Ablo could not reach it \u2014 ${unreachable}`)}`);
287756
288119
  }
287757
288120
  if (validation?.ok && validation.initialSnapshot?.status === "loading") {
287758
288121
  console.log(
287759
- ` ${import_picocolors21.default.yellow("\u25CC")} ${import_picocolors21.default.dim(
287760
- `loading rows that predate the connection \u2014 automatic; check with ${import_picocolors21.default.bold("ablo connect check")}`
288122
+ ` ${import_picocolors22.default.yellow("\u25CC")} ${import_picocolors22.default.dim(
288123
+ `loading rows that predate the connection \u2014 automatic; check with ${import_picocolors22.default.bold("ablo connect check")}`
287761
288124
  )}`
287762
288125
  );
287763
288126
  } else if (validation?.ok && validation.initialSnapshot?.status === "retrying") {
287764
288127
  console.log(
287765
- ` ${import_picocolors21.default.red("\u2717")} ${import_picocolors21.default.dim(
288128
+ ` ${import_picocolors22.default.red("\u2717")} ${import_picocolors22.default.dim(
287766
288129
  `loading existing rows is retrying${validation.initialSnapshot.detail ? ` \u2014 ${validation.initialSnapshot.detail}` : ""}`
287767
288130
  )}`
287768
288131
  );
287769
288132
  }
287770
288133
  } else if (dataSource.kind === "none") {
287771
288134
  console.log(
287772
- ` ${import_picocolors21.default.dim("data")} ${import_picocolors21.default.red("\u2717 this branch is not connected to a database")} ${import_picocolors21.default.dim("\u2014 writes are held")}`
288135
+ ` ${import_picocolors22.default.dim("data")} ${import_picocolors22.default.red("\u2717 this branch is not connected to a database")} ${import_picocolors22.default.dim("\u2014 writes are held")}`
287773
288136
  );
287774
288137
  } else if (reachable) {
287775
288138
  console.log(
287776
- ` ${import_picocolors21.default.dim("data")} ${import_picocolors21.default.yellow("?")} ${import_picocolors21.default.dim(`could not read this branch's database connection (${dataSource.detail})`)}`
288139
+ ` ${import_picocolors22.default.dim("data")} ${import_picocolors22.default.yellow("?")} ${import_picocolors22.default.dim(`could not read this branch's database connection (${dataSource.detail})`)}`
287777
288140
  );
287778
288141
  }
287779
288142
  const pushed = reachable ? await fetchPushedSchema(apiUrl3, introspectKey) : null;
287780
288143
  if (reachable) {
287781
288144
  if (pushed?.active) {
287782
- const when = pushed.pushedAt ? ` ${import_picocolors21.default.dim(`@ ${pushed.pushedAt.slice(0, 10)}`)}` : "";
287783
- const ver = pushed.version != null ? ` ${import_picocolors21.default.dim(`(rev ${pushed.version})`)}` : "";
287784
- const hashLabel = pushed.hash ? ` ${import_picocolors21.default.dim(`hash ${pushed.hash}`)}` : "";
288145
+ const when = pushed.pushedAt ? ` ${import_picocolors22.default.dim(`@ ${pushed.pushedAt.slice(0, 10)}`)}` : "";
288146
+ const ver = pushed.version != null ? ` ${import_picocolors22.default.dim(`(rev ${pushed.version})`)}` : "";
288147
+ const hashLabel = pushed.hash ? ` ${import_picocolors22.default.dim(`hash ${pushed.hash}`)}` : "";
287785
288148
  console.log(
287786
- ` ${import_picocolors21.default.dim("schema")} ${import_picocolors21.default.bold(`${pushed.models.length} models pushed`)}${ver}${hashLabel}${when}`
288149
+ ` ${import_picocolors22.default.dim("schema")} ${import_picocolors22.default.bold(`${pushed.models.length} models pushed`)}${ver}${hashLabel}${when}`
287787
288150
  );
287788
288151
  for (const m2 of pushed.models) {
287789
- const tn = m2.typename === m2.key ? import_picocolors21.default.dim(`typename=${m2.typename}`) : import_picocolors21.default.yellow(`typename=${m2.typename}`);
288152
+ const tn = m2.typename === m2.key ? import_picocolors22.default.dim(`typename=${m2.typename}`) : import_picocolors22.default.yellow(`typename=${m2.typename}`);
287790
288153
  const conflict = formatConflict(m2.conflict);
287791
- const conflictStr2 = conflict ? ` ${import_picocolors21.default.dim(`conflict=${conflict}`)}` : "";
287792
- console.log(` ${import_picocolors21.default.dim("\u2022")} ${m2.key.padEnd(14)} ${tn}${conflictStr2}`);
288154
+ const conflictStr2 = conflict ? ` ${import_picocolors22.default.dim(`conflict=${conflict}`)}` : "";
288155
+ console.log(` ${import_picocolors22.default.dim("\u2022")} ${m2.key.padEnd(14)} ${tn}${conflictStr2}`);
287793
288156
  }
287794
288157
  } else if (pushed && !pushed.active) {
287795
288158
  console.log(
287796
- ` ${import_picocolors21.default.dim("schema")} ${import_picocolors21.default.yellow("none pushed")} ${import_picocolors21.default.dim(`(run ${import_picocolors21.default.bold("ablo push")} or ${import_picocolors21.default.bold("ablo dev")})`)}`
288159
+ ` ${import_picocolors22.default.dim("schema")} ${import_picocolors22.default.yellow("none pushed")} ${import_picocolors22.default.dim(`(run ${import_picocolors22.default.bold("ablo push")} or ${import_picocolors22.default.bold("ablo dev")})`)}`
287797
288160
  );
287798
288161
  }
287799
288162
  }
287800
288163
  const drift = schemaDrift(await readLocalSchemaHash(), pushed?.hash);
287801
288164
  if (drift) {
287802
288165
  console.log(
287803
- ` ${import_picocolors21.default.dim("drift")} ${import_picocolors21.default.red("\u2717 local schema differs from the server")} ` + import_picocolors21.default.dim(`(local ${drift.local}, server ${drift.server})`)
288166
+ ` ${import_picocolors22.default.dim("drift")} ${import_picocolors22.default.red("\u2717 local schema differs from the server")} ` + import_picocolors22.default.dim(`(local ${drift.local}, server ${drift.server})`)
287804
288167
  );
287805
288168
  }
287806
288169
  const found = blockers({
@@ -287812,18 +288175,18 @@ async function status(args = []) {
287812
288175
  });
287813
288176
  console.log();
287814
288177
  if (found.length > 0) {
287815
- console.log(` ${import_picocolors21.default.red("\u2717")} ${import_picocolors21.default.bold("writes would fail right now")}`);
288178
+ console.log(` ${import_picocolors22.default.red("\u2717")} ${import_picocolors22.default.bold("writes would fail right now")}`);
287816
288179
  for (const b4 of found) {
287817
- console.log(` ${import_picocolors21.default.dim("\xB7")} ${b4.problem}`);
287818
- console.log(` ${import_picocolors21.default.dim(b4.fix)}`);
288180
+ console.log(` ${import_picocolors22.default.dim("\xB7")} ${b4.problem}`);
288181
+ console.log(` ${import_picocolors22.default.dim(b4.fix)}`);
287819
288182
  }
287820
288183
  } else if (dataSource.kind === "unknown") {
287821
288184
  console.log(
287822
- ` ${import_picocolors21.default.yellow("?")} ${import_picocolors21.default.dim("nothing is blocking a write, but this key could not read the branch's database connection \u2014 some checks were skipped")}`
288185
+ ` ${import_picocolors22.default.yellow("?")} ${import_picocolors22.default.dim("nothing is blocking a write, but this key could not read the branch's database connection \u2014 some checks were skipped")}`
287823
288186
  );
287824
288187
  } else {
287825
288188
  console.log(
287826
- ` ${import_picocolors21.default.green("\u2713")} ${import_picocolors21.default.dim("write infrastructure is ready \u2014 database constraints and row-level policies still apply")}`
288189
+ ` ${import_picocolors22.default.green("\u2713")} ${import_picocolors22.default.dim(WRITE_READY_VERDICT)}`
287827
288190
  );
287828
288191
  }
287829
288192
  console.log();
@@ -287831,9 +288194,9 @@ async function status(args = []) {
287831
288194
 
287832
288195
  // src/logs.ts
287833
288196
  init_cjs_shims();
287834
- var import_errors18 = require("@abloatai/transaction/errors");
288197
+ var import_errors19 = require("@abloatai/transaction/errors");
287835
288198
  var import_wire9 = require("@abloatai/transaction/wire");
287836
- var import_picocolors22 = __toESM(require_picocolors(), 1);
288199
+ var import_picocolors23 = __toESM(require_picocolors(), 1);
287837
288200
  init_config();
287838
288201
  init_theme();
287839
288202
  init_controlPlane();
@@ -287873,12 +288236,12 @@ function parseLogsArgs(argv) {
287873
288236
  args.json = true;
287874
288237
  break;
287875
288238
  case "--mode":
287876
- throw new import_errors18.AbloValidationError(
288239
+ throw new import_errors19.AbloValidationError(
287877
288240
  "--mode was removed. Logs follow the branch bound to ABLO_API_KEY; select a different branch by supplying its key.",
287878
288241
  { code: "cli_invalid_arguments" }
287879
288242
  );
287880
288243
  default:
287881
- throw new import_errors18.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
288244
+ throw new import_errors19.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
287882
288245
  }
287883
288246
  }
287884
288247
  return args;
@@ -287897,10 +288260,10 @@ function resolveSince(since) {
287897
288260
  var sleep2 = (ms) => new Promise((r2) => setTimeout(r2, ms));
287898
288261
  function colorOp(op) {
287899
288262
  const label = op.padEnd(6);
287900
- if (op === "create") return import_picocolors22.default.green(label);
287901
- if (op === "update") return import_picocolors22.default.yellow(label);
287902
- if (op === "delete") return import_picocolors22.default.red(label);
287903
- return import_picocolors22.default.dim(label);
288263
+ if (op === "create") return import_picocolors23.default.green(label);
288264
+ if (op === "update") return import_picocolors23.default.yellow(label);
288265
+ if (op === "delete") return import_picocolors23.default.red(label);
288266
+ return import_picocolors23.default.dim(label);
287904
288267
  }
287905
288268
  function render2(e2, json) {
287906
288269
  if (json) {
@@ -287909,21 +288272,21 @@ function render2(e2, json) {
287909
288272
  return;
287910
288273
  }
287911
288274
  const t = new Date(e2.at).toLocaleTimeString();
287912
- const actor = e2.actor ? import_picocolors22.default.dim(` ${e2.actor}`) : "";
287913
- console.log(` ${import_picocolors22.default.dim(t)} ${colorOp(e2.op)} ${import_picocolors22.default.bold(e2.model)} ${import_picocolors22.default.dim(e2.recordId)}${actor}`);
288275
+ const actor = e2.actor ? import_picocolors23.default.dim(` ${e2.actor}`) : "";
288276
+ console.log(` ${import_picocolors23.default.dim(t)} ${colorOp(e2.op)} ${import_picocolors23.default.bold(e2.model)} ${import_picocolors23.default.dim(e2.recordId)}${actor}`);
287914
288277
  }
287915
288278
  async function logs(argv) {
287916
288279
  let args;
287917
288280
  try {
287918
288281
  args = parseLogsArgs(argv);
287919
288282
  } catch (err) {
287920
- console.error(import_picocolors22.default.red(` ${err instanceof Error ? err.message : String(err)}`));
288283
+ console.error(import_picocolors23.default.red(` ${err instanceof Error ? err.message : String(err)}`));
287921
288284
  process.exit(1);
287922
288285
  }
287923
288286
  const apiKey = resolveRuntimeApiKey().key;
287924
288287
  if (!apiKey) {
287925
288288
  console.error(
287926
- import_picocolors22.default.red(` No API key.`) + import_picocolors22.default.dim(` Run ${import_picocolors22.default.bold("ablo login")} or set ${import_picocolors22.default.bold("ABLO_API_KEY")}.`)
288289
+ import_picocolors23.default.red(` No API key.`) + import_picocolors23.default.dim(` Run ${import_picocolors23.default.bold("ablo login")} or set ${import_picocolors23.default.bold("ABLO_API_KEY")}.`)
287927
288290
  );
287928
288291
  process.exit(1);
287929
288292
  }
@@ -287937,7 +288300,7 @@ async function logs(argv) {
287937
288300
  if (!res) return null;
287938
288301
  if (!res.ok) {
287939
288302
  const body = await res.json().catch(() => ({}));
287940
- console.error(import_picocolors22.default.red(` logs failed (${res.status}): ${body.reason ?? body.message ?? ""}`));
288303
+ console.error(import_picocolors23.default.red(` logs failed (${res.status}): ${body.reason ?? body.message ?? ""}`));
287941
288304
  process.exit(1);
287942
288305
  }
287943
288306
  const json = await res.json();
@@ -287948,7 +288311,7 @@ async function logs(argv) {
287948
288311
  }
287949
288312
  if (!args.json) {
287950
288313
  console.log(`
287951
- ${brand("ablo")} ${import_picocolors22.default.dim("logs")}
288314
+ ${brand("ablo")} ${import_picocolors23.default.dim("logs")}
287952
288315
  `);
287953
288316
  }
287954
288317
  const initial = await fetchPage({
@@ -287958,13 +288321,13 @@ async function logs(argv) {
287958
288321
  ...args.op ? { op: args.op } : {}
287959
288322
  });
287960
288323
  if (!initial) {
287961
- console.error(import_picocolors22.default.red(` Couldn't reach ${baseUrl2}.`));
288324
+ console.error(import_picocolors23.default.red(` Couldn't reach ${baseUrl2}.`));
287962
288325
  process.exit(1);
287963
288326
  }
287964
288327
  for (const e2 of initial.events) render2(e2, args.json);
287965
288328
  let cursor = initial.cursor;
287966
288329
  if (!args.follow) return;
287967
- if (!args.json) console.log(` ${import_picocolors22.default.dim("watching for new activity \u2026 (Ctrl-C to stop)")}
288330
+ if (!args.json) console.log(` ${import_picocolors23.default.dim("watching for new activity \u2026 (Ctrl-C to stop)")}
287968
288331
  `);
287969
288332
  for (; ; ) {
287970
288333
  await sleep2(1500);
@@ -287984,7 +288347,7 @@ async function logs(argv) {
287984
288347
  // src/webhooks.ts
287985
288348
  init_cjs_shims();
287986
288349
  var import_fs9 = require("fs");
287987
- var import_picocolors23 = __toESM(require_picocolors(), 1);
288350
+ var import_picocolors24 = __toESM(require_picocolors(), 1);
287988
288351
  var import_credentialPolicy4 = require("@abloatai/transaction/auth/credentialPolicy");
287989
288352
  init_config();
287990
288353
  init_theme();
@@ -288017,12 +288380,12 @@ function requireKey3(mode) {
288017
288380
  const apiKey = resolveMutationApiKey(mode);
288018
288381
  if (!apiKey) {
288019
288382
  console.error(
288020
- import_picocolors23.default.red(" No API key.") + import_picocolors23.default.dim(` Run ${import_picocolors23.default.bold("ablo login")} or set ${import_picocolors23.default.bold("ABLO_API_KEY")}.`)
288383
+ import_picocolors24.default.red(" No API key.") + import_picocolors24.default.dim(` Run ${import_picocolors24.default.bold("ablo login")} or set ${import_picocolors24.default.bold("ABLO_API_KEY")}.`)
288021
288384
  );
288022
288385
  process.exit(1);
288023
288386
  }
288024
288387
  if ((0, import_credentialPolicy4.classifyCredentialKind)(apiKey) !== "secret") {
288025
- console.error(import_picocolors23.default.red(" Managing webhooks requires a branch-bound secret key ") + import_picocolors23.default.dim("(sk_)."));
288388
+ console.error(import_picocolors24.default.red(" Managing webhooks requires a branch-bound secret key ") + import_picocolors24.default.dim("(sk_)."));
288026
288389
  process.exit(1);
288027
288390
  }
288028
288391
  return apiKey;
@@ -288038,12 +288401,12 @@ async function api(apiKey, method, path, body) {
288038
288401
  ...body ? { body: JSON.stringify(body) } : {}
288039
288402
  }).catch(() => null);
288040
288403
  if (!res) {
288041
- console.error(import_picocolors23.default.red(` Couldn't reach ${baseUrl()}.`));
288404
+ console.error(import_picocolors24.default.red(` Couldn't reach ${baseUrl()}.`));
288042
288405
  process.exit(1);
288043
288406
  }
288044
288407
  if (!res.ok) {
288045
288408
  const err = await res.json().catch(() => ({}));
288046
- console.error(import_picocolors23.default.red(` Request failed (${res.status}): ${err.message ?? err.reason ?? ""}`));
288409
+ console.error(import_picocolors24.default.red(` Request failed (${res.status}): ${err.message ?? err.reason ?? ""}`));
288047
288410
  process.exit(1);
288048
288411
  }
288049
288412
  return await res.json();
@@ -288065,11 +288428,11 @@ ${line}
288065
288428
  return file;
288066
288429
  }
288067
288430
  function printEndpoint(e2) {
288068
- const dot = e2.status === "enabled" ? import_picocolors23.default.green("\u25CF") : import_picocolors23.default.red("\u25CF");
288069
- const health = e2.last_error ? import_picocolors23.default.red(` last error: ${e2.last_error}`) : "";
288070
- console.log(` ${dot} ${import_picocolors23.default.bold(e2.id)} ${e2.url}`);
288431
+ const dot = e2.status === "enabled" ? import_picocolors24.default.green("\u25CF") : import_picocolors24.default.red("\u25CF");
288432
+ const health = e2.last_error ? import_picocolors24.default.red(` last error: ${e2.last_error}`) : "";
288433
+ console.log(` ${dot} ${import_picocolors24.default.bold(e2.id)} ${e2.url}`);
288071
288434
  console.log(
288072
- import_picocolors23.default.dim(
288435
+ import_picocolors24.default.dim(
288073
288436
  ` ${e2.status} \xB7 ${e2.environment} \xB7 events ${e2.enabled_events.join(",")} \xB7 cursor ${e2.cursor ?? "\u2014"}${health}`
288074
288437
  )
288075
288438
  );
@@ -288081,7 +288444,7 @@ async function webhooks(argv) {
288081
288444
  if (sub === "create") {
288082
288445
  const url = positional(rest);
288083
288446
  if (!url) {
288084
- console.error(import_picocolors23.default.red(" Usage: ") + brand("ablo webhooks create <url>"));
288447
+ console.error(import_picocolors24.default.red(" Usage: ") + brand("ablo webhooks create <url>"));
288085
288448
  process.exit(1);
288086
288449
  }
288087
288450
  const apiKey = requireKey3(mode);
@@ -288093,8 +288456,8 @@ async function webhooks(argv) {
288093
288456
  });
288094
288457
  const file = writeSecretToEnv(created.secret);
288095
288458
  console.log(`
288096
- ${import_picocolors23.default.green("\u2713")} Registered ${import_picocolors23.default.bold(created.id)} \u2192 ${created.url}`);
288097
- console.log(` ${import_picocolors23.default.green("\u2713")} Wrote ${import_picocolors23.default.bold(ENV_KEY)} to ${import_picocolors23.default.bold(file)} ${import_picocolors23.default.dim("(shown once)")}
288459
+ ${import_picocolors24.default.green("\u2713")} Registered ${import_picocolors24.default.bold(created.id)} \u2192 ${created.url}`);
288460
+ console.log(` ${import_picocolors24.default.green("\u2713")} Wrote ${import_picocolors24.default.bold(ENV_KEY)} to ${import_picocolors24.default.bold(file)} ${import_picocolors24.default.dim("(shown once)")}
288098
288461
  `);
288099
288462
  return;
288100
288463
  }
@@ -288102,7 +288465,7 @@ async function webhooks(argv) {
288102
288465
  const apiKey = requireKey3(mode);
288103
288466
  const { data } = await api(apiKey, "GET", "");
288104
288467
  if (data.length === 0) {
288105
- console.log(import_picocolors23.default.dim(" No webhook endpoints. ") + brand("ablo webhooks create <url>"));
288468
+ console.log(import_picocolors24.default.dim(" No webhook endpoints. ") + brand("ablo webhooks create <url>"));
288106
288469
  return;
288107
288470
  }
288108
288471
  console.log();
@@ -288113,40 +288476,40 @@ async function webhooks(argv) {
288113
288476
  if (sub === "roll") {
288114
288477
  const id = positional(rest);
288115
288478
  if (!id) {
288116
- console.error(import_picocolors23.default.red(" Usage: ") + brand("ablo webhooks roll <id>"));
288479
+ console.error(import_picocolors24.default.red(" Usage: ") + brand("ablo webhooks roll <id>"));
288117
288480
  process.exit(1);
288118
288481
  }
288119
288482
  const apiKey = requireKey3(mode);
288120
288483
  const rolled = await api(apiKey, "POST", `/${id}/roll_secret`);
288121
288484
  const file = writeSecretToEnv(rolled.secret);
288122
288485
  console.log(`
288123
- ${import_picocolors23.default.green("\u2713")} Rolled secret for ${import_picocolors23.default.bold(id)} \u2192 ${import_picocolors23.default.bold(file)} ${import_picocolors23.default.dim("(old secret now invalid)")}
288486
+ ${import_picocolors24.default.green("\u2713")} Rolled secret for ${import_picocolors24.default.bold(id)} \u2192 ${import_picocolors24.default.bold(file)} ${import_picocolors24.default.dim("(old secret now invalid)")}
288124
288487
  `);
288125
288488
  return;
288126
288489
  }
288127
288490
  if (sub === "enable") {
288128
288491
  const id = positional(rest);
288129
288492
  if (!id) {
288130
- console.error(import_picocolors23.default.red(" Usage: ") + brand("ablo webhooks enable <id>"));
288493
+ console.error(import_picocolors24.default.red(" Usage: ") + brand("ablo webhooks enable <id>"));
288131
288494
  process.exit(1);
288132
288495
  }
288133
288496
  const apiKey = requireKey3(mode);
288134
288497
  const e2 = await api(apiKey, "POST", `/${id}/enable`);
288135
- console.log(` ${import_picocolors23.default.green("\u2713")} Re-enabled ${import_picocolors23.default.bold(e2.id)}`);
288498
+ console.log(` ${import_picocolors24.default.green("\u2713")} Re-enabled ${import_picocolors24.default.bold(e2.id)}`);
288136
288499
  return;
288137
288500
  }
288138
288501
  if (sub === "rm" || sub === "delete") {
288139
288502
  const id = positional(rest);
288140
288503
  if (!id) {
288141
- console.error(import_picocolors23.default.red(" Usage: ") + brand("ablo webhooks rm <id>"));
288504
+ console.error(import_picocolors24.default.red(" Usage: ") + brand("ablo webhooks rm <id>"));
288142
288505
  process.exit(1);
288143
288506
  }
288144
288507
  const apiKey = requireKey3(mode);
288145
288508
  await api(apiKey, "DELETE", `/${id}`);
288146
- console.log(` ${import_picocolors23.default.green("\u2713")} Removed ${import_picocolors23.default.bold(id)}`);
288509
+ console.log(` ${import_picocolors24.default.green("\u2713")} Removed ${import_picocolors24.default.bold(id)}`);
288147
288510
  return;
288148
288511
  }
288149
- console.log(` ${import_picocolors23.default.bold("Usage:")}`);
288512
+ console.log(` ${import_picocolors24.default.bold("Usage:")}`);
288150
288513
  console.log(` ${brand("ablo webhooks create <url>")} Register an endpoint; writes ${ENV_KEY}`);
288151
288514
  console.log(` ${brand("ablo webhooks list")} List endpoints + delivery health`);
288152
288515
  console.log(` ${brand("ablo webhooks roll <id>")} Mint a fresh signing secret`);
@@ -288157,8 +288520,8 @@ async function webhooks(argv) {
288157
288520
 
288158
288521
  // src/check.ts
288159
288522
  init_cjs_shims();
288160
- var import_errors19 = require("@abloatai/transaction/errors");
288161
- var import_picocolors24 = __toESM(require_picocolors(), 1);
288523
+ var import_errors20 = require("@abloatai/transaction/errors");
288524
+ var import_picocolors25 = __toESM(require_picocolors(), 1);
288162
288525
  init_src();
288163
288526
  var import_schema9 = require("@abloatai/transaction/schema");
288164
288527
  init_push();
@@ -288305,11 +288668,29 @@ function parseCheckArgs(argv) {
288305
288668
  appSchema = argv[++i] ?? appSchema;
288306
288669
  break;
288307
288670
  default:
288308
- throw new import_errors19.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
288671
+ throw new import_errors20.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
288309
288672
  }
288310
288673
  }
288311
288674
  return { schemaPath, exportName, appSchema };
288312
288675
  }
288676
+ function quoteIdent2(raw) {
288677
+ return `"${raw.replace(/"/g, '""')}"`;
288678
+ }
288679
+ var UNSTAMPED_CAP = 500;
288680
+ async function countUnstamped(sql, appSchema, table, column) {
288681
+ try {
288682
+ const rows = await sql.unsafe(
288683
+ `SELECT count(*)::int AS n FROM (
288684
+ SELECT 1 FROM ${quoteIdent2(appSchema)}.${quoteIdent2(table)}
288685
+ WHERE ${quoteIdent2(column)} IS NULL
288686
+ LIMIT ${UNSTAMPED_CAP + 1}
288687
+ ) s`
288688
+ );
288689
+ return rows[0]?.n ?? 0;
288690
+ } catch {
288691
+ return null;
288692
+ }
288693
+ }
288313
288694
  function hostOf(connectionString) {
288314
288695
  try {
288315
288696
  return new URL(connectionString).hostname || null;
@@ -288319,22 +288700,22 @@ function hostOf(connectionString) {
288319
288700
  }
288320
288701
  async function reportReadSubject(dbUrl) {
288321
288702
  const host = hostOf(dbUrl);
288322
- console.log(` ${import_picocolors24.default.dim("reading")} ${import_picocolors24.default.bold(host ?? "your database")}`);
288703
+ console.log(` ${import_picocolors25.default.dim("reading")} ${import_picocolors25.default.bold(host ?? "your database")}`);
288323
288704
  const runtimeKey = resolveRuntimeApiKey();
288324
288705
  const state = await fetchDataSourceState(apiBaseUrl(), runtimeKey.key);
288325
288706
  if (state.kind === "unknown") {
288326
288707
  console.log(
288327
- ` ${import_picocolors24.default.dim("ablo")} ${import_picocolors24.default.yellow("?")} ${import_picocolors24.default.dim(`couldn't ask which database Ablo reads (${state.detail})`)}
288708
+ ` ${import_picocolors25.default.dim("ablo")} ${import_picocolors25.default.yellow("?")} ${import_picocolors25.default.dim(`couldn't ask which database Ablo reads (${state.detail})`)}
288328
288709
  `
288329
288710
  );
288330
288711
  return;
288331
288712
  }
288332
288713
  if (state.kind === "none") {
288333
288714
  console.log(
288334
- ` ${import_picocolors24.default.dim("ablo")} ${import_picocolors24.default.yellow("!")} this branch is not connected to a database, so Ablo does not read this one`
288715
+ ` ${import_picocolors25.default.dim("ablo")} ${import_picocolors25.default.yellow("!")} this branch is not connected to a database, so Ablo does not read this one`
288335
288716
  );
288336
288717
  console.log(
288337
- ` ${import_picocolors24.default.dim(`Connect it with ${import_picocolors24.default.bold("ablo connect apply")}. Until then a table here is invisible to the engine.`)}
288718
+ ` ${import_picocolors25.default.dim(`Connect it with ${import_picocolors25.default.bold("ablo connect apply")}. Until then a table here is invisible to the engine.`)}
288338
288719
  `
288339
288720
  );
288340
288721
  return;
@@ -288342,15 +288723,15 @@ async function reportReadSubject(dbUrl) {
288342
288723
  const registered = [...new Set(state.hosts)];
288343
288724
  if (host && registered.length > 0 && !registered.includes(host)) {
288344
288725
  console.log(
288345
- ` ${import_picocolors24.default.dim("ablo")} ${import_picocolors24.default.yellow("!")} Ablo reads ${import_picocolors24.default.bold(registered.join(", "))}`
288726
+ ` ${import_picocolors25.default.dim("ablo")} ${import_picocolors25.default.yellow("!")} Ablo reads ${import_picocolors25.default.bold(registered.join(", "))}`
288346
288727
  );
288347
288728
  console.log(
288348
- ` ${import_picocolors24.default.dim("If that is this database under a pooled hostname, this is fine \u2014 otherwise the report below describes a database Ablo never reads.")}
288729
+ ` ${import_picocolors25.default.dim("If that is this database under a pooled hostname, this is fine \u2014 otherwise the report below describes a database Ablo never reads.")}
288349
288730
  `
288350
288731
  );
288351
288732
  return;
288352
288733
  }
288353
- console.log(` ${import_picocolors24.default.dim("ablo")} ${import_picocolors24.default.green("\u2713")} ${import_picocolors24.default.dim("reads this database")}
288734
+ console.log(` ${import_picocolors25.default.dim("ablo")} ${import_picocolors25.default.green("\u2713")} ${import_picocolors25.default.dim("reads this database")}
288354
288735
  `);
288355
288736
  }
288356
288737
  async function check(argv) {
@@ -288358,20 +288739,20 @@ async function check(argv) {
288358
288739
  try {
288359
288740
  args = parseCheckArgs(argv);
288360
288741
  } catch (err) {
288361
- console.error(import_picocolors24.default.red(` ${err instanceof Error ? err.message : String(err)}`));
288742
+ console.error(import_picocolors25.default.red(` ${err instanceof Error ? err.message : String(err)}`));
288362
288743
  process.exit(1);
288363
288744
  }
288364
288745
  const dbUrl = readProjectAdminDatabaseUrl();
288365
288746
  if (!dbUrl) {
288366
288747
  console.error(
288367
- import_picocolors24.default.red(` No database.`) + import_picocolors24.default.dim(` Set ${import_picocolors24.default.bold(ADMIN_URL_VAR)} to the Postgres you want Ablo to adopt.`)
288748
+ import_picocolors25.default.red(` No database.`) + import_picocolors25.default.dim(` Set ${import_picocolors25.default.bold(ADMIN_URL_VAR)} to the Postgres you want Ablo to adopt.`)
288368
288749
  );
288369
288750
  process.exit(1);
288370
288751
  }
288371
288752
  const schema = await loadSchema(args.schemaPath, args.exportName);
288372
288753
  const schemaJson = JSON.parse((0, import_schema9.serializeSchema)(schema));
288373
288754
  console.log(`
288374
- ${brand("ablo")} ${import_picocolors24.default.dim("check")} ${import_picocolors24.default.dim(`schema "${args.appSchema}"`)}
288755
+ ${brand("ablo")} ${import_picocolors25.default.dim("check")} ${import_picocolors25.default.dim(`schema "${args.appSchema}"`)}
288375
288756
  `);
288376
288757
  await reportReadSubject(dbUrl);
288377
288758
  const sql = src_default(dbUrl, { max: 1, prepare: false, onnotice: () => {
@@ -288383,11 +288764,10 @@ async function check(argv) {
288383
288764
  [args.appSchema]
288384
288765
  );
288385
288766
  } catch (err) {
288386
- console.error(import_picocolors24.default.red(` Couldn't read the database: ${err instanceof Error ? err.message : String(err)}`));
288767
+ console.error(import_picocolors25.default.red(` Couldn't read the database: ${err instanceof Error ? err.message : String(err)}`));
288387
288768
  await sql.end({ timeout: 2 });
288388
288769
  process.exit(1);
288389
288770
  }
288390
- await sql.end({ timeout: 2 });
288391
288771
  const colsByTable = /* @__PURE__ */ new Map();
288392
288772
  for (const r2 of rows) {
288393
288773
  let set = colsByTable.get(r2.table_name);
@@ -288405,7 +288785,7 @@ async function check(argv) {
288405
288785
  declaredTables.add(table);
288406
288786
  const present = colsByTable.get(table);
288407
288787
  if (!present) {
288408
- console.log(` ${import_picocolors24.default.red("\u2717")} ${import_picocolors24.default.bold(key)} ${import_picocolors24.default.dim("\u2192")} table ${import_picocolors24.default.bold(table)} ${import_picocolors24.default.red("not found")}`);
288788
+ console.log(` ${import_picocolors25.default.red("\u2717")} ${import_picocolors25.default.bold(key)} ${import_picocolors25.default.dim("\u2192")} table ${import_picocolors25.default.bold(table)} ${import_picocolors25.default.red("not found")}`);
288409
288789
  errors++;
288410
288790
  continue;
288411
288791
  }
@@ -288426,27 +288806,37 @@ async function check(argv) {
288426
288806
  if (BASE_COLUMNS.has(col) || col === orgCol) continue;
288427
288807
  if (!present.has(col)) problems.push(`missing column "${col}" (field ${fieldName})`);
288428
288808
  }
288809
+ if (orgCol && present.has(orgCol)) {
288810
+ const unstamped = await countUnstamped(sql, args.appSchema, table, orgCol);
288811
+ if (unstamped !== null && unstamped > 0) {
288812
+ const count = unstamped > UNSTAMPED_CAP ? `${UNSTAMPED_CAP}+ rows` : `${unstamped} row${unstamped === 1 ? "" : "s"}`;
288813
+ problems.push(
288814
+ `${count} have no "${orgCol}", so nothing can route them. Ablo stamps it on writes it makes; an insert straight into Postgres does not. Backfill the value, then run \`ablo connect resnapshot\`.`
288815
+ );
288816
+ }
288817
+ }
288429
288818
  if (problems.length > 0) {
288430
- console.log(` ${import_picocolors24.default.red("\u2717")} ${import_picocolors24.default.bold(key)} ${import_picocolors24.default.dim("\u2192")} ${table}`);
288431
- for (const p2 of problems) console.log(` ${import_picocolors24.default.red("\u2022")} ${p2}`);
288432
- for (const w2 of warns) console.log(` ${import_picocolors24.default.yellow("\u2022")} ${w2}`);
288819
+ console.log(` ${import_picocolors25.default.red("\u2717")} ${import_picocolors25.default.bold(key)} ${import_picocolors25.default.dim("\u2192")} ${table}`);
288820
+ for (const p2 of problems) console.log(` ${import_picocolors25.default.red("\u2022")} ${p2}`);
288821
+ for (const w2 of warns) console.log(` ${import_picocolors25.default.yellow("\u2022")} ${w2}`);
288433
288822
  errors++;
288434
288823
  } else if (warns.length > 0) {
288435
- console.log(` ${import_picocolors24.default.yellow("!")} ${import_picocolors24.default.bold(key)} ${import_picocolors24.default.dim("\u2192")} ${table}`);
288436
- for (const w2 of warns) console.log(` ${import_picocolors24.default.yellow("\u2022")} ${w2}`);
288824
+ console.log(` ${import_picocolors25.default.yellow("!")} ${import_picocolors25.default.bold(key)} ${import_picocolors25.default.dim("\u2192")} ${table}`);
288825
+ for (const w2 of warns) console.log(` ${import_picocolors25.default.yellow("\u2022")} ${w2}`);
288437
288826
  warnings++;
288438
288827
  } else {
288439
- console.log(` ${import_picocolors24.default.green("\u2713")} ${import_picocolors24.default.bold(key)} ${import_picocolors24.default.dim(`\u2192 ${table} (id, ${orgCol ?? "no org"} ok)`)}`);
288828
+ console.log(` ${import_picocolors25.default.green("\u2713")} ${import_picocolors25.default.bold(key)} ${import_picocolors25.default.dim(`\u2192 ${table} (id, ${orgCol ?? "no org"} ok)`)}`);
288440
288829
  }
288441
288830
  }
288831
+ await sql.end({ timeout: 2 });
288442
288832
  const modelCount = Object.keys(schemaJson.models).length;
288443
288833
  const ignored = [...colsByTable.keys()].filter((t) => !declaredTables.has(t)).length;
288444
288834
  console.log(
288445
288835
  `
288446
- ${modelCount} model${modelCount === 1 ? "" : "s"} \xB7 ${import_picocolors24.default.green(`${modelCount - errors - warnings} ok`)}` + (warnings ? ` \xB7 ${import_picocolors24.default.yellow(`${warnings} warning${warnings === 1 ? "" : "s"}`)}` : "") + (errors ? ` \xB7 ${import_picocolors24.default.red(`${errors} error${errors === 1 ? "" : "s"}`)}` : "")
288836
+ ${modelCount} model${modelCount === 1 ? "" : "s"} \xB7 ${import_picocolors25.default.green(`${modelCount - errors - warnings} ok`)}` + (warnings ? ` \xB7 ${import_picocolors25.default.yellow(`${warnings} warning${warnings === 1 ? "" : "s"}`)}` : "") + (errors ? ` \xB7 ${import_picocolors25.default.red(`${errors} error${errors === 1 ? "" : "s"}`)}` : "")
288447
288837
  );
288448
288838
  if (ignored > 0) {
288449
- console.log(` ${import_picocolors24.default.dim(`${ignored} other table${ignored === 1 ? "" : "s"} in your database \u2014 ignored by Ablo`)}`);
288839
+ console.log(` ${import_picocolors25.default.dim(`${ignored} other table${ignored === 1 ? "" : "s"} in your database \u2014 ignored by Ablo`)}`);
288450
288840
  }
288451
288841
  console.log();
288452
288842
  process.exit(errors > 0 ? 1 : 0);
@@ -288454,7 +288844,7 @@ async function check(argv) {
288454
288844
 
288455
288845
  // src/upgrade.ts
288456
288846
  init_cjs_shims();
288457
- var import_picocolors25 = __toESM(require_picocolors(), 1);
288847
+ var import_picocolors26 = __toESM(require_picocolors(), 1);
288458
288848
  var import_ts_morph = __toESM(require_ts_morph(), 1);
288459
288849
  var DEFAULT_GLOBS = ["app/**/*.{ts,tsx}", "src/**/*.{ts,tsx}", "ablo/**/*.{ts,tsx}", "lib/**/*.{ts,tsx}"];
288460
288850
  var VERB_ARGS = {
@@ -288532,7 +288922,7 @@ async function upgrade(argv) {
288532
288922
  project.addSourceFilesAtPaths(globs.length > 0 ? globs : DEFAULT_GLOBS);
288533
288923
  const files = project.getSourceFiles();
288534
288924
  if (files.length === 0) {
288535
- console.log(import_picocolors25.default.yellow(' No .ts/.tsx files found. Pass a glob, e.g. `ablo upgrade "src/**/*.tsx"`.'));
288925
+ console.log(import_picocolors26.default.yellow(' No .ts/.tsx files found. Pass a glob, e.g. `ablo upgrade "src/**/*.tsx"`.'));
288536
288926
  return;
288537
288927
  }
288538
288928
  const edits = [];
@@ -288606,39 +288996,39 @@ async function upgrade(argv) {
288606
288996
  const rel = (f) => f.replace(cwd + "/", "");
288607
288997
  console.log();
288608
288998
  if (edits.length === 0 && manual.length === 0) {
288609
- console.log(import_picocolors25.default.green(" \u2713 Nothing to migrate \u2014 your code is already on the current API."));
288999
+ console.log(import_picocolors26.default.green(" \u2713 Nothing to migrate \u2014 your code is already on the current API."));
288610
289000
  return;
288611
289001
  }
288612
289002
  if (edits.length > 0) {
288613
- console.log(import_picocolors25.default.bold(` ${write ? "Applied" : "Would apply"} ${edits.length} change${edits.length === 1 ? "" : "s"}:`));
289003
+ console.log(import_picocolors26.default.bold(` ${write ? "Applied" : "Would apply"} ${edits.length} change${edits.length === 1 ? "" : "s"}:`));
288614
289004
  for (const e2 of edits) {
288615
- console.log(` ${import_picocolors25.default.dim(`${rel(e2.file)}:${e2.line}`)} ${import_picocolors25.default.cyan(e2.rule)}`);
288616
- console.log(` ${import_picocolors25.default.red("-")} ${e2.before}`);
288617
- console.log(` ${import_picocolors25.default.green("+")} ${e2.after}`);
289005
+ console.log(` ${import_picocolors26.default.dim(`${rel(e2.file)}:${e2.line}`)} ${import_picocolors26.default.cyan(e2.rule)}`);
289006
+ console.log(` ${import_picocolors26.default.red("-")} ${e2.before}`);
289007
+ console.log(` ${import_picocolors26.default.green("+")} ${e2.after}`);
288618
289008
  }
288619
289009
  }
288620
289010
  if (manual.length > 0) {
288621
289011
  console.log();
288622
- console.log(import_picocolors25.default.bold(import_picocolors25.default.yellow(` ${manual.length} spot${manual.length === 1 ? "" : "s"} need manual review (structural):`)));
289012
+ console.log(import_picocolors26.default.bold(import_picocolors26.default.yellow(` ${manual.length} spot${manual.length === 1 ? "" : "s"} need manual review (structural):`)));
288623
289013
  for (const m2 of manual) {
288624
- console.log(` ${import_picocolors25.default.dim(`${rel(m2.file)}:${m2.line}`)} ${import_picocolors25.default.yellow(m2.rule)}`);
288625
- console.log(` ${import_picocolors25.default.dim(m2.snippet)}`);
289014
+ console.log(` ${import_picocolors26.default.dim(`${rel(m2.file)}:${m2.line}`)} ${import_picocolors26.default.yellow(m2.rule)}`);
289015
+ console.log(` ${import_picocolors26.default.dim(m2.snippet)}`);
288626
289016
  console.log(` \u2192 ${m2.hint}`);
288627
289017
  }
288628
289018
  }
288629
289019
  console.log();
288630
289020
  if (write) {
288631
289021
  await project.save();
288632
- console.log(import_picocolors25.default.green(` \u2713 Wrote ${edits.length} change${edits.length === 1 ? "" : "s"}. Review the diff, run your typecheck.`));
289022
+ console.log(import_picocolors26.default.green(` \u2713 Wrote ${edits.length} change${edits.length === 1 ? "" : "s"}. Review the diff, run your typecheck.`));
288633
289023
  } else {
288634
- console.log(import_picocolors25.default.dim(" Dry run. Re-run with `--write` to apply the auto-fixes above (manual items are never auto-written)."));
289024
+ console.log(import_picocolors26.default.dim(" Dry run. Re-run with `--write` to apply the auto-fixes above (manual items are never auto-written)."));
288635
289025
  }
288636
289026
  }
288637
289027
 
288638
289028
  // src/pull.ts
288639
289029
  init_cjs_shims();
288640
- var import_errors20 = require("@abloatai/transaction/errors");
288641
- var import_picocolors26 = __toESM(require_picocolors(), 1);
289030
+ var import_errors21 = require("@abloatai/transaction/errors");
289031
+ var import_picocolors27 = __toESM(require_picocolors(), 1);
288642
289032
  init_src();
288643
289033
  var import_fs10 = require("fs");
288644
289034
  init_theme();
@@ -288666,7 +289056,7 @@ function parsePullArgs(argv) {
288666
289056
  force = true;
288667
289057
  break;
288668
289058
  default:
288669
- throw new import_errors20.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
289059
+ throw new import_errors21.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
288670
289060
  }
288671
289061
  }
288672
289062
  return { out, appSchema, importPath, force };
@@ -288736,56 +289126,56 @@ async function pull(argv) {
288736
289126
  try {
288737
289127
  args = parsePullArgs(argv);
288738
289128
  } catch (err) {
288739
- console.error(import_picocolors26.default.red(` ${err instanceof Error ? err.message : String(err)}`));
289129
+ console.error(import_picocolors27.default.red(` ${err instanceof Error ? err.message : String(err)}`));
288740
289130
  process.exit(1);
288741
289131
  }
288742
289132
  const dbUrl = readProjectAdminDatabaseUrl();
288743
289133
  if (!dbUrl) {
288744
289134
  console.error(
288745
- import_picocolors26.default.red(` No database.`) + import_picocolors26.default.dim(` Set ${import_picocolors26.default.bold(ADMIN_URL_VAR)} to the Postgres to pull from.`)
289135
+ import_picocolors27.default.red(` No database.`) + import_picocolors27.default.dim(` Set ${import_picocolors27.default.bold(ADMIN_URL_VAR)} to the Postgres to pull from.`)
288746
289136
  );
288747
289137
  process.exit(1);
288748
289138
  }
288749
289139
  if ((0, import_fs10.existsSync)(args.out) && !args.force) {
288750
289140
  console.error(
288751
- import_picocolors26.default.red(` ${args.out} already exists.`) + import_picocolors26.default.dim(` Re-run with ${import_picocolors26.default.bold("--force")} to overwrite.`)
289141
+ import_picocolors27.default.red(` ${args.out} already exists.`) + import_picocolors27.default.dim(` Re-run with ${import_picocolors27.default.bold("--force")} to overwrite.`)
288752
289142
  );
288753
289143
  process.exit(1);
288754
289144
  }
288755
289145
  console.log(`
288756
- ${brand("ablo")} ${import_picocolors26.default.dim("pull")} ${import_picocolors26.default.dim(`schema "${args.appSchema}"`)}
289146
+ ${brand("ablo")} ${import_picocolors27.default.dim("pull")} ${import_picocolors27.default.dim(`schema "${args.appSchema}"`)}
288757
289147
  `);
288758
289148
  let result;
288759
289149
  try {
288760
289150
  result = await buildSchemaSourceFromDb({ dbUrl, appSchema: args.appSchema, importPath: args.importPath });
288761
289151
  } catch (err) {
288762
- console.error(import_picocolors26.default.red(` Couldn't read the database: ${err instanceof Error ? err.message : String(err)}`));
289152
+ console.error(import_picocolors27.default.red(` Couldn't read the database: ${err instanceof Error ? err.message : String(err)}`));
288763
289153
  process.exit(1);
288764
289154
  }
288765
289155
  if (result.models.length === 0) {
288766
289156
  console.error(
288767
- import_picocolors26.default.yellow(` No adoptable tables found`) + import_picocolors26.default.dim(` (a model needs an ${import_picocolors26.default.bold("id")} + ${import_picocolors26.default.bold("organization_id")} column).`)
289157
+ import_picocolors27.default.yellow(` No adoptable tables found`) + import_picocolors27.default.dim(` (a model needs an ${import_picocolors27.default.bold("id")} + ${import_picocolors27.default.bold("organization_id")} column).`)
288768
289158
  );
288769
289159
  process.exit(1);
288770
289160
  }
288771
289161
  (0, import_fs10.writeFileSync)(args.out, result.source);
288772
- console.log(` ${import_picocolors26.default.green("\u2713")} wrote ${import_picocolors26.default.bold(args.out)} ${import_picocolors26.default.dim(`(${result.models.length} models)`)}`);
288773
- console.log(` ${import_picocolors26.default.dim(`models: ${result.models.join(", ")}`)}`);
289162
+ console.log(` ${import_picocolors27.default.green("\u2713")} wrote ${import_picocolors27.default.bold(args.out)} ${import_picocolors27.default.dim(`(${result.models.length} models)`)}`);
289163
+ console.log(` ${import_picocolors27.default.dim(`models: ${result.models.join(", ")}`)}`);
288774
289164
  if (result.skipped.length > 0) {
288775
- console.log(` ${import_picocolors26.default.dim(`${result.skipped.length} table(s) skipped:`)}`);
288776
- for (const s of result.skipped) console.log(` ${import_picocolors26.default.dim(`- ${s.name}: ${s.reason}`)}`);
289165
+ console.log(` ${import_picocolors27.default.dim(`${result.skipped.length} table(s) skipped:`)}`);
289166
+ for (const s of result.skipped) console.log(` ${import_picocolors27.default.dim(`- ${s.name}: ${s.reason}`)}`);
288777
289167
  }
288778
289168
  console.log(
288779
289169
  `
288780
- ${import_picocolors26.default.dim("Introspection is lossy (enums, JSON shape, relations). Review the file, then")} ${import_picocolors26.default.bold("ablo check")}.
289170
+ ${import_picocolors27.default.dim("Introspection is lossy (enums, JSON shape, relations). Review the file, then")} ${import_picocolors27.default.bold("ablo check")}.
288781
289171
  `
288782
289172
  );
288783
289173
  }
288784
289174
 
288785
289175
  // src/prismaPull.ts
288786
289176
  init_cjs_shims();
288787
- var import_errors21 = require("@abloatai/transaction/errors");
288788
- var import_picocolors27 = __toESM(require_picocolors(), 1);
289177
+ var import_errors22 = require("@abloatai/transaction/errors");
289178
+ var import_picocolors28 = __toESM(require_picocolors(), 1);
288789
289179
  var import_fs11 = require("fs");
288790
289180
  init_theme();
288791
289181
  var DEFAULT_SCHEMA = "prisma/schema.prisma";
@@ -288982,7 +289372,7 @@ function parsePrismaPullArgs(argv) {
288982
289372
  force = true;
288983
289373
  break;
288984
289374
  default:
288985
- if (arg.startsWith("--")) throw new import_errors21.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
289375
+ if (arg.startsWith("--")) throw new import_errors22.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
288986
289376
  schema = arg;
288987
289377
  }
288988
289378
  }
@@ -288993,56 +289383,56 @@ async function prismaPull(argv) {
288993
289383
  try {
288994
289384
  args = parsePrismaPullArgs(argv);
288995
289385
  } catch (err) {
288996
- console.error(import_picocolors27.default.red(` ${err instanceof Error ? err.message : String(err)}`));
289386
+ console.error(import_picocolors28.default.red(` ${err instanceof Error ? err.message : String(err)}`));
288997
289387
  process.exit(1);
288998
289388
  }
288999
289389
  if (!(0, import_fs11.existsSync)(args.schema)) {
289000
289390
  console.error(
289001
- import_picocolors27.default.red(` No Prisma schema at ${import_picocolors27.default.bold(args.schema)}.`) + import_picocolors27.default.dim(` Pass a path: ${import_picocolors27.default.bold("ablo pull prisma <path>")}.`)
289391
+ import_picocolors28.default.red(` No Prisma schema at ${import_picocolors28.default.bold(args.schema)}.`) + import_picocolors28.default.dim(` Pass a path: ${import_picocolors28.default.bold("ablo pull prisma <path>")}.`)
289002
289392
  );
289003
289393
  process.exit(1);
289004
289394
  }
289005
289395
  if ((0, import_fs11.existsSync)(args.out) && !args.force) {
289006
289396
  console.error(
289007
- import_picocolors27.default.red(` ${args.out} already exists.`) + import_picocolors27.default.dim(` Re-run with ${import_picocolors27.default.bold("--force")} to overwrite.`)
289397
+ import_picocolors28.default.red(` ${args.out} already exists.`) + import_picocolors28.default.dim(` Re-run with ${import_picocolors28.default.bold("--force")} to overwrite.`)
289008
289398
  );
289009
289399
  process.exit(1);
289010
289400
  }
289011
289401
  console.log(`
289012
- ${brand("ablo")} ${import_picocolors27.default.dim("pull prisma")} ${import_picocolors27.default.dim(args.schema)}
289402
+ ${brand("ablo")} ${import_picocolors28.default.dim("pull prisma")} ${import_picocolors28.default.dim(args.schema)}
289013
289403
  `);
289014
289404
  let result;
289015
289405
  try {
289016
289406
  const src = (0, import_fs11.readFileSync)(args.schema, "utf8");
289017
289407
  result = buildSchemaSourceFromPrisma({ src, importPath: args.importPath });
289018
289408
  } catch (err) {
289019
- console.error(import_picocolors27.default.red(` Couldn't parse the schema: ${err instanceof Error ? err.message : String(err)}`));
289409
+ console.error(import_picocolors28.default.red(` Couldn't parse the schema: ${err instanceof Error ? err.message : String(err)}`));
289020
289410
  process.exit(1);
289021
289411
  }
289022
289412
  if (result.models.length === 0) {
289023
289413
  console.error(
289024
- import_picocolors27.default.yellow(` No adoptable models found`) + import_picocolors27.default.dim(` (a model needs an ${import_picocolors27.default.bold("id")} + ${import_picocolors27.default.bold("organizationId")} / ${import_picocolors27.default.bold("organization_id")}).`)
289414
+ import_picocolors28.default.yellow(` No adoptable models found`) + import_picocolors28.default.dim(` (a model needs an ${import_picocolors28.default.bold("id")} + ${import_picocolors28.default.bold("organizationId")} / ${import_picocolors28.default.bold("organization_id")}).`)
289025
289415
  );
289026
289416
  process.exit(1);
289027
289417
  }
289028
289418
  (0, import_fs11.writeFileSync)(args.out, result.source);
289029
- console.log(` ${import_picocolors27.default.green("\u2713")} wrote ${import_picocolors27.default.bold(args.out)} ${import_picocolors27.default.dim(`(${result.models.length} models)`)}`);
289030
- console.log(` ${import_picocolors27.default.dim(`models: ${result.models.join(", ")}`)}`);
289419
+ console.log(` ${import_picocolors28.default.green("\u2713")} wrote ${import_picocolors28.default.bold(args.out)} ${import_picocolors28.default.dim(`(${result.models.length} models)`)}`);
289420
+ console.log(` ${import_picocolors28.default.dim(`models: ${result.models.join(", ")}`)}`);
289031
289421
  if (result.skipped.length > 0) {
289032
- console.log(` ${import_picocolors27.default.dim(`${result.skipped.length} model(s) skipped:`)}`);
289033
- for (const s of result.skipped) console.log(` ${import_picocolors27.default.dim(`- ${s.name}: ${s.reason}`)}`);
289422
+ console.log(` ${import_picocolors28.default.dim(`${result.skipped.length} model(s) skipped:`)}`);
289423
+ for (const s of result.skipped) console.log(` ${import_picocolors28.default.dim(`- ${s.name}: ${s.reason}`)}`);
289034
289424
  }
289035
289425
  console.log(
289036
289426
  `
289037
- ${import_picocolors27.default.dim("Enums and relations were preserved. Review the file, then")} ${import_picocolors27.default.bold("ablo check")}.
289427
+ ${import_picocolors28.default.dim("Enums and relations were preserved. Review the file, then")} ${import_picocolors28.default.bold("ablo check")}.
289038
289428
  `
289039
289429
  );
289040
289430
  }
289041
289431
 
289042
289432
  // src/drizzlePull.ts
289043
289433
  init_cjs_shims();
289044
- var import_picocolors28 = __toESM(require_picocolors(), 1);
289045
- var import_errors22 = require("@abloatai/transaction/errors");
289434
+ var import_picocolors29 = __toESM(require_picocolors(), 1);
289435
+ var import_errors23 = require("@abloatai/transaction/errors");
289046
289436
  var import_fs12 = require("fs");
289047
289437
  var import_path7 = require("path");
289048
289438
  init_theme();
@@ -289149,7 +289539,7 @@ function parseDrizzlePullArgs(argv) {
289149
289539
  force = true;
289150
289540
  break;
289151
289541
  default:
289152
- if (arg.startsWith("--")) throw new import_errors22.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
289542
+ if (arg.startsWith("--")) throw new import_errors23.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
289153
289543
  schema = arg;
289154
289544
  }
289155
289545
  }
@@ -289166,27 +289556,27 @@ async function drizzlePull(argv) {
289166
289556
  try {
289167
289557
  args = parseDrizzlePullArgs(argv);
289168
289558
  } catch (err) {
289169
- console.error(import_picocolors28.default.red(` ${err instanceof Error ? err.message : String(err)}`));
289559
+ console.error(import_picocolors29.default.red(` ${err instanceof Error ? err.message : String(err)}`));
289170
289560
  process.exit(1);
289171
289561
  }
289172
289562
  if (!args.schema) {
289173
289563
  console.error(
289174
- import_picocolors28.default.red(` No Drizzle schema given.`) + import_picocolors28.default.dim(` Pass the module: ${import_picocolors28.default.bold("ablo pull drizzle src/db/schema.ts")}.`)
289564
+ import_picocolors29.default.red(` No Drizzle schema given.`) + import_picocolors29.default.dim(` Pass the module: ${import_picocolors29.default.bold("ablo pull drizzle src/db/schema.ts")}.`)
289175
289565
  );
289176
289566
  process.exit(1);
289177
289567
  }
289178
289568
  if (!(0, import_fs12.existsSync)(args.schema)) {
289179
- console.error(import_picocolors28.default.red(` No file at ${import_picocolors28.default.bold(args.schema)}.`));
289569
+ console.error(import_picocolors29.default.red(` No file at ${import_picocolors29.default.bold(args.schema)}.`));
289180
289570
  process.exit(1);
289181
289571
  }
289182
289572
  if ((0, import_fs12.existsSync)(args.out) && !args.force) {
289183
289573
  console.error(
289184
- import_picocolors28.default.red(` ${args.out} already exists.`) + import_picocolors28.default.dim(` Re-run with ${import_picocolors28.default.bold("--force")} to overwrite.`)
289574
+ import_picocolors29.default.red(` ${args.out} already exists.`) + import_picocolors29.default.dim(` Re-run with ${import_picocolors29.default.bold("--force")} to overwrite.`)
289185
289575
  );
289186
289576
  process.exit(1);
289187
289577
  }
289188
289578
  console.log(`
289189
- ${brand("ablo")} ${import_picocolors28.default.dim("pull drizzle")} ${import_picocolors28.default.dim(args.schema)}
289579
+ ${brand("ablo")} ${import_picocolors29.default.dim("pull drizzle")} ${import_picocolors29.default.dim(args.schema)}
289190
289580
  `);
289191
289581
  let result;
289192
289582
  try {
@@ -289194,26 +289584,26 @@ async function drizzlePull(argv) {
289194
289584
  result = await buildSchemaSourceFromDrizzle({ mod, importPath: args.importPath });
289195
289585
  } catch (err) {
289196
289586
  const msg = err instanceof Error ? err.message : String(err);
289197
- const hint = msg.includes("Cannot find package 'drizzle-orm'") ? import_picocolors28.default.dim(` (install ${import_picocolors28.default.bold("drizzle-orm")} in this project)`) : "";
289198
- console.error(import_picocolors28.default.red(` Couldn't load the schema: ${msg}`) + hint);
289587
+ const hint = msg.includes("Cannot find package 'drizzle-orm'") ? import_picocolors29.default.dim(` (install ${import_picocolors29.default.bold("drizzle-orm")} in this project)`) : "";
289588
+ console.error(import_picocolors29.default.red(` Couldn't load the schema: ${msg}`) + hint);
289199
289589
  process.exit(1);
289200
289590
  }
289201
289591
  if (result.models.length === 0) {
289202
289592
  console.error(
289203
- import_picocolors28.default.yellow(` No adoptable tables found`) + import_picocolors28.default.dim(` (a table needs an ${import_picocolors28.default.bold("id")} + ${import_picocolors28.default.bold("organization_id")} column).`)
289593
+ import_picocolors29.default.yellow(` No adoptable tables found`) + import_picocolors29.default.dim(` (a table needs an ${import_picocolors29.default.bold("id")} + ${import_picocolors29.default.bold("organization_id")} column).`)
289204
289594
  );
289205
289595
  process.exit(1);
289206
289596
  }
289207
289597
  (0, import_fs12.writeFileSync)(args.out, result.source);
289208
- console.log(` ${import_picocolors28.default.green("\u2713")} wrote ${import_picocolors28.default.bold(args.out)} ${import_picocolors28.default.dim(`(${result.models.length} models)`)}`);
289209
- console.log(` ${import_picocolors28.default.dim(`models: ${result.models.join(", ")}`)}`);
289598
+ console.log(` ${import_picocolors29.default.green("\u2713")} wrote ${import_picocolors29.default.bold(args.out)} ${import_picocolors29.default.dim(`(${result.models.length} models)`)}`);
289599
+ console.log(` ${import_picocolors29.default.dim(`models: ${result.models.join(", ")}`)}`);
289210
289600
  if (result.skipped.length > 0) {
289211
- console.log(` ${import_picocolors28.default.dim(`${result.skipped.length} table(s) skipped:`)}`);
289212
- for (const s of result.skipped) console.log(` ${import_picocolors28.default.dim(`- ${s.name}: ${s.reason}`)}`);
289601
+ console.log(` ${import_picocolors29.default.dim(`${result.skipped.length} table(s) skipped:`)}`);
289602
+ for (const s of result.skipped) console.log(` ${import_picocolors29.default.dim(`- ${s.name}: ${s.reason}`)}`);
289213
289603
  }
289214
289604
  console.log(
289215
289605
  `
289216
- ${import_picocolors28.default.dim("Enums and relations were preserved. Review the file, then")} ${import_picocolors28.default.bold("ablo check")}.
289606
+ ${import_picocolors29.default.dim("Enums and relations were preserved. Review the file, then")} ${import_picocolors29.default.bold("ablo check")}.
289217
289607
  `
289218
289608
  );
289219
289609
  }
@@ -289226,7 +289616,7 @@ init_telemetry();
289226
289616
 
289227
289617
  // src/init/options.ts
289228
289618
  init_cjs_shims();
289229
- var import_node_fs3 = require("fs");
289619
+ var import_node_fs4 = require("fs");
289230
289620
  var import_node_path3 = require("path");
289231
289621
  var INIT_FRAMEWORKS = ["nextjs", "vite", "remix", "vanilla"];
289232
289622
  var INIT_AUTHS = [
@@ -289266,7 +289656,7 @@ function parseInitArgs(args) {
289266
289656
  function detectOrm(override, root = process.cwd()) {
289267
289657
  if (override === "prisma" || override === "drizzle" || override === "none") return override;
289268
289658
  try {
289269
- const pkg = JSON.parse((0, import_node_fs3.readFileSync)((0, import_node_path3.resolve)(root, "package.json"), "utf8"));
289659
+ const pkg = JSON.parse((0, import_node_fs4.readFileSync)((0, import_node_path3.resolve)(root, "package.json"), "utf8"));
289270
289660
  const dependencies = { ...pkg.dependencies, ...pkg.devDependencies };
289271
289661
  if (dependencies["@prisma/client"] || dependencies.prisma) return "prisma";
289272
289662
  if (dependencies["drizzle-orm"]) return "drizzle";
@@ -289275,24 +289665,24 @@ function detectOrm(override, root = process.cwd()) {
289275
289665
  return "none";
289276
289666
  }
289277
289667
  function detectNextLayout(root = process.cwd()) {
289278
- const useSrc = (0, import_node_fs3.existsSync)((0, import_node_path3.resolve)(root, "src", "app")) || !(0, import_node_fs3.existsSync)((0, import_node_path3.resolve)(root, "app")) && (0, import_node_fs3.existsSync)((0, import_node_path3.resolve)(root, "src"));
289668
+ const useSrc = (0, import_node_fs4.existsSync)((0, import_node_path3.resolve)(root, "src", "app")) || !(0, import_node_fs4.existsSync)((0, import_node_path3.resolve)(root, "app")) && (0, import_node_fs4.existsSync)((0, import_node_path3.resolve)(root, "src"));
289279
289669
  return useSrc ? { appBase: (0, import_node_path3.join)("src", "app"), aliasBase: "src" } : { appBase: "app", aliasBase: "." };
289280
289670
  }
289281
289671
  function detectPackageManager(root = process.cwd()) {
289282
- if ((0, import_node_fs3.existsSync)((0, import_node_path3.resolve)(root, "pnpm-lock.yaml"))) return "pnpm";
289283
- if ((0, import_node_fs3.existsSync)((0, import_node_path3.resolve)(root, "yarn.lock"))) return "yarn";
289284
- if ((0, import_node_fs3.existsSync)((0, import_node_path3.resolve)(root, "bun.lockb"))) return "bun";
289672
+ if ((0, import_node_fs4.existsSync)((0, import_node_path3.resolve)(root, "pnpm-lock.yaml"))) return "pnpm";
289673
+ if ((0, import_node_fs4.existsSync)((0, import_node_path3.resolve)(root, "yarn.lock"))) return "yarn";
289674
+ if ((0, import_node_fs4.existsSync)((0, import_node_path3.resolve)(root, "bun.lockb"))) return "bun";
289285
289675
  return "npm";
289286
289676
  }
289287
289677
 
289288
289678
  // src/init/run.ts
289289
289679
  init_cjs_shims();
289290
289680
  var import_node_child_process3 = require("child_process");
289291
- var import_node_fs5 = require("fs");
289681
+ var import_node_fs6 = require("fs");
289292
289682
  var import_node_path5 = require("path");
289293
289683
  init_dist2();
289294
- var import_picocolors29 = __toESM(require_picocolors(), 1);
289295
- var import_errors23 = require("@abloatai/transaction/errors");
289684
+ var import_picocolors30 = __toESM(require_picocolors(), 1);
289685
+ var import_errors24 = require("@abloatai/transaction/errors");
289296
289686
  init_dbRole();
289297
289687
  init_config();
289298
289688
  init_projects();
@@ -289717,9 +290107,9 @@ export function RecordList() {
289717
290107
 
289718
290108
  // src/init/writer.ts
289719
290109
  init_cjs_shims();
289720
- var import_node_fs4 = require("fs");
290110
+ var import_node_fs5 = require("fs");
289721
290111
  var import_node_path4 = require("path");
289722
- var import_node_crypto5 = require("crypto");
290112
+ var import_node_crypto7 = require("crypto");
289723
290113
  function projectInitWritePlan(plan) {
289724
290114
  return setupInitPlanProjectionSchema.parse({
289725
290115
  root: plan.root,
@@ -289741,10 +290131,10 @@ function absolute(root, path) {
289741
290131
  return target;
289742
290132
  }
289743
290133
  function sha2562(content) {
289744
- return (0, import_node_crypto5.createHash)("sha256").update(content).digest("hex");
290134
+ return (0, import_node_crypto7.createHash)("sha256").update(content).digest("hex");
289745
290135
  }
289746
290136
  function readIfPresent(path) {
289747
- return (0, import_node_fs4.existsSync)(path) ? (0, import_node_fs4.readFileSync)(path, "utf8") : void 0;
290137
+ return (0, import_node_fs5.existsSync)(path) ? (0, import_node_fs5.readFileSync)(path, "utf8") : void 0;
289748
290138
  }
289749
290139
  function mergeEnvironmentTemplate(existing, template) {
289750
290140
  const assignments = template.split(/\r?\n/).map((line) => {
@@ -289813,18 +290203,18 @@ function planInitWrites(input) {
289813
290203
  return { root, actions, conflicts };
289814
290204
  }
289815
290205
  function writeAtomic(path, content, kind) {
289816
- (0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(path), { recursive: true });
289817
- const temporary = (0, import_node_path4.join)((0, import_node_path4.dirname)(path), `.${(0, import_node_crypto5.randomUUID)()}.ablo-init.tmp`);
289818
- (0, import_node_fs4.writeFileSync)(temporary, content, { flag: "wx" });
290206
+ (0, import_node_fs5.mkdirSync)((0, import_node_path4.dirname)(path), { recursive: true });
290207
+ const temporary = (0, import_node_path4.join)((0, import_node_path4.dirname)(path), `.${(0, import_node_crypto7.randomUUID)()}.ablo-init.tmp`);
290208
+ (0, import_node_fs5.writeFileSync)(temporary, content, { flag: "wx" });
289819
290209
  try {
289820
290210
  if (kind === "create") {
289821
- (0, import_node_fs4.linkSync)(temporary, path);
289822
- (0, import_node_fs4.unlinkSync)(temporary);
290211
+ (0, import_node_fs5.linkSync)(temporary, path);
290212
+ (0, import_node_fs5.unlinkSync)(temporary);
289823
290213
  } else {
289824
- (0, import_node_fs4.renameSync)(temporary, path);
290214
+ (0, import_node_fs5.renameSync)(temporary, path);
289825
290215
  }
289826
290216
  } catch (error) {
289827
- if ((0, import_node_fs4.existsSync)(temporary)) (0, import_node_fs4.unlinkSync)(temporary);
290217
+ if ((0, import_node_fs5.existsSync)(temporary)) (0, import_node_fs5.unlinkSync)(temporary);
289828
290218
  throw error;
289829
290219
  }
289830
290220
  }
@@ -289858,7 +290248,7 @@ function bailIfCancelled(value) {
289858
290248
  async function chooseOption(name, flagValue, fallback, allowed, interactive, prompt) {
289859
290249
  if (flagValue !== void 0) {
289860
290250
  if (!allowed.includes(flagValue)) {
289861
- throw new import_errors23.AbloValidationError(
290251
+ throw new import_errors24.AbloValidationError(
289862
290252
  `Invalid --${name} "${flagValue}". Allowed: ${allowed.join(", ")}`,
289863
290253
  { code: "cli_invalid_arguments" }
289864
290254
  );
@@ -289882,7 +290272,7 @@ async function ensureInitProject(opts) {
289882
290272
  const slug = opts.project ?? projectSlugFromPackageName(
289883
290273
  (() => {
289884
290274
  try {
289885
- return JSON.parse((0, import_node_fs5.readFileSync)("package.json", "utf8")).name;
290275
+ return JSON.parse((0, import_node_fs6.readFileSync)("package.json", "utf8")).name;
289886
290276
  } catch {
289887
290277
  return void 0;
289888
290278
  }
@@ -289892,7 +290282,7 @@ async function ensureInitProject(opts) {
289892
290282
  const ensured = await ensureProject(slug);
289893
290283
  if (ensured) {
289894
290284
  console.log(
289895
- ` ${import_picocolors29.default.green("\u2713")} ${ensured.created ? "Created" : "Using"} project ${import_picocolors29.default.bold(ensured.slug)} ${import_picocolors29.default.dim(`(${ensured.id})`)} \u2014 keys you mint for it are isolated from the org's other apps.`
290285
+ ` ${import_picocolors30.default.green("\u2713")} ${ensured.created ? "Created" : "Using"} project ${import_picocolors30.default.bold(ensured.slug)} ${import_picocolors30.default.dim(`(${ensured.id})`)} \u2014 keys you mint for it are isolated from the org's other apps.`
289896
290286
  );
289897
290287
  }
289898
290288
  }
@@ -289904,16 +290294,16 @@ function renderWritePlan(actions) {
289904
290294
  }
289905
290295
  function renderAppliedWrites(actions) {
289906
290296
  return actions.map((action) => {
289907
- const status2 = action.kind === "create" ? import_picocolors29.default.green("created") : action.kind === "update" ? import_picocolors29.default.yellow("updated") : import_picocolors29.default.dim("unchanged");
289908
- return `${import_picocolors29.default.green("\u2713")} ${action.path}${action.note ?? ""} ${import_picocolors29.default.dim(`(${status2})`)}`;
290297
+ const status2 = action.kind === "create" ? import_picocolors30.default.green("created") : action.kind === "update" ? import_picocolors30.default.yellow("updated") : import_picocolors30.default.dim("unchanged");
290298
+ return `${import_picocolors30.default.green("\u2713")} ${action.path}${action.note ?? ""} ${import_picocolors30.default.dim(`(${status2})`)}`;
289909
290299
  }).join("\n");
289910
290300
  }
289911
290301
  async function runInit(args = []) {
289912
290302
  const opts = parseInitArgs(args);
289913
290303
  const interactive = Boolean(process.stdin.isTTY) && !opts.yes && !process.env.CI;
289914
- Ie(`${brand("ablo")} ${import_picocolors29.default.dim("sync engine")}`);
289915
- if (!(0, import_node_fs5.existsSync)("package.json")) {
289916
- throw new import_errors23.AbloValidationError("No package.json found. Run this from your project root.", {
290304
+ Ie(`${brand("ablo")} ${import_picocolors30.default.dim("sync engine")}`);
290305
+ if (!(0, import_node_fs6.existsSync)("package.json")) {
290306
+ throw new import_errors24.AbloValidationError("No package.json found. Run this from your project root.", {
289917
290307
  code: "cli_invalid_arguments"
289918
290308
  });
289919
290309
  }
@@ -289989,7 +290379,7 @@ async function runInit(args = []) {
289989
290379
  if (pullExisting) {
289990
290380
  const dbUrl = readProjectAdminDatabaseUrl();
289991
290381
  if (!dbUrl) {
289992
- schemaNote = import_picocolors29.default.dim(` (no ${ADMIN_URL_VAR} \u2014 wrote starter; run \`ablo pull\` later)`);
290382
+ schemaNote = import_picocolors30.default.dim(` (no ${ADMIN_URL_VAR} \u2014 wrote starter; run \`ablo pull\` later)`);
289993
290383
  } else {
289994
290384
  try {
289995
290385
  const pulled = await buildSchemaSourceFromDb({
@@ -289999,12 +290389,12 @@ async function runInit(args = []) {
289999
290389
  });
290000
290390
  if (pulled.models.length > 0) {
290001
290391
  schemaSource = pulled.source;
290002
- schemaNote = import_picocolors29.default.dim(` (pulled ${pulled.models.length} models)`);
290392
+ schemaNote = import_picocolors30.default.dim(` (pulled ${pulled.models.length} models)`);
290003
290393
  } else {
290004
- schemaNote = import_picocolors29.default.dim(" (no adoptable tables \u2014 wrote starter)");
290394
+ schemaNote = import_picocolors30.default.dim(" (no adoptable tables \u2014 wrote starter)");
290005
290395
  }
290006
290396
  } catch {
290007
- schemaNote = import_picocolors29.default.dim(" (pull failed \u2014 wrote starter)");
290397
+ schemaNote = import_picocolors30.default.dim(" (pull failed \u2014 wrote starter)");
290008
290398
  }
290009
290399
  }
290010
290400
  }
@@ -290048,7 +290438,7 @@ async function runInit(args = []) {
290048
290438
  const writePlan = planInitWrites({ files, environment: { path: envFile, template: envBody } });
290049
290439
  if (writePlan.conflicts.length > 0) {
290050
290440
  const occupied = writePlan.conflicts.map(({ path }) => ` - ${path}`).join("\n");
290051
- throw new import_errors23.AbloValidationError(
290441
+ throw new import_errors24.AbloValidationError(
290052
290442
  `Ablo init did not change any files because these application-owned paths already contain different contents:
290053
290443
  ${occupied}
290054
290444
 
@@ -290058,7 +290448,7 @@ Move them, reconcile Ablo manually, or rerun after they match the generated scaf
290058
290448
  }
290059
290449
  if (opts.plan) {
290060
290450
  Me(renderWritePlan(writePlan.actions), "Plan (no files changed)");
290061
- Se(`Dry run complete. Re-run without ${import_picocolors29.default.bold("--plan")} to apply it.`);
290451
+ Se(`Dry run complete. Re-run without ${import_picocolors30.default.bold("--plan")} to apply it.`);
290062
290452
  return setupInitResultSchema.parse({
290063
290453
  status: "planned",
290064
290454
  plan: projectInitWritePlan(writePlan)
@@ -290079,28 +290469,28 @@ Move them, reconcile Ablo manually, or rerun after they match the generated scaf
290079
290469
  progress.stop("Installed @abloatai/ablo");
290080
290470
  } catch {
290081
290471
  progress.stop(
290082
- `${import_picocolors29.default.yellow("!")} Couldn't auto-install \u2014 run ${import_picocolors29.default.bold(`${packageManager2} install @abloatai/ablo`)}`
290472
+ `${import_picocolors30.default.yellow("!")} Couldn't auto-install \u2014 run ${import_picocolors30.default.bold(`${packageManager2} install @abloatai/ablo`)}`
290083
290473
  );
290084
290474
  }
290085
290475
  }
290086
290476
  const steps = [
290087
- `Run ${import_picocolors29.default.bold("npx ablo login")} to authorize branch management`,
290088
- `Set ${import_picocolors29.default.bold("DATABASE_URL")} in ${import_picocolors29.default.bold(envFile)} \u2014 your Postgres is the system of record; rows live there, never with Ablo`,
290089
- `Run ${import_picocolors29.default.bold("npx ablo dev")} \u2014 pushes your schema definition and watches for changes`,
290477
+ `Run ${import_picocolors30.default.bold("npx ablo login")} to authorize branch management`,
290478
+ `Set ${import_picocolors30.default.bold("DATABASE_URL")} in ${import_picocolors30.default.bold(envFile)} \u2014 your Postgres is the system of record; rows live there, never with Ablo`,
290479
+ `Run ${import_picocolors30.default.bold("npx ablo dev")} \u2014 pushes your schema definition and watches for changes`,
290090
290480
  ...storage === "replication" ? [
290091
- `Connect your database \u2014 ${import_picocolors29.default.bold("npx ablo connect")} prints the one-time logical-replication setup SQL to run on your Postgres`,
290092
- `Verify it \u2014 ${import_picocolors29.default.bold("npx ablo connect check")} walks wal_level, the publication, the role, and replica identity, with the exact fix for anything missing`,
290093
- `Register it \u2014 ${import_picocolors29.default.bold("npx ablo connect register")} tells Ablo to start replicating; your app keeps writing through your own backend while Ablo tails the WAL`
290481
+ `Connect your database \u2014 ${import_picocolors30.default.bold("npx ablo connect")} prints the one-time logical-replication setup SQL to run on your Postgres`,
290482
+ `Verify it \u2014 ${import_picocolors30.default.bold("npx ablo connect check")} walks wal_level, the publication, the role, and replica identity, with the exact fix for anything missing`,
290483
+ `Register it \u2014 ${import_picocolors30.default.bold("npx ablo connect register")} tells Ablo to start replicating; your app keeps writing through your own backend while Ablo tails the WAL`
290094
290484
  ] : [
290095
- `Provision your DB: ${import_picocolors29.default.bold("npx ablo migrate")} (creates your Ablo-model tables + the adapter tables; keep your own migrations for everything else), then mount ${import_picocolors29.default.bold(`${abloDir}/data-source.ts`)} at ${import_picocolors29.default.bold("/api/ablo/source")}`
290485
+ `Provision your DB: ${import_picocolors30.default.bold("npx ablo migrate")} (creates your Ablo-model tables + the adapter tables; keep your own migrations for everything else), then mount ${import_picocolors30.default.bold(`${abloDir}/data-source.ts`)} at ${import_picocolors30.default.bold("/api/ablo/source")}`
290096
290486
  ],
290097
290487
  ...framework === "nextjs" ? [
290098
- `Wrap ${import_picocolors29.default.bold((0, import_node_path5.join)(layout.appBase, "layout.tsx"))} in ${import_picocolors29.default.bold("<Providers>")} (${(0, import_node_path5.join)(layout.appBase, "providers.tsx")}) and add your auth to ${import_picocolors29.default.bold((0, import_node_path5.join)(layout.appBase, "api", "ablo-session", "route.ts"))}`
290488
+ `Wrap ${import_picocolors30.default.bold((0, import_node_path5.join)(layout.appBase, "layout.tsx"))} in ${import_picocolors30.default.bold("<Providers>")} (${(0, import_node_path5.join)(layout.appBase, "providers.tsx")}) and add your auth to ${import_picocolors30.default.bold((0, import_node_path5.join)(layout.appBase, "api", "ablo-session", "route.ts"))}`
290099
290489
  ] : [],
290100
- `Run ${import_picocolors29.default.bold(`${packageManager2} run dev`)} and open two browser tabs \u2014 changes sync in real-time`,
290490
+ `Run ${import_picocolors30.default.bold(`${packageManager2} run dev`)} and open two browser tabs \u2014 changes sync in real-time`,
290101
290491
  ...agent ? [
290102
- `Run ${import_picocolors29.default.bold(`npx tsx ${abloDir}/agent.ts`)} \u2014 an AI teammate edits the same records`,
290103
- `Run ${import_picocolors29.default.bold("npx ablo logs")} to watch human + agent commits stream by`
290492
+ `Run ${import_picocolors30.default.bold(`npx tsx ${abloDir}/agent.ts`)} \u2014 an AI teammate edits the same records`,
290493
+ `Run ${import_picocolors30.default.bold("npx ablo logs")} to watch human + agent commits stream by`
290104
290494
  ] : []
290105
290495
  ];
290106
290496
  Me(steps.map((step, index) => `${index + 1}. ${step}`).join("\n"), "Next steps");
@@ -290108,26 +290498,26 @@ Move them, reconcile Ablo manually, or rerun after they match the generated scaf
290108
290498
  if (existingKey) {
290109
290499
  await ensureInitProject(opts);
290110
290500
  Se(
290111
- `Already authorized ${import_picocolors29.default.dim(`(${existingKey.slice(0, 11)}\u2026)`)}. Run ${import_picocolors29.default.bold("npx ablo dev")} next. ${import_picocolors29.default.dim("Docs:")} https://abloatai.com/docs`
290501
+ `Already authorized ${import_picocolors30.default.dim(`(${existingKey.slice(0, 11)}\u2026)`)}. Run ${import_picocolors30.default.bold("npx ablo dev")} next. ${import_picocolors30.default.dim("Docs:")} https://abloatai.com/docs`
290112
290502
  );
290113
290503
  return initResult;
290114
290504
  }
290115
290505
  if (interactive && opts.login) {
290116
290506
  const loginNow = await ye({ message: "Log in now? (opens your browser)", initialValue: true });
290117
290507
  if (!pD(loginNow) && loginNow) {
290118
- Se(`${import_picocolors29.default.dim("Docs:")} https://abloatai.com/docs`);
290508
+ Se(`${import_picocolors30.default.dim("Docs:")} https://abloatai.com/docs`);
290119
290509
  await login();
290120
290510
  await ensureInitProject(opts);
290121
290511
  return initResult;
290122
290512
  }
290123
290513
  }
290124
- Se(`Run ${import_picocolors29.default.bold("npx ablo login")} when ready. ${import_picocolors29.default.dim("Docs:")} https://abloatai.com/docs`);
290514
+ Se(`Run ${import_picocolors30.default.bold("npx ablo login")} when ready. ${import_picocolors30.default.dim("Docs:")} https://abloatai.com/docs`);
290125
290515
  return initResult;
290126
290516
  }
290127
290517
 
290128
290518
  // src/index.ts
290129
290519
  var LOGO = `
290130
- ${brand("ablo")} ${import_picocolors30.default.dim("sync engine")}
290520
+ ${brand("ablo")} ${import_picocolors31.default.dim("sync engine")}
290131
290521
  `;
290132
290522
  var HANDLERS = {
290133
290523
  setup: (argv) => runSetup(argv),
@@ -290146,6 +290536,7 @@ var HANDLERS = {
290146
290536
  webhooks: (argv) => webhooks([...argv]),
290147
290537
  check: (argv) => check([...argv]),
290148
290538
  docs: (argv) => docs([...argv]),
290539
+ feedback: (argv) => feedback([...argv]),
290149
290540
  connect: (argv) => connect([...argv]),
290150
290541
  migrate: (argv) => migrate([...argv]),
290151
290542
  upgrade: (argv) => upgrade([...argv]),
@@ -290159,7 +290550,7 @@ async function runDev(argv) {
290159
290550
  const devArgs = [...argv];
290160
290551
  const oneShot = devArgs.includes("--no-watch");
290161
290552
  console.log(
290162
- import_picocolors30.default.dim(
290553
+ import_picocolors31.default.dim(
290163
290554
  oneShot ? " `ablo dev --no-watch` prepares this Git branch and pushes once." : " `ablo dev` prepares this Git branch and watches the schema."
290164
290555
  )
290165
290556
  );
@@ -290177,7 +290568,7 @@ async function runPush2(argv) {
290177
290568
  }
290178
290569
  function runRenamedSchema(argv) {
290179
290570
  const forwarded = argv.slice(1).join(" ");
290180
- console.error(` ${import_picocolors30.default.red("\u2717")} \`ablo schema push\` was renamed to \`${brand("ablo push")}\`.`);
290571
+ console.error(` ${import_picocolors31.default.red("\u2717")} \`ablo schema push\` was renamed to \`${brand("ablo push")}\`.`);
290181
290572
  console.error(` Run \`ablo push${forwarded ? " " + forwarded : ""}\` instead.`);
290182
290573
  process.exitCode = 1;
290183
290574
  }
@@ -290187,7 +290578,7 @@ async function main() {
290187
290578
  const argv = process.argv.slice(3);
290188
290579
  if (!command && raw !== void 0 && raw !== "help" && !raw.startsWith("-")) {
290189
290580
  const suggestion = suggestCommand(raw);
290190
- throw new import_errors24.AbloValidationError(
290581
+ throw new import_errors25.AbloValidationError(
290191
290582
  `\`${raw}\` isn't an ablo command.` + (suggestion ? ` Did you mean \`ablo ${suggestion}\`?` : " Run `ablo help --all` to see every command."),
290192
290583
  { code: "cli_invalid_arguments" }
290193
290584
  );
@@ -290228,7 +290619,7 @@ function printCoreHelp() {
290228
290619
  const width = Math.max(...rows.map((r2) => r2.run.length)) + 4;
290229
290620
  console.log(LOGO);
290230
290621
  for (const group of CORE_GROUPS) {
290231
- console.log(` ${import_picocolors30.default.bold(group)}`);
290622
+ console.log(` ${import_picocolors31.default.bold(group)}`);
290232
290623
  const printed = group === "More" ? [...coreRows(group), ...extra] : coreRows(group);
290233
290624
  for (const row of printed) console.log(` npx ablo ${row.run.padEnd(width)}${row.does}`);
290234
290625
  console.log();
@@ -290237,7 +290628,7 @@ function printCoreHelp() {
290237
290628
  }
290238
290629
  function printSchemaReminder() {
290239
290630
  console.log(
290240
- import_picocolors30.default.dim(` Edit ${import_picocolors30.default.bold("ablo/schema.ts")}, then push \u2014 writes to models you haven't pushed fail with `) + import_picocolors30.default.yellow("server_execute_unknown_model") + import_picocolors30.default.dim(".")
290631
+ import_picocolors31.default.dim(` Edit ${import_picocolors31.default.bold("ablo/schema.ts")}, then push \u2014 writes to models you haven't pushed fail with `) + import_picocolors31.default.yellow("server_execute_unknown_model") + import_picocolors31.default.dim(".")
290241
290632
  );
290242
290633
  console.log();
290243
290634
  }
@@ -290247,7 +290638,7 @@ function printFullHelp() {
290247
290638
  ) + 2;
290248
290639
  console.log(LOGO);
290249
290640
  for (const group of FULL_GROUPS) {
290250
- console.log(` ${import_picocolors30.default.bold(group)}`);
290641
+ console.log(` ${import_picocolors31.default.bold(group)}`);
290251
290642
  for (const row of fullRows(group)) {
290252
290643
  console.log(row.does === void 0 ? ` ${" ".repeat(9)}${row.run}` : ` npx ablo ${row.run.padEnd(width)}${row.does}`);
290253
290644
  }