@remixhq/claude-plugin 0.1.16 → 0.1.17

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.
@@ -7795,7 +7795,7 @@ function summarizeUnifiedDiff(diff) {
7795
7795
  return { changedFilesCount, insertions, deletions };
7796
7796
  }
7797
7797
 
7798
- // node_modules/@remixhq/core/dist/chunk-4L3ZBZUQ.js
7798
+ // node_modules/@remixhq/core/dist/chunk-IXWQWFYT.js
7799
7799
  var import_promises13 = __toESM(require("fs/promises"), 1);
7800
7800
  var import_path2 = __toESM(require("path"), 1);
7801
7801
  var import_promises14 = __toESM(require("fs/promises"), 1);
@@ -7817,7 +7817,8 @@ function buildBindingFileV3(params) {
7817
7817
  repoFingerprint: params.repoFingerprint,
7818
7818
  remoteUrl: params.remoteUrl,
7819
7819
  defaultBranch: params.defaultBranch,
7820
- branchBindings: params.branchBindings
7820
+ branchBindings: params.branchBindings,
7821
+ ...params.explicitRootBinding ? { explicitRootBinding: params.explicitRootBinding } : {}
7821
7822
  };
7822
7823
  }
7823
7824
  function normalizeBranchName(value) {
@@ -7836,7 +7837,7 @@ function normalizeBranchBinding(value) {
7836
7837
  upstreamAppId: value.upstreamAppId,
7837
7838
  threadId: value.threadId ?? null,
7838
7839
  laneId: value.laneId ?? null,
7839
- bindingMode: value.bindingMode === "legacy" ? "legacy" : "lane"
7840
+ bindingMode: value.bindingMode === "legacy" ? "legacy" : value.bindingMode === "explicit_root" ? "explicit_root" : "lane"
7840
7841
  };
7841
7842
  }
