@meistrari/tela-cli 0.7.44 → 0.7.45

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/index.js +249 -59
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2267,12 +2267,14 @@ var require_git = __commonJS({
2267
2267
  Object.defineProperty(exports2, "__esModule", { value: true });
2268
2268
  exports2.buildGitSshCommand = buildGitSshCommand;
2269
2269
  exports2.isSshRemoteUrl = isSshRemoteUrl;
2270
+ exports2.getRemoteUrl = getRemoteUrl;
2270
2271
  exports2.findRepositoryRoot = findRepositoryRoot;
2271
2272
  exports2.getRepositoryRoot = getRepositoryRoot;
2272
2273
  exports2.assertGitRepository = assertGitRepository;
2273
2274
  exports2.cloneRepository = cloneRepository;
2274
2275
  exports2.getOriginUrl = getOriginUrl;
2275
2276
  exports2.fetchOrigin = fetchOrigin;
2277
+ exports2.fetchRemote = fetchRemote;
2276
2278
  exports2.fetchAllRemotes = fetchAllRemotes;
2277
2279
  exports2.getWorktreeStatus = getWorktreeStatus;
2278
2280
  exports2.isWorktreeDirty = isWorktreeDirty;
@@ -2281,6 +2283,10 @@ var require_git = __commonJS({
2281
2283
  exports2.unstageMatching = unstageMatching;
2282
2284
  exports2.getCurrentBranch = getCurrentBranch;
2283
2285
  exports2.getUpstreamBranch = getUpstreamBranch;
2286
+ exports2.getPushBranch = getPushBranch;
2287
+ exports2.refExists = refExists;
2288
+ exports2.getAheadBehind = getAheadBehind;
2289
+ exports2.getCommitCount = getCommitCount;
2284
2290
  exports2.pullCurrentBranch = pullCurrentBranch;
2285
2291
  exports2.pullDefaultBranch = pullDefaultBranch;
2286
2292
  exports2.getShortStatus = getShortStatus;
@@ -2348,6 +2354,9 @@ var require_git = __commonJS({
2348
2354
  }
2349
2355
  return result.stdout.trim() || null;
2350
2356
  }
2357
+ async function getRemoteUrl(cwd, remote) {
2358
+ return await getRemoteUrlInternal(cwd, remote);
2359
+ }
2351
2360
  async function remoteRequiresConfiguredSsh(cwd, remote) {
2352
2361
  const remoteUrl = await getRemoteUrlInternal(cwd, remote);
2353
2362
  return Boolean(remoteUrl && isSshRemoteUrl(remoteUrl));
@@ -2420,6 +2429,14 @@ var require_git = __commonJS({
2420
2429
  sshHostKeyPolicy: "accept-new"
2421
2430
  });
2422
2431
  }
2432
+ async function fetchRemote(cwd, remote, sshPrivateKeyPath) {
2433
+ await runGitCommand(["fetch", remote, "--prune"], {
2434
+ cwd,
2435
+ requireConfiguredSsh: await remoteRequiresConfiguredSsh(cwd, remote),
2436
+ sshPrivateKeyPath,
2437
+ sshHostKeyPolicy: "accept-new"
2438
+ });
2439
+ }
2423
2440
  async function fetchAllRemotes(cwd, sshPrivateKeyPath) {
2424
2441
  await runGitCommand(["fetch", "--all", "--prune"], {
2425
2442
  cwd,
@@ -2465,6 +2482,38 @@ var require_git = __commonJS({
2465
2482
  }
2466
2483
  return result.stdout.trim() || null;
2467
2484
  }
2485
+ async function getPushBranch(cwd) {
2486
+ const result = await runGitCommand(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{push}"], { cwd, allowFailure: true });
2487
+ if (result.exitCode !== 0) {
2488
+ return null;
2489
+ }
2490
+ return result.stdout.trim() || null;
2491
+ }
2492
+ async function refExists(cwd, ref) {
2493
+ const result = await runGitCommand(["rev-parse", "--verify", "--quiet", ref], {
2494
+ cwd,
2495
+ allowFailure: true
2496
+ });
2497
+ return result.exitCode === 0;
2498
+ }
2499
+ async function getAheadBehind(cwd, ref) {
2500
+ if (!await refExists(cwd, ref)) {
2501
+ return { aheadCount: 0, behindCount: 0 };
2502
+ }
2503
+ const result = await runGitCommand(["rev-list", "--left-right", "--count", `HEAD...${ref}`], { cwd });
2504
+ const [aheadRaw, behindRaw] = result.stdout.trim().split(/\s+/);
2505
+ return {
2506
+ aheadCount: Number.parseInt(aheadRaw ?? "0", 10) || 0,
2507
+ behindCount: Number.parseInt(behindRaw ?? "0", 10) || 0
2508
+ };
2509
+ }
2510
+ async function getCommitCount(cwd, ref = "HEAD") {
2511
+ const result = await runGitCommand(["rev-list", "--count", ref], { cwd, allowFailure: true });
2512
+ if (result.exitCode !== 0) {
2513
+ return 0;
2514
+ }
2515
+ return Number.parseInt(result.stdout.trim(), 10) || 0;
2516
+ }
2468
2517
  async function pullCurrentBranch(cwd, sshPrivateKeyPath) {
2469
2518
  await runGitCommand(["pull", "--ff-only"], {
2470
2519
  cwd,
@@ -2555,26 +2604,27 @@ var require_git = __commonJS({
2555
2604
  }
2556
2605
  function buildFallbackCommitMessage(files) {
2557
2606
  if (files.length === 0) {
2558
- return "Update repository files";
2607
+ return "chore: update repository files";
2559
2608
  }
2560
2609
  if (files.length === 1) {
2561
- return `Update ${(0, node_path_1.basename)(files[0]) || files[0]}`;
2610
+ return `chore: update ${(0, node_path_1.basename)(files[0]) || files[0]}`;
2562
2611
  }
2563
- return `Update ${(0, node_path_1.basename)(files[0]) || files[0]} and ${files.length - 1} other files`;
2612
+ return `chore: update ${(0, node_path_1.basename)(files[0]) || files[0]} and ${files.length - 1} other files`;
2564
2613
  }
2565
2614
  async function commitWithMessage(cwd, message) {
2566
- await runGitCommand(["commit", "-F", "-"], {
2615
+ await runGitCommand(["commit", "--no-verify", "-F", "-"], {
2567
2616
  cwd,
2568
2617
  input: message
2569
2618
  });
2570
2619
  }
2571
- async function pushBranch(cwd, branch, setUpstream, sshPrivateKeyPath) {
2572
- const args = setUpstream ? ["push", "--set-upstream", "origin", branch] : ["push"];
2573
- const requireConfiguredSsh = setUpstream ? await remoteRequiresConfiguredSsh(cwd, "origin") : await upstreamRequiresConfiguredSsh(cwd);
2620
+ async function pushBranch(cwd, branch, setUpstream, sshPrivateKeyPath, remote = "origin") {
2621
+ const args = setUpstream ? ["push", "--set-upstream", remote, branch] : ["push"];
2622
+ const requireConfiguredSsh = sshPrivateKeyPath ? await anyRemoteRequiresConfiguredSsh(cwd) : setUpstream ? await remoteRequiresConfiguredSsh(cwd, remote) : await upstreamRequiresConfiguredSsh(cwd);
2574
2623
  await runGitCommand(args, {
2575
2624
  cwd,
2576
2625
  requireConfiguredSsh,
2577
- sshPrivateKeyPath
2626
+ sshPrivateKeyPath,
2627
+ sshHostKeyPolicy: "accept-new"
2578
2628
  });
2579
2629
  }
2580
2630
  async function getHeadShortSha(cwd) {
@@ -3208,33 +3258,73 @@ var require_commit_message = __commonJS({
3208
3258
  "../../packages/agent/dist/commit-message.js"(exports2) {
3209
3259
  "use strict";
3210
3260
  Object.defineProperty(exports2, "__esModule", { value: true });
3261
+ exports2.isConventionalCommitMessage = isConventionalCommitMessage;
3262
+ exports2.normalizeConventionalCommitMessage = normalizeConventionalCommitMessage;
3211
3263
  exports2.generateCommitMessageWithClaude = generateCommitMessageWithClaude;
3212
3264
  exports2.fallbackCommitMessageFromFiles = fallbackCommitMessageFromFiles;
3213
3265
  var node_path_1 = require("node:path");
3214
3266
  var process_1 = require_process();
3267
+ var conventionalCommitPattern = /^(?:build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(?:\([^)]+\))?!?:\s+\S/;
3215
3268
  function firstNonEmptyLine(input) {
3216
3269
  return input.split(/\r?\n/).map((line) => line.trim()).find(Boolean) ?? "";
3217
3270
  }
3271
+ function splitCommitMessage(message) {
3272
+ const lines = message.trim().split(/\r?\n/);
3273
+ const subjectIndex = lines.findIndex((line) => Boolean(line.trim()));
3274
+ if (subjectIndex === -1) {
3275
+ return { subject: "", body: "" };
3276
+ }
3277
+ return {
3278
+ subject: lines[subjectIndex].trim(),
3279
+ body: lines.slice(subjectIndex + 1).join("\n").trim()
3280
+ };
3281
+ }
3282
+ function cleanCommitSubject(message) {
3283
+ const rawSubject = splitCommitMessage(message).subject;
3284
+ const subject = rawSubject.replace(/^["'`]+|["'`]+$/g, "").replace(/^commit message:\s*/i, "").replace(/^[-*]\s+/, "").replace(/\s+/g, " ").replace(/[.!?]$/, "").trim();
3285
+ if (!subject) {
3286
+ return "update repository files";
3287
+ }
3288
+ return `${subject.charAt(0).toLowerCase()}${subject.slice(1)}`;
3289
+ }
3290
+ function isConventionalCommitMessage(message) {
3291
+ return conventionalCommitPattern.test(firstNonEmptyLine(message));
3292
+ }
3293
+ function normalizeConventionalCommitMessage(message) {
3294
+ const trimmed = message.trim();
3295
+ if (!trimmed) {
3296
+ return "chore: update repository files";
3297
+ }
3298
+ if (isConventionalCommitMessage(trimmed)) {
3299
+ return trimmed;
3300
+ }
3301
+ const { body } = splitCommitMessage(trimmed);
3302
+ const subject = `chore: ${cleanCommitSubject(trimmed)}`;
3303
+ return body ? `${subject}
3304
+
3305
+ ${body}` : subject;
3306
+ }
3218
3307
  async function generateCommitMessageWithClaude(context) {
3219
3308
  const claudePath = await (0, process_1.resolveExecutable)("claude");
3220
3309
  if (!claudePath) {
3221
3310
  throw new Error("Claude CLI is not available");
3222
3311
  }
3223
- const prompt = `You are writing a git commit message for already staged changes.
3312
+ const prompt = `You are writing a git commit message for pushable changes.
3224
3313
 
3225
3314
  Recent git status:
3226
3315
  ${context.status || "<empty>"}
3227
3316
 
3228
- Recent git diff --cached:
3317
+ Recent git diff:
3229
3318
  ${context.diff || "<empty>"}
3230
3319
 
3231
3320
  Recent git log:
3232
3321
  ${context.log || "<empty>"}
3233
3322
 
3234
- Write exactly one short natural-language git commit message.
3235
- - Do not use conventional commit prefixes like feat:, fix:, or chore:
3323
+ Write exactly one short Conventional Commit message.
3324
+ - Format the first line as <type>: <subject>
3325
+ - Use a lowercase type such as feat, fix, docs, refactor, test, chore, or perf
3236
3326
  - Focus on the purpose of the change
3237
- - Keep it concise
3327
+ - Keep the first line under 72 characters when possible
3238
3328
  - Return only the commit message text`;
3239
3329
  const result = await (0, process_1.runCommand)([
3240
3330
  claudePath,
@@ -3249,16 +3339,16 @@ Write exactly one short natural-language git commit message.
3249
3339
  if (!message) {
3250
3340
  throw new Error("Claude returned an empty commit message");
3251
3341
  }
3252
- return message;
3342
+ return normalizeConventionalCommitMessage(message);
3253
3343
  }
3254
3344
  function fallbackCommitMessageFromFiles(files) {
3255
3345
  if (files.length === 0) {
3256
- return "Update repository files";
3346
+ return "chore: update repository files";
3257
3347
  }
3258
3348
  if (files.length === 1) {
3259
- return `Update ${(0, node_path_1.basename)(files[0]) || files[0]}`;
3349
+ return `chore: update ${(0, node_path_1.basename)(files[0]) || files[0]}`;
3260
3350
  }
3261
- return `Update ${(0, node_path_1.basename)(files[0]) || files[0]} and ${files.length - 1} other files`;
3351
+ return `chore: update ${(0, node_path_1.basename)(files[0]) || files[0]} and ${files.length - 1} other files`;
3262
3352
  }
3263
3353
  }
3264
3354
  });
@@ -3269,10 +3359,11 @@ var require_push = __commonJS({
3269
3359
  "use strict";
3270
3360
  Object.defineProperty(exports2, "__esModule", { value: true });
3271
3361
  exports2.previewPush = previewPush;
3362
+ exports2.preparePushPreview = preparePushPreview;
3272
3363
  exports2.pushRepository = pushRepository;
3273
3364
  var commit_message_1 = require_commit_message();
3274
3365
  var git_1 = require_git();
3275
- var process_1 = require_process();
3366
+ var errors_1 = require_errors();
3276
3367
  var PUSH_ARTIFACT_ROOTS = ["input", "output"];
3277
3368
  var PUSH_INCLUDED_PATHSPECS = [
3278
3369
  ".",
@@ -3281,14 +3372,6 @@ var require_push = __commonJS({
3281
3372
  ":(exclude)output",
3282
3373
  ":(exclude)output/**"
3283
3374
  ];
3284
- function shouldRetryCommit(error) {
3285
- if (!(error instanceof process_1.CommandError)) {
3286
- return false;
3287
- }
3288
- const details = `${error.result.stdout}
3289
- ${error.result.stderr}`.toLowerCase();
3290
- return details.includes("hook") || details.includes("pre-commit") || details.includes("modified") || details.includes("stashed changes conflicted");
3291
- }
3292
3375
  async function resolveCommitMessage(repoRoot, options, mode = "staged") {
3293
3376
  if (options.mode === "manual" && options.manualMessage?.trim()) {
3294
3377
  return {
@@ -3307,7 +3390,7 @@ ${error.result.stderr}`.toLowerCase();
3307
3390
  const generatedMessage = await generateCommitMessage({ status, diff, log });
3308
3391
  if (generatedMessage.trim()) {
3309
3392
  return {
3310
- message: generatedMessage.trim(),
3393
+ message: (0, commit_message_1.normalizeConventionalCommitMessage)(generatedMessage),
3311
3394
  source: "claude"
3312
3395
  };
3313
3396
  }
@@ -3332,8 +3415,72 @@ ${error.result.stderr}`.toLowerCase();
3332
3415
  await (0, git_1.stageAllMatching)(repoRoot, PUSH_INCLUDED_PATHSPECS);
3333
3416
  await (0, git_1.unstageMatching)(repoRoot, PUSH_ARTIFACT_ROOTS);
3334
3417
  }
3335
- async function previewPush(options) {
3336
- const repoRoot = await (0, git_1.getRepositoryRoot)(options.cwd ?? process.cwd());
3418
+ function getUpstreamRemoteName(upstream) {
3419
+ if (!upstream) {
3420
+ return null;
3421
+ }
3422
+ const separator = upstream.indexOf("/");
3423
+ return separator > 0 ? upstream.slice(0, separator) : null;
3424
+ }
3425
+ async function inspectPushRemoteState(repoRoot, branch, upstream, sshPrivateKeyPath) {
3426
+ const pushRef = await (0, git_1.getPushBranch)(repoRoot);
3427
+ const compareRef = pushRef ?? upstream ?? `origin/${branch}`;
3428
+ const remoteName = getUpstreamRemoteName(compareRef) ?? "origin";
3429
+ const setUpstream = !upstream;
3430
+ const remoteUrl = await (0, git_1.getRemoteUrl)(repoRoot, remoteName);
3431
+ if (!remoteUrl) {
3432
+ return {
3433
+ branch,
3434
+ upstream,
3435
+ remoteName,
3436
+ compareRef,
3437
+ setUpstream,
3438
+ aheadCount: 0,
3439
+ behindCount: 0
3440
+ };
3441
+ }
3442
+ await (0, git_1.fetchRemote)(repoRoot, remoteName, sshPrivateKeyPath);
3443
+ if (!await (0, git_1.refExists)(repoRoot, compareRef)) {
3444
+ return {
3445
+ branch,
3446
+ upstream,
3447
+ remoteName,
3448
+ compareRef,
3449
+ setUpstream,
3450
+ aheadCount: await (0, git_1.getCommitCount)(repoRoot),
3451
+ behindCount: 0
3452
+ };
3453
+ }
3454
+ const counts = await (0, git_1.getAheadBehind)(repoRoot, compareRef);
3455
+ return {
3456
+ branch,
3457
+ upstream,
3458
+ remoteName,
3459
+ compareRef,
3460
+ setUpstream,
3461
+ ...counts
3462
+ };
3463
+ }
3464
+ function assertPushRemoteCurrent(state) {
3465
+ if (state.behindCount === 0) {
3466
+ return;
3467
+ }
3468
+ throw (0, errors_1.createUserFacingError)({
3469
+ code: "push_remote_ahead",
3470
+ summary: state.aheadCount > 0 ? "Remote branch has diverged." : "Remote branch has new commits.",
3471
+ details: `${state.compareRef ?? "The push target"} is ${state.behindCount} commit${state.behindCount === 1 ? "" : "s"} ahead of the local branch.`,
3472
+ fixes: [
3473
+ "Run `git pull --rebase --autostash`, resolve conflicts if needed, then retry Push."
3474
+ ]
3475
+ });
3476
+ }
3477
+ function getReusableRemoteState(state, branch, upstream) {
3478
+ if (!state || state.branch !== branch || state.upstream !== upstream) {
3479
+ return null;
3480
+ }
3481
+ return state;
3482
+ }
3483
+ async function buildPushPreview(repoRoot, options, mode) {
3337
3484
  const [worktreeStatus, statusCounts] = await Promise.all([
3338
3485
  (0, git_1.getShortStatus)(repoRoot, PUSH_INCLUDED_PATHSPECS),
3339
3486
  (0, git_1.getStatusCounts)(repoRoot, PUSH_INCLUDED_PATHSPECS)
@@ -3349,15 +3496,24 @@ ${error.result.stderr}`.toLowerCase();
3349
3496
  detached = true;
3350
3497
  }
3351
3498
  const upstream = detached ? null : await (0, git_1.getUpstreamBranch)(repoRoot);
3352
- const hasChanges = Boolean(worktreeStatus.trim());
3499
+ const remoteState = branch && !detached ? await inspectPushRemoteState(repoRoot, branch, upstream, options.sshPrivateKeyPath) : null;
3500
+ if (remoteState) {
3501
+ assertPushRemoteCurrent(remoteState);
3502
+ }
3503
+ const hasChanges = mode === "staged" ? await (0, git_1.hasStagedChanges)(repoRoot, PUSH_INCLUDED_PATHSPECS) : Boolean(worktreeStatus.trim());
3504
+ const willCommit = hasChanges;
3505
+ const willPushExistingCommits = !willCommit && Boolean(remoteState && remoteState.aheadCount > 0);
3353
3506
  let suggestedMessage;
3354
3507
  let messageSource;
3355
3508
  let fallbackReason;
3356
3509
  if (hasChanges) {
3357
- const resolved = await resolveCommitMessage(repoRoot, options, "worktree");
3510
+ const resolved = await resolveCommitMessage(repoRoot, options, mode);
3358
3511
  suggestedMessage = resolved.message;
3359
3512
  messageSource = resolved.source;
3360
3513
  fallbackReason = resolved.fallbackReason;
3514
+ } else if (willPushExistingCommits) {
3515
+ suggestedMessage = await (0, git_1.getHeadCommitMessage)(repoRoot);
3516
+ messageSource = "manual";
3361
3517
  }
3362
3518
  return {
3363
3519
  repoRoot,
@@ -3369,39 +3525,56 @@ ${error.result.stderr}`.toLowerCase();
3369
3525
  statusCounts,
3370
3526
  suggestedMessage,
3371
3527
  messageSource,
3372
- fallbackReason
3528
+ fallbackReason,
3529
+ aheadCount: remoteState?.aheadCount ?? 0,
3530
+ behindCount: remoteState?.behindCount ?? 0,
3531
+ willCommit,
3532
+ willPushExistingCommits,
3533
+ remoteState: remoteState ?? void 0
3373
3534
  };
3374
3535
  }
3536
+ async function previewPush(options) {
3537
+ const repoRoot = await (0, git_1.getRepositoryRoot)(options.cwd ?? process.cwd());
3538
+ return await buildPushPreview(repoRoot, options, "worktree");
3539
+ }
3540
+ async function preparePushPreview(options) {
3541
+ const repoRoot = await (0, git_1.getRepositoryRoot)(options.cwd ?? process.cwd());
3542
+ await stagePushableChanges(repoRoot);
3543
+ return await buildPushPreview(repoRoot, options, "staged");
3544
+ }
3375
3545
  async function pushRepository(options) {
3376
3546
  const repoRoot = await (0, git_1.getRepositoryRoot)(options.cwd ?? process.cwd());
3547
+ const branch = await (0, git_1.getCurrentBranch)(repoRoot);
3548
+ const upstream = await (0, git_1.getUpstreamBranch)(repoRoot);
3549
+ const remoteState = getReusableRemoteState(options.remoteState, branch, upstream) ?? await inspectPushRemoteState(repoRoot, branch, upstream, options.sshPrivateKeyPath);
3550
+ assertPushRemoteCurrent(remoteState);
3377
3551
  await stagePushableChanges(repoRoot);
3378
3552
  if (!await (0, git_1.hasStagedChanges)(repoRoot, PUSH_INCLUDED_PATHSPECS)) {
3553
+ if (remoteState.aheadCount > 0) {
3554
+ const message2 = options.resolvedMessage?.message ?? options.manualMessage?.trim() ?? await (0, git_1.getHeadCommitMessage)(repoRoot);
3555
+ await (0, git_1.pushBranch)(repoRoot, branch, remoteState.setUpstream, options.sshPrivateKeyPath, remoteState.remoteName ?? "origin");
3556
+ return {
3557
+ repoRoot,
3558
+ branch,
3559
+ message: message2,
3560
+ retriedCommit: false,
3561
+ commitSha: await (0, git_1.getHeadShortSha)(repoRoot),
3562
+ upstream: await (0, git_1.getUpstreamBranch)(repoRoot),
3563
+ messageSource: options.resolvedMessage?.source ?? "manual",
3564
+ fallbackReason: options.resolvedMessage?.fallbackReason
3565
+ };
3566
+ }
3379
3567
  throw new Error("No changes to push.");
3380
3568
  }
3381
3569
  const resolvedMessage = options.resolvedMessage ?? await resolveCommitMessage(repoRoot, options);
3382
3570
  const message = resolvedMessage.message;
3383
- let retriedCommit = false;
3384
- try {
3385
- await (0, git_1.commitWithMessage)(repoRoot, message);
3386
- } catch (error) {
3387
- if (!shouldRetryCommit(error)) {
3388
- throw error;
3389
- }
3390
- retriedCommit = true;
3391
- await stagePushableChanges(repoRoot);
3392
- if (!await (0, git_1.hasStagedChanges)(repoRoot, PUSH_INCLUDED_PATHSPECS)) {
3393
- throw new Error("No changes to push.");
3394
- }
3395
- await (0, git_1.commitWithMessage)(repoRoot, message);
3396
- }
3397
- const branch = await (0, git_1.getCurrentBranch)(repoRoot);
3398
- const upstream = await (0, git_1.getUpstreamBranch)(repoRoot);
3399
- await (0, git_1.pushBranch)(repoRoot, branch, !upstream, options.sshPrivateKeyPath);
3571
+ await (0, git_1.commitWithMessage)(repoRoot, message);
3572
+ await (0, git_1.pushBranch)(repoRoot, branch, remoteState.setUpstream, options.sshPrivateKeyPath, remoteState.remoteName ?? "origin");
3400
3573
  return {
3401
3574
  repoRoot,
3402
3575
  branch,
3403
3576
  message,
3404
- retriedCommit,
3577
+ retriedCommit: false,
3405
3578
  commitSha: await (0, git_1.getHeadShortSha)(repoRoot),
3406
3579
  upstream: await (0, git_1.getUpstreamBranch)(repoRoot),
3407
3580
  messageSource: resolvedMessage.source,
@@ -6726,23 +6899,25 @@ var require_cli = __commonJS({
6726
6899
  });
6727
6900
  }
6728
6901
  const mode = resolvePushMode(options);
6902
+ const config = await (0, config_1.resolveAgentConfig)();
6729
6903
  const preview = await (0, push_1.previewPush)({
6730
6904
  cwd: repoRoot,
6731
6905
  mode,
6732
- manualMessage: options.message?.trim() || void 0
6906
+ manualMessage: options.message?.trim() || void 0,
6907
+ sshPrivateKeyPath: config.gitSshKey?.privateKeyPath
6733
6908
  });
6734
- if (!preview.hasChanges) {
6735
- throw (0, errors_1.createUserFacingError)({
6736
- code: "push_no_changes",
6737
- summary: "No changes to push."
6738
- });
6739
- }
6740
6909
  if (preview.detached) {
6741
6910
  throw (0, errors_1.createUserFacingError)({
6742
6911
  code: "push_detached_head",
6743
6912
  summary: "Detached HEAD; check out a branch before pushing."
6744
6913
  });
6745
6914
  }
6915
+ if (!preview.hasChanges && !preview.willPushExistingCommits) {
6916
+ throw (0, errors_1.createUserFacingError)({
6917
+ code: "push_no_changes",
6918
+ summary: "No changes to push."
6919
+ });
6920
+ }
6746
6921
  if (!options.json) {
6747
6922
  write(io.stdout, renderPushPreview(preview));
6748
6923
  }
@@ -6756,15 +6931,24 @@ var require_cli = __commonJS({
6756
6931
  if (options.dryRun) {
6757
6932
  const result2 = {
6758
6933
  ok: true,
6934
+ repoRoot: preview.repoRoot,
6759
6935
  branch: preview.branch,
6936
+ upstream: preview.upstream,
6937
+ statusCounts: preview.statusCounts,
6938
+ worktreeStatus: preview.worktreeStatus,
6760
6939
  commitMessage: resolvedMessage,
6940
+ messageSource: preview.messageSource,
6941
+ fallbackReason: preview.fallbackReason,
6942
+ aheadCount: preview.aheadCount,
6943
+ behindCount: preview.behindCount,
6944
+ willCommit: preview.willCommit,
6945
+ willPushExistingCommits: preview.willPushExistingCommits,
6761
6946
  nextActions: ["Run `tela agent push` without `--dry-run` when the plan looks correct."]
6762
6947
  };
6763
6948
  if (options.json)
6764
6949
  emitJson(io, result2);
6765
6950
  return 0;
6766
6951
  }
6767
- const config = await (0, config_1.resolveAgentConfig)();
6768
6952
  const push = await (0, push_1.pushRepository)({
6769
6953
  cwd: repoRoot,
6770
6954
  mode: "manual",
@@ -6774,12 +6958,17 @@ var require_cli = __commonJS({
6774
6958
  source: preview.messageSource ?? (options.message ? "manual" : "fallback"),
6775
6959
  fallbackReason: preview.fallbackReason
6776
6960
  },
6777
- sshPrivateKeyPath: config.gitSshKey?.privateKeyPath
6961
+ sshPrivateKeyPath: config.gitSshKey?.privateKeyPath,
6962
+ remoteState: preview.remoteState
6778
6963
  });
6779
6964
  const result = {
6780
6965
  ok: true,
6966
+ repoRoot: push.repoRoot,
6781
6967
  branch: push.branch,
6968
+ upstream: push.upstream,
6782
6969
  commitMessage: push.message,
6970
+ messageSource: push.messageSource,
6971
+ fallbackReason: push.fallbackReason,
6783
6972
  commitSha: push.commitSha,
6784
6973
  retriedCommit: push.retriedCommit,
6785
6974
  nextActions: ["Run `tela agent feedback --list` to inspect feedback for the pushed commit."]
@@ -7229,6 +7418,7 @@ var require_dist2 = __commonJS({
7229
7418
  __exportStar(require_push(), exports2);
7230
7419
  __exportStar(require_run(), exports2);
7231
7420
  __exportStar(require_sync(), exports2);
7421
+ __exportStar(require_commit_message(), exports2);
7232
7422
  var config_1 = require_config2();
7233
7423
  Object.defineProperty(exports2, "getDefaultAgentCloneRoot", { enumerable: true, get: function() {
7234
7424
  return config_1.getDefaultAgentCloneRoot;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/tela-cli",
3
- "version": "0.7.44",
3
+ "version": "0.7.45",
4
4
  "description": "Tela command line tools for local state and agent workflows.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {