@usecontextlayer/ctxe 0.5.4 → 0.5.6

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.
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6317e92d-f910-5336-9f6a-2445ebdf6ed8")}catch(e){}}();
3
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="507e416d-f409-5878-9327-a3aaeaedfd78")}catch(e){}}();
4
4
  import { createRequire } from "node:module";
5
5
  import * as Sentry from "@sentry/node";
6
6
  import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
@@ -59,7 +59,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
59
59
 
60
60
  //#endregion
61
61
  //#region package.json
62
- var version$2 = "0.5.4";
62
+ var version$2 = "0.5.6";
63
63
 
64
64
  //#endregion
65
65
  //#region sentry.ts
@@ -363,6 +363,22 @@ async function drainExecStream(handle, options) {
363
363
  signal?.removeEventListener("abort", onAbort);
364
364
  }
365
365
  }
366
+ const MICROSANDBOX_HOST_ALIAS = "host.microsandbox.internal";
367
+ const HOST_LOOPBACK_HOSTNAMES = new Set([
368
+ "localhost",
369
+ "127.0.0.1",
370
+ "0.0.0.0"
371
+ ]);
372
+ const IPV6_LOOPBACK_HOSTNAMES = new Set(["[::1]", "[::]"]);
373
+ function rewriteHostUrlForGuest(url) {
374
+ const parsed = new URL(url);
375
+ const hostname = parsed.hostname.toLowerCase();
376
+ if (HOST_LOOPBACK_HOSTNAMES.has(hostname) || IPV6_LOOPBACK_HOSTNAMES.has(hostname)) {
377
+ parsed.hostname = MICROSANDBOX_HOST_ALIAS;
378
+ return parsed.toString();
379
+ }
380
+ return url;
381
+ }
366
382
  const DEBUG_SANDBOX_NAME = "ctx-sandbox-debug";
367
383
  const DEFAULT_BOOT_COMMAND = ["uname", "-a"];
368
384
  async function runSandbox(input) {
@@ -4129,6 +4145,63 @@ function refine$1(fn, _params = {}) {
4129
4145
  function superRefine$1(fn, params) {
4130
4146
  return /* @__PURE__ */ _superRefine$1(fn, params);
4131
4147
  }
4148
+ `${JSON.stringify({ render: {
4149
+ elements: {
4150
+ body: {
4151
+ props: { text: { $item: "body" } },
4152
+ type: "Text"
4153
+ },
4154
+ card: {
4155
+ children: ["body"],
4156
+ props: { title: { $item: "title" } },
4157
+ type: "Card"
4158
+ },
4159
+ detail: {
4160
+ children: ["card"],
4161
+ props: {
4162
+ className: "mx-auto max-w-md p-8",
4163
+ direction: "vertical",
4164
+ gap: "md"
4165
+ },
4166
+ repeat: {
4167
+ key: "path",
4168
+ statePath: "/items"
4169
+ },
4170
+ type: "Stack"
4171
+ }
4172
+ },
4173
+ root: "detail"
4174
+ } }, null, " ")}`, `${JSON.stringify({ render: {
4175
+ elements: {
4176
+ card: {
4177
+ props: { title: { $item: "title" } },
4178
+ type: "Card"
4179
+ },
4180
+ list: {
4181
+ children: ["row"],
4182
+ props: {
4183
+ className: "mx-auto max-w-md p-8",
4184
+ direction: "vertical",
4185
+ gap: "md"
4186
+ },
4187
+ repeat: {
4188
+ key: "path",
4189
+ statePath: "/items"
4190
+ },
4191
+ type: "Stack"
4192
+ },
4193
+ row: {
4194
+ children: ["card"],
4195
+ on: { press: {
4196
+ action: "navigate",
4197
+ params: { path: { $template: "${path}" } }
4198
+ } },
4199
+ props: { className: null },
4200
+ type: "Pressable"
4201
+ }
4202
+ },
4203
+ root: "list"
4204
+ } }, null, " ")}`;
4132
4205
  const segmentSchema = string$4().min(1, "a repoId segment must be non-empty").refine((s) => s !== "." && s !== ".." && !s.includes("/"), { message: "a repoId segment must not be '.'/'..' or contain '/'" });
4133
4206
  const sessionMetaSchema = object$3({
4134
4207
  created: string$4().nullable(),
@@ -30553,9 +30626,7 @@ async function inspectWorkingTree(repo) {
30553
30626
  paths: parsePorcelainV1Z(result.stdout)
30554
30627
  };
30555
30628
  }
30556
- async function assertSynthesizerTransactionReady(repo) {
30557
- const branch = await inspectBranchReadiness(repo);
30558
- if (branch.kind !== "ready" && branch.kind !== "ready_empty") throw new Error(formatBranchReadinessError(repo, branch));
30629
+ async function assertCleanWorkingTree(repo) {
30559
30630
  const tree = await inspectWorkingTree(repo);
30560
30631
  if (!tree.clean) throw new Error(formatDirtyTreeError(repo, tree.paths));
30561
30632
  }
@@ -30572,10 +30643,15 @@ async function fastForwardRoot(repo) {
30572
30643
  if (remoteSha === null) throw new Error(`Remote ${repo.branch} did not exist after 'git fetch origin ${repo.branch}'; nothing to fast-forward.`);
30573
30644
  if (fromSha === remoteSha) return {
30574
30645
  from: fromSha,
30646
+ kind: "fast_forwarded",
30575
30647
  to: remoteSha
30576
30648
  };
30577
30649
  if (fromSha !== null) {
30578
- if (!await isAncestorRef(repo, fromSha, remoteSha)) throw new Error(`Local HEAD ${fromSha} is not an ancestor of ${repo.branch} (${remoteSha}); fast-forward refused (no merge, rebase, or reset).`);
30650
+ if (!await isAncestorRef(repo, fromSha, remoteSha)) return {
30651
+ kind: "diverged",
30652
+ localSha: fromSha,
30653
+ remoteSha
30654
+ };
30579
30655
  await runGit(repo, [
30580
30656
  "merge",
30581
30657
  "--ff-only",
@@ -30600,6 +30676,7 @@ async function fastForwardRoot(repo) {
30600
30676
  }
30601
30677
  return {
30602
30678
  from: fromSha,
30679
+ kind: "fast_forwarded",
30603
30680
  to: remoteSha
30604
30681
  };
30605
30682
  }
@@ -30625,11 +30702,39 @@ async function commitRootReset(repo, input) {
30625
30702
  return await createCommit(repo, buildRootResetCommitMessage(input));
30626
30703
  }
30627
30704
  async function pushToOrigin(repo) {
30628
- await runGit(repo, [
30705
+ const result = await runGit(repo, [
30629
30706
  "push",
30630
30707
  "origin",
30631
30708
  `HEAD:${repo.branch}`
30709
+ ], {
30710
+ auth: true,
30711
+ throwOnNonZero: false
30712
+ });
30713
+ if (result.exitCode === 0) return "pushed";
30714
+ if (classifyPushFailure(result.stderr) === "rejected") return "rejected";
30715
+ throw new Error(`git push origin HEAD:${repo.branch} (exit ${result.exitCode}) in ${repo.rootDir}\n${result.stderr.trim()}`);
30716
+ }
30717
+ function classifyPushFailure(stderr) {
30718
+ return /\[(rejected|remote rejected)\]/.test(stderr) ? "rejected" : "transport";
30719
+ }
30720
+ async function discardToOrigin(repo) {
30721
+ const discardedSha = await readLocalHeadSha(repo);
30722
+ await runGit(repo, [
30723
+ "fetch",
30724
+ "origin",
30725
+ repo.branch
30632
30726
  ], { auth: true });
30727
+ const originSha = await readFetchHeadSha(repo);
30728
+ if (originSha === null) throw new Error(`Remote ${repo.branch} did not exist after 'git fetch origin ${repo.branch}'; nothing to discard to.`);
30729
+ await runGit(repo, [
30730
+ "reset",
30731
+ "--hard",
30732
+ originSha
30733
+ ]);
30734
+ return {
30735
+ discardedSha,
30736
+ originSha
30737
+ };
30633
30738
  }
30634
30739
  async function runGit(repo, args, options = {}) {
30635
30740
  const throwOnNonZero = options.throwOnNonZero ?? true;
@@ -30778,17 +30883,6 @@ function parsePorcelainV1Z(stdout) {
30778
30883
  }
30779
30884
  return paths;
30780
30885
  }
30781
- function formatBranchReadinessError(repo, branch) {
30782
- const prefix = `Engine root '${repo.rootDir}' is not transaction-ready (branch state)`;
30783
- switch (branch.kind) {
30784
- case "no_origin": return `${prefix}: 'origin' remote is not configured. Provisioning must configure origin.`;
30785
- case "local_unborn_remote_has_main": return `${prefix}: local checkout has no commits but origin/${repo.branch} exists at ${branch.remoteSha}. Run 'ctxe repair' to fast-forward.`;
30786
- case "local_head_without_remote_main": return `${prefix}: local HEAD is at ${branch.localSha} but origin/${repo.branch} does not exist. Operator must reconcile.`;
30787
- case "remote_mismatch": return `${prefix}: local HEAD ${branch.localSha} does not match origin/${repo.branch} ${branch.remoteSha}. Run 'ctxe repair' if local can fast-forward; otherwise reconcile manually.`;
30788
- case "ready":
30789
- case "ready_empty": return `${prefix}: state '${branch.kind}' is unexpectedly being treated as not ready (this is a bug).`;
30790
- }
30791
- }
30792
30886
  function formatDirtyTreeError(repo, paths) {
30793
30887
  const list = formatWorkingTreePaths(paths);
30794
30888
  return `Engine root '${repo.rootDir}' has uncommitted or untracked changes:\n${list}`;
@@ -30861,11 +30955,11 @@ function branchIssueFor(branch) {
30861
30955
  };
30862
30956
  case "local_head_without_remote_main": return {
30863
30957
  code: "local_head_without_remote_main",
30864
- message: `Local HEAD is at ${branch.localSha} but origin/main does not exist. Operator must reconcile manually.`
30958
+ message: `Local HEAD is at ${branch.localSha} but origin/main does not exist. Run 'ctxe repair' (publishes the local commits, or discards them if origin was created meanwhile).`
30865
30959
  };
30866
30960
  case "remote_mismatch": return {
30867
30961
  code: "remote_mismatch",
30868
- message: `Local HEAD ${branch.localSha} does not match origin/main ${branch.remoteSha}. If local is behind, run 'ctxe repair'; otherwise reconcile manually.`
30962
+ message: `Local HEAD ${branch.localSha} does not match origin/main ${branch.remoteSha}. Run 'ctxe repair' (fast-forwards when behind; publishes or discards own commits when ahead/diverged).`
30869
30963
  };
30870
30964
  }
30871
30965
  }
@@ -30884,7 +30978,8 @@ _enum([
30884
30978
  "success",
30885
30979
  "failed",
30886
30980
  "timed_out",
30887
- "rate_limited"
30981
+ "rate_limited",
30982
+ "stale"
30888
30983
  ]);
30889
30984
  const runStatusSchema = _enum([
30890
30985
  "starting",
@@ -30893,6 +30988,7 @@ const runStatusSchema = _enum([
30893
30988
  "failed",
30894
30989
  "timed_out",
30895
30990
  "rate_limited",
30991
+ "stale",
30896
30992
  "interrupted"
30897
30993
  ]);
30898
30994
  const claudeResultSchema = strictObject({
@@ -31058,23 +31154,35 @@ function compareRunRecordEntries(left, right) {
31058
31154
  if (timeCompare !== 0) return timeCompare;
31059
31155
  return right.runId.localeCompare(left.runId);
31060
31156
  }
31061
- async function runRootFastForward(repo) {
31157
+ async function runRootReconcile(repo) {
31062
31158
  await assertGitCheckout(repo);
31063
31159
  const branch = await inspectBranchReadiness(repo);
31064
31160
  const tree = await inspectWorkingTree(repo);
31065
31161
  if (branch.kind === "no_origin") throw new Error("RootRepair requires 'origin' to be configured. Provisioning must add origin before repair.");
31066
- if (branch.kind === "local_head_without_remote_main") throw new Error(`RootRepair refuses to act: local HEAD is at ${branch.localSha} but origin/${repo.branch} does not exist. Operator must reconcile manually.`);
31067
- const needsFastForward = branch.kind === "local_unborn_remote_has_main" || branch.kind === "remote_mismatch";
31068
- if (needsFastForward && !tree.clean) throw new Error(formatCombinedRepairError(repo, branch, tree));
31069
- if (needsFastForward) return {
31070
- kind: "fast_forward",
31071
- ...await fastForwardRoot(repo)
31162
+ if (branch.kind === "ready" || branch.kind === "ready_empty") return { kind: "no_op" };
31163
+ if (!tree.clean) throw new Error(formatCombinedRepairError(repo, branch, tree));
31164
+ if (branch.kind === "local_head_without_remote_main") return await publishOrDiscard(repo, branch.localSha);
31165
+ const ff = await fastForwardRoot(repo);
31166
+ if (ff.kind === "fast_forwarded") return {
31167
+ from: ff.from,
31168
+ kind: "fast_forwarded",
31169
+ to: ff.to
31170
+ };
31171
+ return await publishOrDiscard(repo, ff.localSha);
31172
+ }
31173
+ async function publishOrDiscard(repo, localSha) {
31174
+ if (await pushToOrigin(repo) === "pushed") return {
31175
+ kind: "published",
31176
+ sha: localSha
31177
+ };
31178
+ return {
31179
+ kind: "discarded_to_origin",
31180
+ ...await discardToOrigin(repo)
31072
31181
  };
31073
- return { kind: "no_op" };
31074
31182
  }
31075
31183
  async function runRootRepair(repo) {
31076
- const fastForward = await runRootFastForward(repo);
31077
- if (fastForward.kind === "fast_forward") return fastForward;
31184
+ const reconciled = await runRootReconcile(repo);
31185
+ if (reconciled.kind !== "no_op") return reconciled;
31078
31186
  if (!(await inspectWorkingTree(repo)).clean) return await runDirtyRootRepair(repo);
31079
31187
  return { kind: "no_op" };
31080
31188
  }
@@ -31090,7 +31198,14 @@ async function runDirtyRootRepair(repo) {
31090
31198
  interruptedRunIds,
31091
31199
  repairId: v7()
31092
31200
  });
31093
- await pushToOrigin(repo);
31201
+ if (await pushToOrigin(repo) === "rejected") {
31202
+ await discardToOrigin(repo);
31203
+ return {
31204
+ commit: null,
31205
+ interruptedRunIds,
31206
+ kind: "dirty_root_repair"
31207
+ };
31208
+ }
31094
31209
  return {
31095
31210
  commit: { sha },
31096
31211
  interruptedRunIds,
@@ -31100,7 +31215,7 @@ async function runDirtyRootRepair(repo) {
31100
31215
  function formatCombinedRepairError(repo, branch, tree) {
31101
31216
  const dirtyPaths = tree.clean ? "(clean)" : formatWorkingTreePaths(tree.paths);
31102
31217
  return [
31103
- "RootRepair refuses to combine branch fast-forward with dirty-root repair in v1.",
31218
+ "RootRepair refuses to combine branch reconcile with dirty-root repair in v1.",
31104
31219
  `Branch: ${branch.kind === "local_unborn_remote_has_main" ? `local checkout is unborn but origin/${repo.branch} exists` : branch.kind === "remote_mismatch" ? `local HEAD does not match origin/${repo.branch}` : `branch state is '${branch.kind}'`}.`,
31105
31220
  "Dirty paths:",
31106
31221
  dirtyPaths,
@@ -31250,22 +31365,6 @@ function fromParseError(error) {
31250
31365
  sourcePath: error.sourcePath
31251
31366
  };
31252
31367
  }
31253
- const MICROSANDBOX_HOST_ALIAS = "host.microsandbox.internal";
31254
- const HOST_LOOPBACK_HOSTNAMES = new Set([
31255
- "localhost",
31256
- "127.0.0.1",
31257
- "0.0.0.0"
31258
- ]);
31259
- const IPV6_LOOPBACK_HOSTNAMES = new Set(["[::1]", "[::]"]);
31260
- function rewriteHostUrlForGuest(url) {
31261
- const parsed = new URL(url);
31262
- const hostname = parsed.hostname.toLowerCase();
31263
- if (HOST_LOOPBACK_HOSTNAMES.has(hostname) || IPV6_LOOPBACK_HOSTNAMES.has(hostname)) {
31264
- parsed.hostname = MICROSANDBOX_HOST_ALIAS;
31265
- return parsed.toString();
31266
- }
31267
- return url;
31268
- }
31269
31368
  function assembleGuestEnv(input) {
31270
31369
  return {
31271
31370
  ...input.contextEngineEnv,
@@ -31514,7 +31613,13 @@ async function finalizeSuccessfulSynthesizerTransaction(input) {
31514
31613
  await rollbackAfterTransactionCommitFailure(input.repo);
31515
31614
  throw commitError;
31516
31615
  }
31517
- await pushToOrigin(input.repo);
31616
+ if (await pushToOrigin(input.repo) === "rejected") {
31617
+ await discardToOrigin(input.repo);
31618
+ return {
31619
+ ...input.record,
31620
+ status: "stale"
31621
+ };
31622
+ }
31518
31623
  return input.record;
31519
31624
  }
31520
31625
  async function finalizeFailedSynthesizerTransaction(input) {
@@ -31526,7 +31631,7 @@ async function finalizeFailedSynthesizerTransaction(input) {
31526
31631
  synthesizerName: input.ctx.synthesizer.name,
31527
31632
  trigger: input.ctx.trigger
31528
31633
  });
31529
- await pushToOrigin(input.repo);
31634
+ if (await pushToOrigin(input.repo) === "rejected") await discardToOrigin(input.repo);
31530
31635
  return input.record;
31531
31636
  }
31532
31637
  function buildTerminalRecord(input) {
@@ -31602,8 +31707,8 @@ var Engine = class {
31602
31707
  try {
31603
31708
  let report = await runRootPreflight(this.repo);
31604
31709
  if (!report.ready) {
31605
- const repaired = await runRootFastForward(this.repo);
31606
- if (repaired.kind === "fast_forward") this.logger.info(`[engine] root was behind origin/${this.repo.branch} — fast-forwarded ${repaired.from ?? "(unborn)"} → ${repaired.to}`);
31710
+ const repaired = await runRootReconcile(this.repo);
31711
+ if (repaired.kind !== "no_op") this.logger.info(`[engine] startup reconcile: ${describeReconcile(repaired)}`);
31607
31712
  report = await runRootPreflight(this.repo);
31608
31713
  }
31609
31714
  if (!report.ready) throw new Error(formatPreflightFailure(this.repo.rootDir, report.issues));
@@ -31766,7 +31871,9 @@ var Engine = class {
31766
31871
  async runSynthesizerTransaction(request) {
31767
31872
  const releaseLock = await acquireTransactionLock(this.repo.rootDir);
31768
31873
  try {
31769
- await assertSynthesizerTransactionReady(this.repo);
31874
+ await assertCleanWorkingTree(this.repo);
31875
+ const reconciled = await runRootReconcile(this.repo);
31876
+ if (reconciled.kind !== "no_op") this.logger.info(`[engine] pre-run reconcile: ${describeReconcile(reconciled)}`);
31770
31877
  await this.refreshSynthesizers();
31771
31878
  const synthesizer = this.synthesizers.get(request.synthesizerName);
31772
31879
  if (!synthesizer) throw new Error(`Synthesizer '${request.synthesizerName}' was not found after refresh; no run record manufactured.`);
@@ -31851,6 +31958,14 @@ function sleepAbortable(ms, signal) {
31851
31958
  function formatPreflightFailure(rootDir, issues) {
31852
31959
  return `Engine root '${rootDir}' is not ready:\n${issues.map((issue) => ` [${issue.code}] ${issue.message}`).join("\n")}`;
31853
31960
  }
31961
+ function describeReconcile(result) {
31962
+ switch (result.kind) {
31963
+ case "no_op": return "no-op";
31964
+ case "fast_forwarded": return `fast-forwarded ${result.from ?? "(unborn)"} → ${result.to}`;
31965
+ case "published": return `published own unpushed commit ${result.sha}`;
31966
+ case "discarded_to_origin": return `discarded own commit ${result.discardedSha ?? "(none)"} to origin ${result.originSha} (someone else advanced)`;
31967
+ }
31968
+ }
31854
31969
  function assembleEngineStatus(input) {
31855
31970
  const observation = input.syncHorizon;
31856
31971
  const horizon = observation.kind === "captured" ? observation.horizon : null;
@@ -32220,7 +32335,7 @@ async function runRootReset(repo, options = {}) {
32220
32335
  });
32221
32336
  if ((await inspectWorkingTree(repo)).clean) return { kind: "no_op" };
32222
32337
  const { sha } = await commitRootReset(repo, { resetId: v7() });
32223
- await pushToOrigin(repo);
32338
+ if (await pushToOrigin(repo) === "rejected") throw new Error(`Reset commit ${sha} was not pushed: origin/${repo.branch} advanced during the reset (non-fast-forward). Nothing was reset on origin. Re-run 'ctxe reset' against the new head.`);
32224
32339
  return {
32225
32340
  commit: { sha },
32226
32341
  kind: "reset",
@@ -32397,6 +32512,19 @@ var ForbiddenError$1 = class extends BaseAPIError {
32397
32512
  this.name = "ForbiddenError";
32398
32513
  }
32399
32514
  };
32515
+ var NotFoundError$1 = class extends BaseAPIError {
32516
+ constructor(body, rawResponse) {
32517
+ super({
32518
+ message: "NotFoundError",
32519
+ statusCode: 404,
32520
+ body,
32521
+ rawResponse
32522
+ });
32523
+ Object.setPrototypeOf(this, new.target.prototype);
32524
+ if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
32525
+ this.name = "NotFoundError";
32526
+ }
32527
+ };
32400
32528
  function mergeHeaders$1(...headersArray) {
32401
32529
  const result = {};
32402
32530
  for (const [key, value] of headersArray.filter((headers) => headers != null).flatMap((headers) => Object.entries(headers))) {
@@ -33616,7 +33744,7 @@ function createIdentitySchemaCreator$1(schemaType, validate) {
33616
33744
  };
33617
33745
  };
33618
33746
  }
33619
- function enum_(values) {
33747
+ function enum_$1(values) {
33620
33748
  const validValues = new Set(values);
33621
33749
  return createIdentitySchemaCreator$1(SchemaType$1.ENUM, (value, { allowUnrecognizedEnumValues, breadcrumbsPrefix = [] } = {}) => {
33622
33750
  if (typeof value !== "string") return {
@@ -34182,7 +34310,7 @@ const _hasOwn$4 = Object.prototype.hasOwnProperty;
34182
34310
  function union(discriminant, union) {
34183
34311
  const rawDiscriminant = typeof discriminant === "string" ? discriminant : discriminant.rawDiscriminant;
34184
34312
  const parsedDiscriminant = typeof discriminant === "string" ? discriminant : discriminant.parsedDiscriminant;
34185
- const discriminantValueSchema = enum_(keys$1(union));
34313
+ const discriminantValueSchema = enum_$1(keys$1(union));
34186
34314
  const baseSchema = {
34187
34315
  parse: (raw, opts) => {
34188
34316
  return transformAndValidateUnion({
@@ -34435,7 +34563,7 @@ const Binding = object$1({
34435
34563
  updatedAt: property$1("updated_at", date$1())
34436
34564
  });
34437
34565
  const ListBindingsResponse = object$1({ bindings: list$1(Binding) });
34438
- const RunStatus = enum_([
34566
+ const RunStatus = enum_$1([
34439
34567
  "QUEUED",
34440
34568
  "NOT_STARTED",
34441
34569
  "MANAGED",
@@ -34484,7 +34612,7 @@ const BindingStateResponse = object$1({
34484
34612
  bindings: record(string$1(), BindingState),
34485
34613
  version: number$1()
34486
34614
  });
34487
- const DagsterAllPlanBindingMode = enum_(["dagster"]);
34615
+ const DagsterAllPlanBindingMode = enum_$1(["dagster"]);
34488
34616
  const DagsterAllPlanBinding = object$1({
34489
34617
  auth: BindingAuth,
34490
34618
  bindingId: property$1("binding_id", string$1()),
@@ -34666,6 +34794,62 @@ var BasesClient = class {
34666
34794
  }
34667
34795
  return handleNonStatusCodeError$1(_response.error, _response.rawResponse, "GET", "/base/bases/{base_id}");
34668
34796
  }
34797
+ /**
34798
+ * @param {BaseAPI.DeleteBaseRequest} request
34799
+ * @param {BasesClient.RequestOptions} requestOptions - Request-specific configuration.
34800
+ *
34801
+ * @throws {@link BaseAPI.ForbiddenError}
34802
+ * @throws {@link BaseAPI.NotFoundError}
34803
+ *
34804
+ * @example
34805
+ * await client.bases.deleteBase({
34806
+ * baseId: "base_id"
34807
+ * })
34808
+ */
34809
+ deleteBase(request, requestOptions) {
34810
+ return HttpResponsePromise$1.fromPromise(this.__deleteBase(request, requestOptions));
34811
+ }
34812
+ async __deleteBase(request, requestOptions) {
34813
+ const { baseId } = request;
34814
+ const _headers = mergeHeaders$1(this._options?.headers, requestOptions?.headers);
34815
+ const _response = await fetcher$1({
34816
+ url: join$1(await Supplier$1.get(this._options.baseUrl) ?? await Supplier$1.get(this._options.environment), `base/bases/${encodePathParam$1(baseId)}`),
34817
+ method: "DELETE",
34818
+ headers: _headers,
34819
+ queryString: queryBuilder$1().mergeAdditional(requestOptions?.queryParams).build(),
34820
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
34821
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
34822
+ abortSignal: requestOptions?.abortSignal,
34823
+ fetchFn: this._options?.fetch,
34824
+ logging: this._options.logging
34825
+ });
34826
+ if (_response.ok) return {
34827
+ data: void 0,
34828
+ rawResponse: _response.rawResponse
34829
+ };
34830
+ if (_response.error.reason === "status-code") switch (_response.error.statusCode) {
34831
+ case 403: throw new ForbiddenError$1(Error_$1.parseOrThrow(_response.error.body, {
34832
+ unrecognizedObjectKeys: "passthrough",
34833
+ allowUnrecognizedUnionMembers: true,
34834
+ allowUnrecognizedEnumValues: true,
34835
+ skipValidation: true,
34836
+ breadcrumbsPrefix: ["response"]
34837
+ }), _response.rawResponse);
34838
+ case 404: throw new NotFoundError$1(Error_$1.parseOrThrow(_response.error.body, {
34839
+ unrecognizedObjectKeys: "passthrough",
34840
+ allowUnrecognizedUnionMembers: true,
34841
+ allowUnrecognizedEnumValues: true,
34842
+ skipValidation: true,
34843
+ breadcrumbsPrefix: ["response"]
34844
+ }), _response.rawResponse);
34845
+ default: throw new BaseAPIError({
34846
+ statusCode: _response.error.statusCode,
34847
+ body: _response.error.body,
34848
+ rawResponse: _response.rawResponse
34849
+ });
34850
+ }
34851
+ return handleNonStatusCodeError$1(_response.error, _response.rawResponse, "DELETE", "/base/bases/{base_id}");
34852
+ }
34669
34853
  };
34670
34854
  var BindingPlanClient = class {
34671
34855
  _options;
@@ -35230,6 +35414,19 @@ var ForbiddenError = class extends SlateAPIError {
35230
35414
  this.name = "ForbiddenError";
35231
35415
  }
35232
35416
  };
35417
+ var NotFoundError = class extends SlateAPIError {
35418
+ constructor(body, rawResponse) {
35419
+ super({
35420
+ message: "NotFoundError",
35421
+ statusCode: 404,
35422
+ body,
35423
+ rawResponse
35424
+ });
35425
+ Object.setPrototypeOf(this, new.target.prototype);
35426
+ if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
35427
+ this.name = "NotFoundError";
35428
+ }
35429
+ };
35233
35430
  function mergeHeaders(...headersArray) {
35234
35431
  const result = {};
35235
35432
  for (const [key, value] of headersArray.filter((headers) => headers != null).flatMap((headers) => Object.entries(headers))) {
@@ -36449,6 +36646,29 @@ function createIdentitySchemaCreator(schemaType, validate) {
36449
36646
  };
36450
36647
  };
36451
36648
  }
36649
+ function enum_(values) {
36650
+ const validValues = new Set(values);
36651
+ return createIdentitySchemaCreator(SchemaType.ENUM, (value, { allowUnrecognizedEnumValues, breadcrumbsPrefix = [] } = {}) => {
36652
+ if (typeof value !== "string") return {
36653
+ ok: false,
36654
+ errors: [{
36655
+ path: breadcrumbsPrefix,
36656
+ message: getErrorMessageForIncorrectType(value, "string")
36657
+ }]
36658
+ };
36659
+ if (!validValues.has(value) && !allowUnrecognizedEnumValues) return {
36660
+ ok: false,
36661
+ errors: [{
36662
+ path: breadcrumbsPrefix,
36663
+ message: getErrorMessageForIncorrectType(value, "enum")
36664
+ }]
36665
+ };
36666
+ return {
36667
+ ok: true,
36668
+ value
36669
+ };
36670
+ })();
36671
+ }
36452
36672
  function entries(object) {
36453
36673
  return Object.entries(object);
36454
36674
  }
@@ -37023,6 +37243,8 @@ const CreateWorkspaceInput = object({
37023
37243
  synthesizerImage: property("synthesizer_image", string().optional()),
37024
37244
  tick: string().optional()
37025
37245
  });
37246
+ const DeleteWorkspaceRequestDeleteBases = enum_(["true", "false"]);
37247
+ const DeleteWorkspaceRequestDeleteRepos = enum_(["true", "false"]);
37026
37248
  const BridgePlan = object({
37027
37249
  baseIds: property("base_ids", list(string())),
37028
37250
  claudeOauthToken: property("claude_oauth_token", string().nullable()),
@@ -37464,6 +37686,72 @@ var WorkspacesClient = class {
37464
37686
  }
37465
37687
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/slate/workspaces");
37466
37688
  }
37689
+ /**
37690
+ * @param {SlateAPI.DeleteWorkspaceRequest} request
37691
+ * @param {WorkspacesClient.RequestOptions} requestOptions - Request-specific configuration.
37692
+ *
37693
+ * @throws {@link SlateAPI.ForbiddenError}
37694
+ * @throws {@link SlateAPI.NotFoundError}
37695
+ *
37696
+ * @example
37697
+ * await client.workspaces.deleteWorkspace({
37698
+ * workspaceId: "workspace_id"
37699
+ * })
37700
+ */
37701
+ deleteWorkspace(request, requestOptions) {
37702
+ return HttpResponsePromise.fromPromise(this.__deleteWorkspace(request, requestOptions));
37703
+ }
37704
+ async __deleteWorkspace(request, requestOptions) {
37705
+ const { workspaceId, deleteBases, deleteRepos } = request;
37706
+ const _queryParams = {
37707
+ delete_bases: deleteBases != null ? DeleteWorkspaceRequestDeleteBases.jsonOrThrow(deleteBases, {
37708
+ unrecognizedObjectKeys: "strip",
37709
+ omitUndefined: true
37710
+ }) : void 0,
37711
+ delete_repos: deleteRepos != null ? DeleteWorkspaceRequestDeleteRepos.jsonOrThrow(deleteRepos, {
37712
+ unrecognizedObjectKeys: "strip",
37713
+ omitUndefined: true
37714
+ }) : void 0
37715
+ };
37716
+ const _headers = mergeHeaders(this._options?.headers, requestOptions?.headers);
37717
+ const _response = await fetcher({
37718
+ url: join(await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment), `slate/workspaces/${encodePathParam(workspaceId)}`),
37719
+ method: "DELETE",
37720
+ headers: _headers,
37721
+ queryString: queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
37722
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
37723
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
37724
+ abortSignal: requestOptions?.abortSignal,
37725
+ fetchFn: this._options?.fetch,
37726
+ logging: this._options.logging
37727
+ });
37728
+ if (_response.ok) return {
37729
+ data: void 0,
37730
+ rawResponse: _response.rawResponse
37731
+ };
37732
+ if (_response.error.reason === "status-code") switch (_response.error.statusCode) {
37733
+ case 403: throw new ForbiddenError(Error_.parseOrThrow(_response.error.body, {
37734
+ unrecognizedObjectKeys: "passthrough",
37735
+ allowUnrecognizedUnionMembers: true,
37736
+ allowUnrecognizedEnumValues: true,
37737
+ skipValidation: true,
37738
+ breadcrumbsPrefix: ["response"]
37739
+ }), _response.rawResponse);
37740
+ case 404: throw new NotFoundError(Error_.parseOrThrow(_response.error.body, {
37741
+ unrecognizedObjectKeys: "passthrough",
37742
+ allowUnrecognizedUnionMembers: true,
37743
+ allowUnrecognizedEnumValues: true,
37744
+ skipValidation: true,
37745
+ breadcrumbsPrefix: ["response"]
37746
+ }), _response.rawResponse);
37747
+ default: throw new SlateAPIError({
37748
+ statusCode: _response.error.statusCode,
37749
+ body: _response.error.body,
37750
+ rawResponse: _response.rawResponse
37751
+ });
37752
+ }
37753
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "DELETE", "/slate/workspaces/{workspace_id}");
37754
+ }
37467
37755
  };
37468
37756
  var SlateAPIClient = class {
37469
37757
  _options;
@@ -38586,7 +38874,7 @@ function createProgram() {
38586
38874
  program.command("preflight").description("Report whether the ContextEngine root is ready to run. Validation-only; never mutates the checkout. Exits non-zero when not ready.").action(async function() {
38587
38875
  await runPreflightCommand(resolveRepoContext(this));
38588
38876
  });
38589
- program.command("repair").description("Explicit out-of-band root repair: safe fast-forward when clean and stale, or dirty-root rollback that preserves .engine/runs/**. Refuses local-ahead state, divergence, and the combined stale-plus-dirty case.").action(async function() {
38877
+ program.command("repair").description("Explicit out-of-band root repair: reconciles the root against origin (fast-forward when behind; publish own unpushed commits, or discard them to origin when the push is rejected) and rolls back a dirty tree preserving .engine/runs/**.").action(async function() {
38590
38878
  await runRepairCommand(resolveRepoContext(this));
38591
38879
  });
38592
38880
  program.command("reset").option("--yes", "Execute the reset (delete cursors + wipe synthesized content, then commit). Without it, prints the plan and exits without mutating.").option("--force", "Reset even when the root is not preflight-ready (e.g. a dirty working tree). Use with care; normally you commit authored config or run 'ctxe repair' first.").description("Reset the whole workspace to a clean pre-synthesis state so it can be rebuilt from scratch: delete every synthesizer cursor (the next run bootstraps from the configured oldestConsideredPoint) and wipe all synthesized content under output/ except the authored types/ and views/, in one commit. Whole-workspace by design — output/ is not partitioned by synthesizer. Preserves .engine/runs/**. Default is a dry run; pass --yes to execute, then rebuild with 'ctxe backfill <synthesizer>' or 'ctxe daemon start'.").action(async function(options) {
@@ -38646,4 +38934,4 @@ runCli().catch((error) => {
38646
38934
  //#endregion
38647
38935
  export { createProgram, resolveRepoContext, resolveRuntimePaths, runCli };
38648
38936
  //# sourceMappingURL=cli.mjs.map
38649
- //# debugId=6317e92d-f910-5336-9f6a-2445ebdf6ed8
38937
+ //# debugId=507e416d-f409-5878-9327-a3aaeaedfd78