7842
7843
  function buildResolvedBinding(params) {
@@ -7910,6 +7911,7 @@ async function readCollabBindingState(repoRoot, options) {
7910
7911
  defaultBranch: migratedFile.defaultBranch,
7911
7912
  currentBranch,
7912
7913
  branchBindings: migratedFile.branchBindings,
7914
+ explicitRootBinding: null,
7913
7915
  binding: buildResolvedBinding({
7914
7916
  fallbackProjectId: projectId,
7915
7917
  repoFingerprint: migratedFile.repoFingerprint,
@@ -7953,7 +7955,22 @@ async function readCollabBindingState(repoRoot, options) {
7953
7955
  };
7954
7956
  shouldPersistNormalizedBranchBindings = true;
7955
7957
  }
7956
- if (persist && ("explicitBinding" in file || shouldPersistNormalizedBranchBindings || parsed.schemaVersion === 2)) {
7958
+ let explicitRootBinding = normalizeBranchBinding(file.explicitRootBinding ?? null);
7959
+ if (explicitRootBinding && !explicitRootBinding.projectId && legacyProjectId) {
7960
+ explicitRootBinding = {
7961
+ ...explicitRootBinding,
7962
+ projectId: legacyProjectId
7963
+ };
7964
+ shouldPersistNormalizedBranchBindings = true;
7965
+ }
7966
+ if (explicitRootBinding && explicitRootBinding.bindingMode !== "explicit_root") {
7967
+ explicitRootBinding = {
7968
+ ...explicitRootBinding,
7969
+ bindingMode: "explicit_root"
7970
+ };
7971
+ shouldPersistNormalizedBranchBindings = true;
7972
+ }
7973
+ if (persist && ("explicitBinding" in file || "explicitRootBinding" in file || shouldPersistNormalizedBranchBindings || parsed.schemaVersion === 2)) {
7957
7974
  try {
7958
7975
  await writeJsonAtomic(
7959
7976
  filePath,
@@ -7961,7 +7978,8 @@ async function readCollabBindingState(repoRoot, options) {
7961
7978
  repoFingerprint: file.repoFingerprint ?? null,
7962
7979
  remoteUrl: file.remoteUrl ?? null,
7963
7980
  defaultBranch: file.defaultBranch ?? null,
7964
- branchBindings
7981
+ branchBindings,
7982
+ explicitRootBinding
7965
7983
  })
7966
7984
  );
7967
7985
  } catch {
@@ -7972,8 +7990,23 @@ async function readCollabBindingState(repoRoot, options) {
7972
7990
  branchBindings,
7973
7991
  currentBranch: resolvedBranch,
7974
7992
  defaultBranch: normalizeBranchName(file.defaultBranch),
7975
- legacyProjectId
7993
+ legacyProjectId: explicitRootBinding?.projectId ?? legacyProjectId
7976
7994
  });
7995
+ const resolvedBinding = buildResolvedBinding({
7996
+ fallbackProjectId,
7997
+ repoFingerprint: file.repoFingerprint ?? null,
7998
+ remoteUrl: file.remoteUrl ?? null,
7999
+ defaultBranch: file.defaultBranch ?? null,
8000
+ branchName: resolvedBranch,
8001
+ binding: resolvedBranch ? branchBindings[resolvedBranch] ?? null : null
8002
+ }) ?? (resolvedBranch && resolvedBranch === normalizeBranchName(file.defaultBranch) && explicitRootBinding ? buildResolvedBinding({
8003
+ fallbackProjectId,
8004
+ repoFingerprint: file.repoFingerprint ?? null,
8005
+ remoteUrl: file.remoteUrl ?? null,
8006
+ defaultBranch: file.defaultBranch ?? null,
8007
+ branchName: normalizeBranchName(file.defaultBranch),
8008
+ binding: explicitRootBinding
8009
+ }) : null);
7977
8010
  return {
7978
8011
  schemaVersion: parsed.schemaVersion,
7979
8012
  projectId: fallbackProjectId,
@@ -7982,14 +8015,15 @@ async function readCollabBindingState(repoRoot, options) {
7982
8015
  defaultBranch: file.defaultBranch ?? null,
7983
8016
  currentBranch,
7984
8017
  branchBindings,
7985
- binding: buildResolvedBinding({
8018
+ explicitRootBinding: buildResolvedBinding({
7986
8019
  fallbackProjectId,
7987
8020
  repoFingerprint: file.repoFingerprint ?? null,
7988
8021
  remoteUrl: file.remoteUrl ?? null,
7989
8022
  defaultBranch: file.defaultBranch ?? null,
7990
- branchName: resolvedBranch,
7991
- binding: resolvedBranch ? branchBindings[resolvedBranch] ?? null : null
7992
- })
8023
+ branchName: normalizeBranchName(file.defaultBranch),
8024
+ binding: explicitRootBinding
8025
+ }),
8026
+ binding: resolvedBinding
7993
8027
  };
7994
8028
  } catch {
7995
8029
  return null;
@@ -8013,13 +8047,25 @@ async function writeCollabBinding(repoRoot, binding) {
8013
8047
  laneId: binding.laneId ?? null,
8014
8048
  bindingMode: binding.bindingMode ?? "lane"
8015
8049
  };
8050
+ const explicitRootBinding = binding.bindingMode === "explicit_root" ? {
8051
+ ...branchBindings[branchName],
8052
+ bindingMode: "explicit_root"
8053
+ } : existing?.explicitRootBinding ? {
8054
+ projectId: existing.explicitRootBinding.projectId,
8055
+ currentAppId: existing.explicitRootBinding.currentAppId,
8056
+ upstreamAppId: existing.explicitRootBinding.upstreamAppId,
8057
+ threadId: existing.explicitRootBinding.threadId,
8058
+ laneId: existing.explicitRootBinding.laneId,
8059
+ bindingMode: "explicit_root"
8060
+ } : null;
8016
8061
  await writeJsonAtomic(
8017
8062
  filePath,
8018
8063
  buildBindingFileV3({
8019
8064
  repoFingerprint: binding.repoFingerprint ?? null,
8020
8065
  remoteUrl: binding.remoteUrl ?? null,
8021
8066
  defaultBranch: binding.defaultBranch ?? null,
8022
- branchBindings
8067
+ branchBindings,
8068
+ explicitRootBinding
8023
8069
  })
8024
8070
  );
8025
8071
  return filePath;
@@ -8157,6 +8203,10 @@ function normalizeBranchName2(value) {
8157
8203
  }
8158
8204
  function buildBindingFromLane(state, lane) {
8159
8205
  if (!lane.currentAppId || !lane.upstreamAppId) return null;
8206
+ const resolvedBranch = normalizeBranchName2(lane.branchName) ?? state.currentBranch ?? null;
8207
+ const resolvedDefaultBranch = normalizeBranchName2(lane.defaultBranch) ?? normalizeBranchName2(state.defaultBranch);
8208
+ const explicitRootProjectId = state.explicitRootBinding?.projectId ?? null;
8209
+ const bindingMode = explicitRootProjectId && lane.projectId === explicitRootProjectId && resolvedBranch && resolvedBranch === resolvedDefaultBranch ? "explicit_root" : "lane";
8160
8210
  return {
8161
8211
  schemaVersion: 3,
8162
8212
  projectId: lane.projectId ?? state.projectId,
@@ -8167,8 +8217,8 @@ function buildBindingFromLane(state, lane) {
8167
8217
  remoteUrl: lane.remoteUrl ?? state.remoteUrl ?? null,
8168
8218
  defaultBranch: lane.defaultBranch ?? state.defaultBranch ?? null,
8169
8219
  laneId: lane.laneId ?? null,
8170
- branchName: lane.branchName ?? state.currentBranch ?? null,
8171
- bindingMode: "lane"
8220
+ branchName: resolvedBranch,
8221
+ bindingMode
8172
8222
  };
8173
8223
  }
8174
8224
  function shouldPersistRemoteLaneMetadata(localBinding, lane) {
@@ -8197,6 +8247,16 @@ async function persistResolvedLane(repoRoot, binding) {
8197
8247
  });
8198
8248
  return readCollabBinding(repoRoot);
8199
8249
  }
8250
+ function buildAmbiguousResolution(params) {
8251
+ return {
8252
+ status: "ambiguous_family_selection",
8253
+ currentBranch: params.currentBranch,
8254
+ projectIds: Array.isArray(params.lane.projectIds) ? params.lane.projectIds.filter((value) => typeof value === "string" && value.trim().length > 0) : [],
8255
+ repoFingerprint: params.lane.repoFingerprint ?? params.state.repoFingerprint,
8256
+ remoteUrl: params.lane.remoteUrl ?? params.state.remoteUrl,
8257
+ defaultBranch: params.lane.defaultBranch ?? params.state.defaultBranch
8258
+ };
8259
+ }
8200
8260
  async function resolveActiveLaneBinding(params) {
8201
8261
  const state = await readCollabBindingState(params.repoRoot);
8202
8262
  if (!state) {
@@ -8219,13 +8279,16 @@ async function resolveActiveLaneBinding(params) {
8219
8279
  };
8220
8280
  }
8221
8281
  const laneResp2 = await params.api.resolveProjectLaneBinding({
8222
- projectId: localBinding.projectId ?? state.projectId ?? void 0,
8282
+ projectId: state.explicitRootBinding?.projectId ?? (requireRemoteLane ? void 0 : localBinding.projectId ?? state.projectId ?? void 0),
8223
8283
  repoFingerprint: state.repoFingerprint ?? void 0,
8224
8284
  remoteUrl: state.remoteUrl ?? void 0,
8225
8285
  defaultBranch: state.defaultBranch ?? void 0,
8226
8286
  branchName: currentBranch
8227
8287
  });
8228
8288
  const lane2 = unwrapResponseObject(laneResp2, "project lane binding");
8289
+ if (lane2.status === "ambiguous_family_selection") {
8290
+ return buildAmbiguousResolution({ state, currentBranch, lane: lane2 });
8291
+ }
8229
8292
  if (lane2.status === "resolved") {
8230
8293
  const resolvedBranch = normalizeBranchName2(lane2.branchName);
8231
8294
  const resolvedProjectId = lane2.projectId ?? state.projectId;
@@ -8268,12 +8331,12 @@ async function resolveActiveLaneBinding(params) {
8268
8331
  return {
8269
8332
  status: "missing_branch_binding",
8270
8333
  currentBranch,
8271
- projectId: state.projectId,
8272
- repoFingerprint: state.repoFingerprint,
8273
- remoteUrl: state.remoteUrl,
8274
- defaultBranch: state.defaultBranch,
8275
- upstreamAppId: localBinding.upstreamAppId ?? null,
8276
- threadId: localBinding.threadId ?? null
8334
+ projectId: lane2.projectId ?? state.projectId,
8335
+ repoFingerprint: lane2.repoFingerprint ?? state.repoFingerprint,
8336
+ remoteUrl: lane2.remoteUrl ?? state.remoteUrl,
8337
+ defaultBranch: lane2.defaultBranch ?? state.defaultBranch,
8338
+ upstreamAppId: lane2.upstreamAppId ?? localBinding.upstreamAppId ?? null,
8339
+ threadId: lane2.threadId ?? localBinding.threadId ?? null
8277
8340
  };
8278
8341
  }
8279
8342
  return {
@@ -8296,13 +8359,16 @@ async function resolveActiveLaneBinding(params) {
8296
8359
  };
8297
8360
  }
8298
8361
  const laneResp = await params.api.resolveProjectLaneBinding({
8299
- projectId: state.projectId ?? void 0,
8362
+ projectId: state.explicitRootBinding?.projectId ?? state.projectId ?? void 0,
8300
8363
  repoFingerprint: state.repoFingerprint ?? void 0,
8301
8364
  remoteUrl: state.remoteUrl ?? void 0,
8302
8365
  defaultBranch: state.defaultBranch ?? void 0,
8303
8366
  branchName: currentBranch
8304
8367
  });
8305
8368
  const lane = unwrapResponseObject(laneResp, "project lane binding");
8369
+ if (lane.status === "ambiguous_family_selection") {
8370
+ return buildAmbiguousResolution({ state, currentBranch, lane });
8371
+ }
8306
8372
  if (lane.status === "resolved") {
8307
8373
  const binding = buildBindingFromLane(state, lane);
8308
8374
  if (binding) {
@@ -8314,18 +8380,15 @@ async function resolveActiveLaneBinding(params) {
8314
8380
  };
8315
8381
  }
8316
8382
  }
8317
- if (lane.status === "binding_not_found") {
8318
- return { status: "not_bound", currentBranch };
8319
- }
8320
8383
  return {
8321
8384
  status: "missing_branch_binding",
8322
8385
  currentBranch,
8323
- projectId: lane.projectId ?? state.projectId,
8386
+ projectId: lane.projectId ?? state.explicitRootBinding?.projectId ?? state.projectId,
8324
8387
  repoFingerprint: lane.repoFingerprint ?? state.repoFingerprint,
8325
8388
  remoteUrl: lane.remoteUrl ?? state.remoteUrl,
8326
8389
  defaultBranch: lane.defaultBranch ?? state.defaultBranch,
8327
- upstreamAppId: lane.upstreamAppId ?? null,
8328
- threadId: lane.threadId ?? null
8390
+ upstreamAppId: lane.upstreamAppId ?? state.explicitRootBinding?.upstreamAppId ?? null,
8391
+ threadId: lane.threadId ?? state.explicitRootBinding?.threadId ?? null
8329
8392
  };
8330
8393
  }
8331
8394
  async function ensureActiveLaneBinding(params) {
@@ -8345,6 +8408,12 @@ async function ensureActiveLaneBinding(params) {
8345
8408
  hint: `Local app ${resolved.binding.currentAppId}; server app ${resolved.resolvedLane.currentAppId ?? "(unknown)"}. Repair the branch binding before running ${params.operation ?? "this command"}.`
8346
8409
  });
8347
8410
  }
8411
+ if (resolved.status === "ambiguous_family_selection") {
8412
+ throw new RemixError("Multiple canonical Remix families match this repository.", {
8413
+ exitCode: 2,
8414
+ hint: "This checkout is not specific enough to choose a single family for the current branch. Continue from a checkout already bound to the intended family, or run `remix collab init --force-new` to create a new canonical family."
8415
+ });
8416
+ }
8348
8417
  if (resolved.status === "not_bound") {
8349
8418
  return null;
8350
8419
  }
@@ -8419,6 +8488,24 @@ async function collabRecordingPreflight(params) {
8419
8488
  hint: `Current branch ${bindingResolution.currentBranch ?? "(detached)"} is not yet bound to a Remix lane.`
8420
8489
  };
8421
8490
  }
8491
+ if (bindingResolution.status === "ambiguous_family_selection") {
8492
+ return {
8493
+ status: "family_ambiguous",
8494
+ repoRoot,
8495
+ appId: null,
8496
+ currentBranch: bindingResolution.currentBranch,
8497
+ branchName: bindingResolution.currentBranch,
8498
+ headCommitHash: null,
8499
+ worktreeClean: false,
8500
+ syncStatus: null,
8501
+ syncTargetCommitHash: null,
8502
+ syncTargetCommitId: null,
8503
+ reconcileTargetHeadCommitHash: null,
8504
+ reconcileTargetHeadCommitId: null,
8505
+ warnings: [],
8506
+ hint: "Multiple canonical Remix families match this repository. Continue from a checkout already bound to the intended family, or run `remix collab init --force-new` to create a new canonical family."
8507
+ };
8508
+ }
8422
8509
  if (bindingResolution.status === "binding_conflict") {
8423
8510
  return {
8424
8511
  status: "metadata_conflict",
@@ -8928,6 +9015,12 @@ function assertSupportedRecordingPreflight(preflight) {
8928
9015
  hint: preflight.hint
8929
9016
  });
8930
9017
  }
9018
+ if (preflight.status === "family_ambiguous") {
9019
+ throw new RemixError("Multiple canonical Remix families match this repository.", {
9020
+ exitCode: 2,
9021
+ hint: preflight.hint
9022
+ });
9023
+ }
8931
9024
  if (preflight.status === "not_git_repo") {
8932
9025
  throw new RemixError(preflight.hint || "Not inside a git repository.", {
8933
9026
  exitCode: 2,
@@ -9243,6 +9336,12 @@ function assertSupportedRecordingPreflight2(preflight) {
9243
9336
  hint: preflight.hint
9244
9337
  });
9245
9338
  }
9339
+ if (preflight.status === "family_ambiguous") {
9340
+ throw new RemixError("Multiple canonical Remix families match this repository.", {
9341
+ exitCode: 2,
9342
+ hint: preflight.hint
9343
+ });
9344
+ }
9246
9345
  if (preflight.status === "not_git_repo") {
9247
9346
  throw new RemixError(preflight.hint || "Not inside a git repository.", {
9248
9347
  exitCode: 2,
@@ -34012,7 +34111,7 @@ async function clearPendingTurnState(sessionId) {
34012
34111
  // package.json
34013
34112
  var package_default = {
34014
34113
  name: "@remixhq/claude-plugin",
34015
- version: "0.1.16",
34114
+ version: "0.1.17",
34016
34115
  description: "Claude Code plugin for Remix collaboration workflows",
34017
34116
  homepage: "https://github.com/RemixDotOne/remix-claude-plugin",
34018
34117
  license: "MIT",
@@ -34043,8 +34142,8 @@ var package_default = {
34043
34142
  prepack: "npm run build"
34044
34143
  },
34045
34144
  dependencies: {
34046
- "@remixhq/core": "^0.1.11",
34047
- "@remixhq/mcp": "^0.1.11"
34145
+ "@remixhq/core": "^0.1.12",
34146
+ "@remixhq/mcp": "^0.1.12"
34048
34147
  },
34049
34148
  devDependencies: {
34050
34149
  "@types/node": "^25.4.0",
@@ -34260,6 +34359,12 @@ function getRecordingBlockedMessage(status, repoRoot) {
34260
34359
  hint: status.hint || `Run \`remix_collab_status\` for ${repoRoot}, then initialize or provision the current branch lane before recording work.`
34261
34360
  };
34262
34361
  }
34362
+ if (status.status === "family_ambiguous") {
34363
+ return {
34364
+ message: "Fallback Remix turn recording was blocked because multiple canonical Remix families match this repository and the current checkout does not identify which family to use.",
34365
+ hint: status.hint || `Continue from a checkout already bound to the intended family, or run \`remix_collab_init\` with forceNew=true for ${repoRoot} to create a new canonical family.`
34366
+ };
34367
+ }
34263
34368
  switch (status.status) {
34264
34369
  case "not_git_repo":
34265
34370
  return {